Optimize performance of my_bitmap
MDEV-33502 Slowdown when running nested statement with many partitions This change was triggered to help some MariaDB users with close to 10000 bits in their bitmaps. - Change underlaying storage to be 64 bit instead of 32bit. - This reduses number of loops to scan bitmaps. - This can cause some bitmaps to be 4 byte large. - Ensure that all not used top-bits are always 0 (simplifes code as the last 64 bit storage is not a special case anymore). - Use my_find_first_bit() to find the first set bit which is much faster than scanning trough things byte by byte and then bit by bit. Other things: - Added a bool to remember if my_bitmap_init() did allocate the bitmap array. my_bitmap_free() will only free arrays it did allocate. This allowed me to remove setting 'bitmap=0' before calling my_bitmap_free() for cases where the bitmap's where allocated externally. - my_bitmap_init() sets bitmap to 0 in case of failure. - Added 'universal' asserts to most bitmap functions. - Change all remaining calls to bitmap_init() to my_bitmap_init(). - To finish the change from 2014. - Changed all usage of uint32 in my_bitmap.h to my_bitmap_map. - Updated bitmap_copy() to handle bitmaps of different size. - Removed const from bitmap_exists_intersection() as this caused casts on all usage. - Removed not used function bitmap_set_above(). - Renamed create_last_word_mask() to create_last_bit_mask() (to match name changes in my_bitmap.cc) - Extended bitmap-t with test for more bitmap functions.
This commit is contained in:
parent
d4e1731fbc
commit
b5d65fc105
@ -22,7 +22,7 @@
|
||||
#include <m_string.h>
|
||||
#include <my_pthread.h>
|
||||
|
||||
typedef uint32 my_bitmap_map;
|
||||
typedef ulonglong my_bitmap_map;
|
||||
|
||||
typedef struct st_bitmap
|
||||
{
|
||||
@ -34,21 +34,19 @@ typedef struct st_bitmap
|
||||
acquiring the mutex
|
||||
*/
|
||||
mysql_mutex_t *mutex;
|
||||
my_bitmap_map last_word_mask;
|
||||
my_bitmap_map last_bit_mask;
|
||||
uint32 n_bits; /* number of bits occupied by the above */
|
||||
my_bool bitmap_allocated;
|
||||
} MY_BITMAP;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* compatibility functions */
|
||||
#define bitmap_init(A,B,C,D) my_bitmap_init(A,B,C,D)
|
||||
#define bitmap_free(A) my_bitmap_free(A)
|
||||
/* Reset memory. Faster then doing a full bzero */
|
||||
#define my_bitmap_clear(A) ((A)->bitmap= 0)
|
||||
|
||||
extern void create_last_word_mask(MY_BITMAP *map);
|
||||
extern void create_last_bit_mask(MY_BITMAP *map);
|
||||
extern my_bool my_bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits,
|
||||
my_bool thread_safe);
|
||||
extern my_bool bitmap_is_clear_all(const MY_BITMAP *map);
|
||||
@ -63,12 +61,12 @@ extern my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit);
|
||||
extern my_bool bitmap_fast_test_and_clear(MY_BITMAP *map, uint bitmap_bit);
|
||||
extern my_bool bitmap_union_is_set_all(const MY_BITMAP *map1,
|
||||
const MY_BITMAP *map2);
|
||||
extern my_bool bitmap_exists_intersection(const MY_BITMAP **bitmap_array,
|
||||
extern my_bool bitmap_exists_intersection(MY_BITMAP **bitmap_array,
|
||||
uint bitmap_count,
|
||||
uint start_bit, uint end_bit);
|
||||
|
||||
extern uint bitmap_set_next(MY_BITMAP *map);
|
||||
extern uint bitmap_get_first(const MY_BITMAP *map);
|
||||
extern uint bitmap_get_first_clear(const MY_BITMAP *map);
|
||||
extern uint bitmap_get_first_set(const MY_BITMAP *map);
|
||||
extern uint bitmap_bits_set(const MY_BITMAP *map);
|
||||
extern uint bitmap_get_next_set(const MY_BITMAP *map, uint bitmap_bit);
|
||||
@ -84,12 +82,16 @@ extern void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2);
|
||||
|
||||
extern uint bitmap_lock_set_next(MY_BITMAP *map);
|
||||
extern void bitmap_lock_clear_bit(MY_BITMAP *map, uint bitmap_bit);
|
||||
/* Fast, not thread safe, bitmap functions */
|
||||
#define bitmap_buffer_size(bits) (((bits)+31)/32)*4
|
||||
|
||||
#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 no_words_in_map(map) (((map)->n_bits + 31)/32)
|
||||
#define bytes_word_aligned(bytes) (4*((bytes + 3)/4))
|
||||
/* The following functions must be compatible with create_last_word_mask()! */
|
||||
#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)
|
||||
{
|
||||
@ -119,18 +121,26 @@ bitmap_is_set(const MY_BITMAP *map,uint bit)
|
||||
return !!(*b & (1U << (bit & 7)));
|
||||
}
|
||||
|
||||
/* Return true if bitmaps are equal */
|
||||
static inline my_bool bitmap_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2)
|
||||
{
|
||||
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));
|
||||
DBUG_ASSERT(map1->n_bits == map2->n_bits);
|
||||
return (memcmp(map1->bitmap, map2->bitmap, 8*(no_words_in_map(map1))) == 0);
|
||||
}
|
||||
|
||||
#define bitmap_clear_all(MAP) \
|
||||
{ memset((MAP)->bitmap, 0, 4*no_words_in_map((MAP))); }
|
||||
#define bitmap_set_all(MAP) \
|
||||
(memset((MAP)->bitmap, 0xFF, 4*no_words_in_map((MAP))))
|
||||
{ memset((MAP)->bitmap, 0, 8*no_words_in_map((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));
|
||||
DBUG_ASSERT(map->bitmap + no_words_in_map(map)-1 == map->last_word_ptr);
|
||||
*map->last_word_ptr= ~map->last_bit_mask;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -13,7 +13,9 @@
|
||||
|
||||
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 Street, Fifth Floor, Boston, MA 02110-1335 USA */
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335
|
||||
USA
|
||||
*/
|
||||
|
||||
/*
|
||||
Handling of uchar arrays as large bitmaps.
|
||||
@ -21,9 +23,18 @@
|
||||
API limitations (or, rather asserted safety assumptions,
|
||||
to encourage correct programming)
|
||||
|
||||
* the internal size is a set of 32 bit words
|
||||
* the internal storage is a set of 64 bit words
|
||||
* the number of bits specified in creation can be any number > 0
|
||||
|
||||
Implementation notes:
|
||||
* MY_BITMAP includes a pointer, last_word_ptr, to the last word.
|
||||
The implication is that if one copies bitmaps to another memory
|
||||
location, one has to call create_last_bit_mask() on the bitmap to
|
||||
fix the internal pointer.
|
||||
* The not used part of a the last word should always be 0.
|
||||
This avoids special handling of the last bitmap in several cases.
|
||||
This is checked for most calls to bitmap functions.
|
||||
|
||||
TODO:
|
||||
Make assembler thread safe versions of these using test-and-set instructions
|
||||
|
||||
@ -31,95 +42,94 @@
|
||||
New version written and test program added and some changes to the interface
|
||||
was made by Mikael Ronstrom 2005, with assistance of Tomas Ulin and Mats
|
||||
Kindahl.
|
||||
Updated to 64 bits and use my_find_first_bit() to speed up
|
||||
bitmap_get_next_set() by Monty in 2024
|
||||
*/
|
||||
|
||||
#include "mysys_priv.h"
|
||||
#include <my_bitmap.h>
|
||||
#include <m_string.h>
|
||||
#include <my_bit.h>
|
||||
#include <my_byteorder.h>
|
||||
|
||||
|
||||
/* Defines to check bitmaps */
|
||||
|
||||
#define DBUG_ASSERT_BITMAP(M) \
|
||||
DBUG_ASSERT((M)->bitmap); \
|
||||
DBUG_ASSERT((M)->n_bits > 0); \
|
||||
DBUG_ASSERT((M)->last_word_ptr == (M)->bitmap + no_words_in_map(M)-1); \
|
||||
DBUG_ASSERT((*(M)->last_word_ptr & (M)->last_bit_mask) == 0);
|
||||
|
||||
#define DBUG_ASSERT_BITMAP_AND_BIT(M,B) \
|
||||
DBUG_ASSERT_BITMAP(M); \
|
||||
DBUG_ASSERT((B) < (M)->n_bits);
|
||||
|
||||
#define DBUG_ASSERT_DIFFERENT_BITMAPS(M,N) \
|
||||
DBUG_ASSERT_BITMAP(M); \
|
||||
DBUG_ASSERT_BITMAP(N);
|
||||
|
||||
#define DBUG_ASSERT_IDENTICAL_BITMAPS(M,N) \
|
||||
DBUG_ASSERT_BITMAP(M); \
|
||||
DBUG_ASSERT_BITMAP(N); \
|
||||
DBUG_ASSERT((M)->n_bits == (N)->n_bits);
|
||||
|
||||
/*
|
||||
Create a mask with the upper 'unused' bits set and the lower 'used'
|
||||
bits clear. The bits within each byte is stored in big-endian order.
|
||||
Create a mask for the usable bits on the LAST my_bitmap_map position for
|
||||
a bitmap with 'bits' number of bits.
|
||||
|
||||
The lowest 'bits' bits are set to zero and the rest bits are set to 1.
|
||||
For (bits & 63) == 0 , 0 is returned as in this case all bits in the
|
||||
my_bitmap_position are significant. (This example assumes the
|
||||
storage is ulonglong).
|
||||
|
||||
For 'bits & 63' it will return values from the series
|
||||
0, 0xfffffffffffffffe,.... 0x8000000000000000
|
||||
*/
|
||||
|
||||
static inline uchar invers_last_byte_mask(uint bits)
|
||||
static inline my_bitmap_map last_bit_mask(uint bits)
|
||||
{
|
||||
return last_byte_mask(bits) ^ 255;
|
||||
uint bits_in_last_map= (bits & (my_bitmap_map_bits-1));
|
||||
return bits_in_last_map ? ~((1ULL << bits_in_last_map)-1) : 0ULL;
|
||||
}
|
||||
|
||||
|
||||
void create_last_word_mask(MY_BITMAP *map)
|
||||
/*
|
||||
Get a mask of the bits that are to be considered as 'on' at location
|
||||
starting with 'bits'.
|
||||
This function has _inv in it's name as it's usage is invers compared
|
||||
to last_bit_mask().
|
||||
|
||||
For (bits & 63) it will return values from the series
|
||||
0xffffffffffffffff, 0xfffffffffffffffe,.... 0x8000000000000000
|
||||
*/
|
||||
|
||||
static inline my_bitmap_map first_bit_mask_inv(uint bits)
|
||||
{
|
||||
unsigned char const mask= invers_last_byte_mask(map->n_bits);
|
||||
|
||||
/*
|
||||
The first bytes are to be set to zero since they represent real bits
|
||||
in the bitvector. The last bytes are set to 0xFF since they represent
|
||||
bytes not used by the bitvector. Finally the last byte contains bits
|
||||
as set by the mask above.
|
||||
*/
|
||||
unsigned char *ptr= (unsigned char*)&map->last_word_mask;
|
||||
|
||||
map->last_word_ptr= map->bitmap + no_words_in_map(map)-1;
|
||||
switch (no_bytes_in_map(map) & 3) {
|
||||
case 1:
|
||||
map->last_word_mask= ~0U;
|
||||
ptr[0]= mask;
|
||||
return;
|
||||
case 2:
|
||||
map->last_word_mask= ~0U;
|
||||
ptr[0]= 0;
|
||||
ptr[1]= mask;
|
||||
return;
|
||||
case 3:
|
||||
map->last_word_mask= 0U;
|
||||
ptr[2]= mask;
|
||||
ptr[3]= 0xFFU;
|
||||
return;
|
||||
case 0:
|
||||
map->last_word_mask= 0U;
|
||||
ptr[3]= mask;
|
||||
return;
|
||||
}
|
||||
uint bits_in_last_map= (bits & (my_bitmap_map_bits-1));
|
||||
return ~((1ULL << bits_in_last_map)-1);
|
||||
}
|
||||
|
||||
|
||||
static inline my_bitmap_map last_word_mask(uint bit)
|
||||
/*
|
||||
Update the bitmap's last_word_ptr and last_bit_mask
|
||||
Also ensure that the last world is all zero to make it
|
||||
easy to find the next set bit.
|
||||
|
||||
Note that if n_bits is 0, then last_word_ptr will point to
|
||||
bitmap (safely). The bitmap will not be usable for almost any operation.
|
||||
*/
|
||||
|
||||
void create_last_bit_mask(MY_BITMAP *map)
|
||||
{
|
||||
my_bitmap_map last_word_mask;
|
||||
uint n_bits= bit + 1;
|
||||
unsigned char const mask= invers_last_byte_mask(n_bits);
|
||||
|
||||
/*
|
||||
The first bytes are to be set to zero since they represent real bits
|
||||
in the bitvector. The last bytes are set to 0xFF since they represent
|
||||
bytes not used by the bitvector. Finally the last byte contains bits
|
||||
as set by the mask above.
|
||||
*/
|
||||
unsigned char *ptr= (unsigned char*)&last_word_mask;
|
||||
|
||||
switch ((n_bits + 7)/8 & 3) {
|
||||
case 1:
|
||||
last_word_mask= ~0U;
|
||||
ptr[0]= mask;
|
||||
break;
|
||||
case 2:
|
||||
last_word_mask= ~0U;
|
||||
ptr[0]= 0;
|
||||
ptr[1]= mask;
|
||||
break;
|
||||
case 3:
|
||||
last_word_mask= 0U;
|
||||
ptr[2]= mask;
|
||||
ptr[3]= 0xFFU;
|
||||
break;
|
||||
case 0:
|
||||
last_word_mask= 0U;
|
||||
ptr[3]= mask;
|
||||
break;
|
||||
my_bitmap_map mask= last_bit_mask(map->n_bits);
|
||||
map->last_bit_mask= mask;
|
||||
map->last_word_ptr= map->bitmap + MY_MAX(no_words_in_map(map),1) -1;
|
||||
if (map->n_bits > 0)
|
||||
{
|
||||
*map->last_word_ptr&= ~mask; /* Set not used bits to 0 */
|
||||
DBUG_ASSERT_BITMAP(map);
|
||||
}
|
||||
return last_word_mask;
|
||||
}
|
||||
|
||||
|
||||
@ -136,25 +146,6 @@ static inline void bitmap_unlock(MY_BITMAP *map __attribute__((unused)))
|
||||
}
|
||||
|
||||
|
||||
static inline uint get_first_set(my_bitmap_map value, uint word_pos)
|
||||
{
|
||||
uchar *byte_ptr= (uchar*)&value;
|
||||
uchar byte_value;
|
||||
uint byte_pos, bit_pos;
|
||||
|
||||
DBUG_ASSERT(value);
|
||||
for (byte_pos=0; ; byte_pos++, byte_ptr++)
|
||||
{
|
||||
if ((byte_value= *byte_ptr))
|
||||
{
|
||||
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; /* Impossible */
|
||||
}
|
||||
|
||||
/*
|
||||
Initialize a bitmap object. All bits will be set to zero
|
||||
*/
|
||||
@ -164,6 +155,7 @@ my_bool my_bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits,
|
||||
{
|
||||
DBUG_ENTER("my_bitmap_init");
|
||||
map->mutex= 0;
|
||||
|
||||
if (!buf)
|
||||
{
|
||||
uint size_in_bytes= bitmap_buffer_size(n_bits);
|
||||
@ -175,21 +167,26 @@ my_bool my_bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits,
|
||||
}
|
||||
if (!(buf= (my_bitmap_map*) my_malloc(key_memory_MY_BITMAP_bitmap,
|
||||
size_in_bytes+extra, MYF(MY_WME))))
|
||||
{
|
||||
map->bitmap= 0;
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
if (thread_safe)
|
||||
{
|
||||
map->mutex= (mysql_mutex_t *) ((char*) buf + size_in_bytes);
|
||||
mysql_mutex_init(key_BITMAP_mutex, map->mutex, MY_MUTEX_INIT_FAST);
|
||||
}
|
||||
map->bitmap_allocated= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_ASSERT(thread_safe == 0);
|
||||
map->bitmap_allocated= 0;
|
||||
}
|
||||
|
||||
map->bitmap= buf;
|
||||
map->n_bits= n_bits;
|
||||
create_last_word_mask(map);
|
||||
create_last_bit_mask(map);
|
||||
bitmap_clear_all(map);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
@ -202,7 +199,8 @@ void my_bitmap_free(MY_BITMAP *map)
|
||||
{
|
||||
if (map->mutex)
|
||||
mysql_mutex_destroy(map->mutex);
|
||||
my_free(map->bitmap);
|
||||
if (map->bitmap_allocated)
|
||||
my_free(map->bitmap);
|
||||
map->bitmap=0;
|
||||
}
|
||||
DBUG_VOID_RETURN;
|
||||
@ -227,6 +225,7 @@ 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;
|
||||
DBUG_ASSERT_BITMAP_AND_BIT(map, bitmap_bit);
|
||||
*value|= bit;
|
||||
return res;
|
||||
}
|
||||
@ -248,8 +247,7 @@ my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit)
|
||||
my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit)
|
||||
{
|
||||
my_bool res;
|
||||
DBUG_ASSERT(map->bitmap);
|
||||
DBUG_ASSERT(bitmap_bit < map->n_bits);
|
||||
DBUG_ASSERT_BITMAP_AND_BIT(map, bitmap_bit);
|
||||
bitmap_lock(map);
|
||||
res= bitmap_fast_test_and_set(map, bitmap_bit);
|
||||
bitmap_unlock(map);
|
||||
@ -274,6 +272,8 @@ 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;
|
||||
DBUG_ASSERT_BITMAP_AND_BIT(map, bitmap_bit);
|
||||
|
||||
*byte&= ~bit;
|
||||
return res;
|
||||
}
|
||||
@ -282,8 +282,8 @@ my_bool bitmap_fast_test_and_clear(MY_BITMAP *map, uint bitmap_bit)
|
||||
my_bool bitmap_test_and_clear(MY_BITMAP *map, uint bitmap_bit)
|
||||
{
|
||||
my_bool res;
|
||||
DBUG_ASSERT(map->bitmap);
|
||||
DBUG_ASSERT(bitmap_bit < map->n_bits);
|
||||
DBUG_ASSERT_BITMAP_AND_BIT(map, bitmap_bit);
|
||||
|
||||
bitmap_lock(map);
|
||||
res= bitmap_fast_test_and_clear(map, bitmap_bit);
|
||||
bitmap_unlock(map);
|
||||
@ -294,8 +294,8 @@ my_bool bitmap_test_and_clear(MY_BITMAP *map, uint bitmap_bit)
|
||||
uint bitmap_set_next(MY_BITMAP *map)
|
||||
{
|
||||
uint bit_found;
|
||||
DBUG_ASSERT(map->bitmap);
|
||||
if ((bit_found= bitmap_get_first(map)) != MY_BIT_NONE)
|
||||
DBUG_ASSERT_BITMAP(map);
|
||||
if ((bit_found= bitmap_get_first_clear(map)) != MY_BIT_NONE)
|
||||
bitmap_set_bit(map, bit_found);
|
||||
return bit_found;
|
||||
}
|
||||
@ -305,15 +305,16 @@ uint bitmap_set_next(MY_BITMAP *map)
|
||||
Set the specified number of bits in the bitmap buffer.
|
||||
|
||||
@param map [IN] Bitmap
|
||||
@param prefix_size [IN] Number of bits to be set
|
||||
@param prefix_size [IN] Number of bits to be set or (uint) ~0 for all
|
||||
*/
|
||||
|
||||
void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size)
|
||||
{
|
||||
uint prefix_bytes, prefix_bits, d;
|
||||
uchar *m= (uchar *)map->bitmap;
|
||||
|
||||
DBUG_ASSERT(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);
|
||||
@ -326,37 +327,45 @@ void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size)
|
||||
}
|
||||
if ((d= no_bytes_in_map(map)-prefix_bytes))
|
||||
memset(m, 0, d);
|
||||
DBUG_ASSERT_BITMAP(map);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check if bitmap is a bitmap of prefix bits set in the beginning
|
||||
|
||||
@param map bitmap
|
||||
@param prefix_size number of bits that should be set. 0 is allowed.
|
||||
|
||||
@return 1 Yes, prefix bits where set or prefix_size == 0.
|
||||
@return 0 No
|
||||
*/
|
||||
|
||||
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;
|
||||
DBUG_ASSERT(m);
|
||||
DBUG_ASSERT(prefix_size <= map->n_bits);
|
||||
|
||||
/* Empty prefix is always true */
|
||||
if (!prefix_size)
|
||||
return 1;
|
||||
|
||||
DBUG_ASSERT_BITMAP_AND_BIT(map, prefix_size-1);
|
||||
|
||||
while (m < end_prefix)
|
||||
if (*m++ != 0xff)
|
||||
return 0;
|
||||
|
||||
end= ((uchar*) map->bitmap) + no_bytes_in_map(map) - 1;
|
||||
if (m == end)
|
||||
return ((*m & last_byte_mask(map->n_bits)) == prefix_mask);
|
||||
|
||||
end= ((uchar*) map->last_word_ptr) + sizeof(*map->last_word_ptr)-1;
|
||||
if (*m != prefix_mask)
|
||||
return 0;
|
||||
|
||||
while (++m < end)
|
||||
while (++m <= end)
|
||||
if (*m != 0)
|
||||
return 0;
|
||||
return ((*m & last_byte_mask(map->n_bits)) == 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@ -364,10 +373,12 @@ my_bool bitmap_is_set_all(const MY_BITMAP *map)
|
||||
{
|
||||
my_bitmap_map *data_ptr= map->bitmap;
|
||||
my_bitmap_map *end= map->last_word_ptr;
|
||||
DBUG_ASSERT_BITMAP(map);
|
||||
|
||||
for (; data_ptr < end; data_ptr++)
|
||||
if (*data_ptr != 0xFFFFFFFF)
|
||||
if (*data_ptr != ~(my_bitmap_map)0)
|
||||
return FALSE;
|
||||
return (*data_ptr | map->last_word_mask) == 0xFFFFFFFF;
|
||||
return (*data_ptr | map->last_bit_mask) == ~(my_bitmap_map)0;
|
||||
}
|
||||
|
||||
|
||||
@ -375,61 +386,58 @@ my_bool bitmap_is_clear_all(const MY_BITMAP *map)
|
||||
{
|
||||
my_bitmap_map *data_ptr= map->bitmap;
|
||||
my_bitmap_map *end= map->last_word_ptr;
|
||||
DBUG_ASSERT_BITMAP(map);
|
||||
|
||||
DBUG_ASSERT(map->n_bits > 0);
|
||||
for (; data_ptr < end; data_ptr++)
|
||||
for (; data_ptr <= end; data_ptr++)
|
||||
if (*data_ptr)
|
||||
return FALSE;
|
||||
return (*data_ptr & ~map->last_word_mask) == 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Return TRUE if map1 is a subset of map2 */
|
||||
|
||||
my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2)
|
||||
{
|
||||
my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end;
|
||||
my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end= map1->last_word_ptr;
|
||||
DBUG_ASSERT_IDENTICAL_BITMAPS(map1,map2);
|
||||
|
||||
DBUG_ASSERT(map1->bitmap && map2->bitmap);
|
||||
DBUG_ASSERT(map1->n_bits==map2->n_bits);
|
||||
|
||||
end= map1->last_word_ptr;
|
||||
while (m1 < end)
|
||||
while (m1 <= end)
|
||||
{
|
||||
if ((*m1++) & ~(*m2++))
|
||||
return 0;
|
||||
}
|
||||
/* here both maps have the same number of bits - see assert above */
|
||||
return ((*m1 & ~*m2 & ~map1->last_word_mask) ? 0 : 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* True if bitmaps has any common bits */
|
||||
|
||||
my_bool bitmap_is_overlapping(const MY_BITMAP *map1, const MY_BITMAP *map2)
|
||||
{
|
||||
my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end;
|
||||
my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end= map1->last_word_ptr;
|
||||
DBUG_ASSERT_IDENTICAL_BITMAPS(map1,map2);
|
||||
|
||||
DBUG_ASSERT(map1->bitmap);
|
||||
DBUG_ASSERT(map2->bitmap);
|
||||
DBUG_ASSERT(map1->n_bits==map2->n_bits);
|
||||
|
||||
end= map1->last_word_ptr;
|
||||
while (m1 < end)
|
||||
while (m1 <= end)
|
||||
{
|
||||
if ((*m1++) & (*m2++))
|
||||
return 1;
|
||||
}
|
||||
/* here both maps have the same number of bits - see assert above */
|
||||
return ((*m1 & *m2 & ~map1->last_word_mask) ? 1 : 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Create intersection of two bitmaps
|
||||
|
||||
@param map map1. Result is stored here
|
||||
@param map2 map2
|
||||
*/
|
||||
|
||||
void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2)
|
||||
{
|
||||
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
|
||||
uint len= no_words_in_map(map), len2 = no_words_in_map(map2);
|
||||
|
||||
DBUG_ASSERT(map->bitmap);
|
||||
DBUG_ASSERT(map2->bitmap);
|
||||
DBUG_ASSERT_DIFFERENT_BITMAPS(map,map2);
|
||||
|
||||
end= to+MY_MIN(len,len2);
|
||||
while (to < end)
|
||||
@ -437,7 +445,7 @@ void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2)
|
||||
|
||||
if (len2 <= len)
|
||||
{
|
||||
to[-1]&= ~map2->last_word_mask; /* Clear last not relevant bits */
|
||||
to[-1]&= ~map2->last_bit_mask; /* Clear last not relevant bits */
|
||||
end+= len-len2;
|
||||
while (to < end)
|
||||
*to++= 0;
|
||||
@ -447,50 +455,51 @@ void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2)
|
||||
|
||||
/*
|
||||
Check if there is some bit index between start_bit and end_bit, such that
|
||||
this is bit is set for all bitmaps in bitmap_list.
|
||||
this is at least on bit that set for all bitmaps in bitmap_list.
|
||||
|
||||
SYNOPSIS
|
||||
bitmap_exists_intersection()
|
||||
bitmpap_array [in] a set of MY_BITMAPs
|
||||
bitmap_count [in] number of elements in bitmpap_array
|
||||
bitmap_count [in] number of elements in bitmap_array
|
||||
start_bit [in] beginning (inclusive) of the range of bits to search
|
||||
end_bit [in] end (inclusive) of the range of bits to search, must be
|
||||
no bigger than the bits of the shortest bitmap.
|
||||
|
||||
NOTES
|
||||
This function assumes that for at least one of the bitmaps in bitmap_array all
|
||||
bits outside the range [start_bit, end_bit] are 0. As a result is not
|
||||
necessary to take care of the bits outside the range [start_bit, end_bit].
|
||||
|
||||
RETURN
|
||||
TRUE if an intersecion exists
|
||||
FALSE no intersection
|
||||
*/
|
||||
|
||||
my_bool bitmap_exists_intersection(const MY_BITMAP **bitmap_array,
|
||||
my_bool bitmap_exists_intersection(MY_BITMAP **bitmap_array,
|
||||
uint bitmap_count,
|
||||
uint start_bit, uint end_bit)
|
||||
{
|
||||
uint i, j, start_idx, end_idx;
|
||||
my_bitmap_map cur_res;
|
||||
my_bitmap_map cur_res, first_map;
|
||||
|
||||
DBUG_ASSERT(bitmap_count);
|
||||
DBUG_ASSERT(end_bit >= start_bit);
|
||||
for (j= 0; j < bitmap_count; j++)
|
||||
DBUG_ASSERT(end_bit < bitmap_array[j]->n_bits);
|
||||
{
|
||||
DBUG_ASSERT_BITMAP_AND_BIT(bitmap_array[j], end_bit);
|
||||
}
|
||||
|
||||
start_idx= start_bit/8/sizeof(my_bitmap_map);
|
||||
end_idx= end_bit/8/sizeof(my_bitmap_map);
|
||||
|
||||
first_map= first_bit_mask_inv(start_bit);
|
||||
cur_res= first_map;
|
||||
for (i= start_idx; i < end_idx; i++)
|
||||
{
|
||||
cur_res= ~0;
|
||||
for (j= 0; cur_res && j < bitmap_count; j++)
|
||||
cur_res &= bitmap_array[j]->bitmap[i];
|
||||
if (cur_res)
|
||||
return TRUE;
|
||||
cur_res= ~(my_bitmap_map) 0;
|
||||
}
|
||||
cur_res= ~last_word_mask(end_bit);
|
||||
cur_res= ~last_bit_mask(end_bit+1);
|
||||
if (start_idx == end_idx)
|
||||
cur_res&= first_map;
|
||||
for (j= 0; cur_res && j < bitmap_count; j++)
|
||||
cur_res &= bitmap_array[j]->bitmap[end_idx];
|
||||
return cur_res != 0;
|
||||
@ -501,60 +510,21 @@ my_bool bitmap_exists_intersection(const MY_BITMAP **bitmap_array,
|
||||
|
||||
my_bool bitmap_union_is_set_all(const MY_BITMAP *map1, const MY_BITMAP *map2)
|
||||
{
|
||||
my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end;
|
||||
my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end= map1->last_word_ptr;
|
||||
DBUG_ASSERT_IDENTICAL_BITMAPS(map1,map2);
|
||||
|
||||
DBUG_ASSERT(map1->bitmap);
|
||||
DBUG_ASSERT(map2->bitmap);
|
||||
DBUG_ASSERT(map1->n_bits==map2->n_bits);
|
||||
end= map1->last_word_ptr;
|
||||
while ( m1 < end)
|
||||
if ((*m1++ | *m2++) != 0xFFFFFFFF)
|
||||
if ((*m1++ | *m2++) != ~(my_bitmap_map)0)
|
||||
return FALSE;
|
||||
/* here both maps have the same number of bits - see assert above */
|
||||
return ((*m1 | *m2 | map1->last_word_mask) != 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Set/clear all bits above a bit.
|
||||
|
||||
SYNOPSIS
|
||||
bitmap_set_above()
|
||||
map RETURN The bitmap to change.
|
||||
from_byte The bitmap buffer byte offset to start with.
|
||||
use_bit The bit value (1/0) to use for all upper bits.
|
||||
|
||||
NOTE
|
||||
You can only set/clear full bytes.
|
||||
The function is meant for the situation that you copy a smaller bitmap
|
||||
to a bigger bitmap. Bitmap lengths are always multiple of eigth (the
|
||||
size of a byte). Using 'from_byte' saves multiplication and division
|
||||
by eight during parameter passing.
|
||||
|
||||
RETURN
|
||||
void
|
||||
*/
|
||||
|
||||
void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit)
|
||||
{
|
||||
uchar use_byte= use_bit ? 0xff : 0;
|
||||
uchar *to= (uchar *)map->bitmap + from_byte;
|
||||
uchar *end= (uchar *)map->bitmap + (map->n_bits+7)/8;
|
||||
|
||||
while (to < end)
|
||||
*to++= use_byte;
|
||||
return ((*m1 | *m2 | map1->last_bit_mask) != ~(my_bitmap_map)0);
|
||||
}
|
||||
|
||||
|
||||
void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2)
|
||||
{
|
||||
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
|
||||
DBUG_ASSERT(map->bitmap);
|
||||
DBUG_ASSERT(map2->bitmap);
|
||||
DBUG_ASSERT(map->n_bits==map2->n_bits);
|
||||
|
||||
end= map->last_word_ptr;
|
||||
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end= map->last_word_ptr;
|
||||
DBUG_ASSERT_IDENTICAL_BITMAPS(map,map2);
|
||||
|
||||
while (to <= end)
|
||||
*to++ &= ~(*from++);
|
||||
@ -563,12 +533,8 @@ void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2)
|
||||
|
||||
void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2)
|
||||
{
|
||||
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
|
||||
|
||||
DBUG_ASSERT(map->bitmap);
|
||||
DBUG_ASSERT(map2->bitmap);
|
||||
DBUG_ASSERT(map->n_bits == map2->n_bits);
|
||||
end= map->last_word_ptr;
|
||||
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end= map->last_word_ptr;
|
||||
DBUG_ASSERT_IDENTICAL_BITMAPS(map,map2);
|
||||
|
||||
while (to <= end)
|
||||
*to++ |= *from++;
|
||||
@ -578,9 +544,8 @@ void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2)
|
||||
void bitmap_xor(MY_BITMAP *map, const MY_BITMAP *map2)
|
||||
{
|
||||
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end= map->last_word_ptr;
|
||||
DBUG_ASSERT(map->bitmap);
|
||||
DBUG_ASSERT(map2->bitmap);
|
||||
DBUG_ASSERT(map->n_bits == map2->n_bits);
|
||||
DBUG_ASSERT_IDENTICAL_BITMAPS(map,map2);
|
||||
|
||||
while (to <= end)
|
||||
*to++ ^= *from++;
|
||||
}
|
||||
@ -588,13 +553,14 @@ void bitmap_xor(MY_BITMAP *map, const MY_BITMAP *map2)
|
||||
|
||||
void bitmap_invert(MY_BITMAP *map)
|
||||
{
|
||||
my_bitmap_map *to= map->bitmap, *end;
|
||||
my_bitmap_map *to= map->bitmap, *end= map->last_word_ptr;
|
||||
DBUG_ASSERT_BITMAP(map);
|
||||
|
||||
DBUG_ASSERT(map->bitmap);
|
||||
end= map->last_word_ptr;
|
||||
while (to < end)
|
||||
*to++ ^= ~(my_bitmap_map)0;
|
||||
|
||||
while (to <= end)
|
||||
*to++ ^= 0xFFFFFFFF;
|
||||
*to ^= (~(my_bitmap_map)0 & ~map->last_bit_mask);
|
||||
DBUG_ASSERT_BITMAP(map);
|
||||
}
|
||||
|
||||
|
||||
@ -603,45 +569,54 @@ uint bitmap_bits_set(const MY_BITMAP *map)
|
||||
my_bitmap_map *data_ptr= map->bitmap;
|
||||
my_bitmap_map *end= map->last_word_ptr;
|
||||
uint res= 0;
|
||||
DBUG_ASSERT(map->bitmap);
|
||||
DBUG_ASSERT_BITMAP(map);
|
||||
|
||||
for (; data_ptr < end; data_ptr++)
|
||||
res+= my_count_bits_uint32(*data_ptr);
|
||||
for (; data_ptr <= end; data_ptr++)
|
||||
res+= my_count_bits(*data_ptr);
|
||||
|
||||
/*Reset last bits to zero*/
|
||||
res+= my_count_bits_uint32(*map->last_word_ptr & ~map->last_word_mask);
|
||||
return res;
|
||||
}
|
||||
|
||||
void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2)
|
||||
|
||||
/**
|
||||
Copy bitmaps
|
||||
|
||||
@param map1 to-bitmap
|
||||
@param map2 from-bitmap
|
||||
|
||||
@notes
|
||||
Code will work even of the bitmaps are of different size.
|
||||
In this case, only up to to->n_bits will be copied.
|
||||
*/
|
||||
|
||||
void bitmap_copy(MY_BITMAP *map1, const MY_BITMAP *map2)
|
||||
{
|
||||
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
|
||||
my_bitmap_map *to= map1->bitmap, *from= map2->bitmap;
|
||||
uint map1_length= no_words_in_map(map1)*sizeof(my_bitmap_map);
|
||||
uint map2_length= no_words_in_map(map2)*sizeof(my_bitmap_map);
|
||||
uint length= MY_MIN(map1_length, map2_length);
|
||||
DBUG_ASSERT_DIFFERENT_BITMAPS(map1,map2);
|
||||
|
||||
DBUG_ASSERT(map->bitmap);
|
||||
DBUG_ASSERT(map2->bitmap);
|
||||
DBUG_ASSERT(map->n_bits == map2->n_bits);
|
||||
end= map->last_word_ptr;
|
||||
|
||||
while (to <= end)
|
||||
*to++ = *from++;
|
||||
memcpy(to, from, length);
|
||||
if (length < map1_length)
|
||||
bzero(to + length, map1_length - length);
|
||||
*map1->last_word_ptr&= ~map1->last_bit_mask;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Find first set bit in the bitmap
|
||||
*/
|
||||
|
||||
uint bitmap_get_first_set(const MY_BITMAP *map)
|
||||
{
|
||||
uint i;
|
||||
my_bitmap_map *data_ptr= map->bitmap, *end= map->last_word_ptr;
|
||||
DBUG_ASSERT_BITMAP(map);
|
||||
|
||||
DBUG_ASSERT(map->bitmap);
|
||||
|
||||
for (i=0; data_ptr < end; data_ptr++, i++)
|
||||
for (uint i=0; data_ptr <= end; data_ptr++, i++)
|
||||
if (*data_ptr)
|
||||
goto found;
|
||||
if (!(*data_ptr & ~map->last_word_mask))
|
||||
return MY_BIT_NONE;
|
||||
|
||||
found:
|
||||
return get_first_set(*data_ptr, i);
|
||||
return my_find_first_bit(*data_ptr) + i * sizeof(my_bitmap_map)*8;
|
||||
return MY_BIT_NONE;
|
||||
}
|
||||
|
||||
|
||||
@ -656,82 +631,54 @@ found:
|
||||
|
||||
uint bitmap_get_next_set(const MY_BITMAP *map, uint bitmap_bit)
|
||||
{
|
||||
uint word_pos, byte_to_mask, i;
|
||||
union { my_bitmap_map bitmap ; uchar bitmap_buff[sizeof(my_bitmap_map)]; }
|
||||
first_word;
|
||||
uchar *ptr= &first_word.bitmap_buff[0];
|
||||
my_bitmap_map *data_ptr, *end= map->last_word_ptr;
|
||||
|
||||
DBUG_ASSERT(map->bitmap);
|
||||
uint word_pos;
|
||||
my_bitmap_map first_word, *data_ptr, *end= map->last_word_ptr;
|
||||
DBUG_ASSERT_BITMAP(map);
|
||||
|
||||
/* Look for the next bit */
|
||||
bitmap_bit++;
|
||||
if (bitmap_bit >= map->n_bits)
|
||||
return MY_BIT_NONE;
|
||||
word_pos= bitmap_bit / 32;
|
||||
|
||||
word_pos= bitmap_bit / 64;
|
||||
data_ptr= map->bitmap + word_pos;
|
||||
first_word.bitmap= *data_ptr;
|
||||
|
||||
/* Mask out previous bits from first_word */
|
||||
byte_to_mask= (bitmap_bit % 32) / 8;
|
||||
for (i= 0; i < byte_to_mask; i++)
|
||||
ptr[i]= 0;
|
||||
ptr[byte_to_mask]&= 0xFFU << (bitmap_bit & 7);
|
||||
first_word= *data_ptr & first_bit_mask_inv(bitmap_bit);
|
||||
|
||||
if (data_ptr == end)
|
||||
if (first_word)
|
||||
{
|
||||
if (first_word.bitmap & ~map->last_word_mask)
|
||||
return get_first_set(first_word.bitmap, word_pos);
|
||||
else
|
||||
return MY_BIT_NONE;
|
||||
/* Optimize common case when most bits are set */
|
||||
if (first_word & (1ULL << ((bitmap_bit & (my_bitmap_map_bits-1)))))
|
||||
return bitmap_bit;
|
||||
return my_find_first_bit(first_word) + (bitmap_bit & ~(my_bitmap_map_bits-1));
|
||||
}
|
||||
|
||||
if (first_word.bitmap)
|
||||
return get_first_set(first_word.bitmap, word_pos);
|
||||
|
||||
for (data_ptr++, word_pos++; data_ptr < end; data_ptr++, word_pos++)
|
||||
for (data_ptr++; data_ptr <= end; data_ptr++)
|
||||
{
|
||||
bitmap_bit+= 64;
|
||||
if (*data_ptr)
|
||||
return get_first_set(*data_ptr, word_pos);
|
||||
|
||||
if (!(*end & ~map->last_word_mask))
|
||||
return MY_BIT_NONE;
|
||||
return get_first_set(*end, word_pos);
|
||||
return my_find_first_bit(*data_ptr) + (bitmap_bit & ~(my_bitmap_map_bits-1));
|
||||
}
|
||||
return MY_BIT_NONE;
|
||||
}
|
||||
|
||||
|
||||
/* Get first free bit */
|
||||
/* Get first clear bit */
|
||||
|
||||
uint bitmap_get_first(const MY_BITMAP *map)
|
||||
uint bitmap_get_first_clear(const MY_BITMAP *map)
|
||||
{
|
||||
uchar *byte_ptr;
|
||||
uint i,j,k;
|
||||
my_bitmap_map *data_ptr, *end= map->last_word_ptr;
|
||||
uint i;
|
||||
my_bitmap_map *data_ptr= map->bitmap, *end= map->last_word_ptr;
|
||||
DBUG_ASSERT_BITMAP(map);
|
||||
|
||||
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++)
|
||||
if (*data_ptr != 0xFFFFFFFF)
|
||||
for (i= 0; data_ptr < end; data_ptr++, i++)
|
||||
if (*data_ptr != ~(my_bitmap_map)0)
|
||||
goto found;
|
||||
if ((*data_ptr | map->last_word_mask) == 0xFFFFFFFF)
|
||||
if ((*data_ptr | map->last_bit_mask) == ~(my_bitmap_map)0)
|
||||
return MY_BIT_NONE;
|
||||
|
||||
found:
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
DBUG_ASSERT(0);
|
||||
return MY_BIT_NONE; /* Impossible */
|
||||
/* find first zero bit by reverting all bits and find first bit */
|
||||
return my_find_first_bit(~*data_ptr) + i * sizeof(my_bitmap_map)*8;
|
||||
}
|
||||
|
||||
|
||||
@ -753,4 +700,3 @@ void bitmap_lock_clear_bit(MY_BITMAP *map, uint bitmap_bit)
|
||||
bitmap_clear_bit(map, bitmap_bit);
|
||||
bitmap_unlock(map);
|
||||
}
|
||||
|
||||
|
@ -3731,7 +3731,7 @@ bool ha_partition::init_partition_bitmaps()
|
||||
if (my_bitmap_init(&m_key_not_found_partitions, NULL, m_tot_parts, FALSE))
|
||||
DBUG_RETURN(true);
|
||||
|
||||
if (bitmap_init(&m_mrr_used_partitions, NULL, m_tot_parts, TRUE))
|
||||
if (my_bitmap_init(&m_mrr_used_partitions, NULL, m_tot_parts, TRUE))
|
||||
DBUG_RETURN(true);
|
||||
|
||||
if (my_bitmap_init(&m_opened_partitions, NULL, m_tot_parts, FALSE))
|
||||
|
@ -6706,9 +6706,10 @@ exists_complementing_null_row(MY_BITMAP *keys_to_complement)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return bitmap_exists_intersection((const MY_BITMAP**) null_bitmaps,
|
||||
return bitmap_exists_intersection(null_bitmaps,
|
||||
count_null_keys,
|
||||
(uint)highest_min_row, (uint)lowest_max_row);
|
||||
(uint)highest_min_row,
|
||||
(uint)lowest_max_row);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3387,22 +3387,18 @@ Rows_log_event::Rows_log_event(const uchar *buf, uint event_len,
|
||||
|
||||
/* if my_bitmap_init fails, caught in is_valid() */
|
||||
if (likely(!my_bitmap_init(&m_cols,
|
||||
m_width <= sizeof(m_bitbuf)*8 ? m_bitbuf : NULL,
|
||||
m_width,
|
||||
false)))
|
||||
m_width <= sizeof(m_bitbuf)*8 ? m_bitbuf : NULL,
|
||||
m_width,
|
||||
false)))
|
||||
{
|
||||
DBUG_PRINT("debug", ("Reading from %p", ptr_after_width));
|
||||
memcpy(m_cols.bitmap, ptr_after_width, (m_width + 7) / 8);
|
||||
create_last_word_mask(&m_cols);
|
||||
create_last_bit_mask(&m_cols); // Needed to fix last part of bitmap
|
||||
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;
|
||||
}
|
||||
|
||||
m_cols_ai.bitmap= m_cols.bitmap; /* See explanation in is_valid() */
|
||||
|
||||
@ -3412,23 +3408,20 @@ Rows_log_event::Rows_log_event(const uchar *buf, uint event_len,
|
||||
|
||||
/* if my_bitmap_init fails, caught in is_valid() */
|
||||
if (likely(!my_bitmap_init(&m_cols_ai,
|
||||
m_width <= sizeof(m_bitbuf_ai)*8 ? m_bitbuf_ai : NULL,
|
||||
m_width,
|
||||
false)))
|
||||
m_width <= sizeof(m_bitbuf_ai)*8 ? m_bitbuf_ai :
|
||||
NULL,
|
||||
m_width,
|
||||
false)))
|
||||
{
|
||||
DBUG_PRINT("debug", ("Reading from %p", ptr_after_width));
|
||||
memcpy(m_cols_ai.bitmap, ptr_after_width, (m_width + 7) / 8);
|
||||
create_last_word_mask(&m_cols_ai);
|
||||
create_last_bit_mask(&m_cols_ai); // Needed to fix last part of bitmap
|
||||
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
|
||||
{
|
||||
// Needed because my_bitmap_init() does not set it to null on failure
|
||||
m_cols_ai.bitmap= 0;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
}
|
||||
|
||||
const uchar* const ptr_rows_data= (const uchar*) ptr_after_width;
|
||||
@ -3491,8 +3484,6 @@ void Rows_log_event::uncompress_buf()
|
||||
|
||||
Rows_log_event::~Rows_log_event()
|
||||
{
|
||||
if (m_cols.bitmap == m_bitbuf) // no my_malloc happened
|
||||
m_cols.bitmap= 0; // so no my_free in my_bitmap_free
|
||||
my_bitmap_free(&m_cols); // To pair with my_bitmap_init().
|
||||
my_free(m_rows_buf);
|
||||
my_free(m_extra_row_data);
|
||||
@ -4058,12 +4049,7 @@ Delete_rows_compressed_log_event::Delete_rows_compressed_log_event(
|
||||
|
||||
Update_rows_log_event::~Update_rows_log_event()
|
||||
{
|
||||
if (m_cols_ai.bitmap)
|
||||
{
|
||||
if (m_cols_ai.bitmap == m_bitbuf_ai) // no my_malloc happened
|
||||
m_cols_ai.bitmap= 0; // so no my_free in my_bitmap_free
|
||||
my_bitmap_free(&m_cols_ai); // To pair with my_bitmap_init().
|
||||
}
|
||||
my_bitmap_free(&m_cols_ai); // To pair with my_bitmap_init().
|
||||
}
|
||||
|
||||
|
||||
|
@ -5163,8 +5163,8 @@ protected:
|
||||
ulong m_master_reclength; /* Length of record on master side */
|
||||
|
||||
/* Bit buffers in the same memory as the class */
|
||||
uint32 m_bitbuf[128/(sizeof(uint32)*8)];
|
||||
uint32 m_bitbuf_ai[128/(sizeof(uint32)*8)];
|
||||
my_bitmap_map m_bitbuf[128/(sizeof(my_bitmap_map)*8)];
|
||||
my_bitmap_map m_bitbuf_ai[128/(sizeof(my_bitmap_map)*8)];
|
||||
|
||||
uchar *m_rows_buf; /* The rows in packed format */
|
||||
uchar *m_rows_cur; /* One-after the end of the data */
|
||||
|
@ -1156,21 +1156,13 @@ Old_rows_log_event::Old_rows_log_event(THD *thd_arg, TABLE *tbl_arg,
|
||||
set_flags(RELAXED_UNIQUE_CHECKS_F);
|
||||
/* if my_bitmap_init fails, caught in is_valid() */
|
||||
if (likely(!my_bitmap_init(&m_cols,
|
||||
m_width <= sizeof(m_bitbuf)*8 ? m_bitbuf : NULL,
|
||||
m_width,
|
||||
false)))
|
||||
m_width <= sizeof(m_bitbuf)*8 ? m_bitbuf : NULL,
|
||||
m_width,
|
||||
false)))
|
||||
{
|
||||
/* Cols can be zero if this is a dummy binrows event */
|
||||
if (likely(cols != NULL))
|
||||
{
|
||||
memcpy(m_cols.bitmap, cols->bitmap, no_bytes_in_map(cols));
|
||||
create_last_word_mask(&m_cols);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Needed because my_bitmap_init() does not set it to null on failure
|
||||
m_cols.bitmap= 0;
|
||||
bitmap_copy(&m_cols, cols);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -1232,13 +1224,13 @@ Old_rows_log_event::Old_rows_log_event(const uchar *buf, uint event_len,
|
||||
|
||||
/* if my_bitmap_init fails, caught in is_valid() */
|
||||
if (likely(!my_bitmap_init(&m_cols,
|
||||
m_width <= sizeof(m_bitbuf)*8 ? m_bitbuf : NULL,
|
||||
m_width,
|
||||
false)))
|
||||
m_width <= sizeof(m_bitbuf)*8 ? m_bitbuf : NULL,
|
||||
m_width,
|
||||
false)))
|
||||
{
|
||||
DBUG_PRINT("debug", ("Reading from %p", ptr_after_width));
|
||||
memcpy(m_cols.bitmap, ptr_after_width, (m_width + 7) / 8);
|
||||
create_last_word_mask(&m_cols);
|
||||
create_last_bit_mask(&m_cols); // Needed to fix last part of bitmap
|
||||
ptr_after_width+= (m_width + 7) / 8;
|
||||
DBUG_DUMP("m_cols", (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols));
|
||||
}
|
||||
@ -1274,8 +1266,6 @@ Old_rows_log_event::Old_rows_log_event(const uchar *buf, uint event_len,
|
||||
|
||||
Old_rows_log_event::~Old_rows_log_event()
|
||||
{
|
||||
if (m_cols.bitmap == m_bitbuf) // no my_malloc happened
|
||||
m_cols.bitmap= 0; // so no my_free in my_bitmap_free
|
||||
my_bitmap_free(&m_cols); // To pair with my_bitmap_init().
|
||||
my_free(m_rows_buf);
|
||||
}
|
||||
|
@ -183,8 +183,8 @@ protected:
|
||||
ulong m_master_reclength; /* Length of record on master side */
|
||||
|
||||
/* Bit buffers in the same memory as the class */
|
||||
uint32 m_bitbuf[128/(sizeof(uint32)*8)];
|
||||
uint32 m_bitbuf_ai[128/(sizeof(uint32)*8)];
|
||||
my_bitmap_map m_bitbuf[128/(sizeof(my_bitmap_map)*8)];
|
||||
my_bitmap_map m_bitbuf_ai[128/(sizeof(my_bitmap_map)*8)];
|
||||
|
||||
uchar *m_rows_buf; /* The rows in packed format */
|
||||
uchar *m_rows_cur; /* One-after the end of the data */
|
||||
|
@ -5289,21 +5289,13 @@ Rows_log_event::Rows_log_event(THD *thd_arg, TABLE *tbl_arg,
|
||||
set_flags(NO_CHECK_CONSTRAINT_CHECKS_F);
|
||||
/* if my_bitmap_init fails, caught in is_valid() */
|
||||
if (likely(!my_bitmap_init(&m_cols,
|
||||
m_width <= sizeof(m_bitbuf)*8 ? m_bitbuf : NULL,
|
||||
m_width,
|
||||
false)))
|
||||
m_width <= sizeof(m_bitbuf)*8 ? m_bitbuf : NULL,
|
||||
m_width,
|
||||
false)))
|
||||
{
|
||||
/* Cols can be zero if this is a dummy binrows event */
|
||||
if (likely(cols != NULL))
|
||||
{
|
||||
memcpy(m_cols.bitmap, cols->bitmap, no_bytes_in_map(cols));
|
||||
create_last_word_mask(&m_cols);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Needed because my_bitmap_init() does not set it to null on failure
|
||||
m_cols.bitmap= 0;
|
||||
bitmap_copy(&m_cols, cols);
|
||||
}
|
||||
}
|
||||
|
||||
@ -8401,7 +8393,7 @@ void Update_rows_log_event::init(MY_BITMAP const *cols)
|
||||
if (likely(cols != NULL))
|
||||
{
|
||||
memcpy(m_cols_ai.bitmap, cols->bitmap, no_bytes_in_map(cols));
|
||||
create_last_word_mask(&m_cols_ai);
|
||||
create_last_bit_mask(&m_cols_ai); // Needed to fix last part of bitmap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3582,7 +3582,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
|
||||
table->reginfo.impossible_range= 0;
|
||||
|
||||
uint used_fields_buff_size= bitmap_buffer_size(table->s->fields);
|
||||
uint32 *used_fields_buff= (uint32*)thd->alloc(used_fields_buff_size);
|
||||
my_bitmap_map *used_fields_buff= (my_bitmap_map*)thd->alloc(used_fields_buff_size);
|
||||
MY_BITMAP cols_for_indexes;
|
||||
(void) my_bitmap_init(&cols_for_indexes, used_fields_buff, table->s->fields, 0);
|
||||
bitmap_clear_all(&cols_for_indexes);
|
||||
@ -7439,7 +7439,7 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param,
|
||||
(*scan)->used_fields_covered=
|
||||
bitmap_bits_set(&(*scan)->covered_fields);
|
||||
(*scan)->first_uncovered_field=
|
||||
bitmap_get_first(&(*scan)->covered_fields);
|
||||
bitmap_get_first_clear(&(*scan)->covered_fields);
|
||||
}
|
||||
|
||||
my_qsort(ror_scan_mark, ror_scans_end-ror_scan_mark, sizeof(ROR_SCAN_INFO*),
|
||||
|
@ -1419,7 +1419,7 @@ static bool check_view_insertability(THD * thd, TABLE_LIST *view)
|
||||
*trans_end= trans_start + num;
|
||||
Field_translator *trans;
|
||||
uint used_fields_buff_size= bitmap_buffer_size(table->s->fields);
|
||||
uint32 *used_fields_buff= (uint32*)thd->alloc(used_fields_buff_size);
|
||||
my_bitmap_map *used_fields_buff= (my_bitmap_map*)thd->alloc(used_fields_buff_size);
|
||||
MY_BITMAP used_fields;
|
||||
enum_column_usage saved_column_usage= thd->column_usage;
|
||||
DBUG_ENTER("check_key_in_view");
|
||||
@ -2828,6 +2828,8 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
|
||||
copy->def_read_set.bitmap= (my_bitmap_map*) bitmap;
|
||||
copy->def_write_set.bitmap= ((my_bitmap_map*)
|
||||
(bitmap + share->column_bitmap_size));
|
||||
create_last_bit_mask(©->def_read_set);
|
||||
create_last_bit_mask(©->def_write_set);
|
||||
bitmaps_used= 2;
|
||||
if (share->default_fields || share->default_expressions)
|
||||
{
|
||||
|
@ -1085,7 +1085,7 @@ void check_range_capable_PF(TABLE *table)
|
||||
|
||||
static bool set_up_partition_bitmaps(THD *thd, partition_info *part_info)
|
||||
{
|
||||
uint32 *bitmap_buf;
|
||||
my_bitmap_map *bitmap_buf;
|
||||
uint bitmap_bits= part_info->num_subparts?
|
||||
(part_info->num_subparts* part_info->num_parts):
|
||||
part_info->num_parts;
|
||||
@ -1096,14 +1096,15 @@ static bool set_up_partition_bitmaps(THD *thd, partition_info *part_info)
|
||||
|
||||
/* Allocate for both read and lock_partitions */
|
||||
if (unlikely(!(bitmap_buf=
|
||||
(uint32*) alloc_root(&part_info->table->mem_root,
|
||||
bitmap_bytes * 2))))
|
||||
(my_bitmap_map*) alloc_root(&part_info->table->mem_root,
|
||||
bitmap_bytes * 2))))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
my_bitmap_init(&part_info->read_partitions, bitmap_buf, bitmap_bits, FALSE);
|
||||
/* Use the second half of the allocated buffer for lock_partitions */
|
||||
my_bitmap_init(&part_info->lock_partitions, bitmap_buf + (bitmap_bytes / 4),
|
||||
bitmap_bits, FALSE);
|
||||
my_bitmap_init(&part_info->lock_partitions,
|
||||
(my_bitmap_map*) (((char*) bitmap_buf) + bitmap_bytes),
|
||||
bitmap_bits, FALSE);
|
||||
part_info->bitmaps_are_initialized= TRUE;
|
||||
part_info->set_partition_bitmaps(NULL);
|
||||
DBUG_RETURN(FALSE);
|
||||
|
@ -4923,7 +4923,8 @@ int ha_mroonga::open(const char *name,
|
||||
DBUG_RETURN(error);
|
||||
thr_lock_data_init(&share->lock,&thr_lock_data,NULL);
|
||||
|
||||
if (bitmap_init(&multiple_column_key_bitmap, NULL, table->s->fields, false))
|
||||
if (my_bitmap_init(&multiple_column_key_bitmap, NULL, table->s->fields,
|
||||
false))
|
||||
{
|
||||
mrn_free_share(share);
|
||||
share = NULL;
|
||||
@ -4939,7 +4940,7 @@ int ha_mroonga::open(const char *name,
|
||||
|
||||
if (error)
|
||||
{
|
||||
bitmap_free(&multiple_column_key_bitmap);
|
||||
my_bitmap_free(&multiple_column_key_bitmap);
|
||||
mrn_free_share(share);
|
||||
share = NULL;
|
||||
}
|
||||
@ -5017,7 +5018,7 @@ int ha_mroonga::close()
|
||||
{
|
||||
error = add_wrap_hton(share->table_name, share->hton);
|
||||
}
|
||||
bitmap_free(&multiple_column_key_bitmap);
|
||||
my_bitmap_free(&multiple_column_key_bitmap);
|
||||
if (share->use_count == 1) {
|
||||
mrn_free_long_term_share(share->long_term_share);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ namespace mrn {
|
||||
|
||||
SmartBitmap::~SmartBitmap() {
|
||||
if (bitmap_) {
|
||||
bitmap_free(bitmap_);
|
||||
my_bitmap_free(bitmap_);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10832,7 +10832,7 @@ int ha_rocksdb::index_end() {
|
||||
|
||||
release_scan_iterator();
|
||||
|
||||
bitmap_free(&m_lookup_bitmap);
|
||||
my_bitmap_free(&m_lookup_bitmap);
|
||||
|
||||
active_index = MAX_KEY;
|
||||
in_range_check_pushed_down = FALSE;
|
||||
|
@ -397,7 +397,7 @@ class ha_rocksdb : public my_core::handler {
|
||||
current lookup to be covered. If the bitmap field is null, that means this
|
||||
index does not cover the current lookup for any record.
|
||||
*/
|
||||
MY_BITMAP m_lookup_bitmap = {nullptr, nullptr, nullptr, 0, 0};
|
||||
MY_BITMAP m_lookup_bitmap = {nullptr, nullptr, nullptr, 0, 0, 0};
|
||||
|
||||
int alloc_key_buffers(const TABLE *const table_arg,
|
||||
const Rdb_tbl_def *const tbl_def_arg,
|
||||
|
@ -1102,12 +1102,12 @@ size_t Rdb_key_def::get_unpack_header_size(char tag) {
|
||||
*/
|
||||
void Rdb_key_def::get_lookup_bitmap(const TABLE *table, MY_BITMAP *map) const {
|
||||
DBUG_ASSERT(map->bitmap == nullptr);
|
||||
bitmap_init(map, nullptr, MAX_REF_PARTS, false);
|
||||
my_bitmap_init(map, nullptr, MAX_REF_PARTS, false);
|
||||
uint curr_bitmap_pos = 0;
|
||||
|
||||
// Indicates which columns in the read set might be covered.
|
||||
MY_BITMAP maybe_covered_bitmap;
|
||||
bitmap_init(&maybe_covered_bitmap, nullptr, table->read_set->n_bits, false);
|
||||
my_bitmap_init(&maybe_covered_bitmap, nullptr, table->read_set->n_bits, false);
|
||||
|
||||
for (uint i = 0; i < m_key_parts; i++) {
|
||||
if (table_has_hidden_pk(table) && i + 1 == m_key_parts) {
|
||||
@ -1135,8 +1135,8 @@ void Rdb_key_def::get_lookup_bitmap(const TABLE *table, MY_BITMAP *map) const {
|
||||
}
|
||||
curr_bitmap_pos++;
|
||||
} else {
|
||||
bitmap_free(&maybe_covered_bitmap);
|
||||
bitmap_free(map);
|
||||
my_bitmap_free(&maybe_covered_bitmap);
|
||||
my_bitmap_free(map);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@ -1144,8 +1144,8 @@ void Rdb_key_def::get_lookup_bitmap(const TABLE *table, MY_BITMAP *map) const {
|
||||
// know this lookup will never be covered.
|
||||
default:
|
||||
if (bitmap_is_set(table->read_set, field->field_index)) {
|
||||
bitmap_free(&maybe_covered_bitmap);
|
||||
bitmap_free(map);
|
||||
my_bitmap_free(&maybe_covered_bitmap);
|
||||
my_bitmap_free(map);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@ -1155,9 +1155,9 @@ void Rdb_key_def::get_lookup_bitmap(const TABLE *table, MY_BITMAP *map) const {
|
||||
// If there are columns which are not covered in the read set, the lookup
|
||||
// can't be covered.
|
||||
if (!bitmap_cmp(table->read_set, &maybe_covered_bitmap)) {
|
||||
bitmap_free(map);
|
||||
my_bitmap_free(map);
|
||||
}
|
||||
bitmap_free(&maybe_covered_bitmap);
|
||||
my_bitmap_free(&maybe_covered_bitmap);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1187,7 +1187,7 @@ bool Rdb_key_def::covers_lookup(const rocksdb::Slice *const unpack_info,
|
||||
|
||||
MY_BITMAP covered_bitmap;
|
||||
my_bitmap_map covered_bits;
|
||||
bitmap_init(&covered_bitmap, &covered_bits, MAX_REF_PARTS, false);
|
||||
my_bitmap_init(&covered_bitmap, &covered_bits, MAX_REF_PARTS, false);
|
||||
covered_bits = rdb_netbuf_to_uint16((const uchar *)unpack_header +
|
||||
sizeof(RDB_UNPACK_COVERED_DATA_TAG) +
|
||||
RDB_UNPACK_COVERED_DATA_LEN_SIZE);
|
||||
@ -1356,7 +1356,7 @@ uint Rdb_key_def::pack_record(const TABLE *const tbl, uchar *const pack_buffer,
|
||||
MY_BITMAP covered_bitmap;
|
||||
my_bitmap_map covered_bits;
|
||||
uint curr_bitmap_pos = 0;
|
||||
bitmap_init(&covered_bitmap, &covered_bits, MAX_REF_PARTS, false);
|
||||
my_bitmap_init(&covered_bitmap, &covered_bits, MAX_REF_PARTS, false);
|
||||
|
||||
for (uint i = 0; i < n_key_parts; i++) {
|
||||
// Fill hidden pk id into the last key part for secondary keys for tables
|
||||
@ -1661,7 +1661,7 @@ int Rdb_key_def::unpack_record(TABLE *const table, uchar *const buf,
|
||||
bool has_covered_bitmap =
|
||||
has_unpack_info && (unpack_header[0] == RDB_UNPACK_COVERED_DATA_TAG);
|
||||
if (has_covered_bitmap) {
|
||||
bitmap_init(&covered_bitmap, &covered_bits, MAX_REF_PARTS, false);
|
||||
my_bitmap_init(&covered_bitmap, &covered_bits, MAX_REF_PARTS, false);
|
||||
covered_bits = rdb_netbuf_to_uint16((const uchar *)unpack_header +
|
||||
sizeof(RDB_UNPACK_COVERED_DATA_TAG) +
|
||||
RDB_UNPACK_COVERED_DATA_LEN_SIZE);
|
||||
|
@ -29,6 +29,8 @@
|
||||
|
||||
uint get_rand_bit(uint bitsize)
|
||||
{
|
||||
if (bitsize == 0)
|
||||
return 0;
|
||||
return (rand() % bitsize);
|
||||
}
|
||||
|
||||
@ -266,7 +268,7 @@ my_bool test_get_first_bit(MY_BITMAP *map, uint bitsize)
|
||||
bitmap_clear_all(map);
|
||||
for (i=0; i < bitsize; i++)
|
||||
bitmap_set_bit(map, i);
|
||||
if (bitmap_get_first(map) != MY_BIT_NONE)
|
||||
if (bitmap_get_first_clear(map) != MY_BIT_NONE)
|
||||
goto error2;
|
||||
bitmap_clear_all(map);
|
||||
|
||||
@ -278,7 +280,7 @@ my_bool test_get_first_bit(MY_BITMAP *map, uint bitsize)
|
||||
goto error1;
|
||||
bitmap_set_all(map);
|
||||
bitmap_clear_bit(map, test_bit);
|
||||
if (bitmap_get_first(map) != test_bit)
|
||||
if (bitmap_get_first_clear(map) != test_bit)
|
||||
goto error2;
|
||||
bitmap_clear_all(map);
|
||||
}
|
||||
@ -297,14 +299,45 @@ my_bool test_get_next_bit(MY_BITMAP *map, uint bitsize)
|
||||
uint no_loops= bitsize > 128 ? 128 : bitsize;
|
||||
for (i=0; i < no_loops; i++)
|
||||
{
|
||||
uint count= 0, bits_set= 0;
|
||||
bitmap_clear_all(map);
|
||||
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;
|
||||
j= bitmap_get_first_set(map);
|
||||
if (j == MY_BIT_NONE)
|
||||
{
|
||||
if (test_bit != 0)
|
||||
goto error1;
|
||||
continue;
|
||||
}
|
||||
count= 1;
|
||||
while ((j= bitmap_get_next_set(map,j)) != MY_BIT_NONE)
|
||||
count++;
|
||||
if (count != test_bit)
|
||||
goto error1;
|
||||
|
||||
if (test_bit < 3)
|
||||
continue;
|
||||
bitmap_clear_all(map);
|
||||
for (j=1; j < test_bit; j+=2)
|
||||
{
|
||||
bits_set++;
|
||||
bitmap_set_bit(map, j);
|
||||
}
|
||||
if ((j= bitmap_get_first_set(map)) == MY_BIT_NONE)
|
||||
goto error1;
|
||||
count= 1;
|
||||
while ((j= bitmap_get_next_set(map,j)) != MY_BIT_NONE)
|
||||
count++;
|
||||
if (count != bits_set)
|
||||
goto error1;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
error1:
|
||||
diag("get_next error bitsize= %u, prefix_size= %u", bitsize,test_bit);
|
||||
return TRUE;
|
||||
@ -371,7 +404,7 @@ error5:
|
||||
my_bool test_compare(MY_BITMAP *map, uint bitsize)
|
||||
{
|
||||
MY_BITMAP map2;
|
||||
uint32 map2buf[MAX_TESTED_BITMAP_SIZE];
|
||||
my_bitmap_map map2buf[MAX_TESTED_BITMAP_SIZE];
|
||||
uint i, test_bit;
|
||||
uint no_loops= bitsize > 128 ? 128 : bitsize;
|
||||
if (my_bitmap_init(&map2, map2buf, bitsize, FALSE))
|
||||
@ -431,7 +464,7 @@ 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[MAX_TESTED_BITMAP_SIZE];
|
||||
my_bitmap_map map2buf[MAX_TESTED_BITMAP_SIZE];
|
||||
uint i, test_bit1, test_bit2, test_bit3;
|
||||
if (my_bitmap_init(&map2, map2buf, bitsize2, FALSE))
|
||||
{
|
||||
@ -477,6 +510,94 @@ error:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
my_bool test_copy(MY_BITMAP *map, uint bitsize)
|
||||
{
|
||||
my_bitmap_map buff[16];
|
||||
MY_BITMAP map2;
|
||||
my_bitmap_init(&map2, buff, sizeof(buff)*8, FALSE);
|
||||
memset((void*) buff, 0xff, sizeof(buff));
|
||||
|
||||
bitsize= MY_MIN(bitsize, map2.n_bits);
|
||||
bitmap_copy(map, &map2);
|
||||
if (bitmap_bits_set(map) != bitsize)
|
||||
{
|
||||
diag("bitmap_copy failed on bitsize %d", bitsize);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static my_bool exec_bitmap_exists_intersection(MY_BITMAP **maps, uint bitsize,
|
||||
uint start, uint end, uint bit)
|
||||
{
|
||||
bitmap_clear_all(maps[0]);
|
||||
bitmap_clear_all(maps[1]);
|
||||
bitmap_set_bit(maps[0], bit);
|
||||
bitmap_set_bit(maps[1], bit);
|
||||
return bitmap_exists_intersection(maps, 2, start, end);
|
||||
}
|
||||
|
||||
my_bool test_bitmap_exists_intersection(MY_BITMAP *map, uint bitsize)
|
||||
{
|
||||
MY_BITMAP map2;
|
||||
uint start_bit, end_bit, rnd_bit;
|
||||
MY_BITMAP *maps[2];
|
||||
maps[0]= map;
|
||||
maps[1]= &map2;
|
||||
|
||||
my_bitmap_init(&map2, 0, bitsize, FALSE);
|
||||
bitmap_clear_all(map);
|
||||
bitmap_clear_all(&map2);
|
||||
|
||||
start_bit= get_rand_bit(bitsize);
|
||||
end_bit= get_rand_bit(bitsize);
|
||||
if (start_bit > end_bit)
|
||||
swap_variables(uint, start_bit, end_bit);
|
||||
rnd_bit= start_bit+get_rand_bit(end_bit-start_bit);
|
||||
|
||||
if (!exec_bitmap_exists_intersection(maps, bitsize, start_bit, end_bit,
|
||||
rnd_bit))
|
||||
goto err;
|
||||
|
||||
start_bit= end_bit= rnd_bit= 0;
|
||||
if (!exec_bitmap_exists_intersection(maps, bitsize, start_bit, end_bit,
|
||||
rnd_bit))
|
||||
goto err;
|
||||
|
||||
start_bit= rnd_bit= 0 ; end_bit= bitsize-1;
|
||||
if (!exec_bitmap_exists_intersection(maps, bitsize, start_bit, end_bit,
|
||||
rnd_bit))
|
||||
goto err;
|
||||
|
||||
start_bit= rnd_bit= end_bit= bitsize-1;
|
||||
if (!exec_bitmap_exists_intersection(maps, bitsize, start_bit, end_bit,
|
||||
rnd_bit))
|
||||
goto err;
|
||||
|
||||
if (bitsize > 1)
|
||||
{
|
||||
start_bit= end_bit= 1 ; rnd_bit= 0;
|
||||
if (exec_bitmap_exists_intersection(maps, bitsize, start_bit, end_bit,
|
||||
rnd_bit))
|
||||
goto err;
|
||||
|
||||
start_bit= end_bit= bitsize-1 ; rnd_bit= bitsize-2;
|
||||
if (exec_bitmap_exists_intersection(maps, bitsize, start_bit, end_bit,
|
||||
rnd_bit))
|
||||
goto err;
|
||||
}
|
||||
|
||||
my_bitmap_free(&map2);
|
||||
return 0;
|
||||
err:
|
||||
diag("bitmap_exist_intersection failed on bitsize: %d start_bit: %d "
|
||||
"end_bit: %d rnd_bit: %d",
|
||||
bitsize, start_bit, end_bit, rnd_bit);
|
||||
my_bitmap_free(&map2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
my_bool do_test(uint bitsize)
|
||||
{
|
||||
MY_BITMAP map;
|
||||
@ -515,6 +636,11 @@ my_bool do_test(uint bitsize)
|
||||
bitmap_clear_all(&map);
|
||||
if (test_intersect(&map,bitsize))
|
||||
goto error;
|
||||
bitmap_clear_all(&map);
|
||||
if (test_copy(&map,bitsize))
|
||||
goto error;
|
||||
if (test_bitmap_exists_intersection(&map, bitsize))
|
||||
goto error;
|
||||
return FALSE;
|
||||
error:
|
||||
return TRUE;
|
||||
|
Loading…
x
Reference in New Issue
Block a user