1 /*
2    Copyright (c) 2003, 2015, 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 <ndb_global.h>
26 #include <my_sys.h>
27 
28 #define DBDICT_C
29 #include "Dbdict.hpp"
30 #include "diskpage.hpp"
31 
32 #include <ndb_limits.h>
33 #include <ndb_math.h>
34 #include <NdbOut.hpp>
35 #include <OutputStream.hpp>
36 #include <Properties.hpp>
37 #include <Configuration.hpp>
38 #include <SectionReader.hpp>
39 #include <SimpleProperties.hpp>
40 #include <AttributeHeader.hpp>
41 #include <KeyDescriptor.hpp>
42 #include <Checksum.hpp>
43 #include <signaldata/NodeRecoveryStatusRep.hpp>
44 #include <signaldata/DictSchemaInfo.hpp>
45 #include <signaldata/DictTabInfo.hpp>
46 #include <signaldata/DropTabFile.hpp>
47 
48 #include <signaldata/EventReport.hpp>
49 #include <signaldata/FsCloseReq.hpp>
50 #include <signaldata/FsConf.hpp>
51 #include <signaldata/FsOpenReq.hpp>
52 #include <signaldata/FsReadWriteReq.hpp>
53 #include <signaldata/FsRef.hpp>
54 #include <signaldata/GetTabInfo.hpp>
55 #include <signaldata/GetTableId.hpp>
56 #include <signaldata/HotSpareRep.hpp>
57 #include <signaldata/NFCompleteRep.hpp>
58 #include <signaldata/NodeFailRep.hpp>
59 #include <signaldata/ReadNodesConf.hpp>
60 #include <signaldata/RelTabMem.hpp>
61 #include <signaldata/WaitGCP.hpp>
62 #include <signaldata/ListTables.hpp>
63 
64 #include <signaldata/CreateTrig.hpp>
65 #include <signaldata/DropTrig.hpp>
66 #include <signaldata/CreateIndx.hpp>
67 #include <signaldata/DropIndx.hpp>
68 #include <signaldata/BuildIndx.hpp>
69 
70 #include <signaldata/DropFilegroup.hpp>
71 #include <signaldata/CreateFilegroup.hpp>
72 #include <signaldata/CreateFilegroupImpl.hpp>
73 
74 #include <signaldata/CreateEvnt.hpp>
75 #include <signaldata/UtilPrepare.hpp>
76 #include <signaldata/UtilExecute.hpp>
77 #include <signaldata/UtilRelease.hpp>
78 #include <signaldata/SumaImpl.hpp>
79 
80 #include <signaldata/LqhFrag.hpp>
81 #include <signaldata/DictStart.hpp>
82 #include <signaldata/DiAddTab.hpp>
83 #include <signaldata/DihStartTab.hpp>
84 
85 #include <signaldata/DropTable.hpp>
86 #include <signaldata/DropTab.hpp>
87 #include <signaldata/PrepDropTab.hpp>
88 
89 #include <signaldata/CreateTable.hpp>
90 #include <signaldata/AlterTable.hpp>
91 #include <signaldata/AlterTab.hpp>
92 #include <signaldata/CreateFragmentation.hpp>
93 #include <signaldata/CreateTab.hpp>
94 #include <NdbSleep.h>
95 #include <signaldata/ApiBroadcast.hpp>
96 #include <signaldata/DictLock.hpp>
97 #include <signaldata/BackupLockTab.hpp>
98 #include <IntrusiveList.hpp>
99 
100 #include <signaldata/DumpStateOrd.hpp>
101 #include <signaldata/CheckNodeGroups.hpp>
102 
103 #include <NdbEnv.h>
104 
105 #include <EventLogger.hpp>
106 extern EventLogger * g_eventLogger;
107 
108 #include <signaldata/SchemaTrans.hpp>
109 #include <DebuggerNames.hpp>
110 
111 #include <signaldata/DbinfoScan.hpp>
112 #include <signaldata/TransIdAI.hpp>
113 
114 #include <signaldata/IndexStatSignal.hpp>
115 
116 #define ZNOT_FOUND 626
117 #define ZALREADYEXIST 630
118 
119 #define ZRESTART_OPS_PER_TRANS 25
120 #define ZRESTART_NO_WRITE_AFTER_READ 1
121 
122 //#define EVENT_PH2_DEBUG
123 //#define EVENT_PH3_DEBUG
124 //#define EVENT_DEBUG
125 
126 static const char EVENT_SYSTEM_TABLE_NAME[] = "sys/def/NDB$EVENTS_0";
127 
128 #define EVENT_TRACE \
129 //  ndbout_c("Event debug trace: File: %s Line: %u", __FILE__, __LINE__)
130 
131 #define DIV(x,y) (((x)+(y)-1)/(y))
132 #define WORDS2PAGES(x) DIV(x, (ZSIZE_OF_PAGES_IN_WORDS - ZPAGE_HEADER_SIZE))
133 #include <ndb_version.h>
134 
135 #define JAM_FILE_ID 465
136 
137 
138 static
139 Uint32
alter_obj_inc_schema_version(Uint32 old)140 alter_obj_inc_schema_version(Uint32 old)
141 {
142    return (old & 0x00FFFFFF) + ((old + 0x1000000) & 0xFF000000);
143 }
144 
145 static
146 Uint32
alter_obj_dec_schema_version(Uint32 old)147 alter_obj_dec_schema_version(Uint32 old)
148 {
149   return (old & 0x00FFFFFF) + ((old - 0x1000000) & 0xFF000000);
150 }
151 
152 static
153 Uint32
create_obj_inc_schema_version(Uint32 old)154 create_obj_inc_schema_version(Uint32 old)
155 {
156   return (old + 0x00000001) & 0x00FFFFFF;
157 }
158 
159 static
160 void
do_swap(Uint32 & v0,Uint32 & v1)161 do_swap(Uint32 & v0, Uint32 & v1)
162 {
163   Uint32 save = v0;
164   v0 = v1;
165   v1 = save;
166 }
167 
168 /* **************************************************************** */
169 /* ---------------------------------------------------------------- */
170 /* MODULE:          GENERAL MODULE -------------------------------- */
171 /* ---------------------------------------------------------------- */
172 /*                                                                  */
173 /* This module contains general stuff. Mostly debug signals and     */
174 /* general signals that go into a specific module after checking a  */
175 /* state variable. Also general subroutines used by many.           */
176 /* ---------------------------------------------------------------- */
177 /* **************************************************************** */
178 
179 /* ---------------------------------------------------------------- */
180 // This signal is used to dump states of various variables in the
181 // block by command.
182 /* ---------------------------------------------------------------- */
183 void
execDUMP_STATE_ORD(Signal * signal)184 Dbdict::execDUMP_STATE_ORD(Signal* signal)
185 {
186   jamEntry();
187 
188 #ifdef VM_TRACE
189   if(signal->theData[0] == 1222){
190     const Uint32 tab = signal->theData[1];
191     PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
192     req->senderRef = reference();
193     req->senderData = 1222;
194     req->tableId = tab;
195     sendSignal(DBLQH_REF, GSN_PREP_DROP_TAB_REQ, signal,
196 	       PrepDropTabReq::SignalLength, JBB);
197   }
198 
199   if(signal->theData[0] == 1223){
200     const Uint32 tab = signal->theData[1];
201     PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
202     req->senderRef = reference();
203     req->senderData = 1222;
204     req->tableId = tab;
205     sendSignal(DBTC_REF, GSN_PREP_DROP_TAB_REQ, signal,
206 	       PrepDropTabReq::SignalLength, JBB);
207   }
208 
209   if(signal->theData[0] == 1224){
210     const Uint32 tab = signal->theData[1];
211     PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
212     req->senderRef = reference();
213     req->senderData = 1222;
214     req->tableId = tab;
215     sendSignal(DBDIH_REF, GSN_PREP_DROP_TAB_REQ, signal,
216 	       PrepDropTabReq::SignalLength, JBB);
217   }
218 
219   if(signal->theData[0] == 1225){
220     const Uint32 tab = signal->theData[1];
221     const Uint32 ver = signal->theData[2];
222     TableRecordPtr tabRecPtr;
223     bool ok = find_object(tabRecPtr, tab);
224     ndbrequire(ok);
225     DropTableReq * req = (DropTableReq*)signal->getDataPtr();
226     req->senderData = 1225;
227     req->senderRef = numberToRef(1,1);
228     req->tableId = tab;
229     req->tableVersion = tabRecPtr.p->tableVersion + ver;
230     sendSignal(DBDICT_REF, GSN_DROP_TABLE_REQ, signal,
231 	       DropTableReq::SignalLength, JBB);
232   }
233 #endif
234 #define MEMINFO(x, y) infoEvent(x ": %d %d", y.getSize(), y.getNoOfFree())
235   if(signal->theData[0] == 1226){
236     MEMINFO("c_obj_pool", c_obj_pool);
237     MEMINFO("c_opRecordPool", c_opRecordPool);
238     MEMINFO("c_rope_pool", c_rope_pool);
239   }
240 
241   if (signal->theData[0] == 1227)
242   {
243     DictObjectName_hash::Iterator iter;
244     bool ok = c_obj_name_hash.first(iter);
245     for (; ok; ok = c_obj_name_hash.next(iter))
246     {
247       LocalRope name(c_rope_pool, iter.curr.p->m_name);
248       char buf[1024];
249       name.copy(buf);
250       ndbout_c("%s m_ref_count: %d", buf, iter.curr.p->m_ref_count);
251       if (iter.curr.p->m_trans_key != 0)
252         ndbout_c("- m_trans_key: %u m_op_ref_count: %u",
253                  iter.curr.p->m_trans_key, iter.curr.p->m_op_ref_count);
254     }
255   }
256   if (signal->theData[0] == DumpStateOrd::DictDumpLockQueue)
257   {
258     jam();
259     m_dict_lock.dump_queue(m_dict_lock_pool, this);
260 
261     /* Space for hex form of enough words for node bitmask + \0 */
262     char buf[(((MAX_NDB_NODES + 31)/32) * 8) + 1 ];
263     infoEvent("DICT : c_sub_startstop _outstanding %u _lock %s",
264               c_outstanding_sub_startstop,
265               c_sub_startstop_lock.getText(buf));
266   }
267 
268   if (signal->theData[0] == 8004)
269   {
270     infoEvent("DICT: c_counterMgr size: %u free: %u",
271               c_counterMgr.getSize(),
272               c_counterMgr.getNoOfFree());
273     c_counterMgr.printNODE_FAILREP();
274   }
275 
276   if (signal->theData[0] == DumpStateOrd::SchemaResourceSnapshot)
277   {
278     RSS_AP_SNAPSHOT_SAVE(c_rope_pool);
279     RSS_AP_SNAPSHOT_SAVE(c_attributeRecordPool);
280     RSS_AP_SNAPSHOT_SAVE(c_tableRecordPool_);
281     RSS_AP_SNAPSHOT_SAVE(c_triggerRecordPool_);
282     RSS_AP_SNAPSHOT_SAVE(c_obj_pool);
283     RSS_AP_SNAPSHOT_SAVE(c_hash_map_pool);
284     RSS_AP_SNAPSHOT_SAVE(g_hash_map);
285   }
286 
287   if (signal->theData[0] == DumpStateOrd::SchemaResourceCheckLeak)
288   {
289     RSS_AP_SNAPSHOT_CHECK(c_rope_pool);
290     RSS_AP_SNAPSHOT_CHECK(c_attributeRecordPool);
291     RSS_AP_SNAPSHOT_CHECK(c_tableRecordPool_);
292     RSS_AP_SNAPSHOT_CHECK(c_triggerRecordPool_);
293     RSS_AP_SNAPSHOT_CHECK(c_obj_pool);
294     RSS_AP_SNAPSHOT_CHECK(c_hash_map_pool);
295     RSS_AP_SNAPSHOT_CHECK(g_hash_map);
296   }
297 
298   return;
299 
300 
301 }//Dbdict::execDUMP_STATE_ORD()
302 
execDBINFO_SCANREQ(Signal * signal)303 void Dbdict::execDBINFO_SCANREQ(Signal *signal)
304 {
305   DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
306   const Ndbinfo::ScanCursor* cursor =
307     CAST_CONSTPTR(Ndbinfo::ScanCursor, DbinfoScan::getCursorPtr(&req));
308   Ndbinfo::Ratelimit rl;
309 
310   jamEntry();
311 
312   switch(req.tableId){
313   case Ndbinfo::POOLS_TABLEID:
314   {
315     Ndbinfo::pool_entry pools[] =
316     {
317       { "Attribute Record",
318         c_attributeRecordPool.getUsed(),
319         c_attributeRecordPool.getSize(),
320         c_attributeRecordPool.getEntrySize(),
321         c_attributeRecordPool.getUsedHi(),
322         { CFG_DB_NO_ATTRIBUTES,0,0,0 }},
323       { "Table Record",
324         c_tableRecordPool_.getUsed(),
325         c_noOfMetaTables,
326         c_tableRecordPool_.getEntrySize(),
327         c_tableRecordPool_.getUsedHi(),
328         { CFG_DB_NO_TABLES,0,0,0 }},
329       { "Trigger Record",
330         c_triggerRecordPool_.getUsed(),
331         c_triggerRecordPool_.getSize(),
332         c_triggerRecordPool_.getEntrySize(),
333         c_triggerRecordPool_.getUsedHi(),
334         { CFG_DB_NO_TRIGGERS,0,0,0 }},
335       { "FS Connect Record",
336         c_fsConnectRecordPool.getUsed(),
337         c_fsConnectRecordPool.getSize(),
338         c_fsConnectRecordPool.getEntrySize(),
339         c_fsConnectRecordPool.getUsedHi(),
340         { 0,0,0,0 }},
341       { "DictObject",
342         c_obj_pool.getUsed(),
343         c_obj_pool.getSize(),
344         c_obj_pool.getEntrySize(),
345         c_obj_pool.getUsedHi(),
346         { CFG_DB_NO_TABLES,
347           CFG_DB_NO_ORDERED_INDEXES,
348           CFG_DB_NO_UNIQUE_HASH_INDEXES,
349           CFG_DB_NO_TRIGGERS }},
350       { "Transaction Handle",
351         c_txHandlePool.getUsed(),
352         c_txHandlePool.getSize(),
353         c_txHandlePool.getEntrySize(),
354         c_txHandlePool.getUsedHi(),
355         { 0,0,0,0 }},
356       { "Operation Record",
357         c_opRecordPool.getUsed(),
358         c_opRecordPool.getSize(),
359         c_opRecordPool.getEntrySize(),
360         c_opRecordPool.getUsedHi(),
361         { 0,0,0,0 }},
362       { NULL, 0,0,0,0,{0,0,0,0}}
363     };
364 
365     const size_t num_config_params =
366       sizeof(pools[0].config_params) / sizeof(pools[0].config_params[0]);
367     Uint32 pool = cursor->data[0];
368     BlockNumber bn = blockToMain(number());
369     while(pools[pool].poolname)
370     {
371       jam();
372       Ndbinfo::Row row(signal, req);
373       row.write_uint32(getOwnNodeId());
374       row.write_uint32(bn);           // block number
375       row.write_uint32(instance());   // block instance
376       row.write_string(pools[pool].poolname);
377       row.write_uint64(pools[pool].used);
378       row.write_uint64(pools[pool].total);
379       row.write_uint64(pools[pool].used_hi);
380       row.write_uint64(pools[pool].entry_size);
381       for (size_t i = 0; i < num_config_params; i++)
382         row.write_uint32(pools[pool].config_params[i]);
383       ndbinfo_send_row(signal, req, row, rl);
384       pool++;
385       if (rl.need_break(req))
386       {
387         jam();
388         ndbinfo_send_scan_break(signal, req, rl, pool);
389         return;
390       }
391     }
392     break;
393   }
394   case Ndbinfo::DICT_OBJ_INFO_TABLEID:
395   {
396     jam();
397     if (c_masterNodeId != getOwnNodeId())
398     {
399       jam();
400       break;
401     }
402     DictObjectName_hash::Iterator iter;
403     bool done = false;
404     const Uint32 nextBucket = cursor->data[0];
405 
406     if (nextBucket == 0)
407     {
408       // Start from the beginning.
409       jam();
410       done = !c_obj_name_hash.first(iter);
411     }
412     else
413     {
414       // Continue from where the last batch ended.
415       jam();
416       done = !c_obj_name_hash.next(nextBucket, iter);
417     }
418 
419     while (!done)
420     {
421       jam();
422       ListTablesData ltd;
423       Uint32 version, parentObjType, parentObjId;
424 
425       ndbrequire(buildListTablesData(*iter.curr.p,
426                                      RNIL,
427                                      ltd,
428                                      version,
429                                      parentObjType,
430                                      parentObjId));
431 
432       LocalRope name(c_rope_pool, iter.curr.p->m_name);
433       char nameBuff[PATH_MAX];
434       name.copy(nameBuff);
435       ndbassert(strlen(nameBuff) < PATH_MAX);
436 
437       /*
438         Try to find the parent of blob tables. Blob tables are named
439         <db name>/def/NDB$BLOB_<parent obj id>_<parent column num>
440        */
441       if (DictTabInfo::isTable(ltd.getTableType()) && parentObjId == 0)
442       {
443         jam();
444         const char* const blobNamePrefix = "/NDB$BLOB_";
445         const char* const blobNameStart = strstr(nameBuff, blobNamePrefix);
446 
447         if (blobNameStart != NULL)
448         {
449           jam();
450           char* parentIdEnd = NULL;
451           const long long num =
452             strtoll(blobNameStart+strlen(blobNamePrefix), &parentIdEnd, 10);
453           ndbassert(num > 0);
454           ndbassert(num < UINT_MAX32);
455           ndbassert(*parentIdEnd == '_');
456 
457           parentObjId = static_cast<Uint32>(num);
458           parentObjType = ltd.getTableType(); // System or user table.
459         }
460       }
461 
462       Ndbinfo::Row row(signal, req);
463 
464       /* Write values */
465       row.write_uint32(ltd.getTableType());
466       row.write_uint32(ltd.getTableId());
467       row.write_uint32(version);
468       row.write_uint32(ltd.getTableState());
469       row.write_uint32(parentObjType);
470       row.write_uint32(parentObjId);
471       row.write_string(nameBuff); /* FQ name */
472 
473       ndbinfo_send_row(signal, req, row, rl);
474 
475       const Uint32 oldBucket = iter.bucket;
476       done = !c_obj_name_hash.next(iter);
477 
478       if (!done)
479       {
480         jam();
481         const bool onBucketBoundary = (iter.bucket != oldBucket);
482 
483         /*
484           Ensure that we send all the entries in the current hash bucket before
485           ending the batch, since we use the bucket number to indicate where
486           the next batch should start.
487         */
488         if (onBucketBoundary && rl.need_break(req))
489         {
490           jam();
491           ndbinfo_send_scan_break(signal, req, rl, iter.bucket);
492           return;
493         }
494       }
495     }
496     break;
497   }
498   default:
499     break;
500   }
501 
502   ndbinfo_send_scan_conf(signal, req, rl);
503 }
504 
505 
506 /* ---------------------------------------------------------------- */
507 /* ---------------------------------------------------------------- */
508 // CONTINUEB is used when a real-time break is needed for long
509 // processes.
510 /* ---------------------------------------------------------------- */
511 /* ---------------------------------------------------------------- */
execCONTINUEB(Signal * signal)512 void Dbdict::execCONTINUEB(Signal* signal)
513 {
514   jamEntry();
515   switch (signal->theData[0]) {
516   case ZPACK_TABLE_INTO_PAGES :
517     jam();
518     packTableIntoPages(signal);
519     break;
520 
521   case ZSEND_GET_TAB_RESPONSE :
522     jam();
523     sendGetTabResponse(signal);
524     break;
525   case ZWAIT_SUBSTARTSTOP:
526     jam();
527     wait_substartstop(signal, signal->theData[1]);
528     return;
529   case ZDICT_TAKEOVER_REQ :
530   {
531     jam();
532     Uint32* data = &signal->theData[0];
533     memmove(&data[0], &data[1], DictTakeoverReq::SignalLength << 2);
534     execDICT_TAKEOVER_REQ(signal);
535   }
536   break;
537   case ZINDEX_STAT_BG_PROCESS:
538     jam();
539     indexStatBg_process(signal);
540     break;
541 #ifdef ERROR_INSERT
542   case 6103: // search for it
543     jam();
544     {
545       Uint32* data = &signal->theData[0];
546       Uint32 masterRef = data[1];
547       memmove(&data[0], &data[2], SchemaTransImplConf::SignalLength << 2);
548       sendSignal(masterRef, GSN_SCHEMA_TRANS_IMPL_CONF, signal,
549                  SchemaTransImplConf::SignalLength, JBB);
550     }
551     break;
552   case 9999:
553     CRASH_INSERTION(ERROR_INSERT_VALUE);
554     break;
555 #endif
556   case ZCOMMIT_WAIT_GCI:
557     jam();
558     trans_commit_wait_gci(signal);
559     break;
560   case ZGET_TABINFO_RETRY:
561     // We have waited a while. Now we send a new request to the master.
562     memmove(signal->theData, signal->theData+1,
563             GetTabInfoReq::SignalLength * sizeof *signal->theData);
564     sendSignal(calcDictBlockRef(c_masterNodeId), GSN_GET_TABINFOREQ, signal,
565                GetTabInfoReq::SignalLength, JBB);
566     break;
567   case ZNEXT_GET_TAB_REQ:
568     jam();
569     startNextGetTabInfoReq(signal);
570     break;
571   default :
572     ndbrequire(false);
573     break;
574   }//switch
575   return;
576 }//execCONTINUEB()
577 
578 /* ---------------------------------------------------------------- */
579 /* ---------------------------------------------------------------- */
580 // Routine to handle pack table into pages.
581 /* ---------------------------------------------------------------- */
582 /* ---------------------------------------------------------------- */
583 
packTableIntoPages(Signal * signal)584 void Dbdict::packTableIntoPages(Signal* signal)
585 {
586   const Uint32 tableId= signal->theData[1];
587   const Uint32 type= signal->theData[2];
588   const Uint32 pageId= signal->theData[3];
589 
590   Uint32 transId = c_retrieveRecord.schemaTransId;
591   GetTabInfoReq req_copy;
592   req_copy.senderRef = c_retrieveRecord.blockRef;
593   req_copy.senderData = c_retrieveRecord.m_senderData;
594   req_copy.schemaTransId = c_retrieveRecord.schemaTransId;
595   req_copy.requestType = c_retrieveRecord.requestType;
596   req_copy.tableId = tableId;
597 
598   {
599     SchemaFile::TableEntry *objEntry = 0;
600     if(tableId != RNIL)
601     {
602       XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
603       objEntry = getTableEntry(xsf, tableId);
604     }
605 
606     // The table seached for was not found
607     if(objEntry == 0)
608     {
609       jam();
610       sendGET_TABINFOREF(signal, &req_copy,
611                          GetTabInfoRef::TableNotDefined, __LINE__);
612       initRetrieveRecord(signal, 0, 0);
613       return;
614     }
615 
616     if (transId != 0 && transId == objEntry->m_transId)
617     {
618       jam();
619       // see own trans always
620     }
621     else if (refToBlock(req_copy.senderRef) != DBUTIL && /** XXX cheat */
622              refToBlock(req_copy.senderRef) != SUMA)
623     {
624       jam();
625       Uint32 err;
626       if ((err = check_read_obj(objEntry)))
627       {
628         jam();
629         // cannot see another uncommitted trans
630         sendGET_TABINFOREF(signal, &req_copy,
631                            (GetTabInfoRef::ErrorCode)err, __LINE__);
632         initRetrieveRecord(signal, 0, 0);
633         return;
634       }
635     }
636   }
637 
638   PageRecordPtr pagePtr;
639   c_pageRecordArray.getPtr(pagePtr, pageId);
640 
641   memset(&pagePtr.p->word[0], 0, 4 * ZPAGE_HEADER_SIZE);
642   LinearWriter w(&pagePtr.p->word[ZPAGE_HEADER_SIZE],
643 		 ZMAX_PAGES_OF_TABLE_DEFINITION * ZSIZE_OF_PAGES_IN_WORDS);
644   w.first();
645   switch((DictTabInfo::TableType)type) {
646   case DictTabInfo::SystemTable:
647   case DictTabInfo::UserTable:
648   case DictTabInfo::UniqueHashIndex:
649   case DictTabInfo::HashIndex:
650   case DictTabInfo::UniqueOrderedIndex:
651   case DictTabInfo::OrderedIndex:{
652     jam();
653     TableRecordPtr tablePtr;
654     bool ok = find_object(tablePtr, tableId);
655     if (!ok)
656     {
657       jam();
658       sendGET_TABINFOREF(signal, &req_copy,
659                          GetTabInfoRef::TableNotDefined, __LINE__);
660       initRetrieveRecord(signal, 0, 0);
661       return;
662     }
663 
664     packTableIntoPages(w, tablePtr, signal);
665     if (unlikely(signal->theData[0] != 0))
666     {
667       jam();
668       Uint32 err = signal->theData[0];
669       GetTabInfoRef * ref = CAST_PTR(GetTabInfoRef, signal->getDataPtrSend());
670       ref->tableId = c_retrieveRecord.tableId;
671       ref->senderRef = reference();
672       ref->senderData = c_retrieveRecord.m_senderData;
673       ref->errorCode = err;
674       Uint32 dstRef = c_retrieveRecord.blockRef;
675       sendSignal(dstRef, GSN_GET_TABINFOREF, signal,
676                  GetTabInfoRef::SignalLength, JBB);
677       initRetrieveRecord(signal,0,0);
678       return;
679     }
680     break;
681   }
682   case DictTabInfo::Tablespace:
683   case DictTabInfo::LogfileGroup:{
684     FilegroupPtr fg_ptr;
685     ndbrequire(find_object(fg_ptr, tableId));
686     const Uint32 free_hi= signal->theData[4];
687     const Uint32 free_lo= signal->theData[5];
688     packFilegroupIntoPages(w, fg_ptr, free_hi, free_lo);
689     break;
690   }
691   case DictTabInfo::Datafile:{
692     FilePtr fg_ptr;
693     ndbrequire(find_object(fg_ptr, tableId));
694     const Uint32 free_extents= signal->theData[4];
695     packFileIntoPages(w, fg_ptr, free_extents);
696     break;
697   }
698   case DictTabInfo::Undofile:{
699     FilePtr fg_ptr;
700     ndbrequire(find_object(fg_ptr, tableId));
701     packFileIntoPages(w, fg_ptr, 0);
702     break;
703   }
704   case DictTabInfo::HashMap:{
705     HashMapRecordPtr hm_ptr;
706     ndbrequire(find_object(hm_ptr, tableId));
707     packHashMapIntoPages(w, hm_ptr);
708     break;
709   }
710   case DictTabInfo::ForeignKey: {
711     Ptr<ForeignKeyRec> fk_ptr;
712     ndbrequire(find_object(fk_ptr, tableId));
713     packFKIntoPages(w, fk_ptr);
714     break;
715   }
716   case DictTabInfo::UndefTableType:
717   case DictTabInfo::HashIndexTrigger:
718   case DictTabInfo::SubscriptionTrigger:
719   case DictTabInfo::ReadOnlyConstraint:
720   case DictTabInfo::IndexTrigger:
721   case DictTabInfo::SchemaTransaction:
722   case DictTabInfo::ReorgTrigger:
723   case DictTabInfo::FKParentTrigger:
724   case DictTabInfo::FKChildTrigger:
725     ndbrequire(false);
726   }
727 
728   Uint32 wordsOfTable = w.getWordsUsed();
729   Uint32 pagesUsed = WORDS2PAGES(wordsOfTable);
730   pagePtr.p->word[ZPOS_CHECKSUM] =
731     computeChecksum(&pagePtr.p->word[0], pagesUsed * ZSIZE_OF_PAGES_IN_WORDS);
732 
733   switch (c_packTable.m_state) {
734   case PackTable::PTS_IDLE:
735     ndbrequire(false);
736     break;
737   case PackTable::PTS_GET_TAB:
738     jam();
739     c_retrieveRecord.retrievedNoOfPages = pagesUsed;
740     c_retrieveRecord.retrievedNoOfWords = wordsOfTable;
741     sendGetTabResponse(signal);
742     return;
743     break;
744   }//switch
745   ndbrequire(false);
746   return;
747 }//packTableIntoPages()
748 
749 void
packTableIntoPages(SimpleProperties::Writer & w,TableRecordPtr tablePtr,Signal * signal)750 Dbdict::packTableIntoPages(SimpleProperties::Writer & w,
751 			       TableRecordPtr tablePtr,
752 			       Signal* signal){
753 
754   union {
755     char tableName[MAX_TAB_NAME_SIZE];
756     char frmData[MAX_FRM_DATA_SIZE];
757     char rangeData[16*MAX_NDB_PARTITIONS];
758     char ngData[2*MAX_NDB_PARTITIONS];
759     char defaultValue[MAX_ATTR_DEFAULT_VALUE_SIZE];
760     char attributeName[MAX_ATTR_NAME_SIZE];
761   };
762   ConstRope r(c_rope_pool, tablePtr.p->tableName);
763   r.copy(tableName);
764   w.add(DictTabInfo::TableName, tableName);
765   w.add(DictTabInfo::TableId, tablePtr.p->tableId);
766   w.add(DictTabInfo::TableVersion, tablePtr.p->tableVersion);
767   w.add(DictTabInfo::NoOfKeyAttr, tablePtr.p->noOfPrimkey);
768   w.add(DictTabInfo::NoOfAttributes, tablePtr.p->noOfAttributes);
769   w.add(DictTabInfo::NoOfNullable, tablePtr.p->noOfNullAttr);
770   w.add(DictTabInfo::NoOfVariable, (Uint32)0);
771   w.add(DictTabInfo::KeyLength, tablePtr.p->tupKeyLength);
772 
773   w.add(DictTabInfo::TableLoggedFlag,
774 	!!(tablePtr.p->m_bits & TableRecord::TR_Logged));
775   w.add(DictTabInfo::RowGCIFlag,
776 	!!(tablePtr.p->m_bits & TableRecord::TR_RowGCI));
777   w.add(DictTabInfo::RowChecksumFlag,
778 	!!(tablePtr.p->m_bits & TableRecord::TR_RowChecksum));
779   w.add(DictTabInfo::TableTemporaryFlag,
780 	!!(tablePtr.p->m_bits & TableRecord::TR_Temporary));
781   w.add(DictTabInfo::ForceVarPartFlag,
782 	!!(tablePtr.p->m_bits & TableRecord::TR_ForceVarPart));
783 
784   w.add(DictTabInfo::MinLoadFactor, tablePtr.p->minLoadFactor);
785   w.add(DictTabInfo::MaxLoadFactor, tablePtr.p->maxLoadFactor);
786   w.add(DictTabInfo::TableKValue, tablePtr.p->kValue);
787   w.add(DictTabInfo::FragmentTypeVal, tablePtr.p->fragmentType);
788   w.add(DictTabInfo::TableTypeVal, tablePtr.p->tableType);
789   w.add(DictTabInfo::MaxRowsLow, tablePtr.p->maxRowsLow);
790   w.add(DictTabInfo::MaxRowsHigh, tablePtr.p->maxRowsHigh);
791   w.add(DictTabInfo::DefaultNoPartFlag, tablePtr.p->defaultNoPartFlag);
792   w.add(DictTabInfo::LinearHashFlag, tablePtr.p->linearHashFlag);
793   w.add(DictTabInfo::FragmentCount, tablePtr.p->fragmentCount);
794   w.add(DictTabInfo::MinRowsLow, tablePtr.p->minRowsLow);
795   w.add(DictTabInfo::MinRowsHigh, tablePtr.p->minRowsHigh);
796   w.add(DictTabInfo::SingleUserMode, tablePtr.p->singleUserMode);
797   w.add(DictTabInfo::HashMapObjectId, tablePtr.p->hashMapObjectId);
798   w.add(DictTabInfo::TableStorageType, tablePtr.p->storageType);
799   w.add(DictTabInfo::ExtraRowGCIBits, tablePtr.p->m_extra_row_gci_bits);
800   w.add(DictTabInfo::ExtraRowAuthorBits, tablePtr.p->m_extra_row_author_bits);
801 
802 
803   if (tablePtr.p->hashMapObjectId != RNIL)
804   {
805     HashMapRecordPtr hm_ptr;
806     ndbrequire(find_object(hm_ptr, tablePtr.p->hashMapObjectId));
807     w.add(DictTabInfo::HashMapVersion, hm_ptr.p->m_object_version);
808   }
809 
810   if(signal)
811   {
812     /* This branch is run at GET_TABINFOREQ */
813 
814     Uint32 err = 0;
815     if (!ERROR_INSERTED(6025))
816     {
817       err = get_fragmentation(signal, tablePtr.p->tableId);
818     }
819     else
820     {
821       err = CreateFragmentationRef::InvalidPrimaryTable;
822     }
823     if (unlikely(err != 0))
824     {
825       jam();
826       signal->theData[0] = err;
827       return;
828     }
829 
830     ndbrequire(err == 0);
831     Uint16 *data = (Uint16*)&signal->theData[25];
832     Uint32 count = 2 + (1 + data[0]) * data[1];
833     w.add(DictTabInfo::ReplicaDataLen, 2*count);
834     for (Uint32 i = 0; i < count; i++)
835       data[i] = htons(data[i]);
836     w.add(DictTabInfo::ReplicaData, data, 2*count);
837   }
838   else
839   {
840     /* This part is run at CREATE_TABLEREQ, ALTER_TABLEREQ */
841     ;
842   }
843 
844   if (tablePtr.p->primaryTableId != RNIL)
845   {
846     jam();
847     TableRecordPtr primTab;
848     bool ok = find_object(primTab, tablePtr.p->primaryTableId);
849     if (!ok)
850     {
851       jam();
852       ndbrequire(signal != NULL);
853       Uint32 err = CreateFragmentationRef::InvalidPrimaryTable;
854       signal->theData[0] = err;
855       return;
856     }
857     ConstRope r2(c_rope_pool, primTab.p->tableName);
858     r2.copy(tableName);
859     w.add(DictTabInfo::PrimaryTable, tableName);
860     w.add(DictTabInfo::PrimaryTableId, tablePtr.p->primaryTableId);
861     w.add(DictTabInfo::IndexState, tablePtr.p->indexState);
862     w.add(DictTabInfo::CustomTriggerId, tablePtr.p->triggerId);
863   }
864 
865   ConstRope frm(c_rope_pool, tablePtr.p->frmData);
866   frm.copy(frmData);
867   w.add(DictTabInfo::FrmLen, frm.size());
868   w.add(DictTabInfo::FrmData, frmData, frm.size());
869 
870   {
871     jam();
872     w.add(DictTabInfo::TablespaceDataLen, (Uint32)0);
873 
874     ConstRope ng(c_rope_pool, tablePtr.p->ngData);
875     ng.copy(ngData);
876     w.add(DictTabInfo::FragmentDataLen, ng.size());
877     w.add(DictTabInfo::FragmentData, ngData, ng.size());
878 
879     ConstRope range(c_rope_pool, tablePtr.p->rangeData);
880     range.copy(rangeData);
881     w.add(DictTabInfo::RangeListDataLen, range.size());
882     w.add(DictTabInfo::RangeListData, rangeData, range.size());
883   }
884 
885   if(tablePtr.p->m_tablespace_id != RNIL)
886   {
887     w.add(DictTabInfo::TablespaceId, tablePtr.p->m_tablespace_id);
888     FilegroupPtr tsPtr;
889     ndbrequire(find_object(tsPtr, tablePtr.p->m_tablespace_id));
890     w.add(DictTabInfo::TablespaceVersion, tsPtr.p->m_version);
891   }
892 
893   AttributeRecordPtr attrPtr;
894   LocalAttributeRecord_list list(c_attributeRecordPool,
895 				    tablePtr.p->m_attributes);
896   for(list.first(attrPtr); !attrPtr.isNull(); list.next(attrPtr)){
897     jam();
898 
899     ConstRope name(c_rope_pool, attrPtr.p->attributeName);
900     name.copy(attributeName);
901 
902     w.add(DictTabInfo::AttributeName, attributeName);
903     w.add(DictTabInfo::AttributeId, attrPtr.p->attributeId);
904     w.add(DictTabInfo::AttributeKeyFlag, attrPtr.p->tupleKey > 0);
905 
906     const Uint32 desc = attrPtr.p->attributeDescriptor;
907     const Uint32 attrType = AttributeDescriptor::getType(desc);
908     const Uint32 attrSize = AttributeDescriptor::getSize(desc);
909     const Uint32 arraySize = AttributeDescriptor::getArraySize(desc);
910     const Uint32 arrayType = AttributeDescriptor::getArrayType(desc);
911     const Uint32 nullable = AttributeDescriptor::getNullable(desc);
912     const Uint32 DKey = AttributeDescriptor::getDKey(desc);
913     const Uint32 disk= AttributeDescriptor::getDiskBased(desc);
914     const Uint32 dynamic= AttributeDescriptor::getDynamic(desc);
915 
916 
917     // AttributeType deprecated
918     w.add(DictTabInfo::AttributeSize, attrSize);
919     w.add(DictTabInfo::AttributeArraySize, arraySize);
920     w.add(DictTabInfo::AttributeArrayType, arrayType);
921     w.add(DictTabInfo::AttributeNullableFlag, nullable);
922     w.add(DictTabInfo::AttributeDynamic, dynamic);
923     w.add(DictTabInfo::AttributeDKey, DKey);
924     w.add(DictTabInfo::AttributeExtType, attrType);
925     w.add(DictTabInfo::AttributeExtPrecision, attrPtr.p->extPrecision);
926     w.add(DictTabInfo::AttributeExtScale, attrPtr.p->extScale);
927     w.add(DictTabInfo::AttributeExtLength, attrPtr.p->extLength);
928     w.add(DictTabInfo::AttributeAutoIncrement,
929 	  (Uint32)attrPtr.p->autoIncrement);
930 
931     if(disk)
932       w.add(DictTabInfo::AttributeStorageType, (Uint32)NDB_STORAGETYPE_DISK);
933     else
934       w.add(DictTabInfo::AttributeStorageType, (Uint32)NDB_STORAGETYPE_MEMORY);
935 
936     ConstRope def(c_rope_pool, attrPtr.p->defaultValue);
937     def.copy(defaultValue);
938 
939     if (def.size())
940     {
941       /* Convert default value to network byte order for storage */
942       /* Attribute header */
943       ndbrequire(def.size() >= sizeof(Uint32));
944       Uint32 a;
945       memcpy(&a, defaultValue, sizeof(Uint32));
946       a = htonl(a);
947       memcpy(defaultValue, &a, sizeof(Uint32));
948 
949       Uint32 remainBytes = def.size() - sizeof(Uint32);
950 
951       if (remainBytes)
952         NdbSqlUtil::convertByteOrder(attrType,
953                                      attrSize,
954                                      arrayType,
955                                      arraySize,
956                                      (uchar*) defaultValue + sizeof(Uint32),
957                                      remainBytes);
958     }
959 
960     w.add(DictTabInfo::AttributeDefaultValueLen, def.size());
961     w.add(DictTabInfo::AttributeDefaultValue, defaultValue, def.size());
962     w.add(DictTabInfo::AttributeEnd, 1);
963   }
964 
965   w.add(DictTabInfo::TableEnd, 1);
966 }
967 
968 void
packFilegroupIntoPages(SimpleProperties::Writer & w,FilegroupPtr fg_ptr,const Uint32 undo_free_hi,const Uint32 undo_free_lo)969 Dbdict::packFilegroupIntoPages(SimpleProperties::Writer & w,
970 			       FilegroupPtr fg_ptr,
971 			       const Uint32 undo_free_hi,
972 			       const Uint32 undo_free_lo){
973 
974   DictFilegroupInfo::Filegroup fg; fg.init();
975   ConstRope r(c_rope_pool, fg_ptr.p->m_name);
976   r.copy(fg.FilegroupName);
977 
978   fg.FilegroupId = fg_ptr.p->key;
979   fg.FilegroupType = fg_ptr.p->m_type;
980   fg.FilegroupVersion = fg_ptr.p->m_version;
981 
982   switch(fg.FilegroupType){
983   case DictTabInfo::Tablespace:
984   {
985     //fg.TS_DataGrow = group.m_grow_spec;
986     fg.TS_ExtentSize = fg_ptr.p->m_tablespace.m_extent_size;
987     fg.TS_LogfileGroupId = fg_ptr.p->m_tablespace.m_default_logfile_group_id;
988     FilegroupPtr lfg_ptr;
989     ndbrequire(find_object(lfg_ptr, fg.TS_LogfileGroupId));
990     fg.TS_LogfileGroupVersion = lfg_ptr.p->m_version;
991     break;
992   }
993   case DictTabInfo::LogfileGroup:
994     fg.LF_UndoBufferSize = fg_ptr.p->m_logfilegroup.m_undo_buffer_size;
995     fg.LF_UndoFreeWordsHi= undo_free_hi;
996     fg.LF_UndoFreeWordsLo= undo_free_lo;
997     //fg.LF_UndoGrow = ;
998     break;
999   default:
1000     ndbrequire(false);
1001   }
1002 
1003   SimpleProperties::UnpackStatus s;
1004   s = SimpleProperties::pack(w,
1005 			     &fg,
1006 			     DictFilegroupInfo::Mapping,
1007 			     DictFilegroupInfo::MappingSize, true);
1008 
1009   ndbrequire(s == SimpleProperties::Eof);
1010 }
1011 
1012 void
packFileIntoPages(SimpleProperties::Writer & w,FilePtr f_ptr,const Uint32 free_extents)1013 Dbdict::packFileIntoPages(SimpleProperties::Writer & w,
1014 			  FilePtr f_ptr, const Uint32 free_extents){
1015 
1016   DictFilegroupInfo::File f; f.init();
1017   ConstRope r(c_rope_pool, f_ptr.p->m_path);
1018   r.copy(f.FileName);
1019 
1020   f.FileType = f_ptr.p->m_type;
1021   f.FilegroupId = f_ptr.p->m_filegroup_id;; //group.m_id;
1022   f.FileSizeHi = (Uint32)(f_ptr.p->m_file_size >> 32);
1023   f.FileSizeLo = (Uint32)(f_ptr.p->m_file_size & 0xFFFFFFFF);
1024   f.FileFreeExtents= free_extents;
1025   f.FileId =  f_ptr.p->key;
1026   f.FileVersion = f_ptr.p->m_version;
1027 
1028   FilegroupPtr lfg_ptr;
1029   ndbrequire(find_object(lfg_ptr, f.FilegroupId));
1030   f.FilegroupVersion = lfg_ptr.p->m_version;
1031 
1032   SimpleProperties::UnpackStatus s;
1033   s = SimpleProperties::pack(w,
1034 			     &f,
1035 			     DictFilegroupInfo::FileMapping,
1036 			     DictFilegroupInfo::FileMappingSize, true);
1037 
1038   ndbrequire(s == SimpleProperties::Eof);
1039 }
1040 
1041 void
execCREATE_FRAGMENTATION_REQ(Signal * signal)1042 Dbdict::execCREATE_FRAGMENTATION_REQ(Signal* signal)
1043 {
1044   CreateFragmentationReq* req = (CreateFragmentationReq*)signal->getDataPtr();
1045 
1046   if (req->primaryTableId == RNIL) {
1047     jam();
1048     EXECUTE_DIRECT(DBDIH, GSN_CREATE_FRAGMENTATION_REQ, signal,
1049                    CreateFragmentationReq::SignalLength);
1050     return;
1051   }
1052 
1053   XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
1054   SchemaFile::TableEntry * te = getTableEntry(xsf, req->primaryTableId);
1055   if (te->m_tableState != SchemaFile::SF_CREATE)
1056   {
1057     jam();
1058     if (req->requestInfo == 0)
1059     {
1060       jam();
1061       req->requestInfo |= CreateFragmentationReq::RI_GET_FRAGMENTATION;
1062     }
1063     EXECUTE_DIRECT(DBDIH, GSN_CREATE_FRAGMENTATION_REQ, signal,
1064                    CreateFragmentationReq::SignalLength);
1065     return;
1066   }
1067 
1068   DictObjectPtr obj_ptr;
1069   TableRecordPtr tablePtr;
1070   bool ok = find_object(obj_ptr, tablePtr, req->primaryTableId);
1071   ndbrequire(ok);
1072   SchemaOpPtr op_ptr;
1073   findDictObjectOp(op_ptr, obj_ptr);
1074   ndbrequire(!op_ptr.isNull());
1075   OpRecPtr oprec_ptr = op_ptr.p->m_oprec_ptr;
1076   ndbrequire(memcmp(oprec_ptr.p->m_opType, "CTa", 4) == 0);
1077 
1078   Uint32 *theData = &signal->theData[0];
1079   const OpSection& fragSection =
1080     getOpSection(op_ptr, CreateTabReq::FRAGMENTATION);
1081   LocalArenaPoolImpl op_sec_pool(op_ptr.p->m_trans_ptr.p->m_arena,c_opSectionBufferPool);
1082   copyOut(op_sec_pool, fragSection, &theData[25], ZNIL);
1083   theData[0] = 0;
1084 }
1085 
1086 /* ---------------------------------------------------------------- */
1087 /* ---------------------------------------------------------------- */
1088 // The routines to handle responses from file system.
1089 /* ---------------------------------------------------------------- */
1090 /* ---------------------------------------------------------------- */
1091 
1092 /* ---------------------------------------------------------------- */
1093 // A file was successfully closed.
1094 /* ---------------------------------------------------------------- */
execFSCLOSECONF(Signal * signal)1095 void Dbdict::execFSCLOSECONF(Signal* signal)
1096 {
1097   FsConnectRecordPtr fsPtr;
1098   FsConf * const fsConf = (FsConf *)&signal->theData[0];
1099   jamEntry();
1100   c_fsConnectRecordPool.getPtr(fsPtr, fsConf->userPointer);
1101   switch (fsPtr.p->fsState) {
1102   case FsConnectRecord::CLOSE_WRITE_SCHEMA:
1103     jam();
1104     closeWriteSchemaConf(signal, fsPtr);
1105     break;
1106   case FsConnectRecord::CLOSE_READ_SCHEMA:
1107     jam();
1108     closeReadSchemaConf(signal, fsPtr);
1109     break;
1110   case FsConnectRecord::CLOSE_READ_TAB_FILE:
1111     jam();
1112     closeReadTableConf(signal, fsPtr);
1113     break;
1114   case FsConnectRecord::CLOSE_WRITE_TAB_FILE:
1115     jam();
1116     closeWriteTableConf(signal, fsPtr);
1117     break;
1118   case FsConnectRecord::OPEN_READ_SCHEMA2:
1119     openSchemaFile(signal, 1, fsPtr.i, false, false);
1120     break;
1121   case FsConnectRecord::OPEN_READ_TAB_FILE2:
1122     openTableFile(signal, 1, fsPtr.i, c_readTableRecord.tableId, false);
1123     break;
1124   default:
1125     jamLine((fsPtr.p->fsState & 0xFFF));
1126     ndbrequire(false);
1127     break;
1128   }//switch
1129 }//execFSCLOSECONF()
1130 
1131 
1132 /* ---------------------------------------------------------------- */
1133 // A file was successfully opened.
1134 /* ---------------------------------------------------------------- */
execFSOPENCONF(Signal * signal)1135 void Dbdict::execFSOPENCONF(Signal* signal)
1136 {
1137   FsConnectRecordPtr fsPtr;
1138   jamEntry();
1139   FsConf * const fsConf = (FsConf *)&signal->theData[0];
1140   c_fsConnectRecordPool.getPtr(fsPtr, fsConf->userPointer);
1141 
1142   Uint32 filePointer = fsConf->filePointer;
1143   fsPtr.p->filePtr = filePointer;
1144   switch (fsPtr.p->fsState) {
1145   case FsConnectRecord::OPEN_WRITE_SCHEMA:
1146     jam();
1147     fsPtr.p->fsState = FsConnectRecord::WRITE_SCHEMA;
1148     writeSchemaFile(signal, filePointer, fsPtr.i);
1149     break;
1150   case FsConnectRecord::OPEN_READ_SCHEMA1:
1151     jam();
1152     fsPtr.p->fsState = FsConnectRecord::READ_SCHEMA1;
1153     readSchemaFile(signal, filePointer, fsPtr.i);
1154     break;
1155   case FsConnectRecord::OPEN_READ_SCHEMA2:
1156     jam();
1157     fsPtr.p->fsState = FsConnectRecord::READ_SCHEMA2;
1158     readSchemaFile(signal, filePointer, fsPtr.i);
1159     break;
1160   case FsConnectRecord::OPEN_READ_TAB_FILE1:
1161     jam();
1162     fsPtr.p->fsState = FsConnectRecord::READ_TAB_FILE1;
1163     readTableFile(signal, filePointer, fsPtr.i);
1164     break;
1165   case FsConnectRecord::OPEN_READ_TAB_FILE2:
1166     jam();
1167     fsPtr.p->fsState = FsConnectRecord::READ_TAB_FILE2;
1168     readTableFile(signal, filePointer, fsPtr.i);
1169     break;
1170   case FsConnectRecord::OPEN_WRITE_TAB_FILE:
1171     jam();
1172     fsPtr.p->fsState = FsConnectRecord::WRITE_TAB_FILE;
1173     writeTableFile(signal, filePointer, fsPtr.i);
1174     break;
1175   default:
1176     jamLine((fsPtr.p->fsState & 0xFFF));
1177     ndbrequire(false);
1178     break;
1179   }//switch
1180 }//execFSOPENCONF()
1181 
1182 /* ---------------------------------------------------------------- */
1183 // An open file was refused.
1184 /* ---------------------------------------------------------------- */
execFSOPENREF(Signal * signal)1185 void Dbdict::execFSOPENREF(Signal* signal)
1186 {
1187   jamEntry();
1188   FsRef * const fsRef = (FsRef *)&signal->theData[0];
1189   FsConnectRecordPtr fsPtr;
1190   c_fsConnectRecordPool.getPtr(fsPtr, fsRef->userPointer);
1191   switch (fsPtr.p->fsState) {
1192   case FsConnectRecord::OPEN_READ_SCHEMA1:
1193     jam();
1194     openReadSchemaRef(signal, fsPtr);
1195     return;
1196   case FsConnectRecord::OPEN_READ_TAB_FILE1:
1197     jam();
1198     openReadTableRef(signal, fsPtr);
1199     return;
1200   default:
1201     break;
1202   }//switch
1203   {
1204     char msg[100];
1205     sprintf(msg, "File system open failed during FsConnectRecord state %d", (Uint32)fsPtr.p->fsState);
1206     fsRefError(signal,__LINE__,msg);
1207   }
1208 }//execFSOPENREF()
1209 
1210 /* ---------------------------------------------------------------- */
1211 // A file was successfully read.
1212 /* ---------------------------------------------------------------- */
execFSREADCONF(Signal * signal)1213 void Dbdict::execFSREADCONF(Signal* signal)
1214 {
1215   jamEntry();
1216   FsConf * const fsConf = (FsConf *)&signal->theData[0];
1217   FsConnectRecordPtr fsPtr;
1218   c_fsConnectRecordPool.getPtr(fsPtr, fsConf->userPointer);
1219   switch (fsPtr.p->fsState) {
1220   case FsConnectRecord::READ_SCHEMA1:
1221   case FsConnectRecord::READ_SCHEMA2:
1222     readSchemaConf(signal ,fsPtr);
1223     break;
1224   case FsConnectRecord::READ_TAB_FILE1:
1225     if(ERROR_INSERTED(6024))
1226     {
1227       jam();
1228       CLEAR_ERROR_INSERT_VALUE;
1229       FsRef * const fsRef = (FsRef *)&signal->theData[0];
1230       fsRef->userPointer = fsConf->userPointer;
1231       fsRef->setErrorCode(fsRef->errorCode, NDBD_EXIT_AFS_UNKNOWN);
1232       fsRef->osErrorCode = ~0; // Indicate local error
1233       execFSREADREF(signal);
1234       return;
1235     }//Testing how DICT behave if read of file 1 fails (Bug#28770)
1236   case FsConnectRecord::READ_TAB_FILE2:
1237     jam();
1238     readTableConf(signal ,fsPtr);
1239     break;
1240   default:
1241     jamLine((fsPtr.p->fsState & 0xFFF));
1242     ndbrequire(false);
1243     break;
1244   }//switch
1245 }//execFSREADCONF()
1246 
1247 /* ---------------------------------------------------------------- */
1248 // A read file was refused.
1249 /* ---------------------------------------------------------------- */
execFSREADREF(Signal * signal)1250 void Dbdict::execFSREADREF(Signal* signal)
1251 {
1252   jamEntry();
1253   FsRef * const fsRef = (FsRef *)&signal->theData[0];
1254   FsConnectRecordPtr fsPtr;
1255   c_fsConnectRecordPool.getPtr(fsPtr, fsRef->userPointer);
1256   switch (fsPtr.p->fsState) {
1257   case FsConnectRecord::READ_SCHEMA1:
1258     jam();
1259     readSchemaRef(signal, fsPtr);
1260     return;
1261   case FsConnectRecord::READ_TAB_FILE1:
1262     jam();
1263     readTableRef(signal, fsPtr);
1264     return;
1265   default:
1266     break;
1267   }//switch
1268   {
1269     char msg[100];
1270     sprintf(msg, "File system read failed during FsConnectRecord state %d", (Uint32)fsPtr.p->fsState);
1271     fsRefError(signal,__LINE__,msg);
1272   }
1273 }//execFSREADREF()
1274 
1275 /* ---------------------------------------------------------------- */
1276 // A file was successfully written.
1277 /* ---------------------------------------------------------------- */
execFSWRITECONF(Signal * signal)1278 void Dbdict::execFSWRITECONF(Signal* signal)
1279 {
1280   FsConf * const fsConf = (FsConf *)&signal->theData[0];
1281   FsConnectRecordPtr fsPtr;
1282   jamEntry();
1283   c_fsConnectRecordPool.getPtr(fsPtr, fsConf->userPointer);
1284   switch (fsPtr.p->fsState) {
1285   case FsConnectRecord::WRITE_TAB_FILE:
1286     writeTableConf(signal, fsPtr);
1287     break;
1288   case FsConnectRecord::WRITE_SCHEMA:
1289     jam();
1290     writeSchemaConf(signal, fsPtr);
1291     break;
1292   default:
1293     jamLine((fsPtr.p->fsState & 0xFFF));
1294     ndbrequire(false);
1295     break;
1296   }//switch
1297 }//execFSWRITECONF()
1298 
1299 
1300 /* ---------------------------------------------------------------- */
1301 // Routines to handle Read/Write of Table Files
1302 /* ---------------------------------------------------------------- */
1303 void
writeTableFile(Signal * signal,Uint32 tableId,SegmentedSectionPtr tabInfoPtr,Callback * callback)1304 Dbdict::writeTableFile(Signal* signal, Uint32 tableId,
1305 		       SegmentedSectionPtr tabInfoPtr, Callback* callback){
1306 
1307   ndbrequire(c_writeTableRecord.tableWriteState == WriteTableRecord::IDLE);
1308 
1309   Uint32 pages = WORDS2PAGES(tabInfoPtr.sz);
1310   c_writeTableRecord.no_of_words = tabInfoPtr.sz;
1311   c_writeTableRecord.tableWriteState = WriteTableRecord::TWR_CALLBACK;
1312   c_writeTableRecord.m_callback = * callback;
1313 
1314   c_writeTableRecord.pageId = 0;
1315   ndbrequire(pages == 1);
1316 
1317   PageRecordPtr pageRecPtr;
1318   c_pageRecordArray.getPtr(pageRecPtr, c_writeTableRecord.pageId);
1319   copy(&pageRecPtr.p->word[ZPAGE_HEADER_SIZE], tabInfoPtr);
1320 
1321   memset(&pageRecPtr.p->word[0], 0, 4 * ZPAGE_HEADER_SIZE);
1322   pageRecPtr.p->word[ZPOS_CHECKSUM] =
1323     computeChecksum(&pageRecPtr.p->word[0],
1324 		    pages * ZSIZE_OF_PAGES_IN_WORDS);
1325 
1326   startWriteTableFile(signal, tableId);
1327 }
1328 
1329 // SchemaTrans variant
1330 void
writeTableFile(Signal * signal,SchemaOpPtr op_ptr,Uint32 tableId,OpSection tabInfoSec,Callback * callback)1331 Dbdict::writeTableFile(Signal* signal, SchemaOpPtr op_ptr, Uint32 tableId,
1332                        OpSection tabInfoSec, Callback* callback)
1333 {
1334   ndbrequire(c_writeTableRecord.tableWriteState == WriteTableRecord::IDLE);
1335 
1336   {
1337     const Uint32 size = tabInfoSec.getSize();
1338     const Uint32 pages = WORDS2PAGES(size);
1339 
1340     c_writeTableRecord.no_of_words = size;
1341     c_writeTableRecord.tableWriteState = WriteTableRecord::TWR_CALLBACK;
1342     c_writeTableRecord.m_callback = * callback;
1343 
1344     c_writeTableRecord.pageId = 0;
1345 
1346     PageRecordPtr pageRecPtr;
1347     c_pageRecordArray.getPtr(pageRecPtr, c_writeTableRecord.pageId);
1348 
1349     Uint32* dst = &pageRecPtr.p->word[ZPAGE_HEADER_SIZE];
1350     Uint32 dstSize = (ZMAX_PAGES_OF_TABLE_DEFINITION * ZSIZE_OF_PAGES_IN_WORDS)
1351       - ZPAGE_HEADER_SIZE;
1352     LocalArenaPoolImpl op_sec_pool(op_ptr.p->m_trans_ptr.p->m_arena, c_opSectionBufferPool);
1353     bool ok = copyOut(op_sec_pool, tabInfoSec, dst, dstSize);
1354     ndbrequire(ok);
1355 
1356     memset(&pageRecPtr.p->word[0], 0, 4 * ZPAGE_HEADER_SIZE);
1357     pageRecPtr.p->word[ZPOS_CHECKSUM] =
1358       computeChecksum(&pageRecPtr.p->word[0],
1359                       pages * ZSIZE_OF_PAGES_IN_WORDS);
1360   }
1361 
1362   startWriteTableFile(signal, tableId);
1363 }
1364 
startWriteTableFile(Signal * signal,Uint32 tableId)1365 void Dbdict::startWriteTableFile(Signal* signal, Uint32 tableId)
1366 {
1367   FsConnectRecordPtr fsPtr;
1368   c_writeTableRecord.tableId = tableId;
1369   c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
1370   fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_TAB_FILE;
1371   openTableFile(signal, 0, fsPtr.i, tableId, true);
1372   c_writeTableRecord.noOfTableFilesHandled = 0;
1373 }//Dbdict::startWriteTableFile()
1374 
openTableFile(Signal * signal,Uint32 fileNo,Uint32 fsConPtr,Uint32 tableId,bool writeFlag)1375 void Dbdict::openTableFile(Signal* signal,
1376                            Uint32 fileNo,
1377                            Uint32 fsConPtr,
1378                            Uint32 tableId,
1379                            bool   writeFlag)
1380 {
1381   FsOpenReq * const fsOpenReq = (FsOpenReq *)&signal->theData[0];
1382 
1383   fsOpenReq->userReference = reference();
1384   fsOpenReq->userPointer = fsConPtr;
1385   if (writeFlag) {
1386     jam();
1387     fsOpenReq->fileFlags =
1388       FsOpenReq::OM_WRITEONLY |
1389       FsOpenReq::OM_TRUNCATE |
1390       FsOpenReq::OM_CREATE |
1391       FsOpenReq::OM_SYNC;
1392   } else {
1393     jam();
1394     fsOpenReq->fileFlags = FsOpenReq::OM_READONLY;
1395   }//if
1396   fsOpenReq->fileNumber[3] = 0; // Initialise before byte changes
1397   FsOpenReq::setVersion(fsOpenReq->fileNumber, 1);
1398   FsOpenReq::setSuffix(fsOpenReq->fileNumber, FsOpenReq::S_TABLELIST);
1399   FsOpenReq::v1_setDisk(fsOpenReq->fileNumber, (fileNo + 1));
1400   FsOpenReq::v1_setTable(fsOpenReq->fileNumber, tableId);
1401   FsOpenReq::v1_setFragment(fsOpenReq->fileNumber, (Uint32)-1);
1402   FsOpenReq::v1_setS(fsOpenReq->fileNumber, 0);
1403   FsOpenReq::v1_setP(fsOpenReq->fileNumber, 255);
1404 /* ---------------------------------------------------------------- */
1405 // File name : D1/DBDICT/T0/S1.TableList
1406 // D1 means Disk 1 (set by fileNo + 1)
1407 // T0 means table id = 0
1408 // S1 means tableVersion 1
1409 // TableList indicates that this is a file for a table description.
1410 /* ---------------------------------------------------------------- */
1411   sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
1412 }//openTableFile()
1413 
writeTableFile(Signal * signal,Uint32 filePtr,Uint32 fsConPtr)1414 void Dbdict::writeTableFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
1415 {
1416   FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
1417 
1418   fsRWReq->filePointer = filePtr;
1419   fsRWReq->userReference = reference();
1420   fsRWReq->userPointer = fsConPtr;
1421   fsRWReq->operationFlag = 0; // Initialise before bit changes
1422   FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 1);
1423   FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
1424                                 FsReadWriteReq::fsFormatArrayOfPages);
1425   fsRWReq->varIndex = ZBAT_TABLE_FILE;
1426   fsRWReq->numberOfPages = WORDS2PAGES(c_writeTableRecord.no_of_words);
1427   fsRWReq->data.arrayOfPages.varIndex = c_writeTableRecord.pageId;
1428   fsRWReq->data.arrayOfPages.fileOffset = 0; // Write to file page 0
1429   sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
1430 }//writeTableFile()
1431 
writeTableConf(Signal * signal,FsConnectRecordPtr fsPtr)1432 void Dbdict::writeTableConf(Signal* signal,
1433                                 FsConnectRecordPtr fsPtr)
1434 {
1435   fsPtr.p->fsState = FsConnectRecord::CLOSE_WRITE_TAB_FILE;
1436   closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
1437   return;
1438 }//Dbdict::writeTableConf()
1439 
closeWriteTableConf(Signal * signal,FsConnectRecordPtr fsPtr)1440 void Dbdict::closeWriteTableConf(Signal* signal,
1441                                  FsConnectRecordPtr fsPtr)
1442 {
1443   c_writeTableRecord.noOfTableFilesHandled++;
1444   if (c_writeTableRecord.noOfTableFilesHandled < 2) {
1445     jam();
1446     fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_TAB_FILE;
1447     openTableFile(signal, 1, fsPtr.i, c_writeTableRecord.tableId, true);
1448     return;
1449   }
1450   ndbrequire(c_writeTableRecord.noOfTableFilesHandled == 2);
1451   c_fsConnectRecordPool.release(fsPtr);
1452   WriteTableRecord::TableWriteState state = c_writeTableRecord.tableWriteState;
1453   c_writeTableRecord.tableWriteState = WriteTableRecord::IDLE;
1454   switch (state) {
1455   case WriteTableRecord::IDLE:
1456   case WriteTableRecord::WRITE_ADD_TABLE_MASTER :
1457   case WriteTableRecord::WRITE_ADD_TABLE_SLAVE :
1458   case WriteTableRecord::WRITE_RESTART_FROM_MASTER :
1459   case WriteTableRecord::WRITE_RESTART_FROM_OWN :
1460     ndbrequire(false);
1461     break;
1462   case WriteTableRecord::TWR_CALLBACK:
1463     jam();
1464     execute(signal, c_writeTableRecord.m_callback, 0);
1465     return;
1466   }
1467   ndbrequire(false);
1468 }//Dbdict::closeWriteTableConf()
1469 
startReadTableFile(Signal * signal,Uint32 tableId)1470 void Dbdict::startReadTableFile(Signal* signal, Uint32 tableId)
1471 {
1472   //globalSignalLoggers.log(number(), "startReadTableFile");
1473   ndbrequire(!c_readTableRecord.inUse);
1474 
1475   FsConnectRecordPtr fsPtr;
1476   c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
1477   c_readTableRecord.inUse = true;
1478   c_readTableRecord.tableId = tableId;
1479   fsPtr.p->fsState = FsConnectRecord::OPEN_READ_TAB_FILE1;
1480   openTableFile(signal, 0, fsPtr.i, tableId, false);
1481 }//Dbdict::startReadTableFile()
1482 
openReadTableRef(Signal * signal,FsConnectRecordPtr fsPtr)1483 void Dbdict::openReadTableRef(Signal* signal,
1484                               FsConnectRecordPtr fsPtr)
1485 {
1486   fsPtr.p->fsState = FsConnectRecord::OPEN_READ_TAB_FILE2;
1487   openTableFile(signal, 1, fsPtr.i, c_readTableRecord.tableId, false);
1488   return;
1489 }//Dbdict::openReadTableConf()
1490 
readTableFile(Signal * signal,Uint32 filePtr,Uint32 fsConPtr)1491 void Dbdict::readTableFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
1492 {
1493   FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
1494 
1495   fsRWReq->filePointer = filePtr;
1496   fsRWReq->userReference = reference();
1497   fsRWReq->userPointer = fsConPtr;
1498   fsRWReq->operationFlag = 0; // Initialise before bit changes
1499   FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 0);
1500   FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
1501                                 FsReadWriteReq::fsFormatArrayOfPages);
1502   fsRWReq->varIndex = ZBAT_TABLE_FILE;
1503   fsRWReq->numberOfPages = WORDS2PAGES(c_readTableRecord.no_of_words);
1504   fsRWReq->data.arrayOfPages.varIndex = c_readTableRecord.pageId;
1505   fsRWReq->data.arrayOfPages.fileOffset = 0; // Write to file page 0
1506   sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 8, JBA);
1507 }//readTableFile()
1508 
readTableConf(Signal * signal,FsConnectRecordPtr fsPtr)1509 void Dbdict::readTableConf(Signal* signal,
1510 			   FsConnectRecordPtr fsPtr)
1511 {
1512   /* ---------------------------------------------------------------- */
1513   // Verify the data read from disk
1514   /* ---------------------------------------------------------------- */
1515   bool crashInd;
1516   if (fsPtr.p->fsState == FsConnectRecord::READ_TAB_FILE1) {
1517     jam();
1518     crashInd = false;
1519   } else {
1520     jam();
1521     crashInd = true;
1522   }//if
1523 
1524   PageRecordPtr tmpPagePtr;
1525   c_pageRecordArray.getPtr(tmpPagePtr, c_readTableRecord.pageId);
1526   Uint32 sz =
1527     WORDS2PAGES(c_readTableRecord.no_of_words)*ZSIZE_OF_PAGES_IN_WORDS;
1528   Uint32 chk = computeChecksum((const Uint32*)tmpPagePtr.p, sz);
1529 
1530   ndbrequire((chk == 0) || !crashInd);
1531   if(chk != 0){
1532     jam();
1533     ndbrequire(fsPtr.p->fsState == FsConnectRecord::READ_TAB_FILE1);
1534     readTableRef(signal, fsPtr);
1535     return;
1536   }//if
1537 
1538   fsPtr.p->fsState = FsConnectRecord::CLOSE_READ_TAB_FILE;
1539   closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
1540   return;
1541 }//Dbdict::readTableConf()
1542 
readTableRef(Signal * signal,FsConnectRecordPtr fsPtr)1543 void Dbdict::readTableRef(Signal* signal,
1544                           FsConnectRecordPtr fsPtr)
1545 {
1546   /**
1547    * First close corrupt file
1548    */
1549   fsPtr.p->fsState = FsConnectRecord::OPEN_READ_TAB_FILE2;
1550   closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
1551   return;
1552 }//Dbdict::readTableRef()
1553 
closeReadTableConf(Signal * signal,FsConnectRecordPtr fsPtr)1554 void Dbdict::closeReadTableConf(Signal* signal,
1555                                 FsConnectRecordPtr fsPtr)
1556 {
1557   c_fsConnectRecordPool.release(fsPtr);
1558   c_readTableRecord.inUse = false;
1559 
1560   execute(signal, c_readTableRecord.m_callback, 0);
1561   return;
1562 }//Dbdict::closeReadTableConf()
1563 
1564 /* ---------------------------------------------------------------- */
1565 // Routines to handle Read/Write of Schema Files
1566 /* ---------------------------------------------------------------- */
1567 NdbOut& operator<<(NdbOut& out, const SchemaFile::TableEntry entry);
1568 
1569 void
updateSchemaState(Signal * signal,Uint32 tableId,SchemaFile::TableEntry * te,Callback * callback,bool savetodisk,bool dicttrans)1570 Dbdict::updateSchemaState(Signal* signal, Uint32 tableId,
1571 			  SchemaFile::TableEntry* te, Callback* callback,
1572                           bool savetodisk, bool dicttrans)
1573 {
1574   jam();
1575   XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
1576   SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, tableId);
1577 
1578   if (!dicttrans) {
1579     /*
1580      * Old code may not zero transId, leaving the entry not visible
1581      * to tabinfo request (old code may also skip updateSchemaState).
1582    */
1583     te->m_transId = 0;
1584   }
1585 
1586   D("updateSchemaState" << V(tableId));
1587   D("old:" << *tableEntry);
1588   D("new:" << *te);
1589 
1590 #ifndef TODO
1591   * tableEntry = * te;
1592   computeChecksum(xsf, tableId / NDB_SF_PAGE_ENTRIES);
1593 #else
1594   SchemaFile::TableState newState =
1595     (SchemaFile::TableState)te->m_tableState;
1596   SchemaFile::TableState oldState =
1597     (SchemaFile::TableState)tableEntry->m_tableState;
1598 
1599   Uint32 newVersion = te->m_tableVersion;
1600   Uint32 oldVersion = tableEntry->m_tableVersion;
1601 
1602   bool ok = false;
1603   switch (newState){
1604   case SchemaFile::CREATE_PARSED:
1605     jam();
1606     ok = true;
1607     ndbrequire(create_obj_inc_schema_version(oldVersion) == newVersion);
1608     ndbrequire(oldState == SchemaFile::INIT ||
1609                oldState == SchemaFile::DROP_TABLE_COMMITTED);
1610     break;
1611   case SchemaFile::DROP_PARSED:
1612     ok = true;
1613     break;
1614   case SchemaFile::ALTER_PARSED:
1615     // wl3600_todo
1616     ok = true;
1617     break;
1618   case SchemaFile::ADD_STARTED:
1619     jam();
1620     ok = true;
1621     if (dicttrans) {
1622       ndbrequire(oldVersion == newVersion);
1623       ndbrequire(oldState == SchemaFile::CREATE_PARSED);
1624       break;
1625     }
1626     ndbrequire(create_obj_inc_schema_version(oldVersion) == newVersion);
1627     ndbrequire(oldState == SchemaFile::INIT ||
1628 	       oldState == SchemaFile::DROP_TABLE_COMMITTED);
1629     break;
1630   case SchemaFile::TABLE_ADD_COMMITTED:
1631     jam();
1632     ok = true;
1633     ndbrequire(newVersion == oldVersion);
1634     ndbrequire(oldState == SchemaFile::ADD_STARTED ||
1635 	       oldState == SchemaFile::DROP_TABLE_STARTED);
1636     break;
1637   case SchemaFile::ALTER_TABLE_COMMITTED:
1638     jam();
1639     ok = true;
1640     ndbrequire(alter_obj_inc_schema_version(oldVersion) == newVersion);
1641     ndbrequire(oldState == SchemaFile::TABLE_ADD_COMMITTED ||
1642 	       oldState == SchemaFile::ALTER_TABLE_COMMITTED);
1643     break;
1644   case SchemaFile::DROP_TABLE_STARTED:
1645     jam();
1646   case SchemaFile::DROP_TABLE_COMMITTED:
1647     jam();
1648     ok = true;
1649     break;
1650   case SchemaFile::TEMPORARY_TABLE_COMMITTED:
1651     jam();
1652     ndbrequire(oldState == SchemaFile::ADD_STARTED ||
1653                oldState == SchemaFile::TEMPORARY_TABLE_COMMITTED);
1654     ok = true;
1655     break;
1656   case SchemaFile::INIT:
1657     jam();
1658     ok = true;
1659     if (dicttrans) {
1660       ndbrequire((oldState == SchemaFile::CREATE_PARSED));
1661       break;
1662     }
1663     ndbrequire((oldState == SchemaFile::ADD_STARTED));
1664   }//if
1665   ndbrequire(ok);
1666 
1667   * tableEntry = * te;
1668   computeChecksum(xsf, tableId / NDB_SF_PAGE_ENTRIES);
1669 
1670   if (savetodisk)
1671   {
1672     ndbrequire(c_writeSchemaRecord.inUse == false);
1673     c_writeSchemaRecord.inUse = true;
1674 
1675     c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
1676     c_writeSchemaRecord.newFile = false;
1677     c_writeSchemaRecord.firstPage = tableId / NDB_SF_PAGE_ENTRIES;
1678     c_writeSchemaRecord.noOfPages = 1;
1679     c_writeSchemaRecord.m_callback = * callback;
1680 
1681     startWriteSchemaFile(signal);
1682   }
1683   else
1684   {
1685     jam();
1686     if (callback != 0) {
1687       jam();
1688       execute(signal, *callback, 0);
1689     }
1690   }
1691 #endif
1692 }
1693 
startWriteSchemaFile(Signal * signal)1694 void Dbdict::startWriteSchemaFile(Signal* signal)
1695 {
1696   FsConnectRecordPtr fsPtr;
1697   c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
1698   fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_SCHEMA;
1699   openSchemaFile(signal, 0, fsPtr.i, true, c_writeSchemaRecord.newFile);
1700   c_writeSchemaRecord.noOfSchemaFilesHandled = 0;
1701 }//Dbdict::startWriteSchemaFile()
1702 
openSchemaFile(Signal * signal,Uint32 fileNo,Uint32 fsConPtr,bool writeFlag,bool newFile)1703 void Dbdict::openSchemaFile(Signal* signal,
1704                             Uint32 fileNo,
1705                             Uint32 fsConPtr,
1706                             bool writeFlag,
1707                             bool newFile)
1708 {
1709   FsOpenReq * const fsOpenReq = (FsOpenReq *)&signal->theData[0];
1710   fsOpenReq->userReference = reference();
1711   fsOpenReq->userPointer = fsConPtr;
1712   if (writeFlag) {
1713     jam();
1714     fsOpenReq->fileFlags =
1715       FsOpenReq::OM_WRITEONLY |
1716       FsOpenReq::OM_SYNC;
1717     if (newFile)
1718       fsOpenReq->fileFlags |=
1719         FsOpenReq::OM_TRUNCATE |
1720         FsOpenReq::OM_CREATE;
1721   } else {
1722     jam();
1723     fsOpenReq->fileFlags = FsOpenReq::OM_READONLY;
1724   }//if
1725   fsOpenReq->fileNumber[3] = 0; // Initialise before byte changes
1726   FsOpenReq::setVersion(fsOpenReq->fileNumber, 1);
1727   FsOpenReq::setSuffix(fsOpenReq->fileNumber, FsOpenReq::S_SCHEMALOG);
1728   FsOpenReq::v1_setDisk(fsOpenReq->fileNumber, (fileNo + 1));
1729   FsOpenReq::v1_setTable(fsOpenReq->fileNumber, (Uint32)-1);
1730   FsOpenReq::v1_setFragment(fsOpenReq->fileNumber, (Uint32)-1);
1731   FsOpenReq::v1_setS(fsOpenReq->fileNumber, (Uint32)-1);
1732   FsOpenReq::v1_setP(fsOpenReq->fileNumber, 0);
1733 /* ---------------------------------------------------------------- */
1734 // File name : D1/DBDICT/P0.SchemaLog
1735 // D1 means Disk 1 (set by fileNo + 1). Writes to both D1 and D2
1736 // SchemaLog indicates that this is a file giving a list of current tables.
1737 /* ---------------------------------------------------------------- */
1738   sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
1739 }//openSchemaFile()
1740 
writeSchemaFile(Signal * signal,Uint32 filePtr,Uint32 fsConPtr)1741 void Dbdict::writeSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
1742 {
1743   FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
1744 
1745   // check write record
1746   WriteSchemaRecord & wr = c_writeSchemaRecord;
1747   ndbrequire(wr.pageId == (wr.pageId != 0) * NDB_SF_MAX_PAGES);
1748   ndbrequire(wr.noOfPages != 0);
1749   ndbrequire(wr.firstPage + wr.noOfPages <= NDB_SF_MAX_PAGES);
1750 
1751   fsRWReq->filePointer = filePtr;
1752   fsRWReq->userReference = reference();
1753   fsRWReq->userPointer = fsConPtr;
1754   fsRWReq->operationFlag = 0; // Initialise before bit changes
1755   FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 1);
1756   FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
1757                                 FsReadWriteReq::fsFormatArrayOfPages);
1758   fsRWReq->varIndex = ZBAT_SCHEMA_FILE;
1759   fsRWReq->numberOfPages = wr.noOfPages;
1760   // Write from memory page
1761   fsRWReq->data.arrayOfPages.varIndex = wr.pageId + wr.firstPage;
1762   fsRWReq->data.arrayOfPages.fileOffset = wr.firstPage;
1763   sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
1764 }//writeSchemaFile()
1765 
writeSchemaConf(Signal * signal,FsConnectRecordPtr fsPtr)1766 void Dbdict::writeSchemaConf(Signal* signal,
1767                                 FsConnectRecordPtr fsPtr)
1768 {
1769   fsPtr.p->fsState = FsConnectRecord::CLOSE_WRITE_SCHEMA;
1770   closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
1771   return;
1772 }//Dbdict::writeSchemaConf()
1773 
closeFile(Signal * signal,Uint32 filePtr,Uint32 fsConPtr)1774 void Dbdict::closeFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
1775 {
1776   FsCloseReq * const fsCloseReq = (FsCloseReq *)&signal->theData[0];
1777   fsCloseReq->filePointer = filePtr;
1778   fsCloseReq->userReference = reference();
1779   fsCloseReq->userPointer = fsConPtr;
1780   FsCloseReq::setRemoveFileFlag(fsCloseReq->fileFlag, false);
1781   sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, FsCloseReq::SignalLength, JBA);
1782   return;
1783 }//closeFile()
1784 
closeWriteSchemaConf(Signal * signal,FsConnectRecordPtr fsPtr)1785 void Dbdict::closeWriteSchemaConf(Signal* signal,
1786                                      FsConnectRecordPtr fsPtr)
1787 {
1788   c_writeSchemaRecord.noOfSchemaFilesHandled++;
1789   if (c_writeSchemaRecord.noOfSchemaFilesHandled < 2) {
1790     jam();
1791     fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_SCHEMA;
1792     openSchemaFile(signal, 1, fsPtr.i, true, c_writeSchemaRecord.newFile);
1793     return;
1794   }
1795   ndbrequire(c_writeSchemaRecord.noOfSchemaFilesHandled == 2);
1796 
1797   c_fsConnectRecordPool.release(fsPtr);
1798 
1799   c_writeSchemaRecord.inUse = false;
1800   execute(signal, c_writeSchemaRecord.m_callback, 0);
1801   return;
1802 }//Dbdict::closeWriteSchemaConf()
1803 
startReadSchemaFile(Signal * signal)1804 void Dbdict::startReadSchemaFile(Signal* signal)
1805 {
1806   //globalSignalLoggers.log(number(), "startReadSchemaFile");
1807   FsConnectRecordPtr fsPtr;
1808   c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
1809   fsPtr.p->fsState = FsConnectRecord::OPEN_READ_SCHEMA1;
1810   openSchemaFile(signal, 0, fsPtr.i, false, false);
1811 }//Dbdict::startReadSchemaFile()
1812 
openReadSchemaRef(Signal * signal,FsConnectRecordPtr fsPtr)1813 void Dbdict::openReadSchemaRef(Signal* signal,
1814                                FsConnectRecordPtr fsPtr)
1815 {
1816   fsPtr.p->fsState = FsConnectRecord::OPEN_READ_SCHEMA2;
1817   openSchemaFile(signal, 1, fsPtr.i, false, false);
1818 }//Dbdict::openReadSchemaRef()
1819 
readSchemaFile(Signal * signal,Uint32 filePtr,Uint32 fsConPtr)1820 void Dbdict::readSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
1821 {
1822   FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
1823 
1824   // check read record
1825   ReadSchemaRecord & rr = c_readSchemaRecord;
1826   ndbrequire(rr.pageId == (rr.pageId != 0) * NDB_SF_MAX_PAGES);
1827   ndbrequire(rr.noOfPages != 0);
1828   ndbrequire(rr.firstPage + rr.noOfPages <= NDB_SF_MAX_PAGES);
1829 
1830   fsRWReq->filePointer = filePtr;
1831   fsRWReq->userReference = reference();
1832   fsRWReq->userPointer = fsConPtr;
1833   fsRWReq->operationFlag = 0; // Initialise before bit changes
1834   FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 0);
1835   FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
1836                                 FsReadWriteReq::fsFormatArrayOfPages);
1837   fsRWReq->varIndex = ZBAT_SCHEMA_FILE;
1838   fsRWReq->numberOfPages = rr.noOfPages;
1839   fsRWReq->data.arrayOfPages.varIndex = rr.pageId + rr.firstPage;
1840   fsRWReq->data.arrayOfPages.fileOffset = rr.firstPage;
1841   sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 8, JBA);
1842 }//readSchemaFile()
1843 
readSchemaConf(Signal * signal,FsConnectRecordPtr fsPtr)1844 void Dbdict::readSchemaConf(Signal* signal,
1845                             FsConnectRecordPtr fsPtr)
1846 {
1847 /* ---------------------------------------------------------------- */
1848 // Verify the data read from disk
1849 /* ---------------------------------------------------------------- */
1850   bool crashInd;
1851   if (fsPtr.p->fsState == FsConnectRecord::READ_SCHEMA1) {
1852     jam();
1853     crashInd = false;
1854   } else {
1855     jam();
1856     crashInd = true;
1857   }//if
1858 
1859   ReadSchemaRecord & rr = c_readSchemaRecord;
1860   XSchemaFile * xsf = &c_schemaFile[rr.pageId != 0];
1861 
1862   if (rr.schemaReadState == ReadSchemaRecord::INITIAL_READ_HEAD) {
1863     jam();
1864     ndbrequire(rr.firstPage == 0);
1865     SchemaFile * sf = &xsf->schemaPage[0];
1866     Uint32 noOfPages;
1867     if (sf->NdbVersion < NDB_SF_VERSION_5_0_6) {
1868       jam();
1869       const Uint32 pageSize_old = 32 * 1024;
1870       noOfPages = pageSize_old / NDB_SF_PAGE_SIZE - 1;
1871     } else {
1872       noOfPages = sf->FileSize / NDB_SF_PAGE_SIZE - 1;
1873     }
1874     rr.schemaReadState = ReadSchemaRecord::INITIAL_READ;
1875     if (noOfPages != 0) {
1876       rr.firstPage = 1;
1877       rr.noOfPages = noOfPages;
1878       readSchemaFile(signal, fsPtr.p->filePtr, fsPtr.i);
1879       return;
1880     }
1881   }
1882 
1883   SchemaFile * sf0 = &xsf->schemaPage[0];
1884   xsf->noOfPages = sf0->FileSize / NDB_SF_PAGE_SIZE;
1885 
1886   if (sf0->NdbVersion < NDB_SF_VERSION_5_0_6 &&
1887       ! convertSchemaFileTo_5_0_6(xsf)) {
1888     jam();
1889     ndbrequire(! crashInd);
1890     ndbrequire(fsPtr.p->fsState == FsConnectRecord::READ_SCHEMA1);
1891     readSchemaRef(signal, fsPtr);
1892     return;
1893   }
1894 
1895   if (sf0->NdbVersion < NDB_MAKE_VERSION(6,4,0) &&
1896       ! convertSchemaFileTo_6_4(xsf))
1897   {
1898     jam();
1899     ndbrequire(! crashInd);
1900     ndbrequire(fsPtr.p->fsState == FsConnectRecord::READ_SCHEMA1);
1901     readSchemaRef(signal, fsPtr);
1902     return;
1903   }
1904 
1905 
1906   for (Uint32 n = 0; n < xsf->noOfPages; n++) {
1907     SchemaFile * sf = &xsf->schemaPage[n];
1908     bool ok = false;
1909     const char *reason;
1910     if (memcmp(sf->Magic, NDB_SF_MAGIC, sizeof(sf->Magic)) != 0)
1911     { jam(); reason = "magic code"; }
1912     else if (sf->FileSize == 0)
1913     { jam(); reason = "file size == 0"; }
1914     else if (sf->FileSize % NDB_SF_PAGE_SIZE != 0)
1915     { jam(); reason = "invalid size multiple"; }
1916     else if (sf->FileSize != sf0->FileSize)
1917     { jam(); reason = "invalid size"; }
1918     else if (sf->PageNumber != n)
1919     { jam(); reason = "invalid page number"; }
1920     else if (computeChecksum((Uint32*)sf, NDB_SF_PAGE_SIZE_IN_WORDS) != 0)
1921     { jam(); reason = "invalid checksum"; }
1922     else
1923       ok = true;
1924 
1925     if (!ok)
1926     {
1927       char reason_msg[128];
1928       BaseString::snprintf(reason_msg, sizeof(reason_msg),
1929                "schema file corrupt, page %u (%s, "
1930                "sz=%u sz0=%u pn=%u)",
1931                n, reason, sf->FileSize, sf0->FileSize, sf->PageNumber);
1932       if (crashInd)
1933         progError(__LINE__, NDBD_EXIT_SR_SCHEMAFILE, reason_msg);
1934       ndbrequireErr(fsPtr.p->fsState == FsConnectRecord::READ_SCHEMA1,
1935                     NDBD_EXIT_SR_SCHEMAFILE);
1936       jam();
1937       infoEvent("primary %s, trying backup", reason_msg);
1938       readSchemaRef(signal, fsPtr);
1939       return;
1940     }
1941   }
1942 
1943   fsPtr.p->fsState = FsConnectRecord::CLOSE_READ_SCHEMA;
1944   closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
1945   return;
1946 }//Dbdict::readSchemaConf()
1947 
readSchemaRef(Signal * signal,FsConnectRecordPtr fsPtr)1948 void Dbdict::readSchemaRef(Signal* signal,
1949                            FsConnectRecordPtr fsPtr)
1950 {
1951   /**
1952    * First close corrupt file
1953    */
1954   fsPtr.p->fsState = FsConnectRecord::OPEN_READ_SCHEMA2;
1955   closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
1956   return;
1957 }
1958 
closeReadSchemaConf(Signal * signal,FsConnectRecordPtr fsPtr)1959 void Dbdict::closeReadSchemaConf(Signal* signal,
1960                                  FsConnectRecordPtr fsPtr)
1961 {
1962   c_fsConnectRecordPool.release(fsPtr);
1963   ReadSchemaRecord::SchemaReadState state = c_readSchemaRecord.schemaReadState;
1964   c_readSchemaRecord.schemaReadState = ReadSchemaRecord::IDLE;
1965 
1966   switch(state) {
1967   case ReadSchemaRecord::INITIAL_READ :
1968     jam();
1969     {
1970       // write back both copies
1971 
1972       ndbrequire(c_writeSchemaRecord.inUse == false);
1973       XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0 ];
1974       Uint32 noOfPages =
1975         (c_noOfMetaTables + NDB_SF_PAGE_ENTRIES - 1) /
1976         NDB_SF_PAGE_ENTRIES;
1977       resizeSchemaFile(xsf, noOfPages);
1978 
1979       if (c_at_restart_skip_indexes || c_at_restart_skip_fks)
1980       {
1981         jam();
1982         modifySchemaFileAtRestart(xsf);
1983       }
1984 
1985       c_writeSchemaRecord.inUse = true;
1986       c_writeSchemaRecord.pageId = c_schemaRecord.oldSchemaPage;
1987       c_writeSchemaRecord.newFile = true;
1988       c_writeSchemaRecord.firstPage = 0;
1989       c_writeSchemaRecord.noOfPages = xsf->noOfPages;
1990 
1991       c_writeSchemaRecord.m_callback.m_callbackFunction =
1992         safe_cast(&Dbdict::initSchemaFile_conf);
1993 
1994       startWriteSchemaFile(signal);
1995     }
1996     break;
1997 
1998   default :
1999     ndbrequire(false);
2000     break;
2001 
2002   }//switch
2003 }//Dbdict::closeReadSchemaConf()
2004 
2005 bool
convertSchemaFileTo_5_0_6(XSchemaFile * xsf)2006 Dbdict::convertSchemaFileTo_5_0_6(XSchemaFile * xsf)
2007 {
2008   const Uint32 pageSize_old = 32 * 1024;
2009   union {
2010     Uint32 page_old[pageSize_old >> 2];
2011     SchemaFile _SchemaFile;
2012   };
2013   (void)_SchemaFile;
2014   SchemaFile * sf_old = (SchemaFile *)page_old;
2015 
2016   if (xsf->noOfPages * NDB_SF_PAGE_SIZE != pageSize_old)
2017     return false;
2018   SchemaFile * sf0 = &xsf->schemaPage[0];
2019   memcpy(sf_old, sf0, pageSize_old);
2020 
2021   // init max number new pages needed
2022   xsf->noOfPages = (sf_old->NoOfTableEntries + NDB_SF_PAGE_ENTRIES - 1) /
2023                    NDB_SF_PAGE_ENTRIES;
2024   initSchemaFile(xsf, 0, xsf->noOfPages, true);
2025 
2026   Uint32 noOfPages = 1;
2027   Uint32 n, i, j;
2028   for (n = 0; n < xsf->noOfPages; n++) {
2029     jam();
2030     for (i = 0; i < NDB_SF_PAGE_ENTRIES; i++) {
2031       j = n * NDB_SF_PAGE_ENTRIES + i;
2032       if (j >= sf_old->NoOfTableEntries)
2033         continue;
2034       const SchemaFile::TableEntry_old & te_old = sf_old->TableEntries_old[j];
2035       if (te_old.m_tableState == SchemaFile::SF_UNUSED ||
2036           te_old.m_noOfPages == 0)
2037         continue;
2038       SchemaFile * sf = &xsf->schemaPage[n];
2039       SchemaFile::TableEntry & te = sf->TableEntries[i];
2040       te.m_tableState = te_old.m_tableState;
2041       te.m_tableVersion = te_old.m_tableVersion;
2042       te.m_tableType = te_old.m_tableType;
2043       te.m_info_words = te_old.m_noOfPages * ZSIZE_OF_PAGES_IN_WORDS -
2044                         ZPAGE_HEADER_SIZE;
2045       te.m_gcp = te_old.m_gcp;
2046       if (noOfPages < n)
2047         noOfPages = n;
2048     }
2049   }
2050   xsf->noOfPages = noOfPages;
2051   initSchemaFile(xsf, 0, xsf->noOfPages, false);
2052 
2053   return true;
2054 }
2055 
2056 bool
convertSchemaFileTo_6_4(XSchemaFile * xsf)2057 Dbdict::convertSchemaFileTo_6_4(XSchemaFile * xsf)
2058 {
2059   for (Uint32 i = 0; i < xsf->noOfPages; i++)
2060   {
2061     xsf->schemaPage[i].NdbVersion = NDB_VERSION_D;
2062     for (Uint32 j = 0; j < NDB_SF_PAGE_ENTRIES; j++)
2063     {
2064       Uint32 n = i * NDB_SF_PAGE_ENTRIES + j;
2065       SchemaFile::TableEntry * transEntry = getTableEntry(xsf, n);
2066 
2067       switch(SchemaFile::Old::TableState(transEntry->m_tableState)) {
2068       case SchemaFile::Old::INIT:
2069         transEntry->m_tableState = SchemaFile::SF_UNUSED;
2070         break;
2071       case SchemaFile::Old::ADD_STARTED:
2072         transEntry->m_tableState = SchemaFile::SF_UNUSED;
2073         break;
2074       case SchemaFile::Old::TABLE_ADD_COMMITTED:
2075         transEntry->m_tableState = SchemaFile::SF_IN_USE;
2076         break;
2077       case SchemaFile::Old::DROP_TABLE_STARTED:
2078         transEntry->m_tableState = SchemaFile::SF_UNUSED;
2079         break;
2080       case SchemaFile::Old::DROP_TABLE_COMMITTED:
2081         transEntry->m_tableState = SchemaFile::SF_UNUSED;
2082         break;
2083       case SchemaFile::Old::ALTER_TABLE_COMMITTED:
2084         transEntry->m_tableState = SchemaFile::SF_IN_USE;
2085         break;
2086       case SchemaFile::Old::TEMPORARY_TABLE_COMMITTED:
2087         transEntry->m_tableState = SchemaFile::SF_IN_USE;
2088         break;
2089       default:
2090         transEntry->m_tableState = SchemaFile::SF_UNUSED;
2091         break;
2092       }
2093     }
2094     computeChecksum(xsf, i);
2095   }
2096   return true;
2097 }
2098 
2099 /* **************************************************************** */
2100 /* ---------------------------------------------------------------- */
2101 /* MODULE:          INITIALISATION MODULE ------------------------- */
2102 /* ---------------------------------------------------------------- */
2103 /*                                                                  */
2104 /* This module contains initialisation of data at start/restart.    */
2105 /* ---------------------------------------------------------------- */
2106 /* **************************************************************** */
2107 
Dbdict(Block_context & ctx)2108 Dbdict::Dbdict(Block_context& ctx):
2109   SimulatedBlock(DBDICT, ctx),
2110   c_attributeRecordHash(c_attributeRecordPool),
2111   c_obj_name_hash(c_obj_pool),
2112   c_obj_id_hash(c_obj_pool),
2113   c_gettabinforeq_q(*this),
2114   c_schemaOpHash(c_schemaOpPool),
2115   c_schemaTransHash(c_schemaTransPool),
2116   c_schemaTransList(c_schemaTransPool),
2117   c_schemaTransCount(0),
2118   c_txHandleHash(c_txHandlePool),
2119   c_opCreateEvent(c_opRecordPool),
2120   c_opSubEvent(c_opRecordPool),
2121   c_opDropEvent(c_opRecordPool),
2122   c_opSignalUtil(c_opRecordPool),
2123   c_opRecordSequence(0),
2124   c_restart_enable_fks(false),
2125   c_at_restart_skip_indexes(0),
2126   c_at_restart_skip_fks(0)
2127 {
2128   BLOCK_CONSTRUCTOR(Dbdict);
2129 
2130   // Transit signals
2131   addRecSignal(GSN_DUMP_STATE_ORD, &Dbdict::execDUMP_STATE_ORD);
2132   addRecSignal(GSN_GET_TABINFOREQ, &Dbdict::execGET_TABINFOREQ);
2133   addRecSignal(GSN_GET_TABLEID_REQ, &Dbdict::execGET_TABLEDID_REQ);
2134   addRecSignal(GSN_GET_TABINFOREF, &Dbdict::execGET_TABINFOREF);
2135   addRecSignal(GSN_GET_TABINFO_CONF, &Dbdict::execGET_TABINFO_CONF);
2136   addRecSignal(GSN_CONTINUEB, &Dbdict::execCONTINUEB);
2137 
2138   addRecSignal(GSN_DBINFO_SCANREQ, &Dbdict::execDBINFO_SCANREQ);
2139 
2140   addRecSignal(GSN_CREATE_TABLE_REQ, &Dbdict::execCREATE_TABLE_REQ);
2141   addRecSignal(GSN_CREATE_TAB_REQ, &Dbdict::execCREATE_TAB_REQ);
2142   addRecSignal(GSN_CREATE_TAB_REF, &Dbdict::execCREATE_TAB_REF);
2143   addRecSignal(GSN_CREATE_TAB_CONF, &Dbdict::execCREATE_TAB_CONF);
2144   addRecSignal(GSN_CREATE_FRAGMENTATION_REQ, &Dbdict::execCREATE_FRAGMENTATION_REQ);
2145   addRecSignal(GSN_CREATE_FRAGMENTATION_REF, &Dbdict::execCREATE_FRAGMENTATION_REF);
2146   addRecSignal(GSN_CREATE_FRAGMENTATION_CONF, &Dbdict::execCREATE_FRAGMENTATION_CONF);
2147   addRecSignal(GSN_DIADDTABCONF, &Dbdict::execDIADDTABCONF);
2148   addRecSignal(GSN_DIADDTABREF, &Dbdict::execDIADDTABREF);
2149   addRecSignal(GSN_ADD_FRAGREQ, &Dbdict::execADD_FRAGREQ);
2150   addRecSignal(GSN_TAB_COMMITCONF, &Dbdict::execTAB_COMMITCONF);
2151   addRecSignal(GSN_TAB_COMMITREF, &Dbdict::execTAB_COMMITREF);
2152   addRecSignal(GSN_ALTER_TABLE_REQ, &Dbdict::execALTER_TABLE_REQ);
2153   addRecSignal(GSN_ALTER_TAB_REF, &Dbdict::execALTER_TAB_REF);
2154   addRecSignal(GSN_ALTER_TAB_CONF, &Dbdict::execALTER_TAB_CONF);
2155   addRecSignal(GSN_ALTER_TABLE_REF, &Dbdict::execALTER_TABLE_REF);
2156   addRecSignal(GSN_ALTER_TABLE_CONF, &Dbdict::execALTER_TABLE_CONF);
2157 
2158   // Index signals
2159   addRecSignal(GSN_CREATE_INDX_REQ, &Dbdict::execCREATE_INDX_REQ);
2160   addRecSignal(GSN_CREATE_INDX_IMPL_CONF, &Dbdict::execCREATE_INDX_IMPL_CONF);
2161   addRecSignal(GSN_CREATE_INDX_IMPL_REF, &Dbdict::execCREATE_INDX_IMPL_REF);
2162 
2163   addRecSignal(GSN_ALTER_INDX_REQ, &Dbdict::execALTER_INDX_REQ);
2164   addRecSignal(GSN_ALTER_INDX_CONF, &Dbdict::execALTER_INDX_CONF);
2165   addRecSignal(GSN_ALTER_INDX_REF, &Dbdict::execALTER_INDX_REF);
2166   addRecSignal(GSN_ALTER_INDX_IMPL_CONF, &Dbdict::execALTER_INDX_IMPL_CONF);
2167   addRecSignal(GSN_ALTER_INDX_IMPL_REF, &Dbdict::execALTER_INDX_IMPL_REF);
2168 
2169   addRecSignal(GSN_CREATE_TABLE_CONF, &Dbdict::execCREATE_TABLE_CONF);
2170   addRecSignal(GSN_CREATE_TABLE_REF, &Dbdict::execCREATE_TABLE_REF);
2171 
2172   addRecSignal(GSN_DROP_INDX_REQ, &Dbdict::execDROP_INDX_REQ);
2173   addRecSignal(GSN_DROP_INDX_IMPL_CONF, &Dbdict::execDROP_INDX_IMPL_CONF);
2174   addRecSignal(GSN_DROP_INDX_IMPL_REF, &Dbdict::execDROP_INDX_IMPL_REF);
2175 
2176   addRecSignal(GSN_DROP_TABLE_CONF, &Dbdict::execDROP_TABLE_CONF);
2177   addRecSignal(GSN_DROP_TABLE_REF, &Dbdict::execDROP_TABLE_REF);
2178 
2179   addRecSignal(GSN_BUILDINDXREQ, &Dbdict::execBUILDINDXREQ);
2180   addRecSignal(GSN_BUILDINDXCONF, &Dbdict::execBUILDINDXCONF);
2181   addRecSignal(GSN_BUILDINDXREF, &Dbdict::execBUILDINDXREF);
2182   addRecSignal(GSN_BUILD_INDX_IMPL_CONF, &Dbdict::execBUILD_INDX_IMPL_CONF);
2183   addRecSignal(GSN_BUILD_INDX_IMPL_REF, &Dbdict::execBUILD_INDX_IMPL_REF);
2184 
2185   // Util signals
2186   addRecSignal(GSN_UTIL_PREPARE_CONF, &Dbdict::execUTIL_PREPARE_CONF);
2187   addRecSignal(GSN_UTIL_PREPARE_REF,  &Dbdict::execUTIL_PREPARE_REF);
2188 
2189   addRecSignal(GSN_UTIL_EXECUTE_CONF, &Dbdict::execUTIL_EXECUTE_CONF);
2190   addRecSignal(GSN_UTIL_EXECUTE_REF,  &Dbdict::execUTIL_EXECUTE_REF);
2191 
2192   addRecSignal(GSN_UTIL_RELEASE_CONF, &Dbdict::execUTIL_RELEASE_CONF);
2193   addRecSignal(GSN_UTIL_RELEASE_REF,  &Dbdict::execUTIL_RELEASE_REF);
2194 
2195   // Event signals
2196   addRecSignal(GSN_CREATE_EVNT_REQ,  &Dbdict::execCREATE_EVNT_REQ);
2197   addRecSignal(GSN_CREATE_EVNT_CONF, &Dbdict::execCREATE_EVNT_CONF);
2198   addRecSignal(GSN_CREATE_EVNT_REF,  &Dbdict::execCREATE_EVNT_REF);
2199 
2200   addRecSignal(GSN_CREATE_SUBID_CONF, &Dbdict::execCREATE_SUBID_CONF);
2201   addRecSignal(GSN_CREATE_SUBID_REF,  &Dbdict::execCREATE_SUBID_REF);
2202 
2203   addRecSignal(GSN_SUB_CREATE_CONF, &Dbdict::execSUB_CREATE_CONF);
2204   addRecSignal(GSN_SUB_CREATE_REF,  &Dbdict::execSUB_CREATE_REF);
2205 
2206   addRecSignal(GSN_SUB_START_REQ,  &Dbdict::execSUB_START_REQ);
2207   addRecSignal(GSN_SUB_START_CONF,  &Dbdict::execSUB_START_CONF);
2208   addRecSignal(GSN_SUB_START_REF,  &Dbdict::execSUB_START_REF);
2209 
2210   addRecSignal(GSN_SUB_STOP_REQ,  &Dbdict::execSUB_STOP_REQ);
2211   addRecSignal(GSN_SUB_STOP_CONF,  &Dbdict::execSUB_STOP_CONF);
2212   addRecSignal(GSN_SUB_STOP_REF,  &Dbdict::execSUB_STOP_REF);
2213 
2214   addRecSignal(GSN_DROP_EVNT_REQ,  &Dbdict::execDROP_EVNT_REQ);
2215 
2216   addRecSignal(GSN_SUB_REMOVE_REQ, &Dbdict::execSUB_REMOVE_REQ);
2217   addRecSignal(GSN_SUB_REMOVE_CONF, &Dbdict::execSUB_REMOVE_CONF);
2218   addRecSignal(GSN_SUB_REMOVE_REF,  &Dbdict::execSUB_REMOVE_REF);
2219 
2220   // Trigger signals
2221   addRecSignal(GSN_CREATE_TRIG_REQ, &Dbdict::execCREATE_TRIG_REQ);
2222   addRecSignal(GSN_CREATE_TRIG_CONF, &Dbdict::execCREATE_TRIG_CONF);
2223   addRecSignal(GSN_CREATE_TRIG_REF, &Dbdict::execCREATE_TRIG_REF);
2224   addRecSignal(GSN_DROP_TRIG_REQ, &Dbdict::execDROP_TRIG_REQ);
2225   addRecSignal(GSN_DROP_TRIG_CONF, &Dbdict::execDROP_TRIG_CONF);
2226   addRecSignal(GSN_DROP_TRIG_REF, &Dbdict::execDROP_TRIG_REF);
2227   // Impl
2228   addRecSignal(GSN_CREATE_TRIG_IMPL_CONF, &Dbdict::execCREATE_TRIG_IMPL_CONF);
2229   addRecSignal(GSN_CREATE_TRIG_IMPL_REF, &Dbdict::execCREATE_TRIG_IMPL_REF);
2230   addRecSignal(GSN_DROP_TRIG_IMPL_CONF, &Dbdict::execDROP_TRIG_IMPL_CONF);
2231   addRecSignal(GSN_DROP_TRIG_IMPL_REF, &Dbdict::execDROP_TRIG_IMPL_REF);
2232 
2233   // Received signals
2234   addRecSignal(GSN_GET_SCHEMA_INFOREQ, &Dbdict::execGET_SCHEMA_INFOREQ);
2235   addRecSignal(GSN_SCHEMA_INFO, &Dbdict::execSCHEMA_INFO);
2236   addRecSignal(GSN_SCHEMA_INFOCONF, &Dbdict::execSCHEMA_INFOCONF);
2237   addRecSignal(GSN_DICTSTARTREQ, &Dbdict::execDICTSTARTREQ);
2238   addRecSignal(GSN_READ_NODESCONF, &Dbdict::execREAD_NODESCONF);
2239   addRecSignal(GSN_FSOPENCONF, &Dbdict::execFSOPENCONF);
2240   addRecSignal(GSN_FSOPENREF, &Dbdict::execFSOPENREF, true);
2241   addRecSignal(GSN_FSCLOSECONF, &Dbdict::execFSCLOSECONF);
2242   addRecSignal(GSN_FSWRITECONF, &Dbdict::execFSWRITECONF);
2243   addRecSignal(GSN_FSREADCONF, &Dbdict::execFSREADCONF);
2244   addRecSignal(GSN_FSREADREF, &Dbdict::execFSREADREF, true);
2245   addRecSignal(GSN_LQHFRAGCONF, &Dbdict::execLQHFRAGCONF);
2246   addRecSignal(GSN_LQHADDATTCONF, &Dbdict::execLQHADDATTCONF);
2247   addRecSignal(GSN_LQHADDATTREF, &Dbdict::execLQHADDATTREF);
2248   addRecSignal(GSN_LQHFRAGREF, &Dbdict::execLQHFRAGREF);
2249   addRecSignal(GSN_NDB_STTOR, &Dbdict::execNDB_STTOR);
2250   addRecSignal(GSN_READ_CONFIG_REQ, &Dbdict::execREAD_CONFIG_REQ, true);
2251   addRecSignal(GSN_STTOR, &Dbdict::execSTTOR);
2252   addRecSignal(GSN_TC_SCHVERCONF, &Dbdict::execTC_SCHVERCONF);
2253   addRecSignal(GSN_NODE_FAILREP, &Dbdict::execNODE_FAILREP);
2254   addRecSignal(GSN_INCL_NODEREQ, &Dbdict::execINCL_NODEREQ);
2255   addRecSignal(GSN_API_FAILREQ, &Dbdict::execAPI_FAILREQ);
2256 
2257   addRecSignal(GSN_WAIT_GCP_REF, &Dbdict::execWAIT_GCP_REF);
2258   addRecSignal(GSN_WAIT_GCP_CONF, &Dbdict::execWAIT_GCP_CONF);
2259 
2260   addRecSignal(GSN_LIST_TABLES_REQ, &Dbdict::execLIST_TABLES_REQ);
2261 
2262   addRecSignal(GSN_DROP_TABLE_REQ, &Dbdict::execDROP_TABLE_REQ);
2263 
2264   addRecSignal(GSN_PREP_DROP_TAB_REQ, &Dbdict::execPREP_DROP_TAB_REQ);
2265   addRecSignal(GSN_PREP_DROP_TAB_REF, &Dbdict::execPREP_DROP_TAB_REF);
2266   addRecSignal(GSN_PREP_DROP_TAB_CONF, &Dbdict::execPREP_DROP_TAB_CONF);
2267 
2268   addRecSignal(GSN_DROP_TAB_REF, &Dbdict::execDROP_TAB_REF);
2269   addRecSignal(GSN_DROP_TAB_CONF, &Dbdict::execDROP_TAB_CONF);
2270 
2271   addRecSignal(GSN_CREATE_FILE_REQ, &Dbdict::execCREATE_FILE_REQ);
2272   addRecSignal(GSN_CREATE_FILEGROUP_REQ, &Dbdict::execCREATE_FILEGROUP_REQ);
2273 
2274   addRecSignal(GSN_DROP_FILE_REQ, &Dbdict::execDROP_FILE_REQ);
2275   addRecSignal(GSN_DROP_FILEGROUP_REQ, &Dbdict::execDROP_FILEGROUP_REQ);
2276 
2277   addRecSignal(GSN_DROP_FILE_IMPL_REF, &Dbdict::execDROP_FILE_IMPL_REF);
2278   addRecSignal(GSN_DROP_FILE_IMPL_CONF, &Dbdict::execDROP_FILE_IMPL_CONF);
2279 
2280   addRecSignal(GSN_DROP_FILEGROUP_IMPL_REF,
2281                &Dbdict::execDROP_FILEGROUP_IMPL_REF);
2282   addRecSignal(GSN_DROP_FILEGROUP_IMPL_CONF,
2283                &Dbdict::execDROP_FILEGROUP_IMPL_CONF);
2284 
2285   addRecSignal(GSN_CREATE_FILE_IMPL_REF, &Dbdict::execCREATE_FILE_IMPL_REF);
2286   addRecSignal(GSN_CREATE_FILE_IMPL_CONF, &Dbdict::execCREATE_FILE_IMPL_CONF);
2287   addRecSignal(GSN_CREATE_FILEGROUP_IMPL_REF,
2288                &Dbdict::execCREATE_FILEGROUP_IMPL_REF);
2289   addRecSignal(GSN_CREATE_FILEGROUP_IMPL_CONF,
2290                &Dbdict::execCREATE_FILEGROUP_IMPL_CONF);
2291 
2292   addRecSignal(GSN_BACKUP_LOCK_TAB_REQ, &Dbdict::execBACKUP_LOCK_TAB_REQ);
2293 
2294   addRecSignal(GSN_SCHEMA_TRANS_BEGIN_REQ, &Dbdict::execSCHEMA_TRANS_BEGIN_REQ);
2295   addRecSignal(GSN_SCHEMA_TRANS_BEGIN_CONF, &Dbdict::execSCHEMA_TRANS_BEGIN_CONF);
2296   addRecSignal(GSN_SCHEMA_TRANS_BEGIN_REF, &Dbdict::execSCHEMA_TRANS_BEGIN_REF);
2297   addRecSignal(GSN_SCHEMA_TRANS_END_REQ, &Dbdict::execSCHEMA_TRANS_END_REQ);
2298   addRecSignal(GSN_SCHEMA_TRANS_END_CONF, &Dbdict::execSCHEMA_TRANS_END_CONF);
2299   addRecSignal(GSN_SCHEMA_TRANS_END_REF, &Dbdict::execSCHEMA_TRANS_END_REF);
2300   addRecSignal(GSN_SCHEMA_TRANS_END_REP, &Dbdict::execSCHEMA_TRANS_END_REP);
2301   addRecSignal(GSN_SCHEMA_TRANS_IMPL_REQ, &Dbdict::execSCHEMA_TRANS_IMPL_REQ);
2302   addRecSignal(GSN_SCHEMA_TRANS_IMPL_CONF, &Dbdict::execSCHEMA_TRANS_IMPL_CONF);
2303   addRecSignal(GSN_SCHEMA_TRANS_IMPL_REF, &Dbdict::execSCHEMA_TRANS_IMPL_REF);
2304 
2305   addRecSignal(GSN_DICT_LOCK_REQ, &Dbdict::execDICT_LOCK_REQ);
2306   addRecSignal(GSN_DICT_UNLOCK_ORD, &Dbdict::execDICT_UNLOCK_ORD);
2307 
2308   addRecSignal(GSN_DICT_TAKEOVER_REQ, &Dbdict::execDICT_TAKEOVER_REQ);
2309   addRecSignal(GSN_DICT_TAKEOVER_REF, &Dbdict::execDICT_TAKEOVER_REF);
2310   addRecSignal(GSN_DICT_TAKEOVER_CONF, &Dbdict::execDICT_TAKEOVER_CONF);
2311 
2312   addRecSignal(GSN_CREATE_HASH_MAP_REQ, &Dbdict::execCREATE_HASH_MAP_REQ);
2313 
2314   addRecSignal(GSN_COPY_DATA_REQ, &Dbdict::execCOPY_DATA_REQ);
2315   addRecSignal(GSN_COPY_DATA_REF, &Dbdict::execCOPY_DATA_REF);
2316   addRecSignal(GSN_COPY_DATA_CONF, &Dbdict::execCOPY_DATA_CONF);
2317 
2318   addRecSignal(GSN_COPY_DATA_IMPL_REF, &Dbdict::execCOPY_DATA_IMPL_REF);
2319   addRecSignal(GSN_COPY_DATA_IMPL_CONF, &Dbdict::execCOPY_DATA_IMPL_CONF);
2320 
2321   addRecSignal(GSN_CREATE_NODEGROUP_REQ, &Dbdict::execCREATE_NODEGROUP_REQ);
2322   addRecSignal(GSN_CREATE_NODEGROUP_IMPL_REF, &Dbdict::execCREATE_NODEGROUP_IMPL_REF);
2323   addRecSignal(GSN_CREATE_NODEGROUP_IMPL_CONF, &Dbdict::execCREATE_NODEGROUP_IMPL_CONF);
2324 
2325   addRecSignal(GSN_CREATE_HASH_MAP_REF, &Dbdict::execCREATE_HASH_MAP_REF);
2326   addRecSignal(GSN_CREATE_HASH_MAP_CONF, &Dbdict::execCREATE_HASH_MAP_CONF);
2327 
2328   addRecSignal(GSN_DROP_NODEGROUP_REQ, &Dbdict::execDROP_NODEGROUP_REQ);
2329   addRecSignal(GSN_DROP_NODEGROUP_IMPL_REF, &Dbdict::execDROP_NODEGROUP_IMPL_REF);
2330   addRecSignal(GSN_DROP_NODEGROUP_IMPL_CONF, &Dbdict::execDROP_NODEGROUP_IMPL_CONF);
2331 
2332   // ordered index statistics
2333   addRecSignal(GSN_INDEX_STAT_REQ, &Dbdict::execINDEX_STAT_REQ);
2334   addRecSignal(GSN_INDEX_STAT_CONF, &Dbdict::execINDEX_STAT_CONF);
2335   addRecSignal(GSN_INDEX_STAT_REF, &Dbdict::execINDEX_STAT_REF);
2336   addRecSignal(GSN_INDEX_STAT_IMPL_CONF, &Dbdict::execINDEX_STAT_IMPL_CONF);
2337   addRecSignal(GSN_INDEX_STAT_IMPL_REF, &Dbdict::execINDEX_STAT_IMPL_REF);
2338   addRecSignal(GSN_INDEX_STAT_REP, &Dbdict::execINDEX_STAT_REP);
2339 
2340   // fk
2341   addRecSignal(GSN_CREATE_FK_REQ, &Dbdict::execCREATE_FK_REQ);
2342   addRecSignal(GSN_CREATE_FK_IMPL_REF, &Dbdict::execCREATE_FK_IMPL_REF);
2343   addRecSignal(GSN_CREATE_FK_IMPL_CONF, &Dbdict::execCREATE_FK_IMPL_CONF);
2344   addRecSignal(GSN_CREATE_FK_REF, &Dbdict::execCREATE_FK_REF);
2345   addRecSignal(GSN_CREATE_FK_CONF, &Dbdict::execCREATE_FK_CONF);
2346 
2347   addRecSignal(GSN_BUILD_FK_REQ, &Dbdict::execBUILD_FK_REQ);
2348   addRecSignal(GSN_BUILD_FK_REF, &Dbdict::execBUILD_FK_REF);
2349   addRecSignal(GSN_BUILD_FK_CONF, &Dbdict::execBUILD_FK_CONF);
2350   addRecSignal(GSN_BUILD_FK_IMPL_REF, &Dbdict::execBUILD_FK_IMPL_REF);
2351   addRecSignal(GSN_BUILD_FK_IMPL_CONF, &Dbdict::execBUILD_FK_IMPL_CONF);
2352 
2353   addRecSignal(GSN_DROP_FK_REQ, &Dbdict::execDROP_FK_REQ);
2354   addRecSignal(GSN_DROP_FK_IMPL_REF, &Dbdict::execDROP_FK_IMPL_REF);
2355   addRecSignal(GSN_DROP_FK_IMPL_CONF, &Dbdict::execDROP_FK_IMPL_CONF);
2356 }//Dbdict::Dbdict()
2357 
~Dbdict()2358 Dbdict::~Dbdict()
2359 {
2360 }//Dbdict::~Dbdict()
2361 
BLOCK_FUNCTIONS(Dbdict)2362 BLOCK_FUNCTIONS(Dbdict)
2363 
2364 bool
2365 Dbdict::getParam(const char * name, Uint32 * count)
2366 {
2367   if (name != 0 && count != 0)
2368   {
2369     if (strcmp(name, "ActiveCounters") == 0)
2370     {
2371       * count = 25;
2372       return true;
2373     }
2374   }
2375   return false;
2376 }
2377 
initCommonData()2378 void Dbdict::initCommonData()
2379 {
2380 /* ---------------------------------------------------------------- */
2381 // Initialise all common variables.
2382 /* ---------------------------------------------------------------- */
2383   initRetrieveRecord(0, 0, 0);
2384   initSchemaRecord();
2385   initRestartRecord();
2386   initSendSchemaRecord();
2387   initReadTableRecord();
2388   initWriteTableRecord();
2389   initReadSchemaRecord();
2390   initWriteSchemaRecord();
2391 
2392   c_masterNodeId = ZNIL;
2393   c_numberNode = 0;
2394   c_noNodesFailed = 0;
2395   c_failureNr = 0;
2396   c_packTable.m_state = PackTable::PTS_IDLE;
2397   c_startPhase = 0;
2398   c_restartType = 255; //Ensure not used restartType
2399   c_tabinfoReceived = 0;
2400   c_initialStart = false;
2401   c_systemRestart = false;
2402   c_initialNodeRestart = false;
2403   c_nodeRestart = false;
2404   c_takeOverInProgress = false;
2405 
2406   c_outstanding_sub_startstop = 0;
2407   c_sub_startstop_lock.clear();
2408 
2409 #if defined VM_TRACE || defined ERROR_INSERT
2410   g_trace = 99;
2411 #else
2412   g_trace = 0;
2413 #endif
2414 
2415 }//Dbdict::initCommonData()
2416 
initRecords()2417 void Dbdict::initRecords()
2418 {
2419   initNodeRecords();
2420   initPageRecords();
2421 }//Dbdict::initRecords()
2422 
initSendSchemaRecord()2423 void Dbdict::initSendSchemaRecord()
2424 {
2425   c_sendSchemaRecord.noOfWords = (Uint32)-1;
2426   c_sendSchemaRecord.pageId = RNIL;
2427   c_sendSchemaRecord.noOfWordsCurrentlySent = 0;
2428   c_sendSchemaRecord.noOfSignalsSentSinceDelay = 0;
2429   c_sendSchemaRecord.inUse = false;
2430   //c_sendSchemaRecord.sendSchemaState = SendSchemaRecord::IDLE;
2431 }//initSendSchemaRecord()
2432 
initReadTableRecord()2433 void Dbdict::initReadTableRecord()
2434 {
2435   c_readTableRecord.no_of_words= 0;
2436   c_readTableRecord.pageId = RNIL;
2437   c_readTableRecord.tableId = ZNIL;
2438   c_readTableRecord.inUse = false;
2439 }//initReadTableRecord()
2440 
initWriteTableRecord()2441 void Dbdict::initWriteTableRecord()
2442 {
2443   c_writeTableRecord.no_of_words= 0;
2444   c_writeTableRecord.pageId = RNIL;
2445   c_writeTableRecord.noOfTableFilesHandled = 3;
2446   c_writeTableRecord.tableId = ZNIL;
2447   c_writeTableRecord.tableWriteState = WriteTableRecord::IDLE;
2448 }//initWriteTableRecord()
2449 
initReadSchemaRecord()2450 void Dbdict::initReadSchemaRecord()
2451 {
2452   c_readSchemaRecord.pageId = RNIL;
2453   c_readSchemaRecord.schemaReadState = ReadSchemaRecord::IDLE;
2454 }//initReadSchemaRecord()
2455 
initWriteSchemaRecord()2456 void Dbdict::initWriteSchemaRecord()
2457 {
2458   c_writeSchemaRecord.inUse = false;
2459   c_writeSchemaRecord.pageId = RNIL;
2460   c_writeSchemaRecord.noOfSchemaFilesHandled = 3;
2461 }//initWriteSchemaRecord()
2462 
initRetrieveRecord(Signal * signal,Uint32 i,Uint32 returnCode)2463 void Dbdict::initRetrieveRecord(Signal* signal, Uint32 i, Uint32 returnCode)
2464 {
2465   jam();
2466   c_retrieveRecord.blockRef = 0;
2467   c_retrieveRecord.m_senderData = RNIL;
2468   c_retrieveRecord.tableId = RNIL;
2469   c_retrieveRecord.currentSent = 0;
2470   c_retrieveRecord.retrievedNoOfPages = 0;
2471   c_retrieveRecord.retrievedNoOfWords = 0;
2472   c_retrieveRecord.m_useLongSig = false;
2473 
2474   if (!c_gettabinforeq_q.isEmpty())
2475   {
2476     jam();
2477     ndbrequire(signal != NULL);
2478 
2479     /* Take a real-time break now, CONTINUEB will
2480      * start processing the next request.
2481      * busyState = true will maintain fairness
2482      */
2483     signal->theData[0] = ZNEXT_GET_TAB_REQ;
2484     sendSignal(reference(), GSN_CONTINUEB, signal,
2485                1, JBB);
2486   }
2487   else
2488   {
2489     /* Done */
2490     c_retrieveRecord.busyState = false;
2491   }
2492 
2493 }//initRetrieveRecord()
2494 
initSchemaRecord()2495 void Dbdict::initSchemaRecord()
2496 {
2497   c_schemaRecord.schemaPage = RNIL;
2498   c_schemaRecord.oldSchemaPage = RNIL;
2499 }//Dbdict::initSchemaRecord()
2500 
initNodeRecords()2501 void Dbdict::initNodeRecords()
2502 {
2503   jam();
2504   for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
2505     NodeRecordPtr nodePtr;
2506     c_nodes.getPtr(nodePtr, i);
2507     new (nodePtr.p) NodeRecord();
2508     nodePtr.p->hotSpare = false;
2509     nodePtr.p->nodeState = NodeRecord::API_NODE;
2510   }//for
2511 }//Dbdict::initNodeRecords()
2512 
initPageRecords()2513 void Dbdict::initPageRecords()
2514 {
2515   c_retrieveRecord.retrievePage =  ZMAX_PAGES_OF_TABLE_DEFINITION;
2516   ndbrequire(ZNUMBER_OF_PAGES >= (ZMAX_PAGES_OF_TABLE_DEFINITION + 1));
2517   c_schemaRecord.schemaPage = 0;
2518   c_schemaRecord.oldSchemaPage = NDB_SF_MAX_PAGES;
2519 }//Dbdict::initPageRecords()
2520 
initialiseTableRecord(TableRecordPtr tablePtr,Uint32 tableId)2521 void Dbdict::initialiseTableRecord(TableRecordPtr tablePtr, Uint32 tableId)
2522 {
2523   new (tablePtr.p) TableRecord();
2524   tablePtr.p->filePtr[0] = RNIL;
2525   tablePtr.p->filePtr[1] = RNIL;
2526   tablePtr.p->tableId = tableId;
2527   tablePtr.p->tableVersion = (Uint32)-1;
2528   tablePtr.p->fragmentType = DictTabInfo::AllNodesSmallTable;
2529   tablePtr.p->gciTableCreated = 0;
2530   tablePtr.p->noOfAttributes = ZNIL;
2531   tablePtr.p->noOfNullAttr = 0;
2532   tablePtr.p->fragmentCount = 0;
2533   /*
2534     tablePtr.p->lh3PageIndexBits = 0;
2535     tablePtr.p->lh3DistrBits = 0;
2536     tablePtr.p->lh3PageBits = 6;
2537   */
2538   tablePtr.p->kValue = 6;
2539   tablePtr.p->localKeyLen = 1;
2540   tablePtr.p->maxLoadFactor = 80;
2541   tablePtr.p->minLoadFactor = 70;
2542   tablePtr.p->noOfPrimkey = 1;
2543   tablePtr.p->tupKeyLength = 1;
2544   tablePtr.p->maxRowsLow = 0;
2545   tablePtr.p->maxRowsHigh = 0;
2546   tablePtr.p->defaultNoPartFlag = true;
2547   tablePtr.p->linearHashFlag = true;
2548   tablePtr.p->m_bits = 0;
2549   tablePtr.p->minRowsLow = 0;
2550   tablePtr.p->minRowsHigh = 0;
2551   tablePtr.p->singleUserMode = 0;
2552   tablePtr.p->tableType = DictTabInfo::UserTable;
2553   tablePtr.p->primaryTableId = RNIL;
2554   // volatile elements
2555   tablePtr.p->indexState = TableRecord::IS_UNDEFINED;
2556   tablePtr.p->triggerId = RNIL;
2557   tablePtr.p->buildTriggerId = RNIL;
2558   tablePtr.p->m_read_locked= 0;
2559   tablePtr.p->storageType = NDB_STORAGETYPE_DEFAULT;
2560   tablePtr.p->indexStatFragId = ZNIL;
2561   bzero(tablePtr.p->indexStatNodes, sizeof(tablePtr.p->indexStatNodes));
2562   tablePtr.p->indexStatBgRequest = 0;
2563   tablePtr.p->m_obj_ptr_i = RNIL;
2564 }//Dbdict::initialiseTableRecord()
2565 
initialiseTriggerRecord(TriggerRecordPtr triggerPtr,Uint32 triggerId)2566 void Dbdict::initialiseTriggerRecord(TriggerRecordPtr triggerPtr, Uint32 triggerId)
2567 {
2568   new (triggerPtr.p) TriggerRecord();
2569   triggerPtr.p->triggerState = TriggerRecord::TS_NOT_DEFINED;
2570   triggerPtr.p->triggerId = triggerId;
2571   triggerPtr.p->tableId = RNIL;
2572   triggerPtr.p->attributeMask.clear();
2573   triggerPtr.p->indexId = RNIL;
2574   triggerPtr.p->m_obj_ptr_i = RNIL;
2575 }
2576 
getFsConnRecord()2577 Uint32 Dbdict::getFsConnRecord()
2578 {
2579   FsConnectRecordPtr fsPtr;
2580   c_fsConnectRecordPool.seize(fsPtr);
2581   ndbrequire(fsPtr.i != RNIL);
2582   fsPtr.p->filePtr = (Uint32)-1;
2583   fsPtr.p->ownerPtr = RNIL;
2584   fsPtr.p->fsState = FsConnectRecord::IDLE;
2585   return fsPtr.i;
2586 }//Dbdict::getFsConnRecord()
2587 
2588 /*
2589  * Search schemafile for free entry.  Its index is used as 'logical id'
2590  * of new disk-stored object.
2591  */
getFreeObjId(bool both)2592 Uint32 Dbdict::getFreeObjId(bool both)
2593 {
2594   const XSchemaFile * newxsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
2595   const XSchemaFile * oldxsf = &c_schemaFile[SchemaRecord::OLD_SCHEMA_FILE];
2596   const Uint32 noOfEntries = newxsf->noOfPages * NDB_SF_PAGE_ENTRIES;
2597   for (Uint32 i = 0; i<noOfEntries; i++)
2598   {
2599     const SchemaFile::TableEntry * oldentry = getTableEntry(oldxsf, i);
2600     const SchemaFile::TableEntry * newentry = getTableEntry(newxsf, i);
2601     if (newentry->m_tableState == (Uint32)SchemaFile::SF_UNUSED)
2602     {
2603       jam();
2604       if (both == false ||
2605           oldentry->m_tableState == (Uint32)SchemaFile::SF_UNUSED)
2606       {
2607         jam();
2608         return i;
2609       }
2610     }
2611   }
2612   return RNIL;
2613 }
2614 
seizeTableRecord(TableRecordPtr & tablePtr,Uint32 & schemaFileId)2615 bool Dbdict::seizeTableRecord(TableRecordPtr& tablePtr, Uint32& schemaFileId)
2616 {
2617   if (schemaFileId == RNIL)
2618   {
2619     jam();
2620     schemaFileId = getFreeObjId();
2621   }
2622   if (schemaFileId == RNIL)
2623   {
2624     jam();
2625     return false;
2626   }
2627   if (schemaFileId >= c_noOfMetaTables)
2628   {
2629     jam();
2630     return false;
2631   }
2632 
2633   c_tableRecordPool_.seize(tablePtr);
2634   if (tablePtr.isNull())
2635   {
2636     jam();
2637     return false;
2638   }
2639   D("seizeTableRecord " << schemaFileId);
2640   initialiseTableRecord(tablePtr, schemaFileId);
2641   return true;
2642 }
2643 
getFreeTriggerRecord()2644 Uint32 Dbdict::getFreeTriggerRecord()
2645 {
2646   const Uint32 size = c_triggerRecordPool_.getSize();
2647   TriggerRecordPtr triggerPtr;
2648   for (Uint32 id = 0; id < size; id++) {
2649     jam();
2650     bool ok = find_object(triggerPtr, id);
2651     if (!ok)
2652     {
2653       jam();
2654       return id;
2655     }
2656   }
2657   return RNIL;
2658 }
2659 
seizeTriggerRecord(TriggerRecordPtr & triggerPtr,Uint32 triggerId)2660 bool Dbdict::seizeTriggerRecord(TriggerRecordPtr& triggerPtr, Uint32 triggerId)
2661 {
2662   if (triggerId == RNIL)
2663   {
2664     triggerId = getFreeTriggerRecord();
2665   }
2666   else
2667   {
2668     TriggerRecordPtr ptr;
2669     bool ok =  find_object(ptr, triggerId);
2670     if (ok)
2671     { // triggerId already in use
2672       jam();
2673       return false;
2674     }
2675   }
2676   if (triggerId == RNIL)
2677   {
2678     jam();
2679     return false;
2680   }
2681   c_triggerRecordPool_.seize(triggerPtr);
2682   if (triggerPtr.isNull())
2683   {
2684     jam();
2685     return false;
2686   }
2687   initialiseTriggerRecord(triggerPtr, triggerId);
2688   return true;
2689 }
2690 
2691 Uint32
check_read_obj(Uint32 objId,Uint32 transId)2692 Dbdict::check_read_obj(Uint32 objId, Uint32 transId)
2693 {
2694   XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
2695   if (objId < (NDB_SF_PAGE_ENTRIES * xsf->noOfPages))
2696   {
2697     jam();
2698     return check_read_obj(getTableEntry(xsf, objId), transId);
2699   }
2700   return GetTabInfoRef::InvalidTableId;
2701 }
2702 
2703 Uint32
check_read_obj(SchemaFile::TableEntry * te,Uint32 transId)2704 Dbdict::check_read_obj(SchemaFile::TableEntry* te, Uint32 transId)
2705 {
2706   D("check_read_obj" << V(*te) << V(transId));
2707 
2708   if (te->m_tableState == SchemaFile::SF_UNUSED)
2709   {
2710     jam();
2711     return GetTabInfoRef::TableNotDefined;
2712   }
2713 
2714   if (te->m_transId == 0 || te->m_transId == transId)
2715   {
2716     jam();
2717     return 0;
2718   }
2719 
2720   switch(te->m_tableState){
2721   case SchemaFile::SF_CREATE:
2722     jam();
2723     return GetTabInfoRef::TableNotDefined;
2724     break;
2725   case SchemaFile::SF_ALTER:
2726     jam();
2727     return 0;
2728   case SchemaFile::SF_DROP:
2729     jam();
2730     /** uncommitted drop */
2731     return DropTableRef::ActiveSchemaTrans;
2732   case SchemaFile::SF_IN_USE:
2733     jam();
2734     return 0;
2735   default:
2736     /** weird... */
2737     return GetTabInfoRef::TableNotDefined;
2738   }
2739 }
2740 
2741 
2742 Uint32
check_write_obj(Uint32 objId,Uint32 transId,SchemaFile::EntryState op)2743 Dbdict::check_write_obj(Uint32 objId, Uint32 transId,
2744                        SchemaFile::EntryState op)
2745 {
2746   XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
2747   if (objId < (NDB_SF_PAGE_ENTRIES * xsf->noOfPages))
2748   {
2749     jam();
2750     SchemaFile::TableEntry* te = getTableEntry(xsf, objId);
2751     D("check_write_obj" << V(op) << V(*te) << V(transId));
2752 
2753     if (te->m_tableState == SchemaFile::SF_UNUSED)
2754     {
2755       jam();
2756       return GetTabInfoRef::TableNotDefined;
2757     }
2758 
2759     // bug#18766430 - detect double drop earlier
2760     // TODO: detect other incompatible ops at this stage
2761     if (te->m_tableState == SchemaFile::SF_DROP &&
2762         op == SchemaFile::SF_DROP)
2763     {
2764       jam();
2765       return DropTableRef::ActiveSchemaTrans;
2766     }
2767 
2768     if (te->m_transId == 0 || te->m_transId == transId)
2769     {
2770       jam();
2771       return 0;
2772     }
2773 
2774     return DropTableRef::ActiveSchemaTrans;
2775   }
2776   return GetTabInfoRef::InvalidTableId;
2777 }
2778 
2779 Uint32
check_write_obj(Uint32 objId,Uint32 transId,SchemaFile::EntryState op,ErrorInfo & error)2780 Dbdict::check_write_obj(Uint32 objId, Uint32 transId,
2781                         SchemaFile::EntryState op,
2782                         ErrorInfo& error)
2783 {
2784   Uint32 err = check_write_obj(objId, transId, op);
2785   if (err)
2786   {
2787     jam();
2788     setError(error, err, __LINE__);
2789   }
2790 
2791   return err;
2792 }
2793 
2794 
2795 
2796 /* **************************************************************** */
2797 /* ---------------------------------------------------------------- */
2798 /* MODULE:          START/RESTART HANDLING ------------------------ */
2799 /* ---------------------------------------------------------------- */
2800 /*                                                                  */
2801 /* This module contains the code that is common for all             */
2802 /* start/restart types.                                             */
2803 /* ---------------------------------------------------------------- */
2804 /* **************************************************************** */
2805 
2806 /* ---------------------------------------------------------------- */
2807 // This is sent as the first signal during start/restart.
2808 /* ---------------------------------------------------------------- */
execSTTOR(Signal * signal)2809 void Dbdict::execSTTOR(Signal* signal)
2810 {
2811   jamEntry();
2812   c_startPhase = signal->theData[1];
2813   switch (c_startPhase) {
2814   case 1:
2815     break;
2816   case 3:
2817     c_restartType = signal->theData[7];         /* valid if 3 */
2818     ndbrequire(c_restartType == NodeState::ST_INITIAL_START ||
2819                c_restartType == NodeState::ST_SYSTEM_RESTART ||
2820                c_restartType == NodeState::ST_INITIAL_NODE_RESTART ||
2821                c_restartType == NodeState::ST_NODE_RESTART);
2822     break;
2823   case 7:
2824     /*
2825      * config cannot yet be changed dynamically but we start the
2826      * loop always anyway because the cost is minimal
2827      */
2828     c_indexStatBgId = 0;
2829     indexStatBg_sendContinueB(signal);
2830     break;
2831   }
2832   sendSTTORRY(signal);
2833 }//execSTTOR()
2834 
sendSTTORRY(Signal * signal)2835 void Dbdict::sendSTTORRY(Signal* signal)
2836 {
2837   signal->theData[0] = 0;       /* garbage SIGNAL KEY */
2838   signal->theData[1] = 0;       /* garbage SIGNAL VERSION NUMBER  */
2839   signal->theData[2] = 0;       /* garbage */
2840   signal->theData[3] = 1;       /* first wanted start phase */
2841   signal->theData[4] = 3;       /* get type of start */
2842   signal->theData[5] = 7;       /* start index stat bg loop */
2843   signal->theData[6] = ZNOMOREPHASES;
2844   sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 7, JBB);
2845 }
2846 
2847 /* ---------------------------------------------------------------- */
2848 // We receive information about sizes of records.
2849 /* ---------------------------------------------------------------- */
execREAD_CONFIG_REQ(Signal * signal)2850 void Dbdict::execREAD_CONFIG_REQ(Signal* signal)
2851 {
2852   const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
2853   Uint32 ref = req->senderRef;
2854   Uint32 senderData = req->senderData;
2855   ndbrequire(req->noOfParameters == 0);
2856 
2857   jamEntry();
2858 
2859   const ndb_mgm_configuration_iterator * p =
2860     m_ctx.m_config.getOwnConfigIterator();
2861   ndbrequire(p != 0);
2862 
2863   Uint32 attributesize;
2864   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_TRIGGERS,
2865 					&c_maxNoOfTriggers));
2866   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DICT_ATTRIBUTE,&attributesize));
2867   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DICT_TABLE, &c_noOfMetaTables));
2868   c_indexStatAutoCreate = 0;
2869   ndb_mgm_get_int_parameter(p, CFG_DB_INDEX_STAT_AUTO_CREATE,
2870                             &c_indexStatAutoCreate);
2871   c_indexStatAutoUpdate = 0;
2872   ndb_mgm_get_int_parameter(p, CFG_DB_INDEX_STAT_AUTO_UPDATE,
2873                             &c_indexStatAutoUpdate);
2874   ndb_mgm_get_int_parameter(p, CFG_DB_AT_RESTART_SKIP_INDEXES,
2875                             &c_at_restart_skip_indexes);
2876   ndb_mgm_get_int_parameter(p, CFG_DB_AT_RESTART_SKIP_FKS,
2877                             &c_at_restart_skip_fks);
2878 
2879   c_default_hashmap_size = 0;
2880   ndb_mgm_get_int_parameter(p, CFG_DEFAULT_HASHMAP_SIZE, &c_default_hashmap_size);
2881   if (c_default_hashmap_size == 0)
2882   {
2883     c_default_hashmap_size = NDB_DEFAULT_HASHMAP_BUCKETS;
2884   }
2885 
2886   Pool_context pc;
2887   pc.m_block = this;
2888 
2889   c_arenaAllocator.init(796, RT_DBDICT_SCHEMA_TRANS_ARENA, pc);
2890   /**
2891     TODO: set size automagical? INFO: 796 is about 1/41 of a page,
2892     and bigger than CreateIndexRec (784 bytes)
2893   */
2894 
2895   c_attributeRecordPool.setSize(attributesize);
2896   c_attributeRecordHash.setSize(64);
2897   c_fsConnectRecordPool.setSize(ZFS_CONNECT_SIZE);
2898   c_nodes.setSize(MAX_NDB_NODES);
2899   c_pageRecordArray.setSize(ZNUMBER_OF_PAGES);
2900   c_schemaPageRecordArray.setSize(2 * NDB_SF_MAX_PAGES);
2901   c_tableRecordPool_.setSize(c_noOfMetaTables);
2902   g_key_descriptor_pool.setSize(c_noOfMetaTables);
2903   c_triggerRecordPool_.setSize(c_maxNoOfTriggers);
2904 
2905   Record_info ri;
2906   OpSectionBuffer::createRecordInfo(ri, RT_DBDICT_OP_SECTION_BUFFER);
2907   c_opSectionBufferPool.init(&c_arenaAllocator, ri, pc);
2908 
2909   c_schemaOpHash.setSize(MAX_SCHEMA_OPERATIONS);
2910   c_schemaTransPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_SCHEMA_TRANSACTION, pc);
2911   c_schemaTransHash.setSize(2);
2912   c_txHandlePool.setSize(2);
2913   c_txHandleHash.setSize(2);
2914 
2915   c_obj_pool.setSize(c_noOfMetaTables+c_maxNoOfTriggers);
2916   c_obj_name_hash.setSize((c_noOfMetaTables+c_maxNoOfTriggers+1)/2);
2917   c_obj_id_hash.setSize((c_noOfMetaTables+c_maxNoOfTriggers+1)/2);
2918   m_dict_lock_pool.setSize(MAX_NDB_NODES);
2919 
2920   c_file_pool.init(RT_DBDICT_FILE, pc);
2921   c_filegroup_pool.init(RT_DBDICT_FILEGROUP, pc);
2922 
2923   c_fk_pool.init(RT_DBDICT_FILE, pc); // TODO
2924 
2925   // new OpRec pools
2926   /**
2927    * one mysql index can be 2 ndb indexes
2928    */
2929   /**
2930    * TODO: Use arena-allocator for schema-transactions
2931    */
2932   c_createTableRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_CREATE_TABLE, pc);
2933   c_dropTableRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_DROP_TABLE, pc);
2934   c_alterTableRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_ALTER_TABLE, pc);
2935   c_createTriggerRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_CREATE_TRIGGER, pc);
2936   c_dropTriggerRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_DROP_TRIGGER, pc);
2937   c_createIndexRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_CREATE_INDEX, pc);
2938   c_dropIndexRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_DROP_INDEX, pc);
2939   c_alterIndexRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_ALTER_INDEX, pc);
2940   c_buildIndexRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_BUILD_INDEX, pc);
2941   c_indexStatRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_INDEX_STAT, pc);
2942   c_createFilegroupRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_CREATE_FILEGROUP, pc);
2943   c_createFileRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_CREATE_FILE, pc);
2944   c_dropFilegroupRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_DROP_FILEGROUP, pc);
2945   c_dropFileRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_DROP_FILE, pc);
2946   c_createHashMapRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_CREATE_HASH_MAP, pc);
2947   c_copyDataRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_COPY_DATA, pc);
2948   c_schemaOpPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_SCHEMA_OPERATION, pc);
2949 
2950   c_hash_map_pool.setSize(32);
2951   g_hash_map.setSize(32);
2952 
2953   c_createNodegroupRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_CREATE_NODEGROUP, pc);
2954   c_dropNodegroupRecPool.arena_pool_init(&c_arenaAllocator, RT_DBDICT_DROP_NODEGROUP, pc);
2955 
2956 // TODO
2957 #define RT_DBDICT_CREATE_FK RT_DBDICT_CREATE_NODEGROUP
2958 #define RT_DBDICT_BUILD_FK RT_DBDICT_DROP_NODEGROUP
2959 #define RT_DBDICT_DROP_FK RT_DBDICT_DROP_NODEGROUP
2960 
2961   c_createFKRecPool.arena_pool_init(&c_arenaAllocator,
2962                                     RT_DBDICT_CREATE_FK, pc);
2963   c_buildFKRecPool.arena_pool_init(&c_arenaAllocator,
2964                                    RT_DBDICT_BUILD_FK, pc);
2965   c_dropFKRecPool.arena_pool_init(&c_arenaAllocator,
2966                                   RT_DBDICT_DROP_FK, pc);
2967 
2968   c_opRecordPool.setSize(256);   // XXX need config params
2969   c_opCreateEvent.setSize(2);
2970   c_opSubEvent.setSize(2);
2971   c_opDropEvent.setSize(2);
2972   c_opSignalUtil.setSize(8);
2973 
2974   // Initialize schema file copies
2975   c_schemaFile[0].schemaPage =
2976     (SchemaFile*)c_schemaPageRecordArray.getPtr(0 * NDB_SF_MAX_PAGES);
2977   c_schemaFile[0].noOfPages = 0;
2978   c_schemaFile[1].schemaPage =
2979     (SchemaFile*)c_schemaPageRecordArray.getPtr(1 * NDB_SF_MAX_PAGES);
2980   c_schemaFile[1].noOfPages = 0;
2981 
2982   Uint32 rps = 0;
2983   rps += c_noOfMetaTables * (MAX_TAB_NAME_SIZE + MAX_FRM_DATA_SIZE);
2984   rps += attributesize * (MAX_ATTR_NAME_SIZE + MAX_ATTR_DEFAULT_VALUE_SIZE);
2985   rps += c_maxNoOfTriggers * MAX_TAB_NAME_SIZE;
2986   rps += (10 + 10) * MAX_TAB_NAME_SIZE;
2987 
2988   Uint32 sm = 5;
2989   ndb_mgm_get_int_parameter(p, CFG_DB_STRING_MEMORY, &sm);
2990   if (sm == 0)
2991     sm = 25;
2992 
2993   Uint64 sb = 0;
2994   if (sm <= 100)
2995   {
2996     sb = (Uint64(rps) * Uint64(sm)) / 100;
2997   }
2998   else
2999   {
3000     sb = sm;
3001   }
3002 
3003   sb /= (LocalRope::getSegmentSize() * sizeof(Uint32));
3004   sb += 100; // more safty
3005   ndbrequire(sb < (Uint64(1) << 32));
3006   c_rope_pool.setSize(Uint32(sb));
3007 
3008   // Initialize BAT for interface to file system
3009   NewVARIABLE* bat = allocateBat(2);
3010   bat[0].WA = &c_schemaPageRecordArray.getPtr(0)->word[0];
3011   bat[0].nrr = 2 * NDB_SF_MAX_PAGES;
3012   bat[0].ClusterSize = NDB_SF_PAGE_SIZE;
3013   bat[0].bits.q = NDB_SF_PAGE_SIZE_IN_WORDS_LOG2;
3014   bat[0].bits.v = 5;  // 32 bits per element
3015   bat[1].WA = &c_pageRecordArray.getPtr(0)->word[0];
3016   bat[1].nrr = ZNUMBER_OF_PAGES;
3017   bat[1].ClusterSize = ZSIZE_OF_PAGES_IN_WORDS * 4;
3018   bat[1].bits.q = ZLOG_SIZE_OF_PAGES_IN_WORDS; // 2**13 = 8192 elements
3019   bat[1].bits.v = 5;  // 32 bits per element
3020 
3021   /* Initialize Segment Sub pool in GetTabInfoReq queue */
3022   ndbrequire(c_gettabinforeq_q.init(jamBuffer()));
3023 
3024   initCommonData();
3025   initRecords();
3026 
3027   ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
3028   conf->senderRef = reference();
3029   conf->senderData = senderData;
3030   sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
3031 	     ReadConfigConf::SignalLength, JBB);
3032 
3033   {
3034     DictObjectPtr ptr;
3035     DictObject_list objs(c_obj_pool);
3036     while (objs.seizeFirst(ptr))
3037       new (ptr.p) DictObject();
3038     while (objs.releaseFirst());
3039   }
3040 
3041   bool use_get_env = false;
3042 #ifdef NDB_USE_GET_ENV
3043   use_get_env = true;
3044 #endif
3045   unsigned trace = 0;
3046   char buf[100];
3047   if (use_get_env && NdbEnv_GetEnv("DICT_TRACE", buf, sizeof(buf)))
3048   {
3049     jam();
3050     g_trace = (unsigned)atoi(buf);
3051   }
3052   else if (ndb_mgm_get_int_parameter(p, CFG_DB_DICT_TRACE, &trace) == 0)
3053   {
3054     g_trace = trace;
3055   }
3056 }
3057 
3058 /* ---------------------------------------------------------------- */
3059 // Start phase signals sent by CNTR. We reply with NDB_STTORRY when
3060 // we completed this phase.
3061 /* ---------------------------------------------------------------- */
execNDB_STTOR(Signal * signal)3062 void Dbdict::execNDB_STTOR(Signal* signal)
3063 {
3064   jamEntry();
3065   c_startPhase = signal->theData[2];
3066   const Uint32 restartType = signal->theData[3];
3067   if (restartType == NodeState::ST_INITIAL_START) {
3068     jam();
3069     c_initialStart = true;
3070   } else if (restartType == NodeState::ST_SYSTEM_RESTART) {
3071     jam();
3072     c_systemRestart = true;
3073   } else if (restartType == NodeState::ST_INITIAL_NODE_RESTART) {
3074     jam();
3075     c_initialNodeRestart = true;
3076   } else if (restartType == NodeState::ST_NODE_RESTART) {
3077     jam();
3078     c_nodeRestart = true;
3079   } else {
3080     ndbrequire(false);
3081   }//if
3082   switch (c_startPhase) {
3083   case 1:
3084     jam();
3085     initSchemaFile(signal);
3086     break;
3087   case 3:
3088     jam();
3089     signal->theData[0] = reference();
3090     sendSignal(NDBCNTR_REF, GSN_READ_NODESREQ, signal, 1, JBB);
3091     break;
3092   case 6:
3093     jam();
3094     c_initialStart = false;
3095     c_systemRestart = false;
3096     c_initialNodeRestart = false;
3097     c_nodeRestart = false;
3098     sendNDB_STTORRY(signal);
3099     break;
3100   case 7:
3101     jam();
3102     g_eventLogger->info("Foreign Key enabling Starting");
3103     enableFKs(signal, 0);
3104     break;
3105   default:
3106     jam();
3107     sendNDB_STTORRY(signal);
3108     break;
3109   }//switch
3110 }//execNDB_STTOR()
3111 
sendNDB_STTORRY(Signal * signal)3112 void Dbdict::sendNDB_STTORRY(Signal* signal)
3113 {
3114   signal->theData[0] = reference();
3115   sendSignal(NDBCNTR_REF, GSN_NDB_STTORRY, signal, 1, JBB);
3116   return;
3117 }//sendNDB_STTORRY()
3118 
3119 /* ---------------------------------------------------------------- */
3120 // We receive the information about which nodes that are up and down.
3121 /* ---------------------------------------------------------------- */
execREAD_NODESCONF(Signal * signal)3122 void Dbdict::execREAD_NODESCONF(Signal* signal)
3123 {
3124   jamEntry();
3125 
3126   ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
3127   c_numberNode   = readNodes->noOfNodes;
3128   c_masterNodeId = readNodes->masterNodeId;
3129 
3130   c_noNodesFailed = 0;
3131   c_aliveNodes.clear();
3132   for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
3133     jam();
3134     NodeRecordPtr nodePtr;
3135     c_nodes.getPtr(nodePtr, i);
3136 
3137     if (NdbNodeBitmask::get(readNodes->allNodes, i)) {
3138       jam();
3139       nodePtr.p->nodeState = NodeRecord::NDB_NODE_ALIVE;
3140       if (NdbNodeBitmask::get(readNodes->inactiveNodes, i)) {
3141 	jam();
3142 	/**-------------------------------------------------------------------
3143 	 *
3144 	 * THIS NODE IS DEFINED IN THE CLUSTER BUT IS NOT ALIVE CURRENTLY.
3145 	 * WE ADD THE NODE TO THE SET OF FAILED NODES AND ALSO SET THE
3146 	 * BLOCKSTATE TO BUSY TO AVOID ADDING TABLES WHILE NOT ALL NODES ARE
3147 	 * ALIVE.
3148 	 *------------------------------------------------------------------*/
3149         nodePtr.p->nodeState = NodeRecord::NDB_NODE_DEAD;
3150 	c_noNodesFailed++;
3151       } else {
3152 	c_aliveNodes.set(i);
3153       }
3154     }//if
3155   }//for
3156   sendNDB_STTORRY(signal);
3157 }//execREAD_NODESCONF()
3158 
initSchemaFile(Signal * signal)3159 void Dbdict::initSchemaFile(Signal* signal)
3160 {
3161   XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
3162   xsf->noOfPages = (c_noOfMetaTables + NDB_SF_PAGE_ENTRIES - 1)
3163                    / NDB_SF_PAGE_ENTRIES;
3164   initSchemaFile(xsf, 0, xsf->noOfPages, true);
3165   // init alt copy too for INR
3166   XSchemaFile * oldxsf = &c_schemaFile[SchemaRecord::OLD_SCHEMA_FILE];
3167   oldxsf->noOfPages = xsf->noOfPages;
3168   memcpy(&oldxsf->schemaPage[0], &xsf->schemaPage[0], xsf->schemaPage[0].FileSize);
3169 
3170   g_eventLogger->info("Schema file initialisation Starting");
3171 
3172   if (c_initialStart || c_initialNodeRestart) {
3173     jam();
3174     ndbrequire(c_writeSchemaRecord.inUse == false);
3175     c_writeSchemaRecord.inUse = true;
3176     c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
3177     c_writeSchemaRecord.newFile = true;
3178     c_writeSchemaRecord.firstPage = 0;
3179     c_writeSchemaRecord.noOfPages = xsf->noOfPages;
3180 
3181     c_writeSchemaRecord.m_callback.m_callbackFunction =
3182       safe_cast(&Dbdict::initSchemaFile_conf);
3183 
3184     startWriteSchemaFile(signal);
3185   } else if (c_systemRestart || c_nodeRestart) {
3186     jam();
3187     ndbrequire(c_readSchemaRecord.schemaReadState == ReadSchemaRecord::IDLE);
3188     c_readSchemaRecord.pageId = c_schemaRecord.oldSchemaPage;
3189     c_readSchemaRecord.firstPage = 0;
3190     c_readSchemaRecord.noOfPages = 1;
3191     c_readSchemaRecord.schemaReadState = ReadSchemaRecord::INITIAL_READ_HEAD;
3192     startReadSchemaFile(signal);
3193   } else {
3194     ndbrequire(false);
3195   }//if
3196 }//Dbdict::initSchemaFile()
3197 
3198 void
initSchemaFile_conf(Signal * signal,Uint32 callbackData,Uint32 rv)3199 Dbdict::initSchemaFile_conf(Signal* signal, Uint32 callbackData, Uint32 rv){
3200   jam();
3201   g_eventLogger->info("Schema file initialisation Completed");
3202   sendNDB_STTORRY(signal);
3203 }
3204 
3205 void
activateIndexes(Signal * signal,Uint32 id)3206 Dbdict::activateIndexes(Signal* signal, Uint32 id)
3207 {
3208   if (id == 0)
3209     D("activateIndexes start");
3210 
3211   Uint32 requestFlags = 0;
3212 
3213   switch (c_restartType) {
3214   case NodeState::ST_SYSTEM_RESTART:
3215     // activate in a distributed trans but do not build yet
3216     if (c_masterNodeId != getOwnNodeId()) {
3217       D("activateIndexes not master");
3218       goto out;
3219     }
3220     requestFlags |= DictSignal::RF_NO_BUILD;
3221     break;
3222   case NodeState::ST_NODE_RESTART:
3223   case NodeState::ST_INITIAL_NODE_RESTART:
3224     // activate on this node in a local trans
3225     requestFlags |= DictSignal::RF_LOCAL_TRANS;
3226     requestFlags |= DictSignal::RF_NO_BUILD;
3227     break;
3228   default:
3229     ndbrequire(false);
3230     break;
3231   }
3232 
3233   for (; id < c_noOfMetaTables; id++)
3234   {
3235     TableRecordPtr indexPtr;
3236     bool ok = find_object(indexPtr, id);
3237     if (!ok)
3238     {
3239       jam();
3240       continue;
3241     }
3242 
3243     if (check_read_obj(id))
3244     {
3245       continue;
3246     }
3247 
3248     if (!indexPtr.p->isIndex())
3249     {
3250       continue;
3251     }
3252 
3253     if ((requestFlags & DictSignal::RF_LOCAL_TRANS) &&
3254         indexPtr.p->indexState != TableRecord::IS_ONLINE)
3255     {
3256       jam();
3257       continue;
3258     }
3259 
3260     // wl3600_todo use simple schema trans when implemented
3261     D("activateIndexes id=" << id);
3262 
3263     TxHandlePtr tx_ptr;
3264     seizeTxHandle(tx_ptr);
3265     ndbrequire(!tx_ptr.isNull());
3266 
3267     tx_ptr.p->m_requestInfo = 0;
3268     tx_ptr.p->m_requestInfo |= requestFlags;
3269     tx_ptr.p->m_userData = indexPtr.i;
3270 
3271     Callback c = {
3272       safe_cast(&Dbdict::activateIndex_fromBeginTrans),
3273       tx_ptr.p->tx_key
3274     };
3275     tx_ptr.p->m_callback = c;
3276     beginSchemaTrans(signal, tx_ptr);
3277     return;
3278   }
3279 
3280   D("activateIndexes done");
3281 #ifdef VM_TRACE
3282   check_consistency();
3283 #endif
3284 out:
3285 
3286   if (c_systemRestart)
3287   {
3288     infoEvent("Restore dictionary information from disk Completed");
3289   }
3290   else
3291   {
3292     g_eventLogger->info("Copying of dictionary information"
3293                         " from master Completed");
3294   }
3295 
3296   signal->theData[0] = reference();
3297   signal->theData[1] = c_restartRecord.m_senderData;
3298   sendSignal(c_restartRecord.returnBlockRef, GSN_DICTSTARTCONF,
3299 	     signal, 2, JBB);
3300 }
3301 
3302 void
activateIndex_fromBeginTrans(Signal * signal,Uint32 tx_key,Uint32 ret)3303 Dbdict::activateIndex_fromBeginTrans(Signal* signal, Uint32 tx_key, Uint32 ret)
3304 {
3305   D("activateIndex_fromBeginTrans" << V(tx_key) << V(ret));
3306 
3307   ndbrequire(ret == 0); //wl3600_todo
3308 
3309   TxHandlePtr tx_ptr;
3310   findTxHandle(tx_ptr, tx_key);
3311   ndbrequire(!tx_ptr.isNull());
3312 
3313   TableRecordPtr indexPtr;
3314   c_tableRecordPool_.getPtr(indexPtr, tx_ptr.p->m_userData);
3315   ndbrequire(!indexPtr.isNull());
3316   DictObjectPtr index_obj_ptr;
3317   c_obj_pool.getPtr(index_obj_ptr, indexPtr.p->m_obj_ptr_i);
3318 
3319   AlterIndxReq* req = (AlterIndxReq*)signal->getDataPtrSend();
3320 
3321   Uint32 requestInfo = 0;
3322   DictSignal::setRequestType(requestInfo, AlterIndxImplReq::AlterIndexOnline);
3323   DictSignal::addRequestFlagsGlobal(requestInfo, tx_ptr.p->m_requestInfo);
3324 
3325   req->clientRef = reference();
3326   req->clientData = tx_ptr.p->tx_key;
3327   req->transId = tx_ptr.p->m_transId;
3328   req->transKey = tx_ptr.p->m_transKey;
3329   req->requestInfo = requestInfo;
3330   req->indexId = index_obj_ptr.p->m_id;
3331   req->indexVersion = indexPtr.p->tableVersion;
3332 
3333   Callback c = {
3334     safe_cast(&Dbdict::activateIndex_fromAlterIndex),
3335     tx_ptr.p->tx_key
3336   };
3337   tx_ptr.p->m_callback = c;
3338 
3339   sendSignal(reference(), GSN_ALTER_INDX_REQ, signal,
3340              AlterIndxReq::SignalLength, JBB);
3341 }
3342 
3343 void
activateIndex_fromAlterIndex(Signal * signal,Uint32 tx_key,Uint32 ret)3344 Dbdict::activateIndex_fromAlterIndex(Signal* signal, Uint32 tx_key, Uint32 ret)
3345 {
3346   D("activateIndex_fromAlterIndex" << V(tx_key) << V(ret));
3347 
3348   ndbrequire(ret == 0); // wl3600_todo
3349 
3350   TxHandlePtr tx_ptr;
3351   findTxHandle(tx_ptr, tx_key);
3352   ndbrequire(!tx_ptr.isNull());
3353 
3354   if (ret != 0)
3355     setError(tx_ptr.p->m_error, ret, __LINE__);
3356 
3357   Callback c = {
3358     safe_cast(&Dbdict::activateIndex_fromEndTrans),
3359     tx_ptr.p->tx_key
3360   };
3361   tx_ptr.p->m_callback = c;
3362 
3363   Uint32 flags = 0;
3364   if (hasError(tx_ptr.p->m_error))
3365     flags |= SchemaTransEndReq::SchemaTransAbort;
3366   endSchemaTrans(signal, tx_ptr, flags);
3367 }
3368 
3369 void
activateIndex_fromEndTrans(Signal * signal,Uint32 tx_key,Uint32 ret)3370 Dbdict::activateIndex_fromEndTrans(Signal* signal, Uint32 tx_key, Uint32 ret)
3371 {
3372   D("activateIndex_fromEndTrans" << V(tx_key) << V(ret));
3373 
3374   ndbrequire(ret == 0); //wl3600_todo
3375 
3376   TxHandlePtr tx_ptr;
3377   findTxHandle(tx_ptr, tx_key);
3378   ndbrequire(!tx_ptr.isNull());
3379 
3380   TableRecordPtr indexPtr;
3381   c_tableRecordPool_.getPtr(indexPtr, tx_ptr.p->m_userData);
3382   DictObjectPtr index_obj_ptr;
3383   c_obj_pool.getPtr(index_obj_ptr, indexPtr.p->m_obj_ptr_i);
3384 
3385   char indexName[MAX_TAB_NAME_SIZE];
3386   {
3387     LocalRope name(c_rope_pool, index_obj_ptr.p->m_name);
3388     name.copy(indexName);
3389   }
3390 
3391   ErrorInfo error = tx_ptr.p->m_error;
3392   if (!hasError(error))
3393   {
3394     jam();
3395     infoEvent("DICT: activate index %u done (%s)",
3396              index_obj_ptr.p->m_id, indexName);
3397   }
3398   else
3399   {
3400     jam();
3401     warningEvent("DICT: activate index %u error: code=%u line=%u node=%u (%s)",
3402                 index_obj_ptr.p->m_id,
3403 		 error.errorCode, error.errorLine, error.errorNodeId,
3404 		 indexName);
3405   }
3406 
3407   Uint32 id = index_obj_ptr.p->m_id;
3408   releaseTxHandle(tx_ptr);
3409   activateIndexes(signal, id + 1);
3410 }
3411 
3412 void
rebuildIndexes(Signal * signal,Uint32 id)3413 Dbdict::rebuildIndexes(Signal* signal, Uint32 id)
3414 {
3415   if (id == 0)
3416     D("rebuildIndexes start");
3417 
3418   TableRecordPtr indexPtr;
3419   for (; id < c_noOfMetaTables; id++) {
3420     bool ok = find_object(indexPtr, id);
3421     if (!ok)
3422     {
3423       jam();
3424       continue;
3425     }
3426     if (check_read_obj(id))
3427       continue;
3428     if (!indexPtr.p->isIndex())
3429       continue;
3430 
3431     // wl3600_todo use simple schema trans when implemented
3432     D("rebuildIndexes id=" << id);
3433 
3434     TxHandlePtr tx_ptr;
3435     seizeTxHandle(tx_ptr);
3436     ndbrequire(!tx_ptr.isNull());
3437 
3438     Uint32 requestInfo = 0;
3439     if (indexPtr.p->m_bits & TableRecord::TR_Logged) {
3440       // only sets index online - the flag propagates to trans and ops
3441       requestInfo |= DictSignal::RF_NO_BUILD;
3442     }
3443     tx_ptr.p->m_requestInfo = requestInfo;
3444     tx_ptr.p->m_userData = indexPtr.i;
3445 
3446     Callback c = {
3447       safe_cast(&Dbdict::rebuildIndex_fromBeginTrans),
3448       tx_ptr.p->tx_key
3449     };
3450     tx_ptr.p->m_callback = c;
3451     beginSchemaTrans(signal, tx_ptr);
3452     return;
3453   }
3454 
3455   D("rebuildIndexes done");
3456   sendNDB_STTORRY(signal);
3457 }
3458 
3459 void
rebuildIndex_fromBeginTrans(Signal * signal,Uint32 tx_key,Uint32 ret)3460 Dbdict::rebuildIndex_fromBeginTrans(Signal* signal, Uint32 tx_key, Uint32 ret)
3461 {
3462   D("rebuildIndex_fromBeginTrans" << V(tx_key) << V(ret));
3463 
3464   ndbrequire(ret == 0); //wl3600_todo
3465 
3466   TxHandlePtr tx_ptr;
3467   findTxHandle(tx_ptr, tx_key);
3468   ndbrequire(!tx_ptr.isNull());
3469 
3470   TableRecordPtr indexPtr;
3471   c_tableRecordPool_.getPtr(indexPtr, tx_ptr.p->m_userData);
3472   DictObjectPtr index_obj_ptr;
3473   c_obj_pool.getPtr(index_obj_ptr,indexPtr.p->m_obj_ptr_i);
3474 
3475   BuildIndxReq* req = (BuildIndxReq*)signal->getDataPtrSend();
3476 
3477   Uint32 requestInfo = 0;
3478   DictSignal::setRequestType(requestInfo, BuildIndxReq::MainOp);
3479   DictSignal::addRequestFlagsGlobal(requestInfo, tx_ptr.p->m_requestInfo);
3480 
3481   req->clientRef = reference();
3482   req->clientData = tx_ptr.p->tx_key;
3483   req->transId = tx_ptr.p->m_transId;
3484   req->transKey = tx_ptr.p->m_transKey;
3485   req->requestInfo = requestInfo;
3486   req->buildId = 0;
3487   req->buildKey = 0;
3488   req->tableId = indexPtr.p->primaryTableId;
3489   req->indexId = index_obj_ptr.p->m_id;
3490   req->indexType = indexPtr.p->tableType;
3491   req->parallelism = 16;
3492 
3493   Callback c = {
3494     safe_cast(&Dbdict::rebuildIndex_fromBuildIndex),
3495     tx_ptr.p->tx_key
3496   };
3497   tx_ptr.p->m_callback = c;
3498 
3499   sendSignal(reference(), GSN_BUILDINDXREQ, signal,
3500              BuildIndxReq::SignalLength, JBB);
3501 }
3502 
3503 void
rebuildIndex_fromBuildIndex(Signal * signal,Uint32 tx_key,Uint32 ret)3504 Dbdict::rebuildIndex_fromBuildIndex(Signal* signal, Uint32 tx_key, Uint32 ret)
3505 {
3506   D("rebuildIndex_fromBuildIndex" << V(tx_key) << V(ret));
3507 
3508   ndbrequire(ret == 0); //wl3600_todo
3509 
3510   TxHandlePtr tx_ptr;
3511   findTxHandle(tx_ptr, tx_key);
3512   ndbrequire(!tx_ptr.isNull());
3513 
3514   if (ret != 0)
3515     setError(tx_ptr.p->m_error, ret, __LINE__);
3516 
3517   Callback c = {
3518     safe_cast(&Dbdict::rebuildIndex_fromEndTrans),
3519     tx_ptr.p->tx_key
3520   };
3521   tx_ptr.p->m_callback = c;
3522 
3523   Uint32 flags = 0;
3524   if (hasError(tx_ptr.p->m_error))
3525     flags |= SchemaTransEndReq::SchemaTransAbort;
3526   endSchemaTrans(signal, tx_ptr, flags);
3527 }
3528 
3529 void
rebuildIndex_fromEndTrans(Signal * signal,Uint32 tx_key,Uint32 ret)3530 Dbdict::rebuildIndex_fromEndTrans(Signal* signal, Uint32 tx_key, Uint32 ret)
3531 {
3532   D("rebuildIndex_fromEndTrans" << V(tx_key) << V(ret));
3533 
3534   ndbrequire(ret == 0); //wl3600_todo
3535 
3536   TxHandlePtr tx_ptr;
3537   findTxHandle(tx_ptr, tx_key);
3538   ndbrequire(!tx_ptr.isNull());
3539 
3540   TableRecordPtr indexPtr;
3541   c_tableRecordPool_.getPtr(indexPtr, tx_ptr.p->m_userData);
3542 
3543   const char* actionName;
3544   {
3545     Uint32 requestInfo = tx_ptr.p->m_requestInfo;
3546     bool noBuild = (requestInfo & DictSignal::RF_NO_BUILD);
3547     actionName = !noBuild ? "rebuild" : "online";
3548   }
3549 
3550   DictObjectPtr obj_ptr;
3551   c_obj_pool.getPtr(obj_ptr, indexPtr.p->m_obj_ptr_i);
3552 
3553   char indexName[MAX_TAB_NAME_SIZE];
3554   {
3555     LocalRope name(c_rope_pool, obj_ptr.p->m_name);
3556     name.copy(indexName);
3557   }
3558 
3559   ErrorInfo error = tx_ptr.p->m_error;
3560   if (!hasError(error)) {
3561     jam();
3562     infoEvent(
3563         "DICT: %s index %u done (%s)",
3564         actionName, obj_ptr.p->m_id, indexName);
3565   } else {
3566     jam();
3567     warningEvent(
3568         "DICT: %s index %u error: code=%u line=%u node=%u (%s)",
3569         actionName,
3570         obj_ptr.p->m_id, error.errorCode, error.errorLine, error.errorNodeId,
3571         indexName);
3572   }
3573 
3574   Uint32 id = obj_ptr.p->m_id;
3575   releaseTxHandle(tx_ptr);
3576 
3577   rebuildIndexes(signal, id + 1);
3578 }
3579 
3580 /*
3581  * Activate FKs i.e. create child and parent triggers.
3582  * This is done as a local trans in both NR and SR.
3583  * There is no AlterFK so just re-run parts of CreateFK.
3584  * Existing data is not validated.
3585  */
3586 
3587 void
enableFKs(Signal * signal,Uint32 id)3588 Dbdict::enableFKs(Signal* signal, Uint32 id)
3589 {
3590   if (id == 0)
3591   {
3592     D("enableFKs start");
3593     ndbrequire(c_restart_enable_fks == false);
3594     c_restart_enable_fks = true;
3595   }
3596 
3597   Uint32 requestFlags = 0;
3598   requestFlags |= DictSignal::RF_LOCAL_TRANS;
3599   requestFlags |= DictSignal::RF_NO_BUILD;
3600 
3601   Ptr<ForeignKeyRec> fk_ptr;
3602   for (; id < c_noOfMetaTables; id++)
3603   {
3604     bool ok = find_object(fk_ptr, id);
3605     D(V(id) << V(ok));
3606     if (!ok)
3607     {
3608       jam();
3609       continue;
3610     }
3611     if (check_read_obj(id))
3612     {
3613       jam();
3614       continue;
3615     }
3616 
3617     D("enableFKs id=" << id);
3618 
3619     TxHandlePtr tx_ptr;
3620     seizeTxHandle(tx_ptr);
3621     ndbrequire(!tx_ptr.isNull());
3622 
3623     tx_ptr.p->m_requestInfo = 0;
3624     tx_ptr.p->m_requestInfo |= requestFlags;
3625     tx_ptr.p->m_userData = fk_ptr.i;
3626 
3627     Callback c = {
3628       safe_cast(&Dbdict::enableFK_fromBeginTrans),
3629       tx_ptr.p->tx_key
3630     };
3631     tx_ptr.p->m_callback = c;
3632     beginSchemaTrans(signal, tx_ptr);
3633     return;
3634   }
3635 
3636   c_restart_enable_fks = false;
3637   D("enableFKs done");
3638   g_eventLogger->info("Foreign key enabling Completed");
3639   sendNDB_STTORRY(signal);
3640 }
3641 
3642 void
enableFK_fromBeginTrans(Signal * signal,Uint32 tx_key,Uint32 ret)3643 Dbdict::enableFK_fromBeginTrans(Signal* signal, Uint32 tx_key, Uint32 ret)
3644 {
3645   D("enableFK_fromBeginTrans" << V(tx_key) << V(ret));
3646 
3647   ndbrequire(ret == 0); //wl6244_todo
3648 
3649   TxHandlePtr tx_ptr;
3650   findTxHandle(tx_ptr, tx_key);
3651   ndbrequire(!tx_ptr.isNull());
3652 
3653   Ptr<ForeignKeyRec> fk_ptr;
3654   c_fk_pool.getPtr(fk_ptr, tx_ptr.p->m_userData);
3655   ndbrequire(!fk_ptr.isNull());
3656   DictObjectPtr fk_obj_ptr;
3657   c_obj_pool.getPtr(fk_obj_ptr, fk_ptr.p->m_obj_ptr_i);
3658 
3659   CreateFKReq* req = (CreateFKReq*)signal->getDataPtrSend();
3660 
3661   Uint32 requestInfo = 0;
3662   DictSignal::addRequestFlagsGlobal(requestInfo, tx_ptr.p->m_requestInfo);
3663 
3664   req->clientData =tx_ptr.p->tx_key;
3665   req->clientRef = reference();
3666   req->requestInfo = requestInfo;
3667   req->transId = tx_ptr.p->m_transId;
3668   req->transKey = tx_ptr.p->m_transKey;
3669 
3670   Uint32* wbuffer = &c_indexPage.word[0];
3671   LinearWriter w(wbuffer, sizeof(c_indexPage) >> 2);
3672   packFKIntoPages(w, fk_ptr);
3673   LinearSectionPtr lsPtr[3];
3674   lsPtr[0].p = wbuffer;
3675   lsPtr[0].sz = w.getWordsUsed();
3676 
3677   Callback c = {
3678     safe_cast(&Dbdict::enableFK_fromCreateFK),
3679     tx_ptr.p->tx_key
3680   };
3681   tx_ptr.p->m_callback = c;
3682 
3683   sendSignal(reference(), GSN_CREATE_FK_REQ, signal,
3684              CreateFKReq::SignalLength, JBB, lsPtr, 1);
3685 }
3686 
3687 void
enableFK_fromCreateFK(Signal * signal,Uint32 tx_key,Uint32 ret)3688 Dbdict::enableFK_fromCreateFK(Signal* signal, Uint32 tx_key, Uint32 ret)
3689 {
3690   D("enableFK_fromCreateFK");
3691 
3692   ndbrequire(ret == 0); //wl6244_todo
3693 
3694   TxHandlePtr tx_ptr;
3695   findTxHandle(tx_ptr, tx_key);
3696   ndbrequire(!tx_ptr.isNull());
3697 
3698   if (ret != 0)
3699     setError(tx_ptr.p->m_error, ret, __LINE__);
3700 
3701   Callback c = {
3702     safe_cast(&Dbdict::enableFK_fromEndTrans),
3703     tx_ptr.p->tx_key
3704   };
3705   tx_ptr.p->m_callback = c;
3706 
3707   Uint32 flags = 0;
3708   if (hasError(tx_ptr.p->m_error))
3709     flags |= SchemaTransEndReq::SchemaTransAbort;
3710   endSchemaTrans(signal, tx_ptr, flags);
3711 }
3712 
3713 void
enableFK_fromEndTrans(Signal * signal,Uint32 tx_key,Uint32 ret)3714 Dbdict::enableFK_fromEndTrans(Signal* signal, Uint32 tx_key, Uint32 ret)
3715 {
3716   D("enableFK_fromEndTrans" << V(tx_key) << V(ret));
3717 
3718   ndbrequire(ret == 0); //wl6244_todo
3719 
3720   TxHandlePtr tx_ptr;
3721   findTxHandle(tx_ptr, tx_key);
3722   ndbrequire(!tx_ptr.isNull());
3723 
3724   Ptr<ForeignKeyRec> fk_ptr;
3725   c_fk_pool.getPtr(fk_ptr, tx_ptr.p->m_userData);
3726   DictObjectPtr fk_obj_ptr;
3727   c_obj_pool.getPtr(fk_obj_ptr, fk_ptr.p->m_obj_ptr_i);
3728 
3729   char fk_name[MAX_TAB_NAME_SIZE];
3730   {
3731     LocalRope name(c_rope_pool, fk_obj_ptr.p->m_name);
3732     name.copy(fk_name);
3733   }
3734 
3735   ErrorInfo error = tx_ptr.p->m_error;
3736   if (!hasError(error))
3737   {
3738     jam();
3739     infoEvent("DICT: enable FK %u done (%s)",
3740              fk_obj_ptr.p->m_id, fk_name);
3741   }
3742   else
3743   {
3744     jam();
3745     warningEvent("DICT: enable FK %u error: code=%u line=%u node=%u (%s)",
3746                  fk_obj_ptr.p->m_id,
3747 		 error.errorCode, error.errorLine, error.errorNodeId,
3748 		 fk_name);
3749   }
3750 
3751   Uint32 id = fk_obj_ptr.p->m_id;
3752   releaseTxHandle(tx_ptr);
3753   enableFKs(signal, id + 1);
3754 }
3755 
3756 /* **************************************************************** */
3757 /* ---------------------------------------------------------------- */
3758 /* MODULE:          SYSTEM RESTART MODULE ------------------------- */
3759 /* ---------------------------------------------------------------- */
3760 /*                                                                  */
3761 /* This module contains code specific for system restart            */
3762 /* ---------------------------------------------------------------- */
3763 /* **************************************************************** */
3764 
3765 /* ---------------------------------------------------------------- */
3766 // DIH asks DICT to read in table data from disk during system
3767 // restart. DIH also asks DICT to send information about which
3768 // tables that should be started as part of this system restart.
3769 // DICT will also activate the tables in TC as part of this process.
3770 /* ---------------------------------------------------------------- */
execDICTSTARTREQ(Signal * signal)3771 void Dbdict::execDICTSTARTREQ(Signal* signal)
3772 {
3773   jamEntry();
3774   c_restartRecord.gciToRestart = signal->theData[0];
3775   c_restartRecord.returnBlockRef = signal->theData[1];
3776   c_restartRecord.m_senderData = signal->theData[2];
3777   if (signal->getLength() < DictStartReq::SignalLength)
3778   {
3779     jam();
3780     c_restartRecord.m_senderData = 0;
3781   }
3782   if (c_nodeRestart || c_initialNodeRestart) {
3783     jam();
3784 
3785     CRASH_INSERTION(6000);
3786 
3787     g_eventLogger->info("Copying of dictionary information"
3788                         " from master Starting");
3789 
3790     BlockReference dictRef = calcDictBlockRef(c_masterNodeId);
3791     signal->theData[0] = getOwnNodeId();
3792     sendSignal(dictRef, GSN_GET_SCHEMA_INFOREQ, signal, 1, JBB);
3793     return;
3794   }
3795   ndbrequire(c_systemRestart);
3796   ndbrequire(c_masterNodeId == getOwnNodeId());
3797 
3798   infoEvent("Restore dictionary information from disk Starting");
3799 
3800   c_schemaRecord.m_callback.m_callbackData = 0;
3801   c_schemaRecord.m_callback.m_callbackFunction =
3802     safe_cast(&Dbdict::masterRestart_checkSchemaStatusComplete);
3803 
3804   /**
3805    * master has same new/old schema file...
3806    *   copy old(read from disk) to new
3807    */
3808   {
3809     XSchemaFile * oldxsf = &c_schemaFile[SchemaRecord::OLD_SCHEMA_FILE];
3810     checkPendingSchemaTrans(oldxsf);
3811     XSchemaFile * newxsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
3812     newxsf->noOfPages = oldxsf->noOfPages;
3813     memcpy(&newxsf->schemaPage[0],
3814            &oldxsf->schemaPage[0],
3815            oldxsf->schemaPage[0].FileSize);
3816   }
3817 
3818   Callback cb =
3819     { safe_cast(&Dbdict::masterRestart_checkSchemaStatusComplete), 0 };
3820   startRestoreSchema(signal, cb);
3821 }//execDICTSTARTREQ()
3822 
3823 void
masterRestart_checkSchemaStatusComplete(Signal * signal,Uint32 callbackData,Uint32 returnCode)3824 Dbdict::masterRestart_checkSchemaStatusComplete(Signal* signal,
3825 						Uint32 callbackData,
3826 						Uint32 returnCode)
3827 {
3828   XSchemaFile * oldxsf = &c_schemaFile[SchemaRecord::OLD_SCHEMA_FILE];
3829   ndbrequire(oldxsf->noOfPages != 0);
3830 
3831   LinearSectionPtr ptr[3];
3832   ptr[0].p = (Uint32*)&oldxsf->schemaPage[0];
3833   ptr[0].sz = oldxsf->noOfPages * NDB_SF_PAGE_SIZE_IN_WORDS;
3834 
3835   c_sendSchemaRecord.m_SCHEMAINFO_Counter = c_aliveNodes;
3836   NodeReceiverGroup rg(DBDICT, c_aliveNodes);
3837 
3838   rg.m_nodes.clear(getOwnNodeId());
3839   Callback c = { 0, 0 };
3840   sendFragmentedSignal(rg,
3841 		       GSN_SCHEMA_INFO,
3842 		       signal,
3843 		       1, //SchemaInfo::SignalLength,
3844 		       JBB,
3845 		       ptr,
3846 		       1,
3847 		       c);
3848 
3849   XSchemaFile * newxsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
3850   newxsf->noOfPages = oldxsf->noOfPages;
3851   memcpy(&newxsf->schemaPage[0], &oldxsf->schemaPage[0],
3852          oldxsf->noOfPages * NDB_SF_PAGE_SIZE);
3853 
3854   signal->theData[0] = getOwnNodeId();
3855   sendSignal(reference(), GSN_SCHEMA_INFOCONF, signal, 1, JBB);
3856 }
3857 
3858 void
execGET_SCHEMA_INFOREQ(Signal * signal)3859 Dbdict::execGET_SCHEMA_INFOREQ(Signal* signal){
3860 
3861   const Uint32 ref = signal->getSendersBlockRef();
3862   //const Uint32 senderData = signal->theData[0];
3863 
3864   ndbrequire(c_sendSchemaRecord.inUse == false);
3865   c_sendSchemaRecord.inUse = true;
3866 
3867   LinearSectionPtr ptr[3];
3868 
3869   XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
3870   ndbrequire(xsf->noOfPages != 0);
3871 
3872   ptr[0].p = (Uint32*)&xsf->schemaPage[0];
3873   ptr[0].sz = xsf->noOfPages * NDB_SF_PAGE_SIZE_IN_WORDS;
3874 
3875   Callback c = { safe_cast(&Dbdict::sendSchemaComplete), 0 };
3876   sendFragmentedSignal(ref,
3877 		       GSN_SCHEMA_INFO,
3878 		       signal,
3879 		       1, //GetSchemaInfoConf::SignalLength,
3880 		       JBB,
3881 		       ptr,
3882 		       1,
3883 		       c);
3884 }//Dbdict::execGET_SCHEMA_INFOREQ()
3885 
3886 void
sendSchemaComplete(Signal * signal,Uint32 callbackData,Uint32 returnCode)3887 Dbdict::sendSchemaComplete(Signal * signal,
3888 			   Uint32 callbackData,
3889 			   Uint32 returnCode){
3890   ndbrequire(c_sendSchemaRecord.inUse == true);
3891   c_sendSchemaRecord.inUse = false;
3892 
3893 }
3894 
3895 
3896 /* ---------------------------------------------------------------- */
3897 // We receive the schema info from master as part of all restarts
3898 // except the initial start where no tables exists.
3899 /* ---------------------------------------------------------------- */
execSCHEMA_INFO(Signal * signal)3900 void Dbdict::execSCHEMA_INFO(Signal* signal)
3901 {
3902   jamEntry();
3903   if(!assembleFragments(signal)){
3904     jam();
3905     return;
3906   }
3907 
3908   if(getNodeState().getNodeRestartInProgress()){
3909     CRASH_INSERTION(6001);
3910   }
3911 
3912   {
3913     /**
3914      * Copy "own" into new
3915      */
3916     XSchemaFile * oldxsf = &c_schemaFile[SchemaRecord::OLD_SCHEMA_FILE];
3917     XSchemaFile * newxsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
3918     memcpy(&newxsf->schemaPage[0],
3919            &oldxsf->schemaPage[0],
3920            oldxsf->schemaPage[0].FileSize);
3921   }
3922 
3923   SectionHandle handle(this, signal);
3924   SegmentedSectionPtr schemaDataPtr;
3925   handle.getSection(schemaDataPtr, 0);
3926 
3927   XSchemaFile * xsf = &c_schemaFile[SchemaRecord::OLD_SCHEMA_FILE];
3928   ndbrequire(schemaDataPtr.sz % NDB_SF_PAGE_SIZE_IN_WORDS == 0);
3929   xsf->noOfPages = schemaDataPtr.sz / NDB_SF_PAGE_SIZE_IN_WORDS;
3930   copy((Uint32*)&xsf->schemaPage[0], schemaDataPtr);
3931   releaseSections(handle);
3932 
3933   SchemaFile * sf0 = &xsf->schemaPage[0];
3934   if (sf0->NdbVersion < NDB_SF_VERSION_5_0_6) {
3935     bool ok = convertSchemaFileTo_5_0_6(xsf);
3936     ndbrequire(ok);
3937   }
3938 
3939   if (sf0->NdbVersion < NDB_MAKE_VERSION(6,4,0))
3940   {
3941     jam();
3942     bool ok = convertSchemaFileTo_6_4(xsf);
3943     ndbrequire(ok);
3944   }
3945 
3946   validateChecksum(xsf);
3947 
3948   XSchemaFile * ownxsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
3949   checkPendingSchemaTrans(ownxsf);
3950   resizeSchemaFile(xsf, ownxsf->noOfPages);
3951 
3952   ndbrequire(signal->getSendersBlockRef() != reference());
3953 
3954   /* ---------------------------------------------------------------- */
3955   // Synchronise our view on data with other nodes in the cluster.
3956   // This is an important part of restart handling where we will handle
3957   // cases where the table have been added but only partially, where
3958   // tables have been deleted but not completed the deletion yet and
3959   // other scenarios needing synchronisation.
3960   /* ---------------------------------------------------------------- */
3961   Callback cb =
3962     { safe_cast(&Dbdict::restart_checkSchemaStatusComplete), 0 };
3963   startRestoreSchema(signal, cb);
3964 }//execSCHEMA_INFO()
3965 
3966 void
restart_checkSchemaStatusComplete(Signal * signal,Uint32 callbackData,Uint32 returnCode)3967 Dbdict::restart_checkSchemaStatusComplete(Signal * signal,
3968 					  Uint32 callbackData,
3969 					  Uint32 returnCode)
3970 {
3971   jam();
3972 
3973   if(c_systemRestart)
3974   {
3975     jam();
3976     signal->theData[0] = getOwnNodeId();
3977     sendSignal(calcDictBlockRef(c_masterNodeId), GSN_SCHEMA_INFOCONF,
3978 	       signal, 1, JBB);
3979     return;
3980   }
3981 
3982   ndbrequire(c_restartRecord.m_op_cnt == 0);
3983   ndbrequire(c_nodeRestart || c_initialNodeRestart);
3984   activateIndexes(signal, 0);
3985   return;
3986 }
3987 
execSCHEMA_INFOCONF(Signal * signal)3988 void Dbdict::execSCHEMA_INFOCONF(Signal* signal)
3989 {
3990   jamEntry();
3991   ndbrequire(signal->getNoOfSections() == 0);
3992 
3993 /* ---------------------------------------------------------------- */
3994 // This signal is received in the master as part of system restart
3995 // from all nodes (including the master) after they have synchronised
3996 // their data with the master node's schema information.
3997 /* ---------------------------------------------------------------- */
3998   const Uint32 nodeId = signal->theData[0];
3999   c_sendSchemaRecord.m_SCHEMAINFO_Counter.clearWaitingFor(nodeId);
4000 
4001   if (!c_sendSchemaRecord.m_SCHEMAINFO_Counter.done()){
4002     jam();
4003     return;
4004   }//if
4005   activateIndexes(signal, 0);
4006 }//execSCHEMA_INFOCONF()
4007 
4008 static bool
checkSchemaStatus(Uint32 tableType,Uint32 pass)4009 checkSchemaStatus(Uint32 tableType, Uint32 pass)
4010 {
4011   switch(tableType){
4012   case DictTabInfo::UndefTableType:
4013     return true;
4014   case DictTabInfo::HashIndexTrigger:
4015   case DictTabInfo::SubscriptionTrigger:
4016   case DictTabInfo::ReadOnlyConstraint:
4017   case DictTabInfo::IndexTrigger:
4018     return false;
4019   case DictTabInfo::LogfileGroup:
4020     return pass == 0 || pass == 13 || pass == 14;
4021   case DictTabInfo::Tablespace:
4022     return pass == 1 || pass == 12 || pass == 15;
4023   case DictTabInfo::Datafile:
4024   case DictTabInfo::Undofile:
4025     return pass == 2 || pass == 11 || pass == 16;
4026   case DictTabInfo::HashMap:
4027     return pass == 3 || pass == 10 || pass == 17;
4028   case DictTabInfo::SystemTable:
4029   case DictTabInfo::UserTable:
4030     return /* pass == 4 || pass == 9 || */ pass == 18;
4031   case DictTabInfo::UniqueHashIndex:
4032   case DictTabInfo::HashIndex:
4033   case DictTabInfo::UniqueOrderedIndex:
4034   case DictTabInfo::OrderedIndex:
4035     return /* pass == 5 || pass == 8 || */ pass == 19;
4036   case DictTabInfo::ForeignKey:
4037     return pass == 6 || pass == 7 || pass == 20;
4038   }
4039 
4040   return false;
4041 }
4042 
4043 static const Uint32 CREATE_OLD_PASS = 6;
4044 static const Uint32 DROP_OLD_PASS = 13;
4045 static const Uint32 CREATE_NEW_PASS = 20;
4046 static const Uint32 LAST_PASS = 20;
4047 
4048 NdbOut&
operator <<(NdbOut & out,const SchemaFile::TableEntry entry)4049 operator<<(NdbOut& out, const SchemaFile::TableEntry entry)
4050 {
4051   out << "[";
4052   out << " state: " << entry.m_tableState;
4053   out << " version: " << hex << entry.m_tableVersion << dec;
4054   out << " type: " << entry.m_tableType;
4055   out << " words: " << entry.m_info_words;
4056   out << " gcp: " << entry.m_gcp;
4057   out << " trans: " << entry.m_transId;
4058   out << " ]";
4059   return out;
4060 }
4061 
initRestartRecord(Uint32 startpass,Uint32 lastpass,const char * sb,const char * eb)4062 void Dbdict::initRestartRecord(Uint32 startpass, Uint32 lastpass,
4063                                const char * sb, const char * eb)
4064 {
4065   c_restartRecord.gciToRestart = 0;
4066   c_restartRecord.activeTable = 0;
4067   c_restartRecord.m_op_cnt = 0;
4068   if (startpass == 0 && lastpass == 0)
4069   {
4070     jam();
4071     c_restartRecord.m_pass = 0;
4072     c_restartRecord.m_end_pass = LAST_PASS;
4073     c_restartRecord.m_start_banner = "Starting to restore schema";
4074     c_restartRecord.m_end_banner = "Restore of schema complete";
4075   }
4076   else
4077   {
4078     jam();
4079     c_restartRecord.m_pass = startpass;
4080     c_restartRecord.m_end_pass = lastpass;
4081     c_restartRecord.m_start_banner = sb;
4082     c_restartRecord.m_end_banner = eb;
4083   }
4084 }//Dbdict::initRestartRecord()
4085 
4086 /**
4087  * Pass 0 Create old LogfileGroup
4088  * Pass 1 Create old Tablespace
4089  * Pass 2 Create old Datafile/Undofile
4090  * Pass 3 Create old HashMap
4091  * Pass 4 Create old Table           // NOT DONE DUE TO DIH
4092  * Pass 5 Create old Index           // NOT DONE DUE TO DIH
4093  * Pass 6 Create old ForeignKey
4094 
4095  * Pass 7 Drop old ForeignKey
4096  * Pass 8 Drop old Index             // NOT DONE DUE TO DIH
4097  * Pass 9 Drop old Table             // NOT DONE DUE TO DIH
4098  * Pass 10 Drop old HashMap
4099  * Pass 11 Drop old Datafile/Undofile
4100  * Pass 12 Drop old Tablespace
4101  * Pass 13 Drop old Logfilegroup
4102 
4103  * Pass 14 Create new LogfileGroup
4104  * Pass 15 Create new Tablespace
4105  * Pass 16 Create new Datafile/Undofile
4106  * Pass 17 Create new HashMap
4107  * Pass 18 Create new Table
4108  * Pass 19 Create new Index
4109  * Pass 20 Create new ForeignKey
4110  */
4111 
checkSchemaStatus(Signal * signal)4112 void Dbdict::checkSchemaStatus(Signal* signal)
4113 {
4114   // masterxsf == schema file of master (i.e what's currently in cluster)
4115   // ownxsf = schema file read from disk
4116   XSchemaFile * masterxsf = &c_schemaFile[SchemaRecord::OLD_SCHEMA_FILE];
4117   XSchemaFile * ownxsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
4118 
4119   ndbrequire(masterxsf->noOfPages == ownxsf->noOfPages);
4120   const Uint32 noOfEntries = masterxsf->noOfPages * NDB_SF_PAGE_ENTRIES;
4121 
4122   for (; c_restartRecord.activeTable < noOfEntries;
4123        c_restartRecord.activeTable++)
4124   {
4125     jam();
4126 
4127     Uint32 tableId = c_restartRecord.activeTable;
4128     SchemaFile::TableEntry *masterEntry = getTableEntry(masterxsf, tableId);
4129     SchemaFile::TableEntry *ownEntry = getTableEntry(ownxsf, tableId);
4130     SchemaFile::EntryState masterState =
4131       (SchemaFile::EntryState)masterEntry->m_tableState;
4132     SchemaFile::EntryState ownState =
4133       (SchemaFile::EntryState)ownEntry->m_tableState;
4134 
4135     if (c_restartRecord.activeTable >= c_noOfMetaTables)
4136     {
4137       jam();
4138       ndbrequire(masterState == SchemaFile::SF_UNUSED);
4139       ndbrequire(ownState == SchemaFile::SF_UNUSED);
4140       continue;
4141     }//if
4142 
4143     D("checkSchemaStatus" << V(c_restartRecord.m_pass) << V(c_restartRecord.activeTable));
4144     D("own" << *ownEntry);
4145     D("mst" << *masterEntry);
4146 
4147 //#define PRINT_SCHEMA_RESTART
4148 #ifdef PRINT_SCHEMA_RESTART
4149     printf("checkSchemaStatus: pass: %d table: %d",
4150            c_restartRecord.m_pass, tableId);
4151     ndbout << "old: " << *ownEntry << " new: " << *masterEntry << endl;
4152 #endif
4153 
4154     if (c_restartRecord.m_pass <= CREATE_OLD_PASS)
4155     {
4156       if (!::checkSchemaStatus(ownEntry->m_tableType, c_restartRecord.m_pass))
4157         continue;
4158 
4159 
4160       if (ownState == SchemaFile::SF_UNUSED)
4161         continue;
4162 
4163       restartCreateObj(signal, tableId, ownEntry, true);
4164       return;
4165     }
4166 
4167     if (c_restartRecord.m_pass <= DROP_OLD_PASS)
4168     {
4169       if (!::checkSchemaStatus(ownEntry->m_tableType, c_restartRecord.m_pass))
4170         continue;
4171 
4172       if (ownState != SchemaFile::SF_IN_USE)
4173         continue;
4174 
4175       if (* ownEntry == * masterEntry)
4176         continue;
4177 
4178       restartDropObj(signal, tableId, ownEntry);
4179       return;
4180     }
4181 
4182     if (c_restartRecord.m_pass <= CREATE_NEW_PASS)
4183     {
4184       if (!::checkSchemaStatus(masterEntry->m_tableType, c_restartRecord.m_pass))
4185         continue;
4186 
4187       if (masterState != SchemaFile::SF_IN_USE)
4188       {
4189         if (ownEntry->m_tableType != DictTabInfo::SchemaTransaction)
4190         {
4191           jam();
4192           ownEntry->init();
4193         }
4194         continue;
4195       }
4196 
4197       /**
4198        * handle table(index) special as DIH has already copied
4199        *   table (using COPY_TABREQ)
4200        */
4201       if (DictTabInfo::isIndex(masterEntry->m_tableType) ||
4202           DictTabInfo::isTable(masterEntry->m_tableType))
4203       {
4204         bool file = * ownEntry == *masterEntry &&
4205           (!DictTabInfo::isIndex(masterEntry->m_tableType) || c_systemRestart);
4206 
4207         restartCreateObj(signal, tableId, masterEntry, file);
4208         return;
4209       }
4210 
4211       if (* ownEntry == *masterEntry)
4212         continue;
4213 
4214       restartCreateObj(signal, tableId, masterEntry, false);
4215       return;
4216     }
4217   }
4218 
4219   if (c_restartRecord.m_op_cnt == 0)
4220   {
4221     jam();
4222     restartNextPass(signal);
4223     return;
4224   }
4225   else
4226   {
4227     jam();
4228 
4229     c_restartRecord.m_op_cnt = 0;
4230 
4231     TxHandlePtr tx_ptr;
4232     c_txHandleHash.getPtr(tx_ptr, c_restartRecord.m_tx_ptr_i);
4233 
4234     Callback c = {
4235       safe_cast(&Dbdict::restartEndPass_fromEndTrans),
4236       tx_ptr.p->tx_key
4237     };
4238     tx_ptr.p->m_callback = c;
4239 
4240     Uint32 flags = 0;
4241     endSchemaTrans(signal, tx_ptr, flags);
4242     return;
4243   }
4244 }//checkSchemaStatus()
4245 
4246 void
checkPendingSchemaTrans(XSchemaFile * xsf)4247 Dbdict::checkPendingSchemaTrans(XSchemaFile* xsf)
4248 {
4249   for (Uint32 i = 0; i < xsf->noOfPages * NDB_SF_PAGE_ENTRIES; i++)
4250   {
4251     SchemaFile::TableEntry * transEntry = getTableEntry(xsf, i);
4252 
4253     if (transEntry->m_tableType == DictTabInfo::SchemaTransaction &&
4254         transEntry->m_transId != 0)
4255     {
4256       jam();
4257 
4258       bool commit = false;
4259       switch(transEntry->m_tableState){
4260       case SchemaFile::SF_STARTED:
4261       case SchemaFile::SF_PREPARE:
4262       case SchemaFile::SF_ABORT:
4263         jam();
4264         ndbout_c("Found pending trans (%u) - aborting", i);
4265         break;
4266       case SchemaFile::SF_COMMIT:
4267       case SchemaFile::SF_COMPLETE:
4268         jam();
4269         commit = true;
4270         ndbout_c("Found pending trans (%u) - committing", i);
4271         break;
4272       }
4273 
4274       const Uint32 transId = transEntry->m_transId;
4275       for (Uint32 j = 0; j<xsf->noOfPages * NDB_SF_PAGE_ENTRIES; j++)
4276       {
4277         SchemaFile::TableEntry * tmp = getTableEntry(xsf, j);
4278         if (tmp->m_transId == transId &&
4279             tmp->m_tableType != DictTabInfo::SchemaTransaction)
4280         {
4281           jam();
4282           tmp->m_transId = 0;
4283           switch(tmp->m_tableState){
4284           case SchemaFile::SF_CREATE:
4285             if (commit)
4286             {
4287               jam();
4288               tmp->m_tableState = SchemaFile::SF_IN_USE;
4289               ndbout_c("commit create %u", j);
4290             }
4291             else
4292             {
4293               jam();
4294               tmp->m_tableState = SchemaFile::SF_UNUSED;
4295               ndbout_c("abort create %u", j);
4296             }
4297             break;
4298           case SchemaFile::SF_ALTER:
4299             tmp->m_tableState = SchemaFile::SF_IN_USE;
4300             if (commit)
4301             {
4302               jam();
4303               ndbout_c("commit alter %u", j);
4304             }
4305             else
4306             {
4307               jam();
4308               ndbout_c("abort alter %u", j);
4309               tmp->m_tableVersion =
4310                 alter_obj_dec_schema_version(tmp->m_tableVersion);
4311             }
4312             break;
4313           case SchemaFile::SF_DROP:
4314             if (commit)
4315             {
4316               jam();
4317               tmp->m_tableState = SchemaFile::SF_UNUSED;
4318               ndbout_c("commit drop %u", j);
4319             }
4320             else
4321             {
4322               jam();
4323               tmp->m_tableState = SchemaFile::SF_IN_USE;
4324               ndbout_c("abort drop %u", j);
4325             }
4326             break;
4327           }
4328         }
4329       }
4330 
4331       transEntry->m_tableType = DictTabInfo::UndefTableType;
4332       transEntry->m_tableState = SchemaFile::SF_UNUSED;
4333       transEntry->m_transId = 0;
4334     }
4335   }
4336 }
4337 
4338 void
startRestoreSchema(Signal * signal,Callback cb)4339 Dbdict::startRestoreSchema(Signal* signal, Callback cb)
4340 {
4341   jam();
4342 
4343   initRestartRecord();
4344   c_schemaRecord.m_callback = cb;
4345 
4346   TxHandlePtr tx_ptr;
4347   seizeTxHandle(tx_ptr);
4348   ndbrequire(!tx_ptr.isNull());
4349 
4350   c_restartRecord.m_tx_ptr_i = tx_ptr.i;
4351   tx_ptr.p->m_requestInfo = DictSignal::RF_LOCAL_TRANS;
4352   tx_ptr.p->m_userData = 0;
4353 
4354   Callback c = {
4355     safe_cast(&Dbdict::restart_fromBeginTrans),
4356     tx_ptr.p->tx_key
4357   };
4358   tx_ptr.p->m_callback = c;
4359   beginSchemaTrans(signal, tx_ptr);
4360 
4361   if (c_restartRecord.m_start_banner)
4362   {
4363     jam();
4364     infoEvent("%s", c_restartRecord.m_start_banner);
4365   }
4366 }
4367 
4368 void
restart_fromBeginTrans(Signal * signal,Uint32 tx_key,Uint32 ret)4369 Dbdict::restart_fromBeginTrans(Signal* signal, Uint32 tx_key, Uint32 ret)
4370 {
4371   ndbrequire(ret == 0);
4372 
4373   TxHandlePtr tx_ptr;
4374   findTxHandle(tx_ptr, tx_key);
4375   ndbrequire(!tx_ptr.isNull());
4376 
4377   checkSchemaStatus(signal);
4378 }
4379 
4380 void
restart_nextOp(Signal * signal,bool commit)4381 Dbdict::restart_nextOp(Signal* signal, bool commit)
4382 {
4383   c_restartRecord.m_op_cnt++;
4384 
4385   Resource_limit rl;
4386   Uint32 free_words;
4387   m_ctx.m_mm.get_resource_limit(RG_SCHEMA_TRANS_MEMORY, rl);
4388   free_words = (rl.m_min - rl.m_curr) * GLOBAL_PAGE_SIZE_WORDS; // underestimate
4389   if (free_words < 2*MAX_WORDS_META_FILE)
4390   {
4391     jam();
4392     /**
4393      * Commit transaction now...so we don't risk overflowing
4394      *   c_opSectionBufferPool
4395      */
4396     c_restartRecord.m_op_cnt = ZRESTART_OPS_PER_TRANS;
4397   }
4398 
4399   if (commit || c_restartRecord.m_op_cnt >= ZRESTART_OPS_PER_TRANS)
4400   {
4401     jam();
4402     c_restartRecord.m_op_cnt = 0;
4403 
4404     TxHandlePtr tx_ptr;
4405     c_txHandleHash.getPtr(tx_ptr, c_restartRecord.m_tx_ptr_i);
4406 
4407     Callback c = {
4408       safe_cast(&Dbdict::restart_fromEndTrans),
4409       tx_ptr.p->tx_key
4410     };
4411     tx_ptr.p->m_callback = c;
4412 
4413     Uint32 flags = 0;
4414     endSchemaTrans(signal, tx_ptr, flags);
4415   }
4416   else
4417   {
4418     jam();
4419     c_restartRecord.activeTable++;
4420     checkSchemaStatus(signal);
4421   }
4422 }
4423 
4424 void
restart_fromEndTrans(Signal * signal,Uint32 tx_key,Uint32 ret)4425 Dbdict::restart_fromEndTrans(Signal* signal, Uint32 tx_key, Uint32 ret)
4426 {
4427   TxHandlePtr tx_ptr;
4428   findTxHandle(tx_ptr, tx_key);
4429   ndbrequire(!tx_ptr.isNull());
4430 
4431   if (unlikely(hasError(tx_ptr.p->m_error)))
4432   {
4433     jam();
4434     /*
4435       Fatal error while restoring shchema during restart,
4436       dump debug info and crash
4437     */
4438     ndbout << "error: " << tx_ptr.p->m_error << endl;
4439 
4440     char msg[128];
4441     BaseString::snprintf(msg, sizeof(msg),
4442                          "Failed to restore schema during restart, error %u."
4443                          ,tx_ptr.p->m_error.errorCode);
4444     progError(__LINE__, NDBD_EXIT_RESTORE_SCHEMA, msg);
4445   }
4446   ndbrequire(ret == 0); //wl3600_todo
4447 
4448   releaseTxHandle(tx_ptr);
4449 
4450   ndbrequire(c_restartRecord.m_op_cnt == 0);
4451   c_restartRecord.activeTable++;
4452 
4453   seizeTxHandle(tx_ptr);
4454   ndbrequire(!tx_ptr.isNull());
4455   c_restartRecord.m_tx_ptr_i = tx_ptr.i;
4456   tx_ptr.p->m_requestInfo = DictSignal::RF_LOCAL_TRANS;
4457   tx_ptr.p->m_userData = 0;
4458 
4459   Callback c = {
4460     safe_cast(&Dbdict::restart_fromBeginTrans),
4461     tx_ptr.p->tx_key
4462   };
4463   tx_ptr.p->m_callback = c;
4464   beginSchemaTrans(signal, tx_ptr);
4465 }
4466 
4467 void
restartEndPass_fromEndTrans(Signal * signal,Uint32 tx_key,Uint32 ret)4468 Dbdict::restartEndPass_fromEndTrans(Signal* signal, Uint32 tx_key, Uint32 ret)
4469 {
4470   TxHandlePtr tx_ptr;
4471   findTxHandle(tx_ptr, tx_key);
4472   ndbrequire(!tx_ptr.isNull());
4473 
4474   if (unlikely(hasError(tx_ptr.p->m_error)))
4475   {
4476     jam();
4477     /*
4478       Fatal error while restoring shchema during restart,
4479       dump debug info and crash
4480     */
4481     ndbout << "error: " << tx_ptr.p->m_error << endl;
4482 
4483     char msg[128];
4484     BaseString::snprintf(msg, sizeof(msg),
4485                          "Failed to restore schema during restart, error %u."
4486                          ,tx_ptr.p->m_error.errorCode);
4487     progError(__LINE__, NDBD_EXIT_RESTORE_SCHEMA, msg);
4488   }
4489   ndbrequire(ret == 0); //wl3600_todo
4490 
4491   releaseTxHandle(tx_ptr);
4492   c_restartRecord.m_tx_ptr_i = RNIL;
4493 
4494   restartNextPass(signal);
4495 }
4496 
4497 void
restartNextPass(Signal * signal)4498 Dbdict::restartNextPass(Signal* signal)
4499 {
4500   c_restartRecord.m_pass++;
4501   c_restartRecord.activeTable= 0;
4502 
4503   if (c_restartRecord.m_pass <= c_restartRecord.m_end_pass)
4504   {
4505     TxHandlePtr tx_ptr;
4506     if (c_restartRecord.m_tx_ptr_i == RNIL)
4507     {
4508       jam();
4509       seizeTxHandle(tx_ptr);
4510       ndbrequire(!tx_ptr.isNull());
4511       c_restartRecord.m_tx_ptr_i  = tx_ptr.i;
4512       tx_ptr.p->m_requestInfo = DictSignal::RF_LOCAL_TRANS;
4513       tx_ptr.p->m_userData = 0;
4514 
4515       Callback c = {
4516         safe_cast(&Dbdict::restart_fromBeginTrans),
4517         tx_ptr.p->tx_key
4518       };
4519       tx_ptr.p->m_callback = c;
4520       beginSchemaTrans(signal, tx_ptr);
4521       return;
4522     }
4523     else
4524     {
4525       jam();
4526       c_txHandleHash.getPtr(tx_ptr, c_restartRecord.m_tx_ptr_i);
4527       restart_fromBeginTrans(signal, tx_ptr.p->tx_key, 0);
4528       return;
4529     }
4530   }
4531   else if (c_restartRecord.m_tx_ptr_i != RNIL)
4532   {
4533     /**
4534      * Complete last trans
4535      */
4536     jam();
4537 
4538     c_restartRecord.m_pass--;
4539     c_restartRecord.m_op_cnt = 0;
4540 
4541     TxHandlePtr tx_ptr;
4542     c_txHandleHash.getPtr(tx_ptr, c_restartRecord.m_tx_ptr_i);
4543 
4544     Callback c = {
4545       safe_cast(&Dbdict::restartEndPass_fromEndTrans),
4546       tx_ptr.p->tx_key
4547     };
4548     tx_ptr.p->m_callback = c;
4549 
4550     Uint32 flags = 0;
4551     endSchemaTrans(signal, tx_ptr, flags);
4552     return;
4553   }
4554   else
4555   {
4556     jam();
4557 
4558     ndbrequire(c_restartRecord.m_op_cnt == 0);
4559 
4560     /**
4561      * Write schema file at-end of checkSchemaStatus
4562      */
4563     XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
4564     ndbrequire(c_writeSchemaRecord.inUse == false);
4565     c_writeSchemaRecord.inUse = true;
4566     c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
4567     c_writeSchemaRecord.newFile = false;
4568     c_writeSchemaRecord.firstPage = 0;
4569     c_writeSchemaRecord.noOfPages = xsf->noOfPages;
4570     c_writeSchemaRecord.m_callback.m_callbackData = 0;
4571     c_writeSchemaRecord.m_callback.m_callbackFunction =
4572       safe_cast(&Dbdict::restart_fromWriteSchemaFile);
4573 
4574     for(Uint32 i = 0; i<xsf->noOfPages; i++)
4575       computeChecksum(xsf, i);
4576 
4577     startWriteSchemaFile(signal);
4578   }
4579 }
4580 
4581 void
restart_fromWriteSchemaFile(Signal * signal,Uint32 senderData,Uint32 retCode)4582 Dbdict::restart_fromWriteSchemaFile(Signal* signal,
4583                                     Uint32 senderData,
4584                                     Uint32 retCode)
4585 {
4586   if (c_restartRecord.m_end_banner)
4587   {
4588     jam();
4589     infoEvent("%s", c_restartRecord.m_end_banner);
4590   }
4591 
4592   execute(signal, c_schemaRecord.m_callback, retCode);
4593 }
4594 
4595 void
execGET_TABINFOREF(Signal * signal)4596 Dbdict::execGET_TABINFOREF(Signal* signal)
4597 {
4598   jamEntry();
4599 
4600   /**
4601    * Make copy of 'ref' such that we can build 'req' without overwriting
4602    * source.
4603    */
4604   const GetTabInfoRef ref_copy =
4605     *reinterpret_cast<const GetTabInfoRef*>(signal->getDataPtr());
4606 
4607   if (ref_copy.errorCode == GetTabInfoRef::Busy)
4608   {
4609     jam();
4610 
4611     const Uint32 senderRef = ref_copy.senderRef;
4612     ndbout_c("DICT : GET_TABINFOREF(Busy)  Retained for upgrade "
4613              "compatibility.  Sender node : %u block : %u version : %x",
4614              refToNode(senderRef),
4615              refToMain(senderRef),
4616              getNodeInfo(refToNode(senderRef)).m_version);
4617 
4618     /**
4619      * Master is busy. Send delayed CONTINUEB to self to add some delay, then
4620      * send new GET_TABINFOREQ to master.
4621      */
4622     signal->getDataPtrSend()[0] = ZGET_TABINFO_RETRY;
4623 
4624     GetTabInfoReq* const req =
4625       reinterpret_cast<GetTabInfoReq*>(signal->getDataPtrSend()+1);
4626     memset(req, 0, sizeof *req);
4627     req->senderRef = reference();
4628     req->senderData = ref_copy.senderData;
4629     req->requestType =
4630       GetTabInfoReq::RequestById | GetTabInfoReq::LongSignalConf;
4631     req->tableId = ref_copy.tableId;
4632     req->schemaTransId = ref_copy.schemaTransId;
4633     // Add a random 5-10ms delay.
4634     sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 5 + rand()%6,
4635                         GetTabInfoReq::SignalLength+1);
4636   }
4637   else
4638   {
4639     // Other error. Restart node.
4640     char msg[250];
4641     BaseString::snprintf(msg, sizeof(msg),
4642                          "Got GET_TABINFOREF from node %u with unexpected "
4643                          " error code %u",
4644                          refToNode(signal->getSendersBlockRef()),
4645                          ref_copy.errorCode);
4646     progError(__LINE__, NDBD_EXIT_RESTORE_SCHEMA, msg);
4647   }
4648 } // Dbdict::execGET_TABINFOREF()
4649 
4650 void
execGET_TABINFO_CONF(Signal * signal)4651 Dbdict::execGET_TABINFO_CONF(Signal* signal)
4652 {
4653   jamEntry();
4654 
4655   if(!assembleFragments(signal)){
4656     jam();
4657     return;
4658   }
4659 
4660   GetTabInfoConf * const conf = (GetTabInfoConf*)signal->getDataPtr();
4661 
4662   switch(conf->tableType){
4663   case DictTabInfo::UndefTableType:
4664   case DictTabInfo::HashIndexTrigger:
4665   case DictTabInfo::SubscriptionTrigger:
4666   case DictTabInfo::ReadOnlyConstraint:
4667   case DictTabInfo::IndexTrigger:
4668     ndbrequire(false);
4669   case DictTabInfo::SystemTable:
4670   case DictTabInfo::UserTable:
4671   case DictTabInfo::UniqueHashIndex:
4672   case DictTabInfo::HashIndex:
4673   case DictTabInfo::UniqueOrderedIndex:
4674   case DictTabInfo::OrderedIndex:
4675     break;
4676   case DictTabInfo::Tablespace:
4677   case DictTabInfo::LogfileGroup:
4678   case DictTabInfo::Datafile:
4679   case DictTabInfo::Undofile:
4680     if(refToBlock(conf->senderRef) == TSMAN
4681        && (refToNode(conf->senderRef) == 0
4682 	   || refToNode(conf->senderRef) == getOwnNodeId()))
4683     {
4684       jam();
4685       FilePtr fg_ptr;
4686       ndbrequire(find_object(fg_ptr, conf->tableId));
4687       const Uint32 free_extents= conf->freeExtents;
4688       const Uint32 id= conf->tableId;
4689       const Uint32 type= conf->tableType;
4690       const Uint32 data= conf->senderData;
4691       signal->theData[0]= ZPACK_TABLE_INTO_PAGES;
4692       signal->theData[1]= id;
4693       signal->theData[2]= type;
4694       signal->theData[3]= data;
4695       signal->theData[4]= free_extents;
4696       sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);
4697     }
4698     else if(refToBlock(conf->senderRef) == LGMAN
4699 	    && (refToNode(conf->senderRef) == 0
4700 		|| refToNode(conf->senderRef) == getOwnNodeId()))
4701     {
4702       jam();
4703       FilegroupPtr fg_ptr;
4704       ndbrequire(find_object(fg_ptr, conf->tableId));
4705       const Uint32 free_hi= conf->freeWordsHi;
4706       const Uint32 free_lo= conf->freeWordsLo;
4707       const Uint32 id= conf->tableId;
4708       const Uint32 type= conf->tableType;
4709       const Uint32 data= conf->senderData;
4710       signal->theData[0]= ZPACK_TABLE_INTO_PAGES;
4711       signal->theData[1]= id;
4712       signal->theData[2]= type;
4713       signal->theData[3]= data;
4714       signal->theData[4]= free_hi;
4715       signal->theData[5]= free_lo;
4716       sendSignal(reference(), GSN_CONTINUEB, signal, 6, JBB);
4717     }
4718     else
4719     {
4720       jam();
4721       break;
4722     }
4723     return;
4724   }
4725 
4726   restartCreateObj_getTabInfoConf(signal);
4727 }
4728 
4729 /**
4730  * Create Obj during NR/SR
4731  */
4732 void
restartCreateObj(Signal * signal,Uint32 tableId,const SchemaFile::TableEntry * new_entry,bool file)4733 Dbdict::restartCreateObj(Signal* signal,
4734 			 Uint32 tableId,
4735 			 const SchemaFile::TableEntry * new_entry,
4736 			 bool file){
4737   jam();
4738 
4739 
4740 #ifdef PRINT_SCHEMA_RESTART
4741   ndbout_c("restartCreateObj table: %u file: %u", tableId, Uint32(file));
4742 #endif
4743 
4744   c_restartRecord.m_entry = *new_entry;
4745   if(file)
4746   {
4747     c_readTableRecord.no_of_words = new_entry->m_info_words;
4748     c_readTableRecord.pageId = 0;
4749     c_readTableRecord.m_callback.m_callbackData = tableId;
4750     c_readTableRecord.m_callback.m_callbackFunction =
4751       safe_cast(&Dbdict::restartCreateObj_readConf);
4752 
4753     g_eventLogger->info("Restart recreating table with id = %u", tableId);
4754 
4755     startReadTableFile(signal, tableId);
4756   }
4757   else
4758   {
4759     /**
4760      * Get from master
4761      */
4762     GetTabInfoReq * const req = (GetTabInfoReq *)&signal->theData[0];
4763     req->senderRef = reference();
4764     req->senderData = tableId;
4765     req->requestType = GetTabInfoReq::RequestById |
4766       GetTabInfoReq::LongSignalConf;
4767     req->tableId = tableId;
4768     sendSignal(calcDictBlockRef(c_masterNodeId), GSN_GET_TABINFOREQ, signal,
4769 	       GetTabInfoReq::SignalLength, JBB);
4770   }
4771 }
4772 
4773 void
restartCreateObj_getTabInfoConf(Signal * signal)4774 Dbdict::restartCreateObj_getTabInfoConf(Signal* signal)
4775 {
4776   jam();
4777 
4778   SectionHandle handle(this, signal);
4779   SegmentedSectionPtr objInfoPtr;
4780   handle.getSection(objInfoPtr, GetTabInfoConf::DICT_TAB_INFO);
4781   handle.clear();
4782 
4783   restartCreateObj_parse(signal, objInfoPtr, false);
4784 }
4785 
4786 void
restartCreateObj_readConf(Signal * signal,Uint32 callbackData,Uint32 returnCode)4787 Dbdict::restartCreateObj_readConf(Signal* signal,
4788 				  Uint32 callbackData,
4789 				  Uint32 returnCode)
4790 {
4791   jam();
4792   ndbrequire(returnCode == 0);
4793 
4794   PageRecordPtr pageRecPtr;
4795   c_pageRecordArray.getPtr(pageRecPtr, c_readTableRecord.pageId);
4796 
4797   Uint32 sz = c_readTableRecord.no_of_words;
4798 
4799   Ptr<SectionSegment> ptr;
4800   ndbrequire(import(ptr, pageRecPtr.p->word+ZPAGE_HEADER_SIZE, sz));
4801   SegmentedSectionPtr tmp(sz, ptr.i, ptr.p);
4802   restartCreateObj_parse(signal, tmp, true);
4803 }
4804 
4805 void
restartCreateObj_parse(Signal * signal,SegmentedSectionPtr ptr,bool file)4806 Dbdict::restartCreateObj_parse(Signal* signal,
4807                                SegmentedSectionPtr ptr,
4808                                bool file)
4809 {
4810   jam();
4811   SchemaOpPtr op_ptr;
4812 
4813   TxHandlePtr tx_ptr;
4814   c_txHandleHash.getPtr(tx_ptr, c_restartRecord.m_tx_ptr_i);
4815 
4816   SchemaTransPtr trans_ptr;
4817   findSchemaTrans(trans_ptr, tx_ptr.p->m_transKey);
4818 
4819   switch(c_restartRecord.m_entry.m_tableType){
4820   case DictTabInfo::SystemTable:
4821   case DictTabInfo::UserTable:
4822   case DictTabInfo::UniqueHashIndex:
4823   case DictTabInfo::HashIndex:
4824   case DictTabInfo::UniqueOrderedIndex:
4825   case DictTabInfo::OrderedIndex:
4826   {
4827     CreateTableRecPtr opRecPtr;
4828     seizeSchemaOp(trans_ptr, op_ptr, opRecPtr);
4829     break;
4830   }
4831   case DictTabInfo::Undofile:
4832   case DictTabInfo::Datafile:
4833   {
4834     CreateFileRecPtr opRecPtr;
4835     seizeSchemaOp(trans_ptr, op_ptr, opRecPtr);
4836     break;
4837   }
4838   case DictTabInfo::Tablespace:
4839   case DictTabInfo::LogfileGroup:
4840   {
4841     CreateFilegroupRecPtr opRecPtr;
4842     seizeSchemaOp(trans_ptr, op_ptr, opRecPtr);
4843     break;
4844   }
4845   case DictTabInfo::HashMap:
4846   {
4847     CreateHashMapRecPtr opRecPtr;
4848     seizeSchemaOp(trans_ptr, op_ptr, opRecPtr);
4849     break;
4850   }
4851   case DictTabInfo::ForeignKey:
4852   {
4853     CreateFKRecPtr opRecPtr;
4854     seizeSchemaOp(trans_ptr, op_ptr, opRecPtr);
4855     break;
4856   }
4857   }
4858 
4859   op_ptr.p->m_restart = file ? 1 : 2;
4860   op_ptr.p->m_state = SchemaOp::OS_PARSE_MASTER;
4861 
4862   SectionHandle handle(this, ptr.i);
4863   ErrorInfo error;
4864   const OpInfo& info = getOpInfo(op_ptr);
4865   (this->*(info.m_parse))(signal, false, op_ptr, handle, error);
4866   releaseSections(handle);
4867   if (unlikely(hasError(error)))
4868   {
4869     jam();
4870     /*
4871       Fatal error while restoring shchema during restart,
4872       dump debug info and crash
4873     */
4874     ndbout << "error: " << error << endl;
4875 
4876     char msg[128];
4877     BaseString::snprintf(msg, sizeof(msg),
4878                          "Failed to recreate object %u during restart,"
4879                          " error %u."
4880                          ,c_restartRecord.activeTable
4881                          ,error.errorCode);
4882     progError(__LINE__, NDBD_EXIT_RESTORE_SCHEMA, msg);
4883   }
4884   ndbrequire(!hasError(error));
4885 
4886   restart_nextOp(signal);
4887 }
4888 
4889 /**
4890  * Drop object during NR/SR
4891  */
4892 void
restartDropObj(Signal * signal,Uint32 tableId,const SchemaFile::TableEntry * entry)4893 Dbdict::restartDropObj(Signal* signal,
4894                        Uint32 tableId,
4895                        const SchemaFile::TableEntry * entry)
4896 {
4897   jam();
4898   c_restartRecord.m_entry = *entry;
4899 
4900   jam();
4901   SchemaOpPtr op_ptr;
4902 
4903   TxHandlePtr tx_ptr;
4904   c_txHandleHash.getPtr(tx_ptr, c_restartRecord.m_tx_ptr_i);
4905 
4906   SchemaTransPtr trans_ptr;
4907   findSchemaTrans(trans_ptr, tx_ptr.p->m_transKey);
4908 
4909   switch(c_restartRecord.m_entry.m_tableType){
4910   case DictTabInfo::SystemTable:
4911   case DictTabInfo::UserTable:
4912   case DictTabInfo::UniqueHashIndex:
4913   case DictTabInfo::HashIndex:
4914   case DictTabInfo::UniqueOrderedIndex:
4915   case DictTabInfo::OrderedIndex:
4916   {
4917     DropTableRecPtr opRecPtr;
4918     seizeSchemaOp(trans_ptr, op_ptr, opRecPtr);
4919     ndbrequire(false);
4920     break;
4921   }
4922   case DictTabInfo::Undofile:
4923   case DictTabInfo::Datafile:
4924   {
4925     DropFileRecPtr opRecPtr;
4926     seizeSchemaOp(trans_ptr, op_ptr, opRecPtr);
4927     opRecPtr.p->m_request.file_id = tableId;
4928     opRecPtr.p->m_request.file_version = entry->m_tableVersion;
4929     break;
4930   }
4931   case DictTabInfo::Tablespace:
4932   case DictTabInfo::LogfileGroup:
4933   {
4934     DropFilegroupRecPtr opRecPtr;
4935     seizeSchemaOp(trans_ptr, op_ptr, opRecPtr);
4936     opRecPtr.p->m_request.filegroup_id = tableId;
4937     opRecPtr.p->m_request.filegroup_version = entry->m_tableVersion;
4938     break;
4939   }
4940   }
4941 
4942   ndbout_c("restartDropObj(%u)", tableId);
4943 
4944   op_ptr.p->m_restart = 1; //
4945   op_ptr.p->m_state = SchemaOp::OS_PARSE_MASTER;
4946 
4947   SectionHandle handle(this);
4948   ErrorInfo error;
4949   const OpInfo& info = getOpInfo(op_ptr);
4950   (this->*(info.m_parse))(signal, false, op_ptr, handle, error);
4951   releaseSections(handle);
4952   if (unlikely(hasError(error)))
4953   {
4954     jam();
4955     /*
4956       Fatal error while restoring shchema during restart,
4957       dump debug info and crash
4958     */
4959     ndbout << "error: " << error << endl;
4960 
4961     char msg[128];
4962     BaseString::snprintf(msg, sizeof(msg),
4963                          "Failed to drop object %u during restart, error %u"
4964                          ,c_restartRecord.activeTable
4965                          ,error.errorCode);
4966     progError(__LINE__, NDBD_EXIT_RESTORE_SCHEMA, msg);
4967   }
4968   ndbrequire(!hasError(error));
4969 
4970   restart_nextOp(signal);
4971 }
4972 
4973 /* **************************************************************** */
4974 /* ---------------------------------------------------------------- */
4975 /* MODULE:          NODE FAILURE HANDLING ------------------------- */
4976 /* ---------------------------------------------------------------- */
4977 /*                                                                  */
4978 /* This module contains the code that is used when nodes            */
4979 /* (kernel/api) fails.                                              */
4980 /* ---------------------------------------------------------------- */
4981 /* **************************************************************** */
4982 
handleApiFailureCallback(Signal * signal,Uint32 failedNodeId,Uint32 ignoredRc)4983 void Dbdict::handleApiFailureCallback(Signal* signal,
4984                                       Uint32 failedNodeId,
4985                                       Uint32 ignoredRc)
4986 {
4987   jamEntry();
4988 
4989   signal->theData[0] = failedNodeId;
4990   signal->theData[1] = reference();
4991   sendSignal(QMGR_REF, GSN_API_FAILCONF, signal, 2, JBB);
4992 }
4993 
4994 /* ---------------------------------------------------------------- */
4995 // We receive a report of an API that failed.
4996 /* ---------------------------------------------------------------- */
execAPI_FAILREQ(Signal * signal)4997 void Dbdict::execAPI_FAILREQ(Signal* signal)
4998 {
4999   jamEntry();
5000   Uint32 failedApiNode = signal->theData[0];
5001   BlockReference retRef = signal->theData[1];
5002 
5003   ndbrequire(retRef == QMGR_REF); // As callback hard-codes QMGR_REF
5004 #if 0
5005   Uint32 userNode = refToNode(c_connRecord.userBlockRef);
5006   if (userNode == failedApiNode) {
5007     jam();
5008     c_connRecord.userBlockRef = (Uint32)-1;
5009   }//if
5010 #endif
5011 
5012   // sends API_FAILCONF when done
5013   handleApiFail(signal, failedApiNode);
5014 }//execAPI_FAILREQ()
5015 
handleNdbdFailureCallback(Signal * signal,Uint32 failedNodeId,Uint32 ignoredRc)5016 void Dbdict::handleNdbdFailureCallback(Signal* signal,
5017                                        Uint32 failedNodeId,
5018                                        Uint32 ignoredRc)
5019 {
5020   jamEntry();
5021 
5022   /* Node failure handling is complete */
5023   NFCompleteRep * const nfCompRep = (NFCompleteRep *)&signal->theData[0];
5024   nfCompRep->blockNo      = DBDICT;
5025   nfCompRep->nodeId       = getOwnNodeId();
5026   nfCompRep->failedNodeId = failedNodeId;
5027   sendSignal(DBDIH_REF, GSN_NF_COMPLETEREP, signal,
5028              NFCompleteRep::SignalLength, JBB);
5029 }
5030 
5031 /* ---------------------------------------------------------------- */
5032 // We receive a report of one or more node failures of kernel nodes.
5033 /* ---------------------------------------------------------------- */
execNODE_FAILREP(Signal * signal)5034 void Dbdict::execNODE_FAILREP(Signal* signal)
5035 {
5036   jamEntry();
5037   NodeFailRep nodeFailRep = *(NodeFailRep *)&signal->theData[0];
5038   NodeFailRep * nodeFail = &nodeFailRep;
5039   NodeRecordPtr ownNodePtr;
5040 
5041   c_nodes.getPtr(ownNodePtr, getOwnNodeId());
5042   c_failureNr  = nodeFail->failNo;
5043   const Uint32 numberOfFailedNodes  = nodeFail->noOfNodes;
5044   const bool masterFailed = (c_masterNodeId != nodeFail->masterNodeId);
5045   c_masterNodeId = nodeFail->masterNodeId;
5046 
5047   c_noNodesFailed += numberOfFailedNodes;
5048   Uint32 theFailedNodes[NdbNodeBitmask::Size];
5049   memcpy(theFailedNodes, nodeFail->theNodes, sizeof(theFailedNodes));
5050   c_counterMgr.execNODE_FAILREP(signal);
5051 
5052   NdbNodeBitmask failedNodes;
5053   failedNodes.assign(NdbNodeBitmask::Size, theFailedNodes);
5054   c_aliveNodes.bitANDC(failedNodes);
5055   if (masterFailed && c_masterNodeId == getOwnNodeId())
5056   {
5057     /*
5058       Master node has failed, we need to take over
5059       any pending transaction(s) and decide if to
5060       rollforward or rollback.
5061      */
5062     jam();
5063     ownNodePtr.p->nodeState = NodeRecord::NDB_MASTER_TAKEOVER;
5064     ownNodePtr.p->nodeFailRep = nodeFailRep;
5065     infoEvent("Node %u taking over as DICT master", c_masterNodeId);
5066     handle_master_takeover(signal);
5067     return;
5068   }
5069 
5070   send_nf_complete_rep(signal, &nodeFailRep);
5071   return;
5072 }//execNODE_FAILREP()
5073 
send_nf_complete_rep(Signal * signal,const NodeFailRep * nodeFail)5074 void Dbdict::send_nf_complete_rep(Signal* signal, const NodeFailRep* nodeFail)
5075 {
5076   jam();
5077   Uint32 theFailedNodes[NdbNodeBitmask::Size];
5078   memcpy(theFailedNodes, nodeFail->theNodes, sizeof(theFailedNodes));
5079   NdbNodeBitmask tmp;
5080   tmp.assign(NdbNodeBitmask::Size, theFailedNodes);
5081 
5082   NodeRecordPtr ownNodePtr;
5083   c_nodes.getPtr(ownNodePtr, getOwnNodeId());
5084   ownNodePtr.p->nodeState = NodeRecord::NDB_NODE_ALIVE; // reset take-over
5085 
5086   for(unsigned i = 1; i < MAX_NDB_NODES; i++) {
5087     jam();
5088     if(tmp.get(i)) {
5089       jam();
5090       NodeRecordPtr nodePtr;
5091       c_nodes.getPtr(nodePtr, i);
5092 #ifdef VM_TRACE
5093       ndbout_c("Sending NF_COMPLETEREP for node %u", i);
5094 #endif
5095       nodePtr.p->nodeState = NodeRecord::NDB_NODE_DEAD;
5096 
5097       Callback cb = {safe_cast(&Dbdict::handleNdbdFailureCallback),
5098                      i};
5099 
5100       simBlockNodeFailure(signal, nodePtr.i, cb);
5101     }//if
5102   }//for
5103 
5104   /*
5105    * NODE_FAILREP guarantees that no "in flight" signal from
5106    * a dead node is accepted, and also that the job buffer contains
5107    * no such (un-executed) signals.  Therefore no DICT_UNLOCK_ORD
5108    * from a dead node (leading to master crash) is possible after
5109    * this clean-up removes the lock record.
5110    */
5111   removeStaleDictLocks(signal, theFailedNodes);
5112 
5113   c_sub_startstop_lock.bitANDC(tmp);
5114 }//send_nf_complete_rep
5115 
handle_master_takeover(Signal * signal)5116 void Dbdict::handle_master_takeover(Signal* signal)
5117 {
5118   /*
5119     This is the new master, handle take-over of
5120     pending schema transactions.
5121     Ask all slave nodes about state of any pending
5122     transactions
5123   */
5124   jam();
5125   NodeRecordPtr masterNodePtr;
5126   c_nodes.getPtr(masterNodePtr, c_masterNodeId);
5127 
5128   masterNodePtr.p->m_nodes = c_aliveNodes;
5129   NodeReceiverGroup rg(DBDICT, masterNodePtr.p->m_nodes);
5130   {
5131     SafeCounter sc(c_counterMgr, masterNodePtr.p->m_counter);
5132     bool ok = sc.init<DictTakeoverRef>(rg, c_masterNodeId);
5133     ndbrequire(ok);
5134   }
5135   DictTakeoverReq* req = (DictTakeoverReq*)signal->getDataPtrSend();
5136   req->senderRef = reference();
5137   c_takeOverInProgress = true;
5138   sendSignal(rg, GSN_DICT_TAKEOVER_REQ, signal,
5139                DictTakeoverReq::SignalLength, JBB);
5140 }
5141 
5142 
5143 /* **************************************************************** */
5144 /* ---------------------------------------------------------------- */
5145 /* MODULE:          NODE START HANDLING --------------------------- */
5146 /* ---------------------------------------------------------------- */
5147 /*                                                                  */
5148 /* This module contains the code that is used when kernel nodes     */
5149 /* starts.                                                          */
5150 /* ---------------------------------------------------------------- */
5151 /* **************************************************************** */
5152 
5153 /* ---------------------------------------------------------------- */
5154 // Include a starting node in list of nodes to be part of adding
5155 // and dropping tables.
5156 /* ---------------------------------------------------------------- */
execINCL_NODEREQ(Signal * signal)5157 void Dbdict::execINCL_NODEREQ(Signal* signal)
5158 {
5159   jamEntry();
5160   NodeRecordPtr nodePtr;
5161   BlockReference retRef = signal->theData[0];
5162   nodePtr.i = signal->theData[1];
5163 
5164   ndbrequire(c_noNodesFailed > 0);
5165   c_noNodesFailed--;
5166 
5167   c_nodes.getPtr(nodePtr);
5168   ndbrequire(nodePtr.p->nodeState == NodeRecord::NDB_NODE_DEAD);
5169   nodePtr.p->nodeState = NodeRecord::NDB_NODE_ALIVE;
5170   signal->theData[0] = nodePtr.i;
5171   signal->theData[1] = reference();
5172   sendSignal(retRef, GSN_INCL_NODECONF, signal, 2, JBB);
5173 
5174   c_aliveNodes.set(nodePtr.i);
5175 }//execINCL_NODEREQ()
5176 
5177 /* **************************************************************** */
5178 /* ---------------------------------------------------------------- */
5179 /* MODULE:          ADD TABLE HANDLING ---------------------------- */
5180 /* ---------------------------------------------------------------- */
5181 /*                                                                  */
5182 /* This module contains the code that is used when adding a table.  */
5183 /* ---------------------------------------------------------------- */
5184 /* **************************************************************** */
5185 
5186 inline
printTables()5187 void Dbdict::printTables()
5188 {
5189   DictObjectName_hash::Iterator iter;
5190   bool moreTables = c_obj_name_hash.first(iter);
5191   printf("OBJECTS IN DICT:\n");
5192   char name[PATH_MAX];
5193   while (moreTables) {
5194     DictObjectPtr tablePtr = iter.curr;
5195     ConstRope r(c_rope_pool, tablePtr.p->m_name);
5196     r.copy(name);
5197     printf("%s ", name);
5198     moreTables = c_obj_name_hash.next(iter);
5199   }
5200   printf("\n");
5201 }
5202 
5203 #define tabRequire(cond, error) \
5204   if (!(cond)) { \
5205     jam();    \
5206     parseP->errorCode = error; parseP->errorLine = __LINE__; \
5207     parseP->errorKey = it.getKey(); \
5208     return;   \
5209   }//if
5210 
5211 // handleAddTableFailure(signal, __LINE__, allocatedTable);
5212 
5213 Dbdict::DictObject *
get_object(const char * name,Uint32 len,Uint32 hash)5214 Dbdict::get_object(const char * name, Uint32 len, Uint32 hash){
5215   DictObjectPtr old_ptr;
5216   if (get_object(old_ptr, name, len, hash))
5217   {
5218     return old_ptr.p;
5219   }
5220   return 0;
5221 }
5222 
5223 bool
get_object(DictObjectPtr & obj_ptr,const char * name,Uint32 len,Uint32 hash)5224 Dbdict::get_object(DictObjectPtr& obj_ptr, const char* name, Uint32 len, Uint32 hash)
5225 {
5226   DictObject key;
5227   key.m_key.m_name_ptr = name;
5228   key.m_key.m_name_len = len;
5229   key.m_key.m_pool = &c_rope_pool;
5230   key.m_name.m_hash = hash;
5231   return c_obj_name_hash.find(obj_ptr, key);
5232 }
5233 
5234 void
release_object(Uint32 obj_ptr_i,DictObject * obj_ptr_p)5235 Dbdict::release_object(Uint32 obj_ptr_i, DictObject* obj_ptr_p){
5236   jam();
5237   RopeHandle obj_name = obj_ptr_p->m_name;
5238   DictObjectPtr ptr(obj_ptr_p, obj_ptr_i);
5239 
5240   LocalRope name(c_rope_pool, obj_name);
5241   name.erase();
5242 
5243 jam();
5244   c_obj_name_hash.remove(ptr);
5245 jam();
5246   c_obj_id_hash.remove(ptr);
5247 jam();
5248   c_obj_pool.release(ptr);
5249 jam();
5250 }
5251 
5252 void
increase_ref_count(Uint32 obj_ptr_i)5253 Dbdict::increase_ref_count(Uint32 obj_ptr_i)
5254 {
5255   DictObject* ptr = c_obj_pool.getPtr(obj_ptr_i);
5256   ptr->m_ref_count++;
5257 }
5258 
5259 void
decrease_ref_count(Uint32 obj_ptr_i)5260 Dbdict::decrease_ref_count(Uint32 obj_ptr_i)
5261 {
5262   DictObject* ptr = c_obj_pool.getPtr(obj_ptr_i);
5263   ndbrequire(ptr->m_ref_count);
5264   ptr->m_ref_count--;
5265 }
5266 
handleTabInfoInit(Signal * signal,SchemaTransPtr & trans_ptr,SimpleProperties::Reader & it,ParseDictTabInfoRecord * parseP,bool checkExist)5267 void Dbdict::handleTabInfoInit(Signal * signal, SchemaTransPtr & trans_ptr,
5268                                SimpleProperties::Reader & it,
5269 			       ParseDictTabInfoRecord * parseP,
5270 			       bool checkExist)
5271 {
5272 /* ---------------------------------------------------------------- */
5273 // We always start by handling table name since this must be the first
5274 // item in the list. Through the table name we can derive if it is a
5275 // correct name, a new name or an already existing table.
5276 /* ---------------------------------------------------------------- */
5277 
5278   it.first();
5279 
5280   SimpleProperties::UnpackStatus status;
5281   c_tableDesc.init();
5282   status = SimpleProperties::unpack(it, &c_tableDesc,
5283 				    DictTabInfo::TableMapping,
5284 				    DictTabInfo::TableMappingSize,
5285 				    true, true);
5286 
5287   if(status != SimpleProperties::Break){
5288     parseP->errorCode = CreateTableRef::InvalidFormat;
5289     parseP->status    = status;
5290     parseP->errorKey  = it.getKey();
5291     parseP->errorLine = __LINE__;
5292     return;
5293   }
5294 
5295   if(parseP->requestType == DictTabInfo::AlterTableFromAPI)
5296   {
5297     ndbrequire(!checkExist);
5298   }
5299   if(!checkExist)
5300   {
5301     ndbrequire(parseP->requestType == DictTabInfo::AlterTableFromAPI);
5302   }
5303 
5304   /* ---------------------------------------------------------------- */
5305   // Verify that table name is an allowed table name.
5306   // TODO
5307   /* ---------------------------------------------------------------- */
5308   const Uint32 tableNameLength = Uint32(strlen(c_tableDesc.TableName) + 1);
5309   const Uint32 name_hash = LocalRope::hash(c_tableDesc.TableName, tableNameLength);
5310 
5311   if(checkExist){
5312     jam();
5313     tabRequire(get_object(c_tableDesc.TableName, tableNameLength) == 0,
5314 	       CreateTableRef::TableAlreadyExist);
5315   }
5316 
5317   if (DictTabInfo::isIndex(c_tableDesc.TableType))
5318   {
5319     jam();
5320     parseP->requestType = DictTabInfo::AddTableFromDict;
5321   }
5322 
5323   TableRecordPtr tablePtr;
5324   Uint32 schemaFileId;
5325   switch (parseP->requestType) {
5326   case DictTabInfo::CreateTableFromAPI: {
5327     jam();
5328   }
5329   case DictTabInfo::AlterTableFromAPI:{
5330     jam();
5331     schemaFileId = RNIL;
5332     bool ok = seizeTableRecord(tablePtr,schemaFileId);
5333     tabRequire(ok, CreateTableRef::NoMoreTableRecords);
5334     break;
5335   }
5336   case DictTabInfo::AddTableFromDict:
5337   case DictTabInfo::ReadTableFromDiskSR:
5338   case DictTabInfo::GetTabInfoConf:
5339   {
5340 /* ---------------------------------------------------------------- */
5341 // Get table id and check that table doesn't already exist
5342 /* ---------------------------------------------------------------- */
5343     if (parseP->requestType == DictTabInfo::ReadTableFromDiskSR) {
5344       ndbrequire(c_tableDesc.TableId == c_restartRecord.activeTable);
5345     }//if
5346     if (parseP->requestType == DictTabInfo::GetTabInfoConf) {
5347       ndbrequire(c_tableDesc.TableId == c_restartRecord.activeTable);
5348     }//if
5349 
5350     schemaFileId = c_tableDesc.TableId;
5351     bool ok = seizeTableRecord(tablePtr,schemaFileId);
5352     ndbrequire(ok); // Already exists or out of memory
5353 /* ---------------------------------------------------------------- */
5354 // Set table version
5355 /* ---------------------------------------------------------------- */
5356     Uint32 tableVersion = c_tableDesc.TableVersion;
5357     tablePtr.p->tableVersion = tableVersion;
5358 
5359     break;
5360   }
5361   default:
5362     ndbrequire(false);
5363     break;
5364   }//switch
5365 
5366   {
5367     LocalRope name(c_rope_pool, tablePtr.p->tableName);
5368     tabRequire(name.assign(c_tableDesc.TableName, tableNameLength, name_hash),
5369 	       CreateTableRef::OutOfStringBuffer);
5370   }
5371 
5372   if (parseP->requestType != DictTabInfo::AlterTableFromAPI) {
5373     jam();
5374 
5375     DictObjectPtr obj_ptr;
5376     ndbrequire(c_obj_pool.seize(obj_ptr));
5377     new (obj_ptr.p) DictObject;
5378     obj_ptr.p->m_id = schemaFileId;
5379     obj_ptr.p->m_type = c_tableDesc.TableType;
5380     obj_ptr.p->m_name = tablePtr.p->tableName;
5381     obj_ptr.p->m_ref_count = 0;
5382     ndbrequire(link_object(obj_ptr, tablePtr));
5383     c_obj_id_hash.add(obj_ptr);
5384     c_obj_name_hash.add(obj_ptr);
5385 
5386     if (g_trace)
5387     {
5388       g_eventLogger->info("Dbdict: %u: create name=%s,id=%u,obj_ptr_i=%d",__LINE__,
5389                           c_tableDesc.TableName,
5390                           schemaFileId, tablePtr.p->m_obj_ptr_i);
5391     }
5392     send_event(signal, trans_ptr,
5393                NDB_LE_CreateSchemaObject,
5394                schemaFileId,
5395                tablePtr.p->tableVersion,
5396                c_tableDesc.TableType);
5397   }
5398   parseP->tablePtr = tablePtr;
5399 
5400   // Disallow logging of a temporary table.
5401   tabRequire(!(c_tableDesc.TableTemporaryFlag && c_tableDesc.TableLoggedFlag),
5402              CreateTableRef::NoLoggingTemporaryTable);
5403 
5404   tablePtr.p->noOfAttributes = c_tableDesc.NoOfAttributes;
5405   tablePtr.p->m_bits |=
5406     (c_tableDesc.TableLoggedFlag ? TableRecord::TR_Logged : 0);
5407   tablePtr.p->m_bits |=
5408     (c_tableDesc.RowChecksumFlag ? TableRecord::TR_RowChecksum : 0);
5409   tablePtr.p->m_bits |=
5410     (c_tableDesc.RowGCIFlag ? TableRecord::TR_RowGCI : 0);
5411 #if DOES_NOT_WORK_CURRENTLY
5412   tablePtr.p->m_bits |=
5413     (c_tableDesc.TableTemporaryFlag ? TableRecord::TR_Temporary : 0);
5414 #endif
5415   tablePtr.p->m_bits |=
5416     (c_tableDesc.ForceVarPartFlag ? TableRecord::TR_ForceVarPart : 0);
5417   tablePtr.p->minLoadFactor = c_tableDesc.MinLoadFactor;
5418   tablePtr.p->maxLoadFactor = c_tableDesc.MaxLoadFactor;
5419   tablePtr.p->fragmentType = (DictTabInfo::FragmentType)c_tableDesc.FragmentType;
5420   tablePtr.p->tableType = (DictTabInfo::TableType)c_tableDesc.TableType;
5421   tablePtr.p->kValue = c_tableDesc.TableKValue;
5422   tablePtr.p->fragmentCount = c_tableDesc.FragmentCount;
5423   tablePtr.p->m_tablespace_id = c_tableDesc.TablespaceId;
5424   tablePtr.p->maxRowsLow = c_tableDesc.MaxRowsLow;
5425   tablePtr.p->maxRowsHigh = c_tableDesc.MaxRowsHigh;
5426   tablePtr.p->minRowsLow = c_tableDesc.MinRowsLow;
5427   tablePtr.p->minRowsHigh = c_tableDesc.MinRowsHigh;
5428   tablePtr.p->defaultNoPartFlag = c_tableDesc.DefaultNoPartFlag;
5429   tablePtr.p->linearHashFlag = c_tableDesc.LinearHashFlag;
5430   tablePtr.p->singleUserMode = c_tableDesc.SingleUserMode;
5431   tablePtr.p->hashMapObjectId = c_tableDesc.HashMapObjectId;
5432   tablePtr.p->hashMapVersion = c_tableDesc.HashMapVersion;
5433   tablePtr.p->storageType = c_tableDesc.TableStorageType;
5434   tablePtr.p->m_extra_row_gci_bits = c_tableDesc.ExtraRowGCIBits;
5435   tablePtr.p->m_extra_row_author_bits = c_tableDesc.ExtraRowAuthorBits;
5436 
5437   tabRequire(tablePtr.p->noOfAttributes <= MAX_ATTRIBUTES_IN_TABLE,
5438              CreateTableRef::NoMoreAttributeRecords); // bad error code!
5439 
5440   if (tablePtr.p->fragmentType == DictTabInfo::HashMapPartition &&
5441       tablePtr.p->hashMapObjectId == RNIL)
5442   {
5443     Uint32 fragments = tablePtr.p->fragmentCount;
5444     if (fragments == 0)
5445     {
5446       jam();
5447       tablePtr.p->fragmentCount = fragments = get_default_fragments(signal);
5448     }
5449 
5450     tabRequire(fragments <= MAX_NDB_PARTITIONS,
5451                CreateTableRef::TooManyFragments);
5452 
5453     char buf[MAX_TAB_NAME_SIZE+1];
5454     BaseString::snprintf(buf, sizeof(buf), "DEFAULT-HASHMAP-%u-%u",
5455                          c_default_hashmap_size,
5456                          fragments);
5457     DictObject* dictObj = get_object(buf);
5458     if (dictObj && dictObj->m_type == DictTabInfo::HashMap)
5459     {
5460       jam();
5461       HashMapRecordPtr hm_ptr;
5462       ndbrequire(find_object(hm_ptr, dictObj->m_id));
5463       tablePtr.p->hashMapObjectId = hm_ptr.p->m_object_id;
5464       tablePtr.p->hashMapVersion = hm_ptr.p->m_object_version;
5465     }
5466   }
5467 
5468   if (tablePtr.p->fragmentType == DictTabInfo::HashMapPartition)
5469   {
5470     jam();
5471     HashMapRecordPtr hm_ptr;
5472     tabRequire(find_object(hm_ptr, tablePtr.p->hashMapObjectId),
5473                CreateTableRef::InvalidHashMap);
5474 
5475     tabRequire(hm_ptr.p->m_object_version ==  tablePtr.p->hashMapVersion,
5476                CreateTableRef::InvalidHashMap);
5477 
5478     Ptr<Hash2FragmentMap> mapptr;
5479     g_hash_map.getPtr(mapptr, hm_ptr.p->m_map_ptr_i);
5480 
5481     if (tablePtr.p->fragmentCount == 0)
5482     {
5483       jam();
5484       tablePtr.p->fragmentCount = mapptr.p->m_fragments;
5485     }
5486     else
5487     {
5488       tabRequire(mapptr.p->m_fragments == tablePtr.p->fragmentCount,
5489                  CreateTableRef::InvalidHashMap);
5490     }
5491   }
5492 
5493   {
5494     LocalRope frm(c_rope_pool, tablePtr.p->frmData);
5495     tabRequire(frm.assign(c_tableDesc.FrmData, c_tableDesc.FrmLen),
5496 	       CreateTableRef::OutOfStringBuffer);
5497     LocalRope range(c_rope_pool, tablePtr.p->rangeData);
5498     tabRequire(range.assign((const char*)c_tableDesc.RangeListData,
5499                c_tableDesc.RangeListDataLen),
5500 	      CreateTableRef::OutOfStringBuffer);
5501     LocalRope fd(c_rope_pool, tablePtr.p->ngData);
5502     tabRequire(fd.assign((const char*)c_tableDesc.FragmentData,
5503                          c_tableDesc.FragmentDataLen),
5504 	       CreateTableRef::OutOfStringBuffer);
5505   }
5506 
5507   c_fragDataLen = c_tableDesc.FragmentDataLen;
5508   memcpy(c_fragData, c_tableDesc.FragmentData,
5509          c_tableDesc.FragmentDataLen);
5510 
5511   if(c_tableDesc.PrimaryTableId != RNIL)
5512   {
5513     jam();
5514     tablePtr.p->primaryTableId = c_tableDesc.PrimaryTableId;
5515     tablePtr.p->indexState = (TableRecord::IndexState)c_tableDesc.IndexState;
5516 
5517     if (getNodeState().getSystemRestartInProgress())
5518     {
5519       jam();
5520       tablePtr.p->triggerId = RNIL;
5521     }
5522     else
5523     {
5524       jam();
5525       tablePtr.p->triggerId = c_tableDesc.CustomTriggerId;
5526 
5527       if (c_tableDesc.InsertTriggerId != RNIL ||
5528           c_tableDesc.UpdateTriggerId != RNIL ||
5529           c_tableDesc.DeleteTriggerId != RNIL)
5530       {
5531         jam();
5532         /**
5533          * Upgrade...unique index
5534          */
5535         ndbrequire(tablePtr.p->isUniqueIndex());
5536         ndbrequire(c_tableDesc.CustomTriggerId == RNIL);
5537         ndbrequire(c_tableDesc.InsertTriggerId != RNIL);
5538         ndbrequire(c_tableDesc.UpdateTriggerId != RNIL);
5539         ndbrequire(c_tableDesc.DeleteTriggerId != RNIL);
5540         ndbout_c("table: %u UPGRADE saving (%u/%u/%u)",
5541                  schemaFileId,
5542                  c_tableDesc.InsertTriggerId,
5543                  c_tableDesc.UpdateTriggerId,
5544                  c_tableDesc.DeleteTriggerId);
5545         infoEvent("table: %u UPGRADE saving (%u/%u/%u)",
5546                   schemaFileId,
5547                   c_tableDesc.InsertTriggerId,
5548                   c_tableDesc.UpdateTriggerId,
5549                   c_tableDesc.DeleteTriggerId);
5550         tablePtr.p->triggerId = c_tableDesc.InsertTriggerId;
5551         tablePtr.p->m_upgrade_trigger_handling.m_upgrade = true;
5552         tablePtr.p->m_upgrade_trigger_handling.insertTriggerId = c_tableDesc.InsertTriggerId;
5553         tablePtr.p->m_upgrade_trigger_handling.updateTriggerId = c_tableDesc.UpdateTriggerId;
5554         tablePtr.p->m_upgrade_trigger_handling.deleteTriggerId = c_tableDesc.DeleteTriggerId;
5555 
5556         upgrade_seizeTrigger(tablePtr,
5557                              c_tableDesc.InsertTriggerId,
5558                              c_tableDesc.UpdateTriggerId,
5559                              c_tableDesc.DeleteTriggerId);
5560       }
5561     }
5562   }
5563   else
5564   {
5565     jam();
5566     tablePtr.p->primaryTableId = RNIL;
5567     tablePtr.p->indexState = TableRecord::IS_UNDEFINED;
5568     tablePtr.p->triggerId = RNIL;
5569   }
5570   tablePtr.p->buildTriggerId = RNIL;
5571 
5572   handleTabInfo(it, parseP, c_tableDesc);
5573 
5574   if(parseP->errorCode != 0)
5575   {
5576     /**
5577      * Release table
5578      */
5579     releaseTableObject(tablePtr.i, checkExist);
5580     parseP->tablePtr.setNull();
5581     return;
5582   }
5583 
5584   if (checkExist && tablePtr.p->m_tablespace_id != RNIL)
5585   {
5586     /**
5587      * Increase ref count
5588      */
5589     FilegroupPtr ptr;
5590     ndbrequire(find_object(ptr, tablePtr.p->m_tablespace_id));
5591     increase_ref_count(ptr.p->m_obj_ptr_i);
5592   }
5593 }//handleTabInfoInit()
5594 
5595 void
upgrade_seizeTrigger(TableRecordPtr tabPtr,Uint32 insertTriggerId,Uint32 updateTriggerId,Uint32 deleteTriggerId)5596 Dbdict::upgrade_seizeTrigger(TableRecordPtr tabPtr,
5597                              Uint32 insertTriggerId,
5598                              Uint32 updateTriggerId,
5599                              Uint32 deleteTriggerId)
5600 {
5601   /**
5602    * The insert trigger will be "main" trigger so
5603    *   it does not need any special treatment
5604    */
5605   const Uint32 size = c_triggerRecordPool_.getSize();
5606   ndbrequire(updateTriggerId == RNIL || updateTriggerId < size);
5607   ndbrequire(deleteTriggerId == RNIL || deleteTriggerId < size);
5608 
5609   DictObjectPtr tab_obj_ptr;
5610   c_obj_pool.getPtr(tab_obj_ptr, tabPtr.p->m_obj_ptr_i);
5611 
5612   TriggerRecordPtr triggerPtr;
5613   if (updateTriggerId != RNIL)
5614   {
5615     jam();
5616     bool ok = find_object(triggerPtr, updateTriggerId);
5617     if (!ok)
5618     {
5619       jam();
5620       bool ok = seizeTriggerRecord(triggerPtr, updateTriggerId);
5621       if (!ok)
5622       {
5623         jam();
5624         ndbrequire(ok);
5625       }
5626       triggerPtr.p->triggerState = TriggerRecord::TS_FAKE_UPGRADE;
5627       triggerPtr.p->tableId = tabPtr.p->primaryTableId;
5628       triggerPtr.p->indexId = tab_obj_ptr.p->m_id;
5629       TriggerInfo::packTriggerInfo(triggerPtr.p->triggerInfo,
5630                                    g_hashIndexTriggerTmpl[0].triggerInfo);
5631 
5632       char buf[256];
5633       BaseString::snprintf(buf, sizeof(buf),
5634                            "UPG_UPD_NDB$INDEX_%u_UI", tab_obj_ptr.p->m_id);
5635       {
5636         LocalRope name(c_rope_pool, triggerPtr.p->triggerName);
5637         name.assign(buf);
5638       }
5639 
5640       DictObjectPtr obj_ptr;
5641       ok = c_obj_pool.seize(obj_ptr);
5642       ndbrequire(ok);
5643       new (obj_ptr.p) DictObject();
5644 
5645       obj_ptr.p->m_name = triggerPtr.p->triggerName;
5646       obj_ptr.p->m_ref_count = 0;
5647 
5648       obj_ptr.p->m_id = triggerPtr.p->triggerId;
5649       obj_ptr.p->m_type =TriggerInfo::getTriggerType(triggerPtr.p->triggerInfo);
5650       link_object(obj_ptr, triggerPtr);
5651       c_obj_name_hash.add(obj_ptr);
5652       c_obj_id_hash.add(obj_ptr);
5653     }
5654   }
5655 
5656   if (deleteTriggerId != RNIL)
5657   {
5658     jam();
5659     bool ok = find_object(triggerPtr, deleteTriggerId); // TODO: msundell seizeTriggerRecord
5660     if (!ok)
5661     {
5662       jam();
5663       bool ok = seizeTriggerRecord(triggerPtr, deleteTriggerId);
5664       if (!ok)
5665       {
5666         jam();
5667         ndbrequire(ok);
5668       }
5669       triggerPtr.p->triggerState = TriggerRecord::TS_FAKE_UPGRADE;
5670       triggerPtr.p->tableId = tabPtr.p->primaryTableId;
5671       triggerPtr.p->indexId = tab_obj_ptr.p->m_id;
5672       TriggerInfo::packTriggerInfo(triggerPtr.p->triggerInfo,
5673                                    g_hashIndexTriggerTmpl[0].triggerInfo);
5674       char buf[256];
5675       BaseString::snprintf(buf, sizeof(buf),
5676                            "UPG_DEL_NDB$INDEX_%u_UI", tab_obj_ptr.p->m_id);
5677 
5678       {
5679         LocalRope name(c_rope_pool, triggerPtr.p->triggerName);
5680         name.assign(buf);
5681       }
5682 
5683       DictObjectPtr obj_ptr;
5684       ok = c_obj_pool.seize(obj_ptr);
5685       ndbrequire(ok);
5686       new (obj_ptr.p) DictObject();
5687 
5688       obj_ptr.p->m_name = triggerPtr.p->triggerName;
5689       obj_ptr.p->m_ref_count = 0;
5690 
5691       obj_ptr.p->m_id = triggerPtr.p->triggerId;
5692       obj_ptr.p->m_type =TriggerInfo::getTriggerType(triggerPtr.p->triggerInfo);
5693       link_object(obj_ptr, triggerPtr);
5694       c_obj_name_hash.add(obj_ptr);
5695       c_obj_id_hash.add(obj_ptr);
5696     }
5697   }
5698 }
5699 
handleTabInfo(SimpleProperties::Reader & it,ParseDictTabInfoRecord * parseP,DictTabInfo::Table & tableDesc)5700 void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
5701 			   ParseDictTabInfoRecord * parseP,
5702 			   DictTabInfo::Table &tableDesc)
5703 {
5704   TableRecordPtr tablePtr = parseP->tablePtr;
5705 
5706   SimpleProperties::UnpackStatus status;
5707 
5708   Uint32 keyCount = 0;
5709   Uint32 keyLength = 0;
5710   Uint32 attrCount = tablePtr.p->noOfAttributes;
5711   Uint32 nullCount = 0;
5712   Uint32 nullBits = 0;
5713   Uint32 noOfCharsets = 0;
5714   Uint16 charsets[128];
5715   Uint32 recordLength = 0;
5716   AttributeRecordPtr attrPtr;
5717   c_attributeRecordHash.removeAll();
5718 
5719   LocalAttributeRecord_list list(c_attributeRecordPool,
5720 					tablePtr.p->m_attributes);
5721 
5722   Uint32 counts[] = {0,0,0,0,0};
5723 
5724   for(Uint32 i = 0; i<attrCount; i++){
5725     /**
5726      * Attribute Name
5727      */
5728     DictTabInfo::Attribute attrDesc; attrDesc.init();
5729     status = SimpleProperties::unpack(it, &attrDesc,
5730 				      DictTabInfo::AttributeMapping,
5731 				      DictTabInfo::AttributeMappingSize,
5732 				      true, true);
5733 
5734     if(status != SimpleProperties::Break){
5735       parseP->errorCode = CreateTableRef::InvalidFormat;
5736       parseP->status    = status;
5737       parseP->errorKey  = it.getKey();
5738       parseP->errorLine = __LINE__;
5739       return;
5740     }
5741 
5742     /**
5743      * Check that attribute is not defined twice
5744      */
5745     const Uint32 len = Uint32(strlen(attrDesc.AttributeName)+1);
5746     const Uint32 name_hash = LocalRope::hash(attrDesc.AttributeName, len);
5747     {
5748       AttributeRecord key;
5749       key.m_key.m_name_ptr = attrDesc.AttributeName;
5750       key.m_key.m_name_len = len;
5751       key.attributeName.m_hash = name_hash;
5752       key.m_key.m_pool = &c_rope_pool;
5753       AttributeRecordPtr old_ptr;
5754       c_attributeRecordHash.find(old_ptr, key);
5755 
5756       if(old_ptr.i != RNIL){
5757 	parseP->errorCode = CreateTableRef::AttributeNameTwice;
5758 	return;
5759       }
5760     }
5761 
5762     list.seizeLast(attrPtr);
5763     if(attrPtr.i == RNIL){
5764       jam();
5765       parseP->errorCode = CreateTableRef::NoMoreAttributeRecords;
5766       return;
5767     }
5768 
5769     new (attrPtr.p) AttributeRecord();
5770     attrPtr.p->attributeDescriptor = 0x00012255; //Default value
5771     attrPtr.p->tupleKey = 0;
5772 
5773     /**
5774      * TmpAttrib to Attribute mapping
5775      */
5776     {
5777       LocalRope name(c_rope_pool, attrPtr.p->attributeName);
5778       if (!name.assign(attrDesc.AttributeName, len, name_hash))
5779       {
5780 	jam();
5781 	parseP->errorCode = CreateTableRef::OutOfStringBuffer;
5782 	parseP->errorLine = __LINE__;
5783 	return;
5784       }
5785     }
5786     attrPtr.p->attributeId = i;
5787     //attrPtr.p->attributeId = attrDesc.AttributeId;
5788     attrPtr.p->tupleKey = (keyCount + 1) * attrDesc.AttributeKeyFlag;
5789 
5790     attrPtr.p->extPrecision = attrDesc.AttributeExtPrecision;
5791     attrPtr.p->extScale = attrDesc.AttributeExtScale;
5792     attrPtr.p->extLength = attrDesc.AttributeExtLength;
5793     // charset in upper half of precision
5794     unsigned csNumber = (attrPtr.p->extPrecision >> 16);
5795     if (csNumber != 0) {
5796       /*
5797        * A new charset is first accessed here on this node.
5798        * TODO use separate thread (e.g. via NDBFS) if need to load from file
5799        */
5800       CHARSET_INFO* cs = get_charset(csNumber, MYF(0));
5801       if (cs == NULL) {
5802         parseP->errorCode = CreateTableRef::InvalidCharset;
5803         parseP->errorLine = __LINE__;
5804         return;
5805       }
5806       // XXX should be done somewhere in mysql
5807       all_charsets[cs->number] = cs;
5808       unsigned i = 0;
5809       while (i < noOfCharsets) {
5810         if (charsets[i] == csNumber)
5811           break;
5812         i++;
5813       }
5814       if (i == noOfCharsets) {
5815         noOfCharsets++;
5816         if (noOfCharsets > sizeof(charsets)/sizeof(charsets[0])) {
5817           parseP->errorCode = CreateTableRef::InvalidFormat;
5818           parseP->errorLine = __LINE__;
5819           return;
5820         }
5821         charsets[i] = csNumber;
5822       }
5823     }
5824 
5825     // compute attribute size and array size
5826     bool translateOk = attrDesc.translateExtType();
5827     tabRequire(translateOk, CreateTableRef::Inconsistency);
5828 
5829     if(attrDesc.AttributeArraySize > 65535){
5830       parseP->errorCode = CreateTableRef::ArraySizeTooBig;
5831       parseP->status    = status;
5832       parseP->errorKey  = it.getKey();
5833       parseP->errorLine = __LINE__;
5834       return;
5835     }
5836 
5837     Uint32 desc = 0;
5838     AttributeDescriptor::setType(desc, attrDesc.AttributeExtType);
5839     AttributeDescriptor::setSize(desc, attrDesc.AttributeSize);
5840     AttributeDescriptor::setArraySize(desc, attrDesc.AttributeArraySize);
5841     AttributeDescriptor::setArrayType(desc, attrDesc.AttributeArrayType);
5842     AttributeDescriptor::setNullable(desc, attrDesc.AttributeNullableFlag);
5843     AttributeDescriptor::setDKey(desc, attrDesc.AttributeDKey);
5844     AttributeDescriptor::setPrimaryKey(desc, attrDesc.AttributeKeyFlag);
5845     AttributeDescriptor::setDiskBased(desc, attrDesc.AttributeStorageType == NDB_STORAGETYPE_DISK);
5846     AttributeDescriptor::setDynamic(desc, attrDesc.AttributeDynamic);
5847     attrPtr.p->attributeDescriptor = desc;
5848     attrPtr.p->autoIncrement = attrDesc.AttributeAutoIncrement;
5849     {
5850       char defaultValueBuf [MAX_ATTR_DEFAULT_VALUE_SIZE];
5851 
5852       if (attrDesc.AttributeDefaultValueLen)
5853       {
5854         ndbrequire(attrDesc.AttributeDefaultValueLen >= sizeof(Uint32));
5855 
5856         memcpy(defaultValueBuf, attrDesc.AttributeDefaultValue,
5857                attrDesc.AttributeDefaultValueLen);
5858 
5859         /* Table meta-info is normally stored in network byte order by
5860          * SimpleProperties.
5861          * For the default value, we convert as necessary here
5862          */
5863         /* Convert AttrInfoHeader */
5864         Uint32 a;
5865         memcpy(&a, defaultValueBuf, sizeof(Uint32));
5866         a = ntohl(a);
5867         memcpy(defaultValueBuf, &a, sizeof(Uint32));
5868 
5869         Uint32 remainBytes = attrDesc.AttributeDefaultValueLen - sizeof(Uint32);
5870 
5871         if (remainBytes)
5872         {
5873           /* Convert attribute */
5874           NdbSqlUtil::convertByteOrder(attrDesc.AttributeExtType,
5875                                        attrDesc.AttributeSize,
5876                                        attrDesc.AttributeArrayType,
5877                                        attrDesc.AttributeArraySize,
5878                                        (uchar*) defaultValueBuf + sizeof(Uint32),
5879                                        remainBytes);
5880         }
5881       }
5882 
5883       LocalRope defaultValue(c_rope_pool, attrPtr.p->defaultValue);
5884       defaultValue.assign(defaultValueBuf,
5885                           attrDesc.AttributeDefaultValueLen);
5886     }
5887 
5888     keyCount += attrDesc.AttributeKeyFlag;
5889     nullCount += attrDesc.AttributeNullableFlag;
5890 
5891     const Uint32 aSz = (1 << attrDesc.AttributeSize);
5892     Uint32 sz;
5893     if(aSz != 1)
5894     {
5895       sz = ((aSz * attrDesc.AttributeArraySize) + 31) >> 5;
5896     }
5897     else
5898     {
5899       sz = 0;
5900       nullBits += attrDesc.AttributeArraySize;
5901     }
5902 
5903     if(attrDesc.AttributeArraySize == 0)
5904     {
5905       parseP->errorCode = CreateTableRef::InvalidArraySize;
5906       parseP->status    = status;
5907       parseP->errorKey  = it.getKey();
5908       parseP->errorLine = __LINE__;
5909       return;
5910     }
5911 
5912     recordLength += sz;
5913     if(attrDesc.AttributeKeyFlag){
5914       keyLength += sz;
5915 
5916       if(attrDesc.AttributeNullableFlag){
5917 	parseP->errorCode = CreateTableRef::NullablePrimaryKey;
5918 	parseP->status    = status;
5919 	parseP->errorKey  = it.getKey();
5920 	parseP->errorLine = __LINE__;
5921 	return;
5922       }
5923     }
5924 
5925     c_attributeRecordHash.add(attrPtr);
5926 
5927     int a= AttributeDescriptor::getDiskBased(desc);
5928     int b= AttributeDescriptor::getArrayType(desc);
5929     Uint32 pos= 2*(a ? 1 : 0) + (b == NDB_ARRAYTYPE_FIXED ? 0 : 1);
5930     counts[pos+1]++;
5931 
5932     if(b != NDB_ARRAYTYPE_FIXED && sz == 0)
5933     {
5934       parseP->errorCode = CreateTableRef::VarsizeBitfieldNotSupported;
5935       parseP->status    = status;
5936       parseP->errorKey  = it.getKey();
5937       parseP->errorLine = __LINE__;
5938       return;
5939     }
5940 
5941     if(!it.next())
5942       break;
5943 
5944     if(it.getKey() != DictTabInfo::AttributeName)
5945       break;
5946   }//while
5947 
5948   tablePtr.p->noOfPrimkey = keyCount;
5949   tablePtr.p->noOfNullAttr = nullCount;
5950   tablePtr.p->noOfCharsets = noOfCharsets;
5951   tablePtr.p->tupKeyLength = keyLength;
5952   tablePtr.p->noOfNullBits = nullCount + nullBits;
5953 
5954   tabRequire(recordLength<= MAX_TUPLE_SIZE_IN_WORDS,
5955 	     CreateTableRef::RecordTooBig);
5956   tabRequire(keyLength <= MAX_KEY_SIZE_IN_WORDS,
5957 	     CreateTableRef::InvalidPrimaryKeySize);
5958   tabRequire(keyLength > 0,
5959 	     CreateTableRef::InvalidPrimaryKeySize);
5960   tabRequire(CHECK_SUMA_MESSAGE_SIZE(keyCount, keyLength, attrCount, recordLength),
5961              CreateTableRef::RecordTooBig);
5962 
5963   /* Check that all currently running nodes data support
5964    * table features
5965    */
5966   for (Uint32 nodeId=1; nodeId < MAX_NODES; nodeId++)
5967   {
5968     const NodeInfo& ni = getNodeInfo(nodeId);
5969 
5970     if (ni.m_connected &&
5971         (ni.m_type == NODE_TYPE_DB))
5972     {
5973       /* Check that all nodes support extra bits */
5974       if (tablePtr.p->m_extra_row_gci_bits ||
5975           tablePtr.p->m_extra_row_author_bits)
5976       {
5977         tabRequire(ndb_tup_extrabits(ni.m_version),
5978                    CreateTableRef::FeatureRequiresUpgrade);
5979       }
5980     }
5981   }
5982 
5983 
5984   if(tablePtr.p->m_tablespace_id != RNIL || counts[3] || counts[4])
5985   {
5986     FilegroupPtr tablespacePtr;
5987     if (!find_object(tablespacePtr, tablePtr.p->m_tablespace_id))
5988     {
5989       tabRequire(false, CreateTableRef::InvalidTablespace);
5990     }
5991 
5992     if(tablespacePtr.p->m_type != DictTabInfo::Tablespace)
5993     {
5994       tabRequire(false, CreateTableRef::NotATablespace);
5995     }
5996 
5997     if(tablespacePtr.p->m_version != tableDesc.TablespaceVersion)
5998     {
5999       tabRequire(false, CreateTableRef::InvalidTablespaceVersion);
6000     }
6001   }
6002 }//handleTabInfo()
6003 
6004 // MODULE: block/unblock substartstop
6005 void
block_substartstop(Signal * signal,SchemaOpPtr op_ptr)6006 Dbdict::block_substartstop(Signal* signal, SchemaOpPtr op_ptr)
6007 {
6008   ndbrequire(c_sub_startstop_lock.get(getOwnNodeId()) == false);
6009   c_sub_startstop_lock.set(getOwnNodeId());
6010   signal->theData[0] = ZWAIT_SUBSTARTSTOP;
6011   signal->theData[1] = op_ptr.p->op_key;
6012   sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
6013 }
6014 
6015 void
unblock_substartstop()6016 Dbdict::unblock_substartstop()
6017 {
6018   ndbrequire(c_sub_startstop_lock.get(getOwnNodeId()));
6019   c_sub_startstop_lock.clear(getOwnNodeId());
6020 }
6021 
6022 void
wait_substartstop(Signal * signal,Uint32 opkey)6023 Dbdict::wait_substartstop(Signal* signal, Uint32 opkey)
6024 {
6025   if (c_outstanding_sub_startstop == 0)
6026   {
6027     jam();
6028     Callback callback;
6029     bool ok = findCallback(callback, opkey);
6030     ndbrequire(ok);
6031     execute(signal, callback, 0);
6032     return;
6033   }
6034 
6035   signal->theData[0] = ZWAIT_SUBSTARTSTOP;
6036   signal->theData[1] = opkey;
6037   sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100,
6038                       signal->length());
6039 }
6040 
6041 /* ---------------------------------------------------------------- */
6042 // New global checkpoint created.
6043 /* ---------------------------------------------------------------- */
6044 void
wait_gcp(Signal * signal,SchemaOpPtr op_ptr,Uint32 flags)6045 Dbdict::wait_gcp(Signal* signal, SchemaOpPtr op_ptr, Uint32 flags)
6046 {
6047   WaitGCPReq* req = (WaitGCPReq*)signal->getDataPtrSend();
6048 
6049   req->senderRef = reference();
6050   req->senderData = op_ptr.p->op_key;
6051   req->requestType = flags;
6052 
6053   sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
6054              WaitGCPReq::SignalLength, JBB);
6055 }
6056 
execWAIT_GCP_CONF(Signal * signal)6057 void Dbdict::execWAIT_GCP_CONF(Signal* signal)
6058 {
6059   WaitGCPConf* conf = (WaitGCPConf*)signal->getDataPtr();
6060   handleDictConf(signal, conf);
6061 }//execWAIT_GCP_CONF()
6062 
6063 /* ---------------------------------------------------------------- */
6064 // Refused new global checkpoint.
6065 /* ---------------------------------------------------------------- */
execWAIT_GCP_REF(Signal * signal)6066 void Dbdict::execWAIT_GCP_REF(Signal* signal)
6067 {
6068   jamEntry();
6069   WaitGCPRef* ref = (WaitGCPRef*)signal->getDataPtr();
6070   handleDictRef(signal, ref);
6071 }//execWAIT_GCP_REF()
6072 
6073 // MODULE: CreateTable
6074 
6075 const Dbdict::OpInfo
6076 Dbdict::CreateTableRec::g_opInfo = {
6077   { 'C', 'T', 'a', 0 },
6078   ~RT_DBDICT_CREATE_TABLE,
6079   GSN_CREATE_TAB_REQ,
6080   CreateTabReq::SignalLength,
6081   //
6082   &Dbdict::createTable_seize,
6083   &Dbdict::createTable_release,
6084   //
6085   &Dbdict::createTable_parse,
6086   &Dbdict::createTable_subOps,
6087   &Dbdict::createTable_reply,
6088   //
6089   &Dbdict::createTable_prepare,
6090   &Dbdict::createTable_commit,
6091   &Dbdict::createTable_complete,
6092   //
6093   &Dbdict::createTable_abortParse,
6094   &Dbdict::createTable_abortPrepare
6095 };
6096 
6097 bool
createTable_seize(SchemaOpPtr op_ptr)6098 Dbdict::createTable_seize(SchemaOpPtr op_ptr)
6099 {
6100   return seizeOpRec<CreateTableRec>(op_ptr);
6101 }
6102 
6103 void
createTable_release(SchemaOpPtr op_ptr)6104 Dbdict::createTable_release(SchemaOpPtr op_ptr)
6105 {
6106   CreateTableRecPtr createTabPtr;
6107   getOpRec(op_ptr, createTabPtr);
6108   if (createTabPtr.p->m_tabInfoPtrI != RNIL) {
6109     jam();
6110     SegmentedSectionPtr ss_ptr;
6111     getSection(ss_ptr, createTabPtr.p->m_tabInfoPtrI);
6112     SimulatedBlock::release(ss_ptr);
6113     createTabPtr.p->m_tabInfoPtrI = RNIL;
6114   }
6115   if (createTabPtr.p->m_fragmentsPtrI != RNIL) {
6116     jam();
6117     SegmentedSectionPtr ss_ptr;
6118     getSection(ss_ptr, createTabPtr.p->m_fragmentsPtrI);
6119     SimulatedBlock::release(ss_ptr);
6120     createTabPtr.p->m_fragmentsPtrI = RNIL;
6121   }
6122   releaseOpRec<CreateTableRec>(op_ptr);
6123 }
6124 
6125 void
execCREATE_TABLE_REQ(Signal * signal)6126 Dbdict::execCREATE_TABLE_REQ(Signal* signal)
6127 {
6128   jamEntry();
6129   if (!assembleFragments(signal)) {
6130     jam();
6131     return;
6132   }
6133   SectionHandle handle(this, signal);
6134 
6135   if (check_sender_version(signal, MAKE_VERSION(6,4,0)) < 0)
6136   {
6137     jam();
6138     /**
6139      * Pekka has for some obscure reason switched places of
6140      *   senderRef/senderData
6141      */
6142     CreateTableReq* tmp = (CreateTableReq*)signal->getDataPtr();
6143     do_swap(tmp->senderRef, tmp->senderData);
6144   }
6145 
6146   const CreateTableReq req_copy =
6147     *(const CreateTableReq*)signal->getDataPtr();
6148   const CreateTableReq* req = &req_copy;
6149 
6150   ErrorInfo error;
6151   do {
6152     SchemaOpPtr op_ptr;
6153     CreateTableRecPtr createTabPtr;
6154     CreateTabReq* impl_req;
6155 
6156     startClientReq(op_ptr, createTabPtr, req, impl_req, error);
6157     if (hasError(error)) {
6158       jam();
6159       break;
6160     }
6161 
6162     impl_req->tableId = RNIL;
6163     impl_req->tableVersion = 0;
6164     impl_req->gci = 0;
6165 
6166     handleClientReq(signal, op_ptr, handle);
6167     return;
6168   } while (0);
6169 
6170   releaseSections(handle);
6171 
6172   CreateTableRef* ref = (CreateTableRef*)signal->getDataPtrSend();
6173   ref->senderRef = reference();
6174   ref->transId = req->transId;
6175   ref->clientData = req->clientData;
6176   getError(error, ref);
6177   ref->errorStatus = error.errorStatus;
6178   ref->errorKey = error.errorKey;
6179 
6180   sendSignal(req->clientRef, GSN_CREATE_TABLE_REF, signal,
6181 	     CreateTableRef::SignalLength, JBB);
6182 }
6183 
6184 // CreateTable: PARSE
6185 
6186 Uint32
get_fragmentation(Signal * signal,Uint32 tableId)6187 Dbdict::get_fragmentation(Signal* signal, Uint32 tableId)
6188 {
6189   CreateFragmentationReq * req =
6190     (CreateFragmentationReq*)signal->getDataPtrSend();
6191   req->senderRef = 0;
6192   req->senderData = RNIL;
6193   req->fragmentationType = 0;
6194   req->noOfFragments = 0;
6195   req->primaryTableId = tableId;
6196   req->requestInfo = CreateFragmentationReq::RI_GET_FRAGMENTATION;
6197   EXECUTE_DIRECT(DBDICT, GSN_CREATE_FRAGMENTATION_REQ, signal,
6198                  CreateFragmentationReq::SignalLength);
6199 
6200   return signal->theData[0];
6201 }
6202 
6203 Uint32
create_fragmentation(Signal * signal,TableRecordPtr tabPtr,const Uint16 * src,Uint32 cnt,Uint32 flags)6204 Dbdict::create_fragmentation(Signal* signal,
6205                              TableRecordPtr tabPtr,
6206                              const Uint16 *src,
6207                              Uint32 cnt,
6208                              Uint32 flags)
6209 {
6210   CreateFragmentationReq* frag_req =
6211     (CreateFragmentationReq*)signal->getDataPtrSend();
6212   frag_req->senderRef = 0; // direct conf
6213   frag_req->senderData = RNIL;
6214   frag_req->primaryTableId = tabPtr.p->primaryTableId;
6215   frag_req->noOfFragments = tabPtr.p->fragmentCount;
6216   frag_req->fragmentationType = tabPtr.p->fragmentType;
6217   frag_req->requestInfo = flags;
6218 
6219   if (tabPtr.p->hashMapObjectId != RNIL)
6220   {
6221     jam();
6222     HashMapRecordPtr hm_ptr;
6223     ndbrequire(find_object(hm_ptr, tabPtr.p->hashMapObjectId));
6224     frag_req->map_ptr_i = hm_ptr.p->m_map_ptr_i;
6225   }
6226   else
6227   {
6228     jam();
6229     frag_req->map_ptr_i = RNIL;
6230   }
6231 
6232   memcpy(signal->theData+25, src, 2*cnt);
6233 
6234   if (cnt != 0 && cnt != tabPtr.p->fragmentCount)
6235   {
6236     /**
6237      * Either you dont specify fragmentation, or
6238      *   you specify it for each fragment
6239      */
6240     return CreateTableRef::InvalidFormat;
6241   }
6242 
6243   if (tabPtr.p->isOrderedIndex()) {
6244     jam();
6245     // ordered index has same fragmentation as the table
6246     frag_req->primaryTableId = tabPtr.p->primaryTableId;
6247     frag_req->fragmentationType = DictTabInfo::DistrKeyOrderedIndex;
6248   }
6249   else if (tabPtr.p->isHashIndex())
6250   {
6251     jam();
6252     /*
6253      * Unique hash indexes has same amount of fragments as primary table
6254      * and distributed in the same manner but has always a normal hash
6255      * fragmentation.
6256      */
6257     frag_req->primaryTableId = RNIL;
6258   }
6259   else
6260   {
6261     jam();
6262     /*
6263      * Blob tables come here with primaryTableId != RNIL but we only need
6264      * it for creating the fragments so we set it to RNIL now that we got
6265      * what we wanted from it to avoid other side effects.
6266      */
6267     tabPtr.p->primaryTableId = RNIL;
6268   }
6269 
6270   EXECUTE_DIRECT(DBDICT, GSN_CREATE_FRAGMENTATION_REQ, signal,
6271                  CreateFragmentationReq::SignalLength);
6272   jamEntry();
6273 
6274   return signal->theData[0];
6275 }
6276 
6277 void
createTable_parse(Signal * signal,bool master,SchemaOpPtr op_ptr,SectionHandle & handle,ErrorInfo & error)6278 Dbdict::createTable_parse(Signal* signal, bool master,
6279                           SchemaOpPtr op_ptr,
6280                           SectionHandle& handle, ErrorInfo& error)
6281 {
6282   D("createTable_parse");
6283 
6284   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
6285   CreateTableRecPtr createTabPtr;
6286   getOpRec(op_ptr, createTabPtr);
6287   CreateTabReq* impl_req = &createTabPtr.p->m_request;
6288 
6289   /*
6290    * Master parses client DictTabInfo (sec 0) into new table record.
6291    * DIH is called to create fragmentation.  The table record is
6292    * then dumped back into DictTabInfo to produce a canonical format.
6293    * The new DictTabInfo (sec 0) and the fragmentation (sec 1) are
6294    * sent to all participants when master parse returns.
6295    */
6296   if (master)
6297   {
6298     jam();
6299 
6300     // parse client DictTabInfo into new TableRecord
6301 
6302     ParseDictTabInfoRecord parseRecord;
6303     parseRecord.requestType = DictTabInfo::CreateTableFromAPI;
6304     parseRecord.errorCode = 0;
6305 
6306     SegmentedSectionPtr ss_ptr;
6307     if (!handle.getSection(ss_ptr, CreateTableReq::DICT_TAB_INFO)) {
6308       jam();
6309       setError(error, CreateTableRef::InvalidFormat, __LINE__);
6310       return;
6311     }
6312     SimplePropertiesSectionReader r(ss_ptr, getSectionSegmentPool());
6313 
6314     handleTabInfoInit(signal, trans_ptr, r, &parseRecord);
6315     releaseSections(handle);
6316 
6317     if (parseRecord.errorCode == 0)
6318     {
6319       if (ERROR_INSERTED(6200) ||
6320           (ERROR_INSERTED(6201) &&
6321            DictTabInfo::isIndex(parseRecord.tablePtr.p->tableType)))
6322       {
6323         jam();
6324         CLEAR_ERROR_INSERT_VALUE;
6325         parseRecord.errorCode = 1;
6326       }
6327     }
6328 
6329     if (parseRecord.errorCode != 0)
6330     {
6331       jam();
6332       if (!parseRecord.tablePtr.isNull())
6333       {
6334         jam();
6335         releaseTableObject(parseRecord.tablePtr.i, true);
6336       }
6337       setError(error, parseRecord);
6338       BaseString::snprintf(error.errorObjectName, sizeof(error.errorObjectName),
6339                            "%s", c_tableDesc.TableName);
6340       return;
6341     }
6342 
6343     TableRecordPtr tabPtr = parseRecord.tablePtr;
6344 
6345     // link operation to object seized in handleTabInfoInit
6346     DictObjectPtr obj_ptr;
6347     {
6348       Uint32 obj_ptr_i = tabPtr.p->m_obj_ptr_i;
6349       bool ok = findDictObject(op_ptr, obj_ptr, obj_ptr_i);
6350       ndbrequire(ok);
6351     }
6352 
6353     {
6354       Uint32 version = getTableEntry(obj_ptr.p->m_id)->m_tableVersion;
6355       tabPtr.p->tableVersion = create_obj_inc_schema_version(version);
6356     }
6357 
6358     // fill in table id and version
6359     impl_req->tableId = obj_ptr.p->m_id;
6360     impl_req->tableVersion = tabPtr.p->tableVersion;
6361 
6362     if (ERROR_INSERTED(6202) ||
6363         (ERROR_INSERTED(6203) &&
6364          DictTabInfo::isIndex(parseRecord.tablePtr.p->tableType)))
6365     {
6366       jam();
6367       CLEAR_ERROR_INSERT_VALUE;
6368       setError(error, 1, __LINE__);
6369       return;
6370     }
6371 
6372     // create fragmentation via DIH (no changes in DIH)
6373     Uint16* frag_data = (Uint16*)(signal->getDataPtr()+25);
6374     Uint32 err = create_fragmentation(signal, tabPtr,
6375                                       c_fragData, c_fragDataLen / 2);
6376     if (err)
6377     {
6378       jam();
6379       setError(error, err, __LINE__);
6380       return;
6381     }
6382 
6383     // save fragmentation in long signal memory
6384     {
6385       // wl3600_todo make a method for this magic stuff
6386       Uint32 count = 2 + (1 + frag_data[0]) * frag_data[1];
6387 
6388       Ptr<SectionSegment> frag_ptr;
6389       bool ok = import(frag_ptr, (Uint32*)frag_data, (count + 1) / 2);
6390       ndbrequire(ok);
6391       createTabPtr.p->m_fragmentsPtrI = frag_ptr.i;
6392 
6393       // save fragment count
6394       tabPtr.p->fragmentCount = frag_data[1];
6395     }
6396 
6397     // dump table record back into DictTabInfo
6398     {
6399       SimplePropertiesSectionWriter w(* this);
6400       packTableIntoPages(w, tabPtr);
6401 
6402       SegmentedSectionPtr ss_ptr;
6403       w.getPtr(ss_ptr);
6404       createTabPtr.p->m_tabInfoPtrI = ss_ptr.i;
6405     }
6406 
6407     // assign signal sections to send to participants
6408     {
6409       SegmentedSectionPtr ss0_ptr;
6410       SegmentedSectionPtr ss1_ptr;
6411 
6412       getSection(ss0_ptr, createTabPtr.p->m_tabInfoPtrI);
6413       getSection(ss1_ptr, createTabPtr.p->m_fragmentsPtrI);
6414 
6415       ndbrequire(handle.m_cnt == 0);
6416       handle.m_ptr[CreateTabReq::DICT_TAB_INFO] = ss0_ptr;
6417       handle.m_ptr[CreateTabReq::FRAGMENTATION] = ss1_ptr;
6418       handle.m_cnt = 2;
6419 
6420       // handle owns the memory now
6421       createTabPtr.p->m_tabInfoPtrI = RNIL;
6422       createTabPtr.p->m_fragmentsPtrI = RNIL;
6423     }
6424   }
6425   else if (op_ptr.p->m_restart)
6426   {
6427     jam();
6428     impl_req->tableId = c_restartRecord.activeTable;
6429     impl_req->tableVersion = c_restartRecord.m_entry.m_tableVersion;
6430     impl_req->gci = c_restartRecord.m_entry.m_gcp;
6431   }
6432 
6433   const Uint32 gci = impl_req->gci;
6434   const Uint32 tableId = impl_req->tableId;
6435   const Uint32 tableVersion = impl_req->tableVersion;
6436 
6437   SegmentedSectionPtr tabInfoPtr;
6438   {
6439     bool ok = handle.getSection(tabInfoPtr, CreateTabReq::DICT_TAB_INFO);
6440     ndbrequire(ok);
6441   }
6442 
6443   // wl3600_todo parse the rewritten DictTabInfo in master too
6444   if (!master)
6445   {
6446     jam();
6447     createTabPtr.p->m_request.tableId = tableId;
6448 
6449     ParseDictTabInfoRecord parseRecord;
6450     parseRecord.requestType = DictTabInfo::AddTableFromDict;
6451     parseRecord.errorCode = 0;
6452 
6453     SimplePropertiesSectionReader r(tabInfoPtr, getSectionSegmentPool());
6454 
6455     bool checkExist = true;
6456     handleTabInfoInit(signal, trans_ptr, r, &parseRecord, checkExist);
6457 
6458     if (parseRecord.errorCode != 0)
6459     {
6460       jam();
6461       setError(error, parseRecord);
6462       BaseString::snprintf(error.errorObjectName, sizeof(error.errorObjectName),
6463                            "%s", c_tableDesc.TableName);
6464       return;
6465     }
6466 
6467     TableRecordPtr tabPtr = parseRecord.tablePtr;
6468 
6469     // link operation to object seized in handleTabInfoInit
6470     {
6471       DictObjectPtr obj_ptr;
6472       Uint32 obj_ptr_i = tabPtr.p->m_obj_ptr_i;
6473       bool ok = findDictObject(op_ptr, obj_ptr, obj_ptr_i);
6474       ndbrequire(ok);
6475     }
6476   }
6477 
6478   {
6479     SegmentedSectionPtr ptr;
6480     handle.getSection(ptr, CreateTabReq::DICT_TAB_INFO);
6481     if (ptr.sz > MAX_WORDS_META_FILE)
6482     {
6483       jam();
6484       setError(error, CreateTableRef::TableDefinitionTooBig, __LINE__);
6485       return;
6486     }
6487   }
6488 
6489   // save sections to DICT memory
6490   saveOpSection(op_ptr, handle, CreateTabReq::DICT_TAB_INFO);
6491   if (op_ptr.p->m_restart == 0)
6492   {
6493     jam();
6494     saveOpSection(op_ptr, handle, CreateTabReq::FRAGMENTATION);
6495   }
6496 
6497   TableRecordPtr tabPtr;
6498   bool ok = find_object(tabPtr, tableId);
6499   if (!ok)
6500   {
6501     jam();
6502     setError(error, GetTabInfoRef::TableNotDefined, __LINE__);
6503     return;
6504   }
6505   tabPtr.p->packedSize = tabInfoPtr.sz;
6506   // wl3600_todo verify version on slave
6507   tabPtr.p->tableVersion = tableVersion;
6508   tabPtr.p->gciTableCreated = gci;
6509 
6510   if (ERROR_INSERTED(6121)) {
6511     jam();
6512     CLEAR_ERROR_INSERT_VALUE;
6513     setError(error, 9121, __LINE__);
6514     return;
6515   }
6516 
6517   SchemaFile::TableEntry te; te.init();
6518   te.m_tableState = SchemaFile::SF_CREATE;
6519   te.m_tableVersion = tableVersion;
6520   te.m_tableType = tabPtr.p->tableType;
6521   te.m_info_words = tabInfoPtr.sz;
6522   te.m_gcp = gci;
6523   te.m_transId = trans_ptr.p->m_transId;
6524 
6525   Uint32 err = trans_log_schema_op(op_ptr, tableId, &te);
6526   if (err)
6527   {
6528     jam();
6529     setError(error, err, __LINE__);
6530     return;
6531   }
6532   D("createTable_parse: "
6533     << copyRope<MAX_TAB_NAME_SIZE>(tabPtr.p->tableName)
6534     << V(tabPtr.p->tableVersion));
6535 }
6536 
6537 bool
createTable_subOps(Signal * signal,SchemaOpPtr op_ptr)6538 Dbdict::createTable_subOps(Signal* signal, SchemaOpPtr op_ptr)
6539 {
6540   D("createTable_subOps" << V(op_ptr.i) << *op_ptr.p);
6541   // wl3600_todo blobs
6542   return false;
6543 }
6544 
6545 void
createTable_reply(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)6546 Dbdict::createTable_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
6547 {
6548   jam();
6549   D("createTable_reply" << V(op_ptr.i) << *op_ptr.p);
6550 
6551   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
6552 
6553   CreateTableRecPtr createTabPtr;
6554   getOpRec(op_ptr, createTabPtr);
6555 
6556   if (!hasError(error)) {
6557     CreateTableConf* conf = (CreateTableConf*)signal->getDataPtrSend();
6558     conf->senderRef = reference();
6559     conf->clientData = op_ptr.p->m_clientData;
6560     conf->transId = trans_ptr.p->m_transId;
6561     conf->tableId = createTabPtr.p->m_request.tableId;
6562     conf->tableVersion = createTabPtr.p->m_request.tableVersion;
6563 
6564     D(V(conf->tableId) << V(conf->tableVersion));
6565 
6566     Uint32 clientRef = op_ptr.p->m_clientRef;
6567     sendSignal(clientRef, GSN_CREATE_TABLE_CONF, signal,
6568                CreateTableConf::SignalLength, JBB);
6569   } else {
6570     jam();
6571     CreateTableRef* ref = (CreateTableRef*)signal->getDataPtrSend();
6572     ref->senderRef = reference();
6573     ref->clientData = op_ptr.p->m_clientData;
6574     ref->transId = trans_ptr.p->m_transId;
6575     getError(error, ref);
6576     ref->errorStatus = error.errorStatus;
6577     ref->errorKey = error.errorKey;
6578 
6579     Uint32 clientRef = op_ptr.p->m_clientRef;
6580     sendSignal(clientRef, GSN_CREATE_TABLE_REF, signal,
6581                CreateTableRef::SignalLength, JBB);
6582   }
6583 }
6584 
6585 // CreateTable: PREPARE
6586 
6587 void
createTable_prepare(Signal * signal,SchemaOpPtr op_ptr)6588 Dbdict::createTable_prepare(Signal* signal, SchemaOpPtr op_ptr)
6589 {
6590   jam();
6591   CreateTableRecPtr createTabPtr;
6592   getOpRec(op_ptr, createTabPtr);
6593 
6594   Uint32 tableId = createTabPtr.p->m_request.tableId;
6595   TableRecordPtr tabPtr;
6596   bool ok = find_object(tabPtr, tableId);
6597 
6598   Callback cb;
6599   cb.m_callbackData = op_ptr.p->op_key;
6600   cb.m_callbackFunction = safe_cast(&Dbdict::createTab_writeTableConf);
6601 
6602   if (ZRESTART_NO_WRITE_AFTER_READ && op_ptr.p->m_restart == 1)
6603   {
6604     jam();
6605     /**
6606      * We read obj from disk, no need to rewrite it
6607      */
6608     execute(signal, cb, 0);
6609     return;
6610   }
6611 
6612   ndbrequire(ok);
6613   bool savetodisk = !(tabPtr.p->m_bits & TableRecord::TR_Temporary);
6614   if (savetodisk)
6615   {
6616     jam();
6617     const OpSection& tabInfoSec =
6618       getOpSection(op_ptr, CreateTabReq::DICT_TAB_INFO);
6619     writeTableFile(signal, op_ptr, createTabPtr.p->m_request.tableId,
6620                    tabInfoSec, &cb);
6621   }
6622   else
6623   {
6624     jam();
6625     execute(signal, cb, 0);
6626   }
6627 }
6628 
6629 void
createTab_writeTableConf(Signal * signal,Uint32 op_key,Uint32 ret)6630 Dbdict::createTab_writeTableConf(Signal* signal,
6631 				 Uint32 op_key,
6632 				 Uint32 ret)
6633 {
6634   jam();
6635 
6636   SchemaOpPtr op_ptr;
6637   CreateTableRecPtr createTabPtr;
6638   findSchemaOp(op_ptr, createTabPtr, op_key);
6639   ndbrequire(!op_ptr.isNull());
6640 
6641   OpSection& fragSec = op_ptr.p->m_section[CreateTabReq::FRAGMENTATION];
6642   if (op_ptr.p->m_restart)
6643   {
6644     jam();
6645     new (&fragSec) OpSection();
6646   }
6647   else
6648   {
6649     const OpSection& fragSec =
6650       getOpSection(op_ptr, CreateTabReq::FRAGMENTATION);
6651     ndbrequire(fragSec.getSize() > 0);
6652   }
6653 
6654   Callback callback;
6655   callback.m_callbackData = op_ptr.p->op_key;
6656   callback.m_callbackFunction =
6657     safe_cast(&Dbdict::createTab_localComplete);
6658 
6659   createTab_local(signal, op_ptr, fragSec, &callback);
6660 }
6661 
6662 void
createTab_local(Signal * signal,SchemaOpPtr op_ptr,OpSection afragSec,Callback * c)6663 Dbdict::createTab_local(Signal* signal,
6664                         SchemaOpPtr op_ptr,
6665                         OpSection afragSec,
6666                         Callback * c)
6667 {
6668   jam();
6669   CreateTableRecPtr createTabPtr;
6670   getOpRec(op_ptr, createTabPtr);
6671 
6672   createTabPtr.p->m_callback = * c;
6673 
6674   TableRecordPtr tabPtr;
6675   bool ok = find_object(tabPtr, createTabPtr.p->m_request.tableId);
6676   ndbrequire(ok);
6677 
6678   /**
6679    * Start by createing table in LQH
6680    */
6681   CreateTabReq* req = (CreateTabReq*)signal->getDataPtrSend();
6682   req->senderRef = reference();
6683   req->senderData = op_ptr.p->op_key;
6684   req->tableId = createTabPtr.p->m_request.tableId;
6685   req->tableVersion = tabPtr.p->tableVersion;
6686   req->requestType = 0;
6687   req->gci = 0;
6688   req->noOfCharsets = tabPtr.p->noOfCharsets;
6689   req->tableType = tabPtr.p->tableType;
6690   req->primaryTableId = tabPtr.p->primaryTableId;
6691   req->forceVarPartFlag = !!(tabPtr.p->m_bits& TableRecord::TR_ForceVarPart);
6692   req->noOfNullAttributes = tabPtr.p->noOfNullBits;
6693   req->noOfKeyAttr = tabPtr.p->noOfPrimkey;
6694   req->checksumIndicator = 1;
6695   req->GCPIndicator = 1 + tabPtr.p->m_extra_row_gci_bits;
6696   req->noOfAttributes = tabPtr.p->noOfAttributes;
6697   req->extraRowAuthorBits = tabPtr.p->m_extra_row_author_bits;
6698   sendSignal(DBLQH_REF, GSN_CREATE_TAB_REQ, signal,
6699              CreateTabReq::SignalLengthLDM, JBB);
6700 
6701 
6702   /**
6703    * Create KeyDescriptor
6704    */
6705   {
6706     KeyDescriptor* desc= g_key_descriptor_pool.getPtr(createTabPtr.p->m_request.tableId);
6707     new (desc) KeyDescriptor();
6708 
6709     if (tabPtr.p->primaryTableId == RNIL)
6710     {
6711       jam();
6712       desc->primaryTableId = createTabPtr.p->m_request.tableId;
6713     }
6714     else
6715     {
6716       jam();
6717       desc->primaryTableId = tabPtr.p->primaryTableId;
6718     }
6719 
6720     Uint32 key = 0;
6721     AttributeRecordPtr attrPtr;
6722     LocalAttributeRecord_list list(c_attributeRecordPool,
6723                                           tabPtr.p->m_attributes);
6724     for(list.first(attrPtr); !attrPtr.isNull(); list.next(attrPtr))
6725     {
6726       AttributeRecord* aRec = attrPtr.p;
6727       if (aRec->tupleKey)
6728       {
6729         Uint32 attr = aRec->attributeDescriptor;
6730 
6731         desc->noOfKeyAttr ++;
6732         desc->keyAttr[key].attributeDescriptor = attr;
6733         Uint32 csNumber = (aRec->extPrecision >> 16);
6734         if (csNumber)
6735         {
6736           desc->keyAttr[key].charsetInfo = all_charsets[csNumber];
6737           ndbrequire(all_charsets[csNumber] != 0);
6738           desc->hasCharAttr = 1;
6739         }
6740         else
6741         {
6742           desc->keyAttr[key].charsetInfo = 0;
6743         }
6744         if (AttributeDescriptor::getDKey(attr))
6745         {
6746           desc->noOfDistrKeys ++;
6747         }
6748         if (AttributeDescriptor::getArrayType(attr) != NDB_ARRAYTYPE_FIXED)
6749         {
6750           desc->noOfVarKeys ++;
6751         }
6752         key++;
6753       }
6754     }
6755     ndbrequire(key == tabPtr.p->noOfPrimkey);
6756   }
6757 }
6758 
6759 void
execCREATE_TAB_REF(Signal * signal)6760 Dbdict::execCREATE_TAB_REF(Signal* signal)
6761 {
6762   jamEntry();
6763 
6764   CreateTabRef * const ref = (CreateTabRef*)signal->getDataPtr();
6765 
6766   SchemaOpPtr op_ptr;
6767   CreateTableRecPtr createTabPtr;
6768   findSchemaOp(op_ptr, createTabPtr, ref->senderData);
6769   ndbrequire(!op_ptr.isNull());
6770 
6771   setError(op_ptr, ref->errorCode, __LINE__);
6772   execute(signal, createTabPtr.p->m_callback, 0);
6773 }
6774 
6775 void
execCREATE_TAB_CONF(Signal * signal)6776 Dbdict::execCREATE_TAB_CONF(Signal* signal)
6777 {
6778   jamEntry();
6779 
6780   CreateTabConf* conf = (CreateTabConf*)signal->getDataPtr();
6781 
6782   SchemaOpPtr op_ptr;
6783   CreateTableRecPtr createTabPtr;
6784   findSchemaOp(op_ptr, createTabPtr, conf->senderData);
6785   ndbrequire(!op_ptr.isNull());
6786 
6787   createTabPtr.p->m_lqhFragPtr = conf->lqhConnectPtr;
6788 
6789   TableRecordPtr tabPtr;
6790   bool ok = find_object(tabPtr, createTabPtr.p->m_request.tableId);
6791   ndbrequire(ok);
6792   sendLQHADDATTRREQ(signal, op_ptr, tabPtr.p->m_attributes.getFirst());
6793 }
6794 
6795 
6796 void
sendLQHADDATTRREQ(Signal * signal,SchemaOpPtr op_ptr,Uint32 attributePtrI)6797 Dbdict::sendLQHADDATTRREQ(Signal* signal,
6798 			  SchemaOpPtr op_ptr,
6799 			  Uint32 attributePtrI)
6800 {
6801   jam();
6802   CreateTableRecPtr createTabPtr;
6803   getOpRec(op_ptr, createTabPtr);
6804 
6805   TableRecordPtr tabPtr;
6806   bool ok = find_object(tabPtr, createTabPtr.p->m_request.tableId);
6807   ndbrequire(ok);
6808 
6809   const bool isHashIndex = tabPtr.p->isHashIndex();
6810 
6811   LqhAddAttrReq * const req = (LqhAddAttrReq*)signal->getDataPtrSend();
6812   Uint32 i = 0;
6813   Uint32 startIndex = 25;
6814   Uint32 *defVal_dst = &signal->theData[startIndex];
6815   Uint32 defVal_length = 0;
6816   for(i = 0; i<LqhAddAttrReq::MAX_ATTRIBUTES && attributePtrI != RNIL; i++){
6817     jam();
6818     AttributeRecordPtr attrPtr;
6819     c_attributeRecordPool.getPtr(attrPtr, attributePtrI);
6820     LqhAddAttrReq::Entry& entry = req->attributes[i];
6821     entry.attrId = attrPtr.p->attributeId;
6822     entry.attrDescriptor = attrPtr.p->attributeDescriptor;
6823     entry.extTypeInfo = 0;
6824     // charset number passed to TUP, TUX in upper half
6825     entry.extTypeInfo |= (attrPtr.p->extPrecision & ~0xFFFF);
6826 
6827     ConstRope def(c_rope_pool, attrPtr.p->defaultValue);
6828     def.copy((char*)defVal_dst);
6829 
6830     Uint32 defValueLen = def.size();
6831     defVal_length += (defValueLen + 3)/4;
6832     defVal_dst += (defValueLen + 3)/4;
6833 
6834     if (tabPtr.p->isIndex()) {
6835       Uint32 primaryAttrId;
6836       if (attrPtr.p->nextList != RNIL) {
6837         getIndexAttr(tabPtr, attributePtrI, &primaryAttrId);
6838       } else {
6839         primaryAttrId = ZNIL;
6840         if (tabPtr.p->isOrderedIndex())
6841           entry.attrId = 0;     // attribute goes to TUP
6842       }
6843       entry.attrId |= (primaryAttrId << 16);
6844     }
6845 
6846     if (attrPtr.p->nextList == RNIL && isHashIndex)
6847     {
6848       jam();
6849       /**
6850        * Nasty code to handle upgrade of unique index(es)
6851        *   If unique index is "old" rewrite it to new format
6852        */
6853       char tmp[MAX_TAB_NAME_SIZE];
6854       ConstRope name(c_rope_pool, attrPtr.p->attributeName);
6855       name.copy(tmp);
6856       ndbrequire(memcmp(tmp, "NDB$PK", sizeof("NDB$PK")) == 0);
6857       Uint32 at = AttributeDescriptor::getArrayType(entry.attrDescriptor);
6858       if (at == NDB_ARRAYTYPE_MEDIUM_VAR)
6859       {
6860         jam();
6861         AttributeDescriptor::clearArrayType(entry.attrDescriptor);
6862         AttributeDescriptor::setArrayType(entry.attrDescriptor,
6863                                           NDB_ARRAYTYPE_NONE_VAR);
6864       }
6865     }
6866 
6867     attributePtrI = attrPtr.p->nextList;
6868   }
6869   req->lqhFragPtr = createTabPtr.p->m_lqhFragPtr;
6870   req->senderData = op_ptr.p->op_key;
6871   req->senderAttrPtr = attributePtrI;
6872   req->noOfAttributes = i;
6873 
6874   if (defVal_length != 0)
6875   {
6876     LinearSectionPtr ptr[3];
6877     ptr[0].p= &signal->theData[startIndex];
6878     ptr[0].sz= defVal_length;
6879 
6880     sendSignal(DBLQH_REF, GSN_LQHADDATTREQ, signal,
6881        	       LqhAddAttrReq::HeaderLength + LqhAddAttrReq::EntryLength * i, JBB, ptr, 1);
6882   }
6883   else
6884     sendSignal(DBLQH_REF, GSN_LQHADDATTREQ, signal,
6885                LqhAddAttrReq::HeaderLength + LqhAddAttrReq::EntryLength * i, JBB);
6886 }
6887 
6888 void
execLQHADDATTCONF(Signal * signal)6889 Dbdict::execLQHADDATTCONF(Signal * signal)
6890 {
6891   jamEntry();
6892   LqhAddAttrConf * const conf = (LqhAddAttrConf*)signal->getDataPtr();
6893 
6894   SchemaOpPtr op_ptr;
6895   CreateTableRecPtr createTabPtr;
6896   findSchemaOp(op_ptr, createTabPtr, conf->senderData);
6897   ndbrequire(!op_ptr.isNull());
6898 
6899   const Uint32 nextAttrPtr = conf->senderAttrPtr;
6900   if(nextAttrPtr != RNIL){
6901     jam();
6902     sendLQHADDATTRREQ(signal, op_ptr, nextAttrPtr);
6903     return;
6904   }
6905 
6906   createTab_dih(signal, op_ptr);
6907 }
6908 
6909 void
execLQHADDATTREF(Signal * signal)6910 Dbdict::execLQHADDATTREF(Signal * signal)
6911 {
6912   jamEntry();
6913   LqhAddAttrRef * const ref = (LqhAddAttrRef*)signal->getDataPtr();
6914 
6915   SchemaOpPtr op_ptr;
6916   CreateTableRecPtr createTabPtr;
6917   findSchemaOp(op_ptr, createTabPtr, ref->senderData);
6918   ndbrequire(!op_ptr.isNull());
6919 
6920   setError(op_ptr, ref->errorCode, __LINE__);
6921 
6922   sendTransConf(signal, op_ptr);
6923 }
6924 
6925 void
createTab_dih(Signal * signal,SchemaOpPtr op_ptr)6926 Dbdict::createTab_dih(Signal* signal, SchemaOpPtr op_ptr)
6927 {
6928   CreateTableRecPtr createTabPtr;
6929   getOpRec(op_ptr, createTabPtr);
6930   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
6931 
6932   D("createTab_dih" << *op_ptr.p);
6933 
6934   TableRecordPtr tabPtr;
6935   bool ok = find_object(tabPtr, createTabPtr.p->m_request.tableId);
6936   ndbrequire(ok);
6937 
6938   /**
6939    * NOTE: use array access here...
6940    *   as during SR m_noOfSections == 0
6941    *   i.e getOpSection will crash
6942    */
6943   const OpSection& fragSec = op_ptr.p->m_section[CreateTabReq::FRAGMENTATION];
6944 
6945   DiAddTabReq * req = (DiAddTabReq*)signal->getDataPtrSend();
6946   req->connectPtr = op_ptr.p->op_key;
6947   req->tableId = createTabPtr.p->m_request.tableId;
6948   req->fragType = tabPtr.p->fragmentType;
6949   req->kValue = tabPtr.p->kValue;
6950   req->noOfReplicas = 0;
6951   req->loggedTable = !!(tabPtr.p->m_bits & TableRecord::TR_Logged);
6952   req->tableType = tabPtr.p->tableType;
6953   req->schemaVersion = tabPtr.p->tableVersion;
6954   req->primaryTableId = tabPtr.p->primaryTableId;
6955   req->temporaryTable = !!(tabPtr.p->m_bits & TableRecord::TR_Temporary);
6956   // no transaction for restart tab (should add one)
6957   req->schemaTransId = !trans_ptr.isNull() ? trans_ptr.p->m_transId : 0;
6958 
6959   if (tabPtr.p->hashMapObjectId != RNIL)
6960   {
6961     HashMapRecordPtr hm_ptr;
6962     ndbrequire(find_object(hm_ptr, tabPtr.p->hashMapObjectId));
6963     req->hashMapPtrI = hm_ptr.p->m_map_ptr_i;
6964   }
6965   else
6966   {
6967     req->hashMapPtrI = RNIL;
6968   }
6969 
6970   // fragmentation in long signal section
6971   {
6972     Uint32 page[MAX_FRAGMENT_DATA_WORDS];
6973     LinearSectionPtr ptr[3];
6974     Uint32 noOfSections = 0;
6975 
6976     const Uint32 size = fragSec.getSize();
6977     ndbrequire(size <= NDB_ARRAY_SIZE(page));
6978 
6979     // wl3600_todo add ndbrequire on SR, NR
6980     if (size != 0) {
6981       jam();
6982       LocalArenaPoolImpl op_sec_pool(op_ptr.p->m_trans_ptr.p->m_arena,c_opSectionBufferPool);
6983       bool ok = copyOut(op_sec_pool, fragSec, page, size);
6984       ndbrequire(ok);
6985       ptr[noOfSections].sz = size;
6986       ptr[noOfSections].p = page;
6987       noOfSections++;
6988     }
6989 
6990     sendSignal(DBDIH_REF, GSN_DIADDTABREQ, signal,
6991                DiAddTabReq::SignalLength, JBB,
6992                ptr, noOfSections);
6993   }
6994 }
6995 
6996 static
6997 void
calcLHbits(Uint32 * lhPageBits,Uint32 * lhDistrBits,Uint32 fid,Uint32 totalFragments,Dbdict * dict)6998 calcLHbits(Uint32 * lhPageBits, Uint32 * lhDistrBits,
6999 	   Uint32 fid, Uint32 totalFragments, Dbdict * dict)
7000 {
7001   Uint32 distrBits = 0;
7002   Uint32 pageBits = 0;
7003 
7004   Uint32 tmp = 1;
7005   while (tmp < totalFragments) {
7006     jamBlock(dict);
7007     tmp <<= 1;
7008     distrBits++;
7009   }//while
7010 #ifdef ndb_classical_lhdistrbits
7011   if (tmp != totalFragments) {
7012     tmp >>= 1;
7013     if ((fid >= (totalFragments - tmp)) && (fid < (tmp - 1))) {
7014       distrBits--;
7015     }//if
7016   }//if
7017 #endif
7018   * lhPageBits = pageBits;
7019   * lhDistrBits = distrBits;
7020 
7021 }//calcLHbits()
7022 
7023 void
execADD_FRAGREQ(Signal * signal)7024 Dbdict::execADD_FRAGREQ(Signal* signal)
7025 {
7026   jamEntry();
7027 
7028   AddFragReq * const req = (AddFragReq*)signal->getDataPtr();
7029 
7030   Uint32 dihPtr = req->dihPtr;
7031   Uint32 senderData = req->senderData;
7032   Uint32 tableId = req->tableId;
7033   Uint32 fragId = req->fragmentId;
7034   Uint32 node = req->nodeId;
7035   Uint32 lcpNo = req->nextLCP;
7036   Uint32 fragCount = req->totalFragments;
7037   Uint32 requestInfo = req->requestInfo;
7038   Uint32 startGci = req->startGci;
7039   Uint32 logPart = req->logPartId;
7040   Uint32 changeMask = req->changeMask;
7041 
7042   ndbrequire(node == getOwnNodeId());
7043 
7044   SchemaOpPtr op_ptr;
7045   TableRecordPtr tabPtr;
7046   if (AlterTableReq::getAddFragFlag(changeMask))
7047   {
7048     bool ok = find_object(tabPtr, tableId);
7049     ndbrequire(ok);
7050     if (DictTabInfo::isTable(tabPtr.p->tableType))
7051     {
7052       jam();
7053       AlterTableRecPtr alterTabPtr;
7054       findSchemaOp(op_ptr, alterTabPtr, senderData);
7055       ndbrequire(!op_ptr.isNull());
7056       alterTabPtr.p->m_dihAddFragPtr = dihPtr;
7057       tabPtr.i = alterTabPtr.p->m_newTablePtrI;
7058       c_tableRecordPool_.getPtr(tabPtr);
7059     }
7060     else
7061     {
7062       jam();
7063       ndbrequire(DictTabInfo::isOrderedIndex(tabPtr.p->tableType));
7064       AlterIndexRecPtr alterIndexPtr;
7065       findSchemaOp(op_ptr, alterIndexPtr, senderData);
7066       ndbrequire(!op_ptr.isNull());
7067       alterIndexPtr.p->m_dihAddFragPtr = dihPtr;
7068     }
7069   }
7070   else
7071   {
7072     jam();
7073     CreateTableRecPtr createTabPtr;
7074     findSchemaOp(op_ptr, createTabPtr, senderData);
7075     ndbrequire(!op_ptr.isNull());
7076     createTabPtr.p->m_dihAddFragPtr = dihPtr;
7077     bool ok = find_object(tabPtr, tableId);
7078     ndbrequire(ok);
7079   }
7080 
7081 #if 0
7082   tabPtr.p->gciTableCreated = (startGci > tabPtr.p->gciTableCreated ? startGci:
7083 			       startGci > tabPtr.p->gciTableCreated);
7084 #endif
7085 
7086   /**
7087    * Calc lh3PageBits
7088    */
7089   Uint32 lhDistrBits = 0;
7090   Uint32 lhPageBits = 0;
7091   ::calcLHbits(&lhPageBits, &lhDistrBits, fragId, fragCount, this);
7092 
7093   Uint64 maxRows = tabPtr.p->maxRowsLow +
7094     (((Uint64)tabPtr.p->maxRowsHigh) << 32);
7095   Uint64 minRows = tabPtr.p->minRowsLow +
7096     (((Uint64)tabPtr.p->minRowsHigh) << 32);
7097   maxRows = (maxRows + fragCount - 1) / fragCount;
7098   minRows = (minRows + fragCount - 1) / fragCount;
7099 
7100   {
7101     LqhFragReq* req = (LqhFragReq*)signal->getDataPtrSend();
7102     req->senderData = senderData;
7103     req->senderRef = reference();
7104     req->fragmentId = fragId;
7105     req->requestInfo = requestInfo;
7106     req->tableId = tableId;
7107     req->localKeyLength = tabPtr.p->localKeyLen;
7108     req->maxLoadFactor = tabPtr.p->maxLoadFactor;
7109     req->minLoadFactor = tabPtr.p->minLoadFactor;
7110     req->kValue = tabPtr.p->kValue;
7111     req->lh3DistrBits = 0; //lhDistrBits;
7112     req->lh3PageBits = 0; //lhPageBits;
7113     req->maxRowsLow = (Uint32)(maxRows & 0xFFFFFFFF);
7114     req->maxRowsHigh = (Uint32)(maxRows >> 32);
7115     req->minRowsLow = (Uint32)(minRows & 0xFFFFFFFF);
7116     req->minRowsHigh = (Uint32)(minRows >> 32);
7117     Uint32 keyLen = tabPtr.p->tupKeyLength;
7118     req->keyLength = keyLen; // wl-2066 no more "long keys"
7119     req->nextLCP = lcpNo;
7120 
7121     req->startGci = startGci;
7122     req->tablespace_id= tabPtr.p->m_tablespace_id;
7123     req->tablespace_id = tabPtr.p->m_tablespace_id;
7124     req->logPartId = logPart;
7125     req->changeMask = changeMask;
7126     sendSignal(DBLQH_REF, GSN_LQHFRAGREQ, signal,
7127 	       LqhFragReq::SignalLength, JBB);
7128   }
7129 }
7130 
7131 void
execLQHFRAGCONF(Signal * signal)7132 Dbdict::execLQHFRAGCONF(Signal * signal)
7133 {
7134   jamEntry();
7135   LqhFragConf * const conf = (LqhFragConf*)signal->getDataPtr();
7136 
7137   Uint32 dihPtr;
7138   Uint32 fragId = conf->fragId;
7139   Uint32 tableId = conf->tableId;
7140 
7141   if (AlterTableReq::getAddFragFlag(conf->changeMask))
7142   {
7143     jam();
7144     SchemaOpPtr op_ptr;
7145     TableRecordPtr tabPtr;
7146     bool ok = find_object(tabPtr, tableId);
7147     ndbrequire(ok);
7148     if (DictTabInfo::isTable(tabPtr.p->tableType))
7149     {
7150       AlterTableRecPtr alterTabPtr;
7151       findSchemaOp(op_ptr, alterTabPtr, conf->senderData);
7152       ndbrequire(!op_ptr.isNull());
7153       dihPtr = alterTabPtr.p->m_dihAddFragPtr;
7154     }
7155     else
7156     {
7157       jam();
7158       ndbrequire(DictTabInfo::isOrderedIndex(tabPtr.p->tableType));
7159       AlterIndexRecPtr alterIndexPtr;
7160       findSchemaOp(op_ptr, alterIndexPtr, conf->senderData);
7161       ndbrequire(!op_ptr.isNull());
7162       dihPtr = alterIndexPtr.p->m_dihAddFragPtr;
7163     }
7164   }
7165   else
7166   {
7167     jam();
7168     SchemaOpPtr op_ptr;
7169     CreateTableRecPtr createTabPtr;
7170     findSchemaOp(op_ptr, createTabPtr, conf->senderData);
7171     ndbrequire(!op_ptr.isNull());
7172 
7173     createTabPtr.p->m_lqhFragPtr = conf->lqhFragPtr;
7174     dihPtr = createTabPtr.p->m_dihAddFragPtr;
7175   }
7176 
7177   {
7178     AddFragConf * const conf = (AddFragConf*)signal->getDataPtr();
7179     conf->dihPtr = dihPtr;
7180     conf->fragId = fragId;
7181     sendSignal(DBDIH_REF, GSN_ADD_FRAGCONF, signal,
7182 	       AddFragConf::SignalLength, JBB);
7183   }
7184 }
7185 
7186 void
execLQHFRAGREF(Signal * signal)7187 Dbdict::execLQHFRAGREF(Signal * signal)
7188 {
7189   jamEntry();
7190   LqhFragRef * const ref = (LqhFragRef*)signal->getDataPtr();
7191 
7192   Uint32 dihPtr;
7193   Uint32 tableId = ref->tableId;
7194   Uint32 fragId = ref->fragId;
7195   if (AlterTableReq::getAddFragFlag(ref->changeMask))
7196   {
7197     jam();
7198     SchemaOpPtr op_ptr;
7199     TableRecordPtr tabPtr;
7200     bool ok = find_object(tabPtr, tableId);
7201     ndbrequire(ok);
7202     if (DictTabInfo::isTable(tabPtr.p->tableType))
7203     {
7204       jam();
7205       AlterTableRecPtr alterTabPtr;
7206       findSchemaOp(op_ptr, alterTabPtr, ref->senderData);
7207       ndbrequire(!op_ptr.isNull());
7208       setError(op_ptr, ref->errorCode, __LINE__);
7209       dihPtr = alterTabPtr.p->m_dihAddFragPtr;
7210     }
7211     else
7212     {
7213       jam();
7214       AlterIndexRecPtr alterIndexPtr;
7215       findSchemaOp(op_ptr, alterIndexPtr, ref->senderData);
7216       ndbrequire(!op_ptr.isNull());
7217       setError(op_ptr, ref->errorCode, __LINE__);
7218       dihPtr = alterIndexPtr.p->m_dihAddFragPtr;
7219     }
7220   }
7221   else
7222   {
7223     jam();
7224     SchemaOpPtr op_ptr;
7225     CreateTableRecPtr createTabPtr;
7226     findSchemaOp(op_ptr, createTabPtr, ref->senderData);
7227     ndbrequire(!op_ptr.isNull());
7228     setError(op_ptr, ref->errorCode, __LINE__);
7229     dihPtr = createTabPtr.p->m_dihAddFragPtr;
7230   }
7231 
7232   {
7233     AddFragRef * const ref = (AddFragRef*)signal->getDataPtr();
7234     ref->dihPtr = dihPtr;
7235     ref->fragId = fragId;
7236     sendSignal(DBDIH_REF, GSN_ADD_FRAGREF, signal,
7237 	       AddFragRef::SignalLength, JBB);
7238   }
7239 }
7240 
7241 void
execDIADDTABCONF(Signal * signal)7242 Dbdict::execDIADDTABCONF(Signal* signal)
7243 {
7244   jam();
7245 
7246   DiAddTabConf * const conf = (DiAddTabConf*)signal->getDataPtr();
7247 
7248   SchemaOpPtr op_ptr;
7249   CreateTableRecPtr createTabPtr;
7250   findSchemaOp(op_ptr, createTabPtr, conf->senderData);
7251   ndbrequire(!op_ptr.isNull());
7252 
7253   signal->theData[0] = op_ptr.p->op_key;
7254   signal->theData[1] = reference();
7255   signal->theData[2] = createTabPtr.p->m_request.tableId;
7256 
7257   sendSignal(DBLQH_REF, GSN_TAB_COMMITREQ, signal, 3, JBB);
7258 }
7259 
7260 void
execDIADDTABREF(Signal * signal)7261 Dbdict::execDIADDTABREF(Signal* signal)
7262 {
7263   jam();
7264 
7265   DiAddTabRef * const ref = (DiAddTabRef*)signal->getDataPtr();
7266 
7267   SchemaOpPtr op_ptr;
7268   CreateTableRecPtr createTabPtr;
7269   findSchemaOp(op_ptr, createTabPtr, ref->senderData);
7270   ndbrequire(!op_ptr.isNull());
7271 
7272   setError(op_ptr, ref->errorCode, __LINE__);
7273   execute(signal, createTabPtr.p->m_callback, 0);
7274 }
7275 
7276 // wl3600_todo split into 2 methods for prepare/commit
7277 void
execTAB_COMMITCONF(Signal * signal)7278 Dbdict::execTAB_COMMITCONF(Signal* signal)
7279 {
7280   jamEntry();
7281 
7282   SchemaOpPtr op_ptr;
7283   CreateTableRecPtr createTabPtr;
7284   findSchemaOp(op_ptr, createTabPtr, signal->theData[0]);
7285   ndbrequire(!op_ptr.isNull());
7286   //const CreateTabReq* impl_req = &createTabPtr.p->m_request;
7287 
7288   TableRecordPtr tabPtr;
7289   bool ok = find_object(tabPtr, createTabPtr.p->m_request.tableId);
7290   ndbrequire(ok);
7291 
7292   if (refToBlock(signal->getSendersBlockRef()) == DBLQH)
7293   {
7294     jam();
7295     // prepare table in DBSPJ
7296     TcSchVerReq * req = (TcSchVerReq*)signal->getDataPtr();
7297     req->tableId = createTabPtr.p->m_request.tableId;
7298     req->tableVersion = tabPtr.p->tableVersion;
7299     req->tableLogged = (Uint32)!!(tabPtr.p->m_bits & TableRecord::TR_Logged);
7300     req->senderRef = reference();
7301     req->tableType = (Uint32)tabPtr.p->tableType;
7302     req->senderData = op_ptr.p->op_key;
7303     req->noOfPrimaryKeys = (Uint32)tabPtr.p->noOfPrimkey;
7304     req->singleUserMode = (Uint32)tabPtr.p->singleUserMode;
7305     req->userDefinedPartition = (tabPtr.p->fragmentType == DictTabInfo::UserDefined);
7306 
7307     if (DictTabInfo::isOrderedIndex(tabPtr.p->tableType))
7308     {
7309       jam();
7310       TableRecordPtr basePtr;
7311       bool ok = find_object(basePtr, tabPtr.p->primaryTableId);
7312       ndbrequire(ok);
7313       req->userDefinedPartition = (basePtr.p->fragmentType == DictTabInfo::UserDefined);
7314     }
7315 
7316     sendSignal(DBSPJ_REF, GSN_TC_SCHVERREQ, signal,
7317                TcSchVerReq::SignalLength, JBB);
7318     return;
7319   }
7320 
7321   if (refToBlock(signal->getSendersBlockRef()) == DBDIH)
7322   {
7323     jam();
7324     // commit table in DBSPJ
7325     signal->theData[0] = op_ptr.p->op_key;
7326     signal->theData[1] = reference();
7327     signal->theData[2] = createTabPtr.p->m_request.tableId;
7328     sendSignal(DBSPJ_REF, GSN_TAB_COMMITREQ, signal, 3, JBB);
7329     return;
7330   }
7331 
7332   if (refToBlock(signal->getSendersBlockRef()) == DBSPJ)
7333   {
7334     jam();
7335     // commit table in DBTC
7336     signal->theData[0] = op_ptr.p->op_key;
7337     signal->theData[1] = reference();
7338     signal->theData[2] = createTabPtr.p->m_request.tableId;
7339     sendSignal(DBTC_REF, GSN_TAB_COMMITREQ, signal, 3, JBB);
7340     return;
7341   }
7342 
7343   if (refToBlock(signal->getSendersBlockRef()) == DBTC)
7344   {
7345     jam();
7346     execute(signal, createTabPtr.p->m_callback, 0);
7347     return;
7348   }
7349 
7350   ndbrequire(false);
7351 }
7352 
7353 void
execTAB_COMMITREF(Signal * signal)7354 Dbdict::execTAB_COMMITREF(Signal* signal) {
7355   jamEntry();
7356   ndbrequire(false);
7357 }//execTAB_COMMITREF()
7358 
7359 void
createTab_localComplete(Signal * signal,Uint32 op_key,Uint32 ret)7360 Dbdict::createTab_localComplete(Signal* signal,
7361                                 Uint32 op_key,
7362                                 Uint32 ret)
7363 {
7364   jam();
7365 
7366   SchemaOpPtr op_ptr;
7367   CreateTableRecPtr createTabPtr;
7368   findSchemaOp(op_ptr, createTabPtr, op_key);
7369   ndbrequire(!op_ptr.isNull());
7370   //const CreateTabReq* impl_req = &createTabPtr.p->m_request;
7371 
7372   //@todo check for master failed
7373 
7374   if (ERROR_INSERTED(6131)) {
7375     jam();
7376     CLEAR_ERROR_INSERT_VALUE;
7377     setError(op_ptr.p->m_error, 9131, __LINE__);
7378   }
7379 
7380   if (!hasError(op_ptr.p->m_error)) {
7381     jam();
7382     // prepare done
7383     sendTransConf(signal, op_ptr);
7384   } else {
7385     jam();
7386     sendTransRef(signal, op_ptr);
7387   }
7388 }
7389 
7390 // CreateTable: COMMIT
7391 
7392 void
createTable_commit(Signal * signal,SchemaOpPtr op_ptr)7393 Dbdict::createTable_commit(Signal* signal, SchemaOpPtr op_ptr)
7394 {
7395   jam();
7396 
7397   CreateTableRecPtr createTabPtr;
7398   getOpRec(op_ptr, createTabPtr);
7399 
7400   Uint32 tableId = createTabPtr.p->m_request.tableId;
7401   TableRecordPtr tabPtr;
7402   bool ok = find_object(tabPtr, tableId);
7403   ndbrequire(ok);
7404 
7405   D("createTable_commit" << *op_ptr.p);
7406 
7407   Callback c;
7408   c.m_callbackData = op_ptr.p->op_key;
7409   c.m_callbackFunction = safe_cast(&Dbdict::createTab_alterComplete);
7410   createTab_activate(signal, op_ptr, &c);
7411 
7412   if (DictTabInfo::isIndex(tabPtr.p->tableType))
7413   {
7414     TableRecordPtr basePtr;
7415     bool ok = find_object(basePtr, tabPtr.p->primaryTableId);
7416     ndbrequire(ok);
7417 
7418     LocalTableRecord_list list(c_tableRecordPool_, basePtr.p->m_indexes);
7419     list.addLast(tabPtr);
7420   }
7421 }
7422 
7423 void
createTab_activate(Signal * signal,SchemaOpPtr op_ptr,Callback * c)7424 Dbdict::createTab_activate(Signal* signal, SchemaOpPtr op_ptr,
7425 			  Callback * c)
7426 {
7427   CreateTableRecPtr createTabPtr;
7428   getOpRec(op_ptr, createTabPtr);
7429   createTabPtr.p->m_callback = * c;
7430 
7431   signal->theData[0] = op_ptr.p->op_key;
7432   signal->theData[1] = reference();
7433   signal->theData[2] = createTabPtr.p->m_request.tableId;
7434   sendSignal(DBDIH_REF, GSN_TAB_COMMITREQ, signal, 3, JBB);
7435 }
7436 
7437 void
execTC_SCHVERCONF(Signal * signal)7438 Dbdict::execTC_SCHVERCONF(Signal* signal)
7439 {
7440   jamEntry();
7441 
7442   SchemaOpPtr op_ptr;
7443   CreateTableRecPtr createTabPtr;
7444   findSchemaOp(op_ptr, createTabPtr, signal->theData[1]);
7445   ndbrequire(!op_ptr.isNull());
7446 
7447   if (refToBlock(signal->getSendersBlockRef()) == DBSPJ)
7448   {
7449     jam();
7450     // prepare table in DBTC
7451     TableRecordPtr tabPtr;
7452     bool ok = find_object(tabPtr, createTabPtr.p->m_request.tableId);
7453     ndbrequire(ok);
7454 
7455     TcSchVerReq * req = (TcSchVerReq*)signal->getDataPtr();
7456     req->tableId = createTabPtr.p->m_request.tableId;
7457     req->tableVersion = tabPtr.p->tableVersion;
7458     req->tableLogged = (Uint32)!!(tabPtr.p->m_bits & TableRecord::TR_Logged);
7459     req->senderRef = reference();
7460     req->tableType = (Uint32)tabPtr.p->tableType;
7461     req->senderData = op_ptr.p->op_key;
7462     req->noOfPrimaryKeys = (Uint32)tabPtr.p->noOfPrimkey;
7463     req->singleUserMode = (Uint32)tabPtr.p->singleUserMode;
7464     req->userDefinedPartition = (tabPtr.p->fragmentType == DictTabInfo::UserDefined);
7465 
7466     if (DictTabInfo::isOrderedIndex(tabPtr.p->tableType))
7467     {
7468       jam();
7469       TableRecordPtr basePtr;
7470       bool ok = find_object(basePtr, tabPtr.p->primaryTableId);
7471       ndbrequire(ok);
7472       req->userDefinedPartition = (basePtr.p->fragmentType == DictTabInfo::UserDefined);
7473     }
7474 
7475     sendSignal(DBTC_REF, GSN_TC_SCHVERREQ, signal,
7476                TcSchVerReq::SignalLength, JBB);
7477     return;
7478   }
7479   ndbrequire(refToBlock(signal->getSendersBlockRef()) == DBTC);
7480   execute(signal, createTabPtr.p->m_callback, 0);
7481 }
7482 
7483 void
createTab_alterComplete(Signal * signal,Uint32 op_key,Uint32 ret)7484 Dbdict::createTab_alterComplete(Signal* signal,
7485 				Uint32 op_key,
7486 				Uint32 ret)
7487 {
7488   jam();
7489 
7490   SchemaOpPtr op_ptr;
7491   CreateTableRecPtr createTabPtr;
7492   findSchemaOp(op_ptr, createTabPtr, op_key);
7493   ndbrequire(!op_ptr.isNull());
7494   const CreateTabReq* impl_req = &createTabPtr.p->m_request;
7495 
7496   TableRecordPtr tabPtr;
7497   bool ok = find_object(tabPtr, impl_req->tableId);
7498   ndbrequire(ok);
7499 
7500   D("createTab_alterComplete" << *op_ptr.p);
7501 
7502   //@todo check error
7503   //@todo check master failed
7504 
7505   // inform SUMA
7506   {
7507     CreateTabConf* conf = (CreateTabConf*)signal->getDataPtrSend();
7508     conf->senderRef = reference();
7509     conf->senderData = impl_req->tableId; // special usage
7510 #if 0
7511     signal->header.m_noOfSections = 1;
7512     SegmentedSectionPtr tabInfoPtr;
7513     getSection(tabInfoPtr, createTabPtr.p->m_tabInfoPtrI);
7514     signal->setSection(tabInfoPtr, 0);
7515 #endif
7516     sendSignal(SUMA_REF, GSN_CREATE_TAB_CONF, signal,
7517                CreateTabConf::SignalLength, JBB);
7518 #if 0
7519     signal->header.m_noOfSections = 0;
7520 #endif
7521   }
7522 
7523   sendTransConf(signal, op_ptr);
7524 }
7525 
7526 // CreateTable: COMPLETE
7527 
7528 void
createTable_complete(Signal * signal,SchemaOpPtr op_ptr)7529 Dbdict::createTable_complete(Signal* signal, SchemaOpPtr op_ptr)
7530 {
7531   jam();
7532   sendTransConf(signal, op_ptr);
7533 }
7534 
7535 void
createTable_abortParse(Signal * signal,SchemaOpPtr op_ptr)7536 Dbdict::createTable_abortParse(Signal* signal, SchemaOpPtr op_ptr)
7537 {
7538   CreateTableRecPtr createTabPtr;
7539   getOpRec(op_ptr, createTabPtr);
7540   const CreateTabReq* impl_req = &createTabPtr.p->m_request;
7541   const Uint32 tableId = impl_req->tableId;
7542 
7543   D("createTable_abortParse" << V(tableId) << *op_ptr.p);
7544 
7545   do {
7546     if (createTabPtr.p->m_abortPrepareDone)
7547     {
7548       jam();
7549       D("done by abort prepare");
7550       break;
7551     }
7552 
7553     if (tableId == RNIL) {
7554       jam();
7555       D("no table allocated");
7556       break;
7557     }
7558 
7559     TableRecordPtr tabPtr;
7560     bool ok = find_object(tabPtr, tableId);
7561 
7562     // any link was to a new object
7563     if (hasDictObject(op_ptr)) {
7564       jam();
7565       unlinkDictObject(op_ptr);
7566       if (ok)
7567       {
7568         jam();
7569         releaseTableObject(tabPtr.i, true);
7570       }
7571     }
7572   } while (0);
7573 
7574   sendTransConf(signal, op_ptr);
7575 }
7576 
7577 void
createTable_abortPrepare(Signal * signal,SchemaOpPtr op_ptr)7578 Dbdict::createTable_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
7579 {
7580   CreateTableRecPtr createTabPtr;
7581   getOpRec(op_ptr, createTabPtr);
7582   const CreateTabReq* impl_req = &createTabPtr.p->m_request;
7583   //const Uint32 tableId = impl_req->tableId;
7584 
7585   D("createTable_abortPrepare" << *op_ptr.p);
7586 
7587   TableRecordPtr tabPtr;
7588   bool ok = find_object(tabPtr, impl_req->tableId);
7589   ndbrequire(ok);
7590 
7591   // create drop table operation  wl3600_todo must pre-allocate
7592 
7593   SchemaOpPtr oplnk_ptr;
7594   DropTableRecPtr dropTabPtr;
7595   ok = seizeLinkedSchemaOp(op_ptr, oplnk_ptr, dropTabPtr);
7596   ndbrequire(ok);
7597 
7598   DropTabReq* aux_impl_req = &dropTabPtr.p->m_request;
7599 
7600   aux_impl_req->senderRef = impl_req->senderRef;
7601   aux_impl_req->senderData = impl_req->senderData;
7602   aux_impl_req->requestType = DropTabReq::CreateTabDrop;
7603   aux_impl_req->tableId = impl_req->tableId;
7604   aux_impl_req->tableVersion = impl_req->tableVersion;
7605 
7606   // wl3600_todo use ref count
7607   unlinkDictObject(op_ptr);
7608 
7609   dropTabPtr.p->m_block = 0;
7610   dropTabPtr.p->m_blockNo[0] = DBTC;
7611   dropTabPtr.p->m_blockNo[1] = DBSPJ;
7612   dropTabPtr.p->m_blockNo[2] = DBLQH; // wait usage + LCP
7613   dropTabPtr.p->m_blockNo[3] = DBDIH; //
7614   dropTabPtr.p->m_blockNo[4] = DBLQH; // release
7615   dropTabPtr.p->m_blockNo[5] = 0;
7616 
7617   dropTabPtr.p->m_callback.m_callbackData =
7618     oplnk_ptr.p->op_key;
7619   dropTabPtr.p->m_callback.m_callbackFunction =
7620     safe_cast(&Dbdict::createTable_abortLocalConf);
7621 
7622   // invoke the "complete" phase of drop table
7623   dropTable_complete_nextStep(signal, oplnk_ptr);
7624 
7625   if (tabPtr.p->m_tablespace_id != RNIL) {
7626     FilegroupPtr ptr;
7627     ndbrequire(find_object(ptr, tabPtr.p->m_tablespace_id));
7628     decrease_ref_count(ptr.p->m_obj_ptr_i);
7629   }
7630 }
7631 
7632 void
createTable_abortLocalConf(Signal * signal,Uint32 oplnk_key,Uint32 ret)7633 Dbdict::createTable_abortLocalConf(Signal* signal,
7634                                    Uint32 oplnk_key,
7635                                    Uint32 ret)
7636 {
7637   jam();
7638   D("createTable_abortLocalConf" << V(oplnk_key));
7639 
7640   SchemaOpPtr oplnk_ptr;
7641   DropTableRecPtr dropTabPtr;
7642   findSchemaOp(oplnk_ptr, dropTabPtr, oplnk_key);
7643   ndbrequire(!oplnk_ptr.isNull());
7644 
7645   SchemaOpPtr op_ptr = oplnk_ptr.p->m_opbck_ptr;
7646   CreateTableRecPtr createTabPtr;
7647   getOpRec(op_ptr, createTabPtr);
7648   const CreateTabReq* impl_req = &createTabPtr.p->m_request;
7649   Uint32 tableId = impl_req->tableId;
7650 
7651   TableRecordPtr tablePtr;
7652   bool ok = find_object(tablePtr, tableId);
7653   if (ok)
7654   {
7655     jam();
7656     releaseTableObject(tablePtr.i);
7657   }
7658   createTabPtr.p->m_abortPrepareDone = true;
7659   sendTransConf(signal, op_ptr);
7660 }
7661 
7662 // CreateTable: MISC
7663 
7664 void
execCREATE_FRAGMENTATION_REF(Signal * signal)7665 Dbdict::execCREATE_FRAGMENTATION_REF(Signal * signal)
7666 {
7667   // currently not received
7668   ndbrequire(false);
7669 }
7670 
7671 void
execCREATE_FRAGMENTATION_CONF(Signal * signal)7672 Dbdict::execCREATE_FRAGMENTATION_CONF(Signal* signal)
7673 {
7674   // currently not received
7675   ndbrequire(false);
7676 }
7677 
7678 void
execCREATE_TAB_REQ(Signal * signal)7679 Dbdict::execCREATE_TAB_REQ(Signal* signal)
7680 {
7681   // no longer received
7682   ndbrequire(false);
7683 }
7684 
execCREATE_TABLE_CONF(Signal * signal)7685 void Dbdict::execCREATE_TABLE_CONF(Signal* signal)
7686 {
7687   jamEntry();
7688   const CreateTableConf* conf = (const CreateTableConf*)signal->getDataPtr();
7689   handleDictConf(signal, conf);
7690 }
7691 
execCREATE_TABLE_REF(Signal * signal)7692 void Dbdict::execCREATE_TABLE_REF(Signal* signal)
7693 {
7694   jamEntry();
7695   const CreateTableRef* ref = (const CreateTableRef*)signal->getDataPtr();
7696   handleDictRef(signal, ref);
7697 }
7698 
releaseTableObject(Uint32 table_ptr_i,bool removeFromHash)7699 void Dbdict::releaseTableObject(Uint32 table_ptr_i, bool removeFromHash)
7700 {
7701   TableRecordPtr tablePtr;
7702   c_tableRecordPool_.getPtr(tablePtr, table_ptr_i);
7703   if (removeFromHash)
7704   {
7705     jam();
7706     ndbrequire(tablePtr.p->m_obj_ptr_i != RNIL);
7707     release_object(tablePtr.p->m_obj_ptr_i);
7708     tablePtr.p->m_obj_ptr_i = RNIL;
7709   }
7710   else
7711   {
7712     ndbrequire(tablePtr.p->m_obj_ptr_i == RNIL);
7713     LocalRope tmp(c_rope_pool, tablePtr.p->tableName);
7714     tmp.erase();
7715   }
7716 
7717   {
7718     LocalRope tmp(c_rope_pool, tablePtr.p->frmData);
7719     tmp.erase();
7720   }
7721 
7722   {
7723     LocalRope tmp(c_rope_pool, tablePtr.p->ngData);
7724     tmp.erase();
7725   }
7726 
7727   {
7728     LocalRope tmp(c_rope_pool, tablePtr.p->rangeData);
7729     tmp.erase();
7730   }
7731 
7732   LocalAttributeRecord_list list(c_attributeRecordPool,
7733 					tablePtr.p->m_attributes);
7734   AttributeRecordPtr attrPtr;
7735   for(list.first(attrPtr); !attrPtr.isNull(); list.next(attrPtr)){
7736     LocalRope name(c_rope_pool, attrPtr.p->attributeName);
7737     LocalRope def(c_rope_pool, attrPtr.p->defaultValue);
7738     name.erase();
7739     def.erase();
7740   }
7741   while (list.releaseFirst())
7742   {
7743     ;
7744   }
7745 
7746   {
7747     if (tablePtr.p->m_upgrade_trigger_handling.m_upgrade)
7748     {
7749       jam();
7750       Uint32 triggerId;
7751 
7752       triggerId = tablePtr.p->m_upgrade_trigger_handling.updateTriggerId;
7753       if (triggerId != RNIL)
7754       {
7755         jam();
7756         TriggerRecordPtr triggerPtr;
7757         bool ok = find_object(triggerPtr, triggerId);
7758         if (ok)
7759         {
7760           release_object(triggerPtr.p->m_obj_ptr_i);
7761           c_triggerRecordPool_.release(triggerPtr);
7762         }
7763       }
7764 
7765       triggerId = tablePtr.p->m_upgrade_trigger_handling.deleteTriggerId;
7766       if (triggerId != RNIL)
7767       {
7768         jam();
7769         TriggerRecordPtr triggerPtr;
7770         bool ok = find_object(triggerPtr, triggerId);
7771         if (ok)
7772         {
7773           release_object(triggerPtr.p->m_obj_ptr_i);
7774           c_triggerRecordPool_.release(triggerPtr);
7775         }
7776       }
7777     }
7778   }
7779   c_tableRecordPool_.release(tablePtr);
7780 }//releaseTableObject()
7781 
7782 // CreateTable: END
7783 
7784 // MODULE: DropTable
7785 
7786 const Dbdict::OpInfo
7787 Dbdict::DropTableRec::g_opInfo = {
7788   { 'D', 'T', 'a', 0 },
7789   ~RT_DBDICT_DROP_TABLE,
7790   GSN_DROP_TAB_REQ,
7791   DropTabReq::SignalLength,
7792   //
7793   &Dbdict::dropTable_seize,
7794   &Dbdict::dropTable_release,
7795   //
7796   &Dbdict::dropTable_parse,
7797   &Dbdict::dropTable_subOps,
7798   &Dbdict::dropTable_reply,
7799   //
7800   &Dbdict::dropTable_prepare,
7801   &Dbdict::dropTable_commit,
7802   &Dbdict::dropTable_complete,
7803   //
7804   &Dbdict::dropTable_abortParse,
7805   &Dbdict::dropTable_abortPrepare
7806 };
7807 
7808 bool
dropTable_seize(SchemaOpPtr op_ptr)7809 Dbdict::dropTable_seize(SchemaOpPtr op_ptr)
7810 {
7811   return seizeOpRec<DropTableRec>(op_ptr);
7812 }
7813 
7814 void
dropTable_release(SchemaOpPtr op_ptr)7815 Dbdict::dropTable_release(SchemaOpPtr op_ptr)
7816 {
7817   releaseOpRec<DropTableRec>(op_ptr);
7818 }
7819 
7820 void
execDROP_TABLE_REQ(Signal * signal)7821 Dbdict::execDROP_TABLE_REQ(Signal* signal)
7822 {
7823   jamEntry();
7824   if (!assembleFragments(signal)) {
7825     jam();
7826     return;
7827   }
7828   SectionHandle handle(this, signal);
7829 
7830   if (check_sender_version(signal, MAKE_VERSION(6,4,0)) < 0)
7831   {
7832     jam();
7833     /**
7834      * Pekka has for some obscure reason switched places of
7835      *   senderRef/senderData
7836      */
7837     DropTableReq * tmp = (DropTableReq*)signal->getDataPtr();
7838     do_swap(tmp->senderRef, tmp->senderData);
7839   }
7840 
7841   const DropTableReq req_copy =
7842     *(const DropTableReq*)signal->getDataPtr();
7843   const DropTableReq* req = &req_copy;
7844 
7845   ErrorInfo error;
7846   do {
7847     SchemaOpPtr op_ptr;
7848     DropTableRecPtr dropTabPtr;
7849     DropTabReq* impl_req;
7850 
7851     startClientReq(op_ptr, dropTabPtr, req, impl_req, error);
7852     if (hasError(error)) {
7853       jam();
7854       break;
7855     }
7856 
7857     impl_req->tableId = req->tableId;
7858     impl_req->tableVersion = req->tableVersion;
7859 
7860     handleClientReq(signal, op_ptr, handle);
7861     return;
7862   } while (0);
7863 
7864   releaseSections(handle);
7865 
7866   DropTableRef* ref = (DropTableRef*)signal->getDataPtrSend();
7867   ref->senderRef = reference();
7868   ref->clientData = req->clientData;
7869   ref->transId = req->transId;
7870   ref->tableId = req->tableId;
7871   ref->tableVersion = req->tableVersion;
7872   getError(error, ref);
7873   sendSignal(req->clientRef, GSN_DROP_TABLE_REF, signal,
7874              DropTableRef::SignalLength, JBB);
7875 }
7876 
7877 // DropTable: PARSE
7878 
7879 void
dropTable_parse(Signal * signal,bool master,SchemaOpPtr op_ptr,SectionHandle & handle,ErrorInfo & error)7880 Dbdict::dropTable_parse(Signal* signal, bool master,
7881                         SchemaOpPtr op_ptr,
7882                         SectionHandle& handle, ErrorInfo& error)
7883 {
7884   D("dropTable_parse" << V(op_ptr.i) << *op_ptr.p);
7885 
7886   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
7887   DropTableRecPtr dropTabPtr;
7888   getOpRec(op_ptr, dropTabPtr);
7889   DropTabReq* impl_req = &dropTabPtr.p->m_request;
7890   Uint32 tableId = impl_req->tableId;
7891   Uint32 err;
7892 
7893   TableRecordPtr tablePtr;
7894   if (!(tableId < c_noOfMetaTables)) {
7895     jam();
7896     setError(error, DropTableRef::NoSuchTable, __LINE__);
7897     return;
7898   }
7899 
7900   err = check_read_obj(impl_req->tableId, trans_ptr.p->m_transId);
7901   if (err)
7902   {
7903     jam();
7904     setError(error, err, __LINE__);
7905     return;
7906   }
7907 
7908   bool ok = find_object(tablePtr, impl_req->tableId);
7909   if (!ok)
7910   {
7911     jam();
7912     setError(error, GetTabInfoRef::TableNotDefined, __LINE__);
7913     return;
7914   }
7915 
7916 
7917   // check version first (api will retry)
7918   if (tablePtr.p->tableVersion != impl_req->tableVersion) {
7919     jam();
7920     setError(error, DropTableRef::InvalidTableVersion, __LINE__);
7921     return;
7922   }
7923 
7924   if (tablePtr.p->m_read_locked)
7925   {
7926     jam();
7927     setError(error, DropTableRef::BackupInProgress, __LINE__);
7928     return;
7929   }
7930 
7931   if (check_write_obj(impl_req->tableId,
7932                       trans_ptr.p->m_transId,
7933                       SchemaFile::SF_DROP, error))
7934   {
7935     jam();
7936     return;
7937   }
7938 
7939   // link operation to object
7940   {
7941     DictObjectPtr obj_ptr;
7942     Uint32 obj_ptr_i = tablePtr.p->m_obj_ptr_i;
7943     bool ok = findDictObject(op_ptr, obj_ptr, obj_ptr_i);
7944     ndbrequire(ok);
7945   }
7946 
7947   if (ERROR_INSERTED(6121)) {
7948     jam();
7949     CLEAR_ERROR_INSERT_VALUE;
7950     setError(error, 9121, __LINE__);
7951     return;
7952   }
7953 
7954   SchemaFile::TableEntry te; te.init();
7955   te.m_tableState = SchemaFile::SF_DROP;
7956   te.m_transId = trans_ptr.p->m_transId;
7957   err = trans_log_schema_op(op_ptr, tableId, &te);
7958   if (err)
7959   {
7960     jam();
7961     setError(error, err, __LINE__);
7962     return;
7963   }
7964 }
7965 
7966 bool
dropTable_subOps(Signal * signal,SchemaOpPtr op_ptr)7967 Dbdict::dropTable_subOps(Signal* signal, SchemaOpPtr op_ptr)
7968 {
7969   D("dropTable_subOps" << V(op_ptr.i) << *op_ptr.p);
7970   // wl3600_todo blobs, indexes, events
7971   return false;
7972 }
7973 
7974 void
dropTable_reply(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)7975 Dbdict::dropTable_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
7976 {
7977   jam();
7978   D("dropTable_reply" << V(op_ptr.i) << *op_ptr.p);
7979 
7980   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
7981 
7982   DropTableRecPtr dropTabPtr;
7983   getOpRec(op_ptr, dropTabPtr);
7984 
7985   if (!hasError(error)) {
7986     DropTableConf* conf = (DropTableConf*)signal->getDataPtrSend();
7987     conf->senderRef = reference();
7988     conf->clientData = op_ptr.p->m_clientData;
7989     conf->transId = trans_ptr.p->m_transId;
7990     conf->tableId = dropTabPtr.p->m_request.tableId;
7991     conf->tableVersion = dropTabPtr.p->m_request.tableVersion;
7992 
7993     D(V(conf->tableId) << V(conf->tableVersion));
7994 
7995     Uint32 clientRef = op_ptr.p->m_clientRef;
7996     sendSignal(clientRef, GSN_DROP_TABLE_CONF, signal,
7997                DropTableConf::SignalLength, JBB);
7998   } else {
7999     jam();
8000     DropTableRef* ref = (DropTableRef*)signal->getDataPtrSend();
8001     ref->senderRef = reference();
8002     ref->clientData = op_ptr.p->m_clientData;
8003     ref->transId = trans_ptr.p->m_transId;
8004     ref->tableId = dropTabPtr.p->m_request.tableId;
8005     ref->tableVersion = dropTabPtr.p->m_request.tableVersion;
8006     getError(error, ref);
8007 
8008     Uint32 clientRef = op_ptr.p->m_clientRef;
8009     sendSignal(clientRef, GSN_DROP_TABLE_REF, signal,
8010                DropTableRef::SignalLength, JBB);
8011   }
8012 }
8013 
8014 // DropTable: PREPARE
8015 
8016 void
dropTable_prepare(Signal * signal,SchemaOpPtr op_ptr)8017 Dbdict::dropTable_prepare(Signal* signal, SchemaOpPtr op_ptr)
8018 {
8019   DropTableRecPtr dropTabPtr;
8020   getOpRec(op_ptr, dropTabPtr);
8021 
8022   D("dropTable_prepare" << *op_ptr.p);
8023 
8024   Mutex mutex(signal, c_mutexMgr, dropTabPtr.p->m_define_backup_mutex);
8025   Callback c = {
8026     safe_cast(&Dbdict::dropTable_backup_mutex_locked),
8027     op_ptr.p->op_key
8028   };
8029   bool ok = mutex.lock(c);
8030   ndbrequire(ok);
8031   return;
8032 }
8033 
8034 void
dropTable_backup_mutex_locked(Signal * signal,Uint32 op_key,Uint32 ret)8035 Dbdict::dropTable_backup_mutex_locked(Signal* signal,
8036                                       Uint32 op_key,
8037                                       Uint32 ret)
8038 {
8039   jamEntry();
8040   D("dropTable_backup_mutex_locked");
8041 
8042   ndbrequire(ret == 0);
8043 
8044   SchemaOpPtr op_ptr;
8045   DropTableRecPtr dropTabPtr;
8046   findSchemaOp(op_ptr, dropTabPtr, op_key);
8047   ndbrequire(!op_ptr.isNull());
8048   const DropTabReq* impl_req = &dropTabPtr.p->m_request;
8049 
8050   TableRecordPtr tablePtr;
8051   bool ok = find_object(tablePtr, impl_req->tableId);
8052   ndbrequire(ok);
8053 
8054   Mutex mutex(signal, c_mutexMgr, dropTabPtr.p->m_define_backup_mutex);
8055   mutex.unlock(); // ignore response
8056 
8057   if (tablePtr.p->m_read_locked)
8058   {
8059     jam();
8060     setError(op_ptr, DropTableRef::BackupInProgress, __LINE__);
8061     sendTransRef(signal, op_ptr);
8062     return;
8063   }
8064 
8065   sendTransConf(signal, op_ptr);
8066 }
8067 // DropTable: COMMIT
8068 
8069 void
dropTable_commit(Signal * signal,SchemaOpPtr op_ptr)8070 Dbdict::dropTable_commit(Signal* signal, SchemaOpPtr op_ptr)
8071 {
8072   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
8073 
8074   DropTableRecPtr dropTabPtr;
8075   getOpRec(op_ptr, dropTabPtr);
8076 
8077   D("dropTable_commit" << *op_ptr.p);
8078 
8079   TableRecordPtr tablePtr;
8080   bool ok = find_object(tablePtr, dropTabPtr.p->m_request.tableId);
8081   ndbrequire(ok);
8082 
8083   if (tablePtr.p->m_tablespace_id != RNIL)
8084   {
8085     FilegroupPtr ptr;
8086     ndbrequire(find_object(ptr, tablePtr.p->m_tablespace_id));
8087     decrease_ref_count(ptr.p->m_obj_ptr_i);
8088   }
8089 
8090   if (g_trace)
8091   // from a newer execDROP_TAB_REQ version
8092   {
8093     char buf[1024];
8094     LocalRope name(c_rope_pool, tablePtr.p->tableName);
8095     name.copy(buf);
8096     g_eventLogger->info("Dbdict: drop name=%s,id=%u,obj_id=%u", buf, dropTabPtr.p->m_request.tableId,
8097                         tablePtr.p->m_obj_ptr_i);
8098   }
8099 
8100   send_event(signal, trans_ptr,
8101              NDB_LE_DropSchemaObject,
8102              dropTabPtr.p->m_request.tableId,
8103              tablePtr.p->tableVersion,
8104              tablePtr.p->tableType);
8105 
8106   if (DictTabInfo::isIndex(tablePtr.p->tableType))
8107   {
8108     TableRecordPtr basePtr;
8109     bool ok = find_object(basePtr, tablePtr.p->primaryTableId);
8110     ndbrequire(ok);
8111     LocalTableRecord_list list(c_tableRecordPool_, basePtr.p->m_indexes);
8112     list.remove(tablePtr);
8113   }
8114   dropTabPtr.p->m_block = 0;
8115   dropTabPtr.p->m_blockNo[0] = DBLQH;
8116   dropTabPtr.p->m_blockNo[1] = DBSPJ;
8117   dropTabPtr.p->m_blockNo[2] = DBTC;
8118   dropTabPtr.p->m_blockNo[3] = DBDIH;
8119   dropTabPtr.p->m_blockNo[4] = 0;
8120   dropTable_commit_nextStep(signal, op_ptr);
8121 }
8122 
8123 
8124 void
dropTable_commit_nextStep(Signal * signal,SchemaOpPtr op_ptr)8125 Dbdict::dropTable_commit_nextStep(Signal* signal, SchemaOpPtr op_ptr)
8126 {
8127   DropTableRecPtr dropTabPtr;
8128   getOpRec(op_ptr, dropTabPtr);
8129   const DropTabReq* impl_req = &dropTabPtr.p->m_request;
8130 
8131   /**
8132    * No errors currently allowed
8133    */
8134   ndbrequire(!hasError(op_ptr.p->m_error));
8135 
8136   Uint32 block = dropTabPtr.p->m_block;
8137   Uint32 blockNo = dropTabPtr.p->m_blockNo[block];
8138   D("dropTable_commit_nextStep" << hex << V(blockNo) << *op_ptr.p);
8139 
8140   if (blockNo == 0)
8141   {
8142     jam();
8143     dropTable_commit_done(signal, op_ptr);
8144     return;
8145   }
8146 
8147   if (ERROR_INSERTED(6131) &&
8148       blockNo == DBDIH) {
8149     jam();
8150     CLEAR_ERROR_INSERT_VALUE;
8151 
8152     PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
8153     ref->senderRef = numberToRef(block, getOwnNodeId());
8154     ref->senderData = op_ptr.p->op_key;
8155     ref->tableId = impl_req->tableId;
8156     ref->errorCode = 9131;
8157     sendSignal(reference(), GSN_PREP_DROP_TAB_REF, signal,
8158                PrepDropTabRef::SignalLength, JBB);
8159     return;
8160   }
8161 
8162 
8163   PrepDropTabReq* prep = (PrepDropTabReq*)signal->getDataPtrSend();
8164   prep->senderRef = reference();
8165   prep->senderData = op_ptr.p->op_key;
8166   prep->tableId = impl_req->tableId;
8167   prep->requestType = impl_req->requestType;
8168 
8169   BlockReference ref = numberToRef(blockNo, getOwnNodeId());
8170   sendSignal(ref, GSN_PREP_DROP_TAB_REQ, signal,
8171              PrepDropTabReq::SignalLength, JBB);
8172 }
8173 
8174 void
execPREP_DROP_TAB_REQ(Signal * signal)8175 Dbdict::execPREP_DROP_TAB_REQ(Signal* signal)
8176 {
8177   // no longer received
8178   ndbrequire(false);
8179 }
8180 
8181 void
execPREP_DROP_TAB_CONF(Signal * signal)8182 Dbdict::execPREP_DROP_TAB_CONF(Signal * signal)
8183 {
8184   jamEntry();
8185   const PrepDropTabConf* conf = (const PrepDropTabConf*)signal->getDataPtr();
8186 
8187   Uint32 nodeId = refToNode(conf->senderRef);
8188   Uint32 block = refToBlock(conf->senderRef);
8189   ndbrequire(nodeId == getOwnNodeId() && block != DBDICT);
8190 
8191   dropTable_commit_fromLocal(signal, conf->senderData, 0);
8192 }
8193 
8194 void
execPREP_DROP_TAB_REF(Signal * signal)8195 Dbdict::execPREP_DROP_TAB_REF(Signal* signal)
8196 {
8197   jamEntry();
8198   const PrepDropTabRef* ref = (const PrepDropTabRef*)signal->getDataPtr();
8199 
8200   Uint32 nodeId = refToNode(ref->senderRef);
8201   Uint32 block = refToBlock(ref->senderRef);
8202   ndbrequire(nodeId == getOwnNodeId() && block != DBDICT);
8203 
8204   Uint32 errorCode = ref->errorCode;
8205   ndbrequire(errorCode != 0);
8206 
8207   if (errorCode == PrepDropTabRef::NoSuchTable && block == DBLQH)
8208   {
8209     jam();
8210     /**
8211      * Ignore errors:
8212      * 1) no such table and LQH, it might not exists in different LQH's
8213      */
8214     errorCode = 0;
8215   }
8216   dropTable_commit_fromLocal(signal, ref->senderData, errorCode);
8217 }
8218 
8219 void
dropTable_commit_fromLocal(Signal * signal,Uint32 op_key,Uint32 errorCode)8220 Dbdict::dropTable_commit_fromLocal(Signal* signal, Uint32 op_key, Uint32 errorCode)
8221 {
8222   SchemaOpPtr op_ptr;
8223   DropTableRecPtr dropTabPtr;
8224   findSchemaOp(op_ptr, dropTabPtr, op_key);
8225   ndbrequire(!op_ptr.isNull());
8226 
8227   if (errorCode != 0)
8228   {
8229     jam();
8230     setError(op_ptr, errorCode, __LINE__);
8231   }
8232 
8233   dropTabPtr.p->m_block++;
8234   dropTable_commit_nextStep(signal, op_ptr);
8235 }
8236 
8237 void
dropTable_commit_done(Signal * signal,SchemaOpPtr op_ptr)8238 Dbdict::dropTable_commit_done(Signal* signal, SchemaOpPtr op_ptr)
8239 {
8240   jam();
8241   D("dropTable_commit_done");
8242 
8243   sendTransConf(signal, op_ptr);
8244 }
8245 
8246 // DropTable: COMPLETE
8247 
8248 void
dropTable_complete(Signal * signal,SchemaOpPtr op_ptr)8249 Dbdict::dropTable_complete(Signal* signal, SchemaOpPtr op_ptr)
8250 {
8251   jam();
8252 
8253   DropTableRecPtr dropTabPtr;
8254   getOpRec(op_ptr, dropTabPtr);
8255 
8256   dropTabPtr.p->m_block = 0;
8257   dropTabPtr.p->m_blockNo[0] = DBTC;
8258   dropTabPtr.p->m_blockNo[1] = DBSPJ;
8259   dropTabPtr.p->m_blockNo[2] = DBLQH; // wait usage + LCP
8260   dropTabPtr.p->m_blockNo[3] = DBDIH; //
8261   dropTabPtr.p->m_blockNo[4] = DBLQH; // release
8262   dropTabPtr.p->m_blockNo[5] = 0;
8263   dropTabPtr.p->m_callback.m_callbackData =
8264     op_ptr.p->op_key;
8265   dropTabPtr.p->m_callback.m_callbackFunction =
8266     safe_cast(&Dbdict::dropTable_complete_done);
8267 
8268   dropTable_complete_nextStep(signal, op_ptr);
8269 }
8270 
8271 void
dropTable_complete_nextStep(Signal * signal,SchemaOpPtr op_ptr)8272 Dbdict::dropTable_complete_nextStep(Signal* signal, SchemaOpPtr op_ptr)
8273 {
8274   DropTableRecPtr dropTabPtr;
8275   getOpRec(op_ptr, dropTabPtr);
8276   const DropTabReq* impl_req = &dropTabPtr.p->m_request;
8277 
8278   /**
8279    * No errors currently allowed
8280    */
8281   ndbrequire(!hasError(op_ptr.p->m_error));
8282 
8283   Uint32 block = dropTabPtr.p->m_block;
8284   Uint32 blockNo = dropTabPtr.p->m_blockNo[block];
8285   D("dropTable_complete_nextStep" << hex << V(blockNo) << *op_ptr.p);
8286 
8287   if (blockNo == 0)
8288   {
8289     jam();
8290     execute(signal, dropTabPtr.p->m_callback, 0);
8291     return;
8292   }
8293 
8294   DropTabReq* req = (DropTabReq*)signal->getDataPtrSend();
8295   req->senderRef = reference();
8296   req->senderData = op_ptr.p->op_key;
8297   req->tableId = impl_req->tableId;
8298   req->requestType = impl_req->requestType;
8299 
8300   BlockReference ref = numberToRef(blockNo, getOwnNodeId());
8301   sendSignal(ref, GSN_DROP_TAB_REQ, signal,
8302              DropTabReq::SignalLength, JBB);
8303 }
8304 
8305 void
execDROP_TAB_CONF(Signal * signal)8306 Dbdict::execDROP_TAB_CONF(Signal* signal)
8307 {
8308   jamEntry();
8309   const DropTabConf* conf = (const DropTabConf*)signal->getDataPtr();
8310 
8311   Uint32 nodeId = refToNode(conf->senderRef);
8312   Uint32 block = refToBlock(conf->senderRef);
8313   ndbrequire(nodeId == getOwnNodeId() && block != DBDICT);
8314 
8315   dropTable_complete_fromLocal(signal, conf->senderData);
8316 }
8317 
8318 void
execDROP_TAB_REF(Signal * signal)8319 Dbdict::execDROP_TAB_REF(Signal* signal)
8320 {
8321   jamEntry();
8322   const DropTabRef* ref = (const DropTabRef*)signal->getDataPtr();
8323 
8324   Uint32 nodeId = refToNode(ref->senderRef);
8325   Uint32 block = refToBlock(ref->senderRef);
8326   ndbrequire(nodeId == getOwnNodeId() && block != DBDICT);
8327   ndbrequire(ref->errorCode == DropTabRef::NoSuchTable);
8328 
8329   dropTable_complete_fromLocal(signal, ref->senderData);
8330 }
8331 
8332 void
dropTable_complete_fromLocal(Signal * signal,Uint32 op_key)8333 Dbdict::dropTable_complete_fromLocal(Signal* signal, Uint32 op_key)
8334 {
8335   jamEntry();
8336 
8337   SchemaOpPtr op_ptr;
8338   DropTableRecPtr dropTabPtr;
8339   findSchemaOp(op_ptr, dropTabPtr, op_key);
8340   ndbrequire(!op_ptr.isNull());
8341   //const DropTabReq* impl_req = &dropTabPtr.p->m_request;
8342 
8343   D("dropTable_complete_fromLocal" << *op_ptr.p);
8344 
8345   dropTabPtr.p->m_block++;
8346   dropTable_complete_nextStep(signal, op_ptr);
8347 }
8348 
8349 void
dropTable_complete_done(Signal * signal,Uint32 op_key,Uint32 ret)8350 Dbdict::dropTable_complete_done(Signal* signal,
8351                                 Uint32 op_key,
8352                                 Uint32 ret)
8353 {
8354   jam();
8355 
8356   SchemaOpPtr op_ptr;
8357   DropTableRecPtr dropTabPtr;
8358   findSchemaOp(op_ptr, dropTabPtr, op_key);
8359   ndbrequire(!op_ptr.isNull());
8360   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
8361 
8362   Uint32 tableId = dropTabPtr.p->m_request.tableId;
8363 
8364   unlinkDictObject(op_ptr);
8365   TableRecordPtr tablePtr;
8366   bool ok = find_object(tablePtr, tableId);
8367   if (ok)
8368   {
8369     releaseTableObject(tablePtr.i);
8370   }
8371 
8372   // inform SUMA
8373   {
8374     DropTabConf* conf = (DropTabConf*)signal->getDataPtrSend();
8375 
8376     // special use of senderRef
8377     if (trans_ptr.p->m_isMaster) {
8378       jam();
8379       conf->senderRef = trans_ptr.p->m_clientRef;
8380     } else {
8381       jam();
8382       conf->senderRef = 0;
8383     }
8384     conf->senderData = op_key;
8385     conf->tableId = tableId;
8386     sendSignal(SUMA_REF, GSN_DROP_TAB_CONF, signal,
8387                DropTabConf::SignalLength, JBB);
8388   }
8389   ndbassert(op_ptr.p->m_state == SchemaOp::OS_COMPLETING);
8390   sendTransConf(signal, op_ptr);
8391 }
8392 
8393 // DropTable: ABORT
8394 
8395 void
dropTable_abortParse(Signal * signal,SchemaOpPtr op_ptr)8396 Dbdict::dropTable_abortParse(Signal* signal, SchemaOpPtr op_ptr)
8397 {
8398   D("dropTable_abortParse" << *op_ptr.p);
8399 
8400   sendTransConf(signal, op_ptr);
8401 }
8402 
8403 void
dropTable_abortPrepare(Signal * signal,SchemaOpPtr op_ptr)8404 Dbdict::dropTable_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
8405 {
8406   D("dropTable_abortPrepare" << *op_ptr.p);
8407 
8408   sendTransConf(signal, op_ptr);
8409 }
8410 
8411 // DropTable: MISC
8412 
execDROP_TABLE_CONF(Signal * signal)8413 void Dbdict::execDROP_TABLE_CONF(Signal* signal)
8414 {
8415   jamEntry();
8416   const DropTableConf* conf = (const DropTableConf*)signal->getDataPtr();
8417   handleDictConf(signal, conf);
8418 }
8419 
execDROP_TABLE_REF(Signal * signal)8420 void Dbdict::execDROP_TABLE_REF(Signal* signal)
8421 {
8422   jamEntry();
8423   const DropTableRef* ref = (const DropTableRef*)signal->getDataPtr();
8424   handleDictRef(signal, ref);
8425 }
8426 
8427 // DropTable: END
8428 
8429 // MODULE: AlterTable
8430 
8431 const Dbdict::OpInfo
8432 Dbdict::AlterTableRec::g_opInfo = {
8433   { 'A', 'T', 'a', 0 },
8434   ~RT_DBDICT_ALTER_TABLE,
8435   GSN_ALTER_TAB_REQ,
8436   AlterTabReq::SignalLength,
8437   //
8438   &Dbdict::alterTable_seize,
8439   &Dbdict::alterTable_release,
8440   //
8441   &Dbdict::alterTable_parse,
8442   &Dbdict::alterTable_subOps,
8443   &Dbdict::alterTable_reply,
8444   //
8445   &Dbdict::alterTable_prepare,
8446   &Dbdict::alterTable_commit,
8447   &Dbdict::alterTable_complete,
8448   //
8449   &Dbdict::alterTable_abortParse,
8450   &Dbdict::alterTable_abortPrepare
8451 };
8452 
8453 bool
alterTable_seize(SchemaOpPtr op_ptr)8454 Dbdict::alterTable_seize(SchemaOpPtr op_ptr)
8455 {
8456   return seizeOpRec<AlterTableRec>(op_ptr);
8457 }
8458 
8459 void
alterTable_release(SchemaOpPtr op_ptr)8460 Dbdict::alterTable_release(SchemaOpPtr op_ptr)
8461 {
8462   AlterTableRecPtr alterTabPtr;
8463   getOpRec(op_ptr, alterTabPtr);
8464   {
8465     LocalRope r(c_rope_pool, alterTabPtr.p->m_oldTableName);
8466     r.erase();
8467   }
8468   {
8469     LocalRope r(c_rope_pool, alterTabPtr.p->m_oldFrmData);
8470     r.erase();
8471   }
8472   LocalArenaPoolImpl op_sec_pool(op_ptr.p->m_trans_ptr.p->m_arena, c_opSectionBufferPool);
8473   release(op_sec_pool, alterTabPtr.p->m_newAttrData);
8474   releaseOpRec<AlterTableRec>(op_ptr);
8475 }
8476 
8477 bool
check_ndb_versions() const8478 Dbdict::check_ndb_versions() const
8479 {
8480   Uint32 node = 0;
8481   Uint32 version = getNodeInfo(getOwnNodeId()).m_version;
8482   while((node = c_aliveNodes.find(node + 1)) != BitmaskImpl::NotFound)
8483   {
8484     if(getNodeInfo(node).m_version != version)
8485     {
8486       return false;
8487     }
8488   }
8489   return true;
8490 }
8491 
8492 int
check_sender_version(const Signal * signal,Uint32 version) const8493 Dbdict::check_sender_version(const Signal* signal, Uint32 version) const
8494 {
8495   Uint32 ver = getNodeInfo(refToNode(signal->getSendersBlockRef())).m_version;
8496   if (ver < version)
8497     return -1;
8498   else if (ver > version)
8499     return 1;
8500   return 0;
8501 }
8502 
8503 void
execALTER_TABLE_REQ(Signal * signal)8504 Dbdict::execALTER_TABLE_REQ(Signal* signal)
8505 {
8506   jamEntry();
8507 
8508   if (!assembleFragments(signal)) {
8509     jam();
8510     return;
8511   }
8512   SectionHandle handle(this, signal);
8513 
8514   if (check_sender_version(signal, MAKE_VERSION(6,4,0)) < 0)
8515   {
8516     jam();
8517     /**
8518      * Pekka has for some obscure reason switched places of
8519      *   senderRef/senderData
8520      */
8521     AlterTableReq * tmp = (AlterTableReq*)signal->getDataPtr();
8522     do_swap(tmp->clientRef, tmp->clientData);
8523   }
8524 
8525   const AlterTableReq req_copy =
8526     *(const AlterTableReq*)signal->getDataPtr();
8527   const AlterTableReq* req = &req_copy;
8528 
8529   ErrorInfo error;
8530   do {
8531     SchemaOpPtr op_ptr;
8532     AlterTableRecPtr alterTabPtr;
8533     AlterTabReq* impl_req;
8534 
8535     startClientReq(op_ptr, alterTabPtr, req, impl_req, error);
8536     if (hasError(error)) {
8537       jam();
8538       break;
8539     }
8540 
8541     impl_req->tableId = req->tableId;
8542     impl_req->tableVersion = req->tableVersion;
8543     impl_req->newTableVersion = 0; // set in master parse
8544     impl_req->gci = 0;
8545     impl_req->changeMask = req->changeMask;
8546     impl_req->connectPtr = RNIL; // set from TUP
8547     impl_req->noOfNewAttr = 0; // set these in master parse
8548     impl_req->newNoOfCharsets = 0;
8549     impl_req->newNoOfKeyAttrs = 0;
8550 
8551     handleClientReq(signal, op_ptr, handle);
8552     return;
8553   } while (0);
8554 
8555   releaseSections(handle);
8556 
8557   AlterTableRef* ref = (AlterTableRef*)signal->getDataPtrSend();
8558   ref->senderRef = reference();
8559   ref->clientData = req->clientData;
8560   ref->transId = req->transId;
8561   getError(error, ref);
8562   sendSignal(req->clientRef, GSN_ALTER_TABLE_REF, signal,
8563              AlterTableRef::SignalLength, JBB);
8564 }
8565 
8566 // AlterTable: PARSE
8567 
8568 void
alterTable_parse(Signal * signal,bool master,SchemaOpPtr op_ptr,SectionHandle & handle,ErrorInfo & error)8569 Dbdict::alterTable_parse(Signal* signal, bool master,
8570                          SchemaOpPtr op_ptr,
8571                          SectionHandle& handle, ErrorInfo& error)
8572 {
8573   D("alterTable_parse");
8574 
8575   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
8576   AlterTableRecPtr alterTabPtr;
8577   getOpRec(op_ptr, alterTabPtr);
8578   AlterTabReq* impl_req = &alterTabPtr.p->m_request;
8579   Uint32 err;
8580 
8581   if (AlterTableReq::getReorgSubOp(impl_req->changeMask))
8582   {
8583     /**
8584      * This should only be a sub-op to AddFragFrag
8585      */
8586     if (master && op_ptr.p->m_base_op_ptr_i == RNIL)
8587     {
8588       jam();
8589       setError(error, AlterTableRef::Inconsistency, __LINE__);
8590       return;
8591     }
8592 
8593     return;
8594   }
8595 
8596   // get table definition
8597   TableRecordPtr tablePtr;
8598   if (!(impl_req->tableId < c_noOfMetaTables)) {
8599     jam();
8600     setError(error, AlterTableRef::NoSuchTable, __LINE__);
8601     return;
8602   }
8603 
8604   bool ok = find_object(tablePtr, impl_req->tableId);
8605   if (!ok)
8606   {
8607     jam();
8608     setError(error, GetTabInfoRef::TableNotDefined, __LINE__);
8609     return;
8610   }
8611 
8612   if (tablePtr.p->m_read_locked)
8613   {
8614     jam();
8615     setError(error, AlterTableRef::BackupInProgress, __LINE__);
8616     return;
8617   }
8618 
8619   if (check_write_obj(impl_req->tableId, trans_ptr.p->m_transId,
8620                       SchemaFile::SF_ALTER, error))
8621   {
8622     jam();
8623     return;
8624   }
8625 
8626   // save it for abort code
8627 
8628   if (tablePtr.p->tableVersion != impl_req->tableVersion) {
8629     jam();
8630     setError(error, AlterTableRef::InvalidTableVersion, __LINE__);
8631     return;
8632   }
8633 
8634   // parse new table definition into new table record
8635   TableRecordPtr newTablePtr;
8636   {
8637     ParseDictTabInfoRecord parseRecord;
8638     parseRecord.requestType = DictTabInfo::AlterTableFromAPI;
8639     parseRecord.errorCode = 0;
8640 
8641     SegmentedSectionPtr ptr;
8642     bool ok = handle.getSection(ptr, AlterTableReq::DICT_TAB_INFO);
8643     ndbrequire(ok);
8644     SimplePropertiesSectionReader r(ptr, getSectionSegmentPool());
8645 
8646     handleTabInfoInit(signal,
8647                       trans_ptr, r, &parseRecord, false); // Will not save info
8648 
8649     if (parseRecord.errorCode != 0) {
8650       jam();
8651       setError(error, parseRecord);
8652       return;
8653     }
8654 
8655     // the new temporary table record seized from pool
8656     newTablePtr = parseRecord.tablePtr;
8657     alterTabPtr.p->m_newTablePtrI = newTablePtr.i;
8658     alterTabPtr.p->m_newTable_realObjectId = newTablePtr.p->tableId;
8659     newTablePtr.p->tableId = impl_req->tableId; // set correct table id...(not the temporary)
8660   }
8661 
8662 
8663   {
8664     /**
8665      * Mark SchemaObject as in-use so that it's won't be found by other op
8666      *   choose a state that will be automatically cleaned incase we crash
8667      */
8668     SchemaFile::TableEntry *
8669       objEntry = getTableEntry(alterTabPtr.p->m_newTable_realObjectId);
8670     objEntry->m_tableType = DictTabInfo::SchemaTransaction;
8671     objEntry->m_tableState = SchemaFile::SF_STARTED;
8672     objEntry->m_transId = trans_ptr.p->m_transId + 1;
8673   }
8674 
8675   // set the new version now
8676   impl_req->newTableVersion =
8677     newTablePtr.p->tableVersion =
8678     alter_obj_inc_schema_version(tablePtr.p->tableVersion);
8679 
8680   // rename stuff
8681   {
8682     ConstRope r1(c_rope_pool, tablePtr.p->tableName);
8683     ConstRope r2(c_rope_pool, newTablePtr.p->tableName);
8684 
8685     char name[MAX_TAB_NAME_SIZE];
8686     r2.copy(name);
8687 
8688     if (r1.compare(name) != 0)
8689     {
8690       jam();
8691       if (get_object(name) != 0)
8692       {
8693         jam();
8694         setError(error, CreateTableRef::TableAlreadyExist, __LINE__);
8695         return;
8696       }
8697 
8698       if (master)
8699       {
8700         jam();
8701         AlterTableReq::setNameFlag(impl_req->changeMask, 1);
8702       }
8703       else if (!AlterTableReq::getNameFlag(impl_req->changeMask))
8704       {
8705         jam();
8706         setError(error, AlterTableRef::Inconsistency, __LINE__);
8707         return;
8708       }
8709     }
8710     else if (AlterTableReq::getNameFlag(impl_req->changeMask))
8711     {
8712       jam();
8713       setError(error, AlterTableRef::Inconsistency, __LINE__);
8714       return;
8715     }
8716   }
8717 
8718   // frm stuff
8719   {
8720     ConstRope r1(c_rope_pool, tablePtr.p->frmData);
8721     ConstRope r2(c_rope_pool, newTablePtr.p->frmData);
8722     if (!r1.equal(r2))
8723     {
8724       if (master)
8725       {
8726         jam();
8727         AlterTableReq::setFrmFlag(impl_req->changeMask, 1);
8728       }
8729       else if (!AlterTableReq::getFrmFlag(impl_req->changeMask))
8730       {
8731         jam();
8732         setError(error, AlterTableRef::Inconsistency, __LINE__);
8733         return;
8734       }
8735     }
8736     else if (AlterTableReq::getFrmFlag(impl_req->changeMask))
8737     {
8738       jam();
8739       setError(error, AlterTableRef::Inconsistency, __LINE__);
8740       return;
8741     }
8742   }
8743 
8744   // add attribute stuff
8745   {
8746     const Uint32 noOfNewAttr =
8747       newTablePtr.p->noOfAttributes - tablePtr.p->noOfAttributes;
8748 
8749     if (newTablePtr.p->noOfAttributes > tablePtr.p->noOfAttributes)
8750     {
8751       if (master)
8752       {
8753         jam();
8754         AlterTableReq::setAddAttrFlag(impl_req->changeMask, 1);
8755       }
8756       else if (!AlterTableReq::getAddAttrFlag(impl_req->changeMask))
8757       {
8758         jam();
8759         setError(error, AlterTableRef::Inconsistency, __LINE__);
8760         return;
8761       }
8762     }
8763     else if (AlterTableReq::getAddAttrFlag(impl_req->changeMask))
8764     {
8765       jam();
8766       setError(error, AlterTableRef::Inconsistency, __LINE__);
8767       return;
8768     }
8769     else if (newTablePtr.p->noOfAttributes < tablePtr.p->noOfAttributes)
8770     {
8771       jam();
8772       setError(error, AlterTableRef::UnsupportedChange, __LINE__);
8773       return;
8774     }
8775 
8776     if (master)
8777     {
8778       jam();
8779       impl_req->noOfNewAttr = noOfNewAttr;
8780       impl_req->newNoOfCharsets = newTablePtr.p->noOfCharsets;
8781       impl_req->newNoOfKeyAttrs = newTablePtr.p->noOfPrimkey;
8782     }
8783     else if (impl_req->noOfNewAttr != noOfNewAttr)
8784     {
8785       jam();
8786       setError(error, AlterTableRef::Inconsistency, __LINE__);
8787       return;
8788     }
8789 
8790     LocalAttributeRecord_list
8791       list(c_attributeRecordPool, newTablePtr.p->m_attributes);
8792     AttributeRecordPtr attrPtr;
8793     list.first(attrPtr);
8794     Uint32 i = 0;
8795     LocalArenaPoolImpl op_sec_pool(trans_ptr.p->m_arena, c_opSectionBufferPool);
8796     for (i = 0; i < newTablePtr.p->noOfAttributes; i++) {
8797       if (i >= tablePtr.p->noOfAttributes) {
8798         jam();
8799         Uint32 attrData[2];
8800         attrData[0] = attrPtr.p->attributeDescriptor;
8801         attrData[1] = attrPtr.p->extPrecision & ~0xFFFF;
8802         if(!copyIn(op_sec_pool, alterTabPtr.p->m_newAttrData, attrData, 2))
8803         {
8804           jam();
8805           setError(error, SchemaTransBeginRef::OutOfSchemaTransMemory, __LINE__);
8806           return;
8807         }
8808       }
8809       list.next(attrPtr);
8810     }
8811   }
8812 
8813   if (AlterTableReq::getAddFragFlag(impl_req->changeMask))
8814   {
8815     if (newTablePtr.p->fragmentType != DictTabInfo::HashMapPartition)
8816     {
8817       jam();
8818       setError(error, AlterTableRef::UnsupportedChange, __LINE__);
8819       return;
8820     }
8821 
8822     /**
8823      * Verify that reorg is possible with the hash map(s)
8824      */
8825     if (ERROR_INSERTED(6212))
8826     {
8827       CLEAR_ERROR_INSERT_VALUE;
8828       setError(error, 1, __LINE__);
8829       return;
8830     }
8831 
8832     Uint32 err;
8833     if ((err = check_supported_reorg(tablePtr.p->hashMapObjectId,
8834                                      newTablePtr.p->hashMapObjectId)))
8835     {
8836       jam();
8837       setError(error, AlterTableRef::UnsupportedChange, __LINE__);
8838       return;
8839     }
8840 
8841     if (tablePtr.p->hashMapObjectId != newTablePtr.p->hashMapObjectId)
8842     {
8843       jam();
8844       AlterTableReq::setReorgFragFlag(impl_req->changeMask, 1);
8845     }
8846 
8847     if (master)
8848     {
8849       /**
8850        * 1) Create fragmentation for new table
8851        * 2) Get fragmentation for old table
8852        * 3) Check if supported alter table and
8853        *    save fragmentation for new fragment op operation record
8854        */
8855       jam();
8856       Uint32 save0 = newTablePtr.p->fragmentType;
8857       newTablePtr.p->fragmentType = DictTabInfo::DistrKeyHash;
8858 
8859       /**
8860        * Here we reset all the NODEGROUPS for the new partitions
8861        *   i.e they can't be specified...this should change later
8862        *   once we got our act together
8863        */
8864       Uint32 cnt = c_fragDataLen / 2;
8865       for (Uint32 i = cnt; i<newTablePtr.p->fragmentCount; i++)
8866       {
8867         jam();
8868         c_fragData[i] = NDB_UNDEF_NODEGROUP;
8869       }
8870       c_fragDataLen = 2 * newTablePtr.p->fragmentCount;
8871       Uint32 save1 = newTablePtr.p->primaryTableId;
8872       Uint32 flags = 0;
8873       if (save1 == RNIL)
8874       {
8875         /**
8876          * This is a "base" table
8877          *   signal that this is a add-partitions
8878          *   by setting primaryTableId to "original" table and setting flag
8879          */
8880         flags = CreateFragmentationReq::RI_ADD_PARTITION;
8881         newTablePtr.p->primaryTableId = tablePtr.p->tableId;
8882       }
8883       err = create_fragmentation(signal, newTablePtr,
8884                                  c_fragData, c_fragDataLen / 2,
8885                                  flags);
8886       newTablePtr.p->fragmentType = (DictTabInfo::FragmentType)save0;
8887       newTablePtr.p->primaryTableId = save1;
8888 
8889       if (err)
8890       {
8891         jam();
8892         setError(error, err, __LINE__);
8893         return;
8894       }
8895 
8896       Uint16* data = (Uint16*)(signal->theData+25);
8897       Uint32 count = 2 + (1 + data[0]) * data[1];
8898       memcpy(c_fragData, data, 2*count);
8899 
8900       err = get_fragmentation(signal, tablePtr.p->tableId);
8901       if (err)
8902       {
8903         jam();
8904         setError(error, err, __LINE__);
8905         return;
8906       }
8907 
8908       err = check_supported_add_fragment(c_fragData,
8909                                          (Uint16*)(signal->theData+25));
8910       if (err)
8911       {
8912         jam();
8913         setError(error, err, __LINE__);
8914         return;
8915       }
8916 
8917       count = 2 + (1 + c_fragData[0]) * c_fragData[1];
8918       c_fragDataLen = sizeof(Uint16)*count;
8919     }
8920   }
8921   else if (AlterTableReq::getReorgFragFlag(impl_req->changeMask))
8922   { // Reorg without adding fragments are not supported
8923     jam();
8924     setError(error, AlterTableRef::UnsupportedChange, __LINE__);
8925     return;
8926   }
8927 
8928   if (tablePtr.p->hashMapObjectId != newTablePtr.p->hashMapObjectId &&
8929       !AlterTableReq::getReorgFragFlag(impl_req->changeMask))
8930   { // Change in hashmap without reorg is not supported
8931     jam();
8932     setError(error, AlterTableRef::UnsupportedChange, __LINE__);
8933     return;
8934   }
8935 
8936   D("alterTable_parse " << V(newTablePtr.i) << hex << V(newTablePtr.p->tableVersion));
8937 
8938   if (ERROR_INSERTED(6121)) {
8939     jam();
8940     CLEAR_ERROR_INSERT_VALUE;
8941     setError(error, 9121, __LINE__);
8942     return;
8943   }
8944 
8945   // master rewrites DictTabInfo (it is re-parsed only on slaves)
8946   if (master)
8947   {
8948     jam();
8949     releaseSections(handle);
8950     SimplePropertiesSectionWriter w(* this);
8951     packTableIntoPages(w, newTablePtr);
8952 
8953     SegmentedSectionPtr tabInfoPtr;
8954     w.getPtr(tabInfoPtr);
8955     handle.m_ptr[AlterTabReq::DICT_TAB_INFO] = tabInfoPtr;
8956     handle.m_cnt = 1;
8957 
8958     if (AlterTableReq::getAddFragFlag(impl_req->changeMask))
8959     {
8960       jam();
8961       SegmentedSectionPtr ss_ptr;
8962       ndbrequire(import(ss_ptr, c_fragData_align32, (c_fragDataLen+1)/2));
8963       handle.m_ptr[AlterTabReq::FRAGMENTATION] = ss_ptr;
8964       handle.m_cnt = 2;
8965     }
8966    }
8967 
8968 
8969   {
8970     SegmentedSectionPtr ptr;
8971     handle.getSection(ptr, AlterTabReq::DICT_TAB_INFO);
8972     if (ptr.sz > MAX_WORDS_META_FILE)
8973     {
8974       jam();
8975       setError(error, AlterTableRef::TableDefinitionTooBig, __LINE__);
8976       return;
8977     }
8978   }
8979 
8980   // save sections
8981   saveOpSection(op_ptr, handle, AlterTabReq::DICT_TAB_INFO);
8982   if (AlterTableReq::getAddFragFlag(impl_req->changeMask))
8983   {
8984     jam();
8985     saveOpSection(op_ptr, handle, AlterTabReq::FRAGMENTATION);
8986   }
8987 
8988   SchemaFile::TableEntry te; te.init();
8989   te.m_tableState = SchemaFile::SF_ALTER;
8990   te.m_tableVersion = newTablePtr.p->tableVersion;
8991   te.m_info_words = getOpSection(op_ptr, AlterTabReq::DICT_TAB_INFO).getSize();
8992   te.m_gcp = 0;
8993   te.m_transId = trans_ptr.p->m_transId;
8994 
8995   err = trans_log_schema_op(op_ptr, impl_req->tableId, &te);
8996   if (err)
8997   {
8998     jam();
8999     setError(error, err, __LINE__);
9000     return;
9001   }
9002 }
9003 
9004 Uint32
check_supported_reorg(Uint32 org_map_id,Uint32 new_map_id)9005 Dbdict::check_supported_reorg(Uint32 org_map_id, Uint32 new_map_id)
9006 {
9007   if (org_map_id == new_map_id)
9008   {
9009     jam();
9010     return 0;
9011   }
9012 
9013   HashMapRecordPtr orgmap_ptr;
9014   ndbrequire(find_object(orgmap_ptr, org_map_id));
9015 
9016   HashMapRecordPtr newmap_ptr;
9017   ndbrequire(find_object(newmap_ptr, new_map_id));
9018 
9019   Ptr<Hash2FragmentMap> orgptr;
9020   g_hash_map.getPtr(orgptr, orgmap_ptr.p->m_map_ptr_i);
9021 
9022   Ptr<Hash2FragmentMap> newptr;
9023   g_hash_map.getPtr(newptr, newmap_ptr.p->m_map_ptr_i);
9024 
9025   /*
9026    * check that old fragments maps to same old fragment
9027    * or to a new fragment.
9028    * allow both extending and shrinking hashmap.
9029    */
9030   Uint32 period = lcm(orgptr.p->m_cnt, newptr.p->m_cnt);
9031   for (Uint32 i = 0; i < period; i++)
9032   {
9033     if (orgptr.p->m_map[i % orgptr.p->m_cnt] != newptr.p->m_map[i % newptr.p->m_cnt] &&
9034         newptr.p->m_map[i % newptr.p->m_cnt] < orgptr.p->m_fragments)
9035     {
9036       /**
9037        * Moving data from "old" fragment into "old" fragment
9038        *   is not supported...
9039        */
9040       jam();
9041       return AlterTableRef::UnsupportedChange;
9042     }
9043   }
9044   return 0;
9045 }
9046 
9047 Uint32
check_supported_add_fragment(Uint16 * newdata,const Uint16 * olddata)9048 Dbdict::check_supported_add_fragment(Uint16* newdata, const Uint16* olddata)
9049 {
9050   Uint32 replicas = newdata[0];
9051   if (replicas != olddata[0])
9052   {
9053     jam();
9054     return AlterTableRef::UnsupportedChange;
9055   }
9056 
9057   Uint32 fragments = newdata[1];
9058   if (fragments < olddata[1])
9059   {
9060     jam();
9061     return AlterTableRef::UnsupportedChange;
9062   }
9063 
9064   Uint32 oldFragments = olddata[1];
9065 #ifdef TODO_XXX
9066   /**
9067    * This doesnt work after a add-nodegroup
9068    *   dont't know why, so we instead just ignore what the API
9069    *   for the already existing partitions
9070    */
9071 
9072   // Check that all the old has the same properties...
9073   // Only compare prefered primary, as replicas come in any order
9074   for (Uint32 i = 0; i<oldFragments; i++)
9075   {
9076     Uint32 idx = 2 + (1 + replicas) * i + 1;
9077     if (newdata[idx] != olddata[idx])
9078     {
9079       jam();
9080       return AlterTableRef::UnsupportedChange;
9081     }
9082   }
9083 #endif
9084 
9085   memmove(newdata + 2,
9086           newdata + 2 + (1 + replicas) * oldFragments,
9087           sizeof(short) * (1 + replicas) * (fragments - oldFragments));
9088 
9089   newdata[1] = (fragments - oldFragments);
9090 
9091   return 0;
9092 }
9093 
9094 bool
alterTable_subOps(Signal * signal,SchemaOpPtr op_ptr)9095 Dbdict::alterTable_subOps(Signal* signal, SchemaOpPtr op_ptr)
9096 {
9097   D("alterTable_subOps" << V(op_ptr.i) << *op_ptr.p);
9098 
9099   AlterTableRecPtr alterTabPtr;
9100   getOpRec(op_ptr, alterTabPtr);
9101   const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
9102 
9103   if (AlterTableReq::getAddFragFlag(impl_req->changeMask))
9104   {
9105     jam();
9106     if (alterTabPtr.p->m_sub_add_frag == false)
9107     {
9108       jam();
9109       TableRecordPtr tabPtr;
9110       TableRecordPtr indexPtr;
9111       bool ok = find_object(tabPtr, impl_req->tableId);
9112       ndbrequire(ok);
9113       LocalTableRecord_list list(c_tableRecordPool_, tabPtr.p->m_indexes);
9114       Uint32 ptrI = alterTabPtr.p->m_sub_add_frag_index_ptr;
9115 
9116       if (ptrI == RNIL)
9117       {
9118         jam();
9119         list.first(indexPtr);
9120       }
9121       else
9122       {
9123         jam();
9124         list.getPtr(indexPtr, ptrI);
9125         list.next(indexPtr);
9126       }
9127 
9128       for (; !indexPtr.isNull(); list.next(indexPtr))
9129       {
9130         if (DictTabInfo::isOrderedIndex(indexPtr.p->tableType))
9131         {
9132           jam();
9133           break;
9134         }
9135       }
9136       if (indexPtr.isNull())
9137       {
9138         jam();
9139         alterTabPtr.p->m_sub_add_frag = true;
9140       }
9141       else
9142       {
9143         jam();
9144         Callback c = {
9145           safe_cast(&Dbdict::alterTable_fromAlterIndex),
9146           op_ptr.p->op_key
9147         };
9148         op_ptr.p->m_callback = c;
9149 
9150         alterTabPtr.p->m_sub_add_frag_index_ptr = indexPtr.i;
9151         alterTable_toAlterIndex(signal, op_ptr);
9152         return true;
9153       }
9154     }
9155   }
9156 
9157   if (AlterTableReq::getReorgFragFlag(impl_req->changeMask))
9158   {
9159     if (alterTabPtr.p->m_sub_reorg_commit == false)
9160     {
9161       jam();
9162       Callback c = {
9163         safe_cast(&Dbdict::alterTable_fromReorgTable),
9164         op_ptr.p->op_key
9165       };
9166       op_ptr.p->m_callback = c;
9167 
9168       alterTabPtr.p->m_sub_reorg_commit = true;
9169       alterTable_toReorgTable(signal, op_ptr, 0);
9170       return true;
9171     }
9172 
9173     if (alterTabPtr.p->m_sub_suma_enable == false)
9174     {
9175       jam();
9176       Callback c = {
9177         safe_cast(&Dbdict::alterTable_fromReorgTable),
9178         op_ptr.p->op_key
9179       };
9180       op_ptr.p->m_callback = c;
9181 
9182       alterTabPtr.p->m_sub_suma_enable = true;
9183       alterTable_toSumaSync(signal, op_ptr, 0);
9184       return true;
9185     }
9186 
9187 
9188     if (alterTabPtr.p->m_sub_suma_filter == false)
9189     {
9190       jam();
9191       Callback c = {
9192         safe_cast(&Dbdict::alterTable_fromReorgTable),
9193         op_ptr.p->op_key
9194       };
9195       op_ptr.p->m_callback = c;
9196 
9197       alterTabPtr.p->m_sub_suma_filter = true;
9198       alterTable_toSumaSync(signal, op_ptr, 1);
9199       return true;
9200     }
9201 
9202     if (alterTabPtr.p->m_sub_trigger == false)
9203     {
9204       jam();
9205       Callback c = {
9206         safe_cast(&Dbdict::alterTable_fromCreateTrigger),
9207         op_ptr.p->op_key
9208       };
9209       op_ptr.p->m_callback = c;
9210 
9211       alterTable_toCreateTrigger(signal, op_ptr);
9212 
9213       alterTabPtr.p->m_sub_trigger = true;
9214       return true;
9215     }
9216 
9217     if (alterTabPtr.p->m_sub_copy_data == false)
9218     {
9219       jam();
9220       Callback c = {
9221         safe_cast(&Dbdict::alterTable_fromCopyData),
9222         op_ptr.p->op_key
9223       };
9224       op_ptr.p->m_callback = c;
9225 
9226       alterTable_toCopyData(signal, op_ptr);
9227 
9228       alterTabPtr.p->m_sub_copy_data = true;
9229       return true;
9230     }
9231 
9232     if (alterTabPtr.p->m_sub_reorg_complete == false)
9233     {
9234       jam();
9235       Callback c = {
9236         safe_cast(&Dbdict::alterTable_fromReorgTable),
9237         op_ptr.p->op_key
9238       };
9239       op_ptr.p->m_callback = c;
9240 
9241       alterTabPtr.p->m_sub_reorg_complete = true;
9242       alterTable_toReorgTable(signal, op_ptr, 1);
9243       return true;
9244     }
9245   }
9246 
9247   return false;
9248 }
9249 
9250 void
alterTable_toAlterIndex(Signal * signal,SchemaOpPtr op_ptr)9251 Dbdict::alterTable_toAlterIndex(Signal* signal,
9252                                 SchemaOpPtr op_ptr)
9253 {
9254   jam();
9255   AlterTableRecPtr alterTabPtr;
9256   getOpRec(op_ptr, alterTabPtr);
9257   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
9258 
9259   TableRecordPtr indexPtr;
9260   c_tableRecordPool_.getPtr(indexPtr, alterTabPtr.p->m_sub_add_frag_index_ptr);
9261   ndbrequire(!indexPtr.isNull());
9262 
9263   AlterIndxReq* req = (AlterIndxReq*)signal->getDataPtrSend();
9264   req->clientRef = reference();
9265   req->clientData = op_ptr.p->op_key;
9266   req->transId = trans_ptr.p->m_transId;
9267   req->transKey = trans_ptr.p->trans_key;
9268   req->requestInfo = 0;
9269   req->indexId = indexPtr.p->tableId;
9270   req->indexVersion = indexPtr.p->tableVersion;
9271   DictSignal::setRequestType(req->requestInfo,
9272                              AlterIndxImplReq::AlterIndexAddPartition);
9273   sendSignal(reference(), GSN_ALTER_INDX_REQ, signal,
9274              AlterIndxReq::SignalLength, JBB);
9275 }
9276 
9277 void
alterTable_fromAlterIndex(Signal * signal,Uint32 op_key,Uint32 ret)9278 Dbdict::alterTable_fromAlterIndex(Signal* signal,
9279                                   Uint32 op_key,
9280                                   Uint32 ret)
9281 {
9282   jamEntry();
9283 
9284   SchemaOpPtr op_ptr;
9285   AlterTableRecPtr alterTablePtr;
9286 
9287   findSchemaOp(op_ptr, alterTablePtr, op_key);
9288   ndbrequire(!op_ptr.isNull());
9289   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
9290 
9291   if (ret == 0) {
9292     const AlterIndxConf* conf =
9293       (const AlterIndxConf*)signal->getDataPtr();
9294 
9295     ndbrequire(conf->transId == trans_ptr.p->m_transId);
9296     createSubOps(signal, op_ptr);
9297   } else {
9298     jam();
9299     const AlterIndxRef* ref =
9300       (const AlterIndxRef*)signal->getDataPtr();
9301     ErrorInfo error;
9302     setError(error, ref);
9303     abortSubOps(signal, op_ptr, error);
9304   }
9305 }
9306 
9307 void
alterTable_toReorgTable(Signal * signal,SchemaOpPtr op_ptr,Uint32 step)9308 Dbdict::alterTable_toReorgTable(Signal* signal,
9309                                 SchemaOpPtr op_ptr,
9310                                 Uint32 step)
9311 {
9312   jam();
9313   AlterTableRecPtr alterTabPtr;
9314   getOpRec(op_ptr, alterTabPtr);
9315   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
9316   const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
9317 
9318   AlterTableReq* req = (AlterTableReq*)signal->getDataPtrSend();
9319   req->clientRef = reference();
9320   req->clientData = op_ptr.p->op_key;
9321   req->transId = trans_ptr.p->m_transId;
9322   req->transKey = trans_ptr.p->trans_key;
9323   req->requestInfo = 0;
9324   req->tableId = impl_req->tableId;
9325   req->tableVersion = impl_req->tableVersion;
9326   req->changeMask = 0;
9327   if (step == 0)
9328   {
9329     jam();
9330     AlterTableReq::setReorgCommitFlag(req->changeMask, 1);
9331   }
9332   else if (step == 1)
9333   {
9334     jam();
9335     AlterTableReq::setReorgCompleteFlag(req->changeMask, 1);
9336   }
9337   else
9338   {
9339     jamLine(step);
9340     ndbrequire(false);
9341   }
9342   sendSignal(reference(), GSN_ALTER_TABLE_REQ, signal,
9343              AlterTableReq::SignalLength, JBB);
9344 }
9345 
9346 void
alterTable_fromReorgTable(Signal * signal,Uint32 op_key,Uint32 ret)9347 Dbdict::alterTable_fromReorgTable(Signal* signal,
9348                                   Uint32 op_key,
9349                                   Uint32 ret)
9350 {
9351   jamEntry();
9352 
9353   SchemaOpPtr op_ptr;
9354   AlterTableRecPtr alterTablePtr;
9355 
9356   findSchemaOp(op_ptr, alterTablePtr, op_key);
9357   ndbrequire(!op_ptr.isNull());
9358   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
9359 
9360   if (ret == 0)
9361   {
9362     jam();
9363     const AlterTableConf* conf =
9364       (const AlterTableConf*)signal->getDataPtr();
9365 
9366     ndbrequire(conf->transId == trans_ptr.p->m_transId);
9367     createSubOps(signal, op_ptr);
9368   } else {
9369     jam();
9370     const AlterTableRef* ref =
9371       (const AlterTableRef*)signal->getDataPtr();
9372     ErrorInfo error;
9373     setError(error, ref);
9374     abortSubOps(signal, op_ptr, error);
9375   }
9376 }
9377 
9378 void
alterTable_toCreateTrigger(Signal * signal,SchemaOpPtr op_ptr)9379 Dbdict::alterTable_toCreateTrigger(Signal* signal,
9380                                    SchemaOpPtr op_ptr)
9381 {
9382   jam();
9383 
9384   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
9385   AlterTableRecPtr alterTablePtr;
9386   getOpRec(op_ptr, alterTablePtr);
9387   const AlterTabReq* impl_req = &alterTablePtr.p->m_request;
9388 
9389   const TriggerTmpl& triggerTmpl = g_reorgTriggerTmpl[0];
9390 
9391   CreateTrigReq* req = (CreateTrigReq*)signal->getDataPtrSend();
9392 
9393   Uint32 requestInfo = 0;
9394   DictSignal::setRequestType(requestInfo, CreateTrigReq::CreateTriggerOnline);
9395 
9396   req->clientRef = reference();
9397   req->clientData = op_ptr.p->op_key;
9398   req->transId = trans_ptr.p->m_transId;
9399   req->transKey = trans_ptr.p->trans_key;
9400   req->requestInfo = requestInfo;
9401   req->tableId = impl_req->tableId;
9402   req->tableVersion = impl_req->tableVersion;
9403   req->indexId = RNIL;
9404   req->indexVersion = RNIL;
9405   req->triggerNo = 0;
9406   req->forceTriggerId = RNIL;
9407 
9408   TriggerInfo::packTriggerInfo(req->triggerInfo, triggerTmpl.triggerInfo);
9409 
9410   req->receiverRef = 0;
9411 
9412   char triggerName[MAX_TAB_NAME_SIZE];
9413   sprintf(triggerName, triggerTmpl.nameFormat, impl_req->tableId);
9414 
9415   // name section
9416   Uint32 buffer[2 + ((MAX_TAB_NAME_SIZE + 3) >> 2)];    // SP string
9417   LinearWriter w(buffer, sizeof(buffer) >> 2);
9418   w.reset();
9419   w.add(DictTabInfo::TableName, triggerName);
9420   LinearSectionPtr lsPtr[3];
9421   lsPtr[0].p = buffer;
9422   lsPtr[0].sz = w.getWordsUsed();
9423 
9424   AttributeMask mask;
9425   mask.clear();
9426   lsPtr[1].p = mask.rep.data;
9427   lsPtr[1].sz = mask.getSizeInWords();
9428 
9429   sendSignal(reference(), GSN_CREATE_TRIG_REQ, signal,
9430              CreateTrigReq::SignalLength, JBB, lsPtr, 2);
9431 }
9432 
9433 void
alterTable_fromCreateTrigger(Signal * signal,Uint32 op_key,Uint32 ret)9434 Dbdict::alterTable_fromCreateTrigger(Signal* signal, Uint32 op_key, Uint32 ret)
9435 {
9436   alterTable_fromAlterIndex(signal, op_key, ret);
9437 }
9438 
9439 void
alterTable_toCopyData(Signal * signal,SchemaOpPtr op_ptr)9440 Dbdict::alterTable_toCopyData(Signal* signal, SchemaOpPtr op_ptr)
9441 {
9442   jam();
9443 
9444   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
9445   AlterTableRecPtr alterTablePtr;
9446   getOpRec(op_ptr, alterTablePtr);
9447   const AlterTabReq* impl_req = &alterTablePtr.p->m_request;
9448   TableRecordPtr tablePtr;
9449   bool ok = find_object(tablePtr, impl_req->tableId);
9450   ndbrequire(ok);
9451 
9452   CopyDataReq* req = (CopyDataReq*)signal->getDataPtrSend();
9453 
9454   req->clientRef = reference();
9455   req->clientData = op_ptr.p->op_key;
9456   req->transId = trans_ptr.p->m_transId;
9457   req->transKey = trans_ptr.p->trans_key;
9458   req->requestInfo = 0;
9459   req->requestType = 0;
9460   req->srcTableId = impl_req->tableId;
9461   req->dstTableId = impl_req->tableId;
9462   req->srcFragments = tablePtr.p->fragmentCount;
9463 
9464   sendSignal(reference(), GSN_COPY_DATA_REQ, signal,
9465              CopyDataReq::SignalLength, JBB);
9466 }
9467 
9468 void
alterTable_fromCopyData(Signal * signal,Uint32 op_key,Uint32 ret)9469 Dbdict::alterTable_fromCopyData(Signal* signal, Uint32 op_key, Uint32 ret)
9470 {
9471   alterTable_fromAlterIndex(signal, op_key, ret);
9472 }
9473 
9474 void
alterTable_reply(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)9475 Dbdict::alterTable_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
9476 {
9477   jam();
9478   D("alterTable_reply" << V(op_ptr.i) << *op_ptr.p);
9479 
9480   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
9481 
9482   AlterTableRecPtr alterTabPtr;
9483   getOpRec(op_ptr, alterTabPtr);
9484   const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
9485 
9486   if (!hasError(error)) {
9487     AlterTableConf* conf = (AlterTableConf*)signal->getDataPtrSend();
9488     conf->senderRef = reference();
9489     conf->clientData = op_ptr.p->m_clientData;
9490     conf->transId = trans_ptr.p->m_transId;
9491     conf->tableId = impl_req->tableId;
9492     conf->tableVersion = impl_req->tableVersion;
9493     conf->newTableVersion = impl_req->newTableVersion;
9494 
9495     Uint32 clientRef = op_ptr.p->m_clientRef;
9496     sendSignal(clientRef, GSN_ALTER_TABLE_CONF, signal,
9497                AlterTableConf::SignalLength, JBB);
9498   } else {
9499     jam();
9500     AlterTableRef* ref = (AlterTableRef*)signal->getDataPtrSend();
9501     ref->senderRef = reference();
9502     ref->clientData = op_ptr.p->m_clientData;
9503     ref->transId = trans_ptr.p->m_transId;
9504     getError(error, ref);
9505     ref->errorStatus = error.errorStatus;
9506     ref->errorKey = error.errorKey;
9507 
9508     Uint32 clientRef = op_ptr.p->m_clientRef;
9509     sendSignal(clientRef, GSN_ALTER_TABLE_REF, signal,
9510                AlterTableRef::SignalLength, JBB);
9511   }
9512 }
9513 
9514 void
alterTable_toSumaSync(Signal * signal,SchemaOpPtr op_ptr,Uint32 step)9515 Dbdict::alterTable_toSumaSync(Signal* signal,
9516                               SchemaOpPtr op_ptr,
9517                               Uint32 step)
9518 {
9519   jam();
9520   AlterTableRecPtr alterTabPtr;
9521   getOpRec(op_ptr, alterTabPtr);
9522   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
9523   const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
9524 
9525   AlterTableReq* req = (AlterTableReq*)signal->getDataPtrSend();
9526   req->clientRef = reference();
9527   req->clientData = op_ptr.p->op_key;
9528   req->transId = trans_ptr.p->m_transId;
9529   req->transKey = trans_ptr.p->trans_key;
9530   req->requestInfo = 0;
9531   req->tableId = impl_req->tableId;
9532   req->tableVersion = impl_req->tableVersion;
9533   req->changeMask = 0;
9534   if (step == 0)
9535   {
9536     jam();
9537     AlterTableReq::setReorgSumaEnableFlag(req->changeMask, 1);
9538   }
9539   else if (step == 1)
9540   {
9541     AlterTableReq::setReorgSumaFilterFlag(req->changeMask, 1);
9542   }
9543   else
9544   {
9545     jamLine(step);
9546     ndbrequire(false);
9547   }
9548   sendSignal(reference(), GSN_ALTER_TABLE_REQ, signal,
9549              AlterTableReq::SignalLength, JBB);
9550 }
9551 
9552 
9553 // AlterTable: PREPARE
9554 
9555 void
alterTable_prepare(Signal * signal,SchemaOpPtr op_ptr)9556 Dbdict::alterTable_prepare(Signal* signal, SchemaOpPtr op_ptr)
9557 {
9558   jam();
9559   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
9560 
9561   AlterTableRecPtr alterTabPtr;
9562   getOpRec(op_ptr, alterTabPtr);
9563   const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
9564 
9565   D("alterTable_prepare" << *op_ptr.p);
9566 
9567   if (AlterTableReq::getReorgSubOp(impl_req->changeMask))
9568   {
9569     jam();
9570 
9571     /**
9572      * Get DIH connectPtr for future commit
9573      */
9574     {
9575       SchemaOpPtr tmp = op_ptr;
9576       LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
9577       for (list.prev(tmp); !tmp.isNull(); list.prev(tmp))
9578       {
9579         jam();
9580         if (&tmp.p->m_oprec_ptr.p->m_opInfo== &Dbdict::AlterTableRec::g_opInfo)
9581         {
9582           jam();
9583           break;
9584         }
9585       }
9586       ndbrequire(!tmp.isNull());
9587       alterTabPtr.p->m_dihAddFragPtr =
9588         ((AlterTableRec*)tmp.p->m_oprec_ptr.p)->m_dihAddFragPtr;
9589       alterTabPtr.p->m_lqhFragPtr =
9590         ((AlterTableRec*)tmp.p->m_oprec_ptr.p)->m_lqhFragPtr;
9591     }
9592 
9593     sendTransConf(signal, op_ptr);
9594     return;
9595   }
9596 
9597   Mutex mutex(signal, c_mutexMgr, alterTabPtr.p->m_define_backup_mutex);
9598   Callback c = {
9599     safe_cast(&Dbdict::alterTable_backup_mutex_locked),
9600     op_ptr.p->op_key
9601   };
9602   bool ok = mutex.lock(c);
9603   ndbrequire(ok);
9604   return;
9605 }
9606 
9607 void
alterTable_backup_mutex_locked(Signal * signal,Uint32 op_key,Uint32 ret)9608 Dbdict::alterTable_backup_mutex_locked(Signal* signal,
9609                                        Uint32 op_key,
9610                                        Uint32 ret)
9611 {
9612   jamEntry();
9613   D("alterTable_backup_mutex_locked");
9614 
9615   ndbrequire(ret == 0);
9616 
9617   SchemaOpPtr op_ptr;
9618   AlterTableRecPtr alterTabPtr;
9619   findSchemaOp(op_ptr, alterTabPtr, op_key);
9620   ndbrequire(!op_ptr.isNull());
9621   const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
9622 
9623   TableRecordPtr tablePtr;
9624   bool ok = find_object(tablePtr, impl_req->tableId);
9625   ndbrequire(ok);
9626 
9627   Mutex mutex(signal, c_mutexMgr, alterTabPtr.p->m_define_backup_mutex);
9628   mutex.unlock(); // ignore response
9629 
9630   if (tablePtr.p->m_read_locked)
9631   {
9632     jam();
9633     setError(op_ptr, AlterTableRef::BackupInProgress, __LINE__);
9634     sendTransRef(signal, op_ptr);
9635     return;
9636   }
9637 
9638   /**
9639    * Write new table definition on prepare
9640    */
9641   Callback callback = {
9642     safe_cast(&Dbdict::alterTab_writeTableConf),
9643     callback.m_callbackData = op_ptr.p->op_key
9644   };
9645 
9646   const OpSection& tabInfoSec =
9647     getOpSection(op_ptr, CreateTabReq::DICT_TAB_INFO);
9648 
9649   bool savetodisk = !(tablePtr.p->m_bits & TableRecord::TR_Temporary);
9650   if (savetodisk) {
9651     writeTableFile(signal, op_ptr, impl_req->tableId, tabInfoSec, &callback);
9652   } else {
9653     execute(signal, callback, 0);
9654   }
9655 }
9656 
9657 void
alterTab_writeTableConf(Signal * signal,Uint32 op_key,Uint32 ret)9658 Dbdict::alterTab_writeTableConf(Signal* signal, Uint32 op_key, Uint32 ret)
9659 {
9660   jam();
9661   ndbrequire(ret == 0);
9662 
9663   SchemaOpPtr op_ptr;
9664   AlterTableRecPtr alterTabPtr;
9665   findSchemaOp(op_ptr, alterTabPtr, op_key);
9666 
9667   alterTable_toLocal(signal, op_ptr);
9668 }
9669 
9670 void
alterTable_toLocal(Signal * signal,SchemaOpPtr op_ptr)9671 Dbdict::alterTable_toLocal(Signal* signal, SchemaOpPtr op_ptr)
9672 {
9673   AlterTableRecPtr alterTabPtr;
9674   getOpRec(op_ptr, alterTabPtr);
9675   const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
9676 
9677   const Uint32 blockIndex = alterTabPtr.p->m_blockIndex;
9678   if (blockIndex == AlterTableRec::BlockCount)
9679   {
9680     jam();
9681     sendTransConf(signal, op_ptr);
9682     return;
9683   }
9684 
9685   ndbrequire(blockIndex < AlterTableRec::BlockCount);
9686   const Uint32 blockNo = alterTabPtr.p->m_blockNo[blockIndex];
9687 
9688   D("alterTable_toLocal" << V(blockIndex) << V(getBlockName(blockNo)));
9689 
9690   AlterTabReq* req = (AlterTabReq*)signal->getDataPtrSend();
9691   req->senderRef = reference();
9692   req->senderData = op_ptr.p->op_key;
9693   req->requestType = AlterTabReq::AlterTablePrepare;
9694   req->tableId = impl_req->tableId;
9695   req->tableVersion = impl_req->tableVersion;
9696   req->newTableVersion = impl_req->newTableVersion;
9697   req->gci = impl_req->gci;
9698   req->changeMask = impl_req->changeMask;
9699   req->connectPtr = RNIL;
9700   req->noOfNewAttr = impl_req->noOfNewAttr;
9701   req->newNoOfCharsets = impl_req->newNoOfCharsets;
9702   req->newNoOfKeyAttrs = impl_req->newNoOfKeyAttrs;
9703 
9704   Callback c = {
9705     safe_cast(&Dbdict::alterTable_fromLocal),
9706     op_ptr.p->op_key
9707   };
9708   op_ptr.p->m_callback = c;
9709 
9710   if (ERROR_INSERTED(6131) &&
9711       blockIndex + 1 == AlterTableRec::BlockCount) {
9712     jam();
9713     CLEAR_ERROR_INSERT_VALUE;
9714     AlterTabRef* ref = (AlterTabRef*)signal->getDataPtrSend();
9715     ref->senderRef = reference();
9716     ref->senderData = op_ptr.p->op_key;
9717     ref->errorCode = 9131;
9718     sendSignal(reference(), GSN_ALTER_TAB_REF, signal,
9719                AlterTabRef::SignalLength, JBB);
9720     return;
9721   }
9722 
9723   BlockReference blockRef = numberToRef(blockNo, getOwnNodeId());
9724 
9725   if (blockNo == DBLQH && req->noOfNewAttr > 0)
9726   {
9727     jam();
9728     LinearSectionPtr ptr[3];
9729     Uint32 newAttrData[2 * MAX_ATTRIBUTES_IN_TABLE];
9730     ndbrequire(impl_req->noOfNewAttr <= MAX_ATTRIBUTES_IN_TABLE);
9731     ndbrequire(2 * impl_req->noOfNewAttr == alterTabPtr.p->m_newAttrData.getSize());
9732     LocalArenaPoolImpl op_sec_pool(op_ptr.p->m_trans_ptr.p->m_arena, c_opSectionBufferPool);
9733     bool ok = copyOut(op_sec_pool, alterTabPtr.p->m_newAttrData, newAttrData, 2 * impl_req->noOfNewAttr);
9734     ndbrequire(ok);
9735 
9736     ptr[0].p = newAttrData;
9737     ptr[0].sz = 2 * impl_req->noOfNewAttr;
9738     sendSignal(blockRef, GSN_ALTER_TAB_REQ, signal,
9739                AlterTabReq::SignalLength, JBB, ptr, 1);
9740   }
9741   else if (blockNo == DBDIH && AlterTableReq::getAddFragFlag(req->changeMask))
9742   {
9743     jam();
9744     const OpSection& fragInfoSec =
9745       getOpSection(op_ptr, AlterTabReq::FRAGMENTATION);
9746     SegmentedSectionPtr fragInfoPtr;
9747     LocalArenaPoolImpl op_sec_pool(op_ptr.p->m_trans_ptr.p->m_arena,c_opSectionBufferPool);
9748     bool ok = copyOut(op_sec_pool, fragInfoSec, fragInfoPtr);
9749     ndbrequire(ok);
9750 
9751     if (AlterTableReq::getReorgFragFlag(req->changeMask))
9752     {
9753       jam();
9754       HashMapRecordPtr hm_ptr;
9755       TableRecordPtr newTablePtr;
9756       newTablePtr.i = alterTabPtr.p->m_newTablePtrI;
9757       c_tableRecordPool_.getPtr(newTablePtr);
9758       ndbrequire(find_object(hm_ptr,
9759                              newTablePtr.p->hashMapObjectId));
9760       req->new_map_ptr_i = hm_ptr.p->m_map_ptr_i;
9761     }
9762 
9763     SectionHandle handle(this, fragInfoPtr.i);
9764     sendSignal(blockRef, GSN_ALTER_TAB_REQ, signal,
9765                AlterTabReq::SignalLength, JBB, &handle);
9766   }
9767   else
9768   {
9769     jam();
9770     sendSignal(blockRef, GSN_ALTER_TAB_REQ, signal,
9771                AlterTabReq::SignalLength, JBB);
9772   }
9773 }
9774 
9775 void
alterTable_fromLocal(Signal * signal,Uint32 op_key,Uint32 ret)9776 Dbdict::alterTable_fromLocal(Signal* signal,
9777                              Uint32 op_key,
9778                              Uint32 ret)
9779 {
9780   D("alterTable_fromLocal");
9781 
9782   SchemaOpPtr op_ptr;
9783   AlterTableRecPtr alterTabPtr;
9784   findSchemaOp(op_ptr, alterTabPtr, op_key);
9785   ndbrequire(!op_ptr.isNull());
9786 
9787   Uint32& blockIndex = alterTabPtr.p->m_blockIndex; //ref
9788   ndbrequire(blockIndex < AlterTableRec::BlockCount);
9789   const Uint32 blockNo = alterTabPtr.p->m_blockNo[blockIndex];
9790 
9791   if (ret)
9792   {
9793     jam();
9794     setError(op_ptr, ret, __LINE__);
9795     sendTransRef(signal, op_ptr);
9796     return;
9797   }
9798 
9799   const AlterTabConf* conf = (const AlterTabConf*)signal->getDataPtr();
9800 
9801   // save TUP operation record for commit/abort
9802   switch(blockNo){
9803   case DBLQH:
9804     jam();
9805     alterTabPtr.p->m_lqhFragPtr = conf->connectPtr;
9806     break;
9807   case DBDIH:
9808     jam();
9809     alterTabPtr.p->m_dihAddFragPtr = conf->connectPtr;
9810     break;
9811   }
9812 
9813   blockIndex += 1;
9814   alterTable_toLocal(signal, op_ptr);
9815 }
9816 
9817 // AlterTable: COMMIT
9818 
9819 void
alterTable_commit(Signal * signal,SchemaOpPtr op_ptr)9820 Dbdict::alterTable_commit(Signal* signal, SchemaOpPtr op_ptr)
9821 {
9822   AlterTableRecPtr alterTabPtr;
9823   getOpRec(op_ptr, alterTabPtr);
9824   const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
9825 
9826   D("alterTable_commit" << *op_ptr.p);
9827 
9828   TableRecordPtr tablePtr;
9829   bool ok = find_object(tablePtr, impl_req->tableId);
9830   ndbrequire(ok);
9831 
9832   if (op_ptr.p->m_sections)
9833   {
9834     jam();
9835     // main-op
9836     ndbrequire(AlterTableReq::getReorgSubOp(impl_req->changeMask) == false);
9837 
9838     const OpSection& tabInfoSec =
9839       getOpSection(op_ptr, CreateTabReq::DICT_TAB_INFO);
9840     const Uint32 size = tabInfoSec.getSize();
9841 
9842     // update table record
9843     tablePtr.p->packedSize = size;
9844     tablePtr.p->tableVersion = impl_req->newTableVersion;
9845     tablePtr.p->gciTableCreated = impl_req->gci;
9846 
9847     TableRecordPtr newTablePtr;
9848     newTablePtr.i = alterTabPtr.p->m_newTablePtrI;
9849     c_tableRecordPool_.getPtr(newTablePtr);
9850 
9851     const Uint32 changeMask = impl_req->changeMask;
9852 
9853     // perform DICT memory changes
9854     if (AlterTableReq::getNameFlag(changeMask))
9855     {
9856       jam();
9857       const Uint32 sz = MAX_TAB_NAME_SIZE;
9858       D("alter name:"
9859         << " old=" << copyRope<sz>(tablePtr.p->tableName)
9860         << " new=" << copyRope<sz>(newTablePtr.p->tableName));
9861 
9862       DictObjectPtr obj_ptr;
9863       c_obj_pool.getPtr(obj_ptr, tablePtr.p->m_obj_ptr_i);
9864 
9865       // remove old name from hash
9866       c_obj_name_hash.remove(obj_ptr);
9867 
9868       // save old name and replace it by new
9869       bool ok =
9870         copyRope<sz>(alterTabPtr.p->m_oldTableName, tablePtr.p->tableName) &&
9871         copyRope<sz>(tablePtr.p->tableName, newTablePtr.p->tableName);
9872       ndbrequire(ok);
9873 
9874       // add new name to object hash
9875       obj_ptr.p->m_name = tablePtr.p->tableName;
9876       c_obj_name_hash.add(obj_ptr);
9877     }
9878 
9879     if (AlterTableReq::getFrmFlag(changeMask))
9880     {
9881       jam();
9882       // save old frm and replace it by new
9883       const Uint32 sz = MAX_FRM_DATA_SIZE;
9884       bool ok =
9885         copyRope<sz>(alterTabPtr.p->m_oldFrmData, tablePtr.p->frmData) &&
9886         copyRope<sz>(tablePtr.p->frmData, newTablePtr.p->frmData);
9887       ndbrequire(ok);
9888     }
9889 
9890     if (AlterTableReq::getAddAttrFlag(changeMask))
9891     {
9892       jam();
9893 
9894       /* Move the column definitions to the real table definitions. */
9895       LocalAttributeRecord_list
9896         list(c_attributeRecordPool, tablePtr.p->m_attributes);
9897       LocalAttributeRecord_list
9898         newlist(c_attributeRecordPool, newTablePtr.p->m_attributes);
9899 
9900       const Uint32 noOfNewAttr = impl_req->noOfNewAttr;
9901       ndbrequire(noOfNewAttr > 0);
9902       Uint32 i;
9903 
9904       /* Move back to find the first column to move. */
9905       AttributeRecordPtr pPtr;
9906       ndbrequire(newlist.last(pPtr));
9907       for (i = 1; i < noOfNewAttr; i++) {
9908         jam();
9909         ndbrequire(newlist.prev(pPtr));
9910       }
9911 
9912       /* Move columns. */
9913       for (i = 0; i < noOfNewAttr; i++) {
9914         AttributeRecordPtr qPtr = pPtr;
9915         newlist.next(pPtr);
9916         newlist.remove(qPtr);
9917         list.addLast(qPtr);
9918       }
9919       tablePtr.p->noOfAttributes += noOfNewAttr;
9920     }
9921 
9922     if (AlterTableReq::getAddFragFlag(changeMask))
9923     {
9924       jam();
9925       Uint32 save = tablePtr.p->fragmentCount;
9926       tablePtr.p->fragmentCount = newTablePtr.p->fragmentCount;
9927       newTablePtr.p->fragmentCount = save;
9928     }
9929   }
9930 
9931   alterTabPtr.p->m_blockIndex = 0;
9932   alterTabPtr.p->m_blockNo[0] = DBLQH;
9933   alterTabPtr.p->m_blockNo[1] = DBDIH;
9934   alterTabPtr.p->m_blockNo[2] = DBSPJ;
9935   alterTabPtr.p->m_blockNo[3] = DBTC;
9936 
9937   if (AlterTableReq::getReorgFragFlag(impl_req->changeMask))
9938   {
9939     /**
9940      * DIH is next op
9941      */
9942     TableRecordPtr newTablePtr;
9943     newTablePtr.i = alterTabPtr.p->m_newTablePtrI;
9944     c_tableRecordPool_.getPtr(newTablePtr);
9945     tablePtr.p->hashMapObjectId = newTablePtr.p->hashMapObjectId;
9946     tablePtr.p->hashMapVersion = newTablePtr.p->hashMapVersion;
9947     alterTabPtr.p->m_blockNo[1] = RNIL;
9948   }
9949   else if (AlterTableReq::getReorgCommitFlag(impl_req->changeMask))
9950   {
9951     jam();
9952     /**
9953      * Reorg commit, only commit at DIH
9954      */
9955     alterTabPtr.p->m_blockNo[0] = RNIL;
9956     alterTabPtr.p->m_blockNo[2] = RNIL;
9957     alterTabPtr.p->m_blockNo[3] = RNIL;
9958   }
9959   else if (AlterTableReq::getReorgCompleteFlag(impl_req->changeMask) ||
9960            AlterTableReq::getReorgSumaEnableFlag(impl_req->changeMask) ||
9961            AlterTableReq::getReorgSumaFilterFlag(impl_req->changeMask))
9962   {
9963     jam();
9964     sendTransConf(signal, op_ptr);
9965     return;
9966   }
9967 
9968   alterTable_toCommitComplete(signal, op_ptr);
9969 }
9970 
9971 void
alterTable_toCommitComplete(Signal * signal,SchemaOpPtr op_ptr,Uint32 type)9972 Dbdict::alterTable_toCommitComplete(Signal* signal,
9973                                     SchemaOpPtr op_ptr,
9974                                     Uint32 type)
9975 {
9976   D("alterTable_toTupCommit");
9977 
9978   AlterTableRecPtr alterTabPtr;
9979   getOpRec(op_ptr, alterTabPtr);
9980   const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
9981 
9982   AlterTabReq* req = (AlterTabReq*)signal->getDataPtrSend();
9983   req->senderRef = reference();
9984   req->senderData = op_ptr.p->op_key;
9985   if (type == ~Uint32(0))
9986   {
9987     jam();
9988     switch(op_ptr.p->m_state){
9989     case SchemaOp::OS_COMMITTING:
9990       jam();
9991       req->requestType = AlterTabReq::AlterTableCommit;
9992       break;
9993     case SchemaOp::OS_COMPLETING:
9994       jam();
9995       req->requestType = AlterTabReq::AlterTableComplete;
9996       break;
9997     default:
9998       jamLine(op_ptr.p->m_state);
9999       ndbrequire(false);
10000     }
10001   }
10002   else
10003   {
10004     jam();
10005     jamLine(type);
10006     req->requestType = type;
10007   }
10008 
10009   req->tableId = impl_req->tableId;
10010   req->tableVersion = impl_req->tableVersion;
10011   req->newTableVersion = impl_req->newTableVersion;
10012   req->gci = impl_req->gci;
10013   req->changeMask = impl_req->changeMask;
10014   req->noOfNewAttr = impl_req->noOfNewAttr;
10015   req->newNoOfCharsets = impl_req->newNoOfCharsets;
10016   req->newNoOfKeyAttrs = impl_req->newNoOfKeyAttrs;
10017   req->connectPtr = RNIL;
10018 
10019   Uint32 blockIndex = alterTabPtr.p->m_blockIndex; //ref
10020   const Uint32 blockNo = alterTabPtr.p->m_blockNo[blockIndex];
10021   switch(blockNo){
10022   case DBDIH:
10023     jam();
10024     req->connectPtr = alterTabPtr.p->m_dihAddFragPtr;
10025     break;
10026   case DBLQH:
10027     req->connectPtr = alterTabPtr.p->m_lqhFragPtr;
10028     break;
10029   case RNIL:
10030     alterTable_fromCommitComplete(signal, op_ptr.p->op_key, 0);
10031     return;
10032   }
10033 
10034   Callback c = {
10035     safe_cast(&Dbdict::alterTable_fromCommitComplete),
10036     op_ptr.p->op_key
10037   };
10038   op_ptr.p->m_callback = c;
10039 
10040   sendSignal(numberToRef(blockNo, getOwnNodeId()),
10041              GSN_ALTER_TAB_REQ, signal,
10042              AlterTabReq::SignalLength, JBB);
10043 }
10044 
10045 void
alterTable_fromCommitComplete(Signal * signal,Uint32 op_key,Uint32 ret)10046 Dbdict::alterTable_fromCommitComplete(Signal* signal,
10047                                       Uint32 op_key,
10048                                       Uint32 ret)
10049 {
10050   D("alterTable_fromCommit");
10051 
10052   SchemaOpPtr op_ptr;
10053   AlterTableRecPtr alterTabPtr;
10054   findSchemaOp(op_ptr, alterTabPtr, op_key);
10055   ndbrequire(!op_ptr.isNull());
10056   const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
10057 
10058   ndbrequire(ret == 0); // Failure during commit is not allowed
10059   if (++ alterTabPtr.p->m_blockIndex < AlterTableRec::BlockCount)
10060   {
10061     jam();
10062     alterTable_toCommitComplete(signal, op_ptr);
10063     return;
10064   }
10065 
10066   if (AlterTableReq::getReorgSubOp(impl_req->changeMask))
10067   {
10068     jam();
10069     sendTransConf(signal, op_ptr);
10070     return;
10071   }
10072 
10073   if (op_ptr.p->m_state == SchemaOp::OS_COMPLETING)
10074   {
10075     jam();
10076     sendTransConf(signal, op_ptr);
10077     return;
10078   }
10079 
10080   const Uint32 tableId = impl_req->tableId;
10081   TableRecordPtr tablePtr;
10082   bool ok = find_object(tablePtr, tableId);
10083   ndbrequire(ok);
10084 
10085   // inform Suma so it can send events to any subscribers of the table
10086   {
10087     AlterTabReq* req = (AlterTabReq*)signal->getDataPtrSend();
10088 
10089     SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
10090 
10091     // special use of senderRef
10092     if (trans_ptr.p->m_isMaster)
10093       req->senderRef = trans_ptr.p->m_clientRef;
10094     else
10095       req->senderRef = 0;
10096     req->senderData = op_key;
10097     req->tableId = impl_req->tableId;
10098     req->tableVersion = impl_req->tableVersion;
10099     req->newTableVersion = impl_req->newTableVersion;
10100     req->gci = tablePtr.p->gciTableCreated;
10101     req->requestType = 0;
10102     req->changeMask = impl_req->changeMask;
10103     req->connectPtr = RNIL;
10104     req->noOfNewAttr = impl_req->noOfNewAttr;
10105     req->newNoOfCharsets = impl_req->newNoOfCharsets;
10106     req->newNoOfKeyAttrs = impl_req->newNoOfKeyAttrs;
10107 
10108     const OpSection& tabInfoSec =
10109       getOpSection(op_ptr, AlterTabReq::DICT_TAB_INFO);
10110     SegmentedSectionPtr tabInfoPtr;
10111     LocalArenaPoolImpl op_sec_pool(op_ptr.p->m_trans_ptr.p->m_arena,c_opSectionBufferPool);
10112     bool ok = copyOut(op_sec_pool, tabInfoSec, tabInfoPtr);
10113     ndbrequire(ok);
10114 
10115     SectionHandle handle(this, tabInfoPtr.i);
10116     sendSignal(SUMA_REF, GSN_ALTER_TAB_REQ, signal,
10117                AlterTabReq::SignalLength, JBB, &handle);
10118   }
10119 
10120   // older way to notify  wl3600_todo disable to find SUMA problems
10121   {
10122     ApiBroadcastRep* api= (ApiBroadcastRep*)signal->getDataPtrSend();
10123     api->gsn = GSN_ALTER_TABLE_REP;
10124     api->minVersion = MAKE_VERSION(4,1,15);
10125 
10126     AlterTableRep* rep = (AlterTableRep*)api->theData;
10127     rep->tableId = tablePtr.p->tableId;
10128     // wl3600_todo wants old version?
10129     rep->tableVersion = impl_req->tableVersion;
10130     rep->changeType = AlterTableRep::CT_ALTERED;
10131 
10132     char oldTableName[MAX_TAB_NAME_SIZE];
10133     memset(oldTableName, 0, sizeof(oldTableName));
10134     {
10135       const RopeHandle& rh =
10136         AlterTableReq::getNameFlag(impl_req->changeMask)
10137           ? alterTabPtr.p->m_oldTableName
10138           : tablePtr.p->tableName;
10139       ConstRope r(c_rope_pool, rh);
10140       r.copy(oldTableName);
10141     }
10142 
10143     LinearSectionPtr ptr[3];
10144     ptr[0].p = (Uint32*)oldTableName;
10145     ptr[0].sz = (sizeof(oldTableName) + 3) >> 2;
10146 
10147     sendSignal(QMGR_REF, GSN_API_BROADCAST_REP, signal,
10148 	       ApiBroadcastRep::SignalLength + AlterTableRep::SignalLength,
10149 	       JBB, ptr, 1);
10150   }
10151 
10152   {
10153     // Remark object as free
10154     SchemaFile::TableEntry *
10155       objEntry = getTableEntry(alterTabPtr.p->m_newTable_realObjectId);
10156     objEntry->m_tableType = DictTabInfo::UndefTableType;
10157     objEntry->m_tableState = SchemaFile::SF_UNUSED;
10158     objEntry->m_transId = 0;
10159   }
10160 
10161   releaseTableObject(alterTabPtr.p->m_newTablePtrI, false);
10162   sendTransConf(signal, op_ptr);
10163 }
10164 
10165 // AlterTable: COMPLETE
10166 
10167 void
alterTable_complete(Signal * signal,SchemaOpPtr op_ptr)10168 Dbdict::alterTable_complete(Signal* signal, SchemaOpPtr op_ptr)
10169 {
10170   jam();
10171 
10172   AlterTableRecPtr alterTabPtr;
10173   getOpRec(op_ptr, alterTabPtr);
10174   const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
10175 
10176   alterTabPtr.p->m_blockIndex = 0;
10177   alterTabPtr.p->m_blockNo[0] = RNIL;
10178   alterTabPtr.p->m_blockNo[1] = RNIL;
10179   alterTabPtr.p->m_blockNo[2] = RNIL;
10180   alterTabPtr.p->m_blockNo[3] = RNIL;
10181 
10182   if (AlterTableReq::getReorgCommitFlag(impl_req->changeMask))
10183   {
10184     jam();
10185     alterTabPtr.p->m_blockNo[0] = DBDIH;
10186     alterTable_toCommitComplete(signal, op_ptr,
10187                                 AlterTabReq::AlterTableWaitScan);
10188     return;
10189   }
10190   else if (AlterTableReq::getReorgCompleteFlag(impl_req->changeMask))
10191   {
10192     jam();
10193 
10194     /**
10195      * Reorg complete, LQH/DIH
10196      */
10197     alterTabPtr.p->m_blockNo[0] = DBDIH;
10198     alterTabPtr.p->m_blockNo[1] = DBLQH;
10199     alterTable_toCommitComplete(signal, op_ptr);
10200     return;
10201   }
10202   else if (AlterTableReq::getReorgSumaEnableFlag(impl_req->changeMask))
10203   {
10204     jam();
10205     alterTabPtr.p->m_blockNo[0] = DBLQH;
10206     alterTable_toCommitComplete(signal, op_ptr,
10207                                 AlterTabReq::AlterTableSumaEnable);
10208     return;
10209   }
10210   else if (AlterTableReq::getReorgSumaFilterFlag(impl_req->changeMask))
10211   {
10212     jam();
10213     alterTabPtr.p->m_blockNo[0] = DBLQH;
10214     alterTable_toCommitComplete(signal, op_ptr,
10215                                 AlterTabReq::AlterTableSumaFilter);
10216     return;
10217   }
10218   sendTransConf(signal, op_ptr);
10219 }
10220 
10221 // AlterTable: ABORT
10222 
10223 void
alterTable_abortParse(Signal * signal,SchemaOpPtr op_ptr)10224 Dbdict::alterTable_abortParse(Signal* signal, SchemaOpPtr op_ptr)
10225 {
10226   D("alterTable_abortParse" << *op_ptr.p);
10227 
10228   AlterTableRecPtr alterTabPtr;
10229   getOpRec(op_ptr, alterTabPtr);
10230   const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
10231 
10232   if (AlterTableReq::getReorgSubOp(impl_req->changeMask))
10233   {
10234     jam();
10235     sendTransConf(signal, op_ptr);
10236     return;
10237   }
10238 
10239   if (alterTabPtr.p->m_newTablePtrI != RNIL) {
10240     jam();
10241     // release the temporary work table
10242 
10243     {
10244       // Remark object as free
10245       SchemaFile::TableEntry *
10246         objEntry = getTableEntry(alterTabPtr.p->m_newTable_realObjectId);
10247       objEntry->m_tableType = DictTabInfo::UndefTableType;
10248       objEntry->m_tableState = SchemaFile::SF_UNUSED;
10249       objEntry->m_transId = 0;
10250     }
10251 
10252     releaseTableObject(alterTabPtr.p->m_newTablePtrI, false);
10253     alterTabPtr.p->m_newTablePtrI = RNIL;
10254   }
10255 
10256   sendTransConf(signal, op_ptr);
10257 }
10258 
10259 void
alterTable_abortPrepare(Signal * signal,SchemaOpPtr op_ptr)10260 Dbdict::alterTable_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
10261 {
10262   D("alterTable_abortPrepare" << *op_ptr.p);
10263 
10264   AlterTableRecPtr alterTabPtr;
10265   getOpRec(op_ptr, alterTabPtr);
10266   const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
10267 
10268   if (AlterTableReq::getReorgSubOp(impl_req->changeMask))
10269   {
10270     jam();
10271 
10272     /**
10273      * Does nothing...
10274      */
10275     sendTransConf(signal, op_ptr);
10276     return;
10277   }
10278 
10279   if (alterTabPtr.p->m_blockIndex > 0)
10280   {
10281     jam();
10282     /*
10283      * Local blocks have only updated table version.
10284      * Reset it to original in reverse block order.
10285      */
10286     alterTable_abortToLocal(signal, op_ptr);
10287     return;
10288   }
10289   else
10290   {
10291     jam();
10292     sendTransConf(signal, op_ptr);
10293     return;
10294   }
10295 }
10296 
10297 void
alterTable_abortToLocal(Signal * signal,SchemaOpPtr op_ptr)10298 Dbdict::alterTable_abortToLocal(Signal* signal, SchemaOpPtr op_ptr)
10299 {
10300   AlterTableRecPtr alterTabPtr;
10301   getOpRec(op_ptr, alterTabPtr);
10302   const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
10303 
10304   const Uint32 blockCount = alterTabPtr.p->m_blockIndex;
10305   ndbrequire(blockCount != 0 && blockCount <= AlterTableRec::BlockCount);
10306   const Uint32 blockIndex = blockCount - 1;
10307   const Uint32 blockNo = alterTabPtr.p->m_blockNo[blockIndex];
10308 
10309   D("alterTable_abortToLocal" << V(blockIndex) << V(getBlockName(blockNo)));
10310 
10311   Uint32 connectPtr = RNIL;
10312   switch(blockNo){
10313   case DBLQH:
10314     jam();
10315     connectPtr = alterTabPtr.p->m_lqhFragPtr;
10316     break;
10317   case DBDIH:
10318     jam();
10319     connectPtr = alterTabPtr.p->m_dihAddFragPtr;
10320     break;
10321   }
10322 
10323   AlterTabReq* req = (AlterTabReq*)signal->getDataPtrSend();
10324   req->senderRef = reference();
10325   req->senderData = op_ptr.p->op_key;
10326   req->requestType = AlterTabReq::AlterTableRevert;
10327   req->tableId = impl_req->tableId;
10328   req->tableVersion = impl_req->tableVersion;
10329   req->newTableVersion = impl_req->newTableVersion;
10330   req->gci = impl_req->gci;
10331   req->changeMask = impl_req->changeMask;
10332   req->connectPtr = connectPtr;
10333   req->noOfNewAttr = impl_req->noOfNewAttr;
10334   req->newNoOfCharsets = impl_req->newNoOfCharsets;
10335   req->newNoOfKeyAttrs = impl_req->newNoOfKeyAttrs;
10336 
10337   Callback c = {
10338     safe_cast(&Dbdict::alterTable_abortFromLocal),
10339     op_ptr.p->op_key
10340   };
10341   op_ptr.p->m_callback = c;
10342 
10343   BlockReference blockRef = numberToRef(blockNo, getOwnNodeId());
10344   sendSignal(blockRef, GSN_ALTER_TAB_REQ, signal,
10345              AlterTabReq::SignalLength, JBB);
10346 }
10347 
10348 void
alterTable_abortFromLocal(Signal * signal,Uint32 op_key,Uint32 ret)10349 Dbdict::alterTable_abortFromLocal(Signal*signal, Uint32 op_key, Uint32 ret)
10350 {
10351   SchemaOpPtr op_ptr;
10352   AlterTableRecPtr alterTabPtr;
10353   findSchemaOp(op_ptr, alterTabPtr, op_key);
10354   ndbrequire(!op_ptr.isNull());
10355 
10356   const Uint32 blockCount = alterTabPtr.p->m_blockIndex;
10357   ndbrequire(blockCount != 0 && blockCount <= AlterTableRec::BlockCount);
10358   const Uint32 blockIndex = blockCount - 1;
10359   alterTabPtr.p->m_blockIndex = blockIndex;
10360 
10361   ndbrequire(ret == 0); // abort is not allowed to fail
10362 
10363   if (blockIndex > 0)
10364   {
10365     jam();
10366     alterTable_abortToLocal(signal, op_ptr);
10367     return;
10368   }
10369   else
10370   {
10371     jam();
10372     sendTransConf(signal, op_ptr);
10373   }
10374 }
10375 
10376 // AlterTable: MISC
10377 
10378 void
execALTER_TAB_CONF(Signal * signal)10379 Dbdict::execALTER_TAB_CONF(Signal* signal)
10380 {
10381   jamEntry();
10382   const AlterTabConf* conf = (const AlterTabConf*)signal->getDataPtr();
10383   ndbrequire(refToNode(conf->senderRef) == getOwnNodeId());
10384   handleDictConf(signal, conf);
10385 }
10386 
10387 void
execALTER_TAB_REF(Signal * signal)10388 Dbdict::execALTER_TAB_REF(Signal* signal)
10389 {
10390   jamEntry();
10391   const AlterTabRef* ref = (const AlterTabRef*)signal->getDataPtr();
10392   ndbrequire(refToNode(ref->senderRef) == getOwnNodeId());
10393   handleDictRef(signal, ref);
10394 }
10395 
10396 void
execALTER_TABLE_CONF(Signal * signal)10397 Dbdict::execALTER_TABLE_CONF(Signal* signal)
10398 {
10399   jamEntry();
10400   const AlterTableConf* conf = (const AlterTableConf*)signal->getDataPtr();
10401   ndbrequire(refToNode(conf->senderRef) == getOwnNodeId());
10402   handleDictConf(signal, conf);
10403 }
10404 
10405 void
execALTER_TABLE_REF(Signal * signal)10406 Dbdict::execALTER_TABLE_REF(Signal* signal)
10407 {
10408   jamEntry();
10409   const AlterTableRef* ref = (const AlterTableRef*)signal->getDataPtr();
10410   ndbrequire(refToNode(ref->senderRef) == getOwnNodeId());
10411   handleDictRef(signal, ref);
10412 }
10413 
10414 // AlterTable: END
10415 
10416 /* **************************************************************** */
10417 /* ---------------------------------------------------------------- */
10418 /* MODULE:          EXTERNAL INTERFACE TO DATA -------------------- */
10419 /* ---------------------------------------------------------------- */
10420 /*                                                                  */
10421 /* This module contains the code that is used by other modules to.  */
10422 /* access the data within DBDICT.                                   */
10423 /* ---------------------------------------------------------------- */
10424 /* **************************************************************** */
10425 
execGET_TABLEDID_REQ(Signal * signal)10426 void Dbdict::execGET_TABLEDID_REQ(Signal * signal)
10427 {
10428   jamEntry();
10429   ndbrequire(signal->getNoOfSections() == 1);
10430   GetTableIdReq const * req = (GetTableIdReq *)signal->getDataPtr();
10431   Uint32 senderData = req->senderData;
10432   Uint32 senderRef = req->senderRef;
10433   Uint32 len = req->len;
10434 
10435   if(len>PATH_MAX)
10436   {
10437     jam();
10438     sendGET_TABLEID_REF((Signal*)signal,
10439 			(GetTableIdReq *)req,
10440 			GetTableIdRef::TableNameTooLong);
10441     return;
10442   }
10443 
10444   char tableName[PATH_MAX];
10445   SectionHandle handle(this, signal);
10446   SegmentedSectionPtr ssPtr;
10447   handle.getSection(ssPtr,GetTableIdReq::TABLE_NAME);
10448   copy((Uint32*)tableName, ssPtr);
10449   releaseSections(handle);
10450 
10451   DictObject * obj_ptr_p = get_object(tableName, len);
10452   if(obj_ptr_p == 0 || !DictTabInfo::isTable(obj_ptr_p->m_type)){
10453     jam();
10454     sendGET_TABLEID_REF(signal,
10455 			(GetTableIdReq *)req,
10456 			GetTableIdRef::TableNotDefined);
10457     return;
10458   }
10459 
10460   TableRecordPtr tablePtr;
10461   c_tableRecordPool_.getPtr(tablePtr, obj_ptr_p->m_object_ptr_i);
10462 
10463   GetTableIdConf * conf = (GetTableIdConf *)req;
10464   conf->tableId = tablePtr.p->tableId;
10465   conf->schemaVersion = tablePtr.p->tableVersion;
10466   conf->senderData = senderData;
10467   sendSignal(senderRef, GSN_GET_TABLEID_CONF, signal,
10468 	     GetTableIdConf::SignalLength, JBB);
10469 }
10470 
10471 
sendGET_TABLEID_REF(Signal * signal,GetTableIdReq * req,GetTableIdRef::ErrorCode errorCode)10472 void Dbdict::sendGET_TABLEID_REF(Signal* signal,
10473 				 GetTableIdReq * req,
10474 				 GetTableIdRef::ErrorCode errorCode)
10475 {
10476   GetTableIdRef * const ref = (GetTableIdRef *)req;
10477   /**
10478    * The format of GetTabInfo Req/Ref is the same
10479    */
10480   BlockReference retRef = req->senderRef;
10481   ref->err = errorCode;
10482   sendSignal(retRef, GSN_GET_TABLEID_REF, signal,
10483 	     GetTableIdRef::SignalLength, JBB);
10484 }
10485 
10486 /* ---------------------------------------------------------------- */
10487 // Get a full table description.
10488 /* ---------------------------------------------------------------- */
execGET_TABINFOREQ(Signal * signal)10489 void Dbdict::execGET_TABINFOREQ(Signal* signal)
10490 {
10491   jamEntry();
10492   if(!assembleFragments(signal))
10493   {
10494     return;
10495   }
10496 
10497   /**
10498    * First stage response / queueing handled here
10499    * Actual processing is done in doGET_TABINFOREQ()
10500    */
10501 
10502   GetTabInfoReq * const req = (GetTabInfoReq *)&signal->theData[0];
10503 
10504   if (ERROR_INSERTED(6215) &&
10505       (signal->senderBlockRef() != reference()))
10506   {
10507     jam();
10508     // API tries 100 times and (80/100)^100 is quite small..
10509     if (rand() % 100 >= 20)
10510     {
10511       jam();
10512       SectionHandle handle(this, signal);
10513       releaseSections(handle);
10514       sendGET_TABINFOREF(signal, req, GetTabInfoRef::Busy, __LINE__);
10515       return;
10516     }
10517     // no CLEAR_ERROR_INSERT_VALUE
10518   }
10519 
10520   const bool testRef = (ERROR_INSERTED(6026) &&
10521                         refToMain(signal->senderBlockRef()) == DBDICT &&
10522                         (signal->senderBlockRef() != reference()));
10523   if (testRef)
10524   {
10525     ndbout_c("DICT : ERROR_INSERT(6026) simulating old internal "
10526              "GET_TABINFOREF");
10527     CLEAR_ERROR_INSERT_VALUE;
10528     SectionHandle handle(this, signal);
10529     releaseSections(handle);
10530     sendGET_TABINFOREF(signal, req, GetTabInfoRef::Busy, __LINE__);
10531     return;
10532   }
10533 
10534   if (c_retrieveRecord.busyState)
10535   {
10536     jam();
10537     NodeInfo sendersNI = getNodeInfo(refToNode(req->senderRef));
10538     bool internalReq = (sendersNI.m_type == NodeInfo::DB);
10539 
10540     /* Queue request
10541      * Will be processed later when current requests + queue are completed
10542      */
10543     if (!c_gettabinforeq_q.tryEnqReq(internalReq,
10544                                      signal))
10545     {
10546       jam();
10547       /**
10548        * Enqueue failure resulting in Busy signal only allowed for
10549        * external requests
10550        */
10551       ndbrequire(!internalReq);
10552 
10553       SectionHandle handle(this, signal);
10554       releaseSections(handle);
10555 
10556       sendGET_TABINFOREF(signal, req, GetTabInfoRef::Busy, __LINE__);
10557     }
10558 
10559     return;
10560   }
10561 
10562   /* Not busy, cannot be anything queued... */
10563   ndbrequire(c_gettabinforeq_q.isEmpty());
10564 
10565   doGET_TABINFOREQ(signal);
10566 } // execGET_TABINFOREQ()
10567 
10568 void
doGET_TABINFOREQ(Signal * signal)10569 Dbdict::doGET_TABINFOREQ(Signal* signal)
10570 {
10571   jam();
10572   GetTabInfoReq * const req = (GetTabInfoReq *)&signal->theData[0];
10573 
10574   SectionHandle handle(this, signal);
10575 
10576   if(ERROR_INSERTED(6216))
10577   {
10578     ndbout_c("Delaying GSN_GET_TABINFOREQ\n");
10579     sendSignalWithDelay(reference(), GSN_GET_TABINFOREQ, signal, 10000,
10580                        signal->length(),
10581                        &handle);
10582     return;
10583   }
10584 
10585   const bool useLongSig = (req->requestType & GetTabInfoReq::LongSignalConf);
10586   const bool byName = (req->requestType & GetTabInfoReq::RequestByName);
10587   const Uint32 transId = req->schemaTransId;
10588 
10589   Uint32 obj_id = RNIL;
10590   if (byName) {
10591     jam();
10592     ndbrequire(handle.m_cnt == 1);
10593     const Uint32 len = req->tableNameLen;
10594 
10595     if(len > PATH_MAX){
10596       jam();
10597       releaseSections(handle);
10598       sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNameTooLong, __LINE__);
10599       return;
10600     }
10601 
10602     Uint32 tableName[(PATH_MAX + 3) / 4];
10603     SegmentedSectionPtr ssPtr;
10604     handle.getSection(ssPtr,GetTabInfoReq::TABLE_NAME);
10605     copy(tableName, ssPtr);
10606 
10607     DictObject * old_ptr_p = get_object((char*)tableName, len);
10608     if(old_ptr_p)
10609       obj_id = old_ptr_p->m_id;
10610   } else {
10611     jam();
10612     obj_id = req->tableId;
10613   }
10614   releaseSections(handle);
10615 
10616   SchemaFile::TableEntry *objEntry = 0;
10617   if(obj_id != RNIL)
10618   {
10619     XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
10620     objEntry = getTableEntry(xsf, obj_id);
10621   }
10622 
10623   // The table seached for was not found
10624   if(objEntry == 0)
10625   {
10626     jam();
10627     sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNotDefined, __LINE__);
10628     return;
10629   }//if
10630 
10631   // If istable/index, allow ADD_STARTED (not to ref)
10632 
10633   D("doGET_TABINFOREQ" << V(transId) << " " << *objEntry);
10634 
10635   if (transId != 0 && transId == objEntry->m_transId)
10636   {
10637     jam();
10638     // see own trans always
10639   }
10640   else if (refToBlock(req->senderRef) != DBUTIL && /** XXX cheat */
10641            refToBlock(req->senderRef) != SUMA)
10642   {
10643     jam();
10644     Uint32 err;
10645     if ((err = check_read_obj(objEntry)))
10646     {
10647       jam();
10648       // cannot see another uncommitted trans
10649       sendGET_TABINFOREF(signal, req, (GetTabInfoRef::ErrorCode)err, __LINE__);
10650       return;
10651     }
10652   }
10653 
10654   /**
10655    * From this point we agree to process this request
10656    * and are 'busy' w.r.t. GETTABINFOREQ.
10657    * Further incoming GETTABINFOREQ signals will
10658    * be queued or rejected.
10659    * When we finish processing this one, we must
10660    * start any queued req.
10661    */
10662 
10663   c_retrieveRecord.busyState = true;
10664   c_retrieveRecord.blockRef = req->senderRef;
10665   c_retrieveRecord.m_senderData = req->senderData;
10666   c_retrieveRecord.tableId = obj_id;
10667   c_retrieveRecord.currentSent = 0;
10668   c_retrieveRecord.m_useLongSig = useLongSig;
10669   c_retrieveRecord.m_table_type = objEntry->m_tableType;
10670   c_retrieveRecord.schemaTransId = transId;
10671   c_retrieveRecord.requestType = req->requestType;
10672   c_packTable.m_state = PackTable::PTS_GET_TAB;
10673 
10674   Uint32 len = 4;
10675   if(objEntry->m_tableType == DictTabInfo::Datafile)
10676   {
10677     jam();
10678 
10679     if (objEntry->m_tableState != SchemaFile::SF_CREATE)
10680     {
10681       jam();
10682 
10683       GetTabInfoReq *req= (GetTabInfoReq*)signal->getDataPtrSend();
10684       req->senderData= c_retrieveRecord.retrievePage;
10685       req->senderRef= reference();
10686       req->requestType= GetTabInfoReq::RequestById;
10687       req->tableId= obj_id;
10688       req->schemaTransId = 0;
10689 
10690       sendSignal(TSMAN_REF, GSN_GET_TABINFOREQ, signal,
10691                  GetTabInfoReq::SignalLength, JBB);
10692       return;
10693     }
10694     else
10695     {
10696       jam();
10697       /**
10698        * Obj is being created, return 0 free extents
10699        */
10700       len = 5;
10701       signal->theData[4] = 0;
10702     }
10703   }
10704   else if(objEntry->m_tableType == DictTabInfo::LogfileGroup)
10705   {
10706     jam();
10707     if (objEntry->m_tableState != SchemaFile::SF_CREATE)
10708     {
10709       jam();
10710       GetTabInfoReq *req= (GetTabInfoReq*)signal->getDataPtrSend();
10711       req->senderData= c_retrieveRecord.retrievePage;
10712       req->senderRef= reference();
10713       req->requestType= GetTabInfoReq::RequestById;
10714       req->tableId= obj_id;
10715       req->schemaTransId = 0;
10716 
10717       sendSignal(LGMAN_REF, GSN_GET_TABINFOREQ, signal,
10718                  GetTabInfoReq::SignalLength, JBB);
10719       return;
10720     }
10721     else
10722     {
10723       jam();
10724       /**
10725        * Obj is being created, return 0 free space
10726        */
10727       len = 6;
10728       signal->theData[4] = 0;
10729       signal->theData[5] = 0;
10730     }
10731   }
10732 
10733   jam();
10734   signal->theData[0] = ZPACK_TABLE_INTO_PAGES;
10735   signal->theData[1] = obj_id;
10736   signal->theData[2] = objEntry->m_tableType;
10737   signal->theData[3] = c_retrieveRecord.retrievePage;
10738   sendSignal(reference(), GSN_CONTINUEB, signal, len, JBB);
10739 }//doGET_TABINFOREQ()
10740 
sendGetTabResponse(Signal * signal)10741 void Dbdict::sendGetTabResponse(Signal* signal)
10742 {
10743   PageRecordPtr pagePtr;
10744   DictTabInfo * const conf = (DictTabInfo *)&signal->theData[0];
10745   conf->senderRef   = reference();
10746   conf->senderData  = c_retrieveRecord.m_senderData;
10747   conf->requestType = DictTabInfo::GetTabInfoConf;
10748   conf->totalLen    = c_retrieveRecord.retrievedNoOfWords;
10749 
10750   c_pageRecordArray.getPtr(pagePtr, c_retrieveRecord.retrievePage);
10751   Uint32* pagePointer = (Uint32*)&pagePtr.p->word[0] + ZPAGE_HEADER_SIZE;
10752 
10753   if(c_retrieveRecord.m_useLongSig){
10754     jam();
10755     GetTabInfoConf* conf = (GetTabInfoConf*)signal->getDataPtr();
10756     conf->gci = 0;
10757     conf->tableId = c_retrieveRecord.tableId;
10758     conf->senderData = c_retrieveRecord.m_senderData;
10759     conf->totalLen = c_retrieveRecord.retrievedNoOfWords;
10760     conf->tableType = c_retrieveRecord.m_table_type;
10761 
10762     Callback c = { safe_cast(&Dbdict::initRetrieveRecord), 0 };
10763     LinearSectionPtr ptr[3];
10764     ptr[0].p = pagePointer;
10765     ptr[0].sz = c_retrieveRecord.retrievedNoOfWords;
10766     sendFragmentedSignal(c_retrieveRecord.blockRef,
10767 			 GSN_GET_TABINFO_CONF,
10768 			 signal,
10769 			 GetTabInfoConf::SignalLength,
10770 			 JBB,
10771 			 ptr,
10772 			 1,
10773 			 c);
10774     return;
10775   }
10776 
10777   ndbrequire(false);
10778 }//sendGetTabResponse()
10779 
sendGET_TABINFOREF(Signal * signal,GetTabInfoReq * req,GetTabInfoRef::ErrorCode errorCode,Uint32 errorLine)10780 void Dbdict::sendGET_TABINFOREF(Signal* signal,
10781 				GetTabInfoReq * req,
10782 				GetTabInfoRef::ErrorCode errorCode,
10783                                 Uint32 errorLine)
10784 {
10785   jamEntry();
10786   const GetTabInfoReq req_copy = *req;
10787   GetTabInfoRef * const ref = (GetTabInfoRef *)&signal->theData[0];
10788 
10789   ref->senderData = req_copy.senderData;
10790   ref->senderRef = reference();
10791   ref->requestType = req_copy.requestType;
10792   ref->tableId = req_copy.tableId;
10793   ref->schemaTransId = req_copy.schemaTransId;
10794   ref->errorCode = (Uint32)errorCode;
10795   ref->errorLine = errorLine;
10796 
10797   BlockReference retRef = req_copy.senderRef;
10798   sendSignal(retRef, GSN_GET_TABINFOREF, signal,
10799              GetTabInfoRef::SignalLength, JBB);
10800 }
10801 
10802 void
execLIST_TABLES_REQ(Signal * signal)10803 Dbdict::execLIST_TABLES_REQ(Signal* signal)
10804 {
10805   jamEntry();
10806   ListTablesReq * req = (ListTablesReq*)signal->getDataPtr();
10807 
10808   Uint32 senderRef  = req->senderRef;
10809   Uint32 receiverVersion = getNodeInfo(refToNode(senderRef)).m_version;
10810 
10811   if (ndbd_LIST_TABLES_CONF_long_signal(receiverVersion))
10812     sendLIST_TABLES_CONF(signal, req);
10813   else
10814     sendOLD_LIST_TABLES_CONF(signal, req);
10815 }
10816 
sendOLD_LIST_TABLES_CONF(Signal * signal,ListTablesReq * req)10817 void Dbdict::sendOLD_LIST_TABLES_CONF(Signal* signal, ListTablesReq* req)
10818 {
10819   Uint32 senderRef  = req->senderRef;
10820   Uint32 senderData = req->senderData;
10821   // save req flags
10822   const Uint32 reqTableId = req->oldGetTableId();
10823   const Uint32 reqTableType = req->oldGetTableType();
10824   const bool reqListNames = req->getListNames();
10825   const bool reqListIndexes = req->getListIndexes();
10826   XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
10827   // init the confs
10828   OldListTablesConf * conf = (OldListTablesConf *)signal->getDataPtrSend();
10829   conf->senderData = senderData;
10830   conf->counter = 0;
10831   Uint32 pos = 0;
10832 
10833   DictObjectName_hash::Iterator iter;
10834   bool ok = c_obj_name_hash.first(iter);
10835   for (; ok; ok = c_obj_name_hash.next(iter)){
10836     Uint32 type = iter.curr.p->m_type;
10837     if ((reqTableType != (Uint32)0) && (reqTableType != type))
10838       continue;
10839 
10840     if (reqListIndexes && !DictTabInfo::isIndex(type))
10841       continue;
10842 
10843     TableRecordPtr tablePtr;
10844     if (DictTabInfo::isTable(type) || DictTabInfo::isIndex(type)){
10845       c_tableRecordPool_.getPtr(tablePtr, iter.curr.p->m_object_ptr_i);
10846 
10847       if(reqListIndexes && (reqTableId != tablePtr.p->primaryTableId))
10848 	continue;
10849 
10850       conf->tableData[pos] = 0;
10851       conf->setTableId(pos, iter.curr.p->m_id); // id
10852       conf->setTableType(pos, type); // type
10853       // state
10854 
10855       if(DictTabInfo::isTable(type))
10856       {
10857         SchemaFile::TableEntry * te = getTableEntry(xsf, iter.curr.p->m_id);
10858         switch(te->m_tableState){
10859         case SchemaFile::SF_CREATE:
10860           jam();
10861           conf->setTableState(pos, DictTabInfo::StateBuilding);
10862           break;
10863         case SchemaFile::SF_ALTER:
10864           jam();
10865           conf->setTableState(pos, DictTabInfo::StateOnline);
10866           break;
10867         case SchemaFile::SF_DROP:
10868           jam();
10869 	  conf->setTableState(pos, DictTabInfo::StateDropping);
10870           break;
10871         case SchemaFile::SF_IN_USE:
10872         {
10873           if (tablePtr.p->m_read_locked)
10874           {
10875             jam();
10876             conf->setTableState(pos, DictTabInfo::StateBackup);
10877           }
10878           else
10879           {
10880             jam();
10881             conf->setTableState(pos, DictTabInfo::StateOnline);
10882           }
10883 	  break;
10884         }
10885 	default:
10886 	  conf->setTableState(pos, DictTabInfo::StateBroken);
10887 	  break;
10888 	}
10889       }
10890       if (tablePtr.p->isIndex()) {
10891 	switch (tablePtr.p->indexState) {
10892 	case TableRecord::IS_OFFLINE:
10893 	  conf->setTableState(pos, DictTabInfo::StateOffline);
10894 	  break;
10895 	case TableRecord::IS_BUILDING:
10896 	  conf->setTableState(pos, DictTabInfo::StateBuilding);
10897 	  break;
10898 	case TableRecord::IS_DROPPING:
10899 	  conf->setTableState(pos, DictTabInfo::StateDropping);
10900 	  break;
10901 	case TableRecord::IS_ONLINE:
10902 	  conf->setTableState(pos, DictTabInfo::StateOnline);
10903 	  break;
10904 	default:
10905 	  conf->setTableState(pos, DictTabInfo::StateBroken);
10906 	  break;
10907 	}
10908       }
10909       // Logging status
10910       if (! (tablePtr.p->m_bits & TableRecord::TR_Logged)) {
10911 	conf->setTableStore(pos, DictTabInfo::StoreNotLogged);
10912       } else {
10913 	conf->setTableStore(pos, DictTabInfo::StorePermanent);
10914       }
10915       // Temporary status
10916       if (tablePtr.p->m_bits & TableRecord::TR_Temporary) {
10917 	conf->setTableTemp(pos, NDB_TEMP_TAB_TEMPORARY);
10918       } else {
10919 	conf->setTableTemp(pos, NDB_TEMP_TAB_PERMANENT);
10920       }
10921       pos++;
10922     }
10923     if(DictTabInfo::isTrigger(type)){
10924       TriggerRecordPtr triggerPtr;
10925       bool ok = find_object(triggerPtr, iter.curr.p->m_id);
10926       conf->tableData[pos] = 0;
10927       conf->setTableId(pos, iter.curr.p->m_id);
10928       conf->setTableType(pos, type);
10929       if (!ok)
10930       {
10931         conf->setTableState(pos, DictTabInfo::StateBroken);
10932       }
10933       else
10934       {
10935         switch (triggerPtr.p->triggerState) {
10936         case TriggerRecord::TS_DEFINING:
10937           conf->setTableState(pos, DictTabInfo::StateBuilding);
10938           break;
10939         case TriggerRecord::TS_OFFLINE:
10940           conf->setTableState(pos, DictTabInfo::StateOffline);
10941           break;
10942         case TriggerRecord::TS_ONLINE:
10943           conf->setTableState(pos, DictTabInfo::StateOnline);
10944           break;
10945         default:
10946           conf->setTableState(pos, DictTabInfo::StateBroken);
10947           break;
10948         }
10949       }
10950       conf->setTableStore(pos, DictTabInfo::StoreNotLogged);
10951       pos++;
10952     }
10953     if (DictTabInfo::isFilegroup(type)){
10954       jam();
10955       conf->tableData[pos] = 0;
10956       conf->setTableId(pos, iter.curr.p->m_id);
10957       conf->setTableType(pos, type); // type
10958       conf->setTableState(pos, DictTabInfo::StateOnline);  // XXX todo
10959       pos++;
10960     }
10961     if (DictTabInfo::isFile(type)){
10962       jam();
10963       conf->tableData[pos] = 0;
10964       conf->setTableId(pos, iter.curr.p->m_id);
10965       conf->setTableType(pos, type); // type
10966       conf->setTableState(pos, DictTabInfo::StateOnline); // XXX todo
10967       pos++;
10968     }
10969 
10970     if (pos >= OldListTablesConf::DataLength) {
10971       sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
10972 		 OldListTablesConf::SignalLength, JBB);
10973       conf->counter++;
10974       pos = 0;
10975     }
10976 
10977     if (! reqListNames)
10978       continue;
10979 
10980     LocalRope name(c_rope_pool, iter.curr.p->m_name);
10981     const Uint32 size = name.size();
10982     conf->tableData[pos] = size;
10983     pos++;
10984     if (pos >= OldListTablesConf::DataLength) {
10985       sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
10986 		 OldListTablesConf::SignalLength, JBB);
10987       conf->counter++;
10988       pos = 0;
10989     }
10990     Uint32 i = 0;
10991     char tmp[PATH_MAX];
10992     name.copy(tmp);
10993     while (i < size) {
10994       char* p = (char*)&conf->tableData[pos];
10995       for (Uint32 j = 0; j < 4; j++) {
10996 	if (i < size)
10997 	  *p++ = tmp[i++];
10998 	else
10999 	  *p++ = 0;
11000       }
11001       pos++;
11002       if (pos >= OldListTablesConf::DataLength) {
11003 	sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
11004 		   OldListTablesConf::SignalLength, JBB);
11005 	conf->counter++;
11006 	pos = 0;
11007       }
11008     }
11009   }
11010   // last signal must have less than max length
11011   sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
11012 	     OldListTablesConf::HeaderLength + pos, JBB);
11013 }
11014 
buildListTablesData(const DictObject & dictObject,Uint32 parentTableId,ListTablesData & ltd,Uint32 & objectVersion,Uint32 & parentObjectType,Uint32 & parentObjectId)11015 bool Dbdict::buildListTablesData(const DictObject& dictObject,
11016                                  Uint32 parentTableId,
11017                                  ListTablesData& ltd,
11018                                  Uint32& objectVersion,
11019                                  Uint32& parentObjectType,
11020                                  Uint32& parentObjectId)
11021 {
11022   jam();
11023   const XSchemaFile* const xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
11024   const Uint32 type = dictObject.m_type;
11025 
11026   objectVersion = 0;
11027   parentObjectType = 0;
11028   parentObjectId = 0;
11029 
11030   if (DictTabInfo::isTable(type) || DictTabInfo::isIndex(type))
11031   {
11032     jam();
11033     TableRecordPtr tablePtr;
11034     c_tableRecordPool_.getPtr(tablePtr, dictObject.m_object_ptr_i);
11035 
11036     if (parentTableId != RNIL && parentTableId != tablePtr.p->primaryTableId)
11037     {
11038       jam();
11039       return false;
11040     }
11041 
11042     ltd.requestData = 0; // clear
11043     ltd.setTableId(dictObject.m_id); // id
11044     ltd.setTableType(type); // type
11045     objectVersion = tablePtr.p->tableVersion;
11046 
11047     // state
11048 
11049     if(DictTabInfo::isTable(type)){
11050       ndbassert(!tablePtr.p->isIndex());
11051       const SchemaFile::TableEntry* const te
11052         = getTableEntry(xsf, dictObject.m_id);
11053       switch(te->m_tableState){
11054       case SchemaFile::SF_CREATE:
11055         jam();
11056         ltd.setTableState(DictTabInfo::StateBuilding);
11057         break;
11058       case SchemaFile::SF_ALTER:
11059         jam();
11060         ltd.setTableState(DictTabInfo::StateOnline);
11061         break;
11062       case SchemaFile::SF_DROP:
11063         jam();
11064         ltd.setTableState(DictTabInfo::StateDropping);
11065         break;
11066       case SchemaFile::SF_IN_USE:
11067         {
11068           if (tablePtr.p->m_read_locked)
11069           {
11070             jam();
11071             ltd.setTableState(DictTabInfo::StateBackup);
11072           }
11073           else
11074           {
11075             jam();
11076             ltd.setTableState(DictTabInfo::StateOnline);
11077           }
11078 	  break;
11079         }
11080       default:
11081         jam();
11082         ltd.setTableState(DictTabInfo::StateBroken);
11083         break;
11084       }
11085       /* Don't know about 'parent' objects for normal tables,
11086        * have no visibility of blobs at this layer
11087        */
11088     }
11089     else
11090     {
11091       ndbassert(tablePtr.p->isIndex());
11092 
11093       switch (tablePtr.p->indexState) {
11094       case TableRecord::IS_OFFLINE:
11095         jam();
11096         ltd.setTableState(DictTabInfo::StateOffline);
11097         break;
11098       case TableRecord::IS_BUILDING:
11099         jam();
11100         ltd.setTableState(DictTabInfo::StateBuilding);
11101         break;
11102       case TableRecord::IS_DROPPING:
11103         jam();
11104         ltd.setTableState(DictTabInfo::StateDropping);
11105         break;
11106       case TableRecord::IS_ONLINE:
11107         jam();
11108         ltd.setTableState(DictTabInfo::StateOnline);
11109         break;
11110       default:
11111         jam();
11112         ltd.setTableState(DictTabInfo::StateBroken);
11113         break;
11114       }
11115 
11116       ndbrequire(tablePtr.p->primaryTableId != RNIL);
11117       TableRecordPtr primTablePtr;
11118       ndbrequire(find_object(primTablePtr, tablePtr.p->primaryTableId));
11119       parentObjectType = primTablePtr.p->tableType;
11120       parentObjectId = primTablePtr.p->tableId;
11121     }
11122     // Logging status
11123     if (! (tablePtr.p->m_bits & TableRecord::TR_Logged)) {
11124       jam();
11125       ltd.setTableStore(DictTabInfo::StoreNotLogged);
11126     } else {
11127       ltd.setTableStore(DictTabInfo::StorePermanent);
11128     }
11129     // Temporary status
11130     if (tablePtr.p->m_bits & TableRecord::TR_Temporary) {
11131       jam();
11132       ltd.setTableTemp(NDB_TEMP_TAB_TEMPORARY);
11133     } else {
11134       ltd.setTableTemp(NDB_TEMP_TAB_PERMANENT);
11135     }
11136   }
11137   if(DictTabInfo::isTrigger(type)){
11138     jam();
11139     TriggerRecordPtr triggerPtr;
11140     const bool ok = find_object(triggerPtr, dictObject.m_id);
11141 
11142     if (parentTableId != RNIL &&
11143         parentTableId != triggerPtr.p->tableId)
11144     {
11145       jam();
11146       return false;
11147     }
11148 
11149     ltd.requestData = 0;
11150     ltd.setTableId(dictObject.m_id);
11151     ltd.setTableType(type);
11152     if (!ok)
11153     {
11154       jam();
11155       ltd.setTableState(DictTabInfo::StateBroken);
11156     }
11157     else
11158     {
11159       switch (triggerPtr.p->triggerState) {
11160       case TriggerRecord::TS_DEFINING:
11161         jam();
11162         ltd.setTableState(DictTabInfo::StateBuilding);
11163         break;
11164       case TriggerRecord::TS_OFFLINE:
11165         jam();
11166         ltd.setTableState(DictTabInfo::StateOffline);
11167         break;
11168       case TriggerRecord::TS_ONLINE:
11169         jam();
11170         ltd.setTableState(DictTabInfo::StateOnline);
11171         break;
11172       default:
11173         jam();
11174         ltd.setTableState(DictTabInfo::StateBroken);
11175         break;
11176       }
11177     }
11178     ltd.setTableStore(DictTabInfo::StoreNotLogged);
11179 
11180     objectVersion = 1;  /* No object version for triggers */
11181 
11182     switch (TriggerInfo::getTriggerType(triggerPtr.p->triggerInfo))
11183     {
11184     case TriggerType::FK_PARENT:
11185     case TriggerType::FK_CHILD:
11186       {
11187         // Foreign key triggers are children of the FK definition.
11188         jam();
11189         Ptr<ForeignKeyRec> fk_ptr;
11190         ndbrequire(find_object(fk_ptr, triggerPtr.p->indexId));
11191         parentObjectType = DictTabInfo::ForeignKey;
11192         parentObjectId = fk_ptr.p->m_fk_id;
11193       }
11194       break;
11195 
11196     default:
11197       {
11198         jam();
11199         TableRecordPtr myTabPtr;
11200         const Uint32 parentId = (triggerPtr.p->indexId == RNIL ?
11201                                  triggerPtr.p->tableId:
11202                                  triggerPtr.p->indexId);
11203         ndbrequire(find_object(myTabPtr, parentId));
11204         parentObjectType = myTabPtr.p->tableType;
11205         parentObjectId = myTabPtr.p->tableId;
11206       }
11207       break;
11208     }
11209   } // if(DictTabInfo::isTrigger(type))
11210   if (DictTabInfo::isFilegroup(type)){
11211     jam();
11212 
11213     if (parentTableId != RNIL)
11214       return false;
11215 
11216     ltd.requestData = 0;
11217     ltd.setTableId(dictObject.m_id);
11218     ltd.setTableType(type); // type
11219     ltd.setTableState(DictTabInfo::StateOnline);
11220 
11221     FilegroupPtr fg_ptr;
11222     ndbrequire(find_object(fg_ptr, dictObject.m_id));
11223     objectVersion = fg_ptr.p->m_version;
11224   }
11225   if (DictTabInfo::isFile(type)){
11226     jam();
11227 
11228     if (parentTableId != RNIL)
11229       return false;
11230 
11231     ltd.requestData = 0;
11232     ltd.setTableId(dictObject.m_id);
11233     ltd.setTableType(type); // type
11234     ltd.setTableState(DictTabInfo::StateOnline);
11235 
11236     FilePtr file_ptr;
11237     ndbrequire(find_object(file_ptr, dictObject.m_id));
11238     objectVersion = file_ptr.p->m_version;
11239     FilegroupPtr fg_ptr;
11240     ndbrequire(find_object(fg_ptr, file_ptr.p->m_filegroup_id));
11241     parentObjectType = fg_ptr.p->m_type;
11242     parentObjectId = fg_ptr.p->key;
11243   }
11244   if (DictTabInfo::isHashMap(type))
11245   {
11246     jam();
11247 
11248     if (parentTableId != RNIL)
11249       return false;
11250 
11251     ltd.requestData = 0;
11252     ltd.setTableId(dictObject.m_id);
11253     ltd.setTableType(type); // type
11254     ltd.setTableState(DictTabInfo::StateOnline);
11255 
11256     HashMapRecordPtr hm_ptr;
11257     ndbrequire(find_object(hm_ptr, dictObject.m_id));
11258     objectVersion = hm_ptr.p->m_object_version;
11259   }
11260 
11261   if (DictTabInfo::isForeignKey(type))
11262   {
11263     jam();
11264 
11265     Ptr<ForeignKeyRec> fk_ptr;
11266     ndbrequire(find_object(fk_ptr, dictObject.m_id));
11267 
11268     if (parentTableId != RNIL &&
11269         parentTableId != fk_ptr.p->m_parentTableId &&
11270         parentTableId != fk_ptr.p->m_parentIndexId &&
11271         parentTableId != fk_ptr.p->m_childTableId  &&
11272         parentTableId != fk_ptr.p->m_childIndexId)
11273       return false;
11274 
11275     ltd.requestData = 0;
11276     ltd.setTableId(dictObject.m_id);
11277     ltd.setTableType(type); // type
11278     ltd.setTableState(DictTabInfo::StateOnline);
11279     objectVersion = fk_ptr.p->m_version;
11280   }
11281 
11282   jam();
11283   return true;
11284 }
11285 
sendLIST_TABLES_CONF(Signal * signal,ListTablesReq * req)11286 void Dbdict::sendLIST_TABLES_CONF(Signal* signal, ListTablesReq* req)
11287 {
11288   Uint32 senderRef  = req->senderRef;
11289   Uint32 senderData = req->senderData;
11290   // save req flags
11291   const Uint32 reqTableId = req->getTableId();
11292   const Uint32 reqTableType = req->getTableType();
11293   const bool reqListNames = req->getListNames();
11294   const bool reqListIndexes = req->getListIndexes();
11295   const bool reqListDependent = req->getListDependent();
11296   NodeReceiverGroup rg(senderRef);
11297 
11298   DictObjectName_hash::Iterator iter;
11299   bool done = !c_obj_name_hash.first(iter);
11300 
11301   if (done)
11302   {
11303     /*
11304      * Empty hashtable, send empty signal
11305      */
11306     jam();
11307     ListTablesConf * const conf = (ListTablesConf*)signal->getDataPtrSend();
11308     conf->senderData = senderData;
11309     conf->noOfTables = 0;
11310     sendSignal(rg, GSN_LIST_TABLES_CONF, signal,
11311                ListTablesConf::SignalLength, JBB);
11312     return;
11313   }
11314 
11315   /*
11316     Pack table data and table names (if requested) in
11317     two signal segments and send it in one long fragmented
11318     signal
11319    */
11320   const Uint32 listTablesDataSizeInWords = (sizeof(ListTablesData) + 3) / 4;
11321   char tname[PATH_MAX];
11322   SimplePropertiesSectionWriter tableDataWriter(* this);
11323   SimplePropertiesSectionWriter tableNamesWriter(* this);
11324 
11325   Uint32 count = 0;
11326   Uint32 fragId = rand();
11327   Uint32 fragInfo = 0;
11328   const Uint32 fragSize = 240;
11329 
11330   tableDataWriter.first();
11331   tableNamesWriter.first();
11332   while(true)
11333   {
11334     Uint32 type = iter.curr.p->m_type;
11335 
11336     if ((reqTableType != (Uint32)0) && (reqTableType != type))
11337       goto flush;
11338 
11339     if (reqListIndexes && !DictTabInfo::isIndex(type))
11340       goto flush;
11341 
11342     ListTablesData ltd;
11343     Uint32 objectVersion, parentObjectType, parentObjectId; /* Unused */
11344 
11345     if (reqListDependent || reqListIndexes)
11346     {
11347       // Check if current object depends on reqTableId.
11348       if (!buildListTablesData(*iter.curr.p,
11349                                reqTableId,
11350                                ltd,
11351                                objectVersion,
11352                                parentObjectType,
11353                                parentObjectId))
11354       {
11355         jam();
11356         goto flush;
11357       }
11358       // A table should not depend on anything.
11359       ndbassert(!DictTabInfo::isTable(type));
11360     }
11361     else
11362     {
11363       const bool found = buildListTablesData(*iter.curr.p,
11364                                              RNIL,
11365                                              ltd,
11366                                              objectVersion,
11367                                              parentObjectType,
11368                                              parentObjectId);
11369       (void)found;
11370       ndbassert(found);
11371     }
11372 
11373     tableDataWriter.putWords((Uint32 *) &ltd, listTablesDataSizeInWords);
11374     count++;
11375 
11376     if (reqListNames)
11377     {
11378       jam();
11379       LocalRope name(c_rope_pool, iter.curr.p->m_name);
11380       const Uint32 size = name.size(); // String length including \0
11381       const Uint32 wsize = (size + 3) / 4;
11382       tableNamesWriter.putWord(size);
11383       name.copy(tname);
11384       tableNamesWriter.putWords((Uint32 *) tname, wsize);
11385     }
11386 
11387 flush:
11388     Uint32 tableDataWords = tableDataWriter.getWordsUsed();
11389     Uint32 tableNameWords = tableNamesWriter.getWordsUsed();
11390 
11391     done = !c_obj_name_hash.next(iter);
11392     if ((tableDataWords + tableNameWords) > fragSize || done)
11393     {
11394       jam();
11395 
11396       /*
11397        * Flush signal fragment to keep memory usage down
11398        */
11399       Uint32 sigLen = ListTablesConf::SignalLength;
11400       Uint32 secs = 0;
11401       if (tableDataWords != 0)
11402       {
11403         jam();
11404         secs++;
11405       }
11406       if (tableNameWords != 0)
11407       {
11408         jam();
11409         secs++;
11410       }
11411       Uint32 * secNos = &signal->theData[sigLen];
11412       signal->theData[sigLen + secs] = fragId;
11413       SectionHandle handle(this);
11414       switch (secs) {
11415       case(0):
11416         jam();
11417         sigLen++; // + fragId;
11418         handle.m_cnt = 0;
11419         break;
11420       case(1):
11421       {
11422         jam();
11423         SegmentedSectionPtr segSecPtr;
11424         sigLen += 2; // 1 sections + fragid
11425         if (tableNameWords == 0)
11426         {
11427           tableDataWriter.getPtr(segSecPtr);
11428           secNos[0] = ListTablesConf::TABLE_DATA;;
11429         }
11430         else
11431         {
11432           tableNamesWriter.getPtr(segSecPtr);
11433           secNos[0] = ListTablesConf::TABLE_NAMES;
11434         }
11435         handle.m_ptr[0] = segSecPtr;
11436         handle.m_cnt = 1;
11437         break;
11438       }
11439       case(2):
11440       {
11441         jam();
11442         sigLen += 3; // 2 sections + fragid
11443         SegmentedSectionPtr tableDataPtr;
11444         tableDataWriter.getPtr(tableDataPtr);
11445         SegmentedSectionPtr tableNamesPtr;
11446         tableNamesWriter.getPtr(tableNamesPtr);
11447         handle.m_ptr[0] = tableDataPtr;
11448         handle.m_ptr[1] = tableNamesPtr;
11449         handle.m_cnt = 2;
11450         secNos[0] = ListTablesConf::TABLE_DATA;
11451         secNos[1] = ListTablesConf::TABLE_NAMES;
11452         break;
11453       }
11454       }
11455 
11456       if (done)
11457       {
11458         jam();
11459         if (fragInfo)
11460         {
11461           jam();
11462           fragInfo = 3;
11463         }
11464       }
11465       else
11466       {
11467         jam();
11468         if (fragInfo == 0)
11469         {
11470           jam();
11471           fragInfo = 1;
11472         }
11473         else
11474         {
11475           jam();
11476           fragInfo = 2;
11477         }
11478       }
11479       signal->header.m_fragmentInfo = fragInfo;
11480 
11481       ListTablesConf * const conf = (ListTablesConf*)signal->getDataPtrSend();
11482       conf->senderData = senderData;
11483       conf->noOfTables = count;
11484       sendSignal(rg, GSN_LIST_TABLES_CONF, signal,
11485                  sigLen, JBB, &handle);
11486 
11487       signal->header.m_noOfSections = 0;
11488       signal->header.m_fragmentInfo = 0;
11489 
11490       if (done)
11491       {
11492         jam();
11493         return;
11494       }
11495 
11496       /**
11497        * Reset counter for next signal
11498        * Reset buffers
11499        */
11500       count = 0;
11501       tableDataWriter.first();
11502       tableNamesWriter.first();
11503     }
11504   }
11505 }
11506 
11507 // MODULE: CreateIndex
11508 
11509 const Dbdict::OpInfo
11510 Dbdict::CreateIndexRec::g_opInfo = {
11511   { 'C', 'I', 'n', 0 },
11512   ~RT_DBDICT_CREATE_INDEX,
11513   GSN_CREATE_INDX_IMPL_REQ,
11514   CreateIndxImplReq::SignalLength,
11515   //
11516   &Dbdict::createIndex_seize,
11517   &Dbdict::createIndex_release,
11518   //
11519   &Dbdict::createIndex_parse,
11520   &Dbdict::createIndex_subOps,
11521   &Dbdict::createIndex_reply,
11522   //
11523   &Dbdict::createIndex_prepare,
11524   &Dbdict::createIndex_commit,
11525   &Dbdict::createIndex_complete,
11526   //
11527   &Dbdict::createIndex_abortParse,
11528   &Dbdict::createIndex_abortPrepare
11529 };
11530 
11531 bool
createIndex_seize(SchemaOpPtr op_ptr)11532 Dbdict::createIndex_seize(SchemaOpPtr op_ptr)
11533 {
11534   return seizeOpRec<CreateIndexRec>(op_ptr);
11535 }
11536 
11537 void
createIndex_release(SchemaOpPtr op_ptr)11538 Dbdict::createIndex_release(SchemaOpPtr op_ptr)
11539 {
11540   releaseOpRec<CreateIndexRec>(op_ptr);
11541 }
11542 
11543 void
execCREATE_INDX_REQ(Signal * signal)11544 Dbdict::execCREATE_INDX_REQ(Signal* signal)
11545 {
11546   jamEntry();
11547   if (!assembleFragments(signal)) {
11548     jam();
11549     return;
11550   }
11551   SectionHandle handle(this, signal);
11552 
11553   if (check_sender_version(signal, MAKE_VERSION(6,4,0)) < 0)
11554   {
11555     jam();
11556     /**
11557      * Pekka has for some obscure reason switched places of
11558      *   senderRef/senderData
11559      */
11560     CreateIndxReq * tmp = (CreateIndxReq*)signal->getDataPtr();
11561     do_swap(tmp->clientRef, tmp->clientData);
11562   }
11563 
11564   const CreateIndxReq req_copy =
11565     *(const CreateIndxReq*)signal->getDataPtr();
11566   const CreateIndxReq* req = &req_copy;
11567 
11568   ErrorInfo error;
11569   do {
11570     SchemaOpPtr op_ptr;
11571     CreateIndexRecPtr createIndexPtr;
11572     CreateIndxImplReq* impl_req;
11573 
11574     startClientReq(op_ptr, createIndexPtr, req, impl_req, error);
11575     if (hasError(error)) {
11576       jam();
11577       break;
11578     }
11579 
11580     impl_req->tableId = req->tableId;
11581     impl_req->tableVersion = req->tableVersion;
11582     impl_req->indexType = req->indexType;
11583     // these are set in sub-operation create table
11584     impl_req->indexId = RNIL;
11585     impl_req->indexVersion = 0;
11586 
11587     handleClientReq(signal, op_ptr, handle);
11588     return;
11589   } while (0);
11590 
11591   releaseSections(handle);
11592 
11593   CreateIndxRef* ref = (CreateIndxRef*)signal->getDataPtrSend();
11594 
11595   ref->senderRef = reference();
11596   ref->clientData = req->clientData;
11597   ref->transId = req->transId;
11598   getError(error, ref);
11599 
11600   sendSignal(req->clientRef, GSN_CREATE_INDX_REF, signal,
11601              CreateIndxRef::SignalLength, JBB);
11602 }
11603 
11604 // CreateIndex: PARSE
11605 
11606 void
createIndex_parse(Signal * signal,bool master,SchemaOpPtr op_ptr,SectionHandle & handle,ErrorInfo & error)11607 Dbdict::createIndex_parse(Signal* signal, bool master,
11608                           SchemaOpPtr op_ptr,
11609                           SectionHandle& handle, ErrorInfo& error)
11610 {
11611   D("createIndex_parse");
11612 
11613   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
11614   CreateIndexRecPtr createIndexPtr;
11615   getOpRec(op_ptr, createIndexPtr);
11616   CreateIndxImplReq* impl_req = &createIndexPtr.p->m_request;
11617 
11618   // save attribute list
11619   IndexAttributeList& attrList = createIndexPtr.p->m_attrList;
11620   {
11621     SegmentedSectionPtr ss_ptr;
11622     handle.getSection(ss_ptr, CreateIndxReq::ATTRIBUTE_LIST_SECTION);
11623     SimplePropertiesSectionReader r(ss_ptr, getSectionSegmentPool());
11624     r.reset(); // undo implicit first()
11625     if (!r.getWord(&attrList.sz) ||
11626         r.getSize() != 1 + attrList.sz ||
11627         attrList.sz == 0 ||
11628         attrList.sz > MAX_ATTRIBUTES_IN_INDEX ||
11629         !r.getWords(attrList.id, attrList.sz)) {
11630       jam();
11631       setError(error, CreateIndxRef::InvalidIndexType, __LINE__);
11632       return;
11633     }
11634   }
11635 
11636   // save name and some index table properties
11637   Uint32& bits = createIndexPtr.p->m_bits;
11638   bits = TableRecord::TR_RowChecksum;
11639   {
11640     SegmentedSectionPtr ss_ptr;
11641     handle.getSection(ss_ptr, CreateIndxReq::INDEX_NAME_SECTION);
11642     SimplePropertiesSectionReader r(ss_ptr, getSectionSegmentPool());
11643     DictTabInfo::Table tableDesc;
11644     tableDesc.init();
11645     SimpleProperties::UnpackStatus status =
11646       SimpleProperties::unpack(
11647           r, &tableDesc,
11648           DictTabInfo::TableMapping, DictTabInfo::TableMappingSize,
11649           true, true);
11650     if (status != SimpleProperties::Eof ||
11651         tableDesc.TableName[0] == 0)
11652     {
11653       ndbassert(false);
11654       setError(error, CreateIndxRef::InvalidName, __LINE__);
11655       return;
11656     }
11657     const Uint32 bytesize = sizeof(createIndexPtr.p->m_indexName);
11658     memcpy(createIndexPtr.p->m_indexName, tableDesc.TableName, bytesize);
11659     if (tableDesc.TableLoggedFlag) {
11660       jam();
11661       bits |= TableRecord::TR_Logged;
11662     }
11663     if (tableDesc.TableTemporaryFlag) {
11664       jam();
11665       bits |= TableRecord::TR_Temporary;
11666     }
11667     D("index " << createIndexPtr.p->m_indexName);
11668   }
11669 
11670   // check primary table
11671   TableRecordPtr tablePtr;
11672   {
11673     if (!(impl_req->tableId < c_noOfMetaTables)) {
11674       jam();
11675       setError(error, CreateIndxRef::InvalidPrimaryTable, __LINE__);
11676       return;
11677     }
11678     bool ok = find_object(tablePtr, impl_req->tableId);
11679     if (!ok || !tablePtr.p->isTable()) {
11680 
11681       jam();
11682       setError(error, CreateIndxRef::InvalidPrimaryTable, __LINE__);
11683       return;
11684     }
11685 
11686     Uint32 err;
11687     if ((err = check_read_obj(impl_req->tableId, trans_ptr.p->m_transId)))
11688     {
11689       jam();
11690       setError(error, err, __LINE__);
11691       return;
11692     }
11693   }
11694 
11695   // check index type and set more properties
11696   {
11697     switch (impl_req->indexType) {
11698     case DictTabInfo::UniqueHashIndex:
11699       jam();
11700       createIndexPtr.p->m_fragmentType = DictTabInfo::HashMapPartition;
11701       break;
11702     case DictTabInfo::OrderedIndex:
11703       jam();
11704       if (bits & TableRecord::TR_Logged) {
11705         jam();
11706         setError(error, CreateIndxRef::InvalidIndexType, __LINE__);
11707         return;
11708       }
11709       createIndexPtr.p->m_fragmentType = DictTabInfo::DistrKeyOrderedIndex;
11710       // hash case is computed later from attribute list
11711       createIndexPtr.p->m_indexKeyLength = MAX_TTREE_NODE_SIZE;
11712       break;
11713     default:
11714       setError(error, CreateIndxRef::InvalidIndexType, __LINE__);
11715       return;
11716     }
11717   }
11718 
11719   // check that the temporary status of index is compatible with table
11720   {
11721     if (!(bits & TableRecord::TR_Temporary) &&
11722         (tablePtr.p->m_bits & TableRecord::TR_Temporary))
11723     {
11724       jam();
11725       setError(error, CreateIndxRef::TableIsTemporary, __LINE__);
11726       return;
11727     }
11728     if ((bits & TableRecord::TR_Temporary) &&
11729         !(tablePtr.p->m_bits & TableRecord::TR_Temporary))
11730     {
11731       // This could be implemented later, but mysqld does currently not detect
11732       // that the index disappears after SR, and it appears not too useful.
11733       jam();
11734       setError(error, CreateIndxRef::TableIsNotTemporary, __LINE__);
11735       return;
11736     }
11737     if ((bits & TableRecord::TR_Temporary) &&
11738         (bits & TableRecord::TR_Logged))
11739     {
11740       jam();
11741       setError(error, CreateIndxRef::NoLoggingTemporaryIndex, __LINE__);
11742       return;
11743     }
11744   }
11745 
11746   // check attribute list
11747   AttributeMask& attrMask = createIndexPtr.p->m_attrMask;
11748   AttributeMap& attrMap = createIndexPtr.p->m_attrMap;
11749   {
11750     Uint32 k;
11751     for (k = 0; k < attrList.sz; k++) {
11752       jam();
11753       Uint32 current_id = attrList.id[k];
11754       AttributeRecordPtr attrPtr;
11755 
11756       // find the attribute
11757       {
11758         LocalAttributeRecord_list
11759           list(c_attributeRecordPool, tablePtr.p->m_attributes);
11760         list.first(attrPtr);
11761         while (!attrPtr.isNull()) {
11762           jam();
11763           if (attrPtr.p->attributeId == current_id) {
11764             jam();
11765             break;
11766           }
11767           list.next(attrPtr);
11768         }
11769       }
11770       if (attrPtr.isNull()) {
11771         jam();
11772 	ndbassert(false);
11773         setError(error, CreateIndxRef::BadRequestType, __LINE__);
11774         return;
11775       }
11776 
11777       // add attribute to mask
11778       if (attrMask.get(current_id)) {
11779         jam();
11780         setError(error, CreateIndxRef::DuplicateAttributes, __LINE__);
11781         return;
11782       }
11783       attrMask.set(current_id);
11784 
11785       // check disk based
11786       const Uint32 attrDesc = attrPtr.p->attributeDescriptor;
11787       if (AttributeDescriptor::getDiskBased(attrDesc)) {
11788         jam();
11789         setError(error, CreateIndxRef::IndexOnDiskAttributeError, __LINE__);
11790         return;
11791       }
11792 
11793       // re-order hash index by attribute id
11794       Uint32 new_index = k;
11795       if (impl_req->indexType == DictTabInfo::UniqueHashIndex) {
11796         jam();
11797         // map contains (old_index,attr_id) ordered by attr_id
11798         while (new_index > 0) {
11799           jam();
11800           if (current_id >= attrMap[new_index - 1].attr_id) {
11801             jam();
11802             break;
11803           }
11804           attrMap[new_index] = attrMap[new_index - 1];
11805           new_index--;
11806         }
11807       }
11808       attrMap[new_index].old_index = k;
11809       attrMap[new_index].attr_id = current_id;
11810       attrMap[new_index].attr_ptr_i = attrPtr.i;
11811 
11812       // add key size for hash index (ordered case was handled before)
11813       if (impl_req->indexType == DictTabInfo::UniqueHashIndex) {
11814         jam();
11815         const Uint32 s1 = AttributeDescriptor::getSize(attrDesc);
11816         const Uint32 s2 = AttributeDescriptor::getArraySize(attrDesc);
11817         createIndexPtr.p->m_indexKeyLength += ((1 << s1) * s2 + 31) >> 5;
11818       }
11819     }
11820   }
11821 
11822   if (master)
11823   {
11824     jam();
11825     impl_req->indexId = getFreeObjId();
11826   }
11827 
11828   if (impl_req->indexId == RNIL)
11829   {
11830     jam();
11831     setError(error, CreateTableRef::NoMoreTableRecords, __LINE__);
11832     return;
11833   }
11834 
11835   if (impl_req->indexId >= c_noOfMetaTables)
11836   {
11837     jam();
11838     setError(error, CreateTableRef::NoMoreTableRecords, __LINE__);
11839     return;
11840   }
11841 
11842   if (ERROR_INSERTED(6122)) {
11843     jam();
11844     CLEAR_ERROR_INSERT_VALUE;
11845     setError(error, 9122, __LINE__);
11846     return;
11847   }
11848 }
11849 
11850 bool
createIndex_subOps(Signal * signal,SchemaOpPtr op_ptr)11851 Dbdict::createIndex_subOps(Signal* signal, SchemaOpPtr op_ptr)
11852 {
11853   D("createIndex_subOps" << V(op_ptr.i) << *op_ptr.p);
11854 
11855   CreateIndexRecPtr createIndexPtr;
11856   getOpRec(op_ptr, createIndexPtr);
11857 
11858   // op to create index table
11859   if (!createIndexPtr.p->m_sub_create_table) {
11860     jam();
11861     Callback c = {
11862       safe_cast(&Dbdict::createIndex_fromCreateTable),
11863       op_ptr.p->op_key
11864     };
11865     op_ptr.p->m_callback = c;
11866     createIndex_toCreateTable(signal, op_ptr);
11867     return true;
11868   }
11869   // op to alter index online
11870   if (!createIndexPtr.p->m_sub_alter_index) {
11871     jam();
11872     Callback c = {
11873       safe_cast(&Dbdict::createIndex_fromAlterIndex),
11874       op_ptr.p->op_key
11875     };
11876     op_ptr.p->m_callback = c;
11877     createIndex_toAlterIndex(signal, op_ptr);
11878     return true;
11879   }
11880   return false;
11881 }
11882 
11883 void
createIndex_toCreateTable(Signal * signal,SchemaOpPtr op_ptr)11884 Dbdict::createIndex_toCreateTable(Signal* signal, SchemaOpPtr op_ptr)
11885 {
11886   D("createIndex_toCreateTable");
11887 
11888   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
11889   CreateIndexRecPtr createIndexPtr;
11890   getOpRec(op_ptr, createIndexPtr);
11891 
11892   TableRecordPtr tablePtr;
11893   bool ok = find_object(tablePtr, createIndexPtr.p->m_request.tableId);
11894   ndbrequire(ok);
11895 
11896   // signal data writer
11897   Uint32* wbuffer = &c_indexPage.word[0];
11898   LinearWriter w(wbuffer, sizeof(c_indexPage) >> 2);
11899   w.first();
11900 
11901   //indexPtr.p->noOfPrimkey = indexPtr.p->noOfAttributes;
11902   // plus concatenated primary table key attribute
11903   //indexPtr.p->noOfAttributes += 1;
11904   //indexPtr.p->noOfNullAttr = 0;
11905 
11906   w.add(DictTabInfo::TableId, createIndexPtr.p->m_request.indexId);
11907   w.add(DictTabInfo::TableName, createIndexPtr.p->m_indexName);
11908   { bool flag = createIndexPtr.p->m_bits & TableRecord::TR_Logged;
11909     w.add(DictTabInfo::TableLoggedFlag, (Uint32)flag);
11910   }
11911   { bool flag = createIndexPtr.p->m_bits & TableRecord::TR_Temporary;
11912     w.add(DictTabInfo::TableTemporaryFlag, (Uint32)flag);
11913   }
11914   w.add(DictTabInfo::FragmentTypeVal, createIndexPtr.p->m_fragmentType);
11915   // Inherit fragment count if main table is also hashmap partitioned.
11916   // Otherwise better do use default.
11917   if ((DictTabInfo::FragmentType)createIndexPtr.p->m_fragmentType == tablePtr.p->fragmentType &&
11918       tablePtr.p->fragmentType == DictTabInfo::HashMapPartition)
11919   {
11920     w.add(DictTabInfo::FragmentCount, tablePtr.p->fragmentCount);
11921   }
11922 
11923   w.add(DictTabInfo::TableTypeVal, createIndexPtr.p->m_request.indexType);
11924   { LocalRope name(c_rope_pool, tablePtr.p->tableName);
11925     char tableName[MAX_TAB_NAME_SIZE];
11926     name.copy(tableName);
11927     w.add(DictTabInfo::PrimaryTable, tableName);
11928   }
11929   w.add(DictTabInfo::PrimaryTableId, tablePtr.p->tableId);
11930   w.add(DictTabInfo::NoOfAttributes, createIndexPtr.p->m_attrList.sz + 1);
11931   w.add(DictTabInfo::NoOfKeyAttr, createIndexPtr.p->m_attrList.sz);//XXX ordered??
11932   w.add(DictTabInfo::NoOfNullable, (Uint32)0);
11933   w.add(DictTabInfo::KeyLength, createIndexPtr.p->m_indexKeyLength);
11934   w.add(DictTabInfo::SingleUserMode, (Uint32)NDB_SUM_READ_WRITE);
11935 
11936   // write index key attributes
11937 
11938   //const IndexAttributeList& attrList = createIndexPtr.p->m_attrList;
11939   const AttributeMap& attrMap = createIndexPtr.p->m_attrMap;
11940   Uint32 k;
11941   for (k = 0; k < createIndexPtr.p->m_attrList.sz; k++) {
11942     jam();
11943     // insert the attributes in the order decided before in attrMap
11944     // TODO: make sure "old_index" is stored with the table and
11945     // passed up to NdbDictionary
11946     AttributeRecordPtr attrPtr;
11947     c_attributeRecordPool.getPtr(attrPtr, attrMap[k].attr_ptr_i);
11948 
11949     { LocalRope attrName(c_rope_pool, attrPtr.p->attributeName);
11950       char attributeName[MAX_ATTR_NAME_SIZE];
11951       attrName.copy(attributeName);
11952       w.add(DictTabInfo::AttributeName, attributeName);
11953     }
11954 
11955     const Uint32 attrDesc = attrPtr.p->attributeDescriptor;
11956     const bool isNullable = AttributeDescriptor::getNullable(attrDesc);
11957     const Uint32 arrayType = AttributeDescriptor::getArrayType(attrDesc);
11958     const Uint32 attrType = AttributeDescriptor::getType(attrDesc);
11959 
11960     w.add(DictTabInfo::AttributeId, k);
11961     if (createIndexPtr.p->m_request.indexType == DictTabInfo::UniqueHashIndex) {
11962       jam();
11963       w.add(DictTabInfo::AttributeKeyFlag, (Uint32)true);
11964       w.add(DictTabInfo::AttributeNullableFlag, (Uint32)false);
11965     }
11966     if (createIndexPtr.p->m_request.indexType == DictTabInfo::OrderedIndex) {
11967       jam();
11968       w.add(DictTabInfo::AttributeKeyFlag, (Uint32)false);
11969       w.add(DictTabInfo::AttributeNullableFlag, (Uint32)isNullable);
11970     }
11971     w.add(DictTabInfo::AttributeArrayType, arrayType);
11972     w.add(DictTabInfo::AttributeExtType, attrType);
11973     w.add(DictTabInfo::AttributeExtPrecision, attrPtr.p->extPrecision);
11974     w.add(DictTabInfo::AttributeExtScale, attrPtr.p->extScale);
11975     w.add(DictTabInfo::AttributeExtLength, attrPtr.p->extLength);
11976     w.add(DictTabInfo::AttributeEnd, (Uint32)true);
11977   }
11978 
11979   if (createIndexPtr.p->m_request.indexType == DictTabInfo::UniqueHashIndex) {
11980     jam();
11981     Uint32 key_type = NDB_ARRAYTYPE_FIXED;
11982     AttributeRecordPtr attrPtr;
11983     LocalAttributeRecord_list list(c_attributeRecordPool,
11984                                           tablePtr.p->m_attributes);
11985     // XXX move to parse
11986     for (list.first(attrPtr); !attrPtr.isNull(); list.next(attrPtr))
11987     {
11988       const Uint32 desc = attrPtr.p->attributeDescriptor;
11989       if (AttributeDescriptor::getPrimaryKey(desc) &&
11990 	  AttributeDescriptor::getArrayType(desc) != NDB_ARRAYTYPE_FIXED)
11991       {
11992 	key_type = NDB_ARRAYTYPE_MEDIUM_VAR;
11993         if (NDB_VERSION_D >= MAKE_VERSION(7,1,0))
11994         {
11995           jam();
11996           /**
11997            * We can only set this new array type "globally" if
11998            *   version >= X, this to allow down-grade(s) within minor versions
11999            *   if unique index has been added in newer version
12000            *
12001            * There is anyway nasty code sendLQHADDATTRREQ to handle the
12002            *   "local" variant of this
12003            */
12004           key_type = NDB_ARRAYTYPE_NONE_VAR;
12005         }
12006 	break;
12007       }
12008     }
12009 
12010     // write concatenated primary table key attribute i.e. keyinfo
12011     w.add(DictTabInfo::AttributeName, "NDB$PK");
12012     w.add(DictTabInfo::AttributeId, createIndexPtr.p->m_attrList.sz);
12013     w.add(DictTabInfo::AttributeArrayType, key_type);
12014     w.add(DictTabInfo::AttributeKeyFlag, (Uint32)false);
12015     w.add(DictTabInfo::AttributeNullableFlag, (Uint32)false);
12016     w.add(DictTabInfo::AttributeExtType, (Uint32)DictTabInfo::ExtUnsigned);
12017     w.add(DictTabInfo::AttributeExtLength, tablePtr.p->tupKeyLength+1);
12018     w.add(DictTabInfo::AttributeEnd, (Uint32)true);
12019   }
12020   if (createIndexPtr.p->m_request.indexType == DictTabInfo::OrderedIndex) {
12021     jam();
12022     // write index tree node as Uint32 array attribute
12023     w.add(DictTabInfo::AttributeName, "NDB$TNODE");
12024     w.add(DictTabInfo::AttributeId, createIndexPtr.p->m_attrList.sz);
12025     // should not matter but VAR crashes in TUP
12026     w.add(DictTabInfo::AttributeArrayType, (Uint32)NDB_ARRAYTYPE_FIXED);
12027     w.add(DictTabInfo::AttributeKeyFlag, (Uint32)true);
12028     w.add(DictTabInfo::AttributeNullableFlag, (Uint32)false);
12029     w.add(DictTabInfo::AttributeExtType, (Uint32)DictTabInfo::ExtUnsigned);
12030     w.add(DictTabInfo::AttributeExtLength, createIndexPtr.p->m_indexKeyLength);
12031     w.add(DictTabInfo::AttributeEnd, (Uint32)true);
12032   }
12033   // finish
12034   w.add(DictTabInfo::TableEnd, (Uint32)true);
12035 
12036   CreateTableReq* req = (CreateTableReq*)signal->getDataPtrSend();
12037 
12038   Uint32 requestInfo = 0;
12039   DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
12040 
12041   req->clientRef = reference();
12042   req->clientData = op_ptr.p->op_key;
12043   req->transId = trans_ptr.p->m_transId;
12044   req->transKey = trans_ptr.p->trans_key;
12045   req->requestInfo = requestInfo;
12046 
12047   LinearSectionPtr lsPtr[3];
12048   lsPtr[0].p = wbuffer;
12049   lsPtr[0].sz = w.getWordsUsed();
12050   sendSignal(reference(), GSN_CREATE_TABLE_REQ, signal,
12051              CreateTableReq::SignalLength, JBB, lsPtr, 1);
12052 }
12053 
12054 void
createIndex_fromCreateTable(Signal * signal,Uint32 op_key,Uint32 ret)12055 Dbdict::createIndex_fromCreateTable(Signal* signal, Uint32 op_key, Uint32 ret)
12056 {
12057   jam();
12058   D("createIndex_fromCreateTable" << dec << V(op_key) << V(ret));
12059 
12060   SchemaOpPtr op_ptr;
12061   CreateIndexRecPtr createIndexPtr;
12062 
12063   findSchemaOp(op_ptr, createIndexPtr, op_key);
12064   ndbrequire(!op_ptr.isNull());
12065   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12066   CreateIndxImplReq* impl_req = &createIndexPtr.p->m_request;
12067 
12068   if (ret == 0) {
12069     const CreateTableConf* conf =
12070       (const CreateTableConf*)signal->getDataPtr();
12071 
12072     ndbrequire(conf->transId == trans_ptr.p->m_transId);
12073     impl_req->indexVersion = conf->tableVersion;
12074     createIndexPtr.p->m_sub_create_table = true;
12075 
12076     createSubOps(signal, op_ptr);
12077   } else {
12078     jam();
12079     const CreateTableRef* ref =
12080       (const CreateTableRef*)signal->getDataPtr();
12081     ErrorInfo error;
12082     setError(error, ref);
12083     abortSubOps(signal, op_ptr, error);
12084   }
12085 }
12086 
12087 void
createIndex_toAlterIndex(Signal * signal,SchemaOpPtr op_ptr)12088 Dbdict::createIndex_toAlterIndex(Signal* signal, SchemaOpPtr op_ptr)
12089 {
12090   D("createIndex_toAlterIndex");
12091 
12092   AlterIndxReq* req = (AlterIndxReq*)signal->getDataPtrSend();
12093 
12094   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12095   CreateIndexRecPtr createIndexPtr;
12096   getOpRec(op_ptr, createIndexPtr);
12097 
12098   Uint32 requestInfo = 0;
12099   DictSignal::setRequestType(requestInfo, AlterIndxImplReq::AlterIndexOnline);
12100   DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
12101 
12102   if (op_ptr.p->m_requestInfo & CreateIndxReq::RF_BUILD_OFFLINE)
12103   {
12104     jam();
12105     requestInfo |= AlterIndxReq::RF_BUILD_OFFLINE;
12106   }
12107 
12108   req->clientRef = reference();
12109   req->clientData = op_ptr.p->op_key;
12110   req->transId = trans_ptr.p->m_transId;
12111   req->transKey = trans_ptr.p->trans_key;
12112   req->requestInfo = requestInfo;
12113   req->indexId = createIndexPtr.p->m_request.indexId;
12114   req->indexVersion = createIndexPtr.p->m_request.indexVersion;
12115 
12116   sendSignal(reference(), GSN_ALTER_INDX_REQ, signal,
12117              AlterIndxReq::SignalLength, JBB);
12118 }
12119 
12120 void
createIndex_fromAlterIndex(Signal * signal,Uint32 op_key,Uint32 ret)12121 Dbdict::createIndex_fromAlterIndex(Signal* signal, Uint32 op_key, Uint32 ret)
12122 {
12123   jam();
12124   D("createIndex_fromAlterIndex");
12125 
12126   SchemaOpPtr op_ptr;
12127   CreateIndexRecPtr createIndexPtr;
12128 
12129   findSchemaOp(op_ptr, createIndexPtr, op_key);
12130   ndbrequire(!op_ptr.isNull());
12131   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12132 
12133   //Uint32 errorCode = 0;
12134   if (ret == 0) {
12135     const AlterIndxConf* conf =
12136       (const AlterIndxConf*)signal->getDataPtr();
12137 
12138     ndbrequire(conf->transId == trans_ptr.p->m_transId);
12139     createIndexPtr.p->m_sub_alter_index = true;
12140     createSubOps(signal, op_ptr);
12141   } else {
12142     jam();
12143     const AlterIndxRef* ref =
12144       (const AlterIndxRef*)signal->getDataPtr();
12145 
12146     ErrorInfo error;
12147     setError(error, ref);
12148     abortSubOps(signal, op_ptr, error);
12149   }
12150 }
12151 
12152 void
createIndex_reply(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)12153 Dbdict::createIndex_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
12154 {
12155   jam();
12156   D("createIndex_reply");
12157 
12158   SchemaTransPtr& trans_ptr = op_ptr.p->m_trans_ptr;
12159   CreateIndexRecPtr createIndexPtr;
12160   getOpRec(op_ptr, createIndexPtr);
12161   const CreateIndxImplReq* impl_req = &createIndexPtr.p->m_request;
12162 
12163   if (!hasError(error)) {
12164     CreateIndxConf* conf = (CreateIndxConf*)signal->getDataPtrSend();
12165     conf->senderRef = reference();
12166     conf->clientData = op_ptr.p->m_clientData;
12167     conf->transId = trans_ptr.p->m_transId;
12168     conf->indexId = impl_req->indexId;
12169     conf->indexVersion = impl_req->indexVersion;
12170 
12171     D(V(conf->indexId) << V(conf->indexVersion));
12172 
12173     Uint32 clientRef = op_ptr.p->m_clientRef;
12174     sendSignal(clientRef, GSN_CREATE_INDX_CONF, signal,
12175                CreateIndxConf::SignalLength, JBB);
12176   } else {
12177     jam();
12178     CreateIndxRef* ref = (CreateIndxRef*)signal->getDataPtrSend();
12179     ref->senderRef = reference();
12180     ref->clientData = op_ptr.p->m_clientData;
12181     ref->transId = trans_ptr.p->m_transId;
12182     getError(error, ref);
12183 
12184     Uint32 clientRef = op_ptr.p->m_clientRef;
12185     sendSignal(clientRef, GSN_CREATE_INDX_REF, signal,
12186                CreateIndxRef::SignalLength, JBB);
12187   }
12188 }
12189 
12190 // CreateIndex: PREPARE
12191 
12192 void
createIndex_prepare(Signal * signal,SchemaOpPtr op_ptr)12193 Dbdict::createIndex_prepare(Signal* signal, SchemaOpPtr op_ptr)
12194 {
12195   jam();
12196   D("createIndex_prepare");
12197 
12198   CreateIndexRecPtr createIndexPtr;
12199   getOpRec(op_ptr, createIndexPtr);
12200 
12201   sendTransConf(signal, op_ptr);
12202 }
12203 
12204 // CreateIndex: COMMIT
12205 
12206 void
createIndex_commit(Signal * signal,SchemaOpPtr op_ptr)12207 Dbdict::createIndex_commit(Signal* signal, SchemaOpPtr op_ptr)
12208 {
12209   jam();
12210   D("createIndex_commit");
12211 
12212   sendTransConf(signal, op_ptr);
12213 }
12214 
12215 // CreateIndex: COMPLETE
12216 
12217 void
createIndex_complete(Signal * signal,SchemaOpPtr op_ptr)12218 Dbdict::createIndex_complete(Signal* signal, SchemaOpPtr op_ptr)
12219 {
12220   jam();
12221   sendTransConf(signal, op_ptr);
12222 }
12223 
12224 // CreateIndex: ABORT
12225 
12226 void
createIndex_abortParse(Signal * signal,SchemaOpPtr op_ptr)12227 Dbdict::createIndex_abortParse(Signal* signal, SchemaOpPtr op_ptr)
12228 {
12229   D("createIndex_abortParse" << *op_ptr.p);
12230 
12231   // wl3600_todo probably nothing..
12232 
12233   sendTransConf(signal, op_ptr);
12234 }
12235 
12236 void
createIndex_abortPrepare(Signal * signal,SchemaOpPtr op_ptr)12237 Dbdict::createIndex_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
12238 {
12239   D("createIndex_abortPrepare" << *op_ptr.p);
12240   // wl3600_todo
12241 
12242   CreateIndexRecPtr createIndexPtr;
12243   getOpRec(op_ptr, createIndexPtr);
12244 
12245   sendTransConf(signal, op_ptr);
12246 }
12247 
12248 // CreateIndex: MISC
12249 
12250 void
execCREATE_INDX_IMPL_CONF(Signal * signal)12251 Dbdict::execCREATE_INDX_IMPL_CONF(Signal* signal)
12252 {
12253   jamEntry();
12254   const CreateIndxImplConf* conf = (const CreateIndxImplConf*)signal->getDataPtr();
12255   ndbrequire(refToNode(conf->senderRef) == getOwnNodeId());
12256   handleDictConf(signal, conf);
12257 }
12258 
12259 void
execCREATE_INDX_IMPL_REF(Signal * signal)12260 Dbdict::execCREATE_INDX_IMPL_REF(Signal* signal)
12261 {
12262   jamEntry();
12263   const CreateIndxImplRef* ref = (const CreateIndxImplRef*)signal->getDataPtr();
12264   ndbrequire(refToNode(ref->senderRef) == getOwnNodeId());
12265   handleDictRef(signal, ref);
12266 }
12267 
12268 // CreateIndex: END
12269 
12270 // MODULE: DropIndex
12271 
12272 const Dbdict::OpInfo
12273 Dbdict::DropIndexRec::g_opInfo = {
12274   { 'D', 'I', 'n', 0 },
12275   ~RT_DBDICT_DROP_INDEX,
12276   GSN_DROP_INDX_IMPL_REQ,
12277   DropIndxImplReq::SignalLength,
12278   //
12279   &Dbdict::dropIndex_seize,
12280   &Dbdict::dropIndex_release,
12281   //
12282   &Dbdict::dropIndex_parse,
12283   &Dbdict::dropIndex_subOps,
12284   &Dbdict::dropIndex_reply,
12285   //
12286   &Dbdict::dropIndex_prepare,
12287   &Dbdict::dropIndex_commit,
12288   &Dbdict::dropIndex_complete,
12289   //
12290   &Dbdict::dropIndex_abortParse,
12291   &Dbdict::dropIndex_abortPrepare
12292 };
12293 
12294 bool
dropIndex_seize(SchemaOpPtr op_ptr)12295 Dbdict::dropIndex_seize(SchemaOpPtr op_ptr)
12296 {
12297   return seizeOpRec<DropIndexRec>(op_ptr);
12298 }
12299 
12300 void
dropIndex_release(SchemaOpPtr op_ptr)12301 Dbdict::dropIndex_release(SchemaOpPtr op_ptr)
12302 {
12303   releaseOpRec<DropIndexRec>(op_ptr);
12304 }
12305 
12306 void
execDROP_INDX_REQ(Signal * signal)12307 Dbdict::execDROP_INDX_REQ(Signal* signal)
12308 {
12309   jamEntry();
12310   if (!assembleFragments(signal)) {
12311     jam();
12312     return;
12313   }
12314   SectionHandle handle(this, signal);
12315 
12316   if (check_sender_version(signal, MAKE_VERSION(6,4,0)) < 0)
12317   {
12318     jam();
12319     /**
12320      * Pekka has for some obscure reason switched places of
12321      *   senderRef/senderData
12322      */
12323     DropIndxReq * tmp = (DropIndxReq*)signal->getDataPtr();
12324     do_swap(tmp->clientRef, tmp->clientData);
12325   }
12326 
12327   const DropIndxReq req_copy =
12328     *(const DropIndxReq*)signal->getDataPtr();
12329   const DropIndxReq* req = &req_copy;
12330 
12331   ErrorInfo error;
12332   do {
12333     SchemaOpPtr op_ptr;
12334     DropIndexRecPtr dropIndexPtr;
12335     DropIndxImplReq* impl_req;
12336 
12337     startClientReq(op_ptr, dropIndexPtr, req, impl_req, error);
12338     if (hasError(error)) {
12339       jam();
12340       break;
12341     }
12342 
12343     impl_req->tableId = RNIL;    // wl3600_todo fill in in parse
12344     impl_req->tableVersion = 0;
12345     impl_req->indexId = req->indexId;
12346     impl_req->indexVersion = req->indexVersion;
12347 
12348     handleClientReq(signal, op_ptr, handle);
12349     return;
12350   } while (0);
12351 
12352   releaseSections(handle);
12353 
12354   DropIndxRef* ref = (DropIndxRef*)signal->getDataPtrSend();
12355   ref->senderRef = reference();
12356   ref->clientData = req->clientData;
12357   ref->transId = req->transId;
12358   ref->indexId = req->indexId;
12359   ref->indexVersion = req->indexVersion;
12360   getError(error, ref);
12361 
12362   sendSignal(req->clientRef, GSN_DROP_INDX_REF, signal,
12363              DropIndxRef::SignalLength, JBB);
12364 }
12365 
12366 // DropIndex: PARSE
12367 
12368 void
dropIndex_parse(Signal * signal,bool master,SchemaOpPtr op_ptr,SectionHandle & handle,ErrorInfo & error)12369 Dbdict::dropIndex_parse(Signal* signal, bool master,
12370                         SchemaOpPtr op_ptr,
12371                         SectionHandle& handle, ErrorInfo& error)
12372 {
12373   D("dropIndex_parse" << V(op_ptr.i) << *op_ptr.p);
12374   jam();
12375 
12376   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12377   DropIndexRecPtr dropIndexPtr;
12378   getOpRec(op_ptr, dropIndexPtr);
12379   DropIndxImplReq* impl_req = &dropIndexPtr.p->m_request;
12380 
12381   if (!(impl_req->indexId < c_noOfMetaTables)) {
12382     jam();
12383     setError(error, DropIndxRef::IndexNotFound, __LINE__);
12384     return;
12385   }
12386 
12387   Uint32 err = check_read_obj(impl_req->indexId, trans_ptr.p->m_transId);
12388   if (err)
12389   {
12390     jam();
12391     setError(error, err, __LINE__);
12392     return;
12393   }
12394 
12395   TableRecordPtr indexPtr;
12396   bool ok = find_object(indexPtr, impl_req->indexId);
12397   if (!ok || !indexPtr.p->isIndex())
12398   {
12399     jam();
12400     setError(error, DropIndxRef::NotAnIndex, __LINE__);
12401     return;
12402   }
12403 
12404   if (indexPtr.p->tableVersion != impl_req->indexVersion)
12405   {
12406     jam();
12407     setError(error, DropIndxRef::InvalidIndexVersion, __LINE__);
12408     return;
12409   }
12410 
12411   if (check_write_obj(impl_req->indexId, trans_ptr.p->m_transId,
12412                       SchemaFile::SF_DROP, error))
12413   {
12414     jam();
12415     return;
12416   }
12417 
12418   TableRecordPtr tablePtr;
12419   ok = find_object(tablePtr, indexPtr.p->primaryTableId);
12420   if (!ok)
12421   {
12422     jam();
12423     setError(error, CreateIndxRef::InvalidPrimaryTable, __LINE__);
12424     return;
12425   }
12426 
12427   // master sets primary table, slave verifies it agrees
12428   if (master)
12429   {
12430     jam();
12431     impl_req->tableId = tablePtr.p->tableId;
12432     impl_req->tableVersion = tablePtr.p->tableVersion;
12433   }
12434   else
12435   {
12436     if (impl_req->tableId != tablePtr.p->tableId)
12437     {
12438       jam(); // wl3600_todo better error code
12439       setError(error, DropIndxRef::InvalidIndexVersion, __LINE__);
12440       return;
12441     }
12442     if (impl_req->tableVersion != tablePtr.p->tableVersion)
12443     {
12444       jam(); // wl3600_todo better error code
12445       setError(error, DropIndxRef::InvalidIndexVersion, __LINE__);
12446       return;
12447     }
12448   }
12449 
12450   if (ERROR_INSERTED(6122)) {
12451     jam();
12452     CLEAR_ERROR_INSERT_VALUE;
12453     setError(error, 9122, __LINE__);
12454     return;
12455   }
12456 }
12457 
12458 bool
dropIndex_subOps(Signal * signal,SchemaOpPtr op_ptr)12459 Dbdict::dropIndex_subOps(Signal* signal, SchemaOpPtr op_ptr)
12460 {
12461   D("dropIndex_subOps" << V(op_ptr.i) << *op_ptr.p);
12462 
12463   DropIndexRecPtr dropIndexPtr;
12464   getOpRec(op_ptr, dropIndexPtr);
12465 
12466   // op to alter index offline
12467   if (!dropIndexPtr.p->m_sub_alter_index) {
12468     jam();
12469     Callback c = {
12470       safe_cast(&Dbdict::dropIndex_fromAlterIndex),
12471       op_ptr.p->op_key
12472     };
12473     op_ptr.p->m_callback = c;
12474     dropIndex_toAlterIndex(signal, op_ptr);
12475     return true;
12476   }
12477 
12478   // op to drop index table
12479   if (!dropIndexPtr.p->m_sub_drop_table) {
12480     jam();
12481     Callback c = {
12482       safe_cast(&Dbdict::dropIndex_fromDropTable),
12483       op_ptr.p->op_key
12484     };
12485     op_ptr.p->m_callback = c;
12486     dropIndex_toDropTable(signal, op_ptr);
12487     return true;
12488   }
12489 
12490   return false;
12491 }
12492 
12493 void
dropIndex_reply(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)12494 Dbdict::dropIndex_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
12495 {
12496   jam();
12497   D("dropIndex_reply" << V(op_ptr.i) << *op_ptr.p);
12498 
12499   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12500 
12501   DropIndexRecPtr dropIndexPtr;
12502   getOpRec(op_ptr, dropIndexPtr);
12503   const DropIndxImplReq* impl_req = &dropIndexPtr.p->m_request;
12504 
12505   if (!hasError(error)) {
12506     DropIndxConf* conf = (DropIndxConf*)signal->getDataPtrSend();
12507     conf->senderRef = reference();
12508     conf->clientData = op_ptr.p->m_clientData;
12509     conf->transId = trans_ptr.p->m_transId;
12510     // wl3600_todo why send redundant fields?
12511     conf->indexId = impl_req->indexId;
12512     conf->indexVersion = impl_req->indexVersion;
12513 
12514     Uint32 clientRef = op_ptr.p->m_clientRef;
12515     sendSignal(clientRef, GSN_DROP_INDX_CONF, signal,
12516                DropIndxConf::SignalLength, JBB);
12517   } else {
12518     jam();
12519     DropIndxRef* ref = (DropIndxRef*)signal->getDataPtrSend();
12520     ref->senderRef = reference();
12521     ref->clientData = op_ptr.p->m_clientData;
12522     ref->transId = trans_ptr.p->m_transId;
12523     // wl3600_todo why send redundant fields?
12524     ref->indexId = impl_req->indexId;
12525     ref->indexVersion = impl_req->indexVersion;
12526     getError(error, ref);
12527 
12528     Uint32 clientRef = op_ptr.p->m_clientRef;
12529     sendSignal(clientRef, GSN_DROP_INDX_REF, signal,
12530                DropIndxRef::SignalLength, JBB);
12531   }
12532 }
12533 
12534 // DropIndex: PREPARE
12535 
12536 void
dropIndex_prepare(Signal * signal,SchemaOpPtr op_ptr)12537 Dbdict::dropIndex_prepare(Signal* signal, SchemaOpPtr op_ptr)
12538 {
12539   DropIndexRecPtr dropIndexPtr;
12540   getOpRec(op_ptr, dropIndexPtr);
12541 
12542   D("dropIndex_prepare" << *op_ptr.p);
12543 
12544   sendTransConf(signal, op_ptr);
12545 }
12546 
12547 // DropIndex: COMMIT
12548 
12549 void
dropIndex_commit(Signal * signal,SchemaOpPtr op_ptr)12550 Dbdict::dropIndex_commit(Signal* signal, SchemaOpPtr op_ptr)
12551 {
12552   DropIndexRecPtr dropIndexPtr;
12553   getOpRec(op_ptr, dropIndexPtr);
12554 
12555   D("dropIndex_commit" << *op_ptr.p);
12556 
12557   sendTransConf(signal, op_ptr);
12558 }
12559 
12560 // DropIndex: COMPLETE
12561 
12562 void
dropIndex_complete(Signal * signal,SchemaOpPtr op_ptr)12563 Dbdict::dropIndex_complete(Signal* signal, SchemaOpPtr op_ptr)
12564 {
12565   jam();
12566   sendTransConf(signal, op_ptr);
12567 }
12568 
12569 // DropIndex: ABORT
12570 
12571 void
dropIndex_abortParse(Signal * signal,SchemaOpPtr op_ptr)12572 Dbdict::dropIndex_abortParse(Signal* signal, SchemaOpPtr op_ptr)
12573 {
12574   D("dropIndex_abortParse" << *op_ptr.p);
12575   // wl3600_todo
12576   sendTransConf(signal, op_ptr);
12577 }
12578 
12579 void
dropIndex_abortPrepare(Signal * signal,SchemaOpPtr op_ptr)12580 Dbdict::dropIndex_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
12581 {
12582   D("dropIndex_abortPrepare" << *op_ptr.p);
12583   ndbrequire(false);
12584   sendTransConf(signal, op_ptr);
12585 }
12586 
12587 void
dropIndex_toAlterIndex(Signal * signal,SchemaOpPtr op_ptr)12588 Dbdict::dropIndex_toAlterIndex(Signal* signal, SchemaOpPtr op_ptr)
12589 {
12590   D("dropIndex_toAlterIndex");
12591 
12592   AlterIndxReq* req = (AlterIndxReq*)signal->getDataPtrSend();
12593 
12594   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12595   DropIndexRecPtr dropIndexPtr;
12596   getOpRec(op_ptr, dropIndexPtr);
12597 
12598   Uint32 requestInfo = 0;
12599   DictSignal::setRequestType(requestInfo, AlterIndxImplReq::AlterIndexOffline);
12600   DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
12601 
12602   req->clientRef = reference();
12603   req->clientData = op_ptr.p->op_key;
12604   req->transId = trans_ptr.p->m_transId;
12605   req->transKey = trans_ptr.p->trans_key;
12606   req->requestInfo = requestInfo;
12607   req->indexId = dropIndexPtr.p->m_request.indexId;
12608   req->indexVersion = dropIndexPtr.p->m_request.indexVersion;
12609 
12610   sendSignal(reference(), GSN_ALTER_INDX_REQ, signal,
12611              AlterIndxReq::SignalLength, JBB);
12612 }
12613 
12614 void
dropIndex_fromAlterIndex(Signal * signal,Uint32 op_key,Uint32 ret)12615 Dbdict::dropIndex_fromAlterIndex(Signal* signal, Uint32 op_key, Uint32 ret)
12616 {
12617   jam();
12618   D("dropIndex_fromAlterIndex");
12619 
12620   SchemaOpPtr op_ptr;
12621   DropIndexRecPtr dropIndexPtr;
12622 
12623   findSchemaOp(op_ptr, dropIndexPtr, op_key);
12624   ndbrequire(!op_ptr.isNull());
12625   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12626 
12627   if (ret == 0) {
12628     const AlterIndxConf* conf =
12629       (const AlterIndxConf*)signal->getDataPtr();
12630 
12631     ndbrequire(conf->transId == trans_ptr.p->m_transId);
12632     dropIndexPtr.p->m_sub_alter_index = true;
12633     createSubOps(signal, op_ptr);
12634   } else {
12635     jam();
12636     const AlterIndxRef* ref =
12637       (const AlterIndxRef*)signal->getDataPtr();
12638 
12639     ErrorInfo error;
12640     setError(error, ref);
12641     abortSubOps(signal, op_ptr, error);
12642   }
12643 }
12644 
12645 void
dropIndex_toDropTable(Signal * signal,SchemaOpPtr op_ptr)12646 Dbdict::dropIndex_toDropTable(Signal* signal, SchemaOpPtr op_ptr)
12647 {
12648   D("dropIndex_toDropTable");
12649 
12650   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12651   DropIndexRecPtr dropIndexPtr;
12652   getOpRec(op_ptr, dropIndexPtr);
12653   const DropIndxImplReq* impl_req = &dropIndexPtr.p->m_request;
12654 
12655   DropTableReq* req = (DropTableReq*)signal->getDataPtrSend();
12656 
12657   Uint32 requestInfo = 0;
12658   DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
12659 
12660   req->clientRef = reference();
12661   req->clientData = op_ptr.p->op_key;
12662   req->transId = trans_ptr.p->m_transId;
12663   req->transKey = trans_ptr.p->trans_key;
12664   req->requestInfo = requestInfo;
12665   req->tableId = impl_req->indexId;
12666   req->tableVersion = impl_req->indexVersion;
12667   sendSignal(reference(), GSN_DROP_TABLE_REQ, signal,
12668              DropTableReq::SignalLength, JBB);
12669 }
12670 
12671 void
dropIndex_fromDropTable(Signal * signal,Uint32 op_key,Uint32 ret)12672 Dbdict::dropIndex_fromDropTable(Signal* signal, Uint32 op_key, Uint32 ret)
12673 {
12674   jam();
12675   D("dropIndex_fromDropTable" << dec << V(op_key) << V(ret));
12676 
12677   SchemaOpPtr op_ptr;
12678   DropIndexRecPtr dropIndexPtr;
12679 
12680   findSchemaOp(op_ptr, dropIndexPtr, op_key);
12681   ndbrequire(!op_ptr.isNull());
12682   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12683 
12684   if (ret == 0) {
12685     jam();
12686     const DropTableConf* conf =
12687       (const DropTableConf*)signal->getDataPtr();
12688 
12689     ndbrequire(conf->transId == trans_ptr.p->m_transId);
12690     dropIndexPtr.p->m_sub_drop_table = true;
12691     createSubOps(signal, op_ptr);
12692   } else {
12693     jam();
12694     const DropTableRef* ref =
12695       (const DropTableRef*)signal->getDataPtr();
12696     ErrorInfo error;
12697     setError(error, ref);
12698     abortSubOps(signal, op_ptr, error);
12699   }
12700 }
12701 
12702 // DropIndex: MISC
12703 
12704 void
execDROP_INDX_IMPL_CONF(Signal * signal)12705 Dbdict::execDROP_INDX_IMPL_CONF(Signal* signal)
12706 {
12707   jamEntry();
12708   const DropIndxImplConf* conf = (const DropIndxImplConf*)signal->getDataPtr();
12709   ndbrequire(refToNode(conf->senderRef) == getOwnNodeId());
12710   handleDictConf(signal, conf);
12711 }
12712 
12713 void
execDROP_INDX_IMPL_REF(Signal * signal)12714 Dbdict::execDROP_INDX_IMPL_REF(Signal* signal)
12715 {
12716   jamEntry();
12717   const DropIndxImplRef* ref = (const DropIndxImplRef*)signal->getDataPtr();
12718   ndbrequire(refToNode(ref->senderRef) == getOwnNodeId());
12719   handleDictRef(signal, ref);
12720 }
12721 
12722 // DropIndex: END
12723 
12724 // MODULE: AlterIndex
12725 
12726 const Dbdict::OpInfo
12727 Dbdict::AlterIndexRec::g_opInfo = {
12728   { 'A', 'I', 'n', 0 },
12729   ~RT_DBDICT_ALTER_INDEX,
12730   GSN_ALTER_INDX_IMPL_REQ,
12731   AlterIndxImplReq::SignalLength,
12732   //
12733   &Dbdict::alterIndex_seize,
12734   &Dbdict::alterIndex_release,
12735   //
12736   &Dbdict::alterIndex_parse,
12737   &Dbdict::alterIndex_subOps,
12738   &Dbdict::alterIndex_reply,
12739   //
12740   &Dbdict::alterIndex_prepare,
12741   &Dbdict::alterIndex_commit,
12742   &Dbdict::alterIndex_complete,
12743   //
12744   &Dbdict::alterIndex_abortParse,
12745   &Dbdict::alterIndex_abortPrepare
12746 };
12747 
12748 bool
alterIndex_seize(SchemaOpPtr op_ptr)12749 Dbdict::alterIndex_seize(SchemaOpPtr op_ptr)
12750 {
12751   return seizeOpRec<AlterIndexRec>(op_ptr);
12752 }
12753 
12754 void
alterIndex_release(SchemaOpPtr op_ptr)12755 Dbdict::alterIndex_release(SchemaOpPtr op_ptr)
12756 {
12757   releaseOpRec<AlterIndexRec>(op_ptr);
12758 }
12759 
12760 void
execALTER_INDX_REQ(Signal * signal)12761 Dbdict::execALTER_INDX_REQ(Signal* signal)
12762 {
12763   jamEntry();
12764   if (!assembleFragments(signal)) {
12765     jam();
12766     return;
12767   }
12768   SectionHandle handle(this, signal);
12769 
12770   const AlterIndxReq req_copy =
12771     *(const AlterIndxReq*)signal->getDataPtr();
12772   const AlterIndxReq* req = &req_copy;
12773 
12774   ErrorInfo error;
12775   do {
12776     SchemaOpPtr op_ptr;
12777     AlterIndexRecPtr alterIndexPtr;
12778     AlterIndxImplReq* impl_req;
12779 
12780     startClientReq(op_ptr, alterIndexPtr, req, impl_req, error);
12781     if (hasError(error)) {
12782       jam();
12783       break;
12784     }
12785 
12786     impl_req->tableId = RNIL;    // wl3600_todo fill in in parse
12787     impl_req->tableVersion = 0;
12788     impl_req->indexId = req->indexId;
12789     impl_req->indexVersion = req->indexVersion;
12790     impl_req->indexType = 0; // fill in parse
12791 
12792     handleClientReq(signal, op_ptr, handle);
12793     return;
12794   } while (0);
12795 
12796   releaseSections(handle);
12797 
12798   AlterIndxRef* ref = (AlterIndxRef*)signal->getDataPtrSend();
12799   ref->senderRef = reference();
12800   ref->clientData = req->clientData;
12801   ref->transId = req->transId;
12802   ref->indexId = req->indexId;
12803   ref->indexVersion = req->indexVersion;
12804   getError(error, ref);
12805 
12806   sendSignal(req->clientRef, GSN_ALTER_INDX_REF, signal,
12807              AlterIndxRef::SignalLength, JBB);
12808 }
12809 
12810 const Dbdict::TriggerTmpl
12811 Dbdict::g_hashIndexTriggerTmpl[1] = {
12812   { "NDB$INDEX_%u_UI",
12813     {
12814       TriggerType::SECONDARY_INDEX,
12815       TriggerActionTime::TA_AFTER,
12816       TriggerEvent::TE_CUSTOM,
12817       false, false, true // monitor replicas, monitor all, report all
12818     }
12819   }
12820 };
12821 
12822 const Dbdict::TriggerTmpl
12823 Dbdict::g_orderedIndexTriggerTmpl[1] = {
12824   { "NDB$INDEX_%u_CUSTOM",
12825     {
12826       TriggerType::ORDERED_INDEX,
12827       TriggerActionTime::TA_CUSTOM,
12828       TriggerEvent::TE_CUSTOM,
12829       true, false, true
12830     }
12831   }
12832 };
12833 
12834 const Dbdict::TriggerTmpl
12835 Dbdict::g_buildIndexConstraintTmpl[1] = {
12836   { "NDB$INDEX_%u_BUILD",
12837     {
12838       TriggerType::READ_ONLY_CONSTRAINT,
12839       TriggerActionTime::TA_AFTER,
12840       TriggerEvent::TE_UPDATE,
12841       false, true, false
12842     }
12843   }
12844 };
12845 
12846 const Dbdict::TriggerTmpl
12847 Dbdict::g_reorgTriggerTmpl[1] = {
12848   { "NDB$REORG_%u",
12849     {
12850       TriggerType::REORG_TRIGGER,
12851       TriggerActionTime::TA_AFTER,
12852       TriggerEvent::TE_CUSTOM,
12853       false, true, false
12854     }
12855   }
12856 };
12857 
12858 const Dbdict::TriggerTmpl
12859 Dbdict::g_fkTriggerTmpl[2] = {
12860   { "NDB$FK_%u_PARENT_%u",
12861     {
12862       TriggerType::FK_PARENT,
12863       TriggerActionTime::TA_AFTER,
12864       TriggerEvent::TE_CUSTOM,
12865       false, false, true // monitor replicas, monitor all, report all
12866     }
12867   },
12868 
12869   { "NDB$FK_%u_CHILD_%u",
12870     {
12871       TriggerType::FK_CHILD,
12872       TriggerActionTime::TA_AFTER,
12873       TriggerEvent::TE_CUSTOM,
12874       false, false, true // monitor replicas, monitor all, report all
12875     }
12876   }
12877 };
12878 
12879 // AlterIndex: PARSE
12880 
12881 void
alterIndex_parse(Signal * signal,bool master,SchemaOpPtr op_ptr,SectionHandle & handle,ErrorInfo & error)12882 Dbdict::alterIndex_parse(Signal* signal, bool master,
12883                          SchemaOpPtr op_ptr,
12884                          SectionHandle& handle, ErrorInfo& error)
12885 {
12886   D("alterIndex_parse" << V(op_ptr.i) << *op_ptr.p);
12887 
12888   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12889   AlterIndexRecPtr alterIndexPtr;
12890   getOpRec(op_ptr, alterIndexPtr);
12891   AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
12892 
12893   TableRecordPtr indexPtr;
12894   if (!(impl_req->indexId < c_noOfMetaTables)) {
12895     jam();
12896     setError(error, AlterIndxRef::IndexNotFound, __LINE__);
12897     return;
12898   }
12899   if (check_read_obj(impl_req->indexId, trans_ptr.p->m_transId) == GetTabInfoRef::TableNotDefined)
12900   {
12901     jam();
12902     setError(error, GetTabInfoRef::TableNotDefined, __LINE__);
12903     return;
12904   }
12905   jam();
12906 
12907   bool ok = find_object(indexPtr, impl_req->indexId);
12908   if (!ok)
12909   {
12910     jam();
12911     setError(error, GetTabInfoRef::TableNotDefined, __LINE__);
12912     return;
12913   }
12914 
12915   // get name for system index check later
12916   char indexName[MAX_TAB_NAME_SIZE];
12917   memset(indexName, 0, sizeof(indexName));
12918   {
12919     ConstRope r(c_rope_pool, indexPtr.p->tableName);
12920     r.copy(indexName);
12921   }
12922   D("index " << indexName);
12923 
12924   if (indexPtr.p->tableVersion != impl_req->indexVersion) {
12925     jam();
12926     setError(error, AlterIndxRef::InvalidIndexVersion, __LINE__);
12927     return;
12928   }
12929 
12930   if (check_write_obj(impl_req->indexId, trans_ptr.p->m_transId,
12931                       SchemaFile::SF_ALTER, error))
12932   {
12933     jam();
12934     return;
12935   }
12936 
12937   // check it is an index and set trigger info for sub-ops
12938   switch (indexPtr.p->tableType) {
12939   case DictTabInfo::UniqueHashIndex:
12940     jam();
12941     alterIndexPtr.p->m_triggerTmpl = g_hashIndexTriggerTmpl;
12942     break;
12943   case DictTabInfo::OrderedIndex:
12944     jam();
12945     alterIndexPtr.p->m_triggerTmpl = g_orderedIndexTriggerTmpl;
12946     break;
12947   default:
12948     jam();
12949     setError(error, AlterIndxRef::NotAnIndex, __LINE__);
12950     return;
12951   }
12952 
12953   if (master)
12954   {
12955     jam();
12956     impl_req->indexType = indexPtr.p->tableType;
12957   }
12958   else
12959   {
12960     jam();
12961     ndbrequire(impl_req->indexType == (Uint32)indexPtr.p->tableType);
12962   }
12963 
12964   ndbrequire(indexPtr.p->primaryTableId != RNIL);
12965   TableRecordPtr tablePtr;
12966   ok = find_object(tablePtr, indexPtr.p->primaryTableId);
12967   ndbrequire(ok); // TODO:msundell set error
12968 
12969   // master sets primary table, participant verifies it agrees
12970   if (master)
12971   {
12972     jam();
12973     impl_req->tableId = tablePtr.p->tableId;
12974     impl_req->tableVersion = tablePtr.p->tableVersion;
12975   }
12976   else
12977   {
12978     if (impl_req->tableId != tablePtr.p->tableId)
12979     {
12980       jam(); // wl3600_todo better error code
12981       setError(error, AlterIndxRef::InvalidIndexVersion, __LINE__);
12982       return;
12983     }
12984     if (impl_req->tableVersion != tablePtr.p->tableVersion)
12985     {
12986       jam(); // wl3600_todo better error code
12987       setError(error, AlterIndxRef::InvalidIndexVersion, __LINE__);
12988       return;
12989     }
12990   }
12991 
12992   // check request type
12993   Uint32 requestType = impl_req->requestType;
12994   switch (requestType) {
12995   case AlterIndxImplReq::AlterIndexOnline:
12996     jam();
12997     indexPtr.p->indexState = TableRecord::IS_BUILDING;
12998     break;
12999   case AlterIndxImplReq::AlterIndexOffline:
13000     jam();
13001     indexPtr.p->indexState = TableRecord::IS_DROPPING;
13002     break;
13003   case AlterIndxImplReq::AlterIndexAddPartition:
13004     jam();
13005     if (indexPtr.p->tableType == DictTabInfo::OrderedIndex)
13006     {
13007       jam();
13008       /**
13009        * Link operation to AlterTable
13010        *   either if prev op is AlterTable using baseop.i
13011        *       or if prev op is AlterIndex using baseop.p->m_base_op_ptr_i
13012        *   (i.e recursivly, assuming that no operation can come inbetween)
13013        */
13014       SchemaOpPtr baseop = op_ptr;
13015       LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
13016       ndbrequire(list.prev(baseop));
13017       Uint32 sz = sizeof(baseop.p->m_oprec_ptr.p->m_opType);
13018       const char * opType = baseop.p->m_oprec_ptr.p->m_opType;
13019       if (memcmp(opType, AlterTableRec::g_opInfo.m_opType, sz) == 0)
13020       {
13021         jam();
13022         op_ptr.p->m_base_op_ptr_i = baseop.i;
13023       }
13024       else
13025       {
13026         jam();
13027         ndbrequire(memcmp(opType, AlterIndexRec::g_opInfo.m_opType, sz) == 0);
13028         op_ptr.p->m_base_op_ptr_i = baseop.p->m_base_op_ptr_i;
13029       }
13030       break;
13031     }
13032     // else invalid request type
13033   default:
13034     ndbassert(false);
13035     setError(error, AlterIndxRef::BadRequestType, __LINE__);
13036     return;
13037   }
13038 
13039   // set attribute mask (of primary table attribute ids)
13040   getIndexAttrMask(indexPtr, alterIndexPtr.p->m_attrMask);
13041 
13042   // ordered index stats
13043   if (indexPtr.p->tableType == DictTabInfo::OrderedIndex) {
13044     jam();
13045 
13046     // always compute monitored replica
13047     if (requestType == AlterIndxImplReq::AlterIndexOnline) {
13048       jam();
13049       set_index_stat_frag(signal, indexPtr);
13050     }
13051 
13052     // skip system indexes (at least index stats indexes)
13053     if (strstr(indexName, "/" NDB_INDEX_STAT_PREFIX) != 0) {
13054       jam();
13055       D("skip index stats operations for system index");
13056       alterIndexPtr.p->m_sub_index_stat_dml = true;
13057       alterIndexPtr.p->m_sub_index_stat_mon = true;
13058     }
13059 
13060     // disable update/delete if db not up
13061     if (getNodeState().startLevel != NodeState::SL_STARTED &&
13062         getNodeState().startLevel != NodeState::SL_SINGLEUSER) {
13063       jam();
13064       alterIndexPtr.p->m_sub_index_stat_dml = true;
13065     }
13066 
13067     // disable update on create if not auto
13068     if (requestType == AlterIndxImplReq::AlterIndexOnline &&
13069         !c_indexStatAutoCreate) {
13070       jam();
13071       alterIndexPtr.p->m_sub_index_stat_dml = true;
13072     }
13073 
13074     // always delete on drop because manual update may have been done
13075     if (requestType == AlterIndxImplReq::AlterIndexOffline) {
13076       jam();
13077     }
13078 
13079     // always assign/remove monitored replica in TUX instances
13080   }
13081 
13082   if (ERROR_INSERTED(6123)) {
13083     jam();
13084     CLEAR_ERROR_INSERT_VALUE;
13085     setError(error, 9123, __LINE__);
13086     return;
13087   }
13088 }
13089 
13090 void
set_index_stat_frag(Signal * signal,TableRecordPtr indexPtr)13091 Dbdict::set_index_stat_frag(Signal* signal, TableRecordPtr indexPtr)
13092 {
13093   jam();
13094   DictObjectPtr index_obj_ptr;
13095   c_obj_pool.getPtr(index_obj_ptr, indexPtr.p->m_obj_ptr_i);
13096   const Uint32 indexId = index_obj_ptr.p->m_id;
13097   Uint32 err = get_fragmentation(signal, indexId);
13098   ndbrequire(err == 0);
13099   // format: R F { fragId node1 .. nodeR } x { F }
13100   // fragId: 0 1 2 .. (or whatever)
13101   const Uint16* frag_data = (Uint16*)(signal->theData+25);
13102   const Uint32 noOfFragments = frag_data[1];
13103   const Uint32 noOfReplicas = frag_data[0];
13104   ndbrequire(noOfFragments != 0 && noOfReplicas != 0);
13105 
13106   // distribute by table and index id
13107   const Uint32 value = indexPtr.p->primaryTableId + indexId;
13108   const Uint32 fragId = value % noOfFragments;
13109   const Uint32 fragIndex = 2 + (1 + noOfReplicas) * fragId;
13110   const Uint32 nodeIndex = value % noOfReplicas;
13111 
13112   indexPtr.p->indexStatFragId = fragId;
13113   bzero(indexPtr.p->indexStatNodes, sizeof(indexPtr.p->indexStatNodes));
13114   for (Uint32 i = 0; i < noOfReplicas; i++)
13115   {
13116     Uint32 idx = fragIndex + 1 + (nodeIndex + i) % noOfReplicas;
13117     indexPtr.p->indexStatNodes[i] = frag_data[idx];
13118   }
13119   D("set_index_stat_frag" << V(indexId) << V(fragId)
13120     << V(indexPtr.p->indexStatNodes[0]));
13121 }
13122 
13123 bool
alterIndex_subOps(Signal * signal,SchemaOpPtr op_ptr)13124 Dbdict::alterIndex_subOps(Signal* signal, SchemaOpPtr op_ptr)
13125 {
13126   D("alterIndex_subOps" << V(op_ptr.i) << *op_ptr.p);
13127 
13128   AlterIndexRecPtr alterIndexPtr;
13129   getOpRec(op_ptr, alterIndexPtr);
13130   const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
13131   Uint32 requestType = impl_req->requestType;
13132 
13133   // ops to create or drop triggers
13134   if (alterIndexPtr.p->m_sub_trigger == false)
13135   {
13136     jam();
13137     alterIndexPtr.p->m_sub_trigger = true;
13138     switch (requestType) {
13139     case AlterIndxImplReq::AlterIndexOnline:
13140       jam();
13141       {
13142         Callback c = {
13143           safe_cast(&Dbdict::alterIndex_fromCreateTrigger),
13144           op_ptr.p->op_key
13145         };
13146         op_ptr.p->m_callback = c;
13147         alterIndex_toCreateTrigger(signal, op_ptr);
13148       }
13149       break;
13150     case AlterIndxImplReq::AlterIndexOffline:
13151       jam();
13152       {
13153         Callback c = {
13154           safe_cast(&Dbdict::alterIndex_fromDropTrigger),
13155           op_ptr.p->op_key
13156         };
13157         op_ptr.p->m_callback = c;
13158         alterIndex_toDropTrigger(signal, op_ptr);
13159       }
13160       break;
13161     case AlterIndxImplReq::AlterIndexAddPartition:
13162       jam();
13163       return false;
13164     default:
13165       ndbrequire(false);
13166       break;
13167     }
13168     return true;
13169   }
13170 
13171   if (requestType == AlterIndxImplReq::AlterIndexOnline &&
13172       !alterIndexPtr.p->m_sub_build_index) {
13173     jam();
13174     Callback c = {
13175       safe_cast(&Dbdict::alterIndex_fromBuildIndex),
13176       op_ptr.p->op_key
13177     };
13178     op_ptr.p->m_callback = c;
13179     alterIndex_toBuildIndex(signal, op_ptr);
13180     return true;
13181   }
13182 
13183   TableRecordPtr indexPtr;
13184   bool ok = find_object(indexPtr, impl_req->indexId);
13185 
13186   if (ok && indexPtr.p->isOrderedIndex() &&
13187       (!alterIndexPtr.p->m_sub_index_stat_dml ||
13188        !alterIndexPtr.p->m_sub_index_stat_mon)) {
13189     jam();
13190     Callback c = {
13191       safe_cast(&Dbdict::alterIndex_fromIndexStat),
13192       op_ptr.p->op_key
13193     };
13194     op_ptr.p->m_callback = c;
13195     alterIndex_toIndexStat(signal, op_ptr);
13196     return true;
13197   }
13198 
13199   return false;
13200 }
13201 
13202 void
alterIndex_toCreateTrigger(Signal * signal,SchemaOpPtr op_ptr)13203 Dbdict::alterIndex_toCreateTrigger(Signal* signal, SchemaOpPtr op_ptr)
13204 {
13205   D("alterIndex_toCreateTrigger");
13206 
13207   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
13208   AlterIndexRecPtr alterIndexPtr;
13209   getOpRec(op_ptr, alterIndexPtr);
13210   const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
13211   TableRecordPtr indexPtr;
13212   bool ok = find_object(indexPtr, impl_req->indexId);
13213   ndbrequire(ok);
13214 
13215   const TriggerTmpl& triggerTmpl = alterIndexPtr.p->m_triggerTmpl[0];
13216 
13217   CreateTrigReq* req = (CreateTrigReq*)signal->getDataPtrSend();
13218 
13219   Uint32 requestInfo = 0;
13220   DictSignal::setRequestType(requestInfo, CreateTrigReq::CreateTriggerOnline);
13221   DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
13222 
13223   req->clientRef = reference();
13224   req->clientData = op_ptr.p->op_key;
13225   req->transId = trans_ptr.p->m_transId;
13226   req->transKey = trans_ptr.p->trans_key;
13227   req->requestInfo = requestInfo;
13228   req->tableId = impl_req->tableId;
13229   req->tableVersion = impl_req->tableVersion;
13230   req->indexId = impl_req->indexId;
13231   req->indexVersion = impl_req->indexVersion;
13232   req->triggerNo = 0;
13233 
13234   Uint32 forceTriggerId = indexPtr.p->triggerId;
13235   D(V(getNodeState().startLevel) << V(NodeState::SL_STARTED));
13236   if (getNodeState().startLevel == NodeState::SL_STARTED)
13237   {
13238     ndbrequire(forceTriggerId == RNIL);
13239   }
13240   req->forceTriggerId = forceTriggerId;
13241 
13242   TriggerInfo::packTriggerInfo(req->triggerInfo, triggerTmpl.triggerInfo);
13243 
13244   req->receiverRef = 0;
13245 
13246   char triggerName[MAX_TAB_NAME_SIZE];
13247   sprintf(triggerName, triggerTmpl.nameFormat, impl_req->indexId);
13248 
13249   // name section
13250   Uint32 buffer[2 + ((MAX_TAB_NAME_SIZE + 3) >> 2)];    // SP string
13251   LinearWriter w(buffer, sizeof(buffer) >> 2);
13252   w.reset();
13253   w.add(DictTabInfo::TableName, triggerName);
13254   LinearSectionPtr lsPtr[3];
13255   lsPtr[0].p = buffer;
13256   lsPtr[0].sz = w.getWordsUsed();
13257 
13258   lsPtr[1].p = alterIndexPtr.p->m_attrMask.rep.data;
13259   lsPtr[1].sz = alterIndexPtr.p->m_attrMask.getSizeInWords();
13260 
13261   sendSignal(reference(), GSN_CREATE_TRIG_REQ, signal,
13262              CreateTrigReq::SignalLength, JBB, lsPtr, 2);
13263 }
13264 
13265 void
alterIndex_fromCreateTrigger(Signal * signal,Uint32 op_key,Uint32 ret)13266 Dbdict::alterIndex_fromCreateTrigger(Signal* signal, Uint32 op_key, Uint32 ret)
13267 {
13268   jam();
13269 
13270   SchemaOpPtr op_ptr;
13271   AlterIndexRecPtr alterIndexPtr;
13272 
13273   findSchemaOp(op_ptr, alterIndexPtr, op_key);
13274   ndbrequire(!op_ptr.isNull());
13275   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
13276   //const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
13277 
13278   D("alterIndex_fromCreateTrigger" << dec << V(op_key) << V(ret));
13279 
13280   if (ret == 0) {
13281     jam();
13282     const CreateTrigConf* conf =
13283       (const CreateTrigConf*)signal->getDataPtr();
13284 
13285     ndbrequire(conf->transId == trans_ptr.p->m_transId);
13286     createSubOps(signal, op_ptr);
13287   } else {
13288     const CreateTrigRef* ref =
13289       (const CreateTrigRef*)signal->getDataPtr();
13290     ErrorInfo error;
13291     setError(error, ref);
13292     abortSubOps(signal, op_ptr, error);
13293   }
13294 }
13295 
13296 void
alterIndex_toDropTrigger(Signal * signal,SchemaOpPtr op_ptr)13297 Dbdict::alterIndex_toDropTrigger(Signal* signal, SchemaOpPtr op_ptr)
13298 {
13299   D("alterIndex_toDropTrigger");
13300 
13301   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
13302   AlterIndexRecPtr alterIndexPtr;
13303   getOpRec(op_ptr, alterIndexPtr);
13304   const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
13305 
13306   TableRecordPtr indexPtr;
13307   bool ok = find_object(indexPtr, impl_req->indexId);
13308   ndbrequire(ok);
13309 
13310   //const TriggerTmpl& triggerTmpl = alterIndexPtr.p->m_triggerTmpl[0];
13311 
13312   DropTrigReq* req = (DropTrigReq*)signal->getDataPtrSend();
13313 
13314   Uint32 requestInfo = 0;
13315   DictSignal::setRequestType(requestInfo, 0);
13316   DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
13317 
13318   req->clientRef = reference();
13319   req->clientData = op_ptr.p->op_key;
13320   req->transId = trans_ptr.p->m_transId;
13321   req->transKey = trans_ptr.p->trans_key;
13322   req->requestInfo = requestInfo;
13323   req->tableId = impl_req->tableId;
13324   req->tableVersion = impl_req->tableVersion;
13325   req->indexId = impl_req->indexId;
13326   req->indexVersion = impl_req->indexVersion;
13327   req->triggerNo = 0;
13328   req->triggerId = indexPtr.p->triggerId;
13329 
13330   sendSignal(reference(), GSN_DROP_TRIG_REQ, signal,
13331              DropTrigReq::SignalLength, JBB);
13332 }
13333 
13334 void
alterIndex_fromDropTrigger(Signal * signal,Uint32 op_key,Uint32 ret)13335 Dbdict::alterIndex_fromDropTrigger(Signal* signal, Uint32 op_key, Uint32 ret)
13336 {
13337   jam();
13338 
13339   SchemaOpPtr op_ptr;
13340   AlterIndexRecPtr alterIndexPtr;
13341 
13342   findSchemaOp(op_ptr, alterIndexPtr, op_key);
13343   ndbrequire(!op_ptr.isNull());
13344   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
13345   //const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
13346 
13347   D("alterIndex_fromDropTrigger" << dec << V(op_key) << V(ret));
13348 
13349   if (ret == 0) {
13350     const DropTrigConf* conf =
13351       (const DropTrigConf*)signal->getDataPtr();
13352 
13353     ndbrequire(conf->transId == trans_ptr.p->m_transId);
13354     createSubOps(signal, op_ptr);
13355   } else {
13356     jam();
13357     const DropTrigRef* ref =
13358       (const DropTrigRef*)signal->getDataPtr();
13359     ErrorInfo error;
13360     setError(error, ref);
13361     abortSubOps(signal, op_ptr, error);
13362   }
13363 }
13364 
13365 void
alterIndex_toBuildIndex(Signal * signal,SchemaOpPtr op_ptr)13366 Dbdict::alterIndex_toBuildIndex(Signal* signal, SchemaOpPtr op_ptr)
13367 {
13368   D("alterIndex_toBuildIndex");
13369 
13370   BuildIndxReq* req = (BuildIndxReq*)signal->getDataPtrSend();
13371 
13372   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
13373   AlterIndexRecPtr alterIndexPtr;
13374   getOpRec(op_ptr, alterIndexPtr);
13375   const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
13376 
13377   Uint32 requestInfo = 0;
13378   DictSignal::setRequestType(requestInfo, BuildIndxReq::MainOp);
13379   DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
13380 
13381   if (op_ptr.p->m_requestInfo & AlterIndxReq::RF_BUILD_OFFLINE)
13382   {
13383     jam();
13384     requestInfo |= BuildIndxReq::RF_BUILD_OFFLINE;
13385   }
13386 
13387   req->clientRef = reference();
13388   req->clientData = op_ptr.p->op_key;
13389   req->transId = trans_ptr.p->m_transId;
13390   req->transKey = trans_ptr.p->trans_key;
13391   req->requestInfo = requestInfo;
13392   req->buildId = 0; // not used
13393   req->buildKey = 0; // not used
13394   req->tableId = impl_req->tableId;
13395   req->indexId = impl_req->indexId;
13396   req->indexType = impl_req->indexType;
13397   req->parallelism = 16;
13398 
13399   sendSignal(reference(), GSN_BUILDINDXREQ, signal,
13400              BuildIndxReq::SignalLength, JBB);
13401 }
13402 
13403 void
alterIndex_fromBuildIndex(Signal * signal,Uint32 op_key,Uint32 ret)13404 Dbdict::alterIndex_fromBuildIndex(Signal* signal, Uint32 op_key, Uint32 ret)
13405 {
13406   jam();
13407   D("alterIndex_fromBuildIndex");
13408 
13409   SchemaOpPtr op_ptr;
13410   AlterIndexRecPtr alterIndexPtr;
13411 
13412   findSchemaOp(op_ptr, alterIndexPtr, op_key);
13413   ndbrequire(!op_ptr.isNull());
13414   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
13415 
13416   if (ret == 0) {
13417     jam();
13418     const BuildIndxConf* conf =
13419       (const BuildIndxConf*)signal->getDataPtr();
13420 
13421     ndbrequire(conf->transId == trans_ptr.p->m_transId);
13422     alterIndexPtr.p->m_sub_build_index = true;
13423     createSubOps(signal, op_ptr);
13424   } else {
13425     jam();
13426     const BuildIndxRef* ref =
13427       (const BuildIndxRef*)signal->getDataPtr();
13428 
13429     ErrorInfo error;
13430     setError(error, ref);
13431     abortSubOps(signal, op_ptr, error);
13432   }
13433 }
13434 
13435 void
alterIndex_toIndexStat(Signal * signal,SchemaOpPtr op_ptr)13436 Dbdict::alterIndex_toIndexStat(Signal* signal, SchemaOpPtr op_ptr)
13437 {
13438   D("alterIndex_toIndexStat");
13439 
13440   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
13441   AlterIndexRecPtr alterIndexPtr;
13442   getOpRec(op_ptr, alterIndexPtr);
13443   const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
13444 
13445   IndexStatReq* req = (IndexStatReq*)signal->getDataPtrSend();
13446 
13447   Uint32 requestType = 0;
13448   switch (impl_req->requestType) {
13449   case AlterIndxImplReq::AlterIndexOnline:
13450     if (!alterIndexPtr.p->m_sub_index_stat_dml)
13451       requestType = IndexStatReq::RT_UPDATE_STAT;
13452     else
13453       requestType = IndexStatReq::RT_START_MON;
13454     break;
13455   case AlterIndxImplReq::AlterIndexOffline:
13456     if (!alterIndexPtr.p->m_sub_index_stat_dml)
13457       requestType = IndexStatReq::RT_DELETE_STAT;
13458     else
13459       requestType = IndexStatReq::RT_STOP_MON;
13460     break;
13461   default:
13462     ndbrequire(false);
13463     break;
13464   }
13465 
13466   Uint32 requestInfo = 0;
13467   DictSignal::setRequestType(requestInfo, requestType);
13468   DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
13469 
13470   TableRecordPtr indexPtr;
13471   bool ok = find_object(indexPtr, impl_req->indexId);
13472   ndbrequire(ok);
13473 
13474   req->clientRef = reference();
13475   req->clientData = op_ptr.p->op_key;
13476   req->transId = trans_ptr.p->m_transId;
13477   req->transKey = trans_ptr.p->trans_key;
13478   req->requestInfo = requestInfo;
13479   req->requestFlag = 0;
13480   req->indexId = impl_req->indexId;
13481   req->indexVersion = indexPtr.p->tableVersion;
13482   req->tableId = impl_req->tableId;
13483 
13484   sendSignal(reference(), GSN_INDEX_STAT_REQ,
13485              signal, IndexStatReq::SignalLength, JBB);
13486 }
13487 
13488 void
alterIndex_fromIndexStat(Signal * signal,Uint32 op_key,Uint32 ret)13489 Dbdict::alterIndex_fromIndexStat(Signal* signal, Uint32 op_key, Uint32 ret)
13490 {
13491   jam();
13492   D("alterIndex_fromIndexStat");
13493 
13494   SchemaOpPtr op_ptr;
13495   AlterIndexRecPtr alterIndexPtr;
13496 
13497   findSchemaOp(op_ptr, alterIndexPtr, op_key);
13498   ndbrequire(!op_ptr.isNull());
13499   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
13500 
13501   if (ret == 0) {
13502     jam();
13503     const IndexStatConf* conf =
13504       (const IndexStatConf*)signal->getDataPtr();
13505 
13506     ndbrequire(conf->transId == trans_ptr.p->m_transId);
13507     ndbrequire(!alterIndexPtr.p->m_sub_index_stat_dml ||
13508                !alterIndexPtr.p->m_sub_index_stat_mon);
13509     alterIndexPtr.p->m_sub_index_stat_dml = true;
13510     alterIndexPtr.p->m_sub_index_stat_mon = true;
13511     createSubOps(signal, op_ptr);
13512   } else {
13513     jam();
13514     const IndexStatRef* ref =
13515       (const IndexStatRef*)signal->getDataPtr();
13516 
13517     ErrorInfo error;
13518     setError(error, ref);
13519     abortSubOps(signal, op_ptr, error);
13520   }
13521 }
13522 
13523 void
alterIndex_reply(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)13524 Dbdict::alterIndex_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
13525 {
13526   D("alterIndex_reply" << V(op_ptr.i) << *op_ptr.p);
13527 
13528   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
13529 
13530   AlterIndexRecPtr alterIndexPtr;
13531   getOpRec(op_ptr, alterIndexPtr);
13532   const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
13533 
13534   if (!hasError(error)) {
13535     AlterIndxConf* conf = (AlterIndxConf*)signal->getDataPtrSend();
13536     conf->senderRef = reference();
13537     conf->clientData = op_ptr.p->m_clientData;
13538     conf->transId = trans_ptr.p->m_transId;
13539     conf->indexId = impl_req->indexId;
13540     conf->indexVersion = impl_req->indexVersion;
13541 
13542     Uint32 clientRef = op_ptr.p->m_clientRef;
13543     sendSignal(clientRef, GSN_ALTER_INDX_CONF,
13544                signal, AlterIndxConf::SignalLength, JBB);
13545   } else {
13546     jam();
13547     AlterIndxRef* ref = (AlterIndxRef*)signal->getDataPtrSend();
13548     ref->senderRef = reference();
13549     ref->clientData = op_ptr.p->m_clientData;
13550     ref->transId = trans_ptr.p->m_transId;
13551     // wl3600_todo requestType (fix all at once)
13552     // wl3600_todo next 2 redundant (fix all at once)
13553     ref->indexId = impl_req->indexId;
13554     ref->indexVersion = impl_req->indexVersion;
13555     getError(error, ref);
13556 
13557     Uint32 clientRef = op_ptr.p->m_clientRef;
13558     sendSignal(clientRef, GSN_ALTER_INDX_REF,
13559                signal, AlterIndxRef::SignalLength, JBB);
13560   }
13561 }
13562 
13563 // AlterIndex: PREPARE
13564 
13565 void
alterIndex_prepare(Signal * signal,SchemaOpPtr op_ptr)13566 Dbdict::alterIndex_prepare(Signal* signal, SchemaOpPtr op_ptr)
13567 {
13568   AlterIndexRecPtr alterIndexPtr;
13569   getOpRec(op_ptr, alterIndexPtr);
13570   const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
13571   Uint32 requestType = impl_req->requestType;
13572 
13573   TableRecordPtr indexPtr;
13574   bool ok = find_object(indexPtr, impl_req->indexId);
13575   ndbrequire(ok);
13576 
13577   D("alterIndex_prepare" << *op_ptr.p);
13578 
13579   /*
13580    * Create table creates index table in all blocks.  DBTC has
13581    * an additional entry for hash index.  It is created (offline)
13582    * and dropped here.  wl3600_todo redesign
13583    */
13584 
13585   switch (indexPtr.p->tableType) {
13586   case DictTabInfo::UniqueHashIndex:
13587     {
13588       Callback c = {
13589         safe_cast(&Dbdict::alterIndex_fromLocal),
13590         op_ptr.p->op_key
13591       };
13592       op_ptr.p->m_callback = c;
13593 
13594       switch (requestType) {
13595       case AlterIndxImplReq::AlterIndexOnline:
13596         alterIndex_toCreateLocal(signal, op_ptr);
13597         break;
13598       case AlterIndxImplReq::AlterIndexOffline:
13599         /**
13600          * Defer to complete (e.g after triggers has been dropped)
13601          */
13602         sendTransConf(signal, op_ptr);
13603         break;
13604       default:
13605         ndbrequire(false);
13606         break;
13607       }
13608     }
13609     break;
13610   case DictTabInfo::OrderedIndex:
13611     if (requestType == AlterIndxImplReq::AlterIndexAddPartition)
13612     {
13613       jam();
13614       Callback c = {
13615         safe_cast(&Dbdict::alterIndex_fromAddPartitions),
13616         op_ptr.p->op_key
13617       };
13618       op_ptr.p->m_callback = c;
13619       alterIndex_toAddPartitions(signal, op_ptr);
13620       return;
13621     }
13622     sendTransConf(signal, op_ptr);
13623     break;
13624   default:
13625     ndbrequire(false);
13626     break;
13627   }
13628 }
13629 
13630 void
alterIndex_toCreateLocal(Signal * signal,SchemaOpPtr op_ptr)13631 Dbdict::alterIndex_toCreateLocal(Signal* signal, SchemaOpPtr op_ptr)
13632 {
13633   AlterIndexRecPtr alterIndexPtr;
13634   getOpRec(op_ptr, alterIndexPtr);
13635   const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
13636 
13637   TableRecordPtr indexPtr;
13638   bool ok = find_object(indexPtr, impl_req->indexId);
13639   ndbrequire(ok);
13640 
13641   D("alterIndex_toCreateLocal" << *op_ptr.p);
13642 
13643   CreateIndxImplReq* req = (CreateIndxImplReq*)signal->getDataPtrSend();
13644 
13645   req->senderRef = reference();
13646   req->senderData = op_ptr.p->op_key;
13647   req->requestType = 0;
13648   req->tableId = impl_req->tableId;
13649   req->tableVersion = 0; // not used
13650   req->indexType = indexPtr.p->tableType;
13651   req->indexId = impl_req->indexId;
13652   req->indexVersion = 0; // not used
13653 
13654   // attribute list
13655   getIndexAttrList(indexPtr, alterIndexPtr.p->m_attrList);
13656   LinearSectionPtr ls_ptr[3];
13657   ls_ptr[0].p = (Uint32*)&alterIndexPtr.p->m_attrList;
13658   ls_ptr[0].sz = 1 + alterIndexPtr.p->m_attrList.sz;
13659 
13660   BlockReference ref = DBTC_REF;
13661   sendSignal(ref, GSN_CREATE_INDX_IMPL_REQ, signal,
13662              CreateIndxImplReq::SignalLength, JBB, ls_ptr, 1);
13663 }
13664 
13665 void
alterIndex_toDropLocal(Signal * signal,SchemaOpPtr op_ptr)13666 Dbdict::alterIndex_toDropLocal(Signal* signal, SchemaOpPtr op_ptr)
13667 {
13668   AlterIndexRecPtr alterIndexPtr;
13669   getOpRec(op_ptr, alterIndexPtr);
13670   const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
13671 
13672   D("alterIndex_toDropLocal" << *op_ptr.p);
13673 
13674   DropIndxImplReq* req = (DropIndxImplReq*)signal->getDataPtrSend();
13675 
13676   req->senderRef = reference();
13677   req->senderData = op_ptr.p->op_key;
13678   req->tableId = impl_req->tableId;
13679   req->tableVersion = 0; // not used
13680   req->indexId = impl_req->indexId;
13681   req->indexVersion = 0; // not used
13682 
13683   BlockReference ref = DBTC_REF;
13684   sendSignal(ref, GSN_DROP_INDX_IMPL_REQ, signal,
13685              DropIndxImplReq::SignalLength, JBB);
13686 }
13687 
13688 void
alterIndex_fromLocal(Signal * signal,Uint32 op_key,Uint32 ret)13689 Dbdict::alterIndex_fromLocal(Signal* signal, Uint32 op_key, Uint32 ret)
13690 {
13691   SchemaOpPtr op_ptr;
13692   AlterIndexRecPtr alterIndexPtr;
13693   findSchemaOp(op_ptr, alterIndexPtr, op_key);
13694   ndbrequire(!op_ptr.isNull());
13695 
13696   D("alterIndex_fromLocal" << *op_ptr.p << V(ret));
13697 
13698   if (ret == 0) {
13699     jam();
13700     alterIndexPtr.p->m_tc_index_done = true;
13701     sendTransConf(signal, op_ptr);
13702   } else {
13703     jam();
13704     setError(op_ptr, ret, __LINE__);
13705     sendTransRef(signal, op_ptr);
13706   }
13707 }
13708 
13709 void
alterIndex_toAddPartitions(Signal * signal,SchemaOpPtr op_ptr)13710 Dbdict::alterIndex_toAddPartitions(Signal* signal, SchemaOpPtr op_ptr)
13711 {
13712   AlterIndexRecPtr alterIndexPtr;
13713   getOpRec(op_ptr, alterIndexPtr);
13714   const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
13715 
13716   /**
13717    * Get fragmentation for table table from alterTable operation
13718    */
13719   SchemaOpPtr base_op;
13720   c_schemaOpPool.getPtr(base_op, op_ptr.p->m_base_op_ptr_i);
13721 
13722   const OpSection& fragInfoSec =
13723     getOpSection(base_op, AlterTabReq::FRAGMENTATION);
13724   SegmentedSectionPtr fragInfoPtr;
13725   LocalArenaPoolImpl op_sec_pool(op_ptr.p->m_trans_ptr.p->m_arena, c_opSectionBufferPool);
13726   bool ok = copyOut(op_sec_pool, fragInfoSec, fragInfoPtr);
13727   ndbrequire(ok);
13728   SectionHandle handle(this, fragInfoPtr.i);
13729 
13730   AlterTabReq* req = (AlterTabReq*)signal->getDataPtrSend();
13731   req->senderRef = reference();
13732   req->senderData = op_ptr.p->op_key;
13733   req->requestType = AlterTabReq::AlterTablePrepare;
13734   req->tableId = impl_req->indexId;
13735   req->tableVersion = impl_req->indexVersion;
13736   req->newTableVersion = impl_req->indexVersion;
13737   req->gci = 0;
13738   req->changeMask = 0;
13739   req->connectPtr = RNIL;
13740   req->noOfNewAttr = 0;
13741   req->newNoOfCharsets = 0;
13742   req->newNoOfKeyAttrs = 0;
13743   AlterTableReq::setAddFragFlag(req->changeMask, 1);
13744 
13745   sendSignal(DBDIH_REF, GSN_ALTER_TAB_REQ, signal,
13746              AlterTabReq::SignalLength, JBB, &handle);
13747 }
13748 
13749 void
alterIndex_fromAddPartitions(Signal * signal,Uint32 op_key,Uint32 ret)13750 Dbdict::alterIndex_fromAddPartitions(Signal* signal, Uint32 op_key, Uint32 ret)
13751 {
13752   SchemaOpPtr op_ptr;
13753   AlterIndexRecPtr alterIndexPtr;
13754   findSchemaOp(op_ptr, alterIndexPtr, op_key);
13755   ndbrequire(!op_ptr.isNull());
13756 
13757   if (ret == 0) {
13758     jam();
13759 
13760     const AlterTabConf* conf =
13761       (const AlterTabConf*)signal->getDataPtr();
13762 
13763     alterIndexPtr.p->m_dihAddFragPtr = conf->connectPtr;
13764 
13765     sendTransConf(signal, op_ptr);
13766   } else {
13767     jam();
13768     setError(op_ptr, ret, __LINE__);
13769     sendTransRef(signal, op_ptr);
13770   }
13771 }
13772 
13773 // AlterIndex: COMMIT
13774 
13775 void
alterIndex_commit(Signal * signal,SchemaOpPtr op_ptr)13776 Dbdict::alterIndex_commit(Signal* signal, SchemaOpPtr op_ptr)
13777 {
13778   jam();
13779 
13780   AlterIndexRecPtr alterIndexPtr;
13781   getOpRec(op_ptr, alterIndexPtr);
13782   const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
13783 
13784   if (impl_req->requestType == AlterIndxImplReq::AlterIndexAddPartition)
13785   {
13786     AlterTabReq* req = (AlterTabReq*)signal->getDataPtrSend();
13787     req->senderRef = reference();
13788     req->senderData = op_ptr.p->op_key;
13789     req->requestType = AlterTabReq::AlterTableCommit;
13790     req->tableId = impl_req->indexId;
13791     req->tableVersion = impl_req->indexVersion;
13792     req->newTableVersion = impl_req->indexVersion;
13793     req->gci = 0;
13794     req->changeMask = 0;
13795     req->connectPtr = RNIL;
13796     req->noOfNewAttr = 0;
13797     req->newNoOfCharsets = 0;
13798     req->newNoOfKeyAttrs = 0;
13799     req->connectPtr = alterIndexPtr.p->m_dihAddFragPtr;
13800 
13801     Callback c = {
13802       safe_cast(&Dbdict::alterIndex_fromLocal),
13803       op_ptr.p->op_key
13804     };
13805     op_ptr.p->m_callback = c;
13806 
13807     sendSignal(DBDIH_REF,
13808                GSN_ALTER_TAB_REQ, signal,
13809                AlterTabReq::SignalLength, JBB);
13810     return;
13811   }
13812 
13813   sendTransConf(signal, op_ptr);
13814 }
13815 
13816 // AlterIndex: COMPLETE
13817 
13818 void
alterIndex_complete(Signal * signal,SchemaOpPtr op_ptr)13819 Dbdict::alterIndex_complete(Signal* signal, SchemaOpPtr op_ptr)
13820 {
13821   jam();
13822   AlterIndexRecPtr alterIndexPtr;
13823   getOpRec(op_ptr, alterIndexPtr);
13824   const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
13825 
13826   if (impl_req->requestType == AlterIndxImplReq::AlterIndexOffline)
13827   {
13828     jam();
13829     TableRecordPtr indexPtr;
13830     bool ok = find_object(indexPtr, impl_req->indexId);
13831     ndbrequire(ok);
13832     if (indexPtr.p->tableType == DictTabInfo::UniqueHashIndex)
13833     {
13834       jam();
13835       alterIndex_toDropLocal(signal, op_ptr);
13836       return;
13837     }
13838   }
13839 
13840   sendTransConf(signal, op_ptr);
13841 }
13842 
13843 // AlterIndex: ABORT
13844 
13845 void
alterIndex_abortParse(Signal * signal,SchemaOpPtr op_ptr)13846 Dbdict::alterIndex_abortParse(Signal* signal, SchemaOpPtr op_ptr)
13847 {
13848   AlterIndexRecPtr alterIndexPtr;
13849   getOpRec(op_ptr, alterIndexPtr);
13850   const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
13851   Uint32 requestType = impl_req->requestType;
13852   Uint32 indexId = impl_req->indexId;
13853 
13854   D("alterIndex_abortParse" << *op_ptr.p);
13855 
13856   do {
13857     if (!(impl_req->indexId < c_noOfMetaTables)) {
13858       jam();
13859       D("invalid index id" << V(indexId));
13860       break;
13861     }
13862 
13863     TableRecordPtr indexPtr;
13864     bool ok = find_object(indexPtr, indexId);
13865     if (!ok)
13866     {
13867       jam();
13868       break;
13869     }
13870 
13871     switch (requestType) {
13872     case AlterIndxImplReq::AlterIndexOnline:
13873       jam();
13874       indexPtr.p->indexState = TableRecord::IS_OFFLINE;
13875       break;
13876     case AlterIndxImplReq::AlterIndexOffline:
13877       jam();
13878       indexPtr.p->indexState = TableRecord::IS_ONLINE;
13879       break;
13880     default:
13881       break;
13882     }
13883   } while (0);
13884 
13885   sendTransConf(signal, op_ptr);
13886 }
13887 
13888 void
alterIndex_abortPrepare(Signal * signal,SchemaOpPtr op_ptr)13889 Dbdict::alterIndex_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
13890 {
13891   AlterIndexRecPtr alterIndexPtr;
13892   getOpRec(op_ptr, alterIndexPtr);
13893   const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
13894   Uint32 requestType = impl_req->requestType;
13895 
13896   D("alterIndex_abortPrepare" << *op_ptr.p);
13897 
13898   if (impl_req->requestType == AlterIndxImplReq::AlterIndexAddPartition)
13899   {
13900     AlterTabReq* req = (AlterTabReq*)signal->getDataPtrSend();
13901     req->senderRef = reference();
13902     req->senderData = op_ptr.p->op_key;
13903     req->requestType = AlterTabReq::AlterTableRevert;
13904     req->tableId = impl_req->indexId;
13905     req->tableVersion = impl_req->indexVersion;
13906     req->newTableVersion = impl_req->indexVersion;
13907     req->gci = 0;
13908     req->changeMask = 0;
13909     req->connectPtr = RNIL;
13910     req->noOfNewAttr = 0;
13911     req->newNoOfCharsets = 0;
13912     req->newNoOfKeyAttrs = 0;
13913     req->connectPtr = alterIndexPtr.p->m_dihAddFragPtr;
13914     AlterTableReq::setAddFragFlag(req->changeMask, 1);
13915 
13916     Callback c = {
13917       safe_cast(&Dbdict::alterIndex_fromLocal),
13918       op_ptr.p->op_key
13919     };
13920     op_ptr.p->m_callback = c;
13921 
13922     sendSignal(DBDIH_REF,
13923                GSN_ALTER_TAB_REQ, signal,
13924                AlterTabReq::SignalLength, JBB);
13925     return;
13926   }
13927 
13928   if (!alterIndexPtr.p->m_tc_index_done) {
13929     jam();
13930     sendTransConf(signal, op_ptr);
13931     return;
13932   }
13933 
13934   Callback c = {
13935     safe_cast(&Dbdict::alterIndex_abortFromLocal),
13936     op_ptr.p->op_key
13937   };
13938   op_ptr.p->m_callback = c;
13939 
13940   switch (requestType) {
13941   case AlterIndxImplReq::AlterIndexOnline:
13942     jam();
13943     alterIndex_toDropLocal(signal, op_ptr);
13944     break;
13945   case AlterIndxImplReq::AlterIndexOffline:
13946     jam();
13947     alterIndex_toCreateLocal(signal, op_ptr);
13948     break;
13949   default:
13950     ndbrequire(false);
13951     break;
13952   }
13953 }
13954 
13955 void
alterIndex_abortFromLocal(Signal * signal,Uint32 op_key,Uint32 ret)13956 Dbdict::alterIndex_abortFromLocal(Signal* signal,
13957                                   Uint32 op_key,
13958                                   Uint32 ret)
13959 {
13960   SchemaOpPtr op_ptr;
13961   AlterIndexRecPtr alterIndexPtr;
13962   findSchemaOp(op_ptr, alterIndexPtr, op_key);
13963   ndbrequire(!op_ptr.isNull());
13964 
13965   D("alterIndex_abortFromLocal" << V(ret) << *op_ptr.p);
13966 
13967   if (ret == 0) {
13968     jam();
13969     alterIndexPtr.p->m_tc_index_done = false;
13970     sendTransConf(signal, op_ptr);
13971   } else {
13972     // abort is not allowed to fail
13973     ndbrequire(false);
13974   }
13975 }
13976 
13977 // AlterIndex: MISC
13978 
13979 void
execALTER_INDX_CONF(Signal * signal)13980 Dbdict::execALTER_INDX_CONF(Signal* signal)
13981 {
13982   jamEntry();
13983   const AlterIndxConf* conf = (const AlterIndxConf*)signal->getDataPtr();
13984   handleDictConf(signal, conf);
13985 }
13986 
13987 void
execALTER_INDX_REF(Signal * signal)13988 Dbdict::execALTER_INDX_REF(Signal* signal)
13989 {
13990   jamEntry();
13991   const AlterIndxRef* ref = (const AlterIndxRef*)signal->getDataPtr();
13992   handleDictRef(signal, ref);
13993 }
13994 
13995 void
execALTER_INDX_IMPL_CONF(Signal * signal)13996 Dbdict::execALTER_INDX_IMPL_CONF(Signal* signal)
13997 {
13998   jamEntry();
13999   const AlterIndxImplConf* conf = (const AlterIndxImplConf*)signal->getDataPtr();
14000   handleDictConf(signal, conf);
14001 }
14002 
14003 void
execALTER_INDX_IMPL_REF(Signal * signal)14004 Dbdict::execALTER_INDX_IMPL_REF(Signal* signal)
14005 {
14006   jamEntry();
14007   const AlterIndxImplRef* ref = (const AlterIndxImplRef*)signal->getDataPtr();
14008   handleDictRef(signal, ref);
14009 }
14010 
14011 // AlterIndex: END
14012 
14013 // MODULE: BuildIndex
14014 
14015 const Dbdict::OpInfo
14016 Dbdict::BuildIndexRec::g_opInfo = {
14017   { 'B', 'I', 'n', 0 },
14018   ~RT_DBDICT_BUILD_INDEX,
14019   GSN_BUILD_INDX_IMPL_REQ,
14020   BuildIndxImplReq::SignalLength,
14021   //
14022   &Dbdict::buildIndex_seize,
14023   &Dbdict::buildIndex_release,
14024   //
14025   &Dbdict::buildIndex_parse,
14026   &Dbdict::buildIndex_subOps,
14027   &Dbdict::buildIndex_reply,
14028   //
14029   &Dbdict::buildIndex_prepare,
14030   &Dbdict::buildIndex_commit,
14031   &Dbdict::buildIndex_complete,
14032   //
14033   &Dbdict::buildIndex_abortParse,
14034   &Dbdict::buildIndex_abortPrepare
14035 };
14036 
14037 bool
buildIndex_seize(SchemaOpPtr op_ptr)14038 Dbdict::buildIndex_seize(SchemaOpPtr op_ptr)
14039 {
14040   return seizeOpRec<BuildIndexRec>(op_ptr);
14041 }
14042 
14043 void
buildIndex_release(SchemaOpPtr op_ptr)14044 Dbdict::buildIndex_release(SchemaOpPtr op_ptr)
14045 {
14046   releaseOpRec<BuildIndexRec>(op_ptr);
14047 }
14048 
14049 void
execBUILDINDXREQ(Signal * signal)14050 Dbdict::execBUILDINDXREQ(Signal* signal)
14051 {
14052   jamEntry();
14053   if (!assembleFragments(signal)) {
14054     jam();
14055     return;
14056   }
14057   SectionHandle handle(this, signal);
14058 
14059   const BuildIndxReq req_copy =
14060     *(const BuildIndxReq*)signal->getDataPtr();
14061   const BuildIndxReq* req = &req_copy;
14062 
14063   ErrorInfo error;
14064   do {
14065     SchemaOpPtr op_ptr;
14066     BuildIndexRecPtr buildIndexPtr;
14067     BuildIndxImplReq* impl_req;
14068 
14069     startClientReq(op_ptr, buildIndexPtr, req, impl_req, error);
14070     if (hasError(error)) {
14071       jam();
14072       break;
14073     }
14074 
14075     impl_req->buildId = req->buildId; //wl3600_todo remove from client sig
14076     impl_req->buildKey = req->buildKey;
14077     impl_req->tableId = req->tableId;
14078     impl_req->indexId = req->indexId;
14079     impl_req->indexType = req->indexType;  //wl3600_todo remove from client sig
14080     impl_req->parallelism = req->parallelism;
14081 
14082     handleClientReq(signal, op_ptr, handle);
14083     return;
14084   } while (0);
14085 
14086   releaseSections(handle);
14087 
14088   BuildIndxRef* ref = (BuildIndxRef*)signal->getDataPtrSend();
14089   ref->senderRef = reference();
14090   ref->clientData = req->clientData;
14091   ref->transId = req->transId;
14092   ref->tableId = req->tableId;
14093   ref->indexId = req->indexId;
14094   ref->indexType = req->indexType;
14095   getError(error, ref);
14096 
14097   sendSignal(req->clientRef, GSN_BUILDINDXREF, signal,
14098              BuildIndxRef::SignalLength, JBB);
14099 }
14100 
14101 // BuildIndex: PARSE
14102 
14103 void
buildIndex_parse(Signal * signal,bool master,SchemaOpPtr op_ptr,SectionHandle & handle,ErrorInfo & error)14104 Dbdict::buildIndex_parse(Signal* signal, bool master,
14105                          SchemaOpPtr op_ptr,
14106                          SectionHandle& handle, ErrorInfo& error)
14107 {
14108    D("buildIndex_parse");
14109 
14110   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
14111   BuildIndexRecPtr buildIndexPtr;
14112   getOpRec(op_ptr, buildIndexPtr);
14113   BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
14114   Uint32 err;
14115 
14116   // get index
14117   TableRecordPtr indexPtr;
14118   err = check_read_obj(impl_req->indexId, trans_ptr.p->m_transId);
14119   if (err)
14120   {
14121     jam();
14122     setError(error, err, __LINE__);
14123     return;
14124   }
14125   bool ok = find_object(indexPtr, impl_req->indexId);
14126   if (!ok)
14127   {
14128     jam();
14129     setError(error, GetTabInfoRef::TableNotDefined, __LINE__);
14130     return;
14131   }
14132 
14133   ndbrequire(indexPtr.p->primaryTableId == impl_req->tableId);
14134 
14135   // get primary table
14136   TableRecordPtr tablePtr;
14137   if (!(impl_req->tableId < c_noOfMetaTables)) {
14138     jam();
14139     setError(error, BuildIndxRef::IndexNotFound, __LINE__);
14140     return;
14141   }
14142   ok = find_object(tablePtr, impl_req->tableId);
14143   if (!ok)
14144   {
14145     jam();
14146     setError(error, GetTabInfoRef::TableNotDefined, __LINE__);
14147     return;
14148   }
14149 
14150   // set attribute lists
14151   getIndexAttrList(indexPtr, buildIndexPtr.p->m_indexKeyList);
14152   getTableKeyList(tablePtr, buildIndexPtr.p->m_tableKeyList);
14153 
14154   Uint32 requestType = impl_req->requestType;
14155   switch (requestType) {
14156   case BuildIndxReq::MainOp:
14157   case BuildIndxReq::SubOp:
14158     break;
14159   default:
14160     jam();
14161     ndbassert(false);
14162     setError(error, BuildIndxRef::BadRequestType, __LINE__);
14163     return;
14164   }
14165 
14166   // set build constraint info and attribute mask
14167   switch (indexPtr.p->tableType) {
14168   case DictTabInfo::UniqueHashIndex:
14169     jam();
14170     if (requestType == BuildIndxReq::MainOp) {
14171       buildIndexPtr.p->m_triggerTmpl = g_buildIndexConstraintTmpl;
14172       buildIndexPtr.p->m_subOpCount = 3;
14173       buildIndexPtr.p->m_subOpIndex = 0;
14174 
14175       // mask is NDB$PK (last attribute)
14176       Uint32 attrId = indexPtr.p->noOfAttributes - 1;
14177       buildIndexPtr.p->m_attrMask.clear();
14178       buildIndexPtr.p->m_attrMask.set(attrId);
14179       break;
14180     }
14181     /*FALLTHRU*/
14182   default:
14183     jam();
14184     {
14185       buildIndexPtr.p->m_triggerTmpl = 0;
14186       buildIndexPtr.p->m_subOpCount = 0;
14187       buildIndexPtr.p->m_doBuild = true;
14188     }
14189     break;
14190   }
14191 
14192   if (ERROR_INSERTED(6126)) {
14193     jam();
14194     CLEAR_ERROR_INSERT_VALUE;
14195     setError(error, 9126, __LINE__);
14196     return;
14197   }
14198 }
14199 
14200 bool
buildIndex_subOps(Signal * signal,SchemaOpPtr op_ptr)14201 Dbdict::buildIndex_subOps(Signal* signal, SchemaOpPtr op_ptr)
14202 {
14203   D("buildIndex_subOps" << V(op_ptr.i) << *op_ptr.p);
14204 
14205   BuildIndexRecPtr buildIndexPtr;
14206   getOpRec(op_ptr, buildIndexPtr);
14207   //const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
14208 
14209   if (buildIndexPtr.p->m_subOpIndex < buildIndexPtr.p->m_subOpCount) {
14210     jam();
14211     switch (buildIndexPtr.p->m_subOpIndex) {
14212     case 0:
14213       jam();
14214       {
14215         Callback c = {
14216           safe_cast(&Dbdict::buildIndex_fromCreateConstraint),
14217           op_ptr.p->op_key
14218         };
14219         op_ptr.p->m_callback = c;
14220         buildIndex_toCreateConstraint(signal, op_ptr);
14221         return true;
14222       }
14223       break;
14224     case 1:
14225       jam();
14226       // the sub-op that does the actual hash index build
14227       {
14228         Callback c = {
14229           safe_cast(&Dbdict::buildIndex_fromBuildIndex),
14230           op_ptr.p->op_key
14231         };
14232         op_ptr.p->m_callback = c;
14233         buildIndex_toBuildIndex(signal, op_ptr);
14234         return true;
14235       }
14236       break;
14237     case 2:
14238       jam();
14239       {
14240         Callback c = {
14241           safe_cast(&Dbdict::buildIndex_fromDropConstraint),
14242           op_ptr.p->op_key
14243         };
14244         op_ptr.p->m_callback = c;
14245         buildIndex_toDropConstraint(signal, op_ptr);
14246         return true;
14247       }
14248       break;
14249     default:
14250       ndbrequire(false);
14251       break;
14252     }
14253   }
14254 
14255   return false;
14256 }
14257 
14258 void
buildIndex_toCreateConstraint(Signal * signal,SchemaOpPtr op_ptr)14259 Dbdict::buildIndex_toCreateConstraint(Signal* signal, SchemaOpPtr op_ptr)
14260 {
14261   D("buildIndex_toCreateConstraint");
14262 
14263   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
14264   BuildIndexRecPtr buildIndexPtr;
14265   getOpRec(op_ptr, buildIndexPtr);
14266   const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
14267 
14268   const TriggerTmpl& triggerTmpl = buildIndexPtr.p->m_triggerTmpl[0];
14269 
14270   CreateTrigReq* req = (CreateTrigReq*)signal->getDataPtrSend();
14271 
14272   Uint32 requestInfo = 0;
14273   DictSignal::setRequestType(requestInfo, CreateTrigReq::CreateTriggerOnline);
14274   DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
14275 
14276   req->clientRef = reference();
14277   req->clientData = op_ptr.p->op_key;
14278   req->transId = trans_ptr.p->m_transId;
14279   req->transKey = trans_ptr.p->trans_key;
14280   req->requestInfo = requestInfo;
14281   req->tableId = impl_req->indexId; // constraint is on index table
14282   req->tableVersion = 0;
14283   req->indexId = RNIL;
14284   req->indexVersion = 0;
14285   req->triggerNo = 0;
14286   req->forceTriggerId = RNIL;
14287 
14288   TriggerInfo::packTriggerInfo(req->triggerInfo, triggerTmpl.triggerInfo);
14289 
14290   req->receiverRef = 0;
14291 
14292   char triggerName[MAX_TAB_NAME_SIZE];
14293   sprintf(triggerName, triggerTmpl.nameFormat, impl_req->indexId);
14294 
14295   // name section
14296   Uint32 buffer[2 + ((MAX_TAB_NAME_SIZE + 3) >> 2)];    // SP string
14297   LinearWriter w(buffer, sizeof(buffer) >> 2);
14298   w.reset();
14299   w.add(DictTabInfo::TableName, triggerName);
14300   LinearSectionPtr ls_ptr[3];
14301   ls_ptr[0].p = buffer;
14302   ls_ptr[0].sz = w.getWordsUsed();
14303 
14304   ls_ptr[1].p = buildIndexPtr.p->m_attrMask.rep.data;
14305   ls_ptr[1].sz = buildIndexPtr.p->m_attrMask.getSizeInWords();
14306 
14307   sendSignal(reference(), GSN_CREATE_TRIG_REQ, signal,
14308              CreateTrigReq::SignalLength, JBB, ls_ptr, 2);
14309 }
14310 
14311 void
buildIndex_fromCreateConstraint(Signal * signal,Uint32 op_key,Uint32 ret)14312 Dbdict::buildIndex_fromCreateConstraint(Signal* signal, Uint32 op_key, Uint32 ret)
14313 {
14314   jam();
14315 
14316   SchemaOpPtr op_ptr;
14317   BuildIndexRecPtr buildIndexPtr;
14318 
14319   findSchemaOp(op_ptr, buildIndexPtr, op_key);
14320   ndbrequire(!op_ptr.isNull());
14321   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
14322   //const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
14323 
14324   D("buildIndex_fromCreateConstraint" << dec << V(op_key) << V(ret));
14325 
14326   if (ret == 0) {
14327     jam();
14328     const CreateTrigConf* conf =
14329       (const CreateTrigConf*)signal->getDataPtr();
14330 
14331     ndbrequire(conf->transId == trans_ptr.p->m_transId);
14332     ndbrequire(buildIndexPtr.p->m_subOpIndex < buildIndexPtr.p->m_subOpCount);
14333     buildIndexPtr.p->m_subOpIndex += 1;
14334     createSubOps(signal, op_ptr);
14335   } else {
14336     const CreateTrigRef* ref =
14337       (const CreateTrigRef*)signal->getDataPtr();
14338 
14339     ErrorInfo error;
14340     setError(error, ref);
14341     abortSubOps(signal, op_ptr, error);
14342   }
14343 }
14344 
14345 void
buildIndex_toBuildIndex(Signal * signal,SchemaOpPtr op_ptr)14346 Dbdict::buildIndex_toBuildIndex(Signal* signal, SchemaOpPtr op_ptr)
14347 {
14348   D("buildIndex_toBuildIndex");
14349 
14350   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
14351   BuildIndexRecPtr buildIndexPtr;
14352   getOpRec(op_ptr, buildIndexPtr);
14353   const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
14354 
14355   BuildIndxReq* req = (BuildIndxReq*)signal->getDataPtrSend();
14356 
14357   Uint32 requestInfo = 0;
14358   DictSignal::setRequestType(requestInfo, BuildIndxReq::SubOp);
14359   DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
14360 
14361   req->clientRef = reference();
14362   req->clientData = op_ptr.p->op_key;
14363   req->transId = trans_ptr.p->m_transId;
14364   req->transKey = trans_ptr.p->trans_key;
14365   req->requestInfo = requestInfo;
14366   req->buildId = 0;
14367   req->buildKey = 0;
14368   req->tableId = impl_req->tableId;
14369   req->indexId = impl_req->indexId;
14370   req->indexType = impl_req->indexType;
14371   req->parallelism = impl_req->parallelism;
14372 
14373   sendSignal(reference(), GSN_BUILDINDXREQ, signal,
14374             BuildIndxReq::SignalLength, JBB);
14375 }
14376 
14377 void
buildIndex_fromBuildIndex(Signal * signal,Uint32 op_key,Uint32 ret)14378 Dbdict::buildIndex_fromBuildIndex(Signal* signal, Uint32 op_key, Uint32 ret)
14379 {
14380   jam();
14381   D("buildIndex_fromBuildIndex");
14382 
14383   SchemaOpPtr op_ptr;
14384   BuildIndexRecPtr buildIndexPtr;
14385 
14386   findSchemaOp(op_ptr, buildIndexPtr, op_key);
14387   ndbrequire(!op_ptr.isNull());
14388   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
14389 
14390   if (ret == 0) {
14391     jam();
14392     const BuildIndxConf* conf =
14393       (const BuildIndxConf*)signal->getDataPtr();
14394 
14395     ndbrequire(conf->transId == trans_ptr.p->m_transId);
14396     ndbrequire(buildIndexPtr.p->m_subOpIndex < buildIndexPtr.p->m_subOpCount);
14397     buildIndexPtr.p->m_subOpIndex += 1;
14398     createSubOps(signal, op_ptr);
14399   } else {
14400     jam();
14401     const BuildIndxRef* ref =
14402       (const BuildIndxRef*)signal->getDataPtr();
14403 
14404     ErrorInfo error;
14405     setError(error, ref);
14406     abortSubOps(signal, op_ptr, error);
14407   }
14408 }
14409 
14410 void
buildIndex_toDropConstraint(Signal * signal,SchemaOpPtr op_ptr)14411 Dbdict::buildIndex_toDropConstraint(Signal* signal, SchemaOpPtr op_ptr)
14412 {
14413   D("buildIndex_toDropConstraint");
14414 
14415   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
14416   BuildIndexRecPtr buildIndexPtr;
14417   getOpRec(op_ptr, buildIndexPtr);
14418   const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
14419 
14420   const TriggerTmpl& triggerTmpl = buildIndexPtr.p->m_triggerTmpl[0];
14421 
14422   DropTrigReq* req = (DropTrigReq*)signal->getDataPtrSend();
14423 
14424   Uint32 requestInfo = 0;
14425   DictSignal::setRequestType(requestInfo, 0);
14426   DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
14427 
14428   req->clientRef = reference();
14429   req->clientData = op_ptr.p->op_key;
14430   req->transId = trans_ptr.p->m_transId;
14431   req->transKey = trans_ptr.p->trans_key;
14432   req->requestInfo = requestInfo;
14433   req->tableId = impl_req->indexId; // constraint is on index table
14434   req->tableVersion = 0;
14435   req->indexId = RNIL;
14436   req->indexVersion = 0;
14437   req->triggerNo = 0;
14438   req->triggerId = RNIL;
14439 
14440   // wl3600_todo use name now, connect by tree walk later
14441 
14442   char triggerName[MAX_TAB_NAME_SIZE];
14443   sprintf(triggerName, triggerTmpl.nameFormat, impl_req->indexId);
14444 
14445   // name section
14446   Uint32 buffer[2 + ((MAX_TAB_NAME_SIZE + 3) >> 2)];    // SP string
14447   LinearWriter w(buffer, sizeof(buffer) >> 2);
14448   w.reset();
14449   w.add(DictTabInfo::TableName, triggerName);
14450   LinearSectionPtr ls_ptr[3];
14451   ls_ptr[0].p = buffer;
14452   ls_ptr[0].sz = w.getWordsUsed();
14453 
14454   sendSignal(reference(), GSN_DROP_TRIG_REQ, signal,
14455              DropTrigReq::SignalLength, JBB, ls_ptr, 1);
14456 }
14457 
14458 void
buildIndex_fromDropConstraint(Signal * signal,Uint32 op_key,Uint32 ret)14459 Dbdict::buildIndex_fromDropConstraint(Signal* signal, Uint32 op_key, Uint32 ret)
14460 {
14461   jam();
14462 
14463   SchemaOpPtr op_ptr;
14464   BuildIndexRecPtr buildIndexPtr;
14465 
14466   findSchemaOp(op_ptr, buildIndexPtr, op_key);
14467   ndbrequire(!op_ptr.isNull());
14468   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
14469   //const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
14470 
14471   D("buildIndex_fromDropConstraint" << dec << V(op_key) << V(ret));
14472 
14473   if (ret == 0) {
14474     const DropTrigConf* conf =
14475       (const DropTrigConf*)signal->getDataPtr();
14476 
14477     ndbrequire(conf->transId == trans_ptr.p->m_transId);
14478     ndbrequire(buildIndexPtr.p->m_subOpIndex < buildIndexPtr.p->m_subOpCount);
14479     buildIndexPtr.p->m_subOpIndex += 1;
14480     createSubOps(signal, op_ptr);
14481   } else {
14482     jam();
14483     const DropTrigRef* ref =
14484       (const DropTrigRef*)signal->getDataPtr();
14485 
14486     ErrorInfo error;
14487     setError(error, ref);
14488     abortSubOps(signal, op_ptr, error);
14489   }
14490 }
14491 
14492 void
buildIndex_reply(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)14493 Dbdict::buildIndex_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
14494 {
14495   jam();
14496 
14497   SchemaTransPtr& trans_ptr = op_ptr.p->m_trans_ptr;
14498   BuildIndexRecPtr buildIndexPtr;
14499   getOpRec(op_ptr, buildIndexPtr);
14500   const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
14501 
14502   D("buildIndex_reply" << V(impl_req->indexId));
14503 
14504   if (!hasError(error)) {
14505     BuildIndxConf* conf = (BuildIndxConf*)signal->getDataPtrSend();
14506     conf->senderRef = reference();
14507     conf->clientData = op_ptr.p->m_clientData;
14508     conf->transId = trans_ptr.p->m_transId;
14509     conf->tableId = impl_req->tableId;
14510     conf->indexId = impl_req->indexId;
14511     conf->indexType = impl_req->indexType;
14512 
14513     Uint32 clientRef = op_ptr.p->m_clientRef;
14514     sendSignal(clientRef, GSN_BUILDINDXCONF, signal,
14515                BuildIndxConf::SignalLength, JBB);
14516   } else {
14517     jam();
14518     BuildIndxRef* ref = (BuildIndxRef*)signal->getDataPtrSend();
14519     ref->senderRef = reference();
14520     ref->clientData = op_ptr.p->m_clientData;
14521     ref->transId = trans_ptr.p->m_transId;
14522     ref->tableId = impl_req->tableId;
14523     ref->indexId = impl_req->indexId;
14524     ref->indexType = impl_req->indexType;
14525     getError(error, ref);
14526 
14527     Uint32 clientRef = op_ptr.p->m_clientRef;
14528     sendSignal(clientRef, GSN_BUILDINDXREF, signal,
14529                BuildIndxRef::SignalLength, JBB);
14530   }
14531 }
14532 
14533 // BuildIndex: PREPARE
14534 
14535 void
buildIndex_prepare(Signal * signal,SchemaOpPtr op_ptr)14536 Dbdict::buildIndex_prepare(Signal* signal, SchemaOpPtr op_ptr)
14537 {
14538   jam();
14539   BuildIndexRecPtr buildIndexPtr;
14540   getOpRec(op_ptr, buildIndexPtr);
14541   //const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
14542 
14543   Uint32 requestInfo = op_ptr.p->m_requestInfo;
14544   bool noBuild = (requestInfo & DictSignal::RF_NO_BUILD);
14545 
14546   D("buildIndex_prepare" << hex << V(requestInfo));
14547 
14548   if (noBuild || !buildIndexPtr.p->m_doBuild) {
14549     jam();
14550     sendTransConf(signal, op_ptr);
14551     return;
14552   }
14553 
14554   buildIndex_toLocalBuild(signal, op_ptr);
14555 }
14556 
14557 void
buildIndex_toLocalBuild(Signal * signal,SchemaOpPtr op_ptr)14558 Dbdict:: buildIndex_toLocalBuild(Signal* signal, SchemaOpPtr op_ptr)
14559 {
14560   BuildIndexRecPtr buildIndexPtr;
14561   getOpRec(op_ptr, buildIndexPtr);
14562   const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
14563   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
14564 
14565   TableRecordPtr indexPtr;
14566   bool ok = find_object(indexPtr, impl_req->indexId);
14567   ndbrequire(ok);
14568 
14569   D("buildIndex_toLocalBuild");
14570 
14571   BuildIndxImplReq* req = (BuildIndxImplReq*)signal->getDataPtrSend();
14572 
14573   req->senderRef = reference();
14574   req->senderData = op_ptr.p->op_key;
14575   req->requestType = impl_req->requestType;
14576   req->transId = trans_ptr.p->m_transId;
14577   req->buildId = impl_req->buildId;
14578   req->buildKey = impl_req->buildKey;
14579   req->tableId = impl_req->tableId;
14580   req->indexId = impl_req->indexId;
14581   req->indexType = indexPtr.p->tableType;
14582   req->parallelism = impl_req->parallelism;
14583 
14584   /* All indexed columns must be in memory currently */
14585   req->requestType |= BuildIndxImplReq::RF_NO_DISK;
14586 
14587   Callback c = {
14588     safe_cast(&Dbdict::buildIndex_fromLocalBuild),
14589     op_ptr.p->op_key
14590   };
14591   op_ptr.p->m_callback = c;
14592 
14593   switch (indexPtr.p->tableType) {
14594   case DictTabInfo::UniqueHashIndex:
14595     jam();
14596     {
14597       LinearSectionPtr ls_ptr[3];
14598       ls_ptr[0].sz = buildIndexPtr.p->m_indexKeyList.sz;
14599       ls_ptr[0].p = buildIndexPtr.p->m_indexKeyList.id;
14600       ls_ptr[1].sz = buildIndexPtr.p->m_tableKeyList.sz;
14601       ls_ptr[1].p = buildIndexPtr.p->m_tableKeyList.id;
14602 
14603       sendSignal(TRIX_REF, GSN_BUILD_INDX_IMPL_REQ, signal,
14604                  BuildIndxImplReq::SignalLength, JBB, ls_ptr, 2);
14605     }
14606     break;
14607   case DictTabInfo::OrderedIndex:
14608     jam();
14609     if (op_ptr.p->m_requestInfo & BuildIndxReq::RF_BUILD_OFFLINE)
14610     {
14611       jam();
14612       req->requestType |= BuildIndxImplReq::RF_BUILD_OFFLINE;
14613     }
14614 
14615     {
14616       sendSignal(DBTUP_REF, GSN_BUILD_INDX_IMPL_REQ, signal,
14617                  BuildIndxImplReq::SignalLength, JBB);
14618     }
14619     break;
14620   default:
14621     ndbrequire(false);
14622     break;
14623   }
14624 }
14625 
14626 void
buildIndex_fromLocalBuild(Signal * signal,Uint32 op_key,Uint32 ret)14627 Dbdict::buildIndex_fromLocalBuild(Signal* signal, Uint32 op_key, Uint32 ret)
14628 {
14629   SchemaOpPtr op_ptr;
14630   BuildIndexRecPtr buildIndexPtr;
14631   findSchemaOp(op_ptr, buildIndexPtr, op_key);
14632   ndbrequire(!op_ptr.isNull());
14633 
14634   D("buildIndex_fromLocalBuild");
14635 
14636   if (ret == 0) {
14637     jam();
14638     sendTransConf(signal, op_ptr);
14639   } else {
14640     jam();
14641     setError(op_ptr, ret, __LINE__);
14642     sendTransRef(signal, op_ptr);
14643   }
14644 }
14645 
14646 // BuildIndex: COMMIT
14647 
14648 void
buildIndex_commit(Signal * signal,SchemaOpPtr op_ptr)14649 Dbdict::buildIndex_commit(Signal* signal, SchemaOpPtr op_ptr)
14650 {
14651   jam();
14652   BuildIndexRecPtr buildIndexPtr;
14653   getOpRec(op_ptr, buildIndexPtr);
14654 
14655   D("buildIndex_commit" << *op_ptr.p);
14656 
14657   buildIndex_toLocalOnline(signal, op_ptr);
14658 }
14659 
14660 void
buildIndex_toLocalOnline(Signal * signal,SchemaOpPtr op_ptr)14661 Dbdict::buildIndex_toLocalOnline(Signal* signal, SchemaOpPtr op_ptr)
14662 {
14663   BuildIndexRecPtr buildIndexPtr;
14664   getOpRec(op_ptr, buildIndexPtr);
14665   const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
14666 
14667   TableRecordPtr indexPtr;
14668   bool ok = find_object(indexPtr, impl_req->indexId);
14669   ndbrequire(ok);
14670 
14671   D("buildIndex_toLocalOnline");
14672 
14673   AlterIndxImplReq* req = (AlterIndxImplReq*)signal->getDataPtrSend();
14674 
14675   req->senderRef = reference();
14676   req->senderData = op_ptr.p->op_key;
14677   req->requestType = impl_req->requestType;
14678   req->tableId = impl_req->tableId;
14679   req->tableVersion = 0; // not used
14680   req->indexId = impl_req->indexId;
14681   req->indexVersion = 0; // not used
14682 
14683   Callback c = {
14684     safe_cast(&Dbdict::buildIndex_fromLocalOnline),
14685     op_ptr.p->op_key
14686   };
14687   op_ptr.p->m_callback = c;
14688 
14689   switch (indexPtr.p->tableType) {
14690   case DictTabInfo::UniqueHashIndex:
14691     jam();
14692     {
14693       sendSignal(DBTC_REF, GSN_ALTER_INDX_IMPL_REQ, signal,
14694                  AlterIndxImplReq::SignalLength, JBB);
14695     }
14696     break;
14697   case DictTabInfo::OrderedIndex:
14698     jam();
14699     {
14700       sendSignal(DBTUX_REF, GSN_ALTER_INDX_IMPL_REQ, signal,
14701                  AlterIndxImplReq::SignalLength, JBB);
14702     }
14703     break;
14704   default:
14705     ndbrequire(false);
14706     break;
14707   }
14708 }
14709 
14710 void
buildIndex_fromLocalOnline(Signal * signal,Uint32 op_key,Uint32 ret)14711 Dbdict::buildIndex_fromLocalOnline(Signal* signal, Uint32 op_key, Uint32 ret)
14712 {
14713   SchemaOpPtr op_ptr;
14714   BuildIndexRecPtr buildIndexPtr;
14715   findSchemaOp(op_ptr, buildIndexPtr, op_key);
14716   ndbrequire(!op_ptr.isNull());
14717   const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
14718 
14719   TableRecordPtr indexPtr;
14720   bool ok = find_object(indexPtr, impl_req->indexId);
14721   ndbrequire(ok);
14722 
14723   D("buildIndex_fromLocalOnline");
14724 
14725   if (ret == 0) {
14726     jam();
14727     // set index online
14728     indexPtr.p->indexState = TableRecord::IS_ONLINE;
14729     sendTransConf(signal, op_ptr);
14730   } else {
14731     //wl3600_todo
14732     ndbrequire(false);
14733   }
14734 }
14735 
14736 // BuildIndex: COMPLETE
14737 
14738 void
buildIndex_complete(Signal * signal,SchemaOpPtr op_ptr)14739 Dbdict::buildIndex_complete(Signal* signal, SchemaOpPtr op_ptr)
14740 {
14741   jam();
14742   sendTransConf(signal, op_ptr);
14743 }
14744 
14745 // BuildIndex: ABORT
14746 
14747 void
buildIndex_abortParse(Signal * signal,SchemaOpPtr op_ptr)14748 Dbdict::buildIndex_abortParse(Signal* signal, SchemaOpPtr op_ptr)
14749 {
14750   D("buildIndex_abortParse" << *op_ptr.p);
14751   // wl3600_todo
14752   sendTransConf(signal, op_ptr);
14753 }
14754 
14755 void
buildIndex_abortPrepare(Signal * signal,SchemaOpPtr op_ptr)14756 Dbdict::buildIndex_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
14757 {
14758   D("buildIndex_abortPrepare" << *op_ptr.p);
14759 
14760   // nothing to do, entire index table will be dropped
14761   sendTransConf(signal, op_ptr);
14762 }
14763 
14764 // BuildIndex: MISC
14765 
14766 void
execBUILDINDXCONF(Signal * signal)14767 Dbdict::execBUILDINDXCONF(Signal* signal)
14768 {
14769   jamEntry();
14770   const BuildIndxConf* conf = (const BuildIndxConf*)signal->getDataPtr();
14771   handleDictConf(signal, conf);
14772 }
14773 
14774 void
execBUILDINDXREF(Signal * signal)14775 Dbdict::execBUILDINDXREF(Signal* signal)
14776 {
14777   jamEntry();
14778   const BuildIndxRef* ref = (const BuildIndxRef*)signal->getDataPtr();
14779   handleDictRef(signal, ref);
14780 }
14781 
14782 void
execBUILD_INDX_IMPL_CONF(Signal * signal)14783 Dbdict::execBUILD_INDX_IMPL_CONF(Signal* signal)
14784 {
14785   jamEntry();
14786   const BuildIndxImplConf* conf = (const BuildIndxImplConf*)signal->getDataPtr();
14787   handleDictConf(signal, conf);
14788 }
14789 
14790 void
execBUILD_INDX_IMPL_REF(Signal * signal)14791 Dbdict::execBUILD_INDX_IMPL_REF(Signal* signal)
14792 {
14793   jamEntry();
14794   const BuildIndxImplRef* ref = (const BuildIndxImplRef*)signal->getDataPtr();
14795   handleDictRef(signal, ref);
14796 }
14797 
14798 // BuildIndex: END
14799 
14800 // MODULE: IndexStat
14801 
14802 const Dbdict::OpInfo
14803 Dbdict::IndexStatRec::g_opInfo = {
14804   { 'S', 'I', 'n', 0 },
14805   ~RT_DBDICT_INDEX_STAT,
14806   GSN_INDEX_STAT_IMPL_REQ,
14807   IndexStatImplReq::SignalLength,
14808   //
14809   &Dbdict::indexStat_seize,
14810   &Dbdict::indexStat_release,
14811   //
14812   &Dbdict::indexStat_parse,
14813   &Dbdict::indexStat_subOps,
14814   &Dbdict::indexStat_reply,
14815   //
14816   &Dbdict::indexStat_prepare,
14817   &Dbdict::indexStat_commit,
14818   &Dbdict::indexStat_complete,
14819   //
14820   &Dbdict::indexStat_abortParse,
14821   &Dbdict::indexStat_abortPrepare
14822 };
14823 
14824 bool
indexStat_seize(SchemaOpPtr op_ptr)14825 Dbdict::indexStat_seize(SchemaOpPtr op_ptr)
14826 {
14827   return seizeOpRec<IndexStatRec>(op_ptr);
14828 }
14829 
14830 void
indexStat_release(SchemaOpPtr op_ptr)14831 Dbdict::indexStat_release(SchemaOpPtr op_ptr)
14832 {
14833   releaseOpRec<IndexStatRec>(op_ptr);
14834 }
14835 
14836 void
execINDEX_STAT_REQ(Signal * signal)14837 Dbdict::execINDEX_STAT_REQ(Signal* signal)
14838 {
14839   jamEntry();
14840   if (!assembleFragments(signal)) {
14841     jam();
14842     return;
14843   }
14844   SectionHandle handle(this, signal);
14845 
14846   const IndexStatReq req_copy =
14847     *(const IndexStatReq*)signal->getDataPtr();
14848   const IndexStatReq* req = &req_copy;
14849 
14850   ErrorInfo error;
14851   do {
14852     SchemaOpPtr op_ptr;
14853     IndexStatRecPtr indexStatPtr;
14854     IndexStatImplReq* impl_req;
14855 
14856     startClientReq(op_ptr, indexStatPtr, req, impl_req, error);
14857     if (hasError(error)) {
14858       jam();
14859       break;
14860     }
14861 
14862     // senderRef, senderData, requestType have been set already
14863     impl_req->transId = req->transId;
14864     impl_req->requestFlag = req->requestFlag;
14865     impl_req->indexId = req->indexId;
14866     impl_req->indexVersion = req->indexVersion;
14867     impl_req->tableId = req->tableId;
14868     impl_req->fragId = ZNIL;
14869     impl_req->fragCount = ZNIL;
14870 
14871     handleClientReq(signal, op_ptr, handle);
14872     return;
14873   } while (0);
14874 
14875   releaseSections(handle);
14876 
14877   IndexStatRef* ref = (IndexStatRef*)signal->getDataPtrSend();
14878   ref->senderRef = reference();
14879   ref->clientData = req->clientData;
14880   ref->transId = req->transId;
14881   getError(error, ref);
14882 
14883   sendSignal(req->clientRef, GSN_INDEX_STAT_REF, signal,
14884              IndexStatRef::SignalLength, JBB);
14885 }
14886 
14887 // IndexStat: PARSE
14888 
14889 void
indexStat_parse(Signal * signal,bool master,SchemaOpPtr op_ptr,SectionHandle & handle,ErrorInfo & error)14890 Dbdict::indexStat_parse(Signal* signal, bool master,
14891                         SchemaOpPtr op_ptr,
14892                         SectionHandle& handle, ErrorInfo& error)
14893 {
14894   D("indexStat_parse");
14895 
14896   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
14897   IndexStatRecPtr indexStatPtr;
14898   getOpRec(op_ptr, indexStatPtr);
14899   IndexStatImplReq* impl_req = &indexStatPtr.p->m_request;
14900   Uint32 err;
14901 
14902   // get index
14903   TableRecordPtr indexPtr;
14904   err = check_read_obj(impl_req->indexId, trans_ptr.p->m_transId);
14905   if (err)
14906   {
14907     jam();
14908     setError(error, err, __LINE__);
14909     return;
14910   }
14911   bool ok = find_object(indexPtr, impl_req->indexId);
14912   if (!ok || !indexPtr.p->isOrderedIndex()) {
14913     jam();
14914     setError(error, IndexStatRef::InvalidIndex, __LINE__);
14915     return;
14916   }
14917 
14918   XSchemaFile* xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
14919   const SchemaFile::TableEntry* te = getTableEntry(xsf, impl_req->indexId);
14920   if (te->m_tableState != SchemaFile::SF_CREATE &&
14921       te->m_tableState != SchemaFile::SF_IN_USE) {
14922     jam();
14923     setError(error, IndexStatRef::InvalidIndex, __LINE__);
14924     return;
14925   }
14926 
14927   // fragmentId is defined only in signals from DICT to TRIX,TUX
14928   if (impl_req->fragId != ZNIL) {
14929     jam();
14930     setError(error, IndexStatRef::InvalidRequest, __LINE__);
14931     return;
14932   }
14933   impl_req->fragCount = indexPtr.p->fragmentCount;
14934 
14935   switch (impl_req->requestType) {
14936   case IndexStatReq::RT_UPDATE_STAT:
14937     jam();
14938     // clean new samples, scan, clean old samples, start frag monitor
14939     indexStatPtr.p->m_subOpCount = 4;
14940     indexStatPtr.p->m_subOpIndex = 0;
14941     break;
14942   case IndexStatReq::RT_DELETE_STAT:
14943     jam();
14944     // stop frag monitor, delete head, clean all samples
14945     indexStatPtr.p->m_subOpCount = 3;
14946     indexStatPtr.p->m_subOpIndex = 0;
14947     break;
14948   case IndexStatReq::RT_SCAN_FRAG:
14949   case IndexStatReq::RT_CLEAN_NEW:
14950   case IndexStatReq::RT_CLEAN_OLD:
14951   case IndexStatReq::RT_CLEAN_ALL:
14952   case IndexStatReq::RT_DROP_HEAD:
14953   case IndexStatReq::RT_START_MON:
14954   case IndexStatReq::RT_STOP_MON:
14955     jam();
14956     // sub-operations can be invoked only by DICT
14957     if (master && refToBlock(op_ptr.p->m_clientRef) != DBDICT) {
14958       jam();
14959       setError(error, IndexStatRef::InvalidRequest, __LINE__);
14960       return;
14961     }
14962     indexStatPtr.p->m_subOpCount = 0;
14963     indexStatPtr.p->m_subOpIndex = 0;
14964     break;
14965   default:
14966     jam();
14967     setError(error, IndexStatRef::InvalidRequest, __LINE__);
14968     return;
14969   }
14970 }
14971 
14972 bool
indexStat_subOps(Signal * signal,SchemaOpPtr op_ptr)14973 Dbdict::indexStat_subOps(Signal* signal, SchemaOpPtr op_ptr)
14974 {
14975   D("indexStat_subOps" << V(op_ptr.i) << V(*op_ptr.p));
14976 
14977   IndexStatRecPtr indexStatPtr;
14978   getOpRec(op_ptr, indexStatPtr);
14979   const IndexStatImplReq* impl_req = &indexStatPtr.p->m_request;
14980 
14981   const Uint32 subOpIndex = indexStatPtr.p->m_subOpIndex;
14982   const Uint32 subOpCount = indexStatPtr.p->m_subOpCount;
14983   if (subOpIndex >= subOpCount) {
14984     jam();
14985     ndbrequire(subOpIndex == subOpCount);
14986     return false;
14987   }
14988 
14989   Uint32 requestType = 0;
14990 
14991   switch (impl_req->requestType) {
14992   case IndexStatReq::RT_UPDATE_STAT:
14993     if (subOpIndex == 0)
14994       requestType = IndexStatReq::RT_CLEAN_NEW;
14995     else if (subOpIndex == 1)
14996       requestType = IndexStatReq::RT_SCAN_FRAG;
14997     else if (subOpIndex == 2)
14998       requestType = IndexStatReq::RT_CLEAN_OLD;
14999     else if (subOpIndex == 3)
15000       requestType = IndexStatReq::RT_START_MON;
15001     break;
15002 
15003   case IndexStatReq::RT_DELETE_STAT:
15004     jam();
15005     if (subOpIndex == 0)
15006       requestType = IndexStatReq::RT_STOP_MON;
15007     else if (subOpIndex == 1)
15008       requestType = IndexStatReq::RT_DROP_HEAD;
15009     else if (subOpIndex == 2)
15010       requestType = IndexStatReq::RT_CLEAN_ALL;
15011     break;
15012   };
15013 
15014   ndbrequire(requestType != 0);
15015   Callback c = {
15016     safe_cast(&Dbdict::indexStat_fromIndexStat),
15017     op_ptr.p->op_key
15018   };
15019   op_ptr.p->m_callback = c;
15020   indexStat_toIndexStat(signal, op_ptr, requestType);
15021   return true;
15022 }
15023 
15024 void
indexStat_toIndexStat(Signal * signal,SchemaOpPtr op_ptr,Uint32 requestType)15025 Dbdict::indexStat_toIndexStat(Signal* signal, SchemaOpPtr op_ptr,
15026                               Uint32 requestType)
15027 {
15028   D("indexStat_toIndexStat");
15029 
15030   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
15031   IndexStatRecPtr indexStatPtr;
15032   getOpRec(op_ptr, indexStatPtr);
15033   const IndexStatImplReq* impl_req = &indexStatPtr.p->m_request;
15034 
15035   IndexStatReq* req = (IndexStatReq*)signal->getDataPtrSend();
15036 
15037   Uint32 requestInfo = 0;
15038   DictSignal::setRequestType(requestInfo, requestType);
15039   DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
15040 
15041   TableRecordPtr indexPtr;
15042   bool ok = find_object(indexPtr, impl_req->indexId);
15043   ndbrequire(ok);
15044 
15045   req->clientRef = reference();
15046   req->clientData = op_ptr.p->op_key;
15047   req->transId = trans_ptr.p->m_transId;
15048   req->transKey = trans_ptr.p->trans_key;
15049   req->requestInfo = requestInfo;
15050   req->requestFlag = 0;
15051   req->indexId = impl_req->indexId;
15052   req->indexVersion = indexPtr.p->tableVersion;
15053   req->tableId = impl_req->tableId;
15054 
15055   sendSignal(reference(), GSN_INDEX_STAT_REQ,
15056              signal, IndexStatReq::SignalLength, JBB);
15057 }
15058 
15059 void
indexStat_fromIndexStat(Signal * signal,Uint32 op_key,Uint32 ret)15060 Dbdict::indexStat_fromIndexStat(Signal* signal, Uint32 op_key, Uint32 ret)
15061 {
15062   jam();
15063   D("indexStat_fromIndexStat");
15064 
15065   SchemaOpPtr op_ptr;
15066   IndexStatRecPtr indexStatPtr;
15067 
15068   findSchemaOp(op_ptr, indexStatPtr, op_key);
15069   ndbrequire(!op_ptr.isNull());
15070   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
15071 
15072   if (ret == 0) {
15073     jam();
15074     const IndexStatConf* conf =
15075       (const IndexStatConf*)signal->getDataPtr();
15076 
15077     ndbrequire(conf->transId == trans_ptr.p->m_transId);
15078     ndbrequire(indexStatPtr.p->m_subOpIndex < indexStatPtr.p->m_subOpCount);
15079     indexStatPtr.p->m_subOpIndex += 1;
15080     createSubOps(signal, op_ptr);
15081   } else {
15082     jam();
15083     const IndexStatRef* ref =
15084       (const IndexStatRef*)signal->getDataPtr();
15085 
15086     ErrorInfo error;
15087     setError(error, ref);
15088     abortSubOps(signal, op_ptr, error);
15089   }
15090 }
15091 
15092 void
indexStat_reply(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)15093 Dbdict::indexStat_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
15094 {
15095   jam();
15096 
15097   SchemaTransPtr& trans_ptr = op_ptr.p->m_trans_ptr;
15098   IndexStatRecPtr indexStatPtr;
15099   getOpRec(op_ptr, indexStatPtr);
15100 
15101   D("indexStat_reply" << V(indexStatPtr.p->m_request.indexId));
15102 
15103   if (!hasError(error)) {
15104     IndexStatConf* conf = (IndexStatConf*)signal->getDataPtrSend();
15105     conf->senderRef = reference();
15106     conf->clientData = op_ptr.p->m_clientData;
15107     conf->transId = trans_ptr.p->m_transId;
15108 
15109     Uint32 clientRef = op_ptr.p->m_clientRef;
15110     sendSignal(clientRef, GSN_INDEX_STAT_CONF, signal,
15111                IndexStatConf::SignalLength, JBB);
15112   } else {
15113     jam();
15114     IndexStatRef* ref = (IndexStatRef*)signal->getDataPtrSend();
15115     ref->senderRef = reference();
15116     ref->clientData = op_ptr.p->m_clientData;
15117     ref->transId = trans_ptr.p->m_transId;
15118     getError(error, ref);
15119 
15120     Uint32 clientRef = op_ptr.p->m_clientRef;
15121     sendSignal(clientRef, GSN_INDEX_STAT_REF, signal,
15122                IndexStatRef::SignalLength, JBB);
15123   }
15124 }
15125 
15126 // IndexStat: PREPARE
15127 
15128 void
indexStat_prepare(Signal * signal,SchemaOpPtr op_ptr)15129 Dbdict::indexStat_prepare(Signal* signal, SchemaOpPtr op_ptr)
15130 {
15131   jam();
15132   IndexStatRecPtr indexStatPtr;
15133   getOpRec(op_ptr, indexStatPtr);
15134   const IndexStatImplReq* impl_req = &indexStatPtr.p->m_request;
15135 
15136   D("indexStat_prepare" << V(*op_ptr.p));
15137 
15138   if (impl_req->requestType == IndexStatReq::RT_UPDATE_STAT ||
15139       impl_req->requestType == IndexStatReq::RT_DELETE_STAT) {
15140     // the main op of stat update or delete does nothing
15141     sendTransConf(signal, op_ptr);
15142     return;
15143   }
15144 
15145   indexStat_toLocalStat(signal, op_ptr);
15146 }
15147 
15148 static
15149 bool
do_action(const NdbNodeBitmask & mask,const Uint16 list[],Uint16 ownId)15150 do_action(const NdbNodeBitmask & mask, const Uint16 list[], Uint16 ownId)
15151 {
15152   for (Uint32 i = 0; i < MAX_REPLICAS; i++)
15153   {
15154     if (mask.get(list[i]))
15155     {
15156       if (list[i] == ownId)
15157         return true;
15158       return false;
15159     }
15160   }
15161   return false;
15162 }
15163 
15164 void
indexStat_toLocalStat(Signal * signal,SchemaOpPtr op_ptr)15165 Dbdict::indexStat_toLocalStat(Signal* signal, SchemaOpPtr op_ptr)
15166 {
15167   IndexStatRecPtr indexStatPtr;
15168   getOpRec(op_ptr, indexStatPtr);
15169   const IndexStatImplReq* impl_req = &indexStatPtr.p->m_request;
15170   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
15171 
15172   D("indexStat_toLocalStat");
15173 
15174   TableRecordPtr indexPtr;
15175   bool ok = find_object(indexPtr, impl_req->indexId);
15176   ndbrequire(ok && indexPtr.p->isOrderedIndex());
15177 
15178   Callback c = {
15179     safe_cast(&Dbdict::indexStat_fromLocalStat),
15180     op_ptr.p->op_key
15181   };
15182   op_ptr.p->m_callback = c;
15183 
15184   IndexStatImplReq* req = (IndexStatImplReq*)signal->getDataPtrSend();
15185   *req = *impl_req;
15186   req->senderRef = reference();
15187   req->senderData = op_ptr.p->op_key;
15188   ndbrequire(req->fragId == ZNIL);
15189   ndbrequire(indexPtr.p->indexStatFragId != ZNIL);
15190   BlockReference ref = 0;
15191 
15192   switch (impl_req->requestType) {
15193   case IndexStatReq::RT_SCAN_FRAG:
15194     trans_ptr.p->m_abort_on_node_fail = true;
15195     req->fragId = indexPtr.p->indexStatFragId;
15196     if (!do_action(trans_ptr.p->m_nodes, indexPtr.p->indexStatNodes,
15197                    getOwnNodeId()))
15198     {
15199       jam();
15200       D("skip" << V(impl_req->requestType));
15201       execute(signal, c, 0);
15202       return;
15203     }
15204     ref = TRIX_REF;
15205     break;
15206 
15207   case IndexStatReq::RT_CLEAN_NEW:
15208   case IndexStatReq::RT_CLEAN_OLD:
15209   case IndexStatReq::RT_CLEAN_ALL:
15210     /*
15211      * Index stats "v4" does scan deletes via TRIX-SUMA.  But SUMA does
15212      * only local scans so do it on all nodes.
15213      */
15214     req->fragId = ZNIL;
15215     ref = TRIX_REF;
15216     break;
15217 
15218   case IndexStatReq::RT_DROP_HEAD:
15219     req->fragId = indexPtr.p->indexStatFragId;
15220     if (!do_action(trans_ptr.p->m_nodes, indexPtr.p->indexStatNodes,
15221                    getOwnNodeId()))
15222     {
15223       jam();
15224       D("skip" << V(impl_req->requestType));
15225       execute(signal, c, 0);
15226       return;
15227     }
15228     ref = TRIX_REF;
15229     break;
15230 
15231   case IndexStatReq::RT_START_MON:
15232     req->fragId = indexPtr.p->indexStatFragId;
15233     if (!do_action(trans_ptr.p->m_nodes, indexPtr.p->indexStatNodes,
15234                    getOwnNodeId()))
15235     {
15236       jam();
15237       req->fragId = ZNIL;
15238     }
15239     ref = DBTUX_REF;
15240     break;
15241 
15242   case IndexStatReq::RT_STOP_MON:
15243     req->fragId = ZNIL;
15244     ref = DBTUX_REF;
15245     break;
15246 
15247   default:
15248     ndbrequire(false); // only sub-ops seen here
15249     break;
15250   }
15251 
15252   sendSignal(ref, GSN_INDEX_STAT_IMPL_REQ,
15253              signal, IndexStatImplReq::SignalLength, JBB);
15254 }
15255 
15256 void
indexStat_fromLocalStat(Signal * signal,Uint32 op_key,Uint32 ret)15257 Dbdict::indexStat_fromLocalStat(Signal* signal, Uint32 op_key, Uint32 ret)
15258 {
15259   SchemaOpPtr op_ptr;
15260   IndexStatRecPtr indexStatPtr;
15261   findSchemaOp(op_ptr, indexStatPtr, op_key);
15262   ndbrequire(!op_ptr.isNull());
15263   const IndexStatImplReq* impl_req = &indexStatPtr.p->m_request;
15264 
15265   if (ret != 0) {
15266     jam();
15267     if (impl_req->requestType != IndexStatReq::RT_CLEAN_OLD &&
15268         impl_req->requestType != IndexStatReq::RT_CLEAN_ALL &&
15269         impl_req->requestType != IndexStatReq::RT_DROP_HEAD) {
15270       jam();
15271       setError(op_ptr, ret, __LINE__);
15272       sendTransRef(signal, op_ptr);
15273       return;
15274     }
15275     D("ignore failed index stat cleanup");
15276   }
15277   sendTransConf(signal, op_ptr);
15278 }
15279 
15280 // IndexStat: COMMIT
15281 
15282 void
indexStat_commit(Signal * signal,SchemaOpPtr op_ptr)15283 Dbdict::indexStat_commit(Signal* signal, SchemaOpPtr op_ptr)
15284 {
15285   jam();
15286   IndexStatRecPtr indexStatPtr;
15287   getOpRec(op_ptr, indexStatPtr);
15288   D("indexStat_commit" << *op_ptr.p);
15289   sendTransConf(signal, op_ptr);
15290 }
15291 
15292 // IndexStat: COMPLETE
15293 
15294 void
indexStat_complete(Signal * signal,SchemaOpPtr op_ptr)15295 Dbdict::indexStat_complete(Signal* signal, SchemaOpPtr op_ptr)
15296 {
15297   jam();
15298   IndexStatRecPtr indexStatPtr;
15299   getOpRec(op_ptr, indexStatPtr);
15300   D("indexStat_complete" << *op_ptr.p);
15301   sendTransConf(signal, op_ptr);
15302 }
15303 
15304 // IndexStat: ABORT
15305 
15306 void
indexStat_abortParse(Signal * signal,SchemaOpPtr op_ptr)15307 Dbdict::indexStat_abortParse(Signal* signal, SchemaOpPtr op_ptr)
15308 {
15309   D("indexStat_abortParse" << *op_ptr.p);
15310   // wl3600_todo
15311   sendTransConf(signal, op_ptr);
15312 }
15313 
15314 void
indexStat_abortPrepare(Signal * signal,SchemaOpPtr op_ptr)15315 Dbdict::indexStat_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
15316 {
15317   D("indexStat_abortPrepare" << *op_ptr.p);
15318 
15319   // nothing to do, entire index table will be dropped
15320   sendTransConf(signal, op_ptr);
15321 }
15322 
15323 // IndexStat: MISC
15324 
15325 void
execINDEX_STAT_CONF(Signal * signal)15326 Dbdict::execINDEX_STAT_CONF(Signal* signal)
15327 {
15328   jamEntry();
15329   const IndexStatConf* conf = (const IndexStatConf*)signal->getDataPtr();
15330   handleDictConf(signal, conf);
15331 }
15332 
15333 void
execINDEX_STAT_REF(Signal * signal)15334 Dbdict::execINDEX_STAT_REF(Signal* signal)
15335 {
15336   jamEntry();
15337   const IndexStatRef* ref = (const IndexStatRef*)signal->getDataPtr();
15338   handleDictRef(signal, ref);
15339 }
15340 
15341 void
execINDEX_STAT_IMPL_CONF(Signal * signal)15342 Dbdict::execINDEX_STAT_IMPL_CONF(Signal* signal)
15343 {
15344   jamEntry();
15345   const IndexStatImplConf* conf = (const IndexStatImplConf*)signal->getDataPtr();
15346   handleDictConf(signal, conf);
15347 }
15348 
15349 void
execINDEX_STAT_IMPL_REF(Signal * signal)15350 Dbdict::execINDEX_STAT_IMPL_REF(Signal* signal)
15351 {
15352   jamEntry();
15353   const IndexStatImplRef* ref = (const IndexStatImplRef*)signal->getDataPtr();
15354   handleDictRef(signal, ref);
15355 }
15356 
15357 // IndexStat: background processing
15358 
15359 /*
15360  * Receive report that an index needs stats update.  Request to
15361  * non-master is sent to master.  Index is marked for stats update.
15362  * Invalid request is simply ignored.  Master-NF really need not be
15363  * handled but could be, by broadcasting all reports to all DICTs.
15364  */
15365 void
execINDEX_STAT_REP(Signal * signal)15366 Dbdict::execINDEX_STAT_REP(Signal* signal)
15367 {
15368   const IndexStatRep* rep = (const IndexStatRep*)signal->getDataPtr();
15369 
15370   // non-master
15371   if (c_masterNodeId != getOwnNodeId()) {
15372     jam();
15373     BlockReference dictRef = calcDictBlockRef(c_masterNodeId);
15374     sendSignal(dictRef, GSN_INDEX_STAT_REP, signal,
15375                IndexStatRep::SignalLength, JBB);
15376     return;
15377   }
15378 
15379   // check
15380   TableRecordPtr indexPtr;
15381   if (rep->indexId >= c_noOfMetaTables) {
15382     jam();
15383     return;
15384   }
15385   XSchemaFile* xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
15386   const SchemaFile::TableEntry* te = getTableEntry(xsf, rep->indexId);
15387   if (te->m_tableState != SchemaFile::SF_IN_USE) {
15388     jam();
15389     return;
15390   }
15391   bool ok = find_object(indexPtr, rep->indexId);
15392   if (!ok)
15393   {
15394     jam();
15395     return;
15396   }
15397   if (rep->indexVersion != 0 &&
15398       rep->indexVersion != indexPtr.p->tableVersion) {
15399     jam();
15400     return;
15401   }
15402   if (!indexPtr.p->isOrderedIndex()) {
15403     jam();
15404     return;
15405   }
15406   if (rep->requestType != IndexStatRep::RT_UPDATE_REQ) {
15407     jam();
15408     return;
15409   }
15410 
15411   D("index stat: " << copyRope<MAX_TAB_NAME_SIZE>(indexPtr.p->tableName)
15412     << " request type:" << rep->requestType);
15413 
15414   infoEvent("DICT: index %u stats auto-update requested", rep->indexId);
15415   indexPtr.p->indexStatBgRequest = rep->requestType;
15416 }
15417 
15418 void
indexStatBg_process(Signal * signal)15419 Dbdict::indexStatBg_process(Signal* signal)
15420 {
15421   if (!c_indexStatAutoUpdate ||
15422       c_masterNodeId != getOwnNodeId() ||
15423       getNodeState().startLevel != NodeState::SL_STARTED) {
15424     jam();
15425     indexStatBg_sendContinueB(signal);
15426     return;
15427   }
15428 
15429   D("indexStatBg_process" << V(c_indexStatBgId));
15430   const uint maxloop = 32;
15431   uint loop;
15432   for (loop = 0; loop < maxloop; loop++, c_indexStatBgId++) {
15433     jam();
15434     c_indexStatBgId %= c_noOfMetaTables;
15435 
15436     // check
15437     TableRecordPtr indexPtr;
15438     XSchemaFile* xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
15439     const SchemaFile::TableEntry* te = getTableEntry(xsf, c_indexStatBgId);
15440     if (te->m_tableState != SchemaFile::SF_IN_USE) {
15441       jam();
15442       continue;
15443     }
15444     bool ok = find_object(indexPtr, c_indexStatBgId);
15445     if (!ok || !indexPtr.p->isOrderedIndex()) {
15446       jam();
15447       continue;
15448     }
15449     if (indexPtr.p->indexStatBgRequest == 0) {
15450       jam();
15451       continue;
15452     }
15453     ndbrequire(indexPtr.p->indexStatBgRequest == IndexStatRep::RT_UPDATE_REQ);
15454 
15455     TxHandlePtr tx_ptr;
15456     if (!seizeTxHandle(tx_ptr)) {
15457       jam();
15458       return; // wait for one
15459     }
15460     Callback c = {
15461       safe_cast(&Dbdict::indexStatBg_fromBeginTrans),
15462       tx_ptr.p->tx_key
15463     };
15464     tx_ptr.p->m_callback = c;
15465     beginSchemaTrans(signal, tx_ptr);
15466     return;
15467   }
15468 
15469   indexStatBg_sendContinueB(signal);
15470 }
15471 
15472 void
indexStatBg_fromBeginTrans(Signal * signal,Uint32 tx_key,Uint32 ret)15473 Dbdict::indexStatBg_fromBeginTrans(Signal* signal, Uint32 tx_key, Uint32 ret)
15474 {
15475   D("indexStatBg_fromBeginTrans" << V(c_indexStatBgId) << V(tx_key) << V(ret));
15476 
15477   TxHandlePtr tx_ptr;
15478   findTxHandle(tx_ptr, tx_key);
15479   ndbrequire(!tx_ptr.isNull());
15480 
15481   if (ret != 0) {
15482     jam();
15483     indexStatBg_sendContinueB(signal);
15484     return;
15485   }
15486 
15487   TableRecordPtr indexPtr;
15488   bool ok = find_object(indexPtr, c_indexStatBgId);
15489   ndbrequire(ok);
15490 
15491   Callback c = {
15492     safe_cast(&Dbdict::indexStatBg_fromIndexStat),
15493     tx_ptr.p->tx_key
15494   };
15495   tx_ptr.p->m_callback = c;
15496 
15497   IndexStatReq* req = (IndexStatReq*)signal->getDataPtrSend();
15498   req->clientRef = reference();
15499   req->clientData = tx_ptr.p->tx_key;
15500   req->transId = tx_ptr.p->m_transId;
15501   req->transKey = tx_ptr.p->m_transKey;
15502   req->requestInfo = IndexStatReq::RT_UPDATE_STAT;
15503   req->requestFlag = 0;
15504   req->indexId = c_indexStatBgId;
15505   req->indexVersion = indexPtr.p->tableVersion;
15506   req->tableId = indexPtr.p->primaryTableId;
15507   sendSignal(reference(), GSN_INDEX_STAT_REQ,
15508              signal, IndexStatReq::SignalLength, JBB);
15509 }
15510 
15511 void
indexStatBg_fromIndexStat(Signal * signal,Uint32 tx_key,Uint32 ret)15512 Dbdict::indexStatBg_fromIndexStat(Signal* signal, Uint32 tx_key, Uint32 ret)
15513 {
15514   D("indexStatBg_fromIndexStat" << V(c_indexStatBgId) << V(tx_key) << (ret));
15515 
15516   TxHandlePtr tx_ptr;
15517   findTxHandle(tx_ptr, tx_key);
15518   ndbrequire(!tx_ptr.isNull());
15519 
15520   if (ret != 0) {
15521     jam();
15522     setError(tx_ptr.p->m_error, ret, __LINE__);
15523     warningEvent("DICT: index %u stats auto-update error: %d", c_indexStatBgId, ret);
15524   }
15525 
15526   Callback c = {
15527     safe_cast(&Dbdict::indexStatBg_fromEndTrans),
15528     tx_ptr.p->tx_key
15529   };
15530   tx_ptr.p->m_callback = c;
15531 
15532   Uint32 flags = 0;
15533   if (hasError(tx_ptr.p->m_error))
15534     flags |= SchemaTransEndReq::SchemaTransAbort;
15535   endSchemaTrans(signal, tx_ptr, flags);
15536 }
15537 
15538 void
indexStatBg_fromEndTrans(Signal * signal,Uint32 tx_key,Uint32 ret)15539 Dbdict::indexStatBg_fromEndTrans(Signal* signal, Uint32 tx_key, Uint32 ret)
15540 {
15541   D("indexStatBg_fromEndTrans" << V(c_indexStatBgId) << V(tx_key) << (ret));
15542 
15543   TxHandlePtr tx_ptr;
15544   findTxHandle(tx_ptr, tx_key);
15545   ndbrequire(!tx_ptr.isNull());
15546 
15547   TableRecordPtr indexPtr;
15548   bool ok = find_object(indexPtr, c_indexStatBgId);
15549 
15550   if (ret != 0) {
15551     jam();
15552     // skip over but leave the request on
15553     warningEvent("DICT: index %u stats auto-update error: %d", c_indexStatBgId, ret);
15554   } else {
15555     jam();
15556     ndbrequire(ok);
15557     // mark request done
15558     indexPtr.p->indexStatBgRequest = 0;
15559     infoEvent("DICT: index %u stats auto-update done", c_indexStatBgId);
15560   }
15561 
15562   releaseTxHandle(tx_ptr);
15563   c_indexStatBgId++;
15564   indexStatBg_sendContinueB(signal);
15565 }
15566 
15567 void
indexStatBg_sendContinueB(Signal * signal)15568 Dbdict::indexStatBg_sendContinueB(Signal* signal)
15569 {
15570   D("indexStatBg_sendContinueB" << V(c_indexStatBgId));
15571   signal->theData[0] = ZINDEX_STAT_BG_PROCESS;
15572   sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 1000, 1);
15573 }
15574 
15575 // IndexStat: END
15576 
15577 // MODULE: CopyData
15578 
15579 const Dbdict::OpInfo
15580 Dbdict::CopyDataRec::g_opInfo = {
15581   { 'D', 'C', 'D', 0 },
15582   ~RT_DBDICT_COPY_DATA,
15583   GSN_COPY_DATA_IMPL_REQ,
15584   CopyDataImplReq::SignalLength,
15585 
15586   //
15587   &Dbdict::copyData_seize,
15588   &Dbdict::copyData_release,
15589   //
15590   &Dbdict::copyData_parse,
15591   &Dbdict::copyData_subOps,
15592   &Dbdict::copyData_reply,
15593   //
15594   &Dbdict::copyData_prepare,
15595   &Dbdict::copyData_commit,
15596   &Dbdict::copyData_complete,
15597   //
15598   &Dbdict::copyData_abortParse,
15599   &Dbdict::copyData_abortPrepare
15600 };
15601 
15602 bool
copyData_seize(SchemaOpPtr op_ptr)15603 Dbdict::copyData_seize(SchemaOpPtr op_ptr)
15604 {
15605   return seizeOpRec<CopyDataRec>(op_ptr);
15606 }
15607 
15608 void
copyData_release(SchemaOpPtr op_ptr)15609 Dbdict::copyData_release(SchemaOpPtr op_ptr)
15610 {
15611   releaseOpRec<CopyDataRec>(op_ptr);
15612 }
15613 
15614 void
execCOPY_DATA_REQ(Signal * signal)15615 Dbdict::execCOPY_DATA_REQ(Signal* signal)
15616 {
15617   jamEntry();
15618   if (!assembleFragments(signal)) {
15619     jam();
15620     return;
15621   }
15622   SectionHandle handle(this, signal);
15623 
15624   const CopyDataReq req_copy =
15625     *(const CopyDataReq*)signal->getDataPtr();
15626   const CopyDataReq* req = &req_copy;
15627 
15628   ErrorInfo error;
15629   do {
15630     SchemaOpPtr op_ptr;
15631     CopyDataRecPtr copyDataPtr;
15632     CopyDataImplReq* impl_req;
15633 
15634     startClientReq(op_ptr, copyDataPtr, req, impl_req, error);
15635     if (hasError(error)) {
15636       jam();
15637       break;
15638     }
15639 
15640     impl_req->srcTableId = req->srcTableId;
15641     impl_req->dstTableId = req->dstTableId;
15642     impl_req->srcFragments = req->srcFragments;
15643 
15644     handleClientReq(signal, op_ptr, handle);
15645     return;
15646   } while (0);
15647 
15648   releaseSections(handle);
15649 
15650   CopyDataRef* ref = (CopyDataRef*)signal->getDataPtrSend();
15651   ref->senderRef = reference();
15652   ref->senderData = req->clientData;
15653   ref->transId = req->transId;
15654   getError(error, ref);
15655 
15656   sendSignal(req->clientRef, GSN_COPY_DATA_REF, signal,
15657              CopyDataRef::SignalLength, JBB);
15658 }
15659 
15660 // CopyData: PARSE
15661 
15662 void
copyData_parse(Signal * signal,bool master,SchemaOpPtr op_ptr,SectionHandle & handle,ErrorInfo & error)15663 Dbdict::copyData_parse(Signal* signal, bool master,
15664                        SchemaOpPtr op_ptr,
15665                        SectionHandle& handle, ErrorInfo& error)
15666 {
15667   D("copyData_parse");
15668 
15669   /**
15670    * Nothing here...
15671    */
15672 }
15673 
15674 bool
copyData_subOps(Signal * signal,SchemaOpPtr op_ptr)15675 Dbdict::copyData_subOps(Signal* signal, SchemaOpPtr op_ptr)
15676 {
15677   D("copyData_subOps" << V(op_ptr.i) << *op_ptr.p);
15678 
15679   return false;
15680 }
15681 
15682 void
copyData_reply(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)15683 Dbdict::copyData_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
15684 {
15685   jam();
15686 
15687   SchemaTransPtr& trans_ptr = op_ptr.p->m_trans_ptr;
15688   CopyDataRecPtr copyDataPtr;
15689   getOpRec(op_ptr, copyDataPtr);
15690   //const CopyDataImplReq* impl_req = &copyDataPtr.p->m_request;
15691 
15692   if (!hasError(error)) {
15693     CopyDataConf* conf = (CopyDataConf*)signal->getDataPtrSend();
15694     conf->senderRef = reference();
15695     conf->senderData = op_ptr.p->m_clientData;
15696     conf->transId = trans_ptr.p->m_transId;
15697 
15698     Uint32 clientRef = op_ptr.p->m_clientRef;
15699     sendSignal(clientRef, GSN_COPY_DATA_CONF, signal,
15700                CopyDataConf::SignalLength, JBB);
15701   } else {
15702     jam();
15703     CopyDataRef* ref = (CopyDataRef*)signal->getDataPtrSend();
15704     ref->senderRef = reference();
15705     ref->senderData = op_ptr.p->m_clientData;
15706     ref->transId = trans_ptr.p->m_transId;
15707     getError(error, ref);
15708 
15709     Uint32 clientRef = op_ptr.p->m_clientRef;
15710     sendSignal(clientRef, GSN_COPY_DATA_REF, signal,
15711                CopyDataRef::SignalLength, JBB);
15712   }
15713 }
15714 
15715 // CopyData: PREPARE
15716 
15717 void
copyData_prepare(Signal * signal,SchemaOpPtr op_ptr)15718 Dbdict::copyData_prepare(Signal* signal, SchemaOpPtr op_ptr)
15719 {
15720   jam();
15721 
15722   CopyDataRecPtr copyDataPtr;
15723   getOpRec(op_ptr, copyDataPtr);
15724   const CopyDataImplReq* impl_req = &copyDataPtr.p->m_request;
15725   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
15726 
15727   CopyDataImplReq* req = (CopyDataImplReq*)signal->getDataPtrSend();
15728   * req = * impl_req;
15729   req->senderRef = reference();
15730   req->senderData = op_ptr.p->op_key;
15731   req->transId = trans_ptr.p->m_transId;
15732   req->srcFragments = 0; // All
15733 
15734   Callback c = {
15735     safe_cast(&Dbdict::copyData_fromLocal),
15736     op_ptr.p->op_key
15737   };
15738   op_ptr.p->m_callback = c;
15739 
15740   Uint32 cnt =0;
15741   Uint32 tmp[MAX_ATTRIBUTES_IN_TABLE];
15742   bool tabHasDiskCols = false;
15743   TableRecordPtr tabPtr;
15744   bool ok = find_object(tabPtr, impl_req->srcTableId);
15745   ndbrequire(ok);
15746   {
15747     LocalAttributeRecord_list alist(c_attributeRecordPool,
15748                                            tabPtr.p->m_attributes);
15749     AttributeRecordPtr attrPtr;
15750     for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr))
15751     {
15752       if (AttributeDescriptor::getPrimaryKey(attrPtr.p->attributeDescriptor))
15753         tmp[cnt++] = attrPtr.p->attributeId;
15754     }
15755     for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr))
15756     {
15757       if (!AttributeDescriptor::getPrimaryKey(attrPtr.p->attributeDescriptor))
15758       {
15759         tmp[cnt++] = attrPtr.p->attributeId;
15760 
15761         if (AttributeDescriptor::getDiskBased(attrPtr.p->attributeDescriptor))
15762           tabHasDiskCols = true;
15763       }
15764     }
15765   }
15766 
15767   /* Request Tup-ordered copy when we have disk columns for efficiency */
15768   if (tabHasDiskCols)
15769   {
15770     jam();
15771     req->requestInfo |= CopyDataReq::TupOrder;
15772   }
15773 
15774   LinearSectionPtr ls_ptr[3];
15775   ls_ptr[0].sz = cnt;
15776   ls_ptr[0].p = tmp;
15777 
15778   sendSignal(TRIX_REF, GSN_COPY_DATA_IMPL_REQ, signal,
15779              CopyDataImplReq::SignalLength, JBB, ls_ptr, 1);
15780 }
15781 
15782 void
copyData_fromLocal(Signal * signal,Uint32 op_key,Uint32 ret)15783 Dbdict::copyData_fromLocal(Signal* signal, Uint32 op_key, Uint32 ret)
15784 {
15785   SchemaOpPtr op_ptr;
15786   CopyDataRecPtr copyDataPtr;
15787   findSchemaOp(op_ptr, copyDataPtr, op_key);
15788   ndbrequire(!op_ptr.isNull());
15789 
15790   if (ERROR_INSERTED(6214))
15791   {
15792     CLEAR_ERROR_INSERT_VALUE;
15793     ret = 1;
15794   }
15795 
15796   if (ret == 0) {
15797     jam();
15798     sendTransConf(signal, op_ptr);
15799   } else {
15800     jam();
15801     setError(op_ptr, ret, __LINE__);
15802     sendTransRef(signal, op_ptr);
15803   }
15804 }
15805 
15806 
15807 // CopyData: COMMIT
15808 
15809 void
copyData_commit(Signal * signal,SchemaOpPtr op_ptr)15810 Dbdict::copyData_commit(Signal* signal, SchemaOpPtr op_ptr)
15811 {
15812   jam();
15813 
15814   sendTransConf(signal, op_ptr);
15815 }
15816 
15817 // CopyData: COMPLETE
15818 
15819 void
copyData_complete(Signal * signal,SchemaOpPtr op_ptr)15820 Dbdict::copyData_complete(Signal* signal, SchemaOpPtr op_ptr)
15821 {
15822   jam();
15823 
15824   CopyDataRecPtr copyDataPtr;
15825   getOpRec(op_ptr, copyDataPtr);
15826   const CopyDataImplReq* impl_req = &copyDataPtr.p->m_request;
15827   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
15828 
15829   CopyDataImplReq* req = (CopyDataImplReq*)signal->getDataPtrSend();
15830   * req = * impl_req;
15831   req->senderRef = reference();
15832   req->senderData = op_ptr.p->op_key;
15833   req->transId = trans_ptr.p->m_transId;
15834   req->requestType = CopyDataImplReq::ReorgDelete;
15835 
15836   Callback c = {
15837     safe_cast(&Dbdict::copyData_fromLocal),
15838     op_ptr.p->op_key
15839   };
15840   op_ptr.p->m_callback = c;
15841 
15842   Uint32 cnt =0;
15843   Uint32 tmp[MAX_ATTRIBUTES_IN_TABLE];
15844   bool tabHasDiskCols = false;
15845   TableRecordPtr tabPtr;
15846   bool ok = find_object(tabPtr, impl_req->srcTableId);
15847   ndbrequire(ok);
15848   {
15849     LocalAttributeRecord_list alist(c_attributeRecordPool,
15850                                            tabPtr.p->m_attributes);
15851     AttributeRecordPtr attrPtr;
15852     for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr))
15853     {
15854       if (AttributeDescriptor::getPrimaryKey(attrPtr.p->attributeDescriptor))
15855         tmp[cnt++] = attrPtr.p->attributeId;
15856       else
15857       {
15858         if (AttributeDescriptor::getDiskBased(attrPtr.p->attributeDescriptor))
15859           tabHasDiskCols = true;
15860       }
15861     }
15862   }
15863 
15864   /* Request Tup-ordered delete when we have disk columns for efficiency */
15865   if (tabHasDiskCols)
15866   {
15867     jam();
15868     req->requestInfo |= CopyDataReq::TupOrder;
15869   }
15870 
15871   LinearSectionPtr ls_ptr[3];
15872   ls_ptr[0].sz = cnt;
15873   ls_ptr[0].p = tmp;
15874 
15875   sendSignal(TRIX_REF, GSN_COPY_DATA_IMPL_REQ, signal,
15876              CopyDataImplReq::SignalLength, JBB, ls_ptr, 1);
15877 }
15878 
15879 // CopyData: ABORT
15880 
15881 void
copyData_abortParse(Signal * signal,SchemaOpPtr op_ptr)15882 Dbdict::copyData_abortParse(Signal* signal, SchemaOpPtr op_ptr)
15883 {
15884   D("copyData_abortParse" << *op_ptr.p);
15885   // wl3600_todo
15886   sendTransConf(signal, op_ptr);
15887 }
15888 
15889 void
copyData_abortPrepare(Signal * signal,SchemaOpPtr op_ptr)15890 Dbdict::copyData_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
15891 {
15892   D("copyData_abortPrepare" << *op_ptr.p);
15893 
15894   // nothing to do, entire index table will be dropped
15895   sendTransConf(signal, op_ptr);
15896 }
15897 
15898 void
execCOPY_DATA_CONF(Signal * signal)15899 Dbdict::execCOPY_DATA_CONF(Signal* signal)
15900 {
15901   jamEntry();
15902   const CopyDataConf* conf = (const CopyDataConf*)signal->getDataPtr();
15903   handleDictConf(signal, conf);
15904 }
15905 
15906 void
execCOPY_DATA_REF(Signal * signal)15907 Dbdict::execCOPY_DATA_REF(Signal* signal)
15908 {
15909   jamEntry();
15910   const CopyDataRef* ref = (const CopyDataRef*)signal->getDataPtr();
15911   handleDictRef(signal, ref);
15912 }
15913 
15914 void
execCOPY_DATA_IMPL_CONF(Signal * signal)15915 Dbdict::execCOPY_DATA_IMPL_CONF(Signal* signal)
15916 {
15917   jamEntry();
15918   const CopyDataImplConf* conf = (const CopyDataImplConf*)signal->getDataPtr();
15919   ndbrequire(refToNode(conf->senderRef) == getOwnNodeId());
15920   handleDictConf(signal, conf);
15921 }
15922 
15923 void
execCOPY_DATA_IMPL_REF(Signal * signal)15924 Dbdict::execCOPY_DATA_IMPL_REF(Signal* signal)
15925 {
15926   jamEntry();
15927   const CopyDataImplRef* ref = (const CopyDataImplRef*)signal->getDataPtr();
15928   ndbrequire(refToNode(ref->senderRef) == getOwnNodeId());
15929   handleDictRef(signal, ref);
15930 }
15931 
15932 
15933 // CopyData: END
15934 
15935 
15936 /*****************************************************
15937  *
15938  * MODULE: Util signalling
15939  *
15940  *****************************************************/
15941 
15942 int
sendSignalUtilReq(Callback * pcallback,BlockReference ref,GlobalSignalNumber gsn,Signal * signal,Uint32 length,JobBufferLevel jbuf,LinearSectionPtr ptr[3],Uint32 noOfSections)15943 Dbdict::sendSignalUtilReq(Callback *pcallback,
15944 			  BlockReference ref,
15945 			  GlobalSignalNumber gsn,
15946 			  Signal* signal,
15947 			  Uint32 length,
15948 			  JobBufferLevel jbuf,
15949 			  LinearSectionPtr ptr[3],
15950 			  Uint32 noOfSections)
15951 {
15952   jam();
15953   EVENT_TRACE;
15954   OpSignalUtilPtr utilRecPtr;
15955 
15956   // Seize a Util Send record
15957   if (!c_opSignalUtil.seize(utilRecPtr)) {
15958     // Failed to allocate util record
15959     return -1;
15960   }
15961   utilRecPtr.p->m_callback = *pcallback;
15962 
15963   // should work for all util signal classes
15964   UtilPrepareReq *req = (UtilPrepareReq*)signal->getDataPtrSend();
15965   utilRecPtr.p->m_userData = req->getSenderData();
15966   req->setSenderData(utilRecPtr.i);
15967 
15968   if (ptr) {
15969     jam();
15970     sendSignal(ref, gsn, signal, length, jbuf, ptr, noOfSections);
15971   } else {
15972     jam();
15973     sendSignal(ref, gsn, signal, length, jbuf);
15974   }
15975 
15976   return 0;
15977 }
15978 
15979 int
recvSignalUtilReq(Signal * signal,Uint32 returnCode)15980 Dbdict::recvSignalUtilReq(Signal* signal, Uint32 returnCode)
15981 {
15982   jam();
15983   EVENT_TRACE;
15984   UtilPrepareConf * const req = (UtilPrepareConf*)signal->getDataPtr();
15985   OpSignalUtilPtr utilRecPtr;
15986   utilRecPtr.i = req->getSenderData();
15987   if ((utilRecPtr.p = c_opSignalUtil.getPtr(utilRecPtr.i)) == NULL) {
15988     jam();
15989     return -1;
15990   }
15991 
15992   req->setSenderData(utilRecPtr.p->m_userData);
15993   Callback c = utilRecPtr.p->m_callback;
15994   c_opSignalUtil.release(utilRecPtr);
15995 
15996   execute(signal, c, returnCode);
15997   return 0;
15998 }
15999 
execUTIL_PREPARE_CONF(Signal * signal)16000 void Dbdict::execUTIL_PREPARE_CONF(Signal *signal)
16001 {
16002   jamEntry();
16003   EVENT_TRACE;
16004   ndbrequire(recvSignalUtilReq(signal, 0) == 0);
16005 }
16006 
16007 void
execUTIL_PREPARE_REF(Signal * signal)16008 Dbdict::execUTIL_PREPARE_REF(Signal *signal)
16009 {
16010   jamEntry();
16011   const UtilPrepareRef * ref = CAST_CONSTPTR(UtilPrepareRef,
16012                                              signal->getDataPtr());
16013   Uint32 code = ref->errorCode;
16014   if (code == UtilPrepareRef::DICT_TAB_INFO_ERROR)
16015     code = ref->dictErrCode;
16016   EVENT_TRACE;
16017   ndbrequire(recvSignalUtilReq(signal, code) == 0);
16018 }
16019 
execUTIL_EXECUTE_CONF(Signal * signal)16020 void Dbdict::execUTIL_EXECUTE_CONF(Signal *signal)
16021 {
16022   jamEntry();
16023   EVENT_TRACE;
16024   ndbrequire(recvSignalUtilReq(signal, 0) == 0);
16025 }
16026 
execUTIL_EXECUTE_REF(Signal * signal)16027 void Dbdict::execUTIL_EXECUTE_REF(Signal *signal)
16028 {
16029   jamEntry();
16030   EVENT_TRACE;
16031 
16032 #ifdef EVENT_DEBUG
16033   UtilExecuteRef * ref = (UtilExecuteRef *)signal->getDataPtrSend();
16034 
16035   ndbout_c("execUTIL_EXECUTE_REF");
16036   ndbout_c("senderData %u",ref->getSenderData());
16037   ndbout_c("errorCode %u",ref->getErrorCode());
16038   ndbout_c("TCErrorCode %u",ref->getTCErrorCode());
16039 #endif
16040 
16041   ndbrequire(recvSignalUtilReq(signal, 1) == 0);
16042 }
execUTIL_RELEASE_CONF(Signal * signal)16043 void Dbdict::execUTIL_RELEASE_CONF(Signal *signal)
16044 {
16045   jamEntry();
16046   EVENT_TRACE;
16047   ndbrequire(false);
16048   ndbrequire(recvSignalUtilReq(signal, 0) == 0);
16049 }
execUTIL_RELEASE_REF(Signal * signal)16050 void Dbdict::execUTIL_RELEASE_REF(Signal *signal)
16051 {
16052   jamEntry();
16053   EVENT_TRACE;
16054   ndbrequire(false);
16055   ndbrequire(recvSignalUtilReq(signal, 1) == 0);
16056 }
16057 
16058 /**
16059  * MODULE: Create event
16060  *
16061  * Create event in DICT.
16062  *
16063  *
16064  * Request type in CREATE_EVNT signals:
16065  *
16066  * Signalflow see Dbdict.txt
16067  *
16068  */
16069 
16070 /*****************************************************************
16071  *
16072  * Systable stuff
16073  *
16074  */
16075 
16076 static const
16077 Uint32
16078 sysTab_NDBEVENTS_0_szs[] =
16079 {
16080   sizeof(((sysTab_NDBEVENTS_0*)0)->NAME),
16081   sizeof(((sysTab_NDBEVENTS_0*)0)->EVENT_TYPE),
16082   sizeof(((sysTab_NDBEVENTS_0*)0)->TABLEID),
16083   sizeof(((sysTab_NDBEVENTS_0*)0)->TABLEVERSION),
16084   sizeof(((sysTab_NDBEVENTS_0*)0)->TABLE_NAME),
16085   sizeof(((sysTab_NDBEVENTS_0*)0)->ATTRIBUTE_MASK),
16086   sizeof(((sysTab_NDBEVENTS_0*)0)->SUBID),
16087   sizeof(((sysTab_NDBEVENTS_0*)0)->SUBKEY),
16088   sizeof(((sysTab_NDBEVENTS_0*)0)->ATTRIBUTE_MASK2)
16089 };
16090 
16091 static const
16092 UintPtr
16093 sysTab_NDBEVENTS_0_offsets[] =
16094 {
16095   (UintPtr)&(((sysTab_NDBEVENTS_0*)0)->NAME),
16096   (UintPtr)&(((sysTab_NDBEVENTS_0*)0)->EVENT_TYPE),
16097   (UintPtr)&(((sysTab_NDBEVENTS_0*)0)->TABLEID),
16098   (UintPtr)&(((sysTab_NDBEVENTS_0*)0)->TABLEVERSION),
16099   (UintPtr)&(((sysTab_NDBEVENTS_0*)0)->TABLE_NAME),
16100   (UintPtr)&(((sysTab_NDBEVENTS_0*)0)->ATTRIBUTE_MASK),
16101   (UintPtr)&(((sysTab_NDBEVENTS_0*)0)->SUBID),
16102   (UintPtr)&(((sysTab_NDBEVENTS_0*)0)->SUBKEY),
16103   (UintPtr)&(((sysTab_NDBEVENTS_0*)0)->ATTRIBUTE_MASK2)
16104 };
16105 
16106 void
prepareTransactionEventSysTable(Callback * pcallback,Signal * signal,Uint32 senderData,UtilPrepareReq::OperationTypeValue prepReq)16107 Dbdict::prepareTransactionEventSysTable (Callback *pcallback,
16108 					 Signal* signal,
16109 					 Uint32 senderData,
16110 					 UtilPrepareReq::OperationTypeValue prepReq)
16111 {
16112   // find table id for event system table
16113   DictObject * opj_ptr_p = get_object(EVENT_SYSTEM_TABLE_NAME,
16114 				      sizeof(EVENT_SYSTEM_TABLE_NAME));
16115 
16116   ndbrequire(opj_ptr_p != 0);
16117   TableRecordPtr tablePtr;
16118   c_tableRecordPool_.getPtr(tablePtr, opj_ptr_p->m_object_ptr_i);
16119   ndbrequire(tablePtr.i != RNIL); // system table must exist
16120 
16121   Uint32 tableId = tablePtr.p->tableId; /* System table */
16122   Uint32 noAttr = tablePtr.p->noOfAttributes;
16123   if (noAttr > EVENT_SYSTEM_TABLE_LENGTH)
16124   {
16125     jam();
16126     noAttr = EVENT_SYSTEM_TABLE_LENGTH;
16127   }
16128 
16129   switch (prepReq) {
16130   case UtilPrepareReq::Update:
16131   case UtilPrepareReq::Insert:
16132   case UtilPrepareReq::Write:
16133   case UtilPrepareReq::Read:
16134     jam();
16135     break;
16136   case UtilPrepareReq::Delete:
16137     jam();
16138     noAttr = 1; // only involves Primary key which should be the first
16139     break;
16140   case UtilPrepareReq::Probe:
16141     ndbrequire(false);
16142   }
16143   prepareUtilTransaction(pcallback, signal, senderData, tableId, NULL,
16144 		      prepReq, noAttr, NULL, NULL);
16145 }
16146 
16147 void
prepareUtilTransaction(Callback * pcallback,Signal * signal,Uint32 senderData,Uint32 tableId,const char * tableName,UtilPrepareReq::OperationTypeValue prepReq,Uint32 noAttr,Uint32 attrIds[],const char * attrNames[])16148 Dbdict::prepareUtilTransaction(Callback *pcallback,
16149 			       Signal* signal,
16150 			       Uint32 senderData,
16151 			       Uint32 tableId,
16152 			       const char* tableName,
16153 			       UtilPrepareReq::OperationTypeValue prepReq,
16154 			       Uint32 noAttr,
16155 			       Uint32 attrIds[],
16156 			       const char *attrNames[])
16157 {
16158   jam();
16159   EVENT_TRACE;
16160 
16161   UtilPrepareReq * utilPrepareReq =
16162     (UtilPrepareReq *)signal->getDataPtrSend();
16163 
16164   utilPrepareReq->setSenderRef(reference());
16165   utilPrepareReq->setSenderData(senderData);
16166 
16167   const Uint32 pageSizeInWords = 128;
16168   Uint32 propPage[pageSizeInWords];
16169   LinearWriter w(&propPage[0],128);
16170   w.first();
16171   w.add(UtilPrepareReq::NoOfOperations, 1);
16172   w.add(UtilPrepareReq::OperationType, prepReq);
16173   if (tableName) {
16174     jam();
16175     w.add(UtilPrepareReq::TableName, tableName);
16176   } else {
16177     jam();
16178     w.add(UtilPrepareReq::TableId, tableId);
16179   }
16180   for(Uint32 i = 0; i < noAttr; i++)
16181     if (tableName) {
16182       jam();
16183       w.add(UtilPrepareReq::AttributeName, attrNames[i]);
16184     } else {
16185       if (attrIds) {
16186 	jam();
16187 	w.add(UtilPrepareReq::AttributeId, attrIds[i]);
16188       } else {
16189 	jam();
16190 	w.add(UtilPrepareReq::AttributeId, i);
16191       }
16192     }
16193 #ifdef EVENT_DEBUG
16194   // Debugging
16195   SimplePropertiesLinearReader reader(propPage, w.getWordsUsed());
16196   printf("Dict::prepareInsertTransactions: Sent SimpleProperties:\n");
16197   reader.printAll(ndbout);
16198 #endif
16199 
16200   struct LinearSectionPtr sectionsPtr[UtilPrepareReq::NoOfSections];
16201   sectionsPtr[UtilPrepareReq::PROPERTIES_SECTION].p = propPage;
16202   sectionsPtr[UtilPrepareReq::PROPERTIES_SECTION].sz = w.getWordsUsed();
16203 
16204   sendSignalUtilReq(pcallback, DBUTIL_REF, GSN_UTIL_PREPARE_REQ, signal,
16205 		    UtilPrepareReq::SignalLength, JBB,
16206 		    sectionsPtr, UtilPrepareReq::NoOfSections);
16207 }
16208 
16209 /*****************************************************************
16210  *
16211  * CREATE_EVNT_REQ has three types RT_CREATE, RT_GET (from user)
16212  * and RT_DICT_AFTER_GET send from master DICT to slaves
16213  *
16214  * This function just dscpaches these to
16215  *
16216  * createEvent_RT_USER_CREATE
16217  * createEvent_RT_USER_GET
16218  * createEvent_RT_DICT_AFTER_GET
16219  *
16220  * repectively
16221  *
16222  */
16223 
16224 void
execCREATE_EVNT_REQ(Signal * signal)16225 Dbdict::execCREATE_EVNT_REQ(Signal* signal)
16226 {
16227   jamEntry();
16228 
16229   CreateEvntReq *req = (CreateEvntReq*)signal->getDataPtr();
16230 
16231   if (! assembleFragments(signal)) {
16232     jam();
16233     return;
16234   }
16235 
16236   const CreateEvntReq::RequestType requestType = req->getRequestType();
16237   const Uint32                     requestFlag = req->getRequestFlag();
16238   SectionHandle handle(this, signal);
16239 
16240   if (refToBlock(signal->senderBlockRef()) != DBDICT &&
16241       getOwnNodeId() != c_masterNodeId)
16242   {
16243     jam();
16244     releaseSections(handle);
16245 
16246     CreateEvntRef * ref = (CreateEvntRef *)signal->getDataPtrSend();
16247     ref->setUserRef(reference());
16248     ref->setErrorCode(CreateEvntRef::NotMaster);
16249     ref->setErrorLine(__LINE__);
16250     ref->setErrorNode(reference());
16251     ref->setMasterNode(c_masterNodeId);
16252     sendSignal(signal->senderBlockRef(), GSN_CREATE_EVNT_REF, signal,
16253 	       CreateEvntRef::SignalLength2, JBB);
16254     return;
16255   }
16256 
16257   OpCreateEventPtr evntRecPtr;
16258   // Seize a Create Event record
16259   if (!c_opCreateEvent.seize(evntRecPtr)) {
16260     // Failed to allocate event record
16261     jam();
16262     releaseSections(handle);
16263 
16264     CreateEvntRef * ret = (CreateEvntRef *)signal->getDataPtrSend();
16265     ret->senderRef = reference();
16266     ret->setErrorCode(747);
16267     ret->setErrorLine(__LINE__);
16268     ret->setErrorNode(reference());
16269     sendSignal(signal->senderBlockRef(), GSN_CREATE_EVNT_REF, signal,
16270 	       CreateEvntRef::SignalLength, JBB);
16271     return;
16272   }
16273 
16274 #ifdef EVENT_DEBUG
16275   ndbout_c("DBDICT::execCREATE_EVNT_REQ from %u evntRecId = (%d)", refToNode(signal->getSendersBlockRef()), evntRecPtr.i);
16276 #endif
16277 
16278   ndbrequire(req->getUserRef() == signal->getSendersBlockRef());
16279 
16280   evntRecPtr.p->init(req,this);
16281 
16282   if (requestFlag & (Uint32)CreateEvntReq::RT_DICT_AFTER_GET) {
16283     jam();
16284     EVENT_TRACE;
16285     releaseSections(handle);
16286 
16287     if (ERROR_INSERTED(6023))
16288     {
16289       jam();
16290       signal->theData[0] = 9999;
16291       sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 1000, 1);
16292       return;
16293     }
16294 
16295     createEvent_RT_DICT_AFTER_GET(signal, evntRecPtr);
16296     return;
16297   }
16298   if (requestType == CreateEvntReq::RT_USER_GET) {
16299     jam();
16300     EVENT_TRACE;
16301     createEvent_RT_USER_GET(signal, evntRecPtr, handle);
16302     return;
16303   }
16304   if (requestType == CreateEvntReq::RT_USER_CREATE) {
16305     jam();
16306     EVENT_TRACE;
16307     createEvent_RT_USER_CREATE(signal, evntRecPtr, handle);
16308     return;
16309   }
16310 
16311 #ifdef EVENT_DEBUG
16312   ndbout << "Dbdict.cpp: Dbdict::execCREATE_EVNT_REQ other" << endl;
16313 #endif
16314   jam();
16315   releaseSections(handle);
16316 
16317   evntRecPtr.p->m_errorCode = 1;
16318   evntRecPtr.p->m_errorLine = __LINE__;
16319   evntRecPtr.p->m_errorNode = reference();
16320 
16321   createEvent_sendReply(signal, evntRecPtr);
16322 }
16323 
16324 /********************************************************************
16325  *
16326  * Event creation
16327  *
16328  *****************************************************************/
16329 
16330 void
createEvent_RT_USER_CREATE(Signal * signal,OpCreateEventPtr evntRecPtr,SectionHandle & handle)16331 Dbdict::createEvent_RT_USER_CREATE(Signal* signal,
16332 				   OpCreateEventPtr evntRecPtr,
16333 				   SectionHandle& handle)
16334 {
16335   jam();
16336   DBUG_ENTER("Dbdict::createEvent_RT_USER_CREATE");
16337   evntRecPtr.p->m_request.setUserRef(signal->senderBlockRef());
16338 
16339 #ifdef EVENT_DEBUG
16340   ndbout << "Dbdict.cpp: Dbdict::execCREATE_EVNT_REQ RT_USER" << endl;
16341   char buf[128] = {0};
16342   AttributeMask mask = evntRecPtr.p->m_request.getAttrListBitmask();
16343   mask.getText(buf);
16344   ndbout_c("mask = %s", buf);
16345 #endif
16346 
16347   // Interpret the long signal
16348 
16349   SegmentedSectionPtr ssPtr;
16350   // save name and event properties
16351   ndbrequire(handle.getSection(ssPtr, CreateEvntReq::EVENT_NAME_SECTION));
16352 
16353   SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
16354 #ifdef EVENT_DEBUG
16355   r0.printAll(ndbout);
16356 #endif
16357     // event name
16358   if ((!r0.first()) ||
16359       (r0.getValueType() != SimpleProperties::StringValue) ||
16360       (r0.getValueLen() <= 0)) {
16361     jam();
16362     releaseSections(handle);
16363 
16364     evntRecPtr.p->m_errorCode = 1;
16365     evntRecPtr.p->m_errorLine = __LINE__;
16366     evntRecPtr.p->m_errorNode = reference();
16367 
16368     createEvent_sendReply(signal, evntRecPtr);
16369     DBUG_VOID_RETURN;
16370   }
16371   r0.getString(evntRecPtr.p->m_eventRec.NAME);
16372   {
16373     int len = (int)strlen(evntRecPtr.p->m_eventRec.NAME);
16374     memset(evntRecPtr.p->m_eventRec.NAME+len, 0, MAX_TAB_NAME_SIZE-len);
16375 #ifdef EVENT_DEBUG
16376     printf("CreateEvntReq::RT_USER_CREATE; EventName %s, len %u\n",
16377 	   evntRecPtr.p->m_eventRec.NAME, len);
16378     for(int i = 0; i < MAX_TAB_NAME_SIZE/4; i++)
16379       printf("H'%.8x ", ((Uint32*)evntRecPtr.p->m_eventRec.NAME)[i]);
16380     printf("\n");
16381 #endif
16382   }
16383   // table name
16384   if ((!r0.next()) ||
16385       (r0.getValueType() != SimpleProperties::StringValue) ||
16386       (r0.getValueLen() <= 0)) {
16387     jam();
16388 
16389     evntRecPtr.p->m_errorCode = 1;
16390 sendref:
16391     evntRecPtr.p->m_errorLine = __LINE__;
16392     evntRecPtr.p->m_errorNode = reference();
16393 
16394     releaseSections(handle);
16395 
16396     createEvent_sendReply(signal, evntRecPtr);
16397     DBUG_VOID_RETURN;
16398   }
16399   r0.getString(evntRecPtr.p->m_eventRec.TABLE_NAME);
16400   {
16401     int len = (int)strlen(evntRecPtr.p->m_eventRec.TABLE_NAME);
16402     memset(evntRecPtr.p->m_eventRec.TABLE_NAME+len, 0, MAX_TAB_NAME_SIZE-len);
16403   }
16404 
16405   if (handle.m_cnt >= CreateEvntReq::ATTRIBUTE_MASK)
16406   {
16407     jam();
16408     handle.getSection(ssPtr, CreateEvntReq::ATTRIBUTE_MASK);
16409     if (ssPtr.sz >= NDB_ARRAY_SIZE(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2))
16410     {
16411       jam();
16412       evntRecPtr.p->m_errorCode = 1;
16413       goto sendref;
16414     }
16415     bzero(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2,
16416           sizeof(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2));
16417     copy(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2, ssPtr);
16418     memcpy(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK,
16419            evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2,
16420            sizeof(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK));
16421   }
16422   else
16423   {
16424     jam();
16425     AttributeMask_OLD m = evntRecPtr.p->m_request.getAttrListBitmask();
16426     Uint32 sz0 = m.getSizeInWords();
16427     Uint32 sz1 = NDB_ARRAY_SIZE(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK);
16428     ndbrequire(sz1 == sz0);
16429     bzero(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK,
16430           sizeof(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK));
16431     bzero(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2,
16432           sizeof(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2));
16433     BitmaskImpl::assign(sz0, evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK,
16434                         m.rep.data);
16435     BitmaskImpl::assign(sz0, evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2,
16436                         m.rep.data);
16437   }
16438 
16439   releaseSections(handle);
16440 
16441   // Send request to SUMA
16442 
16443   CreateSubscriptionIdReq * sumaIdReq =
16444     (CreateSubscriptionIdReq *)signal->getDataPtrSend();
16445 
16446   // make sure we save the original sender for later
16447   sumaIdReq->senderRef  = reference();
16448   sumaIdReq->senderData = evntRecPtr.i;
16449 #ifdef EVENT_DEBUG
16450   ndbout << "sumaIdReq->senderData = " << sumaIdReq->senderData << endl;
16451 #endif
16452   sendSignal(SUMA_REF, GSN_CREATE_SUBID_REQ, signal,
16453 	     CreateSubscriptionIdReq::SignalLength, JBB);
16454   // we should now return in either execCREATE_SUBID_CONF
16455   // or execCREATE_SUBID_REF
16456   DBUG_VOID_RETURN;
16457 }
16458 
execCREATE_SUBID_REF(Signal * signal)16459 void Dbdict::execCREATE_SUBID_REF(Signal* signal)
16460 {
16461   jamEntry();
16462   DBUG_ENTER("Dbdict::execCREATE_SUBID_REF");
16463   CreateSubscriptionIdRef * const ref =
16464     (CreateSubscriptionIdRef *)signal->getDataPtr();
16465   OpCreateEventPtr evntRecPtr;
16466 
16467   evntRecPtr.i = ref->senderData;
16468   ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
16469 
16470   if (ref->errorCode)
16471   {
16472     evntRecPtr.p->m_errorCode = ref->errorCode;
16473     evntRecPtr.p->m_errorLine = __LINE__;
16474   }
16475   else
16476   {
16477     evntRecPtr.p->m_errorCode = 1;
16478     evntRecPtr.p->m_errorLine = __LINE__;
16479   }
16480   evntRecPtr.p->m_errorNode = reference();
16481 
16482   createEvent_sendReply(signal, evntRecPtr);
16483   DBUG_VOID_RETURN;
16484 }
16485 
execCREATE_SUBID_CONF(Signal * signal)16486 void Dbdict::execCREATE_SUBID_CONF(Signal* signal)
16487 {
16488   jamEntry();
16489   DBUG_ENTER("Dbdict::execCREATE_SUBID_CONF");
16490 
16491   CreateSubscriptionIdConf const * sumaIdConf =
16492     (CreateSubscriptionIdConf *)signal->getDataPtr();
16493 
16494   Uint32 evntRecId = sumaIdConf->senderData;
16495   OpCreateEvent *evntRec;
16496 
16497   ndbrequire((evntRec = c_opCreateEvent.getPtr(evntRecId)) != NULL);
16498 
16499   evntRec->m_request.setEventId(sumaIdConf->subscriptionId);
16500   evntRec->m_request.setEventKey(sumaIdConf->subscriptionKey);
16501 
16502   Callback c = { safe_cast(&Dbdict::createEventUTIL_PREPARE), 0 };
16503 
16504   prepareTransactionEventSysTable(&c, signal, evntRecId,
16505 				  UtilPrepareReq::Insert);
16506   DBUG_VOID_RETURN;
16507 }
16508 
16509 void
createEventComplete_RT_USER_CREATE(Signal * signal,OpCreateEventPtr evntRecPtr)16510 Dbdict::createEventComplete_RT_USER_CREATE(Signal* signal,
16511 					   OpCreateEventPtr evntRecPtr){
16512   jam();
16513   createEvent_sendReply(signal, evntRecPtr);
16514 }
16515 
16516 /*********************************************************************
16517  *
16518  * UTIL_PREPARE, UTIL_EXECUTE
16519  *
16520  * insert or read systable NDB$EVENTS_0
16521  */
16522 
interpretUtilPrepareErrorCode(UtilPrepareRef::ErrorCode errorCode,Uint32 & error,Uint32 & line,const Dbdict * dict)16523 void interpretUtilPrepareErrorCode(UtilPrepareRef::ErrorCode errorCode,
16524 				   Uint32& error, Uint32& line,
16525                                    const Dbdict *dict)
16526 {
16527   DBUG_ENTER("interpretUtilPrepareErrorCode");
16528   switch (errorCode) {
16529   case UtilPrepareRef::NO_ERROR:
16530     jamBlock(dict);
16531     error = 1;
16532     line = __LINE__;
16533     DBUG_VOID_RETURN;
16534   case UtilPrepareRef::PREPARE_SEIZE_ERROR:
16535     jamBlock(dict);
16536     error = 748;
16537     line = __LINE__;
16538     DBUG_VOID_RETURN;
16539   case UtilPrepareRef::PREPARE_PAGES_SEIZE_ERROR:
16540     jamBlock(dict);
16541     error = 748;
16542     line = __LINE__;
16543     DBUG_VOID_RETURN;
16544   case UtilPrepareRef::PREPARED_OPERATION_SEIZE_ERROR:
16545     jamBlock(dict);
16546     error = 748;
16547     line = __LINE__;
16548     DBUG_VOID_RETURN;
16549   case UtilPrepareRef::DICT_TAB_INFO_ERROR:
16550     jamBlock(dict);
16551     error = 748;
16552     line = __LINE__;
16553     DBUG_VOID_RETURN;
16554   case UtilPrepareRef::MISSING_PROPERTIES_SECTION:
16555     jamBlock(dict);
16556     error = 1;
16557     line = __LINE__;
16558     DBUG_VOID_RETURN;
16559   default:
16560     jamBlock(dict);
16561     error = 1;
16562     line = __LINE__;
16563     DBUG_VOID_RETURN;
16564   }
16565   DBUG_VOID_RETURN;
16566 }
16567 
16568 void
createEventUTIL_PREPARE(Signal * signal,Uint32 callbackData,Uint32 returnCode)16569 Dbdict::createEventUTIL_PREPARE(Signal* signal,
16570 				Uint32 callbackData,
16571 				Uint32 returnCode)
16572 {
16573   jam();
16574   EVENT_TRACE;
16575   if (returnCode == 0) {
16576     UtilPrepareConf* const req = (UtilPrepareConf*)signal->getDataPtr();
16577     OpCreateEventPtr evntRecPtr;
16578     jam();
16579     evntRecPtr.i = req->getSenderData();
16580     const Uint32 prepareId = req->getPrepareId();
16581 
16582     ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
16583 
16584     Callback c = { safe_cast(&Dbdict::createEventUTIL_EXECUTE), 0 };
16585 
16586     switch (evntRecPtr.p->m_requestType) {
16587     case CreateEvntReq::RT_USER_GET:
16588       jam();
16589       executeTransEventSysTable(&c, signal,
16590 				evntRecPtr.i, evntRecPtr.p->m_eventRec,
16591 				prepareId, UtilPrepareReq::Read);
16592       break;
16593     case CreateEvntReq::RT_USER_CREATE:
16594       {
16595 	evntRecPtr.p->m_eventRec.EVENT_TYPE =
16596           evntRecPtr.p->m_request.getEventType() | evntRecPtr.p->m_request.getReportFlags();
16597 	evntRecPtr.p->m_eventRec.TABLEID  = evntRecPtr.p->m_request.getTableId();
16598 	evntRecPtr.p->m_eventRec.TABLEVERSION=evntRecPtr.p->m_request.getTableVersion();
16599 	evntRecPtr.p->m_eventRec.SUBID  = evntRecPtr.p->m_request.getEventId();
16600 	evntRecPtr.p->m_eventRec.SUBKEY = evntRecPtr.p->m_request.getEventKey();
16601 	DBUG_PRINT("info",
16602 		   ("CREATE: event name: %s table name: %s table id: %u table version: %u",
16603 		    evntRecPtr.p->m_eventRec.NAME,
16604 		    evntRecPtr.p->m_eventRec.TABLE_NAME,
16605 		    evntRecPtr.p->m_eventRec.TABLEID,
16606 		    evntRecPtr.p->m_eventRec.TABLEVERSION));
16607 
16608       }
16609       jam();
16610       executeTransEventSysTable(&c, signal,
16611 				evntRecPtr.i, evntRecPtr.p->m_eventRec,
16612 				prepareId, UtilPrepareReq::Insert);
16613       break;
16614     default:
16615 #ifdef EVENT_DEBUG
16616       printf("type = %d\n", evntRecPtr.p->m_requestType);
16617       printf("bet type = %d\n", CreateEvntReq::RT_USER_GET);
16618       printf("create type = %d\n", CreateEvntReq::RT_USER_CREATE);
16619 #endif
16620       ndbrequire(false);
16621     }
16622   } else { // returnCode != 0
16623     UtilPrepareRef* const ref = (UtilPrepareRef*)signal->getDataPtr();
16624 
16625     const UtilPrepareRef::ErrorCode errorCode =
16626       (UtilPrepareRef::ErrorCode)ref->getErrorCode();
16627 
16628     OpCreateEventPtr evntRecPtr;
16629     evntRecPtr.i = ref->getSenderData();
16630     ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
16631 
16632     interpretUtilPrepareErrorCode(errorCode, evntRecPtr.p->m_errorCode,
16633 				  evntRecPtr.p->m_errorLine, this);
16634     evntRecPtr.p->m_errorNode = reference();
16635 
16636     createEvent_sendReply(signal, evntRecPtr);
16637   }
16638 }
16639 
16640 static
16641 Uint32
countPrefixBytes(Uint32 len,const Uint8 * mask)16642 countPrefixBytes(Uint32 len, const Uint8 * mask)
16643 {
16644   while (len && mask[len - 1] == 0)
16645     len--;
16646   return len;
16647 }
16648 
executeTransEventSysTable(Callback * pcallback,Signal * signal,const Uint32 ptrI,sysTab_NDBEVENTS_0 & m_eventRec,const Uint32 prepareId,UtilPrepareReq::OperationTypeValue prepReq)16649 void Dbdict::executeTransEventSysTable(Callback *pcallback, Signal *signal,
16650 				       const Uint32 ptrI,
16651 				       sysTab_NDBEVENTS_0& m_eventRec,
16652 				       const Uint32 prepareId,
16653 				       UtilPrepareReq::OperationTypeValue prepReq)
16654 {
16655   jam();
16656 
16657   DictObject * opj_ptr_p = get_object(EVENT_SYSTEM_TABLE_NAME,
16658 				      sizeof(EVENT_SYSTEM_TABLE_NAME));
16659 
16660   ndbrequire(opj_ptr_p != 0);
16661   TableRecordPtr tablePtr;
16662   c_tableRecordPool_.getPtr(tablePtr, opj_ptr_p->m_object_ptr_i);
16663   ndbrequire(tablePtr.i != RNIL); // system table must exist
16664 
16665   Uint32 noAttr = tablePtr.p->noOfAttributes;
16666   if (noAttr > EVENT_SYSTEM_TABLE_LENGTH)
16667   {
16668     jam();
16669     noAttr = EVENT_SYSTEM_TABLE_LENGTH;
16670   }
16671 
16672   Uint32 total_len = 0;
16673 
16674   Uint32* attrHdr = signal->theData + 25;
16675   Uint32* attrPtr = attrHdr;
16676   Uint32* dataPtr = attrHdr + noAttr;
16677 
16678   Uint32 id=0;
16679   // attribute 0 event name: Primary Key
16680   {
16681     char *base = (char*)&m_eventRec;
16682     Uint32 sz = sysTab_NDBEVENTS_0_szs[id];
16683     const Uint32 *src = (const Uint32*)(base +sysTab_NDBEVENTS_0_offsets[id]);
16684     memcpy(dataPtr, src, sz);
16685     dataPtr += (sz / 4);
16686 
16687     AttributeHeader::init(attrPtr, id, sz);
16688     total_len += sz;
16689     attrPtr++; id++;
16690   }
16691 
16692   switch (prepReq) {
16693   case UtilPrepareReq::Read:
16694     jam();
16695     EVENT_TRACE;
16696 
16697     // clear it, since NDB$EVENTS_0.ATTRIBUTE_MASK2 might not be present
16698     bzero(m_eventRec.ATTRIBUTE_MASK2, sizeof(m_eventRec.ATTRIBUTE_MASK2));
16699 
16700     // no more
16701     while ( id < noAttr )
16702       AttributeHeader::init(attrPtr++, id++, 0);
16703     ndbrequire(id == noAttr);
16704     break;
16705   case UtilPrepareReq::Insert:
16706   {
16707     jam();
16708     EVENT_TRACE;
16709     char *base = (char*)&m_eventRec;
16710     while ( id < noAttr )
16711     {
16712       if (id != EVENT_SYSTEM_TABLE_ATTRIBUTE_MASK2_ID)
16713       {
16714         jam();
16715         Uint32 sz = sysTab_NDBEVENTS_0_szs[id];
16716         AttributeHeader::init(attrPtr, id, sz);
16717         const Uint32 *src = (const Uint32*)(base +sysTab_NDBEVENTS_0_offsets[id]);
16718         memcpy(dataPtr, src, sz);
16719         dataPtr += (sz / 4);
16720         total_len += sysTab_NDBEVENTS_0_szs[id];
16721       }
16722       else
16723       {
16724         jam();
16725         Uint32 szBytes = countPrefixBytes(sizeof(m_eventRec.ATTRIBUTE_MASK2) - 4,
16726                                           (Uint8*)m_eventRec.ATTRIBUTE_MASK2);
16727         AttributeHeader::init(attrPtr, id, 2 + szBytes);
16728 
16729         Uint8 * lenbytes = (Uint8*)dataPtr;
16730         lenbytes[0] = (szBytes & 0xFF);
16731         lenbytes[1] = (szBytes / 256);
16732         memcpy(lenbytes + 2, m_eventRec.ATTRIBUTE_MASK2, szBytes);
16733         if (szBytes & 3)
16734         {
16735           bzero(lenbytes + 2 + szBytes, 4 - (szBytes & 3));
16736         }
16737         szBytes += 2;
16738         dataPtr += (szBytes + 3) / 4;
16739         total_len += 4 * ((szBytes + 3) / 4);
16740       }
16741       attrPtr++; id++;
16742     }
16743     break;
16744   }
16745   case UtilPrepareReq::Delete:
16746     ndbrequire(id == 1);
16747     break;
16748   default:
16749     ndbrequire(false);
16750   }
16751 
16752   LinearSectionPtr headerPtr;
16753   LinearSectionPtr lsdataPtr;
16754 
16755   headerPtr.p = attrHdr;
16756   headerPtr.sz = id;
16757 
16758   lsdataPtr.p = attrHdr + noAttr;
16759   lsdataPtr.sz = total_len/4;
16760 
16761 #if 0
16762     printf("Header size %u\n", headerPtr.sz);
16763     for(int i = 0; i < (int)headerPtr.sz; i++)
16764       printf("H'%.8x ", attrHdr[i]);
16765     printf("\n");
16766 
16767     printf("Data size %u\n", lsdataPtr.sz);
16768     for(int i = 0; i < (int)lsdataPtr.sz; i++)
16769       printf("H'%.8x ", dataPage[i]);
16770     printf("\n");
16771 #endif
16772 
16773   executeTransaction(pcallback, signal,
16774 		     ptrI,
16775 		     prepareId,
16776 		     id,
16777 		     headerPtr,
16778 		     lsdataPtr);
16779 }
16780 
executeTransaction(Callback * pcallback,Signal * signal,Uint32 senderData,Uint32 prepareId,Uint32 noAttr,LinearSectionPtr headerPtr,LinearSectionPtr dataPtr)16781 void Dbdict::executeTransaction(Callback *pcallback,
16782 				Signal* signal,
16783 				Uint32 senderData,
16784 				Uint32 prepareId,
16785 				Uint32 noAttr,
16786 				LinearSectionPtr headerPtr,
16787 				LinearSectionPtr dataPtr)
16788 {
16789   jam();
16790   EVENT_TRACE;
16791 
16792   UtilExecuteReq * utilExecuteReq =
16793     (UtilExecuteReq *)signal->getDataPtrSend();
16794 
16795   utilExecuteReq->setSenderRef(reference());
16796   utilExecuteReq->setSenderData(senderData);
16797   utilExecuteReq->setPrepareId(prepareId);
16798   utilExecuteReq->setReleaseFlag(); // must be done after setting prepareId
16799 
16800 #if 0
16801   printf("Header size %u\n", headerPtr.sz);
16802   for(int i = 0; i < (int)headerPtr.sz; i++)
16803     printf("H'%.8x ", headerBuffer[i]);
16804   printf("\n");
16805 
16806   printf("Data size %u\n", dataPtr.sz);
16807   for(int i = 0; i < (int)dataPtr.sz; i++)
16808     printf("H'%.8x ", dataBuffer[i]);
16809   printf("\n");
16810 #endif
16811 
16812   struct LinearSectionPtr sectionsPtr[UtilExecuteReq::NoOfSections];
16813   sectionsPtr[UtilExecuteReq::HEADER_SECTION].p = headerPtr.p;
16814   sectionsPtr[UtilExecuteReq::HEADER_SECTION].sz = noAttr;
16815   sectionsPtr[UtilExecuteReq::DATA_SECTION].p = dataPtr.p;
16816   sectionsPtr[UtilExecuteReq::DATA_SECTION].sz = dataPtr.sz;
16817 
16818   sendSignalUtilReq(pcallback, DBUTIL_REF, GSN_UTIL_EXECUTE_REQ, signal,
16819 		    UtilExecuteReq::SignalLength, JBB,
16820 		    sectionsPtr, UtilExecuteReq::NoOfSections);
16821 }
16822 
parseReadEventSys(Signal * signal,sysTab_NDBEVENTS_0 & m_eventRec)16823 void Dbdict::parseReadEventSys(Signal* signal, sysTab_NDBEVENTS_0& m_eventRec)
16824 {
16825   jam();
16826   SectionHandle handle(this, signal);
16827   SegmentedSectionPtr headerPtr, dataPtr;
16828 
16829   handle.getSection(headerPtr, UtilExecuteReq::HEADER_SECTION);
16830   SectionReader headerReader(headerPtr, getSectionSegmentPool());
16831 
16832   handle.getSection(dataPtr, UtilExecuteReq::DATA_SECTION);
16833   SectionReader dataReader(dataPtr, getSectionSegmentPool());
16834 
16835   char *base = (char*)&m_eventRec;
16836 
16837   DictObject * opj_ptr_p = get_object(EVENT_SYSTEM_TABLE_NAME,
16838 				      sizeof(EVENT_SYSTEM_TABLE_NAME));
16839 
16840   ndbrequire(opj_ptr_p != 0);
16841   TableRecordPtr tablePtr;
16842   c_tableRecordPool_.getPtr(tablePtr, opj_ptr_p->m_object_ptr_i);
16843   ndbrequire(tablePtr.i != RNIL); // system table must exist
16844 
16845   Uint32 noAttr = tablePtr.p->noOfAttributes;
16846   if (noAttr > EVENT_SYSTEM_TABLE_LENGTH)
16847   {
16848     jam();
16849     noAttr = EVENT_SYSTEM_TABLE_LENGTH;
16850   }
16851 
16852   for (Uint32 i = 0; i < noAttr; i++)
16853   {
16854     jam();
16855     Uint32 headerWord;
16856     headerReader.getWord(&headerWord);
16857     Uint32 sz = AttributeHeader::getDataSize(headerWord);
16858     ndbrequire(4 * sz <= sysTab_NDBEVENTS_0_szs[i]);
16859     Uint32 * dst = (Uint32*)(base + sysTab_NDBEVENTS_0_offsets[i]);
16860     for (Uint32 j = 0; j < sz; j++)
16861       dataReader.getWord(dst++);
16862   }
16863 
16864   releaseSections(handle);
16865 
16866   if (noAttr < EVENT_SYSTEM_TABLE_LENGTH)
16867   {
16868     jam();
16869     bzero(m_eventRec.ATTRIBUTE_MASK2, sizeof(m_eventRec.ATTRIBUTE_MASK2));
16870     memcpy(m_eventRec.ATTRIBUTE_MASK2, m_eventRec.ATTRIBUTE_MASK,
16871            sizeof(m_eventRec.ATTRIBUTE_MASK));
16872   }
16873   else
16874   {
16875     jam();
16876     Uint8* lenbytes = (Uint8*)m_eventRec.ATTRIBUTE_MASK2;
16877     Uint32 szBytes  = lenbytes[0] + (lenbytes[1] * 256);
16878     memmove(lenbytes, lenbytes + 2, szBytes);
16879     bzero(lenbytes + szBytes, sizeof(m_eventRec.ATTRIBUTE_MASK2) - szBytes);
16880   }
16881 }
16882 
createEventUTIL_EXECUTE(Signal * signal,Uint32 callbackData,Uint32 returnCode)16883 void Dbdict::createEventUTIL_EXECUTE(Signal *signal,
16884 				     Uint32 callbackData,
16885 				     Uint32 returnCode)
16886 {
16887   jam();
16888   EVENT_TRACE;
16889   if (returnCode == 0) {
16890     // Entry into system table all set
16891     UtilExecuteConf* const conf = (UtilExecuteConf*)signal->getDataPtr();
16892     jam();
16893     OpCreateEventPtr evntRecPtr;
16894     evntRecPtr.i = conf->getSenderData();
16895 
16896     ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
16897     OpCreateEvent *evntRec = evntRecPtr.p;
16898 
16899     switch (evntRec->m_requestType) {
16900     case CreateEvntReq::RT_USER_GET: {
16901       parseReadEventSys(signal, evntRecPtr.p->m_eventRec);
16902 
16903       evntRec->m_request.setEventType(evntRecPtr.p->m_eventRec.EVENT_TYPE);
16904       evntRec->m_request.setReportFlags(evntRecPtr.p->m_eventRec.EVENT_TYPE);
16905       evntRec->m_request.setTableId(evntRecPtr.p->m_eventRec.TABLEID);
16906       evntRec->m_request.setTableVersion(evntRecPtr.p->m_eventRec.TABLEVERSION);
16907       Uint32 sz = NDB_ARRAY_SIZE(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK);
16908       evntRec->m_request.setAttrListBitmask(sz, evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK);
16909       evntRec->m_request.setEventId(evntRecPtr.p->m_eventRec.SUBID);
16910       evntRec->m_request.setEventKey(evntRecPtr.p->m_eventRec.SUBKEY);
16911 
16912       DBUG_PRINT("info",
16913 		 ("GET: event name: %s table name: %s table id: %u table version: %u",
16914 		  evntRecPtr.p->m_eventRec.NAME,
16915 		  evntRecPtr.p->m_eventRec.TABLE_NAME,
16916 		  evntRecPtr.p->m_eventRec.TABLEID,
16917 		  evntRecPtr.p->m_eventRec.TABLEVERSION));
16918 
16919       // find table id for event table
16920       DictObject* obj_ptr_p = get_object(evntRecPtr.p->m_eventRec.TABLE_NAME);
16921       if(!obj_ptr_p){
16922 	jam();
16923 	evntRecPtr.p->m_errorCode = 723;
16924 	evntRecPtr.p->m_errorLine = __LINE__;
16925 	evntRecPtr.p->m_errorNode = reference();
16926 
16927 	createEvent_sendReply(signal, evntRecPtr);
16928 	return;
16929       }
16930 
16931       TableRecordPtr tablePtr;
16932       c_tableRecordPool_.getPtr(tablePtr, obj_ptr_p->m_object_ptr_i);
16933       evntRec->m_request.setTableId(tablePtr.p->tableId);
16934       evntRec->m_request.setTableVersion(tablePtr.p->tableVersion);
16935 
16936       createEventComplete_RT_USER_GET(signal, evntRecPtr);
16937       return;
16938     }
16939     case CreateEvntReq::RT_USER_CREATE: {
16940 #ifdef EVENT_DEBUG
16941       printf("create type = %d\n", CreateEvntReq::RT_USER_CREATE);
16942 #endif
16943       jam();
16944       createEventComplete_RT_USER_CREATE(signal, evntRecPtr);
16945       return;
16946     }
16947       break;
16948     default:
16949       ndbrequire(false);
16950     }
16951   } else { // returnCode != 0
16952     UtilExecuteRef * const ref = (UtilExecuteRef *)signal->getDataPtr();
16953     OpCreateEventPtr evntRecPtr;
16954     evntRecPtr.i = ref->getSenderData();
16955     ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
16956     jam();
16957     evntRecPtr.p->m_errorNode = reference();
16958     evntRecPtr.p->m_errorLine = __LINE__;
16959 
16960     switch (ref->getErrorCode()) {
16961     case UtilExecuteRef::TCError:
16962       switch (ref->getTCErrorCode()) {
16963       case ZNOT_FOUND:
16964 	jam();
16965 	evntRecPtr.p->m_errorCode = 4710;
16966 	break;
16967       case ZALREADYEXIST:
16968 	jam();
16969 	evntRecPtr.p->m_errorCode = 746;
16970 	break;
16971       default:
16972 	jam();
16973 	evntRecPtr.p->m_errorCode = ref->getTCErrorCode();
16974 	break;
16975       }
16976       break;
16977     default:
16978       jam();
16979       evntRecPtr.p->m_errorCode = ref->getErrorCode();
16980       break;
16981     }
16982 
16983     createEvent_sendReply(signal, evntRecPtr);
16984   }
16985 }
16986 
16987 /***********************************************************************
16988  *
16989  * NdbEventOperation, reading systable, creating event in suma
16990  *
16991  */
16992 
16993 void
createEvent_RT_USER_GET(Signal * signal,OpCreateEventPtr evntRecPtr,SectionHandle & handle)16994 Dbdict::createEvent_RT_USER_GET(Signal* signal,
16995 				OpCreateEventPtr evntRecPtr,
16996 				SectionHandle& handle){
16997   jam();
16998   EVENT_TRACE;
16999 #ifdef EVENT_PH2_DEBUG
17000   ndbout_c("DBDICT(Coordinator) got GSN_CREATE_EVNT_REQ::RT_USER_GET evntRecPtr.i = (%d), ref = %u", evntRecPtr.i, evntRecPtr.p->m_request.getUserRef());
17001 #endif
17002 
17003   SegmentedSectionPtr ssPtr;
17004 
17005   handle.getSection(ssPtr, 0);
17006 
17007   SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
17008 #ifdef EVENT_DEBUG
17009   r0.printAll(ndbout);
17010 #endif
17011   if ((!r0.first()) ||
17012       (r0.getValueType() != SimpleProperties::StringValue) ||
17013       (r0.getValueLen() <= 0)) {
17014     jam();
17015     releaseSections(handle);
17016 
17017     evntRecPtr.p->m_errorCode = 1;
17018     evntRecPtr.p->m_errorLine = __LINE__;
17019     evntRecPtr.p->m_errorNode = reference();
17020 
17021     createEvent_sendReply(signal, evntRecPtr);
17022     return;
17023   }
17024 
17025   r0.getString(evntRecPtr.p->m_eventRec.NAME);
17026   int len = (int)strlen(evntRecPtr.p->m_eventRec.NAME);
17027   memset(evntRecPtr.p->m_eventRec.NAME+len, 0, MAX_TAB_NAME_SIZE-len);
17028 
17029   releaseSections(handle);
17030 
17031   Callback c = { safe_cast(&Dbdict::createEventUTIL_PREPARE), 0 };
17032 
17033   prepareTransactionEventSysTable(&c, signal, evntRecPtr.i,
17034 				  UtilPrepareReq::Read);
17035   /*
17036    * Will read systable and fill an OpCreateEventPtr
17037    * and return below
17038    */
17039 }
17040 
17041 void
createEventComplete_RT_USER_GET(Signal * signal,OpCreateEventPtr evntRecPtr)17042 Dbdict::createEventComplete_RT_USER_GET(Signal* signal,
17043 					OpCreateEventPtr evntRecPtr){
17044   jam();
17045 
17046   // Send to oneself and the other DICT's
17047   CreateEvntReq * req = (CreateEvntReq *)signal->getDataPtrSend();
17048 
17049   *req = evntRecPtr.p->m_request;
17050   req->senderRef = reference();
17051   req->senderData = evntRecPtr.i;
17052 
17053   req->addRequestFlag(CreateEvntReq::RT_DICT_AFTER_GET);
17054 
17055 #ifdef EVENT_PH2_DEBUG
17056   ndbout_c("DBDICT(Coordinator) sending GSN_CREATE_EVNT_REQ::RT_DICT_AFTER_GET to DBDICT participants evntRecPtr.i = (%d)", evntRecPtr.i);
17057 #endif
17058 
17059   NodeReceiverGroup rg(DBDICT, c_aliveNodes);
17060   RequestTracker & p = evntRecPtr.p->m_reqTracker;
17061   if (!p.init<CreateEvntRef>(c_counterMgr, rg, GSN_CREATE_EVNT_REF,
17062 			     evntRecPtr.i))
17063   {
17064     jam();
17065     evntRecPtr.p->m_errorCode = 701;
17066     createEvent_sendReply(signal, evntRecPtr);
17067     return;
17068   }
17069 
17070   sendSignal(rg, GSN_CREATE_EVNT_REQ, signal, CreateEvntReq::SignalLength, JBB);
17071   return;
17072 }
17073 
17074 void
createEvent_nodeFailCallback(Signal * signal,Uint32 eventRecPtrI,Uint32 returnCode)17075 Dbdict::createEvent_nodeFailCallback(Signal* signal, Uint32 eventRecPtrI,
17076 				     Uint32 returnCode){
17077   OpCreateEventPtr evntRecPtr;
17078   c_opCreateEvent.getPtr(evntRecPtr, eventRecPtrI);
17079   createEvent_sendReply(signal, evntRecPtr);
17080 }
17081 
execCREATE_EVNT_REF(Signal * signal)17082 void Dbdict::execCREATE_EVNT_REF(Signal* signal)
17083 {
17084   jamEntry();
17085   EVENT_TRACE;
17086   CreateEvntRef * const ref = (CreateEvntRef *)signal->getDataPtr();
17087   OpCreateEventPtr evntRecPtr;
17088 
17089   evntRecPtr.i = ref->getUserData();
17090   ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
17091 
17092 #ifdef EVENT_PH2_DEBUG
17093   ndbout_c("DBDICT(Coordinator) got GSN_CREATE_EVNT_REF evntRecPtr.i = (%d)", evntRecPtr.i);
17094 #endif
17095 
17096   LinearSectionPtr ptr[2];
17097 
17098   int noLSP = 0;
17099   LinearSectionPtr *ptr0 = NULL;
17100   if (ref->errorCode == CreateEvntRef::NF_FakeErrorREF)
17101   {
17102     jam();
17103     evntRecPtr.p->m_reqTracker.ignoreRef(c_counterMgr,
17104                                          refToNode(ref->senderRef));
17105 
17106     /**
17107      * If a CREATE_EVNT_REF finishes request,
17108      *   we need to make sure that table name is sent
17109      *   same as it is if a CREATE_EVNT_CONF finishes request
17110      */
17111     if (evntRecPtr.p->m_reqTracker.done())
17112     {
17113       jam();
17114       /**
17115        * Add "extra" check if tracker is done...
17116        *   (strictly not necessary...)
17117        *   but makes case more explicit
17118        */
17119       ptr[0].p = (Uint32 *)evntRecPtr.p->m_eventRec.TABLE_NAME;
17120       ptr[0].sz = Uint32((strlen(evntRecPtr.p->m_eventRec.TABLE_NAME)+4)/4);
17121       ptr[1].p = evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2;
17122       ptr[1].sz = NDB_ARRAY_SIZE(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2) - 1;
17123       ptr0 = ptr;
17124       noLSP = 2;
17125     }
17126   }
17127   else
17128   {
17129     jam();
17130     evntRecPtr.p->m_errorCode = ref->errorCode;
17131     evntRecPtr.p->m_reqTracker.reportRef(c_counterMgr,
17132                                          refToNode(ref->senderRef));
17133   }
17134 
17135   createEvent_sendReply(signal, evntRecPtr, ptr0, noLSP);
17136 
17137   return;
17138 }
17139 
execCREATE_EVNT_CONF(Signal * signal)17140 void Dbdict::execCREATE_EVNT_CONF(Signal* signal)
17141 {
17142   jamEntry();
17143   EVENT_TRACE;
17144   CreateEvntConf * const conf = (CreateEvntConf *)signal->getDataPtr();
17145   OpCreateEventPtr evntRecPtr;
17146 
17147   evntRecPtr.i = conf->getUserData();
17148 
17149   ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
17150 
17151 #ifdef EVENT_PH2_DEBUG
17152   ndbout_c("DBDICT(Coordinator) got GSN_CREATE_EVNT_CONF evntRecPtr.i = (%d)", evntRecPtr.i);
17153 #endif
17154 
17155   evntRecPtr.p->m_reqTracker.reportConf(c_counterMgr, refToNode(conf->senderRef));
17156 
17157   // we will only have a valid tablename if it the master DICT sending this
17158   // but that's ok
17159   LinearSectionPtr ptr[2];
17160   ptr[0].p = (Uint32 *)evntRecPtr.p->m_eventRec.TABLE_NAME;
17161   ptr[0].sz =
17162     Uint32(strlen(evntRecPtr.p->m_eventRec.TABLE_NAME)+4)/4; // to make sure we have a null
17163   ptr[1].p = evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2;
17164   ptr[1].sz = NDB_ARRAY_SIZE(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2) - 1;
17165 
17166   createEvent_sendReply(signal, evntRecPtr, ptr, 2);
17167 
17168   return;
17169 }
17170 
17171 /************************************************
17172  *
17173  * Participant stuff
17174  *
17175  */
17176 
17177 void
createEvent_RT_DICT_AFTER_GET(Signal * signal,OpCreateEventPtr evntRecPtr)17178 Dbdict::createEvent_RT_DICT_AFTER_GET(Signal* signal, OpCreateEventPtr evntRecPtr){
17179   DBUG_ENTER("Dbdict::createEvent_RT_DICT_AFTER_GET");
17180   jam();
17181   evntRecPtr.p->m_request.setUserRef(signal->senderBlockRef());
17182 
17183 #ifdef EVENT_PH2_DEBUG
17184   ndbout_c("DBDICT(Participant) got CREATE_EVNT_REQ::RT_DICT_AFTER_GET evntRecPtr.i = (%d)", evntRecPtr.i);
17185 #endif
17186 
17187   // the signal comes from the DICT block that got the first user request!
17188   // This code runs on all DICT nodes, including oneself
17189 
17190   // Seize a Create Event record, the Coordinator will now have two seized
17191   // but that's ok, it's like a recursion
17192 
17193   CRASH_INSERTION2(6009, getOwnNodeId() != c_masterNodeId);
17194 
17195   SubCreateReq * sumaReq = (SubCreateReq *)signal->getDataPtrSend();
17196 
17197   sumaReq->senderRef        = reference(); // reference to DICT
17198   sumaReq->senderData       = evntRecPtr.i;
17199   sumaReq->subscriptionId   = evntRecPtr.p->m_request.getEventId();
17200   sumaReq->subscriptionKey  = evntRecPtr.p->m_request.getEventKey();
17201   sumaReq->subscriptionType = SubCreateReq::TableEvent;
17202   if (evntRecPtr.p->m_request.getReportAll())
17203     sumaReq->subscriptionType|= SubCreateReq::ReportAll;
17204   if (evntRecPtr.p->m_request.getReportSubscribe())
17205     sumaReq->subscriptionType|= SubCreateReq::ReportSubscribe;
17206   if (! evntRecPtr.p->m_request.getReportDDL())
17207   {
17208     sumaReq->subscriptionType |= SubCreateReq::NoReportDDL;
17209   }
17210   sumaReq->tableId          = evntRecPtr.p->m_request.getTableId();
17211   sumaReq->schemaTransId    = 0;
17212 
17213 #ifdef EVENT_PH2_DEBUG
17214   ndbout_c("sending GSN_SUB_CREATE_REQ");
17215 #endif
17216 
17217   sendSignal(SUMA_REF, GSN_SUB_CREATE_REQ, signal,
17218 	     SubCreateReq::SignalLength, JBB);
17219   DBUG_VOID_RETURN;
17220 }
17221 
execSUB_CREATE_REF(Signal * signal)17222 void Dbdict::execSUB_CREATE_REF(Signal* signal)
17223 {
17224   jamEntry();
17225   DBUG_ENTER("Dbdict::execSUB_CREATE_REF");
17226 
17227   SubCreateRef * const ref = (SubCreateRef *)signal->getDataPtr();
17228   OpCreateEventPtr evntRecPtr;
17229 
17230   evntRecPtr.i = ref->senderData;
17231   ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
17232 
17233   if (ref->errorCode == SubCreateRef::NotStarted)
17234   {
17235     jam();
17236     // ignore (was previously NF_FakeErrorREF)
17237     // NOTE: different handling then rest of execSUB_XXX_REF
17238     // note to mess with GSN_CREATE_EVNT
17239   }
17240   else if (ref->errorCode)
17241   {
17242     jam();
17243     evntRecPtr.p->m_errorCode = ref->errorCode;
17244     evntRecPtr.p->m_errorLine = __LINE__;
17245     evntRecPtr.p->m_errorNode = reference();
17246   }
17247   else
17248   {
17249     jam();
17250     evntRecPtr.p->m_errorCode = 1;
17251     evntRecPtr.p->m_errorLine = __LINE__;
17252     evntRecPtr.p->m_errorNode = reference();
17253   }
17254 
17255   createEvent_sendReply(signal, evntRecPtr);
17256   DBUG_VOID_RETURN;
17257 }
17258 
execSUB_CREATE_CONF(Signal * signal)17259 void Dbdict::execSUB_CREATE_CONF(Signal* signal)
17260 {
17261   jamEntry();
17262   DBUG_ENTER("Dbdict::execSUB_CREATE_CONF");
17263   EVENT_TRACE;
17264 
17265   SubCreateConf * const sumaConf = (SubCreateConf *)signal->getDataPtr();
17266   OpCreateEventPtr evntRecPtr;
17267   evntRecPtr.i = sumaConf->senderData;
17268   ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
17269 
17270   createEvent_sendReply(signal, evntRecPtr);
17271 
17272   DBUG_VOID_RETURN;
17273 }
17274 
17275 /****************************************************
17276  *
17277  * common create reply method
17278  *
17279  *******************************************************/
17280 
createEvent_sendReply(Signal * signal,OpCreateEventPtr evntRecPtr,LinearSectionPtr * ptr,int noLSP)17281 void Dbdict::createEvent_sendReply(Signal* signal,
17282 				   OpCreateEventPtr evntRecPtr,
17283 				   LinearSectionPtr *ptr, int noLSP)
17284 {
17285   jam();
17286   EVENT_TRACE;
17287 
17288   // check if we're ready to sent reply
17289   // if we are the master dict we might be waiting for conf/ref
17290 
17291   if (!evntRecPtr.p->m_reqTracker.done()) {
17292     jam();
17293     return; // there's more to come
17294   }
17295 
17296   if (evntRecPtr.p->m_reqTracker.hasRef()) {
17297     ptr = NULL; // we don't want to return anything if there's an error
17298     if (!evntRecPtr.p->hasError()) {
17299       evntRecPtr.p->m_errorCode = 1;
17300       evntRecPtr.p->m_errorLine = __LINE__;
17301       evntRecPtr.p->m_errorNode = reference();
17302       jam();
17303     }
17304     else
17305     {
17306       jam();
17307     }
17308   }
17309 
17310   // reference to API if master DICT
17311   // else reference to master DICT
17312   Uint32 senderRef = evntRecPtr.p->m_request.getUserRef();
17313   Uint32 signalLength;
17314   Uint32 gsn;
17315 
17316   if (evntRecPtr.p->hasError()) {
17317     jam();
17318     EVENT_TRACE;
17319     CreateEvntRef * ret = (CreateEvntRef *)signal->getDataPtrSend();
17320 
17321     ret->setEventId(evntRecPtr.p->m_request.getEventId());
17322     ret->setEventKey(evntRecPtr.p->m_request.getEventKey());
17323     ret->setUserData(evntRecPtr.p->m_request.getUserData());
17324     ret->senderRef = reference();
17325     ret->setTableId(evntRecPtr.p->m_request.getTableId());
17326     ret->setTableVersion(evntRecPtr.p->m_request.getTableVersion());
17327     ret->setEventType(evntRecPtr.p->m_request.getEventType());
17328     ret->setRequestType(evntRecPtr.p->m_request.getRequestType());
17329 
17330     ret->setErrorCode(evntRecPtr.p->m_errorCode);
17331     ret->setErrorLine(evntRecPtr.p->m_errorLine);
17332     ret->setErrorNode(evntRecPtr.p->m_errorNode);
17333 
17334     signalLength = CreateEvntRef::SignalLength;
17335 #ifdef EVENT_PH2_DEBUG
17336     ndbout_c("DBDICT sending GSN_CREATE_EVNT_REF to evntRecPtr.i = (%d) node = %u ref = %u", evntRecPtr.i, refToNode(senderRef), senderRef);
17337     ndbout_c("errorCode = %u", evntRecPtr.p->m_errorCode);
17338     ndbout_c("errorLine = %u", evntRecPtr.p->m_errorLine);
17339 #endif
17340     gsn = GSN_CREATE_EVNT_REF;
17341 
17342   } else {
17343     jam();
17344     EVENT_TRACE;
17345     CreateEvntConf * evntConf = (CreateEvntConf *)signal->getDataPtrSend();
17346 
17347     evntConf->setEventId(evntRecPtr.p->m_request.getEventId());
17348     evntConf->setEventKey(evntRecPtr.p->m_request.getEventKey());
17349     evntConf->setUserData(evntRecPtr.p->m_request.getUserData());
17350     evntConf->senderRef = reference();
17351     evntConf->setTableId(evntRecPtr.p->m_request.getTableId());
17352     evntConf->setTableVersion(evntRecPtr.p->m_request.getTableVersion());
17353     evntConf->setAttrListBitmask(evntRecPtr.p->m_request.getAttrListBitmask());
17354     evntConf->setEventType(evntRecPtr.p->m_request.getEventType());
17355     evntConf->setRequestType(evntRecPtr.p->m_request.getRequestType());
17356 
17357     signalLength = CreateEvntConf::SignalLength;
17358 #ifdef EVENT_PH2_DEBUG
17359     ndbout_c("DBDICT sending GSN_CREATE_EVNT_CONF to evntRecPtr.i = (%d) node = %u ref = %u", evntRecPtr.i, refToNode(senderRef), senderRef);
17360 #endif
17361     gsn = GSN_CREATE_EVNT_CONF;
17362   }
17363 
17364   if (ptr) {
17365     jam();
17366     sendSignal(senderRef, gsn, signal, signalLength, JBB, ptr, noLSP);
17367   } else {
17368     jam();
17369     sendSignal(senderRef, gsn, signal, signalLength, JBB);
17370   }
17371 
17372   c_opCreateEvent.release(evntRecPtr);
17373 }
17374 
17375 /*************************************************************/
17376 
17377 /********************************************************************
17378  *
17379  * Start event
17380  *
17381  *******************************************************************/
17382 
execSUB_START_REQ(Signal * signal)17383 void Dbdict::execSUB_START_REQ(Signal* signal)
17384 {
17385   jamEntry();
17386 
17387   Uint32 origSenderRef = signal->senderBlockRef();
17388 
17389   if (refToBlock(origSenderRef) != DBDICT &&
17390       getOwnNodeId() != c_masterNodeId)
17391   {
17392     /*
17393      * Coordinator but not master
17394      */
17395     SubStartRef * ref = (SubStartRef *)signal->getDataPtrSend();
17396     ref->senderRef = reference();
17397     ref->errorCode = SubStartRef::NotMaster;
17398     ref->m_masterNodeId = c_masterNodeId;
17399     sendSignal(origSenderRef, GSN_SUB_START_REF, signal,
17400 	       SubStartRef::SignalLength2, JBB);
17401     return;
17402   }
17403   OpSubEventPtr subbPtr;
17404   Uint32 errCode = 0;
17405 
17406   if (!c_opSubEvent.seize(subbPtr)) {
17407     errCode = SubStartRef::Busy;
17408 busy:
17409     jam();
17410     SubStartRef * ref = (SubStartRef *)signal->getDataPtrSend();
17411 
17412     { // fix
17413       Uint32 subcriberRef = ((SubStartReq*)signal->getDataPtr())->subscriberRef;
17414       ref->subscriberRef = subcriberRef;
17415     }
17416     jam();
17417     //      ret->setErrorCode(SubStartRef::SeizeError);
17418     //      ret->setErrorLine(__LINE__);
17419     //      ret->setErrorNode(reference());
17420     ref->senderRef = reference();
17421     ref->errorCode = errCode;
17422     ref->m_masterNodeId = c_masterNodeId;
17423 
17424     sendSignal(origSenderRef, GSN_SUB_START_REF, signal,
17425 	       SubStartRef::SL_MasterNode, JBB);
17426     return;
17427   }
17428 
17429   {
17430     const SubStartReq* req = (SubStartReq*) signal->getDataPtr();
17431     subbPtr.p->m_senderRef = req->senderRef;
17432     subbPtr.p->m_senderData = req->senderData;
17433     subbPtr.p->m_errorCode = 0;
17434     subbPtr.p->m_gsn = GSN_SUB_START_REQ;
17435     subbPtr.p->m_subscriptionId = req->subscriptionId;
17436     subbPtr.p->m_subscriptionKey = req->subscriptionKey;
17437     subbPtr.p->m_subscriberRef = req->subscriberRef;
17438     subbPtr.p->m_subscriberData = req->subscriberData;
17439     bzero(subbPtr.p->m_buckets_per_ng, sizeof(subbPtr.p->m_buckets_per_ng));
17440   }
17441 
17442   if (refToBlock(origSenderRef) != DBDICT) {
17443     /*
17444      * Coordinator
17445      */
17446     jam();
17447 
17448     if (c_masterNodeId != getOwnNodeId())
17449     {
17450       jam();
17451       c_opSubEvent.release(subbPtr);
17452       errCode = SubStartRef::NotMaster;
17453       goto busy;
17454     }
17455 
17456     if (!c_sub_startstop_lock.isclear())
17457     {
17458       jam();
17459       c_opSubEvent.release(subbPtr);
17460       errCode = SubStartRef::BusyWithNR;
17461       goto busy;
17462     }
17463 
17464     subbPtr.p->m_senderRef = origSenderRef; // not sure if API sets correctly
17465     NodeReceiverGroup rg(DBDICT, c_aliveNodes);
17466 
17467     RequestTracker & p = subbPtr.p->m_reqTracker;
17468     if (!p.init<SubStartRef>(c_counterMgr, rg, GSN_SUB_START_REF, subbPtr.i))
17469     {
17470       c_opSubEvent.release(subbPtr);
17471       errCode = SubStartRef::Busy;
17472       goto busy;
17473     }
17474 
17475     SubStartReq* req = (SubStartReq*) signal->getDataPtrSend();
17476 
17477     req->senderRef  = reference();
17478     req->senderData = subbPtr.i;
17479 
17480 #ifdef EVENT_PH3_DEBUG
17481     ndbout_c("DBDICT(Coordinator) sending GSN_SUB_START_REQ to DBDICT participants subbPtr.i = (%d)", subbPtr.i);
17482 #endif
17483 
17484     if (ERROR_INSERTED(6011))
17485     {
17486       ndbout_c("sending delayed to self...");
17487       if (ERROR_INSERTED(6011))
17488       {
17489         rg.m_nodes.clear(getOwnNodeId());
17490       }
17491       sendSignal(rg, GSN_SUB_START_REQ, signal,
17492                  SubStartReq::SignalLength, JBB);
17493       sendSignalWithDelay(reference(),
17494                           GSN_SUB_START_REQ,
17495                           signal, 5000, SubStartReq::SignalLength);
17496     }
17497     else
17498     {
17499       c_outstanding_sub_startstop++;
17500       sendSignal(rg, GSN_SUB_START_REQ, signal,
17501                  SubStartReq::SignalLength, JBB);
17502     }
17503     return;
17504   }
17505   /*
17506    * Participant
17507    */
17508   ndbrequire(refToBlock(origSenderRef) == DBDICT);
17509 
17510   CRASH_INSERTION(6007);
17511 
17512   {
17513     SubStartReq* req = (SubStartReq*) signal->getDataPtrSend();
17514 
17515     req->senderRef = reference();
17516     req->senderData = subbPtr.i;
17517 
17518 #ifdef EVENT_PH3_DEBUG
17519     ndbout_c("DBDICT(Participant) sending GSN_SUB_START_REQ to SUMA subbPtr.i = (%d)", subbPtr.i);
17520 #endif
17521     sendSignal(SUMA_REF, GSN_SUB_START_REQ, signal, SubStartReq::SignalLength, JBB);
17522   }
17523 }
17524 
17525 bool
upgrade_suma_NotStarted(Uint32 err,Uint32 ref) const17526 Dbdict::upgrade_suma_NotStarted(Uint32 err, Uint32 ref) const
17527 {
17528   /**
17529    * Check that receiver can handle 1428,
17530    *   else return true if error code should be replaced by NF_FakeErrorREF
17531    */
17532   if (err == 1428)
17533   {
17534     jam();
17535     if (!ndb_suma_not_started_ref(getNodeInfo(refToNode(ref)).m_version))
17536       return true;
17537   }
17538   return false;
17539 }
17540 
execSUB_START_REF(Signal * signal)17541 void Dbdict::execSUB_START_REF(Signal* signal)
17542 {
17543   jamEntry();
17544 
17545   const SubStartRef* ref = (SubStartRef*) signal->getDataPtr();
17546   Uint32 senderRef  = ref->senderRef;
17547   Uint32 err = ref->errorCode;
17548 
17549   OpSubEventPtr subbPtr;
17550   c_opSubEvent.getPtr(subbPtr, ref->senderData);
17551 
17552   if (refToBlock(senderRef) == SUMA)
17553   {
17554     /*
17555      * Participant
17556      */
17557     jam();
17558 
17559 #ifdef EVENT_PH3_DEBUG
17560     ndbout_c("DBDICT(Participant) got GSN_SUB_START_REF = (%d)", subbPtr.i);
17561 #endif
17562 
17563     if (upgrade_suma_NotStarted(err, subbPtr.p->m_senderRef))
17564     {
17565       jam();
17566       err = SubStartRef::NF_FakeErrorREF;
17567     }
17568 
17569     SubStartRef* ref = (SubStartRef*) signal->getDataPtrSend();
17570     ref->senderRef = reference();
17571     ref->senderData = subbPtr.p->m_senderData;
17572     ref->errorCode = err;
17573     sendSignal(subbPtr.p->m_senderRef, GSN_SUB_START_REF,
17574 	       signal, SubStartRef::SignalLength2, JBB);
17575     c_opSubEvent.release(subbPtr);
17576     return;
17577   }
17578   /*
17579    * Coordinator
17580    */
17581   ndbrequire(refToBlock(senderRef) == DBDICT);
17582 #ifdef EVENT_PH3_DEBUG
17583   ndbout_c("DBDICT(Coordinator) got GSN_SUB_START_REF = (%d)", subbPtr.i);
17584 #endif
17585   if (err == SubStartRef::NotStarted)
17586   {
17587     jam();
17588     subbPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(senderRef));
17589   }
17590   else
17591   {
17592     if (err == SubStartRef::NF_FakeErrorREF)
17593     {
17594       jam();
17595       err = SubStartRef::NodeDied;
17596     }
17597 
17598     if (subbPtr.p->m_errorCode == 0)
17599     {
17600       subbPtr.p->m_errorCode= err ? err : 1;
17601     }
17602     subbPtr.p->m_reqTracker.reportRef(c_counterMgr, refToNode(senderRef));
17603   }
17604   completeSubStartReq(signal,subbPtr.i,0);
17605 }
17606 
execSUB_START_CONF(Signal * signal)17607 void Dbdict::execSUB_START_CONF(Signal* signal)
17608 {
17609   jamEntry();
17610 
17611   const SubStartConf* conf = (SubStartConf*) signal->getDataPtr();
17612   Uint32 senderRef  = conf->senderRef;
17613   Uint32 buckets = conf->bucketCount;
17614   Uint32 nodegroup = conf->nodegroup;
17615 
17616   OpSubEventPtr subbPtr;
17617   c_opSubEvent.getPtr(subbPtr, conf->senderData);
17618 
17619   if (refToBlock(senderRef) == SUMA) {
17620     /*
17621      * Participant
17622      */
17623     jam();
17624     SubStartConf* conf = (SubStartConf*) signal->getDataPtrSend();
17625 
17626 #ifdef EVENT_PH3_DEBUG
17627   ndbout_c("DBDICT(Participant) got GSN_SUB_START_CONF = (%d)", subbPtr.i);
17628 #endif
17629 
17630     conf->senderRef = reference();
17631     conf->senderData = subbPtr.p->m_senderData;
17632     conf->bucketCount = buckets;
17633     conf->nodegroup = nodegroup;
17634 
17635     sendSignal(subbPtr.p->m_senderRef, GSN_SUB_START_CONF,
17636 	       signal, SubStartConf::SignalLength, JBB);
17637     c_opSubEvent.release(subbPtr);
17638     return;
17639   }
17640   /*
17641    * Coordinator
17642    */
17643   ndbrequire(refToBlock(senderRef) == DBDICT);
17644 #ifdef EVENT_PH3_DEBUG
17645   ndbout_c("DBDICT(Coordinator) got GSN_SUB_START_CONF = (%d)", subbPtr.i);
17646 #endif
17647 #define ARRAY_SIZE(x) (sizeof(x)/(sizeof(x[0])))
17648 
17649   if (buckets)
17650   {
17651     jam();
17652     ndbrequire(nodegroup < ARRAY_SIZE(subbPtr.p->m_buckets_per_ng));
17653     ndbrequire(subbPtr.p->m_buckets_per_ng[nodegroup] == 0 ||
17654                subbPtr.p->m_buckets_per_ng[nodegroup] == buckets);
17655     subbPtr.p->m_buckets_per_ng[nodegroup] = buckets;
17656   }
17657   subbPtr.p->m_sub_start_conf = *conf;
17658   subbPtr.p->m_reqTracker.reportConf(c_counterMgr, refToNode(senderRef));
17659   completeSubStartReq(signal,subbPtr.i,0);
17660 }
17661 
17662 /*
17663  * Coordinator
17664  */
completeSubStartReq(Signal * signal,Uint32 ptrI,Uint32 returnCode)17665 void Dbdict::completeSubStartReq(Signal* signal,
17666 				 Uint32 ptrI,
17667 				 Uint32 returnCode){
17668   jam();
17669 
17670   OpSubEventPtr subbPtr;
17671   c_opSubEvent.getPtr(subbPtr, ptrI);
17672 
17673   if (!subbPtr.p->m_reqTracker.done()){
17674     jam();
17675     return;
17676   }
17677 
17678   if (subbPtr.p->m_reqTracker.hasRef())
17679   {
17680     jam();
17681 #ifdef EVENT_DEBUG
17682     ndbout_c("SUB_START_REF");
17683 #endif
17684 
17685     if (subbPtr.p->m_reqTracker.hasConf())
17686     {
17687       jam();
17688       NodeReceiverGroup rg(DBDICT, subbPtr.p->m_reqTracker.m_confs);
17689       RequestTracker & p = subbPtr.p->m_reqTracker;
17690       ndbrequire(p.init<SubStopRef>(c_counterMgr, rg, GSN_SUB_STOP_REF,
17691                                     subbPtr.i));
17692 
17693       SubStopReq* req = (SubStopReq*) signal->getDataPtrSend();
17694 
17695       req->senderRef  = reference();
17696       req->senderData = subbPtr.i;
17697       req->subscriptionId = subbPtr.p->m_subscriptionId;
17698       req->subscriptionKey = subbPtr.p->m_subscriptionKey;
17699       req->subscriberRef = subbPtr.p->m_subscriberRef;
17700       req->subscriberData = subbPtr.p->m_subscriberData;
17701       req->requestInfo = SubStopReq::RI_ABORT_START;
17702       sendSignal(rg, GSN_SUB_STOP_REQ, signal, SubStopReq::SignalLength, JBB);
17703       return;
17704     }
17705     else
17706     {
17707       jam();
17708       completeSubStopReq(signal, subbPtr.i, 0);
17709       return;
17710     }
17711   }
17712 #ifdef EVENT_DEBUG
17713   ndbout_c("SUB_START_CONF");
17714 #endif
17715 
17716   ndbrequire(c_outstanding_sub_startstop);
17717   c_outstanding_sub_startstop--;
17718   SubStartConf* conf = (SubStartConf*)signal->getDataPtrSend();
17719   * conf = subbPtr.p->m_sub_start_conf;
17720 
17721   Uint32 cnt = 0;
17722   for (Uint32 i = 0; i<ARRAY_SIZE(subbPtr.p->m_buckets_per_ng); i++)
17723     cnt += subbPtr.p->m_buckets_per_ng[i];
17724   conf->bucketCount = cnt;
17725 
17726   sendSignal(subbPtr.p->m_senderRef, GSN_SUB_START_CONF,
17727 	     signal, SubStartConf::SignalLength, JBB);
17728   c_opSubEvent.release(subbPtr);
17729 }
17730 
17731 /********************************************************************
17732  *
17733  * Stop event
17734  *
17735  *******************************************************************/
17736 
execSUB_STOP_REQ(Signal * signal)17737 void Dbdict::execSUB_STOP_REQ(Signal* signal)
17738 {
17739   jamEntry();
17740 
17741   Uint32 origSenderRef = signal->senderBlockRef();
17742 
17743   OpSubEventPtr subbPtr;
17744   Uint32 errCode = 0;
17745   if (!c_opSubEvent.seize(subbPtr)) {
17746     errCode = SubStopRef::Busy;
17747 busy:
17748     SubStopRef * ref = (SubStopRef *)signal->getDataPtrSend();
17749     jam();
17750     //      ret->setErrorCode(SubStartRef::SeizeError);
17751     //      ret->setErrorLine(__LINE__);
17752     //      ret->setErrorNode(reference());
17753     ref->senderRef = reference();
17754     ref->errorCode = errCode;
17755     ref->m_masterNodeId = c_masterNodeId;
17756 
17757     sendSignal(origSenderRef, GSN_SUB_STOP_REF, signal,
17758 	       SubStopRef::SL_MasterNode, JBB);
17759     return;
17760   }
17761 
17762   {
17763     SubStopReq* req = (SubStopReq*) signal->getDataPtr();
17764     subbPtr.p->m_senderRef = req->senderRef;
17765     subbPtr.p->m_senderData = req->senderData;
17766     subbPtr.p->m_errorCode = 0;
17767     subbPtr.p->m_gsn = GSN_SUB_STOP_REQ;
17768     subbPtr.p->m_subscriptionId = req->subscriptionId;
17769     subbPtr.p->m_subscriptionKey = req->subscriptionKey;
17770     subbPtr.p->m_subscriberRef = req->subscriberRef;
17771     subbPtr.p->m_subscriberData = req->subscriberData;
17772     bzero(&subbPtr.p->m_sub_stop_conf, sizeof(subbPtr.p->m_sub_stop_conf));
17773 
17774     if (signal->getLength() < SubStopReq::SignalLength)
17775     {
17776       jam();
17777       req->requestInfo = 0;
17778     }
17779   }
17780 
17781   if (refToBlock(origSenderRef) != DBDICT) {
17782     /*
17783      * Coordinator
17784      */
17785     jam();
17786 
17787     if (c_masterNodeId != getOwnNodeId())
17788     {
17789       jam();
17790       c_opSubEvent.release(subbPtr);
17791       errCode = SubStopRef::NotMaster;
17792       goto busy;
17793     }
17794 
17795     if (!c_sub_startstop_lock.isclear())
17796     {
17797       jam();
17798       c_opSubEvent.release(subbPtr);
17799       errCode = SubStopRef::BusyWithNR;
17800       goto busy;
17801     }
17802 
17803 #ifdef EVENT_DEBUG
17804     ndbout_c("SUB_STOP_REQ 1");
17805 #endif
17806     subbPtr.p->m_senderRef = origSenderRef; // not sure if API sets correctly
17807     NodeReceiverGroup rg(DBDICT, c_aliveNodes);
17808     RequestTracker & p = subbPtr.p->m_reqTracker;
17809     if (!p.init<SubStopRef>(c_counterMgr, rg, GSN_SUB_STOP_REF, subbPtr.i))
17810     {
17811       jam();
17812       c_opSubEvent.release(subbPtr);
17813       errCode = SubStopRef::Busy;
17814       goto busy;
17815     }
17816 
17817     SubStopReq* req = (SubStopReq*) signal->getDataPtrSend();
17818 
17819     req->senderRef  = reference();
17820     req->senderData = subbPtr.i;
17821 
17822     c_outstanding_sub_startstop++;
17823     sendSignal(rg, GSN_SUB_STOP_REQ, signal, SubStopReq::SignalLength, JBB);
17824     return;
17825   }
17826   /*
17827    * Participant
17828    */
17829 #ifdef EVENT_DEBUG
17830   ndbout_c("SUB_STOP_REQ 2");
17831 #endif
17832   ndbrequire(refToBlock(origSenderRef) == DBDICT);
17833 
17834   CRASH_INSERTION(6008);
17835 
17836   {
17837     SubStopReq* req = (SubStopReq*) signal->getDataPtrSend();
17838 
17839     req->senderRef = reference();
17840     req->senderData = subbPtr.i;
17841 
17842     sendSignal(SUMA_REF, GSN_SUB_STOP_REQ, signal, SubStopReq::SignalLength, JBB);
17843   }
17844 }
17845 
execSUB_STOP_REF(Signal * signal)17846 void Dbdict::execSUB_STOP_REF(Signal* signal)
17847 {
17848   jamEntry();
17849   const SubStopRef* ref = (SubStopRef*) signal->getDataPtr();
17850   Uint32 senderRef  = ref->senderRef;
17851   Uint32 err = ref->errorCode;
17852 
17853   OpSubEventPtr subbPtr;
17854   c_opSubEvent.getPtr(subbPtr, ref->senderData);
17855 
17856   if (refToBlock(senderRef) == SUMA)
17857   {
17858     /*
17859      * Participant
17860      */
17861     jam();
17862 
17863     if (upgrade_suma_NotStarted(err, subbPtr.p->m_senderRef))
17864     {
17865       jam();
17866       err = SubStopRef::NF_FakeErrorREF;
17867     }
17868 
17869     SubStopRef* ref = (SubStopRef*) signal->getDataPtrSend();
17870     ref->senderRef = reference();
17871     ref->senderData = subbPtr.p->m_senderData;
17872     ref->errorCode = err;
17873     sendSignal(subbPtr.p->m_senderRef, GSN_SUB_STOP_REF,
17874 	       signal, SubStopRef::SignalLength, JBB);
17875     c_opSubEvent.release(subbPtr);
17876     return;
17877   }
17878   /*
17879    * Coordinator
17880    */
17881   ndbrequire(refToBlock(senderRef) == DBDICT);
17882   if (err == SubStopRef::NF_FakeErrorREF || err == SubStopRef::NotStarted)
17883   {
17884     jam();
17885     subbPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(senderRef));
17886   }
17887   else
17888   {
17889     jam();
17890     if (subbPtr.p->m_errorCode == 0)
17891     {
17892       subbPtr.p->m_errorCode= err ? err : 1;
17893     }
17894     subbPtr.p->m_reqTracker.reportRef(c_counterMgr, refToNode(senderRef));
17895   }
17896   completeSubStopReq(signal,subbPtr.i,0);
17897 }
17898 
execSUB_STOP_CONF(Signal * signal)17899 void Dbdict::execSUB_STOP_CONF(Signal* signal)
17900 {
17901   jamEntry();
17902 
17903   const SubStopConf* conf = (SubStopConf*) signal->getDataPtr();
17904   Uint32 senderRef  = conf->senderRef;
17905 
17906   OpSubEventPtr subbPtr;
17907   c_opSubEvent.getPtr(subbPtr, conf->senderData);
17908 
17909   if (refToBlock(senderRef) == SUMA) {
17910     /*
17911      * Participant
17912      */
17913     jam();
17914     SubStopConf* conf = (SubStopConf*) signal->getDataPtrSend();
17915 
17916     conf->senderRef = reference();
17917     conf->senderData = subbPtr.p->m_senderData;
17918 
17919     sendSignal(subbPtr.p->m_senderRef, GSN_SUB_STOP_CONF,
17920 	       signal, SubStopConf::SignalLength, JBB);
17921     c_opSubEvent.release(subbPtr);
17922     return;
17923   }
17924   /*
17925    * Coordinator
17926    */
17927   ndbrequire(refToBlock(senderRef) == DBDICT);
17928   Uint64 old_gci, new_gci = 0;
17929   {
17930     Uint32 old_gci_hi = subbPtr.p->m_sub_stop_conf.gci_hi;
17931     Uint32 old_gci_lo = subbPtr.p->m_sub_stop_conf.gci_lo;
17932     old_gci = old_gci_lo | (Uint64(old_gci_hi) << 32);
17933     if (signal->getLength() >= SubStopConf::SignalLengthWithGci)
17934     {
17935       Uint32 new_gci_hi = conf->gci_hi;
17936       Uint32 new_gci_lo = conf->gci_lo;
17937       new_gci = new_gci_lo | (Uint64(new_gci_hi) << 32);
17938     }
17939   }
17940   subbPtr.p->m_sub_stop_conf = *conf;
17941   if (old_gci > new_gci)
17942   {
17943     subbPtr.p->m_sub_stop_conf.gci_hi= Uint32(old_gci>>32);
17944     subbPtr.p->m_sub_stop_conf.gci_lo= Uint32(old_gci);
17945   }
17946   subbPtr.p->m_reqTracker.reportConf(c_counterMgr, refToNode(senderRef));
17947   completeSubStopReq(signal,subbPtr.i,0);
17948 }
17949 
17950 /*
17951  * Coordinator
17952  */
completeSubStopReq(Signal * signal,Uint32 ptrI,Uint32 returnCode)17953 void Dbdict::completeSubStopReq(Signal* signal,
17954 				Uint32 ptrI,
17955 				Uint32 returnCode){
17956   OpSubEventPtr subbPtr;
17957   c_opSubEvent.getPtr(subbPtr, ptrI);
17958 
17959   if (!subbPtr.p->m_reqTracker.done()){
17960     jam();
17961     return;
17962   }
17963 
17964   ndbrequire(c_outstanding_sub_startstop);
17965   c_outstanding_sub_startstop--;
17966 
17967   if (subbPtr.p->m_gsn == GSN_SUB_START_REQ)
17968   {
17969     jam();
17970     SubStartRef* ref = (SubStartRef*)signal->getDataPtrSend();
17971     ref->senderRef  = reference();
17972     ref->senderData = subbPtr.p->m_senderData;
17973     ref->errorCode  = subbPtr.p->m_errorCode;
17974 
17975     sendSignal(subbPtr.p->m_senderRef, GSN_SUB_START_REF,
17976 	       signal, SubStartRef::SignalLength, JBB);
17977     c_opSubEvent.release(subbPtr);
17978     return;
17979   }
17980 
17981   if (subbPtr.p->m_reqTracker.hasRef()) {
17982     jam();
17983 #ifdef EVENT_DEBUG
17984     ndbout_c("SUB_STOP_REF");
17985 #endif
17986     SubStopRef* ref = (SubStopRef*)signal->getDataPtrSend();
17987 
17988     ref->senderRef  = reference();
17989     ref->senderData = subbPtr.p->m_senderData;
17990     ref->errorCode  = subbPtr.p->m_errorCode;
17991 
17992     sendSignal(subbPtr.p->m_senderRef, GSN_SUB_STOP_REF,
17993 	       signal, SubStopRef::SignalLength, JBB);
17994     if (subbPtr.p->m_reqTracker.hasConf()) {
17995       //  stopStartedNodes(signal);
17996     }
17997     c_opSubEvent.release(subbPtr);
17998     return;
17999   }
18000 #ifdef EVENT_DEBUG
18001   ndbout_c("SUB_STOP_CONF");
18002 #endif
18003   SubStopConf* conf = (SubStopConf*)signal->getDataPtrSend();
18004   * conf = subbPtr.p->m_sub_stop_conf;
18005   sendSignal(subbPtr.p->m_senderRef, GSN_SUB_STOP_CONF,
18006 	     signal, SubStopConf::SignalLength, JBB);
18007   c_opSubEvent.release(subbPtr);
18008 }
18009 
18010 /***************************************************************
18011  * MODULE: Drop event.
18012  *
18013  * Drop event.
18014  *
18015  * TODO
18016  */
18017 
18018 void
execDROP_EVNT_REQ(Signal * signal)18019 Dbdict::execDROP_EVNT_REQ(Signal* signal)
18020 {
18021   jamEntry();
18022   DBUG_ENTER("Dbdict::execDROP_EVNT_REQ");
18023 
18024   DropEvntReq *req = (DropEvntReq*)signal->getDataPtr();
18025   const Uint32 senderRef = signal->senderBlockRef();
18026   OpDropEventPtr evntRecPtr;
18027   SectionHandle handle(this, signal);
18028 
18029   if (refToBlock(senderRef) != DBDICT &&
18030       getOwnNodeId() != c_masterNodeId)
18031   {
18032     jam();
18033     releaseSections(handle);
18034 
18035     DropEvntRef * ref = (DropEvntRef *)signal->getDataPtrSend();
18036     ref->setUserRef(reference());
18037     ref->setErrorCode(DropEvntRef::NotMaster);
18038     ref->setErrorLine(__LINE__);
18039     ref->setErrorNode(reference());
18040     ref->setMasterNode(c_masterNodeId);
18041     sendSignal(senderRef, GSN_DROP_EVNT_REF, signal,
18042 	       DropEvntRef::SignalLength2, JBB);
18043     DBUG_VOID_RETURN;
18044   }
18045 
18046   // Seize a Create Event record
18047   if (!c_opDropEvent.seize(evntRecPtr)) {
18048     // Failed to allocate event record
18049     jam();
18050     releaseSections(handle);
18051 
18052     DropEvntRef * ret = (DropEvntRef *)signal->getDataPtrSend();
18053     ret->setErrorCode(747);
18054     ret->setErrorLine(__LINE__);
18055     ret->setErrorNode(reference());
18056     sendSignal(senderRef, GSN_DROP_EVNT_REF, signal,
18057 	       DropEvntRef::SignalLength, JBB);
18058     DBUG_VOID_RETURN;
18059   }
18060 
18061 #ifdef EVENT_DEBUG
18062   ndbout_c("DBDICT::execDROP_EVNT_REQ evntRecId = (%d)", evntRecPtr.i);
18063 #endif
18064 
18065   OpDropEvent* evntRec = evntRecPtr.p;
18066   evntRec->init(req);
18067 
18068   SegmentedSectionPtr ssPtr;
18069 
18070   handle.getSection(ssPtr, 0);
18071 
18072   SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
18073 #ifdef EVENT_DEBUG
18074   r0.printAll(ndbout);
18075 #endif
18076   // event name
18077   if ((!r0.first()) ||
18078       (r0.getValueType() != SimpleProperties::StringValue) ||
18079       (r0.getValueLen() <= 0)) {
18080     jam();
18081     releaseSections(handle);
18082 
18083     evntRecPtr.p->m_errorCode = 1;
18084     evntRecPtr.p->m_errorLine = __LINE__;
18085     evntRecPtr.p->m_errorNode = reference();
18086 
18087     dropEvent_sendReply(signal, evntRecPtr);
18088     DBUG_VOID_RETURN;
18089   }
18090   r0.getString(evntRecPtr.p->m_eventRec.NAME);
18091   {
18092     int len = (int)strlen(evntRecPtr.p->m_eventRec.NAME);
18093     memset(evntRecPtr.p->m_eventRec.NAME+len, 0, MAX_TAB_NAME_SIZE-len);
18094 #ifdef EVENT_DEBUG
18095     printf("DropEvntReq; EventName %s, len %u\n",
18096 	   evntRecPtr.p->m_eventRec.NAME, len);
18097     for(int i = 0; i < MAX_TAB_NAME_SIZE/4; i++)
18098       printf("H'%.8x ", ((Uint32*)evntRecPtr.p->m_eventRec.NAME)[i]);
18099     printf("\n");
18100 #endif
18101   }
18102 
18103   releaseSections(handle);
18104 
18105   Callback c = { safe_cast(&Dbdict::dropEventUTIL_PREPARE_READ), 0 };
18106 
18107   prepareTransactionEventSysTable(&c, signal, evntRecPtr.i,
18108 				  UtilPrepareReq::Read);
18109   DBUG_VOID_RETURN;
18110 }
18111 
18112 void
dropEventUTIL_PREPARE_READ(Signal * signal,Uint32 callbackData,Uint32 returnCode)18113 Dbdict::dropEventUTIL_PREPARE_READ(Signal* signal,
18114 				   Uint32 callbackData,
18115 				   Uint32 returnCode)
18116 {
18117   jam();
18118   EVENT_TRACE;
18119   if (returnCode != 0) {
18120     EVENT_TRACE;
18121     dropEventUtilPrepareRef(signal, callbackData, returnCode);
18122     return;
18123   }
18124 
18125   UtilPrepareConf* const req = (UtilPrepareConf*)signal->getDataPtr();
18126   OpDropEventPtr evntRecPtr;
18127   evntRecPtr.i = req->getSenderData();
18128   const Uint32 prepareId = req->getPrepareId();
18129 
18130   ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
18131 
18132   Callback c = { safe_cast(&Dbdict::dropEventUTIL_EXECUTE_READ), 0 };
18133 
18134   executeTransEventSysTable(&c, signal,
18135 			    evntRecPtr.i, evntRecPtr.p->m_eventRec,
18136 			    prepareId, UtilPrepareReq::Read);
18137 }
18138 
18139 void
dropEventUTIL_EXECUTE_READ(Signal * signal,Uint32 callbackData,Uint32 returnCode)18140 Dbdict::dropEventUTIL_EXECUTE_READ(Signal* signal,
18141 				   Uint32 callbackData,
18142 				   Uint32 returnCode)
18143 {
18144   jam();
18145   EVENT_TRACE;
18146   if (returnCode != 0) {
18147     EVENT_TRACE;
18148     dropEventUtilExecuteRef(signal, callbackData, returnCode);
18149     return;
18150   }
18151 
18152   OpDropEventPtr evntRecPtr;
18153   UtilExecuteConf * const ref = (UtilExecuteConf *)signal->getDataPtr();
18154   jam();
18155   evntRecPtr.i = ref->getSenderData();
18156   ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
18157 
18158   parseReadEventSys(signal, evntRecPtr.p->m_eventRec);
18159 
18160   NodeReceiverGroup rg(DBDICT, c_aliveNodes);
18161   RequestTracker & p = evntRecPtr.p->m_reqTracker;
18162   if (!p.init<SubRemoveRef>(c_counterMgr, rg, GSN_SUB_REMOVE_REF,
18163 			    evntRecPtr.i))
18164   {
18165     evntRecPtr.p->m_errorCode = 701;
18166     dropEvent_sendReply(signal, evntRecPtr);
18167     return;
18168   }
18169 
18170   SubRemoveReq* req = (SubRemoveReq*) signal->getDataPtrSend();
18171 
18172   req->senderRef       = reference();
18173   req->senderData      = evntRecPtr.i;
18174   req->subscriptionId  = evntRecPtr.p->m_eventRec.SUBID;
18175   req->subscriptionKey = evntRecPtr.p->m_eventRec.SUBKEY;
18176 
18177   sendSignal(rg, GSN_SUB_REMOVE_REQ, signal, SubRemoveReq::SignalLength, JBB);
18178 }
18179 
18180 /*
18181  * Participant
18182  */
18183 
18184 void
execSUB_REMOVE_REQ(Signal * signal)18185 Dbdict::execSUB_REMOVE_REQ(Signal* signal)
18186 {
18187   jamEntry();
18188   DBUG_ENTER("Dbdict::execSUB_REMOVE_REQ");
18189 
18190   Uint32 origSenderRef = signal->senderBlockRef();
18191 
18192   OpSubEventPtr subbPtr;
18193   if (!c_opSubEvent.seize(subbPtr)) {
18194     SubRemoveRef * ref = (SubRemoveRef *)signal->getDataPtrSend();
18195     jam();
18196     ref->senderRef = reference();
18197     ref->errorCode = SubRemoveRef::Busy;
18198 
18199     sendSignal(origSenderRef, GSN_SUB_REMOVE_REF, signal,
18200 	       SubRemoveRef::SignalLength, JBB);
18201     DBUG_VOID_RETURN;
18202   }
18203 
18204   {
18205     const SubRemoveReq* req = (SubRemoveReq*) signal->getDataPtr();
18206     subbPtr.p->m_senderRef = req->senderRef;
18207     subbPtr.p->m_senderData = req->senderData;
18208     subbPtr.p->m_errorCode = 0;
18209     subbPtr.p->m_gsn = GSN_SUB_REMOVE_REQ;
18210     subbPtr.p->m_subscriptionId = req->subscriptionId;
18211     subbPtr.p->m_subscriptionKey = req->subscriptionKey;
18212     subbPtr.p->m_subscriberRef = RNIL;
18213     subbPtr.p->m_subscriberData = RNIL;
18214   }
18215 
18216   CRASH_INSERTION2(6010, getOwnNodeId() != c_masterNodeId);
18217 
18218   SubRemoveReq* req = (SubRemoveReq*) signal->getDataPtrSend();
18219   req->senderRef = reference();
18220   req->senderData = subbPtr.i;
18221 
18222   sendSignal(SUMA_REF, GSN_SUB_REMOVE_REQ, signal, SubRemoveReq::SignalLength, JBB);
18223   DBUG_VOID_RETURN;
18224 }
18225 
18226 /*
18227  * Coordintor/Participant
18228  */
18229 
18230 void
execSUB_REMOVE_REF(Signal * signal)18231 Dbdict::execSUB_REMOVE_REF(Signal* signal)
18232 {
18233   jamEntry();
18234   DBUG_ENTER("Dbdict::execSUB_REMOVE_REF");
18235 
18236   const SubRemoveRef* ref = (SubRemoveRef*) signal->getDataPtr();
18237   Uint32 senderRef = ref->senderRef;
18238   Uint32 err= ref->errorCode;
18239 
18240   if (refToBlock(senderRef) == SUMA)
18241   {
18242     /*
18243      * Participant
18244      */
18245     jam();
18246     OpSubEventPtr subbPtr;
18247     c_opSubEvent.getPtr(subbPtr, ref->senderData);
18248     if (err == SubRemoveRef::NoSuchSubscription)
18249     {
18250       jam();
18251       // conf this since this may occur if a nodefailure has occured
18252       // earlier so that the systable was not cleared
18253       SubRemoveConf* conf = (SubRemoveConf*) signal->getDataPtrSend();
18254       conf->senderRef  = reference();
18255       conf->senderData = subbPtr.p->m_senderData;
18256       sendSignal(subbPtr.p->m_senderRef, GSN_SUB_REMOVE_CONF,
18257 		 signal, SubRemoveConf::SignalLength, JBB);
18258     }
18259     else
18260     {
18261       jam();
18262 
18263       if (upgrade_suma_NotStarted(err, subbPtr.p->m_senderRef))
18264       {
18265         jam();
18266         err = SubRemoveRef::NF_FakeErrorREF;
18267       }
18268 
18269       SubRemoveRef* ref = (SubRemoveRef*) signal->getDataPtrSend();
18270       ref->senderRef = reference();
18271       ref->senderData = subbPtr.p->m_senderData;
18272       ref->errorCode = err;
18273       sendSignal(subbPtr.p->m_senderRef, GSN_SUB_REMOVE_REF,
18274 		 signal, SubRemoveRef::SignalLength, JBB);
18275     }
18276     c_opSubEvent.release(subbPtr);
18277     DBUG_VOID_RETURN;
18278   }
18279   /*
18280    * Coordinator
18281    */
18282   ndbrequire(refToBlock(senderRef) == DBDICT);
18283   OpDropEventPtr eventRecPtr;
18284   c_opDropEvent.getPtr(eventRecPtr, ref->senderData);
18285   if (err == SubRemoveRef::NF_FakeErrorREF || err == SubRemoveRef::NotStarted)
18286   {
18287     jam();
18288     eventRecPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(senderRef));
18289   }
18290   else
18291   {
18292     jam();
18293     if (eventRecPtr.p->m_errorCode == 0)
18294     {
18295       eventRecPtr.p->m_errorCode= err ? err : 1;
18296       eventRecPtr.p->m_errorLine= __LINE__;
18297       eventRecPtr.p->m_errorNode= reference();
18298     }
18299     eventRecPtr.p->m_reqTracker.reportRef(c_counterMgr, refToNode(senderRef));
18300   }
18301   completeSubRemoveReq(signal,eventRecPtr.i,0);
18302   DBUG_VOID_RETURN;
18303 }
18304 
18305 void
execSUB_REMOVE_CONF(Signal * signal)18306 Dbdict::execSUB_REMOVE_CONF(Signal* signal)
18307 {
18308   jamEntry();
18309   const SubRemoveConf* conf = (SubRemoveConf*) signal->getDataPtr();
18310   Uint32 senderRef = conf->senderRef;
18311 
18312   if (refToBlock(senderRef) == SUMA) {
18313     /*
18314      * Participant
18315      */
18316     jam();
18317     OpSubEventPtr subbPtr;
18318     c_opSubEvent.getPtr(subbPtr, conf->senderData);
18319     SubRemoveConf* conf = (SubRemoveConf*) signal->getDataPtrSend();
18320     conf->senderRef = reference();
18321     conf->senderData = subbPtr.p->m_senderData;
18322     sendSignal(subbPtr.p->m_senderRef, GSN_SUB_REMOVE_CONF,
18323 	       signal, SubRemoveConf::SignalLength, JBB);
18324     c_opSubEvent.release(subbPtr);
18325     return;
18326   }
18327   /*
18328    * Coordinator
18329    */
18330   ndbrequire(refToBlock(senderRef) == DBDICT);
18331   OpDropEventPtr eventRecPtr;
18332   c_opDropEvent.getPtr(eventRecPtr, conf->senderData);
18333   eventRecPtr.p->m_reqTracker.reportConf(c_counterMgr, refToNode(senderRef));
18334   completeSubRemoveReq(signal,eventRecPtr.i,0);
18335 }
18336 
18337 void
completeSubRemoveReq(Signal * signal,Uint32 ptrI,Uint32 xxx)18338 Dbdict::completeSubRemoveReq(Signal* signal, Uint32 ptrI, Uint32 xxx)
18339 {
18340   OpDropEventPtr evntRecPtr;
18341   c_opDropEvent.getPtr(evntRecPtr, ptrI);
18342 
18343   if (!evntRecPtr.p->m_reqTracker.done()){
18344     jam();
18345     return;
18346   }
18347 
18348   if (evntRecPtr.p->m_reqTracker.hasRef()) {
18349     jam();
18350     if ( evntRecPtr.p->m_errorCode == 0 )
18351     {
18352       evntRecPtr.p->m_errorNode = reference();
18353       evntRecPtr.p->m_errorLine = __LINE__;
18354       evntRecPtr.p->m_errorCode = 1;
18355     }
18356     dropEvent_sendReply(signal, evntRecPtr);
18357     return;
18358   }
18359 
18360   Callback c = { safe_cast(&Dbdict::dropEventUTIL_PREPARE_DELETE), 0 };
18361 
18362   prepareTransactionEventSysTable(&c, signal, evntRecPtr.i,
18363 				  UtilPrepareReq::Delete);
18364 }
18365 
18366 void
dropEventUTIL_PREPARE_DELETE(Signal * signal,Uint32 callbackData,Uint32 returnCode)18367 Dbdict::dropEventUTIL_PREPARE_DELETE(Signal* signal,
18368 				     Uint32 callbackData,
18369 				     Uint32 returnCode)
18370 {
18371   jam();
18372   EVENT_TRACE;
18373   if (returnCode != 0) {
18374     EVENT_TRACE;
18375     dropEventUtilPrepareRef(signal, callbackData, returnCode);
18376     return;
18377   }
18378 
18379   UtilPrepareConf* const req = (UtilPrepareConf*)signal->getDataPtr();
18380   OpDropEventPtr evntRecPtr;
18381   jam();
18382   evntRecPtr.i = req->getSenderData();
18383   const Uint32 prepareId = req->getPrepareId();
18384 
18385   ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
18386 #ifdef EVENT_DEBUG
18387   printf("DropEvntUTIL_PREPARE; evntRecPtr.i len %u\n",evntRecPtr.i);
18388 #endif
18389 
18390   Callback c = { safe_cast(&Dbdict::dropEventUTIL_EXECUTE_DELETE), 0 };
18391 
18392   executeTransEventSysTable(&c, signal,
18393 			    evntRecPtr.i, evntRecPtr.p->m_eventRec,
18394 			    prepareId, UtilPrepareReq::Delete);
18395 }
18396 
18397 void
dropEventUTIL_EXECUTE_DELETE(Signal * signal,Uint32 callbackData,Uint32 returnCode)18398 Dbdict::dropEventUTIL_EXECUTE_DELETE(Signal* signal,
18399 				     Uint32 callbackData,
18400 				     Uint32 returnCode)
18401 {
18402   jam();
18403   EVENT_TRACE;
18404   if (returnCode != 0) {
18405     EVENT_TRACE;
18406     dropEventUtilExecuteRef(signal, callbackData, returnCode);
18407     return;
18408   }
18409 
18410   OpDropEventPtr evntRecPtr;
18411   UtilExecuteConf * const ref = (UtilExecuteConf *)signal->getDataPtr();
18412   jam();
18413   evntRecPtr.i = ref->getSenderData();
18414   ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
18415 
18416   dropEvent_sendReply(signal, evntRecPtr);
18417 }
18418 
18419 void
dropEventUtilPrepareRef(Signal * signal,Uint32 callbackData,Uint32 returnCode)18420 Dbdict::dropEventUtilPrepareRef(Signal* signal,
18421 				Uint32 callbackData,
18422 				Uint32 returnCode)
18423 {
18424   jam();
18425   EVENT_TRACE;
18426   UtilPrepareRef * const ref = (UtilPrepareRef *)signal->getDataPtr();
18427   OpDropEventPtr evntRecPtr;
18428   evntRecPtr.i = ref->getSenderData();
18429   ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
18430 
18431   interpretUtilPrepareErrorCode((UtilPrepareRef::ErrorCode)ref->getErrorCode(),
18432 				evntRecPtr.p->m_errorCode,
18433                                 evntRecPtr.p->m_errorLine, this);
18434   evntRecPtr.p->m_errorNode = reference();
18435 
18436   dropEvent_sendReply(signal, evntRecPtr);
18437 }
18438 
18439 void
dropEventUtilExecuteRef(Signal * signal,Uint32 callbackData,Uint32 returnCode)18440 Dbdict::dropEventUtilExecuteRef(Signal* signal,
18441 				Uint32 callbackData,
18442 				Uint32 returnCode)
18443 {
18444   jam();
18445   EVENT_TRACE;
18446   OpDropEventPtr evntRecPtr;
18447   UtilExecuteRef * const ref = (UtilExecuteRef *)signal->getDataPtr();
18448   jam();
18449   evntRecPtr.i = ref->getSenderData();
18450   ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
18451 
18452   evntRecPtr.p->m_errorNode = reference();
18453   evntRecPtr.p->m_errorLine = __LINE__;
18454 
18455   switch (ref->getErrorCode()) {
18456   case UtilExecuteRef::TCError:
18457     switch (ref->getTCErrorCode()) {
18458     case ZNOT_FOUND:
18459       jam();
18460       evntRecPtr.p->m_errorCode = 4710;
18461       break;
18462     default:
18463       jam();
18464       evntRecPtr.p->m_errorCode = ref->getTCErrorCode();
18465       break;
18466     }
18467     break;
18468   default:
18469     jam();
18470     evntRecPtr.p->m_errorCode = ref->getErrorCode();
18471     break;
18472   }
18473   dropEvent_sendReply(signal, evntRecPtr);
18474 }
18475 
dropEvent_sendReply(Signal * signal,OpDropEventPtr evntRecPtr)18476 void Dbdict::dropEvent_sendReply(Signal* signal,
18477 				 OpDropEventPtr evntRecPtr)
18478 {
18479   jam();
18480   EVENT_TRACE;
18481   Uint32 senderRef = evntRecPtr.p->m_request.getUserRef();
18482 
18483   if (evntRecPtr.p->hasError()) {
18484     jam();
18485     DropEvntRef * ret = (DropEvntRef *)signal->getDataPtrSend();
18486 
18487     ret->setUserData(evntRecPtr.p->m_request.getUserData());
18488     ret->setUserRef(evntRecPtr.p->m_request.getUserRef());
18489 
18490     ret->setErrorCode(evntRecPtr.p->m_errorCode);
18491     ret->setErrorLine(evntRecPtr.p->m_errorLine);
18492     ret->setErrorNode(evntRecPtr.p->m_errorNode);
18493 
18494     sendSignal(senderRef, GSN_DROP_EVNT_REF, signal,
18495 	       DropEvntRef::SignalLength, JBB);
18496   } else {
18497     jam();
18498     DropEvntConf * evntConf = (DropEvntConf *)signal->getDataPtrSend();
18499 
18500     evntConf->setUserData(evntRecPtr.p->m_request.getUserData());
18501     evntConf->setUserRef(evntRecPtr.p->m_request.getUserRef());
18502 
18503     sendSignal(senderRef, GSN_DROP_EVNT_CONF, signal,
18504 	       DropEvntConf::SignalLength, JBB);
18505   }
18506 
18507   c_opDropEvent.release(evntRecPtr);
18508 }
18509 
18510 // MODULE: CreateTrigger
18511 
18512 const Dbdict::OpInfo
18513 Dbdict::CreateTriggerRec::g_opInfo = {
18514   { 'C', 'T', 'r', 0 },
18515   ~RT_DBDICT_CREATE_TRIGGER,
18516   GSN_CREATE_TRIG_IMPL_REQ,
18517   CreateTrigImplReq::SignalLength,
18518   //
18519   &Dbdict::createTrigger_seize,
18520   &Dbdict::createTrigger_release,
18521   //
18522   &Dbdict::createTrigger_parse,
18523   &Dbdict::createTrigger_subOps,
18524   &Dbdict::createTrigger_reply,
18525   //
18526   &Dbdict::createTrigger_prepare,
18527   &Dbdict::createTrigger_commit,
18528   &Dbdict::createTrigger_complete,
18529   //
18530   &Dbdict::createTrigger_abortParse,
18531   &Dbdict::createTrigger_abortPrepare
18532 };
18533 
18534 bool
createTrigger_seize(SchemaOpPtr op_ptr)18535 Dbdict::createTrigger_seize(SchemaOpPtr op_ptr)
18536 {
18537   return seizeOpRec<CreateTriggerRec>(op_ptr);
18538 }
18539 
18540 void
createTrigger_release(SchemaOpPtr op_ptr)18541 Dbdict::createTrigger_release(SchemaOpPtr op_ptr)
18542 {
18543   releaseOpRec<CreateTriggerRec>(op_ptr);
18544 }
18545 
18546 void
execCREATE_TRIG_REQ(Signal * signal)18547 Dbdict::execCREATE_TRIG_REQ(Signal* signal)
18548 {
18549   jamEntry();
18550   if (!assembleFragments(signal)) {
18551     jam();
18552     return;
18553   }
18554   SectionHandle handle(this, signal);
18555 
18556   const CreateTrigReq req_copy =
18557     *(const CreateTrigReq*)signal->getDataPtr();
18558   const CreateTrigReq* req = &req_copy;
18559 
18560   ErrorInfo error;
18561   do {
18562     SchemaOpPtr op_ptr;
18563     CreateTriggerRecPtr createTriggerPtr;
18564     CreateTrigImplReq* impl_req;
18565 
18566     startClientReq(op_ptr, createTriggerPtr, req, impl_req, error);
18567     if (hasError(error)) {
18568       jam();
18569       break;
18570     }
18571 
18572     impl_req->tableId = req->tableId;
18573     impl_req->tableVersion = req->tableVersion;
18574     impl_req->indexId = req->indexId;
18575     impl_req->indexVersion = req->indexVersion;
18576     impl_req->triggerNo = req->triggerNo;
18577     impl_req->triggerId = req->forceTriggerId;
18578     impl_req->triggerInfo = req->triggerInfo;
18579     impl_req->receiverRef = req->receiverRef;
18580 
18581     handleClientReq(signal, op_ptr, handle);
18582     return;
18583   } while (0);
18584 
18585   releaseSections(handle);
18586 
18587   CreateTrigRef* ref = (CreateTrigRef*)signal->getDataPtrSend();
18588 
18589   ref->senderRef = reference();
18590   ref->clientData = req->clientData;
18591   ref->transId = req->transId;
18592   ref->tableId = req->tableId;
18593   ref->indexId = req->indexId;
18594   ref->triggerInfo = req->triggerInfo;
18595   getError(error, ref);
18596 
18597   sendSignal(req->clientRef, GSN_CREATE_TRIG_REF, signal,
18598              CreateTrigRef::SignalLength, JBB);
18599 }
18600 
18601 // CreateTrigger: PARSE
18602 
18603 void
createTrigger_parse(Signal * signal,bool master,SchemaOpPtr op_ptr,SectionHandle & handle,ErrorInfo & error)18604 Dbdict::createTrigger_parse(Signal* signal, bool master,
18605                             SchemaOpPtr op_ptr,
18606                             SectionHandle& handle, ErrorInfo& error)
18607 {
18608   D("createTrigger_parse" << V(op_ptr.i) << *op_ptr.p);
18609 
18610   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
18611   CreateTriggerRecPtr createTriggerPtr;
18612   getOpRec(op_ptr, createTriggerPtr);
18613   CreateTrigImplReq* impl_req = &createTriggerPtr.p->m_request;
18614 
18615   // check request type
18616   Uint32 requestType = impl_req->requestType;
18617   switch (CreateTrigReq::getOnlineFlag(requestType)) {
18618   case CreateTrigImplReq::CreateTriggerOnline:
18619     break;
18620   case CreateTrigImplReq::CreateTriggerOffline:
18621     jam();
18622   default:
18623     ndbassert(false);
18624     setError(error, CreateTrigRef::BadRequestType, __LINE__);
18625     return;
18626   }
18627 
18628   // check the table
18629   {
18630     const Uint32 tableId = impl_req->tableId;
18631     if (! (tableId < c_noOfMetaTables))
18632     {
18633       jam();
18634       setError(error, CreateTrigRef::InvalidTable, __LINE__);
18635       return;
18636     }
18637 
18638     Uint32 err;
18639     if ((err = check_read_obj(tableId, trans_ptr.p->m_transId)))
18640     {
18641       jam();
18642       setError(error, err, __LINE__);
18643       return;
18644     }
18645   }
18646 
18647   switch(CreateTrigReq::getEndpointFlag(requestType)){
18648   case CreateTrigReq::MainTrigger:
18649     jam();
18650     createTriggerPtr.p->m_main_op = true;
18651     break;
18652   case CreateTrigReq::TriggerDst:
18653     jam();
18654   case CreateTrigReq::TriggerSrc:
18655     jam();
18656     if (handle.m_cnt)
18657     {
18658       jam();
18659       ndbassert(false);
18660       setError(error, CreateTrigRef::BadRequestType, __LINE__);
18661       return;
18662     }
18663     createTriggerPtr.p->m_main_op = false;
18664     createTrigger_parse_endpoint(signal, op_ptr, error);
18665     return;
18666   }
18667 
18668   SegmentedSectionPtr ss_ptr;
18669   handle.getSection(ss_ptr, CreateTrigReq::TRIGGER_NAME_SECTION);
18670   SimplePropertiesSectionReader r(ss_ptr, getSectionSegmentPool());
18671   DictTabInfo::Table tableDesc;
18672   tableDesc.init();
18673   SimpleProperties::UnpackStatus status =
18674     SimpleProperties::unpack(r, &tableDesc,
18675 			     DictTabInfo::TableMapping,
18676 			     DictTabInfo::TableMappingSize,
18677 			     true, true);
18678 
18679   if (status != SimpleProperties::Eof ||
18680       tableDesc.TableName[0] == 0)
18681   {
18682     jam();
18683     ndbassert(false);
18684     setError(error, CreateTrigRef::InvalidName, __LINE__);
18685     return;
18686   }
18687   const Uint32 bytesize = sizeof(createTriggerPtr.p->m_triggerName);
18688   memcpy(createTriggerPtr.p->m_triggerName, tableDesc.TableName, bytesize);
18689   D("trigger " << createTriggerPtr.p->m_triggerName);
18690 
18691   // check name is unique
18692   if (get_object(createTriggerPtr.p->m_triggerName) != 0) {
18693     jam();
18694     D("duplicate trigger name " << createTriggerPtr.p->m_triggerName);
18695     setError(error, CreateTrigRef::TriggerExists, __LINE__);
18696     return;
18697   }
18698 
18699   TriggerRecordPtr triggerPtr;
18700   if (master)
18701   {
18702     jam();
18703     if (impl_req->triggerId == RNIL)
18704     {
18705       jam();
18706       impl_req->triggerId = getFreeTriggerRecord();
18707       if (impl_req->triggerId == RNIL)
18708       {
18709         jam();
18710         setError(error, CreateTrigRef::TooManyTriggers, __LINE__);
18711         return;
18712       }
18713       bool ok = find_object(triggerPtr, impl_req->triggerId);
18714       if (ok)
18715       {
18716         jam();
18717         setError(error, CreateTrigRef::TriggerExists, __LINE__);
18718         return;
18719       }
18720       D("master allocated triggerId " << impl_req->triggerId);
18721     }
18722     else
18723     {
18724       if (!(impl_req->triggerId < c_triggerRecordPool_.getSize()))
18725       {
18726 	jam();
18727 	setError(error, CreateTrigRef::TooManyTriggers, __LINE__);
18728 	return;
18729       }
18730       bool ok = find_object(triggerPtr, impl_req->triggerId);
18731       if (ok)
18732       {
18733         jam();
18734         setError(error, CreateTrigRef::TriggerExists, __LINE__);
18735         return;
18736       }
18737       D("master forced triggerId " << impl_req->triggerId);
18738     }
18739   }
18740   else
18741   {
18742     jam();
18743     // slave receives trigger id from master
18744     if (! (impl_req->triggerId < c_triggerRecordPool_.getSize()))
18745     {
18746       jam();
18747       setError(error, CreateTrigRef::TooManyTriggers, __LINE__);
18748       return;
18749     }
18750     bool ok = find_object(triggerPtr, impl_req->triggerId);
18751     if (ok)
18752     {
18753       jam();
18754       setError(error, CreateTrigRef::TriggerExists, __LINE__);
18755       return;
18756     }
18757     D("slave allocated triggerId " << hex << impl_req->triggerId);
18758   }
18759 
18760   bool ok = seizeTriggerRecord(triggerPtr, impl_req->triggerId);
18761   if (!ok)
18762   {
18763     jam();
18764     setError(error, CreateTrigRef::TooManyTriggers, __LINE__);
18765     return;
18766   }
18767   triggerPtr.p->tableId = impl_req->tableId;
18768   triggerPtr.p->indexId = RNIL; // feedback method connects to index
18769   triggerPtr.p->triggerInfo = impl_req->triggerInfo;
18770   triggerPtr.p->receiverRef = impl_req->receiverRef;
18771   triggerPtr.p->triggerState = TriggerRecord::TS_DEFINING;
18772 
18773   // TODO:msundell on failure below, leak of TriggerRecord
18774   if (handle.m_cnt >= 2)
18775   {
18776     jam();
18777     SegmentedSectionPtr mask_ptr;
18778     handle.getSection(mask_ptr, CreateTrigReq::ATTRIBUTE_MASK_SECTION);
18779     if (mask_ptr.sz > triggerPtr.p->attributeMask.getSizeInWords())
18780     {
18781       jam();
18782       setError(error, CreateTrigRef::BadRequestType, __LINE__);
18783       return;
18784     }
18785     ::copy(triggerPtr.p->attributeMask.rep.data, mask_ptr);
18786     if (mask_ptr.sz < triggerPtr.p->attributeMask.getSizeInWords())
18787     {
18788       jam();
18789       Uint32 len = triggerPtr.p->attributeMask.getSizeInWords() - mask_ptr.sz;
18790       bzero(triggerPtr.p->attributeMask.rep.data + mask_ptr.sz,
18791             4 * len);
18792     }
18793   }
18794   else
18795   {
18796     jam();
18797     setError(error, CreateTrigRef::BadRequestType, __LINE__);
18798     return;
18799   }
18800 
18801   {
18802     LocalRope name(c_rope_pool, triggerPtr.p->triggerName);
18803     if (!name.assign(createTriggerPtr.p->m_triggerName)) {
18804       jam();
18805       setError(error, CreateTrigRef::OutOfStringBuffer, __LINE__);
18806       return;
18807     }
18808   }
18809 
18810   // connect to new DictObject
18811   {
18812     DictObjectPtr obj_ptr;
18813     seizeDictObject(op_ptr, obj_ptr, triggerPtr.p->triggerName); // added to c_obj_name_hash
18814 
18815     obj_ptr.p->m_id = impl_req->triggerId; // wl3600_todo id
18816     obj_ptr.p->m_type =
18817       TriggerInfo::getTriggerType(triggerPtr.p->triggerInfo);
18818     link_object(obj_ptr, triggerPtr);
18819     c_obj_id_hash.add(obj_ptr);
18820   }
18821 
18822   {
18823     TriggerType::Value type =
18824       TriggerInfo::getTriggerType(triggerPtr.p->triggerInfo);
18825     switch(type){
18826     case TriggerType::REORG_TRIGGER:
18827       jam();
18828       createTrigger_create_drop_trigger_operation(signal, op_ptr, error);
18829     case TriggerType::SECONDARY_INDEX:
18830     case TriggerType::FK_PARENT:
18831     case TriggerType::FK_CHILD:
18832       jam();
18833       createTriggerPtr.p->m_sub_dst = false;
18834       createTriggerPtr.p->m_sub_src = false;
18835       break;
18836     case TriggerType::ORDERED_INDEX:
18837     case TriggerType::READ_ONLY_CONSTRAINT:
18838       jam();
18839       createTriggerPtr.p->m_sub_dst = true; // Only need LQH
18840       createTriggerPtr.p->m_sub_src = false;
18841       break;
18842     default:
18843     case TriggerType::SUBSCRIPTION:
18844     case TriggerType::SUBSCRIPTION_BEFORE:
18845       ndbassert(false);
18846       setError(error, CreateTrigRef::UnsupportedTriggerType, __LINE__);
18847       return;
18848     }
18849   }
18850 
18851   if (ERROR_INSERTED(6124))
18852   {
18853     jam();
18854     CLEAR_ERROR_INSERT_VALUE;
18855     setError(error, 9124, __LINE__);
18856     return;
18857   }
18858 
18859   triggerPtr.p->indexId = impl_req->indexId;
18860   if (impl_req->indexId != RNIL)
18861   {
18862     jam();
18863     TableRecordPtr indexPtr;
18864     if (find_object(indexPtr, impl_req->indexId))
18865     {
18866       jam();
18867       indexPtr.p->triggerId = impl_req->triggerId;
18868     }
18869     ForeignKeyRecPtr fk_ptr;
18870     if (find_object(fk_ptr, impl_req->indexId))
18871     {
18872       jam();
18873       switch (impl_req->triggerNo) {
18874       case 0:
18875         fk_ptr.p->m_parentTriggerId = impl_req->triggerId;
18876         D("fk: parent" << V(impl_req->triggerId));
18877         break;
18878       case 1:
18879         fk_ptr.p->m_childTriggerId = impl_req->triggerId;
18880         D("fk: child" << V(impl_req->triggerId));
18881         break;
18882       default:
18883         ndbrequire(false);
18884         break;
18885       }
18886     }
18887   }
18888 }
18889 
18890 void
createTrigger_parse_endpoint(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo & error)18891 Dbdict::createTrigger_parse_endpoint(Signal* signal,
18892 				     SchemaOpPtr op_ptr,
18893 				     ErrorInfo& error)
18894 {
18895   jam();
18896 
18897   CreateTriggerRecPtr createTriggerPtr;
18898   getOpRec(op_ptr, createTriggerPtr);
18899   CreateTrigImplReq* impl_req = &createTriggerPtr.p->m_request;
18900 
18901   // check request type
18902   Uint32 requestType = impl_req->requestType;
18903   switch(CreateTrigReq::getEndpointFlag(requestType)){
18904   case CreateTrigReq::TriggerDst:
18905     jam();
18906     createTriggerPtr.p->m_block_list[0] = DBTC_REF;
18907     break;
18908   case CreateTrigReq::TriggerSrc:
18909     jam();
18910     createTriggerPtr.p->m_block_list[0] = DBLQH_REF;
18911     break;
18912   default:
18913     ndbassert(false);
18914     setError(error, CreateTrigRef::BadRequestType, __LINE__);
18915     return;
18916   }
18917 
18918   TriggerRecordPtr triggerPtr;
18919   bool ok = find_object(triggerPtr, impl_req->triggerId);
18920   if (!ok)
18921   {
18922     jam();
18923     return;
18924   }
18925   switch(TriggerInfo::getTriggerType(triggerPtr.p->triggerInfo)){
18926   case TriggerType::REORG_TRIGGER:
18927     jam();
18928     createTrigger_create_drop_trigger_operation(signal, op_ptr, error);
18929     return;
18930   default:
18931     return;
18932   }
18933 }
18934 
18935 void
createTrigger_create_drop_trigger_operation(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo & error)18936 Dbdict::createTrigger_create_drop_trigger_operation(Signal* signal,
18937                                                     SchemaOpPtr op_ptr,
18938                                                     ErrorInfo& error)
18939 {
18940   jam();
18941 
18942   CreateTriggerRecPtr createTriggerPtr;
18943   getOpRec(op_ptr, createTriggerPtr);
18944   CreateTrigImplReq* impl_req = &createTriggerPtr.p->m_request;
18945 
18946   /**
18947    * Construct a dropTrigger operation
18948    */
18949   SchemaOpPtr oplnk_ptr;
18950   DropTriggerRecPtr dropTriggerPtr;
18951   if(!seizeLinkedSchemaOp(op_ptr, oplnk_ptr, dropTriggerPtr))
18952   {
18953     jam();
18954     setError(error, CreateTrigRef::TooManyTriggers, __LINE__);
18955     return;
18956   }
18957 
18958 
18959   DropTrigImplReq* aux_impl_req = &dropTriggerPtr.p->m_request;
18960   aux_impl_req->senderRef = reference();
18961   aux_impl_req->senderData = op_ptr.p->op_key;
18962   aux_impl_req->requestType = 0;
18963   aux_impl_req->tableId = impl_req->tableId;
18964   aux_impl_req->tableVersion = 0; // not used
18965   aux_impl_req->indexId = 0;
18966   aux_impl_req->indexVersion = 0; // not used
18967   aux_impl_req->triggerNo = 0;
18968   aux_impl_req->triggerId = impl_req->triggerId;
18969   aux_impl_req->triggerInfo = impl_req->triggerInfo;
18970 
18971   dropTriggerPtr.p->m_main_op = createTriggerPtr.p->m_main_op;
18972 
18973   if (createTriggerPtr.p->m_main_op)
18974   {
18975     jam();
18976     return;
18977   }
18978 
18979   switch(refToBlock(createTriggerPtr.p->m_block_list[0])){
18980   case DBTC:
18981     jam();
18982     dropTriggerPtr.p->m_block_list[0] = DBLQH_REF;
18983     break;
18984   case DBLQH:
18985     jam();
18986     dropTriggerPtr.p->m_block_list[0] = DBTC_REF;
18987     break;
18988   default:
18989     ndbassert(false);
18990     setError(error, CreateTrigRef::BadRequestType, __LINE__);
18991     return;
18992   }
18993 }
18994 
18995 bool
createTrigger_subOps(Signal * signal,SchemaOpPtr op_ptr)18996 Dbdict::createTrigger_subOps(Signal* signal, SchemaOpPtr op_ptr)
18997 {
18998   D("createTrigger_subOps" << V(op_ptr.i) << *op_ptr.p);
18999 
19000   CreateTriggerRecPtr createTriggerPtr;
19001   getOpRec(op_ptr, createTriggerPtr);
19002 
19003   Uint32 requestType =
19004     DictSignal::getRequestType(createTriggerPtr.p->m_request.requestType);
19005   switch(CreateTrigReq::getEndpointFlag(requestType)){
19006   case CreateTrigReq::MainTrigger:
19007     jam();
19008     break;
19009   case CreateTrigReq::TriggerDst:
19010   case CreateTrigReq::TriggerSrc:
19011     jam();
19012     return false;
19013   }
19014 
19015   /**
19016    * NOTE create dst before src
19017    */
19018   if (!createTriggerPtr.p->m_sub_dst)
19019   {
19020     jam();
19021     createTriggerPtr.p->m_sub_dst = true;
19022     Callback c = {
19023       safe_cast(&Dbdict::createTrigger_fromCreateEndpoint),
19024       op_ptr.p->op_key
19025     };
19026     op_ptr.p->m_callback = c;
19027     createTrigger_toCreateEndpoint(signal, op_ptr,
19028 				   CreateTrigReq::TriggerDst);
19029     return true;
19030   }
19031 
19032   if (!createTriggerPtr.p->m_sub_src)
19033   {
19034     jam();
19035     createTriggerPtr.p->m_sub_src = true;
19036     Callback c = {
19037       safe_cast(&Dbdict::createTrigger_fromCreateEndpoint),
19038       op_ptr.p->op_key
19039     };
19040     op_ptr.p->m_callback = c;
19041     createTrigger_toCreateEndpoint(signal, op_ptr,
19042 				   CreateTrigReq::TriggerSrc);
19043     return true;
19044   }
19045 
19046   return false;
19047 }
19048 
19049 void
createTrigger_toCreateEndpoint(Signal * signal,SchemaOpPtr op_ptr,CreateTrigReq::EndpointFlag endpoint)19050 Dbdict::createTrigger_toCreateEndpoint(Signal* signal,
19051 				       SchemaOpPtr op_ptr,
19052 				       CreateTrigReq::EndpointFlag endpoint)
19053 {
19054   D("alterIndex_toCreateTrigger");
19055 
19056   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
19057   CreateTriggerRecPtr createTriggerPtr;
19058   getOpRec(op_ptr, createTriggerPtr);
19059   const CreateTrigImplReq* impl_req = &createTriggerPtr.p->m_request;
19060 
19061   CreateTrigReq* req = (CreateTrigReq*)signal->getDataPtrSend();
19062 
19063   Uint32 type = 0;
19064   CreateTrigReq::setOnlineFlag(type, CreateTrigReq::CreateTriggerOnline);
19065   CreateTrigReq::setEndpointFlag(type, endpoint);
19066 
19067   Uint32 requestInfo = 0;
19068   DictSignal::setRequestType(requestInfo, type);
19069   DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
19070 
19071   req->clientRef = reference();
19072   req->clientData = op_ptr.p->op_key;
19073   req->transId = trans_ptr.p->m_transId;
19074   req->transKey = trans_ptr.p->trans_key;
19075   req->requestInfo = requestInfo;
19076   req->tableId = impl_req->tableId;
19077   req->tableVersion = impl_req->tableVersion;
19078   req->indexId = impl_req->indexId;
19079   req->indexVersion = impl_req->indexVersion;
19080   req->forceTriggerId = impl_req->triggerId;
19081   req->triggerInfo = impl_req->triggerInfo;
19082 
19083   sendSignal(reference(), GSN_CREATE_TRIG_REQ, signal,
19084              CreateTrigReq::SignalLength, JBB);
19085 }
19086 
19087 void
createTrigger_fromCreateEndpoint(Signal * signal,Uint32 op_key,Uint32 ret)19088 Dbdict::createTrigger_fromCreateEndpoint(Signal* signal,
19089 					 Uint32 op_key, Uint32 ret)
19090 {
19091   SchemaOpPtr op_ptr;
19092   CreateTriggerRecPtr createTriggerPtr;
19093   findSchemaOp(op_ptr, createTriggerPtr, op_key);
19094   ndbrequire(!op_ptr.isNull());
19095   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
19096 
19097   if (ret == 0)
19098   {
19099     jam();
19100     const CreateTrigConf* conf =
19101       (const CreateTrigConf*)signal->getDataPtr();
19102 
19103     ndbrequire(conf->transId == trans_ptr.p->m_transId);
19104     createSubOps(signal, op_ptr);
19105   }
19106   else
19107   {
19108     jam();
19109     const CreateTrigRef* ref =
19110       (const CreateTrigRef*)signal->getDataPtr();
19111     ErrorInfo error;
19112     setError(error, ref);
19113     abortSubOps(signal, op_ptr, error);
19114   }
19115 }
19116 
19117 void
createTrigger_reply(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)19118 Dbdict::createTrigger_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
19119 {
19120   jam();
19121 
19122   SchemaTransPtr& trans_ptr = op_ptr.p->m_trans_ptr;
19123   CreateTriggerRecPtr createTriggerPtr;
19124   getOpRec(op_ptr, createTriggerPtr);
19125   const CreateTrigImplReq* impl_req = &createTriggerPtr.p->m_request;
19126 
19127   D("createTrigger_reply" << V(impl_req->triggerId) << *op_ptr.p);
19128 
19129   if (!hasError(error)) {
19130     CreateTrigConf* conf = (CreateTrigConf*)signal->getDataPtrSend();
19131     conf->senderRef = reference();
19132     conf->clientData = op_ptr.p->m_clientData;
19133     conf->transId = trans_ptr.p->m_transId;
19134     conf->tableId = impl_req->tableId;
19135     conf->indexId = impl_req->indexId;
19136     conf->triggerId = impl_req->triggerId;
19137     conf->triggerInfo = impl_req->triggerInfo;
19138 
19139     Uint32 clientRef = op_ptr.p->m_clientRef;
19140     sendSignal(clientRef, GSN_CREATE_TRIG_CONF, signal,
19141                CreateTrigConf::SignalLength, JBB);
19142   } else {
19143     jam();
19144     CreateTrigRef* ref = (CreateTrigRef*)signal->getDataPtrSend();
19145     ref->senderRef = reference();
19146     ref->clientData = op_ptr.p->m_clientData;
19147     ref->transId = trans_ptr.p->m_transId;
19148     ref->tableId = impl_req->tableId;
19149     ref->indexId = impl_req->indexId;
19150     ref->triggerInfo =impl_req->triggerInfo;
19151     getError(error, ref);
19152 
19153     Uint32 clientRef = op_ptr.p->m_clientRef;
19154     sendSignal(clientRef, GSN_CREATE_TRIG_REF, signal,
19155                CreateTrigRef::SignalLength, JBB);
19156   }
19157 }
19158 
19159 // CreateTrigger: PREPARE
19160 
19161 void
createTrigger_prepare(Signal * signal,SchemaOpPtr op_ptr)19162 Dbdict::createTrigger_prepare(Signal* signal, SchemaOpPtr op_ptr)
19163 {
19164   jam();
19165   CreateTriggerRecPtr createTriggerPtr;
19166   getOpRec(op_ptr, createTriggerPtr);
19167 
19168   if (createTriggerPtr.p->m_main_op)
19169   {
19170     jam();
19171     sendTransConf(signal, op_ptr);
19172     return;
19173   }
19174 
19175   if (ERROR_INSERTED(6213))
19176   {
19177     CLEAR_ERROR_INSERT_VALUE;
19178     setError(op_ptr, 1, __LINE__);
19179     sendTransRef(signal, op_ptr);
19180     return;
19181   }
19182 
19183   Callback c =  { safe_cast(&Dbdict::createTrigger_prepare_fromLocal),
19184                   op_ptr.p->op_key
19185   };
19186 
19187   op_ptr.p->m_callback = c;
19188   send_create_trig_req(signal, op_ptr);
19189 }
19190 
19191 void
createTrigger_prepare_fromLocal(Signal * signal,Uint32 op_key,Uint32 ret)19192 Dbdict::createTrigger_prepare_fromLocal(Signal* signal,
19193                                         Uint32 op_key, Uint32 ret)
19194 {
19195   SchemaOpPtr op_ptr;
19196   CreateTriggerRecPtr createTriggerPtr;
19197   findSchemaOp(op_ptr, createTriggerPtr, op_key);
19198   ndbrequire(!op_ptr.isNull());
19199 
19200   if (ret == 0)
19201   {
19202     jam();
19203     createTriggerPtr.p->m_created = true;
19204     sendTransConf(signal, op_ptr);
19205   }
19206   else
19207   {
19208     jam();
19209     setError(op_ptr, ret, __LINE__);
19210     sendTransRef(signal, op_ptr);
19211   }
19212 }
19213 
19214 // CreateTrigger: COMMIT
19215 
19216 void
createTrigger_commit(Signal * signal,SchemaOpPtr op_ptr)19217 Dbdict::createTrigger_commit(Signal* signal, SchemaOpPtr op_ptr)
19218 {
19219   jam();
19220 
19221   CreateTriggerRecPtr createTriggerPtr;
19222   getOpRec(op_ptr, createTriggerPtr);
19223   const CreateTrigImplReq* impl_req = &createTriggerPtr.p->m_request;
19224 
19225   if (!op_ptr.p->m_oplnk_ptr.isNull())
19226   {
19227     jam();
19228     sendTransConf(signal, op_ptr);
19229     return;
19230   }
19231 
19232   if (createTriggerPtr.p->m_main_op)
19233   {
19234     jam();
19235 
19236     Uint32 triggerId = impl_req->triggerId;
19237     TriggerRecordPtr triggerPtr;
19238     bool ok = find_object(triggerPtr, triggerId);
19239     ndbrequire(ok);
19240     triggerPtr.p->triggerState = TriggerRecord::TS_ONLINE;
19241     unlinkDictObject(op_ptr);
19242   }
19243 
19244   sendTransConf(signal, op_ptr);
19245 }
19246 
19247 // CreateTrigger: COMPLETE
19248 
19249 void
createTrigger_complete(Signal * signal,SchemaOpPtr op_ptr)19250 Dbdict::createTrigger_complete(Signal* signal, SchemaOpPtr op_ptr)
19251 {
19252   jam();
19253 
19254   CreateTriggerRecPtr createTriggerPtr;
19255   getOpRec(op_ptr, createTriggerPtr);
19256 
19257   if (!op_ptr.p->m_oplnk_ptr.isNull())
19258   {
19259     jam();
19260 
19261     /**
19262      * Create trigger commit...will drop trigger
19263      */
19264     if (hasDictObject(op_ptr))
19265     {
19266       jam();
19267       DictObjectPtr obj_ptr;
19268       getDictObject(op_ptr, obj_ptr);
19269       unlinkDictObject(op_ptr);
19270       linkDictObject(op_ptr.p->m_oplnk_ptr, obj_ptr);
19271     }
19272     op_ptr.p->m_oplnk_ptr.p->m_state = SchemaOp::OS_COMPLETING;
19273     dropTrigger_commit(signal, op_ptr.p->m_oplnk_ptr);
19274     return;
19275   }
19276 
19277   sendTransConf(signal, op_ptr);
19278 }
19279 
19280 // CreateTrigger: ABORT
19281 
19282 void
createTrigger_abortParse(Signal * signal,SchemaOpPtr op_ptr)19283 Dbdict::createTrigger_abortParse(Signal* signal, SchemaOpPtr op_ptr)
19284 {
19285   D("createTrigger_abortParse" << *op_ptr.p);
19286 
19287   CreateTriggerRecPtr createTriggerPtr;
19288   getOpRec(op_ptr, createTriggerPtr);
19289   CreateTrigImplReq* impl_req = &createTriggerPtr.p->m_request;
19290   Uint32 triggerId = impl_req->triggerId;
19291 
19292   if (createTriggerPtr.p->m_main_op)
19293   {
19294     jam();
19295 
19296     TriggerRecordPtr triggerPtr;
19297     if (! (triggerId < c_triggerRecordPool_.getSize()))
19298     {
19299       jam();
19300       goto done;
19301     }
19302 
19303     bool ok = find_object(triggerPtr, triggerId);
19304     if (ok)
19305     {
19306       jam();
19307 
19308       if (triggerPtr.p->indexId != RNIL)
19309       {
19310         TableRecordPtr indexPtr;
19311         bool ok = find_object(indexPtr, triggerPtr.p->indexId);
19312         if (ok)
19313         {
19314           jam();
19315           indexPtr.p->triggerId = RNIL;
19316         }
19317         triggerPtr.p->indexId = RNIL;
19318       }
19319 
19320       c_triggerRecordPool_.release(triggerPtr);
19321     }
19322 
19323     // ignore Feedback for now (referencing object will be dropped too)
19324 
19325     if (hasDictObject(op_ptr))
19326     {
19327       jam();
19328       releaseDictObject(op_ptr);
19329     }
19330   }
19331 
19332 done:
19333 
19334   sendTransConf(signal, op_ptr);
19335 }
19336 
19337 void
createTrigger_abortPrepare(Signal * signal,SchemaOpPtr op_ptr)19338 Dbdict::createTrigger_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
19339 {
19340   D("createTrigger_abortPrepare" << *op_ptr.p);
19341 
19342   CreateTriggerRecPtr createTriggerPtr;
19343   getOpRec(op_ptr, createTriggerPtr);
19344   const CreateTrigImplReq* impl_req = &createTriggerPtr.p->m_request;
19345 
19346   if (createTriggerPtr.p->m_main_op)
19347   {
19348     jam();
19349     sendTransConf(signal, op_ptr);
19350     return;
19351   }
19352 
19353   if (createTriggerPtr.p->m_created == false)
19354   {
19355     jam();
19356     sendTransConf(signal, op_ptr);
19357     return;
19358   }
19359 
19360   Callback c =  { safe_cast(&Dbdict::createTrigger_abortPrepare_fromLocal),
19361 		  op_ptr.p->op_key
19362   };
19363   op_ptr.p->m_callback = c;
19364 
19365   DropTrigImplReq* req = (DropTrigImplReq*)signal->getDataPtrSend();
19366   req->senderRef = reference();
19367   req->senderData = op_ptr.p->op_key;
19368   req->requestType = 0;
19369   req->tableId = impl_req->tableId;
19370   req->tableVersion = 0; // not used
19371   req->indexId = impl_req->indexId;
19372   req->indexVersion = 0; // not used
19373   req->triggerNo = 0;
19374   req->triggerId = impl_req->triggerId;
19375   req->triggerInfo = impl_req->triggerInfo;
19376   req->receiverRef = impl_req->receiverRef;
19377 
19378   BlockReference ref = createTriggerPtr.p->m_block_list[0];
19379   sendSignal(ref, GSN_DROP_TRIG_IMPL_REQ, signal,
19380              DropTrigImplReq::SignalLength, JBB);
19381 }
19382 
19383 void
createTrigger_abortPrepare_fromLocal(Signal * signal,Uint32 op_key,Uint32 ret)19384 Dbdict::createTrigger_abortPrepare_fromLocal(Signal* signal,
19385                                              Uint32 op_key, Uint32 ret)
19386 {
19387   SchemaOpPtr op_ptr;
19388   CreateTriggerRecPtr createTriggerPtr;
19389   findSchemaOp(op_ptr, createTriggerPtr, op_key);
19390   ndbrequire(!op_ptr.isNull());
19391 
19392   ndbrequire(ret == 0); // abort can't fail
19393 
19394   sendTransConf(signal, op_ptr);
19395 }
19396 
19397 void
send_create_trig_req(Signal * signal,SchemaOpPtr op_ptr)19398 Dbdict::send_create_trig_req(Signal* signal,
19399                              SchemaOpPtr op_ptr)
19400 {
19401   CreateTriggerRecPtr createTriggerPtr;
19402   getOpRec(op_ptr, createTriggerPtr);
19403   const CreateTrigImplReq* impl_req = &createTriggerPtr.p->m_request;
19404 
19405   TriggerRecordPtr triggerPtr;
19406   bool ok = find_object(triggerPtr, impl_req->triggerId);
19407   ndbrequire(ok);
19408   D("send_create_trig_req");
19409 
19410   CreateTrigImplReq* req = (CreateTrigImplReq*)signal->getDataPtrSend();
19411 
19412   req->senderRef = reference();
19413   req->senderData = op_ptr.p->op_key;
19414   req->requestType = 0;
19415   req->tableId = triggerPtr.p->tableId;
19416   req->tableVersion = 0; // not used
19417   req->indexId = triggerPtr.p->indexId;
19418   req->indexVersion = 0; // not used
19419   req->triggerNo = 0; // not used
19420   req->triggerId = triggerPtr.p->triggerId;
19421   req->triggerInfo = triggerPtr.p->triggerInfo;
19422   req->receiverRef = triggerPtr.p->receiverRef;
19423 
19424   {
19425     /**
19426      * Handle the upgrade...
19427      */
19428     Uint32 tmp[3];
19429     tmp[0] = triggerPtr.p->triggerId;
19430     tmp[1] = triggerPtr.p->triggerId;
19431     tmp[2] = triggerPtr.p->triggerId;
19432 
19433     TableRecordPtr indexPtr;
19434     TriggerType::Value type =
19435       TriggerInfo::getTriggerType(triggerPtr.p->triggerInfo);
19436 
19437     if (type == TriggerType::SECONDARY_INDEX)
19438     {
19439       jam();
19440       bool ok = find_object(indexPtr, triggerPtr.p->indexId);
19441       ndbrequire(ok);
19442       if (indexPtr.p->m_upgrade_trigger_handling.m_upgrade)
19443       {
19444         jam();
19445         tmp[0] = indexPtr.p->m_upgrade_trigger_handling.insertTriggerId;
19446         tmp[1] = indexPtr.p->m_upgrade_trigger_handling.updateTriggerId;
19447         tmp[2] = indexPtr.p->m_upgrade_trigger_handling.deleteTriggerId;
19448       }
19449     }
19450     req->upgradeExtra[0] = tmp[0];
19451     req->upgradeExtra[1] = tmp[1];
19452     req->upgradeExtra[2] = tmp[2];
19453   }
19454 
19455   LinearSectionPtr ptr[3];
19456   ptr[0].p = triggerPtr.p->attributeMask.rep.data;
19457   ptr[0].sz = triggerPtr.p->attributeMask.getSizeInWords();
19458 
19459   BlockReference ref = createTriggerPtr.p->m_block_list[0];
19460   sendSignal(ref, GSN_CREATE_TRIG_IMPL_REQ, signal,
19461              CreateTrigImplReq::SignalLength, JBB, ptr, 1);
19462 }
19463 
19464 // CreateTrigger: MISC
19465 
19466 void
execCREATE_TRIG_CONF(Signal * signal)19467 Dbdict::execCREATE_TRIG_CONF(Signal* signal)
19468 {
19469   jamEntry();
19470   const CreateTrigConf* conf = (const CreateTrigConf*)signal->getDataPtr();
19471   handleDictConf(signal, conf);
19472 }
19473 
19474 void
execCREATE_TRIG_REF(Signal * signal)19475 Dbdict::execCREATE_TRIG_REF(Signal* signal)
19476 {
19477   jamEntry();
19478   const CreateTrigRef* ref = (const CreateTrigRef*)signal->getDataPtr();
19479   handleDictRef(signal, ref);
19480 }
19481 
19482 void
execCREATE_TRIG_IMPL_CONF(Signal * signal)19483 Dbdict::execCREATE_TRIG_IMPL_CONF(Signal* signal)
19484 {
19485   jamEntry();
19486   const CreateTrigImplConf* conf = (const CreateTrigImplConf*)signal->getDataPtr();
19487   ndbrequire(refToNode(conf->senderRef) == getOwnNodeId());
19488   handleDictConf(signal, conf);
19489 }
19490 
19491 void
execCREATE_TRIG_IMPL_REF(Signal * signal)19492 Dbdict::execCREATE_TRIG_IMPL_REF(Signal* signal)
19493 {
19494   jamEntry();
19495   const CreateTrigImplRef* ref = (const CreateTrigImplRef*)signal->getDataPtr();
19496   ndbrequire(refToNode(ref->senderRef) == getOwnNodeId());
19497   handleDictRef(signal, ref);
19498 }
19499 
19500 // CreateTrigger: END
19501 
19502 // MODULE: DropTrigger
19503 
19504 const Dbdict::OpInfo
19505 Dbdict::DropTriggerRec::g_opInfo = {
19506   { 'D', 'T', 'r', 0 },
19507   ~RT_DBDICT_DROP_TRIGGER,
19508   GSN_DROP_TRIG_IMPL_REQ,
19509   DropTrigImplReq::SignalLength,
19510   //
19511   &Dbdict::dropTrigger_seize,
19512   &Dbdict::dropTrigger_release,
19513   //
19514   &Dbdict::dropTrigger_parse,
19515   &Dbdict::dropTrigger_subOps,
19516   &Dbdict::dropTrigger_reply,
19517   //
19518   &Dbdict::dropTrigger_prepare,
19519   &Dbdict::dropTrigger_commit,
19520   &Dbdict::dropTrigger_complete,
19521   //
19522   &Dbdict::dropTrigger_abortParse,
19523   &Dbdict::dropTrigger_abortPrepare
19524 };
19525 
19526 bool
dropTrigger_seize(SchemaOpPtr op_ptr)19527 Dbdict::dropTrigger_seize(SchemaOpPtr op_ptr)
19528 {
19529   return seizeOpRec<DropTriggerRec>(op_ptr);
19530 }
19531 
19532 void
dropTrigger_release(SchemaOpPtr op_ptr)19533 Dbdict::dropTrigger_release(SchemaOpPtr op_ptr)
19534 {
19535   releaseOpRec<DropTriggerRec>(op_ptr);
19536 }
19537 
19538 void
execDROP_TRIG_REQ(Signal * signal)19539 Dbdict::execDROP_TRIG_REQ(Signal* signal)
19540 {
19541   jamEntry();
19542   if (!assembleFragments(signal)) {
19543     jam();
19544     return;
19545   }
19546   SectionHandle handle(this, signal);
19547 
19548   const DropTrigReq req_copy =
19549     *(const DropTrigReq*)signal->getDataPtr();
19550   const DropTrigReq* req = &req_copy;
19551 
19552   ErrorInfo error;
19553   do {
19554     SchemaOpPtr op_ptr;
19555     DropTriggerRecPtr dropTriggerPtr;
19556     DropTrigImplReq* impl_req;
19557 
19558     startClientReq(op_ptr, dropTriggerPtr, req, impl_req, error);
19559     if (hasError(error)) {
19560       jam();
19561       break;
19562     }
19563 
19564     impl_req->tableId = req->tableId;
19565     impl_req->tableVersion = req->tableVersion;
19566     impl_req->indexId = req->indexId;
19567     impl_req->indexVersion = req->indexVersion;
19568     impl_req->triggerNo = req->triggerNo;
19569     impl_req->triggerId = req->triggerId;
19570     impl_req->triggerInfo = ~(Uint32)0;
19571 
19572     handleClientReq(signal, op_ptr, handle);
19573     return;
19574   } while (0);
19575 
19576   releaseSections(handle);
19577 
19578   DropTrigRef* ref = (DropTrigRef*)signal->getDataPtrSend();
19579 
19580   ref->senderRef = reference();
19581   ref->clientData = req->clientData;
19582   ref->transId = req->transId;
19583   ref->tableId = req->tableId;
19584   ref->indexId = req->indexId;
19585   getError(error, ref);
19586 
19587   sendSignal(req->clientRef, GSN_DROP_TRIG_REF, signal,
19588              DropTrigRef::SignalLength, JBB);
19589 }
19590 
19591 // DropTrigger: PARSE
19592 
19593 void
dropTrigger_parse(Signal * signal,bool master,SchemaOpPtr op_ptr,SectionHandle & handle,ErrorInfo & error)19594 Dbdict::dropTrigger_parse(Signal* signal, bool master,
19595                           SchemaOpPtr op_ptr,
19596                           SectionHandle& handle, ErrorInfo& error)
19597 {
19598   D("dropTrigger_parse" << V(op_ptr.i) << *op_ptr.p);
19599 
19600   DropTriggerRecPtr dropTriggerPtr;
19601   getOpRec(op_ptr, dropTriggerPtr);
19602   DropTrigImplReq* impl_req = &dropTriggerPtr.p->m_request;
19603 
19604   bool reqByName = false;
19605   if (handle.m_cnt > 0) { // wl3600_todo use requestType
19606     jam();
19607     ndbrequire(handle.m_cnt == 1);
19608     reqByName = true;
19609   }
19610 
19611   if (reqByName) {
19612     jam();
19613     SegmentedSectionPtr ss_ptr;
19614     handle.getSection(ss_ptr, DropTrigImplReq::TRIGGER_NAME_SECTION);
19615     SimplePropertiesSectionReader r(ss_ptr, getSectionSegmentPool());
19616     DictTabInfo::Table tableDesc;
19617     tableDesc.init();
19618     SimpleProperties::UnpackStatus status =
19619       SimpleProperties::unpack(
19620           r, &tableDesc,
19621           DictTabInfo::TableMapping, DictTabInfo::TableMappingSize,
19622           true, true);
19623 
19624     if (status != SimpleProperties::Eof ||
19625         tableDesc.TableName[0] == 0)
19626     {
19627       jam();
19628       ndbassert(false);
19629       setError(error, DropTrigRef::InvalidName, __LINE__);
19630       return;
19631     }
19632     const Uint32 bytesize = sizeof(dropTriggerPtr.p->m_triggerName);
19633     memcpy(dropTriggerPtr.p->m_triggerName, tableDesc.TableName, bytesize);
19634     D("parsed trigger name: " << dropTriggerPtr.p->m_triggerName);
19635 
19636     // find object by name and link it to operation
19637     DictObjectPtr obj_ptr;
19638     if (!findDictObject(op_ptr, obj_ptr, dropTriggerPtr.p->m_triggerName)) {
19639       jam();
19640       setError(error, DropTrigRef::TriggerNotFound, __LINE__);
19641       return;
19642     }
19643     if (impl_req->triggerId != RNIL &&
19644         impl_req->triggerId != obj_ptr.p->m_id) {
19645       jam();
19646       // inconsistency in request
19647       setError(error, DropTrigRef::TriggerNotFound, __LINE__);
19648       return;
19649     }
19650     impl_req->triggerId = obj_ptr.p->m_id;
19651   }
19652 
19653   // check trigger id from user or via name
19654   TriggerRecordPtr triggerPtr;
19655   {
19656     if (!(impl_req->triggerId < c_triggerRecordPool_.getSize())) {
19657       jam();
19658       setError(error, DropTrigImplRef::TriggerNotFound, __LINE__);
19659       return;
19660     }
19661     bool ok = find_object(triggerPtr, impl_req->triggerId);
19662     if (!ok)
19663     {
19664       jam();
19665       setError(error, DropTrigImplRef::TriggerNotFound, __LINE__);
19666       return;
19667     }
19668     // wl3600_todo state check
19669   }
19670 
19671   D("trigger " << copyRope<MAX_TAB_NAME_SIZE>(triggerPtr.p->triggerName));
19672   impl_req->triggerInfo = triggerPtr.p->triggerInfo;
19673   Uint32 requestType = impl_req->requestType;
19674 
19675   switch(DropTrigReq::getEndpointFlag(requestType)){
19676   case DropTrigReq::MainTrigger:
19677     jam();
19678     dropTriggerPtr.p->m_main_op = true;
19679     break;
19680   case DropTrigReq::TriggerDst:
19681   case DropTrigReq::TriggerSrc:
19682     jam();
19683     if (handle.m_cnt)
19684     {
19685       jam();
19686       ndbassert(false);
19687       setError(error, DropTrigRef::BadRequestType, __LINE__);
19688       return;
19689     }
19690     dropTriggerPtr.p->m_main_op = false;
19691     dropTrigger_parse_endpoint(signal, op_ptr, error);
19692     return;
19693   }
19694 
19695   // connect to object in request by id
19696   if (!reqByName) {
19697     jam();
19698     DictObjectPtr obj_ptr;
19699     if (!findDictObject(op_ptr, obj_ptr, triggerPtr.p->m_obj_ptr_i)) {
19700       jam();
19701       // broken trigger object wl3600_todo bad error code
19702       setError(error, DropTrigRef::TriggerNotFound, __LINE__);
19703       return;
19704     }
19705     ndbrequire(obj_ptr.p->m_id == triggerPtr.p->triggerId);
19706 
19707     // fill in name just to be complete
19708     ConstRope name(c_rope_pool, triggerPtr.p->triggerName);
19709     name.copy(dropTriggerPtr.p->m_triggerName); //wl3600_todo length check
19710   }
19711 
19712   // check the table (must match trigger record)
19713   {
19714     if (impl_req->tableId != triggerPtr.p->tableId) {
19715       jam();
19716       setError(error, DropTrigRef::InvalidTable, __LINE__);
19717       return;
19718     }
19719   }
19720 
19721   // check the index (must match trigger record, maybe both RNIL)
19722   {
19723     if (impl_req->indexId != triggerPtr.p->indexId) {
19724       jam();  // wl3600_todo wrong error code
19725       D("mismatch" << V(impl_req->indexId) << V(triggerPtr.p->indexId));
19726       setError(error, DropTrigRef::InvalidTable, __LINE__);
19727       return;
19728     }
19729   }
19730 
19731   {
19732     TriggerType::Value type =
19733       TriggerInfo::getTriggerType(triggerPtr.p->triggerInfo);
19734     switch(type){
19735     case TriggerType::SECONDARY_INDEX:
19736     case TriggerType::FK_PARENT:
19737     case TriggerType::FK_CHILD:
19738       jam();
19739       dropTriggerPtr.p->m_sub_dst = false;
19740       dropTriggerPtr.p->m_sub_src = false;
19741       break;
19742     case TriggerType::ORDERED_INDEX:
19743     case TriggerType::READ_ONLY_CONSTRAINT:
19744       jam();
19745       dropTriggerPtr.p->m_sub_dst = true; // Only need LQH
19746       dropTriggerPtr.p->m_sub_src = false;
19747       break;
19748     default:
19749     case TriggerType::SUBSCRIPTION:
19750     case TriggerType::SUBSCRIPTION_BEFORE:
19751       ndbassert(false);
19752       setError(error, DropTrigRef::UnsupportedTriggerType, __LINE__);
19753       return;
19754     }
19755   }
19756 
19757   if (ERROR_INSERTED(6124)) {
19758     jam();
19759     CLEAR_ERROR_INSERT_VALUE;
19760     setError(error, 9124, __LINE__);
19761     return;
19762   }
19763 }
19764 
19765 void
dropTrigger_parse_endpoint(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo & error)19766 Dbdict::dropTrigger_parse_endpoint(Signal* signal,
19767 				   SchemaOpPtr op_ptr,
19768 				   ErrorInfo& error)
19769 {
19770   DropTriggerRecPtr dropTriggerPtr;
19771   getOpRec(op_ptr, dropTriggerPtr);
19772   DropTrigImplReq* impl_req = &dropTriggerPtr.p->m_request;
19773 
19774   // check request type
19775   Uint32 requestType = impl_req->requestType;
19776   switch(DropTrigReq::getEndpointFlag(requestType)){
19777   case DropTrigReq::TriggerDst:
19778     jam();
19779     dropTriggerPtr.p->m_block_list[0] = DBTC_REF;
19780     break;
19781   case DropTrigReq::TriggerSrc:
19782     jam();
19783     dropTriggerPtr.p->m_block_list[0] = DBLQH_REF;
19784     break;
19785   default:
19786     ndbassert(false);
19787     setError(error, DropTrigRef::BadRequestType, __LINE__);
19788     return;
19789   }
19790 }
19791 
19792 bool
dropTrigger_subOps(Signal * signal,SchemaOpPtr op_ptr)19793 Dbdict::dropTrigger_subOps(Signal* signal, SchemaOpPtr op_ptr)
19794 {
19795   D("dropTrigger_subOps" << V(op_ptr.i) << *op_ptr.p);
19796 
19797   DropTriggerRecPtr dropTriggerPtr;
19798   getOpRec(op_ptr, dropTriggerPtr);
19799 
19800   Uint32 requestType = dropTriggerPtr.p->m_request.requestType;
19801   switch(DropTrigReq::getEndpointFlag(requestType)){
19802   case DropTrigReq::MainTrigger:
19803     jam();
19804     break;
19805   case DropTrigReq::TriggerDst:
19806   case DropTrigReq::TriggerSrc:
19807     jam();
19808     return false;
19809   }
19810 
19811   /**
19812    * NOTE drop src before dst
19813    */
19814   if (!dropTriggerPtr.p->m_sub_src)
19815   {
19816     jam();
19817     dropTriggerPtr.p->m_sub_src = true;
19818     Callback c = {
19819       safe_cast(&Dbdict::dropTrigger_fromDropEndpoint),
19820       op_ptr.p->op_key
19821     };
19822     op_ptr.p->m_callback = c;
19823     dropTrigger_toDropEndpoint(signal, op_ptr,
19824 			       DropTrigReq::TriggerSrc);
19825     return true;
19826   }
19827 
19828   if (!dropTriggerPtr.p->m_sub_dst)
19829   {
19830     jam();
19831     dropTriggerPtr.p->m_sub_dst = true;
19832     Callback c = {
19833       safe_cast(&Dbdict::dropTrigger_fromDropEndpoint),
19834       op_ptr.p->op_key
19835     };
19836     op_ptr.p->m_callback = c;
19837     dropTrigger_toDropEndpoint(signal, op_ptr,
19838 			       DropTrigReq::TriggerDst);
19839     return true;
19840   }
19841 
19842   return false;
19843 }
19844 
19845 void
dropTrigger_toDropEndpoint(Signal * signal,SchemaOpPtr op_ptr,DropTrigReq::EndpointFlag endpoint)19846 Dbdict::dropTrigger_toDropEndpoint(Signal* signal,
19847 				   SchemaOpPtr op_ptr,
19848 				   DropTrigReq::EndpointFlag endpoint)
19849 {
19850   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
19851   DropTriggerRecPtr dropTriggerPtr;
19852   getOpRec(op_ptr, dropTriggerPtr);
19853   const DropTrigImplReq* impl_req = &dropTriggerPtr.p->m_request;
19854 
19855   DropTrigReq* req = (DropTrigReq*)signal->getDataPtrSend();
19856 
19857   Uint32 requestType = 0;
19858   DropTrigReq::setEndpointFlag(requestType, endpoint);
19859 
19860   Uint32 requestInfo = 0;
19861   DictSignal::setRequestType(requestInfo, requestType);
19862   DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
19863 
19864   req->clientRef = reference();
19865   req->clientData = op_ptr.p->op_key;
19866   req->transId = trans_ptr.p->m_transId;
19867   req->transKey = trans_ptr.p->trans_key;
19868   req->requestInfo = requestInfo;
19869   req->tableId = impl_req->tableId;
19870   req->tableVersion = impl_req->tableVersion;
19871   req->indexId = impl_req->indexId;
19872   req->indexVersion = impl_req->indexVersion;
19873   req->triggerId = impl_req->triggerId;
19874   req->triggerNo = 0;
19875 
19876   sendSignal(reference(), GSN_DROP_TRIG_REQ, signal,
19877              DropTrigReq::SignalLength, JBB);
19878 }
19879 
19880 void
dropTrigger_fromDropEndpoint(Signal * signal,Uint32 op_key,Uint32 ret)19881 Dbdict::dropTrigger_fromDropEndpoint(Signal* signal,
19882 					 Uint32 op_key, Uint32 ret)
19883 {
19884   SchemaOpPtr op_ptr;
19885   DropTriggerRecPtr dropTriggerPtr;
19886   findSchemaOp(op_ptr, dropTriggerPtr, op_key);
19887   ndbrequire(!op_ptr.isNull());
19888   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
19889 
19890   if (ret == 0)
19891   {
19892     jam();
19893     const DropTrigConf* conf =
19894       (const DropTrigConf*)signal->getDataPtr();
19895 
19896     ndbrequire(conf->transId == trans_ptr.p->m_transId);
19897     createSubOps(signal, op_ptr);
19898   }
19899   else
19900   {
19901     jam();
19902     const DropTrigRef* ref =
19903       (const DropTrigRef*)signal->getDataPtr();
19904     ErrorInfo error;
19905     setError(error, ref);
19906     abortSubOps(signal, op_ptr, error);
19907   }
19908 }
19909 
19910 void
dropTrigger_reply(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)19911 Dbdict::dropTrigger_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
19912 {
19913   jam();
19914   SchemaTransPtr& trans_ptr = op_ptr.p->m_trans_ptr;
19915   DropTriggerRecPtr dropTriggerPtr;
19916   getOpRec(op_ptr, dropTriggerPtr);
19917   const DropTrigImplReq* impl_req = &dropTriggerPtr.p->m_request;
19918 
19919   D("dropTrigger_reply" << V(impl_req->triggerId));
19920 
19921   if (!hasError(error)) {
19922     DropTrigConf* conf = (DropTrigConf*)signal->getDataPtrSend();
19923     conf->senderRef = reference();
19924     conf->clientData = op_ptr.p->m_clientData;
19925     conf->transId = trans_ptr.p->m_transId;
19926     conf->tableId = impl_req->tableId;
19927     conf->indexId = impl_req->indexId;
19928     conf->triggerId = impl_req->triggerId;
19929 
19930     Uint32 clientRef = op_ptr.p->m_clientRef;
19931     sendSignal(clientRef, GSN_DROP_TRIG_CONF, signal,
19932                DropTrigConf::SignalLength, JBB);
19933   } else {
19934     jam();
19935     DropTrigRef* ref = (DropTrigRef*)signal->getDataPtrSend();
19936     ref->senderRef = reference();
19937     ref->clientData = op_ptr.p->m_clientData;
19938     ref->transId = trans_ptr.p->m_transId;
19939     ref->tableId = impl_req->tableId;
19940     ref->indexId = impl_req->indexId;
19941     ref->triggerId = impl_req->triggerId;
19942     getError(error, ref);
19943 
19944     Uint32 clientRef = op_ptr.p->m_clientRef;
19945     sendSignal(clientRef, GSN_DROP_TRIG_REF, signal,
19946                DropTrigRef::SignalLength, JBB);
19947   }
19948 }
19949 
19950 // DropTrigger: PREPARE
19951 
19952 void
dropTrigger_prepare(Signal * signal,SchemaOpPtr op_ptr)19953 Dbdict::dropTrigger_prepare(Signal* signal, SchemaOpPtr op_ptr)
19954 {
19955   jam();
19956   D("dropTrigger_prepare");
19957 
19958   /**
19959    * This could check that triggers actually are present
19960    */
19961 
19962   sendTransConf(signal, op_ptr);
19963 }
19964 
19965 // DropTrigger: COMMIT
19966 
19967 void
dropTrigger_commit(Signal * signal,SchemaOpPtr op_ptr)19968 Dbdict::dropTrigger_commit(Signal* signal, SchemaOpPtr op_ptr)
19969 {
19970   jam();
19971   DropTriggerRecPtr dropTriggerPtr;
19972   getOpRec(op_ptr, dropTriggerPtr);
19973 
19974   if (dropTriggerPtr.p->m_main_op)
19975   {
19976     jam();
19977 
19978     Uint32 triggerId = dropTriggerPtr.p->m_request.triggerId;
19979 
19980     TriggerRecordPtr triggerPtr;
19981     bool ok = find_object(triggerPtr, triggerId);
19982     ndbrequire(ok);
19983     if (triggerPtr.p->indexId != RNIL)
19984     {
19985       jam();
19986       TableRecordPtr indexPtr;
19987       bool ok = find_object(indexPtr, triggerPtr.p->indexId);
19988       if (ok)
19989       {
19990         jam();
19991         indexPtr.p->triggerId = RNIL;
19992       }
19993       triggerPtr.p->indexId = RNIL;
19994     }
19995 
19996     // remove trigger
19997     c_triggerRecordPool_.release(triggerPtr);
19998     releaseDictObject(op_ptr);
19999 
20000     sendTransConf(signal, op_ptr);
20001     return;
20002   }
20003 
20004   Callback c =  { safe_cast(&Dbdict::dropTrigger_commit_fromLocal),
20005                   op_ptr.p->op_key
20006   };
20007 
20008   op_ptr.p->m_callback = c;
20009   send_drop_trig_req(signal, op_ptr);
20010 }
20011 
20012 void
dropTrigger_commit_fromLocal(Signal * signal,Uint32 op_key,Uint32 ret)20013 Dbdict::dropTrigger_commit_fromLocal(Signal* signal,
20014                                        Uint32 op_key, Uint32 ret)
20015 {
20016   SchemaOpPtr op_ptr;
20017   DropTriggerRecPtr dropTriggerPtr;
20018   findSchemaOp(op_ptr, dropTriggerPtr, op_key);
20019   ndbrequire(!op_ptr.isNull());
20020 
20021   if (ret)
20022   {
20023     jam();
20024     warningEvent("Got error code %u from %x (DROP_TRIG_IMPL_REQ)",
20025                  ret,
20026                  dropTriggerPtr.p->m_block_list[0]);
20027   }
20028 
20029   sendTransConf(signal, op_ptr);
20030 }
20031 
20032 void
send_drop_trig_req(Signal * signal,SchemaOpPtr op_ptr)20033 Dbdict::send_drop_trig_req(Signal* signal, SchemaOpPtr op_ptr)
20034 {
20035   DropTriggerRecPtr dropTriggerPtr;
20036   getOpRec(op_ptr, dropTriggerPtr);
20037   const DropTrigImplReq* impl_req = &dropTriggerPtr.p->m_request;
20038 
20039   DropTrigImplReq* req = (DropTrigImplReq*)signal->getDataPtrSend();
20040 
20041   req->senderRef = reference();
20042   req->senderData = op_ptr.p->op_key;
20043   req->requestType = impl_req->requestType;
20044   req->tableId = impl_req->tableId;
20045   req->tableVersion = 0; // not used
20046   req->indexId = impl_req->indexId;
20047   req->indexVersion = 0; // not used
20048   req->triggerNo = 0;
20049   req->triggerId = impl_req->triggerId;
20050   req->triggerInfo = impl_req->triggerInfo;
20051   req->receiverRef = impl_req->receiverRef;
20052 
20053   BlockReference ref = dropTriggerPtr.p->m_block_list[0];
20054   sendSignal(ref, GSN_DROP_TRIG_IMPL_REQ, signal,
20055              DropTrigImplReq::SignalLength, JBB);
20056 }
20057 
20058 // DropTrigger: COMPLETE
20059 
20060 void
dropTrigger_complete(Signal * signal,SchemaOpPtr op_ptr)20061 Dbdict::dropTrigger_complete(Signal* signal, SchemaOpPtr op_ptr)
20062 {
20063   jam();
20064   sendTransConf(signal, op_ptr);
20065 }
20066 
20067 // DropTrigger: ABORT
20068 
20069 void
dropTrigger_abortParse(Signal * signal,SchemaOpPtr op_ptr)20070 Dbdict::dropTrigger_abortParse(Signal* signal, SchemaOpPtr op_ptr)
20071 {
20072   DropTriggerRecPtr dropTriggerPtr;
20073   getOpRec(op_ptr, dropTriggerPtr);
20074 
20075   D("dropTrigger_abortParse" << *op_ptr.p);
20076 
20077   if (hasDictObject(op_ptr)) {
20078     jam();
20079     unlinkDictObject(op_ptr);
20080   }
20081   sendTransConf(signal, op_ptr);
20082 }
20083 
20084 void
dropTrigger_abortPrepare(Signal * signal,SchemaOpPtr op_ptr)20085 Dbdict::dropTrigger_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
20086 {
20087   D("dropTrigger_abortPrepare" << *op_ptr.p);
20088 
20089   sendTransConf(signal, op_ptr);
20090 }
20091 
20092 // DropTrigger: MISC
20093 
20094 void
execDROP_TRIG_CONF(Signal * signal)20095 Dbdict::execDROP_TRIG_CONF(Signal* signal)
20096 {
20097   jamEntry();
20098   const DropTrigConf* conf = (const DropTrigConf*)signal->getDataPtr();
20099   handleDictConf(signal, conf);
20100 }
20101 
20102 void
execDROP_TRIG_REF(Signal * signal)20103 Dbdict::execDROP_TRIG_REF(Signal* signal)
20104 {
20105   jamEntry();
20106   const DropTrigRef* ref = (const DropTrigRef*)signal->getDataPtr();
20107   handleDictRef(signal, ref);
20108 }
20109 
20110 void
execDROP_TRIG_IMPL_CONF(Signal * signal)20111 Dbdict::execDROP_TRIG_IMPL_CONF(Signal* signal)
20112 {
20113   jamEntry();
20114   const DropTrigImplConf* conf = (const DropTrigImplConf*)signal->getDataPtr();
20115   ndbrequire(refToNode(conf->senderRef) == getOwnNodeId());
20116   handleDictConf(signal, conf);
20117 }
20118 
20119 void
execDROP_TRIG_IMPL_REF(Signal * signal)20120 Dbdict::execDROP_TRIG_IMPL_REF(Signal* signal)
20121 {
20122   jamEntry();
20123   const DropTrigImplRef* ref = (const DropTrigImplRef*)signal->getDataPtr();
20124   ndbrequire(refToNode(ref->senderRef) == getOwnNodeId());
20125   handleDictRef(signal, ref);
20126 }
20127 
20128 // DropTrigger: END
20129 
20130 
20131 /**
20132  * MODULE: Support routines for index and trigger.
20133  */
20134 
20135 /*
20136   This routine is used to set-up the primary key attributes of the unique
20137   hash index. Since we store fragment id as part of the primary key here
20138   we insert the pseudo column for getting fragment id first in the array.
20139   This routine is used as part of the building of the index.
20140 */
20141 
20142 void
getTableKeyList(TableRecordPtr tablePtr,Id_array<MAX_ATTRIBUTES_IN_INDEX+1> & list)20143 Dbdict::getTableKeyList(TableRecordPtr tablePtr,
20144 			Id_array<MAX_ATTRIBUTES_IN_INDEX+1>& list)
20145 {
20146   jam();
20147   list.sz = 0;
20148   list.id[list.sz++] = AttributeHeader::FRAGMENT;
20149   LocalAttributeRecord_list alist(c_attributeRecordPool,
20150                                          tablePtr.p->m_attributes);
20151   AttributeRecordPtr attrPtr;
20152   for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr)) {
20153     if (attrPtr.p->tupleKey) {
20154       list.id[list.sz++] = attrPtr.p->attributeId;
20155     }
20156   }
20157   ndbrequire(list.sz == (uint)(tablePtr.p->noOfPrimkey + 1));
20158   ndbrequire(list.sz <= MAX_ATTRIBUTES_IN_INDEX + 1);
20159 }
20160 
20161 // XXX should store the primary attribute id
20162 void
getIndexAttr(TableRecordPtr indexPtr,Uint32 itAttr,Uint32 * id)20163 Dbdict::getIndexAttr(TableRecordPtr indexPtr, Uint32 itAttr, Uint32* id)
20164 {
20165   jam();
20166 
20167   Uint32 len;
20168   char name[MAX_ATTR_NAME_SIZE];
20169   TableRecordPtr tablePtr;
20170   AttributeRecordPtr attrPtr;
20171 
20172   bool ok = find_object(tablePtr, indexPtr.p->primaryTableId);
20173   ndbrequire(ok);
20174   AttributeRecord* iaRec = c_attributeRecordPool.getPtr(itAttr);
20175   {
20176     ConstRope tmp(c_rope_pool, iaRec->attributeName);
20177     tmp.copy(name);
20178     len = tmp.size();
20179   }
20180   LocalAttributeRecord_list alist(c_attributeRecordPool,
20181 					 tablePtr.p->m_attributes);
20182   for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr)){
20183     ConstRope tmp(c_rope_pool, attrPtr.p->attributeName);
20184     if(tmp.compare(name, len) == 0){
20185       id[0] = attrPtr.p->attributeId;
20186       return;
20187     }
20188   }
20189   ndbrequire(false);
20190 }
20191 
20192 void
getIndexAttrList(TableRecordPtr indexPtr,IndexAttributeList & list)20193 Dbdict::getIndexAttrList(TableRecordPtr indexPtr, IndexAttributeList& list)
20194 {
20195   jam();
20196   list.sz = 0;
20197   memset(list.id, 0, sizeof(list.id));
20198 
20199   LocalAttributeRecord_list alist(c_attributeRecordPool,
20200                                   indexPtr.p->m_attributes);
20201   AttributeRecordPtr attrPtr;
20202   if (indexPtr.p->isIndex())
20203   {
20204     jam();
20205     ndbrequire(indexPtr.p->noOfAttributes >= 2);
20206     for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr))
20207     {
20208       // skip last
20209       AttributeRecordPtr tempPtr = attrPtr;
20210       if (! alist.next(tempPtr))
20211         break;
20212       /**
20213        * Post-increment moved out of original expression &list.id[list.sz++]
20214        * due to Intel compiler bug on ia64 (BUG#34208).
20215        */
20216       getIndexAttr(indexPtr, attrPtr.i, &list.id[list.sz]);
20217       list.sz++;
20218     }
20219     ndbrequire(indexPtr.p->noOfAttributes == list.sz + 1);
20220   }
20221   else
20222   {
20223     jam();
20224     for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr))
20225     {
20226       if (attrPtr.p->tupleKey)
20227       {
20228         jam();
20229         list.id[list.sz] = attrPtr.p->attributeId;
20230         /**
20231          * Post-increment moved out of original expression &list.id[list.sz++]
20232          * due to Intel compiler bug on ia64 (BUG#34208).
20233          */
20234         list.sz++;
20235       }
20236     }
20237     ndbrequire(indexPtr.p->noOfPrimkey == list.sz);
20238   }
20239 }
20240 
20241 void
getIndexAttrMask(TableRecordPtr indexPtr,AttributeMask & mask)20242 Dbdict::getIndexAttrMask(TableRecordPtr indexPtr, AttributeMask& mask)
20243 {
20244   jam();
20245   mask.clear();
20246   ndbrequire(indexPtr.p->noOfAttributes >= 2);
20247 
20248   AttributeRecordPtr attrPtr, currPtr;
20249   LocalAttributeRecord_list alist(c_attributeRecordPool,
20250 					 indexPtr.p->m_attributes);
20251 
20252 
20253   for (alist.first(attrPtr); currPtr = attrPtr, alist.next(attrPtr); ){
20254     Uint32 id;
20255     getIndexAttr(indexPtr, currPtr.i, &id);
20256     mask.set(id);
20257   }
20258 }
20259 
20260 // DICT lock master
20261 
20262 const Dbdict::DictLockType*
getDictLockType(Uint32 lockType)20263 Dbdict::getDictLockType(Uint32 lockType)
20264 {
20265   static const DictLockType lt[] = {
20266     { DictLockReq::NodeRestartLock, "NodeRestart" }
20267     ,{ DictLockReq::SchemaTransLock, "SchemaTransLock" }
20268     ,{ DictLockReq::CreateFileLock,  "CreateFile" }
20269     ,{ DictLockReq::CreateFilegroupLock, "CreateFilegroup" }
20270     ,{ DictLockReq::DropFileLock,    "DropFile" }
20271     ,{ DictLockReq::DropFilegroupLock, "DropFilegroup" }
20272   };
20273   for (unsigned int i = 0; i < sizeof(lt)/sizeof(lt[0]); i++) {
20274     if ((Uint32) lt[i].lockType == lockType)
20275       return &lt[i];
20276   }
20277   return NULL;
20278 }
20279 
20280 void
debugLockInfo(Signal * signal,const char * text,Uint32 rc)20281 Dbdict::debugLockInfo(Signal* signal,
20282                       const char* text,
20283                       Uint32 rc)
20284 {
20285   if (!g_trace)
20286     return;
20287 
20288   static const char* rctext = "Unknown result";
20289 
20290   switch(rc)
20291   {
20292   case UtilLockRef::OK:
20293     rctext = "Success";
20294     break;
20295   case UtilLockRef::NoSuchLock:
20296     rctext = "No such lock";
20297     break;
20298   case UtilLockRef::OutOfLockRecords:
20299     rctext = "Out of records";
20300     break;
20301   case UtilLockRef::DistributedLockNotSupported:
20302     rctext = "Distributed lock not supported";
20303     break;
20304   case UtilLockRef::LockAlreadyHeld:
20305     rctext = "Already held";
20306     break;
20307   case UtilLockRef::InLockQueue:
20308     rctext = "Queued";
20309     break;
20310     /* try returns these... */
20311   case SchemaTransBeginRef::Busy:
20312     rctext = "SchemaTransBeginRef::Busy";
20313     break;
20314   case SchemaTransBeginRef::BusyWithNR:
20315     rctext = "SchemaTransBeginRef::BusyWithNR";
20316     break;
20317   default:
20318     break;
20319   }
20320 
20321   infoEvent("DICT : %s %u %s",
20322             text,
20323             rc,
20324             rctext);
20325 }
20326 
20327 void
sendDictLockInfoEvent(Signal *,const UtilLockReq * req,const char * text)20328 Dbdict::sendDictLockInfoEvent(Signal*, const UtilLockReq* req, const char* text)
20329 {
20330   const Dbdict::DictLockType* lt = getDictLockType(req->extra);
20331 
20332   infoEvent("DICT: %s %u for %s",
20333             text,
20334             (unsigned)refToNode(req->senderRef), lt->text);
20335 }
20336 
20337 void
execDICT_LOCK_REQ(Signal * signal)20338 Dbdict::execDICT_LOCK_REQ(Signal* signal)
20339 {
20340   jamEntry();
20341   const DictLockReq req = *(DictLockReq*)&signal->theData[0];
20342 
20343   UtilLockReq lockReq;
20344   lockReq.senderRef = req.userRef;
20345   lockReq.senderData = req.userPtr;
20346   lockReq.lockId = 0;
20347   lockReq.requestInfo = 0;
20348   lockReq.extra = req.lockType;
20349 
20350   const DictLockType* lt = getDictLockType(req.lockType);
20351 
20352   Uint32 err;
20353   if (req.lockType == DictLockReq::SumaStartMe ||
20354       req.lockType == DictLockReq::SumaHandOver)
20355   {
20356     jam();
20357 
20358     if (c_outstanding_sub_startstop)
20359     {
20360       jam();
20361       g_eventLogger->info("refing dict lock to %u", refToNode(req.userRef));
20362       err = DictLockRef::TooManyRequests;
20363       goto ref;
20364     }
20365 
20366     if (req.lockType == DictLockReq::SumaHandOver &&
20367         !c_sub_startstop_lock.isclear())
20368     {
20369       g_eventLogger->info("refing dict lock to %u", refToNode(req.userRef));
20370       err = DictLockRef::TooManyRequests;
20371       goto ref;
20372     }
20373 
20374     c_sub_startstop_lock.set(refToNode(req.userRef));
20375 
20376     g_eventLogger->info("granting SumaStartMe dict lock to %u", refToNode(req.userRef));
20377     DictLockConf* conf = (DictLockConf*)signal->getDataPtrSend();
20378     conf->userPtr = req.userPtr;
20379     conf->lockType = req.lockType;
20380     conf->lockPtr = 0;
20381     sendSignal(req.userRef, GSN_DICT_LOCK_CONF, signal,
20382                DictLockConf::SignalLength, JBB);
20383     return;
20384   }
20385 
20386   if (req.lockType == DictLockReq::NodeRestartLock)
20387   {
20388     jam();
20389     lockReq.requestInfo |= UtilLockReq::SharedLock;
20390   }
20391 
20392   // make sure bad request crashes slave, not master (us)
20393   Uint32 res;
20394   if (getOwnNodeId() != c_masterNodeId)
20395   {
20396     jam();
20397     err = DictLockRef::NotMaster;
20398     goto ref;
20399   }
20400 
20401   if (lt == NULL)
20402   {
20403     jam();
20404     err = DictLockRef::InvalidLockType;
20405     goto ref;
20406   }
20407 
20408   if (req.userRef != signal->getSendersBlockRef() ||
20409       getNodeInfo(refToNode(req.userRef)).m_type != NodeInfo::DB)
20410   {
20411     jam();
20412     err = DictLockRef::BadUserRef;
20413     goto ref;
20414   }
20415 
20416   if (c_aliveNodes.get(refToNode(req.userRef)))
20417   {
20418     jam();
20419     err = DictLockRef::TooLate;
20420     goto ref;
20421   }
20422 
20423   res = m_dict_lock.lock(this, m_dict_lock_pool, &lockReq, 0);
20424   debugLockInfo(signal,
20425                 "DICT_LOCK_REQ lock",
20426                 res);
20427   switch(res){
20428   case 0:
20429     jam();
20430     sendDictLockInfoEvent(signal, &lockReq, "locked by node");
20431     goto conf;
20432     break;
20433   case UtilLockRef::OutOfLockRecords:
20434     jam();
20435     err = DictLockRef::TooManyRequests;
20436     goto ref;
20437     break;
20438   default:
20439     jam();
20440     sendDictLockInfoEvent(signal, &lockReq, "lock request by node queued");
20441     m_dict_lock.dump_queue(m_dict_lock_pool, this);
20442     break;
20443   }
20444   return;
20445 
20446 ref:
20447   {
20448     DictLockRef* ref = (DictLockRef*)signal->getDataPtrSend();
20449     ref->userPtr = lockReq.senderData;
20450     ref->lockType = lockReq.extra;
20451     ref->errorCode = err;
20452 
20453     sendSignal(lockReq.senderRef, GSN_DICT_LOCK_REF, signal,
20454                DictLockRef::SignalLength, JBB);
20455   }
20456   return;
20457 
20458 conf:
20459   {
20460     DictLockConf* conf = (DictLockConf*)signal->getDataPtrSend();
20461 
20462     conf->userPtr = lockReq.senderData;
20463     conf->lockType = lockReq.extra;
20464     conf->lockPtr = lockReq.senderData;
20465 
20466     sendSignal(lockReq.senderRef, GSN_DICT_LOCK_CONF, signal,
20467                DictLockConf::SignalLength, JBB);
20468   }
20469   return;
20470 }
20471 
20472 void
execDICT_UNLOCK_ORD(Signal * signal)20473 Dbdict::execDICT_UNLOCK_ORD(Signal* signal)
20474 {
20475   jamEntry();
20476   const DictUnlockOrd* ord = (const DictUnlockOrd*)&signal->theData[0];
20477 
20478   DictLockReq req;
20479   req.userPtr = ord->senderData;
20480   req.userRef = ord->senderRef;
20481 
20482   if (signal->getLength() < DictUnlockOrd::SignalLength)
20483   {
20484     jam();
20485     req.userPtr = ord->lockPtr;
20486     req.userRef = signal->getSendersBlockRef();
20487   }
20488 
20489   if (ord->lockType == DictLockReq::SumaStartMe ||
20490       ord->lockType == DictLockReq::SumaHandOver)
20491   {
20492     Uint32 nodeId = refToNode(ord->senderRef);
20493     jam();
20494     g_eventLogger->info("clearing SumaStartMe dict lock for %u", nodeId);
20495     c_sub_startstop_lock.clear(nodeId);
20496 
20497     if (ord->lockType == DictLockReq::SumaHandOver)
20498     {
20499       /**
20500        * Inform the master DIH that the SUMA handover is now completed, this
20501        * is the very last phase of the node recovery. This code is only
20502        * executed in the master node.
20503        */
20504       SumaHandoverCompleteRep *rep =
20505         (SumaHandoverCompleteRep*)signal->getDataPtrSend();
20506       rep->nodeId = nodeId;
20507       EXECUTE_DIRECT(DBDIH, GSN_SUMA_HANDOVER_COMPLETE_REP, signal,
20508                      SumaHandoverCompleteRep::SignalLength);
20509     }
20510     return;
20511   }
20512 
20513   UtilLockReq lockReq;
20514   lockReq.senderData = req.userPtr;
20515   lockReq.senderRef = req.userRef;
20516   DictLockReq::LockType lockType = DictLockReq::NodeRestartLock;
20517   Uint32 res = dict_lock_unlock(signal, &req, &lockType);
20518   debugLockInfo(signal,
20519                 "DICT_UNLOCK_ORD unlock",
20520                 res);
20521   lockReq.extra = lockType;
20522   switch(res){
20523   case UtilUnlockRef::OK:
20524     jam();
20525     sendDictLockInfoEvent(signal, &lockReq, "unlocked by node");
20526     return;
20527   case UtilUnlockRef::NotLockOwner:
20528     jam();
20529     sendDictLockInfoEvent(signal, &lockReq, "lock request removed by node");
20530     return;
20531   default:
20532     ndbassert(false);
20533   }
20534 }
20535 
20536 // Master take-over
20537 
20538 void
execDICT_TAKEOVER_REQ(Signal * signal)20539 Dbdict::execDICT_TAKEOVER_REQ(Signal* signal)
20540  {
20541    jamEntry();
20542 
20543    if (!checkNodeFailSequence(signal))
20544    {
20545      jam();
20546      return;
20547    }
20548 
20549    DictTakeoverReq* req = (DictTakeoverReq*)signal->getDataPtr();
20550    Uint32 masterRef = req->senderRef;
20551    Uint32 op_count = 0;
20552    Uint32 rollforward_op = 0;
20553    Uint32 rollforward_op_state = SchemaOp::OS_COMPLETED;
20554    Uint32 rollback_op = 0;
20555    Uint32 rollback_op_state = SchemaOp::OS_INITIAL;
20556    Uint32 lowest_op = 0;
20557    Uint32 lowest_op_state = SchemaOp::OS_COMPLETED;
20558    Uint32 lowest_op_impl_req_gsn = 0;
20559    Uint32 highest_op = 0;
20560    Uint32 highest_op_state = SchemaOp::OS_INITIAL;
20561    Uint32 highest_op_impl_req_gsn = 0;
20562    SchemaTransPtr trans_ptr;
20563    bool ending = false;
20564 
20565    jam();
20566    bool pending_trans = c_schemaTransList.first(trans_ptr);
20567    if (!pending_trans)
20568    {
20569      /*
20570        Slave has no pending transaction
20571      */
20572      jam();
20573      DictTakeoverRef* ref = (DictTakeoverRef*)signal->getDataPtrSend();
20574      ref->senderRef = reference();
20575      ref->masterRef = masterRef;
20576      ref->errorCode = DictTakeoverRef::NoTransaction;
20577      sendSignal(masterRef, GSN_DICT_TAKEOVER_REF, signal,
20578                 DictTakeoverRef::SignalLength, JBB);
20579      return;
20580    }
20581    while (pending_trans)
20582    {
20583      trans_ptr.p->m_masterRef = masterRef;
20584 #ifdef VM_TRACE
20585       ndbout_c("Dbdict::execDICT_TAKEOVER_REQ: trans %u(0x%8x), state %u, op_list %s", trans_ptr.i, (uint)trans_ptr.p->trans_key, trans_ptr.p->m_state, (trans_ptr.p->m_op_list.in_use)?"yes":"no");
20586 #endif
20587 
20588      SchemaOpPtr op_ptr;
20589      LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
20590      bool pending_op = list.first(op_ptr);
20591      if (pending_op &&
20592          (trans_ptr.p->m_state == SchemaTrans::TS_COMPLETING ||
20593           trans_ptr.p->m_state == SchemaTrans::TS_ENDING))
20594      {
20595        jam();
20596        /*
20597          We were ending (releasing) operations, check how
20598          far slave got by finding lowest operation.
20599        */
20600        ending = true;
20601        lowest_op = op_ptr.p->op_key;
20602        lowest_op_state = op_ptr.p->m_state;
20603        /*
20604          Find the OpInfo gsn for the next operation to
20605          be removed,
20606          this might be needed by new master to create missing operation.
20607        */
20608        lowest_op_impl_req_gsn = getOpInfo(op_ptr).m_impl_req_gsn;
20609      }
20610      while (pending_op)
20611      {
20612        jam();
20613        op_count++;
20614        ndbrequire(!op_ptr.isNull());
20615        ndbrequire(trans_ptr.i == op_ptr.p->m_trans_ptr.i);
20616 #ifdef VM_TRACE
20617        ndbout_c("Dbdict::execDICT_TAKEOVER_REQ: op %u state %u", op_ptr.p->op_key, op_ptr.p->m_state);
20618 #endif
20619 
20620        /*
20621          Check if operation is busy
20622        */
20623        switch(op_ptr.p->m_state) {
20624        case SchemaOp::OS_PARSING:
20625        case SchemaOp::OS_PREPARING:
20626        case SchemaOp::OS_ABORTING_PREPARE:
20627        case SchemaOp::OS_ABORTING_PARSE:
20628        case SchemaOp::OS_COMMITTING:
20629        case SchemaOp::OS_COMPLETING:
20630        {
20631          /**
20632           * Wait 100ms and check again. This delay is there to save CPU cycles
20633           * and to avoid filling the jam trace buffer.
20634           */
20635          jam();
20636          Uint32* data = &signal->theData[0];
20637          memmove(&data[1], &data[0], DictTakeoverReq::SignalLength << 2);
20638          data[0] = ZDICT_TAKEOVER_REQ;
20639          sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
20640                              100, 1 + DictTakeoverReq::SignalLength);
20641          return;
20642        }
20643        default:
20644          break;
20645        }
20646        if (ending)
20647        {
20648          pending_op = list.next(op_ptr);
20649          continue;
20650        }
20651        if (trans_ptr.p->m_state == SchemaTrans::TS_STARTED || // master
20652            trans_ptr.p->m_state == SchemaTrans::TS_PARSING)
20653        {
20654          jam();
20655          /*
20656            We were parsing operations from client, check how
20657            far slave got by finding highest operation.
20658          */
20659          highest_op = op_ptr.p->op_key;
20660          highest_op_state = op_ptr.p->m_state;
20661          /*
20662            Find the OpInfo gsn for the latest created operation,
20663            this might be needed by new master to create missing operation.
20664          */
20665          highest_op_impl_req_gsn = getOpInfo(op_ptr).m_impl_req_gsn;
20666        }
20667        else
20668        {
20669          jam();
20670 #ifdef VM_TRACE
20671          ndbout_c("Op %u, state %u, rollforward %u/%u, rollback %u/%u",op_ptr.p->op_key,op_ptr.p->m_state, rollforward_op,  rollforward_op_state, rollback_op,  rollback_op_state);
20672 #endif
20673          /*
20674            Find the starting point for a roll forward, the first
20675            operation found with a lower state than the previous.
20676          */
20677          if (SchemaOp::weight(op_ptr.p->m_state) <
20678              SchemaOp::weight(rollforward_op_state))
20679          {
20680            rollforward_op = op_ptr.p->op_key;
20681            rollforward_op_state = op_ptr.p->m_state;
20682          }
20683          /*
20684            Find the starting point for a rollback, the last
20685            operation found that changed state.
20686          */
20687          if (SchemaOp::weight(op_ptr.p->m_state) >=
20688              SchemaOp::weight(rollback_op_state))
20689          {
20690            rollback_op = op_ptr.p->op_key;
20691            rollback_op_state = op_ptr.p->m_state;
20692          }
20693        }
20694        pending_op = list.next(op_ptr);
20695      }
20696 #ifdef VM_TRACE
20697      ndbout_c("Slave transaction %u has %u schema operations, rf %u/%u, rb %u/%u", trans_ptr.p->trans_key, op_count, rollforward_op, rollforward_op_state, rollback_op, rollback_op_state);
20698 #endif
20699      DictTakeoverConf* conf = (DictTakeoverConf*)signal->getDataPtrSend();
20700      conf->senderRef = reference();
20701      conf->clientRef = trans_ptr.p->m_clientRef;
20702      conf->trans_key = trans_ptr.p->trans_key;
20703      conf->trans_state = trans_ptr.p->m_state;
20704      conf->op_count = op_count;
20705      conf->rollforward_op = rollforward_op;
20706      conf->rollforward_op_state = rollforward_op_state;
20707      conf->rollback_op = rollback_op;
20708      conf->rollback_op_state = rollback_op_state;
20709      if (trans_ptr.p->m_state == SchemaTrans::TS_STARTED ||
20710          trans_ptr.p->m_state == SchemaTrans::TS_PARSING)
20711      {
20712        /*
20713          New master might not have parsed highest found operation yet.
20714         */
20715        conf->highest_op = highest_op;
20716        conf->highest_op_state = highest_op_state;
20717        conf->highest_op_impl_req_gsn = highest_op_impl_req_gsn;
20718      }
20719      if (ending)
20720      {
20721        /*
20722          New master might already have released lowest operation found.
20723         */
20724        conf->lowest_op = lowest_op;
20725        conf->lowest_op_state = lowest_op_state;
20726        conf->lowest_op_impl_req_gsn = lowest_op_impl_req_gsn;
20727      }
20728      sendSignal(masterRef, GSN_DICT_TAKEOVER_CONF, signal,
20729                 DictTakeoverConf::SignalLength, JBB);
20730      ndbrequire(!(pending_trans = c_schemaTransList.next(trans_ptr)));
20731    }
20732  }
20733 
20734 void
execDICT_TAKEOVER_REF(Signal * signal)20735 Dbdict::execDICT_TAKEOVER_REF(Signal* signal)
20736 {
20737   DictTakeoverRef* ref = (DictTakeoverRef*)signal->getDataPtr();
20738   Uint32 senderRef = ref->senderRef;
20739   Uint32 nodeId = refToNode(senderRef);
20740   NodeRecordPtr masterNodePtr;
20741   jamEntry();
20742 #ifdef VM_TRACE
20743   ndbout_c("Dbdict::execDICT_TAKEOVER_REF: error %u, from %u",
20744            ref->errorCode,
20745            nodeId);
20746 #endif
20747   /*
20748     Slave has died (didn't reply) or doesn't not have any transaction
20749     Ignore it during rest of master takeover.
20750   */
20751   ndbassert(refToNode(ref->masterRef) == c_masterNodeId);
20752   c_nodes.getPtr(masterNodePtr, c_masterNodeId);
20753   masterNodePtr.p->m_nodes.clear(nodeId);
20754   /*
20755     Check if we got replies from all nodes
20756   */
20757   {
20758     SafeCounter sc(c_counterMgr, masterNodePtr.p->m_counter);
20759     if (!sc.clearWaitingFor(nodeId)) {
20760       jam();
20761       return;
20762     }
20763   }
20764   c_takeOverInProgress = false;
20765   check_takeover_replies(signal);
20766 }
20767 
20768 void
execDICT_TAKEOVER_CONF(Signal * signal)20769 Dbdict::execDICT_TAKEOVER_CONF(Signal* signal)
20770 {
20771   jamEntry();
20772   DictTakeoverConf* conf = (DictTakeoverConf*)signal->getDataPtr();
20773   jamEntry();
20774   Uint32 senderRef = conf->senderRef;
20775   Uint32 nodeId = refToNode(senderRef);
20776   //Uint32 clientRef = conf->clientRef;
20777   //Uint32 op_count = conf->op_count;
20778   //Uint32 trans_key = conf->trans_key;
20779   //Uint32 rollforward_op = conf->rollforward_op;
20780   //Uint32 rollforward_op_state = conf->rollforward_op_state;
20781   //Uint32 rollback_op = conf->rollback_op;
20782   //Uint32 rollback_op_state = conf->rollback_op_state;
20783   NodeRecordPtr masterNodePtr;
20784 
20785   /*
20786     Accumulate all responses
20787   */
20788   NodeRecordPtr nodePtr;
20789   c_nodes.getPtr(nodePtr, nodeId);
20790   nodePtr.p->takeOverConf = *conf;
20791 
20792   ndbassert(getOwnNodeId() == c_masterNodeId);
20793   c_nodes.getPtr(masterNodePtr, c_masterNodeId);
20794 #ifdef VM_TRACE
20795   ndbout_c("execDICT_TAKEOVER_CONF: Node %u, trans %u(%u), count %u, rollf %u/%u, rb %u/%u",
20796            nodeId, conf->trans_key, conf->trans_state, conf->op_count, conf->rollforward_op,
20797            conf->rollforward_op_state, conf->rollback_op, conf->rollback_op_state);
20798 #endif
20799 
20800   /*
20801     Check that we got reply from all nodes
20802   */
20803   {
20804     SafeCounter sc(c_counterMgr, masterNodePtr.p->m_counter);
20805     if (!sc.clearWaitingFor(nodeId)) {
20806       jam();
20807       return;
20808     }
20809   }
20810   c_takeOverInProgress = false;
20811   check_takeover_replies(signal);
20812 }
20813 
check_takeover_replies(Signal * signal)20814 void Dbdict::check_takeover_replies(Signal* signal)
20815 {
20816   SchemaTransPtr trans_ptr;
20817   NodeRecordPtr masterNodePtr;
20818   ErrorInfo error;
20819 
20820   c_nodes.getPtr(masterNodePtr, c_masterNodeId); // this node
20821   if (masterNodePtr.p->m_nodes.isclear())
20822   {
20823     /*
20824       No slave found any pending transactions, we are done
20825      */
20826     jam();
20827     send_nf_complete_rep(signal, &masterNodePtr.p->nodeFailRep);
20828     return;
20829   }
20830   /*
20831     Take schema trans lock.
20832     Set initial values for rollforward/rollback points
20833     and highest/lowest transaction states
20834    */
20835   bool pending_trans = c_schemaTransList.first(trans_ptr);
20836   while (pending_trans) {
20837     jam();
20838     Uint32 trans_key = trans_ptr.p->trans_key;
20839     DictLockReq& lockReq = trans_ptr.p->m_lockReq;
20840     lockReq.userPtr = trans_key;
20841     lockReq.userRef = reference();
20842     lockReq.lockType = DictLockReq::SchemaTransLock;
20843     int lockError = dict_lock_trylock(&lockReq);
20844     debugLockInfo(signal,
20845                   "check_takeover_replies trylock 1",
20846                   lockError);
20847     if (lockError != 0)
20848     {
20849       jam();
20850 #ifdef VM_TRACE
20851       ndbout_c("New master failed locking transaction %u, error %u", trans_key, lockError);
20852 #endif
20853       ndbassert(false);
20854     }
20855     else
20856     {
20857       jam();
20858 #ifdef VM_TRACE
20859       ndbout_c("New master locked transaction %u", trans_key);
20860 #endif
20861     }
20862     trans_ptr.p->m_isMaster = true;
20863     trans_ptr.p->m_nodes.clear();
20864     trans_ptr.p->m_rollforward_op = -1;
20865     trans_ptr.p->m_rollforward_op_state = SchemaOp::OS_COMPLETED;
20866     trans_ptr.p->m_rollback_op = 0;
20867     trans_ptr.p->m_rollback_op_state = SchemaOp::OS_INITIAL;
20868     trans_ptr.p->m_lowest_trans_state = SchemaTrans::TS_ENDING;
20869     trans_ptr.p->m_highest_trans_state = SchemaTrans::TS_INITIAL;
20870     trans_ptr.p->check_partial_rollforward = false;
20871     trans_ptr.p->ressurected_op = false;
20872     pending_trans = c_schemaTransList.next(trans_ptr);
20873   }
20874   /*
20875     Find rollforward/rollback operations and highest/lowest transaction state
20876    */
20877   for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
20878     jam();
20879     NodeRecordPtr nodePtr;
20880     if (masterNodePtr.p->m_nodes.get(i))
20881     {
20882       jam();
20883       c_nodes.getPtr(nodePtr, i);
20884       {
20885 	DictTakeoverConf* conf = &nodePtr.p->takeOverConf;
20886         Uint32 clientRef = conf->clientRef;
20887 	Uint32 rollforward_op = conf->rollforward_op;
20888 	Uint32 rollforward_op_state = conf->rollforward_op_state;
20889 	Uint32 rollback_op = conf->highest_op;
20890 	Uint32 rollback_op_state = conf->rollback_op_state;
20891         Uint32 trans_key = conf->trans_key;
20892         Uint32 trans_state = conf->trans_state;
20893         SchemaTransPtr trans_ptr;
20894 
20895         if (!findSchemaTrans(trans_ptr, trans_key))
20896         {
20897           jam();
20898           /*
20899             New master doesn't know about the transaction.
20900           */
20901           if (!seizeSchemaTrans(trans_ptr, trans_key))
20902           {
20903             jam();
20904             ndbassert(false);
20905           }
20906 #ifdef VM_TRACE
20907           ndbout_c("New master seized transaction %u", trans_key);
20908 #endif
20909           /*
20910             Take schema trans lock.
20911           */
20912           DictLockReq& lockReq = trans_ptr.p->m_lockReq;
20913           lockReq.userPtr = trans_ptr.p->trans_key;
20914           lockReq.userRef = reference();
20915           lockReq.lockType = DictLockReq::SchemaTransLock;
20916           int lockError = dict_lock_trylock(&lockReq);
20917           debugLockInfo(signal,
20918                         "check_takeover_replies trylock 2",
20919                         lockError);
20920           if (lockError != 0)
20921           {
20922             jam();
20923 #ifdef VM_TRACE
20924             ndbout_c("New master failed locking transaction %u, error %u", trans_key, lockError);
20925 #endif
20926             ndbassert(false);
20927           }
20928           else
20929           {
20930             jam();
20931 #ifdef VM_TRACE
20932             ndbout_c("New master locked transaction %u", trans_key);
20933 #endif
20934           }
20935           trans_ptr.p->m_nodes.clear();
20936           trans_ptr.p->m_rollforward_op = -1;
20937           trans_ptr.p->m_rollforward_op_state = SchemaOp::OS_COMPLETED;
20938           trans_ptr.p->m_rollback_op = 0;
20939           trans_ptr.p->m_rollback_op_state = SchemaOp::OS_INITIAL;
20940           trans_ptr.p->m_lowest_trans_state = SchemaTrans::TS_ENDING;
20941           trans_ptr.p->m_highest_trans_state = SchemaTrans::TS_INITIAL;
20942           trans_ptr.p->check_partial_rollforward = false;
20943           trans_ptr.p->ressurected_op = false;
20944         }
20945 
20946         trans_ptr.p->m_isMaster = true;
20947         trans_ptr.p->m_masterRef = reference();
20948         trans_ptr.p->m_clientRef = clientRef;
20949         trans_ptr.p->m_nodes.set(i);
20950 #ifdef VM_TRACE
20951         ndbout_c("Adding node %u to transaction %u", i, trans_ptr.p->trans_key);
20952 #endif
20953         /*
20954           Save the operation with lowest state and lowest key
20955           for roll forward
20956          */
20957         if ((SchemaOp::weight(rollforward_op_state) <
20958              SchemaOp::weight(trans_ptr.p->m_rollforward_op_state)) ||
20959             ((rollforward_op_state ==
20960               trans_ptr.p->m_rollforward_op_state &&
20961               rollforward_op < trans_ptr.p->m_rollforward_op)))
20962 	{
20963           jam();
20964 	  trans_ptr.p->m_rollforward_op = rollforward_op;
20965 	  trans_ptr.p->m_rollforward_op_state = rollforward_op_state;
20966 	}
20967 
20968         /*
20969           Save operation with the highest state and the highest key
20970           for rollback
20971          */
20972         if ((SchemaOp::weight(rollback_op_state) >
20973              SchemaOp::weight(trans_ptr.p->m_rollback_op_state)) ||
20974             ((rollback_op_state ==
20975               trans_ptr.p->m_rollback_op_state &&
20976               rollback_op > trans_ptr.p->m_rollback_op)))
20977 	{
20978           jam();
20979 	  trans_ptr.p->m_rollback_op = rollback_op;
20980 	  trans_ptr.p->m_rollback_op_state = rollback_op_state;
20981 	}
20982 
20983         if (SchemaTrans::weight(trans_state) <
20984             SchemaTrans::weight(trans_ptr.p->m_lowest_trans_state))
20985         {
20986           jam();
20987           trans_ptr.p->m_lowest_trans_state = trans_state;
20988         }
20989         if (SchemaTrans::weight(trans_state) >
20990             SchemaTrans::weight(trans_ptr.p->m_highest_trans_state))
20991         {
20992           jam();
20993           trans_ptr.p->m_highest_trans_state = trans_state;
20994         }
20995       }
20996     }
20997   }
20998 
20999   /*
21000     Check the progress of transactions.
21001   */
21002   pending_trans = c_schemaTransList.first(trans_ptr);
21003   while (pending_trans)
21004   {
21005     jam();
21006 #ifdef VM_TRACE
21007     ndbout_c("Analyzing transaction progress, trans %u/%u, lowest/highest %u/%u", trans_ptr.p->trans_key, trans_ptr.p->m_state, trans_ptr.p->m_lowest_trans_state, trans_ptr.p->m_highest_trans_state);
21008 #endif
21009     switch(trans_ptr.p->m_highest_trans_state) {
21010     case SchemaTrans::TS_INITIAL:
21011     case SchemaTrans::TS_STARTING:
21012     case SchemaTrans::TS_STARTED:
21013     case SchemaTrans::TS_PARSING:
21014     case SchemaTrans::TS_SUBOP:
21015     case SchemaTrans::TS_ROLLBACK_SP:
21016     case SchemaTrans::TS_FLUSH_PREPARE:
21017     case SchemaTrans::TS_PREPARING:
21018     case SchemaTrans::TS_ABORTING_PREPARE:
21019     case SchemaTrans::TS_ABORTING_PARSE:
21020       jam();
21021       trans_ptr.p->m_master_recovery_state = SchemaTrans::TRS_ROLLBACK;
21022       break;
21023     case SchemaTrans::TS_FLUSH_COMMIT:
21024     case SchemaTrans::TS_COMMITTING:
21025     case SchemaTrans::TS_FLUSH_COMPLETE:
21026     case SchemaTrans::TS_COMPLETING:
21027     case SchemaTrans::TS_ENDING:
21028       jam();
21029       trans_ptr.p->m_master_recovery_state = SchemaTrans::TRS_ROLLFORWARD;
21030       break;
21031     }
21032 
21033     if (trans_ptr.p->m_master_recovery_state == SchemaTrans::TRS_ROLLFORWARD)
21034     {
21035       /*
21036         We must start rolling forward from lowest state of any slave
21037         and partially skip more progressed slaves.
21038        */
21039       jam();
21040       infoEvent("Pending schema transaction %u will be rolled forward", trans_ptr.p->trans_key);
21041       trans_ptr.p->check_partial_rollforward = true;
21042       trans_ptr.p->m_state = trans_ptr.p->m_lowest_trans_state;
21043 #ifdef VM_TRACE
21044       ndbout_c("Setting transaction state to %u for rollforward", trans_ptr.p->m_state);
21045 #endif
21046     }
21047     else
21048     {
21049       /*
21050         We must start rolling back from highest state of any slave
21051         and partially skip less progressed slaves.
21052        */
21053       jam();
21054       infoEvent("Pending schema transaction %u will be rolled back", trans_ptr.p->trans_key);
21055       trans_ptr.p->m_state = trans_ptr.p->m_highest_trans_state;
21056 #ifdef VM_TRACE
21057       ndbout_c("Setting transaction state to %u for rollback", trans_ptr.p->m_state);
21058 #endif
21059     }
21060 #ifdef VM_TRACE
21061     ndbout_c("Setting start state for transaction %u to %u", trans_ptr.p->trans_key, trans_ptr.p->m_state);
21062 #endif
21063     pending_trans = c_schemaTransList.next(trans_ptr);
21064   }
21065 
21066   /*
21067      Initialize all node recovery states
21068   */
21069   for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
21070     jam();
21071     NodeRecordPtr nodePtr;
21072     c_nodes.getPtr(nodePtr, i);
21073     nodePtr.p->recoveryState = NodeRecord::RS_NORMAL;
21074   }
21075 
21076   pending_trans = c_schemaTransList.first(trans_ptr);
21077   while (pending_trans)
21078   {
21079     /*
21080       Find nodes that need partial rollforward/rollback,
21081       create any missing operations on new master
21082     */
21083 
21084     for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
21085       jam();
21086       NodeRecordPtr nodePtr;
21087       if (trans_ptr.p->m_nodes.get(i))
21088       {
21089         jam();
21090         c_nodes.getPtr(nodePtr, i);
21091 #ifdef VM_TRACE
21092         ndbout_c("Node %u had %u operations, master has %u",i , nodePtr.p->takeOverConf.op_count, masterNodePtr.p->takeOverConf.op_count);
21093 #endif
21094 
21095         /** BEWARE:
21096          * 'takeOverConf' is not valid if a node replied TAKEOVER_REF,
21097          * in that case node was cleared from 'masterNodePtr.p->m_nodes'.
21098          */
21099         ndbassert(masterNodePtr.p->m_nodes.get(i));
21100         if (nodePtr.p->takeOverConf.op_count == 0)
21101         {
21102           if (SchemaTrans::weight(trans_ptr.p->m_state)
21103               < SchemaTrans::weight(SchemaTrans::TS_PREPARING))
21104           {
21105             /*
21106               Node didn't parse any operations,
21107               remove, skip it when aborting parse.
21108             */
21109             jam();
21110 #ifdef VM_TRACE
21111             ndbout_c("Node %u had no operations for  transaction %u, ignore it when aborting", i, trans_ptr.p->trans_key);
21112 #endif
21113             nodePtr.p->start_op = 0;
21114             nodePtr.p->start_op_state = SchemaOp::OS_PARSED;
21115           }
21116           else
21117           {
21118             /*
21119               Node is ended
21120             */
21121             jam();
21122             // Is this possible??
21123           }
21124         }
21125         else if (!masterNodePtr.p->m_nodes.get(c_masterNodeId) ||
21126                  nodePtr.p->takeOverConf.op_count >
21127                  masterNodePtr.p->takeOverConf.op_count)
21128         {
21129           /*
21130             Operation missing on new master
21131            */
21132           jam();
21133           if (SchemaTrans::weight(trans_ptr.p->m_state)
21134               < SchemaTrans::weight(SchemaTrans::TS_PREPARING))
21135           {
21136             /*
21137               Last parsed operation is missing on new master
21138              */
21139             jam();
21140             if (masterNodePtr.p->recoveryState !=
21141                 NodeRecord::RS_PARTIAL_ROLLBACK)
21142             {
21143               /*
21144                 We haven't decided to partially rollback master yet.
21145                 Operation is missing on new master (not yet parsed).
21146                 Create it so new master can tell slaves to abort it,
21147                 but skip it on master.
21148               */
21149               jam();
21150               SchemaOpPtr missing_op_ptr;
21151               const OpInfo& info =
21152                 *findOpInfo(nodePtr.p->takeOverConf.highest_op_impl_req_gsn);
21153               if (seizeSchemaOp(trans_ptr,
21154                                 missing_op_ptr,
21155                                 nodePtr.p->takeOverConf.highest_op,
21156                                 info))
21157               {
21158                 jam();
21159 #ifdef VM_TRACE
21160                 ndbout_c("Created missing operation %u, on new master", missing_op_ptr.p->op_key);
21161 #endif
21162                 ndbassert(masterNodePtr.p->m_nodes.get(c_masterNodeId));
21163                 missing_op_ptr.p->m_state = nodePtr.p->takeOverConf.highest_op_state;
21164                 masterNodePtr.p->recoveryState = NodeRecord::RS_PARTIAL_ROLLBACK;
21165                 masterNodePtr.p->start_op = masterNodePtr.p->takeOverConf.highest_op;
21166                 masterNodePtr.p->start_op_state = masterNodePtr.p->takeOverConf.highest_op_state;
21167               }
21168               else
21169               {
21170                 jam();
21171                 ndbassert(false);
21172               }
21173               trans_ptr.p->m_nodes.set(c_masterNodeId);
21174 #ifdef VM_TRACE
21175               ndbout_c("Adding master node %u to transaction %u", c_masterNodeId, trans_ptr.p->trans_key);
21176 #endif
21177             }
21178           }
21179           else if (SchemaTrans::weight(trans_ptr.p->m_state)
21180                    >= SchemaTrans::weight(SchemaTrans::TS_PREPARING) &&
21181                    (!trans_ptr.p->ressurected_op))
21182           {
21183             /*
21184               New master has already ended some operation,
21185               create it again so we can tell slaves to end it.
21186               Note: we don't add node to transaction since the
21187               ressurected operation cannot be completed. Instead
21188               we need to release it explicitly when transaction is
21189               ended.
21190             */
21191             jam();
21192             SchemaOpPtr missing_op_ptr;
21193             Uint32 op_key = nodePtr.p->takeOverConf.lowest_op;
21194             Uint32 op_state = nodePtr.p->takeOverConf.lowest_op_state;
21195             const OpInfo& info =
21196               *findOpInfo(nodePtr.p->takeOverConf.lowest_op_impl_req_gsn);
21197             if (seizeSchemaOp(trans_ptr,
21198                               missing_op_ptr,
21199                               op_key,
21200                               info))
21201             {
21202               jam();
21203 #ifdef VM_TRACE
21204               ndbout_c("Created ressurected operation %u, on new master", op_key);
21205 #endif
21206               trans_ptr.p->ressurected_op = true;
21207               missing_op_ptr.p->m_state = op_state;
21208               nodePtr.p->recoveryState = NodeRecord::RS_PARTIAL_ROLLFORWARD;
21209               nodePtr.p->start_op = op_key;
21210               nodePtr.p->start_op_state = op_state;
21211 
21212             }
21213             else
21214             {
21215               jam();
21216               assert(false);
21217             }
21218             continue;
21219           }
21220         }
21221         else if (nodePtr.p->takeOverConf.op_count <
21222                  masterNodePtr.p->takeOverConf.op_count)
21223         {
21224           jam();
21225           ndbassert(masterNodePtr.p->m_nodes.get(c_masterNodeId));
21226 
21227           /*
21228               Operation is missing on slave
21229           */
21230           if (SchemaTrans::weight(trans_ptr.p->m_state) <
21231               SchemaTrans::weight(SchemaTrans::TS_PREPARING))
21232           {
21233             /*
21234               Last parsed operation is missing on slave, skip it
21235               when aborting parse.
21236             */
21237             jam();
21238 #ifdef VM_TRACE
21239             ndbout_c("Node %u did not have all operations for transaction %u, skip > %u", i, trans_ptr.p->trans_key, nodePtr.p->takeOverConf.highest_op);
21240 #endif
21241             nodePtr.p->recoveryState = NodeRecord::RS_PARTIAL_ROLLBACK;
21242             nodePtr.p->start_op = nodePtr.p->takeOverConf.highest_op;
21243             nodePtr.p->start_op_state = nodePtr.p->takeOverConf.highest_op_state;
21244           }
21245           else
21246           {
21247             /*
21248               Slave has already ended some operations
21249             */
21250             jam();
21251 #ifdef VM_TRACE
21252             ndbout_c("Node %u did not have all operations for transaction %u, skip < %u", i, trans_ptr.p->trans_key, nodePtr.p->takeOverConf.lowest_op);
21253 #endif
21254             nodePtr.p->recoveryState = NodeRecord::RS_PARTIAL_ROLLFORWARD;
21255             nodePtr.p->start_op = nodePtr.p->takeOverConf.lowest_op;
21256             nodePtr.p->start_op_state = nodePtr.p->takeOverConf.lowest_op_state;
21257           }
21258         }
21259       }
21260     }
21261 
21262     /*
21263       Compare node progress
21264     */
21265     for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
21266       jam();
21267       NodeRecordPtr nodePtr;
21268       if (trans_ptr.p->m_nodes.get(i))
21269       {
21270         jam();
21271         c_nodes.getPtr(nodePtr, i);
21272 #ifdef VM_TRACE
21273         ndbout_c("Comparing node %u rollforward(%u(%u)<%u(%u))/rollback(%u(%u)<%u(%u))", i, nodePtr.p->takeOverConf.rollforward_op_state, nodePtr.p->takeOverConf.rollforward_op, trans_ptr.p->m_rollforward_op_state, trans_ptr.p->m_rollforward_op, nodePtr.p->takeOverConf.rollback_op_state, nodePtr.p->takeOverConf.rollback_op, trans_ptr.p->m_rollback_op_state, trans_ptr.p->m_rollback_op);
21274 #endif
21275         if (trans_ptr.p->m_master_recovery_state == SchemaTrans::TRS_ROLLFORWARD)
21276         {
21277           jam();
21278           if (trans_ptr.p->m_lowest_trans_state == SchemaTrans::TS_PREPARING &&
21279               nodePtr.p->takeOverConf.trans_state == SchemaTrans::TS_COMMITTING)
21280           {
21281             /*
21282               Some slave have flushed the commit start, but not all.
21283               Flushed slaves need to be partially rolled forward.
21284              */
21285             jam();
21286             nodePtr.p->recoveryState = NodeRecord::RS_PARTIAL_ROLLFORWARD;
21287 #ifdef VM_TRACE
21288             ndbout_c("Node %u will be partially rolled forward, skipping RT_FLUSH_COMMIT", nodePtr.i);
21289 #endif
21290           }
21291           else if (SchemaOp::weight(nodePtr.p->takeOverConf.rollforward_op_state) >
21292                    SchemaOp::weight(trans_ptr.p->m_rollforward_op_state) ||
21293                    nodePtr.p->takeOverConf.rollforward_op >
21294                    trans_ptr.p->m_rollforward_op)
21295           {
21296             /*
21297               Slave has started committing, but other slaves have non-committed
21298               operations. Node needs to be partially rollforward.
21299             */
21300             jam();
21301             nodePtr.p->recoveryState = NodeRecord::RS_PARTIAL_ROLLFORWARD;
21302             nodePtr.p->start_op = nodePtr.p->takeOverConf.rollforward_op;
21303             nodePtr.p->start_op_state = nodePtr.p->takeOverConf.rollforward_op_state;
21304 #ifdef VM_TRACE
21305             ndbout_c("Node %u will be partially rolled forward to operation %u, state %u", nodePtr.i, nodePtr.p->start_op, nodePtr.p->start_op_state);
21306 #endif
21307             if (i == c_masterNodeId)
21308             {
21309               /*
21310                 New master is ahead of other slaves
21311                 Change operation state back to rollforward
21312                 other slaves.
21313                */
21314               jam();
21315               SchemaOpPtr op_ptr;
21316               ndbrequire(findSchemaOp(op_ptr,
21317                                       trans_ptr.p->m_rollforward_op));
21318 #ifdef VM_TRACE
21319               ndbout_c("Changed op %u from state %u to %u", trans_ptr.p->m_rollforward_op, op_ptr.p->m_state, trans_ptr.p->m_rollforward_op_state);
21320 #endif
21321               op_ptr.p->m_state = trans_ptr.p->m_rollforward_op_state;
21322             }
21323           }
21324           else if (trans_ptr.p->m_lowest_trans_state == SchemaTrans::TS_COMMITTING &&
21325                    nodePtr.p->takeOverConf.trans_state >= SchemaTrans::TS_FLUSH_COMPLETE)
21326           {
21327             /*
21328               Some slave have flushed the commit complete, but not all.
21329               Flushed slaves need to be partially rolled forward.
21330             */
21331             jam();
21332             nodePtr.p->recoveryState = NodeRecord::RS_PARTIAL_ROLLFORWARD;
21333 #ifdef VM_TRACE
21334             ndbout_c("Node %u will be partially rolled forward, skipping RT_FLUSH_COMPLETE", nodePtr.i);
21335 #endif
21336           }
21337         }
21338         else // if (trans_ptr.p->m_master_recovery_state == SchemaTrans::TRS_ROLLBACK)
21339         {
21340           jam();
21341           if (SchemaOp::weight(nodePtr.p->takeOverConf.rollback_op_state) <
21342               SchemaOp::weight(trans_ptr.p->m_rollback_op_state) ||
21343               nodePtr.p->takeOverConf.rollback_op <
21344               trans_ptr.p->m_rollback_op)
21345           {
21346             /*
21347               Slave is behind. Other nodes have further
21348               progress, or has already started aborting.
21349               Node needs to be partially rolled back.
21350             */
21351             jam();
21352             nodePtr.p->recoveryState = NodeRecord::RS_PARTIAL_ROLLBACK;
21353             nodePtr.p->start_op = nodePtr.p->takeOverConf.rollback_op;
21354             nodePtr.p->start_op_state = nodePtr.p->takeOverConf.rollback_op_state;
21355 #ifdef VM_TRACE
21356             ndbout_c("Node %u will be partially rolled back from operation %u, state %u", nodePtr.i, nodePtr.p->start_op, nodePtr.p->start_op_state);
21357 #endif
21358             if (i == c_masterNodeId &&
21359                 (SchemaTrans::weight(trans_ptr.p->m_state) <=
21360                  SchemaTrans::weight(SchemaTrans::TS_PREPARING)))
21361             {
21362               /*
21363                 New master is behind of other slaves
21364                 Change operation state forward to rollback
21365                 other slaves.
21366                */
21367               jam();
21368               SchemaOpPtr op_ptr;
21369               ndbrequire(findSchemaOp(op_ptr,
21370                                       trans_ptr.p->m_rollback_op));
21371 #ifdef VM_TRACE
21372               ndbout_c("Changed op %u from state %u to %u", trans_ptr.p->m_rollback_op, op_ptr.p->m_state, trans_ptr.p->m_rollback_op_state);
21373 #endif
21374               op_ptr.p->m_state = trans_ptr.p->m_rollback_op_state;
21375             }
21376           }
21377         }
21378       }
21379     }
21380     /*
21381       Set current op to the lowest/highest reported by slaves
21382       depending on if decision is to rollforward/rollback.
21383     */
21384     if (trans_ptr.p->m_master_recovery_state == SchemaTrans::TRS_ROLLFORWARD)
21385     {
21386       jam();
21387       SchemaOpPtr rollforward_op_ptr;
21388       ndbrequire(findSchemaOp(rollforward_op_ptr, trans_ptr.p->m_rollforward_op));
21389       trans_ptr.p->m_curr_op_ptr_i = rollforward_op_ptr.i;
21390 #ifdef VM_TRACE
21391       ndbout_c("execDICT_TAKEOVER_CONF: Transaction %u rolled forward starting at %u(%u)", trans_ptr.p->trans_key,  trans_ptr.p->m_rollforward_op, trans_ptr.p->m_curr_op_ptr_i);
21392 #endif
21393     }
21394     else // if (trans_ptr.p->master_recovery_state == SchemaTrans::TRS_ROLLBACK)
21395     {
21396       jam();
21397       if (trans_ptr.p->m_state >= SchemaTrans::TS_PARSING)
21398       {
21399         /*
21400           Some slave had at least started parsing operations
21401          */
21402         jam();
21403         SchemaOpPtr rollback_op_ptr;
21404         ndbrequire(findSchemaOp(rollback_op_ptr, trans_ptr.p->m_rollback_op));
21405         trans_ptr.p->m_curr_op_ptr_i = rollback_op_ptr.i;
21406 #ifdef VM_TRACE
21407         ndbout_c("execDICT_TAKEOVER_CONF: Transaction %u rolled back starting at %u(%u)", trans_ptr.p->trans_key,  trans_ptr.p->m_rollback_op, trans_ptr.p->m_curr_op_ptr_i);
21408 #endif
21409       }
21410     }
21411 
21412     trans_recover(signal, trans_ptr);
21413     pending_trans = c_schemaTransList.next(trans_ptr);
21414   }
21415 }
21416 
21417 
21418 // NF handling
21419 
21420 void
removeStaleDictLocks(Signal * signal,const Uint32 * theFailedNodes)21421 Dbdict::removeStaleDictLocks(Signal* signal, const Uint32* theFailedNodes)
21422 {
21423   LockQueue::Iterator iter;
21424   if (m_dict_lock.first(this, m_dict_lock_pool, iter))
21425   {
21426 #ifdef MARTIN
21427     infoEvent("Iterating lock queue");
21428 #endif
21429     do {
21430       if (NodeBitmask::get(theFailedNodes,
21431                            refToNode(iter.m_curr.p->m_req.senderRef)))
21432       {
21433         if (iter.m_curr.p->m_req.requestInfo & UtilLockReq::Granted)
21434         {
21435           jam();
21436           infoEvent("Removed lock for node %u", refToNode(iter.m_curr.p->m_req.senderRef));
21437           sendDictLockInfoEvent(signal, &iter.m_curr.p->m_req,
21438                                 "remove lock by failed node");
21439         }
21440         else
21441         {
21442           jam();
21443           infoEvent("Removed lock request for node %u", refToNode(iter.m_curr.p->m_req.senderRef));
21444           sendDictLockInfoEvent(signal, &iter.m_curr.p->m_req,
21445                                 "remove lock request by failed node");
21446         }
21447         DictUnlockOrd* ord = (DictUnlockOrd*)signal->getDataPtrSend();
21448         ord->senderRef = iter.m_curr.p->m_req.senderRef;
21449         ord->senderData = iter.m_curr.p->m_req.senderData;
21450         ord->lockPtr = iter.m_curr.p->m_req.senderData;
21451         ord->lockType = iter.m_curr.p->m_req.extra;
21452         sendSignal(reference(), GSN_DICT_UNLOCK_ORD, signal,
21453                    DictUnlockOrd::SignalLength, JBB);
21454       }
21455     } while (m_dict_lock.next(iter));
21456   }
21457 }
21458 
21459 Uint32
dict_lock_trylock(const DictLockReq * _req)21460 Dbdict::dict_lock_trylock(const DictLockReq* _req)
21461 {
21462   UtilLockReq req;
21463   const UtilLockReq *lockOwner;
21464   req.senderData = _req->userPtr;
21465   req.senderRef = _req->userRef;
21466   req.extra = _req->lockType;
21467   req.requestInfo = UtilLockReq::TryLock | UtilLockReq::Notify;
21468 
21469   Uint32 res = m_dict_lock.lock(this, m_dict_lock_pool, &req, &lockOwner);
21470   switch(res){
21471   case UtilLockRef::OK:
21472     jam();
21473     return 0;
21474   case UtilLockRef::LockAlreadyHeld:
21475     jam();
21476     if (lockOwner->extra == DictLockReq::NodeRestartLock)
21477     {
21478       jam();
21479       return SchemaTransBeginRef::BusyWithNR;
21480     }
21481     break;
21482   case UtilLockRef::OutOfLockRecords:
21483     jam();
21484     break;
21485   case UtilLockRef::InLockQueue:
21486     jam();
21487     /**
21488      * Should not happen with trylock
21489      */
21490     ndbassert(false);
21491     break;
21492   }
21493 #ifdef MARTIN
21494   infoEvent("Busy with schema transaction");
21495 #endif
21496   if (g_trace)
21497     m_dict_lock.dump_queue(m_dict_lock_pool, this);
21498 
21499   return SchemaTransBeginRef::Busy;
21500 }
21501 
21502 Uint32
dict_lock_unlock(Signal * signal,const DictLockReq * _req,DictLockReq::LockType * type)21503 Dbdict::dict_lock_unlock(Signal* signal, const DictLockReq* _req,
21504                          DictLockReq::LockType* type)
21505 {
21506   UtilUnlockReq req;
21507   req.senderData = _req->userPtr;
21508   req.senderRef = _req->userRef;
21509 
21510   UtilLockReq lockReq;
21511   Uint32 res = m_dict_lock.unlock(this, m_dict_lock_pool, &req,
21512                                   &lockReq);
21513   switch(res){
21514   case UtilUnlockRef::OK:
21515     if (type)
21516     {
21517       *type = (DictLockReq::LockType) lockReq.extra;
21518     }
21519     /* Fall through */
21520   case UtilUnlockRef::NotLockOwner:
21521     break;
21522   case UtilUnlockRef::NotInLockQueue:
21523     ndbassert(false);
21524     return res;
21525   }
21526 
21527   LockQueue::Iterator iter;
21528   if (m_dict_lock.first(this, m_dict_lock_pool, iter))
21529   {
21530     int res;
21531     while ((res = m_dict_lock.checkLockGrant(iter, &lockReq)) > 0)
21532     {
21533       jam();
21534       /**
21535        *
21536        */
21537       if (res == 2)
21538       {
21539         jam();
21540         DictLockConf* conf = (DictLockConf*)signal->getDataPtrSend();
21541         conf->userPtr = lockReq.senderData;
21542         conf->lockPtr = lockReq.senderData;
21543         conf->lockType = lockReq.extra;
21544         sendSignal(lockReq.senderRef, GSN_DICT_LOCK_CONF, signal,
21545                    DictLockConf::SignalLength, JBB);
21546 
21547         sendDictLockInfoEvent(signal, &lockReq,
21548                               "queued lock request granted for node");
21549       }
21550 
21551       if (!m_dict_lock.next(iter))
21552         break;
21553     }
21554   }
21555 
21556   return res;
21557 }
21558 
21559 void
execBACKUP_LOCK_TAB_REQ(Signal * signal)21560 Dbdict::execBACKUP_LOCK_TAB_REQ(Signal* signal)
21561 {
21562   jamEntry();
21563   BackupLockTab *req = (BackupLockTab *)signal->getDataPtrSend();
21564   Uint32 senderRef = req->m_senderRef;
21565   Uint32 tableId = req->m_tableId;
21566   Uint32 lock = req->m_lock_unlock;
21567 
21568   TableRecordPtr tablePtr;
21569   bool ok = find_object(tablePtr, tableId);
21570   Uint32 err = 0;
21571   if (!ok)
21572   {
21573     jam();
21574     err = GetTabInfoRef::InvalidTableId;
21575   }
21576   else if(lock == BackupLockTab::LOCK_TABLE)
21577   {
21578     jam();
21579     if ((err = check_write_obj(tableId)) == 0)
21580     {
21581       jam();
21582       tablePtr.p->m_read_locked = 1;
21583     }
21584   }
21585   else
21586   {
21587     jam();
21588     tablePtr.p->m_read_locked = 0;
21589   }
21590 
21591   req->errorCode = err;
21592   sendSignal(senderRef, GSN_BACKUP_LOCK_TAB_CONF, signal,
21593              BackupLockTab::SignalLength, JBB);
21594 }
21595 
21596 /* **************************************************************** */
21597 /* ---------------------------------------------------------------- */
21598 /* MODULE:          STORE/RESTORE SCHEMA FILE---------------------- */
21599 /* ---------------------------------------------------------------- */
21600 /*                                                                  */
21601 /* General module used to store the schema file on disk and         */
21602 /* similar function to restore it from disk.                        */
21603 /* ---------------------------------------------------------------- */
21604 /* **************************************************************** */
21605 
21606 void
initSchemaFile(XSchemaFile * xsf,Uint32 firstPage,Uint32 lastPage,bool initEntries)21607 Dbdict::initSchemaFile(XSchemaFile * xsf, Uint32 firstPage, Uint32 lastPage,
21608                        bool initEntries)
21609 {
21610   ndbrequire(lastPage <= xsf->noOfPages);
21611   for (Uint32 n = firstPage; n < lastPage; n++) {
21612     SchemaFile * sf = &xsf->schemaPage[n];
21613     if (initEntries)
21614       memset(sf, 0, NDB_SF_PAGE_SIZE);
21615 
21616     Uint32 ndb_version = NDB_VERSION;
21617     if (ndb_version < NDB_SF_VERSION_5_0_6)
21618       ndb_version = NDB_SF_VERSION_5_0_6;
21619 
21620     memcpy(sf->Magic, NDB_SF_MAGIC, sizeof(sf->Magic));
21621     sf->ByteOrder = 0x12345678;
21622     sf->NdbVersion =  ndb_version;
21623     sf->FileSize = xsf->noOfPages * NDB_SF_PAGE_SIZE;
21624     sf->PageNumber = n;
21625     sf->CheckSum = 0;
21626     sf->NoOfTableEntries = NDB_SF_PAGE_ENTRIES;
21627 
21628     computeChecksum(xsf, n);
21629   }
21630 }
21631 
21632 void
resizeSchemaFile(XSchemaFile * xsf,Uint32 noOfPages)21633 Dbdict::resizeSchemaFile(XSchemaFile * xsf, Uint32 noOfPages)
21634 {
21635   ndbrequire(noOfPages <= NDB_SF_MAX_PAGES);
21636   if (xsf->noOfPages < noOfPages) {
21637     jam();
21638     Uint32 firstPage = xsf->noOfPages;
21639     xsf->noOfPages = noOfPages;
21640     initSchemaFile(xsf, 0, firstPage, false);
21641     initSchemaFile(xsf, firstPage, xsf->noOfPages, true);
21642   }
21643   if (xsf->noOfPages > noOfPages) {
21644     jam();
21645     Uint32 tableId = noOfPages * NDB_SF_PAGE_ENTRIES;
21646     while (tableId < xsf->noOfPages * NDB_SF_PAGE_ENTRIES) {
21647       SchemaFile::TableEntry * te = getTableEntry(xsf, tableId);
21648       if (te->m_tableState != SchemaFile::SF_UNUSED)
21649       {
21650         ndbrequire(false);
21651       }
21652       tableId++;
21653     }
21654     xsf->noOfPages = noOfPages;
21655     initSchemaFile(xsf, 0, xsf->noOfPages, false);
21656   }
21657 }
21658 
21659 void
modifySchemaFileAtRestart(XSchemaFile * xsf)21660 Dbdict::modifySchemaFileAtRestart(XSchemaFile * xsf)
21661 {
21662   D("modifySchemaFileAtRestart" << V(c_at_restart_skip_indexes) << V(c_at_restart_skip_fks));
21663   const Uint32 noOfEntries = xsf->noOfPages * NDB_SF_PAGE_ENTRIES;
21664   for (Uint32 i = 0; i < noOfEntries; i++)
21665   {
21666     SchemaFile::TableEntry * entry = getTableEntry(xsf, i);
21667     bool zap = false;
21668     if (c_at_restart_skip_indexes)
21669       if (entry->m_tableType == DictTabInfo::UniqueHashIndex ||
21670           entry->m_tableType == DictTabInfo::OrderedIndex ||
21671           entry->m_tableType == DictTabInfo::ForeignKey)
21672         zap = true;
21673     if (c_at_restart_skip_fks)
21674       if (entry->m_tableType == DictTabInfo::ForeignKey)
21675         zap = true;
21676     if (zap)
21677     {
21678       D("zap entry " << i << " " << *entry);
21679       entry->init();
21680     }
21681   }
21682   for (Uint32 n = 0; n < xsf->noOfPages; n++)
21683     computeChecksum(xsf, n);
21684 }
21685 
21686 void
computeChecksum(XSchemaFile * xsf,Uint32 pageNo)21687 Dbdict::computeChecksum(XSchemaFile * xsf, Uint32 pageNo){
21688   SchemaFile * sf = &xsf->schemaPage[pageNo];
21689   sf->CheckSum = 0;
21690   sf->CheckSum = computeChecksum((Uint32*)sf, NDB_SF_PAGE_SIZE_IN_WORDS);
21691 }
21692 
21693 bool
validateChecksum(const XSchemaFile * xsf)21694 Dbdict::validateChecksum(const XSchemaFile * xsf){
21695 
21696   for (Uint32 n = 0; n < xsf->noOfPages; n++) {
21697     SchemaFile * sf = &xsf->schemaPage[n];
21698     Uint32 c = computeChecksum((Uint32*)sf, NDB_SF_PAGE_SIZE_IN_WORDS);
21699     if ( c != 0)
21700       return false;
21701   }
21702   return true;
21703 }
21704 
21705 Uint32
computeChecksum(const Uint32 * src,Uint32 len)21706 Dbdict::computeChecksum(const Uint32 * src, Uint32 len){
21707   return computeXorChecksum(src,len);
21708 }
21709 
21710 SchemaFile::TableEntry *
getTableEntry(Uint32 tableId)21711 Dbdict::getTableEntry(Uint32 tableId)
21712 {
21713   return getTableEntry(&c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE], tableId);
21714 }
21715 
21716 SchemaFile::TableEntry *
getTableEntry(XSchemaFile * xsf,Uint32 tableId)21717 Dbdict::getTableEntry(XSchemaFile * xsf, Uint32 tableId)
21718 {
21719   Uint32 n = tableId / NDB_SF_PAGE_ENTRIES;
21720   Uint32 i = tableId % NDB_SF_PAGE_ENTRIES;
21721   ndbrequire(n < xsf->noOfPages);
21722 
21723   SchemaFile * sf = &xsf->schemaPage[n];
21724   return &sf->TableEntries[i];
21725 }
21726 
21727 const SchemaFile::TableEntry *
getTableEntry(const XSchemaFile * xsf,Uint32 tableId)21728 Dbdict::getTableEntry(const XSchemaFile * xsf, Uint32 tableId)
21729 {
21730   Uint32 n = tableId / NDB_SF_PAGE_ENTRIES;
21731   Uint32 i = tableId % NDB_SF_PAGE_ENTRIES;
21732   ndbrequire(n < xsf->noOfPages);
21733 
21734   SchemaFile * sf = &xsf->schemaPage[n];
21735   return &sf->TableEntries[i];
21736 }
21737 
21738 //******************************************
21739 
21740 // MODULE: CreateFile
21741 
21742 const Dbdict::OpInfo
21743 Dbdict::CreateFileRec::g_opInfo = {
21744   { 'C', 'F', 'l', 0 },
21745   ~RT_DBDICT_CREATE_FILE,
21746   GSN_CREATE_FILE_IMPL_REQ,
21747   CreateFileImplReq::SignalLength,
21748   //
21749   &Dbdict::createFile_seize,
21750   &Dbdict::createFile_release,
21751   //
21752   &Dbdict::createFile_parse,
21753   &Dbdict::createFile_subOps,
21754   &Dbdict::createFile_reply,
21755   //
21756   &Dbdict::createFile_prepare,
21757   &Dbdict::createFile_commit,
21758   &Dbdict::createFile_complete,
21759   //
21760   &Dbdict::createFile_abortParse,
21761   &Dbdict::createFile_abortPrepare
21762 };
21763 
21764 void
execCREATE_FILE_REQ(Signal * signal)21765 Dbdict::execCREATE_FILE_REQ(Signal* signal)
21766 {
21767   jamEntry();
21768   if (!assembleFragments(signal)) {
21769     jam();
21770     return;
21771   }
21772   SectionHandle handle(this, signal);
21773 
21774   const CreateFileReq req_copy =
21775     *(const CreateFileReq*)signal->getDataPtr();
21776   const CreateFileReq* req = &req_copy;
21777 
21778   ErrorInfo error;
21779   do {
21780     SchemaOpPtr op_ptr;
21781     CreateFileRecPtr createFilePtr;
21782     CreateFileImplReq* impl_req;
21783 
21784     startClientReq(op_ptr, createFilePtr, req, impl_req, error);
21785     if (hasError(error)) {
21786       jam();
21787       break;
21788     }
21789 
21790     impl_req->file_id = RNIL;
21791     impl_req->file_version = 0;
21792     impl_req->requestInfo = CreateFileImplReq::Create;
21793     if (req->requestInfo & CreateFileReq::ForceCreateFile)
21794     {
21795       jam();
21796       impl_req->requestInfo = CreateFileImplReq::CreateForce;
21797     }
21798 
21799     handleClientReq(signal, op_ptr, handle);
21800     return;
21801   } while (0);
21802 
21803   releaseSections(handle);
21804 
21805   CreateFileRef* ref = (CreateFileRef*)signal->getDataPtrSend();
21806   ref->senderRef = reference();
21807   ref->transId = req->transId;
21808   ref->senderData = req->senderData;
21809   getError(error, ref);
21810 
21811   sendSignal(req->senderRef, GSN_CREATE_FILE_REF, signal,
21812 	     CreateFileRef::SignalLength, JBB);
21813 }
21814 
21815 bool
createFile_seize(SchemaOpPtr op_ptr)21816 Dbdict::createFile_seize(SchemaOpPtr op_ptr)
21817 {
21818   return seizeOpRec<CreateFileRec>(op_ptr);
21819 }
21820 
21821 void
createFile_release(SchemaOpPtr op_ptr)21822 Dbdict::createFile_release(SchemaOpPtr op_ptr)
21823 {
21824   releaseOpRec<CreateFileRec>(op_ptr);
21825 }
21826 
21827 // CreateFile: PARSE
21828 
21829 void
createFile_parse(Signal * signal,bool master,SchemaOpPtr op_ptr,SectionHandle & handle,ErrorInfo & error)21830 Dbdict::createFile_parse(Signal* signal, bool master,
21831                           SchemaOpPtr op_ptr,
21832                           SectionHandle& handle, ErrorInfo& error)
21833 {
21834   jam();
21835 
21836   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
21837   CreateFileRecPtr createFilePtr;
21838   getOpRec(op_ptr, createFilePtr);
21839   CreateFileImplReq* impl_req = &createFilePtr.p->m_request;
21840 
21841   SegmentedSectionPtr objInfoPtr;
21842   {
21843     bool ok = handle.getSection(objInfoPtr, 0);
21844     if (!ok)
21845     {
21846       jam();
21847       setError(error, CreateTableRef::InvalidFormat, __LINE__);
21848       return;
21849     }
21850   }
21851   SimplePropertiesSectionReader it(objInfoPtr, getSectionSegmentPool());
21852 
21853   DictObjectPtr obj_ptr; obj_ptr.setNull();
21854   FilePtr filePtr; filePtr.setNull();
21855 
21856   DictFilegroupInfo::File f; f.init();
21857   SimpleProperties::UnpackStatus status;
21858   status = SimpleProperties::unpack(it, &f,
21859 				    DictFilegroupInfo::FileMapping,
21860 				    DictFilegroupInfo::FileMappingSize,
21861 				    true, true);
21862 
21863   if (status != SimpleProperties::Eof)
21864   {
21865     jam();
21866     setError(error, CreateFileRef::InvalidFormat, __LINE__);
21867     return;
21868   }
21869 
21870   // Get Filegroup
21871   FilegroupPtr fg_ptr;
21872   if (!find_object(fg_ptr, f.FilegroupId))
21873   {
21874     jam();
21875     setError(error, CreateFileRef::NoSuchFilegroup, __LINE__, f.FileName);
21876     return;
21877   }
21878 
21879   if(fg_ptr.p->m_version != f.FilegroupVersion)
21880   {
21881     jam();
21882     setError(error, CreateFileRef::InvalidFilegroupVersion, __LINE__,
21883              f.FileName);
21884     return;
21885   }
21886 
21887   switch(f.FileType){
21888   case DictTabInfo::Datafile:
21889   {
21890     if(fg_ptr.p->m_type != DictTabInfo::Tablespace)
21891     {
21892       jam();
21893       setError(error, CreateFileRef::InvalidFileType, __LINE__, f.FileName);
21894       return;
21895     }
21896     break;
21897   }
21898   case DictTabInfo::Undofile:
21899   {
21900     if(fg_ptr.p->m_type != DictTabInfo::LogfileGroup)
21901     {
21902       jam();
21903       setError(error, CreateFileRef::InvalidFileType, __LINE__, f.FileName);
21904       return;
21905     }
21906     break;
21907   }
21908   default:
21909     jam();
21910     setError(error, CreateFileRef::InvalidFileType, __LINE__, f.FileName);
21911     return;
21912   }
21913 
21914   Uint32 len = Uint32(strlen(f.FileName) + 1);
21915   Uint32 hash = LocalRope::hash(f.FileName, len);
21916   if(get_object(f.FileName, len, hash) != 0)
21917   {
21918     jam();
21919     setError(error, CreateFileRef::FilenameAlreadyExists, __LINE__, f.FileName);
21920     return;
21921   }
21922 
21923   {
21924     Uint32 dl;
21925     const ndb_mgm_configuration_iterator * p =
21926       m_ctx.m_config.getOwnConfigIterator();
21927     if(!ndb_mgm_get_int_parameter(p, CFG_DB_DISCLESS, &dl) && dl)
21928     {
21929       jam();
21930       setError(error, CreateFileRef::NotSupportedWhenDiskless, __LINE__,
21931                f.FileName);
21932       return;
21933     }
21934   }
21935 
21936   if (fg_ptr.p->m_type == DictTabInfo::Tablespace &&
21937       f.FileSizeHi == 0 &&
21938       f.FileSizeLo < fg_ptr.p->m_tablespace.m_extent_size)
21939   {
21940     jam();
21941     setError(error, CreateFileRef::FileSizeTooSmall, __LINE__, f.FileName);
21942     return;
21943   }
21944 
21945   if(!c_obj_pool.seize(obj_ptr))
21946   {
21947     jam();
21948     setError(error, CreateTableRef::NoMoreTableRecords, __LINE__, f.FileName);
21949     goto error;
21950   }
21951   new (obj_ptr.p) DictObject;
21952 
21953   if (! c_file_pool.seize(filePtr))
21954   {
21955     jam();
21956     setError(error, CreateFileRef::OutOfFileRecords, __LINE__, f.FileName);
21957     goto error;
21958   }
21959 
21960   new (filePtr.p) File();
21961 
21962   {
21963     LocalRope name(c_rope_pool, obj_ptr.p->m_name);
21964     if(!name.assign(f.FileName, len, hash))
21965     {
21966       jam();
21967       setError(error, CreateTableRef::OutOfStringBuffer, __LINE__, f.FileName);
21968       goto error;
21969     }
21970   }
21971 
21972   if (master)
21973   {
21974     jam();
21975 
21976     Uint32 objId = getFreeObjId();
21977     if (objId == RNIL)
21978     {
21979       jam();
21980       setError(error, CreateFilegroupRef::NoMoreObjectRecords, __LINE__,
21981                f.FileName);
21982       goto error;
21983     }
21984     Uint32 version = getTableEntry(objId)->m_tableVersion;
21985 
21986     impl_req->file_id = objId;
21987     impl_req->file_version = create_obj_inc_schema_version(version);
21988   }
21989   else if (op_ptr.p->m_restart)
21990   {
21991     jam();
21992     impl_req->file_id = c_restartRecord.activeTable;
21993     impl_req->file_version = c_restartRecord.m_entry.m_tableVersion;
21994     switch(op_ptr.p->m_restart){
21995     case 1:
21996       jam();
21997       impl_req->requestInfo = CreateFileImplReq::Open;
21998       break;
21999     case 2:
22000       impl_req->requestInfo = CreateFileImplReq::CreateForce;
22001       break;
22002     }
22003   }
22004 
22005   /**
22006    * Init file
22007    */
22008   filePtr.p->key = impl_req->file_id;
22009   filePtr.p->m_file_size = ((Uint64)f.FileSizeHi) << 32 | f.FileSizeLo;
22010   if (fg_ptr.p->m_type == DictTabInfo::Tablespace)
22011   {
22012     // round down to page size and up to extent size - Tsman::open_file
22013     const Uint64 page_size = (Uint64)File_formats::NDB_PAGE_SIZE;
22014     const Uint64 extent_size = (Uint64)fg_ptr.p->m_tablespace.m_extent_size;
22015     ndbrequire(extent_size != 0);
22016     if (filePtr.p->m_file_size % page_size != 0 &&
22017         !ERROR_INSERTED(6030))
22018     {
22019       jam();
22020       filePtr.p->m_file_size /= page_size;
22021       filePtr.p->m_file_size *= page_size;
22022       createFilePtr.p->m_warningFlags |= CreateFileConf::WarnDatafileRoundDown;
22023     }
22024     if (filePtr.p->m_file_size % extent_size != 0 &&
22025         !ERROR_INSERTED(6030))
22026     {
22027       jam();
22028       filePtr.p->m_file_size +=
22029         extent_size - filePtr.p->m_file_size % extent_size;
22030       createFilePtr.p->m_warningFlags |= CreateFileConf::WarnDatafileRoundUp;
22031     }
22032   }
22033   if (fg_ptr.p->m_type == DictTabInfo::LogfileGroup)
22034   {
22035     // round down to page size - Lgman::Undofile::Undofile
22036     const Uint64 page_size = (Uint64)File_formats::NDB_PAGE_SIZE;
22037     if (filePtr.p->m_file_size % page_size != 0 &&
22038         !ERROR_INSERTED(6030))
22039     {
22040       jam();
22041       filePtr.p->m_file_size /= page_size;
22042       filePtr.p->m_file_size *= page_size;
22043       createFilePtr.p->m_warningFlags |= CreateFileConf::WarnUndofileRoundDown;
22044     }
22045   }
22046   filePtr.p->m_path = obj_ptr.p->m_name;
22047   filePtr.p->m_obj_ptr_i = obj_ptr.i;
22048   filePtr.p->m_filegroup_id = f.FilegroupId;
22049   filePtr.p->m_type = f.FileType;
22050   filePtr.p->m_version = impl_req->file_version;
22051 
22052   obj_ptr.p->m_id = impl_req->file_id;
22053   obj_ptr.p->m_type = f.FileType;
22054   obj_ptr.p->m_ref_count = 0;
22055 
22056   ndbrequire(link_object(obj_ptr, filePtr));
22057 
22058   {
22059     SchemaFile::TableEntry te; te.init();
22060     te.m_tableState = SchemaFile::SF_CREATE;
22061     te.m_tableVersion = filePtr.p->m_version;
22062     te.m_tableType = filePtr.p->m_type;
22063     te.m_info_words = objInfoPtr.sz;
22064     te.m_gcp = 0;
22065     te.m_transId = trans_ptr.p->m_transId;
22066 
22067     Uint32 err = trans_log_schema_op(op_ptr, impl_req->file_id, &te);
22068     if (err)
22069     {
22070       jam();
22071       setError(error, err, __LINE__);
22072       goto error;
22073     }
22074   }
22075 
22076   c_obj_name_hash.add(obj_ptr);
22077   c_obj_id_hash.add(obj_ptr);
22078 
22079   // save sections to DICT memory
22080   saveOpSection(op_ptr, handle, 0);
22081 
22082   switch(fg_ptr.p->m_type){
22083   case DictTabInfo::Tablespace:
22084   {
22085     jam();
22086     increase_ref_count(fg_ptr.p->m_obj_ptr_i);
22087     break;
22088   }
22089   case DictTabInfo::LogfileGroup:
22090   {
22091     jam();
22092     Local_file_list list(c_file_pool, fg_ptr.p->m_logfilegroup.m_files);
22093     list.addFirst(filePtr);
22094     break;
22095   }
22096   default:
22097     ndbrequire(false);
22098   }
22099 
22100   createFilePtr.p->m_parsed = true;
22101 
22102 
22103   if (g_trace)
22104   {
22105     g_eventLogger->info("Dbdict: %u: create name=%s,id=%u,obj_ptr_i=%d,"
22106                         "type=%s,bytes=%llu,warn=0x%x",__LINE__,
22107                         f.FileName,
22108                         impl_req->file_id,
22109                         filePtr.p->m_obj_ptr_i,
22110                         f.FileType == DictTabInfo::Datafile ? "datafile" :
22111                         f.FileType == DictTabInfo::Undofile ? "undofile" :
22112                         "<unknown>",
22113                         filePtr.p->m_file_size,
22114                         createFilePtr.p->m_warningFlags);
22115   }
22116 
22117   send_event(signal, trans_ptr,
22118              NDB_LE_CreateSchemaObject,
22119              impl_req->file_id,
22120              impl_req->file_version,
22121              f.FileType);
22122 
22123   return;
22124 error:
22125   if (!filePtr.isNull())
22126   {
22127     jam();
22128     c_file_pool.release(filePtr);
22129   }
22130 
22131   if (!obj_ptr.isNull())
22132   {
22133     jam();
22134     release_object(obj_ptr.i, obj_ptr.p);
22135   }
22136 }
22137 
22138 void
createFile_abortParse(Signal * signal,SchemaOpPtr op_ptr)22139 Dbdict::createFile_abortParse(Signal* signal, SchemaOpPtr op_ptr)
22140 {
22141   CreateFileRecPtr createFilePtr;
22142   getOpRec(op_ptr, createFilePtr);
22143   CreateFileImplReq* impl_req = &createFilePtr.p->m_request;
22144 
22145   if (createFilePtr.p->m_parsed)
22146   {
22147     FilePtr f_ptr;
22148     FilegroupPtr fg_ptr;
22149     ndbrequire(find_object(f_ptr, impl_req->file_id));
22150     ndbrequire(find_object(fg_ptr, f_ptr.p->m_filegroup_id));
22151     if (f_ptr.p->m_type == DictTabInfo::Datafile)
22152     {
22153       jam();
22154       decrease_ref_count(fg_ptr.p->m_obj_ptr_i);
22155     }
22156     else if (f_ptr.p->m_type == DictTabInfo::Undofile)
22157     {
22158       jam();
22159       Local_file_list list(c_file_pool, fg_ptr.p->m_logfilegroup.m_files);
22160       list.remove(f_ptr);
22161     }
22162 
22163     release_object(f_ptr.p->m_obj_ptr_i);
22164     c_file_pool.release(f_ptr);
22165   }
22166 
22167   sendTransConf(signal, op_ptr);
22168 }
22169 
22170 bool
createFile_subOps(Signal * signal,SchemaOpPtr op_ptr)22171 Dbdict::createFile_subOps(Signal* signal, SchemaOpPtr op_ptr)
22172 {
22173   return false;
22174 }
22175 
22176 void
createFile_reply(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)22177 Dbdict::createFile_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
22178 {
22179   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
22180   CreateFileRecPtr createFileRecPtr;
22181   getOpRec(op_ptr, createFileRecPtr);
22182   CreateFileImplReq* impl_req = &createFileRecPtr.p->m_request;
22183 
22184   if (!hasError(error))
22185   {
22186     jam();
22187     CreateFileConf* conf = (CreateFileConf*)signal->getDataPtrSend();
22188     conf->senderRef = reference();
22189     conf->senderData = op_ptr.p->m_clientData;
22190     conf->transId = trans_ptr.p->m_transId;
22191     conf->fileId = impl_req->file_id;
22192     conf->fileVersion = impl_req->file_version;
22193     conf->warningFlags = createFileRecPtr.p->m_warningFlags;
22194     Uint32 clientRef = op_ptr.p->m_clientRef;
22195     sendSignal(clientRef, GSN_CREATE_FILE_CONF, signal,
22196                CreateFileConf::SignalLength, JBB);
22197   }
22198   else
22199   {
22200     jam();
22201     CreateFileRef* ref = (CreateFileRef*)signal->getDataPtrSend();
22202     ref->senderRef = reference();
22203     ref->senderData = op_ptr.p->m_clientData;
22204     ref->transId = trans_ptr.p->m_transId;
22205     getError(error, ref);
22206 
22207     Uint32 clientRef = op_ptr.p->m_clientRef;
22208     sendSignal(clientRef, GSN_CREATE_FILE_REF, signal,
22209                CreateFileRef::SignalLength, JBB);
22210   }
22211 }
22212 
22213 // CreateFile: PREPARE
22214 
22215 void
createFile_prepare(Signal * signal,SchemaOpPtr op_ptr)22216 Dbdict::createFile_prepare(Signal* signal, SchemaOpPtr op_ptr)
22217 {
22218   jam();
22219 
22220   CreateFileRecPtr createFileRecPtr;
22221   getOpRec(op_ptr, createFileRecPtr);
22222   CreateFileImplReq* impl_req = &createFileRecPtr.p->m_request;
22223 
22224   Callback cb =  {
22225     safe_cast(&Dbdict::createFile_fromWriteObjInfo), op_ptr.p->op_key
22226   };
22227 
22228   if (ZRESTART_NO_WRITE_AFTER_READ && op_ptr.p->m_restart == 1)
22229   {
22230     jam();
22231     /**
22232      * We read obj from disk, no need to rewrite it
22233      */
22234     execute(signal, cb, 0);
22235     return;
22236   }
22237 
22238   const OpSection& objInfoSec = getOpSection(op_ptr, 0);
22239   writeTableFile(signal, op_ptr, impl_req->file_id, objInfoSec, &cb);
22240 }
22241 
22242 void
createFile_fromWriteObjInfo(Signal * signal,Uint32 op_key,Uint32 ret)22243 Dbdict::createFile_fromWriteObjInfo(Signal* signal,
22244                                     Uint32 op_key,
22245                                     Uint32 ret)
22246 {
22247   SchemaOpPtr op_ptr;
22248   CreateFileRecPtr createFileRecPtr;
22249   ndbrequire(findSchemaOp(op_ptr, createFileRecPtr, op_key));
22250   CreateFileImplReq* impl_req = &createFileRecPtr.p->m_request;
22251 
22252   if (ret)
22253   {
22254     jam();
22255     setError(op_ptr, ret, __LINE__);
22256     sendTransRef(signal, op_ptr);
22257     return;
22258   }
22259 
22260   /**
22261    * CONTACT TSMAN LGMAN PGMAN
22262    */
22263   CreateFileImplReq* req = (CreateFileImplReq*)signal->getDataPtrSend();
22264   FilePtr f_ptr;
22265   FilegroupPtr fg_ptr;
22266 
22267   ndbrequire(find_object(f_ptr, impl_req->file_id));
22268   ndbrequire(find_object(fg_ptr, f_ptr.p->m_filegroup_id));
22269 
22270   req->senderData = op_ptr.p->op_key;
22271   req->senderRef = reference();
22272 
22273   req->file_id = f_ptr.p->key;
22274   req->filegroup_id = f_ptr.p->m_filegroup_id;
22275   req->filegroup_version = fg_ptr.p->m_version;
22276   req->file_size_hi = (Uint32)(f_ptr.p->m_file_size >> 32);
22277   req->file_size_lo = (Uint32)(f_ptr.p->m_file_size & 0xFFFFFFFF);
22278   req->requestInfo = impl_req->requestInfo;
22279 
22280   Uint32 ref= 0;
22281   Uint32 len= 0;
22282   switch(f_ptr.p->m_type){
22283   case DictTabInfo::Datafile:
22284   {
22285     jam();
22286     ref = TSMAN_REF;
22287     len = CreateFileImplReq::DatafileLength;
22288     req->tablespace.extent_size = fg_ptr.p->m_tablespace.m_extent_size;
22289     break;
22290   }
22291   case DictTabInfo::Undofile:
22292   {
22293     jam();
22294     ref = LGMAN_REF;
22295     len = CreateFileImplReq::UndofileLength;
22296     break;
22297   }
22298   default:
22299     ndbrequire(false);
22300   }
22301 
22302   char name[PATH_MAX];
22303   ConstRope tmp(c_rope_pool, f_ptr.p->m_path);
22304   tmp.copy(name);
22305   LinearSectionPtr ptr[3];
22306   ptr[0].p = (Uint32*)&name[0];
22307   ptr[0].sz = Uint32(strlen(name)+1+3)/4;
22308   sendSignal(ref, GSN_CREATE_FILE_IMPL_REQ, signal, len, JBB, ptr, 1);
22309 
22310   Callback c =  {
22311     safe_cast(&Dbdict::createFile_fromLocal), op_ptr.p->op_key
22312   };
22313   op_ptr.p->m_callback = c;
22314 }
22315 
22316 void
createFile_abortPrepare(Signal * signal,SchemaOpPtr op_ptr)22317 Dbdict::createFile_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
22318 {
22319   CreateFileImplReq* req = (CreateFileImplReq*)signal->getDataPtrSend();
22320   FilePtr f_ptr;
22321   FilegroupPtr fg_ptr;
22322 
22323   CreateFileRecPtr createFileRecPtr;
22324   getOpRec(op_ptr, createFileRecPtr);
22325   CreateFileImplReq* impl_req = &createFileRecPtr.p->m_request;
22326 
22327   ndbrequire(find_object(f_ptr, impl_req->file_id));
22328   ndbrequire(find_object(fg_ptr, f_ptr.p->m_filegroup_id));
22329 
22330   req->senderData = op_ptr.p->op_key;
22331   req->senderRef = reference();
22332   req->requestInfo = CreateFileImplReq::Abort;
22333   req->file_id = f_ptr.p->key;
22334   req->filegroup_id = f_ptr.p->m_filegroup_id;
22335   req->filegroup_version = fg_ptr.p->m_version;
22336 
22337   Uint32 ref= 0;
22338   switch(f_ptr.p->m_type){
22339   case DictTabInfo::Datafile:
22340   {
22341     jam();
22342     ref = TSMAN_REF;
22343     break;
22344   }
22345   case DictTabInfo::Undofile:
22346   {
22347     jam();
22348     ref = LGMAN_REF;
22349     break;
22350   }
22351   default:
22352     ndbrequire(false);
22353   }
22354 
22355   sendSignal(ref, GSN_CREATE_FILE_IMPL_REQ, signal,
22356              CreateFileImplReq::AbortLength, JBB);
22357 
22358   Callback c =  {
22359     safe_cast(&Dbdict::createFile_fromLocal), op_ptr.p->op_key
22360   };
22361   op_ptr.p->m_callback = c;
22362 }
22363 
22364 // CreateFile: COMMIT
22365 
22366 void
createFile_commit(Signal * signal,SchemaOpPtr op_ptr)22367 Dbdict::createFile_commit(Signal* signal, SchemaOpPtr op_ptr)
22368 {
22369   jam();
22370 
22371   CreateFileRecPtr createFileRecPtr;
22372   getOpRec(op_ptr, createFileRecPtr);
22373   CreateFileImplReq* impl_req = &createFileRecPtr.p->m_request;
22374 
22375   /**
22376    * CONTACT TSMAN LGMAN PGMAN
22377    */
22378   CreateFileImplReq* req = (CreateFileImplReq*)signal->getDataPtrSend();
22379   FilePtr f_ptr;
22380   FilegroupPtr fg_ptr;
22381 
22382   jam();
22383   ndbrequire(find_object(f_ptr, impl_req->file_id));
22384   ndbrequire(find_object(fg_ptr, f_ptr.p->m_filegroup_id));
22385 
22386   req->senderData = op_ptr.p->op_key;
22387   req->senderRef = reference();
22388   req->requestInfo = CreateFileImplReq::Commit;
22389 
22390   req->file_id = f_ptr.p->key;
22391   req->filegroup_id = f_ptr.p->m_filegroup_id;
22392   req->filegroup_version = fg_ptr.p->m_version;
22393 
22394   Uint32 ref= 0;
22395   switch(f_ptr.p->m_type){
22396   case DictTabInfo::Datafile:
22397   {
22398     jam();
22399     ref = TSMAN_REF;
22400     break;
22401   }
22402   case DictTabInfo::Undofile:
22403   {
22404     jam();
22405     ref = LGMAN_REF;
22406     break;
22407   }
22408   default:
22409     ndbrequire(false);
22410   }
22411   sendSignal(ref, GSN_CREATE_FILE_IMPL_REQ, signal,
22412 	     CreateFileImplReq::CommitLength, JBB);
22413 
22414   Callback c =  {
22415     safe_cast(&Dbdict::createFile_fromLocal), op_ptr.p->op_key
22416   };
22417   op_ptr.p->m_callback = c;
22418 }
22419 
22420 // CreateFile: COMPLETE
22421 
22422 void
createFile_complete(Signal * signal,SchemaOpPtr op_ptr)22423 Dbdict::createFile_complete(Signal* signal, SchemaOpPtr op_ptr)
22424 {
22425   jam();
22426   sendTransConf(signal, op_ptr);
22427 }
22428 
22429 void
createFile_fromLocal(Signal * signal,Uint32 op_key,Uint32 ret)22430 Dbdict::createFile_fromLocal(Signal* signal, Uint32 op_key, Uint32 ret)
22431 {
22432   jam();
22433   SchemaOpPtr op_ptr;
22434   CreateFileRecPtr createFilePtr;
22435   ndbrequire(findSchemaOp(op_ptr, createFilePtr, op_key));
22436 
22437   if (ret == 0)
22438   {
22439     jam();
22440     sendTransConf(signal, op_ptr);
22441   }
22442   else
22443   {
22444     jam();
22445     setError(op_ptr, ret, __LINE__);
22446     sendTransRef(signal, op_ptr);
22447   }
22448 }
22449 
22450 void
execCREATE_FILE_IMPL_REF(Signal * signal)22451 Dbdict::execCREATE_FILE_IMPL_REF(Signal* signal)
22452 {
22453   jamEntry();
22454   CreateFileImplRef * ref = (CreateFileImplRef*)signal->getDataPtr();
22455   handleDictRef(signal, ref);
22456 }
22457 
22458 void
execCREATE_FILE_IMPL_CONF(Signal * signal)22459 Dbdict::execCREATE_FILE_IMPL_CONF(Signal* signal)
22460 {
22461   jamEntry();
22462   CreateFileImplConf * conf = (CreateFileImplConf*)signal->getDataPtr();
22463   handleDictConf(signal, conf);
22464 }
22465 
22466 // CreateFile: END
22467 
22468 // MODULE: CreateFilegroup
22469 
22470 const Dbdict::OpInfo
22471 Dbdict::CreateFilegroupRec::g_opInfo = {
22472   { 'C', 'F', 'G', 0 },
22473   ~RT_DBDICT_CREATE_FILEGROUP,
22474   GSN_CREATE_FILEGROUP_IMPL_REQ,
22475   CreateFilegroupImplReq::SignalLength,
22476   //
22477   &Dbdict::createFilegroup_seize,
22478   &Dbdict::createFilegroup_release,
22479   //
22480   &Dbdict::createFilegroup_parse,
22481   &Dbdict::createFilegroup_subOps,
22482   &Dbdict::createFilegroup_reply,
22483   //
22484   &Dbdict::createFilegroup_prepare,
22485   &Dbdict::createFilegroup_commit,
22486   &Dbdict::createFilegroup_complete,
22487   //
22488   &Dbdict::createFilegroup_abortParse,
22489   &Dbdict::createFilegroup_abortPrepare
22490 };
22491 
22492 void
execCREATE_FILEGROUP_REQ(Signal * signal)22493 Dbdict::execCREATE_FILEGROUP_REQ(Signal* signal)
22494 {
22495   jamEntry();
22496   if (!assembleFragments(signal)) {
22497     jam();
22498     return;
22499   }
22500   SectionHandle handle(this, signal);
22501 
22502   const CreateFilegroupReq req_copy =
22503     *(const CreateFilegroupReq*)signal->getDataPtr();
22504   const CreateFilegroupReq* req = &req_copy;
22505 
22506   ErrorInfo error;
22507   do {
22508     SchemaOpPtr op_ptr;
22509     CreateFilegroupRecPtr createFilegroupPtr;
22510     CreateFilegroupImplReq* impl_req;
22511 
22512     startClientReq(op_ptr, createFilegroupPtr, req, impl_req, error);
22513     if (hasError(error)) {
22514       jam();
22515       break;
22516     }
22517 
22518     impl_req->filegroup_id = RNIL;
22519     impl_req->filegroup_version = 0;
22520 
22521     handleClientReq(signal, op_ptr, handle);
22522     return;
22523   } while (0);
22524 
22525   releaseSections(handle);
22526 
22527   CreateFilegroupRef* ref = (CreateFilegroupRef*)signal->getDataPtrSend();
22528   ref->senderRef = reference();
22529   ref->transId = req->transId;
22530   ref->senderData = req->senderData;
22531   getError(error, ref);
22532 
22533   sendSignal(req->senderRef, GSN_CREATE_FILEGROUP_REF, signal,
22534 	     CreateFilegroupRef::SignalLength, JBB);
22535 }
22536 
22537 bool
createFilegroup_seize(SchemaOpPtr op_ptr)22538 Dbdict::createFilegroup_seize(SchemaOpPtr op_ptr)
22539 {
22540   return seizeOpRec<CreateFilegroupRec>(op_ptr);
22541 }
22542 
22543 void
createFilegroup_release(SchemaOpPtr op_ptr)22544 Dbdict::createFilegroup_release(SchemaOpPtr op_ptr)
22545 {
22546   releaseOpRec<CreateFilegroupRec>(op_ptr);
22547 }
22548 
22549 // CreateFilegroup: PARSE
22550 
22551 void
createFilegroup_parse(Signal * signal,bool master,SchemaOpPtr op_ptr,SectionHandle & handle,ErrorInfo & error)22552 Dbdict::createFilegroup_parse(Signal* signal, bool master,
22553                               SchemaOpPtr op_ptr,
22554                               SectionHandle& handle, ErrorInfo& error)
22555 {
22556   jam();
22557 
22558   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
22559   CreateFilegroupRecPtr createFilegroupPtr;
22560   getOpRec(op_ptr, createFilegroupPtr);
22561   CreateFilegroupImplReq* impl_req = &createFilegroupPtr.p->m_request;
22562 
22563   SegmentedSectionPtr objInfoPtr;
22564   {
22565     bool ok = handle.getSection(objInfoPtr, 0);
22566     if (!ok)
22567     {
22568       jam();
22569       setError(error, CreateTableRef::InvalidFormat, __LINE__);
22570       return;
22571     }
22572   }
22573   SimplePropertiesSectionReader it(objInfoPtr, getSectionSegmentPool());
22574 
22575   DictObjectPtr obj_ptr; obj_ptr.setNull();
22576   FilegroupPtr fg_ptr; fg_ptr.setNull();
22577 
22578   DictFilegroupInfo::Filegroup fg; fg.init();
22579   SimpleProperties::UnpackStatus status =
22580     SimpleProperties::unpack(it, &fg,
22581                              DictFilegroupInfo::Mapping,
22582                              DictFilegroupInfo::MappingSize,
22583                              true, true);
22584 
22585   if(status != SimpleProperties::Eof)
22586   {
22587     jam();
22588     setError(error, CreateTableRef::InvalidFormat, __LINE__);
22589     return;
22590   }
22591 
22592   if(fg.FilegroupType == DictTabInfo::Tablespace)
22593   {
22594     if(!fg.TS_ExtentSize)
22595     {
22596       jam();
22597       setError(error, CreateFilegroupRef::InvalidExtentSize, __LINE__);
22598       return;
22599     }
22600   }
22601   else if(fg.FilegroupType == DictTabInfo::LogfileGroup)
22602   {
22603     /**
22604      * undo_buffer_size can't be less than 96KB in LGMAN block
22605      */
22606     if(fg.LF_UndoBufferSize < 3 * File_formats::NDB_PAGE_SIZE)
22607     {
22608       jam();
22609       setError(error, CreateFilegroupRef::InvalidUndoBufferSize, __LINE__);
22610       return;
22611     }
22612   }
22613 
22614   Uint32 len = Uint32(strlen(fg.FilegroupName) + 1);
22615   Uint32 hash = LocalRope::hash(fg.FilegroupName, len);
22616   if(get_object(fg.FilegroupName, len, hash) != 0)
22617   {
22618     jam();
22619     setError(error, CreateTableRef::TableAlreadyExist, __LINE__);
22620     return;
22621   }
22622 
22623   if(!c_obj_pool.seize(obj_ptr))
22624   {
22625     jam();
22626     setError(error, CreateTableRef::NoMoreTableRecords, __LINE__);
22627     return;
22628   }
22629   new (obj_ptr.p) DictObject;
22630 
22631   Uint32 inc_obj_ptr_i = RNIL;
22632   if(!c_filegroup_pool.seize(fg_ptr))
22633   {
22634     jam();
22635     setError(error, CreateTableRef::NoMoreTableRecords, __LINE__);
22636     goto error;
22637   }
22638 
22639   new (fg_ptr.p) Filegroup();
22640 
22641   {
22642     LocalRope name(c_rope_pool, obj_ptr.p->m_name);
22643     if(!name.assign(fg.FilegroupName, len, hash))
22644     {
22645       jam();
22646       setError(error, CreateTableRef::OutOfStringBuffer, __LINE__);
22647       goto error;
22648     }
22649   }
22650 
22651   switch(fg.FilegroupType){
22652   case DictTabInfo::Tablespace:
22653   {
22654     //fg.TS_DataGrow = group.m_grow_spec;
22655     fg_ptr.p->m_tablespace.m_extent_size = fg.TS_ExtentSize;
22656     // round up to page size - Tsman::Tablespace::Tablespace
22657     const Uint32 page_size = (Uint32)File_formats::NDB_PAGE_SIZE;
22658     if (fg_ptr.p->m_tablespace.m_extent_size % page_size != 0 &&
22659         !ERROR_INSERTED(6030))
22660     {
22661       jam();
22662       fg_ptr.p->m_tablespace.m_extent_size +=
22663         page_size - fg_ptr.p->m_tablespace.m_extent_size % page_size;
22664       createFilegroupPtr.p->m_warningFlags |= CreateFilegroupConf::WarnExtentRoundUp;
22665     }
22666 #if defined VM_TRACE || defined ERROR_INSERT
22667     ndbout << "DD dict: ts id:" << "?" << " extent bytes:" << fg_ptr.p->m_tablespace.m_extent_size << " warn:" << hex << createFilegroupPtr.p->m_warningFlags << endl;
22668 #endif
22669     fg_ptr.p->m_tablespace.m_default_logfile_group_id = fg.TS_LogfileGroupId;
22670 
22671     FilegroupPtr lg_ptr;
22672     if (!find_object(lg_ptr, fg.TS_LogfileGroupId))
22673     {
22674       jam();
22675       setError(error, CreateFilegroupRef::NoSuchLogfileGroup, __LINE__);
22676       goto error;
22677     }
22678 
22679     if (lg_ptr.p->m_version != fg.TS_LogfileGroupVersion)
22680     {
22681       jam();
22682       setError(error, CreateFilegroupRef::InvalidFilegroupVersion, __LINE__);
22683       goto error;
22684     }
22685     inc_obj_ptr_i = lg_ptr.p->m_obj_ptr_i;
22686     break;
22687   }
22688   case DictTabInfo::LogfileGroup:
22689   {
22690     jam();
22691     fg_ptr.p->m_logfilegroup.m_undo_buffer_size = fg.LF_UndoBufferSize;
22692     // round up to page size - Lgman::alloc_logbuffer_memory
22693     const Uint32 page_size = (Uint32)File_formats::NDB_PAGE_SIZE;
22694     if (fg_ptr.p->m_logfilegroup.m_undo_buffer_size % page_size != 0 &&
22695         !ERROR_INSERTED(6030))
22696     {
22697       jam();
22698       fg_ptr.p->m_logfilegroup.m_undo_buffer_size +=
22699         page_size - fg_ptr.p->m_logfilegroup.m_undo_buffer_size % page_size;
22700       createFilegroupPtr.p->m_warningFlags |= CreateFilegroupConf::WarnUndobufferRoundUp;
22701     }
22702 #if defined VM_TRACE || defined ERROR_INSERT
22703     ndbout << "DD dict: fg id:" << "?" << " undo buffer bytes:" << fg_ptr.p->m_logfilegroup.m_undo_buffer_size << " warn:" << hex << createFilegroupPtr.p->m_warningFlags << endl;
22704 #endif
22705     fg_ptr.p->m_logfilegroup.m_files.init();
22706     //fg.LF_UndoGrow = ;
22707     break;
22708   }
22709   default:
22710     ndbrequire(false);
22711   }
22712 
22713   if (master)
22714   {
22715     jam();
22716 
22717     Uint32 objId = getFreeObjId();
22718     if (objId == RNIL)
22719     {
22720       jam();
22721       setError(error, CreateFilegroupRef::NoMoreObjectRecords, __LINE__);
22722       goto error;
22723     }
22724     Uint32 version = getTableEntry(objId)->m_tableVersion;
22725 
22726     impl_req->filegroup_id = objId;
22727     impl_req->filegroup_version = create_obj_inc_schema_version(version);
22728   }
22729   else if (op_ptr.p->m_restart)
22730   {
22731     jam();
22732     impl_req->filegroup_id = c_restartRecord.activeTable;
22733     impl_req->filegroup_version = c_restartRecord.m_entry.m_tableVersion;
22734   }
22735 
22736   fg_ptr.p->key = impl_req->filegroup_id;
22737   fg_ptr.p->m_type = fg.FilegroupType;
22738   fg_ptr.p->m_version = impl_req->filegroup_version;
22739   fg_ptr.p->m_name = obj_ptr.p->m_name;
22740 
22741   obj_ptr.p->m_id = impl_req->filegroup_id;
22742   obj_ptr.p->m_type = fg.FilegroupType;
22743   obj_ptr.p->m_ref_count = 0;
22744 
22745   ndbrequire(link_object(obj_ptr, fg_ptr));
22746 
22747   if (master)
22748   {
22749     jam();
22750     releaseSections(handle);
22751     SimplePropertiesSectionWriter w(*this);
22752     packFilegroupIntoPages(w, fg_ptr, 0, 0);
22753     w.getPtr(objInfoPtr);
22754     handle.m_ptr[0] = objInfoPtr;
22755     handle.m_cnt = 1;
22756   }
22757 
22758   {
22759     SchemaFile::TableEntry te; te.init();
22760     te.m_tableState = SchemaFile::SF_CREATE;
22761     te.m_tableVersion = fg_ptr.p->m_version;
22762     te.m_tableType = fg_ptr.p->m_type;
22763     te.m_info_words = objInfoPtr.sz;
22764     te.m_gcp = 0;
22765     te.m_transId = trans_ptr.p->m_transId;
22766 
22767     Uint32 err = trans_log_schema_op(op_ptr, impl_req->filegroup_id, &te);
22768     if (err)
22769     {
22770       jam();
22771       setError(error, err, __LINE__);
22772       goto error;
22773     }
22774   }
22775 
22776   c_obj_name_hash.add(obj_ptr);
22777   c_obj_id_hash.add(obj_ptr);
22778 
22779   // save sections to DICT memory
22780   saveOpSection(op_ptr, handle, 0);
22781 
22782   if (inc_obj_ptr_i != RNIL)
22783   {
22784     jam();
22785     increase_ref_count(inc_obj_ptr_i);
22786   }
22787   createFilegroupPtr.p->m_parsed = true;
22788 
22789 #if defined VM_TRACE || defined ERROR_INSERT
22790   ndbout_c("Dbdict: %u: create name=%s,id=%u,obj_ptr_i=%d",__LINE__,
22791            fg.FilegroupName, impl_req->filegroup_id, fg_ptr.p->m_obj_ptr_i);
22792 #endif
22793 
22794   return;
22795 
22796 error:
22797   jam();
22798   if (!fg_ptr.isNull())
22799   {
22800     jam();
22801     c_filegroup_pool.release(fg_ptr);
22802   }
22803 
22804   if (!obj_ptr.isNull())
22805   {
22806     jam();
22807     release_object(obj_ptr.i, obj_ptr.p);
22808   }
22809 }
22810 
22811 void
createFilegroup_abortParse(Signal * signal,SchemaOpPtr op_ptr)22812 Dbdict::createFilegroup_abortParse(Signal* signal, SchemaOpPtr op_ptr)
22813 {
22814   CreateFilegroupRecPtr createFilegroupPtr;
22815   getOpRec(op_ptr, createFilegroupPtr);
22816 
22817   if (createFilegroupPtr.p->m_parsed)
22818   {
22819     jam();
22820     CreateFilegroupImplReq* impl_req = &createFilegroupPtr.p->m_request;
22821 
22822     FilegroupPtr fg_ptr;
22823     ndbrequire(find_object(fg_ptr, impl_req->filegroup_id));
22824 
22825     if (fg_ptr.p->m_type == DictTabInfo::Tablespace)
22826     {
22827       jam();
22828       FilegroupPtr lg_ptr;
22829       ndbrequire(find_object
22830                  (lg_ptr, fg_ptr.p->m_tablespace.m_default_logfile_group_id));
22831       decrease_ref_count(lg_ptr.p->m_obj_ptr_i);
22832     }
22833 
22834     release_object(fg_ptr.p->m_obj_ptr_i);
22835     c_filegroup_pool.release(fg_ptr);
22836   }
22837 
22838   sendTransConf(signal, op_ptr);
22839 }
22840 
22841 
22842 bool
createFilegroup_subOps(Signal * signal,SchemaOpPtr op_ptr)22843 Dbdict::createFilegroup_subOps(Signal* signal, SchemaOpPtr op_ptr)
22844 {
22845   return false;
22846 }
22847 
22848 void
createFilegroup_reply(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)22849 Dbdict::createFilegroup_reply(Signal* signal,
22850                               SchemaOpPtr op_ptr,
22851                               ErrorInfo error)
22852 {
22853   jam();
22854 
22855   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
22856   CreateFilegroupRecPtr createFilegroupRecPtr;
22857   getOpRec(op_ptr, createFilegroupRecPtr);
22858   CreateFilegroupImplReq* impl_req = &createFilegroupRecPtr.p->m_request;
22859 
22860   if (!hasError(error))
22861   {
22862     jam();
22863     CreateFilegroupConf* conf = (CreateFilegroupConf*)signal->getDataPtrSend();
22864     conf->senderRef = reference();
22865     conf->senderData = op_ptr.p->m_clientData;
22866     conf->transId = trans_ptr.p->m_transId;
22867     conf->filegroupId = impl_req->filegroup_id;
22868     conf->filegroupVersion = impl_req->filegroup_version;
22869     conf->warningFlags = createFilegroupRecPtr.p->m_warningFlags;
22870     Uint32 clientRef = op_ptr.p->m_clientRef;
22871     sendSignal(clientRef, GSN_CREATE_FILEGROUP_CONF, signal,
22872                CreateFilegroupConf::SignalLength, JBB);
22873   } else {
22874     jam();
22875     CreateFilegroupRef* ref = (CreateFilegroupRef*)signal->getDataPtrSend();
22876     ref->senderRef = reference();
22877     ref->senderData = op_ptr.p->m_clientData;
22878     ref->transId = trans_ptr.p->m_transId;
22879     getError(error, ref);
22880 
22881     Uint32 clientRef = op_ptr.p->m_clientRef;
22882     sendSignal(clientRef, GSN_CREATE_FILEGROUP_REF, signal,
22883                CreateFilegroupRef::SignalLength, JBB);
22884   }
22885 }
22886 
22887 // CreateFilegroup: PREPARE
22888 
22889 void
createFilegroup_prepare(Signal * signal,SchemaOpPtr op_ptr)22890 Dbdict::createFilegroup_prepare(Signal* signal, SchemaOpPtr op_ptr)
22891 {
22892   jam();
22893 
22894   CreateFilegroupRecPtr createFilegroupRecPtr;
22895   getOpRec(op_ptr, createFilegroupRecPtr);
22896   CreateFilegroupImplReq* impl_req = &createFilegroupRecPtr.p->m_request;
22897 
22898   Callback cb =  {
22899     safe_cast(&Dbdict::createFilegroup_fromWriteObjInfo), op_ptr.p->op_key
22900   };
22901 
22902   if (ZRESTART_NO_WRITE_AFTER_READ && op_ptr.p->m_restart == 1)
22903   {
22904     jam();
22905     /**
22906      * We read obj from disk, no need to rewrite it
22907      */
22908     execute(signal, cb, 0);
22909     return;
22910   }
22911 
22912   const OpSection& objInfoSec = getOpSection(op_ptr, 0);
22913   writeTableFile(signal, op_ptr, impl_req->filegroup_id, objInfoSec, &cb);
22914 }
22915 
22916 void
createFilegroup_fromWriteObjInfo(Signal * signal,Uint32 op_key,Uint32 ret)22917 Dbdict::createFilegroup_fromWriteObjInfo(Signal* signal,
22918                                          Uint32 op_key,
22919                                          Uint32 ret)
22920 {
22921   SchemaOpPtr op_ptr;
22922   CreateFilegroupRecPtr createFilegroupRecPtr;
22923   ndbrequire(findSchemaOp(op_ptr, createFilegroupRecPtr, op_key));
22924 
22925   if (ret)
22926   {
22927     setError(op_ptr, ret, __LINE__);
22928     sendTransRef(signal, op_ptr);
22929     return;
22930   }
22931 
22932   /**
22933    * CONTACT TSMAN LGMAN PGMAN
22934    */
22935   CreateFilegroupImplReq* impl_req = &createFilegroupRecPtr.p->m_request;
22936 
22937   CreateFilegroupImplReq* req =
22938     (CreateFilegroupImplReq*)signal->getDataPtrSend();
22939   jam();
22940   req->senderData = op_ptr.p->op_key;
22941   req->senderRef = reference();
22942   req->filegroup_id = impl_req->filegroup_id;
22943   req->filegroup_version = impl_req->filegroup_version;
22944 
22945   FilegroupPtr fg_ptr;
22946 
22947   ndbrequire(find_object(fg_ptr, impl_req->filegroup_id));
22948 
22949   Uint32 ref= 0;
22950   Uint32 len= 0;
22951   switch(fg_ptr.p->m_type){
22952   case DictTabInfo::Tablespace:
22953   {
22954     jam();
22955     ref = TSMAN_REF;
22956     len = CreateFilegroupImplReq::TablespaceLength;
22957     req->tablespace.extent_size = fg_ptr.p->m_tablespace.m_extent_size;
22958     req->tablespace.logfile_group_id =
22959       fg_ptr.p->m_tablespace.m_default_logfile_group_id;
22960     break;
22961   }
22962   case DictTabInfo::LogfileGroup:
22963   {
22964     jam();
22965     ref = LGMAN_REF;
22966     len = CreateFilegroupImplReq::LogfileGroupLength;
22967     req->logfile_group.buffer_size =
22968       fg_ptr.p->m_logfilegroup.m_undo_buffer_size;
22969     break;
22970   }
22971   default:
22972     ndbrequire(false);
22973   }
22974 
22975   sendSignal(ref, GSN_CREATE_FILEGROUP_IMPL_REQ, signal, len, JBB);
22976 
22977   Callback c =  {
22978     safe_cast(&Dbdict::createFilegroup_fromLocal), op_ptr.p->op_key
22979   };
22980   op_ptr.p->m_callback = c;
22981 }
22982 
22983 // CreateFilegroup: COMMIT
22984 
22985 void
createFilegroup_commit(Signal * signal,SchemaOpPtr op_ptr)22986 Dbdict::createFilegroup_commit(Signal* signal, SchemaOpPtr op_ptr)
22987 {
22988   jam();
22989 
22990   /**
22991    * cheat...only create...abort is implemented as DROP
22992    */
22993   sendTransConf(signal, op_ptr);
22994 }
22995 
22996 // CreateFilegroup: COMPLETE
22997 
22998 void
createFilegroup_complete(Signal * signal,SchemaOpPtr op_ptr)22999 Dbdict::createFilegroup_complete(Signal* signal, SchemaOpPtr op_ptr)
23000 {
23001   jam();
23002   sendTransConf(signal, op_ptr);
23003 }
23004 
23005 void
createFilegroup_abortPrepare(Signal * signal,SchemaOpPtr op_ptr)23006 Dbdict::createFilegroup_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
23007 {
23008   CreateFilegroupRecPtr createFilegroupRecPtr;
23009   getOpRec(op_ptr, createFilegroupRecPtr);
23010   CreateFilegroupImplReq* impl_req = &createFilegroupRecPtr.p->m_request;
23011 
23012   if (createFilegroupRecPtr.p->m_prepared)
23013   {
23014     Callback c =  {
23015       safe_cast(&Dbdict::createFilegroup_fromLocal), op_ptr.p->op_key
23016     };
23017     op_ptr.p->m_callback = c;
23018 
23019     send_drop_fg(signal, op_ptr.p->op_key, impl_req->filegroup_id,
23020                  DropFilegroupImplReq::Prepare);
23021   }
23022 
23023   sendTransConf(signal, op_ptr);
23024 }
23025 
23026 void
createFilegroup_fromLocal(Signal * signal,Uint32 op_key,Uint32 ret)23027 Dbdict::createFilegroup_fromLocal(Signal* signal, Uint32 op_key, Uint32 ret)
23028 {
23029   jam();
23030   SchemaOpPtr op_ptr;
23031   CreateFilegroupRecPtr createFilegroupPtr;
23032   ndbrequire(findSchemaOp(op_ptr, createFilegroupPtr, op_key));
23033 
23034   if (ret == 0)
23035   {
23036     jam();
23037     createFilegroupPtr.p->m_prepared = true;
23038     sendTransConf(signal, op_ptr);
23039   }
23040   else
23041   {
23042     jam();
23043     setError(op_ptr, ret, __LINE__);
23044     sendTransRef(signal, op_ptr);
23045   }
23046 }
23047 
23048 void
execCREATE_FILEGROUP_IMPL_REF(Signal * signal)23049 Dbdict::execCREATE_FILEGROUP_IMPL_REF(Signal* signal)
23050 {
23051   jamEntry();
23052   CreateFilegroupImplRef * ref = (CreateFilegroupImplRef*)signal->getDataPtr();
23053   handleDictRef(signal, ref);
23054 }
23055 
23056 void
execCREATE_FILEGROUP_IMPL_CONF(Signal * signal)23057 Dbdict::execCREATE_FILEGROUP_IMPL_CONF(Signal* signal)
23058 {
23059   jamEntry();
23060   CreateFilegroupImplConf * conf =
23061     (CreateFilegroupImplConf*)signal->getDataPtr();
23062   handleDictConf(signal, conf);
23063 }
23064 
23065 // CreateFilegroup: END
23066 
23067 // MODULE: DropFile
23068 
23069 const Dbdict::OpInfo
23070 Dbdict::DropFileRec::g_opInfo = {
23071   { 'D', 'F', 'l', 0 },
23072   ~RT_DBDICT_DROP_FILE,
23073   GSN_DROP_FILE_IMPL_REQ,
23074   DropFileImplReq::SignalLength,
23075   //
23076   &Dbdict::dropFile_seize,
23077   &Dbdict::dropFile_release,
23078   //
23079   &Dbdict::dropFile_parse,
23080   &Dbdict::dropFile_subOps,
23081   &Dbdict::dropFile_reply,
23082   //
23083   &Dbdict::dropFile_prepare,
23084   &Dbdict::dropFile_commit,
23085   &Dbdict::dropFile_complete,
23086   //
23087   &Dbdict::dropFile_abortParse,
23088   &Dbdict::dropFile_abortPrepare
23089 };
23090 
23091 void
execDROP_FILE_REQ(Signal * signal)23092 Dbdict::execDROP_FILE_REQ(Signal* signal)
23093 {
23094   jamEntry();
23095   if (!assembleFragments(signal)) {
23096     jam();
23097     return;
23098   }
23099   SectionHandle handle(this, signal);
23100 
23101   const DropFileReq req_copy =
23102     *(const DropFileReq*)signal->getDataPtr();
23103   const DropFileReq* req = &req_copy;
23104 
23105   ErrorInfo error;
23106   do {
23107     SchemaOpPtr op_ptr;
23108     DropFileRecPtr dropFilePtr;
23109     DropFileImplReq* impl_req;
23110 
23111     startClientReq(op_ptr, dropFilePtr, req, impl_req, error);
23112     if (hasError(error)) {
23113       jam();
23114       break;
23115     }
23116 
23117     impl_req->file_id = req->file_id;
23118     impl_req->file_version = req->file_version;
23119 
23120     handleClientReq(signal, op_ptr, handle);
23121     return;
23122   } while (0);
23123 
23124   releaseSections(handle);
23125 
23126   DropFileRef* ref = (DropFileRef*)signal->getDataPtrSend();
23127   ref->senderRef = reference();
23128   ref->transId = req->transId;
23129   ref->senderData = req->senderData;
23130   getError(error, ref);
23131 
23132   sendSignal(req->senderRef, GSN_DROP_FILE_REF, signal,
23133 	     DropFileRef::SignalLength, JBB);
23134 }
23135 
23136 bool
dropFile_seize(SchemaOpPtr op_ptr)23137 Dbdict::dropFile_seize(SchemaOpPtr op_ptr)
23138 {
23139   return seizeOpRec<DropFileRec>(op_ptr);
23140 }
23141 
23142 void
dropFile_release(SchemaOpPtr op_ptr)23143 Dbdict::dropFile_release(SchemaOpPtr op_ptr)
23144 {
23145   releaseOpRec<DropFileRec>(op_ptr);
23146 }
23147 
23148 // DropFile: PARSE
23149 
23150 void
dropFile_parse(Signal * signal,bool master,SchemaOpPtr op_ptr,SectionHandle & handle,ErrorInfo & error)23151 Dbdict::dropFile_parse(Signal* signal, bool master,
23152                        SchemaOpPtr op_ptr,
23153                        SectionHandle& handle, ErrorInfo& error)
23154 {
23155   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23156   DropFileRecPtr dropFileRecPtr;
23157   getOpRec(op_ptr, dropFileRecPtr);
23158   DropFileImplReq* impl_req = &dropFileRecPtr.p->m_request;
23159 
23160   FilePtr f_ptr;
23161   if (!find_object(f_ptr, impl_req->file_id))
23162   {
23163     jam();
23164     setError(error, DropFileRef::NoSuchFile, __LINE__);
23165     return;
23166   }
23167 
23168   if (f_ptr.p->m_version != impl_req->file_version)
23169   {
23170     jam();
23171     setError(error, DropFileRef::InvalidSchemaObjectVersion, __LINE__);
23172     return;
23173   }
23174 
23175   if (f_ptr.p->m_type == DictTabInfo::Undofile)
23176   {
23177     jam();
23178     setError(error, DropFileRef::DropUndoFileNotSupported, __LINE__);
23179     return;
23180   }
23181 
23182   if (check_write_obj(impl_req->file_id,
23183                       trans_ptr.p->m_transId,
23184                       SchemaFile::SF_DROP, error))
23185   {
23186     jam();
23187     return;
23188   }
23189 
23190   SchemaFile::TableEntry te; te.init();
23191   te.m_tableState = SchemaFile::SF_DROP;
23192   te.m_transId = trans_ptr.p->m_transId;
23193   Uint32 err = trans_log_schema_op(op_ptr, impl_req->file_id, &te);
23194   if (err)
23195   {
23196     jam();
23197     setError(error, err, __LINE__);
23198     return;
23199   }
23200 
23201 #if defined VM_TRACE || defined ERROR_INSERT
23202   {
23203     char buf[1024];
23204     LocalRope name(c_rope_pool, f_ptr.p->m_path);
23205     name.copy(buf);
23206     ndbout_c("Dbdict: drop name=%s,id=%u,obj_id=%u", buf,
23207              impl_req->file_id,
23208              f_ptr.p->m_obj_ptr_i);
23209   }
23210 #endif
23211 }
23212 
23213 void
dropFile_abortParse(Signal * signal,SchemaOpPtr op_ptr)23214 Dbdict::dropFile_abortParse(Signal* signal, SchemaOpPtr op_ptr)
23215 {
23216   jam();
23217   sendTransConf(signal, op_ptr);
23218 }
23219 
23220 bool
dropFile_subOps(Signal * signal,SchemaOpPtr op_ptr)23221 Dbdict::dropFile_subOps(Signal* signal, SchemaOpPtr op_ptr)
23222 {
23223   return false;
23224 }
23225 
23226 void
dropFile_reply(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)23227 Dbdict::dropFile_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
23228 {
23229   jam();
23230   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23231   DropFileRecPtr dropFileRecPtr;
23232   getOpRec(op_ptr, dropFileRecPtr);
23233   DropFileImplReq* impl_req = &dropFileRecPtr.p->m_request;
23234 
23235   if (!hasError(error))
23236   {
23237     jam();
23238     DropFileConf* conf = (DropFileConf*)signal->getDataPtrSend();
23239     conf->senderRef = reference();
23240     conf->senderData = op_ptr.p->m_clientData;
23241     conf->transId = trans_ptr.p->m_transId;
23242     conf->fileId = impl_req->file_id;
23243     conf->fileVersion = impl_req->file_version;
23244     Uint32 clientRef = op_ptr.p->m_clientRef;
23245     sendSignal(clientRef, GSN_DROP_FILE_CONF, signal,
23246                DropFileConf::SignalLength, JBB);
23247   }
23248   else
23249   {
23250     jam();
23251     DropFileRef* ref = (DropFileRef*)signal->getDataPtrSend();
23252     ref->senderRef = reference();
23253     ref->senderData = op_ptr.p->m_clientData;
23254     ref->transId = trans_ptr.p->m_transId;
23255     getError(error, ref);
23256 
23257     Uint32 clientRef = op_ptr.p->m_clientRef;
23258     sendSignal(clientRef, GSN_DROP_FILE_REF, signal,
23259                DropFileRef::SignalLength, JBB);
23260   }
23261 }
23262 
23263 // DropFile: PREPARE
23264 
23265 void
dropFile_prepare(Signal * signal,SchemaOpPtr op_ptr)23266 Dbdict::dropFile_prepare(Signal* signal, SchemaOpPtr op_ptr)
23267 {
23268   jam();
23269 
23270   DropFileRecPtr dropFileRecPtr;
23271   getOpRec(op_ptr, dropFileRecPtr);
23272   DropFileImplReq* impl_req = &dropFileRecPtr.p->m_request;
23273 
23274   Callback c =  {
23275     safe_cast(&Dbdict::dropFile_fromLocal), op_ptr.p->op_key
23276   };
23277   op_ptr.p->m_callback = c;
23278 
23279   send_drop_file(signal, op_ptr.p->op_key, impl_req->file_id,
23280                  DropFileImplReq::Prepare);
23281 }
23282 
23283 void
dropFile_abortPrepare(Signal * signal,SchemaOpPtr op_ptr)23284 Dbdict::dropFile_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
23285 {
23286   DropFileRecPtr dropFilePtr;
23287   getOpRec(op_ptr, dropFilePtr);
23288   DropFileImplReq* impl_req = &dropFilePtr.p->m_request;
23289 
23290   Callback c =  {
23291     safe_cast(&Dbdict::dropFile_fromLocal), op_ptr.p->op_key
23292   };
23293   op_ptr.p->m_callback = c;
23294 
23295   send_drop_file(signal, op_ptr.p->op_key, impl_req->file_id,
23296                  DropFileImplReq::Abort);
23297 }
23298 
23299 // DropFile: COMMIT
23300 
23301 void
dropFile_commit(Signal * signal,SchemaOpPtr op_ptr)23302 Dbdict::dropFile_commit(Signal* signal, SchemaOpPtr op_ptr)
23303 {
23304   jam();
23305 
23306   DropFileRecPtr dropFileRecPtr;
23307   getOpRec(op_ptr, dropFileRecPtr);
23308   DropFileImplReq* impl_req = &dropFileRecPtr.p->m_request;
23309 
23310   Callback c =  {
23311     safe_cast(&Dbdict::dropFile_fromLocal), op_ptr.p->op_key
23312   };
23313   op_ptr.p->m_callback = c;
23314 
23315 
23316   send_drop_file(signal, op_ptr.p->op_key, impl_req->file_id,
23317                  DropFileImplReq::Commit);
23318 }
23319 
23320 // DropFile: COMPLETE
23321 
23322 void
dropFile_complete(Signal * signal,SchemaOpPtr op_ptr)23323 Dbdict::dropFile_complete(Signal* signal, SchemaOpPtr op_ptr)
23324 {
23325   jam();
23326 
23327   DropFileRecPtr dropFileRecPtr;
23328   getOpRec(op_ptr, dropFileRecPtr);
23329   DropFileImplReq* impl_req = &dropFileRecPtr.p->m_request;
23330 
23331   FilePtr f_ptr;
23332   FilegroupPtr fg_ptr;
23333 
23334   jam();
23335   ndbrequire(find_object(f_ptr, impl_req->file_id));
23336   ndbrequire(find_object(fg_ptr, f_ptr.p->m_filegroup_id));
23337   decrease_ref_count(fg_ptr.p->m_obj_ptr_i);
23338   release_object(f_ptr.p->m_obj_ptr_i);
23339   c_file_pool.release(f_ptr);
23340 
23341   sendTransConf(signal, op_ptr);
23342 }
23343 
23344 void
dropFile_fromLocal(Signal * signal,Uint32 op_key,Uint32 ret)23345 Dbdict::dropFile_fromLocal(Signal* signal, Uint32 op_key, Uint32 ret)
23346 {
23347   jam();
23348   SchemaOpPtr op_ptr;
23349   DropFileRecPtr dropFilePtr;
23350   ndbrequire(findSchemaOp(op_ptr, dropFilePtr, op_key));
23351 
23352   if (ret == 0)
23353   {
23354     jam();
23355     sendTransConf(signal, op_ptr);
23356   }
23357   else
23358   {
23359     jam();
23360     setError(op_ptr, ret, __LINE__);
23361     sendTransRef(signal, op_ptr);
23362   }
23363 }
23364 
23365 void
execDROP_FILE_IMPL_REF(Signal * signal)23366 Dbdict::execDROP_FILE_IMPL_REF(Signal* signal)
23367 {
23368   jamEntry();
23369   DropFileImplRef * ref = (DropFileImplRef*)signal->getDataPtr();
23370   handleDictRef(signal, ref);
23371 }
23372 
23373 void
execDROP_FILE_IMPL_CONF(Signal * signal)23374 Dbdict::execDROP_FILE_IMPL_CONF(Signal* signal)
23375 {
23376   jamEntry();
23377   DropFileImplConf * conf = (DropFileImplConf*)signal->getDataPtr();
23378   handleDictConf(signal, conf);
23379 }
23380 
23381 void
send_drop_file(Signal * signal,Uint32 op_key,Uint32 fileId,DropFileImplReq::RequestInfo type)23382 Dbdict::send_drop_file(Signal* signal, Uint32 op_key, Uint32 fileId,
23383 		       DropFileImplReq::RequestInfo type)
23384 {
23385   DropFileImplReq* req = (DropFileImplReq*)signal->getDataPtrSend();
23386   FilePtr f_ptr;
23387   FilegroupPtr fg_ptr;
23388 
23389   jam();
23390   ndbrequire(find_object(f_ptr, fileId));
23391   ndbrequire(find_object(fg_ptr, f_ptr.p->m_filegroup_id));
23392 
23393   req->senderData = op_key;
23394   req->senderRef = reference();
23395   req->requestInfo = type;
23396 
23397   req->file_id = f_ptr.p->key;
23398   req->filegroup_id = f_ptr.p->m_filegroup_id;
23399   req->filegroup_version = fg_ptr.p->m_version;
23400 
23401   Uint32 ref= 0;
23402   switch(f_ptr.p->m_type){
23403   case DictTabInfo::Datafile:
23404   {
23405     jam();
23406     ref = TSMAN_REF;
23407     break;
23408   }
23409   case DictTabInfo::Undofile:
23410   {
23411     jam();
23412     ref = LGMAN_REF;
23413     break;
23414   }
23415   default:
23416     ndbrequire(false);
23417   }
23418   sendSignal(ref, GSN_DROP_FILE_IMPL_REQ, signal,
23419 	     DropFileImplReq::SignalLength, JBB);
23420 }
23421 
23422 // DropFile: END
23423 
23424 // MODULE: DropFilegroup
23425 
23426 const Dbdict::OpInfo
23427 Dbdict::DropFilegroupRec::g_opInfo = {
23428   { 'D', 'F', 'g', 0 },
23429   ~RT_DBDICT_DROP_FILEGROUP,
23430   GSN_DROP_FILEGROUP_IMPL_REQ,
23431   DropFilegroupImplReq::SignalLength,
23432   //
23433   &Dbdict::dropFilegroup_seize,
23434   &Dbdict::dropFilegroup_release,
23435   //
23436   &Dbdict::dropFilegroup_parse,
23437   &Dbdict::dropFilegroup_subOps,
23438   &Dbdict::dropFilegroup_reply,
23439   //
23440   &Dbdict::dropFilegroup_prepare,
23441   &Dbdict::dropFilegroup_commit,
23442   &Dbdict::dropFilegroup_complete,
23443   //
23444   &Dbdict::dropFilegroup_abortParse,
23445   &Dbdict::dropFilegroup_abortPrepare
23446 };
23447 
23448 void
execDROP_FILEGROUP_REQ(Signal * signal)23449 Dbdict::execDROP_FILEGROUP_REQ(Signal* signal)
23450 {
23451   jamEntry();
23452   if (!assembleFragments(signal)) {
23453     jam();
23454     return;
23455   }
23456   SectionHandle handle(this, signal);
23457 
23458   const DropFilegroupReq req_copy =
23459     *(const DropFilegroupReq*)signal->getDataPtr();
23460   const DropFilegroupReq* req = &req_copy;
23461 
23462   ErrorInfo error;
23463   do {
23464     SchemaOpPtr op_ptr;
23465     DropFilegroupRecPtr dropFilegroupPtr;
23466     DropFilegroupImplReq* impl_req;
23467 
23468     startClientReq(op_ptr, dropFilegroupPtr, req, impl_req, error);
23469     if (hasError(error)) {
23470       jam();
23471       break;
23472     }
23473 
23474     impl_req->filegroup_id = req->filegroup_id;
23475     impl_req->filegroup_version = req->filegroup_version;
23476 
23477     handleClientReq(signal, op_ptr, handle);
23478     return;
23479   } while (0);
23480 
23481   releaseSections(handle);
23482 
23483   DropFilegroupRef* ref = (DropFilegroupRef*)signal->getDataPtrSend();
23484   ref->senderRef = reference();
23485   ref->transId = req->transId;
23486   ref->senderData = req->senderData;
23487   getError(error, ref);
23488 
23489   sendSignal(req->senderRef, GSN_DROP_FILEGROUP_REF, signal,
23490 	     DropFilegroupRef::SignalLength, JBB);
23491 }
23492 
23493 bool
dropFilegroup_seize(SchemaOpPtr op_ptr)23494 Dbdict::dropFilegroup_seize(SchemaOpPtr op_ptr)
23495 {
23496   return seizeOpRec<DropFilegroupRec>(op_ptr);
23497 }
23498 
23499 void
dropFilegroup_release(SchemaOpPtr op_ptr)23500 Dbdict::dropFilegroup_release(SchemaOpPtr op_ptr)
23501 {
23502   releaseOpRec<DropFilegroupRec>(op_ptr);
23503 }
23504 
23505 // DropFilegroup: PARSE
23506 
23507 void
dropFilegroup_parse(Signal * signal,bool master,SchemaOpPtr op_ptr,SectionHandle & handle,ErrorInfo & error)23508 Dbdict::dropFilegroup_parse(Signal* signal, bool master,
23509                           SchemaOpPtr op_ptr,
23510                           SectionHandle& handle, ErrorInfo& error)
23511 {
23512   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23513   DropFilegroupRecPtr dropFilegroupRecPtr;
23514   getOpRec(op_ptr, dropFilegroupRecPtr);
23515   DropFilegroupImplReq* impl_req = &dropFilegroupRecPtr.p->m_request;
23516 
23517   FilegroupPtr fg_ptr;
23518   if (!find_object(fg_ptr, impl_req->filegroup_id))
23519   {
23520     jam();
23521     setError(error, DropFilegroupRef::NoSuchFilegroup, __LINE__);
23522     return;
23523   }
23524 
23525   if (fg_ptr.p->m_version != impl_req->filegroup_version)
23526   {
23527     jam();
23528     setError(error, DropFilegroupRef::InvalidSchemaObjectVersion, __LINE__);
23529     return;
23530   }
23531 
23532   DictObject * obj = c_obj_pool.getPtr(fg_ptr.p->m_obj_ptr_i);
23533   if (obj->m_ref_count)
23534   {
23535     jam();
23536     setError(error, DropFilegroupRef::FilegroupInUse, __LINE__);
23537     return;
23538   }
23539 
23540   if (check_write_obj(impl_req->filegroup_id,
23541                       trans_ptr.p->m_transId,
23542                       SchemaFile::SF_DROP, error))
23543   {
23544     jam();
23545     return;
23546   }
23547 
23548   SchemaFile::TableEntry te; te.init();
23549   te.m_tableState = SchemaFile::SF_DROP;
23550   te.m_transId = trans_ptr.p->m_transId;
23551   Uint32 err = trans_log_schema_op(op_ptr, impl_req->filegroup_id, &te);
23552   if (err)
23553   {
23554     jam();
23555     setError(error, err, __LINE__);
23556     return;
23557   }
23558 
23559 #if defined VM_TRACE || defined ERROR_INSERT
23560   {
23561     char buf[1024];
23562     LocalRope name(c_rope_pool, fg_ptr.p->m_name);
23563     name.copy(buf);
23564     ndbout_c("Dbdict: drop name=%s,id=%u,obj_id=%u", buf,
23565              impl_req->filegroup_id,
23566              fg_ptr.p->m_obj_ptr_i);
23567   }
23568 #endif
23569 }
23570 
23571 void
dropFilegroup_abortParse(Signal * signal,SchemaOpPtr op_ptr)23572 Dbdict::dropFilegroup_abortParse(Signal* signal, SchemaOpPtr op_ptr)
23573 {
23574   jam();
23575   sendTransConf(signal, op_ptr);
23576 }
23577 
23578 bool
dropFilegroup_subOps(Signal * signal,SchemaOpPtr op_ptr)23579 Dbdict::dropFilegroup_subOps(Signal* signal, SchemaOpPtr op_ptr)
23580 {
23581   return false;
23582 }
23583 
23584 void
dropFilegroup_reply(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)23585 Dbdict::dropFilegroup_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
23586 {
23587   jam();
23588   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23589   DropFilegroupRecPtr dropFilegroupRecPtr;
23590   getOpRec(op_ptr, dropFilegroupRecPtr);
23591   DropFilegroupImplReq* impl_req = &dropFilegroupRecPtr.p->m_request;
23592 
23593   if (!hasError(error))
23594   {
23595     jam();
23596     DropFilegroupConf* conf = (DropFilegroupConf*)signal->getDataPtrSend();
23597     conf->senderRef = reference();
23598     conf->senderData = op_ptr.p->m_clientData;
23599     conf->transId = trans_ptr.p->m_transId;
23600     conf->filegroupId = impl_req->filegroup_id;
23601     conf->filegroupVersion = impl_req->filegroup_version;
23602     Uint32 clientRef = op_ptr.p->m_clientRef;
23603     sendSignal(clientRef, GSN_DROP_FILEGROUP_CONF, signal,
23604                DropFilegroupConf::SignalLength, JBB);
23605   }
23606   else
23607   {
23608     jam();
23609     DropFilegroupRef* ref = (DropFilegroupRef*)signal->getDataPtrSend();
23610     ref->senderRef = reference();
23611     ref->senderData = op_ptr.p->m_clientData;
23612     ref->transId = trans_ptr.p->m_transId;
23613     getError(error, ref);
23614 
23615     Uint32 clientRef = op_ptr.p->m_clientRef;
23616     sendSignal(clientRef, GSN_DROP_FILEGROUP_REF, signal,
23617                DropFilegroupRef::SignalLength, JBB);
23618   }
23619 }
23620 
23621 // DropFilegroup: PREPARE
23622 
23623 void
dropFilegroup_prepare(Signal * signal,SchemaOpPtr op_ptr)23624 Dbdict::dropFilegroup_prepare(Signal* signal, SchemaOpPtr op_ptr)
23625 {
23626   jam();
23627   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23628   DropFilegroupRecPtr dropFilegroupRecPtr;
23629   getOpRec(op_ptr, dropFilegroupRecPtr);
23630   DropFilegroupImplReq* impl_req = &dropFilegroupRecPtr.p->m_request;
23631 
23632   Callback c =  {
23633     safe_cast(&Dbdict::dropFilegroup_fromLocal), op_ptr.p->op_key
23634   };
23635   op_ptr.p->m_callback = c;
23636 
23637   send_drop_fg(signal, op_ptr.p->op_key, impl_req->filegroup_id,
23638                DropFilegroupImplReq::Prepare);
23639 
23640   FilegroupPtr fg_ptr;
23641   ndbrequire(find_object(fg_ptr, impl_req->filegroup_id));
23642 
23643   if (fg_ptr.p->m_type == DictTabInfo::LogfileGroup)
23644   {
23645     XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
23646     FilePtr filePtr;
23647     Local_file_list list(c_file_pool, fg_ptr.p->m_logfilegroup.m_files);
23648     for(list.first(filePtr); !filePtr.isNull(); list.next(filePtr))
23649     {
23650       jam();
23651 
23652       DictObjectPtr objPtr;
23653       c_obj_pool.getPtr(objPtr, filePtr.p->m_obj_ptr_i);
23654       SchemaFile::TableEntry * entry = getTableEntry(xsf, objPtr.p->m_id);
23655       entry->m_tableState = SchemaFile::SF_DROP;
23656       entry->m_transId = trans_ptr.p->m_transId;
23657     }
23658   }
23659 }
23660 
23661 void
dropFilegroup_abortPrepare(Signal * signal,SchemaOpPtr op_ptr)23662 Dbdict::dropFilegroup_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
23663 {
23664   ndbrequire(false);
23665   DropFilegroupRecPtr dropFilegroupPtr;
23666   getOpRec(op_ptr, dropFilegroupPtr);
23667   DropFilegroupImplReq* impl_req = &dropFilegroupPtr.p->m_request;
23668 
23669   Callback c =  {
23670     safe_cast(&Dbdict::dropFilegroup_fromLocal), op_ptr.p->op_key
23671   };
23672   op_ptr.p->m_callback = c;
23673 
23674   send_drop_fg(signal, op_ptr.p->op_key, impl_req->filegroup_id,
23675                DropFilegroupImplReq::Abort);
23676 
23677   FilegroupPtr fg_ptr;
23678   ndbrequire(find_object(fg_ptr, impl_req->filegroup_id));
23679 
23680   if (fg_ptr.p->m_type == DictTabInfo::LogfileGroup)
23681   {
23682     jam();
23683     XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
23684     FilePtr filePtr;
23685     Local_file_list list(c_file_pool, fg_ptr.p->m_logfilegroup.m_files);
23686     for(list.first(filePtr); !filePtr.isNull(); list.next(filePtr))
23687     {
23688       jam();
23689 
23690       DictObjectPtr objPtr;
23691       c_obj_pool.getPtr(objPtr, filePtr.p->m_obj_ptr_i);
23692       SchemaFile::TableEntry * entry = getTableEntry(xsf, objPtr.p->m_id);
23693       entry->m_tableState = SchemaFile::SF_IN_USE;
23694       entry->m_transId = 0;
23695     }
23696   }
23697 }
23698 
23699 // DropFilegroup: COMMIT
23700 
23701 void
dropFilegroup_commit(Signal * signal,SchemaOpPtr op_ptr)23702 Dbdict::dropFilegroup_commit(Signal* signal, SchemaOpPtr op_ptr)
23703 {
23704   jam();
23705   DropFilegroupRecPtr dropFilegroupRecPtr;
23706   getOpRec(op_ptr, dropFilegroupRecPtr);
23707   DropFilegroupImplReq* impl_req = &dropFilegroupRecPtr.p->m_request;
23708 
23709   Callback c =  {
23710     safe_cast(&Dbdict::dropFilegroup_fromLocal), op_ptr.p->op_key
23711   };
23712   op_ptr.p->m_callback = c;
23713 
23714   send_drop_fg(signal, op_ptr.p->op_key, impl_req->filegroup_id,
23715                DropFilegroupImplReq::Commit);
23716 
23717   FilegroupPtr fg_ptr;
23718   ndbrequire(find_object(fg_ptr, impl_req->filegroup_id));
23719 
23720   if (fg_ptr.p->m_type == DictTabInfo::LogfileGroup)
23721   {
23722     jam();
23723     /**
23724      * Mark all undofiles as dropped
23725      */
23726     XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
23727 
23728     FilePtr filePtr;
23729     Local_file_list list(c_file_pool, fg_ptr.p->m_logfilegroup.m_files);
23730     for(list.first(filePtr); !filePtr.isNull(); list.next(filePtr))
23731     {
23732       jam();
23733 
23734       DictObjectPtr objPtr;
23735       c_obj_pool.getPtr(objPtr, filePtr.p->m_obj_ptr_i);
23736       SchemaFile::TableEntry * entry = getTableEntry(xsf, objPtr.p->m_id);
23737       entry->m_tableState = SchemaFile::SF_UNUSED;
23738       entry->m_transId = 0;
23739 
23740       release_object(objPtr.i, objPtr.p);
23741     }
23742     while (list.releaseFirst());
23743   }
23744   else if(fg_ptr.p->m_type == DictTabInfo::Tablespace)
23745   {
23746     jam();
23747     FilegroupPtr lg_ptr;
23748     ndbrequire(find_object(lg_ptr,
23749 		    fg_ptr.p->m_tablespace.m_default_logfile_group_id));
23750 
23751     decrease_ref_count(lg_ptr.p->m_obj_ptr_i);
23752   }
23753 }
23754 
23755 // DropFilegroup: COMPLETE
23756 
23757 void
dropFilegroup_complete(Signal * signal,SchemaOpPtr op_ptr)23758 Dbdict::dropFilegroup_complete(Signal* signal, SchemaOpPtr op_ptr)
23759 {
23760   jam();
23761 
23762   DropFilegroupRecPtr dropFilegroupRecPtr;
23763   getOpRec(op_ptr, dropFilegroupRecPtr);
23764   DropFilegroupImplReq* impl_req = &dropFilegroupRecPtr.p->m_request;
23765 
23766   FilegroupPtr fg_ptr;
23767   ndbrequire(find_object(fg_ptr, impl_req->filegroup_id));
23768 
23769   release_object(fg_ptr.p->m_obj_ptr_i);
23770   c_filegroup_pool.release(fg_ptr);
23771 
23772   sendTransConf(signal, op_ptr);
23773 }
23774 
23775 void
dropFilegroup_fromLocal(Signal * signal,Uint32 op_key,Uint32 ret)23776 Dbdict::dropFilegroup_fromLocal(Signal* signal, Uint32 op_key, Uint32 ret)
23777 {
23778   jam();
23779   SchemaOpPtr op_ptr;
23780   DropFilegroupRecPtr dropFilegroupPtr;
23781   ndbrequire(findSchemaOp(op_ptr, dropFilegroupPtr, op_key));
23782 
23783   if (ret == 0)
23784   {
23785     jam();
23786     sendTransConf(signal, op_ptr);
23787   }
23788   else
23789   {
23790     jam();
23791     setError(op_ptr, ret, __LINE__);
23792     sendTransRef(signal, op_ptr);
23793   }
23794 }
23795 
23796 void
execDROP_FILEGROUP_IMPL_REF(Signal * signal)23797 Dbdict::execDROP_FILEGROUP_IMPL_REF(Signal* signal)
23798 {
23799   jamEntry();
23800   DropFilegroupImplRef * ref = (DropFilegroupImplRef*)signal->getDataPtr();
23801   handleDictRef(signal, ref);
23802 }
23803 
23804 void
execDROP_FILEGROUP_IMPL_CONF(Signal * signal)23805 Dbdict::execDROP_FILEGROUP_IMPL_CONF(Signal* signal)
23806 {
23807   jamEntry();
23808   DropFilegroupImplConf * conf = (DropFilegroupImplConf*)signal->getDataPtr();
23809   handleDictConf(signal, conf);
23810 }
23811 
23812 
23813 void
send_drop_fg(Signal * signal,Uint32 op_key,Uint32 filegroupId,DropFilegroupImplReq::RequestInfo type)23814 Dbdict::send_drop_fg(Signal* signal, Uint32 op_key, Uint32 filegroupId,
23815 		     DropFilegroupImplReq::RequestInfo type)
23816 {
23817   DropFilegroupImplReq* req = (DropFilegroupImplReq*)signal->getDataPtrSend();
23818 
23819   FilegroupPtr fg_ptr;
23820   ndbrequire(find_object(fg_ptr, filegroupId));
23821 
23822   req->senderData = op_key;
23823   req->senderRef = reference();
23824   req->requestInfo = type;
23825 
23826   req->filegroup_id = fg_ptr.p->key;
23827   req->filegroup_version = fg_ptr.p->m_version;
23828 
23829   Uint32 ref= 0;
23830   switch(fg_ptr.p->m_type){
23831   case DictTabInfo::Tablespace:
23832     ref = TSMAN_REF;
23833     break;
23834   case DictTabInfo::LogfileGroup:
23835     ref = LGMAN_REF;
23836     break;
23837   default:
23838     ndbrequire(false);
23839   }
23840 
23841   sendSignal(ref, GSN_DROP_FILEGROUP_IMPL_REQ, signal,
23842 	     DropFilegroupImplReq::SignalLength, JBB);
23843 }
23844 
23845 // DropFilegroup: END
23846 
23847 // MODULE: CreateNodegroup
23848 
23849 const Dbdict::OpInfo
23850 Dbdict::CreateNodegroupRec::g_opInfo = {
23851   { 'C', 'N', 'G', 0 },
23852   ~RT_DBDICT_CREATE_NODEGROUP,
23853   GSN_CREATE_NODEGROUP_IMPL_REQ,
23854   CreateNodegroupImplReq::SignalLength,
23855   //
23856   &Dbdict::createNodegroup_seize,
23857   &Dbdict::createNodegroup_release,
23858   //
23859   &Dbdict::createNodegroup_parse,
23860   &Dbdict::createNodegroup_subOps,
23861   &Dbdict::createNodegroup_reply,
23862   //
23863   &Dbdict::createNodegroup_prepare,
23864   &Dbdict::createNodegroup_commit,
23865   &Dbdict::createNodegroup_complete,
23866   //
23867   &Dbdict::createNodegroup_abortParse,
23868   &Dbdict::createNodegroup_abortPrepare
23869 };
23870 
23871 void
execCREATE_NODEGROUP_REQ(Signal * signal)23872 Dbdict::execCREATE_NODEGROUP_REQ(Signal* signal)
23873 {
23874   jamEntry();
23875   if (!assembleFragments(signal)) {
23876     jam();
23877     return;
23878   }
23879   SectionHandle handle(this, signal);
23880 
23881   const CreateNodegroupReq req_copy =
23882     *(const CreateNodegroupReq*)signal->getDataPtr();
23883   const CreateNodegroupReq* req = &req_copy;
23884 
23885   ErrorInfo error;
23886   do {
23887     SchemaOpPtr op_ptr;
23888     CreateNodegroupRecPtr createNodegroupRecPtr;
23889     CreateNodegroupImplReq* impl_req;
23890 
23891     startClientReq(op_ptr, createNodegroupRecPtr, req, impl_req, error);
23892     if (hasError(error)) {
23893       jam();
23894       break;
23895     }
23896 
23897     impl_req->nodegroupId = req->nodegroupId;
23898     for (Uint32 i = 0; i<NDB_ARRAY_SIZE(req->nodes) &&
23899            i<NDB_ARRAY_SIZE(impl_req->nodes); i++)
23900     {
23901       impl_req->nodes[i] = req->nodes[i];
23902     }
23903 
23904     handleClientReq(signal, op_ptr, handle);
23905     return;
23906   } while (0);
23907 
23908   releaseSections(handle);
23909 
23910   CreateNodegroupRef* ref = (CreateNodegroupRef*)signal->getDataPtrSend();
23911   ref->senderRef = reference();
23912   ref->transId = req->transId;
23913   ref->senderData = req->senderData;
23914   getError(error, ref);
23915 
23916   sendSignal(req->senderRef, GSN_CREATE_NODEGROUP_REF, signal,
23917 	     CreateNodegroupRef::SignalLength, JBB);
23918 }
23919 
23920 bool
createNodegroup_seize(SchemaOpPtr op_ptr)23921 Dbdict::createNodegroup_seize(SchemaOpPtr op_ptr)
23922 {
23923   return seizeOpRec<CreateNodegroupRec>(op_ptr);
23924 }
23925 
23926 void
createNodegroup_release(SchemaOpPtr op_ptr)23927 Dbdict::createNodegroup_release(SchemaOpPtr op_ptr)
23928 {
23929   releaseOpRec<CreateNodegroupRec>(op_ptr);
23930 }
23931 
23932 // CreateNodegroup: PARSE
23933 
23934 void
createNodegroup_parse(Signal * signal,bool master,SchemaOpPtr op_ptr,SectionHandle & handle,ErrorInfo & error)23935 Dbdict::createNodegroup_parse(Signal* signal, bool master,
23936                               SchemaOpPtr op_ptr,
23937                               SectionHandle& handle, ErrorInfo& error)
23938 {
23939   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23940   CreateNodegroupRecPtr createNodegroupRecPtr;
23941   getOpRec(op_ptr, createNodegroupRecPtr);
23942   CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
23943 
23944   jam();
23945 
23946   Uint32 save = impl_req->requestType;
23947   impl_req->requestType = CreateNodegroupImplReq::RT_PARSE;
23948   memcpy(signal->theData, impl_req, 4*CreateNodegroupImplReq::SignalLength);
23949   impl_req->requestType = save;
23950 
23951   EXECUTE_DIRECT(DBDIH, GSN_CREATE_NODEGROUP_IMPL_REQ, signal,
23952                  CreateNodegroupImplReq::SignalLength);
23953   jamEntry();
23954 
23955   Uint32 ret = signal->theData[0];
23956   if (ret)
23957   {
23958     jam();
23959     setError(error, ret, __LINE__);
23960     return ;
23961   }
23962 
23963   impl_req->senderRef = reference();
23964   impl_req->senderData = op_ptr.p->op_key;
23965   impl_req->nodegroupId = signal->theData[1];
23966 
23967   /**
23968    * createNodegroup blocks gcp
23969    *   so trans_ptr can *not* do this (endless loop)
23970    */
23971   trans_ptr.p->m_wait_gcp_on_commit = false;
23972 }
23973 
23974 void
createNodegroup_abortParse(Signal * signal,SchemaOpPtr op_ptr)23975 Dbdict::createNodegroup_abortParse(Signal* signal, SchemaOpPtr op_ptr)
23976 {
23977   jam();
23978   sendTransConf(signal, op_ptr);
23979 }
23980 
23981 bool
createNodegroup_subOps(Signal * signal,SchemaOpPtr op_ptr)23982 Dbdict::createNodegroup_subOps(Signal* signal, SchemaOpPtr op_ptr)
23983 {
23984   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23985   CreateNodegroupRecPtr createNodegroupRecPtr;
23986   getOpRec(op_ptr, createNodegroupRecPtr);
23987   //CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
23988 
23989   if (createNodegroupRecPtr.p->m_map_created == false)
23990   {
23991     jam();
23992     createNodegroupRecPtr.p->m_map_created = true;
23993 
23994     /**
23995      * This is a bit cheating...
23996      *   it would be better to handle "object-exists"
23997      *   and still continue transaction
23998      *   but that i dont know how
23999      */
24000     Uint32 buckets = c_default_hashmap_size;
24001     Uint32 fragments = get_default_fragments(signal, 1);
24002     char buf[MAX_TAB_NAME_SIZE+1];
24003     BaseString::snprintf(buf, sizeof(buf), "DEFAULT-HASHMAP-%u-%u",
24004                          buckets,
24005                          fragments);
24006 
24007     if (get_object(buf) != 0)
24008     {
24009       jam();
24010       return false;
24011     }
24012 
24013 
24014     Callback c = {
24015       safe_cast(&Dbdict::createNodegroup_fromCreateHashMap),
24016       op_ptr.p->op_key
24017     };
24018     op_ptr.p->m_callback = c;
24019 
24020     CreateHashMapReq* const req = (CreateHashMapReq*)signal->getDataPtrSend();
24021     req->clientRef = reference();
24022     req->clientData = op_ptr.p->op_key;
24023     req->requestInfo = 0;
24024     req->transId = trans_ptr.p->m_transId;
24025     req->transKey = trans_ptr.p->trans_key;
24026     req->buckets = buckets;
24027     req->fragments = fragments;
24028     sendSignal(DBDICT_REF, GSN_CREATE_HASH_MAP_REQ, signal,
24029                CreateHashMapReq::SignalLength, JBB);
24030     return true;
24031   }
24032 
24033   return false;
24034 }
24035 
24036 void
createNodegroup_fromCreateHashMap(Signal * signal,Uint32 op_key,Uint32 ret)24037 Dbdict::createNodegroup_fromCreateHashMap(Signal* signal,
24038                                           Uint32 op_key,
24039                                           Uint32 ret)
24040 {
24041   SchemaOpPtr op_ptr;
24042   CreateNodegroupRecPtr createNodegroupRecPtr;
24043   findSchemaOp(op_ptr, createNodegroupRecPtr, op_key);
24044   ndbrequire(!op_ptr.isNull());
24045 
24046   if (ret == 0)
24047   {
24048     jam();
24049     createSubOps(signal, op_ptr);
24050   }
24051   else
24052   {
24053     jam();
24054     const CreateHashMapRef* ref = (const CreateHashMapRef*)signal->getDataPtr();
24055 
24056     ErrorInfo error;
24057     setError(error, ref);
24058     abortSubOps(signal, op_ptr, error);
24059   }
24060 }
24061 
24062 void
createNodegroup_reply(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)24063 Dbdict::createNodegroup_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
24064 {
24065   jam();
24066   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
24067   CreateNodegroupRecPtr createNodegroupRecPtr;
24068   getOpRec(op_ptr, createNodegroupRecPtr);
24069   CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
24070 
24071   if (!hasError(error))
24072   {
24073     jam();
24074     CreateNodegroupConf* conf = (CreateNodegroupConf*)signal->getDataPtrSend();
24075     conf->senderRef = reference();
24076     conf->senderData = op_ptr.p->m_clientData;
24077     conf->transId = trans_ptr.p->m_transId;
24078     conf->nodegroupId = impl_req->nodegroupId;
24079     Uint32 clientRef = op_ptr.p->m_clientRef;
24080     sendSignal(clientRef, GSN_CREATE_NODEGROUP_CONF, signal,
24081                CreateNodegroupConf::SignalLength, JBB);
24082   }
24083   else
24084   {
24085     jam();
24086     CreateNodegroupRef* ref = (CreateNodegroupRef*)signal->getDataPtrSend();
24087     ref->senderRef = reference();
24088     ref->senderData = op_ptr.p->m_clientData;
24089     ref->transId = trans_ptr.p->m_transId;
24090     getError(error, ref);
24091 
24092     Uint32 clientRef = op_ptr.p->m_clientRef;
24093     sendSignal(clientRef, GSN_CREATE_NODEGROUP_REF, signal,
24094                CreateNodegroupRef::SignalLength, JBB);
24095   }
24096 }
24097 
24098 // CreateNodegroup: PREPARE
24099 
24100 void
createNodegroup_prepare(Signal * signal,SchemaOpPtr op_ptr)24101 Dbdict::createNodegroup_prepare(Signal* signal, SchemaOpPtr op_ptr)
24102 {
24103   jam();
24104   CreateNodegroupRecPtr createNodegroupRecPtr;
24105   getOpRec(op_ptr, createNodegroupRecPtr);
24106   CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
24107 
24108   impl_req->requestType = CreateNodegroupImplReq::RT_PREPARE;
24109   createNodegroupRecPtr.p->m_blockCnt = 2;
24110   createNodegroupRecPtr.p->m_blockIndex = 0;
24111   createNodegroupRecPtr.p->m_blockNo[0] = DBDIH_REF;
24112   createNodegroupRecPtr.p->m_blockNo[1] = SUMA_REF;
24113 
24114   Callback c = {
24115     safe_cast(&Dbdict::createNodegroup_fromBlockSubStartStop),
24116     op_ptr.p->op_key
24117   };
24118   op_ptr.p->m_callback = c;
24119 
24120   block_substartstop(signal, op_ptr);
24121 }
24122 
24123 void
createNodegroup_fromBlockSubStartStop(Signal * signal,Uint32 op_key,Uint32 ret)24124 Dbdict::createNodegroup_fromBlockSubStartStop(Signal* signal,
24125                                               Uint32 op_key,
24126                                               Uint32 ret)
24127 {
24128   SchemaOpPtr op_ptr;
24129   CreateNodegroupRecPtr createNodegroupRecPtr;
24130   findSchemaOp(op_ptr, createNodegroupRecPtr, op_key);
24131   ndbrequire(!op_ptr.isNull());
24132   //CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
24133 
24134   if (ret == 0)
24135   {
24136     jam();
24137     createNodegroupRecPtr.p->m_substartstop_blocked = true;
24138     createNodegroup_toLocal(signal, op_ptr);
24139   }
24140   else
24141   {
24142     jam();
24143     setError(op_ptr, ret, __LINE__);
24144     sendTransRef(signal, op_ptr);
24145   }
24146 }
24147 
24148 void
createNodegroup_toLocal(Signal * signal,SchemaOpPtr op_ptr)24149 Dbdict::createNodegroup_toLocal(Signal* signal, SchemaOpPtr op_ptr)
24150 {
24151   CreateNodegroupRecPtr createNodegroupRecPtr;
24152   getOpRec(op_ptr, createNodegroupRecPtr);
24153   CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
24154 
24155   const Uint32 blockIndex = createNodegroupRecPtr.p->m_blockIndex;
24156   if (blockIndex == createNodegroupRecPtr.p->m_blockCnt)
24157   {
24158     jam();
24159 
24160     if (op_ptr.p->m_state == SchemaOp::OS_PREPARING)
24161     {
24162       jam();
24163 
24164       /**
24165        * Block GCP as last part of prepare
24166        */
24167       Callback c = {
24168         safe_cast(&Dbdict::createNodegroup_fromWaitGCP),
24169         op_ptr.p->op_key
24170       };
24171       op_ptr.p->m_callback = c;
24172 
24173       createNodegroupRecPtr.p->m_cnt_waitGCP = 0;
24174       createNodegroupRecPtr.p->m_wait_gcp_type = WaitGCPReq::BlockStartGcp;
24175       wait_gcp(signal, op_ptr, WaitGCPReq::BlockStartGcp);
24176       return;
24177     }
24178 
24179     if (op_ptr.p->m_state == SchemaOp::OS_COMPLETING)
24180     {
24181       jam();
24182       /**
24183        * Unblock GCP as last step of complete
24184        */
24185       Callback c = {
24186         safe_cast(&Dbdict::createNodegroup_fromWaitGCP),
24187         op_ptr.p->op_key
24188       };
24189       op_ptr.p->m_callback = c;
24190 
24191       createNodegroupRecPtr.p->m_cnt_waitGCP = 0;
24192       createNodegroupRecPtr.p->m_wait_gcp_type = WaitGCPReq::UnblockStartGcp;
24193       wait_gcp(signal, op_ptr, WaitGCPReq::UnblockStartGcp);
24194       return;
24195     }
24196 
24197     sendTransConf(signal, op_ptr);
24198     return;
24199   }
24200 
24201   Callback c = {
24202     safe_cast(&Dbdict::createNodegroup_fromLocal),
24203     op_ptr.p->op_key
24204   };
24205   op_ptr.p->m_callback = c;
24206 
24207   Uint32 ref = createNodegroupRecPtr.p->m_blockNo[blockIndex];
24208   CreateNodegroupImplReq * req = (CreateNodegroupImplReq*)signal->getDataPtrSend();
24209   memcpy(req, impl_req, 4*CreateNodegroupImplReq::SignalLength);
24210   sendSignal(ref, GSN_CREATE_NODEGROUP_IMPL_REQ, signal,
24211              CreateNodegroupImplReq::SignalLength, JBB);
24212 }
24213 
24214 void
createNodegroup_fromLocal(Signal * signal,Uint32 op_key,Uint32 ret)24215 Dbdict::createNodegroup_fromLocal(Signal* signal,
24216                                   Uint32 op_key,
24217                                   Uint32 ret)
24218 {
24219   SchemaOpPtr op_ptr;
24220   CreateNodegroupRecPtr createNodegroupRecPtr;
24221   findSchemaOp(op_ptr, createNodegroupRecPtr, op_key);
24222   ndbrequire(!op_ptr.isNull());
24223   CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
24224 
24225   Uint32 blockIndex = createNodegroupRecPtr.p->m_blockIndex;
24226   ndbrequire(blockIndex < createNodegroupRecPtr.p->m_blockCnt);
24227   if (ret)
24228   {
24229     jam();
24230     setError(op_ptr, ret, __LINE__);
24231     sendTransRef(signal, op_ptr);
24232     return;
24233   }
24234 
24235   Uint32 idx = createNodegroupRecPtr.p->m_blockIndex;
24236   if (op_ptr.p->m_state == SchemaOp::OS_COMPLETING &&
24237       createNodegroupRecPtr.p->m_blockNo[idx] == DBDIH_REF)
24238   {
24239     jam();
24240 
24241     CreateNodegroupImplConf * conf =
24242       (CreateNodegroupImplConf*)signal->getDataPtr();
24243     impl_req->gci_hi = conf->gci_hi;
24244     impl_req->gci_lo = conf->gci_lo;
24245   }
24246 
24247   createNodegroupRecPtr.p->m_blockIndex++;
24248   createNodegroup_toLocal(signal, op_ptr);
24249 }
24250 
24251 void
createNodegroup_abortPrepare(Signal * signal,SchemaOpPtr op_ptr)24252 Dbdict::createNodegroup_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
24253 {
24254   CreateNodegroupRecPtr createNodegroupRecPtr;
24255   getOpRec(op_ptr, createNodegroupRecPtr);
24256   //CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
24257 
24258   if (createNodegroupRecPtr.p->m_substartstop_blocked)
24259   {
24260     jam();
24261     unblock_substartstop();
24262   }
24263 
24264   if (createNodegroupRecPtr.p->m_gcp_blocked)
24265   {
24266     jam();
24267 
24268     Callback c = {
24269       safe_cast(&Dbdict::createNodegroup_fromWaitGCP),
24270       op_ptr.p->op_key
24271     };
24272     op_ptr.p->m_callback = c;
24273 
24274     createNodegroupRecPtr.p->m_cnt_waitGCP = 0;
24275     createNodegroupRecPtr.p->m_wait_gcp_type = WaitGCPReq::UnblockStartGcp;
24276     wait_gcp(signal, op_ptr, WaitGCPReq::UnblockStartGcp);
24277     return;
24278   }
24279 
24280   sendTransConf(signal, op_ptr);
24281 }
24282 
24283 // CreateNodegroup: COMMIT
24284 
24285 void
createNodegroup_commit(Signal * signal,SchemaOpPtr op_ptr)24286 Dbdict::createNodegroup_commit(Signal* signal, SchemaOpPtr op_ptr)
24287 {
24288   jam();
24289   CreateNodegroupRecPtr createNodegroupRecPtr;
24290   getOpRec(op_ptr, createNodegroupRecPtr);
24291   CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
24292 
24293   impl_req->requestType = CreateNodegroupImplReq::RT_COMMIT;
24294   createNodegroupRecPtr.p->m_blockCnt = 2;
24295   createNodegroupRecPtr.p->m_blockIndex = 0;
24296   createNodegroupRecPtr.p->m_blockNo[0] = DBDIH_REF;
24297   createNodegroupRecPtr.p->m_blockNo[1] = NDBCNTR_REF;
24298 
24299   Callback c = {
24300     safe_cast(&Dbdict::createNodegroup_fromWaitGCP),
24301     op_ptr.p->op_key
24302   };
24303   op_ptr.p->m_callback = c;
24304 
24305   createNodegroupRecPtr.p->m_cnt_waitGCP = 0;
24306   createNodegroupRecPtr.p->m_wait_gcp_type = WaitGCPReq::WaitEpoch;
24307   wait_gcp(signal, op_ptr, WaitGCPReq::WaitEpoch);
24308 }
24309 
24310 void
createNodegroup_fromWaitGCP(Signal * signal,Uint32 op_key,Uint32 ret)24311 Dbdict::createNodegroup_fromWaitGCP(Signal* signal,
24312                                     Uint32 op_key,
24313                                     Uint32 ret)
24314 {
24315   jam();
24316   SchemaOpPtr op_ptr;
24317   CreateNodegroupRecPtr createNodegroupRecPtr;
24318   findSchemaOp(op_ptr, createNodegroupRecPtr, op_key);
24319   ndbrequire(!op_ptr.isNull());
24320 
24321   //CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
24322 
24323   if (ret == 0)
24324   {
24325     jam();
24326 
24327     Uint32 wait_type = createNodegroupRecPtr.p->m_wait_gcp_type;
24328     if (op_ptr.p->m_state == SchemaOp::OS_ABORTED_PREPARE)
24329     {
24330       jam();
24331       ndbrequire(wait_type == WaitGCPReq::UnblockStartGcp);
24332       sendTransConf(signal, op_ptr);
24333       return;
24334     }
24335     else if (op_ptr.p->m_state == SchemaOp::OS_PREPARING)
24336     {
24337       jam();
24338       ndbrequire(wait_type == WaitGCPReq::BlockStartGcp);
24339       createNodegroupRecPtr.p->m_gcp_blocked = true;
24340       sendTransConf(signal, op_ptr);
24341       return;
24342     }
24343     else if (op_ptr.p->m_state == SchemaOp::OS_COMMITTING)
24344     {
24345       jam();
24346       ndbrequire(wait_type == WaitGCPReq::WaitEpoch);
24347       createNodegroup_toLocal(signal, op_ptr);
24348       return;
24349     }
24350     else
24351     {
24352       jam();
24353       ndbrequire(op_ptr.p->m_state == SchemaOp::OS_COMPLETING);
24354 
24355       if (wait_type == WaitGCPReq::UnblockStartGcp)
24356       {
24357         jam();
24358         wait_type = WaitGCPReq::CompleteForceStart;
24359         createNodegroupRecPtr.p->m_wait_gcp_type = wait_type;
24360         goto retry;
24361       }
24362       else
24363       {
24364         jam();
24365         ndbrequire(wait_type == WaitGCPReq::CompleteForceStart);
24366         unblock_substartstop();
24367       }
24368 
24369       sendTransConf(signal, op_ptr);
24370       return;
24371     }
24372   }
24373 
24374   createNodegroupRecPtr.p->m_cnt_waitGCP++;
24375   switch(ret){
24376   case WaitGCPRef::NoWaitGCPRecords:
24377     jam();
24378   case WaitGCPRef::NF_CausedAbortOfProcedure:
24379     jam();
24380   case WaitGCPRef::NF_MasterTakeOverInProgress:
24381     jam();
24382   }
24383 
24384 retry:
24385   wait_gcp(signal, op_ptr, createNodegroupRecPtr.p->m_wait_gcp_type);
24386 }
24387 
24388 // CreateNodegroup: COMPLETE
24389 
24390 void
createNodegroup_complete(Signal * signal,SchemaOpPtr op_ptr)24391 Dbdict::createNodegroup_complete(Signal* signal, SchemaOpPtr op_ptr)
24392 {
24393   jam();
24394   CreateNodegroupRecPtr createNodegroupRecPtr;
24395   getOpRec(op_ptr, createNodegroupRecPtr);
24396   CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
24397 
24398   impl_req->requestType = CreateNodegroupImplReq::RT_COMPLETE;
24399   createNodegroupRecPtr.p->m_blockCnt = 2;
24400   createNodegroupRecPtr.p->m_blockIndex = 0;
24401   createNodegroupRecPtr.p->m_blockNo[0] = DBDIH_REF;
24402   createNodegroupRecPtr.p->m_blockNo[1] = SUMA_REF;
24403 
24404   createNodegroup_toLocal(signal, op_ptr);
24405 }
24406 
24407 void
execCREATE_NODEGROUP_IMPL_REF(Signal * signal)24408 Dbdict::execCREATE_NODEGROUP_IMPL_REF(Signal* signal)
24409 {
24410   jamEntry();
24411   CreateNodegroupImplRef * ref = (CreateNodegroupImplRef*)signal->getDataPtr();
24412   handleDictRef(signal, ref);
24413 }
24414 
24415 void
execCREATE_NODEGROUP_IMPL_CONF(Signal * signal)24416 Dbdict::execCREATE_NODEGROUP_IMPL_CONF(Signal* signal)
24417 {
24418   jamEntry();
24419   CreateNodegroupImplConf * conf = (CreateNodegroupImplConf*)signal->getDataPtr();
24420   handleDictConf(signal, conf);
24421 }
24422 
24423 void
execCREATE_HASH_MAP_REF(Signal * signal)24424 Dbdict::execCREATE_HASH_MAP_REF(Signal* signal)
24425 {
24426   jamEntry();
24427   CreateHashMapRef * ref = (CreateHashMapRef*)signal->getDataPtr();
24428   handleDictRef(signal, ref);
24429 }
24430 
24431 void
execCREATE_HASH_MAP_CONF(Signal * signal)24432 Dbdict::execCREATE_HASH_MAP_CONF(Signal* signal)
24433 {
24434   jamEntry();
24435   CreateHashMapConf * conf = (CreateHashMapConf*)signal->getDataPtr();
24436   handleDictConf(signal, conf);
24437 }
24438 
24439 // CreateNodegroup: END
24440 
24441 // MODULE: DropNodegroup
24442 
24443 const Dbdict::OpInfo
24444 Dbdict::DropNodegroupRec::g_opInfo = {
24445   { 'D', 'N', 'G', 0 },
24446   ~RT_DBDICT_DROP_NODEGROUP,
24447   GSN_DROP_NODEGROUP_IMPL_REQ,
24448   DropNodegroupImplReq::SignalLength,
24449   //
24450   &Dbdict::dropNodegroup_seize,
24451   &Dbdict::dropNodegroup_release,
24452   //
24453   &Dbdict::dropNodegroup_parse,
24454   &Dbdict::dropNodegroup_subOps,
24455   &Dbdict::dropNodegroup_reply,
24456   //
24457   &Dbdict::dropNodegroup_prepare,
24458   &Dbdict::dropNodegroup_commit,
24459   &Dbdict::dropNodegroup_complete,
24460   //
24461   &Dbdict::dropNodegroup_abortParse,
24462   &Dbdict::dropNodegroup_abortPrepare
24463 };
24464 
24465 void
execDROP_NODEGROUP_REQ(Signal * signal)24466 Dbdict::execDROP_NODEGROUP_REQ(Signal* signal)
24467 {
24468   jamEntry();
24469   if (!assembleFragments(signal)) {
24470     jam();
24471     return;
24472   }
24473   SectionHandle handle(this, signal);
24474 
24475   const DropNodegroupReq req_copy =
24476     *(const DropNodegroupReq*)signal->getDataPtr();
24477   const DropNodegroupReq* req = &req_copy;
24478 
24479   ErrorInfo error;
24480   do {
24481     SchemaOpPtr op_ptr;
24482     DropNodegroupRecPtr dropNodegroupRecPtr;
24483     DropNodegroupImplReq* impl_req;
24484 
24485     startClientReq(op_ptr, dropNodegroupRecPtr, req, impl_req, error);
24486     if (hasError(error)) {
24487       jam();
24488       break;
24489     }
24490 
24491     impl_req->nodegroupId = req->nodegroupId;
24492 
24493     handleClientReq(signal, op_ptr, handle);
24494     return;
24495   } while (0);
24496 
24497   releaseSections(handle);
24498 
24499   DropNodegroupRef* ref = (DropNodegroupRef*)signal->getDataPtrSend();
24500   ref->senderRef = reference();
24501   ref->transId = req->transId;
24502   ref->senderData = req->senderData;
24503   getError(error, ref);
24504 
24505   sendSignal(req->senderRef, GSN_DROP_NODEGROUP_REF, signal,
24506 	     DropNodegroupRef::SignalLength, JBB);
24507 }
24508 
24509 bool
dropNodegroup_seize(SchemaOpPtr op_ptr)24510 Dbdict::dropNodegroup_seize(SchemaOpPtr op_ptr)
24511 {
24512   return seizeOpRec<DropNodegroupRec>(op_ptr);
24513 }
24514 
24515 void
dropNodegroup_release(SchemaOpPtr op_ptr)24516 Dbdict::dropNodegroup_release(SchemaOpPtr op_ptr)
24517 {
24518   releaseOpRec<DropNodegroupRec>(op_ptr);
24519 }
24520 
24521 // DropNodegroup: PARSE
24522 
24523 void
dropNodegroup_parse(Signal * signal,bool master,SchemaOpPtr op_ptr,SectionHandle & handle,ErrorInfo & error)24524 Dbdict::dropNodegroup_parse(Signal* signal, bool master,
24525                           SchemaOpPtr op_ptr,
24526                           SectionHandle& handle, ErrorInfo& error)
24527 {
24528   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
24529   DropNodegroupRecPtr dropNodegroupRecPtr;
24530   getOpRec(op_ptr, dropNodegroupRecPtr);
24531   DropNodegroupImplReq* impl_req = &dropNodegroupRecPtr.p->m_request;
24532 
24533   impl_req->senderRef = reference();
24534   impl_req->senderData = op_ptr.p->op_key;
24535 
24536   /**
24537    * dropNodegroup blocks gcp
24538    *   so trans_ptr can *not* do this (endless loop)
24539    */
24540   trans_ptr.p->m_wait_gcp_on_commit = false;
24541 }
24542 
24543 void
dropNodegroup_abortParse(Signal * signal,SchemaOpPtr op_ptr)24544 Dbdict::dropNodegroup_abortParse(Signal* signal, SchemaOpPtr op_ptr)
24545 {
24546   jam();
24547   sendTransConf(signal, op_ptr);
24548 }
24549 
24550 bool
dropNodegroup_subOps(Signal * signal,SchemaOpPtr op_ptr)24551 Dbdict::dropNodegroup_subOps(Signal* signal, SchemaOpPtr op_ptr)
24552 {
24553   return false;
24554 }
24555 
24556 void
dropNodegroup_reply(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)24557 Dbdict::dropNodegroup_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
24558 {
24559   jam();
24560   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
24561   DropNodegroupRecPtr dropNodegroupRecPtr;
24562   getOpRec(op_ptr, dropNodegroupRecPtr);
24563   //DropNodegroupImplReq* impl_req = &dropNodegroupRecPtr.p->m_request;
24564 
24565   if (!hasError(error))
24566   {
24567     jam();
24568     DropNodegroupConf* conf = (DropNodegroupConf*)signal->getDataPtrSend();
24569     conf->senderRef = reference();
24570     conf->senderData = op_ptr.p->m_clientData;
24571     conf->transId = trans_ptr.p->m_transId;
24572     Uint32 clientRef = op_ptr.p->m_clientRef;
24573     sendSignal(clientRef, GSN_DROP_NODEGROUP_CONF, signal,
24574                DropNodegroupConf::SignalLength, JBB);
24575   }
24576   else
24577   {
24578     jam();
24579     DropNodegroupRef* ref = (DropNodegroupRef*)signal->getDataPtrSend();
24580     ref->senderRef = reference();
24581     ref->senderData = op_ptr.p->m_clientData;
24582     ref->transId = trans_ptr.p->m_transId;
24583     getError(error, ref);
24584 
24585     Uint32 clientRef = op_ptr.p->m_clientRef;
24586     sendSignal(clientRef, GSN_DROP_NODEGROUP_REF, signal,
24587                DropNodegroupRef::SignalLength, JBB);
24588   }
24589 }
24590 
24591 // DropNodegroup: PREPARE
24592 
24593 void
dropNodegroup_prepare(Signal * signal,SchemaOpPtr op_ptr)24594 Dbdict::dropNodegroup_prepare(Signal* signal, SchemaOpPtr op_ptr)
24595 {
24596   jam();
24597   DropNodegroupRecPtr dropNodegroupRecPtr;
24598   getOpRec(op_ptr, dropNodegroupRecPtr);
24599   DropNodegroupImplReq* impl_req = &dropNodegroupRecPtr.p->m_request;
24600 
24601   impl_req->requestType = DropNodegroupImplReq::RT_PREPARE;
24602   dropNodegroupRecPtr.p->m_blockCnt = 2;
24603   dropNodegroupRecPtr.p->m_blockIndex = 0;
24604   dropNodegroupRecPtr.p->m_blockNo[0] = DBDIH_REF;
24605   dropNodegroupRecPtr.p->m_blockNo[1] = SUMA_REF;
24606 
24607   Callback c = {
24608     safe_cast(&Dbdict::dropNodegroup_fromBlockSubStartStop),
24609     op_ptr.p->op_key
24610   };
24611   op_ptr.p->m_callback = c;
24612 
24613   block_substartstop(signal, op_ptr);
24614 }
24615 
24616 void
dropNodegroup_fromBlockSubStartStop(Signal * signal,Uint32 op_key,Uint32 ret)24617 Dbdict::dropNodegroup_fromBlockSubStartStop(Signal* signal,
24618                                               Uint32 op_key,
24619                                               Uint32 ret)
24620 {
24621   SchemaOpPtr op_ptr;
24622   DropNodegroupRecPtr dropNodegroupRecPtr;
24623   findSchemaOp(op_ptr, dropNodegroupRecPtr, op_key);
24624   ndbrequire(!op_ptr.isNull());
24625   //DropNodegroupImplReq* impl_req = &dropNodegroupRecPtr.p->m_request;
24626 
24627   if (ret == 0)
24628   {
24629     jam();
24630     dropNodegroupRecPtr.p->m_substartstop_blocked = true;
24631     dropNodegroup_toLocal(signal, op_ptr);
24632   }
24633   else
24634   {
24635     jam();
24636     setError(op_ptr, ret, __LINE__);
24637     sendTransRef(signal, op_ptr);
24638   }
24639 }
24640 
24641 void
dropNodegroup_toLocal(Signal * signal,SchemaOpPtr op_ptr)24642 Dbdict::dropNodegroup_toLocal(Signal* signal, SchemaOpPtr op_ptr)
24643 {
24644   DropNodegroupRecPtr dropNodegroupRecPtr;
24645   getOpRec(op_ptr, dropNodegroupRecPtr);
24646   DropNodegroupImplReq* impl_req = &dropNodegroupRecPtr.p->m_request;
24647 
24648   const Uint32 blockIndex = dropNodegroupRecPtr.p->m_blockIndex;
24649   if (blockIndex == dropNodegroupRecPtr.p->m_blockCnt)
24650   {
24651     jam();
24652 
24653     if (op_ptr.p->m_state == SchemaOp::OS_PREPARING)
24654     {
24655       jam();
24656 
24657       /**
24658        * Block GCP as last part of prepare
24659        */
24660       Callback c = {
24661         safe_cast(&Dbdict::dropNodegroup_fromWaitGCP),
24662         op_ptr.p->op_key
24663       };
24664       op_ptr.p->m_callback = c;
24665 
24666       dropNodegroupRecPtr.p->m_cnt_waitGCP = 0;
24667       dropNodegroupRecPtr.p->m_wait_gcp_type = WaitGCPReq::BlockStartGcp;
24668       wait_gcp(signal, op_ptr, WaitGCPReq::BlockStartGcp);
24669       return;
24670     }
24671 
24672     if (op_ptr.p->m_state == SchemaOp::OS_COMPLETING)
24673     {
24674       jam();
24675       /**
24676        * Unblock GCP as last step of complete
24677        */
24678       Callback c = {
24679         safe_cast(&Dbdict::dropNodegroup_fromWaitGCP),
24680         op_ptr.p->op_key
24681       };
24682       op_ptr.p->m_callback = c;
24683 
24684       dropNodegroupRecPtr.p->m_cnt_waitGCP = 0;
24685       dropNodegroupRecPtr.p->m_wait_gcp_type = WaitGCPReq::UnblockStartGcp;
24686       wait_gcp(signal, op_ptr, WaitGCPReq::UnblockStartGcp);
24687       return;
24688     }
24689 
24690     sendTransConf(signal, op_ptr);
24691     return;
24692   }
24693 
24694   Callback c = {
24695     safe_cast(&Dbdict::dropNodegroup_fromLocal),
24696     op_ptr.p->op_key
24697   };
24698   op_ptr.p->m_callback = c;
24699 
24700   Uint32 ref = dropNodegroupRecPtr.p->m_blockNo[blockIndex];
24701   DropNodegroupImplReq * req = (DropNodegroupImplReq*)signal->getDataPtrSend();
24702   memcpy(req, impl_req, 4*DropNodegroupImplReq::SignalLength);
24703   sendSignal(ref, GSN_DROP_NODEGROUP_IMPL_REQ, signal,
24704              DropNodegroupImplReq::SignalLength, JBB);
24705 }
24706 
24707 void
dropNodegroup_fromLocal(Signal * signal,Uint32 op_key,Uint32 ret)24708 Dbdict::dropNodegroup_fromLocal(Signal* signal,
24709                                   Uint32 op_key,
24710                                   Uint32 ret)
24711 {
24712   SchemaOpPtr op_ptr;
24713   DropNodegroupRecPtr dropNodegroupRecPtr;
24714   findSchemaOp(op_ptr, dropNodegroupRecPtr, op_key);
24715   ndbrequire(!op_ptr.isNull());
24716   DropNodegroupImplReq* impl_req = &dropNodegroupRecPtr.p->m_request;
24717 
24718   Uint32 blockIndex = dropNodegroupRecPtr.p->m_blockIndex;
24719   ndbrequire(blockIndex < dropNodegroupRecPtr.p->m_blockCnt);
24720 
24721   if (ret)
24722   {
24723     jam();
24724     setError(op_ptr, ret, __LINE__);
24725     sendTransRef(signal, op_ptr);
24726     return;
24727   }
24728 
24729   Uint32 idx = dropNodegroupRecPtr.p->m_blockIndex;
24730   if (op_ptr.p->m_state == SchemaOp::OS_COMMITTING &&
24731       dropNodegroupRecPtr.p->m_blockNo[idx] == DBDIH_REF)
24732   {
24733     jam();
24734 
24735     DropNodegroupImplConf * conf =
24736       (DropNodegroupImplConf*)signal->getDataPtr();
24737     impl_req->gci_hi = conf->gci_hi;
24738     impl_req->gci_lo = conf->gci_lo;
24739   }
24740 
24741 
24742   dropNodegroupRecPtr.p->m_blockIndex++;
24743   dropNodegroup_toLocal(signal, op_ptr);
24744 }
24745 
24746 
24747 void
dropNodegroup_abortPrepare(Signal * signal,SchemaOpPtr op_ptr)24748 Dbdict::dropNodegroup_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
24749 {
24750   DropNodegroupRecPtr dropNodegroupRecPtr;
24751   getOpRec(op_ptr, dropNodegroupRecPtr);
24752   //DropNodegroupImplReq* impl_req = &dropNodegroupRecPtr.p->m_request;
24753 
24754   if (dropNodegroupRecPtr.p->m_substartstop_blocked)
24755   {
24756     jam();
24757     unblock_substartstop();
24758   }
24759 
24760   if (dropNodegroupRecPtr.p->m_gcp_blocked)
24761   {
24762     jam();
24763 
24764     Callback c = {
24765       safe_cast(&Dbdict::dropNodegroup_fromWaitGCP),
24766       op_ptr.p->op_key
24767     };
24768     op_ptr.p->m_callback = c;
24769 
24770     dropNodegroupRecPtr.p->m_cnt_waitGCP = 0;
24771     dropNodegroupRecPtr.p->m_wait_gcp_type = WaitGCPReq::UnblockStartGcp;
24772     wait_gcp(signal, op_ptr, WaitGCPReq::UnblockStartGcp);
24773     return;
24774   }
24775 
24776   sendTransConf(signal, op_ptr);
24777 }
24778 
24779 // DropNodegroup: COMMIT
24780 
24781 void
dropNodegroup_commit(Signal * signal,SchemaOpPtr op_ptr)24782 Dbdict::dropNodegroup_commit(Signal* signal, SchemaOpPtr op_ptr)
24783 {
24784   jam();
24785   DropNodegroupRecPtr dropNodegroupRecPtr;
24786   getOpRec(op_ptr, dropNodegroupRecPtr);
24787   DropNodegroupImplReq* impl_req = &dropNodegroupRecPtr.p->m_request;
24788 
24789   impl_req->requestType = DropNodegroupImplReq::RT_COMMIT;
24790 
24791   dropNodegroupRecPtr.p->m_blockIndex = 0;
24792   dropNodegroupRecPtr.p->m_blockCnt = 1;
24793   dropNodegroupRecPtr.p->m_blockNo[0] = DBDIH_REF;
24794 
24795   Callback c = {
24796     safe_cast(&Dbdict::dropNodegroup_fromWaitGCP),
24797     op_ptr.p->op_key
24798   };
24799   op_ptr.p->m_callback = c;
24800 
24801   dropNodegroupRecPtr.p->m_cnt_waitGCP = 0;
24802   dropNodegroupRecPtr.p->m_wait_gcp_type = WaitGCPReq::WaitEpoch;
24803   wait_gcp(signal, op_ptr, WaitGCPReq::WaitEpoch);
24804 }
24805 
24806 void
dropNodegroup_fromWaitGCP(Signal * signal,Uint32 op_key,Uint32 ret)24807 Dbdict::dropNodegroup_fromWaitGCP(Signal* signal,
24808                                   Uint32 op_key,
24809                                   Uint32 ret)
24810 {
24811   jam();
24812   SchemaOpPtr op_ptr;
24813   DropNodegroupRecPtr dropNodegroupRecPtr;
24814   findSchemaOp(op_ptr, dropNodegroupRecPtr, op_key);
24815   ndbrequire(!op_ptr.isNull());
24816 
24817   //DropNodegroupImplReq* impl_req = &dropNodegroupRecPtr.p->m_request;
24818 
24819   if (ret == 0)
24820   {
24821     jam();
24822 
24823     Uint32 wait_type = dropNodegroupRecPtr.p->m_wait_gcp_type;
24824     if (op_ptr.p->m_state == SchemaOp::OS_ABORTING_PREPARE)
24825     {
24826       jam();
24827       ndbrequire(wait_type == WaitGCPReq::UnblockStartGcp);
24828       sendTransConf(signal, op_ptr);
24829       return;
24830     }
24831     else if (op_ptr.p->m_state == SchemaOp::OS_PREPARING)
24832     {
24833       jam();
24834       ndbrequire(wait_type == WaitGCPReq::BlockStartGcp);
24835       dropNodegroupRecPtr.p->m_gcp_blocked = true;
24836       sendTransConf(signal, op_ptr);
24837       return;
24838     }
24839     else if (op_ptr.p->m_state == SchemaOp::OS_COMMITTING)
24840     {
24841       jam();
24842       ndbrequire(wait_type == WaitGCPReq::WaitEpoch);
24843       dropNodegroup_toLocal(signal, op_ptr);
24844       return;
24845     }
24846     else
24847     {
24848       jam();
24849 
24850       ndbrequire(op_ptr.p->m_state == SchemaOp::OS_COMPLETING);
24851       if (wait_type == WaitGCPReq::UnblockStartGcp)
24852       {
24853         /**
24854          * Also wait for the epoch to complete
24855          */
24856         jam();
24857         dropNodegroupRecPtr.p->m_wait_gcp_type = WaitGCPReq::CompleteForceStart;
24858         goto retry;
24859       }
24860       else
24861       {
24862         jam();
24863         ndbrequire(wait_type == WaitGCPReq::CompleteForceStart);
24864         unblock_substartstop();
24865       }
24866       sendTransConf(signal, op_ptr);
24867       return;
24868     }
24869   }
24870 
24871   dropNodegroupRecPtr.p->m_cnt_waitGCP++;
24872   switch(ret){
24873   case WaitGCPRef::NoWaitGCPRecords:
24874     jam();
24875   case WaitGCPRef::NF_CausedAbortOfProcedure:
24876     jam();
24877   case WaitGCPRef::NF_MasterTakeOverInProgress:
24878     jam();
24879   }
24880 
24881 retry:
24882   wait_gcp(signal, op_ptr, dropNodegroupRecPtr.p->m_wait_gcp_type);
24883 }
24884 
24885 // DropNodegroup: COMPLETE
24886 
24887 void
dropNodegroup_complete(Signal * signal,SchemaOpPtr op_ptr)24888 Dbdict::dropNodegroup_complete(Signal* signal, SchemaOpPtr op_ptr)
24889 {
24890   jam();
24891 
24892   DropNodegroupRecPtr dropNodegroupRecPtr;
24893   getOpRec(op_ptr, dropNodegroupRecPtr);
24894   DropNodegroupImplReq* impl_req = &dropNodegroupRecPtr.p->m_request;
24895 
24896   impl_req->requestType = DropNodegroupImplReq::RT_COMPLETE;
24897   dropNodegroupRecPtr.p->m_blockIndex = 0;
24898   dropNodegroupRecPtr.p->m_blockCnt = 3;
24899   dropNodegroupRecPtr.p->m_blockNo[0] = SUMA_REF;
24900   dropNodegroupRecPtr.p->m_blockNo[1] = DBDIH_REF;
24901   dropNodegroupRecPtr.p->m_blockNo[2] = NDBCNTR_REF;
24902 
24903   dropNodegroup_toLocal(signal, op_ptr);
24904 }
24905 
24906 void
execDROP_NODEGROUP_IMPL_REF(Signal * signal)24907 Dbdict::execDROP_NODEGROUP_IMPL_REF(Signal* signal)
24908 {
24909   jamEntry();
24910   DropNodegroupImplRef * ref = (DropNodegroupImplRef*)signal->getDataPtr();
24911   handleDictRef(signal, ref);
24912 }
24913 
24914 void
execDROP_NODEGROUP_IMPL_CONF(Signal * signal)24915 Dbdict::execDROP_NODEGROUP_IMPL_CONF(Signal* signal)
24916 {
24917   jamEntry();
24918   DropNodegroupImplConf * conf = (DropNodegroupImplConf*)signal->getDataPtr();
24919   handleDictConf(signal, conf);
24920 }
24921 
24922 // DropNodegroup: END
24923 
24924 // MODULE: CreateFK
24925 
24926 const Dbdict::OpInfo
24927 Dbdict::CreateFKRec::g_opInfo = {
24928   { 'C', 'F', 'K', 0 },
24929   ~RT_DBDICT_CREATE_FK,
24930   GSN_CREATE_FK_IMPL_REQ,
24931   CreateFKImplReq::SignalLength,
24932 
24933   //
24934   &Dbdict::createFK_seize,
24935   &Dbdict::createFK_release,
24936   //
24937   &Dbdict::createFK_parse,
24938   &Dbdict::createFK_subOps,
24939   &Dbdict::createFK_reply,
24940   //
24941   &Dbdict::createFK_prepare,
24942   &Dbdict::createFK_commit,
24943   &Dbdict::createFK_complete,
24944   //
24945   &Dbdict::createFK_abortParse,
24946   &Dbdict::createFK_abortPrepare
24947 };
24948 
24949 void
execCREATE_FK_REQ(Signal * signal)24950 Dbdict::execCREATE_FK_REQ(Signal* signal)
24951 {
24952   jamEntry();
24953   if (!assembleFragments(signal)) {
24954     jam();
24955     return;
24956   }
24957   SectionHandle handle(this, signal);
24958 
24959   const CreateFKReq req_copy =
24960     *(const CreateFKReq*)signal->getDataPtr();
24961   const CreateFKReq* req = &req_copy;
24962 
24963   ErrorInfo error;
24964   do {
24965     SchemaOpPtr op_ptr;
24966     CreateFKRecPtr createFKRecPtr;
24967     CreateFKImplReq* impl_req;
24968 
24969     startClientReq(op_ptr, createFKRecPtr, req, impl_req, error);
24970     if (hasError(error)) {
24971       jam();
24972       break;
24973     }
24974 
24975     handleClientReq(signal, op_ptr, handle);
24976     return;
24977   } while (0);
24978 
24979   releaseSections(handle);
24980 
24981   CreateFKRef* ref = (CreateFKRef*)signal->getDataPtrSend();
24982   ref->senderRef = reference();
24983   ref->transId = req->transId;
24984   ref->senderData = req->senderData;
24985   getError(error, ref);
24986 
24987   sendSignal(req->senderRef, GSN_CREATE_FK_REF, signal,
24988 	     CreateFKRef::SignalLength, JBB);
24989 }
24990 
24991 bool
createFK_seize(SchemaOpPtr op_ptr)24992 Dbdict::createFK_seize(SchemaOpPtr op_ptr)
24993 {
24994   return seizeOpRec<CreateFKRec>(op_ptr);
24995 }
24996 
24997 void
createFK_release(SchemaOpPtr op_ptr)24998 Dbdict::createFK_release(SchemaOpPtr op_ptr)
24999 {
25000   releaseOpRec<CreateFKRec>(op_ptr);
25001 }
25002 
25003 // CreateFK: PARSE
25004 
25005 void
createFK_parse(Signal * signal,bool master,SchemaOpPtr op_ptr,SectionHandle & handle,ErrorInfo & error)25006 Dbdict::createFK_parse(Signal* signal, bool master,
25007                               SchemaOpPtr op_ptr,
25008                               SectionHandle& handle, ErrorInfo& error)
25009 {
25010   D("createFK_parse");
25011   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
25012   CreateFKRecPtr createFKRecPtr;
25013   getOpRec(op_ptr, createFKRecPtr);
25014   CreateFKImplReq* impl_req = &createFKRecPtr.p->m_request;
25015 
25016   SegmentedSectionPtr objInfoPtr;
25017   {
25018     bool ok = handle.getSection(objInfoPtr, 0);
25019     if (!ok)
25020     {
25021       jam();
25022       setError(error, CreateTableRef::InvalidFormat, __LINE__);
25023       return;
25024     }
25025   }
25026   SimplePropertiesSectionReader it(objInfoPtr, getSectionSegmentPool());
25027 
25028   DictForeignKeyInfo::ForeignKey fk; fk.init();
25029   SimpleProperties::UnpackStatus status =
25030     SimpleProperties::unpack(it, &fk,
25031                              DictForeignKeyInfo::Mapping,
25032                              DictForeignKeyInfo::MappingSize,
25033                              true, true);
25034 
25035   if(status != SimpleProperties::Eof)
25036   {
25037     jam();
25038     setError(error, CreateFKRef::InvalidFormat, __LINE__);
25039     return;
25040   }
25041 
25042   D("FK: " << fk);
25043 
25044   /**
25045    * validate
25046    */
25047   if (fk.ParentTableId == RNIL || fk.ChildTableId == RNIL)
25048   {
25049     jam();
25050     setError(error, CreateFKRef::InvalidFormat, __LINE__);
25051     return;
25052   }
25053 
25054   if (fk.ParentColumnsLength != fk.ChildColumnsLength)
25055   {
25056     jam();
25057     setError(error, CreateFKRef::InvalidFormat, __LINE__);
25058     return;
25059   }
25060 
25061   const Uint32 colCount = (fk.ParentColumnsLength / 4);
25062 
25063   Uint32 bits = 0;
25064 
25065   {
25066     const SchemaFile::TableEntry * parentEntry= getTableEntry(fk.ParentTableId);
25067     if (parentEntry == 0 || !DictTabInfo::isTable(parentEntry->m_tableType))
25068     {
25069       jam();
25070       setError(error, CreateFKRef::ParentTableIsNotATable, __LINE__);
25071       return;
25072     }
25073 
25074     /*
25075      * See comment below about child table version.
25076      */
25077     if (table_version_major(fk.ParentTableVersion) !=
25078         table_version_major(parentEntry->m_tableVersion))
25079     {
25080       jam();
25081       setError(error, CreateFKRef::InvalidParentTableVersion, __LINE__);
25082       return;
25083     }
25084   }
25085 
25086   {
25087     const SchemaFile::TableEntry * childEntry= getTableEntry(fk.ChildTableId);
25088     if (childEntry == 0 || !DictTabInfo::isTable(childEntry->m_tableType))
25089     {
25090       jam();
25091       setError(error, CreateFKRef::ChildTableIsNotATable, __LINE__);
25092       return;
25093     }
25094 
25095     /*
25096      * We cannot keep table version fully synced with FKs.
25097      * Even handler does create FK, alter table (in this order)
25098      * so version is instantly out-of-date.  Checking major version
25099      * should be good enough (or even the right thing).
25100      *
25101      * A test case is NR/SR create FKs.
25102      */
25103     if (table_version_major(fk.ChildTableVersion) !=
25104         table_version_major(childEntry->m_tableVersion))
25105     {
25106       jam();
25107       setError(error, CreateFKRef::InvalidChildTableVersion, __LINE__);
25108       return;
25109     }
25110   }
25111 
25112   /*
25113    * Table/index may not yet exist on restart so in the following
25114    * check op_ptr.p->m_restart before find_object().
25115    */
25116 
25117   if (fk.ParentIndexId != RNIL)
25118   {
25119     const SchemaFile::TableEntry * parentIndexEntry=
25120       getTableEntry(fk.ParentIndexId);
25121     if (parentIndexEntry == 0 ||
25122         !DictTabInfo::isUniqueIndex(parentIndexEntry->m_tableType))
25123     {
25124       jam();
25125       setError(error, CreateFKRef::ParentIndexIsNotAnUniqueIndex, __LINE__);
25126       return;
25127     }
25128 
25129     if (fk.ParentIndexVersion != parentIndexEntry->m_tableVersion)
25130     {
25131       jam();
25132       setError(error, CreateFKRef::InvalidParentIndexVersion, __LINE__);
25133       return;
25134     }
25135 
25136     if (DictTabInfo::isUniqueIndex(parentIndexEntry->m_tableType))
25137     {
25138       bits |= CreateFKImplReq::FK_PARENT_UI;
25139     }
25140     else
25141     {
25142       bits |= CreateFKImplReq::FK_PARENT_OI;
25143     }
25144 
25145     if (!op_ptr.p->m_restart)
25146     {
25147       jam();
25148       TableRecordPtr parentIndexPtr;
25149       ndbrequire(find_object(parentIndexPtr, fk.ParentIndexId));
25150       if (parentIndexPtr.p->noOfAttributes != colCount + 1)
25151       {
25152         jam();
25153         setError(error, CreateFKRef::InvalidFormat, __LINE__);
25154         ndbassert(false);
25155         return;
25156       }
25157     }
25158   }
25159   else
25160   {
25161     if (!op_ptr.p->m_restart)
25162     {
25163       jam();
25164       TableRecordPtr parentTablePtr;
25165       ndbrequire(find_object(parentTablePtr, fk.ParentTableId));
25166       if (parentTablePtr.p->noOfPrimkey  != colCount)
25167       {
25168         jam();
25169         setError(error, CreateFKRef::InvalidFormat, __LINE__);
25170         return;
25171       }
25172     }
25173   }
25174 
25175   if (fk.ChildIndexId != RNIL)
25176   {
25177     const SchemaFile::TableEntry * childIndexEntry=
25178       getTableEntry(fk.ChildIndexId);
25179     if (childIndexEntry == 0 ||
25180         !DictTabInfo::isIndex(childIndexEntry->m_tableType))
25181     {
25182       jam();
25183       setError(error, CreateFKRef::ChildIndexIsNotAnIndex, __LINE__);
25184       return;
25185     }
25186 
25187     if (fk.ChildIndexVersion != childIndexEntry->m_tableVersion)
25188     {
25189       jam();
25190       setError(error, CreateFKRef::InvalidChildIndexVersion, __LINE__);
25191       return;
25192     }
25193 
25194     if (DictTabInfo::isUniqueIndex(childIndexEntry->m_tableType))
25195     {
25196       jam();
25197       bits |= CreateFKImplReq::FK_CHILD_UI;
25198     }
25199     else
25200     {
25201       jam();
25202       bits |= CreateFKImplReq::FK_CHILD_OI;
25203     }
25204 
25205     if (!op_ptr.p->m_restart)
25206     {
25207       jam();
25208       TableRecordPtr childIndexPtr;
25209       ndbrequire(find_object(childIndexPtr, fk.ChildIndexId));
25210       if (DictTabInfo::isUniqueIndex(childIndexEntry->m_tableType) &&
25211           childIndexPtr.p->noOfAttributes != colCount + 1)
25212       {
25213         jam();
25214         setError(error, CreateFKRef::InvalidFormat, __LINE__);
25215         return;
25216       }
25217     }
25218   }
25219   else
25220   {
25221     jam();
25222     if (!op_ptr.p->m_restart)
25223     {
25224       jam();
25225       TableRecordPtr childTablePtr;
25226       ndbrequire(find_object(childTablePtr, fk.ChildTableId));
25227       if (childTablePtr.p->noOfPrimkey  != colCount)
25228       {
25229         jam();
25230         setError(error, CreateFKRef::InvalidFormat, __LINE__);
25231         ndbassert(false);
25232         return;
25233       }
25234     }
25235   }
25236 
25237   /**
25238    * TODO verify column data-types etc...
25239    */
25240   switch(fk.OnUpdateAction){
25241   case NDB_FK_NO_ACTION:
25242     break;
25243   case NDB_FK_RESTRICT:
25244     bits |= CreateFKImplReq::FK_UPDATE_RESTRICT;
25245     break;
25246   case NDB_FK_CASCADE:
25247     bits |= CreateFKImplReq::FK_UPDATE_CASCADE;
25248     break;
25249   case NDB_FK_SET_NULL:
25250     bits |= CreateFKImplReq::FK_UPDATE_SET_NULL;
25251     break;
25252   case NDB_FK_SET_DEFAULT:
25253     bits |= CreateFKImplReq::FK_UPDATE_SET_DEFAULT;
25254     break;
25255   }
25256 
25257   switch(fk.OnDeleteAction){
25258   case NDB_FK_NO_ACTION:
25259     break;
25260   case NDB_FK_RESTRICT:
25261     bits |= CreateFKImplReq::FK_DELETE_RESTRICT;
25262     break;
25263   case NDB_FK_CASCADE:
25264     bits |= CreateFKImplReq::FK_DELETE_CASCADE;
25265     break;
25266   case NDB_FK_SET_NULL:
25267     bits |= CreateFKImplReq::FK_DELETE_SET_NULL;
25268     break;
25269   case NDB_FK_SET_DEFAULT:
25270     bits |= CreateFKImplReq::FK_DELETE_SET_DEFAULT;
25271     break;
25272   }
25273 
25274   /*
25275    * Handle SR/NR activate FK in late SP. The FK object was already
25276    * created without triggers in early SP.
25277    */
25278   if (c_restart_enable_fks)
25279   {
25280     jam();
25281     ndbrequire(fk.ForeignKeyId != RNIL && fk.ForeignKeyVersion != RNIL);
25282     impl_req->fkId = fk.ForeignKeyId;
25283     impl_req->fkVersion = fk.ForeignKeyVersion;
25284 
25285     Ptr<ForeignKeyRec> fk_ptr; fk_ptr.setNull();
25286     if (!find_object(fk_ptr, impl_req->fkId))
25287     {
25288       jam();
25289       setError(error, CreateFKRef::InvalidFormat, __LINE__);
25290       return;
25291     }
25292 
25293     saveOpSection(op_ptr, handle, 0);
25294     return;
25295   }
25296 
25297   Uint32 len = Uint32(strlen(fk.Name) + 1);
25298   Uint32 hash = LocalRope::hash(fk.Name, len);
25299   if (get_object(fk.Name, len, hash) != 0)
25300   {
25301     jam();
25302     setError(error, CreateFKRef::ObjectAlreadyExist, __LINE__);
25303     return;
25304   }
25305 
25306   Ptr<DictObject> obj_ptr; obj_ptr.setNull();
25307   if(!c_obj_pool.seize(obj_ptr))
25308   {
25309     jam();
25310     setError(error, CreateFKRef::NoMoreTableRecords, __LINE__);
25311     return;
25312   }
25313   new (obj_ptr.p) DictObject;
25314 
25315   Ptr<ForeignKeyRec> fk_ptr; fk_ptr.setNull();
25316   if(!c_fk_pool.seize(fk_ptr))
25317   {
25318     jam();
25319     setError(error, CreateFKRef::NoMoreTableRecords, __LINE__);
25320     goto error;
25321   }
25322 
25323   new (fk_ptr.p) ForeignKeyRec();
25324 
25325   {
25326     LocalRope name(c_rope_pool, obj_ptr.p->m_name);
25327     if(!name.assign(fk.Name, len, hash))
25328     {
25329       jam();
25330       setError(error, CreateFKRef::OutOfStringBuffer, __LINE__);
25331       goto error;
25332     }
25333   }
25334 
25335   if (master)
25336   {
25337     jam();
25338 
25339     Uint32 objId = getFreeObjId(0);
25340     if (objId == RNIL)
25341     {
25342       jam();
25343       setError(error, CreateFKRef::NoMoreObjectRecords, __LINE__);
25344       goto error;
25345     }
25346     Uint32 version = getTableEntry(objId)->m_tableVersion;
25347 
25348     impl_req->fkId = objId;
25349     impl_req->fkVersion = create_obj_inc_schema_version(version);
25350   }
25351   else if (op_ptr.p->m_restart)
25352   {
25353     jam();
25354     impl_req->fkId = c_restartRecord.activeTable;
25355     impl_req->fkVersion = c_restartRecord.m_entry.m_tableVersion;
25356   }
25357 
25358   fk_ptr.p->m_fk_id = impl_req->fkId;
25359   fk_ptr.p->m_obj_ptr_i = obj_ptr.i;
25360   fk_ptr.p->m_version = impl_req->fkVersion;
25361   fk_ptr.p->m_name = obj_ptr.p->m_name;
25362   fk_ptr.p->m_parentTableId = fk.ParentTableId;
25363   fk_ptr.p->m_childTableId = fk.ChildTableId;
25364   fk_ptr.p->m_parentIndexId = fk.ParentIndexId;
25365   fk_ptr.p->m_childIndexId = fk.ChildIndexId;
25366   fk_ptr.p->m_bits = bits;
25367   fk_ptr.p->m_columnCount = (fk.ParentColumnsLength / 4);
25368 
25369   for (Uint32 i = 0; i < fk_ptr.p->m_columnCount; i++)
25370   {
25371     fk_ptr.p->m_parentColumns[i] = fk.ParentColumns[i];
25372   }
25373 
25374   for (Uint32 i = 0; i < fk_ptr.p->m_columnCount; i++)
25375   {
25376     fk_ptr.p->m_childColumns[i] = fk.ChildColumns[i];
25377   }
25378 
25379   obj_ptr.p->m_id = impl_req->fkId;
25380   obj_ptr.p->m_type = DictTabInfo::ForeignKey;
25381   obj_ptr.p->m_ref_count = 0;
25382 
25383   if (master)
25384   {
25385     jam();
25386     releaseSections(handle);
25387     SimplePropertiesSectionWriter w(*this);
25388     packFKIntoPages(w, fk_ptr);
25389     w.getPtr(objInfoPtr);
25390     handle.m_ptr[0] = objInfoPtr;
25391     handle.m_cnt = 1;
25392   }
25393 
25394   {
25395     SchemaFile::TableEntry te; te.init();
25396     te.m_tableState = SchemaFile::SF_CREATE;
25397     te.m_tableVersion = fk_ptr.p->m_version;
25398     te.m_tableType = DictTabInfo::ForeignKey;
25399     te.m_info_words = objInfoPtr.sz;
25400     te.m_gcp = 0;
25401     te.m_transId = trans_ptr.p->m_transId;
25402 
25403     Uint32 err = trans_log_schema_op(op_ptr, impl_req->fkId, &te);
25404     if (err)
25405     {
25406       jam();
25407       setError(error, err, __LINE__);
25408       goto error;
25409     }
25410   }
25411 
25412   ndbrequire(link_object(obj_ptr, fk_ptr));
25413   c_obj_name_hash.add(obj_ptr);
25414   c_obj_id_hash.add(obj_ptr);
25415 
25416   // save sections to DICT memory
25417   saveOpSection(op_ptr, handle, 0);
25418 
25419   createFKRecPtr.p->m_parsed = true;
25420 
25421 #if defined VM_TRACE || defined ERROR_INSERT
25422   ndbout_c("Dbdict: create name=%s,id=%u,obj_ptr_i=%d",
25423            fk.Name, impl_req->fkId, fk_ptr.p->m_obj_ptr_i);
25424 #endif
25425 
25426   return;
25427 
25428 error:
25429   jam();
25430   if (!fk_ptr.isNull())
25431   {
25432     jam();
25433     c_fk_pool.release(fk_ptr);
25434   }
25435 
25436   if (!obj_ptr.isNull())
25437   {
25438     jam();
25439     release_object(obj_ptr.i, obj_ptr.p);
25440   }
25441 }
25442 
25443 void
packFKIntoPages(SimpleProperties::Writer & w,Ptr<ForeignKeyRec> fk_ptr)25444 Dbdict::packFKIntoPages(SimpleProperties::Writer & w,
25445                         Ptr<ForeignKeyRec> fk_ptr)
25446 {
25447   D("packFKIntoPages");
25448   DictForeignKeyInfo::ForeignKey fk; fk.init();
25449   ConstRope r(c_rope_pool, fk_ptr.p->m_name);
25450   r.copy(fk.Name);
25451 
25452   fk.ForeignKeyId = fk_ptr.p->m_fk_id;
25453   fk.ForeignKeyVersion = fk_ptr.p->m_version;
25454   fk.ParentTableId = fk_ptr.p->m_parentTableId;
25455   {
25456     TableRecordPtr tablePtr;
25457     ndbrequire(find_object(tablePtr, fk_ptr.p->m_parentTableId));
25458     fk.ParentTableVersion = tablePtr.p->tableVersion;
25459     ConstRope name(c_rope_pool, tablePtr.p->tableName);
25460     name.copy(fk.ParentTableName);
25461   }
25462   fk.ChildTableId = fk_ptr.p->m_childTableId;
25463   {
25464     TableRecordPtr tablePtr;
25465     ndbrequire(find_object(tablePtr, fk_ptr.p->m_childTableId));
25466     fk.ChildTableVersion = tablePtr.p->tableVersion;
25467     ConstRope name(c_rope_pool, tablePtr.p->tableName);
25468     name.copy(fk.ChildTableName);
25469   }
25470 
25471   fk.ParentIndexId = fk_ptr.p->m_parentIndexId;
25472   if (fk.ParentIndexId != RNIL)
25473   {
25474     TableRecordPtr tablePtr;
25475     ndbrequire(find_object(tablePtr, fk_ptr.p->m_parentIndexId));
25476     fk.ParentIndexVersion = tablePtr.p->tableVersion;
25477     ConstRope name(c_rope_pool, tablePtr.p->tableName);
25478     name.copy(fk.ParentIndexName);
25479   }
25480   fk.ChildIndexId = fk_ptr.p->m_childIndexId;
25481   if (fk.ChildIndexId != RNIL)
25482   {
25483     TableRecordPtr tablePtr;
25484     ndbrequire(find_object(tablePtr, fk_ptr.p->m_childIndexId));
25485     fk.ChildIndexVersion = tablePtr.p->tableVersion;
25486     ConstRope name(c_rope_pool, tablePtr.p->tableName);
25487     name.copy(fk.ChildIndexName);
25488   }
25489 
25490   // bytes...
25491   fk.ParentColumnsLength = 4 * fk_ptr.p->m_columnCount;
25492   fk.ChildColumnsLength = 4 * fk_ptr.p->m_columnCount;
25493   for (Uint32 i = 0; i < fk_ptr.p->m_columnCount; i++)
25494   {
25495     fk.ParentColumns[i] = fk_ptr.p->m_parentColumns[i];
25496     fk.ChildColumns[i] = fk_ptr.p->m_childColumns[i];
25497   }
25498 
25499   fk.OnUpdateAction = NDB_FK_NO_ACTION;
25500   if (fk_ptr.p->m_bits & CreateFKImplReq::FK_UPDATE_RESTRICT)
25501     fk.OnUpdateAction = NDB_FK_RESTRICT;
25502   else if (fk_ptr.p->m_bits & CreateFKImplReq::FK_UPDATE_CASCADE)
25503     fk.OnUpdateAction = NDB_FK_CASCADE;
25504   else if (fk_ptr.p->m_bits & CreateFKImplReq::FK_UPDATE_SET_NULL)
25505     fk.OnUpdateAction = NDB_FK_SET_NULL;
25506   else if (fk_ptr.p->m_bits & CreateFKImplReq::FK_UPDATE_SET_DEFAULT)
25507     fk.OnUpdateAction = NDB_FK_SET_DEFAULT;
25508 
25509   fk.OnDeleteAction = NDB_FK_NO_ACTION;
25510   if (fk_ptr.p->m_bits & CreateFKImplReq::FK_DELETE_RESTRICT)
25511     fk.OnDeleteAction = NDB_FK_RESTRICT;
25512   else if (fk_ptr.p->m_bits & CreateFKImplReq::FK_DELETE_CASCADE)
25513     fk.OnDeleteAction = NDB_FK_CASCADE;
25514   else if (fk_ptr.p->m_bits & CreateFKImplReq::FK_DELETE_SET_NULL)
25515     fk.OnDeleteAction = NDB_FK_SET_NULL;
25516   else if (fk_ptr.p->m_bits & CreateFKImplReq::FK_DELETE_SET_DEFAULT)
25517     fk.OnDeleteAction = NDB_FK_SET_DEFAULT;
25518 
25519   SimpleProperties::UnpackStatus s;
25520   s = SimpleProperties::pack(w,
25521 			     &fk,
25522 			     DictForeignKeyInfo::Mapping,
25523 			     DictForeignKeyInfo::MappingSize, true);
25524   ndbrequire(s == SimpleProperties::Eof);
25525 }
25526 
25527 void
createFK_abortParse(Signal * signal,SchemaOpPtr op_ptr)25528 Dbdict::createFK_abortParse(Signal* signal, SchemaOpPtr op_ptr)
25529 {
25530   D("createFK_abortParse");
25531   jam();
25532 
25533   CreateFKRecPtr createFKPtr;
25534   getOpRec(op_ptr, createFKPtr);
25535 
25536   if (createFKPtr.p->m_parsed)
25537   {
25538     jam();
25539     CreateFKImplReq* impl_req = &createFKPtr.p->m_request;
25540 
25541     Ptr<ForeignKeyRec> fk_ptr;
25542     ndbrequire(find_object(fk_ptr, impl_req->fkId));
25543 
25544     release_object(fk_ptr.p->m_obj_ptr_i);
25545   }
25546 
25547   sendTransConf(signal, op_ptr);
25548 }
25549 
25550 bool
createFK_subOps(Signal * signal,SchemaOpPtr op_ptr)25551 Dbdict::createFK_subOps(Signal* signal, SchemaOpPtr op_ptr)
25552 {
25553   D("createFK_subOps");
25554   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
25555   CreateFKRecPtr createFKRecPtr;
25556   getOpRec(op_ptr, createFKRecPtr);
25557   CreateFKImplReq* impl_req = &createFKRecPtr.p->m_request;
25558 
25559   if (createFKRecPtr.p->m_sub_create_trigger < 2)
25560   {
25561     jam();
25562 
25563     /**
25564      * 0 - trigger on parent table
25565      * 1 - trigger on child table
25566      */
25567     Callback c = {
25568       safe_cast(&Dbdict::createFK_fromCreateTrigger),
25569       op_ptr.p->op_key
25570     };
25571     op_ptr.p->m_callback = c;
25572 
25573     createFK_toCreateTrigger(signal, op_ptr);
25574     return true;
25575   }
25576 
25577   if (createFKRecPtr.p->m_sub_build_fk == false)
25578   {
25579     jam();
25580     Callback c = {
25581       safe_cast(&Dbdict::createFK_fromBuildFK),
25582       op_ptr.p->op_key
25583     };
25584     op_ptr.p->m_callback = c;
25585 
25586     BuildFKReq* req = (BuildFKReq*)signal->getDataPtrSend();
25587     Uint32 requestInfo = 0;
25588     DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
25589 
25590     req->clientRef = reference();
25591     req->clientData = op_ptr.p->op_key;
25592     req->transId = trans_ptr.p->m_transId;
25593     req->transKey = trans_ptr.p->trans_key;
25594     req->requestInfo = requestInfo;
25595     req->fkId = impl_req->fkId;
25596     req->fkVersion = impl_req->fkVersion;
25597 
25598     sendSignal(reference(), GSN_BUILD_FK_REQ, signal,
25599                BuildFKReq::SignalLength, JBB);
25600     return true;
25601   }
25602 
25603   return false;
25604 }
25605 
25606 void
createFK_toCreateTrigger(Signal * signal,SchemaOpPtr op_ptr)25607 Dbdict::createFK_toCreateTrigger(Signal* signal,
25608                                  SchemaOpPtr op_ptr)
25609 {
25610   D("createFK_toCreateTrigger");
25611   jam();
25612 
25613   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
25614   CreateFKRecPtr createFKPtr;
25615   getOpRec(op_ptr, createFKPtr);
25616   const CreateFKImplReq* impl_req = &createFKPtr.p->m_request;
25617 
25618   Ptr<ForeignKeyRec> fk_ptr;
25619   ndbrequire(find_object(fk_ptr, impl_req->fkId));
25620 
25621   TriggerTmpl triggerTmpl =
25622     g_fkTriggerTmpl[createFKPtr.p->m_sub_create_trigger];
25623 
25624   Uint32 tableId = RNIL;
25625   Uint32 indexId = RNIL;
25626   Uint32 triggerNo = RNIL;
25627   switch(createFKPtr.p->m_sub_create_trigger) {
25628   case 0:
25629     tableId = fk_ptr.p->m_parentTableId;
25630     indexId = fk_ptr.p->m_parentIndexId;
25631     triggerNo = 0;
25632     break;
25633   case 1:
25634     tableId = fk_ptr.p->m_childTableId;
25635     indexId = fk_ptr.p->m_childIndexId;
25636     triggerNo = 1;
25637     break;
25638   default:
25639     ndbrequire(false);
25640   }
25641 
25642   TableRecordPtr tablePtr;
25643   ndbrequire(find_object(tablePtr, tableId));
25644   CreateTrigReq* req = (CreateTrigReq*)signal->getDataPtrSend();
25645 
25646   Uint32 requestInfo = 0;
25647   DictSignal::setRequestType(requestInfo, CreateTrigReq::CreateTriggerOnline);
25648   DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
25649 
25650   req->clientRef = reference();
25651   req->clientData = op_ptr.p->op_key;
25652   req->transId = trans_ptr.p->m_transId;
25653   req->transKey = trans_ptr.p->trans_key;
25654   req->requestInfo = requestInfo;
25655   req->tableId = tableId;
25656   req->tableVersion = tablePtr.p->tableVersion;
25657   req->indexId = fk_ptr.p->m_fk_id;
25658   req->indexVersion = fk_ptr.p->m_version;
25659   req->triggerNo = triggerNo;
25660   req->forceTriggerId = RNIL;
25661 
25662   if ((fk_ptr.p->m_bits & CreateFKImplReq::FK_ACTION_MASK) == 0)
25663   {
25664     jam();
25665     triggerTmpl.triggerInfo.triggerActionTime = TriggerActionTime::TA_DEFERRED;
25666   }
25667 
25668   TriggerInfo::packTriggerInfo(req->triggerInfo, triggerTmpl.triggerInfo);
25669 
25670   req->receiverRef = 0;
25671 
25672   char triggerName[MAX_TAB_NAME_SIZE];
25673   sprintf(triggerName, triggerTmpl.nameFormat, fk_ptr.p->m_fk_id, tableId);
25674 
25675   // name section
25676   Uint32 buffer[2 + ((MAX_TAB_NAME_SIZE + 3) >> 2)];    // SP string
25677   LinearWriter w(buffer, sizeof(buffer) >> 2);
25678   w.reset();
25679   w.add(DictTabInfo::TableName, triggerName);
25680   LinearSectionPtr lsPtr[3];
25681   lsPtr[0].p = buffer;
25682   lsPtr[0].sz = w.getWordsUsed();
25683 
25684   AttributeMask mask;
25685   mask.clear();
25686 
25687   if (createFKPtr.p->m_sub_create_trigger == 0)
25688   {
25689     for (Uint32 i = 0; i < fk_ptr.p->m_columnCount; i++)
25690       mask.set(fk_ptr.p->m_parentColumns[i]);
25691   }
25692   else
25693   {
25694     for (Uint32 i = 0; i < fk_ptr.p->m_columnCount; i++)
25695       mask.set(fk_ptr.p->m_childColumns[i]);
25696   }
25697 
25698   lsPtr[1].p = mask.rep.data;
25699   lsPtr[1].sz = mask.getSizeInWords();
25700 
25701   sendSignal(reference(), GSN_CREATE_TRIG_REQ, signal,
25702              CreateTrigReq::SignalLength, JBB, lsPtr, 2);
25703 }
25704 
25705 void
createFK_fromCreateTrigger(Signal * signal,Uint32 op_key,Uint32 ret)25706 Dbdict::createFK_fromCreateTrigger(Signal* signal, Uint32 op_key, Uint32 ret)
25707 {
25708   D("createFK_fromCreateTrigger");
25709   jamEntry();
25710 
25711   SchemaOpPtr op_ptr;
25712   CreateFKRecPtr createFKRecPtr;
25713 
25714   findSchemaOp(op_ptr, createFKRecPtr, op_key);
25715   ndbrequire(!op_ptr.isNull());
25716   CreateFKImplReq* impl_req = &createFKRecPtr.p->m_request;
25717 
25718   if (ret == 0)
25719   {
25720     jam();
25721 
25722     const CreateTrigConf* conf = CAST_CONSTPTR(CreateTrigConf,
25723                                                signal->getDataPtr());
25724     Ptr<ForeignKeyRec> fk_ptr;
25725     ndbrequire(find_object(fk_ptr, impl_req->fkId));
25726     switch(createFKRecPtr.p->m_sub_create_trigger) {
25727     case 0:
25728       fk_ptr.p->m_parentTriggerId = conf->triggerId;
25729       break;
25730     case 1:
25731       fk_ptr.p->m_childTriggerId = conf->triggerId;
25732       break;
25733     default:
25734       ndbrequire(false);
25735     }
25736 
25737     createFKRecPtr.p->m_sub_create_trigger++;
25738     createSubOps(signal, op_ptr);
25739   }
25740   else
25741   {
25742     jam();
25743     const CreateTrigRef* ref = CAST_CONSTPTR(CreateTrigRef,
25744                                              signal->getDataPtr());
25745     ErrorInfo error;
25746     setError(error, ref);
25747     abortSubOps(signal, op_ptr, error);
25748   }
25749 }
25750 
25751 void
createFK_fromBuildFK(Signal * signal,Uint32 op_key,Uint32 ret)25752 Dbdict::createFK_fromBuildFK(Signal* signal, Uint32 op_key, Uint32 ret)
25753 {
25754   D("createFK_fromBuildFK");
25755   jamEntry();
25756 
25757   SchemaOpPtr op_ptr;
25758   CreateFKRecPtr createFKRecPtr;
25759 
25760   findSchemaOp(op_ptr, createFKRecPtr, op_key);
25761   ndbrequire(!op_ptr.isNull());
25762   CreateFKImplReq* impl_req = &createFKRecPtr.p->m_request;
25763 
25764   if (ret == 0)
25765   {
25766     jam();
25767 
25768     Ptr<ForeignKeyRec> fk_ptr;
25769     ndbrequire(find_object(fk_ptr, impl_req->fkId));
25770     createFKRecPtr.p->m_sub_build_fk = true;
25771     createSubOps(signal, op_ptr);
25772   }
25773   else
25774   {
25775     jam();
25776     const BuildFKRef* ref = CAST_CONSTPTR(BuildFKRef,
25777                                           signal->getDataPtr());
25778     ErrorInfo error;
25779     setError(error, ref);
25780     abortSubOps(signal, op_ptr, error);
25781   }
25782 }
25783 
25784 void
createFK_reply(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)25785 Dbdict::createFK_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
25786 {
25787   D("createFK_reply");
25788   jam();
25789   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
25790   CreateFKRecPtr createFKRecPtr;
25791   getOpRec(op_ptr, createFKRecPtr);
25792   CreateFKImplReq* impl_req = &createFKRecPtr.p->m_request;
25793 
25794   if (!hasError(error))
25795   {
25796     jam();
25797     CreateFKConf* conf = (CreateFKConf*)signal->getDataPtrSend();
25798     conf->senderRef = reference();
25799     conf->senderData = op_ptr.p->m_clientData;
25800     conf->transId = trans_ptr.p->m_transId;
25801     conf->fkId = impl_req->fkId;
25802     conf->fkVersion = impl_req->fkVersion;
25803     Uint32 clientRef = op_ptr.p->m_clientRef;
25804     sendSignal(clientRef, GSN_CREATE_FK_CONF, signal,
25805                CreateFKConf::SignalLength, JBB);
25806   }
25807   else
25808   {
25809     jam();
25810     CreateFKRef* ref = (CreateFKRef*)signal->getDataPtrSend();
25811     ref->senderRef = reference();
25812     ref->senderData = op_ptr.p->m_clientData;
25813     ref->transId = trans_ptr.p->m_transId;
25814     getError(error, ref);
25815 
25816     Uint32 clientRef = op_ptr.p->m_clientRef;
25817     sendSignal(clientRef, GSN_CREATE_FK_REF, signal,
25818                CreateFKRef::SignalLength, JBB);
25819   }
25820 }
25821 
25822 static
25823 int
cmp_uint(const void * _p1,const void * _p2)25824 cmp_uint(const void * _p1, const void * _p2)
25825 {
25826   Uint32 * p1 = (Uint32*)_p1;
25827   Uint32 * p2 = (Uint32*)_p2;
25828 
25829   if (* p1 < * p2)
25830     return -1;
25831   else if (* p2 < * p1)
25832     return 1;
25833   return 0;
25834 }
25835 
25836 // CreateFK: PREPARE
25837 void
createFK_prepare(Signal * signal,SchemaOpPtr op_ptr)25838 Dbdict::createFK_prepare(Signal* signal, SchemaOpPtr op_ptr)
25839 {
25840   D("createFK_prepare");
25841   jam();
25842   CreateFKRecPtr createFKRecPtr;
25843   getOpRec(op_ptr, createFKRecPtr);
25844   const CreateFKImplReq* impl_req = &createFKRecPtr.p->m_request;
25845 
25846   Callback cb;
25847   cb.m_callbackData = op_ptr.p->op_key;
25848   cb.m_callbackFunction = safe_cast(&Dbdict::createFK_writeTableConf);
25849 
25850   /*
25851    * On restart from disk there is no need to rewrite schemafile.
25852    */
25853   if (ZRESTART_NO_WRITE_AFTER_READ && op_ptr.p->m_restart == 1)
25854   {
25855     jam();
25856     execute(signal, cb, 0);
25857     return;
25858   }
25859 
25860   /*
25861    * On SR/NR activate FK there is no need to rewrite schemafile.
25862    */
25863   if (c_restart_enable_fks)
25864   {
25865     jam();
25866     execute(signal, cb, 0);
25867     return;
25868   }
25869 
25870   const OpSection& sec = getOpSection(op_ptr, 0);
25871   writeTableFile(signal, op_ptr, impl_req->fkId, sec, &cb);
25872 }
25873 
25874 void
createFK_writeTableConf(Signal * signal,Uint32 op_key,Uint32 ret)25875 Dbdict::createFK_writeTableConf(Signal* signal,
25876                                 Uint32 op_key,
25877                                 Uint32 ret)
25878 {
25879   D("createFK_writeTableConf");
25880   jam();
25881   SchemaOpPtr op_ptr;
25882   CreateFKRecPtr createFKRecPtr;
25883   findSchemaOp(op_ptr, createFKRecPtr, op_key);
25884   ndbrequire(!op_ptr.isNull());
25885 
25886   CreateFKImplReq* impl_req = &createFKRecPtr.p->m_request;
25887   impl_req->requestType = CreateFKImplReq::RT_PREPARE;
25888 
25889   Ptr<ForeignKeyRec> fk_ptr;
25890   ndbrequire(find_object(fk_ptr, impl_req->fkId));
25891 
25892   Callback c = {
25893     safe_cast(&Dbdict::createFK_prepareFromLocal),
25894     op_ptr.p->op_key
25895   };
25896   op_ptr.p->m_callback = c;
25897 
25898   /*
25899    * Restart does not call subOps (for reasons such as indexes).
25900    * Prepare here would create DBTC triggers with no DICT counterpart.
25901    * In any case, we do not want any triggers before data copy.
25902    *
25903    * op_ptr.p->m_restart is not set when we come from enable fks.
25904    * Check also c_restart_enable_fks to be more robust.
25905    */
25906   if (op_ptr.p->m_restart && !c_restart_enable_fks)
25907   {
25908     jam();
25909     D("no DBTC triggers" << V(op_ptr.p->m_restart) << V(c_restart_enable_fks));
25910     execute(signal, c, 0);
25911     return;
25912   }
25913   D("do DBTC triggers" << V(op_ptr.p->m_restart) << V(c_restart_enable_fks));
25914 
25915   CreateFKImplReq* req = (CreateFKImplReq*)signal->getDataPtrSend();
25916   req->senderRef = reference();
25917   req->senderData = op_ptr.p->op_key;
25918   req->requestType = CreateFKImplReq::RT_PREPARE;
25919   req->fkId = impl_req->fkId;
25920   req->fkVersion = impl_req->fkVersion;
25921   req->bits = fk_ptr.p->m_bits;
25922   req->parentTableId = fk_ptr.p->m_parentTableId;
25923   req->childTableId = fk_ptr.p->m_childTableId;
25924   req->parentIndexId = fk_ptr.p->m_parentIndexId;
25925   req->childIndexId = fk_ptr.p->m_childIndexId;
25926 
25927   /**
25928    * How do I transform input data from a parent row
25929    *  into access on a child row
25930    */
25931   Uint32 parent_to_child[MAX_ATTRIBUTES_IN_INDEX];
25932   memcpy(parent_to_child, fk_ptr.p->m_parentColumns, 4*fk_ptr.p->m_columnCount);
25933   if ((fk_ptr.p->m_bits & CreateFKImplReq::FK_CHILD_OI) == 0)
25934   {
25935     jam();
25936     Uint32 tmp[MAX_ATTRIBUTES_IN_INDEX];
25937     memcpy(tmp, fk_ptr.p->m_childColumns, 4*fk_ptr.p->m_columnCount);
25938     qsort(tmp, fk_ptr.p->m_columnCount, sizeof(Uint32), cmp_uint);
25939     for (Uint32 i = 0; i < fk_ptr.p->m_columnCount; i++)
25940     {
25941       Uint32 col = tmp[i];
25942       for (Uint32 j = 0; j < fk_ptr.p->m_columnCount; j++)
25943       {
25944         if (fk_ptr.p->m_childColumns[j] == col)
25945         {
25946           parent_to_child[i] = fk_ptr.p->m_parentColumns[j];
25947           break;
25948         }
25949       }
25950     }
25951   }
25952 
25953   Uint32 child_to_parent[MAX_ATTRIBUTES_IN_INDEX];
25954   memcpy(child_to_parent, fk_ptr.p->m_childColumns, 4*fk_ptr.p->m_columnCount);
25955   if ((fk_ptr.p->m_bits & CreateFKImplReq::FK_PARENT_OI) == 0)
25956   {
25957     jam();
25958     /**
25959      * PK/UI are stored in attribute id order...so sort child columns
25960      *   in parent order...
25961      */
25962     Uint32 tmp[MAX_ATTRIBUTES_IN_INDEX];
25963     memcpy(tmp, fk_ptr.p->m_parentColumns, 4*fk_ptr.p->m_columnCount);
25964     qsort(tmp, fk_ptr.p->m_columnCount, sizeof(Uint32), cmp_uint);
25965     for (Uint32 i = 0; i < fk_ptr.p->m_columnCount; i++)
25966     {
25967       Uint32 col = tmp[i];
25968       for (Uint32 j = 0; j < fk_ptr.p->m_columnCount; j++)
25969       {
25970         if (fk_ptr.p->m_parentColumns[j] == col)
25971         {
25972           child_to_parent[i] = fk_ptr.p->m_childColumns[j];
25973           break;
25974         }
25975       }
25976     }
25977   }
25978 
25979   BlockReference ref = DBTC_REF;
25980   LinearSectionPtr ptr[3];
25981   ptr[CreateFKImplReq::PARENT_COLUMNS].p = parent_to_child;
25982   ptr[CreateFKImplReq::PARENT_COLUMNS].sz = fk_ptr.p->m_columnCount;
25983 
25984   ptr[CreateFKImplReq::CHILD_COLUMNS].p = child_to_parent;
25985   ptr[CreateFKImplReq::CHILD_COLUMNS].sz = fk_ptr.p->m_columnCount;
25986   sendSignal(ref, GSN_CREATE_FK_IMPL_REQ, signal,
25987              CreateFKImplReq::SignalLength, JBB,
25988              ptr, 2);
25989 }
25990 
25991 void
createFK_prepareFromLocal(Signal * signal,Uint32 op_key,Uint32 ret)25992 Dbdict::createFK_prepareFromLocal(Signal* signal, Uint32 op_key, Uint32 ret)
25993 {
25994   D("createFK_prepareFromLocal");
25995   jamEntry();
25996 
25997   SchemaOpPtr op_ptr;
25998   CreateFKRecPtr createFKRecPtr;
25999   findSchemaOp(op_ptr, createFKRecPtr, op_key);
26000   ndbrequire(!op_ptr.isNull());
26001 
26002   if (ret == 0)
26003   {
26004     jam();
26005     createFKRecPtr.p->m_prepared = true;
26006     sendTransConf(signal, op_ptr);
26007   }
26008   else
26009   {
26010     jam();
26011     setError(op_ptr, ret, __LINE__);
26012     sendTransRef(signal, op_ptr);
26013   }
26014 }
26015 
26016 void
createFK_abortPrepare(Signal * signal,SchemaOpPtr op_ptr)26017 Dbdict::createFK_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
26018 {
26019   D("createFK_abortPrepare");
26020   CreateFKRecPtr createFKRecPtr;
26021   getOpRec(op_ptr, createFKRecPtr);
26022   CreateFKImplReq* impl_req = &createFKRecPtr.p->m_request;
26023 
26024   if (createFKRecPtr.p->m_prepared)
26025   {
26026     Callback c = {
26027       safe_cast(&Dbdict::createFK_abortPrepareFromLocal),
26028       op_ptr.p->op_key
26029     };
26030     op_ptr.p->m_callback = c;
26031 
26032     CreateFKImplReq* req = CAST_PTR(CreateFKImplReq, signal->getDataPtrSend());
26033     req->senderRef = reference();
26034     req->senderData = op_ptr.p->op_key;
26035     req->requestType = CreateFKImplReq::RT_ABORT;
26036     req->fkId = impl_req->fkId;
26037     req->fkVersion = impl_req->fkVersion;
26038     sendSignal(DBTC_REF, GSN_CREATE_FK_IMPL_REQ, signal,
26039                CreateFKImplReq::SignalLength, JBB);
26040     return;
26041   }
26042 
26043   sendTransConf(signal, op_ptr);
26044 }
26045 
26046 void
createFK_abortPrepareFromLocal(Signal * signal,Uint32 op_key,Uint32 ret)26047 Dbdict::createFK_abortPrepareFromLocal(Signal* signal,
26048                                        Uint32 op_key, Uint32 ret)
26049 {
26050   D("createFK_abortPrepareFromLocal");
26051   jamEntry();
26052 
26053   SchemaOpPtr op_ptr;
26054   CreateFKRecPtr createFKRecPtr;
26055   findSchemaOp(op_ptr, createFKRecPtr, op_key);
26056   ndbrequire(!op_ptr.isNull());
26057 
26058   if (ret == 0)
26059   {
26060     jam();
26061     createFKRecPtr.p->m_prepared = false;
26062     sendTransConf(signal, op_ptr);
26063   }
26064   else
26065   {
26066     jam();
26067     setError(op_ptr, ret, __LINE__);
26068     sendTransRef(signal, op_ptr);
26069   }
26070 }
26071 
26072 // CreateFK: COMMIT
26073 
26074 void
createFK_commit(Signal * signal,SchemaOpPtr op_ptr)26075 Dbdict::createFK_commit(Signal* signal, SchemaOpPtr op_ptr)
26076 {
26077   D("createFK_commit");
26078   jam();
26079   CreateFKRecPtr createFKRecPtr;
26080   getOpRec(op_ptr, createFKRecPtr);
26081   CreateFKImplReq* impl_req = &createFKRecPtr.p->m_request;
26082   impl_req->requestType = CreateFKImplReq::RT_COMMIT;
26083   sendTransConf(signal, op_ptr);
26084 }
26085 
26086 // CreateFK: COMPLETE
26087 
26088 void
createFK_complete(Signal * signal,SchemaOpPtr op_ptr)26089 Dbdict::createFK_complete(Signal* signal, SchemaOpPtr op_ptr)
26090 {
26091   D("createFK_complete");
26092   jam();
26093   CreateFKRecPtr createFKRecPtr;
26094   getOpRec(op_ptr, createFKRecPtr);
26095   CreateFKImplReq* impl_req = &createFKRecPtr.p->m_request;
26096   impl_req->requestType = CreateFKImplReq::RT_COMPLETE;
26097   sendTransConf(signal, op_ptr);
26098 }
26099 
26100 void
execCREATE_FK_REF(Signal * signal)26101 Dbdict::execCREATE_FK_REF(Signal* signal)
26102 {
26103   jamEntry();
26104   CreateFKRef * ref = (CreateFKRef*)signal->getDataPtr();
26105   handleDictRef(signal, ref);
26106 }
26107 
26108 void
execCREATE_FK_CONF(Signal * signal)26109 Dbdict::execCREATE_FK_CONF(Signal* signal)
26110 {
26111   jamEntry();
26112   CreateFKConf * conf = (CreateFKConf*)signal->getDataPtr();
26113   handleDictConf(signal, conf);
26114 }
26115 
26116 void
execCREATE_FK_IMPL_REF(Signal * signal)26117 Dbdict::execCREATE_FK_IMPL_REF(Signal* signal)
26118 {
26119   jamEntry();
26120   CreateFKImplRef * ref = (CreateFKImplRef*)signal->getDataPtr();
26121   handleDictRef(signal, ref);
26122 }
26123 
26124 void
execCREATE_FK_IMPL_CONF(Signal * signal)26125 Dbdict::execCREATE_FK_IMPL_CONF(Signal* signal)
26126 {
26127   jamEntry();
26128   CreateFKImplConf * conf = (CreateFKImplConf*)signal->getDataPtr();
26129   handleDictConf(signal, conf);
26130 }
26131 
26132 // CreateFK: END
26133 
26134 // MODULE: BuildFK
26135 
26136 const Dbdict::OpInfo
26137 Dbdict::BuildFKRec::g_opInfo = {
26138   { 'B', 'F', 'K', 0 },
26139   ~RT_DBDICT_DROP_NODEGROUP, // TODO
26140   GSN_BUILD_FK_IMPL_REQ,
26141   BuildFKImplReq::SignalLength,
26142 
26143   //
26144   &Dbdict::buildFK_seize,
26145   &Dbdict::buildFK_release,
26146   //
26147   &Dbdict::buildFK_parse,
26148   &Dbdict::buildFK_subOps,
26149   &Dbdict::buildFK_reply,
26150   //
26151   &Dbdict::buildFK_prepare,
26152   &Dbdict::buildFK_commit,
26153   &Dbdict::buildFK_complete,
26154   //
26155   &Dbdict::buildFK_abortParse,
26156   &Dbdict::buildFK_abortPrepare
26157 };
26158 
26159 void
execBUILD_FK_REQ(Signal * signal)26160 Dbdict::execBUILD_FK_REQ(Signal* signal)
26161 {
26162   jamEntry();
26163   if (!assembleFragments(signal)) {
26164     jam();
26165     return;
26166   }
26167   SectionHandle handle(this, signal);
26168 
26169   const BuildFKReq req_copy =
26170     *(const BuildFKReq*)signal->getDataPtr();
26171   const BuildFKReq* req = &req_copy;
26172 
26173   ErrorInfo error;
26174   do {
26175     SchemaOpPtr op_ptr;
26176     BuildFKRecPtr buildFKRecPtr;
26177     BuildFKImplReq* impl_req;
26178 
26179     startClientReq(op_ptr, buildFKRecPtr, req, impl_req, error);
26180     if (hasError(error)) {
26181       jam();
26182       break;
26183     }
26184 
26185     impl_req->fkId = req->fkId;
26186     impl_req->fkVersion = req->fkVersion;
26187 
26188     handleClientReq(signal, op_ptr, handle);
26189     return;
26190   } while (0);
26191 
26192   releaseSections(handle);
26193 
26194   BuildFKRef* ref = (BuildFKRef*)signal->getDataPtrSend();
26195   ref->senderRef = reference();
26196   ref->transId = req->transId;
26197   ref->senderData = req->senderData;
26198   getError(error, ref);
26199 
26200   sendSignal(req->senderRef, GSN_BUILD_FK_REF, signal,
26201 	     BuildFKRef::SignalLength, JBB);
26202 }
26203 
26204 bool
buildFK_seize(SchemaOpPtr op_ptr)26205 Dbdict::buildFK_seize(SchemaOpPtr op_ptr)
26206 {
26207   return seizeOpRec<BuildFKRec>(op_ptr);
26208 }
26209 
26210 void
buildFK_release(SchemaOpPtr op_ptr)26211 Dbdict::buildFK_release(SchemaOpPtr op_ptr)
26212 {
26213   releaseOpRec<BuildFKRec>(op_ptr);
26214 }
26215 
26216 // BuildFK: PARSE
26217 
26218 void
buildFK_parse(Signal * signal,bool master,SchemaOpPtr op_ptr,SectionHandle & handle,ErrorInfo & error)26219 Dbdict::buildFK_parse(Signal* signal, bool master,
26220                               SchemaOpPtr op_ptr,
26221                               SectionHandle& handle, ErrorInfo& error)
26222 {
26223   D("buildFK_parse");
26224   BuildFKRecPtr buildFKRecPtr;
26225   getOpRec(op_ptr, buildFKRecPtr);
26226   BuildFKImplReq* impl_req = &buildFKRecPtr.p->m_request;
26227 
26228   jam();
26229 
26230   Ptr<ForeignKeyRec> fk_ptr;
26231   if (!find_object(fk_ptr, impl_req->fkId))
26232   {
26233     jam();
26234     setError(error, BuildFKRef::FKNotFound, __LINE__);
26235     return;
26236   }
26237 
26238   if (fk_ptr.p->m_version != impl_req->fkVersion)
26239   {
26240     jam();
26241     setError(error, BuildFKRef::InvalidFKVersion, __LINE__);
26242     return;
26243   }
26244  }
26245 
26246 void
buildFK_abortParse(Signal * signal,SchemaOpPtr op_ptr)26247 Dbdict::buildFK_abortParse(Signal* signal, SchemaOpPtr op_ptr)
26248 {
26249   D("buildFK_abortParse");
26250   jam();
26251   sendTransConf(signal, op_ptr);
26252 }
26253 
26254 bool
buildFK_subOps(Signal * signal,SchemaOpPtr op_ptr)26255 Dbdict::buildFK_subOps(Signal* signal, SchemaOpPtr op_ptr)
26256 {
26257   D("buildFK_subOps");
26258   BuildFKRecPtr buildFKRecPtr;
26259   getOpRec(op_ptr, buildFKRecPtr);
26260   //BuildFKImplReq* impl_req = &buildFKRecPtr.p->m_request;
26261 
26262 
26263   return false;
26264 }
26265 
26266 void
buildFK_reply(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)26267 Dbdict::buildFK_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
26268 {
26269   D("buildFK_reply");
26270   jam();
26271   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
26272   BuildFKRecPtr buildFKRecPtr;
26273   getOpRec(op_ptr, buildFKRecPtr);
26274   //BuildFKImplReq* impl_req = &buildFKRecPtr.p->m_request;
26275 
26276   if (!hasError(error))
26277   {
26278     jam();
26279     BuildFKConf* conf = (BuildFKConf*)signal->getDataPtrSend();
26280     conf->senderRef = reference();
26281     conf->senderData = op_ptr.p->m_clientData;
26282     conf->transId = trans_ptr.p->m_transId;
26283     Uint32 clientRef = op_ptr.p->m_clientRef;
26284     sendSignal(clientRef, GSN_BUILD_FK_CONF, signal,
26285                BuildFKConf::SignalLength, JBB);
26286   }
26287   else
26288   {
26289     jam();
26290     BuildFKRef* ref = (BuildFKRef*)signal->getDataPtrSend();
26291     ref->senderRef = reference();
26292     ref->senderData = op_ptr.p->m_clientData;
26293     ref->transId = trans_ptr.p->m_transId;
26294     getError(error, ref);
26295 
26296     Uint32 clientRef = op_ptr.p->m_clientRef;
26297     sendSignal(clientRef, GSN_BUILD_FK_REF, signal,
26298                BuildFKRef::SignalLength, JBB);
26299   }
26300 }
26301 
26302 // BuildFK: PREPARE
26303 
26304 void
buildFK_prepare(Signal * signal,SchemaOpPtr op_ptr)26305 Dbdict::buildFK_prepare(Signal* signal, SchemaOpPtr op_ptr)
26306 {
26307   D("buildFK_prepare");
26308   jam();
26309   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
26310   BuildFKRecPtr buildFKRecPtr;
26311   getOpRec(op_ptr, buildFKRecPtr);
26312   BuildFKImplReq* impl_req = &buildFKRecPtr.p->m_request;
26313 
26314   Ptr<ForeignKeyRec> fk_ptr;
26315   ndbrequire(find_object(fk_ptr, impl_req->fkId));
26316 
26317   bool noBuild = (op_ptr.p->m_requestInfo & DictSignal::RF_NO_BUILD);
26318   if (noBuild)
26319   {
26320     jam();
26321     D("FK: no build" << V(noBuild) << V(c_restart_enable_fks));
26322     sendTransConf(signal, op_ptr);
26323     return;
26324   }
26325   D("FK: do build" << V(noBuild) << V(c_restart_enable_fks));
26326 
26327   BuildFKImplReq* req = CAST_PTR(BuildFKImplReq, signal->getDataPtrSend());
26328   * req = * impl_req;
26329   req->senderRef = reference();
26330   req->senderData = op_ptr.p->op_key;
26331   req->transId = trans_ptr.p->m_transId;
26332   req->parentTableId = fk_ptr.p->m_parentTableId;
26333   req->childTableId = fk_ptr.p->m_childTableId;
26334   if (fk_ptr.p->m_parentIndexId != RNIL)
26335   {
26336     jam();
26337     req->parentTableId = fk_ptr.p->m_parentIndexId;
26338   }
26339 
26340   Callback c = {
26341     safe_cast(&Dbdict::buildFK_fromLocal),
26342     op_ptr.p->op_key
26343   };
26344   op_ptr.p->m_callback = c;
26345 
26346   IndexAttributeList parentColumns;
26347   if (fk_ptr.p->m_parentIndexId == RNIL)
26348   {
26349     jam();
26350     TableRecordPtr parentPtr;
26351     ndbrequire(find_object(parentPtr, req->parentTableId));
26352     getIndexAttrList(parentPtr, parentColumns);
26353   }
26354   else
26355   {
26356     jam();
26357     /**
26358      * Unique index has key columns 0...N
26359      */
26360     TableRecordPtr parentPtr;
26361     ndbrequire(find_object(parentPtr, req->parentTableId));
26362     parentColumns.sz = fk_ptr.p->m_columnCount;
26363     for (Uint32 i = 0; i < parentColumns.sz ; i++)
26364       parentColumns.id[i] = i;
26365   }
26366 
26367   LinearSectionPtr ptr[3];
26368   ptr[0].p = parentColumns.id;
26369   ptr[0].sz = parentColumns.sz;
26370   ptr[1].p = fk_ptr.p->m_childColumns;
26371   ptr[1].sz = fk_ptr.p->m_columnCount;
26372 
26373   sendSignal(TRIX_REF, GSN_BUILD_FK_IMPL_REQ, signal,
26374              BuildFKImplReq::SignalLength, JBB, ptr, 2);
26375 }
26376 
26377 void
buildFK_fromLocal(Signal * signal,Uint32 op_key,Uint32 ret)26378 Dbdict::buildFK_fromLocal(Signal* signal, Uint32 op_key, Uint32 ret)
26379 {
26380   D("buildFK_fromLocal");
26381   jam();
26382   SchemaOpPtr op_ptr;
26383   BuildFKRecPtr buildFKPtr;
26384   findSchemaOp(op_ptr, buildFKPtr, op_key);
26385   ndbrequire(!op_ptr.isNull());
26386 
26387   if (ret == 0)
26388   {
26389     jam();
26390     sendTransConf(signal, op_ptr);
26391   }
26392   else
26393   {
26394     jam();
26395     setError(op_ptr, ret, __LINE__);
26396     sendTransRef(signal, op_ptr);
26397   }
26398 }
26399 
26400 void
buildFK_abortPrepare(Signal * signal,SchemaOpPtr op_ptr)26401 Dbdict::buildFK_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
26402 {
26403   D("buildFK_abortPrepare");
26404   jam();
26405   sendTransConf(signal, op_ptr);
26406 }
26407 
26408 // BuildFK: COMMIT
26409 
26410 void
buildFK_commit(Signal * signal,SchemaOpPtr op_ptr)26411 Dbdict::buildFK_commit(Signal* signal, SchemaOpPtr op_ptr)
26412 {
26413   D("buildFK_commit");
26414   jam();
26415   sendTransConf(signal, op_ptr);
26416 }
26417 
26418 // BuildFK: COMPLETE
26419 
26420 void
buildFK_complete(Signal * signal,SchemaOpPtr op_ptr)26421 Dbdict::buildFK_complete(Signal* signal, SchemaOpPtr op_ptr)
26422 {
26423   D("buildFK_complete");
26424   jam();
26425   sendTransConf(signal, op_ptr);
26426 }
26427 
26428 void
execBUILD_FK_REF(Signal * signal)26429 Dbdict::execBUILD_FK_REF(Signal* signal)
26430 {
26431   jamEntry();
26432   const BuildFKRef* ref = (const BuildFKRef*)signal->getDataPtr();
26433   handleDictRef(signal, ref);
26434 }
26435 
26436 void
execBUILD_FK_CONF(Signal * signal)26437 Dbdict::execBUILD_FK_CONF(Signal* signal)
26438 {
26439   jamEntry();
26440   const BuildFKConf* conf = (const BuildFKConf*)signal->getDataPtr();
26441   handleDictConf(signal, conf);
26442 }
26443 
26444 void
execBUILD_FK_IMPL_REF(Signal * signal)26445 Dbdict::execBUILD_FK_IMPL_REF(Signal* signal)
26446 {
26447   jamEntry();
26448   BuildFKImplRef * ref = (BuildFKImplRef*)signal->getDataPtr();
26449   handleDictRef(signal, ref);
26450 }
26451 
26452 void
execBUILD_FK_IMPL_CONF(Signal * signal)26453 Dbdict::execBUILD_FK_IMPL_CONF(Signal* signal)
26454 {
26455   jamEntry();
26456   BuildFKImplConf * conf = (BuildFKImplConf*)signal->getDataPtr();
26457   handleDictConf(signal, conf);
26458 }
26459 
26460 // BuildFK: END
26461 
26462 // MODULE: DropFK
26463 
26464 const Dbdict::OpInfo
26465 Dbdict::DropFKRec::g_opInfo = {
26466   { 'D', 'F', 'K', 0 },
26467   ~RT_DBDICT_DROP_FK,
26468   GSN_DROP_FK_IMPL_REQ,
26469   DropFKImplReq::SignalLength,
26470   //
26471   &Dbdict::dropFK_seize,
26472   &Dbdict::dropFK_release,
26473   //
26474   &Dbdict::dropFK_parse,
26475   &Dbdict::dropFK_subOps,
26476   &Dbdict::dropFK_reply,
26477   //
26478   &Dbdict::dropFK_prepare,
26479   &Dbdict::dropFK_commit,
26480   &Dbdict::dropFK_complete,
26481   //
26482   &Dbdict::dropFK_abortParse,
26483   &Dbdict::dropFK_abortPrepare
26484 };
26485 
26486 void
execDROP_FK_REQ(Signal * signal)26487 Dbdict::execDROP_FK_REQ(Signal* signal)
26488 {
26489   jamEntry();
26490   if (!assembleFragments(signal)) {
26491     jam();
26492     return;
26493   }
26494   SectionHandle handle(this, signal);
26495 
26496   const DropFKReq req_copy =
26497     *(const DropFKReq*)signal->getDataPtr();
26498   const DropFKReq* req = &req_copy;
26499 
26500   ErrorInfo error;
26501   do {
26502     SchemaOpPtr op_ptr;
26503     DropFKRecPtr dropFKRecPtr;
26504     DropFKImplReq* impl_req;
26505 
26506     startClientReq(op_ptr, dropFKRecPtr, req, impl_req, error);
26507     if (hasError(error)) {
26508       jam();
26509       break;
26510     }
26511 
26512     impl_req->fkId = req->fkId;
26513     impl_req->fkVersion = req->fkVersion;
26514 
26515     handleClientReq(signal, op_ptr, handle);
26516     return;
26517   } while (0);
26518 
26519   releaseSections(handle);
26520 
26521   DropFKRef* ref = (DropFKRef*)signal->getDataPtrSend();
26522   ref->senderRef = reference();
26523   ref->transId = req->transId;
26524   ref->senderData = req->senderData;
26525   getError(error, ref);
26526 
26527   sendSignal(req->senderRef, GSN_DROP_FK_REF, signal,
26528 	     DropFKRef::SignalLength, JBB);
26529 }
26530 
26531 bool
dropFK_seize(SchemaOpPtr op_ptr)26532 Dbdict::dropFK_seize(SchemaOpPtr op_ptr)
26533 {
26534   return seizeOpRec<DropFKRec>(op_ptr);
26535 }
26536 
26537 void
dropFK_release(SchemaOpPtr op_ptr)26538 Dbdict::dropFK_release(SchemaOpPtr op_ptr)
26539 {
26540   releaseOpRec<DropFKRec>(op_ptr);
26541 }
26542 
26543 // DropFK: PARSE
26544 
26545 void
dropFK_parse(Signal * signal,bool master,SchemaOpPtr op_ptr,SectionHandle & handle,ErrorInfo & error)26546 Dbdict::dropFK_parse(Signal* signal, bool master,
26547                      SchemaOpPtr op_ptr,
26548                      SectionHandle& handle, ErrorInfo& error)
26549 {
26550   D("dropFK_parse");
26551   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
26552   DropFKRecPtr dropFKRecPtr;
26553   getOpRec(op_ptr, dropFKRecPtr);
26554   DropFKImplReq* impl_req = &dropFKRecPtr.p->m_request;
26555 
26556   Ptr<ForeignKeyRec> fk_ptr;
26557   if (!find_object(fk_ptr, impl_req->fkId))
26558   {
26559     jam();
26560     setError(error, DropFKRef::FKNotFound, __LINE__);
26561     return;
26562   }
26563 
26564   if (fk_ptr.p->m_version != impl_req->fkVersion)
26565   {
26566     jam();
26567     setError(error, DropFKRef::InvalidFKVersion, __LINE__);
26568     return;
26569   }
26570 
26571   if (check_write_obj(impl_req->fkId, trans_ptr.p->m_transId,
26572                       SchemaFile::SF_DROP, error))
26573   {
26574     jam();
26575     return;
26576   }
26577 
26578   SchemaFile::TableEntry te; te.init();
26579   te.m_tableState = SchemaFile::SF_DROP;
26580   te.m_transId = trans_ptr.p->m_transId;
26581   Uint32 err = trans_log_schema_op(op_ptr, impl_req->fkId, &te);
26582   if (err)
26583   {
26584     jam();
26585     setError(error, err, __LINE__);
26586     return;
26587   }
26588 
26589 #if defined VM_TRACE || defined ERROR_INSERT
26590   {
26591     char buf[1024];
26592     LocalRope name(c_rope_pool, fk_ptr.p->m_name);
26593     name.copy(buf);
26594     ndbout_c("Dbdict: drop name=%s,id=%u,obj_id=%u", buf,
26595              impl_req->fkId,
26596              fk_ptr.p->m_obj_ptr_i);
26597   }
26598 #endif
26599 }
26600 
26601 void
dropFK_abortParse(Signal * signal,SchemaOpPtr op_ptr)26602 Dbdict::dropFK_abortParse(Signal* signal, SchemaOpPtr op_ptr)
26603 {
26604   D("dropFK_abortParse");
26605   jam();
26606   sendTransConf(signal, op_ptr);
26607 }
26608 
26609 bool
dropFK_subOps(Signal * signal,SchemaOpPtr op_ptr)26610 Dbdict::dropFK_subOps(Signal* signal, SchemaOpPtr op_ptr)
26611 {
26612   D("dropFK_subOps");
26613   DropFKRecPtr dropFKRecPtr;
26614   getOpRec(op_ptr, dropFKRecPtr);
26615 
26616   if (dropFKRecPtr.p->m_sub_drop_trigger < 2)
26617   {
26618     jam();
26619 
26620     /**
26621      * 0 - trigger on parent table
26622      * 1 - trigger on child table
26623      */
26624     Callback c = {
26625       safe_cast(&Dbdict::dropFK_fromDropTrigger),
26626       op_ptr.p->op_key
26627     };
26628     op_ptr.p->m_callback = c;
26629 
26630     dropFK_toDropTrigger(signal, op_ptr, dropFKRecPtr.p->m_sub_drop_trigger);
26631     return true;
26632   }
26633 
26634   return false;
26635 }
26636 
26637 void
dropFK_toDropTrigger(Signal * signal,SchemaOpPtr op_ptr,Uint32 no)26638 Dbdict::dropFK_toDropTrigger(Signal* signal,
26639                              SchemaOpPtr op_ptr,
26640                              Uint32 no)
26641 {
26642   D("dropFK_toDropTrigger");
26643   jam();
26644 
26645   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
26646   DropFKRecPtr dropFKPtr;
26647   getOpRec(op_ptr, dropFKPtr);
26648   const DropFKImplReq* impl_req = &dropFKPtr.p->m_request;
26649 
26650   Ptr<ForeignKeyRec> fk_ptr;
26651   ndbrequire(find_object(fk_ptr, impl_req->fkId));
26652 
26653   Uint32 triggerId = RNIL;
26654   TableRecordPtr tablePtr;
26655   if (no == 0)
26656   {
26657     jam();
26658     ndbrequire(find_object(tablePtr, fk_ptr.p->m_parentTableId));
26659     triggerId = fk_ptr.p->m_parentTriggerId;
26660   }
26661   else if (no == 1)
26662   {
26663     jam();
26664     ndbrequire(find_object(tablePtr, fk_ptr.p->m_childTableId));
26665     triggerId = fk_ptr.p->m_childTriggerId;
26666   }
26667   else
26668   {
26669     ndbrequire(false);
26670   }
26671 
26672   DropTrigReq* req = (DropTrigReq*)signal->getDataPtrSend();
26673 
26674   Uint32 requestInfo = 0;
26675   DictSignal::setRequestType(requestInfo, 0);
26676   DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
26677 
26678   req->clientRef = reference();
26679   req->clientData = op_ptr.p->op_key;
26680   req->transId = trans_ptr.p->m_transId;
26681   req->transKey = trans_ptr.p->trans_key;
26682   req->requestInfo = requestInfo;
26683   req->tableId = tablePtr.p->tableId;
26684   req->tableVersion = tablePtr.p->tableVersion;
26685   req->indexId = impl_req->fkId;
26686   req->indexVersion = impl_req->fkVersion;
26687   req->triggerNo = 0;
26688   req->triggerId = triggerId;
26689 
26690   sendSignal(reference(), GSN_DROP_TRIG_REQ, signal,
26691              DropTrigReq::SignalLength, JBB);
26692 }
26693 
26694 void
dropFK_fromDropTrigger(Signal * signal,Uint32 op_key,Uint32 ret)26695 Dbdict::dropFK_fromDropTrigger(Signal* signal, Uint32 op_key, Uint32 ret)
26696 {
26697   D("dropFK_fromDropTrigger");
26698   jamEntry();
26699 
26700   SchemaOpPtr op_ptr;
26701   DropFKRecPtr dropFKRecPtr;
26702 
26703   findSchemaOp(op_ptr, dropFKRecPtr, op_key);
26704   ndbrequire(!op_ptr.isNull());
26705   DropFKImplReq* impl_req = &dropFKRecPtr.p->m_request;
26706 
26707   if (ret == 0)
26708   {
26709     jam();
26710 
26711     const DropTrigConf* conf = CAST_CONSTPTR(DropTrigConf,
26712                                              signal->getDataPtr());
26713     (void)conf;
26714     Ptr<ForeignKeyRec> fk_ptr;
26715     ndbrequire(find_object(fk_ptr, impl_req->fkId));
26716     switch(dropFKRecPtr.p->m_sub_drop_trigger) {
26717     case 0:
26718       jam();
26719       break;
26720     case 1:
26721       jam();
26722       break;
26723     default:
26724       ndbrequire(false);
26725     }
26726 
26727     dropFKRecPtr.p->m_sub_drop_trigger++;
26728     createSubOps(signal, op_ptr);
26729   }
26730   else
26731   {
26732     jam();
26733     const DropTrigRef* ref = CAST_CONSTPTR(DropTrigRef,
26734                                              signal->getDataPtr());
26735     ErrorInfo error;
26736     setError(error, ref);
26737     abortSubOps(signal, op_ptr, error);
26738   }
26739 }
26740 
26741 void
dropFK_reply(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)26742 Dbdict::dropFK_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
26743 {
26744   D("dropFK_reply");
26745   jam();
26746   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
26747   DropFKRecPtr dropFKRecPtr;
26748   getOpRec(op_ptr, dropFKRecPtr);
26749   //DropFKImplReq* impl_req = &dropFKRecPtr.p->m_request;
26750 
26751   if (!hasError(error))
26752   {
26753     jam();
26754     DropFKConf* conf = (DropFKConf*)signal->getDataPtrSend();
26755     conf->senderRef = reference();
26756     conf->senderData = op_ptr.p->m_clientData;
26757     conf->transId = trans_ptr.p->m_transId;
26758     Uint32 clientRef = op_ptr.p->m_clientRef;
26759     sendSignal(clientRef, GSN_DROP_FK_CONF, signal,
26760                DropFKConf::SignalLength, JBB);
26761   }
26762   else
26763   {
26764     jam();
26765     DropFKRef* ref = (DropFKRef*)signal->getDataPtrSend();
26766     ref->senderRef = reference();
26767     ref->senderData = op_ptr.p->m_clientData;
26768     ref->transId = trans_ptr.p->m_transId;
26769     getError(error, ref);
26770 
26771     Uint32 clientRef = op_ptr.p->m_clientRef;
26772     sendSignal(clientRef, GSN_DROP_FK_REF, signal,
26773                DropFKRef::SignalLength, JBB);
26774   }
26775 }
26776 
26777 // DropFK: PREPARE
26778 
26779 void
dropFK_prepare(Signal * signal,SchemaOpPtr op_ptr)26780 Dbdict::dropFK_prepare(Signal* signal, SchemaOpPtr op_ptr)
26781 {
26782   D("dropFK_prepare");
26783   jam();
26784   DropFKRecPtr dropFKRecPtr;
26785   getOpRec(op_ptr, dropFKRecPtr);
26786   DropFKImplReq* impl_req = &dropFKRecPtr.p->m_request;
26787   impl_req->requestType = DropFKImplReq::RT_PREPARE;
26788 
26789   sendTransConf(signal, op_ptr);
26790 }
26791 
26792 void
dropFK_abortPrepare(Signal * signal,SchemaOpPtr op_ptr)26793 Dbdict::dropFK_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
26794 {
26795   D("dropFK_abortPrepare");
26796   DropFKRecPtr dropFKRecPtr;
26797   getOpRec(op_ptr, dropFKRecPtr);
26798   DropFKImplReq* impl_req = &dropFKRecPtr.p->m_request;
26799   impl_req->requestType = DropFKImplReq::RT_ABORT;
26800 
26801   sendTransConf(signal, op_ptr);
26802 }
26803 
26804 // DropFK: COMMIT
26805 
26806 void
dropFK_fromLocal(Signal * signal,Uint32 op_key,Uint32 ret)26807 Dbdict::dropFK_fromLocal(Signal* signal, Uint32 op_key, Uint32 ret)
26808 {
26809   D("dropFK_fromLocal");
26810   jamEntry();
26811 
26812   SchemaOpPtr op_ptr;
26813   DropFKRecPtr dropFKRecPtr;
26814   findSchemaOp(op_ptr, dropFKRecPtr, op_key);
26815   ndbrequire(!op_ptr.isNull());
26816 
26817   if (ret == 0)
26818   {
26819     jam();
26820     DropFKImplReq* impl_req = &dropFKRecPtr.p->m_request;
26821     Ptr<ForeignKeyRec> fk_ptr;
26822     ndbrequire(find_object(fk_ptr, impl_req->fkId));
26823 
26824     release_object(fk_ptr.p->m_obj_ptr_i);
26825 
26826     sendTransConf(signal, op_ptr);
26827   } else {
26828     jam();
26829     setError(op_ptr, ret, __LINE__);
26830     sendTransRef(signal, op_ptr);
26831   }
26832 }
26833 
26834 void
dropFK_commit(Signal * signal,SchemaOpPtr op_ptr)26835 Dbdict::dropFK_commit(Signal* signal, SchemaOpPtr op_ptr)
26836 {
26837   D("dropFK_commit");
26838   jam();
26839   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
26840   DropFKRecPtr dropFKRecPtr;
26841   getOpRec(op_ptr, dropFKRecPtr);
26842   DropFKImplReq* impl_req = &dropFKRecPtr.p->m_request;
26843   impl_req->requestType = DropFKImplReq::RT_COMMIT;
26844   sendTransConf(signal, trans_ptr);
26845 }
26846 
26847 void
send_drop_fk_req(Signal * signal,SchemaOpPtr op_ptr)26848 Dbdict::send_drop_fk_req(Signal* signal, SchemaOpPtr op_ptr)
26849 {
26850   DropFKRecPtr dropFKPtr;
26851   getOpRec(op_ptr, dropFKPtr);
26852   const DropFKImplReq* impl_req = &dropFKPtr.p->m_request;
26853 
26854   DropFKImplReq* req = (DropFKImplReq*)signal->getDataPtrSend();
26855 
26856   req->senderRef = reference();
26857   req->senderData = op_ptr.p->op_key;
26858   req->requestType = impl_req->requestType;
26859   req->fkId = impl_req->fkId;
26860   req->fkVersion = impl_req->fkVersion;
26861 
26862   sendSignal(DBTC_REF, GSN_DROP_FK_IMPL_REQ, signal,
26863              DropFKImplReq::SignalLength, JBB);
26864 }
26865 
26866 // DropFK: COMPLETE
26867 
26868 void
dropFK_complete(Signal * signal,SchemaOpPtr op_ptr)26869 Dbdict::dropFK_complete(Signal* signal, SchemaOpPtr op_ptr)
26870 {
26871   D("dropFK_complete");
26872   jam();
26873 
26874   DropFKRecPtr dropFKRecPtr;
26875   getOpRec(op_ptr, dropFKRecPtr);
26876   DropFKImplReq* impl_req = &dropFKRecPtr.p->m_request;
26877 
26878   impl_req->requestType = DropFKImplReq::RT_COMPLETE;
26879 
26880   /**
26881    * drop the FK in complete...as it needs to be done after
26882    *   triggers are dropped...which they are in commit
26883    */
26884   Callback c =  { safe_cast(&Dbdict::dropFK_fromLocal), op_ptr.p->op_key };
26885   op_ptr.p->m_callback = c;
26886 
26887   send_drop_fk_req(signal, op_ptr);
26888 }
26889 
26890 void
execDROP_FK_IMPL_REF(Signal * signal)26891 Dbdict::execDROP_FK_IMPL_REF(Signal* signal)
26892 {
26893   jamEntry();
26894   DropFKImplRef * ref = (DropFKImplRef*)signal->getDataPtr();
26895   handleDictRef(signal, ref);
26896 }
26897 
26898 void
execDROP_FK_IMPL_CONF(Signal * signal)26899 Dbdict::execDROP_FK_IMPL_CONF(Signal* signal)
26900 {
26901   jamEntry();
26902   DropFKImplConf * conf = (DropFKImplConf*)signal->getDataPtr();
26903   handleDictConf(signal, conf);
26904 }
26905 
26906 // DropFK: END
26907 
26908 
26909 /*
26910   return 1 if all of the below is true
26911   a) node in single user mode
26912   b) senderRef is not a db node
26913   c) senderRef nodeid is not the singleUserApi
26914 */
checkSingleUserMode(Uint32 senderRef)26915 int Dbdict::checkSingleUserMode(Uint32 senderRef)
26916 {
26917   Uint32 nodeId = refToNode(senderRef);
26918   return
26919     getNodeState().getSingleUserMode() &&
26920     (getNodeInfo(nodeId).m_type != NodeInfo::DB) &&
26921     (nodeId != getNodeState().getSingleUserApi());
26922 }
26923 
26924 // MODULE: SchemaTrans
26925 
26926 // ErrorInfo
26927 
26928 void
setError(ErrorInfo & e,Uint32 code,Uint32 line,Uint32 nodeId,Uint32 status,Uint32 key,const char * name)26929 Dbdict::setError(ErrorInfo& e,
26930                  Uint32 code,
26931                  Uint32 line,
26932                  Uint32 nodeId,
26933                  Uint32 status,
26934                  Uint32 key,
26935                  const char * name)
26936 {
26937   D("setError" << V(code) << V(line) << V(nodeId) << V(e.errorCount));
26938 
26939   // can only store details for first error
26940   if (e.errorCount == 0) {
26941     e.errorCode = code;
26942     e.errorLine = line;
26943     e.errorNodeId = nodeId ? nodeId : getOwnNodeId();
26944     e.errorStatus = status;
26945     e.errorKey = key;
26946     BaseString::snprintf(e.errorObjectName, sizeof(e.errorObjectName), "%s",
26947                          name ? name : "");
26948   }
26949   e.errorCount++;
26950 }
26951 
26952 void
setError(ErrorInfo & e,Uint32 code,Uint32 line,const char * name)26953 Dbdict::setError(ErrorInfo& e,
26954                  Uint32 code,
26955                  Uint32 line,
26956                  const char * name)
26957 {
26958   setError(e, code, line, 0, 0, 0, name);
26959 }
26960 
26961 void
setError(ErrorInfo & e,const ErrorInfo & e2)26962 Dbdict::setError(ErrorInfo& e, const ErrorInfo& e2)
26963 {
26964   setError(e, e2.errorCode, e2.errorLine, e2.errorNodeId);
26965 }
26966 
26967 void
setError(ErrorInfo & e,const ParseDictTabInfoRecord & e2)26968 Dbdict::setError(ErrorInfo& e, const ParseDictTabInfoRecord& e2)
26969 {
26970   setError(e, e2.errorCode, e2.errorLine, 0, e2.status, e2.errorKey);
26971 }
26972 
26973 void
setError(SchemaOpPtr op_ptr,Uint32 code,Uint32 line,Uint32 nodeId)26974 Dbdict::setError(SchemaOpPtr op_ptr, Uint32 code, Uint32 line, Uint32 nodeId)
26975 {
26976   D("setError" << *op_ptr.p << V(code) << V(line) << V(nodeId));
26977   setError(op_ptr.p->m_error, code, line, nodeId);
26978 
26979   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
26980   // wl3600_todo remove the check
26981   if (!trans_ptr.isNull()) {
26982     setError(trans_ptr.p->m_error, op_ptr.p->m_error);
26983   }
26984 }
26985 
26986 void
setError(SchemaOpPtr op_ptr,const ErrorInfo & e2)26987 Dbdict::setError(SchemaOpPtr op_ptr, const ErrorInfo& e2)
26988 {
26989   setError(op_ptr, e2.errorCode, e2.errorLine, e2.errorNodeId);
26990 }
26991 
26992 void
setError(SchemaTransPtr trans_ptr,Uint32 code,Uint32 line,Uint32 nodeId)26993 Dbdict::setError(SchemaTransPtr trans_ptr, Uint32 code, Uint32 line, Uint32 nodeId)
26994 {
26995   D("setError" << *trans_ptr.p << V(code) << V(line) << V(nodeId));
26996   setError(trans_ptr.p->m_error, code, line, nodeId);
26997 }
26998 
26999 void
setError(SchemaTransPtr trans_ptr,const ErrorInfo & e2)27000 Dbdict::setError(SchemaTransPtr trans_ptr, const ErrorInfo& e2)
27001 {
27002   setError(trans_ptr, e2.errorCode, e2.errorLine, e2.errorNodeId);
27003 }
27004 
27005 void
setError(TxHandlePtr tx_ptr,Uint32 code,Uint32 line,Uint32 nodeId)27006 Dbdict::setError(TxHandlePtr tx_ptr, Uint32 code, Uint32 line, Uint32 nodeId)
27007 {
27008   D("setError" << *tx_ptr.p << V(code) << V(line) << V(nodeId));
27009   setError(tx_ptr.p->m_error, code, line, nodeId);
27010 }
27011 
27012 void
setError(TxHandlePtr tx_ptr,const ErrorInfo & e2)27013 Dbdict::setError(TxHandlePtr tx_ptr, const ErrorInfo& e2)
27014 {
27015   setError(tx_ptr, e2.errorCode, e2.errorLine, e2.errorNodeId);
27016 }
27017 
27018 bool
hasError(const ErrorInfo & e)27019 Dbdict::hasError(const ErrorInfo& e)
27020 {
27021   return e.errorCount != 0;
27022 }
27023 
27024 void
resetError(ErrorInfo & e)27025 Dbdict::resetError(ErrorInfo& e)
27026 {
27027   new (&e) ErrorInfo();
27028 }
27029 
27030 void
resetError(SchemaOpPtr op_ptr)27031 Dbdict::resetError(SchemaOpPtr op_ptr)
27032 {
27033   if (hasError(op_ptr.p->m_error)) {
27034     jam();
27035     D("resetError" << *op_ptr.p);
27036     resetError(op_ptr.p->m_error);
27037   }
27038 }
27039 
27040 void
resetError(SchemaTransPtr trans_ptr)27041 Dbdict::resetError(SchemaTransPtr trans_ptr)
27042 {
27043   if (hasError(trans_ptr.p->m_error)) {
27044     jam();
27045     D("resetError" << *trans_ptr.p);
27046     resetError(trans_ptr.p->m_error);
27047   }
27048 }
27049 
27050 void
resetError(TxHandlePtr tx_ptr)27051 Dbdict::resetError(TxHandlePtr tx_ptr)
27052 {
27053   if (hasError(tx_ptr.p->m_error)) {
27054     jam();
27055     D("resetError" << *tx_ptr.p);
27056     resetError(tx_ptr.p->m_error);
27057   }
27058 }
27059 
27060 // OpInfo
27061 
27062 const Dbdict::OpInfo*
27063 Dbdict::g_opInfoList[] = {
27064   &Dbdict::CreateTableRec::g_opInfo,
27065   &Dbdict::DropTableRec::g_opInfo,
27066   &Dbdict::AlterTableRec::g_opInfo,
27067   &Dbdict::CreateTriggerRec::g_opInfo,
27068   &Dbdict::DropTriggerRec::g_opInfo,
27069   &Dbdict::CreateIndexRec::g_opInfo,
27070   &Dbdict::DropIndexRec::g_opInfo,
27071   &Dbdict::AlterIndexRec::g_opInfo,
27072   &Dbdict::BuildIndexRec::g_opInfo,
27073   &Dbdict::IndexStatRec::g_opInfo,
27074   &Dbdict::CreateFilegroupRec::g_opInfo,
27075   &Dbdict::CreateFileRec::g_opInfo,
27076   &Dbdict::DropFilegroupRec::g_opInfo,
27077   &Dbdict::DropFileRec::g_opInfo,
27078   &Dbdict::CreateHashMapRec::g_opInfo,
27079   &Dbdict::CopyDataRec::g_opInfo,
27080   &Dbdict::CreateNodegroupRec::g_opInfo,
27081   &Dbdict::DropNodegroupRec::g_opInfo,
27082   &Dbdict::CreateFKRec::g_opInfo,
27083   &Dbdict::DropFKRec::g_opInfo,
27084   &Dbdict::BuildFKRec::g_opInfo,
27085   0
27086 };
27087 
27088 const Dbdict::OpInfo*
findOpInfo(Uint32 gsn)27089 Dbdict::findOpInfo(Uint32 gsn)
27090 {
27091   Uint32 i = 0;
27092   while (g_opInfoList[i]) {
27093     const OpInfo* info = g_opInfoList[i];
27094     if (info->m_impl_req_gsn == 0)
27095       break;
27096     if (info->m_impl_req_gsn == gsn)
27097       return info;
27098     i++;
27099   }
27100   ndbrequire(false);
27101   return 0;
27102 }
27103 
27104 // OpRec
27105 
27106 // OpSection
27107 
27108 bool
copyIn(OpSectionBufferPool & pool,OpSection & op_sec,const SegmentedSectionPtr & ss_ptr)27109 Dbdict::copyIn(OpSectionBufferPool& pool, OpSection& op_sec, const SegmentedSectionPtr& ss_ptr)
27110 {
27111   const Uint32 size = 1024;
27112   Uint32 buf[size];
27113 
27114   SegmentedSectionPtr tmp = ss_ptr;
27115   SectionReader reader(tmp, getSectionSegmentPool());
27116   Uint32 len = ss_ptr.sz;
27117   while (len > size)
27118   {
27119     jam();
27120     ndbrequire(reader.getWords(buf, size));
27121     if (!copyIn(pool, op_sec, buf, size))
27122     {
27123       jam();
27124       return false;
27125     }
27126     len -= size;
27127   }
27128 
27129   ndbrequire(reader.getWords(buf, len));
27130   if (!copyIn(pool, op_sec, buf, len))
27131   {
27132     jam();
27133     return false;
27134   }
27135 
27136   return true;
27137 }
27138 
27139 bool
copyIn(OpSectionBufferPool & pool,OpSection & op_sec,const Uint32 * src,Uint32 srcSize)27140 Dbdict::copyIn(OpSectionBufferPool& pool, OpSection& op_sec, const Uint32* src, Uint32 srcSize)
27141 {
27142   OpSectionBuffer buffer(pool, op_sec.m_head);
27143   if (!buffer.append(src, srcSize)) {
27144     jam();
27145     return false;
27146   }
27147   return true;
27148 }
27149 
27150 bool
copyOut(Dbdict::OpSectionBuffer & buffer,Dbdict::OpSectionBufferConstIterator & iter,Uint32 * dst,Uint32 len)27151 Dbdict::copyOut(Dbdict::OpSectionBuffer & buffer,
27152                 Dbdict::OpSectionBufferConstIterator & iter,
27153                 Uint32 * dst,
27154                 Uint32 len)
27155 {
27156   Uint32 n = 0;
27157   for(; !iter.isNull() && n < len; buffer.next(iter))
27158   {
27159     dst[n] = *iter.data;
27160     n++;
27161   }
27162 
27163   return n == len;
27164 }
27165 
27166 bool
copyOut(OpSectionBufferPool & pool,const OpSection & op_sec,SegmentedSectionPtr & ss_ptr)27167 Dbdict::copyOut(OpSectionBufferPool& pool, const OpSection& op_sec, SegmentedSectionPtr& ss_ptr)
27168 {
27169   const Uint32 size = 1024;
27170   Uint32 buf[size];
27171 
27172   Uint32 len = op_sec.getSize();
27173   OpSectionBufferHead tmp_head = op_sec.m_head;
27174 
27175   OpSectionBuffer buffer(pool, tmp_head);
27176 
27177   OpSectionBufferConstIterator iter;
27178   buffer.first(iter);
27179   Uint32 ptrI = RNIL;
27180   while (len > size)
27181   {
27182     if (!copyOut(buffer, iter, buf, size))
27183     {
27184       jam();
27185       goto fail;
27186     }
27187     if (!appendToSection(ptrI, buf, size))
27188     {
27189       jam();
27190       goto fail;
27191     }
27192     len -= size;
27193   }
27194 
27195   if (!copyOut(buffer, iter, buf, len))
27196   {
27197     jam();
27198     goto fail;
27199   }
27200 
27201   if (!appendToSection(ptrI, buf, len))
27202   {
27203     jam();
27204     goto fail;
27205   }
27206 
27207   getSection(ss_ptr, ptrI);
27208   return true;
27209 
27210 fail:
27211   releaseSection(ptrI);
27212   return false;
27213 }
27214 
27215 bool
copyOut(OpSectionBufferPool & pool,const OpSection & op_sec,Uint32 * dst,Uint32 dstSize)27216 Dbdict::copyOut(OpSectionBufferPool& pool, const OpSection& op_sec, Uint32* dst, Uint32 dstSize)
27217 {
27218   if (op_sec.getSize() > dstSize) {
27219     jam();
27220     return false;
27221   }
27222 
27223   // there is no const version of LocalDataBuffer
27224   OpSectionBufferHead tmp_head = op_sec.m_head;
27225   OpSectionBuffer buffer(pool, tmp_head);
27226 
27227   OpSectionBufferConstIterator iter;
27228   Uint32 n = 0;
27229   for(buffer.first(iter); !iter.isNull(); buffer.next(iter)) {
27230     jam();
27231     dst[n] = *iter.data;
27232     n++;
27233   }
27234   ndbrequire(n == op_sec.getSize());
27235   return true;
27236 }
27237 
27238 void
release(OpSectionBufferPool & pool,OpSection & op_sec)27239 Dbdict::release(OpSectionBufferPool& pool, OpSection& op_sec)
27240 {
27241   OpSectionBuffer buffer(pool, op_sec.m_head);
27242   buffer.release();
27243 }
27244 
27245 // SchemaOp
27246 
27247 const Dbdict::OpInfo&
getOpInfo(SchemaOpPtr op_ptr)27248 Dbdict::getOpInfo(SchemaOpPtr op_ptr)
27249 {
27250   ndbrequire(!op_ptr.isNull());
27251   OpRecPtr oprec_ptr = op_ptr.p->m_oprec_ptr;
27252   ndbrequire(!oprec_ptr.isNull());
27253   return oprec_ptr.p->m_opInfo;
27254 }
27255 
27256 bool
seizeSchemaOp(SchemaTransPtr trans_ptr,SchemaOpPtr & op_ptr,Uint32 op_key,const OpInfo & info,bool linked)27257 Dbdict::seizeSchemaOp(SchemaTransPtr trans_ptr, SchemaOpPtr& op_ptr, Uint32 op_key, const OpInfo& info, bool linked)
27258 {
27259   if ((ERROR_INSERTED(6111) &&
27260        (info.m_impl_req_gsn == GSN_CREATE_TAB_REQ ||
27261         info.m_impl_req_gsn == GSN_DROP_TAB_REQ ||
27262         info.m_impl_req_gsn == GSN_ALTER_TAB_REQ)) ||
27263       (ERROR_INSERTED(6112) &&
27264        (info.m_impl_req_gsn == GSN_CREATE_INDX_IMPL_REQ ||
27265         info.m_impl_req_gsn == GSN_DROP_INDX_IMPL_REQ)) ||
27266       (ERROR_INSERTED(6113) &&
27267        (info.m_impl_req_gsn == GSN_ALTER_INDX_IMPL_REQ)) ||
27268       (ERROR_INSERTED(6114) &&
27269        (info.m_impl_req_gsn == GSN_CREATE_TRIG_IMPL_REQ ||
27270         info.m_impl_req_gsn == GSN_DROP_TRIG_IMPL_REQ)) ||
27271       (ERROR_INSERTED(6116) &&
27272        (info.m_impl_req_gsn == GSN_BUILD_INDX_IMPL_REQ)))
27273   {
27274     jam();
27275     CLEAR_ERROR_INSERT_VALUE;
27276     op_ptr.setNull();
27277     return false;
27278   }
27279 
27280   if (!findSchemaOp(op_ptr, op_key)) {
27281     jam();
27282     if (c_schemaOpPool.seize(trans_ptr.p->m_arena, op_ptr)) {
27283       jam();
27284       new (op_ptr.p) SchemaOp();
27285       op_ptr.p->op_key = op_key;
27286       op_ptr.p->m_trans_ptr = trans_ptr;
27287       if ((this->*(info.m_seize))(op_ptr)) {
27288         jam();
27289 
27290         if(!linked) {
27291           jam();
27292           addSchemaOp(op_ptr);
27293         }
27294 
27295         c_schemaOpHash.add(op_ptr);
27296         D("seizeSchemaOp" << V(op_key) << V(info.m_opType));
27297         return true;
27298       }
27299       c_schemaOpPool.release(op_ptr);
27300     }
27301   }
27302   op_ptr.setNull();
27303   return false;
27304 }
27305 
27306 bool
findSchemaOp(SchemaOpPtr & op_ptr,Uint32 op_key)27307 Dbdict::findSchemaOp(SchemaOpPtr& op_ptr, Uint32 op_key)
27308 {
27309   SchemaOp op_rec(op_key);
27310   if (c_schemaOpHash.find(op_ptr, op_rec)) {
27311     jam();
27312     const OpRecPtr& oprec_ptr = op_ptr.p->m_oprec_ptr;
27313     ndbrequire(!oprec_ptr.isNull());
27314     ndbrequire(op_ptr.p->m_magic == SchemaOp::DICT_MAGIC);
27315     D("findSchemaOp" << V(op_key));
27316     return true;
27317   }
27318   return false;
27319 }
27320 
27321 void
releaseSchemaOp(SchemaOpPtr & op_ptr)27322 Dbdict::releaseSchemaOp(SchemaOpPtr& op_ptr)
27323 {
27324   D("releaseSchemaOp" << V(op_ptr.p->op_key));
27325 
27326   const OpInfo& info = getOpInfo(op_ptr);
27327 
27328   /* Release first any sections connected to this Schema Operation */
27329 
27330   while (op_ptr.p->m_sections != 0)
27331   {
27332     jam();
27333     releaseOpSection(op_ptr, op_ptr.p->m_sections - 1);
27334   }
27335 
27336   /* Now unlink any DICT objects connected to this schema operation */
27337 
27338   OpRecPtr oprec_ptr = op_ptr.p->m_oprec_ptr;
27339   Uint32 obj_ptr_i = oprec_ptr.p->m_obj_ptr_i;
27340   if (obj_ptr_i != RNIL)
27341   {
27342     jam();
27343     unlinkDictObject(op_ptr);
27344   }
27345 
27346   /**
27347    * Now that we have released sections and objects connected to the
27348    * operation record specific for this schema operation, we're ready
27349    * to release the specific schema operation and unlink it from the
27350    * schema operation.
27351    */
27352   (this->*(info.m_release))(op_ptr);
27353 
27354   /**
27355    * Now we will release all schema operations and their connected records
27356    * associated with this schema operation. (Recursive call!)
27357    */
27358   if (!op_ptr.p->m_oplnk_ptr.isNull())
27359   {
27360     jam();
27361     releaseSchemaOp(op_ptr.p->m_oplnk_ptr);
27362   }
27363 
27364   /**
27365    * Now we only have remaining the schema operation, so we release this,
27366    * but first we remove it from the hash table. Finally we ensure that
27367    * we don't reuse the operation pointer.
27368    */
27369   ndbrequire(op_ptr.p->m_magic == SchemaOp::DICT_MAGIC);
27370   c_schemaOpHash.remove(op_ptr);
27371   c_schemaOpPool.release(op_ptr);
27372   op_ptr.setNull();
27373 }
27374 
27375 // save signal sections
27376 
27377 const Dbdict::OpSection&
getOpSection(SchemaOpPtr op_ptr,Uint32 ss_no)27378 Dbdict::getOpSection(SchemaOpPtr op_ptr, Uint32 ss_no)
27379 {
27380   ndbrequire(ss_no < op_ptr.p->m_sections);
27381   return op_ptr.p->m_section[ss_no];
27382 }
27383 
27384 bool
saveOpSection(SchemaOpPtr op_ptr,SectionHandle & handle,Uint32 ss_no)27385 Dbdict::saveOpSection(SchemaOpPtr op_ptr,
27386                       SectionHandle& handle, Uint32 ss_no)
27387 {
27388   SegmentedSectionPtr ss_ptr;
27389   bool ok = handle.getSection(ss_ptr, ss_no);
27390   ndbrequire(ok);
27391   return saveOpSection(op_ptr, ss_ptr, ss_no);
27392 }
27393 
27394 bool
saveOpSection(SchemaOpPtr op_ptr,SegmentedSectionPtr ss_ptr,Uint32 ss_no)27395 Dbdict::saveOpSection(SchemaOpPtr op_ptr,
27396                       SegmentedSectionPtr ss_ptr, Uint32 ss_no)
27397 {
27398   ndbrequire(ss_no <= 2 && op_ptr.p->m_sections == ss_no);
27399   OpSection& op_sec = op_ptr.p->m_section[ss_no];
27400   op_ptr.p->m_sections++;
27401 
27402   LocalArenaPoolImpl op_sec_pool(op_ptr.p->m_trans_ptr.p->m_arena, c_opSectionBufferPool);
27403   bool ok =  copyIn(op_sec_pool, op_sec, ss_ptr);
27404   ndbrequire(ok);
27405   return true;
27406 }
27407 
27408 void
releaseOpSection(SchemaOpPtr op_ptr,Uint32 ss_no)27409 Dbdict::releaseOpSection(SchemaOpPtr op_ptr, Uint32 ss_no)
27410 {
27411   ndbrequire(ss_no + 1 == op_ptr.p->m_sections);
27412   OpSection& op_sec = op_ptr.p->m_section[ss_no];
27413   LocalArenaPoolImpl op_sec_pool(op_ptr.p->m_trans_ptr.p->m_arena, c_opSectionBufferPool);
27414   release(op_sec_pool, op_sec);
27415   op_ptr.p->m_sections = ss_no;
27416 }
27417 
27418 // add schema op to trans during parse phase
27419 
27420 void
addSchemaOp(SchemaOpPtr op_ptr)27421 Dbdict::addSchemaOp(SchemaOpPtr op_ptr)
27422 {
27423   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
27424   LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
27425   list.addLast(op_ptr);
27426 
27427   // jonas_todo REMOVE side effect
27428   // add global flags from trans
27429   const Uint32& src_info = trans_ptr.p->m_requestInfo;
27430   DictSignal::addRequestFlagsGlobal(op_ptr.p->m_requestInfo, src_info);
27431 }
27432 
27433 // update op step after successful execution
27434 
27435 // the link SchemaOp -> DictObject -> SchemaTrans
27436 
27437 // check if link to dict object exists
27438 bool
hasDictObject(SchemaOpPtr op_ptr)27439 Dbdict::hasDictObject(SchemaOpPtr op_ptr)
27440 {
27441   OpRecPtr oprec_ptr = op_ptr.p->m_oprec_ptr;
27442   return oprec_ptr.p->m_obj_ptr_i != RNIL;
27443 }
27444 
27445 // get dict object for existing link
27446 void
getDictObject(SchemaOpPtr op_ptr,DictObjectPtr & obj_ptr)27447 Dbdict::getDictObject(SchemaOpPtr op_ptr, DictObjectPtr& obj_ptr)
27448 {
27449   OpRecPtr oprec_ptr = op_ptr.p->m_oprec_ptr;
27450   ndbrequire(oprec_ptr.p->m_obj_ptr_i != RNIL);
27451   c_obj_pool.getPtr(obj_ptr, oprec_ptr.p->m_obj_ptr_i);
27452 }
27453 
27454 // create link from schema op to dict object
27455 void
linkDictObject(SchemaOpPtr op_ptr,DictObjectPtr obj_ptr)27456 Dbdict::linkDictObject(SchemaOpPtr op_ptr, DictObjectPtr obj_ptr)
27457 {
27458   ndbrequire(!obj_ptr.isNull());
27459   D("linkDictObject" << V(op_ptr.p->op_key) << V(obj_ptr.i));
27460 
27461   OpRecPtr oprec_ptr = op_ptr.p->m_oprec_ptr;
27462   ndbrequire(oprec_ptr.p->m_obj_ptr_i == RNIL);
27463   oprec_ptr.p->m_obj_ptr_i = obj_ptr.i;
27464 
27465   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
27466   if (!trans_ptr.isNull()) {
27467     jam();
27468     ndbrequire(trans_ptr.p->trans_key != 0);
27469     if (obj_ptr.p->m_op_ref_count == 0) {
27470       jam();
27471       obj_ptr.p->m_trans_key = trans_ptr.p->trans_key;
27472     } else {
27473       ndbrequire(obj_ptr.p->m_trans_key == trans_ptr.p->trans_key);
27474     }
27475   } else {
27476     jam();
27477     // restart table uses no trans (yet)
27478     ndbrequire(memcmp(oprec_ptr.p->m_opType, "CTa", 4) == 0);
27479     ndbrequire(getNodeState().startLevel != NodeState::SL_STARTED);
27480   }
27481 
27482   obj_ptr.p->m_op_ref_count += 1;
27483   D("linkDictObject done" << *obj_ptr.p);
27484 }
27485 
27486 // drop link from schema op to dict object
27487 void
unlinkDictObject(SchemaOpPtr op_ptr)27488 Dbdict::unlinkDictObject(SchemaOpPtr op_ptr)
27489 {
27490   DictObjectPtr obj_ptr;
27491   OpRecPtr oprec_ptr = op_ptr.p->m_oprec_ptr;
27492   ndbrequire(oprec_ptr.p->m_obj_ptr_i != RNIL);
27493   c_obj_pool.getPtr(obj_ptr, oprec_ptr.p->m_obj_ptr_i);
27494 
27495   D("unlinkDictObject" << V(op_ptr.p->op_key) << V(obj_ptr.i));
27496 
27497   oprec_ptr.p->m_obj_ptr_i = RNIL;
27498   ndbrequire(obj_ptr.p->m_op_ref_count != 0);
27499   obj_ptr.p->m_op_ref_count -= 1;
27500   ndbrequire(obj_ptr.p->m_trans_key != 0);
27501   if (obj_ptr.p->m_op_ref_count == 0) {
27502     jam();
27503     obj_ptr.p->m_trans_key = 0;
27504   }
27505   D("unlinkDictObject done" << *obj_ptr.p);
27506 }
27507 
27508 // add new dict object and link schema op to it
27509 void
seizeDictObject(SchemaOpPtr op_ptr,DictObjectPtr & obj_ptr,const RopeHandle & name)27510 Dbdict::seizeDictObject(SchemaOpPtr op_ptr,
27511                         DictObjectPtr& obj_ptr,
27512                         const RopeHandle& name)
27513 {
27514   D("seizeDictObject" << *op_ptr.p);
27515 
27516   bool ok = c_obj_pool.seize(obj_ptr);
27517   ndbrequire(ok);
27518   new (obj_ptr.p) DictObject();
27519 
27520   obj_ptr.p->m_name = name;
27521   c_obj_name_hash.add(obj_ptr);
27522   obj_ptr.p->m_ref_count = 0;
27523 
27524   linkDictObject(op_ptr, obj_ptr);
27525   D("seizeDictObject done" << *obj_ptr.p);
27526 }
27527 
27528 // find dict object by name and link schema op to it
27529 bool
findDictObject(SchemaOpPtr op_ptr,DictObjectPtr & obj_ptr,const char * name)27530 Dbdict::findDictObject(SchemaOpPtr op_ptr,
27531                        DictObjectPtr& obj_ptr,
27532                        const char* name)
27533 {
27534   D("findDictObject" << *op_ptr.p << V(name));
27535   if (get_object(obj_ptr, name)) {
27536     jam();
27537     linkDictObject(op_ptr, obj_ptr);
27538     return true;
27539   }
27540   return false;
27541 }
27542 
27543 // find dict object by i-value and link schema op to it
27544 bool
findDictObject(SchemaOpPtr op_ptr,DictObjectPtr & obj_ptr,Uint32 obj_ptr_i)27545 Dbdict::findDictObject(SchemaOpPtr op_ptr,
27546                        DictObjectPtr& obj_ptr,
27547                        Uint32 obj_ptr_i)
27548 {
27549   D("findDictObject" << *op_ptr.p << V(obj_ptr.i));
27550   if (obj_ptr_i != RNIL) {
27551     jam();
27552     c_obj_pool.getPtr(obj_ptr, obj_ptr_i);
27553     linkDictObject(op_ptr, obj_ptr);
27554     return true;
27555   }
27556   return false;
27557 }
27558 
27559 // remove link to dict object and release the dict object
27560 void
releaseDictObject(SchemaOpPtr op_ptr)27561 Dbdict::releaseDictObject(SchemaOpPtr op_ptr)
27562 {
27563   DictObjectPtr obj_ptr;
27564   getDictObject(op_ptr, obj_ptr);
27565 
27566   D("releaseDictObject" << *op_ptr.p << V(obj_ptr.i) << *obj_ptr.p);
27567 
27568   unlinkDictObject(op_ptr);
27569 
27570   // check no other object or operation references it
27571   ndbrequire(obj_ptr.p->m_ref_count == 0);
27572   if (obj_ptr.p->m_op_ref_count == 0) {
27573     jam();
27574     release_object(obj_ptr.i);
27575   }
27576 }
27577 
27578 // find last op on dict object
27579 void
findDictObjectOp(SchemaOpPtr & op_ptr,DictObjectPtr obj_ptr)27580 Dbdict::findDictObjectOp(SchemaOpPtr& op_ptr, DictObjectPtr obj_ptr)
27581 {
27582   D("findDictObjectOp" << *obj_ptr.p);
27583   op_ptr.setNull();
27584 
27585   Uint32 trans_key = obj_ptr.p->m_trans_key;
27586   do {
27587     if (trans_key == 0) {
27588       jam();
27589       D("no trans_key");
27590       break;
27591     }
27592 
27593     SchemaTransPtr trans_ptr;
27594     findSchemaTrans(trans_ptr, trans_key);
27595     if (trans_ptr.isNull()) {
27596       jam();
27597       D("trans not found");
27598       break;
27599     }
27600     D("found" << *trans_ptr.p);
27601 
27602     {
27603       LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
27604       SchemaOpPtr loop_ptr;
27605       list.first(loop_ptr);
27606       while (!loop_ptr.isNull()) {
27607         jam();
27608         OpRecPtr oprec_ptr = loop_ptr.p->m_oprec_ptr;
27609         if (oprec_ptr.p->m_obj_ptr_i == obj_ptr.i) {
27610           jam();
27611           op_ptr = loop_ptr;
27612           D("found candidate" << *op_ptr.p);
27613         }
27614         list.next(loop_ptr);
27615       }
27616     }
27617   } while (0);
27618 }
27619 
27620 // trans state
27621 
27622 
27623 // SchemaTrans
27624 
27625 bool
seizeSchemaTrans(SchemaTransPtr & trans_ptr,Uint32 trans_key)27626 Dbdict::seizeSchemaTrans(SchemaTransPtr& trans_ptr, Uint32 trans_key)
27627 {
27628   if (ERROR_INSERTED(6101)) {
27629     jam();
27630     CLEAR_ERROR_INSERT_VALUE;
27631     trans_ptr.setNull();
27632     return false;
27633   }
27634   if (!findSchemaTrans(trans_ptr, trans_key)) {
27635     jam();
27636     ArenaHead arena;
27637     bool ok = c_arenaAllocator.seize(arena);
27638     ndbrequire(ok); // TODO: report error
27639     if (c_schemaTransPool.seize(arena, trans_ptr)) {
27640       jam();
27641       new (trans_ptr.p) SchemaTrans();
27642       trans_ptr.p->trans_key = trans_key;
27643       trans_ptr.p->m_arena = arena;
27644       c_schemaTransHash.add(trans_ptr);
27645       c_schemaTransList.addLast(trans_ptr);
27646       c_schemaTransCount++;
27647       D("seizeSchemaTrans" << V(trans_key));
27648       return true;
27649     }
27650     c_arenaAllocator.release(arena);
27651   }
27652   trans_ptr.setNull();
27653   return false;
27654 }
27655 
27656 bool
seizeSchemaTrans(SchemaTransPtr & trans_ptr)27657 Dbdict::seizeSchemaTrans(SchemaTransPtr& trans_ptr)
27658 {
27659   Uint32 trans_key = c_opRecordSequence + 1;
27660   if (seizeSchemaTrans(trans_ptr, trans_key)) {
27661 #ifdef MARTIN
27662     ndbout_c("Dbdict::seizeSchemaTrans: Seized schema trans %u", trans_key);
27663 #endif
27664     c_opRecordSequence = trans_key;
27665     return true;
27666   }
27667 #ifdef MARTIN
27668   ndbout_c("Dbdict::seizeSchemaTrans: Failed to seize schema trans");
27669 #endif
27670   return false;
27671 }
27672 
27673 bool
findSchemaTrans(SchemaTransPtr & trans_ptr,Uint32 trans_key)27674 Dbdict::findSchemaTrans(SchemaTransPtr& trans_ptr, Uint32 trans_key)
27675 {
27676   SchemaTrans trans_rec(trans_key);
27677   if (c_schemaTransHash.find(trans_ptr, trans_rec)) {
27678     jam();
27679     ndbrequire(trans_ptr.p->m_magic == SchemaTrans::DICT_MAGIC);
27680     D("findSchemaTrans" << V(trans_key));
27681     return true;
27682   }
27683   trans_ptr.setNull();
27684   return false;
27685 }
27686 
27687 void
releaseSchemaTrans(SchemaTransPtr & trans_ptr)27688 Dbdict::releaseSchemaTrans(SchemaTransPtr& trans_ptr)
27689 {
27690   D("releaseSchemaTrans" << V(trans_ptr.p->trans_key));
27691 
27692   {
27693     /**
27694      * Put in own scope...since LocalSchemaOp_list stores back head
27695      *   in destructor
27696      */
27697     LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
27698     SchemaOpPtr op_ptr;
27699     while (list.first(op_ptr)) {
27700       list.remove(op_ptr);
27701       releaseSchemaOp(op_ptr);
27702     }
27703   }
27704   ndbrequire(trans_ptr.p->m_magic == SchemaTrans::DICT_MAGIC);
27705   ndbrequire(c_schemaTransCount != 0);
27706   c_schemaTransCount--;
27707   c_schemaTransList.remove(trans_ptr);
27708   c_schemaTransHash.remove(trans_ptr);
27709   ArenaHead arena = trans_ptr.p->m_arena;
27710   c_schemaTransPool.release(trans_ptr);
27711   c_arenaAllocator.release(arena);
27712   trans_ptr.setNull();
27713 
27714   if (c_schemaTransCount == 0)
27715   {
27716     jam();
27717 
27718     Resource_limit rl;
27719     m_ctx.m_mm.get_resource_limit(RG_SCHEMA_TRANS_MEMORY, rl);
27720     ndbrequire(rl.m_curr <= 1); // ArenaAllocator can keep one page for empty pool
27721 #ifdef VM_TRACE
27722     if (getNodeState().startLevel == NodeState::SL_STARTED)
27723       check_consistency();
27724 #endif
27725   }
27726 }
27727 
27728 // client requests
27729 
27730 void
execSCHEMA_TRANS_BEGIN_REQ(Signal * signal)27731 Dbdict::execSCHEMA_TRANS_BEGIN_REQ(Signal* signal)
27732 {
27733   jamEntry();
27734   const SchemaTransBeginReq* req =
27735     (const SchemaTransBeginReq*)signal->getDataPtr();
27736   Uint32 clientRef = req->clientRef;
27737 #ifdef MARTIN
27738   ndbout_c("Dbdict::execSCHEMA_TRANS_BEGIN_REQ: received GSN_SCHEMA_TRANS_BEGIN_REQ from 0x%8x", clientRef);
27739 #endif
27740 
27741   Uint32 transId = req->transId;
27742   Uint32 requestInfo = req->requestInfo;
27743 
27744   bool localTrans = (requestInfo & DictSignal::RF_LOCAL_TRANS);
27745 
27746   SchemaTransPtr trans_ptr;
27747   ErrorInfo error;
27748   do {
27749     if (getOwnNodeId() != c_masterNodeId && !localTrans) {
27750       jam();
27751       setError(error, SchemaTransBeginRef::NotMaster, __LINE__);
27752       break;
27753     }
27754 
27755     if (!localTrans)
27756     {
27757       ndbassert(getOwnNodeId() == c_masterNodeId);
27758       NodeRecordPtr masterNodePtr;
27759       c_nodes.getPtr(masterNodePtr, c_masterNodeId);
27760 
27761       if (masterNodePtr.p->nodeState == NodeRecord::NDB_MASTER_TAKEOVER)
27762       {
27763         jam();
27764         /**
27765          * There is a dict takeover in progress. There may thus be another
27766          * transaction that should be rolled backward or forward before we
27767          * can allow another transaction to start.
27768          * (Multiple concurrent schema transactions are not supported)
27769          */
27770         setError(error, SchemaTransBeginRef::Busy, __LINE__);
27771         break;
27772       }
27773     }
27774     ndbassert(!c_takeOverInProgress);
27775 
27776     if (!check_ndb_versions() && !localTrans)
27777     {
27778       jam();
27779       setError(error, SchemaTransBeginRef::IncompatibleVersions, __LINE__);
27780       break;
27781     }
27782 
27783     if (!seizeSchemaTrans(trans_ptr)) {
27784       jam();
27785       // future when more than 1 tx allowed
27786       setError(error, SchemaTransBeginRef::TooManySchemaTrans, __LINE__);
27787       break;
27788     }
27789 
27790     trans_ptr.p->m_isMaster = true;
27791     trans_ptr.p->m_masterRef = reference();
27792     trans_ptr.p->m_clientRef = clientRef;
27793     trans_ptr.p->m_transId = transId;
27794     trans_ptr.p->m_requestInfo = requestInfo;
27795     trans_ptr.p->m_obj_id = getFreeObjId();
27796     if (localTrans)
27797     {
27798       /**
27799        * TODO...use better mechanism...
27800        *
27801        * During restart...we need to check both old/new
27802        *   schema file so that we don't accidently allocate
27803        *   an objectId that should be used to recreate an object
27804        */
27805       trans_ptr.p->m_obj_id = getFreeObjId(true);
27806     }
27807 
27808     if (!localTrans)
27809     {
27810       jam();
27811       trans_ptr.p->m_nodes = c_aliveNodes;
27812     }
27813     else
27814     {
27815       jam();
27816       trans_ptr.p->m_nodes.clear();
27817       trans_ptr.p->m_nodes.set(getOwnNodeId());
27818     }
27819     trans_ptr.p->m_clientState = TransClient::BeginReq;
27820 
27821     // lock
27822     DictLockReq& lockReq = trans_ptr.p->m_lockReq;
27823     lockReq.userPtr = trans_ptr.p->trans_key;
27824     lockReq.userRef = reference();
27825     lockReq.lockType = DictLockReq::SchemaTransLock;
27826     int lockError = dict_lock_trylock(&lockReq);
27827     debugLockInfo(signal,
27828                   "SCHEMA_TRANS_BEGIN_REQ trylock",
27829                   lockError);
27830     if (lockError != 0)
27831     {
27832       // remove the trans
27833       releaseSchemaTrans(trans_ptr);
27834       setError(error, lockError, __LINE__);
27835       break;
27836     }
27837 
27838     // begin tx on all participants
27839     trans_ptr.p->m_state = SchemaTrans::TS_STARTING;
27840 
27841     /**
27842      * Send RT_START
27843      */
27844     {
27845       trans_ptr.p->m_ref_nodes.clear();
27846       NodeReceiverGroup rg(DBDICT, trans_ptr.p->m_nodes);
27847       {
27848         SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
27849         bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
27850         ndbrequire(ok);
27851       }
27852 
27853       if (ERROR_INSERTED(6140))
27854       {
27855         /*
27856           Simulate slave missing start
27857         */
27858         jam();
27859 	Uint32 nodeId = rand() % MAX_NDB_NODES;
27860 	while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
27861 	  nodeId = rand() % MAX_NDB_NODES;
27862 
27863 	infoEvent("Simulating node %u missing RT_START", nodeId);
27864         rg.m_nodes.clear(nodeId);
27865         signal->theData[0] = 9999;
27866         signal->theData[1] = ERROR_INSERT_VALUE;
27867         CLEAR_ERROR_INSERT_VALUE;
27868         sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
27869                             5000, 2);
27870       }
27871 
27872       SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
27873       req->senderRef = reference();
27874       req->transKey = trans_ptr.p->trans_key;
27875       req->opKey = RNIL;
27876       req->requestInfo = SchemaTransImplReq::RT_START;
27877       req->start.clientRef = trans_ptr.p->m_clientRef;
27878       req->start.objectId = trans_ptr.p->m_obj_id;
27879       req->transId = trans_ptr.p->m_transId;
27880       sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
27881                  SchemaTransImplReq::SignalLengthStart, JBB);
27882     }
27883 
27884     if (ERROR_INSERTED(6102)) {
27885       jam();
27886       CLEAR_ERROR_INSERT_VALUE;
27887       signal->theData[0] = refToNode(clientRef);
27888       sendSignal(QMGR_REF, GSN_API_FAILREQ, signal, 1, JBB);
27889     }
27890     return;
27891   } while(0);
27892 
27893   SchemaTrans tmp_trans;
27894   trans_ptr.i = RNIL;
27895   trans_ptr.p = &tmp_trans;
27896   trans_ptr.p->trans_key = 0;
27897   trans_ptr.p->m_clientRef = clientRef;
27898   trans_ptr.p->m_transId = transId;
27899   trans_ptr.p->m_clientState = TransClient::BeginReq;
27900   setError(trans_ptr.p->m_error, error);
27901   sendTransClientReply(signal, trans_ptr);
27902 }
27903 
27904 void
trans_start_recv_reply(Signal * signal,SchemaTransPtr trans_ptr)27905 Dbdict::trans_start_recv_reply(Signal* signal, SchemaTransPtr trans_ptr)
27906 {
27907   jam();
27908 
27909   switch(trans_ptr.p->m_state){
27910   case SchemaTrans::TS_STARTING:
27911     if (hasError(trans_ptr.p->m_error))
27912     {
27913       jam();
27914 
27915       /**
27916        * Clear nodes that did not reply START-CONF
27917        */
27918       trans_ptr.p->m_nodes.bitANDC(trans_ptr.p->m_ref_nodes);
27919 
27920       /**
27921        * Abort before replying to client
27922        */
27923       trans_end_start(signal, trans_ptr);
27924       return;
27925     }
27926     else
27927     {
27928       jam();
27929       sendTransClientReply(signal, trans_ptr);
27930       return;
27931     }
27932     break;
27933   default:
27934     jamLine(trans_ptr.p->m_state);
27935     ndbrequire(false);
27936   }
27937 }
27938 
27939 void
execSCHEMA_TRANS_END_REQ(Signal * signal)27940 Dbdict::execSCHEMA_TRANS_END_REQ(Signal* signal)
27941 {
27942   jamEntry();
27943   const SchemaTransEndReq* req =
27944     (const SchemaTransEndReq*)signal->getDataPtr();
27945   Uint32 clientRef = req->clientRef;
27946   Uint32 transId = req->transId;
27947   Uint32 trans_key = req->transKey;
27948   Uint32 requestInfo = req->requestInfo;
27949   Uint32 flags = req->flags;
27950 
27951   SchemaTransPtr trans_ptr;
27952   ErrorInfo error;
27953   do {
27954     const bool localTrans = (requestInfo & DictSignal::RF_LOCAL_TRANS);
27955     if (getOwnNodeId() != c_masterNodeId && !localTrans) {
27956       jam();
27957       setError(error, SchemaTransEndRef::NotMaster, __LINE__);
27958       break;
27959     }
27960 
27961     if (!findSchemaTrans(trans_ptr, trans_key)) {
27962       jam();
27963       setError(error, SchemaTransEndRef::InvalidTransKey, __LINE__);
27964       break;
27965     }
27966 
27967     if (trans_ptr.p->m_transId != transId) {
27968       jam();
27969       setError(error, SchemaTransEndRef::InvalidTransId, __LINE__);
27970       break;
27971     }
27972 
27973     const bool localTrans2 =
27974       (trans_ptr.p->m_requestInfo & DictSignal::RF_LOCAL_TRANS);
27975 
27976     if (localTrans != localTrans2)
27977     {
27978       jam();
27979       ndbassert(false);
27980       setError(error, SchemaTransEndRef::InvalidTransState, __LINE__);
27981       break;
27982     }
27983 
27984     if (!localTrans)
27985     {
27986       ndbassert(getOwnNodeId() == c_masterNodeId);
27987       NodeRecordPtr masterNodePtr;
27988       c_nodes.getPtr(masterNodePtr, c_masterNodeId);
27989 
27990       if (masterNodePtr.p->nodeState == NodeRecord::NDB_MASTER_TAKEOVER)
27991       {
27992         jam();
27993         /**
27994          * There is a dict takeover in progress.
27995          * Transaction might be in an inconsistent state where its fate
27996          * has not been decided yet. When takeover eventually completes,
27997          * it will ::sendTransClientReply() which will inform the client
27998          * about the fate of the Txn in a TRANS_END_REP.
27999          * For now we don't send any reply, and let the client wait for
28000          * TRANS_END_REP.
28001          */
28002         return;
28003       }
28004     }
28005 
28006 #ifdef MARTIN
28007     ndbout_c("Dbdict::execSCHEMA_TRANS_END_REQ: trans %u, state %u", trans_ptr.i, trans_ptr.p->m_state);
28008 #endif
28009 
28010     // Assert that we are not in an inconsistent/incomplete state
28011     ndbassert(!hasError(trans_ptr.p->m_error));
28012     ndbassert(!c_takeOverInProgress);
28013     ndbassert(trans_ptr.p->m_counter.done());
28014 
28015     trans_ptr.p->m_clientState = TransClient::EndReq;
28016 
28017     const bool doBackground = flags & SchemaTransEndReq::SchemaTransBackground;
28018     if (doBackground)
28019     {
28020       jam();
28021       // send reply to original client and restore EndReq state
28022       sendTransClientReply(signal, trans_ptr);
28023       trans_ptr.p->m_clientState = TransClient::EndReq;
28024 
28025       // take over client role via internal trans
28026       trans_ptr.p->m_clientFlags |= TransClient::Background;
28027       takeOverTransClient(signal, trans_ptr);
28028     }
28029 
28030     if (flags & SchemaTransEndReq::SchemaTransAbort)
28031     {
28032       jam();
28033       trans_abort_prepare_start(signal, trans_ptr);
28034       return;
28035     }
28036     else if ((flags & SchemaTransEndReq::SchemaTransPrepare) == 0)
28037     {
28038       jam();
28039       trans_ptr.p->m_clientFlags |= TransClient::Commit;
28040     }
28041 
28042     trans_prepare_start(signal, trans_ptr);
28043     return;
28044   } while (0);
28045 
28046   SchemaTrans tmp_trans;
28047   trans_ptr.i = RNIL;
28048   trans_ptr.p = &tmp_trans;
28049   trans_ptr.p->trans_key = trans_key;
28050   trans_ptr.p->m_clientRef = clientRef;
28051   trans_ptr.p->m_transId = transId;
28052   trans_ptr.p->m_clientState = TransClient::EndReq;
28053   setError(trans_ptr.p->m_error, error);
28054   sendTransClientReply(signal, trans_ptr);
28055 }
28056 
28057 // coordinator
28058 
28059 void
handleClientReq(Signal * signal,SchemaOpPtr op_ptr,SectionHandle & handle)28060 Dbdict::handleClientReq(Signal* signal, SchemaOpPtr op_ptr,
28061                         SectionHandle& handle)
28062 {
28063   D("handleClientReq" << *op_ptr.p);
28064 
28065   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
28066 
28067   if (trans_ptr.p->m_state == SchemaTrans::TS_SUBOP)
28068   {
28069     jam();
28070     SchemaOpPtr baseOp;
28071     c_schemaOpPool.getPtr(baseOp, trans_ptr.p->m_curr_op_ptr_i);
28072     op_ptr.p->m_base_op_ptr_i = baseOp.i;
28073   }
28074 
28075   trans_ptr.p->m_curr_op_ptr_i = op_ptr.i;
28076   op_ptr.p->m_state = SchemaOp::OS_PARSE_MASTER;
28077 
28078   ErrorInfo error;
28079   const OpInfo& info = getOpInfo(op_ptr);
28080 
28081   if (checkSingleUserMode(trans_ptr.p->m_clientRef))
28082   {
28083     jam();
28084     setError(error, AlterTableRef::SingleUser, __LINE__);
28085   }
28086   else
28087   {
28088     jam();
28089     (this->*(info.m_parse))(signal, true, op_ptr, handle, error);
28090   }
28091 
28092   if (hasError(error))
28093   {
28094     jam();
28095     setError(trans_ptr, error);
28096     releaseSections(handle);
28097     trans_rollback_sp_start(signal, trans_ptr);
28098     return;
28099   }
28100 
28101   trans_ptr.p->m_state = SchemaTrans::TS_PARSING;
28102   op_ptr.p->m_state = SchemaOp::OS_PARSING;
28103 
28104   Uint32 gsn = info.m_impl_req_gsn;
28105   const Uint32* src = op_ptr.p->m_oprec_ptr.p->m_impl_req_data;
28106 
28107   Uint32* data = signal->getDataPtrSend();
28108   Uint32 skip = SchemaTransImplReq::SignalLength;
28109   Uint32 extra_length = info.m_impl_req_length;
28110   ndbrequire(skip + extra_length <= 25);
28111 
28112   Uint32 i;
28113   for (i = 0; i < extra_length; i++)
28114     data[skip + i] = src[i];
28115 
28116   Uint32 requestInfo = 0;
28117   DictSignal::setRequestType(requestInfo, SchemaTransImplReq::RT_PARSE);
28118   DictSignal::addRequestFlags(requestInfo, op_ptr.p->m_requestInfo);
28119   DictSignal::addRequestExtra(requestInfo, op_ptr.p->m_requestInfo);
28120 
28121   trans_ptr.p->m_ref_nodes.clear();
28122   trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
28123   NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
28124 
28125   NodeReceiverGroup rg(DBDICT, nodes);
28126   {
28127     SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
28128     bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
28129     ndbrequire(ok);
28130   }
28131 
28132   if (ERROR_INSERTED(6141))
28133   {
28134     /*
28135       Simulate slave missing parsing last (this) op
28136      */
28137     jam();
28138     Uint32 nodeId = rand() % MAX_NDB_NODES;
28139     while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
28140       nodeId = rand() % MAX_NDB_NODES;
28141 
28142     infoEvent("Simulating node %u missing RT_PARSE", nodeId);
28143     rg.m_nodes.clear(nodeId);
28144     signal->theData[0] = 9999;
28145     signal->theData[1] = ERROR_INSERT_VALUE;
28146     CLEAR_ERROR_INSERT_VALUE;
28147     sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
28148                         5000, 2);
28149   }
28150 
28151   SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
28152   req->senderRef = reference();
28153   req->transKey = trans_ptr.p->trans_key;
28154   req->opKey = op_ptr.p->op_key;
28155   req->requestInfo = requestInfo;
28156   req->transId = trans_ptr.p->m_transId;
28157   req->parse.gsn = gsn;
28158   sendFragmentedSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
28159                        SchemaTransImplReq::SignalLength + extra_length, JBB,
28160                        &handle);
28161 }
28162 
28163 void
trans_parse_recv_reply(Signal * signal,SchemaTransPtr trans_ptr)28164 Dbdict::trans_parse_recv_reply(Signal* signal, SchemaTransPtr trans_ptr)
28165 {
28166   SchemaOpPtr op_ptr;
28167   c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
28168 
28169   op_ptr.p->m_state = SchemaOp::OS_PARSED;
28170 
28171   if (hasError(trans_ptr.p->m_error))
28172   {
28173     jam();
28174     trans_rollback_sp_start(signal, trans_ptr);
28175     return;
28176   }
28177 
28178   const OpInfo& info = getOpInfo(op_ptr);
28179   if ((this->*(info.m_subOps))(signal, op_ptr))
28180   {
28181     jam();
28182     // more sub-ops on the way
28183     trans_ptr.p->m_curr_op_ptr_i = op_ptr.i;
28184     trans_ptr.p->m_state = SchemaTrans::TS_SUBOP;
28185     return;
28186   }
28187 
28188   /**
28189    * Reply to client
28190    */
28191   ErrorInfo error;
28192   (this->*(info.m_reply))(signal, op_ptr, error);
28193 
28194   trans_ptr.p->m_clientState = TransClient::ParseReply;
28195   trans_ptr.p->m_state = SchemaTrans::TS_STARTED;
28196 }
28197 
28198 void
execSCHEMA_TRANS_IMPL_CONF(Signal * signal)28199 Dbdict::execSCHEMA_TRANS_IMPL_CONF(Signal* signal)
28200 {
28201   jamEntry();
28202   ndbrequire(signal->getNoOfSections() == 0);
28203 
28204   if (c_takeOverInProgress)
28205   {
28206     /**
28207      * The new master will rebuild the transaction state from the
28208      * DICT_TAKEOVER_CONF signals. Therefore we ignore this signal during
28209      * takeover.
28210      */
28211     jam();
28212     return;
28213   }
28214 
28215   const SchemaTransImplConf* conf =
28216     (const SchemaTransImplConf*)signal->getDataPtr();
28217 
28218   SchemaTransPtr trans_ptr;
28219   ndbrequire(findSchemaTrans(trans_ptr, conf->transKey));
28220 
28221   Uint32 senderRef = conf->senderRef;
28222   Uint32 nodeId = refToNode(senderRef);
28223 
28224   {
28225     SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
28226     if (!sc.clearWaitingFor(nodeId)) {
28227       jam();
28228       return;
28229     }
28230   }
28231 
28232   trans_recv_reply(signal, trans_ptr);
28233 }
28234 
28235 void
execSCHEMA_TRANS_IMPL_REF(Signal * signal)28236 Dbdict::execSCHEMA_TRANS_IMPL_REF(Signal* signal)
28237 {
28238   jamEntry();
28239   ndbrequire(signal->getNoOfSections() == 0);
28240 
28241   if (c_takeOverInProgress)
28242   {
28243     /**
28244      * The new master will rebuild the transaction state from the
28245      * DICT_TAKEOVER_CONF signals. Therefore we ignore this signal during
28246      * takeover.
28247      */
28248     jam();
28249     return;
28250   }
28251 
28252   SchemaTransImplRef refCopy =
28253     *(SchemaTransImplRef*)signal->getDataPtr();
28254   SchemaTransImplRef * ref = &refCopy;
28255 
28256   SchemaTransPtr trans_ptr;
28257   ndbrequire(findSchemaTrans(trans_ptr, ref->transKey));
28258 
28259   Uint32 senderRef = ref->senderRef;
28260   Uint32 nodeId = refToNode(senderRef);
28261 
28262 #ifdef MARTIN
28263   ndbout_c("Got SCHEMA_TRANS_IMPL_REF from node %u, error %u", nodeId, ref->errorCode);
28264 #endif
28265   if (ref->errorCode == SchemaTransImplRef::NF_FakeErrorREF)
28266   {
28267     jam();
28268     // trans_ptr.p->m_nodes.clear(nodeId);
28269     // No need to clear, will be cleared when next REQ is set
28270     if (!trans_ptr.p->m_abort_on_node_fail)
28271     {
28272       jam();
28273       ref->errorCode = 0;
28274     }
28275     else
28276     {
28277       jam();
28278       ref->errorCode = SchemaTransBeginRef::Nodefailure;
28279     }
28280   }
28281 
28282   if (ref->errorCode)
28283   {
28284     jam();
28285     ErrorInfo error;
28286     setError(error, ref);
28287     setError(trans_ptr, error);
28288     switch(trans_ptr.p->m_state){
28289     case SchemaTrans::TS_STARTING:
28290       jam();
28291       trans_ptr.p->m_ref_nodes.set(nodeId);
28292       break;
28293     case SchemaTrans::TS_PARSING:
28294       jam();
28295       if (ref->errorCode == SchemaTransImplRef::SeizeFailed)
28296       {
28297         jam();
28298         trans_ptr.p->m_ref_nodes.set(nodeId);
28299       }
28300       break;
28301     default:
28302       jam();
28303     }
28304   }
28305 
28306   {
28307     SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
28308     if (!sc.clearWaitingFor(nodeId)) {
28309       jam();
28310       return;
28311     }
28312   }
28313 
28314   trans_recv_reply(signal, trans_ptr);
28315 }
28316 
28317 void
trans_recv_reply(Signal * signal,SchemaTransPtr trans_ptr)28318 Dbdict::trans_recv_reply(Signal* signal, SchemaTransPtr trans_ptr)
28319 {
28320   switch(trans_ptr.p->m_state){
28321   case SchemaTrans::TS_INITIAL:
28322     ndbrequire(false);
28323   case SchemaTrans::TS_STARTING:
28324     jam();
28325     trans_start_recv_reply(signal, trans_ptr);
28326     return;
28327   case SchemaTrans::TS_PARSING:
28328     jam();
28329     trans_parse_recv_reply(signal, trans_ptr);
28330     return;
28331   case SchemaTrans::TS_SUBOP:
28332     ndbrequire(false);
28333   case SchemaTrans::TS_ROLLBACK_SP:
28334     jam();
28335     trans_rollback_sp_recv_reply(signal, trans_ptr);
28336     return;
28337   case SchemaTrans::TS_FLUSH_PREPARE:
28338     jam();
28339     trans_prepare_first(signal, trans_ptr);
28340     return;
28341   case SchemaTrans::TS_PREPARING:
28342     jam();
28343     trans_prepare_recv_reply(signal, trans_ptr);
28344     return;
28345   case SchemaTrans::TS_ABORTING_PREPARE:
28346     jam();
28347     trans_abort_prepare_recv_reply(signal, trans_ptr);
28348     return;
28349   case SchemaTrans::TS_ABORTING_PARSE:
28350     jam();
28351     trans_abort_parse_recv_reply(signal, trans_ptr);
28352     return;
28353   case SchemaTrans::TS_FLUSH_COMMIT:
28354     jam();
28355     trans_commit_first(signal, trans_ptr);
28356     return;
28357   case SchemaTrans::TS_COMMITTING:
28358     jam();
28359     trans_commit_recv_reply(signal, trans_ptr);
28360     return;
28361   case SchemaTrans::TS_FLUSH_COMPLETE:
28362     jam();
28363     trans_complete_first(signal, trans_ptr);
28364     return;
28365   case SchemaTrans::TS_COMPLETING:
28366     jam();
28367     trans_complete_recv_reply(signal, trans_ptr);
28368     return;
28369   case SchemaTrans::TS_ENDING:
28370     jam();
28371     trans_end_recv_reply(signal, trans_ptr);
28372     return;
28373   case SchemaTrans::TS_STARTED:   // These states are waiting for client
28374     jam();                        // And should not get a "internal" reply
28375     ndbrequire(false);
28376   }
28377 }
28378 
28379 #if 0
28380 void
28381 Dbdict::handleTransReply(Signal* signal, SchemaTransPtr trans_ptr)
28382 {
28383   TransLoc& tLoc = trans_ptr.p->m_transLoc;
28384   SchemaOpPtr op_ptr;
28385   getOpPtr(tLoc, op_ptr);
28386 
28387   //const Uint32 trans_key = trans_ptr.p->trans_key;
28388   //const Uint32 clientRef = trans_ptr.p->m_clientRef;
28389   //const Uint32 transId = trans_ptr.p->m_transId;
28390 
28391   D("handleTransReply" << tLoc);
28392   if (!op_ptr.isNull())
28393     D("have op" << *op_ptr.p);
28394 
28395   if (hasError(trans_ptr.p->m_error)) {
28396     jam();
28397     if (tLoc.m_mode == TransMode::Normal) {
28398       if (tLoc.m_phase == TransPhase::Parse) {
28399         jam();
28400         setTransMode(trans_ptr, TransMode::Rollback, true);
28401       } else {
28402         jam();
28403         setTransMode(trans_ptr, TransMode::Abort, true);
28404       }
28405     }
28406   }
28407 
28408   if (tLoc.m_mode == TransMode::Normal) {
28409     if (tLoc.m_phase == TransPhase::Begin) {
28410       jam();
28411       sendTransClientReply(signal, trans_ptr);
28412     }
28413     else if (tLoc.m_phase == TransPhase::Parse) {
28414       jam();
28415       /*
28416        * Create any sub-operations via client signals.  This is
28417        * a recursive process.  When done at current level, sends reply
28418        * to client.  On inner levels the client is us (dict master).
28419        */
28420       createSubOps(signal, op_ptr, true);
28421     }
28422     else if (tLoc.m_phase == TransPhase::Prepare) {
28423       jam();
28424       runTransMaster(signal, trans_ptr);
28425     }
28426     else if (tLoc.m_phase == TransPhase::Commit) {
28427       jam();
28428       runTransMaster(signal, trans_ptr);
28429     }
28430     else if (tLoc.m_phase == TransPhase::End)
28431     {
28432       jam();
28433       trans_commit_done(signal, trans_ptr);
28434       return;
28435     }
28436     else {
28437       ndbrequire(false);
28438     }
28439   }
28440   else if (tLoc.m_mode == TransMode::Rollback) {
28441     if (tLoc.m_phase == TransPhase::Parse) {
28442       jam();
28443       /*
28444        * Rolling back current client op and its sub-ops.
28445        * We do not follow the signal train of master REQs back.
28446        * Instead we simply run backwards in abort mode until
28447        * (and including) first op of depth zero.  All ops involved
28448        * are removed.  On master this is done here.
28449        */
28450       ndbrequire(hasError(trans_ptr.p->m_error));
28451       ndbrequire(!op_ptr.isNull());
28452       if (tLoc.m_hold) {
28453         jam();
28454         // error seen first time, re-run current op
28455         runTransMaster(signal, trans_ptr);
28456       }
28457       else {
28458         if (op_ptr.p->m_opDepth != 0) {
28459           jam();
28460           runTransMaster(signal, trans_ptr);
28461         }
28462         else {
28463           jam();
28464           // reached original client op
28465           const OpInfo& info = getOpInfo(op_ptr);
28466           (this->*(info.m_reply))(signal, op_ptr, trans_ptr.p->m_error);
28467           resetError(trans_ptr);
28468 
28469           // restore depth counter
28470           trans_ptr.p->m_opDepth = 0;
28471           trans_ptr.p->m_clientState = TransClient::ParseReply;
28472         }
28473         iteratorRemoveLastOp(tLoc, op_ptr);
28474       }
28475     }
28476     else {
28477       ndbrequire(false);
28478     }
28479   }
28480   else if (tLoc.m_mode == TransMode::Abort) {
28481     if (tLoc.m_phase == TransPhase::Begin) {
28482       jam();
28483       sendTransClientReply(signal, trans_ptr);
28484       // unlock
28485       const DictLockReq& lockReq = trans_ptr.p->m_lockReq;
28486       Uint32 rc = dict_lock_unlock(signal, &lockReq);
28487       debugLockInfo(signal,
28488                     "handleTransReply unlock",
28489                     rc);
28490       releaseSchemaTrans(trans_ptr);
28491     }
28492     else if (tLoc.m_phase == TransPhase::Parse) {
28493       jam();
28494       runTransMaster(signal, trans_ptr);
28495     }
28496     else if (tLoc.m_phase == TransPhase::Prepare) {
28497       jam();
28498       runTransMaster(signal, trans_ptr);
28499     }
28500     else {
28501       ndbrequire(false);
28502     }
28503   }
28504   else {
28505     ndbrequire(false);
28506   }
28507 }
28508 #endif
28509 
28510 void
createSubOps(Signal * signal,SchemaOpPtr op_ptr,bool first)28511 Dbdict::createSubOps(Signal* signal, SchemaOpPtr op_ptr, bool first)
28512 {
28513   D("createSubOps" << *op_ptr.p);
28514 
28515   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
28516 
28517   const OpInfo& info = getOpInfo(op_ptr);
28518   if ((this->*(info.m_subOps))(signal, op_ptr)) {
28519     jam();
28520     // more sub-ops on the way
28521     trans_ptr.p->m_curr_op_ptr_i = op_ptr.i;
28522     trans_ptr.p->m_state = SchemaTrans::TS_SUBOP;
28523     return;
28524   }
28525 
28526   ErrorInfo error;
28527   (this->*(info.m_reply))(signal, op_ptr, error);
28528 
28529   trans_ptr.p->m_clientState = TransClient::ParseReply;
28530   trans_ptr.p->m_state = SchemaTrans::TS_STARTED;
28531 }
28532 
28533 // a sub-op create failed, roll back and send REF to client
28534 void
abortSubOps(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)28535 Dbdict::abortSubOps(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
28536 {
28537   D("abortSubOps" << *op_ptr.p << error);
28538   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
28539   setError(trans_ptr, error);
28540   trans_rollback_sp_start(signal, trans_ptr);
28541 }
28542 
28543 void
trans_prepare_start(Signal * signal,SchemaTransPtr trans_ptr)28544 Dbdict::trans_prepare_start(Signal* signal, SchemaTransPtr trans_ptr)
28545 {
28546   trans_ptr.p->m_state = SchemaTrans::TS_FLUSH_PREPARE;
28547 
28548   trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
28549   NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
28550   NodeReceiverGroup rg(DBDICT, nodes);
28551   {
28552     SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
28553     bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
28554     ndbrequire(ok);
28555   }
28556 
28557   if (ERROR_INSERTED(6013))
28558   {
28559     jam();
28560     CRASH_INSERTION(6013);
28561   }
28562 
28563   if (ERROR_INSERTED(6022))
28564   {
28565     jam();
28566     NodeReceiverGroup rg(CMVMI, c_aliveNodes);
28567     signal->theData[0] = 9999;
28568     sendSignal(rg, GSN_NDB_TAMPER, signal, 1, JBB);
28569     return;
28570   }
28571 
28572   if (ERROR_INSERTED(6142))
28573   {
28574     /*
28575       Simulate slave missing flush prepare
28576      */
28577     jam();
28578     Uint32 nodeId = rand() % MAX_NDB_NODES;
28579     while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
28580       nodeId = rand() % MAX_NDB_NODES;
28581 
28582     infoEvent("Simulating node %u missing RT_FLUSH_PREPARE", nodeId);
28583     rg.m_nodes.clear(nodeId);
28584     signal->theData[0] = 9999;
28585     signal->theData[1] = ERROR_INSERT_VALUE;
28586     CLEAR_ERROR_INSERT_VALUE;
28587     sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
28588                         5000, 2);
28589   }
28590 
28591   SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
28592   req->senderRef = reference();
28593   req->transKey = trans_ptr.p->trans_key;
28594   req->opKey = RNIL;
28595   req->requestInfo = SchemaTransImplReq::RT_FLUSH_PREPARE;
28596   req->transId = trans_ptr.p->m_transId;
28597   sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
28598              SchemaTransImplReq::SignalLength, JBB);
28599 }
28600 
28601 void
trans_prepare_first(Signal * signal,SchemaTransPtr trans_ptr)28602 Dbdict::trans_prepare_first(Signal* signal, SchemaTransPtr trans_ptr)
28603 {
28604   if (ERROR_INSERTED(6021))
28605   {
28606     jam();
28607     NodeReceiverGroup rg(CMVMI, c_aliveNodes);
28608     signal->theData[0] = 9999;
28609     sendSignal(rg, GSN_NDB_TAMPER, signal, 1, JBB);
28610     return;
28611   }
28612 
28613   trans_ptr.p->m_state = SchemaTrans::TS_PREPARING;
28614 
28615   SchemaOpPtr op_ptr;
28616   {
28617     bool first;
28618     {
28619       LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
28620       first = list.first(op_ptr);
28621     }
28622     if (first)
28623     {
28624       jam();
28625       trans_prepare_next(signal, trans_ptr, op_ptr);
28626       return;
28627     }
28628   }
28629 
28630   trans_prepare_done(signal, trans_ptr);
28631 }
28632 
28633 void
trans_prepare_next(Signal * signal,SchemaTransPtr trans_ptr,SchemaOpPtr op_ptr)28634 Dbdict::trans_prepare_next(Signal* signal,
28635                            SchemaTransPtr trans_ptr,
28636                            SchemaOpPtr op_ptr)
28637 {
28638   ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_PREPARING);
28639 
28640   trans_ptr.p->m_curr_op_ptr_i = op_ptr.i;
28641   op_ptr.p->m_state = SchemaOp::OS_PREPARING;
28642 
28643   trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
28644   NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
28645   NodeReceiverGroup rg(DBDICT, nodes);
28646   {
28647     SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
28648     bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
28649     ndbrequire(ok);
28650   }
28651 
28652   if (ERROR_INSERTED(6143))
28653   {
28654     jam();
28655     LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
28656     if (!list.hasNext(op_ptr))
28657     {
28658       /*
28659         Simulate slave missing preparing last op
28660       */
28661       jam();
28662       Uint32 nodeId = rand() % MAX_NDB_NODES;
28663       while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
28664         nodeId = rand() % MAX_NDB_NODES;
28665 
28666       infoEvent("Simulating node %u missing RT_PREPARE", nodeId);
28667       rg.m_nodes.clear(nodeId);
28668       signal->theData[0] = 9999;
28669       signal->theData[1] = ERROR_INSERT_VALUE;
28670       CLEAR_ERROR_INSERT_VALUE;
28671       sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
28672                           5000, 2);
28673     }
28674   }
28675 
28676   SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
28677   req->senderRef = reference();
28678   req->transKey = trans_ptr.p->trans_key;
28679   req->opKey = op_ptr.p->op_key;
28680   req->requestInfo = SchemaTransImplReq::RT_PREPARE;
28681   req->transId = trans_ptr.p->m_transId;
28682   sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
28683              SchemaTransImplReq::SignalLength, JBB);
28684 }
28685 
28686 void
trans_prepare_recv_reply(Signal * signal,SchemaTransPtr trans_ptr)28687 Dbdict::trans_prepare_recv_reply(Signal* signal, SchemaTransPtr trans_ptr)
28688 {
28689   jam();
28690 
28691   SchemaOpPtr op_ptr;
28692   c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
28693   if (hasError(trans_ptr.p->m_error))
28694   {
28695     jam();
28696     trans_ptr.p->m_state = SchemaTrans::TS_ABORTING_PREPARE;
28697     trans_abort_prepare_next(signal, trans_ptr, op_ptr);
28698     return;
28699   }
28700 
28701   {
28702     bool next;
28703     {
28704       LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
28705       next = list.next(op_ptr);
28706     }
28707     if (next)
28708     {
28709       jam();
28710       trans_prepare_next(signal, trans_ptr, op_ptr);
28711       return;
28712     }
28713   }
28714 
28715   trans_prepare_done(signal, trans_ptr);
28716   return;
28717 }
28718 
28719 void
trans_prepare_done(Signal * signal,SchemaTransPtr trans_ptr)28720 Dbdict::trans_prepare_done(Signal* signal, SchemaTransPtr trans_ptr)
28721 {
28722   ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_PREPARING);
28723 
28724   if (ERROR_INSERTED(6145))
28725   {
28726     jam();
28727     trans_abort_prepare_start(signal, trans_ptr);
28728     return;
28729   }
28730 
28731   if (trans_ptr.p->m_clientFlags & TransClient::Commit)
28732   {
28733     jam();
28734     trans_commit_start(signal, trans_ptr);
28735     return;
28736   }
28737 
28738   // prepare not currently implemted (fully)
28739   ndbrequire(false);
28740 }
28741 
28742 void
trans_abort_parse_start(Signal * signal,SchemaTransPtr trans_ptr)28743 Dbdict::trans_abort_parse_start(Signal* signal, SchemaTransPtr trans_ptr)
28744 {
28745   trans_ptr.p->m_state = SchemaTrans::TS_ABORTING_PARSE;
28746 
28747   SchemaOpPtr op_ptr;
28748   bool last = false;
28749   {
28750     LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
28751     last =  list.last(op_ptr);
28752   }
28753 
28754   if (last)
28755   {
28756     jam();
28757     trans_abort_parse_next(signal, trans_ptr, op_ptr);
28758     return;
28759   }
28760 
28761   trans_abort_parse_done(signal, trans_ptr);
28762 
28763 }
28764 
28765 void
trans_abort_parse_recv_reply(Signal * signal,SchemaTransPtr trans_ptr)28766 Dbdict::trans_abort_parse_recv_reply(Signal* signal, SchemaTransPtr trans_ptr)
28767 {
28768   SchemaOpPtr op_ptr;
28769   c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
28770 
28771   {
28772     SchemaOpPtr last_op = op_ptr;
28773     bool prev = false;
28774     {
28775       LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
28776       prev = list.prev(op_ptr);
28777       list.remove(last_op);         // Release aborted op
28778     }
28779     releaseSchemaOp(last_op);
28780 
28781     if (prev)
28782     {
28783       jam();
28784       trans_abort_parse_next(signal, trans_ptr, op_ptr);
28785       return;
28786     }
28787   }
28788 
28789   trans_abort_parse_done(signal, trans_ptr);
28790 }
28791 
28792 void
check_partial_trans_abort_parse_next(SchemaTransPtr trans_ptr,NdbNodeBitmask & nodes,SchemaOpPtr op_ptr)28793 Dbdict::check_partial_trans_abort_parse_next(SchemaTransPtr trans_ptr,
28794                                              NdbNodeBitmask &nodes,
28795                                              SchemaOpPtr op_ptr)
28796 {
28797   jam();
28798   NodeRecordPtr ownNodePtr;
28799   c_nodes.getPtr(ownNodePtr, getOwnNodeId());
28800   if (ownNodePtr.p->nodeState == NodeRecord::NDB_MASTER_TAKEOVER)
28801   {
28802     /*
28803       A new master is in the process of aborting a
28804       transaction taken over from the failed master.
28805       Check if any nodes should be skipped because they
28806       have not parsed the operation to be aborted
28807     */
28808     jam();
28809     for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
28810       NodeRecordPtr nodePtr;
28811       if (trans_ptr.p->m_nodes.get(i))
28812       {
28813         jam();
28814         c_nodes.getPtr(nodePtr, i);
28815 #ifdef VM_TRACE
28816         ndbout_c("Checking node %u(%u), %u(%u)<%u", nodePtr.i, nodePtr.p->recoveryState, nodePtr.p->start_op, nodePtr.p->start_op_state, op_ptr.p->op_key);
28817 #endif
28818         if (nodePtr.p->recoveryState == NodeRecord::RS_PARTIAL_ROLLBACK &&
28819             //nodePtr.p->start_op_state == SchemaOp::OS_PARSED &&
28820             nodePtr.p->start_op < op_ptr.p->op_key)
28821         {
28822           jam();
28823 #ifdef VM_TRACE
28824           ndbout_c("Skip aborting operation %u on node %u", op_ptr.p->op_key, i);
28825 #endif
28826           nodes.clear(i);
28827           nodePtr.p->recoveryState = NodeRecord::RS_NORMAL;
28828         }
28829       }
28830     }
28831   }
28832 }
28833 
28834 void
trans_abort_parse_next(Signal * signal,SchemaTransPtr trans_ptr,SchemaOpPtr op_ptr)28835 Dbdict::trans_abort_parse_next(Signal* signal,
28836                                SchemaTransPtr trans_ptr,
28837                                SchemaOpPtr op_ptr)
28838 {
28839   jam();
28840   ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_ABORTING_PARSE);
28841 #ifdef MARTIN
28842   ndbout_c("Dbdict::trans_abort_parse_next: op %u state %u", op_ptr.i,op_ptr.p->m_state);
28843 #endif
28844   trans_ptr.p->m_curr_op_ptr_i = op_ptr.i;
28845   op_ptr.p->m_state = SchemaOp::OS_ABORTING_PARSE;
28846 
28847   trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
28848   NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
28849   check_partial_trans_abort_parse_next(trans_ptr, nodes, op_ptr);
28850   NodeReceiverGroup rg(DBDICT, nodes);
28851   {
28852     SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
28853     bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
28854     ndbrequire(ok);
28855   }
28856 
28857   if (ERROR_INSERTED(6144))
28858   {
28859     jam();
28860     LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
28861     if (!list.hasNext(op_ptr))
28862     {
28863       /*
28864         Simulate slave missing aborting parse for last op
28865       */
28866       jam();
28867       Uint32 nodeId = rand() % MAX_NDB_NODES;
28868       while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
28869         nodeId = rand() % MAX_NDB_NODES;
28870 
28871       infoEvent("Simulating node %u missing RT_ABORT_PARSE", nodeId);
28872       rg.m_nodes.clear(nodeId);
28873       signal->theData[0] = 9999;
28874       signal->theData[1] = ERROR_INSERT_VALUE;
28875       CLEAR_ERROR_INSERT_VALUE;
28876       sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
28877                           5000, 2);
28878     }
28879   }
28880 
28881   SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
28882   req->senderRef = reference();
28883   req->transKey = trans_ptr.p->trans_key;
28884   req->opKey = op_ptr.p->op_key;
28885   req->requestInfo = SchemaTransImplReq::RT_ABORT_PARSE;
28886   req->transId = trans_ptr.p->m_transId;
28887   sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
28888              SchemaTransImplReq::SignalLength, JBB);
28889 }
28890 
28891 void
trans_abort_parse_done(Signal * signal,SchemaTransPtr trans_ptr)28892 Dbdict::trans_abort_parse_done(Signal* signal, SchemaTransPtr trans_ptr)
28893 {
28894   ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_ABORTING_PARSE);
28895 
28896   trans_end_start(signal, trans_ptr);
28897 }
28898 
28899 void
trans_abort_prepare_start(Signal * signal,SchemaTransPtr trans_ptr)28900 Dbdict::trans_abort_prepare_start(Signal* signal, SchemaTransPtr trans_ptr)
28901 {
28902   trans_ptr.p->m_state = SchemaTrans::TS_ABORTING_PREPARE;
28903 
28904   bool last = false;
28905   SchemaOpPtr op_ptr;
28906   {
28907     LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
28908     last = list.last(op_ptr);
28909   }
28910 
28911   if (last)
28912   {
28913     jam();
28914     trans_abort_prepare_next(signal, trans_ptr, op_ptr);
28915   }
28916   else
28917   {
28918     jam();
28919     trans_abort_prepare_done(signal, trans_ptr);
28920   }
28921 }
28922 
28923 void
trans_abort_prepare_recv_reply(Signal * signal,SchemaTransPtr trans_ptr)28924 Dbdict::trans_abort_prepare_recv_reply(Signal* signal, SchemaTransPtr trans_ptr)
28925 {
28926   // XXX error states
28927 
28928   SchemaOpPtr op_ptr;
28929   c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
28930 
28931   op_ptr.p->m_state = SchemaOp::OS_ABORTED_PREPARE;
28932 
28933   bool prev = false;
28934   {
28935     LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
28936     prev = list.prev(op_ptr);
28937   }
28938 
28939   if (prev)
28940   {
28941     jam();
28942     trans_abort_prepare_next(signal, trans_ptr, op_ptr);
28943   }
28944   else
28945   {
28946     jam();
28947     trans_abort_prepare_done(signal, trans_ptr);
28948   }
28949 }
28950 
28951 void
check_partial_trans_abort_prepare_next(SchemaTransPtr trans_ptr,NdbNodeBitmask & nodes,SchemaOpPtr op_ptr)28952 Dbdict::check_partial_trans_abort_prepare_next(SchemaTransPtr trans_ptr,
28953                                                NdbNodeBitmask &nodes,
28954                                                SchemaOpPtr op_ptr)
28955 {
28956   jam();
28957   NodeRecordPtr ownNodePtr;
28958   c_nodes.getPtr(ownNodePtr, getOwnNodeId());
28959   if (ownNodePtr.p->nodeState == NodeRecord::NDB_MASTER_TAKEOVER)
28960   {
28961     /*
28962       A new master is in the process of aborting a
28963       transaction taken over from the failed master.
28964       Check if any nodes should be skipped because they
28965       have already aborted the operation.
28966     */
28967     for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
28968       NodeRecordPtr nodePtr;
28969       if (trans_ptr.p->m_nodes.get(i))
28970       {
28971         c_nodes.getPtr(nodePtr, i);
28972 #ifdef VM_TRACE
28973         ndbout_c("Checking node %u(%u), %u(%u)<%u", nodePtr.i, nodePtr.p->recoveryState, nodePtr.p->start_op, nodePtr.p->start_op_state, op_ptr.p->op_key);
28974 #endif
28975         if (nodePtr.p->recoveryState == NodeRecord::RS_PARTIAL_ROLLBACK &&
28976             ((nodePtr.p->start_op_state == SchemaOp::OS_PARSED &&
28977               nodePtr.p->start_op <= op_ptr.p->op_key) ||
28978              (nodePtr.p->start_op_state == SchemaOp::OS_PREPARED &&
28979               nodePtr.p->start_op < op_ptr.p->op_key) ||
28980              (nodePtr.p->start_op_state == SchemaOp::OS_ABORTED_PREPARE &&
28981               nodePtr.p->start_op >= op_ptr.p->op_key)))
28982         {
28983 #ifdef VM_TRACE
28984           ndbout_c("Skip aborting operation %u on node %u", op_ptr.p->op_key, i);
28985 #endif
28986           nodes.clear(i);
28987           nodePtr.p->recoveryState = NodeRecord::RS_NORMAL;
28988         }
28989       }
28990     }
28991   }
28992 }
28993 
28994 void
trans_abort_prepare_next(Signal * signal,SchemaTransPtr trans_ptr,SchemaOpPtr op_ptr)28995 Dbdict::trans_abort_prepare_next(Signal* signal,
28996                                  SchemaTransPtr trans_ptr,
28997                                  SchemaOpPtr op_ptr)
28998 {
28999   jam();
29000   ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_ABORTING_PREPARE);
29001 #ifdef MARTIN
29002   ndbout_c("Dbdict::trans_abort_prepare_next: op %u state %u", op_ptr.p->op_key, op_ptr.p->m_state);
29003 #endif
29004   trans_ptr.p->m_curr_op_ptr_i = op_ptr.i;
29005 
29006   switch(op_ptr.p->m_state){
29007   case SchemaOp::OS_PARSED:
29008     jam();
29009     /**
29010      * Operation has not beed prepared...
29011      *   continue with next
29012      */
29013     trans_abort_prepare_recv_reply(signal, trans_ptr);
29014     return;
29015   case SchemaOp::OS_PREPARING:
29016   case SchemaOp::OS_PREPARED:
29017     jam();
29018     break;
29019   case SchemaOp::OS_INITIAL:
29020   case SchemaOp::OS_PARSE_MASTER:
29021   case SchemaOp::OS_PARSING:
29022   case SchemaOp::OS_ABORTING_PREPARE:
29023   case SchemaOp::OS_ABORTED_PREPARE:
29024   case SchemaOp::OS_ABORTING_PARSE:
29025     //case SchemaOp::OS_ABORTED_PARSE:
29026   case SchemaOp::OS_COMMITTING:
29027   case SchemaOp::OS_COMMITTED:
29028 #ifndef VM_TRACE
29029   default:
29030 #endif
29031     jamLine(op_ptr.p->m_state);
29032     ndbrequire(false);
29033   }
29034 
29035   op_ptr.p->m_state = SchemaOp::OS_ABORTING_PREPARE;
29036 
29037   trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
29038   NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
29039   check_partial_trans_abort_prepare_next(trans_ptr, nodes, op_ptr);
29040   NodeReceiverGroup rg(DBDICT, nodes);
29041   {
29042     SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
29043     bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
29044     ndbrequire(ok);
29045   }
29046 
29047   if (ERROR_INSERTED(6145))
29048   {
29049     jam();
29050     LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
29051     if (!list.hasPrev(op_ptr))
29052     {
29053       /*
29054         Simulate slave missing aborting prepare of last op
29055       */
29056       jam();
29057       Uint32 nodeId = rand() % MAX_NDB_NODES;
29058       while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
29059         nodeId = rand() % MAX_NDB_NODES;
29060 
29061       infoEvent("Simulating node %u missing RT_ABORT_PREPARE", nodeId);
29062       rg.m_nodes.clear(nodeId);
29063       signal->theData[0] = 9999;
29064       signal->theData[1] = ERROR_INSERT_VALUE;
29065       CLEAR_ERROR_INSERT_VALUE;
29066       sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
29067                           5000, 2);
29068     }
29069   }
29070 
29071   SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
29072   req->senderRef = reference();
29073   req->transKey = trans_ptr.p->trans_key;
29074   req->opKey = op_ptr.p->op_key;
29075   req->requestInfo = SchemaTransImplReq::RT_ABORT_PREPARE;
29076   req->transId = trans_ptr.p->m_transId;
29077   sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
29078              SchemaTransImplReq::SignalLength, JBB);
29079 }
29080 
29081 void
trans_abort_prepare_done(Signal * signal,SchemaTransPtr trans_ptr)29082 Dbdict::trans_abort_prepare_done(Signal* signal, SchemaTransPtr trans_ptr)
29083 {
29084   jam();
29085   ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_ABORTING_PREPARE);
29086 #ifdef MARTIN
29087   ndbout_c("Dbdict::trans_abort_prepare_done");
29088 #endif
29089   /**
29090    * Now run abort parse
29091    */
29092   trans_abort_parse_start(signal, trans_ptr);
29093 }
29094 
29095 /**
29096  * FLOW: Rollback SP
29097  *   abort parse each operation (backwards) until op which is not subop
29098  */
29099 void
trans_rollback_sp_start(Signal * signal,SchemaTransPtr trans_ptr)29100 Dbdict::trans_rollback_sp_start(Signal* signal, SchemaTransPtr trans_ptr)
29101 {
29102   SchemaOpPtr op_ptr;
29103 
29104   {
29105     LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
29106     ndbrequire(list.last(op_ptr));
29107   }
29108 
29109   trans_ptr.p->m_state = SchemaTrans::TS_ROLLBACK_SP;
29110 
29111   if (op_ptr.p->m_state == SchemaOp::OS_PARSE_MASTER)
29112   {
29113     jam();
29114     /**
29115      * This op is only parsed at master..
29116      *
29117      */
29118     NdbNodeBitmask nodes;
29119     nodes.set(getOwnNodeId());
29120     NodeReceiverGroup rg(DBDICT, nodes);
29121     SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
29122     bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
29123     ndbrequire(ok);
29124 
29125     const OpInfo& info = getOpInfo(op_ptr);
29126     (this->*(info.m_abortParse))(signal, op_ptr);
29127     trans_log_schema_op_abort(op_ptr);
29128     return;
29129   }
29130 
29131   trans_rollback_sp_next(signal, trans_ptr, op_ptr);
29132 }
29133 
29134 void
trans_rollback_sp_recv_reply(Signal * signal,SchemaTransPtr trans_ptr)29135 Dbdict::trans_rollback_sp_recv_reply(Signal* signal, SchemaTransPtr trans_ptr)
29136 {
29137   // TODO split trans error from op_error...?
29138 
29139   SchemaOpPtr op_ptr;
29140   c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
29141 
29142   if (op_ptr.p->m_base_op_ptr_i == RNIL)
29143   {
29144     /**
29145      * SP
29146      */
29147     jam();
29148     trans_rollback_sp_done(signal, trans_ptr, op_ptr);
29149     return;
29150   }
29151 
29152   {
29153     LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
29154 
29155     SchemaOpPtr last_op = op_ptr;
29156     ndbrequire(list.prev(op_ptr)); // Must have prev, as not SP
29157     list.remove(last_op);         // Release aborted op
29158     releaseSchemaOp(last_op);
29159   }
29160 
29161   trans_rollback_sp_next(signal, trans_ptr, op_ptr);
29162 }
29163 
29164 void
trans_rollback_sp_next(Signal * signal,SchemaTransPtr trans_ptr,SchemaOpPtr op_ptr)29165 Dbdict::trans_rollback_sp_next(Signal* signal,
29166                                SchemaTransPtr trans_ptr,
29167                                SchemaOpPtr op_ptr)
29168 {
29169   trans_ptr.p->m_curr_op_ptr_i = op_ptr.i;
29170 
29171   trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
29172   NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
29173   nodes.bitANDC(trans_ptr.p->m_ref_nodes);
29174   trans_ptr.p->m_ref_nodes.clear();
29175   NodeReceiverGroup rg(DBDICT, nodes);
29176   {
29177     SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
29178     bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
29179     ndbrequire(ok);
29180   }
29181 
29182   if (ERROR_INSERTED(6144))
29183   {
29184     jam();
29185     LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
29186     if (!list.hasPrev(op_ptr))
29187     {
29188       /*
29189         Simulate slave missing aborting parsing of last op
29190       */
29191       jam();
29192       Uint32 nodeId = rand() % MAX_NDB_NODES;
29193       while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
29194         nodeId = rand() % MAX_NDB_NODES;
29195 
29196       infoEvent("Simulating node %u missing RT_ABORT_PARSE", nodeId);
29197       rg.m_nodes.clear(nodeId);
29198       signal->theData[0] = 9999;
29199       signal->theData[1] = ERROR_INSERT_VALUE;
29200       CLEAR_ERROR_INSERT_VALUE;
29201       sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
29202                           5000, 2);
29203     }
29204   }
29205 
29206   SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
29207   req->senderRef = reference();
29208   req->transKey = trans_ptr.p->trans_key;
29209   req->opKey = op_ptr.p->op_key;
29210   req->requestInfo = SchemaTransImplReq::RT_ABORT_PARSE;
29211   req->transId = trans_ptr.p->m_transId;
29212   sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
29213              SchemaTransImplReq::SignalLength, JBB);
29214 
29215 }
29216 
29217 void
trans_rollback_sp_done(Signal * signal,SchemaTransPtr trans_ptr,SchemaOpPtr op_ptr)29218 Dbdict::trans_rollback_sp_done(Signal* signal,
29219                                SchemaTransPtr trans_ptr,
29220                                SchemaOpPtr op_ptr)
29221 {
29222   jam();
29223   ErrorInfo error = trans_ptr.p->m_error;
29224   const OpInfo info = getOpInfo(op_ptr);
29225   (this->*(info.m_reply))(signal, op_ptr, error);
29226 
29227   LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
29228   list.remove(op_ptr);
29229   releaseSchemaOp(op_ptr);
29230 
29231   resetError(trans_ptr);
29232   trans_ptr.p->m_clientState = TransClient::ParseReply;
29233   trans_ptr.p->m_state = SchemaTrans::TS_STARTED;
29234 }
29235 
check_partial_trans_commit_start(SchemaTransPtr trans_ptr,NdbNodeBitmask & nodes)29236 void Dbdict::check_partial_trans_commit_start(SchemaTransPtr trans_ptr,
29237                                               NdbNodeBitmask &nodes)
29238 {
29239   jam();
29240   NodeRecordPtr ownNodePtr;
29241   c_nodes.getPtr(ownNodePtr, getOwnNodeId());
29242   if (ownNodePtr.p->nodeState == NodeRecord::NDB_MASTER_TAKEOVER)
29243   {
29244     /*
29245       A new master is in the process of commiting a
29246       transaction taken over from the failed master.
29247       Check if some slave have already flushed the commit.
29248      */
29249     jam();
29250     for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
29251       jam();
29252       NodeRecordPtr nodePtr;
29253       if (trans_ptr.p->m_nodes.get(i))
29254       {
29255         jam();
29256         c_nodes.getPtr(nodePtr, i);
29257         if (nodePtr.p->recoveryState == NodeRecord::RS_PARTIAL_ROLLFORWARD)
29258         {
29259           jam();
29260 #ifdef VM_TRACE
29261           ndbout_c("Skip flushing commit on node %u", i);
29262 #endif
29263           nodes.clear(i);
29264           nodePtr.p->recoveryState = NodeRecord::RS_NORMAL;
29265         }
29266       }
29267     }
29268   }
29269 }
29270 
29271 void
trans_commit_start(Signal * signal,SchemaTransPtr trans_ptr)29272 Dbdict::trans_commit_start(Signal* signal, SchemaTransPtr trans_ptr)
29273 {
29274   if (ERROR_INSERTED(6016) || ERROR_INSERTED(6017))
29275   {
29276     jam();
29277     signal->theData[0] = 9999;
29278     NdbNodeBitmask mask = c_aliveNodes;
29279     if (c_masterNodeId == getOwnNodeId())
29280     {
29281       jam();
29282       mask.clear(getOwnNodeId());
29283       sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 1000, 1);
29284       if (mask.isclear())
29285       {
29286         return;
29287       }
29288     }
29289     NodeReceiverGroup rg(CMVMI, mask);
29290     sendSignal(rg, GSN_NDB_TAMPER, signal, 1, JBB);
29291     return;
29292   }
29293 
29294   trans_ptr.p->m_state = SchemaTrans::TS_FLUSH_COMMIT;
29295 
29296   trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
29297   NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
29298   check_partial_trans_commit_start(trans_ptr, nodes);
29299   NodeReceiverGroup rg(DBDICT, nodes);
29300   {
29301     SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
29302     bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
29303     ndbrequire(ok);
29304   }
29305 
29306   if (ERROR_INSERTED(6146))
29307   {
29308     jam();
29309     /*
29310       Simulate slave missing flushing commit
29311     */
29312     jam();
29313     Uint32 nodeId = rand() % MAX_NDB_NODES;
29314     while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
29315       nodeId = rand() % MAX_NDB_NODES;
29316 
29317     infoEvent("Simulating node %u missing RT_FLUSH_COMMIT", nodeId);
29318     rg.m_nodes.clear(nodeId);
29319     signal->theData[0] = 9999;
29320     signal->theData[1] = ERROR_INSERT_VALUE;
29321     CLEAR_ERROR_INSERT_VALUE;
29322     sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
29323 			5000, 2);
29324   }
29325 
29326   SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
29327   req->senderRef = reference();
29328   req->transKey = trans_ptr.p->trans_key;
29329   req->opKey = RNIL;
29330   req->requestInfo = SchemaTransImplReq::RT_FLUSH_COMMIT;
29331   req->transId = trans_ptr.p->m_transId;
29332   sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
29333              SchemaTransImplReq::SignalLength, JBB);
29334 }
29335 
29336 void
trans_commit_first(Signal * signal,SchemaTransPtr trans_ptr)29337 Dbdict::trans_commit_first(Signal* signal, SchemaTransPtr trans_ptr)
29338 {
29339   jam();
29340 
29341   if (ERROR_INSERTED(6018))
29342   {
29343     jam();
29344     NodeReceiverGroup rg(CMVMI, c_aliveNodes);
29345     signal->theData[0] = 9999;
29346     sendSignal(rg, GSN_NDB_TAMPER, signal, 1, JBB);
29347     return;
29348   }
29349 
29350 #ifdef MARTIN
29351   ndbout_c("trans_commit");
29352 #endif
29353 
29354   trans_ptr.p->m_state = SchemaTrans::TS_COMMITTING;
29355 
29356   NodeRecordPtr ownNodePtr;
29357   c_nodes.getPtr(ownNodePtr, getOwnNodeId());
29358   if (ownNodePtr.p->nodeState == NodeRecord::NDB_MASTER_TAKEOVER &&
29359       ownNodePtr.p->takeOverConf.trans_state >= SchemaTrans::TS_COMMITTING)
29360   {
29361     /*
29362       Master take-over, new master already has lock.
29363      */
29364     jam();
29365     trans_commit_mutex_locked(signal, trans_ptr.i, 0);
29366   }
29367   else if (trans_ptr.p->m_wait_gcp_on_commit)
29368   {
29369     jam();
29370 
29371     signal->theData[0] = 0; // user ptr
29372     signal->theData[1] = 0; // Execute direct
29373     signal->theData[2] = 1; // Current
29374     EXECUTE_DIRECT(DBDIH, GSN_GETGCIREQ, signal, 3);
29375 
29376     jamEntry();
29377     Uint32 gci_hi = signal->theData[1];
29378     Uint32 gci_lo = signal->theData[2];
29379 
29380     signal->theData[0] = ZCOMMIT_WAIT_GCI;
29381     signal->theData[1] = trans_ptr.i;
29382     signal->theData[2] = gci_hi;
29383     signal->theData[3] = gci_lo;
29384     sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 20, 4);
29385 
29386     signal->theData[0] = 6099;
29387     sendSignal(DBDIH_REF, GSN_DUMP_STATE_ORD, signal, 1, JBB);
29388   }
29389   else
29390   {
29391     jam();
29392     Mutex mutex(signal, c_mutexMgr, trans_ptr.p->m_commit_mutex);
29393     Callback c = { safe_cast(&Dbdict::trans_commit_mutex_locked), trans_ptr.i };
29394 
29395     // Todo should alloc mutex on SCHEMA_BEGIN
29396     bool ok = mutex.lock(c);
29397     ndbrequire(ok);
29398   }
29399 }
29400 
29401 void
trans_commit_wait_gci(Signal * signal)29402 Dbdict::trans_commit_wait_gci(Signal* signal)
29403 {
29404   jam();
29405   SchemaTransPtr trans_ptr;
29406   c_schemaTransPool.getPtr(trans_ptr, signal->theData[1]);
29407 
29408   ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_COMMITTING);
29409 
29410   Uint32 gci_hi = signal->theData[2];
29411   Uint32 gci_lo = signal->theData[3];
29412 
29413   signal->theData[0] = 0; // user ptr
29414   signal->theData[1] = 0; // Execute direct
29415   signal->theData[2] = 1; // Current
29416   EXECUTE_DIRECT(DBDIH, GSN_GETGCIREQ, signal, 3);
29417 
29418   jamEntry();
29419   Uint32 curr_gci_hi = signal->theData[1];
29420   Uint32 curr_gci_lo = signal->theData[2];
29421 
29422   if (!getNodeState().getStarted())
29423   {
29424     jam();
29425     /**
29426      * node is starting
29427      */
29428   }
29429   else if (curr_gci_hi == gci_hi && curr_gci_lo == gci_lo)
29430   {
29431     jam();
29432     signal->theData[0] = ZCOMMIT_WAIT_GCI;
29433     signal->theData[1] = trans_ptr.i;
29434     signal->theData[2] = gci_hi;
29435     signal->theData[3] = gci_lo;
29436     sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 20, 4);
29437     return;
29438   }
29439 
29440   Mutex mutex(signal, c_mutexMgr, trans_ptr.p->m_commit_mutex);
29441   Callback c = { safe_cast(&Dbdict::trans_commit_mutex_locked), trans_ptr.i };
29442 
29443   // Todo should alloc mutex on SCHEMA_BEGIN
29444   bool ok = mutex.lock(c);
29445   ndbrequire(ok);
29446 }
29447 
29448 void
trans_commit_mutex_locked(Signal * signal,Uint32 transPtrI,Uint32 ret)29449 Dbdict::trans_commit_mutex_locked(Signal* signal,
29450                                   Uint32 transPtrI,
29451                                   Uint32 ret)
29452 {
29453   jamEntry();
29454 #ifdef MARTIN
29455   ndbout_c("trans_commit_mutex_locked");
29456 #endif
29457   SchemaTransPtr trans_ptr;
29458   c_schemaTransPool.getPtr(trans_ptr, transPtrI);
29459 
29460   ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_COMMITTING);
29461 
29462   bool first = false;
29463   SchemaOpPtr op_ptr;
29464   {
29465     LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
29466     first = list.first(op_ptr);
29467   }
29468 
29469   if (first)
29470   {
29471     jam();
29472     trans_commit_next(signal, trans_ptr, op_ptr);
29473     if (ERROR_INSERTED(6014)) {
29474       jam();
29475       CRASH_INSERTION(6014);
29476     }
29477   }
29478   else
29479   {
29480     jam();
29481     trans_commit_done(signal, trans_ptr);
29482     if (ERROR_INSERTED(6015)) {
29483       jam();
29484       CRASH_INSERTION(6015);
29485     }
29486   }
29487 }
29488 
check_partial_trans_commit_next(SchemaTransPtr trans_ptr,NdbNodeBitmask & nodes,SchemaOpPtr op_ptr)29489 void Dbdict::check_partial_trans_commit_next(SchemaTransPtr trans_ptr,
29490                                              NdbNodeBitmask &nodes,
29491                                              SchemaOpPtr op_ptr)
29492 {
29493   jam();
29494   NodeRecordPtr ownNodePtr;
29495   c_nodes.getPtr(ownNodePtr, getOwnNodeId());
29496   if (ownNodePtr.p->nodeState == NodeRecord::NDB_MASTER_TAKEOVER &&
29497       trans_ptr.p->check_partial_rollforward)
29498   {
29499     /*
29500       A new master is in the process of committing a
29501       transaction taken over from the failed master.
29502       Check if any nodes should be skipped because they
29503       have already commited the operation
29504     */
29505     jam();
29506     for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
29507       jam();
29508       NodeRecordPtr nodePtr;
29509 #ifdef VM_TRACE
29510       ndbout_c("Node %u", i);
29511 #endif
29512       if (trans_ptr.p->m_nodes.get(i))
29513       {
29514         jam();
29515         c_nodes.getPtr(nodePtr, i);
29516 #ifdef VM_TRACE
29517         ndbout_c("Checking node %u(%u), %u<%u", nodePtr.i, nodePtr.p->recoveryState, nodePtr.p->start_op, op_ptr.p->op_key);
29518 #endif
29519         if (nodePtr.p->recoveryState == NodeRecord::RS_PARTIAL_ROLLFORWARD &&
29520             (nodePtr.p->start_op > op_ptr.p->op_key ||
29521              nodePtr.p->start_op_state > op_ptr.p->m_state))
29522         {
29523 #ifdef VM_TRACE
29524           ndbout_c("Skipping commit of operation %u on node %u", op_ptr.p->op_key, i);
29525 #endif
29526           jam();
29527           nodes.clear(i);
29528           nodePtr.p->recoveryState = NodeRecord::RS_NORMAL;
29529         }
29530       }
29531     }
29532     trans_ptr.p->check_partial_rollforward = false;
29533   }
29534 
29535 }
29536 void
trans_commit_next(Signal * signal,SchemaTransPtr trans_ptr,SchemaOpPtr op_ptr)29537 Dbdict::trans_commit_next(Signal* signal,
29538                           SchemaTransPtr trans_ptr,
29539                           SchemaOpPtr op_ptr)
29540 {
29541   jam();
29542 #ifdef MARTIN
29543   ndbout_c("Dbdict::trans_commit_next: op %u state %u", op_ptr.i,op_ptr.p->m_state);
29544 #endif
29545   op_ptr.p->m_state = SchemaOp::OS_COMMITTING;
29546   trans_ptr.p->m_curr_op_ptr_i = op_ptr.i;
29547 
29548   trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
29549   NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
29550   check_partial_trans_commit_next(trans_ptr, nodes, op_ptr);
29551   NodeReceiverGroup rg(DBDICT, nodes);
29552   {
29553     SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
29554     bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
29555     ndbrequire(ok);
29556   }
29557 
29558   if (ERROR_INSERTED(6147))
29559   {
29560     LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
29561     if (!list.hasNext(op_ptr))
29562     {
29563       jam();
29564       /*
29565         Simulate slave missing committing last op
29566       */
29567       jam();
29568       Uint32 nodeId = rand() % MAX_NDB_NODES;
29569       while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
29570         nodeId = rand() % MAX_NDB_NODES;
29571 
29572       infoEvent("Simulating node %u missing RT_COMMIT", nodeId);
29573       rg.m_nodes.clear(nodeId);
29574       signal->theData[0] = 9999;
29575       signal->theData[1] = ERROR_INSERT_VALUE;
29576       CLEAR_ERROR_INSERT_VALUE;
29577       sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
29578                           5000, 2);
29579     }
29580   }
29581 
29582   SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
29583   req->senderRef = reference();
29584   req->transKey = trans_ptr.p->trans_key;
29585   req->opKey = op_ptr.p->op_key;
29586   req->requestInfo = SchemaTransImplReq::RT_COMMIT;
29587   req->transId = trans_ptr.p->m_transId;
29588 
29589   if (rg.m_nodes.get(getOwnNodeId()))
29590   {
29591     /*
29592       To ensure that slave participants register the commit
29593       first we mask out the master node and send commit signal
29594       to master last. This is necessary to handle master node
29595       failure where one of the slaves take over and need to know
29596       that transaction is to be committed.
29597     */
29598     jam();
29599     rg.m_nodes.clear(getOwnNodeId());
29600 
29601     sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
29602                SchemaTransImplReq::SignalLength, JBB);
29603     sendSignal(reference(), GSN_SCHEMA_TRANS_IMPL_REQ, signal,
29604                SchemaTransImplReq::SignalLength, JBB);
29605   }
29606   else
29607   {
29608     jam();
29609     /*
29610       New master had already committed operation
29611      */
29612     sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
29613                SchemaTransImplReq::SignalLength, JBB);
29614   }
29615 }
29616 
29617 void
trans_commit_recv_reply(Signal * signal,SchemaTransPtr trans_ptr)29618 Dbdict::trans_commit_recv_reply(Signal* signal, SchemaTransPtr trans_ptr)
29619 {
29620   if (hasError(trans_ptr.p->m_error))
29621   {
29622     jam();
29623     // kill nodes that failed COMMIT
29624     ndbrequire(false);
29625     return;
29626   }
29627 
29628   SchemaOpPtr op_ptr;
29629   c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
29630 
29631   bool next = false;
29632   {
29633     LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
29634     next = list.next(op_ptr);
29635   }
29636 
29637   if (next)
29638   {
29639     jam();
29640     trans_commit_next(signal, trans_ptr, op_ptr);
29641     if (ERROR_INSERTED(6014)) {
29642       jam();
29643       CRASH_INSERTION(6014);
29644     }
29645     return;
29646   }
29647   else
29648   {
29649     jam();
29650     trans_commit_done(signal, trans_ptr);
29651     if (ERROR_INSERTED(6015)) {
29652       jam();
29653       CRASH_INSERTION(6015);
29654     }
29655   }
29656   return;
29657 }
29658 
29659 void
trans_commit_done(Signal * signal,SchemaTransPtr trans_ptr)29660 Dbdict::trans_commit_done(Signal* signal, SchemaTransPtr trans_ptr)
29661 {
29662 #ifdef MARTIN
29663   ndbout_c("trans_commit_done");
29664 #endif
29665 
29666   Mutex mutex(signal, c_mutexMgr, trans_ptr.p->m_commit_mutex);
29667   Callback c = { safe_cast(&Dbdict::trans_commit_mutex_unlocked), trans_ptr.i };
29668   mutex.unlock(c);
29669 }
29670 
29671 void
trans_commit_mutex_unlocked(Signal * signal,Uint32 transPtrI,Uint32 ret)29672 Dbdict::trans_commit_mutex_unlocked(Signal* signal,
29673                                     Uint32 transPtrI,
29674                                     Uint32 ret)
29675 {
29676   jamEntry();
29677 #ifdef MARTIN
29678   ndbout_c("trans_commit_mutex_unlocked");
29679 #endif
29680   SchemaTransPtr trans_ptr;
29681   c_schemaTransPool.getPtr(trans_ptr, transPtrI);
29682 
29683   trans_ptr.p->m_commit_mutex.release(c_mutexMgr);
29684 
29685   /**
29686    * Here we should wait for SCHEMA_TRANS_COMMIT_ACK
29687    *
29688    * But for now, we proceed and complete transaction
29689    */
29690   trans_complete_start(signal, trans_ptr);
29691 }
29692 
29693 void
check_partial_trans_complete_start(SchemaTransPtr trans_ptr,NdbNodeBitmask & nodes)29694 Dbdict::check_partial_trans_complete_start(SchemaTransPtr trans_ptr,
29695                                    NdbNodeBitmask &nodes)
29696 {
29697   jam();
29698   NodeRecordPtr ownNodePtr;
29699   c_nodes.getPtr(ownNodePtr, getOwnNodeId());
29700   if (ownNodePtr.p->nodeState == NodeRecord::NDB_MASTER_TAKEOVER)
29701   {
29702     /*
29703       A new master is in the process of committing a
29704       transaction taken over from the failed master.
29705       Check if any nodes should be skipped because they
29706       have already completed the operation
29707     */
29708     jam();
29709     for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
29710       jam();
29711       NodeRecordPtr nodePtr;
29712 #ifdef VM_TRACE
29713       ndbout_c("Node %u", i);
29714 #endif
29715       if (trans_ptr.p->m_nodes.get(i))
29716       {
29717         jam();
29718         c_nodes.getPtr(nodePtr, i);
29719 #ifdef VM_TRACE
29720         ndbout_c("Checking node %u(%u,%u)", nodePtr.i, nodePtr.p->recoveryState, nodePtr.p->takeOverConf.trans_state);
29721 #endif
29722         if (nodePtr.p->takeOverConf.trans_state >= SchemaTrans::TS_FLUSH_COMPLETE)
29723         {
29724           jam();
29725 #ifdef VM_TRACE
29726           ndbout_c("Skipping TS_FLUSH_COMPLETE of node %u", i);
29727 #endif
29728           nodes.clear(i);
29729         }
29730       }
29731     }
29732   }
29733 }
29734 
29735 void
trans_complete_start(Signal * signal,SchemaTransPtr trans_ptr)29736 Dbdict::trans_complete_start(Signal* signal, SchemaTransPtr trans_ptr)
29737 {
29738   jam();
29739 
29740   if (ERROR_INSERTED(6019))
29741   {
29742     jam();
29743     NodeReceiverGroup rg(CMVMI, c_aliveNodes);
29744     signal->theData[0] = 9999;
29745     sendSignal(rg, GSN_NDB_TAMPER, signal, 1, JBB);
29746     return;
29747   }
29748 
29749 #ifdef MARTIN
29750   ndbout_c("trans_complete_start %u", trans_ptr.p->trans_key);
29751 #endif
29752   trans_ptr.p->m_state = SchemaTrans::TS_FLUSH_COMPLETE;
29753 
29754   trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
29755   NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
29756   check_partial_trans_complete_start(trans_ptr, nodes);
29757   NodeReceiverGroup rg(DBDICT, nodes);
29758   {
29759     SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
29760     bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
29761     ndbrequire(ok);
29762   }
29763 
29764   if (ERROR_INSERTED(6148))
29765   {
29766     jam();
29767     /*
29768       Simulate slave missing flushing complete last op
29769     */
29770     jam();
29771     Uint32 nodeId = rand() % MAX_NDB_NODES;
29772     while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
29773       nodeId = rand() % MAX_NDB_NODES;
29774 
29775     infoEvent("Simulating node %u missing RT_FLUSH_COMPLETE", nodeId);
29776     rg.m_nodes.clear(nodeId);
29777     signal->theData[0] = 9999;
29778     signal->theData[1] = ERROR_INSERT_VALUE;
29779     CLEAR_ERROR_INSERT_VALUE;
29780     sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
29781 			5000, 2);
29782   }
29783 
29784   SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
29785   req->senderRef = reference();
29786   req->transKey = trans_ptr.p->trans_key;
29787   req->opKey = RNIL;
29788   req->requestInfo = SchemaTransImplReq::RT_FLUSH_COMPLETE;
29789   req->transId = trans_ptr.p->m_transId;
29790   sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
29791              SchemaTransImplReq::SignalLength, JBB);
29792 }
29793 
29794 void
trans_complete_first(Signal * signal,SchemaTransPtr trans_ptr)29795 Dbdict::trans_complete_first(Signal * signal, SchemaTransPtr trans_ptr)
29796 {
29797   jam();
29798 
29799   if (ERROR_INSERTED(6020))
29800   {
29801     jam();
29802     NodeReceiverGroup rg(CMVMI, c_aliveNodes);
29803     signal->theData[0] = 9999;
29804     sendSignal(rg, GSN_NDB_TAMPER, signal, 1, JBB);
29805     return;
29806   }
29807 
29808   trans_ptr.p->m_state = SchemaTrans::TS_COMPLETING;
29809 
29810   bool first = false;
29811   SchemaOpPtr op_ptr;
29812   {
29813     LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
29814     first = list.first(op_ptr);
29815   }
29816 
29817   if (first)
29818   {
29819     jam();
29820     trans_complete_next(signal, trans_ptr, op_ptr);
29821   }
29822   else
29823   {
29824     jam();
29825     trans_complete_done(signal, trans_ptr);
29826   }
29827 }
29828 
29829 void
trans_complete_next(Signal * signal,SchemaTransPtr trans_ptr,SchemaOpPtr op_ptr)29830 Dbdict::trans_complete_next(Signal* signal,
29831                             SchemaTransPtr trans_ptr, SchemaOpPtr op_ptr)
29832 {
29833   op_ptr.p->m_state = SchemaOp::OS_COMPLETING;
29834   trans_ptr.p->m_curr_op_ptr_i = op_ptr.i;
29835 
29836   trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
29837   NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
29838   NodeReceiverGroup rg(DBDICT, nodes);
29839   {
29840     SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
29841     bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
29842     ndbrequire(ok);
29843   }
29844 
29845   if (ERROR_INSERTED(6149))
29846   {
29847     jam();
29848     /*
29849       Simulate slave missing completing last op
29850     */
29851     jam();
29852     Uint32 nodeId = rand() % MAX_NDB_NODES;
29853     while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
29854       nodeId = rand() % MAX_NDB_NODES;
29855 
29856     infoEvent("Simulating node %u missing RT_COMPLETE", nodeId);
29857     rg.m_nodes.clear(nodeId);
29858     signal->theData[0] = 9999;
29859     signal->theData[1] = ERROR_INSERT_VALUE;
29860     CLEAR_ERROR_INSERT_VALUE;
29861     sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
29862 			5000, 2);
29863   }
29864 
29865   SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
29866   req->senderRef = reference();
29867   req->transKey = trans_ptr.p->trans_key;
29868   req->opKey = op_ptr.p->op_key;
29869   req->requestInfo = SchemaTransImplReq::RT_COMPLETE;
29870   req->transId = trans_ptr.p->m_transId;
29871   sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
29872              SchemaTransImplReq::SignalLength, JBB);
29873 }
29874 
29875 void
trans_complete_recv_reply(Signal * signal,SchemaTransPtr trans_ptr)29876 Dbdict::trans_complete_recv_reply(Signal* signal, SchemaTransPtr trans_ptr)
29877 {
29878   if (hasError(trans_ptr.p->m_error))
29879   {
29880     jam();
29881     // kill nodes that failed COMMIT
29882     ndbrequire(false);
29883     return;
29884   }
29885 
29886   SchemaOpPtr op_ptr;
29887   c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
29888 
29889   bool next = false;
29890   {
29891     LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
29892     next = list.next(op_ptr);
29893   }
29894 
29895   if (next)
29896   {
29897     jam();
29898     trans_complete_next(signal, trans_ptr, op_ptr);
29899     return;
29900   }
29901   else
29902   {
29903     jam();
29904     trans_complete_done(signal, trans_ptr);
29905   }
29906   return;
29907 }
29908 
29909 void
trans_complete_done(Signal * signal,SchemaTransPtr trans_ptr)29910 Dbdict::trans_complete_done(Signal* signal, SchemaTransPtr trans_ptr)
29911 {
29912   jam();
29913   trans_end_start(signal, trans_ptr);
29914 }
29915 
29916 void
trans_end_start(Signal * signal,SchemaTransPtr trans_ptr)29917 Dbdict::trans_end_start(Signal* signal, SchemaTransPtr trans_ptr)
29918 {
29919   ndbrequire(trans_ptr.p->m_state != SchemaTrans::TS_ENDING);
29920   trans_ptr.p->m_state = SchemaTrans::TS_ENDING;
29921 
29922   trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
29923   NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
29924   NodeReceiverGroup rg(DBDICT, nodes);
29925   {
29926     SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
29927     bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
29928     ndbrequire(ok);
29929   }
29930 
29931   if (ERROR_INSERTED(6150))
29932   {
29933     jam();
29934     /*
29935       Simulate slave missing ending transaction
29936     */
29937     jam();
29938     Uint32 nodeId = rand() % MAX_NDB_NODES;
29939     while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
29940       nodeId = rand() % MAX_NDB_NODES;
29941 
29942     infoEvent("Simulating node %u missing RT_END", nodeId);
29943     rg.m_nodes.clear(nodeId);
29944     signal->theData[0] = 9999;
29945     signal->theData[1] = ERROR_INSERT_VALUE;
29946     CLEAR_ERROR_INSERT_VALUE;
29947     sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
29948 			5000, 2);
29949   }
29950 
29951   if (ERROR_INSERTED(6050))
29952   {
29953     /**
29954      * Simulate only next master getting the RT_END
29955      */
29956     infoEvent("Simulating only node %u getting RT_END",
29957               ERROR_INSERT_EXTRA);
29958     rg.m_nodes.clear();
29959     rg.m_nodes.set(ERROR_INSERT_EXTRA);
29960     signal->theData[0] = 9999;
29961     signal->theData[1] = ERROR_INSERT_VALUE;
29962     sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
29963 			5000, 2);
29964     CLEAR_ERROR_INSERT_VALUE;
29965   }
29966 
29967   SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
29968   req->senderRef = reference();
29969   req->transKey = trans_ptr.p->trans_key;
29970   req->opKey = RNIL;
29971   req->requestInfo = SchemaTransImplReq::RT_END;
29972   req->transId = trans_ptr.p->m_transId;
29973   sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
29974              SchemaTransImplReq::SignalLength, JBB);
29975 }
29976 
29977 void
trans_end_recv_reply(Signal * signal,SchemaTransPtr trans_ptr)29978 Dbdict::trans_end_recv_reply(Signal* signal, SchemaTransPtr trans_ptr)
29979 {
29980   // unlock
29981   const DictLockReq& lockReq = trans_ptr.p->m_lockReq;
29982   Uint32 rc = dict_lock_unlock(signal, &lockReq);
29983   debugLockInfo(signal,
29984                 "trans_end_recv_reply unlock",
29985                 rc);
29986 
29987   sendTransClientReply(signal, trans_ptr);
29988   releaseSchemaTrans(trans_ptr);
29989 }
29990 
trans_recover(Signal * signal,SchemaTransPtr trans_ptr)29991 void Dbdict::trans_recover(Signal* signal, SchemaTransPtr trans_ptr)
29992 {
29993   ErrorInfo error;
29994 
29995   jam();
29996 #ifdef VM_TRACE
29997   ndbout_c("Dbdict::trans_recover trans %u, state %u", trans_ptr.p->trans_key, trans_ptr.p->m_state);
29998 #endif
29999 
30000   switch(trans_ptr.p->m_state) {
30001   case SchemaTrans::TS_INITIAL:
30002     jam();
30003   case SchemaTrans::TS_STARTING:
30004     jam();
30005   case SchemaTrans::TS_STARTED:
30006     jam();
30007     if (trans_ptr.p->m_rollback_op == 0)
30008     {
30009       /*
30010         No parsed operations found
30011        */
30012       jam();
30013 #ifdef VM_TRACE
30014       ndbout_c("Dbdict::trans_recover: ENDING START, trans %u(0x%8x), state %u", trans_ptr.i, (uint)trans_ptr.p->trans_key, trans_ptr.p->m_state);
30015 #endif
30016       setError(trans_ptr.p->m_error, SchemaTransEndRep::TransAborted, __LINE__);
30017       trans_end_start(signal, trans_ptr);
30018       return;
30019     }
30020   case SchemaTrans::TS_PARSING:
30021     jam();
30022     setError(trans_ptr.p->m_error, SchemaTransEndRep::TransAborted, __LINE__);
30023     trans_abort_parse_start(signal, trans_ptr);
30024     return;
30025   case SchemaTrans::TS_ABORTING_PARSE:
30026   {
30027     jam();
30028 #ifdef VM_TRACE
30029     ndbout_c("Dbdict::trans_recover: ABORTING_PARSE, trans %u(0x%8x), state %u", trans_ptr.i, (uint)trans_ptr.p->trans_key, trans_ptr.p->m_state);
30030 #endif
30031     setError(trans_ptr.p->m_error, SchemaTransEndRep::TransAborted, __LINE__);
30032     SchemaOpPtr op_ptr;
30033     c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
30034     // Revert operation state to restart abort
30035     op_ptr.p->m_state = SchemaOp::OS_PREPARED;
30036     trans_abort_parse_next(signal, trans_ptr, op_ptr);
30037     return;
30038   }
30039   case SchemaTrans::TS_PREPARING:
30040     jam();
30041     if (trans_ptr.p->m_master_recovery_state == SchemaTrans::TRS_ROLLFORWARD)
30042     {
30043       goto flush_commit;
30044     }
30045     setError(trans_ptr.p->m_error, SchemaTransEndRep::TransAborted, __LINE__);
30046     trans_abort_prepare_start(signal, trans_ptr);
30047     return;
30048   case SchemaTrans::TS_ABORTING_PREPARE:
30049   {
30050     jam();
30051 #ifdef VM_TRACE
30052     ndbout_c("Dbdict::trans_recover: ABORTING PREPARE, trans %u(0x%8x), state %u", trans_ptr.i, (uint)trans_ptr.p->trans_key, trans_ptr.p->m_state);
30053 #endif
30054     setError(trans_ptr.p->m_error, SchemaTransEndRep::TransAborted, __LINE__);
30055     SchemaOpPtr op_ptr;
30056     c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
30057     // Revert operation state to restart abort
30058     op_ptr.p->m_state = SchemaOp::OS_PREPARED;
30059     trans_abort_prepare_next(signal, trans_ptr, op_ptr);
30060     return;
30061   }
30062   case SchemaTrans::TS_FLUSH_COMMIT:
30063     flush_commit:
30064     /*
30065        Flush commit any unflushed slaves
30066     */
30067     jam();
30068     trans_commit_start(signal, trans_ptr);
30069     return;
30070   case SchemaTrans::TS_COMMITTING:
30071   {
30072     if (trans_ptr.p->m_highest_trans_state <= SchemaTrans::TS_COMMITTING)
30073     {
30074       jam();
30075       /*
30076         Commit any uncommited operations
30077       */
30078       SchemaOpPtr op_ptr;
30079       c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
30080       if (op_ptr.p->m_state < SchemaOp::OS_COMMITTED)
30081       {
30082         jam();
30083         trans_commit_next(signal, trans_ptr, op_ptr);
30084         return;
30085       }
30086     }
30087     /*
30088       We have started flushing commits
30089     */
30090     jam();
30091     NodeRecordPtr masterNodePtr;
30092     c_nodes.getPtr(masterNodePtr, c_masterNodeId);
30093     if (masterNodePtr.p->recoveryState
30094         == NodeRecord::RS_PARTIAL_ROLLFORWARD)
30095     {
30096       /*
30097         New master has flushed commit and
30098         thus have released commit mutex
30099       */
30100       jam();
30101       trans_commit_mutex_unlocked(signal, trans_ptr.i, 0);
30102       return;
30103     }
30104     else
30105     {
30106       /*
30107         New master has not flushed commit and
30108         thus have to release commit mutex
30109       */
30110       jam();
30111       trans_commit_done(signal, trans_ptr);
30112       return;
30113     }
30114   }
30115   case SchemaTrans::TS_FLUSH_COMPLETE:
30116     jam();
30117 #ifdef VM_TRACE
30118     ndbout_c("Dbdict::trans_recover: COMMITTING DONE, trans %u(0x%8x), state %u", trans_ptr.i, (uint)trans_ptr.p->trans_key, trans_ptr.p->m_state);
30119 #endif
30120     trans_complete_done(signal, trans_ptr);
30121     return;
30122   case SchemaTrans::TS_COMPLETING:
30123   {
30124     /*
30125       Complete any uncommited operations
30126     */
30127     jam();
30128 #ifdef VM_TRACE
30129     ndbout_c("Dbdict::trans_recover: COMPLETING, trans %u(0x%8x), state %u", trans_ptr.i, (uint)trans_ptr.p->trans_key, trans_ptr.p->m_state);
30130 #endif
30131     SchemaOpPtr op_ptr;
30132     c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
30133     if (op_ptr.p->m_state < SchemaOp::OS_COMPLETED)
30134     {
30135       jam();
30136       trans_complete_next(signal, trans_ptr, op_ptr);
30137       return;
30138     }
30139   }
30140   case SchemaTrans::TS_ENDING:
30141     /*
30142       End any pending slaves
30143      */
30144     jam();
30145 #ifdef VM_TRACE
30146     ndbout_c("Dbdict::trans_recover: ENDING, trans %u(0x%8x), state %u", trans_ptr.i, (uint)trans_ptr.p->trans_key, trans_ptr.p->m_state);
30147 #endif
30148     trans_end_start(signal, trans_ptr);
30149     return;
30150   default:
30151     jam();
30152   }
30153   ndbassert(false);
30154 }
30155 
30156 
30157 // participant
30158 
30159 void
execSCHEMA_TRANS_IMPL_REQ(Signal * signal)30160 Dbdict::execSCHEMA_TRANS_IMPL_REQ(Signal* signal)
30161 {
30162   jamEntry();
30163   if (!assembleFragments(signal)) {
30164     jam();
30165     return;
30166   }
30167   SchemaTransImplReq reqCopy =
30168     *(const SchemaTransImplReq*)signal->getDataPtr();
30169   const SchemaTransImplReq *req = &reqCopy;
30170   const Uint32 rt = DictSignal::getRequestType(req->requestInfo);
30171 
30172   if (rt == SchemaTransImplReq::RT_START)
30173   {
30174     jam();
30175     if (signal->getLength() < SchemaTransImplReq::SignalLengthStart)
30176     {
30177       jam();
30178       reqCopy.start.objectId = getFreeObjId();
30179     }
30180     slave_run_start(signal, req);
30181     return;
30182   }
30183 
30184   ErrorInfo error;
30185   SchemaTransPtr trans_ptr;
30186   SchemaOpPtr op_ptr;
30187   const Uint32 trans_key = req->transKey;
30188   if (!findSchemaTrans(trans_ptr, trans_key))
30189   {
30190     jam();
30191     setError(error, SchemaTransImplRef::InvalidTransKey, __LINE__);
30192     goto err;
30193   }
30194 
30195 #ifdef MARTIN
30196   char buf[256];
30197   switch(rt) {
30198   case(SchemaTransImplReq::RT_START):
30199     sprintf(buf, " RequestType: RT_START");
30200     break;
30201   case(SchemaTransImplReq::RT_PARSE):
30202     sprintf(buf, " RequestType: RT_PARSE");
30203     break;
30204   case(SchemaTransImplReq::RT_FLUSH_PREPARE):
30205     sprintf(buf, " RequestType: RT_FLUSH_PREPARE");
30206     break;
30207   case(SchemaTransImplReq::RT_PREPARE):
30208     sprintf(buf, " RequestType: RT_PREPARE");
30209     break;
30210   case(SchemaTransImplReq::RT_ABORT_PARSE):
30211     sprintf(buf, " RequestType: RT_ABORT_PARSE");
30212     break;
30213   case(SchemaTransImplReq::RT_ABORT_PREPARE):
30214     sprintf(buf, " RequestType: RT_ABORT_PREPARE");
30215     break;
30216   case(SchemaTransImplReq::RT_FLUSH_COMMIT):
30217     sprintf(buf, " RequestType: RT_FLUSH_COMMIT");
30218     break;
30219   case(SchemaTransImplReq::RT_COMMIT):
30220     sprintf(buf, " RequestType: RT_COMMIT");
30221     break;
30222   case(SchemaTransImplReq::RT_FLUSH_COMPLETE):
30223     sprintf(buf, " RequestType: RT_FLUSH_COMPLETE");
30224     break;
30225   case(SchemaTransImplReq::RT_COMPLETE):
30226     sprintf(buf, " RequestType: RT_COMPLETE");
30227     break;
30228   case(SchemaTransImplReq::RT_END):
30229     sprintf(buf, " RequestType: RT_END");
30230     break;
30231   }
30232   infoEvent("Dbdict::execSCHEMA_TRANS_IMPL_REQ: %s", buf);
30233 #endif
30234 
30235   /**
30236    * Check *transaction* request
30237    */
30238   switch(rt){
30239   case SchemaTransImplReq::RT_PARSE:
30240     jam();
30241     slave_run_parse(signal, trans_ptr, req);
30242     return;
30243   case SchemaTransImplReq::RT_END:
30244   case SchemaTransImplReq::RT_FLUSH_PREPARE:
30245   case SchemaTransImplReq::RT_FLUSH_COMMIT:
30246   case SchemaTransImplReq::RT_FLUSH_COMPLETE:
30247     jam();
30248     jamLine(rt);
30249     slave_run_flush(signal, trans_ptr, req);
30250     return;
30251   default:
30252     break;
30253   }
30254 
30255   if (!findSchemaOp(op_ptr, req->opKey))
30256   {
30257     jam();
30258     // wl3600_todo better error no
30259     setError(error, SchemaTransImplRef::InvalidTransKey, __LINE__);
30260     goto err;
30261   }
30262 
30263   {
30264     const OpInfo info = getOpInfo(op_ptr);
30265     switch(rt){
30266     case SchemaTransImplReq::RT_START:
30267     case SchemaTransImplReq::RT_PARSE:
30268     case SchemaTransImplReq::RT_FLUSH_PREPARE:
30269     case SchemaTransImplReq::RT_FLUSH_COMMIT:
30270     case SchemaTransImplReq::RT_FLUSH_COMPLETE:
30271       ndbrequire(false); // handled above
30272     case SchemaTransImplReq::RT_PREPARE:
30273       jam();
30274       op_ptr.p->m_state = SchemaOp::OS_PREPARING;
30275       (this->*(info.m_prepare))(signal, op_ptr);
30276       return;
30277     case SchemaTransImplReq::RT_ABORT_PARSE:
30278       jam();
30279       ndbrequire(op_ptr.p->nextList == RNIL);
30280       op_ptr.p->m_state = SchemaOp::OS_ABORTING_PARSE;
30281       (this->*(info.m_abortParse))(signal, op_ptr);
30282       trans_log_schema_op_abort(op_ptr);
30283       if (!trans_ptr.p->m_isMaster)
30284       {
30285         jam();
30286         trans_ptr.p->m_state = SchemaTrans::TS_ABORTING_PARSE;
30287         /**
30288          * Remove op (except at coordinator
30289          */
30290         LocalSchemaOp_list list(c_schemaOpPool, trans_ptr.p->m_op_list);
30291         list.remove(op_ptr);
30292         releaseSchemaOp(op_ptr);
30293       }
30294       return;
30295     case SchemaTransImplReq::RT_ABORT_PREPARE:
30296       jam();
30297       op_ptr.p->m_state = SchemaOp::OS_ABORTING_PREPARE;
30298       (this->*(info.m_abortPrepare))(signal, op_ptr);
30299       if (!trans_ptr.p->m_isMaster)
30300       {
30301         jam();
30302         trans_ptr.p->m_state = SchemaTrans::TS_ABORTING_PREPARE;
30303       }
30304       return;
30305     case SchemaTransImplReq::RT_COMMIT:
30306       jam();
30307       op_ptr.p->m_state = SchemaOp::OS_COMMITTING;
30308       (this->*(info.m_commit))(signal, op_ptr);
30309       return;
30310     case SchemaTransImplReq::RT_COMPLETE:
30311       jam();
30312       op_ptr.p->m_state = SchemaOp::OS_COMPLETING;
30313       (this->*(info.m_complete))(signal, op_ptr);
30314       trans_log_schema_op_complete(op_ptr);
30315       return;
30316     }
30317   }
30318 
30319   return;
30320 err:
30321   ndbrequire(false);
30322 }
30323 
30324 void
slave_run_start(Signal * signal,const SchemaTransImplReq * req)30325 Dbdict::slave_run_start(Signal *signal, const SchemaTransImplReq* req)
30326 {
30327   ErrorInfo error;
30328   SchemaTransPtr trans_ptr;
30329   const Uint32 trans_key = req->transKey;
30330 
30331   Uint32 objId = req->start.objectId;
30332   if (check_read_obj(objId,0) == 0)
30333   { /* schema file id already in use */
30334     jam();
30335     setError(error, CreateTableRef::NoMoreTableRecords, __LINE__);
30336     goto err;
30337   }
30338 
30339   if (req->senderRef != reference())
30340   {
30341     jam();
30342     if (!seizeSchemaTrans(trans_ptr, trans_key))
30343     {
30344       jam();
30345       setError(error, SchemaTransImplRef::TooManySchemaTrans, __LINE__);
30346       goto err;
30347     }
30348     trans_ptr.p->m_clientRef = req->start.clientRef;
30349     trans_ptr.p->m_transId = req->transId;
30350     trans_ptr.p->m_isMaster = false;
30351     trans_ptr.p->m_masterRef = req->senderRef;
30352     trans_ptr.p->m_requestInfo = req->requestInfo;
30353     trans_ptr.p->m_state = SchemaTrans::TS_STARTED;
30354 
30355     ndbrequire((req->requestInfo & DictSignal::RF_LOCAL_TRANS) == 0);
30356     trans_ptr.p->m_nodes = c_aliveNodes;
30357   }
30358   else
30359   {
30360     jam();
30361     // this branch does nothing but is convenient for signal pong
30362     ndbrequire(findSchemaTrans(trans_ptr, req->transKey));
30363   }
30364 
30365   trans_ptr.p->m_obj_id = objId;
30366   trans_log(trans_ptr);
30367 
30368   sendTransConf(signal, trans_ptr);
30369   return;
30370 
30371 err:
30372   SchemaTrans tmp_trans;
30373   trans_ptr.i = RNIL;
30374   trans_ptr.p = &tmp_trans;
30375   trans_ptr.p->trans_key = trans_key;
30376   trans_ptr.p->m_masterRef = req->senderRef;
30377   setError(trans_ptr.p->m_error, error);
30378   sendTransRef(signal, trans_ptr);
30379 }
30380 
30381 void
slave_run_parse(Signal * signal,SchemaTransPtr trans_ptr,const SchemaTransImplReq * req)30382 Dbdict::slave_run_parse(Signal *signal,
30383                         SchemaTransPtr trans_ptr,
30384                         const SchemaTransImplReq* req)
30385 {
30386   SchemaOpPtr op_ptr;
30387   D("slave_run_parse");
30388 
30389   const Uint32 op_key = req->opKey;
30390   const Uint32 gsn = req->parse.gsn;
30391   const Uint32 requestInfo = req->requestInfo;
30392   const OpInfo& info = *findOpInfo(gsn);
30393 
30394   // signal data contains impl_req
30395   const Uint32* src = signal->getDataPtr() + SchemaTransImplReq::SignalLength;
30396   const Uint32 len = info.m_impl_req_length;
30397 
30398   SectionHandle handle(this, signal);
30399 
30400   ndbrequire(op_key != RNIL);
30401   ErrorInfo error;
30402   if (trans_ptr.p->m_isMaster)
30403   {
30404     jam();
30405     // this branch does nothing but is convenient for signal pong
30406 
30407     //XXX Check if op == last op in trans
30408     findSchemaOp(op_ptr, op_key);
30409     ndbrequire(!op_ptr.isNull());
30410 
30411     OpRecPtr oprec_ptr = op_ptr.p->m_oprec_ptr;
30412     const Uint32* dst = oprec_ptr.p->m_impl_req_data;
30413     ndbrequire(memcmp(dst, src, len << 2) == 0);
30414   }
30415   else
30416   {
30417     if (checkSingleUserMode(trans_ptr.p->m_clientRef))
30418     {
30419       jam();
30420       setError(error, AlterTableRef::SingleUser, __LINE__);
30421     }
30422     else if (seizeSchemaOp(trans_ptr, op_ptr, op_key, info))
30423     {
30424       jam();
30425 
30426       DictSignal::addRequestExtra(op_ptr.p->m_requestInfo, requestInfo);
30427       DictSignal::addRequestFlags(op_ptr.p->m_requestInfo, requestInfo);
30428 
30429       OpRecPtr oprec_ptr = op_ptr.p->m_oprec_ptr;
30430       Uint32* dst = oprec_ptr.p->m_impl_req_data;
30431       memcpy(dst, src, len << 2);
30432 
30433       op_ptr.p->m_state = SchemaOp::OS_PARSING;
30434       (this->*(info.m_parse))(signal, false, op_ptr, handle, error);
30435     } else {
30436       jam();
30437       setError(error, SchemaTransImplRef::TooManySchemaOps, __LINE__);
30438     }
30439   }
30440 
30441   // parse must consume but not release signal sections
30442   releaseSections(handle);
30443 
30444   if (hasError(error))
30445   {
30446     jam();
30447     setError(trans_ptr, error);
30448     sendTransRef(signal, trans_ptr);
30449     return;
30450   }
30451   sendTransConf(signal, op_ptr);
30452 }
30453 
30454 void
slave_run_flush(Signal * signal,SchemaTransPtr trans_ptr,const SchemaTransImplReq * req)30455 Dbdict::slave_run_flush(Signal *signal,
30456                         SchemaTransPtr trans_ptr,
30457                         const SchemaTransImplReq* req)
30458 {
30459   bool do_flush = false;
30460   const Uint32 rt = DictSignal::getRequestType(req->requestInfo);
30461   const bool master = trans_ptr.p->m_isMaster;
30462 
30463   jam();
30464   jamLine(trans_ptr.p->m_state);
30465   switch(rt){
30466   case SchemaTransImplReq::RT_FLUSH_PREPARE:
30467     if (master)
30468     {
30469       jam();
30470       ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_FLUSH_PREPARE);
30471     }
30472     else
30473     {
30474       jam();
30475       ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_STARTED ||
30476                  trans_ptr.p->m_state == SchemaTrans::TS_ABORTING_PARSE);
30477       trans_ptr.p->m_state = SchemaTrans::TS_FLUSH_PREPARE;
30478     }
30479     do_flush = trans_ptr.p->m_flush_prepare;
30480     break;
30481   case SchemaTransImplReq::RT_FLUSH_COMMIT:
30482     if (master)
30483     {
30484       jam();
30485       ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_FLUSH_COMMIT);
30486     }
30487     else
30488     {
30489       jam();
30490       ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_PREPARING);
30491       trans_ptr.p->m_state = SchemaTrans::TS_FLUSH_COMMIT;
30492     }
30493     do_flush = trans_ptr.p->m_flush_commit;
30494     break;
30495   case SchemaTransImplReq::RT_FLUSH_COMPLETE:
30496     if (master)
30497     {
30498       jam();
30499       ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_FLUSH_COMPLETE);
30500     }
30501     else
30502     {
30503       jam();
30504       ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_COMMITTING);
30505       trans_ptr.p->m_state = SchemaTrans::TS_FLUSH_COMPLETE;
30506     }
30507     do_flush = trans_ptr.p->m_flush_complete;
30508     break;
30509   case SchemaTransImplReq::RT_END:
30510     /**
30511      * No state check here, cause we get here regardless if transaction
30512      *   succeded or not...
30513      */
30514     jam();
30515     trans_ptr.p->m_state = SchemaTrans::TS_ENDING;
30516     do_flush = trans_ptr.p->m_flush_end;
30517     break;
30518   default:
30519     ndbrequire(false);
30520   }
30521 
30522   trans_log(trans_ptr);
30523 
30524 #if 1
30525   if (do_flush == false)
30526   {
30527     /**
30528      * If no operations needs durable complete phase...
30529      *   skip it and leave pending trans...
30530      *   will be flushed on next schema trans
30531      *   or will be found in state COMMIT
30532      */
30533     jam();
30534     slave_writeSchema_conf(signal, trans_ptr.p->trans_key, 0);
30535     return;
30536   }
30537 #endif
30538 
30539   XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
30540   ndbrequire(c_writeSchemaRecord.inUse == false);
30541   c_writeSchemaRecord.inUse = true;
30542   c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
30543   c_writeSchemaRecord.newFile = false;
30544   c_writeSchemaRecord.firstPage = 0;
30545   c_writeSchemaRecord.noOfPages = xsf->noOfPages;
30546 
30547   c_writeSchemaRecord.m_callback.m_callbackData = trans_ptr.p->trans_key;
30548   c_writeSchemaRecord.m_callback.m_callbackFunction =
30549     safe_cast(&Dbdict::slave_writeSchema_conf);
30550 
30551   for(Uint32 i = 0; i<xsf->noOfPages; i++)
30552     computeChecksum(xsf, i);
30553 
30554   startWriteSchemaFile(signal);
30555 }
30556 
30557 void
slave_writeSchema_conf(Signal * signal,Uint32 trans_key,Uint32 ret)30558 Dbdict::slave_writeSchema_conf(Signal* signal,
30559                                Uint32 trans_key,
30560                                Uint32 ret)
30561 {
30562   jamEntry();
30563   ndbrequire(ret == 0);
30564   SchemaTransPtr trans_ptr;
30565   ndbrequire(findSchemaTrans(trans_ptr, trans_key));
30566 
30567   bool release = false;
30568   if (!trans_ptr.p->m_isMaster)
30569   {
30570     switch(trans_ptr.p->m_state){
30571     case SchemaTrans::TS_FLUSH_PREPARE:
30572       jam();
30573       trans_ptr.p->m_state = SchemaTrans::TS_PREPARING;
30574       break;
30575     case SchemaTrans::TS_FLUSH_COMMIT:
30576     {
30577       jam();
30578       trans_ptr.p->m_state = SchemaTrans::TS_COMMITTING;
30579       // Take commit lock
30580       Mutex mutex(signal, c_mutexMgr, trans_ptr.p->m_commit_mutex);
30581       Callback c = { safe_cast(&Dbdict::slave_commit_mutex_locked), trans_ptr.i };
30582       bool ok = mutex.lock(c);
30583       ndbrequire(ok);
30584       return;
30585     }
30586     case SchemaTrans::TS_FLUSH_COMPLETE:
30587     {
30588       jam();
30589       trans_ptr.p->m_state = SchemaTrans::TS_COMPLETING;
30590      // Release commit lock
30591       Mutex mutex(signal, c_mutexMgr, trans_ptr.p->m_commit_mutex);
30592       Callback c = { safe_cast(&Dbdict::slave_commit_mutex_unlocked), trans_ptr.i };
30593       mutex.unlock(c);
30594       return;
30595     }
30596     case SchemaTrans::TS_ENDING:
30597       jam();
30598       release = true;
30599       break;
30600     default:
30601       jamLine(trans_ptr.p->m_state);
30602       ndbrequire(false);
30603     }
30604   }
30605 
30606   sendTransConfRelease(signal, trans_ptr);
30607 }
30608 
30609 void
slave_commit_mutex_locked(Signal * signal,Uint32 transPtrI,Uint32 ret)30610 Dbdict::slave_commit_mutex_locked(Signal* signal,
30611                                   Uint32 transPtrI,
30612                                   Uint32 ret)
30613 {
30614   jamEntry();
30615 #ifdef MARTIN
30616   ndbout_c("slave_commit_mutex_locked");
30617 #endif
30618   SchemaTransPtr trans_ptr;
30619   c_schemaTransPool.getPtr(trans_ptr, transPtrI);
30620 
30621   ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_COMMITTING);
30622   sendTransConfRelease(signal, trans_ptr);
30623 }
30624 
30625 void
slave_commit_mutex_unlocked(Signal * signal,Uint32 transPtrI,Uint32 ret)30626 Dbdict::slave_commit_mutex_unlocked(Signal* signal,
30627                                     Uint32 transPtrI,
30628                                     Uint32 ret)
30629 {
30630   jamEntry();
30631 #ifdef MARTIN
30632   ndbout_c("slave_commit_mutex_unlocked");
30633 #endif
30634   SchemaTransPtr trans_ptr;
30635   c_schemaTransPool.getPtr(trans_ptr, transPtrI);
30636 
30637   trans_ptr.p->m_commit_mutex.release(c_mutexMgr);
30638 
30639   ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_COMPLETING);
30640   sendTransConfRelease(signal, trans_ptr);
30641 }
30642 
sendTransConfRelease(Signal * signal,SchemaTransPtr trans_ptr)30643 void Dbdict::sendTransConfRelease(Signal*signal, SchemaTransPtr trans_ptr)
30644 {
30645   jam();
30646   sendTransConf(signal, trans_ptr);
30647 
30648   if ((!trans_ptr.p->m_isMaster) &&
30649       trans_ptr.p->m_state == SchemaTrans::TS_ENDING)
30650   {
30651     jam();
30652     releaseSchemaTrans(trans_ptr);
30653   }
30654 }
30655 
30656 void
update_op_state(SchemaOpPtr op_ptr)30657 Dbdict::update_op_state(SchemaOpPtr op_ptr)
30658 {
30659   switch(op_ptr.p->m_state){
30660   case SchemaOp::OS_PARSE_MASTER:
30661     jam();
30662     break;
30663   case SchemaOp::OS_PARSING:
30664     jam();
30665     op_ptr.p->m_state = SchemaOp::OS_PARSED;
30666     break;
30667   case SchemaOp::OS_PARSED:
30668     ndbrequire(false);
30669   case SchemaOp::OS_PREPARING:
30670     jam();
30671     op_ptr.p->m_state = SchemaOp::OS_PREPARED;
30672     break;
30673   case SchemaOp::OS_PREPARED:
30674     ndbrequire(false);
30675   case SchemaOp::OS_ABORTING_PREPARE:
30676     jam();
30677     op_ptr.p->m_state = SchemaOp::OS_ABORTED_PREPARE;
30678     break;
30679   case SchemaOp::OS_ABORTED_PREPARE:
30680     ndbrequire(false);
30681   case SchemaOp::OS_ABORTING_PARSE:
30682     jam();
30683     break;
30684     //case SchemaOp::OS_ABORTED_PARSE:  // Not used, op released
30685   case SchemaOp::OS_COMMITTING:
30686     jam();
30687     op_ptr.p->m_state = SchemaOp::OS_COMMITTED;
30688     break;
30689   case SchemaOp::OS_COMMITTED:
30690     ndbrequire(false);
30691   case SchemaOp::OS_COMPLETING:
30692     jam();
30693     op_ptr.p->m_state = SchemaOp::OS_COMPLETED;
30694     break;
30695   case SchemaOp::OS_COMPLETED:
30696     ndbrequire(false);
30697   }
30698 }
30699 
30700 void
sendTransConf(Signal * signal,SchemaOpPtr op_ptr)30701 Dbdict::sendTransConf(Signal* signal, SchemaOpPtr op_ptr)
30702 {
30703   jam();
30704   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
30705   update_op_state(op_ptr);
30706   sendTransConf(signal, trans_ptr);
30707 }
30708 
30709 void
sendTransConf(Signal * signal,SchemaTransPtr trans_ptr)30710 Dbdict::sendTransConf(Signal* signal, SchemaTransPtr trans_ptr)
30711 {
30712   ndbrequire(!trans_ptr.isNull());
30713   ndbrequire(signal->getNoOfSections() == 0);
30714 
30715   SchemaTransImplConf* conf =
30716     (SchemaTransImplConf*)signal->getDataPtrSend();
30717   conf->senderRef = reference();
30718   conf->transKey = trans_ptr.p->trans_key;
30719 
30720   const Uint32 masterRef = trans_ptr.p->m_masterRef;
30721 
30722   if (ERROR_INSERTED(6103)) {
30723     jam();
30724     CLEAR_ERROR_INSERT_VALUE;
30725 
30726     // delay CONF
30727 
30728     Uint32* data = &signal->theData[0];
30729     memmove(&data[2], &data[0], SchemaTransImplConf::SignalLength << 2);
30730     data[0] = 6103;
30731     data[1] = masterRef;
30732     sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
30733                         5000, 2 + SchemaTransImplConf::SignalLength);
30734     return;
30735   }
30736 
30737   sendSignal(masterRef, GSN_SCHEMA_TRANS_IMPL_CONF, signal,
30738              SchemaTransImplConf::SignalLength, JBB);
30739 }
30740 
30741 void
sendTransRef(Signal * signal,SchemaOpPtr op_ptr)30742 Dbdict::sendTransRef(Signal* signal, SchemaOpPtr op_ptr)
30743 {
30744   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
30745   // must have error and already propagated to trans
30746   ndbrequire(hasError(op_ptr.p->m_error));
30747   ndbrequire(hasError(trans_ptr.p->m_error));
30748 
30749   update_op_state(op_ptr);
30750 
30751   sendTransRef(signal, trans_ptr);
30752 }
30753 
30754 void
sendTransRef(Signal * signal,SchemaTransPtr trans_ptr)30755 Dbdict::sendTransRef(Signal* signal, SchemaTransPtr trans_ptr)
30756 {
30757   D("sendTransRef");
30758   ndbrequire(hasError(trans_ptr.p->m_error));
30759 
30760   // trans is not defined on RT_BEGIN REF
30761 
30762   SchemaTransImplRef* ref =
30763     (SchemaTransImplRef*)signal->getDataPtrSend();
30764   ref->senderRef = reference();
30765   ref->transKey = trans_ptr.p->trans_key;
30766   getError(trans_ptr.p->m_error, ref);
30767 
30768   // erro has been reported, clear it
30769   resetError(trans_ptr.p->m_error);
30770 
30771   const Uint32 masterRef = trans_ptr.p->m_masterRef;
30772   sendSignal(masterRef, GSN_SCHEMA_TRANS_IMPL_REF, signal,
30773              SchemaTransImplRef::SignalLength, JBB);
30774 }
30775 
30776 void
trans_log(SchemaTransPtr trans_ptr)30777 Dbdict::trans_log(SchemaTransPtr trans_ptr)
30778 {
30779   Uint32 objectId = trans_ptr.p->m_obj_id;
30780   XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
30781   SchemaFile::TableEntry * entry = getTableEntry(xsf, objectId);
30782 
30783   jam();
30784   jamLine(trans_ptr.p->m_state);
30785   jamLine(entry->m_tableState);
30786   switch(trans_ptr.p->m_state){
30787   case SchemaTrans::TS_STARTED:
30788   case SchemaTrans::TS_STARTING:{
30789     jam();
30790     Uint32 version = entry->m_tableVersion;
30791     Uint32 new_version = create_obj_inc_schema_version(version);
30792     entry->init();
30793     entry->m_tableState = SchemaFile::SF_STARTED;
30794     entry->m_tableVersion = new_version;
30795     entry->m_tableType = DictTabInfo::SchemaTransaction;
30796     entry->m_info_words = 0;
30797     entry->m_gcp = 0;
30798     entry->m_transId = trans_ptr.p->m_transId;
30799     break;
30800   }
30801   case SchemaTrans::TS_FLUSH_PREPARE:
30802     jam();
30803     ndbrequire(entry->m_tableState == SchemaFile::SF_STARTED);
30804     entry->m_tableState = SchemaFile::SF_PREPARE;
30805     break;
30806   case SchemaTrans::TS_ABORTING_PREPARE:
30807     jam();
30808     ndbrequire(entry->m_tableState == SchemaFile::SF_PREPARE);
30809     entry->m_tableState = SchemaFile::SF_ABORT;
30810     break;
30811   case SchemaTrans::TS_FLUSH_COMMIT:
30812     jam();
30813     ndbrequire(entry->m_tableState == SchemaFile::SF_PREPARE);
30814     entry->m_tableState = SchemaFile::SF_COMMIT;
30815     break;
30816   case SchemaTrans::TS_FLUSH_COMPLETE:
30817     jam();
30818     ndbrequire(entry->m_tableState == SchemaFile::SF_COMMIT);
30819     entry->m_tableState = SchemaFile::SF_COMPLETE;
30820     break;
30821   case SchemaTrans::TS_ENDING:
30822     jam();
30823     entry->m_transId = 0;
30824     entry->m_tableState = SchemaFile::SF_UNUSED;
30825     break;
30826   default:
30827     ndbrequire(false);
30828   }
30829 }
30830 
30831 /**
30832  * Schema operation logging (SchemaFile)
30833  */
30834 Uint32
trans_log_schema_op(SchemaOpPtr op_ptr,Uint32 objectId,const SchemaFile::TableEntry * newEntry)30835 Dbdict::trans_log_schema_op(SchemaOpPtr op_ptr,
30836                             Uint32 objectId,
30837                             const SchemaFile::TableEntry * newEntry)
30838 {
30839   jam();
30840 
30841   XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
30842   SchemaFile::TableEntry * oldEntry = getTableEntry(xsf, objectId);
30843   D("trans_log_schema_op" << V(*oldEntry) << V(*newEntry));
30844 
30845   if (oldEntry->m_transId != 0)
30846   {
30847     jam();
30848     return DropTableRef::ActiveSchemaTrans; // XXX todo add general code
30849   }
30850 
30851   SchemaFile::TableEntry tmp = * newEntry;
30852   bool restart = op_ptr.p->m_restart;
30853   switch((SchemaFile::EntryState)newEntry->m_tableState){
30854   case SchemaFile::SF_CREATE:
30855     jam();
30856     ndbrequire(restart || oldEntry->m_tableState == SchemaFile::SF_UNUSED);
30857     break;
30858   case SchemaFile::SF_ALTER:
30859     jam();
30860     ndbrequire(restart || oldEntry->m_tableState == SchemaFile::SF_IN_USE);
30861     tmp = * oldEntry;
30862     tmp.m_info_words = newEntry->m_info_words;
30863     tmp.m_tableVersion = newEntry->m_tableVersion;
30864     break;
30865   case SchemaFile::SF_DROP:
30866     jam();
30867     ndbrequire(restart || oldEntry->m_tableState == SchemaFile::SF_IN_USE);
30868     tmp = *oldEntry;
30869     tmp.m_tableState = SchemaFile::SF_DROP;
30870     break;
30871   default:
30872     jamLine(newEntry->m_tableState);
30873     ndbrequire(false);
30874   }
30875 
30876   tmp.m_tableState = newEntry->m_tableState;
30877   tmp.m_transId = newEntry->m_transId;
30878   op_ptr.p->m_orig_entry_id = objectId;
30879   op_ptr.p->m_orig_entry = * oldEntry;
30880 
30881   * oldEntry = tmp;
30882 
30883   if (op_ptr.p->m_restart != 1)
30884   {
30885     jam();
30886 
30887     SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
30888     trans_ptr.p->m_flush_prepare |= true;
30889     trans_ptr.p->m_flush_commit |= true;
30890   }
30891 
30892   return 0;
30893 }
30894 
30895 void
trans_log_schema_op_abort(SchemaOpPtr op_ptr)30896 Dbdict::trans_log_schema_op_abort(SchemaOpPtr op_ptr)
30897 {
30898   Uint32 objectId = op_ptr.p->m_orig_entry_id;
30899   if (objectId != RNIL)
30900   {
30901     jam();
30902     op_ptr.p->m_orig_entry_id = RNIL;
30903     XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
30904     SchemaFile::TableEntry * entry = getTableEntry(xsf, objectId);
30905     * entry = op_ptr.p->m_orig_entry;
30906   }
30907 }
30908 
30909 void
trans_log_schema_op_complete(SchemaOpPtr op_ptr)30910 Dbdict::trans_log_schema_op_complete(SchemaOpPtr op_ptr)
30911 {
30912   Uint32 objectId = op_ptr.p->m_orig_entry_id;
30913   if (objectId != RNIL)
30914   {
30915     jam();
30916     op_ptr.p->m_orig_entry_id = RNIL;
30917     XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
30918     SchemaFile::TableEntry * entry = getTableEntry(xsf, objectId);
30919     switch((SchemaFile::EntryState)entry->m_tableState){
30920     case SchemaFile::SF_CREATE:
30921       jam();
30922       entry->m_tableState = SchemaFile::SF_IN_USE;
30923       break;
30924     case SchemaFile::SF_ALTER:
30925       jam();
30926       entry->m_tableState = SchemaFile::SF_IN_USE;
30927       break;
30928     case SchemaFile::SF_DROP:
30929       jam();
30930       entry->m_tableState = SchemaFile::SF_UNUSED;
30931       break;
30932     default:
30933       jamLine(entry->m_tableState);
30934       ndbrequire(false);
30935     }
30936     entry->m_transId = 0;
30937   }
30938 }
30939 
30940 // reply to trans client for begin/end trans
30941 
30942 void
sendTransClientReply(Signal * signal,SchemaTransPtr trans_ptr)30943 Dbdict::sendTransClientReply(Signal* signal, SchemaTransPtr trans_ptr)
30944 {
30945   const Uint32 clientFlags = trans_ptr.p->m_clientFlags;
30946   D("sendTransClientReply" << hex << V(clientFlags));
30947   D("c_rope_pool free: " << c_rope_pool.getNoOfFree());
30948 
30949   Uint32 receiverRef = 0;
30950   Uint32 transId = 0;
30951   NodeRecordPtr ownNodePtr;
30952 
30953   c_nodes.getPtr(ownNodePtr, getOwnNodeId());
30954 
30955   if (!(clientFlags & TransClient::TakeOver)) {
30956     jam();
30957     receiverRef = trans_ptr.p->m_clientRef;
30958     transId = trans_ptr.p->m_transId;
30959   } else {
30960     jam();
30961     receiverRef = reference();
30962     transId = trans_ptr.p->m_takeOverTxKey;
30963   }
30964 
30965   if (trans_ptr.p->m_clientState == TransClient::BeginReq) {
30966     if (!hasError(trans_ptr.p->m_error)) {
30967       jam();
30968       SchemaTransBeginConf* conf =
30969         (SchemaTransBeginConf*)signal->getDataPtrSend();
30970       conf->senderRef = reference();
30971       conf->transId = transId;
30972       conf->transKey = trans_ptr.p->trans_key;
30973       sendSignal(receiverRef, GSN_SCHEMA_TRANS_BEGIN_CONF, signal,
30974                  SchemaTransBeginConf::SignalLength, JBB);
30975     } else {
30976       jam();
30977       SchemaTransBeginRef* ref =
30978         (SchemaTransBeginRef*)signal->getDataPtrSend();
30979       ref->senderRef = reference();
30980       ref->transId = transId;
30981       getError(trans_ptr.p->m_error, ref);
30982       sendSignal(receiverRef, GSN_SCHEMA_TRANS_BEGIN_REF, signal,
30983                  SchemaTransBeginRef::SignalLength, JBB);
30984     }
30985     resetError(trans_ptr);
30986     trans_ptr.p->m_clientState = TransClient::BeginReply;
30987     return;
30988   }
30989 
30990   if (trans_ptr.p->m_clientState == TransClient::EndReq) {
30991     if (!hasError(trans_ptr.p->m_error)) {
30992       jam();
30993       SchemaTransEndConf* conf =
30994         (SchemaTransEndConf*)signal->getDataPtrSend();
30995       conf->senderRef = reference();
30996       conf->transId = transId;
30997       sendSignal(receiverRef, GSN_SCHEMA_TRANS_END_CONF, signal,
30998                  SchemaTransEndConf::SignalLength, JBB);
30999     } else {
31000       jam();
31001       SchemaTransEndRef* ref =
31002         (SchemaTransEndRef*)signal->getDataPtrSend();
31003       ref->senderRef = reference();
31004       ref->transId = transId;
31005       getError(trans_ptr.p->m_error, ref);
31006       ref->masterNodeId = c_masterNodeId;
31007       sendSignal(receiverRef, GSN_SCHEMA_TRANS_END_REF, signal,
31008                  SchemaTransEndRef::SignalLength, JBB);
31009     }
31010     resetError(trans_ptr);
31011     trans_ptr.p->m_clientState = TransClient::EndReply;
31012     if (ownNodePtr.p->nodeState == NodeRecord::NDB_MASTER_TAKEOVER)
31013     {
31014       /*
31015         New master was taking over transaction
31016        */
31017       jam();
31018       goto send_node_fail_rep;
31019     }
31020     return;
31021   }
31022 
31023   if (ownNodePtr.p->nodeState == NodeRecord::NDB_MASTER_TAKEOVER)
31024   {
31025     /*
31026       New master was taking over transaction
31027       Report transaction outcome to client
31028      */
31029     jam();
31030     {
31031       SchemaTransEndRep* rep =
31032         (SchemaTransEndRep*)signal->getDataPtrSend();
31033       rep->senderRef = reference();
31034       rep->transId = transId;
31035       if (hasError(trans_ptr.p->m_error))
31036       {
31037         jam();
31038         getError(trans_ptr.p->m_error, rep);
31039       }
31040       else
31041       {
31042         jam();
31043         rep->errorCode = 0;
31044         rep->errorLine = 0;
31045         rep->errorNodeId = 0;
31046       }
31047       rep->masterNodeId = c_masterNodeId;
31048 #ifdef VM_TRACE
31049       ndbout_c("Dbdict::sendTransClientReply: sending GSN_SCHEMA_TRANS_END_REP to 0x%8x", receiverRef);
31050 #endif
31051       sendSignal(receiverRef, GSN_SCHEMA_TRANS_END_REP, signal,
31052                  SchemaTransEndRep::SignalLength, JBB);
31053     }
31054 send_node_fail_rep:
31055     /*
31056       Continue with NODE_FAILREP
31057     */
31058     send_nf_complete_rep(signal, &ownNodePtr.p->nodeFailRep);
31059   }
31060 }
31061 
31062 
31063 // DICT as schema trans client
31064 
31065 bool
seizeTxHandle(TxHandlePtr & tx_ptr)31066 Dbdict::seizeTxHandle(TxHandlePtr& tx_ptr)
31067 {
31068   Uint32 tx_key = c_opRecordSequence + 1;
31069   if (c_txHandleHash.seize(tx_ptr)) {
31070     jam();
31071     new (tx_ptr.p) TxHandle();
31072     tx_ptr.p->tx_key = tx_key;
31073     c_txHandleHash.add(tx_ptr);
31074     tx_ptr.p->m_magic = TxHandle::DICT_MAGIC;
31075     D("seizeTxHandle" << V(tx_key));
31076     c_opRecordSequence = tx_key;
31077     return true;
31078   }
31079   tx_ptr.setNull();
31080   return false;
31081 }
31082 
31083 bool
findTxHandle(TxHandlePtr & tx_ptr,Uint32 tx_key)31084 Dbdict::findTxHandle(TxHandlePtr& tx_ptr, Uint32 tx_key)
31085 {
31086   TxHandle tx_rec(tx_key);
31087   if (c_txHandleHash.find(tx_ptr, tx_rec)) {
31088     jam();
31089     ndbrequire(tx_ptr.p->m_magic == TxHandle::DICT_MAGIC);
31090     D("findTxHandle" << V(tx_key));
31091     return true;
31092   }
31093   tx_ptr.setNull();
31094   return false;
31095 }
31096 
31097 void
releaseTxHandle(TxHandlePtr & tx_ptr)31098 Dbdict::releaseTxHandle(TxHandlePtr& tx_ptr)
31099 {
31100   D("releaseTxHandle" << V(tx_ptr.p->tx_key));
31101 
31102   ndbrequire(tx_ptr.p->m_magic == TxHandle::DICT_MAGIC);
31103   tx_ptr.p->m_magic = 0;
31104   c_txHandleHash.release(tx_ptr);
31105 }
31106 
31107 void
beginSchemaTrans(Signal * signal,TxHandlePtr tx_ptr)31108 Dbdict::beginSchemaTrans(Signal* signal, TxHandlePtr tx_ptr)
31109 {
31110   D("beginSchemaTrans");
31111   tx_ptr.p->m_transId = tx_ptr.p->tx_key;
31112 
31113   SchemaTransBeginReq* req =
31114     (SchemaTransBeginReq*)signal->getDataPtrSend();
31115 
31116   Uint32 requestInfo = 0;
31117   DictSignal::addRequestFlags(requestInfo, tx_ptr.p->m_requestInfo);
31118 
31119   const Uint32 clientFlags = tx_ptr.p->m_clientFlags;
31120   ndbrequire(!(clientFlags & TransClient::TakeOver));
31121   req->clientRef = reference();
31122   req->transId = tx_ptr.p->m_transId;
31123   req->requestInfo = requestInfo;
31124   sendSignal(reference(), GSN_SCHEMA_TRANS_BEGIN_REQ, signal,
31125              SchemaTransBeginReq::SignalLength, JBB);
31126 }
31127 
31128 void
endSchemaTrans(Signal * signal,TxHandlePtr tx_ptr,Uint32 flags)31129 Dbdict::endSchemaTrans(Signal* signal, TxHandlePtr tx_ptr, Uint32 flags)
31130 {
31131   D("endSchemaTrans" << hex << V(flags));
31132 
31133   SchemaTransEndReq* req =
31134     (SchemaTransEndReq*)signal->getDataPtrSend();
31135 
31136   Uint32 requestInfo = 0;
31137   DictSignal::addRequestFlags(requestInfo, tx_ptr.p->m_requestInfo);
31138 
31139   const Uint32 clientFlags = tx_ptr.p->m_clientFlags;
31140   Uint32 transId = 0;
31141   if (!(clientFlags & TransClient::TakeOver)) {
31142     jam();
31143     transId = tx_ptr.p->m_transId;
31144   } else {
31145     jam();
31146     transId = tx_ptr.p->m_takeOverTransId;
31147     D("take over mode" << hex << V(transId));
31148   }
31149 
31150   req->clientRef = reference();
31151   req->transId = transId;
31152   req->transKey = tx_ptr.p->m_transKey;
31153   req->requestInfo = requestInfo;
31154   req->flags = flags;
31155   sendSignal(reference(), GSN_SCHEMA_TRANS_END_REQ, signal,
31156              SchemaTransEndReq::SignalLength, JBB);
31157 }
31158 
31159 void
execSCHEMA_TRANS_BEGIN_CONF(Signal * signal)31160 Dbdict::execSCHEMA_TRANS_BEGIN_CONF(Signal* signal)
31161 {
31162   jamEntry();
31163   const SchemaTransBeginConf* conf =
31164     (const SchemaTransBeginConf*)signal->getDataPtr();
31165 
31166   TxHandlePtr tx_ptr;
31167   findTxHandle(tx_ptr, conf->transId);
31168   ndbrequire(!tx_ptr.isNull());
31169 
31170   // record trans key
31171   tx_ptr.p->m_transKey = conf->transKey;
31172 
31173   execute(signal, tx_ptr.p->m_callback, 0);
31174 }
31175 
31176 void
execSCHEMA_TRANS_BEGIN_REF(Signal * signal)31177 Dbdict::execSCHEMA_TRANS_BEGIN_REF(Signal* signal)
31178 {
31179   jamEntry();
31180   const SchemaTransBeginRef* ref =
31181     (const SchemaTransBeginRef*)signal->getDataPtr();
31182 
31183   TxHandlePtr tx_ptr;
31184   findTxHandle(tx_ptr, ref->transId);
31185   ndbrequire(!tx_ptr.isNull());
31186 
31187   setError(tx_ptr.p->m_error, ref);
31188   ndbrequire(ref->errorCode != 0);
31189   execute(signal, tx_ptr.p->m_callback, ref->errorCode);
31190 }
31191 
31192 void
execSCHEMA_TRANS_END_CONF(Signal * signal)31193 Dbdict::execSCHEMA_TRANS_END_CONF(Signal* signal)
31194 {
31195   jamEntry();
31196   const SchemaTransEndConf* conf =
31197     (const SchemaTransEndConf*)signal->getDataPtr();
31198 
31199   TxHandlePtr tx_ptr;
31200   findTxHandle(tx_ptr, conf->transId);
31201   ndbrequire(!tx_ptr.isNull());
31202 
31203   execute(signal, tx_ptr.p->m_callback, 0);
31204 }
31205 
31206 void
execSCHEMA_TRANS_END_REF(Signal * signal)31207 Dbdict::execSCHEMA_TRANS_END_REF(Signal* signal)
31208 {
31209   jamEntry();
31210   const SchemaTransEndRef* ref =
31211     (const SchemaTransEndRef*)signal->getDataPtr();
31212 
31213   TxHandlePtr tx_ptr;
31214   findTxHandle(tx_ptr, ref->transId);
31215   ndbrequire(!tx_ptr.isNull());
31216 
31217   setError(tx_ptr.p->m_error, ref);
31218   ndbrequire(ref->errorCode != 0);
31219   execute(signal, tx_ptr.p->m_callback, ref->errorCode);
31220 }
31221 
31222 void
execSCHEMA_TRANS_END_REP(Signal * signal)31223 Dbdict::execSCHEMA_TRANS_END_REP(Signal* signal)
31224 {
31225   jamEntry();
31226   const SchemaTransEndRep* rep =
31227     (const SchemaTransEndRep*)signal->getDataPtr();
31228 
31229   TxHandlePtr tx_ptr;
31230   findTxHandle(tx_ptr, rep->transId);
31231   ndbrequire(!tx_ptr.isNull());
31232 
31233   if (rep->errorCode != 0)
31234   {
31235     jam();
31236     setError(tx_ptr.p->m_error, rep);
31237   }
31238   execute(signal, tx_ptr.p->m_callback, rep->errorCode);
31239 }
31240 
31241 // trans client takeover
31242 
31243 /*
31244  * API node failure.  Each trans is taken over by a new TxHandle,
31245  * unless already running in background by api request (unlikely).
31246  * All transes are marked with ApiFail.  API node failure handling
31247  * is complete when last such trans completes.  This is checked
31248  * in finishApiFail.
31249  */
31250 void
handleApiFail(Signal * signal,Uint32 failedApiNode)31251 Dbdict::handleApiFail(Signal* signal,
31252                       Uint32 failedApiNode)
31253 {
31254   D("handleApiFail" << V(failedApiNode));
31255 
31256   Uint32 takeOvers = 0;
31257   SchemaTransPtr trans_ptr;
31258   c_schemaTransList.first(trans_ptr);
31259   while (trans_ptr.i != RNIL) {
31260     jam();
31261     D("check" << *trans_ptr.p);
31262     Uint32 clientRef = trans_ptr.p->m_clientRef;
31263 
31264     if (refToNode(clientRef) == failedApiNode)
31265     {
31266       jam();
31267       D("failed" << hex << V(clientRef));
31268 
31269       ndbrequire(!(trans_ptr.p->m_clientFlags & TransClient::ApiFail));
31270       trans_ptr.p->m_clientFlags |= TransClient::ApiFail;
31271 
31272       if (trans_ptr.p->m_isMaster)
31273       {
31274         jam();
31275         if (trans_ptr.p->m_clientFlags & TransClient::TakeOver)
31276         {
31277           // maybe already running in background
31278           jam();
31279           ndbrequire(trans_ptr.p->m_clientFlags & TransClient::Background);
31280         }
31281         else
31282         {
31283           jam();
31284           takeOverTransClient(signal, trans_ptr);
31285         }
31286 
31287         TxHandlePtr tx_ptr;
31288         bool ok = findTxHandle(tx_ptr, trans_ptr.p->m_takeOverTxKey);
31289         ndbrequire(ok);
31290 
31291         tx_ptr.p->m_clientFlags |= TransClient::ApiFail;
31292         takeOvers++;
31293       }
31294     }
31295 
31296     c_schemaTransList.next(trans_ptr);
31297   }
31298 
31299   D("handleApiFail" << V(takeOvers));
31300 
31301   if (takeOvers == 0) {
31302     jam();
31303     apiFailBlockHandling(signal, failedApiNode);
31304   }
31305 }
31306 
31307 /*
31308  * Take over client trans, either by background request or at API
31309  * node failure.  Continue to the callback routine.
31310  */
31311 void
takeOverTransClient(Signal * signal,SchemaTransPtr trans_ptr)31312 Dbdict::takeOverTransClient(Signal* signal, SchemaTransPtr trans_ptr)
31313 {
31314   D("takeOverTransClient" << *trans_ptr.p);
31315 
31316   TxHandlePtr tx_ptr;
31317   bool ok = seizeTxHandle(tx_ptr);
31318   ndbrequire(ok);
31319 
31320   ndbrequire(!(trans_ptr.p->m_clientFlags & TransClient::TakeOver));
31321   trans_ptr.p->m_clientFlags |= TransClient::TakeOver;
31322   trans_ptr.p->m_takeOverTxKey = tx_ptr.p->tx_key;
31323 
31324   tx_ptr.p->m_transId = tx_ptr.p->tx_key;
31325   tx_ptr.p->m_transKey = trans_ptr.p->trans_key;
31326   // start with SchemaTrans point of view
31327   tx_ptr.p->m_clientState = trans_ptr.p->m_clientState;
31328   tx_ptr.p->m_clientFlags = trans_ptr.p->m_clientFlags;
31329   tx_ptr.p->m_takeOverRef = trans_ptr.p->m_clientRef;
31330   tx_ptr.p->m_takeOverTransId = trans_ptr.p->m_transId;
31331 
31332   runTransClientTakeOver(signal, tx_ptr.p->tx_key, 0);
31333 }
31334 
31335 /*
31336  * Run one step in client takeover.  If not waiting for a signal,
31337  * send end trans abort.  The only commit case is when takeover
31338  * takes place in client state EndReq.  At the end, send an info
31339  * event and check if the trans was from API node failure.
31340  */
31341 void
runTransClientTakeOver(Signal * signal,Uint32 tx_key,Uint32 ret)31342 Dbdict::runTransClientTakeOver(Signal* signal,
31343                                Uint32 tx_key,
31344                                Uint32 ret)
31345 {
31346   TxHandlePtr tx_ptr;
31347   bool ok = findTxHandle(tx_ptr, tx_key);
31348   ndbrequire(ok);
31349   D("runClientTakeOver" << *tx_ptr.p << V(ret));
31350 
31351   if (ret != 0) {
31352     jam();
31353     setError(tx_ptr, ret, __LINE__);
31354   }
31355 
31356   const TransClient::State oldState = tx_ptr.p->m_clientState;
31357   const Uint32 clientFlags = tx_ptr.p->m_clientFlags;
31358   ndbrequire(clientFlags & TransClient::TakeOver);
31359 
31360   TransClient::State newState = oldState;
31361   bool wait_sig = false;
31362   bool at_end = false;
31363 
31364   switch (oldState) {
31365   case TransClient::BeginReq:
31366     jam();
31367     newState = TransClient::BeginReply;
31368     wait_sig = true;
31369     break;
31370   case TransClient::BeginReply:
31371     jam();
31372     newState = TransClient::EndReply;
31373     break;
31374   case TransClient::ParseReq:
31375     jam();
31376     newState = TransClient::ParseReply;
31377     wait_sig = true;
31378     break;
31379   case TransClient::ParseReply:
31380     jam();
31381     newState = TransClient::EndReply;
31382     break;
31383   case TransClient::EndReq:
31384     jam();
31385     newState = TransClient::EndReply;
31386     wait_sig = true;
31387     break;
31388   case TransClient::EndReply:
31389     jam();
31390     newState = TransClient::StateUndef;
31391     at_end = true;
31392     break;
31393   default:
31394     ndbrequire(false);
31395     break;
31396   }
31397 
31398   D("set" << V(oldState) << " -> " << V(newState));
31399   tx_ptr.p->m_clientState = newState;
31400 
31401   if (!at_end) {
31402     jam();
31403     Callback c = {
31404       safe_cast(&Dbdict::runTransClientTakeOver),
31405       tx_ptr.p->tx_key
31406     };
31407     tx_ptr.p->m_callback = c;
31408 
31409     if (!wait_sig) {
31410       jam();
31411       Uint32 flags = 0;
31412       flags |= SchemaTransEndReq::SchemaTransAbort;
31413       endSchemaTrans(signal, tx_ptr, flags);
31414     }
31415     return;
31416   }
31417 
31418   if (!hasError(tx_ptr.p->m_error)) {
31419     jam();
31420     infoEvent("DICT: api:0x%8x trans:0x%8x takeover completed",
31421               tx_ptr.p->m_takeOverRef, tx_ptr.p->m_takeOverTransId);
31422   } else {
31423     jam();
31424     infoEvent("DICT: api:0x%8x trans:0x%8x takeover failed, error:%u line:%u",
31425               tx_ptr.p->m_takeOverRef, tx_ptr.p->m_takeOverTransId,
31426               tx_ptr.p->m_error.errorCode, tx_ptr.p->m_error.errorLine);
31427   }
31428 
31429   // if from API fail, check if finished
31430   if (clientFlags & TransClient::ApiFail) {
31431     jam();
31432     finishApiFail(signal, tx_ptr);
31433   }
31434   releaseTxHandle(tx_ptr);
31435 }
31436 
31437 void
finishApiFail(Signal * signal,TxHandlePtr tx_ptr)31438 Dbdict::finishApiFail(Signal* signal, TxHandlePtr tx_ptr)
31439 {
31440   D("finishApiFail" << *tx_ptr.p);
31441   const Uint32 failedApiNode = refToNode(tx_ptr.p->m_takeOverRef);
31442 
31443   Uint32 takeOvers = 0;
31444   SchemaTransPtr trans_ptr;
31445   c_schemaTransList.first(trans_ptr);
31446   while (trans_ptr.i != RNIL) {
31447     jam();
31448     D("check" << *trans_ptr.p);
31449     const BlockReference clientRef = trans_ptr.p->m_clientRef;
31450 
31451     if (refToNode(clientRef) == failedApiNode) {
31452       jam();
31453       const Uint32 clientFlags = trans_ptr.p->m_clientFlags;
31454       D("failed" << hex << V(clientRef) << dec << V(clientFlags));
31455       ndbrequire(clientFlags & TransClient::ApiFail);
31456       takeOvers++;
31457     }
31458     c_schemaTransList.next(trans_ptr);
31459   }
31460 
31461   D("finishApiFail" << V(takeOvers));
31462 
31463   if (takeOvers == 0) {
31464     jam();
31465     apiFailBlockHandling(signal, failedApiNode);
31466   }
31467 }
31468 
31469 void
apiFailBlockHandling(Signal * signal,Uint32 failedApiNode)31470 Dbdict::apiFailBlockHandling(Signal* signal,
31471                              Uint32 failedApiNode)
31472 {
31473   Callback cb = { safe_cast(&Dbdict::handleApiFailureCallback),
31474                   failedApiNode };
31475   simBlockNodeFailure(signal, failedApiNode, cb);
31476 }
31477 
31478 // find callback for any key
31479 
31480 bool
findCallback(Callback & callback,Uint32 any_key)31481 Dbdict::findCallback(Callback& callback, Uint32 any_key)
31482 {
31483   SchemaOpPtr op_ptr;
31484   SchemaTransPtr trans_ptr;
31485   TxHandlePtr tx_ptr;
31486 
31487   bool ok1 = findSchemaOp(op_ptr, any_key);
31488   bool ok2 = findSchemaTrans(trans_ptr, any_key);
31489   bool ok3 = findTxHandle(tx_ptr, any_key);
31490   ndbrequire(ok1 + ok2 + ok3 <= 1);
31491 
31492   if (ok1) {
31493     callback = op_ptr.p->m_callback;
31494     return true;
31495   }
31496   if (ok2) {
31497     callback = trans_ptr.p->m_callback;
31498     return true;
31499   }
31500   if (ok3) {
31501     callback = tx_ptr.p->m_callback;
31502     return true;
31503   }
31504   callback.m_callbackFunction = 0;
31505   callback.m_callbackData = 0;
31506   return false;
31507 }
31508 
31509 // MODULE: CreateHashMap
31510 
31511 ArrayPool<Hash2FragmentMap> g_hash_map;
31512 
31513 const Dbdict::OpInfo
31514 Dbdict::CreateHashMapRec::g_opInfo = {
31515   { 'C', 'H', 'M', 0 },
31516   ~RT_DBDICT_CREATE_HASH_MAP,
31517   GSN_CREATE_HASH_MAP_REQ,
31518   CreateHashMapReq::SignalLength,
31519   //
31520   &Dbdict::createHashMap_seize,
31521   &Dbdict::createHashMap_release,
31522   //
31523   &Dbdict::createHashMap_parse,
31524   &Dbdict::createHashMap_subOps,
31525   &Dbdict::createHashMap_reply,
31526   //
31527   &Dbdict::createHashMap_prepare,
31528   &Dbdict::createHashMap_commit,
31529   &Dbdict::createHashMap_complete,
31530   //
31531   &Dbdict::createHashMap_abortParse,
31532   &Dbdict::createHashMap_abortPrepare
31533 };
31534 
31535 bool
createHashMap_seize(SchemaOpPtr op_ptr)31536 Dbdict::createHashMap_seize(SchemaOpPtr op_ptr)
31537 {
31538   return seizeOpRec<CreateHashMapRec>(op_ptr);
31539 }
31540 
31541 void
createHashMap_release(SchemaOpPtr op_ptr)31542 Dbdict::createHashMap_release(SchemaOpPtr op_ptr)
31543 {
31544   releaseOpRec<CreateHashMapRec>(op_ptr);
31545 }
31546 
31547 void
execCREATE_HASH_MAP_REQ(Signal * signal)31548 Dbdict::execCREATE_HASH_MAP_REQ(Signal* signal)
31549 {
31550   jamEntry();
31551   if (!assembleFragments(signal)) {
31552     jam();
31553     return;
31554   }
31555   SectionHandle handle(this, signal);
31556 
31557   const CreateHashMapReq req_copy =
31558     *(const CreateHashMapReq*)signal->getDataPtr();
31559   const CreateHashMapReq* req = &req_copy;
31560 
31561   ErrorInfo error;
31562   do {
31563     SchemaOpPtr op_ptr;
31564     CreateHashMapRecPtr createHashMapRecordPtr;
31565     CreateHashMapImplReq* impl_req;
31566 
31567     startClientReq(op_ptr, createHashMapRecordPtr, req, impl_req, error);
31568     if (hasError(error)) {
31569       jam();
31570       break;
31571     }
31572 
31573     impl_req->objectId = RNIL;
31574     impl_req->objectVersion = 0;
31575     impl_req->buckets = req->buckets;
31576     impl_req->fragments = req->fragments;
31577 
31578     handleClientReq(signal, op_ptr, handle);
31579     return;
31580   } while (0);
31581 
31582   releaseSections(handle);
31583 
31584   CreateHashMapRef* ref = (CreateHashMapRef*)signal->getDataPtrSend();
31585 
31586   ref->senderRef = reference();
31587   ref->senderData= req->clientData;
31588   ref->transId = req->transId;
31589   getError(error, ref);
31590 
31591   sendSignal(req->clientRef, GSN_CREATE_HASH_MAP_REF, signal,
31592              CreateHashMapRef::SignalLength, JBB);
31593 }
31594 
31595 // CreateHashMap: PARSE
31596 
31597 Uint32
get_default_fragments(Signal * signal,Uint32 extranodegroups)31598 Dbdict::get_default_fragments(Signal* signal, Uint32 extranodegroups)
31599 {
31600   jam();
31601 
31602   CheckNodeGroups * sd = CAST_PTR(CheckNodeGroups, signal->getDataPtrSend());
31603   sd->extraNodeGroups = extranodegroups;
31604   sd->requestType = CheckNodeGroups::Direct | CheckNodeGroups::GetDefaultFragments;
31605   EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal,
31606 		 CheckNodeGroups::SignalLength);
31607   jamEntry();
31608   return sd->output;
31609 }
31610 
31611 void
createHashMap_parse(Signal * signal,bool master,SchemaOpPtr op_ptr,SectionHandle & handle,ErrorInfo & error)31612 Dbdict::createHashMap_parse(Signal* signal, bool master,
31613                             SchemaOpPtr op_ptr,
31614                             SectionHandle& handle, ErrorInfo& error)
31615 {
31616 
31617   SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
31618   CreateHashMapRecPtr createHashMapRecordPtr;
31619   getOpRec(op_ptr, createHashMapRecordPtr);
31620   CreateHashMapImplReq* impl_req = &createHashMapRecordPtr.p->m_request;
31621 
31622   jam();
31623 
31624   SegmentedSectionPtr objInfoPtr;
31625   DictHashMapInfo::HashMap hm; hm.init();
31626   if (handle.m_cnt)
31627   {
31628     jam();
31629     SimpleProperties::UnpackStatus status;
31630 
31631     handle.getSection(objInfoPtr, CreateHashMapReq::INFO);
31632     SimplePropertiesSectionReader it(objInfoPtr, getSectionSegmentPool());
31633     status = SimpleProperties::unpack(it, &hm,
31634 				      DictHashMapInfo::Mapping,
31635 				      DictHashMapInfo::MappingSize,
31636 				      true, true);
31637 
31638     if (ERROR_INSERTED(6204))
31639     {
31640       jam();
31641       CLEAR_ERROR_INSERT_VALUE;
31642       setError(error, 1, __LINE__);
31643       return;
31644     }
31645 
31646     if (status != SimpleProperties::Eof)
31647     {
31648       jam();
31649       setError(error, CreateTableRef::InvalidFormat, __LINE__);
31650       return;
31651     }
31652   }
31653   else if (!master)
31654   {
31655     jam();
31656     setError(error, CreateTableRef::InvalidFormat, __LINE__);
31657     return;
31658   }
31659   else
31660   {
31661     /**
31662      * Convienienc branch...(only master)
31663      * No info, create "default"
31664      */
31665     jam();
31666     if (impl_req->requestType & CreateHashMapReq::CreateDefault)
31667     {
31668       jam();
31669       impl_req->buckets = c_default_hashmap_size;
31670       impl_req->fragments = 0;
31671     }
31672 
31673     Uint32 buckets = impl_req->buckets;
31674     Uint32 fragments = impl_req->fragments;
31675     if (fragments == 0)
31676     {
31677       jam();
31678 
31679       fragments = get_default_fragments(signal);
31680     }
31681 
31682     if (fragments > MAX_NDB_PARTITIONS)
31683     {
31684       jam();
31685       setError(error, CreateTableRef::TooManyFragments, __LINE__);
31686       return;
31687     }
31688 
31689     BaseString::snprintf(hm.HashMapName, sizeof(hm.HashMapName),
31690                          "DEFAULT-HASHMAP-%u-%u",
31691                          buckets,
31692                          fragments);
31693 
31694     if (buckets == 0 || buckets > Hash2FragmentMap::MAX_MAP)
31695     {
31696       jam();
31697       setError(error, CreateTableRef::InvalidFormat, __LINE__);
31698       return;
31699     }
31700 
31701     hm.HashMapBuckets = buckets;
31702     for (Uint32 i = 0; i<buckets; i++)
31703     {
31704       hm.HashMapValues[i] = (i % fragments);
31705     }
31706 
31707     /**
31708      * pack is stupid...and requires bytes!
31709      * we store shorts...so multiply by 2
31710      */
31711     hm.HashMapBuckets *= sizeof(Uint16);
31712     SimpleProperties::UnpackStatus s;
31713     SimplePropertiesSectionWriter w(* this);
31714     s = SimpleProperties::pack(w,
31715                                &hm,
31716                                DictHashMapInfo::Mapping,
31717                                DictHashMapInfo::MappingSize, true);
31718     ndbrequire(s == SimpleProperties::Eof);
31719     w.getPtr(objInfoPtr);
31720 
31721     handle.m_cnt = 1;
31722     handle.m_ptr[CreateHashMapReq::INFO] = objInfoPtr;
31723   }
31724 
31725   Uint32 len = Uint32(strlen(hm.HashMapName) + 1);
31726   Uint32 hash = LocalRope::hash(hm.HashMapName, len);
31727 
31728   if (ERROR_INSERTED(6205))
31729   {
31730     jam();
31731     CLEAR_ERROR_INSERT_VALUE;
31732     setError(error, 1, __LINE__);
31733     return;
31734   }
31735 
31736   DictObject * objptr = get_object(hm.HashMapName, len, hash);
31737   if(objptr != 0)
31738   {
31739     jam();
31740 
31741     if (! (impl_req->requestType & CreateHashMapReq::CreateIfNotExists))
31742     {
31743       jam();
31744       setError(error, CreateTableRef::TableAlreadyExist, __LINE__);
31745       return;
31746     }
31747 
31748     /**
31749      * verify object found
31750      */
31751 
31752     if (objptr->m_type != DictTabInfo::HashMap)
31753     {
31754       jam();
31755       setError(error, CreateTableRef::TableAlreadyExist, __LINE__);
31756       return;
31757     }
31758 
31759     if (check_write_obj(objptr->m_id,
31760                         trans_ptr.p->m_transId,
31761                         SchemaFile::SF_CREATE, error))
31762     {
31763       jam();
31764       return;
31765     }
31766 
31767     HashMapRecordPtr hm_ptr;
31768     ndbrequire(find_object(hm_ptr, objptr->m_id));
31769 
31770     impl_req->objectId = objptr->m_id;
31771     impl_req->objectVersion = hm_ptr.p->m_object_version;
31772     return;
31773   }
31774   else
31775   {
31776     jam();
31777     /**
31778      * Clear the IfNotExistsFlag
31779      */
31780     impl_req->requestType &= ~Uint32(CreateHashMapReq::CreateIfNotExists);
31781   }
31782 
31783   if (ERROR_INSERTED(6206))
31784   {
31785     jam();
31786     CLEAR_ERROR_INSERT_VALUE;
31787     setError(error, 1, __LINE__);
31788     return;
31789   }
31790 
31791   RopeHandle name;
31792   {
31793     LocalRope tmp(c_rope_pool, name);
31794     if(!tmp.assign(hm.HashMapName, len, hash))
31795     {
31796       jam();
31797       setError(error, CreateTableRef::OutOfStringBuffer, __LINE__);
31798       return;
31799     }
31800   }
31801 
31802   Uint32 objId = RNIL;
31803   Uint32 objVersion = RNIL;
31804   DictObjectPtr obj_ptr; obj_ptr.setNull();
31805   HashMapRecordPtr hm_ptr; hm_ptr.setNull();
31806   Ptr<Hash2FragmentMap> map_ptr; map_ptr.setNull();
31807 
31808   if (master)
31809   {
31810     jam();
31811 
31812     if (ERROR_INSERTED(6207))
31813     {
31814       jam();
31815       CLEAR_ERROR_INSERT_VALUE;
31816       setError(error, 1, __LINE__);
31817       goto error;
31818     }
31819 
31820     objId = impl_req->objectId = getFreeObjId();
31821     if (objId == RNIL)
31822     {
31823       jam();
31824       setError(error, CreateTableRef::NoMoreTableRecords, __LINE__);
31825       goto error;
31826     }
31827 
31828     Uint32 version = getTableEntry(impl_req->objectId)->m_tableVersion;
31829     impl_req->objectVersion = create_obj_inc_schema_version(version);
31830   }
31831   else if (op_ptr.p->m_restart)
31832   {
31833     jam();
31834     impl_req->objectId = c_restartRecord.activeTable;
31835     impl_req->objectVersion=c_restartRecord.m_entry.m_tableVersion;
31836   }
31837 
31838   objId = impl_req->objectId;
31839   objVersion = impl_req->objectVersion;
31840 
31841   if (ERROR_INSERTED(6208))
31842   {
31843     jam();
31844     CLEAR_ERROR_INSERT_VALUE;
31845     setError(error, 1, __LINE__);
31846     goto error;
31847   }
31848 
31849   if(!c_obj_pool.seize(obj_ptr))
31850   {
31851     jam();
31852     setError(error, CreateTableRef::NoMoreTableRecords, __LINE__);
31853     goto error;
31854   }
31855 
31856   new (obj_ptr.p) DictObject;
31857   obj_ptr.p->m_id = objId;
31858   obj_ptr.p->m_type = DictTabInfo::HashMap;
31859   obj_ptr.p->m_ref_count = 0;
31860   obj_ptr.p->m_name = name;
31861   c_obj_name_hash.add(obj_ptr);
31862   c_obj_id_hash.add(obj_ptr);
31863 
31864   if (ERROR_INSERTED(6209))
31865   {
31866     jam();
31867     CLEAR_ERROR_INSERT_VALUE;
31868     setError(error, 1, __LINE__);
31869     goto error;
31870   }
31871 
31872   if (!g_hash_map.seize(map_ptr))
31873   {
31874     jam();
31875     setError(error, CreateTableRef::NoMoreHashmapRecords, __LINE__);
31876     goto error;
31877   }
31878 
31879   if (ERROR_INSERTED(6210))
31880   {
31881     jam();
31882     CLEAR_ERROR_INSERT_VALUE;
31883     setError(error, 1, __LINE__);
31884     goto error;
31885   }
31886 
31887   if(!c_hash_map_pool.seize(hm_ptr))
31888   {
31889     jam();
31890     setError(error, CreateTableRef::NoMoreHashmapRecords, __LINE__);
31891     goto error;
31892   }
31893 
31894   new (hm_ptr.p) HashMapRecord();
31895 
31896   hm_ptr.p->m_object_id = objId;
31897   hm_ptr.p->m_object_version = objVersion;
31898   hm_ptr.p->m_name = name;
31899   hm_ptr.p->m_map_ptr_i = map_ptr.i;
31900   link_object(obj_ptr, hm_ptr);
31901 
31902   /**
31903    * pack is stupid...and requires bytes!
31904    * we store shorts...so divide by 2
31905    */
31906   hm.HashMapBuckets /= sizeof(Uint16);
31907 
31908   map_ptr.p->m_cnt = hm.HashMapBuckets;
31909   map_ptr.p->m_object_id = objId;
31910   {
31911     Uint32 tmp = 0;
31912     for (Uint32 i = 0; i<hm.HashMapBuckets; i++)
31913     {
31914       map_ptr.p->m_map[i] = hm.HashMapValues[i];
31915       if (hm.HashMapValues[i] > tmp)
31916         tmp = hm.HashMapValues[i];
31917     }
31918     map_ptr.p->m_fragments = tmp + 1;
31919   }
31920   if (map_ptr.p->m_fragments > MAX_NDB_PARTITIONS)
31921   {
31922     jam();
31923     setError(error, CreateTableRef::TooManyFragments, __LINE__);
31924     goto error;
31925   }
31926 
31927   if (ERROR_INSERTED(6211))
31928   {
31929     jam();
31930     CLEAR_ERROR_INSERT_VALUE;
31931     setError(error, 1, __LINE__);
31932     goto error;
31933   }
31934 
31935   {
31936     SchemaFile::TableEntry te; te.init();
31937     te.m_tableState = SchemaFile::SF_CREATE;
31938     te.m_tableVersion = objVersion;
31939     te.m_tableType = obj_ptr.p->m_type;
31940     te.m_info_words = objInfoPtr.sz;
31941     te.m_gcp = 0;
31942     te.m_transId = trans_ptr.p->m_transId;
31943 
31944     Uint32 err = trans_log_schema_op(op_ptr, objId, &te);
31945     ndbrequire(err == 0);
31946   }
31947 
31948   saveOpSection(op_ptr, objInfoPtr, 0);
31949   handle.m_ptr[CreateHashMapReq::INFO] = objInfoPtr;
31950   handle.m_cnt = 1;
31951 
31952 #if defined VM_TRACE || defined ERROR_INSERT
31953   ndbout_c("Dbdict: %u: create name=%s,id=%u,obj_ptr_i=%d",__LINE__,
31954            hm.HashMapName, objId, hm_ptr.p->m_obj_ptr_i);
31955 #endif
31956 
31957   return;
31958 
31959 error:
31960   ndbrequire(hasError(error));
31961 
31962   if (!hm_ptr.isNull())
31963   {
31964     jam();
31965     c_hash_map_pool.release(hm_ptr);
31966   }
31967 
31968   if (!map_ptr.isNull())
31969   {
31970     jam();
31971     g_hash_map.release(map_ptr);
31972   }
31973 
31974   if (!obj_ptr.isNull())
31975   {
31976     jam();
31977     release_object(obj_ptr.i);
31978   }
31979   else
31980   {
31981     jam();
31982     LocalRope tmp(c_rope_pool, name);
31983     tmp.erase();
31984   }
31985 }
31986 
31987 void
createHashMap_abortParse(Signal * signal,SchemaOpPtr op_ptr)31988 Dbdict::createHashMap_abortParse(Signal* signal, SchemaOpPtr op_ptr)
31989 {
31990   D("createHashMap_abortParse" << *op_ptr.p);
31991 
31992   CreateHashMapRecPtr createHashMapRecordPtr;
31993   getOpRec(op_ptr, createHashMapRecordPtr);
31994   CreateHashMapImplReq* impl_req = &createHashMapRecordPtr.p->m_request;
31995 
31996   if (impl_req->requestType & CreateHashMapReq::CreateIfNotExists)
31997   {
31998     jam();
31999     ndbrequire(op_ptr.p->m_orig_entry_id == RNIL);
32000   }
32001 
32002   if (op_ptr.p->m_orig_entry_id != RNIL)
32003   {
32004     jam();
32005 
32006     HashMapRecordPtr hm_ptr;
32007     ndbrequire(find_object(hm_ptr, impl_req->objectId));
32008 
32009     release_object(hm_ptr.p->m_obj_ptr_i);
32010     g_hash_map.release(hm_ptr.p->m_map_ptr_i);
32011     c_hash_map_pool.release(hm_ptr);
32012   }
32013 
32014   // wl3600_todo probably nothing..
32015 
32016   sendTransConf(signal, op_ptr);
32017 }
32018 
32019 bool
createHashMap_subOps(Signal * signal,SchemaOpPtr op_ptr)32020 Dbdict::createHashMap_subOps(Signal* signal, SchemaOpPtr op_ptr)
32021 {
32022   jam();
32023   return false;
32024 }
32025 
32026 void
createHashMap_reply(Signal * signal,SchemaOpPtr op_ptr,ErrorInfo error)32027 Dbdict::createHashMap_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
32028 {
32029   jam();
32030   D("createHashMap_reply");
32031 
32032   SchemaTransPtr& trans_ptr = op_ptr.p->m_trans_ptr;
32033   CreateHashMapRecPtr createHashMapRecordPtr;
32034   getOpRec(op_ptr, createHashMapRecordPtr);
32035   const CreateHashMapImplReq* impl_req = &createHashMapRecordPtr.p->m_request;
32036 
32037   if (!hasError(error)) {
32038     jam();
32039     CreateHashMapConf* conf = (CreateHashMapConf*)signal->getDataPtrSend();
32040     conf->senderRef = reference();
32041     conf->senderData = op_ptr.p->m_clientData;
32042     conf->transId = trans_ptr.p->m_transId;
32043     conf->objectId = impl_req->objectId;
32044     conf->objectVersion = impl_req->objectVersion;
32045 
32046     D(V(conf->objectId) << V(conf->objectVersion));
32047 
32048     Uint32 clientRef = op_ptr.p->m_clientRef;
32049     sendSignal(clientRef, GSN_CREATE_HASH_MAP_CONF, signal,
32050                CreateHashMapConf::SignalLength, JBB);
32051   } else {
32052     jam();
32053     CreateHashMapRef* ref = (CreateHashMapRef*)signal->getDataPtrSend();
32054     ref->senderRef = reference();
32055     ref->senderData = op_ptr.p->m_clientData;
32056     ref->transId = trans_ptr.p->m_transId;
32057     getError(error, ref);
32058 
32059     Uint32 clientRef = op_ptr.p->m_clientRef;
32060     sendSignal(clientRef, GSN_CREATE_HASH_MAP_REF, signal,
32061                CreateHashMapRef::SignalLength, JBB);
32062   }
32063 }
32064 
32065 // CreateHashMap: PREPARE
32066 
32067 void
createHashMap_prepare(Signal * signal,SchemaOpPtr op_ptr)32068 Dbdict::createHashMap_prepare(Signal* signal, SchemaOpPtr op_ptr)
32069 {
32070   jam();
32071   D("createHashMap_prepare");
32072 
32073   CreateHashMapRecPtr createHashMapRecordPtr;
32074   getOpRec(op_ptr, createHashMapRecordPtr);
32075   CreateHashMapImplReq* impl_req = &createHashMapRecordPtr.p->m_request;
32076 
32077   if (impl_req->requestType & CreateHashMapReq::CreateIfNotExists)
32078   {
32079     jam();
32080     sendTransConf(signal, op_ptr);
32081     return;
32082   }
32083 
32084   Callback cb;
32085   cb.m_callbackData = op_ptr.p->op_key;
32086   cb.m_callbackFunction = safe_cast(&Dbdict::createHashMap_writeObjConf);
32087 
32088   const OpSection& tabInfoSec = getOpSection(op_ptr, 0);
32089   writeTableFile(signal, op_ptr, impl_req->objectId, tabInfoSec, &cb);
32090 }
32091 
32092 void
createHashMap_writeObjConf(Signal * signal,Uint32 op_key,Uint32 ret)32093 Dbdict::createHashMap_writeObjConf(Signal* signal, Uint32 op_key, Uint32 ret)
32094 {
32095   jam();
32096   SchemaOpPtr op_ptr;
32097   CreateHashMapRecPtr createHashMapRecordPtr;
32098   findSchemaOp(op_ptr, createHashMapRecordPtr, op_key);
32099 
32100   ndbrequire(!op_ptr.isNull());
32101 
32102   sendTransConf(signal, op_ptr);
32103 }
32104 
32105 // CreateHashMap: COMMIT
32106 
32107 void
createHashMap_commit(Signal * signal,SchemaOpPtr op_ptr)32108 Dbdict::createHashMap_commit(Signal* signal, SchemaOpPtr op_ptr)
32109 {
32110   jam();
32111   D("createHashMap_commit");
32112 
32113   CreateHashMapRecPtr createHashMapRecordPtr;
32114   getOpRec(op_ptr, createHashMapRecordPtr);
32115 
32116   sendTransConf(signal, op_ptr);
32117 }
32118 
32119 // CreateHashMap: COMPLETE
32120 
32121 void
createHashMap_complete(Signal * signal,SchemaOpPtr op_ptr)32122 Dbdict::createHashMap_complete(Signal* signal, SchemaOpPtr op_ptr)
32123 {
32124   jam();
32125   sendTransConf(signal, op_ptr);
32126 }
32127 
32128 // CreateHashMap: ABORT
32129 
32130 void
createHashMap_abortPrepare(Signal * signal,SchemaOpPtr op_ptr)32131 Dbdict::createHashMap_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
32132 {
32133   D("createHashMap_abortPrepare" << *op_ptr.p);
32134   // wl3600_todo
32135   sendTransConf(signal, op_ptr);
32136 }
32137 
32138 void
packHashMapIntoPages(SimpleProperties::Writer & w,HashMapRecordPtr hm_ptr)32139 Dbdict::packHashMapIntoPages(SimpleProperties::Writer & w,
32140                              HashMapRecordPtr hm_ptr)
32141 {
32142   DictHashMapInfo::HashMap hm; hm.init();
32143 
32144   Ptr<Hash2FragmentMap> map_ptr;
32145   g_hash_map.getPtr(map_ptr, hm_ptr.p->m_map_ptr_i);
32146 
32147   ConstRope r(c_rope_pool, hm_ptr.p->m_name);
32148   r.copy(hm.HashMapName);
32149   hm.HashMapBuckets = map_ptr.p->m_cnt;
32150   hm.HashMapObjectId = hm_ptr.p->m_object_id;
32151   hm.HashMapVersion = hm_ptr.p->m_object_version;
32152 
32153   for (Uint32 i = 0; i<hm.HashMapBuckets; i++)
32154   {
32155     hm.HashMapValues[i] = map_ptr.p->m_map[i];
32156   }
32157 
32158   /**
32159    * pack is stupid...and requires bytes!
32160    * we store shorts...so multiply by 2
32161    */
32162   hm.HashMapBuckets *= sizeof(Uint16);
32163   SimpleProperties::UnpackStatus s;
32164   s = SimpleProperties::pack(w,
32165 			     &hm,
32166 			     DictHashMapInfo::Mapping,
32167 			     DictHashMapInfo::MappingSize, true);
32168 
32169   ndbrequire(s == SimpleProperties::Eof);
32170 }
32171 
32172 // CreateHashMap: END
32173 
32174 
32175 // MODULE: debug
32176 
32177 // ErrorInfo
32178 
32179 NdbOut&
operator <<(NdbOut & out,const Dbdict::ErrorInfo & a)32180 operator<<(NdbOut& out, const Dbdict::ErrorInfo& a)
32181 {
32182   a.print(out);
32183   return out;
32184 }
32185 
32186 void
print(NdbOut & out) const32187 Dbdict::ErrorInfo::print(NdbOut& out) const
32188 {
32189   out << "[";
32190   out << " code: " << errorCode;
32191   out << " line: " << errorLine;
32192   out << " node: " << errorNodeId;
32193   out << " count: " << errorCount;
32194   out << " status: " << errorStatus;
32195   out << " key: " << errorKey;
32196   out << " name: '" << errorObjectName << "'";
32197   out << " ]";
32198 }
32199 
32200 #ifdef VM_TRACE
32201 
32202 // DictObject
32203 
32204 NdbOut&
operator <<(NdbOut & out,const Dbdict::DictObject & a)32205 operator<<(NdbOut& out, const Dbdict::DictObject& a)
32206 {
32207   a.print(out);
32208   return out;
32209 }
32210 
32211 void
print(NdbOut & out) const32212 Dbdict::DictObject::print(NdbOut& out) const
32213 {
32214   Dbdict* dict = (Dbdict*)globalData.getBlock(DBDICT);
32215   out << " (DictObject";
32216   out << dec << V(m_id);
32217   out << dec << V(m_type);
32218   out << " name:" << dict->copyRope<PATH_MAX>(m_name);
32219   out << dec << V(m_ref_count);
32220   out << dec << V(m_trans_key);
32221   out << dec << V(m_op_ref_count);
32222   out << ")";
32223 }
32224 
32225 
32226 // SchemaOp
32227 
32228 NdbOut&
operator <<(NdbOut & out,const Dbdict::SchemaOp & a)32229 operator<<(NdbOut& out, const Dbdict::SchemaOp& a)
32230 {
32231   a.print(out);
32232   return out;
32233 }
32234 
32235 void
print(NdbOut & out) const32236 Dbdict::SchemaOp::print(NdbOut& out) const
32237 {
32238   //Dbdict* dict = (Dbdict*)globalData.getBlock(DBDICT);
32239   const Dbdict::OpInfo& info = m_oprec_ptr.p->m_opInfo;
32240   out << " (SchemaOp";
32241   out << " " << info.m_opType;
32242   out << dec << V(op_key);
32243   if (m_error.errorCode != 0)
32244     out << m_error;
32245   if (m_sections != 0)
32246     out << dec << V(m_sections);
32247   if (m_base_op_ptr_i == RNIL)
32248     out << "-> RNIL";
32249   else
32250   {
32251     out << "-> " << m_base_op_ptr_i;
32252   }
32253 
32254   out << ")";
32255 }
32256 
32257 
32258 
32259 // SchemaTrans
32260 
32261 NdbOut&
operator <<(NdbOut & out,const Dbdict::SchemaTrans & a)32262 operator<<(NdbOut& out, const Dbdict::SchemaTrans& a)
32263 {
32264   a.print(out);
32265   return out;
32266 }
32267 
32268 void
print(NdbOut & out) const32269 Dbdict::SchemaTrans::print(NdbOut& out) const
32270 {
32271   out << " (SchemaTrans";
32272   out << dec << V(m_state);
32273   out << dec << V(trans_key);
32274   out << dec << V(m_isMaster);
32275   out << hex << V(m_clientRef);
32276   out << hex << V(m_transId);
32277   out << dec << V(m_clientState);
32278   out << hex << V(m_clientFlags);
32279   out << ")";
32280 }
32281 
32282 // TxHandle
32283 
32284 NdbOut&
operator <<(NdbOut & out,const Dbdict::TxHandle & a)32285 operator<<(NdbOut& out, const Dbdict::TxHandle& a)
32286 {
32287   a.print(out);
32288   return out;
32289 }
32290 
32291 void
print(NdbOut & out) const32292 Dbdict::TxHandle::print(NdbOut& out) const
32293 {
32294   out << " (TxHandle";
32295   out << dec << V(tx_key);
32296   out << hex << V(m_transId);
32297   out << dec << V(m_transKey);
32298   out << dec << V(m_clientState);
32299   out << hex << V(m_clientFlags);
32300   out << hex << V(m_takeOverRef);
32301   out << hex << V(m_takeOverTransId);
32302   out << ")";
32303 }
32304 
32305 // check consistency when no schema trans is active
32306 
32307 #undef SZ
32308 #define SZ PATH_MAX
32309 
32310 void
check_consistency()32311 Dbdict::check_consistency()
32312 {
32313   D("check_consistency");
32314 
32315 #if 0
32316   // schema file entries // mis-named "tables"
32317   TableRecordPtr tablePtr;
32318   for (tablePtr.i = 0;
32319       tablePtr.i < c_noOfMetaTables;
32320       tablePtr.i++) {
32321     if (check_read_obj(tablePtr.i,
32322 
32323     c_tableRecordPool_.getPtr(tablePtr);
32324 
32325     switch (tablePtr.p->tabState) {
32326     case TableRecord::NOT_DEFINED:
32327       continue;
32328     default:
32329       break;
32330     }
32331     check_consistency_entry(tablePtr);
32332   }
32333 #endif
32334 
32335   // triggers // should be in schema file
32336   TriggerRecordPtr triggerPtr;
32337   for (Uint32 id = 0;
32338       id < c_triggerRecordPool_.getSize();
32339       id++) {
32340     bool ok = find_object(triggerPtr, id);
32341     if (!ok) continue;
32342     switch (triggerPtr.p->triggerState) {
32343     case TriggerRecord::TS_NOT_DEFINED:
32344       continue;
32345     default:
32346       break;
32347     }
32348     check_consistency_trigger(triggerPtr);
32349   }
32350 }
32351 
32352 void
check_consistency_entry(TableRecordPtr tablePtr)32353 Dbdict::check_consistency_entry(TableRecordPtr tablePtr)
32354 {
32355   switch (tablePtr.p->tableType) {
32356   case DictTabInfo::SystemTable:
32357     jam();
32358     check_consistency_table(tablePtr);
32359     break;
32360   case DictTabInfo::UserTable:
32361     jam();
32362     check_consistency_table(tablePtr);
32363     break;
32364   case DictTabInfo::UniqueHashIndex:
32365     jam();
32366     check_consistency_index(tablePtr);
32367     break;
32368   case DictTabInfo::OrderedIndex:
32369     jam();
32370     check_consistency_index(tablePtr);
32371     break;
32372   case DictTabInfo::Tablespace:
32373   case DictTabInfo::LogfileGroup:
32374   case DictTabInfo::Datafile:
32375   case DictTabInfo::Undofile:
32376     jam();
32377     break;
32378   default:
32379     ndbrequire(false);
32380     break;
32381   }
32382 }
32383 
32384 void
check_consistency_table(TableRecordPtr tablePtr)32385 Dbdict::check_consistency_table(TableRecordPtr tablePtr)
32386 {
32387   D("table " << copyRope<SZ>(tablePtr.p->tableName));
32388 
32389   switch (tablePtr.p->tableType) {
32390   case DictTabInfo::SystemTable: // should just be "Table"
32391     jam();
32392     break;
32393   case DictTabInfo::UserTable: // should just be "Table"
32394     jam();
32395     break;
32396   default:
32397     ndbrequire(false);
32398     break;
32399   }
32400 
32401   DictObjectPtr obj_ptr;
32402   obj_ptr.i = tablePtr.p->m_obj_ptr_i;
32403   ndbrequire(obj_ptr.i != RNIL);
32404   c_obj_pool.getPtr(obj_ptr);
32405   check_consistency_object(obj_ptr);
32406 
32407   ndbrequire(obj_ptr.p->m_id == tablePtr.p->tableId);
32408   ndbrequire(!strcmp(
32409         copyRope<SZ>(obj_ptr.p->m_name),
32410         copyRope<SZ>(tablePtr.p->tableName)));
32411 }
32412 
32413 void
check_consistency_index(TableRecordPtr indexPtr)32414 Dbdict::check_consistency_index(TableRecordPtr indexPtr)
32415 {
32416   D("index " << copyRope<SZ>(indexPtr.p->tableName));
32417   ndbrequire(indexPtr.p->tableId == indexPtr.i);
32418 
32419   switch (indexPtr.p->indexState) { // these states are non-sense
32420   case TableRecord::IS_ONLINE:
32421     jam();
32422     break;
32423   default:
32424     ndbrequire(false);
32425     break;
32426   }
32427 
32428   TableRecordPtr tablePtr;
32429   bool ok = find_object(tablePtr, indexPtr.p->primaryTableId);
32430   ndbrequire(ok);
32431   check_consistency_table(tablePtr);
32432 
32433   bool is_unique_index = false;
32434   switch (indexPtr.p->tableType) {
32435   case DictTabInfo::UniqueHashIndex:
32436     jam();
32437     is_unique_index = true;
32438     break;
32439   case DictTabInfo::OrderedIndex:
32440     jam();
32441     break;
32442   default:
32443     ndbrequire(false);
32444     break;
32445   }
32446 
32447   TriggerRecordPtr triggerPtr;
32448   ok = find_object(triggerPtr, indexPtr.p->triggerId);
32449   ndbrequire(ok);
32450   ndbrequire(triggerPtr.p->tableId == tablePtr.p->tableId);
32451   ndbrequire(triggerPtr.p->indexId == indexPtr.p->tableId);
32452 
32453   check_consistency_trigger(triggerPtr);
32454 
32455   TriggerInfo ti;
32456   TriggerInfo::unpackTriggerInfo(triggerPtr.p->triggerInfo, ti);
32457   ndbrequire(ti.triggerEvent == TriggerEvent::TE_CUSTOM);
32458 
32459   DictObjectPtr obj_ptr;
32460   obj_ptr.i = triggerPtr.p->m_obj_ptr_i;
32461   ndbrequire(obj_ptr.i != RNIL);
32462   c_obj_pool.getPtr(obj_ptr);
32463   check_consistency_object(obj_ptr);
32464 
32465   ndbrequire(obj_ptr.p->m_id == triggerPtr.p->triggerId);
32466   ndbrequire(!strcmp(copyRope<SZ>(obj_ptr.p->m_name),
32467 		     copyRope<SZ>(triggerPtr.p->triggerName)));
32468 }
32469 
32470 void
check_consistency_trigger(TriggerRecordPtr triggerPtr)32471 Dbdict::check_consistency_trigger(TriggerRecordPtr triggerPtr)
32472 {
32473   if (! (triggerPtr.p->triggerState == TriggerRecord::TS_FAKE_UPGRADE))
32474   {
32475     ndbrequire(triggerPtr.p->triggerState == TriggerRecord::TS_ONLINE);
32476   }
32477 
32478   TableRecordPtr tablePtr;
32479   bool ok = find_object(tablePtr, triggerPtr.p->tableId);
32480   ndbrequire(ok);
32481   check_consistency_table(tablePtr);
32482 
32483   if (triggerPtr.p->indexId != RNIL)
32484   {
32485     jam();
32486     TriggerInfo ti;
32487     TriggerInfo::unpackTriggerInfo(triggerPtr.p->triggerInfo, ti);
32488     ndbrequire(check_read_obj(triggerPtr.p->indexId) == 0);
32489     if (ti.triggerType == TriggerType::FK_PARENT ||
32490         ti.triggerType == TriggerType::FK_CHILD)
32491     {
32492       jam();
32493       Ptr<ForeignKeyRec> fk_ptr;
32494       ndbrequire(find_object(fk_ptr, triggerPtr.p->indexId));
32495     }
32496     else
32497     {
32498       jam();
32499       TableRecordPtr indexPtr;
32500       bool ok = find_object(indexPtr, triggerPtr.p->indexId);
32501       ndbrequire(ok);
32502       ndbrequire(indexPtr.p->indexState == TableRecord::IS_ONLINE);
32503       switch (ti.triggerEvent) {
32504       case TriggerEvent::TE_CUSTOM:
32505         if (! (triggerPtr.p->triggerState == TriggerRecord::TS_FAKE_UPGRADE))
32506         {
32507           ndbrequire(triggerPtr.p->triggerId == indexPtr.p->triggerId);
32508         }
32509         break;
32510       default:
32511         ndbrequire(false);
32512         break;
32513       }
32514     }
32515   }
32516   else
32517   {
32518     TriggerInfo ti;
32519     TriggerInfo::unpackTriggerInfo(triggerPtr.p->triggerInfo, ti);
32520     ndbrequire(ti.triggerType == TriggerType::REORG_TRIGGER);
32521   }
32522 }
32523 
32524 void
check_consistency_object(DictObjectPtr obj_ptr)32525 Dbdict::check_consistency_object(DictObjectPtr obj_ptr)
32526 {
32527   ndbrequire(obj_ptr.p->m_trans_key == 0);
32528   ndbrequire(obj_ptr.p->m_op_ref_count == 0);
32529 }
32530 
32531 #endif
32532 
32533 void
send_event(Signal * signal,SchemaTransPtr & trans_ptr,Uint32 ev,Uint32 id,Uint32 version,Uint32 type)32534 Dbdict::send_event(Signal* signal,
32535                    SchemaTransPtr& trans_ptr,
32536                    Uint32 ev,
32537                    Uint32 id,
32538                    Uint32 version,
32539                    Uint32 type)
32540 {
32541   if (!trans_ptr.p->m_isMaster)
32542   {
32543     return;
32544   }
32545 
32546   switch(ev){
32547   case NDB_LE_CreateSchemaObject:
32548   case NDB_LE_AlterSchemaObject:
32549   case NDB_LE_DropSchemaObject:
32550     break;
32551   default:
32552     ndbassert(false);
32553     return;
32554   }
32555   signal->theData[0] = ev;
32556   signal->theData[1] = id;
32557   signal->theData[2] = version;
32558   signal->theData[3] = type;
32559   signal->theData[4] = refToNode(trans_ptr.p->m_clientRef);
32560   sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 5, JBB);
32561 }
32562 
32563 void
startNextGetTabInfoReq(Signal * signal)32564 Dbdict::startNextGetTabInfoReq(Signal* signal)
32565 {
32566   jam();
32567 
32568   /* Retrieve record should be in busy state to block
32569    * queue-jumpers.  We can clear it now as we will
32570    * execute direct from the head of the queue(s)
32571    */
32572   ndbrequire(c_retrieveRecord.busyState);
32573   ndbrequire(!c_gettabinforeq_q.isEmpty());
32574 
32575   /* Directly start next queued request
32576    * Prefer internalQueue, but give externalQueue entries
32577    * a proportional share to avoid starvation.
32578    */
32579   ndbrequire(c_gettabinforeq_q.deqReq(signal));
32580 
32581   signal->header.theLength = GetTabInfoReq::SignalLength;
32582 
32583   c_retrieveRecord.busyState = false;
32584 
32585   /**
32586    * Todo : Queue + jam signal id to indicate which req
32587    * we are starting in trace file
32588    */
32589   doGET_TABINFOREQ(signal);
32590 
32591   if (!c_retrieveRecord.busyState)
32592   {
32593     jam();
32594     /* That GET_TABINFOREQ is done with no
32595      * blocking work.
32596      * Any more on the queue?
32597      */
32598     if (!c_gettabinforeq_q.isEmpty())
32599     {
32600       jam();
32601       /* We will trigger starting the next
32602        * entry.
32603        */
32604       /* TODO : Option to do immediate DIRECT
32605        * exec of next req up to limit of n
32606        */
32607 
32608       /* Stop queue-jumpers */
32609       c_retrieveRecord.busyState = true;
32610 
32611       signal->theData[0] = ZNEXT_GET_TAB_REQ;
32612       sendSignal(reference(), GSN_CONTINUEB, signal,
32613                  1, JBB);
32614     }
32615   }
32616 }
32617