From: Jon Olav Hauglid Date: February 16 2011 3:26pm Subject: bzr commit into mysql-5.1 branch (jon.hauglid:3592) Bug#11752069 List-Archive: http://lists.mysql.com/commits/131449 X-Bug: 11752069 Message-Id: <201102161526.p1G7i2f7025052@acsinet15.oracle.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0775674718854539626==" --===============0775674718854539626== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///export/home/x/mysql-5.1-bug11752069/ based on revid:dmitry.lenev@stripped 3592 Jon Olav Hauglid 2011-02-16 Bug #11752069 (former bug 43152) Assertion `bitmap_is_set_all(&table->s->all_set)' failed in handler::ha_reset This assertion could be triggered if two connections simultaneously executed two bitmap test functions on the same bitmap. For example, the assertion could be triggered if one connection executed UPDATE while a second connection executed SELECT on the same table. Even if bitmap test functions have read-only semantics and have const bitmaps as parameter, several of them modified the internal state of the bitmap. With interleaved execution of two such functions it was possible for one function to modify the state of the same bitmap that the other function had just modified. This lead to an inconsistent state and could trigger the assert. Internally the bitmap uses 32 bit words for storage. Since bitmaps can contain any number of bits, the last word in the bitmap may not be fully used. A 32 bit mask is maintained where a bit is set if the corresponding bit in the last bitmap word is unused. The problem was that several test functions applied this mask to the last word. Sometimes the mask was negated and used to zero out the remainder of the last word and sometimes the mask was used as-is to fill the remainder of the last word with 1's. This meant that if a function first used the negated mask and another function then used the mask as-is (or vice-versa), the first function would then get the wrong result. This patch fixes the problem by changing the implementation of 9 bitmap functions that modified the bitmap state even if the bitmap was declared const. These functions now preserve the internal state of the bitmap. This makes it possible for two connections to concurrently execute two of these functions on the same bitmap without issues. The patch also removes dead testing code from my_bitmap.c. These tests have already been moved to unittest/mysys/bitmap-t.c. Existing test coverage of my_bitmap has been extended. No MTR test case added as this would require adding several sync points to the bitmap functions. The patch has been tested with a non-deterministic test case posted on the bug report. @ include/my_bit.h Removed my_count_bits_ushort() which is not needed anymore. Added my_count_bits_uint32(). @ unittest/mysys/bitmap-t.c Extended test coverage of my_bitmap. modified: include/my_bit.h include/my_bitmap.h mysys/my_bitmap.c unittest/mysys/bitmap-t.c === modified file 'include/my_bit.h' --- a/include/my_bit.h 2007-10-16 15:03:13 +0000 +++ b/include/my_bit.h 2011-02-16 15:26:19 +0000 @@ -1,3 +1,18 @@ +/* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + /* Some useful bit functions */ @@ -42,9 +57,12 @@ STATIC_INLINE uint my_count_bits(ulonglo #endif } -STATIC_INLINE uint my_count_bits_ushort(ushort v) +STATIC_INLINE uint my_count_bits_uint32(uint32 v) { - return _my_bits_nbits[v]; + return (uint) (uchar) (_my_bits_nbits[(uchar) v] + + _my_bits_nbits[(uchar) (v >> 8)] + + _my_bits_nbits[(uchar) (v >> 16)] + + _my_bits_nbits[(uchar) (v >> 24)]); } @@ -104,6 +122,6 @@ extern uint32 my_round_up_to_next_power( uint32 my_clear_highest_bit(uint32 v); uint32 my_reverse_bits(uint32 key); extern uint my_count_bits(ulonglong v); -extern uint my_count_bits_ushort(ushort v); +extern uint my_count_bits_uint32(uint32 v); #endif /* HAVE_INLINE */ C_MODE_END === modified file 'include/my_bitmap.h' --- a/include/my_bitmap.h 2010-07-02 18:30:47 +0000 +++ b/include/my_bitmap.h 2011-02-16 15:26:19 +0000 @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -149,9 +149,10 @@ bitmap_is_set(const MY_BITMAP *map,uint static inline my_bool bitmap_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2) { - *(map1)->last_word_ptr|= (map1)->last_word_mask; - *(map2)->last_word_ptr|= (map2)->last_word_mask; - return memcmp((map1)->bitmap, (map2)->bitmap, 4*no_words_in_map((map1)))==0; + if (memcmp(map1->bitmap, map2->bitmap, 4*(no_words_in_map(map1)-1)) != 0) + return FALSE; + return ((*map1->last_word_ptr | map1->last_word_mask) == + (*map2->last_word_ptr | map2->last_word_mask)); } #define bitmap_clear_all(MAP) \ === modified file 'mysys/my_bitmap.c' --- a/mysys/my_bitmap.c 2010-07-02 18:30:47 +0000 +++ b/mysys/my_bitmap.c 2011-02-16 15:26:19 +0000 @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -91,6 +91,7 @@ static inline void bitmap_lock(MY_BITMAP #endif } + static inline void bitmap_unlock(MY_BITMAP *map __attribute__((unused))) { #ifdef THREAD @@ -100,6 +101,46 @@ static inline void bitmap_unlock(MY_BITM } +static inline uint get_first_set(uint32 value, uint word_pos) +{ + uchar *byte_ptr= (uchar*)&value; + uchar byte_value; + uint byte_pos, bit_pos; + + for (byte_pos=0; byte_pos < 4; byte_pos++, byte_ptr++) + { + byte_value= *byte_ptr; + if (byte_value) + { + for (bit_pos=0; ; bit_pos++) + if (byte_value & (1 << bit_pos)) + return (word_pos*32) + (byte_pos*8) + bit_pos; + } + } + return MY_BIT_NONE; +} + + +static inline uint get_first_not_set(uint32 value, uint word_pos) +{ + uchar *byte_ptr= (uchar*)&value; + uchar byte_value; + uint byte_pos, bit_pos; + + for (byte_pos=0; byte_pos < 4; byte_pos++, byte_ptr++) + { + byte_value= *byte_ptr; + if (byte_value != 0xFF) + { + for (bit_pos=0; ; bit_pos++) + if (!(byte_value & (1 << bit_pos))) + return (word_pos*32) + (byte_pos*8) + bit_pos; + } + } + return MY_BIT_NONE; +} + + my_bool bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits, my_bool thread_safe __attribute__((unused))) { @@ -259,7 +300,7 @@ void bitmap_set_prefix(MY_BITMAP *map, u memset(m, 0xff, prefix_bytes); m+= prefix_bytes; if ((prefix_bits= prefix_size & 7)) - *m++= (1 << prefix_bits)-1; + *(m++)= (1 << prefix_bits)-1; if ((d= no_bytes_in_map(map)-prefix_bytes)) bzero(m, d); } @@ -267,28 +308,43 @@ void bitmap_set_prefix(MY_BITMAP *map, u my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size) { - uint prefix_bits= prefix_size & 0x7, res; - uchar *m= (uchar*)map->bitmap; - uchar *end_prefix= m+prefix_size/8; - uchar *end; - DBUG_ASSERT(m && prefix_size <= map->n_bits); - end= m+no_bytes_in_map(map); - - while (m < end_prefix) - if (*m++ != 0xff) - return 0; - - *map->last_word_ptr&= ~map->last_word_mask; /*Clear bits*/ - res= 0; - if (prefix_bits && *m++ != (1 << prefix_bits)-1) - goto ret; - - while (m < end) - if (*m++ != 0) - goto ret; - res= 1; -ret: - return res; + uint prefix_bits= prefix_size % 32; + my_bitmap_map *word_ptr= map->bitmap, last_word; + my_bitmap_map *end_prefix= word_ptr + prefix_size / 32; + DBUG_ASSERT(word_ptr && prefix_size <= map->n_bits); + + /* 1: Words that should be filled with 1 */ + for (; word_ptr < end_prefix; word_ptr++) + if (*word_ptr != 0xFFFFFFFF) + return FALSE; + + last_word= *map->last_word_ptr & ~map->last_word_mask; + + /* 2: Word which contains the end of the prefix (if any) */ + if (prefix_bits) + { + if (word_ptr == map->last_word_ptr) + return uint4korr((uchar*)&last_word) == (uint32)((1 << prefix_bits) - 1); + else if (uint4korr((uchar*)word_ptr) != (uint32)((1 << prefix_bits) - 1)) + return FALSE; + word_ptr++; + } + + /* 3: Words that should be filled with 0 */ + for (; word_ptr < map->last_word_ptr; word_ptr++) + if (*word_ptr != 0) + return FALSE; + + /* + We can end up here in two situations: + 1) We went through the whole bitmap in step 1. This will happen if the + whole bitmap is filled with 1 and prefix_size is a multiple of 32 + (i.e. the prefix does not end in the middle of a word). + In this case word_ptr will be larger than map->last_word_ptr. + 2) We have gone through steps 1-3 and just need to check that also + the last word is 0. + */ + return word_ptr > map->last_word_ptr || last_word == 0; } @@ -296,10 +352,12 @@ my_bool bitmap_is_set_all(const MY_BITMA { my_bitmap_map *data_ptr= map->bitmap; my_bitmap_map *end= map->last_word_ptr; - *map->last_word_ptr |= map->last_word_mask; - for (; data_ptr <= end; data_ptr++) + + for (; data_ptr < end; data_ptr++) if (*data_ptr != 0xFFFFFFFF) return FALSE; + if ((*map->last_word_ptr | map->last_word_mask) != 0xFFFFFFFF) + return FALSE; return TRUE; } @@ -307,13 +365,13 @@ my_bool bitmap_is_set_all(const MY_BITMA my_bool bitmap_is_clear_all(const MY_BITMAP *map) { my_bitmap_map *data_ptr= map->bitmap; - my_bitmap_map *end; - if (*map->last_word_ptr & ~map->last_word_mask) - return FALSE; - end= map->last_word_ptr; + my_bitmap_map *end= map->last_word_ptr; + for (; data_ptr < end; data_ptr++) if (*data_ptr) return FALSE; + if (*map->last_word_ptr & ~map->last_word_mask) + return FALSE; return TRUE; } @@ -327,14 +385,14 @@ my_bool bitmap_is_subset(const MY_BITMAP map1->n_bits==map2->n_bits); end= map1->last_word_ptr; - *map1->last_word_ptr &= ~map1->last_word_mask; - *map2->last_word_ptr &= ~map2->last_word_mask; - while (m1 <= end) - { - if ((*m1++) & ~(*m2++)) - return 0; - } - return 1; + for (; m1 < end; m1++, m2++) + if (*m1 & ~(*m2)) + return FALSE; + + if ((*map1->last_word_ptr & ~map1->last_word_mask) & + ~(*map2->last_word_ptr & ~map2->last_word_mask)) + return FALSE; + return TRUE; } /* True if bitmaps has any common bits */ @@ -347,14 +405,14 @@ my_bool bitmap_is_overlapping(const MY_B map1->n_bits==map2->n_bits); end= map1->last_word_ptr; - *map1->last_word_ptr &= ~map1->last_word_mask; - *map2->last_word_ptr &= ~map2->last_word_mask; - while (m1 <= end) - { - if ((*m1++) & (*m2++)) - return 1; - } - return 0; + for (; m1 < end; m1++, m2++) + if (*m1 & *m2) + return TRUE; + + if ((*map1->last_word_ptr & ~map1->last_word_mask) & + (*map2->last_word_ptr & ~map2->last_word_mask)) + return TRUE; + return FALSE; } @@ -366,15 +424,17 @@ void bitmap_intersect(MY_BITMAP *map, co DBUG_ASSERT(map->bitmap && map2->bitmap); end= to+min(len,len2); - *map2->last_word_ptr&= ~map2->last_word_mask; /*Clear last bits in map2*/ - while (to < end) - *to++ &= *from++; + for (; to < end; to++, from++) + *to &= *from; + + if (len >= len2) + map->bitmap[len2 - 1] &= ~map2->last_word_mask; if (len2 < len) { end+=len-len2; - while (to < end) - *to++=0; + for (; to < end; to++) + *to= 0; } } @@ -405,8 +465,8 @@ void bitmap_set_above(MY_BITMAP *map, ui uchar *to= (uchar *)map->bitmap + from_byte; uchar *end= (uchar *)map->bitmap + (map->n_bits+7)/8; - while (to < end) - *to++= use_byte; + for (; to < end; to++) + *to= use_byte; } @@ -415,59 +475,60 @@ void bitmap_subtract(MY_BITMAP *map, con my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; DBUG_ASSERT(map->bitmap && map2->bitmap && map->n_bits==map2->n_bits); - end= map->last_word_ptr; - while (to <= end) - *to++ &= ~(*from++); + for (; to <= end; to++, from++) + *to &= ~(*from); } void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2) { my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; - DBUG_ASSERT(map->bitmap && map2->bitmap && map->n_bits==map2->n_bits); end= map->last_word_ptr; - while (to <= end) - *to++ |= *from++; + for (; to <= end; to++, from++) + *to |= *from; } void bitmap_xor(MY_BITMAP *map, const MY_BITMAP *map2) { - my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end= map->last_word_ptr; + my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; DBUG_ASSERT(map->bitmap && map2->bitmap && map->n_bits==map2->n_bits); - while (to <= end) - *to++ ^= *from++; + end= map->last_word_ptr; + + for (; to <= end; to++, from++) + *to ^= *from; } void bitmap_invert(MY_BITMAP *map) { my_bitmap_map *to= map->bitmap, *end; - DBUG_ASSERT(map->bitmap); end= map->last_word_ptr; - while (to <= end) - *to++ ^= 0xFFFFFFFF; + for (; to <= end; to++) + *to ^= 0xFFFFFFFF; } uint bitmap_bits_set(const MY_BITMAP *map) -{ - uchar *m= (uchar*)map->bitmap; - uchar *end= m + no_bytes_in_map(map); +{ + my_bitmap_map *data_ptr= map->bitmap; + my_bitmap_map *end= map->last_word_ptr; uint res= 0; - DBUG_ASSERT(map->bitmap); - *map->last_word_ptr&= ~map->last_word_mask; /*Reset last bits to zero*/ - while (m < end) - res+= my_count_bits_ushort(*m++); + + for (; data_ptr < end; data_ptr++) + res+= my_count_bits_uint32(*data_ptr); + + /*Reset last bits to zero*/ + res+= my_count_bits_uint32(*map->last_word_ptr & ~map->last_word_mask); return res; } @@ -475,76 +536,44 @@ uint bitmap_bits_set(const MY_BITMAP *ma void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2) { my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end; - DBUG_ASSERT(map->bitmap && map2->bitmap && map->n_bits==map2->n_bits); end= map->last_word_ptr; - while (to <= end) - *to++ = *from++; + + for (; to <= end; to++, from++) + *to = *from; } uint bitmap_get_first_set(const MY_BITMAP *map) { - uchar *byte_ptr; - uint i,j,k; + uint word_pos; my_bitmap_map *data_ptr, *end= map->last_word_ptr; DBUG_ASSERT(map->bitmap); data_ptr= map->bitmap; - *map->last_word_ptr &= ~map->last_word_mask; - for (i=0; data_ptr <= end; data_ptr++, i++) - { + for (word_pos=0; data_ptr < end; data_ptr++, word_pos++) if (*data_ptr) - { - byte_ptr= (uchar*)data_ptr; - for (j=0; ; j++, byte_ptr++) - { - if (*byte_ptr) - { - for (k=0; ; k++) - { - if (*byte_ptr & (1 << k)) - return (i*32) + (j*8) + k; - } - } - } - } - } - return MY_BIT_NONE; + return get_first_set(*data_ptr, word_pos); + + return get_first_set(*map->last_word_ptr & ~map->last_word_mask, word_pos); } uint bitmap_get_first(const MY_BITMAP *map) { - uchar *byte_ptr; - uint i,j,k; + uint word_pos; my_bitmap_map *data_ptr, *end= map->last_word_ptr; DBUG_ASSERT(map->bitmap); data_ptr= map->bitmap; - *map->last_word_ptr|= map->last_word_mask; - for (i=0; data_ptr <= end; data_ptr++, i++) - { + for (word_pos=0; data_ptr < end; data_ptr++, word_pos++) if (*data_ptr != 0xFFFFFFFF) - { - byte_ptr= (uchar*)data_ptr; - for (j=0; ; j++, byte_ptr++) - { - if (*byte_ptr != 0xFF) - { - for (k=0; ; k++) - { - if (!(*byte_ptr & (1 << k))) - return (i*32) + (j*8) + k; - } - } - } - } - } - return MY_BIT_NONE; + return get_first_not_set(*data_ptr, word_pos); + + return get_first_not_set(*map->last_word_ptr | map->last_word_mask, word_pos); } @@ -752,375 +781,3 @@ void bitmap_lock_flip_bit(MY_BITMAP *map bitmap_unlock(map); } #endif -#ifdef MAIN - -uint get_rand_bit(uint bitsize) -{ - return (rand() % bitsize); -} - -bool test_set_get_clear_bit(MY_BITMAP *map, uint bitsize) -{ - uint i, test_bit; - uint no_loops= bitsize > 128 ? 128 : bitsize; - for (i=0; i < no_loops; i++) - { - test_bit= get_rand_bit(bitsize); - bitmap_set_bit(map, test_bit); - if (!bitmap_is_set(map, test_bit)) - goto error1; - bitmap_clear_bit(map, test_bit); - if (bitmap_is_set(map, test_bit)) - goto error2; - } - return FALSE; -error1: - printf("Error in set bit, bit %u, bitsize = %u", test_bit, bitsize); - return TRUE; -error2: - printf("Error in clear bit, bit %u, bitsize = %u", test_bit, bitsize); - return TRUE; -} - -bool test_flip_bit(MY_BITMAP *map, uint bitsize) -{ - uint i, test_bit; - uint no_loops= bitsize > 128 ? 128 : bitsize; - for (i=0; i < no_loops; i++) - { - test_bit= get_rand_bit(bitsize); - bitmap_flip_bit(map, test_bit); - if (!bitmap_is_set(map, test_bit)) - goto error1; - bitmap_flip_bit(map, test_bit); - if (bitmap_is_set(map, test_bit)) - goto error2; - } - return FALSE; -error1: - printf("Error in flip bit 1, bit %u, bitsize = %u", test_bit, bitsize); - return TRUE; -error2: - printf("Error in flip bit 2, bit %u, bitsize = %u", test_bit, bitsize); - return TRUE; -} - -bool test_operators(MY_BITMAP *map __attribute__((unused)), - uint bitsize __attribute__((unused))) -{ - return FALSE; -} - -bool test_get_all_bits(MY_BITMAP *map, uint bitsize) -{ - uint i; - bitmap_set_all(map); - if (!bitmap_is_set_all(map)) - goto error1; - if (!bitmap_is_prefix(map, bitsize)) - goto error5; - bitmap_clear_all(map); - if (!bitmap_is_clear_all(map)) - goto error2; - if (!bitmap_is_prefix(map, 0)) - goto error6; - for (i=0; i 128 ? 128 : bitsize; - MY_BITMAP map2_obj, map3_obj; - MY_BITMAP *map2= &map2_obj, *map3= &map3_obj; - my_bitmap_map map2buf[1024]; - my_bitmap_map map3buf[1024]; - bitmap_init(&map2_obj, map2buf, bitsize, FALSE); - bitmap_init(&map3_obj, map3buf, bitsize, FALSE); - bitmap_clear_all(map2); - bitmap_clear_all(map3); - for (i=0; i < no_loops; i++) - { - test_bit1=get_rand_bit(bitsize); - bitmap_set_prefix(map, test_bit1); - test_bit2=get_rand_bit(bitsize); - bitmap_set_prefix(map2, test_bit2); - bitmap_intersect(map, map2); - test_bit3= test_bit2 < test_bit1 ? test_bit2 : test_bit1; - bitmap_set_prefix(map3, test_bit3); - if (!bitmap_cmp(map, map3)) - goto error1; - bitmap_clear_all(map); - bitmap_clear_all(map2); - bitmap_clear_all(map3); - test_bit1=get_rand_bit(bitsize); - test_bit2=get_rand_bit(bitsize); - test_bit3=get_rand_bit(bitsize); - bitmap_set_prefix(map, test_bit1); - bitmap_set_prefix(map2, test_bit2); - test_bit3= test_bit2 > test_bit1 ? test_bit2 : test_bit1; - bitmap_set_prefix(map3, test_bit3); - bitmap_union(map, map2); - if (!bitmap_cmp(map, map3)) - goto error2; - bitmap_clear_all(map); - bitmap_clear_all(map2); - bitmap_clear_all(map3); - test_bit1=get_rand_bit(bitsize); - test_bit2=get_rand_bit(bitsize); - test_bit3=get_rand_bit(bitsize); - bitmap_set_prefix(map, test_bit1); - bitmap_set_prefix(map2, test_bit2); - bitmap_xor(map, map2); - test_bit3= test_bit2 > test_bit1 ? test_bit2 : test_bit1; - test_bit4= test_bit2 < test_bit1 ? test_bit2 : test_bit1; - bitmap_set_prefix(map3, test_bit3); - for (j=0; j < test_bit4; j++) - bitmap_clear_bit(map3, j); - if (!bitmap_cmp(map, map3)) - goto error3; - bitmap_clear_all(map); - bitmap_clear_all(map2); - bitmap_clear_all(map3); - test_bit1=get_rand_bit(bitsize); - test_bit2=get_rand_bit(bitsize); - test_bit3=get_rand_bit(bitsize); - bitmap_set_prefix(map, test_bit1); - bitmap_set_prefix(map2, test_bit2); - bitmap_subtract(map, map2); - if (test_bit2 < test_bit1) - { - bitmap_set_prefix(map3, test_bit1); - for (j=0; j < test_bit2; j++) - bitmap_clear_bit(map3, j); - } - if (!bitmap_cmp(map, map3)) - goto error4; - bitmap_clear_all(map); - bitmap_clear_all(map2); - bitmap_clear_all(map3); - test_bit1=get_rand_bit(bitsize); - bitmap_set_prefix(map, test_bit1); - bitmap_invert(map); - bitmap_set_all(map3); - for (j=0; j < test_bit1; j++) - bitmap_clear_bit(map3, j); - if (!bitmap_cmp(map, map3)) - goto error5; - bitmap_clear_all(map); - bitmap_clear_all(map3); - } - return FALSE; -error1: - printf("intersect error bitsize=%u,size1=%u,size2=%u", bitsize, - test_bit1,test_bit2); - return TRUE; -error2: - printf("union error bitsize=%u,size1=%u,size2=%u", bitsize, - test_bit1,test_bit2); - return TRUE; -error3: - printf("xor error bitsize=%u,size1=%u,size2=%u", bitsize, - test_bit1,test_bit2); - return TRUE; -error4: - printf("subtract error bitsize=%u,size1=%u,size2=%u", bitsize, - test_bit1,test_bit2); - return TRUE; -error5: - printf("invert error bitsize=%u,size=%u", bitsize, - test_bit1); - return TRUE; -} - -bool test_count_bits_set(MY_BITMAP *map, uint bitsize) -{ - uint i, bit_count=0, test_bit; - uint no_loops= bitsize > 128 ? 128 : bitsize; - for (i=0; i < no_loops; i++) - { - test_bit=get_rand_bit(bitsize); - if (!bitmap_is_set(map, test_bit)) - { - bitmap_set_bit(map, test_bit); - bit_count++; - } - } - if (bit_count==0 && bitsize > 0) - goto error1; - if (bitmap_bits_set(map) != bit_count) - goto error2; - return FALSE; -error1: - printf("No bits set bitsize = %u", bitsize); - return TRUE; -error2: - printf("Wrong count of bits set, bitsize = %u", bitsize); - return TRUE; -} - -bool test_get_first_bit(MY_BITMAP *map, uint bitsize) -{ - uint i, test_bit; - uint no_loops= bitsize > 128 ? 128 : bitsize; - for (i=0; i < no_loops; i++) - { - test_bit=get_rand_bit(bitsize); - bitmap_set_bit(map, test_bit); - if (bitmap_get_first_set(map) != test_bit) - goto error1; - bitmap_set_all(map); - bitmap_clear_bit(map, test_bit); - if (bitmap_get_first(map) != test_bit) - goto error2; - bitmap_clear_all(map); - } - return FALSE; -error1: - printf("get_first_set error bitsize=%u,prefix_size=%u",bitsize,test_bit); - return TRUE; -error2: - printf("get_first error bitsize= %u, prefix_size= %u",bitsize,test_bit); - return TRUE; -} - -bool test_get_next_bit(MY_BITMAP *map, uint bitsize) -{ - uint i, j, test_bit; - uint no_loops= bitsize > 128 ? 128 : bitsize; - for (i=0; i < no_loops; i++) - { - test_bit=get_rand_bit(bitsize); - for (j=0; j < test_bit; j++) - bitmap_set_next(map); - if (!bitmap_is_prefix(map, test_bit)) - goto error1; - bitmap_clear_all(map); - } - return FALSE; -error1: - printf("get_next error bitsize= %u, prefix_size= %u", bitsize,test_bit); - return TRUE; -} - -bool test_prefix(MY_BITMAP *map, uint bitsize) -{ - uint i, j, test_bit; - uint no_loops= bitsize > 128 ? 128 : bitsize; - for (i=0; i < no_loops; i++) - { - test_bit=get_rand_bit(bitsize); - bitmap_set_prefix(map, test_bit); - if (!bitmap_is_prefix(map, test_bit)) - goto error1; - bitmap_clear_all(map); - for (j=0; j < test_bit; j++) - bitmap_set_bit(map, j); - if (!bitmap_is_prefix(map, test_bit)) - goto error2; - bitmap_set_all(map); - for (j=bitsize - 1; ~(j-test_bit); j--) - bitmap_clear_bit(map, j); - if (!bitmap_is_prefix(map, test_bit)) - goto error3; - bitmap_clear_all(map); - } - return FALSE; -error1: - printf("prefix1 error bitsize = %u, prefix_size = %u", bitsize,test_bit); - return TRUE; -error2: - printf("prefix2 error bitsize = %u, prefix_size = %u", bitsize,test_bit); - return TRUE; -error3: - printf("prefix3 error bitsize = %u, prefix_size = %u", bitsize,test_bit); - return TRUE; -} - - -bool do_test(uint bitsize) -{ - MY_BITMAP map; - my_bitmap_map buf[1024]; - if (bitmap_init(&map, buf, bitsize, FALSE)) - { - printf("init error for bitsize %d", bitsize); - goto error; - } - if (test_set_get_clear_bit(&map,bitsize)) - goto error; - bitmap_clear_all(&map); - if (test_flip_bit(&map,bitsize)) - goto error; - bitmap_clear_all(&map); - if (test_operators(&map,bitsize)) - goto error; - bitmap_clear_all(&map); - if (test_get_all_bits(&map, bitsize)) - goto error; - bitmap_clear_all(&map); - if (test_compare_operators(&map,bitsize)) - goto error; - bitmap_clear_all(&map); - if (test_count_bits_set(&map,bitsize)) - goto error; - bitmap_clear_all(&map); - if (test_get_first_bit(&map,bitsize)) - goto error; - bitmap_clear_all(&map); - if (test_get_next_bit(&map,bitsize)) - goto error; - if (test_prefix(&map,bitsize)) - goto error; - return FALSE; -error: - printf("\n"); - return TRUE; -} - -int main() -{ - int i; - for (i= 1; i < 4096; i++) - { - printf("Start test for bitsize=%u\n",i); - if (do_test(i)) - return -1; - } - printf("OK\n"); - return 0; -} - -/* - In directory mysys: - make test_bitmap - will build the bitmap tests and ./test_bitmap will execute it -*/ - -#endif === modified file 'unittest/mysys/bitmap-t.c' --- a/unittest/mysys/bitmap-t.c 2008-02-18 22:29:39 +0000 +++ b/unittest/mysys/bitmap-t.c 2011-02-16 15:26:19 +0000 @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 MySQL AB +/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,6 +24,8 @@ #include #include +#define MAX_TESTED_BITMAP_SIZE 1024 + uint get_rand_bit(uint bitsize) { return (rand() % bitsize); @@ -75,12 +77,6 @@ error2: return TRUE; } -my_bool test_operators(MY_BITMAP *map __attribute__((unused)), - uint bitsize __attribute__((unused))) -{ - return FALSE; -} - my_bool test_get_all_bits(MY_BITMAP *map, uint bitsize) { uint i; @@ -129,8 +125,8 @@ my_bool test_compare_operators(MY_BITMAP uint no_loops= bitsize > 128 ? 128 : bitsize; MY_BITMAP map2_obj, map3_obj; MY_BITMAP *map2= &map2_obj, *map3= &map3_obj; - uint32 map2buf[1024]; - uint32 map3buf[1024]; + uint32 map2buf[MAX_TESTED_BITMAP_SIZE]; + uint32 map3buf[MAX_TESTED_BITMAP_SIZE]; bitmap_init(&map2_obj, map2buf, bitsize, FALSE); bitmap_init(&map3_obj, map3buf, bitsize, FALSE); bitmap_clear_all(map2); @@ -259,6 +255,19 @@ my_bool test_get_first_bit(MY_BITMAP *ma { uint i, test_bit; uint no_loops= bitsize > 128 ? 128 : bitsize; + + bitmap_set_all(map); + for (i=0; i < bitsize; i++) + bitmap_clear_bit(map, i); + if (bitmap_get_first_set(map) != MY_BIT_NONE) + goto error1; + bitmap_clear_all(map); + for (i=0; i < bitsize; i++) + bitmap_set_bit(map, i); + if (bitmap_get_first(map) != MY_BIT_NONE) + goto error2; + bitmap_clear_all(map); + for (i=0; i < no_loops; i++) { test_bit=get_rand_bit(bitsize); @@ -321,6 +330,24 @@ my_bool test_prefix(MY_BITMAP *map, uint goto error3; bitmap_clear_all(map); } + for (i=0; i < bitsize; i++) + { + if (bitmap_is_prefix(map, i + 1)) + goto error4; + bitmap_set_bit(map, i); + if (!bitmap_is_prefix(map, i + 1)) + goto error5; + test_bit=get_rand_bit(bitsize); + bitmap_set_bit(map, test_bit); + if (test_bit <= i && !bitmap_is_prefix(map, i + 1)) + goto error5; + else if (test_bit > i) + { + if (bitmap_is_prefix(map, i + 1)) + goto error4; + bitmap_clear_bit(map, test_bit); + } + } return FALSE; error1: diag("prefix1 error bitsize = %u, prefix_size = %u", bitsize,test_bit); @@ -331,13 +358,127 @@ error2: error3: diag("prefix3 error bitsize = %u, prefix_size = %u", bitsize,test_bit); return TRUE; +error4: + diag("prefix4 error bitsize = %u, i = %u", bitsize,i); + return TRUE; +error5: + diag("prefix5 error bitsize = %u, i = %u", bitsize,i); + return TRUE; +} + +my_bool test_compare(MY_BITMAP *map, uint bitsize) +{ + MY_BITMAP map2; + uint32 map2buf[MAX_TESTED_BITMAP_SIZE]; + uint i, test_bit; + uint no_loops= bitsize > 128 ? 128 : bitsize; + if (bitmap_init(&map2, map2buf, bitsize, FALSE)) + { + diag("init error for bitsize %d", bitsize); + return TRUE; + } + /* Test all 4 possible combinations of set/unset bits. */ + for (i=0; i < no_loops; i++) + { + test_bit=get_rand_bit(bitsize); + bitmap_clear_bit(map, test_bit); + bitmap_clear_bit(&map2, test_bit); + if (!bitmap_is_subset(map, &map2)) + goto error_is_subset; + bitmap_set_bit(map, test_bit); + if (bitmap_is_subset(map, &map2)) + goto error_is_subset; + bitmap_set_bit(&map2, test_bit); + if (!bitmap_is_subset(map, &map2)) + goto error_is_subset; + bitmap_clear_bit(map, test_bit); + if (!bitmap_is_subset(map, &map2)) + goto error_is_subset; + /* Note that test_bit is not cleared i map2. */ + } + bitmap_clear_all(map); + bitmap_clear_all(&map2); + /* Test all 4 possible combinations of set/unset bits. */ + for (i=0; i < no_loops; i++) + { + test_bit=get_rand_bit(bitsize); + if (bitmap_is_overlapping(map, &map2)) + goto error_is_overlapping; + bitmap_set_bit(map, test_bit); + if (bitmap_is_overlapping(map, &map2)) + goto error_is_overlapping; + bitmap_set_bit(&map2, test_bit); + if (!bitmap_is_overlapping(map, &map2)) + goto error_is_overlapping; + bitmap_clear_bit(map, test_bit); + if (bitmap_is_overlapping(map, &map2)) + goto error_is_overlapping; + bitmap_clear_bit(&map2, test_bit); + /* Note that test_bit is not cleared i map2. */ + } + return FALSE; +error_is_subset: + diag("is_subset error bitsize = %u", bitsize); + return TRUE; +error_is_overlapping: + diag("is_overlapping error bitsize = %u", bitsize); + return TRUE; } +my_bool test_intersect(MY_BITMAP *map, uint bitsize) +{ + uint bitsize2 = 1 + get_rand_bit(MAX_TESTED_BITMAP_SIZE - 1); + MY_BITMAP map2; + uint32 map2buf[bitsize2]; + uint i, test_bit1, test_bit2, test_bit3; + if (bitmap_init(&map2, map2buf, bitsize2, FALSE)) + { + diag("init error for bitsize %d", bitsize2); + return TRUE; + } + test_bit1= get_rand_bit(bitsize); + test_bit2= get_rand_bit(bitsize); + bitmap_set_bit(map, test_bit1); + bitmap_set_bit(map, test_bit2); + test_bit3= get_rand_bit(bitsize2); + bitmap_set_bit(&map2, test_bit3); + if (test_bit2 < bitsize2) + bitmap_set_bit(&map2, test_bit2); + + bitmap_intersect(map, &map2); + if (test_bit2 < bitsize2) + { + if (!bitmap_is_set(map, test_bit2)) + goto error; + bitmap_clear_bit(map, test_bit2); + } + if (test_bit1 == test_bit3) + { + if (!bitmap_is_set(map, test_bit1)) + goto error; + bitmap_clear_bit(map, test_bit1); + } + if (!bitmap_is_clear_all(map)) + goto error; + + bitmap_set_all(map); + bitmap_set_all(&map2); + for (i=0; i < bitsize2; i++) + bitmap_clear_bit(&map2, i); + bitmap_intersect(map, &map2); + if (!bitmap_is_clear_all(map)) + goto error; + return FALSE; +error: + diag("intersect error bitsize = %u, bit1 = %u, bit2 = %u, bit3 = %u", + bitsize, test_bit1, test_bit2, test_bit3); + return TRUE; +} my_bool do_test(uint bitsize) { MY_BITMAP map; - uint32 buf[1024]; + uint32 buf[MAX_TESTED_BITMAP_SIZE]; if (bitmap_init(&map, buf, bitsize, FALSE)) { diag("init error for bitsize %d", bitsize); @@ -349,9 +490,6 @@ my_bool do_test(uint bitsize) if (test_flip_bit(&map,bitsize)) goto error; bitmap_clear_all(&map); - if (test_operators(&map,bitsize)) - goto error; - bitmap_clear_all(&map); if (test_get_all_bits(&map, bitsize)) goto error; bitmap_clear_all(&map); @@ -366,8 +504,15 @@ my_bool do_test(uint bitsize) bitmap_clear_all(&map); if (test_get_next_bit(&map,bitsize)) goto error; + bitmap_clear_all(&map); if (test_prefix(&map,bitsize)) goto error; + bitmap_clear_all(&map); + if (test_compare(&map,bitsize)) + goto error; + bitmap_clear_all(&map); + if (test_intersect(&map,bitsize)) + goto error; return FALSE; error: return TRUE; @@ -377,7 +522,7 @@ int main() { int i; int const min_size = 1; - int const max_size = 1024; + int const max_size = MAX_TESTED_BITMAP_SIZE; MY_INIT("bitmap-t"); plan(max_size - min_size); --===============0775674718854539626== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/jon.hauglid@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: jon.hauglid@stripped # target_branch: file:///export/home/x/mysql-5.1-bug11752069/ # testament_sha1: 1cb82f03431059378ba8fe672f5b4014b61986b3 # timestamp: 2011-02-16 16:26:23 +0100 # base_revision_id: dmitry.lenev@stripped\ # 23v66cenqyhgi6l6 # # Begin bundle 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 +myUIxAuJ7yB/8XckU4UJBJscQ2A --===============0775674718854539626==--