diff --git a/ndb/include/util/Bitmask.hpp b/ndb/include/util/Bitmask.hpp index b6bc6e3d5e3..2cd95190ed7 100644 --- a/ndb/include/util/Bitmask.hpp +++ b/ndb/include/util/Bitmask.hpp @@ -811,36 +811,45 @@ public: }; inline void -BitmaskImpl::getField(unsigned size, const Uint32 data[], +BitmaskImpl::getField(unsigned size, const Uint32 src[], unsigned pos, unsigned len, Uint32 dst[]) { assert(len > 0); assert(pos + len < (size << 5)); - Uint32 word = pos >> 5; + + src += (pos >> 5); Uint32 offset = pos & 31; + dst[0] = (* src >> offset) & (len >= 32 ? ~0 : (1 << len) - 1); + if(offset + len <= 32) { - dst[0] = (data[word] >> offset) & ((1 << len) - 1); return; } - getFieldImpl(data, pos, len, dst); + Uint32 used = (32 - offset); + assert(len > used); + getFieldImpl(src+1, used & 31, len-used, dst+(used >> 5)); } inline void -BitmaskImpl::setField(unsigned size, Uint32 data[], +BitmaskImpl::setField(unsigned size, Uint32 dst[], unsigned pos, unsigned len, const Uint32 src[]) { assert(len > 0); assert(pos + len < (size << 5)); - Uint32 word = pos >> 5; + + dst += (pos >> 5); Uint32 offset = pos & 31; - Uint32 mask = ((1 << len) - 1) << offset; - data[word] = (data[word] & ~mask) | ((src[0] << offset) & mask); + Uint32 mask = (len >= 32 ? ~0 : (1 << len) - 1) << offset; + + * dst = (* dst & ~mask) | ((*src << offset) & mask); + if(offset + len <= 32) { return; } - setFieldImpl(data, pos, len, src); + Uint32 used = (32 - offset); + assert(len > used); + setFieldImpl(dst+1, used & 31, len-used, src+(used >> 5)); } diff --git a/ndb/src/common/util/Bitmask.cpp b/ndb/src/common/util/Bitmask.cpp index 536620ce305..eecde77aad3 100644 --- a/ndb/src/common/util/Bitmask.cpp +++ b/ndb/src/common/util/Bitmask.cpp @@ -1,69 +1,59 @@ #include #include -#ifndef __TEST_BITMASK__ -void -BitmaskImpl::getFieldImpl(const Uint32 data[], - unsigned pos, unsigned l, Uint32 dst[]) +static +void print(const Uint32 src[], Uint32 len, Uint32 pos = 0) { - Uint32 word; - Uint32 offset; - int next_offset,i; - int len= l; - for(i=0,next_offset=0;len >0;i++) + printf("b'"); + for(int i = 0; i> 5; - offset = pos & 31; - - if(i%32==0) - dst[i/32]=0; - - if(!next_offset && (offset+len) > 32) - { - dst[i/32] = (data[word] >> offset) & ((1 << (32-offset)) - 1); - next_offset = 32-offset; - } + if(BitmaskImpl::get((pos + len + 31) >> 5, src, i+pos)) + printf("1"); else - { - dst[i/32]|= ((data[word] >> offset) & ((1 << len) - 1)) << next_offset; - next_offset = 0; - } - - if(len < 32-offset) - break; - - len-=32-offset; - pos+=32-offset; + printf("0"); + if((i & 7) == 7) + printf(" "); } } - -void -BitmaskImpl::setFieldImpl(Uint32 data[], - unsigned pos, unsigned l, const Uint32 src[]) -{ - Uint32 word; - Uint32 offset; - Uint32 mask; - int i=0,stored=0; - int len= l; - while(len>0) +#ifndef __TEST_BITMASK__ +void +BitmaskImpl::getFieldImpl(const Uint32 src[], + unsigned shift, unsigned len, Uint32 dst[]) +{ + assert(shift < 32); + + if(len <= (32 - shift)) { - ndbout_c("len: %d", len); - word = pos >> 5; - offset = pos & 31; - - if(offset+len > 32) - stored = 32-offset; - else - stored = len; - - mask = ((1 << stored) - 1) << (i+offset)%32; - data[word] = (data[word] & ~mask) | ((src[i/32] << (i+offset)%32) & mask); - - i+=stored; - len-=32-offset; - pos+=32-offset; + * dst++ |= ((* src) & ((1 << len) - 1)) << shift; + } + else + { + abort(); + while(len > 32) + { + * dst++ |= (* src) << shift; + * dst = (* src++) >> (32 - shift); + len -= 32; + } + } +} + +void +BitmaskImpl::setFieldImpl(Uint32 dst[], + unsigned shift, unsigned len, const Uint32 src[]) +{ + assert(shift < 32); + + Uint32 mask; + if(len < (32 - shift)) + { + mask = (1 << len) - 1; + * dst = (* dst & ~mask) | (((* src++) >> shift) & mask); + } + else + { + abort(); } } @@ -71,7 +61,7 @@ BitmaskImpl::setFieldImpl(Uint32 data[], #define DEBUG 0 #include -void do_test(int bitmask_size); +static void do_test(int bitmask_size); int main(int argc, char** argv) @@ -91,30 +81,86 @@ struct Alloc Vector data; }; -void require(bool b) +static void require(bool b) { if(!b) abort(); } -void +static int val_pos = 0; +static int val[] = { 384, 241, 32, + 1,1,1,1, 0,0,0,0, 1,1,1,1, 0,0,0,0, + 241 }; + +static int lrand() +{ +#if 0 + return val[val_pos++]; +#else + return rand(); +#endif +} + +static +void rand(Uint32 dst[], Uint32 len) +{ + for(int i = 0; i> 5, dst, i, (lrand() % 1000) > 500); +} + +static +void simple(int pos, int size) +{ + ndbout_c("simple pos: %d size: %d", pos, size); + Vector _mask; + Vector _src; + Vector _dst; + Uint32 sz32 = (size + pos + 32) >> 5; + const Uint32 sz = 4 * sz32; + + Uint32 zero = 0; + _mask.fill(sz32, zero); + _src.fill(sz32, zero); + _dst.fill(sz32, zero); + + Uint32 * src = _src.getBase(); + Uint32 * dst = _dst.getBase(); + Uint32 * mask = _mask.getBase(); + + memset(src, 0x0, sz); + memset(dst, 0x0, sz); + memset(mask, 0x0, sz); + rand(src, size); + BitmaskImpl::setField(sz32, mask, pos, size, src); + BitmaskImpl::getField(sz32, mask, pos, size, dst); + printf("src: "); print(src, size); printf("\n"); + printf("msk: "); print(mask, size, pos); printf("\n"); + printf("dst: "); print(dst, size); printf("\n"); + require(memcmp(src, dst, sz) == 0); +}; + +static void do_test(int bitmask_size) { +#if 0 + simple(rand() % 33, (rand() % 31)+1); +#else Vector alloc_list; bitmask_size = (bitmask_size + 31) & ~31; Uint32 sz32 = (bitmask_size >> 5); Vector alloc_mask; Vector test_mask; - Vector tmp; ndbout_c("Testing bitmask of size %d", bitmask_size); Uint32 zero = 0; alloc_mask.fill(sz32, zero); test_mask.fill(sz32, zero); - tmp.fill(sz32, zero); - for(int i = 0; i<1000; i++) + for(int i = 0; i<5000; i++) { - int pos = rand() % (bitmask_size - 1); + Vector tmp; + tmp.fill(sz32, zero); + + int pos = lrand() % (bitmask_size - 1); int free = 0; if(BitmaskImpl::get(sz32, alloc_mask.getBase(), pos)) { @@ -133,26 +179,26 @@ do_test(int bitmask_size) break; } } - if(DEBUG) - ndbout_c("freeing [ %d %d ]", min, max); - require(pos >= min && pos < max); BitmaskImpl::getField(sz32, test_mask.getBase(), min, max-min, tmp.getBase()); - if(memcmp(tmp.getBase(), alloc_list[j].data.getBase(), - ((max - min) + 31) >> 5) != 0) + if(DEBUG) { - printf("mask: "); + printf("freeing [ %d %d ]", min, max); + printf("- mask: "); + for(size_t k = 0; k<(((max - min)+31)>>5); k++) + printf("%.8x ", tmp.getBase()[k]); + + printf("save: "); size_t k; Alloc& a = alloc_list[j]; for(k = 0; k>5); k++) - printf("%.8x ", tmp.getBase()[k]); - printf("\n"); + } + int bytes = (max - min + 7) >> 3; + if(memcmp(tmp.getBase(), alloc_list[j].data.getBase(), bytes) != 0) + { abort(); } while(min < max) @@ -161,31 +207,36 @@ do_test(int bitmask_size) } else { + Vector tmp; + tmp.fill(sz32, zero); + // Bit was free // 1) Check how much space is avaiable - // 2) Create new allocation of random size - // 3) Fill data with random data + // 2) Create new allocation of lrandom size + // 3) Fill data with lrandom data // 4) Update alloc mask while(pos+free < bitmask_size && !BitmaskImpl::get(sz32, alloc_mask.getBase(), pos+free)) free++; - Uint32 sz = (rand() % free); sz = sz ? sz : 1; + Uint32 sz = (lrand() % free); + sz = sz ? sz : 1; + sz = (sz > 31) ? 31 : sz; Alloc a; a.pos = pos; a.size = sz; - a.data.fill(sz >> 5, zero); + a.data.fill(((sz+31)>> 5)-1, zero); if(DEBUG) - ndbout_c("pos %d -> alloc [ %d %d ]", pos, pos, pos+sz); + printf("pos %d -> alloc [ %d %d ]", pos, pos, pos+sz); for(size_t j = 0; j 500) + if((lrand() % 1000) > 500) BitmaskImpl::set((sz + 31) >> 5, a.data.getBase(), j); } if(DEBUG) { - printf("mask: "); + printf("- mask: "); size_t k; for(k = 0; k;