18 #include <ndb_global.h> 
   21 #include <NdbTest.hpp> 
   22 #include <ndb_version.h> 
   28 #if !defined(min) || !defined(max) 
   29 #define min(x, y) ((x) < (y) ? (x) : (y)) 
   30 #define max(x, y) ((x) > (y) ? (x) : (y)) 
   70   my_bool abort_on_error;
 
   77   my_bool no_implicit_nulls;
 
   78   my_bool no_missing_update;
 
   85   my_bool separate_events;
 
   91 static const uint g_maxpk = 1000;
 
   92 static const uint g_maxtab = 100;
 
   93 static const uint g_maxopstringpart = 100;
 
   94 static const char* g_opstringpart[g_maxopstringpart];
 
   95 static uint g_opstringparts = 0;
 
   96 static uint g_loop = 0;
 
   99 static Ndb* g_ndb = 0;
 
  105 static const uint g_charlen = 5;
 
  106 static const char* g_charval = 
"abcdefgh";
 
  107 static const char* g_csname = 
"latin1_swedish_ci";
 
  109 static uint g_blobinlinesize = 256;
 
  110 static uint g_blobpartsize = 2000;
 
  111 static const uint g_maxblobsize = 100000;
 
  119   uint r = (uint)ndb_rand();
 
  134 urandom(uint per, uint cent)
 
  136   return urandom(cent) < per;
 
  139 static int& g_loglevel = g_opts.loglevel; 
 
  142   do { if (x) break; ndbout << "line " << __LINE__ << " FAIL " << #x << endl; errdb(); if (g_opts.abort_on_error) abort(); return -1; } while (0) 
  145   do { if (x) break; ndbout << "line " << __LINE__ << " FAIL " << #x << endl; if (g_opts.abort_on_error) abort(); return -1; } while (0) 
  148   do { if (x) break; ndbout << "line " << __LINE__ << " ASSERT " << #x << endl; abort(); } while (0) 
  151   do { if (g_loglevel < 0) break; ndbout << x << endl; } while (0) 
  154   do { if (g_loglevel < 1) break; ndbout << x << endl; } while (0) 
  157   do { if (g_loglevel < 2) break; ndbout << x << endl; } while (0) 
  160   do { if (g_loglevel < 3) break; ndbout << x << endl; } while (0) 
  170       ll0(++any << 
" ndb: error " << e);
 
  175       ll0(++any << 
" dic: error " << e);
 
  180       ll0(++any << 
" con: error " << e);
 
  185       ll0(++any << 
" op: error " << e);
 
  187   if (g_scan_op != 0) {
 
  190       ll0(++any << 
" scan_op: error " << e);
 
  195       ll0(++any << 
" evt_op: error " << e);
 
  200       ll0(++any << 
" bh: error " << e);
 
  203     ll0(
"unknown db error");
 
  217   bool isblob()
 const {
 
  225 static const Col g_col[] = {
 
  228        g_charlen, 1 + g_charlen, 0, 0, 0  },
 
  237        g_charlen, g_charlen, 0, 0, 0  },
 
  240        0, 0, g_blobinlinesize, g_blobpartsize, 0 }, 
 
  243        0, 0, g_blobinlinesize, g_blobpartsize, 4 },
 
  246        0, 0, g_blobinlinesize, 0, 0 }
 
  249 static const uint g_maxcol = 
sizeof(g_col)/
sizeof(g_col[0]);
 
  250 static const uint g_blobcols = 3;
 
  258   else if (g_opts.one_blob)
 
  259     n -= (g_blobcols - 2);
 
  273 getcol(
const char* 
name)
 
  276   for (i = 0; i < ncol(); i++)
 
  277     if (strcmp(g_col[i].name, name) == 0)
 
  293     sprintf(tabname, 
"tem%d", idx);
 
  294     sprintf(evtname, 
"tem%dev", idx);
 
  298 static Tab* g_tablst[g_maxtab];
 
  303   return g_opts.maxtab;
 
  309   assert(i < maxtab() && g_tablst[i] != 0);
 
  316   ll2(
"createtable: " << t.tabname);
 
  319   tab.setLogging(
false);
 
  321   chkrc((cs = get_charset_by_name(g_csname, MYF(0))) != 0);
 
  323   for (i = 0; i < ncol(); i++) {
 
  324     const Col& c = t.col[
i];
 
  327     col.setPrimaryKey(c.pk);
 
  328     col.setNullable(c.nullable);
 
  334       col.setLength(c.length);
 
  338       col.setBlobVersion(g_opts.blob_version);
 
  339       col.setInlineSize(c.inlinesize);
 
  340       col.setPartSize(c.partsize);
 
  341       col.setStripeSize(g_opts.blob_version == 1 ? 4 : c.stripesize);
 
  345       col.setBlobVersion(g_opts.blob_version);
 
  346       col.setInlineSize(c.inlinesize);
 
  347       col.setPartSize(c.partsize);
 
  348       col.setStripeSize(g_opts.blob_version == 1 ? 4 : c.stripesize);
 
  357   if (! g_opts.use_table) {
 
  358     if (g_dic->
getTable(t.tabname) != 0)
 
  362   chkdb((t.tab = g_dic->
getTable(t.tabname)) != 0);
 
  364   if (! g_opts.use_table) {
 
  370     char pk2[1 + g_charlen + 1];
 
  372     sprintf(pk2 + 1, 
"%-u", pk1);
 
  373     *(uchar*)pk2 = (uchar)(strlen(pk2 + 1));
 
  374     chkdb(g_op->
equal(
"pk1", (
char*)&pk1) == 0);
 
  375     chkdb(g_op->
equal(
"pk2", (
char*)&pk2[0]) == 0);
 
  376     chkdb(g_con->
execute(Commit) == 0);
 
  388   for (uint i = 0; i < maxtab(); i++)
 
  389     chkrc(createtable(tab(i)) == 0);
 
  396   ll2(
"droptable: " << t.tabname);
 
  397   if (! g_opts.use_table) {
 
  410   for (uint i = 0; i < maxtab(); i++)
 
  411     chkrc(droptable(tab(i)) == 0);
 
  418   ll2(
"createevent: " << t.evtname);
 
  423   evt.setTable(*t.tab);
 
  426   for (i = 0; i < ncol(); i++) {
 
  427     const Col& c = g_col[
i];
 
  428     evt.addEventColumn(c.name);
 
  430   evt.setReport(NdbDictionary::Event::ER_UPDATED);
 
  431   evt.mergeEvents(! g_opts.separate_events);
 
  432 #if 0 // XXX random bugs 
  433   if (g_dic->
getEvent(t.evtname) != 0)
 
  439   chkdb((t.evt = g_dic->
getEvent(t.evtname)) != 0);
 
  448   for (uint i = 0; i < maxtab(); i++)
 
  449     chkrc(createevent(tab(i)) == 0);
 
  454 dropevent(
Tab& t, 
bool force = 
false)
 
  456   ll2(
"dropevent: " << t.evtname);
 
  458   chkdb(g_dic->
dropEvent(t.evtname) == 0 || force);
 
  465 dropevents(
bool force = 
false)
 
  468   for (uint i = 0; i < maxtab(); i++) {
 
  469     if (force && g_tablst[i] == 0)
 
  471     chkrc(dropevent(tab(i), force) == 0 || force);
 
  477   struct Txt { 
char* val; uint len; };
 
  478   union Ptr { Uint32* u32; 
char* ch; uchar* uch; 
Txt* txt; 
void* v; };
 
  480   char pk2[g_charlen + 1];
 
  482   char cc1[g_charlen + 1];
 
  493     memset(pk2, 0, 
sizeof(pk2));
 
  495     memset(cc1, 0, 
sizeof(cc1));
 
  496     tx1.val = tx2.val = bl1.val = 0;
 
  497     tx1.len = tx2.len = bl1.len = 0;
 
  505     for (i = 0; i < g_maxcol; i++)
 
  514     tx1.val = tx2.val = bl1.val = 0;
 
  515     tx1.len = tx2.len = bl1.len = 0;
 
  520 cmpcol(
const Col& c, 
const Data& d1, 
const Data& d2)
 
  523   if (d1.ind[i] != d2.ind[i])
 
  525   if (d1.ind[i] == 0) {
 
  528       if (*d1.ptr[i].u32 != *d2.ptr[i].u32)
 
  532       if (memcmp(d1.ptr[i].ch, d2.ptr[i].ch, c.size) != 0)
 
  537         uint l1 = d1.ptr[
i].uch[0];
 
  538         uint l2 = d2.ptr[
i].uch[0];
 
  541         if (memcmp(d1.ptr[i].ch, d2.ptr[i].ch, l1) != 0)
 
  550         if (t1.len != t2.len)
 
  552         if (memcmp(t1.val, t2.val, t1.len) != 0)
 
  565 operator<<(NdbOut& out, 
const Data& d)
 
  568   for (i = 0; i < ncol(); i++) {
 
  569     const Col& c = getcol(i);
 
  570     out << (i == 0 ? 
"" : 
" ") << c.name;
 
  571     out << (! (d.noop & (1 << i)) ? 
"=" : 
":");
 
  580       out << *d.ptr[
i].u32;
 
  584         char buf[g_charlen + 1];
 
  585         memcpy(buf, d.ptr[i].ch, g_charlen);
 
  589           if (n == 0 || buf[n - 1] != 0x20)
 
  593         out << 
"'" << buf << 
"'";
 
  598         char buf[g_charlen + 1];
 
  599         uint l = d.ptr[
i].uch[0];
 
  600         assert(l <= g_charlen);
 
  601         memcpy(buf, &d.ptr[i].ch[1], l);
 
  603         out << 
"'" << buf << 
"'";
 
  612         while (j < txt.len) {
 
  617           while (j < txt.len && txt.val[j] == c[0])
 
  641 static const uint g_optypes = 3; 
 
  649   enum Kind { OP = 1, EV = 2 };
 
  650   enum Type { UNDEF = -1, INS, DEL, UPD, NUL };
 
  664   void init(Kind a_kind, Type a_type = UNDEF) {
 
  666     assert(kind == OP || kind == EV);
 
  668     next_op = next_com = next_gci = next_ev = next_free = 0;
 
  670     num_op = num_com = 0;
 
  683 operator<<(NdbOut& out, Op::Type optype)
 
  706 operator<<(NdbOut& out, 
const Op& op)
 
  709   out << 
" " << op.data[0];
 
  710   out << 
" [" << op.data[1] << 
"]";
 
  712     out << 
" gci:" << op.gci;
 
  719   Op::Type optype = Op::UNDEF;
 
  731     ll0(
"EVT: " << *ev << 
": bad event type " << hex << (uint)te);
 
  741   Counter(
const char* a_name) : name(a_name), count(0) {
 
  743   friend class NdbOut& operator<<(NdbOut& out, 
const Counter& counter) {
 
  744     out << counter.name << 
"(" << counter.count << 
")";
 
  765 static Op* g_opfree = 0;
 
  766 static uint g_freeops = 0;
 
  767 static uint g_usedops = 0;
 
  768 static uint g_gciops = 0;
 
  769 static uint g_maxcom = 10; 
 
  770 static uint g_seq = 0;
 
  772 static uint g_num_ev = 0;
 
  774 static const uint g_maxgcis = 500; 
 
  781   Uint64 gcinum[g_maxgcis];
 
  782   Uint32 gcievtypes[g_maxgcis][2]; 
 
  788   uint ev_pos[g_maxpk]; 
 
  802     for (i = 0; i < (int)g_maxgcis; i++) {
 
  803       gcinum[
i] = (Uint64)0;
 
  804       gcievtypes[
i][0] = gcievtypes[
i][1] = (Uint32)0;
 
  809     for (i = 0; i < (int)g_maxpk; i++) {
 
  814     for (j = 0; i < 2; j ++) {
 
  815       for (i = 0; i < (int)g_maxcol; i++) {
 
  821   int addgci(Uint64 gci)
 
  823     assert(gcicnt < g_maxgcis);
 
  824     chkrc(gcicnt == 0 || gcinum[gcicnt - 1] < gci);
 
  825     gcinum[gcicnt++] = gci;
 
  828   void addevtypes(Uint64 gci, Uint32 evtypes, uint i)
 
  830     assert(gcicnt != 0 && gci == gcinum[gcicnt - 1]);
 
  831     assert(evtypes != 0);
 
  833     gcievtypes[gcicnt - 1][
i] |= evtypes;
 
  837 static Run* g_runlst[g_maxtab];
 
  848   assert(i < maxrun() && g_runlst[i] != 0);
 
  856   for (i = 0; i < maxrun(); i++)
 
  857     g_tablst[i] = g_runlst[i] = 
new Run(i);
 
  861 getop(Op::Kind a_kind, Op::Type a_type = Op::UNDEF)
 
  864     assert(g_freeops == 0);
 
  867     op->next_free = g_opfree; 
 
  873   g_opfree = op->next_free;
 
  874   assert(g_freeops != 0);
 
  877   op->init(a_kind, a_type);
 
  879   ll3(
"getop: " << op);
 
  886   ll3(
"freeop: " << op);
 
  890   op->next_free = g_opfree;
 
  893   assert(g_usedops != 0);
 
  902   for (pk1 = 0; pk1 < g_opts.maxpk; pk1++)
 
  905   for (pk1 = 0; pk1 < g_opts.maxpk; pk1++) {
 
  906     if (r.pk_op[pk1] != 0) {
 
  907       Op* tot_op = r.pk_op[pk1];
 
  908       while (tot_op->next_gci != 0) {
 
  909         Op* gci_op = tot_op->next_gci;
 
  910         while (gci_op->next_com != 0) {
 
  911           Op* com_op = gci_op->next_com;
 
  912           while (com_op->next_op != 0) {
 
  913             Op* op = com_op->next_op;
 
  914             com_op->next_op = op->next_op;
 
  917           gci_op->next_com = com_op->next_com;
 
  920         tot_op->next_gci = gci_op->next_gci;
 
  926     if (r.pk_ev[pk1] != 0) {
 
  927       Op* tot_op = r.pk_ev[pk1];
 
  928       while (tot_op->next_ev != 0) {
 
  929         Op* ev = tot_op->next_ev;
 
  930         tot_op->next_ev = ev->next_ev;
 
  947   for (uint i = 0; i < maxrun(); i++)
 
  949   assert(g_usedops == 0);
 
  950   g_gciops = g_num_ev = 0;
 
  956   while (g_opfree != 0) {
 
  957     Op* tmp_op = g_opfree;
 
  958     g_opfree = g_opfree->next_free;
 
  962   assert(g_freeops == 0);
 
  971   { Op::INS, Op::DEL, Op::NUL },
 
  972   { Op::INS, Op::UPD, Op::INS },
 
  973   { Op::DEL, Op::INS, Op::UPD },
 
  974   { Op::UPD, Op::DEL, Op::DEL },
 
  975   { Op::UPD, Op::UPD, Op::UPD }
 
  978 static const uint g_ncomp = 
sizeof(g_comp)/
sizeof(g_comp[0]);
 
  981 checkop(
const Op* op, Uint32& pk1)
 
  983   Op::Type optype = op->type;
 
  984   assert(optype != Op::UNDEF);
 
  985   if (optype == Op::NUL)
 
  987   chkrc(optype == Op::INS || optype == Op::DEL || optype == Op::UPD);
 
  988   const Data& d0 = op->data[0];
 
  989   const Data& d1 = op->data[1];
 
  991     const Col& c = getcol(
"pk1");
 
  992     chkrc(d0.ind[c.no] == 0);
 
  994     chkrc(pk1 < g_opts.maxpk);
 
  997   for (i = 0; i < ncol(); i++) {
 
  998     const Col& c = getcol(i);
 
  999     const int ind0 = d0.ind[
i];
 
 1000     const int ind1 = d1.ind[
i];
 
 1004       if (optype == Op::INS)
 
 1006       if (optype == Op::DEL)
 
 1008       if (optype == Op::UPD)
 
 1012       if (optype == Op::INS)
 
 1013         chkrc(ind0 >= 0 && ind1 == -1);
 
 1014       if (optype == Op::DEL)
 
 1015         chkrc(ind0 == -1 && ind1 >= 0); 
 
 1016       if (optype == Op::UPD)
 
 1017         chkrc(ind0 == -1 || ind1 >= 0); 
 
 1020       chkrc(ind0 <= 0 && ind1 <= 0);
 
 1025       for (j = 0; j < 2; j++) {
 
 1026         const Data& d = op->data[j];
 
 1027         if (d.ind[i] == 0) {
 
 1030           for (k = 0; k < (int)txt.len; k++) {
 
 1031             chkrc(strchr(g_charval, txt.val[k]) != 0);
 
 1041 comptype(Op::Type t1, Op::Type t2) 
 
 1044   for (i = 0; i < g_ncomp; i++)
 
 1045     if (g_comp[i].t1 == t1 && g_comp[i].t2 == t2)
 
 1054   if ((d3.ind[i] = d1.ind[i]) == 0) {
 
 1056       memmove(d3.ptr[i].v, d1.ptr[i].v, c.size);
 
 1061       t3.val = 
new char [t1.len];
 
 1063       memcpy(t3.val, t1.val, t1.len);
 
 1069 copydata(
const Data& d1, 
Data& d3, 
bool pk, 
bool nonpk)
 
 1072   for (i = 0; i < ncol(); i++) {
 
 1073     const Col& c = g_col[
i];
 
 1074     if ((c.pk && pk) || (! c.pk && nonpk))
 
 1080 compdata(
const Data& d1, 
const Data& d2, 
Data& d3, 
bool pk, 
bool nonpk)
 
 1083   for (i = 0; i < ncol(); i++) {
 
 1084     const Col& c = g_col[
i];
 
 1085     if ((c.pk && pk) || (! c.pk && nonpk)) {
 
 1087       if (d1.ind[i] == -1 && d2.ind[i] == -1)
 
 1089       else if (d1.ind[i] == -1 && d2.ind[i] != -1)
 
 1091       else if (d1.ind[i] != -1 && d2.ind[i] == -1)
 
 1102 copyop(
const Op* op1, 
Op* op3)
 
 1104   op3->type = op1->type;
 
 1105   copydata(op1->data[0], op3->data[0], 
true, 
true);
 
 1106   copydata(op1->data[1], op3->data[1], 
true, 
true);
 
 1107   op3->gci = op1->gci;
 
 1109   reqrc(checkop(op3, pk1_tmp) == 0);
 
 1113 compop(
const Op* op1, 
const Op* op2, 
Op* op3) 
 
 1115   assert(op1->type != Op::UNDEF && op2->type != Op::UNDEF);
 
 1117   if (op2->type == Op::NUL) {
 
 1121   if (op1->type == Op::NUL) {
 
 1126     op1->kind == Op::OP && op2->kind == Op::OP ? Op::OP : Op::EV;
 
 1127   Op* res_op = getop(kind);
 
 1128   chkrc((comp = comptype(op1->type, op2->type)) != 0);
 
 1129   res_op->type = comp->t3;
 
 1130   if (res_op->type == Op::INS) {
 
 1132     compdata(op1->data[0], op2->data[0], res_op->data[0], 
true, 
true);
 
 1135   if (res_op->type == Op::DEL) {
 
 1137     copydata(op2->data[0], res_op->data[0], 
true, 
false); 
 
 1138     copydata(op1->data[1], res_op->data[1], 
true, 
true); 
 
 1140   if (res_op->type == Op::UPD && op1->type == Op::DEL) {
 
 1142     copydata(op2->data[0], res_op->data[0], 
true, 
true);
 
 1143     copydata(op1->data[0], res_op->data[1], 
true, 
false); 
 
 1144     copydata(op1->data[1], res_op->data[1], 
true, 
true); 
 
 1146   if (res_op->type == Op::UPD && op1->type == Op::UPD) {
 
 1148     compdata(op1->data[0], op2->data[0], res_op->data[0], 
true, 
true);
 
 1149     compdata(op2->data[1], op1->data[1], res_op->data[1], 
true, 
true);
 
 1151   assert(op1->gci == op2->gci);
 
 1152   res_op->gci = op2->gci;
 
 1154   reqrc(checkop(res_op, pk1_tmp) == 0);
 
 1155   copyop(res_op, op3);
 
 1161 createeventop(
Run& r)
 
 1163   ll2(
"createeventop: " << r.tabname);
 
 1167   for (i = 0; i < ncol(); i++) {
 
 1168     const Col& c = g_col[
i];
 
 1169     Data (&d)[2] = g_rec_ev->data;
 
 1171       chkdb((r.ev_ra[0][i] = r.evt_op->
getValue(c.name, (
char*)d[0].ptr[i].v)) != 0);
 
 1172       chkdb((r.ev_ra[1][i] = r.evt_op->
getPreValue(c.name, (
char*)d[1].ptr[i].v)) != 0);
 
 1174       chkdb((r.ev_bh[0][i] = r.evt_op->
getBlobHandle(c.name)) != 0);
 
 1175       chkdb((r.ev_bh[1][i] = r.evt_op->getPreBlobHandle(c.name)) != 0);
 
 1184   ll1(
"createeventop");
 
 1185   for (uint i = 0; i < maxrun(); i++)
 
 1186     chkrc(createeventop(
run(i)) == 0);
 
 1191 executeeventop(
Run& r)
 
 1193   ll2(
"executeeventop: " << r.tabname);
 
 1194   chkdb(r.evt_op->
execute() == 0);
 
 1201   ll1(
"executeeventop");
 
 1202   for (uint i = 0; i < maxrun(); i++)
 
 1203     chkrc(executeeventop(
run(i)) == 0);
 
 1208 dropeventop(
Run& r, 
bool force = 
false)
 
 1210   ll2(
"dropeventop: " << r.tabname);
 
 1211   if (r.evt_op != 0) {
 
 1219 dropeventops(
bool force = 
false)
 
 1221   ll1(
"dropeventops");
 
 1222   for (uint i = 0; i < maxrun(); i++) {
 
 1223     if (force && g_runlst[i] == 0)
 
 1225     chkrc(dropeventop(
run(i), force) == 0 || force);
 
 1234   ll1(
"waitgci " << ngci);
 
 1242       char pk2[1 + g_charlen + 1];
 
 1244       sprintf(pk2 + 1, 
"%-u", pk1);
 
 1245       *(uchar*)pk2 = (uchar)(strlen(pk2 + 1));
 
 1248       chkdb(g_op->
equal(
"pk1", (
char*)&pk1) == 0);
 
 1249       chkdb(g_op->
equal(
"pk2", (
char*)&pk2[0]) == 0);
 
 1250       chkdb(g_con->
execute(Commit) == 0);
 
 1256     if (i == 1 && gci[0] + ngci <= gci[1]) {
 
 1257       ll1(
"waitgci: " << gci[0] << 
" " << gci[1]);
 
 1270   ll2(
"scantable: " << r.tabname);
 
 1273   Op* rec_op = getop(Op::OP);
 
 1274   Data& d0 = rec_op->data[0];
 
 1279   for (i = 0; i < ncol(); i++) {
 
 1280     const Col& c = getcol(i);
 
 1282       chkdb((ra[i] = g_scan_op->
getValue(c.name, (
char*)d0.ptr[i].v)) != 0);
 
 1287   chkdb(g_con->
execute(NoCommit) == 0);
 
 1289   while ((ret = g_scan_op->
nextResult()) == 0) {
 
 1290     Uint32 pk1 = d0.pk1;
 
 1291     if (pk1 >= g_opts.maxpk)
 
 1293     rec_op->type = Op::INS;
 
 1294     for (i = 0; i < ncol(); i++) {
 
 1295       const Col& c = getcol(i);
 
 1301         ret = bh[
i]->getDefined(ind);
 
 1308           txt.len = (uint)len64;
 
 1310           txt.val = 
new char [txt.len];
 
 1311           memset(txt.val, 
'X', txt.len);
 
 1312           Uint32 len = txt.len;
 
 1314           assert(ret == 0 && len == txt.len);
 
 1316           chkdb(g_con->
execute(NoCommit) == 0);
 
 1317           assert(memchr(txt.val, 
'X', txt.len) == 0);
 
 1323     assert(r.pk_op[pk1] == 0);
 
 1324     Op* tot_op = r.pk_op[pk1] = getop(Op::OP);
 
 1325     copyop(rec_op, tot_op);
 
 1326     tot_op->type = Op::INS;
 
 1340   for (uint i = 0; i < maxrun(); i++)
 
 1341     chkrc(scantable(
run(i)) == 0);
 
 1346 makedata(
const Col& c, 
Data& d, Uint32 pk1, Op::Type optype)
 
 1353         Uint32* p = d.ptr[
i].u32;
 
 1359         char* p = d.ptr[
i].ch;
 
 1360         sprintf(p, 
"%-*u", g_charlen, pk1);
 
 1365         char* p = &d.ptr[
i].ch[1];
 
 1366         sprintf(p, 
"%-u", pk1);
 
 1367         uint len = pk1 % g_charlen;
 
 1370           p[j] = 
'a' + j % 26;
 
 1373         d.ptr[
i].uch[0] = len;
 
 1381   } 
else if (optype == Op::DEL) {
 
 1383   } 
else if (i == getcol(
"seq").no) {
 
 1386   } 
else if (optype == Op::INS && ! g_opts.no_implicit_nulls && c.nullable && urandom(10, 100)) {
 
 1389   } 
else if (optype == Op::UPD && ! g_opts.no_missing_update && urandom(10, 100)) {
 
 1392   } 
else if (! g_opts.no_nulls && c.nullable && urandom(10, 100)) {
 
 1398         Uint32* p = d.ptr[
i].u32;
 
 1405         char* p = d.ptr[
i].ch;
 
 1406         uint u = urandom(g_charlen);
 
 1408           u = urandom(g_charlen); 
 
 1410         for (j = 0; j < g_charlen; j++) {
 
 1411           uint v = urandom(strlen(g_charval));
 
 1412           p[j] = j < u ? g_charval[v] : 0x20;
 
 1423         if (g_opts.tweak & 1) {
 
 1424           uint u = g_blobinlinesize + (tinyblob ? 0 : g_blobpartsize);
 
 1425           uint v = (g_opts.tweak & 2) ? 0 : urandom(strlen(g_charval));
 
 1426           txt.val = 
new char [u];
 
 1428           memset(txt.val, g_charval[v], u);
 
 1431         uint u = urandom(tinyblob ? g_blobinlinesize : g_maxblobsize);
 
 1434         txt.val = 
new char [u];
 
 1439           uint k = 1 + urandom(u - 1);
 
 1442           uint v = urandom(strlen(g_charval));
 
 1443           memset(&txt.val[j], g_charval[v], k);
 
 1457 makeop(
const Op* prev_op, 
Op* op, Uint32 pk1, Op::Type optype)
 
 1460   const Data& dp = prev_op->data[0];
 
 1461   Data& d0 = op->data[0];
 
 1462   Data& d1 = op->data[1];
 
 1464   for (i = 0; i < ncol(); i++) {
 
 1465     const Col& c = getcol(i);
 
 1466     makedata(c, d0, pk1, optype);
 
 1467     if (optype == Op::INS) {
 
 1469     } 
else if (optype == Op::DEL) {
 
 1470       assert(dp.ind[i] >= 0);
 
 1472     } 
else if (optype == Op::UPD) {
 
 1473       assert(dp.ind[i] >= 0);
 
 1474       if (d0.ind[i] == -1) 
 
 1481   Uint32 pk1_tmp = ~(Uint32)0;
 
 1482   reqrc(checkop(op, pk1_tmp) == 0);
 
 1483   reqrc(pk1 == pk1_tmp);
 
 1487 approxblobops(
Op* op)
 
 1489   uint avg_blob_size = g_maxblobsize / 4; 
 
 1490   uint avg_blob_ops = avg_blob_size / 2000;
 
 1492   if (! g_opts.no_blobs) {
 
 1494     if (! g_opts.one_blob)
 
 1496     if (op->type == Op::UPD)
 
 1505   ll1(
"makeops: " << r.tabname);
 
 1508     if (g_opts.opstring == 0) {
 
 1509       if (r.tableops + r.blobops >= g_opts.maxops) 
 
 1511       pk1 = urandom(g_opts.maxpk);
 
 1513       if (pk1 >= g_opts.maxpk) 
 
 1516     ll2(
"makeops: pk1=" << pk1);
 
 1519     Op* tot_op = r.pk_op[pk1];
 
 1521       tot_op = r.pk_op[pk1] = getop(Op::OP, Op::NUL);
 
 1522     assert(tot_op->type == Op::NUL || tot_op->type == Op::INS);
 
 1524     Op* last_gci = tot_op;
 
 1525     while (last_gci->next_gci != 0)
 
 1526       last_gci = last_gci->next_gci;
 
 1527     Op* gci_op = getop(Op::OP, Op::NUL);
 
 1528     last_gci->next_gci = gci_op;
 
 1529     Op* com_op = getop(Op::OP, Op::NUL);
 
 1530     gci_op->next_com = com_op;
 
 1533     if (g_opts.opstring == 0) {
 
 1534       len = 1 + urandom(g_maxcom - 1);
 
 1535       len = 1 + urandom(len - 1); 
 
 1541       if (g_opts.opstring == 0) {
 
 1545           optype = (Op::Type)urandom(g_optypes);
 
 1546         } 
while ((tot_op->type == Op::NUL &&
 
 1547                   (optype == Op::DEL || optype == Op::UPD)) ||
 
 1548                  (tot_op->type == Op::INS && optype == Op::INS));
 
 1550         const char* str = g_opstringpart[g_loop % g_opstringparts];
 
 1551         uint m = strlen(str);
 
 1552         uint k = tot_op->num_com + tot_op->num_op;
 
 1560         const char* p = 
"idu";
 
 1561         const char* q = strchr(p, c);
 
 1563         optype = (Op::Type)(q - p);
 
 1565       Op* op = getop(Op::OP);
 
 1566       makeop(tot_op, op, pk1, optype);
 
 1568       r.blobops += approxblobops(op);
 
 1570       Op* last_op = com_op;
 
 1571       while (last_op->next_op != 0)
 
 1572         last_op = last_op->next_op;
 
 1573       last_op->next_op = op;
 
 1575       reqrc(compop(com_op, op, com_op) == 0);
 
 1576       reqrc(compop(tot_op, op, tot_op) == 0);
 
 1577       assert(tot_op->type == Op::NUL || tot_op->type == Op::INS);
 
 1579       com_op->num_op += 1;
 
 1580       tot_op->num_op += 1;
 
 1584     copyop(com_op, gci_op);
 
 1585     tot_op->num_com += 1;
 
 1589   ll1(
"makeops: " << r.tabname << 
": com recs = " << r.gciops);
 
 1596   for (i = 0; i < maxrun(); i++)
 
 1597     run(i).skip = 
false;
 
 1598   if (g_opts.opstring != 0) {
 
 1599     ll1(
"using all tables due to fixed ops");
 
 1602   for (i = 0; i + 1 < maxrun(); i++)
 
 1603     run(urandom(maxrun())).
skip = 
true;
 
 1605   for (i = 0; i < maxrun(); i++) {
 
 1606     if (! 
run(i).skip) {
 
 1607       ll2(
"use table " << 
run(i).tabname);
 
 1611   ll0(
"selecttables: use " << cnt << 
"/" << maxrun() << 
" in this loop");
 
 1618   for (uint i = 0; i < maxrun(); i++)
 
 1621   ll0(
"makeops: used records = " << g_usedops);
 
 1625 addndbop(
Run& r, 
Op* op)
 
 1643   for (i = 0; i < ncol(); i++) {
 
 1644     const Col& c = getcol(i);
 
 1645     const Data& d = op->data[0];
 
 1648     chkdb(g_op->
equal(c.name, (
const char*)d.ptr[i].v) == 0);
 
 1650   if (op->type != Op::DEL) {
 
 1651     for (i = 0; i < ncol(); i++) {
 
 1652       const Col& c = getcol(i);
 
 1653       const Data& d = op->data[0];
 
 1656       if (d.noop & (1 << i))
 
 1658       assert(d.ind[i] >= 0);
 
 1661           chkdb(g_op->
setValue(c.name, (
const char*)d.ptr[i].v) == 0);
 
 1663           chkdb(g_op->
setValue(c.name, (
const char*)0) == 0);
 
 1668           chkdb(g_bh->
setValue(txt.val, txt.len) == 0);
 
 1683   Op* gci_op[g_maxtab][g_maxpk];
 
 1687   for (i = 0; i < (int)maxrun(); i++) {
 
 1689     for (pk1 = 0; pk1 < g_opts.maxpk; pk1++) {
 
 1692       Op* tot_op = r.pk_op[pk1];
 
 1695       if (tot_op->next_gci == 0) {
 
 1696         assert(g_loop != 0 && tot_op->type == Op::INS);
 
 1700       assert(tot_op->next_gci != 0);
 
 1701       gci_op[
i][pk1] = tot_op->next_gci;
 
 1707     unsigned int i = urandom(maxrun());
 
 1708     pk1 = urandom(g_opts.maxpk);
 
 1709     if (gci_op[i][pk1] == 0)
 
 1714     Op* com_op = gci_op[
i][pk1]->next_com;
 
 1715     assert(com_op != 0);
 
 1717     Op* op = com_op->next_op;
 
 1720       ll2(
"runops:" << *op);
 
 1721       chkrc(addndbop(r, op) == 0);
 
 1724     chkdb(g_con->
execute(Commit) == 0);
 
 1727     gci_op[
i][pk1]->gci = com_op->gci = val;
 
 1728     ll2(
"commit: " << 
run(i).tabname << 
" gci=" << com_op->gci);
 
 1732     gci_op[
i][pk1] = gci_op[
i][pk1]->next_gci;
 
 1733     if (gci_op[i][pk1] == 0) {
 
 1746   ll2(
"mergeops: " << r.tabname);
 
 1749   for (pk1 = 0; pk1 < g_opts.maxpk; pk1++) {
 
 1750     Op* tot_op = r.pk_op[pk1];
 
 1753     Op* gci_op = tot_op->next_gci;
 
 1755       assert(g_loop != 0 && tot_op->type == Op::INS);
 
 1758     while (gci_op != 0) {
 
 1759       Op* com_op = gci_op->next_com;
 
 1760       assert(com_op != 0 && com_op->next_com == 0);
 
 1761       assert(gci_op->gci == com_op->gci);
 
 1762       Op* last_com = com_op;
 
 1763       Op* gci_op2 = gci_op->next_gci;
 
 1764       while (gci_op2 != 0 && gci_op->gci == gci_op2->gci) {
 
 1766         last_com = last_com->next_com = gci_op2->next_com;
 
 1768         reqrc(compop(gci_op, gci_op2, gci_op) == 0);
 
 1770         Op* tmp_op = gci_op2;
 
 1771         gci_op2 = gci_op2->next_gci;
 
 1774         assert(r.gciops != 0 && g_gciops != 0);
 
 1778       gci_op = gci_op->next_gci = gci_op2;
 
 1781   ll1(
"mergeops: " << r.tabname << 
": gci recs = " << r.gciops);
 
 1787   for (uint i = 0; i < maxrun(); i++)
 
 1789   ll1(
"mergeops: used recs = " << g_usedops << 
" gci recs = " << g_gciops);
 
 1796   ll2(
"cmppostpre: " << r.tabname);
 
 1798   for (pk1 = 0; pk1 < g_opts.maxpk; pk1++) {
 
 1799     Op* tot_op = r.pk_op[pk1];
 
 1800     Op* gci_op = tot_op ? tot_op->next_gci : 0;
 
 1801     while (gci_op != 0) {
 
 1802       if (gci_op->type == Op::UPD) {
 
 1803         Data (&d)[2] = gci_op->data;
 
 1805         for (i = 0; i < ncol(); i++) {
 
 1806           const Col& c = getcol(i);
 
 1808             (d[0].ind[
i] == 1 && d[1].ind[
i] == 1) ||
 
 1809             (d[0].ind[i] == 0 && d[1].ind[i] == 0 && cmpcol(c, d[0], d[1])== 0);
 
 1811             d[0].ppeq |= (1 << 
i);
 
 1812             d[1].ppeq |= (1 << 
i);
 
 1816       gci_op = gci_op->next_gci;
 
 1825   for (uint i = 0; i < maxrun(); i++)
 
 1833   for (i = 0; i < maxrun(); i++) {
 
 1834     if (
run(i).evt_op == evt_op)
 
 1837   chkrc(i < maxrun());
 
 1842 geteventdata(
Run& r)
 
 1844   Data (&d)[2] = g_rec_ev->data;
 
 1846   for (j = 0; j < 2; j++) {
 
 1847     for (i = 0; i < (int)ncol(); i++) {
 
 1848       const Col& c = getcol(i);
 
 1855         ret = bh->getDefined(ind);
 
 1862           txt.len = (uint)len64;
 
 1864           txt.val = 
new char [txt.len];
 
 1865           memset(txt.val, 
'X', txt.len);
 
 1866           Uint32 len = txt.len;
 
 1868           assert(ret == 0 && len == txt.len);
 
 1877 addgcievents(Uint64 gci)
 
 1879   ll1(
"getgcieventops");
 
 1881   uint seen_current = 0;
 
 1891     chkrc((i = findevent(evt_op)) != -1);
 
 1892     run(i).addevtypes(gci, evtypes, 0);
 
 1893     seen_current += (g_evt_op == evt_op);
 
 1896   chkrc(seen_current == 1);
 
 1897   ll1(
"addgcievents: " << count);
 
 1907   ll1(
"poll " << npoll);
 
 1908   Uint64 gci = (Uint64)0;
 
 1909   while (npoll != 0) {
 
 1916       g_rec_ev->init(Op::EV);
 
 1920       Uint64 newgci = g_evt_op->
getGCI();
 
 1921       assert(newgci != 0);
 
 1922       g_rec_ev->gci = newgci;
 
 1923       if (gci != newgci) {
 
 1924         ll1(
"new gci: " << gci << 
" -> " << newgci);
 
 1928         for (i = 0; i < maxtab(); i++)
 
 1929           chkrc(
run(i).addgci(gci) == 0);
 
 1930         chkrc(addgcievents(gci) == 0);
 
 1933       chkrc((i = findevent(g_evt_op)) != -1);
 
 1936       chkrc(seteventtype(g_rec_ev, evtype) == 0);
 
 1937       r.addevtypes(gci, (Uint32)evtype, 1);
 
 1939       ll2(
"runevents: EVT: " << *g_rec_ev);
 
 1941       Uint32 pk1 = ~(Uint32)0;
 
 1942       chkrc(checkop(g_rec_ev, pk1) == 0);
 
 1944       Op* tot_ev = r.pk_ev[pk1];
 
 1946         tot_ev = r.pk_ev[pk1] = getop(Op::EV);
 
 1947       Op* last_ev = tot_ev;
 
 1948       while (last_ev->next_ev != 0)
 
 1949         last_ev = last_ev->next_ev;
 
 1951       Op* ev = getop(Op::EV);
 
 1952       copyop(g_rec_ev, ev);
 
 1953       g_rec_ev->freemem();
 
 1954       last_ev->next_ev = ev;
 
 1958   ll1(
"runevents: used ops = " << g_usedops << 
" events = " << g_num_ev);
 
 1963 cmpopevdata(
const Data& d1, 
const Data& d2)
 
 1966   for (i = 0; i < ncol(); i++) {
 
 1967     const Col& c = getcol(i);
 
 1968     if (cmpcol(c, d1, d2) != 0) {
 
 1969       if ((d1.ppeq & (1 << i)) && d2.ind[i] == -1)
 
 1980 cmpopevdata(
const Data (&d1)[2], 
const Data (&d2)[2])
 
 1982   if (cmpopevdata(d1[0], d2[0]) != 0)
 
 1984   if (cmpopevdata(d1[1], d2[1]) != 0)
 
 1990 matchevent(
Run& r, 
Op* ev)
 
 1992   Data (&d2)[2] = ev->data;
 
 1994   Uint32 pk1 = d2[0].pk1;
 
 1995   chkrc(pk1 < g_opts.maxpk);
 
 1999     int g_loglevel = loop == 0 ? g_opts.loglevel : 2;
 
 2000     ll1(
"matchevent: " << r.tabname << 
": pk1=" << pk1 << 
" type=" << ev->type);
 
 2001     ll2(
"EVT: " << *ev);
 
 2002     Op* tot_op = r.pk_op[pk1];
 
 2003     Op* gci_op = tot_op ? tot_op->next_gci : 0;
 
 2006     while (gci_op != 0) {
 
 2007       ll2(
"GCI: " << *gci_op);
 
 2009       Op* com_op = gci_op->next_com;
 
 2010       assert(com_op != 0);
 
 2011       while (com_op != 0) {
 
 2012         ll2(
"COM: " << *com_op);
 
 2013         Op* op = com_op->next_op;
 
 2016           ll2(
"OP : " << *op);
 
 2019         com_op = com_op->next_com;
 
 2022       if (gci_op->type != Op::NUL) {
 
 2023         const Data (&d1)[2] = gci_op->data;
 
 2024         if (cmpopevdata(d1, d2) == 0) {
 
 2026           if (gci_op->type != ev->type) {
 
 2027             ll2(
"***: wrong type " << gci_op->type << 
" != " << ev->type);
 
 2030           if (gci_op->match) {
 
 2031             ll2(
"***: duplicate match");
 
 2034           if (pos != r.ev_pos[pk1]) {
 
 2035             ll2(
"***: wrong pos " << pos << 
" != " << r.ev_pos[pk1]);
 
 2038           if (gci_op->gci != ev->gci) {
 
 2039             ll2(
"***: wrong gci " << gci_op->gci << 
" != " << ev->gci);
 
 2043             ok = gci_op->match = 
true;
 
 2049       gci_op = gci_op->next_gci;
 
 2052       ll2(
"matchevent: match");
 
 2055     ll0(
"matchevent: ERROR: no match");
 
 2056     if (g_loglevel >= 2)
 
 2066   ll1(
"matchevents: " << r.tabname);
 
 2069   for (pk1 = 0; pk1 < g_opts.maxpk; pk1++) {
 
 2070     Op* tot_ev = r.pk_ev[pk1];
 
 2073     Op* ev = tot_ev->next_ev;
 
 2075       if (matchevent(r, ev) < 0)
 
 2081   chkrc(nomatch == 0);
 
 2089   for (uint i = 0; i < maxrun(); i++)
 
 2090     chkrc(matchevents(
run(i)) == 0);
 
 2097   ll1(
"matchops: " << r.tabname);
 
 2100   for (pk1 = 0; pk1 < g_opts.maxpk; pk1++) {
 
 2101     Op* tot_op = r.pk_op[pk1];
 
 2104     Op* gci_op = tot_op->next_gci;
 
 2105     while (gci_op != 0) {
 
 2106       if (gci_op->type == Op::NUL) {
 
 2107         ll2(
"GCI: " << *gci_op << 
" [skip NUL]");
 
 2108       } 
else if (gci_op->match) {
 
 2109         ll2(
"GCI: " << *gci_op << 
" [match OK]");
 
 2111         ll0(
"GCI: " << *gci_op);
 
 2112         Op* com_op = gci_op->next_com;
 
 2113         assert(com_op != 0);
 
 2114         ll0(
"COM: " << *com_op);
 
 2115         Op* op = com_op->next_op;
 
 2118           ll0(
"OP : " << *op);
 
 2121         ll0(
"no matching event");
 
 2124       gci_op = gci_op->next_gci;
 
 2127   chkrc(nomatch == 0);
 
 2135   for (uint i = 0; i < maxrun(); i++)
 
 2136     chkrc(matchops(
run(i)) == 0);
 
 2141 matchgcievents(
Run& r)
 
 2143   ll1(
"matchgcievents: " << r.tabname);
 
 2145   for (i = 0; i < r.gcicnt; i++) {
 
 2146     Uint32 t0 = r.gcievtypes[
i][0];
 
 2147     Uint32 t1 = r.gcievtypes[
i][1];
 
 2148     ll1(
"gci: " << r.gcinum[i] << hex << 
" report: " << t0 << 
" seen: " << t1);
 
 2151       chkrc(t0 == 0 && t1 == 0);
 
 2152     if (t0 == 0 && t1 == 0)
 
 2158     chkrc((~t0 & t1) == 0);
 
 2161     if (g_opts.separate_events) {
 
 2165       chkrc((t0 & ~t1) == 0);
 
 2174   ll1(
"matchgcievents");
 
 2175   for (uint i = 0; i < maxrun(); i++)
 
 2176     chkrc(matchgcievents(
run(i)) == 0);
 
 2185     if (g_opts.seed == 0)
 
 2187     if (g_opts.seed != (uint)-1)
 
 2188       seed = (uint)g_opts.seed;
 
 2190       seed = 1 + (ushort)getpid();
 
 2192     if (g_opts.seed != 0)
 
 2196   ll0(
"seed=" << seed);
 
 2205   chkrc(createtables() == 0);
 
 2206   chkrc(createevents() == 0);
 
 2207   for (g_loop = 0; g_opts.loop == 0 || g_loop < g_opts.loop; g_loop++) {
 
 2208     ll0(
"=== loop " << g_loop << 
" ===");
 
 2211     chkrc(scantable() == 0); 
 
 2213     g_rec_ev = getop(Op::EV);
 
 2214     chkrc(createeventop() == 0);
 
 2215     chkrc(executeeventop() == 0);
 
 2216     chkrc(waitgci(3) == 0);
 
 2217     chkrc(runops() == 0);
 
 2218     if (! g_opts.separate_events)
 
 2221     chkrc(runevents() == 0);
 
 2222     ll0(
"counts: gci ops = " << g_gciops << 
" ev ops = " << g_num_ev);
 
 2223     chkrc(matchevents() == 0);
 
 2224     chkrc(matchops() == 0);
 
 2225     chkrc(matchgcievents() == 0);
 
 2226     chkrc(dropeventops() == 0);
 
 2228     chkrc(waitgci(1) == 0);
 
 2230   chkrc(dropevents() == 0);
 
 2231   chkrc(droptables() == 0);
 
 2240   NDB_STD_OPTS(
"test_event_merge"),
 
 2241   { 
"abort-on-error", NDB_OPT_NOSHORT, 
"Do abort() on any error",
 
 2242     (uchar **)&g_opts.abort_on_error, (uchar **)&g_opts.abort_on_error, 0,
 
 2243     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
 
 2244   { 
"loglevel", NDB_OPT_NOSHORT, 
"Logging level in this program 0-3 (default 0)",
 
 2245     (uchar **)&g_opts.loglevel, (uchar **)&g_opts.loglevel, 0,
 
 2246     GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
 
 2247   { 
"loop", NDB_OPT_NOSHORT, 
"Number of test loops (default 5, 0=forever)",
 
 2248     (uchar **)&g_opts.loop, (uchar **)&g_opts.loop, 0,
 
 2249     GET_INT, REQUIRED_ARG, 5, 0, 0, 0, 0, 0 },
 
 2250   { 
"maxops", NDB_OPT_NOSHORT, 
"Approx number of PK operations per table (default 1000)",
 
 2251     (uchar **)&g_opts.maxops, (uchar **)&g_opts.maxops, 0,
 
 2252     GET_UINT, REQUIRED_ARG, 1000, 0, 0, 0, 0, 0 },
 
 2253   { 
"maxpk", NDB_OPT_NOSHORT, 
"Number of different PK values (default 10, max 1000)",
 
 2254     (uchar **)&g_opts.maxpk, (uchar **)&g_opts.maxpk, 0,
 
 2255     GET_UINT, REQUIRED_ARG, 10, 0, 0, 0, 0, 0 },
 
 2256   { 
"maxtab", NDB_OPT_NOSHORT, 
"Number of tables (default 10, max 100)",
 
 2257     (uchar **)&g_opts.maxtab, (uchar **)&g_opts.maxtab, 0,
 
 2258     GET_INT, REQUIRED_ARG, 10, 0, 0, 0, 0, 0 },
 
 2259   { 
"no-blobs", NDB_OPT_NOSHORT, 
"Omit blob attributes (5.0: true)",
 
 2260     (uchar **)&g_opts.no_blobs, (uchar **)&g_opts.no_blobs, 0,
 
 2261     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
 
 2262   { 
"no-implicit-nulls", NDB_OPT_NOSHORT, 
"Insert must include all attrs" 
 2263                                " i.e. no implicit NULLs",
 
 2264     (uchar **)&g_opts.no_implicit_nulls, (uchar **)&g_opts.no_implicit_nulls, 0,
 
 2265     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
 
 2266   { 
"no-missing-update", NDB_OPT_NOSHORT, 
"Update must include all non-PK attrs",
 
 2267     (uchar **)&g_opts.no_missing_update, (uchar **)&g_opts.no_missing_update, 0,
 
 2268     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
 
 2269   { 
"no-multiops", NDB_OPT_NOSHORT, 
"Allow only 1 operation per commit",
 
 2270     (uchar **)&g_opts.no_multiops, (uchar **)&g_opts.no_multiops, 0,
 
 2271     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
 
 2272   { 
"no-nulls", NDB_OPT_NOSHORT, 
"Create no NULL values",
 
 2273     (uchar **)&g_opts.no_nulls, (uchar **)&g_opts.no_nulls, 0,
 
 2274     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
 
 2275   { 
"one-blob", NDB_OPT_NOSHORT, 
"Only one blob attribute (default 2)",
 
 2276     (uchar **)&g_opts.one_blob, (uchar **)&g_opts.one_blob, 0,
 
 2277     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
 
 2278   { 
"opstring", NDB_OPT_NOSHORT, 
"Operations to run e.g. idiucdc (c is commit) or" 
 2279                       " iuuc:uudc (the : separates loops)",
 
 2280     (uchar **)&g_opts.opstring, (uchar **)&g_opts.opstring, 0,
 
 2281     GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
 
 2282   { 
"seed", NDB_OPT_NOSHORT, 
"Random seed (0=loop number, default -1=random)",
 
 2283     (uchar **)&g_opts.seed, (uchar **)&g_opts.seed, 0,
 
 2284     GET_INT, REQUIRED_ARG, -1, 0, 0, 0, 0, 0 },
 
 2285   { 
"separate-events", NDB_OPT_NOSHORT, 
"Do not combine events per GCI (5.0: true)",
 
 2286     (uchar **)&g_opts.separate_events, (uchar **)&g_opts.separate_events, 0,
 
 2287     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
 
 2288   { 
"tweak", NDB_OPT_NOSHORT, 
"Whatever the source says",
 
 2289     (uchar **)&g_opts.tweak, (uchar **)&g_opts.tweak, 0,
 
 2290     GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
 
 2291   { 
"use-table", NDB_OPT_NOSHORT, 
"Use existing tables",
 
 2292     (uchar **)&g_opts.use_table, (uchar **)&g_opts.use_table, 0,
 
 2293     GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
 
 2294   { 
"blob-version", NDB_OPT_NOSHORT, 
"Blob version 1 or 2 (default 2)",
 
 2295     (uchar**)&g_opts.blob_version, (uchar**)&g_opts.blob_version, 0,
 
 2296     GET_INT, REQUIRED_ARG, 2, 0, 0, 0, 0, 0 },
 
 2299     GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }
 
 2306   if (g_opts.separate_events) {
 
 2307     g_opts.no_blobs = 
true;
 
 2309   if (g_opts.no_multiops) {
 
 2312   if (g_opts.opstring != 0) {
 
 2313     uint len = strlen(g_opts.opstring);
 
 2314     char* str = 
new char [len + 1];
 
 2315     memcpy(str, g_opts.opstring, len + 1);
 
 2318       g_opstringpart[g_opstringparts++] = s;
 
 2325     for (i = 0; i < g_opstringparts; i++) {
 
 2326       const char* s = g_opstringpart[
i];
 
 2328         if (strchr(
"iduc", *s++) == 0) {
 
 2329           ll0(
"opstring chars are i,d,u,c");
 
 2333       if (s == g_opstringpart[i] || s[-1] != 
'c') {
 
 2334         ll0(
"opstring chain must end in 'c'");
 
 2339   if (g_opts.no_nulls) {
 
 2340     g_opts.no_implicit_nulls = 
true;
 
 2342   if (g_opts.maxpk > g_maxpk ||
 
 2343       g_opts.maxtab > (
int)g_maxtab) {
 
 2346   if (g_opts.blob_version < 1 || g_opts.blob_version > 2) {
 
 2356   chkdb(g_ncc->
connect(30) == 0);
 
 2357   g_ndb = 
new Ndb(g_ncc, 
"TEST_DB");
 
 2358   chkdb(g_ndb->init() == 0 && g_ndb->waitUntilReady(30) == 0);
 
 2363 main(
int argc, 
char** argv)
 
 2366   const char* progname =
 
 2367     strchr(argv[0], 
'/') ? strrchr(argv[0], 
'/') + 1 : argv[0];
 
 2369   for (
int i = 1; i < argc; i++)
 
 2370     ndbout << 
" " << argv[i];
 
 2373   ret = handle_options(&argc, &argv, my_long_options, ndb_std_get_one_option);
 
 2374   if (ret != 0 || argc != 0 || checkopts() != 0)
 
 2375     return NDBT_ProgramExit(NDBT_WRONGARGS);
 
 2376   if (doconnect() == 0 && runtest() == 0) {
 
 2379     return NDBT_ProgramExit(NDBT_OK);
 
 2385   return NDBT_ProgramExit(NDBT_FAILED);