2004-04-14 10:53:21 +02:00
|
|
|
/* Copyright (C) 2003 MySQL AB
|
|
|
|
|
|
|
|
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; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* testDataBuffers
|
|
|
|
*
|
|
|
|
* Test getValue() of byte arrays:
|
|
|
|
* - using application buffers of different alignments and sizes
|
|
|
|
* - using NdbApi allocated small (<32) and big (>=32) buffers
|
|
|
|
*
|
|
|
|
* Verifies fixes to tickets 189 and 206.
|
|
|
|
*
|
|
|
|
* Options: see printusage() below.
|
|
|
|
*
|
|
|
|
* Creates tables TB00 to TB15
|
|
|
|
*/
|
|
|
|
|
2004-05-07 08:39:42 +02:00
|
|
|
#include <ndb_global.h>
|
|
|
|
|
2004-04-14 10:53:21 +02:00
|
|
|
#include <NdbMain.h>
|
|
|
|
#include <NdbOut.hpp>
|
|
|
|
#include <NdbApi.hpp>
|
|
|
|
#include <NdbTest.hpp>
|
2004-05-25 11:53:07 +02:00
|
|
|
#include <NdbSchemaCon.hpp>
|
2004-04-14 10:53:21 +02:00
|
|
|
// limits
|
|
|
|
static int const MaxAttr = 64;
|
|
|
|
static int const MaxOper = 1000;
|
|
|
|
static int const MaxSize = 10000;
|
|
|
|
static int const MaxOff = 64; // max offset to add to data buffer
|
|
|
|
static int const MaxData = MaxSize + MaxOff + 100;
|
|
|
|
|
|
|
|
// options
|
|
|
|
static int attrcnt = 25;
|
|
|
|
static int existok = 0;
|
|
|
|
static bool kontinue = false;
|
|
|
|
static int loopcnt = 1;
|
|
|
|
static int opercnt = 100; // also does this many scans
|
|
|
|
static int randomizer = 171317;
|
|
|
|
static int sizelim = 500;
|
|
|
|
static int xverbose = 0;
|
|
|
|
|
|
|
|
static void printusage() {
|
|
|
|
ndbout
|
|
|
|
<< "usage: testDataBuffers options [default/max]"
|
|
|
|
<< endl
|
|
|
|
<< "NOTE: too large combinations result in NDB error"
|
|
|
|
<< endl
|
|
|
|
<< "-a N number of attributes (including the key) [25/64]"
|
|
|
|
<< endl
|
|
|
|
<< "-e no error if table exists (assumed to have same structure)"
|
|
|
|
<< endl
|
|
|
|
<< "-k on error continue with next test case"
|
|
|
|
<< endl
|
|
|
|
<< "-l N number of loops to run, 0 means infinite [1]"
|
|
|
|
<< endl
|
|
|
|
<< "-o N number of operations (rows in each table) [100/1000]"
|
|
|
|
<< endl
|
|
|
|
<< "-r N source of randomness (big number (prime)) [171317]"
|
|
|
|
<< endl
|
|
|
|
<< "-s N array size limit (rounded up in some tests) [500/10000]"
|
|
|
|
<< endl
|
|
|
|
<< "-x extremely verbose"
|
|
|
|
<< endl
|
|
|
|
<< "Tables: TB00 .. TB15"
|
|
|
|
<< endl
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Ndb* ndb = 0;
|
|
|
|
static NdbSchemaCon* tcon = 0;
|
|
|
|
static NdbSchemaOp* top = 0;
|
|
|
|
static NdbConnection* con = 0;
|
|
|
|
static NdbOperation* op = 0;
|
2004-05-26 13:24:14 +02:00
|
|
|
static NdbScanOperation* sop = 0;
|
|
|
|
static NdbResultSet* rs = 0;
|
2004-04-14 10:53:21 +02:00
|
|
|
|
|
|
|
static int
|
|
|
|
ndberror(char const* fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
char buf[200];
|
|
|
|
va_start(ap, fmt);
|
|
|
|
vsnprintf(buf, sizeof(buf), fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
ndbout << buf << " --" << endl;
|
|
|
|
if (ndb)
|
|
|
|
ndbout << "ndb : " << ndb->getNdbError() << endl;
|
|
|
|
if (tcon)
|
|
|
|
ndbout << "tcon: " << tcon->getNdbError() << endl;
|
|
|
|
if (top)
|
2004-05-25 11:53:07 +02:00
|
|
|
ndbout << "top: " << top->getNdbError() << endl;
|
2004-04-14 10:53:21 +02:00
|
|
|
if (con)
|
|
|
|
ndbout << "con : " << con->getNdbError() << endl;
|
|
|
|
if (op)
|
|
|
|
ndbout << "op : " << op->getNdbError() << endl;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
chkerror(char const* fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
char buf[200];
|
|
|
|
va_start(ap, fmt);
|
|
|
|
vsnprintf(buf, sizeof(buf), fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
ndbout << "*** check failed: " << buf << " ***" << endl;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// alignment of addresses and data sizes
|
|
|
|
|
|
|
|
static bool isAligned(unsigned x)
|
|
|
|
{
|
|
|
|
return ((x & 3) == 0);
|
|
|
|
}
|
|
|
|
static bool isAligned(char* p)
|
|
|
|
{
|
|
|
|
return isAligned(unsigned(p));
|
|
|
|
}
|
|
|
|
static unsigned toAligned(unsigned x)
|
|
|
|
{
|
|
|
|
while (! isAligned(x))
|
|
|
|
x++;
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
static char* toAligned(char* p)
|
|
|
|
{
|
|
|
|
while (! isAligned(p))
|
|
|
|
p++;
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
// byte value for key k column i byte j
|
|
|
|
static int byteVal(int k, int i, int j)
|
|
|
|
{
|
|
|
|
return '0' + (k + i + j) % 10;
|
|
|
|
}
|
|
|
|
|
|
|
|
// tables
|
|
|
|
|
|
|
|
static char tab[20] = "";
|
|
|
|
|
|
|
|
static struct col {
|
|
|
|
char aAttrName[20];
|
|
|
|
AttrType aAttrType;
|
|
|
|
int aAttrSize;
|
|
|
|
int aArraySize;
|
|
|
|
KeyType aTupleKey;
|
|
|
|
bool nullable;
|
|
|
|
NdbRecAttr* aRa;
|
|
|
|
char* buf;
|
|
|
|
int bufsiz;
|
|
|
|
char data[MaxData];
|
|
|
|
} ccol[MaxAttr];
|
|
|
|
|
|
|
|
static int key = 0;
|
|
|
|
|
|
|
|
// independent test bits
|
|
|
|
static bool alignAddr; // align our buffer addresses to 4x
|
|
|
|
static bool alignSize; // align data sizes to 4x
|
|
|
|
static bool useBuf; // use our buffers for output
|
|
|
|
static bool noRandom; // do not randomize sizes and offsets
|
|
|
|
static int testbits = 4;
|
|
|
|
|
|
|
|
static int
|
|
|
|
makeSize(int i)
|
|
|
|
{
|
|
|
|
int n;
|
|
|
|
if (noRandom)
|
|
|
|
n = i;
|
|
|
|
else
|
|
|
|
n = i * randomizer;
|
|
|
|
n %= sizelim;
|
|
|
|
if (n <= 0)
|
|
|
|
n = 1;
|
|
|
|
if (alignSize)
|
|
|
|
n = toAligned(n);
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
makeOff(int k)
|
|
|
|
{
|
|
|
|
int n;
|
|
|
|
if (alignAddr)
|
|
|
|
n = 0;
|
|
|
|
else if (noRandom)
|
|
|
|
n = k;
|
|
|
|
else
|
|
|
|
n = k * randomizer;
|
|
|
|
n %= MaxOff;
|
|
|
|
if (n < 0)
|
|
|
|
n = -n;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
testcase(int flag)
|
|
|
|
{
|
|
|
|
ndbout << "--- case " << flag << " ---" << endl;
|
|
|
|
sprintf(tab, "TB%02d", flag);
|
|
|
|
|
|
|
|
alignAddr = ! (flag & 1);
|
|
|
|
ndbout << (alignAddr ? "align addresses" : "mis-align addresses") << endl;
|
|
|
|
alignSize = ! (flag & 2);
|
|
|
|
ndbout << (alignSize ? "align data sizes" : "mis-align data sizes") << endl;
|
|
|
|
useBuf = ! (flag & 4);
|
|
|
|
ndbout << (useBuf ? "use our buffers" : "use ndbapi buffers") << endl;
|
|
|
|
noRandom = ! (flag & 8);
|
|
|
|
ndbout << (noRandom ? "simple sizes" : "randomize sizes") << endl;
|
|
|
|
|
|
|
|
int smax = 0, stot = 0;
|
|
|
|
if (xverbose)
|
|
|
|
ndbout << "- define table " << tab << endl;
|
|
|
|
for (int i = 0; i < attrcnt; i++) {
|
|
|
|
col& c = ccol[i];
|
|
|
|
memset(&c, 0, sizeof(c));
|
|
|
|
sprintf(c.aAttrName, "C%d", i);
|
|
|
|
if (i == 0) {
|
|
|
|
c.aAttrType = UnSigned;
|
|
|
|
c.aAttrSize = 32;
|
|
|
|
c.aArraySize = 1;
|
|
|
|
c.aTupleKey = TupleKey;
|
|
|
|
c.nullable = false;
|
|
|
|
} else {
|
|
|
|
c.aAttrType = String;
|
|
|
|
c.aAttrSize = 8;
|
|
|
|
c.aArraySize = makeSize(i);
|
|
|
|
if (smax < c.aArraySize)
|
|
|
|
smax = c.aArraySize;
|
|
|
|
stot += c.aArraySize;
|
|
|
|
c.aTupleKey = NoKey;
|
|
|
|
c.nullable = true;
|
|
|
|
if (xverbose)
|
|
|
|
ndbout << "-- column " << i << " size=" << c.aArraySize << endl;
|
|
|
|
}
|
|
|
|
c.buf = toAligned(c.data);
|
|
|
|
c.bufsiz = sizeof(c.data) - (c.buf - c.data);
|
|
|
|
}
|
|
|
|
ndbout << "tab=" << tab << " cols=" << attrcnt
|
|
|
|
<< " size max=" << smax << " tot=" << stot << endl;
|
|
|
|
|
|
|
|
ndb = new Ndb("TEST_DB");
|
|
|
|
if (ndb->init() != 0)
|
|
|
|
return ndberror("init");
|
|
|
|
if (ndb->waitUntilReady(30) < 0)
|
|
|
|
return ndberror("waitUntilReady");
|
|
|
|
|
2004-05-25 11:53:07 +02:00
|
|
|
if ((tcon = NdbSchemaCon::startSchemaTrans(ndb)) == 0)
|
2004-04-14 10:53:21 +02:00
|
|
|
return ndberror("startSchemaTransaction");
|
|
|
|
if ((top = tcon->getNdbSchemaOp()) == 0)
|
|
|
|
return ndberror("getNdbSchemaOp");
|
|
|
|
if (top->createTable(tab) < 0)
|
|
|
|
return ndberror("createTable");
|
|
|
|
for (int i = 0; i < attrcnt; i++) {
|
|
|
|
col& c = ccol[i];
|
|
|
|
if (top->createAttribute(
|
|
|
|
c.aAttrName,
|
|
|
|
c.aTupleKey,
|
|
|
|
c.aAttrSize,
|
|
|
|
c.aArraySize,
|
|
|
|
c.aAttrType,
|
|
|
|
MMBased,
|
|
|
|
c.nullable
|
|
|
|
) < 0)
|
|
|
|
return ndberror("createAttribute col=%d", i);
|
|
|
|
}
|
|
|
|
if (tcon->execute() < 0) {
|
|
|
|
if (! (tcon->getNdbError().code == 721 && existok))
|
|
|
|
return ndberror("execute");
|
|
|
|
ndbout << "using " << tab << endl;
|
|
|
|
} else {
|
|
|
|
ndbout << "created " << tab << endl;
|
|
|
|
}
|
|
|
|
top = 0;
|
|
|
|
tcon = 0;
|
|
|
|
|
|
|
|
if (xverbose)
|
|
|
|
ndbout << "- delete" << endl;
|
|
|
|
int delcnt = 0;
|
|
|
|
for (key = 0; key < opercnt; key++) {
|
|
|
|
if ((con = ndb->startTransaction()) == 0)
|
|
|
|
return ndberror("startTransaction key=%d", key);
|
|
|
|
if ((op = con->getNdbOperation(tab)) == 0)
|
|
|
|
return ndberror("getNdbOperation key=%d", key);
|
|
|
|
if (op->deleteTuple() < 0)
|
|
|
|
return ndberror("deleteTuple key=%d", key);
|
|
|
|
for (int i = 0; i < attrcnt; i++) {
|
|
|
|
col& c = ccol[i];
|
|
|
|
if (i == 0) {
|
|
|
|
if (op->equal(c.aAttrName, (char*)&key, sizeof(key)) < 0)
|
|
|
|
return ndberror("equal key=%d", key);
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (con->execute(Commit) < 0) {
|
|
|
|
if (con->getNdbError().code != 626)
|
|
|
|
return ndberror("execute key=%d", key);
|
|
|
|
} else {
|
|
|
|
delcnt++;
|
|
|
|
}
|
|
|
|
ndb->closeTransaction(con);
|
|
|
|
}
|
|
|
|
con = 0;
|
|
|
|
op = 0;
|
|
|
|
ndbout << "deleted " << delcnt << endl;
|
|
|
|
|
|
|
|
if (xverbose)
|
|
|
|
ndbout << "- insert" << endl;
|
|
|
|
for (key = 0; key < opercnt; key++) {
|
|
|
|
int off = makeOff(key);
|
|
|
|
if ((con = ndb->startTransaction()) == 0)
|
|
|
|
return ndberror("startTransaction key=%d", key);
|
|
|
|
if ((op = con->getNdbOperation(tab)) == 0)
|
|
|
|
return ndberror("getNdbOperation key=%d", key);
|
|
|
|
if (op->insertTuple() < 0)
|
|
|
|
return ndberror("insertTuple key=%d", key);
|
|
|
|
for (int i = 0; i < attrcnt; i++) {
|
|
|
|
col& c = ccol[i];
|
|
|
|
if (i == 0) {
|
|
|
|
if (op->equal(c.aAttrName, (char*)&key, sizeof(key)) < 0)
|
|
|
|
return ndberror("equal key=%d", key);
|
|
|
|
} else {
|
|
|
|
memset(c.buf, 'A', c.bufsiz);
|
|
|
|
for (int j = 0; j < c.aArraySize; j++)
|
|
|
|
c.buf[j + off] = byteVal(key, i, j);
|
|
|
|
if (op->setValue(c.aAttrName, c.buf + off, c.aArraySize) < 0)
|
|
|
|
return ndberror("setValue key=%d col=%d", key, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (con->execute(Commit) < 0)
|
|
|
|
return ndberror("execute key=%d", key);
|
|
|
|
ndb->closeTransaction(con);
|
|
|
|
}
|
|
|
|
con = 0;
|
|
|
|
op = 0;
|
|
|
|
ndbout << "inserted " << key << endl;
|
|
|
|
|
|
|
|
if (xverbose)
|
|
|
|
ndbout << "- select" << endl;
|
|
|
|
for (key = 0; key < opercnt; key++) {
|
|
|
|
int off = makeOff(key);
|
|
|
|
if (xverbose)
|
|
|
|
ndbout << "-- key " << key << " off=" << off << endl;
|
|
|
|
if ((con = ndb->startTransaction()) == 0)
|
|
|
|
return ndberror("startTransaction key=%d", key);
|
|
|
|
if ((op = con->getNdbOperation(tab)) == 0)
|
|
|
|
return ndberror("getNdbOperation key=%d", key);
|
|
|
|
if (op->readTuple() < 0)
|
|
|
|
return ndberror("readTuple key=%d", key);
|
|
|
|
for (int i = 0; i < attrcnt; i++) {
|
|
|
|
col& c = ccol[i];
|
|
|
|
if (i == 0) {
|
|
|
|
if (op->equal(c.aAttrName, (char*)&key, sizeof(key)) < 0)
|
|
|
|
return ndberror("equal key=%d", key);
|
|
|
|
} else {
|
|
|
|
if (xverbose) {
|
|
|
|
char tmp[20];
|
|
|
|
if (useBuf)
|
|
|
|
sprintf(tmp, "0x%x", int(c.buf + off));
|
|
|
|
else
|
|
|
|
strcpy(tmp, "ndbapi");
|
|
|
|
ndbout << "--- column " << i << " addr=" << tmp << endl;
|
|
|
|
}
|
|
|
|
memset(c.buf, 'B', c.bufsiz);
|
|
|
|
if (useBuf) {
|
|
|
|
if (op->getValue(c.aAttrName, c.buf + off) < 0)
|
|
|
|
return ndberror("getValue key=%d col=%d", key, i);
|
|
|
|
} else {
|
|
|
|
if ((c.aRa = op->getValue(c.aAttrName)) == 0)
|
|
|
|
return ndberror("getValue key=%d col=%d", key, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (con->execute(Commit) != 0)
|
|
|
|
return ndberror("execute key=%d", key);
|
|
|
|
for (int i = 0; i < attrcnt; i++) {
|
|
|
|
col& c = ccol[i];
|
|
|
|
if (i == 0) {
|
|
|
|
} else if (useBuf) {
|
|
|
|
for (int j = 0; j < off; j++) {
|
|
|
|
if (c.buf[j] != 'B') {
|
|
|
|
return chkerror("mismatch before key=%d col=%d pos=%d ok=%02x bad=%02x",
|
|
|
|
key, i, j, 'B', c.buf[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int j = 0; j < c.aArraySize; j++) {
|
|
|
|
if (c.buf[j + off] != byteVal(key, i, j)) {
|
|
|
|
return chkerror("mismatch key=%d col=%d pos=%d ok=%02x bad=%02x",
|
|
|
|
key, i, j, byteVal(key, i, j), c.buf[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int j = c.aArraySize + off; j < c.bufsiz; j++) {
|
|
|
|
if (c.buf[j] != 'B') {
|
|
|
|
return chkerror("mismatch after key=%d col=%d pos=%d ok=%02x bad=%02x",
|
|
|
|
key, i, j, 'B', c.buf[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
char* buf = c.aRa->aRef();
|
|
|
|
if (buf == 0)
|
|
|
|
return ndberror("null aRef key=%d col%d", key, i);
|
|
|
|
for (int j = 0; j < c.aArraySize; j++) {
|
|
|
|
if (buf[j] != byteVal(key, i, j)) {
|
|
|
|
return chkerror("mismatch key=%d col=%d pos=%d ok=%02x bad=%02x",
|
|
|
|
key, i, j, byteVal(key, i, j), buf[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ndb->closeTransaction(con);
|
|
|
|
}
|
|
|
|
con = 0;
|
|
|
|
op = 0;
|
|
|
|
ndbout << "selected " << key << endl;
|
|
|
|
|
|
|
|
if (xverbose)
|
|
|
|
ndbout << "- scan" << endl;
|
|
|
|
char found[MaxOper];
|
|
|
|
for (int k = 0; k < opercnt; k++)
|
|
|
|
found[k] = 0;
|
|
|
|
for (key = 0; key < opercnt; key++) {
|
|
|
|
int off = makeOff(key);
|
|
|
|
if (xverbose)
|
|
|
|
ndbout << "-- key " << key << " off=" << off << endl;
|
|
|
|
int newkey = 0;
|
|
|
|
if ((con = ndb->startTransaction()) == 0)
|
|
|
|
return ndberror("startTransaction key=%d", key);
|
2004-06-17 23:42:17 +02:00
|
|
|
if ((op = sop = con->getNdbScanOperation(tab)) == 0)
|
2004-04-14 10:53:21 +02:00
|
|
|
return ndberror("getNdbOperation key=%d", key);
|
2004-05-26 13:24:14 +02:00
|
|
|
if ((rs = sop->readTuples(1)) == 0)
|
2004-04-14 10:53:21 +02:00
|
|
|
return ndberror("openScanRead key=%d", key);
|
|
|
|
{
|
|
|
|
col& c = ccol[0];
|
|
|
|
if (op->load_const_u32(1, key) < 0)
|
|
|
|
return ndberror("load_const_u32");
|
|
|
|
if (op->read_attr(c.aAttrName, 2) < 0)
|
|
|
|
return ndberror("read_attr");
|
|
|
|
if (op->branch_eq(1, 2, 0) < 0)
|
|
|
|
return ndberror("branch_eq");
|
|
|
|
if (op->interpret_exit_nok() < 0)
|
|
|
|
return ndberror("interpret_exit_nok");
|
|
|
|
if (op->def_label(0) < 0)
|
|
|
|
return ndberror("def_label");
|
|
|
|
if (op->interpret_exit_ok() < 0)
|
|
|
|
return ndberror("interpret_exit_ok");
|
|
|
|
}
|
|
|
|
for (int i = 0; i < attrcnt; i++) {
|
|
|
|
col& c = ccol[i];
|
|
|
|
if (i == 0) {
|
|
|
|
if (op->getValue(c.aAttrName, (char*)&newkey) < 0)
|
|
|
|
return ndberror("getValue key=%d col=%d", key, i);
|
|
|
|
} else {
|
|
|
|
if (xverbose) {
|
|
|
|
char tmp[20];
|
|
|
|
if (useBuf)
|
|
|
|
sprintf(tmp, "0x%x", int(c.buf + off));
|
|
|
|
else
|
|
|
|
strcpy(tmp, "ndbapi");
|
|
|
|
ndbout << "--- column " << i << " addr=" << tmp << endl;
|
|
|
|
}
|
|
|
|
memset(c.buf, 'C', c.bufsiz);
|
|
|
|
if (useBuf) {
|
|
|
|
if (op->getValue(c.aAttrName, c.buf + off) < 0)
|
|
|
|
return ndberror("getValue key=%d col=%d", key, i);
|
|
|
|
} else {
|
|
|
|
if ((c.aRa = op->getValue(c.aAttrName)) == 0)
|
|
|
|
return ndberror("getValue key=%d col=%d", key, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-05-26 13:24:14 +02:00
|
|
|
if (con->execute(NoCommit) < 0)
|
2004-04-14 10:53:21 +02:00
|
|
|
return ndberror("executeScan key=%d", key);
|
|
|
|
int ret, cnt = 0;
|
2004-05-26 13:24:14 +02:00
|
|
|
while ((ret = rs->nextResult()) == 0) {
|
2004-04-14 10:53:21 +02:00
|
|
|
if (key != newkey)
|
|
|
|
return ndberror("unexpected key=%d newkey=%d", key, newkey);
|
|
|
|
for (int i = 1; i < attrcnt; i++) {
|
|
|
|
col& c = ccol[i];
|
|
|
|
if (useBuf) {
|
|
|
|
for (int j = 0; j < off; j++) {
|
|
|
|
if (c.buf[j] != 'C') {
|
|
|
|
return chkerror("mismatch before key=%d col=%d pos=%d ok=%02x bad=%02x",
|
|
|
|
key, i, j, 'C', c.buf[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int j = 0; j < c.aArraySize; j++) {
|
|
|
|
if (c.buf[j + off] != byteVal(key, i, j)) {
|
|
|
|
return chkerror("mismatch key=%d col=%d pos=%d ok=%02x bad=%02x",
|
|
|
|
key, i, j, byteVal(key, i, j), c.buf[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (int j = c.aArraySize + off; j < c.bufsiz; j++) {
|
|
|
|
if (c.buf[j] != 'C') {
|
|
|
|
return chkerror("mismatch after key=%d col=%d pos=%d ok=%02x bad=%02x",
|
|
|
|
key, i, j, 'C', c.buf[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
char* buf = c.aRa->aRef();
|
|
|
|
if (buf == 0)
|
|
|
|
return ndberror("null aRef key=%d col%d", key, i);
|
|
|
|
for (int j = 0; j < c.aArraySize; j++) {
|
|
|
|
if (buf[j] != byteVal(key, i, j)) {
|
|
|
|
return chkerror("mismatch key=%d col=%d pos=%d ok=%02x bad=%02x",
|
|
|
|
key, i, j, byteVal(key, i, j), buf[j]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cnt++;
|
|
|
|
}
|
|
|
|
if (ret < 0)
|
|
|
|
return ndberror("nextScanResult key=%d", key);
|
|
|
|
if (cnt != 1)
|
|
|
|
return ndberror("scan key=%d found %d", key, cnt);
|
|
|
|
found[key] = 1;
|
|
|
|
ndb->closeTransaction(con);
|
|
|
|
}
|
|
|
|
con = 0;
|
|
|
|
op = 0;
|
|
|
|
for (int k = 0; k < opercnt; k++)
|
|
|
|
if (! found[k])
|
|
|
|
return ndberror("key %d not found", k);
|
|
|
|
ndbout << "scanned " << key << endl;
|
|
|
|
|
|
|
|
ndb = 0;
|
|
|
|
ndbout << "done" << endl;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
NDB_COMMAND(testDataBuffers, "testDataBuffers", "testDataBuffers", "testDataBuffers", 65535)
|
|
|
|
{
|
2004-09-15 11:49:18 +02:00
|
|
|
ndb_init();
|
2004-04-14 10:53:21 +02:00
|
|
|
while (++argv, --argc > 0) {
|
|
|
|
char const* p = argv[0];
|
|
|
|
if (*p++ != '-' || strlen(p) != 1)
|
|
|
|
goto wrongargs;
|
|
|
|
switch (*p) {
|
|
|
|
case 'a':
|
|
|
|
if (++argv, --argc > 0) {
|
|
|
|
attrcnt = atoi(argv[0]);
|
|
|
|
if (1 <= attrcnt && attrcnt <= MaxAttr)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
goto wrongargs;
|
|
|
|
case 'e':
|
|
|
|
existok = 1;
|
|
|
|
break;
|
|
|
|
case 'k':
|
|
|
|
kontinue = true;
|
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
if (++argv, --argc > 0) {
|
|
|
|
loopcnt = atoi(argv[0]);
|
|
|
|
if (0 <= loopcnt)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
goto wrongargs;
|
|
|
|
case 'o':
|
|
|
|
if (++argv, --argc > 0) {
|
|
|
|
opercnt = atoi(argv[0]);
|
|
|
|
if (0 <= opercnt && opercnt <= MaxOper)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
goto wrongargs;
|
|
|
|
case 'r':
|
|
|
|
if (++argv, --argc > 0) {
|
|
|
|
randomizer = atoi(argv[0]);
|
|
|
|
if (1 <= randomizer)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
goto wrongargs;
|
|
|
|
case 's':
|
|
|
|
if (++argv, --argc > 0) {
|
|
|
|
sizelim = atoi(argv[0]);
|
|
|
|
if (1 <= sizelim && sizelim <= MaxSize)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
goto wrongargs;
|
|
|
|
case 'x':
|
|
|
|
xverbose = 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
wrongargs:
|
|
|
|
printusage();
|
|
|
|
return NDBT_ProgramExit(NDBT_WRONGARGS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
unsigned ok = true;
|
|
|
|
for (int i = 1; 0 == loopcnt || i <= loopcnt; i++) {
|
|
|
|
ndbout << "=== loop " << i << " ===" << endl;
|
|
|
|
for (int flag = 0; flag < (1<<testbits); flag++) {
|
|
|
|
if (testcase(flag) < 0) {
|
|
|
|
ok = false;
|
|
|
|
if (! kontinue)
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
out:
|
|
|
|
return NDBT_ProgramExit(ok ? NDBT_OK : NDBT_FAILED);
|
|
|
|
}
|
|
|
|
|
|
|
|
// vim: set sw=4:
|