MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NdbApiTwsDriver.cpp
1 /* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=4:tabstop=4:smarttab:
3  *
4  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 #include "NdbApiTwsDriver.hpp"
21 
22 #include <iostream>
23 #include <string>
24 #include <cassert>
25 
26 #include "helpers.hpp"
27 #include "string_helpers.hpp"
28 #include "Properties.hpp"
29 
30 using std::cout;
31 using std::flush;
32 using std::endl;
33 using std::ios_base;
34 using std::string;
35 
36 using utils::Properties;
37 using utils::toBool;
38 using utils::toInt;
39 using utils::toString;
40 
41 // ---------------------------------------------------------------------------
42 // Helper Macros & Functions
43 // ---------------------------------------------------------------------------
44 
45 // This benchmark's error handling of NDBAPI calls is rigorous but crude:
46 // - all calls' return value is checked for errors
47 // - all errors are reported and then followed by a process exit
48 #define ABORT_NDB_ERROR(error) \
49  do { cout << "!!! error in " << __FILE__ << ", line: " << __LINE__ \
50  << ", code: " << (int)(error).code \
51  << ", msg: " << (error).message << "." << endl; \
52  exit(-1); \
53  } while (0)
54 
55 // ---------------------------------------------------------------------------
56 // NDB API Model Implementation
57 // ---------------------------------------------------------------------------
58 
59 NdbApiTwsModel::NdbApiTwsModel(Ndb* ndb) {
60  const NdbDictionary::Dictionary* dict = ndb->getDictionary();
61 
62  // get table T0
63  if ((table_t0 = dict->getTable("mytable")) == NULL)
64  ABORT_NDB_ERROR(dict->getNdbError());
65 
66  // get columns of table T0
67  if ((column_c0 = table_t0->getColumn("c0")) == NULL)
68  ABORT_NDB_ERROR(dict->getNdbError());
69  if ((column_c1 = table_t0->getColumn("c1")) == NULL)
70  ABORT_NDB_ERROR(dict->getNdbError());
71  if ((column_c2 = table_t0->getColumn("c2")) == NULL)
72  ABORT_NDB_ERROR(dict->getNdbError());
73  if ((column_c3 = table_t0->getColumn("c3")) == NULL)
74  ABORT_NDB_ERROR(dict->getNdbError());
75  if ((column_c4 = table_t0->getColumn("c4")) == NULL)
76  ABORT_NDB_ERROR(dict->getNdbError());
77  if ((column_c5 = table_t0->getColumn("c5")) == NULL)
78  ABORT_NDB_ERROR(dict->getNdbError());
79  if ((column_c6 = table_t0->getColumn("c6")) == NULL)
80  ABORT_NDB_ERROR(dict->getNdbError());
81  if ((column_c7 = table_t0->getColumn("c7")) == NULL)
82  ABORT_NDB_ERROR(dict->getNdbError());
83  if ((column_c8 = table_t0->getColumn("c8")) == NULL)
84  ABORT_NDB_ERROR(dict->getNdbError());
85  if ((column_c9 = table_t0->getColumn("c9")) == NULL)
86  ABORT_NDB_ERROR(dict->getNdbError());
87  if ((column_c10 = table_t0->getColumn("c10")) == NULL)
88  ABORT_NDB_ERROR(dict->getNdbError());
89  if ((column_c11 = table_t0->getColumn("c11")) == NULL)
90  ABORT_NDB_ERROR(dict->getNdbError());
91  if ((column_c12 = table_t0->getColumn("c12")) == NULL)
92  ABORT_NDB_ERROR(dict->getNdbError());
93  if ((column_c13 = table_t0->getColumn("c13")) == NULL)
94  ABORT_NDB_ERROR(dict->getNdbError());
95  if ((column_c14 = table_t0->getColumn("c14")) == NULL)
96  ABORT_NDB_ERROR(dict->getNdbError());
97 
98  // get attribute ids for columns of table T0
99  attr_c0 = column_c0->getAttrId();
100  attr_c1 = column_c1->getAttrId();
101  attr_c2 = column_c2->getAttrId();
102  attr_c3 = column_c3->getAttrId();
103  attr_c4 = column_c4->getAttrId();
104  attr_c5 = column_c5->getAttrId();
105  attr_c6 = column_c6->getAttrId();
106  attr_c7 = column_c7->getAttrId();
107  attr_c8 = column_c8->getAttrId();
108  attr_c9 = column_c9->getAttrId();
109  attr_c10 = column_c10->getAttrId();
110  attr_c11 = column_c11->getAttrId();
111  attr_c12 = column_c12->getAttrId();
112  attr_c13 = column_c13->getAttrId();
113  attr_c14 = column_c14->getAttrId();
114 
115  width_c0 = columnWidth(column_c0);
116  width_c1 = columnWidth(column_c1);
117  width_c2 = columnWidth(column_c2);
118  width_c3 = columnWidth(column_c3);
119  width_c4 = columnWidth(column_c4);
120  width_c5 = columnWidth(column_c5);
121  width_c6 = columnWidth(column_c6);
122  width_c7 = columnWidth(column_c7);
123  width_c8 = columnWidth(column_c8);
124  width_c9 = columnWidth(column_c9);
125  width_c10 = columnWidth(column_c10);
126  width_c11 = columnWidth(column_c11);
127  width_c12 = columnWidth(column_c12);
128  width_c13 = columnWidth(column_c13);
129  width_c14 = columnWidth(column_c14);
130 
131  width_row = (
132  + width_c0
133  + width_c1
134  + width_c2
135  + width_c3
136  + width_c4
137  + width_c5
138  + width_c6
139  + width_c7
140  + width_c8
141  + width_c9
142  + width_c10
143  + width_c11
144  + width_c12
145  + width_c13
146  + width_c14);
147 }
148 
149 // ---------------------------------------------------------------------------
150 // NdbApiTwsDriver Implementation
151 // ---------------------------------------------------------------------------
152 
153 void
154 NdbApiTwsDriver::init() {
155  TwsDriver::init();
156 
157  // ndb_init must be called first
158  cout << endl
159  << "initializing NDBAPI ..." << flush;
160  int stat = ndb_init();
161  if (stat != 0)
162  ABORT_ERROR("ndb_init() returned: " << stat);
163  cout << " [ok]" << endl;
164 
165  initConnection();
166 }
167 
168 void
169 NdbApiTwsDriver::close() {
170  closeConnection();
171 
172  // ndb_close must be called last
173  cout << "closing NDBAPI ... " << flush;
174  ndb_end(0);
175  cout << " [ok]" << endl;
176 
177  TwsDriver::close();
178 }
179 
180 void
181 NdbApiTwsDriver::initProperties() {
182  TwsDriver::initProperties();
183 
184  cout << "setting ndb properties ..." << flush;
185 
186  ostringstream msg;
187 
188  mgmdConnect = toString(props[L"ndb.mgmdConnect"]);
189  if (mgmdConnect.empty()) {
190  mgmdConnect = string("localhost");
191  }
192 
193  catalog = toString(props[L"ndb.catalog"]);
194  if (catalog.empty()) {
195  catalog = string("testdb");
196  }
197 
198  schema = toString(props[L"ndb.schema"]);
199  if (schema.empty()) {
200  schema = string("def");
201  }
202 
203  //if (msg.tellp() == 0) {
204  if (msg.str().empty()) {
205  cout << " [ok]" << endl;
206  } else {
207  cout << endl << msg.str() << endl;
208  }
209 
210  descr = "ndbapi(" + mgmdConnect + ")";
211 }
212 
213 void
214 NdbApiTwsDriver::printProperties() {
215  TwsDriver::printProperties();
216 
217  const ios_base::fmtflags f = cout.flags();
218  // no effect calling manipulator function, not sure why
219  //cout << ios_base::boolalpha;
220  cout.flags(ios_base::boolalpha);
221 
222  cout << endl << "ndb settings ..." << endl;
223  cout << "ndb.mgmdConnect: \"" << mgmdConnect << "\"" << endl;
224  cout << "ndb.catalog: \"" << catalog << "\"" << endl;
225  cout << "ndb.schema: \"" << schema << "\"" << endl;
226 
227  cout.flags(f);
228 }
229 
230 void
231 NdbApiTwsDriver::initNdbapiBuffers() {
232  assert(model->column_c0 != NULL);
233  assert(bb == NULL);
234  assert(ra == NULL);
235 
236  cout << "allocating ndbapi buffers ..." << flush;
237  bb = new char[model->width_row * nRows];
238  ra = new NdbRecAttr*[model->nCols * nRows];
239  cout << " [ok]" << endl;
240 }
241 
242 void
243 NdbApiTwsDriver::closeNdbapiBuffers() {
244  assert(bb != NULL);
245  assert(ra != NULL);
246 
247  cout << "releasing ndbapi buffers ..." << flush;
248  delete[] ra;
249  ra = NULL;
250  delete[] bb;
251  bb = NULL;
252  cout << " [ok]" << endl;
253 }
254 
255 // ---------------------------------------------------------------------------
256 
257 void
258 NdbApiTwsDriver::runLoadOperations() {
259  cout << endl
260  << "running NDB API operations ..." << " [nRows=" << nRows << "]"
261  << endl;
262 
263  if (doSingle) {
264  if (doInsert) runNdbapiInsert(SINGLE);
265  if (doLookup) runNdbapiLookup(SINGLE);
266  if (doUpdate) runNdbapiUpdate(SINGLE);
267  if (doDelete) runNdbapiDelete(SINGLE);
268  }
269  if (doBulk) {
270  if (doInsert) runNdbapiInsert(BULK);
271  if (doLookup) runNdbapiLookup(BULK);
272  if (doUpdate) runNdbapiUpdate(BULK);
273  if (doDelete) runNdbapiDelete(BULK);
274  }
275  if (doBatch) {
276  if (doInsert) runNdbapiInsert(BATCH);
277  if (doLookup) runNdbapiLookup(BATCH);
278  if (doUpdate) runNdbapiUpdate(BATCH);
279  if (doDelete) runNdbapiDelete(BATCH);
280  }
281 }
282 
283 // Alternative Implementation:
284 // The recurring pattern of runNdbapiXXX(XMode mode) can be parametrized
285 // over the operation, for instance, by a member function template:
286 //
287 // template< XMode M, void (NdbApiTwsDriver::*OP)(int) >
288 // void runOp(string name);
289 //
290 // which tests the template parameter XMode and calls the operation
291 // ...
292 // if (M == SINGLE) {
293 // ... (this->*OP)(i); ...
294 // }
295 // ...
296 // while the caller selects the mode and function to be invoked
297 // ...
298 // switch (mode) {
299 // case SINGLE:
300 // runOp< SINGLE, &NdbApiTwsDriver::ndbapiInsert >(name);
301 // }...
302 // Alas, it turns out not worth it in terms of readability and lines of code.
303 
304 void
305 NdbApiTwsDriver::runNdbapiInsert(XMode mode) {
306  const string name = string("insert_") + toStr(mode);
307  begin(name);
308 
309  if (mode == SINGLE) {
310  for(int i = 0; i < nRows; i++) {
311  ndbapiBeginTransaction();
312  ndbapiInsert(i);
313  ndbapiCommitTransaction();
314  ndbapiCloseTransaction();
315  }
316  } else {
317  ndbapiBeginTransaction();
318  for(int i = 0; i < nRows; i++) {
319  ndbapiInsert(i);
320  if (mode == BULK)
321  ndbapiExecuteTransaction();
322  }
323  ndbapiCommitTransaction();
324  ndbapiCloseTransaction();
325  }
326 
327  finish(name);
328 }
329 
330 void
331 NdbApiTwsDriver::ndbapiInsert(int c0) {
332  // get an insert operation for the table
333  NdbOperation* op = tx->getNdbOperation(model->table_t0);
334  if (op == NULL)
335  ABORT_NDB_ERROR(tx->getNdbError());
336  if (op->insertTuple() != 0)
337  ABORT_NDB_ERROR(tx->getNdbError());
338 
339  // values
340  Uint32 i = c0;
341  const int maxlen = 256;
342  char str[maxlen];
343  snprintf(str, maxlen, "%d", i);
344 
345  // set values; key attribute needs to be set first
346  ndbapiToBuffer1blp(bb_pos, str, model->width_c0);
347  if (op->equal(model->attr_c0, bb_pos) != 0) // key
348  ABORT_NDB_ERROR(tx->getNdbError());
349  bb_pos += model->width_c0;
350 
351  ndbapiToBuffer1blp(bb_pos, str, model->width_c1);
352  if (op->setValue(model->attr_c1, bb_pos) != 0)
353  ABORT_NDB_ERROR(tx->getNdbError());
354  bb_pos += model->width_c1;
355 
356  if (op->setValue(model->attr_c2, i) != 0)
357  ABORT_NDB_ERROR(tx->getNdbError());
358  bb_pos += model->width_c2;
359 
360  if (op->setValue(model->attr_c3, i) != 0)
361  ABORT_NDB_ERROR(tx->getNdbError());
362  bb_pos += model->width_c3;
363 
364  if (op->setValue(model->attr_c4, (char*)NULL) != 0)
365  ABORT_NDB_ERROR(tx->getNdbError());
366  bb_pos += model->width_c4;
367 
368  ndbapiToBuffer1blp(bb_pos, str, model->width_c5);
369  if (op->setValue(model->attr_c5, bb_pos) != 0)
370  ABORT_NDB_ERROR(tx->getNdbError());
371  bb_pos += model->width_c5;
372 
373  ndbapiToBuffer1blp(bb_pos, str, model->width_c6);
374  if (op->setValue(model->attr_c6, bb_pos) != 0)
375  ABORT_NDB_ERROR(tx->getNdbError());
376  bb_pos += model->width_c6;
377 
378  ndbapiToBuffer1blp(bb_pos, str, model->width_c7);
379  if (op->setValue(model->attr_c7, bb_pos) != 0)
380  ABORT_NDB_ERROR(tx->getNdbError());
381  bb_pos += model->width_c7;
382 
383  ndbapiToBuffer1blp(bb_pos, str, model->width_c8);
384  if (op->setValue(model->attr_c8, bb_pos) != 0)
385  ABORT_NDB_ERROR(tx->getNdbError());
386  bb_pos += model->width_c8;
387 
388  if (op->setValue(model->attr_c9, (char*)NULL) != 0)
389  ABORT_NDB_ERROR(tx->getNdbError());
390  bb_pos += model->width_c9;
391 
392  if (op->setValue(model->attr_c10, (char*)NULL) != 0)
393  ABORT_NDB_ERROR(tx->getNdbError());
394  bb_pos += model->width_c10;
395 
396  if (op->setValue(model->attr_c11, (char*)NULL) != 0)
397  ABORT_NDB_ERROR(tx->getNdbError());
398  bb_pos += model->width_c11;
399 
400  if (op->setValue(model->attr_c12, (char*)NULL) != 0)
401  ABORT_NDB_ERROR(tx->getNdbError());
402  bb_pos += model->width_c12;
403 
404  if (op->setValue(model->attr_c13, (char*)NULL) != 0)
405  ABORT_NDB_ERROR(tx->getNdbError());
406  bb_pos += model->width_c13;
407 
408  if (op->setValue(model->attr_c14, (char*)NULL) != 0)
409  ABORT_NDB_ERROR(tx->getNdbError());
410  bb_pos += model->width_c14;
411 }
412 
413 void
414 NdbApiTwsDriver::runNdbapiLookup(XMode mode) {
415  const string name = string("lookup_") + toStr(mode);
416  begin(name);
417 
418  if (mode == SINGLE) {
419  for(int i = 0; i < nRows; i++) {
420  ndbapiBeginTransaction();
421  ndbapiLookup(i);
422  ndbapiCommitTransaction();
423  ndbapiRead(i);
424  ndbapiCloseTransaction();
425  }
426  } else {
427  ndbapiBeginTransaction();
428  for(int i = 0; i < nRows; i++) {
429  ndbapiLookup(i);
430 
431  if (mode == BULK)
432  ndbapiExecuteTransaction();
433  }
434  ndbapiCommitTransaction();
435  for(int i = 0; i < nRows; i++) {
436  ndbapiRead(i);
437  }
438  ndbapiCloseTransaction();
439  }
440 
441  finish(name);
442 }
443 
444 void
445 NdbApiTwsDriver::ndbapiLookup(int c0) {
446  // get a lookup operation for the table
447  NdbOperation* op = tx->getNdbOperation(model->table_t0);
448  if (op == NULL)
449  ABORT_NDB_ERROR(tx->getNdbError());
450  if (op->readTuple(ndbOpLockMode) != 0)
451  ABORT_NDB_ERROR(tx->getNdbError());
452 
453  // values
454  Uint32 i = c0;
455  const int maxlen = 256;
456  char str[maxlen];
457  snprintf(str, maxlen, "%d", i);
458 
459  // set values; key attribute needs to be set first
460  ndbapiToBuffer1blp(bb_pos, str, model->width_c0);
461  if (op->equal(model->attr_c0, bb_pos) != 0) // key
462  ABORT_NDB_ERROR(tx->getNdbError());
463  bb_pos += model->width_c0;
464 
465  // get attributes (not readable until after commit)
466  if ((*ra_pos = op->getValue(model->attr_c1, bb_pos)) == NULL)
467  ABORT_NDB_ERROR(tx->getNdbError());
468  bb_pos += model->width_c1;
469  ra_pos++;
470 
471  if ((*ra_pos = op->getValue(model->attr_c2, bb_pos)) == NULL)
472  ABORT_NDB_ERROR(tx->getNdbError());
473  bb_pos += model->width_c2;
474  ra_pos++;
475 
476  if ((*ra_pos = op->getValue(model->attr_c3, bb_pos)) == NULL)
477  ABORT_NDB_ERROR(tx->getNdbError());
478  bb_pos += model->width_c3;
479  ra_pos++;
480 
481  if ((*ra_pos = op->getValue(model->attr_c4, bb_pos)) == NULL)
482  ABORT_NDB_ERROR(tx->getNdbError());
483  bb_pos += model->width_c4;
484  ra_pos++;
485 
486  if ((*ra_pos = op->getValue(model->attr_c5, bb_pos)) == NULL)
487  ABORT_NDB_ERROR(tx->getNdbError());
488  bb_pos += model->width_c5;
489  ra_pos++;
490 
491  if ((*ra_pos = op->getValue(model->attr_c6, bb_pos)) == NULL)
492  ABORT_NDB_ERROR(tx->getNdbError());
493  bb_pos += model->width_c6;
494  ra_pos++;
495 
496  if ((*ra_pos = op->getValue(model->attr_c7, bb_pos)) == NULL)
497  ABORT_NDB_ERROR(tx->getNdbError());
498  bb_pos += model->width_c7;
499  ra_pos++;
500 
501  if ((*ra_pos = op->getValue(model->attr_c8, bb_pos)) == NULL)
502  ABORT_NDB_ERROR(tx->getNdbError());
503  bb_pos += model->width_c8;
504  ra_pos++;
505 
506  if ((*ra_pos = op->getValue(model->attr_c9, bb_pos)) == NULL)
507  ABORT_NDB_ERROR(tx->getNdbError());
508  bb_pos += model->width_c9;
509  ra_pos++;
510 
511  if ((*ra_pos = op->getValue(model->attr_c10, bb_pos)) == NULL)
512  ABORT_NDB_ERROR(tx->getNdbError());
513  bb_pos += model->width_c10;
514  ra_pos++;
515 
516  if ((*ra_pos = op->getValue(model->attr_c11, bb_pos)) == NULL)
517  ABORT_NDB_ERROR(tx->getNdbError());
518  bb_pos += model->width_c11;
519  ra_pos++;
520 
521  if ((*ra_pos = op->getValue(model->attr_c12, bb_pos)) == NULL)
522  ABORT_NDB_ERROR(tx->getNdbError());
523  bb_pos += model->width_c12;
524  ra_pos++;
525 
526  if ((*ra_pos = op->getValue(model->attr_c13, bb_pos)) == NULL)
527  ABORT_NDB_ERROR(tx->getNdbError());
528  bb_pos += model->width_c13;
529  ra_pos++;
530 
531  if ((*ra_pos = op->getValue(model->attr_c14, bb_pos)) == NULL)
532  ABORT_NDB_ERROR(tx->getNdbError());
533  bb_pos += model->width_c14;
534  ra_pos++;
535 }
536 
537 void
538 NdbApiTwsDriver::ndbapiRead(int c0) {
539  // values
540  const int maxlen = 256;
541  char str0[maxlen];
542  snprintf(str0, maxlen, "%d", c0);
543  Int32 i1;
544  char str1[maxlen];
545 
546  // no need to read key column
547  bb_pos += model->width_c0;
548 
549  ndbapiToString1blp(str1, bb_pos, model->width_c1);
550  verify(str0, str1);
551  bb_pos += model->width_c1;
552  ra_pos++;
553 
554  memcpy(&i1, bb_pos, model->width_c2);
555  verify(c0, i1);
556  bb_pos += model->width_c2;
557  ra_pos++;
558 
559  memcpy(&i1, bb_pos, model->width_c3);
560  verify(c0, i1);
561  bb_pos += model->width_c3;
562  ra_pos++;
563 
564  // null expected
565  verify(1, (*ra_pos)->isNULL());
566  bb_pos += model->width_c4;
567  ra_pos++;
568 
569  ndbapiToString1blp(str1, bb_pos, model->width_c5);
570  verify(str0, str1);
571  bb_pos += model->width_c5;
572  ra_pos++;
573 
574  ndbapiToString1blp(str1, bb_pos, model->width_c6);
575  verify(str0, str1);
576  bb_pos += model->width_c6;
577  ra_pos++;
578 
579  ndbapiToString1blp(str1, bb_pos, model->width_c7);
580  verify(str0, str1);
581  bb_pos += model->width_c7;
582  ra_pos++;
583 
584  ndbapiToString1blp(str1, bb_pos, model->width_c8);
585  verify(str0, str1);
586  bb_pos += model->width_c8;
587  ra_pos++;
588 
589  // null expected
590  verify(1, (*ra_pos)->isNULL());
591  bb_pos += model->width_c9;
592  ra_pos++;
593 
594  // null expected
595  verify(1, (*ra_pos)->isNULL());
596  bb_pos += model->width_c10;
597  ra_pos++;
598 
599  // null expected
600  verify(1, (*ra_pos)->isNULL());
601  bb_pos += model->width_c11;
602  ra_pos++;
603 
604  // null expected
605  verify(1, (*ra_pos)->isNULL());
606  bb_pos += model->width_c12;
607  ra_pos++;
608 
609  // null expected
610  verify(1, (*ra_pos)->isNULL());
611  bb_pos += model->width_c13;
612  ra_pos++;
613 
614  // null expected
615  verify(1, (*ra_pos)->isNULL());
616  bb_pos += model->width_c14;
617  ra_pos++;
618 }
619 
620 void
621 NdbApiTwsDriver::runNdbapiUpdate(XMode mode) {
622  const string name = string("update_") + toStr(mode);
623  begin(name);
624 
625  if (mode == SINGLE) {
626  for(int i = 0; i < nRows; i++) {
627  ndbapiBeginTransaction();
628  ndbapiUpdate(i);
629  ndbapiCommitTransaction();
630  ndbapiCloseTransaction();
631  }
632  } else {
633  ndbapiBeginTransaction();
634  for(int i = 0; i < nRows; i++) {
635  ndbapiUpdate(i);
636  if (mode == BULK)
637  ndbapiExecuteTransaction();
638  }
639  ndbapiCommitTransaction();
640  ndbapiCloseTransaction();
641  }
642 
643  finish(name);
644 }
645 
646 void
647 NdbApiTwsDriver::ndbapiUpdate(int c0) {
648  // get an update operation for the table
649  NdbOperation* op = tx->getNdbOperation(model->table_t0);
650  if (op == NULL)
651  ABORT_NDB_ERROR(tx->getNdbError());
652  if (op->updateTuple() != 0)
653  ABORT_NDB_ERROR(tx->getNdbError());
654 
655  // values
656  const int maxlen = 256;
657  char str0[maxlen];
658  snprintf(str0, maxlen, "%d", c0);
659  int i = -c0;
660  char str1[maxlen];
661  snprintf(str1, maxlen, "%d", i);
662 
663  // set values; key attribute needs to be set first
664  ndbapiToBuffer1blp(bb_pos, str0, model->width_c0);
665  if (op->equal(model->attr_c0, bb_pos) != 0) // key
666  ABORT_NDB_ERROR(tx->getNdbError());
667  bb_pos += model->width_c0;
668 
669  ndbapiToBuffer1blp(bb_pos, str1, model->width_c1);
670  if (op->setValue(model->attr_c1, bb_pos) != 0)
671  ABORT_NDB_ERROR(tx->getNdbError());
672  bb_pos += model->width_c1;
673 
674  if (op->setValue(model->attr_c2, i) != 0)
675  ABORT_NDB_ERROR(tx->getNdbError());
676  bb_pos += model->width_c2;
677 
678  if (op->setValue(model->attr_c3, i) != 0)
679  ABORT_NDB_ERROR(tx->getNdbError());
680  bb_pos += model->width_c3;
681 
682  ndbapiToBuffer1blp(bb_pos, str1, model->width_c5);
683  if (op->setValue(model->attr_c5, bb_pos) != 0)
684  ABORT_NDB_ERROR(tx->getNdbError());
685  bb_pos += model->width_c5;
686 
687  ndbapiToBuffer1blp(bb_pos, str1, model->width_c6);
688  if (op->setValue(model->attr_c6, bb_pos) != 0)
689  ABORT_NDB_ERROR(tx->getNdbError());
690  bb_pos += model->width_c6;
691 
692  ndbapiToBuffer1blp(bb_pos, str1, model->width_c7);
693  if (op->setValue(model->attr_c7, bb_pos) != 0)
694  ABORT_NDB_ERROR(tx->getNdbError());
695  bb_pos += model->width_c7;
696 
697  ndbapiToBuffer1blp(bb_pos, str1, model->width_c8);
698  if (op->setValue(model->attr_c8, bb_pos) != 0)
699  ABORT_NDB_ERROR(tx->getNdbError());
700  bb_pos += model->width_c8;
701 }
702 
703 void
704 NdbApiTwsDriver::runNdbapiDelete(XMode mode) {
705  const string name = string("delete_") + toStr(mode);
706  begin(name);
707 
708  if (mode == SINGLE) {
709  for(int i = 0; i < nRows; i++) {
710  ndbapiBeginTransaction();
711  ndbapiDelete(i);
712  ndbapiCommitTransaction();
713  ndbapiCloseTransaction();
714  }
715  } else {
716  ndbapiBeginTransaction();
717  for(int i = 0; i < nRows; i++) {
718  ndbapiDelete(i);
719  if (mode == BULK)
720  ndbapiExecuteTransaction();
721  }
722  ndbapiCommitTransaction();
723  ndbapiCloseTransaction();
724  }
725 
726  finish(name);
727 }
728 
729 void
730 NdbApiTwsDriver::ndbapiDelete(int c0) {
731  // get a delete operation for the table
732  NdbOperation* op = tx->getNdbOperation(model->table_t0);
733  if (op == NULL)
734  ABORT_NDB_ERROR(tx->getNdbError());
735  if (op->deleteTuple() != 0)
736  ABORT_NDB_ERROR(tx->getNdbError());
737 
738  // values
739  Uint32 i = c0;
740  const int maxlen = 256;
741  char str[maxlen];
742  snprintf(str, maxlen, "%d", i);
743 
744  // set values; key attribute needs to be set first
745  ndbapiToBuffer1blp(bb_pos, str, model->width_c0);
746  if (op->equal(model->attr_c0, bb_pos) != 0) // key
747  ABORT_NDB_ERROR(tx->getNdbError());
748  bb_pos += model->width_c0;
749 }
750 
751 // ----------------------------------------------------------------------
752 
753 void
754 NdbApiTwsDriver::ndbapiBeginTransaction() {
755  assert(tx == NULL);
756 
757  // prepare buffer for writing
758  bb_pos = bb; // clear
759  ra_pos = ra;
760 
761  // start a transaction
762  // must be closed with Ndb::closeTransaction or NdbTransaction::close
763  if ((tx = ndb->startTransaction()) == NULL)
764  ABORT_NDB_ERROR(ndb->getNdbError());
765 }
766 
767 void
768 NdbApiTwsDriver::ndbapiExecuteTransaction() {
769  assert(tx != NULL);
770 
771  // execute but don't commit the current transaction
772  if (tx->execute(NdbTransaction::NoCommit) != 0
774  ABORT_NDB_ERROR(tx->getNdbError());
775 }
776 
777 void
778 NdbApiTwsDriver::ndbapiCommitTransaction() {
779  assert(tx != NULL);
780 
781  // commit the current transaction
782  if (tx->execute(NdbTransaction::Commit) != 0
784  ABORT_NDB_ERROR(tx->getNdbError());
785 
786  // prepare buffer for reading
787  bb_pos = bb; // rewind
788  ra_pos = ra;
789 }
790 
791 void
792 NdbApiTwsDriver::ndbapiCloseTransaction() {
793  assert(tx != NULL);
794 
795  // close the current transaction
796  // to be called irrespectively of success or failure
797  ndb->closeTransaction(tx);
798  tx = NULL;
799 }
800 
801 // ---------------------------------------------------------------------------
802 
803 void
804 NdbApiTwsDriver::initConnection() {
805  assert(mgmd == NULL);
806  assert(ndb == NULL);
807  assert(tx == NULL);
808  assert(model == NULL);
809 
810  cout << endl;
811 
812  // instantiate NDB cluster singleton
813  cout << "creating cluster connection ..." << flush;
814  assert(!mgmdConnect.empty());
815  mgmd = new Ndb_cluster_connection(mgmdConnect.c_str());
816  cout << " [ok]" << endl; // no useful mgmd->string conversion
817 
818  // connect to cluster management node (ndb_mgmd)
819  cout << "connecting to mgmd ..." << flush;
820  const int retries = 0; // number of retries (< 0 = indefinitely)
821  const int delay = 0; // seconds to wait after retry
822  const int verbose = 1; // print report of progess
823  // returns: 0 = success, 1 = recoverable error, -1 = non-recoverable error
824  if (mgmd->connect(retries, delay, verbose) != 0)
825  ABORT_ERROR("mgmd@" << mgmdConnect << " was not ready within "
826  << (retries * delay) << "s.");
827  cout << " [ok: " << mgmdConnect << "]" << endl;
828 
829  // optionally, connect and wait for reaching the data nodes (ndbds)
830  cout << "waiting for data nodes ..." << flush;
831  const int initial_wait = 10; // seconds to wait until first node detected
832  const int final_wait = 0; // seconds to wait after first node detected
833  // returns: 0 all nodes live, > 0 at least one node live, < 0 error
834  if (mgmd->wait_until_ready(initial_wait, final_wait) < 0)
835  ABORT_ERROR("data nodes were not ready within "
836  << (initial_wait + final_wait) << "s.");
837  cout << " [ok]" << endl;
838 
839  // connect to database
840  cout << "connecting to database ..." << flush;
841  ndb = new Ndb(mgmd, catalog.c_str(), schema.c_str());
842  const int max_no_tx = 10; // maximum number of parallel tx (<=1024)
843  // note each scan or index scan operation uses one extra transaction
844  //if (ndb->init() != 0)
845  if (ndb->init(max_no_tx) != 0)
846  ABORT_NDB_ERROR(ndb->getNdbError());
847  cout << " [ok: " << catalog << "." << schema << "]" << endl;
848 
849  cout << "caching metadata ..." << flush;
850  model = new NdbApiTwsModel(ndb);
851  cout << " [ok]" << endl;
852 
853  initNdbapiBuffers();
854 
855  cout << "using lock mode for reads ..." << flush;
856  string lm;
857  switch (lockMode) {
858  case READ_COMMITTED:
859  ndbOpLockMode = NdbOperation::LM_CommittedRead;
860  lm = "LM_CommittedRead";
861  break;
862  case SHARED:
863  ndbOpLockMode = NdbOperation::LM_Read;
864  lm = "LM_Read";
865  break;
866  case EXCLUSIVE:
867  ndbOpLockMode = NdbOperation::LM_Exclusive;
868  lm = "LM_Exclusive";
869  break;
870  default:
871  ndbOpLockMode = NdbOperation::LM_CommittedRead;
872  lm = "LM_CommittedRead";
873  assert(false);
874  }
875  cout << " [ok: " + lm + "]" << endl;
876 }
877 
878 void
879 NdbApiTwsDriver::closeConnection() {
880  assert(mgmd != NULL);
881  assert(ndb != NULL);
882  assert(tx == NULL);
883  assert(model != NULL);
884 
885  cout << endl;
886 
887  closeNdbapiBuffers();
888 
889  cout << "clearing metadata cache ..." << flush;
890  delete model;
891  model = NULL;
892  cout << " [ok]" << endl;
893 
894  cout << "closing database connection ..." << flush;
895  // no ndb->close();
896  delete ndb;
897  ndb = NULL;
898  cout << " [ok]" << endl;
899 
900  cout << "closing cluster connection ..." << flush;
901  delete mgmd;
902  mgmd = NULL;
903  cout << " [ok]" << endl;
904 }
905 
906 //---------------------------------------------------------------------------
907 
908 void
909 NdbApiTwsDriver::ndbapiToBuffer1blp(void* to, const char* from, size_t width) {
910  char* t = (char*)to;
911  size_t n = strlen(from);
912  assert(0 <= n && n < width && width < 256); // width <= 256 ?
913 
914  memcpy(t + 1, from, n);
915  *t = n;
916 }
917 
918 void
919 NdbApiTwsDriver::ndbapiToString1blp(char* to, const void* from, size_t width) {
920  const char* s = (const char*)from;
921  size_t n = *s;
922  assert(0 <= n && n < width && width < 256); // width <= 256 ?
923 
924  memcpy(to, s + 1, n);
925  to[n] = '\0';
926 }
927 
928 // ---------------------------------------------------------------------------
929 
930 int
931 main(int argc, const char* argv[])
932 {
934  NdbApiTwsDriver d;
935  d.run();
936 
937  return 0;
938 }
939 
940 //---------------------------------------------------------------------------