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 TRIX_H
26 #define TRIX_H
27 
28 #include <SimulatedBlock.hpp>
29 #include <trigger_definitions.h>
30 #include <DataBuffer.hpp>
31 #include <SimpleProperties.hpp>
32 #include <signaldata/DictTabInfo.hpp>
33 #include <signaldata/CreateTrig.hpp>
34 #include <signaldata/BuildIndx.hpp>
35 #include <signaldata/IndexStatSignal.hpp>
36 #include <signaldata/GetTabInfo.hpp>
37 #include <signaldata/TuxBound.hpp>
38 
39 #define JAM_FILE_ID 432
40 
41 #define ZNOT_FOUND 626
42 
43 // Error codes
44 #define INTERNAL_ERROR_ILLEGAL_CALL 4344
45 #define INTERNAL_ERROR_TRIX_BUSY 4345
46 
47 /**
48  * TRIX - This block manages triggers and index (in coop with DICT)
49  */
50 class Trix : public SimulatedBlock
51 {
52 public:
53   Trix(Block_context&);
54   virtual ~Trix();
55 
56 public:
57   // Subscription data, when communicating with SUMA
58 
59   enum RequestType {
60     REORG_COPY = 0
61     ,REORG_DELETE = 1
62     ,INDEX_BUILD = 2
63     ,STAT_UTIL = 3  // PK op of HEAD table directly via DBUTIL
64     ,STAT_CLEAN = 4
65     ,STAT_SCAN = 5
66     ,FK_BUILD = 6
67     //ALTER_TABLE
68   };
69   typedef DataBuffer<11> AttrOrderBuffer;
70 
71 private:
72   // Private attributes
73 
74   BLOCK_DEFINES(Trix);
75 
76   // Declared but not defined
77   //DBtrix(const Trix &obj);
78   //void operator = (const Trix &);
79 
80   // Block state
81   enum BlockState {
82     NOT_STARTED,
83     STARTED,
84     NODE_FAILURE,
85     IDLE,
86     BUSY
87   };
88 
89   BlockState c_blockState;
90 
91   // Node data needed when communicating with remote TRIX:es
92   struct NodeRecord {
NodeRecordTrix::NodeRecord93     NodeRecord() {}
94     bool alive;
95     BlockReference trixRef;
96     union {
97       Uint32 nextPool;
98       Uint32 nextList;
99     };
100     Uint32 prevList;
101   };
102 
103   typedef Ptr<NodeRecord> NodeRecPtr;
104 
105   /**
106    * The pool of node records
107    */
108   ArrayPool<NodeRecord> c_theNodeRecPool;
109 
110   /**
111    * The list of other NDB nodes
112    */
113   DLList<NodeRecord> c_theNodes;
114 
115   Uint32 c_masterNodeId;
116   BlockReference c_masterTrixRef;
117   Uint16 c_noNodesFailed;
118   Uint16 c_noActiveNodes;
119 
120   AttrOrderBuffer::DataBufferPool c_theAttrOrderBufferPool;
121 
122   struct SubscriptionRecord {
SubscriptionRecordTrix::SubscriptionRecord123     SubscriptionRecord(AttrOrderBuffer::DataBufferPool & aop):
124       attributeOrder(aop)
125     {}
126     enum RequestFlags {
127       RF_WAIT_GCP = 0x1
128       ,RF_NO_DISK = 0x2
129       ,RF_TUP_ORDER = 0x4
130     };
131     Uint32 m_flags;
132     RequestType requestType;
133     BlockReference userReference; // For user
134     Uint32 connectionPtr; // For user
135     Uint32 subscriptionId; // For Suma
136     Uint32 schemaTransId;
137     Uint32 subscriptionKey; // For Suma
138     Uint32 prepareId; // For DbUtil
139     Uint32 indexType;
140     Uint32 sourceTableId;
141     Uint32 targetTableId;
142     AttrOrderBuffer attributeOrder;
143     Uint32 noOfIndexColumns;
144     Uint32 noOfKeyColumns;
145     Uint32 parallelism;
146     Uint32 fragCount;
147     Uint32 fragId;
148     Uint32 syncPtr;
149     BuildIndxRef::ErrorCode errorCode;
150     bool subscriptionCreated;
151     bool pendingSubSyncContinueConf;
152     Uint32 expectedConf; // Count in n UTIL_EXECUTE_CONF + 1 SUB_SYNC_CONF
153     Uint64 m_rows_processed;
154     Uint64 m_gci;
155     Uint32 m_statPtrI;
156     union {
157       Uint32 nextPool;
158       Uint32 nextList;
159     };
160     Uint32 prevList;
161   };
162 
163   typedef Ptr<SubscriptionRecord> SubscriptionRecPtr;
164 
165   /**
166    * The pool of node records
167    */
168   ArrayPool<SubscriptionRecord> c_theSubscriptionRecPool;
169   RSS_AP_SNAPSHOT(c_theSubscriptionRecPool);
170 
171   /**
172    * The list of other subscriptions
173    */
174   DLList<SubscriptionRecord> c_theSubscriptions;
175 
176   /*
177    * Ordered index stats.  Implements sub-ops of DBDICT index stat
178    * schema op.  Each sub-op is a simple REQ which seizes and releases
179    * a stat op here before returning CONF or REF.  A stat op always has
180    * an associated SubscriptionRecord.  It is used for SUMA index scans
181    * and as proxy for PK ops to DBUTIL.
182    */
183 
184   bool c_statGetMetaDone;
185   struct SysColumn {
186     Uint32 pos;
187     const char* name;
188     bool keyFlag;
189   };
190   struct SysTable {
191     const char* name;
192     mutable Uint32 tableId;
193     const Uint32 columnCount;
194     const SysColumn* columnList;
195   };
196   struct SysIndex {
197     const char* name;
198     mutable Uint32 tableId;
199     mutable Uint32 indexId;
200   };
201   static const SysColumn g_statMetaHead_column[];
202   static const SysColumn g_statMetaSample_column[];
203   static const SysTable g_statMetaHead;
204   static const SysTable g_statMetaSample;
205   static const SysIndex g_statMetaSampleX1;
206 
207   struct StatOp {
208     struct Meta {
209       GetTabInfoConf m_conf;
210       Callback m_cb;
211     };
212     struct Data {
213       Int32 m_head_found;
214       Uint32 m_indexId;
215       Uint32 m_indexVersion;
216       Uint32 m_tableId;
217       Uint32 m_fragCount;
218       Uint32 m_valueFormat;
219       Uint32 m_sampleVersion;
220       Uint32 m_loadTime;
221       Uint32 m_sampleCount;
222       Uint32 m_keyBytes;
223       Uint32* m_statKey;
224       Uint32* m_statValue;
DataTrix::StatOp::Data225       Data() {
226         m_head_found = -1;
227         m_sampleVersion = 0;
228       }
229     };
230     struct Attr {
231       Uint32* m_attr;
232       Uint32 m_attrMax;
233       Uint32 m_attrSize;
234       Uint32* m_data;
235       Uint32 m_dataMax;
236       Uint32 m_dataSize;
AttrTrix::StatOp::Attr237       Attr() {}
238     };
239     struct Util {
240       Uint32 m_prepareId;
241       bool m_not_found;
242       Callback m_cb;
UtilTrix::StatOp::Util243       Util() {
244         m_prepareId = RNIL;
245         m_not_found = false; // read + ZNOT_FOUND
246       };
247     };
248     struct Clean {
249       Uint32 m_cleanCount;
250       // bounds on index_id, index_version, sample_version
251       Uint32 m_bound[3 * 3];
252       Uint32 m_boundCount;
253       Uint32 m_boundSize;
CleanTrix::StatOp::Clean254       Clean() {}
255     };
256     struct Scan {
257       Uint32 m_sampleCount;
258       Uint32 m_keyBytes;
ScanTrix::StatOp::Scan259       Scan() {}
260     };
261     struct Drop {
262     };
263     struct Send {
264       const SysTable* m_sysTable;
265       Uint32 m_operationType;     // UtilPrepareReq::OperationTypeValue
266       Uint32 m_prepareId;
SendTrix::StatOp::Send267       Send() {}
268     };
269     IndexStatImplReq m_req;
270     Uint32 m_requestType;
271     const char* m_requestName;
272     Uint32 m_subRecPtrI;
273     Meta m_meta;
274     Data m_data;
275     Attr m_attr;
276     Util m_util;
277     Clean m_clean;
278     Scan m_scan;
279     Drop m_drop;
280     Send m_send;
281     Uint32 m_errorCode;
282     Uint32 m_errorLine;
283     union {
284       Uint32 m_ownPtrI;
285       Uint32 nextPool;
286     };
StatOpTrix::StatOp287     StatOp() {
288       m_subRecPtrI = RNIL;
289       m_errorCode = 0;
290       m_errorLine = 0;
291     };
292   };
293   typedef Ptr<StatOp> StatOpPtr;
294   ArrayPool<StatOp> c_statOpPool;
295   RSS_AP_SNAPSHOT(c_statOpPool);
296 
297   // System start
298   void execREAD_CONFIG_REQ(Signal* signal);
299   void execSTTOR(Signal* signal);
300   void execNDB_STTOR(Signal* signal);
301 
302   // Node management
303   void execREAD_NODESCONF(Signal* signal);
304   void execREAD_NODESREF(Signal* signal);
305   void execNODE_FAILREP(Signal* signal);
306   void execINCL_NODEREQ(Signal* signal);
307   // Debugging
308   void execDUMP_STATE_ORD(Signal* signal);
309 
310   void execDBINFO_SCANREQ(Signal* signal);
311 
312   // Build index
313   void execBUILD_INDX_IMPL_REQ(Signal* signal);
314   void execBUILD_INDX_IMPL_CONF(Signal* signal);
315   void execBUILD_INDX_IMPL_REF(Signal* signal);
316 
317   void execCOPY_DATA_IMPL_REQ(Signal* signal);
318 
319   // Build FK
320   void execBUILD_FK_IMPL_REQ(Signal*);
321 
322   void execUTIL_PREPARE_CONF(Signal* signal);
323   void execUTIL_PREPARE_REF(Signal* signal);
324   void execUTIL_EXECUTE_CONF(Signal* signal);
325   void execUTIL_EXECUTE_REF(Signal* signal);
326   void execUTIL_RELEASE_CONF(Signal* signal);
327   void execUTIL_RELEASE_REF(Signal* signal);
328 
329   // Suma signals
330   void execSUB_CREATE_CONF(Signal* signal);
331   void execSUB_CREATE_REF(Signal* signal);
332   void execSUB_REMOVE_CONF(Signal* signal);
333   void execSUB_REMOVE_REF(Signal* signal);
334   void execSUB_SYNC_CONF(Signal* signal);
335   void execSUB_SYNC_REF(Signal* signal);
336   void execSUB_SYNC_CONTINUE_REQ(Signal* signal);
337   void execSUB_TABLE_DATA(Signal* signal);
338 
339   // GCP
340   void execWAIT_GCP_REF(Signal*);
341   void execWAIT_GCP_CONF(Signal*);
342 
343   // Utility functions
344   void setupSubscription(Signal* signal, SubscriptionRecPtr subRecPtr);
345   void startTableScan(Signal* signal, SubscriptionRecPtr subRecPtr);
346   void prepareInsertTransactions(Signal* signal, SubscriptionRecPtr subRecPtr);
347   void executeBuildInsertTransaction(Signal* signal, SubscriptionRecPtr);
348   void executeReorgTransaction(Signal*, SubscriptionRecPtr, Uint32);
349   void executeBuildFKTransaction(Signal* signal, SubscriptionRecPtr);
350   void buildComplete(Signal* signal, SubscriptionRecPtr subRecPtr);
351   void wait_gcp(Signal*, SubscriptionRecPtr subRecPtr, Uint32 delay = 0);
352   void buildFailed(Signal* signal,
353 		   SubscriptionRecPtr subRecPtr,
354 		   BuildIndxRef::ErrorCode);
355   void checkParallelism(Signal* signal, SubscriptionRecord* subRec);
356 
357   // index stats
358   StatOp& statOpGetPtr(Uint32 statPtrI);
359   bool statOpSeize(Uint32& statPtrI);
360   void statOpRelease(StatOp&);
361   void execINDEX_STAT_IMPL_REQ(Signal*);
362   // sys tables metadata
363   void statMetaGetHead(Signal*, StatOp&);
364   void statMetaGetHeadCB(Signal*, Uint32 statPtrI, Uint32 ret);
365   void statMetaGetSample(Signal*, StatOp&);
366   void statMetaGetSampleCB(Signal*, Uint32 statPtrI, Uint32 ret);
367   void statMetaGetSampleX1(Signal*, StatOp&);
368   void statMetaGetSampleX1CB(Signal*, Uint32 statPtrI, Uint32 ret);
369   void sendGetTabInfoReq(Signal*, StatOp&, const char* name);
370   void execGET_TABINFO_CONF(Signal*);
371   void execGET_TABINFO_REF(Signal*);
372   // continue
373   void statGetMetaDone(Signal*, StatOp&);
374   // head table ops
375   void statHeadRead(Signal*, StatOp&);
376   void statHeadReadCB(Signal*, Uint32 statPtrI, Uint32 ret);
377   void statHeadInsert(Signal*, StatOp&);
378   void statHeadInsertCB(Signal*, Uint32 statPtrI, Uint32 ret);
379   void statHeadUpdate(Signal*, StatOp&);
380   void statHeadUpdateCB(Signal*, Uint32 statPtrI, Uint32 ret);
381   void statHeadDelete(Signal*, StatOp&);
382   void statHeadDeleteCB(Signal*, Uint32 statPtrI, Uint32 ret);
383   // util
384   void statUtilPrepare(Signal*, StatOp&);
385   void statUtilPrepareConf(Signal*, Uint32 statPtrI);
386   void statUtilPrepareRef(Signal*, Uint32 statPtrI);
387   void statUtilExecute(Signal*, StatOp&);
388   void statUtilExecuteConf(Signal*, Uint32 statPtrI);
389   void statUtilExecuteRef(Signal*, Uint32 statPtrI);
390   void statUtilRelease(Signal*, StatOp&);
391   void statUtilReleaseConf(Signal*, Uint32 statPtrI);
392   // continue
393   void statReadHeadDone(Signal*, StatOp&);
394   void statInsertHeadDone(Signal*, StatOp&);
395   void statUpdateHeadDone(Signal*, StatOp&);
396   void statDeleteHeadDone(Signal*, StatOp&);
397   // clean
398   void statCleanBegin(Signal*, StatOp&);
399   void statCleanPrepare(Signal*, StatOp&);
400   void statCleanExecute(Signal*, StatOp&);
401   void statCleanRelease(Signal*, StatOp&);
402   void statCleanEnd(Signal*, StatOp&);
403   // scan
404   void statScanBegin(Signal*, StatOp&);
405   void statScanPrepare(Signal*, StatOp&);
406   void statScanExecute(Signal*, StatOp&);
407   void statScanRelease(Signal*, StatOp&);
408   void statScanEnd(Signal*, StatOp&);
409   // drop
410   void statDropBegin(Signal*, StatOp&);
411   void statDropEnd(Signal*, StatOp&);
412   // send
413   void statSendPrepare(Signal*, StatOp&);
414   void statSendExecute(Signal*, StatOp&);
415   void statSendRelease(Signal*, StatOp&);
416   // data
417   void statDataPtr(StatOp&, Uint32 i, Uint32*& dptr, Uint32& bytes);
418   void statDataOut(StatOp&, Uint32 i);
419   void statDataIn(StatOp&, Uint32 i);
420   // abort ongoing
421   void statAbortUtil(Signal*, StatOp&);
422   void statAbortUtilCB(Signal*, Uint32 statPtrI, Uint32 ret);
423   // conf and ref
424   void statOpSuccess(Signal*, StatOp&);
425   void statOpConf(Signal*, StatOp&);
426   void statOpError(Signal*, StatOp&, Uint32 errorCode, Uint32 errorLine,
427                    const Uint32 * supress = 0);
428   void statOpAbort(Signal*, StatOp&);
429   void statOpRef(Signal*, StatOp&);
430   void statOpRef(Signal*, const IndexStatImplReq*, Uint32 errorCode, Uint32 errorLine);
431   void statOpEvent(StatOp&, const char* level, const char* msg, ...);
432   // debug
433   friend class NdbOut& operator<<(NdbOut&, const StatOp& stat);
434 };
435 
436 
437 #undef JAM_FILE_ID
438 
439 #endif
440