Commit 07735208 authored by unknown's avatar unknown

ndb - bitfields - more tests, now passes all api tests!!


ndb/include/kernel/ndb_limits.h:
  #define for max null bits
ndb/include/kernel/signaldata/TupFrag.hpp:
  Error code for too many nullbits
ndb/include/util/Bitmask.hpp:
  Cosmetic fix
ndb/src/common/util/Bitmask.cpp:
  handle (pos % 32) == 0
  more unit tests
ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp:
  Check bitmask overflow
ndb/src/ndbapi/ndberror.c:
  New error code
ndb/test/ndbapi/testBitfield.cpp:
  Update test program
ndb/test/run-test/daily-basic-tests.txt:
  Add testBitfield to autotest
parent d4076cec
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
#define MAX_FIXED_KEY_LENGTH_IN_WORDS 8 #define MAX_FIXED_KEY_LENGTH_IN_WORDS 8
#define MAX_KEY_SIZE_IN_WORDS 1023 #define MAX_KEY_SIZE_IN_WORDS 1023
#define MAX_FRM_DATA_SIZE 6000 #define MAX_FRM_DATA_SIZE 6000
#define MAX_NULL_BITS 4096
#define MIN_ATTRBUF ((MAX_ATTRIBUTES_IN_TABLE/24) + 1) #define MIN_ATTRBUF ((MAX_ATTRIBUTES_IN_TABLE/24) + 1)
/* /*
......
...@@ -145,7 +145,8 @@ public: ...@@ -145,7 +145,8 @@ public:
STATIC_CONST( SignalLength = 2 ); STATIC_CONST( SignalLength = 2 );
enum ErrorCode { enum ErrorCode {
NoError = 0, NoError = 0,
InvalidCharset = 743 InvalidCharset = 743,
TooManyBitsUsed = 831
}; };
private: private:
Uint32 userPtr; Uint32 userPtr;
......
...@@ -818,7 +818,7 @@ BitmaskImpl::getField(unsigned size, const Uint32 src[], ...@@ -818,7 +818,7 @@ BitmaskImpl::getField(unsigned size, const Uint32 src[],
src += (pos >> 5); src += (pos >> 5);
Uint32 offset = pos & 31; Uint32 offset = pos & 31;
dst[0] = (* src >> offset) & (len >= 32 ? ~0 : (1 << len) - 1); * dst = (* src >> offset) & (len >= 32 ? ~0 : (1 << len) - 1);
if(offset + len <= 32) if(offset + len <= 32)
{ {
......
...@@ -23,9 +23,12 @@ BitmaskImpl::getFieldImpl(const Uint32 src[], ...@@ -23,9 +23,12 @@ BitmaskImpl::getFieldImpl(const Uint32 src[],
unsigned shiftL, unsigned len, Uint32 dst[]) unsigned shiftL, unsigned len, Uint32 dst[])
{ {
assert(shiftL < 32); assert(shiftL < 32);
unsigned shiftR = 32 - shiftL; unsigned shiftR = 32 - shiftL;
unsigned undefined = shiftL ? ~0 : 0; unsigned undefined = shiftL ? ~0 : 0;
* dst = shiftL ? * dst : 0;
while(len >= 32) while(len >= 32)
{ {
* dst++ |= (* src) << shiftL; * dst++ |= (* src) << shiftL;
...@@ -169,6 +172,69 @@ void simple(int pos, int size) ...@@ -169,6 +172,69 @@ void simple(int pos, int size)
require(cmp(src, dst, size+31)); require(cmp(src, dst, size+31));
}; };
static
void simple2(int size, int loops)
{
ndbout_c("simple2 %d - ", size);
Vector<Uint32> _mask;
Vector<Uint32> _src;
Vector<Uint32> _dst;
Uint32 sz32 = (size + 32) >> 5;
Uint32 sz = sz32 << 2;
Uint32 zero = 0;
_mask.fill(sz32+1, zero);
_src.fill(sz32+1, zero);
_dst.fill(sz32+1, zero);
Uint32 * src = _src.getBase();
Uint32 * dst = _dst.getBase();
Uint32 * mask = _mask.getBase();
Vector<Uint32> save;
for(int i = 0; i<loops; i++)
{
memset(mask, 0xFF, sz);
memset(dst, 0xFF, sz);
int len;
int pos = 0;
while(pos+1 < size)
{
memset(src, 0xFF, sz);
while(!(len = rand() % (size - pos)));
BitmaskImpl::setField(sz32, mask, pos, len, src);
if(memcmp(dst, mask, sz))
{
ndbout_c("pos: %d len: %d", pos, len);
print(mask, size);
abort();
}
printf("[ %d %d ]", pos, len);
save.push_back(pos);
save.push_back(len);
pos += len;
}
for(int j = 0; j<save.size(); )
{
pos = save[j++];
len = save[j++];
memset(src, 0xFF, sz);
BitmaskImpl::getField(sz32, mask, pos, len, src);
if(memcmp(dst, src, sz))
{
ndbout_c("pos: %d len: %d", pos, len);
printf("src: "); print(src, size); printf("\n");
printf("dst: "); print(dst, size); printf("\n");
printf("msk: "); print(mask, size); printf("\n");
abort();
}
}
ndbout_c("");
}
}
static void static void
do_test(int bitmask_size) do_test(int bitmask_size)
{ {
......
...@@ -311,6 +311,7 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal) ...@@ -311,6 +311,7 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
setTabDescrWord(firstTabDesIndex, attrDescriptor); setTabDescrWord(firstTabDesIndex, attrDescriptor);
Uint32 attrLen = AttributeDescriptor::getSize(attrDescriptor); Uint32 attrLen = AttributeDescriptor::getSize(attrDescriptor);
Uint32 nullBitPos = fragOperPtr.p->currNullBit; Uint32 nullBitPos = fragOperPtr.p->currNullBit;
Uint32 bitCount = 0;
if (AttributeDescriptor::getNullable(attrDescriptor)) { if (AttributeDescriptor::getNullable(attrDescriptor)) {
if (!AttributeDescriptor::getDynamic(attrDescriptor)) { if (!AttributeDescriptor::getDynamic(attrDescriptor)) {
...@@ -342,7 +343,7 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal) ...@@ -342,7 +343,7 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
else else
{ {
ljam(); ljam();
Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor); bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
fragOperPtr.p->currNullBit += bitCount; fragOperPtr.p->currNullBit += bitCount;
break; break;
} }
...@@ -351,6 +352,12 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal) ...@@ -351,6 +352,12 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
ndbrequire(false); ndbrequire(false);
break; break;
}//switch }//switch
if(nullBitPos + bitCount + 1 >= MAX_NULL_BITS)
{
terrorCode = TupAddAttrRef::TooManyBitsUsed;
addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
return;
}
AttributeOffset::setOffset(attrDes2, attributePos); AttributeOffset::setOffset(attrDes2, attributePos);
AttributeOffset::setNullFlagPos(attrDes2, nullBitPos); AttributeOffset::setNullFlagPos(attrDes2, nullBitPos);
} else { } else {
......
...@@ -259,6 +259,7 @@ ErrorBundle ErrorCodes[] = { ...@@ -259,6 +259,7 @@ ErrorBundle ErrorCodes[] = {
* Application error * Application error
*/ */
{ 823, AE, "Too much attrinfo from application in tuple manager" }, { 823, AE, "Too much attrinfo from application in tuple manager" },
{ 831, AE, "Too many nullable/bitfields in table definition" },
{ 876, AE, "876" }, { 876, AE, "876" },
{ 877, AE, "877" }, { 877, AE, "877" },
{ 878, AE, "878" }, { 878, AE, "878" },
...@@ -270,7 +271,7 @@ ErrorBundle ErrorCodes[] = { ...@@ -270,7 +271,7 @@ ErrorBundle ErrorCodes[] = {
{ 897, AE, "Update attempt of primary key via ndbcluster internal api (if this occurs via the MySQL server it is a bug, please report)" }, { 897, AE, "Update attempt of primary key via ndbcluster internal api (if this occurs via the MySQL server it is a bug, please report)" },
{ 4256, AE, "Must call Ndb::init() before this function" }, { 4256, AE, "Must call Ndb::init() before this function" },
{ 4257, AE, "Tried to read too much - too many getValue calls" }, { 4257, AE, "Tried to read too much - too many getValue calls" },
/** /**
* Scan application errors * Scan application errors
*/ */
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
static const char* opt_connect_str= 0; static const char* opt_connect_str= 0;
static const char* _dbname = "TEST_DB"; static const char* _dbname = "TEST_DB";
static int g_loops = 5; static int g_loops = 7;
static struct my_option my_long_options[] = static struct my_option my_long_options[] =
{ {
NDB_STD_OPTS("ndb_desc"), NDB_STD_OPTS("ndb_desc"),
...@@ -130,44 +130,48 @@ static ...@@ -130,44 +130,48 @@ static
const NdbDictionary::Table* const NdbDictionary::Table*
create_random_table(Ndb* pNdb) create_random_table(Ndb* pNdb)
{ {
NdbDictionary::Table tab; do {
Uint32 cols = 1 + (rand() % (NDB_MAX_ATTRIBUTES_IN_TABLE - 1)); NdbDictionary::Table tab;
Uint32 keys = NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY; Uint32 cols = 1 + (rand() % (NDB_MAX_ATTRIBUTES_IN_TABLE - 1));
Uint32 length = 4096; Uint32 keys = NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY;
Uint32 key_size = NDB_MAX_KEYSIZE_IN_WORDS; Uint32 length = 4090;
Uint32 key_size = NDB_MAX_KEYSIZE_IN_WORDS;
BaseString name;
name.assfmt("TAB_%d", rand() & 65535); BaseString name;
tab.setName(name.c_str()); name.assfmt("TAB_%d", rand() & 65535);
for(int i = 0; i<cols && length > 0; i++) tab.setName(name.c_str());
{ for(int i = 0; i<cols && length > 2; i++)
NdbDictionary::Column col;
name.assfmt("COL_%d", i);
col.setName(name.c_str());
if(i == 0 || i == 1)
{ {
col.setType(NdbDictionary::Column::Unsigned); NdbDictionary::Column col;
col.setLength(1); name.assfmt("COL_%d", i);
col.setNullable(false); col.setName(name.c_str());
col.setPrimaryKey(i == 0); if(i == 0 || i == 1)
{
col.setType(NdbDictionary::Column::Unsigned);
col.setLength(1);
col.setNullable(false);
col.setPrimaryKey(i == 0);
tab.addColumn(col);
continue;
}
col.setType(NdbDictionary::Column::Bit);
Uint32 len = 1 + (rand() % (length - 1));
col.setLength(len); length -= len;
int nullable = (rand() >> 16) & 1;
col.setNullable(nullable); length -= nullable;
col.setPrimaryKey(false);
tab.addColumn(col); tab.addColumn(col);
continue;
} }
col.setType(NdbDictionary::Column::Bit);
Uint32 len = 1 + (rand() % 128); //(length - 1)); pNdb->getDictionary()->dropTable(tab.getName());
col.setLength(len); length -= len; if(pNdb->getDictionary()->createTable(tab) == 0)
col.setNullable((rand() >> 16) & 1); {
col.setPrimaryKey(false); ndbout << (NDBT_Table&)tab << endl;
tab.addColumn(col); return pNdb->getDictionary()->getTable(tab.getName());
} }
} while(0);
ndbout << (NDBT_Table&)tab << endl;
if(pNdb->getDictionary()->createTable(tab) == 0)
{
return pNdb->getDictionary()->getTable(tab.getName());
}
return 0; return 0;
} }
......
...@@ -506,6 +506,10 @@ max-time: 2500 ...@@ -506,6 +506,10 @@ max-time: 2500
cmd: testOIBasic cmd: testOIBasic
args: args:
max-time: 2500
cmd: testBitfield
args:
# #
# #
# SYSTEM RESTARTS # SYSTEM RESTARTS
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment