From f838b2d7998f18ac2a1bb9d56081aac6e563de1e Mon Sep 17 00:00:00 2001 From: Monty Date: Fri, 8 Mar 2024 15:18:21 +0200 Subject: [PATCH] MDEV-33623 Partitioning is broken on big endian architectures MDEV-33502 Slowdown when running nested statement with many partitions caused this error as I failed to take into account bigendian architectures. This patch also introduces bitmap_import() and bitmap_export() to be used when one wants to store bitmaps in files/logs in a portable way. Reviewed-by: Kristian Nielsen --- include/my_bitmap.h | 32 +++--- mysys/my_bitmap.c | 134 ++++++++++++++++++------- sql/log_event.cc | 22 ++-- sql/log_event_old.cc | 27 +++-- sql/log_event_server.cc | 26 +++-- sql/opt_range.cc | 3 +- storage/spider/ha_spider.cc | 44 ++++---- storage/spider/spd_db_handlersocket.cc | 6 +- storage/spider/spd_db_mysql.cc | 6 +- unittest/mysys/bitmap-t.c | 20 +++- 10 files changed, 202 insertions(+), 118 deletions(-) diff --git a/include/my_bitmap.h b/include/my_bitmap.h index 5f722d9fbec..5589236664d 100644 --- a/include/my_bitmap.h +++ b/include/my_bitmap.h @@ -79,64 +79,68 @@ extern void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2); extern void bitmap_xor(MY_BITMAP *map, const MY_BITMAP *map2); extern void bitmap_invert(MY_BITMAP *map); extern void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2); +/* Functions to export/import bitmaps to an architecture independent format */ +extern void bitmap_export(uchar *to, MY_BITMAP *map); +extern void bitmap_import(MY_BITMAP *map, uchar *from); extern uint bitmap_lock_set_next(MY_BITMAP *map); extern void bitmap_lock_clear_bit(MY_BITMAP *map, uint bitmap_bit); #define my_bitmap_map_bytes sizeof(my_bitmap_map) #define my_bitmap_map_bits (my_bitmap_map_bytes*8) -#define bitmap_buffer_size(bits) (MY_ALIGN(bits, my_bitmap_map_bits)*my_bitmap_map_bytes) -#define no_bytes_in_map(map) (((map)->n_bits + 7)/8) +#define bitmap_buffer_size(bits) (MY_ALIGN((bits), my_bitmap_map_bits)/8) +#define my_bitmap_buffer_size(map) bitmap_buffer_size((map)->n_bits) +#define no_bytes_in_export_map(map) (((map)->n_bits + 7)/8) #define no_words_in_map(map) (((map)->n_bits + (my_bitmap_map_bits-1))/my_bitmap_map_bits) -#define bytes_word_aligned(bytes) (8*((bytes + 7)/8)) /* Fast, not thread safe, bitmap functions */ /* The following functions must be compatible with create_last_bit_mask()! */ static inline void bitmap_set_bit(MY_BITMAP *map,uint bit) { - uchar *b= (uchar*) map->bitmap + bit / 8; DBUG_ASSERT(bit < map->n_bits); - *b= (uchar) (*b | 1U << (bit & 7)); + map->bitmap[bit/my_bitmap_map_bits]|= + (1ULL << (bit & (my_bitmap_map_bits-1))); } static inline void bitmap_flip_bit(MY_BITMAP *map,uint bit) { - uchar *b= (uchar*) map->bitmap + bit / 8; DBUG_ASSERT(bit < map->n_bits); - *b= (uchar) (*b ^ 1U << (bit & 7)); + map->bitmap[bit/my_bitmap_map_bits]^= + (1ULL << (bit & (my_bitmap_map_bits-1))); } static inline void bitmap_clear_bit(MY_BITMAP *map,uint bit) { - uchar *b= (uchar*) map->bitmap + bit / 8; DBUG_ASSERT(bit < map->n_bits); - *b= (uchar) (*b & ~(1U << (bit & 7))); + map->bitmap[bit/my_bitmap_map_bits]&= + ~(1ULL << (bit & (my_bitmap_map_bits-1))); } static inline uint bitmap_is_set(const MY_BITMAP *map,uint bit) { - const uchar *b= (const uchar*) map->bitmap + bit / 8; DBUG_ASSERT(bit < map->n_bits); - return !!(*b & (1U << (bit & 7))); + return (!!(map->bitmap[bit/my_bitmap_map_bits] & + (1ULL << (bit & (my_bitmap_map_bits-1))))); } /* Return true if bitmaps are equal */ static inline my_bool bitmap_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2) { DBUG_ASSERT(map1->n_bits == map2->n_bits); - return (memcmp(map1->bitmap, map2->bitmap, 8*(no_words_in_map(map1))) == 0); + return (memcmp(map1->bitmap, map2->bitmap, + my_bitmap_buffer_size(map1)) == 0); } #define bitmap_clear_all(MAP) \ - { memset((MAP)->bitmap, 0, 8*no_words_in_map((MAP))); } + { memset((MAP)->bitmap, 0, my_bitmap_buffer_size(MAP)); } static inline void bitmap_set_all(const MY_BITMAP *map) { if (map->n_bits) { - memset(map->bitmap, 0xFF, 8*(no_words_in_map(map)-1)); + memset(map->bitmap, 0xFF, my_bitmap_map_bytes * (no_words_in_map(map)-1)); DBUG_ASSERT(map->bitmap + no_words_in_map(map)-1 == map->last_word_ptr); *map->last_word_ptr= ~map->last_bit_mask; } diff --git a/mysys/my_bitmap.c b/mysys/my_bitmap.c index 6a646a35fd1..68747f57702 100644 --- a/mysys/my_bitmap.c +++ b/mysys/my_bitmap.c @@ -18,7 +18,7 @@ */ /* - Handling of uchar arrays as large bitmaps. + Handling of my_bitmap_map (ulonglong) arrays as large bitmaps. API limitations (or, rather asserted safety assumptions, to encourage correct programming) @@ -222,12 +222,14 @@ void my_bitmap_free(MY_BITMAP *map) my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit) { - uchar *value= ((uchar*) map->bitmap) + (bitmap_bit / 8); - uchar bit= 1 << ((bitmap_bit) & 7); - uchar res= (*value) & bit; + my_bitmap_map *value, bit, res; DBUG_ASSERT_BITMAP_AND_BIT(map, bitmap_bit); + + value= map->bitmap + (bitmap_bit/my_bitmap_map_bits); + bit= 1ULL << (bitmap_bit & (my_bitmap_map_bits-1)); + res= *value & bit; *value|= bit; - return res; + return MY_TEST(res); } @@ -269,13 +271,14 @@ my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit) my_bool bitmap_fast_test_and_clear(MY_BITMAP *map, uint bitmap_bit) { - uchar *byte= (uchar*) map->bitmap + (bitmap_bit / 8); - uchar bit= 1 << ((bitmap_bit) & 7); - uchar res= (*byte) & bit; + my_bitmap_map *value, bit, res; DBUG_ASSERT_BITMAP_AND_BIT(map, bitmap_bit); - *byte&= ~bit; - return res; + value= map->bitmap + (bitmap_bit/my_bitmap_map_bits); + bit= 1ULL << (bitmap_bit & (my_bitmap_map_bits-1)); + res= *value & bit; + *value&= ~bit; + return MY_TEST(res); } @@ -310,23 +313,24 @@ uint bitmap_set_next(MY_BITMAP *map) void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size) { - uint prefix_bytes, prefix_bits, d; - uchar *m= (uchar *)map->bitmap; + uint prefix, prefix_bits; + my_bitmap_map *value= map->bitmap; DBUG_ASSERT_BITMAP(map); DBUG_ASSERT(prefix_size <= map->n_bits || prefix_size == (uint) ~0); - set_if_smaller(prefix_size, map->n_bits); - if ((prefix_bytes= prefix_size / 8)) - memset(m, 0xff, prefix_bytes); - m+= prefix_bytes; - if ((prefix_bits= prefix_size & 7)) + + if ((prefix= prefix_size / my_bitmap_map_bits)) { - *(m++)= (1 << prefix_bits)-1; - // As the prefix bits are set, lets count this byte too as a prefix byte. - prefix_bytes ++; + my_bitmap_map *end= value+prefix; + do + { + *value++= ~(my_bitmap_map) 0; + } while (value < end); } - if ((d= no_bytes_in_map(map)-prefix_bytes)) - memset(m, 0, d); + if ((prefix_bits= prefix_size & (my_bitmap_map_bits-1))) + *value++= (1ULL << prefix_bits)-1; + while (value <= map->last_word_ptr) + *value++= 0; DBUG_ASSERT_BITMAP(map); } @@ -343,10 +347,9 @@ void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size) my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size) { - uint prefix_mask= last_byte_mask(prefix_size); - uchar *m= (uchar*) map->bitmap; - uchar *end_prefix= m+(prefix_size-1)/8; - uchar *end; + my_bitmap_map *value= map->bitmap; + my_bitmap_map *end= value+ (prefix_size/my_bitmap_map_bits); + uint prefix_bits; /* Empty prefix is always true */ if (!prefix_size) @@ -354,16 +357,18 @@ my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size) DBUG_ASSERT_BITMAP_AND_BIT(map, prefix_size-1); - while (m < end_prefix) - if (*m++ != 0xff) + while (value < end) + if (*value++ != ~(my_bitmap_map) 0) return 0; - end= ((uchar*) map->last_word_ptr) + sizeof(*map->last_word_ptr)-1; - if (*m != prefix_mask) - return 0; - - while (++m <= end) - if (*m != 0) + if ((prefix_bits= prefix_size & (my_bitmap_map_bits-1))) + { + if (*value++ != (1ULL << prefix_bits)-1) + return 0; + } + end= map->last_word_ptr; + while (value <= end) + if (*value++ != 0) return 0; return 1; } @@ -700,3 +705,64 @@ void bitmap_lock_clear_bit(MY_BITMAP *map, uint bitmap_bit) bitmap_clear_bit(map, bitmap_bit); bitmap_unlock(map); } +/* + Functions to export/import bitmaps to an architecture independent format + (low_byte_first) +*/ + +#ifdef WORDS_BIGENDIAN +/* Big endian machines, like powerpc or s390x */ + +void bitmap_export(uchar *to, MY_BITMAP *map) +{ + my_bitmap_map *value; + uint length; + uchar buff[my_bitmap_map_bytes]; + + for (value= map->bitmap ; value < map->last_word_ptr ; value++) + { + int8store(to, *value); + to+= 8; + } + int8store(buff, *value); + + /* We want length & 7 to return a serie 8,2,3,4,5,6,7, 8,2,3,... */ + length= 1+ ((no_bytes_in_export_map(map) + 7) & 7); + memcpy(to, buff, length); +} + + +void bitmap_import(MY_BITMAP *map, uchar *from) +{ + my_bitmap_map *value; + uint length; + uchar buff[my_bitmap_map_bytes]; + + for (value= map->bitmap ; value < map->last_word_ptr ; value++) + { + *value= uint8korr(from); + from+= 8; + } + bzero(buff, sizeof(buff)); + + /* We want length & 7 to return a serie 8,2,3,4,5,6,7, 8,2,3,... */ + length= 1+ ((no_bytes_in_export_map(map) + 7) & 7); + memcpy(buff, from, length); + *value= uint8korr(buff) & ~map->last_bit_mask; +} + +#else + +/* Little endian machines, like intel and amd */ + +void bitmap_export(uchar *to, MY_BITMAP *map) +{ + memcpy(to, (uchar*) map->bitmap, no_bytes_in_export_map(map)); +} + +void bitmap_import(MY_BITMAP *map, uchar *from) +{ + memcpy((uchar*) map->bitmap, from, no_bytes_in_export_map(map)); + *map->last_word_ptr&= ~map->last_bit_mask; +} +#endif /* WORDS_BIGENDIAN */ diff --git a/sql/log_event.cc b/sql/log_event.cc index 5719296746a..6779419e682 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3392,10 +3392,9 @@ Rows_log_event::Rows_log_event(const uchar *buf, uint event_len, false))) { DBUG_PRINT("debug", ("Reading from %p", ptr_after_width)); - memcpy(m_cols.bitmap, ptr_after_width, (m_width + 7) / 8); - create_last_bit_mask(&m_cols); // Needed to fix last part of bitmap + bitmap_import(&m_cols, ptr_after_width); + DBUG_DUMP("m_cols", (uchar*) ptr_after_width, no_bytes_in_export_map(&m_cols)); ptr_after_width+= (m_width + 7) / 8; - DBUG_DUMP("m_cols", (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols)); } else DBUG_VOID_RETURN; @@ -3414,11 +3413,9 @@ Rows_log_event::Rows_log_event(const uchar *buf, uint event_len, false))) { DBUG_PRINT("debug", ("Reading from %p", ptr_after_width)); - memcpy(m_cols_ai.bitmap, ptr_after_width, (m_width + 7) / 8); - create_last_bit_mask(&m_cols_ai); // Needed to fix last part of bitmap + bitmap_import(&m_cols_ai, ptr_after_width); + DBUG_DUMP("m_cols_ai", ptr_after_width, no_bytes_in_export_map(&m_cols_ai)); ptr_after_width+= (m_width + 7) / 8; - DBUG_DUMP("m_cols_ai", (uchar*) m_cols_ai.bitmap, - no_bytes_in_map(&m_cols_ai)); } else DBUG_VOID_RETURN; @@ -3497,9 +3494,10 @@ int Rows_log_event::get_data_size() uchar *end= net_store_length(buf, m_width); DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", - return (int)(6 + no_bytes_in_map(&m_cols) + (end - buf) + - (general_type_code == UPDATE_ROWS_EVENT ? no_bytes_in_map(&m_cols_ai) : 0) + - m_rows_cur - m_rows_buf);); + return (int) (6 + no_bytes_in_export_map(&m_cols) + (end - buf) + + (general_type_code == UPDATE_ROWS_EVENT ? + no_bytes_in_export_map(&m_cols_ai) : 0) + + m_rows_cur - m_rows_buf);); int data_size= 0; Log_event_type type= get_type_code(); bool is_v2_event= LOG_EVENT_IS_ROW_V2(type); @@ -3514,11 +3512,11 @@ int Rows_log_event::get_data_size() { data_size= ROWS_HEADER_LEN_V1; } - data_size+= no_bytes_in_map(&m_cols); + data_size+= no_bytes_in_export_map(&m_cols); data_size+= (uint) (end - buf); if (general_type_code == UPDATE_ROWS_EVENT) - data_size+= no_bytes_in_map(&m_cols_ai); + data_size+= no_bytes_in_export_map(&m_cols_ai); data_size+= (uint) (m_rows_cur - m_rows_buf); return data_size; diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc index a7d5519276c..29465e30efb 100644 --- a/sql/log_event_old.cc +++ b/sql/log_event_old.cc @@ -1229,17 +1229,12 @@ Old_rows_log_event::Old_rows_log_event(const uchar *buf, uint event_len, false))) { DBUG_PRINT("debug", ("Reading from %p", ptr_after_width)); - memcpy(m_cols.bitmap, ptr_after_width, (m_width + 7) / 8); - create_last_bit_mask(&m_cols); // Needed to fix last part of bitmap + bitmap_import(&m_cols, ptr_after_width); + DBUG_DUMP("m_cols", ptr_after_width, no_bytes_in_export_map(&m_cols)); ptr_after_width+= (m_width + 7) / 8; - DBUG_DUMP("m_cols", (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols)); } else - { - // Needed because my_bitmap_init() does not set it to null on failure - m_cols.bitmap= NULL; DBUG_VOID_RETURN; - } const uchar* const ptr_rows_data= (const uchar*) ptr_after_width; size_t const data_size= event_len - (ptr_rows_data - (const uchar *) buf); @@ -1257,8 +1252,6 @@ Old_rows_log_event::Old_rows_log_event(const uchar *buf, uint event_len, m_rows_cur= m_rows_end; memcpy(m_rows_buf, ptr_rows_data, data_size); } - else - m_cols.bitmap= 0; // to not free it DBUG_VOID_RETURN; } @@ -1277,10 +1270,10 @@ int Old_rows_log_event::get_data_size() uchar *end= net_store_length(buf, (m_width + 7) / 8); DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", - return (int)(6 + no_bytes_in_map(&m_cols) + (end - buf) + - m_rows_cur - m_rows_buf);); + return (int)(6 + no_bytes_in_export_map(&m_cols) + (end - buf) + + m_rows_cur - m_rows_buf);); int data_size= ROWS_HEADER_LEN; - data_size+= no_bytes_in_map(&m_cols); + data_size+= no_bytes_in_export_map(&m_cols); data_size+= (uint) (end - buf); data_size+= (uint) (m_rows_cur - m_rows_buf); @@ -1798,6 +1791,8 @@ bool Old_rows_log_event::write_data_body() */ uchar sbuf[MAX_INT_WIDTH]; my_ptrdiff_t const data_size= m_rows_cur - m_rows_buf; + uint bitmap_size= no_bytes_in_export_map(&m_cols); + uchar *bitmap; // This method should not be reached. assert(0); @@ -1809,10 +1804,14 @@ bool Old_rows_log_event::write_data_body() DBUG_DUMP("m_width", sbuf, (size_t) (sbuf_end - sbuf)); res= res || write_data(sbuf, (size_t) (sbuf_end - sbuf)); - DBUG_DUMP("m_cols", (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols)); - res= res || write_data((uchar*)m_cols.bitmap, no_bytes_in_map(&m_cols)); + bitmap= (uchar*) my_alloca(bitmap_size); + bitmap_export(bitmap, &m_cols); + + DBUG_DUMP("m_cols", bitmap, no_bytes_in_export_map(&m_cols)); + res= res || write_data(bitmap, no_bytes_in_export_map(&m_cols)); DBUG_DUMP("rows", m_rows_buf, data_size); res= res || write_data(m_rows_buf, (size_t) data_size); + my_afree(bitmap); return res; diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index 744a41ca782..cafac67a51d 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -6085,30 +6085,37 @@ bool Rows_log_event::write_data_body() my_ptrdiff_t const data_size= m_rows_cur - m_rows_buf; bool res= false; uchar *const sbuf_end= net_store_length(sbuf, (size_t) m_width); + uint bitmap_size= no_bytes_in_export_map(&m_cols); + uchar *bitmap; DBUG_ASSERT(static_cast(sbuf_end - sbuf) <= sizeof(sbuf)); DBUG_DUMP("m_width", sbuf, (size_t) (sbuf_end - sbuf)); res= res || write_data(sbuf, (size_t) (sbuf_end - sbuf)); - DBUG_DUMP("m_cols", (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols)); - res= res || write_data((uchar*)m_cols.bitmap, no_bytes_in_map(&m_cols)); + bitmap= (uchar*) my_alloca(bitmap_size); + bitmap_export(bitmap, &m_cols); + + DBUG_DUMP("m_cols", bitmap, bitmap_size); + res= res || write_data(bitmap, bitmap_size); /* TODO[refactor write]: Remove the "down cast" here (and elsewhere). */ if (get_general_type_code() == UPDATE_ROWS_EVENT) { - DBUG_DUMP("m_cols_ai", (uchar*) m_cols_ai.bitmap, - no_bytes_in_map(&m_cols_ai)); - res= res || write_data((uchar*)m_cols_ai.bitmap, - no_bytes_in_map(&m_cols_ai)); + DBUG_ASSERT(m_cols.n_bits == m_cols_ai.n_bits); + bitmap_export(bitmap, &m_cols_ai); + + DBUG_DUMP("m_cols_ai", bitmap, bitmap_size); + res= res || write_data(bitmap, bitmap_size); } DBUG_DUMP("rows", m_rows_buf, data_size); res= res || write_data(m_rows_buf, (size_t) data_size); + my_afree(bitmap); return res; - } + bool Rows_log_event::write_compressed() { uchar *m_rows_buf_tmp= m_rows_buf; @@ -8391,10 +8398,7 @@ void Update_rows_log_event::init(MY_BITMAP const *cols) { /* Cols can be zero if this is a dummy binrows event */ if (likely(cols != NULL)) - { - memcpy(m_cols_ai.bitmap, cols->bitmap, no_bytes_in_map(cols)); - create_last_bit_mask(&m_cols_ai); // Needed to fix last part of bitmap - } + bitmap_copy(&m_cols_ai, cols); } } diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 7bf712cff2b..9c47639596d 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -6781,8 +6781,7 @@ ROR_INTERSECT_INFO* ror_intersect_init(const PARAM *param) void ror_intersect_cpy(ROR_INTERSECT_INFO *dst, const ROR_INTERSECT_INFO *src) { dst->param= src->param; - memcpy(dst->covered_fields.bitmap, src->covered_fields.bitmap, - no_bytes_in_map(&src->covered_fields)); + bitmap_copy(&dst->covered_fields, &src->covered_fields); dst->out_rows= src->out_rows; dst->is_covering= src->is_covering; dst->index_records= src->index_records; diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc index eaf2ac9289d..60e2bc198a8 100644 --- a/storage/spider/ha_spider.cc +++ b/storage/spider/ha_spider.cc @@ -379,19 +379,19 @@ int ha_spider::open( spider_bulk_malloc(spider_current_trx, 16, MYF(MY_WME | MY_ZEROFILL), &wide_handler, sizeof(SPIDER_WIDE_HANDLER), &searched_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &ft_discard_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &position_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &idx_read_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &idx_write_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &rnd_read_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &rnd_write_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &partition_handler, (uint) sizeof(SPIDER_PARTITION_HANDLER), NullS) @@ -399,19 +399,19 @@ int ha_spider::open( spider_bulk_malloc(spider_current_trx, 16, MYF(MY_WME | MY_ZEROFILL), &wide_handler, sizeof(SPIDER_WIDE_HANDLER), &searched_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &ft_discard_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &position_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &idx_read_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &idx_write_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &rnd_read_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), &rnd_write_bitmap, - (uint) sizeof(uchar) * no_bytes_in_map(table->read_set), + (uint) sizeof(uchar) * my_bitmap_buffer_size(table->read_set), NullS) #endif ) @@ -436,9 +436,9 @@ int ha_spider::open( wide_handler->top_share = table->s; owner->wide_handler_owner = TRUE; memset(wide_handler->ft_discard_bitmap, 0xFF, - no_bytes_in_map(table->read_set)); + my_bitmap_buffer_size(table->read_set)); memset(wide_handler->searched_bitmap, 0, - no_bytes_in_map(table->read_set)); + my_bitmap_buffer_size(table->read_set)); wide_handler_alloc = TRUE; if (!share && !spider_get_share(name, table, thd, this, &error_num)) @@ -1386,9 +1386,9 @@ int ha_spider::reset() if (!is_clone) { memset(wide_handler->ft_discard_bitmap, 0xFF, - no_bytes_in_map(table->read_set)); + my_bitmap_buffer_size(table->read_set)); memset(wide_handler->searched_bitmap, 0, - no_bytes_in_map(table->read_set)); + my_bitmap_buffer_size(table->read_set)); } while (wide_handler->condition) { @@ -1678,7 +1678,7 @@ int ha_spider::index_init( bitmap_set_all(table->read_set); if (is_clone) memset(wide_handler->searched_bitmap, 0xFF, - no_bytes_in_map(table->read_set)); + my_bitmap_buffer_size(table->read_set)); } } @@ -4114,7 +4114,7 @@ ha_rows ha_spider::multi_range_read_info_const( bitmap_set_all(table->read_set); if (is_clone) memset(wide_handler->searched_bitmap, 0xFF, - no_bytes_in_map(table->read_set)); + my_bitmap_buffer_size(table->read_set)); } } @@ -4179,7 +4179,7 @@ ha_rows ha_spider::multi_range_read_info( bitmap_set_all(table->read_set); if (is_clone) memset(wide_handler->searched_bitmap, 0xFF, - no_bytes_in_map(table->read_set)); + my_bitmap_buffer_size(table->read_set)); } } @@ -7183,7 +7183,7 @@ int ha_spider::rnd_init( bitmap_set_all(table->read_set); if (is_clone) memset(wide_handler->searched_bitmap, 0xFF, - no_bytes_in_map(table->read_set)); + my_bitmap_buffer_size(table->read_set)); } set_select_column_mode(); diff --git a/storage/spider/spd_db_handlersocket.cc b/storage/spider/spd_db_handlersocket.cc index 656ea991619..e5b4607d6b0 100644 --- a/storage/spider/spd_db_handlersocket.cc +++ b/storage/spider/spd_db_handlersocket.cc @@ -4484,7 +4484,7 @@ int spider_handlersocket_handler::init() &link_for_hash, sizeof(SPIDER_LINK_FOR_HASH) * share->link_count, &minimum_select_bitmap, - table ? sizeof(uchar) * no_bytes_in_map(table->read_set) : 0, + table ? sizeof(uchar) * my_bitmap_buffer_size(table->read_set) : 0, NullS)) ) { DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -6159,7 +6159,7 @@ void spider_handlersocket_handler::minimum_select_bitmap_create() TABLE *table = spider->get_table(); Field **field_p; DBUG_ENTER("spider_handlersocket_handler::minimum_select_bitmap_create"); - memset(minimum_select_bitmap, 0, no_bytes_in_map(table->read_set)); + memset(minimum_select_bitmap, 0, my_bitmap_buffer_size(table->read_set)); if ( spider->use_index_merge || #ifdef HA_CAN_BULK_ACCESS @@ -6174,7 +6174,7 @@ void spider_handlersocket_handler::minimum_select_bitmap_create() table_share->primary_key == MAX_KEY ) { /* need all columns */ - memset(minimum_select_bitmap, 0xFF, no_bytes_in_map(table->read_set)); + memset(minimum_select_bitmap, 0xFF, my_bitmap_buffer_size(table->read_set)); DBUG_VOID_RETURN; } else { /* need primary key columns */ diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index ee215add995..cc9af072c8d 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -8591,7 +8591,7 @@ int spider_mbase_handler::init() &link_for_hash, sizeof(SPIDER_LINK_FOR_HASH) * share->link_count, &minimum_select_bitmap, - table ? sizeof(uchar) * no_bytes_in_map(table->read_set) : 0, + table ? sizeof(uchar) * my_bitmap_buffer_size(table->read_set) : 0, NullS)) ) { DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -15750,7 +15750,7 @@ void spider_mbase_handler::minimum_select_bitmap_create() Field **field_p; DBUG_ENTER("spider_mbase_handler::minimum_select_bitmap_create"); DBUG_PRINT("info",("spider this=%p", this)); - memset(minimum_select_bitmap, 0, no_bytes_in_map(table->read_set)); + memset(minimum_select_bitmap, 0, my_bitmap_buffer_size(table->read_set)); if ( spider->use_index_merge || #ifdef HA_CAN_BULK_ACCESS @@ -15765,7 +15765,7 @@ void spider_mbase_handler::minimum_select_bitmap_create() table_share->primary_key == MAX_KEY ) { /* need all columns */ - memset(minimum_select_bitmap, 0xFF, no_bytes_in_map(table->read_set)); + memset(minimum_select_bitmap, 0xFF, my_bitmap_buffer_size(table->read_set)); DBUG_VOID_RETURN; } else { /* need primary key columns */ diff --git a/unittest/mysys/bitmap-t.c b/unittest/mysys/bitmap-t.c index 1f438dd67c5..3698d76654d 100644 --- a/unittest/mysys/bitmap-t.c +++ b/unittest/mysys/bitmap-t.c @@ -512,10 +512,14 @@ error: my_bool test_copy(MY_BITMAP *map, uint bitsize) { - my_bitmap_map buff[16]; - MY_BITMAP map2; + my_bitmap_map buff[16], buff2[16], buff3[16]; + MY_BITMAP map2, map3; + uint rnd_bit; + my_bitmap_init(&map2, buff, sizeof(buff)*8, FALSE); - memset((void*) buff, 0xff, sizeof(buff)); + my_bitmap_init(&map3, buff2, sizeof(buff)*8, FALSE); + bitmap_set_all(&map2); + bitmap_set_all(&map3); bitsize= MY_MIN(bitsize, map2.n_bits); bitmap_copy(map, &map2); @@ -524,6 +528,15 @@ my_bool test_copy(MY_BITMAP *map, uint bitsize) diag("bitmap_copy failed on bitsize %d", bitsize); return 1; } + bitmap_set_prefix(&map2, rnd_bit= get_rand_bit(bitsize)+1); + bitmap_export((uchar*) buff3, &map2); + bitmap_import(&map3, (uchar*) buff3); + if (!bitmap_cmp(&map2, &map3)) + { + diag("bitmap_export/bitmap_import failed on bitsize %d rnd_bit: %d", + bitsize, rnd_bit); + return 1; + } return 0; } @@ -639,6 +652,7 @@ my_bool do_test(uint bitsize) bitmap_clear_all(&map); if (test_copy(&map,bitsize)) goto error; + bitmap_clear_all(&map); if (test_bitmap_exists_intersection(&map, bitsize)) goto error; return FALSE;