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 
26 #define DBTUP_C
27 #define DBTUP_GEN_CPP
28 #include "Dbtup.hpp"
29 #include <RefConvert.hpp>
30 #include <ndb_limits.h>
31 #include <pc.hpp>
32 #include <AttributeDescriptor.hpp>
33 #include "AttributeOffset.hpp"
34 #include <AttributeHeader.hpp>
35 #include <Interpreter.hpp>
36 #include <signaldata/FsConf.hpp>
37 #include <signaldata/FsRef.hpp>
38 #include <signaldata/FsRemoveReq.hpp>
39 #include <signaldata/TupCommit.hpp>
40 #include <signaldata/TupKey.hpp>
41 #include <signaldata/NodeFailRep.hpp>
42 #include <signaldata/NodeStateSignalData.hpp>
43 
44 #include <signaldata/DropTab.hpp>
45 #include <IntrusiveList.hpp>
46 
47 #include <EventLogger.hpp>
48 
49 #define JAM_FILE_ID 420
50 
51 extern EventLogger * g_eventLogger;
52 
53 #define DEBUG(x) { ndbout << "TUP::" << x << endl; }
54 
initData()55 void Dbtup::initData()
56 {
57   TablerecPtr tablePtr;
58   (void)tablePtr; // hide unused warning
59   cnoOfFragrec = NDB_ARRAY_SIZE(tablePtr.p->fragrec);
60   cnoOfFragoprec = NDB_ARRAY_SIZE(tablePtr.p->fragrec);
61   cnoOfAlterTabOps = NDB_ARRAY_SIZE(tablePtr.p->fragrec);
62   c_maxTriggersPerTable = ZDEFAULT_MAX_NO_TRIGGERS_PER_TABLE;
63   c_noOfBuildIndexRec = 32;
64 
65   cCopyProcedure = RNIL;
66   cCopyLastSeg = RNIL;
67   cCopyOverwrite = 0;
68   cCopyOverwriteLen = 0;
69 
70   // Records with constant sizes
71   init_list_sizes();
72   cpackedListIndex = 0;
73 
74   m_minFreePages = 0;
75 }//Dbtup::initData()
76 
Dbtup(Block_context & ctx,Uint32 instanceNumber)77 Dbtup::Dbtup(Block_context& ctx, Uint32 instanceNumber)
78   : SimulatedBlock(DBTUP, ctx, instanceNumber),
79     c_lqh(0),
80     c_backup(0),
81     c_tsman(0),
82     c_lgman(0),
83     c_pgman(0),
84     c_extent_hash(c_extent_pool),
85     c_storedProcPool(),
86     c_buildIndexList(c_buildIndexPool),
87     c_undo_buffer(&ctx.m_mm),
88     m_pages_allocated(0),
89     m_pages_allocated_max(0),
90     f_undo_done(true)
91 {
92   BLOCK_CONSTRUCTOR(Dbtup);
93 
94   addRecSignal(GSN_DEBUG_SIG, &Dbtup::execDEBUG_SIG);
95   addRecSignal(GSN_CONTINUEB, &Dbtup::execCONTINUEB);
96   addRecSignal(GSN_LCP_FRAG_ORD, &Dbtup::execLCP_FRAG_ORD);
97   addRecSignal(GSN_NODE_FAILREP, &Dbtup::execNODE_FAILREP);
98 
99   addRecSignal(GSN_DUMP_STATE_ORD, &Dbtup::execDUMP_STATE_ORD);
100   addRecSignal(GSN_DBINFO_SCANREQ, &Dbtup::execDBINFO_SCANREQ);
101   addRecSignal(GSN_SEND_PACKED, &Dbtup::execSEND_PACKED, true);
102   addRecSignal(GSN_STTOR, &Dbtup::execSTTOR);
103   addRecSignal(GSN_MEMCHECKREQ, &Dbtup::execMEMCHECKREQ);
104   addRecSignal(GSN_TUPSEIZEREQ, &Dbtup::execTUPSEIZEREQ);
105   addRecSignal(GSN_TUPRELEASEREQ, &Dbtup::execTUPRELEASEREQ);
106   addRecSignal(GSN_STORED_PROCREQ, &Dbtup::execSTORED_PROCREQ);
107 
108   addRecSignal(GSN_CREATE_TAB_REQ, &Dbtup::execCREATE_TAB_REQ);
109   addRecSignal(GSN_TUPFRAGREQ, &Dbtup::execTUPFRAGREQ);
110   addRecSignal(GSN_TUP_ADD_ATTRREQ, &Dbtup::execTUP_ADD_ATTRREQ);
111   addRecSignal(GSN_ALTER_TAB_REQ, &Dbtup::execALTER_TAB_REQ);
112   addRecSignal(GSN_TUP_COMMITREQ, &Dbtup::execTUP_COMMITREQ);
113   addRecSignal(GSN_TUP_ABORTREQ, &Dbtup::execTUP_ABORTREQ);
114   addRecSignal(GSN_NDB_STTOR, &Dbtup::execNDB_STTOR);
115   addRecSignal(GSN_READ_CONFIG_REQ, &Dbtup::execREAD_CONFIG_REQ, true);
116   addRecSignal(GSN_NODE_STATE_REP, &Dbtup::execNODE_STATE_REP, true);
117 
118   // Trigger Signals
119   addRecSignal(GSN_CREATE_TRIG_IMPL_REQ, &Dbtup::execCREATE_TRIG_IMPL_REQ);
120   addRecSignal(GSN_DROP_TRIG_IMPL_REQ,  &Dbtup::execDROP_TRIG_IMPL_REQ);
121 
122   addRecSignal(GSN_DROP_TAB_REQ, &Dbtup::execDROP_TAB_REQ);
123 
124   addRecSignal(GSN_TUP_DEALLOCREQ, &Dbtup::execTUP_DEALLOCREQ);
125   addRecSignal(GSN_TUP_WRITELOG_REQ, &Dbtup::execTUP_WRITELOG_REQ);
126 
127   // Ordered index related
128   addRecSignal(GSN_BUILD_INDX_IMPL_REQ, &Dbtup::execBUILD_INDX_IMPL_REQ);
129   addRecSignal(GSN_BUILD_INDX_IMPL_REF, &Dbtup::execBUILD_INDX_IMPL_REF);
130   addRecSignal(GSN_BUILD_INDX_IMPL_CONF, &Dbtup::execBUILD_INDX_IMPL_CONF);
131   addRecSignal(GSN_ALTER_TAB_CONF, &Dbtup::execALTER_TAB_CONF);
132   m_max_parallel_index_build = 0;
133 
134   // Tup scan
135   addRecSignal(GSN_ACC_SCANREQ, &Dbtup::execACC_SCANREQ);
136   addRecSignal(GSN_NEXT_SCANREQ, &Dbtup::execNEXT_SCANREQ);
137   addRecSignal(GSN_ACC_CHECK_SCAN, &Dbtup::execACC_CHECK_SCAN);
138   addRecSignal(GSN_ACCKEYCONF, &Dbtup::execACCKEYCONF);
139   addRecSignal(GSN_ACCKEYREF, &Dbtup::execACCKEYREF);
140   addRecSignal(GSN_ACC_ABORTCONF, &Dbtup::execACC_ABORTCONF);
141 
142   // Drop table
143   addRecSignal(GSN_FSREMOVEREF, &Dbtup::execFSREMOVEREF, true);
144   addRecSignal(GSN_FSREMOVECONF, &Dbtup::execFSREMOVECONF, true);
145 
146   addRecSignal(GSN_DROP_FRAG_REQ, &Dbtup::execDROP_FRAG_REQ);
147   addRecSignal(GSN_SUB_GCP_COMPLETE_REP, &Dbtup::execSUB_GCP_COMPLETE_REP);
148 
149   addRecSignal(GSN_FIRE_TRIG_REQ, &Dbtup::execFIRE_TRIG_REQ);
150 
151   fragoperrec = 0;
152   fragrecord = 0;
153   alterTabOperRec = 0;
154   hostBuffer = 0;
155   tablerec = 0;
156   tableDescriptor = 0;
157 
158   initData();
159   CLEAR_ERROR_INSERT_VALUE;
160 
161   RSS_OP_COUNTER_INIT(cnoOfFreeFragoprec);
162   RSS_OP_COUNTER_INIT(cnoOfFreeFragrec);
163   RSS_OP_COUNTER_INIT(cnoOfFreeTabDescrRec);
164   c_storedProcCountNonAPI = 0;
165 
166   {
167     CallbackEntry& ce = m_callbackEntry[THE_NULL_CALLBACK];
168     ce.m_function = TheNULLCallback.m_callbackFunction;
169     ce.m_flags = 0;
170   }
171   { // 1
172     CallbackEntry& ce = m_callbackEntry[UNDO_CREATETABLE_LOGSYNC_CALLBACK];
173     ce.m_function = safe_cast(&Dbtup::undo_createtable_logsync_callback);
174     ce.m_flags = 0;
175   }
176   { // 2
177     CallbackEntry& ce = m_callbackEntry[DROP_TABLE_LOGSYNC_CALLBACK];
178     ce.m_function = safe_cast(&Dbtup::drop_table_logsync_callback);
179     ce.m_flags = 0;
180   }
181   { // 3
182     CallbackEntry& ce = m_callbackEntry[UNDO_CREATETABLE_CALLBACK];
183     ce.m_function = safe_cast(&Dbtup::undo_createtable_callback);
184     ce.m_flags = 0;
185   }
186   { // 4
187     CallbackEntry& ce = m_callbackEntry[DROP_TABLE_LOG_BUFFER_CALLBACK];
188     ce.m_function = safe_cast(&Dbtup::drop_table_log_buffer_callback);
189     ce.m_flags = 0;
190   }
191   { // 5
192     CallbackEntry& ce = m_callbackEntry[DROP_FRAGMENT_FREE_EXTENT_LOG_BUFFER_CALLBACK];
193     ce.m_function = safe_cast(&Dbtup::drop_fragment_free_extent_log_buffer_callback);
194     ce.m_flags = 0;
195   }
196   { // 6
197     CallbackEntry& ce = m_callbackEntry[NR_DELETE_LOG_BUFFER_CALLBACK];
198     ce.m_function = safe_cast(&Dbtup::nr_delete_log_buffer_callback);
199     ce.m_flags = 0;
200   }
201   { // 7
202     CallbackEntry& ce = m_callbackEntry[DISK_PAGE_LOG_BUFFER_CALLBACK];
203     ce.m_function = safe_cast(&Dbtup::disk_page_log_buffer_callback);
204     ce.m_flags = CALLBACK_ACK;
205   }
206   {
207     CallbackTable& ct = m_callbackTable;
208     ct.m_count = COUNT_CALLBACKS;
209     ct.m_entry = m_callbackEntry;
210     m_callbackTableAddr = &ct;
211   }
212 }//Dbtup::Dbtup()
213 
~Dbtup()214 Dbtup::~Dbtup()
215 {
216   /* Free Fragment Copy Procedure info */
217   freeCopyProcedure();
218 
219   // Records with dynamic sizes
220   c_page_pool.clear();
221 
222   deallocRecord((void **)&fragoperrec,"Fragoperrec",
223 		sizeof(Fragoperrec),
224 		cnoOfFragoprec);
225 
226   deallocRecord((void **)&fragrecord,"Fragrecord",
227 		sizeof(Fragrecord),
228 		cnoOfFragrec);
229 
230   deallocRecord((void **)&alterTabOperRec,"AlterTabOperRec",
231                 sizeof(alterTabOperRec),
232                 cnoOfAlterTabOps);
233 
234   deallocRecord((void **)&hostBuffer,"HostBuffer",
235 		sizeof(HostBuffer),
236 		MAX_NODES);
237 
238   deallocRecord((void **)&tablerec,"Tablerec",
239 		sizeof(Tablerec),
240 		cnoOfTablerec);
241 
242   deallocRecord((void **)&tableDescriptor, "TableDescriptor",
243 		sizeof(TableDescriptor),
244 		cnoOfTabDescrRec);
245 
246 }//Dbtup::~Dbtup()
247 
Apply_undo()248 Dbtup::Apply_undo::Apply_undo()
249 {
250   m_type = 0;
251   m_len = 0;
252   m_ptr = 0;
253   m_lsn = (Uint64)0;
254   m_table_ptr.setNull();
255   m_fragment_ptr.setNull();
256   m_page_ptr.setNull();
257   m_extent_ptr.setNull();
258   m_key.setNull();
259 }
260 
BLOCK_FUNCTIONS(Dbtup)261 BLOCK_FUNCTIONS(Dbtup)
262 
263 void Dbtup::execCONTINUEB(Signal* signal)
264 {
265   jamEntry();
266   Uint32 actionType = signal->theData[0];
267   Uint32 dataPtr = signal->theData[1];
268 
269   switch (actionType) {
270   case ZINITIALISE_RECORDS:
271     jam();
272     initialiseRecordsLab(signal, dataPtr,
273 			 signal->theData[2], signal->theData[3]);
274     break;
275   case ZREL_FRAG:
276     jam();
277     releaseFragment(signal, dataPtr, signal->theData[2]);
278     break;
279   case ZBUILD_INDEX:
280     jam();
281     buildIndex(signal, dataPtr);
282     break;
283   case ZTUP_SCAN:
284     jam();
285     {
286       ScanOpPtr scanPtr;
287       c_scanOpPool.getPtr(scanPtr, dataPtr);
288       scanCont(signal, scanPtr);
289     }
290     return;
291   case ZFREE_EXTENT:
292   {
293     jam();
294     TablerecPtr tabPtr;
295     tabPtr.i= dataPtr;
296     FragrecordPtr fragPtr;
297     fragPtr.i= signal->theData[2];
298     ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
299     ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
300     drop_fragment_free_extent(signal, tabPtr, fragPtr, signal->theData[3]);
301     return;
302   }
303   case ZUNMAP_PAGES:
304   {
305     jam();
306     TablerecPtr tabPtr;
307     tabPtr.i= dataPtr;
308     FragrecordPtr fragPtr;
309     fragPtr.i= signal->theData[2];
310     ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
311     ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
312     drop_fragment_unmap_pages(signal, tabPtr, fragPtr, signal->theData[3]);
313     return;
314   }
315   case ZFREE_VAR_PAGES:
316   {
317     jam();
318     drop_fragment_free_var_pages(signal);
319     return;
320   }
321   case ZFREE_PAGES:
322   {
323     jam();
324     drop_fragment_free_pages(signal);
325     return;
326   }
327   case ZREBUILD_FREE_PAGE_LIST:
328   {
329     jam();
330     rebuild_page_free_list(signal);
331     return;
332   }
333   case ZDISK_RESTART_UNDO:
334   {
335     jam();
336     if (!assembleFragments(signal)) {
337       jam();
338       return;
339     }
340     Uint32 type = signal->theData[1];
341     Uint32 len = signal->theData[2];
342     Uint64 lsn_hi = signal->theData[3];
343     Uint64 lsn_lo = signal->theData[4];
344     Uint64 lsn = (lsn_hi << 32) | lsn_lo;
345     SectionHandle handle(this, signal);
346     ndbrequire(handle.m_cnt == 1);
347     SegmentedSectionPtr ssptr;
348     handle.getSection(ssptr, 0);
349     ::copy(c_proxy_undo_data, ssptr);
350     releaseSections(handle);
351     disk_restart_undo(signal, lsn, type, c_proxy_undo_data, len);
352     return;
353   }
354 
355   default:
356     ndbrequire(false);
357     break;
358   }//switch
359 }//Dbtup::execTUP_CONTINUEB()
360 
361 /* **************************************************************** */
362 /* ---------------------------------------------------------------- */
363 /* ------------------- SYSTEM RESTART MODULE ---------------------- */
364 /* ---------------------------------------------------------------- */
365 /* **************************************************************** */
execSTTOR(Signal * signal)366 void Dbtup::execSTTOR(Signal* signal)
367 {
368   jamEntry();
369   Uint32 startPhase = signal->theData[1];
370   Uint32 sigKey = signal->theData[6];
371   switch (startPhase) {
372   case ZSTARTPHASE1:
373     jam();
374     ndbrequire((c_lqh= (Dblqh*)globalData.getBlock(DBLQH, instance())) != 0);
375     ndbrequire((c_backup= (Backup*)globalData.getBlock(BACKUP, instance())) != 0);
376     ndbrequire((c_tsman= (Tsman*)globalData.getBlock(TSMAN)) != 0);
377     ndbrequire((c_lgman= (Lgman*)globalData.getBlock(LGMAN)) != 0);
378     ndbrequire((c_pgman= (Pgman*)globalData.getBlock(PGMAN, instance())) != 0);
379     cownref = calcInstanceBlockRef(DBTUP);
380     break;
381   default:
382     jam();
383     break;
384   }//switch
385   signal->theData[0] = sigKey;
386   signal->theData[1] = 3;
387   signal->theData[2] = 2;
388   signal->theData[3] = ZSTARTPHASE1;
389   signal->theData[4] = 255;
390   BlockReference cntrRef = !isNdbMtLqh() ? NDBCNTR_REF : DBTUP_REF;
391   sendSignal(cntrRef, GSN_STTORRY, signal, 5, JBB);
392   return;
393 }//Dbtup::execSTTOR()
394 
395 /************************************************************************************************/
396 // SIZE_ALTREP INITIALIZE DATA STRUCTURES, FILES AND DS VARIABLES, GET READY FOR EXTERNAL
397 // CONNECTIONS.
398 /************************************************************************************************/
execREAD_CONFIG_REQ(Signal * signal)399 void Dbtup::execREAD_CONFIG_REQ(Signal* signal)
400 {
401   const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
402   Uint32 ref = req->senderRef;
403   Uint32 senderData = req->senderData;
404   ndbrequire(req->noOfParameters == 0);
405 
406   jamEntry();
407 
408   const ndb_mgm_configuration_iterator * p =
409     m_ctx.m_config.getOwnConfigIterator();
410   ndbrequire(p != 0);
411 
412   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_FRAG, &cnoOfFragrec));
413 
414   Uint32 noOfTriggers= 0;
415   Uint32 noOfAttribs = 0;
416 
417   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_TABLE, &cnoOfTablerec));
418   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_ATTRIBUTES, &noOfAttribs));
419 
420   Uint32 noOfStoredProc;
421   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_STORED_PROC,
422 					&noOfStoredProc));
423   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_TRIGGERS,
424 					&noOfTriggers));
425 
426 
427   {
428     Uint32 keyDesc = noOfAttribs;
429     Uint32 maxKeyDesc = cnoOfTablerec * MAX_ATTRIBUTES_IN_INDEX;
430     if (keyDesc > maxKeyDesc)
431     {
432       /**
433        * There can be no-more key's
434        *   than "cnoOfTablerec * MAX_ATTRIBUTES_IN_INDEX"
435        */
436       jam();
437       keyDesc = maxKeyDesc;
438     }
439 
440     cnoOfTabDescrRec =
441       cnoOfTablerec * 2 * (ZTD_SIZE + ZTD_TRAILER_SIZE) +
442       noOfAttribs * (sizeOfReadFunction() + // READ
443                      sizeOfReadFunction() + // UPDATE
444                      (sizeof(char*) >> 2) + // Charset
445                      ZAD_SIZE +             // Descriptor
446                      1 +                    // real order
447                      InternalMaxDynFix) +   // Worst case dynamic
448       keyDesc;                              // key-descr
449 
450     cnoOfTabDescrRec = (cnoOfTabDescrRec & 0xFFFFFFF0) + 16;
451   }
452 
453   initRecords();
454 
455   c_storedProcPool.setSize(noOfStoredProc);
456 
457   // Allocate fragment copy procedure
458   allocCopyProcedure();
459 
460   c_buildIndexPool.setSize(c_noOfBuildIndexRec);
461   c_triggerPool.setSize(noOfTriggers, false, true, true, CFG_DB_NO_TRIGGERS);
462 
463   c_extent_hash.setSize(1024); // 4k
464 
465   Pool_context pc;
466   pc.m_block = this;
467   c_page_request_pool.wo_pool_init(RT_DBTUP_PAGE_REQUEST, pc);
468   c_extent_pool.init(RT_DBTUP_EXTENT_INFO, pc);
469   NdbMutex_Init(&c_page_map_pool_mutex);
470   c_page_map_pool.init(&c_page_map_pool_mutex, RT_DBTUP_PAGE_MAP, pc);
471 
472   Uint32 nScanOp;       // use TUX config for now
473   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_SCAN_OP, &nScanOp));
474   c_scanOpPool.setSize(nScanOp + 1);
475   Uint32 nScanBatch;
476   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_BATCH_SIZE, &nScanBatch));
477   c_scanLockPool.setSize(nScanOp * nScanBatch);
478 
479 
480   /* read ahead for disk scan can not be more that disk page buffer */
481   {
482     Uint64 tmp = 64*1024*1024;
483     ndb_mgm_get_int64_parameter(p, CFG_DB_DISK_PAGE_BUFFER_MEMORY, &tmp);
484     tmp = (tmp  + GLOBAL_PAGE_SIZE - 1) / GLOBAL_PAGE_SIZE; // in pages
485     // never read ahead more than 32 pages
486     if (tmp > 32)
487       m_max_page_read_ahead = 32;
488     else
489       m_max_page_read_ahead = (Uint32)tmp;
490   }
491 
492 
493   ScanOpPtr lcp;
494   ndbrequire(c_scanOpPool.seize(lcp));
495   new (lcp.p) ScanOp();
496   c_lcp_scan_op= lcp.i;
497 
498   czero = 0;
499   cminusOne = czero - 1;
500   clastBitMask = 1;
501   clastBitMask = clastBitMask << 31;
502 
503   ndb_mgm_get_int_parameter(p, CFG_DB_MT_BUILD_INDEX,
504                             &m_max_parallel_index_build);
505 
506   if (isNdbMtLqh() && globalData.ndbMtLqhThreads > 1)
507   {
508     /**
509      * Divide by LQH threads
510      */
511     Uint32 val = m_max_parallel_index_build;
512     val = (val + instance() - 1) / globalData.ndbMtLqhThreads;
513     m_max_parallel_index_build = val;
514   }
515 
516   initialiseRecordsLab(signal, 0, ref, senderData);
517 
518   {
519     Uint32 val = 0;
520     ndb_mgm_get_int_parameter(p, CFG_DB_CRASH_ON_CORRUPTED_TUPLE,
521                               &val);
522     c_crashOnCorruptedTuple = val ? true : false;
523   }
524 
525 }
526 
initRecords()527 void Dbtup::initRecords()
528 {
529   unsigned i;
530   Uint32 tmp;
531   Uint32 tmp1 = 0;
532   const ndb_mgm_configuration_iterator * p =
533     m_ctx.m_config.getOwnConfigIterator();
534   ndbrequire(p != 0);
535 
536   // Records with dynamic sizes
537   void* ptr = m_ctx.m_mm.get_memroot();
538   c_page_pool.set((Page*)ptr, (Uint32)~0);
539 
540   fragoperrec = (Fragoperrec*)allocRecord("Fragoperrec",
541 					  sizeof(Fragoperrec),
542 					  cnoOfFragoprec);
543 
544   fragrecord = (Fragrecord*)allocRecord("Fragrecord",
545 					sizeof(Fragrecord),
546 					cnoOfFragrec);
547 
548   alterTabOperRec = (AlterTabOperation*)allocRecord("AlterTabOperation",
549                                                     sizeof(AlterTabOperation),
550                                                     cnoOfAlterTabOps);
551 
552   hostBuffer = (HostBuffer*)allocRecord("HostBuffer",
553 					sizeof(HostBuffer),
554 					MAX_NODES);
555 
556   tableDescriptor = (TableDescriptor*)allocRecord("TableDescriptor",
557 						  sizeof(TableDescriptor),
558 						  cnoOfTabDescrRec);
559 
560   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUP_OP_RECS, &tmp));
561   ndb_mgm_get_int_parameter(p, CFG_DB_NO_LOCAL_OPS, &tmp1);
562   c_operation_pool.setSize(tmp, false, true, true,
563       tmp1 == 0 ? CFG_DB_NO_OPS : CFG_DB_NO_LOCAL_OPS);
564 
565   tablerec = (Tablerec*)allocRecord("Tablerec",
566 				    sizeof(Tablerec),
567 				    cnoOfTablerec);
568 
569   for (i = 0; i<cnoOfTablerec; i++) {
570     void * p = &tablerec[i];
571     new (p) Tablerec(c_triggerPool);
572   }
573 }//Dbtup::initRecords()
574 
initialiseRecordsLab(Signal * signal,Uint32 switchData,Uint32 retRef,Uint32 retData)575 void Dbtup::initialiseRecordsLab(Signal* signal, Uint32 switchData,
576 				 Uint32 retRef, Uint32 retData)
577 {
578   switch (switchData) {
579   case 0:
580     jam();
581     initializeHostBuffer();
582     break;
583   case 1:
584     jam();
585     initializeOperationrec();
586     break;
587   case 2:
588     jam();
589     initializePage();
590     break;
591   case 3:
592     jam();
593     break;
594   case 4:
595     jam();
596     initializeTablerec();
597     break;
598   case 5:
599     jam();
600     break;
601   case 6:
602     jam();
603     initializeFragrecord();
604     break;
605   case 7:
606     jam();
607     initializeFragoperrec();
608     break;
609   case 8:
610     jam();
611     break;
612   case 9:
613     jam();
614     initializeTabDescr();
615     break;
616   case 10:
617     jam();
618     initializeAlterTabOperation();
619     break;
620   case 11:
621     jam();
622     break;
623   case 12:
624     jam();
625     break;
626   case 13:
627     jam();
628     break;
629   case 14:
630     jam();
631 
632     {
633       ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
634       conf->senderRef = reference();
635       conf->senderData = retData;
636       sendSignal(retRef, GSN_READ_CONFIG_CONF, signal,
637 		 ReadConfigConf::SignalLength, JBB);
638     }
639     return;
640   default:
641     ndbrequire(false);
642     break;
643   }//switch
644   signal->theData[0] = ZINITIALISE_RECORDS;
645   signal->theData[1] = switchData + 1;
646   signal->theData[2] = retRef;
647   signal->theData[3] = retData;
648   sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
649   return;
650 }//Dbtup::initialiseRecordsLab()
651 
execNDB_STTOR(Signal * signal)652 void Dbtup::execNDB_STTOR(Signal* signal)
653 {
654   jamEntry();
655   cndbcntrRef = signal->theData[0];
656   Uint32 ownNodeId = signal->theData[1];
657   Uint32 startPhase = signal->theData[2];
658   switch (startPhase) {
659   case ZSTARTPHASE1:
660     jam();
661     cownNodeId = ownNodeId;
662     cownref = calcInstanceBlockRef(DBTUP);
663     initializeDefaultValuesFrag();
664     break;
665   case ZSTARTPHASE2:
666     jam();
667     break;
668   case ZSTARTPHASE3:
669     jam();
670     break;
671   case ZSTARTPHASE4:
672     jam();
673     break;
674   case ZSTARTPHASE6:
675     jam();
676     break;
677   default:
678     jam();
679     break;
680   }//switch
681   signal->theData[0] = cownref;
682   BlockReference cntrRef = !isNdbMtLqh() ? NDBCNTR_REF : DBTUP_REF;
683   sendSignal(cntrRef, GSN_NDB_STTORRY, signal, 1, JBB);
684 }//Dbtup::execNDB_STTOR()
685 
initializeDefaultValuesFrag()686 void Dbtup::initializeDefaultValuesFrag()
687 {
688   /* Grab and initialize a fragment record for storing default
689    * values for the table fragments held by this TUP instance
690    */
691   seizeFragrecord(DefaultValuesFragment);
692   DefaultValuesFragment.p->fragStatus = Fragrecord::FS_ONLINE;
693   DefaultValuesFragment.p->m_undo_complete= false;
694   DefaultValuesFragment.p->m_lcp_scan_op = RNIL;
695   DefaultValuesFragment.p->noOfPages = 0;
696   DefaultValuesFragment.p->noOfVarPages = 0;
697   DefaultValuesFragment.p->m_varWordsFree = 0;
698   DefaultValuesFragment.p->m_max_page_cnt = 0;
699   DefaultValuesFragment.p->m_free_page_id_list = FREE_PAGE_RNIL;
700   ndbrequire(DefaultValuesFragment.p->m_page_map.isEmpty());
701   DefaultValuesFragment.p->m_restore_lcp_id = RNIL;
702   for (Uint32 i = 0; i<MAX_FREE_LIST+1; i++)
703     ndbrequire(DefaultValuesFragment.p->free_var_page_array[i].isEmpty());
704 
705   DefaultValuesFragment.p->m_logfile_group_id = RNIL;
706 
707   return;
708 }
709 
initializeFragoperrec()710 void Dbtup::initializeFragoperrec()
711 {
712   FragoperrecPtr fragoperPtr;
713   for (fragoperPtr.i = 0; fragoperPtr.i < cnoOfFragoprec; fragoperPtr.i++) {
714     ptrAss(fragoperPtr, fragoperrec);
715     fragoperPtr.p->nextFragoprec = fragoperPtr.i + 1;
716   }//for
717   fragoperPtr.i = cnoOfFragoprec - 1;
718   ptrAss(fragoperPtr, fragoperrec);
719   fragoperPtr.p->nextFragoprec = RNIL;
720   cfirstfreeFragopr = 0;
721 }//Dbtup::initializeFragoperrec()
722 
initializeFragrecord()723 void Dbtup::initializeFragrecord()
724 {
725   FragrecordPtr regFragPtr;
726   for (regFragPtr.i = 0; regFragPtr.i < cnoOfFragrec; regFragPtr.i++) {
727     refresh_watch_dog();
728     ptrAss(regFragPtr, fragrecord);
729     new (regFragPtr.p) Fragrecord();
730     regFragPtr.p->nextfreefrag = regFragPtr.i + 1;
731     regFragPtr.p->fragStatus = Fragrecord::FS_FREE;
732   }//for
733   regFragPtr.i = cnoOfFragrec - 1;
734   ptrAss(regFragPtr, fragrecord);
735   regFragPtr.p->nextfreefrag = RNIL;
736   cfirstfreefrag = 0;
737 }//Dbtup::initializeFragrecord()
738 
initializeAlterTabOperation()739 void Dbtup::initializeAlterTabOperation()
740 {
741   AlterTabOperationPtr regAlterTabOpPtr;
742   for (regAlterTabOpPtr.i= 0;
743        regAlterTabOpPtr.i<cnoOfAlterTabOps;
744        regAlterTabOpPtr.i++)
745   {
746     refresh_watch_dog();
747     ptrAss(regAlterTabOpPtr, alterTabOperRec);
748     new (regAlterTabOpPtr.p) AlterTabOperation();
749     regAlterTabOpPtr.p->nextAlterTabOp= regAlterTabOpPtr.i+1;
750   }
751   regAlterTabOpPtr.i= cnoOfAlterTabOps-1;
752   ptrAss(regAlterTabOpPtr, alterTabOperRec);
753   regAlterTabOpPtr.p->nextAlterTabOp= RNIL;
754   cfirstfreeAlterTabOp= 0;
755 }
756 
initializeHostBuffer()757 void Dbtup::initializeHostBuffer()
758 {
759   Uint32 hostId;
760   cpackedListIndex = 0;
761   for (hostId = 0; hostId < MAX_NODES; hostId++) {
762     hostBuffer[hostId].inPackedList = false;
763     hostBuffer[hostId].noOfPacketsTA = 0;
764     hostBuffer[hostId].packetLenTA = 0;
765   }//for
766 }//Dbtup::initializeHostBuffer()
767 
768 
initializeOperationrec()769 void Dbtup::initializeOperationrec()
770 {
771   refresh_watch_dog();
772 }//Dbtup::initializeOperationrec()
773 
initializeTablerec()774 void Dbtup::initializeTablerec()
775 {
776   TablerecPtr regTabPtr;
777   for (regTabPtr.i = 0; regTabPtr.i < cnoOfTablerec; regTabPtr.i++) {
778     jam();
779     refresh_watch_dog();
780     ptrAss(regTabPtr, tablerec);
781     initTab(regTabPtr.p);
782   }//for
783 }//Dbtup::initializeTablerec()
784 
785 void
initTab(Tablerec * const regTabPtr)786 Dbtup::initTab(Tablerec* const regTabPtr)
787 {
788   for (Uint32 i = 0; i < NDB_ARRAY_SIZE(regTabPtr->fragid); i++) {
789     regTabPtr->fragid[i] = RNIL;
790     regTabPtr->fragrec[i] = RNIL;
791   }//for
792   regTabPtr->readFunctionArray = NULL;
793   regTabPtr->updateFunctionArray = NULL;
794   regTabPtr->charsetArray = NULL;
795 
796   regTabPtr->tabDescriptor = RNIL;
797   regTabPtr->readKeyArray = RNIL;
798   regTabPtr->dynTabDescriptor[MM] = RNIL;
799   regTabPtr->dynTabDescriptor[DD] = RNIL;
800   regTabPtr->dynFixSizeMask[MM] = NULL;
801   regTabPtr->dynVarSizeMask[MM] = NULL;
802   regTabPtr->dynFixSizeMask[DD] = NULL;
803   regTabPtr->dynVarSizeMask[DD] = NULL;
804 
805   regTabPtr->m_bits = 0;
806 
807   regTabPtr->m_no_of_attributes = 0;
808   regTabPtr->noOfKeyAttr = 0;
809 
810   regTabPtr->m_dropTable.tabUserPtr = RNIL;
811   regTabPtr->m_dropTable.tabUserRef = 0;
812   regTabPtr->tableStatus = NOT_DEFINED;
813   regTabPtr->m_default_value_location.setNull();
814 
815   // Clear trigger data
816   if (!regTabPtr->afterInsertTriggers.isEmpty())
817     while (regTabPtr->afterInsertTriggers.releaseFirst());
818   if (!regTabPtr->afterDeleteTriggers.isEmpty())
819     while (regTabPtr->afterDeleteTriggers.releaseFirst());
820   if (!regTabPtr->afterUpdateTriggers.isEmpty())
821     while (regTabPtr->afterUpdateTriggers.releaseFirst());
822   if (!regTabPtr->subscriptionInsertTriggers.isEmpty())
823     while (regTabPtr->subscriptionInsertTriggers.releaseFirst());
824   if (!regTabPtr->subscriptionDeleteTriggers.isEmpty())
825     while (regTabPtr->subscriptionDeleteTriggers.releaseFirst());
826   if (!regTabPtr->subscriptionUpdateTriggers.isEmpty())
827     while (regTabPtr->subscriptionUpdateTriggers.releaseFirst());
828   if (!regTabPtr->constraintUpdateTriggers.isEmpty())
829     while (regTabPtr->constraintUpdateTriggers.releaseFirst());
830   if (!regTabPtr->tuxCustomTriggers.isEmpty())
831     while (regTabPtr->tuxCustomTriggers.releaseFirst());
832 }//Dbtup::initTab()
833 
initializeTabDescr()834 void Dbtup::initializeTabDescr()
835 {
836   TableDescriptorPtr regTabDesPtr;
837   for (Uint32 i = 0; i < 16; i++) {
838     cfreeTdList[i] = RNIL;
839   }//for
840   for (regTabDesPtr.i = 0; regTabDesPtr.i < cnoOfTabDescrRec; regTabDesPtr.i++) {
841     refresh_watch_dog();
842     ptrAss(regTabDesPtr, tableDescriptor);
843     regTabDesPtr.p->tabDescr = RNIL;
844   }//for
845   freeTabDescr(0, cnoOfTabDescrRec);
846 }//Dbtup::initializeTabDescr()
847 
848 /* ---------------------------------------------------------------- */
849 /* ---------------------------------------------------------------- */
850 /* --------------- CONNECT/DISCONNECT MODULE ---------------------- */
851 /* ---------------------------------------------------------------- */
852 /* ---------------------------------------------------------------- */
execTUPSEIZEREQ(Signal * signal)853 void Dbtup::execTUPSEIZEREQ(Signal* signal)
854 {
855   OperationrecPtr regOperPtr;
856   jamEntry();
857   Uint32 userPtr = signal->theData[0];
858   BlockReference userRef = signal->theData[1];
859   if (!c_operation_pool.seize(regOperPtr))
860   {
861     jam();
862     signal->theData[0] = userPtr;
863     signal->theData[1] = ZGET_OPREC_ERROR;
864     sendSignal(userRef, GSN_TUPSEIZEREF, signal, 2, JBB);
865     return;
866   }//if
867 
868   new (regOperPtr.p) Operationrec();
869   regOperPtr.p->m_any_value = 0;
870   regOperPtr.p->op_type = ZREAD;
871   regOperPtr.p->op_struct.bit_field.in_active_list = false;
872   set_trans_state(regOperPtr.p, TRANS_DISCONNECTED);
873   regOperPtr.p->prevActiveOp = RNIL;
874   regOperPtr.p->nextActiveOp = RNIL;
875   regOperPtr.p->op_struct.bit_field.tupVersion = ZNIL;
876   regOperPtr.p->op_struct.bit_field.delete_insert_flag = false;
877 
878   initOpConnection(regOperPtr.p);
879   regOperPtr.p->userpointer = userPtr;
880   signal->theData[0] = regOperPtr.p->userpointer;
881   signal->theData[1] = regOperPtr.i;
882   sendSignal(userRef, GSN_TUPSEIZECONF, signal, 2, JBB);
883   return;
884 }//Dbtup::execTUPSEIZEREQ()
885 
886 #define printFragment(t){ for(Uint32 i = 0; i < NDB_ARRAY_SIZE(t.p->fragid);i++){ \
887   ndbout_c("table = %d fragid[%d] = %d fragrec[%d] = %d", \
888            t.i, t.p->fragid[i], i, t.p->fragrec[i]); }}
889 
execTUPRELEASEREQ(Signal * signal)890 void Dbtup::execTUPRELEASEREQ(Signal* signal)
891 {
892   OperationrecPtr regOperPtr;
893   jamEntry();
894   regOperPtr.i = signal->theData[0];
895   c_operation_pool.getPtr(regOperPtr);
896   set_trans_state(regOperPtr.p, TRANS_DISCONNECTED);
897   c_operation_pool.release(regOperPtr);
898 
899   signal->theData[0] = regOperPtr.p->userpointer;
900   sendSignal(DBLQH_REF, GSN_TUPRELEASECONF, signal, 1, JBB);
901   return;
902 }//Dbtup::execTUPRELEASEREQ()
903 
releaseFragrec(FragrecordPtr regFragPtr)904 void Dbtup::releaseFragrec(FragrecordPtr regFragPtr)
905 {
906   regFragPtr.p->nextfreefrag = cfirstfreefrag;
907   cfirstfreefrag = regFragPtr.i;
908   RSS_OP_FREE(cnoOfFreeFragrec);
909 }//Dbtup::releaseFragrec()
910 
911 
execNODE_FAILREP(Signal * signal)912 void Dbtup::execNODE_FAILREP(Signal* signal)
913 {
914   jamEntry();
915   const NodeFailRep * rep = (NodeFailRep*)signal->getDataPtr();
916   NdbNodeBitmask failed;
917   failed.assign(NdbNodeBitmask::Size, rep->theNodes);
918 
919   /* Block level cleanup */
920   for(unsigned i = 1; i < MAX_NDB_NODES; i++) {
921     jam();
922     if(failed.get(i)) {
923       jam();
924       Uint32 elementsCleaned = simBlockNodeFailure(signal, i); // No callback
925       ndbassert(elementsCleaned == 0); // No distributed fragmented signals
926       (void) elementsCleaned; // Remove compiler warning
927     }//if
928   }//for
929 }
930 
931 extern Uint32 compute_acc_32kpages(const ndb_mgm_configuration_iterator * p);
932 
933 void
execNODE_STATE_REP(Signal * signal)934 Dbtup::execNODE_STATE_REP(Signal* signal)
935 {
936   jamEntry();
937   const NodeStateRep* rep = CAST_CONSTPTR(NodeStateRep,
938                                           signal->getDataPtr());
939 
940   if (rep->nodeState.startLevel == NodeState::SL_STARTED)
941   {
942     jam();
943 
944     const ndb_mgm_configuration_iterator * p =
945       m_ctx.m_config.getOwnConfigIterator();
946     ndbrequire(p != 0);
947 
948     Uint32 free_pct = 5;
949     ndb_mgm_get_int_parameter(p, CFG_DB_FREE_PCT, &free_pct);
950 
951     Uint32 accpages = compute_acc_32kpages(p);
952 
953     Resource_limit rl;
954     m_ctx.m_mm.get_resource_limit(RG_DATAMEM, rl);
955     m_minFreePages = ((rl.m_min - accpages) * free_pct) / 100;
956   }
957   SimulatedBlock::execNODE_STATE_REP(signal);
958 }
959