MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
testDataBuffers.cpp
1 /*
2  Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 /*
19  * testDataBuffers
20  *
21  * Test getValue() of byte arrays:
22  * - using application buffers of different alignments and sizes
23  * - using NdbApi allocated small (<32) and big (>=32) buffers
24  *
25  * Verifies fixes to tickets 189 and 206.
26  *
27  * Options: see printusage() below.
28  *
29  * Creates tables TB00 to TB15
30  */
31 
32 #include <ndb_global.h>
33 
34 #include <NdbMain.h>
35 #include <NdbOut.hpp>
36 #include <NdbApi.hpp>
37 #include <NdbTest.hpp>
38 #include <NdbSchemaCon.hpp>
39 // limits
40 static int const MaxAttr = 64;
41 static int const MaxOper = 1000;
42 static int const MaxSize = 10000;
43 static int const MaxOff = 64; // max offset to add to data buffer
44 static int const MaxData = MaxSize + MaxOff + 100;
45 
46 // options
47 static int attrcnt = 25;
48 static int existok = 0;
49 static bool kontinue = false;
50 static int loopcnt = 1;
51 static int opercnt = 100; // also does this many scans
52 static int randomizer = 171317;
53 static int sizelim = 500;
54 static int xverbose = 0;
55 
56 static void printusage() {
57  ndbout
58  << "usage: testDataBuffers options [default/max]"
59  << endl
60  << "NOTE: too large combinations result in NDB error"
61  << endl
62  << "-a N number of attributes (including the key) [25/64]"
63  << endl
64  << "-e no error if table exists (assumed to have same structure)"
65  << endl
66  << "-k on error continue with next test case"
67  << endl
68  << "-l N number of loops to run, 0 means infinite [1]"
69  << endl
70  << "-o N number of operations (rows in each table) [100/1000]"
71  << endl
72  << "-r N source of randomness (big number (prime)) [171317]"
73  << endl
74  << "-s N array size limit (rounded up in some tests) [500/10000]"
75  << endl
76  << "-x extremely verbose"
77  << endl
78  << "Tables: TB00 .. TB15"
79  << endl
80  ;
81 }
82 
83 static Ndb* ndb = 0;
84 static NdbSchemaCon* tcon = 0;
85 static NdbSchemaOp* top = 0;
86 static NdbConnection* con = 0;
87 static NdbOperation* op = 0;
88 static NdbScanOperation* sop = 0;
89 
90 static int
91 ndberror(char const* fmt, ...)
92 {
93  va_list ap;
94  char buf[200];
95  va_start(ap, fmt);
96  BaseString::vsnprintf(buf, sizeof(buf), fmt, ap);
97  va_end(ap);
98  ndbout << buf << " --" << endl;
99  if (ndb)
100  ndbout << "ndb : " << ndb->getNdbError() << endl;
101  if (tcon)
102  ndbout << "tcon: " << tcon->getNdbError() << endl;
103  if (top)
104  ndbout << "top: " << top->getNdbError() << endl;
105  if (con)
106  ndbout << "con : " << con->getNdbError() << endl;
107  if (op)
108  ndbout << "op : " << op->getNdbError() << endl;
109  return -1;
110 }
111 
112 static int
113 chkerror(char const* fmt, ...)
114 {
115  va_list ap;
116  char buf[200];
117  va_start(ap, fmt);
118  BaseString::vsnprintf(buf, sizeof(buf), fmt, ap);
119  va_end(ap);
120  ndbout << "*** check failed: " << buf << " ***" << endl;
121  return -1;
122 }
123 
124 // alignment of addresses and data sizes
125 
126 static bool isAligned(UintPtr x)
127 {
128  return ((x & 3) == 0);
129 }
130 static bool isAligned(char* p)
131 {
132  return isAligned(UintPtr(p));
133 }
134 static unsigned toAligned(unsigned x)
135 {
136  while (! isAligned(x))
137  x++;
138  return x;
139 }
140 static char* toAligned(char* p)
141 {
142  while (! isAligned(p))
143  p++;
144  return p;
145 }
146 
147 // byte value for key k column i byte j
148 static int byteVal(int k, int i, int j)
149 {
150  return '0' + (k + i + j) % 10;
151 }
152 
153 // tables
154 
155 static char tab[20] = "";
156 
157 static struct col {
158  char aAttrName[20];
159  AttrType aAttrType;
160  int aAttrSize;
161  int aArraySize;
162  KeyType aTupleKey;
163  bool nullable;
164  NdbRecAttr* aRa;
165  char* buf;
166  int bufsiz;
167  char data[MaxData];
168 } ccol[MaxAttr];
169 
170 static int key = 0;
171 
172 // independent test bits
173 static bool alignAddr; // align our buffer addresses to 4x
174 static bool alignSize; // align data sizes to 4x
175 static bool useBuf; // use our buffers for output
176 static bool noRandom; // do not randomize sizes and offsets
177 static int testbits = 4;
178 
179 static int
180 makeSize(int i)
181 {
182  int n;
183  if (noRandom)
184  n = i;
185  else
186  n = i * randomizer;
187  n %= sizelim;
188  if (n <= 0)
189  n = 1;
190  if (alignSize)
191  n = toAligned(n);
192  return n;
193 }
194 
195 static int
196 makeOff(int k)
197 {
198  int n;
199  if (alignAddr)
200  n = 0;
201  else if (noRandom)
202  n = k;
203  else
204  n = k * randomizer;
205  n %= MaxOff;
206  if (n < 0)
207  n = -n;
208  return n;
209 }
210 
211 static int
212 testcase(Ndb_cluster_connection&cc, int flag)
213 {
214  ndbout << "--- case " << flag << " ---" << endl;
215  sprintf(tab, "TB%02d", flag);
216 
217  alignAddr = ! (flag & 1);
218  ndbout << (alignAddr ? "align addresses" : "mis-align addresses") << endl;
219  alignSize = ! (flag & 2);
220  ndbout << (alignSize ? "align data sizes" : "mis-align data sizes") << endl;
221  useBuf = ! (flag & 4);
222  ndbout << (useBuf ? "use our buffers" : "use ndbapi buffers") << endl;
223  noRandom = ! (flag & 8);
224  ndbout << (noRandom ? "simple sizes" : "randomize sizes") << endl;
225 
226  int smax = 0, stot = 0, i;
227  if (xverbose)
228  ndbout << "- define table " << tab << endl;
229  for (i = 0; i < attrcnt; i++) {
230  col& c = ccol[i];
231  memset(&c, 0, sizeof(c));
232  sprintf(c.aAttrName, "C%d", i);
233  if (i == 0) {
234  c.aAttrType = UnSigned;
235  c.aAttrSize = 32;
236  c.aArraySize = 1;
237  c.aTupleKey = TupleKey;
238  c.nullable = false;
239  } else {
240  c.aAttrType = String;
241  c.aAttrSize = 8;
242  c.aArraySize = makeSize(i);
243  if (smax < c.aArraySize)
244  smax = c.aArraySize;
245  stot += c.aArraySize;
246  c.aTupleKey = NoKey;
247  c.nullable = true;
248  if (xverbose)
249  ndbout << "-- column " << i << " size=" << c.aArraySize << endl;
250  }
251  c.buf = toAligned(c.data);
252  c.bufsiz = sizeof(c.data) - (c.buf - c.data);
253  }
254  ndbout << "tab=" << tab << " cols=" << attrcnt
255  << " size max=" << smax << " tot=" << stot << endl;
256 
257  if ((tcon = NdbSchemaCon::startSchemaTrans(ndb)) == 0)
258  return ndberror("startSchemaTransaction");
259  if ((top = tcon->getNdbSchemaOp()) == 0)
260  return ndberror("getNdbSchemaOp");
261  if (top->createTable(tab) < 0)
262  return ndberror("createTable");
263  for (i = 0; i < attrcnt; i++) {
264  col& c = ccol[i];
265  if (top->createAttribute(
266  c.aAttrName,
267  c.aTupleKey,
268  c.aAttrSize,
269  c.aArraySize,
270  c.aAttrType,
271  MMBased,
272  c.nullable
273  ) < 0)
274  return ndberror("createAttribute col=%d", i);
275  }
276  if (tcon->execute() < 0) {
277  if (! (tcon->getNdbError().code == 721 && existok))
278  return ndberror("execute");
279  ndbout << "using " << tab << endl;
280  } else {
281  ndbout << "created " << tab << endl;
282  }
283  top = 0;
284  tcon = 0;
285 
286  if (xverbose)
287  ndbout << "- delete" << endl;
288  int delcnt = 0;
289  for (key = 0; key < opercnt; key++) {
290  if ((con = ndb->startTransaction()) == 0)
291  return ndberror("startTransaction key=%d", key);
292  if ((op = con->getNdbOperation(tab)) == 0)
293  return ndberror("getNdbOperation key=%d", key);
294  if (op->deleteTuple() < 0)
295  return ndberror("deleteTuple key=%d", key);
296  for (i = 0; i < attrcnt; i++) {
297  col& c = ccol[i];
298  if (i == 0) {
299  if (op->equal(c.aAttrName, (char*)&key, sizeof(key)) < 0)
300  return ndberror("equal key=%d", key);
301  } else {
302  }
303  }
304  if (con->execute(Commit) < 0) {
305  if (con->getNdbError().code != 626)
306  return ndberror("execute key=%d", key);
307  } else {
308  delcnt++;
309  }
310  ndb->closeTransaction(con);
311  }
312  con = 0;
313  op = 0;
314  ndbout << "deleted " << delcnt << endl;
315 
316  if (xverbose)
317  ndbout << "- insert" << endl;
318  for (key = 0; key < opercnt; key++) {
319  int off = makeOff(key);
320  if ((con = ndb->startTransaction()) == 0)
321  return ndberror("startTransaction key=%d", key);
322  if ((op = con->getNdbOperation(tab)) == 0)
323  return ndberror("getNdbOperation key=%d", key);
324  if (op->insertTuple() < 0)
325  return ndberror("insertTuple key=%d", key);
326  for (i = 0; i < attrcnt; i++) {
327  col& c = ccol[i];
328  if (i == 0) {
329  if (op->equal(c.aAttrName, (char*)&key, sizeof(key)) < 0)
330  return ndberror("equal key=%d", key);
331  } else {
332  memset(c.buf, 'A', c.bufsiz);
333  for (int j = 0; j < c.aArraySize; j++)
334  c.buf[j + off] = byteVal(key, i, j);
335  if (op->setValue(c.aAttrName, c.buf + off, c.aArraySize) < 0)
336  return ndberror("setValue key=%d col=%d", key, i);
337  }
338  }
339  if (con->execute(Commit) < 0)
340  return ndberror("execute key=%d", key);
341  ndb->closeTransaction(con);
342  }
343  con = 0;
344  op = 0;
345  ndbout << "inserted " << key << endl;
346 
347  if (xverbose)
348  ndbout << "- select" << endl;
349  for (key = 0; key < opercnt; key++) {
350  int off = makeOff(key);
351  if (xverbose)
352  ndbout << "-- key " << key << " off=" << off << endl;
353  if ((con = ndb->startTransaction()) == 0)
354  return ndberror("startTransaction key=%d", key);
355  if ((op = con->getNdbOperation(tab)) == 0)
356  return ndberror("getNdbOperation key=%d", key);
357  if (op->readTuple() < 0)
358  return ndberror("readTuple key=%d", key);
359  for (i = 0; i < attrcnt; i++) {
360  col& c = ccol[i];
361  if (i == 0) {
362  if (op->equal(c.aAttrName, (char*)&key, sizeof(key)) < 0)
363  return ndberror("equal key=%d", key);
364  } else {
365  if (xverbose) {
366  char tmp[20];
367  if (useBuf)
368  sprintf(tmp, "0x%p", c.buf + off);
369  else
370  strcpy(tmp, "ndbapi");
371  ndbout << "--- column " << i << " addr=" << tmp << endl;
372  }
373  memset(c.buf, 'B', c.bufsiz);
374  if (useBuf) {
375  if (op->getValue(c.aAttrName, c.buf + off) < 0)
376  return ndberror("getValue key=%d col=%d", key, i);
377  } else {
378  if ((c.aRa = op->getValue(c.aAttrName)) == 0)
379  return ndberror("getValue key=%d col=%d", key, i);
380  }
381  }
382  }
383  if (con->execute(Commit) != 0)
384  return ndberror("execute key=%d", key);
385  for (i = 0; i < attrcnt; i++) {
386  col& c = ccol[i];
387  if (i == 0) {
388  } else if (useBuf) {
389  int j;
390  for (j = 0; j < off; j++) {
391  if (c.buf[j] != 'B') {
392  return chkerror("mismatch before key=%d col=%d pos=%d ok=%02x bad=%02x",
393  key, i, j, 'B', c.buf[j]);
394  }
395  }
396  for (j = 0; j < c.aArraySize; j++) {
397  if (c.buf[j + off] != byteVal(key, i, j)) {
398  return chkerror("mismatch key=%d col=%d pos=%d ok=%02x bad=%02x",
399  key, i, j, byteVal(key, i, j), c.buf[j]);
400  }
401  }
402  for (j = c.aArraySize + off; j < c.bufsiz; j++) {
403  if (c.buf[j] != 'B') {
404  return chkerror("mismatch after key=%d col=%d pos=%d ok=%02x bad=%02x",
405  key, i, j, 'B', c.buf[j]);
406  }
407  }
408  } else {
409  char* buf = c.aRa->aRef();
410  if (buf == 0)
411  return ndberror("null aRef key=%d col%d", key, i);
412  for (int j = 0; j < c.aArraySize; j++) {
413  if (buf[j] != byteVal(key, i, j)) {
414  return chkerror("mismatch key=%d col=%d pos=%d ok=%02x bad=%02x",
415  key, i, j, byteVal(key, i, j), buf[j]);
416  }
417  }
418  }
419  }
420  ndb->closeTransaction(con);
421  }
422  con = 0;
423  op = 0;
424  ndbout << "selected " << key << endl;
425 
426  if (xverbose)
427  ndbout << "- scan" << endl;
428  char found[MaxOper];
429  int k;
431  const NdbDictionary::Table * table = dict->getTable(tab);
432 
433  for (k = 0; k < opercnt; k++)
434  found[k] = 0;
435  for (key = 0; key < opercnt; key++) {
436  int off = makeOff(key);
437  NdbInterpretedCode codeObj(table);
438  NdbInterpretedCode *code= &codeObj;
439 
440  if (xverbose)
441  ndbout << "-- key " << key << " off=" << off << endl;
442  int newkey = 0;
443  if ((con = ndb->startTransaction()) == 0)
444  return ndberror("startTransaction key=%d", key);
445  if ((op = sop = con->getNdbScanOperation(tab)) == 0)
446  return ndberror("getNdbOperation key=%d", key);
447  if (sop->readTuples(1))
448  return ndberror("openScanRead key=%d", key);
449  {
450  col& c = ccol[0];
451  Uint32 colNum= table->getColumn(c.aAttrName)->getAttrId();
452  if (code->load_const_u32(1, key) < 0)
453  return ndberror("load_const_u32");
454  if (code->read_attr(2, colNum) < 0)
455  return ndberror("read_attr");
456  if (code->branch_eq(1, 2, 0) < 0)
457  return ndberror("branch_eq");
458  if (code->interpret_exit_nok() < 0)
459  return ndberror("interpret_exit_nok");
460  if (code->def_label(0) < 0)
461  return ndberror("def_label");
462  if (code->interpret_exit_ok() < 0)
463  return ndberror("interpret_exit_ok");
464  if (code->finalise() != 0)
465  return ndberror("finalise");
466  if (sop->setInterpretedCode(code) != 0)
467  return ndberror("setInterpretedCode");
468  }
469  for (i = 0; i < attrcnt; i++) {
470  col& c = ccol[i];
471  if (i == 0) {
472  if (op->getValue(c.aAttrName, (char*)&newkey) < 0)
473  return ndberror("getValue key=%d col=%d", key, i);
474  } else {
475  if (xverbose) {
476  char tmp[20];
477  if (useBuf)
478  sprintf(tmp, "0x%p", c.buf + off);
479  else
480  strcpy(tmp, "ndbapi");
481  ndbout << "--- column " << i << " addr=" << tmp << endl;
482  }
483  memset(c.buf, 'C', c.bufsiz);
484  if (useBuf) {
485  if (op->getValue(c.aAttrName, c.buf + off) < 0)
486  return ndberror("getValue key=%d col=%d", key, i);
487  } else {
488  if ((c.aRa = op->getValue(c.aAttrName)) == 0)
489  return ndberror("getValue key=%d col=%d", key, i);
490  }
491  }
492  }
493  if (con->execute(NoCommit) < 0)
494  return ndberror("executeScan key=%d", key);
495  int ret, cnt = 0;
496  while ((ret = sop->nextResult()) == 0) {
497  if (key != newkey)
498  return ndberror("unexpected key=%d newkey=%d", key, newkey);
499  for (i = 1; i < attrcnt; i++) {
500  col& c = ccol[i];
501  if (useBuf) {
502  int j;
503  for (j = 0; j < off; j++) {
504  if (c.buf[j] != 'C') {
505  return chkerror("mismatch before key=%d col=%d pos=%d ok=%02x bad=%02x",
506  key, i, j, 'C', c.buf[j]);
507  }
508  }
509  for (j = 0; j < c.aArraySize; j++) {
510  if (c.buf[j + off] != byteVal(key, i, j)) {
511  return chkerror("mismatch key=%d col=%d pos=%d ok=%02x bad=%02x",
512  key, i, j, byteVal(key, i, j), c.buf[j]);
513  }
514  }
515  for (j = c.aArraySize + off; j < c.bufsiz; j++) {
516  if (c.buf[j] != 'C') {
517  return chkerror("mismatch after key=%d col=%d pos=%d ok=%02x bad=%02x",
518  key, i, j, 'C', c.buf[j]);
519  }
520  }
521  } else {
522  char* buf = c.aRa->aRef();
523  if (buf == 0)
524  return ndberror("null aRef key=%d col%d", key, i);
525  for (int j = 0; j < c.aArraySize; j++) {
526  if (buf[j] != byteVal(key, i, j)) {
527  return chkerror("mismatch key=%d col=%d pos=%d ok=%02x bad=%02x",
528  key, i, j, byteVal(key, i, j), buf[j]);
529  }
530  }
531  }
532  }
533  cnt++;
534  }
535  if (ret < 0)
536  return ndberror("nextScanResult key=%d", key);
537  if (cnt != 1)
538  return ndberror("scan key=%d found %d", key, cnt);
539  found[key] = 1;
540  ndb->closeTransaction(con);
541  }
542  con = 0;
543  op = 0;
544  for (k = 0; k < opercnt; k++)
545  if (! found[k])
546  return ndberror("key %d not found", k);
547  ndbout << "scanned " << key << endl;
548 
549  ndbout << "done" << endl;
550  return 0;
551 }
552 
553 NDB_COMMAND(testDataBuffers, "testDataBuffers", "testDataBuffers", "testDataBuffers", 65535)
554 {
555  int i;
556  ndb_init();
557  while (++argv, --argc > 0) {
558  char const* p = argv[0];
559  if (*p++ != '-' || strlen(p) != 1)
560  goto wrongargs;
561  switch (*p) {
562  case 'a':
563  if (++argv, --argc > 0) {
564  attrcnt = atoi(argv[0]);
565  if (1 <= attrcnt && attrcnt <= MaxAttr)
566  break;
567  }
568  goto wrongargs;
569  case 'e':
570  existok = 1;
571  break;
572  case 'k':
573  kontinue = true;
574  break;
575  case 'l':
576  if (++argv, --argc > 0) {
577  loopcnt = atoi(argv[0]);
578  if (0 <= loopcnt)
579  break;
580  }
581  goto wrongargs;
582  case 'o':
583  if (++argv, --argc > 0) {
584  opercnt = atoi(argv[0]);
585  if (0 <= opercnt && opercnt <= MaxOper)
586  break;
587  }
588  goto wrongargs;
589  case 'r':
590  if (++argv, --argc > 0) {
591  randomizer = atoi(argv[0]);
592  if (1 <= randomizer)
593  break;
594  }
595  goto wrongargs;
596  case 's':
597  if (++argv, --argc > 0) {
598  sizelim = atoi(argv[0]);
599  if (1 <= sizelim && sizelim <= MaxSize)
600  break;
601  }
602  goto wrongargs;
603  case 'x':
604  xverbose = 1;
605  break;
606  default:
607  wrongargs:
608  printusage();
609  return NDBT_ProgramExit(NDBT_WRONGARGS);
610  }
611  }
612 
613  unsigned ok = true;
614 
616  if(con.connect(12, 5, 1))
617  {
618  return NDBT_ProgramExit(NDBT_FAILED);
619  }
620 
621  ndb = new Ndb(&con, "TEST_DB");
622  if (ndb->init() != 0)
623  {
624  ndberror("init");
625  ok = false;
626  goto out;
627  }
628  if (ndb->waitUntilReady(30) < 0)
629  {
630  ndberror("waitUntilReady");
631  ok = false;
632  goto out;
633  }
634 
635  for (i = 1; 0 == loopcnt || i <= loopcnt; i++) {
636  ndbout << "=== loop " << i << " ===" << endl;
637  for (int flag = 0; flag < (1<<testbits); flag++) {
638  if (testcase(con, flag) < 0) {
639  ok = false;
640  if (! kontinue)
641  goto out;
642  }
644  dict->dropTable(tab);
645  }
646  }
647 
648 out:
649  delete ndb;
650  return NDBT_ProgramExit(ok ? NDBT_OK : NDBT_FAILED);
651 }
652 
653 // vim: set sw=4: