1 /* Copyright (c) 2003-2008 MySQL AB, 2009 Sun Microsystems, Inc.
2    Use is subject to license terms
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA */
16 
17 #include <ndb_global.h>
18 #include <my_sys.h>
19 
20 #define DBDICT_C
21 #include "Dbdict.hpp"
22 #include "diskpage.hpp"
23 
24 #include <ndb_limits.h>
25 #include <NdbOut.hpp>
26 #include <Properties.hpp>
27 #include <Configuration.hpp>
28 #include <SectionReader.hpp>
29 #include <SimpleProperties.hpp>
30 #include <AttributeHeader.hpp>
31 #include <KeyDescriptor.hpp>
32 #include <signaldata/DictSchemaInfo.hpp>
33 #include <signaldata/DictTabInfo.hpp>
34 #include <signaldata/DropTabFile.hpp>
35 
36 #include <signaldata/EventReport.hpp>
37 #include <signaldata/FsCloseReq.hpp>
38 #include <signaldata/FsConf.hpp>
39 #include <signaldata/FsOpenReq.hpp>
40 #include <signaldata/FsReadWriteReq.hpp>
41 #include <signaldata/FsRef.hpp>
42 #include <signaldata/GetTabInfo.hpp>
43 #include <signaldata/GetTableId.hpp>
44 #include <signaldata/HotSpareRep.hpp>
45 #include <signaldata/NFCompleteRep.hpp>
46 #include <signaldata/NodeFailRep.hpp>
47 #include <signaldata/ReadNodesConf.hpp>
48 #include <signaldata/RelTabMem.hpp>
49 #include <signaldata/WaitGCP.hpp>
50 #include <signaldata/ListTables.hpp>
51 
52 #include <signaldata/CreateTrig.hpp>
53 #include <signaldata/AlterTrig.hpp>
54 #include <signaldata/DropTrig.hpp>
55 #include <signaldata/CreateIndx.hpp>
56 #include <signaldata/DropIndx.hpp>
57 #include <signaldata/BuildIndx.hpp>
58 
59 #include <signaldata/DropFilegroup.hpp>
60 #include <signaldata/CreateFilegroup.hpp>
61 #include <signaldata/CreateFilegroupImpl.hpp>
62 
63 #include <signaldata/CreateEvnt.hpp>
64 #include <signaldata/UtilPrepare.hpp>
65 #include <signaldata/UtilExecute.hpp>
66 #include <signaldata/UtilRelease.hpp>
67 #include <signaldata/SumaImpl.hpp>
68 
69 #include <signaldata/LqhFrag.hpp>
70 
71 #include <signaldata/DiAddTab.hpp>
72 #include <signaldata/DihStartTab.hpp>
73 
74 #include <signaldata/DropTable.hpp>
75 #include <signaldata/DropTab.hpp>
76 #include <signaldata/PrepDropTab.hpp>
77 
78 #include <signaldata/CreateTable.hpp>
79 #include <signaldata/AlterTable.hpp>
80 #include <signaldata/AlterTab.hpp>
81 #include <signaldata/CreateFragmentation.hpp>
82 #include <signaldata/CreateTab.hpp>
83 #include <NdbSleep.h>
84 #include <signaldata/ApiBroadcast.hpp>
85 
86 #include <signaldata/DropObj.hpp>
87 #include <signaldata/CreateObj.hpp>
88 #include <SLList.hpp>
89 
90 #include <EventLogger.hpp>
91 extern EventLogger g_eventLogger;
92 
93 #define ZNOT_FOUND 626
94 #define ZALREADYEXIST 630
95 
96 //#define EVENT_PH2_DEBUG
97 //#define EVENT_PH3_DEBUG
98 //#define EVENT_DEBUG
99 
100 static const char EVENT_SYSTEM_TABLE_NAME[] = "sys/def/NDB$EVENTS_0";
101 
102 #define EVENT_TRACE \
103 //  ndbout_c("Event debug trace: File: %s Line: %u", __FILE__, __LINE__)
104 
105 #define DIV(x,y) (((x)+(y)-1)/(y))
106 #define WORDS2PAGES(x) DIV(x, (ZSIZE_OF_PAGES_IN_WORDS - ZPAGE_HEADER_SIZE))
107 #include <ndb_version.h>
108 
109 static
110 struct {
111   Uint32 m_gsn_user_req;
112   Uint32 m_gsn_req;
113   Uint32 m_gsn_ref;
114   Uint32 m_gsn_conf;
115   void (Dbdict::* m_trans_commit_start)(Signal*, Dbdict::SchemaTransaction*);
116   void (Dbdict::* m_trans_commit_complete)(Signal*,Dbdict::SchemaTransaction*);
117   void (Dbdict::* m_trans_abort_start)(Signal*, Dbdict::SchemaTransaction*);
118   void (Dbdict::* m_trans_abort_complete)(Signal*, Dbdict::SchemaTransaction*);
119 
120   void (Dbdict::* m_prepare_start)(Signal*, Dbdict::SchemaOp*);
121   void (Dbdict::* m_prepare_complete)(Signal*, Dbdict::SchemaOp*);
122   void (Dbdict::* m_commit)(Signal*, Dbdict::SchemaOp*);
123   void (Dbdict::* m_commit_start)(Signal*, Dbdict::SchemaOp*);
124   void (Dbdict::* m_commit_complete)(Signal*, Dbdict::SchemaOp*);
125   void (Dbdict::* m_abort)(Signal*, Dbdict::SchemaOp*);
126   void (Dbdict::* m_abort_start)(Signal*, Dbdict::SchemaOp*);
127   void (Dbdict::* m_abort_complete)(Signal*, Dbdict::SchemaOp*);
128 
129 } f_dict_op[] = {
130   /**
131    * Create filegroup
132    */
133   {
134     GSN_CREATE_FILEGROUP_REQ,
135     GSN_CREATE_OBJ_REQ, GSN_CREATE_OBJ_REF, GSN_CREATE_OBJ_CONF,
136     0, 0, 0, 0,
137     &Dbdict::create_fg_prepare_start, &Dbdict::create_fg_prepare_complete,
138     &Dbdict::createObj_commit,
139     0, 0,
140     &Dbdict::createObj_abort,
141     &Dbdict::create_fg_abort_start, &Dbdict::create_fg_abort_complete,
142   }
143 
144   /**
145    * Create file
146    */
147   ,{
148     GSN_CREATE_FILE_REQ,
149     GSN_CREATE_OBJ_REQ, GSN_CREATE_OBJ_REF, GSN_CREATE_OBJ_CONF,
150     0, 0, 0, 0,
151     &Dbdict::create_file_prepare_start, &Dbdict::create_file_prepare_complete,
152     &Dbdict::createObj_commit,
153     &Dbdict::create_file_commit_start, 0,
154     &Dbdict::createObj_abort,
155     &Dbdict::create_file_abort_start, &Dbdict::create_file_abort_complete,
156   }
157 
158   /**
159    * Drop file
160    */
161   ,{
162     GSN_DROP_FILE_REQ,
163     GSN_DROP_OBJ_REQ, GSN_DROP_OBJ_REF, GSN_DROP_OBJ_CONF,
164     0, 0, 0, 0,
165     &Dbdict::drop_file_prepare_start, 0,
166     &Dbdict::dropObj_commit,
167     &Dbdict::drop_file_commit_start, &Dbdict::drop_file_commit_complete,
168     &Dbdict::dropObj_abort,
169     &Dbdict::drop_file_abort_start, 0
170   }
171 
172   /**
173    * Drop filegroup
174    */
175   ,{
176     GSN_DROP_FILEGROUP_REQ,
177     GSN_DROP_OBJ_REQ, GSN_DROP_OBJ_REF, GSN_DROP_OBJ_CONF,
178     0, 0, 0, 0,
179     &Dbdict::drop_fg_prepare_start, 0,
180     &Dbdict::dropObj_commit,
181     &Dbdict::drop_fg_commit_start, &Dbdict::drop_fg_commit_complete,
182     &Dbdict::dropObj_abort,
183     &Dbdict::drop_fg_abort_start, 0
184   }
185 
186   /**
187    * Drop undofile
188    */
189   ,{
190     GSN_DROP_FILE_REQ,
191     GSN_DROP_OBJ_REQ, GSN_DROP_OBJ_REF, GSN_DROP_OBJ_CONF,
192     0, 0, 0, 0,
193     &Dbdict::drop_undofile_prepare_start, 0,
194     0,
195     0, &Dbdict::drop_undofile_commit_complete,
196     0, 0, 0
197   }
198 };
199 
200 Uint32
alter_obj_inc_schema_version(Uint32 old)201 alter_obj_inc_schema_version(Uint32 old)
202 {
203    return (old & 0x00FFFFFF) + ((old + 0x1000000) & 0xFF000000);
204 }
205 
206 static
207 Uint32
alter_obj_dec_schema_version(Uint32 old)208 alter_obj_dec_schema_version(Uint32 old)
209 {
210   return (old & 0x00FFFFFF) + ((old - 0x1000000) & 0xFF000000);
211 }
212 
213 static
214 Uint32
create_obj_inc_schema_version(Uint32 old)215 create_obj_inc_schema_version(Uint32 old)
216 {
217   return (old + 0x00000001) & 0x00FFFFFF;
218 }
219 
220 /* **************************************************************** */
221 /* ---------------------------------------------------------------- */
222 /* MODULE:          GENERAL MODULE -------------------------------- */
223 /* ---------------------------------------------------------------- */
224 /*                                                                  */
225 /* This module contains general stuff. Mostly debug signals and     */
226 /* general signals that go into a specific module after checking a  */
227 /* state variable. Also general subroutines used by many.           */
228 /* ---------------------------------------------------------------- */
229 /* **************************************************************** */
230 
231 /* ---------------------------------------------------------------- */
232 // This signal is used to dump states of various variables in the
233 // block by command.
234 /* ---------------------------------------------------------------- */
235 void
execDUMP_STATE_ORD(Signal * signal)236 Dbdict::execDUMP_STATE_ORD(Signal* signal)
237 {
238   jamEntry();
239 
240 #ifdef VM_TRACE
241   if(signal->theData[0] == 1222){
242     const Uint32 tab = signal->theData[1];
243     PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
244     req->senderRef = reference();
245     req->senderData = 1222;
246     req->tableId = tab;
247     sendSignal(DBLQH_REF, GSN_PREP_DROP_TAB_REQ, signal,
248 	       PrepDropTabReq::SignalLength, JBB);
249   }
250 
251   if(signal->theData[0] == 1223){
252     const Uint32 tab = signal->theData[1];
253     PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
254     req->senderRef = reference();
255     req->senderData = 1222;
256     req->tableId = tab;
257     sendSignal(DBTC_REF, GSN_PREP_DROP_TAB_REQ, signal,
258 	       PrepDropTabReq::SignalLength, JBB);
259   }
260 
261   if(signal->theData[0] == 1224){
262     const Uint32 tab = signal->theData[1];
263     PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
264     req->senderRef = reference();
265     req->senderData = 1222;
266     req->tableId = tab;
267     sendSignal(DBDIH_REF, GSN_PREP_DROP_TAB_REQ, signal,
268 	       PrepDropTabReq::SignalLength, JBB);
269   }
270 
271   if(signal->theData[0] == 1225){
272     const Uint32 tab = signal->theData[1];
273     const Uint32 ver = signal->theData[2];
274     TableRecordPtr tabRecPtr;
275     c_tableRecordPool.getPtr(tabRecPtr, tab);
276     DropTableReq * req = (DropTableReq*)signal->getDataPtr();
277     req->senderData = 1225;
278     req->senderRef = numberToRef(1,1);
279     req->tableId = tab;
280     req->tableVersion = tabRecPtr.p->tableVersion + ver;
281     sendSignal(DBDICT_REF, GSN_DROP_TABLE_REQ, signal,
282 	       DropTableReq::SignalLength, JBB);
283   }
284 #endif
285 #define MEMINFO(x, y) infoEvent(x ": %d %d", y.getSize(), y.getNoOfFree())
286   if(signal->theData[0] == 1226){
287     MEMINFO("c_obj_pool", c_obj_pool);
288     MEMINFO("c_opRecordPool", c_opRecordPool);
289     MEMINFO("c_rope_pool", c_rope_pool);
290   }
291 
292   if (signal->theData[0] == 1227)
293   {
294     DLHashTable<DictObject>::Iterator iter;
295     bool ok = c_obj_hash.first(iter);
296     for(; ok; ok = c_obj_hash.next(iter))
297     {
298       Rope name(c_rope_pool, iter.curr.p->m_name);
299       char buf[1024];
300       name.copy(buf);
301       ndbout_c("%s m_ref_count: %d", buf, iter.curr.p->m_ref_count);
302     }
303   }
304 
305   return;
306 }//Dbdict::execDUMP_STATE_ORD()
307 
308 /* ---------------------------------------------------------------- */
309 /* ---------------------------------------------------------------- */
310 // CONTINUEB is used when a real-time break is needed for long
311 // processes.
312 /* ---------------------------------------------------------------- */
313 /* ---------------------------------------------------------------- */
execCONTINUEB(Signal * signal)314 void Dbdict::execCONTINUEB(Signal* signal)
315 {
316   jamEntry();
317   switch (signal->theData[0]) {
318   case ZPACK_TABLE_INTO_PAGES :
319     jam();
320     packTableIntoPages(signal);
321     break;
322 
323   case ZSEND_GET_TAB_RESPONSE :
324     jam();
325     sendGetTabResponse(signal);
326     break;
327 
328   case ZDICT_LOCK_POLL:
329     jam();
330     checkDictLockQueue(signal, true);
331     break;
332 
333   default :
334     ndbrequire(false);
335     break;
336   }//switch
337   return;
338 }//execCONTINUEB()
339 
340 /* ---------------------------------------------------------------- */
341 /* ---------------------------------------------------------------- */
342 // Routine to handle pack table into pages.
343 /* ---------------------------------------------------------------- */
344 /* ---------------------------------------------------------------- */
345 
packTableIntoPages(Signal * signal)346 void Dbdict::packTableIntoPages(Signal* signal)
347 {
348   const Uint32 tableId= signal->theData[1];
349   const Uint32 type= signal->theData[2];
350   const Uint32 pageId= signal->theData[3];
351 
352   PageRecordPtr pagePtr;
353   c_pageRecordArray.getPtr(pagePtr, pageId);
354 
355   memset(&pagePtr.p->word[0], 0, 4 * ZPAGE_HEADER_SIZE);
356   LinearWriter w(&pagePtr.p->word[ZPAGE_HEADER_SIZE],
357 		 ZMAX_PAGES_OF_TABLE_DEFINITION * ZSIZE_OF_PAGES_IN_WORDS);
358   w.first();
359   switch((DictTabInfo::TableType)type) {
360   case DictTabInfo::SystemTable:
361   case DictTabInfo::UserTable:
362   case DictTabInfo::UniqueHashIndex:
363   case DictTabInfo::HashIndex:
364   case DictTabInfo::UniqueOrderedIndex:
365   case DictTabInfo::OrderedIndex:{
366     jam();
367     TableRecordPtr tablePtr;
368     c_tableRecordPool.getPtr(tablePtr, tableId);
369     packTableIntoPages(w, tablePtr, signal);
370     break;
371   }
372   case DictTabInfo::Tablespace:
373   case DictTabInfo::LogfileGroup:{
374     FilegroupPtr fg_ptr;
375     ndbrequire(c_filegroup_hash.find(fg_ptr, tableId));
376     const Uint32 free_hi= signal->theData[4];
377     const Uint32 free_lo= signal->theData[5];
378     packFilegroupIntoPages(w, fg_ptr, free_hi, free_lo);
379     break;
380   }
381   case DictTabInfo::Datafile:{
382     FilePtr fg_ptr;
383     ndbrequire(c_file_hash.find(fg_ptr, tableId));
384     const Uint32 free_extents= signal->theData[4];
385     packFileIntoPages(w, fg_ptr, free_extents);
386     break;
387   }
388   case DictTabInfo::Undofile:{
389     FilePtr fg_ptr;
390     ndbrequire(c_file_hash.find(fg_ptr, tableId));
391     packFileIntoPages(w, fg_ptr, 0);
392     break;
393   }
394   case DictTabInfo::UndefTableType:
395   case DictTabInfo::HashIndexTrigger:
396   case DictTabInfo::SubscriptionTrigger:
397   case DictTabInfo::ReadOnlyConstraint:
398   case DictTabInfo::IndexTrigger:
399     ndbrequire(false);
400   }
401 
402   Uint32 wordsOfTable = w.getWordsUsed();
403   Uint32 pagesUsed = WORDS2PAGES(wordsOfTable);
404   pagePtr.p->word[ZPOS_CHECKSUM] =
405     computeChecksum(&pagePtr.p->word[0], pagesUsed * ZSIZE_OF_PAGES_IN_WORDS);
406 
407   switch (c_packTable.m_state) {
408   case PackTable::PTS_IDLE:
409     ndbrequire(false);
410     break;
411   case PackTable::PTS_GET_TAB:
412     jam();
413     c_retrieveRecord.retrievedNoOfPages = pagesUsed;
414     c_retrieveRecord.retrievedNoOfWords = wordsOfTable;
415     sendGetTabResponse(signal);
416     return;
417     break;
418   }//switch
419   ndbrequire(false);
420   return;
421 }//packTableIntoPages()
422 
423 void
packTableIntoPages(SimpleProperties::Writer & w,TableRecordPtr tablePtr,Signal * signal)424 Dbdict::packTableIntoPages(SimpleProperties::Writer & w,
425 			       TableRecordPtr tablePtr,
426 			       Signal* signal){
427 
428   union {
429     char tableName[MAX_TAB_NAME_SIZE];
430     char frmData[MAX_FRM_DATA_SIZE];
431     char rangeData[16*MAX_NDB_PARTITIONS];
432     char ngData[2*MAX_NDB_PARTITIONS];
433     char tsData[2*2*MAX_NDB_PARTITIONS];
434     char defaultValue[MAX_ATTR_DEFAULT_VALUE_SIZE];
435     char attributeName[MAX_ATTR_NAME_SIZE];
436   };
437   ConstRope r(c_rope_pool, tablePtr.p->tableName);
438   r.copy(tableName);
439   w.add(DictTabInfo::TableName, tableName);
440   w.add(DictTabInfo::TableId, tablePtr.i);
441   w.add(DictTabInfo::TableVersion, tablePtr.p->tableVersion);
442   w.add(DictTabInfo::NoOfKeyAttr, tablePtr.p->noOfPrimkey);
443   w.add(DictTabInfo::NoOfAttributes, tablePtr.p->noOfAttributes);
444   w.add(DictTabInfo::NoOfNullable, tablePtr.p->noOfNullAttr);
445   w.add(DictTabInfo::NoOfVariable, (Uint32)0);
446   w.add(DictTabInfo::KeyLength, tablePtr.p->tupKeyLength);
447 
448   w.add(DictTabInfo::TableLoggedFlag,
449 	!!(tablePtr.p->m_bits & TableRecord::TR_Logged));
450   w.add(DictTabInfo::RowGCIFlag,
451 	!!(tablePtr.p->m_bits & TableRecord::TR_RowGCI));
452   w.add(DictTabInfo::RowChecksumFlag,
453 	!!(tablePtr.p->m_bits & TableRecord::TR_RowChecksum));
454   w.add(DictTabInfo::TableTemporaryFlag,
455 	!!(tablePtr.p->m_bits & TableRecord::TR_Temporary));
456   w.add(DictTabInfo::ForceVarPartFlag,
457 	!!(tablePtr.p->m_bits & TableRecord::TR_ForceVarPart));
458 
459   w.add(DictTabInfo::MinLoadFactor, tablePtr.p->minLoadFactor);
460   w.add(DictTabInfo::MaxLoadFactor, tablePtr.p->maxLoadFactor);
461   w.add(DictTabInfo::TableKValue, tablePtr.p->kValue);
462   w.add(DictTabInfo::FragmentTypeVal, tablePtr.p->fragmentType);
463   w.add(DictTabInfo::TableTypeVal, tablePtr.p->tableType);
464   w.add(DictTabInfo::MaxRowsLow, tablePtr.p->maxRowsLow);
465   w.add(DictTabInfo::MaxRowsHigh, tablePtr.p->maxRowsHigh);
466   w.add(DictTabInfo::DefaultNoPartFlag, tablePtr.p->defaultNoPartFlag);
467   w.add(DictTabInfo::LinearHashFlag, tablePtr.p->linearHashFlag);
468   w.add(DictTabInfo::FragmentCount, tablePtr.p->fragmentCount);
469   w.add(DictTabInfo::MinRowsLow, tablePtr.p->minRowsLow);
470   w.add(DictTabInfo::MinRowsHigh, tablePtr.p->minRowsHigh);
471   w.add(DictTabInfo::SingleUserMode, tablePtr.p->singleUserMode);
472 
473   if(signal)
474   {
475     /* Denna branch k�rs vid GET_TABINFOREQ */
476 
477     Uint32 * theData = signal->getDataPtrSend();
478     CreateFragmentationReq * const req = (CreateFragmentationReq*)theData;
479     req->senderRef = 0;
480     req->senderData = RNIL;
481     req->fragmentationType = tablePtr.p->fragmentType;
482     req->noOfFragments = 0;
483     req->primaryTableId = tablePtr.i;
484     EXECUTE_DIRECT(DBDIH, GSN_CREATE_FRAGMENTATION_REQ, signal,
485 		   CreateFragmentationReq::SignalLength);
486     ndbrequire(signal->theData[0] == 0);
487     Uint16 *data = (Uint16*)&signal->theData[25];
488     Uint32 count = 2 + (1 + data[0]) * data[1];
489     w.add(DictTabInfo::ReplicaDataLen, 2*count);
490     for (Uint32 i = 0; i < count; i++)
491       data[i] = htons(data[i]);
492     w.add(DictTabInfo::ReplicaData, data, 2*count);
493   }
494   else
495   {
496     /* Denna del k�rs vid CREATE_TABLEREQ, ALTER_TABLEREQ */
497     ;
498   }
499 
500   if (tablePtr.p->primaryTableId != RNIL){
501     TableRecordPtr primTab;
502     c_tableRecordPool.getPtr(primTab, tablePtr.p->primaryTableId);
503     ConstRope r2(c_rope_pool, primTab.p->tableName);
504     r2.copy(tableName);
505     w.add(DictTabInfo::PrimaryTable, tableName);
506     w.add(DictTabInfo::PrimaryTableId, tablePtr.p->primaryTableId);
507     w.add(DictTabInfo::IndexState, tablePtr.p->indexState);
508     w.add(DictTabInfo::InsertTriggerId, tablePtr.p->insertTriggerId);
509     w.add(DictTabInfo::UpdateTriggerId, tablePtr.p->updateTriggerId);
510     w.add(DictTabInfo::DeleteTriggerId, tablePtr.p->deleteTriggerId);
511     w.add(DictTabInfo::CustomTriggerId, tablePtr.p->customTriggerId);
512   }
513 
514   ConstRope frm(c_rope_pool, tablePtr.p->frmData);
515   frm.copy(frmData);
516   w.add(DictTabInfo::FrmLen, frm.size());
517   w.add(DictTabInfo::FrmData, frmData, frm.size());
518 
519   {
520     jam();
521     ConstRope ts(c_rope_pool, tablePtr.p->tsData);
522     ts.copy(tsData);
523     w.add(DictTabInfo::TablespaceDataLen, ts.size());
524     w.add(DictTabInfo::TablespaceData, tsData, ts.size());
525 
526     ConstRope ng(c_rope_pool, tablePtr.p->ngData);
527     ng.copy(ngData);
528     w.add(DictTabInfo::FragmentDataLen, ng.size());
529     w.add(DictTabInfo::FragmentData, ngData, ng.size());
530 
531     ConstRope range(c_rope_pool, tablePtr.p->rangeData);
532     range.copy(rangeData);
533     w.add(DictTabInfo::RangeListDataLen, range.size());
534     w.add(DictTabInfo::RangeListData, rangeData, range.size());
535   }
536 
537   if(tablePtr.p->m_tablespace_id != RNIL)
538   {
539     w.add(DictTabInfo::TablespaceId, tablePtr.p->m_tablespace_id);
540     FilegroupPtr tsPtr;
541     ndbrequire(c_filegroup_hash.find(tsPtr, tablePtr.p->m_tablespace_id));
542     w.add(DictTabInfo::TablespaceVersion, tsPtr.p->m_version);
543   }
544 
545   AttributeRecordPtr attrPtr;
546   LocalDLFifoList<AttributeRecord> list(c_attributeRecordPool,
547 				    tablePtr.p->m_attributes);
548   for(list.first(attrPtr); !attrPtr.isNull(); list.next(attrPtr)){
549     jam();
550 
551     ConstRope name(c_rope_pool, attrPtr.p->attributeName);
552     name.copy(attributeName);
553 
554     w.add(DictTabInfo::AttributeName, attributeName);
555     w.add(DictTabInfo::AttributeId, attrPtr.p->attributeId);
556     w.add(DictTabInfo::AttributeKeyFlag, attrPtr.p->tupleKey > 0);
557 
558     const Uint32 desc = attrPtr.p->attributeDescriptor;
559     const Uint32 attrType = AttributeDescriptor::getType(desc);
560     const Uint32 attrSize = AttributeDescriptor::getSize(desc);
561     const Uint32 arraySize = AttributeDescriptor::getArraySize(desc);
562     const Uint32 arrayType = AttributeDescriptor::getArrayType(desc);
563     const Uint32 nullable = AttributeDescriptor::getNullable(desc);
564     const Uint32 DKey = AttributeDescriptor::getDKey(desc);
565     const Uint32 disk= AttributeDescriptor::getDiskBased(desc);
566 
567 
568     // AttributeType deprecated
569     w.add(DictTabInfo::AttributeSize, attrSize);
570     w.add(DictTabInfo::AttributeArraySize, arraySize);
571     w.add(DictTabInfo::AttributeArrayType, arrayType);
572     w.add(DictTabInfo::AttributeNullableFlag, nullable);
573     w.add(DictTabInfo::AttributeDKey, DKey);
574     w.add(DictTabInfo::AttributeExtType, attrType);
575     w.add(DictTabInfo::AttributeExtPrecision, attrPtr.p->extPrecision);
576     w.add(DictTabInfo::AttributeExtScale, attrPtr.p->extScale);
577     w.add(DictTabInfo::AttributeExtLength, attrPtr.p->extLength);
578     w.add(DictTabInfo::AttributeAutoIncrement,
579 	  (Uint32)attrPtr.p->autoIncrement);
580 
581     if(disk)
582       w.add(DictTabInfo::AttributeStorageType, (Uint32)NDB_STORAGETYPE_DISK);
583     else
584       w.add(DictTabInfo::AttributeStorageType, (Uint32)NDB_STORAGETYPE_MEMORY);
585 
586     ConstRope def(c_rope_pool, attrPtr.p->defaultValue);
587     def.copy(defaultValue);
588     w.add(DictTabInfo::AttributeDefaultValue, defaultValue);
589 
590     w.add(DictTabInfo::AttributeEnd, 1);
591   }
592 
593   w.add(DictTabInfo::TableEnd, 1);
594 }
595 
596 void
packFilegroupIntoPages(SimpleProperties::Writer & w,FilegroupPtr fg_ptr,const Uint32 undo_free_hi,const Uint32 undo_free_lo)597 Dbdict::packFilegroupIntoPages(SimpleProperties::Writer & w,
598 			       FilegroupPtr fg_ptr,
599 			       const Uint32 undo_free_hi,
600 			       const Uint32 undo_free_lo){
601 
602   DictFilegroupInfo::Filegroup fg; fg.init();
603   ConstRope r(c_rope_pool, fg_ptr.p->m_name);
604   r.copy(fg.FilegroupName);
605 
606   fg.FilegroupId = fg_ptr.p->key;
607   fg.FilegroupType = fg_ptr.p->m_type;
608   fg.FilegroupVersion = fg_ptr.p->m_version;
609 
610   switch(fg.FilegroupType){
611   case DictTabInfo::Tablespace:
612     //fg.TS_DataGrow = group.m_grow_spec;
613     fg.TS_ExtentSize = fg_ptr.p->m_tablespace.m_extent_size;
614     fg.TS_LogfileGroupId = fg_ptr.p->m_tablespace.m_default_logfile_group_id;
615     FilegroupPtr lfg_ptr;
616     ndbrequire(c_filegroup_hash.find(lfg_ptr, fg.TS_LogfileGroupId));
617     fg.TS_LogfileGroupVersion = lfg_ptr.p->m_version;
618     break;
619   case DictTabInfo::LogfileGroup:
620     fg.LF_UndoBufferSize = fg_ptr.p->m_logfilegroup.m_undo_buffer_size;
621     fg.LF_UndoFreeWordsHi= undo_free_hi;
622     fg.LF_UndoFreeWordsLo= undo_free_lo;
623     //fg.LF_UndoGrow = ;
624     break;
625   default:
626     ndbrequire(false);
627   }
628 
629   SimpleProperties::UnpackStatus s;
630   s = SimpleProperties::pack(w,
631 			     &fg,
632 			     DictFilegroupInfo::Mapping,
633 			     DictFilegroupInfo::MappingSize, true);
634 
635   ndbrequire(s == SimpleProperties::Eof);
636 }
637 
638 void
packFileIntoPages(SimpleProperties::Writer & w,FilePtr f_ptr,const Uint32 free_extents)639 Dbdict::packFileIntoPages(SimpleProperties::Writer & w,
640 			  FilePtr f_ptr, const Uint32 free_extents){
641 
642   DictFilegroupInfo::File f; f.init();
643   ConstRope r(c_rope_pool, f_ptr.p->m_path);
644   r.copy(f.FileName);
645 
646   f.FileType = f_ptr.p->m_type;
647   f.FilegroupId = f_ptr.p->m_filegroup_id;; //group.m_id;
648   f.FileSizeHi = (f_ptr.p->m_file_size >> 32);
649   f.FileSizeLo = (f_ptr.p->m_file_size & 0xFFFFFFFF);
650   f.FileFreeExtents= free_extents;
651   f.FileId =  f_ptr.p->key;
652   f.FileVersion = f_ptr.p->m_version;
653 
654   FilegroupPtr lfg_ptr;
655   ndbrequire(c_filegroup_hash.find(lfg_ptr, f.FilegroupId));
656   f.FilegroupVersion = lfg_ptr.p->m_version;
657 
658   SimpleProperties::UnpackStatus s;
659   s = SimpleProperties::pack(w,
660 			     &f,
661 			     DictFilegroupInfo::FileMapping,
662 			     DictFilegroupInfo::FileMappingSize, true);
663 
664   ndbrequire(s == SimpleProperties::Eof);
665 }
666 
667 /* ---------------------------------------------------------------- */
668 /* ---------------------------------------------------------------- */
669 // The routines to handle responses from file system.
670 /* ---------------------------------------------------------------- */
671 /* ---------------------------------------------------------------- */
672 
673 /* ---------------------------------------------------------------- */
674 // A file was successfully closed.
675 /* ---------------------------------------------------------------- */
execFSCLOSECONF(Signal * signal)676 void Dbdict::execFSCLOSECONF(Signal* signal)
677 {
678   FsConnectRecordPtr fsPtr;
679   FsConf * const fsConf = (FsConf *)&signal->theData[0];
680   jamEntry();
681   c_fsConnectRecordPool.getPtr(fsPtr, fsConf->userPointer);
682   switch (fsPtr.p->fsState) {
683   case FsConnectRecord::CLOSE_WRITE_SCHEMA:
684     jam();
685     closeWriteSchemaConf(signal, fsPtr);
686     break;
687   case FsConnectRecord::CLOSE_READ_SCHEMA:
688     jam();
689     closeReadSchemaConf(signal, fsPtr);
690     break;
691   case FsConnectRecord::CLOSE_READ_TAB_FILE:
692     jam();
693     closeReadTableConf(signal, fsPtr);
694     break;
695   case FsConnectRecord::CLOSE_WRITE_TAB_FILE:
696     jam();
697     closeWriteTableConf(signal, fsPtr);
698     break;
699   case FsConnectRecord::OPEN_READ_SCHEMA2:
700     openSchemaFile(signal, 1, fsPtr.i, false, false);
701     break;
702   case FsConnectRecord::OPEN_READ_TAB_FILE2:
703     openTableFile(signal, 1, fsPtr.i, c_readTableRecord.tableId, false);
704     break;
705   default:
706     jamLine((fsPtr.p->fsState & 0xFFF));
707     ndbrequire(false);
708     break;
709   }//switch
710 }//execFSCLOSECONF()
711 
712 
713 /* ---------------------------------------------------------------- */
714 // A file was successfully opened.
715 /* ---------------------------------------------------------------- */
execFSOPENCONF(Signal * signal)716 void Dbdict::execFSOPENCONF(Signal* signal)
717 {
718   FsConnectRecordPtr fsPtr;
719   jamEntry();
720   FsConf * const fsConf = (FsConf *)&signal->theData[0];
721   c_fsConnectRecordPool.getPtr(fsPtr, fsConf->userPointer);
722 
723   Uint32 filePointer = fsConf->filePointer;
724   fsPtr.p->filePtr = filePointer;
725   switch (fsPtr.p->fsState) {
726   case FsConnectRecord::OPEN_WRITE_SCHEMA:
727     jam();
728     fsPtr.p->fsState = FsConnectRecord::WRITE_SCHEMA;
729     writeSchemaFile(signal, filePointer, fsPtr.i);
730     break;
731   case FsConnectRecord::OPEN_READ_SCHEMA1:
732     jam();
733     fsPtr.p->fsState = FsConnectRecord::READ_SCHEMA1;
734     readSchemaFile(signal, filePointer, fsPtr.i);
735     break;
736   case FsConnectRecord::OPEN_READ_SCHEMA2:
737     jam();
738     fsPtr.p->fsState = FsConnectRecord::READ_SCHEMA2;
739     readSchemaFile(signal, filePointer, fsPtr.i);
740     break;
741   case FsConnectRecord::OPEN_READ_TAB_FILE1:
742     jam();
743     fsPtr.p->fsState = FsConnectRecord::READ_TAB_FILE1;
744     readTableFile(signal, filePointer, fsPtr.i);
745     break;
746   case FsConnectRecord::OPEN_READ_TAB_FILE2:
747     jam();
748     fsPtr.p->fsState = FsConnectRecord::READ_TAB_FILE2;
749     readTableFile(signal, filePointer, fsPtr.i);
750     break;
751   case FsConnectRecord::OPEN_WRITE_TAB_FILE:
752     jam();
753     fsPtr.p->fsState = FsConnectRecord::WRITE_TAB_FILE;
754     writeTableFile(signal, filePointer, fsPtr.i);
755     break;
756   default:
757     jamLine((fsPtr.p->fsState & 0xFFF));
758     ndbrequire(false);
759     break;
760   }//switch
761 }//execFSOPENCONF()
762 
763 /* ---------------------------------------------------------------- */
764 // An open file was refused.
765 /* ---------------------------------------------------------------- */
execFSOPENREF(Signal * signal)766 void Dbdict::execFSOPENREF(Signal* signal)
767 {
768   jamEntry();
769   FsRef * const fsRef = (FsRef *)&signal->theData[0];
770   FsConnectRecordPtr fsPtr;
771   c_fsConnectRecordPool.getPtr(fsPtr, fsRef->userPointer);
772   switch (fsPtr.p->fsState) {
773   case FsConnectRecord::OPEN_READ_SCHEMA1:
774     jam();
775     openReadSchemaRef(signal, fsPtr);
776     return;
777   case FsConnectRecord::OPEN_READ_TAB_FILE1:
778     jam();
779     openReadTableRef(signal, fsPtr);
780     return;
781   default:
782     break;
783   }//switch
784   {
785     char msg[100];
786     sprintf(msg, "File system open failed during FsConnectRecord state %d", (Uint32)fsPtr.p->fsState);
787     fsRefError(signal,__LINE__,msg);
788   }
789 }//execFSOPENREF()
790 
791 /* ---------------------------------------------------------------- */
792 // A file was successfully read.
793 /* ---------------------------------------------------------------- */
execFSREADCONF(Signal * signal)794 void Dbdict::execFSREADCONF(Signal* signal)
795 {
796   jamEntry();
797   FsConf * const fsConf = (FsConf *)&signal->theData[0];
798   FsConnectRecordPtr fsPtr;
799   c_fsConnectRecordPool.getPtr(fsPtr, fsConf->userPointer);
800   switch (fsPtr.p->fsState) {
801   case FsConnectRecord::READ_SCHEMA1:
802   case FsConnectRecord::READ_SCHEMA2:
803     readSchemaConf(signal ,fsPtr);
804     break;
805   case FsConnectRecord::READ_TAB_FILE1:
806     if(ERROR_INSERTED(6007)){
807       jam();
808       FsRef * const fsRef = (FsRef *)&signal->theData[0];
809       fsRef->userPointer = fsConf->userPointer;
810       fsRef->setErrorCode(fsRef->errorCode, NDBD_EXIT_AFS_UNKNOWN);
811       fsRef->osErrorCode = ~0; // Indicate local error
812       execFSREADREF(signal);
813       return;
814     }//Testing how DICT behave if read of file 1 fails (Bug#28770)
815   case FsConnectRecord::READ_TAB_FILE2:
816     jam();
817     readTableConf(signal ,fsPtr);
818     break;
819   default:
820     jamLine((fsPtr.p->fsState & 0xFFF));
821     ndbrequire(false);
822     break;
823   }//switch
824 }//execFSREADCONF()
825 
826 /* ---------------------------------------------------------------- */
827 // A read file was refused.
828 /* ---------------------------------------------------------------- */
execFSREADREF(Signal * signal)829 void Dbdict::execFSREADREF(Signal* signal)
830 {
831   jamEntry();
832   FsRef * const fsRef = (FsRef *)&signal->theData[0];
833   FsConnectRecordPtr fsPtr;
834   c_fsConnectRecordPool.getPtr(fsPtr, fsRef->userPointer);
835   switch (fsPtr.p->fsState) {
836   case FsConnectRecord::READ_SCHEMA1:
837     jam();
838     readSchemaRef(signal, fsPtr);
839     return;
840   case FsConnectRecord::READ_TAB_FILE1:
841     jam();
842     readTableRef(signal, fsPtr);
843     return;
844   default:
845     break;
846   }//switch
847   {
848     char msg[100];
849     sprintf(msg, "File system read failed during FsConnectRecord state %d", (Uint32)fsPtr.p->fsState);
850     fsRefError(signal,__LINE__,msg);
851   }
852 }//execFSREADREF()
853 
854 /* ---------------------------------------------------------------- */
855 // A file was successfully written.
856 /* ---------------------------------------------------------------- */
execFSWRITECONF(Signal * signal)857 void Dbdict::execFSWRITECONF(Signal* signal)
858 {
859   FsConf * const fsConf = (FsConf *)&signal->theData[0];
860   FsConnectRecordPtr fsPtr;
861   jamEntry();
862   c_fsConnectRecordPool.getPtr(fsPtr, fsConf->userPointer);
863   switch (fsPtr.p->fsState) {
864   case FsConnectRecord::WRITE_TAB_FILE:
865     writeTableConf(signal, fsPtr);
866     break;
867   case FsConnectRecord::WRITE_SCHEMA:
868     jam();
869     writeSchemaConf(signal, fsPtr);
870     break;
871   default:
872     jamLine((fsPtr.p->fsState & 0xFFF));
873     ndbrequire(false);
874     break;
875   }//switch
876 }//execFSWRITECONF()
877 
878 
879 /* ---------------------------------------------------------------- */
880 // Routines to handle Read/Write of Table Files
881 /* ---------------------------------------------------------------- */
882 void
writeTableFile(Signal * signal,Uint32 tableId,SegmentedSectionPtr tabInfoPtr,Callback * callback)883 Dbdict::writeTableFile(Signal* signal, Uint32 tableId,
884 		       SegmentedSectionPtr tabInfoPtr, Callback* callback){
885 
886   ndbrequire(c_writeTableRecord.tableWriteState == WriteTableRecord::IDLE);
887 
888   Uint32 pages = WORDS2PAGES(tabInfoPtr.sz);
889   c_writeTableRecord.no_of_words = tabInfoPtr.sz;
890   c_writeTableRecord.tableWriteState = WriteTableRecord::TWR_CALLBACK;
891   c_writeTableRecord.m_callback = * callback;
892 
893   c_writeTableRecord.pageId = 0;
894   ndbrequire(pages == 1);
895 
896   PageRecordPtr pageRecPtr;
897   c_pageRecordArray.getPtr(pageRecPtr, c_writeTableRecord.pageId);
898   copy(&pageRecPtr.p->word[ZPAGE_HEADER_SIZE], tabInfoPtr);
899 
900   memset(&pageRecPtr.p->word[0], 0, 4 * ZPAGE_HEADER_SIZE);
901   pageRecPtr.p->word[ZPOS_CHECKSUM] =
902     computeChecksum(&pageRecPtr.p->word[0],
903 		    pages * ZSIZE_OF_PAGES_IN_WORDS);
904 
905   startWriteTableFile(signal, tableId);
906 }
907 
startWriteTableFile(Signal * signal,Uint32 tableId)908 void Dbdict::startWriteTableFile(Signal* signal, Uint32 tableId)
909 {
910   FsConnectRecordPtr fsPtr;
911   c_writeTableRecord.tableId = tableId;
912   c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
913   fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_TAB_FILE;
914   openTableFile(signal, 0, fsPtr.i, tableId, true);
915   c_writeTableRecord.noOfTableFilesHandled = 0;
916 }//Dbdict::startWriteTableFile()
917 
openTableFile(Signal * signal,Uint32 fileNo,Uint32 fsConPtr,Uint32 tableId,bool writeFlag)918 void Dbdict::openTableFile(Signal* signal,
919                            Uint32 fileNo,
920                            Uint32 fsConPtr,
921                            Uint32 tableId,
922                            bool   writeFlag)
923 {
924   FsOpenReq * const fsOpenReq = (FsOpenReq *)&signal->theData[0];
925 
926   fsOpenReq->userReference = reference();
927   fsOpenReq->userPointer = fsConPtr;
928   if (writeFlag) {
929     jam();
930     fsOpenReq->fileFlags =
931       FsOpenReq::OM_WRITEONLY |
932       FsOpenReq::OM_TRUNCATE |
933       FsOpenReq::OM_CREATE |
934       FsOpenReq::OM_SYNC;
935   } else {
936     jam();
937     fsOpenReq->fileFlags = FsOpenReq::OM_READONLY;
938   }//if
939   fsOpenReq->fileNumber[3] = 0; // Initialise before byte changes
940   FsOpenReq::setVersion(fsOpenReq->fileNumber, 1);
941   FsOpenReq::setSuffix(fsOpenReq->fileNumber, FsOpenReq::S_TABLELIST);
942   FsOpenReq::v1_setDisk(fsOpenReq->fileNumber, (fileNo + 1));
943   FsOpenReq::v1_setTable(fsOpenReq->fileNumber, tableId);
944   FsOpenReq::v1_setFragment(fsOpenReq->fileNumber, (Uint32)-1);
945   FsOpenReq::v1_setS(fsOpenReq->fileNumber, 0);
946   FsOpenReq::v1_setP(fsOpenReq->fileNumber, 255);
947 /* ---------------------------------------------------------------- */
948 // File name : D1/DBDICT/T0/S1.TableList
949 // D1 means Disk 1 (set by fileNo + 1)
950 // T0 means table id = 0
951 // S1 means tableVersion 1
952 // TableList indicates that this is a file for a table description.
953 /* ---------------------------------------------------------------- */
954   sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
955 }//openTableFile()
956 
writeTableFile(Signal * signal,Uint32 filePtr,Uint32 fsConPtr)957 void Dbdict::writeTableFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
958 {
959   FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
960 
961   fsRWReq->filePointer = filePtr;
962   fsRWReq->userReference = reference();
963   fsRWReq->userPointer = fsConPtr;
964   fsRWReq->operationFlag = 0; // Initialise before bit changes
965   FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 1);
966   FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
967                                 FsReadWriteReq::fsFormatArrayOfPages);
968   fsRWReq->varIndex = ZBAT_TABLE_FILE;
969   fsRWReq->numberOfPages = WORDS2PAGES(c_writeTableRecord.no_of_words);
970   fsRWReq->data.arrayOfPages.varIndex = c_writeTableRecord.pageId;
971   fsRWReq->data.arrayOfPages.fileOffset = 0; // Write to file page 0
972   sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
973 }//writeTableFile()
974 
writeTableConf(Signal * signal,FsConnectRecordPtr fsPtr)975 void Dbdict::writeTableConf(Signal* signal,
976                                 FsConnectRecordPtr fsPtr)
977 {
978   fsPtr.p->fsState = FsConnectRecord::CLOSE_WRITE_TAB_FILE;
979   closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
980   return;
981 }//Dbdict::writeTableConf()
982 
closeWriteTableConf(Signal * signal,FsConnectRecordPtr fsPtr)983 void Dbdict::closeWriteTableConf(Signal* signal,
984                                  FsConnectRecordPtr fsPtr)
985 {
986   c_writeTableRecord.noOfTableFilesHandled++;
987   if (c_writeTableRecord.noOfTableFilesHandled < 2) {
988     jam();
989     fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_TAB_FILE;
990     openTableFile(signal, 1, fsPtr.i, c_writeTableRecord.tableId, true);
991     return;
992   }
993   ndbrequire(c_writeTableRecord.noOfTableFilesHandled == 2);
994   c_fsConnectRecordPool.release(fsPtr);
995   WriteTableRecord::TableWriteState state = c_writeTableRecord.tableWriteState;
996   c_writeTableRecord.tableWriteState = WriteTableRecord::IDLE;
997   switch (state) {
998   case WriteTableRecord::IDLE:
999   case WriteTableRecord::WRITE_ADD_TABLE_MASTER :
1000   case WriteTableRecord::WRITE_ADD_TABLE_SLAVE :
1001   case WriteTableRecord::WRITE_RESTART_FROM_MASTER :
1002   case WriteTableRecord::WRITE_RESTART_FROM_OWN :
1003     ndbrequire(false);
1004     break;
1005   case WriteTableRecord::TWR_CALLBACK:
1006     jam();
1007     execute(signal, c_writeTableRecord.m_callback, 0);
1008     return;
1009   }
1010   ndbrequire(false);
1011 }//Dbdict::closeWriteTableConf()
1012 
startReadTableFile(Signal * signal,Uint32 tableId)1013 void Dbdict::startReadTableFile(Signal* signal, Uint32 tableId)
1014 {
1015   //globalSignalLoggers.log(number(), "startReadTableFile");
1016   ndbrequire(!c_readTableRecord.inUse);
1017 
1018   FsConnectRecordPtr fsPtr;
1019   c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
1020   c_readTableRecord.inUse = true;
1021   c_readTableRecord.tableId = tableId;
1022   fsPtr.p->fsState = FsConnectRecord::OPEN_READ_TAB_FILE1;
1023   openTableFile(signal, 0, fsPtr.i, tableId, false);
1024 }//Dbdict::startReadTableFile()
1025 
openReadTableRef(Signal * signal,FsConnectRecordPtr fsPtr)1026 void Dbdict::openReadTableRef(Signal* signal,
1027                               FsConnectRecordPtr fsPtr)
1028 {
1029   fsPtr.p->fsState = FsConnectRecord::OPEN_READ_TAB_FILE2;
1030   openTableFile(signal, 1, fsPtr.i, c_readTableRecord.tableId, false);
1031   return;
1032 }//Dbdict::openReadTableConf()
1033 
readTableFile(Signal * signal,Uint32 filePtr,Uint32 fsConPtr)1034 void Dbdict::readTableFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
1035 {
1036   FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
1037 
1038   fsRWReq->filePointer = filePtr;
1039   fsRWReq->userReference = reference();
1040   fsRWReq->userPointer = fsConPtr;
1041   fsRWReq->operationFlag = 0; // Initialise before bit changes
1042   FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 0);
1043   FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
1044                                 FsReadWriteReq::fsFormatArrayOfPages);
1045   fsRWReq->varIndex = ZBAT_TABLE_FILE;
1046   fsRWReq->numberOfPages = WORDS2PAGES(c_readTableRecord.no_of_words);
1047   fsRWReq->data.arrayOfPages.varIndex = c_readTableRecord.pageId;
1048   fsRWReq->data.arrayOfPages.fileOffset = 0; // Write to file page 0
1049   sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 8, JBA);
1050 }//readTableFile()
1051 
readTableConf(Signal * signal,FsConnectRecordPtr fsPtr)1052 void Dbdict::readTableConf(Signal* signal,
1053 			   FsConnectRecordPtr fsPtr)
1054 {
1055   /* ---------------------------------------------------------------- */
1056   // Verify the data read from disk
1057   /* ---------------------------------------------------------------- */
1058   bool crashInd;
1059   if (fsPtr.p->fsState == FsConnectRecord::READ_TAB_FILE1) {
1060     jam();
1061     crashInd = false;
1062   } else {
1063     jam();
1064     crashInd = true;
1065   }//if
1066 
1067   PageRecordPtr tmpPagePtr;
1068   c_pageRecordArray.getPtr(tmpPagePtr, c_readTableRecord.pageId);
1069   Uint32 sz =
1070     WORDS2PAGES(c_readTableRecord.no_of_words)*ZSIZE_OF_PAGES_IN_WORDS;
1071   Uint32 chk = computeChecksum((const Uint32*)tmpPagePtr.p, sz);
1072 
1073   ndbrequire((chk == 0) || !crashInd);
1074   if(chk != 0){
1075     jam();
1076     ndbrequire(fsPtr.p->fsState == FsConnectRecord::READ_TAB_FILE1);
1077     readTableRef(signal, fsPtr);
1078     return;
1079   }//if
1080 
1081   fsPtr.p->fsState = FsConnectRecord::CLOSE_READ_TAB_FILE;
1082   closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
1083   return;
1084 }//Dbdict::readTableConf()
1085 
readTableRef(Signal * signal,FsConnectRecordPtr fsPtr)1086 void Dbdict::readTableRef(Signal* signal,
1087                           FsConnectRecordPtr fsPtr)
1088 {
1089   /**
1090    * First close corrupt file
1091    */
1092   fsPtr.p->fsState = FsConnectRecord::OPEN_READ_TAB_FILE2;
1093   closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
1094   return;
1095 }//Dbdict::readTableRef()
1096 
closeReadTableConf(Signal * signal,FsConnectRecordPtr fsPtr)1097 void Dbdict::closeReadTableConf(Signal* signal,
1098                                 FsConnectRecordPtr fsPtr)
1099 {
1100   c_fsConnectRecordPool.release(fsPtr);
1101   c_readTableRecord.inUse = false;
1102 
1103   execute(signal, c_readTableRecord.m_callback, 0);
1104   return;
1105 }//Dbdict::closeReadTableConf()
1106 
1107 /* ---------------------------------------------------------------- */
1108 // Routines to handle Read/Write of Schema Files
1109 /* ---------------------------------------------------------------- */
1110 void
updateSchemaState(Signal * signal,Uint32 tableId,SchemaFile::TableEntry * te,Callback * callback,bool savetodisk)1111 Dbdict::updateSchemaState(Signal* signal, Uint32 tableId,
1112 			  SchemaFile::TableEntry* te, Callback* callback,
1113                           bool savetodisk){
1114   jam();
1115   XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
1116   SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, tableId);
1117 
1118   SchemaFile::TableState newState =
1119     (SchemaFile::TableState)te->m_tableState;
1120   SchemaFile::TableState oldState =
1121     (SchemaFile::TableState)tableEntry->m_tableState;
1122 
1123   Uint32 newVersion = te->m_tableVersion;
1124   Uint32 oldVersion = tableEntry->m_tableVersion;
1125 
1126   bool ok = false;
1127   switch(newState){
1128   case SchemaFile::ADD_STARTED:
1129     jam();
1130     ok = true;
1131     ndbrequire(create_obj_inc_schema_version(oldVersion) == newVersion);
1132     ndbrequire(oldState == SchemaFile::INIT ||
1133 	       oldState == SchemaFile::DROP_TABLE_COMMITTED);
1134     break;
1135   case SchemaFile::TABLE_ADD_COMMITTED:
1136     jam();
1137     ok = true;
1138     ndbrequire(newVersion == oldVersion);
1139     ndbrequire(oldState == SchemaFile::ADD_STARTED ||
1140 	       oldState == SchemaFile::DROP_TABLE_STARTED);
1141     break;
1142   case SchemaFile::ALTER_TABLE_COMMITTED:
1143     jam();
1144     ok = true;
1145     ndbrequire(alter_obj_inc_schema_version(oldVersion) == newVersion);
1146     ndbrequire(oldState == SchemaFile::TABLE_ADD_COMMITTED ||
1147 	       oldState == SchemaFile::ALTER_TABLE_COMMITTED);
1148     break;
1149   case SchemaFile::DROP_TABLE_STARTED:
1150     jam();
1151   case SchemaFile::DROP_TABLE_COMMITTED:
1152     jam();
1153     ok = true;
1154     break;
1155   case SchemaFile::TEMPORARY_TABLE_COMMITTED:
1156     jam();
1157     ndbrequire(oldState == SchemaFile::ADD_STARTED ||
1158                oldState == SchemaFile::TEMPORARY_TABLE_COMMITTED);
1159     ok = true;
1160     break;
1161   case SchemaFile::INIT:
1162     jam();
1163     ok = true;
1164     ndbrequire((oldState == SchemaFile::ADD_STARTED));
1165   }//if
1166   ndbrequire(ok);
1167 
1168   * tableEntry = * te;
1169   computeChecksum(xsf, tableId / NDB_SF_PAGE_ENTRIES);
1170 
1171   if (savetodisk)
1172   {
1173     ndbrequire(c_writeSchemaRecord.inUse == false);
1174     c_writeSchemaRecord.inUse = true;
1175 
1176     c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
1177     c_writeSchemaRecord.newFile = false;
1178     c_writeSchemaRecord.firstPage = tableId / NDB_SF_PAGE_ENTRIES;
1179     c_writeSchemaRecord.noOfPages = 1;
1180     c_writeSchemaRecord.m_callback = * callback;
1181 
1182     startWriteSchemaFile(signal);
1183   }
1184   else
1185   {
1186     execute(signal, *callback, 0);
1187   }
1188 }
1189 
startWriteSchemaFile(Signal * signal)1190 void Dbdict::startWriteSchemaFile(Signal* signal)
1191 {
1192   FsConnectRecordPtr fsPtr;
1193   c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
1194   fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_SCHEMA;
1195   openSchemaFile(signal, 0, fsPtr.i, true, c_writeSchemaRecord.newFile);
1196   c_writeSchemaRecord.noOfSchemaFilesHandled = 0;
1197 }//Dbdict::startWriteSchemaFile()
1198 
openSchemaFile(Signal * signal,Uint32 fileNo,Uint32 fsConPtr,bool writeFlag,bool newFile)1199 void Dbdict::openSchemaFile(Signal* signal,
1200                             Uint32 fileNo,
1201                             Uint32 fsConPtr,
1202                             bool writeFlag,
1203                             bool newFile)
1204 {
1205   FsOpenReq * const fsOpenReq = (FsOpenReq *)&signal->theData[0];
1206   fsOpenReq->userReference = reference();
1207   fsOpenReq->userPointer = fsConPtr;
1208   if (writeFlag) {
1209     jam();
1210     fsOpenReq->fileFlags =
1211       FsOpenReq::OM_WRITEONLY |
1212       FsOpenReq::OM_SYNC;
1213     if (newFile)
1214       fsOpenReq->fileFlags |=
1215         FsOpenReq::OM_TRUNCATE |
1216         FsOpenReq::OM_CREATE;
1217   } else {
1218     jam();
1219     fsOpenReq->fileFlags = FsOpenReq::OM_READONLY;
1220   }//if
1221   fsOpenReq->fileNumber[3] = 0; // Initialise before byte changes
1222   FsOpenReq::setVersion(fsOpenReq->fileNumber, 1);
1223   FsOpenReq::setSuffix(fsOpenReq->fileNumber, FsOpenReq::S_SCHEMALOG);
1224   FsOpenReq::v1_setDisk(fsOpenReq->fileNumber, (fileNo + 1));
1225   FsOpenReq::v1_setTable(fsOpenReq->fileNumber, (Uint32)-1);
1226   FsOpenReq::v1_setFragment(fsOpenReq->fileNumber, (Uint32)-1);
1227   FsOpenReq::v1_setS(fsOpenReq->fileNumber, (Uint32)-1);
1228   FsOpenReq::v1_setP(fsOpenReq->fileNumber, 0);
1229 /* ---------------------------------------------------------------- */
1230 // File name : D1/DBDICT/P0.SchemaLog
1231 // D1 means Disk 1 (set by fileNo + 1). Writes to both D1 and D2
1232 // SchemaLog indicates that this is a file giving a list of current tables.
1233 /* ---------------------------------------------------------------- */
1234   sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
1235 }//openSchemaFile()
1236 
writeSchemaFile(Signal * signal,Uint32 filePtr,Uint32 fsConPtr)1237 void Dbdict::writeSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
1238 {
1239   FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
1240 
1241   // check write record
1242   WriteSchemaRecord & wr = c_writeSchemaRecord;
1243   ndbrequire(wr.pageId == (wr.pageId != 0) * NDB_SF_MAX_PAGES);
1244   ndbrequire(wr.noOfPages != 0);
1245   ndbrequire(wr.firstPage + wr.noOfPages <= NDB_SF_MAX_PAGES);
1246 
1247   fsRWReq->filePointer = filePtr;
1248   fsRWReq->userReference = reference();
1249   fsRWReq->userPointer = fsConPtr;
1250   fsRWReq->operationFlag = 0; // Initialise before bit changes
1251   FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 1);
1252   FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
1253                                 FsReadWriteReq::fsFormatArrayOfPages);
1254   fsRWReq->varIndex = ZBAT_SCHEMA_FILE;
1255   fsRWReq->numberOfPages = wr.noOfPages;
1256   // Write from memory page
1257   fsRWReq->data.arrayOfPages.varIndex = wr.pageId + wr.firstPage;
1258   fsRWReq->data.arrayOfPages.fileOffset = wr.firstPage;
1259   sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
1260 }//writeSchemaFile()
1261 
writeSchemaConf(Signal * signal,FsConnectRecordPtr fsPtr)1262 void Dbdict::writeSchemaConf(Signal* signal,
1263                                 FsConnectRecordPtr fsPtr)
1264 {
1265   fsPtr.p->fsState = FsConnectRecord::CLOSE_WRITE_SCHEMA;
1266   closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
1267   return;
1268 }//Dbdict::writeSchemaConf()
1269 
closeFile(Signal * signal,Uint32 filePtr,Uint32 fsConPtr)1270 void Dbdict::closeFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
1271 {
1272   FsCloseReq * const fsCloseReq = (FsCloseReq *)&signal->theData[0];
1273   fsCloseReq->filePointer = filePtr;
1274   fsCloseReq->userReference = reference();
1275   fsCloseReq->userPointer = fsConPtr;
1276   FsCloseReq::setRemoveFileFlag(fsCloseReq->fileFlag, false);
1277   sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, FsCloseReq::SignalLength, JBA);
1278   return;
1279 }//closeFile()
1280 
closeWriteSchemaConf(Signal * signal,FsConnectRecordPtr fsPtr)1281 void Dbdict::closeWriteSchemaConf(Signal* signal,
1282                                      FsConnectRecordPtr fsPtr)
1283 {
1284   c_writeSchemaRecord.noOfSchemaFilesHandled++;
1285   if (c_writeSchemaRecord.noOfSchemaFilesHandled < 2) {
1286     jam();
1287     fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_SCHEMA;
1288     openSchemaFile(signal, 1, fsPtr.i, true, c_writeSchemaRecord.newFile);
1289     return;
1290   }
1291   ndbrequire(c_writeSchemaRecord.noOfSchemaFilesHandled == 2);
1292 
1293   c_fsConnectRecordPool.release(fsPtr);
1294 
1295   c_writeSchemaRecord.inUse = false;
1296   execute(signal, c_writeSchemaRecord.m_callback, 0);
1297   return;
1298 }//Dbdict::closeWriteSchemaConf()
1299 
startReadSchemaFile(Signal * signal)1300 void Dbdict::startReadSchemaFile(Signal* signal)
1301 {
1302   //globalSignalLoggers.log(number(), "startReadSchemaFile");
1303   FsConnectRecordPtr fsPtr;
1304   c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
1305   fsPtr.p->fsState = FsConnectRecord::OPEN_READ_SCHEMA1;
1306   openSchemaFile(signal, 0, fsPtr.i, false, false);
1307 }//Dbdict::startReadSchemaFile()
1308 
openReadSchemaRef(Signal * signal,FsConnectRecordPtr fsPtr)1309 void Dbdict::openReadSchemaRef(Signal* signal,
1310                                FsConnectRecordPtr fsPtr)
1311 {
1312   fsPtr.p->fsState = FsConnectRecord::OPEN_READ_SCHEMA2;
1313   openSchemaFile(signal, 1, fsPtr.i, false, false);
1314 }//Dbdict::openReadSchemaRef()
1315 
readSchemaFile(Signal * signal,Uint32 filePtr,Uint32 fsConPtr)1316 void Dbdict::readSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
1317 {
1318   FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
1319 
1320   // check read record
1321   ReadSchemaRecord & rr = c_readSchemaRecord;
1322   ndbrequire(rr.pageId == (rr.pageId != 0) * NDB_SF_MAX_PAGES);
1323   ndbrequire(rr.noOfPages != 0);
1324   ndbrequire(rr.firstPage + rr.noOfPages <= NDB_SF_MAX_PAGES);
1325 
1326   fsRWReq->filePointer = filePtr;
1327   fsRWReq->userReference = reference();
1328   fsRWReq->userPointer = fsConPtr;
1329   fsRWReq->operationFlag = 0; // Initialise before bit changes
1330   FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 0);
1331   FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
1332                                 FsReadWriteReq::fsFormatArrayOfPages);
1333   fsRWReq->varIndex = ZBAT_SCHEMA_FILE;
1334   fsRWReq->numberOfPages = rr.noOfPages;
1335   fsRWReq->data.arrayOfPages.varIndex = rr.pageId + rr.firstPage;
1336   fsRWReq->data.arrayOfPages.fileOffset = rr.firstPage;
1337   sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 8, JBA);
1338 }//readSchemaFile()
1339 
readSchemaConf(Signal * signal,FsConnectRecordPtr fsPtr)1340 void Dbdict::readSchemaConf(Signal* signal,
1341                             FsConnectRecordPtr fsPtr)
1342 {
1343 /* ---------------------------------------------------------------- */
1344 // Verify the data read from disk
1345 /* ---------------------------------------------------------------- */
1346   bool crashInd;
1347   if (fsPtr.p->fsState == FsConnectRecord::READ_SCHEMA1) {
1348     jam();
1349     crashInd = false;
1350   } else {
1351     jam();
1352     crashInd = true;
1353   }//if
1354 
1355   ReadSchemaRecord & rr = c_readSchemaRecord;
1356   XSchemaFile * xsf = &c_schemaFile[rr.pageId != 0];
1357 
1358   if (rr.schemaReadState == ReadSchemaRecord::INITIAL_READ_HEAD) {
1359     jam();
1360     ndbrequire(rr.firstPage == 0);
1361     SchemaFile * sf = &xsf->schemaPage[0];
1362     Uint32 noOfPages;
1363     if (sf->NdbVersion < NDB_SF_VERSION_5_0_6) {
1364       jam();
1365       const Uint32 pageSize_old = 32 * 1024;
1366       noOfPages = pageSize_old / NDB_SF_PAGE_SIZE - 1;
1367     } else {
1368       noOfPages = sf->FileSize / NDB_SF_PAGE_SIZE - 1;
1369     }
1370     rr.schemaReadState = ReadSchemaRecord::INITIAL_READ;
1371     if (noOfPages != 0) {
1372       rr.firstPage = 1;
1373       rr.noOfPages = noOfPages;
1374       readSchemaFile(signal, fsPtr.p->filePtr, fsPtr.i);
1375       return;
1376     }
1377   }
1378 
1379   SchemaFile * sf0 = &xsf->schemaPage[0];
1380   xsf->noOfPages = sf0->FileSize / NDB_SF_PAGE_SIZE;
1381 
1382   if (sf0->NdbVersion < NDB_SF_VERSION_5_0_6 &&
1383       ! convertSchemaFileTo_5_0_6(xsf)) {
1384     jam();
1385     ndbrequire(! crashInd);
1386     ndbrequire(fsPtr.p->fsState == FsConnectRecord::READ_SCHEMA1);
1387     readSchemaRef(signal, fsPtr);
1388     return;
1389   }
1390 
1391   for (Uint32 n = 0; n < xsf->noOfPages; n++) {
1392     SchemaFile * sf = &xsf->schemaPage[n];
1393     bool ok = false;
1394     const char *reason;
1395     if (memcmp(sf->Magic, NDB_SF_MAGIC, sizeof(sf->Magic)) != 0)
1396     { jam(); reason = "magic code"; }
1397     else if (sf->FileSize == 0)
1398     { jam(); reason = "file size == 0"; }
1399     else if (sf->FileSize % NDB_SF_PAGE_SIZE != 0)
1400     { jam(); reason = "invalid size multiple"; }
1401     else if (sf->FileSize != sf0->FileSize)
1402     { jam(); reason = "invalid size"; }
1403     else if (sf->PageNumber != n)
1404     { jam(); reason = "invalid page number"; }
1405     else if (computeChecksum((Uint32*)sf, NDB_SF_PAGE_SIZE_IN_WORDS) != 0)
1406     { jam(); reason = "invalid checksum"; }
1407     else
1408       ok = true;
1409 
1410     if (!ok)
1411     {
1412       char reason_msg[128];
1413       snprintf(reason_msg, sizeof(reason_msg),
1414                "schema file corrupt, page %u (%s, "
1415                "sz=%u sz0=%u pn=%u)",
1416                n, reason, sf->FileSize, sf0->FileSize, sf->PageNumber);
1417       if (crashInd)
1418         progError(__LINE__, NDBD_EXIT_SR_SCHEMAFILE, reason_msg);
1419       ndbrequireErr(fsPtr.p->fsState == FsConnectRecord::READ_SCHEMA1,
1420                     NDBD_EXIT_SR_SCHEMAFILE);
1421       jam();
1422       infoEvent("primary %s, trying backup", reason_msg);
1423       readSchemaRef(signal, fsPtr);
1424       return;
1425     }
1426   }
1427 
1428   fsPtr.p->fsState = FsConnectRecord::CLOSE_READ_SCHEMA;
1429   closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
1430   return;
1431 }//Dbdict::readSchemaConf()
1432 
readSchemaRef(Signal * signal,FsConnectRecordPtr fsPtr)1433 void Dbdict::readSchemaRef(Signal* signal,
1434                            FsConnectRecordPtr fsPtr)
1435 {
1436   /**
1437    * First close corrupt file
1438    */
1439   fsPtr.p->fsState = FsConnectRecord::OPEN_READ_SCHEMA2;
1440   closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
1441   return;
1442 }
1443 
closeReadSchemaConf(Signal * signal,FsConnectRecordPtr fsPtr)1444 void Dbdict::closeReadSchemaConf(Signal* signal,
1445                                  FsConnectRecordPtr fsPtr)
1446 {
1447   c_fsConnectRecordPool.release(fsPtr);
1448   ReadSchemaRecord::SchemaReadState state = c_readSchemaRecord.schemaReadState;
1449   c_readSchemaRecord.schemaReadState = ReadSchemaRecord::IDLE;
1450 
1451   switch(state) {
1452   case ReadSchemaRecord::INITIAL_READ :
1453     jam();
1454     {
1455       // write back both copies
1456 
1457       ndbrequire(c_writeSchemaRecord.inUse == false);
1458       XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0 ];
1459       Uint32 noOfPages =
1460         (c_tableRecordPool.getSize() + NDB_SF_PAGE_ENTRIES - 1) /
1461         NDB_SF_PAGE_ENTRIES;
1462       resizeSchemaFile(xsf, noOfPages);
1463 
1464       c_writeSchemaRecord.inUse = true;
1465       c_writeSchemaRecord.pageId = c_schemaRecord.oldSchemaPage;
1466       c_writeSchemaRecord.newFile = true;
1467       c_writeSchemaRecord.firstPage = 0;
1468       c_writeSchemaRecord.noOfPages = xsf->noOfPages;
1469 
1470       c_writeSchemaRecord.m_callback.m_callbackFunction =
1471         safe_cast(&Dbdict::initSchemaFile_conf);
1472 
1473       startWriteSchemaFile(signal);
1474     }
1475     break;
1476 
1477   default :
1478     ndbrequire(false);
1479     break;
1480 
1481   }//switch
1482 }//Dbdict::closeReadSchemaConf()
1483 
1484 bool
convertSchemaFileTo_5_0_6(XSchemaFile * xsf)1485 Dbdict::convertSchemaFileTo_5_0_6(XSchemaFile * xsf)
1486 {
1487   const Uint32 pageSize_old = 32 * 1024;
1488   Uint32 page_old[pageSize_old >> 2];
1489   SchemaFile * sf_old = (SchemaFile *)page_old;
1490 
1491   if (xsf->noOfPages * NDB_SF_PAGE_SIZE != pageSize_old)
1492     return false;
1493   SchemaFile * sf0 = &xsf->schemaPage[0];
1494   memcpy(sf_old, sf0, pageSize_old);
1495 
1496   // init max number new pages needed
1497   xsf->noOfPages = (sf_old->NoOfTableEntries + NDB_SF_PAGE_ENTRIES - 1) /
1498                    NDB_SF_PAGE_ENTRIES;
1499   initSchemaFile(xsf, 0, xsf->noOfPages, true);
1500 
1501   Uint32 noOfPages = 1;
1502   Uint32 n, i, j;
1503   for (n = 0; n < xsf->noOfPages; n++) {
1504     jam();
1505     for (i = 0; i < NDB_SF_PAGE_ENTRIES; i++) {
1506       j = n * NDB_SF_PAGE_ENTRIES + i;
1507       if (j >= sf_old->NoOfTableEntries)
1508         continue;
1509       const SchemaFile::TableEntry_old & te_old = sf_old->TableEntries_old[j];
1510       if (te_old.m_tableState == SchemaFile::INIT ||
1511           te_old.m_tableState == SchemaFile::DROP_TABLE_COMMITTED ||
1512           te_old.m_noOfPages == 0)
1513         continue;
1514       SchemaFile * sf = &xsf->schemaPage[n];
1515       SchemaFile::TableEntry & te = sf->TableEntries[i];
1516       te.m_tableState = te_old.m_tableState;
1517       te.m_tableVersion = te_old.m_tableVersion;
1518       te.m_tableType = te_old.m_tableType;
1519       te.m_info_words = te_old.m_noOfPages * ZSIZE_OF_PAGES_IN_WORDS -
1520                         ZPAGE_HEADER_SIZE;
1521       te.m_gcp = te_old.m_gcp;
1522       if (noOfPages < n)
1523         noOfPages = n;
1524     }
1525   }
1526   xsf->noOfPages = noOfPages;
1527   initSchemaFile(xsf, 0, xsf->noOfPages, false);
1528 
1529   return true;
1530 }
1531 
1532 /* **************************************************************** */
1533 /* ---------------------------------------------------------------- */
1534 /* MODULE:          INITIALISATION MODULE ------------------------- */
1535 /* ---------------------------------------------------------------- */
1536 /*                                                                  */
1537 /* This module contains initialisation of data at start/restart.    */
1538 /* ---------------------------------------------------------------- */
1539 /* **************************************************************** */
1540 
Dbdict(Block_context & ctx)1541 Dbdict::Dbdict(Block_context& ctx):
1542   SimulatedBlock(DBDICT, ctx),
1543   c_attributeRecordHash(c_attributeRecordPool),
1544   c_file_hash(c_file_pool),
1545   c_filegroup_hash(c_filegroup_pool),
1546   c_obj_hash(c_obj_pool),
1547   c_opCreateTable(c_opRecordPool),
1548   c_opDropTable(c_opRecordPool),
1549   c_opCreateIndex(c_opRecordPool),
1550   c_opDropIndex(c_opRecordPool),
1551   c_opAlterIndex(c_opRecordPool),
1552   c_opBuildIndex(c_opRecordPool),
1553   c_opCreateEvent(c_opRecordPool),
1554   c_opSubEvent(c_opRecordPool),
1555   c_opDropEvent(c_opRecordPool),
1556   c_opSignalUtil(c_opRecordPool),
1557   c_opCreateTrigger(c_opRecordPool),
1558   c_opDropTrigger(c_opRecordPool),
1559   c_opAlterTrigger(c_opRecordPool),
1560   c_schemaOp(c_opRecordPool),
1561   c_Trans(c_opRecordPool),
1562   c_opCreateObj(c_schemaOp),
1563   c_opDropObj(c_schemaOp),
1564   c_opRecordSequence(0),
1565   c_dictLockQueue(c_dictLockPool),
1566   c_dictLockPoll(false)
1567 {
1568   BLOCK_CONSTRUCTOR(Dbdict);
1569 
1570   // Transit signals
1571   addRecSignal(GSN_DUMP_STATE_ORD, &Dbdict::execDUMP_STATE_ORD);
1572   addRecSignal(GSN_GET_TABINFOREQ, &Dbdict::execGET_TABINFOREQ);
1573   addRecSignal(GSN_GET_TABLEID_REQ, &Dbdict::execGET_TABLEDID_REQ);
1574   addRecSignal(GSN_GET_TABINFO_CONF, &Dbdict::execGET_TABINFO_CONF);
1575   addRecSignal(GSN_CONTINUEB, &Dbdict::execCONTINUEB);
1576 
1577   addRecSignal(GSN_CREATE_TABLE_REQ, &Dbdict::execCREATE_TABLE_REQ);
1578   addRecSignal(GSN_CREATE_TAB_REQ, &Dbdict::execCREATE_TAB_REQ);
1579   addRecSignal(GSN_CREATE_TAB_REF, &Dbdict::execCREATE_TAB_REF);
1580   addRecSignal(GSN_CREATE_TAB_CONF, &Dbdict::execCREATE_TAB_CONF);
1581   addRecSignal(GSN_CREATE_FRAGMENTATION_REF, &Dbdict::execCREATE_FRAGMENTATION_REF);
1582   addRecSignal(GSN_CREATE_FRAGMENTATION_CONF, &Dbdict::execCREATE_FRAGMENTATION_CONF);
1583   addRecSignal(GSN_DIADDTABCONF, &Dbdict::execDIADDTABCONF);
1584   addRecSignal(GSN_DIADDTABREF, &Dbdict::execDIADDTABREF);
1585   addRecSignal(GSN_ADD_FRAGREQ, &Dbdict::execADD_FRAGREQ);
1586   addRecSignal(GSN_TAB_COMMITCONF, &Dbdict::execTAB_COMMITCONF);
1587   addRecSignal(GSN_TAB_COMMITREF, &Dbdict::execTAB_COMMITREF);
1588   addRecSignal(GSN_ALTER_TABLE_REQ, &Dbdict::execALTER_TABLE_REQ);
1589   addRecSignal(GSN_ALTER_TAB_REQ, &Dbdict::execALTER_TAB_REQ);
1590   addRecSignal(GSN_ALTER_TAB_REF, &Dbdict::execALTER_TAB_REF);
1591   addRecSignal(GSN_ALTER_TAB_CONF, &Dbdict::execALTER_TAB_CONF);
1592 
1593   // Index signals
1594   addRecSignal(GSN_CREATE_INDX_REQ, &Dbdict::execCREATE_INDX_REQ);
1595   addRecSignal(GSN_CREATE_INDX_CONF, &Dbdict::execCREATE_INDX_CONF);
1596   addRecSignal(GSN_CREATE_INDX_REF, &Dbdict::execCREATE_INDX_REF);
1597 
1598   addRecSignal(GSN_ALTER_INDX_REQ, &Dbdict::execALTER_INDX_REQ);
1599   addRecSignal(GSN_ALTER_INDX_CONF, &Dbdict::execALTER_INDX_CONF);
1600   addRecSignal(GSN_ALTER_INDX_REF, &Dbdict::execALTER_INDX_REF);
1601 
1602   addRecSignal(GSN_CREATE_TABLE_CONF, &Dbdict::execCREATE_TABLE_CONF);
1603   addRecSignal(GSN_CREATE_TABLE_REF, &Dbdict::execCREATE_TABLE_REF);
1604 
1605   addRecSignal(GSN_DROP_INDX_REQ, &Dbdict::execDROP_INDX_REQ);
1606   addRecSignal(GSN_DROP_INDX_CONF, &Dbdict::execDROP_INDX_CONF);
1607   addRecSignal(GSN_DROP_INDX_REF, &Dbdict::execDROP_INDX_REF);
1608 
1609   addRecSignal(GSN_DROP_TABLE_CONF, &Dbdict::execDROP_TABLE_CONF);
1610   addRecSignal(GSN_DROP_TABLE_REF, &Dbdict::execDROP_TABLE_REF);
1611 
1612   addRecSignal(GSN_BUILDINDXREQ, &Dbdict::execBUILDINDXREQ);
1613   addRecSignal(GSN_BUILDINDXCONF, &Dbdict::execBUILDINDXCONF);
1614   addRecSignal(GSN_BUILDINDXREF, &Dbdict::execBUILDINDXREF);
1615 
1616   // Util signals
1617   addRecSignal(GSN_UTIL_PREPARE_CONF, &Dbdict::execUTIL_PREPARE_CONF);
1618   addRecSignal(GSN_UTIL_PREPARE_REF,  &Dbdict::execUTIL_PREPARE_REF);
1619 
1620   addRecSignal(GSN_UTIL_EXECUTE_CONF, &Dbdict::execUTIL_EXECUTE_CONF);
1621   addRecSignal(GSN_UTIL_EXECUTE_REF,  &Dbdict::execUTIL_EXECUTE_REF);
1622 
1623   addRecSignal(GSN_UTIL_RELEASE_CONF, &Dbdict::execUTIL_RELEASE_CONF);
1624   addRecSignal(GSN_UTIL_RELEASE_REF,  &Dbdict::execUTIL_RELEASE_REF);
1625 
1626   // Event signals
1627   addRecSignal(GSN_CREATE_EVNT_REQ,  &Dbdict::execCREATE_EVNT_REQ);
1628   addRecSignal(GSN_CREATE_EVNT_CONF, &Dbdict::execCREATE_EVNT_CONF);
1629   addRecSignal(GSN_CREATE_EVNT_REF,  &Dbdict::execCREATE_EVNT_REF);
1630 
1631   addRecSignal(GSN_CREATE_SUBID_CONF, &Dbdict::execCREATE_SUBID_CONF);
1632   addRecSignal(GSN_CREATE_SUBID_REF,  &Dbdict::execCREATE_SUBID_REF);
1633 
1634   addRecSignal(GSN_SUB_CREATE_CONF, &Dbdict::execSUB_CREATE_CONF);
1635   addRecSignal(GSN_SUB_CREATE_REF,  &Dbdict::execSUB_CREATE_REF);
1636 
1637   addRecSignal(GSN_SUB_START_REQ,  &Dbdict::execSUB_START_REQ);
1638   addRecSignal(GSN_SUB_START_CONF,  &Dbdict::execSUB_START_CONF);
1639   addRecSignal(GSN_SUB_START_REF,  &Dbdict::execSUB_START_REF);
1640 
1641   addRecSignal(GSN_SUB_STOP_REQ,  &Dbdict::execSUB_STOP_REQ);
1642   addRecSignal(GSN_SUB_STOP_CONF,  &Dbdict::execSUB_STOP_CONF);
1643   addRecSignal(GSN_SUB_STOP_REF,  &Dbdict::execSUB_STOP_REF);
1644 
1645   addRecSignal(GSN_DROP_EVNT_REQ,  &Dbdict::execDROP_EVNT_REQ);
1646 
1647   addRecSignal(GSN_SUB_REMOVE_REQ, &Dbdict::execSUB_REMOVE_REQ);
1648   addRecSignal(GSN_SUB_REMOVE_CONF, &Dbdict::execSUB_REMOVE_CONF);
1649   addRecSignal(GSN_SUB_REMOVE_REF,  &Dbdict::execSUB_REMOVE_REF);
1650 
1651   // Trigger signals
1652   addRecSignal(GSN_CREATE_TRIG_REQ, &Dbdict::execCREATE_TRIG_REQ);
1653   addRecSignal(GSN_CREATE_TRIG_CONF, &Dbdict::execCREATE_TRIG_CONF);
1654   addRecSignal(GSN_CREATE_TRIG_REF, &Dbdict::execCREATE_TRIG_REF);
1655   addRecSignal(GSN_ALTER_TRIG_REQ, &Dbdict::execALTER_TRIG_REQ);
1656   addRecSignal(GSN_ALTER_TRIG_CONF, &Dbdict::execALTER_TRIG_CONF);
1657   addRecSignal(GSN_ALTER_TRIG_REF, &Dbdict::execALTER_TRIG_REF);
1658   addRecSignal(GSN_DROP_TRIG_REQ, &Dbdict::execDROP_TRIG_REQ);
1659   addRecSignal(GSN_DROP_TRIG_CONF, &Dbdict::execDROP_TRIG_CONF);
1660   addRecSignal(GSN_DROP_TRIG_REF, &Dbdict::execDROP_TRIG_REF);
1661 
1662   // Received signals
1663   addRecSignal(GSN_HOT_SPAREREP, &Dbdict::execHOT_SPAREREP);
1664   addRecSignal(GSN_GET_SCHEMA_INFOREQ, &Dbdict::execGET_SCHEMA_INFOREQ);
1665   addRecSignal(GSN_SCHEMA_INFO, &Dbdict::execSCHEMA_INFO);
1666   addRecSignal(GSN_SCHEMA_INFOCONF, &Dbdict::execSCHEMA_INFOCONF);
1667   addRecSignal(GSN_DICTSTARTREQ, &Dbdict::execDICTSTARTREQ);
1668   addRecSignal(GSN_READ_NODESCONF, &Dbdict::execREAD_NODESCONF);
1669   addRecSignal(GSN_FSOPENCONF, &Dbdict::execFSOPENCONF);
1670   addRecSignal(GSN_FSOPENREF, &Dbdict::execFSOPENREF, true);
1671   addRecSignal(GSN_FSCLOSECONF, &Dbdict::execFSCLOSECONF);
1672   addRecSignal(GSN_FSWRITECONF, &Dbdict::execFSWRITECONF);
1673   addRecSignal(GSN_FSREADCONF, &Dbdict::execFSREADCONF);
1674   addRecSignal(GSN_FSREADREF, &Dbdict::execFSREADREF, true);
1675   addRecSignal(GSN_LQHFRAGCONF, &Dbdict::execLQHFRAGCONF);
1676   addRecSignal(GSN_LQHADDATTCONF, &Dbdict::execLQHADDATTCONF);
1677   addRecSignal(GSN_LQHADDATTREF, &Dbdict::execLQHADDATTREF);
1678   addRecSignal(GSN_LQHFRAGREF, &Dbdict::execLQHFRAGREF);
1679   addRecSignal(GSN_NDB_STTOR, &Dbdict::execNDB_STTOR);
1680   addRecSignal(GSN_READ_CONFIG_REQ, &Dbdict::execREAD_CONFIG_REQ, true);
1681   addRecSignal(GSN_STTOR, &Dbdict::execSTTOR);
1682   addRecSignal(GSN_TC_SCHVERCONF, &Dbdict::execTC_SCHVERCONF);
1683   addRecSignal(GSN_NODE_FAILREP, &Dbdict::execNODE_FAILREP);
1684   addRecSignal(GSN_INCL_NODEREQ, &Dbdict::execINCL_NODEREQ);
1685   addRecSignal(GSN_API_FAILREQ, &Dbdict::execAPI_FAILREQ);
1686 
1687   addRecSignal(GSN_WAIT_GCP_REF, &Dbdict::execWAIT_GCP_REF);
1688   addRecSignal(GSN_WAIT_GCP_CONF, &Dbdict::execWAIT_GCP_CONF);
1689 
1690   addRecSignal(GSN_LIST_TABLES_REQ, &Dbdict::execLIST_TABLES_REQ);
1691 
1692   addRecSignal(GSN_DROP_TABLE_REQ, &Dbdict::execDROP_TABLE_REQ);
1693 
1694   addRecSignal(GSN_PREP_DROP_TAB_REQ, &Dbdict::execPREP_DROP_TAB_REQ);
1695   addRecSignal(GSN_PREP_DROP_TAB_REF, &Dbdict::execPREP_DROP_TAB_REF);
1696   addRecSignal(GSN_PREP_DROP_TAB_CONF, &Dbdict::execPREP_DROP_TAB_CONF);
1697 
1698   addRecSignal(GSN_DROP_TAB_REQ, &Dbdict::execDROP_TAB_REQ);
1699   addRecSignal(GSN_DROP_TAB_REF, &Dbdict::execDROP_TAB_REF);
1700   addRecSignal(GSN_DROP_TAB_CONF, &Dbdict::execDROP_TAB_CONF);
1701 
1702   addRecSignal(GSN_CREATE_FILE_REQ, &Dbdict::execCREATE_FILE_REQ);
1703   addRecSignal(GSN_CREATE_FILEGROUP_REQ, &Dbdict::execCREATE_FILEGROUP_REQ);
1704 
1705   addRecSignal(GSN_DROP_FILE_REQ, &Dbdict::execDROP_FILE_REQ);
1706   addRecSignal(GSN_DROP_FILE_REF, &Dbdict::execDROP_FILE_REF);
1707   addRecSignal(GSN_DROP_FILE_CONF, &Dbdict::execDROP_FILE_CONF);
1708 
1709   addRecSignal(GSN_DROP_FILEGROUP_REQ, &Dbdict::execDROP_FILEGROUP_REQ);
1710   addRecSignal(GSN_DROP_FILEGROUP_REF, &Dbdict::execDROP_FILEGROUP_REF);
1711   addRecSignal(GSN_DROP_FILEGROUP_CONF, &Dbdict::execDROP_FILEGROUP_CONF);
1712 
1713   addRecSignal(GSN_CREATE_OBJ_REQ, &Dbdict::execCREATE_OBJ_REQ);
1714   addRecSignal(GSN_CREATE_OBJ_REF, &Dbdict::execCREATE_OBJ_REF);
1715   addRecSignal(GSN_CREATE_OBJ_CONF, &Dbdict::execCREATE_OBJ_CONF);
1716   addRecSignal(GSN_DROP_OBJ_REQ, &Dbdict::execDROP_OBJ_REQ);
1717   addRecSignal(GSN_DROP_OBJ_REF, &Dbdict::execDROP_OBJ_REF);
1718   addRecSignal(GSN_DROP_OBJ_CONF, &Dbdict::execDROP_OBJ_CONF);
1719 
1720   addRecSignal(GSN_CREATE_FILE_REF, &Dbdict::execCREATE_FILE_REF);
1721   addRecSignal(GSN_CREATE_FILE_CONF, &Dbdict::execCREATE_FILE_CONF);
1722   addRecSignal(GSN_CREATE_FILEGROUP_REF, &Dbdict::execCREATE_FILEGROUP_REF);
1723   addRecSignal(GSN_CREATE_FILEGROUP_CONF, &Dbdict::execCREATE_FILEGROUP_CONF);
1724 
1725   addRecSignal(GSN_BACKUP_FRAGMENT_REQ, &Dbdict::execBACKUP_FRAGMENT_REQ);
1726 
1727   addRecSignal(GSN_DICT_COMMIT_REQ, &Dbdict::execDICT_COMMIT_REQ);
1728   addRecSignal(GSN_DICT_COMMIT_REF, &Dbdict::execDICT_COMMIT_REF);
1729   addRecSignal(GSN_DICT_COMMIT_CONF, &Dbdict::execDICT_COMMIT_CONF);
1730 
1731   addRecSignal(GSN_DICT_ABORT_REQ, &Dbdict::execDICT_ABORT_REQ);
1732   addRecSignal(GSN_DICT_ABORT_REF, &Dbdict::execDICT_ABORT_REF);
1733   addRecSignal(GSN_DICT_ABORT_CONF, &Dbdict::execDICT_ABORT_CONF);
1734 
1735   addRecSignal(GSN_DICT_LOCK_REQ, &Dbdict::execDICT_LOCK_REQ);
1736   addRecSignal(GSN_DICT_UNLOCK_ORD, &Dbdict::execDICT_UNLOCK_ORD);
1737 }//Dbdict::Dbdict()
1738 
~Dbdict()1739 Dbdict::~Dbdict()
1740 {
1741 }//Dbdict::~Dbdict()
1742 
BLOCK_FUNCTIONS(Dbdict)1743 BLOCK_FUNCTIONS(Dbdict)
1744 
1745 void Dbdict::initCommonData()
1746 {
1747 /* ---------------------------------------------------------------- */
1748 // Initialise all common variables.
1749 /* ---------------------------------------------------------------- */
1750   initRetrieveRecord(0, 0, 0);
1751   initSchemaRecord();
1752   initRestartRecord();
1753   initSendSchemaRecord();
1754   initReadTableRecord();
1755   initWriteTableRecord();
1756   initReadSchemaRecord();
1757   initWriteSchemaRecord();
1758 
1759   c_masterNodeId = ZNIL;
1760   c_numberNode = 0;
1761   c_noNodesFailed = 0;
1762   c_failureNr = 0;
1763   c_blockState = BS_IDLE;
1764   c_packTable.m_state = PackTable::PTS_IDLE;
1765   c_startPhase = 0;
1766   c_restartType = 255; //Ensure not used restartType
1767   c_tabinfoReceived = 0;
1768   c_initialStart = false;
1769   c_systemRestart = false;
1770   c_initialNodeRestart = false;
1771   c_nodeRestart = false;
1772 }//Dbdict::initCommonData()
1773 
initRecords()1774 void Dbdict::initRecords()
1775 {
1776   initNodeRecords();
1777   initPageRecords();
1778   initTableRecords();
1779   initTriggerRecords();
1780 }//Dbdict::initRecords()
1781 
initSendSchemaRecord()1782 void Dbdict::initSendSchemaRecord()
1783 {
1784   c_sendSchemaRecord.noOfWords = (Uint32)-1;
1785   c_sendSchemaRecord.pageId = RNIL;
1786   c_sendSchemaRecord.noOfWordsCurrentlySent = 0;
1787   c_sendSchemaRecord.noOfSignalsSentSinceDelay = 0;
1788   c_sendSchemaRecord.inUse = false;
1789   //c_sendSchemaRecord.sendSchemaState = SendSchemaRecord::IDLE;
1790 }//initSendSchemaRecord()
1791 
initReadTableRecord()1792 void Dbdict::initReadTableRecord()
1793 {
1794   c_readTableRecord.no_of_words= 0;
1795   c_readTableRecord.pageId = RNIL;
1796   c_readTableRecord.tableId = ZNIL;
1797   c_readTableRecord.inUse = false;
1798 }//initReadTableRecord()
1799 
initWriteTableRecord()1800 void Dbdict::initWriteTableRecord()
1801 {
1802   c_writeTableRecord.no_of_words= 0;
1803   c_writeTableRecord.pageId = RNIL;
1804   c_writeTableRecord.noOfTableFilesHandled = 3;
1805   c_writeTableRecord.tableId = ZNIL;
1806   c_writeTableRecord.tableWriteState = WriteTableRecord::IDLE;
1807 }//initWriteTableRecord()
1808 
initReadSchemaRecord()1809 void Dbdict::initReadSchemaRecord()
1810 {
1811   c_readSchemaRecord.pageId = RNIL;
1812   c_readSchemaRecord.schemaReadState = ReadSchemaRecord::IDLE;
1813 }//initReadSchemaRecord()
1814 
initWriteSchemaRecord()1815 void Dbdict::initWriteSchemaRecord()
1816 {
1817   c_writeSchemaRecord.inUse = false;
1818   c_writeSchemaRecord.pageId = RNIL;
1819   c_writeSchemaRecord.noOfSchemaFilesHandled = 3;
1820 }//initWriteSchemaRecord()
1821 
initRetrieveRecord(Signal * signal,Uint32 i,Uint32 returnCode)1822 void Dbdict::initRetrieveRecord(Signal* signal, Uint32 i, Uint32 returnCode)
1823 {
1824   c_retrieveRecord.busyState = false;
1825   c_retrieveRecord.blockRef = 0;
1826   c_retrieveRecord.m_senderData = RNIL;
1827   c_retrieveRecord.tableId = RNIL;
1828   c_retrieveRecord.currentSent = 0;
1829   c_retrieveRecord.retrievedNoOfPages = 0;
1830   c_retrieveRecord.retrievedNoOfWords = 0;
1831   c_retrieveRecord.m_useLongSig = false;
1832 }//initRetrieveRecord()
1833 
initSchemaRecord()1834 void Dbdict::initSchemaRecord()
1835 {
1836   c_schemaRecord.schemaPage = RNIL;
1837   c_schemaRecord.oldSchemaPage = RNIL;
1838 }//Dbdict::initSchemaRecord()
1839 
initRestartRecord()1840 void Dbdict::initRestartRecord()
1841 {
1842   c_restartRecord.gciToRestart = 0;
1843   c_restartRecord.activeTable = ZNIL;
1844   c_restartRecord.m_pass = 0;
1845 }//Dbdict::initRestartRecord()
1846 
initNodeRecords()1847 void Dbdict::initNodeRecords()
1848 {
1849   jam();
1850   for (unsigned i = 1; i < MAX_NODES; i++) {
1851     NodeRecordPtr nodePtr;
1852     c_nodes.getPtr(nodePtr, i);
1853     nodePtr.p->hotSpare = false;
1854     nodePtr.p->nodeState = NodeRecord::API_NODE;
1855   }//for
1856 }//Dbdict::initNodeRecords()
1857 
initPageRecords()1858 void Dbdict::initPageRecords()
1859 {
1860   c_retrieveRecord.retrievePage =  ZMAX_PAGES_OF_TABLE_DEFINITION;
1861   ndbrequire(ZNUMBER_OF_PAGES >= (ZMAX_PAGES_OF_TABLE_DEFINITION + 1));
1862   c_schemaRecord.schemaPage = 0;
1863   c_schemaRecord.oldSchemaPage = NDB_SF_MAX_PAGES;
1864 }//Dbdict::initPageRecords()
1865 
initTableRecords()1866 void Dbdict::initTableRecords()
1867 {
1868   TableRecordPtr tablePtr;
1869   while (1) {
1870     jam();
1871     refresh_watch_dog();
1872     c_tableRecordPool.seize(tablePtr);
1873     if (tablePtr.i == RNIL) {
1874       jam();
1875       break;
1876     }//if
1877     initialiseTableRecord(tablePtr);
1878   }//while
1879 }//Dbdict::initTableRecords()
1880 
initialiseTableRecord(TableRecordPtr tablePtr)1881 void Dbdict::initialiseTableRecord(TableRecordPtr tablePtr)
1882 {
1883   new (tablePtr.p) TableRecord();
1884   tablePtr.p->activePage = RNIL;
1885   tablePtr.p->filePtr[0] = RNIL;
1886   tablePtr.p->filePtr[1] = RNIL;
1887   tablePtr.p->firstPage = RNIL;
1888   tablePtr.p->tableId = tablePtr.i;
1889   tablePtr.p->tableVersion = (Uint32)-1;
1890   tablePtr.p->tabState = TableRecord::NOT_DEFINED;
1891   tablePtr.p->tabReturnState = TableRecord::TRS_IDLE;
1892   tablePtr.p->fragmentType = DictTabInfo::AllNodesSmallTable;
1893   tablePtr.p->gciTableCreated = 0;
1894   tablePtr.p->noOfAttributes = ZNIL;
1895   tablePtr.p->noOfNullAttr = 0;
1896   tablePtr.p->fragmentCount = 0;
1897   /*
1898     tablePtr.p->lh3PageIndexBits = 0;
1899     tablePtr.p->lh3DistrBits = 0;
1900     tablePtr.p->lh3PageBits = 6;
1901   */
1902   tablePtr.p->kValue = 6;
1903   tablePtr.p->localKeyLen = 1;
1904   tablePtr.p->maxLoadFactor = 80;
1905   tablePtr.p->minLoadFactor = 70;
1906   tablePtr.p->noOfPrimkey = 1;
1907   tablePtr.p->tupKeyLength = 1;
1908   tablePtr.p->maxRowsLow = 0;
1909   tablePtr.p->maxRowsHigh = 0;
1910   tablePtr.p->defaultNoPartFlag = true;
1911   tablePtr.p->linearHashFlag = true;
1912   tablePtr.p->m_bits = 0;
1913   tablePtr.p->minRowsLow = 0;
1914   tablePtr.p->minRowsHigh = 0;
1915   tablePtr.p->singleUserMode = 0;
1916   tablePtr.p->tableType = DictTabInfo::UserTable;
1917   tablePtr.p->primaryTableId = RNIL;
1918   // volatile elements
1919   tablePtr.p->indexState = TableRecord::IS_UNDEFINED;
1920   tablePtr.p->insertTriggerId = RNIL;
1921   tablePtr.p->updateTriggerId = RNIL;
1922   tablePtr.p->deleteTriggerId = RNIL;
1923   tablePtr.p->customTriggerId = RNIL;
1924   tablePtr.p->buildTriggerId = RNIL;
1925   tablePtr.p->indexLocal = 0;
1926 }//Dbdict::initialiseTableRecord()
1927 
initTriggerRecords()1928 void Dbdict::initTriggerRecords()
1929 {
1930   TriggerRecordPtr triggerPtr;
1931   while (1) {
1932     jam();
1933     refresh_watch_dog();
1934     c_triggerRecordPool.seize(triggerPtr);
1935     if (triggerPtr.i == RNIL) {
1936       jam();
1937       break;
1938     }//if
1939     initialiseTriggerRecord(triggerPtr);
1940   }//while
1941 }
1942 
initialiseTriggerRecord(TriggerRecordPtr triggerPtr)1943 void Dbdict::initialiseTriggerRecord(TriggerRecordPtr triggerPtr)
1944 {
1945   new (triggerPtr.p) TriggerRecord();
1946   triggerPtr.p->triggerState = TriggerRecord::TS_NOT_DEFINED;
1947   triggerPtr.p->triggerLocal = 0;
1948   triggerPtr.p->triggerId = RNIL;
1949   triggerPtr.p->tableId = RNIL;
1950   triggerPtr.p->triggerType = (TriggerType::Value)~0;
1951   triggerPtr.p->triggerActionTime = (TriggerActionTime::Value)~0;
1952   triggerPtr.p->triggerEvent = (TriggerEvent::Value)~0;
1953   triggerPtr.p->monitorReplicas = false;
1954   triggerPtr.p->monitorAllAttributes = false;
1955   triggerPtr.p->attributeMask.clear();
1956   triggerPtr.p->indexId = RNIL;
1957 }
1958 
getFsConnRecord()1959 Uint32 Dbdict::getFsConnRecord()
1960 {
1961   FsConnectRecordPtr fsPtr;
1962   c_fsConnectRecordPool.seize(fsPtr);
1963   ndbrequire(fsPtr.i != RNIL);
1964   fsPtr.p->filePtr = (Uint32)-1;
1965   fsPtr.p->ownerPtr = RNIL;
1966   fsPtr.p->fsState = FsConnectRecord::IDLE;
1967   return fsPtr.i;
1968 }//Dbdict::getFsConnRecord()
1969 
1970 /*
1971  * Search schemafile for free entry.  Its index is used as 'logical id'
1972  * of new disk-stored object.
1973  */
getFreeObjId(Uint32 minId)1974 Uint32 Dbdict::getFreeObjId(Uint32 minId)
1975 {
1976   const XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
1977   Uint32 noOfPages = xsf->noOfPages;
1978   Uint32 n, i;
1979   for (n = 0; n < noOfPages; n++) {
1980     jam();
1981     const SchemaFile * sf = &xsf->schemaPage[n];
1982     for (i = 0; i < NDB_SF_PAGE_ENTRIES; i++) {
1983       const SchemaFile::TableEntry& te = sf->TableEntries[i];
1984       if (te.m_tableState == (Uint32)SchemaFile::INIT ||
1985           te.m_tableState == (Uint32)SchemaFile::DROP_TABLE_COMMITTED) {
1986         // minId is obsolete anyway
1987         if (minId <= n * NDB_SF_PAGE_ENTRIES + i)
1988           return n * NDB_SF_PAGE_ENTRIES + i;
1989       }
1990     }
1991   }
1992   return RNIL;
1993 }
1994 
getFreeTableRecord(Uint32 primaryTableId)1995 Uint32 Dbdict::getFreeTableRecord(Uint32 primaryTableId)
1996 {
1997   Uint32 minId = (primaryTableId == RNIL ? 0 : primaryTableId + 1);
1998   Uint32 i = getFreeObjId(minId);
1999   if (i == RNIL) {
2000     jam();
2001     return RNIL;
2002   }
2003   if (i >= c_tableRecordPool.getSize()) {
2004     jam();
2005     return RNIL;
2006   }
2007   TableRecordPtr tablePtr;
2008   c_tableRecordPool.getPtr(tablePtr, i);
2009   ndbrequire(tablePtr.p->tabState == TableRecord::NOT_DEFINED);
2010   initialiseTableRecord(tablePtr);
2011   tablePtr.p->tabState = TableRecord::DEFINING;
2012   return i;
2013 }
2014 
getFreeTriggerRecord()2015 Uint32 Dbdict::getFreeTriggerRecord()
2016 {
2017   const Uint32 size = c_triggerRecordPool.getSize();
2018   TriggerRecordPtr triggerPtr;
2019   for (triggerPtr.i = 0; triggerPtr.i < size; triggerPtr.i++) {
2020     jam();
2021     c_triggerRecordPool.getPtr(triggerPtr);
2022     if (triggerPtr.p->triggerState == TriggerRecord::TS_NOT_DEFINED) {
2023       jam();
2024       initialiseTriggerRecord(triggerPtr);
2025       return triggerPtr.i;
2026     }
2027   }
2028   return RNIL;
2029 }
2030 
2031 /* **************************************************************** */
2032 /* ---------------------------------------------------------------- */
2033 /* MODULE:          START/RESTART HANDLING ------------------------ */
2034 /* ---------------------------------------------------------------- */
2035 /*                                                                  */
2036 /* This module contains the code that is common for all             */
2037 /* start/restart types.                                             */
2038 /* ---------------------------------------------------------------- */
2039 /* **************************************************************** */
2040 
2041 /* ---------------------------------------------------------------- */
2042 // This is sent as the first signal during start/restart.
2043 /* ---------------------------------------------------------------- */
execSTTOR(Signal * signal)2044 void Dbdict::execSTTOR(Signal* signal)
2045 {
2046   jamEntry();
2047   c_startPhase = signal->theData[1];
2048   switch (c_startPhase) {
2049   case 1:
2050     break;
2051   case 3:
2052     c_restartType = signal->theData[7];         /* valid if 3 */
2053     ndbrequire(c_restartType == NodeState::ST_INITIAL_START ||
2054                c_restartType == NodeState::ST_SYSTEM_RESTART ||
2055                c_restartType == NodeState::ST_INITIAL_NODE_RESTART ||
2056                c_restartType == NodeState::ST_NODE_RESTART);
2057     break;
2058   }
2059   sendSTTORRY(signal);
2060 }//execSTTOR()
2061 
sendSTTORRY(Signal * signal)2062 void Dbdict::sendSTTORRY(Signal* signal)
2063 {
2064   signal->theData[0] = 0;       /* garbage SIGNAL KEY */
2065   signal->theData[1] = 0;       /* garbage SIGNAL VERSION NUMBER  */
2066   signal->theData[2] = 0;       /* garbage */
2067   signal->theData[3] = 1;       /* first wanted start phase */
2068   signal->theData[4] = 3;       /* get type of start */
2069   signal->theData[5] = ZNOMOREPHASES;
2070   sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 6, JBB);
2071 }
2072 
2073 /* ---------------------------------------------------------------- */
2074 // We receive information about sizes of records.
2075 /* ---------------------------------------------------------------- */
execREAD_CONFIG_REQ(Signal * signal)2076 void Dbdict::execREAD_CONFIG_REQ(Signal* signal)
2077 {
2078   const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
2079   Uint32 ref = req->senderRef;
2080   Uint32 senderData = req->senderData;
2081   ndbrequire(req->noOfParameters == 0);
2082 
2083   jamEntry();
2084 
2085   const ndb_mgm_configuration_iterator * p =
2086     m_ctx.m_config.getOwnConfigIterator();
2087   ndbrequire(p != 0);
2088 
2089   Uint32 attributesize, tablerecSize;
2090   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_TRIGGERS,
2091 					&c_maxNoOfTriggers));
2092   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DICT_ATTRIBUTE,&attributesize));
2093   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DICT_TABLE, &tablerecSize));
2094 
2095   c_attributeRecordPool.setSize(attributesize);
2096   c_attributeRecordHash.setSize(64);
2097   c_fsConnectRecordPool.setSize(ZFS_CONNECT_SIZE);
2098   c_nodes.setSize(MAX_NODES);
2099   c_pageRecordArray.setSize(ZNUMBER_OF_PAGES);
2100   c_schemaPageRecordArray.setSize(2 * NDB_SF_MAX_PAGES);
2101   c_tableRecordPool.setSize(tablerecSize);
2102   g_key_descriptor_pool.setSize(tablerecSize);
2103   c_triggerRecordPool.setSize(c_maxNoOfTriggers);
2104 
2105   c_obj_pool.setSize(tablerecSize+c_maxNoOfTriggers);
2106   c_obj_hash.setSize((tablerecSize+c_maxNoOfTriggers+1)/2);
2107 
2108   Pool_context pc;
2109   pc.m_block = this;
2110 
2111   c_file_hash.setSize(16);
2112   c_filegroup_hash.setSize(16);
2113 
2114   c_file_pool.init(RT_DBDICT_FILE, pc);
2115   c_filegroup_pool.init(RT_DBDICT_FILEGROUP, pc);
2116 
2117   c_opRecordPool.setSize(256);   // XXX need config params
2118   c_opCreateTable.setSize(8);
2119   c_opDropTable.setSize(8);
2120   c_opCreateIndex.setSize(8);
2121   c_opCreateEvent.setSize(2);
2122   c_opSubEvent.setSize(2);
2123   c_opDropEvent.setSize(2);
2124   c_opSignalUtil.setSize(8);
2125   c_opDropIndex.setSize(8);
2126   c_opAlterIndex.setSize(8);
2127   c_opBuildIndex.setSize(8);
2128   c_opCreateTrigger.setSize(8);
2129   c_opDropTrigger.setSize(8);
2130   c_opAlterTrigger.setSize(8);
2131 
2132   c_dictLockPool.setSize(32);
2133 
2134   // Initialize schema file copies
2135   c_schemaFile[0].schemaPage =
2136     (SchemaFile*)c_schemaPageRecordArray.getPtr(0 * NDB_SF_MAX_PAGES);
2137   c_schemaFile[0].noOfPages = 0;
2138   c_schemaFile[1].schemaPage =
2139     (SchemaFile*)c_schemaPageRecordArray.getPtr(1 * NDB_SF_MAX_PAGES);
2140   c_schemaFile[1].noOfPages = 0;
2141 
2142   c_schemaOp.setSize(8);
2143   //c_opDropObj.setSize(8);
2144   c_Trans.setSize(8);
2145 
2146   Uint32 rps = 0;
2147   rps += tablerecSize * (MAX_TAB_NAME_SIZE + MAX_FRM_DATA_SIZE);
2148   rps += attributesize * (MAX_ATTR_NAME_SIZE + MAX_ATTR_DEFAULT_VALUE_SIZE);
2149   rps += c_maxNoOfTriggers * MAX_TAB_NAME_SIZE;
2150   rps += (10 + 10) * MAX_TAB_NAME_SIZE;
2151 
2152   Uint32 sm = 5;
2153   ndb_mgm_get_int_parameter(p, CFG_DB_STRING_MEMORY, &sm);
2154   if (sm == 0)
2155     sm = 5;
2156 
2157   Uint32 sb = 0;
2158   if (sm < 100)
2159   {
2160     sb = (rps * sm) / 100;
2161   }
2162   else
2163   {
2164     sb = sm;
2165   }
2166 
2167   c_rope_pool.setSize(sb/28 + 100);
2168 
2169   // Initialize BAT for interface to file system
2170   NewVARIABLE* bat = allocateBat(2);
2171   bat[0].WA = &c_schemaPageRecordArray.getPtr(0)->word[0];
2172   bat[0].nrr = 2 * NDB_SF_MAX_PAGES;
2173   bat[0].ClusterSize = NDB_SF_PAGE_SIZE;
2174   bat[0].bits.q = NDB_SF_PAGE_SIZE_IN_WORDS_LOG2;
2175   bat[0].bits.v = 5;  // 32 bits per element
2176   bat[1].WA = &c_pageRecordArray.getPtr(0)->word[0];
2177   bat[1].nrr = ZNUMBER_OF_PAGES;
2178   bat[1].ClusterSize = ZSIZE_OF_PAGES_IN_WORDS * 4;
2179   bat[1].bits.q = ZLOG_SIZE_OF_PAGES_IN_WORDS; // 2**13 = 8192 elements
2180   bat[1].bits.v = 5;  // 32 bits per element
2181 
2182   initCommonData();
2183   initRecords();
2184 
2185   ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
2186   conf->senderRef = reference();
2187   conf->senderData = senderData;
2188   sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
2189 	     ReadConfigConf::SignalLength, JBB);
2190 
2191   {
2192     Ptr<DictObject> ptr;
2193     SLList<DictObject> objs(c_obj_pool);
2194     while(objs.seize(ptr))
2195       new (ptr.p) DictObject();
2196     objs.release();
2197   }
2198 }//execSIZEALT_REP()
2199 
2200 /* ---------------------------------------------------------------- */
2201 // Start phase signals sent by CNTR. We reply with NDB_STTORRY when
2202 // we completed this phase.
2203 /* ---------------------------------------------------------------- */
execNDB_STTOR(Signal * signal)2204 void Dbdict::execNDB_STTOR(Signal* signal)
2205 {
2206   jamEntry();
2207   c_startPhase = signal->theData[2];
2208   const Uint32 restartType = signal->theData[3];
2209   if (restartType == NodeState::ST_INITIAL_START) {
2210     jam();
2211     c_initialStart = true;
2212   } else if (restartType == NodeState::ST_SYSTEM_RESTART) {
2213     jam();
2214     c_systemRestart = true;
2215   } else if (restartType == NodeState::ST_INITIAL_NODE_RESTART) {
2216     jam();
2217     c_initialNodeRestart = true;
2218   } else if (restartType == NodeState::ST_NODE_RESTART) {
2219     jam();
2220     c_nodeRestart = true;
2221   } else {
2222     ndbrequire(false);
2223   }//if
2224   switch (c_startPhase) {
2225   case 1:
2226     jam();
2227     initSchemaFile(signal);
2228     break;
2229   case 3:
2230     jam();
2231     signal->theData[0] = reference();
2232     sendSignal(NDBCNTR_REF, GSN_READ_NODESREQ, signal, 1, JBB);
2233     break;
2234   case 6:
2235     jam();
2236     c_initialStart = false;
2237     c_systemRestart = false;
2238     c_initialNodeRestart = false;
2239     c_nodeRestart = false;
2240     sendNDB_STTORRY(signal);
2241     break;
2242   case 7:
2243     // uses c_restartType
2244     if(restartType == NodeState::ST_SYSTEM_RESTART &&
2245        c_masterNodeId == getOwnNodeId()){
2246       rebuildIndexes(signal, 0);
2247       return;
2248     }
2249     sendNDB_STTORRY(signal);
2250     break;
2251   default:
2252     jam();
2253     sendNDB_STTORRY(signal);
2254     break;
2255   }//switch
2256 }//execNDB_STTOR()
2257 
sendNDB_STTORRY(Signal * signal)2258 void Dbdict::sendNDB_STTORRY(Signal* signal)
2259 {
2260   signal->theData[0] = reference();
2261   sendSignal(NDBCNTR_REF, GSN_NDB_STTORRY, signal, 1, JBB);
2262   return;
2263 }//sendNDB_STTORRY()
2264 
2265 /* ---------------------------------------------------------------- */
2266 // We receive the information about which nodes that are up and down.
2267 /* ---------------------------------------------------------------- */
execREAD_NODESCONF(Signal * signal)2268 void Dbdict::execREAD_NODESCONF(Signal* signal)
2269 {
2270   jamEntry();
2271 
2272   ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
2273   c_numberNode   = readNodes->noOfNodes;
2274   c_masterNodeId = readNodes->masterNodeId;
2275 
2276   c_noNodesFailed = 0;
2277   c_aliveNodes.clear();
2278   for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
2279     jam();
2280     NodeRecordPtr nodePtr;
2281     c_nodes.getPtr(nodePtr, i);
2282 
2283     if (NodeBitmask::get(readNodes->allNodes, i)) {
2284       jam();
2285       nodePtr.p->nodeState = NodeRecord::NDB_NODE_ALIVE;
2286       if (NodeBitmask::get(readNodes->inactiveNodes, i)) {
2287 	jam();
2288 	/**-------------------------------------------------------------------
2289 	 *
2290 	 * THIS NODE IS DEFINED IN THE CLUSTER BUT IS NOT ALIVE CURRENTLY.
2291 	 * WE ADD THE NODE TO THE SET OF FAILED NODES AND ALSO SET THE
2292 	 * BLOCKSTATE TO BUSY TO AVOID ADDING TABLES WHILE NOT ALL NODES ARE
2293 	 * ALIVE.
2294 	 *------------------------------------------------------------------*/
2295         nodePtr.p->nodeState = NodeRecord::NDB_NODE_DEAD;
2296 	c_noNodesFailed++;
2297       } else {
2298 	c_aliveNodes.set(i);
2299       }
2300     }//if
2301   }//for
2302   sendNDB_STTORRY(signal);
2303 }//execREAD_NODESCONF()
2304 
2305 /* ---------------------------------------------------------------- */
2306 // HOT_SPAREREP informs DBDICT about which nodes that have become
2307 // hot spare nodes.
2308 /* ---------------------------------------------------------------- */
execHOT_SPAREREP(Signal * signal)2309 void Dbdict::execHOT_SPAREREP(Signal* signal)
2310 {
2311   Uint32 hotSpareNodes = 0;
2312   jamEntry();
2313   HotSpareRep * const hotSpare = (HotSpareRep*)&signal->theData[0];
2314   for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
2315     if (NodeBitmask::get(hotSpare->theHotSpareNodes, i)) {
2316       NodeRecordPtr nodePtr;
2317       c_nodes.getPtr(nodePtr, i);
2318       nodePtr.p->hotSpare = true;
2319       hotSpareNodes++;
2320     }//if
2321   }//for
2322   ndbrequire(hotSpareNodes == hotSpare->noHotSpareNodes);
2323   c_noHotSpareNodes = hotSpareNodes;
2324   return;
2325 }//execHOT_SPAREREP()
2326 
initSchemaFile(Signal * signal)2327 void Dbdict::initSchemaFile(Signal* signal)
2328 {
2329   XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
2330   xsf->noOfPages = (c_tableRecordPool.getSize() + NDB_SF_PAGE_ENTRIES - 1)
2331                    / NDB_SF_PAGE_ENTRIES;
2332   initSchemaFile(xsf, 0, xsf->noOfPages, true);
2333   // init alt copy too for INR
2334   XSchemaFile * oldxsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0];
2335   oldxsf->noOfPages = xsf->noOfPages;
2336   memcpy(&oldxsf->schemaPage[0], &xsf->schemaPage[0], xsf->schemaPage[0].FileSize);
2337 
2338   if (c_initialStart || c_initialNodeRestart) {
2339     jam();
2340     ndbrequire(c_writeSchemaRecord.inUse == false);
2341     c_writeSchemaRecord.inUse = true;
2342     c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
2343     c_writeSchemaRecord.newFile = true;
2344     c_writeSchemaRecord.firstPage = 0;
2345     c_writeSchemaRecord.noOfPages = xsf->noOfPages;
2346 
2347     c_writeSchemaRecord.m_callback.m_callbackFunction =
2348       safe_cast(&Dbdict::initSchemaFile_conf);
2349 
2350     startWriteSchemaFile(signal);
2351   } else if (c_systemRestart || c_nodeRestart) {
2352     jam();
2353     ndbrequire(c_readSchemaRecord.schemaReadState == ReadSchemaRecord::IDLE);
2354     c_readSchemaRecord.pageId = c_schemaRecord.oldSchemaPage;
2355     c_readSchemaRecord.firstPage = 0;
2356     c_readSchemaRecord.noOfPages = 1;
2357     c_readSchemaRecord.schemaReadState = ReadSchemaRecord::INITIAL_READ_HEAD;
2358     startReadSchemaFile(signal);
2359   } else {
2360     ndbrequire(false);
2361   }//if
2362 }//Dbdict::initSchemaFile()
2363 
2364 void
initSchemaFile_conf(Signal * signal,Uint32 callbackData,Uint32 rv)2365 Dbdict::initSchemaFile_conf(Signal* signal, Uint32 callbackData, Uint32 rv){
2366   jam();
2367   sendNDB_STTORRY(signal);
2368 }
2369 
2370 void
activateIndexes(Signal * signal,Uint32 i)2371 Dbdict::activateIndexes(Signal* signal, Uint32 i)
2372 {
2373   AlterIndxReq* req = (AlterIndxReq*)signal->getDataPtrSend();
2374   TableRecordPtr tablePtr;
2375   for (; i < c_tableRecordPool.getSize(); i++) {
2376     tablePtr.i = i;
2377     c_tableRecordPool.getPtr(tablePtr);
2378     if (tablePtr.p->tabState != TableRecord::DEFINED)
2379       continue;
2380     if (! tablePtr.p->isIndex())
2381       continue;
2382     jam();
2383     req->setUserRef(reference());
2384     req->setConnectionPtr(i);
2385     req->setTableId(tablePtr.p->primaryTableId);
2386     req->setIndexId(tablePtr.i);
2387     req->setIndexVersion(tablePtr.p->tableVersion);
2388     req->setOnline(true);
2389     if (c_restartType == NodeState::ST_SYSTEM_RESTART) {
2390       if (c_masterNodeId != getOwnNodeId())
2391         continue;
2392       // from file index state is not defined currently
2393       req->setRequestType(AlterIndxReq::RT_SYSTEMRESTART);
2394       req->addRequestFlag((Uint32)RequestFlag::RF_NOBUILD);
2395     }
2396     else if (
2397         c_restartType == NodeState::ST_NODE_RESTART ||
2398         c_restartType == NodeState::ST_INITIAL_NODE_RESTART) {
2399       // from master index must be online
2400       if (tablePtr.p->indexState != TableRecord::IS_ONLINE)
2401         continue;
2402       req->setRequestType(AlterIndxReq::RT_NODERESTART);
2403       // activate locally, rebuild not needed
2404       req->addRequestFlag((Uint32)RequestFlag::RF_LOCAL);
2405       req->addRequestFlag((Uint32)RequestFlag::RF_NOBUILD);
2406     } else {
2407       ndbrequire(false);
2408     }
2409     sendSignal(reference(), GSN_ALTER_INDX_REQ,
2410       signal, AlterIndxReq::SignalLength, JBB);
2411     return;
2412   }
2413   signal->theData[0] = reference();
2414   sendSignal(c_restartRecord.returnBlockRef, GSN_DICTSTARTCONF,
2415 	     signal, 1, JBB);
2416 }
2417 
2418 void
rebuildIndexes(Signal * signal,Uint32 i)2419 Dbdict::rebuildIndexes(Signal* signal, Uint32 i){
2420   BuildIndxReq* const req = (BuildIndxReq*)signal->getDataPtrSend();
2421 
2422   TableRecordPtr indexPtr;
2423   for (; i < c_tableRecordPool.getSize(); i++) {
2424     indexPtr.i = i;
2425     c_tableRecordPool.getPtr(indexPtr);
2426     if (indexPtr.p->tabState != TableRecord::DEFINED)
2427       continue;
2428     if (! indexPtr.p->isIndex())
2429       continue;
2430 
2431     jam();
2432 
2433     req->setUserRef(reference());
2434     req->setConnectionPtr(i);
2435     req->setRequestType(BuildIndxReq::RT_SYSTEMRESTART);
2436     req->setBuildId(0);   // not used
2437     req->setBuildKey(0);  // not used
2438     req->setIndexType(indexPtr.p->tableType);
2439     req->setIndexId(indexPtr.i);
2440     req->setTableId(indexPtr.p->primaryTableId);
2441     req->setParallelism(16);
2442 
2443     // from file index state is not defined currently
2444     if (indexPtr.p->m_bits & TableRecord::TR_Logged) {
2445       // rebuild not needed
2446       req->addRequestFlag((Uint32)RequestFlag::RF_NOBUILD);
2447     }
2448 
2449     // send
2450     sendSignal(reference(), GSN_BUILDINDXREQ,
2451 	       signal, BuildIndxReq::SignalLength, JBB);
2452     return;
2453   }
2454   sendNDB_STTORRY(signal);
2455 }
2456 
2457 
2458 /* **************************************************************** */
2459 /* ---------------------------------------------------------------- */
2460 /* MODULE:          SYSTEM RESTART MODULE ------------------------- */
2461 /* ---------------------------------------------------------------- */
2462 /*                                                                  */
2463 /* This module contains code specific for system restart            */
2464 /* ---------------------------------------------------------------- */
2465 /* **************************************************************** */
2466 
2467 /* ---------------------------------------------------------------- */
2468 // DIH asks DICT to read in table data from disk during system
2469 // restart. DIH also asks DICT to send information about which
2470 // tables that should be started as part of this system restart.
2471 // DICT will also activate the tables in TC as part of this process.
2472 /* ---------------------------------------------------------------- */
execDICTSTARTREQ(Signal * signal)2473 void Dbdict::execDICTSTARTREQ(Signal* signal)
2474 {
2475   jamEntry();
2476   c_restartRecord.gciToRestart = signal->theData[0];
2477   c_restartRecord.returnBlockRef = signal->theData[1];
2478   if (c_nodeRestart || c_initialNodeRestart) {
2479     jam();
2480 
2481     CRASH_INSERTION(6000);
2482 
2483     BlockReference dictRef = calcDictBlockRef(c_masterNodeId);
2484     signal->theData[0] = getOwnNodeId();
2485     sendSignal(dictRef, GSN_GET_SCHEMA_INFOREQ, signal, 1, JBB);
2486     return;
2487   }
2488   ndbrequire(c_systemRestart);
2489   ndbrequire(c_masterNodeId == getOwnNodeId());
2490 
2491   c_schemaRecord.m_callback.m_callbackData = 0;
2492   c_schemaRecord.m_callback.m_callbackFunction =
2493     safe_cast(&Dbdict::masterRestart_checkSchemaStatusComplete);
2494 
2495   c_restartRecord.m_pass = 0;
2496   c_restartRecord.activeTable = 0;
2497   c_schemaRecord.schemaPage = c_schemaRecord.oldSchemaPage; // ugly
2498   checkSchemaStatus(signal);
2499 }//execDICTSTARTREQ()
2500 
2501 void
masterRestart_checkSchemaStatusComplete(Signal * signal,Uint32 callbackData,Uint32 returnCode)2502 Dbdict::masterRestart_checkSchemaStatusComplete(Signal* signal,
2503 						Uint32 callbackData,
2504 						Uint32 returnCode){
2505 
2506   c_schemaRecord.schemaPage = 0; // ugly
2507   XSchemaFile * oldxsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0];
2508   ndbrequire(oldxsf->noOfPages != 0);
2509 
2510   LinearSectionPtr ptr[3];
2511   ptr[0].p = (Uint32*)&oldxsf->schemaPage[0];
2512   ptr[0].sz = oldxsf->noOfPages * NDB_SF_PAGE_SIZE_IN_WORDS;
2513 
2514   c_sendSchemaRecord.m_SCHEMAINFO_Counter = c_aliveNodes;
2515   NodeReceiverGroup rg(DBDICT, c_aliveNodes);
2516 
2517   rg.m_nodes.clear(getOwnNodeId());
2518   Callback c = { 0, 0 };
2519   sendFragmentedSignal(rg,
2520 		       GSN_SCHEMA_INFO,
2521 		       signal,
2522 		       1, //SchemaInfo::SignalLength,
2523 		       JBB,
2524 		       ptr,
2525 		       1,
2526 		       c);
2527 
2528   XSchemaFile * newxsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
2529   newxsf->noOfPages = oldxsf->noOfPages;
2530   memcpy(&newxsf->schemaPage[0], &oldxsf->schemaPage[0],
2531          oldxsf->noOfPages * NDB_SF_PAGE_SIZE);
2532 
2533   signal->theData[0] = getOwnNodeId();
2534   sendSignal(reference(), GSN_SCHEMA_INFOCONF, signal, 1, JBB);
2535 }
2536 
2537 void
execGET_SCHEMA_INFOREQ(Signal * signal)2538 Dbdict::execGET_SCHEMA_INFOREQ(Signal* signal){
2539 
2540   const Uint32 ref = signal->getSendersBlockRef();
2541   //const Uint32 senderData = signal->theData[0];
2542 
2543   ndbrequire(c_sendSchemaRecord.inUse == false);
2544   c_sendSchemaRecord.inUse = true;
2545 
2546   LinearSectionPtr ptr[3];
2547 
2548   XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
2549   ndbrequire(xsf->noOfPages != 0);
2550 
2551   ptr[0].p = (Uint32*)&xsf->schemaPage[0];
2552   ptr[0].sz = xsf->noOfPages * NDB_SF_PAGE_SIZE_IN_WORDS;
2553 
2554   Callback c = { safe_cast(&Dbdict::sendSchemaComplete), 0 };
2555   sendFragmentedSignal(ref,
2556 		       GSN_SCHEMA_INFO,
2557 		       signal,
2558 		       1, //GetSchemaInfoConf::SignalLength,
2559 		       JBB,
2560 		       ptr,
2561 		       1,
2562 		       c);
2563 }//Dbdict::execGET_SCHEMA_INFOREQ()
2564 
2565 void
sendSchemaComplete(Signal * signal,Uint32 callbackData,Uint32 returnCode)2566 Dbdict::sendSchemaComplete(Signal * signal,
2567 			   Uint32 callbackData,
2568 			   Uint32 returnCode){
2569   ndbrequire(c_sendSchemaRecord.inUse == true);
2570   c_sendSchemaRecord.inUse = false;
2571 
2572 }
2573 
2574 
2575 /* ---------------------------------------------------------------- */
2576 // We receive the schema info from master as part of all restarts
2577 // except the initial start where no tables exists.
2578 /* ---------------------------------------------------------------- */
execSCHEMA_INFO(Signal * signal)2579 void Dbdict::execSCHEMA_INFO(Signal* signal)
2580 {
2581   jamEntry();
2582   if(!assembleFragments(signal)){
2583     jam();
2584     return;
2585   }
2586 
2587   if(getNodeState().getNodeRestartInProgress()){
2588     CRASH_INSERTION(6001);
2589   }
2590 
2591   SegmentedSectionPtr schemaDataPtr;
2592   signal->getSection(schemaDataPtr, 0);
2593 
2594   XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
2595   ndbrequire(schemaDataPtr.sz % NDB_SF_PAGE_SIZE_IN_WORDS == 0);
2596   xsf->noOfPages = schemaDataPtr.sz / NDB_SF_PAGE_SIZE_IN_WORDS;
2597   copy((Uint32*)&xsf->schemaPage[0], schemaDataPtr);
2598   releaseSections(signal);
2599 
2600   SchemaFile * sf0 = &xsf->schemaPage[0];
2601   if (sf0->NdbVersion < NDB_SF_VERSION_5_0_6) {
2602     bool ok = convertSchemaFileTo_5_0_6(xsf);
2603     ndbrequire(ok);
2604   }
2605 
2606   validateChecksum(xsf);
2607 
2608   XSchemaFile * oldxsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0];
2609   resizeSchemaFile(xsf, oldxsf->noOfPages);
2610 
2611   ndbrequire(signal->getSendersBlockRef() != reference());
2612 
2613   /* ---------------------------------------------------------------- */
2614   // Synchronise our view on data with other nodes in the cluster.
2615   // This is an important part of restart handling where we will handle
2616   // cases where the table have been added but only partially, where
2617   // tables have been deleted but not completed the deletion yet and
2618   // other scenarios needing synchronisation.
2619   /* ---------------------------------------------------------------- */
2620   c_schemaRecord.m_callback.m_callbackData = 0;
2621   c_schemaRecord.m_callback.m_callbackFunction =
2622     safe_cast(&Dbdict::restart_checkSchemaStatusComplete);
2623 
2624   c_restartRecord.m_pass= 0;
2625   c_restartRecord.activeTable = 0;
2626   checkSchemaStatus(signal);
2627 }//execSCHEMA_INFO()
2628 
2629 void
restart_checkSchemaStatusComplete(Signal * signal,Uint32 callbackData,Uint32 returnCode)2630 Dbdict::restart_checkSchemaStatusComplete(Signal * signal,
2631 					  Uint32 callbackData,
2632 					  Uint32 returnCode){
2633 
2634   ndbrequire(c_writeSchemaRecord.inUse == false);
2635   c_writeSchemaRecord.inUse = true;
2636   XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
2637   c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
2638   c_writeSchemaRecord.newFile = true;
2639   c_writeSchemaRecord.firstPage = 0;
2640   c_writeSchemaRecord.noOfPages = xsf->noOfPages;
2641   c_writeSchemaRecord.m_callback.m_callbackData = 0;
2642   c_writeSchemaRecord.m_callback.m_callbackFunction =
2643     safe_cast(&Dbdict::restart_writeSchemaConf);
2644 
2645   for(Uint32 i = 0; i<xsf->noOfPages; i++)
2646     computeChecksum(xsf, i);
2647 
2648   startWriteSchemaFile(signal);
2649 }
2650 
2651 void
restart_writeSchemaConf(Signal * signal,Uint32 callbackData,Uint32 returnCode)2652 Dbdict::restart_writeSchemaConf(Signal * signal,
2653 				Uint32 callbackData,
2654 				Uint32 returnCode){
2655 
2656   if(c_systemRestart){
2657     jam();
2658     signal->theData[0] = getOwnNodeId();
2659     sendSignal(calcDictBlockRef(c_masterNodeId), GSN_SCHEMA_INFOCONF,
2660 	       signal, 1, JBB);
2661     return;
2662   }
2663 
2664   ndbrequire(c_nodeRestart || c_initialNodeRestart);
2665   c_blockState = BS_IDLE;
2666   activateIndexes(signal, 0);
2667   return;
2668 }
2669 
execSCHEMA_INFOCONF(Signal * signal)2670 void Dbdict::execSCHEMA_INFOCONF(Signal* signal)
2671 {
2672   jamEntry();
2673   ndbrequire(signal->getNoOfSections() == 0);
2674 
2675 /* ---------------------------------------------------------------- */
2676 // This signal is received in the master as part of system restart
2677 // from all nodes (including the master) after they have synchronised
2678 // their data with the master node's schema information.
2679 /* ---------------------------------------------------------------- */
2680   const Uint32 nodeId = signal->theData[0];
2681   c_sendSchemaRecord.m_SCHEMAINFO_Counter.clearWaitingFor(nodeId);
2682 
2683   if (!c_sendSchemaRecord.m_SCHEMAINFO_Counter.done()){
2684     jam();
2685     return;
2686   }//if
2687   activateIndexes(signal, 0);
2688 }//execSCHEMA_INFOCONF()
2689 
2690 static bool
checkSchemaStatus(Uint32 tableType,Uint32 pass)2691 checkSchemaStatus(Uint32 tableType, Uint32 pass)
2692 {
2693   switch(tableType){
2694   case DictTabInfo::UndefTableType:
2695     return true;
2696   case DictTabInfo::HashIndexTrigger:
2697   case DictTabInfo::SubscriptionTrigger:
2698   case DictTabInfo::ReadOnlyConstraint:
2699   case DictTabInfo::IndexTrigger:
2700     return false;
2701   case DictTabInfo::LogfileGroup:
2702     return pass == 0 || pass == 9 || pass == 10;
2703   case DictTabInfo::Tablespace:
2704     return pass == 1 || pass == 8 || pass == 11;
2705   case DictTabInfo::Datafile:
2706   case DictTabInfo::Undofile:
2707     return pass == 2 || pass == 7 || pass == 12;
2708   case DictTabInfo::SystemTable:
2709   case DictTabInfo::UserTable:
2710     return /* pass == 3 || pass == 6 || */ pass == 13;
2711   case DictTabInfo::UniqueHashIndex:
2712   case DictTabInfo::HashIndex:
2713   case DictTabInfo::UniqueOrderedIndex:
2714   case DictTabInfo::OrderedIndex:
2715     return /* pass == 4 || pass == 5 || */ pass == 14;
2716   }
2717 
2718   return false;
2719 }
2720 
2721 static const Uint32 CREATE_OLD_PASS = 4;
2722 static const Uint32 DROP_OLD_PASS = 9;
2723 static const Uint32 CREATE_NEW_PASS = 14;
2724 static const Uint32 LAST_PASS = 14;
2725 
2726 NdbOut&
operator <<(NdbOut & out,const SchemaFile::TableEntry entry)2727 operator<<(NdbOut& out, const SchemaFile::TableEntry entry)
2728 {
2729   out << "[";
2730   out << " state: " << entry.m_tableState;
2731   out << " version: " << hex << entry.m_tableVersion << dec;
2732   out << " type: " << entry.m_tableType;
2733   out << " words: " << entry.m_info_words;
2734   out << " gcp: " << entry.m_gcp;
2735   out << " ]";
2736   return out;
2737 }
2738 
2739 /**
2740  * Pass 0  Create old LogfileGroup
2741  * Pass 1  Create old Tablespace
2742  * Pass 2  Create old Datafile/Undofile
2743  * Pass 3  Create old Table           // NOT DONE DUE TO DIH
2744  * Pass 4  Create old Index           // NOT DONE DUE TO DIH
2745 
2746  * Pass 5  Drop old Index             // NOT DONE DUE TO DIH
2747  * Pass 6  Drop old Table             // NOT DONE DUE TO DIH
2748  * Pass 7  Drop old Datafile/Undofile
2749  * Pass 8  Drop old Tablespace
2750  * Pass 9  Drop old Logfilegroup
2751 
2752  * Pass 10 Create new LogfileGroup
2753  * Pass 11 Create new Tablespace
2754  * Pass 12 Create new Datafile/Undofile
2755  * Pass 13 Create new Table
2756  * Pass 14 Create new Index
2757  */
2758 
checkSchemaStatus(Signal * signal)2759 void Dbdict::checkSchemaStatus(Signal* signal)
2760 {
2761   XSchemaFile * newxsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
2762   XSchemaFile * oldxsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0];
2763   ndbrequire(newxsf->noOfPages == oldxsf->noOfPages);
2764   const Uint32 noOfEntries = newxsf->noOfPages * NDB_SF_PAGE_ENTRIES;
2765 
2766   for (; c_restartRecord.activeTable < noOfEntries;
2767        c_restartRecord.activeTable++) {
2768     jam();
2769 
2770     Uint32 tableId = c_restartRecord.activeTable;
2771     SchemaFile::TableEntry *newEntry = getTableEntry(newxsf, tableId);
2772     SchemaFile::TableEntry *oldEntry = getTableEntry(oldxsf, tableId);
2773     SchemaFile::TableState newSchemaState =
2774       (SchemaFile::TableState)newEntry->m_tableState;
2775     SchemaFile::TableState oldSchemaState =
2776       (SchemaFile::TableState)oldEntry->m_tableState;
2777 
2778     if (c_restartRecord.activeTable >= c_tableRecordPool.getSize()) {
2779       jam();
2780       ndbrequire(newSchemaState == SchemaFile::INIT);
2781       ndbrequire(oldSchemaState == SchemaFile::INIT);
2782       continue;
2783     }//if
2784 
2785 //#define PRINT_SCHEMA_RESTART
2786 #ifdef PRINT_SCHEMA_RESTART
2787     char buf[100];
2788     snprintf(buf, sizeof(buf), "checkSchemaStatus: pass: %d table: %d",
2789              c_restartRecord.m_pass, tableId);
2790 #endif
2791 
2792     if (c_restartRecord.m_pass <= CREATE_OLD_PASS)
2793     {
2794       if (!::checkSchemaStatus(oldEntry->m_tableType, c_restartRecord.m_pass))
2795         continue;
2796 
2797       switch(oldSchemaState){
2798       case SchemaFile::INIT: jam();
2799       case SchemaFile::DROP_TABLE_COMMITTED: jam();
2800       case SchemaFile::ADD_STARTED: jam();
2801       case SchemaFile::DROP_TABLE_STARTED: jam();
2802       case SchemaFile::TEMPORARY_TABLE_COMMITTED: jam();
2803 	continue;
2804       case SchemaFile::TABLE_ADD_COMMITTED: jam();
2805       case SchemaFile::ALTER_TABLE_COMMITTED: jam();
2806 	jam();
2807 #ifdef PRINT_SCHEMA_RESTART
2808         ndbout_c("%s -> restartCreateTab", buf);
2809         ndbout << *newEntry << " " << *oldEntry << endl;
2810 #endif
2811 	restartCreateTab(signal, tableId, oldEntry, oldEntry, true);
2812         return;
2813       }
2814     }
2815 
2816     if (c_restartRecord.m_pass <= DROP_OLD_PASS)
2817     {
2818       if (!::checkSchemaStatus(oldEntry->m_tableType, c_restartRecord.m_pass))
2819         continue;
2820 
2821       switch(oldSchemaState){
2822       case SchemaFile::INIT: jam();
2823       case SchemaFile::DROP_TABLE_COMMITTED: jam();
2824       case SchemaFile::TEMPORARY_TABLE_COMMITTED: jam();
2825         continue;
2826       case SchemaFile::ADD_STARTED: jam();
2827       case SchemaFile::DROP_TABLE_STARTED: jam();
2828 #ifdef PRINT_SCHEMA_RESTART
2829         ndbout_c("%s -> restartDropTab", buf);
2830         ndbout << *newEntry << " " << *oldEntry << endl;
2831 #endif
2832 	restartDropTab(signal, tableId, oldEntry, newEntry);
2833         return;
2834       case SchemaFile::TABLE_ADD_COMMITTED: jam();
2835       case SchemaFile::ALTER_TABLE_COMMITTED: jam();
2836         if (! (* oldEntry == * newEntry))
2837         {
2838 #ifdef PRINT_SCHEMA_RESTART
2839           ndbout_c("%s -> restartDropTab", buf);
2840           ndbout << *newEntry << " " << *oldEntry << endl;
2841 #endif
2842           restartDropTab(signal, tableId, oldEntry, newEntry);
2843           return;
2844         }
2845         continue;
2846       }
2847     }
2848 
2849     if (c_restartRecord.m_pass <= CREATE_NEW_PASS)
2850     {
2851       if (!::checkSchemaStatus(newEntry->m_tableType, c_restartRecord.m_pass))
2852         continue;
2853 
2854       switch(newSchemaState){
2855       case SchemaFile::INIT: jam();
2856       case SchemaFile::DROP_TABLE_COMMITTED: jam();
2857       case SchemaFile::TEMPORARY_TABLE_COMMITTED: jam();
2858         * oldEntry = * newEntry;
2859         continue;
2860       case SchemaFile::ADD_STARTED: jam();
2861       case SchemaFile::DROP_TABLE_STARTED: jam();
2862         ndbrequire(DictTabInfo::isTable(newEntry->m_tableType) ||
2863                    DictTabInfo::isIndex(newEntry->m_tableType));
2864         newEntry->m_tableState = SchemaFile::INIT;
2865         continue;
2866       case SchemaFile::TABLE_ADD_COMMITTED: jam();
2867       case SchemaFile::ALTER_TABLE_COMMITTED: jam();
2868         if (DictTabInfo::isIndex(newEntry->m_tableType) ||
2869             DictTabInfo::isTable(newEntry->m_tableType))
2870         {
2871           bool file = * oldEntry == *newEntry &&
2872             (!DictTabInfo::isIndex(newEntry->m_tableType) || c_systemRestart);
2873 
2874 #ifdef PRINT_SCHEMA_RESTART
2875           ndbout_c("%s -> restartCreateTab (file: %d)", buf, file);
2876           ndbout << *newEntry << " " << *oldEntry << endl;
2877 #endif
2878           restartCreateTab(signal, tableId, newEntry, newEntry, file);
2879           * oldEntry = * newEntry;
2880           return;
2881         }
2882         else if (! (* oldEntry == *newEntry))
2883         {
2884 #ifdef PRINT_SCHEMA_RESTART
2885           ndbout_c("%s -> restartCreateTab", buf);
2886           ndbout << *newEntry << " " << *oldEntry << endl;
2887 #endif
2888           restartCreateTab(signal, tableId, oldEntry, newEntry, false);
2889           * oldEntry = * newEntry;
2890           return;
2891         }
2892         * oldEntry = * newEntry;
2893         continue;
2894       }
2895     }
2896   }
2897 
2898   c_restartRecord.m_pass++;
2899   c_restartRecord.activeTable= 0;
2900   if(c_restartRecord.m_pass <= LAST_PASS)
2901   {
2902     checkSchemaStatus(signal);
2903   }
2904   else
2905   {
2906     execute(signal, c_schemaRecord.m_callback, 0);
2907   }
2908 }//checkSchemaStatus()
2909 
2910 void
restartCreateTab(Signal * signal,Uint32 tableId,const SchemaFile::TableEntry * old_entry,const SchemaFile::TableEntry * new_entry,bool file)2911 Dbdict::restartCreateTab(Signal* signal, Uint32 tableId,
2912 			 const SchemaFile::TableEntry * old_entry,
2913 			 const SchemaFile::TableEntry * new_entry,
2914 			 bool file){
2915   jam();
2916 
2917   switch(new_entry->m_tableType){
2918   case DictTabInfo::UndefTableType:
2919   case DictTabInfo::HashIndexTrigger:
2920   case DictTabInfo::SubscriptionTrigger:
2921   case DictTabInfo::ReadOnlyConstraint:
2922   case DictTabInfo::IndexTrigger:
2923     ndbrequire(false);
2924   case DictTabInfo::SystemTable:
2925   case DictTabInfo::UserTable:
2926   case DictTabInfo::UniqueHashIndex:
2927   case DictTabInfo::HashIndex:
2928   case DictTabInfo::UniqueOrderedIndex:
2929   case DictTabInfo::OrderedIndex:
2930     break;
2931   case DictTabInfo::Tablespace:
2932   case DictTabInfo::LogfileGroup:
2933   case DictTabInfo::Datafile:
2934   case DictTabInfo::Undofile:
2935     restartCreateObj(signal, tableId, old_entry, new_entry, file);
2936     return;
2937   }
2938 
2939   CreateTableRecordPtr createTabPtr;
2940   c_opCreateTable.seize(createTabPtr);
2941   ndbrequire(!createTabPtr.isNull());
2942 
2943   createTabPtr.p->key = ++c_opRecordSequence;
2944   c_opCreateTable.add(createTabPtr);
2945 
2946   createTabPtr.p->m_errorCode = 0;
2947   createTabPtr.p->m_tablePtrI = tableId;
2948   createTabPtr.p->m_coordinatorRef = reference();
2949   createTabPtr.p->m_senderRef = 0;
2950   createTabPtr.p->m_senderData = RNIL;
2951   createTabPtr.p->m_tabInfoPtrI = RNIL;
2952   createTabPtr.p->m_dihAddFragPtr = RNIL;
2953 
2954   if(file && !ERROR_INSERTED(6002)){
2955     jam();
2956 
2957     c_readTableRecord.no_of_words = old_entry->m_info_words;
2958     c_readTableRecord.pageId = 0;
2959     c_readTableRecord.m_callback.m_callbackData = createTabPtr.p->key;
2960     c_readTableRecord.m_callback.m_callbackFunction =
2961       safe_cast(&Dbdict::restartCreateTab_readTableConf);
2962 
2963     startReadTableFile(signal, tableId);
2964     return;
2965   } else {
2966 
2967     ndbrequire(c_masterNodeId != getOwnNodeId());
2968 
2969     /**
2970      * Get from master
2971      */
2972     GetTabInfoReq * const req = (GetTabInfoReq *)&signal->theData[0];
2973     req->senderRef = reference();
2974     req->senderData = createTabPtr.p->key;
2975     req->requestType = GetTabInfoReq::RequestById |
2976       GetTabInfoReq::LongSignalConf;
2977     req->tableId = tableId;
2978     sendSignal(calcDictBlockRef(c_masterNodeId), GSN_GET_TABINFOREQ, signal,
2979 	       GetTabInfoReq::SignalLength, JBB);
2980 
2981     if(ERROR_INSERTED(6002)){
2982       NdbSleep_MilliSleep(10);
2983       CRASH_INSERTION(6002);
2984     }
2985   }
2986 }
2987 
2988 void
restartCreateTab_readTableConf(Signal * signal,Uint32 callbackData,Uint32 returnCode)2989 Dbdict::restartCreateTab_readTableConf(Signal* signal,
2990 				       Uint32 callbackData,
2991 				       Uint32 returnCode){
2992   jam();
2993 
2994   PageRecordPtr pageRecPtr;
2995   c_pageRecordArray.getPtr(pageRecPtr, c_readTableRecord.pageId);
2996 
2997   ParseDictTabInfoRecord parseRecord;
2998   parseRecord.requestType = DictTabInfo::GetTabInfoConf;
2999   parseRecord.errorCode = 0;
3000 
3001   Uint32 sz = c_readTableRecord.no_of_words;
3002   SimplePropertiesLinearReader r(pageRecPtr.p->word+ZPAGE_HEADER_SIZE, sz);
3003   handleTabInfoInit(r, &parseRecord);
3004   if (parseRecord.errorCode != 0)
3005   {
3006     char buf[255];
3007     BaseString::snprintf(buf, sizeof(buf),
3008 			 "Unable to restart, fail while creating table %d"
3009 			 " error: %d. Most likely change of configuration",
3010 			 c_readTableRecord.tableId,
3011 			 parseRecord.errorCode);
3012     progError(__LINE__,
3013 	      NDBD_EXIT_INVALID_CONFIG,
3014 	      buf);
3015     ndbrequire(parseRecord.errorCode == 0);
3016   }
3017 
3018   /* ---------------------------------------------------------------- */
3019   // We have read the table description from disk as part of system restart.
3020   // We will also write it back again to ensure that both copies are ok.
3021   /* ---------------------------------------------------------------- */
3022   ndbrequire(c_writeTableRecord.tableWriteState == WriteTableRecord::IDLE);
3023   c_writeTableRecord.no_of_words = c_readTableRecord.no_of_words;
3024   c_writeTableRecord.pageId = c_readTableRecord.pageId;
3025   c_writeTableRecord.tableWriteState = WriteTableRecord::TWR_CALLBACK;
3026   c_writeTableRecord.m_callback.m_callbackData = callbackData;
3027   c_writeTableRecord.m_callback.m_callbackFunction =
3028     safe_cast(&Dbdict::restartCreateTab_writeTableConf);
3029   startWriteTableFile(signal, c_readTableRecord.tableId);
3030 }
3031 
3032 void
execGET_TABINFO_CONF(Signal * signal)3033 Dbdict::execGET_TABINFO_CONF(Signal* signal){
3034   jamEntry();
3035 
3036   if(!assembleFragments(signal)){
3037     jam();
3038     return;
3039   }
3040 
3041   GetTabInfoConf * const conf = (GetTabInfoConf*)signal->getDataPtr();
3042 
3043   switch(conf->tableType){
3044   case DictTabInfo::UndefTableType:
3045   case DictTabInfo::HashIndexTrigger:
3046   case DictTabInfo::SubscriptionTrigger:
3047   case DictTabInfo::ReadOnlyConstraint:
3048   case DictTabInfo::IndexTrigger:
3049     ndbrequire(false);
3050   case DictTabInfo::SystemTable:
3051   case DictTabInfo::UserTable:
3052   case DictTabInfo::UniqueHashIndex:
3053   case DictTabInfo::HashIndex:
3054   case DictTabInfo::UniqueOrderedIndex:
3055   case DictTabInfo::OrderedIndex:
3056     break;
3057   case DictTabInfo::Tablespace:
3058   case DictTabInfo::LogfileGroup:
3059   case DictTabInfo::Datafile:
3060   case DictTabInfo::Undofile:
3061     if(refToBlock(conf->senderRef) == TSMAN
3062        && (refToNode(conf->senderRef) == 0
3063 	   || refToNode(conf->senderRef) == getOwnNodeId()))
3064     {
3065       jam();
3066       FilePtr fg_ptr;
3067       ndbrequire(c_file_hash.find(fg_ptr, conf->tableId));
3068       const Uint32 free_extents= conf->freeExtents;
3069       const Uint32 id= conf->tableId;
3070       const Uint32 type= conf->tableType;
3071       const Uint32 data= conf->senderData;
3072       signal->theData[0]= ZPACK_TABLE_INTO_PAGES;
3073       signal->theData[1]= id;
3074       signal->theData[2]= type;
3075       signal->theData[3]= data;
3076       signal->theData[4]= free_extents;
3077       sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);
3078     }
3079     else if(refToBlock(conf->senderRef) == LGMAN
3080 	    && (refToNode(conf->senderRef) == 0
3081 		|| refToNode(conf->senderRef) == getOwnNodeId()))
3082     {
3083       jam();
3084       FilegroupPtr fg_ptr;
3085       ndbrequire(c_filegroup_hash.find(fg_ptr, conf->tableId));
3086       const Uint32 free_hi= conf->freeWordsHi;
3087       const Uint32 free_lo= conf->freeWordsLo;
3088       const Uint32 id= conf->tableId;
3089       const Uint32 type= conf->tableType;
3090       const Uint32 data= conf->senderData;
3091       signal->theData[0]= ZPACK_TABLE_INTO_PAGES;
3092       signal->theData[1]= id;
3093       signal->theData[2]= type;
3094       signal->theData[3]= data;
3095       signal->theData[4]= free_hi;
3096       signal->theData[5]= free_lo;
3097       sendSignal(reference(), GSN_CONTINUEB, signal, 6, JBB);
3098     }
3099     else
3100     {
3101       jam();
3102       restartCreateObj_getTabInfoConf(signal);
3103     }
3104     return;
3105   }
3106 
3107   const Uint32 tableId = conf->tableId;
3108   const Uint32 senderData = conf->senderData;
3109 
3110   SegmentedSectionPtr tabInfoPtr;
3111   signal->getSection(tabInfoPtr, GetTabInfoConf::DICT_TAB_INFO);
3112 
3113   CreateTableRecordPtr createTabPtr;
3114   ndbrequire(c_opCreateTable.find(createTabPtr, senderData));
3115   ndbrequire(!createTabPtr.isNull());
3116   ndbrequire(createTabPtr.p->m_tablePtrI == tableId);
3117 
3118   /**
3119    * Put data into table record
3120    */
3121   ParseDictTabInfoRecord parseRecord;
3122   parseRecord.requestType = DictTabInfo::GetTabInfoConf;
3123   parseRecord.errorCode = 0;
3124 
3125   SimplePropertiesSectionReader r(tabInfoPtr, getSectionSegmentPool());
3126   handleTabInfoInit(r, &parseRecord);
3127   ndbrequire(parseRecord.errorCode == 0);
3128 
3129   // save to disk
3130 
3131   ndbrequire(tableId < c_tableRecordPool.getSize());
3132   XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
3133   SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, tableId);
3134   tableEntry->m_info_words= tabInfoPtr.sz;
3135 
3136   Callback callback;
3137   callback.m_callbackData = createTabPtr.p->key;
3138   callback.m_callbackFunction =
3139     safe_cast(&Dbdict::restartCreateTab_writeTableConf);
3140 
3141   signal->header.m_noOfSections = 0;
3142   writeTableFile(signal, createTabPtr.p->m_tablePtrI, tabInfoPtr, &callback);
3143   signal->setSection(tabInfoPtr, 0);
3144   releaseSections(signal);
3145 }
3146 
3147 void
restartCreateTab_writeTableConf(Signal * signal,Uint32 callbackData,Uint32 returnCode)3148 Dbdict::restartCreateTab_writeTableConf(Signal* signal,
3149 					Uint32 callbackData,
3150 					Uint32 returnCode){
3151   jam();
3152 
3153   CreateTableRecordPtr createTabPtr;
3154   ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
3155 
3156   Callback callback;
3157   callback.m_callbackData = callbackData;
3158   callback.m_callbackFunction =
3159     safe_cast(&Dbdict::restartCreateTab_dihComplete);
3160 
3161   SegmentedSectionPtr fragDataPtr;
3162   fragDataPtr.sz = 0;
3163   fragDataPtr.setNull();
3164   createTab_dih(signal, createTabPtr, fragDataPtr, &callback);
3165 }
3166 
3167 void
restartCreateTab_dihComplete(Signal * signal,Uint32 callbackData,Uint32 returnCode)3168 Dbdict::restartCreateTab_dihComplete(Signal* signal,
3169 				     Uint32 callbackData,
3170 				     Uint32 returnCode){
3171   jam();
3172 
3173   CreateTableRecordPtr createTabPtr;
3174   ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
3175 
3176   if(createTabPtr.p->m_errorCode)
3177   {
3178     char buf[100];
3179     BaseString::snprintf(buf, sizeof(buf), "Failed to create table during"
3180                          " restart, Error: %u",
3181                          createTabPtr.p->m_errorCode);
3182     progError(__LINE__, NDBD_EXIT_RESOURCE_ALLOC_ERROR, buf);
3183   }
3184 
3185   Callback callback;
3186   callback.m_callbackData = callbackData;
3187   callback.m_callbackFunction =
3188     safe_cast(&Dbdict::restartCreateTab_activateComplete);
3189 
3190   alterTab_activate(signal, createTabPtr, &callback);
3191 }
3192 
3193 void
restartCreateTab_activateComplete(Signal * signal,Uint32 callbackData,Uint32 returnCode)3194 Dbdict::restartCreateTab_activateComplete(Signal* signal,
3195 					  Uint32 callbackData,
3196 					  Uint32 returnCode){
3197   jam();
3198 
3199   CreateTableRecordPtr createTabPtr;
3200   ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
3201 
3202   TableRecordPtr tabPtr;
3203   c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
3204   tabPtr.p->tabState = TableRecord::DEFINED;
3205 
3206   releaseCreateTableOp(signal,createTabPtr);
3207 
3208   c_restartRecord.activeTable++;
3209   checkSchemaStatus(signal);
3210 }
3211 
3212 void
releaseCreateTableOp(Signal * signal,CreateTableRecordPtr createTabPtr)3213 Dbdict::releaseCreateTableOp(Signal* signal, CreateTableRecordPtr createTabPtr)
3214 {
3215   if (createTabPtr.p->m_tabInfoPtrI != RNIL)
3216   {
3217     jam();
3218     SegmentedSectionPtr tabInfoPtr;
3219     getSection(tabInfoPtr, createTabPtr.p->m_tabInfoPtrI);
3220     signal->setSection(tabInfoPtr, 0);
3221     releaseSections(signal);
3222   }
3223   c_opCreateTable.release(createTabPtr);
3224 }
3225 
3226 void
restartDropTab(Signal * signal,Uint32 tableId,const SchemaFile::TableEntry * old_entry,const SchemaFile::TableEntry * new_entry)3227 Dbdict::restartDropTab(Signal* signal, Uint32 tableId,
3228                        const SchemaFile::TableEntry * old_entry,
3229                        const SchemaFile::TableEntry * new_entry)
3230 {
3231   switch(old_entry->m_tableType){
3232   case DictTabInfo::UndefTableType:
3233   case DictTabInfo::HashIndexTrigger:
3234   case DictTabInfo::SubscriptionTrigger:
3235   case DictTabInfo::ReadOnlyConstraint:
3236   case DictTabInfo::IndexTrigger:
3237     ndbrequire(false);
3238   case DictTabInfo::SystemTable:
3239   case DictTabInfo::UserTable:
3240   case DictTabInfo::UniqueHashIndex:
3241   case DictTabInfo::HashIndex:
3242   case DictTabInfo::UniqueOrderedIndex:
3243   case DictTabInfo::OrderedIndex:
3244     break;
3245   case DictTabInfo::Tablespace:
3246   case DictTabInfo::LogfileGroup:
3247   case DictTabInfo::Datafile:
3248   case DictTabInfo::Undofile:
3249     restartDropObj(signal, tableId, old_entry);
3250     return;
3251   }
3252 
3253   const Uint32 key = ++c_opRecordSequence;
3254 
3255   DropTableRecordPtr dropTabPtr;
3256   ndbrequire(c_opDropTable.seize(dropTabPtr));
3257 
3258   dropTabPtr.p->key = key;
3259   c_opDropTable.add(dropTabPtr);
3260 
3261   dropTabPtr.p->m_errorCode = 0;
3262   dropTabPtr.p->m_request.tableId = tableId;
3263   dropTabPtr.p->m_coordinatorRef = 0;
3264   dropTabPtr.p->m_requestType = DropTabReq::RestartDropTab;
3265   dropTabPtr.p->m_participantData.m_gsn = GSN_DROP_TAB_REQ;
3266 
3267   dropTabPtr.p->m_participantData.m_block = 0;
3268   dropTabPtr.p->m_participantData.m_callback.m_callbackData = key;
3269   dropTabPtr.p->m_participantData.m_callback.m_callbackFunction =
3270     safe_cast(&Dbdict::restartDropTab_complete);
3271   dropTab_nextStep(signal, dropTabPtr);
3272 }
3273 
3274 void
restartDropTab_complete(Signal * signal,Uint32 callbackData,Uint32 returnCode)3275 Dbdict::restartDropTab_complete(Signal* signal,
3276 				Uint32 callbackData,
3277 				Uint32 returnCode){
3278   jam();
3279 
3280   DropTableRecordPtr dropTabPtr;
3281   ndbrequire(c_opDropTable.find(dropTabPtr, callbackData));
3282 
3283   //@todo check error
3284 
3285   releaseTableObject(c_restartRecord.activeTable);
3286   c_opDropTable.release(dropTabPtr);
3287 
3288   c_restartRecord.activeTable++;
3289   checkSchemaStatus(signal);
3290 }
3291 
3292 /**
3293  * Create Obj during NR/SR
3294  */
3295 void
restartCreateObj(Signal * signal,Uint32 tableId,const SchemaFile::TableEntry * old_entry,const SchemaFile::TableEntry * new_entry,bool file)3296 Dbdict::restartCreateObj(Signal* signal,
3297 			 Uint32 tableId,
3298 			 const SchemaFile::TableEntry * old_entry,
3299 			 const SchemaFile::TableEntry * new_entry,
3300 			 bool file){
3301   jam();
3302 
3303   CreateObjRecordPtr createObjPtr;
3304   ndbrequire(c_opCreateObj.seize(createObjPtr));
3305 
3306   const Uint32 key = ++c_opRecordSequence;
3307   createObjPtr.p->key = key;
3308   c_opCreateObj.add(createObjPtr);
3309   createObjPtr.p->m_errorCode = 0;
3310   createObjPtr.p->m_senderRef = reference();
3311   createObjPtr.p->m_senderData = tableId;
3312   createObjPtr.p->m_clientRef = reference();
3313   createObjPtr.p->m_clientData = tableId;
3314 
3315   createObjPtr.p->m_obj_id = tableId;
3316   createObjPtr.p->m_obj_type = new_entry->m_tableType;
3317   createObjPtr.p->m_obj_version = new_entry->m_tableVersion;
3318 
3319   createObjPtr.p->m_callback.m_callbackData = key;
3320   createObjPtr.p->m_callback.m_callbackFunction=
3321     safe_cast(&Dbdict::restartCreateObj_prepare_start_done);
3322 
3323   createObjPtr.p->m_restart= file ? 1 : 2;
3324   switch(new_entry->m_tableType){
3325   case DictTabInfo::Tablespace:
3326   case DictTabInfo::LogfileGroup:
3327     createObjPtr.p->m_vt_index = 0;
3328     break;
3329   case DictTabInfo::Datafile:
3330   case DictTabInfo::Undofile:
3331     createObjPtr.p->m_vt_index = 1;
3332     break;
3333   default:
3334     ndbrequire(false);
3335   }
3336 
3337   createObjPtr.p->m_obj_info_ptr_i = RNIL;
3338   if(file)
3339   {
3340     c_readTableRecord.no_of_words = old_entry->m_info_words;
3341     c_readTableRecord.pageId = 0;
3342     c_readTableRecord.m_callback.m_callbackData = key;
3343     c_readTableRecord.m_callback.m_callbackFunction =
3344       safe_cast(&Dbdict::restartCreateObj_readConf);
3345 
3346     startReadTableFile(signal, tableId);
3347   }
3348   else
3349   {
3350     /**
3351      * Get from master
3352      */
3353     GetTabInfoReq * const req = (GetTabInfoReq *)&signal->theData[0];
3354     req->senderRef = reference();
3355     req->senderData = key;
3356     req->requestType = GetTabInfoReq::RequestById |
3357       GetTabInfoReq::LongSignalConf;
3358     req->tableId = tableId;
3359     sendSignal(calcDictBlockRef(c_masterNodeId), GSN_GET_TABINFOREQ, signal,
3360 	       GetTabInfoReq::SignalLength, JBB);
3361   }
3362 }
3363 
3364 void
restartCreateObj_getTabInfoConf(Signal * signal)3365 Dbdict::restartCreateObj_getTabInfoConf(Signal* signal)
3366 {
3367   jam();
3368 
3369   GetTabInfoConf * const conf = (GetTabInfoConf*)signal->getDataPtr();
3370 
3371   const Uint32 objId = conf->tableId;
3372   const Uint32 senderData = conf->senderData;
3373 
3374   SegmentedSectionPtr objInfoPtr;
3375   signal->getSection(objInfoPtr, GetTabInfoConf::DICT_TAB_INFO);
3376 
3377   CreateObjRecordPtr createObjPtr;
3378   ndbrequire(c_opCreateObj.find(createObjPtr, senderData));
3379   ndbrequire(createObjPtr.p->m_obj_id == objId);
3380 
3381   createObjPtr.p->m_obj_info_ptr_i= objInfoPtr.i;
3382   signal->header.m_noOfSections = 0;
3383 
3384   (this->*f_dict_op[createObjPtr.p->m_vt_index].m_prepare_start)
3385     (signal, createObjPtr.p);
3386 }
3387 
3388 void
restartCreateObj_readConf(Signal * signal,Uint32 callbackData,Uint32 returnCode)3389 Dbdict::restartCreateObj_readConf(Signal* signal,
3390 				  Uint32 callbackData,
3391 				  Uint32 returnCode)
3392 {
3393   jam();
3394   ndbrequire(returnCode == 0);
3395   CreateObjRecordPtr createObjPtr;
3396   ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
3397   ndbrequire(createObjPtr.p->m_errorCode == 0);
3398 
3399   PageRecordPtr pageRecPtr;
3400   c_pageRecordArray.getPtr(pageRecPtr, c_readTableRecord.pageId);
3401 
3402   Uint32 sz = c_readTableRecord.no_of_words;
3403 
3404   Ptr<SectionSegment> ptr;
3405   ndbrequire(import(ptr, pageRecPtr.p->word+ZPAGE_HEADER_SIZE, sz));
3406   createObjPtr.p->m_obj_info_ptr_i= ptr.i;
3407 
3408   if (f_dict_op[createObjPtr.p->m_vt_index].m_prepare_start)
3409     (this->*f_dict_op[createObjPtr.p->m_vt_index].m_prepare_start)
3410       (signal, createObjPtr.p);
3411   else
3412     execute(signal, createObjPtr.p->m_callback, 0);
3413 }
3414 
3415 void
restartCreateObj_prepare_start_done(Signal * signal,Uint32 callbackData,Uint32 returnCode)3416 Dbdict::restartCreateObj_prepare_start_done(Signal* signal,
3417 					    Uint32 callbackData,
3418 					    Uint32 returnCode)
3419 {
3420   jam();
3421   ndbrequire(returnCode == 0);
3422   CreateObjRecordPtr createObjPtr;
3423   ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
3424   ndbrequire(createObjPtr.p->m_errorCode == 0);
3425 
3426   Callback callback;
3427   callback.m_callbackData = callbackData;
3428   callback.m_callbackFunction =
3429     safe_cast(&Dbdict::restartCreateObj_write_complete);
3430 
3431   SegmentedSectionPtr objInfoPtr;
3432   getSection(objInfoPtr, createObjPtr.p->m_obj_info_ptr_i);
3433 
3434   writeTableFile(signal, createObjPtr.p->m_obj_id, objInfoPtr, &callback);
3435 }
3436 
3437 void
restartCreateObj_write_complete(Signal * signal,Uint32 callbackData,Uint32 returnCode)3438 Dbdict::restartCreateObj_write_complete(Signal* signal,
3439 					Uint32 callbackData,
3440 					Uint32 returnCode)
3441 {
3442   ndbrequire(returnCode == 0);
3443   CreateObjRecordPtr createObjPtr;
3444   ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
3445   ndbrequire(createObjPtr.p->m_errorCode == 0);
3446 
3447   SegmentedSectionPtr objInfoPtr;
3448   getSection(objInfoPtr, createObjPtr.p->m_obj_info_ptr_i);
3449   signal->setSection(objInfoPtr, 0);
3450   releaseSections(signal);
3451   createObjPtr.p->m_obj_info_ptr_i = RNIL;
3452 
3453   createObjPtr.p->m_callback.m_callbackFunction =
3454     safe_cast(&Dbdict::restartCreateObj_prepare_complete_done);
3455 
3456   if (f_dict_op[createObjPtr.p->m_vt_index].m_prepare_complete)
3457     (this->*f_dict_op[createObjPtr.p->m_vt_index].m_prepare_complete)
3458       (signal, createObjPtr.p);
3459   else
3460     execute(signal, createObjPtr.p->m_callback, 0);
3461 }
3462 
3463 void
restartCreateObj_prepare_complete_done(Signal * signal,Uint32 callbackData,Uint32 returnCode)3464 Dbdict::restartCreateObj_prepare_complete_done(Signal* signal,
3465 					       Uint32 callbackData,
3466 					       Uint32 returnCode)
3467 {
3468   jam();
3469   ndbrequire(returnCode == 0);
3470   CreateObjRecordPtr createObjPtr;
3471   ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
3472   ndbrequire(createObjPtr.p->m_errorCode == 0);
3473 
3474   createObjPtr.p->m_callback.m_callbackFunction =
3475     safe_cast(&Dbdict::restartCreateObj_commit_start_done);
3476 
3477   if (f_dict_op[createObjPtr.p->m_vt_index].m_commit_start)
3478     (this->*f_dict_op[createObjPtr.p->m_vt_index].m_commit_start)
3479       (signal, createObjPtr.p);
3480   else
3481     execute(signal, createObjPtr.p->m_callback, 0);
3482 }
3483 
3484 void
restartCreateObj_commit_start_done(Signal * signal,Uint32 callbackData,Uint32 returnCode)3485 Dbdict::restartCreateObj_commit_start_done(Signal* signal,
3486 					   Uint32 callbackData,
3487 					   Uint32 returnCode)
3488 {
3489   jam();
3490   ndbrequire(returnCode == 0);
3491   CreateObjRecordPtr createObjPtr;
3492   ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
3493   ndbrequire(createObjPtr.p->m_errorCode == 0);
3494 
3495   createObjPtr.p->m_callback.m_callbackFunction =
3496     safe_cast(&Dbdict::restartCreateObj_commit_complete_done);
3497 
3498   if (f_dict_op[createObjPtr.p->m_vt_index].m_commit_complete)
3499     (this->*f_dict_op[createObjPtr.p->m_vt_index].m_commit_complete)
3500       (signal, createObjPtr.p);
3501   else
3502     execute(signal, createObjPtr.p->m_callback, 0);
3503 }
3504 
3505 
3506 void
restartCreateObj_commit_complete_done(Signal * signal,Uint32 callbackData,Uint32 returnCode)3507 Dbdict::restartCreateObj_commit_complete_done(Signal* signal,
3508 					      Uint32 callbackData,
3509 					      Uint32 returnCode)
3510 {
3511   jam();
3512   ndbrequire(returnCode == 0);
3513   CreateObjRecordPtr createObjPtr;
3514   ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
3515   ndbrequire(createObjPtr.p->m_errorCode == 0);
3516 
3517   c_opCreateObj.release(createObjPtr);
3518 
3519   c_restartRecord.activeTable++;
3520   checkSchemaStatus(signal);
3521 }
3522 
3523 /**
3524  * Drop object during NR/SR
3525  */
3526 void
restartDropObj(Signal * signal,Uint32 tableId,const SchemaFile::TableEntry * entry)3527 Dbdict::restartDropObj(Signal* signal,
3528                        Uint32 tableId,
3529                        const SchemaFile::TableEntry * entry)
3530 {
3531   jam();
3532 
3533   DropObjRecordPtr dropObjPtr;
3534   ndbrequire(c_opDropObj.seize(dropObjPtr));
3535 
3536   const Uint32 key = ++c_opRecordSequence;
3537   dropObjPtr.p->key = key;
3538   c_opDropObj.add(dropObjPtr);
3539   dropObjPtr.p->m_errorCode = 0;
3540   dropObjPtr.p->m_senderRef = reference();
3541   dropObjPtr.p->m_senderData = tableId;
3542   dropObjPtr.p->m_clientRef = reference();
3543   dropObjPtr.p->m_clientData = tableId;
3544 
3545   dropObjPtr.p->m_obj_id = tableId;
3546   dropObjPtr.p->m_obj_type = entry->m_tableType;
3547   dropObjPtr.p->m_obj_version = entry->m_tableVersion;
3548 
3549   dropObjPtr.p->m_callback.m_callbackData = key;
3550   dropObjPtr.p->m_callback.m_callbackFunction=
3551     safe_cast(&Dbdict::restartDropObj_prepare_start_done);
3552 
3553   ndbout_c("Dropping %d %d", tableId, entry->m_tableType);
3554   switch(entry->m_tableType){
3555   case DictTabInfo::Tablespace:
3556   case DictTabInfo::LogfileGroup:{
3557     jam();
3558     Ptr<Filegroup> fg_ptr;
3559     ndbrequire(c_filegroup_hash.find(fg_ptr, tableId));
3560     dropObjPtr.p->m_obj_ptr_i = fg_ptr.i;
3561     dropObjPtr.p->m_vt_index = 3;
3562     break;
3563   }
3564   case DictTabInfo::Datafile:{
3565     jam();
3566     Ptr<File> file_ptr;
3567     dropObjPtr.p->m_vt_index = 2;
3568     ndbrequire(c_file_hash.find(file_ptr, tableId));
3569     dropObjPtr.p->m_obj_ptr_i = file_ptr.i;
3570     break;
3571   }
3572   case DictTabInfo::Undofile:{
3573     jam();
3574     Ptr<File> file_ptr;
3575     dropObjPtr.p->m_vt_index = 4;
3576     ndbrequire(c_file_hash.find(file_ptr, tableId));
3577     dropObjPtr.p->m_obj_ptr_i = file_ptr.i;
3578 
3579     /**
3580      * Undofiles are only removed from logfile groups file list
3581      *   as drop undofile is currently not supported...
3582      *   file will be dropped by lgman when dropping filegroup
3583      */
3584     dropObjPtr.p->m_callback.m_callbackFunction=
3585       safe_cast(&Dbdict::restartDropObj_commit_complete_done);
3586 
3587     if (f_dict_op[dropObjPtr.p->m_vt_index].m_commit_complete)
3588       (this->*f_dict_op[dropObjPtr.p->m_vt_index].m_commit_complete)
3589         (signal, dropObjPtr.p);
3590     else
3591       execute(signal, dropObjPtr.p->m_callback, 0);
3592     return;
3593   }
3594   default:
3595     jamLine(entry->m_tableType);
3596     ndbrequire(false);
3597   }
3598 
3599   if (f_dict_op[dropObjPtr.p->m_vt_index].m_prepare_start)
3600     (this->*f_dict_op[dropObjPtr.p->m_vt_index].m_prepare_start)
3601       (signal, dropObjPtr.p);
3602   else
3603     execute(signal, dropObjPtr.p->m_callback, 0);
3604 }
3605 
3606 void
restartDropObj_prepare_start_done(Signal * signal,Uint32 callbackData,Uint32 returnCode)3607 Dbdict::restartDropObj_prepare_start_done(Signal* signal,
3608                                           Uint32 callbackData,
3609                                           Uint32 returnCode)
3610 {
3611   jam();
3612   ndbrequire(returnCode == 0);
3613   DropObjRecordPtr dropObjPtr;
3614   ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
3615   ndbrequire(dropObjPtr.p->m_errorCode == 0);
3616 
3617   dropObjPtr.p->m_callback.m_callbackFunction =
3618     safe_cast(&Dbdict::restartDropObj_prepare_complete_done);
3619 
3620   if (f_dict_op[dropObjPtr.p->m_vt_index].m_prepare_complete)
3621     (this->*f_dict_op[dropObjPtr.p->m_vt_index].m_prepare_complete)
3622       (signal, dropObjPtr.p);
3623   else
3624     execute(signal, dropObjPtr.p->m_callback, 0);
3625 }
3626 
3627 void
restartDropObj_prepare_complete_done(Signal * signal,Uint32 callbackData,Uint32 returnCode)3628 Dbdict::restartDropObj_prepare_complete_done(Signal* signal,
3629                                              Uint32 callbackData,
3630                                              Uint32 returnCode)
3631 {
3632   jam();
3633   ndbrequire(returnCode == 0);
3634   DropObjRecordPtr dropObjPtr;
3635   ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
3636   ndbrequire(dropObjPtr.p->m_errorCode == 0);
3637 
3638   dropObjPtr.p->m_callback.m_callbackFunction =
3639     safe_cast(&Dbdict::restartDropObj_commit_start_done);
3640 
3641   if (f_dict_op[dropObjPtr.p->m_vt_index].m_commit_start)
3642     (this->*f_dict_op[dropObjPtr.p->m_vt_index].m_commit_start)
3643       (signal, dropObjPtr.p);
3644   else
3645     execute(signal, dropObjPtr.p->m_callback, 0);
3646 }
3647 
3648 void
restartDropObj_commit_start_done(Signal * signal,Uint32 callbackData,Uint32 returnCode)3649 Dbdict::restartDropObj_commit_start_done(Signal* signal,
3650                                          Uint32 callbackData,
3651                                          Uint32 returnCode)
3652 {
3653   jam();
3654   ndbrequire(returnCode == 0);
3655   DropObjRecordPtr dropObjPtr;
3656   ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
3657   ndbrequire(dropObjPtr.p->m_errorCode == 0);
3658 
3659   dropObjPtr.p->m_callback.m_callbackFunction =
3660     safe_cast(&Dbdict::restartDropObj_commit_complete_done);
3661 
3662   if (f_dict_op[dropObjPtr.p->m_vt_index].m_commit_complete)
3663     (this->*f_dict_op[dropObjPtr.p->m_vt_index].m_commit_complete)
3664       (signal, dropObjPtr.p);
3665   else
3666     execute(signal, dropObjPtr.p->m_callback, 0);
3667 }
3668 
3669 
3670 void
restartDropObj_commit_complete_done(Signal * signal,Uint32 callbackData,Uint32 returnCode)3671 Dbdict::restartDropObj_commit_complete_done(Signal* signal,
3672                                             Uint32 callbackData,
3673                                             Uint32 returnCode)
3674 {
3675   jam();
3676   ndbrequire(returnCode == 0);
3677   DropObjRecordPtr dropObjPtr;
3678   ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
3679   ndbrequire(dropObjPtr.p->m_errorCode == 0);
3680 
3681   c_opDropObj.release(dropObjPtr);
3682 
3683   c_restartRecord.activeTable++;
3684   checkSchemaStatus(signal);
3685 }
3686 
3687 /* **************************************************************** */
3688 /* ---------------------------------------------------------------- */
3689 /* MODULE:          NODE FAILURE HANDLING ------------------------- */
3690 /* ---------------------------------------------------------------- */
3691 /*                                                                  */
3692 /* This module contains the code that is used when nodes            */
3693 /* (kernel/api) fails.                                              */
3694 /* ---------------------------------------------------------------- */
3695 /* **************************************************************** */
3696 
3697 /* ---------------------------------------------------------------- */
3698 // We receive a report of an API that failed.
3699 /* ---------------------------------------------------------------- */
execAPI_FAILREQ(Signal * signal)3700 void Dbdict::execAPI_FAILREQ(Signal* signal)
3701 {
3702   jamEntry();
3703   Uint32 failedApiNode = signal->theData[0];
3704   BlockReference retRef = signal->theData[1];
3705 
3706 #if 0
3707   Uint32 userNode = refToNode(c_connRecord.userBlockRef);
3708   if (userNode == failedApiNode) {
3709     jam();
3710     c_connRecord.userBlockRef = (Uint32)-1;
3711   }//if
3712 #endif
3713 
3714   signal->theData[0] = failedApiNode;
3715   signal->theData[1] = reference();
3716   sendSignal(retRef, GSN_API_FAILCONF, signal, 2, JBB);
3717 }//execAPI_FAILREQ()
3718 
3719 /* ---------------------------------------------------------------- */
3720 // We receive a report of one or more node failures of kernel nodes.
3721 /* ---------------------------------------------------------------- */
execNODE_FAILREP(Signal * signal)3722 void Dbdict::execNODE_FAILREP(Signal* signal)
3723 {
3724   jamEntry();
3725   NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
3726 
3727   c_failureNr    = nodeFail->failNo;
3728   const Uint32 numberOfFailedNodes  = nodeFail->noOfNodes;
3729   const bool masterFailed = (c_masterNodeId != nodeFail->masterNodeId);
3730   c_masterNodeId = nodeFail->masterNodeId;
3731 
3732   c_noNodesFailed += numberOfFailedNodes;
3733   Uint32 theFailedNodes[NodeBitmask::Size];
3734   memcpy(theFailedNodes, nodeFail->theNodes, sizeof(theFailedNodes));
3735 
3736   c_counterMgr.execNODE_FAILREP(signal);
3737 
3738   bool ok = false;
3739   switch(c_blockState){
3740   case BS_IDLE:
3741     jam();
3742     ok = true;
3743     if(c_opRecordPool.getSize() !=
3744        (c_opRecordPool.getNoOfFree() +
3745 	c_opSubEvent.get_count() + c_opCreateEvent.get_count() +
3746 	c_opDropEvent.get_count() + c_opSignalUtil.get_count()))
3747     {
3748       jam();
3749       c_blockState = BS_NODE_FAILURE;
3750     }
3751     break;
3752   case BS_CREATE_TAB:
3753     jam();
3754     ok = true;
3755     if(!masterFailed)
3756       break;
3757     // fall through
3758   case BS_BUSY:
3759   case BS_NODE_FAILURE:
3760     jam();
3761     c_blockState = BS_NODE_FAILURE;
3762     ok = true;
3763     break;
3764   case BS_NODE_RESTART:
3765     jam();
3766     ok = true;
3767     break;
3768   }
3769   ndbrequire(ok);
3770 
3771   for(unsigned i = 1; i < MAX_NDB_NODES; i++) {
3772     jam();
3773     if(NodeBitmask::get(theFailedNodes, i)) {
3774       jam();
3775       NodeRecordPtr nodePtr;
3776       c_nodes.getPtr(nodePtr, i);
3777 
3778       nodePtr.p->nodeState = NodeRecord::NDB_NODE_DEAD;
3779       NFCompleteRep * const nfCompRep = (NFCompleteRep *)&signal->theData[0];
3780       nfCompRep->blockNo      = DBDICT;
3781       nfCompRep->nodeId       = getOwnNodeId();
3782       nfCompRep->failedNodeId = nodePtr.i;
3783       sendSignal(DBDIH_REF, GSN_NF_COMPLETEREP, signal,
3784 		 NFCompleteRep::SignalLength, JBB);
3785 
3786       c_aliveNodes.clear(i);
3787     }//if
3788   }//for
3789 
3790   /*
3791    * NODE_FAILREP guarantees that no "in flight" signal from
3792    * a dead node is accepted, and also that the job buffer contains
3793    * no such (un-executed) signals.  Therefore no DICT_UNLOCK_ORD
3794    * from a dead node (leading to master crash) is possible after
3795    * this clean-up removes the lock record.
3796    */
3797   removeStaleDictLocks(signal, theFailedNodes);
3798 
3799 }//execNODE_FAILREP()
3800 
3801 
3802 /* **************************************************************** */
3803 /* ---------------------------------------------------------------- */
3804 /* MODULE:          NODE START HANDLING --------------------------- */
3805 /* ---------------------------------------------------------------- */
3806 /*                                                                  */
3807 /* This module contains the code that is used when kernel nodes     */
3808 /* starts.                                                          */
3809 /* ---------------------------------------------------------------- */
3810 /* **************************************************************** */
3811 
3812 /* ---------------------------------------------------------------- */
3813 // Include a starting node in list of nodes to be part of adding
3814 // and dropping tables.
3815 /* ---------------------------------------------------------------- */
execINCL_NODEREQ(Signal * signal)3816 void Dbdict::execINCL_NODEREQ(Signal* signal)
3817 {
3818   jamEntry();
3819   NodeRecordPtr nodePtr;
3820   BlockReference retRef = signal->theData[0];
3821   nodePtr.i = signal->theData[1];
3822 
3823   ndbrequire(c_noNodesFailed > 0);
3824   c_noNodesFailed--;
3825 
3826   c_nodes.getPtr(nodePtr);
3827   ndbrequire(nodePtr.p->nodeState == NodeRecord::NDB_NODE_DEAD);
3828   nodePtr.p->nodeState = NodeRecord::NDB_NODE_ALIVE;
3829   signal->theData[0] = nodePtr.i;
3830   signal->theData[1] = reference();
3831   sendSignal(retRef, GSN_INCL_NODECONF, signal, 2, JBB);
3832 
3833   c_aliveNodes.set(nodePtr.i);
3834 }//execINCL_NODEREQ()
3835 
3836 /* **************************************************************** */
3837 /* ---------------------------------------------------------------- */
3838 /* MODULE:          ADD TABLE HANDLING ---------------------------- */
3839 /* ---------------------------------------------------------------- */
3840 /*                                                                  */
3841 /* This module contains the code that is used when adding a table.  */
3842 /* ---------------------------------------------------------------- */
3843 /* **************************************************************** */
3844 
3845 /* ---------------------------------------------------------------- */
3846 // This signal receives information about a table from either:
3847 // API, Ndbcntr or from other DICT.
3848 /* ---------------------------------------------------------------- */
3849 void
execCREATE_TABLE_REQ(Signal * signal)3850 Dbdict::execCREATE_TABLE_REQ(Signal* signal){
3851   jamEntry();
3852   if(!assembleFragments(signal)){
3853     return;
3854   }
3855 
3856   CreateTableReq* const req = (CreateTableReq*)signal->getDataPtr();
3857   const Uint32 senderRef = req->senderRef;
3858   const Uint32 senderData = req->senderData;
3859 
3860   ParseDictTabInfoRecord parseRecord;
3861   do {
3862     if(getOwnNodeId() != c_masterNodeId){
3863       jam();
3864       parseRecord.errorCode = CreateTableRef::NotMaster;
3865       break;
3866     }
3867 
3868     if (c_blockState == BS_NODE_RESTART){
3869       jam();
3870       parseRecord.errorCode = CreateTableRef::BusyWithNR;
3871       break;
3872     }
3873 
3874     if (c_blockState != BS_IDLE){
3875       jam();
3876       parseRecord.errorCode = CreateTableRef::Busy;
3877       break;
3878     }
3879 
3880     if (checkSingleUserMode(signal->getSendersBlockRef()))
3881     {
3882       jam();
3883       parseRecord.errorCode = CreateTableRef::SingleUser;
3884       break;
3885     }
3886 
3887     CreateTableRecordPtr createTabPtr;
3888     c_opCreateTable.seize(createTabPtr);
3889 
3890     if(createTabPtr.isNull()){
3891       jam();
3892       parseRecord.errorCode = CreateTableRef::Busy;
3893       break;
3894     }
3895 
3896     parseRecord.requestType = DictTabInfo::CreateTableFromAPI;
3897     parseRecord.errorCode = 0;
3898 
3899     SegmentedSectionPtr ptr;
3900     signal->getSection(ptr, CreateTableReq::DICT_TAB_INFO);
3901     SimplePropertiesSectionReader r(ptr, getSectionSegmentPool());
3902 
3903     handleTabInfoInit(r, &parseRecord);
3904     releaseSections(signal);
3905 
3906     if(parseRecord.errorCode != 0){
3907       jam();
3908       c_opCreateTable.release(createTabPtr);
3909       break;
3910     }
3911 
3912     createTabPtr.p->m_errorCode = 0;
3913     createTabPtr.p->m_senderRef = senderRef;
3914     createTabPtr.p->m_senderData = senderData;
3915     createTabPtr.p->m_tablePtrI = parseRecord.tablePtr.i;
3916     createTabPtr.p->m_coordinatorRef = reference();
3917     createTabPtr.p->m_fragmentsPtrI = RNIL;
3918     createTabPtr.p->m_dihAddFragPtr = RNIL;
3919 
3920     Uint32 key = c_opRecordSequence + 1;
3921     Uint32 *theData = signal->getDataPtrSend();
3922     Uint16 *frag_data= (Uint16*)&signal->theData[25];
3923     CreateFragmentationReq * const req = (CreateFragmentationReq*)theData;
3924     req->senderRef = reference();
3925     req->senderData = key;
3926     req->primaryTableId = parseRecord.tablePtr.p->primaryTableId;
3927     req->noOfFragments = parseRecord.tablePtr.p->fragmentCount;
3928     req->fragmentationType = parseRecord.tablePtr.p->fragmentType;
3929     MEMCOPY_NO_WORDS(frag_data, c_fragData, c_fragDataLen);
3930 
3931     if (parseRecord.tablePtr.p->isOrderedIndex()) {
3932       jam();
3933       // ordered index has same fragmentation as the table
3934       req->primaryTableId = parseRecord.tablePtr.p->primaryTableId;
3935       req->fragmentationType = DictTabInfo::DistrKeyOrderedIndex;
3936     }
3937     else if (parseRecord.tablePtr.p->isHashIndex())
3938     {
3939       jam();
3940       /*
3941         Unique hash indexes has same amount of fragments as primary table
3942         and distributed in the same manner but has always a normal hash
3943         fragmentation.
3944       */
3945       req->primaryTableId = parseRecord.tablePtr.p->primaryTableId;
3946       req->fragmentationType = DictTabInfo::DistrKeyUniqueHashIndex;
3947     }
3948     else
3949     {
3950       jam();
3951       /*
3952         Blob tables come here with primaryTableId != RNIL but we only need
3953         it for creating the fragments so we set it to RNIL now that we got
3954         what we wanted from it to avoid other side effects.
3955       */
3956       parseRecord.tablePtr.p->primaryTableId = RNIL;
3957     }
3958     EXECUTE_DIRECT(DBDIH, GSN_CREATE_FRAGMENTATION_REQ, signal,
3959 		   CreateFragmentationReq::SignalLength);
3960     jamEntry();
3961     if (signal->theData[0] != 0)
3962     {
3963       jam();
3964       parseRecord.errorCode= signal->theData[0];
3965       c_opCreateTable.release(createTabPtr);
3966       releaseTableObject(parseRecord.tablePtr.i, true);
3967       break;
3968     }
3969     createTabPtr.p->key = key;
3970     c_opRecordSequence++;
3971     c_opCreateTable.add(createTabPtr);
3972     c_blockState = BS_CREATE_TAB;
3973     return;
3974   } while(0);
3975 
3976   /**
3977    * Something went wrong
3978    */
3979 
3980   releaseSections(signal);
3981   CreateTableRef * ref = (CreateTableRef*)signal->getDataPtrSend();
3982   ref->senderData = senderData;
3983   ref->senderRef = reference();
3984   ref->masterNodeId = c_masterNodeId;
3985   ref->errorCode = parseRecord.errorCode;
3986   ref->errorLine = parseRecord.errorLine;
3987   ref->errorKey = parseRecord.errorKey;
3988   ref->status = parseRecord.status;
3989   sendSignal(senderRef, GSN_CREATE_TABLE_REF, signal,
3990 	     CreateTableRef::SignalLength, JBB);
3991 }
3992 
3993 void
execBACKUP_FRAGMENT_REQ(Signal * signal)3994 Dbdict::execBACKUP_FRAGMENT_REQ(Signal* signal)
3995 {
3996   jamEntry();
3997   Uint32 tableId = signal->theData[0];
3998   Uint32 lock = signal->theData[1];
3999 
4000   TableRecordPtr tablePtr;
4001   c_tableRecordPool.getPtr(tablePtr, tableId, true);
4002 
4003   if(lock)
4004   {
4005     ndbrequire(tablePtr.p->tabState == TableRecord::DEFINED);
4006     tablePtr.p->tabState = TableRecord::BACKUP_ONGOING;
4007   }
4008   else if(tablePtr.p->tabState == TableRecord::BACKUP_ONGOING)
4009   {
4010     tablePtr.p->tabState = TableRecord::DEFINED;
4011   }
4012 }
4013 
4014 bool
check_ndb_versions() const4015 Dbdict::check_ndb_versions() const
4016 {
4017   Uint32 node = 0;
4018   Uint32 version = getNodeInfo(getOwnNodeId()).m_version;
4019   while((node = c_aliveNodes.find(node + 1)) != BitmaskImpl::NotFound)
4020   {
4021     if(getNodeInfo(node).m_version != version)
4022     {
4023       return false;
4024     }
4025   }
4026   return true;
4027 }
4028 
4029 void
execALTER_TABLE_REQ(Signal * signal)4030 Dbdict::execALTER_TABLE_REQ(Signal* signal)
4031 {
4032   // Received by master
4033   jamEntry();
4034   if(!assembleFragments(signal)){
4035     return;
4036   }
4037   AlterTableReq* const req = (AlterTableReq*)signal->getDataPtr();
4038   const Uint32 senderRef = req->senderRef;
4039   const Uint32 senderData = req->senderData;
4040   const Uint32 changeMask = req->changeMask;
4041   const Uint32 tableId = req->tableId;
4042   const Uint32 tableVersion = req->tableVersion;
4043   ParseDictTabInfoRecord* aParseRecord;
4044 
4045   // Get table definition
4046   TableRecordPtr tablePtr;
4047   c_tableRecordPool.getPtr(tablePtr, tableId, false);
4048   if(tablePtr.isNull()){
4049     jam();
4050     alterTableRef(signal, req, AlterTableRef::NoSuchTable);
4051     return;
4052   }
4053 
4054   if(getOwnNodeId() != c_masterNodeId){
4055     jam();
4056     alterTableRef(signal, req, AlterTableRef::NotMaster);
4057     return;
4058   }
4059 
4060   if(c_blockState == BS_NODE_RESTART){
4061     jam();
4062     alterTableRef(signal, req, AlterTableRef::BusyWithNR);
4063     return;
4064   }
4065 
4066   if(c_blockState != BS_IDLE){
4067     jam();
4068     alterTableRef(signal, req, AlterTableRef::Busy);
4069     return;
4070   }
4071 
4072   if (!check_ndb_versions())
4073   {
4074     jam();
4075     alterTableRef(signal, req, AlterTableRef::IncompatibleVersions);
4076     return;
4077   }
4078 
4079   if (checkSingleUserMode(signal->getSendersBlockRef()))
4080   {
4081     jam();
4082     alterTableRef(signal, req, AlterTableRef::SingleUser);
4083     return;
4084   }
4085 
4086   const TableRecord::TabState tabState = tablePtr.p->tabState;
4087   bool ok = false;
4088   switch(tabState){
4089   case TableRecord::NOT_DEFINED:
4090   case TableRecord::DEFINING:
4091     jam();
4092     alterTableRef(signal, req, AlterTableRef::NoSuchTable);
4093     return;
4094   case TableRecord::DEFINED:
4095     ok = true;
4096     jam();
4097     break;
4098   case TableRecord::BACKUP_ONGOING:
4099     jam();
4100     alterTableRef(signal, req, AlterTableRef::BackupInProgress);
4101     return;
4102   case TableRecord::PREPARE_DROPPING:
4103   case TableRecord::DROPPING:
4104     jam();
4105     alterTableRef(signal, req, AlterTableRef::DropInProgress);
4106     return;
4107   }
4108   ndbrequire(ok);
4109 
4110   if(tablePtr.p->tableVersion != tableVersion){
4111     jam();
4112     alterTableRef(signal, req, AlterTableRef::InvalidTableVersion);
4113     return;
4114   }
4115   // Parse new table defintion
4116   ParseDictTabInfoRecord parseRecord;
4117   aParseRecord = &parseRecord;
4118 
4119   CreateTableRecordPtr alterTabPtr; // Reuse create table records
4120   c_opCreateTable.seize(alterTabPtr);
4121 
4122   if(alterTabPtr.isNull()){
4123     jam();
4124     alterTableRef(signal, req, AlterTableRef::Busy);
4125     return;
4126   }
4127 
4128   alterTabPtr.p->m_changeMask = changeMask;
4129   parseRecord.requestType = DictTabInfo::AlterTableFromAPI;
4130   parseRecord.errorCode = 0;
4131 
4132   SegmentedSectionPtr ptr;
4133   signal->getSection(ptr, AlterTableReq::DICT_TAB_INFO);
4134   SimplePropertiesSectionReader r(ptr, getSectionSegmentPool());
4135 
4136   handleTabInfoInit(r, &parseRecord, false); // Will not save info
4137 
4138   if(parseRecord.errorCode != 0){
4139     jam();
4140     c_opCreateTable.release(alterTabPtr);
4141     alterTableRef(signal, req,
4142 		  (AlterTableRef::ErrorCode) parseRecord.errorCode,
4143 		  aParseRecord);
4144     return;
4145   }
4146 
4147   releaseSections(signal);
4148   alterTabPtr.p->key = ++c_opRecordSequence;
4149   c_opCreateTable.add(alterTabPtr);
4150   ndbrequire(c_opCreateTable.find(alterTabPtr, alterTabPtr.p->key));
4151   alterTabPtr.p->m_errorCode = 0;
4152   alterTabPtr.p->m_senderRef = senderRef;
4153   alterTabPtr.p->m_senderData = senderData;
4154   alterTabPtr.p->m_tablePtrI = parseRecord.tablePtr.i;
4155   alterTabPtr.p->m_alterTableFailed = false;
4156   alterTabPtr.p->m_coordinatorRef = reference();
4157   alterTabPtr.p->m_fragmentsPtrI = RNIL;
4158   alterTabPtr.p->m_dihAddFragPtr = RNIL;
4159   alterTabPtr.p->m_alterTableId = tablePtr.p->tableId;
4160 
4161   // Send prepare request to all alive nodes
4162   SimplePropertiesSectionWriter w(getSectionSegmentPool());
4163   packTableIntoPages(w, parseRecord.tablePtr);
4164 
4165   SegmentedSectionPtr tabInfoPtr;
4166   w.getPtr(tabInfoPtr);
4167 
4168   alterTabPtr.p->m_tabInfoPtrI = tabInfoPtr.i;
4169 
4170   // Alter table on all nodes
4171   c_blockState = BS_BUSY;
4172 
4173   Mutex mutex(signal, c_mutexMgr, alterTabPtr.p->m_startLcpMutex);
4174   Callback c = { safe_cast(&Dbdict::alterTable_backup_mutex_locked),
4175 		 alterTabPtr.p->key };
4176 
4177   ndbrequire(mutex.lock(c));
4178 }
4179 
4180 void
alterTable_backup_mutex_locked(Signal * signal,Uint32 callbackData,Uint32 retValue)4181 Dbdict::alterTable_backup_mutex_locked(Signal* signal,
4182 				       Uint32 callbackData,
4183 				       Uint32 retValue)
4184 {
4185   jamEntry();
4186 
4187   ndbrequire(retValue == 0);
4188 
4189   CreateTableRecordPtr alterTabPtr;
4190   ndbrequire(c_opCreateTable.find(alterTabPtr, callbackData));
4191 
4192   TableRecordPtr tablePtr;
4193   c_tableRecordPool.getPtr(tablePtr, alterTabPtr.p->m_alterTableId, true);
4194 
4195   Mutex mutex(signal, c_mutexMgr, alterTabPtr.p->m_startLcpMutex);
4196   mutex.unlock(); // ignore response
4197 
4198   SegmentedSectionPtr tabInfoPtr;
4199   getSection(tabInfoPtr, alterTabPtr.p->m_tabInfoPtrI);
4200   signal->setSection(tabInfoPtr, AlterTabReq::DICT_TAB_INFO);
4201 
4202   alterTabPtr.p->m_tabInfoPtrI = RNIL;
4203 
4204   if(tablePtr.p->tabState == TableRecord::BACKUP_ONGOING)
4205   {
4206     jam();
4207     AlterTableReq* req = (AlterTableReq*)signal->getDataPtr();
4208     req->senderData = alterTabPtr.p->m_senderData;
4209     req->senderRef = alterTabPtr.p->m_senderRef;
4210     alterTableRef(signal, req, AlterTableRef::BackupInProgress);
4211 
4212     c_tableRecordPool.getPtr(tablePtr, alterTabPtr.p->m_tablePtrI);
4213     releaseTableObject(tablePtr.i, false);
4214 
4215     c_opCreateTable.release(alterTabPtr);
4216     c_blockState = BS_IDLE;
4217     return;
4218   }
4219 
4220   NodeReceiverGroup rg(DBDICT, c_aliveNodes);
4221   alterTabPtr.p->m_coordinatorData.m_gsn = GSN_ALTER_TAB_REQ;
4222   SafeCounter safeCounter(c_counterMgr,
4223 			  alterTabPtr.p->m_coordinatorData.m_counter);
4224   safeCounter.init<AlterTabRef>(rg, alterTabPtr.p->key);
4225 
4226   AlterTabReq * const lreq = (AlterTabReq*)signal->getDataPtrSend();
4227   lreq->senderRef = reference();
4228   lreq->senderData = alterTabPtr.p->key;
4229   lreq->clientRef = alterTabPtr.p->m_senderRef;
4230   lreq->clientData = alterTabPtr.p->m_senderData;
4231   lreq->changeMask = alterTabPtr.p->m_changeMask;
4232   lreq->tableId = tablePtr.p->tableId;
4233   lreq->tableVersion = alter_obj_inc_schema_version(tablePtr.p->tableVersion);
4234   lreq->gci = tablePtr.p->gciTableCreated;
4235   lreq->requestType = AlterTabReq::AlterTablePrepare;
4236 
4237   sendFragmentedSignal(rg, GSN_ALTER_TAB_REQ, signal,
4238 		       AlterTabReq::SignalLength, JBB);
4239 }
4240 
alterTableRef(Signal * signal,AlterTableReq * req,AlterTableRef::ErrorCode errCode,ParseDictTabInfoRecord * parseRecord)4241 void Dbdict::alterTableRef(Signal * signal,
4242 			   AlterTableReq * req,
4243 			   AlterTableRef::ErrorCode errCode,
4244 			   ParseDictTabInfoRecord* parseRecord)
4245 {
4246   jam();
4247   releaseSections(signal);
4248   AlterTableRef * ref = (AlterTableRef*)signal->getDataPtrSend();
4249   Uint32 senderRef = req->senderRef;
4250   ref->senderData = req->senderData;
4251   ref->senderRef = reference();
4252   ref->masterNodeId = c_masterNodeId;
4253   if (parseRecord) {
4254     ref->errorCode = parseRecord->errorCode;
4255     ref->errorLine = parseRecord->errorLine;
4256     ref->errorKey = parseRecord->errorKey;
4257     ref->status = parseRecord->status;
4258   }
4259   else {
4260     ref->errorCode = errCode;
4261     ref->errorLine = 0;
4262     ref->errorKey = 0;
4263     ref->status = 0;
4264   }
4265   sendSignal(senderRef, GSN_ALTER_TABLE_REF, signal,
4266 	     AlterTableRef::SignalLength, JBB);
4267 }
4268 
4269 void
execALTER_TAB_REQ(Signal * signal)4270 Dbdict::execALTER_TAB_REQ(Signal * signal)
4271 {
4272   // Received in all nodes to handle change locally
4273   jamEntry();
4274 
4275   if(!assembleFragments(signal)){
4276     return;
4277   }
4278   AlterTabReq* const req = (AlterTabReq*)signal->getDataPtr();
4279   const Uint32 senderRef = req->senderRef;
4280   const Uint32 senderData = req->senderData;
4281   const Uint32 changeMask = req->changeMask;
4282   const Uint32 tableId = req->tableId;
4283   const Uint32 tableVersion = req->tableVersion;
4284   const Uint32 gci = req->gci;
4285   AlterTabReq::RequestType requestType =
4286     (AlterTabReq::RequestType) req->requestType;
4287 
4288   SegmentedSectionPtr tabInfoPtr;
4289   signal->getSection(tabInfoPtr, AlterTabReq::DICT_TAB_INFO);
4290 
4291   CreateTableRecordPtr alterTabPtr; // Reuse create table records
4292 
4293   if (senderRef != reference()) {
4294     jam();
4295     c_blockState = BS_BUSY;
4296   }
4297   if ((requestType == AlterTabReq::AlterTablePrepare)
4298       && (senderRef != reference())) {
4299     jam();
4300     c_opCreateTable.seize(alterTabPtr);
4301     if(!alterTabPtr.isNull())
4302       alterTabPtr.p->m_changeMask = changeMask;
4303   }
4304   else {
4305     jam();
4306     ndbrequire(c_opCreateTable.find(alterTabPtr, senderData));
4307   }
4308   if(alterTabPtr.isNull()){
4309     jam();
4310     alterTabRef(signal, req, AlterTableRef::Busy);
4311     return;
4312   }
4313 
4314   if (!check_ndb_versions())
4315   {
4316     jam();
4317     alterTabRef(signal, req, AlterTableRef::IncompatibleVersions);
4318     return;
4319   }
4320 
4321   alterTabPtr.p->m_alterTableId = tableId;
4322   alterTabPtr.p->m_coordinatorRef = senderRef;
4323 
4324   // Get table definition
4325   TableRecordPtr tablePtr;
4326   c_tableRecordPool.getPtr(tablePtr, tableId, false);
4327   if(tablePtr.isNull()){
4328     jam();
4329     alterTabRef(signal, req, AlterTableRef::NoSuchTable);
4330     return;
4331   }
4332 
4333   switch(requestType) {
4334   case(AlterTabReq::AlterTablePrepare): {
4335     ParseDictTabInfoRecord* aParseRecord;
4336 
4337     const TableRecord::TabState tabState = tablePtr.p->tabState;
4338     bool ok = false;
4339     switch(tabState){
4340     case TableRecord::NOT_DEFINED:
4341     case TableRecord::DEFINING:
4342       jam();
4343       alterTabRef(signal, req, AlterTableRef::NoSuchTable);
4344       return;
4345     case TableRecord::DEFINED:
4346       ok = true;
4347       jam();
4348       break;
4349     case TableRecord::PREPARE_DROPPING:
4350     case TableRecord::DROPPING:
4351       jam();
4352       alterTabRef(signal, req, AlterTableRef::DropInProgress);
4353       return;
4354     case TableRecord::BACKUP_ONGOING:
4355       jam();
4356       alterTabRef(signal, req, AlterTableRef::BackupInProgress);
4357       return;
4358     }
4359     ndbrequire(ok);
4360 
4361     if(alter_obj_inc_schema_version(tablePtr.p->tableVersion) != tableVersion){
4362       jam();
4363       alterTabRef(signal, req, AlterTableRef::InvalidTableVersion);
4364       return;
4365     }
4366     TableRecordPtr newTablePtr;
4367     if (senderRef  != reference()) {
4368       jam();
4369       // Parse altered table defintion
4370       ParseDictTabInfoRecord parseRecord;
4371       aParseRecord = &parseRecord;
4372 
4373       parseRecord.requestType = DictTabInfo::AlterTableFromAPI;
4374       parseRecord.errorCode = 0;
4375 
4376       SimplePropertiesSectionReader r(tabInfoPtr, getSectionSegmentPool());
4377 
4378       handleTabInfoInit(r, &parseRecord, false); // Will not save info
4379 
4380       if(parseRecord.errorCode != 0){
4381 	jam();
4382 	c_opCreateTable.release(alterTabPtr);
4383 	alterTabRef(signal, req,
4384 		    (AlterTableRef::ErrorCode) parseRecord.errorCode,
4385 		    aParseRecord);
4386 	return;
4387       }
4388       alterTabPtr.p->key = senderData;
4389       c_opCreateTable.add(alterTabPtr);
4390       alterTabPtr.p->m_errorCode = 0;
4391       alterTabPtr.p->m_senderRef = senderRef;
4392       alterTabPtr.p->m_senderData = senderData;
4393       alterTabPtr.p->m_tablePtrI = parseRecord.tablePtr.i;
4394       alterTabPtr.p->m_fragmentsPtrI = RNIL;
4395       alterTabPtr.p->m_dihAddFragPtr = RNIL;
4396       newTablePtr = parseRecord.tablePtr;
4397       newTablePtr.p->tableVersion = tableVersion;
4398     }
4399     else { // (req->senderRef  == reference())
4400       jam();
4401       c_tableRecordPool.getPtr(newTablePtr, alterTabPtr.p->m_tablePtrI);
4402       newTablePtr.p->tableVersion = tableVersion;
4403     }
4404     if (handleAlterTab(req, alterTabPtr.p, tablePtr, newTablePtr) == -1) {
4405       jam();
4406       c_opCreateTable.release(alterTabPtr);
4407       alterTabRef(signal, req, AlterTableRef::UnsupportedChange);
4408       return;
4409     }
4410     releaseSections(signal);
4411     // Propagate alter table to other local blocks
4412     AlterTabReq * req = (AlterTabReq*)signal->getDataPtrSend();
4413     req->senderRef = reference();
4414     req->senderData = senderData;
4415     req->changeMask = changeMask;
4416     req->tableId = tableId;
4417     req->tableVersion = tableVersion;
4418     req->gci = gci;
4419     req->requestType = requestType;
4420     sendSignal(DBLQH_REF, GSN_ALTER_TAB_REQ, signal,
4421 	       AlterTabReq::SignalLength, JBB);
4422     return;
4423   }
4424   case(AlterTabReq::AlterTableCommit): {
4425     jam();
4426     // Write schema for altered table to disk
4427     SegmentedSectionPtr tabInfoPtr;
4428     signal->getSection(tabInfoPtr, AlterTabReq::DICT_TAB_INFO);
4429     alterTabPtr.p->m_tabInfoPtrI = tabInfoPtr.i;
4430     bool savetodisk = !(tablePtr.p->m_bits & TableRecord::TR_Temporary);
4431 
4432     signal->header.m_noOfSections = 0;
4433 
4434     // Update table record
4435     tablePtr.p->packedSize = tabInfoPtr.sz;
4436     tablePtr.p->tableVersion = tableVersion;
4437     tablePtr.p->gciTableCreated = gci;
4438 
4439     SchemaFile::TableEntry tabEntry;
4440     tabEntry.m_tableVersion = tableVersion;
4441     tabEntry.m_tableType    = tablePtr.p->tableType;
4442     if (savetodisk)
4443       tabEntry.m_tableState   = SchemaFile::ALTER_TABLE_COMMITTED;
4444     else
4445       tabEntry.m_tableState   = SchemaFile::TEMPORARY_TABLE_COMMITTED;
4446     tabEntry.m_gcp          = gci;
4447     tabEntry.m_info_words   = tabInfoPtr.sz;
4448     memset(tabEntry.m_unused, 0, sizeof(tabEntry.m_unused));
4449 
4450     Callback callback;
4451     callback.m_callbackData = senderData;
4452     callback.m_callbackFunction =
4453       safe_cast(&Dbdict::alterTab_writeSchemaConf);
4454 
4455     updateSchemaState(signal, tableId, &tabEntry, &callback, savetodisk);
4456     break;
4457   }
4458   case(AlterTabReq::AlterTableRevert): {
4459     jam();
4460     // Revert failed alter table
4461     revertAlterTable(signal, changeMask, tableId, alterTabPtr.p);
4462     // Acknowledge the reverted alter table
4463     AlterTabConf * conf = (AlterTabConf*)signal->getDataPtrSend();
4464     conf->senderRef = reference();
4465     conf->senderData = senderData;
4466     conf->changeMask = changeMask;
4467     conf->tableId = tableId;
4468     conf->tableVersion = tableVersion;
4469     conf->gci = gci;
4470     conf->requestType = requestType;
4471     sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal,
4472 	       AlterTabConf::SignalLength, JBB);
4473     break;
4474   }
4475   default: ndbrequire(false);
4476   }
4477 }
4478 
alterTabRef(Signal * signal,AlterTabReq * req,AlterTableRef::ErrorCode errCode,ParseDictTabInfoRecord * parseRecord)4479 void Dbdict::alterTabRef(Signal * signal,
4480 			 AlterTabReq * req,
4481 			 AlterTableRef::ErrorCode errCode,
4482 			 ParseDictTabInfoRecord* parseRecord)
4483 {
4484   jam();
4485   releaseSections(signal);
4486   AlterTabRef * ref = (AlterTabRef*)signal->getDataPtrSend();
4487   Uint32 senderRef = req->senderRef;
4488   ref->senderData = req->senderData;
4489   ref->senderRef = reference();
4490   if (parseRecord) {
4491     jam();
4492     ref->errorCode = parseRecord->errorCode;
4493     ref->errorLine = parseRecord->errorLine;
4494     ref->errorKey = parseRecord->errorKey;
4495     ref->errorStatus = parseRecord->status;
4496   }
4497   else {
4498     jam();
4499     ref->errorCode = errCode;
4500     ref->errorLine = 0;
4501     ref->errorKey = 0;
4502     ref->errorStatus = 0;
4503   }
4504   sendSignal(senderRef, GSN_ALTER_TAB_REF, signal,
4505 	     AlterTabRef::SignalLength, JBB);
4506 
4507   c_blockState = BS_IDLE;
4508 }
4509 
execALTER_TAB_REF(Signal * signal)4510 void Dbdict::execALTER_TAB_REF(Signal * signal){
4511   jamEntry();
4512 
4513   AlterTabRef * ref = (AlterTabRef*)signal->getDataPtr();
4514 
4515   Uint32 senderRef = ref->senderRef;
4516   Uint32 senderData = ref->senderData;
4517   Uint32 errorCode = ref->errorCode;
4518   Uint32 errorLine = ref->errorLine;
4519   Uint32 errorKey = ref->errorKey;
4520   Uint32 errorStatus = ref->errorStatus;
4521   AlterTabReq::RequestType requestType =
4522     (AlterTabReq::RequestType) ref->requestType;
4523   CreateTableRecordPtr alterTabPtr;
4524   ndbrequire(c_opCreateTable.find(alterTabPtr, senderData));
4525   Uint32 changeMask = alterTabPtr.p->m_changeMask;
4526   SafeCounter safeCounter(c_counterMgr, alterTabPtr.p->m_coordinatorData.m_counter);
4527   safeCounter.clearWaitingFor(refToNode(senderRef));
4528   switch (requestType) {
4529   case(AlterTabReq::AlterTablePrepare): {
4530     if (safeCounter.done()) {
4531       jam();
4532       // Send revert request to all alive nodes
4533       TableRecordPtr tablePtr;
4534       c_tableRecordPool.getPtr(tablePtr, alterTabPtr.p->m_alterTableId);
4535       Uint32 tableId = tablePtr.p->tableId;
4536       Uint32 tableVersion = tablePtr.p->tableVersion;
4537       Uint32 gci = tablePtr.p->gciTableCreated;
4538       SimplePropertiesSectionWriter w(getSectionSegmentPool());
4539       packTableIntoPages(w, tablePtr);
4540       SegmentedSectionPtr spDataPtr;
4541       w.getPtr(spDataPtr);
4542       signal->setSection(spDataPtr, AlterTabReq::DICT_TAB_INFO);
4543 
4544       NodeReceiverGroup rg(DBDICT, c_aliveNodes);
4545       alterTabPtr.p->m_coordinatorData.m_gsn = GSN_ALTER_TAB_REQ;
4546       safeCounter.init<AlterTabRef>(rg, alterTabPtr.p->key);
4547 
4548       AlterTabReq * const lreq = (AlterTabReq*)signal->getDataPtrSend();
4549       lreq->senderRef = reference();
4550       lreq->senderData = alterTabPtr.p->key;
4551       lreq->clientRef = alterTabPtr.p->m_senderRef;
4552       lreq->clientData = alterTabPtr.p->m_senderData;
4553       lreq->changeMask = changeMask;
4554       lreq->tableId = tableId;
4555       lreq->tableVersion = tableVersion;
4556       lreq->gci = gci;
4557       lreq->requestType = AlterTabReq::AlterTableRevert;
4558 
4559       sendSignal(rg, GSN_ALTER_TAB_REQ, signal,
4560 		 AlterTabReq::SignalLength, JBB);
4561     }
4562     else {
4563       jam();
4564       alterTabPtr.p->m_alterTableFailed = true;
4565     }
4566     break;
4567   }
4568   case(AlterTabReq::AlterTableCommit):
4569     jam();
4570   case(AlterTabReq::AlterTableRevert): {
4571     AlterTableRef * apiRef = (AlterTableRef*)signal->getDataPtrSend();
4572 
4573     apiRef->senderData = senderData;
4574     apiRef->senderRef = reference();
4575     apiRef->masterNodeId = c_masterNodeId;
4576     apiRef->errorCode = errorCode;
4577     apiRef->errorLine = errorLine;
4578     apiRef->errorKey = errorKey;
4579     apiRef->status = errorStatus;
4580     if (safeCounter.done()) {
4581       jam();
4582       sendSignal(senderRef, GSN_ALTER_TABLE_REF, signal,
4583 		 AlterTableRef::SignalLength, JBB);
4584       c_blockState = BS_IDLE;
4585     }
4586     else {
4587       jam();
4588       alterTabPtr.p->m_alterTableFailed = true;
4589       alterTabPtr.p->m_alterTableRef = *apiRef;
4590     }
4591     break;
4592   }
4593   default: ndbrequire(false);
4594   }
4595 }
4596 
4597 void
execALTER_TAB_CONF(Signal * signal)4598 Dbdict::execALTER_TAB_CONF(Signal * signal){
4599   jamEntry();
4600   AlterTabConf * const conf = (AlterTabConf*)signal->getDataPtr();
4601   Uint32 senderRef = conf->senderRef;
4602   Uint32 senderData = conf->senderData;
4603   Uint32 changeMask = conf->changeMask;
4604   Uint32 tableId = conf->tableId;
4605   Uint32 tableVersion = conf->tableVersion;
4606   Uint32 gci = conf->gci;
4607   AlterTabReq::RequestType requestType =
4608     (AlterTabReq::RequestType) conf->requestType;
4609   CreateTableRecordPtr alterTabPtr;
4610   ndbrequire(c_opCreateTable.find(alterTabPtr, senderData));
4611 
4612   switch (requestType) {
4613   case(AlterTabReq::AlterTablePrepare): {
4614     switch(refToBlock(signal->getSendersBlockRef())) {
4615     case DBLQH: {
4616       jam();
4617       AlterTabReq * req = (AlterTabReq*)signal->getDataPtrSend();
4618       req->senderRef = reference();
4619       req->senderData = senderData;
4620       req->changeMask = changeMask;
4621       req->tableId = tableId;
4622       req->tableVersion = tableVersion;
4623       req->gci = gci;
4624       req->requestType = requestType;
4625       sendSignal(DBDIH_REF, GSN_ALTER_TAB_REQ, signal,
4626 		 AlterTabReq::SignalLength, JBB);
4627       return;
4628     }
4629     case DBDIH: {
4630       jam();
4631       AlterTabReq * req = (AlterTabReq*)signal->getDataPtrSend();
4632       req->senderRef = reference();
4633       req->senderData = senderData;
4634       req->changeMask = changeMask;
4635       req->tableId = tableId;
4636       req->tableVersion = tableVersion;
4637       req->gci = gci;
4638       req->requestType = requestType;
4639       sendSignal(DBTC_REF, GSN_ALTER_TAB_REQ, signal,
4640 		 AlterTabReq::SignalLength, JBB);
4641       return;
4642     }
4643     case DBTC: {
4644       jam();
4645       // Participant is done with prepare phase, send conf to coordinator
4646       AlterTabConf * conf = (AlterTabConf*)signal->getDataPtrSend();
4647       conf->senderRef = reference();
4648       conf->senderData = senderData;
4649       conf->changeMask = changeMask;
4650       conf->tableId = tableId;
4651       conf->tableVersion = tableVersion;
4652       conf->gci = gci;
4653       conf->requestType = requestType;
4654       sendSignal(alterTabPtr.p->m_coordinatorRef, GSN_ALTER_TAB_CONF, signal,
4655 		 AlterTabConf::SignalLength, JBB);
4656       return;
4657     }
4658     default :break;
4659     }
4660     // Coordinator only
4661     SafeCounter safeCounter(c_counterMgr, alterTabPtr.p->m_coordinatorData.m_counter);
4662     safeCounter.clearWaitingFor(refToNode(senderRef));
4663     if (safeCounter.done()) {
4664       jam();
4665       // We have received all local confirmations
4666       if (alterTabPtr.p->m_alterTableFailed) {
4667 	jam();
4668 	// Send revert request to all alive nodes
4669 	TableRecordPtr tablePtr;
4670 	c_tableRecordPool.getPtr(tablePtr, alterTabPtr.p->m_alterTableId);
4671 	Uint32 tableId = tablePtr.p->tableId;
4672 	Uint32 tableVersion = tablePtr.p->tableVersion;
4673 	Uint32 gci = tablePtr.p->gciTableCreated;
4674 	SimplePropertiesSectionWriter w(getSectionSegmentPool());
4675 	packTableIntoPages(w, tablePtr);
4676 	SegmentedSectionPtr spDataPtr;
4677 	w.getPtr(spDataPtr);
4678 	signal->setSection(spDataPtr, AlterTabReq::DICT_TAB_INFO);
4679 
4680 	NodeReceiverGroup rg(DBDICT, c_aliveNodes);
4681 	alterTabPtr.p->m_coordinatorData.m_gsn = GSN_ALTER_TAB_REQ;
4682 	safeCounter.init<AlterTabRef>(rg, alterTabPtr.p->key);
4683 
4684 	AlterTabReq * const lreq = (AlterTabReq*)signal->getDataPtrSend();
4685 	lreq->senderRef = reference();
4686 	lreq->senderData = alterTabPtr.p->key;
4687 	lreq->clientRef = alterTabPtr.p->m_senderRef;
4688 	lreq->clientData = alterTabPtr.p->m_senderData;
4689 	lreq->changeMask = changeMask;
4690 	lreq->tableId = tableId;
4691 	lreq->tableVersion = tableVersion;
4692 	lreq->gci = gci;
4693 	lreq->requestType = AlterTabReq::AlterTableRevert;
4694 
4695 	sendSignal(rg, GSN_ALTER_TAB_REQ, signal,
4696 		   AlterTabReq::SignalLength, JBB);
4697       }
4698       else {
4699 	jam();
4700 	// Send commit request to all alive nodes
4701 	TableRecordPtr tablePtr;
4702 	c_tableRecordPool.getPtr(tablePtr, tableId);
4703 	SimplePropertiesSectionWriter w(getSectionSegmentPool());
4704 	packTableIntoPages(w, tablePtr);
4705 	SegmentedSectionPtr spDataPtr;
4706 	w.getPtr(spDataPtr);
4707 	signal->setSection(spDataPtr, AlterTabReq::DICT_TAB_INFO);
4708 
4709 	NodeReceiverGroup rg(DBDICT, c_aliveNodes);
4710 	alterTabPtr.p->m_coordinatorData.m_gsn = GSN_ALTER_TAB_REQ;
4711 	safeCounter.init<AlterTabRef>(rg, alterTabPtr.p->key);
4712 
4713 	AlterTabReq * const lreq = (AlterTabReq*)signal->getDataPtrSend();
4714 	lreq->senderRef = reference();
4715 	lreq->senderData = alterTabPtr.p->key;
4716 	lreq->clientRef = alterTabPtr.p->m_senderRef;
4717 	lreq->clientData = alterTabPtr.p->m_senderData;
4718 	lreq->changeMask = changeMask;
4719 	lreq->tableId = tableId;
4720 	lreq->tableVersion = tableVersion;
4721 	lreq->gci = gci;
4722 	lreq->requestType = AlterTabReq::AlterTableCommit;
4723 
4724 	sendFragmentedSignal(rg, GSN_ALTER_TAB_REQ, signal,
4725 			     AlterTabReq::SignalLength, JBB);
4726       }
4727     }
4728     else {
4729       // (!safeCounter.done())
4730       jam();
4731     }
4732     break;
4733   }
4734   case(AlterTabReq::AlterTableRevert):
4735     jam();
4736   case(AlterTabReq::AlterTableCommit): {
4737     SafeCounter safeCounter(c_counterMgr, alterTabPtr.p->m_coordinatorData.m_counter);
4738     safeCounter.clearWaitingFor(refToNode(senderRef));
4739     if (safeCounter.done()) {
4740       jam();
4741       // We have received all local confirmations
4742       releaseSections(signal);
4743       if (alterTabPtr.p->m_alterTableFailed) {
4744 	jam();
4745 	AlterTableRef * apiRef =
4746 	  (AlterTableRef*)signal->getDataPtrSend();
4747 	*apiRef = alterTabPtr.p->m_alterTableRef;
4748 	sendSignal(alterTabPtr.p->m_senderRef, GSN_ALTER_TABLE_REF, signal,
4749 		   AlterTableRef::SignalLength, JBB);
4750       }
4751       else {
4752 	jam();
4753 	// Alter table completed, inform API
4754 	AlterTableConf * const apiConf =
4755 	  (AlterTableConf*)signal->getDataPtrSend();
4756 	apiConf->senderRef = reference();
4757 	apiConf->senderData = alterTabPtr.p->m_senderData;
4758 	apiConf->tableId = tableId;
4759 	apiConf->tableVersion = tableVersion;
4760 
4761 	//@todo check api failed
4762 	sendSignal(alterTabPtr.p->m_senderRef, GSN_ALTER_TABLE_CONF, signal,
4763 		   AlterTableConf::SignalLength, JBB);
4764       }
4765 
4766       // Release resources
4767       TableRecordPtr tabPtr;
4768       c_tableRecordPool.getPtr(tabPtr, alterTabPtr.p->m_tablePtrI);
4769       releaseTableObject(tabPtr.i, false);
4770       releaseCreateTableOp(signal,alterTabPtr);
4771       c_blockState = BS_IDLE;
4772     }
4773     else {
4774       // (!safeCounter.done())
4775       jam();
4776     }
4777     break;
4778   }
4779   default: ndbrequire(false);
4780   }
4781 }
4782 
4783 // For debugging
4784 inline
printTables()4785 void Dbdict::printTables()
4786 {
4787   DLHashTable<DictObject>::Iterator iter;
4788   bool moreTables = c_obj_hash.first(iter);
4789   printf("OBJECTS IN DICT:\n");
4790   char name[MAX_TAB_NAME_SIZE];
4791   while (moreTables) {
4792     Ptr<DictObject> tablePtr = iter.curr;
4793     ConstRope r(c_rope_pool, tablePtr.p->m_name);
4794     r.copy(name);
4795     printf("%s ", name);
4796     moreTables = c_obj_hash.next(iter);
4797   }
4798   printf("\n");
4799 }
4800 
handleAlterTab(AlterTabReq * req,CreateTableRecord * alterTabPtrP,TableRecordPtr origTablePtr,TableRecordPtr newTablePtr)4801 int Dbdict::handleAlterTab(AlterTabReq * req,
4802 			   CreateTableRecord * alterTabPtrP,
4803 			   TableRecordPtr origTablePtr,
4804 			   TableRecordPtr newTablePtr)
4805 {
4806   bool supportedAlteration = false;
4807   Uint32 changeMask = req->changeMask;
4808 
4809   if (AlterTableReq::getNameFlag(changeMask)) {
4810     jam();
4811     // Table rename
4812     supportedAlteration = true;
4813     // Remove from hashtable
4814     Ptr<DictObject> obj_ptr;
4815     c_obj_pool.getPtr(obj_ptr, origTablePtr.p->m_obj_ptr_i);
4816     c_obj_hash.remove(obj_ptr);
4817     {
4818       Rope org(c_rope_pool, origTablePtr.p->tableName);
4819       org.copy(alterTabPtrP->previousTableName);
4820 
4821       ConstRope src(c_rope_pool, newTablePtr.p->tableName);
4822       char tmp[MAX_TAB_NAME_SIZE];
4823       const int len = src.size();
4824       src.copy(tmp);
4825       ndbrequire(org.assign(tmp, len));
4826     }
4827     obj_ptr.p->m_name = origTablePtr.p->tableName;
4828     // Put it back
4829     c_obj_hash.add(obj_ptr);
4830   }
4831 
4832   if (AlterTableReq::getFrmFlag(changeMask)) {
4833     // Table definition changed (new frm)
4834     supportedAlteration = true;
4835     // Save old definition
4836     Rope org(c_rope_pool, origTablePtr.p->frmData);
4837     org.copy(alterTabPtrP->previousFrmData);
4838     alterTabPtrP->previousFrmLen = org.size();
4839 
4840     // Set new definition
4841     ConstRope src(c_rope_pool, newTablePtr.p->frmData);
4842     char tmp[MAX_FRM_DATA_SIZE];
4843     src.copy(tmp);
4844     ndbrequire(org.assign(tmp, src.size()));
4845   }
4846 
4847 /*
4848   TODO RONM: Lite ny kod f�r FragmentData och RangeOrListData
4849 */
4850   if (supportedAlteration)
4851   {
4852     // Set new schema version
4853     origTablePtr.p->tableVersion = newTablePtr.p->tableVersion;
4854     return 0;
4855   }
4856   else
4857   {
4858     jam();
4859     return -1;
4860   }
4861 }
4862 
revertAlterTable(Signal * signal,Uint32 changeMask,Uint32 tableId,CreateTableRecord * alterTabPtrP)4863 void Dbdict::revertAlterTable(Signal * signal,
4864 			      Uint32 changeMask,
4865 			      Uint32 tableId,
4866 			      CreateTableRecord * alterTabPtrP)
4867 {
4868   bool supportedAlteration = false;
4869 
4870   TableRecordPtr tablePtr;
4871   c_tableRecordPool.getPtr(tablePtr, tableId);
4872 
4873   if (AlterTableReq::getNameFlag(changeMask)) {
4874     jam();
4875     // Table rename
4876     supportedAlteration = true;
4877     // Restore previous name
4878 
4879     Ptr<DictObject> obj_ptr;
4880     c_obj_pool.getPtr(obj_ptr, tablePtr.p->m_obj_ptr_i);
4881     c_obj_hash.remove(obj_ptr);
4882 
4883     {
4884       // Restore name
4885       Rope org(c_rope_pool, tablePtr.p->tableName);
4886       ndbrequire(org.assign(alterTabPtrP->previousTableName));
4887     }
4888     obj_ptr.p->m_name = tablePtr.p->tableName;
4889     // Put it back
4890     c_obj_hash.add(obj_ptr);
4891   }
4892 
4893   if (AlterTableReq::getFrmFlag(changeMask))
4894   {
4895     jam();
4896     // Table redefinition
4897     supportedAlteration = true;
4898     // Restore previous frm
4899     Rope org(c_rope_pool, tablePtr.p->tableName);
4900     ndbrequire(org.assign(alterTabPtrP->previousFrmData,
4901 			  alterTabPtrP->previousFrmLen));
4902 
4903   }
4904 
4905 
4906   if (supportedAlteration)
4907   {
4908     tablePtr.p->tableVersion =
4909       alter_obj_dec_schema_version(tablePtr.p->tableVersion);
4910     return;
4911   }
4912 
4913   ndbrequire(false);
4914 }
4915 
4916 void
alterTab_writeSchemaConf(Signal * signal,Uint32 callbackData,Uint32 returnCode)4917 Dbdict::alterTab_writeSchemaConf(Signal* signal,
4918 				 Uint32 callbackData,
4919 				 Uint32 returnCode)
4920 {
4921   jam();
4922   Uint32 key = callbackData;
4923   CreateTableRecordPtr alterTabPtr;
4924   ndbrequire(c_opCreateTable.find(alterTabPtr, key));
4925   Uint32 tableId = alterTabPtr.p->m_alterTableId;
4926 
4927   Callback callback;
4928   callback.m_callbackData = alterTabPtr.p->key;
4929   callback.m_callbackFunction =
4930     safe_cast(&Dbdict::alterTab_writeTableConf);
4931 
4932   TableRecordPtr tablePtr;
4933   c_tableRecordPool.getPtr(tablePtr, tableId);
4934   bool savetodisk = !(tablePtr.p->m_bits & TableRecord::TR_Temporary);
4935   if (savetodisk)
4936   {
4937     SegmentedSectionPtr tabInfoPtr;
4938     getSection(tabInfoPtr, alterTabPtr.p->m_tabInfoPtrI);
4939     writeTableFile(signal, tableId, tabInfoPtr, &callback);
4940   }
4941   else
4942   {
4943     execute(signal, callback, 0);
4944   }
4945 }
4946 
4947 void
alterTab_writeTableConf(Signal * signal,Uint32 callbackData,Uint32 returnCode)4948 Dbdict::alterTab_writeTableConf(Signal* signal,
4949 				Uint32 callbackData,
4950 				Uint32 returnCode)
4951 {
4952   jam();
4953   CreateTableRecordPtr alterTabPtr;
4954   ndbrequire(c_opCreateTable.find(alterTabPtr, callbackData));
4955   Uint32 coordinatorRef = alterTabPtr.p->m_coordinatorRef;
4956   TableRecordPtr tabPtr;
4957   c_tableRecordPool.getPtr(tabPtr, alterTabPtr.p->m_alterTableId);
4958   // Alter table commit request handled successfully
4959   // Inform Suma so it can send events to any subscribers of the table
4960   AlterTabReq * req = (AlterTabReq*)signal->getDataPtrSend();
4961   if (coordinatorRef == reference())
4962     req->senderRef = alterTabPtr.p->m_senderRef;
4963   else
4964     req->senderRef = 0;
4965   req->senderData = callbackData;
4966   req->tableId = tabPtr.p->tableId;
4967   req->tableVersion = tabPtr.p->tableVersion;
4968   req->gci = tabPtr.p->gciTableCreated;
4969   req->requestType = AlterTabReq::AlterTableCommit;
4970   req->changeMask = alterTabPtr.p->m_changeMask;
4971   SegmentedSectionPtr tabInfoPtr;
4972   getSection(tabInfoPtr, alterTabPtr.p->m_tabInfoPtrI);
4973   signal->setSection(tabInfoPtr, AlterTabReq::DICT_TAB_INFO);
4974   EXECUTE_DIRECT(SUMA, GSN_ALTER_TAB_REQ, signal,
4975                  AlterTabReq::SignalLength);
4976   releaseSections(signal);
4977   alterTabPtr.p->m_tabInfoPtrI = RNIL;
4978   jamEntry();
4979   AlterTabConf * conf = (AlterTabConf*)signal->getDataPtrSend();
4980   conf->senderRef = reference();
4981   conf->senderData = callbackData;
4982   conf->tableId = tabPtr.p->tableId;
4983   conf->tableVersion = tabPtr.p->tableVersion;
4984   conf->gci = tabPtr.p->gciTableCreated;
4985   conf->requestType = AlterTabReq::AlterTableCommit;
4986   conf->changeMask = alterTabPtr.p->m_changeMask;
4987   sendSignal(coordinatorRef, GSN_ALTER_TAB_CONF, signal,
4988 	       AlterTabConf::SignalLength, JBB);
4989 
4990 
4991   {
4992     ApiBroadcastRep* api= (ApiBroadcastRep*)signal->getDataPtrSend();
4993     api->gsn = GSN_ALTER_TABLE_REP;
4994     api->minVersion = MAKE_VERSION(4,1,15);
4995 
4996     AlterTableRep* rep = (AlterTableRep*)api->theData;
4997     rep->tableId = tabPtr.p->tableId;
4998     rep->tableVersion = alter_obj_dec_schema_version(tabPtr.p->tableVersion);
4999     rep->changeType = AlterTableRep::CT_ALTERED;
5000 
5001     LinearSectionPtr ptr[3];
5002     ptr[0].p = (Uint32*)alterTabPtr.p->previousTableName;
5003     ptr[0].sz = (sizeof(alterTabPtr.p->previousTableName) + 3) >> 2;
5004 
5005     sendSignal(QMGR_REF, GSN_API_BROADCAST_REP, signal,
5006 	       ApiBroadcastRep::SignalLength + AlterTableRep::SignalLength,
5007 	       JBB, ptr,1);
5008   }
5009 
5010   if(coordinatorRef != reference()) {
5011     jam();
5012     // Release resources
5013     c_tableRecordPool.getPtr(tabPtr, alterTabPtr.p->m_tablePtrI);
5014     releaseTableObject(tabPtr.i, false);
5015     releaseCreateTableOp(signal,alterTabPtr);
5016     c_blockState = BS_IDLE;
5017   }
5018 }
5019 
5020 void
execCREATE_FRAGMENTATION_REF(Signal * signal)5021 Dbdict::execCREATE_FRAGMENTATION_REF(Signal * signal){
5022   jamEntry();
5023   const Uint32 * theData = signal->getDataPtr();
5024   CreateFragmentationRef * const ref = (CreateFragmentationRef*)theData;
5025   (void)ref;
5026   ndbrequire(false);
5027 }
5028 
5029 void
execCREATE_FRAGMENTATION_CONF(Signal * signal)5030 Dbdict::execCREATE_FRAGMENTATION_CONF(Signal* signal){
5031   jamEntry();
5032   const Uint32 * theData = signal->getDataPtr();
5033   CreateFragmentationConf * const conf = (CreateFragmentationConf*)theData;
5034 
5035   CreateTableRecordPtr createTabPtr;
5036   ndbrequire(c_opCreateTable.find(createTabPtr, conf->senderData));
5037 
5038   ndbrequire(signal->getNoOfSections() == 1);
5039 
5040   SegmentedSectionPtr fragDataPtr;
5041   signal->getSection(fragDataPtr, CreateFragmentationConf::FRAGMENTS);
5042   signal->header.m_noOfSections = 0;
5043 
5044   /**
5045    * Get table
5046    */
5047   TableRecordPtr tabPtr;
5048   c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
5049 
5050   /**
5051    * Save fragment count
5052    */
5053   tabPtr.p->fragmentCount = conf->noOfFragments;
5054 
5055   /**
5056    * Update table version
5057    */
5058   XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
5059   SchemaFile::TableEntry * tabEntry = getTableEntry(xsf, tabPtr.i);
5060 
5061   tabPtr.p->tableVersion =
5062     create_obj_inc_schema_version(tabEntry->m_tableVersion);
5063 
5064   /**
5065    * Pack
5066    */
5067   SimplePropertiesSectionWriter w(getSectionSegmentPool());
5068   packTableIntoPages(w, tabPtr);
5069 
5070   SegmentedSectionPtr spDataPtr;
5071   w.getPtr(spDataPtr);
5072 
5073   signal->setSection(spDataPtr, CreateTabReq::DICT_TAB_INFO);
5074   signal->setSection(fragDataPtr, CreateTabReq::FRAGMENTATION);
5075 
5076   NodeReceiverGroup rg(DBDICT, c_aliveNodes);
5077   SafeCounter tmp(c_counterMgr, createTabPtr.p->m_coordinatorData.m_counter);
5078   createTabPtr.p->m_coordinatorData.m_gsn = GSN_CREATE_TAB_REQ;
5079   createTabPtr.p->m_coordinatorData.m_requestType = CreateTabReq::CreateTablePrepare;
5080   tmp.init<CreateTabRef>(rg, GSN_CREATE_TAB_REF, createTabPtr.p->key);
5081 
5082   CreateTabReq * const req = (CreateTabReq*)theData;
5083   req->senderRef = reference();
5084   req->senderData = createTabPtr.p->key;
5085   req->clientRef = createTabPtr.p->m_senderRef;
5086   req->clientData = createTabPtr.p->m_senderData;
5087   req->requestType = CreateTabReq::CreateTablePrepare;
5088 
5089   req->gci = 0;
5090   req->tableId = tabPtr.i;
5091   req->tableVersion = create_obj_inc_schema_version(tabEntry->m_tableVersion);
5092 
5093   sendFragmentedSignal(rg, GSN_CREATE_TAB_REQ, signal,
5094 		       CreateTabReq::SignalLength, JBB);
5095 
5096   return;
5097 }
5098 
5099 void
execCREATE_TAB_REF(Signal * signal)5100 Dbdict::execCREATE_TAB_REF(Signal* signal){
5101   jamEntry();
5102 
5103   CreateTabRef * const ref = (CreateTabRef*)signal->getDataPtr();
5104 
5105   CreateTableRecordPtr createTabPtr;
5106   ndbrequire(c_opCreateTable.find(createTabPtr, ref->senderData));
5107 
5108   ndbrequire(createTabPtr.p->m_coordinatorRef == reference());
5109   ndbrequire(createTabPtr.p->m_coordinatorData.m_gsn == GSN_CREATE_TAB_REQ);
5110 
5111   if(ref->errorCode != CreateTabRef::NF_FakeErrorREF){
5112     createTabPtr.p->setErrorCode(ref->errorCode);
5113   }
5114   createTab_reply(signal, createTabPtr, refToNode(ref->senderRef));
5115 }
5116 
5117 void
execCREATE_TAB_CONF(Signal * signal)5118 Dbdict::execCREATE_TAB_CONF(Signal* signal){
5119   jamEntry();
5120 
5121   ndbrequire(signal->getNoOfSections() == 0);
5122 
5123   CreateTabConf * const conf = (CreateTabConf*)signal->getDataPtr();
5124 
5125   CreateTableRecordPtr createTabPtr;
5126   ndbrequire(c_opCreateTable.find(createTabPtr, conf->senderData));
5127 
5128   ndbrequire(createTabPtr.p->m_coordinatorRef == reference());
5129   ndbrequire(createTabPtr.p->m_coordinatorData.m_gsn == GSN_CREATE_TAB_REQ);
5130 
5131   createTab_reply(signal, createTabPtr, refToNode(conf->senderRef));
5132 }
5133 
5134 void
createTab_reply(Signal * signal,CreateTableRecordPtr createTabPtr,Uint32 nodeId)5135 Dbdict::createTab_reply(Signal* signal,
5136 			CreateTableRecordPtr createTabPtr,
5137 			Uint32 nodeId)
5138 {
5139 
5140   SafeCounter tmp(c_counterMgr, createTabPtr.p->m_coordinatorData.m_counter);
5141   if(!tmp.clearWaitingFor(nodeId)){
5142     jam();
5143     return;
5144   }
5145 
5146   switch(createTabPtr.p->m_coordinatorData.m_requestType){
5147   case CreateTabReq::CreateTablePrepare:{
5148 
5149     if(createTabPtr.p->m_errorCode != 0){
5150       jam();
5151       /**
5152        * Failed to prepare on atleast one node -> abort on all
5153        */
5154       NodeReceiverGroup rg(DBDICT, c_aliveNodes);
5155       createTabPtr.p->m_coordinatorData.m_gsn = GSN_CREATE_TAB_REQ;
5156       createTabPtr.p->m_coordinatorData.m_requestType = CreateTabReq::CreateTableDrop;
5157       ndbrequire(tmp.init<CreateTabRef>(rg, createTabPtr.p->key));
5158 
5159       CreateTabReq * const req = (CreateTabReq*)signal->getDataPtrSend();
5160       req->senderRef = reference();
5161       req->senderData = createTabPtr.p->key;
5162       req->requestType = CreateTabReq::CreateTableDrop;
5163 
5164       sendSignal(rg, GSN_CREATE_TAB_REQ, signal,
5165 		 CreateTabReq::SignalLength, JBB);
5166       return;
5167     }
5168 
5169     /**
5170      * Lock mutex before commiting table
5171      */
5172     Mutex mutex(signal, c_mutexMgr, createTabPtr.p->m_startLcpMutex);
5173     Callback c = { safe_cast(&Dbdict::createTab_startLcpMutex_locked),
5174 		   createTabPtr.p->key};
5175 
5176     ndbrequire(mutex.lock(c));
5177     return;
5178   }
5179   case CreateTabReq::CreateTableCommit:{
5180     jam();
5181     ndbrequire(createTabPtr.p->m_errorCode == 0);
5182 
5183     /**
5184      * Unlock mutex before commiting table
5185      */
5186     Mutex mutex(signal, c_mutexMgr, createTabPtr.p->m_startLcpMutex);
5187     Callback c = { safe_cast(&Dbdict::createTab_startLcpMutex_unlocked),
5188 		   createTabPtr.p->key};
5189     mutex.unlock(c);
5190     return;
5191   }
5192   case CreateTabReq::CreateTableDrop:{
5193     jam();
5194     CreateTableRef * const ref = (CreateTableRef*)signal->getDataPtr();
5195     ref->senderRef = reference();
5196     ref->senderData = createTabPtr.p->m_senderData;
5197     ref->errorCode = createTabPtr.p->m_errorCode;
5198     ref->masterNodeId = c_masterNodeId;
5199     ref->status = 0;
5200     ref->errorKey = 0;
5201     ref->errorLine = 0;
5202 
5203     //@todo check api failed
5204     sendSignal(createTabPtr.p->m_senderRef, GSN_CREATE_TABLE_REF, signal,
5205 	       CreateTableRef::SignalLength, JBB);
5206     releaseCreateTableOp(signal,createTabPtr);
5207     c_blockState = BS_IDLE;
5208     return;
5209   }
5210   }
5211   ndbrequire(false);
5212 }
5213 
5214 void
createTab_startLcpMutex_locked(Signal * signal,Uint32 callbackData,Uint32 retValue)5215 Dbdict::createTab_startLcpMutex_locked(Signal* signal,
5216 				       Uint32 callbackData,
5217 				       Uint32 retValue){
5218   jamEntry();
5219 
5220   ndbrequire(retValue == 0);
5221 
5222   CreateTableRecordPtr createTabPtr;
5223   ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
5224 
5225   NodeReceiverGroup rg(DBDICT, c_aliveNodes);
5226   createTabPtr.p->m_coordinatorData.m_gsn = GSN_CREATE_TAB_REQ;
5227   createTabPtr.p->m_coordinatorData.m_requestType = CreateTabReq::CreateTableCommit;
5228   SafeCounter tmp(c_counterMgr, createTabPtr.p->m_coordinatorData.m_counter);
5229   tmp.init<CreateTabRef>(rg, GSN_CREATE_TAB_REF, createTabPtr.p->key);
5230 
5231   CreateTabReq * const req = (CreateTabReq*)signal->getDataPtrSend();
5232   req->senderRef = reference();
5233   req->senderData = createTabPtr.p->key;
5234   req->requestType = CreateTabReq::CreateTableCommit;
5235 
5236   sendSignal(rg, GSN_CREATE_TAB_REQ, signal,
5237 	     CreateTabReq::SignalLength, JBB);
5238 }
5239 
5240 void
createTab_startLcpMutex_unlocked(Signal * signal,Uint32 callbackData,Uint32 retValue)5241 Dbdict::createTab_startLcpMutex_unlocked(Signal* signal,
5242 					 Uint32 callbackData,
5243 					 Uint32 retValue){
5244   jamEntry();
5245 
5246   ndbrequire(retValue == 0);
5247 
5248   CreateTableRecordPtr createTabPtr;
5249   ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
5250 
5251   createTabPtr.p->m_startLcpMutex.release(c_mutexMgr);
5252 
5253   TableRecordPtr tabPtr;
5254   c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
5255 
5256   CreateTableConf * const conf = (CreateTableConf*)signal->getDataPtr();
5257   conf->senderRef = reference();
5258   conf->senderData = createTabPtr.p->m_senderData;
5259   conf->tableId = createTabPtr.p->m_tablePtrI;
5260   conf->tableVersion = tabPtr.p->tableVersion;
5261 
5262   //@todo check api failed
5263   sendSignal(createTabPtr.p->m_senderRef, GSN_CREATE_TABLE_CONF, signal,
5264 	     CreateTableConf::SignalLength, JBB);
5265   releaseCreateTableOp(signal,createTabPtr);
5266   c_blockState = BS_IDLE;
5267   return;
5268 }
5269 
5270 /***********************************************************
5271  * CreateTable participant code
5272  **********************************************************/
5273 void
execCREATE_TAB_REQ(Signal * signal)5274 Dbdict::execCREATE_TAB_REQ(Signal* signal){
5275   jamEntry();
5276 
5277   if(!assembleFragments(signal)){
5278     jam();
5279     return;
5280   }
5281 
5282   CreateTabReq * const req = (CreateTabReq*)signal->getDataPtr();
5283 
5284   CreateTabReq::RequestType rt = (CreateTabReq::RequestType)req->requestType;
5285   switch(rt){
5286   case CreateTabReq::CreateTablePrepare:
5287     CRASH_INSERTION2(6003, getOwnNodeId() != c_masterNodeId);
5288     createTab_prepare(signal, req);
5289     return;
5290   case CreateTabReq::CreateTableCommit:
5291     CRASH_INSERTION2(6004, getOwnNodeId() != c_masterNodeId);
5292     createTab_commit(signal, req);
5293     return;
5294   case CreateTabReq::CreateTableDrop:
5295     CRASH_INSERTION2(6005, getOwnNodeId() != c_masterNodeId);
5296     createTab_drop(signal, req);
5297     return;
5298   }
5299   ndbrequire(false);
5300 }
5301 
5302 void
createTab_prepare(Signal * signal,CreateTabReq * req)5303 Dbdict::createTab_prepare(Signal* signal, CreateTabReq * req){
5304 
5305   const Uint32 gci = req->gci;
5306   const Uint32 tableId = req->tableId;
5307   const Uint32 tableVersion = req->tableVersion;
5308 
5309   SegmentedSectionPtr tabInfoPtr;
5310   signal->getSection(tabInfoPtr, CreateTabReq::DICT_TAB_INFO);
5311 
5312   CreateTableRecordPtr createTabPtr;
5313   if(req->senderRef == reference()){
5314     jam();
5315     ndbrequire(c_opCreateTable.find(createTabPtr, req->senderData));
5316   } else {
5317     jam();
5318     c_opCreateTable.seize(createTabPtr);
5319 
5320     ndbrequire(!createTabPtr.isNull());
5321 
5322     createTabPtr.p->key = req->senderData;
5323     c_opCreateTable.add(createTabPtr);
5324     createTabPtr.p->m_errorCode = 0;
5325     createTabPtr.p->m_tablePtrI = tableId;
5326     createTabPtr.p->m_coordinatorRef = req->senderRef;
5327     createTabPtr.p->m_senderRef = req->clientRef;
5328     createTabPtr.p->m_senderData = req->clientData;
5329     createTabPtr.p->m_dihAddFragPtr = RNIL;
5330 
5331     /**
5332      * Put data into table record
5333      */
5334     ParseDictTabInfoRecord parseRecord;
5335     parseRecord.requestType = DictTabInfo::AddTableFromDict;
5336     parseRecord.errorCode = 0;
5337 
5338     SimplePropertiesSectionReader r(tabInfoPtr, getSectionSegmentPool());
5339 
5340     handleTabInfoInit(r, &parseRecord);
5341 
5342     ndbrequire(parseRecord.errorCode == 0);
5343   }
5344 
5345   ndbrequire(!createTabPtr.isNull());
5346 
5347   SegmentedSectionPtr fragPtr;
5348   signal->getSection(fragPtr, CreateTabReq::FRAGMENTATION);
5349 
5350   createTabPtr.p->m_tabInfoPtrI = tabInfoPtr.i;
5351   createTabPtr.p->m_fragmentsPtrI = fragPtr.i;
5352 
5353   signal->header.m_noOfSections = 0;
5354 
5355   TableRecordPtr tabPtr;
5356   c_tableRecordPool.getPtr(tabPtr, tableId);
5357   tabPtr.p->packedSize = tabInfoPtr.sz;
5358   tabPtr.p->tableVersion = tableVersion;
5359   tabPtr.p->gciTableCreated = gci;
5360 
5361   SchemaFile::TableEntry tabEntry;
5362   tabEntry.m_tableVersion = tableVersion;
5363   tabEntry.m_tableType    = tabPtr.p->tableType;
5364   tabEntry.m_tableState   = SchemaFile::ADD_STARTED;
5365   tabEntry.m_gcp          = gci;
5366   tabEntry.m_info_words   = tabInfoPtr.sz;
5367   memset(tabEntry.m_unused, 0, sizeof(tabEntry.m_unused));
5368 
5369   Callback callback;
5370   callback.m_callbackData = createTabPtr.p->key;
5371   callback.m_callbackFunction =
5372     safe_cast(&Dbdict::createTab_writeSchemaConf1);
5373 
5374   bool savetodisk = !(tabPtr.p->m_bits & TableRecord::TR_Temporary);
5375   updateSchemaState(signal, tableId, &tabEntry, &callback, savetodisk);
5376 }
5377 
5378 void getSection(SegmentedSectionPtr & ptr, Uint32 i);
5379 
5380 void
createTab_writeSchemaConf1(Signal * signal,Uint32 callbackData,Uint32 returnCode)5381 Dbdict::createTab_writeSchemaConf1(Signal* signal,
5382 				   Uint32 callbackData,
5383 				   Uint32 returnCode){
5384   jam();
5385 
5386   CreateTableRecordPtr createTabPtr;
5387   ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
5388 
5389   Callback callback;
5390   callback.m_callbackData = createTabPtr.p->key;
5391   callback.m_callbackFunction =
5392     safe_cast(&Dbdict::createTab_writeTableConf);
5393 
5394   TableRecordPtr tabPtr;
5395   c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
5396   bool savetodisk = !(tabPtr.p->m_bits & TableRecord::TR_Temporary);
5397   if (savetodisk)
5398   {
5399     SegmentedSectionPtr tabInfoPtr;
5400     getSection(tabInfoPtr, createTabPtr.p->m_tabInfoPtrI);
5401     writeTableFile(signal, createTabPtr.p->m_tablePtrI, tabInfoPtr, &callback);
5402   }
5403   else
5404   {
5405     execute(signal, callback, 0);
5406   }
5407 #if 0
5408   createTabPtr.p->m_tabInfoPtrI = RNIL;
5409   signal->setSection(tabInfoPtr, 0);
5410   releaseSections(signal);
5411 #endif
5412 }
5413 
5414 void
createTab_writeTableConf(Signal * signal,Uint32 callbackData,Uint32 returnCode)5415 Dbdict::createTab_writeTableConf(Signal* signal,
5416 				 Uint32 callbackData,
5417 				 Uint32 returnCode){
5418   jam();
5419 
5420   CreateTableRecordPtr createTabPtr;
5421   ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
5422 
5423   SegmentedSectionPtr fragDataPtr;
5424   getSection(fragDataPtr, createTabPtr.p->m_fragmentsPtrI);
5425 
5426   Callback callback;
5427   callback.m_callbackData = callbackData;
5428   callback.m_callbackFunction =
5429     safe_cast(&Dbdict::createTab_dihComplete);
5430 
5431   createTab_dih(signal, createTabPtr, fragDataPtr, &callback);
5432 }
5433 
5434 void
createTab_dih(Signal * signal,CreateTableRecordPtr createTabPtr,SegmentedSectionPtr fragDataPtr,Callback * c)5435 Dbdict::createTab_dih(Signal* signal,
5436 		      CreateTableRecordPtr createTabPtr,
5437 		      SegmentedSectionPtr fragDataPtr,
5438 		      Callback * c){
5439   jam();
5440 
5441   createTabPtr.p->m_callback = * c;
5442 
5443   TableRecordPtr tabPtr;
5444   c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
5445 
5446   DiAddTabReq * req = (DiAddTabReq*)signal->getDataPtrSend();
5447   req->connectPtr = createTabPtr.p->key;
5448   req->tableId = tabPtr.i;
5449   req->fragType = tabPtr.p->fragmentType;
5450   req->kValue = tabPtr.p->kValue;
5451   req->noOfReplicas = 0;
5452   req->loggedTable = !!(tabPtr.p->m_bits & TableRecord::TR_Logged);
5453   req->tableType = tabPtr.p->tableType;
5454   req->schemaVersion = tabPtr.p->tableVersion;
5455   req->primaryTableId = tabPtr.p->primaryTableId;
5456   req->temporaryTable = !!(tabPtr.p->m_bits & TableRecord::TR_Temporary);
5457 
5458 /*
5459   Beh�ver fiska upp fragDataPtr fr�n table object ist�llet
5460 */
5461   if(!fragDataPtr.isNull()){
5462     signal->setSection(fragDataPtr, DiAddTabReq::FRAGMENTATION);
5463   }
5464 
5465   sendSignal(DBDIH_REF, GSN_DIADDTABREQ, signal,
5466 	     DiAddTabReq::SignalLength, JBB);
5467 
5468   /**
5469    * Create KeyDescriptor
5470    */
5471   KeyDescriptor* desc= g_key_descriptor_pool.getPtr(tabPtr.i);
5472   new (desc) KeyDescriptor();
5473 
5474   Uint32 key = 0;
5475   Ptr<AttributeRecord> attrPtr;
5476   LocalDLFifoList<AttributeRecord> list(c_attributeRecordPool,
5477                                         tabPtr.p->m_attributes);
5478   for(list.first(attrPtr); !attrPtr.isNull(); list.next(attrPtr))
5479   {
5480     AttributeRecord* aRec = attrPtr.p;
5481     if (aRec->tupleKey)
5482     {
5483       Uint32 attr = aRec->attributeDescriptor;
5484 
5485       desc->noOfKeyAttr ++;
5486       desc->keyAttr[key].attributeDescriptor = attr;
5487       Uint32 csNumber = (aRec->extPrecision >> 16);
5488       if (csNumber)
5489       {
5490         desc->keyAttr[key].charsetInfo = all_charsets[csNumber];
5491         ndbrequire(all_charsets[csNumber] != 0);
5492         desc->hasCharAttr = 1;
5493       }
5494       else
5495       {
5496         desc->keyAttr[key].charsetInfo = 0;
5497       }
5498       if (AttributeDescriptor::getDKey(attr))
5499       {
5500         desc->noOfDistrKeys ++;
5501       }
5502       if (AttributeDescriptor::getArrayType(attr) != NDB_ARRAYTYPE_FIXED)
5503       {
5504         desc->noOfVarKeys ++;
5505       }
5506       key++;
5507     }
5508   }
5509   ndbrequire(key == tabPtr.p->noOfPrimkey);
5510 }
5511 
5512 static
5513 void
calcLHbits(Uint32 * lhPageBits,Uint32 * lhDistrBits,Uint32 fid,Uint32 totalFragments)5514 calcLHbits(Uint32 * lhPageBits, Uint32 * lhDistrBits,
5515 	   Uint32 fid, Uint32 totalFragments)
5516 {
5517   Uint32 distrBits = 0;
5518   Uint32 pageBits = 0;
5519 
5520   Uint32 tmp = 1;
5521   while (tmp < totalFragments) {
5522     jam();
5523     tmp <<= 1;
5524     distrBits++;
5525   }//while
5526 #ifdef ndb_classical_lhdistrbits
5527   if (tmp != totalFragments) {
5528     tmp >>= 1;
5529     if ((fid >= (totalFragments - tmp)) && (fid < (tmp - 1))) {
5530       distrBits--;
5531     }//if
5532   }//if
5533 #endif
5534   * lhPageBits = pageBits;
5535   * lhDistrBits = distrBits;
5536 
5537 }//calcLHbits()
5538 
5539 
5540 void
execADD_FRAGREQ(Signal * signal)5541 Dbdict::execADD_FRAGREQ(Signal* signal) {
5542   jamEntry();
5543 
5544   AddFragReq * const req = (AddFragReq*)signal->getDataPtr();
5545 
5546   Uint32 dihPtr = req->dihPtr;
5547   Uint32 senderData = req->senderData;
5548   Uint32 tableId = req->tableId;
5549   Uint32 fragId = req->fragmentId;
5550   Uint32 node = req->nodeId;
5551   Uint32 lcpNo = req->nextLCP;
5552   Uint32 fragCount = req->totalFragments;
5553   Uint32 requestInfo = req->requestInfo;
5554   Uint32 startGci = req->startGci;
5555   Uint32 logPart = req->logPartId;
5556 
5557   ndbrequire(node == getOwnNodeId());
5558 
5559   CreateTableRecordPtr createTabPtr;
5560   ndbrequire(c_opCreateTable.find(createTabPtr, senderData));
5561 
5562   createTabPtr.p->m_dihAddFragPtr = dihPtr;
5563 
5564   TableRecordPtr tabPtr;
5565   c_tableRecordPool.getPtr(tabPtr, tableId);
5566 
5567 #if 0
5568   tabPtr.p->gciTableCreated = (startGci > tabPtr.p->gciTableCreated ? startGci:
5569 			       startGci > tabPtr.p->gciTableCreated);
5570 #endif
5571 
5572   /**
5573    * Calc lh3PageBits
5574    */
5575   Uint32 lhDistrBits = 0;
5576   Uint32 lhPageBits = 0;
5577   ::calcLHbits(&lhPageBits, &lhDistrBits, fragId, fragCount);
5578 
5579   Uint64 maxRows = tabPtr.p->maxRowsLow +
5580     (((Uint64)tabPtr.p->maxRowsHigh) << 32);
5581   Uint64 minRows = tabPtr.p->minRowsLow +
5582     (((Uint64)tabPtr.p->minRowsHigh) << 32);
5583   maxRows = (maxRows + fragCount - 1) / fragCount;
5584   minRows = (minRows + fragCount - 1) / fragCount;
5585 
5586   {
5587     LqhFragReq* req = (LqhFragReq*)signal->getDataPtrSend();
5588     req->senderData = senderData;
5589     req->senderRef = reference();
5590     req->fragmentId = fragId;
5591     req->requestInfo = requestInfo;
5592     req->tableId = tableId;
5593     req->localKeyLength = tabPtr.p->localKeyLen;
5594     req->maxLoadFactor = tabPtr.p->maxLoadFactor;
5595     req->minLoadFactor = tabPtr.p->minLoadFactor;
5596     req->kValue = tabPtr.p->kValue;
5597     req->lh3DistrBits = 0; //lhDistrBits;
5598     req->lh3PageBits = 0; //lhPageBits;
5599     req->noOfAttributes = tabPtr.p->noOfAttributes;
5600     req->noOfNullAttributes = tabPtr.p->noOfNullBits;
5601     req->maxRowsLow = maxRows & 0xFFFFFFFF;
5602     req->maxRowsHigh = maxRows >> 32;
5603     req->minRowsLow = minRows & 0xFFFFFFFF;
5604     req->minRowsHigh = minRows >> 32;
5605     req->schemaVersion = tabPtr.p->tableVersion;
5606     Uint32 keyLen = tabPtr.p->tupKeyLength;
5607     req->keyLength = keyLen; // wl-2066 no more "long keys"
5608     req->nextLCP = lcpNo;
5609 
5610     req->noOfKeyAttr = tabPtr.p->noOfPrimkey;
5611     req->noOfCharsets = tabPtr.p->noOfCharsets;
5612     req->checksumIndicator = 1;
5613     req->GCPIndicator = 1;
5614     req->startGci = startGci;
5615     req->tableType = tabPtr.p->tableType;
5616     req->primaryTableId = tabPtr.p->primaryTableId;
5617     req->tablespace_id= tabPtr.p->m_tablespace_id;
5618     req->logPartId = logPart;
5619     req->forceVarPartFlag = !!(tabPtr.p->m_bits& TableRecord::TR_ForceVarPart);
5620     sendSignal(DBLQH_REF, GSN_LQHFRAGREQ, signal,
5621 	       LqhFragReq::SignalLength, JBB);
5622   }
5623 }
5624 
5625 void
execLQHFRAGREF(Signal * signal)5626 Dbdict::execLQHFRAGREF(Signal * signal){
5627   jamEntry();
5628   LqhFragRef * const ref = (LqhFragRef*)signal->getDataPtr();
5629 
5630   CreateTableRecordPtr createTabPtr;
5631   ndbrequire(c_opCreateTable.find(createTabPtr, ref->senderData));
5632 
5633   createTabPtr.p->setErrorCode(ref->errorCode);
5634 
5635   {
5636     AddFragRef * const ref = (AddFragRef*)signal->getDataPtr();
5637     ref->dihPtr = createTabPtr.p->m_dihAddFragPtr;
5638     sendSignal(DBDIH_REF, GSN_ADD_FRAGREF, signal,
5639 	       AddFragRef::SignalLength, JBB);
5640   }
5641 }
5642 
5643 void
execLQHFRAGCONF(Signal * signal)5644 Dbdict::execLQHFRAGCONF(Signal * signal){
5645   jamEntry();
5646   LqhFragConf * const conf = (LqhFragConf*)signal->getDataPtr();
5647 
5648   CreateTableRecordPtr createTabPtr;
5649   ndbrequire(c_opCreateTable.find(createTabPtr, conf->senderData));
5650 
5651   createTabPtr.p->m_lqhFragPtr = conf->lqhFragPtr;
5652 
5653   TableRecordPtr tabPtr;
5654   c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
5655   sendLQHADDATTRREQ(signal, createTabPtr, tabPtr.p->m_attributes.firstItem);
5656 }
5657 
5658 void
sendLQHADDATTRREQ(Signal * signal,CreateTableRecordPtr createTabPtr,Uint32 attributePtrI)5659 Dbdict::sendLQHADDATTRREQ(Signal* signal,
5660 			  CreateTableRecordPtr createTabPtr,
5661 			  Uint32 attributePtrI){
5662   jam();
5663   TableRecordPtr tabPtr;
5664   c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
5665   LqhAddAttrReq * const req = (LqhAddAttrReq*)signal->getDataPtrSend();
5666   Uint32 i = 0;
5667   for(i = 0; i<LqhAddAttrReq::MAX_ATTRIBUTES && attributePtrI != RNIL; i++){
5668     jam();
5669     AttributeRecordPtr attrPtr;
5670     c_attributeRecordPool.getPtr(attrPtr, attributePtrI);
5671     LqhAddAttrReq::Entry& entry = req->attributes[i];
5672     entry.attrId = attrPtr.p->attributeId;
5673     entry.attrDescriptor = attrPtr.p->attributeDescriptor;
5674     entry.extTypeInfo = 0;
5675     // charset number passed to TUP, TUX in upper half
5676     entry.extTypeInfo |= (attrPtr.p->extPrecision & ~0xFFFF);
5677     if (tabPtr.p->isIndex()) {
5678       Uint32 primaryAttrId;
5679       if (attrPtr.p->nextList != RNIL) {
5680         getIndexAttr(tabPtr, attributePtrI, &primaryAttrId);
5681       } else {
5682         primaryAttrId = ZNIL;
5683         if (tabPtr.p->isOrderedIndex())
5684           entry.attrId = 0;     // attribute goes to TUP
5685       }
5686       entry.attrId |= (primaryAttrId << 16);
5687     }
5688     attributePtrI = attrPtr.p->nextList;
5689   }
5690   req->lqhFragPtr = createTabPtr.p->m_lqhFragPtr;
5691   req->senderData = createTabPtr.p->key;
5692   req->senderAttrPtr = attributePtrI;
5693   req->noOfAttributes = i;
5694 
5695   sendSignal(DBLQH_REF, GSN_LQHADDATTREQ, signal,
5696 	     LqhAddAttrReq::HeaderLength + LqhAddAttrReq::EntryLength * i, JBB);
5697 }
5698 
5699 void
execLQHADDATTREF(Signal * signal)5700 Dbdict::execLQHADDATTREF(Signal * signal){
5701   jamEntry();
5702   LqhAddAttrRef * const ref = (LqhAddAttrRef*)signal->getDataPtr();
5703 
5704   CreateTableRecordPtr createTabPtr;
5705   ndbrequire(c_opCreateTable.find(createTabPtr, ref->senderData));
5706 
5707   createTabPtr.p->setErrorCode(ref->errorCode);
5708 
5709   {
5710     AddFragRef * const ref = (AddFragRef*)signal->getDataPtr();
5711     ref->dihPtr = createTabPtr.p->m_dihAddFragPtr;
5712     sendSignal(DBDIH_REF, GSN_ADD_FRAGREF, signal,
5713 	       AddFragRef::SignalLength, JBB);
5714   }
5715 
5716 }
5717 
5718 void
execLQHADDATTCONF(Signal * signal)5719 Dbdict::execLQHADDATTCONF(Signal * signal){
5720   jamEntry();
5721   LqhAddAttrConf * const conf = (LqhAddAttrConf*)signal->getDataPtr();
5722 
5723   CreateTableRecordPtr createTabPtr;
5724   ndbrequire(c_opCreateTable.find(createTabPtr, conf->senderData));
5725 
5726   const Uint32 fragId = conf->fragId;
5727   const Uint32 nextAttrPtr = conf->senderAttrPtr;
5728   if(nextAttrPtr != RNIL){
5729     jam();
5730     sendLQHADDATTRREQ(signal, createTabPtr, nextAttrPtr);
5731     return;
5732   }
5733 
5734   {
5735     AddFragConf * const conf = (AddFragConf*)signal->getDataPtr();
5736     conf->dihPtr = createTabPtr.p->m_dihAddFragPtr;
5737     conf->fragId = fragId;
5738     sendSignal(DBDIH_REF, GSN_ADD_FRAGCONF, signal,
5739 	       AddFragConf::SignalLength, JBB);
5740   }
5741 }
5742 
5743 void
execDIADDTABREF(Signal * signal)5744 Dbdict::execDIADDTABREF(Signal* signal){
5745   jam();
5746 
5747   DiAddTabRef * const ref = (DiAddTabRef*)signal->getDataPtr();
5748 
5749   CreateTableRecordPtr createTabPtr;
5750   ndbrequire(c_opCreateTable.find(createTabPtr, ref->senderData));
5751 
5752   createTabPtr.p->setErrorCode(ref->errorCode);
5753   execute(signal, createTabPtr.p->m_callback, 0);
5754 }
5755 
5756 void
execDIADDTABCONF(Signal * signal)5757 Dbdict::execDIADDTABCONF(Signal* signal){
5758   jam();
5759 
5760   DiAddTabConf * const conf = (DiAddTabConf*)signal->getDataPtr();
5761 
5762   CreateTableRecordPtr createTabPtr;
5763   ndbrequire(c_opCreateTable.find(createTabPtr, conf->senderData));
5764 
5765   signal->theData[0] = createTabPtr.p->key;
5766   signal->theData[1] = reference();
5767   signal->theData[2] = createTabPtr.p->m_tablePtrI;
5768 
5769   if(createTabPtr.p->m_dihAddFragPtr != RNIL){
5770     jam();
5771 
5772     /**
5773      * We did perform at least one LQHFRAGREQ
5774      */
5775     sendSignal(DBLQH_REF, GSN_TAB_COMMITREQ, signal, 3, JBB);
5776     return;
5777   } else {
5778     /**
5779      * No local fragment (i.e. no LQHFRAGREQ)
5780      */
5781     execute(signal, createTabPtr.p->m_callback, 0);
5782     return;
5783     //sendSignal(DBDIH_REF, GSN_TAB_COMMITREQ, signal, 3, JBB);
5784   }
5785 }
5786 
5787 void
execTAB_COMMITREF(Signal * signal)5788 Dbdict::execTAB_COMMITREF(Signal* signal) {
5789   jamEntry();
5790   ndbrequire(false);
5791 }//execTAB_COMMITREF()
5792 
5793 void
execTAB_COMMITCONF(Signal * signal)5794 Dbdict::execTAB_COMMITCONF(Signal* signal){
5795   jamEntry();
5796 
5797   CreateTableRecordPtr createTabPtr;
5798   ndbrequire(c_opCreateTable.find(createTabPtr, signal->theData[0]));
5799 
5800   if(refToBlock(signal->getSendersBlockRef()) == DBLQH){
5801 
5802     execute(signal, createTabPtr.p->m_callback, 0);
5803     return;
5804   }
5805 
5806   if(refToBlock(signal->getSendersBlockRef()) == DBDIH){
5807     TableRecordPtr tabPtr;
5808     c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
5809 
5810     signal->theData[0] = tabPtr.i;
5811     signal->theData[1] = tabPtr.p->tableVersion;
5812     signal->theData[2] = (Uint32)!!(tabPtr.p->m_bits & TableRecord::TR_Logged);
5813     signal->theData[3] = reference();
5814     signal->theData[4] = (Uint32)tabPtr.p->tableType;
5815     signal->theData[5] = createTabPtr.p->key;
5816     signal->theData[6] = (Uint32)tabPtr.p->noOfPrimkey;
5817     signal->theData[7] = (Uint32)tabPtr.p->singleUserMode;
5818 
5819     sendSignal(DBTC_REF, GSN_TC_SCHVERREQ, signal, 8, JBB);
5820     return;
5821   }
5822 
5823   ndbrequire(false);
5824 }
5825 
5826 void
createTab_dihComplete(Signal * signal,Uint32 callbackData,Uint32 returnCode)5827 Dbdict::createTab_dihComplete(Signal* signal,
5828 			      Uint32 callbackData,
5829 			      Uint32 returnCode){
5830   jam();
5831 
5832   CreateTableRecordPtr createTabPtr;
5833   ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
5834 
5835   //@todo check for master failed
5836 
5837   if(createTabPtr.p->m_errorCode == 0){
5838     jam();
5839 
5840     CreateTabConf * const conf = (CreateTabConf*)signal->getDataPtr();
5841     conf->senderRef = reference();
5842     conf->senderData = createTabPtr.p->key;
5843     sendSignal(createTabPtr.p->m_coordinatorRef, GSN_CREATE_TAB_CONF,
5844 	       signal, CreateTabConf::SignalLength, JBB);
5845     return;
5846   }
5847 
5848   CreateTabRef * const ref = (CreateTabRef*)signal->getDataPtr();
5849   ref->senderRef = reference();
5850   ref->senderData = createTabPtr.p->key;
5851   ref->errorCode = createTabPtr.p->m_errorCode;
5852   ref->errorLine = 0;
5853   ref->errorKey = 0;
5854   ref->errorStatus = 0;
5855 
5856   sendSignal(createTabPtr.p->m_coordinatorRef, GSN_CREATE_TAB_REF,
5857 	     signal, CreateTabRef::SignalLength, JBB);
5858 }
5859 
5860 void
createTab_commit(Signal * signal,CreateTabReq * req)5861 Dbdict::createTab_commit(Signal * signal, CreateTabReq * req){
5862   jam();
5863 
5864   CreateTableRecordPtr createTabPtr;
5865   ndbrequire(c_opCreateTable.find(createTabPtr, req->senderData));
5866 
5867   TableRecordPtr tabPtr;
5868   c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
5869   bool savetodisk = !(tabPtr.p->m_bits & TableRecord::TR_Temporary);
5870 
5871   SchemaFile::TableEntry tabEntry;
5872   tabEntry.m_tableVersion = tabPtr.p->tableVersion;
5873   tabEntry.m_tableType    = tabPtr.p->tableType;
5874   if (savetodisk)
5875     tabEntry.m_tableState   = SchemaFile::TABLE_ADD_COMMITTED;
5876   else
5877     tabEntry.m_tableState   = SchemaFile::TEMPORARY_TABLE_COMMITTED;
5878 
5879   tabEntry.m_gcp          = tabPtr.p->gciTableCreated;
5880   tabEntry.m_info_words   = tabPtr.p->packedSize;
5881   memset(tabEntry.m_unused, 0, sizeof(tabEntry.m_unused));
5882 
5883   Callback callback;
5884   callback.m_callbackData = createTabPtr.p->key;
5885   callback.m_callbackFunction =
5886     safe_cast(&Dbdict::createTab_writeSchemaConf2);
5887 
5888   updateSchemaState(signal, tabPtr.i, &tabEntry, &callback, savetodisk);
5889 }
5890 
5891 void
createTab_writeSchemaConf2(Signal * signal,Uint32 callbackData,Uint32 returnCode)5892 Dbdict::createTab_writeSchemaConf2(Signal* signal,
5893 				   Uint32 callbackData,
5894 				   Uint32 returnCode){
5895   jam();
5896 
5897   CreateTableRecordPtr createTabPtr;
5898   ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
5899 
5900   Callback c;
5901   c.m_callbackData = callbackData;
5902   c.m_callbackFunction = safe_cast(&Dbdict::createTab_alterComplete);
5903   alterTab_activate(signal, createTabPtr, &c);
5904 }
5905 
5906 void
createTab_alterComplete(Signal * signal,Uint32 callbackData,Uint32 returnCode)5907 Dbdict::createTab_alterComplete(Signal* signal,
5908 				Uint32 callbackData,
5909 				Uint32 returnCode){
5910   jam();
5911 
5912   CreateTableRecordPtr createTabPtr;
5913   ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
5914 
5915   TableRecordPtr tabPtr;
5916   c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
5917   tabPtr.p->tabState = TableRecord::DEFINED;
5918 
5919   //@todo check error
5920   //@todo check master failed
5921 
5922   CreateTabConf * const conf = (CreateTabConf*)signal->getDataPtr();
5923   conf->senderRef = reference();
5924   conf->senderData = createTabPtr.p->key;
5925   {
5926     CreateTabConf tmp= *conf;
5927     conf->senderData = createTabPtr.p->m_tablePtrI;
5928 #if 0
5929     signal->header.m_noOfSections = 1;
5930     SegmentedSectionPtr tabInfoPtr;
5931     getSection(tabInfoPtr, createTabPtr.p->m_tabInfoPtrI);
5932     signal->setSection(tabInfoPtr, 0);
5933 #endif
5934     sendSignal(SUMA_REF, GSN_CREATE_TAB_CONF, signal,
5935 		CreateTabConf::SignalLength, JBB);
5936     *conf= tmp;
5937 #if 0
5938     signal->header.m_noOfSections = 0;
5939 #endif
5940   }
5941   sendSignal(createTabPtr.p->m_coordinatorRef, GSN_CREATE_TAB_CONF,
5942 	     signal, CreateTabConf::SignalLength, JBB);
5943 
5944   if(createTabPtr.p->m_coordinatorRef != reference()){
5945     jam();
5946     releaseCreateTableOp(signal,createTabPtr);
5947   }
5948 }
5949 
5950 void
createTab_drop(Signal * signal,CreateTabReq * req)5951 Dbdict::createTab_drop(Signal* signal, CreateTabReq * req){
5952   jam();
5953 
5954   const Uint32 key = req->senderData;
5955 
5956   CreateTableRecordPtr createTabPtr;
5957   ndbrequire(c_opCreateTable.find(createTabPtr, key));
5958 
5959   TableRecordPtr tabPtr;
5960   c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
5961   tabPtr.p->tabState = TableRecord::DROPPING;
5962 
5963   DropTableRecordPtr dropTabPtr;
5964   ndbrequire(c_opDropTable.seize(dropTabPtr));
5965 
5966   dropTabPtr.p->key = key;
5967   c_opDropTable.add(dropTabPtr);
5968 
5969   dropTabPtr.p->m_errorCode = 0;
5970   dropTabPtr.p->m_request.tableId = createTabPtr.p->m_tablePtrI;
5971   dropTabPtr.p->m_requestType = DropTabReq::CreateTabDrop;
5972   dropTabPtr.p->m_coordinatorRef = createTabPtr.p->m_coordinatorRef;
5973   dropTabPtr.p->m_participantData.m_gsn = GSN_DROP_TAB_REQ;
5974 
5975   dropTabPtr.p->m_participantData.m_block = 0;
5976   dropTabPtr.p->m_participantData.m_callback.m_callbackData = req->senderData;
5977   dropTabPtr.p->m_participantData.m_callback.m_callbackFunction =
5978     safe_cast(&Dbdict::createTab_dropComplete);
5979   dropTab_nextStep(signal, dropTabPtr);
5980 
5981   if (tabPtr.p->m_tablespace_id != RNIL)
5982   {
5983     FilegroupPtr ptr;
5984     ndbrequire(c_filegroup_hash.find(ptr, tabPtr.p->m_tablespace_id));
5985     decrease_ref_count(ptr.p->m_obj_ptr_i);
5986   }
5987 }
5988 
5989 void
createTab_dropComplete(Signal * signal,Uint32 callbackData,Uint32 returnCode)5990 Dbdict::createTab_dropComplete(Signal* signal,
5991 			       Uint32 callbackData,
5992 			       Uint32 returnCode){
5993   jam();
5994 
5995   CreateTableRecordPtr createTabPtr;
5996   ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
5997 
5998   DropTableRecordPtr dropTabPtr;
5999   ndbrequire(c_opDropTable.find(dropTabPtr, callbackData));
6000 
6001   TableRecordPtr tabPtr;
6002   c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
6003 
6004   releaseTableObject(tabPtr.i);
6005 
6006   XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
6007   SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, tabPtr.i);
6008   tableEntry->m_tableState = SchemaFile::DROP_TABLE_COMMITTED;
6009 
6010   //@todo check error
6011   //@todo check master failed
6012 
6013   CreateTabConf * const conf = (CreateTabConf*)signal->getDataPtr();
6014   conf->senderRef = reference();
6015   conf->senderData = createTabPtr.p->key;
6016   sendSignal(createTabPtr.p->m_coordinatorRef, GSN_CREATE_TAB_CONF,
6017 	     signal, CreateTabConf::SignalLength, JBB);
6018 
6019   if(createTabPtr.p->m_coordinatorRef != reference()){
6020     jam();
6021     releaseCreateTableOp(signal,createTabPtr);
6022   }
6023 
6024   c_opDropTable.release(dropTabPtr);
6025 }
6026 
6027 void
alterTab_activate(Signal * signal,CreateTableRecordPtr createTabPtr,Callback * c)6028 Dbdict::alterTab_activate(Signal* signal, CreateTableRecordPtr createTabPtr,
6029 			  Callback * c){
6030 
6031   createTabPtr.p->m_callback = * c;
6032 
6033   signal->theData[0] = createTabPtr.p->key;
6034   signal->theData[1] = reference();
6035   signal->theData[2] = createTabPtr.p->m_tablePtrI;
6036   sendSignal(DBDIH_REF, GSN_TAB_COMMITREQ, signal, 3, JBB);
6037 }
6038 
6039 void
execTC_SCHVERCONF(Signal * signal)6040 Dbdict::execTC_SCHVERCONF(Signal* signal){
6041   jamEntry();
6042 
6043   CreateTableRecordPtr createTabPtr;
6044   ndbrequire(c_opCreateTable.find(createTabPtr, signal->theData[1]));
6045 
6046   execute(signal, createTabPtr.p->m_callback, 0);
6047 }
6048 
6049 #define tabRequire(cond, error) \
6050   if (!(cond)) { \
6051     jam();    \
6052     parseP->errorCode = error; parseP->errorLine = __LINE__; \
6053     parseP->errorKey = it.getKey(); \
6054     return;   \
6055   }//if
6056 
6057 // handleAddTableFailure(signal, __LINE__, allocatedTable);
6058 
6059 Dbdict::DictObject *
get_object(const char * name,Uint32 len,Uint32 hash)6060 Dbdict::get_object(const char * name, Uint32 len, Uint32 hash){
6061   DictObject key;
6062   key.m_key.m_name_ptr = name;
6063   key.m_key.m_name_len = len;
6064   key.m_key.m_pool = &c_rope_pool;
6065   key.m_name.m_hash = hash;
6066   Ptr<DictObject> old_ptr;
6067   c_obj_hash.find(old_ptr, key);
6068   return old_ptr.p;
6069 }
6070 
6071 void
release_object(Uint32 obj_ptr_i,DictObject * obj_ptr_p)6072 Dbdict::release_object(Uint32 obj_ptr_i, DictObject* obj_ptr_p){
6073   Rope name(c_rope_pool, obj_ptr_p->m_name);
6074   name.erase();
6075 
6076   Ptr<DictObject> ptr = { obj_ptr_p, obj_ptr_i };
6077   c_obj_hash.release(ptr);
6078 }
6079 
6080 void
increase_ref_count(Uint32 obj_ptr_i)6081 Dbdict::increase_ref_count(Uint32 obj_ptr_i)
6082 {
6083   DictObject* ptr = c_obj_pool.getPtr(obj_ptr_i);
6084   ptr->m_ref_count++;
6085 }
6086 
6087 void
decrease_ref_count(Uint32 obj_ptr_i)6088 Dbdict::decrease_ref_count(Uint32 obj_ptr_i)
6089 {
6090   DictObject* ptr = c_obj_pool.getPtr(obj_ptr_i);
6091   ndbrequire(ptr->m_ref_count);
6092   ptr->m_ref_count--;
6093 }
6094 
handleTabInfoInit(SimpleProperties::Reader & it,ParseDictTabInfoRecord * parseP,bool checkExist)6095 void Dbdict::handleTabInfoInit(SimpleProperties::Reader & it,
6096 			       ParseDictTabInfoRecord * parseP,
6097 			       bool checkExist)
6098 {
6099 /* ---------------------------------------------------------------- */
6100 // We always start by handling table name since this must be the first
6101 // item in the list. Through the table name we can derive if it is a
6102 // correct name, a new name or an already existing table.
6103 /* ---------------------------------------------------------------- */
6104 
6105   it.first();
6106 
6107   SimpleProperties::UnpackStatus status;
6108   c_tableDesc.init();
6109   status = SimpleProperties::unpack(it, &c_tableDesc,
6110 				    DictTabInfo::TableMapping,
6111 				    DictTabInfo::TableMappingSize,
6112 				    true, true);
6113 
6114   if(status != SimpleProperties::Break){
6115     parseP->errorCode = CreateTableRef::InvalidFormat;
6116     parseP->status    = status;
6117     parseP->errorKey  = it.getKey();
6118     parseP->errorLine = __LINE__;
6119     return;
6120   }
6121 
6122   if(parseP->requestType == DictTabInfo::AlterTableFromAPI)
6123   {
6124     ndbrequire(!checkExist);
6125   }
6126   if(!checkExist)
6127   {
6128     ndbrequire(parseP->requestType == DictTabInfo::AlterTableFromAPI);
6129   }
6130 
6131   /* ---------------------------------------------------------------- */
6132   // Verify that table name is an allowed table name.
6133   // TODO
6134   /* ---------------------------------------------------------------- */
6135   const Uint32 tableNameLength = strlen(c_tableDesc.TableName) + 1;
6136   const Uint32 name_hash = Rope::hash(c_tableDesc.TableName, tableNameLength);
6137 
6138   if(checkExist){
6139     jam();
6140     tabRequire(get_object(c_tableDesc.TableName, tableNameLength) == 0,
6141 	       CreateTableRef::TableAlreadyExist);
6142   }
6143 
6144   TableRecordPtr tablePtr;
6145   switch (parseP->requestType) {
6146   case DictTabInfo::CreateTableFromAPI: {
6147     jam();
6148   }
6149   case DictTabInfo::AlterTableFromAPI:{
6150     jam();
6151     tablePtr.i = getFreeTableRecord(c_tableDesc.PrimaryTableId);
6152     /* ---------------------------------------------------------------- */
6153     // Check if no free tables existed.
6154     /* ---------------------------------------------------------------- */
6155     tabRequire(tablePtr.i != RNIL, CreateTableRef::NoMoreTableRecords);
6156 
6157     c_tableRecordPool.getPtr(tablePtr);
6158     break;
6159   }
6160   case DictTabInfo::AddTableFromDict:
6161   case DictTabInfo::ReadTableFromDiskSR:
6162   case DictTabInfo::GetTabInfoConf:
6163   {
6164 /* ---------------------------------------------------------------- */
6165 // Get table id and check that table doesn't already exist
6166 /* ---------------------------------------------------------------- */
6167     tablePtr.i = c_tableDesc.TableId;
6168 
6169     if (parseP->requestType == DictTabInfo::ReadTableFromDiskSR) {
6170       ndbrequire(tablePtr.i == c_restartRecord.activeTable);
6171     }//if
6172     if (parseP->requestType == DictTabInfo::GetTabInfoConf) {
6173       ndbrequire(tablePtr.i == c_restartRecord.activeTable);
6174     }//if
6175 
6176     c_tableRecordPool.getPtr(tablePtr);
6177     ndbrequire(tablePtr.p->tabState == TableRecord::NOT_DEFINED);
6178 
6179     //Uint32 oldTableVersion = tablePtr.p->tableVersion;
6180     initialiseTableRecord(tablePtr);
6181     if (parseP->requestType == DictTabInfo::AddTableFromDict) {
6182       jam();
6183       tablePtr.p->tabState = TableRecord::DEFINING;
6184     }//if
6185 
6186 /* ---------------------------------------------------------------- */
6187 // Set table version
6188 /* ---------------------------------------------------------------- */
6189     Uint32 tableVersion = c_tableDesc.TableVersion;
6190     tablePtr.p->tableVersion = tableVersion;
6191 
6192     break;
6193   }
6194   default:
6195     ndbrequire(false);
6196     break;
6197   }//switch
6198   parseP->tablePtr = tablePtr;
6199 
6200   {
6201     Rope name(c_rope_pool, tablePtr.p->tableName);
6202     tabRequire(name.assign(c_tableDesc.TableName, tableNameLength, name_hash),
6203 	       CreateTableRef::OutOfStringBuffer);
6204   }
6205 
6206   Ptr<DictObject> obj_ptr;
6207   if (parseP->requestType != DictTabInfo::AlterTableFromAPI) {
6208     jam();
6209     ndbrequire(c_obj_hash.seize(obj_ptr));
6210     obj_ptr.p->m_id = tablePtr.i;
6211     obj_ptr.p->m_type = c_tableDesc.TableType;
6212     obj_ptr.p->m_name = tablePtr.p->tableName;
6213     obj_ptr.p->m_ref_count = 0;
6214     c_obj_hash.add(obj_ptr);
6215     tablePtr.p->m_obj_ptr_i = obj_ptr.i;
6216 
6217 #ifdef VM_TRACE
6218     ndbout_c("Dbdict: name=%s,id=%u,obj_ptr_i=%d",
6219 	     c_tableDesc.TableName, tablePtr.i, tablePtr.p->m_obj_ptr_i);
6220 #endif
6221   }
6222 
6223   // Disallow logging of a temporary table.
6224   tabRequire(!(c_tableDesc.TableTemporaryFlag && c_tableDesc.TableLoggedFlag),
6225              CreateTableRef::NoLoggingTemporaryTable);
6226 
6227   tablePtr.p->noOfAttributes = c_tableDesc.NoOfAttributes;
6228   tablePtr.p->m_bits |=
6229     (c_tableDesc.TableLoggedFlag ? TableRecord::TR_Logged : 0);
6230   tablePtr.p->m_bits |=
6231     (c_tableDesc.RowChecksumFlag ? TableRecord::TR_RowChecksum : 0);
6232   tablePtr.p->m_bits |=
6233     (c_tableDesc.RowGCIFlag ? TableRecord::TR_RowGCI : 0);
6234   tablePtr.p->m_bits |=
6235     (c_tableDesc.TableTemporaryFlag ? TableRecord::TR_Temporary : 0);
6236   tablePtr.p->m_bits |=
6237     (c_tableDesc.ForceVarPartFlag ? TableRecord::TR_ForceVarPart : 0);
6238   tablePtr.p->minLoadFactor = c_tableDesc.MinLoadFactor;
6239   tablePtr.p->maxLoadFactor = c_tableDesc.MaxLoadFactor;
6240   tablePtr.p->fragmentType = (DictTabInfo::FragmentType)c_tableDesc.FragmentType;
6241   tablePtr.p->tableType = (DictTabInfo::TableType)c_tableDesc.TableType;
6242   tablePtr.p->kValue = c_tableDesc.TableKValue;
6243   tablePtr.p->fragmentCount = c_tableDesc.FragmentCount;
6244   tablePtr.p->m_tablespace_id = c_tableDesc.TablespaceId;
6245   tablePtr.p->maxRowsLow = c_tableDesc.MaxRowsLow;
6246   tablePtr.p->maxRowsHigh = c_tableDesc.MaxRowsHigh;
6247   tablePtr.p->minRowsLow = c_tableDesc.MinRowsLow;
6248   tablePtr.p->minRowsHigh = c_tableDesc.MinRowsHigh;
6249   tablePtr.p->defaultNoPartFlag = c_tableDesc.DefaultNoPartFlag;
6250   tablePtr.p->linearHashFlag = c_tableDesc.LinearHashFlag;
6251   tablePtr.p->singleUserMode = c_tableDesc.SingleUserMode;
6252 
6253   {
6254     Rope frm(c_rope_pool, tablePtr.p->frmData);
6255     tabRequire(frm.assign(c_tableDesc.FrmData, c_tableDesc.FrmLen),
6256 	       CreateTableRef::OutOfStringBuffer);
6257     Rope range(c_rope_pool, tablePtr.p->rangeData);
6258     tabRequire(range.assign(c_tableDesc.RangeListData,
6259                c_tableDesc.RangeListDataLen),
6260 	      CreateTableRef::OutOfStringBuffer);
6261     Rope fd(c_rope_pool, tablePtr.p->ngData);
6262     tabRequire(fd.assign((const char*)c_tableDesc.FragmentData,
6263                          c_tableDesc.FragmentDataLen),
6264 	       CreateTableRef::OutOfStringBuffer);
6265     Rope ts(c_rope_pool, tablePtr.p->tsData);
6266     tabRequire(ts.assign((const char*)c_tableDesc.TablespaceData,
6267                          c_tableDesc.TablespaceDataLen),
6268 	       CreateTableRef::OutOfStringBuffer);
6269   }
6270 
6271   c_fragDataLen = c_tableDesc.FragmentDataLen;
6272   memcpy(c_fragData, c_tableDesc.FragmentData,
6273          c_tableDesc.FragmentDataLen);
6274 
6275   if(c_tableDesc.PrimaryTableId != RNIL) {
6276 
6277     tablePtr.p->primaryTableId = c_tableDesc.PrimaryTableId;
6278     tablePtr.p->indexState = (TableRecord::IndexState)c_tableDesc.IndexState;
6279     tablePtr.p->insertTriggerId = c_tableDesc.InsertTriggerId;
6280     tablePtr.p->updateTriggerId = c_tableDesc.UpdateTriggerId;
6281     tablePtr.p->deleteTriggerId = c_tableDesc.DeleteTriggerId;
6282     tablePtr.p->customTriggerId = c_tableDesc.CustomTriggerId;
6283   } else {
6284     tablePtr.p->primaryTableId = RNIL;
6285     tablePtr.p->indexState = TableRecord::IS_UNDEFINED;
6286     tablePtr.p->insertTriggerId = RNIL;
6287     tablePtr.p->updateTriggerId = RNIL;
6288     tablePtr.p->deleteTriggerId = RNIL;
6289     tablePtr.p->customTriggerId = RNIL;
6290   }
6291   tablePtr.p->buildTriggerId = RNIL;
6292   tablePtr.p->indexLocal = 0;
6293 
6294   handleTabInfo(it, parseP, c_tableDesc);
6295 
6296   if(parseP->errorCode != 0)
6297   {
6298     /**
6299      * Release table
6300      */
6301     releaseTableObject(tablePtr.i, checkExist);
6302     return;
6303   }
6304 
6305   if (checkExist && tablePtr.p->m_tablespace_id != RNIL)
6306   {
6307     /**
6308      * Increase ref count
6309      */
6310     FilegroupPtr ptr;
6311     ndbrequire(c_filegroup_hash.find(ptr, tablePtr.p->m_tablespace_id));
6312     increase_ref_count(ptr.p->m_obj_ptr_i);
6313   }
6314 }//handleTabInfoInit()
6315 
handleTabInfo(SimpleProperties::Reader & it,ParseDictTabInfoRecord * parseP,DictTabInfo::Table & tableDesc)6316 void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
6317 			   ParseDictTabInfoRecord * parseP,
6318 			   DictTabInfo::Table &tableDesc)
6319 {
6320   TableRecordPtr tablePtr = parseP->tablePtr;
6321 
6322   SimpleProperties::UnpackStatus status;
6323 
6324   Uint32 keyCount = 0;
6325   Uint32 keyLength = 0;
6326   Uint32 attrCount = tablePtr.p->noOfAttributes;
6327   Uint32 nullCount = 0;
6328   Uint32 nullBits = 0;
6329   Uint32 noOfCharsets = 0;
6330   Uint16 charsets[128];
6331   Uint32 recordLength = 0;
6332   AttributeRecordPtr attrPtr;
6333   c_attributeRecordHash.removeAll();
6334 
6335   LocalDLFifoList<AttributeRecord> list(c_attributeRecordPool,
6336 					tablePtr.p->m_attributes);
6337 
6338   Uint32 counts[] = {0,0,0,0,0};
6339 
6340   for(Uint32 i = 0; i<attrCount; i++){
6341     /**
6342      * Attribute Name
6343      */
6344     DictTabInfo::Attribute attrDesc; attrDesc.init();
6345     status = SimpleProperties::unpack(it, &attrDesc,
6346 				      DictTabInfo::AttributeMapping,
6347 				      DictTabInfo::AttributeMappingSize,
6348 				      true, true);
6349 
6350     if(status != SimpleProperties::Break){
6351       parseP->errorCode = CreateTableRef::InvalidFormat;
6352       parseP->status    = status;
6353       parseP->errorKey  = it.getKey();
6354       parseP->errorLine = __LINE__;
6355       return;
6356     }
6357 
6358     /**
6359      * Check that attribute is not defined twice
6360      */
6361     const size_t len = strlen(attrDesc.AttributeName)+1;
6362     const Uint32 name_hash = Rope::hash(attrDesc.AttributeName, len);
6363     {
6364       AttributeRecord key;
6365       key.m_key.m_name_ptr = attrDesc.AttributeName;
6366       key.m_key.m_name_len = len;
6367       key.attributeName.m_hash = name_hash;
6368       key.m_key.m_pool = &c_rope_pool;
6369       Ptr<AttributeRecord> old_ptr;
6370       c_attributeRecordHash.find(old_ptr, key);
6371 
6372       if(old_ptr.i != RNIL){
6373 	parseP->errorCode = CreateTableRef::AttributeNameTwice;
6374 	return;
6375       }
6376     }
6377 
6378     list.seize(attrPtr);
6379     if(attrPtr.i == RNIL){
6380       jam();
6381       parseP->errorCode = CreateTableRef::NoMoreAttributeRecords;
6382       return;
6383     }
6384 
6385     new (attrPtr.p) AttributeRecord();
6386     attrPtr.p->attributeDescriptor = 0x00012255; //Default value
6387     attrPtr.p->tupleKey = 0;
6388 
6389     /**
6390      * TmpAttrib to Attribute mapping
6391      */
6392     {
6393       Rope name(c_rope_pool, attrPtr.p->attributeName);
6394       if (!name.assign(attrDesc.AttributeName, len, name_hash))
6395       {
6396 	jam();
6397 	parseP->errorCode = CreateTableRef::OutOfStringBuffer;
6398 	parseP->errorLine = __LINE__;
6399 	return;
6400       }
6401     }
6402     attrPtr.p->attributeId = i;
6403     //attrPtr.p->attributeId = attrDesc.AttributeId;
6404     attrPtr.p->tupleKey = (keyCount + 1) * attrDesc.AttributeKeyFlag;
6405 
6406     attrPtr.p->extPrecision = attrDesc.AttributeExtPrecision;
6407     attrPtr.p->extScale = attrDesc.AttributeExtScale;
6408     attrPtr.p->extLength = attrDesc.AttributeExtLength;
6409     // charset in upper half of precision
6410     unsigned csNumber = (attrPtr.p->extPrecision >> 16);
6411     if (csNumber != 0) {
6412       /*
6413        * A new charset is first accessed here on this node.
6414        * TODO use separate thread (e.g. via NDBFS) if need to load from file
6415        */
6416       CHARSET_INFO* cs = get_charset(csNumber, MYF(0));
6417       if (cs == NULL) {
6418         parseP->errorCode = CreateTableRef::InvalidCharset;
6419         parseP->errorLine = __LINE__;
6420         return;
6421       }
6422       // XXX should be done somewhere in mysql
6423       all_charsets[cs->number] = cs;
6424       unsigned i = 0;
6425       while (i < noOfCharsets) {
6426         if (charsets[i] == csNumber)
6427           break;
6428         i++;
6429       }
6430       if (i == noOfCharsets) {
6431         noOfCharsets++;
6432         if (noOfCharsets > sizeof(charsets)/sizeof(charsets[0])) {
6433           parseP->errorCode = CreateTableRef::InvalidFormat;
6434           parseP->errorLine = __LINE__;
6435           return;
6436         }
6437         charsets[i] = csNumber;
6438       }
6439     }
6440 
6441     // compute attribute size and array size
6442     bool translateOk = attrDesc.translateExtType();
6443     tabRequire(translateOk, CreateTableRef::Inconsistency);
6444 
6445     if(attrDesc.AttributeArraySize > 65535){
6446       parseP->errorCode = CreateTableRef::ArraySizeTooBig;
6447       parseP->status    = status;
6448       parseP->errorKey  = it.getKey();
6449       parseP->errorLine = __LINE__;
6450       return;
6451     }
6452 
6453     // XXX old test option, remove
6454     if(!attrDesc.AttributeKeyFlag &&
6455        tablePtr.i > 1 &&
6456        !tablePtr.p->isIndex())
6457     {
6458       //attrDesc.AttributeStorageType= NDB_STORAGETYPE_DISK;
6459     }
6460 
6461     Uint32 desc = 0;
6462     AttributeDescriptor::setType(desc, attrDesc.AttributeExtType);
6463     AttributeDescriptor::setSize(desc, attrDesc.AttributeSize);
6464     AttributeDescriptor::setArraySize(desc, attrDesc.AttributeArraySize);
6465     AttributeDescriptor::setArrayType(desc, attrDesc.AttributeArrayType);
6466     AttributeDescriptor::setNullable(desc, attrDesc.AttributeNullableFlag);
6467     AttributeDescriptor::setDKey(desc, attrDesc.AttributeDKey);
6468     AttributeDescriptor::setPrimaryKey(desc, attrDesc.AttributeKeyFlag);
6469     AttributeDescriptor::setDiskBased(desc, attrDesc.AttributeStorageType == NDB_STORAGETYPE_DISK);
6470     attrPtr.p->attributeDescriptor = desc;
6471     attrPtr.p->autoIncrement = attrDesc.AttributeAutoIncrement;
6472     {
6473       Rope defaultValue(c_rope_pool, attrPtr.p->defaultValue);
6474       defaultValue.assign(attrDesc.AttributeDefaultValue);
6475     }
6476 
6477     keyCount += attrDesc.AttributeKeyFlag;
6478     nullCount += attrDesc.AttributeNullableFlag;
6479 
6480     const Uint32 aSz = (1 << attrDesc.AttributeSize);
6481     Uint32 sz;
6482     if(aSz != 1)
6483     {
6484       sz = ((aSz * attrDesc.AttributeArraySize) + 31) >> 5;
6485     }
6486     else
6487     {
6488       sz = 0;
6489       nullBits += attrDesc.AttributeArraySize;
6490     }
6491 
6492     if(attrDesc.AttributeArraySize == 0)
6493     {
6494       parseP->errorCode = CreateTableRef::InvalidArraySize;
6495       parseP->status    = status;
6496       parseP->errorKey  = it.getKey();
6497       parseP->errorLine = __LINE__;
6498       return;
6499     }
6500 
6501     recordLength += sz;
6502     if(attrDesc.AttributeKeyFlag){
6503       keyLength += sz;
6504 
6505       if(attrDesc.AttributeNullableFlag){
6506 	parseP->errorCode = CreateTableRef::NullablePrimaryKey;
6507 	parseP->status    = status;
6508 	parseP->errorKey  = it.getKey();
6509 	parseP->errorLine = __LINE__;
6510 	return;
6511       }
6512     }
6513 
6514     c_attributeRecordHash.add(attrPtr);
6515 
6516     int a= AttributeDescriptor::getDiskBased(desc);
6517     int b= AttributeDescriptor::getArrayType(desc);
6518     Uint32 pos= 2*(a ? 1 : 0) + (b == NDB_ARRAYTYPE_FIXED ? 0 : 1);
6519     counts[pos+1]++;
6520 
6521     if(b != NDB_ARRAYTYPE_FIXED && sz == 0)
6522     {
6523       parseP->errorCode = CreateTableRef::VarsizeBitfieldNotSupported;
6524       parseP->status    = status;
6525       parseP->errorKey  = it.getKey();
6526       parseP->errorLine = __LINE__;
6527       return;
6528     }
6529 
6530     if(!it.next())
6531       break;
6532 
6533     if(it.getKey() != DictTabInfo::AttributeName)
6534       break;
6535   }//while
6536 
6537   tablePtr.p->noOfPrimkey = keyCount;
6538   tablePtr.p->noOfNullAttr = nullCount;
6539   tablePtr.p->noOfCharsets = noOfCharsets;
6540   tablePtr.p->tupKeyLength = keyLength;
6541   tablePtr.p->noOfNullBits = nullCount + nullBits;
6542 
6543   tabRequire(recordLength<= MAX_TUPLE_SIZE_IN_WORDS,
6544 	     CreateTableRef::RecordTooBig);
6545   tabRequire(keyLength <= MAX_KEY_SIZE_IN_WORDS,
6546 	     CreateTableRef::InvalidPrimaryKeySize);
6547   tabRequire(keyLength > 0,
6548 	     CreateTableRef::InvalidPrimaryKeySize);
6549 
6550   if(tablePtr.p->m_tablespace_id != RNIL || counts[3] || counts[4])
6551   {
6552     FilegroupPtr tablespacePtr;
6553     if(!c_filegroup_hash.find(tablespacePtr, tablePtr.p->m_tablespace_id))
6554     {
6555       tabRequire(false, CreateTableRef::InvalidTablespace);
6556     }
6557 
6558     if(tablespacePtr.p->m_type != DictTabInfo::Tablespace)
6559     {
6560       tabRequire(false, CreateTableRef::NotATablespace);
6561     }
6562 
6563     if(tablespacePtr.p->m_version != tableDesc.TablespaceVersion)
6564     {
6565       tabRequire(false, CreateTableRef::InvalidTablespaceVersion);
6566     }
6567   }
6568 }//handleTabInfo()
6569 
6570 
6571 /* ---------------------------------------------------------------- */
6572 // DICTTABCONF is sent when participants have received all DICTTABINFO
6573 // and successfully handled it.
6574 // Also sent to self (DICT master) when index table creation ready.
6575 /* ---------------------------------------------------------------- */
execCREATE_TABLE_CONF(Signal * signal)6576 void Dbdict::execCREATE_TABLE_CONF(Signal* signal)
6577 {
6578   jamEntry();
6579   ndbrequire(signal->getNoOfSections() == 0);
6580 
6581   CreateTableConf * const conf = (CreateTableConf *)signal->getDataPtr();
6582   // assume part of create index operation
6583   OpCreateIndexPtr opPtr;
6584   c_opCreateIndex.find(opPtr, conf->senderData);
6585   ndbrequire(! opPtr.isNull());
6586   opPtr.p->m_request.setIndexId(conf->tableId);
6587   opPtr.p->m_request.setIndexVersion(conf->tableVersion);
6588   createIndex_fromCreateTable(signal, opPtr);
6589 }//execCREATE_TABLE_CONF()
6590 
execCREATE_TABLE_REF(Signal * signal)6591 void Dbdict::execCREATE_TABLE_REF(Signal* signal)
6592 {
6593   jamEntry();
6594 
6595   CreateTableRef * const ref = (CreateTableRef *)signal->getDataPtr();
6596   // assume part of create index operation
6597   OpCreateIndexPtr opPtr;
6598   c_opCreateIndex.find(opPtr, ref->senderData);
6599   ndbrequire(! opPtr.isNull());
6600   opPtr.p->setError(ref);
6601   createIndex_fromCreateTable(signal, opPtr);
6602 }//execCREATE_TABLE_REF()
6603 
6604 /* ---------------------------------------------------------------- */
6605 // New global checkpoint created.
6606 /* ---------------------------------------------------------------- */
execWAIT_GCP_CONF(Signal * signal)6607 void Dbdict::execWAIT_GCP_CONF(Signal* signal)
6608 {
6609 #if 0
6610   TableRecordPtr tablePtr;
6611   jamEntry();
6612   WaitGCPConf* const conf = (WaitGCPConf*)&signal->theData[0];
6613   c_tableRecordPool.getPtr(tablePtr, c_connRecord.connTableId);
6614   tablePtr.p->gciTableCreated = conf->gcp;
6615   sendUpdateSchemaState(signal,
6616                         tablePtr.i,
6617                         SchemaFile::TABLE_ADD_COMMITTED,
6618                         c_connRecord.noOfPagesForTable,
6619                         conf->gcp);
6620 #endif
6621 }//execWAIT_GCP_CONF()
6622 
6623 /* ---------------------------------------------------------------- */
6624 // Refused new global checkpoint.
6625 /* ---------------------------------------------------------------- */
execWAIT_GCP_REF(Signal * signal)6626 void Dbdict::execWAIT_GCP_REF(Signal* signal)
6627 {
6628   jamEntry();
6629   WaitGCPRef* const ref = (WaitGCPRef*)&signal->theData[0];
6630 /* ---------------------------------------------------------------- */
6631 // Error Handling code needed
6632 /* ---------------------------------------------------------------- */
6633   char buf[32];
6634   BaseString::snprintf(buf, sizeof(buf), "WAIT_GCP_REF ErrorCode=%d",
6635 		       ref->errorCode);
6636   progError(__LINE__, NDBD_EXIT_NDBREQUIRE, buf);
6637 }//execWAIT_GCP_REF()
6638 
6639 
6640 /* **************************************************************** */
6641 /* ---------------------------------------------------------------- */
6642 /* MODULE:          DROP TABLE                 -------------------- */
6643 /* ---------------------------------------------------------------- */
6644 /*                                                                  */
6645 /* This module contains the code used to drop a table.              */
6646 /* ---------------------------------------------------------------- */
6647 /* **************************************************************** */
6648 void
execDROP_TABLE_REQ(Signal * signal)6649 Dbdict::execDROP_TABLE_REQ(Signal* signal){
6650   jamEntry();
6651   DropTableReq* req = (DropTableReq*)signal->getDataPtr();
6652 
6653   TableRecordPtr tablePtr;
6654   c_tableRecordPool.getPtr(tablePtr, req->tableId, false);
6655   if(tablePtr.isNull()){
6656     jam();
6657     dropTableRef(signal, req, DropTableRef::NoSuchTable);
6658     return;
6659   }
6660 
6661   if(getOwnNodeId() != c_masterNodeId){
6662     jam();
6663     dropTableRef(signal, req, DropTableRef::NotMaster);
6664     return;
6665   }
6666 
6667   if(c_blockState == BS_NODE_RESTART){
6668     jam();
6669     dropTableRef(signal, req, DropTableRef::BusyWithNR);
6670     return;
6671   }
6672 
6673   if(c_blockState != BS_IDLE){
6674     jam();
6675     dropTableRef(signal, req, DropTableRef::Busy);
6676     return;
6677   }
6678 
6679   if (checkSingleUserMode(signal->getSendersBlockRef()))
6680   {
6681     jam();
6682     dropTableRef(signal, req, DropTableRef::SingleUser);
6683     return;
6684   }
6685 
6686   const TableRecord::TabState tabState = tablePtr.p->tabState;
6687   bool ok = false;
6688   switch(tabState){
6689   case TableRecord::NOT_DEFINED:
6690   case TableRecord::DEFINING:
6691     jam();
6692     dropTableRef(signal, req, DropTableRef::NoSuchTable);
6693     return;
6694   case TableRecord::DEFINED:
6695     ok = true;
6696     jam();
6697     break;
6698   case TableRecord::PREPARE_DROPPING:
6699   case TableRecord::DROPPING:
6700     jam();
6701     dropTableRef(signal, req, DropTableRef::DropInProgress);
6702     return;
6703   case TableRecord::BACKUP_ONGOING:
6704     jam();
6705     dropTableRef(signal, req, DropTableRef::BackupInProgress);
6706     return;
6707   }
6708   ndbrequire(ok);
6709 
6710   if(tablePtr.p->tableVersion != req->tableVersion){
6711     jam();
6712     dropTableRef(signal, req, DropTableRef::InvalidTableVersion);
6713     return;
6714   }
6715 
6716   /**
6717    * Seems ok
6718    */
6719   DropTableRecordPtr dropTabPtr;
6720   c_opDropTable.seize(dropTabPtr);
6721 
6722   if(dropTabPtr.isNull()){
6723     jam();
6724     dropTableRef(signal, req, DropTableRef::NoDropTableRecordAvailable);
6725     return;
6726   }
6727 
6728   c_blockState = BS_BUSY;
6729 
6730   dropTabPtr.p->key = ++c_opRecordSequence;
6731   c_opDropTable.add(dropTabPtr);
6732 
6733   dropTabPtr.p->m_request = * req;
6734   dropTabPtr.p->m_errorCode = 0;
6735   dropTabPtr.p->m_requestType = DropTabReq::OnlineDropTab;
6736   dropTabPtr.p->m_coordinatorRef = reference();
6737   dropTabPtr.p->m_coordinatorData.m_gsn = GSN_PREP_DROP_TAB_REQ;
6738   dropTabPtr.p->m_coordinatorData.m_block = 0;
6739 
6740   Mutex mutex(signal, c_mutexMgr, dropTabPtr.p->m_define_backup_mutex);
6741   Callback c = { safe_cast(&Dbdict::dropTable_backup_mutex_locked),
6742 		 dropTabPtr.p->key};
6743 
6744   ndbrequire(mutex.lock(c));
6745 
6746 }
6747 
6748 void
dropTable_backup_mutex_locked(Signal * signal,Uint32 callbackData,Uint32 retValue)6749 Dbdict::dropTable_backup_mutex_locked(Signal* signal,
6750 				      Uint32 callbackData,
6751 				      Uint32 retValue){
6752   jamEntry();
6753 
6754   ndbrequire(retValue == 0);
6755 
6756   DropTableRecordPtr dropTabPtr;
6757   ndbrequire(c_opDropTable.find(dropTabPtr, callbackData));
6758 
6759   TableRecordPtr tablePtr;
6760   c_tableRecordPool.getPtr(tablePtr, dropTabPtr.p->m_request.tableId, true);
6761 
6762   Mutex mutex(signal, c_mutexMgr, dropTabPtr.p->m_define_backup_mutex);
6763   mutex.unlock(); // ignore response
6764 
6765   if(tablePtr.p->tabState == TableRecord::BACKUP_ONGOING)
6766   {
6767     jam();
6768     dropTableRef(signal, &dropTabPtr.p->m_request,
6769 		 DropTableRef::BackupInProgress);
6770 
6771     c_blockState = BS_IDLE;
6772     c_opDropTable.release(dropTabPtr);
6773   }
6774   else
6775   {
6776     jam();
6777     tablePtr.p->tabState = TableRecord::PREPARE_DROPPING;
6778     prepDropTab_nextStep(signal, dropTabPtr);
6779   }
6780 }
6781 
6782 void
dropTableRef(Signal * signal,DropTableReq * req,DropTableRef::ErrorCode errCode)6783 Dbdict::dropTableRef(Signal * signal,
6784 		     DropTableReq * req, DropTableRef::ErrorCode errCode){
6785 
6786   Uint32 tableId = req->tableId;
6787   Uint32 tabVersion = req->tableVersion;
6788   Uint32 senderData = req->senderData;
6789   Uint32 senderRef = req->senderRef;
6790 
6791   DropTableRef * ref = (DropTableRef*)signal->getDataPtrSend();
6792   ref->tableId = tableId;
6793   ref->tableVersion = tabVersion;
6794   ref->senderData = senderData;
6795   ref->senderRef = reference();
6796   ref->errorCode = errCode;
6797   ref->masterNodeId = c_masterNodeId;
6798   sendSignal(senderRef, GSN_DROP_TABLE_REF, signal,
6799 	     DropTableRef::SignalLength, JBB);
6800 }
6801 
6802 void
prepDropTab_nextStep(Signal * signal,DropTableRecordPtr dropTabPtr)6803 Dbdict::prepDropTab_nextStep(Signal* signal, DropTableRecordPtr dropTabPtr){
6804 
6805   /**
6806    * No errors currently allowed
6807    */
6808   ndbrequire(dropTabPtr.p->m_errorCode == 0);
6809 
6810   Uint32 block = 0;
6811   switch(dropTabPtr.p->m_coordinatorData.m_block){
6812   case 0:
6813     jam();
6814     block = dropTabPtr.p->m_coordinatorData.m_block = DBDICT;
6815     break;
6816   case DBDICT:
6817     jam();
6818     block = dropTabPtr.p->m_coordinatorData.m_block = DBLQH;
6819     break;
6820   case DBLQH:
6821     jam();
6822     block = dropTabPtr.p->m_coordinatorData.m_block = DBTC;
6823     break;
6824   case DBTC:
6825     jam();
6826     block = dropTabPtr.p->m_coordinatorData.m_block = DBDIH;
6827     break;
6828   case DBDIH:
6829     jam();
6830     prepDropTab_complete(signal, dropTabPtr);
6831     return;
6832   default:
6833     ndbrequire(false);
6834   }
6835 
6836   PrepDropTabReq * prep = (PrepDropTabReq*)signal->getDataPtrSend();
6837   prep->senderRef = reference();
6838   prep->senderData = dropTabPtr.p->key;
6839   prep->tableId = dropTabPtr.p->m_request.tableId;
6840   prep->requestType = dropTabPtr.p->m_requestType;
6841 
6842   dropTabPtr.p->m_coordinatorData.m_signalCounter = c_aliveNodes;
6843   NodeReceiverGroup rg(block, c_aliveNodes);
6844   sendSignal(rg, GSN_PREP_DROP_TAB_REQ, signal,
6845 	     PrepDropTabReq::SignalLength, JBB);
6846 
6847 #if 0
6848   for (Uint32 i = 1; i < MAX_NDB_NODES; i++){
6849     if(c_aliveNodes.get(i)){
6850       jam();
6851       BlockReference ref = numberToRef(block, i);
6852 
6853       dropTabPtr.p->m_coordinatorData.m_signalCounter.setWaitingFor(i);
6854     }
6855   }
6856 #endif
6857 }
6858 
6859 void
execPREP_DROP_TAB_CONF(Signal * signal)6860 Dbdict::execPREP_DROP_TAB_CONF(Signal * signal){
6861   jamEntry();
6862 
6863   PrepDropTabConf * prep = (PrepDropTabConf*)signal->getDataPtr();
6864 
6865   DropTableRecordPtr dropTabPtr;
6866   ndbrequire(c_opDropTable.find(dropTabPtr, prep->senderData));
6867 
6868   ndbrequire(dropTabPtr.p->m_coordinatorRef == reference());
6869   ndbrequire(dropTabPtr.p->m_request.tableId == prep->tableId);
6870   ndbrequire(dropTabPtr.p->m_coordinatorData.m_gsn == GSN_PREP_DROP_TAB_REQ);
6871 
6872   Uint32 nodeId = refToNode(prep->senderRef);
6873   dropTabPtr.p->m_coordinatorData.m_signalCounter.clearWaitingFor(nodeId);
6874 
6875   if(!dropTabPtr.p->m_coordinatorData.m_signalCounter.done()){
6876     jam();
6877     return;
6878   }
6879   prepDropTab_nextStep(signal, dropTabPtr);
6880 }
6881 
6882 void
execPREP_DROP_TAB_REF(Signal * signal)6883 Dbdict::execPREP_DROP_TAB_REF(Signal* signal){
6884   jamEntry();
6885 
6886   PrepDropTabRef * prep = (PrepDropTabRef*)signal->getDataPtr();
6887 
6888   DropTableRecordPtr dropTabPtr;
6889   ndbrequire(c_opDropTable.find(dropTabPtr, prep->senderData));
6890 
6891   ndbrequire(dropTabPtr.p->m_coordinatorRef == reference());
6892   ndbrequire(dropTabPtr.p->m_request.tableId == prep->tableId);
6893   ndbrequire(dropTabPtr.p->m_coordinatorData.m_gsn == GSN_PREP_DROP_TAB_REQ);
6894 
6895   Uint32 nodeId = refToNode(prep->senderRef);
6896   dropTabPtr.p->m_coordinatorData.m_signalCounter.clearWaitingFor(nodeId);
6897 
6898   Uint32 block = refToBlock(prep->senderRef);
6899   if((prep->errorCode == PrepDropTabRef::NoSuchTable && block == DBLQH) ||
6900      (prep->errorCode == PrepDropTabRef::NF_FakeErrorREF)){
6901     jam();
6902     /**
6903      * Ignore errors:
6904      * 1) no such table and LQH, it might not exists in different LQH's
6905      * 2) node failure...
6906      */
6907   } else {
6908     dropTabPtr.p->setErrorCode((Uint32)prep->errorCode);
6909   }
6910 
6911   if(!dropTabPtr.p->m_coordinatorData.m_signalCounter.done()){
6912     jam();
6913     return;
6914   }
6915   prepDropTab_nextStep(signal, dropTabPtr);
6916 }
6917 
6918 void
prepDropTab_complete(Signal * signal,DropTableRecordPtr dropTabPtr)6919 Dbdict::prepDropTab_complete(Signal* signal, DropTableRecordPtr dropTabPtr){
6920   jam();
6921 
6922   dropTabPtr.p->m_coordinatorData.m_gsn = GSN_DROP_TAB_REQ;
6923   dropTabPtr.p->m_coordinatorData.m_block = DBDICT;
6924 
6925   DropTabReq * req = (DropTabReq*)signal->getDataPtrSend();
6926   req->senderRef = reference();
6927   req->senderData = dropTabPtr.p->key;
6928   req->tableId = dropTabPtr.p->m_request.tableId;
6929   req->requestType = dropTabPtr.p->m_requestType;
6930 
6931   dropTabPtr.p->m_coordinatorData.m_signalCounter = c_aliveNodes;
6932   NodeReceiverGroup rg(DBDICT, c_aliveNodes);
6933   sendSignal(rg, GSN_DROP_TAB_REQ, signal,
6934 	     DropTabReq::SignalLength, JBB);
6935 }
6936 
6937 void
execDROP_TAB_REF(Signal * signal)6938 Dbdict::execDROP_TAB_REF(Signal* signal){
6939   jamEntry();
6940 
6941   DropTabRef * const req = (DropTabRef*)signal->getDataPtr();
6942 
6943   Uint32 block = refToBlock(req->senderRef);
6944   ndbrequire(req->errorCode == DropTabRef::NF_FakeErrorREF ||
6945 	     (req->errorCode == DropTabRef::NoSuchTable &&
6946 	      (block == DBTUP || block == DBACC || block == DBLQH)));
6947 
6948   if(block != DBDICT){
6949     jam();
6950     ndbrequire(refToNode(req->senderRef) == getOwnNodeId());
6951     dropTab_localDROP_TAB_CONF(signal);
6952     return;
6953   }
6954   ndbrequire(false);
6955 }
6956 
6957 void
execDROP_TAB_CONF(Signal * signal)6958 Dbdict::execDROP_TAB_CONF(Signal* signal){
6959   jamEntry();
6960 
6961   DropTabConf * const req = (DropTabConf*)signal->getDataPtr();
6962 
6963   if(refToBlock(req->senderRef) != DBDICT){
6964     jam();
6965     ndbrequire(refToNode(req->senderRef) == getOwnNodeId());
6966     dropTab_localDROP_TAB_CONF(signal);
6967     return;
6968   }
6969 
6970   DropTableRecordPtr dropTabPtr;
6971   ndbrequire(c_opDropTable.find(dropTabPtr, req->senderData));
6972 
6973   ndbrequire(dropTabPtr.p->m_coordinatorRef == reference());
6974   ndbrequire(dropTabPtr.p->m_request.tableId == req->tableId);
6975   ndbrequire(dropTabPtr.p->m_coordinatorData.m_gsn == GSN_DROP_TAB_REQ);
6976 
6977   Uint32 nodeId = refToNode(req->senderRef);
6978   dropTabPtr.p->m_coordinatorData.m_signalCounter.clearWaitingFor(nodeId);
6979 
6980   if(!dropTabPtr.p->m_coordinatorData.m_signalCounter.done()){
6981     jam();
6982     return;
6983   }
6984 
6985   DropTableConf* conf = (DropTableConf*)signal->getDataPtrSend();
6986   conf->senderRef = reference();
6987   conf->senderData = dropTabPtr.p->m_request.senderData;
6988   conf->tableId = dropTabPtr.p->m_request.tableId;
6989   conf->tableVersion = dropTabPtr.p->m_request.tableVersion;
6990   Uint32 ref = dropTabPtr.p->m_request.senderRef;
6991   sendSignal(ref, GSN_DROP_TABLE_CONF, signal,
6992 	     DropTableConf::SignalLength, JBB);
6993 
6994   c_opDropTable.release(dropTabPtr);
6995   c_blockState = BS_IDLE;
6996 }
6997 
6998 /**
6999  * DROP TABLE PARTICIPANT CODE
7000  */
7001 void
execPREP_DROP_TAB_REQ(Signal * signal)7002 Dbdict::execPREP_DROP_TAB_REQ(Signal* signal){
7003   jamEntry();
7004   PrepDropTabReq * prep = (PrepDropTabReq*)signal->getDataPtrSend();
7005 
7006   DropTableRecordPtr dropTabPtr;
7007   if(prep->senderRef == reference()){
7008     jam();
7009     ndbrequire(c_opDropTable.find(dropTabPtr, prep->senderData));
7010     ndbrequire(dropTabPtr.p->m_requestType == prep->requestType);
7011   } else {
7012     jam();
7013     c_opDropTable.seize(dropTabPtr);
7014     if(!dropTabPtr.isNull()){
7015       dropTabPtr.p->key = prep->senderData;
7016       c_opDropTable.add(dropTabPtr);
7017     }
7018   }
7019 
7020   ndbrequire(!dropTabPtr.isNull());
7021 
7022   dropTabPtr.p->m_errorCode = 0;
7023   dropTabPtr.p->m_request.tableId = prep->tableId;
7024   dropTabPtr.p->m_requestType = prep->requestType;
7025   dropTabPtr.p->m_coordinatorRef = prep->senderRef;
7026   dropTabPtr.p->m_participantData.m_gsn = GSN_PREP_DROP_TAB_REQ;
7027 
7028   TableRecordPtr tablePtr;
7029   c_tableRecordPool.getPtr(tablePtr, prep->tableId);
7030   tablePtr.p->tabState = TableRecord::PREPARE_DROPPING;
7031 
7032   /**
7033    * Modify schema
7034    */
7035   XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
7036   SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, tablePtr.i);
7037   SchemaFile::TableState tabState =
7038     (SchemaFile::TableState)tableEntry->m_tableState;
7039   ndbrequire(tabState == SchemaFile::TABLE_ADD_COMMITTED ||
7040              tabState == SchemaFile::ALTER_TABLE_COMMITTED ||
7041              tabState == SchemaFile::TEMPORARY_TABLE_COMMITTED);
7042   tableEntry->m_tableState   = SchemaFile::DROP_TABLE_STARTED;
7043   computeChecksum(xsf, tablePtr.i / NDB_SF_PAGE_ENTRIES);
7044 
7045   bool savetodisk = !(tablePtr.p->m_bits & TableRecord::TR_Temporary);
7046   Callback callback;
7047   callback.m_callbackData = dropTabPtr.p->key;
7048   callback.m_callbackFunction = safe_cast(&Dbdict::prepDropTab_writeSchemaConf);
7049   if (savetodisk)
7050   {
7051     ndbrequire(c_writeSchemaRecord.inUse == false);
7052     c_writeSchemaRecord.inUse = true;
7053 
7054     c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
7055     c_writeSchemaRecord.newFile = false;
7056     c_writeSchemaRecord.firstPage = tablePtr.i / NDB_SF_PAGE_ENTRIES;
7057     c_writeSchemaRecord.noOfPages = 1;
7058     c_writeSchemaRecord.m_callback = callback;
7059     startWriteSchemaFile(signal);
7060   }
7061   else
7062   {
7063     execute(signal, callback, 0);
7064   }
7065 }
7066 
7067 void
prepDropTab_writeSchemaConf(Signal * signal,Uint32 dropTabPtrI,Uint32 returnCode)7068 Dbdict::prepDropTab_writeSchemaConf(Signal* signal,
7069 				    Uint32 dropTabPtrI,
7070 				    Uint32 returnCode){
7071   jam();
7072 
7073   DropTableRecordPtr dropTabPtr;
7074   ndbrequire(c_opDropTable.find(dropTabPtr, dropTabPtrI));
7075 
7076   ndbrequire(dropTabPtr.p->m_participantData.m_gsn == GSN_PREP_DROP_TAB_REQ);
7077 
7078   /**
7079    * There probably should be node fail handlign here
7080    *
7081    * To check that coordinator hasn't died
7082    */
7083 
7084   PrepDropTabConf * prep = (PrepDropTabConf*)signal->getDataPtr();
7085   prep->senderRef = reference();
7086   prep->senderData = dropTabPtrI;
7087   prep->tableId = dropTabPtr.p->m_request.tableId;
7088 
7089   dropTabPtr.p->m_participantData.m_gsn = GSN_PREP_DROP_TAB_CONF;
7090   sendSignal(dropTabPtr.p->m_coordinatorRef, GSN_PREP_DROP_TAB_CONF, signal,
7091 	     PrepDropTabConf::SignalLength, JBB);
7092 }
7093 
7094 void
execDROP_TAB_REQ(Signal * signal)7095 Dbdict::execDROP_TAB_REQ(Signal* signal){
7096   jamEntry();
7097   DropTabReq * req = (DropTabReq*)signal->getDataPtrSend();
7098 
7099   DropTableRecordPtr dropTabPtr;
7100   ndbrequire(c_opDropTable.find(dropTabPtr, req->senderData));
7101 
7102   ndbrequire(dropTabPtr.p->m_participantData.m_gsn == GSN_PREP_DROP_TAB_CONF);
7103   dropTabPtr.p->m_participantData.m_gsn = GSN_DROP_TAB_REQ;
7104 
7105   ndbrequire(dropTabPtr.p->m_requestType == req->requestType);
7106 
7107   TableRecordPtr tablePtr;
7108   c_tableRecordPool.getPtr(tablePtr, dropTabPtr.p->m_request.tableId);
7109   tablePtr.p->tabState = TableRecord::DROPPING;
7110 
7111   dropTabPtr.p->m_participantData.m_block = 0;
7112   dropTabPtr.p->m_participantData.m_callback.m_callbackData = dropTabPtr.p->key;
7113   dropTabPtr.p->m_participantData.m_callback.m_callbackFunction =
7114     safe_cast(&Dbdict::dropTab_complete);
7115   dropTab_nextStep(signal, dropTabPtr);
7116 
7117   if (tablePtr.p->m_tablespace_id != RNIL)
7118   {
7119     FilegroupPtr ptr;
7120     ndbrequire(c_filegroup_hash.find(ptr, tablePtr.p->m_tablespace_id));
7121     decrease_ref_count(ptr.p->m_obj_ptr_i);
7122   }
7123 }
7124 
7125 #include <DebuggerNames.hpp>
7126 
7127 void
dropTab_nextStep(Signal * signal,DropTableRecordPtr dropTabPtr)7128 Dbdict::dropTab_nextStep(Signal* signal, DropTableRecordPtr dropTabPtr){
7129 
7130   /**
7131    * No errors currently allowed
7132    */
7133   ndbrequire(dropTabPtr.p->m_errorCode == 0);
7134 
7135   TableRecordPtr tablePtr;
7136   c_tableRecordPool.getPtr(tablePtr, dropTabPtr.p->m_request.tableId);
7137 
7138   Uint32 block = 0;
7139   switch(dropTabPtr.p->m_participantData.m_block){
7140   case 0:
7141     jam();
7142     block = DBTC;
7143     break;
7144   case DBTC:
7145     jam();
7146     if (tablePtr.p->isTable() || tablePtr.p->isHashIndex())
7147       block = DBACC;
7148     if (tablePtr.p->isOrderedIndex())
7149       block = DBTUP;
7150     break;
7151   case DBACC:
7152     jam();
7153     block = DBTUP;
7154     break;
7155   case DBTUP:
7156     jam();
7157     if (tablePtr.p->isTable() || tablePtr.p->isHashIndex())
7158       block = DBLQH;
7159     if (tablePtr.p->isOrderedIndex())
7160       block = DBTUX;
7161     break;
7162   case DBTUX:
7163     jam();
7164     block = DBLQH;
7165     break;
7166   case DBLQH:
7167     jam();
7168     block = DBDIH;
7169     break;
7170   case DBDIH:
7171     jam();
7172     execute(signal, dropTabPtr.p->m_participantData.m_callback, 0);
7173     return;
7174   }
7175   ndbrequire(block != 0);
7176   dropTabPtr.p->m_participantData.m_block = block;
7177 
7178   DropTabReq * req = (DropTabReq*)signal->getDataPtrSend();
7179   req->senderRef = reference();
7180   req->senderData = dropTabPtr.p->key;
7181   req->tableId = dropTabPtr.p->m_request.tableId;
7182   req->requestType = dropTabPtr.p->m_requestType;
7183 
7184   const Uint32 nodeId = getOwnNodeId();
7185   dropTabPtr.p->m_participantData.m_signalCounter.clearWaitingFor();
7186   dropTabPtr.p->m_participantData.m_signalCounter.setWaitingFor(nodeId);
7187   BlockReference ref = numberToRef(block, 0);
7188   sendSignal(ref, GSN_DROP_TAB_REQ, signal, DropTabReq::SignalLength, JBB);
7189 }
7190 
7191 void
dropTab_localDROP_TAB_CONF(Signal * signal)7192 Dbdict::dropTab_localDROP_TAB_CONF(Signal* signal){
7193   jamEntry();
7194 
7195   DropTabConf * conf = (DropTabConf*)signal->getDataPtr();
7196 
7197   DropTableRecordPtr dropTabPtr;
7198   ndbrequire(c_opDropTable.find(dropTabPtr, conf->senderData));
7199 
7200   ndbrequire(dropTabPtr.p->m_request.tableId == conf->tableId);
7201   ndbrequire(dropTabPtr.p->m_participantData.m_gsn == GSN_DROP_TAB_REQ);
7202 
7203   Uint32 nodeId = refToNode(conf->senderRef);
7204   dropTabPtr.p->m_participantData.m_signalCounter.clearWaitingFor(nodeId);
7205 
7206   if(!dropTabPtr.p->m_participantData.m_signalCounter.done()){
7207     jam();
7208     ndbrequire(false);
7209     return;
7210   }
7211   dropTab_nextStep(signal, dropTabPtr);
7212 }
7213 
7214 void
dropTab_complete(Signal * signal,Uint32 dropTabPtrI,Uint32 returnCode)7215 Dbdict::dropTab_complete(Signal* signal,
7216 			 Uint32 dropTabPtrI,
7217 			 Uint32 returnCode){
7218   jam();
7219 
7220   DropTableRecordPtr dropTabPtr;
7221   ndbrequire(c_opDropTable.find(dropTabPtr, dropTabPtrI));
7222 
7223   Uint32 tableId = dropTabPtr.p->m_request.tableId;
7224 
7225   /**
7226    * Write to schema file
7227    */
7228   XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
7229   SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, tableId);
7230   SchemaFile::TableState tabState =
7231     (SchemaFile::TableState)tableEntry->m_tableState;
7232   ndbrequire(tabState == SchemaFile::DROP_TABLE_STARTED);
7233   tableEntry->m_tableState = SchemaFile::DROP_TABLE_COMMITTED;
7234   computeChecksum(xsf, tableId / NDB_SF_PAGE_ENTRIES);
7235 
7236   TableRecordPtr tablePtr;
7237   c_tableRecordPool.getPtr(tablePtr, tableId);
7238   bool savetodisk = !(tablePtr.p->m_bits & TableRecord::TR_Temporary);
7239   Callback callback;
7240   callback.m_callbackData = dropTabPtr.p->key;
7241   callback.m_callbackFunction = safe_cast(&Dbdict::dropTab_writeSchemaConf);
7242   if (savetodisk)
7243   {
7244     ndbrequire(c_writeSchemaRecord.inUse == false);
7245     c_writeSchemaRecord.inUse = true;
7246 
7247     c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
7248     c_writeSchemaRecord.firstPage = tableId / NDB_SF_PAGE_ENTRIES;
7249     c_writeSchemaRecord.noOfPages = 1;
7250     c_writeSchemaRecord.m_callback = callback;
7251     startWriteSchemaFile(signal);
7252   }
7253   else
7254   {
7255     execute(signal, callback, 0);
7256   }
7257 }
7258 
7259 void
dropTab_writeSchemaConf(Signal * signal,Uint32 dropTabPtrI,Uint32 returnCode)7260 Dbdict::dropTab_writeSchemaConf(Signal* signal,
7261 				Uint32 dropTabPtrI,
7262 				Uint32 returnCode){
7263   jam();
7264 
7265   DropTableRecordPtr dropTabPtr;
7266   ndbrequire(c_opDropTable.find(dropTabPtr, dropTabPtrI));
7267 
7268   ndbrequire(dropTabPtr.p->m_participantData.m_gsn == GSN_DROP_TAB_REQ);
7269 
7270   dropTabPtr.p->m_participantData.m_gsn = GSN_DROP_TAB_CONF;
7271 
7272   releaseTableObject(dropTabPtr.p->m_request.tableId);
7273 
7274   DropTabConf * conf = (DropTabConf*)signal->getDataPtr();
7275   conf->senderRef = reference();
7276   conf->senderData = dropTabPtrI;
7277   conf->tableId = dropTabPtr.p->m_request.tableId;
7278   {
7279     DropTabConf tmp= *conf;
7280     if (dropTabPtr.p->m_coordinatorRef == reference())
7281       conf->senderRef = dropTabPtr.p->m_request.senderRef;
7282     else
7283       conf->senderRef = 0;
7284     EXECUTE_DIRECT(SUMA, GSN_DROP_TAB_CONF, signal,
7285 		   DropTabConf::SignalLength);
7286     jamEntry();
7287     *conf= tmp;
7288   }
7289   dropTabPtr.p->m_participantData.m_gsn = GSN_DROP_TAB_CONF;
7290   sendSignal(dropTabPtr.p->m_coordinatorRef, GSN_DROP_TAB_CONF, signal,
7291 	     DropTabConf::SignalLength, JBB);
7292 
7293   if(dropTabPtr.p->m_coordinatorRef != reference()){
7294     c_opDropTable.release(dropTabPtr);
7295   }
7296 }
7297 
releaseTableObject(Uint32 tableId,bool removeFromHash)7298 void Dbdict::releaseTableObject(Uint32 tableId, bool removeFromHash)
7299 {
7300   TableRecordPtr tablePtr;
7301   c_tableRecordPool.getPtr(tablePtr, tableId);
7302   if (removeFromHash)
7303   {
7304     jam();
7305     release_object(tablePtr.p->m_obj_ptr_i);
7306   }
7307   else
7308   {
7309     Rope tmp(c_rope_pool, tablePtr.p->tableName);
7310     tmp.erase();
7311   }
7312 
7313   {
7314     Rope tmp(c_rope_pool, tablePtr.p->frmData);
7315     tmp.erase();
7316   }
7317 
7318   {
7319     Rope tmp(c_rope_pool, tablePtr.p->tsData);
7320     tmp.erase();
7321   }
7322 
7323   {
7324     Rope tmp(c_rope_pool, tablePtr.p->ngData);
7325     tmp.erase();
7326   }
7327 
7328   {
7329     Rope tmp(c_rope_pool, tablePtr.p->rangeData);
7330     tmp.erase();
7331   }
7332 
7333   tablePtr.p->tabState = TableRecord::NOT_DEFINED;
7334 
7335   LocalDLFifoList<AttributeRecord> list(c_attributeRecordPool,
7336 					tablePtr.p->m_attributes);
7337   AttributeRecordPtr attrPtr;
7338   for(list.first(attrPtr); !attrPtr.isNull(); list.next(attrPtr)){
7339     Rope name(c_rope_pool, attrPtr.p->attributeName);
7340     Rope def(c_rope_pool, attrPtr.p->defaultValue);
7341     name.erase();
7342     def.erase();
7343   }
7344   list.release();
7345 }//releaseTableObject()
7346 
7347 /**
7348  * DICT receives these on index create and drop.
7349  */
execDROP_TABLE_CONF(Signal * signal)7350 void Dbdict::execDROP_TABLE_CONF(Signal* signal)
7351 {
7352   jamEntry();
7353   ndbrequire(signal->getNoOfSections() == 0);
7354 
7355   DropTableConf * const conf = (DropTableConf *)signal->getDataPtr();
7356   // assume part of drop index operation
7357   OpDropIndexPtr opPtr;
7358   c_opDropIndex.find(opPtr, conf->senderData);
7359   ndbrequire(! opPtr.isNull());
7360   ndbrequire(opPtr.p->m_request.getIndexId() == conf->tableId);
7361   ndbrequire(opPtr.p->m_request.getIndexVersion() == conf->tableVersion);
7362   dropIndex_fromDropTable(signal, opPtr);
7363 }
7364 
execDROP_TABLE_REF(Signal * signal)7365 void Dbdict::execDROP_TABLE_REF(Signal* signal)
7366 {
7367   jamEntry();
7368 
7369   DropTableRef * const ref = (DropTableRef *)signal->getDataPtr();
7370   // assume part of drop index operation
7371   OpDropIndexPtr opPtr;
7372   c_opDropIndex.find(opPtr, ref->senderData);
7373   ndbrequire(! opPtr.isNull());
7374   opPtr.p->setError(ref);
7375   opPtr.p->m_errorLine = __LINE__;
7376   dropIndex_fromDropTable(signal, opPtr);
7377 }
7378 
7379 /* **************************************************************** */
7380 /* ---------------------------------------------------------------- */
7381 /* MODULE:          EXTERNAL INTERFACE TO DATA -------------------- */
7382 /* ---------------------------------------------------------------- */
7383 /*                                                                  */
7384 /* This module contains the code that is used by other modules to.  */
7385 /* access the data within DBDICT.                                   */
7386 /* ---------------------------------------------------------------- */
7387 /* **************************************************************** */
7388 
execGET_TABLEDID_REQ(Signal * signal)7389 void Dbdict::execGET_TABLEDID_REQ(Signal * signal)
7390 {
7391   jamEntry();
7392   ndbrequire(signal->getNoOfSections() == 1);
7393   GetTableIdReq const * req = (GetTableIdReq *)signal->getDataPtr();
7394   Uint32 senderData = req->senderData;
7395   Uint32 senderRef = req->senderRef;
7396   Uint32 len = req->len;
7397 
7398   if(len>MAX_TAB_NAME_SIZE)
7399   {
7400     jam();
7401     sendGET_TABLEID_REF((Signal*)signal,
7402 			(GetTableIdReq *)req,
7403 			GetTableIdRef::TableNameTooLong);
7404     return;
7405   }
7406 
7407   char tableName[MAX_TAB_NAME_SIZE];
7408   SegmentedSectionPtr ssPtr;
7409   signal->getSection(ssPtr,GetTableIdReq::TABLE_NAME);
7410   copy((Uint32*)tableName, ssPtr);
7411   releaseSections(signal);
7412 
7413   DictObject * obj_ptr_p = get_object(tableName, len);
7414   if(obj_ptr_p == 0 || !DictTabInfo::isTable(obj_ptr_p->m_type)){
7415     jam();
7416     sendGET_TABLEID_REF(signal,
7417 			(GetTableIdReq *)req,
7418 			GetTableIdRef::TableNotDefined);
7419     return;
7420   }
7421 
7422   TableRecordPtr tablePtr;
7423   c_tableRecordPool.getPtr(tablePtr, obj_ptr_p->m_id);
7424 
7425   GetTableIdConf * conf = (GetTableIdConf *)req;
7426   conf->tableId = tablePtr.p->tableId;
7427   conf->schemaVersion = tablePtr.p->tableVersion;
7428   conf->senderData = senderData;
7429   sendSignal(senderRef, GSN_GET_TABLEID_CONF, signal,
7430 	     GetTableIdConf::SignalLength, JBB);
7431 }
7432 
7433 
sendGET_TABLEID_REF(Signal * signal,GetTableIdReq * req,GetTableIdRef::ErrorCode errorCode)7434 void Dbdict::sendGET_TABLEID_REF(Signal* signal,
7435 				 GetTableIdReq * req,
7436 				 GetTableIdRef::ErrorCode errorCode)
7437 {
7438   GetTableIdRef * const ref = (GetTableIdRef *)req;
7439   /**
7440    * The format of GetTabInfo Req/Ref is the same
7441    */
7442   BlockReference retRef = req->senderRef;
7443   ref->err = errorCode;
7444   sendSignal(retRef, GSN_GET_TABLEID_REF, signal,
7445 	     GetTableIdRef::SignalLength, JBB);
7446 }//sendGET_TABINFOREF()
7447 
7448 /* ---------------------------------------------------------------- */
7449 // Get a full table description.
7450 /* ---------------------------------------------------------------- */
execGET_TABINFOREQ(Signal * signal)7451 void Dbdict::execGET_TABINFOREQ(Signal* signal)
7452 {
7453   jamEntry();
7454   if(!assembleFragments(signal))
7455   {
7456     return;
7457   }
7458 
7459   GetTabInfoReq * const req = (GetTabInfoReq *)&signal->theData[0];
7460 
7461   /**
7462    * If I get a GET_TABINFO_REQ from myself
7463    * it's is a one from the time queue
7464    */
7465   bool fromTimeQueue = (signal->senderBlockRef() == reference());
7466 
7467   if (c_retrieveRecord.busyState && fromTimeQueue == true) {
7468     jam();
7469 
7470     sendSignalWithDelay(reference(), GSN_GET_TABINFOREQ, signal, 30,
7471 			signal->length());
7472     return;
7473   }//if
7474 
7475   const Uint32 MAX_WAITERS = 5;
7476 
7477   if(c_retrieveRecord.busyState && fromTimeQueue == false){
7478     jam();
7479     if(c_retrieveRecord.noOfWaiters < MAX_WAITERS){
7480       jam();
7481       c_retrieveRecord.noOfWaiters++;
7482 
7483       sendSignalWithDelay(reference(), GSN_GET_TABINFOREQ, signal, 30,
7484 			  signal->length());
7485       return;
7486     }
7487 
7488     sendGET_TABINFOREF(signal, req, GetTabInfoRef::Busy);
7489     return;
7490   }
7491 
7492   if(fromTimeQueue){
7493     jam();
7494     c_retrieveRecord.noOfWaiters--;
7495   }
7496 
7497   const bool useLongSig = (req->requestType & GetTabInfoReq::LongSignalConf);
7498   const Uint32 reqType = req->requestType & (~GetTabInfoReq::LongSignalConf);
7499 
7500   Uint32 obj_id = RNIL;
7501   if(reqType == GetTabInfoReq::RequestByName){
7502     jam();
7503     ndbrequire(signal->getNoOfSections() == 1);
7504     const Uint32 len = req->tableNameLen;
7505 
7506     if(len > MAX_TAB_NAME_SIZE){
7507       jam();
7508       releaseSections(signal);
7509       sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNameTooLong);
7510       return;
7511     }
7512 
7513     char tableName[MAX_TAB_NAME_SIZE];
7514     SegmentedSectionPtr ssPtr;
7515     signal->getSection(ssPtr,GetTabInfoReq::TABLE_NAME);
7516     SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
7517     r0.reset(); // undo implicit first()
7518     if(!r0.getWords((Uint32*)tableName, (len+3)/4)){
7519       jam();
7520       releaseSections(signal);
7521       sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNotDefined);
7522       return;
7523     }
7524     releaseSections(signal);
7525 
7526     DictObject * old_ptr_p = get_object(tableName, len);
7527     if(old_ptr_p)
7528       obj_id = old_ptr_p->m_id;
7529   } else {
7530     jam();
7531     obj_id = req->tableId;
7532   }
7533 
7534   SchemaFile::TableEntry *objEntry = 0;
7535   if(obj_id != RNIL){
7536     XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
7537     objEntry = getTableEntry(xsf, obj_id);
7538   }
7539 
7540   // The table seached for was not found
7541   if(objEntry == 0){
7542     jam();
7543     sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNotDefined);
7544     return;
7545   }//if
7546 
7547   // If istable/index, allow ADD_STARTED (not to ref)
7548 
7549   if (objEntry->m_tableState != SchemaFile::TABLE_ADD_COMMITTED &&
7550       objEntry->m_tableState != SchemaFile::ALTER_TABLE_COMMITTED &&
7551       objEntry->m_tableState != SchemaFile::TEMPORARY_TABLE_COMMITTED){
7552     jam();
7553     sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNotDefined);
7554     return;
7555   }//if
7556 
7557   if (DictTabInfo::isTable(objEntry->m_tableType) ||
7558       DictTabInfo::isIndex(objEntry->m_tableType))
7559   {
7560     jam();
7561     TableRecordPtr tabPtr;
7562     c_tableRecordPool.getPtr(tabPtr, obj_id);
7563     if (tabPtr.p->tabState != TableRecord::DEFINED &&
7564 	tabPtr.p->tabState != TableRecord::BACKUP_ONGOING)
7565     {
7566       jam();
7567       sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNotDefined);
7568       return;
7569     }
7570     ndbrequire(objEntry->m_tableState == SchemaFile::TEMPORARY_TABLE_COMMITTED ||
7571                !(tabPtr.p->m_bits & TableRecord::TR_Temporary));
7572   }
7573 
7574   c_retrieveRecord.busyState = true;
7575   c_retrieveRecord.blockRef = req->senderRef;
7576   c_retrieveRecord.m_senderData = req->senderData;
7577   c_retrieveRecord.tableId = obj_id;
7578   c_retrieveRecord.currentSent = 0;
7579   c_retrieveRecord.m_useLongSig = useLongSig;
7580   c_retrieveRecord.m_table_type = objEntry->m_tableType;
7581   c_packTable.m_state = PackTable::PTS_GET_TAB;
7582 
7583   if(objEntry->m_tableType==DictTabInfo::Datafile)
7584   {
7585     jam();
7586     GetTabInfoReq *req= (GetTabInfoReq*)signal->getDataPtrSend();
7587     req->senderData= c_retrieveRecord.retrievePage;
7588     req->senderRef= reference();
7589     req->requestType= GetTabInfoReq::RequestById;
7590     req->tableId= obj_id;
7591 
7592     sendSignal(TSMAN_REF, GSN_GET_TABINFOREQ, signal,
7593 	       GetTabInfoReq::SignalLength, JBB);
7594   }
7595   else if(objEntry->m_tableType==DictTabInfo::LogfileGroup)
7596   {
7597     jam();
7598     GetTabInfoReq *req= (GetTabInfoReq*)signal->getDataPtrSend();
7599     req->senderData= c_retrieveRecord.retrievePage;
7600     req->senderRef= reference();
7601     req->requestType= GetTabInfoReq::RequestById;
7602     req->tableId= obj_id;
7603 
7604     sendSignal(LGMAN_REF, GSN_GET_TABINFOREQ, signal,
7605 	       GetTabInfoReq::SignalLength, JBB);
7606   }
7607   else
7608   {
7609     jam();
7610     signal->theData[0] = ZPACK_TABLE_INTO_PAGES;
7611     signal->theData[1] = obj_id;
7612     signal->theData[2] = objEntry->m_tableType;
7613     signal->theData[3] = c_retrieveRecord.retrievePage;
7614     sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
7615   }
7616   jam();
7617 }//execGET_TABINFOREQ()
7618 
sendGetTabResponse(Signal * signal)7619 void Dbdict::sendGetTabResponse(Signal* signal)
7620 {
7621   PageRecordPtr pagePtr;
7622   DictTabInfo * const conf = (DictTabInfo *)&signal->theData[0];
7623   conf->senderRef   = reference();
7624   conf->senderData  = c_retrieveRecord.m_senderData;
7625   conf->requestType = DictTabInfo::GetTabInfoConf;
7626   conf->totalLen    = c_retrieveRecord.retrievedNoOfWords;
7627 
7628   c_pageRecordArray.getPtr(pagePtr, c_retrieveRecord.retrievePage);
7629   Uint32* pagePointer = (Uint32*)&pagePtr.p->word[0] + ZPAGE_HEADER_SIZE;
7630 
7631   if(c_retrieveRecord.m_useLongSig){
7632     jam();
7633     GetTabInfoConf* conf = (GetTabInfoConf*)signal->getDataPtr();
7634     conf->gci = 0;
7635     conf->tableId = c_retrieveRecord.tableId;
7636     conf->senderData = c_retrieveRecord.m_senderData;
7637     conf->totalLen = c_retrieveRecord.retrievedNoOfWords;
7638     conf->tableType = c_retrieveRecord.m_table_type;
7639 
7640     Callback c = { safe_cast(&Dbdict::initRetrieveRecord), 0 };
7641     LinearSectionPtr ptr[3];
7642     ptr[0].p = pagePointer;
7643     ptr[0].sz = c_retrieveRecord.retrievedNoOfWords;
7644     sendFragmentedSignal(c_retrieveRecord.blockRef,
7645 			 GSN_GET_TABINFO_CONF,
7646 			 signal,
7647 			 GetTabInfoConf::SignalLength,
7648 			 JBB,
7649 			 ptr,
7650 			 1,
7651 			 c);
7652     return;
7653   }
7654 
7655   ndbrequire(false);
7656 }//sendGetTabResponse()
7657 
sendGET_TABINFOREF(Signal * signal,GetTabInfoReq * req,GetTabInfoRef::ErrorCode errorCode)7658 void Dbdict::sendGET_TABINFOREF(Signal* signal,
7659 				GetTabInfoReq * req,
7660 				GetTabInfoRef::ErrorCode errorCode)
7661 {
7662   jamEntry();
7663   GetTabInfoRef * const ref = (GetTabInfoRef *)&signal->theData[0];
7664   /**
7665    * The format of GetTabInfo Req/Ref is the same
7666    */
7667   BlockReference retRef = req->senderRef;
7668   ref->errorCode = errorCode;
7669 
7670   sendSignal(retRef, GSN_GET_TABINFOREF, signal, signal->length(), JBB);
7671 }//sendGET_TABINFOREF()
7672 
7673 void
execLIST_TABLES_REQ(Signal * signal)7674 Dbdict::execLIST_TABLES_REQ(Signal* signal)
7675 {
7676   jamEntry();
7677   ListTablesReq * req = (ListTablesReq*)signal->getDataPtr();
7678   Uint32 senderRef  = req->senderRef;
7679   Uint32 senderData = req->senderData;
7680   // save req flags
7681   const Uint32 reqTableId = req->getTableId();
7682   const Uint32 reqTableType = req->getTableType();
7683   const bool reqListNames = req->getListNames();
7684   const bool reqListIndexes = req->getListIndexes();
7685   // init the confs
7686   ListTablesConf * conf = (ListTablesConf *)signal->getDataPtrSend();
7687   conf->senderData = senderData;
7688   conf->counter = 0;
7689   Uint32 pos = 0;
7690 
7691   DLHashTable<DictObject>::Iterator iter;
7692   bool ok = c_obj_hash.first(iter);
7693   for(; ok; ok = c_obj_hash.next(iter)){
7694     Uint32 type = iter.curr.p->m_type;
7695     if ((reqTableType != (Uint32)0) && (reqTableType != type))
7696       continue;
7697 
7698     if (reqListIndexes && !DictTabInfo::isIndex(type))
7699       continue;
7700 
7701     TableRecordPtr tablePtr;
7702     if (DictTabInfo::isTable(type) || DictTabInfo::isIndex(type)){
7703       c_tableRecordPool.getPtr(tablePtr, iter.curr.p->m_id);
7704 
7705       if(reqListIndexes && (reqTableId != tablePtr.p->primaryTableId))
7706 	continue;
7707 
7708       conf->tableData[pos] = 0;
7709       conf->setTableId(pos, tablePtr.i); // id
7710       conf->setTableType(pos, type); // type
7711       // state
7712 
7713       if(DictTabInfo::isTable(type)){
7714 	switch (tablePtr.p->tabState) {
7715 	case TableRecord::DEFINING:
7716 	  conf->setTableState(pos, DictTabInfo::StateBuilding);
7717 	  break;
7718 	case TableRecord::PREPARE_DROPPING:
7719 	case TableRecord::DROPPING:
7720 	  conf->setTableState(pos, DictTabInfo::StateDropping);
7721 	  break;
7722 	case TableRecord::DEFINED:
7723 	  conf->setTableState(pos, DictTabInfo::StateOnline);
7724 	  break;
7725 	case TableRecord::BACKUP_ONGOING:
7726 	  conf->setTableState(pos, DictTabInfo::StateBackup);
7727 	  break;
7728 	default:
7729 	  conf->setTableState(pos, DictTabInfo::StateBroken);
7730 	  break;
7731 	}
7732       }
7733       if (tablePtr.p->isIndex()) {
7734 	switch (tablePtr.p->indexState) {
7735 	case TableRecord::IS_OFFLINE:
7736 	  conf->setTableState(pos, DictTabInfo::StateOffline);
7737 	  break;
7738 	case TableRecord::IS_BUILDING:
7739 	  conf->setTableState(pos, DictTabInfo::StateBuilding);
7740 	  break;
7741 	case TableRecord::IS_DROPPING:
7742 	  conf->setTableState(pos, DictTabInfo::StateDropping);
7743 	  break;
7744 	case TableRecord::IS_ONLINE:
7745 	  conf->setTableState(pos, DictTabInfo::StateOnline);
7746 	  break;
7747 	default:
7748 	  conf->setTableState(pos, DictTabInfo::StateBroken);
7749 	  break;
7750 	}
7751       }
7752       // Logging status
7753       if (! (tablePtr.p->m_bits & TableRecord::TR_Logged)) {
7754 	conf->setTableStore(pos, DictTabInfo::StoreNotLogged);
7755       } else {
7756 	conf->setTableStore(pos, DictTabInfo::StorePermanent);
7757       }
7758       // Temporary status
7759       if (tablePtr.p->m_bits & TableRecord::TR_Temporary) {
7760 	conf->setTableTemp(pos, NDB_TEMP_TAB_TEMPORARY);
7761       } else {
7762 	conf->setTableTemp(pos, NDB_TEMP_TAB_PERMANENT);
7763       }
7764       pos++;
7765     }
7766     if(DictTabInfo::isTrigger(type)){
7767       TriggerRecordPtr triggerPtr;
7768       c_triggerRecordPool.getPtr(triggerPtr, iter.curr.p->m_id);
7769 
7770       conf->tableData[pos] = 0;
7771       conf->setTableId(pos, triggerPtr.i);
7772       conf->setTableType(pos, type);
7773       switch (triggerPtr.p->triggerState) {
7774       case TriggerRecord::TS_OFFLINE:
7775 	conf->setTableState(pos, DictTabInfo::StateOffline);
7776 	break;
7777       case TriggerRecord::TS_ONLINE:
7778 	conf->setTableState(pos, DictTabInfo::StateOnline);
7779 	break;
7780       default:
7781 	conf->setTableState(pos, DictTabInfo::StateBroken);
7782 	break;
7783       }
7784       conf->setTableStore(pos, DictTabInfo::StoreNotLogged);
7785       pos++;
7786     }
7787     if (DictTabInfo::isFilegroup(type)){
7788       jam();
7789       conf->tableData[pos] = 0;
7790       conf->setTableId(pos, iter.curr.p->m_id);
7791       conf->setTableType(pos, type); // type
7792       conf->setTableState(pos, DictTabInfo::StateOnline);  // XXX todo
7793       pos++;
7794     }
7795     if (DictTabInfo::isFile(type)){
7796       jam();
7797       conf->tableData[pos] = 0;
7798       conf->setTableId(pos, iter.curr.p->m_id);
7799       conf->setTableType(pos, type); // type
7800       conf->setTableState(pos, DictTabInfo::StateOnline); // XXX todo
7801       pos++;
7802     }
7803 
7804     if (pos >= ListTablesConf::DataLength) {
7805       sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
7806 		 ListTablesConf::SignalLength, JBB);
7807       conf->counter++;
7808       pos = 0;
7809     }
7810 
7811     if (! reqListNames)
7812       continue;
7813 
7814     Rope name(c_rope_pool, iter.curr.p->m_name);
7815     const Uint32 size = name.size();
7816     conf->tableData[pos] = size;
7817     pos++;
7818     if (pos >= ListTablesConf::DataLength) {
7819       sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
7820 		 ListTablesConf::SignalLength, JBB);
7821       conf->counter++;
7822       pos = 0;
7823     }
7824     Uint32 i = 0;
7825     char tmp[MAX_TAB_NAME_SIZE];
7826     name.copy(tmp);
7827     while (i < size) {
7828       char* p = (char*)&conf->tableData[pos];
7829       for (Uint32 j = 0; j < 4; j++) {
7830 	if (i < size)
7831 	  *p++ = tmp[i++];
7832 	else
7833 	  *p++ = 0;
7834       }
7835       pos++;
7836       if (pos >= ListTablesConf::DataLength) {
7837 	sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
7838 		   ListTablesConf::SignalLength, JBB);
7839 	conf->counter++;
7840 	pos = 0;
7841       }
7842     }
7843   }
7844   // last signal must have less than max length
7845   sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
7846 	     ListTablesConf::HeaderLength + pos, JBB);
7847 }
7848 
7849 /**
7850  * MODULE: Create index
7851  *
7852  * Create index in DICT via create table operation.  Then invoke alter
7853  * index opearation to online the index.
7854  *
7855  * Request type in CREATE_INDX signals:
7856  *
7857  * RT_USER - from API to DICT master
7858  * RT_DICT_PREPARE - prepare participants
7859  * RT_DICT_COMMIT - commit participants
7860  * RT_TC - create index in TC (part of alter index operation)
7861  */
7862 
7863 void
execCREATE_INDX_REQ(Signal * signal)7864 Dbdict::execCREATE_INDX_REQ(Signal* signal)
7865 {
7866   jamEntry();
7867   CreateIndxReq* const req = (CreateIndxReq*)signal->getDataPtrSend();
7868   OpCreateIndexPtr opPtr;
7869   const Uint32 senderRef = signal->senderBlockRef();
7870   const CreateIndxReq::RequestType requestType = req->getRequestType();
7871   if (requestType == CreateIndxReq::RT_USER) {
7872     jam();
7873     if (! assembleFragments(signal)) {
7874       jam();
7875       return;
7876     }
7877     if (signal->getLength() == CreateIndxReq::SignalLength) {
7878       jam();
7879       CreateIndxRef::ErrorCode tmperr = CreateIndxRef::NoError;
7880       if (getOwnNodeId() != c_masterNodeId) {
7881         jam();
7882         tmperr = CreateIndxRef::NotMaster;
7883       } else if (c_blockState == BS_NODE_RESTART) {
7884         jam();
7885         tmperr = CreateIndxRef::BusyWithNR;
7886       } else if (c_blockState != BS_IDLE) {
7887         jam();
7888         tmperr = CreateIndxRef::Busy;
7889       }
7890       else if (checkSingleUserMode(senderRef))
7891       {
7892         jam();
7893         tmperr = CreateIndxRef::SingleUser;
7894       }
7895       if (tmperr != CreateIndxRef::NoError) {
7896 	releaseSections(signal);
7897 	OpCreateIndex opBusy;
7898 	opPtr.p = &opBusy;
7899 	opPtr.p->save(req);
7900 	opPtr.p->m_isMaster = (senderRef == reference());
7901 	opPtr.p->key = 0;
7902 	opPtr.p->m_requestType = CreateIndxReq::RT_DICT_PREPARE;
7903 	opPtr.p->m_errorCode = tmperr;
7904 	opPtr.p->m_errorLine = __LINE__;
7905 	opPtr.p->m_errorNode = c_masterNodeId;
7906 	createIndex_sendReply(signal, opPtr, true);
7907 	return;
7908       }
7909       // forward initial request plus operation key to all
7910       req->setOpKey(++c_opRecordSequence);
7911       NodeReceiverGroup rg(DBDICT, c_aliveNodes);
7912       sendSignal(rg, GSN_CREATE_INDX_REQ,
7913           signal, CreateIndxReq::SignalLength + 1, JBB);
7914       return;
7915     }
7916     // seize operation record
7917     ndbrequire(signal->getLength() == CreateIndxReq::SignalLength + 1);
7918     const Uint32 opKey = req->getOpKey();
7919     OpCreateIndex opBusy;
7920     if (! c_opCreateIndex.seize(opPtr))
7921       opPtr.p = &opBusy;
7922     opPtr.p->save(req);
7923     opPtr.p->m_coordinatorRef = senderRef;
7924     opPtr.p->m_isMaster = (senderRef == reference());
7925     opPtr.p->key = opKey;
7926     opPtr.p->m_requestType = CreateIndxReq::RT_DICT_PREPARE;
7927     if (opPtr.p == &opBusy) {
7928       jam();
7929       opPtr.p->m_errorCode = CreateIndxRef::Busy;
7930       opPtr.p->m_errorLine = __LINE__;
7931       releaseSections(signal);
7932       createIndex_sendReply(signal, opPtr, opPtr.p->m_isMaster);
7933       return;
7934     }
7935     c_opCreateIndex.add(opPtr);
7936     // save attribute list
7937     SegmentedSectionPtr ssPtr;
7938     signal->getSection(ssPtr, CreateIndxReq::ATTRIBUTE_LIST_SECTION);
7939     SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
7940     r0.reset(); // undo implicit first()
7941     if (! r0.getWord(&opPtr.p->m_attrList.sz) ||
7942         ! r0.getWords(opPtr.p->m_attrList.id, opPtr.p->m_attrList.sz)) {
7943       jam();
7944       opPtr.p->m_errorCode = CreateIndxRef::InvalidName;
7945       opPtr.p->m_errorLine = __LINE__;
7946       releaseSections(signal);
7947       createIndex_sendReply(signal, opPtr, opPtr.p->m_isMaster);
7948       return;
7949     }
7950     // save name and index table properties
7951     signal->getSection(ssPtr, CreateIndxReq::INDEX_NAME_SECTION);
7952     SimplePropertiesSectionReader r1(ssPtr, getSectionSegmentPool());
7953     c_tableDesc.init();
7954     SimpleProperties::UnpackStatus status = SimpleProperties::unpack(
7955         r1, &c_tableDesc,
7956         DictTabInfo::TableMapping, DictTabInfo::TableMappingSize,
7957         true, true);
7958     if (status != SimpleProperties::Eof) {
7959       opPtr.p->m_errorCode = CreateIndxRef::InvalidName;
7960       opPtr.p->m_errorLine = __LINE__;
7961       releaseSections(signal);
7962       createIndex_sendReply(signal, opPtr, opPtr.p->m_isMaster);
7963       return;
7964     }
7965     memcpy(opPtr.p->m_indexName, c_tableDesc.TableName, MAX_TAB_NAME_SIZE);
7966     opPtr.p->m_loggedIndex = c_tableDesc.TableLoggedFlag;
7967     opPtr.p->m_temporaryIndex = c_tableDesc.TableTemporaryFlag;
7968     releaseSections(signal);
7969     // master expects to hear from all
7970     if (opPtr.p->m_isMaster)
7971       opPtr.p->m_signalCounter = c_aliveNodes;
7972     createIndex_slavePrepare(signal, opPtr);
7973     createIndex_sendReply(signal, opPtr, false);
7974     return;
7975   }
7976   c_opCreateIndex.find(opPtr, req->getConnectionPtr());
7977   if (! opPtr.isNull()) {
7978     opPtr.p->m_requestType = requestType;
7979     if (requestType == CreateIndxReq::RT_DICT_COMMIT ||
7980         requestType == CreateIndxReq::RT_DICT_ABORT) {
7981       jam();
7982       if (requestType == CreateIndxReq::RT_DICT_COMMIT) {
7983         opPtr.p->m_request.setIndexId(req->getIndexId());
7984         opPtr.p->m_request.setIndexVersion(req->getIndexVersion());
7985         createIndex_slaveCommit(signal, opPtr);
7986       } else {
7987         createIndex_slaveAbort(signal, opPtr);
7988       }
7989       createIndex_sendReply(signal, opPtr, false);
7990       // done in slave
7991       if (! opPtr.p->m_isMaster)
7992         c_opCreateIndex.release(opPtr);
7993       return;
7994     }
7995   }
7996   jam();
7997   // return to sender
7998   releaseSections(signal);
7999   OpCreateIndex opBad;
8000   opPtr.p = &opBad;
8001   opPtr.p->save(req);
8002   opPtr.p->m_errorCode = CreateIndxRef::BadRequestType;
8003   opPtr.p->m_errorLine = __LINE__;
8004   createIndex_sendReply(signal, opPtr, true);
8005 }
8006 
8007 void
execCREATE_INDX_CONF(Signal * signal)8008 Dbdict::execCREATE_INDX_CONF(Signal* signal)
8009 {
8010   jamEntry();
8011   ndbrequire(signal->getNoOfSections() == 0);
8012   CreateIndxConf* conf = (CreateIndxConf*)signal->getDataPtrSend();
8013   createIndex_recvReply(signal, conf, 0);
8014 }
8015 
8016 void
execCREATE_INDX_REF(Signal * signal)8017 Dbdict::execCREATE_INDX_REF(Signal* signal)
8018 {
8019   jamEntry();
8020   CreateIndxRef* ref = (CreateIndxRef*)signal->getDataPtrSend();
8021   createIndex_recvReply(signal, ref->getConf(), ref);
8022 }
8023 
8024 void
createIndex_recvReply(Signal * signal,const CreateIndxConf * conf,const CreateIndxRef * ref)8025 Dbdict::createIndex_recvReply(Signal* signal, const CreateIndxConf* conf,
8026     const CreateIndxRef* ref)
8027 {
8028   jam();
8029   const Uint32 senderRef = signal->senderBlockRef();
8030   const CreateIndxReq::RequestType requestType = conf->getRequestType();
8031   const Uint32 key = conf->getConnectionPtr();
8032   if (requestType == CreateIndxReq::RT_TC) {
8033     jam();
8034     // part of alter index operation
8035     OpAlterIndexPtr opPtr;
8036     c_opAlterIndex.find(opPtr, key);
8037     ndbrequire(! opPtr.isNull());
8038     opPtr.p->setError(ref);
8039     alterIndex_fromCreateTc(signal, opPtr);
8040     return;
8041   }
8042   OpCreateIndexPtr opPtr;
8043   c_opCreateIndex.find(opPtr, key);
8044   ndbrequire(! opPtr.isNull());
8045   ndbrequire(opPtr.p->m_isMaster);
8046   ndbrequire(opPtr.p->m_requestType == requestType);
8047   opPtr.p->setError(ref);
8048   opPtr.p->m_signalCounter.clearWaitingFor(refToNode(senderRef));
8049   if (! opPtr.p->m_signalCounter.done()) {
8050     jam();
8051     return;
8052   }
8053   if (requestType == CreateIndxReq::RT_DICT_COMMIT ||
8054       requestType == CreateIndxReq::RT_DICT_ABORT) {
8055     jam();
8056     // send reply to user
8057     createIndex_sendReply(signal, opPtr, true);
8058     c_opCreateIndex.release(opPtr);
8059     return;
8060   }
8061   if (opPtr.p->hasError()) {
8062     jam();
8063     opPtr.p->m_requestType = CreateIndxReq::RT_DICT_ABORT;
8064     createIndex_sendSlaveReq(signal, opPtr);
8065     return;
8066   }
8067   if (requestType == CreateIndxReq::RT_DICT_PREPARE) {
8068     jam();
8069     // start index table create
8070     createIndex_toCreateTable(signal, opPtr);
8071     if (opPtr.p->hasError()) {
8072       jam();
8073       opPtr.p->m_requestType = CreateIndxReq::RT_DICT_ABORT;
8074       createIndex_sendSlaveReq(signal, opPtr);
8075       return;
8076     }
8077     return;
8078   }
8079   ndbrequire(false);
8080 }
8081 
8082 void
createIndex_slavePrepare(Signal * signal,OpCreateIndexPtr opPtr)8083 Dbdict::createIndex_slavePrepare(Signal* signal, OpCreateIndexPtr opPtr)
8084 {
8085   jam();
8086   if (ERROR_INSERTED(6006) && ! opPtr.p->m_isMaster) {
8087     ndbrequire(false);
8088   }
8089 }
8090 
8091 void
createIndex_toCreateTable(Signal * signal,OpCreateIndexPtr opPtr)8092 Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
8093 {
8094   union {
8095     char tableName[MAX_TAB_NAME_SIZE];
8096     char attributeName[MAX_ATTR_NAME_SIZE];
8097   };
8098   Uint32 k;
8099   Uint32 attrid_map[MAX_ATTRIBUTES_IN_INDEX];
8100 
8101   jam();
8102   const CreateIndxReq* const req = &opPtr.p->m_request;
8103   // signal data writer
8104   Uint32* wbuffer = &c_indexPage.word[0];
8105   LinearWriter w(wbuffer, sizeof(c_indexPage) >> 2);
8106   w.first();
8107   // get table being indexed
8108   if (! (req->getTableId() < c_tableRecordPool.getSize())) {
8109     jam();
8110     opPtr.p->m_errorCode = CreateIndxRef::InvalidPrimaryTable;
8111     opPtr.p->m_errorLine = __LINE__;
8112     return;
8113   }
8114   TableRecordPtr tablePtr;
8115   c_tableRecordPool.getPtr(tablePtr, req->getTableId());
8116   if (tablePtr.p->tabState != TableRecord::DEFINED &&
8117       tablePtr.p->tabState != TableRecord::BACKUP_ONGOING) {
8118     jam();
8119     opPtr.p->m_errorCode = CreateIndxRef::InvalidPrimaryTable;
8120     opPtr.p->m_errorLine = __LINE__;
8121     return;
8122   }
8123   if (! tablePtr.p->isTable()) {
8124     jam();
8125     opPtr.p->m_errorCode = CreateIndxRef::InvalidPrimaryTable;
8126     opPtr.p->m_errorLine = __LINE__;
8127     return;
8128   }
8129 
8130   // Check that the temporary status of index is compatible with table.
8131   if (!opPtr.p->m_temporaryIndex &&
8132       tablePtr.p->m_bits & TableRecord::TR_Temporary)
8133   {
8134     jam();
8135     opPtr.p->m_errorCode= CreateIndxRef::TableIsTemporary;
8136     opPtr.p->m_errorLine= __LINE__;
8137     return;
8138   }
8139   if (opPtr.p->m_temporaryIndex &&
8140       !(tablePtr.p->m_bits & TableRecord::TR_Temporary))
8141   {
8142     // This could be implemented later, but mysqld does currently not detect
8143     // that the index disappears after SR, and it appears not too useful.
8144     jam();
8145     opPtr.p->m_errorCode= CreateIndxRef::TableIsNotTemporary;
8146     opPtr.p->m_errorLine= __LINE__;
8147     return;
8148   }
8149   if (opPtr.p->m_temporaryIndex && opPtr.p->m_loggedIndex)
8150   {
8151     jam();
8152     opPtr.p->m_errorCode= CreateIndxRef::NoLoggingTemporaryIndex;
8153     opPtr.p->m_errorLine= __LINE__;
8154     return;
8155   }
8156 
8157   // compute index table record
8158   TableRecord indexRec;
8159   TableRecordPtr indexPtr;
8160   indexPtr.i = RNIL;            // invalid
8161   indexPtr.p = &indexRec;
8162   initialiseTableRecord(indexPtr);
8163   indexPtr.p->m_bits = TableRecord::TR_RowChecksum;
8164   if (req->getIndexType() == DictTabInfo::UniqueHashIndex) {
8165     indexPtr.p->m_bits |= (opPtr.p->m_loggedIndex ? TableRecord::TR_Logged:0);
8166     indexPtr.p->m_bits |=
8167       (opPtr.p->m_temporaryIndex ? TableRecord::TR_Temporary : 0);
8168     indexPtr.p->fragmentType = DictTabInfo::DistrKeyUniqueHashIndex;
8169   } else if (req->getIndexType() == DictTabInfo::OrderedIndex) {
8170     // first version will not supported logging
8171     if (opPtr.p->m_loggedIndex) {
8172       jam();
8173       opPtr.p->m_errorCode = CreateIndxRef::InvalidIndexType;
8174       opPtr.p->m_errorLine = __LINE__;
8175       return;
8176     }
8177     indexPtr.p->m_bits |=
8178       (opPtr.p->m_temporaryIndex ? TableRecord::TR_Temporary : 0);
8179     indexPtr.p->fragmentType = DictTabInfo::DistrKeyOrderedIndex;
8180   } else {
8181     jam();
8182     opPtr.p->m_errorCode = CreateIndxRef::InvalidIndexType;
8183     opPtr.p->m_errorLine = __LINE__;
8184     return;
8185   }
8186   indexPtr.p->tableType = (DictTabInfo::TableType)req->getIndexType();
8187   indexPtr.p->primaryTableId = req->getTableId();
8188   indexPtr.p->noOfAttributes = opPtr.p->m_attrList.sz;
8189   indexPtr.p->tupKeyLength = 0;
8190   if (indexPtr.p->noOfAttributes == 0) {
8191     jam();
8192     opPtr.p->m_errorCode = CreateIndxRef::InvalidIndexType;
8193     opPtr.p->m_errorLine = __LINE__;
8194     return;
8195   }
8196 
8197   if (indexPtr.p->isOrderedIndex()) {
8198     // tree node size in words (make configurable later)
8199     indexPtr.p->tupKeyLength = MAX_TTREE_NODE_SIZE;
8200   }
8201 
8202   AttributeMask mask;
8203   mask.clear();
8204   for (k = 0; k < opPtr.p->m_attrList.sz; k++) {
8205     jam();
8206     unsigned current_id= opPtr.p->m_attrList.id[k];
8207     Uint32 tAttr = tablePtr.p->m_attributes.firstItem;
8208     AttributeRecord* aRec = NULL;
8209     for (; tAttr != RNIL; )
8210     {
8211       aRec = c_attributeRecordPool.getPtr(tAttr);
8212       if (aRec->attributeId != current_id)
8213       {
8214 	tAttr= aRec->nextList;
8215 	continue;
8216       }
8217       jam();
8218       break;
8219     }
8220     if (tAttr == RNIL) {
8221       jam();
8222       opPtr.p->m_errorCode = CreateIndxRef::BadRequestType;
8223       opPtr.p->m_errorLine = __LINE__;
8224       return;
8225     }
8226     if (mask.get(current_id))
8227     {
8228       jam();
8229       opPtr.p->m_errorCode = CreateIndxRef::DuplicateAttributes;
8230       opPtr.p->m_errorLine = __LINE__;
8231       return;
8232     }
8233     const Uint32 a = aRec->attributeDescriptor;
8234 
8235     if (AttributeDescriptor::getDiskBased(a))
8236     {
8237       jam();
8238       opPtr.p->m_errorCode = CreateIndxRef::IndexOnDiskAttributeError;
8239       opPtr.p->m_errorLine = __LINE__;
8240       return;
8241     }
8242 
8243     mask.set(current_id);
8244     unsigned kk= k;
8245     if (indexPtr.p->isHashIndex()) {
8246       const Uint32 s1 = AttributeDescriptor::getSize(a);
8247       const Uint32 s2 = AttributeDescriptor::getArraySize(a);
8248       indexPtr.p->tupKeyLength += ((1 << s1) * s2 + 31) >> 5;
8249 
8250       for (; kk > 0 && current_id < attrid_map[kk-1]>>16; kk--)
8251 	attrid_map[kk]= attrid_map[kk-1];
8252     }
8253     attrid_map[kk]= k | (current_id << 16);
8254   }
8255 
8256   indexPtr.p->noOfPrimkey = indexPtr.p->noOfAttributes;
8257   // plus concatenated primary table key attribute
8258   indexPtr.p->noOfAttributes += 1;
8259   indexPtr.p->noOfNullAttr = 0;
8260   // write index table
8261   w.add(DictTabInfo::TableName, opPtr.p->m_indexName);
8262   w.add(DictTabInfo::TableLoggedFlag, !!(indexPtr.p->m_bits & TableRecord::TR_Logged));
8263   w.add(DictTabInfo::TableTemporaryFlag, !!(indexPtr.p->m_bits & TableRecord::TR_Temporary));
8264   w.add(DictTabInfo::FragmentTypeVal, indexPtr.p->fragmentType);
8265   w.add(DictTabInfo::TableTypeVal, indexPtr.p->tableType);
8266   Rope name(c_rope_pool, tablePtr.p->tableName);
8267   name.copy(tableName);
8268   w.add(DictTabInfo::PrimaryTable, tableName);
8269   w.add(DictTabInfo::PrimaryTableId, tablePtr.i);
8270   w.add(DictTabInfo::NoOfAttributes, indexPtr.p->noOfAttributes);
8271   w.add(DictTabInfo::NoOfKeyAttr, indexPtr.p->noOfPrimkey);
8272   w.add(DictTabInfo::NoOfNullable, indexPtr.p->noOfNullAttr);
8273   w.add(DictTabInfo::KeyLength, indexPtr.p->tupKeyLength);
8274   w.add(DictTabInfo::SingleUserMode, (Uint32)NDB_SUM_READ_WRITE);
8275   // write index key attributes
8276   for (k = 0; k < opPtr.p->m_attrList.sz; k++) {
8277     // insert the attributes in the order decided above in attrid_map
8278     // k is new order, current_id is in previous order
8279     // ToDo: make sure "current_id" is stored with the table and
8280     // passed up to NdbDictionary
8281     unsigned current_id= opPtr.p->m_attrList.id[attrid_map[k] & 0xffff];
8282     jam();
8283     for (Uint32 tAttr = tablePtr.p->m_attributes.firstItem; tAttr != RNIL; ) {
8284       AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr);
8285       tAttr = aRec->nextList;
8286       if (aRec->attributeId != current_id)
8287         continue;
8288       jam();
8289       const Uint32 a = aRec->attributeDescriptor;
8290       bool isNullable = AttributeDescriptor::getNullable(a);
8291       Uint32 arrayType = AttributeDescriptor::getArrayType(a);
8292       Rope attrName(c_rope_pool, aRec->attributeName);
8293       attrName.copy(attributeName);
8294       w.add(DictTabInfo::AttributeName, attributeName);
8295       Uint32 attrType = AttributeDescriptor::getType(a);
8296       // computed
8297       w.add(DictTabInfo::AttributeId, k);
8298       if (indexPtr.p->isHashIndex()) {
8299         w.add(DictTabInfo::AttributeKeyFlag, (Uint32)true);
8300         w.add(DictTabInfo::AttributeNullableFlag, (Uint32)false);
8301       }
8302       if (indexPtr.p->isOrderedIndex()) {
8303         w.add(DictTabInfo::AttributeKeyFlag, (Uint32)false);
8304         w.add(DictTabInfo::AttributeNullableFlag, (Uint32)isNullable);
8305       }
8306       w.add(DictTabInfo::AttributeArrayType, arrayType);
8307       w.add(DictTabInfo::AttributeExtType, attrType);
8308       w.add(DictTabInfo::AttributeExtPrecision, aRec->extPrecision);
8309       w.add(DictTabInfo::AttributeExtScale, aRec->extScale);
8310       w.add(DictTabInfo::AttributeExtLength, aRec->extLength);
8311       w.add(DictTabInfo::AttributeEnd, (Uint32)true);
8312     }
8313   }
8314   if (indexPtr.p->isHashIndex()) {
8315     jam();
8316 
8317     Uint32 key_type = NDB_ARRAYTYPE_FIXED;
8318     AttributeRecordPtr attrPtr;
8319     LocalDLFifoList<AttributeRecord> alist(c_attributeRecordPool,
8320 					   tablePtr.p->m_attributes);
8321     for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr))
8322     {
8323       const Uint32 desc = attrPtr.p->attributeDescriptor;
8324       if (AttributeDescriptor::getPrimaryKey(desc) &&
8325 	  AttributeDescriptor::getArrayType(desc) != NDB_ARRAYTYPE_FIXED)
8326       {
8327 	key_type = NDB_ARRAYTYPE_MEDIUM_VAR;
8328 	break;
8329       }
8330     }
8331 
8332     // write concatenated primary table key attribute i.e. keyinfo
8333     w.add(DictTabInfo::AttributeName, "NDB$PK");
8334     w.add(DictTabInfo::AttributeId, opPtr.p->m_attrList.sz);
8335     w.add(DictTabInfo::AttributeArrayType, key_type);
8336     w.add(DictTabInfo::AttributeKeyFlag, (Uint32)false);
8337     w.add(DictTabInfo::AttributeNullableFlag, (Uint32)false);
8338     w.add(DictTabInfo::AttributeExtType, (Uint32)DictTabInfo::ExtUnsigned);
8339     w.add(DictTabInfo::AttributeExtLength, tablePtr.p->tupKeyLength+1);
8340     w.add(DictTabInfo::AttributeEnd, (Uint32)true);
8341   }
8342   if (indexPtr.p->isOrderedIndex()) {
8343     jam();
8344     // write index tree node as Uint32 array attribute
8345     w.add(DictTabInfo::AttributeName, "NDB$TNODE");
8346     w.add(DictTabInfo::AttributeId, opPtr.p->m_attrList.sz);
8347     // should not matter but VAR crashes in TUP
8348     w.add(DictTabInfo::AttributeArrayType, (Uint32)NDB_ARRAYTYPE_FIXED);
8349     w.add(DictTabInfo::AttributeKeyFlag, (Uint32)true);
8350     w.add(DictTabInfo::AttributeNullableFlag, (Uint32)false);
8351     w.add(DictTabInfo::AttributeExtType, (Uint32)DictTabInfo::ExtUnsigned);
8352     w.add(DictTabInfo::AttributeExtLength, indexPtr.p->tupKeyLength);
8353     w.add(DictTabInfo::AttributeEnd, (Uint32)true);
8354   }
8355   // finish
8356   w.add(DictTabInfo::TableEnd, (Uint32)true);
8357   // remember to...
8358   releaseSections(signal);
8359   // send create index table request
8360   CreateTableReq * const cre = (CreateTableReq*)signal->getDataPtrSend();
8361   cre->senderRef = reference();
8362   cre->senderData = opPtr.p->key;
8363   LinearSectionPtr lsPtr[3];
8364   lsPtr[0].p = wbuffer;
8365   lsPtr[0].sz = w.getWordsUsed();
8366   sendSignal(DBDICT_REF, GSN_CREATE_TABLE_REQ,
8367       signal, CreateTableReq::SignalLength, JBB, lsPtr, 1);
8368 }
8369 
8370 void
createIndex_fromCreateTable(Signal * signal,OpCreateIndexPtr opPtr)8371 Dbdict::createIndex_fromCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
8372 {
8373   jam();
8374   if (opPtr.p->hasError()) {
8375     jam();
8376     opPtr.p->m_requestType = CreateIndxReq::RT_DICT_ABORT;
8377     createIndex_sendSlaveReq(signal, opPtr);
8378     return;
8379   }
8380   if (! opPtr.p->m_request.getOnline()) {
8381     jam();
8382     opPtr.p->m_requestType = CreateIndxReq::RT_DICT_COMMIT;
8383     createIndex_sendSlaveReq(signal, opPtr);
8384     return;
8385   }
8386   createIndex_toAlterIndex(signal, opPtr);
8387 }
8388 
8389 void
createIndex_toAlterIndex(Signal * signal,OpCreateIndexPtr opPtr)8390 Dbdict::createIndex_toAlterIndex(Signal* signal, OpCreateIndexPtr opPtr)
8391 {
8392   jam();
8393   AlterIndxReq* const req = (AlterIndxReq*)signal->getDataPtrSend();
8394   req->setUserRef(reference());
8395   req->setConnectionPtr(opPtr.p->key);
8396   req->setRequestType(AlterIndxReq::RT_CREATE_INDEX);
8397   req->addRequestFlag(opPtr.p->m_requestFlag);
8398   req->setTableId(opPtr.p->m_request.getTableId());
8399   req->setIndexId(opPtr.p->m_request.getIndexId());
8400   req->setIndexVersion(opPtr.p->m_request.getIndexVersion());
8401   req->setOnline(true);
8402   sendSignal(reference(), GSN_ALTER_INDX_REQ,
8403       signal, AlterIndxReq::SignalLength, JBB);
8404 }
8405 
8406 void
createIndex_fromAlterIndex(Signal * signal,OpCreateIndexPtr opPtr)8407 Dbdict::createIndex_fromAlterIndex(Signal* signal, OpCreateIndexPtr opPtr)
8408 {
8409   jam();
8410   if (opPtr.p->hasError()) {
8411     jam();
8412     opPtr.p->m_requestType = CreateIndxReq::RT_DICT_ABORT;
8413     createIndex_sendSlaveReq(signal, opPtr);
8414     return;
8415   }
8416   opPtr.p->m_requestType = CreateIndxReq::RT_DICT_COMMIT;
8417   createIndex_sendSlaveReq(signal, opPtr);
8418 }
8419 
8420 void
createIndex_slaveCommit(Signal * signal,OpCreateIndexPtr opPtr)8421 Dbdict::createIndex_slaveCommit(Signal* signal, OpCreateIndexPtr opPtr)
8422 {
8423   jam();
8424   const Uint32 indexId = opPtr.p->m_request.getIndexId();
8425   TableRecordPtr indexPtr;
8426   c_tableRecordPool.getPtr(indexPtr, indexId);
8427   if (! opPtr.p->m_request.getOnline()) {
8428     ndbrequire(indexPtr.p->indexState == TableRecord::IS_UNDEFINED);
8429     indexPtr.p->indexState = TableRecord::IS_OFFLINE;
8430   } else {
8431     ndbrequire(indexPtr.p->indexState == TableRecord::IS_ONLINE);
8432   }
8433 }
8434 
8435 void
createIndex_slaveAbort(Signal * signal,OpCreateIndexPtr opPtr)8436 Dbdict::createIndex_slaveAbort(Signal* signal, OpCreateIndexPtr opPtr)
8437 {
8438   jam();
8439   CreateIndxReq* const req = &opPtr.p->m_request;
8440   const Uint32 indexId = req->getIndexId();
8441   if (indexId >= c_tableRecordPool.getSize()) {
8442     jam();
8443     return;
8444   }
8445   TableRecordPtr indexPtr;
8446   c_tableRecordPool.getPtr(indexPtr, indexId);
8447   if (! indexPtr.p->isIndex()) {
8448     jam();
8449     return;
8450   }
8451   indexPtr.p->indexState = TableRecord::IS_BROKEN;
8452 }
8453 
8454 void
createIndex_sendSlaveReq(Signal * signal,OpCreateIndexPtr opPtr)8455 Dbdict::createIndex_sendSlaveReq(Signal* signal, OpCreateIndexPtr opPtr)
8456 {
8457   jam();
8458   CreateIndxReq* const req = (CreateIndxReq*)signal->getDataPtrSend();
8459   *req = opPtr.p->m_request;
8460   req->setUserRef(opPtr.p->m_coordinatorRef);
8461   req->setConnectionPtr(opPtr.p->key);
8462   req->setRequestType(opPtr.p->m_requestType);
8463   req->addRequestFlag(opPtr.p->m_requestFlag);
8464   opPtr.p->m_signalCounter = c_aliveNodes;
8465   NodeReceiverGroup rg(DBDICT, c_aliveNodes);
8466   sendSignal(rg, GSN_CREATE_INDX_REQ,
8467       signal, CreateIndxReq::SignalLength, JBB);
8468 }
8469 
8470 void
createIndex_sendReply(Signal * signal,OpCreateIndexPtr opPtr,bool toUser)8471 Dbdict::createIndex_sendReply(Signal* signal, OpCreateIndexPtr opPtr,
8472     bool toUser)
8473 {
8474   CreateIndxRef* rep = (CreateIndxRef*)signal->getDataPtrSend();
8475   Uint32 gsn = GSN_CREATE_INDX_CONF;
8476   Uint32 length = CreateIndxConf::InternalLength;
8477   bool sendRef;
8478   if (! toUser) {
8479     sendRef = opPtr.p->hasLastError();
8480     rep->setUserRef(opPtr.p->m_coordinatorRef);
8481     rep->setConnectionPtr(opPtr.p->key);
8482     rep->setRequestType(opPtr.p->m_requestType);
8483     if (opPtr.p->m_requestType == CreateIndxReq::RT_DICT_ABORT)
8484       sendRef = false;
8485   } else {
8486     sendRef = opPtr.p->hasError();
8487     rep->setUserRef(opPtr.p->m_request.getUserRef());
8488     rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
8489     rep->setRequestType(opPtr.p->m_request.getRequestType());
8490     length = CreateIndxConf::SignalLength;
8491   }
8492   rep->setTableId(opPtr.p->m_request.getTableId());
8493   rep->setIndexId(opPtr.p->m_request.getIndexId());
8494   rep->setIndexVersion(opPtr.p->m_request.getIndexVersion());
8495   if (sendRef) {
8496     if (opPtr.p->m_errorNode == 0)
8497       opPtr.p->m_errorNode = getOwnNodeId();
8498     rep->setErrorCode(opPtr.p->m_errorCode);
8499     rep->setErrorLine(opPtr.p->m_errorLine);
8500     rep->setErrorNode(opPtr.p->m_errorNode);
8501     gsn = GSN_CREATE_INDX_REF;
8502     length = CreateIndxRef::SignalLength;
8503   }
8504   sendSignal(rep->getUserRef(), gsn, signal, length, JBB);
8505 }
8506 
8507 /**
8508  * MODULE: Drop index.
8509  *
8510  * Drop index.  First alters the index offline (i.e.  drops metadata in
8511  * other blocks) and then drops the index table.
8512  */
8513 
8514 void
execDROP_INDX_REQ(Signal * signal)8515 Dbdict::execDROP_INDX_REQ(Signal* signal)
8516 {
8517   jamEntry();
8518   DropIndxReq* const req = (DropIndxReq*)signal->getDataPtrSend();
8519   OpDropIndexPtr opPtr;
8520 
8521   int err = DropIndxRef::BadRequestType;
8522   const Uint32 senderRef = signal->senderBlockRef();
8523   const DropIndxReq::RequestType requestType = req->getRequestType();
8524   if (requestType == DropIndxReq::RT_USER) {
8525     jam();
8526     if (signal->getLength() == DropIndxReq::SignalLength) {
8527       jam();
8528       DropIndxRef::ErrorCode tmperr = DropIndxRef::NoError;
8529       if (getOwnNodeId() != c_masterNodeId) {
8530         jam();
8531         tmperr = DropIndxRef::NotMaster;
8532       } else if (c_blockState == BS_NODE_RESTART) {
8533         jam();
8534         tmperr = DropIndxRef::BusyWithNR;
8535       } else if (c_blockState != BS_IDLE) {
8536         jam();
8537         tmperr = DropIndxRef::Busy;
8538       }
8539       else if (checkSingleUserMode(senderRef))
8540       {
8541         jam();
8542         tmperr = DropIndxRef::SingleUser;
8543       }
8544       if (tmperr != DropIndxRef::NoError) {
8545 	err = tmperr;
8546 	goto error;
8547       }
8548       // forward initial request plus operation key to all
8549       Uint32 indexId= req->getIndexId();
8550       Uint32 indexVersion= req->getIndexVersion();
8551 
8552       if(indexId >= c_tableRecordPool.getSize())
8553       {
8554 	err = DropIndxRef::IndexNotFound;
8555 	goto error;
8556       }
8557 
8558       TableRecordPtr tmp;
8559       c_tableRecordPool.getPtr(tmp, indexId);
8560       if(tmp.p->tabState == TableRecord::NOT_DEFINED ||
8561 	 tmp.p->tableVersion != indexVersion)
8562       {
8563 	err = DropIndxRef::InvalidIndexVersion;
8564 	goto error;
8565       }
8566 
8567       if (! tmp.p->isIndex()) {
8568 	jam();
8569 	err = DropIndxRef::NotAnIndex;
8570 	goto error;
8571       }
8572 
8573       if (tmp.p->indexState != TableRecord::IS_ONLINE)
8574         req->addRequestFlag(RequestFlag::RF_FORCE);
8575 
8576       tmp.p->indexState = TableRecord::IS_DROPPING;
8577 
8578       req->setOpKey(++c_opRecordSequence);
8579       NodeReceiverGroup rg(DBDICT, c_aliveNodes);
8580       sendSignal(rg, GSN_DROP_INDX_REQ,
8581 		 signal, DropIndxReq::SignalLength + 1, JBB);
8582       return;
8583     }
8584     // seize operation record
8585     ndbrequire(signal->getLength() == DropIndxReq::SignalLength + 1);
8586     const Uint32 opKey = req->getOpKey();
8587     OpDropIndex opBusy;
8588     if (! c_opDropIndex.seize(opPtr))
8589       opPtr.p = &opBusy;
8590     opPtr.p->save(req);
8591     opPtr.p->m_coordinatorRef = senderRef;
8592     opPtr.p->m_isMaster = (senderRef == reference());
8593     opPtr.p->key = opKey;
8594     opPtr.p->m_requestType = DropIndxReq::RT_DICT_PREPARE;
8595     if (opPtr.p == &opBusy) {
8596       jam();
8597       opPtr.p->m_errorCode = DropIndxRef::Busy;
8598       opPtr.p->m_errorLine = __LINE__;
8599       dropIndex_sendReply(signal, opPtr, opPtr.p->m_isMaster);
8600       return;
8601     }
8602     c_opDropIndex.add(opPtr);
8603     // master expects to hear from all
8604     if (opPtr.p->m_isMaster)
8605       opPtr.p->m_signalCounter = c_aliveNodes;
8606     dropIndex_slavePrepare(signal, opPtr);
8607     dropIndex_sendReply(signal, opPtr, false);
8608     return;
8609   }
8610   c_opDropIndex.find(opPtr, req->getConnectionPtr());
8611   if (! opPtr.isNull()) {
8612     opPtr.p->m_requestType = requestType;
8613     if (requestType == DropIndxReq::RT_DICT_COMMIT ||
8614         requestType == DropIndxReq::RT_DICT_ABORT) {
8615       jam();
8616       if (requestType == DropIndxReq::RT_DICT_COMMIT)
8617         dropIndex_slaveCommit(signal, opPtr);
8618       else
8619         dropIndex_slaveAbort(signal, opPtr);
8620       dropIndex_sendReply(signal, opPtr, false);
8621       // done in slave
8622       if (! opPtr.p->m_isMaster)
8623         c_opDropIndex.release(opPtr);
8624       return;
8625     }
8626   }
8627 error:
8628   jam();
8629   // return to sender
8630   OpDropIndex opBad;
8631   opPtr.p = &opBad;
8632   opPtr.p->save(req);
8633   opPtr.p->m_errorCode = (DropIndxRef::ErrorCode)err;
8634   opPtr.p->m_errorLine = __LINE__;
8635   opPtr.p->m_errorNode = c_masterNodeId;
8636   dropIndex_sendReply(signal, opPtr, true);
8637 }
8638 
8639 void
execDROP_INDX_CONF(Signal * signal)8640 Dbdict::execDROP_INDX_CONF(Signal* signal)
8641 {
8642   jamEntry();
8643   DropIndxConf* conf = (DropIndxConf*)signal->getDataPtrSend();
8644   dropIndex_recvReply(signal, conf, 0);
8645 }
8646 
8647 void
execDROP_INDX_REF(Signal * signal)8648 Dbdict::execDROP_INDX_REF(Signal* signal)
8649 {
8650   jamEntry();
8651   DropIndxRef* ref = (DropIndxRef*)signal->getDataPtrSend();
8652   dropIndex_recvReply(signal, ref->getConf(), ref);
8653 }
8654 
8655 void
dropIndex_recvReply(Signal * signal,const DropIndxConf * conf,const DropIndxRef * ref)8656 Dbdict::dropIndex_recvReply(Signal* signal, const DropIndxConf* conf,
8657     const DropIndxRef* ref)
8658 {
8659   jam();
8660   const Uint32 senderRef = signal->senderBlockRef();
8661   const DropIndxReq::RequestType requestType = conf->getRequestType();
8662   const Uint32 key = conf->getConnectionPtr();
8663   if (requestType == DropIndxReq::RT_TC) {
8664     jam();
8665     // part of alter index operation
8666     OpAlterIndexPtr opPtr;
8667     c_opAlterIndex.find(opPtr, key);
8668     ndbrequire(! opPtr.isNull());
8669     opPtr.p->setError(ref);
8670     alterIndex_fromDropTc(signal, opPtr);
8671     return;
8672   }
8673   OpDropIndexPtr opPtr;
8674   c_opDropIndex.find(opPtr, key);
8675   ndbrequire(! opPtr.isNull());
8676   ndbrequire(opPtr.p->m_isMaster);
8677   ndbrequire(opPtr.p->m_requestType == requestType);
8678   opPtr.p->setError(ref);
8679   opPtr.p->m_signalCounter.clearWaitingFor(refToNode(senderRef));
8680   if (! opPtr.p->m_signalCounter.done()) {
8681     jam();
8682     return;
8683   }
8684   if (requestType == DropIndxReq::RT_DICT_COMMIT ||
8685       requestType == DropIndxReq::RT_DICT_ABORT) {
8686     jam();
8687     // send reply to user
8688     dropIndex_sendReply(signal, opPtr, true);
8689     c_opDropIndex.release(opPtr);
8690     return;
8691   }
8692   if (opPtr.p->hasError()) {
8693     jam();
8694     opPtr.p->m_requestType = DropIndxReq::RT_DICT_ABORT;
8695     dropIndex_sendSlaveReq(signal, opPtr);
8696     return;
8697   }
8698   if (requestType == DropIndxReq::RT_DICT_PREPARE) {
8699     jam();
8700     // start alter offline
8701     dropIndex_toAlterIndex(signal, opPtr);
8702     return;
8703   }
8704   ndbrequire(false);
8705 }
8706 
8707 void
dropIndex_slavePrepare(Signal * signal,OpDropIndexPtr opPtr)8708 Dbdict::dropIndex_slavePrepare(Signal* signal, OpDropIndexPtr opPtr)
8709 {
8710   jam();
8711   DropIndxReq* const req = &opPtr.p->m_request;
8712   // check index exists
8713   TableRecordPtr indexPtr;
8714   if (! (req->getIndexId() < c_tableRecordPool.getSize())) {
8715     jam();
8716     opPtr.p->m_errorCode = DropIndxRef::IndexNotFound;
8717     opPtr.p->m_errorLine = __LINE__;
8718     return;
8719   }
8720   c_tableRecordPool.getPtr(indexPtr, req->getIndexId());
8721   if (indexPtr.p->tabState != TableRecord::DEFINED) {
8722     jam();
8723     opPtr.p->m_errorCode = DropIndxRef::IndexNotFound;
8724     opPtr.p->m_errorLine = __LINE__;
8725     return;
8726   }
8727   if (! indexPtr.p->isIndex()) {
8728     jam();
8729     opPtr.p->m_errorCode = DropIndxRef::NotAnIndex;
8730     opPtr.p->m_errorLine = __LINE__;
8731     return;
8732   }
8733   // ignore incoming primary table id
8734   req->setTableId(indexPtr.p->primaryTableId);
8735 }
8736 
8737 void
dropIndex_toAlterIndex(Signal * signal,OpDropIndexPtr opPtr)8738 Dbdict::dropIndex_toAlterIndex(Signal* signal, OpDropIndexPtr opPtr)
8739 {
8740   jam();
8741   AlterIndxReq* const req = (AlterIndxReq*)signal->getDataPtrSend();
8742   req->setUserRef(reference());
8743   req->setConnectionPtr(opPtr.p->key);
8744   req->setRequestType(AlterIndxReq::RT_DROP_INDEX);
8745   req->addRequestFlag(opPtr.p->m_requestFlag);
8746   req->setTableId(opPtr.p->m_request.getTableId());
8747   req->setIndexId(opPtr.p->m_request.getIndexId());
8748   req->setIndexVersion(opPtr.p->m_request.getIndexVersion());
8749   req->setOnline(false);
8750   sendSignal(reference(), GSN_ALTER_INDX_REQ,
8751       signal, AlterIndxReq::SignalLength, JBB);
8752 }
8753 
8754 void
dropIndex_fromAlterIndex(Signal * signal,OpDropIndexPtr opPtr)8755 Dbdict::dropIndex_fromAlterIndex(Signal* signal, OpDropIndexPtr opPtr)
8756 {
8757   jam();
8758   if (opPtr.p->hasError()) {
8759     jam();
8760     opPtr.p->m_requestType = DropIndxReq::RT_DICT_ABORT;
8761     dropIndex_sendSlaveReq(signal, opPtr);
8762     return;
8763   }
8764   dropIndex_toDropTable(signal, opPtr);
8765 }
8766 
8767 void
dropIndex_toDropTable(Signal * signal,OpDropIndexPtr opPtr)8768 Dbdict::dropIndex_toDropTable(Signal* signal, OpDropIndexPtr opPtr)
8769 {
8770   jam();
8771   DropTableReq* const req = (DropTableReq*)signal->getDataPtrSend();
8772   req->senderRef = reference();
8773   req->senderData = opPtr.p->key;
8774   req->tableId = opPtr.p->m_request.getIndexId();
8775   req->tableVersion = opPtr.p->m_request.getIndexVersion();
8776   sendSignal(reference(), GSN_DROP_TABLE_REQ,
8777       signal,DropTableReq::SignalLength, JBB);
8778 }
8779 
8780 void
dropIndex_fromDropTable(Signal * signal,OpDropIndexPtr opPtr)8781 Dbdict::dropIndex_fromDropTable(Signal* signal, OpDropIndexPtr opPtr)
8782 {
8783   jam();
8784   if (opPtr.p->hasError()) {
8785     jam();
8786     opPtr.p->m_requestType = DropIndxReq::RT_DICT_ABORT;
8787     dropIndex_sendSlaveReq(signal, opPtr);
8788     return;
8789   }
8790   opPtr.p->m_requestType = DropIndxReq::RT_DICT_COMMIT;
8791   dropIndex_sendSlaveReq(signal, opPtr);
8792 }
8793 
8794 void
dropIndex_slaveCommit(Signal * signal,OpDropIndexPtr opPtr)8795 Dbdict::dropIndex_slaveCommit(Signal* signal, OpDropIndexPtr opPtr)
8796 {
8797   jam();
8798 }
8799 
8800 void
dropIndex_slaveAbort(Signal * signal,OpDropIndexPtr opPtr)8801 Dbdict::dropIndex_slaveAbort(Signal* signal, OpDropIndexPtr opPtr)
8802 {
8803   jam();
8804   DropIndxReq* const req = &opPtr.p->m_request;
8805   const Uint32 indexId = req->getIndexId();
8806   if (indexId >= c_tableRecordPool.getSize()) {
8807     jam();
8808     return;
8809   }
8810   TableRecordPtr indexPtr;
8811   c_tableRecordPool.getPtr(indexPtr, indexId);
8812   indexPtr.p->indexState = TableRecord::IS_BROKEN;
8813 }
8814 
8815 void
dropIndex_sendSlaveReq(Signal * signal,OpDropIndexPtr opPtr)8816 Dbdict::dropIndex_sendSlaveReq(Signal* signal, OpDropIndexPtr opPtr)
8817 {
8818   DropIndxReq* const req = (DropIndxReq*)signal->getDataPtrSend();
8819   *req = opPtr.p->m_request;
8820   req->setUserRef(opPtr.p->m_coordinatorRef);
8821   req->setConnectionPtr(opPtr.p->key);
8822   req->setRequestType(opPtr.p->m_requestType);
8823   req->addRequestFlag(opPtr.p->m_requestFlag);
8824   opPtr.p->m_signalCounter = c_aliveNodes;
8825   NodeReceiverGroup rg(DBDICT, c_aliveNodes);
8826   sendSignal(rg, GSN_DROP_INDX_REQ,
8827       signal, DropIndxReq::SignalLength, JBB);
8828 }
8829 
8830 void
dropIndex_sendReply(Signal * signal,OpDropIndexPtr opPtr,bool toUser)8831 Dbdict::dropIndex_sendReply(Signal* signal, OpDropIndexPtr opPtr,
8832     bool toUser)
8833 {
8834   DropIndxRef* rep = (DropIndxRef*)signal->getDataPtrSend();
8835   Uint32 gsn = GSN_DROP_INDX_CONF;
8836   Uint32 length = DropIndxConf::InternalLength;
8837   bool sendRef;
8838   if (! toUser) {
8839     sendRef = opPtr.p->hasLastError();
8840     rep->setUserRef(opPtr.p->m_coordinatorRef);
8841     rep->setConnectionPtr(opPtr.p->key);
8842     rep->setRequestType(opPtr.p->m_requestType);
8843     if (opPtr.p->m_requestType == DropIndxReq::RT_DICT_ABORT)
8844       sendRef = false;
8845   } else {
8846     sendRef = opPtr.p->hasError();
8847     rep->setUserRef(opPtr.p->m_request.getUserRef());
8848     rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
8849     rep->setRequestType(opPtr.p->m_request.getRequestType());
8850     length = DropIndxConf::SignalLength;
8851   }
8852   rep->setTableId(opPtr.p->m_request.getTableId());
8853   rep->setIndexId(opPtr.p->m_request.getIndexId());
8854   rep->setIndexVersion(opPtr.p->m_request.getIndexVersion());
8855   if (sendRef) {
8856     if (opPtr.p->m_errorNode == 0)
8857       opPtr.p->m_errorNode = getOwnNodeId();
8858     rep->setErrorCode(opPtr.p->m_errorCode);
8859     rep->setErrorLine(opPtr.p->m_errorLine);
8860     rep->setErrorNode(opPtr.p->m_errorNode);
8861     gsn = GSN_DROP_INDX_REF;
8862     length = DropIndxRef::SignalLength;
8863   }
8864   sendSignal(rep->getUserRef(), gsn, signal, length, JBB);
8865 }
8866 
8867 /*****************************************************
8868  *
8869  * Util signalling
8870  *
8871  *****************************************************/
8872 
8873 int
sendSignalUtilReq(Callback * pcallback,BlockReference ref,GlobalSignalNumber gsn,Signal * signal,Uint32 length,JobBufferLevel jbuf,LinearSectionPtr ptr[3],Uint32 noOfSections)8874 Dbdict::sendSignalUtilReq(Callback *pcallback,
8875 			  BlockReference ref,
8876 			  GlobalSignalNumber gsn,
8877 			  Signal* signal,
8878 			  Uint32 length,
8879 			  JobBufferLevel jbuf,
8880 			  LinearSectionPtr ptr[3],
8881 			  Uint32 noOfSections)
8882 {
8883   jam();
8884   EVENT_TRACE;
8885   OpSignalUtilPtr utilRecPtr;
8886 
8887   // Seize a Util Send record
8888   if (!c_opSignalUtil.seize(utilRecPtr)) {
8889     // Failed to allocate util record
8890     return -1;
8891   }
8892   utilRecPtr.p->m_callback = *pcallback;
8893 
8894   // should work for all util signal classes
8895   UtilPrepareReq *req = (UtilPrepareReq*)signal->getDataPtrSend();
8896   utilRecPtr.p->m_userData = req->getSenderData();
8897   req->setSenderData(utilRecPtr.i);
8898 
8899   if (ptr) {
8900     jam();
8901     sendSignal(ref, gsn, signal, length, jbuf, ptr, noOfSections);
8902   } else {
8903     jam();
8904     sendSignal(ref, gsn, signal, length, jbuf);
8905   }
8906 
8907   return 0;
8908 }
8909 
8910 int
recvSignalUtilReq(Signal * signal,Uint32 returnCode)8911 Dbdict::recvSignalUtilReq(Signal* signal, Uint32 returnCode)
8912 {
8913   jam();
8914   EVENT_TRACE;
8915   UtilPrepareConf * const req = (UtilPrepareConf*)signal->getDataPtr();
8916   OpSignalUtilPtr utilRecPtr;
8917   utilRecPtr.i = req->getSenderData();
8918   if ((utilRecPtr.p = c_opSignalUtil.getPtr(utilRecPtr.i)) == NULL) {
8919     jam();
8920     return -1;
8921   }
8922 
8923   req->setSenderData(utilRecPtr.p->m_userData);
8924   Callback c = utilRecPtr.p->m_callback;
8925   c_opSignalUtil.release(utilRecPtr);
8926 
8927   execute(signal, c, returnCode);
8928   return 0;
8929 }
8930 
execUTIL_PREPARE_CONF(Signal * signal)8931 void Dbdict::execUTIL_PREPARE_CONF(Signal *signal)
8932 {
8933   jamEntry();
8934   EVENT_TRACE;
8935   ndbrequire(recvSignalUtilReq(signal, 0) == 0);
8936 }
8937 
8938 void
execUTIL_PREPARE_REF(Signal * signal)8939 Dbdict::execUTIL_PREPARE_REF(Signal *signal)
8940 {
8941   jamEntry();
8942   EVENT_TRACE;
8943   ndbrequire(recvSignalUtilReq(signal, 1) == 0);
8944 }
8945 
execUTIL_EXECUTE_CONF(Signal * signal)8946 void Dbdict::execUTIL_EXECUTE_CONF(Signal *signal)
8947 {
8948   jamEntry();
8949   EVENT_TRACE;
8950    ndbrequire(recvSignalUtilReq(signal, 0) == 0);
8951 }
8952 
execUTIL_EXECUTE_REF(Signal * signal)8953 void Dbdict::execUTIL_EXECUTE_REF(Signal *signal)
8954 {
8955   jamEntry();
8956   EVENT_TRACE;
8957 
8958 #ifdef EVENT_DEBUG
8959   UtilExecuteRef * ref = (UtilExecuteRef *)signal->getDataPtrSend();
8960 
8961   ndbout_c("execUTIL_EXECUTE_REF");
8962   ndbout_c("senderData %u",ref->getSenderData());
8963   ndbout_c("errorCode %u",ref->getErrorCode());
8964   ndbout_c("TCErrorCode %u",ref->getTCErrorCode());
8965 #endif
8966 
8967   ndbrequire(recvSignalUtilReq(signal, 1) == 0);
8968 }
execUTIL_RELEASE_CONF(Signal * signal)8969 void Dbdict::execUTIL_RELEASE_CONF(Signal *signal)
8970 {
8971   jamEntry();
8972   EVENT_TRACE;
8973   ndbrequire(false);
8974   ndbrequire(recvSignalUtilReq(signal, 0) == 0);
8975 }
execUTIL_RELEASE_REF(Signal * signal)8976 void Dbdict::execUTIL_RELEASE_REF(Signal *signal)
8977 {
8978   jamEntry();
8979   EVENT_TRACE;
8980   ndbrequire(false);
8981   ndbrequire(recvSignalUtilReq(signal, 1) == 0);
8982 }
8983 
8984 /**
8985  * MODULE: Create event
8986  *
8987  * Create event in DICT.
8988  *
8989  *
8990  * Request type in CREATE_EVNT signals:
8991  *
8992  * Signalflow see Dbdict.txt
8993  *
8994  */
8995 
8996 /*****************************************************************
8997  *
8998  * Systable stuff
8999  *
9000  */
9001 
9002 const Uint32 Dbdict::sysTab_NDBEVENTS_0_szs[EVENT_SYSTEM_TABLE_LENGTH] = {
9003   sizeof(((sysTab_NDBEVENTS_0*)0)->NAME),
9004   sizeof(((sysTab_NDBEVENTS_0*)0)->EVENT_TYPE),
9005   sizeof(((sysTab_NDBEVENTS_0*)0)->TABLEID),
9006   sizeof(((sysTab_NDBEVENTS_0*)0)->TABLEVERSION),
9007   sizeof(((sysTab_NDBEVENTS_0*)0)->TABLE_NAME),
9008   sizeof(((sysTab_NDBEVENTS_0*)0)->ATTRIBUTE_MASK),
9009   sizeof(((sysTab_NDBEVENTS_0*)0)->SUBID),
9010   sizeof(((sysTab_NDBEVENTS_0*)0)->SUBKEY)
9011 };
9012 
9013 void
prepareTransactionEventSysTable(Callback * pcallback,Signal * signal,Uint32 senderData,UtilPrepareReq::OperationTypeValue prepReq)9014 Dbdict::prepareTransactionEventSysTable (Callback *pcallback,
9015 					 Signal* signal,
9016 					 Uint32 senderData,
9017 					 UtilPrepareReq::OperationTypeValue prepReq)
9018 {
9019   // find table id for event system table
9020   DictObject * opj_ptr_p = get_object(EVENT_SYSTEM_TABLE_NAME,
9021 				      sizeof(EVENT_SYSTEM_TABLE_NAME));
9022 
9023   ndbrequire(opj_ptr_p != 0);
9024   TableRecordPtr tablePtr;
9025   c_tableRecordPool.getPtr(tablePtr, opj_ptr_p->m_id);
9026   ndbrequire(tablePtr.i != RNIL); // system table must exist
9027 
9028   Uint32 tableId = tablePtr.p->tableId; /* System table */
9029   Uint32 noAttr = tablePtr.p->noOfAttributes;
9030   ndbrequire(noAttr == EVENT_SYSTEM_TABLE_LENGTH);
9031 
9032   switch (prepReq) {
9033   case UtilPrepareReq::Update:
9034   case UtilPrepareReq::Insert:
9035   case UtilPrepareReq::Write:
9036   case UtilPrepareReq::Read:
9037     jam();
9038     break;
9039   case UtilPrepareReq::Delete:
9040     jam();
9041     noAttr = 1; // only involves Primary key which should be the first
9042     break;
9043   }
9044   prepareUtilTransaction(pcallback, signal, senderData, tableId, NULL,
9045 		      prepReq, noAttr, NULL, NULL);
9046 }
9047 
9048 void
prepareUtilTransaction(Callback * pcallback,Signal * signal,Uint32 senderData,Uint32 tableId,const char * tableName,UtilPrepareReq::OperationTypeValue prepReq,Uint32 noAttr,Uint32 attrIds[],const char * attrNames[])9049 Dbdict::prepareUtilTransaction(Callback *pcallback,
9050 			       Signal* signal,
9051 			       Uint32 senderData,
9052 			       Uint32 tableId,
9053 			       const char* tableName,
9054 			       UtilPrepareReq::OperationTypeValue prepReq,
9055 			       Uint32 noAttr,
9056 			       Uint32 attrIds[],
9057 			       const char *attrNames[])
9058 {
9059   jam();
9060   EVENT_TRACE;
9061 
9062   UtilPrepareReq * utilPrepareReq =
9063     (UtilPrepareReq *)signal->getDataPtrSend();
9064 
9065   utilPrepareReq->setSenderRef(reference());
9066   utilPrepareReq->setSenderData(senderData);
9067 
9068   const Uint32 pageSizeInWords = 128;
9069   Uint32 propPage[pageSizeInWords];
9070   LinearWriter w(&propPage[0],128);
9071   w.first();
9072   w.add(UtilPrepareReq::NoOfOperations, 1);
9073   w.add(UtilPrepareReq::OperationType, prepReq);
9074   if (tableName) {
9075     jam();
9076     w.add(UtilPrepareReq::TableName, tableName);
9077   } else {
9078     jam();
9079     w.add(UtilPrepareReq::TableId, tableId);
9080   }
9081   for(Uint32 i = 0; i < noAttr; i++)
9082     if (tableName) {
9083       jam();
9084       w.add(UtilPrepareReq::AttributeName, attrNames[i]);
9085     } else {
9086       if (attrIds) {
9087 	jam();
9088 	w.add(UtilPrepareReq::AttributeId, attrIds[i]);
9089       } else {
9090 	jam();
9091 	w.add(UtilPrepareReq::AttributeId, i);
9092       }
9093     }
9094 #ifdef EVENT_DEBUG
9095   // Debugging
9096   SimplePropertiesLinearReader reader(propPage, w.getWordsUsed());
9097   printf("Dict::prepareInsertTransactions: Sent SimpleProperties:\n");
9098   reader.printAll(ndbout);
9099 #endif
9100 
9101   struct LinearSectionPtr sectionsPtr[UtilPrepareReq::NoOfSections];
9102   sectionsPtr[UtilPrepareReq::PROPERTIES_SECTION].p = propPage;
9103   sectionsPtr[UtilPrepareReq::PROPERTIES_SECTION].sz = w.getWordsUsed();
9104 
9105   sendSignalUtilReq(pcallback, DBUTIL_REF, GSN_UTIL_PREPARE_REQ, signal,
9106 		    UtilPrepareReq::SignalLength, JBB,
9107 		    sectionsPtr, UtilPrepareReq::NoOfSections);
9108 }
9109 
9110 /*****************************************************************
9111  *
9112  * CREATE_EVNT_REQ has three types RT_CREATE, RT_GET (from user)
9113  * and RT_DICT_AFTER_GET send from master DICT to slaves
9114  *
9115  * This function just dscpaches these to
9116  *
9117  * createEvent_RT_USER_CREATE
9118  * createEvent_RT_USER_GET
9119  * createEvent_RT_DICT_AFTER_GET
9120  *
9121  * repectively
9122  *
9123  */
9124 
9125 void
execCREATE_EVNT_REQ(Signal * signal)9126 Dbdict::execCREATE_EVNT_REQ(Signal* signal)
9127 {
9128   jamEntry();
9129 
9130 #if 0
9131   {
9132     SafeCounterHandle handle;
9133     {
9134       SafeCounter tmp(c_counterMgr, handle);
9135       tmp.init<CreateEvntRef>(CMVMI, GSN_DUMP_STATE_ORD, /* senderData */ 13);
9136       tmp.clearWaitingFor();
9137       tmp.setWaitingFor(3);
9138       ndbrequire(!tmp.done());
9139       ndbout_c("Allocted");
9140     }
9141     ndbrequire(!handle.done());
9142     {
9143       SafeCounter tmp(c_counterMgr, handle);
9144       tmp.clearWaitingFor(3);
9145       ndbrequire(tmp.done());
9146       ndbout_c("Deallocted");
9147     }
9148     ndbrequire(handle.done());
9149   }
9150   {
9151     NodeBitmask nodes;
9152     nodes.clear();
9153 
9154     nodes.set(2);
9155     nodes.set(3);
9156     nodes.set(4);
9157     nodes.set(5);
9158 
9159     {
9160       Uint32 i = 0;
9161       while((i = nodes.find(i)) != NodeBitmask::NotFound){
9162 	ndbout_c("1 Node id = %u", i);
9163 	i++;
9164       }
9165     }
9166 
9167     NodeReceiverGroup rg(DBDICT, nodes);
9168     RequestTracker rt2;
9169     ndbrequire(rt2.done());
9170     ndbrequire(!rt2.hasRef());
9171     ndbrequire(!rt2.hasConf());
9172     rt2.init<CreateEvntRef>(c_counterMgr, rg, GSN_CREATE_EVNT_REF, 13);
9173 
9174     RequestTracker rt3;
9175     rt3.init<CreateEvntRef>(c_counterMgr, rg, GSN_CREATE_EVNT_REF, 13);
9176 
9177     ndbrequire(!rt2.done());
9178     ndbrequire(!rt3.done());
9179 
9180     rt2.reportRef(c_counterMgr, 2);
9181     rt3.reportConf(c_counterMgr, 2);
9182 
9183     ndbrequire(!rt2.done());
9184     ndbrequire(!rt3.done());
9185 
9186     rt2.reportConf(c_counterMgr, 3);
9187     rt3.reportConf(c_counterMgr, 3);
9188 
9189     ndbrequire(!rt2.done());
9190     ndbrequire(!rt3.done());
9191 
9192     rt2.reportConf(c_counterMgr, 4);
9193     rt3.reportConf(c_counterMgr, 4);
9194 
9195     ndbrequire(!rt2.done());
9196     ndbrequire(!rt3.done());
9197 
9198     rt2.reportConf(c_counterMgr, 5);
9199     rt3.reportConf(c_counterMgr, 5);
9200 
9201     ndbrequire(rt2.done());
9202     ndbrequire(rt3.done());
9203   }
9204 #endif
9205 
9206   if (! assembleFragments(signal)) {
9207     jam();
9208     return;
9209   }
9210 
9211   CreateEvntReq *req = (CreateEvntReq*)signal->getDataPtr();
9212   const CreateEvntReq::RequestType requestType = req->getRequestType();
9213   const Uint32                     requestFlag = req->getRequestFlag();
9214 
9215   if (refToBlock(signal->senderBlockRef()) != DBDICT &&
9216       getOwnNodeId() != c_masterNodeId)
9217   {
9218     jam();
9219     releaseSections(signal);
9220 
9221     CreateEvntRef * ref = (CreateEvntRef *)signal->getDataPtrSend();
9222     ref->setUserRef(reference());
9223     ref->setErrorCode(CreateEvntRef::NotMaster);
9224     ref->setErrorLine(__LINE__);
9225     ref->setErrorNode(reference());
9226     ref->setMasterNode(c_masterNodeId);
9227     sendSignal(signal->senderBlockRef(), GSN_CREATE_EVNT_REF, signal,
9228 	       CreateEvntRef::SignalLength2, JBB);
9229     return;
9230   }
9231 
9232   OpCreateEventPtr evntRecPtr;
9233   // Seize a Create Event record
9234   if (!c_opCreateEvent.seize(evntRecPtr)) {
9235     // Failed to allocate event record
9236     jam();
9237     releaseSections(signal);
9238 
9239     CreateEvntRef * ret = (CreateEvntRef *)signal->getDataPtrSend();
9240     ret->senderRef = reference();
9241     ret->setErrorCode(747);
9242     ret->setErrorLine(__LINE__);
9243     ret->setErrorNode(reference());
9244     sendSignal(signal->senderBlockRef(), GSN_CREATE_EVNT_REF, signal,
9245 	       CreateEvntRef::SignalLength, JBB);
9246     return;
9247   }
9248 
9249 #ifdef EVENT_DEBUG
9250   ndbout_c("DBDICT::execCREATE_EVNT_REQ from %u evntRecId = (%d)", refToNode(signal->getSendersBlockRef()), evntRecPtr.i);
9251 #endif
9252 
9253   ndbrequire(req->getUserRef() == signal->getSendersBlockRef());
9254 
9255   evntRecPtr.p->init(req,this);
9256 
9257   if (requestFlag & (Uint32)CreateEvntReq::RT_DICT_AFTER_GET) {
9258     jam();
9259     EVENT_TRACE;
9260     createEvent_RT_DICT_AFTER_GET(signal, evntRecPtr);
9261     return;
9262   }
9263   if (requestType == CreateEvntReq::RT_USER_GET) {
9264     jam();
9265     EVENT_TRACE;
9266     createEvent_RT_USER_GET(signal, evntRecPtr);
9267     return;
9268   }
9269   if (requestType == CreateEvntReq::RT_USER_CREATE) {
9270     jam();
9271     EVENT_TRACE;
9272     createEvent_RT_USER_CREATE(signal, evntRecPtr);
9273     return;
9274   }
9275 
9276 #ifdef EVENT_DEBUG
9277   ndbout << "Dbdict.cpp: Dbdict::execCREATE_EVNT_REQ other" << endl;
9278 #endif
9279   jam();
9280   releaseSections(signal);
9281 
9282   evntRecPtr.p->m_errorCode = 1;
9283   evntRecPtr.p->m_errorLine = __LINE__;
9284   evntRecPtr.p->m_errorNode = reference();
9285 
9286   createEvent_sendReply(signal, evntRecPtr);
9287 }
9288 
9289 /********************************************************************
9290  *
9291  * Event creation
9292  *
9293  *****************************************************************/
9294 
9295 void
createEvent_RT_USER_CREATE(Signal * signal,OpCreateEventPtr evntRecPtr)9296 Dbdict::createEvent_RT_USER_CREATE(Signal* signal, OpCreateEventPtr evntRecPtr)
9297 {
9298   jam();
9299   DBUG_ENTER("Dbdict::createEvent_RT_USER_CREATE");
9300   evntRecPtr.p->m_request.setUserRef(signal->senderBlockRef());
9301 
9302 #ifdef EVENT_DEBUG
9303   ndbout << "Dbdict.cpp: Dbdict::execCREATE_EVNT_REQ RT_USER" << endl;
9304   char buf[128] = {0};
9305   AttributeMask mask = evntRecPtr.p->m_request.getAttrListBitmask();
9306   mask.getText(buf);
9307   ndbout_c("mask = %s", buf);
9308 #endif
9309 
9310   // Interpret the long signal
9311 
9312   SegmentedSectionPtr ssPtr;
9313   // save name and event properties
9314   signal->getSection(ssPtr, CreateEvntReq::EVENT_NAME_SECTION);
9315 
9316   SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
9317 #ifdef EVENT_DEBUG
9318   r0.printAll(ndbout);
9319 #endif
9320     // event name
9321   if ((!r0.first()) ||
9322       (r0.getValueType() != SimpleProperties::StringValue) ||
9323       (r0.getValueLen() <= 0)) {
9324     jam();
9325     releaseSections(signal);
9326 
9327     evntRecPtr.p->m_errorCode = 1;
9328     evntRecPtr.p->m_errorLine = __LINE__;
9329     evntRecPtr.p->m_errorNode = reference();
9330 
9331     createEvent_sendReply(signal, evntRecPtr);
9332     DBUG_VOID_RETURN;
9333   }
9334   r0.getString(evntRecPtr.p->m_eventRec.NAME);
9335   {
9336     int len = strlen(evntRecPtr.p->m_eventRec.NAME);
9337     memset(evntRecPtr.p->m_eventRec.NAME+len, 0, MAX_TAB_NAME_SIZE-len);
9338 #ifdef EVENT_DEBUG
9339     printf("CreateEvntReq::RT_USER_CREATE; EventName %s, len %u\n",
9340 	   evntRecPtr.p->m_eventRec.NAME, len);
9341     for(int i = 0; i < MAX_TAB_NAME_SIZE/4; i++)
9342       printf("H'%.8x ", ((Uint32*)evntRecPtr.p->m_eventRec.NAME)[i]);
9343     printf("\n");
9344 #endif
9345   }
9346   // table name
9347   if ((!r0.next()) ||
9348       (r0.getValueType() != SimpleProperties::StringValue) ||
9349       (r0.getValueLen() <= 0)) {
9350     jam();
9351     releaseSections(signal);
9352 
9353     evntRecPtr.p->m_errorCode = 1;
9354     evntRecPtr.p->m_errorLine = __LINE__;
9355     evntRecPtr.p->m_errorNode = reference();
9356 
9357     createEvent_sendReply(signal, evntRecPtr);
9358     DBUG_VOID_RETURN;
9359   }
9360   r0.getString(evntRecPtr.p->m_eventRec.TABLE_NAME);
9361   {
9362     int len = strlen(evntRecPtr.p->m_eventRec.TABLE_NAME);
9363     memset(evntRecPtr.p->m_eventRec.TABLE_NAME+len, 0, MAX_TAB_NAME_SIZE-len);
9364   }
9365 
9366   releaseSections(signal);
9367 
9368   // Send request to SUMA
9369 
9370   CreateSubscriptionIdReq * sumaIdReq =
9371     (CreateSubscriptionIdReq *)signal->getDataPtrSend();
9372 
9373   // make sure we save the original sender for later
9374   sumaIdReq->senderRef  = reference();
9375   sumaIdReq->senderData = evntRecPtr.i;
9376 #ifdef EVENT_DEBUG
9377   ndbout << "sumaIdReq->senderData = " << sumaIdReq->senderData << endl;
9378 #endif
9379   sendSignal(SUMA_REF, GSN_CREATE_SUBID_REQ, signal,
9380 	     CreateSubscriptionIdReq::SignalLength, JBB);
9381   // we should now return in either execCREATE_SUBID_CONF
9382   // or execCREATE_SUBID_REF
9383   DBUG_VOID_RETURN;
9384 }
9385 
execCREATE_SUBID_REF(Signal * signal)9386 void Dbdict::execCREATE_SUBID_REF(Signal* signal)
9387 {
9388   jamEntry();
9389   DBUG_ENTER("Dbdict::execCREATE_SUBID_REF");
9390   CreateSubscriptionIdRef * const ref =
9391     (CreateSubscriptionIdRef *)signal->getDataPtr();
9392   OpCreateEventPtr evntRecPtr;
9393 
9394   evntRecPtr.i = ref->senderData;
9395   ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
9396 
9397   if (ref->errorCode)
9398   {
9399     evntRecPtr.p->m_errorCode = ref->errorCode;
9400     evntRecPtr.p->m_errorLine = __LINE__;
9401   }
9402   else
9403   {
9404     evntRecPtr.p->m_errorCode = 1;
9405     evntRecPtr.p->m_errorLine = __LINE__;
9406   }
9407   evntRecPtr.p->m_errorNode = reference();
9408 
9409   createEvent_sendReply(signal, evntRecPtr);
9410   DBUG_VOID_RETURN;
9411 }
9412 
execCREATE_SUBID_CONF(Signal * signal)9413 void Dbdict::execCREATE_SUBID_CONF(Signal* signal)
9414 {
9415   jamEntry();
9416   DBUG_ENTER("Dbdict::execCREATE_SUBID_CONF");
9417 
9418   CreateSubscriptionIdConf const * sumaIdConf =
9419     (CreateSubscriptionIdConf *)signal->getDataPtr();
9420 
9421   Uint32 evntRecId = sumaIdConf->senderData;
9422   OpCreateEvent *evntRec;
9423 
9424   ndbrequire((evntRec = c_opCreateEvent.getPtr(evntRecId)) != NULL);
9425 
9426   evntRec->m_request.setEventId(sumaIdConf->subscriptionId);
9427   evntRec->m_request.setEventKey(sumaIdConf->subscriptionKey);
9428 
9429   releaseSections(signal);
9430 
9431   Callback c = { safe_cast(&Dbdict::createEventUTIL_PREPARE), 0 };
9432 
9433   prepareTransactionEventSysTable(&c, signal, evntRecId,
9434 				  UtilPrepareReq::Insert);
9435   DBUG_VOID_RETURN;
9436 }
9437 
9438 void
createEventComplete_RT_USER_CREATE(Signal * signal,OpCreateEventPtr evntRecPtr)9439 Dbdict::createEventComplete_RT_USER_CREATE(Signal* signal,
9440 					   OpCreateEventPtr evntRecPtr){
9441   jam();
9442   createEvent_sendReply(signal, evntRecPtr);
9443 }
9444 
9445 /*********************************************************************
9446  *
9447  * UTIL_PREPARE, UTIL_EXECUTE
9448  *
9449  * insert or read systable NDB$EVENTS_0
9450  */
9451 
interpretUtilPrepareErrorCode(UtilPrepareRef::ErrorCode errorCode,Uint32 & error,Uint32 & line)9452 void interpretUtilPrepareErrorCode(UtilPrepareRef::ErrorCode errorCode,
9453 				   Uint32& error, Uint32& line)
9454 {
9455   DBUG_ENTER("interpretUtilPrepareErrorCode");
9456   switch (errorCode) {
9457   case UtilPrepareRef::NO_ERROR:
9458     jam();
9459     error = 1;
9460     line = __LINE__;
9461     DBUG_VOID_RETURN;
9462   case UtilPrepareRef::PREPARE_SEIZE_ERROR:
9463     jam();
9464     error = 748;
9465     line = __LINE__;
9466     DBUG_VOID_RETURN;
9467   case UtilPrepareRef::PREPARE_PAGES_SEIZE_ERROR:
9468     jam();
9469     error = 1;
9470     line = __LINE__;
9471     DBUG_VOID_RETURN;
9472   case UtilPrepareRef::PREPARED_OPERATION_SEIZE_ERROR:
9473     jam();
9474     error = 1;
9475     line = __LINE__;
9476     DBUG_VOID_RETURN;
9477   case UtilPrepareRef::DICT_TAB_INFO_ERROR:
9478     jam();
9479     error = 1;
9480     line = __LINE__;
9481     DBUG_VOID_RETURN;
9482   case UtilPrepareRef::MISSING_PROPERTIES_SECTION:
9483     jam();
9484     error = 1;
9485     line = __LINE__;
9486     DBUG_VOID_RETURN;
9487   default:
9488     jam();
9489     error = 1;
9490     line = __LINE__;
9491     DBUG_VOID_RETURN;
9492   }
9493   DBUG_VOID_RETURN;
9494 }
9495 
9496 void
createEventUTIL_PREPARE(Signal * signal,Uint32 callbackData,Uint32 returnCode)9497 Dbdict::createEventUTIL_PREPARE(Signal* signal,
9498 				Uint32 callbackData,
9499 				Uint32 returnCode)
9500 {
9501   jam();
9502   EVENT_TRACE;
9503   if (returnCode == 0) {
9504     UtilPrepareConf* const req = (UtilPrepareConf*)signal->getDataPtr();
9505     OpCreateEventPtr evntRecPtr;
9506     jam();
9507     evntRecPtr.i = req->getSenderData();
9508     const Uint32 prepareId = req->getPrepareId();
9509 
9510     ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
9511 
9512     Callback c = { safe_cast(&Dbdict::createEventUTIL_EXECUTE), 0 };
9513 
9514     switch (evntRecPtr.p->m_requestType) {
9515     case CreateEvntReq::RT_USER_GET:
9516       jam();
9517       executeTransEventSysTable(&c, signal,
9518 				evntRecPtr.i, evntRecPtr.p->m_eventRec,
9519 				prepareId, UtilPrepareReq::Read);
9520       break;
9521     case CreateEvntReq::RT_USER_CREATE:
9522       {
9523 	evntRecPtr.p->m_eventRec.EVENT_TYPE =
9524           evntRecPtr.p->m_request.getEventType() | evntRecPtr.p->m_request.getReportFlags();
9525 	evntRecPtr.p->m_eventRec.TABLEID  = evntRecPtr.p->m_request.getTableId();
9526 	evntRecPtr.p->m_eventRec.TABLEVERSION=evntRecPtr.p->m_request.getTableVersion();
9527 	AttributeMask m = evntRecPtr.p->m_request.getAttrListBitmask();
9528 	memcpy(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK, &m,
9529 	       sizeof(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK));
9530 	evntRecPtr.p->m_eventRec.SUBID  = evntRecPtr.p->m_request.getEventId();
9531 	evntRecPtr.p->m_eventRec.SUBKEY = evntRecPtr.p->m_request.getEventKey();
9532 	DBUG_PRINT("info",
9533 		   ("CREATE: event name: %s table name: %s table id: %u table version: %u",
9534 		    evntRecPtr.p->m_eventRec.NAME,
9535 		    evntRecPtr.p->m_eventRec.TABLE_NAME,
9536 		    evntRecPtr.p->m_eventRec.TABLEID,
9537 		    evntRecPtr.p->m_eventRec.TABLEVERSION));
9538 
9539       }
9540       jam();
9541       executeTransEventSysTable(&c, signal,
9542 				evntRecPtr.i, evntRecPtr.p->m_eventRec,
9543 				prepareId, UtilPrepareReq::Insert);
9544       break;
9545     default:
9546 #ifdef EVENT_DEBUG
9547       printf("type = %d\n", evntRecPtr.p->m_requestType);
9548       printf("bet type = %d\n", CreateEvntReq::RT_USER_GET);
9549       printf("create type = %d\n", CreateEvntReq::RT_USER_CREATE);
9550 #endif
9551       ndbrequire(false);
9552     }
9553   } else { // returnCode != 0
9554     UtilPrepareRef* const ref = (UtilPrepareRef*)signal->getDataPtr();
9555 
9556     const UtilPrepareRef::ErrorCode errorCode =
9557       (UtilPrepareRef::ErrorCode)ref->getErrorCode();
9558 
9559     OpCreateEventPtr evntRecPtr;
9560     evntRecPtr.i = ref->getSenderData();
9561     ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
9562 
9563     interpretUtilPrepareErrorCode(errorCode, evntRecPtr.p->m_errorCode,
9564 				  evntRecPtr.p->m_errorLine);
9565     evntRecPtr.p->m_errorNode = reference();
9566 
9567     createEvent_sendReply(signal, evntRecPtr);
9568   }
9569 }
9570 
executeTransEventSysTable(Callback * pcallback,Signal * signal,const Uint32 ptrI,sysTab_NDBEVENTS_0 & m_eventRec,const Uint32 prepareId,UtilPrepareReq::OperationTypeValue prepReq)9571 void Dbdict::executeTransEventSysTable(Callback *pcallback, Signal *signal,
9572 				       const Uint32 ptrI,
9573 				       sysTab_NDBEVENTS_0& m_eventRec,
9574 				       const Uint32 prepareId,
9575 				       UtilPrepareReq::OperationTypeValue prepReq)
9576 {
9577   jam();
9578   const Uint32 noAttr = EVENT_SYSTEM_TABLE_LENGTH;
9579   Uint32 total_len = 0;
9580 
9581   Uint32* attrHdr = signal->theData + 25;
9582   Uint32* attrPtr = attrHdr;
9583 
9584   Uint32 id=0;
9585   // attribute 0 event name: Primary Key
9586   {
9587     AttributeHeader::init(attrPtr, id, sysTab_NDBEVENTS_0_szs[id]);
9588     total_len += sysTab_NDBEVENTS_0_szs[id];
9589     attrPtr++; id++;
9590   }
9591 
9592   switch (prepReq) {
9593   case UtilPrepareReq::Read:
9594     jam();
9595     EVENT_TRACE;
9596     // no more
9597     while ( id < noAttr )
9598       AttributeHeader::init(attrPtr++, id++, 0);
9599     ndbrequire(id == (Uint32) noAttr);
9600     break;
9601   case UtilPrepareReq::Insert:
9602     jam();
9603     EVENT_TRACE;
9604     while ( id < noAttr ) {
9605       AttributeHeader::init(attrPtr, id, sysTab_NDBEVENTS_0_szs[id]);
9606       total_len += sysTab_NDBEVENTS_0_szs[id];
9607       attrPtr++; id++;
9608     }
9609     ndbrequire(id == (Uint32) noAttr);
9610     break;
9611   case UtilPrepareReq::Delete:
9612     ndbrequire(id == 1);
9613     break;
9614   default:
9615     ndbrequire(false);
9616   }
9617 
9618   LinearSectionPtr headerPtr;
9619   LinearSectionPtr dataPtr;
9620 
9621   headerPtr.p = attrHdr;
9622   headerPtr.sz = noAttr;
9623 
9624   dataPtr.p = (Uint32*)&m_eventRec;
9625   dataPtr.sz = total_len/4;
9626 
9627   ndbrequire((total_len == sysTab_NDBEVENTS_0_szs[0]) ||
9628 	     (total_len == sizeof(sysTab_NDBEVENTS_0)));
9629 
9630 #if 0
9631     printf("Header size %u\n", headerPtr.sz);
9632     for(int i = 0; i < (int)headerPtr.sz; i++)
9633       printf("H'%.8x ", attrHdr[i]);
9634     printf("\n");
9635 
9636     printf("Data size %u\n", dataPtr.sz);
9637     for(int i = 0; i < (int)dataPtr.sz; i++)
9638       printf("H'%.8x ", dataPage[i]);
9639     printf("\n");
9640 #endif
9641 
9642   executeTransaction(pcallback, signal,
9643 		     ptrI,
9644 		     prepareId,
9645 		     id,
9646 		     headerPtr,
9647 		     dataPtr);
9648 }
9649 
executeTransaction(Callback * pcallback,Signal * signal,Uint32 senderData,Uint32 prepareId,Uint32 noAttr,LinearSectionPtr headerPtr,LinearSectionPtr dataPtr)9650 void Dbdict::executeTransaction(Callback *pcallback,
9651 				Signal* signal,
9652 				Uint32 senderData,
9653 				Uint32 prepareId,
9654 				Uint32 noAttr,
9655 				LinearSectionPtr headerPtr,
9656 				LinearSectionPtr dataPtr)
9657 {
9658   jam();
9659   EVENT_TRACE;
9660 
9661   UtilExecuteReq * utilExecuteReq =
9662     (UtilExecuteReq *)signal->getDataPtrSend();
9663 
9664   utilExecuteReq->setSenderRef(reference());
9665   utilExecuteReq->setSenderData(senderData);
9666   utilExecuteReq->setPrepareId(prepareId);
9667   utilExecuteReq->setReleaseFlag(); // must be done after setting prepareId
9668 
9669 #if 0
9670   printf("Header size %u\n", headerPtr.sz);
9671   for(int i = 0; i < (int)headerPtr.sz; i++)
9672     printf("H'%.8x ", headerBuffer[i]);
9673   printf("\n");
9674 
9675   printf("Data size %u\n", dataPtr.sz);
9676   for(int i = 0; i < (int)dataPtr.sz; i++)
9677     printf("H'%.8x ", dataBuffer[i]);
9678   printf("\n");
9679 #endif
9680 
9681   struct LinearSectionPtr sectionsPtr[UtilExecuteReq::NoOfSections];
9682   sectionsPtr[UtilExecuteReq::HEADER_SECTION].p = headerPtr.p;
9683   sectionsPtr[UtilExecuteReq::HEADER_SECTION].sz = noAttr;
9684   sectionsPtr[UtilExecuteReq::DATA_SECTION].p = dataPtr.p;
9685   sectionsPtr[UtilExecuteReq::DATA_SECTION].sz = dataPtr.sz;
9686 
9687   sendSignalUtilReq(pcallback, DBUTIL_REF, GSN_UTIL_EXECUTE_REQ, signal,
9688 		    UtilExecuteReq::SignalLength, JBB,
9689 		    sectionsPtr, UtilExecuteReq::NoOfSections);
9690 }
9691 
parseReadEventSys(Signal * signal,sysTab_NDBEVENTS_0 & m_eventRec)9692 void Dbdict::parseReadEventSys(Signal* signal, sysTab_NDBEVENTS_0& m_eventRec)
9693 {
9694   SegmentedSectionPtr headerPtr, dataPtr;
9695   jam();
9696   signal->getSection(headerPtr, UtilExecuteReq::HEADER_SECTION);
9697   SectionReader headerReader(headerPtr, getSectionSegmentPool());
9698 
9699   signal->getSection(dataPtr, UtilExecuteReq::DATA_SECTION);
9700   SectionReader dataReader(dataPtr, getSectionSegmentPool());
9701 
9702   AttributeHeader header;
9703   Uint32 *dst = (Uint32*)&m_eventRec;
9704 
9705   for (int i = 0; i < EVENT_SYSTEM_TABLE_LENGTH; i++) {
9706     headerReader.getWord((Uint32 *)&header);
9707     int sz = header.getDataSize();
9708     for (int i=0; i < sz; i++)
9709       dataReader.getWord(dst++);
9710   }
9711 
9712   ndbrequire( ((char*)dst-(char*)&m_eventRec) == sizeof(m_eventRec) );
9713 
9714   releaseSections(signal);
9715 }
9716 
createEventUTIL_EXECUTE(Signal * signal,Uint32 callbackData,Uint32 returnCode)9717 void Dbdict::createEventUTIL_EXECUTE(Signal *signal,
9718 				     Uint32 callbackData,
9719 				     Uint32 returnCode)
9720 {
9721   jam();
9722   EVENT_TRACE;
9723   if (returnCode == 0) {
9724     // Entry into system table all set
9725     UtilExecuteConf* const conf = (UtilExecuteConf*)signal->getDataPtr();
9726     jam();
9727     OpCreateEventPtr evntRecPtr;
9728     evntRecPtr.i = conf->getSenderData();
9729 
9730     ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
9731     OpCreateEvent *evntRec = evntRecPtr.p;
9732 
9733     switch (evntRec->m_requestType) {
9734     case CreateEvntReq::RT_USER_GET: {
9735       parseReadEventSys(signal, evntRecPtr.p->m_eventRec);
9736 
9737       evntRec->m_request.setEventType(evntRecPtr.p->m_eventRec.EVENT_TYPE);
9738       evntRec->m_request.setReportFlags(evntRecPtr.p->m_eventRec.EVENT_TYPE);
9739       evntRec->m_request.setTableId(evntRecPtr.p->m_eventRec.TABLEID);
9740       evntRec->m_request.setTableVersion(evntRecPtr.p->m_eventRec.TABLEVERSION);
9741       evntRec->m_request.setAttrListBitmask(*(AttributeMask*)
9742 					    evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK);
9743       evntRec->m_request.setEventId(evntRecPtr.p->m_eventRec.SUBID);
9744       evntRec->m_request.setEventKey(evntRecPtr.p->m_eventRec.SUBKEY);
9745 
9746       DBUG_PRINT("info",
9747 		 ("GET: event name: %s table name: %s table id: %u table version: %u",
9748 		  evntRecPtr.p->m_eventRec.NAME,
9749 		  evntRecPtr.p->m_eventRec.TABLE_NAME,
9750 		  evntRecPtr.p->m_eventRec.TABLEID,
9751 		  evntRecPtr.p->m_eventRec.TABLEVERSION));
9752 
9753       // find table id for event table
9754       DictObject* obj_ptr_p = get_object(evntRecPtr.p->m_eventRec.TABLE_NAME);
9755       if(!obj_ptr_p){
9756 	jam();
9757 	evntRecPtr.p->m_errorCode = 723;
9758 	evntRecPtr.p->m_errorLine = __LINE__;
9759 	evntRecPtr.p->m_errorNode = reference();
9760 
9761 	createEvent_sendReply(signal, evntRecPtr);
9762 	return;
9763       }
9764 
9765       TableRecordPtr tablePtr;
9766       c_tableRecordPool.getPtr(tablePtr, obj_ptr_p->m_id);
9767       evntRec->m_request.setTableId(tablePtr.p->tableId);
9768       evntRec->m_request.setTableVersion(tablePtr.p->tableVersion);
9769 
9770       createEventComplete_RT_USER_GET(signal, evntRecPtr);
9771       return;
9772     }
9773     case CreateEvntReq::RT_USER_CREATE: {
9774 #ifdef EVENT_DEBUG
9775       printf("create type = %d\n", CreateEvntReq::RT_USER_CREATE);
9776 #endif
9777       jam();
9778       createEventComplete_RT_USER_CREATE(signal, evntRecPtr);
9779       return;
9780     }
9781       break;
9782     default:
9783       ndbrequire(false);
9784     }
9785   } else { // returnCode != 0
9786     UtilExecuteRef * const ref = (UtilExecuteRef *)signal->getDataPtr();
9787     OpCreateEventPtr evntRecPtr;
9788     evntRecPtr.i = ref->getSenderData();
9789     ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
9790     jam();
9791     evntRecPtr.p->m_errorNode = reference();
9792     evntRecPtr.p->m_errorLine = __LINE__;
9793 
9794     switch (ref->getErrorCode()) {
9795     case UtilExecuteRef::TCError:
9796       switch (ref->getTCErrorCode()) {
9797       case ZNOT_FOUND:
9798 	jam();
9799 	evntRecPtr.p->m_errorCode = 4710;
9800 	break;
9801       case ZALREADYEXIST:
9802 	jam();
9803 	evntRecPtr.p->m_errorCode = 746;
9804 	break;
9805       default:
9806 	jam();
9807 	evntRecPtr.p->m_errorCode = ref->getTCErrorCode();
9808 	break;
9809       }
9810       break;
9811     default:
9812       jam();
9813       evntRecPtr.p->m_errorCode = ref->getErrorCode();
9814       break;
9815     }
9816 
9817     createEvent_sendReply(signal, evntRecPtr);
9818   }
9819 }
9820 
9821 /***********************************************************************
9822  *
9823  * NdbEventOperation, reading systable, creating event in suma
9824  *
9825  */
9826 
9827 void
createEvent_RT_USER_GET(Signal * signal,OpCreateEventPtr evntRecPtr)9828 Dbdict::createEvent_RT_USER_GET(Signal* signal, OpCreateEventPtr evntRecPtr){
9829   jam();
9830   EVENT_TRACE;
9831 #ifdef EVENT_PH2_DEBUG
9832   ndbout_c("DBDICT(Coordinator) got GSN_CREATE_EVNT_REQ::RT_USER_GET evntRecPtr.i = (%d), ref = %u", evntRecPtr.i, evntRecPtr.p->m_request.getUserRef());
9833 #endif
9834 
9835   SegmentedSectionPtr ssPtr;
9836 
9837   signal->getSection(ssPtr, 0);
9838 
9839   SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
9840 #ifdef EVENT_DEBUG
9841   r0.printAll(ndbout);
9842 #endif
9843   if ((!r0.first()) ||
9844       (r0.getValueType() != SimpleProperties::StringValue) ||
9845       (r0.getValueLen() <= 0)) {
9846     jam();
9847     releaseSections(signal);
9848 
9849     evntRecPtr.p->m_errorCode = 1;
9850     evntRecPtr.p->m_errorLine = __LINE__;
9851     evntRecPtr.p->m_errorNode = reference();
9852 
9853     createEvent_sendReply(signal, evntRecPtr);
9854     return;
9855   }
9856 
9857   r0.getString(evntRecPtr.p->m_eventRec.NAME);
9858   int len = strlen(evntRecPtr.p->m_eventRec.NAME);
9859   memset(evntRecPtr.p->m_eventRec.NAME+len, 0, MAX_TAB_NAME_SIZE-len);
9860 
9861   releaseSections(signal);
9862 
9863   Callback c = { safe_cast(&Dbdict::createEventUTIL_PREPARE), 0 };
9864 
9865   prepareTransactionEventSysTable(&c, signal, evntRecPtr.i,
9866 				  UtilPrepareReq::Read);
9867   /*
9868    * Will read systable and fill an OpCreateEventPtr
9869    * and return below
9870    */
9871 }
9872 
9873 void
createEventComplete_RT_USER_GET(Signal * signal,OpCreateEventPtr evntRecPtr)9874 Dbdict::createEventComplete_RT_USER_GET(Signal* signal,
9875 					OpCreateEventPtr evntRecPtr){
9876   jam();
9877 
9878   // Send to oneself and the other DICT's
9879   CreateEvntReq * req = (CreateEvntReq *)signal->getDataPtrSend();
9880 
9881   *req = evntRecPtr.p->m_request;
9882   req->senderRef = reference();
9883   req->senderData = evntRecPtr.i;
9884 
9885   req->addRequestFlag(CreateEvntReq::RT_DICT_AFTER_GET);
9886 
9887 #ifdef EVENT_PH2_DEBUG
9888   ndbout_c("DBDICT(Coordinator) sending GSN_CREATE_EVNT_REQ::RT_DICT_AFTER_GET to DBDICT participants evntRecPtr.i = (%d)", evntRecPtr.i);
9889 #endif
9890 
9891   NodeReceiverGroup rg(DBDICT, c_aliveNodes);
9892   RequestTracker & p = evntRecPtr.p->m_reqTracker;
9893   if (!p.init<CreateEvntRef>(c_counterMgr, rg, GSN_CREATE_EVNT_REF,
9894 			     evntRecPtr.i))
9895   {
9896     jam();
9897     evntRecPtr.p->m_errorCode = 701;
9898     createEvent_sendReply(signal, evntRecPtr);
9899     return;
9900   }
9901 
9902   sendSignal(rg, GSN_CREATE_EVNT_REQ, signal, CreateEvntReq::SignalLength, JBB);
9903 }
9904 
9905 void
createEvent_nodeFailCallback(Signal * signal,Uint32 eventRecPtrI,Uint32 returnCode)9906 Dbdict::createEvent_nodeFailCallback(Signal* signal, Uint32 eventRecPtrI,
9907 				     Uint32 returnCode){
9908   OpCreateEventPtr evntRecPtr;
9909   c_opCreateEvent.getPtr(evntRecPtr, eventRecPtrI);
9910   createEvent_sendReply(signal, evntRecPtr);
9911 }
9912 
execCREATE_EVNT_REF(Signal * signal)9913 void Dbdict::execCREATE_EVNT_REF(Signal* signal)
9914 {
9915   jamEntry();
9916   EVENT_TRACE;
9917   CreateEvntRef * const ref = (CreateEvntRef *)signal->getDataPtr();
9918   OpCreateEventPtr evntRecPtr;
9919 
9920   evntRecPtr.i = ref->getUserData();
9921 
9922   ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
9923 
9924 #ifdef EVENT_PH2_DEBUG
9925   ndbout_c("DBDICT(Coordinator) got GSN_CREATE_EVNT_REF evntRecPtr.i = (%d)", evntRecPtr.i);
9926 #endif
9927 
9928   if (ref->errorCode == CreateEvntRef::NF_FakeErrorREF){
9929     jam();
9930     evntRecPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(ref->senderRef));
9931   } else {
9932     jam();
9933     evntRecPtr.p->m_reqTracker.reportRef(c_counterMgr, refToNode(ref->senderRef));
9934   }
9935   createEvent_sendReply(signal, evntRecPtr);
9936 
9937   return;
9938 }
9939 
execCREATE_EVNT_CONF(Signal * signal)9940 void Dbdict::execCREATE_EVNT_CONF(Signal* signal)
9941 {
9942   jamEntry();
9943   EVENT_TRACE;
9944   CreateEvntConf * const conf = (CreateEvntConf *)signal->getDataPtr();
9945   OpCreateEventPtr evntRecPtr;
9946 
9947   evntRecPtr.i = conf->getUserData();
9948 
9949   ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
9950 
9951 #ifdef EVENT_PH2_DEBUG
9952   ndbout_c("DBDICT(Coordinator) got GSN_CREATE_EVNT_CONF evntRecPtr.i = (%d)", evntRecPtr.i);
9953 #endif
9954 
9955   evntRecPtr.p->m_reqTracker.reportConf(c_counterMgr, refToNode(conf->senderRef));
9956 
9957   // we will only have a valid tablename if it the master DICT sending this
9958   // but that's ok
9959   LinearSectionPtr ptr[1];
9960   ptr[0].p = (Uint32 *)evntRecPtr.p->m_eventRec.TABLE_NAME;
9961   ptr[0].sz =
9962     (strlen(evntRecPtr.p->m_eventRec.TABLE_NAME)+4)/4; // to make sure we have a null
9963 
9964   createEvent_sendReply(signal, evntRecPtr, ptr, 1);
9965 
9966   return;
9967 }
9968 
9969 /************************************************
9970  *
9971  * Participant stuff
9972  *
9973  */
9974 
9975 void
createEvent_RT_DICT_AFTER_GET(Signal * signal,OpCreateEventPtr evntRecPtr)9976 Dbdict::createEvent_RT_DICT_AFTER_GET(Signal* signal, OpCreateEventPtr evntRecPtr){
9977   DBUG_ENTER("Dbdict::createEvent_RT_DICT_AFTER_GET");
9978   jam();
9979   evntRecPtr.p->m_request.setUserRef(signal->senderBlockRef());
9980 
9981 #ifdef EVENT_PH2_DEBUG
9982   ndbout_c("DBDICT(Participant) got CREATE_EVNT_REQ::RT_DICT_AFTER_GET evntRecPtr.i = (%d)", evntRecPtr.i);
9983 #endif
9984 
9985   // the signal comes from the DICT block that got the first user request!
9986   // This code runs on all DICT nodes, including oneself
9987 
9988   // Seize a Create Event record, the Coordinator will now have two seized
9989   // but that's ok, it's like a recursion
9990 
9991   CRASH_INSERTION2(6009, getOwnNodeId() != c_masterNodeId);
9992 
9993   SubCreateReq * sumaReq = (SubCreateReq *)signal->getDataPtrSend();
9994 
9995   sumaReq->senderRef        = reference(); // reference to DICT
9996   sumaReq->senderData       = evntRecPtr.i;
9997   sumaReq->subscriptionId   = evntRecPtr.p->m_request.getEventId();
9998   sumaReq->subscriptionKey  = evntRecPtr.p->m_request.getEventKey();
9999   sumaReq->subscriptionType = SubCreateReq::TableEvent;
10000   if (evntRecPtr.p->m_request.getReportAll())
10001     sumaReq->subscriptionType|= SubCreateReq::ReportAll;
10002   if (evntRecPtr.p->m_request.getReportSubscribe())
10003     sumaReq->subscriptionType|= SubCreateReq::ReportSubscribe;
10004   sumaReq->tableId          = evntRecPtr.p->m_request.getTableId();
10005 
10006 #ifdef EVENT_PH2_DEBUG
10007   ndbout_c("sending GSN_SUB_CREATE_REQ");
10008 #endif
10009 
10010   sendSignal(SUMA_REF, GSN_SUB_CREATE_REQ, signal,
10011 	     SubCreateReq::SignalLength, JBB);
10012   DBUG_VOID_RETURN;
10013 }
10014 
execSUB_CREATE_REF(Signal * signal)10015 void Dbdict::execSUB_CREATE_REF(Signal* signal)
10016 {
10017   jamEntry();
10018   DBUG_ENTER("Dbdict::execSUB_CREATE_REF");
10019 
10020   SubCreateRef * const ref = (SubCreateRef *)signal->getDataPtr();
10021   OpCreateEventPtr evntRecPtr;
10022 
10023   evntRecPtr.i = ref->senderData;
10024   ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
10025 
10026   if (ref->errorCode == 1415) {
10027     jam();
10028     createEvent_sendReply(signal, evntRecPtr);
10029     DBUG_VOID_RETURN;
10030   }
10031 
10032   if (ref->errorCode)
10033   {
10034     evntRecPtr.p->m_errorCode = ref->errorCode;
10035     evntRecPtr.p->m_errorLine = __LINE__;
10036   }
10037   else
10038   {
10039     evntRecPtr.p->m_errorCode = 1;
10040     evntRecPtr.p->m_errorLine = __LINE__;
10041   }
10042   evntRecPtr.p->m_errorNode = reference();
10043 
10044   createEvent_sendReply(signal, evntRecPtr);
10045   DBUG_VOID_RETURN;
10046 }
10047 
execSUB_CREATE_CONF(Signal * signal)10048 void Dbdict::execSUB_CREATE_CONF(Signal* signal)
10049 {
10050   jamEntry();
10051   DBUG_ENTER("Dbdict::execSUB_CREATE_CONF");
10052   EVENT_TRACE;
10053 
10054   SubCreateConf * const sumaConf = (SubCreateConf *)signal->getDataPtr();
10055   OpCreateEventPtr evntRecPtr;
10056   evntRecPtr.i = sumaConf->senderData;
10057   ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
10058 
10059   createEvent_sendReply(signal, evntRecPtr);
10060 
10061   DBUG_VOID_RETURN;
10062 }
10063 
10064 /****************************************************
10065  *
10066  * common create reply method
10067  *
10068  *******************************************************/
10069 
createEvent_sendReply(Signal * signal,OpCreateEventPtr evntRecPtr,LinearSectionPtr * ptr,int noLSP)10070 void Dbdict::createEvent_sendReply(Signal* signal,
10071 				   OpCreateEventPtr evntRecPtr,
10072 				   LinearSectionPtr *ptr, int noLSP)
10073 {
10074   jam();
10075   EVENT_TRACE;
10076 
10077   // check if we're ready to sent reply
10078   // if we are the master dict we might be waiting for conf/ref
10079 
10080   if (!evntRecPtr.p->m_reqTracker.done()) {
10081     jam();
10082     return; // there's more to come
10083   }
10084 
10085   if (evntRecPtr.p->m_reqTracker.hasRef()) {
10086     ptr = NULL; // we don't want to return anything if there's an error
10087     if (!evntRecPtr.p->hasError()) {
10088       evntRecPtr.p->m_errorCode = 1;
10089       evntRecPtr.p->m_errorLine = __LINE__;
10090       evntRecPtr.p->m_errorNode = reference();
10091       jam();
10092     } else
10093       jam();
10094   }
10095 
10096   // reference to API if master DICT
10097   // else reference to master DICT
10098   Uint32 senderRef = evntRecPtr.p->m_request.getUserRef();
10099   Uint32 signalLength;
10100   Uint32 gsn;
10101 
10102   if (evntRecPtr.p->hasError()) {
10103     jam();
10104     EVENT_TRACE;
10105     CreateEvntRef * ret = (CreateEvntRef *)signal->getDataPtrSend();
10106 
10107     ret->setEventId(evntRecPtr.p->m_request.getEventId());
10108     ret->setEventKey(evntRecPtr.p->m_request.getEventKey());
10109     ret->setUserData(evntRecPtr.p->m_request.getUserData());
10110     ret->senderRef = reference();
10111     ret->setTableId(evntRecPtr.p->m_request.getTableId());
10112     ret->setTableVersion(evntRecPtr.p->m_request.getTableVersion());
10113     ret->setEventType(evntRecPtr.p->m_request.getEventType());
10114     ret->setRequestType(evntRecPtr.p->m_request.getRequestType());
10115 
10116     ret->setErrorCode(evntRecPtr.p->m_errorCode);
10117     ret->setErrorLine(evntRecPtr.p->m_errorLine);
10118     ret->setErrorNode(evntRecPtr.p->m_errorNode);
10119 
10120     signalLength = CreateEvntRef::SignalLength;
10121 #ifdef EVENT_PH2_DEBUG
10122     ndbout_c("DBDICT sending GSN_CREATE_EVNT_REF to evntRecPtr.i = (%d) node = %u ref = %u", evntRecPtr.i, refToNode(senderRef), senderRef);
10123     ndbout_c("errorCode = %u", evntRecPtr.p->m_errorCode);
10124     ndbout_c("errorLine = %u", evntRecPtr.p->m_errorLine);
10125 #endif
10126     gsn = GSN_CREATE_EVNT_REF;
10127 
10128   } else {
10129     jam();
10130     EVENT_TRACE;
10131     CreateEvntConf * evntConf = (CreateEvntConf *)signal->getDataPtrSend();
10132 
10133     evntConf->setEventId(evntRecPtr.p->m_request.getEventId());
10134     evntConf->setEventKey(evntRecPtr.p->m_request.getEventKey());
10135     evntConf->setUserData(evntRecPtr.p->m_request.getUserData());
10136     evntConf->senderRef = reference();
10137     evntConf->setTableId(evntRecPtr.p->m_request.getTableId());
10138     evntConf->setTableVersion(evntRecPtr.p->m_request.getTableVersion());
10139     evntConf->setAttrListBitmask(evntRecPtr.p->m_request.getAttrListBitmask());
10140     evntConf->setEventType(evntRecPtr.p->m_request.getEventType());
10141     evntConf->setRequestType(evntRecPtr.p->m_request.getRequestType());
10142 
10143     signalLength = CreateEvntConf::SignalLength;
10144 #ifdef EVENT_PH2_DEBUG
10145     ndbout_c("DBDICT sending GSN_CREATE_EVNT_CONF to evntRecPtr.i = (%d) node = %u ref = %u", evntRecPtr.i, refToNode(senderRef), senderRef);
10146 #endif
10147     gsn = GSN_CREATE_EVNT_CONF;
10148   }
10149 
10150   if (ptr) {
10151     jam();
10152     sendSignal(senderRef, gsn, signal, signalLength, JBB, ptr, noLSP);
10153   } else {
10154     jam();
10155     sendSignal(senderRef, gsn, signal, signalLength, JBB);
10156   }
10157 
10158   c_opCreateEvent.release(evntRecPtr);
10159 }
10160 
10161 /*************************************************************/
10162 
10163 /********************************************************************
10164  *
10165  * Start event
10166  *
10167  *******************************************************************/
10168 
execSUB_START_REQ(Signal * signal)10169 void Dbdict::execSUB_START_REQ(Signal* signal)
10170 {
10171   jamEntry();
10172 
10173   Uint32 origSenderRef = signal->senderBlockRef();
10174 
10175   if (refToBlock(origSenderRef) != DBDICT &&
10176       getOwnNodeId() != c_masterNodeId)
10177   {
10178     /*
10179      * Coordinator but not master
10180      */
10181     SubStartRef * ref = (SubStartRef *)signal->getDataPtrSend();
10182     ref->senderRef = reference();
10183     ref->errorCode = SubStartRef::NotMaster;
10184     ref->m_masterNodeId = c_masterNodeId;
10185     sendSignal(origSenderRef, GSN_SUB_START_REF, signal,
10186 	       SubStartRef::SignalLength2, JBB);
10187     return;
10188   }
10189   OpSubEventPtr subbPtr;
10190   Uint32 errCode = 0;
10191 
10192   DictLockPtr loopPtr;
10193   if (c_dictLockQueue.first(loopPtr) &&
10194       loopPtr.p->lt->lockType == DictLockReq::NodeRestartLock)
10195   {
10196     jam();
10197     errCode = 1405;
10198     goto busy;
10199   }
10200 
10201   if (!c_opSubEvent.seize(subbPtr)) {
10202     errCode = SubStartRef::Busy;
10203 busy:
10204     jam();
10205     SubStartRef * ref = (SubStartRef *)signal->getDataPtrSend();
10206 
10207     { // fix
10208       Uint32 subcriberRef = ((SubStartReq*)signal->getDataPtr())->subscriberRef;
10209       ref->subscriberRef = subcriberRef;
10210     }
10211     jam();
10212     //      ret->setErrorCode(SubStartRef::SeizeError);
10213     //      ret->setErrorLine(__LINE__);
10214     //      ret->setErrorNode(reference());
10215     ref->senderRef = reference();
10216     ref->errorCode = errCode;
10217 
10218     sendSignal(origSenderRef, GSN_SUB_START_REF, signal,
10219 	       SubStartRef::SignalLength2, JBB);
10220     return;
10221   }
10222 
10223   {
10224     const SubStartReq* req = (SubStartReq*) signal->getDataPtr();
10225     subbPtr.p->m_senderRef = req->senderRef;
10226     subbPtr.p->m_senderData = req->senderData;
10227     subbPtr.p->m_errorCode = 0;
10228   }
10229 
10230   if (refToBlock(origSenderRef) != DBDICT) {
10231     /*
10232      * Coordinator
10233      */
10234     jam();
10235 
10236     subbPtr.p->m_senderRef = origSenderRef; // not sure if API sets correctly
10237     NodeReceiverGroup rg(DBDICT, c_aliveNodes);
10238     RequestTracker & p = subbPtr.p->m_reqTracker;
10239     if (!p.init<SubStartRef>(c_counterMgr, rg, GSN_SUB_START_REF, subbPtr.i))
10240     {
10241       c_opSubEvent.release(subbPtr);
10242       errCode = SubStartRef::Busy;
10243       goto busy;
10244     }
10245 
10246     SubStartReq* req = (SubStartReq*) signal->getDataPtrSend();
10247 
10248     req->senderRef  = reference();
10249     req->senderData = subbPtr.i;
10250 
10251 #ifdef EVENT_PH3_DEBUG
10252     ndbout_c("DBDICT(Coordinator) sending GSN_SUB_START_REQ to DBDICT participants subbPtr.i = (%d)", subbPtr.i);
10253 #endif
10254 
10255     sendSignal(rg, GSN_SUB_START_REQ, signal, SubStartReq::SignalLength2, JBB);
10256     return;
10257   }
10258   /*
10259    * Participant
10260    */
10261   ndbrequire(refToBlock(origSenderRef) == DBDICT);
10262 
10263   CRASH_INSERTION(6007);
10264 
10265   {
10266     SubStartReq* req = (SubStartReq*) signal->getDataPtrSend();
10267 
10268     req->senderRef = reference();
10269     req->senderData = subbPtr.i;
10270 
10271 #ifdef EVENT_PH3_DEBUG
10272     ndbout_c("DBDICT(Participant) sending GSN_SUB_START_REQ to SUMA subbPtr.i = (%d)", subbPtr.i);
10273 #endif
10274     sendSignal(SUMA_REF, GSN_SUB_START_REQ, signal, SubStartReq::SignalLength2, JBB);
10275   }
10276 }
10277 
execSUB_START_REF(Signal * signal)10278 void Dbdict::execSUB_START_REF(Signal* signal)
10279 {
10280   jamEntry();
10281 
10282   const SubStartRef* ref = (SubStartRef*) signal->getDataPtr();
10283   Uint32 senderRef  = ref->senderRef;
10284   Uint32 err = ref->errorCode;
10285 
10286   OpSubEventPtr subbPtr;
10287   c_opSubEvent.getPtr(subbPtr, ref->senderData);
10288 
10289   if (refToBlock(senderRef) == SUMA) {
10290     /*
10291      * Participant
10292      */
10293     jam();
10294 
10295 #ifdef EVENT_PH3_DEBUG
10296     ndbout_c("DBDICT(Participant) got GSN_SUB_START_REF = (%d)", subbPtr.i);
10297 #endif
10298 
10299     jam();
10300     SubStartRef* ref = (SubStartRef*) signal->getDataPtrSend();
10301     ref->senderRef = reference();
10302     ref->senderData = subbPtr.p->m_senderData;
10303     ref->errorCode = err;
10304     sendSignal(subbPtr.p->m_senderRef, GSN_SUB_START_REF,
10305 	       signal, SubStartRef::SignalLength2, JBB);
10306     c_opSubEvent.release(subbPtr);
10307     return;
10308   }
10309   /*
10310    * Coordinator
10311    */
10312   ndbrequire(refToBlock(senderRef) == DBDICT);
10313 #ifdef EVENT_PH3_DEBUG
10314   ndbout_c("DBDICT(Coordinator) got GSN_SUB_START_REF = (%d)", subbPtr.i);
10315 #endif
10316   if (err == SubStartRef::NF_FakeErrorREF){
10317     jam();
10318     subbPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(senderRef));
10319   } else {
10320     jam();
10321     if (subbPtr.p->m_errorCode == 0)
10322     {
10323       subbPtr.p->m_errorCode= err ? err : 1;
10324     }
10325     subbPtr.p->m_reqTracker.reportRef(c_counterMgr, refToNode(senderRef));
10326   }
10327   completeSubStartReq(signal,subbPtr.i,0);
10328 }
10329 
execSUB_START_CONF(Signal * signal)10330 void Dbdict::execSUB_START_CONF(Signal* signal)
10331 {
10332   jamEntry();
10333 
10334   const SubStartConf* conf = (SubStartConf*) signal->getDataPtr();
10335   Uint32 senderRef  = conf->senderRef;
10336 
10337   OpSubEventPtr subbPtr;
10338   c_opSubEvent.getPtr(subbPtr, conf->senderData);
10339 
10340   if (refToBlock(senderRef) == SUMA) {
10341     /*
10342      * Participant
10343      */
10344     jam();
10345     SubStartConf* conf = (SubStartConf*) signal->getDataPtrSend();
10346 
10347 #ifdef EVENT_PH3_DEBUG
10348   ndbout_c("DBDICT(Participant) got GSN_SUB_START_CONF = (%d)", subbPtr.i);
10349 #endif
10350 
10351     conf->senderRef = reference();
10352     conf->senderData = subbPtr.p->m_senderData;
10353 
10354     sendSignal(subbPtr.p->m_senderRef, GSN_SUB_START_CONF,
10355 	       signal, SubStartConf::SignalLength2, JBB);
10356     c_opSubEvent.release(subbPtr);
10357     return;
10358   }
10359   /*
10360    * Coordinator
10361    */
10362   ndbrequire(refToBlock(senderRef) == DBDICT);
10363 #ifdef EVENT_PH3_DEBUG
10364   ndbout_c("DBDICT(Coordinator) got GSN_SUB_START_CONF = (%d)", subbPtr.i);
10365 #endif
10366   subbPtr.p->m_sub_start_conf = *conf;
10367   subbPtr.p->m_reqTracker.reportConf(c_counterMgr, refToNode(senderRef));
10368   completeSubStartReq(signal,subbPtr.i,0);
10369 }
10370 
10371 /*
10372  * Coordinator
10373  */
completeSubStartReq(Signal * signal,Uint32 ptrI,Uint32 returnCode)10374 void Dbdict::completeSubStartReq(Signal* signal,
10375 				 Uint32 ptrI,
10376 				 Uint32 returnCode){
10377   jam();
10378 
10379   OpSubEventPtr subbPtr;
10380   c_opSubEvent.getPtr(subbPtr, ptrI);
10381 
10382   if (!subbPtr.p->m_reqTracker.done()){
10383     jam();
10384     return;
10385   }
10386 
10387   if (subbPtr.p->m_reqTracker.hasRef()) {
10388     jam();
10389 #ifdef EVENT_DEBUG
10390     ndbout_c("SUB_START_REF");
10391 #endif
10392     SubStartRef * ref = (SubStartRef *)signal->getDataPtrSend();
10393     ref->senderRef = reference();
10394     ref->errorCode = subbPtr.p->m_errorCode;
10395     sendSignal(subbPtr.p->m_senderRef, GSN_SUB_START_REF,
10396 	       signal, SubStartRef::SignalLength, JBB);
10397     if (subbPtr.p->m_reqTracker.hasConf()) {
10398       //  stopStartedNodes(signal);
10399     }
10400     c_opSubEvent.release(subbPtr);
10401     return;
10402   }
10403 #ifdef EVENT_DEBUG
10404   ndbout_c("SUB_START_CONF");
10405 #endif
10406 
10407   SubStartConf* conf = (SubStartConf*)signal->getDataPtrSend();
10408   * conf = subbPtr.p->m_sub_start_conf;
10409   sendSignal(subbPtr.p->m_senderRef, GSN_SUB_START_CONF,
10410 	     signal, SubStartConf::SignalLength, JBB);
10411   c_opSubEvent.release(subbPtr);
10412 }
10413 
10414 /********************************************************************
10415  *
10416  * Stop event
10417  *
10418  *******************************************************************/
10419 
execSUB_STOP_REQ(Signal * signal)10420 void Dbdict::execSUB_STOP_REQ(Signal* signal)
10421 {
10422   jamEntry();
10423 
10424   Uint32 origSenderRef = signal->senderBlockRef();
10425 
10426   if (refToBlock(origSenderRef) != DBDICT &&
10427       getOwnNodeId() != c_masterNodeId)
10428   {
10429     /*
10430      * Coordinator but not master
10431      */
10432     SubStopRef * ref = (SubStopRef *)signal->getDataPtrSend();
10433     ref->senderRef = reference();
10434     ref->errorCode = SubStopRef::NotMaster;
10435     ref->m_masterNodeId = c_masterNodeId;
10436     sendSignal(origSenderRef, GSN_SUB_STOP_REF, signal,
10437 	       SubStopRef::SignalLength2, JBB);
10438     return;
10439   }
10440   OpSubEventPtr subbPtr;
10441   Uint32 errCode = 0;
10442   if (!c_opSubEvent.seize(subbPtr)) {
10443     errCode = SubStopRef::Busy;
10444 busy:
10445     SubStopRef * ref = (SubStopRef *)signal->getDataPtrSend();
10446     jam();
10447     //      ret->setErrorCode(SubStartRef::SeizeError);
10448     //      ret->setErrorLine(__LINE__);
10449     //      ret->setErrorNode(reference());
10450     ref->senderRef = reference();
10451     ref->errorCode = errCode;
10452 
10453     sendSignal(origSenderRef, GSN_SUB_STOP_REF, signal,
10454 	       SubStopRef::SignalLength, JBB);
10455     return;
10456   }
10457 
10458   {
10459     const SubStopReq* req = (SubStopReq*) signal->getDataPtr();
10460     subbPtr.p->m_senderRef = req->senderRef;
10461     subbPtr.p->m_senderData = req->senderData;
10462     subbPtr.p->m_errorCode = 0;
10463   }
10464 
10465   if (refToBlock(origSenderRef) != DBDICT) {
10466     /*
10467      * Coordinator
10468      */
10469     jam();
10470 #ifdef EVENT_DEBUG
10471     ndbout_c("SUB_STOP_REQ 1");
10472 #endif
10473     subbPtr.p->m_senderRef = origSenderRef; // not sure if API sets correctly
10474     NodeReceiverGroup rg(DBDICT, c_aliveNodes);
10475     RequestTracker & p = subbPtr.p->m_reqTracker;
10476     if (!p.init<SubStopRef>(c_counterMgr, rg, GSN_SUB_STOP_REF, subbPtr.i))
10477     {
10478       jam();
10479       c_opSubEvent.release(subbPtr);
10480       errCode = SubStopRef::Busy;
10481       goto busy;
10482     }
10483 
10484     SubStopReq* req = (SubStopReq*) signal->getDataPtrSend();
10485 
10486     req->senderRef  = reference();
10487     req->senderData = subbPtr.i;
10488 
10489     sendSignal(rg, GSN_SUB_STOP_REQ, signal, SubStopReq::SignalLength, JBB);
10490     return;
10491   }
10492   /*
10493    * Participant
10494    */
10495 #ifdef EVENT_DEBUG
10496   ndbout_c("SUB_STOP_REQ 2");
10497 #endif
10498   ndbrequire(refToBlock(origSenderRef) == DBDICT);
10499 
10500   CRASH_INSERTION(6008);
10501 
10502   {
10503     SubStopReq* req = (SubStopReq*) signal->getDataPtrSend();
10504 
10505     req->senderRef = reference();
10506     req->senderData = subbPtr.i;
10507 
10508     sendSignal(SUMA_REF, GSN_SUB_STOP_REQ, signal, SubStopReq::SignalLength, JBB);
10509   }
10510 }
10511 
execSUB_STOP_REF(Signal * signal)10512 void Dbdict::execSUB_STOP_REF(Signal* signal)
10513 {
10514   jamEntry();
10515   const SubStopRef* ref = (SubStopRef*) signal->getDataPtr();
10516   Uint32 senderRef  = ref->senderRef;
10517   Uint32 err = ref->errorCode;
10518 
10519   OpSubEventPtr subbPtr;
10520   c_opSubEvent.getPtr(subbPtr, ref->senderData);
10521 
10522   if (refToBlock(senderRef) == SUMA) {
10523     /*
10524      * Participant
10525      */
10526     jam();
10527     SubStopRef* ref = (SubStopRef*) signal->getDataPtrSend();
10528     ref->senderRef = reference();
10529     ref->senderData = subbPtr.p->m_senderData;
10530     ref->errorCode = err;
10531     sendSignal(subbPtr.p->m_senderRef, GSN_SUB_STOP_REF,
10532 	       signal, SubStopRef::SignalLength, JBB);
10533     c_opSubEvent.release(subbPtr);
10534     return;
10535   }
10536   /*
10537    * Coordinator
10538    */
10539   ndbrequire(refToBlock(senderRef) == DBDICT);
10540   if (err == SubStopRef::NF_FakeErrorREF){
10541     jam();
10542     subbPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(senderRef));
10543   } else {
10544     jam();
10545     if (subbPtr.p->m_errorCode == 0)
10546     {
10547       subbPtr.p->m_errorCode= err ? err : 1;
10548     }
10549     subbPtr.p->m_reqTracker.reportRef(c_counterMgr, refToNode(senderRef));
10550   }
10551   completeSubStopReq(signal,subbPtr.i,0);
10552 }
10553 
execSUB_STOP_CONF(Signal * signal)10554 void Dbdict::execSUB_STOP_CONF(Signal* signal)
10555 {
10556   jamEntry();
10557 
10558   const SubStopConf* conf = (SubStopConf*) signal->getDataPtr();
10559   Uint32 senderRef  = conf->senderRef;
10560 
10561   OpSubEventPtr subbPtr;
10562   c_opSubEvent.getPtr(subbPtr, conf->senderData);
10563 
10564   if (refToBlock(senderRef) == SUMA) {
10565     /*
10566      * Participant
10567      */
10568     jam();
10569     SubStopConf* conf = (SubStopConf*) signal->getDataPtrSend();
10570 
10571     conf->senderRef = reference();
10572     conf->senderData = subbPtr.p->m_senderData;
10573 
10574     sendSignal(subbPtr.p->m_senderRef, GSN_SUB_STOP_CONF,
10575 	       signal, SubStopConf::SignalLength, JBB);
10576     c_opSubEvent.release(subbPtr);
10577     return;
10578   }
10579   /*
10580    * Coordinator
10581    */
10582   ndbrequire(refToBlock(senderRef) == DBDICT);
10583   subbPtr.p->m_sub_stop_conf = *conf;
10584   subbPtr.p->m_reqTracker.reportConf(c_counterMgr, refToNode(senderRef));
10585   completeSubStopReq(signal,subbPtr.i,0);
10586 }
10587 
10588 /*
10589  * Coordinator
10590  */
completeSubStopReq(Signal * signal,Uint32 ptrI,Uint32 returnCode)10591 void Dbdict::completeSubStopReq(Signal* signal,
10592 				Uint32 ptrI,
10593 				Uint32 returnCode){
10594   OpSubEventPtr subbPtr;
10595   c_opSubEvent.getPtr(subbPtr, ptrI);
10596 
10597   if (!subbPtr.p->m_reqTracker.done()){
10598     jam();
10599     return;
10600   }
10601 
10602   if (subbPtr.p->m_reqTracker.hasRef()) {
10603     jam();
10604 #ifdef EVENT_DEBUG
10605     ndbout_c("SUB_STOP_REF");
10606 #endif
10607     SubStopRef* ref = (SubStopRef*)signal->getDataPtrSend();
10608 
10609     ref->senderRef  = reference();
10610     ref->senderData = subbPtr.p->m_senderData;
10611     ref->errorCode  = subbPtr.p->m_errorCode;
10612 
10613     sendSignal(subbPtr.p->m_senderRef, GSN_SUB_STOP_REF,
10614 	       signal, SubStopRef::SignalLength, JBB);
10615     if (subbPtr.p->m_reqTracker.hasConf()) {
10616       //  stopStartedNodes(signal);
10617     }
10618     c_opSubEvent.release(subbPtr);
10619     return;
10620   }
10621 #ifdef EVENT_DEBUG
10622   ndbout_c("SUB_STOP_CONF");
10623 #endif
10624   SubStopConf* conf = (SubStopConf*)signal->getDataPtrSend();
10625   * conf = subbPtr.p->m_sub_stop_conf;
10626   sendSignal(subbPtr.p->m_senderRef, GSN_SUB_STOP_CONF,
10627 	     signal, SubStopConf::SignalLength, JBB);
10628   c_opSubEvent.release(subbPtr);
10629 }
10630 
10631 /***************************************************************
10632  * MODULE: Drop event.
10633  *
10634  * Drop event.
10635  *
10636  * TODO
10637  */
10638 
10639 void
execDROP_EVNT_REQ(Signal * signal)10640 Dbdict::execDROP_EVNT_REQ(Signal* signal)
10641 {
10642   jamEntry();
10643   DBUG_ENTER("Dbdict::execDROP_EVNT_REQ");
10644 
10645   DropEvntReq *req = (DropEvntReq*)signal->getDataPtr();
10646   const Uint32 senderRef = signal->senderBlockRef();
10647   OpDropEventPtr evntRecPtr;
10648 
10649   if (refToBlock(senderRef) != DBDICT &&
10650       getOwnNodeId() != c_masterNodeId)
10651   {
10652     jam();
10653     releaseSections(signal);
10654 
10655     DropEvntRef * ref = (DropEvntRef *)signal->getDataPtrSend();
10656     ref->setUserRef(reference());
10657     ref->setErrorCode(DropEvntRef::NotMaster);
10658     ref->setErrorLine(__LINE__);
10659     ref->setErrorNode(reference());
10660     ref->setMasterNode(c_masterNodeId);
10661     sendSignal(senderRef, GSN_DROP_EVNT_REF, signal,
10662 	       DropEvntRef::SignalLength2, JBB);
10663     return;
10664   }
10665 
10666   // Seize a Create Event record
10667   if (!c_opDropEvent.seize(evntRecPtr)) {
10668     // Failed to allocate event record
10669     jam();
10670     releaseSections(signal);
10671 
10672     DropEvntRef * ret = (DropEvntRef *)signal->getDataPtrSend();
10673     ret->setErrorCode(747);
10674     ret->setErrorLine(__LINE__);
10675     ret->setErrorNode(reference());
10676     sendSignal(senderRef, GSN_DROP_EVNT_REF, signal,
10677 	       DropEvntRef::SignalLength, JBB);
10678     DBUG_VOID_RETURN;
10679   }
10680 
10681 #ifdef EVENT_DEBUG
10682   ndbout_c("DBDICT::execDROP_EVNT_REQ evntRecId = (%d)", evntRecPtr.i);
10683 #endif
10684 
10685   OpDropEvent* evntRec = evntRecPtr.p;
10686   evntRec->init(req);
10687 
10688   SegmentedSectionPtr ssPtr;
10689 
10690   signal->getSection(ssPtr, 0);
10691 
10692   SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
10693 #ifdef EVENT_DEBUG
10694   r0.printAll(ndbout);
10695 #endif
10696   // event name
10697   if ((!r0.first()) ||
10698       (r0.getValueType() != SimpleProperties::StringValue) ||
10699       (r0.getValueLen() <= 0)) {
10700     jam();
10701     releaseSections(signal);
10702 
10703     evntRecPtr.p->m_errorCode = 1;
10704     evntRecPtr.p->m_errorLine = __LINE__;
10705     evntRecPtr.p->m_errorNode = reference();
10706 
10707     dropEvent_sendReply(signal, evntRecPtr);
10708     DBUG_VOID_RETURN;
10709   }
10710   r0.getString(evntRecPtr.p->m_eventRec.NAME);
10711   {
10712     int len = strlen(evntRecPtr.p->m_eventRec.NAME);
10713     memset(evntRecPtr.p->m_eventRec.NAME+len, 0, MAX_TAB_NAME_SIZE-len);
10714 #ifdef EVENT_DEBUG
10715     printf("DropEvntReq; EventName %s, len %u\n",
10716 	   evntRecPtr.p->m_eventRec.NAME, len);
10717     for(int i = 0; i < MAX_TAB_NAME_SIZE/4; i++)
10718       printf("H'%.8x ", ((Uint32*)evntRecPtr.p->m_eventRec.NAME)[i]);
10719     printf("\n");
10720 #endif
10721   }
10722 
10723   releaseSections(signal);
10724 
10725   Callback c = { safe_cast(&Dbdict::dropEventUTIL_PREPARE_READ), 0 };
10726 
10727   prepareTransactionEventSysTable(&c, signal, evntRecPtr.i,
10728 				  UtilPrepareReq::Read);
10729   DBUG_VOID_RETURN;
10730 }
10731 
10732 void
dropEventUTIL_PREPARE_READ(Signal * signal,Uint32 callbackData,Uint32 returnCode)10733 Dbdict::dropEventUTIL_PREPARE_READ(Signal* signal,
10734 				   Uint32 callbackData,
10735 				   Uint32 returnCode)
10736 {
10737   jam();
10738   EVENT_TRACE;
10739   if (returnCode != 0) {
10740     EVENT_TRACE;
10741     dropEventUtilPrepareRef(signal, callbackData, returnCode);
10742     return;
10743   }
10744 
10745   UtilPrepareConf* const req = (UtilPrepareConf*)signal->getDataPtr();
10746   OpDropEventPtr evntRecPtr;
10747   evntRecPtr.i = req->getSenderData();
10748   const Uint32 prepareId = req->getPrepareId();
10749 
10750   ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
10751 
10752   Callback c = { safe_cast(&Dbdict::dropEventUTIL_EXECUTE_READ), 0 };
10753 
10754   executeTransEventSysTable(&c, signal,
10755 			    evntRecPtr.i, evntRecPtr.p->m_eventRec,
10756 			    prepareId, UtilPrepareReq::Read);
10757 }
10758 
10759 void
dropEventUTIL_EXECUTE_READ(Signal * signal,Uint32 callbackData,Uint32 returnCode)10760 Dbdict::dropEventUTIL_EXECUTE_READ(Signal* signal,
10761 				   Uint32 callbackData,
10762 				   Uint32 returnCode)
10763 {
10764   jam();
10765   EVENT_TRACE;
10766   if (returnCode != 0) {
10767     EVENT_TRACE;
10768     dropEventUtilExecuteRef(signal, callbackData, returnCode);
10769     return;
10770   }
10771 
10772   OpDropEventPtr evntRecPtr;
10773   UtilExecuteConf * const ref = (UtilExecuteConf *)signal->getDataPtr();
10774   jam();
10775   evntRecPtr.i = ref->getSenderData();
10776   ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
10777 
10778   parseReadEventSys(signal, evntRecPtr.p->m_eventRec);
10779 
10780   NodeReceiverGroup rg(DBDICT, c_aliveNodes);
10781   RequestTracker & p = evntRecPtr.p->m_reqTracker;
10782   if (!p.init<SubRemoveRef>(c_counterMgr, rg, GSN_SUB_REMOVE_REF,
10783 			    evntRecPtr.i))
10784   {
10785     evntRecPtr.p->m_errorCode = 701;
10786     dropEvent_sendReply(signal, evntRecPtr);
10787     return;
10788   }
10789 
10790   SubRemoveReq* req = (SubRemoveReq*) signal->getDataPtrSend();
10791 
10792   req->senderRef       = reference();
10793   req->senderData      = evntRecPtr.i;
10794   req->subscriptionId  = evntRecPtr.p->m_eventRec.SUBID;
10795   req->subscriptionKey = evntRecPtr.p->m_eventRec.SUBKEY;
10796 
10797   sendSignal(rg, GSN_SUB_REMOVE_REQ, signal, SubRemoveReq::SignalLength, JBB);
10798 }
10799 
10800 /*
10801  * Participant
10802  */
10803 
10804 void
execSUB_REMOVE_REQ(Signal * signal)10805 Dbdict::execSUB_REMOVE_REQ(Signal* signal)
10806 {
10807   jamEntry();
10808   DBUG_ENTER("Dbdict::execSUB_REMOVE_REQ");
10809 
10810   Uint32 origSenderRef = signal->senderBlockRef();
10811 
10812   OpSubEventPtr subbPtr;
10813   if (!c_opSubEvent.seize(subbPtr)) {
10814     SubRemoveRef * ref = (SubRemoveRef *)signal->getDataPtrSend();
10815     jam();
10816     ref->senderRef = reference();
10817     ref->errorCode = SubRemoveRef::Busy;
10818 
10819     sendSignal(origSenderRef, GSN_SUB_REMOVE_REF, signal,
10820 	       SubRemoveRef::SignalLength, JBB);
10821     DBUG_VOID_RETURN;
10822   }
10823 
10824   {
10825     const SubRemoveReq* req = (SubRemoveReq*) signal->getDataPtr();
10826     subbPtr.p->m_senderRef = req->senderRef;
10827     subbPtr.p->m_senderData = req->senderData;
10828     subbPtr.p->m_errorCode = 0;
10829   }
10830 
10831   CRASH_INSERTION2(6010, getOwnNodeId() != c_masterNodeId);
10832 
10833   SubRemoveReq* req = (SubRemoveReq*) signal->getDataPtrSend();
10834   req->senderRef = reference();
10835   req->senderData = subbPtr.i;
10836 
10837   sendSignal(SUMA_REF, GSN_SUB_REMOVE_REQ, signal, SubRemoveReq::SignalLength, JBB);
10838   DBUG_VOID_RETURN;
10839 }
10840 
10841 /*
10842  * Coordintor/Participant
10843  */
10844 
10845 void
execSUB_REMOVE_REF(Signal * signal)10846 Dbdict::execSUB_REMOVE_REF(Signal* signal)
10847 {
10848   jamEntry();
10849   DBUG_ENTER("Dbdict::execSUB_REMOVE_REF");
10850 
10851   const SubRemoveRef* ref = (SubRemoveRef*) signal->getDataPtr();
10852   Uint32 senderRef = ref->senderRef;
10853   Uint32 err= ref->errorCode;
10854 
10855   if (refToBlock(senderRef) == SUMA) {
10856     /*
10857      * Participant
10858      */
10859     jam();
10860     OpSubEventPtr subbPtr;
10861     c_opSubEvent.getPtr(subbPtr, ref->senderData);
10862     if (err == 1407) {
10863       // conf this since this may occur if a nodefailure has occured
10864       // earlier so that the systable was not cleared
10865       SubRemoveConf* conf = (SubRemoveConf*) signal->getDataPtrSend();
10866       conf->senderRef  = reference();
10867       conf->senderData = subbPtr.p->m_senderData;
10868       sendSignal(subbPtr.p->m_senderRef, GSN_SUB_REMOVE_CONF,
10869 		 signal, SubRemoveConf::SignalLength, JBB);
10870     } else {
10871       SubRemoveRef* ref = (SubRemoveRef*) signal->getDataPtrSend();
10872       ref->senderRef = reference();
10873       ref->senderData = subbPtr.p->m_senderData;
10874       ref->errorCode = err;
10875       sendSignal(subbPtr.p->m_senderRef, GSN_SUB_REMOVE_REF,
10876 		 signal, SubRemoveRef::SignalLength, JBB);
10877     }
10878     c_opSubEvent.release(subbPtr);
10879     DBUG_VOID_RETURN;
10880   }
10881   /*
10882    * Coordinator
10883    */
10884   ndbrequire(refToBlock(senderRef) == DBDICT);
10885   OpDropEventPtr eventRecPtr;
10886   c_opDropEvent.getPtr(eventRecPtr, ref->senderData);
10887   if (err == SubRemoveRef::NF_FakeErrorREF){
10888     jam();
10889     eventRecPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(senderRef));
10890   } else {
10891     jam();
10892     if (eventRecPtr.p->m_errorCode == 0)
10893     {
10894       eventRecPtr.p->m_errorCode= err ? err : 1;
10895       eventRecPtr.p->m_errorLine= __LINE__;
10896       eventRecPtr.p->m_errorNode= reference();
10897     }
10898     eventRecPtr.p->m_reqTracker.reportRef(c_counterMgr, refToNode(senderRef));
10899   }
10900   completeSubRemoveReq(signal,eventRecPtr.i,0);
10901   DBUG_VOID_RETURN;
10902 }
10903 
10904 void
execSUB_REMOVE_CONF(Signal * signal)10905 Dbdict::execSUB_REMOVE_CONF(Signal* signal)
10906 {
10907   jamEntry();
10908   const SubRemoveConf* conf = (SubRemoveConf*) signal->getDataPtr();
10909   Uint32 senderRef = conf->senderRef;
10910 
10911   if (refToBlock(senderRef) == SUMA) {
10912     /*
10913      * Participant
10914      */
10915     jam();
10916     OpSubEventPtr subbPtr;
10917     c_opSubEvent.getPtr(subbPtr, conf->senderData);
10918     SubRemoveConf* conf = (SubRemoveConf*) signal->getDataPtrSend();
10919     conf->senderRef = reference();
10920     conf->senderData = subbPtr.p->m_senderData;
10921     sendSignal(subbPtr.p->m_senderRef, GSN_SUB_REMOVE_CONF,
10922 	       signal, SubRemoveConf::SignalLength, JBB);
10923     c_opSubEvent.release(subbPtr);
10924     return;
10925   }
10926   /*
10927    * Coordinator
10928    */
10929   ndbrequire(refToBlock(senderRef) == DBDICT);
10930   OpDropEventPtr eventRecPtr;
10931   c_opDropEvent.getPtr(eventRecPtr, conf->senderData);
10932   eventRecPtr.p->m_reqTracker.reportConf(c_counterMgr, refToNode(senderRef));
10933   completeSubRemoveReq(signal,eventRecPtr.i,0);
10934 }
10935 
10936 void
completeSubRemoveReq(Signal * signal,Uint32 ptrI,Uint32 xxx)10937 Dbdict::completeSubRemoveReq(Signal* signal, Uint32 ptrI, Uint32 xxx)
10938 {
10939   OpDropEventPtr evntRecPtr;
10940   c_opDropEvent.getPtr(evntRecPtr, ptrI);
10941 
10942   if (!evntRecPtr.p->m_reqTracker.done()){
10943     jam();
10944     return;
10945   }
10946 
10947   if (evntRecPtr.p->m_reqTracker.hasRef()) {
10948     jam();
10949     if ( evntRecPtr.p->m_errorCode == 0 )
10950     {
10951       evntRecPtr.p->m_errorNode = reference();
10952       evntRecPtr.p->m_errorLine = __LINE__;
10953       evntRecPtr.p->m_errorCode = 1;
10954     }
10955     dropEvent_sendReply(signal, evntRecPtr);
10956     return;
10957   }
10958 
10959   Callback c = { safe_cast(&Dbdict::dropEventUTIL_PREPARE_DELETE), 0 };
10960 
10961   prepareTransactionEventSysTable(&c, signal, evntRecPtr.i,
10962 				  UtilPrepareReq::Delete);
10963 }
10964 
10965 void
dropEventUTIL_PREPARE_DELETE(Signal * signal,Uint32 callbackData,Uint32 returnCode)10966 Dbdict::dropEventUTIL_PREPARE_DELETE(Signal* signal,
10967 				     Uint32 callbackData,
10968 				     Uint32 returnCode)
10969 {
10970   jam();
10971   EVENT_TRACE;
10972   if (returnCode != 0) {
10973     EVENT_TRACE;
10974     dropEventUtilPrepareRef(signal, callbackData, returnCode);
10975     return;
10976   }
10977 
10978   UtilPrepareConf* const req = (UtilPrepareConf*)signal->getDataPtr();
10979   OpDropEventPtr evntRecPtr;
10980   jam();
10981   evntRecPtr.i = req->getSenderData();
10982   const Uint32 prepareId = req->getPrepareId();
10983 
10984   ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
10985 #ifdef EVENT_DEBUG
10986   printf("DropEvntUTIL_PREPARE; evntRecPtr.i len %u\n",evntRecPtr.i);
10987 #endif
10988 
10989   Callback c = { safe_cast(&Dbdict::dropEventUTIL_EXECUTE_DELETE), 0 };
10990 
10991   executeTransEventSysTable(&c, signal,
10992 			    evntRecPtr.i, evntRecPtr.p->m_eventRec,
10993 			    prepareId, UtilPrepareReq::Delete);
10994 }
10995 
10996 void
dropEventUTIL_EXECUTE_DELETE(Signal * signal,Uint32 callbackData,Uint32 returnCode)10997 Dbdict::dropEventUTIL_EXECUTE_DELETE(Signal* signal,
10998 				     Uint32 callbackData,
10999 				     Uint32 returnCode)
11000 {
11001   jam();
11002   EVENT_TRACE;
11003   if (returnCode != 0) {
11004     EVENT_TRACE;
11005     dropEventUtilExecuteRef(signal, callbackData, returnCode);
11006     return;
11007   }
11008 
11009   OpDropEventPtr evntRecPtr;
11010   UtilExecuteConf * const ref = (UtilExecuteConf *)signal->getDataPtr();
11011   jam();
11012   evntRecPtr.i = ref->getSenderData();
11013   ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
11014 
11015   dropEvent_sendReply(signal, evntRecPtr);
11016 }
11017 
11018 void
dropEventUtilPrepareRef(Signal * signal,Uint32 callbackData,Uint32 returnCode)11019 Dbdict::dropEventUtilPrepareRef(Signal* signal,
11020 				Uint32 callbackData,
11021 				Uint32 returnCode)
11022 {
11023   jam();
11024   EVENT_TRACE;
11025   UtilPrepareRef * const ref = (UtilPrepareRef *)signal->getDataPtr();
11026   OpDropEventPtr evntRecPtr;
11027   evntRecPtr.i = ref->getSenderData();
11028   ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
11029 
11030   interpretUtilPrepareErrorCode((UtilPrepareRef::ErrorCode)ref->getErrorCode(),
11031 				evntRecPtr.p->m_errorCode, evntRecPtr.p->m_errorLine);
11032   evntRecPtr.p->m_errorNode = reference();
11033 
11034   dropEvent_sendReply(signal, evntRecPtr);
11035 }
11036 
11037 void
dropEventUtilExecuteRef(Signal * signal,Uint32 callbackData,Uint32 returnCode)11038 Dbdict::dropEventUtilExecuteRef(Signal* signal,
11039 				Uint32 callbackData,
11040 				Uint32 returnCode)
11041 {
11042   jam();
11043   EVENT_TRACE;
11044   OpDropEventPtr evntRecPtr;
11045   UtilExecuteRef * const ref = (UtilExecuteRef *)signal->getDataPtr();
11046   jam();
11047   evntRecPtr.i = ref->getSenderData();
11048   ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
11049 
11050   evntRecPtr.p->m_errorNode = reference();
11051   evntRecPtr.p->m_errorLine = __LINE__;
11052 
11053   switch (ref->getErrorCode()) {
11054   case UtilExecuteRef::TCError:
11055     switch (ref->getTCErrorCode()) {
11056     case ZNOT_FOUND:
11057       jam();
11058       evntRecPtr.p->m_errorCode = 4710;
11059       break;
11060     default:
11061       jam();
11062       evntRecPtr.p->m_errorCode = ref->getTCErrorCode();
11063       break;
11064     }
11065     break;
11066   default:
11067     jam();
11068     evntRecPtr.p->m_errorCode = ref->getErrorCode();
11069     break;
11070   }
11071   dropEvent_sendReply(signal, evntRecPtr);
11072 }
11073 
dropEvent_sendReply(Signal * signal,OpDropEventPtr evntRecPtr)11074 void Dbdict::dropEvent_sendReply(Signal* signal,
11075 				 OpDropEventPtr evntRecPtr)
11076 {
11077   jam();
11078   EVENT_TRACE;
11079   Uint32 senderRef = evntRecPtr.p->m_request.getUserRef();
11080 
11081   if (evntRecPtr.p->hasError()) {
11082     jam();
11083     DropEvntRef * ret = (DropEvntRef *)signal->getDataPtrSend();
11084 
11085     ret->setUserData(evntRecPtr.p->m_request.getUserData());
11086     ret->setUserRef(evntRecPtr.p->m_request.getUserRef());
11087 
11088     ret->setErrorCode(evntRecPtr.p->m_errorCode);
11089     ret->setErrorLine(evntRecPtr.p->m_errorLine);
11090     ret->setErrorNode(evntRecPtr.p->m_errorNode);
11091 
11092     sendSignal(senderRef, GSN_DROP_EVNT_REF, signal,
11093 	       DropEvntRef::SignalLength, JBB);
11094   } else {
11095     jam();
11096     DropEvntConf * evntConf = (DropEvntConf *)signal->getDataPtrSend();
11097 
11098     evntConf->setUserData(evntRecPtr.p->m_request.getUserData());
11099     evntConf->setUserRef(evntRecPtr.p->m_request.getUserRef());
11100 
11101     sendSignal(senderRef, GSN_DROP_EVNT_CONF, signal,
11102 	       DropEvntConf::SignalLength, JBB);
11103   }
11104 
11105   c_opDropEvent.release(evntRecPtr);
11106 }
11107 
11108 /**
11109  * MODULE: Alter index
11110  *
11111  * Alter index state.  Alter online creates the index in each TC and
11112  * then invokes create trigger and alter trigger protocols to activate
11113  * the 3 triggers.  Alter offline does the opposite.
11114  *
11115  * Request type received in REQ and returned in CONF/REF:
11116  *
11117  * RT_USER - from API to DICT master
11118  * RT_CREATE_INDEX - part of create index operation
11119  * RT_DROP_INDEX - part of drop index operation
11120  * RT_NODERESTART - node restart, activate locally only
11121  * RT_SYSTEMRESTART - system restart, activate and build if not logged
11122  * RT_DICT_PREPARE - prepare participants
11123  * RT_DICT_TC - to local TC via each participant
11124  * RT_DICT_COMMIT - commit in each participant
11125  */
11126 
11127 void
execALTER_INDX_REQ(Signal * signal)11128 Dbdict::execALTER_INDX_REQ(Signal* signal)
11129 {
11130   jamEntry();
11131   AlterIndxReq* const req = (AlterIndxReq*)signal->getDataPtrSend();
11132   OpAlterIndexPtr opPtr;
11133   const Uint32 senderRef = signal->senderBlockRef();
11134   const AlterIndxReq::RequestType requestType = req->getRequestType();
11135   if (requestType == AlterIndxReq::RT_USER ||
11136       requestType == AlterIndxReq::RT_CREATE_INDEX ||
11137       requestType == AlterIndxReq::RT_DROP_INDEX ||
11138       requestType == AlterIndxReq::RT_NODERESTART ||
11139       requestType == AlterIndxReq::RT_SYSTEMRESTART) {
11140     jam();
11141     const bool isLocal = req->getRequestFlag() & RequestFlag::RF_LOCAL;
11142     NdbNodeBitmask receiverNodes = c_aliveNodes;
11143     if (isLocal) {
11144       receiverNodes.clear();
11145       receiverNodes.set(getOwnNodeId());
11146     }
11147     if (signal->getLength() == AlterIndxReq::SignalLength) {
11148       jam();
11149       if (! isLocal && getOwnNodeId() != c_masterNodeId) {
11150         jam();
11151 
11152 	releaseSections(signal);
11153 	OpAlterIndex opBad;
11154 	opPtr.p = &opBad;
11155 	opPtr.p->save(req);
11156 	opPtr.p->m_errorCode = AlterIndxRef::NotMaster;
11157 	opPtr.p->m_errorLine = __LINE__;
11158 	opPtr.p->m_errorNode = c_masterNodeId;
11159 	alterIndex_sendReply(signal, opPtr, true);
11160         return;
11161       }
11162       // forward initial request plus operation key to all
11163       req->setOpKey(++c_opRecordSequence);
11164       NodeReceiverGroup rg(DBDICT, receiverNodes);
11165       sendSignal(rg, GSN_ALTER_INDX_REQ,
11166           signal, AlterIndxReq::SignalLength + 1, JBB);
11167       return;
11168     }
11169     // seize operation record
11170     ndbrequire(signal->getLength() == AlterIndxReq::SignalLength + 1);
11171     const Uint32 opKey = req->getOpKey();
11172     OpAlterIndex opBusy;
11173     if (! c_opAlterIndex.seize(opPtr))
11174       opPtr.p = &opBusy;
11175     opPtr.p->save(req);
11176     opPtr.p->m_coordinatorRef = senderRef;
11177     opPtr.p->m_isMaster = (senderRef == reference());
11178     opPtr.p->key = opKey;
11179     opPtr.p->m_requestType = AlterIndxReq::RT_DICT_PREPARE;
11180     if (opPtr.p == &opBusy) {
11181       jam();
11182       opPtr.p->m_errorCode = AlterIndxRef::Busy;
11183       opPtr.p->m_errorLine = __LINE__;
11184       alterIndex_sendReply(signal, opPtr, opPtr.p->m_isMaster);
11185       return;
11186     }
11187     c_opAlterIndex.add(opPtr);
11188     // master expects to hear from all
11189     if (opPtr.p->m_isMaster)
11190       opPtr.p->m_signalCounter = receiverNodes;
11191     // check request in all participants
11192     alterIndex_slavePrepare(signal, opPtr);
11193     alterIndex_sendReply(signal, opPtr, false);
11194     return;
11195   }
11196   c_opAlterIndex.find(opPtr, req->getConnectionPtr());
11197   if (! opPtr.isNull()) {
11198     opPtr.p->m_requestType = requestType;
11199     if (requestType == AlterIndxReq::RT_DICT_TC) {
11200       jam();
11201       if (opPtr.p->m_request.getOnline())
11202         alterIndex_toCreateTc(signal, opPtr);
11203       else
11204         alterIndex_toDropTc(signal, opPtr);
11205       return;
11206     }
11207     if (requestType == AlterIndxReq::RT_DICT_COMMIT ||
11208         requestType == AlterIndxReq::RT_DICT_ABORT) {
11209       jam();
11210       if (requestType == AlterIndxReq::RT_DICT_COMMIT)
11211         alterIndex_slaveCommit(signal, opPtr);
11212       else
11213         alterIndex_slaveAbort(signal, opPtr);
11214       alterIndex_sendReply(signal, opPtr, false);
11215       // done in slave
11216       if (! opPtr.p->m_isMaster)
11217         c_opAlterIndex.release(opPtr);
11218       return;
11219     }
11220   }
11221   jam();
11222   // return to sender
11223   OpAlterIndex opBad;
11224   opPtr.p = &opBad;
11225   opPtr.p->save(req);
11226   opPtr.p->m_errorCode = AlterIndxRef::BadRequestType;
11227   opPtr.p->m_errorLine = __LINE__;
11228   alterIndex_sendReply(signal, opPtr, true);
11229 }
11230 
11231 void
execALTER_INDX_CONF(Signal * signal)11232 Dbdict::execALTER_INDX_CONF(Signal* signal)
11233 {
11234   jamEntry();
11235   ndbrequire(signal->getNoOfSections() == 0);
11236   AlterIndxConf* conf = (AlterIndxConf*)signal->getDataPtrSend();
11237   alterIndex_recvReply(signal, conf, 0);
11238 }
11239 
11240 void
execALTER_INDX_REF(Signal * signal)11241 Dbdict::execALTER_INDX_REF(Signal* signal)
11242 {
11243   jamEntry();
11244   AlterIndxRef* ref = (AlterIndxRef*)signal->getDataPtrSend();
11245   alterIndex_recvReply(signal, ref->getConf(), ref);
11246 }
11247 
11248 void
alterIndex_recvReply(Signal * signal,const AlterIndxConf * conf,const AlterIndxRef * ref)11249 Dbdict::alterIndex_recvReply(Signal* signal, const AlterIndxConf* conf,
11250     const AlterIndxRef* ref)
11251 {
11252   jam();
11253   const Uint32 senderRef = signal->senderBlockRef();
11254   const AlterIndxReq::RequestType requestType = conf->getRequestType();
11255   const Uint32 key = conf->getConnectionPtr();
11256   if (requestType == AlterIndxReq::RT_CREATE_INDEX) {
11257     jam();
11258     // part of create index operation
11259     OpCreateIndexPtr opPtr;
11260     c_opCreateIndex.find(opPtr, key);
11261     ndbrequire(! opPtr.isNull());
11262     opPtr.p->setError(ref);
11263     createIndex_fromAlterIndex(signal, opPtr);
11264     return;
11265   }
11266   if (requestType == AlterIndxReq::RT_DROP_INDEX) {
11267     jam();
11268     // part of drop index operation
11269     OpDropIndexPtr opPtr;
11270     c_opDropIndex.find(opPtr, key);
11271     ndbrequire(! opPtr.isNull());
11272     opPtr.p->setError(ref);
11273     dropIndex_fromAlterIndex(signal, opPtr);
11274     return;
11275   }
11276   if (requestType == AlterIndxReq::RT_TC ||
11277       requestType == AlterIndxReq::RT_TUX) {
11278     jam();
11279     // part of build index operation
11280     OpBuildIndexPtr opPtr;
11281     c_opBuildIndex.find(opPtr, key);
11282     ndbrequire(! opPtr.isNull());
11283     opPtr.p->setError(ref);
11284     buildIndex_fromOnline(signal, opPtr);
11285     return;
11286   }
11287   if (requestType == AlterIndxReq::RT_NODERESTART) {
11288     jam();
11289     if (ref == 0) {
11290       infoEvent("DICT: index %u activated", (unsigned)key);
11291     } else {
11292       warningEvent("DICT: index %u activation failed: code=%d line=%d",
11293           (unsigned)key,
11294           ref->getErrorCode(), ref->getErrorLine());
11295     }
11296     activateIndexes(signal, key + 1);
11297     return;
11298   }
11299   if (requestType == AlterIndxReq::RT_SYSTEMRESTART) {
11300     jam();
11301     if (ref == 0) {
11302       infoEvent("DICT: index %u activated done", (unsigned)key);
11303     } else {
11304       warningEvent("DICT: index %u activated failed: code=%d line=%d node=%d",
11305           (unsigned)key,
11306           ref->getErrorCode(), ref->getErrorLine(), ref->getErrorNode());
11307     }
11308     activateIndexes(signal, key + 1);
11309     return;
11310   }
11311   OpAlterIndexPtr opPtr;
11312   c_opAlterIndex.find(opPtr, key);
11313   ndbrequire(! opPtr.isNull());
11314   ndbrequire(opPtr.p->m_isMaster);
11315   ndbrequire(opPtr.p->m_requestType == requestType);
11316   opPtr.p->setError(ref);
11317   opPtr.p->m_signalCounter.clearWaitingFor(refToNode(senderRef));
11318   if (! opPtr.p->m_signalCounter.done()) {
11319     jam();
11320     return;
11321   }
11322   if (requestType == AlterIndxReq::RT_DICT_COMMIT ||
11323       requestType == AlterIndxReq::RT_DICT_ABORT) {
11324     jam();
11325     // send reply to user
11326     alterIndex_sendReply(signal, opPtr, true);
11327     c_opAlterIndex.release(opPtr);
11328     return;
11329   }
11330   if (opPtr.p->hasError()) {
11331     jam();
11332     opPtr.p->m_requestType = AlterIndxReq::RT_DICT_ABORT;
11333     alterIndex_sendSlaveReq(signal, opPtr);
11334     return;
11335   }
11336   TableRecordPtr indexPtr;
11337   c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
11338   if (indexPtr.p->isHashIndex()) {
11339     if (requestType == AlterIndxReq::RT_DICT_PREPARE) {
11340       jam();
11341       if (opPtr.p->m_request.getOnline()) {
11342         opPtr.p->m_requestType = AlterIndxReq::RT_DICT_TC;
11343         alterIndex_sendSlaveReq(signal, opPtr);
11344       } else {
11345         // start drop triggers
11346         alterIndex_toDropTrigger(signal, opPtr);
11347       }
11348       return;
11349     }
11350     if (requestType == AlterIndxReq::RT_DICT_TC) {
11351       jam();
11352       if (opPtr.p->m_request.getOnline()) {
11353         // start create triggers
11354         alterIndex_toCreateTrigger(signal, opPtr);
11355       } else {
11356         opPtr.p->m_requestType = AlterIndxReq::RT_DICT_COMMIT;
11357         alterIndex_sendSlaveReq(signal, opPtr);
11358       }
11359       return;
11360     }
11361   }
11362   if (indexPtr.p->isOrderedIndex()) {
11363     if (requestType == AlterIndxReq::RT_DICT_PREPARE) {
11364       jam();
11365       if (opPtr.p->m_request.getOnline()) {
11366         // start create triggers
11367         alterIndex_toCreateTrigger(signal, opPtr);
11368       } else {
11369         // start drop triggers
11370         alterIndex_toDropTrigger(signal, opPtr);
11371       }
11372       return;
11373     }
11374   }
11375   ndbrequire(false);
11376 }
11377 
11378 void
alterIndex_slavePrepare(Signal * signal,OpAlterIndexPtr opPtr)11379 Dbdict::alterIndex_slavePrepare(Signal* signal, OpAlterIndexPtr opPtr)
11380 {
11381   jam();
11382   const AlterIndxReq* const req = &opPtr.p->m_request;
11383   if (! (req->getIndexId() < c_tableRecordPool.getSize())) {
11384     jam();
11385     opPtr.p->m_errorCode = AlterIndxRef::Inconsistency;
11386     opPtr.p->m_errorLine = __LINE__;
11387     return;
11388   }
11389   TableRecordPtr indexPtr;
11390   c_tableRecordPool.getPtr(indexPtr, req->getIndexId());
11391   if (indexPtr.p->tabState != TableRecord::DEFINED) {
11392     jam();
11393     opPtr.p->m_errorCode = AlterIndxRef::IndexNotFound;
11394     opPtr.p->m_errorLine = __LINE__;
11395     return;
11396   }
11397   if (! indexPtr.p->isIndex()) {
11398     jam();
11399     opPtr.p->m_errorCode = AlterIndxRef::NotAnIndex;
11400     opPtr.p->m_errorLine = __LINE__;
11401     return;
11402   }
11403   if (req->getOnline())
11404     indexPtr.p->indexState = TableRecord::IS_BUILDING;
11405   else
11406     indexPtr.p->indexState = TableRecord::IS_DROPPING;
11407 }
11408 
11409 void
alterIndex_toCreateTc(Signal * signal,OpAlterIndexPtr opPtr)11410 Dbdict::alterIndex_toCreateTc(Signal* signal, OpAlterIndexPtr opPtr)
11411 {
11412   jam();
11413   TableRecordPtr indexPtr;
11414   c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
11415   // request to create index in local TC
11416   CreateIndxReq* const req = (CreateIndxReq*)signal->getDataPtrSend();
11417   req->setUserRef(reference());
11418   req->setConnectionPtr(opPtr.p->key);
11419   req->setRequestType(CreateIndxReq::RT_TC);
11420   req->setIndexType(indexPtr.p->tableType);
11421   req->setTableId(indexPtr.p->primaryTableId);
11422   req->setIndexId(indexPtr.i);
11423   req->setOnline(true);
11424   getIndexAttrList(indexPtr, opPtr.p->m_attrList);
11425   // send
11426   LinearSectionPtr lsPtr[3];
11427   lsPtr[0].p = (Uint32*)&opPtr.p->m_attrList;
11428   lsPtr[0].sz = 1 + opPtr.p->m_attrList.sz;
11429   sendSignal(calcTcBlockRef(getOwnNodeId()), GSN_CREATE_INDX_REQ,
11430       signal, CreateIndxReq::SignalLength, JBB, lsPtr, 1);
11431 }
11432 
11433 void
alterIndex_fromCreateTc(Signal * signal,OpAlterIndexPtr opPtr)11434 Dbdict::alterIndex_fromCreateTc(Signal* signal, OpAlterIndexPtr opPtr)
11435 {
11436   jam();
11437   // mark created in local TC
11438   if (! opPtr.p->hasLastError()) {
11439     TableRecordPtr indexPtr;
11440     c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
11441     indexPtr.p->indexLocal |= TableRecord::IL_CREATED_TC;
11442   }
11443   // forward CONF or REF to master
11444   ndbrequire(opPtr.p->m_requestType == AlterIndxReq::RT_DICT_TC);
11445   alterIndex_sendReply(signal, opPtr, false);
11446 }
11447 
11448 void
alterIndex_toDropTc(Signal * signal,OpAlterIndexPtr opPtr)11449 Dbdict::alterIndex_toDropTc(Signal* signal, OpAlterIndexPtr opPtr)
11450 {
11451   jam();
11452   TableRecordPtr indexPtr;
11453   c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
11454   // broken index allowed if force
11455   if (! (indexPtr.p->indexLocal & TableRecord::IL_CREATED_TC)) {
11456     jam();
11457     ndbassert(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
11458     alterIndex_sendReply(signal, opPtr, false);
11459     return;
11460   }
11461   // request to drop in local TC
11462   DropIndxReq* const req = (DropIndxReq*)signal->getDataPtrSend();
11463   req->setUserRef(reference());
11464   req->setConnectionPtr(opPtr.p->key);
11465   req->setRequestType(DropIndxReq::RT_TC);
11466   req->setTableId(indexPtr.p->primaryTableId);
11467   req->setIndexId(indexPtr.i);
11468   req->setIndexVersion(indexPtr.p->tableVersion);
11469   // send
11470   sendSignal(calcTcBlockRef(getOwnNodeId()), GSN_DROP_INDX_REQ,
11471       signal, DropIndxReq::SignalLength, JBB);
11472 }
11473 
11474 void
alterIndex_fromDropTc(Signal * signal,OpAlterIndexPtr opPtr)11475 Dbdict::alterIndex_fromDropTc(Signal* signal, OpAlterIndexPtr opPtr)
11476 {
11477   jam();
11478   ndbrequire(opPtr.p->m_requestType == AlterIndxReq::RT_DICT_TC);
11479   // mark dropped locally
11480   if (! opPtr.p->hasLastError()) {
11481     TableRecordPtr indexPtr;
11482     c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
11483     indexPtr.p->indexLocal &= ~TableRecord::IL_CREATED_TC;
11484   }
11485   // forward CONF or REF to master
11486   alterIndex_sendReply(signal, opPtr, false);
11487 }
11488 
11489 void
alterIndex_toCreateTrigger(Signal * signal,OpAlterIndexPtr opPtr)11490 Dbdict::alterIndex_toCreateTrigger(Signal* signal, OpAlterIndexPtr opPtr)
11491 {
11492   jam();
11493   TableRecordPtr indexPtr;
11494   c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
11495   // start creation of index triggers
11496   CreateTrigReq* const req = (CreateTrigReq*)signal->getDataPtrSend();
11497   req->setUserRef(reference());
11498   req->setConnectionPtr(opPtr.p->key);
11499   req->setRequestType(CreateTrigReq::RT_ALTER_INDEX);
11500   req->addRequestFlag(opPtr.p->m_requestFlag);
11501   req->setTableId(opPtr.p->m_request.getTableId());
11502   req->setIndexId(opPtr.p->m_request.getIndexId());
11503   req->setTriggerId(RNIL);
11504   req->setTriggerActionTime(TriggerActionTime::TA_AFTER);
11505   req->setMonitorAllAttributes(false);
11506   req->setOnline(true);         // alter online after create
11507   req->setReceiverRef(0);       // implicit for index triggers
11508   getIndexAttrMask(indexPtr, req->getAttributeMask());
11509   // name section
11510   char triggerName[MAX_TAB_NAME_SIZE];
11511   Uint32 buffer[2 + ((MAX_TAB_NAME_SIZE + 3) >> 2)];    // SP string
11512   LinearWriter w(buffer, sizeof(buffer) >> 2);
11513   LinearSectionPtr lsPtr[3];
11514   if (indexPtr.p->isHashIndex()) {
11515     req->setTriggerType(TriggerType::SECONDARY_INDEX);
11516     req->setMonitorReplicas(false);
11517     req->setReportAllMonitoredAttributes(true);
11518     // insert
11519     if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL)
11520       req->setTriggerId(indexPtr.p->insertTriggerId);
11521     req->setTriggerEvent(TriggerEvent::TE_INSERT);
11522     sprintf(triggerName, "NDB$INDEX_%u_INSERT", opPtr.p->m_request.getIndexId());
11523     w.reset();
11524     w.add(CreateTrigReq::TriggerNameKey, triggerName);
11525     lsPtr[0].p = buffer;
11526     lsPtr[0].sz = w.getWordsUsed();
11527     sendSignal(reference(), GSN_CREATE_TRIG_REQ,
11528         signal, CreateTrigReq::SignalLength, JBB, lsPtr, 1);
11529     // update
11530     if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL)
11531       req->setTriggerId(indexPtr.p->updateTriggerId);
11532     req->setTriggerEvent(TriggerEvent::TE_UPDATE);
11533     sprintf(triggerName, "NDB$INDEX_%u_UPDATE", opPtr.p->m_request.getIndexId());
11534     w.reset();
11535     w.add(CreateTrigReq::TriggerNameKey, triggerName);
11536     lsPtr[0].p = buffer;
11537     lsPtr[0].sz = w.getWordsUsed();
11538     sendSignal(reference(), GSN_CREATE_TRIG_REQ,
11539         signal, CreateTrigReq::SignalLength, JBB, lsPtr, 1);
11540     // delete
11541     if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL)
11542       req->setTriggerId(indexPtr.p->deleteTriggerId);
11543     req->setTriggerEvent(TriggerEvent::TE_DELETE);
11544     sprintf(triggerName, "NDB$INDEX_%u_DELETE", opPtr.p->m_request.getIndexId());
11545     w.reset();
11546     w.add(CreateTrigReq::TriggerNameKey, triggerName);
11547     lsPtr[0].p = buffer;
11548     lsPtr[0].sz = w.getWordsUsed();
11549     sendSignal(reference(), GSN_CREATE_TRIG_REQ,
11550         signal, CreateTrigReq::SignalLength, JBB, lsPtr, 1);
11551     // triggers left to create
11552     opPtr.p->m_triggerCounter = 3;
11553     return;
11554   }
11555   if (indexPtr.p->isOrderedIndex()) {
11556     req->addRequestFlag(RequestFlag::RF_NOTCTRIGGER);
11557     req->setTriggerType(TriggerType::ORDERED_INDEX);
11558     req->setTriggerActionTime(TriggerActionTime::TA_CUSTOM);
11559     req->setMonitorReplicas(true);
11560     req->setReportAllMonitoredAttributes(true);
11561     // one trigger for 5 events (insert, update, delete, commit, abort)
11562     if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL)
11563       req->setTriggerId(indexPtr.p->customTriggerId);
11564     req->setTriggerEvent(TriggerEvent::TE_CUSTOM);
11565     sprintf(triggerName, "NDB$INDEX_%u_CUSTOM", opPtr.p->m_request.getIndexId());
11566     w.reset();
11567     w.add(CreateTrigReq::TriggerNameKey, triggerName);
11568     lsPtr[0].p = buffer;
11569     lsPtr[0].sz = w.getWordsUsed();
11570     sendSignal(reference(), GSN_CREATE_TRIG_REQ,
11571         signal, CreateTrigReq::SignalLength, JBB, lsPtr, 1);
11572     // triggers left to create
11573     opPtr.p->m_triggerCounter = 1;
11574     return;
11575   }
11576   ndbrequire(false);
11577 }
11578 
11579 void
alterIndex_fromCreateTrigger(Signal * signal,OpAlterIndexPtr opPtr)11580 Dbdict::alterIndex_fromCreateTrigger(Signal* signal, OpAlterIndexPtr opPtr)
11581 {
11582   jam();
11583   ndbrequire(opPtr.p->m_triggerCounter != 0);
11584   if (--opPtr.p->m_triggerCounter != 0) {
11585     jam();
11586     return;
11587   }
11588   if (opPtr.p->hasError()) {
11589     jam();
11590     opPtr.p->m_requestType = AlterIndxReq::RT_DICT_ABORT;
11591     alterIndex_sendSlaveReq(signal, opPtr);
11592     return;
11593   }
11594   if(opPtr.p->m_requestType != AlterIndxReq::RT_SYSTEMRESTART){
11595     // send build request
11596     alterIndex_toBuildIndex(signal, opPtr);
11597     return;
11598   }
11599 
11600   /**
11601    * During system restart,
11602    *   leave index in activated but not build state.
11603    *
11604    * Build a bit later when REDO has been run
11605    */
11606   alterIndex_sendReply(signal, opPtr, true);
11607 }
11608 
11609 void
alterIndex_toDropTrigger(Signal * signal,OpAlterIndexPtr opPtr)11610 Dbdict::alterIndex_toDropTrigger(Signal* signal, OpAlterIndexPtr opPtr)
11611 {
11612   jam();
11613   TableRecordPtr indexPtr;
11614   c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
11615   // start drop of index triggers
11616   DropTrigReq* const req = (DropTrigReq*)signal->getDataPtrSend();
11617   req->setUserRef(reference());
11618   req->setConnectionPtr(opPtr.p->key);
11619   req->setRequestType(DropTrigReq::RT_ALTER_INDEX);
11620   req->addRequestFlag(opPtr.p->m_requestFlag);
11621   req->setTableId(opPtr.p->m_request.getTableId());
11622   req->setIndexId(opPtr.p->m_request.getIndexId());
11623   req->setTriggerInfo(0);       // not used
11624   opPtr.p->m_triggerCounter = 0;
11625   if (indexPtr.p->isHashIndex()) {
11626     // insert
11627     req->setTriggerId(indexPtr.p->insertTriggerId);
11628     sendSignal(reference(), GSN_DROP_TRIG_REQ,
11629         signal, DropTrigReq::SignalLength, JBB);
11630     opPtr.p->m_triggerCounter++;
11631     // update
11632     req->setTriggerId(indexPtr.p->updateTriggerId);
11633     sendSignal(reference(), GSN_DROP_TRIG_REQ,
11634         signal, DropTrigReq::SignalLength, JBB);
11635     opPtr.p->m_triggerCounter++;
11636     // delete
11637     req->setTriggerId(indexPtr.p->deleteTriggerId);
11638     sendSignal(reference(), GSN_DROP_TRIG_REQ,
11639         signal, DropTrigReq::SignalLength, JBB);
11640     opPtr.p->m_triggerCounter++;
11641     // build
11642     if (indexPtr.p->buildTriggerId != RNIL) {
11643       req->setTriggerId(indexPtr.p->buildTriggerId);
11644       sendSignal(reference(), GSN_DROP_TRIG_REQ,
11645           signal, DropTrigReq::SignalLength, JBB);
11646       opPtr.p->m_triggerCounter++;
11647     }
11648     return;
11649   }
11650   if (indexPtr.p->isOrderedIndex()) {
11651     // custom
11652     req->addRequestFlag(RequestFlag::RF_NOTCTRIGGER);
11653     req->setTriggerId(indexPtr.p->customTriggerId);
11654     sendSignal(reference(), GSN_DROP_TRIG_REQ,
11655         signal, DropTrigReq::SignalLength, JBB);
11656     opPtr.p->m_triggerCounter++;
11657     return;
11658   }
11659   ndbrequire(false);
11660 }
11661 
11662 void
alterIndex_fromDropTrigger(Signal * signal,OpAlterIndexPtr opPtr)11663 Dbdict::alterIndex_fromDropTrigger(Signal* signal, OpAlterIndexPtr opPtr)
11664 {
11665   jam();
11666   ndbrequire(opPtr.p->m_triggerCounter != 0);
11667   if (--opPtr.p->m_triggerCounter != 0) {
11668     jam();
11669     return;
11670   }
11671   // finally drop index in each TC
11672   TableRecordPtr indexPtr;
11673   c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
11674   const bool isHashIndex = indexPtr.p->isHashIndex();
11675   const bool isOrderedIndex = indexPtr.p->isOrderedIndex();
11676   ndbrequire(isHashIndex != isOrderedIndex);    // xor
11677   if (isHashIndex)
11678     opPtr.p->m_requestType = AlterIndxReq::RT_DICT_TC;
11679   if (isOrderedIndex)
11680     opPtr.p->m_requestType = AlterIndxReq::RT_DICT_COMMIT;
11681   alterIndex_sendSlaveReq(signal, opPtr);
11682 }
11683 
11684 void
alterIndex_toBuildIndex(Signal * signal,OpAlterIndexPtr opPtr)11685 Dbdict::alterIndex_toBuildIndex(Signal* signal, OpAlterIndexPtr opPtr)
11686 {
11687   jam();
11688   // get index and table records
11689   TableRecordPtr indexPtr;
11690   c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
11691   TableRecordPtr tablePtr;
11692   c_tableRecordPool.getPtr(tablePtr, indexPtr.p->primaryTableId);
11693   // build request to self (short signal)
11694   BuildIndxReq* const req = (BuildIndxReq*)signal->getDataPtrSend();
11695   req->setUserRef(reference());
11696   req->setConnectionPtr(opPtr.p->key);
11697   req->setRequestType(BuildIndxReq::RT_ALTER_INDEX);
11698   req->addRequestFlag(opPtr.p->m_requestFlag);
11699   req->setBuildId(0);   // not used
11700   req->setBuildKey(0);  // not used
11701   req->setIndexType(indexPtr.p->tableType);
11702   req->setIndexId(indexPtr.i);
11703   req->setTableId(indexPtr.p->primaryTableId);
11704   req->setParallelism(16);
11705   // send
11706   sendSignal(reference(), GSN_BUILDINDXREQ,
11707       signal, BuildIndxReq::SignalLength, JBB);
11708 }
11709 
11710 void
alterIndex_fromBuildIndex(Signal * signal,OpAlterIndexPtr opPtr)11711 Dbdict::alterIndex_fromBuildIndex(Signal* signal, OpAlterIndexPtr opPtr)
11712 {
11713   jam();
11714   if (opPtr.p->hasError()) {
11715     jam();
11716     opPtr.p->m_requestType = AlterIndxReq::RT_DICT_ABORT;
11717     alterIndex_sendSlaveReq(signal, opPtr);
11718     return;
11719   }
11720   opPtr.p->m_requestType = AlterIndxReq::RT_DICT_COMMIT;
11721   alterIndex_sendSlaveReq(signal, opPtr);
11722 }
11723 
11724 void
alterIndex_slaveCommit(Signal * signal,OpAlterIndexPtr opPtr)11725 Dbdict::alterIndex_slaveCommit(Signal* signal, OpAlterIndexPtr opPtr)
11726 {
11727   jam();
11728   // get index record
11729   TableRecordPtr indexPtr;
11730   c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
11731   indexPtr.p->indexState = TableRecord::IS_ONLINE;
11732 }
11733 
11734 void
alterIndex_slaveAbort(Signal * signal,OpAlterIndexPtr opPtr)11735 Dbdict::alterIndex_slaveAbort(Signal* signal, OpAlterIndexPtr opPtr)
11736 {
11737   jam();
11738   // find index record
11739   const Uint32 indexId = opPtr.p->m_request.getIndexId();
11740   if (indexId >= c_tableRecordPool.getSize())
11741     return;
11742   TableRecordPtr indexPtr;
11743   c_tableRecordPool.getPtr(indexPtr, indexId);
11744   if (! indexPtr.p->isIndex())
11745     return;
11746   // mark broken
11747   indexPtr.p->indexState = TableRecord::IS_BROKEN;
11748 }
11749 
11750 void
alterIndex_sendSlaveReq(Signal * signal,OpAlterIndexPtr opPtr)11751 Dbdict::alterIndex_sendSlaveReq(Signal* signal, OpAlterIndexPtr opPtr)
11752 {
11753   AlterIndxReq* const req = (AlterIndxReq*)signal->getDataPtrSend();
11754   *req = opPtr.p->m_request;
11755   req->setUserRef(opPtr.p->m_coordinatorRef);
11756   req->setConnectionPtr(opPtr.p->key);
11757   req->setRequestType(opPtr.p->m_requestType);
11758   req->addRequestFlag(opPtr.p->m_requestFlag);
11759   NdbNodeBitmask receiverNodes = c_aliveNodes;
11760   if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL) {
11761     receiverNodes.clear();
11762     receiverNodes.set(getOwnNodeId());
11763   }
11764   opPtr.p->m_signalCounter = receiverNodes;
11765   NodeReceiverGroup rg(DBDICT, receiverNodes);
11766   sendSignal(rg, GSN_ALTER_INDX_REQ,
11767       signal, AlterIndxReq::SignalLength, JBB);
11768 }
11769 
11770 void
alterIndex_sendReply(Signal * signal,OpAlterIndexPtr opPtr,bool toUser)11771 Dbdict::alterIndex_sendReply(Signal* signal, OpAlterIndexPtr opPtr,
11772     bool toUser)
11773 {
11774   AlterIndxRef* rep = (AlterIndxRef*)signal->getDataPtrSend();
11775   Uint32 gsn = GSN_ALTER_INDX_CONF;
11776   Uint32 length = AlterIndxConf::InternalLength;
11777   bool sendRef;
11778   if (! toUser) {
11779     sendRef = opPtr.p->hasLastError();
11780     rep->setUserRef(opPtr.p->m_coordinatorRef);
11781     rep->setConnectionPtr(opPtr.p->key);
11782     rep->setRequestType(opPtr.p->m_requestType);
11783     if (opPtr.p->m_requestType == AlterIndxReq::RT_DICT_ABORT)
11784       sendRef = false;
11785   } else {
11786     sendRef = opPtr.p->hasError();
11787     rep->setUserRef(opPtr.p->m_request.getUserRef());
11788     rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
11789     rep->setRequestType(opPtr.p->m_request.getRequestType());
11790     length = AlterIndxConf::SignalLength;
11791   }
11792   rep->setTableId(opPtr.p->m_request.getTableId());
11793   rep->setIndexId(opPtr.p->m_request.getIndexId());
11794   if (sendRef) {
11795     if (opPtr.p->m_errorNode == 0)
11796       opPtr.p->m_errorNode = getOwnNodeId();
11797     rep->setErrorCode(opPtr.p->m_errorCode);
11798     rep->setErrorLine(opPtr.p->m_errorLine);
11799     rep->setErrorNode(opPtr.p->m_errorNode);
11800     gsn = GSN_ALTER_INDX_REF;
11801     length = AlterIndxRef::SignalLength;
11802   }
11803   sendSignal(rep->getUserRef(), gsn, signal, length, JBB);
11804 }
11805 
11806 /**
11807  * MODULE: Build index
11808  *
11809  * Build index or all indexes on a table.  Request type:
11810  *
11811  * RT_USER - normal user request, not yet used
11812  * RT_ALTER_INDEX - from alter index
11813  * RT_SYSTEM_RESTART -
11814  * RT_DICT_PREPARE - prepare participants
11815  * RT_DICT_TRIX - to participant on way to local TRIX
11816  * RT_DICT_COMMIT - commit in each participant
11817  * RT_DICT_ABORT - abort
11818  * RT_TRIX - to local TRIX
11819  */
11820 
11821 void
execBUILDINDXREQ(Signal * signal)11822 Dbdict::execBUILDINDXREQ(Signal* signal)
11823 {
11824   jamEntry();
11825   BuildIndxReq* const req = (BuildIndxReq*)signal->getDataPtrSend();
11826   OpBuildIndexPtr opPtr;
11827   const Uint32 senderRef = signal->senderBlockRef();
11828   const BuildIndxReq::RequestType requestType = req->getRequestType();
11829   if (requestType == BuildIndxReq::RT_USER ||
11830       requestType == BuildIndxReq::RT_ALTER_INDEX ||
11831       requestType == BuildIndxReq::RT_SYSTEMRESTART) {
11832     jam();
11833 
11834     const bool isLocal = req->getRequestFlag() & RequestFlag::RF_LOCAL;
11835     NdbNodeBitmask receiverNodes = c_aliveNodes;
11836     if (isLocal) {
11837       receiverNodes.clear();
11838       receiverNodes.set(getOwnNodeId());
11839     }
11840 
11841     if (signal->getLength() == BuildIndxReq::SignalLength) {
11842       jam();
11843 
11844       if (!isLocal && getOwnNodeId() != c_masterNodeId) {
11845         jam();
11846 
11847 	releaseSections(signal);
11848 	OpBuildIndex opBad;
11849 	opPtr.p = &opBad;
11850 	opPtr.p->save(req);
11851 	opPtr.p->m_errorCode = BuildIndxRef::NotMaster;
11852 	opPtr.p->m_errorLine = __LINE__;
11853 	opPtr.p->m_errorNode = c_masterNodeId;
11854 	buildIndex_sendReply(signal, opPtr, true);
11855         return;
11856       }
11857       // forward initial request plus operation key to all
11858       req->setOpKey(++c_opRecordSequence);
11859       NodeReceiverGroup rg(DBDICT, receiverNodes);
11860       sendSignal(rg, GSN_BUILDINDXREQ,
11861 		 signal, BuildIndxReq::SignalLength + 1, JBB);
11862       return;
11863     }
11864     // seize operation record
11865     ndbrequire(signal->getLength() == BuildIndxReq::SignalLength + 1);
11866     const Uint32 opKey = req->getOpKey();
11867     OpBuildIndex opBusy;
11868     if (! c_opBuildIndex.seize(opPtr))
11869       opPtr.p = &opBusy;
11870     opPtr.p->save(req);
11871     opPtr.p->m_coordinatorRef = senderRef;
11872     opPtr.p->m_isMaster = (senderRef == reference());
11873     opPtr.p->key = opKey;
11874     opPtr.p->m_requestType = BuildIndxReq::RT_DICT_PREPARE;
11875     if (opPtr.p == &opBusy) {
11876       jam();
11877       opPtr.p->m_errorCode = BuildIndxRef::Busy;
11878       opPtr.p->m_errorLine = __LINE__;
11879       buildIndex_sendReply(signal, opPtr, opPtr.p->m_isMaster);
11880       return;
11881     }
11882     c_opBuildIndex.add(opPtr);
11883     // master expects to hear from all
11884     opPtr.p->m_signalCounter = receiverNodes;
11885     buildIndex_sendReply(signal, opPtr, false);
11886     return;
11887   }
11888   c_opBuildIndex.find(opPtr, req->getConnectionPtr());
11889   if (! opPtr.isNull()) {
11890     opPtr.p->m_requestType = requestType;
11891     if (requestType == BuildIndxReq::RT_DICT_TRIX) {
11892       jam();
11893       buildIndex_buildTrix(signal, opPtr);
11894       return;
11895     }
11896     if (requestType == BuildIndxReq::RT_DICT_TC ||
11897         requestType == BuildIndxReq::RT_DICT_TUX) {
11898       jam();
11899       buildIndex_toOnline(signal, opPtr);
11900       return;
11901     }
11902     if (requestType == BuildIndxReq::RT_DICT_COMMIT ||
11903         requestType == BuildIndxReq::RT_DICT_ABORT) {
11904       jam();
11905       buildIndex_sendReply(signal, opPtr, false);
11906       // done in slave
11907       if (! opPtr.p->m_isMaster)
11908         c_opBuildIndex.release(opPtr);
11909       return;
11910     }
11911   }
11912   jam();
11913   // return to sender
11914   OpBuildIndex opBad;
11915   opPtr.p = &opBad;
11916   opPtr.p->save(req);
11917   opPtr.p->m_errorCode = BuildIndxRef::BadRequestType;
11918   opPtr.p->m_errorLine = __LINE__;
11919   buildIndex_sendReply(signal, opPtr, true);
11920 }
11921 
11922 void
execBUILDINDXCONF(Signal * signal)11923 Dbdict::execBUILDINDXCONF(Signal* signal)
11924 {
11925   jamEntry();
11926   ndbrequire(signal->getNoOfSections() == 0);
11927   BuildIndxConf* conf = (BuildIndxConf*)signal->getDataPtrSend();
11928   buildIndex_recvReply(signal, conf, 0);
11929 }
11930 
11931 void
execBUILDINDXREF(Signal * signal)11932 Dbdict::execBUILDINDXREF(Signal* signal)
11933 {
11934   jamEntry();
11935   BuildIndxRef* ref = (BuildIndxRef*)signal->getDataPtrSend();
11936   buildIndex_recvReply(signal, ref->getConf(), ref);
11937 }
11938 
11939 void
buildIndex_recvReply(Signal * signal,const BuildIndxConf * conf,const BuildIndxRef * ref)11940 Dbdict::buildIndex_recvReply(Signal* signal, const BuildIndxConf* conf,
11941     const BuildIndxRef* ref)
11942 {
11943   jam();
11944   const Uint32 senderRef = signal->senderBlockRef();
11945   const BuildIndxReq::RequestType requestType = conf->getRequestType();
11946   const Uint32 key = conf->getConnectionPtr();
11947   if (requestType == BuildIndxReq::RT_ALTER_INDEX) {
11948     jam();
11949     // part of alter index operation
11950     OpAlterIndexPtr opPtr;
11951     c_opAlterIndex.find(opPtr, key);
11952     ndbrequire(! opPtr.isNull());
11953     opPtr.p->setError(ref);
11954     alterIndex_fromBuildIndex(signal, opPtr);
11955     return;
11956   }
11957 
11958   if (requestType == BuildIndxReq::RT_SYSTEMRESTART) {
11959     jam();
11960     if (ref == 0) {
11961       infoEvent("DICT: index %u rebuild done", (unsigned)key);
11962     } else {
11963       warningEvent("DICT: index %u rebuild failed: code=%d line=%d node=%d",
11964 		   (unsigned)key, ref->getErrorCode());
11965     }
11966     rebuildIndexes(signal, key + 1);
11967     return;
11968   }
11969 
11970   OpBuildIndexPtr opPtr;
11971   c_opBuildIndex.find(opPtr, key);
11972   ndbrequire(! opPtr.isNull());
11973   opPtr.p->setError(ref);
11974   if (requestType == BuildIndxReq::RT_TRIX) {
11975     jam();
11976     // forward to master
11977     opPtr.p->m_requestType = BuildIndxReq::RT_DICT_TRIX;
11978     buildIndex_sendReply(signal, opPtr, false);
11979     return;
11980   }
11981   ndbrequire(opPtr.p->m_isMaster);
11982   ndbrequire(opPtr.p->m_requestType == requestType);
11983   opPtr.p->m_signalCounter.clearWaitingFor(refToNode(senderRef));
11984   if (! opPtr.p->m_signalCounter.done()) {
11985     jam();
11986     return;
11987   }
11988   if (requestType == BuildIndxReq::RT_DICT_COMMIT ||
11989       requestType == BuildIndxReq::RT_DICT_ABORT) {
11990     jam();
11991     // send reply to user
11992     buildIndex_sendReply(signal, opPtr, true);
11993     c_opBuildIndex.release(opPtr);
11994     return;
11995   }
11996   if (opPtr.p->hasError()) {
11997     jam();
11998     opPtr.p->m_requestType = BuildIndxReq::RT_DICT_ABORT;
11999     buildIndex_sendSlaveReq(signal, opPtr);
12000     return;
12001   }
12002   TableRecordPtr indexPtr;
12003   c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
12004   if (indexPtr.p->isHashIndex()) {
12005     if (requestType == BuildIndxReq::RT_DICT_PREPARE) {
12006       jam();
12007       if (! (opPtr.p->m_requestFlag & RequestFlag::RF_NOBUILD)) {
12008         buildIndex_toCreateConstr(signal, opPtr);
12009       } else {
12010         opPtr.p->m_requestType = BuildIndxReq::RT_DICT_TC;
12011         buildIndex_sendSlaveReq(signal, opPtr);
12012       }
12013       return;
12014     }
12015     if (requestType == BuildIndxReq::RT_DICT_TRIX) {
12016       jam();
12017       ndbrequire(! (opPtr.p->m_requestFlag & RequestFlag::RF_NOBUILD));
12018       buildIndex_toDropConstr(signal, opPtr);
12019       return;
12020     }
12021     if (requestType == BuildIndxReq::RT_DICT_TC) {
12022       jam();
12023       opPtr.p->m_requestType = BuildIndxReq::RT_DICT_COMMIT;
12024       buildIndex_sendSlaveReq(signal, opPtr);
12025       return;
12026     }
12027   }
12028   if (indexPtr.p->isOrderedIndex()) {
12029     if (requestType == BuildIndxReq::RT_DICT_PREPARE) {
12030       jam();
12031       if (! (opPtr.p->m_requestFlag & RequestFlag::RF_NOBUILD)) {
12032         opPtr.p->m_requestType = BuildIndxReq::RT_DICT_TRIX;
12033         buildIndex_sendSlaveReq(signal, opPtr);
12034       } else {
12035         opPtr.p->m_requestType = BuildIndxReq::RT_DICT_TUX;
12036         buildIndex_sendSlaveReq(signal, opPtr);
12037       }
12038       return;
12039     }
12040     if (requestType == BuildIndxReq::RT_DICT_TRIX) {
12041       jam();
12042       ndbrequire(! (opPtr.p->m_requestFlag & RequestFlag::RF_NOBUILD));
12043       opPtr.p->m_requestType = BuildIndxReq::RT_DICT_TUX;
12044       buildIndex_sendSlaveReq(signal, opPtr);
12045       return;
12046     }
12047     if (requestType == BuildIndxReq::RT_DICT_TUX) {
12048       jam();
12049       opPtr.p->m_requestType = BuildIndxReq::RT_DICT_COMMIT;
12050       buildIndex_sendSlaveReq(signal, opPtr);
12051       return;
12052     }
12053   }
12054   ndbrequire(false);
12055 }
12056 
12057 void
buildIndex_toCreateConstr(Signal * signal,OpBuildIndexPtr opPtr)12058 Dbdict::buildIndex_toCreateConstr(Signal* signal, OpBuildIndexPtr opPtr)
12059 {
12060   jam();
12061   TableRecordPtr indexPtr;
12062   c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
12063   // request to create constraint trigger
12064   CreateTrigReq* req = (CreateTrigReq*)signal->getDataPtrSend();
12065   req->setUserRef(reference());
12066   req->setConnectionPtr(opPtr.p->key);
12067   req->setRequestType(CreateTrigReq::RT_BUILD_INDEX);
12068   req->addRequestFlag(0);       // none
12069   req->setTableId(indexPtr.i);
12070   req->setIndexId(RNIL);
12071   req->setTriggerId(RNIL);
12072   req->setTriggerType(TriggerType::READ_ONLY_CONSTRAINT);
12073   req->setTriggerActionTime(TriggerActionTime::TA_AFTER);
12074   req->setTriggerEvent(TriggerEvent::TE_UPDATE);
12075   req->setMonitorReplicas(false);
12076   req->setMonitorAllAttributes(false);
12077   req->setReportAllMonitoredAttributes(true);
12078   req->setOnline(true);         // alter online after create
12079   req->setReceiverRef(0);       // no receiver, REF-ed by TUP
12080   req->getAttributeMask().clear();
12081   // NDB$PK is last attribute
12082   req->getAttributeMask().set(indexPtr.p->noOfAttributes - 1);
12083   // name section
12084   char triggerName[MAX_TAB_NAME_SIZE];
12085   Uint32 buffer[2 + ((MAX_TAB_NAME_SIZE + 3) >> 2)];    // SP string
12086   LinearWriter w(buffer, sizeof(buffer) >> 2);
12087   LinearSectionPtr lsPtr[3];
12088   sprintf(triggerName, "NDB$INDEX_%u_BUILD", indexPtr.i);
12089   w.reset();
12090   w.add(CreateTrigReq::TriggerNameKey, triggerName);
12091   lsPtr[0].p = buffer;
12092   lsPtr[0].sz = w.getWordsUsed();
12093   sendSignal(reference(), GSN_CREATE_TRIG_REQ,
12094       signal, CreateTrigReq::SignalLength, JBB, lsPtr, 1);
12095 }
12096 
12097 void
buildIndex_fromCreateConstr(Signal * signal,OpBuildIndexPtr opPtr)12098 Dbdict::buildIndex_fromCreateConstr(Signal* signal, OpBuildIndexPtr opPtr)
12099 {
12100   jam();
12101   if (opPtr.p->hasError()) {
12102     jam();
12103     opPtr.p->m_requestType = BuildIndxReq::RT_DICT_ABORT;
12104     buildIndex_sendSlaveReq(signal, opPtr);
12105     return;
12106   }
12107   opPtr.p->m_requestType = BuildIndxReq::RT_DICT_TRIX;
12108   buildIndex_sendSlaveReq(signal, opPtr);
12109 }
12110 
12111 void
buildIndex_buildTrix(Signal * signal,OpBuildIndexPtr opPtr)12112 Dbdict::buildIndex_buildTrix(Signal* signal, OpBuildIndexPtr opPtr)
12113 {
12114   jam();
12115   TableRecordPtr indexPtr;
12116   c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
12117   TableRecordPtr tablePtr;
12118   c_tableRecordPool.getPtr(tablePtr, indexPtr.p->primaryTableId);
12119   // build request
12120   BuildIndxReq* const req = (BuildIndxReq*)signal->getDataPtrSend();
12121   req->setUserRef(reference());
12122   req->setConnectionPtr(opPtr.p->key);
12123   req->setRequestType(BuildIndxReq::RT_TRIX);
12124   req->setBuildId(0);   // not yet..
12125   req->setBuildKey(0);  // ..in use
12126   req->setIndexType(indexPtr.p->tableType);
12127   req->setIndexId(indexPtr.i);
12128   req->setTableId(indexPtr.p->primaryTableId);
12129   req->setParallelism(16);
12130   if (indexPtr.p->isHashIndex()) {
12131     jam();
12132     getIndexAttrList(indexPtr, opPtr.p->m_attrList);
12133     getTableKeyList(tablePtr, opPtr.p->m_tableKeyList);
12134     // send
12135     LinearSectionPtr lsPtr[3];
12136     lsPtr[0].sz = opPtr.p->m_attrList.sz;
12137     lsPtr[0].p = opPtr.p->m_attrList.id;
12138     lsPtr[1].sz = opPtr.p->m_tableKeyList.sz;
12139     lsPtr[1].p = opPtr.p->m_tableKeyList.id;
12140     sendSignal(calcTrixBlockRef(getOwnNodeId()), GSN_BUILDINDXREQ,
12141         signal, BuildIndxReq::SignalLength, JBB, lsPtr, 2);
12142     return;
12143   }
12144   if (indexPtr.p->isOrderedIndex()) {
12145     jam();
12146     sendSignal(calcTupBlockRef(getOwnNodeId()), GSN_BUILDINDXREQ,
12147         signal, BuildIndxReq::SignalLength, JBB);
12148     return;
12149   }
12150   ndbrequire(false);
12151 }
12152 
12153 void
buildIndex_toDropConstr(Signal * signal,OpBuildIndexPtr opPtr)12154 Dbdict::buildIndex_toDropConstr(Signal* signal, OpBuildIndexPtr opPtr)
12155 {
12156   jam();
12157   TableRecordPtr indexPtr;
12158   c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
12159   // request to drop constraint trigger
12160   DropTrigReq* req = (DropTrigReq*)signal->getDataPtrSend();
12161   req->setUserRef(reference());
12162   req->setConnectionPtr(opPtr.p->key);
12163   req->setRequestType(DropTrigReq::RT_BUILD_INDEX);
12164   req->addRequestFlag(0);       // none
12165   req->setTableId(indexPtr.i);
12166   req->setIndexId(RNIL);
12167   req->setTriggerId(opPtr.p->m_constrTriggerId);
12168   req->setTriggerInfo(0);       // not used
12169   sendSignal(reference(), GSN_DROP_TRIG_REQ,
12170       signal, DropTrigReq::SignalLength, JBB);
12171 }
12172 
12173 void
buildIndex_fromDropConstr(Signal * signal,OpBuildIndexPtr opPtr)12174 Dbdict::buildIndex_fromDropConstr(Signal* signal, OpBuildIndexPtr opPtr)
12175 {
12176   jam();
12177   if (opPtr.p->hasError()) {
12178     jam();
12179     opPtr.p->m_requestType = BuildIndxReq::RT_DICT_ABORT;
12180     buildIndex_sendSlaveReq(signal, opPtr);
12181     return;
12182   }
12183   opPtr.p->m_requestType = BuildIndxReq::RT_DICT_TC;
12184   buildIndex_sendSlaveReq(signal, opPtr);
12185 }
12186 
12187 void
buildIndex_toOnline(Signal * signal,OpBuildIndexPtr opPtr)12188 Dbdict::buildIndex_toOnline(Signal* signal, OpBuildIndexPtr opPtr)
12189 {
12190   jam();
12191   TableRecordPtr indexPtr;
12192   c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
12193   TableRecordPtr tablePtr;
12194   c_tableRecordPool.getPtr(tablePtr, indexPtr.p->primaryTableId);
12195   // request to set index online in TC or TUX
12196   AlterIndxReq* const req = (AlterIndxReq*)signal->getDataPtrSend();
12197   req->setUserRef(reference());
12198   req->setConnectionPtr(opPtr.p->key);
12199   if (opPtr.p->m_requestType == BuildIndxReq::RT_DICT_TC) {
12200     jam();
12201     req->setRequestType(AlterIndxReq::RT_TC);
12202   } else if (opPtr.p->m_requestType == BuildIndxReq::RT_DICT_TUX) {
12203     jam();
12204     req->setRequestType(AlterIndxReq::RT_TUX);
12205   } else {
12206     ndbrequire(false);
12207   }
12208   req->setTableId(tablePtr.i);
12209   req->setIndexId(indexPtr.i);
12210   req->setIndexVersion(indexPtr.p->tableVersion);
12211   req->setOnline(true);
12212   BlockReference blockRef = 0;
12213   if (opPtr.p->m_requestType == BuildIndxReq::RT_DICT_TC) {
12214     jam();
12215     blockRef = calcTcBlockRef(getOwnNodeId());
12216   } else if (opPtr.p->m_requestType == BuildIndxReq::RT_DICT_TUX) {
12217     jam();
12218     blockRef = calcTuxBlockRef(getOwnNodeId());
12219   } else {
12220     ndbrequire(false);
12221   }
12222   // send
12223   sendSignal(blockRef, GSN_ALTER_INDX_REQ,
12224       signal, BuildIndxReq::SignalLength, JBB);
12225 }
12226 
12227 void
buildIndex_fromOnline(Signal * signal,OpBuildIndexPtr opPtr)12228 Dbdict::buildIndex_fromOnline(Signal* signal, OpBuildIndexPtr opPtr)
12229 {
12230   jam();
12231   // forward to master
12232   buildIndex_sendReply(signal, opPtr, false);
12233 }
12234 
12235 void
buildIndex_sendSlaveReq(Signal * signal,OpBuildIndexPtr opPtr)12236 Dbdict::buildIndex_sendSlaveReq(Signal* signal, OpBuildIndexPtr opPtr)
12237 {
12238   BuildIndxReq* const req = (BuildIndxReq*)signal->getDataPtrSend();
12239   *req = opPtr.p->m_request;
12240   req->setUserRef(opPtr.p->m_coordinatorRef);
12241   req->setConnectionPtr(opPtr.p->key);
12242   req->setRequestType(opPtr.p->m_requestType);
12243   req->addRequestFlag(opPtr.p->m_requestFlag);
12244   if(opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL) {
12245     jam();
12246     opPtr.p->m_signalCounter.clearWaitingFor();
12247     opPtr.p->m_signalCounter.setWaitingFor(getOwnNodeId());
12248     sendSignal(reference(), GSN_BUILDINDXREQ,
12249 	       signal, BuildIndxReq::SignalLength, JBB);
12250   } else {
12251     jam();
12252     opPtr.p->m_signalCounter = c_aliveNodes;
12253     NodeReceiverGroup rg(DBDICT, c_aliveNodes);
12254     sendSignal(rg, GSN_BUILDINDXREQ,
12255 	       signal, BuildIndxReq::SignalLength, JBB);
12256   }
12257 }
12258 
12259 void
buildIndex_sendReply(Signal * signal,OpBuildIndexPtr opPtr,bool toUser)12260 Dbdict::buildIndex_sendReply(Signal* signal, OpBuildIndexPtr opPtr,
12261     bool toUser)
12262 {
12263   BuildIndxRef* rep = (BuildIndxRef*)signal->getDataPtrSend();
12264   Uint32 gsn = GSN_BUILDINDXCONF;
12265   Uint32 length = BuildIndxConf::InternalLength;
12266   bool sendRef;
12267   if (! toUser) {
12268     sendRef = opPtr.p->hasLastError();
12269     rep->setUserRef(opPtr.p->m_coordinatorRef);
12270     rep->setConnectionPtr(opPtr.p->key);
12271     rep->setRequestType(opPtr.p->m_requestType);
12272     if (opPtr.p->m_requestType == BuildIndxReq::RT_DICT_ABORT)
12273       sendRef = false;
12274   } else {
12275     sendRef = opPtr.p->hasError();
12276     rep->setUserRef(opPtr.p->m_request.getUserRef());
12277     rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
12278     rep->setRequestType(opPtr.p->m_request.getRequestType());
12279     length = BuildIndxConf::SignalLength;
12280   }
12281   rep->setIndexType(opPtr.p->m_request.getIndexType());
12282   rep->setTableId(opPtr.p->m_request.getTableId());
12283   rep->setIndexId(opPtr.p->m_request.getIndexId());
12284   if (sendRef) {
12285     rep->setErrorCode(opPtr.p->m_errorCode);
12286     rep->masterNodeId = opPtr.p->m_errorNode;
12287     gsn = GSN_BUILDINDXREF;
12288     length = BuildIndxRef::SignalLength;
12289   }
12290   sendSignal(rep->getUserRef(), gsn, signal, length, JBB);
12291 }
12292 
12293 /**
12294  * MODULE: Create trigger
12295  *
12296  * Create trigger in all DICT blocks.  Optionally start alter trigger
12297  * operation to set the trigger online.
12298  *
12299  * Request type received in REQ and returned in CONF/REF:
12300  *
12301  * RT_USER - normal user e.g. BACKUP
12302  * RT_ALTER_INDEX - from alter index online
12303  * RT_DICT_PREPARE - seize operation in each DICT
12304  * RT_DICT_COMMIT - commit create in each DICT
12305  * RT_TC - sending to TC (operation alter trigger)
12306  * RT_LQH - sending to LQH (operation alter trigger)
12307  */
12308 
12309 void
execCREATE_TRIG_REQ(Signal * signal)12310 Dbdict::execCREATE_TRIG_REQ(Signal* signal)
12311 {
12312   jamEntry();
12313   CreateTrigReq* const req = (CreateTrigReq*)signal->getDataPtrSend();
12314   OpCreateTriggerPtr opPtr;
12315   const Uint32 senderRef = signal->senderBlockRef();
12316   const CreateTrigReq::RequestType requestType = req->getRequestType();
12317   if (requestType == CreateTrigReq::RT_USER ||
12318       requestType == CreateTrigReq::RT_ALTER_INDEX ||
12319       requestType == CreateTrigReq::RT_BUILD_INDEX) {
12320     jam();
12321     if (! assembleFragments(signal)) {
12322       jam();
12323       return;
12324     }
12325     const bool isLocal = req->getRequestFlag() & RequestFlag::RF_LOCAL;
12326     NdbNodeBitmask receiverNodes = c_aliveNodes;
12327     if (isLocal) {
12328       receiverNodes.clear();
12329       receiverNodes.set(getOwnNodeId());
12330     }
12331     if (signal->getLength() == CreateTrigReq::SignalLength) {
12332       jam();
12333       if (! isLocal && getOwnNodeId() != c_masterNodeId) {
12334         jam();
12335 
12336 	releaseSections(signal);
12337 	OpCreateTrigger opBad;
12338 	opPtr.p = &opBad;
12339 	opPtr.p->save(req);
12340 	opPtr.p->m_errorCode = CreateTrigRef::NotMaster;
12341 	opPtr.p->m_errorLine = __LINE__;
12342 	opPtr.p->m_errorNode = c_masterNodeId;
12343 	createTrigger_sendReply(signal,  opPtr, true);
12344         return;
12345       }
12346       // forward initial request plus operation key to all
12347       req->setOpKey(++c_opRecordSequence);
12348       NodeReceiverGroup rg(DBDICT, receiverNodes);
12349       sendSignal(rg, GSN_CREATE_TRIG_REQ,
12350           signal, CreateTrigReq::SignalLength + 1, JBB);
12351       return;
12352     }
12353     // seize operation record
12354     ndbrequire(signal->getLength() == CreateTrigReq::SignalLength + 1);
12355     const Uint32 opKey = req->getOpKey();
12356     OpCreateTrigger opBusy;
12357     if (! c_opCreateTrigger.seize(opPtr))
12358       opPtr.p = &opBusy;
12359     opPtr.p->save(req);
12360     opPtr.p->m_coordinatorRef = senderRef;
12361     opPtr.p->m_isMaster = (senderRef == reference());
12362     opPtr.p->key = opKey;
12363     opPtr.p->m_requestType = CreateTrigReq::RT_DICT_PREPARE;
12364     if (opPtr.p == &opBusy) {
12365       jam();
12366       opPtr.p->m_errorCode = CreateTrigRef::Busy;
12367       opPtr.p->m_errorLine = __LINE__;
12368       releaseSections(signal);
12369       createTrigger_sendReply(signal, opPtr, opPtr.p->m_isMaster);
12370       return;
12371     }
12372     c_opCreateTrigger.add(opPtr);
12373     {
12374       // save name
12375       SegmentedSectionPtr ssPtr;
12376       signal->getSection(ssPtr, CreateTrigReq::TRIGGER_NAME_SECTION);
12377       SimplePropertiesSectionReader ssReader(ssPtr, getSectionSegmentPool());
12378       if (ssReader.getKey() != CreateTrigReq::TriggerNameKey ||
12379 	  ! ssReader.getString(opPtr.p->m_triggerName)) {
12380 	jam();
12381 	opPtr.p->m_errorCode = CreateTrigRef::InvalidName;
12382 	opPtr.p->m_errorLine = __LINE__;
12383 	releaseSections(signal);
12384 	createTrigger_sendReply(signal, opPtr, opPtr.p->m_isMaster);
12385 	return;
12386       }
12387     }
12388     releaseSections(signal);
12389     if(get_object(opPtr.p->m_triggerName) != 0){
12390       jam();
12391       opPtr.p->m_errorCode = CreateTrigRef::TriggerExists;
12392       opPtr.p->m_errorLine = __LINE__;
12393       createTrigger_sendReply(signal, opPtr, opPtr.p->m_isMaster);
12394       return;
12395     }
12396 
12397     // master expects to hear from all
12398     if (opPtr.p->m_isMaster)
12399       opPtr.p->m_signalCounter = receiverNodes;
12400     // check request in all participants
12401     createTrigger_slavePrepare(signal, opPtr);
12402     createTrigger_sendReply(signal, opPtr, false);
12403     return;
12404   }
12405   c_opCreateTrigger.find(opPtr, req->getConnectionPtr());
12406   if (! opPtr.isNull()) {
12407     opPtr.p->m_requestType = requestType;
12408     if (requestType == CreateTrigReq::RT_DICT_CREATE) {
12409       jam();
12410       // master has set trigger id
12411       opPtr.p->m_request.setTriggerId(req->getTriggerId());
12412       createTrigger_slaveCreate(signal, opPtr);
12413       createTrigger_sendReply(signal, opPtr, false);
12414       return;
12415     }
12416     if (requestType == CreateTrigReq::RT_DICT_COMMIT ||
12417         requestType == CreateTrigReq::RT_DICT_ABORT) {
12418       jam();
12419       if (requestType == CreateTrigReq::RT_DICT_COMMIT)
12420         createTrigger_slaveCommit(signal, opPtr);
12421       else
12422         createTrigger_slaveAbort(signal, opPtr);
12423       createTrigger_sendReply(signal, opPtr, false);
12424       // done in slave
12425       if (! opPtr.p->m_isMaster)
12426         c_opCreateTrigger.release(opPtr);
12427       return;
12428     }
12429   }
12430   jam();
12431   // return to sender
12432   releaseSections(signal);
12433   OpCreateTrigger opBad;
12434   opPtr.p = &opBad;
12435   opPtr.p->save(req);
12436   opPtr.p->m_errorCode = CreateTrigRef::BadRequestType;
12437   opPtr.p->m_errorLine = __LINE__;
12438   createTrigger_sendReply(signal,  opPtr, true);
12439 }
12440 
12441 void
execCREATE_TRIG_CONF(Signal * signal)12442 Dbdict::execCREATE_TRIG_CONF(Signal* signal)
12443 {
12444   jamEntry();
12445   ndbrequire(signal->getNoOfSections() == 0);
12446   CreateTrigConf* conf = (CreateTrigConf*)signal->getDataPtrSend();
12447   createTrigger_recvReply(signal, conf, 0);
12448 }
12449 
12450 void
execCREATE_TRIG_REF(Signal * signal)12451 Dbdict::execCREATE_TRIG_REF(Signal* signal)
12452 {
12453   jamEntry();
12454   CreateTrigRef* ref = (CreateTrigRef*)signal->getDataPtrSend();
12455   createTrigger_recvReply(signal, ref->getConf(), ref);
12456 }
12457 
12458 void
createTrigger_recvReply(Signal * signal,const CreateTrigConf * conf,const CreateTrigRef * ref)12459 Dbdict::createTrigger_recvReply(Signal* signal, const CreateTrigConf* conf,
12460     const CreateTrigRef* ref)
12461 {
12462   jam();
12463   const Uint32 senderRef = signal->senderBlockRef();
12464   const CreateTrigReq::RequestType requestType = conf->getRequestType();
12465   const Uint32 key = conf->getConnectionPtr();
12466   if (requestType == CreateTrigReq::RT_ALTER_INDEX) {
12467     jam();
12468     // part of alter index operation
12469     OpAlterIndexPtr opPtr;
12470     c_opAlterIndex.find(opPtr, key);
12471     ndbrequire(! opPtr.isNull());
12472     opPtr.p->setError(ref);
12473     alterIndex_fromCreateTrigger(signal, opPtr);
12474     return;
12475   }
12476   if (requestType == CreateTrigReq::RT_BUILD_INDEX) {
12477     jam();
12478     // part of build index operation
12479     OpBuildIndexPtr opPtr;
12480     c_opBuildIndex.find(opPtr, key);
12481     ndbrequire(! opPtr.isNull());
12482     opPtr.p->setError(ref);
12483     // fill in trigger id
12484     opPtr.p->m_constrTriggerId = conf->getTriggerId();
12485     buildIndex_fromCreateConstr(signal, opPtr);
12486     return;
12487   }
12488   if (requestType == CreateTrigReq::RT_TC ||
12489       requestType == CreateTrigReq::RT_LQH) {
12490     jam();
12491     // part of alter trigger operation
12492     OpAlterTriggerPtr opPtr;
12493     c_opAlterTrigger.find(opPtr, key);
12494     ndbrequire(! opPtr.isNull());
12495     opPtr.p->setError(ref);
12496     alterTrigger_fromCreateLocal(signal, opPtr);
12497     return;
12498   }
12499   OpCreateTriggerPtr opPtr;
12500   c_opCreateTrigger.find(opPtr, key);
12501   ndbrequire(! opPtr.isNull());
12502   ndbrequire(opPtr.p->m_isMaster);
12503   ndbrequire(opPtr.p->m_requestType == requestType);
12504   opPtr.p->setError(ref);
12505   opPtr.p->m_signalCounter.clearWaitingFor(refToNode(senderRef));
12506   if (! opPtr.p->m_signalCounter.done()) {
12507     jam();
12508     return;
12509   }
12510   if (requestType == CreateTrigReq::RT_DICT_COMMIT ||
12511       requestType == CreateTrigReq::RT_DICT_ABORT) {
12512     jam();
12513     // send reply to user
12514     createTrigger_sendReply(signal, opPtr, true);
12515     c_opCreateTrigger.release(opPtr);
12516     return;
12517   }
12518   if (opPtr.p->hasError()) {
12519     jam();
12520     opPtr.p->m_requestType = CreateTrigReq::RT_DICT_ABORT;
12521     createTrigger_sendSlaveReq(signal, opPtr);
12522     return;
12523   }
12524   if (requestType == CreateTrigReq::RT_DICT_PREPARE) {
12525     jam();
12526     // seize trigger id in master
12527     createTrigger_masterSeize(signal, opPtr);
12528     if (opPtr.p->hasError()) {
12529       jam();
12530       opPtr.p->m_requestType = CreateTrigReq::RT_DICT_ABORT;
12531       createTrigger_sendSlaveReq(signal, opPtr);
12532       return;
12533     }
12534     opPtr.p->m_requestType = CreateTrigReq::RT_DICT_CREATE;
12535     createTrigger_sendSlaveReq(signal, opPtr);
12536     return;
12537   }
12538   if (requestType == CreateTrigReq::RT_DICT_CREATE) {
12539     jam();
12540     if (opPtr.p->m_request.getOnline()) {
12541       jam();
12542       // start alter online
12543       createTrigger_toAlterTrigger(signal, opPtr);
12544       return;
12545     }
12546     opPtr.p->m_requestType = CreateTrigReq::RT_DICT_COMMIT;
12547     createTrigger_sendSlaveReq(signal, opPtr);
12548     return;
12549   }
12550   ndbrequire(false);
12551 }
12552 
12553 void
createTrigger_slavePrepare(Signal * signal,OpCreateTriggerPtr opPtr)12554 Dbdict::createTrigger_slavePrepare(Signal* signal, OpCreateTriggerPtr opPtr)
12555 {
12556   jam();
12557   const CreateTrigReq* const req = &opPtr.p->m_request;
12558   // check trigger type
12559   if (req->getRequestType() == CreateTrigReq::RT_USER &&
12560       req->getTriggerType() == TriggerType::SUBSCRIPTION ||
12561       req->getRequestType() == CreateTrigReq::RT_ALTER_INDEX &&
12562       req->getTriggerType() == TriggerType::SECONDARY_INDEX ||
12563       req->getRequestType() == CreateTrigReq::RT_ALTER_INDEX &&
12564       req->getTriggerType() == TriggerType::ORDERED_INDEX ||
12565       req->getRequestType() == CreateTrigReq::RT_BUILD_INDEX &&
12566       req->getTriggerType() == TriggerType::READ_ONLY_CONSTRAINT) {
12567     ;
12568   } else {
12569     jam();
12570     opPtr.p->m_errorCode = CreateTrigRef::UnsupportedTriggerType;
12571     opPtr.p->m_errorLine = __LINE__;
12572     return;
12573   }
12574   // check the table
12575   const Uint32 tableId = req->getTableId();
12576   if (! (tableId < c_tableRecordPool.getSize())) {
12577     jam();
12578     opPtr.p->m_errorCode = CreateTrigRef::InvalidTable;
12579     opPtr.p->m_errorLine = __LINE__;
12580     return;
12581   }
12582   TableRecordPtr tablePtr;
12583   c_tableRecordPool.getPtr(tablePtr, tableId);
12584   if (tablePtr.p->tabState != TableRecord::DEFINED &&
12585       tablePtr.p->tabState != TableRecord::BACKUP_ONGOING) {
12586     jam();
12587     opPtr.p->m_errorCode = CreateTrigRef::InvalidTable;
12588     opPtr.p->m_errorLine = __LINE__;
12589     return;
12590   }
12591 }
12592 
12593 void
createTrigger_masterSeize(Signal * signal,OpCreateTriggerPtr opPtr)12594 Dbdict::createTrigger_masterSeize(Signal* signal, OpCreateTriggerPtr opPtr)
12595 {
12596   TriggerRecordPtr triggerPtr;
12597   if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL) {
12598     triggerPtr.i = opPtr.p->m_request.getTriggerId();
12599   } else {
12600     triggerPtr.i = getFreeTriggerRecord();
12601     if (triggerPtr.i == RNIL) {
12602       jam();
12603       opPtr.p->m_errorCode = CreateTrigRef::TooManyTriggers;
12604       opPtr.p->m_errorLine = __LINE__;
12605       return;
12606     }
12607   }
12608   c_triggerRecordPool.getPtr(triggerPtr);
12609   initialiseTriggerRecord(triggerPtr);
12610   triggerPtr.p->triggerState = TriggerRecord::TS_DEFINING;
12611   opPtr.p->m_request.setTriggerId(triggerPtr.i);
12612 }
12613 
12614 void
createTrigger_slaveCreate(Signal * signal,OpCreateTriggerPtr opPtr)12615 Dbdict::createTrigger_slaveCreate(Signal* signal, OpCreateTriggerPtr opPtr)
12616 {
12617   jam();
12618   const CreateTrigReq* const req = &opPtr.p->m_request;
12619   // get the trigger record
12620   const Uint32 triggerId = req->getTriggerId();
12621   TriggerRecordPtr triggerPtr;
12622   c_triggerRecordPool.getPtr(triggerPtr, triggerId);
12623   initialiseTriggerRecord(triggerPtr);
12624   // fill in trigger data
12625   {
12626     Rope name(c_rope_pool, triggerPtr.p->triggerName);
12627     if(!name.assign(opPtr.p->m_triggerName))
12628     {
12629       opPtr.p->m_errorCode = (CreateTrigRef::ErrorCode)CreateTableRef::OutOfStringBuffer;
12630       return;
12631     }
12632   }
12633   triggerPtr.p->triggerId = triggerId;
12634   triggerPtr.p->tableId = req->getTableId();
12635   triggerPtr.p->indexId = RNIL;
12636   triggerPtr.p->triggerType = req->getTriggerType();
12637   triggerPtr.p->triggerActionTime = req->getTriggerActionTime();
12638   triggerPtr.p->triggerEvent = req->getTriggerEvent();
12639   triggerPtr.p->monitorReplicas = req->getMonitorReplicas();
12640   triggerPtr.p->monitorAllAttributes = req->getMonitorAllAttributes();
12641   triggerPtr.p->reportAllMonitoredAttributes = req->getReportAllMonitoredAttributes();
12642   triggerPtr.p->attributeMask = req->getAttributeMask();
12643   triggerPtr.p->triggerState = TriggerRecord::TS_OFFLINE;
12644   // add to hash table
12645   //  ndbout_c("++++++++++++ Adding trigger id %u, %s", triggerPtr.p->triggerId, triggerPtr.p->triggerName);
12646   {
12647     Ptr<DictObject> obj_ptr;
12648     ndbrequire(c_obj_hash.seize(obj_ptr));
12649     obj_ptr.p->m_name = triggerPtr.p->triggerName;
12650     obj_ptr.p->m_id = triggerId;
12651     obj_ptr.p->m_type = triggerPtr.p->triggerType;
12652     obj_ptr.p->m_ref_count = 0;
12653     c_obj_hash.add(obj_ptr);
12654     triggerPtr.p->m_obj_ptr_i = obj_ptr.i;
12655   }
12656   if (triggerPtr.p->triggerType == TriggerType::SECONDARY_INDEX ||
12657       triggerPtr.p->triggerType == TriggerType::ORDERED_INDEX) {
12658     jam();
12659     // connect to index record  XXX should be done in caller instead
12660     triggerPtr.p->indexId = req->getIndexId();
12661     TableRecordPtr indexPtr;
12662     c_tableRecordPool.getPtr(indexPtr, triggerPtr.p->indexId);
12663     switch (triggerPtr.p->triggerEvent) {
12664     case TriggerEvent::TE_INSERT:
12665       indexPtr.p->insertTriggerId = triggerPtr.p->triggerId;
12666       break;
12667     case TriggerEvent::TE_UPDATE:
12668       indexPtr.p->updateTriggerId = triggerPtr.p->triggerId;
12669       break;
12670     case TriggerEvent::TE_DELETE:
12671       indexPtr.p->deleteTriggerId = triggerPtr.p->triggerId;
12672       break;
12673     case TriggerEvent::TE_CUSTOM:
12674       indexPtr.p->customTriggerId = triggerPtr.p->triggerId;
12675       break;
12676     default:
12677       ndbrequire(false);
12678       break;
12679     }
12680   }
12681   if (triggerPtr.p->triggerType == TriggerType::READ_ONLY_CONSTRAINT) {
12682     jam();
12683     // connect to index record  XXX should be done in caller instead
12684     triggerPtr.p->indexId = req->getTableId();
12685     TableRecordPtr indexPtr;
12686     c_tableRecordPool.getPtr(indexPtr, triggerPtr.p->indexId);
12687     indexPtr.p->buildTriggerId = triggerPtr.p->triggerId;
12688   }
12689 }
12690 
12691 void
createTrigger_toAlterTrigger(Signal * signal,OpCreateTriggerPtr opPtr)12692 Dbdict::createTrigger_toAlterTrigger(Signal* signal, OpCreateTriggerPtr opPtr)
12693 {
12694   jam();
12695   AlterTrigReq* req = (AlterTrigReq*)signal->getDataPtrSend();
12696   req->setUserRef(reference());
12697   req->setConnectionPtr(opPtr.p->key);
12698   req->setRequestType(AlterTrigReq::RT_CREATE_TRIGGER);
12699   req->addRequestFlag(opPtr.p->m_requestFlag);
12700   req->setTableId(opPtr.p->m_request.getTableId());
12701   req->setTriggerId(opPtr.p->m_request.getTriggerId());
12702   req->setTriggerInfo(0);       // not used
12703   req->setOnline(true);
12704   req->setReceiverRef(opPtr.p->m_request.getReceiverRef());
12705   sendSignal(reference(), GSN_ALTER_TRIG_REQ,
12706       signal, AlterTrigReq::SignalLength, JBB);
12707 }
12708 
12709 void
createTrigger_fromAlterTrigger(Signal * signal,OpCreateTriggerPtr opPtr)12710 Dbdict::createTrigger_fromAlterTrigger(Signal* signal, OpCreateTriggerPtr opPtr)
12711 {
12712   jam();
12713   if (opPtr.p->hasError()) {
12714     jam();
12715     opPtr.p->m_requestType = CreateTrigReq::RT_DICT_ABORT;
12716     createTrigger_sendSlaveReq(signal, opPtr);
12717     return;
12718   }
12719   opPtr.p->m_requestType = CreateTrigReq::RT_DICT_COMMIT;
12720   createTrigger_sendSlaveReq(signal, opPtr);
12721 }
12722 
12723 void
createTrigger_slaveCommit(Signal * signal,OpCreateTriggerPtr opPtr)12724 Dbdict::createTrigger_slaveCommit(Signal* signal, OpCreateTriggerPtr opPtr)
12725 {
12726   jam();
12727   const CreateTrigReq* const req = &opPtr.p->m_request;
12728   // get the trigger record
12729   const Uint32 triggerId = req->getTriggerId();
12730   TriggerRecordPtr triggerPtr;
12731   c_triggerRecordPool.getPtr(triggerPtr, triggerId);
12732   if (! req->getOnline()) {
12733     triggerPtr.p->triggerState = TriggerRecord::TS_OFFLINE;
12734   } else {
12735     ndbrequire(triggerPtr.p->triggerState == TriggerRecord::TS_ONLINE);
12736   }
12737 }
12738 
12739 void
createTrigger_slaveAbort(Signal * signal,OpCreateTriggerPtr opPtr)12740 Dbdict::createTrigger_slaveAbort(Signal* signal, OpCreateTriggerPtr opPtr)
12741 {
12742   jam();
12743 }
12744 
12745 void
createTrigger_sendSlaveReq(Signal * signal,OpCreateTriggerPtr opPtr)12746 Dbdict::createTrigger_sendSlaveReq(Signal* signal, OpCreateTriggerPtr opPtr)
12747 {
12748   CreateTrigReq* const req = (CreateTrigReq*)signal->getDataPtrSend();
12749   *req = opPtr.p->m_request;
12750   req->setUserRef(opPtr.p->m_coordinatorRef);
12751   req->setConnectionPtr(opPtr.p->key);
12752   req->setRequestType(opPtr.p->m_requestType);
12753   req->addRequestFlag(opPtr.p->m_requestFlag);
12754   NdbNodeBitmask receiverNodes = c_aliveNodes;
12755   if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL) {
12756     receiverNodes.clear();
12757     receiverNodes.set(getOwnNodeId());
12758   }
12759   opPtr.p->m_signalCounter = receiverNodes;
12760   NodeReceiverGroup rg(DBDICT, receiverNodes);
12761   sendSignal(rg, GSN_CREATE_TRIG_REQ,
12762       signal, CreateTrigReq::SignalLength, JBB);
12763 }
12764 
12765 void
createTrigger_sendReply(Signal * signal,OpCreateTriggerPtr opPtr,bool toUser)12766 Dbdict::createTrigger_sendReply(Signal* signal, OpCreateTriggerPtr opPtr,
12767     bool toUser)
12768 {
12769   CreateTrigRef* rep = (CreateTrigRef*)signal->getDataPtrSend();
12770   Uint32 gsn = GSN_CREATE_TRIG_CONF;
12771   Uint32 length = CreateTrigConf::InternalLength;
12772   bool sendRef;
12773   if (! toUser) {
12774     sendRef = opPtr.p->hasLastError();
12775     rep->setUserRef(opPtr.p->m_coordinatorRef);
12776     rep->setConnectionPtr(opPtr.p->key);
12777     rep->setRequestType(opPtr.p->m_requestType);
12778     if (opPtr.p->m_requestType == CreateTrigReq::RT_DICT_ABORT)
12779       sendRef = false;
12780   } else {
12781     sendRef = opPtr.p->hasError();
12782     rep->setUserRef(opPtr.p->m_request.getUserRef());
12783     rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
12784     rep->setRequestType(opPtr.p->m_request.getRequestType());
12785     length = CreateTrigConf::SignalLength;
12786   }
12787   rep->setTableId(opPtr.p->m_request.getTableId());
12788   rep->setIndexId(opPtr.p->m_request.getIndexId());
12789   rep->setTriggerId(opPtr.p->m_request.getTriggerId());
12790   rep->setTriggerInfo(opPtr.p->m_request.getTriggerInfo());
12791   if (sendRef) {
12792     if (opPtr.p->m_errorNode == 0)
12793       opPtr.p->m_errorNode = getOwnNodeId();
12794     rep->setErrorCode(opPtr.p->m_errorCode);
12795     rep->setErrorLine(opPtr.p->m_errorLine);
12796     rep->setErrorNode(opPtr.p->m_errorNode);
12797     gsn = GSN_CREATE_TRIG_REF;
12798     length = CreateTrigRef::SignalLength;
12799   }
12800   sendSignal(rep->getUserRef(), gsn, signal, length, JBB);
12801 }
12802 
12803 /**
12804  * MODULE: Drop trigger.
12805  */
12806 
12807 void
execDROP_TRIG_REQ(Signal * signal)12808 Dbdict::execDROP_TRIG_REQ(Signal* signal)
12809 {
12810   jamEntry();
12811   DropTrigReq* const req = (DropTrigReq*)signal->getDataPtrSend();
12812   OpDropTriggerPtr opPtr;
12813   const Uint32 senderRef = signal->senderBlockRef();
12814   const DropTrigReq::RequestType requestType = req->getRequestType();
12815 
12816   if (signal->getNoOfSections() > 0) {
12817     ndbrequire(signal->getNoOfSections() == 1);
12818     jam();
12819     char triggerName[MAX_TAB_NAME_SIZE];
12820     OpDropTrigger opTmp;
12821     opPtr.p=&opTmp;
12822 
12823     SegmentedSectionPtr ssPtr;
12824     signal->getSection(ssPtr, DropTrigReq::TRIGGER_NAME_SECTION);
12825     SimplePropertiesSectionReader ssReader(ssPtr, getSectionSegmentPool());
12826     if (ssReader.getKey() != DropTrigReq::TriggerNameKey ||
12827 	! ssReader.getString(triggerName)) {
12828       jam();
12829       opPtr.p->m_errorCode = DropTrigRef::InvalidName;
12830       opPtr.p->m_errorLine = __LINE__;
12831       releaseSections(signal);
12832       dropTrigger_sendReply(signal, opPtr, opPtr.p->m_isMaster);
12833       return;
12834     }
12835     releaseSections(signal);
12836 
12837     //ndbout_c("++++++++++++++ Looking for trigger %s", keyRecord.triggerName);
12838     DictObject * obj_ptr_p = get_object(triggerName);
12839     if (obj_ptr_p == 0){
12840       jam();
12841       req->setTriggerId(RNIL);
12842     } else {
12843       jam();
12844       //ndbout_c("++++++++++ Found trigger %s", triggerPtr.p->triggerName);
12845       TriggerRecordPtr triggerPtr;
12846       c_triggerRecordPool.getPtr(triggerPtr, obj_ptr_p->m_id);
12847       req->setTriggerId(triggerPtr.p->triggerId);
12848       req->setTableId(triggerPtr.p->tableId);
12849     }
12850   }
12851   if (requestType == DropTrigReq::RT_USER ||
12852       requestType == DropTrigReq::RT_ALTER_INDEX ||
12853       requestType == DropTrigReq::RT_BUILD_INDEX) {
12854     jam();
12855     if (signal->getLength() == DropTrigReq::SignalLength) {
12856       if (getOwnNodeId() != c_masterNodeId) {
12857 	jam();
12858 	// forward to DICT master
12859 	sendSignal(calcDictBlockRef(c_masterNodeId), GSN_DROP_TRIG_REQ,
12860 		   signal, signal->getLength(), JBB);
12861 	return;
12862       }
12863       if (!c_triggerRecordPool.findId(req->getTriggerId())) {
12864 	jam();
12865 	// return to sender
12866 	OpDropTrigger opBad;
12867 	opPtr.p = &opBad;
12868 	opPtr.p->save(req);
12869         if (! (req->getRequestFlag() & RequestFlag::RF_FORCE)) {
12870           opPtr.p->m_errorCode = DropTrigRef::TriggerNotFound;
12871           opPtr.p->m_errorLine = __LINE__;
12872         }
12873 	dropTrigger_sendReply(signal,  opPtr, true);
12874 	return;
12875       }
12876       // forward initial request plus operation key to all
12877       req->setOpKey(++c_opRecordSequence);
12878       NodeReceiverGroup rg(DBDICT, c_aliveNodes);
12879       sendSignal(rg, GSN_DROP_TRIG_REQ,
12880 		 signal, DropTrigReq::SignalLength + 1, JBB);
12881       return;
12882     }
12883     // seize operation record
12884     ndbrequire(signal->getLength() == DropTrigReq::SignalLength + 1);
12885     const Uint32 opKey = req->getOpKey();
12886     OpDropTrigger opBusy;
12887     if (! c_opDropTrigger.seize(opPtr))
12888       opPtr.p = &opBusy;
12889     opPtr.p->save(req);
12890     opPtr.p->m_coordinatorRef = senderRef;
12891     opPtr.p->m_isMaster = (senderRef == reference());
12892     opPtr.p->key = opKey;
12893     opPtr.p->m_requestType = DropTrigReq::RT_DICT_PREPARE;
12894     if (opPtr.p == &opBusy) {
12895       jam();
12896       opPtr.p->m_errorCode = DropTrigRef::Busy;
12897       opPtr.p->m_errorLine = __LINE__;
12898       dropTrigger_sendReply(signal, opPtr, opPtr.p->m_isMaster);
12899       return;
12900     }
12901     c_opDropTrigger.add(opPtr);
12902       // master expects to hear from all
12903     if (opPtr.p->m_isMaster)
12904 	opPtr.p->m_signalCounter = c_aliveNodes;
12905     dropTrigger_slavePrepare(signal, opPtr);
12906     dropTrigger_sendReply(signal, opPtr, false);
12907     return;
12908   }
12909   c_opDropTrigger.find(opPtr, req->getConnectionPtr());
12910   if (! opPtr.isNull()) {
12911     opPtr.p->m_requestType = requestType;
12912     if (requestType == DropTrigReq::RT_DICT_COMMIT ||
12913 	requestType == DropTrigReq::RT_DICT_ABORT) {
12914       jam();
12915       if (requestType == DropTrigReq::RT_DICT_COMMIT)
12916 	dropTrigger_slaveCommit(signal, opPtr);
12917       else
12918 	dropTrigger_slaveAbort(signal, opPtr);
12919       dropTrigger_sendReply(signal, opPtr, false);
12920       // done in slave
12921       if (! opPtr.p->m_isMaster)
12922 	c_opDropTrigger.release(opPtr);
12923       return;
12924     }
12925   }
12926   jam();
12927   // return to sender
12928   OpDropTrigger opBad;
12929   opPtr.p = &opBad;
12930   opPtr.p->save(req);
12931   opPtr.p->m_errorCode = DropTrigRef::BadRequestType;
12932   opPtr.p->m_errorLine = __LINE__;
12933   dropTrigger_sendReply(signal,  opPtr, true);
12934 }
12935 
12936 void
execDROP_TRIG_CONF(Signal * signal)12937 Dbdict::execDROP_TRIG_CONF(Signal* signal)
12938 {
12939   jamEntry();
12940   DropTrigConf* conf = (DropTrigConf*)signal->getDataPtrSend();
12941   dropTrigger_recvReply(signal, conf, 0);
12942 }
12943 
12944 void
execDROP_TRIG_REF(Signal * signal)12945 Dbdict::execDROP_TRIG_REF(Signal* signal)
12946 {
12947   jamEntry();
12948   DropTrigRef* ref = (DropTrigRef*)signal->getDataPtrSend();
12949   dropTrigger_recvReply(signal, ref->getConf(), ref);
12950 }
12951 
12952 void
dropTrigger_recvReply(Signal * signal,const DropTrigConf * conf,const DropTrigRef * ref)12953 Dbdict::dropTrigger_recvReply(Signal* signal, const DropTrigConf* conf,
12954     const DropTrigRef* ref)
12955 {
12956   jam();
12957   const Uint32 senderRef = signal->senderBlockRef();
12958   const DropTrigReq::RequestType requestType = conf->getRequestType();
12959   const Uint32 key = conf->getConnectionPtr();
12960   if (requestType == DropTrigReq::RT_ALTER_INDEX) {
12961     jam();
12962     // part of alter index operation
12963     OpAlterIndexPtr opPtr;
12964     c_opAlterIndex.find(opPtr, key);
12965     ndbrequire(! opPtr.isNull());
12966     opPtr.p->setError(ref);
12967     alterIndex_fromDropTrigger(signal, opPtr);
12968     return;
12969   }
12970   if (requestType == DropTrigReq::RT_BUILD_INDEX) {
12971     jam();
12972     // part of build index operation
12973     OpBuildIndexPtr opPtr;
12974     c_opBuildIndex.find(opPtr, key);
12975     ndbrequire(! opPtr.isNull());
12976     opPtr.p->setError(ref);
12977     buildIndex_fromDropConstr(signal, opPtr);
12978     return;
12979   }
12980   if (requestType == DropTrigReq::RT_TC ||
12981       requestType == DropTrigReq::RT_LQH) {
12982     jam();
12983     // part of alter trigger operation
12984     OpAlterTriggerPtr opPtr;
12985     c_opAlterTrigger.find(opPtr, key);
12986     ndbrequire(! opPtr.isNull());
12987     opPtr.p->setError(ref);
12988     alterTrigger_fromDropLocal(signal, opPtr);
12989     return;
12990   }
12991   OpDropTriggerPtr opPtr;
12992   c_opDropTrigger.find(opPtr, key);
12993   ndbrequire(! opPtr.isNull());
12994   ndbrequire(opPtr.p->m_isMaster);
12995   ndbrequire(opPtr.p->m_requestType == requestType);
12996   opPtr.p->setError(ref);
12997   opPtr.p->m_signalCounter.clearWaitingFor(refToNode(senderRef));
12998   if (! opPtr.p->m_signalCounter.done()) {
12999     jam();
13000     return;
13001   }
13002   if (requestType == DropTrigReq::RT_DICT_COMMIT ||
13003       requestType == DropTrigReq::RT_DICT_ABORT) {
13004     jam();
13005     // send reply to user
13006     dropTrigger_sendReply(signal, opPtr, true);
13007     c_opDropTrigger.release(opPtr);
13008     return;
13009   }
13010   if (opPtr.p->hasError()) {
13011     jam();
13012     opPtr.p->m_requestType = DropTrigReq::RT_DICT_ABORT;
13013     dropTrigger_sendSlaveReq(signal, opPtr);
13014     return;
13015   }
13016   if (requestType == DropTrigReq::RT_DICT_PREPARE) {
13017     jam();
13018     // start alter offline
13019     dropTrigger_toAlterTrigger(signal, opPtr);
13020     return;
13021   }
13022   ndbrequire(false);
13023 }
13024 
13025 void
dropTrigger_slavePrepare(Signal * signal,OpDropTriggerPtr opPtr)13026 Dbdict::dropTrigger_slavePrepare(Signal* signal, OpDropTriggerPtr opPtr)
13027 {
13028   jam();
13029 }
13030 
13031 void
dropTrigger_toAlterTrigger(Signal * signal,OpDropTriggerPtr opPtr)13032 Dbdict::dropTrigger_toAlterTrigger(Signal* signal, OpDropTriggerPtr opPtr)
13033 {
13034   jam();
13035   AlterTrigReq* req = (AlterTrigReq*)signal->getDataPtrSend();
13036   req->setUserRef(reference());
13037   req->setConnectionPtr(opPtr.p->key);
13038   req->setRequestType(AlterTrigReq::RT_DROP_TRIGGER);
13039   req->addRequestFlag(opPtr.p->m_requestFlag);
13040   req->setTableId(opPtr.p->m_request.getTableId());
13041   req->setTriggerId(opPtr.p->m_request.getTriggerId());
13042   req->setTriggerInfo(0);       // not used
13043   req->setOnline(false);
13044   req->setReceiverRef(0);
13045   sendSignal(reference(), GSN_ALTER_TRIG_REQ,
13046       signal, AlterTrigReq::SignalLength, JBB);
13047 }
13048 
13049 void
dropTrigger_fromAlterTrigger(Signal * signal,OpDropTriggerPtr opPtr)13050 Dbdict::dropTrigger_fromAlterTrigger(Signal* signal, OpDropTriggerPtr opPtr)
13051 {
13052   jam();
13053   // remove in all
13054   opPtr.p->m_requestType = DropTrigReq::RT_DICT_COMMIT;
13055   dropTrigger_sendSlaveReq(signal, opPtr);
13056 }
13057 
13058 void
dropTrigger_sendSlaveReq(Signal * signal,OpDropTriggerPtr opPtr)13059 Dbdict::dropTrigger_sendSlaveReq(Signal* signal, OpDropTriggerPtr opPtr)
13060 {
13061   DropTrigReq* const req = (DropTrigReq*)signal->getDataPtrSend();
13062   *req = opPtr.p->m_request;
13063   req->setUserRef(opPtr.p->m_coordinatorRef);
13064   req->setConnectionPtr(opPtr.p->key);
13065   req->setRequestType(opPtr.p->m_requestType);
13066   req->addRequestFlag(opPtr.p->m_requestFlag);
13067   opPtr.p->m_signalCounter = c_aliveNodes;
13068   NodeReceiverGroup rg(DBDICT, c_aliveNodes);
13069   sendSignal(rg, GSN_DROP_TRIG_REQ,
13070       signal, DropTrigReq::SignalLength, JBB);
13071 }
13072 
13073 void
dropTrigger_slaveCommit(Signal * signal,OpDropTriggerPtr opPtr)13074 Dbdict::dropTrigger_slaveCommit(Signal* signal, OpDropTriggerPtr opPtr)
13075 {
13076   jam();
13077   const DropTrigReq* const req = &opPtr.p->m_request;
13078   // get trigger record
13079   const Uint32 triggerId = req->getTriggerId();
13080   TriggerRecordPtr triggerPtr;
13081   c_triggerRecordPool.getPtr(triggerPtr, triggerId);
13082   if (triggerPtr.p->triggerType == TriggerType::SECONDARY_INDEX ||
13083       triggerPtr.p->triggerType == TriggerType::ORDERED_INDEX) {
13084     jam();
13085     // disconnect from index if index trigger  XXX move to drop index
13086     triggerPtr.p->indexId = req->getIndexId();
13087     TableRecordPtr indexPtr;
13088     c_tableRecordPool.getPtr(indexPtr, triggerPtr.p->indexId);
13089     ndbrequire(! indexPtr.isNull());
13090     switch (triggerPtr.p->triggerEvent) {
13091     case TriggerEvent::TE_INSERT:
13092       indexPtr.p->insertTriggerId = RNIL;
13093       break;
13094     case TriggerEvent::TE_UPDATE:
13095       indexPtr.p->updateTriggerId = RNIL;
13096       break;
13097     case TriggerEvent::TE_DELETE:
13098       indexPtr.p->deleteTriggerId = RNIL;
13099       break;
13100     case TriggerEvent::TE_CUSTOM:
13101       indexPtr.p->customTriggerId = RNIL;
13102       break;
13103     default:
13104       ndbrequire(false);
13105       break;
13106     }
13107   }
13108   if (triggerPtr.p->triggerType == TriggerType::READ_ONLY_CONSTRAINT) {
13109     jam();
13110     // disconnect from index record  XXX should be done in caller instead
13111     triggerPtr.p->indexId = req->getTableId();
13112     TableRecordPtr indexPtr;
13113     c_tableRecordPool.getPtr(indexPtr, triggerPtr.p->indexId);
13114     indexPtr.p->buildTriggerId = RNIL;
13115   }
13116   //remove trigger
13117   //ndbout_c("++++++++++++ Removing trigger id %u, %s", triggerPtr.p->triggerId, triggerPtr.p->triggerName);
13118   release_object(triggerPtr.p->m_obj_ptr_i);
13119   triggerPtr.p->triggerState = TriggerRecord::TS_NOT_DEFINED;
13120 }
13121 
13122 void
dropTrigger_slaveAbort(Signal * signal,OpDropTriggerPtr opPtr)13123 Dbdict::dropTrigger_slaveAbort(Signal* signal, OpDropTriggerPtr opPtr)
13124 {
13125   jam();
13126 }
13127 
13128 void
dropTrigger_sendReply(Signal * signal,OpDropTriggerPtr opPtr,bool toUser)13129 Dbdict::dropTrigger_sendReply(Signal* signal, OpDropTriggerPtr opPtr,
13130     bool toUser)
13131 {
13132   DropTrigRef* rep = (DropTrigRef*)signal->getDataPtrSend();
13133   Uint32 gsn = GSN_DROP_TRIG_CONF;
13134   Uint32 length = DropTrigConf::InternalLength;
13135   bool sendRef;
13136   if (! toUser) {
13137     sendRef = opPtr.p->hasLastError();
13138     rep->setUserRef(opPtr.p->m_coordinatorRef);
13139     rep->setConnectionPtr(opPtr.p->key);
13140     rep->setRequestType(opPtr.p->m_requestType);
13141     if (opPtr.p->m_requestType == DropTrigReq::RT_DICT_ABORT)
13142       sendRef = false;
13143   } else {
13144     sendRef = opPtr.p->hasError();
13145     rep->setUserRef(opPtr.p->m_request.getUserRef());
13146     rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
13147     rep->setRequestType(opPtr.p->m_request.getRequestType());
13148     length = DropTrigConf::SignalLength;
13149   }
13150   rep->setTableId(opPtr.p->m_request.getTableId());
13151   rep->setIndexId(opPtr.p->m_request.getIndexId());
13152   rep->setTriggerId(opPtr.p->m_request.getTriggerId());
13153   if (sendRef) {
13154     if (opPtr.p->m_errorNode == 0)
13155       opPtr.p->m_errorNode = getOwnNodeId();
13156     rep->setErrorCode(opPtr.p->m_errorCode);
13157     rep->setErrorLine(opPtr.p->m_errorLine);
13158     rep->setErrorNode(opPtr.p->m_errorNode);
13159     gsn = GSN_DROP_TRIG_REF;
13160     length = CreateTrigRef::SignalLength;
13161   }
13162   sendSignal(rep->getUserRef(), gsn, signal, length, JBB);
13163 }
13164 
13165 /**
13166  * MODULE: Alter trigger.
13167  *
13168  * Alter trigger state.  Alter online creates the trigger first in all
13169  * TC (if index trigger) and then in all LQH-TUP.
13170  *
13171  * Request type received in REQ and returned in CONF/REF:
13172  *
13173  * RT_USER - normal user e.g. BACKUP
13174  * RT_CREATE_TRIGGER - from create trigger
13175  * RT_DROP_TRIGGER - from drop trigger
13176  * RT_DICT_PREPARE - seize operations and check request
13177  * RT_DICT_TC - master to each DICT on way to TC
13178  * RT_DICT_LQH - master to each DICT on way to LQH-TUP
13179  * RT_DICT_COMMIT - commit state change in each DICT (no reply)
13180  */
13181 
13182 void
execALTER_TRIG_REQ(Signal * signal)13183 Dbdict::execALTER_TRIG_REQ(Signal* signal)
13184 {
13185   jamEntry();
13186   AlterTrigReq* const req = (AlterTrigReq*)signal->getDataPtrSend();
13187   OpAlterTriggerPtr opPtr;
13188   const Uint32 senderRef = signal->senderBlockRef();
13189   const AlterTrigReq::RequestType requestType = req->getRequestType();
13190   if (requestType == AlterTrigReq::RT_USER ||
13191       requestType == AlterTrigReq::RT_CREATE_TRIGGER ||
13192       requestType == AlterTrigReq::RT_DROP_TRIGGER) {
13193     jam();
13194     const bool isLocal = req->getRequestFlag() & RequestFlag::RF_LOCAL;
13195     NdbNodeBitmask receiverNodes = c_aliveNodes;
13196     if (isLocal) {
13197       receiverNodes.clear();
13198       receiverNodes.set(getOwnNodeId());
13199     }
13200     if (signal->getLength() == AlterTrigReq::SignalLength) {
13201       jam();
13202       if (! isLocal && getOwnNodeId() != c_masterNodeId) {
13203         jam();
13204         // forward to DICT master
13205         sendSignal(calcDictBlockRef(c_masterNodeId), GSN_ALTER_TRIG_REQ,
13206             signal, AlterTrigReq::SignalLength, JBB);
13207         return;
13208       }
13209       // forward initial request plus operation key to all
13210       req->setOpKey(++c_opRecordSequence);
13211       NodeReceiverGroup rg(DBDICT, receiverNodes);
13212       sendSignal(rg, GSN_ALTER_TRIG_REQ,
13213           signal, AlterTrigReq::SignalLength + 1, JBB);
13214       return;
13215     }
13216     // seize operation record
13217     ndbrequire(signal->getLength() == AlterTrigReq::SignalLength + 1);
13218     const Uint32 opKey = req->getOpKey();
13219     OpAlterTrigger opBusy;
13220     if (! c_opAlterTrigger.seize(opPtr))
13221       opPtr.p = &opBusy;
13222     opPtr.p->save(req);
13223     opPtr.p->m_coordinatorRef = senderRef;
13224     opPtr.p->m_isMaster = (senderRef == reference());
13225     opPtr.p->key = opKey;
13226     opPtr.p->m_requestType = AlterTrigReq::RT_DICT_PREPARE;
13227     if (opPtr.p == &opBusy) {
13228       jam();
13229       opPtr.p->m_errorCode = AlterTrigRef::Busy;
13230       opPtr.p->m_errorLine = __LINE__;
13231       alterTrigger_sendReply(signal, opPtr, opPtr.p->m_isMaster);
13232       return;
13233     }
13234     c_opAlterTrigger.add(opPtr);
13235     // master expects to hear from all
13236     if (opPtr.p->m_isMaster) {
13237       opPtr.p->m_nodes = receiverNodes;
13238       opPtr.p->m_signalCounter = receiverNodes;
13239     }
13240     alterTrigger_slavePrepare(signal, opPtr);
13241     alterTrigger_sendReply(signal, opPtr, false);
13242     return;
13243   }
13244   c_opAlterTrigger.find(opPtr, req->getConnectionPtr());
13245   if (! opPtr.isNull()) {
13246     opPtr.p->m_requestType = requestType;
13247     if (requestType == AlterTrigReq::RT_DICT_TC ||
13248         requestType == AlterTrigReq::RT_DICT_LQH) {
13249       jam();
13250       if (req->getOnline())
13251         alterTrigger_toCreateLocal(signal, opPtr);
13252       else
13253         alterTrigger_toDropLocal(signal, opPtr);
13254       return;
13255     }
13256     if (requestType == AlterTrigReq::RT_DICT_COMMIT ||
13257         requestType == AlterTrigReq::RT_DICT_ABORT) {
13258       jam();
13259       if (requestType == AlterTrigReq::RT_DICT_COMMIT)
13260         alterTrigger_slaveCommit(signal, opPtr);
13261       else
13262         alterTrigger_slaveAbort(signal, opPtr);
13263       alterTrigger_sendReply(signal, opPtr, false);
13264       // done in slave
13265       if (! opPtr.p->m_isMaster)
13266         c_opAlterTrigger.release(opPtr);
13267       return;
13268     }
13269   }
13270   jam();
13271   // return to sender
13272   OpAlterTrigger opBad;
13273   opPtr.p = &opBad;
13274   opPtr.p->save(req);
13275   opPtr.p->m_errorCode = AlterTrigRef::BadRequestType;
13276   opPtr.p->m_errorLine = __LINE__;
13277   alterTrigger_sendReply(signal, opPtr, true);
13278   return;
13279 }
13280 
13281 void
execALTER_TRIG_CONF(Signal * signal)13282 Dbdict::execALTER_TRIG_CONF(Signal* signal)
13283 {
13284   jamEntry();
13285   AlterTrigConf* conf = (AlterTrigConf*)signal->getDataPtrSend();
13286   alterTrigger_recvReply(signal, conf, 0);
13287 }
13288 
13289 void
execALTER_TRIG_REF(Signal * signal)13290 Dbdict::execALTER_TRIG_REF(Signal* signal)
13291 {
13292   jamEntry();
13293   AlterTrigRef* ref = (AlterTrigRef*)signal->getDataPtrSend();
13294   alterTrigger_recvReply(signal, ref->getConf(), ref);
13295 }
13296 
13297 void
alterTrigger_recvReply(Signal * signal,const AlterTrigConf * conf,const AlterTrigRef * ref)13298 Dbdict::alterTrigger_recvReply(Signal* signal, const AlterTrigConf* conf,
13299     const AlterTrigRef* ref)
13300 {
13301   jam();
13302   const Uint32 senderRef = signal->senderBlockRef();
13303   const AlterTrigReq::RequestType requestType = conf->getRequestType();
13304   const Uint32 key = conf->getConnectionPtr();
13305   if (requestType == AlterTrigReq::RT_CREATE_TRIGGER) {
13306     jam();
13307     // part of create trigger operation
13308     OpCreateTriggerPtr opPtr;
13309     c_opCreateTrigger.find(opPtr, key);
13310     ndbrequire(! opPtr.isNull());
13311     opPtr.p->setError(ref);
13312     createTrigger_fromAlterTrigger(signal, opPtr);
13313     return;
13314   }
13315   if (requestType == AlterTrigReq::RT_DROP_TRIGGER) {
13316     jam();
13317     // part of drop trigger operation
13318     OpDropTriggerPtr opPtr;
13319     c_opDropTrigger.find(opPtr, key);
13320     ndbrequire(! opPtr.isNull());
13321     opPtr.p->setError(ref);
13322     dropTrigger_fromAlterTrigger(signal, opPtr);
13323     return;
13324   }
13325   OpAlterTriggerPtr opPtr;
13326   c_opAlterTrigger.find(opPtr, key);
13327   ndbrequire(! opPtr.isNull());
13328   ndbrequire(opPtr.p->m_isMaster);
13329   ndbrequire(opPtr.p->m_requestType == requestType);
13330   /*
13331    * If refuse on drop trig, because of non-existent trigger,
13332    * comes from anyone but the master node - ignore it and
13333    * remove the node from forter ALTER_TRIG communication
13334    * This will happen if a new node has started since the
13335    * trigger whas created.
13336    */
13337   if (ref &&
13338       refToNode(senderRef) != refToNode(reference()) &&
13339       opPtr.p->m_request.getRequestType() == AlterTrigReq::RT_DROP_TRIGGER &&
13340       ref->getErrorCode() == AlterTrigRef::TriggerNotFound) {
13341     jam();
13342     ref = 0;                                      // ignore this error
13343     opPtr.p->m_nodes.clear(refToNode(senderRef)); // remove this from group
13344   }
13345   opPtr.p->setError(ref);
13346   opPtr.p->m_signalCounter.clearWaitingFor(refToNode(senderRef));
13347   if (! opPtr.p->m_signalCounter.done()) {
13348     jam();
13349     return;
13350   }
13351   if (requestType == AlterTrigReq::RT_DICT_COMMIT ||
13352       requestType == AlterTrigReq::RT_DICT_ABORT) {
13353     jam();
13354     // send reply to user
13355     alterTrigger_sendReply(signal, opPtr, true);
13356     c_opAlterTrigger.release(opPtr);
13357     return;
13358   }
13359   if (opPtr.p->hasError()) {
13360     jam();
13361     opPtr.p->m_requestType = AlterTrigReq::RT_DICT_ABORT;
13362     alterTrigger_sendSlaveReq(signal, opPtr);
13363     return;
13364   }
13365   if (! (opPtr.p->m_request.getRequestFlag() & RequestFlag::RF_NOTCTRIGGER)) {
13366     if (requestType == AlterTrigReq::RT_DICT_PREPARE) {
13367       jam();
13368       if (opPtr.p->m_request.getOnline()) {
13369         jam();
13370         opPtr.p->m_requestType = AlterTrigReq::RT_DICT_TC;
13371       } else {
13372         jam();
13373         opPtr.p->m_requestType = AlterTrigReq::RT_DICT_LQH;
13374       }
13375       alterTrigger_sendSlaveReq(signal, opPtr);
13376       return;
13377     }
13378     if (requestType == AlterTrigReq::RT_DICT_TC) {
13379       jam();
13380       if (opPtr.p->m_request.getOnline()) {
13381         jam();
13382         opPtr.p->m_requestType = AlterTrigReq::RT_DICT_LQH;
13383       } else {
13384         jam();
13385         opPtr.p->m_requestType = AlterTrigReq::RT_DICT_COMMIT;
13386       }
13387       alterTrigger_sendSlaveReq(signal, opPtr);
13388       return;
13389     }
13390     if (requestType == AlterTrigReq::RT_DICT_LQH) {
13391       jam();
13392       if (opPtr.p->m_request.getOnline()) {
13393         jam();
13394         opPtr.p->m_requestType = AlterTrigReq::RT_DICT_COMMIT;
13395       } else {
13396         jam();
13397         opPtr.p->m_requestType = AlterTrigReq::RT_DICT_TC;
13398       }
13399       alterTrigger_sendSlaveReq(signal, opPtr);
13400       return;
13401     }
13402   } else {
13403     if (requestType == AlterTrigReq::RT_DICT_PREPARE) {
13404       jam();
13405       opPtr.p->m_requestType = AlterTrigReq::RT_DICT_LQH;
13406       alterTrigger_sendSlaveReq(signal, opPtr);
13407       return;
13408     }
13409     if (requestType == AlterTrigReq::RT_DICT_LQH) {
13410       jam();
13411       opPtr.p->m_requestType = AlterTrigReq::RT_DICT_COMMIT;
13412       alterTrigger_sendSlaveReq(signal, opPtr);
13413       return;
13414     }
13415   }
13416   ndbrequire(false);
13417 }
13418 
13419 void
alterTrigger_slavePrepare(Signal * signal,OpAlterTriggerPtr opPtr)13420 Dbdict::alterTrigger_slavePrepare(Signal* signal, OpAlterTriggerPtr opPtr)
13421 {
13422   jam();
13423   const AlterTrigReq* const req = &opPtr.p->m_request;
13424   const Uint32 triggerId = req->getTriggerId();
13425   TriggerRecordPtr triggerPtr;
13426   if (! (triggerId < c_triggerRecordPool.getSize())) {
13427     jam();
13428     opPtr.p->m_errorCode = AlterTrigRef::TriggerNotFound;
13429     opPtr.p->m_errorLine = __LINE__;
13430     return;
13431   }
13432   c_triggerRecordPool.getPtr(triggerPtr, triggerId);
13433   if (triggerPtr.p->triggerState == TriggerRecord::TS_NOT_DEFINED) {
13434     jam();
13435     opPtr.p->m_errorCode = AlterTrigRef::TriggerNotFound;
13436     opPtr.p->m_errorLine = __LINE__;
13437     return;
13438   }
13439 
13440   if (triggerPtr.p->triggerType == TriggerType::SUBSCRIPTION)
13441   {
13442     opPtr.p->m_request.addRequestFlag(RequestFlag::RF_NOTCTRIGGER);
13443   }
13444 }
13445 
13446 void
alterTrigger_toCreateLocal(Signal * signal,OpAlterTriggerPtr opPtr)13447 Dbdict::alterTrigger_toCreateLocal(Signal* signal, OpAlterTriggerPtr opPtr)
13448 {
13449   jam();
13450   // find trigger record
13451   const Uint32 triggerId = opPtr.p->m_request.getTriggerId();
13452   TriggerRecordPtr triggerPtr;
13453   c_triggerRecordPool.getPtr(triggerPtr, triggerId);
13454   CreateTrigReq* const req = (CreateTrigReq*)signal->getDataPtrSend();
13455   req->setUserRef(reference());
13456   req->setConnectionPtr(opPtr.p->key);
13457   if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
13458     jam();
13459     req->setRequestType(CreateTrigReq::RT_TC);
13460   } else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
13461     jam();
13462     req->setRequestType(CreateTrigReq::RT_LQH);
13463   } else {
13464     ndbassert(false);
13465   }
13466   req->setTableId(triggerPtr.p->tableId);
13467   req->setIndexId(triggerPtr.p->indexId);
13468   req->setTriggerId(triggerPtr.i);
13469   req->setTriggerType(triggerPtr.p->triggerType);
13470   req->setTriggerActionTime(triggerPtr.p->triggerActionTime);
13471   req->setTriggerEvent(triggerPtr.p->triggerEvent);
13472   req->setMonitorReplicas(triggerPtr.p->monitorReplicas);
13473   req->setMonitorAllAttributes(triggerPtr.p->monitorAllAttributes);
13474   req->setReportAllMonitoredAttributes(triggerPtr.p->reportAllMonitoredAttributes);
13475   req->setOnline(true);
13476   req->setReceiverRef(opPtr.p->m_request.getReceiverRef());
13477   BlockReference blockRef = 0;
13478   if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
13479     jam();
13480     blockRef = calcTcBlockRef(getOwnNodeId());
13481   } else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
13482     jam();
13483     blockRef = calcLqhBlockRef(getOwnNodeId());
13484   } else {
13485     ndbassert(false);
13486   }
13487   req->setAttributeMask(triggerPtr.p->attributeMask);
13488   sendSignal(blockRef, GSN_CREATE_TRIG_REQ,
13489       signal, CreateTrigReq::SignalLength, JBB);
13490 }
13491 
13492 void
alterTrigger_fromCreateLocal(Signal * signal,OpAlterTriggerPtr opPtr)13493 Dbdict::alterTrigger_fromCreateLocal(Signal* signal, OpAlterTriggerPtr opPtr)
13494 {
13495   jam();
13496   if (! opPtr.p->hasLastError()) {
13497     // mark created locally
13498     TriggerRecordPtr triggerPtr;
13499     c_triggerRecordPool.getPtr(triggerPtr, opPtr.p->m_request.getTriggerId());
13500     if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
13501       jam();
13502       triggerPtr.p->triggerLocal |= TriggerRecord::TL_CREATED_TC;
13503     } else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
13504       jam();
13505       triggerPtr.p->triggerLocal |= TriggerRecord::TL_CREATED_LQH;
13506     } else {
13507       ndbrequire(false);
13508     }
13509   }
13510   // forward CONF or REF to master
13511   alterTrigger_sendReply(signal, opPtr, false);
13512 }
13513 
13514 void
alterTrigger_toDropLocal(Signal * signal,OpAlterTriggerPtr opPtr)13515 Dbdict::alterTrigger_toDropLocal(Signal* signal, OpAlterTriggerPtr opPtr)
13516 {
13517   jam();
13518   TriggerRecordPtr triggerPtr;
13519   c_triggerRecordPool.getPtr(triggerPtr, opPtr.p->m_request.getTriggerId());
13520   DropTrigReq* const req = (DropTrigReq*)signal->getDataPtrSend();
13521   req->setUserRef(reference());
13522   req->setConnectionPtr(opPtr.p->key);
13523   if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
13524     jam();
13525     // broken trigger allowed if force
13526     if (! (triggerPtr.p->triggerLocal & TriggerRecord::TL_CREATED_TC)) {
13527       jam();
13528       ndbassert(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
13529       alterTrigger_sendReply(signal, opPtr, false);
13530       return;
13531     }
13532     req->setRequestType(DropTrigReq::RT_TC);
13533   } else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
13534     jam();
13535     // broken trigger allowed if force
13536     if (! (triggerPtr.p->triggerLocal & TriggerRecord::TL_CREATED_LQH)) {
13537       jam();
13538       ndbassert(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
13539       alterTrigger_sendReply(signal, opPtr, false);
13540       return;
13541     }
13542     req->setRequestType(DropTrigReq::RT_LQH);
13543   } else {
13544     ndbassert(false);
13545   }
13546   req->setTableId(triggerPtr.p->tableId);
13547   req->setIndexId(triggerPtr.p->indexId);
13548   req->setTriggerId(triggerPtr.i);
13549   req->setTriggerType(triggerPtr.p->triggerType);
13550   req->setTriggerActionTime(triggerPtr.p->triggerActionTime);
13551   req->setTriggerEvent(triggerPtr.p->triggerEvent);
13552   req->setMonitorReplicas(triggerPtr.p->monitorReplicas);
13553   req->setMonitorAllAttributes(triggerPtr.p->monitorAllAttributes);
13554   BlockReference blockRef = 0;
13555   if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
13556     jam();
13557     blockRef = calcTcBlockRef(getOwnNodeId());
13558   } else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
13559     jam();
13560     blockRef = calcLqhBlockRef(getOwnNodeId());
13561   } else {
13562     ndbassert(false);
13563   }
13564   sendSignal(blockRef, GSN_DROP_TRIG_REQ,
13565       signal, DropTrigReq::SignalLength, JBB);
13566 }
13567 
13568 void
alterTrigger_fromDropLocal(Signal * signal,OpAlterTriggerPtr opPtr)13569 Dbdict::alterTrigger_fromDropLocal(Signal* signal, OpAlterTriggerPtr opPtr)
13570 {
13571   jam();
13572   if (! opPtr.p->hasLastError()) {
13573     // mark dropped locally
13574     TriggerRecordPtr triggerPtr;
13575     c_triggerRecordPool.getPtr(triggerPtr, opPtr.p->m_request.getTriggerId());
13576     if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
13577       jam();
13578       triggerPtr.p->triggerLocal &= ~TriggerRecord::TL_CREATED_TC;
13579     } else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
13580       jam();
13581       triggerPtr.p->triggerLocal &= ~TriggerRecord::TL_CREATED_LQH;
13582     } else {
13583       ndbrequire(false);
13584     }
13585   }
13586   // forward CONF or REF to master
13587   alterTrigger_sendReply(signal, opPtr, false);
13588 }
13589 
13590 void
alterTrigger_slaveCommit(Signal * signal,OpAlterTriggerPtr opPtr)13591 Dbdict::alterTrigger_slaveCommit(Signal* signal, OpAlterTriggerPtr opPtr)
13592 {
13593   jam();
13594   TriggerRecordPtr triggerPtr;
13595   c_triggerRecordPool.getPtr(triggerPtr, opPtr.p->m_request.getTriggerId());
13596   // set state
13597   triggerPtr.p->triggerState = TriggerRecord::TS_ONLINE;
13598 }
13599 
13600 void
alterTrigger_slaveAbort(Signal * signal,OpAlterTriggerPtr opPtr)13601 Dbdict::alterTrigger_slaveAbort(Signal* signal, OpAlterTriggerPtr opPtr)
13602 {
13603   jam();
13604 }
13605 
13606 void
alterTrigger_sendSlaveReq(Signal * signal,OpAlterTriggerPtr opPtr)13607 Dbdict::alterTrigger_sendSlaveReq(Signal* signal, OpAlterTriggerPtr opPtr)
13608 {
13609   AlterTrigReq* const req = (AlterTrigReq*)signal->getDataPtrSend();
13610   *req = opPtr.p->m_request;
13611   req->setUserRef(opPtr.p->m_coordinatorRef);
13612   req->setConnectionPtr(opPtr.p->key);
13613   req->setRequestType(opPtr.p->m_requestType);
13614   req->addRequestFlag(opPtr.p->m_requestFlag);
13615   NdbNodeBitmask receiverNodes = c_aliveNodes;
13616   if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL) {
13617     receiverNodes.clear();
13618     receiverNodes.set(getOwnNodeId());
13619   } else {
13620     opPtr.p->m_nodes.bitAND(receiverNodes);
13621     receiverNodes = opPtr.p->m_nodes;
13622   }
13623   opPtr.p->m_signalCounter = receiverNodes;
13624   NodeReceiverGroup rg(DBDICT, receiverNodes);
13625   sendSignal(rg, GSN_ALTER_TRIG_REQ,
13626       signal, AlterTrigReq::SignalLength, JBB);
13627 }
13628 
13629 void
alterTrigger_sendReply(Signal * signal,OpAlterTriggerPtr opPtr,bool toUser)13630 Dbdict::alterTrigger_sendReply(Signal* signal, OpAlterTriggerPtr opPtr,
13631     bool toUser)
13632 {
13633   jam();
13634   AlterTrigRef* rep = (AlterTrigRef*)signal->getDataPtrSend();
13635   Uint32 gsn = GSN_ALTER_TRIG_CONF;
13636   Uint32 length = AlterTrigConf::InternalLength;
13637   bool sendRef;
13638   if (! toUser) {
13639     sendRef = opPtr.p->hasLastError();
13640     rep->setUserRef(opPtr.p->m_coordinatorRef);
13641     rep->setConnectionPtr(opPtr.p->key);
13642     rep->setRequestType(opPtr.p->m_requestType);
13643     if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_ABORT) {
13644       jam();
13645       sendRef = false;
13646     } else {
13647       jam();
13648     }
13649   } else {
13650     sendRef = opPtr.p->hasError();
13651     jam();
13652     rep->setUserRef(opPtr.p->m_request.getUserRef());
13653     rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
13654     rep->setRequestType(opPtr.p->m_request.getRequestType());
13655     length = AlterTrigConf::SignalLength;
13656   }
13657   rep->setTableId(opPtr.p->m_request.getTableId());
13658   rep->setTriggerId(opPtr.p->m_request.getTriggerId());
13659   if (sendRef) {
13660     if (opPtr.p->m_errorNode == 0) {
13661       jam();
13662       opPtr.p->m_errorNode = getOwnNodeId();
13663     } else {
13664       jam();
13665     }
13666     rep->setErrorCode(opPtr.p->m_errorCode);
13667     rep->setErrorLine(opPtr.p->m_errorLine);
13668     rep->setErrorNode(opPtr.p->m_errorNode);
13669     gsn = GSN_ALTER_TRIG_REF;
13670     length = AlterTrigRef::SignalLength;
13671   }
13672   sendSignal(rep->getUserRef(), gsn, signal, length, JBB);
13673 }
13674 
13675 /**
13676  * MODULE: Support routines for index and trigger.
13677  */
13678 
13679 /*
13680   This routine is used to set-up the primary key attributes of the unique
13681   hash index. Since we store fragment id as part of the primary key here
13682   we insert the pseudo column for getting fragment id first in the array.
13683   This routine is used as part of the building of the index.
13684 */
13685 
13686 void
getTableKeyList(TableRecordPtr tablePtr,Id_array<MAX_ATTRIBUTES_IN_INDEX+1> & list)13687 Dbdict::getTableKeyList(TableRecordPtr tablePtr,
13688 			Id_array<MAX_ATTRIBUTES_IN_INDEX+1>& list)
13689 {
13690   jam();
13691   list.sz = 0;
13692   list.id[list.sz++] = AttributeHeader::FRAGMENT;
13693   LocalDLFifoList<AttributeRecord> alist(c_attributeRecordPool,
13694                                          tablePtr.p->m_attributes);
13695   AttributeRecordPtr attrPtr;
13696   for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr)) {
13697     if (attrPtr.p->tupleKey) {
13698       list.id[list.sz++] = attrPtr.p->attributeId;
13699     }
13700   }
13701   ndbrequire(list.sz == (uint)(tablePtr.p->noOfPrimkey + 1));
13702   ndbrequire(list.sz <= MAX_ATTRIBUTES_IN_INDEX + 1);
13703 }
13704 
13705 // XXX should store the primary attribute id
13706 void
getIndexAttr(TableRecordPtr indexPtr,Uint32 itAttr,Uint32 * id)13707 Dbdict::getIndexAttr(TableRecordPtr indexPtr, Uint32 itAttr, Uint32* id)
13708 {
13709   jam();
13710 
13711   Uint32 len;
13712   char name[MAX_ATTR_NAME_SIZE];
13713   TableRecordPtr tablePtr;
13714   AttributeRecordPtr attrPtr;
13715 
13716   c_tableRecordPool.getPtr(tablePtr, indexPtr.p->primaryTableId);
13717   AttributeRecord* iaRec = c_attributeRecordPool.getPtr(itAttr);
13718   {
13719     ConstRope tmp(c_rope_pool, iaRec->attributeName);
13720     tmp.copy(name);
13721     len = tmp.size();
13722   }
13723   LocalDLFifoList<AttributeRecord> alist(c_attributeRecordPool,
13724 					 tablePtr.p->m_attributes);
13725   for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr)){
13726     ConstRope tmp(c_rope_pool, attrPtr.p->attributeName);
13727     if(tmp.compare(name, len) == 0){
13728       id[0] = attrPtr.p->attributeId;
13729       return;
13730     }
13731   }
13732   ndbrequire(false);
13733 }
13734 
13735 void
getIndexAttrList(TableRecordPtr indexPtr,AttributeList & list)13736 Dbdict::getIndexAttrList(TableRecordPtr indexPtr, AttributeList& list)
13737 {
13738   jam();
13739   list.sz = 0;
13740   memset(list.id, 0, sizeof(list.id));
13741   ndbrequire(indexPtr.p->noOfAttributes >= 2);
13742 
13743   LocalDLFifoList<AttributeRecord> alist(c_attributeRecordPool,
13744                                          indexPtr.p->m_attributes);
13745   AttributeRecordPtr attrPtr;
13746   for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr)) {
13747     // skip last
13748     AttributeRecordPtr tempPtr = attrPtr;
13749     if (! alist.next(tempPtr))
13750       break;
13751     getIndexAttr(indexPtr, attrPtr.i, &list.id[list.sz++]);
13752   }
13753   ndbrequire(indexPtr.p->noOfAttributes == list.sz + 1);
13754 }
13755 
13756 void
getIndexAttrMask(TableRecordPtr indexPtr,AttributeMask & mask)13757 Dbdict::getIndexAttrMask(TableRecordPtr indexPtr, AttributeMask& mask)
13758 {
13759   jam();
13760   mask.clear();
13761   ndbrequire(indexPtr.p->noOfAttributes >= 2);
13762 
13763   AttributeRecordPtr attrPtr, currPtr;
13764   LocalDLFifoList<AttributeRecord> alist(c_attributeRecordPool,
13765 					 indexPtr.p->m_attributes);
13766 
13767 
13768   for (alist.first(attrPtr); currPtr = attrPtr, alist.next(attrPtr); ){
13769     Uint32 id;
13770     getIndexAttr(indexPtr, currPtr.i, &id);
13771     mask.set(id);
13772   }
13773 }
13774 
13775 // DICT lock master
13776 
13777 const Dbdict::DictLockType*
getDictLockType(Uint32 lockType)13778 Dbdict::getDictLockType(Uint32 lockType)
13779 {
13780   static const DictLockType lt[] = {
13781     { DictLockReq::NodeRestartLock, BS_NODE_RESTART, "NodeRestart" }
13782   };
13783   for (unsigned int i = 0; i < sizeof(lt)/sizeof(lt[0]); i++) {
13784     if ((Uint32) lt[i].lockType == lockType)
13785       return &lt[i];
13786   }
13787   return NULL;
13788 }
13789 
13790 void
sendDictLockInfoEvent(Uint32 pollCount)13791 Dbdict::sendDictLockInfoEvent(Uint32 pollCount)
13792 {
13793   DictLockPtr loopPtr;
13794   c_dictLockQueue.first(loopPtr);
13795   unsigned count = 0;
13796 
13797   char queue_buf[100];
13798   char *p = &queue_buf[0];
13799   const char *const q = &queue_buf[sizeof(queue_buf)];
13800   *p = 0;
13801 
13802   while (loopPtr.i != RNIL) {
13803     jam();
13804     my_snprintf(p, q-p, "%s%u%s",
13805                 ++count == 1 ? "" : " ",
13806                 (unsigned)refToNode(loopPtr.p->req.userRef),
13807                 loopPtr.p->locked ? "L" : "");
13808     p += strlen(p);
13809     c_dictLockQueue.next(loopPtr);
13810   }
13811 
13812   infoEvent("DICT: lock bs: %d ops: %d poll: %d cnt: %d queue: %s",
13813       (int)c_blockState,
13814       c_opRecordPool.getSize() - c_opRecordPool.getNoOfFree(),
13815       c_dictLockPoll, (int)pollCount, queue_buf);
13816 }
13817 
13818 void
sendDictLockInfoEvent(DictLockPtr lockPtr,const char * text)13819 Dbdict::sendDictLockInfoEvent(DictLockPtr lockPtr, const char* text)
13820 {
13821   infoEvent("DICT: %s %u for %s",
13822       text,
13823       (unsigned)refToNode(lockPtr.p->req.userRef), lockPtr.p->lt->text);
13824 }
13825 
13826 void
execDICT_LOCK_REQ(Signal * signal)13827 Dbdict::execDICT_LOCK_REQ(Signal* signal)
13828 {
13829   jamEntry();
13830   const DictLockReq* req = (const DictLockReq*)&signal->theData[0];
13831 
13832   // make sure bad request crashes slave, not master (us)
13833 
13834   if (getOwnNodeId() != c_masterNodeId) {
13835     jam();
13836     sendDictLockRef(signal, *req, DictLockRef::NotMaster);
13837     return;
13838   }
13839 
13840   const DictLockType* lt = getDictLockType(req->lockType);
13841   if (lt == NULL) {
13842     jam();
13843     sendDictLockRef(signal, *req, DictLockRef::InvalidLockType);
13844     return;
13845   }
13846 
13847   if (req->userRef != signal->getSendersBlockRef() ||
13848       getNodeInfo(refToNode(req->userRef)).m_type != NodeInfo::DB) {
13849     jam();
13850     sendDictLockRef(signal, *req, DictLockRef::BadUserRef);
13851     return;
13852   }
13853 
13854   if (c_aliveNodes.get(refToNode(req->userRef))) {
13855     jam();
13856     sendDictLockRef(signal, *req, DictLockRef::TooLate);
13857     return;
13858   }
13859 
13860   DictLockPtr lockPtr;
13861   if (! c_dictLockQueue.seize(lockPtr)) {
13862     jam();
13863     sendDictLockRef(signal, *req, DictLockRef::TooManyRequests);
13864     return;
13865   }
13866 
13867   lockPtr.p->req = *req;
13868   lockPtr.p->locked = false;
13869   lockPtr.p->lt = lt;
13870 
13871   checkDictLockQueue(signal, false);
13872 
13873   if (! lockPtr.p->locked)
13874     sendDictLockInfoEvent(lockPtr, "lock request by node");
13875 }
13876 
13877 // only table and index ops are checked
13878 bool
hasDictLockSchemaOp()13879 Dbdict::hasDictLockSchemaOp()
13880 {
13881   return
13882     ! c_opCreateTable.isEmpty() ||
13883     ! c_opDropTable.isEmpty() ||
13884     ! c_opCreateIndex.isEmpty() ||
13885     ! c_opDropIndex.isEmpty();
13886 }
13887 
13888 void
checkDictLockQueue(Signal * signal,bool poll)13889 Dbdict::checkDictLockQueue(Signal* signal, bool poll)
13890 {
13891   Uint32 pollCount = ! poll ? 0 : signal->theData[1];
13892 
13893   DictLockPtr lockPtr;
13894 
13895   do {
13896     if (! c_dictLockQueue.first(lockPtr)) {
13897       jam();
13898       setDictLockPoll(signal, false, pollCount);
13899       return;
13900     }
13901 
13902     if (lockPtr.p->locked) {
13903       jam();
13904       ndbrequire(c_blockState == lockPtr.p->lt->blockState);
13905       break;
13906     }
13907 
13908     if (hasDictLockSchemaOp()) {
13909       jam();
13910       break;
13911     }
13912 
13913     if (c_blockState != BS_IDLE)
13914     {
13915       /**
13916        * If state is BS_NODE_FAILURE, it might be that no op is running
13917        */
13918       jam();
13919       break;
13920     }
13921 
13922     ndbrequire(c_blockState == BS_IDLE);
13923     lockPtr.p->locked = true;
13924     c_blockState = lockPtr.p->lt->blockState;
13925     sendDictLockConf(signal, lockPtr);
13926 
13927     sendDictLockInfoEvent(lockPtr, "locked by node");
13928   } while (0);
13929 
13930   // poll while first request is open
13931   // this routine is called again when it is removed for any reason
13932 
13933   bool on = ! lockPtr.p->locked;
13934   setDictLockPoll(signal, on, pollCount);
13935 }
13936 
13937 void
execDICT_UNLOCK_ORD(Signal * signal)13938 Dbdict::execDICT_UNLOCK_ORD(Signal* signal)
13939 {
13940   jamEntry();
13941   const DictUnlockOrd* ord = (const DictUnlockOrd*)&signal->theData[0];
13942 
13943   DictLockPtr lockPtr;
13944   c_dictLockQueue.getPtr(lockPtr, ord->lockPtr);
13945   ndbrequire((Uint32) lockPtr.p->lt->lockType == ord->lockType);
13946 
13947   if (lockPtr.p->locked) {
13948     jam();
13949     ndbrequire(c_blockState == lockPtr.p->lt->blockState);
13950     ndbrequire(! hasDictLockSchemaOp());
13951     ndbrequire(! c_dictLockQueue.hasPrev(lockPtr));
13952 
13953     c_blockState = BS_IDLE;
13954     sendDictLockInfoEvent(lockPtr, "unlocked by node");
13955   } else {
13956     sendDictLockInfoEvent(lockPtr, "lock request removed by node");
13957   }
13958 
13959   c_dictLockQueue.release(lockPtr);
13960 
13961   checkDictLockQueue(signal, false);
13962 }
13963 
13964 void
sendDictLockConf(Signal * signal,DictLockPtr lockPtr)13965 Dbdict::sendDictLockConf(Signal* signal, DictLockPtr lockPtr)
13966 {
13967   DictLockConf* conf = (DictLockConf*)&signal->theData[0];
13968   const DictLockReq& req = lockPtr.p->req;
13969 
13970   conf->userPtr = req.userPtr;
13971   conf->lockType = req.lockType;
13972   conf->lockPtr = lockPtr.i;
13973 
13974   sendSignal(req.userRef, GSN_DICT_LOCK_CONF, signal,
13975       DictLockConf::SignalLength, JBB);
13976 }
13977 
13978 void
sendDictLockRef(Signal * signal,DictLockReq req,Uint32 errorCode)13979 Dbdict::sendDictLockRef(Signal* signal, DictLockReq req, Uint32 errorCode)
13980 {
13981   DictLockRef* ref = (DictLockRef*)&signal->theData[0];
13982 
13983   ref->userPtr = req.userPtr;
13984   ref->lockType = req.lockType;
13985   ref->errorCode = errorCode;
13986 
13987   sendSignal(req.userRef, GSN_DICT_LOCK_REF, signal,
13988       DictLockRef::SignalLength, JBB);
13989 }
13990 
13991 // control polling
13992 
13993 void
setDictLockPoll(Signal * signal,bool on,Uint32 pollCount)13994 Dbdict::setDictLockPoll(Signal* signal, bool on, Uint32 pollCount)
13995 {
13996   if (on) {
13997     jam();
13998     signal->theData[0] = ZDICT_LOCK_POLL;
13999     signal->theData[1] = pollCount + 1;
14000     sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 2);
14001   }
14002 
14003   bool change = (c_dictLockPoll != on);
14004 
14005   if (change) {
14006     jam();
14007     c_dictLockPoll = on;
14008   }
14009 
14010   // avoid too many messages if master is stuck busy (BS_NODE_FAILURE)
14011   bool periodic =
14012     pollCount < 8 ||
14013     pollCount < 64 && pollCount % 8 == 0 ||
14014     pollCount < 512 && pollCount % 64 == 0 ||
14015     pollCount < 4096 && pollCount % 512 == 0 ||
14016     pollCount % 4096 == 0; // about every 6 minutes
14017 
14018   if (change || periodic)
14019     sendDictLockInfoEvent(pollCount);
14020 }
14021 
14022 // NF handling
14023 
14024 void
removeStaleDictLocks(Signal * signal,const Uint32 * theFailedNodes)14025 Dbdict::removeStaleDictLocks(Signal* signal, const Uint32* theFailedNodes)
14026 {
14027   DictLockPtr loopPtr;
14028   c_dictLockQueue.first(loopPtr);
14029 
14030   if (getOwnNodeId() != c_masterNodeId) {
14031     ndbrequire(loopPtr.i == RNIL);
14032     return;
14033   }
14034 
14035   while (loopPtr.i != RNIL) {
14036     jam();
14037     DictLockPtr lockPtr = loopPtr;
14038     c_dictLockQueue.next(loopPtr);
14039 
14040     Uint32 nodeId = refToNode(lockPtr.p->req.userRef);
14041 
14042     if (NodeBitmask::get(theFailedNodes, nodeId)) {
14043       if (lockPtr.p->locked) {
14044         jam();
14045         ndbrequire(c_blockState == lockPtr.p->lt->blockState);
14046         ndbrequire(! hasDictLockSchemaOp());
14047         ndbrequire(! c_dictLockQueue.hasPrev(lockPtr));
14048 
14049         c_blockState = BS_IDLE;
14050 
14051         sendDictLockInfoEvent(lockPtr, "remove lock by failed node");
14052       } else {
14053         sendDictLockInfoEvent(lockPtr, "remove lock request by failed node");
14054       }
14055 
14056       c_dictLockQueue.release(lockPtr);
14057     }
14058   }
14059 
14060   checkDictLockQueue(signal, false);
14061 }
14062 
14063 
14064 /* **************************************************************** */
14065 /* ---------------------------------------------------------------- */
14066 /* MODULE:          STORE/RESTORE SCHEMA FILE---------------------- */
14067 /* ---------------------------------------------------------------- */
14068 /*                                                                  */
14069 /* General module used to store the schema file on disk and         */
14070 /* similar function to restore it from disk.                        */
14071 /* ---------------------------------------------------------------- */
14072 /* **************************************************************** */
14073 
14074 void
initSchemaFile(XSchemaFile * xsf,Uint32 firstPage,Uint32 lastPage,bool initEntries)14075 Dbdict::initSchemaFile(XSchemaFile * xsf, Uint32 firstPage, Uint32 lastPage,
14076                        bool initEntries)
14077 {
14078   ndbrequire(lastPage <= xsf->noOfPages);
14079   for (Uint32 n = firstPage; n < lastPage; n++) {
14080     SchemaFile * sf = &xsf->schemaPage[n];
14081     if (initEntries)
14082       memset(sf, 0, NDB_SF_PAGE_SIZE);
14083 
14084     Uint32 ndb_version = NDB_VERSION;
14085     if (ndb_version < NDB_SF_VERSION_5_0_6)
14086       ndb_version = NDB_SF_VERSION_5_0_6;
14087 
14088     memcpy(sf->Magic, NDB_SF_MAGIC, sizeof(sf->Magic));
14089     sf->ByteOrder = 0x12345678;
14090     sf->NdbVersion =  ndb_version;
14091     sf->FileSize = xsf->noOfPages * NDB_SF_PAGE_SIZE;
14092     sf->PageNumber = n;
14093     sf->CheckSum = 0;
14094     sf->NoOfTableEntries = NDB_SF_PAGE_ENTRIES;
14095 
14096     computeChecksum(xsf, n);
14097   }
14098 }
14099 
14100 void
resizeSchemaFile(XSchemaFile * xsf,Uint32 noOfPages)14101 Dbdict::resizeSchemaFile(XSchemaFile * xsf, Uint32 noOfPages)
14102 {
14103   ndbrequire(noOfPages <= NDB_SF_MAX_PAGES);
14104   if (xsf->noOfPages < noOfPages) {
14105     jam();
14106     Uint32 firstPage = xsf->noOfPages;
14107     xsf->noOfPages = noOfPages;
14108     initSchemaFile(xsf, 0, firstPage, false);
14109     initSchemaFile(xsf, firstPage, xsf->noOfPages, true);
14110   }
14111   if (xsf->noOfPages > noOfPages) {
14112     jam();
14113     Uint32 tableId = noOfPages * NDB_SF_PAGE_ENTRIES;
14114     while (tableId < xsf->noOfPages * NDB_SF_PAGE_ENTRIES) {
14115       SchemaFile::TableEntry * te = getTableEntry(xsf, tableId);
14116       if (te->m_tableState != SchemaFile::INIT &&
14117           te->m_tableState != SchemaFile::DROP_TABLE_COMMITTED) {
14118         ndbrequire(false);
14119       }
14120       tableId++;
14121     }
14122     xsf->noOfPages = noOfPages;
14123     initSchemaFile(xsf, 0, xsf->noOfPages, false);
14124   }
14125 }
14126 
14127 void
computeChecksum(XSchemaFile * xsf,Uint32 pageNo)14128 Dbdict::computeChecksum(XSchemaFile * xsf, Uint32 pageNo){
14129   SchemaFile * sf = &xsf->schemaPage[pageNo];
14130   sf->CheckSum = 0;
14131   sf->CheckSum = computeChecksum((Uint32*)sf, NDB_SF_PAGE_SIZE_IN_WORDS);
14132 }
14133 
14134 bool
validateChecksum(const XSchemaFile * xsf)14135 Dbdict::validateChecksum(const XSchemaFile * xsf){
14136 
14137   for (Uint32 n = 0; n < xsf->noOfPages; n++) {
14138     SchemaFile * sf = &xsf->schemaPage[n];
14139     Uint32 c = computeChecksum((Uint32*)sf, NDB_SF_PAGE_SIZE_IN_WORDS);
14140     if ( c != 0)
14141       return false;
14142   }
14143   return true;
14144 }
14145 
14146 Uint32
computeChecksum(const Uint32 * src,Uint32 len)14147 Dbdict::computeChecksum(const Uint32 * src, Uint32 len){
14148   Uint32 ret = 0;
14149   for(Uint32 i = 0; i<len; i++)
14150     ret ^= src[i];
14151   return ret;
14152 }
14153 
14154 SchemaFile::TableEntry *
getTableEntry(XSchemaFile * xsf,Uint32 tableId)14155 Dbdict::getTableEntry(XSchemaFile * xsf, Uint32 tableId)
14156 {
14157   Uint32 n = tableId / NDB_SF_PAGE_ENTRIES;
14158   Uint32 i = tableId % NDB_SF_PAGE_ENTRIES;
14159   ndbrequire(n < xsf->noOfPages);
14160 
14161   SchemaFile * sf = &xsf->schemaPage[n];
14162   return &sf->TableEntries[i];
14163 }
14164 
14165 //******************************************
14166 void
execCREATE_FILE_REQ(Signal * signal)14167 Dbdict::execCREATE_FILE_REQ(Signal* signal)
14168 {
14169   jamEntry();
14170 
14171   if(!assembleFragments(signal)){
14172     jam();
14173     return;
14174   }
14175 
14176   CreateFileReq * req = (CreateFileReq*)signal->getDataPtr();
14177   CreateFileRef * ref = (CreateFileRef*)signal->getDataPtrSend();
14178   Uint32 senderRef = req->senderRef;
14179   Uint32 senderData = req->senderData;
14180   Uint32 type = req->objType;
14181   Uint32 requestInfo = req->requestInfo;
14182 
14183   do {
14184     if(getOwnNodeId() != c_masterNodeId){
14185       jam();
14186       ref->errorCode = CreateFileRef::NotMaster;
14187       ref->status    = 0;
14188       ref->errorKey  = 0;
14189       ref->errorLine = __LINE__;
14190       break;
14191     }
14192 
14193     if (c_blockState != BS_IDLE){
14194       jam();
14195       ref->errorCode = CreateFileRef::Busy;
14196       ref->status    = 0;
14197       ref->errorKey  = 0;
14198       ref->errorLine = __LINE__;
14199       break;
14200     }
14201 
14202     if (checkSingleUserMode(senderRef))
14203     {
14204       ref->errorCode = CreateFileRef::SingleUser;
14205       ref->status    = 0;
14206       ref->errorKey  = 0;
14207       ref->errorLine = __LINE__;
14208       break;
14209     }
14210 
14211     Ptr<SchemaTransaction> trans_ptr;
14212     if (! c_Trans.seize(trans_ptr)){
14213       jam();
14214       ref->errorCode = CreateFileRef::Busy;
14215       ref->status    = 0;
14216       ref->errorKey  = 0;
14217       ref->errorLine = __LINE__;
14218       break;
14219     }
14220     jam();
14221     const Uint32 trans_key = ++c_opRecordSequence;
14222     trans_ptr.p->key = trans_key;
14223     trans_ptr.p->m_senderRef = senderRef;
14224     trans_ptr.p->m_senderData = senderData;
14225     trans_ptr.p->m_nodes = c_aliveNodes;
14226     trans_ptr.p->m_errorCode = 0;
14227 //    trans_ptr.p->m_nodes.clear();
14228 //    trans_ptr.p->m_nodes.set(getOwnNodeId());
14229     c_Trans.add(trans_ptr);
14230 
14231     const Uint32 op_key = ++c_opRecordSequence;
14232     trans_ptr.p->m_op.m_key = op_key;
14233     trans_ptr.p->m_op.m_vt_index = 1;
14234     trans_ptr.p->m_op.m_state = DictObjOp::Preparing;
14235 
14236     CreateObjReq* create_obj = (CreateObjReq*)signal->getDataPtrSend();
14237     create_obj->op_key = op_key;
14238     create_obj->senderRef = reference();
14239     create_obj->senderData = trans_key;
14240     create_obj->clientRef = senderRef;
14241     create_obj->clientData = senderData;
14242 
14243     create_obj->objType = type;
14244     create_obj->requestInfo = requestInfo;
14245 
14246     {
14247       Uint32 objId = getFreeObjId(0);
14248       if (objId == RNIL) {
14249         jam();
14250         ref->errorCode = CreateFileRef::NoMoreObjectRecords;
14251         ref->status    = 0;
14252         ref->errorKey  = 0;
14253         ref->errorLine = __LINE__;
14254         break;
14255       }
14256 
14257       create_obj->objId = objId;
14258       trans_ptr.p->m_op.m_obj_id = objId;
14259       create_obj->gci = 0;
14260 
14261       XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
14262       SchemaFile::TableEntry *objEntry = getTableEntry(xsf, objId);
14263       create_obj->objVersion =
14264 	create_obj_inc_schema_version(objEntry->m_tableVersion);
14265     }
14266 
14267     NodeReceiverGroup rg(DBDICT, trans_ptr.p->m_nodes);
14268     SafeCounter tmp(c_counterMgr, trans_ptr.p->m_counter);
14269     tmp.init<CreateObjRef>(rg, GSN_CREATE_OBJ_REF, trans_key);
14270     sendSignal(rg, GSN_CREATE_OBJ_REQ, signal,
14271 	       CreateObjReq::SignalLength, JBB);
14272 
14273     c_blockState = BS_CREATE_TAB;
14274     return;
14275   } while(0);
14276 
14277   ref->senderData = senderData;
14278   ref->masterNodeId = c_masterNodeId;
14279   sendSignal(senderRef, GSN_CREATE_FILE_REF,signal,
14280 	     CreateFileRef::SignalLength, JBB);
14281 }
14282 
14283 void
execCREATE_FILEGROUP_REQ(Signal * signal)14284 Dbdict::execCREATE_FILEGROUP_REQ(Signal* signal)
14285 {
14286   jamEntry();
14287 
14288   if(!assembleFragments(signal)){
14289     jam();
14290     return;
14291   }
14292 
14293   CreateFilegroupReq * req = (CreateFilegroupReq*)signal->getDataPtr();
14294   CreateFilegroupRef * ref = (CreateFilegroupRef*)signal->getDataPtrSend();
14295   Uint32 senderRef = req->senderRef;
14296   Uint32 senderData = req->senderData;
14297   Uint32 type = req->objType;
14298 
14299   do {
14300     if(getOwnNodeId() != c_masterNodeId){
14301       jam();
14302       ref->errorCode = CreateFilegroupRef::NotMaster;
14303       ref->status    = 0;
14304       ref->errorKey  = 0;
14305       ref->errorLine = __LINE__;
14306       break;
14307     }
14308 
14309     if (c_blockState != BS_IDLE){
14310       jam();
14311       ref->errorCode = CreateFilegroupRef::Busy;
14312       ref->status    = 0;
14313       ref->errorKey  = 0;
14314       ref->errorLine = __LINE__;
14315       break;
14316     }
14317 
14318     if (checkSingleUserMode(senderRef))
14319     {
14320       ref->errorCode = CreateFilegroupRef::SingleUser;
14321       ref->status    = 0;
14322       ref->errorKey  = 0;
14323       ref->errorLine = __LINE__;
14324       break;
14325     }
14326 
14327     Ptr<SchemaTransaction> trans_ptr;
14328     if (! c_Trans.seize(trans_ptr)){
14329       jam();
14330       ref->errorCode = CreateFilegroupRef::Busy;
14331       ref->status    = 0;
14332       ref->errorKey  = 0;
14333       ref->errorLine = __LINE__;
14334       break;
14335     }
14336     jam();
14337     const Uint32 trans_key = ++c_opRecordSequence;
14338     trans_ptr.p->key = trans_key;
14339     trans_ptr.p->m_senderRef = senderRef;
14340     trans_ptr.p->m_senderData = senderData;
14341     trans_ptr.p->m_nodes = c_aliveNodes;
14342     trans_ptr.p->m_errorCode = 0;
14343     c_Trans.add(trans_ptr);
14344 
14345     const Uint32 op_key = ++c_opRecordSequence;
14346     trans_ptr.p->m_op.m_key = op_key;
14347     trans_ptr.p->m_op.m_vt_index = 0;
14348     trans_ptr.p->m_op.m_state = DictObjOp::Preparing;
14349 
14350     CreateObjReq* create_obj = (CreateObjReq*)signal->getDataPtrSend();
14351     create_obj->op_key = op_key;
14352     create_obj->senderRef = reference();
14353     create_obj->senderData = trans_key;
14354     create_obj->clientRef = senderRef;
14355     create_obj->clientData = senderData;
14356 
14357     create_obj->objType = type;
14358 
14359     {
14360       Uint32 objId = getFreeObjId(0);
14361       if (objId == RNIL) {
14362         jam();
14363         ref->errorCode = CreateFilegroupRef::NoMoreObjectRecords;
14364         ref->status    = 0;
14365         ref->errorKey  = 0;
14366         ref->errorLine = __LINE__;
14367         break;
14368       }
14369 
14370       create_obj->objId = objId;
14371       trans_ptr.p->m_op.m_obj_id = objId;
14372       create_obj->gci = 0;
14373 
14374       XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
14375       SchemaFile::TableEntry *objEntry = getTableEntry(xsf, objId);
14376       create_obj->objVersion =
14377 	create_obj_inc_schema_version(objEntry->m_tableVersion);
14378     }
14379 
14380     NodeReceiverGroup rg(DBDICT, trans_ptr.p->m_nodes);
14381     SafeCounter tmp(c_counterMgr, trans_ptr.p->m_counter);
14382     tmp.init<CreateObjRef>(rg, GSN_CREATE_OBJ_REF, trans_key);
14383     sendSignal(rg, GSN_CREATE_OBJ_REQ, signal,
14384 	       CreateObjReq::SignalLength, JBB);
14385 
14386     c_blockState = BS_CREATE_TAB;
14387     return;
14388   } while(0);
14389 
14390   ref->senderData = senderData;
14391   ref->masterNodeId = c_masterNodeId;
14392   sendSignal(senderRef, GSN_CREATE_FILEGROUP_REF,signal,
14393 	     CreateFilegroupRef::SignalLength, JBB);
14394 }
14395 
14396 void
execDROP_FILE_REQ(Signal * signal)14397 Dbdict::execDROP_FILE_REQ(Signal* signal)
14398 {
14399   jamEntry();
14400 
14401   if(!assembleFragments(signal)){
14402     jam();
14403     return;
14404   }
14405 
14406   DropFileReq * req = (DropFileReq*)signal->getDataPtr();
14407   DropFileRef * ref = (DropFileRef*)signal->getDataPtrSend();
14408   Uint32 senderRef = req->senderRef;
14409   Uint32 senderData = req->senderData;
14410   Uint32 objId = req->file_id;
14411   Uint32 version = req->file_version;
14412 
14413   do {
14414     if(getOwnNodeId() != c_masterNodeId){
14415       jam();
14416       ref->errorCode = DropFileRef::NotMaster;
14417       ref->errorKey  = 0;
14418       ref->errorLine = __LINE__;
14419       break;
14420     }
14421 
14422     if (c_blockState != BS_IDLE)
14423     {
14424       jam();
14425       ref->errorCode = DropFileRef::Busy;
14426       ref->errorKey  = 0;
14427       ref->errorLine = __LINE__;
14428       break;
14429     }
14430 
14431     if (checkSingleUserMode(senderRef))
14432     {
14433       jam();
14434       ref->errorCode = DropFileRef::SingleUser;
14435       ref->errorKey  = 0;
14436       ref->errorLine = __LINE__;
14437       break;
14438     }
14439 
14440     Ptr<File> file_ptr;
14441     if (!c_file_hash.find(file_ptr, objId))
14442     {
14443       jam();
14444       ref->errorCode = DropFileRef::NoSuchFile;
14445       ref->errorLine = __LINE__;
14446       break;
14447     }
14448 
14449     if (file_ptr.p->m_version != version)
14450     {
14451       jam();
14452       ref->errorCode = DropFileRef::InvalidSchemaObjectVersion;
14453       ref->errorLine = __LINE__;
14454       break;
14455     }
14456 
14457     Ptr<SchemaTransaction> trans_ptr;
14458     if (! c_Trans.seize(trans_ptr))
14459     {
14460       jam();
14461       ref->errorCode = DropFileRef::Busy;
14462       ref->errorLine = __LINE__;
14463       break;
14464     }
14465     jam();
14466 
14467     const Uint32 trans_key = ++c_opRecordSequence;
14468     trans_ptr.p->key = trans_key;
14469     trans_ptr.p->m_senderRef = senderRef;
14470     trans_ptr.p->m_senderData = senderData;
14471     trans_ptr.p->m_nodes = c_aliveNodes;
14472     trans_ptr.p->m_errorCode = 0;
14473     c_Trans.add(trans_ptr);
14474 
14475     const Uint32 op_key = ++c_opRecordSequence;
14476     trans_ptr.p->m_op.m_key = op_key;
14477     trans_ptr.p->m_op.m_vt_index = 2;
14478     trans_ptr.p->m_op.m_state = DictObjOp::Preparing;
14479 
14480     DropObjReq* drop_obj = (DropObjReq*)signal->getDataPtrSend();
14481     drop_obj->op_key = op_key;
14482     drop_obj->objVersion = version;
14483     drop_obj->objId = objId;
14484     drop_obj->objType = file_ptr.p->m_type;
14485     trans_ptr.p->m_op.m_obj_id = objId;
14486 
14487     drop_obj->senderRef = reference();
14488     drop_obj->senderData = trans_key;
14489     drop_obj->clientRef = senderRef;
14490     drop_obj->clientData = senderData;
14491 
14492     drop_obj->requestInfo = 0;
14493 
14494     NodeReceiverGroup rg(DBDICT, trans_ptr.p->m_nodes);
14495     SafeCounter tmp(c_counterMgr, trans_ptr.p->m_counter);
14496     tmp.init<CreateObjRef>(rg, GSN_DROP_OBJ_REF, trans_key);
14497     sendSignal(rg, GSN_DROP_OBJ_REQ, signal,
14498 	       DropObjReq::SignalLength, JBB);
14499 
14500     c_blockState = BS_CREATE_TAB;
14501     return;
14502   } while(0);
14503 
14504   ref->senderData = senderData;
14505   ref->masterNodeId = c_masterNodeId;
14506   sendSignal(senderRef, GSN_DROP_FILE_REF,signal,
14507 	     DropFileRef::SignalLength, JBB);
14508 }
14509 
14510 void
execDROP_FILEGROUP_REQ(Signal * signal)14511 Dbdict::execDROP_FILEGROUP_REQ(Signal* signal)
14512 {
14513   jamEntry();
14514 
14515   if(!assembleFragments(signal)){
14516     jam();
14517     return;
14518   }
14519 
14520   DropFilegroupReq * req = (DropFilegroupReq*)signal->getDataPtr();
14521   DropFilegroupRef * ref = (DropFilegroupRef*)signal->getDataPtrSend();
14522   Uint32 senderRef = req->senderRef;
14523   Uint32 senderData = req->senderData;
14524   Uint32 objId = req->filegroup_id;
14525   Uint32 version = req->filegroup_version;
14526 
14527   do {
14528     if(getOwnNodeId() != c_masterNodeId)
14529     {
14530       jam();
14531       ref->errorCode = DropFilegroupRef::NotMaster;
14532       ref->errorKey  = 0;
14533       ref->errorLine = __LINE__;
14534       break;
14535     }
14536 
14537     if (c_blockState != BS_IDLE)
14538     {
14539       jam();
14540       ref->errorCode = DropFilegroupRef::Busy;
14541       ref->errorKey  = 0;
14542       ref->errorLine = __LINE__;
14543       break;
14544     }
14545 
14546     if (checkSingleUserMode(senderRef))
14547     {
14548       jam();
14549       ref->errorCode = DropFilegroupRef::SingleUser;
14550       ref->errorKey  = 0;
14551       ref->errorLine = __LINE__;
14552       break;
14553     }
14554 
14555     Ptr<Filegroup> filegroup_ptr;
14556     if (!c_filegroup_hash.find(filegroup_ptr, objId))
14557     {
14558       jam();
14559       ref->errorCode = DropFilegroupRef::NoSuchFilegroup;
14560       ref->errorLine = __LINE__;
14561       break;
14562     }
14563 
14564     if (filegroup_ptr.p->m_version != version)
14565     {
14566       jam();
14567       ref->errorCode = DropFilegroupRef::InvalidSchemaObjectVersion;
14568       ref->errorLine = __LINE__;
14569       break;
14570     }
14571 
14572     Ptr<SchemaTransaction> trans_ptr;
14573     if (! c_Trans.seize(trans_ptr))
14574     {
14575       jam();
14576       ref->errorCode = DropFilegroupRef::Busy;
14577       ref->errorLine = __LINE__;
14578       break;
14579     }
14580     jam();
14581 
14582     const Uint32 trans_key = ++c_opRecordSequence;
14583     trans_ptr.p->key = trans_key;
14584     trans_ptr.p->m_senderRef = senderRef;
14585     trans_ptr.p->m_senderData = senderData;
14586     trans_ptr.p->m_nodes = c_aliveNodes;
14587     trans_ptr.p->m_errorCode = 0;
14588     c_Trans.add(trans_ptr);
14589 
14590     const Uint32 op_key = ++c_opRecordSequence;
14591     trans_ptr.p->m_op.m_key = op_key;
14592     trans_ptr.p->m_op.m_vt_index = 3;
14593     trans_ptr.p->m_op.m_state = DictObjOp::Preparing;
14594 
14595     DropObjReq* drop_obj = (DropObjReq*)signal->getDataPtrSend();
14596     drop_obj->op_key = op_key;
14597     drop_obj->objVersion = version;
14598     drop_obj->objId = objId;
14599     drop_obj->objType = filegroup_ptr.p->m_type;
14600     trans_ptr.p->m_op.m_obj_id = objId;
14601 
14602     drop_obj->senderRef = reference();
14603     drop_obj->senderData = trans_key;
14604     drop_obj->clientRef = senderRef;
14605     drop_obj->clientData = senderData;
14606 
14607     drop_obj->requestInfo = 0;
14608 
14609     NodeReceiverGroup rg(DBDICT, trans_ptr.p->m_nodes);
14610     SafeCounter tmp(c_counterMgr, trans_ptr.p->m_counter);
14611     tmp.init<CreateObjRef>(rg, GSN_DROP_OBJ_REF, trans_key);
14612     sendSignal(rg, GSN_DROP_OBJ_REQ, signal,
14613 	       DropObjReq::SignalLength, JBB);
14614 
14615     c_blockState = BS_CREATE_TAB;
14616     return;
14617   } while(0);
14618 
14619   ref->senderData = senderData;
14620   ref->masterNodeId = c_masterNodeId;
14621   sendSignal(senderRef, GSN_DROP_FILEGROUP_REF,signal,
14622 	     DropFilegroupRef::SignalLength, JBB);
14623 }
14624 
14625 void
execCREATE_OBJ_REF(Signal * signal)14626 Dbdict::execCREATE_OBJ_REF(Signal* signal)
14627 {
14628   CreateObjRef * const ref = (CreateObjRef*)signal->getDataPtr();
14629   Ptr<SchemaTransaction> trans_ptr;
14630 
14631   jamEntry();
14632   ndbrequire(c_Trans.find(trans_ptr, ref->senderData));
14633   if(ref->errorCode != CreateObjRef::NF_FakeErrorREF){
14634     jam();
14635     trans_ptr.p->setErrorCode(ref->errorCode);
14636   }
14637   Uint32 node = refToNode(ref->senderRef);
14638   schemaOp_reply(signal, trans_ptr.p, node);
14639 }
14640 
14641 void
execCREATE_OBJ_CONF(Signal * signal)14642 Dbdict::execCREATE_OBJ_CONF(Signal* signal)
14643 {
14644   Ptr<SchemaTransaction> trans_ptr;
14645   CreateObjConf * const conf = (CreateObjConf*)signal->getDataPtr();
14646 
14647   jamEntry();
14648   ndbrequire(c_Trans.find(trans_ptr, conf->senderData));
14649   schemaOp_reply(signal, trans_ptr.p, refToNode(conf->senderRef));
14650 }
14651 
14652 void
schemaOp_reply(Signal * signal,SchemaTransaction * trans_ptr_p,Uint32 nodeId)14653 Dbdict::schemaOp_reply(Signal* signal,
14654 		       SchemaTransaction * trans_ptr_p,
14655 		       Uint32 nodeId)
14656 {
14657   jam();
14658   {
14659     SafeCounter tmp(c_counterMgr, trans_ptr_p->m_counter);
14660     if(!tmp.clearWaitingFor(nodeId)){
14661       jam();
14662       return;
14663     }
14664   }
14665 
14666   switch(trans_ptr_p->m_op.m_state){
14667   case DictObjOp::Preparing:{
14668     if(trans_ptr_p->m_errorCode != 0)
14669     {
14670       /**
14671        * Failed to prepare on atleast one node -> abort on all
14672        */
14673       trans_ptr_p->m_op.m_state = DictObjOp::Aborting;
14674       trans_ptr_p->m_callback.m_callbackData = trans_ptr_p->key;
14675       trans_ptr_p->m_callback.m_callbackFunction=
14676 	safe_cast(&Dbdict::trans_abort_start_done);
14677 
14678       if(f_dict_op[trans_ptr_p->m_op.m_vt_index].m_trans_abort_start)
14679       {
14680         jam();
14681 	(this->*f_dict_op[trans_ptr_p->m_op.m_vt_index].m_trans_abort_start)
14682 	  (signal, trans_ptr_p);
14683       }
14684       else
14685       {
14686         jam();
14687 	execute(signal, trans_ptr_p->m_callback, 0);
14688       }
14689       return;
14690     }
14691 
14692     trans_ptr_p->m_op.m_state = DictObjOp::Prepared;
14693     trans_ptr_p->m_callback.m_callbackData = trans_ptr_p->key;
14694     trans_ptr_p->m_callback.m_callbackFunction=
14695       safe_cast(&Dbdict::trans_commit_start_done);
14696 
14697     if(f_dict_op[trans_ptr_p->m_op.m_vt_index].m_trans_commit_start)
14698     {
14699       jam();
14700       (this->*f_dict_op[trans_ptr_p->m_op.m_vt_index].m_trans_commit_start)
14701 	(signal, trans_ptr_p);
14702     }
14703     else
14704     {
14705       jam();
14706       execute(signal, trans_ptr_p->m_callback, 0);
14707     }
14708     return;
14709   }
14710   case DictObjOp::Committing: {
14711     ndbrequire(trans_ptr_p->m_errorCode == 0);
14712 
14713     trans_ptr_p->m_op.m_state = DictObjOp::Committed;
14714     trans_ptr_p->m_callback.m_callbackData = trans_ptr_p->key;
14715     trans_ptr_p->m_callback.m_callbackFunction=
14716       safe_cast(&Dbdict::trans_commit_complete_done);
14717 
14718     if(f_dict_op[trans_ptr_p->m_op.m_vt_index].m_trans_commit_complete)
14719     {
14720       jam();
14721       (this->*f_dict_op[trans_ptr_p->m_op.m_vt_index].m_trans_commit_complete)
14722 	(signal, trans_ptr_p);
14723     }
14724     else
14725     {
14726       jam();
14727       execute(signal, trans_ptr_p->m_callback, 0);
14728     }
14729     return;
14730   }
14731   case DictObjOp::Aborting:{
14732     trans_ptr_p->m_op.m_state = DictObjOp::Committed;
14733     trans_ptr_p->m_callback.m_callbackData = trans_ptr_p->key;
14734     trans_ptr_p->m_callback.m_callbackFunction=
14735       safe_cast(&Dbdict::trans_abort_complete_done);
14736 
14737     if(f_dict_op[trans_ptr_p->m_op.m_vt_index].m_trans_abort_complete)
14738     {
14739       jam();
14740       (this->*f_dict_op[trans_ptr_p->m_op.m_vt_index].m_trans_abort_complete)
14741 	(signal, trans_ptr_p);
14742     }
14743     else
14744     {
14745       jam();
14746       execute(signal, trans_ptr_p->m_callback, 0);
14747     }
14748     return;
14749   }
14750   case DictObjOp::Defined:
14751   case DictObjOp::Prepared:
14752   case DictObjOp::Committed:
14753   case DictObjOp::Aborted:
14754     jam();
14755     break;
14756   }
14757   ndbrequire(false);
14758 }
14759 
14760 void
trans_commit_start_done(Signal * signal,Uint32 callbackData,Uint32 retValue)14761 Dbdict::trans_commit_start_done(Signal* signal,
14762 				Uint32 callbackData,
14763 				Uint32 retValue)
14764 {
14765   Ptr<SchemaTransaction> trans_ptr;
14766 
14767   jam();
14768   ndbrequire(retValue == 0);
14769   ndbrequire(c_Trans.find(trans_ptr, callbackData));
14770   NodeReceiverGroup rg(DBDICT, trans_ptr.p->m_nodes);
14771   SafeCounter tmp(c_counterMgr, trans_ptr.p->m_counter);
14772   tmp.init<DictCommitRef>(rg, GSN_DICT_COMMIT_REF, trans_ptr.p->key);
14773 
14774   DictCommitReq * const req = (DictCommitReq*)signal->getDataPtrSend();
14775   req->senderRef = reference();
14776   req->senderData = trans_ptr.p->key;
14777   req->op_key = trans_ptr.p->m_op.m_key;
14778   sendSignal(rg, GSN_DICT_COMMIT_REQ, signal, DictCommitReq::SignalLength,
14779 	     JBB);
14780   trans_ptr.p->m_op.m_state = DictObjOp::Committing;
14781 }
14782 
14783 void
trans_commit_complete_done(Signal * signal,Uint32 callbackData,Uint32 retValue)14784 Dbdict::trans_commit_complete_done(Signal* signal,
14785 				   Uint32 callbackData,
14786 				   Uint32 retValue)
14787 {
14788   Ptr<SchemaTransaction> trans_ptr;
14789 
14790   jam();
14791   ndbrequire(retValue == 0);
14792   ndbrequire(c_Trans.find(trans_ptr, callbackData));
14793 
14794   switch(f_dict_op[trans_ptr.p->m_op.m_vt_index].m_gsn_user_req){
14795   case GSN_CREATE_FILEGROUP_REQ:{
14796     FilegroupPtr fg_ptr;
14797     jam();
14798     ndbrequire(c_filegroup_hash.find(fg_ptr, trans_ptr.p->m_op.m_obj_id));
14799 
14800     CreateFilegroupConf * conf = (CreateFilegroupConf*)signal->getDataPtr();
14801     conf->senderRef = reference();
14802     conf->senderData = trans_ptr.p->m_senderData;
14803     conf->filegroupId = fg_ptr.p->key;
14804     conf->filegroupVersion = fg_ptr.p->m_version;
14805 
14806     //@todo check api failed
14807     sendSignal(trans_ptr.p->m_senderRef, GSN_CREATE_FILEGROUP_CONF, signal,
14808 	       CreateFilegroupConf::SignalLength, JBB);
14809     break;
14810   }
14811   case GSN_CREATE_FILE_REQ:{
14812     FilePtr f_ptr;
14813     jam();
14814     ndbrequire(c_file_hash.find(f_ptr, trans_ptr.p->m_op.m_obj_id));
14815     CreateFileConf * conf = (CreateFileConf*)signal->getDataPtr();
14816     conf->senderRef = reference();
14817     conf->senderData = trans_ptr.p->m_senderData;
14818     conf->fileId = f_ptr.p->key;
14819     conf->fileVersion = f_ptr.p->m_version;
14820 
14821     //@todo check api failed
14822     sendSignal(trans_ptr.p->m_senderRef, GSN_CREATE_FILE_CONF, signal,
14823 	       CreateFileConf::SignalLength, JBB);
14824     break;
14825   }
14826   case GSN_DROP_FILE_REQ:{
14827     DropFileConf * conf = (DropFileConf*)signal->getDataPtr();
14828     jam();
14829     conf->senderRef = reference();
14830     conf->senderData = trans_ptr.p->m_senderData;
14831     conf->fileId = trans_ptr.p->m_op.m_obj_id;
14832 
14833     //@todo check api failed
14834     sendSignal(trans_ptr.p->m_senderRef, GSN_DROP_FILE_CONF, signal,
14835 	       DropFileConf::SignalLength, JBB);
14836     break;
14837   }
14838   case GSN_DROP_FILEGROUP_REQ:{
14839     DropFilegroupConf * conf = (DropFilegroupConf*)signal->getDataPtr();
14840     jam();
14841     conf->senderRef = reference();
14842     conf->senderData = trans_ptr.p->m_senderData;
14843     conf->filegroupId = trans_ptr.p->m_op.m_obj_id;
14844 
14845     //@todo check api failed
14846     sendSignal(trans_ptr.p->m_senderRef, GSN_DROP_FILEGROUP_CONF, signal,
14847 	       DropFilegroupConf::SignalLength, JBB);
14848     break;
14849   }
14850   default:
14851     ndbrequire(false);
14852   }
14853 
14854   c_Trans.release(trans_ptr);
14855   ndbrequire(c_blockState == BS_CREATE_TAB);
14856   c_blockState = BS_IDLE;
14857   return;
14858 }
14859 
14860 void
trans_abort_start_done(Signal * signal,Uint32 callbackData,Uint32 retValue)14861 Dbdict::trans_abort_start_done(Signal* signal,
14862 			       Uint32 callbackData,
14863 			       Uint32 retValue)
14864 {
14865   Ptr<SchemaTransaction> trans_ptr;
14866 
14867   jam();
14868   ndbrequire(retValue == 0);
14869   ndbrequire(c_Trans.find(trans_ptr, callbackData));
14870 
14871   NodeReceiverGroup rg(DBDICT, trans_ptr.p->m_nodes);
14872   SafeCounter tmp(c_counterMgr, trans_ptr.p->m_counter);
14873   ndbrequire(tmp.init<DictAbortRef>(rg, trans_ptr.p->key));
14874 
14875   DictAbortReq * const req = (DictAbortReq*)signal->getDataPtrSend();
14876   req->senderRef = reference();
14877   req->senderData = trans_ptr.p->key;
14878   req->op_key = trans_ptr.p->m_op.m_key;
14879 
14880   sendSignal(rg, GSN_DICT_ABORT_REQ, signal, DictAbortReq::SignalLength, JBB);
14881 }
14882 
14883 void
trans_abort_complete_done(Signal * signal,Uint32 callbackData,Uint32 retValue)14884 Dbdict::trans_abort_complete_done(Signal* signal,
14885 				  Uint32 callbackData,
14886 				  Uint32 retValue)
14887 {
14888   Ptr<SchemaTransaction> trans_ptr;
14889 
14890   jam();
14891   ndbrequire(retValue == 0);
14892   ndbrequire(c_Trans.find(trans_ptr, callbackData));
14893 
14894   switch(f_dict_op[trans_ptr.p->m_op.m_vt_index].m_gsn_user_req){
14895   case GSN_CREATE_FILEGROUP_REQ:
14896   {
14897     //
14898     CreateFilegroupRef * ref = (CreateFilegroupRef*)signal->getDataPtr();
14899     jam();
14900     ref->senderRef = reference();
14901     ref->senderData = trans_ptr.p->m_senderData;
14902     ref->masterNodeId = c_masterNodeId;
14903     ref->errorCode = trans_ptr.p->m_errorCode;
14904     ref->errorLine = 0;
14905     ref->errorKey = 0;
14906     ref->status = 0;
14907 
14908     //@todo check api failed
14909     sendSignal(trans_ptr.p->m_senderRef, GSN_CREATE_FILEGROUP_REF, signal,
14910 	       CreateFilegroupRef::SignalLength, JBB);
14911     break;
14912   }
14913   case GSN_CREATE_FILE_REQ:
14914   {
14915     CreateFileRef * ref = (CreateFileRef*)signal->getDataPtr();
14916     jam();
14917     ref->senderRef = reference();
14918     ref->senderData = trans_ptr.p->m_senderData;
14919     ref->masterNodeId = c_masterNodeId;
14920     ref->errorCode = trans_ptr.p->m_errorCode;
14921     ref->errorLine = 0;
14922     ref->errorKey = 0;
14923     ref->status = 0;
14924 
14925     //@todo check api failed
14926     sendSignal(trans_ptr.p->m_senderRef, GSN_CREATE_FILE_REF, signal,
14927 	       CreateFileRef::SignalLength, JBB);
14928     break;
14929   }
14930   case GSN_DROP_FILE_REQ:
14931   {
14932     DropFileRef * ref = (DropFileRef*)signal->getDataPtr();
14933     jam();
14934     ref->senderRef = reference();
14935     ref->senderData = trans_ptr.p->m_senderData;
14936     ref->masterNodeId = c_masterNodeId;
14937     ref->errorCode = trans_ptr.p->m_errorCode;
14938     ref->errorLine = 0;
14939     ref->errorKey = 0;
14940 
14941     //@todo check api failed
14942     sendSignal(trans_ptr.p->m_senderRef, GSN_DROP_FILE_REF, signal,
14943 	       DropFileRef::SignalLength, JBB);
14944     break;
14945   }
14946   case GSN_DROP_FILEGROUP_REQ:
14947   {
14948     //
14949     DropFilegroupRef * ref = (DropFilegroupRef*)signal->getDataPtr();
14950     jam();
14951     ref->senderRef = reference();
14952     ref->senderData = trans_ptr.p->m_senderData;
14953     ref->masterNodeId = c_masterNodeId;
14954     ref->errorCode = trans_ptr.p->m_errorCode;
14955     ref->errorLine = 0;
14956     ref->errorKey = 0;
14957 
14958     //@todo check api failed
14959     sendSignal(trans_ptr.p->m_senderRef, GSN_DROP_FILEGROUP_REF, signal,
14960 	       DropFilegroupRef::SignalLength, JBB);
14961     break;
14962   }
14963   default:
14964     ndbrequire(false);
14965   }
14966 
14967   c_Trans.release(trans_ptr);
14968   ndbrequire(c_blockState == BS_CREATE_TAB);
14969   c_blockState = BS_IDLE;
14970   return;
14971 }
14972 
14973 void
execCREATE_OBJ_REQ(Signal * signal)14974 Dbdict::execCREATE_OBJ_REQ(Signal* signal)
14975 {
14976   jamEntry();
14977 
14978   if(!assembleFragments(signal)){
14979     jam();
14980     return;
14981   }
14982 
14983   CreateObjReq * const req = (CreateObjReq*)signal->getDataPtr();
14984   const Uint32 gci = req->gci;
14985   const Uint32 objId = req->objId;
14986   const Uint32 objVersion = req->objVersion;
14987   const Uint32 objType = req->objType;
14988   const Uint32 requestInfo = req->requestInfo;
14989 
14990   SegmentedSectionPtr objInfoPtr;
14991   signal->getSection(objInfoPtr, CreateObjReq::DICT_OBJ_INFO);
14992 
14993   CreateObjRecordPtr createObjPtr;
14994   ndbrequire(c_opCreateObj.seize(createObjPtr));
14995 
14996   const Uint32 key = req->op_key;
14997   createObjPtr.p->key = key;
14998   c_opCreateObj.add(createObjPtr);
14999   createObjPtr.p->m_errorCode = 0;
15000   createObjPtr.p->m_senderRef = req->senderRef;
15001   createObjPtr.p->m_senderData = req->senderData;
15002   createObjPtr.p->m_clientRef = req->clientRef;
15003   createObjPtr.p->m_clientData = req->clientData;
15004 
15005   createObjPtr.p->m_gci = gci;
15006   createObjPtr.p->m_obj_id = objId;
15007   createObjPtr.p->m_obj_type = objType;
15008   createObjPtr.p->m_obj_version = objVersion;
15009   createObjPtr.p->m_obj_info_ptr_i = objInfoPtr.i;
15010   createObjPtr.p->m_obj_ptr_i = RNIL;
15011 
15012   createObjPtr.p->m_callback.m_callbackData = key;
15013   createObjPtr.p->m_callback.m_callbackFunction=
15014     safe_cast(&Dbdict::createObj_prepare_start_done);
15015 
15016   createObjPtr.p->m_restart= 0;
15017   switch(objType){
15018   case DictTabInfo::Tablespace:
15019   case DictTabInfo::LogfileGroup:
15020     jam();
15021     createObjPtr.p->m_vt_index = 0;
15022     break;
15023   case DictTabInfo::Datafile:
15024   case DictTabInfo::Undofile:
15025     /**
15026      * Use restart code to impl. ForceCreateFile
15027      */
15028     if (requestInfo & CreateFileReq::ForceCreateFile)
15029     {
15030       jam();
15031       createObjPtr.p->m_restart= 2;
15032     }
15033     jam();
15034     createObjPtr.p->m_vt_index = 1;
15035     break;
15036   default:
15037     ndbrequire(false);
15038   }
15039 
15040   signal->header.m_noOfSections = 0;
15041   (this->*f_dict_op[createObjPtr.p->m_vt_index].m_prepare_start)
15042     (signal, createObjPtr.p);
15043 }
15044 
15045 void
execDICT_COMMIT_REQ(Signal * signal)15046 Dbdict::execDICT_COMMIT_REQ(Signal* signal)
15047 {
15048   DictCommitReq* req = (DictCommitReq*)signal->getDataPtr();
15049   Ptr<SchemaOp> op;
15050 
15051   jamEntry();
15052   ndbrequire(c_schemaOp.find(op, req->op_key));
15053   (this->*f_dict_op[op.p->m_vt_index].m_commit)(signal, op.p);
15054 }
15055 
15056 void
execDICT_ABORT_REQ(Signal * signal)15057 Dbdict::execDICT_ABORT_REQ(Signal* signal)
15058 {
15059   DictAbortReq* req = (DictAbortReq*)signal->getDataPtr();
15060   Ptr<SchemaOp> op;
15061 
15062   jamEntry();
15063   ndbrequire(c_schemaOp.find(op, req->op_key));
15064   (this->*f_dict_op[op.p->m_vt_index].m_abort)(signal, op.p);
15065 }
15066 
15067 void
execDICT_COMMIT_REF(Signal * signal)15068 Dbdict::execDICT_COMMIT_REF(Signal* signal)
15069 {
15070   DictCommitRef * const ref = (DictCommitRef*)signal->getDataPtr();
15071   Ptr<SchemaTransaction> trans_ptr;
15072 
15073   jamEntry();
15074   ndbrequire(c_Trans.find(trans_ptr, ref->senderData));
15075   if(ref->errorCode != DictCommitRef::NF_FakeErrorREF){
15076     jam();
15077     trans_ptr.p->setErrorCode(ref->errorCode);
15078   }
15079   Uint32 node = refToNode(ref->senderRef);
15080   schemaOp_reply(signal, trans_ptr.p, node);
15081 }
15082 
15083 void
execDICT_COMMIT_CONF(Signal * signal)15084 Dbdict::execDICT_COMMIT_CONF(Signal* signal)
15085 {
15086   Ptr<SchemaTransaction> trans_ptr;
15087   DictCommitConf * const conf = (DictCommitConf*)signal->getDataPtr();
15088 
15089   jamEntry();
15090   ndbrequire(c_Trans.find(trans_ptr, conf->senderData));
15091   schemaOp_reply(signal, trans_ptr.p, refToNode(conf->senderRef));
15092 }
15093 
15094 void
execDICT_ABORT_REF(Signal * signal)15095 Dbdict::execDICT_ABORT_REF(Signal* signal)
15096 {
15097   DictAbortRef * const ref = (DictAbortRef*)signal->getDataPtr();
15098   Ptr<SchemaTransaction> trans_ptr;
15099 
15100   jamEntry();
15101   ndbrequire(c_Trans.find(trans_ptr, ref->senderData));
15102   if(ref->errorCode != DictAbortRef::NF_FakeErrorREF){
15103     jam();
15104     trans_ptr.p->setErrorCode(ref->errorCode);
15105   }
15106   Uint32 node = refToNode(ref->senderRef);
15107   schemaOp_reply(signal, trans_ptr.p, node);
15108 }
15109 
15110 void
execDICT_ABORT_CONF(Signal * signal)15111 Dbdict::execDICT_ABORT_CONF(Signal* signal)
15112 {
15113   DictAbortConf * const conf = (DictAbortConf*)signal->getDataPtr();
15114   Ptr<SchemaTransaction> trans_ptr;
15115 
15116   jamEntry();
15117   ndbrequire(c_Trans.find(trans_ptr, conf->senderData));
15118   schemaOp_reply(signal, trans_ptr.p, refToNode(conf->senderRef));
15119 }
15120 
15121 void
createObj_prepare_start_done(Signal * signal,Uint32 callbackData,Uint32 returnCode)15122 Dbdict::createObj_prepare_start_done(Signal* signal,
15123 				     Uint32 callbackData,
15124 				     Uint32 returnCode)
15125 {
15126   CreateObjRecordPtr createObjPtr;
15127   SegmentedSectionPtr objInfoPtr;
15128 
15129   ndbrequire(returnCode == 0);
15130   ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
15131   jam();
15132   getSection(objInfoPtr, createObjPtr.p->m_obj_info_ptr_i);
15133   if(createObjPtr.p->m_errorCode != 0){
15134     jam();
15135     createObjPtr.p->m_obj_info_ptr_i= RNIL;
15136     signal->setSection(objInfoPtr, 0);
15137     releaseSections(signal);
15138     createObj_prepare_complete_done(signal, callbackData, 0);
15139     return;
15140   }
15141 
15142   SchemaFile::TableEntry tabEntry;
15143   bzero(&tabEntry, sizeof(tabEntry));
15144   tabEntry.m_tableVersion = createObjPtr.p->m_obj_version;
15145   tabEntry.m_tableType    = createObjPtr.p->m_obj_type;
15146   tabEntry.m_tableState   = SchemaFile::ADD_STARTED;
15147   tabEntry.m_gcp          = createObjPtr.p->m_gci;
15148   tabEntry.m_info_words   = objInfoPtr.sz;
15149 
15150   Callback cb;
15151   cb.m_callbackData = createObjPtr.p->key;
15152   cb.m_callbackFunction = safe_cast(&Dbdict::createObj_writeSchemaConf1);
15153 
15154   updateSchemaState(signal, createObjPtr.p->m_obj_id, &tabEntry, &cb);
15155 }
15156 
15157 void
createObj_writeSchemaConf1(Signal * signal,Uint32 callbackData,Uint32 returnCode)15158 Dbdict::createObj_writeSchemaConf1(Signal* signal,
15159 				   Uint32 callbackData,
15160 				   Uint32 returnCode)
15161 {
15162   CreateObjRecordPtr createObjPtr;
15163   Callback callback;
15164   SegmentedSectionPtr objInfoPtr;
15165 
15166   jam();
15167   ndbrequire(returnCode == 0);
15168   ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
15169 
15170   callback.m_callbackData = createObjPtr.p->key;
15171   callback.m_callbackFunction = safe_cast(&Dbdict::createObj_writeObjConf);
15172 
15173   getSection(objInfoPtr, createObjPtr.p->m_obj_info_ptr_i);
15174   writeTableFile(signal, createObjPtr.p->m_obj_id, objInfoPtr, &callback);
15175 
15176   signal->setSection(objInfoPtr, 0);
15177   releaseSections(signal);
15178   createObjPtr.p->m_obj_info_ptr_i = RNIL;
15179 }
15180 
15181 void
createObj_writeObjConf(Signal * signal,Uint32 callbackData,Uint32 returnCode)15182 Dbdict::createObj_writeObjConf(Signal* signal,
15183 			       Uint32 callbackData,
15184 			       Uint32 returnCode)
15185 {
15186   CreateObjRecordPtr createObjPtr;
15187 
15188   jam();
15189   ndbrequire(returnCode == 0);
15190   ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
15191   createObjPtr.p->m_callback.m_callbackFunction =
15192     safe_cast(&Dbdict::createObj_prepare_complete_done);
15193   (this->*f_dict_op[createObjPtr.p->m_vt_index].m_prepare_complete)
15194     (signal, createObjPtr.p);
15195 }
15196 
15197 void
createObj_prepare_complete_done(Signal * signal,Uint32 callbackData,Uint32 returnCode)15198 Dbdict::createObj_prepare_complete_done(Signal* signal,
15199 					Uint32 callbackData,
15200 					Uint32 returnCode)
15201 {
15202   CreateObjRecordPtr createObjPtr;
15203 
15204   jam();
15205   ndbrequire(returnCode == 0);
15206   ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
15207 
15208   //@todo check for master failed
15209 
15210   if(createObjPtr.p->m_errorCode == 0){
15211     jam();
15212 
15213     CreateObjConf * const conf = (CreateObjConf*)signal->getDataPtr();
15214     conf->senderRef = reference();
15215     conf->senderData = createObjPtr.p->m_senderData;
15216     sendSignal(createObjPtr.p->m_senderRef, GSN_CREATE_OBJ_CONF,
15217 	       signal, CreateObjConf::SignalLength, JBB);
15218     return;
15219   }
15220 
15221   CreateObjRef * const ref = (CreateObjRef*)signal->getDataPtr();
15222   ref->senderRef = reference();
15223   ref->senderData = createObjPtr.p->m_senderData;
15224   ref->errorCode = createObjPtr.p->m_errorCode;
15225   ref->errorLine = 0;
15226   ref->errorKey = 0;
15227   ref->errorStatus = 0;
15228 
15229   sendSignal(createObjPtr.p->m_senderRef, GSN_CREATE_OBJ_REF,
15230 	     signal, CreateObjRef::SignalLength, JBB);
15231 }
15232 
15233 void
createObj_commit(Signal * signal,SchemaOp * op)15234 Dbdict::createObj_commit(Signal * signal, SchemaOp * op)
15235 {
15236   OpCreateObj * createObj = (OpCreateObj*)op;
15237 
15238   createObj->m_callback.m_callbackFunction =
15239     safe_cast(&Dbdict::createObj_commit_start_done);
15240   if (f_dict_op[createObj->m_vt_index].m_commit_start)
15241   {
15242     jam();
15243     (this->*f_dict_op[createObj->m_vt_index].m_commit_start)(signal, createObj);
15244   }
15245   else
15246   {
15247     jam();
15248     execute(signal, createObj->m_callback, 0);
15249   }
15250 }
15251 
15252 void
createObj_commit_start_done(Signal * signal,Uint32 callbackData,Uint32 returnCode)15253 Dbdict::createObj_commit_start_done(Signal* signal,
15254 				    Uint32 callbackData,
15255 				    Uint32 returnCode)
15256 {
15257   CreateObjRecordPtr createObjPtr;
15258 
15259   jam();
15260   ndbrequire(returnCode == 0);
15261   ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
15262 
15263   Uint32 objId = createObjPtr.p->m_obj_id;
15264   XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
15265   SchemaFile::TableEntry objEntry = * getTableEntry(xsf, objId);
15266   objEntry.m_tableState = SchemaFile::TABLE_ADD_COMMITTED;
15267 
15268   Callback callback;
15269   callback.m_callbackData = createObjPtr.p->key;
15270   callback.m_callbackFunction =
15271     safe_cast(&Dbdict::createObj_writeSchemaConf2);
15272 
15273   updateSchemaState(signal, createObjPtr.p->m_obj_id, &objEntry, &callback);
15274 
15275 }
15276 
15277 void
createObj_writeSchemaConf2(Signal * signal,Uint32 callbackData,Uint32 returnCode)15278 Dbdict::createObj_writeSchemaConf2(Signal* signal,
15279 				   Uint32 callbackData,
15280 				   Uint32 returnCode)
15281 {
15282   CreateObjRecordPtr createObjPtr;
15283 
15284   ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
15285   createObjPtr.p->m_callback.m_callbackFunction =
15286     safe_cast(&Dbdict::createObj_commit_complete_done);
15287   if (f_dict_op[createObjPtr.p->m_vt_index].m_commit_complete)
15288   {
15289     jam();
15290     (this->*f_dict_op[createObjPtr.p->m_vt_index].m_commit_complete)
15291       (signal, createObjPtr.p);
15292   }
15293   else
15294   {
15295     jam();
15296     execute(signal, createObjPtr.p->m_callback, 0);
15297   }
15298 
15299 }
15300 
15301 void
createObj_commit_complete_done(Signal * signal,Uint32 callbackData,Uint32 returnCode)15302 Dbdict::createObj_commit_complete_done(Signal* signal,
15303 				       Uint32 callbackData,
15304 				       Uint32 returnCode)
15305 {
15306   CreateObjRecordPtr createObjPtr;
15307 
15308   jam();
15309   ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
15310 
15311   //@todo check error
15312   //@todo check master failed
15313 
15314   DictCommitConf * const conf = (DictCommitConf*)signal->getDataPtr();
15315   conf->senderRef = reference();
15316   conf->senderData = createObjPtr.p->m_senderData;
15317   sendSignal(createObjPtr.p->m_senderRef, GSN_DICT_COMMIT_CONF,
15318 	     signal, DictCommitConf::SignalLength, JBB);
15319 
15320   c_opCreateObj.release(createObjPtr);
15321 }
15322 
15323 void
createObj_abort(Signal * signal,SchemaOp * op)15324 Dbdict::createObj_abort(Signal* signal, SchemaOp* op)
15325 {
15326   OpCreateObj * createObj = (OpCreateObj*)op;
15327 
15328   createObj->m_callback.m_callbackFunction =
15329     safe_cast(&Dbdict::createObj_abort_start_done);
15330   if (f_dict_op[createObj->m_vt_index].m_abort_start)
15331   {
15332     jam();
15333     (this->*f_dict_op[createObj->m_vt_index].m_abort_start)(signal, createObj);
15334   }
15335   else
15336   {
15337     jam();
15338     execute(signal, createObj->m_callback, 0);
15339   }
15340 }
15341 
15342 void
createObj_abort_start_done(Signal * signal,Uint32 callbackData,Uint32 returnCode)15343 Dbdict::createObj_abort_start_done(Signal* signal,
15344 				   Uint32 callbackData,
15345 				   Uint32 returnCode)
15346 {
15347   CreateObjRecordPtr createObjPtr;
15348 
15349   jam();
15350   ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
15351   XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
15352   SchemaFile::TableEntry objEntry = * getTableEntry(xsf,
15353 						    createObjPtr.p->m_obj_id);
15354   objEntry.m_tableState = SchemaFile::DROP_TABLE_COMMITTED;
15355 
15356   Callback callback;
15357   callback.m_callbackData = createObjPtr.p->key;
15358   callback.m_callbackFunction =
15359     safe_cast(&Dbdict::createObj_abort_writeSchemaConf);
15360 
15361   updateSchemaState(signal, createObjPtr.p->m_obj_id, &objEntry, &callback);
15362 }
15363 
15364 void
createObj_abort_writeSchemaConf(Signal * signal,Uint32 callbackData,Uint32 returnCode)15365 Dbdict::createObj_abort_writeSchemaConf(Signal* signal,
15366 					Uint32 callbackData,
15367 					Uint32 returnCode)
15368 {
15369   CreateObjRecordPtr createObjPtr;
15370 
15371   ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
15372   createObjPtr.p->m_callback.m_callbackFunction =
15373     safe_cast(&Dbdict::createObj_abort_complete_done);
15374 
15375   if (f_dict_op[createObjPtr.p->m_vt_index].m_abort_complete)
15376   {
15377     jam();
15378     (this->*f_dict_op[createObjPtr.p->m_vt_index].m_abort_complete)
15379       (signal, createObjPtr.p);
15380   }
15381   else
15382   {
15383     jam();
15384     execute(signal, createObjPtr.p->m_callback, 0);
15385   }
15386 }
15387 
15388 void
createObj_abort_complete_done(Signal * signal,Uint32 callbackData,Uint32 returnCode)15389 Dbdict::createObj_abort_complete_done(Signal* signal,
15390 				      Uint32 callbackData,
15391 				      Uint32 returnCode)
15392 {
15393   CreateObjRecordPtr createObjPtr;
15394 
15395   jam();
15396   ndbrequire(c_opCreateObj.find(createObjPtr, callbackData));
15397 
15398   DictAbortConf * const conf = (DictAbortConf*)signal->getDataPtr();
15399   conf->senderRef = reference();
15400   conf->senderData = createObjPtr.p->m_senderData;
15401   sendSignal(createObjPtr.p->m_senderRef, GSN_DICT_ABORT_CONF,
15402 	     signal, DictAbortConf::SignalLength, JBB);
15403 
15404   c_opCreateObj.release(createObjPtr);
15405 }
15406 
15407 void
execDROP_OBJ_REQ(Signal * signal)15408 Dbdict::execDROP_OBJ_REQ(Signal* signal)
15409 {
15410   jamEntry();
15411 
15412   if(!assembleFragments(signal)){
15413     jam();
15414     return;
15415   }
15416 
15417   DropObjReq * const req = (DropObjReq*)signal->getDataPtr();
15418 
15419   const Uint32 objId = req->objId;
15420   const Uint32 objVersion = req->objVersion;
15421   const Uint32 objType = req->objType;
15422 
15423   DropObjRecordPtr dropObjPtr;
15424   ndbrequire(c_opDropObj.seize(dropObjPtr));
15425 
15426   const Uint32 key = req->op_key;
15427   dropObjPtr.p->key = key;
15428   c_opDropObj.add(dropObjPtr);
15429   dropObjPtr.p->m_errorCode = 0;
15430   dropObjPtr.p->m_senderRef = req->senderRef;
15431   dropObjPtr.p->m_senderData = req->senderData;
15432   dropObjPtr.p->m_clientRef = req->clientRef;
15433   dropObjPtr.p->m_clientData = req->clientData;
15434 
15435   dropObjPtr.p->m_obj_id = objId;
15436   dropObjPtr.p->m_obj_type = objType;
15437   dropObjPtr.p->m_obj_version = objVersion;
15438 
15439   dropObjPtr.p->m_callback.m_callbackData = key;
15440   dropObjPtr.p->m_callback.m_callbackFunction=
15441     safe_cast(&Dbdict::dropObj_prepare_start_done);
15442 
15443   switch(objType){
15444   case DictTabInfo::Tablespace:
15445   case DictTabInfo::LogfileGroup:
15446   {
15447     Ptr<Filegroup> fg_ptr;
15448     jam();
15449     dropObjPtr.p->m_vt_index = 3;
15450     ndbrequire(c_filegroup_hash.find(fg_ptr, objId));
15451     dropObjPtr.p->m_obj_ptr_i = fg_ptr.i;
15452     break;
15453 
15454   }
15455   case DictTabInfo::Datafile:
15456   {
15457     Ptr<File> file_ptr;
15458     jam();
15459     dropObjPtr.p->m_vt_index = 2;
15460     ndbrequire(c_file_hash.find(file_ptr, objId));
15461     dropObjPtr.p->m_obj_ptr_i = file_ptr.i;
15462     break;
15463   }
15464   case DictTabInfo::Undofile:
15465   {
15466     jam();
15467     dropObjPtr.p->m_vt_index = 4;
15468     return;
15469   }
15470   default:
15471     ndbrequire(false);
15472   }
15473 
15474   signal->header.m_noOfSections = 0;
15475   (this->*f_dict_op[dropObjPtr.p->m_vt_index].m_prepare_start)
15476     (signal, dropObjPtr.p);
15477 }
15478 
15479 void
dropObj_prepare_start_done(Signal * signal,Uint32 callbackData,Uint32 returnCode)15480 Dbdict::dropObj_prepare_start_done(Signal* signal,
15481 				   Uint32 callbackData,
15482 				   Uint32 returnCode)
15483 {
15484   DropObjRecordPtr dropObjPtr;
15485   Callback cb;
15486 
15487   ndbrequire(returnCode == 0);
15488   ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
15489 
15490   cb.m_callbackData = callbackData;
15491   cb.m_callbackFunction =
15492     safe_cast(&Dbdict::dropObj_prepare_writeSchemaConf);
15493 
15494   if(dropObjPtr.p->m_errorCode != 0)
15495   {
15496     jam();
15497     dropObj_prepare_complete_done(signal, callbackData, 0);
15498     return;
15499   }
15500   jam();
15501   Uint32 objId = dropObjPtr.p->m_obj_id;
15502   XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
15503   SchemaFile::TableEntry objEntry = *getTableEntry(xsf, objId);
15504   objEntry.m_tableState = SchemaFile::DROP_TABLE_STARTED;
15505   updateSchemaState(signal, objId, &objEntry, &cb);
15506 }
15507 
15508 void
dropObj_prepare_writeSchemaConf(Signal * signal,Uint32 callbackData,Uint32 returnCode)15509 Dbdict::dropObj_prepare_writeSchemaConf(Signal* signal,
15510 					Uint32 callbackData,
15511 					Uint32 returnCode)
15512 {
15513   DropObjRecordPtr dropObjPtr;
15514 
15515   ndbrequire(returnCode == 0);
15516   ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
15517   dropObjPtr.p->m_callback.m_callbackFunction =
15518     safe_cast(&Dbdict::dropObj_prepare_complete_done);
15519   if(f_dict_op[dropObjPtr.p->m_vt_index].m_prepare_complete)
15520   {
15521     jam();
15522     (this->*f_dict_op[dropObjPtr.p->m_vt_index].m_prepare_complete)
15523       (signal, dropObjPtr.p);
15524   }
15525   else
15526   {
15527     jam();
15528     execute(signal, dropObjPtr.p->m_callback, 0);
15529   }
15530 }
15531 
15532 void
dropObj_prepare_complete_done(Signal * signal,Uint32 callbackData,Uint32 returnCode)15533 Dbdict::dropObj_prepare_complete_done(Signal* signal,
15534 				      Uint32 callbackData,
15535 				      Uint32 returnCode)
15536 {
15537   DropObjRecordPtr dropObjPtr;
15538 
15539   ndbrequire(returnCode == 0);
15540   ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
15541   jam();
15542 
15543   //@todo check for master failed
15544 
15545   if(dropObjPtr.p->m_errorCode == 0){
15546     jam();
15547 
15548     DropObjConf * const conf = (DropObjConf*)signal->getDataPtr();
15549     conf->senderRef = reference();
15550     conf->senderData = dropObjPtr.p->m_senderData;
15551     sendSignal(dropObjPtr.p->m_senderRef, GSN_DROP_OBJ_CONF,
15552 	       signal, DropObjConf::SignalLength, JBB);
15553     return;
15554   }
15555 
15556   DropObjRef * const ref = (DropObjRef*)signal->getDataPtr();
15557   ref->senderRef = reference();
15558   ref->senderData = dropObjPtr.p->m_senderData;
15559   ref->errorCode = dropObjPtr.p->m_errorCode;
15560 
15561   sendSignal(dropObjPtr.p->m_senderRef, GSN_DROP_OBJ_REF,
15562 	     signal, DropObjRef::SignalLength, JBB);
15563 
15564 }
15565 
15566 void
dropObj_commit(Signal * signal,SchemaOp * op)15567 Dbdict::dropObj_commit(Signal * signal, SchemaOp * op)
15568 {
15569   OpDropObj * dropObj = (OpDropObj*)op;
15570 
15571   dropObj->m_callback.m_callbackFunction =
15572     safe_cast(&Dbdict::dropObj_commit_start_done);
15573   if (f_dict_op[dropObj->m_vt_index].m_commit_start)
15574   {
15575     jam();
15576     (this->*f_dict_op[dropObj->m_vt_index].m_commit_start)(signal, dropObj);
15577   }
15578   else
15579   {
15580     jam();
15581     execute(signal, dropObj->m_callback, 0);
15582   }
15583 }
15584 
15585 void
dropObj_commit_start_done(Signal * signal,Uint32 callbackData,Uint32 returnCode)15586 Dbdict::dropObj_commit_start_done(Signal* signal,
15587 				  Uint32 callbackData,
15588 				  Uint32 returnCode)
15589 {
15590   DropObjRecordPtr dropObjPtr;
15591 
15592   jam();
15593   ndbrequire(returnCode == 0);
15594   ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
15595 
15596   Uint32 objId = dropObjPtr.p->m_obj_id;
15597   XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
15598   SchemaFile::TableEntry objEntry = * getTableEntry(xsf, objId);
15599   objEntry.m_tableState = SchemaFile::DROP_TABLE_COMMITTED;
15600 
15601   Callback callback;
15602   callback.m_callbackData = dropObjPtr.p->key;
15603   callback.m_callbackFunction =
15604     safe_cast(&Dbdict::dropObj_commit_writeSchemaConf);
15605 
15606   updateSchemaState(signal, objId, &objEntry, &callback);
15607 }
15608 
15609 void
dropObj_commit_writeSchemaConf(Signal * signal,Uint32 callbackData,Uint32 returnCode)15610 Dbdict::dropObj_commit_writeSchemaConf(Signal* signal,
15611 				       Uint32 callbackData,
15612 				       Uint32 returnCode)
15613 {
15614   DropObjRecordPtr dropObjPtr;
15615 
15616   jam();
15617   ndbrequire(returnCode == 0);
15618   ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
15619   dropObjPtr.p->m_callback.m_callbackFunction =
15620     safe_cast(&Dbdict::dropObj_commit_complete_done);
15621 
15622   if(f_dict_op[dropObjPtr.p->m_vt_index].m_commit_complete)
15623   {
15624     jam();
15625     (this->*f_dict_op[dropObjPtr.p->m_vt_index].m_commit_complete)
15626       (signal, dropObjPtr.p);
15627   }
15628   else
15629   {
15630     jam();
15631     execute(signal, dropObjPtr.p->m_callback, 0);
15632   }
15633 }
15634 
15635 void
dropObj_commit_complete_done(Signal * signal,Uint32 callbackData,Uint32 returnCode)15636 Dbdict::dropObj_commit_complete_done(Signal* signal,
15637 				     Uint32 callbackData,
15638 				     Uint32 returnCode)
15639 {
15640   DropObjRecordPtr dropObjPtr;
15641 
15642   jam();
15643   ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
15644 
15645   //@todo check error
15646   //@todo check master failed
15647 
15648   DictCommitConf * const conf = (DictCommitConf*)signal->getDataPtr();
15649   conf->senderRef = reference();
15650   conf->senderData = dropObjPtr.p->m_senderData;
15651   sendSignal(dropObjPtr.p->m_senderRef, GSN_DICT_COMMIT_CONF,
15652 	     signal, DictCommitConf::SignalLength, JBB);
15653   c_opDropObj.release(dropObjPtr);
15654 }
15655 
15656 void
dropObj_abort(Signal * signal,SchemaOp * op)15657 Dbdict::dropObj_abort(Signal * signal, SchemaOp * op)
15658 {
15659   OpDropObj * dropObj = (OpDropObj*)op;
15660 
15661   dropObj->m_callback.m_callbackFunction =
15662     safe_cast(&Dbdict::dropObj_abort_start_done);
15663   if (f_dict_op[dropObj->m_vt_index].m_abort_start)
15664   {
15665     jam();
15666     (this->*f_dict_op[dropObj->m_vt_index].m_abort_start)(signal, dropObj);
15667   }
15668   else
15669   {
15670     jam();
15671     execute(signal, dropObj->m_callback, 0);
15672   }
15673 }
15674 
15675 void
dropObj_abort_start_done(Signal * signal,Uint32 callbackData,Uint32 returnCode)15676 Dbdict::dropObj_abort_start_done(Signal* signal,
15677 				 Uint32 callbackData,
15678 				 Uint32 returnCode)
15679 {
15680   DropObjRecordPtr dropObjPtr;
15681 
15682   jam();
15683   ndbrequire(returnCode == 0);
15684   ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
15685 
15686   XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
15687   SchemaFile::TableEntry objEntry = * getTableEntry(xsf,
15688 						    dropObjPtr.p->m_obj_id);
15689 
15690   Callback callback;
15691   callback.m_callbackData = dropObjPtr.p->key;
15692   callback.m_callbackFunction =
15693     safe_cast(&Dbdict::dropObj_abort_writeSchemaConf);
15694 
15695   if (objEntry.m_tableState == SchemaFile::DROP_TABLE_STARTED)
15696   {
15697     jam();
15698     objEntry.m_tableState = SchemaFile::TABLE_ADD_COMMITTED;
15699 
15700     updateSchemaState(signal, dropObjPtr.p->m_obj_id, &objEntry, &callback);
15701   }
15702   else
15703   {
15704     jam();
15705     execute(signal, callback, 0);
15706   }
15707 }
15708 
15709 void
dropObj_abort_writeSchemaConf(Signal * signal,Uint32 callbackData,Uint32 returnCode)15710 Dbdict::dropObj_abort_writeSchemaConf(Signal* signal,
15711 				      Uint32 callbackData,
15712 				      Uint32 returnCode)
15713 {
15714   DropObjRecordPtr dropObjPtr;
15715 
15716   ndbrequire(returnCode == 0);
15717   ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
15718   dropObjPtr.p->m_callback.m_callbackFunction =
15719     safe_cast(&Dbdict::dropObj_abort_complete_done);
15720 
15721   if(f_dict_op[dropObjPtr.p->m_vt_index].m_abort_complete)
15722   {
15723     jam();
15724     (this->*f_dict_op[dropObjPtr.p->m_vt_index].m_abort_complete)
15725       (signal, dropObjPtr.p);
15726   }
15727   else
15728   {
15729     jam();
15730     execute(signal, dropObjPtr.p->m_callback, 0);
15731   }
15732 }
15733 
15734 void
dropObj_abort_complete_done(Signal * signal,Uint32 callbackData,Uint32 returnCode)15735 Dbdict::dropObj_abort_complete_done(Signal* signal,
15736 				    Uint32 callbackData,
15737 				    Uint32 returnCode)
15738 {
15739   DropObjRecordPtr dropObjPtr;
15740   DictAbortConf * const conf = (DictAbortConf*)signal->getDataPtr();
15741 
15742   ndbrequire(c_opDropObj.find(dropObjPtr, callbackData));
15743   jam();
15744   conf->senderRef = reference();
15745   conf->senderData = dropObjPtr.p->m_senderData;
15746   sendSignal(dropObjPtr.p->m_senderRef, GSN_DICT_ABORT_CONF,
15747 	     signal, DictAbortConf::SignalLength, JBB);
15748   c_opDropObj.release(dropObjPtr);
15749 }
15750 
15751 void
create_fg_prepare_start(Signal * signal,SchemaOp * op)15752 Dbdict::create_fg_prepare_start(Signal* signal, SchemaOp* op)
15753 {
15754   /**
15755    * Put data into table record
15756    */
15757   SegmentedSectionPtr objInfoPtr;
15758   jam();
15759   getSection(objInfoPtr, ((OpCreateObj*)op)->m_obj_info_ptr_i);
15760   SimplePropertiesSectionReader it(objInfoPtr, getSectionSegmentPool());
15761 
15762   Ptr<DictObject> obj_ptr; obj_ptr.setNull();
15763   FilegroupPtr fg_ptr; fg_ptr.setNull();
15764 
15765   SimpleProperties::UnpackStatus status;
15766   DictFilegroupInfo::Filegroup fg; fg.init();
15767   do {
15768     status = SimpleProperties::unpack(it, &fg,
15769 				      DictFilegroupInfo::Mapping,
15770 				      DictFilegroupInfo::MappingSize,
15771 				      true, true);
15772 
15773     if(status != SimpleProperties::Eof)
15774     {
15775       jam();
15776       op->m_errorCode = CreateTableRef::InvalidFormat;
15777       break;
15778     }
15779 
15780     if(fg.FilegroupType == DictTabInfo::Tablespace)
15781     {
15782       if(!fg.TS_ExtentSize)
15783       {
15784         jam();
15785 	op->m_errorCode = CreateFilegroupRef::InvalidExtentSize;
15786 	break;
15787       }
15788     }
15789     else if(fg.FilegroupType == DictTabInfo::LogfileGroup)
15790     {
15791       /**
15792        * undo_buffer_size can't be less than 96KB in LGMAN block
15793        */
15794       if(fg.LF_UndoBufferSize < 3 * File_formats::NDB_PAGE_SIZE)
15795       {
15796         jam();
15797 	op->m_errorCode = CreateFilegroupRef::InvalidUndoBufferSize;
15798 	break;
15799       }
15800     }
15801 
15802     Uint32 len = strlen(fg.FilegroupName) + 1;
15803     Uint32 hash = Rope::hash(fg.FilegroupName, len);
15804     if(get_object(fg.FilegroupName, len, hash) != 0){
15805       jam();
15806       op->m_errorCode = CreateTableRef::TableAlreadyExist;
15807       break;
15808     }
15809 
15810     if(!c_obj_pool.seize(obj_ptr)){
15811       jam();
15812       op->m_errorCode = CreateTableRef::NoMoreTableRecords;
15813       break;
15814     }
15815 
15816     if(!c_filegroup_pool.seize(fg_ptr)){
15817       jam();
15818       op->m_errorCode = CreateTableRef::NoMoreTableRecords;
15819       break;
15820     }
15821 
15822     new (fg_ptr.p) Filegroup();
15823 
15824     {
15825       Rope name(c_rope_pool, obj_ptr.p->m_name);
15826       if(!name.assign(fg.FilegroupName, len, hash)){
15827         jam();
15828 	op->m_errorCode = CreateTableRef::OutOfStringBuffer;
15829 	break;
15830       }
15831     }
15832 
15833     fg_ptr.p->key = op->m_obj_id;
15834     fg_ptr.p->m_obj_ptr_i = obj_ptr.i;
15835     fg_ptr.p->m_type = fg.FilegroupType;
15836     fg_ptr.p->m_version = op->m_obj_version;
15837     fg_ptr.p->m_name = obj_ptr.p->m_name;
15838 
15839     switch(fg.FilegroupType){
15840     case DictTabInfo::Tablespace:
15841     {
15842       //fg.TS_DataGrow = group.m_grow_spec;
15843       fg_ptr.p->m_tablespace.m_extent_size = fg.TS_ExtentSize;
15844       fg_ptr.p->m_tablespace.m_default_logfile_group_id = fg.TS_LogfileGroupId;
15845 
15846       Ptr<Filegroup> lg_ptr;
15847       if (!c_filegroup_hash.find(lg_ptr, fg.TS_LogfileGroupId))
15848       {
15849         jam();
15850 	op->m_errorCode = CreateFilegroupRef::NoSuchLogfileGroup;
15851 	goto error;
15852       }
15853 
15854       if (lg_ptr.p->m_version != fg.TS_LogfileGroupVersion)
15855       {
15856         jam();
15857 	op->m_errorCode = CreateFilegroupRef::InvalidFilegroupVersion;
15858 	goto error;
15859       }
15860       increase_ref_count(lg_ptr.p->m_obj_ptr_i);
15861       break;
15862     }
15863     case DictTabInfo::LogfileGroup:
15864     {
15865       jam();
15866       fg_ptr.p->m_logfilegroup.m_undo_buffer_size = fg.LF_UndoBufferSize;
15867       fg_ptr.p->m_logfilegroup.m_files.init();
15868       //fg.LF_UndoGrow = ;
15869       break;
15870     }
15871     default:
15872       ndbrequire(false);
15873     }
15874 
15875     obj_ptr.p->m_id = op->m_obj_id;
15876     obj_ptr.p->m_type = fg.FilegroupType;
15877     obj_ptr.p->m_ref_count = 0;
15878     c_obj_hash.add(obj_ptr);
15879     c_filegroup_hash.add(fg_ptr);
15880 
15881     op->m_obj_ptr_i = fg_ptr.i;
15882   } while(0);
15883 
15884 error:
15885   if (op->m_errorCode)
15886   {
15887     jam();
15888     if (!fg_ptr.isNull())
15889     {
15890       jam();
15891       c_filegroup_pool.release(fg_ptr);
15892     }
15893 
15894     if (!obj_ptr.isNull())
15895     {
15896       jam();
15897       c_obj_pool.release(obj_ptr);
15898     }
15899   }
15900 
15901   execute(signal, op->m_callback, 0);
15902 }
15903 
15904 void
create_fg_prepare_complete(Signal * signal,SchemaOp * op)15905 Dbdict::create_fg_prepare_complete(Signal* signal, SchemaOp* op)
15906 {
15907   /**
15908    * CONTACT TSMAN LGMAN PGMAN
15909    */
15910   CreateFilegroupImplReq* req =
15911     (CreateFilegroupImplReq*)signal->getDataPtrSend();
15912   jam();
15913   req->senderData = op->key;
15914   req->senderRef = reference();
15915   req->filegroup_id = op->m_obj_id;
15916   req->filegroup_version = op->m_obj_version;
15917 
15918   FilegroupPtr fg_ptr;
15919   c_filegroup_pool.getPtr(fg_ptr, op->m_obj_ptr_i);
15920 
15921   Uint32 ref= 0;
15922   Uint32 len= 0;
15923   switch(op->m_obj_type){
15924   case DictTabInfo::Tablespace:
15925   {
15926     jam();
15927     ref = TSMAN_REF;
15928     len = CreateFilegroupImplReq::TablespaceLength;
15929     req->tablespace.extent_size = fg_ptr.p->m_tablespace.m_extent_size;
15930     req->tablespace.logfile_group_id =
15931       fg_ptr.p->m_tablespace.m_default_logfile_group_id;
15932     break;
15933   }
15934   case DictTabInfo::LogfileGroup:
15935   {
15936     jam();
15937     ref = LGMAN_REF;
15938     len = CreateFilegroupImplReq::LogfileGroupLength;
15939     req->logfile_group.buffer_size =
15940       fg_ptr.p->m_logfilegroup.m_undo_buffer_size;
15941     break;
15942   }
15943   default:
15944     ndbrequire(false);
15945   }
15946 
15947   sendSignal(ref, GSN_CREATE_FILEGROUP_REQ, signal, len, JBB);
15948 }
15949 
15950 void
execCREATE_FILEGROUP_REF(Signal * signal)15951 Dbdict::execCREATE_FILEGROUP_REF(Signal* signal)
15952 {
15953   CreateFilegroupImplRef * ref = (CreateFilegroupImplRef*)signal->getDataPtr();
15954   CreateObjRecordPtr op_ptr;
15955   jamEntry();
15956   ndbrequire(c_opCreateObj.find(op_ptr, ref->senderData));
15957   op_ptr.p->m_errorCode = ref->errorCode;
15958 
15959   execute(signal, op_ptr.p->m_callback, 0);
15960 }
15961 
15962 void
execCREATE_FILEGROUP_CONF(Signal * signal)15963 Dbdict::execCREATE_FILEGROUP_CONF(Signal* signal)
15964 {
15965   CreateFilegroupImplConf * rep =
15966     (CreateFilegroupImplConf*)signal->getDataPtr();
15967   CreateObjRecordPtr op_ptr;
15968   jamEntry();
15969   ndbrequire(c_opCreateObj.find(op_ptr, rep->senderData));
15970 
15971   execute(signal, op_ptr.p->m_callback, 0);
15972 }
15973 
15974 void
create_fg_abort_start(Signal * signal,SchemaOp * op)15975 Dbdict::create_fg_abort_start(Signal* signal, SchemaOp* op){
15976   (void) signal->getDataPtrSend();
15977 
15978   if (op->m_obj_ptr_i != RNIL)
15979   {
15980     jam();
15981     send_drop_fg(signal, op, DropFilegroupImplReq::Commit);
15982     return;
15983   }
15984   jam();
15985   execute(signal, op->m_callback, 0);
15986 }
15987 
15988 void
create_fg_abort_complete(Signal * signal,SchemaOp * op)15989 Dbdict::create_fg_abort_complete(Signal* signal, SchemaOp* op)
15990 {
15991   if (op->m_obj_ptr_i != RNIL)
15992   {
15993     jam();
15994     FilegroupPtr fg_ptr;
15995     c_filegroup_pool.getPtr(fg_ptr, op->m_obj_ptr_i);
15996 
15997     release_object(fg_ptr.p->m_obj_ptr_i);
15998     c_filegroup_hash.release(fg_ptr);
15999   }
16000   jam();
16001   execute(signal, op->m_callback, 0);
16002 }
16003 
16004 void
create_file_prepare_start(Signal * signal,SchemaOp * op)16005 Dbdict::create_file_prepare_start(Signal* signal, SchemaOp* op)
16006 {
16007   /**
16008    * Put data into table record
16009    */
16010   SegmentedSectionPtr objInfoPtr;
16011   getSection(objInfoPtr, ((OpCreateObj*)op)->m_obj_info_ptr_i);
16012   SimplePropertiesSectionReader it(objInfoPtr, getSectionSegmentPool());
16013 
16014   Ptr<DictObject> obj_ptr; obj_ptr.setNull();
16015   FilePtr filePtr; filePtr.setNull();
16016 
16017   DictFilegroupInfo::File f; f.init();
16018   SimpleProperties::UnpackStatus status;
16019   status = SimpleProperties::unpack(it, &f,
16020 				    DictFilegroupInfo::FileMapping,
16021 				    DictFilegroupInfo::FileMappingSize,
16022 				    true, true);
16023 
16024   do {
16025     if(status != SimpleProperties::Eof){
16026       jam();
16027       op->m_errorCode = CreateFileRef::InvalidFormat;
16028       break;
16029     }
16030 
16031     // Get Filegroup
16032     FilegroupPtr fg_ptr;
16033     if(!c_filegroup_hash.find(fg_ptr, f.FilegroupId)){
16034       jam();
16035       op->m_errorCode = CreateFileRef::NoSuchFilegroup;
16036       break;
16037     }
16038 
16039     if(fg_ptr.p->m_version != f.FilegroupVersion){
16040       jam();
16041       op->m_errorCode = CreateFileRef::InvalidFilegroupVersion;
16042       break;
16043     }
16044 
16045     switch(f.FileType){
16046     case DictTabInfo::Datafile:
16047     {
16048       if(fg_ptr.p->m_type != DictTabInfo::Tablespace)
16049       {
16050         jam();
16051 	op->m_errorCode = CreateFileRef::InvalidFileType;
16052       }
16053       jam();
16054       break;
16055     }
16056     case DictTabInfo::Undofile:
16057     {
16058       if(fg_ptr.p->m_type != DictTabInfo::LogfileGroup)
16059       {
16060         jam();
16061 	op->m_errorCode = CreateFileRef::InvalidFileType;
16062       }
16063       jam();
16064       break;
16065     }
16066     default:
16067       jam();
16068       op->m_errorCode = CreateFileRef::InvalidFileType;
16069     }
16070 
16071     if(op->m_errorCode)
16072     {
16073       jam();
16074       break;
16075     }
16076 
16077     Uint32 len = strlen(f.FileName) + 1;
16078     Uint32 hash = Rope::hash(f.FileName, len);
16079     if(get_object(f.FileName, len, hash) != 0){
16080       jam();
16081       op->m_errorCode = CreateFileRef::FilenameAlreadyExists;
16082       break;
16083     }
16084 
16085     {
16086       Uint32 dl;
16087       const ndb_mgm_configuration_iterator * p =
16088 	m_ctx.m_config.getOwnConfigIterator();
16089       if(!ndb_mgm_get_int_parameter(p, CFG_DB_DISCLESS, &dl) && dl)
16090       {
16091         jam();
16092 	op->m_errorCode = CreateFileRef::NotSupportedWhenDiskless;
16093 	break;
16094       }
16095     }
16096 
16097     // Loop through all filenames...
16098     if(!c_obj_pool.seize(obj_ptr)){
16099       jam();
16100       op->m_errorCode = CreateTableRef::NoMoreTableRecords;
16101       break;
16102     }
16103 
16104     if (! c_file_pool.seize(filePtr)){
16105       jam();
16106       op->m_errorCode = CreateFileRef::OutOfFileRecords;
16107       break;
16108     }
16109 
16110     new (filePtr.p) File();
16111 
16112     {
16113       Rope name(c_rope_pool, obj_ptr.p->m_name);
16114       if(!name.assign(f.FileName, len, hash)){
16115         jam();
16116 	op->m_errorCode = CreateTableRef::OutOfStringBuffer;
16117 	break;
16118       }
16119     }
16120 
16121     switch(fg_ptr.p->m_type){
16122     case DictTabInfo::Tablespace:
16123     {
16124       jam();
16125       increase_ref_count(fg_ptr.p->m_obj_ptr_i);
16126       break;
16127     }
16128     case DictTabInfo::LogfileGroup:
16129     {
16130       jam();
16131       Local_file_list list(c_file_pool, fg_ptr.p->m_logfilegroup.m_files);
16132       list.add(filePtr);
16133       break;
16134     }
16135     default:
16136       ndbrequire(false);
16137     }
16138 
16139     /**
16140      * Init file
16141      */
16142     filePtr.p->key = op->m_obj_id;
16143     filePtr.p->m_file_size = ((Uint64)f.FileSizeHi) << 32 | f.FileSizeLo;
16144     filePtr.p->m_path = obj_ptr.p->m_name;
16145     filePtr.p->m_obj_ptr_i = obj_ptr.i;
16146     filePtr.p->m_filegroup_id = f.FilegroupId;
16147     filePtr.p->m_type = f.FileType;
16148     filePtr.p->m_version = op->m_obj_version;
16149 
16150     obj_ptr.p->m_id = op->m_obj_id;
16151     obj_ptr.p->m_type = f.FileType;
16152     obj_ptr.p->m_ref_count = 0;
16153     c_obj_hash.add(obj_ptr);
16154     c_file_hash.add(filePtr);
16155 
16156     op->m_obj_ptr_i = filePtr.i;
16157   } while(0);
16158 
16159   if (op->m_errorCode)
16160   {
16161     jam();
16162     if (!filePtr.isNull())
16163     {
16164       jam();
16165       c_file_pool.release(filePtr);
16166     }
16167 
16168     if (!obj_ptr.isNull())
16169     {
16170       jam();
16171       c_obj_pool.release(obj_ptr);
16172     }
16173   }
16174   execute(signal, op->m_callback, 0);
16175 }
16176 
16177 
16178 void
create_file_prepare_complete(Signal * signal,SchemaOp * op)16179 Dbdict::create_file_prepare_complete(Signal* signal, SchemaOp* op)
16180 {
16181   /**
16182    * CONTACT TSMAN LGMAN PGMAN
16183    */
16184   CreateFileImplReq* req = (CreateFileImplReq*)signal->getDataPtrSend();
16185   FilePtr f_ptr;
16186   FilegroupPtr fg_ptr;
16187 
16188   jam();
16189   c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
16190   ndbrequire(c_filegroup_hash.find(fg_ptr, f_ptr.p->m_filegroup_id));
16191 
16192   req->senderData = op->key;
16193   req->senderRef = reference();
16194   switch(((OpCreateObj*)op)->m_restart){
16195   case 0:
16196   {
16197     jam();
16198     req->requestInfo = CreateFileImplReq::Create;
16199     break;
16200   }
16201   case 1:
16202   {
16203     jam();
16204     req->requestInfo = CreateFileImplReq::Open;
16205     break;
16206   }
16207   case 2:
16208   {
16209     jam();
16210     req->requestInfo = CreateFileImplReq::CreateForce;
16211     break;
16212   }
16213   }
16214 
16215   req->file_id = f_ptr.p->key;
16216   req->filegroup_id = f_ptr.p->m_filegroup_id;
16217   req->filegroup_version = fg_ptr.p->m_version;
16218   req->file_size_hi = f_ptr.p->m_file_size >> 32;
16219   req->file_size_lo = f_ptr.p->m_file_size & 0xFFFFFFFF;
16220 
16221   Uint32 ref= 0;
16222   Uint32 len= 0;
16223   switch(op->m_obj_type){
16224   case DictTabInfo::Datafile:
16225   {
16226     jam();
16227     ref = TSMAN_REF;
16228     len = CreateFileImplReq::DatafileLength;
16229     req->tablespace.extent_size = fg_ptr.p->m_tablespace.m_extent_size;
16230     break;
16231   }
16232   case DictTabInfo::Undofile:
16233   {
16234     jam();
16235     ref = LGMAN_REF;
16236     len = CreateFileImplReq::UndofileLength;
16237     break;
16238   }
16239   default:
16240     ndbrequire(false);
16241   }
16242 
16243   char name[MAX_TAB_NAME_SIZE];
16244   ConstRope tmp(c_rope_pool, f_ptr.p->m_path);
16245   tmp.copy(name);
16246   LinearSectionPtr ptr[3];
16247   ptr[0].p = (Uint32*)&name[0];
16248   ptr[0].sz = (strlen(name)+1+3)/4;
16249   sendSignal(ref, GSN_CREATE_FILE_REQ, signal, len, JBB, ptr, 1);
16250 }
16251 
16252 void
execCREATE_FILE_REF(Signal * signal)16253 Dbdict::execCREATE_FILE_REF(Signal* signal)
16254 {
16255   CreateFileImplRef * ref = (CreateFileImplRef*)signal->getDataPtr();
16256   CreateObjRecordPtr op_ptr;
16257 
16258   jamEntry();
16259   ndbrequire(c_opCreateObj.find(op_ptr, ref->senderData));
16260   op_ptr.p->m_errorCode = ref->errorCode;
16261   execute(signal, op_ptr.p->m_callback, 0);
16262 }
16263 
16264 void
execCREATE_FILE_CONF(Signal * signal)16265 Dbdict::execCREATE_FILE_CONF(Signal* signal)
16266 {
16267   CreateFileImplConf * rep =
16268     (CreateFileImplConf*)signal->getDataPtr();
16269   CreateObjRecordPtr op_ptr;
16270 
16271   jamEntry();
16272   ndbrequire(c_opCreateObj.find(op_ptr, rep->senderData));
16273   execute(signal, op_ptr.p->m_callback, 0);
16274 }
16275 
16276 void
create_file_commit_start(Signal * signal,SchemaOp * op)16277 Dbdict::create_file_commit_start(Signal* signal, SchemaOp* op)
16278 {
16279   /**
16280    * CONTACT TSMAN LGMAN PGMAN
16281    */
16282   CreateFileImplReq* req = (CreateFileImplReq*)signal->getDataPtrSend();
16283   FilePtr f_ptr;
16284   FilegroupPtr fg_ptr;
16285 
16286   jam();
16287   c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
16288   ndbrequire(c_filegroup_hash.find(fg_ptr, f_ptr.p->m_filegroup_id));
16289 
16290   req->senderData = op->key;
16291   req->senderRef = reference();
16292   req->requestInfo = CreateFileImplReq::Commit;
16293 
16294   req->file_id = f_ptr.p->key;
16295   req->filegroup_id = f_ptr.p->m_filegroup_id;
16296   req->filegroup_version = fg_ptr.p->m_version;
16297 
16298   Uint32 ref= 0;
16299   switch(op->m_obj_type){
16300   case DictTabInfo::Datafile:
16301   {
16302     jam();
16303     ref = TSMAN_REF;
16304     break;
16305   }
16306   case DictTabInfo::Undofile:
16307   {
16308     jam();
16309     ref = LGMAN_REF;
16310     break;
16311   }
16312   default:
16313     ndbrequire(false);
16314   }
16315   sendSignal(ref, GSN_CREATE_FILE_REQ, signal,
16316 	     CreateFileImplReq::CommitLength, JBB);
16317 }
16318 
16319 void
create_file_abort_start(Signal * signal,SchemaOp * op)16320 Dbdict::create_file_abort_start(Signal* signal, SchemaOp* op)
16321 {
16322   CreateFileImplReq* req = (CreateFileImplReq*)signal->getDataPtrSend();
16323 
16324   if (op->m_obj_ptr_i != RNIL)
16325   {
16326     FilePtr f_ptr;
16327     FilegroupPtr fg_ptr;
16328 
16329     jam();
16330     c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
16331 
16332     ndbrequire(c_filegroup_hash.find(fg_ptr, f_ptr.p->m_filegroup_id));
16333 
16334     req->senderData = op->key;
16335     req->senderRef = reference();
16336     req->requestInfo = CreateFileImplReq::Abort;
16337 
16338     req->file_id = f_ptr.p->key;
16339     req->filegroup_id = f_ptr.p->m_filegroup_id;
16340     req->filegroup_version = fg_ptr.p->m_version;
16341 
16342     Uint32 ref= 0;
16343     switch(op->m_obj_type){
16344     case DictTabInfo::Datafile:
16345     {
16346       jam();
16347       ref = TSMAN_REF;
16348       break;
16349     }
16350     case DictTabInfo::Undofile:
16351     {
16352       jam();
16353       ref = LGMAN_REF;
16354       break;
16355     }
16356     default:
16357       ndbrequire(false);
16358     }
16359     sendSignal(ref, GSN_CREATE_FILE_REQ, signal,
16360 	       CreateFileImplReq::AbortLength, JBB);
16361     return;
16362   }
16363   execute(signal, op->m_callback, 0);
16364 }
16365 
16366 void
create_file_abort_complete(Signal * signal,SchemaOp * op)16367 Dbdict::create_file_abort_complete(Signal* signal, SchemaOp* op)
16368 {
16369   if (op->m_obj_ptr_i != RNIL)
16370   {
16371     FilePtr f_ptr;
16372     FilegroupPtr fg_ptr;
16373 
16374     jam();
16375     c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
16376     ndbrequire(c_filegroup_hash.find(fg_ptr, f_ptr.p->m_filegroup_id));
16377     switch(fg_ptr.p->m_type){
16378     case DictTabInfo::Tablespace:
16379     {
16380       jam();
16381       decrease_ref_count(fg_ptr.p->m_obj_ptr_i);
16382       break;
16383     }
16384     case DictTabInfo::LogfileGroup:
16385     {
16386       jam();
16387       Local_file_list list(c_file_pool, fg_ptr.p->m_logfilegroup.m_files);
16388       list.remove(f_ptr);
16389       break;
16390     }
16391     default:
16392       ndbrequire(false);
16393     }
16394 
16395     release_object(f_ptr.p->m_obj_ptr_i);
16396     c_file_hash.release(f_ptr);
16397   }
16398   execute(signal, op->m_callback, 0);
16399 }
16400 
16401 void
drop_file_prepare_start(Signal * signal,SchemaOp * op)16402 Dbdict::drop_file_prepare_start(Signal* signal, SchemaOp* op)
16403 {
16404   jam();
16405   send_drop_file(signal, op, DropFileImplReq::Prepare);
16406 }
16407 
16408 void
drop_undofile_prepare_start(Signal * signal,SchemaOp * op)16409 Dbdict::drop_undofile_prepare_start(Signal* signal, SchemaOp* op)
16410 {
16411   jam();
16412   op->m_errorCode = DropFileRef::DropUndoFileNotSupported;
16413   execute(signal, op->m_callback, 0);
16414 }
16415 
16416 void
drop_file_commit_start(Signal * signal,SchemaOp * op)16417 Dbdict::drop_file_commit_start(Signal* signal, SchemaOp* op)
16418 {
16419   jam();
16420   send_drop_file(signal, op, DropFileImplReq::Commit);
16421 }
16422 
16423 void
drop_file_commit_complete(Signal * signal,SchemaOp * op)16424 Dbdict::drop_file_commit_complete(Signal* signal, SchemaOp* op)
16425 {
16426   FilePtr f_ptr;
16427   FilegroupPtr fg_ptr;
16428 
16429   jam();
16430   c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
16431   ndbrequire(c_filegroup_hash.find(fg_ptr, f_ptr.p->m_filegroup_id));
16432   decrease_ref_count(fg_ptr.p->m_obj_ptr_i);
16433   release_object(f_ptr.p->m_obj_ptr_i);
16434   c_file_hash.release(f_ptr);
16435   execute(signal, op->m_callback, 0);
16436 }
16437 
16438 void
drop_undofile_commit_complete(Signal * signal,SchemaOp * op)16439 Dbdict::drop_undofile_commit_complete(Signal* signal, SchemaOp* op)
16440 {
16441   FilePtr f_ptr;
16442   FilegroupPtr fg_ptr;
16443 
16444   jam();
16445   c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
16446   ndbrequire(c_filegroup_hash.find(fg_ptr, f_ptr.p->m_filegroup_id));
16447   Local_file_list list(c_file_pool, fg_ptr.p->m_logfilegroup.m_files);
16448   list.remove(f_ptr);
16449   release_object(f_ptr.p->m_obj_ptr_i);
16450   c_file_hash.release(f_ptr);
16451   execute(signal, op->m_callback, 0);
16452 }
16453 
16454 void
drop_file_abort_start(Signal * signal,SchemaOp * op)16455 Dbdict::drop_file_abort_start(Signal* signal, SchemaOp* op)
16456 {
16457   jam();
16458   send_drop_file(signal, op, DropFileImplReq::Abort);
16459 }
16460 
16461 void
send_drop_file(Signal * signal,SchemaOp * op,DropFileImplReq::RequestInfo type)16462 Dbdict::send_drop_file(Signal* signal, SchemaOp* op,
16463 		       DropFileImplReq::RequestInfo type)
16464 {
16465   DropFileImplReq* req = (DropFileImplReq*)signal->getDataPtrSend();
16466   FilePtr f_ptr;
16467   FilegroupPtr fg_ptr;
16468 
16469   jam();
16470   c_file_pool.getPtr(f_ptr, op->m_obj_ptr_i);
16471   ndbrequire(c_filegroup_hash.find(fg_ptr, f_ptr.p->m_filegroup_id));
16472 
16473   req->senderData = op->key;
16474   req->senderRef = reference();
16475   req->requestInfo = type;
16476 
16477   req->file_id = f_ptr.p->key;
16478   req->filegroup_id = f_ptr.p->m_filegroup_id;
16479   req->filegroup_version = fg_ptr.p->m_version;
16480 
16481   Uint32 ref= 0;
16482   switch(op->m_obj_type){
16483   case DictTabInfo::Datafile:
16484   {
16485     jam();
16486     ref = TSMAN_REF;
16487     break;
16488   }
16489   case DictTabInfo::Undofile:
16490   {
16491     jam();
16492     ref = LGMAN_REF;
16493     break;
16494   }
16495   default:
16496     ndbrequire(false);
16497   }
16498   sendSignal(ref, GSN_DROP_FILE_REQ, signal,
16499 	     DropFileImplReq::SignalLength, JBB);
16500 }
16501 
16502 void
execDROP_OBJ_REF(Signal * signal)16503 Dbdict::execDROP_OBJ_REF(Signal* signal)
16504 {
16505   DropObjRef * const ref = (DropObjRef*)signal->getDataPtr();
16506   Ptr<SchemaTransaction> trans_ptr;
16507 
16508   jamEntry();
16509   ndbrequire(c_Trans.find(trans_ptr, ref->senderData));
16510   if(ref->errorCode != DropObjRef::NF_FakeErrorREF){
16511     jam();
16512     trans_ptr.p->setErrorCode(ref->errorCode);
16513   }
16514   Uint32 node = refToNode(ref->senderRef);
16515   schemaOp_reply(signal, trans_ptr.p, node);
16516 }
16517 
16518 void
execDROP_OBJ_CONF(Signal * signal)16519 Dbdict::execDROP_OBJ_CONF(Signal* signal)
16520 {
16521   DropObjConf * const conf = (DropObjConf*)signal->getDataPtr();
16522   Ptr<SchemaTransaction> trans_ptr;
16523 
16524   jamEntry();
16525   ndbrequire(c_Trans.find(trans_ptr, conf->senderData));
16526   schemaOp_reply(signal, trans_ptr.p, refToNode(conf->senderRef));
16527 }
16528 
16529 void
execDROP_FILE_REF(Signal * signal)16530 Dbdict::execDROP_FILE_REF(Signal* signal)
16531 {
16532   DropFileImplRef * ref = (DropFileImplRef*)signal->getDataPtr();
16533   DropObjRecordPtr op_ptr;
16534 
16535   jamEntry();
16536   ndbrequire(c_opDropObj.find(op_ptr, ref->senderData));
16537   op_ptr.p->m_errorCode = ref->errorCode;
16538   execute(signal, op_ptr.p->m_callback, 0);
16539 }
16540 
16541 void
execDROP_FILE_CONF(Signal * signal)16542 Dbdict::execDROP_FILE_CONF(Signal* signal)
16543 {
16544   DropFileImplConf * rep =
16545     (DropFileImplConf*)signal->getDataPtr();
16546   DropObjRecordPtr op_ptr;
16547 
16548   jamEntry();
16549   ndbrequire(c_opDropObj.find(op_ptr, rep->senderData));
16550   execute(signal, op_ptr.p->m_callback, 0);
16551 }
16552 
16553 void
execDROP_FILEGROUP_REF(Signal * signal)16554 Dbdict::execDROP_FILEGROUP_REF(Signal* signal)
16555 {
16556   DropFilegroupImplRef * ref = (DropFilegroupImplRef*)signal->getDataPtr();
16557   DropObjRecordPtr op_ptr;
16558 
16559   jamEntry();
16560   ndbrequire(c_opDropObj.find(op_ptr, ref->senderData));
16561   op_ptr.p->m_errorCode = ref->errorCode;
16562   execute(signal, op_ptr.p->m_callback, 0);
16563 }
16564 
16565 void
execDROP_FILEGROUP_CONF(Signal * signal)16566 Dbdict::execDROP_FILEGROUP_CONF(Signal* signal)
16567 {
16568   DropFilegroupImplConf * rep =
16569     (DropFilegroupImplConf*)signal->getDataPtr();
16570   DropObjRecordPtr op_ptr;
16571 
16572   jamEntry();
16573   ndbrequire(c_opDropObj.find(op_ptr, rep->senderData));
16574   execute(signal, op_ptr.p->m_callback, 0);
16575 }
16576 
16577 void
drop_fg_prepare_start(Signal * signal,SchemaOp * op)16578 Dbdict::drop_fg_prepare_start(Signal* signal, SchemaOp* op)
16579 {
16580   FilegroupPtr fg_ptr;
16581   c_filegroup_pool.getPtr(fg_ptr, op->m_obj_ptr_i);
16582 
16583   DictObject * obj = c_obj_pool.getPtr(fg_ptr.p->m_obj_ptr_i);
16584   if (obj->m_ref_count)
16585   {
16586     jam();
16587     op->m_errorCode = DropFilegroupRef::FilegroupInUse;
16588     execute(signal, op->m_callback, 0);
16589   }
16590   else
16591   {
16592     jam();
16593     send_drop_fg(signal, op, DropFilegroupImplReq::Prepare);
16594   }
16595 }
16596 
16597 void
drop_fg_commit_start(Signal * signal,SchemaOp * op)16598 Dbdict::drop_fg_commit_start(Signal* signal, SchemaOp* op)
16599 {
16600   FilegroupPtr fg_ptr;
16601   c_filegroup_pool.getPtr(fg_ptr, op->m_obj_ptr_i);
16602   if (op->m_obj_type == DictTabInfo::LogfileGroup)
16603   {
16604     jam();
16605     /**
16606      * Mark all undofiles as dropped
16607      */
16608     Ptr<File> filePtr;
16609     Local_file_list list(c_file_pool, fg_ptr.p->m_logfilegroup.m_files);
16610     XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
16611     for(list.first(filePtr); !filePtr.isNull(); list.next(filePtr))
16612     {
16613       jam();
16614       Uint32 objId = filePtr.p->key;
16615       SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, objId);
16616       tableEntry->m_tableState = SchemaFile::DROP_TABLE_COMMITTED;
16617       computeChecksum(xsf, objId / NDB_SF_PAGE_ENTRIES);
16618       release_object(filePtr.p->m_obj_ptr_i);
16619       c_file_hash.remove(filePtr);
16620     }
16621     list.release();
16622   }
16623   else if(op->m_obj_type == DictTabInfo::Tablespace)
16624   {
16625     FilegroupPtr lg_ptr;
16626     jam();
16627     ndbrequire(c_filegroup_hash.
16628 	       find(lg_ptr,
16629 		    fg_ptr.p->m_tablespace.m_default_logfile_group_id));
16630 
16631     decrease_ref_count(lg_ptr.p->m_obj_ptr_i);
16632   }
16633   jam();
16634   send_drop_fg(signal, op, DropFilegroupImplReq::Commit);
16635 }
16636 
16637 void
drop_fg_commit_complete(Signal * signal,SchemaOp * op)16638 Dbdict::drop_fg_commit_complete(Signal* signal, SchemaOp* op)
16639 {
16640   FilegroupPtr fg_ptr;
16641   c_filegroup_pool.getPtr(fg_ptr, op->m_obj_ptr_i);
16642 
16643   jam();
16644   release_object(fg_ptr.p->m_obj_ptr_i);
16645   c_filegroup_hash.release(fg_ptr);
16646   execute(signal, op->m_callback, 0);
16647 }
16648 
16649 void
drop_fg_abort_start(Signal * signal,SchemaOp * op)16650 Dbdict::drop_fg_abort_start(Signal* signal, SchemaOp* op)
16651 {
16652   jam();
16653   send_drop_fg(signal, op, DropFilegroupImplReq::Abort);
16654 }
16655 
16656 void
send_drop_fg(Signal * signal,SchemaOp * op,DropFilegroupImplReq::RequestInfo type)16657 Dbdict::send_drop_fg(Signal* signal, SchemaOp* op,
16658 		     DropFilegroupImplReq::RequestInfo type)
16659 {
16660   DropFilegroupImplReq* req = (DropFilegroupImplReq*)signal->getDataPtrSend();
16661 
16662   FilegroupPtr fg_ptr;
16663   c_filegroup_pool.getPtr(fg_ptr, op->m_obj_ptr_i);
16664 
16665   req->senderData = op->key;
16666   req->senderRef = reference();
16667   req->requestInfo = type;
16668 
16669   req->filegroup_id = fg_ptr.p->key;
16670   req->filegroup_version = fg_ptr.p->m_version;
16671 
16672   Uint32 ref= 0;
16673   switch(op->m_obj_type){
16674   case DictTabInfo::Tablespace:
16675     ref = TSMAN_REF;
16676     break;
16677   case DictTabInfo::LogfileGroup:
16678     ref = LGMAN_REF;
16679     break;
16680   default:
16681     ndbrequire(false);
16682   }
16683 
16684   sendSignal(ref, GSN_DROP_FILEGROUP_REQ, signal,
16685 	     DropFilegroupImplReq::SignalLength, JBB);
16686 }
16687 
16688 /*
16689   return 1 if all of the below is true
16690   a) node in single user mode
16691   b) senderRef is not a db node
16692   c) senderRef nodeid is not the singleUserApi
16693 */
checkSingleUserMode(Uint32 senderRef)16694 int Dbdict::checkSingleUserMode(Uint32 senderRef)
16695 {
16696   Uint32 nodeId = refToNode(senderRef);
16697   return
16698     getNodeState().getSingleUserMode() &&
16699     (getNodeInfo(nodeId).m_type != NodeInfo::DB) &&
16700     (nodeId != getNodeState().getSingleUserApi());
16701 }
16702 
16703