24 #include <ndb_global.h> 
   29 #include <NdbTest.hpp> 
   31 #include <NdbCondition.h> 
   32 #include <NdbThread.h> 
   36 #include <NdbSqlUtil.hpp> 
   37 #include <ndb_version.h> 
  111 static void printcases();
 
  112 static void printtables();
 
  119     << 
"usage: testOIbasic [options]" << endl
 
  120     << 
"  -batch N      pk operations in batch [" << d.m_batch << 
"]" << endl
 
  121     << 
"  -bound xyz    use only these bound types 0-4 [" << d.m_bound << 
"]" << endl
 
  122     << 
"  -case abc     only given test cases (letters a-z)" << endl
 
  123     << 
"  -collsp       use strnncollsp instead of strnxfrm" << endl
 
  124     << 
"  -cont         on error continue to next test case [" << d.m_cont << 
"]" << endl
 
  125     << 
"  -core         core dump on error [" << d.m_core << 
"]" << endl
 
  126     << 
"  -csname S     charset or collation [" << d.m_csname << 
"]" << endl
 
  127     << 
"  -die nnn      exit immediately on NDB error code nnn" << endl
 
  128     << 
"  -dups         allow duplicate tuples from index scan [" << d.m_dups << 
"]" << endl
 
  129     << 
"  -fragtype T   fragment type single/small/medium/large" << endl
 
  130     << 
"  -index xyz    only given index numbers (digits 0-9)" << endl
 
  131     << 
"  -loop N       loop count full suite 0=forever [" << d.m_loop << 
"]" << endl
 
  132     << 
"  -mrrmaxrng N  max ranges to supply for MRR scan [" << d.m_mrrmaxrng << 
"]" << endl
 
  133     << 
"  -nologging    create tables in no-logging mode" << endl
 
  134     << 
"  -noverify     skip index verifications" << endl
 
  135     << 
"  -pctmrr N     pct of index scans to use MRR [" << d.m_pctmrr << 
"]" << endl
 
  136     << 
"  -pctnull N    pct NULL values in nullable column [" << d.m_pctnull << 
"]" << endl
 
  137     << 
"  -rows N       rows per thread [" << d.m_rows << 
"]" << endl
 
  138     << 
"  -samples N    samples for some timings (0=all) [" << d.m_samples << 
"]" << endl
 
  139     << 
"  -scanbatch N  scan batch 0=default [" << d.m_scanbatch << 
"]" << endl
 
  140     << 
"  -scanpar N    scan parallel 0=default [" << d.m_scanpar << 
"]" << endl
 
  141     << 
"  -seed N       srandom seed 0=loop number -1=random [" << d.m_seed << 
"]" << endl
 
  142     << 
"  -skip abc     skip given test cases (letters a-z)" << endl
 
  143     << 
"  -sloop N      level 2 (sub)loop count [" << d.m_sloop << 
"]" << endl
 
  144     << 
"  -ssloop N     level 3 (sub)loop count [" << d.m_ssloop << 
"]" << endl
 
  145     << 
"  -table xyz    only given table numbers (digits 0-9)" << endl
 
  146     << 
"  -threads N    number of threads [" << d.m_threads << 
"]" << endl
 
  147     << 
"  -vN           verbosity [" << d.m_v << 
"]" << endl
 
  148     << 
"  -h or -help   print this help text" << endl
 
  155 static const bool g_store_null_key = 
true;
 
  158 static const bool g_compare_null = 
true;
 
  160 static const char* hexstr = 
"0123456789abcdef";
 
  164 #define random() rand() 
  165 #define srandom(SEED) srand(SEED) 
  173   uint 
i = random() % 
n;
 
  182   int i = random() % 
n;
 
  195   return urandom(100) < pct;
 
  199 random_coprime(uint n)
 
  201     uint prime[] = { 101, 211, 307, 401, 503, 601, 701, 809, 907 };
 
  202     uint count = 
sizeof(prime) / 
sizeof(prime[0]);
 
  206       uint i = urandom(count);
 
  207       if (n % prime[i] != 0)
 
  228   m_start = urandom(n);
 
  229   m_prime = random_coprime(n);
 
  236   return (m_start + m_i++ * m_prime) % m_n;
 
  241 static NdbMutex *ndbout_mutex = NULL;
 
  242 static const char* getthrprefix();
 
  246     if ((n) > g_opt.m_v) break; \ 
  247     if (g_opt.m_msglock) NdbMutex_Lock(ndbout_mutex); \ 
  248     ndbout << getthrprefix(); \ 
  250       ndbout << "line " << __LINE__ << ": "; \ 
  251     ndbout << s << endl; \ 
  252     if (g_opt.m_msglock) NdbMutex_Unlock(ndbout_mutex); \ 
  255 #define LL0(s) LLN(0, s) 
  256 #define LL1(s) LLN(1, s) 
  257 #define LL2(s) LLN(2, s) 
  258 #define LL3(s) LLN(3, s) 
  259 #define LL4(s) LLN(4, s) 
  260 #define LL5(s) LLN(5, s) 
  262 #define HEX(x)  hex << (x) << dec 
  266 #undef CHK      // simple check 
  267 #undef CHKTRY   // check with action on fail 
  268 #undef CHKCON   // print NDB API errors on failure 
  270 #define CHK(x)  CHKTRY(x, ;) 
  272 #define CHKTRY(x, act) \ 
  275     LL0("line " << __LINE__ << ": " << #x << " failed"); \ 
  276     if (g_opt.m_core) abort(); \ 
  281 #define CHKCON(x, con) \ 
  284     LL0("line " << __LINE__ << ": " << #x << " failed"); \ 
  285     (con).printerror(ndbout); \ 
  286     if (g_opt.m_core) abort(); \ 
  302   Con& con()
 const { assert(m_con != 0); 
return *m_con; }
 
  304   const Tab& tab()
 const { assert(m_tab != 0); 
return *m_tab; }
 
  306   const ITab& itab()
 const { assert(m_itab != 0); 
return *m_itab; }
 
  308   Set& 
set() 
const { assert(m_set != 0); 
return *m_set; }
 
  310   Tmr& tmr()
 const { assert(m_tmr != 0); 
return *m_tmr; }
 
  320   bool m_noindexkeyupdate;
 
  352     m_noindexkeyupdate(
false),
 
  369 usetable(
Par par, uint i)
 
  371   return par.m_table == 0 || strchr(par.m_table, 
'0' + i) != 0;
 
  375 useindex(
Par par, uint i)
 
  377   return par.m_index == 0 || strchr(par.m_index, 
'0' + i) != 0;
 
  381 thrrow(
Par par, uint j)
 
  383   return par.m_usedthreads * j + par.m_no;
 
  388 isthrrow(
Par par, uint i)
 
  390   return i % par.m_usedthreads == par.m_no;
 
  399   void off(uint cnt = 0);
 
  401   const char* pct(
const Tmr& t1);
 
  402   const char* over(
const Tmr& t1);
 
  414   m_on = m_ms = m_cnt = m_time[0] = m_text[0] = 0;
 
  421   m_on = NdbTick_CurrentMillisecond();
 
  427   NDB_TICKS off = NdbTick_CurrentMillisecond();
 
  428   assert(m_on != 0 && off >= m_on);
 
  438     sprintf(m_time, 
"%u ms", (
unsigned)m_ms);
 
  440     sprintf(m_time, 
"%u ms per %u ( %u ms per 1000 )", (
unsigned)m_ms, m_cnt, (
unsigned)((1000 * m_ms) / m_cnt));
 
  446 Tmr::pct(
const Tmr& t1)
 
  449     sprintf(m_text, 
"%u pct", (
unsigned)((100 * m_ms) / t1.m_ms));
 
  451     sprintf(m_text, 
"[cannot measure]");
 
  457 Tmr::over(
const Tmr& t1)
 
  461       sprintf(m_text, 
"%u pct", (
unsigned)((100 * (m_ms - t1.m_ms)) / t1.m_ms));
 
  463       sprintf(m_text, 
"-%u pct", (
unsigned)((100 * (t1.m_ms - m_ms)) / t1.m_ms));
 
  465     sprintf(m_text, 
"[cannot measure]");
 
  472 static const uint maxcsnumber = 512;
 
  473 static const uint maxcharcount = 32;
 
  474 static const uint maxcharsize = 4;
 
  475 static const uint maxxmulsize = 8;
 
  479   uchar m_bytes[maxcharsize];
 
  480   uchar m_xbytes[maxxmulsize * maxcharsize];
 
  487   memset(m_bytes, 0, 
sizeof(m_bytes));
 
  488   memset(m_xbytes, 0, 
sizeof(m_xbytes));
 
  502 operator<<(NdbOut& out, 
const Chs& chs);
 
  507   m_xmul = m_cs->strxfrm_multiply;
 
  510   assert(m_xmul <= maxxmulsize);
 
  511   m_chr = 
new Chr [maxcharcount];
 
  517   while (i < maxcharcount) {
 
  518     uchar* bytes = m_chr[
i].m_bytes;
 
  519     uchar* xbytes = m_chr[
i].m_xbytes;
 
  520     uint& 
size = m_chr[
i].m_size;
 
  522     size = m_cs->mbminlen + urandom(m_cs->mbmaxlen - m_cs->mbminlen + 1);
 
  523     assert(m_cs->mbminlen <= size && size <= m_cs->mbmaxlen);
 
  525     if (size == m_cs->mbminlen && m_cs->mbminlen < m_cs->mbmaxlen && urandom(5) != 0)
 
  527     for (uint j = 0; j < 
size; j++) {
 
  528       bytes[j] = urandom(256);
 
  532     const char* sbytes = (
const char*)bytes;
 
  533     if ((*cs->cset->well_formed_len)(cs, sbytes, sbytes + 
size, 1, ¬_used) != size) {
 
  539     for (uint j = 1; j < 
size; j++) {
 
  540       if ((*cs->cset->well_formed_len)(cs, sbytes, sbytes + j, 1, ¬_used) == j) {
 
  550     memset(xbytes, 0, 
sizeof(xbytes));
 
  555     for (uint j = 0; j < (uint)xlen; j++) {
 
  556       if (xbytes[j] != 0) {
 
  567     for (uint j = 0; j < 
i; j++) {
 
  568       const Chr& chr = m_chr[j];
 
  569       if (chr.m_size == size && memcmp(chr.m_bytes, bytes, size) == 0) {
 
  580   bool disorder = 
true;
 
  584     for (uint i = 1; i < maxcharcount; i++) {
 
  585       uint len = 
sizeof(m_chr[
i].m_xbytes);
 
  586       if (memcmp(m_chr[i-1].m_xbytes, m_chr[i].m_xbytes, len) > 0) {
 
  588         m_chr[
i] = m_chr[i-1];
 
  595   LL3(
"inited charset " << *
this << 
" miss=" << miss1 << 
"," << miss2 << 
"," << miss3 << 
"," << miss4 << 
" bubbles=" << bubbles);
 
  604 operator<<(NdbOut& out, 
const Chs& chs)
 
  607   out << cs->name << 
"[" << cs->mbminlen << 
"-" << cs->mbmaxlen << 
"," << chs.m_xmul << 
"]";
 
  611 static Chs* cslist[maxcsnumber];
 
  616   for (uint i = 0; i < maxcsnumber; i++) {
 
  630       uint n = urandom(maxcsnumber);
 
  631       cs = get_charset(n, MYF(0));
 
  635         if (cs->state & MY_CS_HIDDEN)
 
  638         if (cs->mbmaxlen != 1 || urandom(5) == 0)
 
  643   if (cslist[cs->number] == 0)
 
  644     cslist[cs->number] = 
new Chs(cs);
 
  645   return cslist[cs->number];
 
  659   const struct Tab& m_tab;
 
  671   Col(
const struct Tab& tab, uint num, 
const char* 
name, 
bool pk, Type 
type, uint length, 
bool nullable, 
const Chs* chs);
 
  673   bool equal(
const Col& col2) 
const;
 
  674   void wellformed(
const void* addr) 
const;
 
  677 Col::Col(
const struct Tab& tab, uint num, 
const char* 
name, 
bool pk, Type 
type, uint length, 
bool nullable, 
const Chs* chs) :
 
  680   m_name(strcpy(new char [strlen(name) + 1], name)),
 
  684   m_bytelength(length * (chs == 0 ? 1 : chs->m_cs->mbmaxlen)),
 
  686       type == Unsigned ? sizeof(Uint32) :
 
  687       type == Char ? sizeof(char) :
 
  688       type == Varchar ? sizeof(char) :
 
  689       type == Longvarchar ? sizeof(char) : ~0),
 
  691       type == Unsigned ? 0 :
 
  693       type == Varchar ? 1 :
 
  694       type == Longvarchar ? 2 : ~0),
 
  695   m_bytesize(m_headsize + m_attrsize * m_bytelength),
 
  696   m_nullable(nullable),
 
  700   if (type == Varchar && m_bytelength > 255) {
 
  701     m_type = Longvarchar;
 
  713 Col::equal(
const Col& col2)
 const 
  715   return m_type == col2.m_type && m_length == col2.m_length && m_chs == col2.m_chs;
 
  719 Col::wellformed(
const void* addr)
 const 
  727       const char* src = (
const char*)addr;
 
  728       uint len = m_bytelength;
 
  731       assert((*cs->cset->well_formed_len)(cs, src, src + len, 0xffff, ¬_used) == len);
 
  737       const uchar* src = (
const uchar*)addr;
 
  738       const char* ssrc = (
const char*)src;
 
  742       assert(len <= m_bytelength);
 
  743       assert((*cs->cset->well_formed_len)(cs, ssrc + 1, ssrc + 1 + len, 0xffff, ¬_used) == len);
 
  746   case Col::Longvarchar:
 
  749       const uchar* src = (
const uchar*)addr;
 
  750       const char* ssrc = (
const char*)src;
 
  751       uint len = src[0] + (src[1] << 8);
 
  754       assert(len <= m_bytelength);
 
  755       assert((*cs->cset->well_formed_len)(cs, ssrc + 2, ssrc + 2 + len, 0xffff, ¬_used) == len);
 
  765 operator<<(NdbOut& out, 
const Col& col)
 
  767   out << 
"col[" << col.m_num << 
"] " << col.m_name;
 
  768   switch (col.m_type) {
 
  775       out << 
" char(" << col.m_length << 
"*" << cs->mbmaxlen << 
";" << cs->name << 
")";
 
  781       out << 
" varchar(" << col.m_length << 
"*" << cs->mbmaxlen << 
";" << cs->name << 
")";
 
  784   case Col::Longvarchar:
 
  787       out << 
" longvarchar(" << col.m_length << 
"*" << cs->mbmaxlen << 
";" << cs->name << 
")";
 
  791     out << 
"type" << (int)col.m_type;
 
  795   out << (col.m_pk ? 
" pk" : 
"");
 
  796   out << (col.m_nullable ? 
" nullable" : 
"");
 
  803   const struct ITab& m_itab;
 
  806   ICol(
const struct ITab& itab, uint num, 
const Col& col);
 
  810 ICol::ICol(
const struct ITab& itab, uint num, 
const Col& col) :
 
  822 operator<<(NdbOut& out, 
const ICol& icol)
 
  824   out << 
"icol[" << icol.m_num << 
"] " << icol.m_col;
 
  835   const struct Tab& m_tab;
 
  841   ITab(
const struct Tab& tab, 
const char* name, Type type, uint icols);
 
  843   void icoladd(uint k, 
const ICol* icolptr);
 
  846 ITab::ITab(
const struct Tab& tab, 
const char* name, Type type, uint icols) :
 
  848   m_name(strcpy(new char [strlen(name) + 1], name)),
 
  851   m_icol(new const 
ICol* [icols + 1]),
 
  854   for (uint k = 0; k <= m_icols; k++)
 
  861   for (uint i = 0; i < m_icols; i++)
 
  867 ITab::icoladd(uint k, 
const ICol* icolptr)
 
  869   assert(k == icolptr->m_num && k < m_icols && m_icol[k] == 0);
 
  871   m_keymask |= (1 << icolptr->m_col.m_num);
 
  875 operator<<(NdbOut& out, 
const ITab& itab)
 
  877   out << 
"itab " << itab.m_name << 
" icols=" << itab.m_icols;
 
  878   for (uint k = 0; k < itab.m_icols; k++) {
 
  879     const ICol& icol = *itab.m_icol[k];
 
  894   uint m_orderedindexes;
 
  898   void coladd(uint k, 
Col* colptr);
 
  899   void itabadd(uint j, 
ITab* itab);
 
  900   Tab(
const char* name, uint cols, uint itabs, uint keycol);
 
  904 Tab::Tab(
const char* name, uint cols, uint itabs, uint keycol) :
 
  905   m_name(strcpy(new char [strlen(name) + 1], name)),
 
  907   m_col(new const 
Col* [cols + 1]),
 
  910   m_itab(new const 
ITab* [itabs + 1]),
 
  915   for (uint k = 0; k <= cols; k++)
 
  917   for (uint j = 0; j <= itabs; j++)
 
  924   for (uint i = 0; i < m_cols; i++)
 
  927   for (uint i = 0; i < m_itabs; i++)
 
  933 Tab::coladd(uint k, 
Col* colptr)
 
  935   assert(k == colptr->m_num && k < m_cols && m_col[k] == 0);
 
  938     m_pkmask |= (1 << k);
 
  942 Tab::itabadd(uint j, 
ITab* itabptr)
 
  944   assert(j < m_itabs && m_itab[j] == 0 && itabptr != 0);
 
  946   if (itabptr->m_type == ITab::OrderedIndex)
 
  953 operator<<(NdbOut& out, 
const Tab& tab)
 
  955   out << 
"tab " << tab.m_name << 
" cols=" << tab.m_cols;
 
  956   for (uint k = 0; k < tab.m_cols; k++) {
 
  957     const Col& col =  *tab.m_col[k];
 
  960   for (uint i = 0; i < tab.m_itabs; i++) {
 
  961     if (tab.m_itab[i] == 0)
 
  963     const ITab& itab = *tab.m_itab[
i];
 
  971 static const Tab** tablist = 0;
 
  972 static uint tabcount = 0;
 
  977   for (uint j = 0; j < tabcount; j++) {
 
  978     const Tab* t = tablist[j];
 
  981     assert(t->m_cols != 0 && t->m_col != 0);
 
  982     for (uint k = 0; k < t->m_cols; k++) {
 
  983       const Col* c = t->m_col[k];
 
  984       assert(c != 0 && c->m_num == k);
 
  985       assert(!(c->m_pk && c->m_nullable));
 
  987     assert(t->m_col[t->m_cols] == 0);
 
  989       assert(t->m_keycol < t->m_cols);
 
  990       const Col* c = t->m_col[t->m_keycol];
 
  991       assert(c->m_pk && c->m_type == Col::Unsigned);
 
  993     assert(t->m_itabs != 0 && t->m_itab != 0);
 
  994     for (uint i = 0; i < t->m_itabs; i++) {
 
  995       const ITab* x = t->m_itab[
i];
 
  998       assert(x != 0 && x->m_icols != 0 && x->m_icol != 0);
 
  999       for (uint k = 0; k < x->m_icols; k++) {
 
 1000         const ICol* c = x->m_icol[k];
 
 1001         assert(c != 0 && c->m_num == k && c->m_col.m_num < t->m_cols);
 
 1002         if (x->m_type == ITab::UniqueHashIndex) {
 
 1003           assert(!c->m_col.m_nullable);
 
 1007     assert(t->m_itab[t->m_itabs] == 0);
 
 1012 makebuiltintables(
Par par)
 
 1014   LL2(
"makebuiltintables");
 
 1018     tablist = 
new const Tab* [tabcount];
 
 1019     for (uint j = 0; j < tabcount; j++) {
 
 1023     for (uint j = 0; j < tabcount; j++) {
 
 1029   if (usetable(par, 0)) {
 
 1030     Tab* t = 
new Tab(
"ti0", 5, 7, 0);
 
 1032     t->coladd(0, 
new Col(*t, 0, 
"a", 1, Col::Unsigned, 1, 0, 0));
 
 1033     t->coladd(1, 
new Col(*t, 1, 
"b", 0, Col::Unsigned, 1, 1, 0));
 
 1034     t->coladd(2, 
new Col(*t, 2, 
"c", 0, Col::Unsigned, 1, 0, 0));
 
 1035     t->coladd(3, 
new Col(*t, 3, 
"d", 0, Col::Unsigned, 1, 1, 0));
 
 1036     t->coladd(4, 
new Col(*t, 4, 
"e", 0, Col::Unsigned, 1, 0, 0));
 
 1037     if (useindex(par, 0)) {
 
 1039       ITab* x = 
new ITab(*t, 
"ti0x0", ITab::OrderedIndex, 1);
 
 1040       x->icoladd(0, 
new ICol(*x, 0, *t->m_col[0]));
 
 1043     if (useindex(par, 1)) {
 
 1045       ITab* x = 
new ITab(*t, 
"ti0x1", ITab::OrderedIndex, 1);
 
 1046       x->icoladd(0, 
new ICol(*x, 0, *t->m_col[1]));
 
 1049     if (useindex(par, 2)) {
 
 1051       ITab* x = 
new ITab(*t, 
"ti0x2", ITab::OrderedIndex, 2);
 
 1052       x->icoladd(0, 
new ICol(*x, 0, *t->m_col[1]));
 
 1053       x->icoladd(1, 
new ICol(*x, 1, *t->m_col[2]));
 
 1056     if (useindex(par, 3)) {
 
 1058       ITab* x = 
new ITab(*t, 
"ti0x3", ITab::OrderedIndex, 4);
 
 1059       x->icoladd(0, 
new ICol(*x, 0, *t->m_col[1]));
 
 1060       x->icoladd(1, 
new ICol(*x, 1, *t->m_col[4]));
 
 1061       x->icoladd(2, 
new ICol(*x, 2, *t->m_col[2]));
 
 1062       x->icoladd(3, 
new ICol(*x, 3, *t->m_col[3]));
 
 1065     if (useindex(par, 4)) {
 
 1067       ITab* x = 
new ITab(*t, 
"ti0z4", ITab::UniqueHashIndex, 2);
 
 1068       x->icoladd(0, 
new ICol(*x, 0, *t->m_col[0]));
 
 1069       x->icoladd(1, 
new ICol(*x, 1, *t->m_col[2]));
 
 1072     if (useindex(par, 5)) {
 
 1074       ITab* x = 
new ITab(*t, 
"ti0z5", ITab::UniqueHashIndex, 2);
 
 1075       x->icoladd(0, 
new ICol(*x, 0, *t->m_col[0]));
 
 1076       x->icoladd(1, 
new ICol(*x, 1, *t->m_col[4]));
 
 1082   if (usetable(par, 1)) {
 
 1083     Tab* t = 
new Tab(
"ti1", 5, 7, 1);
 
 1085     t->coladd(0, 
new Col(*t, 0, 
"a", 0, Col::Unsigned, 1, 0, 0));
 
 1086     t->coladd(1, 
new Col(*t, 1, 
"b", 1, Col::Unsigned, 1, 0, 0));
 
 1087     t->coladd(2, 
new Col(*t, 2, 
"c", 0, Col::Varchar, 20, 0, getcs(par)));
 
 1088     t->coladd(3, 
new Col(*t, 3, 
"d", 0, Col::Char, 5, 0, getcs(par)));
 
 1089     t->coladd(4, 
new Col(*t, 4, 
"e", 0, Col::Longvarchar, 5, 1, getcs(par)));
 
 1090     if (useindex(par, 0)) {
 
 1092       ITab* x = 
new ITab(*t, 
"ti1x0", ITab::OrderedIndex, 1);
 
 1093       x->icoladd(0, 
new ICol(*x, 0, *t->m_col[1]));
 
 1096     if (useindex(par, 1)) {
 
 1098       ITab* x = 
new ITab(*t, 
"ti1x1", ITab::OrderedIndex, 2);
 
 1099       x->icoladd(0, 
new ICol(*x, 0, *t->m_col[2]));
 
 1100       x->icoladd(1, 
new ICol(*x, 1, *t->m_col[0]));
 
 1103     if (useindex(par, 2)) {
 
 1105       ITab* x = 
new ITab(*t, 
"ti1x2", ITab::OrderedIndex, 1);
 
 1106       x->icoladd(0, 
new ICol(*x, 0, *t->m_col[3]));
 
 1109     if (useindex(par, 3)) {
 
 1111       ITab* x = 
new ITab(*t, 
"ti1x3", ITab::OrderedIndex, 4);
 
 1112       x->icoladd(0, 
new ICol(*x, 0, *t->m_col[4]));
 
 1113       x->icoladd(1, 
new ICol(*x, 1, *t->m_col[3]));
 
 1114       x->icoladd(2, 
new ICol(*x, 2, *t->m_col[2]));
 
 1115       x->icoladd(3, 
new ICol(*x, 3, *t->m_col[1]));
 
 1118     if (useindex(par, 4)) {
 
 1120       ITab* x = 
new ITab(*t, 
"ti1z4", ITab::UniqueHashIndex, 2);
 
 1121       x->icoladd(0, 
new ICol(*x, 0, *t->m_col[0]));
 
 1122       x->icoladd(1, 
new ICol(*x, 1, *t->m_col[1]));
 
 1125     if (useindex(par, 5)) {
 
 1127       ITab* x = 
new ITab(*t, 
"ti1z5", ITab::UniqueHashIndex, 3);
 
 1128       x->icoladd(0, 
new ICol(*x, 0, *t->m_col[1]));
 
 1129       x->icoladd(1, 
new ICol(*x, 1, *t->m_col[2]));
 
 1130       x->icoladd(2, 
new ICol(*x, 2, *t->m_col[3]));
 
 1136   if (usetable(par, 2)) {
 
 1137     Tab* t = 
new Tab(
"ti2", 5, 7, 2);
 
 1139     t->coladd(0, 
new Col(*t, 0, 
"a", 1, Col::Char, 31, 0, getcs(par)));
 
 1140     t->coladd(1, 
new Col(*t, 1, 
"b", 0, Col::Char, 4, 1, getcs(par)));
 
 1141     t->coladd(2, 
new Col(*t, 2, 
"c", 1, Col::Unsigned, 1, 0, 0));
 
 1142     t->coladd(3, 
new Col(*t, 3, 
"d", 1, Col::Varchar, 128, 0, getcs(par)));
 
 1143     t->coladd(4, 
new Col(*t, 4, 
"e", 0, Col::Varchar, 7, 0, getcs(par)));
 
 1144     if (useindex(par, 0)) {
 
 1146       ITab* x = 
new ITab(*t, 
"ti2x0", ITab::OrderedIndex, 3);
 
 1147       x->icoladd(0, 
new ICol(*x, 0, *t->m_col[0]));
 
 1148       x->icoladd(1, 
new ICol(*x, 1, *t->m_col[2]));
 
 1149       x->icoladd(2, 
new ICol(*x, 2, *t->m_col[3]));
 
 1152     if (useindex(par, 1)) {
 
 1154       ITab* x = 
new ITab(*t, 
"ti2x1", ITab::OrderedIndex, 5);
 
 1155       x->icoladd(0, 
new ICol(*x, 0, *t->m_col[4]));
 
 1156       x->icoladd(1, 
new ICol(*x, 1, *t->m_col[3]));
 
 1157       x->icoladd(2, 
new ICol(*x, 2, *t->m_col[2]));
 
 1158       x->icoladd(3, 
new ICol(*x, 3, *t->m_col[1]));
 
 1159       x->icoladd(4, 
new ICol(*x, 4, *t->m_col[0]));
 
 1162     if (useindex(par, 2)) {
 
 1164       ITab* x = 
new ITab(*t, 
"ti2x2", ITab::OrderedIndex, 1);
 
 1165       x->icoladd(0, 
new ICol(*x, 0, *t->m_col[3]));
 
 1168     if (useindex(par, 3)) {
 
 1170       ITab* x = 
new ITab(*t, 
"ti2x3", ITab::OrderedIndex, 1);
 
 1171       x->icoladd(0, 
new ICol(*x, 0, *t->m_col[1]));
 
 1174     if (useindex(par, 4)) {
 
 1176       ITab* x = 
new ITab(*t, 
"ti2z4", ITab::UniqueHashIndex, 2);
 
 1177       x->icoladd(0, 
new ICol(*x, 0, *t->m_col[0]));
 
 1178       x->icoladd(1, 
new ICol(*x, 1, *t->m_col[2]));
 
 1181     if (useindex(par, 5)) {
 
 1183       ITab* x = 
new ITab(*t, 
"ti2z5", ITab::UniqueHashIndex, 4);
 
 1184       x->icoladd(0, 
new ICol(*x, 0, *t->m_col[0]));
 
 1185       x->icoladd(1, 
new ICol(*x, 1, *t->m_col[2]));
 
 1186       x->icoladd(2, 
new ICol(*x, 2, *t->m_col[3]));
 
 1187       x->icoladd(3, 
new ICol(*x, 3, *t->m_col[4]));
 
 1209   enum ScanMode { ScanNo = 0, Committed, Latest, Exclusive };
 
 1210   ScanMode m_scanmode;
 
 1218   char m_errname[100];
 
 1220     m_ndb(0), m_dic(0), m_tx(0), m_txid(0), m_op(0), m_indexop(0),
 
 1221     m_scanop(0), m_indexscanop(0), m_scanfilter(0),
 
 1222     m_scanmode(ScanNo), m_errtype(ErrNone) {}
 
 1228   void connect(
const Con& con);
 
 1230   int startTransaction();
 
 1231   int getNdbOperation(
const Tab& tab);
 
 1232   int getNdbIndexOperation1(
const ITab& itab, 
const Tab& tab);
 
 1233   int getNdbIndexOperation(
const ITab& itab, 
const Tab& tab);
 
 1234   int getNdbScanOperation(
const Tab& tab);
 
 1235   int getNdbIndexScanOperation1(
const ITab& itab, 
const Tab& tab);
 
 1236   int getNdbIndexScanOperation(
const ITab& itab, 
const Tab& tab);
 
 1237   int getNdbScanFilter();
 
 1238   int equal(
int num, 
const char* addr);
 
 1240   int setValue(
int num, 
const char* addr);
 
 1241   int setBound(
int num, 
int type, 
const void* value);
 
 1242   int beginFilter(
int group);
 
 1244   int setFilter(
int num, 
int cond, 
const void* value, uint len);
 
 1245   int execute(ExecType et);
 
 1246   int execute(ExecType et, uint& err);
 
 1247   int readTuple(
Par par);
 
 1248   int readTuples(
Par par);
 
 1249   int readIndexTuples(
Par par);
 
 1251   int nextScanResult(
bool fetchAllowed);
 
 1252   int nextScanResult(
bool fetchAllowed, uint& err);
 
 1253   int updateScanTuple(
Con& con2);
 
 1254   int deleteScanTuple(
Con& con2);
 
 1256   void closeTransaction();
 
 1257   const char* errname(uint err);
 
 1258   void printerror(NdbOut& out);
 
 1265   m_ndb = 
new Ndb(g_ncc, 
"TEST_DB");
 
 1266   CHKCON(m_ndb->
init() == 0, *
this);
 
 1268   m_tx = 0, m_txid = 0, m_op = 0;
 
 1273 Con::connect(
const Con& con)
 
 1283   m_ndb = 0, m_dic = 0, m_tx = 0, m_txid = 0, m_op = 0;
 
 1287 Con::startTransaction()
 
 1298 Con::getNdbOperation(
const Tab& tab)
 
 1306 Con::getNdbIndexOperation1(
const ITab& itab, 
const Tab& tab)
 
 1314 Con::getNdbIndexOperation(
const ITab& itab, 
const Tab& tab)
 
 1319     if (getNdbIndexOperation1(itab, tab) == 0)
 
 1322     NdbSleep_MilliSleep(100);
 
 1328 Con::getNdbScanOperation(
const Tab& tab)
 
 1336 Con::getNdbIndexScanOperation1(
const ITab& itab, 
const Tab& tab)
 
 1344 Con::getNdbIndexScanOperation(
const ITab& itab, 
const Tab& tab)
 
 1349     if (getNdbIndexScanOperation1(itab, tab) == 0)
 
 1352     NdbSleep_MilliSleep(100);
 
 1358 Con::getNdbScanFilter()
 
 1360   assert(m_tx != 0 && m_scanop != 0);
 
 1361   delete m_scanfilter;
 
 1367 Con::equal(
int num, 
const char* addr)
 
 1369   assert(m_tx != 0 && m_op != 0);
 
 1370   CHKCON(m_op->
equal(num, addr) == 0, *
this);
 
 1377   assert(m_tx != 0 && m_op != 0);
 
 1378   CHKCON((rec = m_op->
getValue(num, 0)) != 0, *
this);
 
 1383 Con::setValue(
int num, 
const char* addr)
 
 1385   assert(m_tx != 0 && m_op != 0);
 
 1386   CHKCON(m_op->
setValue(num, addr) == 0, *
this);
 
 1391 Con::setBound(
int num, 
int type, 
const void* value)
 
 1393   assert(m_tx != 0 && m_indexscanop != 0);
 
 1394   CHKCON(m_indexscanop->
setBound(num, type, value) == 0, *
this);
 
 1399 Con::beginFilter(
int group)
 
 1401   assert(m_tx != 0 && m_scanfilter != 0);
 
 1409   assert(m_tx != 0 && m_scanfilter != 0);
 
 1410   CHKCON(m_scanfilter->
end() == 0, *
this);
 
 1415 Con::setFilter(
int num, 
int cond, 
const void* value, uint len)
 
 1417   assert(m_tx != 0 && m_scanfilter != 0);
 
 1423 Con::execute(ExecType et)
 
 1426   CHKCON(m_tx->
execute(et) == 0, *
this);
 
 1431 Con::execute(ExecType et, uint& err)
 
 1433   int ret = execute(et);
 
 1435   const uint errin = err;
 
 1438     if (m_errtype == ErrDeadlock && (errin & ErrDeadlock)) {
 
 1439       LL3(
"caught deadlock");
 
 1443     if (m_errtype == ErrNospace && (errin & ErrNospace)) {
 
 1444       LL3(
"caught nospace");
 
 1454 Con::readTuple(
Par par)
 
 1456   assert(m_tx != 0 && m_op != 0);
 
 1458   CHKCON(m_op->
readTuple(lm) == 0, *
this);
 
 1463 Con::readTuples(
Par par)
 
 1465   assert(m_tx != 0 && m_scanop != 0);
 
 1468     scan_flags |= NdbScanOperation::SF_TupScan;
 
 1469   CHKCON(m_scanop->
readTuples(par.m_lockmode, scan_flags, par.m_scanpar, par.m_scanbatch) == 0, *
this);
 
 1474 Con::readIndexTuples(
Par par)
 
 1476   assert(m_tx != 0 && m_indexscanop != 0);
 
 1479     scan_flags |= NdbScanOperation::SF_OrderBy;
 
 1480   if (par.m_descending)
 
 1481     scan_flags |= NdbScanOperation::SF_Descending;
 
 1482   if (par.m_multiRange)
 
 1484     scan_flags |= NdbScanOperation::SF_MultiRange;
 
 1485     scan_flags |= NdbScanOperation::SF_ReadRangeNo;
 
 1487   CHKCON(m_indexscanop->
readTuples(par.m_lockmode, scan_flags, par.m_scanpar, par.m_scanbatch) == 0, *
this);
 
 1494   CHKCON(m_tx->
execute(NoCommit) == 0, *
this);
 
 1499 Con::nextScanResult(
bool fetchAllowed)
 
 1502   assert(m_scanop != 0);
 
 1503   CHKCON((ret = m_scanop->
nextResult(fetchAllowed)) != -1, *
this);
 
 1504   assert(ret == 0 || ret == 1 || (!fetchAllowed && ret == 2));
 
 1509 Con::nextScanResult(
bool fetchAllowed, uint& err)
 
 1511   int ret = nextScanResult(fetchAllowed);
 
 1513   const uint errin = err;
 
 1516     if (m_errtype == ErrDeadlock && (errin & ErrDeadlock)) {
 
 1517       LL3(
"caught deadlock");
 
 1522   CHK(ret == 0 || ret == 1 || (!fetchAllowed && ret == 2));
 
 1527 Con::updateScanTuple(
Con& con2)
 
 1529   assert(con2.m_tx != 0);
 
 1531   con2.m_txid = m_txid; 
 
 1536 Con::deleteScanTuple(
Con& con2)
 
 1538   assert(con2.m_tx != 0);
 
 1540   con2.m_txid = m_txid; 
 
 1547   assert(m_scanop != 0);
 
 1549   m_scanop = 0, m_indexscanop = 0;
 
 1554 Con::closeTransaction()
 
 1556   assert(m_ndb != 0 && m_tx != 0);
 
 1558   m_tx = 0, m_txid = 0, m_op = 0;
 
 1559   m_scanop = 0, m_indexscanop = 0;
 
 1563 Con::errname(uint err)
 
 1565   sprintf(m_errname, 
"0x%x", err);
 
 1566   if (err & ErrDeadlock)
 
 1567     strcat(m_errname, 
",deadlock");
 
 1568   if (err & ErrNospace)
 
 1569     strcat(m_errname, 
",nospace");
 
 1574 Con::printerror(NdbOut& out)
 
 1576   m_errtype = ErrOther;
 
 1582       LL0(++any << 
" ndb: error " << m_ndb->
getNdbError());
 
 1583       die += (code == g_opt.m_die);
 
 1586       LL0(++any << 
" dic: error " << m_dic->
getNdbError());
 
 1587       die += (code == g_opt.m_die);
 
 1591         LL0(++any << 
" con: error " << m_tx->
getNdbError());
 
 1592         die += (code == g_opt.m_die);
 
 1594         if (code == 266 || code == 274 || code == 296 || code == 297 || code == 499 || code == 631)
 
 1595           m_errtype = ErrDeadlock;
 
 1596         if (code == 826 || code == 827 || code == 902)
 
 1597           m_errtype = ErrNospace;
 
 1600         LL0(++any << 
" op : error " << m_op->
getNdbError());
 
 1601         die += (code == g_opt.m_die);
 
 1606     LL0(
"failed but no NDB error code");
 
 1618 invalidateindex(
Par par, 
const ITab& itab)
 
 1620   Con& con = par.con();
 
 1621   const Tab& tab = par.tab();
 
 1627 invalidateindex(
Par par)
 
 1629   const Tab& tab = par.tab();
 
 1630   for (uint i = 0; i < tab.m_itabs; i++) {
 
 1631     if (tab.m_itab[i] == 0)
 
 1633     const ITab& itab = *tab.m_itab[
i];
 
 1634     invalidateindex(par, itab);
 
 1640 invalidatetable(
Par par)
 
 1642   Con& con = par.con();
 
 1643   const Tab& tab = par.tab();
 
 1644   invalidateindex(par);
 
 1652   Con& con = par.con();
 
 1653   const Tab& tab = par.tab();
 
 1655   if (con.m_dic->
getTable(tab.m_name) == 0) {
 
 1657     LL4(
"no table " << tab.m_name);
 
 1659     LL3(
"drop table " << tab.m_name);
 
 1660     CHKCON(con.m_dic->
dropTable(tab.m_name) == 0, con);
 
 1667 createtable(
Par par)
 
 1669   Con& con = par.con();
 
 1670   const Tab& tab = par.tab();
 
 1671   LL3(
"create table " << tab.m_name);
 
 1675     t.setFragmentType(par.m_fragtype);
 
 1677   if (par.m_nologging) {
 
 1678     t.setLogging(
false);
 
 1680   for (uint k = 0; k < tab.m_cols; k++) {
 
 1681     const Col& col = *tab.m_col[k];
 
 1684     c.setLength(col.m_bytelength); 
 
 1685     c.setPrimaryKey(col.m_pk);
 
 1686     c.setNullable(col.m_nullable);
 
 1688         c.setCharset(col.m_chs->m_cs);
 
 1698 dropindex(
Par par, 
const ITab& itab)
 
 1700   Con& con = par.con();
 
 1701   const Tab& tab = par.tab();
 
 1703   if (con.m_dic->
getIndex(itab.m_name, tab.m_name) == 0) {
 
 1705     LL4(
"no index " << itab.m_name);
 
 1707     LL3(
"drop index " << itab.m_name);
 
 1708     CHKCON(con.m_dic->
dropIndex(itab.m_name, tab.m_name) == 0, con);
 
 1717   const Tab& tab = par.tab();
 
 1718   for (uint i = 0; i < tab.m_itabs; i++) {
 
 1719     if (tab.m_itab[i] == 0)
 
 1721     const ITab& itab = *tab.m_itab[
i];
 
 1722     CHK(dropindex(par, itab) == 0);
 
 1728 createindex(
Par par, 
const ITab& itab)
 
 1730   Con& con = par.con();
 
 1731   const Tab& tab = par.tab();
 
 1732   LL3(
"create index " << itab.m_name);
 
 1735   x.setTable(tab.m_name);
 
 1737   if (par.m_nologging || itab.m_type == ITab::OrderedIndex) {
 
 1738     x.setLogging(
false);
 
 1740   for (uint k = 0; k < itab.m_icols; k++) {
 
 1741     const ICol& icol = *itab.m_icol[k];
 
 1742     const Col& col = icol.m_col;
 
 1743     x.addColumnName(col.m_name);
 
 1752 createindex(
Par par)
 
 1754   const Tab& tab = par.tab();
 
 1755   for (uint i = 0; i < tab.m_itabs; i++) {
 
 1756     if (tab.m_itab[i] == 0)
 
 1758     const ITab& itab = *tab.m_itab[
i];
 
 1759     CHK(createindex(par, itab) == 0);
 
 1774   uchar* m_longvarchar;
 
 1780   void copy(
const Val& val2);
 
 1781   void copy(
const void* addr);
 
 1782   const void* dataaddr() 
const;
 
 1783   void calc(
Par par, uint i);
 
 1784   void calckey(
Par par, uint i);
 
 1785   void calckeychars(
Par par, uint i, uint& n, uchar* 
buf);
 
 1786   void calcnokey(
Par par);
 
 1787   void calcnokeychars(
Par par, uint& n, uchar* 
buf);
 
 1789   int setval(
Par par) 
const;
 
 1790   int setval(
Par par, 
const ICol& icol) 
const;
 
 1792   int cmp(
Par par, 
const Val& val2) 
const;
 
 1793   int cmpchars(
Par par, 
const uchar* buf1, uint len1, 
const uchar* buf2, uint len2) 
const;
 
 1794   int verify(
Par par, 
const Val& val2) 
const;
 
 1796   Val& operator=(
const Val& val2);
 
 1800 operator<<(NdbOut& out, 
const Val& val);
 
 1804 Val::Val(
const Col& col) :
 
 1807   switch (col.m_type) {
 
 1809     m_uint32 = 0x7e7e7e7e;
 
 1812     m_char = 
new uchar [col.m_bytelength];
 
 1813     memset(m_char, 0x7e, col.m_bytelength);
 
 1816     m_varchar = 
new uchar [1 + col.m_bytelength];
 
 1817     memset(m_char, 0x7e, 1 + col.m_bytelength);
 
 1819   case Col::Longvarchar:
 
 1820     m_longvarchar = 
new uchar [2 + col.m_bytelength];
 
 1821     memset(m_char, 0x7e, 2 + col.m_bytelength);
 
 1831   const Col& col = m_col;
 
 1832   switch (col.m_type) {
 
 1839     delete [] m_varchar;
 
 1841   case Col::Longvarchar:
 
 1842     delete [] m_longvarchar;
 
 1851 Val::copy(
const Val& val2)
 
 1853   const Col& col = m_col;
 
 1854   const Col& col2 = val2.m_col;
 
 1855   assert(col.m_type == col2.m_type && col.m_length == col2.m_length);
 
 1860   copy(val2.dataaddr());
 
 1864 Val::copy(
const void* addr)
 
 1866   const Col& col = m_col;
 
 1867   switch (col.m_type) {
 
 1869     m_uint32 = *(
const Uint32*)addr;
 
 1872     memcpy(m_char, addr, col.m_bytelength);
 
 1875     memcpy(m_varchar, addr, 1 + col.m_bytelength);
 
 1877   case Col::Longvarchar:
 
 1878     memcpy(m_longvarchar, addr, 2 + col.m_bytelength);
 
 1888 Val::dataaddr()
 const 
 1890   const Col& col = m_col;
 
 1891   switch (col.m_type) {
 
 1898   case Col::Longvarchar:
 
 1899     return m_longvarchar;
 
 1908 Val::calc(
Par par, uint i)
 
 1910   const Col& col = m_col;
 
 1911   col.m_pk ? calckey(par, i) : calcnokey(par);
 
 1913     col.wellformed(dataaddr());
 
 1917 Val::calckey(
Par par, uint i)
 
 1919   const Col& col = m_col;
 
 1921   switch (col.m_type) {
 
 1927       const Chs* chs = col.m_chs;
 
 1930       calckeychars(par, i, n, m_char);
 
 1932       (*cs->cset->fill)(cs, (
char*)&m_char[
n], col.m_bytelength - 
n, 0x20);
 
 1938       calckeychars(par, i, n, m_varchar + 1);
 
 1941       memset(&m_varchar[1 + n], 0, col.m_bytelength - n);
 
 1944   case Col::Longvarchar:
 
 1947       calckeychars(par, i, n, m_longvarchar + 2);
 
 1949       m_longvarchar[0] = (n & 0xff);
 
 1950       m_longvarchar[1] = (n >> 8);
 
 1951       memset(&m_longvarchar[2 + n], 0, col.m_bytelength - n);
 
 1961 Val::calckeychars(
Par par, uint i, uint& n, uchar* 
buf)
 
 1963   const Col& col = m_col;
 
 1964   const Chs* chs = col.m_chs;
 
 1967   while (len < col.m_length) {
 
 1968     if (i % (1 + n) == 0) {
 
 1971     const Chr& chr = chs->m_chr[i % maxcharcount];
 
 1972     assert(n + chr.m_size <= col.m_bytelength);
 
 1973     memcpy(buf + n, chr.m_bytes, chr.m_size);
 
 1980 Val::calcnokey(
Par par)
 
 1982   const Col& col = m_col;
 
 1984   if (col.m_nullable && urandom(100) < par.m_pctnull) {
 
 1988   int r = irandom((par.m_pctrange * par.m_range) / 100);
 
 1989   if (par.m_bdir != 0 && urandom(10) != 0) {
 
 1990     if ((r < 0 && par.m_bdir > 0) || (r > 0 && par.m_bdir < 0))
 
 1993   uint v = par.m_range + r;
 
 1994   switch (col.m_type) {
 
 2000       const Chs* chs = col.m_chs;
 
 2003       calcnokeychars(par, n, m_char);
 
 2005       (*cs->cset->fill)(cs, (
char*)&m_char[
n], col.m_bytelength - 
n, 0x20);
 
 2011       calcnokeychars(par, n, m_varchar + 1);
 
 2014       memset(&m_varchar[1 + n], 0, col.m_bytelength - n);
 
 2017   case Col::Longvarchar:
 
 2020       calcnokeychars(par, n, m_longvarchar + 2);
 
 2022       m_longvarchar[0] = (n & 0xff);
 
 2023       m_longvarchar[1] = (n >> 8);
 
 2024       memset(&m_longvarchar[2 + n], 0, col.m_bytelength - n);
 
 2034 Val::calcnokeychars(
Par par, uint& n, uchar* buf)
 
 2036   const Col& col = m_col;
 
 2037   const Chs* chs = col.m_chs;
 
 2040   while (len < col.m_length) {
 
 2041     if (urandom(1 + col.m_bytelength) == 0) {
 
 2044     uint half = maxcharcount / 2;
 
 2045     int r = irandom((par.m_pctrange * half) / 100);
 
 2046     if (par.m_bdir != 0 && urandom(10) != 0) {
 
 2047       if ((r < 0 && par.m_bdir > 0) || (r > 0 && par.m_bdir < 0))
 
 2051     assert(i < maxcharcount);
 
 2052     const Chr& chr = chs->m_chr[
i];
 
 2053     assert(n + chr.m_size <= col.m_bytelength);
 
 2054     memcpy(buf + n, chr.m_bytes, chr.m_size);
 
 2063 Val::setval(
Par par)
 const 
 2065   Con& con = par.con();
 
 2066   const Col& col = m_col;
 
 2069     const char* addr = (
const char*)dataaddr();
 
 2070     LL5(
"setval pk [" << col << 
"] " << *
this);
 
 2071     CHK(con.equal(col.m_num, addr) == 0);
 
 2073     const char* addr = !m_null ? (
const char*)dataaddr() : 0;
 
 2074     LL5(
"setval non-pk [" << col << 
"] " << *
this);
 
 2075     CHK(con.setValue(col.m_num, addr) == 0);
 
 2081 Val::setval(
Par par, 
const ICol& icol)
 const 
 2083   Con& con = par.con();
 
 2085   const char* addr = (
const char*)dataaddr();
 
 2086   LL5(
"setval key [" << icol << 
"] " << *
this);
 
 2087   CHK(con.equal(icol.m_num, addr) == 0);
 
 2094 Val::cmp(
Par par, 
const Val& val2)
 const 
 2096   const Col& col = m_col;
 
 2097   const Col& col2 = val2.m_col;
 
 2098   assert(col.equal(col2));
 
 2099   if (m_null || val2.m_null) {
 
 2107   col.wellformed(dataaddr());
 
 2108   col.wellformed(val2.dataaddr());
 
 2110   switch (col.m_type) {
 
 2113       if (m_uint32 < val2.m_uint32)
 
 2115       if (m_uint32 > val2.m_uint32)
 
 2122       uint len = col.m_bytelength;
 
 2123       return cmpchars(par, m_char, len, val2.m_char, len);
 
 2128       uint len1 = m_varchar[0];
 
 2129       uint len2 = val2.m_varchar[0];
 
 2130       return cmpchars(par, m_varchar + 1, len1, val2.m_varchar + 1, len2);
 
 2133   case Col::Longvarchar:
 
 2135       uint len1 = m_longvarchar[0] + (m_longvarchar[1] << 8);
 
 2136       uint len2 = val2.m_longvarchar[0] + (val2.m_longvarchar[1] << 8);
 
 2137       return cmpchars(par, m_longvarchar + 2, len1, val2.m_longvarchar + 2, len2);
 
 2148 Val::cmpchars(
Par par, 
const uchar* buf1, uint len1, 
const uchar* buf2, uint len2)
 const 
 2150   const Col& col = m_col;
 
 2151   const Chs* chs = col.m_chs;
 
 2154   if (!par.m_collsp) {
 
 2155     uchar x1[maxxmulsize * NDB_MAX_TUPLE_SIZE];
 
 2156     uchar x2[maxxmulsize * NDB_MAX_TUPLE_SIZE];
 
 2158     uint len = maxxmulsize * col.m_bytelength;
 
 2161     assert(n1 != -1 && n1 == n2);
 
 2162     k = memcmp(x1, x2, n1);
 
 2164     k = (*cs->coll->strnncollsp)(cs, buf1, len1, buf2, len2, 
false);
 
 2166   return k < 0 ? -1 : k > 0 ? +1 : 0;
 
 2170 Val::verify(
Par par, 
const Val& val2)
 const 
 2172   CHK(cmp(par, val2) == 0);
 
 2179 printstring(NdbOut& out, 
const uchar* str, uint len, 
bool showlen)
 
 2181   char buf[4 * NDB_MAX_TUPLE_SIZE];
 
 2185     sprintf(p, 
"%u:", len);
 
 2188   for (uint i = 0; i < len; i++) {
 
 2193     } 
else if (0x20 <= c && c <= 0x7e) {
 
 2197       *p++ = hexstr[c >> 4];
 
 2198       *p++ = hexstr[c & 15];
 
 2207 operator<<(NdbOut& out, 
const Val& val)
 
 2209   const Col& col = val.m_col;
 
 2214   switch (col.m_type) {
 
 2216     out << val.m_uint32;
 
 2220       uint len = col.m_bytelength;
 
 2221       printstring(out, val.m_char, len, 
false);
 
 2226       uint len = val.m_varchar[0];
 
 2227       printstring(out, val.m_varchar + 1, len, 
true);
 
 2230   case Col::Longvarchar:
 
 2232       uint len = val.m_longvarchar[0] + (val.m_longvarchar[1] << 8);
 
 2233       printstring(out, val.m_longvarchar + 2, len, 
true);
 
 2237     out << 
"type" << col.m_type;
 
 2264     OpREAD = 16 | 32 | 64
 
 2273   void copy(
const Row& row2, 
bool copy_bi);
 
 2274   void copyval(
const Row& row2, uint colmask = ~0);
 
 2275   void calc(
Par par, uint i, uint colmask = ~0);
 
 2277   int setval(
Par par, uint colmask = ~0);
 
 2278   int setval(
Par par, 
const ITab& itab);
 
 2279   int insrow(
Par par);
 
 2280   int updrow(
Par par);
 
 2281   int updrow(
Par par, 
const ITab& itab);
 
 2282   int delrow(
Par par);
 
 2283   int delrow(
Par par, 
const ITab& itab);
 
 2284   int selrow(
Par par);
 
 2285   int selrow(
Par par, 
const ITab& itab);
 
 2286   int setrow(
Par par);
 
 2288   int cmp(
Par par, 
const Row& row2) 
const;
 
 2289   int cmp(
Par par, 
const Row& row2, 
const ITab& itab) 
const;
 
 2290   int verify(
Par par, 
const Row& row2, 
bool pkonly) 
const;
 
 2292   Row& operator=(
const Row& row2);
 
 2296 operator<<(NdbOut& out, 
const Row* rowp);
 
 2299 operator<<(NdbOut& out, 
const Row& row);
 
 2303 Row::Row(
const Tab& tab) :
 
 2306   m_val = 
new Val* [tab.m_cols];
 
 2307   for (uint k = 0; k < tab.m_cols; k++) {
 
 2308     const Col& col = *tab.m_col[k];
 
 2309     m_val[k] = 
new Val(col);
 
 2319   const Tab& tab = m_tab;
 
 2320   for (uint k = 0; k < tab.m_cols; k++) {
 
 2328 Row::copy(
const Row& row2, 
bool copy_bi)
 
 2330   const Tab& tab = m_tab;
 
 2334   m_txid = row2.m_txid;
 
 2336   if (copy_bi && row2.m_bi != 0) {
 
 2337     m_bi = 
new Row(tab);
 
 2338     m_bi->copy(*row2.m_bi, copy_bi);
 
 2343 Row::copyval(
const Row& row2, uint colmask)
 
 2345   const Tab& tab = m_tab;
 
 2346   assert(&tab == &row2.m_tab);
 
 2347   for (uint k = 0; k < tab.m_cols; k++) {
 
 2348     Val& val = *m_val[k];
 
 2349     const Val& val2 = *row2.m_val[k];
 
 2350     if ((1 << k) & colmask)
 
 2356 Row::calc(
Par par, uint i, uint colmask)
 
 2358   const Tab& tab = m_tab;
 
 2359   for (uint k = 0; k < tab.m_cols; k++) {
 
 2360     if ((1 << k) & colmask) {
 
 2361       Val& val = *m_val[k];
 
 2370 Row::setval(
Par par, uint colmask)
 
 2372   const Tab& tab = m_tab;
 
 2373   Rsq rsq(tab.m_cols);
 
 2374   for (uint k = 0; k < tab.m_cols; k++) {
 
 2375     uint k2 = rsq.next();
 
 2376     if ((1 << k2) & colmask) {
 
 2377       const Val& val = *m_val[k2];
 
 2378       CHK(val.setval(par) == 0);
 
 2385 Row::setval(
Par par, 
const ITab& itab)
 
 2387   Rsq rsq(itab.m_icols);
 
 2388   for (uint k = 0; k < itab.m_icols; k++) {
 
 2389     uint k2 = rsq.next();
 
 2390     const ICol& icol = *itab.m_icol[k2];
 
 2391     const Col& col = icol.m_col;
 
 2393     const Val& val = *m_val[m];
 
 2394     CHK(val.setval(par, icol) == 0);
 
 2400 Row::insrow(
Par par)
 
 2402   Con& con = par.con();
 
 2403   const Tab& tab = m_tab;
 
 2404   CHK(con.getNdbOperation(tab) == 0);
 
 2406   CHK(setval(par, tab.m_pkmask) == 0);
 
 2407   CHK(setval(par, ~tab.m_pkmask) == 0);
 
 2408   assert(m_st == StUndef);
 
 2411   m_txid = con.m_txid;
 
 2416 Row::updrow(
Par par)
 
 2418   Con& con = par.con();
 
 2419   const Tab& tab = m_tab;
 
 2420   CHK(con.getNdbOperation(tab) == 0);
 
 2422   CHK(setval(par, tab.m_pkmask) == 0);
 
 2423   CHK(setval(par, ~tab.m_pkmask) == 0);
 
 2424   assert(m_st == StUndef);
 
 2427   m_txid = con.m_txid;
 
 2432 Row::updrow(
Par par, 
const ITab& itab)
 
 2434   Con& con = par.con();
 
 2435   const Tab& tab = m_tab;
 
 2436   assert(itab.m_type == ITab::UniqueHashIndex && &itab.m_tab == &tab);
 
 2437   CHK(con.getNdbIndexOperation(itab, tab) == 0);
 
 2439   CHK(setval(par, itab) == 0);
 
 2440   CHK(setval(par, ~tab.m_pkmask) == 0);
 
 2441   assert(m_st == StUndef);
 
 2444   m_txid = con.m_txid;
 
 2449 Row::delrow(
Par par)
 
 2451   Con& con = par.con();
 
 2452   const Tab& tab = m_tab;
 
 2453   CHK(con.getNdbOperation(m_tab) == 0);
 
 2455   CHK(setval(par, tab.m_pkmask) == 0);
 
 2456   assert(m_st == StUndef);
 
 2459   m_txid = con.m_txid;
 
 2464 Row::delrow(
Par par, 
const ITab& itab)
 
 2466   Con& con = par.con();
 
 2467   const Tab& tab = m_tab;
 
 2468   assert(itab.m_type == ITab::UniqueHashIndex && &itab.m_tab == &tab);
 
 2469   CHK(con.getNdbIndexOperation(itab, tab) == 0);
 
 2471   CHK(setval(par, itab) == 0);
 
 2472   assert(m_st == StUndef);
 
 2475   m_txid = con.m_txid;
 
 2480 Row::selrow(
Par par)
 
 2482   Con& con = par.con();
 
 2483   const Tab& tab = m_tab;
 
 2484   CHK(con.getNdbOperation(m_tab) == 0);
 
 2485   CHKCON(con.readTuple(par) == 0, con);
 
 2486   CHK(setval(par, tab.m_pkmask) == 0);
 
 2492 Row::selrow(
Par par, 
const ITab& itab)
 
 2494   Con& con = par.con();
 
 2495   const Tab& tab = m_tab;
 
 2496   assert(itab.m_type == ITab::UniqueHashIndex && &itab.m_tab == &tab);
 
 2497   CHK(con.getNdbIndexOperation(itab, tab) == 0);
 
 2498   CHKCON(con.readTuple(par) == 0, con);
 
 2499   CHK(setval(par, itab) == 0);
 
 2505 Row::setrow(
Par par)
 
 2507   Con& con = par.con();
 
 2508   const Tab& tab = m_tab;
 
 2509   CHK(setval(par, ~tab.m_pkmask) == 0);
 
 2510   assert(m_st == StUndef);
 
 2513   m_txid = con.m_txid;
 
 2520 Row::cmp(
Par par, 
const Row& row2)
 const 
 2522   const Tab& tab = m_tab;
 
 2523   assert(&tab == &row2.m_tab);
 
 2525   for (uint k = 0; k < tab.m_cols; k++) {
 
 2526     const Val& val = *m_val[k];
 
 2527     const Val& val2 = *row2.m_val[k];
 
 2528     if ((c = val.cmp(par, val2)) != 0)
 
 2535 Row::cmp(
Par par, 
const Row& row2, 
const ITab& itab)
 const 
 2537   const Tab& tab = m_tab;
 
 2539   for (uint i = 0; i < itab.m_icols; i++) {
 
 2540     const ICol& icol = *itab.m_icol[
i];
 
 2541     const Col& col = icol.m_col;
 
 2543     assert(k < tab.m_cols);
 
 2544     const Val& val = *m_val[k];
 
 2545     const Val& val2 = *row2.m_val[k];
 
 2546     if ((c = val.cmp(par, val2)) != 0)
 
 2553 Row::verify(
Par par, 
const Row& row2, 
bool pkonly)
 const 
 2555   const Tab& tab = m_tab;
 
 2556   const Row& row1 = *
this;
 
 2557   assert(&row1.m_tab == &row2.m_tab);
 
 2558   for (uint k = 0; k < tab.m_cols; k++) {
 
 2559     const Col& col = row1.m_val[k]->m_col;
 
 2560     if (!pkonly || col.m_pk) {
 
 2561       const Val& val1 = *row1.m_val[k];
 
 2562       const Val& val2 = *row2.m_val[k];
 
 2563       CHK(val1.verify(par, val2) == 0);
 
 2572 operator<<(NdbOut& out, 
const Row::St st)
 
 2574   if (st == Row::StUndef)
 
 2576   else if (st == Row::StDefine)
 
 2578   else if (st == Row::StPrepare)
 
 2580   else if (st == Row::StCommit)
 
 2588 operator<<(NdbOut& out, 
const Row::Op op)
 
 2590   if (op == Row::OpNone)
 
 2592   else if (op == Row::OpIns)
 
 2594   else if (op == Row::OpUpd)
 
 2596   else if (op == Row::OpDel)
 
 2598   else if (op == Row::OpRead)
 
 2600   else if (op == Row::OpReadEx)
 
 2602   else if (op == Row::OpReadCom)
 
 2610 operator<<(NdbOut& out, 
const Row* rowp)
 
 2620 operator<<(NdbOut& out, 
const Row& row)
 
 2622   const Tab& tab = row.m_tab;
 
 2624   for (uint i = 0; i < tab.m_cols; i++) {
 
 2627     out << *row.m_val[
i];
 
 2629   out << 
" " << row.m_st;
 
 2630   out << 
" " << row.m_op;
 
 2631   out << 
" " << HEX(row.m_txid);
 
 2633     out << 
" " << row.m_bi;
 
 2648   Set(
const Tab& tab, uint rows);
 
 2651   bool compat(
Par par, uint i, 
const Row::Op op) 
const;
 
 2653   void copyval(uint i, uint colmask = ~0); 
 
 2654   void calc(
Par par, uint i, uint colmask = ~0);
 
 2656   const Row* getrow(uint i, 
bool dirty = 
false) 
const;
 
 2657   int setrow(uint i, 
const Row* src, 
bool force=
false);
 
 2659   void post(
Par par, ExecType et);
 
 2661   int insrow(
Par par, uint i);
 
 2662   int updrow(
Par par, uint i);
 
 2663   int updrow(
Par par, 
const ITab& itab, uint i);
 
 2664   int delrow(
Par par, uint i);
 
 2665   int delrow(
Par par, 
const ITab& itab, uint i);
 
 2666   int selrow(
Par par, 
const Row& keyrow);
 
 2667   int selrow(
Par par, 
const ITab& itab, 
const Row& keyrow);
 
 2668   int setrow(
Par par, uint i);
 
 2669   int getval(
Par par);
 
 2670   int getkey(
Par par, uint* i);
 
 2671   int putval(uint i, 
bool force, uint n = ~0);
 
 2673   void sort(
Par par, 
const ITab& itab);
 
 2674   int verify(
Par par, 
const Set& set2, 
bool pkonly, 
bool dirty = 
false) 
const;
 
 2675   int verifyorder(
Par par, 
const ITab& itab, 
bool descending) 
const;
 
 2679     NdbMutex_Lock(m_mutex);
 
 2681   void unlock()
 const {
 
 2682     NdbMutex_Unlock(m_mutex);
 
 2685   void sort(
Par par, 
const ITab& itab, uint lo, uint hi);
 
 2686   Set& operator=(
const Set& set2);
 
 2691 Set::Set(
const Tab& tab, uint rows) :
 
 2695   m_row = 
new Row* [m_rows];
 
 2696   for (uint i = 0; i < m_rows; i++) {
 
 2699   m_rowkey = 
new uint [m_rows];
 
 2700   for (uint n = 0; n < m_rows; n++) {
 
 2703   m_keyrow = 
new Row(tab);
 
 2705   for (uint k = 0; k < tab.m_cols; k++) {
 
 2708   m_mutex = NdbMutex_Create();
 
 2709   assert(m_mutex != 0);
 
 2714   for (uint i = 0; i < m_rows; i++) {
 
 2721   NdbMutex_Destroy(m_mutex);
 
 2727   for (uint i = 0; i < m_rows; i++) {
 
 2734 Set::compat(
Par par, uint i, 
const Row::Op op)
 const 
 2736   Con& con = par.con();
 
 2740     const Row* rowp = getrow(i);
 
 2742       ret = op == Row::OpIns;
 
 2746     const Row& row = *rowp;
 
 2747     if (!(op & Row::OpREAD)) {
 
 2748       if (row.m_st == Row::StDefine || row.m_st == Row::StPrepare) {
 
 2749         assert(row.m_op & Row::OpDML);
 
 2750         assert(row.m_txid != 0);
 
 2751         if (con.m_txid != row.m_txid) {
 
 2756         if (row.m_op != Row::OpDel) {
 
 2757           ret = op == Row::OpUpd || op == Row::OpDel;
 
 2761         ret = op == Row::OpIns;
 
 2765       if (row.m_st == Row::StCommit) {
 
 2766         assert(row.m_op == Row::OpNone);
 
 2767         assert(row.m_txid == 0);
 
 2768         ret = op == Row::OpUpd || op == Row::OpDel;
 
 2773     if (op & Row::OpREAD) {
 
 2775         con.m_txid != row.m_txid &&
 
 2777       const Row* rowp2 = getrow(i, dirty);
 
 2778       if (rowp2 == 0 || rowp2->m_op == Row::OpDel) {
 
 2788   LL4(
"compat ret=" << ret << 
" place=" << place);
 
 2789   assert(ret == 
false || ret == 
true);
 
 2796   const Tab& tab = m_tab;
 
 2799   m_row[
i] = 
new Row(tab);
 
 2800   Row& row = *m_row[
i];
 
 2807 Set::copyval(uint i, uint colmask)
 
 2809   assert(m_row[i] != 0);
 
 2810   Row& row = *m_row[
i];
 
 2811   assert(row.m_bi != 0);
 
 2812   row.copyval(*row.m_bi, colmask);
 
 2816 Set::calc(
Par par, uint i, uint colmask)
 
 2818   assert(m_row[i] != 0);
 
 2819   Row& row = *m_row[
i];
 
 2820   row.calc(par, i, colmask);
 
 2827   for (uint i = 0; i < m_rows; i++) {
 
 2835 Set::getrow(uint i, 
bool dirty)
 const 
 2838   const Row* rowp = m_row[
i];
 
 2841       bool b1 = rowp->m_op == Row::OpNone;
 
 2842       bool b2 = rowp->m_st == Row::StCommit;
 
 2845         assert(rowp->m_bi == 0);
 
 2855 Set::setrow(uint i, 
const Row* src, 
bool force)
 
 2862   Row* newRow= 
new Row(src->m_tab);
 
 2863   newRow->copy(*src, 
true);
 
 2871 Set::post(
Par par, ExecType et)
 
 2874   Con& con = par.con();
 
 2875   assert(con.m_txid != 0);
 
 2877   for (i = 0; i < m_rows; i++) {
 
 2878     Row* rowp = m_row[
i];
 
 2880       LL5(
"skip " << i << 
" " << rowp);
 
 2883     if (rowp->m_st == Row::StCommit) {
 
 2884       assert(rowp->m_op == Row::OpNone);
 
 2885       assert(rowp->m_txid == 0);
 
 2886       assert(rowp->m_bi == 0);
 
 2887       LL5(
"skip committed " << i << 
" " << rowp);
 
 2890     assert(rowp->m_st == Row::StDefine || rowp->m_st == Row::StPrepare);
 
 2891     assert(rowp->m_txid != 0);
 
 2892     if (con.m_txid != rowp->m_txid) {
 
 2893       LL5(
"skip txid " << i << 
" " << HEX(con.m_txid) << 
" " << rowp);
 
 2897     assert(rowp->m_op & Row::OpDML);
 
 2898     LL4(
"post BEFORE " << rowp);
 
 2899     if (et == NoCommit) {
 
 2900       if (rowp->m_st == Row::StDefine) {
 
 2901         rowp->m_st = Row::StPrepare;
 
 2902         Row* bi = rowp->m_bi;
 
 2903         while (bi != 0 && bi->m_st == Row::StDefine) {
 
 2904           bi->m_st = Row::StPrepare;
 
 2908     } 
else if (et == Commit) {
 
 2909       if (rowp->m_op != Row::OpDel) {
 
 2910         rowp->m_st = Row::StCommit;
 
 2911         rowp->m_op = Row::OpNone;
 
 2919     } 
else if (et == Rollback) {
 
 2920       while (rowp != 0 && rowp->m_st != Row::StCommit) {
 
 2930     LL4(
"post AFTER " << rowp);
 
 2937 Set::insrow(
Par par, uint i)
 
 2939   assert(m_row[i] != 0);
 
 2940   Row& row = *m_row[
i];
 
 2941   CHK(row.insrow(par) == 0);
 
 2946 Set::updrow(
Par par, uint i)
 
 2948   assert(m_row[i] != 0);
 
 2949   Row& row = *m_row[
i];
 
 2950   CHK(row.updrow(par) == 0);
 
 2955 Set::updrow(
Par par, 
const ITab& itab, uint i)
 
 2957   assert(m_row[i] != 0);
 
 2958   Row& row = *m_row[
i];
 
 2959   CHK(row.updrow(par, itab) == 0);
 
 2964 Set::delrow(
Par par, uint i)
 
 2966   assert(m_row[i] != 0);
 
 2967   Row& row = *m_row[
i];
 
 2968   CHK(row.delrow(par) == 0);
 
 2973 Set::delrow(
Par par, 
const ITab& itab, uint i)
 
 2975   assert(m_row[i] != 0);
 
 2976   Row& row = *m_row[
i];
 
 2977   CHK(row.delrow(par, itab) == 0);
 
 2982 Set::selrow(
Par par, 
const Row& keyrow)
 
 2984   const Tab& tab = par.tab();
 
 2985   LL5(
"selrow " << tab.m_name << 
" keyrow " << keyrow);
 
 2986   m_keyrow->copyval(keyrow, tab.m_pkmask);
 
 2987   CHK(m_keyrow->selrow(par) == 0);
 
 2988   CHK(getval(par) == 0);
 
 2993 Set::selrow(
Par par, 
const ITab& itab, 
const Row& keyrow)
 
 2995   LL5(
"selrow " << itab.m_name << 
" keyrow " << keyrow);
 
 2996   m_keyrow->copyval(keyrow, itab.m_keymask);
 
 2997   CHK(m_keyrow->selrow(par, itab) == 0);
 
 2998   CHK(getval(par) == 0);
 
 3003 Set::setrow(
Par par, uint i)
 
 3005   assert(m_row[i] != 0);
 
 3006   CHK(m_row[i]->setrow(par) == 0);
 
 3011 Set::getval(
Par par)
 
 3013   Con& con = par.con();
 
 3014   const Tab& tab = m_tab;
 
 3015   Rsq rsq1(tab.m_cols);
 
 3016   for (uint k = 0; k < tab.m_cols; k++) {
 
 3017     uint k2 = rsq1.next();
 
 3018     CHK(con.getValue(k2, m_rec[k2]) == 0);
 
 3024 Set::getkey(
Par par, uint* i)
 
 3026   const Tab& tab = m_tab;
 
 3027   uint k = tab.m_keycol;
 
 3028   assert(m_rec[k] != 0);
 
 3029   const char* aRef = m_rec[k]->
aRef();
 
 3030   Uint32 key = *(
const Uint32*)aRef;
 
 3031   LL5(
"getkey: " << key);
 
 3038 Set::putval(uint i, 
bool force, uint n)
 
 3040   const Tab& tab = m_tab;
 
 3041   LL4(
"putval key=" << i << 
" row=" << n << 
" old=" << m_row[i]);
 
 3043   if (m_row[i] != 0) {
 
 3048   m_row[
i] = 
new Row(tab);
 
 3049   Row& row = *m_row[
i];
 
 3050   for (uint k = 0; k < tab.m_cols; k++) {
 
 3051     Val& val = *row.m_val[k];
 
 3058     const char* aRef = m_rec[k]->
aRef();
 
 3073 Set::sort(
Par par, 
const ITab& itab)
 
 3076     sort(par, itab, 0, m_rows - 1);
 
 3080 Set::sort(
Par par, 
const ITab& itab, uint lo, uint hi)
 
 3082   assert(lo < m_rows && hi < m_rows && lo <= hi);
 
 3083   Row* 
const p = m_row[lo];
 
 3087     while (i < j && m_row[j]->cmp(par, *p, itab) >= 0)
 
 3090       m_row[
i] = m_row[j];
 
 3093     while (i < j && m_row[i]->cmp(par, *p, itab) <= 0)
 
 3096       m_row[j] = m_row[
i];
 
 3102     sort(par, itab, lo, i - 1);
 
 3104     sort(par, itab, i + 1, hi);
 
 3113 Set::verify(
Par par, 
const Set& set2, 
bool pkonly, 
bool dirty)
 const 
 3115   const Set& set1 = *
this;
 
 3116   assert(&set1.m_tab == &set2.m_tab && set1.m_rows == set2.m_rows);
 
 3117   LL3(
"verify dirty:" << dirty);
 
 3118   for (uint i = 0; i < set1.m_rows; i++) {
 
 3120     const Row* row1p = set1.getrow(i, dirty);
 
 3121     const Row* row2p = set2.getrow(i);
 
 3130       Row::Op op1 = row1p->m_op;
 
 3131       if (op1 != Row::OpDel) {
 
 3135         } 
else if (row1p->verify(par, *row2p, pkonly) == -1) {
 
 3139       } 
else if (row2p != 0) {
 
 3145       LL1(
"verify " << i << 
" failed at " << place);
 
 3146       LL1(
"row1 " << row1p);
 
 3147       LL1(
"row2 " << row2p);
 
 3155 Set::verifyorder(
Par par, 
const ITab& itab, 
bool descending)
 const 
 3157   for (uint n = 0; n < m_rows; n++) {
 
 3158     uint i2 = m_rowkey[
n];
 
 3159     if (i2 == (uint) ~0)
 
 3163     uint i1 = m_rowkey[n - 1];
 
 3164     assert(m_row[i1] != 0 && m_row[i2] != 0);
 
 3165     const Row& row1 = *m_row[i1];
 
 3166     const Row& row2 = *m_row[i2];
 
 3169       ok= (row1.cmp(par, row2, itab) <= 0);
 
 3171       ok= (row1.cmp(par, row2, itab) >= 0);
 
 3175       LL1(
"verifyorder " << n << 
" failed");
 
 3176       LL1(
"row1 " << row1);
 
 3177       LL1(
"row2 " << row2);
 
 3188 operator<<(NdbOut& out, 
const Set& 
set)
 
 3190   for (uint i = 0; i < 
set.m_rows; i++) {
 
 3191     const Row& row = *
set.m_row[
i];
 
 3206   int setbnd(
Par par) 
const;
 
 3207   int setflt(
Par par) 
const;
 
 3210 BVal::BVal(
const ICol& icol) :
 
 3217 BVal::setbnd(
Par par)
 const 
 3219   Con& con = par.con();
 
 3220   assert(g_compare_null || !m_null);
 
 3221   const char* addr = !m_null ? (
const char*)dataaddr() : 0;
 
 3222   const ICol& icol = m_icol;
 
 3223   CHK(con.setBound(icol.m_num, m_type, addr) == 0);
 
 3228 BVal::setflt(
Par par)
 const 
 3230   static uint index_bound_to_filter_bound[5] = {
 
 3237   Con& con = par.con();
 
 3238   assert(g_compare_null || !m_null);
 
 3239   const char* addr = !m_null ? (
const char*)dataaddr() : 0;
 
 3240   const ICol& icol = m_icol;
 
 3241   const Col& col = icol.m_col;
 
 3242   uint length = col.m_bytesize;
 
 3243   uint cond = index_bound_to_filter_bound[m_type];
 
 3244   CHK(con.setFilter(col.m_num, cond, addr, length) == 0);
 
 3249 operator<<(NdbOut& out, 
const BVal& bval)
 
 3251   const ICol& icol = bval.m_icol;
 
 3252   const Col& col = icol.m_col;
 
 3253   const Val& val = bval;
 
 3254   out << 
"type=" << bval.m_type;
 
 3255   out << 
" icol=" << icol.m_num;
 
 3256   out << 
" col=" << col.m_num << 
"," << col.m_name;
 
 3257   out << 
" value=" << val;
 
 3273   void calcpk(
Par par, uint i);
 
 3274   int setbnd(
Par par) 
const;
 
 3275   int setflt(
Par par) 
const;
 
 3276   void filter(
Par par, 
const Set& 
set, 
Set& set2) 
const;
 
 3279 BSet::BSet(
const Tab& tab, 
const ITab& itab) :
 
 3282   m_alloc(2 * itab.m_icols),
 
 3285   m_bval = 
new BVal* [m_alloc];
 
 3286   for (uint i = 0; i < m_alloc; i++) {
 
 3299   while (m_bvals > 0) {
 
 3309   const ITab& itab = m_itab;
 
 3310   par.m_pctrange = par.m_pctbrange;
 
 3312   for (uint k = 0; k < itab.m_icols; k++) {
 
 3313     const ICol& icol = *itab.m_icol[k];
 
 3314     for (uint i = 0; i <= 1; i++) {
 
 3315       if (m_bvals == 0 && urandom(100) == 0)
 
 3317       if (m_bvals != 0 && urandom(3) == 0)
 
 3319       assert(m_bvals < m_alloc);
 
 3321       m_bval[m_bvals++] = &bval;
 
 3322       bval.m_null = 
false;
 
 3326         sel = urandom(5 - i);
 
 3327       } 
while (strchr(par.m_bound, 
'0' + sel) == 0);
 
 3329         bval.m_type = 0 | (1 << 
i);
 
 3331         bval.m_type = 1 | (1 << 
i);
 
 3334       if (k + 1 < itab.m_icols)
 
 3336       if (!g_compare_null)
 
 3338       if (bval.m_type == 0 || bval.m_type == 1)
 
 3340       if (bval.m_type == 2 || bval.m_type == 3)
 
 3343         bval.calcnokey(par);
 
 3345           assert(m_bvals >= 2);
 
 3346           const BVal& bv1 = *m_bval[m_bvals - 2];
 
 3347           const BVal& bv2 = *m_bval[m_bvals - 1];
 
 3348           if (bv1.cmp(par, bv2) > 0 && urandom(100) != 0)
 
 3353       if (bval.m_type == 4)
 
 3360 BSet::calcpk(
Par par, uint i)
 
 3362   const ITab& itab = m_itab;
 
 3364   for (uint k = 0; k < itab.m_icols; k++) {
 
 3365     const ICol& icol = *itab.m_icol[k];
 
 3366     const Col& col = icol.m_col;
 
 3368     assert(m_bvals < m_alloc);
 
 3370     m_bval[m_bvals++] = &bval;
 
 3377 BSet::setbnd(
Par par)
 const 
 3381     for (uint j = 0; j < m_bvals; j++) {
 
 3382       uint j2 = rsq1.next();
 
 3383       const BVal& bval = *m_bval[j2];
 
 3384       CHK(bval.setbnd(par) == 0);
 
 3391 BSet::setflt(
Par par)
 const 
 3393   Con& con = par.con();
 
 3394   CHK(con.getNdbScanFilter() == 0);
 
 3398     for (uint j = 0; j < m_bvals; j++) {
 
 3399       uint j2 = rsq1.next();
 
 3400       const BVal& bval = *m_bval[j2];
 
 3401       CHK(bval.setflt(par) == 0);
 
 3404     if (urandom(5) == 0) {
 
 3405       uint j3 = urandom(m_bvals);
 
 3406       const BVal& bval = *m_bval[j3];
 
 3407       CHK(bval.setflt(par) == 0);
 
 3410   CHK(con.endFilter() == 0);
 
 3415 BSet::filter(
Par par, 
const Set& 
set, 
Set& set2)
 const 
 3417   const Tab& tab = m_tab;
 
 3418   const ITab& itab = m_itab;
 
 3419   assert(&tab == &set2.m_tab && 
set.m_rows == set2.m_rows);
 
 3420   assert(set2.count() == 0);
 
 3421   for (uint i = 0; i < 
set.m_rows; i++) {
 
 3424       if (
set.m_row[i] == 0) {
 
 3427       const Row& row = *
set.m_row[
i];
 
 3428       if (!g_store_null_key) {
 
 3430         for (uint k = 0; k < itab.m_icols; k++) {
 
 3431           const ICol& icol = *itab.m_icol[k];
 
 3432           const Col& col = icol.m_col;
 
 3433           const Val& val = *row.m_val[col.m_num];
 
 3443       for (uint j = 0; j < m_bvals; j++) {
 
 3444         const BVal& bval = *m_bval[j];
 
 3445         const ICol& icol = bval.m_icol;
 
 3446         const Col& col = icol.m_col;
 
 3447         const Val& val = *row.m_val[col.m_num];
 
 3448         int ret = bval.cmp(par, val);
 
 3449         LL5(
"cmp: ret=" << ret << 
" " << bval << 
" vs " << val);
 
 3450         if (bval.m_type == 0)
 
 3452         else if (bval.m_type == 1)
 
 3454         else if (bval.m_type == 2)
 
 3456         else if (bval.m_type == 3)
 
 3458         else if (bval.m_type == 4)
 
 3468       assert(set2.m_row[i] == 0);
 
 3469       set2.m_row[
i] = 
new Row(tab);
 
 3470       Row& row2 = *set2.m_row[
i];
 
 3471       row2.copy(row, 
true);
 
 3478 operator<<(NdbOut& out, 
const BSet& bset)
 
 3480   out << 
"bounds=" << bset.m_bvals;
 
 3481   for (uint j = 0; j < bset.m_bvals; j++) {
 
 3482     const BVal& bval = *bset.m_bval[j];
 
 3483     out << 
" [bound " << j << 
": " << bval << 
"]";
 
 3493   Con& con = par.con();
 
 3494   const Tab& tab = par.tab();
 
 3495   Set& 
set = par.set();
 
 3496   LL3(
"pkinsert " << tab.m_name);
 
 3497   CHK(con.startTransaction() == 0);
 
 3499   for (uint j = 0; j < par.m_rows; j++) {
 
 3500     uint j2 = !par.m_randomkey ? j : urandom(par.m_rows);
 
 3501     uint i = thrrow(par, j2);
 
 3503     if (!
set.compat(par, i, Row::OpIns)) {
 
 3504       LL3(
"pkinsert SKIP " << i << 
" " << 
set.getrow(i));
 
 3509       CHK(
set.insrow(par, i) == 0);
 
 3511       LL4(
"pkinsert key=" << i << 
" " << 
set.getrow(i));
 
 3514     bool lastbatch = (batch != 0 && j + 1 == par.m_rows);
 
 3515     if (batch == par.m_batch || lastbatch) {
 
 3516       uint err = par.m_catcherr;
 
 3517       ExecType et = !randompct(par.m_abortpct) ? Commit : Rollback;
 
 3518       CHK(con.execute(et, err) == 0);
 
 3520       set.post(par, !err ? et : Rollback);
 
 3523         LL1(
"pkinsert key=" << i << 
" stop on " << con.errname(err));
 
 3528         con.closeTransaction();
 
 3529         CHK(con.startTransaction() == 0);
 
 3533   con.closeTransaction();
 
 3540   Con& con = par.con();
 
 3541   const Tab& tab = par.tab();
 
 3542   Set& 
set = par.set();
 
 3543   LL3(
"pkupdate " << tab.m_name);
 
 3544   CHK(con.startTransaction() == 0);
 
 3546   for (uint j = 0; j < par.m_rows; j++) {
 
 3547     uint j2 = !par.m_randomkey ? j : urandom(par.m_rows);
 
 3548     uint i = thrrow(par, j2);
 
 3550     if (!
set.compat(par, i, Row::OpUpd)) {
 
 3551       LL3(
"pkupdate SKIP " << i << 
" " << 
set.getrow(i));
 
 3555       set.copyval(i, tab.m_pkmask);
 
 3556       set.calc(par, i, ~tab.m_pkmask);
 
 3557       CHK(
set.updrow(par, i) == 0);
 
 3559       LL4(
"pkupdate key=" << i << 
" " << 
set.getrow(i));
 
 3562     bool lastbatch = (batch != 0 && j + 1 == par.m_rows);
 
 3563     if (batch == par.m_batch || lastbatch) {
 
 3564       uint err = par.m_catcherr;
 
 3565       ExecType et = !randompct(par.m_abortpct) ? Commit : Rollback;
 
 3566       CHK(con.execute(et, err) == 0);
 
 3568       set.post(par, !err ? et : Rollback);
 
 3571         LL1(
"pkupdate key=" << i << 
": stop on " << con.errname(err));
 
 3576         con.closeTransaction();
 
 3577         CHK(con.startTransaction() == 0);
 
 3581   con.closeTransaction();
 
 3588   Con& con = par.con();
 
 3589   const Tab& tab = par.tab();
 
 3590   Set& 
set = par.set();
 
 3591   LL3(
"pkdelete " << tab.m_name);
 
 3592   CHK(con.startTransaction() == 0);
 
 3594   for (uint j = 0; j < par.m_rows; j++) {
 
 3595     uint j2 = !par.m_randomkey ? j : urandom(par.m_rows);
 
 3596     uint i = thrrow(par, j2);
 
 3598     if (!
set.compat(par, i, Row::OpDel)) {
 
 3599       LL3(
"pkdelete SKIP " << i << 
" " << 
set.getrow(i));
 
 3603       set.copyval(i, tab.m_pkmask);
 
 3604       CHK(
set.delrow(par, i) == 0);
 
 3606       LL4(
"pkdelete key=" << i << 
" " << 
set.getrow(i));
 
 3609     bool lastbatch = (batch != 0 && j + 1 == par.m_rows);
 
 3610     if (batch == par.m_batch || lastbatch) {
 
 3611       uint err = par.m_catcherr;
 
 3612       ExecType et = !randompct(par.m_abortpct) ? Commit : Rollback;
 
 3613       CHK(con.execute(et, err) == 0);
 
 3615       set.post(par, !err ? et : Rollback);
 
 3618         LL1(
"pkdelete key=" << i << 
" stop on " << con.errname(err));
 
 3623         con.closeTransaction();
 
 3624         CHK(con.startTransaction() == 0);
 
 3628   con.closeTransaction();
 
 3636   Con& con = par.con();
 
 3637   const Tab& tab = par.tab();
 
 3638   Set& 
set = par.set();
 
 3639   LL3(
"pkread " << tab.m_name << 
" verify=" << par.m_verify);
 
 3641   const Set& set1 = 
set;
 
 3642   Set set2(tab, 
set.m_rows);
 
 3643   for (uint i = 0; i < 
set.m_rows; i++) {
 
 3646     if (!
set.compat(par, i, Row::OpREAD)) {
 
 3647       LL3(
"pkread SKIP " << i << 
" " << 
set.getrow(i));
 
 3652     CHK(con.startTransaction() == 0);
 
 3653     CHK(set2.selrow(par, *set1.m_row[i]) == 0);
 
 3654     CHK(con.execute(Commit) == 0);
 
 3656     CHK(set2.getkey(par, &i2) == 0 && i == i2);
 
 3657     CHK(set2.putval(i, 
false) == 0);
 
 3658     LL4(
"row " << set2.count() << 
" " << set2.getrow(i));
 
 3659     con.closeTransaction();
 
 3662     CHK(set1.verify(par, set2, 
false) == 0);
 
 3668 pkreadfast(
Par par, uint count)
 
 3670   Con& con = par.con();
 
 3671   const Tab& tab = par.tab();
 
 3672   const Set& 
set = par.set();
 
 3673   LL3(
"pkfast " << tab.m_name);
 
 3676   for (uint j = 0; j < count; j++) {
 
 3677     uint i = urandom(
set.m_rows);
 
 3678     assert(
set.compat(par, i, Row::OpREAD));
 
 3679     CHK(con.startTransaction() == 0);
 
 3681     keyrow.calc(par, i);
 
 3682     CHK(keyrow.selrow(par) == 0);
 
 3685     CHK(con.getValue((Uint32)0, rec) == 0);
 
 3686     CHK(con.execute(Commit) == 0);
 
 3687     con.closeTransaction();
 
 3695 hashindexupdate(
Par par, 
const ITab& itab)
 
 3697   Con& con = par.con();
 
 3698   const Tab& tab = par.tab();
 
 3699   Set& 
set = par.set();
 
 3700   LL3(
"hashindexupdate " << itab.m_name);
 
 3701   CHK(con.startTransaction() == 0);
 
 3703   for (uint j = 0; j < par.m_rows; j++) {
 
 3704     uint j2 = !par.m_randomkey ? j : urandom(par.m_rows);
 
 3705     uint i = thrrow(par, j2);
 
 3707     if (!
set.compat(par, i, Row::OpUpd)) {
 
 3708       LL3(
"hashindexupdate SKIP " << i << 
" " << 
set.getrow(i));
 
 3713       uint keymask = tab.m_pkmask | itab.m_keymask;
 
 3714       set.copyval(i, keymask);
 
 3715       set.calc(par, i, ~keymask);
 
 3716       CHK(
set.updrow(par, itab, i) == 0);
 
 3718       LL4(
"hashindexupdate " << i << 
" " << 
set.getrow(i));
 
 3721     bool lastbatch = (batch != 0 && j + 1 == par.m_rows);
 
 3722     if (batch == par.m_batch || lastbatch) {
 
 3723       uint err = par.m_catcherr;
 
 3724       ExecType et = !randompct(par.m_abortpct) ? Commit : Rollback;
 
 3725       CHK(con.execute(et, err) == 0);
 
 3727       set.post(par, !err ? et : Rollback);
 
 3730         LL1(
"hashindexupdate " << i << 
" stop on " << con.errname(err));
 
 3735         con.closeTransaction();
 
 3736         CHK(con.startTransaction() == 0);
 
 3740   con.closeTransaction();
 
 3745 hashindexdelete(
Par par, 
const ITab& itab)
 
 3747   Con& con = par.con();
 
 3748   Set& 
set = par.set();
 
 3749   LL3(
"hashindexdelete " << itab.m_name);
 
 3750   CHK(con.startTransaction() == 0);
 
 3752   for (uint j = 0; j < par.m_rows; j++) {
 
 3753     uint j2 = !par.m_randomkey ? j : urandom(par.m_rows);
 
 3754     uint i = thrrow(par, j2);
 
 3756     if (!
set.compat(par, i, Row::OpDel)) {
 
 3757       LL3(
"hashindexdelete SKIP " << i << 
" " << 
set.getrow(i));
 
 3761       set.copyval(i, itab.m_keymask);
 
 3762       CHK(
set.delrow(par, itab, i) == 0);
 
 3764       LL4(
"hashindexdelete " << i << 
" " << 
set.getrow(i));
 
 3767     bool lastbatch = (batch != 0 && j + 1 == par.m_rows);
 
 3768     if (batch == par.m_batch || lastbatch) {
 
 3769       uint err = par.m_catcherr;
 
 3770       ExecType et = !randompct(par.m_abortpct) ? Commit : Rollback;
 
 3771       CHK(con.execute(et, err) == 0);
 
 3773       set.post(par, !err ? et : Rollback);
 
 3776         LL1(
"hashindexdelete " << i << 
" stop on " << con.errname(err));
 
 3781         con.closeTransaction();
 
 3782         CHK(con.startTransaction() == 0);
 
 3786   con.closeTransaction();
 
 3791 hashindexread(
Par par, 
const ITab& itab)
 
 3793   Con& con = par.con();
 
 3794   const Tab& tab = par.tab();
 
 3795   Set& 
set = par.set();
 
 3796   LL3(
"hashindexread " << itab.m_name << 
" verify=" << par.m_verify);
 
 3798   const Set& set1 = 
set;
 
 3799   Set set2(tab, 
set.m_rows);
 
 3800   for (uint i = 0; i < 
set.m_rows; i++) {
 
 3803     if (!
set.compat(par, i, Row::OpREAD)) {
 
 3804       LL3(
"hashindexread SKIP " << i << 
" " << 
set.getrow(i));
 
 3809     CHK(con.startTransaction() == 0);
 
 3810     CHK(set2.selrow(par, itab, *set1.m_row[i]) == 0);
 
 3811     CHK(con.execute(Commit) == 0);
 
 3813     CHK(set2.getkey(par, &i2) == 0 && i == i2);
 
 3814     CHK(set2.putval(i, 
false) == 0);
 
 3815     LL4(
"row " << set2.count() << 
" " << *set2.m_row[
i]);
 
 3816     con.closeTransaction();
 
 3819     CHK(set1.verify(par, set2, 
false) == 0);
 
 3826 scanreadtable(
Par par)
 
 3828   Con& con = par.con();
 
 3829   const Tab& tab = par.tab();
 
 3830   const Set& 
set = par.set();
 
 3832   const Set& set1 = 
set;
 
 3833   LL3(
"scanreadtable " << tab.m_name << 
" lockmode=" << par.m_lockmode << 
" tupscan=" << par.m_tupscan << 
" expect=" << set1.count() << 
" verify=" << par.m_verify);
 
 3834   Set set2(tab, 
set.m_rows);
 
 3835   CHK(con.startTransaction() == 0);
 
 3836   CHK(con.getNdbScanOperation(tab) == 0);
 
 3837   CHK(con.readTuples(par) == 0);
 
 3839   CHK(con.executeScan() == 0);
 
 3843     uint err = par.m_catcherr;
 
 3844     CHK((ret = con.nextScanResult(
true, err)) == 0 || ret == 1);
 
 3848       LL1(
"scanreadtable stop on " << con.errname(err));
 
 3852     CHK(set2.getkey(par, &i) == 0);
 
 3853     CHK(set2.putval(i, 
false, n) == 0);
 
 3854     LL4(
"row " << n << 
" " << *set2.m_row[i]);
 
 3857   con.closeTransaction();
 
 3859     CHK(set1.verify(par, set2, 
false) == 0);
 
 3860   LL3(
"scanreadtable " << tab.m_name << 
" done rows=" << n);
 
 3865 scanreadtablefast(
Par par, uint countcheck)
 
 3867   Con& con = par.con();
 
 3868   const Tab& tab = par.tab();
 
 3869   LL3(
"scanfast " << tab.m_name);
 
 3870   CHK(con.startTransaction() == 0);
 
 3871   CHK(con.getNdbScanOperation(tab) == 0);
 
 3872   CHK(con.readTuples(par) == 0);
 
 3875   CHK(con.getValue((Uint32)0, rec) == 0);
 
 3876   CHK(con.executeScan() == 0);
 
 3880     CHK((ret = con.nextScanResult(
true)) == 0 || ret == 1);
 
 3885   con.closeTransaction();
 
 3886   CHK(count == countcheck);
 
 3892 calcscanbounds(
Par par, 
const ITab& itab, 
BSet& bset, 
const Set& 
set, 
Set& set1)
 
 3896     bset.filter(par, 
set, set1);
 
 3897     uint n = set1.count();
 
 3899     if (0 < n && n < 
set.m_rows)
 
 3901     if (urandom(5) == 0)
 
 3908 scanreadindex(
Par par, 
const ITab& itab, 
BSet& bset, 
bool calc)
 
 3910   Con& con = par.con();
 
 3911   const Tab& tab = par.tab();
 
 3912   const Set& 
set = par.set();
 
 3913   Set set1(tab, 
set.m_rows);
 
 3915     calcscanbounds(par, itab, bset, 
set, set1);
 
 3917     bset.filter(par, 
set, set1);
 
 3919   LL3(
"scanreadindex " << itab.m_name << 
" " << bset << 
" lockmode=" << par.m_lockmode << 
" expect=" << set1.count() << 
" ordered=" << par.m_ordered << 
" descending=" << par.m_descending << 
" verify=" << par.m_verify);
 
 3920   Set set2(tab, 
set.m_rows);
 
 3921   CHK(con.startTransaction() == 0);
 
 3922   CHK(con.getNdbIndexScanOperation(itab, tab) == 0);
 
 3923   CHK(con.readIndexTuples(par) == 0);
 
 3924   CHK(bset.setbnd(par) == 0);
 
 3926   CHK(con.executeScan() == 0);
 
 3930     uint err = par.m_catcherr;
 
 3931     CHK((ret = con.nextScanResult(
true, err)) == 0 || ret == 1);
 
 3935       LL1(
"scanreadindex stop on " << con.errname(err));
 
 3939     CHK(set2.getkey(par, &i) == 0);
 
 3940     CHK(set2.putval(i, par.m_dups, n) == 0);
 
 3941     LL4(
"key " << i << 
" row " << n << 
" " << *set2.m_row[i]);
 
 3944   con.closeTransaction();
 
 3946     CHK(set1.verify(par, set2, 
false) == 0);
 
 3948       CHK(set2.verifyorder(par, itab, par.m_descending) == 0);
 
 3950   LL3(
"scanreadindex " << itab.m_name << 
" done rows=" << n);
 
 3956 scanreadindexmrr(
Par par, 
const ITab& itab, 
int numBsets)
 
 3958   Con& con = par.con();
 
 3959   const Tab& tab = par.tab();
 
 3960   const Set& 
set = par.set();
 
 3967   Set** expectedResults;
 
 3968   Set** actualResults;
 
 3971   CHK((boundSets= (
BSet**) malloc(numBsets * 
sizeof(
BSet*))) != 0);
 
 3972   CHK((expectedResults= (
Set**) malloc(numBsets * 
sizeof(
Set*))) != 0);
 
 3973   CHK((actualResults= (
Set**) malloc(numBsets * 
sizeof(
Set*))) != 0);
 
 3974   CHK((setSizes= (uint*) malloc(numBsets * 
sizeof(uint))) != 0);
 
 3976   for (
int n=0; n < numBsets; n++)
 
 3978     CHK((boundSets[n]= 
new BSet(tab, itab)) != NULL );
 
 3979     CHK((expectedResults[n]= 
new Set(tab, 
set.m_rows)) != NULL);
 
 3980     CHK((actualResults[n]= 
new Set(tab, 
set.m_rows)) != NULL);
 
 3983     Set& results= *expectedResults[
n];
 
 3987       calcscanbounds(par, itab, *boundSets[n], 
set, results);
 
 3988     } 
while ((*boundSets[n]).m_bvals == 0);
 
 3992   LL3(
"scanreadindexmrr " << itab.m_name << 
" ranges= " << numBsets << 
" lockmode=" << par.m_lockmode << 
" ordered=" << par.m_ordered << 
" descending=" << par.m_descending << 
" verify=" << par.m_verify);
 
 3993   Set set2(tab, 
set.m_rows);
 
 3995   par.m_multiRange= 
true;
 
 3996   CHK(con.startTransaction() == 0);
 
 3997   CHK(con.getNdbIndexScanOperation(itab, tab) == 0);
 
 3998   CHK(con.readIndexTuples(par) == 0);
 
 4000   for (
int n=0; n < numBsets; n++)
 
 4002     CHK(boundSets[n]->setbnd(par) == 0);
 
 4006       LL1(
"end_of_bound error : " << con.m_indexscanop->
getNdbError().
code);
 
 4011   CHK(con.executeScan() == 0);
 
 4012   int rows_received= 0;
 
 4015     uint err = par.m_catcherr;
 
 4016     CHK((ret = con.nextScanResult(
true, err)) == 0 || ret == 1);
 
 4020       LL1(
"scanreadindexmrr stop on " << con.errname(err));
 
 4025     CHK(set2.getkey(par, &i) == 0);
 
 4026     CHK(set2.putval(i, 
false, -1) == 0);
 
 4030     CHK(rangeNum < numBsets);
 
 4031     CHK(set2.m_row[i] != NULL);
 
 4033     CHK(setSizes[rangeNum] == actualResults[rangeNum]->count());
 
 4034     int rowNum= setSizes[rangeNum];
 
 4035     setSizes[rangeNum] ++;
 
 4036     CHK((uint) rowNum < set2.m_rows);
 
 4037     actualResults[rangeNum]->m_row[
i]= set2.m_row[
i];
 
 4038     actualResults[rangeNum]->m_rowkey[rowNum]= 
i;
 
 4040     LL4(
"range " << rangeNum << 
" key " << i << 
" row " << rowNum << 
" " << *set2.m_row[i]);
 
 4043   con.closeTransaction();
 
 4050     LL4(
"Verifying " << numBsets << 
" sets, " << rows_received << 
" rows");
 
 4051     for (
int n=0; n < numBsets; n++)
 
 4053       LL5(
"Set " << n << 
" of " << expectedResults[n]->count() << 
" rows");
 
 4054       CHK(expectedResults[n]->verify(par, *actualResults[n], 
false) == 0);
 
 4057         LL5(
"Verifying ordering");
 
 4058         CHK(actualResults[n]->verifyorder(par, itab, par.m_descending) == 0);
 
 4064   for (
int n=0; n < numBsets; n++)
 
 4066     boundSets[
n]->reset();
 
 4067     delete boundSets[
n];
 
 4068     delete expectedResults[
n];
 
 4069     delete actualResults[
n];
 
 4073   free(expectedResults);
 
 4074   free(actualResults);
 
 4077   LL3(
"scanreadindexmrr " << itab.m_name << 
" done rows=" << rows_received);
 
 4082 scanreadindexfast(
Par par, 
const ITab& itab, 
const BSet& bset, uint countcheck)
 
 4084   Con& con = par.con();
 
 4085   const Tab& tab = par.tab();
 
 4086   LL3(
"scanfast " << itab.m_name << 
" " << bset);
 
 4088   CHK(con.startTransaction() == 0);
 
 4089   CHK(con.getNdbIndexScanOperation(itab, tab) == 0);
 
 4090   CHK(con.readIndexTuples(par) == 0);
 
 4091   CHK(bset.setbnd(par) == 0);
 
 4094   CHK(con.getValue((Uint32)0, rec) == 0);
 
 4095   CHK(con.executeScan() == 0);
 
 4099     CHK((ret = con.nextScanResult(
true)) == 0 || ret == 1);
 
 4104   con.closeTransaction();
 
 4105   CHK(count == countcheck);
 
 4110 scanreadfilter(
Par par, 
const ITab& itab, 
BSet& bset, 
bool calc)
 
 4112   Con& con = par.con();
 
 4113   const Tab& tab = par.tab();
 
 4114   const Set& 
set = par.set();
 
 4115   Set set1(tab, 
set.m_rows);
 
 4117     calcscanbounds(par, itab, bset, 
set, set1);
 
 4119     bset.filter(par, 
set, set1);
 
 4121   LL3(
"scanfilter " << itab.m_name << 
" " << bset << 
" lockmode=" << par.m_lockmode << 
" expect=" << set1.count() << 
" verify=" << par.m_verify);
 
 4122   Set set2(tab, 
set.m_rows);
 
 4123   CHK(con.startTransaction() == 0);
 
 4124   CHK(con.getNdbScanOperation(tab) == 0);
 
 4125   CHK(con.readTuples(par) == 0);
 
 4126   CHK(bset.setflt(par) == 0);
 
 4128   CHK(con.executeScan() == 0);
 
 4132     uint err = par.m_catcherr;
 
 4133     CHK((ret = con.nextScanResult(
true, err)) == 0 || ret == 1);
 
 4137       LL1(
"scanfilter stop on " << con.errname(err));
 
 4141     CHK(set2.getkey(par, &i) == 0);
 
 4142     CHK(set2.putval(i, par.m_dups, n) == 0);
 
 4143     LL4(
"key " << i << 
" row " << n << 
" " << *set2.m_row[i]);
 
 4146   con.closeTransaction();
 
 4148     CHK(set1.verify(par, set2, 
false) == 0);
 
 4150   LL3(
"scanfilter " << itab.m_name << 
" done rows=" << n);
 
 4155 scanreadindex(
Par par, 
const ITab& itab)
 
 4157   const Tab& tab = par.tab();
 
 4158   for (uint i = 0; i < par.m_ssloop; i++) {
 
 4159     if (itab.m_type == ITab::OrderedIndex) {
 
 4160       BSet bset(tab, itab);
 
 4161       CHK(scanreadfilter(par, itab, bset, 
true) == 0);
 
 4163       if (randompct(g_opt.m_pctmrr))
 
 4164         CHK(scanreadindexmrr(par, 
 
 4166                              1+urandom(g_opt.m_mrrmaxrng-1)) == 0);
 
 4168         CHK(scanreadindex(par, itab, bset, 
true) == 0);
 
 4175 scanreadindex(
Par par)
 
 4177   const Tab& tab = par.tab();
 
 4178   for (uint i = 0; i < tab.m_itabs; i++) {
 
 4179     if (tab.m_itab[i] == 0)
 
 4181     const ITab& itab = *tab.m_itab[
i];
 
 4182     if (itab.m_type == ITab::OrderedIndex) {
 
 4183       CHK(scanreadindex(par, itab) == 0);
 
 4185       CHK(hashindexread(par, itab) == 0);
 
 4193 scanreadall(
Par par)
 
 4195   CHK(scanreadtable(par) == 0);
 
 4196   CHK(scanreadindex(par) == 0);
 
 4204 timescantable(
Par par)
 
 4207   CHK(scanreadtablefast(par, par.m_totrows) == 0);
 
 4208   par.tmr().off(par.set().m_rows);
 
 4213 timescanpkindex(
Par par)
 
 4215   const Tab& tab = par.tab();
 
 4216   const ITab& itab = *tab.m_itab[0];    
 
 4217   BSet bset(tab, itab);
 
 4219   CHK(scanreadindexfast(par, itab, bset, par.m_totrows) == 0);
 
 4220   par.tmr().off(par.set().m_rows);
 
 4225 timepkreadtable(
Par par)
 
 4228   uint count = par.m_samples;
 
 4230     count = par.m_totrows;
 
 4231   CHK(pkreadfast(par, count) == 0);
 
 4232   par.tmr().off(count);
 
 4237 timepkreadindex(
Par par)
 
 4239   const Tab& tab = par.tab();
 
 4240   const ITab& itab = *tab.m_itab[0];    
 
 4241   BSet bset(tab, itab);
 
 4242   uint count = par.m_samples;
 
 4244     count = par.m_totrows;
 
 4246   for (uint j = 0; j < count; j++) {
 
 4247     uint i = urandom(par.m_totrows);
 
 4248     bset.calcpk(par, i);
 
 4249     CHK(scanreadindexfast(par, itab, bset, 1) == 0);
 
 4251   par.tmr().off(count);
 
 4258 scanupdatetable(
Par par)
 
 4260   Con& con = par.con();
 
 4261   const Tab& tab = par.tab();
 
 4262   Set& 
set = par.set();
 
 4263   LL3(
"scanupdatetable " << tab.m_name);
 
 4264   Set set2(tab, 
set.m_rows);
 
 4266   CHK(con.startTransaction() == 0);
 
 4267   CHK(con.getNdbScanOperation(tab) == 0);
 
 4268   CHK(con.readTuples(par) == 0);
 
 4270   CHK(con.executeScan() == 0);
 
 4275   CHK(con2.startTransaction() == 0);
 
 4279     uint32 err = par.m_catcherr;
 
 4280     CHK((ret = con.nextScanResult(
true, err)) != -1);
 
 4284       LL1(
"scanupdatetable [scan] stop on " << con.errname(err));
 
 4287     if (par.m_scanstop != 0 && urandom(par.m_scanstop) == 0) {
 
 4293       CHK(set2.getkey(par, &i) == 0);
 
 4295       if (!
set.compat(par, i, Row::OpUpd)) {
 
 4296         LL3(
"scanupdatetable SKIP " << i << 
" " << 
set.getrow(i));
 
 4298         CHKTRY(set2.putval(i, 
false) == 0, 
set.unlock());
 
 4299         CHKTRY(con.updateScanTuple(con2) == 0, 
set.unlock());
 
 4303         set.calc(par, i, ~tab.m_pkmask);
 
 4304         CHKTRY(
set.setrow(par2, i) == 0, 
set.unlock());
 
 4305         LL4(
"scanupdatetable " << i << 
" " << 
set.getrow(i));
 
 4309       CHK((ret = con.nextScanResult(
false)) != -1);
 
 4310       bool lastbatch = (batch != 0 && ret != 0);
 
 4311       if (batch == par.m_batch || lastbatch) {
 
 4312         uint err = par.m_catcherr;
 
 4313         ExecType et = Commit;
 
 4314         CHK(con2.execute(et, err) == 0);
 
 4316         set.post(par, !err ? et : Rollback);
 
 4319           LL1(
"scanupdatetable [update] stop on " << con2.errname(err));
 
 4322         LL4(
"scanupdatetable committed batch");
 
 4325         con2.closeTransaction();
 
 4326         CHK(con2.startTransaction() == 0);
 
 4333   con2.closeTransaction();
 
 4334   LL3(
"scanupdatetable " << tab.m_name << 
" rows updated=" << count);
 
 4335   con.closeTransaction();
 
 4340 scanupdateindex(
Par par, 
const ITab& itab, 
BSet& bset, 
bool calc)
 
 4342   Con& con = par.con();
 
 4343   const Tab& tab = par.tab();
 
 4344   Set& 
set = par.set();
 
 4346   Set set1(tab, 
set.m_rows);
 
 4348     calcscanbounds(par, itab, bset, 
set, set1);
 
 4350     bset.filter(par, 
set, set1);
 
 4352   LL3(
"scanupdateindex " << itab.m_name << 
" " << bset << 
" expect=" << set1.count() << 
" ordered=" << par.m_ordered << 
" descending=" << par.m_descending << 
" verify=" << par.m_verify);
 
 4353   Set set2(tab, 
set.m_rows);
 
 4355   CHK(con.startTransaction() == 0);
 
 4356   CHK(con.getNdbIndexScanOperation(itab, tab) == 0);
 
 4357   CHK(con.readTuples(par) == 0);
 
 4358   CHK(bset.setbnd(par) == 0);
 
 4360   CHK(con.executeScan() == 0);
 
 4365   CHK(con2.startTransaction() == 0);
 
 4369     uint err = par.m_catcherr;
 
 4370     CHK((ret = con.nextScanResult(
true, err)) != -1);
 
 4374       LL1(
"scanupdateindex [scan] stop on " << con.errname(err));
 
 4377     if (par.m_scanstop != 0 && urandom(par.m_scanstop) == 0) {
 
 4383       CHK(set2.getkey(par, &i) == 0);
 
 4385       if (!
set.compat(par, i, Row::OpUpd)) {
 
 4386         LL4(
"scanupdateindex SKIP " << 
set.getrow(i));
 
 4388         CHKTRY(set2.putval(i, par.m_dups) == 0, 
set.unlock());
 
 4389         CHKTRY(con.updateScanTuple(con2) == 0, 
set.unlock());
 
 4393         uint colmask = !par.m_noindexkeyupdate ? ~0 : ~itab.m_keymask;
 
 4394         set.calc(par, i, colmask);
 
 4395         CHKTRY(
set.setrow(par2, i) == 0, 
set.unlock());
 
 4396         LL4(
"scanupdateindex " << i << 
" " << 
set.getrow(i));
 
 4400       CHK((ret = con.nextScanResult(
false)) != -1);
 
 4401       bool lastbatch = (batch != 0 && ret != 0);
 
 4402       if (batch == par.m_batch || lastbatch) {
 
 4403         uint err = par.m_catcherr;
 
 4404         ExecType et = Commit;
 
 4405         CHK(con2.execute(et, err) == 0);
 
 4407         set.post(par, !err ? et : Rollback);
 
 4410           LL1(
"scanupdateindex [update] stop on " << con2.errname(err));
 
 4413         LL4(
"scanupdateindex committed batch");
 
 4416         con2.closeTransaction();
 
 4417         CHK(con2.startTransaction() == 0);
 
 4424   con2.closeTransaction();
 
 4426     CHK(set1.verify(par, set2, 
true) == 0);
 
 4428       CHK(set2.verifyorder(par, itab, par.m_descending) == 0);
 
 4430   LL3(
"scanupdateindex " << itab.m_name << 
" rows updated=" << count);
 
 4431   con.closeTransaction();
 
 4436 scanupdateindex(
Par par, 
const ITab& itab)
 
 4438   const Tab& tab = par.tab();
 
 4439   for (uint i = 0; i < par.m_ssloop; i++) {
 
 4440     if (itab.m_type == ITab::OrderedIndex) {
 
 4441       BSet bset(tab, itab);
 
 4442       CHK(scanupdateindex(par, itab, bset, 
true) == 0);
 
 4444       CHK(hashindexupdate(par, itab) == 0);
 
 4451 scanupdateindex(
Par par)
 
 4453   const Tab& tab = par.tab();
 
 4454   for (uint i = 0; i < tab.m_itabs; i++) {
 
 4455     if (tab.m_itab[i] == 0)
 
 4457     const ITab& itab = *tab.m_itab[
i];
 
 4458     CHK(scanupdateindex(par, itab) == 0);
 
 4465 scanupdateall(
Par par)
 
 4467   CHK(scanupdatetable(par) == 0);
 
 4468   CHK(scanupdateindex(par) == 0);
 
 4476 readverifyfull(
Par par)
 
 4480   par.m_verify = 
true;
 
 4481   if (par.m_abortpct != 0) {
 
 4482     LL2(
"skip verify in this version"); 
 
 4483     par.m_verify = 
false;
 
 4486   const Tab& tab = par.tab();
 
 4487   if (par.m_no == 0) {
 
 4489     CHK(scanreadtable(par) == 0);
 
 4491     par.m_tupscan = 
true;
 
 4492     CHK(scanreadtable(par) == 0);
 
 4495   for (uint i = 0; i < tab.m_itabs; i++) {
 
 4496     if (i % par.m_usedthreads != par.m_no)
 
 4498     if (tab.m_itab[i] == 0)
 
 4500     const ITab& itab = *tab.m_itab[
i];
 
 4501     if (itab.m_type == ITab::OrderedIndex) {
 
 4502       BSet bset(tab, itab);
 
 4503       CHK(scanreadindex(par, itab, bset, 
false) == 0);
 
 4505       CHK(hashindexread(par, itab) == 0);
 
 4512 readverifyindex(
Par par)
 
 4516   par.m_verify = 
true;
 
 4518   uint sel = urandom(10);
 
 4520     par.m_ordered = 
true;
 
 4521     par.m_descending = (sel < 5);
 
 4523   CHK(scanreadindex(par) == 0);
 
 4530   const Tab& tab = par.tab();
 
 4531   par.m_randomkey = 
true;
 
 4532   for (uint i = 0; i < par.m_ssloop; i++) {
 
 4534     while (j < tab.m_itabs) {
 
 4535       if (tab.m_itab[j] != 0) {
 
 4536         const ITab& itab = *tab.m_itab[j];
 
 4537         if (itab.m_type == ITab::UniqueHashIndex && urandom(5) == 0)
 
 4542     uint sel = urandom(10);
 
 4543     if (par.m_slno % 2 == 0) {
 
 4546         CHK(pkinsert(par) == 0);
 
 4547       } 
else if (sel < 9) {
 
 4548         if (j == tab.m_itabs)
 
 4549           CHK(pkupdate(par) == 0);
 
 4551           const ITab& itab = *tab.m_itab[j];
 
 4552           CHK(hashindexupdate(par, itab) == 0);
 
 4555         if (j == tab.m_itabs)
 
 4556           CHK(pkdelete(par) == 0);
 
 4558           const ITab& itab = *tab.m_itab[j];
 
 4559           CHK(hashindexdelete(par, itab) == 0);
 
 4565         CHK(pkinsert(par) == 0);
 
 4566       } 
else if (sel < 2) {
 
 4567         if (j == tab.m_itabs)
 
 4568           CHK(pkupdate(par) == 0);
 
 4570           const ITab& itab = *tab.m_itab[j];
 
 4571           CHK(hashindexupdate(par, itab) == 0);
 
 4574         if (j == tab.m_itabs)
 
 4575           CHK(pkdelete(par) == 0);
 
 4577           const ITab& itab = *tab.m_itab[j];
 
 4578           CHK(hashindexdelete(par, itab) == 0);
 
 4587 pkupdatescanread(
Par par)
 
 4590   par.m_catcherr |= Con::ErrDeadlock;
 
 4591   uint sel = urandom(10);
 
 4593     CHK(pkupdate(par) == 0);
 
 4594   } 
else if (sel < 6) {
 
 4595     par.m_verify = 
false;
 
 4596     CHK(scanreadtable(par) == 0);
 
 4598     par.m_verify = 
false;
 
 4600       par.m_ordered = 
true;
 
 4601       par.m_descending = (sel < 7);
 
 4603     CHK(scanreadindex(par) == 0);
 
 4609 mixedoperations(
Par par)
 
 4612   par.m_catcherr |= Con::ErrDeadlock;
 
 4613   par.m_scanstop = par.m_totrows;       
 
 4614   uint sel = urandom(10);
 
 4616     CHK(pkdelete(par) == 0);
 
 4617   } 
else if (sel < 4) {
 
 4618     CHK(pkupdate(par) == 0);
 
 4619   } 
else if (sel < 6) {
 
 4620     CHK(scanupdatetable(par) == 0);
 
 4623       par.m_ordered = 
true;
 
 4624       par.m_descending = (sel < 7);
 
 4626     CHK(scanupdateindex(par) == 0);
 
 4632 parallelorderedupdate(
Par par)
 
 4634   const Tab& tab = par.tab();
 
 4636   for (uint i = 0; i < tab.m_itabs; i++) {
 
 4637     if (tab.m_itab[i] == 0)
 
 4639     const ITab& itab = *tab.m_itab[
i];
 
 4640     if (itab.m_type != ITab::OrderedIndex)
 
 4643     if (k++ == par.m_slno % tab.m_orderedindexes) {
 
 4644       LL3(
"parallelorderedupdate: " << itab.m_name);
 
 4645       par.m_noindexkeyupdate = 
true;
 
 4646       par.m_ordered = 
true;
 
 4647       par.m_descending = (par.m_slno != 0);
 
 4649       par.m_verify = 
true;
 
 4650       BSet bset(tab, itab); 
 
 4652       uint sel = urandom(10);
 
 4653       CHK(scanupdateindex(par, itab, bset, sel < 2) == 0);
 
 4660 pkupdateindexbuild(
Par par)
 
 4662   if (par.m_no == 0) {
 
 4663     NdbSleep_MilliSleep(10 + urandom(100));
 
 4664     CHK(createindex(par) == 0);
 
 4666     NdbSleep_MilliSleep(10 + urandom(100));
 
 4667     par.m_randomkey = 
true;
 
 4668     CHK(pkupdate(par) == 0);
 
 4676   enum Res { Committed, Latest, Deadlock };
 
 4682 static Spt sptlist[] = {
 
 4690 static uint sptcount = 
sizeof(sptlist)/
sizeof(sptlist[0]);
 
 4693 savepointreadpk(
Par par, 
Spt spt)
 
 4695   LL3(
"savepointreadpk");
 
 4696   Con& con = par.con();
 
 4697   const Tab& tab = par.tab();
 
 4698   Set& 
set = par.set();
 
 4699   const Set& set1 = 
set;
 
 4700   Set set2(tab, 
set.m_rows);
 
 4702   for (uint i = 0; i < 
set.m_rows; i++) {
 
 4704     if (!
set.compat(par, i, Row::OpREAD)) {
 
 4705       LL4(
"savepointreadpk SKIP " << i << 
" " << 
set.getrow(i));
 
 4710     CHK(set2.selrow(par, *set1.m_row[i]) == 0);
 
 4711     uint err = par.m_catcherr | Con::ErrDeadlock;
 
 4712     ExecType et = NoCommit;
 
 4713     CHK(con.execute(et, err) == 0);
 
 4715       if (err & Con::ErrDeadlock) {
 
 4716         CHK(spt.m_res == Spt::Deadlock);
 
 4720       LL1(
"savepointreadpk stop on " << con.errname(err));
 
 4724     CHK(set2.getkey(par, &i2) == 0 && i == i2);
 
 4725     CHK(set2.putval(i, 
false) == 0);
 
 4726     LL4(
"row " << set2.count() << 
" " << set2.getrow(i));
 
 4730   if (spt.m_res != Spt::Deadlock)
 
 4731     CHK(set1.verify(par, set2, 
false, dirty) == 0);
 
 4736 savepointreadhashindex(
Par par, 
Spt spt)
 
 4739     LL1(
"skip hash index dirty read");
 
 4742   LL3(
"savepointreadhashindex");
 
 4743   Con& con = par.con();
 
 4744   const Tab& tab = par.tab();
 
 4745   const ITab& itab = par.itab();
 
 4746   Set& 
set = par.set();
 
 4747   const Set& set1 = 
set;
 
 4748   Set set2(tab, 
set.m_rows);
 
 4750   for (uint i = 0; i < 
set.m_rows; i++) {
 
 4752     if (!
set.compat(par, i, Row::OpREAD)) {
 
 4753       LL3(
"savepointreadhashindex SKIP " << i << 
" " << 
set.getrow(i));
 
 4758     CHK(set2.selrow(par, itab, *set1.m_row[i]) == 0);
 
 4759     uint err = par.m_catcherr | Con::ErrDeadlock;
 
 4760     ExecType et = NoCommit;
 
 4761     CHK(con.execute(et, err) == 0);
 
 4763       if (err & Con::ErrDeadlock) {
 
 4764         CHK(spt.m_res == Spt::Deadlock);
 
 4768       LL1(
"savepointreadhashindex stop on " << con.errname(err));
 
 4772     CHK(set2.getkey(par, &i2) == 0 && i == i2);
 
 4773     CHK(set2.putval(i, 
false) == 0);
 
 4774     LL4(
"row " << set2.count() << 
" " << *set2.m_row[
i]);
 
 4778   if (spt.m_res != Spt::Deadlock)
 
 4779     CHK(set1.verify(par, set2, 
false, dirty) == 0);
 
 4784 savepointscantable(
Par par, 
Spt spt)
 
 4786   LL3(
"savepointscantable");
 
 4787   Con& con = par.con();
 
 4788   const Tab& tab = par.tab();
 
 4789   const Set& 
set = par.set();
 
 4790   const Set& set1 = 
set; 
 
 4791   Set set2(tab, 
set.m_rows); 
 
 4792   CHK(con.getNdbScanOperation(tab) == 0);
 
 4793   CHK(con.readTuples(par) == 0);
 
 4795   CHK(con.executeScan() == 0);
 
 4796   bool deadlock = 
false;
 
 4800     uint err = par.m_catcherr | Con::ErrDeadlock;
 
 4801     CHK((ret = con.nextScanResult(
true, err)) == 0 || ret == 1);
 
 4805       if (err & Con::ErrDeadlock) {
 
 4806         CHK(spt.m_res == Spt::Deadlock);
 
 4811       LL1(
"savepointscantable stop on " << con.errname(err));
 
 4814     CHK(spt.m_res != Spt::Deadlock);
 
 4816     CHK(set2.getkey(par, &i) == 0);
 
 4817     CHK(set2.putval(i, 
false, n) == 0);
 
 4818     LL4(
"row " << n << 
" key " << i << 
" " << set2.getrow(i));
 
 4821   if (set1.m_rows > 0) {
 
 4823       CHK(spt.m_res != Spt::Deadlock);
 
 4825       CHK(spt.m_res == Spt::Deadlock);
 
 4827   LL2(
"savepointscantable " << n << 
" rows");
 
 4829   if (spt.m_res != Spt::Deadlock)
 
 4830     CHK(set1.verify(par, set2, 
false, dirty) == 0);
 
 4835 savepointscanindex(
Par par, 
Spt spt)
 
 4837   LL3(
"savepointscanindex");
 
 4838   Con& con = par.con();
 
 4839   const Tab& tab = par.tab();
 
 4840   const ITab& itab = par.itab();
 
 4841   const Set& 
set = par.set();
 
 4842   const Set& set1 = 
set;
 
 4843   Set set2(tab, 
set.m_rows);
 
 4844   CHK(con.getNdbIndexScanOperation(itab, tab) == 0);
 
 4845   CHK(con.readIndexTuples(par) == 0);
 
 4847   CHK(con.executeScan() == 0);
 
 4848   bool deadlock = 
false;
 
 4852     uint err = par.m_catcherr | Con::ErrDeadlock;
 
 4853     CHK((ret = con.nextScanResult(
true, err)) == 0 || ret == 1);
 
 4857       if (err & Con::ErrDeadlock) {
 
 4858         CHK(spt.m_res == Spt::Deadlock);
 
 4863       LL1(
"savepointscanindex stop on " << con.errname(err));
 
 4866     CHK(spt.m_res != Spt::Deadlock);
 
 4868     CHK(set2.getkey(par, &i) == 0);
 
 4869     CHK(set2.putval(i, par.m_dups, n) == 0);
 
 4870     LL4(
"row " << n << 
" key " << i << 
" " << set2.getrow(i));
 
 4873   if (set1.m_rows > 0) {
 
 4875       CHK(spt.m_res != Spt::Deadlock);
 
 4877       CHK(spt.m_res == Spt::Deadlock);
 
 4879   LL2(
"savepointscanindex " << n << 
" rows");
 
 4881   if (spt.m_res != Spt::Deadlock)
 
 4882     CHK(set1.verify(par, set2, 
false, dirty) == 0);
 
 4886 typedef int (*SptFun)(
Par, 
Spt);
 
 4889 savepointtest(Par par, 
Spt spt, SptFun fun)
 
 4891   Con& con = par.con();
 
 4897     CHK(con2.startTransaction() == 0);
 
 4899   par2.m_lockmode = spt.m_lm;
 
 4900   CHK((*fun)(par2, spt) == 0);
 
 4902     con2.closeTransaction();
 
 4908 savepointtest(Par par, 
const char* op)
 
 4910   Con& con = par.con();
 
 4911   const Tab& tab = par.tab();
 
 4912   Set& 
set = par.set();
 
 4913   LL2(
"savepointtest op=\"" << op << 
"\"");
 
 4914   CHK(con.startTransaction() == 0);
 
 4917   while ((c = *p++) != 0) {
 
 4919     for (j = 0; j < par.m_rows; j++) {
 
 4920       uint i = thrrow(par, j);
 
 4922         ExecType et = Commit;
 
 4923         CHK(con.execute(et) == 0);
 
 4927         CHK(con.startTransaction() == 0);
 
 4933           CHK(
set.insrow(par, i) == 0);
 
 4934         } 
else if (c == 
'u') {
 
 4935           set.copyval(i, tab.m_pkmask);
 
 4936           set.calc(par, i, ~tab.m_pkmask);
 
 4937           CHK(
set.updrow(par, i) == 0);
 
 4938         } 
else if (c == 
'd') {
 
 4939           set.copyval(i, tab.m_pkmask);
 
 4940           CHK(
set.delrow(par, i) == 0);
 
 4949     ExecType et = NoCommit;
 
 4950     CHK(con.execute(et) == 0);
 
 4955   for (uint k = 0; k < sptcount; k++) {
 
 4956     Spt spt = sptlist[k];
 
 4957     LL2(
"spt lm=" << spt.m_lm << 
" same=" << spt.m_same);
 
 4958     CHK(savepointtest(par, spt, &savepointreadpk) == 0);
 
 4959     CHK(savepointtest(par, spt, &savepointscantable) == 0);
 
 4960     for (uint i = 0; i < tab.m_itabs; i++) {
 
 4961       if (tab.m_itab[i] == 0)
 
 4963       const ITab& itab = *tab.m_itab[
i];
 
 4965       if (itab.m_type == ITab::OrderedIndex)
 
 4966         CHK(savepointtest(par, spt, &savepointscanindex) == 0);
 
 4968         CHK(savepointtest(par, spt, &savepointreadhashindex) == 0);
 
 4973     ExecType et = Rollback;
 
 4974     CHK(con.execute(et) == 0);
 
 4979   con.closeTransaction();
 
 4984 savepointtest(Par par)
 
 4986   assert(par.m_usedthreads == 1);
 
 4987   const char* oplist[] = {
 
 4997   for (i = 0; oplist[
i] != 0; i++) {
 
 4998     CHK(savepointtest(par, oplist[i]) == 0);
 
 5004 halloweentest(Par par, 
const ITab& itab)
 
 5006   LL2(
"halloweentest " << itab.m_name);
 
 5007   Con& con = par.con();
 
 5008   const Tab& tab = par.tab();
 
 5009   Set& 
set = par.set();
 
 5010   CHK(con.startTransaction() == 0);
 
 5015   CHK(
set.insrow(par, i) == 0);
 
 5016   CHK(con.execute(NoCommit) == 0);
 
 5024     Set set1(tab, 
set.m_rows); 
 
 5025     Set set2(tab, 
set.m_rows); 
 
 5026     BSet bset(tab, itab);
 
 5027     calcscanbounds(par, itab, bset, 
set, set1);
 
 5028     CHK(con.getNdbIndexScanOperation(itab, tab) == 0);
 
 5029     CHK(con.readIndexTuples(par) == 0);
 
 5030     CHK(bset.setbnd(par) == 0);
 
 5032     CHK(con.executeScan() == 0);
 
 5033     const uint savepoint = 
i;
 
 5034     LL3(
"scancount=" << scancount << 
" savepoint=" << savepoint);
 
 5038       CHK((ret = con.nextScanResult(
true)) == 0 || ret == 1);
 
 5042       CHK(set2.getkey(par, &k) == 0);
 
 5043       CHK(set2.putval(k, 
false, n) == 0);
 
 5044       LL3(
"row=" << n << 
" key=" << k);
 
 5045       CHK(k <= savepoint);
 
 5046       if (++i == 
set.m_rows) {
 
 5052       CHK(
set.insrow(par, i) == 0);
 
 5053       CHK(con.execute(NoCommit) == 0);
 
 5057     LL3(
"scanrows=" << n);
 
 5059       CHK(set1.verify(par, set2, 
false) == 0);
 
 5063   CHK(con.execute(Commit) == 0);
 
 5064   set.post(par, Commit);
 
 5065   assert(
set.count() == 
set.m_rows);
 
 5066   CHK(pkdelete(par) == 0);
 
 5071 halloweentest(Par par)
 
 5073   assert(par.m_usedthreads == 1);
 
 5074   const Tab& tab = par.tab();
 
 5075   for (uint i = 0; i < tab.m_itabs; i++) {
 
 5076     if (tab.m_itab[i] == 0)
 
 5078     const ITab& itab = *tab.m_itab[
i];
 
 5079     if (itab.m_type == ITab::OrderedIndex)
 
 5080       CHK(halloweentest(par, itab) == 0);
 
 5087 typedef int (*TFunc)(Par par);
 
 5088 enum TMode { ST = 1, MT = 2 };
 
 5090 extern "C" { 
static void* runthread(
void* arg); }
 
 5093   enum State { Wait, Start, Stop, Exit };
 
 5104   Thr(Par par, uint n);
 
 5112     NdbMutex_Lock(m_mutex);
 
 5115     NdbMutex_Unlock(m_mutex);
 
 5118     NdbCondition_Wait(m_cond, m_mutex);
 
 5121     NdbCondition_Signal(m_cond);
 
 5124     NdbThread_WaitFor(m_thread, &m_status);
 
 5129 Thr::Thr(Par par, uint n) :
 
 5141   sprintf(buf, 
"thr%03u", par.m_no);
 
 5142   const char* name = strcpy(
new char[10], buf);
 
 5144   m_mutex = NdbMutex_Create();
 
 5145   m_cond = NdbCondition_Create();
 
 5146   assert(m_mutex != 0 && m_cond != 0);
 
 5148   const uint stacksize = 256 * 1024;
 
 5149   const NDB_THREAD_PRIO prio = NDB_THREAD_PRIO_LOW;
 
 5150   m_thread = NdbThread_Create(runthread, (
void**)
this, stacksize, name, prio);
 
 5155   if (m_thread != 0) {
 
 5156     NdbThread_Destroy(&m_thread);
 
 5160     NdbCondition_Destroy(m_cond);
 
 5164     NdbMutex_Destroy(m_mutex);
 
 5170 runthread(
void* arg)
 
 5173   thr.m_id = pthread_self();
 
 5174   if (thr.run() < 0) {
 
 5175     LL1(
"exit on error");
 
 5187   CHK(con.connect() == 0);
 
 5192     while (m_state != Start && m_state != Exit) {
 
 5196     if (m_state == Exit) {
 
 5202     assert(m_state == Start);
 
 5203     m_ret = (*m_func)(m_par);
 
 5210         LL1(
"continue running due to -cont");
 
 5232   while (m_state != Stop)
 
 5249 static Thr** g_thrlist = 0;
 
 5254   if (g_thrlist != 0) {
 
 5255     pthread_t 
id = pthread_self();
 
 5256     for (uint n = 0; n < g_opt.m_threads; n++) {
 
 5257       if (g_thrlist[n] != 0) {
 
 5258         Thr& thr = *g_thrlist[
n];
 
 5259         if (pthread_equal(thr.m_id, 
id))
 
 5271   Thr* thrp = getthr();
 
 5274     uint n = thr.m_par.m_no;
 
 5276       g_opt.m_threads < 10 ? 1 :
 
 5277       g_opt.m_threads < 100 ? 2 : 3;
 
 5278     sprintf(thr.m_tmp, 
"[%0*u] ", m, n);
 
 5285 runstep(Par par, 
const char* fname, TFunc func, uint 
mode)
 
 5287   LL2(
"step: " << fname);
 
 5288   const int threads = (mode & ST ? 1 : par.m_usedthreads);
 
 5290   for (n = 0; n < threads; n++) {
 
 5292     Thr& thr = *g_thrlist[
n];
 
 5293     Par oldpar = thr.m_par;
 
 5296     thr.m_par.m_no = oldpar.m_no;
 
 5297     thr.m_par.m_con = oldpar.m_con;
 
 5302   for (n = threads - 1; n >= 0; n--) {
 
 5304     Thr& thr = *g_thrlist[
n];
 
 5313 #define RUNSTEP(par, func, mode) \ 
 5314   CHK(runstep(par, #func, func, mode) == 0) 
 5316 #define SUBLOOP(par) \ 
 5317   "sloop: " << par.m_lno << "/" << par.m_currcase << "/" << \ 
 5318   par.m_tab->m_name << "/" << par.m_slno 
 5323   RUNSTEP(par, droptable, ST);
 
 5324   RUNSTEP(par, createtable, ST);
 
 5325   RUNSTEP(par, invalidatetable, MT);
 
 5326   for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
 
 5328     if (par.m_slno % 3 == 0) {
 
 5329       RUNSTEP(par, createindex, ST);
 
 5330       RUNSTEP(par, invalidateindex, MT);
 
 5331       RUNSTEP(par, pkinsert, MT);
 
 5332       RUNSTEP(par, pkupdate, MT);
 
 5333     } 
else if (par.m_slno % 3 == 1) {
 
 5334       RUNSTEP(par, pkinsert, MT);
 
 5335       RUNSTEP(par, createindex, ST);
 
 5336       RUNSTEP(par, invalidateindex, MT);
 
 5337       RUNSTEP(par, pkupdate, MT);
 
 5339       RUNSTEP(par, pkinsert, MT);
 
 5340       RUNSTEP(par, pkupdate, MT);
 
 5341       RUNSTEP(par, createindex, ST);
 
 5342       RUNSTEP(par, invalidateindex, MT);
 
 5344     RUNSTEP(par, readverifyfull, MT);
 
 5346     if (par.m_slno + 1 < par.m_sloop) {
 
 5347       RUNSTEP(par, pkdelete, MT);
 
 5348       RUNSTEP(par, readverifyfull, MT);
 
 5349       RUNSTEP(par, dropindex, ST);
 
 5358   RUNSTEP(par, droptable, ST);
 
 5359   RUNSTEP(par, createtable, ST);
 
 5360   RUNSTEP(par, invalidatetable, MT);
 
 5361   RUNSTEP(par, createindex, ST);
 
 5362   RUNSTEP(par, invalidateindex, MT);
 
 5363   RUNSTEP(par, pkinsert, MT);
 
 5364   RUNSTEP(par, readverifyfull, MT);
 
 5365   for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
 
 5367     RUNSTEP(par, readverifyindex, MT);
 
 5376   RUNSTEP(par, droptable, ST);
 
 5377   RUNSTEP(par, createtable, ST);
 
 5378   RUNSTEP(par, invalidatetable, MT);
 
 5379   RUNSTEP(par, createindex, ST);
 
 5380   RUNSTEP(par, invalidateindex, MT);
 
 5381   for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
 
 5383     RUNSTEP(par, pkops, MT);
 
 5384     LL2(
"rows=" << par.set().count());
 
 5385     RUNSTEP(par, readverifyfull, MT);
 
 5393   RUNSTEP(par, droptable, ST);
 
 5394   RUNSTEP(par, createtable, ST);
 
 5395   RUNSTEP(par, invalidatetable, MT);
 
 5396   RUNSTEP(par, pkinsert, MT);
 
 5397   RUNSTEP(par, createindex, ST);
 
 5398   RUNSTEP(par, invalidateindex, MT);
 
 5399   RUNSTEP(par, readverifyfull, MT);
 
 5400   for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
 
 5402     RUNSTEP(par, pkupdatescanread, MT);
 
 5403     RUNSTEP(par, readverifyfull, MT);
 
 5405   RUNSTEP(par, pkdelete, MT);
 
 5406   RUNSTEP(par, readverifyfull, MT);
 
 5413   RUNSTEP(par, droptable, ST);
 
 5414   RUNSTEP(par, createtable, ST);
 
 5415   RUNSTEP(par, invalidatetable, MT);
 
 5416   RUNSTEP(par, pkinsert, MT);
 
 5417   RUNSTEP(par, createindex, ST);
 
 5418   RUNSTEP(par, invalidateindex, MT);
 
 5419   RUNSTEP(par, readverifyfull, MT);
 
 5420   for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
 
 5422     RUNSTEP(par, mixedoperations, MT);
 
 5423     RUNSTEP(par, readverifyfull, MT);
 
 5431   RUNSTEP(par, droptable, ST);
 
 5432   RUNSTEP(par, createtable, ST);
 
 5433   RUNSTEP(par, invalidatetable, MT);
 
 5434   RUNSTEP(par, pkinsert, MT);
 
 5435   for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
 
 5437     RUNSTEP(par, pkupdateindexbuild, MT);
 
 5438     RUNSTEP(par, invalidateindex, MT);
 
 5439     RUNSTEP(par, readverifyfull, MT);
 
 5440     RUNSTEP(par, dropindex, ST);
 
 5448   par.m_abortpct = 50;
 
 5449   RUNSTEP(par, droptable, ST);
 
 5450   RUNSTEP(par, createtable, ST);
 
 5451   RUNSTEP(par, invalidatetable, MT);
 
 5452   RUNSTEP(par, pkinsert, MT);
 
 5453   RUNSTEP(par, createindex, ST);
 
 5454   RUNSTEP(par, invalidateindex, MT);
 
 5455   RUNSTEP(par, readverifyfull, MT);
 
 5456   for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
 
 5458     RUNSTEP(par, mixedoperations, MT);
 
 5459     RUNSTEP(par, readverifyfull, MT);
 
 5467   RUNSTEP(par, droptable, ST);
 
 5468   RUNSTEP(par, createtable, ST);
 
 5469   RUNSTEP(par, invalidatetable, MT);
 
 5470   RUNSTEP(par, pkinsert, MT);
 
 5471   RUNSTEP(par, createindex, ST);
 
 5472   RUNSTEP(par, invalidateindex, MT);
 
 5473   RUNSTEP(par, readverifyfull, MT);
 
 5474   for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
 
 5476     RUNSTEP(par, parallelorderedupdate, MT);
 
 5477     RUNSTEP(par, readverifyfull, MT);
 
 5485   RUNSTEP(par, droptable, ST);
 
 5486   RUNSTEP(par, createtable, ST);
 
 5487   RUNSTEP(par, invalidatetable, MT);
 
 5488   RUNSTEP(par, createindex, ST);
 
 5489   RUNSTEP(par, invalidateindex, MT);
 
 5490   for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
 
 5492     RUNSTEP(par, savepointtest, MT);
 
 5493     RUNSTEP(par, readverifyfull, MT);
 
 5501   RUNSTEP(par, droptable, ST);
 
 5502   RUNSTEP(par, createtable, ST);
 
 5503   RUNSTEP(par, invalidatetable, MT);
 
 5504   RUNSTEP(par, createindex, ST);
 
 5505   RUNSTEP(par, invalidateindex, MT);
 
 5506   for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
 
 5508     RUNSTEP(par, halloweentest, MT);
 
 5517   RUNSTEP(par, droptable, ST);
 
 5518   RUNSTEP(par, createtable, ST);
 
 5519   RUNSTEP(par, invalidatetable, MT);
 
 5520   for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
 
 5522     RUNSTEP(par, pkinsert, MT);
 
 5524     RUNSTEP(par, createindex, ST);
 
 5525     t1.off(par.m_totrows);
 
 5526     RUNSTEP(par, invalidateindex, MT);
 
 5527     RUNSTEP(par, dropindex, ST);
 
 5529   LL1(
"build index - " << t1.time());
 
 5537   RUNSTEP(par, droptable, ST);
 
 5538   RUNSTEP(par, createtable, ST);
 
 5539   RUNSTEP(par, invalidatetable, MT);
 
 5540   for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
 
 5542     RUNSTEP(par, pkinsert, MT);
 
 5544     RUNSTEP(par, pkupdate, MT);
 
 5545     t1.off(par.m_totrows);
 
 5546     RUNSTEP(par, createindex, ST);
 
 5547     RUNSTEP(par, invalidateindex, MT);
 
 5549     RUNSTEP(par, pkupdate, MT);
 
 5550     t2.off(par.m_totrows);
 
 5551     RUNSTEP(par, dropindex, ST);
 
 5553   LL1(
"update - " << t1.time());
 
 5554   LL1(
"update indexed - " << t2.time());
 
 5555   LL1(
"overhead - " << t2.over(t1));
 
 5562   if (par.tab().m_itab[0] == 0) {
 
 5563     LL1(
"ttimescan - no index 0, skipped");
 
 5567   RUNSTEP(par, droptable, ST);
 
 5568   RUNSTEP(par, createtable, ST);
 
 5569   RUNSTEP(par, invalidatetable, MT);
 
 5570   for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
 
 5572     RUNSTEP(par, pkinsert, MT);
 
 5573     RUNSTEP(par, createindex, ST);
 
 5575     RUNSTEP(par, timescantable, ST);
 
 5577     RUNSTEP(par, timescanpkindex, ST);
 
 5578     RUNSTEP(par, dropindex, ST);
 
 5580   LL1(
"full scan table - " << t1.time());
 
 5581   LL1(
"full scan PK index - " << t2.time());
 
 5582   LL1(
"overhead - " << t2.over(t1));
 
 5587 ttimepkread(Par par)
 
 5589   if (par.tab().m_itab[0] == 0) {
 
 5590     LL1(
"ttimescan - no index 0, skipped");
 
 5594   RUNSTEP(par, droptable, ST);
 
 5595   RUNSTEP(par, createtable, ST);
 
 5596   RUNSTEP(par, invalidatetable, MT);
 
 5597   for (par.m_slno = 0; par.m_slno < par.m_sloop; par.m_slno++) {
 
 5599     RUNSTEP(par, pkinsert, MT);
 
 5600     RUNSTEP(par, createindex, ST);
 
 5602     RUNSTEP(par, timepkreadtable, ST);
 
 5604     RUNSTEP(par, timepkreadindex, ST);
 
 5605     RUNSTEP(par, dropindex, ST);
 
 5607   LL1(
"pk read table - " << t1.time());
 
 5608   LL1(
"pk read PK index - " << t2.time());
 
 5609   LL1(
"overhead - " << t2.over(t1));
 
 5616   RUNSTEP(par, droptable, ST);
 
 5624   TCase(
const char* name, TFunc func, 
const char* desc) :
 
 5633   TCase(
"a", tbuild, 
"index build"),
 
 5634   TCase(
"b", tindexscan, 
"index scans"),
 
 5635   TCase(
"c", tpkops, 
"pk operations"),
 
 5636   TCase(
"d", tpkopsread, 
"pk operations and scan reads"),
 
 5637   TCase(
"e", tmixedops, 
"pk operations and scan operations"),
 
 5638   TCase(
"f", tbusybuild, 
"pk operations and index build"),
 
 5639   TCase(
"g", trollback, 
"operations with random rollbacks"),
 
 5640   TCase(
"h", tparupdate, 
"parallel ordered update bug#20446"),
 
 5641   TCase(
"i", tsavepoint, 
"savepoint test locking bug#31477"),
 
 5642   TCase(
"j", thalloween, 
"savepoint test halloween problem"),
 
 5643   TCase(
"t", ttimebuild, 
"time index build"),
 
 5644   TCase(
"u", ttimemaint, 
"time index maintenance"),
 
 5645   TCase(
"v", ttimescan, 
"time full scan table vs index on pk"),
 
 5646   TCase(
"w", ttimepkread, 
"time pk read table vs index on pk"),
 
 5647   TCase(
"z", tdrop, 
"drop test tables")
 
 5651 tcasecount = 
sizeof(tcaselist) / 
sizeof(tcaselist[0]);
 
 5656   ndbout << 
"test cases:" << endl;
 
 5657   for (uint i = 0; i < tcasecount; i++) {
 
 5658     const TCase& tcase = tcaselist[
i];
 
 5659     ndbout << 
"  " << tcase.m_name << 
" - " << tcase.m_desc << endl;
 
 5667   makebuiltintables(par);
 
 5668   ndbout << 
"tables and indexes (x=ordered z=hash x0=on pk):" << endl;
 
 5669   for (uint j = 0; j < tabcount; j++) {
 
 5670     if (tablist[j] == 0)
 
 5672     const Tab& tab = *tablist[j];
 
 5673     const char* tname = tab.m_name;
 
 5674     ndbout << 
"  " << tname;
 
 5675     for (uint i = 0; i < tab.m_itabs; i++) {
 
 5676       if (tab.m_itab[i] == 0)
 
 5678       const ITab& itab = *tab.m_itab[
i];
 
 5679       const char* iname = itab.m_name;
 
 5680       if (strncmp(tname, iname, strlen(tname)) == 0)
 
 5681         iname += strlen(tname);
 
 5682       ndbout << 
" " << iname;
 
 5684       for (uint k = 0; k < itab.m_icols; k++) {
 
 5687         const ICol& icol = *itab.m_icol[k];
 
 5688         const Col& col = icol.m_col;
 
 5689         ndbout << col.m_name;
 
 5698 setcasepar(Par& par)
 
 5701   const char* c = par.m_currcase;
 
 5705       if (par.m_usedthreads > 1) {
 
 5706         par.m_usedthreads = 1;
 
 5707         LL1(
"case " << c << 
" reduce threads to " << par.m_usedthreads);
 
 5709       const uint rows = 100;
 
 5710       if (par.m_rows > rows) {
 
 5712         LL1(
"case " << c << 
" reduce rows to " << rows);
 
 5718       if (par.m_usedthreads > 1) {
 
 5719         par.m_usedthreads = 1;
 
 5720         LL1(
"case " << c << 
" reduce threads to " << par.m_usedthreads);
 
 5734   if (par.m_seed == -1) {
 
 5736     ushort seed = (ushort)getpid();
 
 5737     LL0(
"random seed: " << seed);
 
 5738     srandom((uint)seed);
 
 5739   } 
else if (par.m_seed != 0) {
 
 5740     LL0(
"random seed: " << par.m_seed);
 
 5741     srandom(par.m_seed);
 
 5743     LL0(
"random seed: loop number");
 
 5746   assert(par.m_csname != 0);
 
 5747   if (strcmp(par.m_csname, 
"random") != 0) {
 
 5749     CHK((cs = get_charset_by_name(par.m_csname, MYF(0))) != 0 || (cs = get_charset_by_csname(par.m_csname, MY_CS_PRIMARY, MYF(0))) != 0);
 
 5754   CHK(con.connect() == 0);
 
 5756   par.m_catcherr |= Con::ErrNospace;
 
 5758   g_thrlist = 
new Thr* [par.m_threads];
 
 5760   for (n = 0; n < par.m_threads; n++) {
 
 5763   for (n = 0; n < par.m_threads; n++) {
 
 5764     g_thrlist[
n] = 
new Thr(par, n);
 
 5765     Thr& thr = *g_thrlist[
n];
 
 5766     assert(thr.m_thread != 0);
 
 5768   for (par.m_lno = 0; par.m_loop == 0 || par.m_lno < par.m_loop; par.m_lno++) {
 
 5769     LL1(
"loop: " << par.m_lno);
 
 5770     if (par.m_seed == 0) {
 
 5771       LL1(
"random seed: " << par.m_lno);
 
 5774     for (uint i = 0; i < tcasecount; i++) {
 
 5775       const TCase& tcase = tcaselist[
i];
 
 5776       if ((par.m_case != 0 && strchr(par.m_case, tcase.m_name[0]) == 0) ||
 
 5777           (par.m_skip != 0 && strchr(par.m_skip, tcase.m_name[0]) != 0)) {
 
 5780       sprintf(par.m_currcase, 
"%c", tcase.m_name[0]);
 
 5781       par.m_usedthreads = par.m_threads;
 
 5782       if (!setcasepar(par)) {
 
 5783         LL1(
"case " << tcase.m_name << 
" cannot run with given options");
 
 5786       par.m_totrows = par.m_usedthreads * par.m_rows;
 
 5787       makebuiltintables(par);
 
 5788       LL1(
"case: " << par.m_lno << 
"/" << tcase.m_name << 
" - " << tcase.m_desc);
 
 5789       for (uint j = 0; j < tabcount; j++) {
 
 5790         if (tablist[j] == 0)
 
 5792         const Tab& tab = *tablist[j];
 
 5794         par.m_set = 
new Set(tab, par.m_totrows);
 
 5795         LL1(
"table: " << par.m_lno << 
"/" << tcase.m_name << 
"/" << tab.m_name);
 
 5796         int ret = tcase.m_func(par);
 
 5803           LL1(
"continue to next case due to -cont");
 
 5809   for (n = 0; n < par.m_threads; n++) {
 
 5810     Thr& thr = *g_thrlist[
n];
 
 5813   for (n = 0; n < par.m_threads; n++) {
 
 5814     Thr& thr = *g_thrlist[
n];
 
 5818   delete [] g_thrlist;
 
 5824 static const char* g_progname = 
"testOIBasic";
 
 5827 main(
int argc,  
char** argv)
 
 5831   ndbout << g_progname;
 
 5832   for (i = 1; i < (uint) argc; i++)
 
 5833     ndbout << 
" " << argv[i];
 
 5835   ndbout_mutex = NdbMutex_Create();
 
 5836   while (++argv, --argc > 0) {
 
 5837     const char* arg = argv[0];
 
 5839       ndbout << 
"testOIBasic: unknown argument " << arg;
 
 5842     if (strcmp(arg, 
"-batch") == 0) {
 
 5843       if (++argv, --argc > 0) {
 
 5844         g_opt.m_batch = atoi(argv[0]);
 
 5848     if (strcmp(arg, 
"-bound") == 0) {
 
 5849       if (++argv, --argc > 0) {
 
 5850         const char* p = argv[0];
 
 5851         if (strlen(p) != 0 && strlen(p) == strspn(p, 
"01234")) {
 
 5852           g_opt.m_bound = strdup(p);
 
 5857     if (strcmp(arg, 
"-case") == 0) {
 
 5858       if (++argv, --argc > 0) {
 
 5859         g_opt.m_case = strdup(argv[0]);
 
 5863     if (strcmp(arg, 
"-collsp") == 0) {
 
 5864       g_opt.m_collsp = 
true;
 
 5867     if (strcmp(arg, 
"-cont") == 0) {
 
 5868       g_opt.m_cont = 
true;
 
 5871     if (strcmp(arg, 
"-core") == 0) {
 
 5872       g_opt.m_core = 
true;
 
 5875     if (strcmp(arg, 
"-csname") == 0) {
 
 5876       if (++argv, --argc > 0) {
 
 5877         g_opt.m_csname = strdup(argv[0]);
 
 5881     if (strcmp(arg, 
"-die") == 0) {
 
 5882       if (++argv, --argc > 0) {
 
 5883         g_opt.m_die = atoi(argv[0]);
 
 5887     if (strcmp(arg, 
"-dups") == 0) {
 
 5888       g_opt.m_dups = 
true;
 
 5891     if (strcmp(arg, 
"-fragtype") == 0) {
 
 5892       if (++argv, --argc > 0) {
 
 5893         if (strcmp(argv[0], 
"single") == 0) {
 
 5897         if (strcmp(argv[0], 
"small") == 0) {
 
 5901         if (strcmp(argv[0], 
"medium") == 0) {
 
 5905         if (strcmp(argv[0], 
"large") == 0) {
 
 5911     if (strcmp(arg, 
"-index") == 0) {
 
 5912       if (++argv, --argc > 0) {
 
 5913         g_opt.m_index = strdup(argv[0]);
 
 5917     if (strcmp(arg, 
"-loop") == 0) {
 
 5918       if (++argv, --argc > 0) {
 
 5919         g_opt.m_loop = atoi(argv[0]);
 
 5923     if (strcmp(arg, 
"-mrrmaxrng") == 0) {
 
 5924       if (++argv, --argc > 0) {
 
 5925         g_opt.m_mrrmaxrng = atoi(argv[0]);
 
 5929     if (strcmp(arg, 
"-nologging") == 0) {
 
 5930       g_opt.m_nologging = 
true;
 
 5933     if (strcmp(arg, 
"-noverify") == 0) {
 
 5934       g_opt.m_noverify = 
true;
 
 5937     if (strcmp(arg, 
"-pctmrr") == 0) {
 
 5938       if (++argv, --argc > 0) {
 
 5939         g_opt.m_pctmrr = atoi(argv[0]);
 
 5943     if (strcmp(arg, 
"-pctnull") == 0) {
 
 5944       if (++argv, --argc > 0) {
 
 5945         g_opt.m_pctnull = atoi(argv[0]);
 
 5949     if (strcmp(arg, 
"-rows") == 0) {
 
 5950       if (++argv, --argc > 0) {
 
 5951         g_opt.m_rows = atoi(argv[0]);
 
 5955     if (strcmp(arg, 
"-samples") == 0) {
 
 5956       if (++argv, --argc > 0) {
 
 5957         g_opt.m_samples = atoi(argv[0]);
 
 5961     if (strcmp(arg, 
"-scanbatch") == 0) {
 
 5962       if (++argv, --argc > 0) {
 
 5963         g_opt.m_scanbatch = atoi(argv[0]);
 
 5967     if (strcmp(arg, 
"-scanpar") == 0) {
 
 5968       if (++argv, --argc > 0) {
 
 5969         g_opt.m_scanpar = atoi(argv[0]);
 
 5973     if (strcmp(arg, 
"-seed") == 0) {
 
 5974       if (++argv, --argc > 0) {
 
 5975         g_opt.m_seed = atoi(argv[0]);
 
 5979     if (strcmp(arg, 
"-skip") == 0) {
 
 5980       if (++argv, --argc > 0) {
 
 5981         g_opt.m_skip = strdup(argv[0]);
 
 5985     if (strcmp(arg, 
"-sloop") == 0) {
 
 5986       if (++argv, --argc > 0) {
 
 5987         g_opt.m_sloop = atoi(argv[0]);
 
 5991     if (strcmp(arg, 
"-ssloop") == 0) {
 
 5992       if (++argv, --argc > 0) {
 
 5993         g_opt.m_ssloop = atoi(argv[0]);
 
 5997     if (strcmp(arg, 
"-table") == 0) {
 
 5998       if (++argv, --argc > 0) {
 
 5999         g_opt.m_table = strdup(argv[0]);
 
 6003     if (strcmp(arg, 
"-threads") == 0) {
 
 6004       if (++argv, --argc > 0) {
 
 6005         g_opt.m_threads = atoi(argv[0]);
 
 6006         if (1 <= g_opt.m_threads)
 
 6010     if (strcmp(arg, 
"-v") == 0) {
 
 6011       if (++argv, --argc > 0) {
 
 6012         g_opt.m_v = atoi(argv[0]);
 
 6016     if (strncmp(arg, 
"-v", 2) == 0 && isdigit(arg[2])) {
 
 6017       g_opt.m_v = atoi(&arg[2]);
 
 6020     if (strcmp(arg, 
"-h") == 0 || strcmp(arg, 
"-help") == 0) {
 
 6024     ndbout << 
"testOIBasic: bad or unknown option " << arg;
 
 6030     if (g_ncc->
connect(30) != 0 || runtest(par) < 0)
 
 6036   return NDBT_ProgramExit(NDBT_OK);
 
 6038   return NDBT_ProgramExit(NDBT_FAILED);
 
 6040   ndbout << 
" (use -h for help)" << endl;
 
 6042   return NDBT_ProgramExit(NDBT_WRONGARGS);