1 /*
2 Copyright (c) 2003, 2020 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, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include <NDBT.hpp>
26 #include <NDBT_Test.hpp>
27 #include <HugoTransactions.hpp>
28 #include <UtilTransactions.hpp>
29 #include <NdbRestarter.hpp>
30 #include <Vector.hpp>
31 #include <signaldata/DumpStateOrd.hpp>
32 #include <../../include/kernel/ndb_limits.h>
33 #include <../../include/kernel/trigger_definitions.h>
34 #include <signaldata/DictTabInfo.hpp>
35 #include <random.h>
36 #include <NdbAutoPtr.hpp>
37 #include <NdbMixRestarter.hpp>
38 #include <NdbBackup.hpp>
39 #include <NdbSqlUtil.hpp>
40 #include <NdbEnv.h>
41 #include <NdbHost.h>
42 #include <ndb_rand.h>
43 #include <Bitmask.hpp>
44 #include <../src/kernel/ndbd.hpp>
45 #include <NdbMgmd.hpp>
46
47 #define ERR_INSERT_MASTER_FAILURE1 6013
48 #define ERR_INSERT_MASTER_FAILURE2 6014
49 #define ERR_INSERT_MASTER_FAILURE3 6015
50
51 #define ERR_INSERT_PARTIAL_START_FAIL 6140
52 #define ERR_INSERT_PARTIAL_PARSE_FAIL 6141
53 #define ERR_INSERT_PARTIAL_FLUSH_PREPARE_FAIL 6142
54 #define ERR_INSERT_PARTIAL_PREPARE_FAIL 6143
55 #define ERR_INSERT_PARTIAL_ABORT_PARSE_FAIL 6144
56 #define ERR_INSERT_PARTIAL_ABORT_PREPARE_FAIL 6145
57 #define ERR_INSERT_PARTIAL_FLUSH_COMMIT_FAIL 6146
58 #define ERR_INSERT_PARTIAL_COMMIT_FAIL 6147
59 #define ERR_INSERT_PARTIAL_FLUSH_COMPLETE_FAIL 6148
60 #define ERR_INSERT_PARTIAL_COMPLETE_FAIL 6149
61 #define ERR_INSERT_PARTIAL_END_FAIL 6150
62
63 #define FAIL_BEGIN 0
64 #define FAIL_CREATE 1
65 #define FAIL_END 2
66 #define SUCCEED_COMMIT 3
67 #define SUCCEED_ABORT 4
68
69 #define ndb_master_failure 1
70 #define NO_NODE_GROUP int(-1)
71 #define FREE_NODE_GROUP 65535
72
73 #define TEST_FRM_DATA_SIZE 14000
74
75 static int numNodeGroups;
76 static int numNoNodeGroups;
77 static int nodeGroup[MAX_NDB_NODE_GROUPS];
78 static int nodeGroupIds[MAX_NDB_NODE_GROUPS];
79
getNodeGroups(NdbRestarter & restarter)80 void getNodeGroups(NdbRestarter & restarter)
81 {
82 Uint32 nextFreeNodeGroup = 0;
83
84 numNoNodeGroups = 0;
85 for (Uint32 i = 0; i < MAX_NDB_NODE_GROUPS; i++)
86 {
87 nodeGroup[i] = NO_NODE_GROUP;
88 nodeGroupIds[i] = NO_NODE_GROUP;
89 }
90
91 int numDbNodes = restarter.getNumDbNodes();
92 for (int i = 0; i < numDbNodes; i++)
93 {
94 int nodeId = restarter.getDbNodeId(i);
95 ndbout_c("nodeId: %d", nodeId);
96 require(nodeId != -1);
97 int nodeGroupId = restarter.getNodeGroup(nodeId);
98 ndbout_c("nodeGroupId: %d", nodeGroupId);
99 require(nodeGroupId != -1);
100 nodeGroup[nodeId] = nodeGroupId;
101 if (nodeGroupId == FREE_NODE_GROUP)
102 {
103 numNoNodeGroups++;
104 }
105 else
106 {
107 bool found = false;
108 for (Uint32 i = 0; i < nextFreeNodeGroup; i++)
109 {
110 if (nodeGroupIds[i] == nodeGroupId)
111 {
112 found = true;
113 break;
114 }
115 }
116 if (!found)
117 {
118 nodeGroupIds[nextFreeNodeGroup++] = nodeGroupId;
119 }
120 }
121 }
122 numNodeGroups = nextFreeNodeGroup;
123 }
124
125 char f_tablename[256];
126
127 #define CHECK(b) if (!(b)) { \
128 g_err << "ERR: "<< step->getName() \
129 << " failed on line " << __LINE__ << endl; \
130 result = NDBT_FAILED; \
131 break; }
132
133 #define CHECK2(b, c) if (!(b)) { \
134 g_err << "ERR: "<< step->getName() \
135 << " failed on line " << __LINE__ << ": " << c << endl; \
136 result = NDBT_FAILED; \
137 goto end; }
138
139 #define CHECK3(b, c) if (!(b)) { \
140 g_err << "ERR: "<< step->getName() \
141 << " failed on line " << __LINE__ << ": " << c << endl; \
142 return NDBT_FAILED; }
143
144
runLoadTable(NDBT_Context * ctx,NDBT_Step * step)145 int runLoadTable(NDBT_Context* ctx, NDBT_Step* step){
146 Ndb* pNdb = GETNDB(step);
147 int records = ctx->getNumRecords();
148 HugoTransactions hugoTrans(*ctx->getTab());
149 if (hugoTrans.loadTable(pNdb, records) != 0){
150 return NDBT_FAILED;
151 }
152 return NDBT_OK;
153 }
154
runCreateInvalidTables(NDBT_Context * ctx,NDBT_Step * step)155 int runCreateInvalidTables(NDBT_Context* ctx, NDBT_Step* step){
156 Ndb* pNdb = GETNDB(step);
157 int result = NDBT_OK;
158
159 char failTabName[256];
160
161 const int expectedDictErrors[6]= {720,
162 4317,
163 737,
164 739,
165 736,
166 740 };
167
168 for (int i = 0; i < 10; i++){
169 BaseString::snprintf(failTabName, 256, "F%d", i);
170
171 const NdbDictionary::Table* pFailTab = NDBT_Tables::getTable(failTabName);
172 if (pFailTab != NULL){
173 ndbout << "|- " << failTabName << endl;
174
175 // Try to create table in db
176 if (pFailTab->createTableInDb(pNdb) == 0){
177 ndbout << failTabName << " created, this was not expected"<< endl;
178 result = NDBT_FAILED;
179 }
180
181 // Ensure any error is roughly as expected
182 int errorCode=pNdb->getDictionary()->getNdbError().code;
183 bool errorOk= false;
184 for (int e=0; e < 6; e++)
185 errorOk |= (errorCode == expectedDictErrors[e]);
186
187 if (!errorOk)
188 {
189 ndbout << "Failure, got dict error : " << pNdb->getDictionary()->
190 getNdbError().code << endl;
191 return NDBT_FAILED;
192 }
193
194 // Verify that table is not in db
195 const NdbDictionary::Table* pTab2 =
196 NDBT_Table::discoverTableFromDb(pNdb, failTabName) ;
197 if (pTab2 != NULL){
198 ndbout << failTabName << " was found in DB, this was not expected"<< endl;
199 result = NDBT_FAILED;
200 if (pFailTab->equal(*pTab2) == true){
201 ndbout << "It was equal" << endl;
202 } else {
203 ndbout << "It was not equal" << endl;
204 }
205 int records = 1000;
206 HugoTransactions hugoTrans(*pTab2);
207 if (hugoTrans.loadTable(pNdb, records) != 0){
208 ndbout << "It can NOT be loaded" << endl;
209 } else{
210 ndbout << "It can be loaded" << endl;
211
212 UtilTransactions utilTrans(*pTab2);
213 if (utilTrans.clearTable(pNdb, records, 64) != 0){
214 ndbout << "It can NOT be cleared" << endl;
215 } else{
216 ndbout << "It can be cleared" << endl;
217 }
218 }
219
220 if (pNdb->getDictionary()->dropTable(pTab2->getName()) == -1){
221 ndbout << "It can NOT be dropped" << endl;
222 } else {
223 ndbout << "It can be dropped" << endl;
224 }
225 }
226 }
227 }
228 return result;
229 }
230
runCreateTheTable(NDBT_Context * ctx,NDBT_Step * step)231 int runCreateTheTable(NDBT_Context* ctx, NDBT_Step* step){
232 Ndb* pNdb = GETNDB(step);
233 const NdbDictionary::Table* pTab = ctx->getTab();
234
235 // Try to create table in db
236 if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0){
237 return NDBT_FAILED;
238 }
239
240 // Verify that table is in db
241 const NdbDictionary::Table* pTab2 =
242 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
243 if (pTab2 == NULL){
244 ndbout << pTab->getName() << " was not found in DB"<< endl;
245 return NDBT_FAILED;
246 }
247 ctx->setTab(pTab2);
248
249 BaseString::snprintf(f_tablename, sizeof(f_tablename),
250 "%s", pTab->getName());
251
252 return NDBT_OK;
253 }
254
runDropTheTable(NDBT_Context * ctx,NDBT_Step * step)255 int runDropTheTable(NDBT_Context* ctx, NDBT_Step* step){
256 Ndb* pNdb = GETNDB(step);
257
258 // Drop table
259 pNdb->getDictionary()->dropTable(f_tablename);
260
261 return NDBT_OK;
262 }
263
runCreateTheIndex(NDBT_Context * ctx,NDBT_Step * step)264 int runCreateTheIndex(NDBT_Context* ctx, NDBT_Step* step){
265 Ndb* pNdb = GETNDB(step);
266 const NdbDictionary::Table* pTab = ctx->getTab();
267 char idxname[20];
268 sprintf(idxname, "%s_idx", pTab->getName());
269 NdbDictionary::Index idx(idxname);
270 idx.setTable(pTab->getName());
271 idx.setType(NdbDictionary::Index::OrderedIndex);
272 idx.setLogging(false);
273 for (int c = 0; c< pTab->getNoOfColumns(); c++)
274 {
275 const NdbDictionary::Column * col = pTab->getColumn(c);
276 if (col->getPrimaryKey())
277 idx.addIndexColumn(col->getName());
278 }
279
280 NdbDictionary::Dictionary *pDict = pNdb->getDictionary();
281 if(pDict->createIndex(idx) != 0)
282 {
283 ndbout << "Failed to create index" << endl;
284 return NDBT_FAILED;
285 }
286 return NDBT_OK;
287 }
288
runDropTheIndex(NDBT_Context * ctx,NDBT_Step * step)289 int runDropTheIndex(NDBT_Context* ctx, NDBT_Step* step){
290 Ndb* pNdb = GETNDB(step);
291 const NdbDictionary::Table* pTab = ctx->getTab();
292 NdbDictionary::Dictionary *pDict = pNdb->getDictionary();
293 char idxname[20];
294 sprintf(idxname, "%s_idx", pTab->getName());
295 if(pDict->dropIndex(idxname, pTab->getName()) != 0)
296 {
297 ndbout << "Failed to drop index" << endl;
298 return NDBT_FAILED;
299 }
300 return NDBT_OK;
301 }
302
runSetDropTableConcurrentLCP(NDBT_Context * ctx,NDBT_Step * step)303 int runSetDropTableConcurrentLCP(NDBT_Context *ctx, NDBT_Step *step)
304 {
305 NdbRestarter restarter;
306 if(restarter.insertErrorInAllNodes(5088) != 0)
307 {
308 g_err << "failed to set error insert"<< endl;
309 return NDBT_FAILED;
310 }
311 return NDBT_OK;
312 }
313
runSetMinTimeBetweenLCP(NDBT_Context * ctx,NDBT_Step * step)314 int runSetMinTimeBetweenLCP(NDBT_Context *ctx, NDBT_Step *step)
315 {
316 NdbRestarter restarter;
317 int result;
318 int val = DumpStateOrd::DihMinTimeBetweenLCP;
319 if (restarter.dumpStateAllNodes(&val, 1) != 0)
320 {
321 do { CHECK(0); } while(0);
322 g_err << "Failed to set LCP to min value" << endl;
323 return NDBT_FAILED;
324 }
325 return NDBT_OK;
326 }
327
runResetMinTimeBetweenLCP(NDBT_Context * ctx,NDBT_Step * step)328 int runResetMinTimeBetweenLCP(NDBT_Context *ctx, NDBT_Step *step)
329 {
330 NdbRestarter restarter;
331 int result;
332 int val2[] = { DumpStateOrd::DihMinTimeBetweenLCP, 0 };
333 if (restarter.dumpStateAllNodes(val2, 2) != 0)
334 {
335 do { CHECK(0); } while(0);
336 g_err << "Failed to set LCP to min value" << endl;
337 return NDBT_FAILED;
338 }
339 return NDBT_OK;
340 }
341
runSetDropTableConcurrentLCP2(NDBT_Context * ctx,NDBT_Step * step)342 int runSetDropTableConcurrentLCP2(NDBT_Context *ctx, NDBT_Step *step)
343 {
344 NdbRestarter restarter;
345 if(restarter.insertErrorInAllNodes(5089) != 0)
346 {
347 g_err << "failed to set error insert"<< endl;
348 return NDBT_FAILED;
349 }
350 return NDBT_OK;
351 }
352
353 /*******
354 * Precondition:
355 * 'DataMemory' has been filled until insertion failed
356 * due to 'DbIsFull'. The table 'TRANSACTION' should
357 * not exist in the DB
358 *
359 * Test:
360 * Creation of the (empty) table 'TRANSACTION'
361 * should succeed even if 'DbIsFull'. Or it could fail
362 * due to memory for hash index. If succeed however,
363 * insertion of the first row should fail.
364 *
365 * Postcond:
366 * The created table 'TRANSACTION is removed.
367 * DataMemory is still full.
368 */
runCreateTableWhenDbIsFull(NDBT_Context * ctx,NDBT_Step * step)369 int runCreateTableWhenDbIsFull(NDBT_Context* ctx, NDBT_Step* step){
370 Ndb* pNdb = GETNDB(step);
371 int result = NDBT_OK;
372 const char* tabName = "TRANSACTION"; //Use a util table
373
374 // Precondition is that 'DataMemory' filled to max.
375 // So we skip test if a DiskStorage table was filled
376 for (Uint32 i = 0; i<(Uint32)ctx->getTab()->getNoOfColumns(); i++)
377 {
378 if (ctx->getTab()->getColumn(i)->getStorageType() ==
379 NdbDictionary::Column::StorageTypeDisk)
380 {
381 ndbout << "Skip test for *disk* tables" << endl;
382 return NDBT_OK;
383 }
384 }
385
386 const NdbDictionary::Table* pTab = NDBT_Tables::getTable(tabName);
387 while (pTab != NULL){ //Always 'break' without looping
388 ndbout << "|- " << tabName << endl;
389
390 // Verify that table is not in db
391 if (NDBT_Table::discoverTableFromDb(pNdb, tabName) != NULL){
392 ndbout << tabName << " was found in DB"<< endl;
393 result = NDBT_FAILED;
394 break;
395 }
396
397 /*
398 * Create (empty) table in db, should succeed even if 'DbIsFull' or fail
399 * with 625:
400 * Out of memory in Ndb Kernel, hash index part (increase DataMemory).
401 */
402 if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0)
403 {
404 if (pNdb->getDictionary()->getNdbError().code == 625)
405 {
406 /*
407 * Fail due to really out of data memory, not even a hash index page
408 * available.
409 */
410 result = NDBT_OK;
411 break;
412 }
413
414 ndbout << tabName << " was not created when DB is full" << endl;
415 result = NDBT_FAILED;
416 break;
417 }
418
419 // Verify that table is now in db
420 if (NDBT_Table::discoverTableFromDb(pNdb, tabName) == NULL){
421 ndbout << tabName << " was not visible in DB"<< endl;
422 result = NDBT_FAILED;
423 break;
424 }
425
426 // As 'DbIsFull', insert of a single record should fail
427 HugoOperations hugoOps(*pTab);
428 CHECK(hugoOps.startTransaction(pNdb) == 0);
429 CHECK(hugoOps.pkInsertRecord(pNdb, 1) == 0);
430 CHECK(hugoOps.execute_Commit(pNdb) != 0); //Should fail
431 CHECK(hugoOps.closeTransaction(pNdb) == 0);
432
433 break;
434 }
435
436 // Drop table (if exist, so we dont care about errors)
437 pNdb->getDictionary()->dropTable(tabName);
438 return result;
439 }
440
runDropTableWhenDbIsFull(NDBT_Context * ctx,NDBT_Step * step)441 int runDropTableWhenDbIsFull(NDBT_Context* ctx, NDBT_Step* step){
442 Ndb* pNdb = GETNDB(step);
443 int result = NDBT_OK;
444 const char* tabName = "TRANSACTION"; //Use a util table
445
446 const NdbDictionary::Table* pTab = NDBT_Table::discoverTableFromDb(pNdb, tabName);
447 if (pTab != NULL){
448 ndbout << "|- TRANSACTION" << endl;
449
450 // Try to drop table in db
451 if (pNdb->getDictionary()->dropTable(pTab->getName()) == -1){
452 result = NDBT_FAILED;
453 }
454
455 // Verify that table is not in db
456 if (NDBT_Table::discoverTableFromDb(pNdb, tabName) != NULL){
457 ndbout << tabName << " was found in DB"<< endl;
458 result = NDBT_FAILED;
459 }
460 }
461
462 return result;
463
464 }
465
466
runCreateAndDrop(NDBT_Context * ctx,NDBT_Step * step)467 int runCreateAndDrop(NDBT_Context* ctx, NDBT_Step* step){
468 Ndb* pNdb = GETNDB(step);
469 int loops = ctx->getNumLoops();
470 int i = 0;
471
472 const NdbDictionary::Table* pTab = ctx->getTab();
473 ndbout << "|- " << pTab->getName() << endl;
474
475 while (i < loops){
476
477 ndbout << i << ": ";
478 // Try to create table in db
479 if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0){
480 return NDBT_FAILED;
481 }
482
483 // Verify that table is in db
484 const NdbDictionary::Table* pTab2 =
485 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
486 if (pTab2 == NULL){
487 ndbout << pTab->getName() << " was not found in DB"<< endl;
488 return NDBT_FAILED;
489 }
490
491 if (pNdb->getDictionary()->dropTable(pTab2->getName())){
492 ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
493 return NDBT_FAILED;
494 }
495
496 // Verify that table is not in db
497 const NdbDictionary::Table* pTab3 =
498 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
499 if (pTab3 != NULL){
500 ndbout << pTab3->getName() << " was found in DB"<< endl;
501 return NDBT_FAILED;
502 }
503 i++;
504 }
505
506 return NDBT_OK;
507 }
508
runCreateAndDropAtRandom(NDBT_Context * ctx,NDBT_Step * step)509 int runCreateAndDropAtRandom(NDBT_Context* ctx, NDBT_Step* step)
510 {
511 myRandom48Init((long)NdbTick_CurrentMillisecond());
512 Ndb* pNdb = GETNDB(step);
513 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
514 int loops = ctx->getNumLoops();
515 int records = ctx->getNumRecords();
516
517 int numAllTables = NDBT_Tables::getNumTables();
518 struct TabList {
519 int exists; // -1 = skip, 0 = no, 1 = yes
520 const NdbDictionary::Table* pTab; // retrieved
521 TabList() { exists = -1; pTab = 0; }
522 };
523 TabList* tabList = new TabList [ numAllTables ];
524 int numTables = 0;
525 int num;
526 for (num = 0; num < numAllTables; num++) {
527 const NdbDictionary::Table* pTab = NDBT_Tables::getTable(num);
528 if (pTab->checkColumns(0, 0) & 2) // skip disk
529 continue;
530 tabList[num].exists = 0;
531 (void)pDic->dropTable(pTab->getName());
532 numTables++;
533 }
534 int numExists = 0;
535
536 const bool createIndexes = ctx->getProperty("CreateIndexes");
537 const bool loadData = ctx->getProperty("LoadData");
538
539 NdbRestarter restarter;
540 int result = NDBT_OK;
541 int bias = 1; // 0-less 1-more
542 int i = 0;
543
544 while (i < loops && result == NDBT_OK) {
545 num = myRandom48(numAllTables);
546 if (tabList[num].exists == -1)
547 continue;
548 g_info << "loop " << i << " tabs " << numExists << "/" << numTables << endl;
549 const NdbDictionary::Table* pTab = NDBT_Tables::getTable(num);
550 char tabName[200];
551 strcpy(tabName, pTab->getName());
552
553 if (tabList[num].exists == 0) {
554 if (bias == 0 && myRandom48(100) < 80)
555 continue;
556 g_info << tabName << ": create" << endl;
557 if (pDic->createTable(*pTab) != 0) {
558 const NdbError err = pDic->getNdbError();
559 g_err << tabName << ": create failed: " << err << endl;
560 result = NDBT_FAILED;
561 break;
562 }
563 const NdbDictionary::Table* pTab2 = pDic->getTable(tabName);
564 if (pTab2 == NULL) {
565 const NdbError err = pDic->getNdbError();
566 g_err << tabName << ": verify create failed: " << err << endl;
567 result = NDBT_FAILED;
568 break;
569 }
570 tabList[num].pTab = pTab2;
571 if (loadData) {
572 g_info << tabName << ": load data" << endl;
573 HugoTransactions hugoTrans(*pTab2);
574 if (hugoTrans.loadTable(pNdb, records) != 0) {
575 g_err << tabName << ": loadTable failed" << endl;
576 result = NDBT_FAILED;
577 break;
578 }
579 }
580 if (createIndexes) {
581 int icount = myRandom48(10);
582 int inum;
583 for (inum = 0; inum < icount; inum++) {
584 const int tcols = pTab2->getNoOfColumns();
585 require(tcols != 0);
586 int icols = 1 + myRandom48(tcols);
587 if (icols > NDB_MAX_ATTRIBUTES_IN_INDEX)
588 icols = NDB_MAX_ATTRIBUTES_IN_INDEX;
589 char indName[256];
590 sprintf(indName, "%s_X%d", tabName, inum);
591 NdbDictionary::Index ind(indName);
592 ind.setTable(tabName);
593 ind.setType(NdbDictionary::Index::OrderedIndex);
594 ind.setLogging(false);
595 Bitmask<MAX_ATTRIBUTES_IN_TABLE> mask;
596 char ilist[200];
597 ilist[0] = 0;
598 int ic;
599 for (ic = 0; ic < icols; ic++) {
600 int tc = myRandom48(tcols);
601 const NdbDictionary::Column* c = pTab2->getColumn(tc);
602 require(c != 0);
603 if (mask.get(tc) ||
604 c->getType() == NdbDictionary::Column::Blob ||
605 c->getType() == NdbDictionary::Column::Text ||
606 c->getType() == NdbDictionary::Column::Bit ||
607 c->getStorageType() == NdbDictionary::Column::StorageTypeDisk)
608 continue;
609 ind.addColumn(*c);
610 mask.set(tc);
611 sprintf(ilist + strlen(ilist), " %d", tc);
612 }
613 if (mask.isclear())
614 continue;
615 g_info << indName << ": columns:" << ilist << endl;
616 if (pDic->createIndex(ind) == 0) {
617 g_info << indName << ": created" << endl;
618 } else {
619 const NdbError err = pDic->getNdbError();
620 g_err << indName << ": create index failed: " << err << endl;
621 if (err.code != 826 && // Too many tables and attributes..
622 err.code != 903 && // Too many ordered indexes..
623 err.code != 904 && // Out of fragment records..
624 err.code != 905 && // Out of attribute records..
625 err.code != 707 && // No more table metadata records..
626 err.code != 708) // No more attribute metadata records..
627 {
628 result = NDBT_FAILED;
629 break;
630 }
631 }
632 }
633 }
634 if (loadData) {
635 // first update a random table to flush global variables
636 int num3 = 0;
637 while (1) {
638 num3 = myRandom48(numAllTables);
639 if (num == num3 || tabList[num3].exists == 1)
640 break;
641 }
642 const NdbDictionary::Table* pTab3 = tabList[num3].pTab;
643 require(pTab3 != 0);
644 char tabName3[200];
645 strcpy(tabName3, pTab3->getName());
646 HugoTransactions hugoTrans(*pTab3);
647 g_info << tabName3 << ": update data" << endl;
648 if (hugoTrans.pkUpdateRecords(pNdb, records) != 0) {
649 g_err << tabName3 << ": pkUpdateRecords failed" << endl;
650 result = NDBT_FAILED;
651 break;
652 }
653 }
654 if (loadData) {
655 HugoTransactions hugoTrans(*pTab2);
656 g_info << tabName << ": update data" << endl;
657 if (hugoTrans.pkUpdateRecords(pNdb, records) != 0) {
658 g_err << "pkUpdateRecords failed" << endl;
659 result = NDBT_FAILED;
660 break;
661 }
662 }
663 tabList[num].exists = 1;
664 require(numExists < numTables);
665 numExists++;
666 if (numExists == numTables)
667 bias = 0;
668 }
669 else if (tabList[num].exists == 1) {
670 if (bias == 1 && myRandom48(100) < 80)
671 continue;
672 g_info << tabName << ": drop" << endl;
673 if (restarter.insertErrorInAllNodes(4013) != 0) {
674 g_err << "error insert failed" << endl;
675 result = NDBT_FAILED;
676 break;
677 }
678 if (pDic->dropTable(tabName) != 0) {
679 const NdbError err = pDic->getNdbError();
680 g_err << tabName << ": drop failed: " << err << endl;
681 result = NDBT_FAILED;
682 break;
683 }
684 const NdbDictionary::Table* pTab2 = pDic->getTable(tabName);
685 if (pTab2 != NULL) {
686 g_err << tabName << ": verify drop: table exists" << endl;
687 result = NDBT_FAILED;
688 break;
689 }
690 if (pDic->getNdbError().code != 709 &&
691 pDic->getNdbError().code != 723) {
692 const NdbError err = pDic->getNdbError();
693 g_err << tabName << ": verify drop: " << err << endl;
694 result = NDBT_FAILED;
695 break;
696 }
697 tabList[num].exists = 0;
698 require(numExists > 0);
699 numExists--;
700 if (numExists == 0)
701 bias = 1;
702 }
703 i++;
704 }
705
706 for (num = 0; num < numAllTables; num++)
707 if (tabList[num].exists == 1)
708 pDic->dropTable(NDBT_Tables::getTable(num)->getName());
709
710 delete [] tabList;
711 return result;
712 }
713
714
runCreateAndDropWithData(NDBT_Context * ctx,NDBT_Step * step)715 int runCreateAndDropWithData(NDBT_Context* ctx, NDBT_Step* step){
716 Ndb* pNdb = GETNDB(step);
717 int loops = ctx->getNumLoops();
718 int records = ctx->getNumRecords();
719 int i = 0;
720
721 NdbRestarter restarter;
722 int val = DumpStateOrd::DihMinTimeBetweenLCP;
723 if(restarter.dumpStateAllNodes(&val, 1) != 0){
724 int result;
725 do { CHECK(0); } while (0);
726 g_err << "Unable to change timebetween LCP" << endl;
727 return NDBT_FAILED;
728 }
729
730 const NdbDictionary::Table* pTab = ctx->getTab();
731 ndbout << "|- " << pTab->getName() << endl;
732
733 while (i < loops){
734 ndbout << i << ": ";
735 // Try to create table in db
736
737 if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0){
738 return NDBT_FAILED;
739 }
740
741 // Verify that table is in db
742 const NdbDictionary::Table* pTab2 =
743 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
744 if (pTab2 == NULL){
745 ndbout << pTab->getName() << " was not found in DB"<< endl;
746 return NDBT_FAILED;
747 }
748
749 HugoTransactions hugoTrans(*pTab2);
750 if (hugoTrans.loadTable(pNdb, records) != 0){
751 return NDBT_FAILED;
752 }
753
754 int count = 0;
755 UtilTransactions utilTrans(*pTab2);
756 if (utilTrans.selectCount(pNdb, 64, &count) != 0){
757 return NDBT_FAILED;
758 }
759 if (count != records){
760 ndbout << count <<" != "<<records << endl;
761 return NDBT_FAILED;
762 }
763
764 if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
765 ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
766 return NDBT_FAILED;
767 }
768
769 // Verify that table is not in db
770 const NdbDictionary::Table* pTab3 =
771 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
772 if (pTab3 != NULL){
773 ndbout << pTab3->getName() << " was found in DB"<< endl;
774 return NDBT_FAILED;
775 }
776
777
778 i++;
779 }
780
781 return NDBT_OK;
782 }
783
runFillTable(NDBT_Context * ctx,NDBT_Step * step)784 int runFillTable(NDBT_Context* ctx, NDBT_Step* step){
785 Ndb* pNdb = GETNDB(step);
786 HugoTransactions hugoTrans(*ctx->getTab());
787 if (hugoTrans.fillTable(pNdb) != 0){
788 return NDBT_FAILED;
789 }
790 return NDBT_OK;
791 }
792
runClearTable(NDBT_Context * ctx,NDBT_Step * step)793 int runClearTable(NDBT_Context* ctx, NDBT_Step* step){
794 Ndb* pNdb = GETNDB(step);
795 int records = ctx->getNumRecords();
796
797 UtilTransactions utilTrans(*ctx->getTab());
798 if (utilTrans.clearTable(pNdb, records) != 0){
799 return NDBT_FAILED;
800 }
801 return NDBT_OK;
802 }
803
runCreateAndDropDuring(NDBT_Context * ctx,NDBT_Step * step)804 int runCreateAndDropDuring(NDBT_Context* ctx, NDBT_Step* step){
805 int result = NDBT_OK;
806 int loops = ctx->getNumLoops();
807 int i = 0;
808
809 const NdbDictionary::Table* pTab = ctx->getTab();
810 ndbout << "|- " << pTab->getName() << endl;
811
812 while (i < loops && result == NDBT_OK){
813 ndbout << i << ": " << endl;
814 // Try to create table in db
815
816 Ndb* pNdb = GETNDB(step);
817 g_debug << "Creating table" << endl;
818
819 if (NDBT_Tables::createTable(pNdb, pTab->getName()) != 0){
820 g_err << "createTableInDb failed" << endl;
821 result = NDBT_FAILED;
822 continue;
823 }
824
825 g_debug << "Verifying creation of table" << endl;
826
827 // Verify that table is in db
828 const NdbDictionary::Table* pTab2 =
829 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
830 if (pTab2 == NULL){
831 g_err << pTab->getName() << " was not found in DB"<< endl;
832 result = NDBT_FAILED;
833 continue;
834 }
835
836 NdbSleep_MilliSleep(3000);
837
838 g_debug << "Dropping table" << endl;
839
840 if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
841 g_err << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
842 result = NDBT_FAILED;
843 continue;
844 }
845
846 g_debug << "Verifying dropping of table" << endl;
847
848 // Verify that table is not in db
849 const NdbDictionary::Table* pTab3 =
850 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
851 if (pTab3 != NULL){
852 g_err << pTab3->getName() << " was found in DB"<< endl;
853 result = NDBT_FAILED;
854 continue;
855 }
856 i++;
857 }
858 ctx->stopTest();
859
860 return result;
861 }
862
863
runUseTableUntilStopped(NDBT_Context * ctx,NDBT_Step * step)864 int runUseTableUntilStopped(NDBT_Context* ctx, NDBT_Step* step){
865 int records = ctx->getNumRecords();
866
867 const NdbDictionary::Table* pTab = ctx->getTab();
868
869 while (ctx->isTestStopped() == false) {
870 // g_info << i++ << ": ";
871
872
873 // Delete and recreate Ndb object
874 // Otherwise you always get Invalid Schema Version
875 // It would be a nice feature to remove this two lines
876 //step->tearDown();
877 //step->setUp();
878
879 Ndb* pNdb = GETNDB(step);
880
881 const NdbDictionary::Table* pTab2 =
882 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
883 if (pTab2 == NULL)
884 continue;
885
886 int res;
887 HugoTransactions hugoTrans(*pTab2);
888 if ((res = hugoTrans.loadTable(pNdb, records)) != 0){
889 NdbError err = pNdb->getNdbError(res);
890 if(err.classification == NdbError::SchemaError){
891 pNdb->getDictionary()->invalidateTable(pTab->getName());
892 }
893 continue;
894 }
895
896 if ((res = hugoTrans.clearTable(pNdb, records)) != 0){
897 NdbError err = pNdb->getNdbError(res);
898 if(err.classification == NdbError::SchemaError){
899 pNdb->getDictionary()->invalidateTable(pTab->getName());
900 }
901 continue;
902 }
903 }
904 g_info << endl;
905 return NDBT_OK;
906 }
907
runUseTableUntilStopped2(NDBT_Context * ctx,NDBT_Step * step)908 int runUseTableUntilStopped2(NDBT_Context* ctx, NDBT_Step* step){
909 int records = ctx->getNumRecords();
910
911 Ndb* pNdb = GETNDB(step);
912 const NdbDictionary::Table* pTab = ctx->getTab();
913 const NdbDictionary::Table* pTab2 =
914 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
915
916 if (pTab2 == NULL) {
917 g_err << "Table: " << pTab->getName()
918 << ", not 'discovered' on line " << __LINE__
919 << endl;
920 return NDBT_FAILED;
921 }
922 HugoTransactions hugoTrans(*pTab2);
923
924 int i = 0;
925 while (ctx->isTestStopped() == false)
926 {
927 ndbout_c("loop: %u", i++);
928
929
930 // Delete and recreate Ndb object
931 // Otherwise you always get Invalid Schema Version
932 // It would be a nice feature to remove this two lines
933 //step->tearDown();
934 //step->setUp();
935
936
937 int res;
938 if ((res = hugoTrans.loadTable(pNdb, records)) != 0){
939 NdbError err = pNdb->getNdbError(res);
940 if(err.classification == NdbError::SchemaError){
941 pNdb->getDictionary()->invalidateTable(pTab->getName());
942 }
943 continue;
944 }
945
946 if ((res = hugoTrans.scanUpdateRecords(pNdb, records)) != 0)
947 {
948 NdbError err = pNdb->getNdbError(res);
949 if(err.classification == NdbError::SchemaError){
950 pNdb->getDictionary()->invalidateTable(pTab->getName());
951 }
952 continue;
953 }
954
955 if ((res = hugoTrans.clearTable(pNdb, records)) != 0){
956 NdbError err = pNdb->getNdbError(res);
957 if(err.classification == NdbError::SchemaError){
958 pNdb->getDictionary()->invalidateTable(pTab->getName());
959 }
960 continue;
961 }
962 }
963 g_info << endl;
964 return NDBT_OK;
965 }
966
runUseTableUntilStopped3(NDBT_Context * ctx,NDBT_Step * step)967 int runUseTableUntilStopped3(NDBT_Context* ctx, NDBT_Step* step){
968 int records = ctx->getNumRecords();
969
970 Ndb* pNdb = GETNDB(step);
971 const NdbDictionary::Table* pTab = ctx->getTab();
972 const NdbDictionary::Table* pTab2 =
973 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
974 if (pTab2 == NULL) {
975 g_err << "Table : " << pTab->getName()
976 << ", not 'discovered' on line " << __LINE__
977 << endl;
978 return NDBT_FAILED;
979 }
980 HugoTransactions hugoTrans(*pTab2);
981
982 int i = 0;
983 while (ctx->isTestStopped() == false)
984 {
985 ndbout_c("loop: %u", i++);
986
987
988 // Delete and recreate Ndb object
989 // Otherwise you always get Invalid Schema Version
990 // It would be a nice feature to remove this two lines
991 //step->tearDown();
992 //step->setUp();
993
994
995 int res;
996 if ((res = hugoTrans.scanUpdateRecords(pNdb, records)) != 0)
997 {
998 NdbError err = pNdb->getNdbError(res);
999 if(err.classification == NdbError::SchemaError){
1000 pNdb->getDictionary()->invalidateTable(pTab->getName());
1001 }
1002 continue;
1003 }
1004 }
1005 g_info << endl;
1006 return NDBT_OK;
1007 }
1008
1009 /**
1010 * This is a regression test for bug 14190114
1011 * "CLUSTER CRASH DUE TO NDBREQUIRE IN ./LOCALPROXY.HPP DBLQH (LINE: 234)".
1012 * This bug occurs if there is a takeover (i.e. the master node crashes)
1013 * while an LQH block is executing a DROP_TAB_REQ signal. It only affects
1014 * multi-threaded ndb.
1015 */
1016 static int
runDropTakeoverTest(NDBT_Context * ctx,NDBT_Step * step)1017 runDropTakeoverTest(NDBT_Context* ctx, NDBT_Step* step)
1018 {
1019 NdbRestarter restarter;
1020 if (restarter.getNumDbNodes() == 1)
1021 {
1022 g_info << "Cannot do this test with just one datanode." << endl;
1023 return NDBT_OK;
1024 }
1025
1026 Ndb* const ndb = GETNDB(step);
1027 NdbDictionary::Dictionary* const dict = ndb->getDictionary();
1028
1029 // First we create a table that is a copy of ctx->getTab().
1030 NdbDictionary::Table copyTab(*ctx->getTab());
1031 const char* copyName = "copyTab";
1032
1033 copyTab.setName(copyName);
1034 if (dict->createTable(copyTab) != 0)
1035 {
1036 g_err << "Failed to create table " << copyName << endl
1037 << dict->getNdbError() << endl;
1038 return NDBT_FAILED;
1039 }
1040
1041 /**
1042 * Find the node id of the master node and another data node that is not
1043 * the master.
1044 */
1045 const int masterNodeId = restarter.getMasterNodeId();
1046 const int nonMasterNodeId =
1047 masterNodeId == restarter.getDbNodeId(0) ?
1048 restarter.getDbNodeId(1) :
1049 restarter.getDbNodeId(0);
1050
1051 /**
1052 * This error insert makes LQH resend the DROP_TAB_REQ to itself (with a
1053 * long delay) rather than executing it.
1054 * This makes it appear as if though the LQH block spends a long time
1055 * executing the DROP_TAB_REQ signal.
1056 */
1057 g_info << "Insert error 5076 in node " << nonMasterNodeId << endl;
1058 restarter.insertErrorInNode(nonMasterNodeId, 5076);
1059 /**
1060 * This error insert makes the master node crash when one of its LQH
1061 * blocks tries to execute a DROP_TAB_REQ signal. This will then trigger
1062 * a takeover.
1063 */
1064 g_info << "Insert error 5077 in node " << masterNodeId << endl;
1065 restarter.insertErrorInNode(masterNodeId, 5077);
1066
1067 // dropTable should succeed with the new master.
1068 g_info << "Trying to drop table " << copyName << endl;
1069 if (dict->dropTable(copyName))
1070 {
1071 g_err << "Unexpectedly failed to drop table " << copyName << endl;
1072 return NDBT_FAILED;
1073 }
1074
1075 /**
1076 * Check that only old master is dead. Bug 14190114 would cause other nodes
1077 * to die as well.
1078 */
1079 const int deadNodeId = restarter.checkClusterAlive(&masterNodeId, 1);
1080 if (deadNodeId != 0)
1081 {
1082 g_err << "NodeId " << deadNodeId << " is down." << endl;
1083 return NDBT_FAILED;
1084 }
1085
1086 // Verify that old master comes back up, and that no other node crashed.
1087 g_info << "Waiting for all nodes to be up." << endl;
1088 if (restarter.waitClusterStarted() != 0)
1089 {
1090 g_err << "One or more cluster nodes are not up." << endl;
1091 return NDBT_FAILED;
1092 }
1093 CHK_NDB_READY(ndb);
1094
1095 /**
1096 * The 'drop table' operation should have been rolled forward, since the
1097 * node crash happened in the complete phase. Verify that the table is
1098 * gone.
1099 */
1100 g_info << "Verifying that table " << copyName << " was deleted." << endl;
1101 if (dict->getTable(copyName) == NULL)
1102 {
1103 if (dict->getNdbError().code != 723) // 723 = no such table existed.
1104 {
1105 g_err << "dict->getTable() for " << copyName
1106 << " failed in unexpedted way:" << endl
1107 << dict->getNdbError() << endl;
1108 return NDBT_FAILED;
1109 }
1110 }
1111 else
1112 {
1113 g_err << "Transaction dropping " << copyName << " was not rolled forward"
1114 << endl;
1115 return NDBT_FAILED;
1116 }
1117
1118 /**
1119 * Do another dictionary transaction, to verify that the cluster allows that.
1120 */
1121 NdbDictionary::Table extraTab(*ctx->getTab());
1122 const char* extraName = "extraTab";
1123
1124 extraTab.setName(extraName);
1125 g_info << "Trying to create table " << extraName << endl;
1126 if (dict->createTable(extraTab) != 0)
1127 {
1128 g_err << "Failed to create table " << extraName << endl
1129 << dict->getNdbError() << endl;
1130 return NDBT_FAILED;
1131 }
1132
1133 // Clean up by dropping extraTab.
1134 g_info << "Trying to drop table " << extraName << endl;
1135 if (dict->dropTable(extraName) != 0)
1136 {
1137 g_err << "Failed to drop table " << extraName << endl
1138 << dict->getNdbError() << endl;
1139 return NDBT_FAILED;
1140 }
1141
1142 return NDBT_OK;
1143 }
1144
1145 int
runBackup(NDBT_Context * ctx,NDBT_Step * step)1146 runBackup(NDBT_Context* ctx, NDBT_Step* step)
1147 {
1148 NdbBackup backup;
1149 Uint32 backupId = 0;
1150 backup.clearOldBackups();
1151 if (backup.start(backupId) == -1)
1152 {
1153 return NDBT_FAILED;
1154 }
1155 return NDBT_OK;
1156 }
1157
1158 int
runCreateMaxTables(NDBT_Context * ctx,NDBT_Step * step)1159 runCreateMaxTables(NDBT_Context* ctx, NDBT_Step* step)
1160 {
1161 char tabName[256];
1162 int numTables = ctx->getProperty("tables", 1000);
1163 Ndb* pNdb = GETNDB(step);
1164 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
1165 int i = 0;
1166 for (i = 0; i < numTables; i++) {
1167 BaseString::snprintf(tabName, 256, "MAXTAB%d", i);
1168 if (pNdb->waitUntilReady(30) != 0) {
1169 // Db is not ready, return with failure
1170 return NDBT_FAILED;
1171 }
1172 const NdbDictionary::Table* pTab = ctx->getTab();
1173 //ndbout << "|- " << tabName << endl;
1174 // Set new name for T1
1175 NdbDictionary::Table newTab(* pTab);
1176 newTab.setName(tabName);
1177 // Drop any old (or try to)
1178 (void)pDic->dropTable(newTab.getName());
1179 // Try to create table in db
1180 if (newTab.createTableInDb(pNdb) != 0) {
1181 ndbout << tabName << " could not be created: "
1182 << pDic->getNdbError() << endl;
1183 if (pDic->getNdbError().code == 625 ||
1184 pDic->getNdbError().code == 707 ||
1185 pDic->getNdbError().code == 708 ||
1186 pDic->getNdbError().code == 826 ||
1187 pDic->getNdbError().code == 827 ||
1188 pDic->getNdbError().code == 921)
1189 break;
1190 return NDBT_FAILED;
1191 }
1192 // Verify that table exists in db
1193 const NdbDictionary::Table* pTab3 =
1194 NDBT_Table::discoverTableFromDb(pNdb, tabName) ;
1195 if (pTab3 == NULL){
1196 ndbout << tabName << " was not found in DB: "
1197 << pDic->getNdbError() << endl;
1198 return NDBT_FAILED;
1199 }
1200 if (! newTab.equal(*pTab3)) {
1201 ndbout << "It was not equal" << endl; abort();
1202 return NDBT_FAILED;
1203 }
1204 int records = ctx->getNumRecords();
1205 HugoTransactions hugoTrans(*pTab3);
1206 if (hugoTrans.loadTable(pNdb, records) != 0) {
1207 ndbout << "It can NOT be loaded" << endl;
1208 return NDBT_FAILED;
1209 }
1210 UtilTransactions utilTrans(*pTab3);
1211 if (utilTrans.clearTable(pNdb, records, 64) != 0) {
1212 ndbout << "It can NOT be cleared" << endl;
1213 return NDBT_FAILED;
1214 }
1215 }
1216 if (pNdb->waitUntilReady(30) != 0) {
1217 // Db is not ready, return with failure
1218 return NDBT_FAILED;
1219 }
1220 ctx->setProperty("maxtables", i);
1221 // HURRAAA!
1222 return NDBT_OK;
1223 }
1224
runDropMaxTables(NDBT_Context * ctx,NDBT_Step * step)1225 int runDropMaxTables(NDBT_Context* ctx, NDBT_Step* step)
1226 {
1227 char tabName[256];
1228 int numTables = ctx->getProperty("maxtables", (Uint32)0);
1229 Ndb* pNdb = GETNDB(step);
1230 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
1231 for (int i = 0; i < numTables; i++) {
1232 BaseString::snprintf(tabName, 256, "MAXTAB%d", i);
1233 if (pNdb->waitUntilReady(30) != 0) {
1234 // Db is not ready, return with failure
1235 return NDBT_FAILED;
1236 }
1237 // Verify that table exists in db
1238 const NdbDictionary::Table* pTab3 =
1239 NDBT_Table::discoverTableFromDb(pNdb, tabName) ;
1240 if (pTab3 == NULL) {
1241 ndbout << tabName << " was not found in DB: "
1242 << pDic->getNdbError() << endl;
1243 return NDBT_FAILED;
1244 }
1245 // Try to drop table in db
1246 if (pDic->dropTable(pTab3->getName()) != 0) {
1247 ndbout << tabName << " could not be dropped: "
1248 << pDic->getNdbError() << endl;
1249 return NDBT_FAILED;
1250 }
1251 }
1252 return NDBT_OK;
1253 }
1254
runTestFragmentTypes(NDBT_Context * ctx,NDBT_Step * step)1255 int runTestFragmentTypes(NDBT_Context* ctx, NDBT_Step* step){
1256 int records = ctx->getNumRecords();
1257 int fragTtype = ctx->getProperty("FragmentType");
1258 Ndb* pNdb = GETNDB(step);
1259 int result = NDBT_OK;
1260 NdbRestarter restarter;
1261
1262 if (pNdb->waitUntilReady(30) != 0){
1263 // Db is not ready, return with failure
1264 return NDBT_FAILED;
1265 }
1266
1267 const NdbDictionary::Table* pTab = ctx->getTab();
1268 pNdb->getDictionary()->dropTable(pTab->getName());
1269
1270 NdbDictionary::Table newTab(* pTab);
1271 // Set fragment type for table
1272 newTab.setFragmentType((NdbDictionary::Object::FragmentType)fragTtype);
1273
1274 // Try to create table in db
1275 if (newTab.createTableInDb(pNdb) != 0){
1276 ndbout << newTab.getName() << " could not be created"
1277 << ", fragmentType = "<<fragTtype <<endl;
1278 ndbout << pNdb->getDictionary()->getNdbError() << endl;
1279 return NDBT_FAILED;
1280 }
1281
1282 // Verify that table exists in db
1283 const NdbDictionary::Table* pTab3 =
1284 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName()) ;
1285 if (pTab3 == NULL){
1286 ndbout << pTab->getName() << " was not found in DB"<< endl;
1287 return NDBT_FAILED;
1288
1289 }
1290
1291 if (pTab3->getFragmentType() != fragTtype){
1292 ndbout << pTab->getName() << " fragmentType error "<< endl;
1293 result = NDBT_FAILED;
1294 goto drop_the_tab;
1295 }
1296 /**
1297 This test does not work since fragmentation is
1298 decided by the kernel, hence the fragementation
1299 attribute on the column will differ
1300
1301 if (newTab.equal(*pTab3) == false){
1302 ndbout << "It was not equal" << endl;
1303 result = NDBT_FAILED;
1304 goto drop_the_tab;
1305 }
1306 */
1307 do {
1308
1309 HugoTransactions hugoTrans(*pTab3);
1310 UtilTransactions utilTrans(*pTab3);
1311 int count;
1312 CHECK(hugoTrans.loadTable(pNdb, records) == 0);
1313 CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
1314 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1315 CHECK(count == records);
1316 CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
1317 CHECK(hugoTrans.scanUpdateRecords(pNdb, records/2) == 0);
1318 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1319 CHECK(count == (records/2));
1320
1321 // restart all
1322 ndbout << "Restarting cluster" << endl;
1323 CHECK(restarter.restartAll() == 0);
1324 int timeout = 120;
1325 CHECK(restarter.waitClusterStarted(timeout) == 0);
1326 CHECK(pNdb->waitUntilReady(timeout) == 0);
1327
1328 // Verify content
1329 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1330 CHECK(count == (records/2));
1331
1332 CHECK(utilTrans.clearTable(pNdb, records) == 0);
1333 CHECK(hugoTrans.loadTable(pNdb, records) == 0);
1334 CHECK(utilTrans.clearTable(pNdb, records) == 0);
1335 CHECK(hugoTrans.loadTable(pNdb, records) == 0);
1336 CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
1337 CHECK(utilTrans.clearTable(pNdb, records, 64) == 0);
1338
1339 } while(false);
1340
1341 drop_the_tab:
1342
1343 // Try to drop table in db
1344 if (pNdb->getDictionary()->dropTable(pTab3->getName()) != 0){
1345 ndbout << pTab3->getName() << " could not be dropped"<< endl;
1346 result = NDBT_FAILED;
1347 }
1348
1349 return result;
1350 }
1351
1352
runTestTemporaryTables(NDBT_Context * ctx,NDBT_Step * step)1353 int runTestTemporaryTables(NDBT_Context* ctx, NDBT_Step* step){
1354 int result = NDBT_OK;
1355 int loops = ctx->getNumLoops();
1356 int records = ctx->getNumRecords();
1357 Ndb* pNdb = GETNDB(step);
1358 int i = 0;
1359 NdbRestarter restarter;
1360
1361 const NdbDictionary::Table* pTab = ctx->getTab();
1362 ndbout << "|- " << pTab->getName() << endl;
1363
1364 NdbDictionary::Table newTab(* pTab);
1365 // Set table as temporary
1366 newTab.setStoredTable(false);
1367
1368 // Try to create table in db
1369 if (newTab.createTableInDb(pNdb) != 0){
1370 return NDBT_FAILED;
1371 }
1372
1373 // Verify that table is in db
1374 const NdbDictionary::Table* pTab2 =
1375 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1376 if (pTab2 == NULL){
1377 ndbout << pTab->getName() << " was not found in DB"<< endl;
1378 return NDBT_FAILED;
1379 }
1380
1381 if (pTab2->getStoredTable() != false){
1382 ndbout << pTab->getName() << " was not temporary in DB"<< endl;
1383 result = NDBT_FAILED;
1384 goto drop_the_tab;
1385 }
1386
1387
1388 while (i < loops && result == NDBT_OK){
1389 ndbout << i << ": ";
1390
1391 HugoTransactions hugoTrans(*pTab2);
1392 CHECK(hugoTrans.loadTable(pNdb, records) == 0);
1393
1394 int count = 0;
1395 UtilTransactions utilTrans(*pTab2);
1396 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1397 CHECK(count == records);
1398
1399 // restart all
1400 ndbout << "Restarting cluster" << endl;
1401 CHECK(restarter.restartAll() == 0);
1402 int timeout = 120;
1403 CHECK(restarter.waitClusterStarted(timeout) == 0);
1404 CHECK(pNdb->waitUntilReady(timeout) == 0);
1405
1406 ndbout << "Verifying records..." << endl;
1407 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1408 CHECK(count == 0);
1409
1410 i++;
1411 }
1412
1413 drop_the_tab:
1414
1415
1416 if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
1417 ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
1418 result = NDBT_FAILED;
1419 }
1420
1421 // Verify that table is not in db
1422 const NdbDictionary::Table* pTab3 =
1423 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1424 if (pTab3 != NULL){
1425 ndbout << pTab3->getName() << " was found in DB"<< endl;
1426 result = NDBT_FAILED;
1427 }
1428
1429 return result;
1430 }
1431
runPkSizes(NDBT_Context * ctx,NDBT_Step * step)1432 int runPkSizes(NDBT_Context* ctx, NDBT_Step* step){
1433 int result = NDBT_OK;
1434 char tabName[256];
1435 int minPkSize = 1;
1436 ndbout << "minPkSize=" <<minPkSize<<endl;
1437 int maxPkSize = MAX_KEY_SIZE_IN_WORDS * 4;
1438 ndbout << "maxPkSize=" <<maxPkSize<<endl;
1439 Ndb* pNdb = GETNDB(step);
1440 int numRecords = ctx->getNumRecords();
1441
1442 for (int i = minPkSize; i < maxPkSize; i++){
1443 BaseString::snprintf(tabName, 256, "TPK_%d", i);
1444
1445 int records = numRecords;
1446 int max = ~0;
1447 // Limit num records for small PKs
1448 if (i == 1)
1449 max = 99;
1450 if (i == 2)
1451 max = 999;
1452 if (i == 3)
1453 max = 9999;
1454 if (records > max)
1455 records = max;
1456 ndbout << "records =" << records << endl;
1457
1458 if (pNdb->waitUntilReady(30) != 0){
1459 // Db is not ready, return with failure
1460 return NDBT_FAILED;
1461 }
1462
1463 ndbout << "|- " << tabName << endl;
1464
1465 if (NDBT_Tables::createTable(pNdb, tabName) != 0){
1466 ndbout << tabName << " could not be created"<< endl;
1467 return NDBT_FAILED;
1468 }
1469
1470 // Verify that table exists in db
1471 const NdbDictionary::Table* pTab3 =
1472 NDBT_Table::discoverTableFromDb(pNdb, tabName) ;
1473 if (pTab3 == NULL){
1474 g_err << tabName << " was not found in DB"<< endl;
1475 return NDBT_FAILED;
1476 }
1477
1478 // ndbout << *pTab3 << endl;
1479
1480 if (pTab3->equal(*NDBT_Tables::getTable(tabName)) == false){
1481 g_err << "It was not equal" << endl;
1482 return NDBT_FAILED;
1483 }
1484
1485 do {
1486 // Do it all
1487 HugoTransactions hugoTrans(*pTab3);
1488 UtilTransactions utilTrans(*pTab3);
1489 int count;
1490 CHECK(hugoTrans.loadTable(pNdb, records) == 0);
1491 CHECK(hugoTrans.pkUpdateRecords(pNdb, records) == 0);
1492 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1493 CHECK(count == records);
1494 CHECK(hugoTrans.pkDelRecords(pNdb, records/2) == 0);
1495 CHECK(hugoTrans.scanUpdateRecords(pNdb, records/2) == 0);
1496 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1497 CHECK(count == (records/2));
1498 CHECK(utilTrans.clearTable(pNdb, records) == 0);
1499
1500 #if 0
1501 // Fill table
1502 CHECK(hugoTrans.fillTable(pNdb) == 0);
1503 CHECK(utilTrans.clearTable2(pNdb, records) == 0);
1504 CHECK(utilTrans.selectCount(pNdb, 64, &count) == 0);
1505 CHECK(count == 0);
1506 #endif
1507 } while(false);
1508
1509 // Drop table
1510 if (pNdb->getDictionary()->dropTable(pTab3->getName()) != 0){
1511 ndbout << "Failed to drop "<<pTab3->getName()<<" in db" << endl;
1512 return NDBT_FAILED;
1513 }
1514 }
1515 return result;
1516 }
1517
runStoreFrm(NDBT_Context * ctx,NDBT_Step * step)1518 int runStoreFrm(NDBT_Context* ctx, NDBT_Step* step){
1519 Ndb* pNdb = GETNDB(step);
1520 const NdbDictionary::Table* pTab = ctx->getTab();
1521 int result = NDBT_OK;
1522 int loops = ctx->getNumLoops();
1523
1524 for (int l = 0; l < loops && result == NDBT_OK ; l++){
1525
1526 Uint32 dataLen = (Uint32)myRandom48(TEST_FRM_DATA_SIZE);
1527 // size_t dataLen = 10;
1528 unsigned char data[TEST_FRM_DATA_SIZE];
1529
1530 char start = l + 248;
1531 for(Uint32 i = 0; i < dataLen; i++){
1532 data[i] = start;
1533 start++;
1534 }
1535 #if 0
1536 ndbout << "dataLen="<<dataLen<<endl;
1537 for (Uint32 i = 0; i < dataLen; i++){
1538 unsigned char c = data[i];
1539 ndbout << hex << c << ", ";
1540 }
1541 ndbout << endl;
1542 #endif
1543
1544 NdbDictionary::Table newTab(* pTab);
1545 void* pData = &data;
1546 newTab.setFrm(pData, dataLen);
1547
1548 // Try to create table in db
1549 if (newTab.createTableInDb(pNdb) != 0){
1550 result = NDBT_FAILED;
1551 continue;
1552 }
1553
1554 // Verify that table is in db
1555 const NdbDictionary::Table* pTab2 =
1556 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1557 if (pTab2 == NULL){
1558 g_err << pTab->getName() << " was not found in DB"<< endl;
1559 result = NDBT_FAILED;
1560 continue;
1561 }
1562
1563 const void* pData2 = pTab2->getFrmData();
1564 Uint32 resultLen = pTab2->getFrmLength();
1565 if (dataLen != resultLen){
1566 g_err << "Length of data failure" << endl
1567 << " expected = " << dataLen << endl
1568 << " got = " << resultLen << endl;
1569 result = NDBT_FAILED;
1570 }
1571
1572 // Verfiy the frm data
1573 if (memcmp(pData, pData2, resultLen) != 0){
1574 g_err << "Wrong data received" << endl;
1575 for (size_t i = 0; i < dataLen; i++){
1576 unsigned char c = ((unsigned char*)pData2)[i];
1577 g_err << hex << c << ", ";
1578 }
1579 g_err << endl;
1580 result = NDBT_FAILED;
1581 }
1582
1583 if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
1584 g_err << "It can NOT be dropped" << endl;
1585 result = NDBT_FAILED;
1586 }
1587 }
1588
1589 return result;
1590 }
1591
runStoreExtraMetada(NDBT_Context * ctx,NDBT_Step * step)1592 int runStoreExtraMetada(NDBT_Context* ctx, NDBT_Step* step)
1593 {
1594 Ndb* pNdb = GETNDB(step);
1595 const NdbDictionary::Table* pTab = ctx->getTab();
1596 int result = NDBT_OK;
1597
1598 static constexpr Uint32 testBufferLenInWords = (TEST_FRM_DATA_SIZE + 3) / 4;
1599 Int32 data[testBufferLenInWords];
1600
1601 for (int l = 0; l < ctx->getNumLoops() && result == NDBT_OK ; l++)
1602 {
1603 /* LENGTH OF DATA: The data fills 75% to 100% of the test buffer. */
1604 const Uint32 dataLen = (testBufferLenInWords * 3) +
1605 myRandom48(testBufferLenInWords);
1606 const Uint32 dataLenInWords = (dataLen + 3) / 4;
1607
1608 /* Fill the buffer with (almost) random data. We use random data to defeat
1609 the zlib compression that will be applied to ExtraMetadata.
1610 Actually myRandom48() returns a signed long int >= 0, so for every 32
1611 bits stored we only get 31 bits of randomness, but this is good enough.
1612 */
1613 for(Uint32 i = 0; i < dataLenInWords; i++)
1614 {
1615 data[i] = myRandom48(INT32_MAX);
1616 }
1617
1618 NdbDictionary::Table newTab(* pTab);
1619 // Using loop counter for version since any version should be supported
1620 const Uint32 version = l;
1621 if (newTab.setExtraMetadata(version,
1622 &data, dataLen))
1623 {
1624 g_err << "table.setExtraMetadata() failed. length:" << dataLen << endl;
1625 result = NDBT_FAILED;
1626 continue;
1627 }
1628
1629 // Try to create table in db
1630 if (newTab.createTableInDb(pNdb) != 0){
1631 g_err << "createTableInDb() failed" << endl;
1632 result = NDBT_FAILED;
1633 continue;
1634 }
1635
1636 // Verify that table is in db
1637 const NdbDictionary::Table* pTab2 =
1638 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1639 if (pTab2 == NULL){
1640 g_err << pTab->getName() << " was not found in DB"<< endl;
1641 result = NDBT_FAILED;
1642 continue;
1643 }
1644
1645 Uint32 version2;
1646 void* data2;
1647 Uint32 dataLen2;
1648 if (pTab2->getExtraMetadata(version2,
1649 &data2, &dataLen2))
1650 {
1651 result = NDBT_FAILED;
1652 }
1653
1654 if (version != version2)
1655 {
1656 g_err << "Wrong version received" << endl
1657 << " expected = " << version << endl
1658 << " got = " << version2 << endl;
1659 result = NDBT_FAILED;
1660 }
1661
1662 if (dataLen != dataLen2){
1663 g_err << "Length of data failure" << endl
1664 << " expected = " << dataLen << endl
1665 << " got = " << dataLen2 << endl;
1666 result = NDBT_FAILED;
1667 }
1668
1669 // Verify the frm data
1670 if (memcmp(data, data2, dataLen2) != 0)
1671 {
1672 g_err << "Wrong data received" << endl;
1673 for (size_t i = 0; i < dataLen; i++){
1674 unsigned char c = ((unsigned char*)data2)[i];
1675 g_err << hex << c << ", ";
1676 }
1677 g_err << endl;
1678 result = NDBT_FAILED;
1679 }
1680 free(data2);
1681
1682 if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
1683 g_err << "It can NOT be dropped" << endl;
1684 result = NDBT_FAILED;
1685 }
1686 }
1687
1688 return result;
1689 }
1690
1691 /* After wl#10665, the limit on the size of ExtraMetadata is
1692 defined by MAX_WORDS_META_FILE.
1693 */
runStoreExtraMetadataError(NDBT_Context * ctx,NDBT_Step * step)1694 int runStoreExtraMetadataError(NDBT_Context* ctx, NDBT_Step* step)
1695 {
1696 Ndb* pNdb = GETNDB(step);
1697 const NdbDictionary::Table* pTab = ctx->getTab();
1698 int result = NDBT_OK;
1699
1700 static constexpr Uint32 dataLenInWords = MAX_WORDS_META_FILE;
1701 static constexpr Uint32 dataLen = dataLenInWords * 4;
1702 Int32 data[dataLenInWords];
1703
1704 for (int l = 0; l < ctx->getNumLoops() && result == NDBT_OK ; l++)
1705 {
1706 // The whole dictionary entry must fit in MAX_WORDS_META_FILE.
1707 // Create a table where the ExtraMetadata alone is too long
1708 // (and cannot be effectively compressed).
1709
1710 for(Uint32 i = 0; i < dataLenInWords; i++)
1711 {
1712 data[i] = myRandom48(INT32_MAX);
1713 }
1714
1715 // It should be possible to set the extra metadata
1716 // even though it later will not work to create the table
1717 NdbDictionary::Table newTab(* pTab);
1718 if (newTab.setExtraMetadata(37, // version
1719 data, dataLen))
1720 {
1721 g_err << "Failed to set the extra metadata, length: " << dataLen << endl;
1722 result = NDBT_FAILED;
1723 continue;
1724 }
1725
1726 // Try to create table in db, should fail!
1727 if (newTab.createTableInDb(pNdb) == 0){
1728 g_err << "Table created, that was unexpected" << endl;
1729 result = NDBT_FAILED;
1730 continue;
1731 }
1732
1733 const NdbDictionary::Table* pTab2 =
1734 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1735 if (pTab2 != NULL){
1736 g_err << pTab->getName() << " was found in DB"<< endl;
1737 result = NDBT_FAILED;
1738 if (pNdb->getDictionary()->dropTable(pTab2->getName()) != 0){
1739 g_err << "It can NOT be dropped" << endl;
1740 result = NDBT_FAILED;
1741 }
1742
1743 continue;
1744 }
1745
1746 }
1747
1748 return result;
1749 }
1750
verifyTablesAreEqual(const NdbDictionary::Table * pTab,const NdbDictionary::Table * pTab2)1751 int verifyTablesAreEqual(const NdbDictionary::Table* pTab, const NdbDictionary::Table* pTab2){
1752 // Verify that getPrimaryKey only returned true for primary keys
1753 for (int i = 0; i < pTab2->getNoOfColumns(); i++){
1754 const NdbDictionary::Column* col = pTab->getColumn(i);
1755 const NdbDictionary::Column* col2 = pTab2->getColumn(i);
1756 if (col->getPrimaryKey() != col2->getPrimaryKey()){
1757 g_err << "col->getPrimaryKey() != col2->getPrimaryKey()" << endl;
1758 return NDBT_FAILED;
1759 }
1760 }
1761
1762 if (!pTab->equal(*pTab2)){
1763 g_err << "equal failed" << endl;
1764 g_info << *(NDBT_Table*)pTab; // gcc-4.1.2
1765 g_info << *(NDBT_Table*)pTab2;
1766 return NDBT_FAILED;
1767 }
1768 return NDBT_OK;
1769 }
1770
runGetPrimaryKey(NDBT_Context * ctx,NDBT_Step * step)1771 int runGetPrimaryKey(NDBT_Context* ctx, NDBT_Step* step){
1772 Ndb* pNdb = GETNDB(step);
1773 const NdbDictionary::Table* pTab = ctx->getTab();
1774 ndbout << "|- " << pTab->getName() << endl;
1775 g_info << *(NDBT_Table*)pTab;
1776 // Try to create table in db
1777 if (pTab->createTableInDb(pNdb) != 0){
1778 return NDBT_FAILED;
1779 }
1780
1781 const NdbDictionary::Table* pTab2 =
1782 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1783 if (pTab2 == NULL){
1784 ndbout << pTab->getName() << " was not found in DB"<< endl;
1785 return NDBT_FAILED;
1786 }
1787
1788 int result = NDBT_OK;
1789 if (verifyTablesAreEqual(pTab, pTab2) != NDBT_OK)
1790 result = NDBT_FAILED;
1791
1792
1793 #if 0
1794 // Create an index on the table and see what
1795 // the function returns now
1796 char name[200];
1797 sprintf(name, "%s_X007", pTab->getName());
1798 NDBT_Index* pInd = new NDBT_Index(name);
1799 pInd->setTable(pTab->getName());
1800 pInd->setType(NdbDictionary::Index::UniqueHashIndex);
1801 // pInd->setLogging(false);
1802 for (int i = 0; i < 2; i++){
1803 const NDBT_Attribute* pAttr = pTab->getAttribute(i);
1804 pInd->addAttribute(*pAttr);
1805 }
1806 g_info << "Create index:" << endl << *pInd;
1807 if (pInd->createIndexInDb(pNdb, false) != 0){
1808 result = NDBT_FAILED;
1809 }
1810 delete pInd;
1811
1812 const NdbDictionary::Table* pTab3 =
1813 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1814 if (pTab3 == NULL){
1815 ndbout << pTab->getName() << " was not found in DB"<< endl;
1816 return NDBT_FAILED;
1817 }
1818
1819 if (verifyTablesAreEqual(pTab, pTab3) != NDBT_OK)
1820 result = NDBT_FAILED;
1821 if (verifyTablesAreEqual(pTab2, pTab3) != NDBT_OK)
1822 result = NDBT_FAILED;
1823 #endif
1824
1825 #if 0
1826 if (pTab2->getDictionary()->dropTable(pNdb) != 0){
1827 ndbout << "Failed to drop "<<pTab2->getName()<<" in db" << endl;
1828 return NDBT_FAILED;
1829 }
1830
1831 // Verify that table is not in db
1832 const NdbDictionary::Table* pTab4 =
1833 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1834 if (pTab4 != NULL){
1835 ndbout << pTab4->getName() << " was found in DB"<< endl;
1836 return NDBT_FAILED;
1837 }
1838 #endif
1839
1840 return result;
1841 }
1842
1843 #define APIERROR(error) \
1844 { g_err << "Error in " << __FILE__ << ", line:" << __LINE__ << ", code:" \
1845 << error.code << ", msg: " << error.message << "." << endl; \
1846 }
1847
1848 int
runCreateAutoincrementTable(NDBT_Context * ctx,NDBT_Step * step)1849 runCreateAutoincrementTable(NDBT_Context* ctx, NDBT_Step* step){
1850
1851 Uint32 startvalues[5] = {256-2, 0, 256*256-2, ~Uint32(0), 256*256*256-2};
1852
1853 int ret = NDBT_OK;
1854
1855 for (int jj = 0; jj < 5 && ret == NDBT_OK; jj++) {
1856 char tabname[] = "AUTOINCTAB";
1857 Uint32 startvalue = startvalues[jj];
1858
1859 NdbDictionary::Table myTable;
1860 NdbDictionary::Column myColumn;
1861
1862 Ndb* myNdb = GETNDB(step);
1863 NdbDictionary::Dictionary* myDict = myNdb->getDictionary();
1864
1865
1866 if (myDict->getTable(tabname) != NULL) {
1867 g_err << "NDB already has example table: " << tabname << endl;
1868 APIERROR(myNdb->getNdbError());
1869 return NDBT_FAILED;
1870 }
1871
1872 myTable.setName(tabname);
1873
1874 myColumn.setName("ATTR1");
1875 myColumn.setType(NdbDictionary::Column::Unsigned);
1876 myColumn.setLength(1);
1877 myColumn.setPrimaryKey(true);
1878 myColumn.setNullable(false);
1879 myColumn.setAutoIncrement(true);
1880 if (startvalue != ~Uint32(0)) // check that default value starts with 1
1881 myColumn.setAutoIncrementInitialValue(startvalue);
1882 myTable.addColumn(myColumn);
1883
1884 if (myDict->createTable(myTable) == -1) {
1885 g_err << "Failed to create table " << tabname << endl;
1886 APIERROR(myNdb->getNdbError());
1887 return NDBT_FAILED;
1888 }
1889
1890
1891 if (startvalue == ~Uint32(0)) // check that default value starts with 1
1892 startvalue = 1;
1893
1894 for (int i = 0; i < 16; i++) {
1895
1896 Uint64 value;
1897 if (myNdb->getAutoIncrementValue(tabname, value, 1) == -1) {
1898 g_err << "getAutoIncrementValue failed on " << tabname << endl;
1899 APIERROR(myNdb->getNdbError());
1900 return NDBT_FAILED;
1901 }
1902 else if (value != (startvalue+i)) {
1903 g_err << "value = " << value << " expected " << startvalue+i << endl;;
1904 APIERROR(myNdb->getNdbError());
1905 // ret = NDBT_FAILED;
1906 // break;
1907 }
1908 }
1909
1910 if (myDict->dropTable(tabname) == -1) {
1911 g_err << "Failed to drop table " << tabname << endl;
1912 APIERROR(myNdb->getNdbError());
1913 ret = NDBT_FAILED;
1914 }
1915 }
1916
1917 return ret;
1918 }
1919
1920 int
runTableRename(NDBT_Context * ctx,NDBT_Step * step)1921 runTableRename(NDBT_Context* ctx, NDBT_Step* step){
1922
1923 int result = NDBT_OK;
1924
1925 Ndb* pNdb = GETNDB(step);
1926 NdbDictionary::Dictionary* dict = pNdb->getDictionary();
1927 int records = ctx->getNumRecords();
1928 const int loops = ctx->getNumLoops();
1929
1930 ndbout << "|- " << ctx->getTab()->getName() << endl;
1931
1932 for (int l = 0; l < loops && result == NDBT_OK ; l++){
1933 const NdbDictionary::Table* pTab = ctx->getTab();
1934
1935 // Try to create table in db
1936 if (pTab->createTableInDb(pNdb) != 0){
1937 return NDBT_FAILED;
1938 }
1939
1940 // Verify that table is in db
1941 const NdbDictionary::Table* pTab2 =
1942 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
1943 if (pTab2 == NULL){
1944 ndbout << pTab->getName() << " was not found in DB"<< endl;
1945 return NDBT_FAILED;
1946 }
1947 ctx->setTab(pTab2);
1948
1949 // Load table
1950 HugoTransactions hugoTrans(*ctx->getTab());
1951 if (hugoTrans.loadTable(pNdb, records) != 0){
1952 return NDBT_FAILED;
1953 }
1954
1955 // Rename table
1956 BaseString pTabName(pTab->getName());
1957 BaseString pTabNewName(pTabName);
1958 pTabNewName.append("xx");
1959
1960 const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
1961 if (oldTable) {
1962 NdbDictionary::Table newTable = *oldTable;
1963 newTable.setName(pTabNewName.c_str());
1964 CHECK2(dict->alterTable(*oldTable, newTable) == 0,
1965 "TableRename failed");
1966 }
1967 else {
1968 result = NDBT_FAILED;
1969 }
1970
1971 // Verify table contents
1972 NdbDictionary::Table pNewTab(pTabNewName.c_str());
1973
1974 UtilTransactions utilTrans(pNewTab);
1975 if (utilTrans.clearTable(pNdb, records) != 0){
1976 continue;
1977 }
1978
1979 // Drop table
1980 dict->dropTable(pNewTab.getName());
1981 }
1982 end:
1983
1984 return result;
1985 }
1986
1987 int
runTableRenameSR(NDBT_Context * ctx,NDBT_Step * step)1988 runTableRenameSR(NDBT_Context* ctx, NDBT_Step* step){
1989 NdbRestarter restarter;
1990 if(restarter.getNumDbNodes() < 2)
1991 return NDBT_OK;
1992
1993 int result = NDBT_OK;
1994
1995 Ndb* pNdb = GETNDB(step);
1996 NdbDictionary::Dictionary* dict = pNdb->getDictionary();
1997 int records = ctx->getNumRecords();
1998 const int loops = ctx->getNumLoops();
1999
2000 ndbout << "|- " << ctx->getTab()->getName() << endl;
2001
2002 for (int l = 0; l < loops && result == NDBT_OK ; l++){
2003 // Rename table
2004 const NdbDictionary::Table* pTab = ctx->getTab();
2005
2006 // Try to create table in db
2007 if (pTab->createTableInDb(pNdb) != 0){
2008 return NDBT_FAILED;
2009 }
2010
2011 // Verify that table is in db
2012 const NdbDictionary::Table* pTab2 =
2013 NDBT_Table::discoverTableFromDb(pNdb, pTab->getName());
2014 if (pTab2 == NULL){
2015 ndbout << pTab->getName() << " was not found in DB"<< endl;
2016 return NDBT_FAILED;
2017 }
2018 ctx->setTab(pTab2);
2019
2020 // Load table
2021 HugoTransactions hugoTrans(*ctx->getTab());
2022 if (hugoTrans.loadTable(pNdb, records) != 0){
2023 return NDBT_FAILED;
2024 }
2025
2026 BaseString pTabName(pTab->getName());
2027 BaseString pTabNewName(pTabName);
2028 pTabNewName.append("xx");
2029
2030 const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
2031 if (oldTable) {
2032 NdbDictionary::Table newTable = *oldTable;
2033 newTable.setName(pTabNewName.c_str());
2034 CHECK2(dict->alterTable(*oldTable, newTable) == 0,
2035 "TableRename failed");
2036 }
2037 else {
2038 result = NDBT_FAILED;
2039 }
2040
2041 // Restart cluster
2042
2043 /**
2044 * Need to run LCP at high rate otherwise
2045 * packed replicas become "to many"
2046 */
2047 int val = DumpStateOrd::DihMinTimeBetweenLCP;
2048 if(restarter.dumpStateAllNodes(&val, 1) != 0){
2049 do { CHECK(0); } while(0);
2050 g_err << "Failed to set LCP to min value" << endl;
2051 return NDBT_FAILED;
2052 }
2053
2054 CHECK2(restarter.restartAll() == 0,
2055 "failed to set restartOneDbNode");
2056
2057 CHECK2(restarter.waitClusterStarted() == 0,
2058 "waitClusterStarted failed");
2059 CHK_NDB_READY(pNdb);
2060
2061 // Verify table contents
2062 NdbDictionary::Table pNewTab(pTabNewName.c_str());
2063
2064 UtilTransactions utilTrans(pNewTab);
2065 if (utilTrans.clearTable(pNdb, records) != 0){
2066 continue;
2067 }
2068
2069 // Drop table
2070 dict->dropTable(pTabNewName.c_str());
2071 }
2072 end:
2073 return result;
2074 }
2075
2076 /*
2077 Run rename column
2078 */
2079 int
runColumnRename(NDBT_Context * ctx,NDBT_Step * step)2080 runColumnRename(NDBT_Context* ctx, NDBT_Step* step){
2081 int result = NDBT_OK;
2082
2083 Ndb* pNdb = GETNDB(step);
2084 NdbDictionary::Dictionary* dict = pNdb->getDictionary();
2085 int records = ctx->getNumRecords();
2086 const int loops = ctx->getNumLoops();
2087
2088 ndbout << "|- " << ctx->getTab()->getName() << endl;
2089
2090 NdbDictionary::Table myTab= *(ctx->getTab());
2091
2092 for (int l = 0; l < loops && result == NDBT_OK ; l++){
2093 // Try to create table in db
2094
2095 if (NDBT_Tables::createTable(pNdb, myTab.getName()) != 0){
2096 return NDBT_FAILED;
2097 }
2098
2099 // Verify that table is in db
2100 const NdbDictionary::Table* pTab2 =
2101 NDBT_Table::discoverTableFromDb(pNdb, myTab.getName());
2102 if (pTab2 == NULL){
2103 ndbout << myTab.getName() << " was not found in DB"<< endl;
2104 return NDBT_FAILED;
2105 }
2106 ctx->setTab(pTab2);
2107
2108 /*
2109 Check that table already has a varpart, otherwise add attr is
2110 not possible.
2111 */
2112 if (pTab2->getForceVarPart() == false)
2113 {
2114 const NdbDictionary::Column *col;
2115 for (Uint32 i= 0; (col= pTab2->getColumn(i)) != 0; i++)
2116 {
2117 if (col->getStorageType() == NDB_STORAGETYPE_MEMORY &&
2118 (col->getDynamic() || col->getArrayType() != NDB_ARRAYTYPE_FIXED))
2119 break;
2120 }
2121 if (col == 0)
2122 {
2123 /* Alter table add attribute not applicable, just mark success. */
2124 dict->dropTable(pTab2->getName());
2125 break;
2126 }
2127 }
2128
2129 ndbout << "Load table" << endl;
2130 // Load table
2131 HugoTransactions beforeTrans(*ctx->getTab());
2132 if (beforeTrans.loadTable(pNdb, records) != 0){
2133 return NDBT_FAILED;
2134 }
2135 ndbout << "Load table completed" << endl;
2136
2137 // Add attributes to table.
2138 BaseString pTabName(pTab2->getName());
2139
2140 const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
2141 if (oldTable) {
2142 NdbDictionary::Table newTable= *oldTable;
2143
2144 NDBT_Attribute newcol1("NEWKOL1", NdbDictionary::Column::Unsigned, 1,
2145 false, true, 0,
2146 NdbDictionary::Column::StorageTypeMemory, true);
2147 newTable.addColumn(newcol1);
2148 CHECK2(dict->alterTable(*oldTable, newTable) == 0,
2149 "runColumnRename failed");
2150 /* Need to purge old version and reload new version after alter table. */
2151 dict->invalidateTable(pTabName.c_str());
2152 }
2153 else {
2154 result = NDBT_FAILED;
2155 }
2156 ndbout << "Added column completed" << endl;
2157 {
2158 const NdbDictionary::Table* oldTable = dict->getTable(pTabName.c_str());
2159 if (oldTable) {
2160 NdbDictionary::Table newTable= *oldTable;
2161 int colNum= newTable.getNoOfColumns()-1;
2162 NdbDictionary::Column* addedCol= newTable.getColumn(colNum);
2163 addedCol->setName("renamed_NEWKOL1");
2164 CHECK2(dict->alterTable(*oldTable, newTable) == 0,
2165 "runColumnRename failed");
2166 /* Need to purge old version and reload new version after alter table. */
2167 dict->invalidateTable(pTabName.c_str());
2168 }
2169 else {
2170 result = NDBT_FAILED;
2171 break;
2172 }
2173 }
2174
2175 ndbout << "Column rename completed" << endl;
2176 {
2177 const NdbDictionary::Table* pTab = dict->getTable(pTabName.c_str());
2178 CHECK2(pTab != NULL, "Table not found");
2179 HugoTransactions afterTrans(*pTab);
2180
2181 ndbout << "Checking renamed column" << endl;
2182 const NdbDictionary::Column* addedCol= pTab->getColumn("renamed_NEWKOL1");
2183 CHECK2((addedCol) && addedCol->getColumnNo() == pTab->getNoOfColumns()-1,
2184 "runColumnRename failed");
2185
2186 ndbout << "delete...";
2187 if (afterTrans.clearTable(pNdb) != 0)
2188 {
2189 return NDBT_FAILED;
2190 }
2191 ndbout << endl;
2192
2193 ndbout << "insert...";
2194 if (afterTrans.loadTable(pNdb, records) != 0){
2195 return NDBT_FAILED;
2196 }
2197 ndbout << endl;
2198
2199 ndbout << "update...";
2200 if (afterTrans.scanUpdateRecords(pNdb, records) != 0)
2201 {
2202 return NDBT_FAILED;
2203 }
2204 ndbout << endl;
2205
2206 ndbout << "delete...";
2207 if (afterTrans.clearTable(pNdb) != 0)
2208 {
2209 return NDBT_FAILED;
2210 }
2211 ndbout << endl;
2212 }
2213
2214 // Drop table
2215 dict->dropTable(pTabName.c_str());
2216 }
2217 end:
2218
2219 return result;
2220 }
2221
2222 /*
2223 Run rename column with restart
2224 */
2225 int
runColumnRenameSR(NDBT_Context * ctx,NDBT_Step * step)2226 runColumnRenameSR(NDBT_Context* ctx, NDBT_Step* step){
2227 int result = NDBT_OK;
2228
2229 Ndb* pNdb = GETNDB(step);
2230 NdbDictionary::Dictionary* dict = pNdb->getDictionary();
2231 int records = ctx->getNumRecords();
2232 const int loops = ctx->getNumLoops();
2233 NdbRestarter res;
2234
2235 ndbout << "|- " << ctx->getTab()->getName() << endl;
2236
2237 NdbDictionary::Table myTab= *(ctx->getTab());
2238
2239 for (int l = 0; l < loops && result == NDBT_OK ; l++){
2240 // Try to create table in db
2241
2242 if (NDBT_Tables::createTable(pNdb, myTab.getName()) != 0){
2243 return NDBT_FAILED;
2244 }
2245
2246 // Verify that table is in db
2247 const NdbDictionary::Table* pTab2 =
2248 NDBT_Table::discoverTableFromDb(pNdb, myTab.getName());
2249 if (pTab2 == NULL){
2250 ndbout << myTab.getName() << " was not found in DB"<< endl;
2251 return NDBT_FAILED;
2252 }
2253 ctx->setTab(pTab2);
2254
2255 /*
2256 Check that table already has a varpart, otherwise add attr is
2257 not possible.
2258 */
2259 if (pTab2->getForceVarPart() == false)
2260 {
2261 const NdbDictionary::Column *col;
2262 for (Uint32 i= 0; (col= pTab2->getColumn(i)) != 0; i++)
2263 {
2264 if (col->getStorageType() == NDB_STORAGETYPE_MEMORY &&
2265 (col->getDynamic() || col->getArrayType() != NDB_ARRAYTYPE_FIXED))
2266 break;
2267 }
2268 if (col == 0)
2269 {
2270 /* Alter table add attribute not applicable, just mark success. */
2271 dict->dropTable(pTab2->getName());
2272 break;
2273 }
2274 }
2275
2276 ndbout << "Load table" << endl;
2277 // Load table
2278 HugoTransactions beforeTrans(*ctx->getTab());
2279 if (beforeTrans.loadTable(pNdb, records) != 0){
2280 return NDBT_FAILED;
2281 }
2282 ndbout << "Load table completed" << endl;
2283
2284 // Add attributes to table.
2285 BaseString pTabName(pTab2->getName());
2286
2287 const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
2288 if (oldTable) {
2289 NdbDictionary::Table newTable= *oldTable;
2290
2291 NDBT_Attribute newcol1("NEWKOL1", NdbDictionary::Column::Unsigned, 1,
2292 false, true, 0,
2293 NdbDictionary::Column::StorageTypeMemory, true);
2294 newTable.addColumn(newcol1);
2295 CHECK2(dict->alterTable(*oldTable, newTable) == 0,
2296 "runColumnRename failed");
2297 /* Need to purge old version and reload new version after alter table. */
2298 dict->invalidateTable(pTabName.c_str());
2299 }
2300 else {
2301 result = NDBT_FAILED;
2302 }
2303 ndbout << "Added column completed" << endl;
2304 {
2305 const NdbDictionary::Table* oldTable = dict->getTable(pTabName.c_str());
2306 if (oldTable) {
2307 NdbDictionary::Table newTable= *oldTable;
2308 int colNum= newTable.getNoOfColumns()-1;
2309 NdbDictionary::Column* addedCol= newTable.getColumn(colNum);
2310 addedCol->setName("renamed_NEWKOL1");
2311 CHECK2(dict->alterTable(*oldTable, newTable) == 0,
2312 "runColumnRename failed");
2313 /* Need to purge old version and reload new version after alter table. */
2314 dict->invalidateTable(pTabName.c_str());
2315 }
2316 else {
2317 result = NDBT_FAILED;
2318 break;
2319 }
2320 }
2321
2322 ndbout << "Column rename completed" << endl;
2323 {
2324 const NdbDictionary::Table* pTab = dict->getTable(pTabName.c_str());
2325 CHECK2(pTab != NULL, "Table not found");
2326 HugoTransactions afterTrans(*pTab);
2327
2328 ndbout_c("performing system restart");
2329 CHECK2(res.restartAll(false, true, false) == 0,
2330 "restart all failed");
2331 CHECK2(res.waitClusterNoStart() == 0,
2332 "waitClusterNoStart failed");
2333 CHECK2(res.startAll() == 0,
2334 "startAll failed");
2335 CHECK2(res.waitClusterStarted() == 0,
2336 "waitClusterStarted failed");
2337
2338 ndbout << "Checking renamed column" << endl;
2339 pTab = dict->getTable(pTabName.c_str());
2340 const NdbDictionary::Column* addedCol= pTab->getColumn("renamed_NEWKOL1");
2341 CHECK2((addedCol) && addedCol->getColumnNo() == pTab->getNoOfColumns()-1,
2342 "runColumnRename failed");
2343
2344 ndbout << "delete...";
2345 if (afterTrans.clearTable(pNdb) != 0)
2346 {
2347 return NDBT_FAILED;
2348 }
2349 ndbout << endl;
2350
2351 ndbout << "insert...";
2352 if (afterTrans.loadTable(pNdb, records) != 0){
2353 return NDBT_FAILED;
2354 }
2355 ndbout << endl;
2356
2357 ndbout << "update...";
2358 if (afterTrans.scanUpdateRecords(pNdb, records) != 0)
2359 {
2360 return NDBT_FAILED;
2361 }
2362 ndbout << endl;
2363
2364 ndbout << "delete...";
2365 if (afterTrans.clearTable(pNdb) != 0)
2366 {
2367 return NDBT_FAILED;
2368 }
2369 ndbout << endl;
2370 }
2371
2372 // Drop table
2373 dict->dropTable(pTabName.c_str());
2374 }
2375 end:
2376
2377 return result;
2378 }
2379
2380 /*
2381 Run online alter table add attributes.
2382 */
2383 int
runTableAddAttrs(NDBT_Context * ctx,NDBT_Step * step)2384 runTableAddAttrs(NDBT_Context* ctx, NDBT_Step* step){
2385
2386 int result = NDBT_OK;
2387
2388 Ndb* pNdb = GETNDB(step);
2389 NdbDictionary::Dictionary* dict = pNdb->getDictionary();
2390 int records = ctx->getNumRecords();
2391 const int loops = ctx->getNumLoops();
2392
2393 ndbout << "|- " << ctx->getTab()->getName() << endl;
2394
2395 NdbDictionary::Table myTab= *(ctx->getTab());
2396
2397 for (int l = 0; l < loops && result == NDBT_OK ; l++){
2398 // Try to create table in db
2399
2400 if (NDBT_Tables::createTable(pNdb, myTab.getName()) != 0){
2401 return NDBT_FAILED;
2402 }
2403
2404 // Verify that table is in db
2405 const NdbDictionary::Table* pTab2 =
2406 NDBT_Table::discoverTableFromDb(pNdb, myTab.getName());
2407 if (pTab2 == NULL){
2408 ndbout << myTab.getName() << " was not found in DB"<< endl;
2409 return NDBT_FAILED;
2410 }
2411 ctx->setTab(pTab2);
2412
2413 /*
2414 Check that table already has a varpart, otherwise add attr is
2415 not possible.
2416 */
2417 if (pTab2->getForceVarPart() == false)
2418 {
2419 const NdbDictionary::Column *col;
2420 for (Uint32 i= 0; (col= pTab2->getColumn(i)) != 0; i++)
2421 {
2422 if (col->getStorageType() == NDB_STORAGETYPE_MEMORY &&
2423 (col->getDynamic() || col->getArrayType() != NDB_ARRAYTYPE_FIXED))
2424 break;
2425 }
2426 if (col == 0)
2427 {
2428 /* Alter table add attribute not applicable, just mark success. */
2429 dict->dropTable(pTab2->getName());
2430 break;
2431 }
2432 }
2433
2434 ndbout << "Load table" << endl;
2435 // Load table
2436 HugoTransactions beforeTrans(*ctx->getTab());
2437 if (beforeTrans.loadTable(pNdb, records) != 0){
2438 return NDBT_FAILED;
2439 }
2440 ndbout << "Load table completed" << endl;
2441
2442 // Add attributes to table.
2443 BaseString pTabName(pTab2->getName());
2444
2445 const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
2446 if (oldTable) {
2447 NdbDictionary::Table newTable= *oldTable;
2448
2449 NDBT_Attribute newcol1("NEWKOL1", NdbDictionary::Column::Unsigned, 1,
2450 false, true, 0,
2451 NdbDictionary::Column::StorageTypeMemory, true);
2452 newTable.addColumn(newcol1);
2453 NDBT_Attribute newcol2("NEWKOL2", NdbDictionary::Column::Char, 14,
2454 false, true, 0,
2455 NdbDictionary::Column::StorageTypeMemory, true);
2456 newTable.addColumn(newcol2);
2457 NDBT_Attribute newcol3("NEWKOL3", NdbDictionary::Column::Bit, 20,
2458 false, true, 0,
2459 NdbDictionary::Column::StorageTypeMemory, true);
2460 newTable.addColumn(newcol3);
2461 NDBT_Attribute newcol4("NEWKOL4", NdbDictionary::Column::Varbinary, 42,
2462 false, true, 0,
2463 NdbDictionary::Column::StorageTypeMemory, true);
2464 newTable.addColumn(newcol4);
2465
2466 CHECK2(dict->alterTable(*oldTable, newTable) == 0,
2467 "TableAddAttrs failed");
2468 /* Need to purge old version and reload new version after alter table. */
2469 dict->invalidateTable(pTabName.c_str());
2470 }
2471 else {
2472 result = NDBT_FAILED;
2473 }
2474
2475 ndbout << "Altered table completed" << endl;
2476 {
2477 const NdbDictionary::Table* pTab = dict->getTable(pTabName.c_str());
2478 CHECK2(pTab != NULL, "Table not found");
2479 HugoTransactions afterTrans(*pTab);
2480
2481 ndbout << "delete...";
2482 if (afterTrans.clearTable(pNdb) != 0)
2483 {
2484 return NDBT_FAILED;
2485 }
2486 ndbout << endl;
2487
2488 ndbout << "insert...";
2489 if (afterTrans.loadTable(pNdb, records) != 0){
2490 return NDBT_FAILED;
2491 }
2492 ndbout << endl;
2493
2494 ndbout << "update...";
2495 if (afterTrans.scanUpdateRecords(pNdb, records) != 0)
2496 {
2497 return NDBT_FAILED;
2498 }
2499 ndbout << endl;
2500
2501 ndbout << "delete...";
2502 if (afterTrans.clearTable(pNdb) != 0)
2503 {
2504 return NDBT_FAILED;
2505 }
2506 ndbout << endl;
2507 }
2508
2509 // Drop table.
2510 dict->dropTable(pTabName.c_str());
2511 }
2512 end:
2513
2514 return result;
2515 }
2516
2517 /*
2518 Run online alter table add attributes while running simultaneous
2519 transactions on it in separate thread.
2520 */
2521 int
runTableAddAttrsDuring(NDBT_Context * ctx,NDBT_Step * step)2522 runTableAddAttrsDuring(NDBT_Context* ctx, NDBT_Step* step){
2523
2524 int result = NDBT_OK;
2525 int abortAlter = ctx->getProperty("AbortAlter", Uint32(0));
2526
2527 int records = ctx->getNumRecords();
2528 const int loops = ctx->getNumLoops();
2529 NdbRestarter res;
2530
2531 ndbout << "|- " << ctx->getTab()->getName() << endl;
2532
2533 NdbDictionary::Table myTab= *(ctx->getTab());
2534
2535 if (myTab.getForceVarPart() == false)
2536 {
2537 const NdbDictionary::Column *col;
2538 for (Uint32 i= 0; (col= myTab.getColumn(i)) != 0; i++)
2539 {
2540 if (col->getStorageType() == NDB_STORAGETYPE_MEMORY &&
2541 (col->getDynamic() || col->getArrayType() != NDB_ARRAYTYPE_FIXED))
2542 break;
2543 }
2544 if (col == 0)
2545 {
2546 ctx->stopTest();
2547 return NDBT_OK;
2548 }
2549 }
2550
2551 //if
2552
2553 for (int l = 0; l < loops && result == NDBT_OK ; l++){
2554 ndbout << l << ": " << endl;
2555
2556 Ndb* pNdb = GETNDB(step);
2557 NdbDictionary::Dictionary* dict = pNdb->getDictionary();
2558
2559 /*
2560 Check that table already has a varpart, otherwise add attr is
2561 not possible.
2562 */
2563
2564 // Add attributes to table.
2565 ndbout << "Altering table" << endl;
2566
2567 const NdbDictionary::Table * oldTable = dict->getTable(myTab.getName());
2568 if (oldTable) {
2569 NdbDictionary::Table newTable= *oldTable;
2570
2571 char name[256];
2572 BaseString::snprintf(name, sizeof(name), "NEWCOL%d", l);
2573 NDBT_Attribute newcol1(name, NdbDictionary::Column::Unsigned, 1,
2574 false, true, 0,
2575 NdbDictionary::Column::StorageTypeMemory, true);
2576 newTable.addColumn(newcol1);
2577 //ToDo: check #loops, how many columns l
2578
2579 if (abortAlter == 0)
2580 {
2581 CHECK2(dict->alterTable(*oldTable, newTable) == 0,
2582 "TableAddAttrsDuring failed");
2583 }
2584 else
2585 {
2586 int nodeId = res.getNode(NdbRestarter::NS_RANDOM);
2587 res.insertErrorInNode(nodeId, 4029);
2588 CHECK2(dict->alterTable(*oldTable, newTable) != 0,
2589 "TableAddAttrsDuring failed");
2590 }
2591
2592 dict->invalidateTable(myTab.getName());
2593 const NdbDictionary::Table * newTab = dict->getTable(myTab.getName());
2594 CHECK2(newTab != NULL, "'newTab' not found");
2595 HugoTransactions hugoTrans(* newTab);
2596 hugoTrans.scanUpdateRecords(pNdb, records);
2597 }
2598 else {
2599 result= NDBT_FAILED;
2600 break;
2601 }
2602 }
2603 end:
2604
2605 ctx->stopTest();
2606
2607 return result;
2608 }
2609
2610 static void
f(const NdbDictionary::Column * col)2611 f(const NdbDictionary::Column * col){
2612 if(col == 0){
2613 abort();
2614 }
2615 }
2616
2617 int
runTestDictionaryPerf(NDBT_Context * ctx,NDBT_Step * step)2618 runTestDictionaryPerf(NDBT_Context* ctx, NDBT_Step* step){
2619 Vector<char*> cols;
2620 Vector<const NdbDictionary::Table*> tabs;
2621 int i;
2622
2623 Ndb* pNdb = GETNDB(step);
2624
2625 const Uint32 count = NDBT_Tables::getNumTables();
2626 for (i=0; i < (int)count; i++){
2627 const NdbDictionary::Table * tab = NDBT_Tables::getTable(i);
2628 pNdb->getDictionary()->createTable(* tab);
2629
2630 const NdbDictionary::Table * tab2 = pNdb->getDictionary()->getTable(tab->getName());
2631
2632 for(int j = 0; j<tab->getNoOfColumns(); j++){
2633 cols.push_back((char*)tab2);
2634 cols.push_back(strdup(tab->getColumn(j)->getName()));
2635 }
2636 }
2637
2638 const Uint32 times = 10000000;
2639
2640 ndbout_c("%d tables and %d columns",
2641 NDBT_Tables::getNumTables(), cols.size()/2);
2642
2643 char ** tcols = cols.getBase();
2644
2645 srand((unsigned int)time(0));
2646 Uint32 size = cols.size() / 2;
2647 //char ** columns = &cols[0];
2648 Uint64 start = NdbTick_CurrentMillisecond();
2649 for(i = 0; i<(int)times; i++){
2650 int j = 2 * (rand() % size);
2651 const NdbDictionary::Table* tab = (const NdbDictionary::Table*)tcols[j];
2652 const char * col = tcols[j+1];
2653 const NdbDictionary::Column* column = tab->getColumn(col);
2654 f(column);
2655 }
2656 Uint64 stop = NdbTick_CurrentMillisecond();
2657 stop -= start;
2658
2659 Uint64 per = stop;
2660 per *= 1000;
2661 per /= times;
2662
2663 ndbout_c("%d random getColumn(name) in %lld ms -> %u us/get",
2664 times, stop, Uint32(per));
2665
2666 return NDBT_OK;
2667 }
2668
2669 int
runCreateLogfileGroup(NDBT_Context * ctx,NDBT_Step * step)2670 runCreateLogfileGroup(NDBT_Context* ctx, NDBT_Step* step){
2671 Ndb* pNdb = GETNDB(step);
2672 NdbDictionary::LogfileGroup lg;
2673 lg.setName("DEFAULT-LG");
2674 lg.setUndoBufferSize(8*1024*1024);
2675
2676 int oneDictParticipantFail = ctx->getProperty("OneDictParticipantFail",
2677 (Uint32)0);
2678 if (oneDictParticipantFail)
2679 {
2680 NdbRestarter restarter;
2681 const int anyDbNodeId = restarter.getNode(NdbRestarter::NS_RANDOM);
2682 restarter.insertErrorInNode(anyDbNodeId, 15001);
2683
2684 if ((pNdb->getDictionary()->createLogfileGroup(lg)) == 0)
2685 {
2686 g_err << "Error: Should have failed to create logfilegroup"
2687 << " due to error insertion" << endl;
2688
2689 // Leave the data nodes error-free before failing
2690 restarter.insertErrorInNode(anyDbNodeId, 0);
2691 return NDBT_FAILED;
2692 }
2693
2694 restarter.insertErrorInNode(anyDbNodeId, 0); // clear error
2695
2696 // Recreate LFG below
2697 }
2698
2699 int res = pNdb->getDictionary()->createLogfileGroup(lg);
2700 if(res != 0){
2701 g_err << "Failed to create logfilegroup:"
2702 << endl << pNdb->getDictionary()->getNdbError() << endl;
2703 return NDBT_FAILED;
2704 }
2705
2706 NdbDictionary::Undofile uf;
2707 uf.setPath("undofile01.dat");
2708 uf.setSize(5*1024*1024);
2709 uf.setLogfileGroup("DEFAULT-LG");
2710
2711 res = pNdb->getDictionary()->createUndofile(uf);
2712 if(res != 0){
2713 g_err << "Failed to create undofile:"
2714 << endl << pNdb->getDictionary()->getNdbError() << endl;
2715 return NDBT_FAILED;
2716 }
2717
2718 uf.setPath("undofile02.dat");
2719 uf.setSize(5*1024*1024);
2720 uf.setLogfileGroup("DEFAULT-LG");
2721
2722 res = pNdb->getDictionary()->createUndofile(uf);
2723 if(res != 0){
2724 g_err << "Failed to create undofile:"
2725 << endl << pNdb->getDictionary()->getNdbError() << endl;
2726 return NDBT_FAILED;
2727 }
2728
2729 return NDBT_OK;
2730 }
2731
2732 int
runCreateTablespace(NDBT_Context * ctx,NDBT_Step * step)2733 runCreateTablespace(NDBT_Context* ctx, NDBT_Step* step){
2734 Ndb* pNdb = GETNDB(step);
2735 NdbDictionary::Tablespace lg;
2736 lg.setName("DEFAULT-TS");
2737 lg.setExtentSize(1024*1024);
2738 lg.setDefaultLogfileGroup("DEFAULT-LG");
2739
2740 int oneDictParticipantFail = ctx->getProperty("OneDictParticipantFail",
2741 (Uint32)0);
2742
2743 if (oneDictParticipantFail)
2744 {
2745 NdbRestarter restarter;
2746 const int anyDbNodeId = restarter.getNode(NdbRestarter::NS_RANDOM);
2747
2748 restarter.insertErrorInNode(anyDbNodeId, 16001);
2749
2750 if ((pNdb->getDictionary()->createTablespace(lg)) == 0)
2751 {
2752 g_err << "Error: Should have failed to createTablespace"
2753 << " due to error insertion." << endl;
2754
2755 // Leave the data nodes error-free before failing
2756 restarter.insertErrorInNode(anyDbNodeId, 0);
2757 return NDBT_FAILED;
2758 }
2759
2760 restarter.insertErrorInNode(anyDbNodeId, 0); // clear error
2761
2762 // recreate TS below.
2763 }
2764
2765 int res = pNdb->getDictionary()->createTablespace(lg);
2766 if(res != 0){
2767 g_err << "Failed to create tablespace:"
2768 << endl << pNdb->getDictionary()->getNdbError() << endl;
2769 return NDBT_FAILED;
2770 }
2771
2772 NdbDictionary::Datafile uf;
2773 uf.setPath("datafile01.dat");
2774 uf.setSize(10*1024*1024);
2775 uf.setTablespace("DEFAULT-TS");
2776
2777 res = pNdb->getDictionary()->createDatafile(uf);
2778 if(res != 0){
2779 g_err << "Failed to create datafile:"
2780 << endl << pNdb->getDictionary()->getNdbError() << endl;
2781 return NDBT_FAILED;
2782 }
2783 return NDBT_OK;
2784 }
2785
2786 int
runDropTableSpaceLogFileGroup(NDBT_Context * ctx,NDBT_Step * step)2787 runDropTableSpaceLogFileGroup(NDBT_Context* ctx, NDBT_Step* step)
2788 {
2789 Ndb* pNdb = GETNDB(step);
2790
2791 if (pNdb->getDictionary()->dropDatafile(
2792 pNdb->getDictionary()->getDatafile(0, "datafile01.dat")) != 0)
2793 {
2794 g_err << "Error: Failed to drop datafile: "
2795 << pNdb->getDictionary()->getNdbError() << endl;
2796 return NDBT_FAILED;
2797 }
2798
2799 if (pNdb->getDictionary()->dropTablespace(pNdb->getDictionary()->
2800 getTablespace("DEFAULT-TS")) != 0)
2801 {
2802 g_err << "Error: Failed to drop tablespace: "
2803 << pNdb->getDictionary()->getNdbError() << endl;
2804 return NDBT_FAILED;
2805 }
2806
2807 if (pNdb->getDictionary()->dropLogfileGroup(
2808 pNdb->getDictionary()->getLogfileGroup("DEFAULT-LG")) != 0)
2809 {
2810 g_err << "Error: Drop of LFG Failed"
2811 << endl << pNdb->getDictionary()->getNdbError() << endl;
2812 return NDBT_FAILED;
2813 }
2814 return NDBT_OK;
2815 }
2816
2817 int
runCreateDiskTable(NDBT_Context * ctx,NDBT_Step * step)2818 runCreateDiskTable(NDBT_Context* ctx, NDBT_Step* step){
2819 Ndb* pNdb = GETNDB(step);
2820
2821 NdbDictionary::Table tab = *ctx->getTab();
2822 tab.setTablespaceName("DEFAULT-TS");
2823
2824 for(Uint32 i = 0; i<(Uint32)tab.getNoOfColumns(); i++)
2825 if(!tab.getColumn(i)->getPrimaryKey())
2826 tab.getColumn(i)->setStorageType(NdbDictionary::Column::StorageTypeDisk);
2827
2828 int res;
2829 res = pNdb->getDictionary()->createTable(tab);
2830 if(res != 0){
2831 g_err << "Failed to create table:"
2832 << endl << pNdb->getDictionary()->getNdbError() << endl;
2833 return NDBT_FAILED;
2834 }
2835
2836 return NDBT_OK;
2837 }
2838
getColumnMaxLength(const NdbDictionary::Column * c)2839 int getColumnMaxLength(const NdbDictionary::Column* c)
2840 {
2841 int length= c->getLength();
2842 if (c->getArrayType() == NDB_ARRAYTYPE_FIXED)
2843 {
2844 /* Not yet set - need to calculate from type etc. */
2845 DictTabInfo::Attribute attrDesc;
2846
2847 attrDesc.init();
2848 attrDesc.AttributeExtType= c->getType();
2849 attrDesc.AttributeExtLength= c->getLength();
2850 attrDesc.AttributeExtPrecision= c->getPrecision();
2851 attrDesc.AttributeExtScale= c->getScale();
2852
2853 if (!attrDesc.translateExtType())
2854 {
2855 return 0;
2856 }
2857
2858 if (attrDesc.AttributeSize == 0)
2859 {
2860 // bits...
2861 length = 4 * ((c->getLength() + 31) / 32);
2862 }
2863 else
2864 {
2865 length = ((1 << attrDesc.AttributeSize) * c->getLength()) >> 3;
2866 }
2867 }
2868
2869 return length;
2870 }
2871
2872 #include <NDBT_Tables.hpp>
2873
2874 #define SAFTY 300
2875
runFailAddFragment(NDBT_Context * ctx,NDBT_Step * step)2876 int runFailAddFragment(NDBT_Context* ctx, NDBT_Step* step){
2877 static int acclst[] = { 3001, 6200, 6202 };
2878 static int tuplst[] = { 4007, 4008, 4009, 4010, 4032, 4033, 4034 };
2879 static int tuxlst[] = { 12001, 12002, 12003, 12004,
2880 6201, 6203 };
2881 static unsigned acccnt = sizeof(acclst)/sizeof(acclst[0]);
2882 static unsigned tupcnt = sizeof(tuplst)/sizeof(tuplst[0]);
2883 static unsigned tuxcnt = sizeof(tuxlst)/sizeof(tuxlst[0]);
2884
2885 NdbRestarter restarter;
2886 int nodeId = restarter.getMasterNodeId();
2887 Ndb* pNdb = GETNDB(step);
2888 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
2889 NdbDictionary::Table tab(*ctx->getTab());
2890 tab.setFragmentType(NdbDictionary::Object::FragAllLarge);
2891
2892 int errNo = 0;
2893 #ifdef NDB_USE_GET_ENV
2894 char buf[100];
2895 if (NdbEnv_GetEnv("ERRNO", buf, sizeof(buf)))
2896 {
2897 errNo = atoi(buf);
2898 ndbout_c("Using errno: %u", errNo);
2899 }
2900 #endif
2901 const NdbDictionary::Table* origTab= ctx->getTab();
2902 HugoCalculator calc(*origTab);
2903
2904 // Add defaults to some columns
2905 for (int colNum= 0; colNum < tab.getNoOfColumns(); colNum++)
2906 {
2907 const NdbDictionary::Column* origCol= origTab->getColumn(colNum);
2908 NdbDictionary::Column* col= tab.getColumn(colNum);
2909 if (!origCol->getPrimaryKey())
2910 {
2911 if (myRandom48(2) == 0)
2912 {
2913 char defaultBuf[ NDB_MAX_TUPLE_SIZE ];
2914 Uint32 real_len;
2915 Uint32 updatesVal = myRandom48(1 << 16);
2916 const char* def= calc.calcValue(0, colNum, updatesVal,
2917 defaultBuf,
2918 getColumnMaxLength(origCol),
2919 &real_len);
2920 if (col->setDefaultValue(def, real_len) != 0)
2921 {
2922 ndbout_c("Error setting default value\n");
2923 return NDBT_FAILED;
2924 }
2925 NdbDictionary::NdbDataPrintFormat dpf;
2926 ndbout << "Set default for column " << origCol->getName()
2927 << " to ";
2928
2929 NdbDictionary::printFormattedValue(ndbout,
2930 dpf,
2931 col,
2932 def);
2933 ndbout << endl;
2934 }
2935 }
2936 }
2937
2938 // ordered index on first few columns
2939 NdbDictionary::Index idx("X");
2940 idx.setTable(tab.getName());
2941 idx.setType(NdbDictionary::Index::OrderedIndex);
2942 idx.setLogging(false);
2943 for (int cnt = 0, i_hate_broken_compilers = 0;
2944 cnt < 3 &&
2945 i_hate_broken_compilers < tab.getNoOfColumns();
2946 i_hate_broken_compilers++) {
2947 if (NdbSqlUtil::check_column_for_ordered_index
2948 (tab.getColumn(i_hate_broken_compilers)->getType(), 0) == 0 &&
2949 tab.getColumn(i_hate_broken_compilers)->getStorageType() !=
2950 NdbDictionary::Column::StorageTypeDisk)
2951 {
2952 idx.addColumn(*tab.getColumn(i_hate_broken_compilers));
2953 cnt++;
2954 }
2955 }
2956
2957 for (Uint32 i = 0; i<(Uint32)tab.getNoOfColumns(); i++)
2958 {
2959 if (tab.getColumn(i)->getStorageType() ==
2960 NdbDictionary::Column::StorageTypeDisk)
2961 {
2962 NDBT_Tables::create_default_tablespace(pNdb);
2963 break;
2964 }
2965 }
2966
2967 const int loops = ctx->getNumLoops();
2968 int result = NDBT_OK;
2969 (void)pDic->dropTable(tab.getName());
2970
2971 int dump1 = DumpStateOrd::SchemaResourceSnapshot;
2972 int dump2 = DumpStateOrd::SchemaResourceCheckLeak;
2973
2974 for (int l = 0; l < loops; l++) {
2975 for (unsigned i0 = 0; i0 < acccnt; i0++) {
2976 unsigned j = (l == 0 ? i0 : myRandom48(acccnt));
2977 int errval = acclst[j];
2978 if (errNo != 0 && errNo != errval)
2979 continue;
2980 g_err << "insert error node=" << nodeId << " value=" << errval << endl;
2981 CHECK(restarter.dumpStateAllNodes(&dump1, 1) == 0);
2982 CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
2983 "failed to set error insert");
2984 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
2985 CHECK2(pDic->createTable(tab) != 0,
2986 "failed to fail after error insert " << errval);
2987 CHECK2(restarter.insertErrorInNode(nodeId, 0) == 0,
2988 "failed to clean error insert value");
2989 CHECK(restarter.dumpStateAllNodes(&dump2, 1) == 0);
2990 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
2991 CHECK2(pDic->createTable(tab) == 0,
2992 pDic->getNdbError());
2993 CHECK2(pDic->dropTable(tab.getName()) == 0,
2994 pDic->getNdbError());
2995 }
2996 for (unsigned i1 = 0; i1 < tupcnt; i1++) {
2997 unsigned j = (l == 0 ? i1 : myRandom48(tupcnt));
2998 int errval = tuplst[j];
2999 if (errNo != 0 && errNo != errval)
3000 continue;
3001 g_err << "insert error node=" << nodeId << " value=" << errval << endl;
3002 CHECK(restarter.dumpStateAllNodes(&dump1, 1) == 0);
3003 CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
3004 "failed to set error insert");
3005 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
3006 CHECK2(pDic->createTable(tab) != 0,
3007 "failed to fail after error insert " << errval);
3008 CHECK2(restarter.insertErrorInNode(nodeId, 0) == 0,
3009 "failed to clean error insert value");
3010 CHECK(restarter.dumpStateAllNodes(&dump2, 1) == 0);
3011 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
3012 CHECK2(pDic->createTable(tab) == 0,
3013 pDic->getNdbError());
3014 CHECK2(pDic->dropTable(tab.getName()) == 0,
3015 pDic->getNdbError());
3016 }
3017 for (unsigned i2 = 0; i2 < tuxcnt; i2++) {
3018 unsigned j = (l == 0 ? i2 : myRandom48(tuxcnt));
3019 int errval = tuxlst[j];
3020 if (errNo != 0 && errNo != errval)
3021 continue;
3022 CHECK2(pDic->createTable(tab) == 0,
3023 pDic->getNdbError());
3024
3025 g_err << "insert error node=" << nodeId << " value=" << errval << endl;
3026 CHECK(restarter.dumpStateAllNodes(&dump1, 1) == 0);
3027 CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
3028 "failed to set error insert");
3029 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
3030
3031 CHECK2(pDic->createIndex(idx) != 0,
3032 "failed to fail after error insert " << errval);
3033 CHECK2(restarter.insertErrorInNode(nodeId, 0) == 0,
3034 "failed to clean error insert value");
3035 CHECK(restarter.dumpStateAllNodes(&dump2, 1) == 0);
3036 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
3037 CHECK2(pDic->createIndex(idx) == 0,
3038 pDic->getNdbError());
3039 CHECK2(pDic->dropTable(tab.getName()) == 0,
3040 pDic->getNdbError());
3041 }
3042 }
3043 end:
3044 return result;
3045 }
3046
3047 // NFNR
3048
3049 // Restarter controls dict ops : 1-run 2-pause 3-stop
3050 // synced by polling...
3051
3052 static bool
send_dict_ops_cmd(NDBT_Context * ctx,Uint32 cmd)3053 send_dict_ops_cmd(NDBT_Context* ctx, Uint32 cmd)
3054 {
3055 ctx->setProperty("DictOps_CMD", cmd);
3056 while (1) {
3057 if (ctx->isTestStopped())
3058 return false;
3059 if (ctx->getProperty("DictOps_ACK") == cmd)
3060 break;
3061 NdbSleep_MilliSleep(100);
3062 }
3063 return true;
3064 }
3065
3066 static bool
recv_dict_ops_run(NDBT_Context * ctx)3067 recv_dict_ops_run(NDBT_Context* ctx)
3068 {
3069 while (1) {
3070 if (ctx->isTestStopped())
3071 return false;
3072 Uint32 cmd = ctx->getProperty("DictOps_CMD");
3073 ctx->setProperty("DictOps_ACK", cmd);
3074 if (cmd == 1)
3075 break;
3076 if (cmd == 3)
3077 return false;
3078 NdbSleep_MilliSleep(100);
3079 }
3080 return true;
3081 }
3082
3083 int
runRestarts(NDBT_Context * ctx,NDBT_Step * step)3084 runRestarts(NDBT_Context* ctx, NDBT_Step* step)
3085 {
3086 static int errlst_master[] = { // non-crashing
3087 7175, // send one fake START_PERMREF
3088 0
3089 };
3090 static int errlst_node[] = {
3091 7174, // crash before sending DICT_LOCK_REQ
3092 7121, // crash at receive START_PERMCONF
3093 0
3094 };
3095 const uint errcnt_master = sizeof(errlst_master)/sizeof(errlst_master[0]);
3096 const uint errcnt_node = sizeof(errlst_node)/sizeof(errlst_node[0]);
3097
3098 myRandom48Init((long)NdbTick_CurrentMillisecond());
3099 NdbRestarter restarter;
3100 int result = NDBT_OK;
3101 const int loops = ctx->getNumLoops();
3102
3103 for (int l = 0; l < loops && result == NDBT_OK; l++) {
3104 g_info << "1: === loop " << l << " ===" << endl;
3105
3106 // assuming 2-way replicated
3107
3108 int numnodes = restarter.getNumDbNodes();
3109 CHECK(numnodes >= 1);
3110 if (numnodes == 1)
3111 break;
3112
3113 int masterNodeId = restarter.getMasterNodeId();
3114 CHECK(masterNodeId != -1);
3115
3116 // for more complex cases need more restarter support methods
3117
3118 int nodeIdList[2] = { 0, 0 };
3119 int nodeIdCnt = 0;
3120
3121 if (numnodes >= 2) {
3122 int rand = myRandom48(numnodes);
3123 int nodeId = restarter.getRandomNotMasterNodeId(rand);
3124 CHECK(nodeId != -1);
3125 nodeIdList[nodeIdCnt++] = nodeId;
3126 }
3127
3128 if (numnodes >= 4 && (myRandom48(2) == 0) && (restarter.getNumNodeGroups() > 1)) {
3129 int rand = myRandom48(numnodes);
3130 int nodeId = restarter.getRandomNodeOtherNodeGroup(nodeIdList[0], rand);
3131 CHECK(nodeId != -1);
3132 if (nodeId != masterNodeId)
3133 nodeIdList[nodeIdCnt++] = nodeId;
3134 }
3135
3136 g_info << "1: master=" << masterNodeId << " nodes=" << nodeIdList[0] << "," << nodeIdList[1] << endl;
3137
3138 const uint timeout = 60; //secs for node wait
3139 const unsigned maxsleep = 2000; //ms
3140
3141 bool NF_ops = ctx->getProperty("Restart_NF_ops");
3142 uint NF_type = ctx->getProperty("Restart_NF_type");
3143 bool NR_ops = ctx->getProperty("Restart_NR_ops");
3144 bool NR_error = ctx->getProperty("Restart_NR_error");
3145
3146 g_info << "1: " << (NF_ops ? "run" : "pause") << " dict ops" << endl;
3147 if (! send_dict_ops_cmd(ctx, NF_ops ? 1 : 2))
3148 break;
3149 NdbSleep_MilliSleep(myRandom48(maxsleep));
3150
3151 {
3152 for (int i = 0; i < nodeIdCnt; i++) {
3153 int nodeId = nodeIdList[i];
3154
3155 bool nostart = true;
3156 bool abort = NF_type == 0 ? myRandom48(2) : (NF_type == 2);
3157 bool initial = myRandom48(2);
3158
3159 char flags[40];
3160 strcpy(flags, "flags: nostart");
3161 if (abort)
3162 strcat(flags, ",abort");
3163 if (initial)
3164 strcat(flags, ",initial");
3165
3166 g_info << "1: restart " << nodeId << " " << flags << endl;
3167 CHECK(restarter.restartOneDbNode(nodeId, initial, nostart, abort) == 0);
3168 }
3169 }
3170
3171 g_info << "1: wait for nostart" << endl;
3172 CHECK(restarter.waitNodesNoStart(nodeIdList, nodeIdCnt, timeout) == 0);
3173 NdbSleep_MilliSleep(myRandom48(maxsleep));
3174
3175 int err_master = 0;
3176 int err_node[2] = { 0, 0 };
3177
3178 if (NR_error) {
3179 err_master = errlst_master[l % errcnt_master];
3180
3181 // limitation: cannot have 2 node restarts and crash_insert
3182 // one node may die for real (NF during startup)
3183
3184 for (int i = 0; i < nodeIdCnt && nodeIdCnt == 1; i++) {
3185 err_node[i] = errlst_node[l % errcnt_node];
3186 }
3187 }
3188
3189 g_info << "1: " << (NR_ops ? "run" : "pause") << " dict ops" << endl;
3190 if (! send_dict_ops_cmd(ctx, NR_ops ? 1 : 2))
3191 break;
3192 NdbSleep_MilliSleep(myRandom48(maxsleep));
3193
3194 g_info << "1: start nodes" << endl;
3195 CHECK(restarter.startNodes(nodeIdList, nodeIdCnt) == 0);
3196
3197 if (NR_error) {
3198 {
3199 int err = err_master;
3200 if (err != 0) {
3201 g_info << "1: insert master error " << err << endl;
3202 CHECK(restarter.insertErrorInNode(masterNodeId, err) == 0);
3203 }
3204 }
3205
3206 for (int i = 0; i < nodeIdCnt; i++) {
3207 int nodeId = nodeIdList[i];
3208
3209 int err = err_node[i];
3210 if (err != 0) {
3211 g_info << "1: insert node " << nodeId << " error " << err << endl;
3212 CHECK(restarter.insertErrorInNode(nodeId, err) == 0);
3213 }
3214 }
3215 }
3216 NdbSleep_MilliSleep(myRandom48(maxsleep));
3217
3218 g_info << "1: wait cluster started" << endl;
3219 CHECK(restarter.waitClusterStarted(timeout) == 0);
3220 CHK_NDB_READY(GETNDB(step));
3221 NdbSleep_MilliSleep(myRandom48(maxsleep));
3222
3223 g_info << "1: restart done" << endl;
3224 }
3225
3226 g_info << "1: stop dict ops" << endl;
3227 send_dict_ops_cmd(ctx, 3);
3228
3229 return result;
3230 }
3231
3232 int
runDictOps(NDBT_Context * ctx,NDBT_Step * step)3233 runDictOps(NDBT_Context* ctx, NDBT_Step* step)
3234 {
3235 myRandom48Init((long)NdbTick_CurrentMillisecond());
3236 int result = NDBT_OK;
3237
3238 for (int l = 0; result == NDBT_OK; l++) {
3239 if (! recv_dict_ops_run(ctx))
3240 break;
3241
3242 g_info << "2: === loop " << l << " ===" << endl;
3243
3244 Ndb* pNdb = GETNDB(step);
3245 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
3246 const NdbDictionary::Table* pTab = ctx->getTab();
3247 //const char* tabName = pTab->getName(); //XXX what goes on?
3248 char tabName[40];
3249 strcpy(tabName, pTab->getName());
3250
3251 const unsigned long maxsleep = 100; //ms
3252
3253 g_info << "2: create table" << endl;
3254 {
3255 uint count = 0;
3256 try_create:
3257 count++;
3258 if (pDic->createTable(*pTab) != 0) {
3259 const NdbError err = pDic->getNdbError();
3260 if (count == 1)
3261 g_err << "2: " << tabName << ": create failed: " << err << endl;
3262 if (err.code != 711) {
3263 result = NDBT_FAILED;
3264 break;
3265 }
3266 NdbSleep_MilliSleep(myRandom48(maxsleep));
3267 goto try_create;
3268 }
3269 }
3270 NdbSleep_MilliSleep(myRandom48(maxsleep));
3271
3272 g_info << "2: verify create" << endl;
3273 const NdbDictionary::Table* pTab2 = pDic->getTable(tabName);
3274 if (pTab2 == NULL) {
3275 const NdbError err = pDic->getNdbError();
3276 g_err << "2: " << tabName << ": verify create: " << err << endl;
3277 result = NDBT_FAILED;
3278 break;
3279 }
3280 NdbSleep_MilliSleep(myRandom48(maxsleep));
3281
3282 // replace by the Retrieved table
3283 pTab = pTab2;
3284
3285 // create indexes
3286 const char** indlist = NDBT_Tables::getIndexes(tabName);
3287 uint indnum = 0;
3288 while (indlist != 0 && *indlist != 0) {
3289 uint count = 0;
3290 try_create_index:
3291 count++;
3292 if (count == 1)
3293 g_info << "2: create index " << indnum << " " << *indlist << endl;
3294 NdbDictionary::Index ind;
3295 char indName[200];
3296 sprintf(indName, "%s_X%u", tabName, indnum);
3297 ind.setName(indName);
3298 ind.setTable(tabName);
3299 if (strcmp(*indlist, "UNIQUE") == 0) {
3300 ind.setType(NdbDictionary::Index::UniqueHashIndex);
3301 ind.setLogging(pTab->getLogging());
3302 } else if (strcmp(*indlist, "ORDERED") == 0) {
3303 ind.setType(NdbDictionary::Index::OrderedIndex);
3304 ind.setLogging(false);
3305 } else {
3306 require(false);
3307 }
3308 const char** indtemp = indlist;
3309 while (*++indtemp != 0) {
3310 ind.addColumn(*indtemp);
3311 }
3312 if (pDic->createIndex(ind) != 0) {
3313 const NdbError err = pDic->getNdbError();
3314 if (count == 1)
3315 g_err << "2: " << indName << ": create failed: " << err << endl;
3316 if (err.code != 711) {
3317 result = NDBT_FAILED;
3318 break;
3319 }
3320 NdbSleep_MilliSleep(myRandom48(maxsleep));
3321 goto try_create_index;
3322 }
3323 indlist = ++indtemp;
3324 indnum++;
3325 }
3326 if (result == NDBT_FAILED)
3327 break;
3328
3329 uint indcount = indnum;
3330
3331 int records = myRandom48(ctx->getNumRecords());
3332 g_info << "2: load " << records << " records" << endl;
3333 HugoTransactions hugoTrans(*pTab);
3334 if (hugoTrans.loadTable(pNdb, records) != 0) {
3335 // XXX get error code from hugo
3336 g_err << "2: " << tabName << ": load failed" << endl;
3337 result = NDBT_FAILED;
3338 break;
3339 }
3340 NdbSleep_MilliSleep(myRandom48(maxsleep));
3341
3342 // drop indexes
3343 indnum = 0;
3344 while (indnum < indcount) {
3345 uint count = 0;
3346 try_drop_index:
3347 count++;
3348 if (count == 1)
3349 g_info << "2: drop index " << indnum << endl;
3350 char indName[200];
3351 sprintf(indName, "%s_X%u", tabName, indnum);
3352 if (pDic->dropIndex(indName, tabName) != 0) {
3353 const NdbError err = pDic->getNdbError();
3354 if (count == 1)
3355 g_err << "2: " << indName << ": drop failed: " << err << endl;
3356 if (err.code != 711) {
3357 result = NDBT_FAILED;
3358 break;
3359 }
3360 NdbSleep_MilliSleep(myRandom48(maxsleep));
3361 goto try_drop_index;
3362 }
3363 indnum++;
3364 }
3365 if (result == NDBT_FAILED)
3366 break;
3367
3368 g_info << "2: drop" << endl;
3369 {
3370 uint count = 0;
3371 try_drop:
3372 count++;
3373 if (pDic->dropTable(tabName) != 0) {
3374 const NdbError err = pDic->getNdbError();
3375 if (count == 1)
3376 g_err << "2: " << tabName << ": drop failed: " << err << endl;
3377 if (err.code != 711) {
3378 result = NDBT_FAILED;
3379 break;
3380 }
3381 NdbSleep_MilliSleep(myRandom48(maxsleep));
3382 goto try_drop;
3383 }
3384 }
3385 NdbSleep_MilliSleep(myRandom48(maxsleep));
3386
3387 g_info << "2: verify drop" << endl;
3388 const NdbDictionary::Table* pTab3 = pDic->getTable(tabName);
3389 if (pTab3 != NULL) {
3390 g_err << "2: " << tabName << ": verify drop: table exists" << endl;
3391 result = NDBT_FAILED;
3392 break;
3393 }
3394 if (pDic->getNdbError().code != 709 &&
3395 pDic->getNdbError().code != 723) {
3396 const NdbError err = pDic->getNdbError();
3397 g_err << "2: " << tabName << ": verify drop: " << err << endl;
3398 result = NDBT_FAILED;
3399 break;
3400 }
3401 NdbSleep_MilliSleep(myRandom48(maxsleep));
3402 }
3403
3404 return result;
3405 }
3406
3407 int
runBug21755(NDBT_Context * ctx,NDBT_Step * step)3408 runBug21755(NDBT_Context* ctx, NDBT_Step* step)
3409 {
3410 char buf[256];
3411 NdbRestarter res;
3412 NdbDictionary::Table pTab0 = * ctx->getTab();
3413 NdbDictionary::Table pTab1 = pTab0;
3414
3415 if (res.getNumDbNodes() < 2)
3416 return NDBT_OK;
3417
3418 Ndb* pNdb = GETNDB(step);
3419 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
3420
3421 if (pDic->createTable(pTab0))
3422 {
3423 ndbout << pDic->getNdbError() << endl;
3424 return NDBT_FAILED;
3425 }
3426
3427 NdbDictionary::Index idx0;
3428 BaseString::snprintf(buf, sizeof(buf), "%s-idx", pTab0.getName());
3429 idx0.setName(buf);
3430 idx0.setType(NdbDictionary::Index::OrderedIndex);
3431 idx0.setTable(pTab0.getName());
3432 idx0.setStoredIndex(false);
3433 for (Uint32 i = 0; i<(Uint32)pTab0.getNoOfColumns(); i++)
3434 {
3435 const NdbDictionary::Column * col = pTab0.getColumn(i);
3436 if(col->getPrimaryKey()){
3437 idx0.addIndexColumn(col->getName());
3438 }
3439 }
3440
3441 if (pDic->createIndex(idx0))
3442 {
3443 ndbout << pDic->getNdbError() << endl;
3444 return NDBT_FAILED;
3445 }
3446
3447 BaseString::snprintf(buf, sizeof(buf), "%s-2", pTab1.getName());
3448 pTab1.setName(buf);
3449
3450 if (pDic->createTable(pTab1))
3451 {
3452 ndbout << pDic->getNdbError() << endl;
3453 return NDBT_FAILED;
3454 }
3455
3456 {
3457 const NdbDictionary::Table* pTab = pDic->getTable(pTab0.getName());
3458 if (pTab == NULL) {
3459 g_err << "Table 'pTab0': " << pTab0.getName()
3460 << ", not found on line " << __LINE__
3461 <<", error: " << pDic->getNdbError()
3462 << endl;
3463 return NDBT_FAILED;
3464 }
3465 HugoTransactions t0 (*pTab);
3466 t0.loadTable(pNdb, 1000);
3467 }
3468
3469 {
3470 const NdbDictionary::Table* pTab = pDic->getTable(pTab1.getName());
3471 if (pTab == NULL) {
3472 g_err << "Table 'pTab1': " << pTab1.getName()
3473 << ", not found on line " << __LINE__
3474 <<", error: " << pDic->getNdbError()
3475 << endl;
3476 return NDBT_FAILED;
3477 }
3478 HugoTransactions t1 (*pTab);
3479 t1.loadTable(pNdb, 1000);
3480 }
3481
3482 int node = res.getRandomNotMasterNodeId(rand());
3483 res.restartOneDbNode(node, false, true, true);
3484
3485 if (pDic->dropTable(pTab1.getName()))
3486 {
3487 ndbout << pDic->getNdbError() << endl;
3488 return NDBT_FAILED;
3489 }
3490
3491 BaseString::snprintf(buf, sizeof(buf), "%s-idx2", pTab0.getName());
3492 idx0.setName(buf);
3493 if (pDic->createIndex(idx0))
3494 {
3495 ndbout << pDic->getNdbError() << endl;
3496 return NDBT_FAILED;
3497 }
3498
3499 res.waitNodesNoStart(&node, 1);
3500 res.startNodes(&node, 1);
3501
3502 if (res.waitClusterStarted())
3503 {
3504 return NDBT_FAILED;
3505 }
3506 CHK_NDB_READY(pNdb);
3507
3508 if (pDic->dropTable(pTab0.getName()))
3509 {
3510 ndbout << pDic->getNdbError() << endl;
3511 return NDBT_FAILED;
3512 }
3513
3514 return NDBT_OK;
3515 }
3516
3517 static
3518 int
create_tablespace(NdbDictionary::Dictionary * pDict,const char * lgname,const char * tsname,const char * dfname)3519 create_tablespace(NdbDictionary::Dictionary* pDict,
3520 const char * lgname,
3521 const char * tsname,
3522 const char * dfname)
3523 {
3524 NdbDictionary::Tablespace ts;
3525 ts.setName(tsname);
3526 ts.setExtentSize(1024*1024);
3527 ts.setDefaultLogfileGroup(lgname);
3528
3529 if(pDict->createTablespace(ts) != 0)
3530 {
3531 g_err << "Failed to create tablespace:"
3532 << endl << pDict->getNdbError() << endl;
3533 return NDBT_FAILED;
3534 }
3535
3536 NdbDictionary::Datafile df;
3537 df.setPath(dfname);
3538 df.setSize(1*1024*1024);
3539 df.setTablespace(tsname);
3540
3541 if(pDict->createDatafile(df) != 0)
3542 {
3543 g_err << "Failed to create datafile:"
3544 << endl << pDict->getNdbError() << endl;
3545 return NDBT_FAILED;
3546 }
3547 return 0;
3548 }
3549
3550 int
runBug24631(NDBT_Context * ctx,NDBT_Step * step)3551 runBug24631(NDBT_Context* ctx, NDBT_Step* step)
3552 {
3553 char tsname[256];
3554 char dfname[256];
3555 char lgname[256];
3556 char ufname[256];
3557 NdbRestarter res;
3558
3559 if (res.getNumDbNodes() < 2)
3560 return NDBT_OK;
3561
3562 Ndb* pNdb = GETNDB(step);
3563 NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
3564
3565 NdbDictionary::Dictionary::List list;
3566 if (pDict->listObjects(list) == -1)
3567 return NDBT_FAILED;
3568
3569 const char * lgfound = 0;
3570
3571 for (Uint32 i = 0; i<list.count; i++)
3572 {
3573 switch(list.elements[i].type){
3574 case NdbDictionary::Object::LogfileGroup:
3575 lgfound = list.elements[i].name;
3576 break;
3577 default:
3578 break;
3579 }
3580 if (lgfound)
3581 break;
3582 }
3583
3584 if (lgfound == 0)
3585 {
3586 BaseString::snprintf(lgname, sizeof(lgname), "LG-%u", rand());
3587 NdbDictionary::LogfileGroup lg;
3588
3589 lg.setName(lgname);
3590 lg.setUndoBufferSize(8*1024*1024);
3591 if(pDict->createLogfileGroup(lg) != 0)
3592 {
3593 g_err << "Failed to create logfilegroup:"
3594 << endl << pDict->getNdbError() << endl;
3595 return NDBT_FAILED;
3596 }
3597
3598 NdbDictionary::Undofile uf;
3599 BaseString::snprintf(ufname, sizeof(ufname), "%s-%u", lgname, rand());
3600 uf.setPath(ufname);
3601 uf.setSize(2*1024*1024);
3602 uf.setLogfileGroup(lgname);
3603
3604 if(pDict->createUndofile(uf) != 0)
3605 {
3606 g_err << "Failed to create undofile:"
3607 << endl << pDict->getNdbError() << endl;
3608 return NDBT_FAILED;
3609 }
3610 }
3611 else
3612 {
3613 BaseString::snprintf(lgname, sizeof(lgname), "%s", lgfound);
3614 }
3615
3616 BaseString::snprintf(tsname, sizeof(tsname), "TS-%u", rand());
3617 BaseString::snprintf(dfname, sizeof(dfname), "%s-%u.dat", tsname, rand());
3618
3619 if (create_tablespace(pDict, lgname, tsname, dfname))
3620 return NDBT_FAILED;
3621
3622
3623 int node = res.getRandomNotMasterNodeId(rand());
3624 res.restartOneDbNode(node, false, true, true);
3625 NdbSleep_SecSleep(3);
3626
3627 if (pDict->dropDatafile(pDict->getDatafile(0, dfname)) != 0)
3628 {
3629 g_err << "Failed to drop datafile: " << pDict->getNdbError() << endl;
3630 return NDBT_FAILED;
3631 }
3632
3633 if (pDict->dropTablespace(pDict->getTablespace(tsname)) != 0)
3634 {
3635 g_err << "Failed to drop tablespace: " << pDict->getNdbError() << endl;
3636 return NDBT_FAILED;
3637 }
3638
3639 if (res.waitNodesNoStart(&node, 1))
3640 return NDBT_FAILED;
3641
3642 res.startNodes(&node, 1);
3643 if (res.waitClusterStarted())
3644 return NDBT_FAILED;
3645 CHK_NDB_READY(pNdb);
3646
3647 if (create_tablespace(pDict, lgname, tsname, dfname))
3648 return NDBT_FAILED;
3649
3650 if (pDict->dropDatafile(pDict->getDatafile(0, dfname)) != 0)
3651 {
3652 g_err << "Failed to drop datafile: " << pDict->getNdbError() << endl;
3653 return NDBT_FAILED;
3654 }
3655
3656 if (pDict->dropTablespace(pDict->getTablespace(tsname)) != 0)
3657 {
3658 g_err << "Failed to drop tablespace: " << pDict->getNdbError() << endl;
3659 return NDBT_FAILED;
3660 }
3661
3662 if (lgfound == 0)
3663 {
3664 if (pDict->dropLogfileGroup(pDict->getLogfileGroup(lgname)) != 0)
3665 return NDBT_FAILED;
3666 }
3667
3668 return NDBT_OK;
3669 }
3670
3671 int
runBug29186(NDBT_Context * ctx,NDBT_Step * step)3672 runBug29186(NDBT_Context* ctx, NDBT_Step* step)
3673 {
3674 int lgError = 15000;
3675 int tsError = 16000;
3676 char lgname[256];
3677 char ufname[256];
3678 char tsname[256];
3679 char dfname[256];
3680
3681 NdbRestarter restarter;
3682
3683 if (restarter.getNumDbNodes() < 2){
3684 ctx->stopTest();
3685 return NDBT_OK;
3686 }
3687
3688 Ndb* pNdb = GETNDB(step);
3689 NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
3690 NdbDictionary::Dictionary::List list;
3691
3692 if (pDict->listObjects(list) == -1)
3693 return NDBT_FAILED;
3694
3695 // 1.create logfile group
3696 const char * lgfound = 0;
3697
3698 for (Uint32 i = 0; i<list.count; i++)
3699 {
3700 switch(list.elements[i].type){
3701 case NdbDictionary::Object::LogfileGroup:
3702 lgfound = list.elements[i].name;
3703 break;
3704 default:
3705 break;
3706 }
3707 if (lgfound)
3708 break;
3709 }
3710
3711 if (lgfound == 0)
3712 {
3713 BaseString::snprintf(lgname, sizeof(lgname), "LG-%u", rand());
3714 NdbDictionary::LogfileGroup lg;
3715
3716 lg.setName(lgname);
3717 lg.setUndoBufferSize(8*1024*1024);
3718 if(pDict->createLogfileGroup(lg) != 0)
3719 {
3720 g_err << "Failed to create logfilegroup:"
3721 << endl << pDict->getNdbError() << endl;
3722 return NDBT_FAILED;
3723 }
3724 }
3725 else
3726 {
3727 BaseString::snprintf(lgname, sizeof(lgname), "%s", lgfound);
3728 }
3729
3730 if(restarter.waitClusterStarted(60)){
3731 g_err << "waitClusterStarted failed"<< endl;
3732 return NDBT_FAILED;
3733 }
3734 CHK_NDB_READY(pNdb);
3735
3736 if(restarter.insertErrorInAllNodes(lgError) != 0){
3737 g_err << "failed to set error insert"<< endl;
3738 return NDBT_FAILED;
3739 }
3740
3741 g_info << "error inserted" << endl;
3742 g_info << "waiting some before add log file" << endl;
3743 g_info << "starting create log file group" << endl;
3744
3745 NdbDictionary::Undofile uf;
3746 BaseString::snprintf(ufname, sizeof(ufname), "%s-%u", lgname, rand());
3747 uf.setPath(ufname);
3748 uf.setSize(2*1024*1024);
3749 uf.setLogfileGroup(lgname);
3750
3751 if(pDict->createUndofile(uf) == 0)
3752 {
3753 g_err << "Create log file group should fail on error_insertion " << lgError << endl;
3754 return NDBT_FAILED;
3755 }
3756
3757 //clear lg error
3758 if(restarter.insertErrorInAllNodes(15099) != 0){
3759 g_err << "failed to set error insert"<< endl;
3760 return NDBT_FAILED;
3761 }
3762 NdbSleep_SecSleep(5);
3763
3764 //lg error has been cleared, so we can add undo file
3765 if(pDict->createUndofile(uf) != 0)
3766 {
3767 g_err << "Failed to create undofile:"
3768 << endl << pDict->getNdbError() << endl;
3769 return NDBT_FAILED;
3770 }
3771
3772 if(restarter.waitClusterStarted(60)){
3773 g_err << "waitClusterStarted failed"<< endl;
3774 return NDBT_FAILED;
3775 }
3776 CHK_NDB_READY(pNdb);
3777
3778 if(restarter.insertErrorInAllNodes(tsError) != 0){
3779 g_err << "failed to set error insert"<< endl;
3780 return NDBT_FAILED;
3781 }
3782 g_info << "error inserted" << endl;
3783 g_info << "waiting some before create table space" << endl;
3784 g_info << "starting create table space" << endl;
3785
3786 //r = runCreateTablespace(ctx, step);
3787 BaseString::snprintf(tsname, sizeof(tsname), "TS-%u", rand());
3788 BaseString::snprintf(dfname, sizeof(dfname), "%s-%u-1.dat", tsname, rand());
3789
3790 NdbDictionary::Tablespace ts;
3791 ts.setName(tsname);
3792 ts.setExtentSize(1024*1024);
3793 ts.setDefaultLogfileGroup(lgname);
3794
3795 if(pDict->createTablespace(ts) != 0)
3796 {
3797 g_err << "Failed to create tablespace:"
3798 << endl << pDict->getNdbError() << endl;
3799 return NDBT_FAILED;
3800 }
3801
3802 NdbDictionary::Datafile df;
3803 df.setPath(dfname);
3804 df.setSize(1*1024*1024);
3805 df.setTablespace(tsname);
3806
3807 if(pDict->createDatafile(df) == 0)
3808 {
3809 g_err << "Create table space should fail on error_insertion " << tsError << endl;
3810 return NDBT_FAILED;
3811 }
3812 //Clear the inserted error
3813 if(restarter.insertErrorInAllNodes(16099) != 0){
3814 g_err << "failed to set error insert"<< endl;
3815 return NDBT_FAILED;
3816 }
3817 NdbSleep_SecSleep(5);
3818
3819 if (pDict->dropTablespace(pDict->getTablespace(tsname)) != 0)
3820 {
3821 g_err << "Failed to drop tablespace: " << pDict->getNdbError() << endl;
3822 return NDBT_FAILED;
3823 }
3824
3825 if (lgfound == 0)
3826 {
3827 if (pDict->dropLogfileGroup(pDict->getLogfileGroup(lgname)) != 0)
3828 return NDBT_FAILED;
3829 }
3830
3831 return NDBT_OK;
3832 }
3833
3834 struct RandSchemaOp
3835 {
RandSchemaOpRandSchemaOp3836 RandSchemaOp(unsigned * randseed = 0) {
3837 if (randseed == 0)
3838 {
3839 ownseed = (unsigned)NdbTick_CurrentMillisecond();
3840 seed = &ownseed;
3841 }
3842 else
3843 {
3844 seed = randseed;
3845 }
3846 }
3847 struct Obj
3848 {
3849 BaseString m_name;
3850 Uint32 m_type;
3851 struct Obj* m_parent;
3852 Vector<Obj*> m_dependant;
3853 };
3854
3855 Vector<Obj*> m_objects;
3856
3857 int schema_op(Ndb*);
3858 int validate(Ndb*);
3859 int cleanup(Ndb*);
3860
3861 Obj* get_obj(Uint32 mask);
3862 int create_table(Ndb*);
3863 int create_index(Ndb*, Obj*);
3864 int alter_table(Ndb*, Obj*);
3865 int drop_obj(Ndb*, Obj*);
3866
3867 void remove_obj(Obj*);
3868 private:
3869 unsigned * seed;
3870 unsigned ownseed;
3871 };
3872
3873 template class Vector<RandSchemaOp::Obj*>;
3874
3875 int
schema_op(Ndb * ndb)3876 RandSchemaOp::schema_op(Ndb* ndb)
3877 {
3878 struct Obj* obj = 0;
3879 Uint32 type = 0;
3880 loop:
3881 switch(ndb_rand_r(seed) % 5){
3882 case 0:
3883 return create_table(ndb);
3884 case 1:
3885 if ((obj = get_obj(1 << NdbDictionary::Object::UserTable)) == 0)
3886 goto loop;
3887 return create_index(ndb, obj);
3888 case 2:
3889 type = (1 << NdbDictionary::Object::UserTable);
3890 goto drop_object;
3891 case 3:
3892 type =
3893 (1 << NdbDictionary::Object::UniqueHashIndex) |
3894 (1 << NdbDictionary::Object::OrderedIndex);
3895 goto drop_object;
3896 case 4:
3897 if ((obj = get_obj(1 << NdbDictionary::Object::UserTable)) == 0)
3898 goto loop;
3899 return alter_table(ndb, obj);
3900 default:
3901 goto loop;
3902 }
3903
3904 drop_object:
3905 if ((obj = get_obj(type)) == 0)
3906 goto loop;
3907 return drop_obj(ndb, obj);
3908 }
3909
3910 RandSchemaOp::Obj*
get_obj(Uint32 mask)3911 RandSchemaOp::get_obj(Uint32 mask)
3912 {
3913 Vector<Obj*> tmp;
3914 for (Uint32 i = 0; i<m_objects.size(); i++)
3915 {
3916 if ((1 << m_objects[i]->m_type) & mask)
3917 tmp.push_back(m_objects[i]);
3918 }
3919
3920 if (tmp.size())
3921 {
3922 return tmp[ndb_rand_r(seed)%tmp.size()];
3923 }
3924 return 0;
3925 }
3926
3927 int
create_table(Ndb * ndb)3928 RandSchemaOp::create_table(Ndb* ndb)
3929 {
3930 int numTables = NDBT_Tables::getNumTables();
3931 int num = ndb_rand_r(seed) % numTables;
3932 NdbDictionary::Table pTab = * NDBT_Tables::getTable(num);
3933
3934 NdbDictionary::Dictionary* pDict = ndb->getDictionary();
3935 pTab.setForceVarPart(true);
3936
3937 if (pDict->getTable(pTab.getName()))
3938 {
3939 char buf[100];
3940 BaseString::snprintf(buf, sizeof(buf), "%s-%d",
3941 pTab.getName(), ndb_rand_r(seed));
3942 pTab.setName(buf);
3943 if (pDict->createTable(pTab))
3944 return NDBT_FAILED;
3945 }
3946 else
3947 {
3948 if (NDBT_Tables::createTable(ndb, pTab.getName()))
3949 {
3950 return NDBT_FAILED;
3951 }
3952 }
3953
3954 ndbout_c("create table %s", pTab.getName());
3955 const NdbDictionary::Table* tab2 = pDict->getTable(pTab.getName());
3956 if (tab2 == NULL) {
3957 g_err << "Table : " << pTab.getName()
3958 << ", not found on line " << __LINE__
3959 <<", error: " << pDict->getNdbError()
3960 << endl;
3961 return NDBT_FAILED;
3962 }
3963 HugoTransactions trans(*tab2);
3964 trans.loadTable(ndb, 1000);
3965
3966 Obj *obj = new Obj;
3967 obj->m_name.assign(pTab.getName());
3968 obj->m_type = NdbDictionary::Object::UserTable;
3969 obj->m_parent = 0;
3970 m_objects.push_back(obj);
3971
3972 return NDBT_OK;
3973 }
3974
3975 int
create_index(Ndb * ndb,Obj * tab)3976 RandSchemaOp::create_index(Ndb* ndb, Obj* tab)
3977 {
3978 NdbDictionary::Dictionary* pDict = ndb->getDictionary();
3979 const NdbDictionary::Table * pTab = pDict->getTable(tab->m_name.c_str());
3980
3981 if (pTab == 0)
3982 {
3983 return NDBT_FAILED;
3984 }
3985
3986 bool ordered = ndb_rand_r(seed) & 1;
3987 bool stored = ndb_rand_r(seed) & 1;
3988
3989 Uint32 type = ordered ?
3990 NdbDictionary::Index::OrderedIndex :
3991 NdbDictionary::Index::UniqueHashIndex;
3992
3993 char buf[255];
3994 BaseString::snprintf(buf, sizeof(buf), "%s-%s",
3995 pTab->getName(),
3996 ordered ? "OI" : "UI");
3997
3998 if (pDict->getIndex(buf, pTab->getName()))
3999 {
4000 // Index exists...let it be ok
4001 return NDBT_OK;
4002 }
4003
4004 ndbout_c("create index %s", buf);
4005 NdbDictionary::Index idx0;
4006 idx0.setName(buf);
4007 idx0.setType((NdbDictionary::Index::Type)type);
4008 idx0.setTable(pTab->getName());
4009 idx0.setStoredIndex(ordered ? false : stored);
4010
4011 for (Uint32 i = 0; i<(Uint32)pTab->getNoOfColumns(); i++)
4012 {
4013 if (pTab->getColumn(i)->getPrimaryKey())
4014 idx0.addColumn(pTab->getColumn(i)->getName());
4015 }
4016 if (pDict->createIndex(idx0))
4017 {
4018 ndbout << pDict->getNdbError() << endl;
4019 return NDBT_FAILED;
4020 }
4021 Obj *obj = new Obj;
4022 obj->m_name.assign(buf);
4023 obj->m_type = type;
4024 obj->m_parent = tab;
4025 m_objects.push_back(obj);
4026
4027 tab->m_dependant.push_back(obj);
4028 return NDBT_OK;
4029 }
4030
4031 int
drop_obj(Ndb * ndb,Obj * obj)4032 RandSchemaOp::drop_obj(Ndb* ndb, Obj* obj)
4033 {
4034 NdbDictionary::Dictionary* pDict = ndb->getDictionary();
4035
4036 if (obj->m_type == NdbDictionary::Object::UserTable)
4037 {
4038 ndbout_c("drop table %s", obj->m_name.c_str());
4039 /**
4040 * Drop of table automatically drops all indexes
4041 */
4042 if (pDict->dropTable(obj->m_name.c_str()))
4043 {
4044 return NDBT_FAILED;
4045 }
4046 while(obj->m_dependant.size())
4047 {
4048 remove_obj(obj->m_dependant[0]);
4049 }
4050 remove_obj(obj);
4051 }
4052 else if (obj->m_type == NdbDictionary::Object::UniqueHashIndex ||
4053 obj->m_type == NdbDictionary::Object::OrderedIndex)
4054 {
4055 ndbout_c("drop index %s", obj->m_name.c_str());
4056 if (pDict->dropIndex(obj->m_name.c_str(),
4057 obj->m_parent->m_name.c_str()))
4058 {
4059 return NDBT_FAILED;
4060 }
4061 remove_obj(obj);
4062 }
4063 return NDBT_OK;
4064 }
4065
4066 void
remove_obj(Obj * obj)4067 RandSchemaOp::remove_obj(Obj* obj)
4068 {
4069 Uint32 i;
4070 if (obj->m_parent)
4071 {
4072 bool found = false;
4073 for (i = 0; i<obj->m_parent->m_dependant.size(); i++)
4074 {
4075 if (obj->m_parent->m_dependant[i] == obj)
4076 {
4077 found = true;
4078 obj->m_parent->m_dependant.erase(i);
4079 break;
4080 }
4081 }
4082 require(found);
4083 }
4084
4085 {
4086 bool found = false;
4087 for (i = 0; i<m_objects.size(); i++)
4088 {
4089 if (m_objects[i] == obj)
4090 {
4091 found = true;
4092 m_objects.erase(i);
4093 break;
4094 }
4095 }
4096 require(found);
4097 }
4098 delete obj;
4099 }
4100
4101 int
alter_table(Ndb * ndb,Obj * obj)4102 RandSchemaOp::alter_table(Ndb* ndb, Obj* obj)
4103 {
4104 NdbDictionary::Dictionary* pDict = ndb->getDictionary();
4105 const NdbDictionary::Table * pOld = pDict->getTable(obj->m_name.c_str());
4106 NdbDictionary::Table tNew = * pOld;
4107
4108 BaseString ops;
4109 unsigned mask = 3;
4110
4111 unsigned type;
4112 while (ops.length() == 0 && (mask != 0))
4113 {
4114 switch((type = (ndb_rand_r(seed) & 1))){
4115 default:
4116 case 0:{
4117 if ((mask & (1 << type)) == 0)
4118 break;
4119 BaseString name;
4120 name.assfmt("newcol_%d", tNew.getNoOfColumns());
4121 NdbDictionary::Column col(name.c_str());
4122 col.setType(NdbDictionary::Column::Unsigned);
4123 col.setDynamic(true);
4124 col.setPrimaryKey(false);
4125 col.setNullable(true);
4126 NdbDictionary::Table save = tNew;
4127 tNew.addColumn(col);
4128 if (!pDict->supportedAlterTable(* pOld, tNew))
4129 {
4130 ndbout_c("not supported...");
4131 mask &= ~(1 << type);
4132 tNew = save;
4133 break;
4134 }
4135 ops.append(" addcol");
4136 break;
4137 }
4138 case 1:{
4139 BaseString name;
4140 do
4141 {
4142 unsigned no = ndb_rand_r(seed);
4143 name.assfmt("%s_%u", pOld->getName(), no);
4144 } while (pDict->getTable(name.c_str()));
4145 tNew.setName(name.c_str());
4146 ops.appfmt(" rename: %s", name.c_str());
4147 break;
4148 }
4149
4150 }
4151 }
4152
4153 if (ops.length())
4154 {
4155 ndbout_c("altering %s ops: %s", pOld->getName(), ops.c_str());
4156 if (pDict->alterTable(*pOld, tNew) != 0)
4157 {
4158 g_err << pDict->getNdbError() << endl;
4159 return NDBT_FAILED;
4160 }
4161 if (strcmp(pOld->getName(), tNew.getName()))
4162 {
4163 obj->m_name.assign(tNew.getName());
4164 }
4165 pDict->invalidateTable(pOld->getName());
4166 }
4167
4168 return NDBT_OK;
4169 }
4170
4171
4172 int
validate(Ndb * ndb)4173 RandSchemaOp::validate(Ndb* ndb)
4174 {
4175 NdbDictionary::Dictionary* pDict = ndb->getDictionary();
4176 for (Uint32 i = 0; i<m_objects.size(); i++)
4177 {
4178 if (m_objects[i]->m_type == NdbDictionary::Object::UserTable)
4179 {
4180 const NdbDictionary::Table* tab2 =
4181 pDict->getTable(m_objects[i]->m_name.c_str());
4182
4183 if (tab2 == NULL) {
4184 g_err << "Table: " << m_objects[i]->m_name.c_str()
4185 << ", not found on line " << __LINE__
4186 <<", error: " << pDict->getNdbError()
4187 << endl;
4188 return NDBT_FAILED;
4189 }
4190 HugoTransactions trans(*tab2);
4191 trans.scanUpdateRecords(ndb, 1000);
4192 trans.clearTable(ndb);
4193 trans.loadTable(ndb, 1000);
4194 }
4195 }
4196
4197 return NDBT_OK;
4198 }
4199
4200 /*
4201 SystemTable = 1, ///< System table
4202 UserTable = 2, ///< User table (may be temporary)
4203 UniqueHashIndex = 3, ///< Unique un-ordered hash index
4204 OrderedIndex = 6, ///< Non-unique ordered index
4205 HashIndexTrigger = 7, ///< Index maintenance, internal
4206 IndexTrigger = 8, ///< Index maintenance, internal
4207 SubscriptionTrigger = 9,///< Backup or replication, internal
4208 ReadOnlyConstraint = 10,///< Trigger, internal
4209 Tablespace = 20, ///< Tablespace
4210 LogfileGroup = 21, ///< Logfile group
4211 Datafile = 22, ///< Datafile
4212 Undofile = 23 ///< Undofile
4213 */
4214
4215 int
cleanup(Ndb * ndb)4216 RandSchemaOp::cleanup(Ndb* ndb)
4217 {
4218 Int32 i;
4219 for (i = m_objects.size() - 1; i >= 0; i--)
4220 {
4221 switch(m_objects[i]->m_type){
4222 case NdbDictionary::Object::UniqueHashIndex:
4223 case NdbDictionary::Object::OrderedIndex:
4224 if (drop_obj(ndb, m_objects[i]))
4225 return NDBT_FAILED;
4226
4227 break;
4228 default:
4229 break;
4230 }
4231 }
4232
4233 for (i = m_objects.size() - 1; i >= 0; i--)
4234 {
4235 switch(m_objects[i]->m_type){
4236 case NdbDictionary::Object::UserTable:
4237 if (drop_obj(ndb, m_objects[i]))
4238 return NDBT_FAILED;
4239 break;
4240 default:
4241 break;
4242 }
4243 }
4244
4245 require(m_objects.size() == 0);
4246 return NDBT_OK;
4247 }
4248
4249 extern unsigned opt_seed;
4250
4251 int
runDictRestart(NDBT_Context * ctx,NDBT_Step * step)4252 runDictRestart(NDBT_Context* ctx, NDBT_Step* step)
4253 {
4254 Ndb* pNdb = GETNDB(step);
4255 int loops = ctx->getNumLoops();
4256
4257 unsigned seed = opt_seed;
4258 NdbMixRestarter res(&seed);
4259 RandSchemaOp dict(&seed);
4260 if (res.getNumDbNodes() < 2)
4261 return NDBT_OK;
4262
4263 if (res.init(ctx, step))
4264 return NDBT_FAILED;
4265
4266 for (int i = 0; i<loops; i++)
4267 {
4268 for (Uint32 j = 0; j<10; j++)
4269 if (dict.schema_op(pNdb))
4270 return NDBT_FAILED;
4271
4272 if (res.dostep(ctx, step))
4273 return NDBT_FAILED;
4274
4275 if (dict.validate(pNdb))
4276 return NDBT_FAILED;
4277 }
4278
4279 if (res.finish(ctx, step))
4280 return NDBT_FAILED;
4281
4282 if (dict.validate(pNdb))
4283 return NDBT_FAILED;
4284
4285 if (dict.cleanup(pNdb))
4286 return NDBT_FAILED;
4287
4288 return NDBT_OK;
4289 }
4290
4291 int
runBug29501(NDBT_Context * ctx,NDBT_Step * step)4292 runBug29501(NDBT_Context* ctx, NDBT_Step* step) {
4293 NdbRestarter res;
4294 NdbDictionary::LogfileGroup lg;
4295 lg.setName("DEFAULT-LG");
4296 lg.setUndoBufferSize(8*1024*1024);
4297
4298 if (res.getNumDbNodes() < 2)
4299 return NDBT_OK;
4300
4301 Ndb* pNdb = GETNDB(step);
4302 NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
4303
4304 int node = res.getRandomNotMasterNodeId(rand());
4305 res.restartOneDbNode(node, true, true, false);
4306
4307 if(pDict->createLogfileGroup(lg) != 0){
4308 g_err << "Failed to create logfilegroup:"
4309 << endl << pDict->getNdbError() << endl;
4310 return NDBT_FAILED;
4311 }
4312
4313 NdbDictionary::Undofile uf;
4314 uf.setPath("undofile01.dat");
4315 uf.setSize(5*1024*1024);
4316 uf.setLogfileGroup("DEFAULT-LG");
4317
4318 if(pDict->createUndofile(uf) != 0){
4319 g_err << "Failed to create undofile:"
4320 << endl << pDict->getNdbError() << endl;
4321 return NDBT_FAILED;
4322 }
4323
4324 res.waitNodesNoStart(&node, 1);
4325 res.startNodes(&node, 1);
4326
4327 if (res.waitClusterStarted()){
4328 g_err << "Node restart failed"
4329 << endl << pDict->getNdbError() << endl;
4330 return NDBT_FAILED;
4331 }
4332 CHK_NDB_READY(pNdb);
4333
4334 if (pDict->dropLogfileGroup(pDict->getLogfileGroup(lg.getName())) != 0){
4335 g_err << "Drop of LFG Failed"
4336 << endl << pDict->getNdbError() << endl;
4337 return NDBT_FAILED;
4338 }
4339
4340 return NDBT_OK;
4341 }
4342
4343 int
runDropDDObjects(NDBT_Context * ctx,NDBT_Step * step)4344 runDropDDObjects(NDBT_Context* ctx, NDBT_Step* step){
4345 //Purpose is to drop all tables, data files, Table spaces and LFG's
4346 Uint32 i = 0;
4347
4348 Ndb* pNdb = GETNDB(step);
4349 NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
4350
4351 NdbDictionary::Dictionary::List list;
4352 if (pDict->listObjects(list) == -1)
4353 return NDBT_FAILED;
4354
4355 //Search the list and drop all tables found
4356 const char * tableFound = 0;
4357 for (i = 0; i < list.count; i++){
4358 switch(list.elements[i].type){
4359 case NdbDictionary::Object::UserTable:
4360 tableFound = list.elements[i].name;
4361 if(tableFound != 0){
4362 if(strcmp(list.elements[i].database, "TEST_DB") == 0 &&
4363 !is_prefix(tableFound, "NDB$BLOB"))
4364 {
4365 if(pDict->dropTable(tableFound) != 0){
4366 g_err << "Failed to drop table: " << tableFound << pDict->getNdbError() << endl;
4367 return NDBT_FAILED;
4368 }
4369 }
4370 }
4371 tableFound = 0;
4372 break;
4373 default:
4374 break;
4375 }
4376 }
4377
4378 //Search the list and drop all data file found
4379 const char * dfFound = 0;
4380 for (i = 0; i < list.count; i++){
4381 switch(list.elements[i].type){
4382 case NdbDictionary::Object::Datafile:
4383 dfFound = list.elements[i].name;
4384 if(dfFound != 0){
4385 if(pDict->dropDatafile(pDict->getDatafile(0, dfFound)) != 0){
4386 g_err << "Failed to drop datafile: " << pDict->getNdbError() << endl;
4387 return NDBT_FAILED;
4388 }
4389 }
4390 dfFound = 0;
4391 break;
4392 default:
4393 break;
4394 }
4395 }
4396
4397 //Search the list and drop all Table Spaces Found
4398 const char * tsFound = 0;
4399 for (i = 0; i <list.count; i++){
4400 switch(list.elements[i].type){
4401 case NdbDictionary::Object::Tablespace:
4402 tsFound = list.elements[i].name;
4403 if(tsFound != 0){
4404 if(pDict->dropTablespace(pDict->getTablespace(tsFound)) != 0){
4405 g_err << "Failed to drop tablespace: " << pDict->getNdbError() << endl;
4406 return NDBT_FAILED;
4407 }
4408 }
4409 tsFound = 0;
4410 break;
4411 default:
4412 break;
4413 }
4414 }
4415
4416 //Search the list and drop all LFG Found
4417 //Currently only 1 LGF is supported, but written for future
4418 //when more then one is supported.
4419 const char * lgFound = 0;
4420 for (i = 0; i < list.count; i++){
4421 switch(list.elements[i].type){
4422 case NdbDictionary::Object::LogfileGroup:
4423 lgFound = list.elements[i].name;
4424 if(lgFound != 0){
4425 if (pDict->dropLogfileGroup(pDict->getLogfileGroup(lgFound)) != 0){
4426 g_err << "Failed to drop tablespace: " << pDict->getNdbError() << endl;
4427 return NDBT_FAILED;
4428 }
4429 }
4430 lgFound = 0;
4431 break;
4432 default:
4433 break;
4434 }
4435 }
4436
4437 return NDBT_OK;
4438 }
4439
4440 int
runWaitStarted(NDBT_Context * ctx,NDBT_Step * step)4441 runWaitStarted(NDBT_Context* ctx, NDBT_Step* step){
4442
4443 NdbRestarter restarter;
4444 restarter.waitClusterStarted(300);
4445 CHK_NDB_READY(GETNDB(step));
4446
4447 NdbSleep_SecSleep(3);
4448 return NDBT_OK;
4449 }
4450
4451 int
testDropDDObjectsSetup(NDBT_Context * ctx,NDBT_Step * step)4452 testDropDDObjectsSetup(NDBT_Context* ctx, NDBT_Step* step){
4453 //Purpose is to setup to test DropDDObjects
4454 char tsname[256];
4455 char dfname[256];
4456
4457 Ndb* pNdb = GETNDB(step);
4458 NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
4459
4460 NdbDictionary::LogfileGroup lg;
4461 lg.setName("DEFAULT-LG");
4462 lg.setUndoBufferSize(8*1024*1024);
4463
4464
4465 if(pDict->createLogfileGroup(lg) != 0){
4466 g_err << "Failed to create logfilegroup:"
4467 << endl << pDict->getNdbError() << endl;
4468 return NDBT_FAILED;
4469 }
4470
4471 NdbDictionary::Undofile uf;
4472 uf.setPath("undofile01.dat");
4473 uf.setSize(5*1024*1024);
4474 uf.setLogfileGroup("DEFAULT-LG");
4475
4476 if(pDict->createUndofile(uf) != 0){
4477 g_err << "Failed to create undofile:"
4478 << endl << pDict->getNdbError() << endl;
4479 return NDBT_FAILED;
4480 }
4481
4482 BaseString::snprintf(tsname, sizeof(tsname), "TS-%u", rand());
4483 BaseString::snprintf(dfname, sizeof(dfname), "%s-%u.dat", tsname, rand());
4484
4485 if (create_tablespace(pDict, lg.getName(), tsname, dfname)){
4486 g_err << "Failed to create undofile:"
4487 << endl << pDict->getNdbError() << endl;
4488 return NDBT_FAILED;
4489 }
4490
4491 return NDBT_OK;
4492 }
4493
4494 int
runBug36072(NDBT_Context * ctx,NDBT_Step * step)4495 runBug36072(NDBT_Context* ctx, NDBT_Step* step)
4496 {
4497 Ndb* pNdb = GETNDB(step);
4498 NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
4499 NdbRestarter res;
4500
4501 int err[] = { 6016,
4502 #ifdef BUG_46856
4503 6017,
4504 #endif
4505 0 };
4506 for (Uint32 i = 0; err[i] != 0; i++)
4507 {
4508 int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 };
4509
4510 if (res.dumpStateAllNodes(val2, 2))
4511 return NDBT_FAILED;
4512
4513 if (res.insertErrorInAllNodes(932)) // arbit
4514 return NDBT_FAILED;
4515
4516 int code = err[i];
4517
4518 if (code == 6016)
4519 {
4520 if (res.insertErrorInAllNodes(code))
4521 return NDBT_FAILED;
4522 }
4523
4524 NdbDictionary::LogfileGroup lg;
4525 lg.setName("DEFAULT-LG");
4526 lg.setUndoBufferSize(8*1024*1024);
4527
4528 NdbDictionary::Undofile uf;
4529 uf.setPath("undofile01.dat");
4530 uf.setSize(5*1024*1024);
4531 uf.setLogfileGroup("DEFAULT-LG");
4532
4533 int r = pDict->createLogfileGroup(lg);
4534 if (code == 6017)
4535 {
4536 if (r)
4537 {
4538 ndbout << __LINE__ << " : " << pDict->getNdbError() << endl;
4539 return NDBT_FAILED;
4540 }
4541
4542 if (res.insertErrorInAllNodes(err[i]))
4543 return NDBT_FAILED;
4544
4545 pDict->createUndofile(uf);
4546 }
4547
4548 if (res.waitClusterNoStart())
4549 return NDBT_FAILED;
4550
4551 res.startAll();
4552 if (res.waitClusterStarted())
4553 return NDBT_FAILED;
4554 CHK_NDB_READY(pNdb);
4555
4556 if (code == 6016)
4557 {
4558 NdbDictionary::LogfileGroup lg2 = pDict->getLogfileGroup("DEFAULT-LG");
4559 NdbError err= pDict->getNdbError();
4560 if( (int) err.classification == (int) ndberror_cl_none)
4561 {
4562 ndbout << __LINE__ << endl;
4563 return NDBT_FAILED;
4564 }
4565
4566 if (pDict->createLogfileGroup(lg) != 0)
4567 {
4568 ndbout << __LINE__ << " : " << pDict->getNdbError() << endl;
4569 return NDBT_FAILED;
4570 }
4571 }
4572 else
4573 {
4574 NdbDictionary::Undofile uf2 = pDict->getUndofile(0, "undofile01.dat");
4575 NdbError err= pDict->getNdbError();
4576 if( (int) err.classification == (int) ndberror_cl_none)
4577 {
4578 ndbout << __LINE__ << endl;
4579 return NDBT_FAILED;
4580 }
4581
4582 if (pDict->createUndofile(uf) != 0)
4583 {
4584 ndbout << __LINE__ << " : " << pDict->getNdbError() << endl;
4585 return NDBT_FAILED;
4586 }
4587 }
4588
4589 {
4590 NdbDictionary::LogfileGroup lg2 = pDict->getLogfileGroup("DEFAULT-LG");
4591 NdbError err= pDict->getNdbError();
4592 if( (int) err.classification != (int) ndberror_cl_none)
4593 {
4594 ndbout << __LINE__ << " : " << pDict->getNdbError() << endl;
4595 return NDBT_FAILED;
4596 }
4597
4598 if (pDict->dropLogfileGroup(lg2))
4599 {
4600 ndbout << __LINE__ << " : " << pDict->getNdbError() << endl;
4601 return NDBT_FAILED;
4602 }
4603 }
4604 }
4605
4606 return NDBT_OK;
4607 }
4608
4609 int
restartClusterInitial(NDBT_Context * ctx,NDBT_Step * step)4610 restartClusterInitial(NDBT_Context* ctx, NDBT_Step* step)
4611 {
4612 NdbRestarter res;
4613
4614 res.restartAll2(NdbRestarter::NRRF_INITIAL |
4615 NdbRestarter::NRRF_NOSTART |
4616 NdbRestarter::NRRF_ABORT);
4617 if (res.waitClusterNoStart())
4618 return NDBT_FAILED;
4619
4620 res.startAll();
4621 if (res.waitClusterStarted())
4622 return NDBT_FAILED;
4623 CHK_NDB_READY(GETNDB(step));
4624
4625 return NDBT_OK;
4626 }
4627
4628
4629 int
DropDDObjectsVerify(NDBT_Context * ctx,NDBT_Step * step)4630 DropDDObjectsVerify(NDBT_Context* ctx, NDBT_Step* step){
4631 //Purpose is to verify test DropDDObjects worked
4632 Uint32 i = 0;
4633
4634 Ndb* pNdb = GETNDB(step);
4635 NdbDictionary::Dictionary* pDict = pNdb->getDictionary();
4636
4637 NdbDictionary::Dictionary::List list;
4638 if (pDict->listObjects(list) == -1)
4639 return NDBT_FAILED;
4640
4641 bool ddFound = false;
4642 for (i = 0; i <list.count; i++){
4643 switch(list.elements[i].type){
4644 case NdbDictionary::Object::Tablespace:
4645 ddFound = true;
4646 break;
4647 case NdbDictionary::Object::LogfileGroup:
4648 ddFound = true;
4649 break;
4650 default:
4651 break;
4652 }
4653 if(ddFound == true){
4654 g_err << "DropDDObjects Failed: DD found:"
4655 << endl;
4656 return NDBT_FAILED;
4657 }
4658 }
4659 return NDBT_OK;
4660 }
4661
4662 // Bug48604
4663
4664 // string messages between local/remote steps identified by stepNo-1
4665 // each Msg<loc><rem> waits for Ack<loc><rem>
4666
4667 static const uint MaxMsg = 100;
4668
4669 static bool
send_msg(NDBT_Context * ctx,int loc,int rem,const char * msg)4670 send_msg(NDBT_Context* ctx, int loc, int rem, const char* msg)
4671 {
4672 char msgName[20], ackName[20];
4673 sprintf(msgName, "Msg%d%d", loc, rem);
4674 sprintf(ackName, "Ack%d%d", loc, rem);
4675 g_info << loc << ": send to:" << rem << " msg:" << msg << endl;
4676 ctx->setProperty(msgName, msg);
4677 int cnt = 0;
4678 while (1)
4679 {
4680 if (ctx->isTestStopped())
4681 return false;
4682 int ret;
4683 if ((ret = ctx->getProperty(ackName, (Uint32)0)) != 0)
4684 break;
4685 if (++cnt % 100 == 0)
4686 g_info << loc << ": send to:" << rem << " wait for ack" << endl;
4687 NdbSleep_MilliSleep(10);
4688 }
4689 ctx->setProperty(ackName, (Uint32)0);
4690 return true;
4691 }
4692
4693 static bool
poll_msg(NDBT_Context * ctx,int loc,int rem,char * msg)4694 poll_msg(NDBT_Context* ctx, int loc, int rem, char* msg)
4695 {
4696 char msgName[20], ackName[20];
4697 sprintf(msgName, "Msg%d%d", rem, loc);
4698 sprintf(ackName, "Ack%d%d", rem, loc);
4699 const char* ptr;
4700 if ((ptr = ctx->getProperty(msgName, (char*)0)) != 0 && ptr[0] != 0)
4701 {
4702 require(strlen(ptr) < MaxMsg);
4703 memset(msg, 0, MaxMsg);
4704 strcpy(msg, ptr);
4705 g_info << loc << ": recv from:" << rem << " msg:" << msg << endl;
4706 ctx->setProperty(msgName, "");
4707 ctx->setProperty(ackName, (Uint32)1);
4708 return true;
4709 }
4710 return false;
4711 }
4712
4713 static int
recv_msg(NDBT_Context * ctx,int loc,int rem,char * msg)4714 recv_msg(NDBT_Context* ctx, int loc, int rem, char* msg)
4715 {
4716 uint cnt = 0;
4717 while (1)
4718 {
4719 if (ctx->isTestStopped())
4720 return false;
4721 if (poll_msg(ctx, loc, rem, msg))
4722 break;
4723 if (++cnt % 100 == 0)
4724 g_info << loc << ": recv from:" << rem << " wait for msg" << endl;
4725 NdbSleep_MilliSleep(10);
4726 }
4727 return true;
4728 }
4729
4730 const char* tabName_Bug48604 = "TBug48604";
4731 const char* indName_Bug48604 = "TBug48604X1";
4732
4733 static const NdbDictionary::Table*
runBug48604createtable(NDBT_Context * ctx,NDBT_Step * step)4734 runBug48604createtable(NDBT_Context* ctx, NDBT_Step* step)
4735 {
4736 Ndb* pNdb = GETNDB(step);
4737 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
4738 const NdbDictionary::Table* pTab = 0;
4739 int result = NDBT_OK;
4740 do
4741 {
4742 NdbDictionary::Table tab(tabName_Bug48604);
4743 {
4744 NdbDictionary::Column col("a");
4745 col.setType(NdbDictionary::Column::Unsigned);
4746 col.setPrimaryKey(true);
4747 tab.addColumn(col);
4748 }
4749 {
4750 NdbDictionary::Column col("b");
4751 col.setType(NdbDictionary::Column::Unsigned);
4752 col.setNullable(false);
4753 tab.addColumn(col);
4754 }
4755 CHECK(pDic->createTable(tab) == 0);
4756 CHECK((pTab = pDic->getTable(tabName_Bug48604)) != 0);
4757 }
4758 while (0);
4759 return pTab;
4760 }
4761
4762 static const NdbDictionary::Index*
runBug48604createindex(NDBT_Context * ctx,NDBT_Step * step)4763 runBug48604createindex(NDBT_Context* ctx, NDBT_Step* step)
4764 {
4765 Ndb* pNdb = GETNDB(step);
4766 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
4767 const NdbDictionary::Index* pInd = 0;
4768 int result = NDBT_OK;
4769 do {
4770 NdbDictionary::Index ind(indName_Bug48604);
4771 ind.setTable(tabName_Bug48604);
4772 ind.setType(NdbDictionary::Index::OrderedIndex);
4773 ind.setLogging(false);
4774 ind.addColumn("b");
4775 g_info << "index create.." << endl;
4776 CHECK(pDic->createIndex(ind) == 0);
4777 CHECK((pInd = pDic->getIndex(indName_Bug48604, tabName_Bug48604)) != 0);
4778 g_info << "index created" << endl;
4779 return pInd;
4780 }
4781 while (0);
4782 return pInd;
4783 }
4784
4785 int
runBug48604(NDBT_Context * ctx,NDBT_Step * step)4786 runBug48604(NDBT_Context* ctx, NDBT_Step* step)
4787 {
4788 Ndb* pNdb = GETNDB(step);
4789 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
4790 const NdbDictionary::Table* pTab = 0;
4791 const NdbDictionary::Index* pInd = 0;
4792 (void)pDic->dropTable(tabName_Bug48604);
4793 int loc = step->getStepNo() - 1;
4794 require(loc == 0);
4795 g_err << "main" << endl;
4796 int result = NDBT_OK;
4797 int loops = ctx->getNumLoops();
4798 char msg[MaxMsg];
4799
4800 do
4801 {
4802 CHECK((pTab = runBug48604createtable(ctx, step)) != 0);
4803 CHECK(send_msg(ctx, 0, 1, "s"));
4804
4805 int loop = 0;
4806 while (result == NDBT_OK && loop++ < loops)
4807 {
4808 g_err << "loop:" << loop << endl;
4809 {
4810 // create index fully while uncommitted ops wait
4811 const char* ops[][3] =
4812 {
4813 { "ozin", "oc", "oa" }, // 0: before 1-2: after
4814 { "oziun", "oc", "oa" },
4815 { "ozidn", "oc", "oa" },
4816 { "ozicun", "oc", "oa" },
4817 { "ozicuuun", "oc", "oa" },
4818 { "ozicdn", "oc", "oa" },
4819 { "ozicdin", "oc", "oa" },
4820 { "ozicdidiuuudidn", "oc", "oa" },
4821 { "ozicdidiuuudidin", "oc", "oa" }
4822 };
4823 const int cnt = sizeof(ops)/sizeof(ops[0]);
4824 int i;
4825 for (i = 0; result == NDBT_OK && i < cnt; i++)
4826 {
4827 int j;
4828 for (j = 1; result == NDBT_OK && j <= 2; j++)
4829 {
4830 if (ops[i][j] == 0)
4831 continue;
4832 CHECK(send_msg(ctx, 0, 1, ops[i][0]));
4833 CHECK(recv_msg(ctx, 0, 1, msg) && msg[0] == 'o');
4834 CHECK((pInd = runBug48604createindex(ctx, step)) != 0);
4835 CHECK(send_msg(ctx, 0, 1, ops[i][j]));
4836 CHECK(recv_msg(ctx, 0, 1, msg) && msg[0] == 'o');
4837
4838 CHECK(pDic->dropIndex(indName_Bug48604, tabName_Bug48604) == 0);
4839 g_info << "index dropped" << endl;
4840 }
4841 }
4842 }
4843 }
4844 }
4845 while (0);
4846
4847 (void)send_msg(ctx, 0, 1, "x");
4848 ctx->stopTest();
4849 g_err << "main: exit:" << result << endl;
4850 return result;
4851 }
4852
4853 int
runBug48604ops(NDBT_Context * ctx,NDBT_Step * step)4854 runBug48604ops(NDBT_Context* ctx, NDBT_Step* step)
4855 {
4856 Ndb* pNdb = GETNDB(step);
4857 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
4858 const NdbDictionary::Table* pTab = 0;
4859 //const NdbDictionary::Index* pInd = 0;
4860 int loc = step->getStepNo() - 1;
4861 require(loc > 0);
4862 g_err << "ops: loc:" << loc << endl;
4863 int result = NDBT_OK;
4864 int records = ctx->getNumRecords();
4865 char msg[MaxMsg];
4866
4867 do
4868 {
4869 CHECK(recv_msg(ctx, loc, 0, msg));
4870 require(msg[0] == 's');
4871 CHECK((pTab = pDic->getTable(tabName_Bug48604)) != 0);
4872 HugoOperations ops(*pTab);
4873 bool have_trans = false;
4874 int opseq = 0;
4875
4876 while (result == NDBT_OK && !ctx->isTestStopped())
4877 {
4878 CHECK(recv_msg(ctx, loc, 0, msg));
4879 if (msg[0] == 'x')
4880 break;
4881 if (msg[0] == 'o')
4882 {
4883 char* p = &msg[1];
4884 int c;
4885 while (result == NDBT_OK && (c = *p++) != 0)
4886 {
4887 if (c == 'n')
4888 {
4889 require(have_trans);
4890 CHECK(ops.execute_NoCommit(pNdb) == 0);
4891 g_info << loc << ": not committed" << endl;
4892 continue;
4893 }
4894 if (c == 'c')
4895 {
4896 require(have_trans);
4897 CHECK(ops.execute_Commit(pNdb) == 0);
4898 ops.closeTransaction(pNdb);
4899 have_trans = false;
4900 g_info << loc << ": committed" << endl;
4901 continue;
4902 }
4903 if (c == 'a')
4904 {
4905 require(have_trans);
4906 CHECK(ops.execute_Rollback(pNdb) == 0);
4907 ops.closeTransaction(pNdb);
4908 have_trans = false;
4909 g_info << loc << ": aborted" << endl;
4910 continue;
4911 }
4912 if (c == 'i' || c == 'u' || c == 'd')
4913 {
4914 if (!have_trans)
4915 {
4916 CHECK(ops.startTransaction(pNdb) == 0);
4917 have_trans = true;
4918 g_info << loc << ": trans started" << endl;
4919 }
4920 int i;
4921 for (i = 0; result == NDBT_OK && i < records; i++)
4922 {
4923 if (c == 'i')
4924 CHECK(ops.pkInsertRecord(pNdb, i, 1, opseq) == 0);
4925 if (c == 'u')
4926 CHECK(ops.pkUpdateRecord(pNdb, i, 1, opseq) == 0);
4927 if (c == 'd')
4928 CHECK(ops.pkDeleteRecord(pNdb, i, 1) == 0);
4929 }
4930 char op_str[2];
4931 sprintf(op_str, "%c", c);
4932 g_info << loc << ": op:" << op_str << " records:" << records << endl;
4933 opseq++;
4934 continue;
4935 }
4936 if (c == 'z')
4937 {
4938 CHECK(ops.clearTable(pNdb) == 0);
4939 continue;
4940 }
4941 require(false);
4942 }
4943 CHECK(send_msg(ctx, loc, 0, "o"));
4944 continue;
4945 }
4946 require(false);
4947 }
4948 } while (0);
4949
4950 g_err << "ops: loc:" << loc << " exit:" << result << endl;
4951 if (result != NDBT_OK)
4952 ctx->stopTest();
4953 return result;
4954 }
4955
4956 int
runBug54651(NDBT_Context * ctx,NDBT_Step * step)4957 runBug54651(NDBT_Context* ctx, NDBT_Step* step)
4958 {
4959 Ndb* pNdb = GETNDB(step);
4960 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
4961
4962 for (Uint32 j = 0; j< 2; j++)
4963 {
4964 pDic->createTable(* ctx->getTab());
4965
4966 const NdbDictionary::Table * pTab =pDic->getTable(ctx->getTab()->getName());
4967 NdbDictionary::Table copy = * pTab;
4968 BaseString name;
4969 name.assfmt("%s_1", pTab->getName());
4970 copy.setName(name.c_str());
4971
4972 if (pDic->createTable(copy))
4973 {
4974 ndbout_c("Failed to create table...");
4975 ndbout << pDic->getNdbError() << endl;
4976 return NDBT_FAILED;
4977 }
4978
4979 NdbDictionary::Table alter = * pTab;
4980 alter.setName(name.c_str());
4981 for (Uint32 i = 0; i<2; i++)
4982 {
4983 // now rename org table to same name...
4984 if (pDic->alterTable(* pTab, alter) == 0)
4985 {
4986 ndbout << "Alter with duplicate name succeeded!!" << endl;
4987 return NDBT_FAILED;
4988 }
4989
4990 ndbout << "Alter with duplicate name failed...good" << endl
4991 << pDic->getNdbError() << endl;
4992 }
4993
4994 pDic->dropTable(copy.getName());
4995 pDic->dropTable(ctx->getTab()->getName());
4996 }
4997 return NDBT_OK;
4998 }
4999
5000 /** telco-6.4 **/
5001
5002 // begin schema trans
5003
5004 #undef chk1
5005 #undef chk2
5006
5007 static bool st_core_on_err = false;
5008
5009 #define chk1(x) \
5010 do { \
5011 if (x) break; \
5012 g_err << "FAIL " << __LINE__ << " " << #x << endl; \
5013 if (st_core_on_err) abort(); \
5014 goto err; \
5015 } while (0)
5016
5017 #define chk2(x, e) \
5018 do { \
5019 if (x) break; \
5020 g_err << "FAIL " << __LINE__ << " " << #x << ": " << e << endl; \
5021 if (st_core_on_err) abort(); \
5022 goto err; \
5023 } while (0)
5024
5025 static uint
urandom(uint m)5026 urandom(uint m)
5027 {
5028 require(m != 0);
5029 uint n = (uint)ndb_rand();
5030 return n % m;
5031 }
5032
5033 static bool
randomly(uint k,uint m)5034 randomly(uint k, uint m)
5035 {
5036 uint n = urandom(m);
5037 return n < k;
5038 }
5039
5040 // structs
5041
5042 struct ST_Obj;
5043 template class Vector<ST_Obj*>;
5044 typedef Vector<ST_Obj*> ST_Objlist;
5045
5046 static ST_Objlist st_objlist;
5047 #ifndef NDEBUG
5048 static const ST_Obj* st_find_obj(const char* db, const char* name);
5049 #endif
5050
5051 #define ST_MAX_NAME_SIZE (MAX_TAB_NAME_SIZE + 100)
5052
5053 struct ST_Obj {
5054 NdbDictionary::Object::Type type;
5055 char dbname[ST_MAX_NAME_SIZE];
5056 char name[ST_MAX_NAME_SIZE];
5057 int id;
5058 enum { Skip = 0xFFFF }; // mark ignored objects in List
5059 bool create; // true/false = create/drop prepared or committed
5060 bool commit;
existsST_Obj5061 bool exists() const { // visible to trans
5062 return !(!create && commit);
5063 }
is_triggerST_Obj5064 virtual bool is_trigger() const {
5065 return false;
5066 }
is_indexST_Obj5067 virtual bool is_index() const {
5068 return false;
5069 }
is_tableST_Obj5070 virtual bool is_table() const {
5071 return false;
5072 }
realnameST_Obj5073 virtual const char* realname() const {
5074 return name;
5075 }
ST_ObjST_Obj5076 ST_Obj(const char* a_dbname, const char* a_name) {
5077 type = NdbDictionary::Object::TypeUndefined;
5078 strcpy(dbname, a_dbname);
5079 strcpy(name, a_name);
5080 id = -1;
5081 create = false; // init as dropped
5082 commit = true;
5083 assert(st_find_obj(dbname, name) == 0);
5084 st_objlist.push_back(this);
5085 }
~ST_ObjST_Obj5086 virtual ~ST_Obj() {}
5087 };
5088
5089 static NdbOut&
operator <<(NdbOut & out,const ST_Obj & obj)5090 operator<<(NdbOut& out, const ST_Obj& obj)
5091 {
5092 out << obj.name << "[" << obj.id << "]";
5093 return out;
5094 }
5095
5096 struct ST_Trg : public ST_Obj {
5097 struct ST_Ind* ind;
5098 TriggerEvent::Value event;
5099 mutable char realname_buf[ST_MAX_NAME_SIZE];
is_triggerST_Trg5100 virtual bool is_trigger() const {
5101 return true;
5102 }
5103 virtual const char* realname() const;
ST_TrgST_Trg5104 ST_Trg(const char* a_db, const char* a_name) :
5105 ST_Obj(a_db, a_name) {
5106 ind = 0;
5107 }
~ST_TrgST_Trg5108 virtual ~ST_Trg() {}
5109 };
5110
5111 template class Vector<ST_Trg*>;
5112 typedef Vector<ST_Trg*> ST_Trglist;
5113
5114 struct ST_Ind : public ST_Obj {
5115 struct ST_Tab* tab;
5116 const NdbDictionary::Index* ind;
5117 const NdbDictionary::Index* ind_r; // retrieved
5118 BaseString colnames;
5119 ST_Trglist* trglist;
5120 int trgcount;
is_indexST_Ind5121 virtual bool is_index() const {
5122 return true;
5123 }
is_uniqueST_Ind5124 bool is_unique() const {
5125 return type == NdbDictionary::Object::UniqueHashIndex;
5126 }
trgST_Ind5127 const ST_Trg& trg(int k) const {
5128 return *((*trglist)[k]);
5129 }
trgST_Ind5130 ST_Trg& trg(int k) {
5131 return *((*trglist)[k]);
5132 }
ST_IndST_Ind5133 ST_Ind(const char* a_db, const char* a_name) :
5134 ST_Obj(a_db, a_name) {
5135 tab = 0;
5136 ind = 0;
5137 ind_r = 0;
5138 trglist = new ST_Trglist;
5139 trgcount = 0;
5140 }
~ST_IndST_Ind5141 virtual ~ST_Ind() {
5142 delete ind;
5143 delete trglist;
5144 ind = 0;
5145 trglist = 0;
5146 }
5147 };
5148
5149 const char*
realname() const5150 ST_Trg::realname() const
5151 {
5152 if (!exists())
5153 return name;
5154 const char* p = name;
5155 const char* q = strchr(p, '<');
5156 const char* r = strchr(p, '>');
5157 require(q != 0 && r != 0 && q < r);
5158 require(ind->id != -1);
5159 sprintf(realname_buf, "%.*s%d%s", (int)(q - p), p, ind->id, r + 1);
5160 return realname_buf;
5161 }
5162
5163 template class Vector<ST_Ind*>;
5164 typedef Vector<ST_Ind*> ST_Indlist;
5165
5166 struct ST_Tab : public ST_Obj {
5167 const NdbDictionary::Table* tab;
5168 const NdbDictionary::Table* tab_r; // retrieved
5169 ST_Indlist* indlist;
5170 int indcount;
5171 int induniquecount;
5172 int indorderedcount;
is_tableST_Tab5173 virtual bool is_table() const {
5174 return true;
5175 }
indST_Tab5176 const ST_Ind& ind(int j) const {
5177 return *((*indlist)[j]);
5178 }
indST_Tab5179 ST_Ind& ind(int j) {
5180 return *((*indlist)[j]);
5181 }
ST_TabST_Tab5182 ST_Tab(const char* a_db, const char* a_name) :
5183 ST_Obj(a_db, a_name) {
5184 tab = 0;
5185 tab_r = 0;
5186 indlist = new ST_Indlist;
5187 indcount = 0;
5188 induniquecount = 0;
5189 indorderedcount = 0;
5190 }
~ST_TabST_Tab5191 virtual ~ST_Tab() {
5192 delete tab;
5193 delete indlist;
5194 tab = 0;
5195 indlist = 0;
5196 }
5197 };
5198
5199 template class Vector<ST_Tab*>;
5200 typedef Vector<ST_Tab*> ST_Tablist;
5201
5202 struct ST_Restarter : public NdbRestarter {
5203 int get_status();
5204 const ndb_mgm_node_state& get_state(int node_id);
ST_RestarterST_Restarter5205 ST_Restarter() {
5206 int i;
5207 for (i = 0; i < MAX_NODES; i++)
5208 state[i].node_type = NDB_MGM_NODE_TYPE_UNKNOWN;
5209 first_time = true;
5210 }
5211 protected:
5212 void set_state(const ndb_mgm_node_state& state);
5213 ndb_mgm_node_state state[MAX_NODES];
5214 bool first_time;
5215 };
5216
5217 const ndb_mgm_node_state&
get_state(int node_id)5218 ST_Restarter::get_state(int node_id) {
5219 require(node_id > 0 && node_id < MAX_NODES);
5220 require(!first_time);
5221 return state[node_id];
5222 }
5223
5224 void
set_state(const ndb_mgm_node_state & new_state)5225 ST_Restarter::set_state(const ndb_mgm_node_state& new_state)
5226 {
5227 int node_id = new_state.node_id;
5228 require(1 <= node_id && node_id < MAX_NODES);
5229
5230 require(new_state.node_type == NDB_MGM_NODE_TYPE_MGM ||
5231 new_state.node_type == NDB_MGM_NODE_TYPE_NDB ||
5232 new_state.node_type == NDB_MGM_NODE_TYPE_API);
5233
5234 ndb_mgm_node_state& old_state = state[node_id];
5235 if (!first_time)
5236 require(old_state.node_type == new_state.node_type);
5237 old_state = new_state;
5238 }
5239
5240 int
get_status()5241 ST_Restarter::get_status()
5242 {
5243 if (getStatus() == -1)
5244 return -1;
5245 int i;
5246 for (i = 0; i < (int)mgmNodes.size(); i++)
5247 set_state(mgmNodes[i]);
5248 for (i = 0; i < (int)ndbNodes.size(); i++)
5249 set_state(ndbNodes[i]);
5250 for (i = 0; i < (int)apiNodes.size(); i++)
5251 set_state(apiNodes[i]);
5252 first_time = false;
5253 return 0;
5254 }
5255
5256 struct ST_Con {
5257 Ndb_cluster_connection* ncc;
5258 Ndb* ndb;
5259 NdbDictionary::Dictionary* dic;
5260 ST_Restarter* restarter;
5261 int numdbnodes;
5262 char dbname[ST_MAX_NAME_SIZE];
5263 ST_Tablist* tablist;
5264 int tabcount;
5265 bool tx_on;
5266 bool tx_commit;
5267 bool is_xcon;
5268 ST_Con* xcon;
5269 int node_id;
5270 int loop;
tabST_Con5271 const ST_Tab& tab(int i) const {
5272 return *((*tablist)[i]);
5273 }
tabST_Con5274 ST_Tab& tab(int i) {
5275 return *((*tablist)[i]);
5276 }
ST_ConST_Con5277 ST_Con(Ndb_cluster_connection* a_ncc,
5278 Ndb* a_ndb,
5279 ST_Restarter* a_restarter) {
5280 ncc = a_ncc;
5281 ndb = a_ndb;
5282 dic = a_ndb->getDictionary();
5283 restarter = a_restarter;
5284 numdbnodes = restarter->getNumDbNodes();
5285 require(numdbnodes >= 1);
5286 sprintf(dbname, "%s", ndb->getDatabaseName());
5287 tablist = new ST_Tablist;
5288 tabcount = 0;
5289 tx_on = false;
5290 tx_commit = false;
5291 is_xcon = false;
5292 xcon = 0;
5293 node_id = ncc->node_id();
5294 {
5295 require(restarter->get_status() == 0);
5296 const ndb_mgm_node_state& state = restarter->get_state(node_id);
5297 require(state.node_type == NDB_MGM_NODE_TYPE_API);
5298 require(state.version != 0); // means "connected"
5299 g_info << "node_id:" << node_id << endl;
5300 }
5301 loop = -1;
5302 }
~ST_ConST_Con5303 ~ST_Con() {
5304 if (!is_xcon) {
5305 delete tablist;
5306 } else {
5307 delete ndb;
5308 delete ncc;
5309 }
5310 tablist = 0;
5311 ndb = 0;
5312 ncc = 0;
5313 }
5314 };
5315
5316 // initialization
5317
5318 static int
st_drop_all_tables(ST_Con & c)5319 st_drop_all_tables(ST_Con& c)
5320 {
5321 g_info << "st_drop_all_tables" << endl;
5322 NdbDictionary::Dictionary::List list;
5323 chk2(c.dic->listObjects(list) == 0, c.dic->getNdbError());
5324 int n;
5325 for (n = 0; n < (int)list.count; n++) {
5326 const NdbDictionary::Dictionary::List::Element& element =
5327 list.elements[n];
5328 if (element.type == NdbDictionary::Object::UserTable &&
5329 strcmp(element.database, "TEST_DB") == 0) {
5330 chk2(c.dic->dropTable(element.name) == 0, c.dic->getNdbError());
5331 }
5332 }
5333 return 0;
5334 err:
5335 return -1;
5336 }
5337
5338 static void
st_init_objects(ST_Con & c,NDBT_Context * ctx)5339 st_init_objects(ST_Con& c, NDBT_Context* ctx)
5340 {
5341 int numTables = ctx->getNumTables();
5342 c.tabcount = 0;
5343 int i;
5344 for (i = 0; i < numTables; i++) {
5345 const NdbDictionary::Table* pTab = 0;
5346 #ifdef ndb_test_ALL_TABLES_is_fixed
5347 const NdbDictionary::Table** tables = ctx->getTables();
5348 pTab = tables[i];
5349 #else
5350 const Vector<BaseString>& tables = ctx->getSuite()->m_tables_in_test;
5351 pTab = NDBT_Tables::getTable(tables[i].c_str());
5352 #endif
5353 require(pTab != 0 && pTab->getName() != 0);
5354
5355 {
5356 bool ok = true;
5357 int n;
5358 for (n = 0; n < pTab->getNoOfColumns(); n++) {
5359 const NdbDictionary::Column* pCol = pTab->getColumn(n);
5360 require(pCol != 0);
5361 if (pCol->getStorageType() !=
5362 NdbDictionary::Column::StorageTypeMemory) {
5363 g_err << pTab->getName() << ": skip non-mem table for now" << endl;
5364 ok = false;
5365 break;
5366 }
5367 }
5368 if (!ok)
5369 continue;
5370 }
5371
5372 c.tablist->push_back(new ST_Tab(c.dbname, pTab->getName()));
5373 c.tabcount++;
5374 ST_Tab& tab = *c.tablist->back();
5375 tab.type = NdbDictionary::Object::UserTable;
5376 tab.tab = new NdbDictionary::Table(*pTab);
5377
5378 const char** indspec = NDBT_Tables::getIndexes(tab.name);
5379
5380 while (indspec != 0 && *indspec != 0) {
5381 char ind_name[ST_MAX_NAME_SIZE];
5382 int ind_len = snprintf(ind_name,
5383 ST_MAX_NAME_SIZE,
5384 "%sX%d",
5385 tab.name,
5386 tab.indcount);
5387 require(ind_len < ST_MAX_NAME_SIZE);
5388 tab.indlist->push_back(new ST_Ind("sys", ind_name));
5389 ST_Ind& ind = *tab.indlist->back();
5390 ind.tab = &tab;
5391
5392 NdbDictionary::Index* pInd = new NdbDictionary::Index(ind.name);
5393 pInd->setTable(tab.name);
5394 pInd->setLogging(false);
5395
5396 const char* type = *indspec++;
5397 if (strcmp(type, "UNIQUE") == 0) {
5398 ind.type = NdbDictionary::Object::UniqueHashIndex;
5399 pInd->setType((NdbDictionary::Index::Type)ind.type);
5400 tab.induniquecount++;
5401
5402 { char trg_name[ST_MAX_NAME_SIZE];
5403 int trg_len = snprintf(trg_name,
5404 ST_MAX_NAME_SIZE,
5405 "NDB$INDEX_<%s>_UI",
5406 ind.name);
5407 require(trg_len < ST_MAX_NAME_SIZE);
5408 ind.trglist->push_back(new ST_Trg("", trg_name));
5409 ST_Trg& trg = *ind.trglist->back();
5410 trg.ind = &ind;
5411 trg.type = NdbDictionary::Object::HashIndexTrigger;
5412 trg.event = TriggerEvent::TE_INSERT;
5413 }
5414 ind.trgcount = 1;
5415 }
5416 else if (strcmp(type, "ORDERED") == 0) {
5417 ind.type = NdbDictionary::Object::OrderedIndex;
5418 pInd->setType((NdbDictionary::Index::Type)ind.type);
5419 tab.indorderedcount++;
5420
5421 { char trg_name[ST_MAX_NAME_SIZE];
5422 int trg_len = snprintf(trg_name,
5423 ST_MAX_NAME_SIZE,
5424 "NDB$INDEX_<%s>_CUSTOM",
5425 ind.name);
5426 require(trg_len < ST_MAX_NAME_SIZE);
5427 ind.trglist->push_back(new ST_Trg("", trg_name));
5428 ST_Trg& trg = *ind.trglist->back();
5429 trg.ind = &ind;
5430 trg.type = NdbDictionary::Object::IndexTrigger;
5431 trg.event = TriggerEvent::TE_CUSTOM;
5432 }
5433 ind.trgcount = 1;
5434 }
5435 else
5436 {
5437 require(false);
5438 }
5439
5440 const char* sep = "";
5441 const char* colname;
5442 while ((colname = *indspec++) != 0) {
5443 const NdbDictionary::Column* col = tab.tab->getColumn(colname);
5444 require(col != 0);
5445 pInd->addColumn(*col);
5446
5447 ind.colnames.appfmt("%s%s", sep, colname);
5448 sep = ",";
5449 }
5450
5451 ind.ind = pInd;
5452 tab.indcount++;
5453 }
5454 }
5455 }
5456
5457 // node states
5458
5459 static int
st_report_db_nodes(ST_Con & c,NdbOut & out)5460 st_report_db_nodes(ST_Con& c, NdbOut& out)
5461 {
5462 chk1(c.restarter->get_status() == 0);
5463 char r1[100]; // up
5464 char r2[100]; // down
5465 char r3[100]; // unknown
5466 r1[0] =r2[0] = r3[0] = 0;
5467 int i;
5468 for (i = 1; i < MAX_NODES; i++) {
5469 const ndb_mgm_node_state& state = c.restarter->get_state(i);
5470 if (state.node_type == NDB_MGM_NODE_TYPE_NDB) {
5471 char* r = 0;
5472 if (state.node_status == NDB_MGM_NODE_STATUS_STARTED)
5473 r = r1;
5474 else if (state.node_status == NDB_MGM_NODE_STATUS_NO_CONTACT)
5475 r = r2;
5476 else
5477 r = r3;
5478 sprintf(r + strlen(r), "%s%d", r[0] == 0 ? "" : ",", i);
5479 }
5480 }
5481 if (r2[0] != 0 || r3[0] != 0) {
5482 out << "nodes up:" << r1 << " down:" << r2 << " unknown:" << r3 << endl;
5483 goto err;
5484 }
5485 out << "nodes up:" << r1 << " (all)" << endl;
5486 return 0;
5487 err:
5488 return -1;
5489 }
5490
5491 static int
st_check_db_nodes(ST_Con & c,int ignore_node_id=-1)5492 st_check_db_nodes(ST_Con& c, int ignore_node_id = -1)
5493 {
5494 chk1(c.restarter->get_status() == 0);
5495 int i;
5496 for (i = 1; i < MAX_NODES; i++) {
5497 const ndb_mgm_node_state& state = c.restarter->get_state(i);
5498 if (state.node_type == NDB_MGM_NODE_TYPE_NDB &&
5499 i != ignore_node_id) {
5500 chk2(state.node_status == NDB_MGM_NODE_STATUS_STARTED, " node:" << i);
5501 }
5502 }
5503 return 0;
5504 err:
5505 return -1;
5506 }
5507
5508 #if 0
5509 static int
5510 st_wait_db_node_up(ST_Con& c, int node_id)
5511 {
5512 int count = 0;
5513 int max_count = 30;
5514 int milli_sleep = 2000;
5515 while (count++ < max_count) {
5516 // get status and check that other db nodes have not crashed
5517 chk1(st_check_db_nodes(c, node_id) == 0);
5518
5519 const ndb_mgm_node_state& state = c.restarter->get_state(node_id);
5520 require(state.node_type == NDB_MGM_NODE_TYPE_NDB);
5521 if (state.node_status == NDB_MGM_NODE_STATUS_STARTED)
5522 break;
5523 g_info << "waiting count:" << count << "/" << max_count << endl;
5524 NdbSleep_MilliSleep(milli_sleep);
5525 }
5526 return 0;
5527 err:
5528 return -1;
5529 }
5530 #endif
5531
5532 // extra connection (separate API node)
5533
5534 static int
st_start_xcon(ST_Con & c)5535 st_start_xcon(ST_Con& c)
5536 {
5537 require(c.xcon == 0);
5538 g_info << "start extra connection" << endl;
5539
5540 do {
5541 int ret;
5542 Ndb_cluster_connection* xncc = new Ndb_cluster_connection;
5543 chk2((ret = xncc->connect(30, 1, 0)) == 0, "ret:" << ret);
5544 chk2((ret = xncc->wait_until_ready(30, 10)) == 0, "ret:" << ret);
5545 Ndb* xndb = new Ndb(xncc, c.dbname);
5546 chk1(xndb->init() == 0);
5547 chk1(xndb->waitUntilReady(30) == 0);
5548 // share restarter
5549 c.xcon = new ST_Con(xncc, xndb, c.restarter);
5550 // share objects
5551 c.xcon->tablist = c.tablist;
5552 c.xcon->tabcount = c.tabcount;
5553 c.xcon->is_xcon = true;
5554 } while (0);
5555 return 0;
5556 err:
5557 return -1;
5558 }
5559
5560 static int
st_stop_xcon(ST_Con & c)5561 st_stop_xcon(ST_Con& c)
5562 {
5563 require(c.xcon != 0);
5564 int node_id = c.xcon->node_id;
5565 g_info << "stop extra connection node_id:" << node_id << endl;
5566
5567 c.xcon->restarter = 0;
5568 c.xcon->tablist = 0;
5569 c.xcon->tabcount = 0;
5570 delete c.xcon;
5571 c.xcon = 0;
5572 int count = 0;
5573 while (1) {
5574 chk1(c.restarter->get_status() == 0);
5575 const ndb_mgm_node_state& state = c.restarter->get_state(node_id);
5576 require(state.node_type == NDB_MGM_NODE_TYPE_API);
5577 if (state.version == 0) // means "disconnected"
5578 break;
5579 g_info << "waiting count:" << ++count << endl;
5580 NdbSleep_MilliSleep(10 * count);
5581 }
5582 return 0;
5583 err:
5584 return -1;
5585 }
5586
5587 // error insert
5588
5589 struct ST_Errins {
5590 int value; // error value to insert
5591 int code; // ndb error code to expect
5592 int master; // insert on master / non-master (-1 = random)
5593 int node; // insert on node id
5594 const ST_Errins* list; // include another list
5595 bool ends; // end list
ST_ErrinsST_Errins5596 ST_Errins() :
5597 value(0), code(0), master(-1), node(0), list(0), ends(true)
5598 {}
ST_ErrinsST_Errins5599 ST_Errins(const ST_Errins* l) :
5600 value(0), code(0), master(-1), node(0), list(l), ends(false)
5601 {}
ST_ErrinsST_Errins5602 ST_Errins(int v, int c, int m = -1) :
5603 value(v), code(c), master(m), node(0), list(0), ends(false)
5604 {}
5605 };
5606
5607 static NdbOut&
operator <<(NdbOut & out,const ST_Errins & errins)5608 operator<<(NdbOut& out, const ST_Errins& errins)
5609 {
5610 out << "value:" << errins.value;
5611 out << " code:" << errins.code;
5612 out << " master:" << errins.master;
5613 out << " node:" << errins.node;
5614 return out;
5615 }
5616
5617 static ST_Errins
st_get_errins(ST_Con & c,const ST_Errins * list)5618 st_get_errins(ST_Con& c, const ST_Errins* list)
5619 {
5620 uint size = 0;
5621 while (!list[size++].ends)
5622 ;
5623 require(size > 1);
5624 uint n = urandom(size - 1);
5625 const ST_Errins& errins = list[n];
5626 if (errins.list == 0) {
5627 require(errins.value != 0);
5628 return errins;
5629 }
5630 return st_get_errins(c, errins.list);
5631 }
5632
5633 static int
st_do_errins(ST_Con & c,ST_Errins & errins)5634 st_do_errins(ST_Con& c, ST_Errins& errins)
5635 {
5636 require(errins.value != 0);
5637 if (c.numdbnodes < 2)
5638 errins.master = 1;
5639 else if (errins.master == -1)
5640 errins.master = randomly(1, 2);
5641 if (errins.master) {
5642 errins.node = c.restarter->getMasterNodeId();
5643 } else {
5644 uint rand = urandom(c.numdbnodes);
5645 errins.node = c.restarter->getRandomNotMasterNodeId(rand);
5646 }
5647 g_info << "errins: " << errins << endl;
5648 chk2(c.restarter->insertErrorInNode(errins.node, errins.value) == 0, errins);
5649 c.restarter->get_status(); // do sync call to ensure error has been inserted
5650 return 0;
5651 err:
5652 return -1;
5653 }
5654
5655 // debug aid
5656 #ifndef NDEBUG
5657 static const ST_Obj*
st_find_obj(const char * dbname,const char * name)5658 st_find_obj(const char* dbname, const char* name)
5659 {
5660 const ST_Obj* ret_objp = 0;
5661 int i;
5662 for (i = 0; i < (int)st_objlist.size(); i++) {
5663 const ST_Obj* objp = st_objlist[i];
5664 if (strcmp(objp->dbname, dbname) == 0 &&
5665 strcmp(objp->name, name) == 0) {
5666 require(ret_objp == 0);
5667 ret_objp = objp;
5668 }
5669 }
5670 return ret_objp;
5671 }
5672 #endif
5673
5674 #if 0
5675 static void
5676 st_print_obj(const char* dbname, const char* name, int line = 0)
5677 {
5678 const ST_Obj* objp = st_find_obj(dbname, name);
5679 g_info << name << ": by name:";
5680 if (objp != 0)
5681 g_info << " create:" << objp->create
5682 << " commit:" << objp->commit
5683 << " exists:" << objp->exists();
5684 else
5685 g_info << " not found";
5686 if (line != 0)
5687 g_info << " line:" << line;
5688 g_info << endl;
5689 }
5690 #endif
5691
5692 // set object state
5693
5694 static void
st_set_commit_obj(ST_Con & c,ST_Obj & obj)5695 st_set_commit_obj(ST_Con& c, ST_Obj& obj)
5696 {
5697 bool create_old = obj.create;
5698 bool commit_old = obj.commit;
5699 if (!c.tx_commit && !obj.commit)
5700 obj.create = !obj.create;
5701 obj.commit = true;
5702 if (create_old != obj.create || commit_old != obj.commit) {
5703 g_info << obj.name << ": set commit:"
5704 << " create:" << create_old << "->" << obj.create
5705 << " commit:" << commit_old << "->" << obj.commit << endl;
5706 }
5707 }
5708
5709 #if 0
5710 static void
5711 st_set_commit_trg(ST_Con& c, ST_Trg& trg)
5712 {
5713 st_set_commit_obj(c, trg);
5714 }
5715 #endif
5716
5717 static void
st_set_commit_ind(ST_Con & c,ST_Ind & ind)5718 st_set_commit_ind(ST_Con& c, ST_Ind& ind)
5719 {
5720 st_set_commit_obj(c, ind);
5721 int k;
5722 for (k = 0; k < ind.trgcount; k++) {
5723 ST_Trg& trg = ind.trg(k);
5724 st_set_commit_obj(c, trg);
5725 }
5726 }
5727
5728 static void
st_set_commit_tab(ST_Con & c,ST_Tab & tab)5729 st_set_commit_tab(ST_Con& c, ST_Tab& tab)
5730 {
5731 st_set_commit_obj(c, tab);
5732 int j;
5733 for (j = 0; j < tab.indcount; j++) {
5734 ST_Ind& ind = tab.ind(j);
5735 st_set_commit_ind(c, ind);
5736 }
5737 }
5738
5739 static void
st_set_commit_all(ST_Con & c)5740 st_set_commit_all(ST_Con& c)
5741 {
5742 int i;
5743 for (i = 0; i < c.tabcount; i++) {
5744 ST_Tab& tab = c.tab(i);
5745 st_set_commit_tab(c, tab);
5746 }
5747 }
5748
5749 static void
st_set_create_obj(ST_Con & c,ST_Obj & obj,bool create)5750 st_set_create_obj(ST_Con& c, ST_Obj& obj, bool create)
5751 {
5752 bool create_old = obj.create;
5753 bool commit_old = obj.commit;
5754 obj.create = create;
5755 obj.commit = !c.tx_on;
5756 if (create_old != obj.create || commit_old != obj.commit) {
5757 g_info << obj.name << ": set create:"
5758 << " create:" << create_old << "->" << obj.create
5759 << " commit:" << commit_old << "->" << obj.commit << endl;
5760 }
5761 }
5762
5763 static void
st_set_create_trg(ST_Con & c,ST_Trg & trg,bool create)5764 st_set_create_trg(ST_Con& c, ST_Trg& trg, bool create)
5765 {
5766 st_set_create_obj(c, trg, create);
5767 }
5768
5769 static void
st_set_create_ind(ST_Con & c,ST_Ind & ind,bool create)5770 st_set_create_ind(ST_Con& c, ST_Ind& ind, bool create)
5771 {
5772 st_set_create_obj(c, ind, create);
5773 int k;
5774 for (k = 0; k < ind.trgcount; k++) {
5775 ST_Trg& trg = ind.trg(k);
5776 st_set_create_trg(c, trg, create);
5777 }
5778 }
5779
5780 static void
st_set_create_tab(ST_Con & c,ST_Tab & tab,bool create)5781 st_set_create_tab(ST_Con& c, ST_Tab& tab, bool create)
5782 {
5783 st_set_create_obj(c, tab, create);
5784 int j;
5785 for (j = 0; j < tab.indcount; j++) {
5786 ST_Ind& ind = tab.ind(j);
5787 if (create == true)
5788 require(!ind.exists());
5789 else {
5790 if (ind.exists())
5791 st_set_create_ind(c, ind, false);
5792 }
5793 }
5794 }
5795
5796 // verify against database listing
5797
5798 static bool
st_known_type(const NdbDictionary::Dictionary::List::Element & element)5799 st_known_type(const NdbDictionary::Dictionary::List::Element& element)
5800 {
5801 return element.id != ST_Obj::Skip;
5802 }
5803
5804 static int
st_find_object(const NdbDictionary::Dictionary::List & list,NdbDictionary::Object::Type type,int id)5805 st_find_object(const NdbDictionary::Dictionary::List& list,
5806 NdbDictionary::Object::Type type, int id)
5807 {
5808 int n;
5809 for (n = 0; n < (int)list.count; n++) {
5810 const NdbDictionary::Dictionary::List::Element& element =
5811 list.elements[n];
5812 if (element.type == type && (int)element.id == id)
5813 return n;
5814 }
5815 return -1;
5816 }
5817
5818 // filter out irrelevant by whatever means (we need listObjects2)
5819 static int
st_list_objects(ST_Con & c,NdbDictionary::Dictionary::List & list)5820 st_list_objects(ST_Con& c, NdbDictionary::Dictionary::List& list)
5821 {
5822 g_info << "st_list_objects" << endl;
5823 int keep[256];
5824 memset(keep, 0, sizeof(keep));
5825 chk2(c.dic->listObjects(list) == 0, c.dic->getNdbError());
5826 int n;
5827 // tables
5828 for (n = 0; n < (int)list.count; n++) {
5829 const NdbDictionary::Dictionary::List::Element& element =
5830 list.elements[n];
5831 if (element.type == NdbDictionary::Object::UserTable) {
5832 int i;
5833 for (i = 0; i < c.tabcount; i++) {
5834 const ST_Tab& tab = c.tab(i);
5835 if (strcmp(element.name, tab.name) == 0)
5836 keep[n]++;
5837 }
5838 }
5839 require(keep[n] <= 1);
5840 }
5841 // indexes
5842 for (n = 0; n < (int)list.count; n++) {
5843 const NdbDictionary::Dictionary::List::Element& element =
5844 list.elements[n];
5845 if (element.type == NdbDictionary::Object::UniqueHashIndex ||
5846 element.type == NdbDictionary::Object::OrderedIndex) {
5847 int i, j;
5848 for (i = 0; i < c.tabcount; i++) {
5849 const ST_Tab& tab = c.tab(i);
5850 for (j = 0; j < tab.indcount; j++) {
5851 const ST_Ind& ind = tab.ind(j);
5852 if (strcmp(element.name, ind.name) == 0)
5853 keep[n]++;
5854 }
5855 }
5856 }
5857 require(keep[n] <= 1);
5858 }
5859 // triggers
5860 for (n = 0; n < (int)list.count; n++) {
5861 const NdbDictionary::Dictionary::List::Element& element =
5862 list.elements[n];
5863 if (element.type == NdbDictionary::Object::HashIndexTrigger) {
5864 int id, n2;
5865 chk2(sscanf(element.name, "NDB$INDEX_%d_UI", &id) == 1,
5866 element.name);
5867 n2 = st_find_object(list, NdbDictionary::Object::UniqueHashIndex, id);
5868 chk2(n2 >= 0, element.name);
5869 if (keep[n2])
5870 keep[n]++;
5871 }
5872 if (element.type == NdbDictionary::Object::IndexTrigger) {
5873 int id, n2;
5874 chk2(sscanf(element.name, "NDB$INDEX_%d_CUSTOM", &id) == 1,
5875 element.name);
5876 n2 = st_find_object(list, NdbDictionary::Object::OrderedIndex, id);
5877 chk2(n2 >= 0, element.name);
5878 if (keep[n2])
5879 keep[n]++;
5880 }
5881 require(keep[n] <= 1);
5882 }
5883 // mark ignored
5884 for (n = 0; n < (int)list.count; n++) {
5885 NdbDictionary::Dictionary::List::Element& element =
5886 list.elements[n];
5887 g_info << "id=" << element.id << " type=" << element.type
5888 << " name=" << element.name << " keep=" << keep[n] << endl;
5889 if (!keep[n]) {
5890 require(element.id != ST_Obj::Skip);
5891 element.id = ST_Obj::Skip;
5892 }
5893 }
5894 return 0;
5895 err:
5896 return -1;
5897 }
5898
5899 static bool
st_match_obj(const ST_Obj & obj,const NdbDictionary::Dictionary::List::Element & element)5900 st_match_obj(const ST_Obj& obj,
5901 const NdbDictionary::Dictionary::List::Element& element)
5902 {
5903 int veryverbose = 0;
5904 if (veryverbose) {
5905 g_info
5906 << "match:"
5907 << " " << obj.type << "-" << element.type
5908 << " " << obj.dbname << "-" << element.database
5909 << " " << obj.realname() << "-" << element.name << endl;
5910 }
5911 return
5912 obj.type == element.type &&
5913 strcmp(obj.dbname, element.database) == 0 &&
5914 strcmp(obj.realname(), element.name) == 0;
5915 }
5916
5917 static int // check state
st_verify_obj(const ST_Obj & obj,const NdbDictionary::Dictionary::List::Element & element)5918 st_verify_obj(const ST_Obj& obj,
5919 const NdbDictionary::Dictionary::List::Element& element)
5920 {
5921 chk2(obj.exists(), obj.name);
5922
5923 if (obj.commit)
5924 chk2(element.state == NdbDictionary::Object::StateOnline, obj.name);
5925
5926 // other states are inconsistent
5927
5928 else if (obj.create) {
5929 if (obj.is_table() || obj.is_index())
5930 chk2(element.state == NdbDictionary::Object::StateBuilding, obj.name);
5931 if (obj.is_trigger())
5932 chk2(element.state == NdbDictionary::Object::StateBuilding, obj.name);
5933 }
5934 else {
5935 if (obj.is_trigger())
5936 chk2(element.state == NdbDictionary::Object::StateOnline, obj.name);
5937 if (obj.is_table() || obj.is_index())
5938 chk2(element.state == NdbDictionary::Object::StateDropping, obj.name);
5939 }
5940 return 0;
5941 err:
5942 return -1;
5943 }
5944
5945 static int // find on list
st_verify_obj(const ST_Obj & obj,const NdbDictionary::Dictionary::List & list)5946 st_verify_obj(const ST_Obj& obj,
5947 const NdbDictionary::Dictionary::List& list)
5948 {
5949 int found = 0;
5950 int n;
5951 for (n = 0; n < (int)list.count; n++) {
5952 const NdbDictionary::Dictionary::List::Element& element =
5953 list.elements[n];
5954 if (!st_known_type(element))
5955 continue;
5956 if (st_match_obj(obj, element)) {
5957 chk1(st_verify_obj(obj, element) == 0);
5958 found += 1;
5959 }
5960 }
5961 if (obj.exists())
5962 chk2(found == 1, obj.name);
5963 else
5964 chk2(found == 0, obj.name);
5965 return 0;
5966 err:
5967 return -1;
5968 }
5969
5970 static int // possible match
st_verify_obj(const ST_Obj & obj,const NdbDictionary::Dictionary::List::Element & element,int & found)5971 st_verify_obj(const ST_Obj& obj,
5972 const NdbDictionary::Dictionary::List::Element& element,
5973 int& found)
5974 {
5975 if (obj.exists()) {
5976 if (st_match_obj(obj, element)) {
5977 chk1(st_verify_obj(obj, element) == 0);
5978 found += 1;
5979 }
5980 }
5981 else {
5982 chk2(st_match_obj(obj, element) == false, obj.name);
5983 }
5984 return 0;
5985 err:
5986 return -1;
5987 }
5988
5989 static int
st_verify_list(ST_Con & c)5990 st_verify_list(ST_Con& c)
5991 {
5992 NdbDictionary::Dictionary::List list;
5993 chk1(st_list_objects(c, list) == 0);
5994 int i, j, k, n;
5995 // us vs list
5996 for (i = 0; i < c.tabcount; i++) {
5997 const ST_Tab& tab = c.tab(i);
5998 chk1(st_verify_obj(tab, list) == 0);
5999 for (j = 0; j < tab.indcount; j++) {
6000 const ST_Ind& ind = tab.ind(j);
6001 chk1(st_verify_obj(ind, list) == 0);
6002 for (k = 0; k < ind.trgcount; k++) {
6003 const ST_Trg& trg = ind.trg(k);
6004 chk1(st_verify_obj(trg, list) == 0);
6005 }
6006 }
6007 }
6008 // list vs us
6009 for (n = 0; n < (int)list.count; n++) {
6010 const NdbDictionary::Dictionary::List::Element& element =
6011 list.elements[n];
6012 if (!st_known_type(element))
6013 continue;
6014 int found = 0;
6015 for (i = 0; i < c.tabcount; i++) {
6016 const ST_Tab& tab = c.tab(i);
6017 chk1(st_verify_obj(tab, element, found) == 0);
6018 for (j = 0; j < tab.indcount; j++) {
6019 const ST_Ind& ind = tab.ind(j);
6020 chk1(st_verify_obj(ind, element, found) == 0);
6021 for (k = 0; k < ind.trgcount; k++) {
6022 const ST_Trg& trg = ind.trg(k);
6023 chk1(st_verify_obj(trg, element, found) == 0);
6024 }
6025 }
6026 }
6027 const char* dot = element.database[0] != 0 ? "." : "";
6028 chk2(found == 1, element.database << dot << element.name);
6029 }
6030 return 0;
6031 err:
6032 return -1;
6033 }
6034
6035 // wait for DICT to finish current trans
6036
6037 static int
st_wait_idle(ST_Con & c)6038 st_wait_idle(ST_Con& c)
6039 {
6040 // todo: use try-lock when available
6041 g_info << "st_wait_idle" << endl;
6042 int count = 0;
6043 int max_count = 60;
6044 int milli_sleep = 1000;
6045 while (count++ < max_count) {
6046 NdbDictionary::Dictionary::List list;
6047 chk1(st_list_objects(c, list) == 0);
6048 bool ok = true;
6049 int n;
6050 for (n = 0; n < (int)list.count; n++) {
6051 const NdbDictionary::Dictionary::List::Element& element =
6052 list.elements[n];
6053 if (!st_known_type(element))
6054 continue;
6055 if (element.state != NdbDictionary::Object::StateOnline) {
6056 ok = false;
6057 break;
6058 }
6059 }
6060 if (ok)
6061 return 0;
6062 g_info << "waiting count:" << count << "/" << max_count << endl;
6063 NdbSleep_MilliSleep(milli_sleep);
6064 }
6065 g_err << "st_wait_idle: objects did not become Online" << endl;
6066 err:
6067 return -1;
6068 }
6069
6070 // ndb dict comparisons (non-retrieved vs retrieved)
6071
6072 static int
st_equal_column(const NdbDictionary::Column & c1,const NdbDictionary::Column & c2,NdbDictionary::Object::Type type)6073 st_equal_column(const NdbDictionary::Column& c1,
6074 const NdbDictionary::Column& c2,
6075 NdbDictionary::Object::Type type)
6076 {
6077 chk1(strcmp(c1.getName(), c2.getName()) == 0);
6078 chk1(c1.getNullable() == c2.getNullable());
6079 if (type == NdbDictionary::Object::UserTable) {
6080 chk1(c1.getPrimaryKey() == c2.getPrimaryKey());
6081 }
6082 if (0) { // should fix
6083 chk1(c1.getColumnNo() == c2.getColumnNo());
6084 }
6085 chk1(c1.getType() == c2.getType());
6086 if (c1.getType() == NdbDictionary::Column::Decimal ||
6087 c1.getType() == NdbDictionary::Column::Decimalunsigned) {
6088 chk1(c1.getPrecision() == c2.getPrecision());
6089 chk1(c1.getScale() == c2.getScale());
6090 }
6091 if (c1.getType() != NdbDictionary::Column::Blob &&
6092 c1.getType() != NdbDictionary::Column::Text) {
6093 chk1(c1.getLength() == c2.getLength());
6094 } else {
6095 chk1(c1.getInlineSize() == c2.getInlineSize());
6096 chk1(c1.getPartSize() == c2.getPartSize());
6097 chk1(c1.getStripeSize() == c2.getStripeSize());
6098 }
6099 chk1(c1.getCharset() == c2.getCharset());
6100 if (type == NdbDictionary::Object::UserTable) {
6101 chk1(c1.getPartitionKey() == c2.getPartitionKey());
6102 }
6103 chk1(c1.getArrayType() == c2.getArrayType());
6104 chk1(c1.getStorageType() == c2.getStorageType());
6105 chk1(c1.getDynamic() == c2.getDynamic());
6106 chk1(c1.getAutoIncrement() == c2.getAutoIncrement());
6107 return 0;
6108 err:
6109 return -1;
6110 }
6111
6112 static int
st_equal_table(const NdbDictionary::Table & t1,const NdbDictionary::Table & t2)6113 st_equal_table(const NdbDictionary::Table& t1, const NdbDictionary::Table& t2)
6114 {
6115 chk1(strcmp(t1.getName(), t2.getName()) == 0);
6116 chk1(t1.getLogging() == t2.getLogging());
6117 chk1(t1.getFragmentType() == t2.getFragmentType());
6118 chk1(t1.getKValue() == t2.getKValue());
6119 chk1(t1.getMinLoadFactor() == t2.getMinLoadFactor());
6120 chk1(t1.getMaxLoadFactor() == t2.getMaxLoadFactor());
6121 chk1(t1.getNoOfColumns() == t2.getNoOfColumns());
6122 /*
6123 * There is no method to get type of table...
6124 * On the other hand SystemTable/UserTable should be just Table
6125 * and "System" should be an independent property.
6126 */
6127 NdbDictionary::Object::Type type;
6128 type = NdbDictionary::Object::UserTable;
6129 int n;
6130 for (n = 0; n < t1.getNoOfColumns(); n++) {
6131 const NdbDictionary::Column* c1 = t1.getColumn(n);
6132 const NdbDictionary::Column* c2 = t2.getColumn(n);
6133 require(c1 != 0 && c2 != 0);
6134 chk2(st_equal_column(*c1, *c2, type) == 0, "col:" << n);
6135 }
6136 chk1(t1.getNoOfPrimaryKeys() == t2.getNoOfPrimaryKeys());
6137 chk1(t1.getTemporary() == t2.getTemporary());
6138 chk1(t1.getForceVarPart() == t2.getForceVarPart());
6139 return 0;
6140 err:
6141 return -1;
6142 }
6143
6144 static int
st_equal_index(const NdbDictionary::Index & i1,const NdbDictionary::Index & i2)6145 st_equal_index(const NdbDictionary::Index& i1, const NdbDictionary::Index& i2)
6146 {
6147 chk1(strcmp(i1.getName(), i2.getName()) == 0);
6148 require(i1.getTable() != 0 && i2.getTable() != 0);
6149 chk1(strcmp(i1.getTable(), i2.getTable()) == 0);
6150 chk1(i1.getNoOfColumns() == i2.getNoOfColumns());
6151 chk1(i1.getType() == i2.getType());
6152 NdbDictionary::Object::Type type;
6153 type = (NdbDictionary::Object::Type)i1.getType();
6154 int n;
6155 for (n = 0; n < (int)i1.getNoOfColumns(); n++) {
6156 const NdbDictionary::Column* c1 = i1.getColumn(n);
6157 const NdbDictionary::Column* c2 = i2.getColumn(n);
6158 require(c1 != 0 && c2 != 0);
6159 chk2(st_equal_column(*c1, *c2, type) == 0, "col:" << n);
6160 }
6161 chk1(i1.getLogging() == i2.getLogging());
6162 chk1(i1.getTemporary() == i2.getTemporary());
6163 return 0;
6164 err:
6165 return -1;
6166 }
6167
6168 // verify against database objects (hits all nodes randomly)
6169
6170 static int
st_verify_table(ST_Con & c,ST_Tab & tab)6171 st_verify_table(ST_Con& c, ST_Tab& tab)
6172 {
6173 c.dic->invalidateTable(tab.name);
6174 const NdbDictionary::Table* pTab = c.dic->getTable(tab.name);
6175 tab.tab_r = pTab;
6176 if (tab.exists()) {
6177 chk2(pTab != 0, c.dic->getNdbError());
6178 chk1(st_equal_table(*tab.tab, *pTab) == 0);
6179 tab.id = pTab->getObjectId();
6180 g_info << tab << ": verified exists tx_on:" << c.tx_on << endl;
6181 } else {
6182 chk2(pTab == 0, tab);
6183 chk2(c.dic->getNdbError().code == 723, c.dic->getNdbError());
6184 g_info << tab << ": verified not exists tx_on:" << c.tx_on << endl;
6185 tab.id = -1;
6186 }
6187 return 0;
6188 err:
6189 return -1;
6190 }
6191
6192 static int
st_verify_index(ST_Con & c,ST_Ind & ind)6193 st_verify_index(ST_Con& c, ST_Ind& ind)
6194 {
6195 ST_Tab& tab = *ind.tab;
6196 c.dic->invalidateIndex(ind.name, tab.name);
6197 const NdbDictionary::Index* pInd = c.dic->getIndex(ind.name, tab.name);
6198 ind.ind_r = pInd;
6199 if (ind.exists()) {
6200 chk2(pInd != 0, c.dic->getNdbError());
6201 chk1(st_equal_index(*ind.ind, *pInd) == 0);
6202 ind.id = pInd->getObjectId();
6203 g_info << ind << ": verified exists tx_on:" << c.tx_on << endl;
6204 } else {
6205 chk2(pInd == 0, ind);
6206 chk2(c.dic->getNdbError().code == 4243, c.dic->getNdbError());
6207 g_info << ind << ": verified not exists tx_on:" << c.tx_on << endl;
6208 ind.id = -1;
6209 }
6210 return 0;
6211 err:
6212 return -1;
6213 }
6214
6215 static int
st_verify_all(ST_Con & c)6216 st_verify_all(ST_Con& c)
6217 {
6218 chk1(st_verify_list(c) == 0);
6219 int i, j;
6220 for (i = 0; i < c.tabcount; i++) {
6221 ST_Tab& tab = c.tab(i);
6222 chk1(st_verify_table(c, tab) == 0);
6223 for (j = 0; j < tab.indcount; j++) {
6224 ST_Ind& ind = tab.ind(j);
6225 chk1(st_verify_index(c, ind) == 0);
6226 }
6227 }
6228 return 0;
6229 err:
6230 return -1;
6231 }
6232
6233 // subroutines
6234
6235 static const uint
6236 ST_CommitFlag = 0;
6237
6238 static const uint
6239 ST_AbortFlag = NdbDictionary::Dictionary::SchemaTransAbort;
6240
6241 static const uint
6242 ST_BackgroundFlag = NdbDictionary::Dictionary::SchemaTransBackground;
6243
6244 struct ST_Retry {
6245 int max_tries;
6246 int sleep_ms;
6247 };
6248
6249 static int
st_begin_trans(ST_Con & c,int code=0)6250 st_begin_trans(ST_Con& c, int code = 0)
6251 {
6252 g_info << "begin trans";
6253 if (code == 0) {
6254 g_info << endl;
6255 chk2(c.dic->beginSchemaTrans() == 0, c.dic->getNdbError());
6256 chk1(c.dic->hasSchemaTrans() == true);
6257 c.tx_on = true;
6258 } else {
6259 g_info << " - expect error " << code << endl;
6260 chk1(c.dic->beginSchemaTrans() == -1);
6261 const NdbError& error = c.dic->getNdbError();
6262 chk2(error.code == code, error << " wanted: " << code);
6263 }
6264 return 0;
6265 err:
6266 return -1;
6267 }
6268
6269 static int
st_begin_trans(ST_Con & c,ST_Errins errins)6270 st_begin_trans(ST_Con& c, ST_Errins errins)
6271 {
6272 require(errins.code != 0);
6273 chk1(st_do_errins(c, errins) == 0);
6274 chk1(st_begin_trans(c, errins.code) == 0);
6275 return 0;
6276 err:
6277 return -1;
6278 }
6279
6280 static int
st_begin_trans(ST_Con & c,ST_Retry retry)6281 st_begin_trans(ST_Con& c, ST_Retry retry)
6282 {
6283 int tries = 0;
6284 while (++tries <= retry.max_tries) {
6285 int code = 0;
6286 if (c.dic->beginSchemaTrans() == -1) {
6287 code = c.dic->getNdbError().code;
6288 require(code != 0);
6289 }
6290 chk2(code == 0 || code == 780 || code == 701, c.dic->getNdbError());
6291 if (code == 0) {
6292 chk1(c.dic->hasSchemaTrans() == true);
6293 g_info << "begin trans at try " << tries << endl;
6294 break;
6295 }
6296 NdbSleep_MilliSleep(retry.sleep_ms);
6297 }
6298 return 0;
6299 err:
6300 return -1;
6301 }
6302
6303 static int
st_end_trans(ST_Con & c,uint flags)6304 st_end_trans(ST_Con& c, uint flags)
6305 {
6306 g_info << "end trans flags:" << hex << flags << endl;
6307 int res= c.dic->endSchemaTrans(flags);
6308 g_info << "end trans result:" << res << endl;
6309 chk2(res == 0, c.dic->getNdbError());
6310 c.tx_on = false;
6311 c.tx_commit = !(flags & ST_AbortFlag);
6312 st_set_commit_all(c);
6313 return 0;
6314 err:
6315 return -1;
6316 }
6317
6318 static int
st_end_trans_aborted(ST_Con & c,uint flags)6319 st_end_trans_aborted(ST_Con& c, uint flags)
6320 {
6321 g_info << "end trans flags:" << hex << flags << endl;
6322 int res= c.dic->endSchemaTrans(flags);
6323 g_info << "end trans result:" << res << endl;
6324 if (flags & ST_AbortFlag)
6325 chk1(res == 0);
6326 else
6327 chk1(res != 0);
6328 c.tx_on = false;
6329 c.tx_commit = (flags & ST_AbortFlag);
6330 return 0;
6331 err:
6332 return -1;
6333 }
6334
6335 static int
st_end_trans(ST_Con & c,ST_Errins errins,uint flags)6336 st_end_trans(ST_Con& c, ST_Errins errins, uint flags)
6337 {
6338 chk1(st_do_errins(c, errins) == 0);
6339 chk1(st_end_trans(c, flags) == 0);
6340 return 0;
6341 err:
6342 return -1;
6343 }
6344
6345 static int
st_end_trans_aborted(ST_Con & c,ST_Errins errins,uint flags)6346 st_end_trans_aborted(ST_Con& c, ST_Errins errins, uint flags)
6347 {
6348 chk1(st_do_errins(c, errins) == 0);
6349 chk1(st_end_trans_aborted(c, flags) == 0);
6350 return 0;
6351 err:
6352 return -1;
6353 }
6354
6355 static int
st_load_table(ST_Con & c,ST_Tab & tab,int rows=1000)6356 st_load_table(ST_Con& c, ST_Tab& tab, int rows = 1000)
6357 {
6358 g_info << tab.name << ": load data rows:" << rows << endl;
6359 chk1(tab.tab_r != NULL);
6360 {
6361 HugoTransactions ht(*tab.tab_r);
6362 chk1(ht.loadTable(c.ndb, rows) == 0);
6363 }
6364 return 0;
6365 err:
6366 return -1;
6367 }
6368
6369 static int
st_create_table(ST_Con & c,ST_Tab & tab,int code=0)6370 st_create_table(ST_Con& c, ST_Tab& tab, int code = 0)
6371 {
6372 g_info << tab.name << ": create table";
6373 if (code == 0) {
6374 g_info << endl;
6375 require(!tab.exists());
6376 chk2(c.dic->createTable(*tab.tab) == 0, c.dic->getNdbError());
6377 g_info << tab.name << ": created" << endl;
6378 st_set_create_tab(c, tab, true);
6379 }
6380 else {
6381 g_info << " - expect error " << code << endl;
6382 chk1(c.dic->createTable(*tab.tab) == -1);
6383 const NdbError& error = c.dic->getNdbError();
6384 chk2(error.code == code, error << " wanted: " << code);
6385 }
6386 chk1(st_verify_table(c, tab) == 0);
6387 return 0;
6388 err:
6389 return -1;
6390 }
6391
6392 static int
st_create_table(ST_Con & c,ST_Tab & tab,ST_Errins errins)6393 st_create_table(ST_Con& c, ST_Tab& tab, ST_Errins errins)
6394 {
6395 require(errins.code != 0);
6396 chk1(st_do_errins(c, errins) == 0);
6397 chk1(st_create_table(c, tab, errins.code) == 0);
6398 return 0;
6399 err:
6400 return -1;
6401 }
6402
6403 static int
st_drop_table(ST_Con & c,ST_Tab & tab,int code=0)6404 st_drop_table(ST_Con& c, ST_Tab& tab, int code = 0)
6405 {
6406 g_info << tab.name << ": drop table";
6407 if (code == 0) {
6408 g_info << endl;
6409 require(tab.exists());
6410 c.dic->invalidateTable(tab.name);
6411 chk2(c.dic->dropTable(tab.name) == 0, c.dic->getNdbError());
6412 g_info << tab.name << ": dropped" << endl;
6413 st_set_create_tab(c, tab, false);
6414 } else {
6415 g_info << " - expect error " << code << endl;
6416 c.dic->invalidateTable(tab.name);
6417 chk1(c.dic->dropTable(tab.name) == -1);
6418 const NdbError& error = c.dic->getNdbError();
6419 chk2(error.code == code, error << " wanted: " << code);
6420 }
6421 chk1(st_verify_table(c, tab) == 0);
6422 return 0;
6423 err:
6424 return -1;
6425 }
6426
6427 static int
st_drop_table(ST_Con & c,ST_Tab & tab,ST_Errins errins)6428 st_drop_table(ST_Con& c, ST_Tab& tab, ST_Errins errins)
6429 {
6430 require(errins.code != 0);
6431 chk1(st_do_errins(c, errins) == 0);
6432 chk1(st_drop_table(c, tab, errins.code) == 0);
6433 return 0;
6434 err:
6435 return -1;
6436 }
6437
6438 static int
st_create_index(ST_Con & c,ST_Ind & ind,int code=0)6439 st_create_index(ST_Con& c, ST_Ind& ind, int code = 0)
6440 {
6441 ST_Tab& tab = *ind.tab;
6442 g_info << ind.name << ": create index on "
6443 << tab.name << "(" << ind.colnames.c_str() << ")";
6444 if (code == 0) {
6445 g_info << endl;
6446 require(!ind.exists());
6447 chk2(c.dic->createIndex(*ind.ind, *tab.tab_r) == 0, c.dic->getNdbError());
6448 st_set_create_ind(c, ind, true);
6449 g_info << ind.name << ": created" << endl;
6450 } else {
6451 g_info << " - expect error " << code << endl;
6452 chk1(c.dic->createIndex(*ind.ind, *tab.tab_r) == -1);
6453 const NdbError& error = c.dic->getNdbError();
6454 chk2(error.code == code, error << " wanted: " << code);
6455 }
6456 chk1(st_verify_index(c, ind) == 0);
6457 return 0;
6458 err:
6459 return -1;
6460 }
6461
6462 static int
st_create_index(ST_Con & c,ST_Ind & ind,ST_Errins errins)6463 st_create_index(ST_Con& c, ST_Ind& ind, ST_Errins errins)
6464 {
6465 require(errins.code != 0);
6466 chk1(st_do_errins(c, errins) == 0);
6467 chk1(st_create_index(c, ind, errins.code) == 0);
6468 return 0;
6469 err:
6470 return -1;
6471 }
6472
6473 static int
st_drop_index(ST_Con & c,ST_Ind & ind,int code=0)6474 st_drop_index(ST_Con& c, ST_Ind& ind, int code = 0)
6475 {
6476 ST_Tab& tab = *ind.tab;
6477 g_info << ind.name << ": drop index";
6478 if (code == 0) {
6479 g_info << endl;
6480 require(ind.exists());
6481 c.dic->invalidateIndex(ind.name, tab.name);
6482 chk2(c.dic->dropIndex(ind.name, tab.name) == 0, c.dic->getNdbError());
6483 g_info << ind.name << ": dropped" << endl;
6484 st_set_create_ind(c, ind, false);
6485 } else {
6486 g_info << " expect error " << code << endl;
6487 c.dic->invalidateIndex(ind.name, tab.name);
6488 chk1(c.dic->dropIndex(ind.name, tab.name) == -1);
6489 const NdbError& error = c.dic->getNdbError();
6490 chk2(error.code == code, error << " wanted: " << code);
6491 }
6492 chk1(st_verify_index(c, ind) == 0);
6493 return 0;
6494 err:
6495 return -1;
6496 }
6497
6498 static int
st_drop_index(ST_Con & c,ST_Ind & ind,ST_Errins errins)6499 st_drop_index(ST_Con& c, ST_Ind& ind, ST_Errins errins)
6500 {
6501 require(errins.code != 0);
6502 chk1(st_do_errins(c, errins) == 0);
6503 chk1(st_drop_index(c, ind, errins.code) == 0);
6504 return 0;
6505 err:
6506 return -1;
6507 }
6508
6509 static int
st_create_table_index(ST_Con & c,ST_Tab & tab)6510 st_create_table_index(ST_Con& c, ST_Tab& tab)
6511 {
6512 chk1(st_create_table(c, tab) == 0);
6513 int j;
6514 for (j = 0; j < tab.indcount; j++) {
6515 ST_Ind& ind = tab.ind(j);
6516 chk1(st_create_index(c, ind) == 0);
6517 }
6518 return 0;
6519 err:
6520 return -1;
6521 }
6522
6523 // drop all
6524
6525 static int
st_drop_test_tables(ST_Con & c)6526 st_drop_test_tables(ST_Con& c)
6527 {
6528 g_info << "st_drop_test_tables" << endl;
6529 int i;
6530 for (i = 0; i < c.tabcount; i++) {
6531 ST_Tab& tab = c.tab(i);
6532 if (tab.exists())
6533 chk1(st_drop_table(c, tab) == 0);
6534 }
6535 return 0;
6536 err:
6537 return -1;
6538 }
6539
6540 // error insert values
6541
6542 static const ST_Errins
6543 st_errins_begin_trans[] = {
6544 ST_Errins(6101, 780),
6545 ST_Errins()
6546 };
6547
6548 static const ST_Errins
6549 st_errins_end_trans1[] = {
6550 ST_Errins(ERR_INSERT_MASTER_FAILURE1, 0, 1),
6551 ST_Errins()
6552 };
6553
6554 static const ST_Errins
6555 st_errins_end_trans2[] = {
6556 ST_Errins(ERR_INSERT_MASTER_FAILURE2, 0, 1),
6557 ST_Errins()
6558 };
6559
6560 static const ST_Errins
6561 st_errins_end_trans3[] = {
6562 ST_Errins(ERR_INSERT_MASTER_FAILURE3, 0, 1),
6563 ST_Errins()
6564 };
6565
6566 static const ST_Errins
6567 st_errins_table[] = {
6568 ST_Errins(6111, 783),
6569 ST_Errins(6121, 9121),
6570 //ST_Errins(6131, 9131),
6571 ST_Errins()
6572 };
6573
6574 static ST_Errins
6575 st_errins_index[] = {
6576 ST_Errins(st_errins_table),
6577 ST_Errins(6112, 783),
6578 ST_Errins(6113, 783),
6579 ST_Errins(6114, 783),
6580 ST_Errins(6122, 9122),
6581 ST_Errins(6123, 9123),
6582 ST_Errins(6124, 9124),
6583 //ST_Errins(6132, 9131),
6584 //ST_Errins(6133, 9131),
6585 //ST_Errins(6134, 9131),
6586 //ST_Errins(6135, 9131),
6587 ST_Errins()
6588 };
6589
6590 static ST_Errins
6591 st_errins_index_create[] = {
6592 ST_Errins(st_errins_index),
6593 ST_Errins(6116, 783),
6594 ST_Errins(6126, 9126),
6595 //ST_Errins(6136, 9136),
6596 ST_Errins()
6597 };
6598
6599 static ST_Errins
6600 st_errins_index_drop[] = {
6601 ST_Errins(st_errins_index),
6602 ST_Errins()
6603 };
6604
6605 // specific test cases
6606
6607 static int
st_test_create(ST_Con & c,int arg=-1)6608 st_test_create(ST_Con& c, int arg = -1)
6609 {
6610 int do_abort = (arg == 1);
6611 int i;
6612 chk1(st_begin_trans(c) == 0);
6613 for (i = 0; i < c.tabcount; i++) {
6614 ST_Tab& tab = c.tab(i);
6615 chk1(st_create_table_index(c, tab) == 0);
6616 }
6617 chk1(st_verify_list(c) == 0);
6618 if (!do_abort)
6619 chk1(st_end_trans(c, 0) == 0);
6620 else
6621 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6622 chk1(st_verify_list(c) == 0);
6623 if (!do_abort)
6624 chk1(st_drop_test_tables(c) == 0);
6625 return NDBT_OK;
6626 err:
6627 return NDBT_FAILED;
6628 }
6629
6630 static int
st_test_drop(ST_Con & c,int arg=-1)6631 st_test_drop(ST_Con& c, int arg = -1)
6632 {
6633 int do_abort = (arg == 1);
6634 int i;
6635 for (i = 0; i < c.tabcount; i++) {
6636 ST_Tab& tab = c.tab(i);
6637 chk1(st_create_table_index(c, tab) == 0);
6638 }
6639 chk1(st_begin_trans(c) == 0);
6640 for (i = 0; i < c.tabcount; i++) {
6641 ST_Tab& tab = c.tab(i);
6642 chk1(st_drop_table(c, tab) == 0);
6643 }
6644 chk1(st_verify_list(c) == 0);
6645 if (!do_abort)
6646 chk1(st_end_trans(c, 0) == 0);
6647 else
6648 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6649 chk1(st_verify_list(c) == 0);
6650 return NDBT_OK;
6651 err:
6652 return NDBT_FAILED;
6653 }
6654
6655 static int
st_test_rollback_create_table(ST_Con & c,int arg=-1)6656 st_test_rollback_create_table(ST_Con& c, int arg = -1)
6657 {
6658 int i;
6659 chk1(st_begin_trans(c) == 0);
6660 for (i = 0; i < c.tabcount; i++) {
6661 ST_Tab& tab = c.tab(i);
6662 if (i % 2 == 0) {
6663 ST_Errins errins(6111, 783, 0); // fail CTa seize op
6664 chk1(st_create_table(c, tab, errins) == 0);
6665 } else {
6666 chk1(st_create_table(c, tab) == 0);
6667 }
6668 }
6669 chk1(st_end_trans(c, 0) == 0);
6670 chk1(st_verify_list(c) == 0);
6671 for (i = 0; i < c.tabcount; i++) {
6672 ST_Tab& tab = c.tab(i);
6673 if (i % 2 == 0)
6674 require(!tab.exists());
6675 else {
6676 require(tab.exists());
6677 chk1(st_drop_table(c, tab) == 0);
6678 }
6679 }
6680 return NDBT_OK;
6681 err:
6682 return NDBT_FAILED;
6683 }
6684
6685 static int
st_test_rollback_drop_table(ST_Con & c,int arg=-1)6686 st_test_rollback_drop_table(ST_Con& c, int arg = -1)
6687 {
6688 int i;
6689 for (i = 0; i < c.tabcount; i++) {
6690 ST_Tab& tab = c.tab(i);
6691 chk1(st_create_table(c, tab) == 0);
6692 }
6693 chk1(st_begin_trans(c) == 0);
6694 for (i = 0; i < c.tabcount; i++) {
6695 ST_Tab& tab = c.tab(i);
6696 if (i % 2 == 0) {
6697 ST_Errins errins(6111, 783, 0); // fail DTa seize op
6698 chk1(st_drop_table(c, tab, errins) == 0);
6699 } else {
6700 chk1(st_drop_table(c, tab) == 0);
6701 }
6702 }
6703 chk1(st_end_trans(c, 0) == 0);
6704 chk1(st_verify_list(c) == 0);
6705 for (i = 0; i < c.tabcount; i++) {
6706 ST_Tab& tab = c.tab(i);
6707 if (i % 2 == 0) {
6708 require(tab.exists());
6709 chk1(st_drop_table(c, tab) == 0);
6710 } else {
6711 require(!tab.exists());
6712 }
6713 }
6714 return NDBT_OK;
6715 err:
6716 return NDBT_FAILED;
6717 }
6718
6719 static int
st_test_rollback_create_index(ST_Con & c,int arg=-1)6720 st_test_rollback_create_index(ST_Con& c, int arg = -1)
6721 {
6722 int i, j;
6723 for (i = 0; i < c.tabcount; i++) {
6724 ST_Tab& tab = c.tab(i);
6725 if (tab.indcount < 1)
6726 continue;
6727 chk1(st_create_table(c, tab) == 0);
6728 chk1(st_begin_trans(c) == 0);
6729 for (j = 0; j < tab.indcount; j++) {
6730 ST_Ind& ind = tab.ind(j);
6731 if (j % 2 == 0) {
6732 ST_Errins errins(6116, 783, 0); // fail BIn seize op
6733 chk1(st_create_index(c, ind, errins) == 0);
6734 } else {
6735 chk1(st_create_index(c, ind) == 0);
6736 }
6737 }
6738 chk1(st_end_trans(c, 0) == 0);
6739 chk1(st_verify_list(c) == 0);
6740 for (j = 0; j < tab.indcount; j++) {
6741 ST_Ind& ind = tab.ind(j);
6742 if (j % 2 == 0)
6743 require(!ind.exists());
6744 else {
6745 require(ind.exists());
6746 chk1(st_drop_index(c, ind) == 0);
6747 }
6748 }
6749 chk1(st_drop_table(c, tab) == 0);
6750 }
6751 return NDBT_OK;
6752 err:
6753 return NDBT_FAILED;
6754 }
6755
6756 static int
st_test_rollback_drop_index(ST_Con & c,int arg=-1)6757 st_test_rollback_drop_index(ST_Con& c, int arg = -1)
6758 {
6759 int i, j;
6760 for (i = 0; i < c.tabcount; i++) {
6761 ST_Tab& tab = c.tab(i);
6762 if (tab.indcount < 1)
6763 continue;
6764 chk1(st_create_table_index(c, tab) == 0);
6765 }
6766 for (i = 0; i < c.tabcount; i++) {
6767 ST_Tab& tab = c.tab(i);
6768 if (tab.indcount < 1)
6769 continue;
6770 chk1(st_begin_trans(c) == 0);
6771 for (j = 0; j < tab.indcount; j++) {
6772 ST_Ind& ind = tab.ind(j);
6773 if (j % 2 == 0) {
6774 ST_Errins errins(6114, 783, 0); // fail ATr seize op
6775 chk1(st_drop_index(c, ind, errins) == 0);
6776 } else {
6777 chk1(st_drop_index(c, ind) == 0);
6778 }
6779 }
6780 chk1(st_end_trans(c, 0) == 0);
6781 chk1(st_verify_list(c) == 0);
6782 for (j = 0; j < tab.indcount; j++) {
6783 ST_Ind& ind = tab.ind(j);
6784 if (j % 2 == 0) {
6785 require(ind.exists());
6786 chk1(st_drop_index(c, ind) == 0);
6787 } else {
6788 require(!ind.exists());
6789 }
6790 }
6791 }
6792 return NDBT_OK;
6793 err:
6794 return NDBT_FAILED;
6795 }
6796
6797 static int
st_test_dup_create_table(ST_Con & c,int arg=-1)6798 st_test_dup_create_table(ST_Con& c, int arg = -1)
6799 {
6800 int do_trans;
6801 int do_abort;
6802 int i;
6803 for (do_trans = 0; do_trans <= 1; do_trans++) {
6804 for (do_abort = 0; do_abort <= do_trans; do_abort++) {
6805 g_info << "trans:" << do_trans
6806 << " abort:" << do_abort << endl;
6807 for (i = 0; i < c.tabcount; i++) {
6808 ST_Tab& tab = c.tab(i);
6809 if (do_trans)
6810 chk1(st_begin_trans(c) == 0);
6811 chk1(st_create_table(c, tab) == 0);
6812 chk1(st_create_table(c, tab, 721) == 0);
6813 if (do_trans) {
6814 if (!do_abort)
6815 chk1(st_end_trans(c, 0) == 0);
6816 else
6817 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6818 }
6819 chk1(st_verify_list(c) == 0);
6820 if (tab.exists()) {
6821 chk1(st_drop_table(c, tab) == 0);
6822 }
6823 }
6824 }
6825 }
6826 return NDBT_OK;
6827 err:
6828 return NDBT_FAILED;
6829 }
6830
6831 static int
st_test_dup_drop_table(ST_Con & c,int arg=-1)6832 st_test_dup_drop_table(ST_Con& c, int arg = -1)
6833 {
6834 int do_trans;
6835 int do_abort;
6836 int i;
6837 for (do_trans = 0; do_trans <= 1; do_trans++) {
6838 for (do_abort = 0; do_abort <= do_trans; do_abort++) {
6839 g_info << "trans:" << do_trans
6840 << " abort:" << do_abort << endl;
6841 for (i = 0; i < c.tabcount; i++) {
6842 ST_Tab& tab = c.tab(i);
6843 chk1(st_create_table(c, tab) == 0);
6844 if (do_trans)
6845 chk1(st_begin_trans(c) == 0);
6846 chk1(st_drop_table(c, tab) == 0);
6847 if (!do_trans)
6848 chk1(st_drop_table(c, tab, 723) == 0);
6849 else
6850 chk1(st_drop_table(c, tab, 785) == 0);
6851 if (do_trans) {
6852 if (!do_abort)
6853 chk1(st_end_trans(c, 0) == 0);
6854 else
6855 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6856 }
6857 chk1(st_verify_list(c) == 0);
6858 if (tab.exists()) {
6859 chk1(st_drop_table(c, tab) == 0);
6860 }
6861 }
6862 }
6863 }
6864 return NDBT_OK;
6865 err:
6866 return NDBT_FAILED;
6867 }
6868
6869 static int
st_test_dup_create_index(ST_Con & c,int arg=-1)6870 st_test_dup_create_index(ST_Con& c, int arg = -1)
6871 {
6872 int do_trans;
6873 int do_abort;
6874 int i, j;
6875 for (do_trans = 0; do_trans <= 1; do_trans++) {
6876 for (do_abort = 0; do_abort <= do_trans; do_abort++) {
6877 g_info << "trans:" << do_trans
6878 << " abort:" << do_abort << endl;
6879 for (i = 0; i < c.tabcount; i++) {
6880 ST_Tab& tab = c.tab(i);
6881 if (tab.indcount < 1)
6882 continue;
6883 chk1(st_create_table(c, tab) == 0);
6884 for (j = 0; j < tab.indcount; j++) {
6885 ST_Ind& ind = tab.ind(j);
6886 if (do_trans)
6887 chk1(st_begin_trans(c) == 0);
6888 chk1(st_create_index(c, ind) == 0);
6889 chk1(st_create_index(c, ind, 721) == 0);
6890 if (do_trans) {
6891 if (!do_abort)
6892 chk1(st_end_trans(c, 0) == 0);
6893 else
6894 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6895 }
6896 chk1(st_verify_list(c) == 0);
6897 }
6898 chk1(st_drop_table(c, tab) == 0);
6899 }
6900 }
6901 }
6902 return NDBT_OK;
6903 err:
6904 return NDBT_FAILED;
6905 }
6906
6907 static int
st_test_dup_drop_index(ST_Con & c,int arg=-1)6908 st_test_dup_drop_index(ST_Con& c, int arg = -1)
6909 {
6910 int do_trans;
6911 int do_abort;
6912 int i, j;
6913 for (do_trans = 0; do_trans <= 1; do_trans++) {
6914 for (do_abort = 0; do_abort <= do_trans; do_abort++) {
6915 g_info << "trans:" << do_trans
6916 << " abort:" << do_abort << endl;
6917 for (i = 0; i < c.tabcount; i++) {
6918 ST_Tab& tab = c.tab(i);
6919 if (tab.indcount < 1)
6920 continue;
6921 chk1(st_create_table(c, tab) == 0);
6922 for (j = 0; j < tab.indcount; j++) {
6923 ST_Ind& ind = tab.ind(j);
6924 chk1(st_create_index(c, ind) == 0);
6925 if (do_trans)
6926 chk1(st_begin_trans(c) == 0);
6927 chk1(st_drop_index(c, ind) == 0);
6928 if (!do_trans)
6929 chk1(st_drop_index(c, ind, 4243) == 0);
6930 else
6931 chk1(st_drop_index(c, ind, 785) == 0);
6932 if (do_trans) {
6933 if (!do_abort)
6934 chk1(st_end_trans(c, 0) == 0);
6935 else
6936 chk1(st_end_trans(c, ST_AbortFlag) == 0);
6937 }
6938 chk1(st_verify_list(c) == 0);
6939 }
6940 chk1(st_drop_table(c, tab) == 0);
6941 }
6942 }
6943 }
6944 return NDBT_OK;
6945 err:
6946 return NDBT_FAILED;
6947 }
6948
6949 static int
st_test_build_index(ST_Con & c,int arg=-1)6950 st_test_build_index(ST_Con& c, int arg = -1)
6951 {
6952 int i, j;
6953 for (i = 0; i < c.tabcount; i++) {
6954 ST_Tab& tab = c.tab(i);
6955 if (tab.indcount < 1)
6956 continue;
6957 chk1(st_create_table(c, tab) == 0);
6958 chk1(st_load_table(c, tab) == 0);
6959 for (j = 0; j < tab.indcount; j++) {
6960 ST_Ind& ind = tab.ind(j);
6961 chk1(st_create_index(c, ind) == 0);
6962 chk1(st_verify_list(c) == 0);
6963 }
6964 chk1(st_drop_table(c, tab) == 0);
6965 }
6966 return NDBT_OK;
6967 err:
6968 return NDBT_FAILED;
6969 }
6970
6971 static ST_Errins
6972 st_test_local_create_list[] = {
6973 ST_Errins(8033, 293, 1), // TC trigger
6974 ST_Errins(8033, 293, 0),
6975 ST_Errins(4003, 4237, 1), // TUP trigger
6976 ST_Errins(4003, 4237, 0),
6977 ST_Errins(8034, 292, 1), // TC index
6978 ST_Errins(8034, 292, 0)
6979 };
6980
6981 static int
st_test_local_create(ST_Con & c,int arg=-1)6982 st_test_local_create(ST_Con& c, int arg = -1)
6983 {
6984 const int n = arg;
6985 ST_Errins *list = st_test_local_create_list;
6986 const int listlen =
6987 sizeof(st_test_local_create_list)/sizeof(st_test_local_create_list[0]);
6988 require(0 <= n && n < listlen);
6989 const bool only_unique = (n == 0 || n == 1 || n == 4 || n == 5);
6990 int i, j;
6991 for (i = 0; i < c.tabcount; i++) {
6992 ST_Tab& tab = c.tab(i);
6993 bool tabdone = false;
6994 for (j = 0; j < tab.indcount; j++) {
6995 ST_Ind& ind = tab.ind(j);
6996 if (only_unique && !ind.is_unique())
6997 continue;
6998 if (!tabdone) {
6999 chk1(st_create_table(c, tab) == 0);
7000 chk1(st_load_table(c, tab) == 0);
7001 tabdone = true;
7002 }
7003 ST_Errins errins = list[n];
7004 chk1(st_create_index(c, ind, errins) == 0);
7005 chk1(st_verify_list(c) == 0);
7006 }
7007 if (tabdone)
7008 chk1(st_drop_table(c, tab) == 0);
7009 }
7010 return NDBT_OK;
7011 err:
7012 return NDBT_FAILED;
7013 }
7014
7015 // random test cases
7016
7017 static const uint ST_AllowAbort = 1;
7018 static const uint ST_AllowErrins = 2;
7019
7020 static int
st_test_trans(ST_Con & c,int arg=-1)7021 st_test_trans(ST_Con& c, int arg = -1)
7022 {
7023 if ((arg & ST_AllowErrins) && randomly(2, 3)) {
7024 ST_Errins errins = st_get_errins(c, st_errins_begin_trans);
7025 chk1(st_begin_trans(c, errins) == 0);
7026 } else {
7027 chk1(st_begin_trans(c) == 0);
7028 if (randomly(1, 5)) {
7029 g_info << "try duplicate begin trans" << endl;
7030 chk1(st_begin_trans(c, 4410) == 0);
7031 chk1(c.dic->hasSchemaTrans() == true);
7032 }
7033 if ((arg & ST_AllowAbort) && randomly(1, 3)) {
7034 chk1(st_end_trans(c, ST_AbortFlag) == 0);
7035 } else {
7036 chk1(st_end_trans(c, 0) == 0);
7037 }
7038 }
7039 return NDBT_OK;
7040 err:
7041 return NDBT_FAILED;
7042 }
7043
7044 static int
st_test_create_table(ST_Con & c,int arg=-1)7045 st_test_create_table(ST_Con& c, int arg = -1)
7046 {
7047 bool trans = randomly(3, 4);
7048 bool simpletrans = !trans && randomly(1, 2);
7049 g_info << "trans:" << trans << " simpletrans:" << simpletrans << endl;
7050 if (trans) {
7051 chk1(st_begin_trans(c) == 0);
7052 }
7053 int i;
7054 for (i = 0; i < c.tabcount; i++) {
7055 ST_Tab& tab = c.tab(i);
7056 if (tab.exists()) {
7057 g_info << tab.name << ": skip existing" << endl;
7058 continue;
7059 }
7060 g_info << tab.name << ": to create" << endl;
7061 if (simpletrans) {
7062 chk1(st_begin_trans(c) == 0);
7063 }
7064 if ((arg & ST_AllowErrins) && randomly(1, 3)) {
7065 ST_Errins errins = st_get_errins(c, st_errins_table);
7066 chk1(st_create_table(c, tab, errins) == 0);
7067 if (simpletrans) {
7068 if (randomly(1, 2))
7069 chk1(st_end_trans(c, 0) == 0);
7070 else
7071 chk1(st_end_trans(c, ST_AbortFlag) == 0);
7072 }
7073 } else {
7074 chk1(st_create_table(c, tab) == 0);
7075 if (simpletrans) {
7076 uint flags = 0;
7077 if ((arg & ST_AllowAbort) && randomly(4, 5))
7078 flags |= ST_AbortFlag;
7079 chk1(st_end_trans(c, flags) == 0);
7080 }
7081 }
7082 if (tab.exists() && randomly(1, 3)) {
7083 g_info << tab.name << ": try duplicate create" << endl;
7084 chk1(st_create_table(c, tab, 721) == 0);
7085 }
7086 }
7087 if (trans) {
7088 uint flags = 0;
7089 if ((arg & ST_AllowAbort) && randomly(4, 5))
7090 flags |= ST_AbortFlag;
7091 chk1(st_end_trans(c, flags) == 0);
7092 }
7093 return NDBT_OK;
7094 err:
7095 return NDBT_FAILED;
7096 }
7097
7098 static int
st_test_drop_table(ST_Con & c,int arg=-1)7099 st_test_drop_table(ST_Con& c, int arg = -1)
7100 {
7101 bool trans = randomly(3, 4);
7102 bool simpletrans = !trans && randomly(1, 2);
7103 g_info << "trans:" << trans << " simpletrans:" << simpletrans << endl;
7104 if (trans) {
7105 chk1(st_begin_trans(c) == 0);
7106 }
7107 int i;
7108 for (i = 0; i < c.tabcount; i++) {
7109 ST_Tab& tab = c.tab(i);
7110 if (!tab.exists()) {
7111 g_info << tab.name << ": skip not existing" << endl;
7112 continue;
7113 }
7114 g_info << tab.name << ": to drop" << endl;
7115 if (simpletrans) {
7116 chk1(st_begin_trans(c) == 0);
7117 }
7118 if ((arg & ST_AllowErrins) && randomly(1, 3)) {
7119 ST_Errins errins = st_get_errins(c, st_errins_table);
7120 chk1(st_drop_table(c, tab, errins) == 0);
7121 if (simpletrans) {
7122 if (randomly(1, 2))
7123 chk1(st_end_trans(c, 0) == 0);
7124 else
7125 chk1(st_end_trans(c, ST_AbortFlag) == 0);
7126 }
7127 } else {
7128 chk1(st_drop_table(c, tab) == 0);
7129 if (simpletrans) {
7130 uint flags = 0;
7131 if ((arg & ST_AllowAbort) && randomly(4, 5))
7132 flags |= ST_AbortFlag;
7133 chk1(st_end_trans(c, flags) == 0);
7134 }
7135 }
7136 if (!tab.exists() && randomly(1, 3)) {
7137 g_info << tab.name << ": try duplicate drop" << endl;
7138 chk1(st_drop_table(c, tab, 723) == 0);
7139 }
7140 }
7141 if (trans) {
7142 uint flags = 0;
7143 if ((arg & ST_AllowAbort) && randomly(4, 5))
7144 flags |= ST_AbortFlag;
7145 chk1(st_end_trans(c, flags) == 0);
7146 }
7147 return NDBT_OK;
7148 err:
7149 return NDBT_FAILED;
7150 }
7151
7152 static int
st_test_table(ST_Con & c,int arg=-1)7153 st_test_table(ST_Con& c, int arg = -1)
7154 {
7155 chk1(st_test_create_table(c) == NDBT_OK);
7156 chk1(st_test_drop_table(c) == NDBT_OK);
7157 return NDBT_OK;
7158 err:
7159 return NDBT_FAILED;
7160 }
7161
7162 static int
st_test_create_index(ST_Con & c,int arg=-1)7163 st_test_create_index(ST_Con& c, int arg = -1)
7164 {
7165 bool trans = randomly(3, 4);
7166 bool simpletrans = !trans && randomly(1, 2);
7167 g_info << "trans:" << trans << " simpletrans:" << simpletrans << endl;
7168 if (trans) {
7169 chk1(st_begin_trans(c) == 0);
7170 }
7171 int i, j;
7172 for (i = 0; i < c.tabcount; i++) {
7173 ST_Tab& tab = c.tab(i);
7174 if (tab.indcount == 0)
7175 continue;
7176 if (!tab.exists()) {
7177 g_info << tab.name << ": to create" << endl;
7178 chk1(st_create_table(c, tab) == 0);
7179 }
7180 for (j = 0; j < tab.indcount; j++) {
7181 ST_Ind& ind = tab.ind(j);
7182 if (ind.exists()) {
7183 g_info << ind.name << ": skip existing" << endl;
7184 continue;
7185 }
7186 g_info << ind.name << ": to create" << endl;
7187 if (simpletrans) {
7188 chk1(st_begin_trans(c) == 0);
7189 }
7190 if ((arg & ST_AllowErrins) && randomly(1, 3)) {
7191 const ST_Errins* list = st_errins_index_create;
7192 ST_Errins errins = st_get_errins(c, list);
7193 chk1(st_create_index(c, ind, errins) == 0);
7194 if (simpletrans) {
7195 if (randomly(1, 2))
7196 chk1(st_end_trans(c, 0) == 0);
7197 else
7198 chk1(st_end_trans(c, ST_AbortFlag) == 0);
7199 }
7200 } else {
7201 chk1(st_create_index(c, ind) == 0);
7202 if (simpletrans) {
7203 uint flags = 0;
7204 if ((arg & ST_AllowAbort) && randomly(4, 5))
7205 flags |= ST_AbortFlag;
7206 chk1(st_end_trans(c, flags) == 0);
7207 }
7208 }
7209 if (ind.exists() && randomly(1, 3)) {
7210 g_info << ind.name << ": try duplicate create" << endl;
7211 chk1(st_create_index(c, ind, 721) == 0);
7212 }
7213 }
7214 }
7215 if (trans) {
7216 uint flags = 0;
7217 if ((arg & ST_AllowAbort) && randomly(4, 5))
7218 flags |= ST_AbortFlag;
7219 chk1(st_end_trans(c, flags) == 0);
7220 }
7221 return NDBT_OK;
7222 err:
7223 return NDBT_FAILED;
7224 }
7225
7226 static int
st_test_drop_index(ST_Con & c,int arg=-1)7227 st_test_drop_index(ST_Con& c, int arg = -1)
7228 {
7229 bool trans = randomly(3, 4);
7230 bool simpletrans = !trans && randomly(1, 2);
7231 g_info << "trans:" << trans << " simpletrans:" << simpletrans << endl;
7232 if (trans) {
7233 chk1(st_begin_trans(c) == 0);
7234 }
7235 int i, j;
7236 for (i = 0; i < c.tabcount; i++) {
7237 ST_Tab& tab = c.tab(i);
7238 if (tab.indcount == 0)
7239 continue;
7240 if (!tab.exists()) {
7241 g_info << tab.name << ": skip not existing" << endl;
7242 continue;
7243 }
7244 for (j = 0; j < tab.indcount; j++) {
7245 ST_Ind& ind = tab.ind(j);
7246 if (!ind.exists()) {
7247 g_info << ind.name << ": skip not existing" << endl;
7248 continue;
7249 }
7250 g_info << ind.name << ": to drop" << endl;
7251 if (simpletrans) {
7252 chk1(st_begin_trans(c) == 0);
7253 }
7254 if ((arg & ST_AllowErrins) && randomly(1, 3)) {
7255 const ST_Errins* list = st_errins_index_drop;
7256 ST_Errins errins = st_get_errins(c, list);
7257 chk1(st_drop_index(c, ind, errins) == 0);
7258 if (simpletrans) {
7259 if (randomly(1, 2))
7260 chk1(st_end_trans(c, 0) == 0);
7261 else
7262 chk1(st_end_trans(c, ST_AbortFlag) == 0);
7263 }
7264 } else {
7265 chk1(st_drop_index(c, ind) == 0);
7266 if (simpletrans) {
7267 uint flags = 0;
7268 if ((arg & ST_AllowAbort) && randomly(4, 5))
7269 flags |= ST_AbortFlag;
7270 chk1(st_end_trans(c, flags) == 0);
7271 }
7272 }
7273 if (!ind.exists() && randomly(1, 3)) {
7274 g_info << ind.name << ": try duplicate drop" << endl;
7275 chk1(st_drop_index(c, ind, 4243) == 0);
7276 }
7277 }
7278 }
7279 if (trans) {
7280 uint flags = 0;
7281 if ((arg & ST_AllowAbort) && randomly(4, 5))
7282 flags |= ST_AbortFlag;
7283 chk1(st_end_trans(c, flags) == 0);
7284 }
7285 return NDBT_OK;
7286 err:
7287 return NDBT_FAILED;
7288 }
7289
7290 static int
st_test_index(ST_Con & c,int arg=-1)7291 st_test_index(ST_Con& c, int arg = -1)
7292 {
7293 chk1(st_test_create_index(c) == NDBT_OK);
7294 chk1(st_test_drop_index(c) == NDBT_OK);
7295 return NDBT_OK;
7296 err:
7297 return NDBT_FAILED;
7298 }
7299
7300 // node failure and system restart
7301
7302 static int
st_test_anf_parse(ST_Con & c,int arg=-1)7303 st_test_anf_parse(ST_Con& c, int arg = -1)
7304 {
7305 int i;
7306 chk1(st_start_xcon(c) == 0);
7307 {
7308 ST_Con& xc = *c.xcon;
7309 chk1(st_begin_trans(xc) == 0);
7310 for (i = 0; i < c.tabcount; i++) {
7311 ST_Tab& tab = c.tab(i);
7312 chk1(st_create_table_index(xc, tab) == 0);
7313 }
7314 // DICT aborts the trans
7315 xc.tx_on = false;
7316 xc.tx_commit = false;
7317 st_set_commit_all(xc);
7318 chk1(st_stop_xcon(c) == 0);
7319 chk1(st_wait_idle(c) == 0);
7320 chk1(st_verify_list(c) == 0);
7321 }
7322 return NDBT_OK;
7323 err:
7324 return NDBT_FAILED;
7325 }
7326
7327 static int
st_test_anf_background(ST_Con & c,int arg=-1)7328 st_test_anf_background(ST_Con& c, int arg = -1)
7329 {
7330 int i;
7331 chk1(st_start_xcon(c) == 0);
7332 {
7333 ST_Con& xc = *c.xcon;
7334 chk1(st_begin_trans(xc) == 0);
7335 for (i = 0; i < c.tabcount; i++) {
7336 ST_Tab& tab = c.tab(i);
7337 chk1(st_create_table(xc, tab) == 0);
7338 }
7339 // DICT takes over and completes the trans
7340 st_end_trans(xc, ST_BackgroundFlag);
7341 chk1(st_stop_xcon(c) == 0);
7342 chk1(st_wait_idle(c) == 0);
7343 chk1(st_verify_list(c) == 0);
7344 }
7345 return NDBT_OK;
7346 err:
7347 return NDBT_FAILED;
7348 }
7349
7350 static int
st_test_anf_fail_begin(ST_Con & c,int arg=-1)7351 st_test_anf_fail_begin(ST_Con& c, int arg = -1)
7352 {
7353 chk1(st_start_xcon(c) == 0);
7354 {
7355 ST_Con& xc = *c.xcon;
7356
7357 ST_Errins errins1(6102, -1, 1); // master kills us at begin
7358 ST_Errins errins2(6103, -1, 0); // slave delays conf
7359 chk1(st_do_errins(xc, errins1) == 0);
7360 chk1(st_do_errins(xc, errins2) == 0);
7361
7362 chk1(st_begin_trans(xc, 4009) == 0);
7363
7364 // DICT aborts the trans
7365 xc.tx_on = false;
7366 xc.tx_commit = false;
7367 st_set_commit_all(xc);
7368 chk1(st_stop_xcon(c) == 0);
7369
7370 // xc may get 4009 before takeover is ready (5000 ms delay)
7371 ST_Retry retry = { 100, 100 }; // 100 * 100ms = 10000ms
7372 chk1(st_begin_trans(c, retry) == 0);
7373 chk1(st_wait_idle(c) == 0);
7374 chk1(st_verify_list(c) == 0);
7375 }
7376 return NDBT_OK;
7377 err:
7378 return NDBT_FAILED;
7379 }
7380
7381 static int
st_test_snf_parse(ST_Con & c,int arg=-1)7382 st_test_snf_parse(ST_Con& c, int arg = -1)
7383 {
7384 bool do_abort = (arg == 1);
7385 chk1(st_begin_trans(c) == 0);
7386 int node_id;
7387 node_id = -1;
7388 int i;
7389 int midcount;
7390 midcount = c.tabcount / 2;
7391
7392 for (i = 0; i < c.tabcount; i++) {
7393 ST_Tab& tab = c.tab(i);
7394 if (i == midcount) {
7395 require(c.numdbnodes > 1);
7396 uint rand = urandom(c.numdbnodes);
7397 node_id = c.restarter->getRandomNotMasterNodeId(rand);
7398 g_info << "restart node " << node_id << " (async)" << endl;
7399 const int flags = NdbRestarter::NRRF_NOSTART;
7400 chk1(c.restarter->restartOneDbNode2(node_id, flags) == 0);
7401 chk1(c.restarter->waitNodesNoStart(&node_id, 1) == 0);
7402 chk1(c.restarter->startNodes(&node_id, 1) == 0);
7403 }
7404 chk1(st_create_table_index(c, tab) == 0);
7405 }
7406 if (!do_abort)
7407 chk1(st_end_trans(c, 0) == 0);
7408 else
7409 chk1(st_end_trans(c, ST_AbortFlag) == 0);
7410
7411 g_info << "wait for node " << node_id << " to come up" << endl;
7412 chk1(c.restarter->waitClusterStarted() == 0);
7413 CHK_NDB_READY(c.ndb);
7414 g_info << "verify all" << endl;
7415 chk1(st_verify_all(c) == 0);
7416 return NDBT_OK;
7417 err:
7418 return NDBT_FAILED;
7419 }
7420
7421 static int
st_test_mnf_parse(ST_Con & c,int arg=-1)7422 st_test_mnf_parse(ST_Con& c, int arg = -1)
7423 {
7424 const NdbDictionary::Table* pTab;
7425 bool do_abort = (arg == 1);
7426 chk1(st_begin_trans(c) == 0);
7427 int node_id;
7428 node_id = -1;
7429 int i;
7430 int midcount;
7431 midcount = c.tabcount / 2;
7432
7433 for (i = 0; i < c.tabcount; i++) {
7434 ST_Tab& tab = c.tab(i);
7435 chk1(st_create_table_index(c, tab) == 0);
7436 if (i == midcount) {
7437 require(c.numdbnodes > 1);
7438 node_id = c.restarter->getMasterNodeId();
7439 g_info << "restart node " << node_id << " (async)" << endl;
7440 const int flags = NdbRestarter::NRRF_NOSTART;
7441 chk1(c.restarter->restartOneDbNode2(node_id, flags) == 0);
7442 chk1(c.restarter->waitNodesNoStart(&node_id, 1) == 0);
7443 chk1(c.restarter->startNodes(&node_id, 1) == 0);
7444 break;
7445 }
7446 }
7447 if (!do_abort)
7448 chk1(st_end_trans_aborted(c, ST_CommitFlag) == 0);
7449 else
7450 chk1(st_end_trans_aborted(c, ST_AbortFlag) == 0);
7451
7452 g_info << "wait for node " << node_id << " to come up" << endl;
7453 chk1(c.restarter->waitClusterStarted() == 0);
7454 CHK_NDB_READY(c.ndb);
7455 g_info << "verify all" << endl;
7456 for (i = 0; i < c.tabcount; i++) {
7457 ST_Tab& tab = c.tab(i);
7458 // Verify that table is not in db
7459 c.dic->invalidateTable(tab.name);
7460 pTab =
7461 NDBT_Table::discoverTableFromDb(c.ndb, tab.name);
7462 chk1(pTab == NULL);
7463 }
7464 /*
7465 chk1(st_verify_all(c) == 0);
7466 */
7467 return NDBT_OK;
7468 err:
7469 return NDBT_FAILED;
7470 }
7471
7472 static int
st_test_mnf_prepare(ST_Con & c,int arg=-1)7473 st_test_mnf_prepare(ST_Con& c, int arg = -1)
7474 {
7475 NdbRestarter restarter;
7476 //int master = restarter.getMasterNodeId();
7477 ST_Errins errins = st_get_errins(c, st_errins_end_trans1);
7478 int i;
7479
7480 chk1(st_begin_trans(c) == 0);
7481 for (i = 0; i < c.tabcount; i++) {
7482 ST_Tab& tab = c.tab(i);
7483 chk1(st_create_table_index(c, tab) == 0);
7484 }
7485 if (arg == 1)
7486 {
7487 chk1(st_end_trans_aborted(c, errins, ST_BackgroundFlag) == 0);
7488 chk1(st_wait_idle(c) == 0);
7489 }
7490 else
7491 chk1(st_end_trans_aborted(c, errins, ST_CommitFlag) == 0);
7492 chk1(c.restarter->waitClusterStarted() == 0);
7493 CHK_NDB_READY(c.ndb);
7494 //st_wait_db_node_up(c, master);
7495 for (i = 0; i < c.tabcount; i++) {
7496 ST_Tab& tab = c.tab(i);
7497 // Verify that table is not in db
7498 c.dic->invalidateTable(tab.name);
7499 const NdbDictionary::Table* pTab =
7500 NDBT_Table::discoverTableFromDb(c.ndb, tab.name);
7501 chk1(pTab == NULL);
7502 }
7503 return NDBT_OK;
7504 err:
7505 return NDBT_FAILED;
7506 }
7507
7508 static int
st_test_mnf_commit1(ST_Con & c,int arg=-1)7509 st_test_mnf_commit1(ST_Con& c, int arg = -1)
7510 {
7511 NdbRestarter restarter;
7512 //int master = restarter.getMasterNodeId();
7513 ST_Errins errins = st_get_errins(c, st_errins_end_trans2);
7514 int i;
7515
7516 chk1(st_begin_trans(c) == 0);
7517 for (i = 0; i < c.tabcount; i++) {
7518 ST_Tab& tab = c.tab(i);
7519 chk1(st_create_table_index(c, tab) == 0);
7520 }
7521 if (arg == 1)
7522 {
7523 chk1(st_end_trans(c, errins, ST_BackgroundFlag) == 0);
7524 chk1(st_wait_idle(c) == 0);
7525 }
7526 else
7527 chk1(st_end_trans(c, errins, ST_CommitFlag) == 0);
7528 chk1(c.restarter->waitClusterStarted() == 0);
7529 CHK_NDB_READY(c.ndb);
7530 //st_wait_db_node_up(c, master);
7531 for (i = 0; i < c.tabcount; i++) {
7532 ST_Tab& tab = c.tab(i);
7533 chk1(st_verify_table(c, tab) == 0);
7534 }
7535 chk1(st_drop_test_tables(c) == 0);
7536 return NDBT_OK;
7537 err:
7538 return NDBT_FAILED;
7539 }
7540
7541 static int
st_test_mnf_commit2(ST_Con & c,int arg=-1)7542 st_test_mnf_commit2(ST_Con& c, int arg = -1)
7543 {
7544 NdbRestarter restarter;
7545 //int master = restarter.getMasterNodeId();
7546 ST_Errins errins = st_get_errins(c, st_errins_end_trans3);
7547 int i;
7548
7549 chk1(st_begin_trans(c) == 0);
7550 for (i = 0; i < c.tabcount; i++) {
7551 ST_Tab& tab = c.tab(i);
7552 chk1(st_create_table_index(c, tab) == 0);
7553 }
7554 if (arg == 1)
7555 {
7556 chk1(st_end_trans(c, errins, ST_BackgroundFlag) == 0);
7557 chk1(st_wait_idle(c) == 0);
7558 }
7559 else
7560 chk1(st_end_trans(c, errins, ST_CommitFlag) == 0);
7561 chk1(c.restarter->waitClusterStarted() == 0);
7562 CHK_NDB_READY(c.ndb);
7563 //st_wait_db_node_up(c, master);
7564 chk1(st_verify_all(c) == 0);
7565 for (i = 0; i < c.tabcount; i++) {
7566 ST_Tab& tab = c.tab(i);
7567 chk1(st_load_table(c, tab) == 0);
7568 }
7569 chk1(st_drop_test_tables(c) == 0);
7570 return NDBT_OK;
7571 err:
7572 return NDBT_FAILED;
7573 }
7574
7575 static int
st_test_mnf_run_commit(ST_Con & c,int arg=-1)7576 st_test_mnf_run_commit(ST_Con& c, int arg = -1)
7577 {
7578 const NdbDictionary::Table* pTab;
7579 NdbRestarter restarter;
7580 //int master = restarter.getMasterNodeId();
7581 int i;
7582
7583 if (arg == FAIL_BEGIN)
7584 {
7585 // No transaction to be found if only one node left
7586 if (restarter.getNumDbNodes() < 3)
7587 return NDBT_OK;
7588 chk1(st_begin_trans(c) == -1);
7589 goto verify;
7590 }
7591 else
7592 chk1(st_begin_trans(c) == 0);
7593 for (i = 0; i < c.tabcount; i++) {
7594 ST_Tab& tab = c.tab(i);
7595 if (arg == FAIL_CREATE)
7596 {
7597 chk1(st_create_table_index(c, tab) == -1);
7598 goto verify;
7599 }
7600 else
7601 chk1(st_create_table_index(c, tab) == 0);
7602 }
7603 if (arg == FAIL_END)
7604 {
7605 chk1(st_end_trans(c, ST_CommitFlag) == -1);
7606 }
7607 else // if (arg == SUCCEED_COMMIT)
7608 chk1(st_end_trans(c, ST_CommitFlag) == 0);
7609
7610 verify:
7611 g_info << "wait for master node to come up" << endl;
7612 chk1(c.restarter->waitClusterStarted() == 0);
7613 CHK_NDB_READY(c.ndb);
7614 //st_wait_db_node_up(c, master);
7615 g_info << "verify all" << endl;
7616 for (i = 0; i < c.tabcount; i++) {
7617 ST_Tab& tab = c.tab(i);
7618 switch (arg) {
7619 case FAIL_BEGIN:
7620 case FAIL_CREATE:
7621 case FAIL_END:
7622 {
7623 // Verify that table is not in db
7624 c.dic->invalidateTable(tab.name);
7625 pTab =
7626 NDBT_Table::discoverTableFromDb(c.ndb, tab.name);
7627 chk1(pTab == NULL);
7628 break;
7629 }
7630 default:
7631 chk1(st_verify_table(c, tab) == 0);
7632 }
7633 }
7634
7635 return NDBT_OK;
7636 err:
7637 return NDBT_FAILED;
7638 }
7639
7640 static int
st_test_mnf_run_abort(ST_Con & c,int arg=-1)7641 st_test_mnf_run_abort(ST_Con& c, int arg = -1)
7642 {
7643 NdbRestarter restarter;
7644 //int master = restarter.getMasterNodeId();
7645 const NdbDictionary::Table* pTab;
7646 bool do_abort = (arg == SUCCEED_ABORT);
7647 int i;
7648
7649 chk1(st_begin_trans(c) == 0);
7650 for (i = 0; i < c.tabcount; i++) {
7651 ST_Tab& tab = c.tab(i);
7652 chk1(st_create_table_index(c, tab) == 0);
7653 }
7654 if (!do_abort)
7655 chk1(st_end_trans(c, ST_CommitFlag) == -1);
7656 else
7657 chk1(st_end_trans_aborted(c, ST_AbortFlag) == 0);
7658
7659 g_info << "wait for master node to come up" << endl;
7660 chk1(c.restarter->waitClusterStarted() == 0);
7661 CHK_NDB_READY(c.ndb);
7662 //st_wait_db_node_up(c, master);
7663 g_info << "verify all" << endl;
7664 for (i = 0; i < c.tabcount; i++) {
7665 ST_Tab& tab = c.tab(i);
7666 // Verify that table is not in db
7667 c.dic->invalidateTable(tab.name);
7668 pTab =
7669 NDBT_Table::discoverTableFromDb(c.ndb, tab.name);
7670 chk1(pTab == NULL);
7671 }
7672
7673 return NDBT_OK;
7674 err:
7675 return NDBT_FAILED;
7676 }
7677
7678 static int
st_test_mnf_start_partial(ST_Con & c,int arg=-1)7679 st_test_mnf_start_partial(ST_Con& c, int arg = -1)
7680 {
7681 ST_Errins errins(ERR_INSERT_PARTIAL_START_FAIL, 0, 1); // slave skips start
7682 chk1(st_do_errins(c, errins) == 0);
7683 return st_test_mnf_run_commit(c, arg);
7684 err:
7685 return -1;
7686 }
7687
7688 static int
st_test_mnf_parse_partial(ST_Con & c,int arg=-1)7689 st_test_mnf_parse_partial(ST_Con& c, int arg = -1)
7690 {
7691 ST_Errins errins(ERR_INSERT_PARTIAL_PARSE_FAIL, 0, 1); // slave skips parse
7692 chk1(st_do_errins(c, errins) == 0);
7693 return st_test_mnf_run_commit(c, arg);
7694 err:
7695 return -1;
7696 }
7697
7698 static int
st_test_mnf_flush_prepare_partial(ST_Con & c,int arg=-1)7699 st_test_mnf_flush_prepare_partial(ST_Con& c, int arg = -1)
7700 {
7701 ST_Errins errins(ERR_INSERT_PARTIAL_FLUSH_PREPARE_FAIL, 0, 1); // slave skips flush prepare
7702 chk1(st_do_errins(c, errins) == 0);
7703 return st_test_mnf_run_commit(c, arg);
7704 err:
7705 return -1;
7706 }
7707
7708 static int
st_test_mnf_prepare_partial(ST_Con & c,int arg=-1)7709 st_test_mnf_prepare_partial(ST_Con& c, int arg = -1)
7710 {
7711 ST_Errins errins(ERR_INSERT_PARTIAL_PREPARE_FAIL, 0, 1); // slave skips prepare
7712 chk1(st_do_errins(c, errins) == 0);
7713 return st_test_mnf_run_commit(c, arg);
7714 err:
7715 return -1;
7716 }
7717
7718 static int
st_test_mnf_abort_parse_partial(ST_Con & c,int arg=-1)7719 st_test_mnf_abort_parse_partial(ST_Con& c, int arg = -1)
7720 {
7721 ST_Errins errins(ERR_INSERT_PARTIAL_ABORT_PARSE_FAIL, 0, 1); // slave skips abort parse
7722 chk1(st_do_errins(c, errins) == 0);
7723 return st_test_mnf_run_abort(c, arg);
7724 err:
7725 return -1;
7726 }
7727
7728 static int
st_test_mnf_abort_prepare_partial(ST_Con & c,int arg=-1)7729 st_test_mnf_abort_prepare_partial(ST_Con& c, int arg = -1)
7730 {
7731 ST_Errins errins(ERR_INSERT_PARTIAL_ABORT_PREPARE_FAIL, 0, 1); // slave skips abort prepare
7732 chk1(st_do_errins(c, errins) == 0);
7733 return st_test_mnf_run_abort(c, arg);
7734 err:
7735 return -1;
7736 }
7737
7738 static int
st_test_mnf_flush_commit_partial(ST_Con & c,int arg=-1)7739 st_test_mnf_flush_commit_partial(ST_Con& c, int arg = -1)
7740 {
7741 NdbRestarter restarter;
7742 ST_Errins errins(ERR_INSERT_PARTIAL_FLUSH_COMMIT_FAIL, 0, 1); // slave skips flush commit
7743 chk1(st_do_errins(c, errins) == 0);
7744 if (restarter.getNumDbNodes() < 3)
7745 // If new master is only node and it hasn't flush commit, we abort
7746 return st_test_mnf_run_commit(c, FAIL_END);
7747 else
7748 return st_test_mnf_run_commit(c, arg);
7749 err:
7750 return -1;
7751 }
7752
7753 static int
st_test_mnf_commit_partial(ST_Con & c,int arg=-1)7754 st_test_mnf_commit_partial(ST_Con& c, int arg = -1)
7755 {
7756 ST_Errins errins(ERR_INSERT_PARTIAL_COMMIT_FAIL, 0, 1); // slave skips commit
7757 chk1(st_do_errins(c, errins) == 0);
7758 return st_test_mnf_run_commit(c, arg);
7759 err:
7760 return -1;
7761 }
7762
7763 static int
st_test_mnf_flush_complete_partial(ST_Con & c,int arg=-1)7764 st_test_mnf_flush_complete_partial(ST_Con& c, int arg = -1)
7765 {
7766 ST_Errins errins(ERR_INSERT_PARTIAL_FLUSH_COMPLETE_FAIL, 0, 1); // slave skips flush complete
7767 chk1(st_do_errins(c, errins) == 0);
7768 return st_test_mnf_run_commit(c, arg);
7769 err:
7770 return -1;
7771 }
7772
7773 static int
st_test_mnf_complete_partial(ST_Con & c,int arg=-1)7774 st_test_mnf_complete_partial(ST_Con& c, int arg = -1)
7775 {
7776 ST_Errins errins(ERR_INSERT_PARTIAL_COMPLETE_FAIL, 0, 1); // slave skips complete
7777 chk1(st_do_errins(c, errins) == 0);
7778 return st_test_mnf_run_commit(c, arg);
7779 err:
7780 return -1;
7781 }
7782
7783 static int
st_test_mnf_end_partial(ST_Con & c,int arg=-1)7784 st_test_mnf_end_partial(ST_Con& c, int arg = -1)
7785 {
7786 ST_Errins errins(ERR_INSERT_PARTIAL_END_FAIL, 0, 1); // slave skips end
7787 chk1(st_do_errins(c, errins) == 0);
7788 return st_test_mnf_run_commit(c, arg);
7789 err:
7790 return -1;
7791 }
7792
7793 static int
st_test_sr_parse(ST_Con & c,int arg=-1)7794 st_test_sr_parse(ST_Con& c, int arg = -1)
7795 {
7796 bool do_abort = (arg == 1);
7797 chk1(st_begin_trans(c) == 0);
7798 int i;
7799 for (i = 0; i < c.tabcount; i++) {
7800 ST_Tab& tab = c.tab(i);
7801 chk1(st_create_table_index(c, tab) == 0);
7802 }
7803 if (!do_abort)
7804 chk1(st_end_trans(c, 0) == 0);
7805 else
7806 chk1(st_end_trans(c, ST_AbortFlag) == 0);
7807
7808 g_info << "restart all" << endl;
7809 int flags;
7810 flags = NdbRestarter::NRRF_NOSTART;
7811 chk1(c.restarter->restartAll2(flags) == 0);
7812 g_info << "wait for cluster started" << endl;
7813 chk1(c.restarter->waitClusterNoStart() == 0);
7814 chk1(c.restarter->startAll() == 0);
7815 chk1(c.restarter->waitClusterStarted() == 0);
7816 CHK_NDB_READY(c.ndb);
7817 g_info << "verify all" << endl;
7818 chk1(st_verify_all(c) == 0);
7819 return NDBT_OK;
7820 err:
7821 return NDBT_FAILED;
7822 }
7823
7824 #if 0
7825 static int
7826 st_test_sr_commit(ST_Con& c, int arg = -1)
7827 {
7828 g_info << "not yet" << endl;
7829 return NDBT_OK;
7830 }
7831 #endif
7832
7833 // run test cases
7834
7835 struct ST_Test {
7836 const char* key;
7837 int mindbnodes;
7838 int arg;
7839 int (*func)(ST_Con& c, int arg);
7840 const char* name;
7841 const char* desc;
7842 };
7843
7844 static NdbOut&
operator <<(NdbOut & out,const ST_Test & test)7845 operator<<(NdbOut& out, const ST_Test& test)
7846 {
7847 out << "CASE " << test.key;
7848 out << " " << test.name;
7849 if (test.arg != -1)
7850 out << "+" << test.arg;
7851 out << " - " << test.desc;
7852 return out;
7853 }
7854
7855 static const ST_Test
7856 st_test_list[] = {
7857 #define func(f) f, #f
7858 // specific ops
7859 { "a1", 1, 0,
7860 func(st_test_create),
7861 "create all within trans, commit" },
7862 { "a2", 1, 1,
7863 func(st_test_create),
7864 "create all within trans, abort" },
7865 { "a3", 1, 0,
7866 func(st_test_drop),
7867 "drop all within trans, commit" },
7868 { "a4", 1, 1,
7869 func(st_test_drop),
7870 "drop all within trans, abort" },
7871 { "b1", 1, -1,
7872 func(st_test_rollback_create_table),
7873 "partial rollback of create table ops" },
7874 { "b2", 1, -1,
7875 func(st_test_rollback_drop_table),
7876 "partial rollback of drop table ops" },
7877 { "b3", 1, -1,
7878 func(st_test_rollback_create_index),
7879 "partial rollback of create index ops" },
7880 { "b4", 1, -1,
7881 func(st_test_rollback_drop_index),
7882 "partial rollback of drop index ops" },
7883 { "c1", 1, -1,
7884 func(st_test_dup_create_table),
7885 "try to create same table twice" },
7886 { "c2", 1, -1,
7887 func(st_test_dup_drop_table),
7888 "try to drop same table twice" },
7889 { "c3", 1, -1,
7890 func(st_test_dup_create_index),
7891 "try to create same index twice" },
7892 { "c4", 1, -1,
7893 func(st_test_dup_drop_index),
7894 "try to drop same index twice" },
7895 { "d1", 1, -1,
7896 func(st_test_build_index),
7897 "build index on non-empty table" },
7898 { "e1", 1, 0,
7899 func(st_test_local_create),
7900 "fail trigger create in TC, master errins 8033" },
7901 { "e2", 2, 1,
7902 func(st_test_local_create),
7903 "fail trigger create in TC, slave errins 8033" },
7904 { "e3", 1, 2,
7905 func(st_test_local_create),
7906 "fail trigger create in TUP, master errins 4003" },
7907 { "e4", 2, 3,
7908 func(st_test_local_create),
7909 "fail trigger create in TUP, slave errins 4003" },
7910 { "e5", 1, 4,
7911 func(st_test_local_create),
7912 "fail index create in TC, master errins 8034" },
7913 { "e6", 2, 5,
7914 func(st_test_local_create),
7915 "fail index create in TC, slave errins 8034" },
7916 // random ops
7917 { "o1", 1, 0,
7918 func(st_test_trans),
7919 "start and stop schema trans" },
7920 { "o2", 1, ST_AllowAbort,
7921 func(st_test_trans),
7922 "start and stop schema trans, allow abort" },
7923 { "o3", 1, ST_AllowAbort | ST_AllowErrins,
7924 func(st_test_trans),
7925 "start and stop schema trans, allow abort errins" },
7926 //
7927 { "p1", 1, 0,
7928 func(st_test_create_table),
7929 "create tables at random" },
7930 { "p2", 1, ST_AllowAbort,
7931 func(st_test_create_table),
7932 "create tables at random, allow abort" },
7933 { "p3", 1, ST_AllowAbort | ST_AllowErrins,
7934 func(st_test_create_table),
7935 "create tables at random, allow abort errins" },
7936 //
7937 { "p4", 1, 0,
7938 func(st_test_table),
7939 "create and drop tables at random" },
7940 { "p5", 1, ST_AllowAbort,
7941 func(st_test_table),
7942 "create and drop tables at random, allow abort" },
7943 { "p6", 1, ST_AllowAbort | ST_AllowErrins,
7944 func(st_test_table),
7945 "create and drop tables at random, allow abort errins" },
7946 //
7947 { "q1", 1, 0,
7948 func(st_test_create_index),
7949 "create indexes at random" },
7950 { "q2", 1, ST_AllowAbort,
7951 func(st_test_create_index),
7952 "create indexes at random, allow abort" },
7953 { "q3", 1, ST_AllowAbort | ST_AllowErrins,
7954 func(st_test_create_index),
7955 "create indexes at random, allow abort errins" },
7956 //
7957 { "q4", 1, 0,
7958 func(st_test_index),
7959 "create and drop indexes at random" },
7960 { "q5", 1, ST_AllowAbort,
7961 func(st_test_index),
7962 "create and drop indexes at random, allow abort" },
7963 { "q6", 1, ST_AllowAbort | ST_AllowErrins,
7964 func(st_test_index),
7965 "create and drop indexes at random, allow abort errins" },
7966 // node failure and system restart
7967 { "u1", 1, -1,
7968 func(st_test_anf_parse),
7969 "api node fail in parse phase" },
7970 { "u2", 1, -1,
7971 func(st_test_anf_background),
7972 "api node fail after background trans" },
7973 { "u3", 2, -1,
7974 func(st_test_anf_fail_begin),
7975 "api node fail in middle of kernel begin trans" },
7976 //
7977 { "v1", 2, 0,
7978 func(st_test_snf_parse),
7979 "slave node fail in parse phase, commit" },
7980 { "v2", 2, 1,
7981 func(st_test_snf_parse),
7982 "slave node fail in parse phase, abort" },
7983 { "w1", 1, 0,
7984 func(st_test_sr_parse),
7985 "system restart in parse phase, commit" },
7986 { "w2", 1, 1,
7987 func(st_test_sr_parse),
7988 "system restart in parse phase, abort" },
7989 #ifdef ndb_master_failure
7990 { "x1", 2, 0,
7991 func(st_test_mnf_parse),
7992 "master node fail in parse phase, commit" },
7993 { "x2", 2, 1,
7994 func(st_test_mnf_parse),
7995 "master node fail in parse phase, abort" },
7996 { "x3", 2, 0,
7997 func(st_test_mnf_prepare),
7998 "master node fail in prepare phase" },
7999 { "x4", 2, 0,
8000 func(st_test_mnf_commit1),
8001 "master node fail in start of commit phase" },
8002 { "x5", 2, 0,
8003 func(st_test_mnf_commit2),
8004 "master node fail in end of commit phase" },
8005 { "y1", 2, SUCCEED_COMMIT,
8006 func(st_test_mnf_start_partial),
8007 "master node fail in start phase, retry will succeed" },
8008 { "y2", 2, FAIL_CREATE,
8009 func(st_test_mnf_parse_partial),
8010 "master node fail in parse phase, partial rollback" },
8011 { "y3", 2, FAIL_END,
8012 func(st_test_mnf_flush_prepare_partial),
8013 "master node fail in flush prepare phase, partial rollback" },
8014 { "y4", 2, FAIL_END,
8015 func(st_test_mnf_prepare_partial),
8016 "master node fail in prepare phase, partial rollback" },
8017 { "y5", 2, SUCCEED_COMMIT,
8018 func(st_test_mnf_flush_commit_partial),
8019 "master node fail in flush commit phase, partial rollback" },
8020 { "y6", 2, SUCCEED_COMMIT,
8021 func(st_test_mnf_commit_partial),
8022 "master node fail in commit phase, commit, partial rollforward" },
8023 { "y7", 2, SUCCEED_COMMIT,
8024 func(st_test_mnf_flush_complete_partial),
8025 "master node fail in flush complete phase, commit, partial rollforward" },
8026 { "y8", 2, SUCCEED_COMMIT,
8027 func(st_test_mnf_complete_partial),
8028 "master node fail in complete phase, commit, partial rollforward" },
8029 { "y9", 2, SUCCEED_COMMIT,
8030 func(st_test_mnf_end_partial),
8031 "master node fail in end phase, commit, partial rollforward" },
8032 { "z1", 2, SUCCEED_ABORT,
8033 func(st_test_mnf_abort_parse_partial),
8034 "master node fail in abort parse phase, partial rollback" },
8035 { "z2", 2, FAIL_END,
8036 func(st_test_mnf_abort_prepare_partial),
8037 "master node fail in abort prepare phase, partial rollback" },
8038 { "z3", 2, 1,
8039 func(st_test_mnf_prepare),
8040 "master node fail in prepare phase in background" },
8041 { "z4", 2, 1,
8042 func(st_test_mnf_commit1),
8043 "master node fail in start of commit phase in background" },
8044 { "z5", 2, 1,
8045 func(st_test_mnf_commit2),
8046 "master node fail in end of commit phase in background" },
8047
8048 #endif
8049 #undef func
8050 };
8051
8052 static const int
8053 st_test_count = sizeof(st_test_list)/sizeof(st_test_list[0]);
8054
8055 static const char* st_test_case = 0;
8056 static const char* st_test_skip = 0;
8057
8058 static bool
st_test_match(const ST_Test & test)8059 st_test_match(const ST_Test& test)
8060 {
8061 const char* p = 0;
8062 if (st_test_case == 0)
8063 goto skip;
8064 if (strstr(st_test_case, test.key) != 0)
8065 goto skip;
8066 p = strchr(st_test_case, test.key[0]);
8067 if (p != 0 && (p[1] < '0' || p[1] > '9'))
8068 goto skip;
8069 return false;
8070 skip:
8071 if (st_test_skip == 0)
8072 return true;
8073 if (strstr(st_test_skip, test.key) != 0)
8074 return false;
8075 p = strchr(st_test_skip, test.key[0]);
8076 if (p != 0 && (p[1] < '0' || p[1] > '9'))
8077 return false;
8078 return true;
8079 }
8080
8081 static int
st_test(ST_Con & c,const ST_Test & test)8082 st_test(ST_Con& c, const ST_Test& test)
8083 {
8084 chk1(st_end_trans(c, ST_AbortFlag) == 0);
8085 chk1(st_drop_test_tables(c) == 0);
8086 chk1(st_check_db_nodes(c) == 0);
8087
8088 g_err << test << endl;
8089 if (c.numdbnodes < test.mindbnodes) {
8090 g_err << "skip, too few db nodes" << endl;
8091 return NDBT_OK;
8092 }
8093
8094 chk1((*test.func)(c, test.arg) == NDBT_OK);
8095 chk1(st_check_db_nodes(c) == 0);
8096 //chk1(st_verify_list(c) == 0);
8097
8098 return NDBT_OK;
8099 err:
8100 return NDBT_FAILED;
8101 }
8102
8103 static int st_random_seed = -1;
8104
8105 int
runSchemaTrans(NDBT_Context * ctx,NDBT_Step * step)8106 runSchemaTrans(NDBT_Context* ctx, NDBT_Step* step)
8107 {
8108 #ifdef NDB_USE_GET_ENV
8109 { const char* env = NdbEnv_GetEnv("NDB_TEST_DBUG", 0, 0);
8110 if (env != 0 && env[0] != 0) // e.g. d:t:L:F:o,ndb_test.log
8111 DBUG_PUSH(env);
8112 }
8113 { const char* env = NdbEnv_GetEnv("NDB_TEST_CORE", 0, 0);
8114 if (env != 0 && env[0] != 0 && env[0] != '0' && env[0] != 'N')
8115 st_core_on_err = true;
8116 }
8117 { const char* env = NdbEnv_GetEnv("NDB_TEST_CASE", 0, 0);
8118 st_test_case = env;
8119 }
8120 { const char* env = NdbEnv_GetEnv("NDB_TEST_SKIP", 0, 0);
8121 st_test_skip = env;
8122 }
8123 { const char* env = NdbEnv_GetEnv("NDB_TEST_SEED", 0, 0);
8124 if (env != 0)
8125 st_random_seed = atoi(env);
8126 }
8127 #endif
8128 if (st_test_case != 0 && strcmp(st_test_case, "?") == 0) {
8129 int i;
8130 ndbout << "case func+arg desc" << endl;
8131 for (i = 0; i < st_test_count; i++) {
8132 const ST_Test& test = st_test_list[i];
8133 ndbout << test << endl;
8134 }
8135 return NDBT_WRONGARGS;
8136 }
8137
8138 if (st_random_seed == -1)
8139 st_random_seed = NdbHost_GetProcessId();
8140 if (st_random_seed != 0) {
8141 g_err << "random seed: " << st_random_seed << endl;
8142 ndb_srand(st_random_seed);
8143 } else {
8144 g_err << "random seed: loop number" << endl;
8145 }
8146
8147 Ndb_cluster_connection* ncc = &ctx->m_cluster_connection;
8148 Ndb* ndb = GETNDB(step);
8149 ST_Restarter* restarter = new ST_Restarter;
8150 ST_Con c(ncc, ndb, restarter);
8151
8152 chk1(st_drop_all_tables(c) == 0);
8153 st_init_objects(c, ctx);
8154
8155 int numloops;
8156 numloops = ctx->getNumLoops();
8157
8158 for (c.loop = 0; numloops == 0 || c.loop < numloops; c.loop++) {
8159 g_err << "LOOP " << c.loop << endl;
8160 if (st_random_seed == 0)
8161 ndb_srand(c.loop);
8162 int i;
8163 for (i = 0; i < st_test_count; i++) {
8164 const ST_Test& test = st_test_list[i];
8165 if (st_test_match(test)) {
8166 chk1(st_test(c, test) == NDBT_OK);
8167 }
8168 }
8169 }
8170
8171 st_report_db_nodes(c, g_err);
8172 return NDBT_OK;
8173 err:
8174 st_report_db_nodes(c, g_err);
8175 return NDBT_FAILED;
8176 }
8177
8178 // end schema trans
8179
8180 int
runFailCreateHashmap(NDBT_Context * ctx,NDBT_Step * step)8181 runFailCreateHashmap(NDBT_Context* ctx, NDBT_Step* step)
8182 {
8183 static int lst[] = { 6204, 6205, 6206, 6207, 6208, 6209, 6210, 6211, 0 };
8184
8185 NdbRestarter restarter;
8186 int nodeId = restarter.getMasterNodeId();
8187 Ndb* pNdb = GETNDB(step);
8188 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8189
8190 int errNo = 0;
8191 #ifdef NDB_USE_GET_ENV
8192 char buf[100];
8193 if (NdbEnv_GetEnv("ERRNO", buf, sizeof(buf)))
8194 {
8195 errNo = atoi(buf);
8196 ndbout_c("Using errno: %u", errNo);
8197 }
8198 #endif
8199 const int loops = ctx->getNumLoops();
8200 int result = NDBT_OK;
8201
8202 int dump1 = DumpStateOrd::SchemaResourceSnapshot;
8203 int dump2 = DumpStateOrd::SchemaResourceCheckLeak;
8204
8205 NdbDictionary::HashMap hm;
8206 pDic->initDefaultHashMap(hm, 1);
8207
8208 loop:
8209 if (pDic->getHashMap(hm, hm.getName()) != -1)
8210 {
8211 pDic->initDefaultHashMap(hm, rand() % 64);
8212 goto loop;
8213 }
8214
8215 for (int l = 0; l < loops; l++)
8216 {
8217 for (unsigned i0 = 0; lst[i0]; i0++)
8218 {
8219 unsigned j = (l == 0 ? i0 : myRandom48(i0 + l));
8220 int errval = lst[j];
8221 if (errNo != 0 && errNo != errval)
8222 continue;
8223 g_info << "insert error node=" << nodeId << " value=" << errval << endl;
8224 CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
8225 "failed to set error insert");
8226 CHECK(restarter.dumpStateAllNodes(&dump1, 1) == 0);
8227
8228 int res = pDic->createHashMap(hm);
8229 CHECK2(res != 0, "create hashmap failed to fail");
8230
8231 NdbDictionary::HashMap check;
8232 CHECK2(res != 0, "create hashmap existed");
8233
8234 CHECK2(restarter.insertErrorInNode(nodeId, 0) == 0,
8235 "failed to clear error insert");
8236 CHECK(restarter.dumpStateAllNodes(&dump2, 1) == 0);
8237 }
8238 }
8239 end:
8240 return result;
8241 }
8242 // end FAIL create hashmap
8243
8244 int
runCreateHashmaps(NDBT_Context * ctx,NDBT_Step * step)8245 runCreateHashmaps(NDBT_Context* ctx, NDBT_Step* step)
8246 {
8247 NdbRestarter restarter;
8248 // int nodeId = restarter.getMasterNodeId();
8249 Ndb* pNdb = GETNDB(step);
8250 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8251
8252 const int loops = ctx->getNumLoops();
8253 int result = NDBT_OK;
8254
8255 NdbDictionary::HashMap hm;
8256
8257 int created = 0;
8258 for (int i = 1; i <= NDB_DEFAULT_HASHMAP_BUCKETS && created < loops ; i++)
8259 {
8260 pDic->initDefaultHashMap(hm, i);
8261 int res = pDic->getHashMap(hm, hm.getName());
8262 if (res == -1)
8263 {
8264 const NdbError err = pDic->getNdbError();
8265 if (err.code != 723)
8266 {
8267 g_err << "getHashMap: " << hm.getName() << ": " << err << endl;
8268 result = NDBT_FAILED;
8269 break;
8270 }
8271 int res = pDic->createHashMap(hm);
8272 if (res == -1)
8273 {
8274 const NdbError err = pDic->getNdbError();
8275 if (err.code != 707 && err.code != 712)
8276 {
8277 g_err << "createHashMap: " << hm.getName() << ": " << err << endl;
8278 result = NDBT_FAILED;
8279 }
8280 break;
8281 }
8282 created++;
8283 }
8284 }
8285
8286 // Drop all hashmaps (and everything else) with initial restart
8287 ndbout << "Restarting cluster" << endl;
8288 restarter.restartAll(/* initial */ true);
8289 restarter.waitClusterStarted();
8290
8291 return result;
8292 }
8293 // end FAIL create hashmap
8294
8295 int
runFailAddPartition(NDBT_Context * ctx,NDBT_Step * step)8296 runFailAddPartition(NDBT_Context* ctx, NDBT_Step* step)
8297 {
8298 static int lst[] = { 7211, 7212, 4050, 12008, 6212, 6124, 6213, 6214, 0 };
8299
8300 Ndb* pNdb = GETNDB(step);
8301 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8302 NdbDictionary::Table tab(*ctx->getTab());
8303 NdbRestarter restarter;
8304 int nodeId = restarter.getMasterNodeId();
8305
8306 int errNo = 0;
8307 #ifdef NDB_USE_GET_ENV
8308 char buf[100];
8309 if (NdbEnv_GetEnv("ERRNO", buf, sizeof(buf)))
8310 {
8311 errNo = atoi(buf);
8312 ndbout_c("Using errno: %u", errNo);
8313 }
8314 #endif
8315 // ordered index on first few columns
8316 NdbDictionary::Index idx("X");
8317 idx.setTable(tab.getName());
8318 idx.setType(NdbDictionary::Index::OrderedIndex);
8319 idx.setLogging(false);
8320 for (int cnt = 0, i_hate_broken_compilers = 0;
8321 cnt < 3 &&
8322 i_hate_broken_compilers < tab.getNoOfColumns();
8323 i_hate_broken_compilers++) {
8324 if (NdbSqlUtil::check_column_for_ordered_index
8325 (tab.getColumn(i_hate_broken_compilers)->getType(), 0) == 0 &&
8326 tab.getColumn(i_hate_broken_compilers)->getStorageType() !=
8327 NdbDictionary::Column::StorageTypeDisk)
8328 {
8329 idx.addColumn(*tab.getColumn(i_hate_broken_compilers));
8330 cnt++;
8331 }
8332 }
8333
8334 for (int i = 0; i<tab.getNoOfColumns(); i++)
8335 {
8336 if (tab.getColumn(i)->getStorageType() ==
8337 NdbDictionary::Column::StorageTypeDisk)
8338 {
8339 NDBT_Tables::create_default_tablespace(pNdb);
8340 break;
8341 }
8342 }
8343
8344 const int loops = ctx->getNumLoops();
8345 int result = NDBT_OK;
8346 (void)pDic->dropTable(tab.getName());
8347 if (pDic->createTable(tab) != 0)
8348 {
8349 ndbout << "FAIL: " << pDic->getNdbError() << endl;
8350 return NDBT_FAILED;
8351 }
8352
8353 if (pDic->createIndex(idx) != 0)
8354 {
8355 ndbout << "FAIL: " << pDic->getNdbError() << endl;
8356 return NDBT_FAILED;
8357 }
8358
8359 const NdbDictionary::Table * org = pDic->getTable(tab.getName());
8360 NdbDictionary::Table altered = * org;
8361 altered.setFragmentCount(org->getFragmentCount() +
8362 restarter.getNumDbNodes());
8363 altered.setPartitionBalance(NdbDictionary::Object::PartitionBalance_Specific);
8364
8365 if (pDic->beginSchemaTrans())
8366 {
8367 ndbout << "Failed to beginSchemaTrans()" << pDic->getNdbError() << endl;
8368 return NDBT_FAILED;
8369 }
8370
8371 if (pDic->prepareHashMap(*org, altered) == -1)
8372 {
8373 ndbout << "Failed to create hashmap: " << pDic->getNdbError() << endl;
8374 return NDBT_FAILED;
8375 }
8376
8377 if (pDic->endSchemaTrans())
8378 {
8379 ndbout << "Failed to endSchemaTrans()" << pDic->getNdbError() << endl;
8380 return NDBT_FAILED;
8381 }
8382
8383 int dump1 = DumpStateOrd::SchemaResourceSnapshot;
8384 int dump2 = DumpStateOrd::SchemaResourceCheckLeak;
8385
8386 for (int l = 0; l < loops; l++)
8387 {
8388 for (unsigned i0 = 0; lst[i0]; i0++)
8389 {
8390 unsigned j = (l == 0 ? i0 : myRandom48(sizeof(lst)/sizeof(lst[0]) - 1));
8391 int errval = lst[j];
8392 if (errNo != 0 && errNo != errval)
8393 continue;
8394 g_err << "insert error node=" << nodeId << " value=" << errval << endl;
8395 CHECK(restarter.dumpStateAllNodes(&dump1, 1) == 0);
8396 CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
8397 "failed to set error insert");
8398
8399 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
8400
8401 int res = pDic->alterTable(*org, altered);
8402 if (res)
8403 {
8404 ndbout << pDic->getNdbError() << endl;
8405 }
8406 CHECK2(res != 0,
8407 "failed to fail after error insert " << errval);
8408 CHECK2(restarter.insertErrorInNode(nodeId, 0) == 0,
8409 "failed to clear error insert");
8410 CHECK(restarter.dumpStateAllNodes(&dump2, 1) == 0);
8411 NdbSleep_MilliSleep(SAFTY); // Hope that snapshot has arrived
8412
8413 int dump3[] = {DumpStateOrd::DihAddFragFailCleanedUp, org->getTableId()};
8414 CHECK(restarter.dumpStateAllNodes(dump3, 2) == 0);
8415
8416 const NdbDictionary::Table* check = pDic->getTable(tab.getName());
8417
8418 CHECK2((check->getObjectId() == org->getObjectId() &&
8419 check->getObjectVersion() == org->getObjectVersion()),
8420 "table has been altered!");
8421 }
8422 }
8423
8424 end:
8425 (void)pDic->dropTable(tab.getName());
8426 return result;
8427 }
8428 // fail add partition
8429
8430 int
runTableAddPartition(NDBT_Context * ctx,NDBT_Step * step)8431 runTableAddPartition(NDBT_Context* ctx, NDBT_Step* step){
8432
8433 int result = NDBT_OK;
8434
8435 Ndb* pNdb = GETNDB(step);
8436 NdbDictionary::Dictionary* dict = pNdb->getDictionary();
8437 int records = ctx->getNumRecords();
8438 const int loops = ctx->getNumLoops();
8439
8440 ndbout << "|- " << ctx->getTab()->getName() << endl;
8441
8442 NdbDictionary::Table myTab= *(ctx->getTab());
8443 myTab.setFragmentType(NdbDictionary::Object::HashMapPartition);
8444
8445 for (int l = 0; l < loops && result == NDBT_OK ; l++)
8446 {
8447 // Try to create table in db
8448 if (NDBT_Tables::createTable(pNdb, myTab.getName()) != 0){
8449 return NDBT_FAILED;
8450 }
8451
8452 // Verify that table is in db
8453 const NdbDictionary::Table* pTab2 =
8454 NDBT_Table::discoverTableFromDb(pNdb, myTab.getName());
8455 if (pTab2 == NULL){
8456 ndbout << myTab.getName() << " was not found in DB"<< endl;
8457 return NDBT_FAILED;
8458 }
8459 ctx->setTab(pTab2);
8460
8461 #if 1
8462 // Load table
8463 const NdbDictionary::Table* pTab;
8464 CHECK((pTab = ctx->getTab()) != NULL);
8465 HugoTransactions beforeTrans(*pTab);
8466 if (beforeTrans.loadTable(pNdb, records) != 0){
8467 return NDBT_FAILED;
8468 }
8469 #endif
8470
8471 // Add attributes to table.
8472 BaseString pTabName(pTab2->getName());
8473 const NdbDictionary::Table * oldTable = dict->getTable(pTabName.c_str());
8474
8475 NdbDictionary::Table newTable= *oldTable;
8476
8477 newTable.setFragmentCount(2 * oldTable->getFragmentCount());
8478 newTable.setPartitionBalance(
8479 NdbDictionary::Object::PartitionBalance_Specific);
8480 CHECK2(dict->alterTable(*oldTable, newTable) == 0,
8481 "TableAddAttrs failed");
8482
8483 /* Need to purge old version and reload new version after alter table. */
8484 dict->invalidateTable(pTabName.c_str());
8485
8486 #if 0
8487 {
8488 HugoTransactions afterTrans(* dict->getTable(pTabName.c_str()));
8489
8490 ndbout << "delete...";
8491 if (afterTrans.clearTable(pNdb) != 0)
8492 {
8493 return NDBT_FAILED;
8494 }
8495 ndbout << endl;
8496
8497 ndbout << "insert...";
8498 if (afterTrans.loadTable(pNdb, records) != 0){
8499 return NDBT_FAILED;
8500 }
8501 ndbout << endl;
8502
8503 ndbout << "update...";
8504 if (afterTrans.scanUpdateRecords(pNdb, records) != 0)
8505 {
8506 return NDBT_FAILED;
8507 }
8508 ndbout << endl;
8509
8510 ndbout << "delete...";
8511 if (afterTrans.clearTable(pNdb) != 0)
8512 {
8513 return NDBT_FAILED;
8514 }
8515 ndbout << endl;
8516 }
8517 #endif
8518 abort();
8519 // Drop table.
8520 dict->dropTable(pTabName.c_str());
8521 }
8522 end:
8523
8524 return result;
8525 }
8526
8527 int
runBug41905(NDBT_Context * ctx,NDBT_Step * step)8528 runBug41905(NDBT_Context* ctx, NDBT_Step* step)
8529 {
8530 const NdbDictionary::Table* pTab = ctx->getTab();
8531 BaseString tabName(pTab->getName());
8532 Ndb* pNdb = GETNDB(step);
8533 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8534
8535 NdbDictionary::Table creTab = *pTab;
8536 creTab.setForceVarPart(true);
8537 int ret = NDBT_OK;
8538
8539 (void)pDic->dropTable(tabName.c_str());
8540 if (pDic->createTable(creTab)) {
8541 g_err << __LINE__ << ": " << pDic->getNdbError() << endl;
8542 ret = NDBT_FAILED;
8543 }
8544
8545 Uint32 cols = creTab.getNoOfColumns();
8546 Uint32 vers = 0;
8547 while (ret == NDBT_OK) {
8548 const NdbDictionary::Table* pOldTab = pDic->getTableGlobal(tabName.c_str());
8549 require(pOldTab != 0);
8550
8551 const Uint32 old_st = pOldTab->getObjectStatus();
8552 const Uint32 old_cols = pOldTab->getNoOfColumns();
8553 const Uint32 old_vers = pOldTab->getObjectVersion() >> 24;
8554
8555 if (old_st != NdbDictionary::Object::Retrieved) {
8556 g_err << __LINE__ << ": " << "got status " << old_st << endl;
8557 ret = NDBT_FAILED;
8558 break;
8559 }
8560 // bug#41905 or related: other thread causes us to get old version
8561 if (old_cols != cols || old_vers != vers) {
8562 g_err << __LINE__ << ": "
8563 << "got cols,vers " << old_cols << "," << old_vers
8564 << " expected " << cols << "," << vers << endl;
8565 ret = NDBT_FAILED;
8566 break;
8567 }
8568 if (old_cols >= 100)
8569 break;
8570 const NdbDictionary::Table& oldTab = *pOldTab;
8571
8572 NdbDictionary::Table newTab = oldTab;
8573 char colName[100];
8574 sprintf(colName, "COL41905_%02d", cols);
8575 g_info << "add " << colName << endl;
8576 NDBT_Attribute newCol(colName, NdbDictionary::Column::Unsigned, 1,
8577 false, true, (CHARSET_INFO*)0,
8578 NdbDictionary::Column::StorageTypeMemory, true);
8579 newTab.addColumn(newCol);
8580
8581 ctx->setProperty("Bug41905", 1);
8582 NdbSleep_MilliSleep(10);
8583
8584 const bool removeEarly = (uint)rand() % 2;
8585 g_info << "removeEarly = " << removeEarly << endl;
8586
8587 if (pDic->beginSchemaTrans() != 0) {
8588 g_err << __LINE__ << ": " << pDic->getNdbError() << endl;
8589 ret = NDBT_FAILED;
8590 break;
8591 }
8592 if (pDic->alterTable(oldTab, newTab) != 0) {
8593 g_err << __LINE__ << ": " << pDic->getNdbError() << endl;
8594 ret = NDBT_FAILED;
8595 break;
8596 }
8597
8598 if (removeEarly)
8599 pDic->removeTableGlobal(*pOldTab, 0);
8600
8601 if (pDic->endSchemaTrans() != 0) {
8602 g_err << __LINE__ << ": " << pDic->getNdbError() << endl;
8603 ret = NDBT_FAILED;
8604 break;
8605 }
8606
8607 cols++;
8608 vers++;
8609 if (!removeEarly)
8610 pDic->removeTableGlobal(*pOldTab, 0);
8611 ctx->setProperty("Bug41905", 2);
8612 NdbSleep_MilliSleep(10);
8613 }
8614
8615 ctx->setProperty("Bug41905", 3);
8616 return ret;
8617 }
8618
8619 int
runBug41905getTable(NDBT_Context * ctx,NDBT_Step * step)8620 runBug41905getTable(NDBT_Context* ctx, NDBT_Step* step)
8621 {
8622 const NdbDictionary::Table* pTab = ctx->getTab();
8623 BaseString tabName(pTab->getName());
8624 Ndb* pNdb = GETNDB(step);
8625 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8626
8627 while (1) {
8628 while (1) {
8629 if (ctx->getProperty("Bug41905") == 1)
8630 break;
8631 if (ctx->getProperty("Bug41905") == 3)
8632 goto out;
8633 NdbSleep_MilliSleep(10);
8634 }
8635
8636 uint ms = (uint)rand() % 1000;
8637 NdbSleep_MilliSleep(ms);
8638 g_info << "get begin ms=" << ms << endl;
8639
8640 Uint32 count = 0;
8641 Uint32 oldstatus = 0;
8642 while (1) {
8643 count++;
8644 const NdbDictionary::Table* pTmp = pDic->getTableGlobal(tabName.c_str());
8645 require(pTmp != 0);
8646 Uint32 code = pDic->getNdbError().code;
8647 Uint32 status = pTmp->getObjectStatus();
8648 if (oldstatus == 2 && status == 3)
8649 g_info << "code=" << code << " status=" << status << endl;
8650 oldstatus = status;
8651 pDic->removeTableGlobal(*pTmp, 0);
8652 if (ctx->getProperty("Bug41905") != 1)
8653 break;
8654 NdbSleep_MilliSleep(10);
8655 }
8656 g_info << "get end count=" << count << endl;
8657 }
8658
8659 out:
8660 (void)pDic->dropTable(tabName.c_str());
8661 return NDBT_OK;
8662 }
8663
8664 static
8665 int
createIndexes(NdbDictionary::Dictionary * pDic,const NdbDictionary::Table & tab,int cnt)8666 createIndexes(NdbDictionary::Dictionary* pDic,
8667 const NdbDictionary::Table & tab, int cnt)
8668 {
8669 for (int i = 0; i<cnt && i < tab.getNoOfColumns(); i++)
8670 {
8671 char buf[256];
8672 NdbDictionary::Index idx0;
8673 BaseString::snprintf(buf, sizeof(buf), "%s-idx-%u", tab.getName(), i);
8674 idx0.setName(buf);
8675 idx0.setType(NdbDictionary::Index::OrderedIndex);
8676 idx0.setTable(tab.getName());
8677 idx0.setStoredIndex(false);
8678 idx0.addIndexColumn(tab.getColumn(i)->getName());
8679
8680 if (pDic->createIndex(idx0))
8681 {
8682 ndbout << pDic->getNdbError() << endl;
8683 return NDBT_FAILED;
8684 }
8685 }
8686
8687 return 0;
8688 }
8689
8690 int
runBug46552(NDBT_Context * ctx,NDBT_Step * step)8691 runBug46552(NDBT_Context* ctx, NDBT_Step* step)
8692 {
8693 Ndb* pNdb = GETNDB(step);
8694 const NdbDictionary::Table* pTab = ctx->getTab();
8695 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8696
8697 NdbRestarter res;
8698 int numDbNodes = res.getNumDbNodes();
8699 getNodeGroups(res);
8700 int num_replicas = (numDbNodes - numNoNodeGroups) / numNodeGroups;
8701 if (res.getNumDbNodes() < 2 || num_replicas != 2)
8702 return NDBT_OK;
8703
8704 NdbDictionary::Table tab0 = *pTab;
8705 NdbDictionary::Table tab1 = *pTab;
8706
8707 BaseString name;
8708 name.assfmt("%s_0", tab0.getName());
8709 tab0.setName(name.c_str());
8710 name.assfmt("%s_1", tab1.getName());
8711 tab1.setName(name.c_str());
8712
8713 pDic->dropTable(tab0.getName());
8714 pDic->dropTable(tab1.getName());
8715
8716 if (pDic->createTable(tab0))
8717 {
8718 ndbout << pDic->getNdbError() << endl;
8719 return NDBT_FAILED;
8720 }
8721
8722 if (pDic->createTable(tab1))
8723 {
8724 ndbout << pDic->getNdbError() << endl;
8725 return NDBT_FAILED;
8726 }
8727
8728 if (createIndexes(pDic, tab1, 4))
8729 return NDBT_FAILED;
8730
8731 Vector<int> group1;
8732 Vector<int> group2;
8733 Bitmask<256/32> nodeGroupMap;
8734 for (int j = 0; j<res.getNumDbNodes(); j++)
8735 {
8736 int node = res.getDbNodeId(j);
8737 int ng = res.getNodeGroup(node);
8738 if (nodeGroupMap.get(ng))
8739 {
8740 group2.push_back(node);
8741 }
8742 else
8743 {
8744 group1.push_back(node);
8745 nodeGroupMap.set(ng);
8746 }
8747 }
8748
8749 res.restartNodes(group1.getBase(), (int)group1.size(),
8750 NdbRestarter::NRRF_NOSTART |
8751 NdbRestarter::NRRF_ABORT);
8752
8753 res.waitNodesNoStart(group1.getBase(), (int)group1.size());
8754 res.startNodes(group1.getBase(), (int)group1.size());
8755 res.waitClusterStarted();
8756
8757 res.restartNodes(group2.getBase(), (int)group2.size(),
8758 NdbRestarter::NRRF_NOSTART |
8759 NdbRestarter::NRRF_ABORT);
8760 res.waitNodesNoStart(group2.getBase(), (int)group2.size());
8761 res.startNodes(group2.getBase(), (int)group2.size());
8762 res.waitClusterStarted();
8763 CHK_NDB_READY(pNdb);
8764
8765 if (pDic->dropTable(tab0.getName()))
8766 {
8767 ndbout << pDic->getNdbError() << endl;
8768 return NDBT_FAILED;
8769 }
8770
8771 if (pDic->createTable(tab0))
8772 {
8773 ndbout << pDic->getNdbError() << endl;
8774 return NDBT_FAILED;
8775 }
8776
8777 if (createIndexes(pDic, tab0, 4))
8778 return NDBT_FAILED;
8779
8780 res.restartAll2(NdbRestarter::NRRF_NOSTART | NdbRestarter::NRRF_ABORT);
8781 res.waitClusterNoStart();
8782 res.startAll();
8783 res.waitClusterStarted();
8784 CHK_NDB_READY(pNdb);
8785
8786 if (pDic->dropTable(tab0.getName()))
8787 {
8788 ndbout << pDic->getNdbError() << endl;
8789 return NDBT_FAILED;
8790 }
8791
8792 if (pDic->dropTable(tab1.getName()))
8793 {
8794 ndbout << pDic->getNdbError() << endl;
8795 return NDBT_FAILED;
8796 }
8797
8798 return NDBT_OK;
8799 }
8800
8801 int
runBug46585(NDBT_Context * ctx,NDBT_Step * step)8802 runBug46585(NDBT_Context* ctx, NDBT_Step* step)
8803 {
8804 Ndb* pNdb = GETNDB(step);
8805 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8806 NdbDictionary::Table tab(*ctx->getTab());
8807 NdbRestarter res;
8808 int records = ctx->getNumRecords();
8809
8810 // ordered index on first few columns
8811 NdbDictionary::Index idx("X");
8812 idx.setTable(tab.getName());
8813 idx.setType(NdbDictionary::Index::OrderedIndex);
8814 idx.setLogging(false);
8815 for (int cnt = 0, i_hate_broken_compilers = 0;
8816 cnt < 3 &&
8817 i_hate_broken_compilers < tab.getNoOfColumns();
8818 i_hate_broken_compilers++) {
8819 if (NdbSqlUtil::check_column_for_ordered_index
8820 (tab.getColumn(i_hate_broken_compilers)->getType(), 0) == 0 &&
8821 tab.getColumn(i_hate_broken_compilers)->getStorageType() !=
8822 NdbDictionary::Column::StorageTypeDisk)
8823 {
8824 idx.addColumn(*tab.getColumn(i_hate_broken_compilers));
8825 cnt++;
8826 }
8827 }
8828
8829 for (int i = 0; i<tab.getNoOfColumns(); i++)
8830 {
8831 if (tab.getColumn(i)->getStorageType() ==
8832 NdbDictionary::Column::StorageTypeDisk)
8833 {
8834 NDBT_Tables::create_default_tablespace(pNdb);
8835 break;
8836 }
8837 }
8838
8839 const int loops = ctx->getNumLoops();
8840 int result = NDBT_OK;
8841 (void)pDic->dropTable(tab.getName());
8842 if (pDic->createTable(tab) != 0)
8843 {
8844 ndbout << "FAIL: " << pDic->getNdbError() << endl;
8845 return NDBT_FAILED;
8846 }
8847
8848 if (pDic->createIndex(idx) != 0)
8849 {
8850 ndbout << "FAIL: " << pDic->getNdbError() << endl;
8851 return NDBT_FAILED;
8852 }
8853
8854 for (int i = 0; i<loops; i++)
8855 {
8856 const NdbDictionary::Table * org = pDic->getTable(tab.getName());
8857 {
8858 CHECK(org != NULL);
8859 HugoTransactions trans(* org);
8860 CHECK2(trans.loadTable(pNdb, records) == 0,
8861 "load table failed");
8862 }
8863
8864 NdbDictionary::Table altered = * org;
8865 altered.setFragmentCount(org->getFragmentCount() + 1);
8866 altered.setPartitionBalance(
8867 NdbDictionary::Object::PartitionBalance_Specific);
8868 ndbout_c("alter from %u to %u partitions",
8869 org->getFragmentCount(),
8870 altered.getFragmentCount());
8871
8872 if (pDic->beginSchemaTrans())
8873 {
8874 ndbout << "Failed to beginSchemaTrans()" << pDic->getNdbError() << endl;
8875 return NDBT_FAILED;
8876 }
8877
8878 if (pDic->prepareHashMap(*org, altered) == -1)
8879 {
8880 ndbout << "Failed to create hashmap: " << pDic->getNdbError() << endl;
8881 return NDBT_FAILED;
8882 }
8883
8884 if (pDic->endSchemaTrans())
8885 {
8886 ndbout << "Failed to endSchemaTrans()" << pDic->getNdbError() << endl;
8887 return NDBT_FAILED;
8888 }
8889
8890 result = pDic->alterTable(*org, altered);
8891 if (result)
8892 {
8893 ndbout << pDic->getNdbError() << endl;
8894 }
8895 if (pDic->getNdbError().code == 1224)
8896 {
8897 /**
8898 * To many fragments is an acceptable error
8899 * depending on configuration used for test-case
8900 */
8901 result = NDBT_OK;
8902 goto end;
8903 }
8904 CHECK2(result == 0,
8905 "failed to alter");
8906
8907 pDic->invalidateTable(tab.getName());
8908 {
8909 const NdbDictionary::Table * alteredP = pDic->getTable(tab.getName());
8910 CHECK2(alteredP->getFragmentCount() == altered.getFragmentCount(),
8911 "altered table does not have correct frag count");
8912
8913 HugoTransactions trans(* alteredP);
8914
8915 CHECK2(trans.scanUpdateRecords(pNdb, records) == 0,
8916 "scan update failed");
8917 trans.startTransaction(pNdb);
8918 trans.pkUpdateRecord(pNdb, 0);
8919 trans.execute_Commit(pNdb);
8920 ndbout_c("before restart, gci: %d", trans.getRecordGci(0));
8921 trans.closeTransaction(pNdb);
8922 }
8923
8924 switch(i % 2){
8925 case 0:
8926 if (res.getNumDbNodes() > 1)
8927 {
8928 int nodeId = res.getNode(NdbRestarter::NS_RANDOM);
8929 ndbout_c("performing node-restart of node %d", nodeId);
8930 CHECK2(res.restartOneDbNode(nodeId,
8931 false,
8932 true,
8933 true) == 0,
8934 "restart one node failed");
8935 CHECK2(res.waitNodesNoStart(&nodeId, 1) == 0,
8936 "wait node started failed");
8937 CHECK2(res.startNodes(&nodeId, 1) == 0,
8938 "start node failed");
8939 break;
8940 }
8941 // Fall through - only system restart possible with one node
8942 case 1:
8943 {
8944 ndbout_c("performing system restart");
8945 CHECK2(res.restartAll(false, true, false) == 0,
8946 "restart all failed");
8947 CHECK2(res.waitClusterNoStart() == 0,
8948 "waitClusterNoStart failed");
8949 CHECK2(res.startAll() == 0,
8950 "startAll failed");
8951 break;
8952 }
8953 }
8954 CHECK2(res.waitClusterStarted() == 0,
8955 "wait cluster started failed");
8956 CHK_NDB_READY(pNdb);
8957
8958 Uint32 restartGCI = 0;
8959 CHECK2(pDic->getRestartGCI(&restartGCI) == 0,
8960 "getRestartGCI failed");
8961 ndbout_c("restartGCI: %u", restartGCI);
8962
8963 pDic->invalidateTable(tab.getName());
8964 {
8965 const NdbDictionary::Table * alteredP = pDic->getTable(tab.getName());
8966 CHECK(alteredP != NULL);
8967 HugoTransactions trans(* alteredP);
8968
8969 int cnt;
8970 CHECK2(trans.selectCount(pNdb, 0, &cnt) == 0,
8971 "select count failed");
8972
8973 CHECK2(cnt == records,
8974 "table does not have correct record count: "
8975 << cnt << " != " << records);
8976
8977 CHECK2(alteredP->getFragmentCount() == altered.getFragmentCount(),
8978 "altered table does not have correct frag count");
8979
8980 CHECK2(trans.scanUpdateRecords(pNdb, records) == 0,
8981 "scan update failed");
8982 CHECK2(trans.pkUpdateRecords(pNdb, records) == 0,
8983 "pkUpdateRecords failed");
8984 CHECK2(trans.clearTable(pNdb) == 0,
8985 "clear table failed");
8986 }
8987 }
8988
8989 end:
8990 (void)pDic->dropTable(tab.getName());
8991 return result;
8992 }
8993
8994 int
runBug53944(NDBT_Context * ctx,NDBT_Step * step)8995 runBug53944(NDBT_Context* ctx, NDBT_Step* step)
8996 {
8997 Ndb* pNdb = GETNDB(step);
8998 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
8999 NdbDictionary::Table tab(*ctx->getTab());
9000 NdbRestarter res;
9001
9002 Vector<int> ids;
9003 for (unsigned i = 0; i< 25; i++)
9004 {
9005 NdbDictionary::Table copy = tab;
9006 BaseString name;
9007 name.appfmt("%s_%u", copy.getName(), i);
9008 copy.setName(name.c_str());
9009 int res = pDic->createTable(copy);
9010 if (res)
9011 {
9012 g_err << "Failed to create table" << copy.getName() << "\n"
9013 << pDic->getNdbError() << endl;
9014 return NDBT_FAILED;
9015 }
9016 const NdbDictionary::Table* tab = pDic->getTable(copy.getName());
9017 if (tab == 0)
9018 {
9019 g_err << "Failed to retreive table" << copy.getName() << endl;
9020 return NDBT_FAILED;
9021
9022 }
9023 ids.push_back(tab->getObjectId());
9024 }
9025
9026 res.restartAll2(NdbRestarter::NRRF_ABORT | NdbRestarter::NRRF_NOSTART);
9027 res.waitClusterNoStart();
9028 res.startAll();
9029 res.waitClusterStarted();
9030 CHK_NDB_READY(pNdb);
9031
9032 for (unsigned i = 0; i< 25; i++)
9033 {
9034 NdbDictionary::Table copy = tab;
9035 BaseString name;
9036 name.appfmt("%s_%u", copy.getName(), i);
9037 copy.setName(name.c_str());
9038 const NdbDictionary::Table* tab = pDic->getTable(copy.getName());
9039 if (tab == 0)
9040 {
9041 g_err << "Failed to retreive table" << copy.getName() << endl;
9042 return NDBT_FAILED;
9043
9044 }
9045 int res = pDic->dropTable(copy.getName());
9046 if (res)
9047 {
9048 g_err << "Failed to drop table" << copy.getName() << "\n"
9049 << pDic->getNdbError() << endl;
9050 return NDBT_FAILED;
9051 }
9052 }
9053
9054 Vector<int> ids2;
9055 for (unsigned i = 0; i< 25; i++)
9056 {
9057 NdbDictionary::Table copy = tab;
9058 BaseString name;
9059 name.appfmt("%s_%u", copy.getName(), i);
9060 copy.setName(name.c_str());
9061 int res = pDic->createTable(copy);
9062 if (res)
9063 {
9064 g_err << "Failed to create table" << copy.getName() << "\n"
9065 << pDic->getNdbError() << endl;
9066 return NDBT_FAILED;
9067 }
9068 const NdbDictionary::Table* tab = pDic->getTable(copy.getName());
9069 if (tab == 0)
9070 {
9071 g_err << "Failed to retreive table" << copy.getName() << endl;
9072 return NDBT_FAILED;
9073
9074 }
9075 ids2.push_back(tab->getObjectId());
9076 }
9077
9078 for (unsigned i = 0; i< 25; i++)
9079 {
9080 NdbDictionary::Table copy = tab;
9081 BaseString name;
9082 name.appfmt("%s_%u", copy.getName(), i);
9083 copy.setName(name.c_str());
9084 const NdbDictionary::Table* tab = pDic->getTable(copy.getName());
9085 if (tab == 0)
9086 {
9087 g_err << "Failed to retreive table" << copy.getName() << endl;
9088 return NDBT_FAILED;
9089
9090 }
9091 int res = pDic->dropTable(copy.getName());
9092 if (res)
9093 {
9094 g_err << "Failed to drop table" << copy.getName() << "\n"
9095 << pDic->getNdbError() << endl;
9096 return NDBT_FAILED;
9097 }
9098 }
9099
9100 /**
9101 * With Bug53944 - none of the table-id have been reused in this scenario
9102 * check that atleast 15 of the 25 have been to return OK
9103 */
9104 unsigned reused = 0;
9105 for (unsigned i = 0; i<ids.size(); i++)
9106 {
9107 int id = ids[i];
9108 for (unsigned j = 0; j<ids2.size(); j++)
9109 {
9110 if (ids2[j] == id)
9111 {
9112 reused++;
9113 break;
9114 }
9115 }
9116 }
9117
9118 ndbout_c("reused %u table-ids out of %u",
9119 (unsigned)reused, (unsigned)ids.size());
9120
9121 if (reused >= (ids.size() >> 2))
9122 {
9123 return NDBT_OK;
9124 }
9125 else
9126 {
9127 return NDBT_FAILED;
9128 }
9129 }
9130
9131 // Bug58277 + Bug57057
9132
9133 #define CHK2(b, e) \
9134 if (!(b)) { \
9135 g_err << "ERR: " << #b << " failed at line " << __LINE__ \
9136 << ": " << e << endl; \
9137 result = NDBT_FAILED; \
9138 break; \
9139 }
9140
9141 // allow list of expected error codes which do not cause NDBT_FAILED
9142 #define CHK3(b, e, x) \
9143 if (!(b)) { \
9144 int n = sizeof(x)/sizeof(x[0]); \
9145 int i; \
9146 for (i = 0; i < n; i++) { \
9147 int s = (x[i] >= 0 ? +1 : -1); \
9148 if (e.code == s * x[i]) { \
9149 if (s == +1) \
9150 g_info << "OK: " << #b << " failed at line " << __LINE__ \
9151 << ": " << e << endl; \
9152 break; \
9153 } \
9154 } \
9155 if (i == n) { \
9156 g_err << "ERR: " << #b << " failed at line " << __LINE__ \
9157 << ": " << e << endl; \
9158 result = NDBT_FAILED; \
9159 } \
9160 break; \
9161 }
9162
9163 const char* tabName_Bug58277 = "TBug58277";
9164 const char* indName_Bug58277 = "TBug58277X1";
9165
9166 static void
sync_main_step(NDBT_Context * ctx,NDBT_Step * step,const char * state)9167 sync_main_step(NDBT_Context* ctx, NDBT_Step* step, const char* state)
9168 {
9169 // total sub-steps
9170 Uint32 sub_steps = ctx->getProperty("SubSteps", (Uint32)0);
9171 require(sub_steps != 0);
9172 // count has been reset before
9173 require(ctx->getProperty("SubCount", (Uint32)0) == 0);
9174 // set the state
9175 g_info << "step main: set " << state << endl;
9176 require(ctx->getProperty(state, (Uint32)0) == 0);
9177 ctx->setProperty(state, (Uint32)1);
9178 // wait for sub-steps
9179 ctx->getPropertyWait("SubCount", sub_steps);
9180 if (ctx->isTestStopped())
9181 return;
9182 g_info << "step main: sub-steps got " << state << endl;
9183 // reset count and state
9184 ctx->setProperty("SubCount", (Uint32)0);
9185 ctx->setProperty(state, (Uint32)0);
9186 }
9187
9188 static void
sync_sub_step(NDBT_Context * ctx,NDBT_Step * step,const char * state)9189 sync_sub_step(NDBT_Context* ctx, NDBT_Step* step, const char* state)
9190 {
9191 // wait for main step to set state
9192 g_info << "step " << step->getStepNo() << ": wait for " << state << endl;
9193 ctx->getPropertyWait(state, (Uint32)1);
9194 if (ctx->isTestStopped())
9195 return;
9196 // add to sub-step counter
9197 ctx->incProperty("SubCount");
9198 g_info << "step " << step->getStepNo() << ": got " << state << endl;
9199 // continue to run until next sync
9200 }
9201
9202 static int
runBug58277createtable(NDBT_Context * ctx,NDBT_Step * step)9203 runBug58277createtable(NDBT_Context* ctx, NDBT_Step* step)
9204 {
9205 Ndb* pNdb = GETNDB(step);
9206 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
9207 int result = NDBT_OK;
9208 const int rows = ctx->getNumRecords();
9209 const char* tabname = tabName_Bug58277;
9210
9211 do
9212 {
9213 CHK2(rows > 0, "cannot use --records=0"); // others require this
9214 g_info << "create table " << tabname << endl;
9215 NdbDictionary::Table tab(tabname);
9216 const char* name[] = { "a", "b" };
9217 for (int i = 0; i <= 1; i++)
9218 {
9219 NdbDictionary::Column c(name[i]);
9220 c.setType(NdbDictionary::Column::Unsigned);
9221 c.setPrimaryKey(i == 0);
9222 c.setNullable(false);
9223 tab.addColumn(c);
9224 }
9225 if (rand() % 3 != 0)
9226 {
9227 g_info << "set FragAllLarge" << endl;
9228 tab.setFragmentType(NdbDictionary::Object::FragAllLarge);
9229 }
9230 CHK2(pDic->createTable(tab) == 0, pDic->getNdbError());
9231 }
9232 while (0);
9233 return result;
9234 }
9235
9236 static int
runBug58277loadtable(NDBT_Context * ctx,NDBT_Step * step)9237 runBug58277loadtable(NDBT_Context* ctx, NDBT_Step* step)
9238 {
9239 Ndb* pNdb = GETNDB(step);
9240 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
9241 int result = NDBT_OK;
9242 const int rows = ctx->getNumRecords();
9243 const char* tabname = tabName_Bug58277;
9244
9245 do
9246 {
9247 g_info << "load table" << endl;
9248 const NdbDictionary::Table* pTab = 0;
9249 CHK2((pTab = pDic->getTable(tabname)) != 0, pDic->getNdbError());
9250
9251 int cnt = 0;
9252 for (int i = 0; i < rows; i++)
9253 {
9254 int retries = 10;
9255 retry:
9256 NdbTransaction* pTx = 0;
9257 CHK2((pTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
9258
9259 NdbOperation* pOp = 0;
9260 CHK2((pOp = pTx->getNdbOperation(pTab)) != 0, pTx->getNdbError());
9261 CHK2(pOp->insertTuple() == 0, pOp->getNdbError());
9262 Uint32 aVal = i;
9263 Uint32 bVal = rand() % rows;
9264 CHK2(pOp->equal("a", (char*)&aVal) == 0, pOp->getNdbError());
9265 CHK2(pOp->setValue("b", bVal) == 0, pOp->getNdbError());
9266
9267 do
9268 {
9269 int x[] = {
9270 -630
9271 };
9272 int res = pTx->execute(Commit);
9273 if (res != 0 &&
9274 pTx->getNdbError().status == NdbError::TemporaryError)
9275 {
9276 retries--;
9277 if (retries >= 0)
9278 {
9279 pTx->close();
9280 NdbSleep_MilliSleep(10);
9281 goto retry;
9282 }
9283 }
9284 CHK3(res == 0, pTx->getNdbError(), x);
9285 cnt++;
9286 }
9287 while (0);
9288 CHK2(result == NDBT_OK, "load failed");
9289 pNdb->closeTransaction(pTx);
9290 }
9291 CHK2(result == NDBT_OK, "load failed");
9292 g_info << "load " << cnt << " rows" << endl;
9293 }
9294 while (0);
9295 return result;
9296 }
9297
9298 static int
runBug58277createindex(NDBT_Context * ctx,NDBT_Step * step)9299 runBug58277createindex(NDBT_Context* ctx, NDBT_Step* step)
9300 {
9301 Ndb* pNdb = GETNDB(step);
9302 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
9303 int result = NDBT_OK;
9304 const char* tabname = tabName_Bug58277;
9305 const char* indname = indName_Bug58277;
9306
9307 do
9308 {
9309 g_info << "create index " << indname << endl;
9310 NdbDictionary::Index ind(indname);
9311 ind.setTable(tabname);
9312 ind.setType(NdbDictionary::Index::OrderedIndex);
9313 ind.setLogging(false);
9314 ind.addColumn("b");
9315 CHK2(pDic->createIndex(ind) == 0, pDic->getNdbError());
9316
9317 const NdbDictionary::Index* pInd = 0;
9318 CHK2((pInd = pDic->getIndex(indname, tabname)) != 0, pDic->getNdbError());
9319 }
9320 while (0);
9321 return result;
9322 }
9323
9324 // separate error handling test
9325 int
runBug58277errtest(NDBT_Context * ctx,NDBT_Step * step)9326 runBug58277errtest(NDBT_Context* ctx, NDBT_Step* step)
9327 {
9328 Ndb* pNdb = GETNDB(step);
9329 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
9330 const int loops = ctx->getNumLoops();
9331 int result = NDBT_OK;
9332 //const int rows = ctx->getNumRecords();
9333 NdbRestarter restarter;
9334 const char* tabname = tabName_Bug58277;
9335 const char* indname = indName_Bug58277;
9336 (void)pDic->dropTable(tabname);
9337
9338 const int errloops = loops < 5 ? loops : 5;
9339 int errloop = 0;
9340 while (!ctx->isTestStopped() && errloop < errloops)
9341 {
9342 g_info << "===== errloop " << errloop << " =====" << endl;
9343
9344 if (errloop == 0)
9345 {
9346 CHK2(runBug58277createtable(ctx, step) == NDBT_OK, "create table failed");
9347 CHK2(runBug58277loadtable(ctx, step) == NDBT_OK, "load table failed");
9348 CHK2(runBug58277createindex(ctx, step) == NDBT_OK, "create index failed");
9349 }
9350 const NdbDictionary::Index* pInd = 0;
9351 CHK2((pInd = pDic->getIndex(indname, tabname)) != 0, pDic->getNdbError());
9352
9353 int errins[] = {
9354 12008, 909, // TuxNoFreeScanOp
9355 12009, 4259 // InvalidBounds
9356 };
9357 const int errcnt = (int)(sizeof(errins)/sizeof(errins[0]));
9358 for (int i = 0; i < errcnt; i += 2)
9359 {
9360 const int ei = errins[i + 0];
9361 const int ec = errins[i + 1];
9362 CHK2(restarter.insertErrorInAllNodes(ei) == 0, "value " << ei);
9363
9364 NdbTransaction* pSTx = 0;
9365 CHK2((pSTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
9366 NdbIndexScanOperation* pSOp = 0;
9367 CHK2((pSOp = pSTx->getNdbIndexScanOperation(pInd)) != 0, pSTx->getNdbError());
9368
9369 NdbOperation::LockMode lm = NdbOperation::LM_Exclusive;
9370 Uint32 flags = 0;
9371 CHK2(pSOp->readTuples(lm, flags) == 0, pSOp->getNdbError());
9372
9373 Uint32 aVal = 0;
9374 CHK2(pSOp->getValue("a", (char*)&aVal) != 0, pSOp->getNdbError());
9375 CHK2(pSTx->execute(NoCommit) == 0, pSTx->getNdbError());
9376 // before fixes 12009 failed to fail at once here
9377 CHK2(pSOp->nextResult(true) == -1, "failed to fail on " << ei);
9378 CHK2(pSOp->getNdbError().code == ec, "expect " << ec << " got " << pSOp->getNdbError());
9379 pNdb->closeTransaction(pSTx);
9380
9381 g_info << "error " << ei << " " << ec << " ok" << endl;
9382 CHK2(restarter.insertErrorInAllNodes(0) == 0, "value " << 0);
9383 }
9384 CHK2(result == NDBT_OK, "test error handling failed");
9385
9386 errloop++;
9387 if (errloop == errloops)
9388 {
9389 CHK2(pDic->dropTable(tabname) == 0, pDic->getNdbError());
9390 g_info << "table " << tabname << " dropped" << endl;
9391 }
9392 }
9393 if (result != NDBT_OK)
9394 {
9395 g_info << "stop test at line " << __LINE__ << endl;
9396 ctx->stopTest();
9397 }
9398 return result;
9399 }
9400
9401 int
runBug58277drop(NDBT_Context * ctx,NDBT_Step * step)9402 runBug58277drop(NDBT_Context* ctx, NDBT_Step* step)
9403 {
9404 Ndb* pNdb = GETNDB(step);
9405 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
9406 int result = NDBT_OK;
9407 const char* tabname = tabName_Bug58277;
9408 const char* indname = indName_Bug58277;
9409 int dropms = 0;
9410
9411 while (!ctx->isTestStopped())
9412 {
9413 sync_sub_step(ctx, step, "Start");
9414 if (ctx->isTestStopped())
9415 break;
9416 dropms = ctx->getProperty("DropMs", (Uint32)0);
9417 NdbSleep_MilliSleep(dropms);
9418
9419 g_info << "drop index " << indname << endl;
9420 CHK2(pDic->dropIndex(indname, tabname) == 0, pDic->getNdbError());
9421 pDic->invalidateIndex(indname, tabname);
9422 CHK2(pDic->getIndex(indname, tabname) == 0, "failed");
9423 g_info << "drop index done" << endl;
9424
9425 sync_sub_step(ctx, step, "Stop");
9426 if (ctx->isTestStopped())
9427 break;
9428 }
9429 if (result != NDBT_OK)
9430 {
9431 g_info << "stop test at line " << __LINE__ << endl;
9432 ctx->stopTest();
9433 }
9434 return result;
9435 }
9436
9437 static int
runBug58277scanop(NDBT_Context * ctx,NDBT_Step * step,int cnt[1+3])9438 runBug58277scanop(NDBT_Context* ctx, NDBT_Step* step, int cnt[1+3])
9439 {
9440 Ndb* pNdb = GETNDB(step);
9441 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
9442 int result = NDBT_OK;
9443 const int rows = ctx->getNumRecords();
9444 const char* tabname = tabName_Bug58277;
9445 const char* indname = indName_Bug58277;
9446 const int range_max = ctx->getProperty("RANGE_MAX", (Uint32)0);
9447 require(range_max > 0);
9448 const bool scan_delete = ctx->getProperty("SCAN_DELETE", (Uint32)0);
9449
9450 do
9451 {
9452 const NdbDictionary::Index* pInd = 0;
9453 {
9454 int x[] = {
9455 4243 // Index not found
9456 };
9457 pDic->invalidateIndex(indname, tabname);
9458 CHK3((pInd = pDic->getIndex(indname, tabname)) != 0, pDic->getNdbError(), x);
9459 }
9460
9461 NdbTransaction* pSTx = 0;
9462 CHK2((pSTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
9463 NdbIndexScanOperation* pSOp = 0;
9464 CHK2((pSOp = pSTx->getNdbIndexScanOperation(pInd)) != 0, pSTx->getNdbError());
9465 NdbOperation::LockMode lm = NdbOperation::LM_Exclusive;
9466 Uint32 flags = 0;
9467 int range_cnt = rand() % range_max;
9468 if (range_cnt > 1 || rand() % 5 == 0)
9469 flags |= NdbIndexScanOperation::SF_MultiRange;
9470 CHK2(pSOp->readTuples(lm, flags) == 0, pSOp->getNdbError());
9471 g_info << "range cnt " << range_cnt << endl;
9472 for (int i = 0; i < range_cnt; )
9473 {
9474 int tlo = -1;
9475 int thi = -1;
9476 if (rand() % 5 == 0)
9477 {
9478 if (rand() % 5 != 0)
9479 tlo = 0 + rand() % 2;
9480 if (rand() % 5 != 0)
9481 thi = 2 + rand() % 2;
9482 }
9483 else
9484 tlo = 4;
9485 // apparently no bounds is not allowed (see also bug#57396)
9486 if (tlo == -1 && thi == -1)
9487 continue;
9488 Uint32 blo = 0;
9489 Uint32 bhi = 0;
9490 if (tlo != -1)
9491 {
9492 blo = rand() % rows;
9493 CHK2(pSOp->setBound("b", tlo, &blo) == 0, pSOp->getNdbError());
9494 }
9495 if (thi != -1)
9496 {
9497 bhi = rand() % (rows + 1);
9498 if (bhi < blo)
9499 bhi = rand() % (rows + 1);
9500 CHK2(pSOp->setBound("b", thi, &bhi) == 0, pSOp->getNdbError());
9501 }
9502 CHK2(pSOp->end_of_bound() == 0, pSOp->getNdbError());
9503 i++;
9504 }
9505 CHK2(result == NDBT_OK, "set bound ranges failed");
9506
9507 Uint32 aVal = 0;
9508 CHK2(pSOp->getValue("a", (char*)&aVal) != 0, pSOp->getNdbError());
9509 CHK2(pSTx->execute(NoCommit) == 0, pSTx->getNdbError());
9510
9511 while (1)
9512 {
9513 int ret;
9514 {
9515 int x[] = {
9516 241, // Invalid schema object version
9517 274, // Time-out in NDB, probably caused by deadlock
9518 283, // Table is being dropped
9519 284, // Table not defined in transaction coordinator
9520 910, // Index is being dropped
9521 1226 // Table is being dropped
9522 };
9523 CHK3((ret = pSOp->nextResult(true)) != -1, pSOp->getNdbError(), x);
9524 }
9525 require(ret == 0 || ret == 1);
9526 if (ret == 1)
9527 break;
9528
9529 NdbTransaction* pTx = 0;
9530 CHK2((pTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
9531
9532 while (1)
9533 {
9534 int type = 1 + rand() % 3;
9535 if (type == 2) // insert->update
9536 type = 1;
9537 if (scan_delete)
9538 type = 3;
9539 do
9540 {
9541 if (type == 1)
9542 {
9543 NdbOperation* pOp = 0;
9544 CHK2((pOp = pSOp->updateCurrentTuple(pTx)) != 0, pSOp->getNdbError());
9545 Uint32 bVal = (Uint32)(rand() % rows);
9546 CHK2(pOp->setValue("b", bVal) == 0, pOp->getNdbError());
9547 break;
9548 }
9549 if (type == 3)
9550 {
9551 CHK2(pSOp->deleteCurrentTuple(pTx) == 0, pSOp->getNdbError());
9552 break;
9553 }
9554 require(false);
9555 }
9556 while (0);
9557 CHK2(result == NDBT_OK, "scan takeover error");
9558 cnt[type]++;
9559 {
9560 int x[] = {
9561 266, // Time-out in NDB, probably caused by deadlock
9562 499, // Scan take over error
9563 631, // 631
9564 4350 // Transaction already aborted
9565 };
9566 CHK3(pTx->execute(NoCommit) == 0, pTx->getNdbError(), x);
9567 }
9568
9569 CHK2((ret = pSOp->nextResult(false)) != -1, pSOp->getNdbError());
9570 require(ret == 0 || ret == 2);
9571 if (ret == 2)
9572 break;
9573 }
9574 CHK2(result == NDBT_OK, "batch failed");
9575
9576 {
9577 int x[] = {
9578 266, // Time-out in NDB, probably caused by deadlock
9579 4350 // Transaction already aborted
9580 };
9581 CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
9582 }
9583 pNdb->closeTransaction(pTx);
9584 }
9585 CHK2(result == NDBT_OK, "batch failed");
9586 pNdb->closeTransaction(pSTx);
9587 }
9588 while (0);
9589 return result;
9590 }
9591
9592 int
runBug58277scan(NDBT_Context * ctx,NDBT_Step * step)9593 runBug58277scan(NDBT_Context* ctx, NDBT_Step* step)
9594 {
9595 int result = NDBT_OK;
9596
9597 while (!ctx->isTestStopped())
9598 {
9599 sync_sub_step(ctx, step, "Start");
9600 if (ctx->isTestStopped())
9601 break;
9602 g_info << "start scan loop" << endl;
9603 while (!ctx->isTestStopped())
9604 {
9605 g_info << "start scan" << endl;
9606 int cnt[1+3] = { 0, 0, 0, 0 };
9607 CHK2(runBug58277scanop(ctx, step, cnt) == NDBT_OK, "scan failed");
9608 g_info << "scan ops " << cnt[1] << "/-/" << cnt[3] << endl;
9609
9610 if (ctx->getProperty("Stop", (Uint32)0) == 1)
9611 {
9612 sync_sub_step(ctx, step, "Stop");
9613 break;
9614 }
9615 }
9616 CHK2(result == NDBT_OK, "scan loop failed");
9617 }
9618 if (result != NDBT_OK)
9619 {
9620 g_info << "stop test at line " << __LINE__ << endl;
9621 ctx->stopTest();
9622 }
9623 return result;
9624 }
9625
9626 static int
runBug58277pkop(NDBT_Context * ctx,NDBT_Step * step,int cnt[1+3])9627 runBug58277pkop(NDBT_Context* ctx, NDBT_Step* step, int cnt[1+3])
9628 {
9629 Ndb* pNdb = GETNDB(step);
9630 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
9631 int result = NDBT_OK;
9632 const int rows = ctx->getNumRecords();
9633 const char* tabname = tabName_Bug58277;
9634
9635 do
9636 {
9637 const NdbDictionary::Table* pTab = 0;
9638 CHK2((pTab = pDic->getTable(tabname)) != 0, pDic->getNdbError());
9639
9640 NdbTransaction* pTx = 0;
9641 CHK2((pTx = pNdb->startTransaction()) != 0, pNdb->getNdbError());
9642 NdbOperation* pOp = 0;
9643 CHK2((pOp = pTx->getNdbOperation(pTab)) != 0, pTx->getNdbError());
9644 int type = 1 + rand() % 3;
9645 Uint32 aVal = rand() % rows;
9646 Uint32 bVal = rand() % rows;
9647
9648 do
9649 {
9650 if (type == 1)
9651 {
9652 CHK2(pOp->updateTuple() == 0, pOp->getNdbError());
9653 CHK2(pOp->equal("a", (char*)&aVal) == 0, pOp->getNdbError());
9654 CHK2(pOp->setValue("b", bVal) == 0, pOp->getNdbError());
9655 int x[] = {
9656 266, // Time-out in NDB, probably caused by deadlock
9657 -626 // Tuple did not exist
9658 };
9659 CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
9660 break;
9661 }
9662 if (type == 2)
9663 {
9664 CHK2(pOp->insertTuple() == 0, pOp->getNdbError());
9665 CHK2(pOp->equal("a", (char*)&aVal) == 0, pOp->getNdbError());
9666 CHK2(pOp->setValue("b", bVal) == 0, pOp->getNdbError());
9667 int x[] = {
9668 266, // Time-out in NDB, probably caused by deadlock
9669 -630 // Tuple already existed when attempting to insert
9670 };
9671 CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
9672 break;
9673 }
9674 if (type == 3)
9675 {
9676 CHK2(pOp->deleteTuple() == 0, pOp->getNdbError());
9677 CHK2(pOp->equal("a", (char*)&aVal) == 0, pOp->getNdbError());
9678 int x[] = {
9679 266, // Time-out in NDB, probably caused by deadlock
9680 -626 // Tuple did not exist
9681 };
9682 CHK3(pTx->execute(Commit) == 0, pTx->getNdbError(), x);
9683 break;
9684 }
9685 require(false);
9686 }
9687 while (0);
9688 CHK2(result == NDBT_OK, "pk op failed");
9689
9690 pNdb->closeTransaction(pTx);
9691 cnt[type]++;
9692 }
9693 while (0);
9694 return result;
9695 }
9696
9697 int
runBug58277pk(NDBT_Context * ctx,NDBT_Step * step)9698 runBug58277pk(NDBT_Context* ctx, NDBT_Step* step)
9699 {
9700 int result = NDBT_OK;
9701
9702 while (!ctx->isTestStopped())
9703 {
9704 sync_sub_step(ctx, step, "Start");
9705 if (ctx->isTestStopped())
9706 break;
9707
9708 g_info << "start pk loop" << endl;
9709 int cnt[1+3] = { 0, 0, 0, 0 };
9710 while (!ctx->isTestStopped())
9711 {
9712 CHK2(runBug58277pkop(ctx, step, cnt) == NDBT_OK, "pk op failed");
9713
9714 if (ctx->getProperty("Stop", (Uint32)0) == 1)
9715 {
9716 sync_sub_step(ctx, step, "Stop");
9717 break;
9718 }
9719 }
9720 CHK2(result == NDBT_OK, "pk loop failed");
9721 g_info << "pk ops " << cnt[1] << "/" << cnt[2] << "/" << cnt[3] << endl;
9722 }
9723 if (result != NDBT_OK)
9724 {
9725 g_info << "stop test at line " << __LINE__ << endl;
9726 ctx->stopTest();
9727 }
9728 return result;
9729 }
9730
9731 int
runBug58277rand(NDBT_Context * ctx,NDBT_Step * step)9732 runBug58277rand(NDBT_Context* ctx, NDBT_Step* step)
9733 {
9734 int result = NDBT_OK;
9735 NdbRestarter restarter;
9736
9737 while (!ctx->isTestStopped())
9738 {
9739 int sleepms = rand() % 5000;
9740 g_info << "rand sleep " << sleepms << " ms" << endl;
9741 NdbSleep_MilliSleep(sleepms);
9742 if (rand() % 5 == 0)
9743 {
9744 g_info << "rand force LCP" << endl;
9745 int dump1[] = { DumpStateOrd::DihStartLcpImmediately };
9746 CHK2(restarter.dumpStateAllNodes(dump1, 1) == 0, "failed");
9747 }
9748 }
9749 if (result != NDBT_OK)
9750 {
9751 g_info << "stop test at line " << __LINE__ << endl;
9752 ctx->stopTest();
9753 }
9754 g_info << "rand exit" << endl;
9755 return result;
9756 }
9757
9758 int
runBug58277(NDBT_Context * ctx,NDBT_Step * step)9759 runBug58277(NDBT_Context* ctx, NDBT_Step* step)
9760 {
9761 Ndb* pNdb = GETNDB(step);
9762 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
9763 const int loops = ctx->getNumLoops();
9764 int result = NDBT_OK;
9765 const bool rss_check = ctx->getProperty("RSS_CHECK", (Uint32)0);
9766 NdbRestarter restarter;
9767 const char* tabname = tabName_Bug58277;
9768 const char* indname = indName_Bug58277;
9769 (void)pDic->dropTable(tabname);
9770
9771 int loop = 0;
9772 while (!ctx->isTestStopped())
9773 {
9774 g_info << "===== loop " << loop << " =====" << endl;
9775
9776 if (loop == 0)
9777 {
9778 CHK2(runBug58277createtable(ctx, step) == NDBT_OK, "create table failed");
9779 CHK2(runBug58277loadtable(ctx, step) == NDBT_OK, "load table failed");
9780 }
9781
9782 if (rss_check)
9783 {
9784 g_info << "save all resource usage" << endl;
9785 int dump1[] = { DumpStateOrd::SchemaResourceSnapshot };
9786 CHK2(restarter.dumpStateAllNodes(dump1, 1) == 0, "failed");
9787 }
9788
9789 CHK2(runBug58277createindex(ctx, step) == NDBT_OK, "create index failed");
9790
9791 int dropmin = 1000;
9792 int dropmax = 9000;
9793 int dropms = dropmin + rand() % (dropmax - dropmin + 1);
9794 g_info << "drop in " << dropms << " ms" << endl;
9795 ctx->setProperty("DropMs", dropms);
9796
9797 sync_main_step(ctx, step, "Start");
9798 if (ctx->isTestStopped())
9799 break;
9800
9801 // vary Stop time a bit in either direction
9802 int stopvar = rand() % 100;
9803 int stopsgn = (rand() % 2 == 0 ? +1 : -1);
9804 int stopms = dropms + stopsgn * stopvar;
9805 NdbSleep_MilliSleep(stopms);
9806
9807 sync_main_step(ctx, step, "Stop");
9808 if (ctx->isTestStopped())
9809 break;
9810
9811 // index must have been dropped
9812 pDic->invalidateIndex(indname, tabname);
9813 CHK2(pDic->getIndex(indname, tabname) == 0, "failed");
9814
9815 if (rss_check)
9816 {
9817 g_info << "check all resource usage" << endl;
9818 int dump2[] = { DumpStateOrd::SchemaResourceCheckLeak };
9819 CHK2(restarter.dumpStateAllNodes(dump2, 1) == 0, "failed");
9820
9821 g_info << "check cluster is up" << endl;
9822 CHK2(restarter.waitClusterStarted() == 0, "failed");
9823 CHK_NDB_READY(pNdb);
9824 }
9825
9826 if (++loop == loops)
9827 {
9828 CHK2(pDic->dropTable(tabname) == 0, pDic->getNdbError());
9829 g_info << "table " << tabname << " dropped" << endl;
9830 break;
9831 }
9832 }
9833
9834 g_info << "stop test at line " << __LINE__ << endl;
9835 ctx->stopTest();
9836 return result;
9837 }
9838
9839 int
runBug57057(NDBT_Context * ctx,NDBT_Step * step)9840 runBug57057(NDBT_Context* ctx, NDBT_Step* step)
9841 {
9842 Ndb* pNdb = GETNDB(step);
9843 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
9844 const int loops = ctx->getNumLoops();
9845 int result = NDBT_OK;
9846 const bool rss_check = ctx->getProperty("RSS_CHECK", (Uint32)0);
9847 NdbRestarter restarter;
9848 const char* tabname = tabName_Bug58277;
9849 //const char* indname = indName_Bug58277;
9850 (void)pDic->dropTable(tabname);
9851
9852 int loop = 0;
9853 while (!ctx->isTestStopped())
9854 {
9855 g_info << "===== loop " << loop << " =====" << endl;
9856
9857 if (loop == 0)
9858 {
9859 CHK2(runBug58277createtable(ctx, step) == NDBT_OK, "create table failed");
9860 CHK2(runBug58277createindex(ctx, step) == NDBT_OK, "create index failed");
9861 }
9862
9863 CHK2(runBug58277loadtable(ctx, step) == NDBT_OK, "load table failed");
9864
9865 if (rss_check)
9866 {
9867 g_info << "save all resource usage" << endl;
9868 int dump1[] = { DumpStateOrd::SchemaResourceSnapshot };
9869 CHK2(restarter.dumpStateAllNodes(dump1, 1) == 0, "failed");
9870 }
9871
9872 int dropmin = 1000;
9873 int dropmax = 2000;
9874 int dropms = dropmin + rand() % (dropmax - dropmin + 1);
9875 int stopms = dropms;
9876
9877 sync_main_step(ctx, step, "Start");
9878 if (ctx->isTestStopped())
9879 break;
9880
9881 g_info << "stop in " << stopms << " ms" << endl;
9882 NdbSleep_MilliSleep(stopms);
9883
9884 sync_main_step(ctx, step, "Stop");
9885 if (ctx->isTestStopped())
9886 break;
9887
9888 if (rss_check)
9889 {
9890 g_info << "check all resource usage" << endl;
9891 int dump2[] = { DumpStateOrd::SchemaResourceCheckLeak };
9892 CHK2(restarter.dumpStateAllNodes(dump2, 1) == 0, "failed");
9893
9894 g_info << "check cluster is up" << endl;
9895 CHK2(restarter.waitClusterStarted() == 0, "failed");
9896 CHK_NDB_READY(pNdb);
9897 }
9898
9899 if (++loop == loops)
9900 {
9901 CHK2(pDic->dropTable(tabname) == 0, pDic->getNdbError());
9902 g_info << "table " << tabname << " dropped" << endl;
9903 break;
9904 }
9905 }
9906
9907 g_info << "stop test at line " << __LINE__ << endl;
9908 ctx->stopTest();
9909 return result;
9910 }
9911
9912 /**
9913 * This is a regression test for Bug #14647210 "CAN CRASH ALL NODES EASILY
9914 * WHEN RESTARTING MORE THAN 6 NODES SIMULTANEOUSLY". The cause of this bug
9915 * was that DICT did not handle GET_TABINFOREF signals.
9916 */
9917 static int
runGetTabInfoRef(NDBT_Context * ctx,NDBT_Step * step)9918 runGetTabInfoRef(NDBT_Context* ctx, NDBT_Step* step)
9919 {
9920 NdbRestarter restarter;
9921 if (restarter.getNumDbNodes() == 1)
9922 {
9923 g_info << "Cannot do this test with just one datanode." << endl;
9924 return NDBT_OK;
9925 }
9926
9927 /**
9928 * This error insert makes DICT respond with GET_TABINFOREF where
9929 * error==busy when receiving the next GET_TABINFOREQ signal.
9930 */
9931 restarter.insertErrorInAllNodes(6026);
9932
9933 /* Find a node in each nodegroup to restart. */
9934 Vector<int> nodeSet;
9935 Bitmask<MAX_NDB_NODES/32> nodeGroupMap;
9936 for (int i = 0; i < restarter.getNumDbNodes(); i++)
9937 {
9938 const int node = restarter.getDbNodeId(i);
9939 const int ng = restarter.getNodeGroup(node);
9940 if (!nodeGroupMap.get(ng))
9941 {
9942 g_info << "Node " << node << " will be stopped." << endl;
9943 nodeSet.push_back(node);
9944 nodeGroupMap.set(ng);
9945 }
9946 }
9947
9948 if (restarter.restartNodes(nodeSet.getBase(), (int)nodeSet.size(),
9949 NdbRestarter::NRRF_NOSTART |
9950 NdbRestarter::NRRF_ABORT))
9951 {
9952 g_err << "Failed to stop nodes" << endl;
9953 restarter.insertErrorInAllNodes(0);
9954 return NDBT_FAILED;
9955 }
9956
9957 g_info << "Waiting for nodes to stop." << endl;
9958 if (restarter.waitNodesNoStart(nodeSet.getBase(), (int)nodeSet.size()))
9959 {
9960 g_err << "Failed to wait for nodes to stop" << endl;
9961 restarter.insertErrorInAllNodes(0);
9962 return NDBT_FAILED;
9963 }
9964
9965 if (restarter.startNodes(nodeSet.getBase(), (int)nodeSet.size()))
9966 {
9967 g_err << "Failed to restart nodes" << endl;
9968 restarter.insertErrorInAllNodes(0);
9969 return NDBT_FAILED;
9970 }
9971
9972 g_info << "Waiting for nodes to start again." << endl;
9973 if (restarter.waitClusterStarted() != 0)
9974 {
9975 g_err << "Failed to restart cluster " << endl;
9976 restarter.insertErrorInAllNodes(0);
9977 return NDBT_FAILED;
9978 }
9979
9980 restarter.insertErrorInAllNodes(0);
9981 return NDBT_OK;
9982 } // runGetTabInfoRef()
9983
9984 int
runBug13416603(NDBT_Context * ctx,NDBT_Step * step)9985 runBug13416603(NDBT_Context* ctx, NDBT_Step* step)
9986 {
9987 Ndb* pNdb = GETNDB(step);
9988 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
9989 NdbIndexStat is;
9990 NdbRestarter res;
9991
9992 int elist[] = { 18026, 0 };
9993 const NdbDictionary::Table *pTab = pDic->getTable(ctx->getTab()->getName());
9994 const NdbDictionary::Index *pIdx = 0;
9995 NdbDictionary::Dictionary::List indexes;
9996 pDic->listIndexes(indexes, * pTab);
9997 for (unsigned i = 0; i < indexes.count; i++)
9998 {
9999 if ((pIdx = pDic->getIndex(indexes.elements[i].name, pTab->getName())) != 0)
10000 break;
10001 }
10002
10003 if (pIdx == 0)
10004 {
10005 // Exit if there aren't any indexes in the table
10006 return NDBT_OK;
10007 }
10008
10009 bool has_created_stat_tables = false;
10010 bool has_created_stat_events = false;
10011 pNdb->setDatabaseName("mysql");
10012 if (is.create_systables(pNdb) == 0)
10013 {
10014 has_created_stat_tables = true;
10015 }
10016
10017 if (is.create_sysevents(pNdb) == 0)
10018 {
10019 has_created_stat_events = true;
10020 }
10021
10022 chk2(is.create_listener(pNdb) == 0, is.getNdbError());
10023 chk2(is.execute_listener(pNdb) == 0, is.getNdbError());
10024
10025 is.set_index(* pIdx, * pTab);
10026
10027 {
10028 ndbout_c("%u - update_stat", __LINE__);
10029 chk2(is.update_stat(pNdb) == 0, is.getNdbError());
10030 int ret;
10031 ndbout_c("%u - poll_listener", __LINE__);
10032 chk2((ret = is.poll_listener(pNdb, 10000)) != -1, is.getNdbError());
10033 chk1(ret == 1);
10034 // one event is expected
10035 ndbout_c("%u - next_listener", __LINE__);
10036 chk2((ret = is.next_listener(pNdb)) != -1, is.getNdbError());
10037 chk1(ret == 1);
10038 ndbout_c("%u - next_listener", __LINE__);
10039 chk2((ret = is.next_listener(pNdb)) != -1, is.getNdbError());
10040 chk1(ret == 0);
10041 }
10042
10043 {
10044 Vector<Vector<int> > partitions = res.splitNodes();
10045 if (partitions.size() == 1)
10046 goto cleanup;
10047
10048 for (unsigned i = 0; i < partitions.size(); i++)
10049 {
10050 printf("stopping: ");
10051 for (unsigned j = 0; j < partitions[i].size(); j++)
10052 printf("%d ", partitions[i][j]);
10053 printf("\n");
10054
10055 res.restartNodes(partitions[i].getBase(),
10056 partitions[i].size(),
10057 NdbRestarter::NRRF_NOSTART | NdbRestarter::NRRF_ABORT);
10058 res.waitNodesNoStart(partitions[i].getBase(),
10059 partitions[i].size());
10060
10061 {
10062 ndbout_c("%u - update_stat", __LINE__);
10063 chk2(is.update_stat(pNdb) == 0, is.getNdbError());
10064 int ret;
10065 ndbout_c("%u - poll_listener", __LINE__);
10066 chk2((ret = is.poll_listener(pNdb, 10000)) != -1, is.getNdbError());
10067 chk1(ret == 1);
10068 // one event is expected
10069 ndbout_c("%u - next_listener", __LINE__);
10070 chk2((ret = is.next_listener(pNdb)) != -1, is.getNdbError());
10071 chk1(ret == 1);
10072 ndbout_c("%u - next_listener", __LINE__);
10073 chk2((ret = is.next_listener(pNdb)) != -1, is.getNdbError());
10074 chk1(ret == 0);
10075 }
10076
10077 res.startNodes(partitions[i].getBase(),
10078 partitions[i].size());
10079 res.waitClusterStarted();
10080 CHK_NDB_READY(pNdb);
10081 }
10082 }
10083
10084 for (int i = 0; elist[i] != 0; i++)
10085 {
10086 ndbout_c("testing errno: %u", elist[i]);
10087 res.insertErrorInAllNodes(elist[i]);
10088 int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 };
10089 res.dumpStateAllNodes(val2, 2);
10090
10091 {
10092 ndbout_c("%u - update_stat", __LINE__);
10093 int ret = is.update_stat(pNdb);
10094 ndbout_c("%u - update_stat => %d", __LINE__, ret);
10095 chk1(ret == -1);
10096 ndbout << is.getNdbError() << endl;
10097 ndbout_c("%u - poll_listener", __LINE__);
10098 chk2((ret = is.poll_listener(pNdb, 10000)) != -1, is.getNdbError());
10099 if (ret == 1)
10100 {
10101 /* After the new api is introduced, pollEvents() (old api version)
10102 * returns 1 when empty epoch is at the head of the event queue.
10103 * pollEvents2() (new api version) returns 1 when exceptional
10104 * epoch is at the head of the event queue.
10105 * So next_listener() must be called to handle them.
10106 */
10107 chk2((ret = is.next_listener(pNdb)) != -1, is.getNdbError());
10108 }
10109 // Check that the event queue is empty
10110 chk1(ret == 0);
10111 }
10112
10113 /**
10114 * Wait for one of the nodes to have died...
10115 */
10116 int count_started = 0;
10117 int count_not_started = 0;
10118 int count_nok = 0;
10119 int down = 0;
10120 do
10121 {
10122 NdbSleep_MilliSleep(100);
10123 count_started = count_not_started = count_nok = 0;
10124 for (int i = 0; i < res.getNumDbNodes(); i++)
10125 {
10126 int n = res.getDbNodeId(i);
10127 if (res.getNodeStatus(n) == NDB_MGM_NODE_STATUS_NOT_STARTED)
10128 {
10129 count_not_started++;
10130 down = n;
10131 }
10132 else if (res.getNodeStatus(n) == NDB_MGM_NODE_STATUS_STARTED)
10133 count_started++;
10134 else
10135 count_nok ++;
10136 }
10137 } while (count_not_started != 1);
10138
10139 res.startNodes(&down, 1);
10140 res.waitClusterStarted();
10141 CHK_NDB_READY(pNdb);
10142 res.insertErrorInAllNodes(0);
10143 }
10144
10145 cleanup:
10146 // cleanup
10147 is.drop_listener(pNdb);
10148 if (has_created_stat_events)
10149 {
10150 is.drop_sysevents(pNdb);
10151 }
10152 if (has_created_stat_tables)
10153 {
10154 is.drop_systables(pNdb);
10155 }
10156
10157 // Ensure that nodes will start after error inserts again.
10158 {
10159 const int restartState[] =
10160 { DumpStateOrd::CmvmiSetRestartOnErrorInsert, NRT_DoStart_Restart };
10161
10162 require(res.dumpStateAllNodes(restartState,
10163 sizeof restartState/sizeof restartState[0])
10164 == 0);
10165 }
10166
10167 return NDBT_OK;
10168
10169 err:
10170 return NDBT_FAILED;
10171 }
10172
10173 int
runIndexStatCreate(NDBT_Context * ctx,NDBT_Step * step)10174 runIndexStatCreate(NDBT_Context* ctx, NDBT_Step* step)
10175 {
10176 Ndb* pNdb = GETNDB(step);
10177 NdbIndexStat is;
10178
10179 const int loops = ctx->getNumLoops();
10180
10181 pNdb->setDatabaseName("mysql");
10182
10183 Uint64 end = NdbTick_CurrentMillisecond() + 1000 * loops;
10184 do
10185 {
10186 if (is.create_systables(pNdb) == 0)
10187 {
10188 /**
10189 * OK
10190 */
10191 }
10192 else if (! (is.getNdbError().code == 701 || // timeout
10193 is.getNdbError().code == 721 || // already exists
10194 is.getNdbError().code == 4244 || // already exists
10195 is.getNdbError().code == 4009)) // no connection
10196 {
10197 ndbout << is.getNdbError() << endl;
10198 return NDBT_FAILED;
10199 }
10200
10201 is.drop_systables(pNdb);
10202 } while (!ctx->isTestStopped() && NdbTick_CurrentMillisecond() < end);
10203
10204 return NDBT_OK;
10205 }
10206
10207 int
runWL946(NDBT_Context * ctx,NDBT_Step * step)10208 runWL946(NDBT_Context* ctx, NDBT_Step* step)
10209 {
10210 Ndb* pNdb = GETNDB(step);
10211 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
10212 const int loops = ctx->getNumLoops();
10213 const int records = ctx->getNumRecords();
10214 bool keep_table = false; // keep table and data
10215 #ifdef VM_TRACE
10216 #ifdef NDB_USE_GET_ENV
10217 {
10218 const char* p = NdbEnv_GetEnv("KEEP_TABLE_WL946", (char*)0, 0);
10219 if (p != 0 && strchr("1Y", p[0]) != 0)
10220 keep_table = true;
10221 }
10222 #endif
10223 #endif
10224 int result = NDBT_OK;
10225
10226 const char* tabname = "T_WL946";
10227 (void)pDic->dropTable(tabname);
10228
10229 for (int loop = 0; loop < loops; loop++)
10230 {
10231 g_info << "loop " << loop << "(" << loops << ")" << endl;
10232
10233 NdbDictionary::Table tab;
10234 tab.setName(tabname);
10235
10236 struct Coldef {
10237 const char* name;
10238 NdbDictionary::Column::Type type;
10239 int prec; // fractional precision 0-6
10240 int flag; // 1-pk 2-nullable 4-fractional 8-create index
10241 const char* indname;
10242 } coldef[] = {
10243 // primary key
10244 { "pk", NdbDictionary::Column::Unsigned, 0, 1, 0 },
10245 // deprecated
10246 { "a0", NdbDictionary::Column::Time, 0, 2|8, "x0" },
10247 { "a1", NdbDictionary::Column::Datetime, 0, 2|8, "x1" },
10248 { "a2", NdbDictionary::Column::Timestamp, 0, 2|8, "x2" },
10249 // fractional
10250 { "b0", NdbDictionary::Column::Time2, 0, 2|4|8, "y0" },
10251 { "b1", NdbDictionary::Column::Datetime2, 0, 2|4|8, "y1" },
10252 { "b2", NdbDictionary::Column::Timestamp2, 0, 2|4|8, "y2" },
10253 // update key
10254 { "uk", NdbDictionary::Column::Unsigned, 0, 0, 0 }
10255 };
10256 const int Colcnt = sizeof(coldef)/sizeof(coldef[0]);
10257
10258 NdbDictionary::Column col[Colcnt];
10259 for (int i = 0; i < Colcnt; i++)
10260 {
10261 Coldef& d = coldef[i];
10262 NdbDictionary::Column& c = col[i];
10263 c.setName(d.name);
10264 c.setType(d.type);
10265 if (d.flag & 4)
10266 {
10267 d.prec = myRandom48(7);
10268 require(d.prec >= 0 && d.prec <= 6);
10269 c.setPrecision(d.prec);
10270 }
10271 c.setPrimaryKey(d.flag & 1);
10272 c.setNullable(d.flag & 2);
10273 tab.addColumn(c);
10274 }
10275
10276 g_info << "create table " << tabname << endl;
10277 const NdbDictionary::Table* pTab = 0;
10278 CHK2(pDic->createTable(tab) == 0, pDic->getNdbError());
10279 CHK2((pTab = pDic->getTable(tabname)) != 0, pDic->getNdbError());
10280
10281 const NdbDictionary::Column* pCol[Colcnt];
10282 for (int i = 0; i < Colcnt; i++)
10283 {
10284 const Coldef& d = coldef[i];
10285 const NdbDictionary::Column* pc = 0;
10286 CHK2((pc = tab.getColumn(i)) != 0, pDic->getNdbError());
10287 CHK2(strcmp(pc->getName(), d.name) == 0, "name");
10288 CHK2(pc->getType() == d.type, "type");
10289 CHK2(pc->getPrecision() == d.prec, "prec");
10290 pCol[i] = pc;
10291 }
10292 CHK2(result == NDBT_OK, "verify columns");
10293
10294 g_info << "create indexes" << endl;
10295 NdbDictionary::Index ind[Colcnt];
10296 const NdbDictionary::Index* pInd[Colcnt];
10297 for (int i = 0; i < Colcnt; i++)
10298 {
10299 Coldef& d = coldef[i];
10300 pInd[i] = 0;
10301 if (d.flag & 8)
10302 {
10303 NdbDictionary::Index& x = ind[i];
10304 x.setName(d.indname);
10305 x.setTable(tabname);
10306 x.setType(NdbDictionary::Index::OrderedIndex);
10307 x.setLogging(false);
10308 x.addColumn(d.name);
10309 const NdbDictionary::Index* px = 0;
10310 CHK2(pDic->createIndex(x) == 0, pDic->getNdbError());
10311 CHK2((px = pDic->getIndex(d.indname, tabname)) != 0, pDic->getNdbError());
10312 pInd[i] = px;
10313 }
10314 }
10315 CHK2(result == NDBT_OK, "create indexes");
10316
10317 HugoTransactions trans(*pTab);
10318
10319 g_info << "load records" << endl;
10320 CHK2(trans.loadTable(pNdb, records) == 0, trans.getNdbError());
10321
10322 const int scanloops = 5;
10323 for (int j = 0; j < scanloops; j++)
10324 {
10325 g_info << "scan table " << j << "(" << scanloops << ")" << endl;
10326 CHK2(trans.scanReadRecords(pNdb, records) == 0, trans.getNdbError());
10327
10328 for (int i = 0; i < Colcnt; i++)
10329 {
10330 Coldef& d = coldef[i];
10331 if (d.flag & 8)
10332 {
10333 g_info << "scan index " << d.indname << endl;
10334 const NdbDictionary::Index* px = pInd[i];
10335 CHK2(trans.scanReadRecords(pNdb, px, records) == 0, trans.getNdbError());
10336 }
10337 }
10338 CHK2(result == NDBT_OK, "index scan");
10339
10340 g_info << "update records" << endl;
10341 CHK2(trans.scanUpdateRecords(pNdb, records) == 0, trans.getNdbError());
10342 }
10343 CHK2(result == NDBT_OK, "scans");
10344
10345 if (loop + 1 < loops || !keep_table)
10346 {
10347 g_info << "delete records" << endl;
10348 CHK2(trans.clearTable(pNdb) == 0, trans.getNdbError());
10349
10350 g_info << "drop table" << endl;
10351 CHK2(pDic->dropTable(tabname) == 0, pDic->getNdbError());
10352 }
10353 }
10354
10355 if (result != NDBT_OK && !keep_table)
10356 {
10357 g_info << "drop table after error" << endl;
10358 (void)pDic->dropTable(tabname);
10359 }
10360 return result;
10361 }
10362
10363 int
getOrCreateDefaultHashMap(NdbDictionary::Dictionary & dict,NdbDictionary::HashMap & hm,Uint32 buckets,Uint32 fragments)10364 getOrCreateDefaultHashMap(NdbDictionary::Dictionary& dict, NdbDictionary::HashMap& hm, Uint32 buckets, Uint32 fragments)
10365 {
10366 if (dict.getDefaultHashMap(hm, buckets, fragments) == 0)
10367 {
10368 return 0;
10369 }
10370
10371 dict.initDefaultHashMap(hm, buckets, fragments);
10372 if (dict.createHashMap(hm, NULL) == -1)
10373 {
10374 return -1;
10375 }
10376
10377 if (dict.getDefaultHashMap(hm, buckets, fragments) == 0)
10378 {
10379 return 0;
10380 }
10381
10382 return -1;
10383 }
10384
10385 struct Bug14645319_createTable_args
10386 {
10387 char const* template_name;
10388 char const* name;
10389 Uint32 buckets;
10390 Uint32 fragments;
10391 };
10392
Bug14645319_createTable(Ndb * pNdb,NdbDictionary::Table & tab,int when,void * arg)10393 int Bug14645319_createTable(Ndb* pNdb, NdbDictionary::Table& tab, int when,
10394 void* arg)
10395 {
10396 Bug14645319_createTable_args& args = *static_cast<Bug14645319_createTable_args*>(arg);
10397 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
10398 if (when == 0)
10399 {
10400 tab.setName(args.name);
10401 tab.setFragmentCount(args.fragments);
10402 if (args.fragments == 0)
10403 {
10404 tab.setFragmentData(0, 0);
10405 }
10406 NdbDictionary::HashMap hm;
10407 getOrCreateDefaultHashMap(*pDic, hm, args.buckets, args.fragments);
10408 tab.setHashMap(hm);
10409 }
10410 return 0;
10411 }
10412
10413 int
runBug14645319(NDBT_Context * ctx,NDBT_Step * step)10414 runBug14645319(NDBT_Context* ctx, NDBT_Step* step)
10415 {
10416 Ndb* pNdb = GETNDB(step);
10417 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
10418 int failures = 0;
10419
10420 struct test_case {
10421 char const* description;
10422 int old_fragments;
10423 int old_buckets;
10424 int new_fragments;
10425 int new_buckets;
10426 int expected_buckets;
10427 };
10428
10429 STATIC_ASSERT(NDB_DEFAULT_HASHMAP_BUCKETS % 240 == 0);
10430 STATIC_ASSERT(NDB_DEFAULT_HASHMAP_BUCKETS % 260 != 0);
10431 test_case test_cases[] = {
10432 { "Simulate online reorg, may or may not change hashmap depending on default fragment count",
10433 3, 120, 0, NDB_DEFAULT_HASHMAP_BUCKETS, 0 },
10434 { "Keep old hashmap since no new fragments",
10435 3, 120, 3, NDB_DEFAULT_HASHMAP_BUCKETS, 120 },
10436 { "Keep old hashmap size since old size a multiple of new fragment count",
10437 3, 120, 6, NDB_DEFAULT_HASHMAP_BUCKETS, 120 },
10438 { "Keep old hashmap size since new size not a multiple of old",
10439 3, 130, 6, NDB_DEFAULT_HASHMAP_BUCKETS, 130 },
10440 { "Extend hashmap",
10441 3, 120, 7, NDB_DEFAULT_HASHMAP_BUCKETS, NDB_DEFAULT_HASHMAP_BUCKETS },
10442 { "Keep old hashmap size since old size not multiple of old fragment count",
10443 5, 84, 7, 42, 84 },
10444 { "Shrink hashmap",
10445 3, 120, 6, 60, 60 },
10446 };
10447
10448 Bug14645319_createTable_args args;
10449 args.template_name = ctx->getTab()->getName();
10450 args.name = "Bug14645319";
10451
10452 for (size_t testi = 0; testi < NDB_ARRAY_SIZE(test_cases); testi++)
10453 {
10454 test_case const& test = test_cases[testi];
10455 int result = NDBT_FAILED;
10456
10457 int old_fragments = 0;
10458 int old_buckets = 0;
10459 int new_fragments = 0;
10460 int new_buckets = 0;
10461
10462 do {
10463 /* setup old table */
10464 args.buckets = test.old_buckets;
10465 args.fragments = test.old_fragments;
10466 result = NDBT_Tables::createTable(pNdb, args.template_name, false, false, Bug14645319_createTable, &args);
10467 if (result != 0) break;
10468
10469 NdbDictionary::Table const& old_tab = *pDic->getTable(args.name);
10470
10471 /* check old table properties */
10472 NdbDictionary::HashMap old_hm;
10473 result = pDic->getHashMap(old_hm, &old_tab);
10474 if (result != 0) break;
10475
10476 old_fragments = old_tab.getFragmentCount();
10477 old_buckets = old_hm.getMapLen();
10478 if (old_fragments != test.old_fragments)
10479 {
10480 result = NDBT_FAILED;
10481 break;
10482 }
10483 if (old_buckets != test.old_buckets)
10484 {
10485 result = NDBT_FAILED;
10486 break;
10487 }
10488
10489 /* alter table */
10490 NdbDictionary::Table new_tab = old_tab;
10491 new_tab.setFragmentCount(test.new_fragments);
10492 if (test.new_fragments == 0)
10493 {
10494 new_tab.setFragmentData(0, 0);
10495 }
10496 else
10497 {
10498 new_tab.setPartitionBalance(
10499 NdbDictionary::Object::PartitionBalance_Specific);
10500 }
10501
10502 result = pDic->beginSchemaTrans();
10503 if (result != 0) break;
10504
10505 result = pDic->prepareHashMap(old_tab, new_tab, test.new_buckets);
10506
10507 result |= pDic->endSchemaTrans();
10508 if (result != 0) break;
10509
10510 result = pDic->alterTable(old_tab, new_tab);
10511 if (result != 0) break;
10512
10513 /* check */
10514 NdbDictionary::HashMap new_hm;
10515 result = pDic->getHashMap(new_hm, &new_tab);
10516 if (result != 0) break;
10517
10518 new_fragments = new_tab.getFragmentCount();
10519 new_buckets = new_hm.getMapLen();
10520
10521 if (test.expected_buckets > 0 &&
10522 new_buckets != test.expected_buckets)
10523 {
10524 result = NDBT_FAILED;
10525 break;
10526 }
10527 result = 0;
10528 } while (false);
10529
10530 result |= pDic->dropTable(args.name);
10531
10532 if (result == 0)
10533 {
10534 ndbout << "Test#" << (testi + 1) << " '" << test_cases[testi].description << "' passed" <<
10535 " (" << old_buckets << " => " << test_cases[testi].new_buckets << " => " << test_cases[testi].expected_buckets << ")" << endl;
10536 }
10537 else
10538 {
10539 ndbout << "Test#" << (testi + 1) << " '" << test_cases[testi].description << "' failed" <<
10540 " (" << old_buckets << " => " << test_cases[testi].new_buckets << " => " << new_buckets << " expected: " << test_cases[testi].expected_buckets << ")" << endl;
10541 failures++;
10542 }
10543 }
10544
10545 return failures > 0 ? NDBT_FAILED : NDBT_OK;
10546 }
10547
10548 // FK SR/NR
10549
10550 #define CHK1(b) CHK2(b, "-");
10551
10552 // myRandom48 seems too non-random
10553 #define myRandom48(x) (unsigned(ndb_rand()) % (x))
10554 #define myRandom48Init(x) (ndb_srand(x))
10555
10556 // used for create and verify
10557 struct Fkdef {
10558 static const int tabmax = 5;
10559 static const int colmax = 5;
10560 static const int indmax = 5;
10561 static const int keymax = tabmax * 5;
10562 static const int strmax = 10;
10563 struct Ob {
10564 bool retrieved;
10565 int id;
10566 int version;
10567 };
10568 struct Col {
10569 char colname[strmax];
10570 bool pk;
10571 bool nullable; // false
10572 int icol; // pos in table columns
10573 };
10574 struct Ind : Ob {
10575 char indname[strmax];
10576 Col col[colmax];
10577 int ncol;
10578 bool pk;
10579 bool unique;
10580 const NdbDictionary::Index* pInd;
10581 };
10582 struct Tab : Ob {
10583 char tabname[strmax];
10584 Col col[colmax];
10585 int ncol;
10586 Ind ind[indmax]; // first "index" is primary key
10587 int nind;
10588 const NdbDictionary::Table* pTab;
10589 };
10590 struct Key : Ob {
10591 char keyname[strmax];
10592 char fullname[20 + strmax]; // bug#19122346
10593 // 0-parent 1-child
10594 const Tab* tab0;
10595 const Tab* tab1;
10596 const Ind* ind0;
10597 const Ind* ind1;
10598 NdbDictionary::ForeignKey::FkAction updateAction;
10599 NdbDictionary::ForeignKey::FkAction deleteAction;
10600 };
10601 struct List {
10602 NdbDictionary::Dictionary::List* list;
10603 int keystart; // FK stuff sorted to end of list starts here
ListFkdef::List10604 List() { list = 0; }
~ListFkdef::List10605 ~List() { delete list; }
10606 };
10607 Tab tab[tabmax];
10608 int ntab;
10609 Key key[keymax];
10610 int nkey;
10611 List list;
10612 bool nokeys;
10613 bool nodrop;
10614 int testcase;
10615 };
10616
10617 static int
fk_compare_icol(const void * p1,const void * p2)10618 fk_compare_icol(const void* p1, const void* p2)
10619 {
10620 const Fkdef::Col& col1 = *(const Fkdef::Col*)p1;
10621 const Fkdef::Col& col2 = *(const Fkdef::Col*)p2;
10622 return col1.icol - col2.icol;
10623 }
10624
10625 static int
fk_type(int t)10626 fk_type(int t)
10627 {
10628 if (
10629 t == NdbDictionary::Object::ForeignKey ||
10630 t == NdbDictionary::Object::FKParentTrigger ||
10631 t == NdbDictionary::Object::FKChildTrigger
10632 )
10633 return 1;
10634 return 0;
10635 }
10636
10637 static int
fk_compare_element(const void * p1,const void * p2)10638 fk_compare_element(const void* p1, const void* p2)
10639 {
10640 const NdbDictionary::Dictionary::List::Element& e1 =
10641 *(const NdbDictionary::Dictionary::List::Element*)p1;
10642 const NdbDictionary::Dictionary::List::Element& e2 =
10643 *(const NdbDictionary::Dictionary::List::Element*)p2;
10644 int k = 0;
10645 if ((k = fk_type(e1.type) - fk_type(e2.type)) != 0)
10646 return k;
10647 if ((k = e1.type - e2.type) != 0)
10648 return k;
10649 if ((k = (int)e1.id - (int)e2.id) != 0)
10650 return k;
10651 return 0;
10652 }
10653
10654 static bool
fk_find_element(const Fkdef::List & list,int type,const char * database,const char * name)10655 fk_find_element(const Fkdef::List& list, int type,
10656 const char* database, const char* name)
10657 {
10658 int found = 0;
10659 for (int i = 0; i < (int)list.list->count; i++)
10660 {
10661 const NdbDictionary::Dictionary::List::Element& e =
10662 list.list->elements[i];
10663 if (e.type == type &&
10664 strcmp(e.database, database) == 0 &&
10665 strcmp(e.name, name) == 0)
10666 {
10667 found++;
10668 }
10669 }
10670 require(found == 0 || found == 1);
10671 return found;
10672 }
10673
10674 // testcase 1: t0 (a0 pk, b0 key), t1 (a1 pk, b1 key), fk b1->a0
10675
10676 static void
fk_define_tables1(Fkdef & d)10677 fk_define_tables1(Fkdef& d)
10678 {
10679 d.ntab = 2;
10680 for (int i = 0; i < d.ntab; i++)
10681 {
10682 Fkdef::Tab& dt = d.tab[i];
10683 sprintf(dt.tabname, "t%d", i);
10684 dt.ncol = 2;
10685 for (int j = 0; j < dt.ncol; j++)
10686 {
10687 Fkdef::Col& dc = dt.col[j];
10688 sprintf(dc.colname, "%c%d", 'a' + j, i);
10689 dc.pk = (j == 0);
10690 dc.nullable = false;
10691 dc.icol = j;
10692 }
10693 dt.nind = 2;
10694 dt.pTab = 0;
10695 dt.retrieved = false;
10696 {
10697 Fkdef::Ind& di = dt.ind[0];
10698 sprintf(di.indname, "%s", "pk");
10699 di.ncol = 1;
10700 di.col[0] = dt.col[0];
10701 di.pk = true;
10702 di.unique = true;
10703 di.pInd = 0;
10704 di.retrieved = false;
10705 }
10706 {
10707 Fkdef::Ind& di = dt.ind[1];
10708 sprintf(di.indname, "t%dx%d", i, 1);
10709 di.ncol = 1;
10710 di.col[0] = dt.col[1];
10711 di.pk = false;
10712 di.unique = false;
10713 di.pInd = 0;
10714 di.retrieved = false;
10715 }
10716 }
10717 g_info << "defined " << d.ntab << " tables" << endl;
10718 }
10719
10720 static void
fk_define_keys1(Fkdef & d)10721 fk_define_keys1(Fkdef& d)
10722 {
10723 d.nkey = 1;
10724 Fkdef::Key& dk = d.key[0];
10725 sprintf(dk.keyname, "fk%d", 0);
10726 dk.tab0 = &d.tab[0];
10727 dk.tab1 = &d.tab[1];
10728 dk.ind0 = &dk.tab0->ind[0];
10729 dk.ind1 = &dk.tab1->ind[1];
10730 dk.updateAction = NdbDictionary::ForeignKey::NoAction;
10731 dk.deleteAction = NdbDictionary::ForeignKey::NoAction;
10732 dk.retrieved = false;
10733 g_info << "defined " << d.nkey << " keys" << endl;
10734 }
10735
10736 // testcase 2: random
10737
10738 static void
fk_define_tables2(Fkdef & d)10739 fk_define_tables2(Fkdef& d)
10740 {
10741 d.ntab = 1 + myRandom48(d.tabmax);
10742 for (int i = 0; i < d.ntab; i++)
10743 {
10744 Fkdef::Tab& dt = d.tab[i];
10745 sprintf(dt.tabname, "t%d", i);
10746 dt.ncol = 2 + myRandom48(d.colmax - 1);
10747 for (int j = 0; j < dt.ncol; j++)
10748 {
10749 Fkdef::Col& dc = dt.col[j];
10750 sprintf(dc.colname, "%c%d", 'a' + j, i);
10751 dc.pk = (j == 0 || myRandom48(d.colmax) == 0);
10752 dc.nullable = false;
10753 dc.icol = j;
10754 }
10755 dt.nind = 1 + myRandom48(d.indmax);
10756 dt.pTab = 0;
10757 dt.retrieved = false;
10758 for (int k = 0; k < dt.nind; k++)
10759 {
10760 Fkdef::Ind& di = dt.ind[k];
10761 if (k == 0)
10762 {
10763 sprintf(di.indname, "%s", "pk");
10764 di.ncol = 0;
10765 for (int j = 0; j < dt.ncol; j++)
10766 {
10767 Fkdef::Col& dc = dt.col[j];
10768 if (dc.pk)
10769 di.col[di.ncol++] = dc;
10770 }
10771 di.pk = true;
10772 di.unique = true;
10773 }
10774 else
10775 {
10776 di.unique = (myRandom48(3) != 0);
10777 sprintf(di.indname, "t%dx%d", i, k);
10778 di.ncol = 1 + myRandom48(dt.ncol);
10779 uint mask = 0;
10780 int n = 0;
10781 while (n < di.ncol)
10782 {
10783 int j = myRandom48(dt.ncol);
10784 Fkdef::Col& dc = dt.col[j];
10785 if ((mask & (1 << j)) == 0)
10786 {
10787 di.col[n++] = dc;
10788 mask |= (1 << j);
10789 }
10790 }
10791 if (di.unique)
10792 qsort(&di.col, di.ncol, sizeof(di.col[0]), fk_compare_icol);
10793 }
10794 di.pInd = 0;
10795 di.retrieved = false;
10796 }
10797 }
10798 g_info << "defined " << d.ntab << " tables" << endl;
10799 }
10800
10801 static void
fk_define_keys2(Fkdef & d)10802 fk_define_keys2(Fkdef& d)
10803 {
10804 int nkey = 1 + myRandom48(d.ntab * 5);
10805 int k = 0;
10806 int ntrymax = nkey * 100;
10807 int ntry = 0;
10808 while (k < nkey && ntry++ < ntrymax)
10809 {
10810 Fkdef::Key& dk = d.key[k];
10811 new (&dk) Fkdef::Key;
10812 int i0 = myRandom48(d.ntab);
10813 int i1 = myRandom48(d.ntab);
10814 Fkdef::Tab& dt0 = d.tab[i0];
10815 Fkdef::Tab& dt1 = d.tab[i1];
10816 int k0 = myRandom48(dt0.nind);
10817 int k1 = myRandom48(dt1.nind);
10818 Fkdef::Ind& di0 = dt0.ind[k0];
10819 Fkdef::Ind& di1 = dt1.ind[k1];
10820 if (!di0.unique || di0.ncol != di1.ncol)
10821 continue;
10822 if (i0 == i1 && k0 == k1)
10823 if (myRandom48(10) != 0) // allowed but try to avoid
10824 continue;
10825 sprintf(dk.keyname, "fk%d", k);
10826 dk.tab0 = &dt0;
10827 dk.tab1 = &dt1;
10828 dk.ind0 = &di0;
10829 dk.ind1 = &di1;
10830 dk.updateAction = NdbDictionary::ForeignKey::NoAction;
10831 dk.deleteAction = NdbDictionary::ForeignKey::NoAction;
10832 dk.retrieved = false;
10833 k++;
10834 }
10835 d.nkey = k;
10836 g_info << "defined " << d.nkey << " keys tries:" << ntry << endl;
10837 }
10838
10839 static void
fk_define_tables(Fkdef & d)10840 fk_define_tables(Fkdef& d)
10841 {
10842 if (d.testcase == 1)
10843 fk_define_tables1(d);
10844 else if (d.testcase == 2)
10845 fk_define_tables2(d);
10846 else
10847 require(false);
10848 }
10849
10850 static void
fk_define_keys(Fkdef & d)10851 fk_define_keys(Fkdef& d)
10852 {
10853 if (d.nokeys)
10854 {
10855 d.nkey = 0;
10856 return;
10857 }
10858 if (d.testcase == 1)
10859 fk_define_keys1(d);
10860 else if (d.testcase == 2)
10861 fk_define_keys2(d);
10862 else
10863 require(false);
10864 }
10865
10866 static void
fk_undefine_keys(Fkdef & d)10867 fk_undefine_keys(Fkdef& d)
10868 {
10869 d.nkey = 0;
10870 }
10871
10872 static void
fk_define_all(Fkdef & d)10873 fk_define_all(Fkdef& d)
10874 {
10875 fk_define_tables(d);
10876 fk_define_keys(d);
10877 }
10878
10879 static int
fk_create_table(Fkdef & d,Ndb * pNdb,int i)10880 fk_create_table(Fkdef& d, Ndb* pNdb, int i)
10881 {
10882 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
10883 int result = NDBT_OK;
10884 do
10885 {
10886 Fkdef::Tab& dt = d.tab[i];
10887 NdbDictionary::Table tab;
10888 tab.setName(dt.tabname);
10889 for (int j = 0; j < dt.ncol; j++)
10890 {
10891 Fkdef::Col& dc = dt.col[j];
10892 NdbDictionary::Column col;
10893 col.setName(dc.colname);
10894 col.setType(NdbDictionary::Column::Unsigned);
10895 col.setPrimaryKey(dc.pk);
10896 col.setNullable(dc.nullable);
10897 tab.addColumn(col);
10898 }
10899 g_info << "create table " << dt.tabname << endl;
10900 CHK2(pDic->createTable(tab) == 0, pDic->getNdbError());
10901 const NdbDictionary::Table* pTab = 0;
10902 CHK2((pTab = pDic->getTable(dt.tabname)) != 0, pDic->getNdbError());
10903 require(!dt.retrieved);
10904 dt.retrieved = true;
10905 dt.id = pTab->getObjectId();
10906 dt.version = pTab->getObjectVersion();
10907 dt.pTab = pTab;
10908 for (int k = 1; k < dt.nind; k++) // skip pk
10909 {
10910 Fkdef::Ind& di = dt.ind[k];
10911 NdbDictionary::Index ind;
10912 ind.setName(di.indname);
10913 ind.setTable(dt.tabname);
10914 if (di.unique)
10915 {
10916 ind.setType(NdbDictionary::Index::UniqueHashIndex);
10917 ind.setLogging(true);
10918 }
10919 else
10920 {
10921 ind.setType(NdbDictionary::Index::OrderedIndex);
10922 ind.setLogging(false);
10923 }
10924 for (int j = 0; j < di.ncol; j++)
10925 {
10926 const Fkdef::Col& dc = di.col[j];
10927 ind.addColumn(dc.colname);
10928 }
10929 g_info << "create index " << di.indname << endl;
10930 CHK2(pDic->createIndex(ind) == 0, pDic->getNdbError());
10931 const NdbDictionary::Index* pInd = 0;
10932 CHK2((pInd = pDic->getIndex(di.indname, dt.tabname)) != 0, pDic->getNdbError());
10933 require(!di.retrieved);
10934 di.retrieved = true;
10935 di.id = pInd->getObjectId();
10936 di.version = pInd->getObjectVersion();
10937 di.pInd = pInd;
10938 }
10939 }
10940 while (0);
10941 return result;
10942 }
10943
10944 static int
fk_create_tables(Fkdef & d,Ndb * pNdb)10945 fk_create_tables(Fkdef& d, Ndb* pNdb)
10946 {
10947 int result = NDBT_OK;
10948 for (int i = 0; i < d.ntab; i++)
10949 {
10950 CHK1(fk_create_table(d, pNdb, i) == NDBT_OK);
10951 }
10952 return result;
10953 }
10954
10955 static int
fk_create_key(Fkdef & d,Ndb * pNdb,int k)10956 fk_create_key(Fkdef& d, Ndb* pNdb, int k)
10957 {
10958 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
10959 int result = NDBT_OK;
10960 do
10961 {
10962 Fkdef::Key& dk = d.key[k];
10963 NdbDictionary::ForeignKey key;
10964 key.setName(dk.keyname);
10965 const Fkdef::Tab& dt0 = *dk.tab0;
10966 const Fkdef::Tab& dt1 = *dk.tab1;
10967 const Fkdef::Ind& di0 = *dk.ind0;
10968 const Fkdef::Ind& di1 = *dk.ind1;
10969 const NdbDictionary::Table* pTab0 = dt0.pTab;
10970 const NdbDictionary::Table* pTab1 = dt1.pTab;
10971 const NdbDictionary::Index* pInd0 = di0.pInd;
10972 const NdbDictionary::Index* pInd1 = di1.pInd;
10973 key.setParent(*pTab0, pInd0);
10974 key.setChild(*pTab1, pInd1);
10975 g_info << "create key " << dk.keyname << endl;
10976 CHK2(pDic->createForeignKey(key) == 0, pDic->getNdbError());
10977 {
10978 NdbDictionary::ForeignKey key;
10979 sprintf(dk.fullname, "%d/%d/%s", dt0.id, dt1.id, dk.keyname);
10980 CHK2(pDic->getForeignKey(key, dk.fullname) == 0, pDic->getNdbError());
10981 require(!dk.retrieved);
10982 dk.retrieved = true;
10983 dk.id = key.getObjectId();
10984 dk.version = key.getObjectVersion();
10985 }
10986 }
10987 while (0);
10988 return result;
10989 }
10990
10991 static int
fk_create_keys(Fkdef & d,Ndb * pNdb)10992 fk_create_keys(Fkdef& d, Ndb* pNdb)
10993 {
10994 int result = NDBT_OK;
10995 for (int k = 0; k < d.nkey; k++)
10996 {
10997 CHK1(fk_create_key(d, pNdb, k) == NDBT_OK);
10998 }
10999 return result;
11000 }
11001
11002 static int
fk_alter_table(Fkdef & d,Ndb * pNdb,int i)11003 fk_alter_table(Fkdef& d, Ndb* pNdb, int i)
11004 {
11005 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
11006 int result = NDBT_OK;
11007 do
11008 {
11009 Fkdef::Tab& dt = d.tab[i];
11010 const NdbDictionary::Table* pTab1 = 0;
11011 CHK2((pTab1 = pDic->getTable(dt.tabname)) != 0, pDic->getNdbError());
11012 g_info << "alter table " << dt.tabname << endl;
11013 int id1 = pTab1->getObjectId();
11014 int version1 = pTab1->getObjectVersion();
11015 g_info << "old: id=" << id1 << " version=" << hex << version1 << endl;
11016 CHK2(pDic->alterTable(*pTab1, *pTab1) == 0, pDic->getNdbError());
11017 pDic->invalidateTable(dt.tabname);
11018 const NdbDictionary::Table* pTab2 = 0;
11019 CHK2((pTab2 = pDic->getTable(dt.tabname)) != 0, pDic->getNdbError());
11020 int id2 = pTab2->getObjectId();
11021 int version2 = pTab2->getObjectVersion();
11022 g_info << "old: id=" << id2 << " version=" << hex << version2 << endl;
11023 CHK2(id1 == id2, id1 << " != " << id2);
11024 CHK2(version1 != version2, version1 << " == " << version2);
11025 dt.id = id2;
11026 dt.version = version2;
11027 }
11028 while (0);
11029 return result;
11030 }
11031
11032 static int
fk_alter_tables(Fkdef & d,Ndb * pNdb,bool atrandom)11033 fk_alter_tables(Fkdef& d, Ndb* pNdb, bool atrandom)
11034 {
11035 int result = NDBT_OK;
11036 for (int i = 0; i < d.ntab; i++)
11037 {
11038 if (!atrandom || myRandom48(2) == 0)
11039 {
11040 CHK1(fk_alter_table(d, pNdb, i) == NDBT_OK);
11041 }
11042 }
11043 return result;
11044 }
11045
11046 static int
fk_create_all(Fkdef & d,Ndb * pNdb)11047 fk_create_all(Fkdef& d, Ndb* pNdb)
11048 {
11049 int result = NDBT_OK;
11050 do
11051 {
11052 CHK1(fk_create_tables(d, pNdb) == 0);
11053 CHK1(fk_create_keys(d, pNdb) == NDBT_OK);
11054 // imitate mysqld by doing an alter table afterwards
11055 CHK1(fk_alter_tables(d, pNdb, true) == NDBT_OK);
11056 }
11057 while (0);
11058 return result;
11059 }
11060
11061 static int
fk_verify_table(const Fkdef & d,Ndb * pNdb,int i)11062 fk_verify_table(const Fkdef& d, Ndb* pNdb, int i)
11063 {
11064 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
11065 int result = NDBT_OK;
11066 do
11067 {
11068 const Fkdef::Tab& dt = d.tab[i];
11069 g_info << "verify table " << dt.tabname << endl;
11070 const NdbDictionary::Table* pTab = 0;
11071 CHK2((pTab = pDic->getTable(dt.tabname)) != 0, pDic->getNdbError());
11072 int id = pTab->getObjectId();
11073 int version = pTab->getObjectVersion();
11074 require(dt.retrieved);
11075 CHK2(dt.id == id, dt.id << " != " << id);
11076 CHK2(dt.version == version, dt.version << " != " << version);
11077 for (int k = 1; k < dt.nind; k++) // skip pk
11078 {
11079 const Fkdef::Ind& di = dt.ind[k];
11080 g_info << "verify index " << di.indname << endl;
11081 const NdbDictionary::Index* pInd = 0;
11082 CHK2((pInd = pDic->getIndex(di.indname, dt.tabname)) != 0, pDic->getNdbError());
11083 int id = pInd->getObjectId();
11084 int version = pInd->getObjectVersion();
11085 require(di.retrieved);
11086 CHK2(di.id == id, di.id << " != " << id);
11087 CHK2(di.version == version, di.version << " != " << version);
11088 }
11089 CHK1(result == NDBT_OK);
11090 }
11091 while (0);
11092 return result;
11093 }
11094
11095 static int
fk_verify_tables(const Fkdef & d,Ndb * pNdb)11096 fk_verify_tables(const Fkdef& d, Ndb* pNdb)
11097 {
11098 int result = NDBT_OK;
11099 for (int i = 0; i < d.ntab; i++)
11100 {
11101 CHK1(fk_verify_table(d, pNdb, i) == 0);
11102 }
11103 return result;
11104 }
11105
11106 static int
fk_verify_key(const Fkdef & d,Ndb * pNdb,int k)11107 fk_verify_key(const Fkdef& d, Ndb* pNdb, int k)
11108 {
11109 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
11110 int result = NDBT_OK;
11111 do
11112 {
11113 const Fkdef::Key& dk = d.key[k];
11114 g_info << "verify key " << dk.fullname << endl;
11115 NdbDictionary::ForeignKey key;
11116 CHK2(pDic->getForeignKey(key, dk.fullname) == 0, pDic->getNdbError());
11117 int id = key.getObjectId();
11118 int version = key.getObjectVersion();
11119 require(dk.retrieved);
11120 CHK2(dk.id == id, dk.id << " != " << id);
11121 CHK2(dk.version == version, dk.version << " != " << version);
11122 CHK2(strcmp(dk.fullname, key.getName()) == 0, dk.fullname << " != " << key.getName());
11123 #if 0 // can add more checks
11124 const Fkdef::Tab& dt0 = *dk.tab0;
11125 const Fkdef::Tab& dt1 = *dk.tab1;
11126 const Fkdef::Ind& di0 = *dk.ind0;
11127 const Fkdef::Ind& di1 = *dk.ind1;
11128 #endif
11129 }
11130 while (0);
11131 return result;
11132 }
11133
11134 static int
fk_verify_keys(const Fkdef & d,Ndb * pNdb)11135 fk_verify_keys(const Fkdef& d, Ndb* pNdb)
11136 {
11137 int result = NDBT_OK;
11138 for (int k = 0; k < d.nkey; k++)
11139 {
11140 CHK1(fk_verify_key(d, pNdb, k) == 0);
11141 }
11142 return result;
11143 }
11144
11145 static int
fk_verify_ddl(const Fkdef & d,Ndb * pNdb)11146 fk_verify_ddl(const Fkdef& d, Ndb* pNdb)
11147 {
11148 int result = NDBT_OK;
11149 do
11150 {
11151 g_info << "verify ddl" << endl;
11152 CHK1(fk_verify_tables(d, pNdb) == 0);
11153 CHK1(fk_verify_keys(d, pNdb) == 0);
11154 }
11155 while (0);
11156 return result;
11157 }
11158
11159 static int
fk_verify_dml(const Fkdef & d,Ndb * pNdb,int records)11160 fk_verify_dml(const Fkdef& d, Ndb* pNdb, int records)
11161 {
11162 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
11163 int result = NDBT_OK;
11164 const int batch = 1;
11165 const bool allowCV = false;
11166 const int errNoParent = 255;
11167 const int errHasChild = 256;
11168 do
11169 {
11170 if (!(d.testcase == 1 && records > 0))
11171 break;
11172 g_info << "verify dml" << endl;
11173 const Fkdef::Tab& dt0 = d.tab[0];
11174 const Fkdef::Tab& dt1 = d.tab[1];
11175 const NdbDictionary::Table* pTab0 = 0;
11176 const NdbDictionary::Table* pTab1 = 0;
11177 CHK2((pTab0 = pDic->getTable(dt0.tabname)) != 0, pDic->getNdbError());
11178 CHK2((pTab1 = pDic->getTable(dt1.tabname)) != 0, pDic->getNdbError());
11179 HugoTransactions tx0(*pTab0);
11180 HugoTransactions tx1(*pTab1);
11181 // insert into child t1 - not ok
11182 g_err << "expect error " << errNoParent << endl;
11183 CHK1(tx1.loadTable(pNdb, records, batch, allowCV) != 0);
11184 CHK2(tx1.getNdbError().code == errNoParent, tx1.getNdbError());
11185 // insert into parent t0 - ok
11186 CHK2(tx0.loadTable(pNdb, records, batch, allowCV) == 0,
11187 tx0.getNdbError());
11188 // insert into child t1 - ok (b1 is 0, a0 is 0,1,2,..)
11189 CHK2(tx1.loadTable(pNdb, records, batch, allowCV) == 0,
11190 tx1.getNdbError());
11191 // delete from parent - not ok
11192 g_err << "expect error " << errHasChild << endl;
11193 CHK1(tx0.pkDelRecords(pNdb, records, batch, allowCV) != 0);
11194 CHK2(tx0.getNdbError().code == errHasChild, tx0.getNdbError());
11195 // delete from child t1 - ok
11196 CHK2(tx1.pkDelRecords(pNdb, records, batch, allowCV) == 0,
11197 tx1.getNdbError());
11198 // delete from parent to - ok
11199 CHK2(tx0.pkDelRecords(pNdb, records, batch, allowCV) == 0,
11200 tx0.getNdbError());
11201 }
11202 while (0);
11203 return result;
11204 }
11205
11206 static int
fk_retrieve_list(Fkdef & d,Ndb * pNdb,Fkdef::List & list)11207 fk_retrieve_list(Fkdef& d, Ndb* pNdb, Fkdef::List& list)
11208 {
11209 (void)d;
11210 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
11211 int result = NDBT_OK;
11212 do
11213 {
11214 g_info << "list objects" << endl;
11215 require(list.list == 0);
11216 list.list = new NdbDictionary::Dictionary::List;
11217 CHK2(pDic->listObjects(*list.list) == 0, pDic->getNdbError());
11218 qsort(list.list->elements, list.list->count, sizeof(list.list->elements[0]),
11219 fk_compare_element);
11220 list.keystart = 0;
11221 for (int i = 0; i < (int)list.list->count; i++)
11222 {
11223 NdbDictionary::Dictionary::List::Element& e =
11224 list.list->elements[i];
11225 if (e.database == 0)
11226 {
11227 e.database = new char [1];
11228 e.database[0] = 0;
11229 }
11230 if (!fk_type(e.type))
11231 list.keystart++;
11232 g_info << "ob " << i << ":"
11233 << " type=" << e.type << " id=" << e.id
11234 << " db=" << e.database << " name=" << e.name << endl;
11235 if (i > 0)
11236 {
11237 const NdbDictionary::Dictionary::List::Element& e2 =
11238 list.list->elements[i - 1];
11239 CHK1(e.type != e2.type || e.id != e2.id);
11240 }
11241 }
11242 g_info << "list count=" << list.list->count
11243 << " keystart=" << list.keystart << endl;
11244 }
11245 while (0);
11246 return result;
11247 }
11248
11249 static int
fk_verify_list(Fkdef & d,Ndb * pNdb,bool ignore_keys)11250 fk_verify_list(Fkdef& d, Ndb* pNdb, bool ignore_keys)
11251 {
11252 int result = NDBT_OK;
11253 do
11254 {
11255 Fkdef::List& list1 = d.list;
11256 if (list1.list == 0)
11257 {
11258 g_info << "retrieve first object list" << endl;
11259 CHK1(fk_retrieve_list(d, pNdb, list1) == 0);
11260 }
11261 else
11262 {
11263 g_info << "verify object list old vs new"
11264 " ignore_keys=" << ignore_keys << endl;
11265 Fkdef::List list2;
11266 CHK1(fk_retrieve_list(d, pNdb, list2) == NDBT_OK);
11267 // optionally ignore FK stuff in either list
11268 int count1 = !ignore_keys ? list1.list->count : list1.keystart;
11269 int count2 = !ignore_keys ? list2.list->count : list2.keystart;
11270 CHK1(count1 == count2);
11271 for (int i = 0; i < count1; i++)
11272 {
11273 const NdbDictionary::Dictionary::List::Element& e1 =
11274 list1.list->elements[i];
11275 const NdbDictionary::Dictionary::List::Element& e2 =
11276 list2.list->elements[i];
11277 CHK2(e1.type == e2.type,
11278 i << ": " << e1.type << " != " << e2.type);
11279 CHK2(e1.id == e2.id,
11280 i << ": " << e1.id << " != " << e2.id);
11281 CHK2(strcmp(e1.database, e2.database) == 0,
11282 i << ": " << e1.database << " != " << e2.database);
11283 CHK2(strcmp(e1.name, e2.name) == 0,
11284 i << ": " << e1.name << " != " << e2.name);
11285 }
11286 CHK1(result == NDBT_OK);
11287 // replace old by new
11288 delete list1.list;
11289 list1.list = list2.list;
11290 list1.keystart = list2.keystart;
11291 list2.list = 0;
11292 }
11293 // verify objects vs list
11294 for (int i = 0; i < d.ntab; i++)
11295 {
11296 const Fkdef::Tab& dt = d.tab[i];
11297 CHK2(fk_find_element(list1, NdbDictionary::Object::UserTable,
11298 "TEST_DB", dt.tabname), dt.tabname);
11299 for (int k = 1; k < dt.nind; k++)
11300 {
11301 const Fkdef::Ind& di = dt.ind[k];
11302 if (di.unique)
11303 {
11304 CHK2(fk_find_element(list1, NdbDictionary::Object::UniqueHashIndex,
11305 "sys", di.indname), di.indname);
11306 }
11307 else
11308 {
11309 CHK2(fk_find_element(list1, NdbDictionary::Object::OrderedIndex,
11310 "sys", di.indname), di.indname);
11311 }
11312 }
11313 CHK1(result == NDBT_OK);
11314 }
11315 for (int k = 0; k < d.nkey; k++) {
11316 const Fkdef::Key& dk = d.key[k];
11317 CHK2(fk_find_element(list1, NdbDictionary::Object::ForeignKey,
11318 "", dk.fullname), dk.fullname);
11319 // could also check FK triggers..
11320 }
11321 CHK1(result == NDBT_OK);
11322 }
11323 while (0);
11324 return result;
11325 }
11326
11327 static int
fk_drop_table(Fkdef & d,Ndb * pNdb,int i,bool force)11328 fk_drop_table(Fkdef& d, Ndb* pNdb, int i, bool force)
11329 {
11330 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
11331 int result = NDBT_OK;
11332 do
11333 {
11334 Fkdef::Tab& dt = d.tab[i];
11335 g_info << "drop table " << dt.tabname
11336 << (force ? " (force)" : "") << endl;
11337 if (pDic->dropTable(dt.tabname) != 0)
11338 {
11339 const NdbError& err = pDic->getNdbError();
11340 CHK2(force, err);
11341 CHK2(err.code == 709 || err.code == 723, err);
11342 break;
11343 }
11344 // all indexes are dropped by ndb api
11345 // all related FKs child/parent are dropped by ndb api
11346 }
11347 while (0);
11348 return result;
11349 }
11350
11351 static int
fk_drop_tables(Fkdef & d,Ndb * pNdb,bool force)11352 fk_drop_tables(Fkdef& d, Ndb* pNdb, bool force)
11353 {
11354 int result = NDBT_OK;
11355 for (int i = 0; i < d.ntab; i++)
11356 {
11357 CHK1(fk_drop_table(d, pNdb, i, force) == NDBT_OK);
11358 }
11359 return result;
11360 }
11361
11362 static int
fk_drop_key(Fkdef & d,Ndb * pNdb,int k,bool force)11363 fk_drop_key(Fkdef& d, Ndb* pNdb, int k, bool force)
11364 {
11365 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
11366 int result = NDBT_OK;
11367 do
11368 {
11369 Fkdef::Key& dk = d.key[k];
11370 g_info << "drop key " << dk.fullname
11371 << (force ? " (force)" : "") << endl;
11372 NdbDictionary::ForeignKey key;
11373 if (pDic->getForeignKey(key, dk.fullname) != 0)
11374 {
11375 const NdbError& err = pDic->getNdbError();
11376 CHK2(force, err);
11377 CHK2(err.code == 709 || err.code == 723 || err.code == 21040, err);
11378 break;
11379 }
11380 CHK2(pDic->dropForeignKey(key) == 0, pDic->getNdbError());
11381 }
11382 while (0);
11383 return result;
11384 }
11385
11386 static int
fk_drop_keys(Fkdef & d,Ndb * pNdb,bool force)11387 fk_drop_keys(Fkdef& d, Ndb* pNdb, bool force)
11388 {
11389 int result = NDBT_OK;
11390 for (int k = 0; k < d.nkey; k++)
11391 {
11392 CHK1(fk_drop_key(d, pNdb, k, force) == NDBT_OK);
11393 }
11394 return result;
11395 }
11396
11397 static int
fk_drop_all(Fkdef & d,Ndb * pNdb,bool force)11398 fk_drop_all(Fkdef& d, Ndb* pNdb, bool force)
11399 {
11400 int result = NDBT_OK;
11401 do
11402 {
11403 CHK1(fk_drop_keys(d, pNdb, force) == NDBT_OK);
11404 CHK1(fk_drop_tables(d, pNdb, force) == NDBT_OK);
11405 }
11406 while (0);
11407 return result;
11408 }
11409
11410 // commit drop
11411
11412 // just reset all retrieved
11413 static void
fk_dropped_all(Fkdef & d)11414 fk_dropped_all(Fkdef& d)
11415 {
11416 for (int i = 0; i < d.ntab; i++)
11417 {
11418 Fkdef::Tab& dt = d.tab[i];
11419 dt.retrieved = false;
11420 for (int k = 0; k < dt.nind; k++)
11421 {
11422 Fkdef::Ind& di = dt.ind[k];
11423 di.retrieved = false;
11424 }
11425 }
11426 for (int k = 0; k < d.nkey; k++)
11427 {
11428 Fkdef::Key& dk = d.key[k];
11429 dk.retrieved = false;
11430 }
11431 }
11432
11433 // for FK_Bug18069680
11434
11435 static int
fk_create_all_random(Fkdef & d,Ndb * pNdb)11436 fk_create_all_random(Fkdef& d, Ndb* pNdb)
11437 {
11438 int result = NDBT_OK;
11439 int ntab = 0;
11440 int nkey = 0;
11441 do
11442 {
11443 for (int i = 0; i < d.ntab; i++)
11444 {
11445 Fkdef::Tab& dt = d.tab[i];
11446 if (!dt.retrieved && myRandom48(3) == 0)
11447 {
11448 CHK1(fk_create_table(d, pNdb, i) == 0);
11449 require(dt.retrieved);
11450 ntab++;
11451 }
11452 }
11453 CHK1(result == NDBT_OK);
11454 for (int k = 0; k < d.nkey; k++)
11455 {
11456 Fkdef::Key& dk = d.key[k];
11457 if (!dk.retrieved && myRandom48(3) == 0 &&
11458 dk.tab0->retrieved && dk.tab1->retrieved)
11459 {
11460 CHK1(fk_create_key(d, pNdb, k) == 0);
11461 require(dk.retrieved);
11462 nkey++;
11463 }
11464 }
11465 CHK1(result == NDBT_OK);
11466 require(ntab <= d.ntab && nkey <= d.nkey);
11467 }
11468 while (ntab < d.ntab || nkey < d.nkey);
11469 return result;
11470 }
11471
11472 static int
fk_drop_indexes_under(const Fkdef & d,Ndb * pNdb)11473 fk_drop_indexes_under(const Fkdef& d, Ndb* pNdb)
11474 {
11475 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
11476 int result = NDBT_OK;
11477 do
11478 {
11479 for (int i = 0; i < d.ntab; i++)
11480 {
11481 const Fkdef::Tab& dt = d.tab[i];
11482 for (int k = 1; k < dt.nind; k++) // skip pk
11483 {
11484 const Fkdef::Ind& di = dt.ind[k];
11485 int parent = 0;
11486 int child = 0;
11487 for (int m = 0; m < d.nkey; m++)
11488 {
11489 const Fkdef::Key& dk = d.key[m];
11490 if (dk.ind0 == &di)
11491 parent++;
11492 if (dk.ind1 == &di)
11493 child++;
11494 }
11495 if (parent != 0 || child != 0)
11496 {
11497 // drop must fail
11498 g_info << "try to drop index under " << di.indname
11499 << " parent:" << parent << " child:" << child << endl;
11500 int ret = pDic->dropIndex(di.indname, dt.tabname);
11501 CHK2(ret != 0, "no error on drop underlying index");
11502 const NdbError& err = pDic->getNdbError();
11503 // could be either error code depending on check order
11504 CHK2(err.code == 21081 || err.code == 21082, pDic->getNdbError());
11505 }
11506 }
11507 CHK1(result == NDBT_OK);
11508 }
11509 CHK1(result == NDBT_OK);
11510 }
11511 while (0);
11512 return result;
11513 }
11514
11515 // for manual testing
11516 static void
fk_env_options(Fkdef & d)11517 fk_env_options(Fkdef& d)
11518 {
11519 // random seed
11520 int seed = NdbHost_GetProcessId();
11521 #ifdef NDB_USE_GET_ENV
11522 {
11523 const char* p = NdbEnv_GetEnv("RANDOM_SEED", (char*)0, 0);
11524 if (p != 0)
11525 seed = atoi(p);
11526 }
11527 #endif
11528 myRandom48Init(seed);
11529 g_err << "random seed: " << seed << endl;
11530 // create no FKs at all
11531 d.nokeys = false;
11532 #ifdef NDB_USE_GET_ENV
11533 {
11534 const char* p = NdbEnv_GetEnv("FK_NOKEYS", (char*)0, 0);
11535 if (p != 0 && strchr("1Y", p[0]) != 0)
11536 d.nokeys = true;
11537 }
11538 #endif
11539 // do not drop objects at end
11540 d.nodrop = false;
11541 #ifdef NDB_USE_GET_ENV
11542 {
11543 const char* p = NdbEnv_GetEnv("FK_NODROP", (char*)0, 0);
11544 if (p != 0 && strchr("1Y", p[0]) != 0)
11545 d.nodrop = true;
11546 }
11547 #endif
11548 }
11549
11550 int
runFK_SRNR(NDBT_Context * ctx,NDBT_Step * step)11551 runFK_SRNR(NDBT_Context* ctx, NDBT_Step* step)
11552 {
11553 Ndb* pNdb = GETNDB(step);
11554 const int loops = ctx->getNumLoops();
11555 const int records = ctx->getNumRecords();
11556 int result = NDBT_OK;
11557
11558 NdbRestarter restarter;
11559 const int numdbnodes = restarter.getNumDbNodes();
11560
11561 Fkdef d;
11562 d.testcase = ctx->getProperty("testcase", (Uint32)0);
11563 fk_env_options(d);
11564 fk_define_all(d);
11565
11566 do
11567 {
11568 (void)fk_drop_all(d, pNdb, true);
11569 CHK1(fk_create_all(d, pNdb) == NDBT_OK);
11570 CHK1(fk_verify_ddl(d, pNdb) == NDBT_OK);
11571 CHK1(fk_verify_dml(d, pNdb, records) == NDBT_OK);
11572 CHK1(fk_verify_list(d, pNdb, false) == NDBT_OK);
11573
11574 for (int loop = 0; loop < loops; loop++)
11575 {
11576 g_info << "loop " << loop << "<" << loops << endl;
11577
11578 bool rs = (numdbnodes == 1 || myRandom48(2) == 0);
11579 if (rs)
11580 {
11581 g_info << "restart all" << endl;
11582 CHK1(restarter.restartAll() == 0);
11583 }
11584 else
11585 {
11586 int i = myRandom48(numdbnodes);
11587 int nodeid = restarter.getDbNodeId(i);
11588 bool initial = (bool)myRandom48(2);
11589 bool nostart = true;
11590 g_info << "restart node " << nodeid << " initial=" << initial << endl;
11591
11592 CHK1(restarter.restartOneDbNode(nodeid, initial, nostart) == 0);
11593 CHK1(restarter.waitNodesNoStart(&nodeid, 1) == 0);
11594 g_info << "nostart node " << nodeid << endl;
11595
11596 CHK1(fk_verify_ddl(d, pNdb) == NDBT_OK);
11597 CHK1(fk_verify_dml(d, pNdb, records) == NDBT_OK);
11598 CHK1(fk_verify_list(d, pNdb, false) == NDBT_OK);
11599
11600 g_info << "start node " << nodeid << endl;
11601 CHK1(restarter.startNodes(&nodeid, 1) == 0);
11602 }
11603
11604 CHK1(restarter.waitClusterStarted() == 0);
11605 CHK_NDB_READY(pNdb);
11606 g_info << "cluster is started" << endl;
11607
11608 CHK1(fk_verify_ddl(d, pNdb) == NDBT_OK);
11609 CHK1(fk_verify_dml(d, pNdb, records) == NDBT_OK);
11610 CHK1(fk_verify_list(d, pNdb, false) == NDBT_OK);
11611 }
11612 CHK1(result == NDBT_OK);
11613
11614 if (!d.nodrop)
11615 {
11616 CHK1(fk_drop_all(d, pNdb, false) == NDBT_OK);
11617 }
11618 }
11619 while (0);
11620
11621 if (result != NDBT_OK)
11622 {
11623 if (!d.nodrop)
11624 (void)fk_drop_all(d, pNdb, true);
11625 }
11626 return result;
11627 }
11628
11629 int
runFK_TRANS(NDBT_Context * ctx,NDBT_Step * step)11630 runFK_TRANS(NDBT_Context* ctx, NDBT_Step* step)
11631 {
11632 Ndb* pNdb = GETNDB(step);
11633 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
11634 const int loops = ctx->getNumLoops();
11635 const int records = ctx->getNumRecords();
11636 int result = NDBT_OK;
11637 const int abort_flag = NdbDictionary::Dictionary::SchemaTransAbort;
11638
11639 Fkdef d;
11640 d.testcase = ctx->getProperty("testcase", (Uint32)0);
11641 fk_env_options(d);
11642 fk_define_tables(d);
11643 fk_undefine_keys(d);
11644
11645 do
11646 {
11647 (void)fk_drop_all(d, pNdb, true);
11648 CHK1(fk_create_tables(d, pNdb) == NDBT_OK);
11649 CHK1(fk_verify_ddl(d, pNdb) == NDBT_OK);
11650 CHK1(fk_verify_list(d, pNdb, false) == NDBT_OK);
11651
11652 // what to do on loop % 3
11653 const int abort_loop[3][2] = { { 1, -1 }, { 0, 1 }, { 0, 0 } };
11654
11655 for (int loop = 0; loop < loops; loop++)
11656 {
11657 g_info << "loop " << loop << "<" << loops << endl;
11658
11659 int abort_create = abort_loop[loop % 3][0];
11660 require(abort_create == 0 || abort_create == 1);
11661 g_info << "abort create: " << abort_create << endl;
11662
11663 fk_define_keys(d);
11664 CHK2(pDic->beginSchemaTrans() == 0, pDic->getNdbError());
11665 CHK1(fk_create_keys(d, pNdb) == 0);
11666 if (!abort_create)
11667 {
11668 g_info << "commit schema trans" << endl;
11669 CHK2(pDic->endSchemaTrans(0) == 0, pDic->getNdbError());
11670 CHK1(fk_verify_ddl(d, pNdb) == NDBT_OK);
11671 CHK1(fk_verify_dml(d, pNdb, records) == NDBT_OK);
11672 CHK1(fk_verify_list(d, pNdb, true) == NDBT_OK);
11673 }
11674 else
11675 {
11676 g_info << "abort schema trans" << endl;
11677 CHK2(pDic->endSchemaTrans(abort_flag) == 0, pDic->getNdbError());
11678 fk_undefine_keys(d);
11679 CHK1(fk_verify_ddl(d, pNdb) == NDBT_OK);
11680 CHK1(fk_verify_list(d, pNdb, false) == NDBT_OK);
11681 continue; // nothing to drop
11682 }
11683
11684 int abort_drop = abort_loop[loop % 3][1];
11685 require(abort_drop == 0 || abort_drop == 1);
11686 g_info << "abort drop: " << abort_drop << endl;
11687
11688 CHK2(pDic->beginSchemaTrans() == 0, pDic->getNdbError());
11689 CHK1(fk_drop_keys(d, pNdb, false) == 0);
11690 if (!abort_drop)
11691 {
11692 g_info << "commit schema trans" << endl;
11693 CHK2(pDic->endSchemaTrans(0) == 0, pDic->getNdbError());
11694 fk_undefine_keys(d);
11695 CHK1(fk_verify_ddl(d, pNdb) == NDBT_OK);
11696 CHK1(fk_verify_list(d, pNdb, true) == NDBT_OK);
11697 }
11698 else
11699 {
11700 g_info << "abort schema trans" << endl;
11701 CHK2(pDic->endSchemaTrans(abort_flag) == 0, pDic->getNdbError());
11702 CHK1(fk_verify_ddl(d, pNdb) == NDBT_OK);
11703 CHK1(fk_verify_dml(d, pNdb, records) == NDBT_OK);
11704 CHK1(fk_verify_list(d, pNdb, false) == NDBT_OK);
11705 // prepare for next round
11706 CHK1(fk_drop_keys(d, pNdb, false) == NDBT_OK);
11707 fk_undefine_keys(d);
11708 }
11709 }
11710 CHK1(result == NDBT_OK);
11711
11712 if (!d.nodrop)
11713 {
11714 CHK1(fk_drop_all(d, pNdb, false) == NDBT_OK);
11715 }
11716 }
11717 while (0);
11718
11719 if (result != NDBT_OK)
11720 {
11721 (void)pDic->endSchemaTrans(abort_flag);
11722 if (!d.nodrop)
11723 (void)fk_drop_all(d, pNdb, true);
11724 }
11725 return result;
11726 }
11727
11728 int
runFK_Bug18069680(NDBT_Context * ctx,NDBT_Step * step)11729 runFK_Bug18069680(NDBT_Context* ctx, NDBT_Step* step)
11730 {
11731 Ndb* pNdb = GETNDB(step);
11732 const int loops = ctx->getNumLoops();
11733 const int records = ctx->getNumRecords();
11734 int result = NDBT_OK;
11735
11736 Fkdef d;
11737 d.testcase = ctx->getProperty("testcase", (Uint32)0);
11738 fk_env_options(d);
11739 fk_define_all(d);
11740
11741 do
11742 {
11743 (void)fk_drop_all(d, pNdb, true);
11744
11745 for (int loop = 0; loop < loops; loop++)
11746 {
11747 g_info << "loop " << loop << "<" << loops << endl;
11748
11749 CHK1(fk_create_all_random(d, pNdb) == NDBT_OK);
11750 CHK1(fk_verify_ddl(d, pNdb) == NDBT_OK);
11751 CHK1(fk_verify_dml(d, pNdb, records) == NDBT_OK);
11752
11753 CHK1(fk_drop_indexes_under(d, pNdb) == NDBT_OK);
11754 CHK1(fk_drop_tables(d, pNdb, false) == NDBT_OK);
11755
11756 fk_dropped_all(d);
11757 }
11758 CHK1(result == NDBT_OK);
11759 }
11760 while (0);
11761
11762 if (result != NDBT_OK)
11763 {
11764 if (!d.nodrop)
11765 (void)fk_drop_all(d, pNdb, true);
11766 }
11767 return result;
11768 }
11769
11770 #undef myRandom48
11771 #undef myRandom48Init
11772
11773 int
runDictTO_1(NDBT_Context * ctx,NDBT_Step * step)11774 runDictTO_1(NDBT_Context* ctx, NDBT_Step* step)
11775 {
11776 Ndb* pNdb = GETNDB(step);
11777 NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
11778 NdbRestarter restarter;
11779
11780 if (restarter.getNumDbNodes() < 3)
11781 return NDBT_OK;
11782
11783 for (int i = 0; i < ctx->getNumLoops(); i++)
11784 {
11785 int master = restarter.getMasterNodeId();
11786 int next = restarter.getNextMasterNodeId(master);
11787 int val2[] = { DumpStateOrd::CmvmiSetRestartOnErrorInsert, 1 };
11788
11789 restarter.dumpStateOneNode(master, val2, 2);
11790 restarter.insertError2InNode(master, 6050, next);
11791
11792 ndbout_c("master: %d next: %d", master, next);
11793 {
11794 g_info << "save all resource usage" << endl;
11795 int dump1[] = { DumpStateOrd::SchemaResourceSnapshot };
11796 restarter.dumpStateAllNodes(dump1, 1);
11797 }
11798
11799
11800 {
11801 if (pDic->beginSchemaTrans() != 0)
11802 {
11803 ndbout << "ERROR: line: " << __LINE__ << endl;
11804 ndbout << pDic->getNdbError();
11805 return NDBT_FAILED;
11806 }
11807 for (int j = 0; j < (i + 1); j++)
11808 {
11809 NdbDictionary::Table pTab(* ctx->getTab());
11810 pTab.setName(BaseString(pTab.getName()).appfmt("_EXTRA_%u", j).c_str());
11811
11812 if (pDic->createTable(pTab) != 0)
11813 {
11814 ndbout << "ERROR: line: " << __LINE__ << endl;
11815 ndbout << pDic->getNdbError();
11816 return NDBT_FAILED;
11817 }
11818 }
11819
11820 // this should give master failuer...but trans should rollforward
11821 if (pDic->endSchemaTrans() != 0)
11822 {
11823 ndbout << "ERROR: line: " << __LINE__ << endl;
11824 ndbout << pDic->getNdbError();
11825 return NDBT_FAILED;
11826 }
11827 }
11828
11829 for (int j = 0; j < (i + 1); j++)
11830 {
11831 pDic->dropTable(BaseString(ctx->getTab()->getName()).appfmt("_EXTRA_%u", j).c_str());
11832 }
11833
11834 {
11835 g_info << "check all resource usage" << endl;
11836 for (int j = 0; j < restarter.getNumDbNodes(); j++)
11837 {
11838 if (restarter.getDbNodeId(j) == master)
11839 continue;
11840
11841 int dump1[] = { DumpStateOrd::SchemaResourceCheckLeak };
11842 restarter.dumpStateOneNode(restarter.getDbNodeId(j), dump1, 1);
11843 }
11844 }
11845
11846 restarter.waitNodesNoStart(&master, 1);
11847 restarter.startNodes(&master, 1);
11848 restarter.waitClusterStarted();
11849 CHK_NDB_READY(pNdb);
11850 }
11851
11852 return NDBT_OK;
11853 }
11854
11855 int
runIndexStatTimeout(NDBT_Context * ctx,NDBT_Step * step)11856 runIndexStatTimeout(NDBT_Context* ctx, NDBT_Step* step)
11857 {
11858 Ndb* pNdb = GETNDB(step);
11859 NdbDictionary::Dictionary *pDict = pNdb->getDictionary();
11860 const NdbDictionary::Table* pTab = ctx->getTab();
11861 char idxname[20];
11862 sprintf(idxname, "%s_idx", pTab->getName());
11863 NdbRestarter restarter;
11864
11865 if(pTab == NULL)
11866 {
11867 ndbout << "Failed to get table " << endl;
11868 return NDBT_FAILED;
11869 }
11870 const NdbDictionary::Index* pIdx = pDict->getIndex(idxname, pTab->getName());
11871 if(pIdx == NULL)
11872 {
11873 ndbout << "Failed to get index" << idxname << " error " << pDict->getNdbError() << endl;
11874 return NDBT_FAILED;
11875 }
11876 ndbout << "Inserting error in ndbd to cause dictsignal timeout" << endl;
11877 if(restarter.insertErrorInAllNodes(6221) != 0)
11878 {
11879 ndbout << "Failed to insert error 6221" << endl;
11880 return NDBT_FAILED;
11881 }
11882
11883 ndbout << "Do error injection in ndbapi to timeout quickly" << endl;
11884 DBUG_SET_INITIAL("+d,ndb_dictsignal_timeout");
11885
11886 if(pDict->updateIndexStat(*pIdx, *pTab) == 0)
11887 {
11888 ndbout << "Error: updateIndexStat succeeded, should have failed" << endl;
11889 return NDBT_FAILED;
11890 }
11891 ndbout << "Clear error injection from ndbapi" << endl;
11892 DBUG_SET_INITIAL("-d,ndb_dictsignal_timeout");
11893
11894 ndbout << "Clear error insert in ndbd" << endl;
11895 if(restarter.insertErrorInAllNodes(0) != 0)
11896 {
11897 ndbout << "Failed to clear error 6221" << endl;
11898 return NDBT_FAILED;
11899 }
11900 int errorCode= pDict->getNdbError().code;
11901 if(errorCode != 4008)
11902 {
11903 ndbout << "Error: updateIndexStat failed with wrong error " << errorCode << endl;
11904 return NDBT_FAILED;
11905 }
11906 ndbout << "Success: updateIndexStat failed with expected error 4008" << endl;
11907 return NDBT_OK;
11908 }
11909
11910 int
runForceGCPWait(NDBT_Context * ctx,NDBT_Step * step)11911 runForceGCPWait(NDBT_Context* ctx, NDBT_Step* step)
11912 {
11913 Ndb* pNdb = GETNDB(step);
11914 NdbDictionary::Dictionary *pDict = pNdb->getDictionary();
11915 NdbRestarter restarter;
11916
11917 ndbout << "Inserting error in ndbd to cause dictsignal timeout" << endl;
11918 if(restarter.insertErrorInAllNodes(7247) != 0)
11919 {
11920 ndbout << "Failed to insert error 7247" << endl;
11921 return NDBT_FAILED;
11922 }
11923
11924 ndbout << "Do error injection in ndbapi to timeout quickly" << endl;
11925 DBUG_SET_INITIAL("+d,ndb_dictsignal_timeout");
11926
11927 if(pDict->forceGCPWait(0) == 0)
11928 {
11929 ndbout << "Error: forceGCPWait succeeded, should have failed" << endl;
11930 return NDBT_FAILED;
11931 }
11932 ndbout << "Clear error injection from ndbapi" << endl;
11933 DBUG_SET_INITIAL("-d,ndb_dictsignal_timeout");
11934
11935 ndbout << "Clear error insert in ndbd" << endl;
11936 if(restarter.insertErrorInAllNodes(0) != 0)
11937 {
11938 ndbout << "Failed to clear error 6222" << endl;
11939 return NDBT_FAILED;
11940 }
11941 int errorCode= pDict->getNdbError().code;
11942 if(errorCode != 4008)
11943 {
11944 ndbout << "Error: forceGCPWait failed with wrong error " << errorCode << endl;
11945 return NDBT_FAILED;
11946 }
11947 ndbout << "Success: forceGCPWait failed with expected error 4008" << endl;
11948 return NDBT_OK;
11949 }
11950
11951 /**
11952 * Testcase CreateManyDataFiles : Check if error code 1517 is
11953 * returned when DiskPageBufferMemory is exhausted.
11954 *
11955 * Provoke lack of DiskPageBufferMemory when creating data files
11956 * by reconfiguring it to the allowed minimum. Save the original
11957 * config value and reinstate it when runCreateManyDataFiles
11958 * creating many files is finished.
11959 */
11960 static int
changeStartDiskPageBufMem(NDBT_Context * ctx,NDBT_Step * step)11961 changeStartDiskPageBufMem(NDBT_Context *ctx, NDBT_Step *step)
11962 {
11963 Config conf;
11964 NdbRestarter restarter;
11965 Uint64 new_diskpage_buffer = 4 * 1024 * 1024; // Configured minimum value
11966 Uint64 start_disk_page_buffer = ctx->getProperty("STARTDISKPAGEBUFFER",
11967 (Uint64)new_diskpage_buffer);
11968
11969 NdbMgmd mgmd;
11970 Uint64 saved_old_value = 0;
11971 CHECK3(mgmd.change_config(start_disk_page_buffer, &saved_old_value,
11972 CFG_SECTION_NODE,
11973 CFG_DB_DISK_PAGE_BUFFER_MEMORY),
11974 "Change config failed");
11975
11976 // Save old config value in the test case context
11977 ctx->setProperty("STARTDISKPAGEBUFFER", Uint64(saved_old_value));
11978
11979 g_err << "Restarting nodes to apply config change from "
11980 << saved_old_value << " to " << start_disk_page_buffer << endl;
11981
11982 CHECK3(restarter.restartAll() == 0,
11983 "Restart all failed");
11984 CHECK3(restarter.waitClusterStarted(120) == 0,
11985 "Cluster has not started");
11986 g_err << "Nodes restarted with new config." << endl;
11987 return NDBT_OK;
11988 }
11989
11990 /**
11991 * If not exists, create LogfileGroup DEFAULT-LG and
11992 * create a tablespace DEFAULT-TS.
11993 * Save in test context whether log file group or
11994 * table space is created in this test case.
11995 */
11996 int
runCreateLogFileGroupTableSpace(NDBT_Context * ctx,NDBT_Step * step)11997 runCreateLogFileGroupTableSpace(NDBT_Context* ctx, NDBT_Step* step)
11998 {
11999 Ndb* pNdb = GETNDB(step);
12000 NdbDictionary::Dictionary *pDict = pNdb->getDictionary();
12001
12002 // Create a new LFG, if not exixts already
12003 bool log_file_group_created = false;
12004 NdbDictionary::LogfileGroup lg = pDict->getLogfileGroup("DEFAULT-LG");
12005 if (strcmp(lg.getName(), "DEFAULT-LG") != 0)
12006 {
12007 lg.setName("DEFAULT-LG");
12008 lg.setUndoBufferSize(1*1024*1024);
12009
12010 CHECK3(pDict->createLogfileGroup(lg) == 0, pDict->getNdbError());
12011 log_file_group_created = true;
12012 }
12013 // Save the info about the test created the log file group
12014 // "DEFAULT-LG" in the test case context.
12015 ctx->setProperty("LOGFILEGROUPCREATED", Uint32(log_file_group_created));
12016
12017 // Create a tablespace, if not exists
12018 bool ts_created = false;
12019 NdbDictionary::Tablespace ts = pDict->getTablespace("DEFAULT-TS");
12020 if (strcmp(ts.getName(), "DEFAULT-TS") != 0)
12021 {
12022 const char * tsName = "DEFAULT-TS";
12023 NdbDictionary::Tablespace ts;
12024 ts.setName(tsName);
12025 ts.setExtentSize(1024*1024);
12026 ts.setDefaultLogfileGroup("DEFAULT-LG");
12027
12028 CHECK3((pDict->createTablespace(ts)) == 0, pNdb->getNdbError());
12029 ts_created = true;
12030 }
12031 // Save the info about the test created the table space
12032 // "DEFAULT-TS" in the test case context.
12033 ctx->setProperty("TABLESPACECREATED", Uint32(ts_created));
12034 return NDBT_OK;
12035 }
12036
12037 /**
12038 * Drop DEFAULT-TS and DEFAULT-LG if the test case created them.
12039 * This info is saved in the test context.
12040 */
12041 int
runDropTableSpaceLG(NDBT_Context * ctx,NDBT_Step * step)12042 runDropTableSpaceLG(NDBT_Context* ctx, NDBT_Step* step)
12043 {
12044 Ndb* pNdb = GETNDB(step);
12045
12046 // Read the info about the test created the table space
12047 // "DEFAULT-TS" from the test case context.
12048 Uint32 ts_created =
12049 ctx->getProperty("TABLESPACECREATED", (Uint32)0);
12050
12051 if (ts_created)
12052 {
12053 // tablespace was created by this test case, remove it.
12054 if (pNdb->getDictionary()->dropTablespace(
12055 pNdb->getDictionary()->getTablespace("DEFAULT-TS")) != 0)
12056 {
12057 g_err << " Dropping table space DEFAULT-TS failed with "
12058 << pNdb->getDictionary()->getNdbError() << endl;
12059 // Don't return NDBT_FAILED, continue clean up log file group
12060 }
12061 }
12062
12063 // Read the info about the test created the log file group
12064 // "DEFAULT-LG" from the test case context.
12065 Uint32 log_file_group_created =
12066 ctx->getProperty("LOGFILEGROUPCREATED", (Uint32)0);
12067
12068 if (log_file_group_created)
12069 {
12070 // Log file group was created by this test case, remove it.
12071 CHECK3(pNdb->getDictionary()->dropLogfileGroup(
12072 pNdb->getDictionary()->getLogfileGroup("DEFAULT-LG")) == 0,
12073 pNdb->getDictionary()->getNdbError());
12074 }
12075 return NDBT_OK;
12076 }
12077
12078 /**
12079 * Create upto the number of data files given in the test case until
12080 * DiskPageBufferMemory gets exhausted, indicated by error code 1517.
12081 *
12082 * Drop data files.
12083 *
12084 * Test succeeds if the DiskPageBufferMemory gets exhausted,
12085 * fails otherwise.
12086 */
12087 int
runCreateManyDataFiles(NDBT_Context * ctx,NDBT_Step * step)12088 runCreateManyDataFiles(NDBT_Context* ctx, NDBT_Step* step)
12089 {
12090 Ndb* pNdb = GETNDB(step);
12091 NdbDictionary::Dictionary *pDict = pNdb->getDictionary();
12092 int result = NDBT_FAILED;
12093
12094 // Add many data files until disk page buffer gets filled
12095 Uint32 data_files_to_create = ctx->getProperty("DATAFILES",
12096 (Uint32)200);
12097 NdbDictionary::Datafile df;
12098 uint created_files = 0; // How many files are created so far
12099 char datafilename[256];
12100
12101 for (Uint32 datafile=0; datafile < data_files_to_create; ++datafile)
12102 {
12103 BaseString::snprintf(datafilename, sizeof(datafilename),
12104 "datafile%d", datafile);
12105 df.setPath(datafilename);
12106 df.setSize(1*1024*1024);
12107 df.setTablespace("DEFAULT-TS");
12108
12109 int res = pDict->createDatafile(df);
12110 if(res != 0)
12111 {
12112 int error = pDict->getNdbError().code;
12113 if (error == 1517)
12114 {
12115 // Error 1517 indicates DiskPageBufferMemory exhaustion.
12116 // Stop creating more data files.
12117 result = NDBT_OK;
12118 }
12119 else
12120 {
12121 g_err << "Failed to create datafile " << datafilename
12122 << endl << pDict->getNdbError() << endl;
12123 }
12124 break;
12125 }
12126 created_files++;
12127 }
12128
12129 // Clean up : remove the data files created
12130 for (uint datafile=0; datafile < created_files; ++datafile)
12131 {
12132 BaseString::snprintf(datafilename, sizeof(datafilename),
12133 "datafile%d", datafile);
12134 df.setPath(datafilename);
12135
12136 if (pNdb->getDictionary()->dropDatafile(
12137 pNdb->getDictionary()->getDatafile(0, datafilename)) != 0)
12138 {
12139 g_err << "Failed to create datafile " << datafilename
12140 << pNdb->getDictionary()->getNdbError() << endl;
12141 // Continue dropping rest of the data files
12142 }
12143 }
12144
12145 return result;
12146 }
12147
12148 NDBT_TESTSUITE(testDict);
12149 TESTCASE("testDropDDObjects",
12150 "* 1. start cluster\n"
12151 "* 2. Create LFG\n"
12152 "* 3. create TS\n"
12153 "* 4. run DropDDObjects\n"
12154 "* 5. Verify DropDDObjectsRestart worked\n"){
12155 INITIALIZER(runWaitStarted);
12156 INITIALIZER(runDropDDObjects);
12157 INITIALIZER(testDropDDObjectsSetup);
12158 STEP(runDropDDObjects);
12159 FINALIZER(DropDDObjectsVerify);
12160 }
12161
12162 TESTCASE("Bug29501",
12163 "* 1. start cluster\n"
12164 "* 2. Restart 1 node -abort -nostart\n"
12165 "* 3. create LFG\n"
12166 "* 4. Restart data node\n"
12167 "* 5. Restart 1 node -nostart\n"
12168 "* 6. Drop LFG\n"){
12169 INITIALIZER(runWaitStarted);
12170 INITIALIZER(runDropDDObjects);
12171 STEP(runBug29501);
12172 FINALIZER(runDropDDObjects);
12173 }
12174 TESTCASE("CreateAndDrop",
12175 "Try to create and drop the table loop number of times\n"){
12176 INITIALIZER(runCreateAndDrop);
12177 }
12178 TESTCASE("CreateAndDropAtRandom",
12179 "Try to create and drop table at random loop number of times\n"
12180 "Uses all available tables\n"
12181 "Uses error insert 4013 to make TUP verify table descriptor"){
12182 INITIALIZER(runCreateAndDropAtRandom);
12183 }
12184 TESTCASE("CreateAndDropIndexes",
12185 "Like CreateAndDropAtRandom but also creates random ordered\n"
12186 "indexes and loads data as a simple check of index operation"){
12187 TC_PROPERTY("CreateIndexes", 1);
12188 TC_PROPERTY("LoadData", 1);
12189 INITIALIZER(runCreateAndDropAtRandom);
12190 }
12191 TESTCASE("CreateAndDropWithData",
12192 "Try to create and drop the table when it's filled with data\n"
12193 "do this loop number of times\n"){
12194 INITIALIZER(runCreateAndDropWithData);
12195 }
12196 TESTCASE("CreateAndDropDuring",
12197 "Try to create and drop the table when other thread is using it\n"
12198 "do this loop number of times\n"){
12199 STEP(runCreateAndDropDuring);
12200 STEP(runUseTableUntilStopped);
12201 }
12202 TESTCASE("DropWithTakeover","bug 14190114"){
12203 INITIALIZER(runDropTakeoverTest);
12204 }
12205 TESTCASE("CreateInvalidTables",
12206 "Try to create the invalid tables we have defined\n"){
12207 INITIALIZER(runCreateInvalidTables);
12208 }
12209 TESTCASE("DropTableConcurrentLCP",
12210 "Drop a table while LCP is ongoing\n")
12211 {
12212 INITIALIZER(runCreateTheTable);
12213 INITIALIZER(runFillTable);
12214 INITIALIZER(runSetMinTimeBetweenLCP);
12215 INITIALIZER(runSetDropTableConcurrentLCP);
12216 INITIALIZER(runDropTheTable);
12217 FINALIZER(runResetMinTimeBetweenLCP);
12218 }
12219 TESTCASE("DropTableConcurrentLCP2",
12220 "Drop a table while LCP is ongoing\n")
12221 {
12222 INITIALIZER(runCreateTheTable);
12223 INITIALIZER(runFillTable);
12224 INITIALIZER(runSetMinTimeBetweenLCP);
12225 INITIALIZER(runSetDropTableConcurrentLCP2);
12226 INITIALIZER(runDropTheTable);
12227 FINALIZER(runResetMinTimeBetweenLCP);
12228 }
12229 TESTCASE("CreateTableWhenDbIsFull",
12230 "Try to create a new table when db already is full\n"){
12231 INITIALIZER(runCreateTheTable);
12232 INITIALIZER(runFillTable);
12233 INITIALIZER(runCreateTableWhenDbIsFull);
12234 INITIALIZER(runDropTableWhenDbIsFull);
12235 FINALIZER(runDropTheTable);
12236 }
12237 TESTCASE("FragmentTypeSingle",
12238 "Create the table with fragment type Single\n"){
12239 TC_PROPERTY("FragmentType", NdbDictionary::Table::FragSingle);
12240 INITIALIZER(runTestFragmentTypes);
12241 }
12242 TESTCASE("FragmentTypeAllSmall",
12243 "Create the table with fragment type AllSmall\n"){
12244 TC_PROPERTY("FragmentType", NdbDictionary::Table::FragAllSmall);
12245 INITIALIZER(runTestFragmentTypes);
12246 }
12247 TESTCASE("FragmentTypeAllMedium",
12248 "Create the table with fragment type AllMedium\n"){
12249 TC_PROPERTY("FragmentType", NdbDictionary::Table::FragAllMedium);
12250 INITIALIZER(runTestFragmentTypes);
12251 }
12252 TESTCASE("FragmentTypeAllLarge",
12253 "Create the table with fragment type AllLarge\n"){
12254 TC_PROPERTY("FragmentType", NdbDictionary::Table::FragAllLarge);
12255 INITIALIZER(runTestFragmentTypes);
12256 }
12257 TESTCASE("TemporaryTables",
12258 "Create the table as temporary and make sure it doesn't\n"
12259 "contain any data when system is restarted\n"){
12260 INITIALIZER(runTestTemporaryTables);
12261 }
12262 TESTCASE("CreateMaxTables",
12263 "Create tables until db says that it can't create any more\n"){
12264 TC_PROPERTY("tables", 1000);
12265 INITIALIZER(runCreateMaxTables);
12266 INITIALIZER(runDropMaxTables);
12267 }
12268 TESTCASE("BackupMaxTables",
12269 "Create max amount of tables and verify backup works\n"){
12270 TC_PROPERTY("tables", 200);
12271 INITIALIZER(runCreateMaxTables);
12272 INITIALIZER(runBackup);
12273 INITIALIZER(runDropMaxTables);
12274 }
12275 TESTCASE("PkSizes",
12276 "Create tables with all different primary key sizes.\n"\
12277 "Test all data operations insert, update, delete etc.\n"\
12278 "Drop table."){
12279 INITIALIZER(runPkSizes);
12280 }
12281 TESTCASE("StoreFrm",
12282 "Test that a frm file can be properly stored as part of the\n"
12283 "data in Dict."){
12284 INITIALIZER(runStoreFrm);
12285 }
12286 TESTCASE("GetPrimaryKey",
12287 "Test the function NdbDictionary::Column::getPrimaryKey\n"
12288 "It should return true only if the column is part of \n"
12289 "the primary key in the table"){
12290 INITIALIZER(runGetPrimaryKey);
12291 }
12292 TESTCASE("StoreExtraMetadata",
12293 "Test that extra metadata can be stored as part of the\n"
12294 "data in Dict."){
12295 INITIALIZER(runStoreExtraMetada);
12296 }
12297 TESTCASE("StoreExtraMetadataError",
12298 "Test that extra metadata with too long length can't be stored."){
12299 INITIALIZER(runStoreExtraMetadataError);
12300 }
12301 TESTCASE("TableRename",
12302 "Test basic table rename"){
12303 INITIALIZER(runTableRename);
12304 }
12305 TESTCASE("TableRenameSR",
12306 "Test that table rename can handle system restart"){
12307 INITIALIZER(runTableRenameSR);
12308 }
12309 TESTCASE("ColumnRename",
12310 "Test basic column rename"){
12311 INITIALIZER(runColumnRename);
12312 }
12313 TESTCASE("ColumnRenameSR",
12314 "Test that column rename can handle system restart"){
12315 INITIALIZER(runColumnRenameSR);
12316 }
12317 TESTCASE("DictionaryPerf",
12318 ""){
12319 INITIALIZER(runTestDictionaryPerf);
12320 }
12321 TESTCASE("CreateLogfileGroup", ""){
12322 INITIALIZER(runCreateLogfileGroup);
12323 }
12324 TESTCASE("CreateLogfileGroupWithFailure",
12325 "Create a log file group where a dict participant"
12326 " fails to create log buffer"){
12327 TC_PROPERTY("OneDictParticipantFail", 1);
12328 INITIALIZER(runCreateLogfileGroup);
12329 }
12330 TESTCASE("CreateTablespaceWithFailure",
12331 "Create a log file group where a dict participant"
12332 " fails to create log buffer"){
12333 TC_PROPERTY("OneDictParticipantFail", 1);
12334 STEP(runCreateTablespace);
12335 FINALIZER(runDropTableSpaceLogFileGroup);
12336 }
12337 TESTCASE("CreateTablespace",
12338 "Create a table space where a dict participant"
12339 " fails to create log buffer"){
12340 INITIALIZER(runCreateTablespace);
12341 }
12342 TESTCASE("CreateDiskTable", ""){
12343 INITIALIZER(runCreateDiskTable);
12344 }
12345 TESTCASE("FailAddFragment",
12346 "Fail add fragment or attribute in ACC or TUP or TUX\n"){
12347 INITIALIZER(runFailAddFragment);
12348 }
12349 TESTCASE("Restart_NF1",
12350 "DICT ops during node graceful shutdown (not master)"){
12351 TC_PROPERTY("Restart_NF_ops", 1);
12352 TC_PROPERTY("Restart_NF_type", 1);
12353 STEP(runRestarts);
12354 STEP(runDictOps);
12355 }
12356 TESTCASE("Restart_NF2",
12357 "DICT ops during node shutdown abort (not master)"){
12358 TC_PROPERTY("Restart_NF_ops", 1);
12359 TC_PROPERTY("Restart_NF_type", 2);
12360 STEP(runRestarts);
12361 STEP(runDictOps);
12362 }
12363 TESTCASE("Restart_NR1",
12364 "DICT ops during node startup (not master)"){
12365 TC_PROPERTY("Restart_NR_ops", 1);
12366 STEP(runRestarts);
12367 STEP(runDictOps);
12368 }
12369 TESTCASE("Restart_NR2",
12370 "DICT ops during node startup with crash inserts (not master)"){
12371 TC_PROPERTY("Restart_NR_ops", 1);
12372 TC_PROPERTY("Restart_NR_error", 1);
12373 STEP(runRestarts);
12374 STEP(runDictOps);
12375 }
12376 TESTCASE("TableAddAttrs",
12377 "Add attributes to an existing table using alterTable()"){
12378 INITIALIZER(runTableAddAttrs);
12379 }
12380 TESTCASE("TableAddAttrsDuring",
12381 "Try to add attributes to the table when other thread is using it\n"
12382 "do this loop number of times\n"){
12383 INITIALIZER(runCreateTheTable);
12384 STEP(runTableAddAttrsDuring);
12385 STEP(runUseTableUntilStopped2);
12386 STEP(runUseTableUntilStopped3);
12387 FINALIZER(runDropTheTable);
12388 }
12389 TESTCASE("TableAddAttrsDuringError",
12390 "Try to add attributes to the table when other thread is using it\n"
12391 "do this loop number of times\n"){
12392 TC_PROPERTY("AbortAlter", 1);
12393 INITIALIZER(runCreateTheTable);
12394 STEP(runTableAddAttrsDuring);
12395 STEP(runUseTableUntilStopped2);
12396 STEP(runUseTableUntilStopped3);
12397 FINALIZER(runDropTheTable);
12398 }
12399 TESTCASE("Bug21755",
12400 ""){
12401 INITIALIZER(runBug21755);
12402 }
12403 TESTCASE("DictRestart",
12404 ""){
12405 INITIALIZER(runDictRestart);
12406 }
12407 TESTCASE("Bug24631",
12408 ""){
12409 INITIALIZER(runBug24631);
12410 }
12411 TESTCASE("Bug36702", "")
12412 {
12413 INITIALIZER(runDropDDObjects);
12414 INITIALIZER(runBug36072);
12415 FINALIZER(restartClusterInitial);
12416 }
12417 TESTCASE("Bug29186",
12418 ""){
12419 INITIALIZER(runBug29186);
12420 }
12421 TESTCASE("Bug48604",
12422 "Online ordered index build.\n"
12423 "Complements testOIBasic -case f"){
12424 STEP(runBug48604);
12425 STEP(runBug48604ops);
12426 #if 0 // for future MT test
12427 STEP(runBug48604ops);
12428 STEP(runBug48604ops);
12429 STEP(runBug48604ops);
12430 #endif
12431 }
12432 TESTCASE("Bug54651", ""){
12433 INITIALIZER(runBug54651);
12434 }
12435 /** telco-6.4 **/
12436 TESTCASE("SchemaTrans",
12437 "Schema transactions"){
12438 ALL_TABLES();
12439 STEP(runSchemaTrans);
12440 }
12441 TESTCASE("FailCreateHashmap",
12442 "Fail create hashmap")
12443 {
12444 INITIALIZER(runFailCreateHashmap);
12445 }
12446 TESTCASE("FailAddPartition",
12447 "Fail add partition")
12448 {
12449 INITIALIZER(runFailAddPartition);
12450 }
12451 TESTCASE("TableAddPartitions",
12452 "Add partitions to an existing table using alterTable()"){
12453 INITIALIZER(runTableAddPartition);
12454 }
12455 TESTCASE("Bug41905",
12456 ""){
12457 STEP(runBug41905);
12458 STEP(runBug41905getTable);
12459 }
12460 TESTCASE("Bug46552", "")
12461 {
12462 INITIALIZER(runBug46552);
12463 }
12464 TESTCASE("Bug46585", "")
12465 {
12466 INITIALIZER(runWaitStarted);
12467 INITIALIZER(runBug46585);
12468 }
12469 TESTCASE("Bug53944", "")
12470 {
12471 INITIALIZER(runBug53944);
12472 }
12473 TESTCASE("Bug58277",
12474 "Dropping busy ordered index can crash data node.\n"
12475 "Give any tablename as argument (T1)"){
12476 TC_PROPERTY("RSS_CHECK", (Uint32)true);
12477 TC_PROPERTY("RANGE_MAX", (Uint32)5);
12478 INITIALIZER(runBug58277errtest);
12479 STEP(runBug58277);
12480 // sub-steps 2-8 synced with main step
12481 TC_PROPERTY("SubSteps", 7);
12482 STEP(runBug58277drop);
12483 /*
12484 * A single scan update can show the bug but this is not likely.
12485 * Add more scan updates. Also add PK ops for other asserts.
12486 */
12487 STEP(runBug58277scan);
12488 STEP(runBug58277scan);
12489 STEP(runBug58277scan);
12490 STEP(runBug58277scan);
12491 STEP(runBug58277pk);
12492 STEP(runBug58277pk);
12493 // kernel side scans (eg. LCP) for resource usage check
12494 STEP(runBug58277rand);
12495 }
12496 TESTCASE("Bug57057",
12497 "MRR + delete leaks stored procs (fixed under Bug58277).\n"
12498 "Give any tablename as argument (T1)"){
12499 TC_PROPERTY("RSS_CHECK", (Uint32)true);
12500 TC_PROPERTY("RANGE_MAX", (Uint32)100);
12501 TC_PROPERTY("SCAN_DELETE", (Uint32)1);
12502 STEP(runBug57057);
12503 TC_PROPERTY("SubSteps", 1);
12504 STEP(runBug58277scan);
12505 }
12506 TESTCASE("GetTabInfoRef", "Regression test for bug #14647210 'CAN CRASH ALL "
12507 "NODES EASILY WHEN RESTARTING MORE THAN 6 NODES SIMULTANEOUSLY'"
12508 " (missing handling of GET_TABINFOREF signal).")
12509 {
12510 INITIALIZER(runGetTabInfoRef);
12511 }
12512 TESTCASE("Bug13416603", "")
12513 {
12514 INITIALIZER(runCreateTheTable);
12515 INITIALIZER(runLoadTable);
12516 INITIALIZER(runBug13416603);
12517 FINALIZER(runDropTheTable);
12518 }
12519 TESTCASE("IndexStatCreate", "")
12520 {
12521 STEPS(runIndexStatCreate, 10);
12522 }
12523 TESTCASE("WL946",
12524 "Time types with fractional seconds.\n"
12525 "Give any tablename as argument (T1)"){
12526 INITIALIZER(runWL946);
12527 }
12528 TESTCASE("Bug14645319", "")
12529 {
12530 STEP(runBug14645319);
12531 }
12532 TESTCASE("FK_SRNR1",
12533 "Foreign keys SR/NR, simple case with DDL and DML checks.\n"
12534 "Give any tablename as argument (T1)"){
12535 TC_PROPERTY("testcase", 1);
12536 INITIALIZER(runFK_SRNR);
12537 }
12538 TESTCASE("FK_SRNR2",
12539 "Foreign keys SR/NR, complex case with DDL checks .\n"
12540 "Give any tablename as argument (T1)"){
12541 TC_PROPERTY("testcase", 2);
12542 INITIALIZER(runFK_SRNR);
12543 }
12544 TESTCASE("FK_TRANS1",
12545 "Foreign keys schema trans, simple case with DDL and DML checks.\n"
12546 "Give any tablename as argument (T1)"){
12547 TC_PROPERTY("testcase", 1);
12548 INITIALIZER(runFK_TRANS);
12549 }
12550 TESTCASE("FK_TRANS2",
12551 "Foreign keys schema trans, complex case with DDL checks.\n"
12552 "Give any tablename as argument (T1)"){
12553 TC_PROPERTY("testcase", 2);
12554 INITIALIZER(runFK_TRANS);
12555 }
12556 TESTCASE("FK_Bug18069680",
12557 "NDB API drop table with foreign keys.\n"
12558 "Give any tablename as argument (T1)"){
12559 TC_PROPERTY("testcase", 2);
12560 INITIALIZER(runFK_Bug18069680);
12561 }
12562 TESTCASE("CreateHashmaps",
12563 "Create (default) hashmaps")
12564 {
12565 INITIALIZER(runCreateHashmaps);
12566 }
12567 TESTCASE("DictTakeOver_1", "")
12568 {
12569 INITIALIZER(runDictTO_1);
12570 }
12571 TESTCASE("indexStat", "test dictsignal timeout in INDEX_STAT_REQ")
12572 {
12573 INITIALIZER(runCreateTheTable);
12574 INITIALIZER(runCreateTheIndex);
12575 INITIALIZER(runIndexStatTimeout);
12576 FINALIZER(runDropTheIndex);
12577 FINALIZER(runDropTheTable);
12578 }
12579 TESTCASE("forceGCPWait", "test dictsignal timeout in FORCE_GCP_WAIT")
12580 {
12581 INITIALIZER(runForceGCPWait);
12582 }
12583 TESTCASE("CreateManyDataFiles", "Test lack of DiskPageBufferMemory "
12584 "when creating data files")
12585 {
12586 INITIALIZER(changeStartDiskPageBufMem);
12587 INITIALIZER(runCreateLogFileGroupTableSpace);
12588 TC_PROPERTY("DATAFILES", (Uint32)200);
12589 INITIALIZER(runCreateManyDataFiles);
12590 FINALIZER(runDropTableSpaceLG);
12591 FINALIZER(changeStartDiskPageBufMem);
12592 }
12593
NDBT_TESTSUITE_END(testDict)12594 NDBT_TESTSUITE_END(testDict)
12595
12596 int main(int argc, const char** argv){
12597 ndb_init();
12598 NDBT_TESTSUITE_INSTANCE(testDict);
12599 // Tables should not be auto created
12600 testDict.setCreateTable(false);
12601 myRandom48Init((long)NdbTick_CurrentMillisecond());
12602 return testDict.execute(argc, argv);
12603 }
12604