1 /*
2    Copyright (c) 2003, 2021, Oracle and/or its affiliates.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #ifndef DBDICT_H
26 #define DBDICT_H
27 
28 /**
29  * Dict : Dictionary Block
30  */
31 #include <ndb_limits.h>
32 #include <trigger_definitions.h>
33 #include <pc.hpp>
34 #include <ArenaPool.hpp>
35 #include <DataBuffer2.hpp>
36 #include <DLHashTable.hpp>
37 #include <IntrusiveList.hpp>
38 #include <CArray.hpp>
39 #include <KeyTable.hpp>
40 #include <KeyTable2.hpp>
41 #include <KeyTable2Ref.hpp>
42 #include <SimulatedBlock.hpp>
43 #include <SimpleProperties.hpp>
44 #include <SignalCounter.hpp>
45 #include <Bitmask.hpp>
46 #include <AttributeList.hpp>
47 #include <signaldata/GetTableId.hpp>
48 #include <signaldata/GetTabInfo.hpp>
49 #include <signaldata/DictTabInfo.hpp>
50 #include <signaldata/CreateTable.hpp>
51 #include <signaldata/CreateTab.hpp>
52 #include <signaldata/DropTable.hpp>
53 #include <signaldata/DropTab.hpp>
54 #include <signaldata/AlterTable.hpp>
55 #include <signaldata/AlterTab.hpp>
56 #include <signaldata/ListTables.hpp>
57 #include <signaldata/CreateIndx.hpp>
58 #include <signaldata/CreateIndxImpl.hpp>
59 #include <signaldata/DropIndx.hpp>
60 #include <signaldata/DropIndxImpl.hpp>
61 #include <signaldata/AlterIndx.hpp>
62 #include <signaldata/AlterIndxImpl.hpp>
63 #include <signaldata/BuildIndx.hpp>
64 #include <signaldata/BuildIndxImpl.hpp>
65 #include <signaldata/IndexStatSignal.hpp>
66 #include <signaldata/UtilPrepare.hpp>
67 #include <signaldata/CreateEvnt.hpp>
68 #include <signaldata/CreateTrig.hpp>
69 #include <signaldata/CreateTrigImpl.hpp>
70 #include <signaldata/DropTrig.hpp>
71 #include <signaldata/DropTrigImpl.hpp>
72 #include <signaldata/DictLock.hpp>
73 #include <signaldata/DictTakeover.hpp>
74 #include <signaldata/SumaImpl.hpp>
75 #include <signaldata/CreateHashMap.hpp>
76 #include <signaldata/HashMapImpl.hpp>
77 #include "SchemaFile.hpp"
78 #include <blocks/mutexes.hpp>
79 #include <SafeCounter.hpp>
80 #include <RequestTracker.hpp>
81 #include <Rope.hpp>
82 #include <signaldata/CreateFilegroupImpl.hpp>
83 #include <signaldata/DropFilegroupImpl.hpp>
84 #include <signaldata/DictSignal.hpp>
85 #include <signaldata/SchemaTransImpl.hpp>
86 #include <LockQueue.hpp>
87 #include <signaldata/CopyData.hpp>
88 #include <signaldata/NodeFailRep.hpp>
89 #include <signaldata/CreateNodegroup.hpp>
90 #include <signaldata/DropNodegroup.hpp>
91 #include <signaldata/CreateNodegroupImpl.hpp>
92 #include <signaldata/DropNodegroupImpl.hpp>
93 #include <Mutex.hpp>
94 #include <SegmentList.hpp>
95 
96 #include <signaldata/CreateFK.hpp>
97 #include <signaldata/CreateFKImpl.hpp>
98 #include <signaldata/BuildFK.hpp>
99 #include <signaldata/BuildFKImpl.hpp>
100 #include <signaldata/DropFK.hpp>
101 #include <signaldata/DropFKImpl.hpp>
102 
103 #define JAM_FILE_ID 464
104 
105 #ifdef DBDICT_C
106 
107 /*--------------------------------------------------------------*/
108 // Constants for CONTINUEB
109 /*--------------------------------------------------------------*/
110 #define ZPACK_TABLE_INTO_PAGES 0
111 #define ZSEND_GET_TAB_RESPONSE 3
112 #define ZWAIT_SUBSTARTSTOP 4
113 #define ZDICT_TAKEOVER_REQ 5
114 
115 #define ZCOMMIT_WAIT_GCI   6
116 #define ZINDEX_STAT_BG_PROCESS 7
117 #define ZGET_TABINFO_RETRY 8
118 #define ZNEXT_GET_TAB_REQ 9
119 
120 /*--------------------------------------------------------------*/
121 // Other constants in alphabetical order
122 /*--------------------------------------------------------------*/
123 #define ZNOMOREPHASES 255
124 
125 /*--------------------------------------------------------------*/
126 // Schema file defines
127 /*--------------------------------------------------------------*/
128 #define ZSCHEMA_WORDS 4
129 
130 /*--------------------------------------------------------------*/
131 // Page constants
132 /*--------------------------------------------------------------*/
133 #define ZBAT_SCHEMA_FILE 0 //Variable number of page for NDBFS
134 #define ZBAT_TABLE_FILE 1 //Variable number of page for NDBFS
135 #define ZPAGE_HEADER_SIZE 32
136 #define ZPOS_PAGE_SIZE 16
137 #define ZPOS_CHECKSUM 17
138 #define ZPOS_VERSION 18
139 #define ZPOS_PAGE_HEADER_SIZE 19
140 
141 /*--------------------------------------------------------------*/
142 // Size constants
143 /*--------------------------------------------------------------*/
144 #define ZFS_CONNECT_SIZE 4
145 #define ZSIZE_OF_PAGES_IN_WORDS 8192
146 #define ZLOG_SIZE_OF_PAGES_IN_WORDS 13
147 #define ZMAX_PAGES_OF_TABLE_DEFINITION \
148   ((ZPAGE_HEADER_SIZE + MAX_WORDS_META_FILE + ZSIZE_OF_PAGES_IN_WORDS - 1) / \
149    ZSIZE_OF_PAGES_IN_WORDS)
150 
151 /**
152  * - one for retreive
153  * - one for read or write
154  */
155 #define ZNUMBER_OF_PAGES (2 * ZMAX_PAGES_OF_TABLE_DEFINITION)
156 #endif
157 
158 /**
159  * Systable NDB$EVENTS_0
160  */
161 #define EVENT_SYSTEM_TABLE_LENGTH 9
162 #define EVENT_SYSTEM_TABLE_ATTRIBUTE_MASK2_ID 8
163 
164 struct sysTab_NDBEVENTS_0 {
165   char   NAME[MAX_TAB_NAME_SIZE];
166   Uint32 EVENT_TYPE;
167   Uint32 TABLEID;
168   Uint32 TABLEVERSION;
169   char   TABLE_NAME[MAX_TAB_NAME_SIZE];
170   Uint32 ATTRIBUTE_MASK[MAXNROFATTRIBUTESINWORDS_OLD];
171   Uint32 SUBID;
172   Uint32 SUBKEY;
173 
174   // +1 to allow var size header to be received
175   Uint32 ATTRIBUTE_MASK2[(MAX_ATTRIBUTES_IN_TABLE / 32) + 1];
176 };
177 
178 /**
179  *  DICT - This blocks handles all metadata
180  */
181 class Dbdict: public SimulatedBlock {
182 public:
183 
184   /*
185    *   2.3 RECORD AND FILESIZES
186    */
187 
188   /**
189    * Table attributes.  Permanent data.
190    *
191    * Indexes have an attribute list which duplicates primary table
192    * attributes.  This is wrong but convenient.
193    */
194   struct AttributeRecord {
AttributeRecordDbdict::AttributeRecord195     AttributeRecord(){}
196 
197     /* attribute id */
198     Uint16 attributeId;
199 
200     /* Attribute number within tuple key (counted from 1) */
201     Uint16 tupleKey;
202 
203     /* Attribute name (unique within table) */
204     RopeHandle attributeName;
205 
206     /* Attribute description (old-style packed descriptor) */
207     Uint32 attributeDescriptor;
208 
209     /* Extended attributes */
210     Uint32 extType;
211     Uint32 extPrecision;
212     Uint32 extScale;
213     Uint32 extLength;
214 
215     /* Autoincrement flag, only for ODBC/SQL */
216     bool autoIncrement;
217 
218     /* Default value as null-terminated string, only for ODBC/SQL */
219     RopeHandle defaultValue;
220 
221     struct {
222       Uint32 m_name_len;
223       const char * m_name_ptr;
224       RopePool * m_pool;
225     } m_key;
226 
227     union {
228       Uint32 nextPool;
229       Uint32 nextList;
230     };
231     Uint32 prevList;
232     Uint32 nextHash;
233     Uint32 prevHash;
234 
hashValueDbdict::AttributeRecord235     Uint32 hashValue() const { return attributeName.hashValue();}
equalDbdict::AttributeRecord236     bool equal(const AttributeRecord& obj) const {
237       if(obj.hashValue() == hashValue()){
238 	ConstRope r(* m_key.m_pool, obj.attributeName);
239 	return r.compare(m_key.m_name_ptr, m_key.m_name_len) == 0;
240       }
241       return false;
242     }
243   };
244   typedef Ptr<AttributeRecord> AttributeRecordPtr;
245   typedef ArrayPool<AttributeRecord> AttributeRecord_pool;
246   typedef DLMHashTable<AttributeRecord_pool, AttributeRecord> AttributeRecord_hash;
247   typedef DLFifoListImpl<AttributeRecord_pool, AttributeRecord, AttributeRecord> AttributeRecord_list;
248   typedef LocalDLFifoListImpl<AttributeRecord_pool, AttributeRecord, AttributeRecord> LocalAttributeRecord_list;
249 
250   AttributeRecord_pool c_attributeRecordPool;
251   AttributeRecord_hash c_attributeRecordHash;
252   RSS_AP_SNAPSHOT(c_attributeRecordPool);
253 
254   /**
255    * Shared table / index record.  Most of this is permanent data stored
256    * on disk.  Index trigger ids are volatile.
257    */
258   struct TableRecord;
259   typedef Ptr<TableRecord> TableRecordPtr;
260   typedef ArrayPool<TableRecord> TableRecord_pool;
261   typedef DLFifoListImpl<TableRecord_pool, TableRecord, TableRecord> TableRecord_list;
262   typedef LocalDLFifoListImpl<TableRecord_pool, TableRecord, TableRecord> LocalTableRecord_list;
263 
264   struct TableRecord {
TableRecordDbdict::TableRecord265     TableRecord(){ m_upgrade_trigger_handling.m_upgrade = false;}
isCompatibleDbdict::TableRecord266     static bool isCompatible(Uint32 type) { return DictTabInfo::isTable(type) || DictTabInfo::isIndex(type); }
267 
268     Uint32 maxRowsLow;
269     Uint32 maxRowsHigh;
270     Uint32 minRowsLow;
271     Uint32 minRowsHigh;
272     /* Table id (array index in DICT and other blocks) */
273     Uint32 tableId;
274     Uint32 m_obj_ptr_i;
275 
276     /* Table version (incremented when tableId is re-used) */
277     Uint32 tableVersion;
278 
279     /* */
280     Uint32 hashMapObjectId;
281     Uint32 hashMapVersion;
282 
283     /* Table name (may not be unique under "alter table") */
284     RopeHandle tableName;
285 
286     /* Type of table or index */
287     DictTabInfo::TableType tableType;
288 
289     /* Is table or index online (this flag is not used in DICT) */
290     bool online;
291 
292     /* Primary table of index otherwise RNIL */
293     Uint32 primaryTableId;
294 
295     /* Type of fragmentation (small/medium/large) */
296     DictTabInfo::FragmentType fragmentType;
297 
298     /* Global checkpoint identity when table created */
299     Uint32 gciTableCreated;
300 
301     /* Is the table logged (i.e. data survives system restart) */
302     enum Bits
303     {
304       TR_Logged       = 0x1,
305       TR_RowGCI       = 0x2,
306       TR_RowChecksum  = 0x4,
307       TR_Temporary    = 0x8,
308       TR_ForceVarPart = 0x10
309     };
310     Uint8 m_extra_row_gci_bits;
311     Uint8 m_extra_row_author_bits;
312     Uint16 m_bits;
313 
314     /* Number of attibutes in table */
315     Uint16 noOfAttributes;
316 
317     /* Number of null attributes in table (should be computed) */
318     Uint16 noOfNullAttr;
319 
320     /* Number of primary key attributes (should be computed) */
321     Uint16 noOfPrimkey;
322 
323     /* Length of primary key in words (should be computed) */
324     /* For ordered index this is tree node size in words */
325     Uint16 tupKeyLength;
326 
327     /** */
328     Uint16 noOfCharsets;
329 
330     /* K value for LH**3 algorithm (only 6 allowed currently) */
331     Uint8 kValue;
332 
333     /* Local key length in words (currently 1) */
334     Uint8 localKeyLen;
335 
336     /*
337      * Parameter for hash algorithm that specifies the load factor in
338      * percentage of fill level in buckets. A high value means we are
339      * splitting early and that buckets are only lightly used. A high
340      * value means that we have fill the buckets more and get more
341      * likelihood of overflow buckets.
342      */
343     Uint8 maxLoadFactor;
344 
345     /*
346       Flag to indicate default number of partitions
347     */
348     bool defaultNoPartFlag;
349 
350     /*
351       Flag to indicate using linear hash function
352     */
353     bool linearHashFlag;
354 
355     /*
356      * Used when shrinking to decide when to merge buckets.  Hysteresis
357      * is thus possible. Should be smaller but not much smaller than
358      * maxLoadFactor
359      */
360     Uint8 minLoadFactor;
361 
362     /**
363      * Table default storage method
364      */
365     Uint8 storageType; // NDB_STORAGETYPE_
366 
367     /* Convenience routines */
368     bool isTable() const;
369     bool isIndex() const;
370     bool isUniqueIndex() const;
371     bool isNonUniqueIndex() const;
372     bool isHashIndex() const;
373     bool isOrderedIndex() const;
374 
375     /****************************************************
376      *    Support variables for table handling
377      ****************************************************/
378 
379     /**    File pointer received from disk   */
380     Uint32 filePtr[2];
381 
382     /**    Pointer to first attribute in table */
383     AttributeRecord_list::Head m_attributes;
384 
385     Uint32 nextPool;
386 
387     Uint32 m_read_locked; // BACKUP_ONGOING
388 
389     /**    Number of words */
390     Uint32 packedSize;
391 
392     /**   Index state (volatile data) TODO remove */
393     enum IndexState {
394       IS_UNDEFINED = 0,         // initial
395       IS_OFFLINE = 1,           // index table created
396       IS_BUILDING = 2,          // building (local state)
397       IS_DROPPING = 3,          // dropping (local state)
398       IS_ONLINE = 4,            // online
399       IS_BROKEN = 9             // build or drop aborted
400     };
401     IndexState indexState;
402 
403     /**   Trigger ids of index (volatile data) */
404     Uint32 triggerId;      // ordered index (1)
405     Uint32 buildTriggerId; // temp during build
406 
407     struct UpgradeTriggerHandling
408     {
409       /**
410        * In 6.3 (and prior) 3 triggers was created for each unique index
411        *  in 6.4 these has been merged to 1
412        *  but...we need to maintain these during an upgrade situation
413        *  puh
414        */
415       bool m_upgrade;
416       Uint32 insertTriggerId;
417       Uint32 updateTriggerId;
418       Uint32 deleteTriggerId;
419     } m_upgrade_trigger_handling;
420 
421     Uint32 noOfNullBits;
422 
423     /**  frm data for this table */
424     RopeHandle frmData;
425     RopeHandle ngData;
426     RopeHandle rangeData;
427 
428     Uint32 fragmentCount;
429     Uint32 m_tablespace_id;
430 
431     /** List of indexes attached to table */
432     TableRecord_list::Head m_indexes;
433     Uint32 nextList, prevList;
434 
435     /*
436      * Access rights to table during single user mode
437      */
438     Uint8 singleUserMode;
439 
440     /*
441      * Fragment and node to use for index statistics.  Not part of
442      * DICTTABINFO.  Computed locally by each DICT.  If the node is
443      * down, no automatic stats update takes place.  This is not
444      * critical and is not worth fixing.
445      */
446     Uint16 indexStatFragId;
447     Uint16 indexStatNodes[MAX_REPLICAS];
448 
449     // pending background request (IndexStatRep::RequestType)
450     Uint32 indexStatBgRequest;
451   };
452 
453   TableRecord_pool c_tableRecordPool_;
454   RSS_AP_SNAPSHOT(c_tableRecordPool_);
get_pool(TableRecordPtr)455   TableRecord_pool& get_pool(TableRecordPtr) { return c_tableRecordPool_; }
456 
457   /**  Node Group and Tablespace id+version + range or list data.
458     *  This is only stored temporarily in DBDICT during an ongoing
459     *  change.
460     *  TODO RONM: Look into improvements of this
461     */
462   Uint32 c_fragDataLen;
463   union {
464     Uint16 c_fragData[MAX_NDB_PARTITIONS];
465     Uint32 c_fragData_align32[1];
466   };
467   Uint32 c_tsIdData[2*MAX_NDB_PARTITIONS];
468 
469   /**
470    * Triggers.  This is volatile data not saved on disk.  Setting a
471    * trigger online creates the trigger in TC (if index) and LQH-TUP.
472    */
473   struct TriggerRecord {
TriggerRecordDbdict::TriggerRecord474     TriggerRecord() {}
isCompatibleDbdict::TriggerRecord475     static bool isCompatible(Uint32 type) { return DictTabInfo::isTrigger(type); }
476 
477     /** Trigger state */
478     enum TriggerState {
479       TS_NOT_DEFINED = 0,
480       TS_DEFINING = 1,
481       TS_OFFLINE  = 2,   // created globally in DICT
482       //TS_BUILDING = 3,
483       //TS_DROPPING = 4,
484       TS_ONLINE = 5,      // created in other blocks
485       TS_FAKE_UPGRADE = 6
486     };
487     TriggerState triggerState;
488 
489     /** Trigger name, used by DICT to identify the trigger */
490     RopeHandle triggerName;
491 
492     /** Trigger id, used by TRIX, TC, LQH, and TUP to identify the trigger */
493     Uint32 triggerId;
494     Uint32 m_obj_ptr_i;
495 
496     /** Table id, the table the trigger is defined on */
497     Uint32 tableId;
498 
499     /** TriggerInfo (packed) */
500     Uint32 triggerInfo;
501 
502     /**
503      * Attribute mask, defines what attributes are to be monitored.
504      * Can be seen as a compact representation of SQL column name list.
505      */
506     AttributeMask attributeMask;
507 
508     /** Receiver.  Not used from index triggers */
509     BlockReference receiverRef;
510 
511     /** Index id, only used by secondary_index triggers */
512     Uint32 indexId;
513 
514     /** Pointer to the next attribute used by ArrayPool */
515     Uint32 nextPool;
516   };
517 
518   typedef Ptr<TriggerRecord> TriggerRecordPtr;
519   typedef ArrayPool<TriggerRecord> TriggerRecord_pool;
520 
521   Uint32 c_maxNoOfTriggers;
522   TriggerRecord_pool c_triggerRecordPool_;
get_pool(TriggerRecordPtr)523   TriggerRecord_pool& get_pool(TriggerRecordPtr) { return c_triggerRecordPool_;}
524   RSS_AP_SNAPSHOT(c_triggerRecordPool_);
525 
526   /**
527    * Information for each FS connection.
528    ***************************************************************************/
529   struct FsConnectRecord {
530     enum FsState {
531       IDLE = 0,
532       OPEN_WRITE_SCHEMA = 1,
533       WRITE_SCHEMA = 2,
534       CLOSE_WRITE_SCHEMA = 3,
535       OPEN_READ_SCHEMA1 = 4,
536       OPEN_READ_SCHEMA2 = 5,
537       READ_SCHEMA1 = 6,
538       READ_SCHEMA2 = 7,
539       CLOSE_READ_SCHEMA = 8,
540       OPEN_READ_TAB_FILE1 = 9,
541       OPEN_READ_TAB_FILE2 = 10,
542       READ_TAB_FILE1 = 11,
543       READ_TAB_FILE2 = 12,
544       CLOSE_READ_TAB_FILE = 13,
545       OPEN_WRITE_TAB_FILE = 14,
546       WRITE_TAB_FILE = 15,
547       CLOSE_WRITE_TAB_FILE = 16
548     };
549     /** File Pointer for this file system connection */
550     Uint32 filePtr;
551 
552     /** Reference of owner record */
553     Uint32 ownerPtr;
554 
555     /** State of file system connection */
556     FsState fsState;
557 
558     /** Used by Array Pool for free list handling */
559     Uint32 nextPool;
560   };
561 
562   typedef Ptr<FsConnectRecord> FsConnectRecordPtr;
563   typedef ArrayPool<FsConnectRecord> FsConnectRecord_pool;
564   FsConnectRecord_pool c_fsConnectRecordPool;
565 
566   /**
567    * This record stores all the information about a node and all its attributes
568    ***************************************************************************/
569   struct NodeRecord {
570     enum NodeState {
571       API_NODE = 0,
572       NDB_NODE_ALIVE = 1,
573       NDB_NODE_DEAD = 2,
574       NDB_MASTER_TAKEOVER = 3
575     };
576     bool hotSpare;
577     NodeState nodeState;
578 
579     // Schema transaction data
580     enum RecoveryState {
581       RS_NORMAL = 0,             // Node is up to date with master
582       RS_PARTIAL_ROLLBACK = 1,   // Node has rolled back some operations
583       RS_PARTIAL_ROLLFORWARD = 2 // Node has committed some operations
584     };
585     RecoveryState recoveryState;
586     NodeFailRep nodeFailRep;
587     NdbNodeBitmask m_nodes;      // Nodes sent DICT_TAKEOVER_REQ during takeover
588     SafeCounterHandle m_counter; // Outstanding DICT_TAKEOVER_REQ's
589     //TODO Accumulate in buffer when DictTakeoverConf becomes long signal
590     DictTakeoverConf takeOverConf; // Accumulated replies
591 
592     // TODO: these should be moved to SchemaTransPtr
593     // Starting operation for partial rollback/rollforward
594     Uint32 start_op;
595     // Starting state of operation for partial rollback/rollforward
596     Uint32 start_op_state;
597   };
598 
599   typedef Ptr<NodeRecord> NodeRecordPtr;
600   CArray<NodeRecord> c_nodes;
601   NdbNodeBitmask c_aliveNodes;
602 
603   struct PageRecord {
604     Uint32 word[8192];
605   };
606 
607   typedef Ptr<PageRecord> PageRecordPtr;
608   CArray<PageRecord> c_pageRecordArray;
609 
610   struct SchemaPageRecord {
611     Uint32 word[NDB_SF_PAGE_SIZE_IN_WORDS];
612   };
613 
614   CArray<SchemaPageRecord> c_schemaPageRecordArray;
615 
616   unsigned g_trace;
617   DictTabInfo::Table c_tableDesc;
618 
619   /**
620    * A page for create index table signal.
621    */
622   PageRecord c_indexPage;
623 
624   struct File {
FileDbdict::File625     File() {}
isCompatibleDbdict::File626     static bool isCompatible(Uint32 type) { return DictTabInfo::isFile(type); }
627 
628     Uint32 key;
629     Uint32 m_magic;
630     Uint32 m_version;
631     Uint32 m_obj_ptr_i;
632     Uint32 m_filegroup_id;
633     Uint32 m_type;
634     Uint64 m_file_size;
635     Uint64 m_file_free;
636     RopeHandle m_path;
637 
638     Uint32 nextList;
639     union {
640       Uint32 prevList;
641       Uint32 nextPool;
642     };
643   };
644   typedef Ptr<File> FilePtr;
645   typedef RecordPool<File, RWPool> File_pool;
646   typedef DLListImpl<File_pool, File> File_list;
647   typedef LocalDLListImpl<File_pool, File> Local_file_list;
648 
649   struct Filegroup {
FilegroupDbdict::Filegroup650     Filegroup(){}
isCompatibleDbdict::Filegroup651     static bool isCompatible(Uint32 type) { return DictTabInfo::isFilegroup(type); }
652 
653     Uint32 key;
654     Uint32 m_obj_ptr_i;
655     Uint32 m_magic;
656 
657     Uint32 m_type;
658     Uint32 m_version;
659     RopeHandle m_name;
660 
661     union {
662       struct {
663 	Uint32 m_extent_size;
664 	Uint32 m_default_logfile_group_id;
665       } m_tablespace;
666 
667       struct {
668 	Uint32 m_undo_buffer_size;
669 	File_list::HeadPOD m_files;
670       } m_logfilegroup;
671     };
672 
673     union {
674       Uint32 nextPool;
675       Uint32 nextList;
676     };
677   };
678   typedef Ptr<Filegroup> FilegroupPtr;
679   typedef RecordPool<Filegroup, RWPool> Filegroup_pool;
680 
681   File_pool c_file_pool;
682   Filegroup_pool c_filegroup_pool;
683 
get_pool(FilePtr)684   File_pool& get_pool(FilePtr) { return c_file_pool; }
get_pool(FilegroupPtr)685   Filegroup_pool& get_pool(FilegroupPtr) { return c_filegroup_pool; }
686 
687   RopePool c_rope_pool;
688   RSS_AP_SNAPSHOT(c_rope_pool);
689 
690   template <typename T, typename U = T> struct HashedById {
nextHashDbdict::HashedById691     static Uint32& nextHash(U& t) { return t.nextHash_by_id; }
prevHashDbdict::HashedById692     static Uint32& prevHash(U& t) { return t.prevHash_by_id; }
hashValueDbdict::HashedById693     static Uint32 hashValue(T const& t) { return t.hashValue_by_id(); }
equalDbdict::HashedById694     static bool equal(T const& lhs, T const& rhs) { return lhs.equal_by_id(rhs); }
695   };
696 
697   template <typename T, typename U = T> struct HashedByName {
nextHashDbdict::HashedByName698     static Uint32& nextHash(U& t) { return t.nextHash_by_name; }
prevHashDbdict::HashedByName699     static Uint32& prevHash(U& t) { return t.prevHash_by_name; }
hashValueDbdict::HashedByName700     static Uint32 hashValue(T const& t) { return t.hashValue_by_name(); }
equalDbdict::HashedByName701     static bool equal(T const& lhs, T const& rhs) { return lhs.equal_by_name(rhs); }
702   };
703 
704   struct DictObject {
DictObjectDbdict::DictObject705     DictObject() {
706       m_trans_key = 0;
707       m_op_ref_count = 0;
708     };
709     Uint32 m_id;
710     Uint32 m_type;
711     Uint32 m_object_ptr_i;
712     Uint32 m_ref_count;
713     RopeHandle m_name;
714     union {
715       struct {
716 	Uint32 m_name_len;
717 	const char * m_name_ptr;
718 	RopePool * m_pool;
719       } m_key;
720       Uint32 nextPool;
721       Uint32 nextList;
722     };
723 
724     // SchemaOp -> DictObject -> SchemaTrans
725     Uint32 m_trans_key;
726     Uint32 m_op_ref_count;
727 
728     // HashedById
729     Uint32 nextHash_by_id;
730     Uint32 prevHash_by_id;
hashValue_by_idDbdict::DictObject731     Uint32 hashValue_by_id() const { return m_id; }
equal_by_idDbdict::DictObject732     bool equal_by_id(DictObject const& obj) const {
733       bool isTrigger = DictTabInfo::isTrigger(m_type);
734       bool objIsTrigger = DictTabInfo::isTrigger(obj.m_type);
735       return (isTrigger == objIsTrigger) &&
736              (obj.m_id == m_id);
737     }
738 
739     // HashedByName
740     Uint32 nextHash_by_name;
741     Uint32 prevHash_by_name;
hashValue_by_nameDbdict::DictObject742     Uint32 hashValue_by_name() const { return m_name.hashValue(); }
equal_by_nameDbdict::DictObject743     bool equal_by_name(DictObject const& obj) const {
744       if(obj.hashValue_by_name() == hashValue_by_name()){
745 	ConstRope r(* m_key.m_pool, obj.m_name);
746 	return r.compare(m_key.m_name_ptr, m_key.m_name_len) == 0;
747       }
748       return false;
749     }
750 
751 #ifdef VM_TRACE
752     void print(NdbOut&) const;
753 #endif
754   };
755 
756   typedef Ptr<DictObject> DictObjectPtr;
757   typedef ArrayPool<DictObject> DictObject_pool;
758   typedef DLMHashTable<DictObject_pool, DictObject, HashedByName<DictObject> > DictObjectName_hash;
759   typedef DLMHashTable<DictObject_pool, DictObject, HashedById<DictObject> > DictObjectId_hash;
760   typedef SLList<DictObject> DictObject_list;
761 
762   DictObjectName_hash c_obj_name_hash; // Name (not temporary TableRecords)
763   DictObjectId_hash c_obj_id_hash; // Schema file id / Trigger id
764   DictObject_pool c_obj_pool;
765   RSS_AP_SNAPSHOT(c_obj_pool);
766 
find_object(DictObjectPtr & obj,Ptr<T> & object,Uint32 id)767   template<typename T> bool find_object(DictObjectPtr& obj, Ptr<T>& object, Uint32 id)
768   {
769     if (!find_object(obj, id))
770     {
771       object.setNull();
772       return false;
773     }
774     if (!T::isCompatible(obj.p->m_type))
775     {
776       object.setNull();
777       return false;
778     }
779     get_pool(object).getPtr(object, obj.p->m_object_ptr_i);
780     return !object.isNull();
781   }
782 
find_object(Ptr<T> & object,Uint32 id)783   template<typename T> bool find_object(Ptr<T>& object, Uint32 id)
784   {
785     DictObjectPtr obj;
786     return find_object(obj, object, id);
787   }
788 
find_object(DictObjectPtr & obj,Ptr<TriggerRecord> & object,Uint32 id)789   bool find_object(DictObjectPtr& obj, Ptr<TriggerRecord>& object, Uint32 id)
790   {
791     if (!find_trigger_object(obj, id))
792     {
793       object.setNull();
794       return false;
795     }
796     get_pool(object).getPtr(object, obj.p->m_object_ptr_i);
797     return !object.isNull();
798   }
799 
find_object(DictObjectPtr & object,Uint32 id)800   bool find_object(DictObjectPtr& object, Uint32 id)
801   {
802     DictObject key;
803     key.m_id = id;
804     key.m_type = 0; // Not a trigger atleast
805     bool ok = c_obj_id_hash.find(object, key);
806     return ok;
807   }
808 
find_trigger_object(DictObjectPtr & object,Uint32 id)809   bool find_trigger_object(DictObjectPtr& object, Uint32 id)
810   {
811     DictObject key;
812     key.m_id = id;
813     key.m_type = DictTabInfo::HashIndexTrigger; // A trigger type
814     bool ok = c_obj_id_hash.find(object, key);
815     return ok;
816   }
817 
link_object(DictObjectPtr obj,Ptr<T> object)818   template<typename T> bool link_object(DictObjectPtr obj, Ptr<T> object)
819   {
820     if (!T::isCompatible(obj.p->m_type))
821     {
822       return false;
823     }
824     obj.p->m_object_ptr_i = object.i;
825     object.p->m_obj_ptr_i = obj.i;
826     return true;
827   }
828 
829   // 1
get_object(const char * name)830   DictObject * get_object(const char * name){
831     return get_object(name, Uint32(strlen(name) + 1));
832   }
833 
get_object(const char * name,Uint32 len)834   DictObject * get_object(const char * name, Uint32 len){
835     return get_object(name, len, LocalRope::hash(name, len));
836   }
837 
838   DictObject * get_object(const char * name, Uint32 len, Uint32 hash);
839 
840   //2
get_object(DictObjectPtr & obj_ptr,const char * name)841   bool get_object(DictObjectPtr& obj_ptr, const char * name){
842     return get_object(obj_ptr, name, Uint32(strlen(name) + 1));
843   }
844 
get_object(DictObjectPtr & obj_ptr,const char * name,Uint32 len)845   bool get_object(DictObjectPtr& obj_ptr, const char * name, Uint32 len){
846     return get_object(obj_ptr, name, len, LocalRope::hash(name, len));
847   }
848 
849   bool get_object(DictObjectPtr&, const char* name, Uint32 len, Uint32 hash);
850 
release_object(Uint32 obj_ptr_i)851   void release_object(Uint32 obj_ptr_i){
852     release_object(obj_ptr_i, c_obj_pool.getPtr(obj_ptr_i));
853   }
854 
855   void release_object(Uint32 obj_ptr_i, DictObject* obj_ptr_p);
856 
857   void increase_ref_count(Uint32 obj_ptr_i);
858   void decrease_ref_count(Uint32 obj_ptr_i);
859 
860 public:
861   Dbdict(Block_context& ctx);
862   virtual ~Dbdict();
863 
864 private:
865   BLOCK_DEFINES(Dbdict);
866 
867   // Signal receivers
868   void execDICTSTARTREQ(Signal* signal);
869 
870   void execGET_TABINFOREQ(Signal* signal);
871   void execGET_TABLEDID_REQ(Signal* signal);
872   void execGET_TABINFOREF(Signal* signal);
873   void execGET_TABINFO_CONF(Signal* signal);
874   void execCONTINUEB(Signal* signal);
875 
876   void execDUMP_STATE_ORD(Signal* signal);
877   void execDBINFO_SCANREQ(Signal* signal);
878   void execHOT_SPAREREP(Signal* signal);
879   void execDIADDTABCONF(Signal* signal);
880   void execDIADDTABREF(Signal* signal);
881   void execTAB_COMMITCONF(Signal* signal);
882   void execTAB_COMMITREF(Signal* signal);
883   void execGET_SCHEMA_INFOREQ(Signal* signal);
884   void execSCHEMA_INFO(Signal* signal);
885   void execSCHEMA_INFOCONF(Signal* signal);
886   void execREAD_NODESCONF(Signal* signal);
887   void execFSCLOSECONF(Signal* signal);
888   void execFSOPENCONF(Signal* signal);
889   void execFSOPENREF(Signal* signal);
890   void execFSREADCONF(Signal* signal);
891   void execFSREADREF(Signal* signal);
892   void execFSWRITECONF(Signal* signal);
893   void execNDB_STTOR(Signal* signal);
894   void execREAD_CONFIG_REQ(Signal* signal);
895   void execSTTOR(Signal* signal);
896   void execTC_SCHVERCONF(Signal* signal);
897   void execNODE_FAILREP(Signal* signal);
898 
899   void send_nf_complete_rep(Signal* signal, const NodeFailRep*);
900 
901   void execINCL_NODEREQ(Signal* signal);
902   void execAPI_FAILREQ(Signal* signal);
903 
904   void execWAIT_GCP_REF(Signal* signal);
905   void execWAIT_GCP_CONF(Signal* signal);
906 
907   void execLIST_TABLES_REQ(Signal* signal);
908 
909   // Index signals
910   void execCREATE_INDX_REQ(Signal* signal);
911   void execCREATE_INDX_IMPL_CONF(Signal* signal);
912   void execCREATE_INDX_IMPL_REF(Signal* signal);
913 
914   void execALTER_INDX_REQ(Signal* signal);
915   void execALTER_INDX_CONF(Signal* signal);
916   void execALTER_INDX_REF(Signal* signal);
917   void execALTER_INDX_IMPL_CONF(Signal* signal);
918   void execALTER_INDX_IMPL_REF(Signal* signal);
919 
920   void execCREATE_TABLE_CONF(Signal* signal);
921   void execCREATE_TABLE_REF(Signal* signal);
922 
923   void execDROP_INDX_REQ(Signal* signal);
924   void execDROP_INDX_IMPL_CONF(Signal* signal);
925   void execDROP_INDX_IMPL_REF(Signal* signal);
926 
927   void execDROP_TABLE_CONF(Signal* signal);
928   void execDROP_TABLE_REF(Signal* signal);
929 
930   void execBUILDINDXREQ(Signal* signal);
931   void execBUILDINDXCONF(Signal* signal);
932   void execBUILDINDXREF(Signal* signal);
933   void execBUILD_INDX_IMPL_CONF(Signal* signal);
934   void execBUILD_INDX_IMPL_REF(Signal* signal);
935 
936   void execBACKUP_LOCK_TAB_REQ(Signal*);
937 
938   // Util signals used by Event code
939   void execUTIL_PREPARE_CONF(Signal* signal);
940   void execUTIL_PREPARE_REF (Signal* signal);
941   void execUTIL_EXECUTE_CONF(Signal* signal);
942   void execUTIL_EXECUTE_REF (Signal* signal);
943   void execUTIL_RELEASE_CONF(Signal* signal);
944   void execUTIL_RELEASE_REF (Signal* signal);
945 
946 
947   // Event signals from API
948   void execCREATE_EVNT_REQ (Signal* signal);
949   void execCREATE_EVNT_CONF(Signal* signal);
950   void execCREATE_EVNT_REF (Signal* signal);
951 
952   void execDROP_EVNT_REQ (Signal* signal);
953 
954   void execSUB_START_REQ (Signal* signal);
955   void execSUB_START_CONF (Signal* signal);
956   void execSUB_START_REF (Signal* signal);
957 
958   void execSUB_STOP_REQ (Signal* signal);
959   void execSUB_STOP_CONF (Signal* signal);
960   void execSUB_STOP_REF (Signal* signal);
961 
962   // Event signals from SUMA
963 
964   void execCREATE_SUBID_CONF(Signal* signal);
965   void execCREATE_SUBID_REF (Signal* signal);
966 
967   void execSUB_CREATE_CONF(Signal* signal);
968   void execSUB_CREATE_REF (Signal* signal);
969 
970   void execSUB_REMOVE_REQ(Signal* signal);
971   void execSUB_REMOVE_CONF(Signal* signal);
972   void execSUB_REMOVE_REF(Signal* signal);
973 
974   // Trigger signals
975   void execCREATE_TRIG_REQ(Signal* signal);
976   void execCREATE_TRIG_CONF(Signal* signal);
977   void execCREATE_TRIG_REF(Signal* signal);
978   void execALTER_TRIG_REQ(Signal* signal);
979   void execALTER_TRIG_CONF(Signal* signal);
980   void execALTER_TRIG_REF(Signal* signal);
981   void execDROP_TRIG_REQ(Signal* signal);
982   void execDROP_TRIG_CONF(Signal* signal);
983   void execDROP_TRIG_REF(Signal* signal);
984   // from other blocks
985   void execCREATE_TRIG_IMPL_CONF(Signal* signal);
986   void execCREATE_TRIG_IMPL_REF(Signal* signal);
987   void execDROP_TRIG_IMPL_CONF(Signal* signal);
988   void execDROP_TRIG_IMPL_REF(Signal* signal);
989 
990   void execDROP_TABLE_REQ(Signal* signal);
991 
992   void execPREP_DROP_TAB_REQ(Signal* signal);
993   void execPREP_DROP_TAB_REF(Signal* signal);
994   void execPREP_DROP_TAB_CONF(Signal* signal);
995 
996   void execDROP_TAB_REF(Signal* signal);
997   void execDROP_TAB_CONF(Signal* signal);
998 
999   void execCREATE_TABLE_REQ(Signal* signal);
1000   void execALTER_TABLE_REQ(Signal* signal);
1001 
1002   Uint32 get_fragmentation(Signal*, Uint32 tableId);
1003   Uint32 create_fragmentation(Signal* signal, TableRecordPtr,
1004                               const Uint16*, Uint32 cnt,
1005                               Uint32 flags = 0);
1006   void execCREATE_FRAGMENTATION_REQ(Signal*);
1007   void execCREATE_FRAGMENTATION_REF(Signal*);
1008   void execCREATE_FRAGMENTATION_CONF(Signal*);
1009   void execCREATE_TAB_REQ(Signal* signal);
1010   void execADD_FRAGREQ(Signal* signal);
1011   void execLQHFRAGREF(Signal* signal);
1012   void execLQHFRAGCONF(Signal* signal);
1013   void execLQHADDATTREF(Signal* signal);
1014   void execLQHADDATTCONF(Signal* signal);
1015   void execCREATE_TAB_REF(Signal* signal);
1016   void execCREATE_TAB_CONF(Signal* signal);
1017   void execALTER_TAB_REF(Signal* signal);
1018   void execALTER_TAB_CONF(Signal* signal);
1019   void execALTER_TABLE_REF(Signal* signal);
1020   void execALTER_TABLE_CONF(Signal* signal);
1021   bool check_ndb_versions() const;
1022   int check_sender_version(const Signal* signal, Uint32 version) const;
1023 
1024 
1025   void execCREATE_FILE_REQ(Signal* signal);
1026   void execCREATE_FILEGROUP_REQ(Signal* signal);
1027   void execDROP_FILE_REQ(Signal* signal);
1028   void execDROP_FILEGROUP_REQ(Signal* signal);
1029 
1030   // Internal
1031   void execCREATE_FILE_IMPL_REF(Signal* signal);
1032   void execCREATE_FILE_IMPL_CONF(Signal* signal);
1033   void execCREATE_FILEGROUP_IMPL_REF(Signal* signal);
1034   void execCREATE_FILEGROUP_IMPL_CONF(Signal* signal);
1035   void execDROP_FILE_IMPL_REF(Signal* signal);
1036   void execDROP_FILE_IMPL_CONF(Signal* signal);
1037   void execDROP_FILEGROUP_IMPL_REF(Signal* signal);
1038   void execDROP_FILEGROUP_IMPL_CONF(Signal* signal);
1039 
1040   void execSCHEMA_TRANS_BEGIN_REQ(Signal* signal);
1041   void execSCHEMA_TRANS_BEGIN_CONF(Signal* signal);
1042   void execSCHEMA_TRANS_BEGIN_REF(Signal* signal);
1043   void execSCHEMA_TRANS_END_REQ(Signal* signal);
1044   void execSCHEMA_TRANS_END_CONF(Signal* signal);
1045   void execSCHEMA_TRANS_END_REF(Signal* signal);
1046   void execSCHEMA_TRANS_END_REP(Signal* signal);
1047   void execSCHEMA_TRANS_IMPL_REQ(Signal* signal);
1048   void execSCHEMA_TRANS_IMPL_CONF(Signal* signal);
1049   void execSCHEMA_TRANS_IMPL_REF(Signal* signal);
1050 
1051   void execDICT_LOCK_REQ(Signal* signal);
1052   void execDICT_UNLOCK_ORD(Signal* signal);
1053 
1054   void execDICT_TAKEOVER_REQ(Signal* signal);
1055   void execDICT_TAKEOVER_REF(Signal* signal);
1056   void execDICT_TAKEOVER_CONF(Signal* signal);
1057 
1058   // ordered index statistics
1059   void execINDEX_STAT_REQ(Signal* signal);
1060   void execINDEX_STAT_CONF(Signal* signal);
1061   void execINDEX_STAT_REF(Signal* signal);
1062   void execINDEX_STAT_IMPL_CONF(Signal* signal);
1063   void execINDEX_STAT_IMPL_REF(Signal* signal);
1064   void execINDEX_STAT_REP(Signal* signal);
1065 
1066   /*
1067    *  2.4 COMMON STORED VARIABLES
1068    */
1069 
1070   /**
1071    * This record stores all the state needed
1072    * when the schema page is being sent to other nodes
1073    ***************************************************************************/
1074   struct SendSchemaRecord {
1075     /** Number of words of schema data */
1076     Uint32 noOfWords;
1077     /** Page Id of schema data */
1078     Uint32 pageId;
1079 
1080     Uint32 nodeId;
1081     SignalCounter m_SCHEMAINFO_Counter;
1082 
1083     Uint32 noOfWordsCurrentlySent;
1084     Uint32 noOfSignalsSentSinceDelay;
1085 
1086     bool inUse;
1087   };
1088   SendSchemaRecord c_sendSchemaRecord;
1089 
1090   /**
1091    * This record stores all the state needed
1092    * when a table file is being read from disk
1093    ****************************************************************************/
1094   struct ReadTableRecord {
1095     /** Number of Pages */
1096     Uint32 no_of_words;
1097     /** Page Id*/
1098     Uint32 pageId;
1099     /** Table Id of read table */
1100     Uint32 tableId;
1101 
1102     bool inUse;
1103     Callback m_callback;
1104   };
1105   ReadTableRecord c_readTableRecord;
1106 
1107   /**
1108    * This record stores all the state needed
1109    * when a table file is being written to disk
1110    ****************************************************************************/
1111   struct WriteTableRecord {
1112     /** Number of Pages */
1113     Uint32 no_of_words;
1114     /** Page Id*/
1115     Uint32 pageId;
1116     /** Table Files Handled, local state variable */
1117     Uint32 noOfTableFilesHandled;
1118     /** Table Id of written table */
1119     Uint32 tableId;
1120     /** State, indicates from where it was called */
1121     enum TableWriteState {
1122       IDLE = 0,
1123       WRITE_ADD_TABLE_MASTER = 1,
1124       WRITE_ADD_TABLE_SLAVE = 2,
1125       WRITE_RESTART_FROM_MASTER = 3,
1126       WRITE_RESTART_FROM_OWN = 4,
1127       TWR_CALLBACK = 5
1128     };
1129     TableWriteState tableWriteState;
1130     Callback m_callback;
1131   };
1132   WriteTableRecord c_writeTableRecord;
1133 
1134   /**
1135    * This record stores all the state needed
1136    * when a schema file is being read from disk
1137    ****************************************************************************/
1138   struct ReadSchemaRecord {
1139     /** Page Id of schema page */
1140     Uint32 pageId;
1141     /** First page to read */
1142     Uint32 firstPage;
1143     /** Number of pages to read */
1144     Uint32 noOfPages;
1145     /** State, indicates from where it was called */
1146     enum SchemaReadState {
1147       IDLE = 0,
1148       INITIAL_READ_HEAD = 1,
1149       INITIAL_READ = 2
1150     };
1151     SchemaReadState schemaReadState;
1152   };
1153   ReadSchemaRecord c_readSchemaRecord;
1154 
1155   /**
1156    * This record stores all the state needed
1157    * when a schema file is being written to disk
1158    ****************************************************************************/
1159   struct WriteSchemaRecord {
1160     /** Page Id of schema page */
1161     Uint32 pageId;
1162     /** Rewrite entire file */
1163     Uint32 newFile;
1164     /** First page to write */
1165     Uint32 firstPage;
1166     /** Number of pages to write */
1167     Uint32 noOfPages;
1168     /** Schema Files Handled, local state variable */
1169     Uint32 noOfSchemaFilesHandled;
1170 
1171     bool inUse;
1172     Callback m_callback;
1173   };
1174   WriteSchemaRecord c_writeSchemaRecord;
1175 
1176   /**
1177    * This record stores all the information needed
1178    * when a file is being read from disk
1179    ****************************************************************************/
1180   struct RestartRecord {
1181     /**    Global check point identity       */
1182     Uint32 gciToRestart;
1183 
1184     /**    The active table at restart process */
1185     Uint32 activeTable;
1186 
1187     /**    The active table at restart process */
1188     BlockReference returnBlockRef;
1189     Uint32 m_senderData;
1190 
1191     Uint32 m_pass;     // 0 tablespaces/logfilegroups, 1 tables, 2 indexes
1192     Uint32 m_end_pass; //
1193     const char * m_start_banner;
1194     const char * m_end_banner;
1195 
1196     Uint32 m_tx_ptr_i;
1197     Uint32 m_op_cnt;
1198     SchemaFile::TableEntry m_entry;
1199   };
1200   RestartRecord c_restartRecord;
1201 
1202   /**
1203    * This record stores all the information needed
1204    * when a file is being read from disk
1205    ****************************************************************************/
1206   struct RetrieveRecord {
RetrieveRecordDbdict::RetrieveRecord1207     RetrieveRecord():
1208       busyState(false) {};
1209 
1210     /**    Only one retrieve table definition at a time       */
1211     bool busyState;
1212 
1213     /**    Block Reference of retriever       */
1214     BlockReference blockRef;
1215 
1216     /**    Id of retriever       */
1217     Uint32 m_senderData;
1218 
1219     /**    Table id of retrieved table       */
1220     Uint32 tableId;
1221 
1222     Uint32 m_table_type;
1223 
1224     /**    Starting page to retrieve data from   */
1225     Uint32 retrievePage;
1226 
1227     /**    Number of pages retrieved   */
1228     Uint32 retrievedNoOfPages;
1229 
1230     /**    Number of words retrieved   */
1231     Uint32 retrievedNoOfWords;
1232 
1233     /**    Number of words sent currently   */
1234     Uint32 currentSent;
1235 
1236     /**
1237      * Long signal stuff
1238      */
1239     bool m_useLongSig;
1240 
1241     Uint32 schemaTransId;
1242     Uint32 requestType;
1243   };
1244   RetrieveRecord c_retrieveRecord;
1245 
1246   class GetTabInfoReqQueue
1247   {
1248   public:
1249     /**
1250      * GetTabInfoReqQueue
1251      *
1252      * This is a queue of GetTabInfoReq signals
1253      * It queues signals from internal (other data nodes)
1254      * and external (NdbApi clients) sources.
1255      * It gives preference to internal requests, but avoids
1256      * starvation.
1257      * Signals are queued using SegmentLists - using
1258      * SegmentedSections to implement a FIFO queue.
1259      * There is an internal requests list and an
1260      * external requests lists.
1261      * To ensure that internal requests can proceed
1262      * during overload, the internal segment list uses
1263      * Segments from a reserved sub pool.
1264      * The external requests use segments from the
1265      * global pool, which may not be able to provide
1266      * segments when the system is overloaded.
1267      * For this reason, an external request can fail
1268      * to be enqueued, resulting in a BUSY response,
1269      * whereas an internal request should never encounter
1270      * this.
1271      * Internal requests are fully catered for as they have
1272      * bounded concurrency, and probably higher priority.
1273      * External requests currently have almost unbounded
1274      * concurrency.
1275      */
GetTabInfoReqQueue(SegmentUtils & pool)1276     explicit GetTabInfoReqQueue(SegmentUtils& pool):
1277       m_internalSegmentPool(pool),
1278       m_internalQueue(m_internalQueueHead,
1279                       m_internalSegmentPool),
1280       m_consecutiveInternalReqCount(0),
1281       m_externalSegmentPool(pool),
1282       m_externalQueue(m_externalQueueHead,
1283                       m_externalSegmentPool),
1284       m_jamBuffer(0)
1285       {};
1286 
init(EmulatedJamBuffer * jamBuff)1287     bool init(EmulatedJamBuffer* jamBuff)
1288     {
1289       m_jamBuffer = jamBuff;
1290       return m_internalSegmentPool.init(InternalSegmentPoolSize,
1291                                         InternalSegmentPoolSize);
1292     }
1293 
1294     /**
1295      * isEmpty
1296      *
1297      * Are both queues empty
1298      */
isEmpty() const1299     bool isEmpty() const
1300     {
1301       return (m_internalQueue.isEmpty() &&
1302               m_externalQueue.isEmpty());
1303     };
1304 
1305     /**
1306      * tryEnqReq
1307      *
1308      * Try to enqueue a request on the indicated queue
1309      * Returns false if this was not possible
1310      */
tryEnqReq(bool internal,Signal * signal)1311     bool tryEnqReq(bool internal,
1312                    Signal* signal)
1313     {
1314       thrjam(m_jamBuffer);
1315       /* Put data inline in signal buffer for atomic enq */
1316       signal->theData[GetTabInfoReq::SignalLength] =
1317         signal->header.m_noOfSections;
1318 
1319       memcpy(&signal->theData[GetTabInfoReq::SignalLength+1],
1320              signal->m_sectionPtrI,
1321              3 * sizeof(Uint32));
1322 
1323       LocalSegmentList& reqQueue = internal?
1324         m_internalQueue:
1325         m_externalQueue;
1326 
1327       /* Check that we are allowed to queue another req */
1328       Uint32 maxReqs = 0;
1329 
1330       if (internal)
1331         maxReqs = MaxInternalReqs;
1332       else
1333         maxReqs = MaxExternalReqs;
1334 
1335       if (getNumReqs(reqQueue) >= maxReqs)
1336       {
1337         thrjam(m_jamBuffer);
1338         return false;
1339       }
1340 
1341       assert(ElementLen == 9);   /* Just in case someone adds words...*/
1342 
1343       if (reqQueue.enqWords(signal->theData,
1344                             ElementLen))
1345       {
1346         thrjam(m_jamBuffer);
1347         /* Detach section(s) */
1348         signal->header.m_noOfSections = 0;
1349         return true;
1350       }
1351 
1352       /* Enqueue failed */
1353       return false;
1354     }
1355 
1356     /**
1357      * deqReq
1358      *
1359      * Dequeue the next request to work on, setting up the Signal
1360      * object with signal data (and sections if appropriate)
1361      * Assumes that there is some next request to be processed.
1362      */
deqReq(Signal * signal)1363     bool deqReq(Signal* signal)
1364     {
1365       assert(signal->header.m_noOfSections == 0);
1366       assert(!isEmpty());
1367 
1368       LocalSegmentList& reqQueue = isInternalQueueNext()?
1369         m_internalQueue :
1370         m_externalQueue;
1371 
1372       assert(getNumReqs(reqQueue) > 0);
1373 
1374       Uint32 noOfSections;
1375 
1376       /* Restore signal context from queue...*/
1377       if (reqQueue.deqWords(signal->theData, GetTabInfoReq::SignalLength) &&
1378           reqQueue.deqWords(&noOfSections, 1) &&
1379           reqQueue.deqWords(signal->m_sectionPtrI, 3))
1380       {
1381         signal->header.m_noOfSections = (Uint8) noOfSections;
1382         return true;
1383       }
1384       return false;
1385     }
1386 
1387   private:
1388     /**
1389      * isInternalQueueNext
1390      *
1391      * Which queue should provide the next request
1392      * to work on
1393      */
isInternalQueueNext()1394     bool isInternalQueueNext()
1395     {
1396       thrjam(m_jamBuffer);
1397       /**
1398        * Prefer the internal request queue, unless we've already
1399        * had a number of those requests consecutively and an
1400        * external request is waiting.
1401        */
1402       if (!m_internalQueue.isEmpty())
1403       {
1404         thrjam(m_jamBuffer);
1405         if (m_externalQueue.isEmpty() ||
1406             m_consecutiveInternalReqCount <= MaxInternalPerExternal)
1407         {
1408           thrjam(m_jamBuffer);
1409           m_consecutiveInternalReqCount++;
1410           return true;  /* Use internal */
1411         }
1412       }
1413       m_consecutiveInternalReqCount = 0;
1414       return false;  /* Use external */
1415     }
1416 
1417     /**
1418      * getNumReqs
1419      *
1420      * Get the number of requests in the given queue
1421      */
getNumReqs(const LocalSegmentList & queue) const1422     Uint32 getNumReqs(const LocalSegmentList& queue) const
1423     {
1424       Uint32 qWordLen = queue.getLen();
1425       assert((qWordLen % ElementLen) == 0);
1426       return qWordLen / ElementLen;
1427     };
1428 
1429     /* Length of GetTabInfoReq queue elements */
1430     static const Uint32 ElementLen = GetTabInfoReq::SignalLength + 1 + 3;
1431 
1432     /**
1433      * Pessimistic estimate of worst-case internally sourced
1434      * GET_TABINFOREQ concurrency.
1435      * Needs updated if more concurrency or use cases are added
1436      */
1437     static const uint MaxInternalReqs =
1438                   MAX_NDB_NODES +                   /* restartCreateObj() forward to Master */
1439                   1 +                               /* SUMA SUB_CREATE_REQ */
1440                   (2 * MAX_NDBMT_LQH_THREADS) +     /* Backup - 1 LCP + 1 Backup per LDM instance */
1441                   1;                                /* Trix Index stat */
1442 
1443     /**
1444      * InternalSegmentPoolSize
1445      * Enough segments to take MaxInternalReqs,
1446      * + 1 to handle max offset within the first segment
1447      */
1448     static const Uint32 InternalSegmentPoolSize =
1449       (((MaxInternalReqs * ElementLen) + SectionSegment::DataLength - 1)/
1450        SectionSegment::DataLength ) + 1;
1451 
1452     /**
1453      * Internal waiters queue
1454      * Uses a reserved segment sub pool.
1455      * We keep a LocalSegmentList around permanently
1456      */
1457     SegmentSubPool m_internalSegmentPool;
1458     SegmentListHead m_internalQueueHead;
1459     LocalSegmentList m_internalQueue;
1460 
1461     /**
1462      * Avoid external request starvation
1463      */
1464     static const Uint32 MaxInternalPerExternal = 10;
1465     Uint32 m_consecutiveInternalReqCount;
1466 
1467     /**
1468      * External waiters queue
1469      * Uses global segment pool.
1470      *
1471      * Max of 1 req per node on average, can be
1472      * less in overload.
1473      */
1474     static const Uint32 MaxExternalReqs = MAX_NODES;
1475     SegmentUtils& m_externalSegmentPool;
1476     SegmentListHead m_externalQueueHead;
1477     LocalSegmentList m_externalQueue;
1478 
1479 
1480     EmulatedJamBuffer* m_jamBuffer;
1481   };
1482 
1483   GetTabInfoReqQueue c_gettabinforeq_q;
1484 
1485   /**
1486    * This record stores all the information needed
1487    * when a file is being read from disk
1488    *
1489    * This is the info stored in one entry of the schema
1490    * page. Each table has 4 words of info.
1491    * Word 1: Schema version (upper 16 bits)
1492    *         Table State (lower 16 bits)
1493    * Word 2: Number of pages of table description
1494    * Word 3: Global checkpoint id table was created
1495    * Word 4: Currently zero
1496    ****************************************************************************/
1497   struct SchemaRecord {
1498     enum
1499     {
1500       NEW_SCHEMA_FILE = 0, // Index in c_schemaFile
1501       OLD_SCHEMA_FILE = 1
1502     };
1503 
1504     /**    Schema file first page (0)   */
1505     Uint32 schemaPage;
1506 
1507     /**    Old Schema file first page (used at node restart)    */
1508     Uint32 oldSchemaPage;
1509 
1510     Callback m_callback;
1511   };
1512   SchemaRecord c_schemaRecord;
1513 
1514   /*
1515    * Schema file, list of schema pages.  Use an array until a pool
1516    * exists and NDBFS interface can use it.
1517    */
1518   struct XSchemaFile {
1519     SchemaFile* schemaPage;
1520     Uint32 noOfPages;
1521   };
1522   // 0-normal 1-old
1523   XSchemaFile c_schemaFile[2];
1524 
1525   void initSchemaFile(XSchemaFile *, Uint32 firstPage, Uint32 lastPage,
1526                       bool initEntries);
1527   void resizeSchemaFile(XSchemaFile * xsf, Uint32 noOfPages);
1528   void modifySchemaFileAtRestart(XSchemaFile * xsf);
1529   void computeChecksum(XSchemaFile *, Uint32 pageNo);
1530   bool validateChecksum(const XSchemaFile *);
1531   SchemaFile::TableEntry * getTableEntry(Uint32 tableId);
1532   SchemaFile::TableEntry * getTableEntry(XSchemaFile *, Uint32 tableId);
1533   const SchemaFile::TableEntry * getTableEntry(const XSchemaFile*, Uint32);
1534 
1535   Uint32 computeChecksum(const Uint32 * src, Uint32 len);
1536 
1537   void doGET_TABINFOREQ(Signal* signal);
1538 
1539 
1540   /* ----------------------------------------------------------------------- */
1541   // Node References
1542   /* ----------------------------------------------------------------------- */
1543   Uint16 c_masterNodeId;
1544 
1545   /* ----------------------------------------------------------------------- */
1546   // Various current system properties
1547   /* ----------------------------------------------------------------------- */
1548   Uint16 c_numberNode;
1549   Uint16 c_noHotSpareNodes;
1550   Uint16 c_noNodesFailed;
1551   Uint32 c_failureNr;
1552 
1553   /* ----------------------------------------------------------------------- */
1554   // State variables
1555   /* ----------------------------------------------------------------------- */
1556 
1557   struct PackTable {
1558 
1559     enum PackTableState {
1560       PTS_IDLE = 0,
1561       PTS_GET_TAB = 3
1562     } m_state;
1563 
1564   } c_packTable;
1565 
1566   Uint32 c_startPhase;
1567   Uint32 c_restartType;
1568   bool   c_initialStart;
1569   bool   c_systemRestart;
1570   bool   c_nodeRestart;
1571   bool   c_initialNodeRestart;
1572   Uint32 c_tabinfoReceived;
1573   /**
1574    * This flag indicates that a dict takeover is in progress, specifically
1575    * that the new master has outstanding DICT_TAKEOVER_REQ messages. The flag
1576    * is used to prevent client from starting (or ending) transactions during
1577    * takeover.
1578    */
1579   bool   c_takeOverInProgress;
1580 
1581   /**
1582    * Temporary structure used when parsing table info
1583    */
1584   struct ParseDictTabInfoRecord {
ParseDictTabInfoRecordDbdict::ParseDictTabInfoRecord1585     ParseDictTabInfoRecord() { tablePtr.setNull();}
1586     DictTabInfo::RequestType requestType;
1587     Uint32 errorCode;
1588     Uint32 errorLine;
1589 
1590     SimpleProperties::UnpackStatus status;
1591     Uint32 errorKey;
1592     TableRecordPtr tablePtr;
1593   };
1594 
1595   // Misc helpers
1596 
1597   template <Uint32 sz>
1598   inline bool
copyRope(RopeHandle & rh_dst,const RopeHandle & rh_src)1599   copyRope(RopeHandle& rh_dst, const RopeHandle& rh_src)
1600   {
1601     char buf[sz];
1602     LocalRope r_dst(c_rope_pool, rh_dst);
1603     ConstRope r_src(c_rope_pool, rh_src);
1604     ndbrequire(r_src.size() <= sz);
1605     r_src.copy(buf);
1606     bool ok = r_dst.assign(buf, r_src.size());
1607     return ok;
1608   }
1609 
1610 #ifdef VM_TRACE
1611   template <Uint32 sz>
1612   inline const char*
copyRope(const RopeHandle & rh)1613   copyRope(const RopeHandle& rh)
1614   {
1615     static char buf[2][sz];
1616     static int i = 0;
1617     ConstRope r(c_rope_pool, rh);
1618     char* str = buf[i++ % 2];
1619     r.copy(str);
1620     return str;
1621   }
1622 #endif
1623 
1624   // Operation records
1625 
1626   /**
1627    * Common part of operation records.  Uses KeyTable2.  Note that each
1628    * seize/release invokes ctor/dtor automatically.
1629    */
1630   struct OpRecordCommon {
OpRecordCommonDbdict::OpRecordCommon1631     OpRecordCommon() {}
1632     Uint32 key;         // key shared between master and slaves
1633     Uint32 nextHash;
1634     Uint32 prevHash;
hashValueDbdict::OpRecordCommon1635     Uint32 hashValue() const {
1636       return key;
1637     }
equalDbdict::OpRecordCommon1638     bool equal(const OpRecordCommon& rec) const {
1639       return key == rec.key;
1640     }
1641   };
1642 
1643   // MODULE: SchemaTrans
1644 
1645   struct SchemaOp;
1646   struct SchemaTrans;
1647   struct TxHandle;
1648   typedef Ptr<SchemaOp> SchemaOpPtr;
1649   typedef Ptr<SchemaTrans> SchemaTransPtr;
1650   typedef Ptr<TxHandle> TxHandlePtr;
1651 
1652   // ErrorInfo
1653 
1654   struct ErrorInfo {
1655     Uint32 errorCode;
1656     Uint32 errorLine;
1657     Uint32 errorNodeId;
1658     Uint32 errorCount;
1659     // for CreateTable
1660     Uint32 errorStatus;
1661     Uint32 errorKey;
1662     char errorObjectName[MAX_TAB_NAME_SIZE];
ErrorInfoDbdict::ErrorInfo1663     ErrorInfo() {
1664       errorCode = 0;
1665       errorLine = 0;
1666       errorNodeId = 0;
1667       errorCount = 0;
1668       errorStatus = 0;
1669       errorKey = 0;
1670       errorObjectName[0] = 0;
1671     }
1672     void print(NdbOut&) const;
1673   private:
1674     ErrorInfo& operator=(const ErrorInfo&);
1675   };
1676 
1677   void setError(ErrorInfo&,
1678                 Uint32 code,
1679                 Uint32 line,
1680                 Uint32 nodeId = 0,
1681                 Uint32 status = 0,
1682                 Uint32 key = 0,
1683                 const char * name = 0);
1684 
1685   void setError(ErrorInfo&,
1686                 Uint32 code,
1687                 Uint32 line,
1688                 const char * name);
1689 
1690   void setError(ErrorInfo&, const ErrorInfo&);
1691   void setError(ErrorInfo&, const ParseDictTabInfoRecord&);
1692 
1693   void setError(SchemaOpPtr, Uint32 code, Uint32 line, Uint32 nodeId = 0);
1694   void setError(SchemaOpPtr, const ErrorInfo&);
1695 
1696   void setError(SchemaTransPtr, Uint32 code, Uint32 line, Uint32 nodeId = 0);
1697   void setError(SchemaTransPtr, const ErrorInfo&);
1698 
1699   void setError(TxHandlePtr, Uint32 code, Uint32 line, Uint32 nodeId = 0);
1700   void setError(TxHandlePtr, const ErrorInfo&);
1701 
1702   template <class Ref>
1703   inline void
setError(ErrorInfo & e,const Ref * ref)1704   setError(ErrorInfo& e, const Ref* ref) {
1705     setError(e, ref->errorCode, ref->errorLine, ref->errorNodeId);
1706   }
1707 
1708   template <class Ref>
1709   inline void
getError(const ErrorInfo & e,Ref * ref)1710   getError(const ErrorInfo& e, Ref* ref) {
1711     ref->errorCode = e.errorCode;
1712     ref->errorLine = e.errorLine;
1713     ref->errorNodeId = e.errorNodeId;
1714     ref->masterNodeId = c_masterNodeId;
1715   }
1716 
1717   bool hasError(const ErrorInfo&);
1718 
1719   void resetError(ErrorInfo&);
1720   void resetError(SchemaOpPtr);
1721   void resetError(SchemaTransPtr);
1722   void resetError(TxHandlePtr);
1723 
1724   // OpInfo
1725 
1726   struct OpInfo {
1727     const char m_opType[4]; // e.g. CTa for CreateTable. TODO: remove. use only m_magic?
1728     Uint32 m_magic;
1729     Uint32 m_impl_req_gsn;
1730     Uint32 m_impl_req_length;
1731 
1732     // seize / release type-specific Data record
1733     bool (Dbdict::*m_seize)(SchemaOpPtr);
1734     void (Dbdict::*m_release)(SchemaOpPtr);
1735 
1736     // parse phase
1737     void (Dbdict::*m_parse)(Signal*, bool master,
1738                             SchemaOpPtr, SectionHandle&, ErrorInfo&);
1739     bool (Dbdict::*m_subOps)(Signal*, SchemaOpPtr);
1740     void (Dbdict::*m_reply)(Signal*, SchemaOpPtr, ErrorInfo);
1741 
1742     // run phases
1743     void (Dbdict::*m_prepare)(Signal*, SchemaOpPtr);
1744     void (Dbdict::*m_commit)(Signal*, SchemaOpPtr);
1745     void (Dbdict::*m_complete)(Signal*, SchemaOpPtr);
1746     // abort mode
1747     void (Dbdict::*m_abortParse)(Signal*, SchemaOpPtr);
1748     void (Dbdict::*m_abortPrepare)(Signal*, SchemaOpPtr);
1749   };
1750 
1751   // all OpInfo records
1752   static const OpInfo* g_opInfoList[];
1753   const OpInfo* findOpInfo(Uint32 gsn);
1754 
1755   // OpRec
1756 
1757   struct OpRec
1758   {
1759     char m_opType[4]; // TODO: remove. only use m_magic
1760 
1761     Uint32 nextPool;
1762 
1763     Uint32 m_magic;
1764 
1765     // reference to the static member in subclass
1766     const OpInfo& m_opInfo;
1767 
1768     // pointer to internal signal in subclass instance
1769     Uint32* const m_impl_req_data;
1770 
1771     // DictObject operated on
1772     Uint32 m_obj_ptr_i;
1773 
OpRecDbdict::OpRec1774     OpRec(const OpInfo& info, Uint32* impl_req_data) :
1775       m_magic(info.m_magic),
1776       m_opInfo(info),
1777       m_impl_req_data(impl_req_data) {
1778       m_obj_ptr_i = RNIL;
1779       memcpy(m_opType, m_opInfo.m_opType, 4);
1780     }
1781   };
1782   typedef Ptr<OpRec> OpRecPtr;
1783 
1784   /*
1785    * OpSection
1786    *
1787    * Signal sections are released in parse phase.  If necessary
1788    * they are first saved under schema op record.
1789    */
1790 
1791   enum { OpSectionSegmentSize = 127 };
1792   typedef
1793     LocalDataBuffer2<OpSectionSegmentSize, LocalArenaPoolImpl>
1794     OpSectionBuffer;
1795   typedef
1796     DataBuffer2<OpSectionSegmentSize, LocalArenaPoolImpl>::Head
1797     OpSectionBufferHead;
1798   typedef
1799     OpSectionBuffer::DataBufferPool
1800     OpSectionBufferPool;
1801   typedef
1802     DataBuffer2<OpSectionSegmentSize, LocalArenaPoolImpl>::ConstDataBufferIterator
1803     OpSectionBufferConstIterator;
1804 
1805   ArenaPool c_opSectionBufferPool;
1806 
1807   struct OpSection {
1808     OpSectionBufferHead m_head;
getSizeDbdict::OpSection1809     Uint32 getSize() const {
1810       return m_head.getSize();
1811     }
1812   };
1813 
1814   bool copyIn(OpSectionBufferPool&, OpSection&, const SegmentedSectionPtr&);
1815   bool copyIn(OpSectionBufferPool&, OpSection&, const Uint32* src, Uint32 srcSize);
1816   bool copyOut(OpSectionBufferPool&, const OpSection&, SegmentedSectionPtr&);
1817   bool copyOut(OpSectionBufferPool&, const OpSection&, Uint32* dst, Uint32 dstSize);
1818   bool copyOut(OpSectionBuffer & buffer, OpSectionBufferConstIterator & iter,
1819                Uint32 * dst, Uint32 len);
1820   void release(OpSectionBufferPool&, OpSection&);
1821 
1822   // SchemaOp
1823 
1824   struct SchemaOp {
1825     Uint32 nextPool;
1826 
1827     enum OpState
1828     {
1829       OS_INITIAL          = 0,
1830       OS_PARSE_MASTER     = 1,
1831       OS_PARSING          = 2,
1832       OS_PARSED           = 3,
1833       OS_PREPARING        = 4,
1834       OS_PREPARED         = 5,
1835       OS_ABORTING_PREPARE = 6,
1836       OS_ABORTED_PREPARE  = 7,
1837       OS_ABORTING_PARSE   = 8,
1838       //OS_ABORTED_PARSE    = 9,  // Not used, op released
1839       OS_COMMITTING       = 10,
1840       OS_COMMITTED        = 11,
1841       OS_COMPLETING       = 12,
1842       OS_COMPLETED        = 13
1843     };
1844 
1845     Uint32 m_state;
1846     /*
1847       Return the "weight" of an operation state, used to determine
1848       the absolute order of operations.
1849      */
weightDbdict::SchemaOp1850     static Uint32 weight(Uint32 state) {
1851       switch ((OpState) state) {
1852       case OS_INITIAL:
1853         return 0;
1854       case OS_PARSE_MASTER:
1855         return 1;
1856       case OS_PARSING:
1857         return 2;
1858       case OS_PARSED:
1859         return 5;
1860       case OS_PREPARING:
1861         return 6;
1862       case OS_PREPARED:
1863         return 9;
1864       case OS_ABORTING_PREPARE:
1865         return 8;
1866       case OS_ABORTED_PREPARE:
1867         return 7;
1868       case OS_ABORTING_PARSE:
1869         return 4;
1870       //case OS_ABORTED_PARSE    = 9,  // Not used, op released
1871         //return 3:
1872       case OS_COMMITTING:
1873         return 10;
1874       case OS_COMMITTED:
1875         return 11;
1876       case OS_COMPLETING:
1877         return 12;
1878       case OS_COMPLETED:
1879         return 13;
1880       }
1881       assert(false);
1882       return -1;
1883     }
1884     Uint32 m_restart;
1885     Uint32 op_key;
1886     Uint32 m_base_op_ptr_i;
1887     Uint32 nextHash;
1888     Uint32 prevHash;
hashValueDbdict::SchemaOp1889     Uint32 hashValue() const {
1890       return op_key;
1891     }
equalDbdict::SchemaOp1892     bool equal(const SchemaOp& rec) const {
1893       return op_key == rec.op_key;
1894     }
1895 
1896     Uint32 nextList;
1897     Uint32 prevList;
1898 
1899     // tx client or DICT master for recursive ops
1900     Uint32 m_clientRef;
1901     Uint32 m_clientData;
1902 
1903     // requestExtra and requestFlags from REQ and trans level
1904     Uint32 m_requestInfo;
1905 
1906     // the op belongs to this trans
1907     SchemaTransPtr m_trans_ptr;
1908 
1909     // type specific record (the other half of schema op)
1910     OpRecPtr m_oprec_ptr;
1911 
1912     // saved signal sections or other variable data
1913     OpSection m_section[3];
1914     Uint32 m_sections;
1915 
1916     // callback for use with sub-operations
1917     Callback m_callback;
1918 
1919     // link to an extra "helper" op and link back from it
1920     SchemaOpPtr m_oplnk_ptr;
1921     SchemaOpPtr m_opbck_ptr;
1922 
1923     // error always propagates to trans level
1924     ErrorInfo m_error;
1925 
1926     // Copy of original and current schema file entry
1927     Uint32 m_orig_entry_id;
1928     SchemaFile::TableEntry m_orig_entry;
1929 
1930     // magic is on when record is seized
1931     enum { DICT_MAGIC = ~RT_DBDICT_SCHEMA_OPERATION };
1932     Uint32 m_magic;
1933 
SchemaOpDbdict::SchemaOp1934     SchemaOp() {
1935       m_restart = 0;
1936       m_clientRef = 0;
1937       m_clientData = 0;
1938       m_requestInfo = 0;
1939       m_trans_ptr.setNull();
1940       m_oprec_ptr.setNull();
1941       m_sections = 0;
1942       m_callback.m_callbackFunction = 0;
1943       m_callback.m_callbackData = 0;
1944       m_oplnk_ptr.setNull();
1945       m_opbck_ptr.setNull();
1946       m_magic = DICT_MAGIC;
1947       m_base_op_ptr_i = RNIL;
1948 
1949       m_orig_entry_id = RNIL;
1950       m_orig_entry.init();
1951     }
1952 
SchemaOpDbdict::SchemaOp1953     SchemaOp(Uint32 the_op_key) {
1954       op_key = the_op_key;
1955     }
1956 
1957 #ifdef VM_TRACE
1958     void print(NdbOut&) const;
1959 #endif
1960   };
1961 
1962   typedef RecordPool<SchemaOp,ArenaPool> SchemaOp_pool;
1963   typedef DLMHashTable<SchemaOp_pool, SchemaOp> SchemaOp_hash;
1964   typedef DLFifoListImpl<SchemaOp_pool, SchemaOp, SchemaOp>::Head  SchemaOp_head;
1965   typedef LocalDLFifoListImpl<SchemaOp_pool, SchemaOp, SchemaOp> LocalSchemaOp_list;
1966 
1967   SchemaOp_pool c_schemaOpPool;
1968   SchemaOp_hash c_schemaOpHash;
1969 
1970   const OpInfo& getOpInfo(SchemaOpPtr op_ptr);
1971 
1972   // set or get the type specific record cast to the specific type
1973 
1974   template <class T>
1975   inline void
setOpRec(SchemaOpPtr op_ptr,const Ptr<T> t_ptr)1976   setOpRec(SchemaOpPtr op_ptr, const Ptr<T> t_ptr) {
1977     OpRecPtr& oprec_ptr = op_ptr.p->m_oprec_ptr;
1978     ndbrequire(!t_ptr.isNull());
1979     oprec_ptr.i = t_ptr.i;
1980     oprec_ptr.p = static_cast<OpRec*>(t_ptr.p);
1981     ndbrequire(memcmp(t_ptr.p->m_opType, T::g_opInfo.m_opType, 4) == 0);
1982   }
1983 
1984   template <class T>
1985   inline void
getOpRec(SchemaOpPtr op_ptr,Ptr<T> & t_ptr)1986   getOpRec(SchemaOpPtr op_ptr, Ptr<T>& t_ptr) {
1987     OpRecPtr oprec_ptr = op_ptr.p->m_oprec_ptr;
1988     ndbrequire(!oprec_ptr.isNull());
1989     t_ptr.i = oprec_ptr.i;
1990     t_ptr.p = static_cast<T*>(oprec_ptr.p);
1991     ndbrequire(memcmp(t_ptr.p->m_opType, T::g_opInfo.m_opType, 4) == 0);
1992   }
1993 
1994   // OpInfo m_seize, m_release
1995 
1996   template <class T>
1997   inline bool
seizeOpRec(SchemaOpPtr op_ptr)1998   seizeOpRec(SchemaOpPtr op_ptr) {
1999     OpRecPtr& oprec_ptr = op_ptr.p->m_oprec_ptr;
2000     RecordPool<T,ArenaPool>& pool = T::getPool(this);
2001     Ptr<T> t_ptr;
2002     if (pool.seize(op_ptr.p->m_trans_ptr.p->m_arena, t_ptr)) {
2003       new (t_ptr.p) T();
2004       setOpRec<T>(op_ptr, t_ptr);
2005       return true;
2006     }
2007     oprec_ptr.setNull();
2008     return false;
2009   }
2010 
2011   template <class T>
2012   inline void
releaseOpRec(SchemaOpPtr op_ptr)2013   releaseOpRec(SchemaOpPtr op_ptr) {
2014     OpRecPtr& oprec_ptr = op_ptr.p->m_oprec_ptr;
2015     RecordPool<T,ArenaPool>& pool = T::getPool(this);
2016     Ptr<T> t_ptr;
2017     getOpRec<T>(op_ptr, t_ptr);
2018     pool.release(t_ptr);
2019     oprec_ptr.setNull();
2020   }
2021 
2022   // seize / find / release, atomic on op rec + data rec
2023 
2024   bool seizeSchemaOp(SchemaTransPtr trans_ptr, SchemaOpPtr& op_ptr, Uint32 op_key, const OpInfo& info, bool linked=false);
2025 
2026   template <class T>
2027   inline bool
seizeSchemaOp(SchemaTransPtr trans_ptr,SchemaOpPtr & op_ptr,Uint32 op_key,bool linked)2028   seizeSchemaOp(SchemaTransPtr trans_ptr, SchemaOpPtr& op_ptr, Uint32 op_key, bool linked) {
2029     return seizeSchemaOp(trans_ptr, op_ptr, op_key, T::g_opInfo, linked);
2030   }
2031 
2032   template <class T>
2033   inline bool
seizeSchemaOp(SchemaTransPtr trans_ptr,SchemaOpPtr & op_ptr,Ptr<T> & t_ptr,Uint32 op_key)2034   seizeSchemaOp(SchemaTransPtr trans_ptr, SchemaOpPtr& op_ptr, Ptr<T>& t_ptr, Uint32 op_key) {
2035     if (seizeSchemaOp<T>(trans_ptr, op_ptr, op_key)) {
2036       getOpRec<T>(op_ptr, t_ptr);
2037       return true;
2038     }
2039     return false;
2040   }
2041 
2042   template <class T>
2043   inline bool
seizeSchemaOp(SchemaTransPtr trans_ptr,SchemaOpPtr & op_ptr,bool linked)2044   seizeSchemaOp(SchemaTransPtr trans_ptr, SchemaOpPtr& op_ptr, bool linked) {
2045     /*
2046       Store node id in high 8 bits to make op_key globally unique
2047      */
2048     Uint32 op_key =
2049       (getOwnNodeId() << 24) +
2050       ((c_opRecordSequence + 1) & 0x00FFFFFF);
2051     if (seizeSchemaOp<T>(trans_ptr, op_ptr, op_key, linked)) {
2052       c_opRecordSequence++;
2053       return true;
2054     }
2055     return false;
2056   }
2057 
2058   template <class T>
2059   inline bool
seizeSchemaOp(SchemaTransPtr trans_ptr,SchemaOpPtr & op_ptr,Ptr<T> & t_ptr,bool linked=false)2060   seizeSchemaOp(SchemaTransPtr trans_ptr, SchemaOpPtr& op_ptr, Ptr<T>& t_ptr, bool linked=false) {
2061     if (seizeSchemaOp<T>(trans_ptr, op_ptr, linked)) {
2062       getOpRec<T>(op_ptr, t_ptr);
2063       return true;
2064     }
2065     return false;
2066   }
2067 
2068   template <class T>
2069   inline bool
seizeLinkedSchemaOp(SchemaOpPtr op_ptr,SchemaOpPtr & oplnk_ptr,Ptr<T> & t_ptr)2070   seizeLinkedSchemaOp(SchemaOpPtr op_ptr, SchemaOpPtr& oplnk_ptr, Ptr<T>& t_ptr) {
2071     ndbrequire(op_ptr.p->m_oplnk_ptr.isNull());
2072     if (seizeSchemaOp<T>(op_ptr.p->m_trans_ptr, oplnk_ptr, true)) {
2073       op_ptr.p->m_oplnk_ptr = oplnk_ptr;
2074       oplnk_ptr.p->m_opbck_ptr = op_ptr;
2075       getOpRec<T>(oplnk_ptr, t_ptr);
2076       return true;
2077     }
2078     oplnk_ptr.setNull();
2079     return false;
2080   }
2081 
2082   bool findSchemaOp(SchemaOpPtr& op_ptr, Uint32 op_key);
2083 
2084   template <class T>
2085   inline bool
findSchemaOp(SchemaOpPtr & op_ptr,Ptr<T> & t_ptr,Uint32 op_key)2086   findSchemaOp(SchemaOpPtr& op_ptr, Ptr<T>& t_ptr, Uint32 op_key) {
2087     if (findSchemaOp(op_ptr, op_key)) {
2088       getOpRec(op_ptr, t_ptr);
2089       return true;
2090     }
2091     return false;
2092   }
2093 
2094   void releaseSchemaOp(SchemaOpPtr& op_ptr);
2095 
2096   // copy signal sections to schema op sections
2097   const OpSection& getOpSection(SchemaOpPtr, Uint32 ss_no);
2098   bool saveOpSection(SchemaOpPtr, SectionHandle&, Uint32 ss_no);
2099   bool saveOpSection(SchemaOpPtr, SegmentedSectionPtr ss_ptr, Uint32 ss_no);
2100   void releaseOpSection(SchemaOpPtr, Uint32 ss_no);
2101 
2102   // add operation to transaction OpList
2103   void addSchemaOp(SchemaOpPtr);
2104 
2105   void updateSchemaOpStep(SchemaTransPtr, SchemaOpPtr);
2106 
2107   // the link between SdhemaOp and DictObject (1-way now)
2108 
2109   bool hasDictObject(SchemaOpPtr);
2110   void getDictObject(SchemaOpPtr, DictObjectPtr&);
2111   void linkDictObject(SchemaOpPtr op_ptr, DictObjectPtr obj_ptr);
2112   void unlinkDictObject(SchemaOpPtr op_ptr);
2113   void seizeDictObject(SchemaOpPtr, DictObjectPtr&, const RopeHandle& name);
2114   bool findDictObject(SchemaOpPtr, DictObjectPtr&, const char* name);
2115   bool findDictObject(SchemaOpPtr, DictObjectPtr&, Uint32 obj_ptr_i);
2116   void releaseDictObject(SchemaOpPtr);
2117   void findDictObjectOp(SchemaOpPtr&, DictObjectPtr);
2118 
2119   /*
2120    * Trans client is the API client (not us, for recursive ops).
2121    * Its state is shared by SchemaTrans / TxHandle (for takeover).
2122    */
2123   struct TransClient {
2124     enum State {
2125       StateUndef = 0,
2126       BeginReq = 1,   // begin trans received
2127       BeginReply = 2, // reply sent / waited for
2128       ParseReq = 3,
2129       ParseReply = 4,
2130       EndReq = 5,
2131       EndReply = 6
2132     };
2133     enum Flag {
2134       ApiFail = 1,
2135       Background = 2,
2136       TakeOver = 4,
2137       Commit = 8
2138     };
2139   };
2140 
2141   // SchemaTrans
2142 
2143   struct SchemaTrans {
2144     // ArrayPool
2145     Uint32 nextPool;
2146 
2147     enum TransState
2148     {
2149       TS_INITIAL          = 0,
2150       TS_STARTING         = 1, // Starting at participants
2151       TS_STARTED          = 2, // Started (potentially with parsed ops)
2152       TS_PARSING          = 3, // Parsing at participants
2153       TS_SUBOP            = 4, // Creating subop
2154       TS_ROLLBACK_SP      = 5, // Rolling back to SP (supported before prepare)
2155       TS_FLUSH_PREPARE    = 6,
2156       TS_PREPARING        = 7, // Preparing operations
2157       TS_ABORTING_PREPARE = 8, // Aborting prepared operations
2158       TS_ABORTING_PARSE   = 9, // Aborting parsed operations
2159       TS_FLUSH_COMMIT     = 10,
2160       TS_COMMITTING       = 11,// Committing
2161       TS_FLUSH_COMPLETE   = 12,// Committed
2162       TS_COMPLETING       = 13,// Completing
2163       TS_ENDING           = 14
2164     };
2165 
2166     Uint32 m_state;
weightDbdict::SchemaTrans2167     static Uint32 weight(Uint32 state) {
2168     /*
2169       Return the "weight" of a transaction state, used to determine
2170       the absolute order of beleived transaction states at master
2171       takeover.
2172      */
2173       switch ((TransState) state) {
2174       case TS_INITIAL:
2175         return 0;
2176       case TS_STARTING:
2177         return 1;
2178       case TS_STARTED:
2179         return 2;
2180       case TS_PARSING:
2181         return 3;
2182       case TS_SUBOP:
2183         return 6;
2184       case TS_ROLLBACK_SP:
2185         return 5;
2186       case TS_FLUSH_PREPARE:
2187         return 7;
2188       case TS_PREPARING:
2189         return 8;
2190       case TS_ABORTING_PREPARE:
2191         return 9;
2192       case TS_ABORTING_PARSE:
2193         return 4;
2194       case TS_FLUSH_COMMIT:
2195         return 10;
2196       case TS_COMMITTING:
2197         return 11;
2198       case TS_FLUSH_COMPLETE:
2199         return 12;
2200       case TS_COMPLETING:
2201         return 13;
2202       case TS_ENDING:
2203         return 14;
2204       }
2205       assert(false);
2206       return -1;
2207     }
2208     // DLMHashTable
2209     Uint32 trans_key;
2210     Uint32 nextHash;
2211     Uint32 prevHash;
hashValueDbdict::SchemaTrans2212     Uint32 hashValue() const {
2213       return trans_key;
2214     }
equalDbdict::SchemaTrans2215     bool equal(const SchemaTrans& rec) const {
2216       return trans_key == rec.trans_key;
2217     }
2218 
2219     // DLFifoList where new ones are added at end
2220     Uint32 nextList;
2221     Uint32 prevList;
2222 
2223     bool m_isMaster;
2224     BlockReference m_masterRef;
2225 
2226     // requestFlags from begin/end trans
2227     Uint32 m_requestInfo;
2228 
2229     BlockReference m_clientRef;
2230     Uint32 m_obj_id;
2231     Uint32 m_transId;
2232     TransClient::State m_clientState;
2233     Uint32 m_clientFlags;
2234     Uint32 m_takeOverTxKey;
2235 
2236     NdbNodeBitmask m_nodes;      // Nodes part of transaction
2237     NdbNodeBitmask m_ref_nodes;  // Nodes replying REF to req
2238     SafeCounterHandle m_counter; // Outstanding REQ's
2239 
2240     ArenaHead m_arena;
2241     Uint32 m_curr_op_ptr_i;
2242     SchemaOp_head m_op_list;
2243 
2244     // Master takeover
2245     enum TakeoverRecoveryState
2246     {
2247       TRS_INITIAL     = 0,
2248       TRS_ROLLFORWARD = 1,
2249       TRS_ROLLBACK    = 2
2250     };
2251     Uint32 m_master_recovery_state;
2252     // These are common states all nodes must achieve
2253     // to be able to be involved in total rollforward/rollbackward
2254     Uint32 m_rollforward_op;
2255     Uint32 m_rollforward_op_state;
2256     Uint32 m_rollback_op;
2257     Uint32 m_rollback_op_state;
2258     Uint32 m_lowest_trans_state;
2259     Uint32 m_highest_trans_state;
2260     // Flag for signalling partial rollforward check during master takeover
2261     bool check_partial_rollforward;
2262     // Flag for signalling that already completed operation is recreated
2263     bool ressurected_op;
2264 
2265     // request for lock/unlock
2266     DictLockReq m_lockReq;
2267 
2268     // callback (not yet used)
2269     Callback m_callback;
2270 
2271     // error is reset after each req/reply
2272     ErrorInfo m_error;
2273 
2274     /**
2275      * Mutex handling
2276      */
2277     MutexHandle2<DIH_START_LCP_MUTEX> m_commit_mutex;
2278 
2279     bool m_flush_prepare;
2280     bool m_flush_commit;
2281     bool m_flush_complete;
2282     bool m_flush_end;
2283     bool m_wait_gcp_on_commit;
2284     bool m_abort_on_node_fail;
2285 
2286     // magic is on when record is seized
2287     enum { DICT_MAGIC = ~RT_DBDICT_SCHEMA_TRANSACTION };
2288     Uint32 m_magic;
2289 
SchemaTransDbdict::SchemaTrans2290     SchemaTrans() {
2291       m_state = TS_INITIAL;
2292       m_isMaster = false;
2293       m_masterRef = 0;
2294       m_requestInfo = 0;
2295       m_clientRef = 0;
2296       m_transId = 0;
2297       m_clientState = TransClient::StateUndef;
2298       m_clientFlags = 0;
2299       m_takeOverTxKey = 0;
2300       bzero(&m_lockReq, sizeof(m_lockReq));
2301       m_callback.m_callbackFunction = 0;
2302       m_callback.m_callbackData = 0;
2303       m_magic = DICT_MAGIC;
2304       m_obj_id = RNIL;
2305       m_flush_prepare = false;
2306       m_flush_commit = false;
2307       m_flush_complete = false;
2308       m_flush_end = false;
2309       m_wait_gcp_on_commit = true;
2310       m_abort_on_node_fail = false;
2311     }
2312 
SchemaTransDbdict::SchemaTrans2313     SchemaTrans(Uint32 the_trans_key) {
2314       trans_key = the_trans_key;
2315     }
2316 
2317 #ifdef VM_TRACE
2318     void print(NdbOut&) const;
2319 #endif
2320   };
2321 
2322   Uint32 check_read_obj(Uint32 objId, Uint32 transId = 0);
2323   Uint32 check_read_obj(SchemaFile::TableEntry*, Uint32 transId = 0);
2324   Uint32 check_write_obj(Uint32 objId, Uint32 transId = 0,
2325          SchemaFile::EntryState = SchemaFile::SF_UNUSED);
2326   Uint32 check_write_obj(Uint32, Uint32, SchemaFile::EntryState, ErrorInfo&);
2327 
2328   typedef RecordPool<SchemaTrans,ArenaPool> SchemaTrans_pool;
2329   typedef DLMHashTable<SchemaTrans_pool, SchemaTrans> SchemaTrans_hash;
2330   typedef DLFifoListImpl<SchemaTrans_pool, SchemaTrans, SchemaTrans> SchemaTrans_list;
2331 
2332   SchemaTrans_pool c_schemaTransPool;
2333   SchemaTrans_hash c_schemaTransHash;
2334   SchemaTrans_list c_schemaTransList;
2335   Uint32 c_schemaTransCount;
2336 
2337   bool seizeSchemaTrans(SchemaTransPtr&, Uint32 trans_key);
2338   bool seizeSchemaTrans(SchemaTransPtr&);
2339   bool findSchemaTrans(SchemaTransPtr&, Uint32 trans_key);
2340   void releaseSchemaTrans(SchemaTransPtr&);
2341 
2342   // coordinator
2343   void createSubOps(Signal*, SchemaOpPtr, bool first = false);
2344   void abortSubOps(Signal*, SchemaOpPtr, ErrorInfo);
2345 
2346   void trans_recv_reply(Signal*, SchemaTransPtr);
2347   void trans_start_recv_reply(Signal*, SchemaTransPtr);
2348   void trans_parse_recv_reply(Signal*, SchemaTransPtr);
2349 
2350   void trans_prepare_start(Signal*, SchemaTransPtr);
2351   void trans_prepare_first(Signal*, SchemaTransPtr);
2352   void trans_prepare_recv_reply(Signal*, SchemaTransPtr);
2353   void trans_prepare_next(Signal*, SchemaTransPtr, SchemaOpPtr);
2354   void trans_prepare_done(Signal*, SchemaTransPtr);
2355 
2356   void trans_abort_prepare_start(Signal*, SchemaTransPtr);
2357   void trans_abort_prepare_recv_reply(Signal*, SchemaTransPtr);
2358   void trans_abort_prepare_next(Signal*, SchemaTransPtr, SchemaOpPtr);
2359   void trans_abort_prepare_done(Signal*, SchemaTransPtr);
2360 
2361   void trans_abort_parse_start(Signal*, SchemaTransPtr);
2362   void trans_abort_parse_recv_reply(Signal*, SchemaTransPtr);
2363   void trans_abort_parse_next(Signal*, SchemaTransPtr, SchemaOpPtr);
2364   void trans_abort_parse_done(Signal*, SchemaTransPtr);
2365 
2366   void trans_rollback_sp_start(Signal* signal, SchemaTransPtr);
2367   void trans_rollback_sp_recv_reply(Signal* signal, SchemaTransPtr);
2368   void trans_rollback_sp_next(Signal* signal, SchemaTransPtr, SchemaOpPtr);
2369   void trans_rollback_sp_done(Signal* signal, SchemaTransPtr, SchemaOpPtr);
2370 
2371   void trans_commit_start(Signal*, SchemaTransPtr);
2372   void trans_commit_wait_gci(Signal*);
2373   void trans_commit_mutex_locked(Signal*, Uint32, Uint32);
2374   void trans_commit_first(Signal*, SchemaTransPtr);
2375   void trans_commit_recv_reply(Signal*, SchemaTransPtr);
2376   void trans_commit_next(Signal*, SchemaTransPtr, SchemaOpPtr);
2377   void trans_commit_done(Signal* signal, SchemaTransPtr);
2378   void trans_commit_mutex_unlocked(Signal*, Uint32, Uint32);
2379 
2380   void trans_complete_start(Signal* signal, SchemaTransPtr);
2381   void trans_complete_first(Signal* signal, SchemaTransPtr);
2382   void trans_complete_next(Signal*, SchemaTransPtr, SchemaOpPtr);
2383   void trans_complete_recv_reply(Signal*, SchemaTransPtr);
2384   void trans_complete_done(Signal*, SchemaTransPtr);
2385 
2386   void trans_end_start(Signal* signal, SchemaTransPtr);
2387   void trans_end_recv_reply(Signal*, SchemaTransPtr);
2388 
2389   void trans_log(SchemaTransPtr);
2390   Uint32 trans_log_schema_op(SchemaOpPtr,
2391                              Uint32 objectId,
2392                              const SchemaFile::TableEntry*);
2393 
2394   void trans_log_schema_op_abort(SchemaOpPtr);
2395   void trans_log_schema_op_complete(SchemaOpPtr);
2396 
2397   void handle_master_takeover(Signal*);
2398   void check_takeover_replies(Signal*);
2399   void trans_recover(Signal*, SchemaTransPtr);
2400   void check_partial_trans_abort_prepare_next(SchemaTransPtr,
2401                                               NdbNodeBitmask &,
2402                                               SchemaOpPtr);
2403   void check_partial_trans_abort_parse_next(SchemaTransPtr,
2404                                             NdbNodeBitmask &,
2405                                             SchemaOpPtr);
2406   void check_partial_trans_complete_start(SchemaTransPtr, NdbNodeBitmask &);
2407   void check_partial_trans_commit_start(SchemaTransPtr, NdbNodeBitmask &);
2408   void check_partial_trans_commit_next(SchemaTransPtr,
2409                                        NdbNodeBitmask &,
2410                                        SchemaOpPtr);
2411 
2412   // participant
2413   void recvTransReq(Signal*);
2414   void recvTransParseReq(Signal*, SchemaTransPtr,
2415                          Uint32 op_key, const OpInfo& info,
2416                          Uint32 requestInfo);
2417   void runTransSlave(Signal*, SchemaTransPtr);
2418   void update_op_state(SchemaOpPtr);
2419   void sendTransConf(Signal*, SchemaOpPtr);
2420   void sendTransConf(Signal*, SchemaTransPtr);
2421   void sendTransConfRelease(Signal*, SchemaTransPtr);
2422   void sendTransRef(Signal*, SchemaOpPtr);
2423   void sendTransRef(Signal*, SchemaTransPtr);
2424 
2425   void slave_run_start(Signal*, const SchemaTransImplReq*);
2426   void slave_run_parse(Signal*, SchemaTransPtr, const SchemaTransImplReq*);
2427   void slave_run_flush(Signal*, SchemaTransPtr, const SchemaTransImplReq*);
2428   void slave_writeSchema_conf(Signal*, Uint32, Uint32);
2429   void slave_commit_mutex_locked(Signal*, Uint32, Uint32);
2430   void slave_commit_mutex_unlocked(Signal*, Uint32, Uint32);
2431 
2432   // reply to trans client for begin/end trans
2433   void sendTransClientReply(Signal*, SchemaTransPtr);
2434 
2435   // on DB slave node failure exclude the node from transactions
2436   void handleTransSlaveFail(Signal*, Uint32 failedNode);
2437 
2438   // common code for different op types
2439 
2440   /*
2441    * Client REQ starts with find trans and add op record.
2442    * Sets request info in op and default request type in impl_req.
2443    */
2444   template <class T, class Req, class ImplReq>
2445   inline void
startClientReq(SchemaOpPtr & op_ptr,Ptr<T> & t_ptr,const Req * req,ImplReq * & impl_req,ErrorInfo & error)2446   startClientReq(SchemaOpPtr& op_ptr, Ptr<T>& t_ptr,
2447                  const Req* req, ImplReq*& impl_req, ErrorInfo& error)
2448   {
2449     SchemaTransPtr trans_ptr;
2450 
2451     const Uint32 requestInfo = req->requestInfo;
2452     const Uint32 requestType = DictSignal::getRequestType(requestInfo);
2453     const Uint32 requestExtra = DictSignal::getRequestExtra(requestInfo);
2454     const bool localTrans = (requestInfo & DictSignal::RF_LOCAL_TRANS);
2455 
2456     if (getOwnNodeId() != c_masterNodeId && !localTrans) {
2457       jam();
2458       setError(error, SchemaTransImplRef::NotMaster, __LINE__);
2459       return;
2460     }
2461 
2462     if (!findSchemaTrans(trans_ptr, req->transKey)) {
2463       jam();
2464       setError(error, SchemaTransImplRef::InvalidTransKey, __LINE__);
2465       return;
2466     }
2467 
2468     if (trans_ptr.p->m_transId != req->transId) {
2469       jam();
2470       setError(error, SchemaTransImplRef::InvalidTransId, __LINE__);
2471       return;
2472     }
2473 
2474     if (!localTrans)
2475     {
2476       ndbassert(getOwnNodeId() == c_masterNodeId);
2477       NodeRecordPtr masterNodePtr;
2478       c_nodes.getPtr(masterNodePtr, c_masterNodeId);
2479 
2480       if (masterNodePtr.p->nodeState == NodeRecord::NDB_MASTER_TAKEOVER)
2481       {
2482         jam();
2483         /**
2484          * There is a dict takeover in progress, and the transaction may thus
2485          * be in an inconsistent state where its fate has not been decided yet.
2486          * If transaction is in error we return that error,
2487          * else we return 'Busy' which will cause a later retry.
2488          */
2489         if (hasError(trans_ptr.p->m_error))
2490         {
2491           jam();
2492           setError(error, trans_ptr.p->m_error);
2493         }
2494         else
2495         {
2496           jam();
2497           setError(error, SchemaTransImplRef::Busy, __LINE__);
2498         }
2499         return;
2500       }
2501     }
2502 
2503     // Assert that we are not in an inconsistent/incomplete state
2504     ndbassert(!hasError(trans_ptr.p->m_error));
2505     ndbassert(!c_takeOverInProgress);
2506     ndbassert(trans_ptr.p->m_counter.done());
2507 
2508     if (!seizeSchemaOp(trans_ptr, op_ptr, t_ptr)) {
2509       jam();
2510       setError(error, SchemaTransImplRef::TooManySchemaOps, __LINE__);
2511       return;
2512     }
2513 
2514     trans_ptr.p->m_clientState = TransClient::ParseReq;
2515 
2516     DictSignal::setRequestExtra(op_ptr.p->m_requestInfo, requestExtra);
2517     DictSignal::addRequestFlags(op_ptr.p->m_requestInfo, requestInfo);
2518 
2519     // impl_req was passed via reference
2520     impl_req = &t_ptr.p->m_request;
2521 
2522     impl_req->senderRef = reference();
2523     impl_req->senderData = op_ptr.p->op_key;
2524     impl_req->requestType = requestType;
2525 
2526     // client of this REQ (trans client or us, recursively)
2527     op_ptr.p->m_clientRef = req->clientRef;
2528     op_ptr.p->m_clientData = req->clientData;
2529   }
2530 
2531   /*
2532    * The other half of client REQ processing.  On error starts
2533    * rollback of current client op and its sub-ops.
2534    */
2535   void handleClientReq(Signal*, SchemaOpPtr, SectionHandle&);
2536 
2537   // DICT receives recursive or internal CONF or REF
2538 
2539   template <class Conf>
2540   inline void
handleDictConf(Signal * signal,const Conf * conf)2541   handleDictConf(Signal* signal, const Conf* conf) {
2542     D("handleDictConf" << V(conf->senderData));
2543     ndbrequire(signal->getNoOfSections() == 0);
2544 
2545     Callback callback;
2546     bool ok = findCallback(callback, conf->senderData);
2547     ndbrequire(ok);
2548     execute(signal, callback, 0);
2549   }
2550 
2551   template <class Ref>
2552   inline void
handleDictRef(Signal * signal,const Ref * ref)2553   handleDictRef(Signal* signal, const Ref* ref) {
2554     D("handleDictRef" << V(ref->senderData) << V(ref->errorCode));
2555     ndbrequire(signal->getNoOfSections() == 0);
2556 
2557     Callback callback;
2558     bool ok = findCallback(callback, ref->senderData);
2559     ndbrequire(ok);
2560     ndbrequire(ref->errorCode != 0);
2561     execute(signal, callback, ref->errorCode);
2562   }
2563 
2564   /*
2565    * TxHandle
2566    *
2567    * DICT as schema trans client.  TxHandle is the client-side record.
2568    * It has same role as NdbDictInterface::Tx in NDB API.  It is used
2569    * for following:
2570    *
2571    * - create or drop table at NR/SR [not yet]
2572    * - build or activate indexes at NR/SR
2573    * - take over client trans if client requests this
2574    * - take over client trans when client API has failed
2575    */
2576 
2577   struct TxHandle {
2578     // ArrayPool
2579     Uint32 nextPool;
2580 
2581     // DLMHashTable
2582     Uint32 tx_key;
2583     Uint32 nextHash;
2584     Uint32 prevHash;
hashValueDbdict::TxHandle2585     Uint32 hashValue() const {
2586       return tx_key;
2587     }
equalDbdict::TxHandle2588     bool equal(const TxHandle& rec) const {
2589       return tx_key == rec.tx_key;
2590     }
2591 
2592     Uint32 m_requestInfo; // global flags are passed to schema trans
2593     Uint32 m_transId;
2594     Uint32 m_transKey;
2595     Uint32 m_userData;
2596 
2597     // when take over for background or for failed API
2598     TransClient::State m_clientState;
2599     Uint32 m_clientFlags;
2600     BlockReference m_takeOverRef;
2601     Uint32 m_takeOverTransId;
2602 
2603     Callback m_callback;
2604     ErrorInfo m_error;
2605 
2606     // magic is on when record is seized
2607     enum { DICT_MAGIC = 0xd1c70003 };
2608     Uint32 m_magic;
2609 
TxHandleDbdict::TxHandle2610     TxHandle() {
2611       m_requestInfo = 0;
2612       m_transId = 0;
2613       m_transKey = 0;
2614       m_userData = 0;
2615       m_clientState = TransClient::StateUndef;
2616       m_clientFlags = 0;
2617       m_takeOverRef = 0;
2618       m_takeOverTransId = 0;
2619       m_callback.m_callbackFunction = 0;
2620       m_callback.m_callbackData = 0;
2621       m_magic = 0;
2622     }
2623 
TxHandleDbdict::TxHandle2624     TxHandle(Uint32 the_tx_key) {
2625       tx_key = the_tx_key;
2626     }
2627 #ifdef VM_TRACE
2628     void print(NdbOut&) const;
2629 #endif
2630   };
2631 
2632   typedef ArrayPool<TxHandle> TxHandle_pool;
2633   typedef DLMHashTable<TxHandle_pool, TxHandle> TxHandle_hash;
2634 
2635   TxHandle_pool c_txHandlePool;
2636   TxHandle_hash c_txHandleHash;
2637 
2638   bool seizeTxHandle(TxHandlePtr&);
2639   bool findTxHandle(TxHandlePtr&, Uint32 tx_key);
2640   void releaseTxHandle(TxHandlePtr&);
2641 
2642   void beginSchemaTrans(Signal*, TxHandlePtr);
2643   void endSchemaTrans(Signal*, TxHandlePtr, Uint32 flags = 0);
2644 
2645   void handleApiFail(Signal*, Uint32 failedApiNode);
2646   void takeOverTransClient(Signal*, SchemaTransPtr);
2647   void runTransClientTakeOver(Signal*, Uint32 tx_key, Uint32 ret);
2648   void finishApiFail(Signal*, TxHandlePtr tx_ptr);
2649   void apiFailBlockHandling(Signal*, Uint32 failedApiNode);
2650 
2651   /*
2652    * Callback key is for different record types in some cases.
2653    * For example a CONF can be for SchemaOp or for TxHandle.
2654    * This looks for match for one of op_key/trans_key/tx_key.
2655    */
2656   bool findCallback(Callback& callback, Uint32 any_key);
2657 
2658   // MODULE: CreateTable
2659 
2660   struct CreateTableRec;
2661   typedef RecordPool<CreateTableRec,ArenaPool> CreateTableRec_pool;
2662 
2663   struct CreateTableRec : public OpRec {
2664     static const OpInfo g_opInfo;
2665 
2666     static CreateTableRec_pool&
getPoolDbdict::CreateTableRec2667     getPool(Dbdict* dict) {
2668       return dict->c_createTableRecPool;
2669     }
2670 
2671     CreateTabReq m_request;
2672 
2673     // wl3600_todo check mutex name and number later
2674     MutexHandle2<DIH_START_LCP_MUTEX> m_startLcpMutex;
2675 
2676     // long signal memory for temp use
2677     Uint32 m_tabInfoPtrI;
2678     Uint32 m_fragmentsPtrI;
2679 
2680     // connect pointers towards DIH and LQH
2681     Uint32 m_dihAddFragPtr;
2682     Uint32 m_lqhFragPtr;
2683 
2684     // who is using local create tab
2685     Callback m_callback;
2686 
2687     // flag if this op has been aborted in RT_PREPARE phase
2688     bool m_abortPrepareDone;
2689 
CreateTableRecDbdict::CreateTableRec2690     CreateTableRec() :
2691       OpRec(g_opInfo, (Uint32*)&m_request) {
2692       memset(&m_request, 0, sizeof(m_request));
2693       m_tabInfoPtrI = RNIL;
2694       m_fragmentsPtrI = RNIL;
2695       m_dihAddFragPtr = RNIL;
2696       m_lqhFragPtr = RNIL;
2697       m_abortPrepareDone = false;
2698     }
2699 
2700 #ifdef VM_TRACE
2701     void print(NdbOut&) const;
2702 #endif
2703   };
2704 
2705   typedef Ptr<CreateTableRec> CreateTableRecPtr;
2706   CreateTableRec_pool c_createTableRecPool;
2707 
2708   // OpInfo
2709   bool createTable_seize(SchemaOpPtr);
2710   void createTable_release(SchemaOpPtr);
2711   //
2712   void createTable_parse(Signal*, bool master,
2713                          SchemaOpPtr, SectionHandle&, ErrorInfo&);
2714   bool createTable_subOps(Signal*, SchemaOpPtr);
2715   void createTable_reply(Signal*, SchemaOpPtr, ErrorInfo);
2716   //
2717   void createTable_prepare(Signal*, SchemaOpPtr);
2718   void createTable_commit(Signal*, SchemaOpPtr);
2719   void createTable_complete(Signal*, SchemaOpPtr);
2720   //
2721   void createTable_abortParse(Signal*, SchemaOpPtr);
2722   void createTable_abortPrepare(Signal*, SchemaOpPtr);
2723 
2724   // prepare
2725   void createTab_writeTableConf(Signal*, Uint32 op_key, Uint32 ret);
2726   void createTab_local(Signal*, SchemaOpPtr, OpSection fragSec, Callback*);
2727   void createTab_dih(Signal*, SchemaOpPtr);
2728   void createTab_localComplete(Signal*, Uint32 op_key, Uint32 ret);
2729 
2730   // commit
2731   void createTab_activate(Signal*, SchemaOpPtr, Callback*);
2732   void createTab_alterComplete(Signal*, Uint32 op_key, Uint32 ret);
2733 
2734   // abort prepare
2735   void createTable_abortLocalConf(Signal*, Uint32 aux_op_key, Uint32 ret);
2736 
2737   // MODULE: DropTable
2738 
2739   struct DropTableRec;
2740   typedef RecordPool<DropTableRec,ArenaPool> DropTableRec_pool;
2741 
2742   struct DropTableRec : public OpRec {
2743     static const OpInfo g_opInfo;
2744 
2745     static DropTableRec_pool&
getPoolDbdict::DropTableRec2746     getPool(Dbdict* dict) {
2747       return dict->c_dropTableRecPool;
2748     }
2749 
2750     DropTabReq m_request;
2751 
2752     // wl3600_todo check mutex name and number later
2753     MutexHandle2<BACKUP_DEFINE_MUTEX> m_define_backup_mutex;
2754 
2755     Uint32 m_block;
2756     enum { BlockCount = 6 };
2757     Uint32 m_blockNo[BlockCount];
2758     Callback m_callback;
2759 
DropTableRecDbdict::DropTableRec2760     DropTableRec() :
2761       OpRec(g_opInfo, (Uint32*)&m_request) {
2762       memset(&m_request, 0, sizeof(m_request));
2763       m_block = 0;
2764     }
2765 
2766 #ifdef VM_TRACE
2767     void print(NdbOut&) const;
2768 #endif
2769   };
2770 
2771   typedef Ptr<DropTableRec> DropTableRecPtr;
2772   DropTableRec_pool c_dropTableRecPool;
2773 
2774   // OpInfo
2775   bool dropTable_seize(SchemaOpPtr);
2776   void dropTable_release(SchemaOpPtr);
2777   //
2778   void dropTable_parse(Signal*, bool master,
2779                        SchemaOpPtr, SectionHandle&, ErrorInfo&);
2780   bool dropTable_subOps(Signal*, SchemaOpPtr);
2781   void dropTable_reply(Signal*, SchemaOpPtr, ErrorInfo);
2782   //
2783   void dropTable_prepare(Signal*, SchemaOpPtr);
2784   void dropTable_commit(Signal*, SchemaOpPtr);
2785   void dropTable_complete(Signal*, SchemaOpPtr);
2786   //
2787   void dropTable_abortParse(Signal*, SchemaOpPtr);
2788   void dropTable_abortPrepare(Signal*, SchemaOpPtr);
2789 
2790   // prepare
2791   void dropTable_backup_mutex_locked(Signal*, Uint32 op_key, Uint32 ret);
2792 
2793   // commit
2794   void dropTable_commit_nextStep(Signal*, SchemaOpPtr);
2795   void dropTable_commit_fromLocal(Signal*, Uint32 op_key, Uint32 errorCode);
2796   void dropTable_commit_done(Signal*, SchemaOpPtr);
2797 
2798   // complete
2799   void dropTable_complete_nextStep(Signal*, SchemaOpPtr);
2800   void dropTable_complete_fromLocal(Signal*, Uint32 op_key);
2801   void dropTable_complete_done(Signal*, Uint32 op_key, Uint32 ret);
2802 
2803   // MODULE: AlterTable
2804 
2805   struct AlterTableRec;
2806   typedef RecordPool<AlterTableRec,ArenaPool> AlterTableRec_pool;
2807 
2808   struct AlterTableRec : public OpRec {
2809     static const OpInfo g_opInfo;
2810 
2811     static AlterTableRec_pool&
getPoolDbdict::AlterTableRec2812     getPool(Dbdict* dict) {
2813       return dict->c_alterTableRecPool;
2814     }
2815 
2816     AlterTabReq m_request;
2817 
2818     // added attributes
2819     OpSection m_newAttrData;
2820 
2821     // wl3600_todo check mutex name and number later
2822     MutexHandle2<BACKUP_DEFINE_MUTEX> m_define_backup_mutex;
2823 
2824     // current and new temporary work table
2825     TableRecordPtr::I m_newTablePtrI;
2826     Uint32 m_newTable_realObjectId;
2827 
2828     // before image
2829     RopeHandle m_oldTableName;
2830     RopeHandle m_oldFrmData;
2831 
2832     // connect ptr towards TUP, DIH, LQH
2833     Uint32 m_dihAddFragPtr;
2834     Uint32 m_lqhFragPtr;
2835 
2836     // local blocks to process
2837     enum { BlockCount = 4 };
2838     Uint32 m_blockNo[BlockCount];
2839     Uint32 m_blockIndex;
2840 
2841     // used for creating subops for add partitions, wrt ordered index
2842     bool m_sub_reorg_commit;
2843     bool m_sub_reorg_complete;
2844     bool m_sub_add_frag;
2845     Uint32 m_sub_add_frag_index_ptr;
2846     bool m_sub_trigger;
2847     bool m_sub_copy_data;
2848     bool m_sub_suma_enable;
2849     bool m_sub_suma_filter;
2850 
AlterTableRecDbdict::AlterTableRec2851     AlterTableRec() :
2852       OpRec(g_opInfo, (Uint32*)&m_request) {
2853       memset(&m_request, 0, sizeof(m_request));
2854       m_newTablePtrI = RNIL;
2855       m_dihAddFragPtr = RNIL;
2856       m_lqhFragPtr = RNIL;
2857       m_blockNo[0] = DBLQH;
2858       m_blockNo[1] = DBDIH;
2859       m_blockNo[2] = DBSPJ;
2860       m_blockNo[3] = DBTC;
2861       m_blockIndex = 0;
2862       m_sub_add_frag_index_ptr = RNIL;
2863       m_sub_add_frag = false;
2864       m_sub_reorg_commit = false;
2865       m_sub_reorg_complete = false;
2866       m_sub_trigger = false;
2867       m_sub_copy_data = false;
2868       m_sub_suma_enable = false;
2869       m_sub_suma_filter = false;
2870     }
2871 #ifdef VM_TRACE
2872     void print(NdbOut&) const;
2873 #endif
2874   };
2875 
2876   typedef Ptr<AlterTableRec> AlterTableRecPtr;
2877   AlterTableRec_pool c_alterTableRecPool;
2878 
2879   // OpInfo
2880   bool alterTable_seize(SchemaOpPtr);
2881   void alterTable_release(SchemaOpPtr);
2882   //
2883   void alterTable_parse(Signal*, bool master,
2884                         SchemaOpPtr, SectionHandle&, ErrorInfo&);
2885   bool alterTable_subOps(Signal*, SchemaOpPtr);
2886   void alterTable_reply(Signal*, SchemaOpPtr, ErrorInfo);
2887   //
2888   void alterTable_prepare(Signal*, SchemaOpPtr);
2889   void alterTable_commit(Signal*, SchemaOpPtr);
2890   void alterTable_complete(Signal*, SchemaOpPtr);
2891   //
2892   void alterTable_abortParse(Signal*, SchemaOpPtr);
2893   void alterTable_abortPrepare(Signal*, SchemaOpPtr);
2894 
2895   void alterTable_toCopyData(Signal* signal, SchemaOpPtr op_ptr);
2896   void alterTable_fromCopyData(Signal*, Uint32 op_key, Uint32 ret);
2897 
2898   // prepare phase
2899   void alterTable_backup_mutex_locked(Signal*, Uint32 op_key, Uint32 ret);
2900   void alterTable_toLocal(Signal*, SchemaOpPtr);
2901   void alterTable_fromLocal(Signal*, Uint32 op_key, Uint32 ret);
2902 
2903   void alterTable_toAlterIndex(Signal*, SchemaOpPtr);
2904   void alterTable_fromAlterIndex(Signal*, Uint32 op_key, Uint32 ret);
2905 
2906   void alterTable_toReorgTable(Signal*, SchemaOpPtr, Uint32 step);
2907   void alterTable_fromReorgTable(Signal*, Uint32 op_key, Uint32 ret);
2908 
2909   void alterTable_toCreateTrigger(Signal* signal, SchemaOpPtr op_ptr);
2910   void alterTable_fromCreateTrigger(Signal*, Uint32 op_key, Uint32 ret);
2911 
2912   void alterTable_toSumaSync(Signal* signal, SchemaOpPtr op_ptr, Uint32);
2913 
2914   // commit phase
2915   void alterTable_toCommitComplete(Signal*, SchemaOpPtr, Uint32 = ~Uint32(0));
2916   void alterTable_fromCommitComplete(Signal*, Uint32 op_key, Uint32 ret);
2917   void alterTab_writeTableConf(Signal*, Uint32 op_key, Uint32 ret);
2918 
2919   // abort
2920   void alterTable_abortToLocal(Signal*, SchemaOpPtr);
2921   void alterTable_abortFromLocal(Signal*, Uint32 op_key, Uint32 ret);
2922 
2923   Uint32 check_supported_add_fragment(Uint16*, const Uint16*);
2924   Uint32 check_supported_reorg(Uint32, Uint32);
2925 
2926   // MODULE: CreateIndex
2927 
2928   typedef struct {
2929     Uint32 old_index;
2930     Uint32 attr_id;
2931     Uint32 attr_ptr_i;
2932   } AttributeMap[MAX_ATTRIBUTES_IN_INDEX];
2933 
2934   struct CreateIndexRec;
2935   typedef RecordPool<CreateIndexRec,ArenaPool> CreateIndexRec_pool;
2936 
2937   struct CreateIndexRec : public OpRec {
2938     CreateIndxImplReq m_request;
2939     char m_indexName[MAX_TAB_NAME_SIZE];
2940     IndexAttributeList m_attrList;
2941     AttributeMask m_attrMask;
2942     AttributeMap m_attrMap;
2943     Uint32 m_bits;
2944     Uint32 m_fragmentType;
2945     Uint32 m_indexKeyLength;
2946 
2947     // reflection
2948     static const OpInfo g_opInfo;
2949 
2950     static CreateIndexRec_pool&
getPoolDbdict::CreateIndexRec2951     getPool(Dbdict* dict) {
2952       return dict->c_createIndexRecPool;
2953     }
2954 
2955     // sub-operation counters
2956     bool m_sub_create_table;
2957     bool m_sub_alter_index;
2958 
CreateIndexRecDbdict::CreateIndexRec2959     CreateIndexRec() :
2960       OpRec(g_opInfo, (Uint32*)&m_request) {
2961       memset(&m_request, 0, sizeof(m_request));
2962       memset(m_indexName, 0, sizeof(m_indexName));
2963       memset(&m_attrList, 0, sizeof(m_attrList));
2964       m_attrMask.clear();
2965       memset(m_attrMap, 0, sizeof(m_attrMap));
2966       m_bits = 0;
2967       m_fragmentType = 0;
2968       m_indexKeyLength = 0;
2969       m_sub_create_table = false;
2970       m_sub_alter_index = false;
2971     }
2972 #ifdef VM_TRACE
2973     void print(NdbOut&) const;
2974 #endif
2975   };
2976 
2977   typedef Ptr<CreateIndexRec> CreateIndexRecPtr;
2978   CreateIndexRec_pool c_createIndexRecPool;
2979 
2980   // OpInfo
2981   bool createIndex_seize(SchemaOpPtr);
2982   void createIndex_release(SchemaOpPtr);
2983   //
2984   void createIndex_parse(Signal*, bool master,
2985                          SchemaOpPtr, SectionHandle&, ErrorInfo&);
2986   bool createIndex_subOps(Signal*, SchemaOpPtr);
2987   void createIndex_reply(Signal*, SchemaOpPtr, ErrorInfo);
2988   //
2989   void createIndex_prepare(Signal*, SchemaOpPtr);
2990   void createIndex_commit(Signal*, SchemaOpPtr);
2991   void createIndex_complete(Signal*, SchemaOpPtr);
2992   //
2993   void createIndex_abortParse(Signal*, SchemaOpPtr);
2994   void createIndex_abortPrepare(Signal*, SchemaOpPtr);
2995 
2996   // sub-ops
2997   void createIndex_toCreateTable(Signal*, SchemaOpPtr);
2998   void createIndex_fromCreateTable(Signal*, Uint32 op_key, Uint32 ret);
2999   void createIndex_toAlterIndex(Signal*, SchemaOpPtr);
3000   void createIndex_fromAlterIndex(Signal*, Uint32 op_key, Uint32 ret);
3001 
3002   // MODULE: DropIndex
3003 
3004   struct DropIndexRec;
3005   typedef RecordPool<DropIndexRec,ArenaPool> DropIndexRec_pool;
3006 
3007   struct DropIndexRec : public OpRec {
3008     DropIndxImplReq m_request;
3009 
3010     // reflection
3011     static const OpInfo g_opInfo;
3012 
3013     static DropIndexRec_pool&
getPoolDbdict::DropIndexRec3014     getPool(Dbdict* dict) {
3015       return dict->c_dropIndexRecPool;
3016     }
3017 
3018     // sub-operation counters
3019     bool m_sub_alter_index;
3020     bool m_sub_drop_table;
3021 
DropIndexRecDbdict::DropIndexRec3022     DropIndexRec() :
3023       OpRec(g_opInfo, (Uint32*)&m_request) {
3024       memset(&m_request, 0, sizeof(m_request));
3025       m_sub_alter_index = false;
3026       m_sub_drop_table = false;
3027     }
3028 #ifdef VM_TRACE
3029     void print(NdbOut&) const;
3030 #endif
3031   };
3032 
3033   typedef Ptr<DropIndexRec> DropIndexRecPtr;
3034   DropIndexRec_pool c_dropIndexRecPool;
3035 
3036   // OpInfo
3037   bool dropIndex_seize(SchemaOpPtr);
3038   void dropIndex_release(SchemaOpPtr);
3039   //
3040   void dropIndex_parse(Signal*, bool master,
3041                        SchemaOpPtr, SectionHandle&, ErrorInfo&);
3042   bool dropIndex_subOps(Signal*, SchemaOpPtr);
3043   void dropIndex_reply(Signal*, SchemaOpPtr, ErrorInfo);
3044   //
3045   void dropIndex_prepare(Signal*, SchemaOpPtr);
3046   void dropIndex_commit(Signal*, SchemaOpPtr);
3047   void dropIndex_complete(Signal*, SchemaOpPtr);
3048   //
3049   void dropIndex_abortParse(Signal*, SchemaOpPtr);
3050   void dropIndex_abortPrepare(Signal*, SchemaOpPtr);
3051 
3052   // sub-ops
3053   void dropIndex_toDropTable(Signal*, SchemaOpPtr);
3054   void dropIndex_fromDropTable(Signal*, Uint32 op_key, Uint32 ret);
3055   void dropIndex_toAlterIndex(Signal*, SchemaOpPtr);
3056   void dropIndex_fromAlterIndex(Signal*, Uint32 op_key, Uint32 ret);
3057 
3058   // MODULE: AlterIndex
3059 
3060   struct TriggerTmpl {
3061     const char* nameFormat; // contains one %u for index id
3062     TriggerInfo triggerInfo;
3063   };
3064 
3065   static const TriggerTmpl g_hashIndexTriggerTmpl[1];
3066   static const TriggerTmpl g_orderedIndexTriggerTmpl[1];
3067   static const TriggerTmpl g_buildIndexConstraintTmpl[1];
3068   static const TriggerTmpl g_reorgTriggerTmpl[1];
3069   static const TriggerTmpl g_fkTriggerTmpl[2];
3070 
3071   struct AlterIndexRec;
3072   typedef RecordPool<AlterIndexRec,ArenaPool> AlterIndexRec_pool;
3073 
3074   struct AlterIndexRec : public OpRec {
3075     AlterIndxImplReq m_request;
3076     IndexAttributeList m_attrList;
3077     AttributeMask m_attrMask;
3078 
3079     // reflection
3080     static const OpInfo g_opInfo;
3081 
3082     static AlterIndexRec_pool&
getPoolDbdict::AlterIndexRec3083     getPool(Dbdict* dict) {
3084       return dict->c_alterIndexRecPool;
3085     }
3086 
3087     // sub-operation counters (true = done or skip)
3088     const TriggerTmpl* m_triggerTmpl;
3089     bool m_sub_trigger;
3090     bool m_sub_build_index;
3091     bool m_sub_index_stat_dml;
3092     bool m_sub_index_stat_mon;
3093 
3094     // prepare phase
3095     bool m_tc_index_done;
3096 
3097     // connect pointers towards DIH and LQH
3098     Uint32 m_dihAddFragPtr;
3099     Uint32 m_lqhFragPtr;
3100 
AlterIndexRecDbdict::AlterIndexRec3101     AlterIndexRec() :
3102       OpRec(g_opInfo, (Uint32*)&m_request) {
3103       memset(&m_request, 0, sizeof(m_request));
3104       memset(&m_attrList, 0, sizeof(m_attrList));
3105       m_attrMask.clear();
3106       m_triggerTmpl = 0;
3107       m_sub_trigger = false;
3108       m_sub_build_index = false;
3109       m_sub_index_stat_dml = false;
3110       m_sub_index_stat_mon = false;
3111       m_tc_index_done = false;
3112     }
3113 
3114 #ifdef VM_TRACE
3115     void print(NdbOut&) const;
3116 #endif
3117   };
3118 
3119   typedef Ptr<AlterIndexRec> AlterIndexRecPtr;
3120   AlterIndexRec_pool c_alterIndexRecPool;
3121 
3122   // OpInfo
3123   bool alterIndex_seize(SchemaOpPtr);
3124   void alterIndex_release(SchemaOpPtr);
3125   //
3126   void alterIndex_parse(Signal*, bool master,
3127                         SchemaOpPtr, SectionHandle&, ErrorInfo&);
3128   bool alterIndex_subOps(Signal*, SchemaOpPtr);
3129   void alterIndex_reply(Signal*, SchemaOpPtr, ErrorInfo);
3130   //
3131   void alterIndex_prepare(Signal*, SchemaOpPtr);
3132   void alterIndex_commit(Signal*, SchemaOpPtr);
3133   void alterIndex_complete(Signal*, SchemaOpPtr);
3134   //
3135   void alterIndex_abortParse(Signal*, SchemaOpPtr);
3136   void alterIndex_abortPrepare(Signal*, SchemaOpPtr);
3137 
3138   // parse phase sub-routine
3139   void set_index_stat_frag(Signal*, TableRecordPtr indexPtr);
3140 
3141   // sub-ops
3142   void alterIndex_toCreateTrigger(Signal*, SchemaOpPtr);
3143   void alterIndex_atCreateTrigger(Signal*, SchemaOpPtr);
3144   void alterIndex_fromCreateTrigger(Signal*, Uint32 op_key, Uint32 ret);
3145   void alterIndex_toDropTrigger(Signal*, SchemaOpPtr);
3146   void alterIndex_atDropTrigger(Signal*, SchemaOpPtr);
3147   void alterIndex_fromDropTrigger(Signal*, Uint32 op_key, Uint32 ret);
3148   void alterIndex_toBuildIndex(Signal*, SchemaOpPtr);
3149   void alterIndex_fromBuildIndex(Signal*, Uint32 op_key, Uint32 ret);
3150   void alterIndex_toIndexStat(Signal*, SchemaOpPtr);
3151   void alterIndex_fromIndexStat(Signal*, Uint32 op_key, Uint32 ret);
3152 
3153   // prepare phase
3154   void alterIndex_toCreateLocal(Signal*, SchemaOpPtr);
3155   void alterIndex_toDropLocal(Signal*, SchemaOpPtr);
3156   void alterIndex_fromLocal(Signal*, Uint32 op_key, Uint32 ret);
3157 
3158   void alterIndex_toAddPartitions(Signal*, SchemaOpPtr);
3159   void alterIndex_fromAddPartitions(Signal*, Uint32 op_key, Uint32 ret);
3160 
3161   // abort
3162   void alterIndex_abortFromLocal(Signal*, Uint32 op_key, Uint32 ret);
3163 
3164   // MODULE: BuildIndex
3165 
3166   // this prepends 1 column used for FRAGMENT in hash index table key
3167   typedef Id_array<1 + MAX_ATTRIBUTES_IN_INDEX> FragAttributeList;
3168 
3169   struct BuildIndexRec;
3170   typedef RecordPool<BuildIndexRec,ArenaPool> BuildIndexRec_pool;
3171 
3172   struct BuildIndexRec : public OpRec {
3173     static const OpInfo g_opInfo;
3174 
3175     static BuildIndexRec_pool&
getPoolDbdict::BuildIndexRec3176     getPool(Dbdict* dict) {
3177       return dict->c_buildIndexRecPool;
3178     }
3179 
3180     BuildIndxImplReq m_request;
3181 
3182     IndexAttributeList m_indexKeyList;
3183     FragAttributeList m_tableKeyList;
3184     AttributeMask m_attrMask;
3185 
3186     // sub-operation counters (CTr BIn DTr)
3187     const TriggerTmpl* m_triggerTmpl;
3188     Uint32 m_subOpCount;    // 3 or 0
3189     Uint32 m_subOpIndex;
3190 
3191     // do the actual build (i.e. not done in a sub-op BIn)
3192     bool m_doBuild;
3193 
BuildIndexRecDbdict::BuildIndexRec3194     BuildIndexRec() :
3195       OpRec(g_opInfo, (Uint32*)&m_request) {
3196       memset(&m_request, 0, sizeof(m_request));
3197       memset(&m_indexKeyList, 0, sizeof(m_indexKeyList));
3198       memset(&m_tableKeyList, 0, sizeof(m_tableKeyList));
3199       m_attrMask.clear();
3200       m_triggerTmpl = 0;
3201       m_subOpCount = 0;
3202       m_subOpIndex = 0;
3203       m_doBuild = false;
3204     }
3205   };
3206 
3207   typedef Ptr<BuildIndexRec> BuildIndexRecPtr;
3208   BuildIndexRec_pool c_buildIndexRecPool;
3209 
3210   // OpInfo
3211   bool buildIndex_seize(SchemaOpPtr);
3212   void buildIndex_release(SchemaOpPtr);
3213   //
3214   void buildIndex_parse(Signal*, bool master,
3215                         SchemaOpPtr, SectionHandle&, ErrorInfo&);
3216   bool buildIndex_subOps(Signal*, SchemaOpPtr);
3217   void buildIndex_reply(Signal*, SchemaOpPtr, ErrorInfo);
3218   //
3219   void buildIndex_prepare(Signal*, SchemaOpPtr);
3220   void buildIndex_commit(Signal*, SchemaOpPtr);
3221   void buildIndex_complete(Signal*, SchemaOpPtr);
3222   //
3223   void buildIndex_abortParse(Signal*, SchemaOpPtr);
3224   void buildIndex_abortPrepare(Signal*, SchemaOpPtr);
3225 
3226   // parse phase
3227   void buildIndex_toCreateConstraint(Signal*, SchemaOpPtr);
3228   void buildIndex_atCreateConstraint(Signal*, SchemaOpPtr);
3229   void buildIndex_fromCreateConstraint(Signal*, Uint32 op_key, Uint32 ret);
3230   //
3231   void buildIndex_toBuildIndex(Signal*, SchemaOpPtr);
3232   void buildIndex_fromBuildIndex(Signal*, Uint32 op_key, Uint32 ret);
3233   //
3234   void buildIndex_toDropConstraint(Signal*, SchemaOpPtr);
3235   void buildIndex_atDropConstraint(Signal*, SchemaOpPtr);
3236   void buildIndex_fromDropConstraint(Signal*, Uint32 op_key, Uint32 ret);
3237 
3238   // prepare phase
3239   void buildIndex_toLocalBuild(Signal*, SchemaOpPtr);
3240   void buildIndex_fromLocalBuild(Signal*, Uint32 op_key, Uint32 ret);
3241 
3242   // commit phase
3243   void buildIndex_toLocalOnline(Signal*, SchemaOpPtr);
3244   void buildIndex_fromLocalOnline(Signal*, Uint32 op_key, Uint32 ret);
3245 
3246   // MODULE: IndexStat
3247 
3248   struct IndexStatRec;
3249   typedef RecordPool<IndexStatRec,ArenaPool> IndexStatRec_pool;
3250 
3251   struct IndexStatRec : public OpRec {
3252     static const OpInfo g_opInfo;
3253 
3254     static IndexStatRec_pool&
getPoolDbdict::IndexStatRec3255     getPool(Dbdict* dict) {
3256       return dict->c_indexStatRecPool;
3257     }
3258 
3259     IndexStatImplReq m_request;
3260 
3261     // sub-operation counters
3262     const TriggerTmpl* m_triggerTmpl;
3263     Uint32 m_subOpCount;
3264     Uint32 m_subOpIndex;
3265 
IndexStatRecDbdict::IndexStatRec3266     IndexStatRec() :
3267       OpRec(g_opInfo, (Uint32*)&m_request) {
3268       memset(&m_request, 0, sizeof(m_request));
3269       m_subOpCount = 0;
3270       m_subOpIndex = 0;
3271     }
3272   };
3273 
3274   typedef Ptr<IndexStatRec> IndexStatRecPtr;
3275   IndexStatRec_pool c_indexStatRecPool;
3276 
3277   Uint32 c_indexStatAutoCreate;
3278   Uint32 c_indexStatAutoUpdate;
3279   Uint32 c_indexStatBgId;
3280 
3281   // OpInfo
3282   bool indexStat_seize(SchemaOpPtr);
3283   void indexStat_release(SchemaOpPtr);
3284   //
3285   void indexStat_parse(Signal*, bool master,
3286                         SchemaOpPtr, SectionHandle&, ErrorInfo&);
3287   bool indexStat_subOps(Signal*, SchemaOpPtr);
3288   void indexStat_reply(Signal*, SchemaOpPtr, ErrorInfo);
3289   //
3290   void indexStat_prepare(Signal*, SchemaOpPtr);
3291   void indexStat_commit(Signal*, SchemaOpPtr);
3292   void indexStat_complete(Signal*, SchemaOpPtr);
3293   //
3294   void indexStat_abortParse(Signal*, SchemaOpPtr);
3295   void indexStat_abortPrepare(Signal*, SchemaOpPtr);
3296 
3297   // parse phase
3298   void indexStat_toIndexStat(Signal*, SchemaOpPtr, Uint32 requestType);
3299   void indexStat_fromIndexStat(Signal*, Uint32 op_key, Uint32 ret);
3300 
3301   // prepare phase
3302   void indexStat_toLocalStat(Signal*, SchemaOpPtr);
3303   void indexStat_fromLocalStat(Signal*, Uint32 op_key, Uint32 ret);
3304 
3305   // background processing of stat requests
3306   void indexStatBg_process(Signal*);
3307   void indexStatBg_fromBeginTrans(Signal*, Uint32 tx_key, Uint32 ret);
3308   void indexStatBg_fromIndexStat(Signal*, Uint32 tx_key, Uint32 ret);
3309   void indexStatBg_fromEndTrans(Signal*, Uint32 tx_key, Uint32 ret);
3310   void indexStatBg_sendContinueB(Signal*);
3311 
3312   // MODULE: CreateHashMap
3313 
3314   struct HashMapRecord {
HashMapRecordDbdict::HashMapRecord3315     HashMapRecord(){}
isCompatibleDbdict::HashMapRecord3316     static bool isCompatible(Uint32 type) { return DictTabInfo::isHashMap(type); }
3317 
3318     /* Table id (array index in DICT and other blocks) */
3319     union {
3320       Uint32 m_object_id;
3321       Uint32 key;
3322     };
3323     Uint32 m_obj_ptr_i;      // in HashMap_pool
3324     Uint32 m_object_version;
3325 
3326     RopeHandle m_name;
3327 
3328     /**
3329      * ptr.i, in g_hash_map
3330      */
3331     Uint32 m_map_ptr_i;
3332     Uint32 nextPool;
3333   };
3334   typedef Ptr<HashMapRecord> HashMapRecordPtr;
3335   typedef ArrayPool<HashMapRecord> HashMapRecord_pool;
3336 
3337   HashMapRecord_pool c_hash_map_pool;
3338   RSS_AP_SNAPSHOT(c_hash_map_pool);
3339   RSS_AP_SNAPSHOT(g_hash_map);
get_pool(HashMapRecordPtr)3340   HashMapRecord_pool& get_pool(HashMapRecordPtr) { return c_hash_map_pool; }
3341 
3342   struct CreateHashMapRec;
3343   typedef RecordPool<CreateHashMapRec,ArenaPool> CreateHashMapRec_pool;
3344 
3345   struct CreateHashMapRec : public OpRec {
3346     static const OpInfo g_opInfo;
3347 
3348     static CreateHashMapRec_pool&
getPoolDbdict::CreateHashMapRec3349     getPool(Dbdict* dict) {
3350       return dict->c_createHashMapRecPool;
3351     }
3352 
3353     CreateHashMapImplReq m_request;
3354 
CreateHashMapRecDbdict::CreateHashMapRec3355     CreateHashMapRec() :
3356       OpRec(g_opInfo, (Uint32*)&m_request) {
3357       memset(&m_request, 0, sizeof(m_request));
3358     }
3359   };
3360 
3361   typedef Ptr<CreateHashMapRec> CreateHashMapRecPtr;
3362   CreateHashMapRec_pool c_createHashMapRecPool;
3363   void execCREATE_HASH_MAP_REQ(Signal* signal);
3364 
3365   // OpInfo
3366   bool createHashMap_seize(SchemaOpPtr);
3367   void createHashMap_release(SchemaOpPtr);
3368   //
3369   void createHashMap_parse(Signal*, bool master,
3370                          SchemaOpPtr, SectionHandle&, ErrorInfo&);
3371   bool createHashMap_subOps(Signal*, SchemaOpPtr);
3372   void createHashMap_reply(Signal*, SchemaOpPtr, ErrorInfo);
3373   //
3374   void createHashMap_prepare(Signal*, SchemaOpPtr);
3375   void createHashMap_writeObjConf(Signal* signal, Uint32, Uint32);
3376   void createHashMap_commit(Signal*, SchemaOpPtr);
3377   void createHashMap_complete(Signal*, SchemaOpPtr);
3378   //
3379   void createHashMap_abortParse(Signal*, SchemaOpPtr);
3380   void createHashMap_abortPrepare(Signal*, SchemaOpPtr);
3381 
3382   void packHashMapIntoPages(SimpleProperties::Writer&, Ptr<HashMapRecord>);
3383 
3384   // MODULE: CopyData
3385 
3386   struct CopyDataRec;
3387   typedef RecordPool<CopyDataRec,ArenaPool> CopyDataRec_pool;
3388 
3389   struct CopyDataRec : public OpRec {
3390     static const OpInfo g_opInfo;
3391 
3392     static CopyDataRec_pool&
getPoolDbdict::CopyDataRec3393     getPool(Dbdict* dict) {
3394       return dict->c_copyDataRecPool;
3395     }
3396 
3397     CopyDataImplReq m_request;
3398 
CopyDataRecDbdict::CopyDataRec3399     CopyDataRec() :
3400       OpRec(g_opInfo, (Uint32*)&m_request) {
3401       memset(&m_request, 0, sizeof(m_request));
3402     }
3403   };
3404 
3405   typedef Ptr<CopyDataRec> CopyDataRecPtr;
3406   CopyDataRec_pool c_copyDataRecPool;
3407   void execCOPY_DATA_REQ(Signal* signal);
3408   void execCOPY_DATA_REF(Signal* signal);
3409   void execCOPY_DATA_CONF(Signal* signal);
3410   void execCOPY_DATA_IMPL_REF(Signal* signal);
3411   void execCOPY_DATA_IMPL_CONF(Signal* signal);
3412 
3413   // OpInfo
3414   bool copyData_seize(SchemaOpPtr);
3415   void copyData_release(SchemaOpPtr);
3416   //
3417   void copyData_parse(Signal*, bool master,
3418                       SchemaOpPtr, SectionHandle&, ErrorInfo&);
3419   bool copyData_subOps(Signal*, SchemaOpPtr);
3420   void copyData_reply(Signal*, SchemaOpPtr, ErrorInfo);
3421   //
3422   void copyData_prepare(Signal*, SchemaOpPtr);
3423   void copyData_fromLocal(Signal*, Uint32, Uint32);
3424   void copyData_commit(Signal*, SchemaOpPtr);
3425   void copyData_complete(Signal*, SchemaOpPtr);
3426   //
3427   void copyData_abortParse(Signal*, SchemaOpPtr);
3428   void copyData_abortPrepare(Signal*, SchemaOpPtr);
3429 
3430   /**
3431    * Operation record for Util Signals.
3432    */
3433   struct OpSignalUtil : OpRecordCommon{
3434     Callback m_callback;
3435     Uint32 m_userData;
3436   };
3437   typedef Ptr<OpSignalUtil> OpSignalUtilPtr;
3438 
3439   /**
3440    * Operation record for subscribe-start-stop
3441    */
3442   struct OpSubEvent : OpRecordCommon {
3443     Uint32 m_senderRef;
3444     Uint32 m_senderData;
3445     Uint32 m_errorCode;
3446 
3447     Uint32 m_gsn;
3448     Uint32 m_subscriptionId;
3449     Uint32 m_subscriptionKey;
3450     Uint32 m_subscriberRef;
3451     Uint32 m_subscriberData;
3452     Uint8 m_buckets_per_ng[256]; // For SUB_START_REQ
3453     union {
3454       SubStartConf m_sub_start_conf;
3455       SubStopConf m_sub_stop_conf;
3456     };
3457     RequestTracker m_reqTracker;
3458   };
3459   typedef Ptr<OpSubEvent> OpSubEventPtr;
3460 
3461   /**
3462    * Operation record for create event.
3463    */
3464   struct OpCreateEvent : OpRecordCommon {
3465     // original request (event id will be added)
3466     CreateEvntReq m_request;
3467     //AttributeMask m_attrListBitmask;
3468     //    AttributeList m_attrList;
3469     sysTab_NDBEVENTS_0 m_eventRec;
3470     //    char m_eventName[MAX_TAB_NAME_SIZE];
3471     //    char m_tableName[MAX_TAB_NAME_SIZE];
3472 
3473     // coordinator DICT
3474     RequestTracker m_reqTracker;
3475     // state info
3476     CreateEvntReq::RequestType m_requestType;
3477     // error info
3478     Uint32 m_errorCode;
3479     Uint32 m_errorLine;
3480     Uint32 m_errorNode; /* also used to store master node id
3481                            in case of NotMaster */
3482     // ctor
OpCreateEventDbdict::OpCreateEvent3483     OpCreateEvent() {
3484       memset(&m_request, 0, sizeof(m_request));
3485       m_requestType = CreateEvntReq::RT_UNDEFINED;
3486       m_errorCode = CreateEvntRef::NoError;
3487       m_errorLine = 0;
3488       m_errorNode = 0;
3489     }
initDbdict::OpCreateEvent3490     void init(const CreateEvntReq* req, Dbdict* dp) {
3491       m_request = *req;
3492       m_errorCode = CreateEvntRef::NoError;
3493       m_errorLine = 0;
3494       m_errorNode = 0;
3495       m_requestType = req->getRequestType();
3496     }
hasErrorDbdict::OpCreateEvent3497     bool hasError() {
3498       return m_errorCode != CreateEvntRef::NoError;
3499     }
setErrorDbdict::OpCreateEvent3500     void setError(const CreateEvntRef* ref) {
3501       if (ref != 0 && ! hasError()) {
3502         m_errorCode = ref->getErrorCode();
3503         m_errorLine = ref->getErrorLine();
3504         m_errorNode = ref->getErrorNode();
3505       }
3506     }
3507 
3508   };
3509   typedef Ptr<OpCreateEvent> OpCreateEventPtr;
3510 
3511   /**
3512    * Operation record for drop event.
3513    */
3514   struct OpDropEvent : OpRecordCommon {
3515     // original request
3516     DropEvntReq m_request;
3517     //    char m_eventName[MAX_TAB_NAME_SIZE];
3518     sysTab_NDBEVENTS_0 m_eventRec;
3519     RequestTracker m_reqTracker;
3520     // error info
3521     Uint32 m_errorCode;
3522     Uint32 m_errorLine;
3523     Uint32 m_errorNode;
3524     // ctor
OpDropEventDbdict::OpDropEvent3525     OpDropEvent() {
3526       memset(&m_request, 0, sizeof(m_request));
3527       m_errorCode = 0;
3528       m_errorLine = 0;
3529       m_errorNode = 0;
3530     }
initDbdict::OpDropEvent3531     void init(const DropEvntReq* req) {
3532       m_request = *req;
3533       m_errorCode = 0;
3534       m_errorLine = 0;
3535       m_errorNode = 0;
3536     }
hasErrorDbdict::OpDropEvent3537     bool hasError() {
3538       return m_errorCode != 0;
3539     }
setErrorDbdict::OpDropEvent3540     void setError(const DropEvntRef* ref) {
3541       if (ref != 0 && ! hasError()) {
3542         m_errorCode = ref->getErrorCode();
3543         m_errorLine = ref->getErrorLine();
3544         m_errorNode = ref->getErrorNode();
3545       }
3546     }
3547   };
3548   typedef Ptr<OpDropEvent> OpDropEventPtr;
3549 
3550   // MODULE: CreateTrigger
3551 
3552   struct CreateTriggerRec;
3553   typedef RecordPool<CreateTriggerRec,ArenaPool> CreateTriggerRec_pool;
3554 
3555   struct CreateTriggerRec : public OpRec {
3556     static const OpInfo g_opInfo;
3557 
3558     static CreateTriggerRec_pool&
getPoolDbdict::CreateTriggerRec3559     getPool(Dbdict* dict) {
3560       return dict->c_createTriggerRecPool;
3561     }
3562 
3563     CreateTrigImplReq m_request;
3564 
3565     char m_triggerName[MAX_TAB_NAME_SIZE];
3566     // sub-operation counters
3567     bool m_created;
3568     bool m_main_op;
3569     bool m_sub_dst; // Create trigger destination
3570     bool m_sub_src; // Create trigger source
3571     Uint32 m_block_list[1]; // Only 1 block...
3572 
CreateTriggerRecDbdict::CreateTriggerRec3573     CreateTriggerRec() :
3574       OpRec(g_opInfo, (Uint32*)&m_request) {
3575       memset(&m_request, 0, sizeof(m_request));
3576       memset(m_triggerName, 0, sizeof(m_triggerName));
3577       m_main_op = true;
3578       m_sub_src = false;
3579       m_sub_dst = false;
3580       m_created = false;
3581     }
3582   };
3583 
3584   typedef Ptr<CreateTriggerRec> CreateTriggerRecPtr;
3585   CreateTriggerRec_pool c_createTriggerRecPool;
3586 
3587   // OpInfo
3588   bool createTrigger_seize(SchemaOpPtr);
3589   void createTrigger_release(SchemaOpPtr);
3590   //
3591   void createTrigger_parse(Signal*, bool master,
3592                            SchemaOpPtr, SectionHandle&, ErrorInfo&);
3593   void createTrigger_parse_endpoint(Signal*, SchemaOpPtr op_ptr, ErrorInfo&);
3594   bool createTrigger_subOps(Signal*, SchemaOpPtr);
3595   void createTrigger_toCreateEndpoint(Signal*, SchemaOpPtr,
3596 				      CreateTrigReq::EndpointFlag);
3597   void createTrigger_fromCreateEndpoint(Signal*, Uint32, Uint32);
3598   void createTrigger_create_drop_trigger_operation(Signal*,SchemaOpPtr,
3599                                                    ErrorInfo& error);
3600 
3601   void createTrigger_reply(Signal*, SchemaOpPtr, ErrorInfo);
3602   //
3603   void createTrigger_prepare(Signal*, SchemaOpPtr);
3604   void createTrigger_prepare_fromLocal(Signal*, Uint32 op_key, Uint32 ret);
3605   void createTrigger_commit(Signal*, SchemaOpPtr);
3606   void createTrigger_commit_fromLocal(Signal*, Uint32 op_key, Uint32 ret);
3607   void createTrigger_complete(Signal*, SchemaOpPtr);
3608   //
3609   void createTrigger_abortParse(Signal*, SchemaOpPtr);
3610   void createTrigger_abortPrepare(Signal*, SchemaOpPtr);
3611   void createTrigger_abortPrepare_fromLocal(Signal*, Uint32, Uint32);
3612   void send_create_trig_req(Signal*, SchemaOpPtr);
3613 
3614   // MODULE: DropTrigger
3615 
3616   struct DropTriggerRec;
3617   typedef RecordPool<DropTriggerRec,ArenaPool> DropTriggerRec_pool;
3618 
3619   struct DropTriggerRec : public OpRec {
3620     static const OpInfo g_opInfo;
3621 
3622     static DropTriggerRec_pool&
getPoolDbdict::DropTriggerRec3623     getPool(Dbdict* dict) {
3624       return dict->c_dropTriggerRecPool;
3625     }
3626 
3627     DropTrigImplReq m_request;
3628 
3629     char m_triggerName[MAX_TAB_NAME_SIZE];
3630     // sub-operation counters
3631     bool m_main_op;
3632     bool m_sub_dst; // Create trigger destination
3633     bool m_sub_src; // Create trigger source
3634     Uint32 m_block_list[1]; // Only 1 block...
3635 
DropTriggerRecDbdict::DropTriggerRec3636     DropTriggerRec() :
3637       OpRec(g_opInfo, (Uint32*)&m_request) {
3638       memset(&m_request, 0, sizeof(m_request));
3639       memset(m_triggerName, 0, sizeof(m_triggerName));
3640       m_main_op = true;
3641       m_sub_src = false;
3642       m_sub_dst = false;
3643     }
3644   };
3645 
3646   typedef Ptr<DropTriggerRec> DropTriggerRecPtr;
3647   DropTriggerRec_pool c_dropTriggerRecPool;
3648 
3649   // OpInfo
3650   bool dropTrigger_seize(SchemaOpPtr);
3651   void dropTrigger_release(SchemaOpPtr);
3652   //
3653   void dropTrigger_parse(Signal*, bool master,
3654                          SchemaOpPtr, SectionHandle&, ErrorInfo&);
3655   void dropTrigger_parse_endpoint(Signal*, SchemaOpPtr op_ptr, ErrorInfo&);
3656   bool dropTrigger_subOps(Signal*, SchemaOpPtr);
3657   void dropTrigger_toDropEndpoint(Signal*, SchemaOpPtr,
3658 				  DropTrigReq::EndpointFlag);
3659   void dropTrigger_fromDropEndpoint(Signal*, Uint32, Uint32);
3660   void dropTrigger_reply(Signal*, SchemaOpPtr, ErrorInfo);
3661   //
3662   void dropTrigger_prepare(Signal*, SchemaOpPtr);
3663   void dropTrigger_commit(Signal*, SchemaOpPtr);
3664   void dropTrigger_commit_fromLocal(Signal*, Uint32, Uint32);
3665   void dropTrigger_complete(Signal*, SchemaOpPtr);
3666   //
3667   void dropTrigger_abortParse(Signal*, SchemaOpPtr);
3668   void dropTrigger_abortPrepare(Signal*, SchemaOpPtr);
3669 
3670   void send_drop_trig_req(Signal*, SchemaOpPtr);
3671 
3672 
3673   // MODULE: CreateFilegroup
3674 
3675   struct CreateFilegroupRec;
3676   typedef RecordPool<CreateFilegroupRec,ArenaPool> CreateFilegroupRec_pool;
3677 
3678   struct CreateFilegroupRec : public OpRec {
3679     bool m_parsed, m_prepared;
3680     CreateFilegroupImplReq m_request;
3681     Uint32 m_warningFlags;
3682 
3683     // reflection
3684     static const OpInfo g_opInfo;
3685 
3686     static CreateFilegroupRec_pool&
getPoolDbdict::CreateFilegroupRec3687     getPool(Dbdict* dict) {
3688       return dict->c_createFilegroupRecPool;
3689     }
3690 
CreateFilegroupRecDbdict::CreateFilegroupRec3691     CreateFilegroupRec() :
3692       OpRec(g_opInfo, (Uint32*)&m_request) {
3693       memset(&m_request, 0, sizeof(m_request));
3694       m_parsed = m_prepared = false;
3695       m_warningFlags = 0;
3696     }
3697   };
3698 
3699   typedef Ptr<CreateFilegroupRec> CreateFilegroupRecPtr;
3700   CreateFilegroupRec_pool c_createFilegroupRecPool;
3701 
3702   // OpInfo
3703   bool createFilegroup_seize(SchemaOpPtr);
3704   void createFilegroup_release(SchemaOpPtr);
3705   //
3706   void createFilegroup_parse(Signal*, bool master,
3707                          SchemaOpPtr, SectionHandle&, ErrorInfo&);
3708   bool createFilegroup_subOps(Signal*, SchemaOpPtr);
3709   void createFilegroup_reply(Signal*, SchemaOpPtr, ErrorInfo);
3710   //
3711   void createFilegroup_prepare(Signal*, SchemaOpPtr);
3712   void createFilegroup_commit(Signal*, SchemaOpPtr);
3713   void createFilegroup_complete(Signal*, SchemaOpPtr);
3714   //
3715   void createFilegroup_abortParse(Signal*, SchemaOpPtr);
3716   void createFilegroup_abortPrepare(Signal*, SchemaOpPtr);
3717 
3718   void createFilegroup_fromLocal(Signal*, Uint32, Uint32);
3719   void createFilegroup_fromWriteObjInfo(Signal*, Uint32, Uint32);
3720 
3721   // MODULE: CreateFile
3722 
3723   struct CreateFileRec;
3724   typedef RecordPool<CreateFileRec,ArenaPool> CreateFileRec_pool;
3725 
3726   struct CreateFileRec : public OpRec {
3727     bool m_parsed, m_prepared;
3728     CreateFileImplReq m_request;
3729     Uint32 m_warningFlags;
3730 
3731     // reflection
3732     static const OpInfo g_opInfo;
3733 
3734     static CreateFileRec_pool&
getPoolDbdict::CreateFileRec3735     getPool(Dbdict* dict) {
3736       return dict->c_createFileRecPool;
3737     }
3738 
CreateFileRecDbdict::CreateFileRec3739     CreateFileRec() :
3740       OpRec(g_opInfo, (Uint32*)&m_request) {
3741       memset(&m_request, 0, sizeof(m_request));
3742       m_parsed = m_prepared = false;
3743       m_warningFlags = 0;
3744     }
3745   };
3746 
3747   typedef Ptr<CreateFileRec> CreateFileRecPtr;
3748   CreateFileRec_pool c_createFileRecPool;
3749 
3750   // OpInfo
3751   bool createFile_seize(SchemaOpPtr);
3752   void createFile_release(SchemaOpPtr);
3753   //
3754   void createFile_parse(Signal*, bool master,
3755                          SchemaOpPtr, SectionHandle&, ErrorInfo&);
3756   bool createFile_subOps(Signal*, SchemaOpPtr);
3757   void createFile_reply(Signal*, SchemaOpPtr, ErrorInfo);
3758   //
3759   void createFile_prepare(Signal*, SchemaOpPtr);
3760   void createFile_commit(Signal*, SchemaOpPtr);
3761   void createFile_complete(Signal*, SchemaOpPtr);
3762   //
3763   void createFile_abortParse(Signal*, SchemaOpPtr);
3764   void createFile_abortPrepare(Signal*, SchemaOpPtr);
3765 
3766   void createFile_fromLocal(Signal*, Uint32, Uint32);
3767   void createFile_fromWriteObjInfo(Signal*, Uint32, Uint32);
3768 
3769   // MODULE: DropFilegroup
3770 
3771   struct DropFilegroupRec;
3772   typedef RecordPool<DropFilegroupRec,ArenaPool> DropFilegroupRec_pool;
3773 
3774   struct DropFilegroupRec : public OpRec {
3775     bool m_parsed, m_prepared;
3776     DropFilegroupImplReq m_request;
3777 
3778     // reflection
3779     static const OpInfo g_opInfo;
3780 
3781     static DropFilegroupRec_pool&
getPoolDbdict::DropFilegroupRec3782     getPool(Dbdict* dict) {
3783       return dict->c_dropFilegroupRecPool;
3784     }
3785 
DropFilegroupRecDbdict::DropFilegroupRec3786     DropFilegroupRec() :
3787       OpRec(g_opInfo, (Uint32*)&m_request) {
3788       memset(&m_request, 0, sizeof(m_request));
3789       m_parsed = m_prepared = false;
3790     }
3791   };
3792 
3793   typedef Ptr<DropFilegroupRec> DropFilegroupRecPtr;
3794   DropFilegroupRec_pool c_dropFilegroupRecPool;
3795 
3796   // OpInfo
3797   bool dropFilegroup_seize(SchemaOpPtr);
3798   void dropFilegroup_release(SchemaOpPtr);
3799   //
3800   void dropFilegroup_parse(Signal*, bool master,
3801                          SchemaOpPtr, SectionHandle&, ErrorInfo&);
3802   bool dropFilegroup_subOps(Signal*, SchemaOpPtr);
3803   void dropFilegroup_reply(Signal*, SchemaOpPtr, ErrorInfo);
3804   //
3805   void dropFilegroup_prepare(Signal*, SchemaOpPtr);
3806   void dropFilegroup_commit(Signal*, SchemaOpPtr);
3807   void dropFilegroup_complete(Signal*, SchemaOpPtr);
3808   //
3809   void dropFilegroup_abortParse(Signal*, SchemaOpPtr);
3810   void dropFilegroup_abortPrepare(Signal*, SchemaOpPtr);
3811 
3812   void dropFilegroup_fromLocal(Signal*, Uint32, Uint32);
3813 
3814   // MODULE: DropFile
3815 
3816   struct DropFileRec;
3817   typedef RecordPool<DropFileRec,ArenaPool> DropFileRec_pool;
3818 
3819   struct DropFileRec : public OpRec {
3820     bool m_parsed, m_prepared;
3821     DropFileImplReq m_request;
3822 
3823     // reflection
3824     static const OpInfo g_opInfo;
3825 
3826     static DropFileRec_pool&
getPoolDbdict::DropFileRec3827     getPool(Dbdict* dict) {
3828       return dict->c_dropFileRecPool;
3829     }
3830 
DropFileRecDbdict::DropFileRec3831     DropFileRec() :
3832       OpRec(g_opInfo, (Uint32*)&m_request) {
3833       memset(&m_request, 0, sizeof(m_request));
3834       m_parsed = m_prepared = false;
3835     }
3836   };
3837 
3838   typedef Ptr<DropFileRec> DropFileRecPtr;
3839   DropFileRec_pool c_dropFileRecPool;
3840 
3841   // OpInfo
3842   bool dropFile_seize(SchemaOpPtr);
3843   void dropFile_release(SchemaOpPtr);
3844   //
3845   void dropFile_parse(Signal*, bool master,
3846                          SchemaOpPtr, SectionHandle&, ErrorInfo&);
3847   bool dropFile_subOps(Signal*, SchemaOpPtr);
3848   void dropFile_reply(Signal*, SchemaOpPtr, ErrorInfo);
3849   //
3850   void dropFile_prepare(Signal*, SchemaOpPtr);
3851   void dropFile_commit(Signal*, SchemaOpPtr);
3852   void dropFile_complete(Signal*, SchemaOpPtr);
3853   //
3854   void dropFile_abortParse(Signal*, SchemaOpPtr);
3855   void dropFile_abortPrepare(Signal*, SchemaOpPtr);
3856 
3857   void dropFile_fromLocal(Signal*, Uint32, Uint32);
3858 
3859   // MODULE: CreateNodegroup
3860 
3861   struct CreateNodegroupRec;
3862   typedef RecordPool<CreateNodegroupRec,ArenaPool> CreateNodegroupRec_pool;
3863 
3864   struct CreateNodegroupRec : public OpRec {
3865     bool m_map_created;
3866     CreateNodegroupImplReq m_request;
3867 
3868     // reflection
3869     static const OpInfo g_opInfo;
3870 
3871     static CreateNodegroupRec_pool&
getPoolDbdict::CreateNodegroupRec3872     getPool(Dbdict* dict) {
3873       return dict->c_createNodegroupRecPool;
3874     }
3875 
CreateNodegroupRecDbdict::CreateNodegroupRec3876     CreateNodegroupRec() :
3877       OpRec(g_opInfo, (Uint32*)&m_request) {
3878       memset(&m_request, 0, sizeof(m_request));
3879       m_map_created = false;
3880       m_blockIndex = RNIL;
3881       m_blockCnt = RNIL;
3882       m_cnt_waitGCP = RNIL;
3883       m_wait_gcp_type = RNIL;
3884       m_substartstop_blocked = false;
3885       m_gcp_blocked = false;
3886     }
3887 
3888     enum { BlockCount = 3 };
3889     Uint32 m_blockNo[BlockCount];
3890     Uint32 m_blockIndex;
3891     Uint32 m_blockCnt;
3892     Uint32 m_cnt_waitGCP;
3893     Uint32 m_wait_gcp_type;
3894     bool m_gcp_blocked;
3895     bool m_substartstop_blocked;
3896   };
3897 
3898   typedef Ptr<CreateNodegroupRec> CreateNodegroupRecPtr;
3899   CreateNodegroupRec_pool c_createNodegroupRecPool;
3900 
3901   // OpInfo
3902   void execCREATE_NODEGROUP_REQ(Signal*);
3903   void execCREATE_NODEGROUP_IMPL_REF(Signal*);
3904   void execCREATE_NODEGROUP_IMPL_CONF(Signal*);
3905 
3906   bool createNodegroup_seize(SchemaOpPtr);
3907   void createNodegroup_release(SchemaOpPtr);
3908   //
3909   void createNodegroup_parse(Signal*, bool master,
3910                          SchemaOpPtr, SectionHandle&, ErrorInfo&);
3911   bool createNodegroup_subOps(Signal*, SchemaOpPtr);
3912   void createNodegroup_reply(Signal*, SchemaOpPtr, ErrorInfo);
3913   //
3914   void createNodegroup_prepare(Signal*, SchemaOpPtr);
3915   void createNodegroup_commit(Signal*, SchemaOpPtr);
3916   void createNodegroup_complete(Signal*, SchemaOpPtr);
3917   //
3918   void createNodegroup_abortParse(Signal*, SchemaOpPtr);
3919   void createNodegroup_abortPrepare(Signal*, SchemaOpPtr);
3920 
3921   void createNodegroup_toLocal(Signal*, SchemaOpPtr);
3922   void createNodegroup_fromLocal(Signal*, Uint32 op_key, Uint32 ret);
3923   void createNodegroup_fromCreateHashMap(Signal*, Uint32 op_key, Uint32 ret);
3924   void createNodegroup_fromWaitGCP(Signal*, Uint32 op_key, Uint32 ret);
3925   void createNodegroup_fromBlockSubStartStop(Signal*, Uint32 op_key, Uint32);
3926 
3927   void execCREATE_HASH_MAP_REF(Signal* signal);
3928   void execCREATE_HASH_MAP_CONF(Signal* signal);
3929 
3930   // MODULE: DropNodegroup
3931 
3932   struct DropNodegroupRec;
3933   typedef RecordPool<DropNodegroupRec,ArenaPool> DropNodegroupRec_pool;
3934 
3935   struct DropNodegroupRec : public OpRec {
3936     DropNodegroupImplReq m_request;
3937 
3938     // reflection
3939     static const OpInfo g_opInfo;
3940 
3941     static DropNodegroupRec_pool&
getPoolDbdict::DropNodegroupRec3942     getPool(Dbdict* dict) {
3943       return dict->c_dropNodegroupRecPool;
3944     }
3945 
DropNodegroupRecDbdict::DropNodegroupRec3946     DropNodegroupRec() :
3947       OpRec(g_opInfo, (Uint32*)&m_request) {
3948       memset(&m_request, 0, sizeof(m_request));
3949       m_blockIndex = RNIL;
3950       m_blockCnt = RNIL;
3951       m_cnt_waitGCP = RNIL;
3952       m_wait_gcp_type = RNIL;
3953       m_gcp_blocked = false;
3954       m_substartstop_blocked = false;
3955     }
3956 
3957     enum { BlockCount = 3 };
3958     Uint32 m_blockNo[BlockCount];
3959     Uint32 m_blockIndex;
3960     Uint32 m_blockCnt;
3961     Uint32 m_cnt_waitGCP;
3962     Uint32 m_wait_gcp_type;
3963     bool m_gcp_blocked;
3964     bool m_substartstop_blocked;
3965   };
3966 
3967   typedef Ptr<DropNodegroupRec> DropNodegroupRecPtr;
3968   DropNodegroupRec_pool c_dropNodegroupRecPool;
3969 
3970   // OpInfo
3971   void execDROP_NODEGROUP_REQ(Signal*);
3972   void execDROP_NODEGROUP_IMPL_REF(Signal*);
3973   void execDROP_NODEGROUP_IMPL_CONF(Signal*);
3974 
3975   bool dropNodegroup_seize(SchemaOpPtr);
3976   void dropNodegroup_release(SchemaOpPtr);
3977   //
3978   void dropNodegroup_parse(Signal*, bool master,
3979                          SchemaOpPtr, SectionHandle&, ErrorInfo&);
3980   bool dropNodegroup_subOps(Signal*, SchemaOpPtr);
3981   void dropNodegroup_reply(Signal*, SchemaOpPtr, ErrorInfo);
3982   //
3983   void dropNodegroup_prepare(Signal*, SchemaOpPtr);
3984   void dropNodegroup_commit(Signal*, SchemaOpPtr);
3985   void dropNodegroup_complete(Signal*, SchemaOpPtr);
3986   //
3987   void dropNodegroup_abortParse(Signal*, SchemaOpPtr);
3988   void dropNodegroup_abortPrepare(Signal*, SchemaOpPtr);
3989 
3990   void dropNodegroup_toLocal(Signal*, SchemaOpPtr);
3991   void dropNodegroup_fromLocal(Signal*, Uint32 op_key, Uint32 ret);
3992   void dropNodegroup_fromWaitGCP(Signal*, Uint32 op_key, Uint32 ret);
3993   void dropNodegroup_fromBlockSubStartStop(Signal*, Uint32 op_key, Uint32);
3994 
3995   // MODULE: CreateFK
3996   struct CreateFKRec;
3997   typedef RecordPool<CreateFKRec,ArenaPool> CreateFKRec_pool;
3998 
3999   struct CreateFKRec : public OpRec {
4000     bool m_parsed;
4001     bool m_prepared;
4002     Uint32 m_sub_create_trigger;
4003     bool m_sub_build_fk;
4004     CreateFKImplReq m_request;
4005 
4006     // reflection
4007     static const OpInfo g_opInfo;
4008 
4009     static CreateFKRec_pool&
getPoolDbdict::CreateFKRec4010     getPool(Dbdict* dict) {
4011       return dict->c_createFKRecPool;
4012     }
4013 
CreateFKRecDbdict::CreateFKRec4014     CreateFKRec() :
4015       OpRec(g_opInfo, (Uint32*)&m_request) {
4016       memset(&m_request, 0, sizeof(m_request));
4017       m_parsed = m_prepared = false;
4018       m_sub_create_trigger = 0;
4019       m_sub_build_fk = false;
4020     }
4021   };
4022 
4023   typedef Ptr<CreateFKRec> CreateFKRecPtr;
4024   CreateFKRec_pool c_createFKRecPool;
4025 
4026   // OpInfo
4027   bool createFK_seize(SchemaOpPtr);
4028   void createFK_release(SchemaOpPtr);
4029   //
4030   void createFK_parse(Signal*, bool master,
4031                       SchemaOpPtr, SectionHandle&, ErrorInfo&);
4032   bool createFK_subOps(Signal*, SchemaOpPtr);
4033   void createFK_reply(Signal*, SchemaOpPtr, ErrorInfo);
4034 
4035   void createFK_toCreateTrigger(Signal* signal, SchemaOpPtr);
4036   void createFK_fromCreateTrigger(Signal* signal, Uint32 op_key, Uint32 ret);
4037   void createFK_fromBuildFK(Signal* signal, Uint32 op_key, Uint32 ret);
4038   //
4039   void createFK_prepare(Signal*, SchemaOpPtr);
4040   void createFK_writeTableConf(Signal* signal, Uint32 op_key, Uint32 ret);
4041   void createFK_prepareFromLocal(Signal* signal, Uint32 op_key, Uint32 ret);
4042 
4043   void createFK_commit(Signal*, SchemaOpPtr);
4044   void createFK_complete(Signal*, SchemaOpPtr);
4045   //
4046   void createFK_abortParse(Signal*, SchemaOpPtr);
4047   void createFK_abortPrepare(Signal*, SchemaOpPtr);
4048   void createFK_abortPrepareFromLocal(Signal*, Uint32 op_key, Uint32 ret);
4049 
4050   void createFK_fromLocal(Signal*, Uint32, Uint32);
4051   void createFK_fromWriteObjInfo(Signal*, Uint32, Uint32);
4052 
4053   void execCREATE_FK_REQ(Signal*);
4054   void execCREATE_FK_IMPL_REF(Signal*);
4055   void execCREATE_FK_IMPL_CONF(Signal*);
4056   void execCREATE_FK_REF(Signal*);
4057   void execCREATE_FK_CONF(Signal*);
4058 
4059   // MODULE: BuildFK
4060   struct BuildFKRec;
4061   typedef RecordPool<BuildFKRec,ArenaPool> BuildFKRec_pool;
4062 
4063   struct BuildFKRec : public OpRec {
4064     bool m_parsed, m_prepared;
4065     BuildFKImplReq m_request;
4066 
4067     // reflection
4068     static const OpInfo g_opInfo;
4069 
4070     static BuildFKRec_pool&
getPoolDbdict::BuildFKRec4071     getPool(Dbdict* dict) {
4072       return dict->c_buildFKRecPool;
4073     }
4074 
BuildFKRecDbdict::BuildFKRec4075     BuildFKRec() :
4076       OpRec(g_opInfo, (Uint32*)&m_request) {
4077       memset(&m_request, 0, sizeof(m_request));
4078       m_parsed = m_prepared = false;
4079     }
4080   };
4081 
4082   typedef Ptr<BuildFKRec> BuildFKRecPtr;
4083   BuildFKRec_pool c_buildFKRecPool;
4084 
4085   // OpInfo
4086   bool buildFK_seize(SchemaOpPtr);
4087   void buildFK_release(SchemaOpPtr);
4088   //
4089   void buildFK_parse(Signal*, bool master,
4090                          SchemaOpPtr, SectionHandle&, ErrorInfo&);
4091   bool buildFK_subOps(Signal*, SchemaOpPtr);
4092   void buildFK_reply(Signal*, SchemaOpPtr, ErrorInfo);
4093   //
4094   void buildFK_prepare(Signal*, SchemaOpPtr);
4095   void buildFK_commit(Signal*, SchemaOpPtr);
4096   void buildFK_complete(Signal*, SchemaOpPtr);
4097   //
4098   void buildFK_abortParse(Signal*, SchemaOpPtr);
4099   void buildFK_abortPrepare(Signal*, SchemaOpPtr);
4100 
4101   void buildFK_fromLocal(Signal*, Uint32, Uint32);
4102 
4103   void execBUILD_FK_REQ(Signal*);
4104   void execBUILD_FK_REF(Signal*);
4105   void execBUILD_FK_CONF(Signal*);
4106   void execBUILD_FK_IMPL_REF(Signal*);
4107   void execBUILD_FK_IMPL_CONF(Signal*);
4108 
4109   // MODULE: DropFK
4110   struct DropFKRec;
4111   typedef RecordPool<DropFKRec,ArenaPool> DropFKRec_pool;
4112 
4113   struct DropFKRec : public OpRec {
4114     bool m_parsed;
4115     bool m_prepared;
4116     Uint32 m_sub_drop_trigger;
4117     DropFKImplReq m_request;
4118 
4119     // reflection
4120     static const OpInfo g_opInfo;
4121 
4122     static DropFKRec_pool&
getPoolDbdict::DropFKRec4123     getPool(Dbdict* dict) {
4124       return dict->c_dropFKRecPool;
4125     }
4126 
DropFKRecDbdict::DropFKRec4127     DropFKRec() :
4128       OpRec(g_opInfo, (Uint32*)&m_request) {
4129       memset(&m_request, 0, sizeof(m_request));
4130       m_parsed = m_prepared = false;
4131       m_sub_drop_trigger = 0;
4132     }
4133   };
4134 
4135   typedef Ptr<DropFKRec> DropFKRecPtr;
4136   DropFKRec_pool c_dropFKRecPool;
4137 
4138   // OpInfo
4139   bool dropFK_seize(SchemaOpPtr);
4140   void dropFK_release(SchemaOpPtr);
4141   //
4142   void dropFK_parse(Signal*, bool master,
4143                          SchemaOpPtr, SectionHandle&, ErrorInfo&);
4144   bool dropFK_subOps(Signal*, SchemaOpPtr);
4145   void dropFK_reply(Signal*, SchemaOpPtr, ErrorInfo);
4146   //
4147   void dropFK_toDropTrigger(Signal* signal, SchemaOpPtr, Uint32);
4148   void dropFK_fromDropTrigger(Signal* signal, Uint32 op_key, Uint32 ret);
4149 
4150   //
4151   void dropFK_prepare(Signal*, SchemaOpPtr);
4152   void dropFK_commit(Signal*, SchemaOpPtr);
4153   void dropFK_complete(Signal*, SchemaOpPtr);
4154   //
4155   void dropFK_abortParse(Signal*, SchemaOpPtr);
4156   void dropFK_abortPrepare(Signal*, SchemaOpPtr);
4157 
4158   void send_drop_fk_req(Signal*, SchemaOpPtr);
4159   void dropFK_fromLocal(Signal*, Uint32, Uint32);
4160   void dropFK_fromWriteObjInfo(Signal*, Uint32, Uint32);
4161 
4162   void execDROP_FK_REQ(Signal*);
4163   void execDROP_FK_IMPL_REF(Signal*);
4164   void execDROP_FK_IMPL_CONF(Signal*);
4165 
4166   /**
4167    * Foreign Key representation
4168    */
4169   struct ForeignKeyRec
4170   {
ForeignKeyRecDbdict::ForeignKeyRec4171     ForeignKeyRec() { }
4172 
isCompatibleDbdict::ForeignKeyRec4173     static bool isCompatible(Uint32 type) {
4174       return DictTabInfo::isForeignKey(type);
4175     }
4176 
4177     Uint32 m_magic;
4178     union {
4179       Uint32 key;
4180       Uint32 m_fk_id;
4181     };
4182 
4183     Uint32 m_obj_ptr_i;
4184     Uint32 m_version;
4185     RopeHandle m_name;
4186     Uint32 m_parentTableId;
4187     Uint32 m_childTableId;
4188     Uint32 m_parentIndexId;
4189     Uint32 m_childIndexId;
4190     Uint32 m_bits; // CreateFKImplReq::Bits
4191 
4192     Uint32 m_parentTriggerId;
4193     Uint32 m_childTriggerId;
4194 
4195     Uint32 m_columnCount;
4196     Uint32 m_parentColumns[MAX_ATTRIBUTES_IN_INDEX];
4197     Uint32 m_childColumns[MAX_ATTRIBUTES_IN_INDEX];
4198 
4199     Uint32 nextPool;
4200     Uint32 nextHash;
4201     Uint32 prevHash;
4202 
hashValueDbdict::ForeignKeyRec4203     Uint32 hashValue() const {
4204       return key;
4205     }
4206 
equalDbdict::ForeignKeyRec4207     Uint32 equal(const ForeignKeyRec& obj) const {
4208       return key == obj.key;
4209     }
4210   };
4211 
4212   typedef Ptr<ForeignKeyRec> ForeignKeyRecPtr;
4213   typedef RecordPool<ForeignKeyRec, RWPool> ForeignKeyRec_pool;
4214 
4215   ForeignKeyRec_pool c_fk_pool;
4216 
get_pool(ForeignKeyRecPtr)4217   ForeignKeyRec_pool& get_pool(ForeignKeyRecPtr) { return c_fk_pool; }
4218   void packFKIntoPages(SimpleProperties::Writer &, Ptr<ForeignKeyRec>);
4219 
4220   /**
4221    * Only used at coordinator/master
4222    */
4223   // Common operation record pool
4224 public:
4225   STATIC_CONST( opCreateEventSize = sizeof(OpCreateEvent) );
4226   STATIC_CONST( opSubEventSize = sizeof(OpSubEvent) );
4227   STATIC_CONST( opDropEventSize = sizeof(OpDropEvent) );
4228   STATIC_CONST( opSignalUtilSize = sizeof(OpSignalUtil) );
4229 private:
4230 #define PTR_ALIGN(n) ((((n)+sizeof(void*)-1)>>2)&~((sizeof(void*)-1)>>2))
4231   union OpRecordUnion {
4232     Uint32 u_opCreateEvent  [PTR_ALIGN(opCreateEventSize)];
4233     Uint32 u_opSubEvent     [PTR_ALIGN(opSubEventSize)];
4234     Uint32 u_opDropEvent    [PTR_ALIGN(opDropEventSize)];
4235     Uint32 u_opSignalUtil   [PTR_ALIGN(opSignalUtilSize)];
4236     Uint32 nextPool;
4237   };
4238   typedef ArrayPool<OpRecordUnion> OpRecordUnion_pool;
4239   OpRecordUnion_pool c_opRecordPool;
4240 
4241   // Operation records
4242   typedef KeyTable2C<OpCreateEvent, OpRecordUnion> OpCreateEvent_pool;
4243   typedef KeyTable2C<OpSubEvent, OpRecordUnion> OpSubEvent_pool;
4244   typedef KeyTable2C<OpDropEvent, OpRecordUnion> OpDropEvent_pool;
4245   typedef KeyTable2C<OpSignalUtil, OpRecordUnion> OpSignalUtil_pool;
4246   OpCreateEvent_pool c_opCreateEvent;
4247   OpSubEvent_pool c_opSubEvent;
4248   OpDropEvent_pool c_opDropEvent;
4249   OpSignalUtil_pool c_opSignalUtil;
4250 
4251   // Unique key for operation  XXX move to some system table
4252   Uint32 c_opRecordSequence;
4253 
4254   void handleNdbdFailureCallback(Signal* signal,
4255                                  Uint32 failedNodeId,
4256                                  Uint32 ignoredRc);
4257   void handleApiFailureCallback(Signal* signal,
4258                                 Uint32 failedNodeId,
4259                                 Uint32 ignoredRc);
4260   // Statement blocks
4261 
4262   /* ------------------------------------------------------------ */
4263   // Start/Restart Handling
4264   /* ------------------------------------------------------------ */
4265   void sendSTTORRY(Signal* signal);
4266   void sendNDB_STTORRY(Signal* signal);
4267   void initSchemaFile(Signal* signal);
4268 
4269   /* ------------------------------------------------------------ */
4270   // Drop Table Handling
4271   /* ------------------------------------------------------------ */
4272   void releaseTableObject(Uint32 table_ptr_i, bool removeFromHash = true);
4273 
4274   /* ------------------------------------------------------------ */
4275   // General Stuff
4276   /* ------------------------------------------------------------ */
4277   Uint32 getFreeObjId(bool both = false);
4278   Uint32 getFreeTableRecord();
4279   bool seizeTableRecord(TableRecordPtr& tableRecord, Uint32& schemaFileId);
4280   Uint32 getFreeTriggerRecord();
4281   bool seizeTriggerRecord(TriggerRecordPtr& tableRecord, Uint32 triggerId);
4282   void releaseTriggerObject(Uint32 trigger_ptr_i);
4283   bool getNewAttributeRecord(TableRecordPtr tablePtr,
4284 			     AttributeRecordPtr & attrPtr);
4285   void packTableIntoPages(Signal* signal);
4286   void packTableIntoPages(SimpleProperties::Writer &, TableRecordPtr, Signal* =0);
4287   void packFilegroupIntoPages(SimpleProperties::Writer &,
4288 			      FilegroupPtr,
4289 			      const Uint32 undo_free_hi,
4290 			      const Uint32 undo_free_lo);
4291   void packFileIntoPages(SimpleProperties::Writer &, FilePtr, const Uint32);
4292 
4293   void sendGET_TABINFOREQ(Signal* signal,
4294                           Uint32 tableId);
4295   void sendTC_SCHVERREQ(Signal* signal,
4296                         Uint32 tableId,
4297                         BlockReference tcRef);
4298 
4299   /* ------------------------------------------------------------ */
4300   // System Restart Handling
4301   /* ------------------------------------------------------------ */
4302   void initSendSchemaData(Signal* signal);
4303   void sendSchemaData(Signal* signal);
4304   Uint32 sendSCHEMA_INFO(Signal* signal, Uint32 nodeId, Uint32* pagePointer);
4305   void sendDIHSTARTTAB_REQ(Signal* signal);
4306 
4307   /* ------------------------------------------------------------ */
4308   // Receive Table Handling
4309   /* ------------------------------------------------------------ */
4310   void handleTabInfoInit(Signal*, SchemaTransPtr&,
4311                          SimpleProperties::Reader &,
4312 			 ParseDictTabInfoRecord *,
4313 			 bool checkExist = true);
4314   void handleTabInfo(SimpleProperties::Reader & it, ParseDictTabInfoRecord *,
4315 		     DictTabInfo::Table & tableDesc);
4316 
4317   void handleAddTableFailure(Signal* signal,
4318                              Uint32 failureLine,
4319                              Uint32 tableId);
4320   bool verifyTableCorrect(Signal* signal, Uint32 tableId);
4321 
4322   /* ------------------------------------------------------------ */
4323   // Add Fragment Handling
4324   /* ------------------------------------------------------------ */
4325   void sendLQHADDATTRREQ(Signal*, SchemaOpPtr, Uint32 attributePtrI);
4326 
4327   /* ------------------------------------------------------------ */
4328   // Read/Write Schema and Table files
4329   /* ------------------------------------------------------------ */
4330   void updateSchemaState(Signal* signal, Uint32 tableId,
4331 			 SchemaFile::TableEntry*, Callback*,
4332                          bool savetodisk = 1, bool dicttrans = 0);
4333   void startWriteSchemaFile(Signal* signal);
4334   void openSchemaFile(Signal* signal,
4335                       Uint32 fileNo,
4336                       Uint32 fsPtr,
4337                       bool writeFlag,
4338                       bool newFile);
4339   void writeSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsPtr);
4340   void writeSchemaConf(Signal* signal,
4341                                FsConnectRecordPtr fsPtr);
4342   void closeFile(Signal* signal, Uint32 filePtr, Uint32 fsPtr);
4343   void closeWriteSchemaConf(Signal* signal,
4344                                FsConnectRecordPtr fsPtr);
4345   void initSchemaFile_conf(Signal* signal, Uint32 i, Uint32 returnCode);
4346 
4347   void writeTableFile(Signal* signal, Uint32 tableId,
4348 		      SegmentedSectionPtr tabInfo, Callback*);
4349   void writeTableFile(Signal* signal, SchemaOpPtr op_ptr, Uint32 tableId,
4350 		      OpSection opSection, Callback*);
4351   void startWriteTableFile(Signal* signal, Uint32 tableId);
4352   void openTableFile(Signal* signal,
4353                      Uint32 fileNo,
4354                      Uint32 fsPtr,
4355                      Uint32 tableId,
4356                      bool writeFlag);
4357   void writeTableFile(Signal* signal, Uint32 filePtr, Uint32 fsPtr);
4358   void writeTableConf(Signal* signal,
4359                       FsConnectRecordPtr fsPtr);
4360   void closeWriteTableConf(Signal* signal,
4361                            FsConnectRecordPtr fsPtr);
4362 
4363   void startReadTableFile(Signal* signal, Uint32 tableId);
4364   void openReadTableRef(Signal* signal,
4365                         FsConnectRecordPtr fsPtr);
4366   void readTableFile(Signal* signal, Uint32 filePtr, Uint32 fsPtr);
4367   void readTableConf(Signal* signal,
4368                      FsConnectRecordPtr fsPtr);
4369   void readTableRef(Signal* signal,
4370                     FsConnectRecordPtr fsPtr);
4371   void closeReadTableConf(Signal* signal,
4372                           FsConnectRecordPtr fsPtr);
4373 
4374   void startReadSchemaFile(Signal* signal);
4375   void openReadSchemaRef(Signal* signal,
4376                          FsConnectRecordPtr fsPtr);
4377   void readSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsPtr);
4378   void readSchemaConf(Signal* signal, FsConnectRecordPtr fsPtr);
4379   void readSchemaRef(Signal* signal, FsConnectRecordPtr fsPtr);
4380   void closeReadSchemaConf(Signal* signal,
4381                            FsConnectRecordPtr fsPtr);
4382   bool convertSchemaFileTo_5_0_6(XSchemaFile*);
4383   bool convertSchemaFileTo_6_4(XSchemaFile*);
4384 
4385   /* ------------------------------------------------------------ */
4386   // Get table definitions
4387   /* ------------------------------------------------------------ */
4388   void sendGET_TABINFOREF(Signal* signal,
4389 			  GetTabInfoReq*,
4390 			  GetTabInfoRef::ErrorCode errorCode,
4391                           Uint32 errorLine);
4392 
4393   void sendGET_TABLEID_REF(Signal* signal,
4394 			   GetTableIdReq * req,
4395 			   GetTableIdRef::ErrorCode errorCode);
4396 
4397   void sendGetTabResponse(Signal* signal);
4398 
4399   /* ------------------------------------------------------------ */
4400   // Indexes and triggers
4401   /* ------------------------------------------------------------ */
4402 
4403   // reactivate and rebuild indexes on start up
4404   void activateIndexes(Signal* signal, Uint32 i);
4405   void activateIndex_fromBeginTrans(Signal*, Uint32 tx_key, Uint32 ret);
4406   void activateIndex_fromAlterIndex(Signal*, Uint32 tx_key, Uint32 ret);
4407   void activateIndex_fromEndTrans(Signal*, Uint32 tx_key, Uint32 ret);
4408   void rebuildIndexes(Signal* signal, Uint32 i);
4409   void rebuildIndex_fromBeginTrans(Signal*, Uint32 tx_key, Uint32 ret);
4410   void rebuildIndex_fromBuildIndex(Signal*, Uint32 tx_key, Uint32 ret);
4411   void rebuildIndex_fromEndTrans(Signal*, Uint32 tx_key, Uint32 ret);
4412   // FK re-enable (create triggers) on start up
4413   void enableFKs(Signal* signal, Uint32 i);
4414   void enableFK_fromBeginTrans(Signal*, Uint32 tx_key, Uint32 ret);
4415   void enableFK_fromCreateFK(Signal*, Uint32 tx_key, Uint32 ret);
4416   void enableFK_fromEndTrans(Signal*, Uint32 tx_key, Uint32 ret);
4417   bool c_restart_enable_fks;
4418   Uint32 c_at_restart_skip_indexes;
4419   Uint32 c_at_restart_skip_fks;
4420 
4421   // Events
4422   void
4423   createEventUTIL_PREPARE(Signal* signal,
4424 			  Uint32 callbackData,
4425 			  Uint32 returnCode);
4426   void
4427   createEventUTIL_EXECUTE(Signal *signal,
4428 			  Uint32 callbackData,
4429 			  Uint32 returnCode);
4430   void
4431   dropEventUTIL_PREPARE_READ(Signal* signal,
4432 			     Uint32 callbackData,
4433 			     Uint32 returnCode);
4434   void
4435   dropEventUTIL_EXECUTE_READ(Signal* signal,
4436 			     Uint32 callbackData,
4437 			     Uint32 returnCode);
4438   void
4439   dropEventUTIL_PREPARE_DELETE(Signal* signal,
4440 			       Uint32 callbackData,
4441 			       Uint32 returnCode);
4442   void
4443   dropEventUTIL_EXECUTE_DELETE(Signal *signal,
4444 			       Uint32 callbackData,
4445 			       Uint32 returnCode);
4446   void
4447   dropEventUtilPrepareRef(Signal* signal,
4448 			  Uint32 callbackData,
4449 			  Uint32 returnCode);
4450   void
4451   dropEventUtilExecuteRef(Signal* signal,
4452 			  Uint32 callbackData,
4453 			  Uint32 returnCode);
4454   int
4455   sendSignalUtilReq(Callback *c,
4456 		    BlockReference ref,
4457 		    GlobalSignalNumber gsn,
4458 		    Signal* signal,
4459 		    Uint32 length,
4460 		    JobBufferLevel jbuf,
4461 		    LinearSectionPtr ptr[3],
4462 		    Uint32 noOfSections);
4463   int
4464   recvSignalUtilReq(Signal* signal, Uint32 returnCode);
4465 
4466   void completeSubStartReq(Signal* signal, Uint32 ptrI,	Uint32 returnCode);
4467   void completeSubStopReq(Signal* signal, Uint32 ptrI, Uint32 returnCode);
4468   void completeSubRemoveReq(Signal* signal, Uint32 ptrI, Uint32 returnCode);
4469 
4470   void dropEvent_sendReply(Signal* signal,
4471 			   OpDropEventPtr evntRecPtr);
4472 
4473   void createEvent_RT_USER_CREATE(Signal* signal,
4474 				  OpCreateEventPtr evntRecPtr,
4475 				  SectionHandle& handle);
4476   void createEventComplete_RT_USER_CREATE(Signal* signal,
4477 					  OpCreateEventPtr evntRecPtr);
4478   void createEvent_RT_USER_GET(Signal*, OpCreateEventPtr, SectionHandle&);
4479   void createEventComplete_RT_USER_GET(Signal* signal, OpCreateEventPtr evntRecPtr);
4480 
4481   void createEvent_RT_DICT_AFTER_GET(Signal* signal, OpCreateEventPtr evntRecPtr);
4482 
4483   void createEvent_nodeFailCallback(Signal* signal, Uint32 eventRecPtrI,
4484 				    Uint32 returnCode);
4485   void createEvent_sendReply(Signal* signal, OpCreateEventPtr evntRecPtr,
4486 			     LinearSectionPtr *ptr = NULL, int noLSP = 0);
4487 
4488   void prepareTransactionEventSysTable (Callback *c,
4489 					Signal* signal,
4490 					Uint32 senderData,
4491 					UtilPrepareReq::OperationTypeValue prepReq);
4492   void prepareUtilTransaction(Callback *c,
4493 			      Signal* signal,
4494 			      Uint32 senderData,
4495 			      Uint32 tableId,
4496 			      const char *tableName,
4497 			      UtilPrepareReq::OperationTypeValue prepReq,
4498 			      Uint32 noAttr,
4499 			      Uint32 attrIds[],
4500 			      const char *attrNames[]);
4501 
4502   void executeTransEventSysTable(Callback *c,
4503 				 Signal *signal,
4504 				 const Uint32 ptrI,
4505 				 sysTab_NDBEVENTS_0& m_eventRec,
4506 				 const Uint32 prepareId,
4507 				 UtilPrepareReq::OperationTypeValue prepReq);
4508   void executeTransaction(Callback *c,
4509 			  Signal* signal,
4510 			  Uint32 senderData,
4511 			  Uint32 prepareId,
4512 			  Uint32 noAttr,
4513 			  LinearSectionPtr headerPtr,
4514 			  LinearSectionPtr dataPtr);
4515 
4516   void parseReadEventSys(Signal *signal, sysTab_NDBEVENTS_0& m_eventRec);
4517   bool upgrade_suma_NotStarted(Uint32 err, Uint32 ref) const;
4518 
4519   // support
4520   void getTableKeyList(TableRecordPtr,
4521 		       Id_array<MAX_ATTRIBUTES_IN_INDEX+1>& list);
4522   void getIndexAttr(TableRecordPtr indexPtr, Uint32 itAttr, Uint32* id);
4523   void getIndexAttrList(TableRecordPtr indexPtr, IndexAttributeList& list);
4524   void getIndexAttrMask(TableRecordPtr indexPtr, AttributeMask& mask);
4525 
4526   /* ------------------------------------------------------------ */
4527   // Initialisation
4528   /* ------------------------------------------------------------ */
4529   void initCommonData();
4530   void initRecords();
4531   void initConnectRecord();
4532   void initRetrieveRecord(Signal*, Uint32, Uint32 returnCode);
4533   void initSchemaRecord();
4534   void initRestartRecord(Uint32 sp = 0, Uint32 lp = 0,
4535                          const char * sb = 0, const char * eb = 0);
4536   void initSendSchemaRecord();
4537   void initReadTableRecord();
4538   void initWriteTableRecord();
4539   void initReadSchemaRecord();
4540   void initWriteSchemaRecord();
4541 
4542   void initNodeRecords();
4543   void initialiseTableRecord(TableRecordPtr tablePtr, Uint32 tableId);
4544   void initialiseTriggerRecord(TriggerRecordPtr triggerPtr, Uint32 triggerId);
4545   void initPageRecords();
4546 
4547   Uint32 getFsConnRecord();
4548 
4549   bool getIsFailed(Uint32 nodeId) const;
4550 
4551   void printTables(); // For debugging only
4552 
4553   void startRestoreSchema(Signal*, Callback);
4554   void restartNextPass(Signal*);
4555   void restart_fromBeginTrans(Signal*, Uint32 tx_key, Uint32 ret);
4556   void restart_fromEndTrans(Signal*, Uint32 tx_key, Uint32 ret);
4557   void restartEndPass_fromEndTrans(Signal*, Uint32 tx_key, Uint32 ret);
4558   void restart_fromWriteSchemaFile(Signal*, Uint32, Uint32);
4559   void restart_nextOp(Signal*, bool commit = false);
4560 
4561   void checkSchemaStatus(Signal* signal);
4562   void checkPendingSchemaTrans(XSchemaFile* xsf);
4563 
4564   void restartCreateObj(Signal*, Uint32, const SchemaFile::TableEntry *, bool);
4565   void restartCreateObj_readConf(Signal*, Uint32, Uint32);
4566   void restartCreateObj_getTabInfoConf(Signal*);
4567   void restartCreateObj_parse(Signal*, SegmentedSectionPtr, bool);
4568   void restartDropObj(Signal*, Uint32, const SchemaFile::TableEntry *);
4569 
4570   void restart_checkSchemaStatusComplete(Signal*, Uint32 callback, Uint32);
4571   void masterRestart_checkSchemaStatusComplete(Signal*, Uint32, Uint32);
4572 
4573   void sendSchemaComplete(Signal*, Uint32 callbackData, Uint32);
4574 
4575 public:
4576   void send_drop_file(Signal*, Uint32, Uint32, DropFileImplReq::RequestInfo);
4577   void send_drop_fg(Signal*, Uint32, Uint32, DropFilegroupImplReq::RequestInfo);
4578 
4579   int checkSingleUserMode(Uint32 senderRef);
4580 
4581   friend NdbOut& operator<<(NdbOut& out, const ErrorInfo&);
4582 #ifdef VM_TRACE
4583   friend NdbOut& operator<<(NdbOut& out, const DictObject&);
4584   friend NdbOut& operator<<(NdbOut& out, const SchemaOp&);
4585   friend NdbOut& operator<<(NdbOut& out, const SchemaTrans&);
4586   friend NdbOut& operator<<(NdbOut& out, const TxHandle&);
4587   void check_consistency();
4588   void check_consistency_entry(TableRecordPtr tablePtr);
4589   void check_consistency_table(TableRecordPtr tablePtr);
4590   void check_consistency_index(TableRecordPtr indexPtr);
4591   void check_consistency_trigger(TriggerRecordPtr triggerPtr);
4592   void check_consistency_object(DictObjectPtr obj_ptr);
4593 #endif
4594 
4595   /**
4596    * Dict lock queue does currently uniformly handle
4597    *
4598    * - starting node
4599    * - schema op
4600    *
4601    * The impl. is based on DbUtil lock's (LockQueue)
4602    *
4603    * It would be very nice to use this *fully*
4604    * But instead of introducing extra break in schema-op
4605    *   a lock queue in instantiated in Dict, for easy trylock-handling
4606    */
4607   struct DictLockType;
4608   friend struct DictLockType;
4609 
4610   struct DictLockType {
4611     DictLockReq::LockType lockType;
4612     const char* text;
4613   };
4614   static const DictLockType* getDictLockType(Uint32 lockType);
4615   void sendDictLockInfoEvent(Signal*, const UtilLockReq*, const char* text);
4616   void debugLockInfo(Signal* signal,
4617                      const char* text,
4618                      Uint32 rc);
4619   void removeStaleDictLocks(Signal* signal, const Uint32* theFailedNodes);
4620 
4621 
4622   Uint32 dict_lock_trylock(const DictLockReq* req);
4623   Uint32 dict_lock_unlock(Signal* signal, const DictLockReq* req,
4624                           DictLockReq::LockType* type=0);
4625 
4626   LockQueue::Pool m_dict_lock_pool;
4627   LockQueue m_dict_lock;
4628 
4629   /**
4630     Make a ListTablesData representation of a DictObject.
4631     @rapam dictObject The input object.
4632     @param parentTableId If not RNIL, leave 'ltd' unchanged and return false if
4633       'dictObject' does not depend on parentTableId. Foreign keys depend on
4634       each of the indexes and tables they refer, triggers depend on the
4635       table on which they are defined, and indexes depend on their base tables.
4636       All other objects are considered to be independent, such that false
4637       will be returned if parentTableId!=RNIL.
4638     @param ltd Result value.
4639     @return false if parentTableId!=RNIL and 'dictObject' did not depend on it,
4640       otherwise true.
4641   **/
4642   bool buildListTablesData(const DictObject& dictObject,
4643                            Uint32 parentTableId,
4644                            ListTablesData& ltd,
4645                            Uint32& objectVersion,
4646                            Uint32& parentObjectType,
4647                            Uint32& parentObjectId);
4648 
4649   void sendOLD_LIST_TABLES_CONF(Signal *signal, ListTablesReq*);
4650   void sendLIST_TABLES_CONF(Signal *signal, ListTablesReq*);
4651 
4652   Uint32 c_outstanding_sub_startstop;
4653   NdbNodeBitmask c_sub_startstop_lock;
4654 
4655   Uint32 get_default_fragments(Signal*, Uint32 extra_nodegroups = 0);
4656   void wait_gcp(Signal* signal, SchemaOpPtr op_ptr, Uint32 flags);
4657 
4658   void block_substartstop(Signal* signal, SchemaOpPtr op_ptr);
4659   void unblock_substartstop();
4660   void wait_substartstop(Signal* signal, Uint32 opPtrI);
4661 
4662   void upgrade_seizeTrigger(Ptr<TableRecord> tabPtr, Uint32, Uint32, Uint32);
4663 
4664   void send_event(Signal*, SchemaTransPtr&,
4665                   Uint32 ev,
4666                   Uint32 id,
4667                   Uint32 version,
4668                   Uint32 type);
4669 
4670   void startNextGetTabInfoReq(Signal*);
4671 
4672 protected:
4673   virtual bool getParam(const char * param, Uint32 * retVal);
4674 private:
4675   ArenaAllocator c_arenaAllocator;
4676   Uint32 c_noOfMetaTables;
4677   Uint32 c_default_hashmap_size;
4678 };
4679 
4680 inline bool
isTable() const4681 Dbdict::TableRecord::isTable() const
4682 {
4683   return DictTabInfo::isTable(tableType);
4684 }
4685 
4686 inline bool
isIndex() const4687 Dbdict::TableRecord::isIndex() const
4688 {
4689   return DictTabInfo::isIndex(tableType);
4690 }
4691 
4692 inline bool
isUniqueIndex() const4693 Dbdict::TableRecord::isUniqueIndex() const
4694 {
4695   return DictTabInfo::isUniqueIndex(tableType);
4696 }
4697 
4698 inline bool
isNonUniqueIndex() const4699 Dbdict::TableRecord::isNonUniqueIndex() const
4700 {
4701   return DictTabInfo::isNonUniqueIndex(tableType);
4702 }
4703 
4704 inline bool
isHashIndex() const4705 Dbdict::TableRecord::isHashIndex() const
4706 {
4707   return DictTabInfo::isHashIndex(tableType);
4708 }
4709 
4710 inline bool
isOrderedIndex() const4711 Dbdict::TableRecord::isOrderedIndex() const
4712 {
4713   return DictTabInfo::isOrderedIndex(tableType);
4714 }
4715 
4716 // quilt keeper
4717 
4718 #undef JAM_FILE_ID
4719 
4720 #endif
4721