MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Dbdict.cpp
1 /*
2  Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #include <ndb_global.h>
19 #include <my_sys.h>
20 
21 #define DBDICT_C
22 #include "Dbdict.hpp"
23 #include "diskpage.hpp"
24 
25 #include <ndb_limits.h>
26 #include <NdbOut.hpp>
27 #include <OutputStream.hpp>
28 #include <Properties.hpp>
29 #include <Configuration.hpp>
30 #include <SectionReader.hpp>
31 #include <SimpleProperties.hpp>
32 #include <AttributeHeader.hpp>
33 #include <KeyDescriptor.hpp>
34 #include <signaldata/DictSchemaInfo.hpp>
35 #include <signaldata/DictTabInfo.hpp>
36 #include <signaldata/DropTabFile.hpp>
37 
38 #include <signaldata/EventReport.hpp>
39 #include <signaldata/FsCloseReq.hpp>
40 #include <signaldata/FsConf.hpp>
41 #include <signaldata/FsOpenReq.hpp>
42 #include <signaldata/FsReadWriteReq.hpp>
43 #include <signaldata/FsRef.hpp>
44 #include <signaldata/GetTabInfo.hpp>
45 #include <signaldata/GetTableId.hpp>
46 #include <signaldata/HotSpareRep.hpp>
47 #include <signaldata/NFCompleteRep.hpp>
48 #include <signaldata/NodeFailRep.hpp>
49 #include <signaldata/ReadNodesConf.hpp>
50 #include <signaldata/RelTabMem.hpp>
51 #include <signaldata/WaitGCP.hpp>
52 #include <signaldata/ListTables.hpp>
53 
54 #include <signaldata/CreateTrig.hpp>
55 #include <signaldata/DropTrig.hpp>
56 #include <signaldata/CreateIndx.hpp>
57 #include <signaldata/DropIndx.hpp>
58 #include <signaldata/BuildIndx.hpp>
59 
60 #include <signaldata/DropFilegroup.hpp>
61 #include <signaldata/CreateFilegroup.hpp>
62 #include <signaldata/CreateFilegroupImpl.hpp>
63 
64 #include <signaldata/CreateEvnt.hpp>
65 #include <signaldata/UtilPrepare.hpp>
66 #include <signaldata/UtilExecute.hpp>
67 #include <signaldata/UtilRelease.hpp>
68 #include <signaldata/SumaImpl.hpp>
69 
70 #include <signaldata/LqhFrag.hpp>
71 #include <signaldata/DictStart.hpp>
72 #include <signaldata/DiAddTab.hpp>
73 #include <signaldata/DihStartTab.hpp>
74 
75 #include <signaldata/DropTable.hpp>
76 #include <signaldata/DropTab.hpp>
77 #include <signaldata/PrepDropTab.hpp>
78 
79 #include <signaldata/CreateTable.hpp>
80 #include <signaldata/AlterTable.hpp>
81 #include <signaldata/AlterTab.hpp>
82 #include <signaldata/CreateFragmentation.hpp>
83 #include <signaldata/CreateTab.hpp>
84 #include <NdbSleep.h>
85 #include <signaldata/ApiBroadcast.hpp>
86 #include <signaldata/DictLock.hpp>
87 #include <signaldata/BackupLockTab.hpp>
88 #include <SLList.hpp>
89 
90 #include <signaldata/DumpStateOrd.hpp>
91 #include <signaldata/CheckNodeGroups.hpp>
92 
93 #include <NdbEnv.h>
94 
95 #include <EventLogger.hpp>
96 extern EventLogger * g_eventLogger;
97 
98 #include <signaldata/SchemaTrans.hpp>
99 #include <DebuggerNames.hpp>
100 
101 #include <signaldata/DbinfoScan.hpp>
102 #include <signaldata/TransIdAI.hpp>
103 
104 #include <signaldata/IndexStatSignal.hpp>
105 
106 #define ZNOT_FOUND 626
107 #define ZALREADYEXIST 630
108 
109 #define ZRESTART_OPS_PER_TRANS 25
110 #define ZRESTART_NO_WRITE_AFTER_READ 1
111 
112 //#define EVENT_PH2_DEBUG
113 //#define EVENT_PH3_DEBUG
114 //#define EVENT_DEBUG
115 
116 static const char EVENT_SYSTEM_TABLE_NAME[] = "sys/def/NDB$EVENTS_0";
117 
118 #define EVENT_TRACE \
119 // ndbout_c("Event debug trace: File: %s Line: %u", __FILE__, __LINE__)
120 
121 #define DIV(x,y) (((x)+(y)-1)/(y))
122 #define WORDS2PAGES(x) DIV(x, (ZSIZE_OF_PAGES_IN_WORDS - ZPAGE_HEADER_SIZE))
123 #include <ndb_version.h>
124 
125 static
126 Uint32
127 alter_obj_inc_schema_version(Uint32 old)
128 {
129  return (old & 0x00FFFFFF) + ((old + 0x1000000) & 0xFF000000);
130 }
131 
132 static
133 Uint32
134 alter_obj_dec_schema_version(Uint32 old)
135 {
136  return (old & 0x00FFFFFF) + ((old - 0x1000000) & 0xFF000000);
137 }
138 
139 static
140 Uint32
141 create_obj_inc_schema_version(Uint32 old)
142 {
143  return (old + 0x00000001) & 0x00FFFFFF;
144 }
145 
146 static
147 void
148 do_swap(Uint32 & v0, Uint32 & v1)
149 {
150  Uint32 save = v0;
151  v0 = v1;
152  v1 = save;
153 }
154 
155 /* **************************************************************** */
156 /* ---------------------------------------------------------------- */
157 /* MODULE: GENERAL MODULE -------------------------------- */
158 /* ---------------------------------------------------------------- */
159 /* */
160 /* This module contains general stuff. Mostly debug signals and */
161 /* general signals that go into a specific module after checking a */
162 /* state variable. Also general subroutines used by many. */
163 /* ---------------------------------------------------------------- */
164 /* **************************************************************** */
165 
166 /* ---------------------------------------------------------------- */
167 // This signal is used to dump states of various variables in the
168 // block by command.
169 /* ---------------------------------------------------------------- */
170 void
171 Dbdict::execDUMP_STATE_ORD(Signal* signal)
172 {
173  jamEntry();
174 
175 #ifdef VM_TRACE
176  if(signal->theData[0] == 1222){
177  const Uint32 tab = signal->theData[1];
178  PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
179  req->senderRef = reference();
180  req->senderData = 1222;
181  req->tableId = tab;
182  sendSignal(DBLQH_REF, GSN_PREP_DROP_TAB_REQ, signal,
183  PrepDropTabReq::SignalLength, JBB);
184  }
185 
186  if(signal->theData[0] == 1223){
187  const Uint32 tab = signal->theData[1];
188  PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
189  req->senderRef = reference();
190  req->senderData = 1222;
191  req->tableId = tab;
192  sendSignal(DBTC_REF, GSN_PREP_DROP_TAB_REQ, signal,
193  PrepDropTabReq::SignalLength, JBB);
194  }
195 
196  if(signal->theData[0] == 1224){
197  const Uint32 tab = signal->theData[1];
198  PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
199  req->senderRef = reference();
200  req->senderData = 1222;
201  req->tableId = tab;
202  sendSignal(DBDIH_REF, GSN_PREP_DROP_TAB_REQ, signal,
203  PrepDropTabReq::SignalLength, JBB);
204  }
205 
206  if(signal->theData[0] == 1225){
207  const Uint32 tab = signal->theData[1];
208  const Uint32 ver = signal->theData[2];
209  TableRecordPtr tabRecPtr;
210  c_tableRecordPool.getPtr(tabRecPtr, tab);
211  DropTableReq * req = (DropTableReq*)signal->getDataPtr();
212  req->senderData = 1225;
213  req->senderRef = numberToRef(1,1);
214  req->tableId = tab;
215  req->tableVersion = tabRecPtr.p->tableVersion + ver;
216  sendSignal(DBDICT_REF, GSN_DROP_TABLE_REQ, signal,
217  DropTableReq::SignalLength, JBB);
218  }
219 #endif
220 #define MEMINFO(x, y) infoEvent(x ": %d %d", y.getSize(), y.getNoOfFree())
221  if(signal->theData[0] == 1226){
222  MEMINFO("c_obj_pool", c_obj_pool);
223  MEMINFO("c_opRecordPool", c_opRecordPool);
224  MEMINFO("c_rope_pool", c_rope_pool);
225  }
226 
227  if (signal->theData[0] == 1227)
228  {
230  bool ok = c_obj_hash.first(iter);
231  for(; ok; ok = c_obj_hash.next(iter))
232  {
233  Rope name(c_rope_pool, iter.curr.p->m_name);
234  char buf[1024];
235  name.copy(buf);
236  ndbout_c("%s m_ref_count: %d", buf, iter.curr.p->m_ref_count);
237  if (iter.curr.p->m_trans_key != 0)
238  ndbout_c("- m_trans_key: %u m_op_ref_count: %u",
239  iter.curr.p->m_trans_key, iter.curr.p->m_op_ref_count);
240  }
241  }
242 
243  if (signal->theData[0] == 8004)
244  {
245  infoEvent("DICT: c_counterMgr size: %u free: %u",
246  c_counterMgr.getSize(),
247  c_counterMgr.getNoOfFree());
248  c_counterMgr.printNODE_FAILREP();
249  }
250 
251  if (signal->theData[0] == DumpStateOrd::SchemaResourceSnapshot)
252  {
253  RSS_AP_SNAPSHOT_SAVE(c_rope_pool);
254  RSS_AP_SNAPSHOT_SAVE(c_attributeRecordPool);
255  RSS_AP_SNAPSHOT_SAVE(c_tableRecordPool);
256  RSS_AP_SNAPSHOT_SAVE(c_triggerRecordPool);
257  RSS_AP_SNAPSHOT_SAVE(c_obj_pool);
258  RSS_AP_SNAPSHOT_SAVE(c_hash_map_pool);
259  RSS_AP_SNAPSHOT_SAVE(g_hash_map);
260  }
261 
262  if (signal->theData[0] == DumpStateOrd::SchemaResourceCheckLeak)
263  {
264  RSS_AP_SNAPSHOT_CHECK(c_rope_pool);
265  RSS_AP_SNAPSHOT_CHECK(c_attributeRecordPool);
266  RSS_AP_SNAPSHOT_CHECK(c_tableRecordPool);
267  RSS_AP_SNAPSHOT_CHECK(c_triggerRecordPool);
268  RSS_AP_SNAPSHOT_CHECK(c_obj_pool);
269  RSS_AP_SNAPSHOT_CHECK(c_hash_map_pool);
270  RSS_AP_SNAPSHOT_CHECK(g_hash_map);
271  }
272 
273  return;
274 
275 
276 }//Dbdict::execDUMP_STATE_ORD()
277 
278 void Dbdict::execDBINFO_SCANREQ(Signal *signal)
279 {
280  DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
281  const Ndbinfo::ScanCursor* cursor =
282  CAST_CONSTPTR(Ndbinfo::ScanCursor, DbinfoScan::getCursorPtr(&req));
284 
285  jamEntry();
286 
287  switch(req.tableId){
288  case Ndbinfo::POOLS_TABLEID:
289  {
290  Ndbinfo::pool_entry pools[] =
291  {
292  { "Attribute Record",
293  c_attributeRecordPool.getUsed(),
294  c_attributeRecordPool.getSize(),
295  c_attributeRecordPool.getEntrySize(),
296  c_attributeRecordPool.getUsedHi(),
297  { CFG_DB_NO_ATTRIBUTES,0,0,0 }},
298  { "Table Record",
299  c_tableRecordPool.getUsed(),
300  c_tableRecordPool.getSize(),
301  c_tableRecordPool.getEntrySize(),
302  c_tableRecordPool.getUsedHi(),
303  { CFG_DB_NO_TABLES,0,0,0 }},
304  { "Trigger Record",
305  c_triggerRecordPool.getUsed(),
306  c_triggerRecordPool.getSize(),
307  c_triggerRecordPool.getEntrySize(),
308  c_triggerRecordPool.getUsedHi(),
309  { CFG_DB_NO_TRIGGERS,0,0,0 }},
310  { "FS Connect Record",
311  c_fsConnectRecordPool.getUsed(),
312  c_fsConnectRecordPool.getSize(),
313  c_fsConnectRecordPool.getEntrySize(),
314  c_fsConnectRecordPool.getUsedHi(),
315  { 0,0,0,0 }},
316  { "DictObject",
317  c_obj_pool.getUsed(),
318  c_obj_pool.getSize(),
319  c_obj_pool.getEntrySize(),
320  c_obj_pool.getUsedHi(),
321  { CFG_DB_NO_TABLES,
322  CFG_DB_NO_ORDERED_INDEXES,
323  CFG_DB_NO_UNIQUE_HASH_INDEXES,
324  CFG_DB_NO_TRIGGERS }},
325  { "Schema Operation",
326  c_schemaOpPool.getUsed(),
327  c_schemaOpPool.getSize(),
328  c_schemaOpPool.getEntrySize(),
329  c_schemaOpPool.getUsedHi(),
330  { 0,0,0,0 }},
331  { "Schema Transaction",
332  c_schemaTransPool.getUsed(),
333  c_schemaTransPool.getSize(),
334  c_schemaTransPool.getEntrySize(),
335  c_schemaTransPool.getUsedHi(),
336  { 0,0,0,0 }},
337  { "Transaction Handle",
338  c_txHandlePool.getUsed(),
339  c_txHandlePool.getSize(),
340  c_txHandlePool.getEntrySize(),
341  c_txHandlePool.getUsedHi(),
342  { 0,0,0,0 }},
343  { "Create Table Record",
344  c_createTableRecPool.getUsed(),
345  c_createTableRecPool.getSize(),
346  c_createTableRecPool.getEntrySize(),
347  c_createTableRecPool.getUsedHi(),
348  { 0,0,0,0 }},
349  { "Drop Table Record",
350  c_dropTableRecPool.getUsed(),
351  c_dropTableRecPool.getSize(),
352  c_dropTableRecPool.getEntrySize(),
353  c_dropTableRecPool.getUsedHi(),
354  { 0,0,0,0 }},
355  { "Alter Table Record",
356  c_alterTableRecPool.getUsed(),
357  c_alterTableRecPool.getSize(),
358  c_alterTableRecPool.getEntrySize(),
359  c_alterTableRecPool.getUsedHi(),
360  { 0,0,0,0 }},
361  { "Create Index Record",
362  c_createIndexRecPool.getUsed(),
363  c_createIndexRecPool.getSize(),
364  c_createIndexRecPool.getEntrySize(),
365  c_createIndexRecPool.getUsedHi(),
366  { 0,0,0,0 }},
367  { "Drop Index Record",
368  c_dropIndexRecPool.getUsed(),
369  c_dropIndexRecPool.getSize(),
370  c_dropIndexRecPool.getEntrySize(),
371  c_dropIndexRecPool.getUsedHi(),
372  { 0,0,0,0 }},
373  { "Alter Index Record",
374  c_alterIndexRecPool.getUsed(),
375  c_alterIndexRecPool.getSize(),
376  c_alterIndexRecPool.getEntrySize(),
377  c_alterIndexRecPool.getUsedHi(),
378  { 0,0,0,0 }},
379  { "Build Index Record",
380  c_buildIndexRecPool.getUsed(),
381  c_buildIndexRecPool.getSize(),
382  c_buildIndexRecPool.getEntrySize(),
383  c_buildIndexRecPool.getUsedHi(),
384  { 0,0,0,0 }},
385  { "Index Stat Record",
386  c_indexStatRecPool.getUsed(),
387  c_indexStatRecPool.getSize(),
388  c_indexStatRecPool.getEntrySize(),
389  c_indexStatRecPool.getUsedHi(),
390  { 0,0,0,0 }},
391  { "Create Hash Map Record",
392  c_createHashMapRecPool.getUsed(),
393  c_createHashMapRecPool.getSize(),
394  c_createHashMapRecPool.getEntrySize(),
395  c_createHashMapRecPool.getUsedHi(),
396  { 0,0,0,0 }},
397  { "Copy Data Record",
398  c_copyDataRecPool.getUsed(),
399  c_copyDataRecPool.getSize(),
400  c_copyDataRecPool.getEntrySize(),
401  c_copyDataRecPool.getUsedHi(),
402  { 0,0,0,0 }},
403  { "Create Trigger Record",
404  c_createTriggerRecPool.getUsed(),
405  c_createTriggerRecPool.getSize(),
406  c_createTriggerRecPool.getEntrySize(),
407  c_createTriggerRecPool.getUsedHi(),
408  { 0,0,0,0 }},
409  { "Drop Trigger Record",
410  c_dropTriggerRecPool.getUsed(),
411  c_dropTriggerRecPool.getSize(),
412  c_dropTriggerRecPool.getEntrySize(),
413  c_dropTriggerRecPool.getUsedHi(),
414  { 0,0,0,0 }},
415  { "Create Filegroup Record",
416  c_createFilegroupRecPool.getUsed(),
417  c_createFilegroupRecPool.getSize(),
418  c_createFilegroupRecPool.getEntrySize(),
419  c_createFilegroupRecPool.getUsedHi(),
420  { 0,0,0,0 }},
421  { "Create File Record",
422  c_createFileRecPool.getUsed(),
423  c_createFileRecPool.getSize(),
424  c_createFileRecPool.getEntrySize(),
425  c_createFileRecPool.getUsedHi(),
426  { 0,0,0,0 }},
427  { "Drop Filegroup Record",
428  c_dropFilegroupRecPool.getUsed(),
429  c_dropFilegroupRecPool.getSize(),
430  c_dropFilegroupRecPool.getEntrySize(),
431  c_dropFilegroupRecPool.getUsedHi(),
432  { 0,0,0,0 }},
433  { "Drop File Record",
434  c_dropFileRecPool.getUsed(),
435  c_dropFileRecPool.getSize(),
436  c_dropFileRecPool.getEntrySize(),
437  c_dropFileRecPool.getUsedHi(),
438  { 0,0,0,0 }},
439  { "Operation Record",
440  c_opRecordPool.getUsed(),
441  c_opRecordPool.getSize(),
442  c_opRecordPool.getEntrySize(),
443  c_opRecordPool.getUsedHi(),
444  { 0,0,0,0 }},
445  { NULL, 0,0,0,0,{0,0,0,0}}
446  };
447 
448  const size_t num_config_params =
449  sizeof(pools[0].config_params) / sizeof(pools[0].config_params[0]);
450  Uint32 pool = cursor->data[0];
451  BlockNumber bn = blockToMain(number());
452  while(pools[pool].poolname)
453  {
454  jam();
455  Ndbinfo::Row row(signal, req);
456  row.write_uint32(getOwnNodeId());
457  row.write_uint32(bn); // block number
458  row.write_uint32(instance()); // block instance
459  row.write_string(pools[pool].poolname);
460  row.write_uint64(pools[pool].used);
461  row.write_uint64(pools[pool].total);
462  row.write_uint64(pools[pool].used_hi);
463  row.write_uint64(pools[pool].entry_size);
464  for (size_t i = 0; i < num_config_params; i++)
465  row.write_uint32(pools[pool].config_params[i]);
466  ndbinfo_send_row(signal, req, row, rl);
467  pool++;
468  if (rl.need_break(req))
469  {
470  jam();
471  ndbinfo_send_scan_break(signal, req, rl, pool);
472  return;
473  }
474  }
475  break;
476  }
477  default:
478  break;
479  }
480 
481  ndbinfo_send_scan_conf(signal, req, rl);
482 }
483 
484 
485 /* ---------------------------------------------------------------- */
486 /* ---------------------------------------------------------------- */
487 // CONTINUEB is used when a real-time break is needed for long
488 // processes.
489 /* ---------------------------------------------------------------- */
490 /* ---------------------------------------------------------------- */
491 void Dbdict::execCONTINUEB(Signal* signal)
492 {
493  jamEntry();
494  switch (signal->theData[0]) {
495  case ZPACK_TABLE_INTO_PAGES :
496  jam();
497  packTableIntoPages(signal);
498  break;
499 
500  case ZSEND_GET_TAB_RESPONSE :
501  jam();
502  sendGetTabResponse(signal);
503  break;
504  case ZWAIT_SUBSTARTSTOP:
505  jam();
506  wait_substartstop(signal, signal->theData[1]);
507  return;
508  case ZDICT_TAKEOVER_REQ :
509  {
510  jam();
511  Uint32* data = &signal->theData[0];
512  memmove(&data[0], &data[1], DictTakeoverReq::SignalLength << 2);
513  execDICT_TAKEOVER_REQ(signal);
514  }
515  break;
516  case ZINDEX_STAT_BG_PROCESS:
517  jam();
518  indexStatBg_process(signal);
519  break;
520 #ifdef ERROR_INSERT
521  case 6103: // search for it
522  jam();
523  {
524  Uint32* data = &signal->theData[0];
525  Uint32 masterRef = data[1];
526  memmove(&data[0], &data[2], SchemaTransImplConf::SignalLength << 2);
527  sendSignal(masterRef, GSN_SCHEMA_TRANS_IMPL_CONF, signal,
528  SchemaTransImplConf::SignalLength, JBB);
529  }
530  break;
531  case 9999:
532  ERROR_INSERTED(signal->theData[1]);
533  CRASH_INSERTION(ERROR_INSERT_VALUE);
534  break;
535 #endif
536  case ZCOMMIT_WAIT_GCI:
537  jam();
538  trans_commit_wait_gci(signal);
539  break;
540  default :
541  ndbrequire(false);
542  break;
543  }//switch
544  return;
545 }//execCONTINUEB()
546 
547 /* ---------------------------------------------------------------- */
548 /* ---------------------------------------------------------------- */
549 // Routine to handle pack table into pages.
550 /* ---------------------------------------------------------------- */
551 /* ---------------------------------------------------------------- */
552 
553 void Dbdict::packTableIntoPages(Signal* signal)
554 {
555  const Uint32 tableId= signal->theData[1];
556  const Uint32 type= signal->theData[2];
557  const Uint32 pageId= signal->theData[3];
558 
559  Uint32 transId = c_retrieveRecord.schemaTransId;
560  GetTabInfoReq req_copy;
561  req_copy.senderRef = c_retrieveRecord.blockRef;
562  req_copy.senderData = c_retrieveRecord.m_senderData;
563  req_copy.schemaTransId = c_retrieveRecord.schemaTransId;
564  req_copy.requestType = c_retrieveRecord.requestType;
565  req_copy.tableId = tableId;
566 
567  {
568  SchemaFile::TableEntry *objEntry = 0;
569  if(tableId != RNIL)
570  {
571  XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
572  objEntry = getTableEntry(xsf, tableId);
573  }
574 
575  // The table seached for was not found
576  if(objEntry == 0)
577  {
578  jam();
579  sendGET_TABINFOREF(signal, &req_copy,
580  GetTabInfoRef::TableNotDefined, __LINE__);
581  initRetrieveRecord(0, 0, 0);
582  return;
583  }
584 
585  if (transId != 0 && transId == objEntry->m_transId)
586  {
587  jam();
588  // see own trans always
589  }
590  else if (refToBlock(req_copy.senderRef) != DBUTIL &&
591  refToBlock(req_copy.senderRef) != SUMA)
592  {
593  jam();
594  Uint32 err;
595  if ((err = check_read_obj(objEntry)))
596  {
597  jam();
598  // cannot see another uncommitted trans
599  sendGET_TABINFOREF(signal, &req_copy,
600  (GetTabInfoRef::ErrorCode)err, __LINE__);
601  initRetrieveRecord(0, 0, 0);
602  return;
603  }
604  }
605  }
606 
607  PageRecordPtr pagePtr;
608  c_pageRecordArray.getPtr(pagePtr, pageId);
609 
610  memset(&pagePtr.p->word[0], 0, 4 * ZPAGE_HEADER_SIZE);
611  LinearWriter w(&pagePtr.p->word[ZPAGE_HEADER_SIZE],
612  ZMAX_PAGES_OF_TABLE_DEFINITION * ZSIZE_OF_PAGES_IN_WORDS);
613  w.first();
614  switch((DictTabInfo::TableType)type) {
615  case DictTabInfo::SystemTable:
616  case DictTabInfo::UserTable:
617  case DictTabInfo::UniqueHashIndex:
618  case DictTabInfo::HashIndex:
619  case DictTabInfo::UniqueOrderedIndex:
620  case DictTabInfo::OrderedIndex:{
621  jam();
622  TableRecordPtr tablePtr;
623  c_tableRecordPool.getPtr(tablePtr, tableId);
624  if (tablePtr.p->m_obj_ptr_i == RNIL)
625  {
626  jam();
627  sendGET_TABINFOREF(signal, &req_copy,
628  GetTabInfoRef::TableNotDefined, __LINE__);
629  initRetrieveRecord(0, 0, 0);
630  return;
631  }
632 
633  packTableIntoPages(w, tablePtr, signal);
634  if (unlikely(signal->theData[0] != 0))
635  {
636  jam();
637  Uint32 err = signal->theData[0];
638  GetTabInfoRef * ref = CAST_PTR(GetTabInfoRef, signal->getDataPtrSend());
639  ref->tableId = c_retrieveRecord.tableId;
640  ref->senderRef = reference();
641  ref->senderData = c_retrieveRecord.m_senderData;
642  ref->errorCode = err;
643  Uint32 dstRef = c_retrieveRecord.blockRef;
644  sendSignal(dstRef, GSN_GET_TABINFOREF, signal,
645  GetTabInfoRef::SignalLength, JBB);
646  initRetrieveRecord(0,0,0);
647  return;
648  }
649  break;
650  }
653  FilegroupPtr fg_ptr;
654  ndbrequire(c_filegroup_hash.find(fg_ptr, tableId));
655  const Uint32 free_hi= signal->theData[4];
656  const Uint32 free_lo= signal->theData[5];
657  packFilegroupIntoPages(w, fg_ptr, free_hi, free_lo);
658  break;
659  }
660  case DictTabInfo::Datafile:{
661  FilePtr fg_ptr;
662  ndbrequire(c_file_hash.find(fg_ptr, tableId));
663  const Uint32 free_extents= signal->theData[4];
664  packFileIntoPages(w, fg_ptr, free_extents);
665  break;
666  }
667  case DictTabInfo::Undofile:{
668  FilePtr fg_ptr;
669  ndbrequire(c_file_hash.find(fg_ptr, tableId));
670  packFileIntoPages(w, fg_ptr, 0);
671  break;
672  }
673  case DictTabInfo::HashMap:{
674  Ptr<HashMapRecord> hm_ptr;
675  ndbrequire(c_hash_map_hash.find(hm_ptr, tableId));
676  packHashMapIntoPages(w, hm_ptr);
677  break;
678  }
679  case DictTabInfo::UndefTableType:
680  case DictTabInfo::HashIndexTrigger:
681  case DictTabInfo::SubscriptionTrigger:
682  case DictTabInfo::ReadOnlyConstraint:
683  case DictTabInfo::IndexTrigger:
684  case DictTabInfo::SchemaTransaction:
685  case DictTabInfo::ReorgTrigger:
686  ndbrequire(false);
687  }
688 
689  Uint32 wordsOfTable = w.getWordsUsed();
690  Uint32 pagesUsed = WORDS2PAGES(wordsOfTable);
691  pagePtr.p->word[ZPOS_CHECKSUM] =
692  computeChecksum(&pagePtr.p->word[0], pagesUsed * ZSIZE_OF_PAGES_IN_WORDS);
693 
694  switch (c_packTable.m_state) {
695  case PackTable::PTS_IDLE:
696  ndbrequire(false);
697  break;
698  case PackTable::PTS_GET_TAB:
699  jam();
700  c_retrieveRecord.retrievedNoOfPages = pagesUsed;
701  c_retrieveRecord.retrievedNoOfWords = wordsOfTable;
702  sendGetTabResponse(signal);
703  return;
704  break;
705  }//switch
706  ndbrequire(false);
707  return;
708 }//packTableIntoPages()
709 
710 void
711 Dbdict::packTableIntoPages(SimpleProperties::Writer & w,
712  TableRecordPtr tablePtr,
713  Signal* signal){
714 
715  union {
716  char tableName[MAX_TAB_NAME_SIZE];
717  char frmData[MAX_FRM_DATA_SIZE];
718  char rangeData[16*MAX_NDB_PARTITIONS];
719  char ngData[2*MAX_NDB_PARTITIONS];
720  char defaultValue[MAX_ATTR_DEFAULT_VALUE_SIZE];
721  char attributeName[MAX_ATTR_NAME_SIZE];
722  };
723  ConstRope r(c_rope_pool, tablePtr.p->tableName);
724  r.copy(tableName);
725  w.add(DictTabInfo::TableName, tableName);
726  w.add(DictTabInfo::TableId, tablePtr.p->tableId);
727  w.add(DictTabInfo::TableVersion, tablePtr.p->tableVersion);
728  w.add(DictTabInfo::NoOfKeyAttr, tablePtr.p->noOfPrimkey);
729  w.add(DictTabInfo::NoOfAttributes, tablePtr.p->noOfAttributes);
730  w.add(DictTabInfo::NoOfNullable, tablePtr.p->noOfNullAttr);
731  w.add(DictTabInfo::NoOfVariable, (Uint32)0);
732  w.add(DictTabInfo::KeyLength, tablePtr.p->tupKeyLength);
733 
734  w.add(DictTabInfo::TableLoggedFlag,
735  !!(tablePtr.p->m_bits & TableRecord::TR_Logged));
736  w.add(DictTabInfo::RowGCIFlag,
737  !!(tablePtr.p->m_bits & TableRecord::TR_RowGCI));
738  w.add(DictTabInfo::RowChecksumFlag,
739  !!(tablePtr.p->m_bits & TableRecord::TR_RowChecksum));
740  w.add(DictTabInfo::TableTemporaryFlag,
741  !!(tablePtr.p->m_bits & TableRecord::TR_Temporary));
742  w.add(DictTabInfo::ForceVarPartFlag,
743  !!(tablePtr.p->m_bits & TableRecord::TR_ForceVarPart));
744 
745  w.add(DictTabInfo::MinLoadFactor, tablePtr.p->minLoadFactor);
746  w.add(DictTabInfo::MaxLoadFactor, tablePtr.p->maxLoadFactor);
747  w.add(DictTabInfo::TableKValue, tablePtr.p->kValue);
748  w.add(DictTabInfo::FragmentTypeVal, tablePtr.p->fragmentType);
749  w.add(DictTabInfo::TableTypeVal, tablePtr.p->tableType);
750  w.add(DictTabInfo::MaxRowsLow, tablePtr.p->maxRowsLow);
751  w.add(DictTabInfo::MaxRowsHigh, tablePtr.p->maxRowsHigh);
752  w.add(DictTabInfo::DefaultNoPartFlag, tablePtr.p->defaultNoPartFlag);
753  w.add(DictTabInfo::LinearHashFlag, tablePtr.p->linearHashFlag);
754  w.add(DictTabInfo::FragmentCount, tablePtr.p->fragmentCount);
755  w.add(DictTabInfo::MinRowsLow, tablePtr.p->minRowsLow);
756  w.add(DictTabInfo::MinRowsHigh, tablePtr.p->minRowsHigh);
757  w.add(DictTabInfo::SingleUserMode, tablePtr.p->singleUserMode);
758  w.add(DictTabInfo::HashMapObjectId, tablePtr.p->hashMapObjectId);
759  w.add(DictTabInfo::TableStorageType, tablePtr.p->storageType);
760  w.add(DictTabInfo::ExtraRowGCIBits, tablePtr.p->m_extra_row_gci_bits);
761  w.add(DictTabInfo::ExtraRowAuthorBits, tablePtr.p->m_extra_row_author_bits);
762 
763 
764  if (tablePtr.p->hashMapObjectId != RNIL)
765  {
766  HashMapPtr hm_ptr;
767  ndbrequire(c_hash_map_hash.find(hm_ptr, tablePtr.p->hashMapObjectId));
768  w.add(DictTabInfo::HashMapVersion, hm_ptr.p->m_object_version);
769  }
770 
771  if(signal)
772  {
773  /* This branch is run at GET_TABINFOREQ */
774 
775  Uint32 err = 0;
776  if (!ERROR_INSERTED(6025))
777  {
778  err = get_fragmentation(signal, tablePtr.p->tableId);
779  }
780  else
781  {
782  err = CreateFragmentationRef::InvalidPrimaryTable;
783  }
784  if (unlikely(err != 0))
785  {
786  jam();
787  signal->theData[0] = err;
788  return;
789  }
790 
791  ndbrequire(err == 0);
792  Uint16 *data = (Uint16*)&signal->theData[25];
793  Uint32 count = 2 + (1 + data[0]) * data[1];
794  w.add(DictTabInfo::ReplicaDataLen, 2*count);
795  for (Uint32 i = 0; i < count; i++)
796  data[i] = htons(data[i]);
797  w.add(DictTabInfo::ReplicaData, data, 2*count);
798  }
799  else
800  {
801  /* This part is run at CREATE_TABLEREQ, ALTER_TABLEREQ */
802  ;
803  }
804 
805  if (tablePtr.p->primaryTableId != RNIL)
806  {
807  jam();
808  TableRecordPtr primTab;
809  c_tableRecordPool.getPtr(primTab, tablePtr.p->primaryTableId);
810  ConstRope r2(c_rope_pool, primTab.p->tableName);
811  r2.copy(tableName);
812  w.add(DictTabInfo::PrimaryTable, tableName);
813  w.add(DictTabInfo::PrimaryTableId, tablePtr.p->primaryTableId);
814  w.add(DictTabInfo::IndexState, tablePtr.p->indexState);
815  w.add(DictTabInfo::CustomTriggerId, tablePtr.p->triggerId);
816  }
817 
818  ConstRope frm(c_rope_pool, tablePtr.p->frmData);
819  frm.copy(frmData);
820  w.add(DictTabInfo::FrmLen, frm.size());
821  w.add(DictTabInfo::FrmData, frmData, frm.size());
822 
823  {
824  jam();
825  w.add(DictTabInfo::TablespaceDataLen, (Uint32)0);
826 
827  ConstRope ng(c_rope_pool, tablePtr.p->ngData);
828  ng.copy(ngData);
829  w.add(DictTabInfo::FragmentDataLen, ng.size());
830  w.add(DictTabInfo::FragmentData, ngData, ng.size());
831 
832  ConstRope range(c_rope_pool, tablePtr.p->rangeData);
833  range.copy(rangeData);
834  w.add(DictTabInfo::RangeListDataLen, range.size());
835  w.add(DictTabInfo::RangeListData, rangeData, range.size());
836  }
837 
838  if(tablePtr.p->m_tablespace_id != RNIL)
839  {
840  w.add(DictTabInfo::TablespaceId, tablePtr.p->m_tablespace_id);
841  FilegroupPtr tsPtr;
842  ndbrequire(c_filegroup_hash.find(tsPtr, tablePtr.p->m_tablespace_id));
843  w.add(DictTabInfo::TablespaceVersion, tsPtr.p->m_version);
844  }
845 
846  AttributeRecordPtr attrPtr;
847  LocalDLFifoList<AttributeRecord> list(c_attributeRecordPool,
848  tablePtr.p->m_attributes);
849  for(list.first(attrPtr); !attrPtr.isNull(); list.next(attrPtr)){
850  jam();
851 
852  ConstRope name(c_rope_pool, attrPtr.p->attributeName);
853  name.copy(attributeName);
854 
855  w.add(DictTabInfo::AttributeName, attributeName);
856  w.add(DictTabInfo::AttributeId, attrPtr.p->attributeId);
857  w.add(DictTabInfo::AttributeKeyFlag, attrPtr.p->tupleKey > 0);
858 
859  const Uint32 desc = attrPtr.p->attributeDescriptor;
860  const Uint32 attrType = AttributeDescriptor::getType(desc);
861  const Uint32 attrSize = AttributeDescriptor::getSize(desc);
862  const Uint32 arraySize = AttributeDescriptor::getArraySize(desc);
863  const Uint32 arrayType = AttributeDescriptor::getArrayType(desc);
864  const Uint32 nullable = AttributeDescriptor::getNullable(desc);
865  const Uint32 DKey = AttributeDescriptor::getDKey(desc);
866  const Uint32 disk= AttributeDescriptor::getDiskBased(desc);
867  const Uint32 dynamic= AttributeDescriptor::getDynamic(desc);
868 
869 
870  // AttributeType deprecated
871  w.add(DictTabInfo::AttributeSize, attrSize);
872  w.add(DictTabInfo::AttributeArraySize, arraySize);
873  w.add(DictTabInfo::AttributeArrayType, arrayType);
874  w.add(DictTabInfo::AttributeNullableFlag, nullable);
875  w.add(DictTabInfo::AttributeDynamic, dynamic);
876  w.add(DictTabInfo::AttributeDKey, DKey);
877  w.add(DictTabInfo::AttributeExtType, attrType);
878  w.add(DictTabInfo::AttributeExtPrecision, attrPtr.p->extPrecision);
879  w.add(DictTabInfo::AttributeExtScale, attrPtr.p->extScale);
880  w.add(DictTabInfo::AttributeExtLength, attrPtr.p->extLength);
881  w.add(DictTabInfo::AttributeAutoIncrement,
882  (Uint32)attrPtr.p->autoIncrement);
883 
884  if(disk)
885  w.add(DictTabInfo::AttributeStorageType, (Uint32)NDB_STORAGETYPE_DISK);
886  else
887  w.add(DictTabInfo::AttributeStorageType, (Uint32)NDB_STORAGETYPE_MEMORY);
888 
889  ConstRope def(c_rope_pool, attrPtr.p->defaultValue);
890  def.copy(defaultValue);
891 
892  if (def.size())
893  {
894  /* Convert default value to network byte order for storage */
895  /* Attribute header */
896  ndbrequire(def.size() >= sizeof(Uint32));
897  Uint32 a;
898  memcpy(&a, defaultValue, sizeof(Uint32));
899  a = htonl(a);
900  memcpy(defaultValue, &a, sizeof(Uint32));
901 
902  Uint32 remainBytes = def.size() - sizeof(Uint32);
903 
904  if (remainBytes)
906  attrSize,
907  arrayType,
908  arraySize,
909  (uchar*) defaultValue + sizeof(Uint32),
910  remainBytes);
911  }
912 
913  w.add(DictTabInfo::AttributeDefaultValueLen, def.size());
914  w.add(DictTabInfo::AttributeDefaultValue, defaultValue, def.size());
915  w.add(DictTabInfo::AttributeEnd, 1);
916  }
917 
918  w.add(DictTabInfo::TableEnd, 1);
919 }
920 
921 void
922 Dbdict::packFilegroupIntoPages(SimpleProperties::Writer & w,
923  FilegroupPtr fg_ptr,
924  const Uint32 undo_free_hi,
925  const Uint32 undo_free_lo){
926 
927  DictFilegroupInfo::Filegroup fg; fg.init();
928  ConstRope r(c_rope_pool, fg_ptr.p->m_name);
929  r.copy(fg.FilegroupName);
930 
931  fg.FilegroupId = fg_ptr.p->key;
932  fg.FilegroupType = fg_ptr.p->m_type;
933  fg.FilegroupVersion = fg_ptr.p->m_version;
934 
935  switch(fg.FilegroupType){
937  //fg.TS_DataGrow = group.m_grow_spec;
938  fg.TS_ExtentSize = fg_ptr.p->m_tablespace.m_extent_size;
939  fg.TS_LogfileGroupId = fg_ptr.p->m_tablespace.m_default_logfile_group_id;
940  FilegroupPtr lfg_ptr;
941  ndbrequire(c_filegroup_hash.find(lfg_ptr, fg.TS_LogfileGroupId));
942  fg.TS_LogfileGroupVersion = lfg_ptr.p->m_version;
943  break;
945  fg.LF_UndoBufferSize = fg_ptr.p->m_logfilegroup.m_undo_buffer_size;
946  fg.LF_UndoFreeWordsHi= undo_free_hi;
947  fg.LF_UndoFreeWordsLo= undo_free_lo;
948  //fg.LF_UndoGrow = ;
949  break;
950  default:
951  ndbrequire(false);
952  }
953 
955  s = SimpleProperties::pack(w,
956  &fg,
957  DictFilegroupInfo::Mapping,
958  DictFilegroupInfo::MappingSize, true);
959 
960  ndbrequire(s == SimpleProperties::Eof);
961 }
962 
963 void
964 Dbdict::packFileIntoPages(SimpleProperties::Writer & w,
965  FilePtr f_ptr, const Uint32 free_extents){
966 
967  DictFilegroupInfo::File f; f.init();
968  ConstRope r(c_rope_pool, f_ptr.p->m_path);
969  r.copy(f.FileName);
970 
971  f.FileType = f_ptr.p->m_type;
972  f.FilegroupId = f_ptr.p->m_filegroup_id;; //group.m_id;
973  f.FileSizeHi = (Uint32)(f_ptr.p->m_file_size >> 32);
974  f.FileSizeLo = (Uint32)(f_ptr.p->m_file_size & 0xFFFFFFFF);
975  f.FileFreeExtents= free_extents;
976  f.FileId = f_ptr.p->key;
977  f.FileVersion = f_ptr.p->m_version;
978 
979  FilegroupPtr lfg_ptr;
980  ndbrequire(c_filegroup_hash.find(lfg_ptr, f.FilegroupId));
981  f.FilegroupVersion = lfg_ptr.p->m_version;
982 
984  s = SimpleProperties::pack(w,
985  &f,
986  DictFilegroupInfo::FileMapping,
987  DictFilegroupInfo::FileMappingSize, true);
988 
989  ndbrequire(s == SimpleProperties::Eof);
990 }
991 
992 void
993 Dbdict::execCREATE_FRAGMENTATION_REQ(Signal* signal)
994 {
995  CreateFragmentationReq* req = (CreateFragmentationReq*)signal->getDataPtr();
996 
997  if (req->primaryTableId == RNIL) {
998  jam();
999  EXECUTE_DIRECT(DBDIH, GSN_CREATE_FRAGMENTATION_REQ, signal,
1000  CreateFragmentationReq::SignalLength);
1001  return;
1002  }
1003 
1004  TableRecordPtr tablePtr;
1005  c_tableRecordPool.getPtr(tablePtr, req->primaryTableId);
1006  XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
1007  SchemaFile::TableEntry * te = getTableEntry(xsf, req->primaryTableId);
1008  if (te->m_tableState != SchemaFile::SF_CREATE)
1009  {
1010  jam();
1011  if (req->requestInfo == 0)
1012  {
1013  jam();
1014  req->requestInfo |= CreateFragmentationReq::RI_GET_FRAGMENTATION;
1015  }
1016  EXECUTE_DIRECT(DBDIH, GSN_CREATE_FRAGMENTATION_REQ, signal,
1017  CreateFragmentationReq::SignalLength);
1018  return;
1019  }
1020 
1021  DictObjectPtr obj_ptr;
1022  c_obj_pool.getPtr(obj_ptr, tablePtr.p->m_obj_ptr_i);
1023 
1024  SchemaOpPtr op_ptr;
1025  findDictObjectOp(op_ptr, obj_ptr);
1026  ndbrequire(!op_ptr.isNull());
1027  OpRecPtr oprec_ptr = op_ptr.p->m_oprec_ptr;
1028  ndbrequire(memcmp(oprec_ptr.p->m_opType, "CTa", 4) == 0);
1029 
1030  Uint32 *theData = &signal->theData[0];
1031  const OpSection& fragSection =
1032  getOpSection(op_ptr, CreateTabReq::FRAGMENTATION);
1033  copyOut(fragSection, &theData[25], ZNIL);
1034  theData[0] = 0;
1035 }
1036 
1037 /* ---------------------------------------------------------------- */
1038 /* ---------------------------------------------------------------- */
1039 // The routines to handle responses from file system.
1040 /* ---------------------------------------------------------------- */
1041 /* ---------------------------------------------------------------- */
1042 
1043 /* ---------------------------------------------------------------- */
1044 // A file was successfully closed.
1045 /* ---------------------------------------------------------------- */
1046 void Dbdict::execFSCLOSECONF(Signal* signal)
1047 {
1048  FsConnectRecordPtr fsPtr;
1049  FsConf * const fsConf = (FsConf *)&signal->theData[0];
1050  jamEntry();
1051  c_fsConnectRecordPool.getPtr(fsPtr, fsConf->userPointer);
1052  switch (fsPtr.p->fsState) {
1053  case FsConnectRecord::CLOSE_WRITE_SCHEMA:
1054  jam();
1055  closeWriteSchemaConf(signal, fsPtr);
1056  break;
1057  case FsConnectRecord::CLOSE_READ_SCHEMA:
1058  jam();
1059  closeReadSchemaConf(signal, fsPtr);
1060  break;
1061  case FsConnectRecord::CLOSE_READ_TAB_FILE:
1062  jam();
1063  closeReadTableConf(signal, fsPtr);
1064  break;
1065  case FsConnectRecord::CLOSE_WRITE_TAB_FILE:
1066  jam();
1067  closeWriteTableConf(signal, fsPtr);
1068  break;
1069  case FsConnectRecord::OPEN_READ_SCHEMA2:
1070  openSchemaFile(signal, 1, fsPtr.i, false, false);
1071  break;
1072  case FsConnectRecord::OPEN_READ_TAB_FILE2:
1073  openTableFile(signal, 1, fsPtr.i, c_readTableRecord.tableId, false);
1074  break;
1075  default:
1076  jamLine((fsPtr.p->fsState & 0xFFF));
1077  ndbrequire(false);
1078  break;
1079  }//switch
1080 }//execFSCLOSECONF()
1081 
1082 
1083 /* ---------------------------------------------------------------- */
1084 // A file was successfully opened.
1085 /* ---------------------------------------------------------------- */
1086 void Dbdict::execFSOPENCONF(Signal* signal)
1087 {
1088  FsConnectRecordPtr fsPtr;
1089  jamEntry();
1090  FsConf * const fsConf = (FsConf *)&signal->theData[0];
1091  c_fsConnectRecordPool.getPtr(fsPtr, fsConf->userPointer);
1092 
1093  Uint32 filePointer = fsConf->filePointer;
1094  fsPtr.p->filePtr = filePointer;
1095  switch (fsPtr.p->fsState) {
1096  case FsConnectRecord::OPEN_WRITE_SCHEMA:
1097  jam();
1098  fsPtr.p->fsState = FsConnectRecord::WRITE_SCHEMA;
1099  writeSchemaFile(signal, filePointer, fsPtr.i);
1100  break;
1101  case FsConnectRecord::OPEN_READ_SCHEMA1:
1102  jam();
1103  fsPtr.p->fsState = FsConnectRecord::READ_SCHEMA1;
1104  readSchemaFile(signal, filePointer, fsPtr.i);
1105  break;
1106  case FsConnectRecord::OPEN_READ_SCHEMA2:
1107  jam();
1108  fsPtr.p->fsState = FsConnectRecord::READ_SCHEMA2;
1109  readSchemaFile(signal, filePointer, fsPtr.i);
1110  break;
1111  case FsConnectRecord::OPEN_READ_TAB_FILE1:
1112  jam();
1113  fsPtr.p->fsState = FsConnectRecord::READ_TAB_FILE1;
1114  readTableFile(signal, filePointer, fsPtr.i);
1115  break;
1116  case FsConnectRecord::OPEN_READ_TAB_FILE2:
1117  jam();
1118  fsPtr.p->fsState = FsConnectRecord::READ_TAB_FILE2;
1119  readTableFile(signal, filePointer, fsPtr.i);
1120  break;
1121  case FsConnectRecord::OPEN_WRITE_TAB_FILE:
1122  jam();
1123  fsPtr.p->fsState = FsConnectRecord::WRITE_TAB_FILE;
1124  writeTableFile(signal, filePointer, fsPtr.i);
1125  break;
1126  default:
1127  jamLine((fsPtr.p->fsState & 0xFFF));
1128  ndbrequire(false);
1129  break;
1130  }//switch
1131 }//execFSOPENCONF()
1132 
1133 /* ---------------------------------------------------------------- */
1134 // An open file was refused.
1135 /* ---------------------------------------------------------------- */
1136 void Dbdict::execFSOPENREF(Signal* signal)
1137 {
1138  jamEntry();
1139  FsRef * const fsRef = (FsRef *)&signal->theData[0];
1140  FsConnectRecordPtr fsPtr;
1141  c_fsConnectRecordPool.getPtr(fsPtr, fsRef->userPointer);
1142  switch (fsPtr.p->fsState) {
1143  case FsConnectRecord::OPEN_READ_SCHEMA1:
1144  jam();
1145  openReadSchemaRef(signal, fsPtr);
1146  return;
1147  case FsConnectRecord::OPEN_READ_TAB_FILE1:
1148  jam();
1149  openReadTableRef(signal, fsPtr);
1150  return;
1151  default:
1152  break;
1153  }//switch
1154  {
1155  char msg[100];
1156  sprintf(msg, "File system open failed during FsConnectRecord state %d", (Uint32)fsPtr.p->fsState);
1157  fsRefError(signal,__LINE__,msg);
1158  }
1159 }//execFSOPENREF()
1160 
1161 /* ---------------------------------------------------------------- */
1162 // A file was successfully read.
1163 /* ---------------------------------------------------------------- */
1164 void Dbdict::execFSREADCONF(Signal* signal)
1165 {
1166  jamEntry();
1167  FsConf * const fsConf = (FsConf *)&signal->theData[0];
1168  FsConnectRecordPtr fsPtr;
1169  c_fsConnectRecordPool.getPtr(fsPtr, fsConf->userPointer);
1170  switch (fsPtr.p->fsState) {
1171  case FsConnectRecord::READ_SCHEMA1:
1172  case FsConnectRecord::READ_SCHEMA2:
1173  readSchemaConf(signal ,fsPtr);
1174  break;
1175  case FsConnectRecord::READ_TAB_FILE1:
1176  if(ERROR_INSERTED(6024))
1177  {
1178  jam();
1179  CLEAR_ERROR_INSERT_VALUE;
1180  FsRef * const fsRef = (FsRef *)&signal->theData[0];
1181  fsRef->userPointer = fsConf->userPointer;
1182  fsRef->setErrorCode(fsRef->errorCode, NDBD_EXIT_AFS_UNKNOWN);
1183  fsRef->osErrorCode = ~0; // Indicate local error
1184  execFSREADREF(signal);
1185  return;
1186  }//Testing how DICT behave if read of file 1 fails (Bug#28770)
1187  case FsConnectRecord::READ_TAB_FILE2:
1188  jam();
1189  readTableConf(signal ,fsPtr);
1190  break;
1191  default:
1192  jamLine((fsPtr.p->fsState & 0xFFF));
1193  ndbrequire(false);
1194  break;
1195  }//switch
1196 }//execFSREADCONF()
1197 
1198 /* ---------------------------------------------------------------- */
1199 // A read file was refused.
1200 /* ---------------------------------------------------------------- */
1201 void Dbdict::execFSREADREF(Signal* signal)
1202 {
1203  jamEntry();
1204  FsRef * const fsRef = (FsRef *)&signal->theData[0];
1205  FsConnectRecordPtr fsPtr;
1206  c_fsConnectRecordPool.getPtr(fsPtr, fsRef->userPointer);
1207  switch (fsPtr.p->fsState) {
1208  case FsConnectRecord::READ_SCHEMA1:
1209  jam();
1210  readSchemaRef(signal, fsPtr);
1211  return;
1212  case FsConnectRecord::READ_TAB_FILE1:
1213  jam();
1214  readTableRef(signal, fsPtr);
1215  return;
1216  default:
1217  break;
1218  }//switch
1219  {
1220  char msg[100];
1221  sprintf(msg, "File system read failed during FsConnectRecord state %d", (Uint32)fsPtr.p->fsState);
1222  fsRefError(signal,__LINE__,msg);
1223  }
1224 }//execFSREADREF()
1225 
1226 /* ---------------------------------------------------------------- */
1227 // A file was successfully written.
1228 /* ---------------------------------------------------------------- */
1229 void Dbdict::execFSWRITECONF(Signal* signal)
1230 {
1231  FsConf * const fsConf = (FsConf *)&signal->theData[0];
1232  FsConnectRecordPtr fsPtr;
1233  jamEntry();
1234  c_fsConnectRecordPool.getPtr(fsPtr, fsConf->userPointer);
1235  switch (fsPtr.p->fsState) {
1236  case FsConnectRecord::WRITE_TAB_FILE:
1237  writeTableConf(signal, fsPtr);
1238  break;
1239  case FsConnectRecord::WRITE_SCHEMA:
1240  jam();
1241  writeSchemaConf(signal, fsPtr);
1242  break;
1243  default:
1244  jamLine((fsPtr.p->fsState & 0xFFF));
1245  ndbrequire(false);
1246  break;
1247  }//switch
1248 }//execFSWRITECONF()
1249 
1250 
1251 /* ---------------------------------------------------------------- */
1252 // Routines to handle Read/Write of Table Files
1253 /* ---------------------------------------------------------------- */
1254 void
1255 Dbdict::writeTableFile(Signal* signal, Uint32 tableId,
1256  SegmentedSectionPtr tabInfoPtr, Callback* callback){
1257 
1258  ndbrequire(c_writeTableRecord.tableWriteState == WriteTableRecord::IDLE);
1259 
1260  Uint32 pages = WORDS2PAGES(tabInfoPtr.sz);
1261  c_writeTableRecord.no_of_words = tabInfoPtr.sz;
1262  c_writeTableRecord.tableWriteState = WriteTableRecord::TWR_CALLBACK;
1263  c_writeTableRecord.m_callback = * callback;
1264 
1265  c_writeTableRecord.pageId = 0;
1266  ndbrequire(pages == 1);
1267 
1268  PageRecordPtr pageRecPtr;
1269  c_pageRecordArray.getPtr(pageRecPtr, c_writeTableRecord.pageId);
1270  copy(&pageRecPtr.p->word[ZPAGE_HEADER_SIZE], tabInfoPtr);
1271 
1272  memset(&pageRecPtr.p->word[0], 0, 4 * ZPAGE_HEADER_SIZE);
1273  pageRecPtr.p->word[ZPOS_CHECKSUM] =
1274  computeChecksum(&pageRecPtr.p->word[0],
1275  pages * ZSIZE_OF_PAGES_IN_WORDS);
1276 
1277  startWriteTableFile(signal, tableId);
1278 }
1279 
1280 // SchemaTrans variant
1281 void
1282 Dbdict::writeTableFile(Signal* signal, Uint32 tableId,
1283  OpSection tabInfoSec, Callback* callback)
1284 {
1285  ndbrequire(c_writeTableRecord.tableWriteState == WriteTableRecord::IDLE);
1286 
1287  {
1288  const Uint32 size = tabInfoSec.getSize();
1289  const Uint32 pages = WORDS2PAGES(size);
1290 
1291  c_writeTableRecord.no_of_words = size;
1292  c_writeTableRecord.tableWriteState = WriteTableRecord::TWR_CALLBACK;
1293  c_writeTableRecord.m_callback = * callback;
1294 
1295  c_writeTableRecord.pageId = 0;
1296 
1297  PageRecordPtr pageRecPtr;
1298  c_pageRecordArray.getPtr(pageRecPtr, c_writeTableRecord.pageId);
1299 
1300  Uint32* dst = &pageRecPtr.p->word[ZPAGE_HEADER_SIZE];
1301  Uint32 dstSize = (ZMAX_PAGES_OF_TABLE_DEFINITION * ZSIZE_OF_PAGES_IN_WORDS)
1302  - ZPAGE_HEADER_SIZE;
1303  bool ok = copyOut(tabInfoSec, dst, dstSize);
1304  ndbrequire(ok);
1305 
1306  memset(&pageRecPtr.p->word[0], 0, 4 * ZPAGE_HEADER_SIZE);
1307  pageRecPtr.p->word[ZPOS_CHECKSUM] =
1308  computeChecksum(&pageRecPtr.p->word[0],
1309  pages * ZSIZE_OF_PAGES_IN_WORDS);
1310  }
1311 
1312  startWriteTableFile(signal, tableId);
1313 }
1314 
1315 void Dbdict::startWriteTableFile(Signal* signal, Uint32 tableId)
1316 {
1317  FsConnectRecordPtr fsPtr;
1318  c_writeTableRecord.tableId = tableId;
1319  c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
1320  fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_TAB_FILE;
1321  openTableFile(signal, 0, fsPtr.i, tableId, true);
1322  c_writeTableRecord.noOfTableFilesHandled = 0;
1323 }//Dbdict::startWriteTableFile()
1324 
1325 void Dbdict::openTableFile(Signal* signal,
1326  Uint32 fileNo,
1327  Uint32 fsConPtr,
1328  Uint32 tableId,
1329  bool writeFlag)
1330 {
1331  FsOpenReq * const fsOpenReq = (FsOpenReq *)&signal->theData[0];
1332 
1333  fsOpenReq->userReference = reference();
1334  fsOpenReq->userPointer = fsConPtr;
1335  if (writeFlag) {
1336  jam();
1337  fsOpenReq->fileFlags =
1338  FsOpenReq::OM_WRITEONLY |
1339  FsOpenReq::OM_TRUNCATE |
1340  FsOpenReq::OM_CREATE |
1341  FsOpenReq::OM_SYNC;
1342  } else {
1343  jam();
1344  fsOpenReq->fileFlags = FsOpenReq::OM_READONLY;
1345  }//if
1346  fsOpenReq->fileNumber[3] = 0; // Initialise before byte changes
1347  FsOpenReq::setVersion(fsOpenReq->fileNumber, 1);
1348  FsOpenReq::setSuffix(fsOpenReq->fileNumber, FsOpenReq::S_TABLELIST);
1349  FsOpenReq::v1_setDisk(fsOpenReq->fileNumber, (fileNo + 1));
1350  FsOpenReq::v1_setTable(fsOpenReq->fileNumber, tableId);
1351  FsOpenReq::v1_setFragment(fsOpenReq->fileNumber, (Uint32)-1);
1352  FsOpenReq::v1_setS(fsOpenReq->fileNumber, 0);
1353  FsOpenReq::v1_setP(fsOpenReq->fileNumber, 255);
1354 /* ---------------------------------------------------------------- */
1355 // File name : D1/DBDICT/T0/S1.TableList
1356 // D1 means Disk 1 (set by fileNo + 1)
1357 // T0 means table id = 0
1358 // S1 means tableVersion 1
1359 // TableList indicates that this is a file for a table description.
1360 /* ---------------------------------------------------------------- */
1361  sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
1362 }//openTableFile()
1363 
1364 void Dbdict::writeTableFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
1365 {
1366  FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
1367 
1368  fsRWReq->filePointer = filePtr;
1369  fsRWReq->userReference = reference();
1370  fsRWReq->userPointer = fsConPtr;
1371  fsRWReq->operationFlag = 0; // Initialise before bit changes
1372  FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 1);
1373  FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
1374  FsReadWriteReq::fsFormatArrayOfPages);
1375  fsRWReq->varIndex = ZBAT_TABLE_FILE;
1376  fsRWReq->numberOfPages = WORDS2PAGES(c_writeTableRecord.no_of_words);
1377  fsRWReq->data.arrayOfPages.varIndex = c_writeTableRecord.pageId;
1378  fsRWReq->data.arrayOfPages.fileOffset = 0; // Write to file page 0
1379  sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
1380 }//writeTableFile()
1381 
1382 void Dbdict::writeTableConf(Signal* signal,
1383  FsConnectRecordPtr fsPtr)
1384 {
1385  fsPtr.p->fsState = FsConnectRecord::CLOSE_WRITE_TAB_FILE;
1386  closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
1387  return;
1388 }//Dbdict::writeTableConf()
1389 
1390 void Dbdict::closeWriteTableConf(Signal* signal,
1391  FsConnectRecordPtr fsPtr)
1392 {
1393  c_writeTableRecord.noOfTableFilesHandled++;
1394  if (c_writeTableRecord.noOfTableFilesHandled < 2) {
1395  jam();
1396  fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_TAB_FILE;
1397  openTableFile(signal, 1, fsPtr.i, c_writeTableRecord.tableId, true);
1398  return;
1399  }
1400  ndbrequire(c_writeTableRecord.noOfTableFilesHandled == 2);
1401  c_fsConnectRecordPool.release(fsPtr);
1402  WriteTableRecord::TableWriteState state = c_writeTableRecord.tableWriteState;
1403  c_writeTableRecord.tableWriteState = WriteTableRecord::IDLE;
1404  switch (state) {
1405  case WriteTableRecord::IDLE:
1406  case WriteTableRecord::WRITE_ADD_TABLE_MASTER :
1407  case WriteTableRecord::WRITE_ADD_TABLE_SLAVE :
1408  case WriteTableRecord::WRITE_RESTART_FROM_MASTER :
1409  case WriteTableRecord::WRITE_RESTART_FROM_OWN :
1410  ndbrequire(false);
1411  break;
1412  case WriteTableRecord::TWR_CALLBACK:
1413  jam();
1414  execute(signal, c_writeTableRecord.m_callback, 0);
1415  return;
1416  }
1417  ndbrequire(false);
1418 }//Dbdict::closeWriteTableConf()
1419 
1420 void Dbdict::startReadTableFile(Signal* signal, Uint32 tableId)
1421 {
1422  //globalSignalLoggers.log(number(), "startReadTableFile");
1423  ndbrequire(!c_readTableRecord.inUse);
1424 
1425  FsConnectRecordPtr fsPtr;
1426  c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
1427  c_readTableRecord.inUse = true;
1428  c_readTableRecord.tableId = tableId;
1429  fsPtr.p->fsState = FsConnectRecord::OPEN_READ_TAB_FILE1;
1430  openTableFile(signal, 0, fsPtr.i, tableId, false);
1431 }//Dbdict::startReadTableFile()
1432 
1433 void Dbdict::openReadTableRef(Signal* signal,
1434  FsConnectRecordPtr fsPtr)
1435 {
1436  fsPtr.p->fsState = FsConnectRecord::OPEN_READ_TAB_FILE2;
1437  openTableFile(signal, 1, fsPtr.i, c_readTableRecord.tableId, false);
1438  return;
1439 }//Dbdict::openReadTableConf()
1440 
1441 void Dbdict::readTableFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
1442 {
1443  FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
1444 
1445  fsRWReq->filePointer = filePtr;
1446  fsRWReq->userReference = reference();
1447  fsRWReq->userPointer = fsConPtr;
1448  fsRWReq->operationFlag = 0; // Initialise before bit changes
1449  FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 0);
1450  FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
1451  FsReadWriteReq::fsFormatArrayOfPages);
1452  fsRWReq->varIndex = ZBAT_TABLE_FILE;
1453  fsRWReq->numberOfPages = WORDS2PAGES(c_readTableRecord.no_of_words);
1454  fsRWReq->data.arrayOfPages.varIndex = c_readTableRecord.pageId;
1455  fsRWReq->data.arrayOfPages.fileOffset = 0; // Write to file page 0
1456  sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 8, JBA);
1457 }//readTableFile()
1458 
1459 void Dbdict::readTableConf(Signal* signal,
1460  FsConnectRecordPtr fsPtr)
1461 {
1462  /* ---------------------------------------------------------------- */
1463  // Verify the data read from disk
1464  /* ---------------------------------------------------------------- */
1465  bool crashInd;
1466  if (fsPtr.p->fsState == FsConnectRecord::READ_TAB_FILE1) {
1467  jam();
1468  crashInd = false;
1469  } else {
1470  jam();
1471  crashInd = true;
1472  }//if
1473 
1474  PageRecordPtr tmpPagePtr;
1475  c_pageRecordArray.getPtr(tmpPagePtr, c_readTableRecord.pageId);
1476  Uint32 sz =
1477  WORDS2PAGES(c_readTableRecord.no_of_words)*ZSIZE_OF_PAGES_IN_WORDS;
1478  Uint32 chk = computeChecksum((const Uint32*)tmpPagePtr.p, sz);
1479 
1480  ndbrequire((chk == 0) || !crashInd);
1481  if(chk != 0){
1482  jam();
1483  ndbrequire(fsPtr.p->fsState == FsConnectRecord::READ_TAB_FILE1);
1484  readTableRef(signal, fsPtr);
1485  return;
1486  }//if
1487 
1488  fsPtr.p->fsState = FsConnectRecord::CLOSE_READ_TAB_FILE;
1489  closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
1490  return;
1491 }//Dbdict::readTableConf()
1492 
1493 void Dbdict::readTableRef(Signal* signal,
1494  FsConnectRecordPtr fsPtr)
1495 {
1499  fsPtr.p->fsState = FsConnectRecord::OPEN_READ_TAB_FILE2;
1500  closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
1501  return;
1502 }//Dbdict::readTableRef()
1503 
1504 void Dbdict::closeReadTableConf(Signal* signal,
1505  FsConnectRecordPtr fsPtr)
1506 {
1507  c_fsConnectRecordPool.release(fsPtr);
1508  c_readTableRecord.inUse = false;
1509 
1510  execute(signal, c_readTableRecord.m_callback, 0);
1511  return;
1512 }//Dbdict::closeReadTableConf()
1513 
1514 /* ---------------------------------------------------------------- */
1515 // Routines to handle Read/Write of Schema Files
1516 /* ---------------------------------------------------------------- */
1517 NdbOut& operator<<(NdbOut& out, const SchemaFile::TableEntry entry);
1518 
1519 void
1520 Dbdict::updateSchemaState(Signal* signal, Uint32 tableId,
1521  SchemaFile::TableEntry* te, Callback* callback,
1522  bool savetodisk, bool dicttrans)
1523 {
1524  jam();
1525  XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
1526  SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, tableId);
1527 
1528  if (!dicttrans) {
1529  /*
1530  * Old code may not zero transId, leaving the entry not visible
1531  * to tabinfo request (old code may also skip updateSchemaState).
1532  */
1533  te->m_transId = 0;
1534  }
1535 
1536  D("updateSchemaState" << V(tableId));
1537  D("old:" << *tableEntry);
1538  D("new:" << *te);
1539 
1540 #ifndef TODO
1541  * tableEntry = * te;
1542  computeChecksum(xsf, tableId / NDB_SF_PAGE_ENTRIES);
1543 #else
1544  SchemaFile::TableState newState =
1545  (SchemaFile::TableState)te->m_tableState;
1546  SchemaFile::TableState oldState =
1547  (SchemaFile::TableState)tableEntry->m_tableState;
1548 
1549  Uint32 newVersion = te->m_tableVersion;
1550  Uint32 oldVersion = tableEntry->m_tableVersion;
1551 
1552  bool ok = false;
1553  switch (newState){
1554  case SchemaFile::CREATE_PARSED:
1555  jam();
1556  ok = true;
1557  ndbrequire(create_obj_inc_schema_version(oldVersion) == newVersion);
1558  ndbrequire(oldState == SchemaFile::INIT ||
1559  oldState == SchemaFile::DROP_TABLE_COMMITTED);
1560  break;
1561  case SchemaFile::DROP_PARSED:
1562  ok = true;
1563  break;
1564  case SchemaFile::ALTER_PARSED:
1565  // wl3600_todo
1566  ok = true;
1567  break;
1568  case SchemaFile::ADD_STARTED:
1569  jam();
1570  ok = true;
1571  if (dicttrans) {
1572  ndbrequire(oldVersion == newVersion);
1573  ndbrequire(oldState == SchemaFile::CREATE_PARSED);
1574  break;
1575  }
1576  ndbrequire(create_obj_inc_schema_version(oldVersion) == newVersion);
1577  ndbrequire(oldState == SchemaFile::INIT ||
1578  oldState == SchemaFile::DROP_TABLE_COMMITTED);
1579  break;
1580  case SchemaFile::TABLE_ADD_COMMITTED:
1581  jam();
1582  ok = true;
1583  ndbrequire(newVersion == oldVersion);
1584  ndbrequire(oldState == SchemaFile::ADD_STARTED ||
1585  oldState == SchemaFile::DROP_TABLE_STARTED);
1586  break;
1587  case SchemaFile::ALTER_TABLE_COMMITTED:
1588  jam();
1589  ok = true;
1590  ndbrequire(alter_obj_inc_schema_version(oldVersion) == newVersion);
1591  ndbrequire(oldState == SchemaFile::TABLE_ADD_COMMITTED ||
1592  oldState == SchemaFile::ALTER_TABLE_COMMITTED);
1593  break;
1594  case SchemaFile::DROP_TABLE_STARTED:
1595  jam();
1596  case SchemaFile::DROP_TABLE_COMMITTED:
1597  jam();
1598  ok = true;
1599  break;
1600  case SchemaFile::TEMPORARY_TABLE_COMMITTED:
1601  jam();
1602  ndbrequire(oldState == SchemaFile::ADD_STARTED ||
1603  oldState == SchemaFile::TEMPORARY_TABLE_COMMITTED);
1604  ok = true;
1605  break;
1606  case SchemaFile::INIT:
1607  jam();
1608  ok = true;
1609  if (dicttrans) {
1610  ndbrequire((oldState == SchemaFile::CREATE_PARSED));
1611  break;
1612  }
1613  ndbrequire((oldState == SchemaFile::ADD_STARTED));
1614  }//if
1615  ndbrequire(ok);
1616 
1617  * tableEntry = * te;
1618  computeChecksum(xsf, tableId / NDB_SF_PAGE_ENTRIES);
1619 
1620  if (savetodisk)
1621  {
1622  ndbrequire(c_writeSchemaRecord.inUse == false);
1623  c_writeSchemaRecord.inUse = true;
1624 
1625  c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
1626  c_writeSchemaRecord.newFile = false;
1627  c_writeSchemaRecord.firstPage = tableId / NDB_SF_PAGE_ENTRIES;
1628  c_writeSchemaRecord.noOfPages = 1;
1629  c_writeSchemaRecord.m_callback = * callback;
1630 
1631  startWriteSchemaFile(signal);
1632  }
1633  else
1634  {
1635  jam();
1636  if (callback != 0) {
1637  jam();
1638  execute(signal, *callback, 0);
1639  }
1640  }
1641 #endif
1642 }
1643 
1644 void Dbdict::startWriteSchemaFile(Signal* signal)
1645 {
1646  FsConnectRecordPtr fsPtr;
1647  c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
1648  fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_SCHEMA;
1649  openSchemaFile(signal, 0, fsPtr.i, true, c_writeSchemaRecord.newFile);
1650  c_writeSchemaRecord.noOfSchemaFilesHandled = 0;
1651 }//Dbdict::startWriteSchemaFile()
1652 
1653 void Dbdict::openSchemaFile(Signal* signal,
1654  Uint32 fileNo,
1655  Uint32 fsConPtr,
1656  bool writeFlag,
1657  bool newFile)
1658 {
1659  FsOpenReq * const fsOpenReq = (FsOpenReq *)&signal->theData[0];
1660  fsOpenReq->userReference = reference();
1661  fsOpenReq->userPointer = fsConPtr;
1662  if (writeFlag) {
1663  jam();
1664  fsOpenReq->fileFlags =
1665  FsOpenReq::OM_WRITEONLY |
1666  FsOpenReq::OM_SYNC;
1667  if (newFile)
1668  fsOpenReq->fileFlags |=
1669  FsOpenReq::OM_TRUNCATE |
1670  FsOpenReq::OM_CREATE;
1671  } else {
1672  jam();
1673  fsOpenReq->fileFlags = FsOpenReq::OM_READONLY;
1674  }//if
1675  fsOpenReq->fileNumber[3] = 0; // Initialise before byte changes
1676  FsOpenReq::setVersion(fsOpenReq->fileNumber, 1);
1677  FsOpenReq::setSuffix(fsOpenReq->fileNumber, FsOpenReq::S_SCHEMALOG);
1678  FsOpenReq::v1_setDisk(fsOpenReq->fileNumber, (fileNo + 1));
1679  FsOpenReq::v1_setTable(fsOpenReq->fileNumber, (Uint32)-1);
1680  FsOpenReq::v1_setFragment(fsOpenReq->fileNumber, (Uint32)-1);
1681  FsOpenReq::v1_setS(fsOpenReq->fileNumber, (Uint32)-1);
1682  FsOpenReq::v1_setP(fsOpenReq->fileNumber, 0);
1683 /* ---------------------------------------------------------------- */
1684 // File name : D1/DBDICT/P0.SchemaLog
1685 // D1 means Disk 1 (set by fileNo + 1). Writes to both D1 and D2
1686 // SchemaLog indicates that this is a file giving a list of current tables.
1687 /* ---------------------------------------------------------------- */
1688  sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
1689 }//openSchemaFile()
1690 
1691 void Dbdict::writeSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
1692 {
1693  FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
1694 
1695  // check write record
1696  WriteSchemaRecord & wr = c_writeSchemaRecord;
1697  ndbrequire(wr.pageId == (wr.pageId != 0) * NDB_SF_MAX_PAGES);
1698  ndbrequire(wr.noOfPages != 0);
1699  ndbrequire(wr.firstPage + wr.noOfPages <= NDB_SF_MAX_PAGES);
1700 
1701  fsRWReq->filePointer = filePtr;
1702  fsRWReq->userReference = reference();
1703  fsRWReq->userPointer = fsConPtr;
1704  fsRWReq->operationFlag = 0; // Initialise before bit changes
1705  FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 1);
1706  FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
1707  FsReadWriteReq::fsFormatArrayOfPages);
1708  fsRWReq->varIndex = ZBAT_SCHEMA_FILE;
1709  fsRWReq->numberOfPages = wr.noOfPages;
1710  // Write from memory page
1711  fsRWReq->data.arrayOfPages.varIndex = wr.pageId + wr.firstPage;
1712  fsRWReq->data.arrayOfPages.fileOffset = wr.firstPage;
1713  sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
1714 }//writeSchemaFile()
1715 
1716 void Dbdict::writeSchemaConf(Signal* signal,
1717  FsConnectRecordPtr fsPtr)
1718 {
1719  fsPtr.p->fsState = FsConnectRecord::CLOSE_WRITE_SCHEMA;
1720  closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
1721  return;
1722 }//Dbdict::writeSchemaConf()
1723 
1724 void Dbdict::closeFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
1725 {
1726  FsCloseReq * const fsCloseReq = (FsCloseReq *)&signal->theData[0];
1727  fsCloseReq->filePointer = filePtr;
1728  fsCloseReq->userReference = reference();
1729  fsCloseReq->userPointer = fsConPtr;
1730  FsCloseReq::setRemoveFileFlag(fsCloseReq->fileFlag, false);
1731  sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, FsCloseReq::SignalLength, JBA);
1732  return;
1733 }//closeFile()
1734 
1735 void Dbdict::closeWriteSchemaConf(Signal* signal,
1736  FsConnectRecordPtr fsPtr)
1737 {
1738  c_writeSchemaRecord.noOfSchemaFilesHandled++;
1739  if (c_writeSchemaRecord.noOfSchemaFilesHandled < 2) {
1740  jam();
1741  fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_SCHEMA;
1742  openSchemaFile(signal, 1, fsPtr.i, true, c_writeSchemaRecord.newFile);
1743  return;
1744  }
1745  ndbrequire(c_writeSchemaRecord.noOfSchemaFilesHandled == 2);
1746 
1747  c_fsConnectRecordPool.release(fsPtr);
1748 
1749  c_writeSchemaRecord.inUse = false;
1750  execute(signal, c_writeSchemaRecord.m_callback, 0);
1751  return;
1752 }//Dbdict::closeWriteSchemaConf()
1753 
1754 void Dbdict::startReadSchemaFile(Signal* signal)
1755 {
1756  //globalSignalLoggers.log(number(), "startReadSchemaFile");
1757  FsConnectRecordPtr fsPtr;
1758  c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
1759  fsPtr.p->fsState = FsConnectRecord::OPEN_READ_SCHEMA1;
1760  openSchemaFile(signal, 0, fsPtr.i, false, false);
1761 }//Dbdict::startReadSchemaFile()
1762 
1763 void Dbdict::openReadSchemaRef(Signal* signal,
1764  FsConnectRecordPtr fsPtr)
1765 {
1766  fsPtr.p->fsState = FsConnectRecord::OPEN_READ_SCHEMA2;
1767  openSchemaFile(signal, 1, fsPtr.i, false, false);
1768 }//Dbdict::openReadSchemaRef()
1769 
1770 void Dbdict::readSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr)
1771 {
1772  FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
1773 
1774  // check read record
1775  ReadSchemaRecord & rr = c_readSchemaRecord;
1776  ndbrequire(rr.pageId == (rr.pageId != 0) * NDB_SF_MAX_PAGES);
1777  ndbrequire(rr.noOfPages != 0);
1778  ndbrequire(rr.firstPage + rr.noOfPages <= NDB_SF_MAX_PAGES);
1779 
1780  fsRWReq->filePointer = filePtr;
1781  fsRWReq->userReference = reference();
1782  fsRWReq->userPointer = fsConPtr;
1783  fsRWReq->operationFlag = 0; // Initialise before bit changes
1784  FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 0);
1785  FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag,
1786  FsReadWriteReq::fsFormatArrayOfPages);
1787  fsRWReq->varIndex = ZBAT_SCHEMA_FILE;
1788  fsRWReq->numberOfPages = rr.noOfPages;
1789  fsRWReq->data.arrayOfPages.varIndex = rr.pageId + rr.firstPage;
1790  fsRWReq->data.arrayOfPages.fileOffset = rr.firstPage;
1791  sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 8, JBA);
1792 }//readSchemaFile()
1793 
1794 void Dbdict::readSchemaConf(Signal* signal,
1795  FsConnectRecordPtr fsPtr)
1796 {
1797 /* ---------------------------------------------------------------- */
1798 // Verify the data read from disk
1799 /* ---------------------------------------------------------------- */
1800  bool crashInd;
1801  if (fsPtr.p->fsState == FsConnectRecord::READ_SCHEMA1) {
1802  jam();
1803  crashInd = false;
1804  } else {
1805  jam();
1806  crashInd = true;
1807  }//if
1808 
1809  ReadSchemaRecord & rr = c_readSchemaRecord;
1810  XSchemaFile * xsf = &c_schemaFile[rr.pageId != 0];
1811 
1812  if (rr.schemaReadState == ReadSchemaRecord::INITIAL_READ_HEAD) {
1813  jam();
1814  ndbrequire(rr.firstPage == 0);
1815  SchemaFile * sf = &xsf->schemaPage[0];
1816  Uint32 noOfPages;
1817  if (sf->NdbVersion < NDB_SF_VERSION_5_0_6) {
1818  jam();
1819  const Uint32 pageSize_old = 32 * 1024;
1820  noOfPages = pageSize_old / NDB_SF_PAGE_SIZE - 1;
1821  } else {
1822  noOfPages = sf->FileSize / NDB_SF_PAGE_SIZE - 1;
1823  }
1824  rr.schemaReadState = ReadSchemaRecord::INITIAL_READ;
1825  if (noOfPages != 0) {
1826  rr.firstPage = 1;
1827  rr.noOfPages = noOfPages;
1828  readSchemaFile(signal, fsPtr.p->filePtr, fsPtr.i);
1829  return;
1830  }
1831  }
1832 
1833  SchemaFile * sf0 = &xsf->schemaPage[0];
1834  xsf->noOfPages = sf0->FileSize / NDB_SF_PAGE_SIZE;
1835 
1836  if (sf0->NdbVersion < NDB_SF_VERSION_5_0_6 &&
1837  ! convertSchemaFileTo_5_0_6(xsf)) {
1838  jam();
1839  ndbrequire(! crashInd);
1840  ndbrequire(fsPtr.p->fsState == FsConnectRecord::READ_SCHEMA1);
1841  readSchemaRef(signal, fsPtr);
1842  return;
1843  }
1844 
1845  if (sf0->NdbVersion < NDB_MAKE_VERSION(6,4,0) &&
1846  ! convertSchemaFileTo_6_4(xsf))
1847  {
1848  jam();
1849  ndbrequire(! crashInd);
1850  ndbrequire(fsPtr.p->fsState == FsConnectRecord::READ_SCHEMA1);
1851  readSchemaRef(signal, fsPtr);
1852  return;
1853  }
1854 
1855 
1856  for (Uint32 n = 0; n < xsf->noOfPages; n++) {
1857  SchemaFile * sf = &xsf->schemaPage[n];
1858  bool ok = false;
1859  const char *reason;
1860  if (memcmp(sf->Magic, NDB_SF_MAGIC, sizeof(sf->Magic)) != 0)
1861  { jam(); reason = "magic code"; }
1862  else if (sf->FileSize == 0)
1863  { jam(); reason = "file size == 0"; }
1864  else if (sf->FileSize % NDB_SF_PAGE_SIZE != 0)
1865  { jam(); reason = "invalid size multiple"; }
1866  else if (sf->FileSize != sf0->FileSize)
1867  { jam(); reason = "invalid size"; }
1868  else if (sf->PageNumber != n)
1869  { jam(); reason = "invalid page number"; }
1870  else if (computeChecksum((Uint32*)sf, NDB_SF_PAGE_SIZE_IN_WORDS) != 0)
1871  { jam(); reason = "invalid checksum"; }
1872  else
1873  ok = true;
1874 
1875  if (!ok)
1876  {
1877  char reason_msg[128];
1878  BaseString::snprintf(reason_msg, sizeof(reason_msg),
1879  "schema file corrupt, page %u (%s, "
1880  "sz=%u sz0=%u pn=%u)",
1881  n, reason, sf->FileSize, sf0->FileSize, sf->PageNumber);
1882  if (crashInd)
1883  progError(__LINE__, NDBD_EXIT_SR_SCHEMAFILE, reason_msg);
1884  ndbrequireErr(fsPtr.p->fsState == FsConnectRecord::READ_SCHEMA1,
1885  NDBD_EXIT_SR_SCHEMAFILE);
1886  jam();
1887  infoEvent("primary %s, trying backup", reason_msg);
1888  readSchemaRef(signal, fsPtr);
1889  return;
1890  }
1891  }
1892 
1893  fsPtr.p->fsState = FsConnectRecord::CLOSE_READ_SCHEMA;
1894  closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
1895  return;
1896 }//Dbdict::readSchemaConf()
1897 
1898 void Dbdict::readSchemaRef(Signal* signal,
1899  FsConnectRecordPtr fsPtr)
1900 {
1904  fsPtr.p->fsState = FsConnectRecord::OPEN_READ_SCHEMA2;
1905  closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
1906  return;
1907 }
1908 
1909 void Dbdict::closeReadSchemaConf(Signal* signal,
1910  FsConnectRecordPtr fsPtr)
1911 {
1912  c_fsConnectRecordPool.release(fsPtr);
1913  ReadSchemaRecord::SchemaReadState state = c_readSchemaRecord.schemaReadState;
1914  c_readSchemaRecord.schemaReadState = ReadSchemaRecord::IDLE;
1915 
1916  switch(state) {
1917  case ReadSchemaRecord::INITIAL_READ :
1918  jam();
1919  {
1920  // write back both copies
1921 
1922  ndbrequire(c_writeSchemaRecord.inUse == false);
1923  XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0 ];
1924  Uint32 noOfPages =
1925  (c_tableRecordPool.getSize() + NDB_SF_PAGE_ENTRIES - 1) /
1926  NDB_SF_PAGE_ENTRIES;
1927  resizeSchemaFile(xsf, noOfPages);
1928 
1929  c_writeSchemaRecord.inUse = true;
1930  c_writeSchemaRecord.pageId = c_schemaRecord.oldSchemaPage;
1931  c_writeSchemaRecord.newFile = true;
1932  c_writeSchemaRecord.firstPage = 0;
1933  c_writeSchemaRecord.noOfPages = xsf->noOfPages;
1934 
1935  c_writeSchemaRecord.m_callback.m_callbackFunction =
1936  safe_cast(&Dbdict::initSchemaFile_conf);
1937 
1938  startWriteSchemaFile(signal);
1939  }
1940  break;
1941 
1942  default :
1943  ndbrequire(false);
1944  break;
1945 
1946  }//switch
1947 }//Dbdict::closeReadSchemaConf()
1948 
1949 bool
1950 Dbdict::convertSchemaFileTo_5_0_6(XSchemaFile * xsf)
1951 {
1952  const Uint32 pageSize_old = 32 * 1024;
1953  union {
1954  Uint32 page_old[pageSize_old >> 2];
1955  SchemaFile _SchemaFile;
1956  };
1957  (void)_SchemaFile;
1958  SchemaFile * sf_old = (SchemaFile *)page_old;
1959 
1960  if (xsf->noOfPages * NDB_SF_PAGE_SIZE != pageSize_old)
1961  return false;
1962  SchemaFile * sf0 = &xsf->schemaPage[0];
1963  memcpy(sf_old, sf0, pageSize_old);
1964 
1965  // init max number new pages needed
1966  xsf->noOfPages = (sf_old->NoOfTableEntries + NDB_SF_PAGE_ENTRIES - 1) /
1967  NDB_SF_PAGE_ENTRIES;
1968  initSchemaFile(xsf, 0, xsf->noOfPages, true);
1969 
1970  Uint32 noOfPages = 1;
1971  Uint32 n, i, j;
1972  for (n = 0; n < xsf->noOfPages; n++) {
1973  jam();
1974  for (i = 0; i < NDB_SF_PAGE_ENTRIES; i++) {
1975  j = n * NDB_SF_PAGE_ENTRIES + i;
1976  if (j >= sf_old->NoOfTableEntries)
1977  continue;
1978  const SchemaFile::TableEntry_old & te_old = sf_old->TableEntries_old[j];
1979  if (te_old.m_tableState == SchemaFile::SF_UNUSED ||
1980  te_old.m_noOfPages == 0)
1981  continue;
1982  SchemaFile * sf = &xsf->schemaPage[n];
1983  SchemaFile::TableEntry & te = sf->TableEntries[i];
1984  te.m_tableState = te_old.m_tableState;
1985  te.m_tableVersion = te_old.m_tableVersion;
1986  te.m_tableType = te_old.m_tableType;
1987  te.m_info_words = te_old.m_noOfPages * ZSIZE_OF_PAGES_IN_WORDS -
1988  ZPAGE_HEADER_SIZE;
1989  te.m_gcp = te_old.m_gcp;
1990  if (noOfPages < n)
1991  noOfPages = n;
1992  }
1993  }
1994  xsf->noOfPages = noOfPages;
1995  initSchemaFile(xsf, 0, xsf->noOfPages, false);
1996 
1997  return true;
1998 }
1999 
2000 bool
2001 Dbdict::convertSchemaFileTo_6_4(XSchemaFile * xsf)
2002 {
2003  for (Uint32 i = 0; i < xsf->noOfPages; i++)
2004  {
2005  xsf->schemaPage[i].NdbVersion = NDB_VERSION_D;
2006  for (Uint32 j = 0; j < NDB_SF_PAGE_ENTRIES; j++)
2007  {
2008  Uint32 n = i * NDB_SF_PAGE_ENTRIES + j;
2009  SchemaFile::TableEntry * transEntry = getTableEntry(xsf, n);
2010 
2011  switch(SchemaFile::Old::TableState(transEntry->m_tableState)) {
2012  case SchemaFile::Old::INIT:
2013  transEntry->m_tableState = SchemaFile::SF_UNUSED;
2014  break;
2015  case SchemaFile::Old::ADD_STARTED:
2016  transEntry->m_tableState = SchemaFile::SF_UNUSED;
2017  break;
2018  case SchemaFile::Old::TABLE_ADD_COMMITTED:
2019  transEntry->m_tableState = SchemaFile::SF_IN_USE;
2020  break;
2021  case SchemaFile::Old::DROP_TABLE_STARTED:
2022  transEntry->m_tableState = SchemaFile::SF_UNUSED;
2023  break;
2024  case SchemaFile::Old::DROP_TABLE_COMMITTED:
2025  transEntry->m_tableState = SchemaFile::SF_UNUSED;
2026  break;
2027  case SchemaFile::Old::ALTER_TABLE_COMMITTED:
2028  transEntry->m_tableState = SchemaFile::SF_IN_USE;
2029  break;
2030  case SchemaFile::Old::TEMPORARY_TABLE_COMMITTED:
2031  transEntry->m_tableState = SchemaFile::SF_IN_USE;
2032  break;
2033  default:
2034  transEntry->m_tableState = SchemaFile::SF_UNUSED;
2035  break;
2036  }
2037  }
2038  computeChecksum(xsf, i);
2039  }
2040  return true;
2041 }
2042 
2043 /* **************************************************************** */
2044 /* ---------------------------------------------------------------- */
2045 /* MODULE: INITIALISATION MODULE ------------------------- */
2046 /* ---------------------------------------------------------------- */
2047 /* */
2048 /* This module contains initialisation of data at start/restart. */
2049 /* ---------------------------------------------------------------- */
2050 /* **************************************************************** */
2051 
2052 Dbdict::Dbdict(Block_context& ctx):
2053  SimulatedBlock(DBDICT, ctx),
2054  c_attributeRecordHash(c_attributeRecordPool),
2055  c_file_hash(c_file_pool),
2056  c_filegroup_hash(c_filegroup_pool),
2057  c_obj_hash(c_obj_pool),
2058  c_schemaOpHash(c_schemaOpPool),
2059  c_schemaTransHash(c_schemaTransPool),
2060  c_schemaTransList(c_schemaTransPool),
2061  c_schemaTransCount(0),
2062  c_txHandleHash(c_txHandlePool),
2063  c_hash_map_hash(c_hash_map_pool),
2064  c_opCreateEvent(c_opRecordPool),
2065  c_opSubEvent(c_opRecordPool),
2066  c_opDropEvent(c_opRecordPool),
2067  c_opSignalUtil(c_opRecordPool),
2068  c_opRecordSequence(0)
2069 {
2070  BLOCK_CONSTRUCTOR(Dbdict);
2071 
2072  // Transit signals
2073  addRecSignal(GSN_DUMP_STATE_ORD, &Dbdict::execDUMP_STATE_ORD);
2074  addRecSignal(GSN_GET_TABINFOREQ, &Dbdict::execGET_TABINFOREQ);
2075  addRecSignal(GSN_GET_TABLEID_REQ, &Dbdict::execGET_TABLEDID_REQ);
2076  addRecSignal(GSN_GET_TABINFO_CONF, &Dbdict::execGET_TABINFO_CONF);
2077  addRecSignal(GSN_CONTINUEB, &Dbdict::execCONTINUEB);
2078 
2079  addRecSignal(GSN_DBINFO_SCANREQ, &Dbdict::execDBINFO_SCANREQ);
2080 
2081  addRecSignal(GSN_CREATE_TABLE_REQ, &Dbdict::execCREATE_TABLE_REQ);
2082  addRecSignal(GSN_CREATE_TAB_REQ, &Dbdict::execCREATE_TAB_REQ);
2083  addRecSignal(GSN_CREATE_TAB_REF, &Dbdict::execCREATE_TAB_REF);
2084  addRecSignal(GSN_CREATE_TAB_CONF, &Dbdict::execCREATE_TAB_CONF);
2085  addRecSignal(GSN_CREATE_FRAGMENTATION_REQ, &Dbdict::execCREATE_FRAGMENTATION_REQ);
2086  addRecSignal(GSN_CREATE_FRAGMENTATION_REF, &Dbdict::execCREATE_FRAGMENTATION_REF);
2087  addRecSignal(GSN_CREATE_FRAGMENTATION_CONF, &Dbdict::execCREATE_FRAGMENTATION_CONF);
2088  addRecSignal(GSN_DIADDTABCONF, &Dbdict::execDIADDTABCONF);
2089  addRecSignal(GSN_DIADDTABREF, &Dbdict::execDIADDTABREF);
2090  addRecSignal(GSN_ADD_FRAGREQ, &Dbdict::execADD_FRAGREQ);
2091  addRecSignal(GSN_TAB_COMMITCONF, &Dbdict::execTAB_COMMITCONF);
2092  addRecSignal(GSN_TAB_COMMITREF, &Dbdict::execTAB_COMMITREF);
2093  addRecSignal(GSN_ALTER_TABLE_REQ, &Dbdict::execALTER_TABLE_REQ);
2094  addRecSignal(GSN_ALTER_TAB_REF, &Dbdict::execALTER_TAB_REF);
2095  addRecSignal(GSN_ALTER_TAB_CONF, &Dbdict::execALTER_TAB_CONF);
2096  addRecSignal(GSN_ALTER_TABLE_REF, &Dbdict::execALTER_TABLE_REF);
2097  addRecSignal(GSN_ALTER_TABLE_CONF, &Dbdict::execALTER_TABLE_CONF);
2098 
2099  // Index signals
2100  addRecSignal(GSN_CREATE_INDX_REQ, &Dbdict::execCREATE_INDX_REQ);
2101  addRecSignal(GSN_CREATE_INDX_IMPL_CONF, &Dbdict::execCREATE_INDX_IMPL_CONF);
2102  addRecSignal(GSN_CREATE_INDX_IMPL_REF, &Dbdict::execCREATE_INDX_IMPL_REF);
2103 
2104  addRecSignal(GSN_ALTER_INDX_REQ, &Dbdict::execALTER_INDX_REQ);
2105  addRecSignal(GSN_ALTER_INDX_CONF, &Dbdict::execALTER_INDX_CONF);
2106  addRecSignal(GSN_ALTER_INDX_REF, &Dbdict::execALTER_INDX_REF);
2107  addRecSignal(GSN_ALTER_INDX_IMPL_CONF, &Dbdict::execALTER_INDX_IMPL_CONF);
2108  addRecSignal(GSN_ALTER_INDX_IMPL_REF, &Dbdict::execALTER_INDX_IMPL_REF);
2109 
2110  addRecSignal(GSN_CREATE_TABLE_CONF, &Dbdict::execCREATE_TABLE_CONF);
2111  addRecSignal(GSN_CREATE_TABLE_REF, &Dbdict::execCREATE_TABLE_REF);
2112 
2113  addRecSignal(GSN_DROP_INDX_REQ, &Dbdict::execDROP_INDX_REQ);
2114  addRecSignal(GSN_DROP_INDX_IMPL_CONF, &Dbdict::execDROP_INDX_IMPL_CONF);
2115  addRecSignal(GSN_DROP_INDX_IMPL_REF, &Dbdict::execDROP_INDX_IMPL_REF);
2116 
2117  addRecSignal(GSN_DROP_TABLE_CONF, &Dbdict::execDROP_TABLE_CONF);
2118  addRecSignal(GSN_DROP_TABLE_REF, &Dbdict::execDROP_TABLE_REF);
2119 
2120  addRecSignal(GSN_BUILDINDXREQ, &Dbdict::execBUILDINDXREQ);
2121  addRecSignal(GSN_BUILDINDXCONF, &Dbdict::execBUILDINDXCONF);
2122  addRecSignal(GSN_BUILDINDXREF, &Dbdict::execBUILDINDXREF);
2123  addRecSignal(GSN_BUILD_INDX_IMPL_CONF, &Dbdict::execBUILD_INDX_IMPL_CONF);
2124  addRecSignal(GSN_BUILD_INDX_IMPL_REF, &Dbdict::execBUILD_INDX_IMPL_REF);
2125 
2126  // Util signals
2127  addRecSignal(GSN_UTIL_PREPARE_CONF, &Dbdict::execUTIL_PREPARE_CONF);
2128  addRecSignal(GSN_UTIL_PREPARE_REF, &Dbdict::execUTIL_PREPARE_REF);
2129 
2130  addRecSignal(GSN_UTIL_EXECUTE_CONF, &Dbdict::execUTIL_EXECUTE_CONF);
2131  addRecSignal(GSN_UTIL_EXECUTE_REF, &Dbdict::execUTIL_EXECUTE_REF);
2132 
2133  addRecSignal(GSN_UTIL_RELEASE_CONF, &Dbdict::execUTIL_RELEASE_CONF);
2134  addRecSignal(GSN_UTIL_RELEASE_REF, &Dbdict::execUTIL_RELEASE_REF);
2135 
2136  // Event signals
2137  addRecSignal(GSN_CREATE_EVNT_REQ, &Dbdict::execCREATE_EVNT_REQ);
2138  addRecSignal(GSN_CREATE_EVNT_CONF, &Dbdict::execCREATE_EVNT_CONF);
2139  addRecSignal(GSN_CREATE_EVNT_REF, &Dbdict::execCREATE_EVNT_REF);
2140 
2141  addRecSignal(GSN_CREATE_SUBID_CONF, &Dbdict::execCREATE_SUBID_CONF);
2142  addRecSignal(GSN_CREATE_SUBID_REF, &Dbdict::execCREATE_SUBID_REF);
2143 
2144  addRecSignal(GSN_SUB_CREATE_CONF, &Dbdict::execSUB_CREATE_CONF);
2145  addRecSignal(GSN_SUB_CREATE_REF, &Dbdict::execSUB_CREATE_REF);
2146 
2147  addRecSignal(GSN_SUB_START_REQ, &Dbdict::execSUB_START_REQ);
2148  addRecSignal(GSN_SUB_START_CONF, &Dbdict::execSUB_START_CONF);
2149  addRecSignal(GSN_SUB_START_REF, &Dbdict::execSUB_START_REF);
2150 
2151  addRecSignal(GSN_SUB_STOP_REQ, &Dbdict::execSUB_STOP_REQ);
2152  addRecSignal(GSN_SUB_STOP_CONF, &Dbdict::execSUB_STOP_CONF);
2153  addRecSignal(GSN_SUB_STOP_REF, &Dbdict::execSUB_STOP_REF);
2154 
2155  addRecSignal(GSN_DROP_EVNT_REQ, &Dbdict::execDROP_EVNT_REQ);
2156 
2157  addRecSignal(GSN_SUB_REMOVE_REQ, &Dbdict::execSUB_REMOVE_REQ);
2158  addRecSignal(GSN_SUB_REMOVE_CONF, &Dbdict::execSUB_REMOVE_CONF);
2159  addRecSignal(GSN_SUB_REMOVE_REF, &Dbdict::execSUB_REMOVE_REF);
2160 
2161  // Trigger signals
2162  addRecSignal(GSN_CREATE_TRIG_REQ, &Dbdict::execCREATE_TRIG_REQ);
2163  addRecSignal(GSN_CREATE_TRIG_CONF, &Dbdict::execCREATE_TRIG_CONF);
2164  addRecSignal(GSN_CREATE_TRIG_REF, &Dbdict::execCREATE_TRIG_REF);
2165  addRecSignal(GSN_DROP_TRIG_REQ, &Dbdict::execDROP_TRIG_REQ);
2166  addRecSignal(GSN_DROP_TRIG_CONF, &Dbdict::execDROP_TRIG_CONF);
2167  addRecSignal(GSN_DROP_TRIG_REF, &Dbdict::execDROP_TRIG_REF);
2168  // Impl
2169  addRecSignal(GSN_CREATE_TRIG_IMPL_CONF, &Dbdict::execCREATE_TRIG_IMPL_CONF);
2170  addRecSignal(GSN_CREATE_TRIG_IMPL_REF, &Dbdict::execCREATE_TRIG_IMPL_REF);
2171  addRecSignal(GSN_DROP_TRIG_IMPL_CONF, &Dbdict::execDROP_TRIG_IMPL_CONF);
2172  addRecSignal(GSN_DROP_TRIG_IMPL_REF, &Dbdict::execDROP_TRIG_IMPL_REF);
2173 
2174  // Received signals
2175  addRecSignal(GSN_GET_SCHEMA_INFOREQ, &Dbdict::execGET_SCHEMA_INFOREQ);
2176  addRecSignal(GSN_SCHEMA_INFO, &Dbdict::execSCHEMA_INFO);
2177  addRecSignal(GSN_SCHEMA_INFOCONF, &Dbdict::execSCHEMA_INFOCONF);
2178  addRecSignal(GSN_DICTSTARTREQ, &Dbdict::execDICTSTARTREQ);
2179  addRecSignal(GSN_READ_NODESCONF, &Dbdict::execREAD_NODESCONF);
2180  addRecSignal(GSN_FSOPENCONF, &Dbdict::execFSOPENCONF);
2181  addRecSignal(GSN_FSOPENREF, &Dbdict::execFSOPENREF, true);
2182  addRecSignal(GSN_FSCLOSECONF, &Dbdict::execFSCLOSECONF);
2183  addRecSignal(GSN_FSWRITECONF, &Dbdict::execFSWRITECONF);
2184  addRecSignal(GSN_FSREADCONF, &Dbdict::execFSREADCONF);
2185  addRecSignal(GSN_FSREADREF, &Dbdict::execFSREADREF, true);
2186  addRecSignal(GSN_LQHFRAGCONF, &Dbdict::execLQHFRAGCONF);
2187  addRecSignal(GSN_LQHADDATTCONF, &Dbdict::execLQHADDATTCONF);
2188  addRecSignal(GSN_LQHADDATTREF, &Dbdict::execLQHADDATTREF);
2189  addRecSignal(GSN_LQHFRAGREF, &Dbdict::execLQHFRAGREF);
2190  addRecSignal(GSN_NDB_STTOR, &Dbdict::execNDB_STTOR);
2191  addRecSignal(GSN_READ_CONFIG_REQ, &Dbdict::execREAD_CONFIG_REQ, true);
2192  addRecSignal(GSN_STTOR, &Dbdict::execSTTOR);
2193  addRecSignal(GSN_TC_SCHVERCONF, &Dbdict::execTC_SCHVERCONF);
2194  addRecSignal(GSN_NODE_FAILREP, &Dbdict::execNODE_FAILREP);
2195  addRecSignal(GSN_INCL_NODEREQ, &Dbdict::execINCL_NODEREQ);
2196  addRecSignal(GSN_API_FAILREQ, &Dbdict::execAPI_FAILREQ);
2197 
2198  addRecSignal(GSN_WAIT_GCP_REF, &Dbdict::execWAIT_GCP_REF);
2199  addRecSignal(GSN_WAIT_GCP_CONF, &Dbdict::execWAIT_GCP_CONF);
2200 
2201  addRecSignal(GSN_LIST_TABLES_REQ, &Dbdict::execLIST_TABLES_REQ);
2202 
2203  addRecSignal(GSN_DROP_TABLE_REQ, &Dbdict::execDROP_TABLE_REQ);
2204 
2205  addRecSignal(GSN_PREP_DROP_TAB_REQ, &Dbdict::execPREP_DROP_TAB_REQ);
2206  addRecSignal(GSN_PREP_DROP_TAB_REF, &Dbdict::execPREP_DROP_TAB_REF);
2207  addRecSignal(GSN_PREP_DROP_TAB_CONF, &Dbdict::execPREP_DROP_TAB_CONF);
2208 
2209  addRecSignal(GSN_DROP_TAB_REF, &Dbdict::execDROP_TAB_REF);
2210  addRecSignal(GSN_DROP_TAB_CONF, &Dbdict::execDROP_TAB_CONF);
2211 
2212  addRecSignal(GSN_CREATE_FILE_REQ, &Dbdict::execCREATE_FILE_REQ);
2213  addRecSignal(GSN_CREATE_FILEGROUP_REQ, &Dbdict::execCREATE_FILEGROUP_REQ);
2214 
2215  addRecSignal(GSN_DROP_FILE_REQ, &Dbdict::execDROP_FILE_REQ);
2216  addRecSignal(GSN_DROP_FILEGROUP_REQ, &Dbdict::execDROP_FILEGROUP_REQ);
2217 
2218  addRecSignal(GSN_DROP_FILE_IMPL_REF, &Dbdict::execDROP_FILE_IMPL_REF);
2219  addRecSignal(GSN_DROP_FILE_IMPL_CONF, &Dbdict::execDROP_FILE_IMPL_CONF);
2220 
2221  addRecSignal(GSN_DROP_FILEGROUP_IMPL_REF,
2222  &Dbdict::execDROP_FILEGROUP_IMPL_REF);
2223  addRecSignal(GSN_DROP_FILEGROUP_IMPL_CONF,
2224  &Dbdict::execDROP_FILEGROUP_IMPL_CONF);
2225 
2226  addRecSignal(GSN_CREATE_FILE_IMPL_REF, &Dbdict::execCREATE_FILE_IMPL_REF);
2227  addRecSignal(GSN_CREATE_FILE_IMPL_CONF, &Dbdict::execCREATE_FILE_IMPL_CONF);
2228  addRecSignal(GSN_CREATE_FILEGROUP_IMPL_REF,
2229  &Dbdict::execCREATE_FILEGROUP_IMPL_REF);
2230  addRecSignal(GSN_CREATE_FILEGROUP_IMPL_CONF,
2231  &Dbdict::execCREATE_FILEGROUP_IMPL_CONF);
2232 
2233  addRecSignal(GSN_BACKUP_LOCK_TAB_REQ, &Dbdict::execBACKUP_LOCK_TAB_REQ);
2234 
2235  addRecSignal(GSN_SCHEMA_TRANS_BEGIN_REQ, &Dbdict::execSCHEMA_TRANS_BEGIN_REQ);
2236  addRecSignal(GSN_SCHEMA_TRANS_BEGIN_CONF, &Dbdict::execSCHEMA_TRANS_BEGIN_CONF);
2237  addRecSignal(GSN_SCHEMA_TRANS_BEGIN_REF, &Dbdict::execSCHEMA_TRANS_BEGIN_REF);
2238  addRecSignal(GSN_SCHEMA_TRANS_END_REQ, &Dbdict::execSCHEMA_TRANS_END_REQ);
2239  addRecSignal(GSN_SCHEMA_TRANS_END_CONF, &Dbdict::execSCHEMA_TRANS_END_CONF);
2240  addRecSignal(GSN_SCHEMA_TRANS_END_REF, &Dbdict::execSCHEMA_TRANS_END_REF);
2241  addRecSignal(GSN_SCHEMA_TRANS_END_REP, &Dbdict::execSCHEMA_TRANS_END_REP);
2242  addRecSignal(GSN_SCHEMA_TRANS_IMPL_REQ, &Dbdict::execSCHEMA_TRANS_IMPL_REQ);
2243  addRecSignal(GSN_SCHEMA_TRANS_IMPL_CONF, &Dbdict::execSCHEMA_TRANS_IMPL_CONF);
2244  addRecSignal(GSN_SCHEMA_TRANS_IMPL_REF, &Dbdict::execSCHEMA_TRANS_IMPL_REF);
2245 
2246  addRecSignal(GSN_DICT_LOCK_REQ, &Dbdict::execDICT_LOCK_REQ);
2247  addRecSignal(GSN_DICT_UNLOCK_ORD, &Dbdict::execDICT_UNLOCK_ORD);
2248 
2249  addRecSignal(GSN_DICT_TAKEOVER_REQ, &Dbdict::execDICT_TAKEOVER_REQ);
2250  addRecSignal(GSN_DICT_TAKEOVER_REF, &Dbdict::execDICT_TAKEOVER_REF);
2251  addRecSignal(GSN_DICT_TAKEOVER_CONF, &Dbdict::execDICT_TAKEOVER_CONF);
2252 
2253  addRecSignal(GSN_CREATE_HASH_MAP_REQ, &Dbdict::execCREATE_HASH_MAP_REQ);
2254 
2255  addRecSignal(GSN_COPY_DATA_REQ, &Dbdict::execCOPY_DATA_REQ);
2256  addRecSignal(GSN_COPY_DATA_REF, &Dbdict::execCOPY_DATA_REF);
2257  addRecSignal(GSN_COPY_DATA_CONF, &Dbdict::execCOPY_DATA_CONF);
2258 
2259  addRecSignal(GSN_COPY_DATA_IMPL_REF, &Dbdict::execCOPY_DATA_IMPL_REF);
2260  addRecSignal(GSN_COPY_DATA_IMPL_CONF, &Dbdict::execCOPY_DATA_IMPL_CONF);
2261 
2262  addRecSignal(GSN_CREATE_NODEGROUP_REQ, &Dbdict::execCREATE_NODEGROUP_REQ);
2263  addRecSignal(GSN_CREATE_NODEGROUP_IMPL_REF, &Dbdict::execCREATE_NODEGROUP_IMPL_REF);
2264  addRecSignal(GSN_CREATE_NODEGROUP_IMPL_CONF, &Dbdict::execCREATE_NODEGROUP_IMPL_CONF);
2265 
2266  addRecSignal(GSN_CREATE_HASH_MAP_REF, &Dbdict::execCREATE_HASH_MAP_REF);
2267  addRecSignal(GSN_CREATE_HASH_MAP_CONF, &Dbdict::execCREATE_HASH_MAP_CONF);
2268 
2269  addRecSignal(GSN_DROP_NODEGROUP_REQ, &Dbdict::execDROP_NODEGROUP_REQ);
2270  addRecSignal(GSN_DROP_NODEGROUP_IMPL_REF, &Dbdict::execDROP_NODEGROUP_IMPL_REF);
2271  addRecSignal(GSN_DROP_NODEGROUP_IMPL_CONF, &Dbdict::execDROP_NODEGROUP_IMPL_CONF);
2272 
2273  // ordered index statistics
2274  addRecSignal(GSN_INDEX_STAT_REQ, &Dbdict::execINDEX_STAT_REQ);
2275  addRecSignal(GSN_INDEX_STAT_CONF, &Dbdict::execINDEX_STAT_CONF);
2276  addRecSignal(GSN_INDEX_STAT_REF, &Dbdict::execINDEX_STAT_REF);
2277  addRecSignal(GSN_INDEX_STAT_IMPL_CONF, &Dbdict::execINDEX_STAT_IMPL_CONF);
2278  addRecSignal(GSN_INDEX_STAT_IMPL_REF, &Dbdict::execINDEX_STAT_IMPL_REF);
2279  addRecSignal(GSN_INDEX_STAT_REP, &Dbdict::execINDEX_STAT_REP);
2280 }//Dbdict::Dbdict()
2281 
2282 Dbdict::~Dbdict()
2283 {
2284 }//Dbdict::~Dbdict()
2285 
2286 BLOCK_FUNCTIONS(Dbdict)
2287 
2288 bool
2289 Dbdict::getParam(const char * name, Uint32 * count)
2290 {
2291  if (name != 0 && count != 0)
2292  {
2293  if (strcmp(name, "ActiveCounters") == 0)
2294  {
2295  * count = 25;
2296  return true;
2297  }
2298  }
2299  return false;
2300 }
2301 
2302 void Dbdict::initCommonData()
2303 {
2304 /* ---------------------------------------------------------------- */
2305 // Initialise all common variables.
2306 /* ---------------------------------------------------------------- */
2307  initRetrieveRecord(0, 0, 0);
2308  initSchemaRecord();
2309  initRestartRecord();
2310  initSendSchemaRecord();
2311  initReadTableRecord();
2312  initWriteTableRecord();
2313  initReadSchemaRecord();
2314  initWriteSchemaRecord();
2315 
2316  c_masterNodeId = ZNIL;
2317  c_numberNode = 0;
2318  c_noNodesFailed = 0;
2319  c_failureNr = 0;
2320  c_packTable.m_state = PackTable::PTS_IDLE;
2321  c_startPhase = 0;
2322  c_restartType = 255; //Ensure not used restartType
2323  c_tabinfoReceived = 0;
2324  c_initialStart = false;
2325  c_systemRestart = false;
2326  c_initialNodeRestart = false;
2327  c_nodeRestart = false;
2328 
2329  c_outstanding_sub_startstop = 0;
2330  c_sub_startstop_lock.clear();
2331 
2332 #if defined VM_TRACE || defined ERROR_INSERT
2333  g_trace = 99;
2334 #else
2335  g_trace = 0;
2336 #endif
2337 
2338 }//Dbdict::initCommonData()
2339 
2340 void Dbdict::initRecords()
2341 {
2342  initNodeRecords();
2343  initPageRecords();
2344  initTableRecords();
2345  initTriggerRecords();
2346 }//Dbdict::initRecords()
2347 
2348 void Dbdict::initSendSchemaRecord()
2349 {
2350  c_sendSchemaRecord.noOfWords = (Uint32)-1;
2351  c_sendSchemaRecord.pageId = RNIL;
2352  c_sendSchemaRecord.noOfWordsCurrentlySent = 0;
2353  c_sendSchemaRecord.noOfSignalsSentSinceDelay = 0;
2354  c_sendSchemaRecord.inUse = false;
2355  //c_sendSchemaRecord.sendSchemaState = SendSchemaRecord::IDLE;
2356 }//initSendSchemaRecord()
2357 
2358 void Dbdict::initReadTableRecord()
2359 {
2360  c_readTableRecord.no_of_words= 0;
2361  c_readTableRecord.pageId = RNIL;
2362  c_readTableRecord.tableId = ZNIL;
2363  c_readTableRecord.inUse = false;
2364 }//initReadTableRecord()
2365 
2366 void Dbdict::initWriteTableRecord()
2367 {
2368  c_writeTableRecord.no_of_words= 0;
2369  c_writeTableRecord.pageId = RNIL;
2370  c_writeTableRecord.noOfTableFilesHandled = 3;
2371  c_writeTableRecord.tableId = ZNIL;
2372  c_writeTableRecord.tableWriteState = WriteTableRecord::IDLE;
2373 }//initWriteTableRecord()
2374 
2375 void Dbdict::initReadSchemaRecord()
2376 {
2377  c_readSchemaRecord.pageId = RNIL;
2378  c_readSchemaRecord.schemaReadState = ReadSchemaRecord::IDLE;
2379 }//initReadSchemaRecord()
2380 
2381 void Dbdict::initWriteSchemaRecord()
2382 {
2383  c_writeSchemaRecord.inUse = false;
2384  c_writeSchemaRecord.pageId = RNIL;
2385  c_writeSchemaRecord.noOfSchemaFilesHandled = 3;
2386 }//initWriteSchemaRecord()
2387 
2388 void Dbdict::initRetrieveRecord(Signal* signal, Uint32 i, Uint32 returnCode)
2389 {
2390  c_retrieveRecord.busyState = false;
2391  c_retrieveRecord.blockRef = 0;
2392  c_retrieveRecord.m_senderData = RNIL;
2393  c_retrieveRecord.tableId = RNIL;
2394  c_retrieveRecord.currentSent = 0;
2395  c_retrieveRecord.retrievedNoOfPages = 0;
2396  c_retrieveRecord.retrievedNoOfWords = 0;
2397  c_retrieveRecord.m_useLongSig = false;
2398 }//initRetrieveRecord()
2399 
2400 void Dbdict::initSchemaRecord()
2401 {
2402  c_schemaRecord.schemaPage = RNIL;
2403  c_schemaRecord.oldSchemaPage = RNIL;
2404 }//Dbdict::initSchemaRecord()
2405 
2406 void Dbdict::initNodeRecords()
2407 {
2408  jam();
2409  for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
2410  NodeRecordPtr nodePtr;
2411  c_nodes.getPtr(nodePtr, i);
2412  new (nodePtr.p) NodeRecord();
2413  nodePtr.p->hotSpare = false;
2414  nodePtr.p->nodeState = NodeRecord::API_NODE;
2415  }//for
2416 }//Dbdict::initNodeRecords()
2417 
2418 void Dbdict::initPageRecords()
2419 {
2420  c_retrieveRecord.retrievePage = ZMAX_PAGES_OF_TABLE_DEFINITION;
2421  ndbrequire(ZNUMBER_OF_PAGES >= (ZMAX_PAGES_OF_TABLE_DEFINITION + 1));
2422  c_schemaRecord.schemaPage = 0;
2423  c_schemaRecord.oldSchemaPage = NDB_SF_MAX_PAGES;
2424 }//Dbdict::initPageRecords()
2425 
2426 void Dbdict::initTableRecords()
2427 {
2428  TableRecordPtr tablePtr;
2429  while (1) {
2430  jam();
2432  c_tableRecordPool.seize(tablePtr);
2433  if (tablePtr.i == RNIL) {
2434  jam();
2435  break;
2436  }//if
2437  initialiseTableRecord(tablePtr);
2438  }//while
2439 }//Dbdict::initTableRecords()
2440 
2441 void Dbdict::initialiseTableRecord(TableRecordPtr tablePtr)
2442 {
2443  new (tablePtr.p) TableRecord();
2444  tablePtr.p->filePtr[0] = RNIL;
2445  tablePtr.p->filePtr[1] = RNIL;
2446  tablePtr.p->tableId = tablePtr.i;
2447  tablePtr.p->tableVersion = (Uint32)-1;
2448  tablePtr.p->fragmentType = DictTabInfo::AllNodesSmallTable;
2449  tablePtr.p->gciTableCreated = 0;
2450  tablePtr.p->noOfAttributes = ZNIL;
2451  tablePtr.p->noOfNullAttr = 0;
2452  tablePtr.p->fragmentCount = 0;
2453  /*
2454  tablePtr.p->lh3PageIndexBits = 0;
2455  tablePtr.p->lh3DistrBits = 0;
2456  tablePtr.p->lh3PageBits = 6;
2457  */
2458  tablePtr.p->kValue = 6;
2459  tablePtr.p->localKeyLen = 1;
2460  tablePtr.p->maxLoadFactor = 80;
2461  tablePtr.p->minLoadFactor = 70;
2462  tablePtr.p->noOfPrimkey = 1;
2463  tablePtr.p->tupKeyLength = 1;
2464  tablePtr.p->maxRowsLow = 0;
2465  tablePtr.p->maxRowsHigh = 0;
2466  tablePtr.p->defaultNoPartFlag = true;
2467  tablePtr.p->linearHashFlag = true;
2468  tablePtr.p->m_bits = 0;
2469  tablePtr.p->minRowsLow = 0;
2470  tablePtr.p->minRowsHigh = 0;
2471  tablePtr.p->singleUserMode = 0;
2472  tablePtr.p->tableType = DictTabInfo::UserTable;
2473  tablePtr.p->primaryTableId = RNIL;
2474  // volatile elements
2475  tablePtr.p->indexState = TableRecord::IS_UNDEFINED;
2476  tablePtr.p->triggerId = RNIL;
2477  tablePtr.p->buildTriggerId = RNIL;
2478  tablePtr.p->m_read_locked= 0;
2479  tablePtr.p->storageType = NDB_STORAGETYPE_DEFAULT;
2480  tablePtr.p->indexStatFragId = ZNIL;
2481  tablePtr.p->indexStatNodeId = ZNIL;
2482  tablePtr.p->indexStatBgRequest = 0;
2483 }//Dbdict::initialiseTableRecord()
2484 
2485 void Dbdict::initTriggerRecords()
2486 {
2487  TriggerRecordPtr triggerPtr;
2488  while (1) {
2489  jam();
2491  c_triggerRecordPool.seize(triggerPtr);
2492  if (triggerPtr.i == RNIL) {
2493  jam();
2494  break;
2495  }//if
2496  initialiseTriggerRecord(triggerPtr);
2497  }//while
2498 }
2499 
2500 void Dbdict::initialiseTriggerRecord(TriggerRecordPtr triggerPtr)
2501 {
2502  new (triggerPtr.p) TriggerRecord();
2503  triggerPtr.p->triggerState = TriggerRecord::TS_NOT_DEFINED;
2504  triggerPtr.p->triggerId = RNIL;
2505  triggerPtr.p->tableId = RNIL;
2506  triggerPtr.p->attributeMask.clear();
2507  triggerPtr.p->indexId = RNIL;
2508 }
2509 
2510 Uint32 Dbdict::getFsConnRecord()
2511 {
2512  FsConnectRecordPtr fsPtr;
2513  c_fsConnectRecordPool.seize(fsPtr);
2514  ndbrequire(fsPtr.i != RNIL);
2515  fsPtr.p->filePtr = (Uint32)-1;
2516  fsPtr.p->ownerPtr = RNIL;
2517  fsPtr.p->fsState = FsConnectRecord::IDLE;
2518  return fsPtr.i;
2519 }//Dbdict::getFsConnRecord()
2520 
2521 /*
2522  * Search schemafile for free entry. Its index is used as 'logical id'
2523  * of new disk-stored object.
2524  */
2525 Uint32 Dbdict::getFreeObjId(Uint32 minId, bool both)
2526 {
2527  const XSchemaFile * newxsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
2528  const XSchemaFile * oldxsf = &c_schemaFile[SchemaRecord::OLD_SCHEMA_FILE];
2529  const Uint32 noOfEntries = newxsf->noOfPages * NDB_SF_PAGE_ENTRIES;
2530  for (Uint32 i = minId; i<noOfEntries; i++)
2531  {
2532  const SchemaFile::TableEntry * oldentry = getTableEntry(oldxsf, i);
2533  const SchemaFile::TableEntry * newentry = getTableEntry(newxsf, i);
2534  if (newentry->m_tableState == (Uint32)SchemaFile::SF_UNUSED)
2535  {
2536  jam();
2537  if (both == false ||
2538  oldentry->m_tableState == (Uint32)SchemaFile::SF_UNUSED)
2539  {
2540  jam();
2541  return i;
2542  }
2543  }
2544  }
2545  return RNIL;
2546 }
2547 
2548 Uint32 Dbdict::getFreeTableRecord(Uint32 primaryTableId)
2549 {
2550  Uint32 minId = (primaryTableId == RNIL ? 0 : primaryTableId + 1);
2551  if (ERROR_INSERTED(6012) && minId < 4096){
2552  minId = 4096;
2553  CLEAR_ERROR_INSERT_VALUE;
2554  }
2555  Uint32 i = getFreeObjId(0);
2556  if (i == RNIL) {
2557  jam();
2558  return RNIL;
2559  }
2560  if (i >= c_tableRecordPool.getSize()) {
2561  jam();
2562  return RNIL;
2563  }
2564 
2565  TableRecordPtr tablePtr;
2566  c_tableRecordPool.getPtr(tablePtr, i);
2567  initialiseTableRecord(tablePtr);
2568  return i;
2569 }
2570 
2571 Uint32 Dbdict::getFreeTriggerRecord()
2572 {
2573  const Uint32 size = c_triggerRecordPool.getSize();
2574  TriggerRecordPtr triggerPtr;
2575  for (triggerPtr.i = 0; triggerPtr.i < size; triggerPtr.i++) {
2576  jam();
2577  c_triggerRecordPool.getPtr(triggerPtr);
2578  if (triggerPtr.p->triggerState == TriggerRecord::TS_NOT_DEFINED) {
2579  jam();
2580  initialiseTriggerRecord(triggerPtr);
2581  return triggerPtr.i;
2582  }
2583  }
2584  return RNIL;
2585 }
2586 
2587 Uint32
2588 Dbdict::check_read_obj(Uint32 objId, Uint32 transId)
2589 {
2590  XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
2591  if (objId < (NDB_SF_PAGE_ENTRIES * xsf->noOfPages))
2592  {
2593  jam();
2594  return check_read_obj(getTableEntry(xsf, objId), transId);
2595  }
2596  return GetTabInfoRef::InvalidTableId;
2597 }
2598 
2599 Uint32
2600 Dbdict::check_read_obj(SchemaFile::TableEntry* te, Uint32 transId)
2601 {
2602  if (te->m_tableState == SchemaFile::SF_UNUSED)
2603  {
2604  jam();
2605  return GetTabInfoRef::TableNotDefined;
2606  }
2607 
2608  if (te->m_transId == 0 || te->m_transId == transId)
2609  {
2610  jam();
2611  return 0;
2612  }
2613 
2614  switch(te->m_tableState){
2615  case SchemaFile::SF_CREATE:
2616  jam();
2617  return GetTabInfoRef::TableNotDefined;
2618  break;
2619  case SchemaFile::SF_ALTER:
2620  jam();
2621  return 0;
2622  case SchemaFile::SF_DROP:
2623  jam();
2625  return DropTableRef::ActiveSchemaTrans;
2626  case SchemaFile::SF_IN_USE:
2627  jam();
2628  return 0;
2629  default:
2631  return GetTabInfoRef::TableNotDefined;
2632  }
2633 }
2634 
2635 
2636 Uint32
2637 Dbdict::check_write_obj(Uint32 objId, Uint32 transId)
2638 {
2639  XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
2640  if (objId < (NDB_SF_PAGE_ENTRIES * xsf->noOfPages))
2641  {
2642  jam();
2643  SchemaFile::TableEntry* te = getTableEntry(xsf, objId);
2644 
2645  if (te->m_tableState == SchemaFile::SF_UNUSED)
2646  {
2647  jam();
2648  return GetTabInfoRef::TableNotDefined;
2649  }
2650 
2651  if (te->m_transId == 0 || te->m_transId == transId)
2652  {
2653  jam();
2654  return 0;
2655  }
2656 
2657  return DropTableRef::ActiveSchemaTrans;
2658  }
2659  return GetTabInfoRef::InvalidTableId;
2660 }
2661 
2662 Uint32
2663 Dbdict::check_write_obj(Uint32 objId, Uint32 transId,
2664  SchemaFile::EntryState op,
2665  ErrorInfo& error)
2666 {
2667  Uint32 err = check_write_obj(objId, transId);
2668  if (err)
2669  {
2670  jam();
2671  setError(error, err, __LINE__);
2672  }
2673 
2674  return err;
2675 }
2676 
2677 
2678 
2679 /* **************************************************************** */
2680 /* ---------------------------------------------------------------- */
2681 /* MODULE: START/RESTART HANDLING ------------------------ */
2682 /* ---------------------------------------------------------------- */
2683 /* */
2684 /* This module contains the code that is common for all */
2685 /* start/restart types. */
2686 /* ---------------------------------------------------------------- */
2687 /* **************************************************************** */
2688 
2689 /* ---------------------------------------------------------------- */
2690 // This is sent as the first signal during start/restart.
2691 /* ---------------------------------------------------------------- */
2692 void Dbdict::execSTTOR(Signal* signal)
2693 {
2694  jamEntry();
2695  c_startPhase = signal->theData[1];
2696  switch (c_startPhase) {
2697  case 1:
2698  break;
2699  case 3:
2700  c_restartType = signal->theData[7]; /* valid if 3 */
2701  ndbrequire(c_restartType == NodeState::ST_INITIAL_START ||
2702  c_restartType == NodeState::ST_SYSTEM_RESTART ||
2703  c_restartType == NodeState::ST_INITIAL_NODE_RESTART ||
2704  c_restartType == NodeState::ST_NODE_RESTART);
2705  break;
2706  case 7:
2707  /*
2708  * config cannot yet be changed dynamically but we start the
2709  * loop always anyway because the cost is minimal
2710  */
2711  c_indexStatBgId = 0;
2712  indexStatBg_sendContinueB(signal);
2713  break;
2714  }
2715  sendSTTORRY(signal);
2716 }//execSTTOR()
2717 
2718 void Dbdict::sendSTTORRY(Signal* signal)
2719 {
2720  signal->theData[0] = 0; /* garbage SIGNAL KEY */
2721  signal->theData[1] = 0; /* garbage SIGNAL VERSION NUMBER */
2722  signal->theData[2] = 0; /* garbage */
2723  signal->theData[3] = 1; /* first wanted start phase */
2724  signal->theData[4] = 3; /* get type of start */
2725  signal->theData[5] = 7; /* start index stat bg loop */
2726  signal->theData[6] = ZNOMOREPHASES;
2727  sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 7, JBB);
2728 }
2729 
2730 /* ---------------------------------------------------------------- */
2731 // We receive information about sizes of records.
2732 /* ---------------------------------------------------------------- */
2733 void Dbdict::execREAD_CONFIG_REQ(Signal* signal)
2734 {
2735  const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
2736  Uint32 ref = req->senderRef;
2737  Uint32 senderData = req->senderData;
2738  ndbrequire(req->noOfParameters == 0);
2739 
2740  jamEntry();
2741 
2742  const ndb_mgm_configuration_iterator * p =
2743  m_ctx.m_config.getOwnConfigIterator();
2744  ndbrequire(p != 0);
2745 
2746  Uint32 attributesize, tablerecSize;
2747  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_TRIGGERS,
2748  &c_maxNoOfTriggers));
2749  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DICT_ATTRIBUTE,&attributesize));
2750  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DICT_TABLE, &tablerecSize));
2751  c_indexStatAutoCreate = 0;
2752  ndb_mgm_get_int_parameter(p, CFG_DB_INDEX_STAT_AUTO_CREATE,
2753  &c_indexStatAutoCreate);
2754  c_indexStatAutoUpdate = 0;
2755  ndb_mgm_get_int_parameter(p, CFG_DB_INDEX_STAT_AUTO_UPDATE,
2756  &c_indexStatAutoUpdate);
2757 
2758  c_attributeRecordPool.setSize(attributesize);
2759  c_attributeRecordHash.setSize(64);
2760  c_fsConnectRecordPool.setSize(ZFS_CONNECT_SIZE);
2761  c_nodes.setSize(MAX_NDB_NODES);
2762  c_pageRecordArray.setSize(ZNUMBER_OF_PAGES);
2763  c_schemaPageRecordArray.setSize(2 * NDB_SF_MAX_PAGES);
2764  c_tableRecordPool.setSize(tablerecSize);
2765  g_key_descriptor_pool.setSize(tablerecSize);
2766  c_triggerRecordPool.setSize(c_maxNoOfTriggers);
2767 
2768  c_opSectionBufferPool.setSize(1024); // units OpSectionSegmentSize
2769  c_schemaOpHash.setSize(MAX_SCHEMA_OPERATIONS);
2770  c_schemaTransPool.setSize(MAX_SCHEMA_TRANSACTIONS);
2771  c_schemaTransHash.setSize(2);
2772  c_txHandlePool.setSize(2);
2773  c_txHandleHash.setSize(2);
2774 
2775  c_obj_pool.setSize(tablerecSize+c_maxNoOfTriggers);
2776  c_obj_hash.setSize((tablerecSize+c_maxNoOfTriggers+1)/2);
2777  m_dict_lock_pool.setSize(MAX_NDB_NODES);
2778 
2779  Pool_context pc;
2780  pc.m_block = this;
2781 
2782  c_file_hash.setSize(16);
2783  c_filegroup_hash.setSize(16);
2784 
2785  c_file_pool.init(RT_DBDICT_FILE, pc);
2786  c_filegroup_pool.init(RT_DBDICT_FILEGROUP, pc);
2787 
2788  // new OpRec pools
2795  c_createTableRecPool.setSize(1 + 2 * MAX_INDEXES);
2796  c_dropTableRecPool.setSize(1 + 2 * MAX_INDEXES);
2797  c_alterTableRecPool.setSize(32);
2798  c_createTriggerRecPool.setSize(4 * 2 * MAX_INDEXES);
2799  c_dropTriggerRecPool.setSize(3 * 2 * MAX_INDEXES);
2800  c_createIndexRecPool.setSize(2*MAX_INDEXES);
2801  c_dropIndexRecPool.setSize(2 * MAX_INDEXES);
2802  c_alterIndexRecPool.setSize(2 * MAX_INDEXES);
2803  c_buildIndexRecPool.setSize(2 * 2 * MAX_INDEXES);
2804  c_indexStatRecPool.setSize((1 + 4) * MAX_INDEXES); //main + 4 subs
2805  c_createFilegroupRecPool.setSize(32);
2806  c_createFileRecPool.setSize(32);
2807  c_dropFilegroupRecPool.setSize(32);
2808  c_dropFileRecPool.setSize(32);
2809  c_createHashMapRecPool.setSize(32);
2810  c_copyDataRecPool.setSize(32);
2811  c_schemaOpPool.setSize(1 + 32 * MAX_INDEXES);
2812 
2813  c_hash_map_hash.setSize(4);
2814  c_hash_map_pool.setSize(32);
2815  g_hash_map.setSize(32);
2816 
2817  c_createNodegroupRecPool.setSize(2);
2818  c_dropNodegroupRecPool.setSize(2);
2819 
2820  c_opRecordPool.setSize(256); // XXX need config params
2821  c_opCreateEvent.setSize(2);
2822  c_opSubEvent.setSize(2);
2823  c_opDropEvent.setSize(2);
2824  c_opSignalUtil.setSize(8);
2825 
2826  // Initialize schema file copies
2827  c_schemaFile[0].schemaPage =
2828  (SchemaFile*)c_schemaPageRecordArray.getPtr(0 * NDB_SF_MAX_PAGES);
2829  c_schemaFile[0].noOfPages = 0;
2830  c_schemaFile[1].schemaPage =
2831  (SchemaFile*)c_schemaPageRecordArray.getPtr(1 * NDB_SF_MAX_PAGES);
2832  c_schemaFile[1].noOfPages = 0;
2833 
2834  Uint32 rps = 0;
2835  rps += tablerecSize * (MAX_TAB_NAME_SIZE + MAX_FRM_DATA_SIZE);
2836  rps += attributesize * (MAX_ATTR_NAME_SIZE + MAX_ATTR_DEFAULT_VALUE_SIZE);
2837  rps += c_maxNoOfTriggers * MAX_TAB_NAME_SIZE;
2838  rps += (10 + 10) * MAX_TAB_NAME_SIZE;
2839 
2840  Uint32 sm = 5;
2841  ndb_mgm_get_int_parameter(p, CFG_DB_STRING_MEMORY, &sm);
2842  if (sm == 0)
2843  sm = 25;
2844 
2845  Uint64 sb = 0;
2846  if (sm <= 100)
2847  {
2848  sb = (Uint64(rps) * Uint64(sm)) / 100;
2849  }
2850  else
2851  {
2852  sb = sm;
2853  }
2854 
2855  sb /= (Rope::getSegmentSize() * sizeof(Uint32));
2856  sb += 100; // more safty
2857  ndbrequire(sb < (Uint64(1) << 32));
2858  c_rope_pool.setSize(Uint32(sb));
2859 
2860  // Initialize BAT for interface to file system
2861  NewVARIABLE* bat = allocateBat(2);
2862  bat[0].WA = &c_schemaPageRecordArray.getPtr(0)->word[0];
2863  bat[0].nrr = 2 * NDB_SF_MAX_PAGES;
2864  bat[0].ClusterSize = NDB_SF_PAGE_SIZE;
2865  bat[0].bits.q = NDB_SF_PAGE_SIZE_IN_WORDS_LOG2;
2866  bat[0].bits.v = 5; // 32 bits per element
2867  bat[1].WA = &c_pageRecordArray.getPtr(0)->word[0];
2868  bat[1].nrr = ZNUMBER_OF_PAGES;
2869  bat[1].ClusterSize = ZSIZE_OF_PAGES_IN_WORDS * 4;
2870  bat[1].bits.q = ZLOG_SIZE_OF_PAGES_IN_WORDS; // 2**13 = 8192 elements
2871  bat[1].bits.v = 5; // 32 bits per element
2872 
2873  initCommonData();
2874  initRecords();
2875 
2876  ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
2877  conf->senderRef = reference();
2878  conf->senderData = senderData;
2879  sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
2880  ReadConfigConf::SignalLength, JBB);
2881 
2882  {
2883  Ptr<DictObject> ptr;
2884  SLList<DictObject> objs(c_obj_pool);
2885  while(objs.seize(ptr))
2886  new (ptr.p) DictObject();
2887  objs.release();
2888  }
2889 
2890  unsigned trace = 0;
2891  char buf[100];
2892  if (NdbEnv_GetEnv("DICT_TRACE", buf, sizeof(buf)))
2893  {
2894  jam();
2895  g_trace = (unsigned)atoi(buf);
2896  }
2897  else if (ndb_mgm_get_int_parameter(p, CFG_DB_DICT_TRACE, &trace) == 0)
2898  {
2899  g_trace = trace;
2900  }
2901 }//execSIZEALT_REP()
2902 
2903 /* ---------------------------------------------------------------- */
2904 // Start phase signals sent by CNTR. We reply with NDB_STTORRY when
2905 // we completed this phase.
2906 /* ---------------------------------------------------------------- */
2907 void Dbdict::execNDB_STTOR(Signal* signal)
2908 {
2909  jamEntry();
2910  c_startPhase = signal->theData[2];
2911  const Uint32 restartType = signal->theData[3];
2912  if (restartType == NodeState::ST_INITIAL_START) {
2913  jam();
2914  c_initialStart = true;
2915  } else if (restartType == NodeState::ST_SYSTEM_RESTART) {
2916  jam();
2917  c_systemRestart = true;
2918  } else if (restartType == NodeState::ST_INITIAL_NODE_RESTART) {
2919  jam();
2920  c_initialNodeRestart = true;
2921  } else if (restartType == NodeState::ST_NODE_RESTART) {
2922  jam();
2923  c_nodeRestart = true;
2924  } else {
2925  ndbrequire(false);
2926  }//if
2927  switch (c_startPhase) {
2928  case 1:
2929  jam();
2930  initSchemaFile(signal);
2931  break;
2932  case 3:
2933  jam();
2934  signal->theData[0] = reference();
2935  sendSignal(NDBCNTR_REF, GSN_READ_NODESREQ, signal, 1, JBB);
2936  break;
2937  case 6:
2938  jam();
2939  c_initialStart = false;
2940  c_systemRestart = false;
2941  c_initialNodeRestart = false;
2942  c_nodeRestart = false;
2943  sendNDB_STTORRY(signal);
2944  break;
2945  case 7:
2946  sendNDB_STTORRY(signal);
2947  break;
2948  default:
2949  jam();
2950  sendNDB_STTORRY(signal);
2951  break;
2952  }//switch
2953 }//execNDB_STTOR()
2954 
2955 void Dbdict::sendNDB_STTORRY(Signal* signal)
2956 {
2957  signal->theData[0] = reference();
2958  sendSignal(NDBCNTR_REF, GSN_NDB_STTORRY, signal, 1, JBB);
2959  return;
2960 }//sendNDB_STTORRY()
2961 
2962 /* ---------------------------------------------------------------- */
2963 // We receive the information about which nodes that are up and down.
2964 /* ---------------------------------------------------------------- */
2965 void Dbdict::execREAD_NODESCONF(Signal* signal)
2966 {
2967  jamEntry();
2968 
2969  ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
2970  c_numberNode = readNodes->noOfNodes;
2971  c_masterNodeId = readNodes->masterNodeId;
2972 
2973  c_noNodesFailed = 0;
2974  c_aliveNodes.clear();
2975  for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
2976  jam();
2977  NodeRecordPtr nodePtr;
2978  c_nodes.getPtr(nodePtr, i);
2979 
2980  if (NdbNodeBitmask::get(readNodes->allNodes, i)) {
2981  jam();
2982  nodePtr.p->nodeState = NodeRecord::NDB_NODE_ALIVE;
2983  if (NdbNodeBitmask::get(readNodes->inactiveNodes, i)) {
2984  jam();
2992  nodePtr.p->nodeState = NodeRecord::NDB_NODE_DEAD;
2993  c_noNodesFailed++;
2994  } else {
2995  c_aliveNodes.set(i);
2996  }
2997  }//if
2998  }//for
2999  sendNDB_STTORRY(signal);
3000 }//execREAD_NODESCONF()
3001 
3002 void Dbdict::initSchemaFile(Signal* signal)
3003 {
3004  XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
3005  xsf->noOfPages = (c_tableRecordPool.getSize() + NDB_SF_PAGE_ENTRIES - 1)
3006  / NDB_SF_PAGE_ENTRIES;
3007  initSchemaFile(xsf, 0, xsf->noOfPages, true);
3008  // init alt copy too for INR
3009  XSchemaFile * oldxsf = &c_schemaFile[SchemaRecord::OLD_SCHEMA_FILE];
3010  oldxsf->noOfPages = xsf->noOfPages;
3011  memcpy(&oldxsf->schemaPage[0], &xsf->schemaPage[0], xsf->schemaPage[0].FileSize);
3012 
3013  if (c_initialStart || c_initialNodeRestart) {
3014  jam();
3015  ndbrequire(c_writeSchemaRecord.inUse == false);
3016  c_writeSchemaRecord.inUse = true;
3017  c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
3018  c_writeSchemaRecord.newFile = true;
3019  c_writeSchemaRecord.firstPage = 0;
3020  c_writeSchemaRecord.noOfPages = xsf->noOfPages;
3021 
3022  c_writeSchemaRecord.m_callback.m_callbackFunction =
3023  safe_cast(&Dbdict::initSchemaFile_conf);
3024 
3025  startWriteSchemaFile(signal);
3026  } else if (c_systemRestart || c_nodeRestart) {
3027  jam();
3028  ndbrequire(c_readSchemaRecord.schemaReadState == ReadSchemaRecord::IDLE);
3029  c_readSchemaRecord.pageId = c_schemaRecord.oldSchemaPage;
3030  c_readSchemaRecord.firstPage = 0;
3031  c_readSchemaRecord.noOfPages = 1;
3032  c_readSchemaRecord.schemaReadState = ReadSchemaRecord::INITIAL_READ_HEAD;
3033  startReadSchemaFile(signal);
3034  } else {
3035  ndbrequire(false);
3036  }//if
3037 }//Dbdict::initSchemaFile()
3038 
3039 void
3040 Dbdict::initSchemaFile_conf(Signal* signal, Uint32 callbackData, Uint32 rv){
3041  jam();
3042  sendNDB_STTORRY(signal);
3043 }
3044 
3045 void
3046 Dbdict::activateIndexes(Signal* signal, Uint32 i)
3047 {
3048  if (i == 0)
3049  D("activateIndexes start");
3050 
3051  Uint32 requestFlags = 0;
3052 
3053  switch (c_restartType) {
3054  case NodeState::ST_SYSTEM_RESTART:
3055  // activate in a distributed trans but do not build yet
3056  if (c_masterNodeId != getOwnNodeId()) {
3057  D("activateIndexes not master");
3058  goto out;
3059  }
3060  requestFlags |= DictSignal::RF_NO_BUILD;
3061  break;
3062  case NodeState::ST_NODE_RESTART:
3063  case NodeState::ST_INITIAL_NODE_RESTART:
3064  // activate on this node in a local trans
3065  requestFlags |= DictSignal::RF_LOCAL_TRANS;
3066  requestFlags |= DictSignal::RF_NO_BUILD;
3067  break;
3068  default:
3069  ndbrequire(false);
3070  break;
3071  }
3072 
3073  TableRecordPtr indexPtr;
3074  indexPtr.i = i;
3075  for (; indexPtr.i < c_tableRecordPool.getSize(); indexPtr.i++)
3076  {
3077  c_tableRecordPool.getPtr(indexPtr);
3078 
3079  if (check_read_obj(indexPtr.i))
3080  {
3081  continue;
3082  }
3083 
3084  if (!indexPtr.p->isIndex())
3085  {
3086  continue;
3087  }
3088 
3089  if ((requestFlags & DictSignal::RF_LOCAL_TRANS) &&
3090  indexPtr.p->indexState != TableRecord::IS_ONLINE)
3091  {
3092  jam();
3093  continue;
3094  }
3095 
3096  // wl3600_todo use simple schema trans when implemented
3097  D("activateIndexes i=" << indexPtr.i);
3098 
3099  TxHandlePtr tx_ptr;
3100  seizeTxHandle(tx_ptr);
3101  ndbrequire(!tx_ptr.isNull());
3102 
3103  tx_ptr.p->m_requestInfo = 0;
3104  tx_ptr.p->m_requestInfo |= requestFlags;
3105  tx_ptr.p->m_userData = indexPtr.i;
3106 
3107  Callback c = {
3108  safe_cast(&Dbdict::activateIndex_fromBeginTrans),
3109  tx_ptr.p->tx_key
3110  };
3111  tx_ptr.p->m_callback = c;
3112  beginSchemaTrans(signal, tx_ptr);
3113  return;
3114  }
3115 
3116  D("activateIndexes done");
3117 #ifdef VM_TRACE
3118  check_consistency();
3119 #endif
3120 out:
3121  signal->theData[0] = reference();
3122  signal->theData[1] = c_restartRecord.m_senderData;
3123  sendSignal(c_restartRecord.returnBlockRef, GSN_DICTSTARTCONF,
3124  signal, 2, JBB);
3125 }
3126 
3127 void
3128 Dbdict::activateIndex_fromBeginTrans(Signal* signal, Uint32 tx_key, Uint32 ret)
3129 {
3130  D("activateIndex_fromBeginTrans" << V(tx_key) << V(ret));
3131 
3132  ndbrequire(ret == 0); //wl3600_todo
3133 
3134  TxHandlePtr tx_ptr;
3135  findTxHandle(tx_ptr, tx_key);
3136  ndbrequire(!tx_ptr.isNull());
3137 
3138  TableRecordPtr indexPtr;
3139  indexPtr.i = tx_ptr.p->m_userData;
3140  c_tableRecordPool.getPtr(indexPtr);
3141 
3142  AlterIndxReq* req = (AlterIndxReq*)signal->getDataPtrSend();
3143 
3144  Uint32 requestInfo = 0;
3145  DictSignal::setRequestType(requestInfo, AlterIndxImplReq::AlterIndexOnline);
3146  DictSignal::addRequestFlagsGlobal(requestInfo, tx_ptr.p->m_requestInfo);
3147 
3148  req->clientRef = reference();
3149  req->clientData = tx_ptr.p->tx_key;
3150  req->transId = tx_ptr.p->m_transId;
3151  req->transKey = tx_ptr.p->m_transKey;
3152  req->requestInfo = requestInfo;
3153  req->indexId = indexPtr.i;
3154  req->indexVersion = indexPtr.p->tableVersion;
3155 
3156  Callback c = {
3157  safe_cast(&Dbdict::activateIndex_fromAlterIndex),
3158  tx_ptr.p->tx_key
3159  };
3160  tx_ptr.p->m_callback = c;
3161 
3162  sendSignal(reference(), GSN_ALTER_INDX_REQ, signal,
3163  AlterIndxReq::SignalLength, JBB);
3164 }
3165 
3166 void
3167 Dbdict::activateIndex_fromAlterIndex(Signal* signal, Uint32 tx_key, Uint32 ret)
3168 {
3169  D("activateIndex_fromAlterIndex" << V(tx_key) << V(ret));
3170 
3171  ndbrequire(ret == 0); // wl3600_todo
3172 
3173  TxHandlePtr tx_ptr;
3174  findTxHandle(tx_ptr, tx_key);
3175  ndbrequire(!tx_ptr.isNull());
3176 
3177  if (ret != 0)
3178  setError(tx_ptr.p->m_error, ret, __LINE__);
3179 
3180  Callback c = {
3181  safe_cast(&Dbdict::activateIndex_fromEndTrans),
3182  tx_ptr.p->tx_key
3183  };
3184  tx_ptr.p->m_callback = c;
3185 
3186  Uint32 flags = 0;
3187  if (hasError(tx_ptr.p->m_error))
3188  flags |= SchemaTransEndReq::SchemaTransAbort;
3189  endSchemaTrans(signal, tx_ptr, flags);
3190 }
3191 
3192 void
3193 Dbdict::activateIndex_fromEndTrans(Signal* signal, Uint32 tx_key, Uint32 ret)
3194 {
3195  D("activateIndex_fromEndTrans" << V(tx_key) << V(ret));
3196 
3197  ndbrequire(ret == 0); //wl3600_todo
3198 
3199  TxHandlePtr tx_ptr;
3200  findTxHandle(tx_ptr, tx_key);
3201  ndbrequire(!tx_ptr.isNull());
3202 
3203  TableRecordPtr indexPtr;
3204  c_tableRecordPool.getPtr(indexPtr, tx_ptr.p->m_userData);
3205 
3206  char indexName[MAX_TAB_NAME_SIZE];
3207  {
3208  DictObjectPtr obj_ptr;
3209  c_obj_pool.getPtr(obj_ptr, indexPtr.p->m_obj_ptr_i);
3210  Rope name(c_rope_pool, obj_ptr.p->m_name);
3211  name.copy(indexName);
3212  }
3213 
3214  ErrorInfo error = tx_ptr.p->m_error;
3215  if (!hasError(error))
3216  {
3217  jam();
3218  infoEvent("DICT: activate index %u done (%s)",
3219  indexPtr.i, indexName);
3220  }
3221  else
3222  {
3223  jam();
3224  warningEvent("DICT: activate index %u error: code=%u line=%u node=%u (%s)",
3225  indexPtr.i,
3226  error.errorCode, error.errorLine, error.errorNodeId,
3227  indexName);
3228  }
3229 
3230  releaseTxHandle(tx_ptr);
3231  activateIndexes(signal, indexPtr.i + 1);
3232 }
3233 
3234 void
3235 Dbdict::rebuildIndexes(Signal* signal, Uint32 i)
3236 {
3237  if (i == 0)
3238  D("rebuildIndexes start");
3239 
3240  TableRecordPtr indexPtr;
3241  indexPtr.i = i;
3242  for (; indexPtr.i < c_tableRecordPool.getSize(); indexPtr.i++) {
3243  c_tableRecordPool.getPtr(indexPtr);
3244  if (check_read_obj(indexPtr.i))
3245  continue;
3246  if (!indexPtr.p->isIndex())
3247  continue;
3248 
3249  // wl3600_todo use simple schema trans when implemented
3250  D("rebuildIndexes i=" << indexPtr.i);
3251 
3252  TxHandlePtr tx_ptr;
3253  seizeTxHandle(tx_ptr);
3254  ndbrequire(!tx_ptr.isNull());
3255 
3256  Uint32 requestInfo = 0;
3257  if (indexPtr.p->m_bits & TableRecord::TR_Logged) {
3258  // only sets index online - the flag propagates to trans and ops
3259  requestInfo |= DictSignal::RF_NO_BUILD;
3260  }
3261  tx_ptr.p->m_requestInfo = requestInfo;
3262  tx_ptr.p->m_userData = indexPtr.i;
3263 
3264  Callback c = {
3265  safe_cast(&Dbdict::rebuildIndex_fromBeginTrans),
3266  tx_ptr.p->tx_key
3267  };
3268  tx_ptr.p->m_callback = c;
3269  beginSchemaTrans(signal, tx_ptr);
3270  return;
3271  }
3272 
3273  D("rebuildIndexes done");
3274  sendNDB_STTORRY(signal);
3275 }
3276 
3277 void
3278 Dbdict::rebuildIndex_fromBeginTrans(Signal* signal, Uint32 tx_key, Uint32 ret)
3279 {
3280  D("rebuildIndex_fromBeginTrans" << V(tx_key) << V(ret));
3281 
3282  ndbrequire(ret == 0); //wl3600_todo
3283 
3284  TxHandlePtr tx_ptr;
3285  findTxHandle(tx_ptr, tx_key);
3286  ndbrequire(!tx_ptr.isNull());
3287 
3288  TableRecordPtr indexPtr;
3289  indexPtr.i = tx_ptr.p->m_userData;
3290  c_tableRecordPool.getPtr(indexPtr);
3291 
3292  BuildIndxReq* req = (BuildIndxReq*)signal->getDataPtrSend();
3293 
3294  Uint32 requestInfo = 0;
3295  DictSignal::setRequestType(requestInfo, BuildIndxReq::MainOp);
3296  DictSignal::addRequestFlagsGlobal(requestInfo, tx_ptr.p->m_requestInfo);
3297 
3298  req->clientRef = reference();
3299  req->clientData = tx_ptr.p->tx_key;
3300  req->transId = tx_ptr.p->m_transId;
3301  req->transKey = tx_ptr.p->m_transKey;
3302  req->requestInfo = requestInfo;
3303  req->buildId = 0;
3304  req->buildKey = 0;
3305  req->tableId = indexPtr.p->primaryTableId;
3306  req->indexId = indexPtr.i;
3307  req->indexType = indexPtr.p->tableType;
3308  req->parallelism = 16;
3309 
3310  Callback c = {
3311  safe_cast(&Dbdict::rebuildIndex_fromBuildIndex),
3312  tx_ptr.p->tx_key
3313  };
3314  tx_ptr.p->m_callback = c;
3315 
3316  sendSignal(reference(), GSN_BUILDINDXREQ, signal,
3317  BuildIndxReq::SignalLength, JBB);
3318 }
3319 
3320 void
3321 Dbdict::rebuildIndex_fromBuildIndex(Signal* signal, Uint32 tx_key, Uint32 ret)
3322 {
3323  D("rebuildIndex_fromBuildIndex" << V(tx_key) << V(ret));
3324 
3325  ndbrequire(ret == 0); //wl3600_todo
3326 
3327  TxHandlePtr tx_ptr;
3328  findTxHandle(tx_ptr, tx_key);
3329  ndbrequire(!tx_ptr.isNull());
3330 
3331  if (ret != 0)
3332  setError(tx_ptr.p->m_error, ret, __LINE__);
3333 
3334  Callback c = {
3335  safe_cast(&Dbdict::rebuildIndex_fromEndTrans),
3336  tx_ptr.p->tx_key
3337  };
3338  tx_ptr.p->m_callback = c;
3339 
3340  Uint32 flags = 0;
3341  if (hasError(tx_ptr.p->m_error))
3342  flags |= SchemaTransEndReq::SchemaTransAbort;
3343  endSchemaTrans(signal, tx_ptr, flags);
3344 }
3345 
3346 void
3347 Dbdict::rebuildIndex_fromEndTrans(Signal* signal, Uint32 tx_key, Uint32 ret)
3348 {
3349  D("rebuildIndex_fromEndTrans" << V(tx_key) << V(ret));
3350 
3351  ndbrequire(ret == 0); //wl3600_todo
3352 
3353  TxHandlePtr tx_ptr;
3354  findTxHandle(tx_ptr, tx_key);
3355  ndbrequire(!tx_ptr.isNull());
3356 
3357  TableRecordPtr indexPtr;
3358  c_tableRecordPool.getPtr(indexPtr, tx_ptr.p->m_userData);
3359 
3360  const char* actionName;
3361  {
3362  Uint32 requestInfo = tx_ptr.p->m_requestInfo;
3363  bool noBuild = (requestInfo & DictSignal::RF_NO_BUILD);
3364  actionName = !noBuild ? "rebuild" : "online";
3365  }
3366 
3367  char indexName[MAX_TAB_NAME_SIZE];
3368  {
3369  DictObjectPtr obj_ptr;
3370  c_obj_pool.getPtr(obj_ptr, indexPtr.p->m_obj_ptr_i);
3371  Rope name(c_rope_pool, obj_ptr.p->m_name);
3372  name.copy(indexName);
3373  }
3374 
3375  ErrorInfo error = tx_ptr.p->m_error;
3376  if (!hasError(error)) {
3377  jam();
3378  infoEvent(
3379  "DICT: %s index %u done (%s)",
3380  actionName, indexPtr.i, indexName);
3381  } else {
3382  jam();
3383  warningEvent(
3384  "DICT: %s index %u error: code=%u line=%u node=%u (%s)",
3385  actionName,
3386  indexPtr.i, error.errorCode, error.errorLine, error.errorNodeId,
3387  indexName);
3388  }
3389 
3390  Uint32 i = tx_ptr.p->m_userData;
3391  releaseTxHandle(tx_ptr);
3392 
3393  rebuildIndexes(signal, i + 1);
3394 }
3395 
3396 /* **************************************************************** */
3397 /* ---------------------------------------------------------------- */
3398 /* MODULE: SYSTEM RESTART MODULE ------------------------- */
3399 /* ---------------------------------------------------------------- */
3400 /* */
3401 /* This module contains code specific for system restart */
3402 /* ---------------------------------------------------------------- */
3403 /* **************************************************************** */
3404 
3405 /* ---------------------------------------------------------------- */
3406 // DIH asks DICT to read in table data from disk during system
3407 // restart. DIH also asks DICT to send information about which
3408 // tables that should be started as part of this system restart.
3409 // DICT will also activate the tables in TC as part of this process.
3410 /* ---------------------------------------------------------------- */
3411 void Dbdict::execDICTSTARTREQ(Signal* signal)
3412 {
3413  jamEntry();
3414  c_restartRecord.gciToRestart = signal->theData[0];
3415  c_restartRecord.returnBlockRef = signal->theData[1];
3416  c_restartRecord.m_senderData = signal->theData[2];
3417  if (signal->getLength() < DictStartReq::SignalLength)
3418  {
3419  jam();
3420  c_restartRecord.m_senderData = 0;
3421  }
3422  if (c_nodeRestart || c_initialNodeRestart) {
3423  jam();
3424 
3425  CRASH_INSERTION(6000);
3426 
3427  BlockReference dictRef = calcDictBlockRef(c_masterNodeId);
3428  signal->theData[0] = getOwnNodeId();
3429  sendSignal(dictRef, GSN_GET_SCHEMA_INFOREQ, signal, 1, JBB);
3430  return;
3431  }
3432  ndbrequire(c_systemRestart);
3433  ndbrequire(c_masterNodeId == getOwnNodeId());
3434 
3435  c_schemaRecord.m_callback.m_callbackData = 0;
3436  c_schemaRecord.m_callback.m_callbackFunction =
3437  safe_cast(&Dbdict::masterRestart_checkSchemaStatusComplete);
3438 
3443  {
3444  XSchemaFile * oldxsf = &c_schemaFile[SchemaRecord::OLD_SCHEMA_FILE];
3445  checkPendingSchemaTrans(oldxsf);
3446  XSchemaFile * newxsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
3447  newxsf->noOfPages = oldxsf->noOfPages;
3448  memcpy(&newxsf->schemaPage[0],
3449  &oldxsf->schemaPage[0],
3450  oldxsf->schemaPage[0].FileSize);
3451  }
3452 
3453  Callback cb =
3454  { safe_cast(&Dbdict::masterRestart_checkSchemaStatusComplete), 0 };
3455  startRestoreSchema(signal, cb);
3456 }//execDICTSTARTREQ()
3457 
3458 void
3459 Dbdict::masterRestart_checkSchemaStatusComplete(Signal* signal,
3460  Uint32 callbackData,
3461  Uint32 returnCode)
3462 {
3463  XSchemaFile * oldxsf = &c_schemaFile[SchemaRecord::OLD_SCHEMA_FILE];
3464  ndbrequire(oldxsf->noOfPages != 0);
3465 
3466  LinearSectionPtr ptr[3];
3467  ptr[0].p = (Uint32*)&oldxsf->schemaPage[0];
3468  ptr[0].sz = oldxsf->noOfPages * NDB_SF_PAGE_SIZE_IN_WORDS;
3469 
3470  c_sendSchemaRecord.m_SCHEMAINFO_Counter = c_aliveNodes;
3471  NodeReceiverGroup rg(DBDICT, c_aliveNodes);
3472 
3473  rg.m_nodes.clear(getOwnNodeId());
3474  Callback c = { 0, 0 };
3475  sendFragmentedSignal(rg,
3476  GSN_SCHEMA_INFO,
3477  signal,
3478  1, //SchemaInfo::SignalLength,
3479  JBB,
3480  ptr,
3481  1,
3482  c);
3483 
3484  XSchemaFile * newxsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
3485  newxsf->noOfPages = oldxsf->noOfPages;
3486  memcpy(&newxsf->schemaPage[0], &oldxsf->schemaPage[0],
3487  oldxsf->noOfPages * NDB_SF_PAGE_SIZE);
3488 
3489  signal->theData[0] = getOwnNodeId();
3490  sendSignal(reference(), GSN_SCHEMA_INFOCONF, signal, 1, JBB);
3491 }
3492 
3493 void
3494 Dbdict::execGET_SCHEMA_INFOREQ(Signal* signal){
3495 
3496  const Uint32 ref = signal->getSendersBlockRef();
3497  //const Uint32 senderData = signal->theData[0];
3498 
3499  ndbrequire(c_sendSchemaRecord.inUse == false);
3500  c_sendSchemaRecord.inUse = true;
3501 
3502  LinearSectionPtr ptr[3];
3503 
3504  XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
3505  ndbrequire(xsf->noOfPages != 0);
3506 
3507  ptr[0].p = (Uint32*)&xsf->schemaPage[0];
3508  ptr[0].sz = xsf->noOfPages * NDB_SF_PAGE_SIZE_IN_WORDS;
3509 
3510  Callback c = { safe_cast(&Dbdict::sendSchemaComplete), 0 };
3511  sendFragmentedSignal(ref,
3512  GSN_SCHEMA_INFO,
3513  signal,
3514  1, //GetSchemaInfoConf::SignalLength,
3515  JBB,
3516  ptr,
3517  1,
3518  c);
3519 }//Dbdict::execGET_SCHEMA_INFOREQ()
3520 
3521 void
3522 Dbdict::sendSchemaComplete(Signal * signal,
3523  Uint32 callbackData,
3524  Uint32 returnCode){
3525  ndbrequire(c_sendSchemaRecord.inUse == true);
3526  c_sendSchemaRecord.inUse = false;
3527 
3528 }
3529 
3530 
3531 /* ---------------------------------------------------------------- */
3532 // We receive the schema info from master as part of all restarts
3533 // except the initial start where no tables exists.
3534 /* ---------------------------------------------------------------- */
3535 void Dbdict::execSCHEMA_INFO(Signal* signal)
3536 {
3537  jamEntry();
3538  if(!assembleFragments(signal)){
3539  jam();
3540  return;
3541  }
3542 
3543  if(getNodeState().getNodeRestartInProgress()){
3544  CRASH_INSERTION(6001);
3545  }
3546 
3547  {
3551  XSchemaFile * oldxsf = &c_schemaFile[SchemaRecord::OLD_SCHEMA_FILE];
3552  XSchemaFile * newxsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
3553  memcpy(&newxsf->schemaPage[0],
3554  &oldxsf->schemaPage[0],
3555  oldxsf->schemaPage[0].FileSize);
3556  }
3557 
3558  SectionHandle handle(this, signal);
3559  SegmentedSectionPtr schemaDataPtr;
3560  handle.getSection(schemaDataPtr, 0);
3561 
3562  XSchemaFile * xsf = &c_schemaFile[SchemaRecord::OLD_SCHEMA_FILE];
3563  ndbrequire(schemaDataPtr.sz % NDB_SF_PAGE_SIZE_IN_WORDS == 0);
3564  xsf->noOfPages = schemaDataPtr.sz / NDB_SF_PAGE_SIZE_IN_WORDS;
3565  copy((Uint32*)&xsf->schemaPage[0], schemaDataPtr);
3566  releaseSections(handle);
3567 
3568  SchemaFile * sf0 = &xsf->schemaPage[0];
3569  if (sf0->NdbVersion < NDB_SF_VERSION_5_0_6) {
3570  bool ok = convertSchemaFileTo_5_0_6(xsf);
3571  ndbrequire(ok);
3572  }
3573 
3574  if (sf0->NdbVersion < NDB_MAKE_VERSION(6,4,0))
3575  {
3576  jam();
3577  bool ok = convertSchemaFileTo_6_4(xsf);
3578  ndbrequire(ok);
3579  }
3580 
3581  validateChecksum(xsf);
3582 
3583  XSchemaFile * ownxsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
3584  checkPendingSchemaTrans(ownxsf);
3585  resizeSchemaFile(xsf, ownxsf->noOfPages);
3586 
3587  ndbrequire(signal->getSendersBlockRef() != reference());
3588 
3589  /* ---------------------------------------------------------------- */
3590  // Synchronise our view on data with other nodes in the cluster.
3591  // This is an important part of restart handling where we will handle
3592  // cases where the table have been added but only partially, where
3593  // tables have been deleted but not completed the deletion yet and
3594  // other scenarios needing synchronisation.
3595  /* ---------------------------------------------------------------- */
3596  Callback cb =
3597  { safe_cast(&Dbdict::restart_checkSchemaStatusComplete), 0 };
3598  startRestoreSchema(signal, cb);
3599 }//execSCHEMA_INFO()
3600 
3601 void
3602 Dbdict::restart_checkSchemaStatusComplete(Signal * signal,
3603  Uint32 callbackData,
3604  Uint32 returnCode)
3605 {
3606  jam();
3607 
3608  if(c_systemRestart)
3609  {
3610  jam();
3611  signal->theData[0] = getOwnNodeId();
3612  sendSignal(calcDictBlockRef(c_masterNodeId), GSN_SCHEMA_INFOCONF,
3613  signal, 1, JBB);
3614  return;
3615  }
3616 
3617  ndbrequire(c_restartRecord.m_op_cnt == 0);
3618  ndbrequire(c_nodeRestart || c_initialNodeRestart);
3619  activateIndexes(signal, 0);
3620  return;
3621 }
3622 
3623 void Dbdict::execSCHEMA_INFOCONF(Signal* signal)
3624 {
3625  jamEntry();
3626  ndbrequire(signal->getNoOfSections() == 0);
3627 
3628 /* ---------------------------------------------------------------- */
3629 // This signal is received in the master as part of system restart
3630 // from all nodes (including the master) after they have synchronised
3631 // their data with the master node's schema information.
3632 /* ---------------------------------------------------------------- */
3633  const Uint32 nodeId = signal->theData[0];
3634  c_sendSchemaRecord.m_SCHEMAINFO_Counter.clearWaitingFor(nodeId);
3635 
3636  if (!c_sendSchemaRecord.m_SCHEMAINFO_Counter.done()){
3637  jam();
3638  return;
3639  }//if
3640  activateIndexes(signal, 0);
3641 }//execSCHEMA_INFOCONF()
3642 
3643 static bool
3644 checkSchemaStatus(Uint32 tableType, Uint32 pass)
3645 {
3646  switch(tableType){
3647  case DictTabInfo::UndefTableType:
3648  return true;
3649  case DictTabInfo::HashIndexTrigger:
3650  case DictTabInfo::SubscriptionTrigger:
3651  case DictTabInfo::ReadOnlyConstraint:
3652  case DictTabInfo::IndexTrigger:
3653  return false;
3655  return pass == 0 || pass == 11 || pass == 12;
3657  return pass == 1 || pass == 10 || pass == 13;
3658  case DictTabInfo::Datafile:
3659  case DictTabInfo::Undofile:
3660  return pass == 2 || pass == 9 || pass == 14;
3661  case DictTabInfo::HashMap:
3662  return pass == 3 || pass == 8 || pass == 15;
3663  case DictTabInfo::SystemTable:
3664  case DictTabInfo::UserTable:
3665  return /* pass == 3 || pass == 7 || */ pass == 16;
3666  case DictTabInfo::UniqueHashIndex:
3667  case DictTabInfo::HashIndex:
3668  case DictTabInfo::UniqueOrderedIndex:
3669  case DictTabInfo::OrderedIndex:
3670  return /* pass == 4 || pass == 6 || */ pass == 17;
3671  }
3672 
3673  return false;
3674 }
3675 
3676 static const Uint32 CREATE_OLD_PASS = 5;
3677 static const Uint32 DROP_OLD_PASS = 11;
3678 static const Uint32 CREATE_NEW_PASS = 17;
3679 static const Uint32 LAST_PASS = 17;
3680 
3681 NdbOut&
3682 operator<<(NdbOut& out, const SchemaFile::TableEntry entry)
3683 {
3684  out << "[";
3685  out << " state: " << entry.m_tableState;
3686  out << " version: " << hex << entry.m_tableVersion << dec;
3687  out << " type: " << entry.m_tableType;
3688  out << " words: " << entry.m_info_words;
3689  out << " gcp: " << entry.m_gcp;
3690  out << " trans: " << entry.m_transId;
3691  out << " ]";
3692  return out;
3693 }
3694 
3695 void Dbdict::initRestartRecord(Uint32 startpass, Uint32 lastpass,
3696  const char * sb, const char * eb)
3697 {
3698  c_restartRecord.gciToRestart = 0;
3699  c_restartRecord.activeTable = 0;
3700  c_restartRecord.m_op_cnt = 0;
3701  if (startpass == 0 && lastpass == 0)
3702  {
3703  jam();
3704  c_restartRecord.m_pass = 0;
3705  c_restartRecord.m_end_pass = LAST_PASS;
3706  c_restartRecord.m_start_banner = "Starting to restore schema";
3707  c_restartRecord.m_end_banner = "Restore of schema complete";
3708  }
3709  else
3710  {
3711  jam();
3712  c_restartRecord.m_pass = startpass;
3713  c_restartRecord.m_end_pass = lastpass;
3714  c_restartRecord.m_start_banner = sb;
3715  c_restartRecord.m_end_banner = eb;
3716  }
3717 }//Dbdict::initRestartRecord()
3718 
3742 void Dbdict::checkSchemaStatus(Signal* signal)
3743 {
3744  // masterxsf == schema file of master (i.e what's currently in cluster)
3745  // ownxsf = schema file read from disk
3746  XSchemaFile * masterxsf = &c_schemaFile[SchemaRecord::OLD_SCHEMA_FILE];
3747  XSchemaFile * ownxsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
3748 
3749  ndbrequire(masterxsf->noOfPages == ownxsf->noOfPages);
3750  const Uint32 noOfEntries = masterxsf->noOfPages * NDB_SF_PAGE_ENTRIES;
3751 
3752  for (; c_restartRecord.activeTable < noOfEntries;
3753  c_restartRecord.activeTable++)
3754  {
3755  jam();
3756 
3757  Uint32 tableId = c_restartRecord.activeTable;
3758  SchemaFile::TableEntry *masterEntry = getTableEntry(masterxsf, tableId);
3759  SchemaFile::TableEntry *ownEntry = getTableEntry(ownxsf, tableId);
3760  SchemaFile::EntryState masterState =
3761  (SchemaFile::EntryState)masterEntry->m_tableState;
3762  SchemaFile::EntryState ownState =
3763  (SchemaFile::EntryState)ownEntry->m_tableState;
3764 
3765  if (c_restartRecord.activeTable >= c_tableRecordPool.getSize())
3766  {
3767  jam();
3768  ndbrequire(masterState == SchemaFile::SF_UNUSED);
3769  ndbrequire(ownState == SchemaFile::SF_UNUSED);
3770  continue;
3771  }//if
3772 
3773  D("checkSchemaStatus" << V(*ownEntry) << V(*masterEntry));
3774 
3775 //#define PRINT_SCHEMA_RESTART
3776 #ifdef PRINT_SCHEMA_RESTART
3777  printf("checkSchemaStatus: pass: %d table: %d",
3778  c_restartRecord.m_pass, tableId);
3779  ndbout << "old: " << *ownEntry << " new: " << *masterEntry << endl;
3780 #endif
3781 
3782  if (c_restartRecord.m_pass <= CREATE_OLD_PASS)
3783  {
3784  if (!::checkSchemaStatus(ownEntry->m_tableType, c_restartRecord.m_pass))
3785  continue;
3786 
3787 
3788  if (ownState == SchemaFile::SF_UNUSED)
3789  continue;
3790 
3791  restartCreateObj(signal, tableId, ownEntry, true);
3792  return;
3793  }
3794 
3795  if (c_restartRecord.m_pass <= DROP_OLD_PASS)
3796  {
3797  if (!::checkSchemaStatus(ownEntry->m_tableType, c_restartRecord.m_pass))
3798  continue;
3799 
3800  if (ownState != SchemaFile::SF_IN_USE)
3801  continue;
3802 
3803  if (* ownEntry == * masterEntry)
3804  continue;
3805 
3806  restartDropObj(signal, tableId, ownEntry);
3807  return;
3808  }
3809 
3810  if (c_restartRecord.m_pass <= CREATE_NEW_PASS)
3811  {
3812  if (!::checkSchemaStatus(masterEntry->m_tableType, c_restartRecord.m_pass))
3813  continue;
3814 
3815  if (masterState != SchemaFile::SF_IN_USE)
3816  {
3817  if (ownEntry->m_tableType != DictTabInfo::SchemaTransaction)
3818  {
3819  jam();
3820  ownEntry->init();
3821  }
3822  continue;
3823  }
3824 
3829  if (DictTabInfo::isIndex(masterEntry->m_tableType) ||
3830  DictTabInfo::isTable(masterEntry->m_tableType))
3831  {
3832  bool file = * ownEntry == *masterEntry &&
3833  (!DictTabInfo::isIndex(masterEntry->m_tableType) || c_systemRestart);
3834 
3835  restartCreateObj(signal, tableId, masterEntry, file);
3836  return;
3837  }
3838 
3839  if (* ownEntry == *masterEntry)
3840  continue;
3841 
3842  restartCreateObj(signal, tableId, masterEntry, false);
3843  return;
3844  }
3845  }
3846 
3847  if (c_restartRecord.m_op_cnt == 0)
3848  {
3849  jam();
3850  restartNextPass(signal);
3851  return;
3852  }
3853  else
3854  {
3855  jam();
3856 
3857  c_restartRecord.m_op_cnt = 0;
3858 
3859  TxHandlePtr tx_ptr;
3860  c_txHandleHash.getPtr(tx_ptr, c_restartRecord.m_tx_ptr_i);
3861 
3862  Callback c = {
3863  safe_cast(&Dbdict::restartEndPass_fromEndTrans),
3864  tx_ptr.p->tx_key
3865  };
3866  tx_ptr.p->m_callback = c;
3867 
3868  Uint32 flags = 0;
3869  endSchemaTrans(signal, tx_ptr, flags);
3870  return;
3871  }
3872 }//checkSchemaStatus()
3873 
3874 void
3875 Dbdict::checkPendingSchemaTrans(XSchemaFile* xsf)
3876 {
3877  for (Uint32 i = 0; i < xsf->noOfPages * NDB_SF_PAGE_ENTRIES; i++)
3878  {
3879  SchemaFile::TableEntry * transEntry = getTableEntry(xsf, i);
3880 
3881  if (transEntry->m_tableType == DictTabInfo::SchemaTransaction &&
3882  transEntry->m_transId != 0)
3883  {
3884  jam();
3885 
3886  bool commit = false;
3887  switch(transEntry->m_tableState){
3888  case SchemaFile::SF_STARTED:
3889  case SchemaFile::SF_PREPARE:
3890  case SchemaFile::SF_ABORT:
3891  jam();
3892  ndbout_c("Found pending trans (%u) - aborting", i);
3893  break;
3894  case SchemaFile::SF_COMMIT:
3895  case SchemaFile::SF_COMPLETE:
3896  jam();
3897  commit = true;
3898  ndbout_c("Found pending trans (%u) - committing", i);
3899  break;
3900  }
3901 
3902  const Uint32 transId = transEntry->m_transId;
3903  for (Uint32 j = 0; j<xsf->noOfPages * NDB_SF_PAGE_ENTRIES; j++)
3904  {
3905  SchemaFile::TableEntry * tmp = getTableEntry(xsf, j);
3906  if (tmp->m_transId == transId &&
3907  tmp->m_tableType != DictTabInfo::SchemaTransaction)
3908  {
3909  jam();
3910  tmp->m_transId = 0;
3911  switch(tmp->m_tableState){
3912  case SchemaFile::SF_CREATE:
3913  if (commit)
3914  {
3915  jam();
3916  tmp->m_tableState = SchemaFile::SF_IN_USE;
3917  ndbout_c("commit create %u", j);
3918  }
3919  else
3920  {
3921  jam();
3922  tmp->m_tableState = SchemaFile::SF_UNUSED;
3923  ndbout_c("abort create %u", j);
3924  }
3925  break;
3926  case SchemaFile::SF_ALTER:
3927  tmp->m_tableState = SchemaFile::SF_IN_USE;
3928  if (commit)
3929  {
3930  jam();
3931  ndbout_c("commit alter %u", j);
3932  }
3933  else
3934  {
3935  jam();
3936  ndbout_c("abort alter %u", j);
3937  tmp->m_tableVersion =
3938  alter_obj_dec_schema_version(tmp->m_tableVersion);
3939  }
3940  break;
3941  case SchemaFile::SF_DROP:
3942  if (commit)
3943  {
3944  jam();
3945  tmp->m_tableState = SchemaFile::SF_UNUSED;
3946  ndbout_c("commit drop %u", j);
3947  }
3948  else
3949  {
3950  jam();
3951  tmp->m_tableState = SchemaFile::SF_IN_USE;
3952  ndbout_c("abort drop %u", j);
3953  }
3954  break;
3955  }
3956  }
3957  }
3958 
3959  transEntry->m_tableType = DictTabInfo::UndefTableType;
3960  transEntry->m_tableState = SchemaFile::SF_UNUSED;
3961  transEntry->m_transId = 0;
3962  }
3963  }
3964 }
3965 
3966 void
3967 Dbdict::startRestoreSchema(Signal* signal, Callback cb)
3968 {
3969  jam();
3970 
3971  initRestartRecord();
3972  c_schemaRecord.m_callback = cb;
3973 
3974  TxHandlePtr tx_ptr;
3975  seizeTxHandle(tx_ptr);
3976  ndbrequire(!tx_ptr.isNull());
3977 
3978  c_restartRecord.m_tx_ptr_i = tx_ptr.i;
3979  tx_ptr.p->m_requestInfo = DictSignal::RF_LOCAL_TRANS;
3980  tx_ptr.p->m_userData = 0;
3981 
3982  Callback c = {
3983  safe_cast(&Dbdict::restart_fromBeginTrans),
3984  tx_ptr.p->tx_key
3985  };
3986  tx_ptr.p->m_callback = c;
3987  beginSchemaTrans(signal, tx_ptr);
3988 
3989  if (c_restartRecord.m_start_banner)
3990  {
3991  jam();
3992  infoEvent("%s", c_restartRecord.m_start_banner);
3993  }
3994 }
3995 
3996 void
3997 Dbdict::restart_fromBeginTrans(Signal* signal, Uint32 tx_key, Uint32 ret)
3998 {
3999  ndbrequire(ret == 0);
4000 
4001  TxHandlePtr tx_ptr;
4002  findTxHandle(tx_ptr, tx_key);
4003  ndbrequire(!tx_ptr.isNull());
4004 
4005  checkSchemaStatus(signal);
4006 }
4007 
4008 void
4009 Dbdict::restart_nextOp(Signal* signal, bool commit)
4010 {
4011  c_restartRecord.m_op_cnt++;
4012 
4014  c_opSectionBufferPool.getNoOfFree() < MAX_WORDS_META_FILE)
4015  {
4016  jam();
4021  c_restartRecord.m_op_cnt = ZRESTART_OPS_PER_TRANS;
4022  }
4023 
4024  if (commit || c_restartRecord.m_op_cnt >= ZRESTART_OPS_PER_TRANS)
4025  {
4026  jam();
4027  c_restartRecord.m_op_cnt = 0;
4028 
4029  Ptr<TxHandle> tx_ptr;
4030  c_txHandleHash.getPtr(tx_ptr, c_restartRecord.m_tx_ptr_i);
4031 
4032  Callback c = {
4033  safe_cast(&Dbdict::restart_fromEndTrans),
4034  tx_ptr.p->tx_key
4035  };
4036  tx_ptr.p->m_callback = c;
4037 
4038  Uint32 flags = 0;
4039  endSchemaTrans(signal, tx_ptr, flags);
4040  }
4041  else
4042  {
4043  jam();
4044  c_restartRecord.activeTable++;
4045  checkSchemaStatus(signal);
4046  }
4047 }
4048 
4049 void
4050 Dbdict::restart_fromEndTrans(Signal* signal, Uint32 tx_key, Uint32 ret)
4051 {
4052  TxHandlePtr tx_ptr;
4053  findTxHandle(tx_ptr, tx_key);
4054  ndbrequire(!tx_ptr.isNull());
4055 
4056  if (unlikely(hasError(tx_ptr.p->m_error)))
4057  {
4058  jam();
4059  /*
4060  Fatal error while restoring shchema during restart,
4061  dump debug info and crash
4062  */
4063  ndbout << "error: " << tx_ptr.p->m_error << endl;
4064 
4065  char msg[128];
4066  BaseString::snprintf(msg, sizeof(msg),
4067  "Failed to restore schema during restart, error %u."
4068  ,tx_ptr.p->m_error.errorCode);
4069  progError(__LINE__, NDBD_EXIT_RESTORE_SCHEMA, msg);
4070  }
4071  ndbrequire(ret == 0); //wl3600_todo
4072 
4073  releaseTxHandle(tx_ptr);
4074 
4075  ndbrequire(c_restartRecord.m_op_cnt == 0);
4076  c_restartRecord.activeTable++;
4077 
4078  seizeTxHandle(tx_ptr);
4079  ndbrequire(!tx_ptr.isNull());
4080  c_restartRecord.m_tx_ptr_i = tx_ptr.i;
4081  tx_ptr.p->m_requestInfo = DictSignal::RF_LOCAL_TRANS;
4082  tx_ptr.p->m_userData = 0;
4083 
4084  Callback c = {
4085  safe_cast(&Dbdict::restart_fromBeginTrans),
4086  tx_ptr.p->tx_key
4087  };
4088  tx_ptr.p->m_callback = c;
4089  beginSchemaTrans(signal, tx_ptr);
4090 }
4091 
4092 void
4093 Dbdict::restartEndPass_fromEndTrans(Signal* signal, Uint32 tx_key, Uint32 ret)
4094 {
4095  TxHandlePtr tx_ptr;
4096  findTxHandle(tx_ptr, tx_key);
4097  ndbrequire(!tx_ptr.isNull());
4098 
4099  if (unlikely(hasError(tx_ptr.p->m_error)))
4100  {
4101  jam();
4102  /*
4103  Fatal error while restoring shchema during restart,
4104  dump debug info and crash
4105  */
4106  ndbout << "error: " << tx_ptr.p->m_error << endl;
4107 
4108  char msg[128];
4109  BaseString::snprintf(msg, sizeof(msg),
4110  "Failed to restore schema during restart, error %u."
4111  ,tx_ptr.p->m_error.errorCode);
4112  progError(__LINE__, NDBD_EXIT_RESTORE_SCHEMA, msg);
4113  }
4114  ndbrequire(ret == 0); //wl3600_todo
4115 
4116  releaseTxHandle(tx_ptr);
4117  c_restartRecord.m_tx_ptr_i = RNIL;
4118 
4119  restartNextPass(signal);
4120 }
4121 
4122 void
4123 Dbdict::restartNextPass(Signal* signal)
4124 {
4125  c_restartRecord.m_pass++;
4126  c_restartRecord.activeTable= 0;
4127 
4128  if (c_restartRecord.m_pass <= c_restartRecord.m_end_pass)
4129  {
4130  TxHandlePtr tx_ptr;
4131  if (c_restartRecord.m_tx_ptr_i == RNIL)
4132  {
4133  jam();
4134  seizeTxHandle(tx_ptr);
4135  ndbrequire(!tx_ptr.isNull());
4136  c_restartRecord.m_tx_ptr_i = tx_ptr.i;
4137  tx_ptr.p->m_requestInfo = DictSignal::RF_LOCAL_TRANS;
4138  tx_ptr.p->m_userData = 0;
4139 
4140  Callback c = {
4141  safe_cast(&Dbdict::restart_fromBeginTrans),
4142  tx_ptr.p->tx_key
4143  };
4144  tx_ptr.p->m_callback = c;
4145  beginSchemaTrans(signal, tx_ptr);
4146  return;
4147  }
4148  else
4149  {
4150  jam();
4151  c_txHandleHash.getPtr(tx_ptr, c_restartRecord.m_tx_ptr_i);
4152  restart_fromBeginTrans(signal, tx_ptr.p->tx_key, 0);
4153  return;
4154  }
4155  }
4156  else if (c_restartRecord.m_tx_ptr_i != RNIL)
4157  {
4161  jam();
4162 
4163  c_restartRecord.m_pass--;
4164  c_restartRecord.m_op_cnt = 0;
4165 
4166  Ptr<TxHandle> tx_ptr;
4167  c_txHandleHash.getPtr(tx_ptr, c_restartRecord.m_tx_ptr_i);
4168 
4169  Callback c = {
4170  safe_cast(&Dbdict::restartEndPass_fromEndTrans),
4171  tx_ptr.p->tx_key
4172  };
4173  tx_ptr.p->m_callback = c;
4174 
4175  Uint32 flags = 0;
4176  endSchemaTrans(signal, tx_ptr, flags);
4177  return;
4178  }
4179  else
4180  {
4181  jam();
4182 
4183  ndbrequire(c_restartRecord.m_op_cnt == 0);
4184 
4188  XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
4189  ndbrequire(c_writeSchemaRecord.inUse == false);
4190  c_writeSchemaRecord.inUse = true;
4191  c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
4192  c_writeSchemaRecord.newFile = false;
4193  c_writeSchemaRecord.firstPage = 0;
4194  c_writeSchemaRecord.noOfPages = xsf->noOfPages;
4195  c_writeSchemaRecord.m_callback.m_callbackData = 0;
4196  c_writeSchemaRecord.m_callback.m_callbackFunction =
4197  safe_cast(&Dbdict::restart_fromWriteSchemaFile);
4198 
4199  for(Uint32 i = 0; i<xsf->noOfPages; i++)
4200  computeChecksum(xsf, i);
4201 
4202  startWriteSchemaFile(signal);
4203  }
4204 }
4205 
4206 void
4207 Dbdict::restart_fromWriteSchemaFile(Signal* signal,
4208  Uint32 senderData,
4209  Uint32 retCode)
4210 {
4211  if (c_restartRecord.m_end_banner)
4212  {
4213  jam();
4214  infoEvent("%s", c_restartRecord.m_end_banner);
4215  }
4216 
4217  execute(signal, c_schemaRecord.m_callback, retCode);
4218 }
4219 
4220 void
4221 Dbdict::execGET_TABINFO_CONF(Signal* signal)
4222 {
4223  jamEntry();
4224 
4225  if(!assembleFragments(signal)){
4226  jam();
4227  return;
4228  }
4229 
4230  GetTabInfoConf * const conf = (GetTabInfoConf*)signal->getDataPtr();
4231 
4232  switch(conf->tableType){
4233  case DictTabInfo::UndefTableType:
4234  case DictTabInfo::HashIndexTrigger:
4235  case DictTabInfo::SubscriptionTrigger:
4236  case DictTabInfo::ReadOnlyConstraint:
4237  case DictTabInfo::IndexTrigger:
4238  ndbrequire(false);
4239  case DictTabInfo::SystemTable:
4240  case DictTabInfo::UserTable:
4241  case DictTabInfo::UniqueHashIndex:
4242  case DictTabInfo::HashIndex:
4243  case DictTabInfo::UniqueOrderedIndex:
4244  case DictTabInfo::OrderedIndex:
4245  break;
4248  case DictTabInfo::Datafile:
4249  case DictTabInfo::Undofile:
4250  if(refToBlock(conf->senderRef) == TSMAN
4251  && (refToNode(conf->senderRef) == 0
4252  || refToNode(conf->senderRef) == getOwnNodeId()))
4253  {
4254  jam();
4255  FilePtr fg_ptr;
4256  ndbrequire(c_file_hash.find(fg_ptr, conf->tableId));
4257  const Uint32 free_extents= conf->freeExtents;
4258  const Uint32 id= conf->tableId;
4259  const Uint32 type= conf->tableType;
4260  const Uint32 data= conf->senderData;
4261  signal->theData[0]= ZPACK_TABLE_INTO_PAGES;
4262  signal->theData[1]= id;
4263  signal->theData[2]= type;
4264  signal->theData[3]= data;
4265  signal->theData[4]= free_extents;
4266  sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);
4267  }
4268  else if(refToBlock(conf->senderRef) == LGMAN
4269  && (refToNode(conf->senderRef) == 0
4270  || refToNode(conf->senderRef) == getOwnNodeId()))
4271  {
4272  jam();
4273  FilegroupPtr fg_ptr;
4274  ndbrequire(c_filegroup_hash.find(fg_ptr, conf->tableId));
4275  const Uint32 free_hi= conf->freeWordsHi;
4276  const Uint32 free_lo= conf->freeWordsLo;
4277  const Uint32 id= conf->tableId;
4278  const Uint32 type= conf->tableType;
4279  const Uint32 data= conf->senderData;
4280  signal->theData[0]= ZPACK_TABLE_INTO_PAGES;
4281  signal->theData[1]= id;
4282  signal->theData[2]= type;
4283  signal->theData[3]= data;
4284  signal->theData[4]= free_hi;
4285  signal->theData[5]= free_lo;
4286  sendSignal(reference(), GSN_CONTINUEB, signal, 6, JBB);
4287  }
4288  else
4289  {
4290  jam();
4291  break;
4292  }
4293  return;
4294  }
4295 
4296  restartCreateObj_getTabInfoConf(signal);
4297 }
4298 
4302 void
4303 Dbdict::restartCreateObj(Signal* signal,
4304  Uint32 tableId,
4305  const SchemaFile::TableEntry * new_entry,
4306  bool file){
4307  jam();
4308 
4309 
4310 #ifdef PRINT_SCHEMA_RESTART
4311  ndbout_c("restartCreateObj table: %u file: %u", tableId, Uint32(file));
4312 #endif
4313 
4314  c_restartRecord.m_entry = *new_entry;
4315  if(file)
4316  {
4317  c_readTableRecord.no_of_words = new_entry->m_info_words;
4318  c_readTableRecord.pageId = 0;
4319  c_readTableRecord.m_callback.m_callbackData = tableId;
4320  c_readTableRecord.m_callback.m_callbackFunction =
4321  safe_cast(&Dbdict::restartCreateObj_readConf);
4322 
4323  ndbout_c("restartCreateObj(%u) file: %u", tableId, file);
4324  startReadTableFile(signal, tableId);
4325  }
4326  else
4327  {
4331  GetTabInfoReq * const req = (GetTabInfoReq *)&signal->theData[0];
4332  req->senderRef = reference();
4333  req->senderData = tableId;
4334  req->requestType = GetTabInfoReq::RequestById |
4335  GetTabInfoReq::LongSignalConf;
4336  req->tableId = tableId;
4337  sendSignal(calcDictBlockRef(c_masterNodeId), GSN_GET_TABINFOREQ, signal,
4338  GetTabInfoReq::SignalLength, JBB);
4339  }
4340 }
4341 
4342 void
4343 Dbdict::restartCreateObj_getTabInfoConf(Signal* signal)
4344 {
4345  jam();
4346 
4347  SectionHandle handle(this, signal);
4348  SegmentedSectionPtr objInfoPtr;
4349  handle.getSection(objInfoPtr, GetTabInfoConf::DICT_TAB_INFO);
4350  handle.clear();
4351 
4352  restartCreateObj_parse(signal, objInfoPtr, false);
4353 }
4354 
4355 void
4356 Dbdict::restartCreateObj_readConf(Signal* signal,
4357  Uint32 callbackData,
4358  Uint32 returnCode)
4359 {
4360  jam();
4361  ndbrequire(returnCode == 0);
4362 
4363  PageRecordPtr pageRecPtr;
4364  c_pageRecordArray.getPtr(pageRecPtr, c_readTableRecord.pageId);
4365 
4366  Uint32 sz = c_readTableRecord.no_of_words;
4367 
4368  Ptr<SectionSegment> ptr;
4369  ndbrequire(import(ptr, pageRecPtr.p->word+ZPAGE_HEADER_SIZE, sz));
4370  SegmentedSectionPtr tmp(sz, ptr.i, ptr.p);
4371  restartCreateObj_parse(signal, tmp, true);
4372 }
4373 
4374 void
4375 Dbdict::restartCreateObj_parse(Signal* signal,
4376  SegmentedSectionPtr ptr,
4377  bool file)
4378 {
4379  jam();
4380  Ptr<SchemaOp> op_ptr;
4381 
4382  switch(c_restartRecord.m_entry.m_tableType){
4383  case DictTabInfo::SystemTable:
4384  case DictTabInfo::UserTable:
4385  case DictTabInfo::UniqueHashIndex:
4386  case DictTabInfo::HashIndex:
4387  case DictTabInfo::UniqueOrderedIndex:
4388  case DictTabInfo::OrderedIndex:
4389  {
4390  Ptr<CreateTableRec> opRecPtr;
4391  seizeSchemaOp(op_ptr, opRecPtr);
4392  break;
4393  }
4394  case DictTabInfo::Undofile:
4395  case DictTabInfo::Datafile:
4396  {
4397  Ptr<CreateFileRec> opRecPtr;
4398  seizeSchemaOp(op_ptr, opRecPtr);
4399  break;
4400  }
4403  {
4404  Ptr<CreateFilegroupRec> opRecPtr;
4405  seizeSchemaOp(op_ptr, opRecPtr);
4406  break;
4407  }
4408  case DictTabInfo::HashMap:
4409  {
4410  Ptr<CreateHashMapRec> opRecPtr;
4411  seizeSchemaOp(op_ptr, opRecPtr);
4412  break;
4413  }
4414  }
4415 
4416  Ptr<TxHandle> tx_ptr;
4417  c_txHandleHash.getPtr(tx_ptr, c_restartRecord.m_tx_ptr_i);
4418 
4419  Ptr<SchemaTrans> trans_ptr;
4420  findSchemaTrans(trans_ptr, tx_ptr.p->m_transKey);
4421  addSchemaOp(trans_ptr, op_ptr);
4422  op_ptr.p->m_restart = file ? 1 : 2;
4423  op_ptr.p->m_state = SchemaOp::OS_PARSE_MASTER;
4424 
4425  SectionHandle handle(this, ptr.i);
4426  ErrorInfo error;
4427  const OpInfo& info = getOpInfo(op_ptr);
4428  (this->*(info.m_parse))(signal, false, op_ptr, handle, error);
4429  releaseSections(handle);
4430  if (unlikely(hasError(error)))
4431  {
4432  jam();
4433  /*
4434  Fatal error while restoring shchema during restart,
4435  dump debug info and crash
4436  */
4437  ndbout << "error: " << error << endl;
4438 
4439  char msg[128];
4440  BaseString::snprintf(msg, sizeof(msg),
4441  "Failed to recreate object %u during restart,"
4442  " error %u."
4443  ,c_restartRecord.activeTable
4444  ,error.errorCode);
4445  progError(__LINE__, NDBD_EXIT_RESTORE_SCHEMA, msg);
4446  }
4447  ndbrequire(!hasError(error));
4448 
4449  restart_nextOp(signal);
4450 }
4451 
4455 void
4456 Dbdict::restartDropObj(Signal* signal,
4457  Uint32 tableId,
4458  const SchemaFile::TableEntry * entry)
4459 {
4460  jam();
4461  c_restartRecord.m_entry = *entry;
4462 
4463  jam();
4464  Ptr<SchemaOp> op_ptr;
4465 
4466  switch(c_restartRecord.m_entry.m_tableType){
4467  case DictTabInfo::SystemTable:
4468  case DictTabInfo::UserTable:
4469  case DictTabInfo::UniqueHashIndex:
4470  case DictTabInfo::HashIndex:
4471  case DictTabInfo::UniqueOrderedIndex:
4472  case DictTabInfo::OrderedIndex:
4473  Ptr<DropTableRec> opRecPtr;
4474  seizeSchemaOp(op_ptr, opRecPtr);
4475  ndbrequire(false);
4476  break;
4477  case DictTabInfo::Undofile:
4478  case DictTabInfo::Datafile:
4479  {
4480  Ptr<DropFileRec> opRecPtr;
4481  seizeSchemaOp(op_ptr, opRecPtr);
4482  opRecPtr.p->m_request.file_id = tableId;
4483  opRecPtr.p->m_request.file_version = entry->m_tableVersion;
4484  break;
4485  }
4488  {
4489  Ptr<DropFilegroupRec> opRecPtr;
4490  seizeSchemaOp(op_ptr, opRecPtr);
4491  opRecPtr.p->m_request.filegroup_id = tableId;
4492  opRecPtr.p->m_request.filegroup_version = entry->m_tableVersion;
4493  break;
4494  }
4495  }
4496 
4497  ndbout_c("restartDropObj(%u)", tableId);
4498 
4499  Ptr<TxHandle> tx_ptr;
4500  c_txHandleHash.getPtr(tx_ptr, c_restartRecord.m_tx_ptr_i);
4501 
4502  Ptr<SchemaTrans> trans_ptr;
4503  findSchemaTrans(trans_ptr, tx_ptr.p->m_transKey);
4504  addSchemaOp(trans_ptr, op_ptr);
4505  op_ptr.p->m_restart = 1; //
4506  op_ptr.p->m_state = SchemaOp::OS_PARSE_MASTER;
4507 
4508  SectionHandle handle(this);
4509  ErrorInfo error;
4510  const OpInfo& info = getOpInfo(op_ptr);
4511  (this->*(info.m_parse))(signal, false, op_ptr, handle, error);
4512  releaseSections(handle);
4513  if (unlikely(hasError(error)))
4514  {
4515  jam();
4516  /*
4517  Fatal error while restoring shchema during restart,
4518  dump debug info and crash
4519  */
4520  ndbout << "error: " << error << endl;
4521 
4522  char msg[128];
4523  BaseString::snprintf(msg, sizeof(msg),
4524  "Failed to drop object %u during restart, error %u"
4525  ,c_restartRecord.activeTable
4526  ,error.errorCode);
4527  progError(__LINE__, NDBD_EXIT_RESTORE_SCHEMA, msg);
4528  }
4529  ndbrequire(!hasError(error));
4530 
4531  restart_nextOp(signal);
4532 }
4533 
4534 /* **************************************************************** */
4535 /* ---------------------------------------------------------------- */
4536 /* MODULE: NODE FAILURE HANDLING ------------------------- */
4537 /* ---------------------------------------------------------------- */
4538 /* */
4539 /* This module contains the code that is used when nodes */
4540 /* (kernel/api) fails. */
4541 /* ---------------------------------------------------------------- */
4542 /* **************************************************************** */
4543 
4544 void Dbdict::handleApiFailureCallback(Signal* signal,
4545  Uint32 failedNodeId,
4546  Uint32 ignoredRc)
4547 {
4548  jamEntry();
4549 
4550  signal->theData[0] = failedNodeId;
4551  signal->theData[1] = reference();
4552  sendSignal(QMGR_REF, GSN_API_FAILCONF, signal, 2, JBB);
4553 }
4554 
4555 /* ---------------------------------------------------------------- */
4556 // We receive a report of an API that failed.
4557 /* ---------------------------------------------------------------- */
4558 void Dbdict::execAPI_FAILREQ(Signal* signal)
4559 {
4560  jamEntry();
4561  Uint32 failedApiNode = signal->theData[0];
4562  BlockReference retRef = signal->theData[1];
4563 
4564  ndbrequire(retRef == QMGR_REF); // As callback hard-codes QMGR_REF
4565 #if 0
4566  Uint32 userNode = refToNode(c_connRecord.userBlockRef);
4567  if (userNode == failedApiNode) {
4568  jam();
4569  c_connRecord.userBlockRef = (Uint32)-1;
4570  }//if
4571 #endif
4572 
4573  // sends API_FAILCONF when done
4574  handleApiFail(signal, failedApiNode);
4575 }//execAPI_FAILREQ()
4576 
4577 void Dbdict::handleNdbdFailureCallback(Signal* signal,
4578  Uint32 failedNodeId,
4579  Uint32 ignoredRc)
4580 {
4581  jamEntry();
4582 
4583  /* Node failure handling is complete */
4584  NFCompleteRep * const nfCompRep = (NFCompleteRep *)&signal->theData[0];
4585  nfCompRep->blockNo = DBDICT;
4586  nfCompRep->nodeId = getOwnNodeId();
4587  nfCompRep->failedNodeId = failedNodeId;
4588  sendSignal(DBDIH_REF, GSN_NF_COMPLETEREP, signal,
4589  NFCompleteRep::SignalLength, JBB);
4590 }
4591 
4592 /* ---------------------------------------------------------------- */
4593 // We receive a report of one or more node failures of kernel nodes.
4594 /* ---------------------------------------------------------------- */
4595 void Dbdict::execNODE_FAILREP(Signal* signal)
4596 {
4597  jamEntry();
4598  NodeFailRep nodeFailRep = *(NodeFailRep *)&signal->theData[0];
4599  NodeFailRep * nodeFail = &nodeFailRep;
4600  NodeRecordPtr ownNodePtr;
4601 
4602  c_nodes.getPtr(ownNodePtr, getOwnNodeId());
4603  c_failureNr = nodeFail->failNo;
4604  const Uint32 numberOfFailedNodes = nodeFail->noOfNodes;
4605  const bool masterFailed = (c_masterNodeId != nodeFail->masterNodeId);
4606  c_masterNodeId = nodeFail->masterNodeId;
4607 
4608  c_noNodesFailed += numberOfFailedNodes;
4609  Uint32 theFailedNodes[NdbNodeBitmask::Size];
4610  memcpy(theFailedNodes, nodeFail->theNodes, sizeof(theFailedNodes));
4611  c_counterMgr.execNODE_FAILREP(signal);
4612 
4613  NdbNodeBitmask failedNodes;
4614  failedNodes.assign(NdbNodeBitmask::Size, theFailedNodes);
4615  c_aliveNodes.bitANDC(failedNodes);
4616  if (masterFailed && c_masterNodeId == getOwnNodeId())
4617  {
4618  /*
4619  Master node has failed, we need to take over
4620  any pending transaction(s) and decide if to
4621  rollforward or rollback.
4622  */
4623  jam();
4624  ownNodePtr.p->nodeState = NodeRecord::NDB_MASTER_TAKEOVER;
4625  ownNodePtr.p->nodeFailRep = nodeFailRep;
4626  infoEvent("Node %u taking over as DICT master", c_masterNodeId);
4627  handle_master_takeover(signal);
4628  return;
4629  }
4630 
4631  send_nf_complete_rep(signal, &nodeFailRep);
4632  return;
4633 }//execNODE_FAILREP()
4634 
4635 void Dbdict::send_nf_complete_rep(Signal* signal, const NodeFailRep* nodeFail)
4636 {
4637  jam();
4638  Uint32 theFailedNodes[NdbNodeBitmask::Size];
4639  memcpy(theFailedNodes, nodeFail->theNodes, sizeof(theFailedNodes));
4640  NdbNodeBitmask tmp;
4641  tmp.assign(NdbNodeBitmask::Size, theFailedNodes);
4642 
4643  NodeRecordPtr ownNodePtr;
4644  c_nodes.getPtr(ownNodePtr, getOwnNodeId());
4645  ownNodePtr.p->nodeState = NodeRecord::NDB_NODE_ALIVE; // reset take-over
4646 
4647  for(unsigned i = 1; i < MAX_NDB_NODES; i++) {
4648  jam();
4649  if(tmp.get(i)) {
4650  jam();
4651  NodeRecordPtr nodePtr;
4652  c_nodes.getPtr(nodePtr, i);
4653 #ifdef VM_TRACE
4654  ndbout_c("Sending NF_COMPLETEREP for node %u", i);
4655 #endif
4656  nodePtr.p->nodeState = NodeRecord::NDB_NODE_DEAD;
4657 
4658  Callback cb = {safe_cast(&Dbdict::handleNdbdFailureCallback),
4659  i};
4660 
4661  simBlockNodeFailure(signal, nodePtr.i, cb);
4662  }//if
4663  }//for
4664 
4665  /*
4666  * NODE_FAILREP guarantees that no "in flight" signal from
4667  * a dead node is accepted, and also that the job buffer contains
4668  * no such (un-executed) signals. Therefore no DICT_UNLOCK_ORD
4669  * from a dead node (leading to master crash) is possible after
4670  * this clean-up removes the lock record.
4671  */
4672  removeStaleDictLocks(signal, theFailedNodes);
4673 
4674  c_sub_startstop_lock.bitANDC(tmp);
4675 }//send_nf_complete_rep
4676 
4677 void Dbdict::handle_master_takeover(Signal* signal)
4678 {
4679  /*
4680  This is the new master, handle take-over of
4681  pending schema transactions.
4682  Ask all slave nodes about state of any pending
4683  transactions
4684  */
4685  jam();
4686  NodeRecordPtr masterNodePtr;
4687  c_nodes.getPtr(masterNodePtr, c_masterNodeId);
4688 
4689  masterNodePtr.p->m_nodes = c_aliveNodes;
4690  NodeReceiverGroup rg(DBDICT, masterNodePtr.p->m_nodes);
4691  {
4692  SafeCounter sc(c_counterMgr, masterNodePtr.p->m_counter);
4693  bool ok = sc.init<DictTakeoverRef>(rg, c_masterNodeId);
4694  ndbrequire(ok);
4695  }
4696  DictTakeoverReq* req = (DictTakeoverReq*)signal->getDataPtrSend();
4697  req->senderRef = reference();
4698  sendSignal(rg, GSN_DICT_TAKEOVER_REQ, signal,
4699  DictTakeoverReq::SignalLength, JBB);
4700 }
4701 
4702 
4703 /* **************************************************************** */
4704 /* ---------------------------------------------------------------- */
4705 /* MODULE: NODE START HANDLING --------------------------- */
4706 /* ---------------------------------------------------------------- */
4707 /* */
4708 /* This module contains the code that is used when kernel nodes */
4709 /* starts. */
4710 /* ---------------------------------------------------------------- */
4711 /* **************************************************************** */
4712 
4713 /* ---------------------------------------------------------------- */
4714 // Include a starting node in list of nodes to be part of adding
4715 // and dropping tables.
4716 /* ---------------------------------------------------------------- */
4717 void Dbdict::execINCL_NODEREQ(Signal* signal)
4718 {
4719  jamEntry();
4720  NodeRecordPtr nodePtr;
4721  BlockReference retRef = signal->theData[0];
4722  nodePtr.i = signal->theData[1];
4723 
4724  ndbrequire(c_noNodesFailed > 0);
4725  c_noNodesFailed--;
4726 
4727  c_nodes.getPtr(nodePtr);
4728  ndbrequire(nodePtr.p->nodeState == NodeRecord::NDB_NODE_DEAD);
4729  nodePtr.p->nodeState = NodeRecord::NDB_NODE_ALIVE;
4730  signal->theData[0] = nodePtr.i;
4731  signal->theData[1] = reference();
4732  sendSignal(retRef, GSN_INCL_NODECONF, signal, 2, JBB);
4733 
4734  c_aliveNodes.set(nodePtr.i);
4735 }//execINCL_NODEREQ()
4736 
4737 /* **************************************************************** */
4738 /* ---------------------------------------------------------------- */
4739 /* MODULE: ADD TABLE HANDLING ---------------------------- */
4740 /* ---------------------------------------------------------------- */
4741 /* */
4742 /* This module contains the code that is used when adding a table. */
4743 /* ---------------------------------------------------------------- */
4744 /* **************************************************************** */
4745 
4746 inline
4747 void Dbdict::printTables()
4748 {
4750  bool moreTables = c_obj_hash.first(iter);
4751  printf("OBJECTS IN DICT:\n");
4752  char name[PATH_MAX];
4753  while (moreTables) {
4754  Ptr<DictObject> tablePtr = iter.curr;
4755  ConstRope r(c_rope_pool, tablePtr.p->m_name);
4756  r.copy(name);
4757  printf("%s ", name);
4758  moreTables = c_obj_hash.next(iter);
4759  }
4760  printf("\n");
4761 }
4762 
4763 #define tabRequire(cond, error) \
4764  if (!(cond)) { \
4765  jam(); \
4766  parseP->errorCode = error; parseP->errorLine = __LINE__; \
4767  parseP->errorKey = it.getKey(); \
4768  return; \
4769  }//if
4770 
4771 // handleAddTableFailure(signal, __LINE__, allocatedTable);
4772 
4774 Dbdict::get_object(const char * name, Uint32 len, Uint32 hash){
4775  Ptr<DictObject> old_ptr;
4776  if (get_object(old_ptr, name, len, hash))
4777  {
4778  return old_ptr.p;
4779  }
4780  return 0;
4781 }
4782 
4783 bool
4784 Dbdict::get_object(DictObjectPtr& obj_ptr, const char* name, Uint32 len, Uint32 hash)
4785 {
4786  DictObject key;
4787  key.m_key.m_name_ptr = name;
4788  key.m_key.m_name_len = len;
4789  key.m_key.m_pool = &c_rope_pool;
4790  key.m_name.m_hash = hash;
4791  return c_obj_hash.find(obj_ptr, key);
4792 }
4793 
4794 void
4795 Dbdict::release_object(Uint32 obj_ptr_i, DictObject* obj_ptr_p){
4796  Rope name(c_rope_pool, obj_ptr_p->m_name);
4797  name.erase();
4798 
4799  Ptr<DictObject> ptr = { obj_ptr_p, obj_ptr_i };
4800  c_obj_hash.release(ptr);
4801 }
4802 
4803 void
4804 Dbdict::increase_ref_count(Uint32 obj_ptr_i)
4805 {
4806  DictObject* ptr = c_obj_pool.getPtr(obj_ptr_i);
4807  ptr->m_ref_count++;
4808 }
4809 
4810 void
4811 Dbdict::decrease_ref_count(Uint32 obj_ptr_i)
4812 {
4813  DictObject* ptr = c_obj_pool.getPtr(obj_ptr_i);
4814  ndbrequire(ptr->m_ref_count);
4815  ptr->m_ref_count--;
4816 }
4817 
4818 void Dbdict::handleTabInfoInit(Signal * signal, SchemaTransPtr & trans_ptr,
4820  ParseDictTabInfoRecord * parseP,
4821  bool checkExist)
4822 {
4823 /* ---------------------------------------------------------------- */
4824 // We always start by handling table name since this must be the first
4825 // item in the list. Through the table name we can derive if it is a
4826 // correct name, a new name or an already existing table.
4827 /* ---------------------------------------------------------------- */
4828 
4829  it.first();
4830 
4832  c_tableDesc.init();
4833  status = SimpleProperties::unpack(it, &c_tableDesc,
4834  DictTabInfo::TableMapping,
4835  DictTabInfo::TableMappingSize,
4836  true, true);
4837 
4838  if(status != SimpleProperties::Break){
4839  parseP->errorCode = CreateTableRef::InvalidFormat;
4840  parseP->status = status;
4841  parseP->errorKey = it.getKey();
4842  parseP->errorLine = __LINE__;
4843  return;
4844  }
4845 
4846  if(parseP->requestType == DictTabInfo::AlterTableFromAPI)
4847  {
4848  ndbrequire(!checkExist);
4849  }
4850  if(!checkExist)
4851  {
4852  ndbrequire(parseP->requestType == DictTabInfo::AlterTableFromAPI);
4853  }
4854 
4855  /* ---------------------------------------------------------------- */
4856  // Verify that table name is an allowed table name.
4857  // TODO
4858  /* ---------------------------------------------------------------- */
4859  const Uint32 tableNameLength = Uint32(strlen(c_tableDesc.TableName) + 1);
4860  const Uint32 name_hash = Rope::hash(c_tableDesc.TableName, tableNameLength);
4861 
4862  if(checkExist){
4863  jam();
4864  tabRequire(get_object(c_tableDesc.TableName, tableNameLength) == 0,
4865  CreateTableRef::TableAlreadyExist);
4866  }
4867 
4868  if (DictTabInfo::isIndex(c_tableDesc.TableType))
4869  {
4870  jam();
4871  parseP->requestType = DictTabInfo::AddTableFromDict;
4872  }
4873 
4874  TableRecordPtr tablePtr;
4875  switch (parseP->requestType) {
4876  case DictTabInfo::CreateTableFromAPI: {
4877  jam();
4878  }
4879  case DictTabInfo::AlterTableFromAPI:{
4880  jam();
4881  tablePtr.i = getFreeTableRecord(c_tableDesc.PrimaryTableId);
4882  /* ---------------------------------------------------------------- */
4883  // Check if no free tables existed.
4884  /* ---------------------------------------------------------------- */
4885  tabRequire(tablePtr.i != RNIL, CreateTableRef::NoMoreTableRecords);
4886 
4887  c_tableRecordPool.getPtr(tablePtr);
4888  break;
4889  }
4890  case DictTabInfo::AddTableFromDict:
4891  case DictTabInfo::ReadTableFromDiskSR:
4892  case DictTabInfo::GetTabInfoConf:
4893  {
4894 /* ---------------------------------------------------------------- */
4895 // Get table id and check that table doesn't already exist
4896 /* ---------------------------------------------------------------- */
4897  tablePtr.i = c_tableDesc.TableId;
4898 
4899  if (parseP->requestType == DictTabInfo::ReadTableFromDiskSR) {
4900  ndbrequire(tablePtr.i == c_restartRecord.activeTable);
4901  }//if
4902  if (parseP->requestType == DictTabInfo::GetTabInfoConf) {
4903  ndbrequire(tablePtr.i == c_restartRecord.activeTable);
4904  }//if
4905 
4906  c_tableRecordPool.getPtr(tablePtr);
4907 
4908  //Uint32 oldTableVersion = tablePtr.p->tableVersion;
4909  initialiseTableRecord(tablePtr);
4910 
4911 /* ---------------------------------------------------------------- */
4912 // Set table version
4913 /* ---------------------------------------------------------------- */
4914  Uint32 tableVersion = c_tableDesc.TableVersion;
4915  tablePtr.p->tableVersion = tableVersion;
4916 
4917  break;
4918  }
4919  default:
4920  ndbrequire(false);
4921  break;
4922  }//switch
4923 
4924  {
4925  Rope name(c_rope_pool, tablePtr.p->tableName);
4926  tabRequire(name.assign(c_tableDesc.TableName, tableNameLength, name_hash),
4927  CreateTableRef::OutOfStringBuffer);
4928  }
4929 
4930  Ptr<DictObject> obj_ptr;
4931  if (parseP->requestType != DictTabInfo::AlterTableFromAPI) {
4932  jam();
4933  ndbrequire(c_obj_hash.seize(obj_ptr));
4934  new (obj_ptr.p) DictObject;
4935  obj_ptr.p->m_id = tablePtr.i;
4936  obj_ptr.p->m_type = c_tableDesc.TableType;
4937  obj_ptr.p->m_name = tablePtr.p->tableName;
4938  obj_ptr.p->m_ref_count = 0;
4939  c_obj_hash.add(obj_ptr);
4940  tablePtr.p->m_obj_ptr_i = obj_ptr.i;
4941 
4942  if (g_trace)
4943  {
4944  g_eventLogger->info("Dbdict: create name=%s,id=%u,obj_ptr_i=%d",
4945  c_tableDesc.TableName,
4946  tablePtr.i, tablePtr.p->m_obj_ptr_i);
4947  }
4948  send_event(signal, trans_ptr,
4949  NDB_LE_CreateSchemaObject,
4950  tablePtr.i,
4951  tablePtr.p->tableVersion,
4952  c_tableDesc.TableType);
4953  }
4954  parseP->tablePtr = tablePtr;
4955 
4956  // Disallow logging of a temporary table.
4957  tabRequire(!(c_tableDesc.TableTemporaryFlag && c_tableDesc.TableLoggedFlag),
4958  CreateTableRef::NoLoggingTemporaryTable);
4959 
4960  tablePtr.p->noOfAttributes = c_tableDesc.NoOfAttributes;
4961  tablePtr.p->m_bits |=
4962  (c_tableDesc.TableLoggedFlag ? TableRecord::TR_Logged : 0);
4963  tablePtr.p->m_bits |=
4964  (c_tableDesc.RowChecksumFlag ? TableRecord::TR_RowChecksum : 0);
4965  tablePtr.p->m_bits |=
4966  (c_tableDesc.RowGCIFlag ? TableRecord::TR_RowGCI : 0);
4967 #if DOES_NOT_WORK_CURRENTLY
4968  tablePtr.p->m_bits |=
4969  (c_tableDesc.TableTemporaryFlag ? TableRecord::TR_Temporary : 0);
4970 #endif
4971  tablePtr.p->m_bits |=
4972  (c_tableDesc.ForceVarPartFlag ? TableRecord::TR_ForceVarPart : 0);
4973  tablePtr.p->minLoadFactor = c_tableDesc.MinLoadFactor;
4974  tablePtr.p->maxLoadFactor = c_tableDesc.MaxLoadFactor;
4975  tablePtr.p->fragmentType = (DictTabInfo::FragmentType)c_tableDesc.FragmentType;
4976  tablePtr.p->tableType = (DictTabInfo::TableType)c_tableDesc.TableType;
4977  tablePtr.p->kValue = c_tableDesc.TableKValue;
4978  tablePtr.p->fragmentCount = c_tableDesc.FragmentCount;
4979  tablePtr.p->m_tablespace_id = c_tableDesc.TablespaceId;
4980  tablePtr.p->maxRowsLow = c_tableDesc.MaxRowsLow;
4981  tablePtr.p->maxRowsHigh = c_tableDesc.MaxRowsHigh;
4982  tablePtr.p->minRowsLow = c_tableDesc.MinRowsLow;
4983  tablePtr.p->minRowsHigh = c_tableDesc.MinRowsHigh;
4984  tablePtr.p->defaultNoPartFlag = c_tableDesc.DefaultNoPartFlag;
4985  tablePtr.p->linearHashFlag = c_tableDesc.LinearHashFlag;
4986  tablePtr.p->singleUserMode = c_tableDesc.SingleUserMode;
4987  tablePtr.p->hashMapObjectId = c_tableDesc.HashMapObjectId;
4988  tablePtr.p->hashMapVersion = c_tableDesc.HashMapVersion;
4989  tablePtr.p->storageType = c_tableDesc.TableStorageType;
4990  tablePtr.p->m_extra_row_gci_bits = c_tableDesc.ExtraRowGCIBits;
4991  tablePtr.p->m_extra_row_author_bits = c_tableDesc.ExtraRowAuthorBits;
4992 
4993  tabRequire(tablePtr.p->noOfAttributes <= MAX_ATTRIBUTES_IN_TABLE,
4994  CreateTableRef::NoMoreAttributeRecords); // bad error code!
4995 
4996  if (tablePtr.p->fragmentType == DictTabInfo::HashMapPartition &&
4997  tablePtr.p->hashMapObjectId == RNIL)
4998  {
4999  Uint32 fragments = tablePtr.p->fragmentCount;
5000  if (fragments == 0)
5001  {
5002  jam();
5003  tablePtr.p->fragmentCount = fragments = get_default_fragments(signal);
5004  }
5005 
5006  char buf[MAX_TAB_NAME_SIZE+1];
5007  BaseString::snprintf(buf, sizeof(buf), "DEFAULT-HASHMAP-%u-%u",
5008  NDB_DEFAULT_HASHMAP_BUCKTETS,
5009  fragments);
5010  DictObject* dictObj = get_object(buf);
5011  if (dictObj && dictObj->m_type == DictTabInfo::HashMap)
5012  {
5013  jam();
5014  HashMapPtr hm_ptr;
5015  ndbrequire(c_hash_map_hash.find(hm_ptr, dictObj->m_id));
5016  tablePtr.p->hashMapObjectId = hm_ptr.p->m_object_id;
5017  tablePtr.p->hashMapVersion = hm_ptr.p->m_object_version;
5018  }
5019  }
5020 
5021  if (tablePtr.p->fragmentType == DictTabInfo::HashMapPartition)
5022  {
5023  jam();
5024  HashMapPtr hm_ptr;
5025  tabRequire(c_hash_map_hash.find(hm_ptr, tablePtr.p->hashMapObjectId),
5026  CreateTableRef::InvalidHashMap);
5027 
5028  tabRequire(hm_ptr.p->m_object_version == tablePtr.p->hashMapVersion,
5029  CreateTableRef::InvalidHashMap);
5030 
5031  Ptr<Hash2FragmentMap> mapptr;
5032  g_hash_map.getPtr(mapptr, hm_ptr.p->m_map_ptr_i);
5033 
5034  if (tablePtr.p->fragmentCount == 0)
5035  {
5036  jam();
5037  tablePtr.p->fragmentCount = mapptr.p->m_fragments;
5038  }
5039  else
5040  {
5041  tabRequire(mapptr.p->m_fragments == tablePtr.p->fragmentCount,
5042  CreateTableRef::InvalidHashMap);
5043  }
5044  }
5045 
5046  {
5047  Rope frm(c_rope_pool, tablePtr.p->frmData);
5048  tabRequire(frm.assign(c_tableDesc.FrmData, c_tableDesc.FrmLen),
5049  CreateTableRef::OutOfStringBuffer);
5050  Rope range(c_rope_pool, tablePtr.p->rangeData);
5051  tabRequire(range.assign((const char*)c_tableDesc.RangeListData,
5052  c_tableDesc.RangeListDataLen),
5053  CreateTableRef::OutOfStringBuffer);
5054  Rope fd(c_rope_pool, tablePtr.p->ngData);
5055  tabRequire(fd.assign((const char*)c_tableDesc.FragmentData,
5056  c_tableDesc.FragmentDataLen),
5057  CreateTableRef::OutOfStringBuffer);
5058  }
5059 
5060  c_fragDataLen = c_tableDesc.FragmentDataLen;
5061  memcpy(c_fragData, c_tableDesc.FragmentData,
5062  c_tableDesc.FragmentDataLen);
5063 
5064  if(c_tableDesc.PrimaryTableId != RNIL)
5065  {
5066  jam();
5067  tablePtr.p->primaryTableId = c_tableDesc.PrimaryTableId;
5068  tablePtr.p->indexState = (TableRecord::IndexState)c_tableDesc.IndexState;
5069 
5071  {
5072  jam();
5073  tablePtr.p->triggerId = RNIL;
5074  }
5075  else
5076  {
5077  jam();
5078  tablePtr.p->triggerId = c_tableDesc.CustomTriggerId;
5079 
5080  if (c_tableDesc.InsertTriggerId != RNIL ||
5081  c_tableDesc.UpdateTriggerId != RNIL ||
5082  c_tableDesc.DeleteTriggerId != RNIL)
5083  {
5084  jam();
5088  ndbrequire(tablePtr.p->isUniqueIndex());
5089  ndbrequire(c_tableDesc.CustomTriggerId == RNIL);
5090  ndbrequire(c_tableDesc.InsertTriggerId != RNIL);
5091  ndbrequire(c_tableDesc.UpdateTriggerId != RNIL);
5092  ndbrequire(c_tableDesc.DeleteTriggerId != RNIL);
5093  ndbout_c("table: %u UPGRADE saving (%u/%u/%u)",
5094  tablePtr.i,
5095  c_tableDesc.InsertTriggerId,
5096  c_tableDesc.UpdateTriggerId,
5097  c_tableDesc.DeleteTriggerId);
5098  infoEvent("table: %u UPGRADE saving (%u/%u/%u)",
5099  tablePtr.i,
5100  c_tableDesc.InsertTriggerId,
5101  c_tableDesc.UpdateTriggerId,
5102  c_tableDesc.DeleteTriggerId);
5103  tablePtr.p->triggerId = c_tableDesc.InsertTriggerId;
5104  tablePtr.p->m_upgrade_trigger_handling.m_upgrade = true;
5105  tablePtr.p->m_upgrade_trigger_handling.insertTriggerId = c_tableDesc.InsertTriggerId;
5106  tablePtr.p->m_upgrade_trigger_handling.updateTriggerId = c_tableDesc.UpdateTriggerId;
5107  tablePtr.p->m_upgrade_trigger_handling.deleteTriggerId = c_tableDesc.DeleteTriggerId;
5108 
5109  upgrade_seizeTrigger(tablePtr,
5110  c_tableDesc.InsertTriggerId,
5111  c_tableDesc.UpdateTriggerId,
5112  c_tableDesc.DeleteTriggerId);
5113  }
5114  }
5115  }
5116  else
5117  {
5118  jam();
5119  tablePtr.p->primaryTableId = RNIL;
5120  tablePtr.p->indexState = TableRecord::IS_UNDEFINED;
5121  tablePtr.p->triggerId = RNIL;
5122  }
5123  tablePtr.p->buildTriggerId = RNIL;
5124 
5125  handleTabInfo(it, parseP, c_tableDesc);
5126 
5127  if(parseP->errorCode != 0)
5128  {
5132  releaseTableObject(tablePtr.i, checkExist);
5133  parseP->tablePtr.setNull();
5134  return;
5135  }
5136 
5137  if (checkExist && tablePtr.p->m_tablespace_id != RNIL)
5138  {
5142  FilegroupPtr ptr;
5143  ndbrequire(c_filegroup_hash.find(ptr, tablePtr.p->m_tablespace_id));
5144  increase_ref_count(ptr.p->m_obj_ptr_i);
5145  }
5146 }//handleTabInfoInit()
5147 
5148 void
5150  Uint32 insertTriggerId,
5151  Uint32 updateTriggerId,
5152  Uint32 deleteTriggerId)
5153 {
5158  const Uint32 size = c_triggerRecordPool.getSize();
5159  ndbrequire(updateTriggerId == RNIL || updateTriggerId < size);
5160  ndbrequire(deleteTriggerId == RNIL || deleteTriggerId < size);
5161 
5162  TriggerRecordPtr triggerPtr;
5163  if (updateTriggerId != RNIL)
5164  {
5165  jam();
5166  c_triggerRecordPool.getPtr(triggerPtr, updateTriggerId);
5167  if (triggerPtr.p->triggerState == TriggerRecord::TS_NOT_DEFINED)
5168  {
5169  jam();
5170  initialiseTriggerRecord(triggerPtr);
5171  triggerPtr.p->triggerState = TriggerRecord::TS_FAKE_UPGRADE;
5172  triggerPtr.p->triggerId = triggerPtr.i;
5173  triggerPtr.p->tableId = tabPtr.p->primaryTableId;
5174  triggerPtr.p->indexId = tabPtr.i;
5175  TriggerInfo::packTriggerInfo(triggerPtr.p->triggerInfo,
5176  g_hashIndexTriggerTmpl[0].triggerInfo);
5177 
5178  char buf[256];
5179  BaseString::snprintf(buf, sizeof(buf),
5180  "UPG_UPD_NDB$INDEX_%u_UI", tabPtr.i);
5181  {
5182  Rope name(c_rope_pool, triggerPtr.p->triggerName);
5183  name.assign(buf);
5184  }
5185 
5186  Ptr<DictObject> obj_ptr;
5187  bool ok = c_obj_hash.seize(obj_ptr);
5188  ndbrequire(ok);
5189  new (obj_ptr.p) DictObject();
5190 
5191  obj_ptr.p->m_name = triggerPtr.p->triggerName;
5192  c_obj_hash.add(obj_ptr);
5193  obj_ptr.p->m_ref_count = 0;
5194 
5195  triggerPtr.p->m_obj_ptr_i = obj_ptr.i;
5196  obj_ptr.p->m_id = triggerPtr.p->triggerId;
5197  obj_ptr.p->m_type =TriggerInfo::getTriggerType(triggerPtr.p->triggerInfo);
5198  }
5199  }
5200 
5201  if (deleteTriggerId != RNIL)
5202  {
5203  jam();
5204  c_triggerRecordPool.getPtr(triggerPtr, deleteTriggerId);
5205  if (triggerPtr.p->triggerState == TriggerRecord::TS_NOT_DEFINED)
5206  {
5207  jam();
5208  initialiseTriggerRecord(triggerPtr);
5209  triggerPtr.p->triggerState = TriggerRecord::TS_FAKE_UPGRADE;
5210  triggerPtr.p->triggerId = triggerPtr.i;
5211  triggerPtr.p->tableId = tabPtr.p->primaryTableId;
5212  triggerPtr.p->indexId = tabPtr.i;
5213  TriggerInfo::packTriggerInfo(triggerPtr.p->triggerInfo,
5214  g_hashIndexTriggerTmpl[0].triggerInfo);
5215  char buf[256];
5216  BaseString::snprintf(buf, sizeof(buf),
5217  "UPG_DEL_NDB$INDEX_%u_UI", tabPtr.i);
5218 
5219  {
5220  Rope name(c_rope_pool, triggerPtr.p->triggerName);
5221  name.assign(buf);
5222  }
5223 
5224  Ptr<DictObject> obj_ptr;
5225  bool ok = c_obj_hash.seize(obj_ptr);
5226  ndbrequire(ok);
5227  new (obj_ptr.p) DictObject();
5228 
5229  obj_ptr.p->m_name = triggerPtr.p->triggerName;
5230  c_obj_hash.add(obj_ptr);
5231  obj_ptr.p->m_ref_count = 0;
5232 
5233  triggerPtr.p->m_obj_ptr_i = obj_ptr.i;
5234  obj_ptr.p->m_id = triggerPtr.p->triggerId;
5235  obj_ptr.p->m_type =TriggerInfo::getTriggerType(triggerPtr.p->triggerInfo);
5236  }
5237  }
5238 }
5239 
5240 void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
5241  ParseDictTabInfoRecord * parseP,
5242  DictTabInfo::Table &tableDesc)
5243 {
5244  TableRecordPtr tablePtr = parseP->tablePtr;
5245 
5247 
5248  Uint32 keyCount = 0;
5249  Uint32 keyLength = 0;
5250  Uint32 attrCount = tablePtr.p->noOfAttributes;
5251  Uint32 nullCount = 0;
5252  Uint32 nullBits = 0;
5253  Uint32 noOfCharsets = 0;
5254  Uint16 charsets[128];
5255  Uint32 recordLength = 0;
5256  AttributeRecordPtr attrPtr;
5257  c_attributeRecordHash.removeAll();
5258 
5259  LocalDLFifoList<AttributeRecord> list(c_attributeRecordPool,
5260  tablePtr.p->m_attributes);
5261 
5262  Uint32 counts[] = {0,0,0,0,0};
5263 
5264  for(Uint32 i = 0; i<attrCount; i++){
5268  DictTabInfo::Attribute attrDesc; attrDesc.init();
5269  status = SimpleProperties::unpack(it, &attrDesc,
5270  DictTabInfo::AttributeMapping,
5271  DictTabInfo::AttributeMappingSize,
5272  true, true);
5273 
5274  if(status != SimpleProperties::Break){
5275  parseP->errorCode = CreateTableRef::InvalidFormat;
5276  parseP->status = status;
5277  parseP->errorKey = it.getKey();
5278  parseP->errorLine = __LINE__;
5279  return;
5280  }
5281 
5285  const Uint32 len = Uint32(strlen(attrDesc.AttributeName)+1);
5286  const Uint32 name_hash = Rope::hash(attrDesc.AttributeName, len);
5287  {
5288  AttributeRecord key;
5289  key.m_key.m_name_ptr = attrDesc.AttributeName;
5290  key.m_key.m_name_len = len;
5291  key.attributeName.m_hash = name_hash;
5292  key.m_key.m_pool = &c_rope_pool;
5293  Ptr<AttributeRecord> old_ptr;
5294  c_attributeRecordHash.find(old_ptr, key);
5295 
5296  if(old_ptr.i != RNIL){
5297  parseP->errorCode = CreateTableRef::AttributeNameTwice;
5298  return;
5299  }
5300  }
5301 
5302  list.seize(attrPtr);
5303  if(attrPtr.i == RNIL){
5304  jam();
5305  parseP->errorCode = CreateTableRef::NoMoreAttributeRecords;
5306  return;
5307  }
5308 
5309  new (attrPtr.p) AttributeRecord();
5310  attrPtr.p->attributeDescriptor = 0x00012255; //Default value
5311  attrPtr.p->tupleKey = 0;
5312 
5316  {
5317  Rope name(c_rope_pool, attrPtr.p->attributeName);
5318  if (!name.assign(attrDesc.AttributeName, len, name_hash))
5319  {
5320  jam();
5321  parseP->errorCode = CreateTableRef::OutOfStringBuffer;
5322  parseP->errorLine = __LINE__;
5323  return;
5324  }
5325  }
5326  attrPtr.p->attributeId = i;
5327  //attrPtr.p->attributeId = attrDesc.AttributeId;
5328  attrPtr.p->tupleKey = (keyCount + 1) * attrDesc.AttributeKeyFlag;
5329 
5330  attrPtr.p->extPrecision = attrDesc.AttributeExtPrecision;
5331  attrPtr.p->extScale = attrDesc.AttributeExtScale;
5332  attrPtr.p->extLength = attrDesc.AttributeExtLength;
5333  // charset in upper half of precision
5334  unsigned csNumber = (attrPtr.p->extPrecision >> 16);
5335  if (csNumber != 0) {
5336  /*
5337  * A new charset is first accessed here on this node.
5338  * TODO use separate thread (e.g. via NDBFS) if need to load from file
5339  */
5340  CHARSET_INFO* cs = get_charset(csNumber, MYF(0));
5341  if (cs == NULL) {
5342  parseP->errorCode = CreateTableRef::InvalidCharset;
5343  parseP->errorLine = __LINE__;
5344  return;
5345  }
5346  // XXX should be done somewhere in mysql
5347  all_charsets[cs->number] = cs;
5348  unsigned i = 0;
5349  while (i < noOfCharsets) {
5350  if (charsets[i] == csNumber)
5351  break;
5352  i++;
5353  }
5354  if (i == noOfCharsets) {
5355  noOfCharsets++;
5356  if (noOfCharsets > sizeof(charsets)/sizeof(charsets[0])) {
5357  parseP->errorCode = CreateTableRef::InvalidFormat;
5358  parseP->errorLine = __LINE__;
5359  return;
5360  }
5361  charsets[i] = csNumber;
5362  }
5363  }
5364 
5365  // compute attribute size and array size
5366  bool translateOk = attrDesc.translateExtType();
5367  tabRequire(translateOk, CreateTableRef::Inconsistency);
5368 
5369  if(attrDesc.AttributeArraySize > 65535){
5370  parseP->errorCode = CreateTableRef::ArraySizeTooBig;
5371  parseP->status = status;
5372  parseP->errorKey = it.getKey();
5373  parseP->errorLine = __LINE__;
5374  return;
5375  }
5376 
5377  // XXX old test option, remove
5378  if(!attrDesc.AttributeKeyFlag &&
5379  tablePtr.i > 1 &&
5380  !tablePtr.p->isIndex())
5381  {
5382  //attrDesc.AttributeStorageType= NDB_STORAGETYPE_DISK;
5383  }
5384 
5385  Uint32 desc = 0;
5386  AttributeDescriptor::setType(desc, attrDesc.AttributeExtType);
5387  AttributeDescriptor::setSize(desc, attrDesc.AttributeSize);
5388  AttributeDescriptor::setArraySize(desc, attrDesc.AttributeArraySize);
5389  AttributeDescriptor::setArrayType(desc, attrDesc.AttributeArrayType);
5390  AttributeDescriptor::setNullable(desc, attrDesc.AttributeNullableFlag);
5391  AttributeDescriptor::setDKey(desc, attrDesc.AttributeDKey);
5392  AttributeDescriptor::setPrimaryKey(desc, attrDesc.AttributeKeyFlag);
5393  AttributeDescriptor::setDiskBased(desc, attrDesc.AttributeStorageType == NDB_STORAGETYPE_DISK);
5394  AttributeDescriptor::setDynamic(desc, attrDesc.AttributeDynamic);
5395  attrPtr.p->attributeDescriptor = desc;
5396  attrPtr.p->autoIncrement = attrDesc.AttributeAutoIncrement;
5397  {
5398  char defaultValueBuf [MAX_ATTR_DEFAULT_VALUE_SIZE];
5399 
5400  if (attrDesc.AttributeDefaultValueLen)
5401  {
5402  ndbrequire(attrDesc.AttributeDefaultValueLen >= sizeof(Uint32));
5403 
5404  memcpy(defaultValueBuf, attrDesc.AttributeDefaultValue,
5405  attrDesc.AttributeDefaultValueLen);
5406 
5407  /* Table meta-info is normally stored in network byte order by
5408  * SimpleProperties.
5409  * For the default value, we convert as necessary here
5410  */
5411  /* Convert AttrInfoHeader */
5412  Uint32 a;
5413  memcpy(&a, defaultValueBuf, sizeof(Uint32));
5414  a = ntohl(a);
5415  memcpy(defaultValueBuf, &a, sizeof(Uint32));
5416 
5417  Uint32 remainBytes = attrDesc.AttributeDefaultValueLen - sizeof(Uint32);
5418 
5419  if (remainBytes)
5420  {
5421  /* Convert attribute */
5422  NdbSqlUtil::convertByteOrder(attrDesc.AttributeExtType,
5423  attrDesc.AttributeSize,
5424  attrDesc.AttributeArrayType,
5425  attrDesc.AttributeArraySize,
5426  (uchar*) defaultValueBuf + sizeof(Uint32),
5427  remainBytes);
5428  }
5429  }
5430 
5431  Rope defaultValue(c_rope_pool, attrPtr.p->defaultValue);
5432  defaultValue.assign(defaultValueBuf,
5433  attrDesc.AttributeDefaultValueLen);
5434  }
5435 
5436  keyCount += attrDesc.AttributeKeyFlag;
5437  nullCount += attrDesc.AttributeNullableFlag;
5438 
5439  const Uint32 aSz = (1 << attrDesc.AttributeSize);
5440  Uint32 sz;
5441  if(aSz != 1)
5442  {
5443  sz = ((aSz * attrDesc.AttributeArraySize) + 31) >> 5;
5444  }
5445  else
5446  {
5447  sz = 0;
5448  nullBits += attrDesc.AttributeArraySize;
5449  }
5450 
5451  if(attrDesc.AttributeArraySize == 0)
5452  {
5453  parseP->errorCode = CreateTableRef::InvalidArraySize;
5454  parseP->status = status;
5455  parseP->errorKey = it.getKey();
5456  parseP->errorLine = __LINE__;
5457  return;
5458  }
5459 
5460  recordLength += sz;
5461  if(attrDesc.AttributeKeyFlag){
5462  keyLength += sz;
5463 
5464  if(attrDesc.AttributeNullableFlag){
5465  parseP->errorCode = CreateTableRef::NullablePrimaryKey;
5466  parseP->status = status;
5467  parseP->errorKey = it.getKey();
5468  parseP->errorLine = __LINE__;
5469  return;
5470  }
5471  }
5472 
5473  c_attributeRecordHash.add(attrPtr);
5474 
5475  int a= AttributeDescriptor::getDiskBased(desc);
5476  int b= AttributeDescriptor::getArrayType(desc);
5477  Uint32 pos= 2*(a ? 1 : 0) + (b == NDB_ARRAYTYPE_FIXED ? 0 : 1);
5478  counts[pos+1]++;
5479 
5480  if(b != NDB_ARRAYTYPE_FIXED && sz == 0)
5481  {
5482  parseP->errorCode = CreateTableRef::VarsizeBitfieldNotSupported;
5483  parseP->status = status;
5484  parseP->errorKey = it.getKey();
5485  parseP->errorLine = __LINE__;
5486  return;
5487  }
5488 
5489  if(!it.next())
5490  break;
5491 
5492  if(it.getKey() != DictTabInfo::AttributeName)
5493  break;
5494  }//while
5495 
5496  tablePtr.p->noOfPrimkey = keyCount;
5497  tablePtr.p->noOfNullAttr = nullCount;
5498  tablePtr.p->noOfCharsets = noOfCharsets;
5499  tablePtr.p->tupKeyLength = keyLength;
5500  tablePtr.p->noOfNullBits = nullCount + nullBits;
5501 
5502  tabRequire(recordLength<= MAX_TUPLE_SIZE_IN_WORDS,
5503  CreateTableRef::RecordTooBig);
5504  tabRequire(keyLength <= MAX_KEY_SIZE_IN_WORDS,
5505  CreateTableRef::InvalidPrimaryKeySize);
5506  tabRequire(keyLength > 0,
5507  CreateTableRef::InvalidPrimaryKeySize);
5508  tabRequire(CHECK_SUMA_MESSAGE_SIZE(keyCount, keyLength, attrCount, recordLength),
5509  CreateTableRef::RecordTooBig);
5510 
5511  /* Check that all currently running nodes data support
5512  * table features
5513  */
5514  for (Uint32 nodeId=1; nodeId < MAX_NODES; nodeId++)
5515  {
5516  const NodeInfo& ni = getNodeInfo(nodeId);
5517 
5518  if (ni.m_connected &&
5519  (ni.m_type == NODE_TYPE_DB))
5520  {
5521  /* Check that all nodes support extra bits */
5522  if (tablePtr.p->m_extra_row_gci_bits ||
5523  tablePtr.p->m_extra_row_author_bits)
5524  {
5525  tabRequire(ndb_tup_extrabits(ni.m_version),
5526  CreateTableRef::FeatureRequiresUpgrade);
5527  }
5528  }
5529  }
5530 
5531 
5532  if(tablePtr.p->m_tablespace_id != RNIL || counts[3] || counts[4])
5533  {
5534  FilegroupPtr tablespacePtr;
5535  if(!c_filegroup_hash.find(tablespacePtr, tablePtr.p->m_tablespace_id))
5536  {
5537  tabRequire(false, CreateTableRef::InvalidTablespace);
5538  }
5539 
5540  if(tablespacePtr.p->m_type != DictTabInfo::Tablespace)
5541  {
5542  tabRequire(false, CreateTableRef::NotATablespace);
5543  }
5544 
5545  if(tablespacePtr.p->m_version != tableDesc.TablespaceVersion)
5546  {
5547  tabRequire(false, CreateTableRef::InvalidTablespaceVersion);
5548  }
5549  }
5550 }//handleTabInfo()
5551 
5552 // MODULE: block/unblock substartstop
5553 void
5554 Dbdict::block_substartstop(Signal* signal, SchemaOpPtr op_ptr)
5555 {
5556  ndbrequire(c_sub_startstop_lock.get(getOwnNodeId()) == false);
5557  c_sub_startstop_lock.set(getOwnNodeId());
5558  signal->theData[0] = ZWAIT_SUBSTARTSTOP;
5559  signal->theData[1] = op_ptr.p->op_key;
5560  sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
5561 }
5562 
5563 void
5564 Dbdict::unblock_substartstop()
5565 {
5566  ndbrequire(c_sub_startstop_lock.get(getOwnNodeId()));
5567  c_sub_startstop_lock.clear(getOwnNodeId());
5568 }
5569 
5570 void
5571 Dbdict::wait_substartstop(Signal* signal, Uint32 opkey)
5572 {
5573  if (c_outstanding_sub_startstop == 0)
5574  {
5575  jam();
5576  Callback callback;
5577  bool ok = findCallback(callback, opkey);
5578  ndbrequire(ok);
5579  execute(signal, callback, 0);
5580  return;
5581  }
5582 
5583  signal->theData[0] = ZWAIT_SUBSTARTSTOP;
5584  signal->theData[1] = opkey;
5585  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100,
5586  signal->length());
5587 }
5588 
5589 /* ---------------------------------------------------------------- */
5590 // New global checkpoint created.
5591 /* ---------------------------------------------------------------- */
5592 void
5593 Dbdict::wait_gcp(Signal* signal, SchemaOpPtr op_ptr, Uint32 flags)
5594 {
5595  WaitGCPReq* req = (WaitGCPReq*)signal->getDataPtrSend();
5596 
5597  req->senderRef = reference();
5598  req->senderData = op_ptr.p->op_key;
5599  req->requestType = flags;
5600 
5601  sendSignal(DBDIH_REF, GSN_WAIT_GCP_REQ, signal,
5602  WaitGCPReq::SignalLength, JBB);
5603 }
5604 
5605 void Dbdict::execWAIT_GCP_CONF(Signal* signal)
5606 {
5607  WaitGCPConf* conf = (WaitGCPConf*)signal->getDataPtr();
5608  handleDictConf(signal, conf);
5609 }//execWAIT_GCP_CONF()
5610 
5611 /* ---------------------------------------------------------------- */
5612 // Refused new global checkpoint.
5613 /* ---------------------------------------------------------------- */
5614 void Dbdict::execWAIT_GCP_REF(Signal* signal)
5615 {
5616  jamEntry();
5617  WaitGCPRef* ref = (WaitGCPRef*)signal->getDataPtr();
5618  handleDictRef(signal, ref);
5619 }//execWAIT_GCP_REF()
5620 
5621 // MODULE: CreateTable
5622 
5623 const Dbdict::OpInfo
5624 Dbdict::CreateTableRec::g_opInfo = {
5625  { 'C', 'T', 'a', 0 },
5626  GSN_CREATE_TAB_REQ,
5627  CreateTabReq::SignalLength,
5628  //
5629  &Dbdict::createTable_seize,
5630  &Dbdict::createTable_release,
5631  //
5632  &Dbdict::createTable_parse,
5633  &Dbdict::createTable_subOps,
5634  &Dbdict::createTable_reply,
5635  //
5636  &Dbdict::createTable_prepare,
5637  &Dbdict::createTable_commit,
5638  &Dbdict::createTable_complete,
5639  //
5640  &Dbdict::createTable_abortParse,
5641  &Dbdict::createTable_abortPrepare
5642 };
5643 
5644 bool
5645 Dbdict::createTable_seize(SchemaOpPtr op_ptr)
5646 {
5647  return seizeOpRec<CreateTableRec>(op_ptr);
5648 }
5649 
5650 void
5651 Dbdict::createTable_release(SchemaOpPtr op_ptr)
5652 {
5653  CreateTableRecPtr createTabPtr;
5654  getOpRec(op_ptr, createTabPtr);
5655  if (createTabPtr.p->m_tabInfoPtrI != RNIL) {
5656  jam();
5657  SegmentedSectionPtr ss_ptr;
5658  getSection(ss_ptr, createTabPtr.p->m_tabInfoPtrI);
5659  SimulatedBlock::release(ss_ptr);
5660  createTabPtr.p->m_tabInfoPtrI = RNIL;
5661  }
5662  if (createTabPtr.p->m_fragmentsPtrI != RNIL) {
5663  jam();
5664  SegmentedSectionPtr ss_ptr;
5665  getSection(ss_ptr, createTabPtr.p->m_fragmentsPtrI);
5666  SimulatedBlock::release(ss_ptr);
5667  createTabPtr.p->m_fragmentsPtrI = RNIL;
5668  }
5669  releaseOpRec<CreateTableRec>(op_ptr);
5670 }
5671 
5672 void
5673 Dbdict::execCREATE_TABLE_REQ(Signal* signal)
5674 {
5675  jamEntry();
5676  if (!assembleFragments(signal)) {
5677  jam();
5678  return;
5679  }
5680  SectionHandle handle(this, signal);
5681 
5682  if (check_sender_version(signal, MAKE_VERSION(6,4,0)) < 0)
5683  {
5684  jam();
5689  CreateTableReq* tmp = (CreateTableReq*)signal->getDataPtr();
5690  do_swap(tmp->senderRef, tmp->senderData);
5691  }
5692 
5693  const CreateTableReq req_copy =
5694  *(const CreateTableReq*)signal->getDataPtr();
5695  const CreateTableReq* req = &req_copy;
5696 
5697  ErrorInfo error;
5698  do {
5699  SchemaOpPtr op_ptr;
5700  CreateTableRecPtr createTabPtr;
5701  CreateTabReq* impl_req;
5702 
5703  startClientReq(op_ptr, createTabPtr, req, impl_req, error);
5704  if (hasError(error)) {
5705  jam();
5706  break;
5707  }
5708 
5709  impl_req->tableId = RNIL;
5710  impl_req->tableVersion = 0;
5711  impl_req->gci = 0;
5712 
5713  handleClientReq(signal, op_ptr, handle);
5714  return;
5715  } while (0);
5716 
5717  releaseSections(handle);
5718 
5719  CreateTableRef* ref = (CreateTableRef*)signal->getDataPtrSend();
5720  ref->senderRef = reference();
5721  ref->transId = req->transId;
5722  ref->clientData = req->clientData;
5723  getError(error, ref);
5724  ref->errorStatus = error.errorStatus;
5725  ref->errorKey = error.errorKey;
5726 
5727  sendSignal(req->clientRef, GSN_CREATE_TABLE_REF, signal,
5728  CreateTableRef::SignalLength, JBB);
5729 }
5730 
5731 // CreateTable: PARSE
5732 
5733 Uint32
5734 Dbdict::get_fragmentation(Signal* signal, Uint32 tableId)
5735 {
5736  CreateFragmentationReq * req =
5737  (CreateFragmentationReq*)signal->getDataPtrSend();
5738  req->senderRef = 0;
5739  req->senderData = RNIL;
5740  req->fragmentationType = 0;
5741  req->noOfFragments = 0;
5742  req->primaryTableId = tableId;
5743  req->requestInfo = CreateFragmentationReq::RI_GET_FRAGMENTATION;
5744  EXECUTE_DIRECT(DBDICT, GSN_CREATE_FRAGMENTATION_REQ, signal,
5745  CreateFragmentationReq::SignalLength);
5746 
5747  return signal->theData[0];
5748 }
5749 
5750 Uint32
5751 Dbdict::create_fragmentation(Signal* signal,
5752  TableRecordPtr tabPtr,
5753  const Uint16 *src,
5754  Uint32 cnt,
5755  Uint32 flags)
5756 {
5757  CreateFragmentationReq* frag_req =
5758  (CreateFragmentationReq*)signal->getDataPtrSend();
5759  frag_req->senderRef = 0; // direct conf
5760  frag_req->senderData = RNIL;
5761  frag_req->primaryTableId = tabPtr.p->primaryTableId;
5762  frag_req->noOfFragments = tabPtr.p->fragmentCount;
5763  frag_req->fragmentationType = tabPtr.p->fragmentType;
5764  frag_req->requestInfo = flags;
5765 
5766  if (tabPtr.p->hashMapObjectId != RNIL)
5767  {
5768  jam();
5769  HashMapPtr hm_ptr;
5770  ndbrequire(c_hash_map_hash.find(hm_ptr, tabPtr.p->hashMapObjectId));
5771  frag_req->map_ptr_i = hm_ptr.p->m_map_ptr_i;
5772  }
5773  else
5774  {
5775  jam();
5776  frag_req->map_ptr_i = RNIL;
5777  }
5778 
5779  memcpy(signal->theData+25, src, 2*cnt);
5780 
5781  if (cnt != 0 && cnt != tabPtr.p->fragmentCount)
5782  {
5787  return CreateTableRef::InvalidFormat;
5788  }
5789 
5790  if (tabPtr.p->isOrderedIndex()) {
5791  jam();
5792  // ordered index has same fragmentation as the table
5793  frag_req->primaryTableId = tabPtr.p->primaryTableId;
5794  frag_req->fragmentationType = DictTabInfo::DistrKeyOrderedIndex;
5795  }
5796  else if (tabPtr.p->isHashIndex())
5797  {
5798  jam();
5799  /*
5800  * Unique hash indexes has same amount of fragments as primary table
5801  * and distributed in the same manner but has always a normal hash
5802  * fragmentation.
5803  */
5804  frag_req->primaryTableId = RNIL;
5805  }
5806  else
5807  {
5808  jam();
5809  /*
5810  * Blob tables come here with primaryTableId != RNIL but we only need
5811  * it for creating the fragments so we set it to RNIL now that we got
5812  * what we wanted from it to avoid other side effects.
5813  */
5814  tabPtr.p->primaryTableId = RNIL;
5815  }
5816 
5817  EXECUTE_DIRECT(DBDICT, GSN_CREATE_FRAGMENTATION_REQ, signal,
5818  CreateFragmentationReq::SignalLength);
5819  jamEntry();
5820 
5821  return signal->theData[0];
5822 }
5823 
5824 void
5825 Dbdict::createTable_parse(Signal* signal, bool master,
5826  SchemaOpPtr op_ptr,
5827  SectionHandle& handle, ErrorInfo& error)
5828 {
5829  D("createTable_parse");
5830 
5831  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
5832  CreateTableRecPtr createTabPtr;
5833  getOpRec(op_ptr, createTabPtr);
5834  CreateTabReq* impl_req = &createTabPtr.p->m_request;
5835 
5836  /*
5837  * Master parses client DictTabInfo (sec 0) into new table record.
5838  * DIH is called to create fragmentation. The table record is
5839  * then dumped back into DictTabInfo to produce a canonical format.
5840  * The new DictTabInfo (sec 0) and the fragmentation (sec 1) are
5841  * sent to all participants when master parse returns.
5842  */
5843  if (master)
5844  {
5845  jam();
5846 
5847  // parse client DictTabInfo into new TableRecord
5848 
5849  ParseDictTabInfoRecord parseRecord;
5850  parseRecord.requestType = DictTabInfo::CreateTableFromAPI;
5851  parseRecord.errorCode = 0;
5852 
5853  SegmentedSectionPtr ss_ptr;
5854  if (!handle.getSection(ss_ptr, CreateTableReq::DICT_TAB_INFO)) {
5855  jam();
5856  setError(error, CreateTableRef::InvalidFormat, __LINE__);
5857  return;
5858  }
5859  SimplePropertiesSectionReader r(ss_ptr, getSectionSegmentPool());
5860 
5861  handleTabInfoInit(signal, trans_ptr, r, &parseRecord);
5862  releaseSections(handle);
5863 
5864  if (parseRecord.errorCode == 0)
5865  {
5866  if (ERROR_INSERTED(6200) ||
5867  (ERROR_INSERTED(6201) &&
5868  DictTabInfo::isIndex(parseRecord.tablePtr.p->tableType)))
5869  {
5870  jam();
5871  CLEAR_ERROR_INSERT_VALUE;
5872  parseRecord.errorCode = 1;
5873  }
5874  }
5875 
5876  if (parseRecord.errorCode != 0)
5877  {
5878  jam();
5879  if (!parseRecord.tablePtr.isNull())
5880  {
5881  jam();
5882  releaseTableObject(parseRecord.tablePtr.i, true);
5883  }
5884  setError(error, parseRecord);
5885  BaseString::snprintf(error.errorObjectName, sizeof(error.errorObjectName),
5886  "%s", c_tableDesc.TableName);
5887  return;
5888  }
5889 
5890  TableRecordPtr tabPtr = parseRecord.tablePtr;
5891 
5892  // link operation to object seized in handleTabInfoInit
5893  {
5894  DictObjectPtr obj_ptr;
5895  Uint32 obj_ptr_i = tabPtr.p->m_obj_ptr_i;
5896  bool ok = findDictObject(op_ptr, obj_ptr, obj_ptr_i);
5897  ndbrequire(ok);
5898  }
5899 
5900  {
5901  Uint32 version = getTableEntry(tabPtr.i)->m_tableVersion;
5902  tabPtr.p->tableVersion = create_obj_inc_schema_version(version);
5903  }
5904 
5905  // fill in table id and version
5906  impl_req->tableId = tabPtr.i;
5907  impl_req->tableVersion = tabPtr.p->tableVersion;
5908 
5909  if (ERROR_INSERTED(6202) ||
5910  (ERROR_INSERTED(6203) &&
5911  DictTabInfo::isIndex(parseRecord.tablePtr.p->tableType)))
5912  {
5913  jam();
5914  CLEAR_ERROR_INSERT_VALUE;
5915  setError(error, 1, __LINE__);
5916  return;
5917  }
5918 
5919  // create fragmentation via DIH (no changes in DIH)
5920  Uint16* frag_data = (Uint16*)(signal->getDataPtr()+25);
5921  Uint32 err = create_fragmentation(signal, tabPtr,
5922  c_fragData, c_fragDataLen / 2);
5923  if (err)
5924  {
5925  jam();
5926  setError(error, err, __LINE__);
5927  return;
5928  }
5929 
5930  // save fragmentation in long signal memory
5931  {
5932  // wl3600_todo make a method for this magic stuff
5933  Uint32 count = 2 + (1 + frag_data[0]) * frag_data[1];
5934 
5935  Ptr<SectionSegment> frag_ptr;
5936  bool ok = import(frag_ptr, (Uint32*)frag_data, (count + 1) / 2);
5937  ndbrequire(ok);
5938  createTabPtr.p->m_fragmentsPtrI = frag_ptr.i;
5939 
5940  // save fragment count
5941  tabPtr.p->fragmentCount = frag_data[1];
5942  }
5943 
5944  // dump table record back into DictTabInfo
5945  {
5947  packTableIntoPages(w, tabPtr);
5948 
5949  SegmentedSectionPtr ss_ptr;
5950  w.getPtr(ss_ptr);
5951  createTabPtr.p->m_tabInfoPtrI = ss_ptr.i;
5952  }
5953 
5954  // assign signal sections to send to participants
5955  {
5956  SegmentedSectionPtr ss0_ptr;
5957  SegmentedSectionPtr ss1_ptr;
5958 
5959  getSection(ss0_ptr, createTabPtr.p->m_tabInfoPtrI);
5960  getSection(ss1_ptr, createTabPtr.p->m_fragmentsPtrI);
5961 
5962  ndbrequire(handle.m_cnt == 0);
5963  handle.m_ptr[CreateTabReq::DICT_TAB_INFO] = ss0_ptr;
5964  handle.m_ptr[CreateTabReq::FRAGMENTATION] = ss1_ptr;
5965  handle.m_cnt = 2;
5966 
5967  // handle owns the memory now
5968  createTabPtr.p->m_tabInfoPtrI = RNIL;
5969  createTabPtr.p->m_fragmentsPtrI = RNIL;
5970  }
5971  }
5972  else if (op_ptr.p->m_restart)
5973  {
5974  jam();
5975  impl_req->tableId = c_restartRecord.activeTable;
5976  impl_req->tableVersion = c_restartRecord.m_entry.m_tableVersion;
5977  impl_req->gci = c_restartRecord.m_entry.m_gcp;
5978  }
5979 
5980  const Uint32 gci = impl_req->gci;
5981  const Uint32 tableId = impl_req->tableId;
5982  const Uint32 tableVersion = impl_req->tableVersion;
5983 
5984  SegmentedSectionPtr tabInfoPtr;
5985  {
5986  bool ok = handle.getSection(tabInfoPtr, CreateTabReq::DICT_TAB_INFO);
5987  ndbrequire(ok);
5988  }
5989 
5990  // wl3600_todo parse the rewritten DictTabInfo in master too
5991  if (!master)
5992  {
5993  jam();
5994  createTabPtr.p->m_request.tableId = tableId;
5995 
5996  ParseDictTabInfoRecord parseRecord;
5997  parseRecord.requestType = DictTabInfo::AddTableFromDict;
5998  parseRecord.errorCode = 0;
5999 
6000  SimplePropertiesSectionReader r(tabInfoPtr, getSectionSegmentPool());
6001 
6002  bool checkExist = true;
6003  handleTabInfoInit(signal, trans_ptr, r, &parseRecord, checkExist);
6004 
6005  if (parseRecord.errorCode != 0)
6006  {
6007  jam();
6008  setError(error, parseRecord);
6009  BaseString::snprintf(error.errorObjectName, sizeof(error.errorObjectName),
6010  "%s", c_tableDesc.TableName);
6011  return;
6012  }
6013 
6014  TableRecordPtr tabPtr = parseRecord.tablePtr;
6015 
6016  // link operation to object seized in handleTabInfoInit
6017  {
6018  DictObjectPtr obj_ptr;
6019  Uint32 obj_ptr_i = tabPtr.p->m_obj_ptr_i;
6020  bool ok = findDictObject(op_ptr, obj_ptr, obj_ptr_i);
6021  ndbrequire(ok);
6022  }
6023  }
6024 
6025  {
6026  SegmentedSectionPtr ptr;
6027  handle.getSection(ptr, CreateTabReq::DICT_TAB_INFO);
6028  if (ptr.sz > MAX_WORDS_META_FILE)
6029  {
6030  jam();
6031  setError(error, CreateTableRef::TableDefinitionTooBig, __LINE__);
6032  return;
6033  }
6034  }
6035 
6036  // save sections to DICT memory
6037  saveOpSection(op_ptr, handle, CreateTabReq::DICT_TAB_INFO);
6038  if (op_ptr.p->m_restart == 0)
6039  {
6040  jam();
6041  saveOpSection(op_ptr, handle, CreateTabReq::FRAGMENTATION);
6042  }
6043 
6044  TableRecordPtr tabPtr;
6045  c_tableRecordPool.getPtr(tabPtr, tableId);
6046  tabPtr.p->packedSize = tabInfoPtr.sz;
6047  // wl3600_todo verify version on slave
6048  tabPtr.p->tableVersion = tableVersion;
6049  tabPtr.p->gciTableCreated = gci;
6050 
6051  if (ERROR_INSERTED(6121)) {
6052  jam();
6053  CLEAR_ERROR_INSERT_VALUE;
6054  setError(error, 9121, __LINE__);
6055  return;
6056  }
6057 
6058  SchemaFile::TableEntry te; te.init();
6059  te.m_tableState = SchemaFile::SF_CREATE;
6060  te.m_tableVersion = tableVersion;
6061  te.m_tableType = tabPtr.p->tableType;
6062  te.m_info_words = tabInfoPtr.sz;
6063  te.m_gcp = gci;
6064  te.m_transId = trans_ptr.p->m_transId;
6065 
6066  Uint32 err = trans_log_schema_op(op_ptr, tableId, &te);
6067  if (err)
6068  {
6069  jam();
6070  setError(error, err, __LINE__);
6071  return;
6072  }
6073  D("createTable_parse: "
6074  << copyRope<MAX_TAB_NAME_SIZE>(tabPtr.p->tableName)
6075  << V(tabPtr.p->tableVersion));
6076 }
6077 
6078 bool
6079 Dbdict::createTable_subOps(Signal* signal, SchemaOpPtr op_ptr)
6080 {
6081  D("createTable_subOps" << V(op_ptr.i) << *op_ptr.p);
6082  // wl3600_todo blobs
6083  return false;
6084 }
6085 
6086 void
6087 Dbdict::createTable_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
6088 {
6089  jam();
6090  D("createTable_reply" << V(op_ptr.i) << *op_ptr.p);
6091 
6092  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
6093 
6094  CreateTableRecPtr createTabPtr;
6095  getOpRec(op_ptr, createTabPtr);
6096 
6097  if (!hasError(error)) {
6098  CreateTableConf* conf = (CreateTableConf*)signal->getDataPtrSend();
6099  conf->senderRef = reference();
6100  conf->clientData = op_ptr.p->m_clientData;
6101  conf->transId = trans_ptr.p->m_transId;
6102  conf->tableId = createTabPtr.p->m_request.tableId;
6103  conf->tableVersion = createTabPtr.p->m_request.tableVersion;
6104 
6105  D(V(conf->tableId) << V(conf->tableVersion));
6106 
6107  Uint32 clientRef = op_ptr.p->m_clientRef;
6108  sendSignal(clientRef, GSN_CREATE_TABLE_CONF, signal,
6109  CreateTableConf::SignalLength, JBB);
6110  } else {
6111  jam();
6112  CreateTableRef* ref = (CreateTableRef*)signal->getDataPtrSend();
6113  ref->senderRef = reference();
6114  ref->clientData = op_ptr.p->m_clientData;
6115  ref->transId = trans_ptr.p->m_transId;
6116  getError(error, ref);
6117  ref->errorStatus = error.errorStatus;
6118  ref->errorKey = error.errorKey;
6119 
6120  Uint32 clientRef = op_ptr.p->m_clientRef;
6121  sendSignal(clientRef, GSN_CREATE_TABLE_REF, signal,
6122  CreateTableRef::SignalLength, JBB);
6123  }
6124 }
6125 
6126 // CreateTable: PREPARE
6127 
6128 void
6129 Dbdict::createTable_prepare(Signal* signal, SchemaOpPtr op_ptr)
6130 {
6131  jam();
6132  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
6133  CreateTableRecPtr createTabPtr;
6134  getOpRec(op_ptr, createTabPtr);
6135 
6136  Uint32 tableId = createTabPtr.p->m_request.tableId;
6137  TableRecordPtr tabPtr;
6138  c_tableRecordPool.getPtr(tabPtr, tableId);
6139 
6140  Callback cb;
6141  cb.m_callbackData = op_ptr.p->op_key;
6142  cb.m_callbackFunction = safe_cast(&Dbdict::createTab_writeTableConf);
6143 
6144  if (ZRESTART_NO_WRITE_AFTER_READ && op_ptr.p->m_restart == 1)
6145  {
6146  jam();
6150  execute(signal, cb, 0);
6151  return;
6152  }
6153 
6154  bool savetodisk = !(tabPtr.p->m_bits & TableRecord::TR_Temporary);
6155  if (savetodisk)
6156  {
6157  jam();
6158  const OpSection& tabInfoSec =
6159  getOpSection(op_ptr, CreateTabReq::DICT_TAB_INFO);
6160  writeTableFile(signal, createTabPtr.p->m_request.tableId,
6161  tabInfoSec, &cb);
6162  }
6163  else
6164  {
6165  jam();
6166  execute(signal, cb, 0);
6167  }
6168 }
6169 
6170 void
6171 Dbdict::createTab_writeTableConf(Signal* signal,
6172  Uint32 op_key,
6173  Uint32 ret)
6174 {
6175  jam();
6176 
6177  SchemaOpPtr op_ptr;
6178  CreateTableRecPtr createTabPtr;
6179  findSchemaOp(op_ptr, createTabPtr, op_key);
6180  ndbrequire(!op_ptr.isNull());
6181 
6182  OpSection& fragSec = op_ptr.p->m_section[CreateTabReq::FRAGMENTATION];
6183  if (op_ptr.p->m_restart)
6184  {
6185  jam();
6186  new (&fragSec) OpSection();
6187  }
6188  else
6189  {
6190  const OpSection& fragSec =
6191  getOpSection(op_ptr, CreateTabReq::FRAGMENTATION);
6192  ndbrequire(fragSec.getSize() > 0);
6193  }
6194 
6195  Callback callback;
6196  callback.m_callbackData = op_ptr.p->op_key;
6197  callback.m_callbackFunction =
6198  safe_cast(&Dbdict::createTab_localComplete);
6199 
6200  createTab_local(signal, op_ptr, fragSec, &callback);
6201 }
6202 
6203 void
6204 Dbdict::createTab_local(Signal* signal,
6205  SchemaOpPtr op_ptr,
6206  OpSection afragSec,
6207  Callback * c)
6208 {
6209  jam();
6210  CreateTableRecPtr createTabPtr;
6211  getOpRec(op_ptr, createTabPtr);
6212  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
6213 
6214  createTabPtr.p->m_callback = * c;
6215 
6216  TableRecordPtr tabPtr;
6217  c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_request.tableId);
6218 
6222  CreateTabReq* req = (CreateTabReq*)signal->getDataPtrSend();
6223  req->senderRef = reference();
6224  req->senderData = op_ptr.p->op_key;
6225  req->tableId = createTabPtr.p->m_request.tableId;
6226  req->tableVersion = tabPtr.p->tableVersion;
6227  req->requestType = 0;
6228  req->gci = 0;
6229  req->noOfCharsets = tabPtr.p->noOfCharsets;
6230  req->tableType = tabPtr.p->tableType;
6231  req->primaryTableId = tabPtr.p->primaryTableId;
6232  req->forceVarPartFlag = !!(tabPtr.p->m_bits& TableRecord::TR_ForceVarPart);
6233  req->noOfNullAttributes = tabPtr.p->noOfNullBits;
6234  req->noOfKeyAttr = tabPtr.p->noOfPrimkey;
6235  req->checksumIndicator = 1;
6236  req->GCPIndicator = 1 + tabPtr.p->m_extra_row_gci_bits;
6237  req->noOfAttributes = tabPtr.p->noOfAttributes;
6238  req->extraRowAuthorBits = tabPtr.p->m_extra_row_author_bits;
6239  sendSignal(DBLQH_REF, GSN_CREATE_TAB_REQ, signal,
6240  CreateTabReq::SignalLengthLDM, JBB);
6241 
6242 
6246  {
6247  KeyDescriptor* desc= g_key_descriptor_pool.getPtr(tabPtr.i);
6248  new (desc) KeyDescriptor();
6249 
6250  if (tabPtr.p->primaryTableId == RNIL)
6251  {
6252  jam();
6253  desc->primaryTableId = createTabPtr.p->m_request.tableId;
6254  }
6255  else
6256  {
6257  jam();
6258  desc->primaryTableId = tabPtr.p->primaryTableId;
6259  }
6260 
6261  Uint32 key = 0;
6262  Ptr<AttributeRecord> attrPtr;
6263  LocalDLFifoList<AttributeRecord> list(c_attributeRecordPool,
6264  tabPtr.p->m_attributes);
6265  for(list.first(attrPtr); !attrPtr.isNull(); list.next(attrPtr))
6266  {
6267  AttributeRecord* aRec = attrPtr.p;
6268  if (aRec->tupleKey)
6269  {
6270  Uint32 attr = aRec->attributeDescriptor;
6271 
6272  desc->noOfKeyAttr ++;
6273  desc->keyAttr[key].attributeDescriptor = attr;
6274  Uint32 csNumber = (aRec->extPrecision >> 16);
6275  if (csNumber)
6276  {
6277  desc->keyAttr[key].charsetInfo = all_charsets[csNumber];
6278  ndbrequire(all_charsets[csNumber] != 0);
6279  desc->hasCharAttr = 1;
6280  }
6281  else
6282  {
6283  desc->keyAttr[key].charsetInfo = 0;
6284  }
6285  if (AttributeDescriptor::getDKey(attr))
6286  {
6287  desc->noOfDistrKeys ++;
6288  }
6289  if (AttributeDescriptor::getArrayType(attr) != NDB_ARRAYTYPE_FIXED)
6290  {
6291  desc->noOfVarKeys ++;
6292  }
6293  key++;
6294  }
6295  }
6296  ndbrequire(key == tabPtr.p->noOfPrimkey);
6297  }
6298 }
6299 
6300 void
6301 Dbdict::execCREATE_TAB_REF(Signal* signal)
6302 {
6303  jamEntry();
6304 
6305  CreateTabRef * const ref = (CreateTabRef*)signal->getDataPtr();
6306 
6307  SchemaOpPtr op_ptr;
6308  CreateTableRecPtr createTabPtr;
6309  findSchemaOp(op_ptr, createTabPtr, ref->senderData);
6310  ndbrequire(!op_ptr.isNull());
6311 
6312  setError(op_ptr, ref->errorCode, __LINE__);
6313  execute(signal, createTabPtr.p->m_callback, 0);
6314 }
6315 
6316 void
6317 Dbdict::execCREATE_TAB_CONF(Signal* signal)
6318 {
6319  jamEntry();
6320 
6321  CreateTabConf* conf = (CreateTabConf*)signal->getDataPtr();
6322 
6323  SchemaOpPtr op_ptr;
6324  CreateTableRecPtr createTabPtr;
6325  findSchemaOp(op_ptr, createTabPtr, conf->senderData);
6326  ndbrequire(!op_ptr.isNull());
6327 
6328  createTabPtr.p->m_lqhFragPtr = conf->lqhConnectPtr;
6329 
6330  TableRecordPtr tabPtr;
6331  c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_request.tableId);
6332  sendLQHADDATTRREQ(signal, op_ptr, tabPtr.p->m_attributes.firstItem);
6333 }
6334 
6335 
6336 void
6337 Dbdict::sendLQHADDATTRREQ(Signal* signal,
6338  SchemaOpPtr op_ptr,
6339  Uint32 attributePtrI)
6340 {
6341  jam();
6342  CreateTableRecPtr createTabPtr;
6343  getOpRec(op_ptr, createTabPtr);
6344 
6345  TableRecordPtr tabPtr;
6346  c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_request.tableId);
6347 
6348  const bool isHashIndex = tabPtr.p->isHashIndex();
6349 
6350  LqhAddAttrReq * const req = (LqhAddAttrReq*)signal->getDataPtrSend();
6351  Uint32 i = 0;
6352  Uint32 startIndex = 25;
6353  Uint32 *defVal_dst = &signal->theData[startIndex];
6354  Uint32 defVal_length = 0;
6355  for(i = 0; i<LqhAddAttrReq::MAX_ATTRIBUTES && attributePtrI != RNIL; i++){
6356  jam();
6357  AttributeRecordPtr attrPtr;
6358  c_attributeRecordPool.getPtr(attrPtr, attributePtrI);
6359  LqhAddAttrReq::Entry& entry = req->attributes[i];
6360  entry.attrId = attrPtr.p->attributeId;
6361  entry.attrDescriptor = attrPtr.p->attributeDescriptor;
6362  entry.extTypeInfo = 0;
6363  // charset number passed to TUP, TUX in upper half
6364  entry.extTypeInfo |= (attrPtr.p->extPrecision & ~0xFFFF);
6365 
6366  ConstRope def(c_rope_pool, attrPtr.p->defaultValue);
6367  def.copy((char*)defVal_dst);
6368 
6369  Uint32 defValueLen = def.size();
6370  defVal_length += (defValueLen + 3)/4;
6371  defVal_dst += (defValueLen + 3)/4;
6372 
6373  if (tabPtr.p->isIndex()) {
6374  Uint32 primaryAttrId;
6375  if (attrPtr.p->nextList != RNIL) {
6376  getIndexAttr(tabPtr, attributePtrI, &primaryAttrId);
6377  } else {
6378  primaryAttrId = ZNIL;
6379  if (tabPtr.p->isOrderedIndex())
6380  entry.attrId = 0; // attribute goes to TUP
6381  }
6382  entry.attrId |= (primaryAttrId << 16);
6383  }
6384 
6385  if (attrPtr.p->nextList == RNIL && isHashIndex)
6386  {
6387  jam();
6392  char tmp[MAX_TAB_NAME_SIZE];
6393  ConstRope name(c_rope_pool, attrPtr.p->attributeName);
6394  name.copy(tmp);
6395  ndbrequire(memcmp(tmp, "NDB$PK", sizeof("NDB$PK")) == 0);
6396  Uint32 at = AttributeDescriptor::getArrayType(entry.attrDescriptor);
6397  if (at == NDB_ARRAYTYPE_MEDIUM_VAR)
6398  {
6399  jam();
6400  AttributeDescriptor::clearArrayType(entry.attrDescriptor);
6401  AttributeDescriptor::setArrayType(entry.attrDescriptor,
6402  NDB_ARRAYTYPE_NONE_VAR);
6403  }
6404  }
6405 
6406  attributePtrI = attrPtr.p->nextList;
6407  }
6408  req->lqhFragPtr = createTabPtr.p->m_lqhFragPtr;
6409  req->senderData = op_ptr.p->op_key;
6410  req->senderAttrPtr = attributePtrI;
6411  req->noOfAttributes = i;
6412 
6413  if (defVal_length != 0)
6414  {
6415  LinearSectionPtr ptr[3];
6416  ptr[0].p= &signal->theData[startIndex];
6417  ptr[0].sz= defVal_length;
6418 
6419  sendSignal(DBLQH_REF, GSN_LQHADDATTREQ, signal,
6420  LqhAddAttrReq::HeaderLength + LqhAddAttrReq::EntryLength * i, JBB, ptr, 1);
6421  }
6422  else
6423  sendSignal(DBLQH_REF, GSN_LQHADDATTREQ, signal,
6424  LqhAddAttrReq::HeaderLength + LqhAddAttrReq::EntryLength * i, JBB);
6425 }
6426 
6427 void
6428 Dbdict::execLQHADDATTCONF(Signal * signal)
6429 {
6430  jamEntry();
6431  LqhAddAttrConf * const conf = (LqhAddAttrConf*)signal->getDataPtr();
6432 
6433  SchemaOpPtr op_ptr;
6434  CreateTableRecPtr createTabPtr;
6435  findSchemaOp(op_ptr, createTabPtr, conf->senderData);
6436  ndbrequire(!op_ptr.isNull());
6437 
6438  const Uint32 nextAttrPtr = conf->senderAttrPtr;
6439  if(nextAttrPtr != RNIL){
6440  jam();
6441  sendLQHADDATTRREQ(signal, op_ptr, nextAttrPtr);
6442  return;
6443  }
6444 
6445  createTab_dih(signal, op_ptr);
6446 }
6447 
6448 void
6449 Dbdict::execLQHADDATTREF(Signal * signal)
6450 {
6451  jamEntry();
6452  LqhAddAttrRef * const ref = (LqhAddAttrRef*)signal->getDataPtr();
6453 
6454  SchemaOpPtr op_ptr;
6455  CreateTableRecPtr createTabPtr;
6456  findSchemaOp(op_ptr, createTabPtr, ref->senderData);
6457  ndbrequire(!op_ptr.isNull());
6458 
6459  setError(op_ptr, ref->errorCode, __LINE__);
6460 
6461  sendTransConf(signal, op_ptr);
6462 }
6463 
6464 void
6465 Dbdict::createTab_dih(Signal* signal, SchemaOpPtr op_ptr)
6466 {
6467  CreateTableRecPtr createTabPtr;
6468  getOpRec(op_ptr, createTabPtr);
6469  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
6470 
6471  D("createTab_dih" << *op_ptr.p);
6472 
6473  TableRecordPtr tabPtr;
6474  c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_request.tableId);
6475 
6476 
6482  const OpSection& fragSec = op_ptr.p->m_section[CreateTabReq::FRAGMENTATION];
6483 
6484  DiAddTabReq * req = (DiAddTabReq*)signal->getDataPtrSend();
6485  req->connectPtr = op_ptr.p->op_key;
6486  req->tableId = tabPtr.i;
6487  req->fragType = tabPtr.p->fragmentType;
6488  req->kValue = tabPtr.p->kValue;
6489  req->noOfReplicas = 0;
6490  req->loggedTable = !!(tabPtr.p->m_bits & TableRecord::TR_Logged);
6491  req->tableType = tabPtr.p->tableType;
6492  req->schemaVersion = tabPtr.p->tableVersion;
6493  req->primaryTableId = tabPtr.p->primaryTableId;
6494  req->temporaryTable = !!(tabPtr.p->m_bits & TableRecord::TR_Temporary);
6495  // no transaction for restart tab (should add one)
6496  req->schemaTransId = !trans_ptr.isNull() ? trans_ptr.p->m_transId : 0;
6497 
6498  if (tabPtr.p->hashMapObjectId != RNIL)
6499  {
6500  HashMapPtr hm_ptr;
6501  ndbrequire(c_hash_map_hash.find(hm_ptr, tabPtr.p->hashMapObjectId));
6502  req->hashMapPtrI = hm_ptr.p->m_map_ptr_i;
6503  }
6504  else
6505  {
6506  req->hashMapPtrI = RNIL;
6507  }
6508 
6509  // fragmentation in long signal section
6510  {
6511  Uint32 page[1024];
6512  LinearSectionPtr ptr[3];
6513  Uint32 noOfSections = 0;
6514 
6515  const Uint32 size = fragSec.getSize();
6516 
6517  // wl3600_todo add ndbrequire on SR, NR
6518  if (size != 0) {
6519  jam();
6520  bool ok = copyOut(fragSec, page, 1024);
6521  ndbrequire(ok);
6522  ptr[noOfSections].sz = size;
6523  ptr[noOfSections].p = page;
6524  noOfSections++;
6525  }
6526 
6527  sendSignal(DBDIH_REF, GSN_DIADDTABREQ, signal,
6528  DiAddTabReq::SignalLength, JBB,
6529  ptr, noOfSections);
6530  }
6531 }
6532 
6533 static
6534 void
6535 calcLHbits(Uint32 * lhPageBits, Uint32 * lhDistrBits,
6536  Uint32 fid, Uint32 totalFragments, Dbdict * dict)
6537 {
6538  Uint32 distrBits = 0;
6539  Uint32 pageBits = 0;
6540 
6541  Uint32 tmp = 1;
6542  while (tmp < totalFragments) {
6543  jamBlock(dict);
6544  tmp <<= 1;
6545  distrBits++;
6546  }//while
6547 #ifdef ndb_classical_lhdistrbits
6548  if (tmp != totalFragments) {
6549  tmp >>= 1;
6550  if ((fid >= (totalFragments - tmp)) && (fid < (tmp - 1))) {
6551  distrBits--;
6552  }//if
6553  }//if
6554 #endif
6555  * lhPageBits = pageBits;
6556  * lhDistrBits = distrBits;
6557 
6558 }//calcLHbits()
6559 
6560 void
6561 Dbdict::execADD_FRAGREQ(Signal* signal)
6562 {
6563  jamEntry();
6564 
6565  AddFragReq * const req = (AddFragReq*)signal->getDataPtr();
6566 
6567  Uint32 dihPtr = req->dihPtr;
6568  Uint32 senderData = req->senderData;
6569  Uint32 tableId = req->tableId;
6570  Uint32 fragId = req->fragmentId;
6571  Uint32 node = req->nodeId;
6572  Uint32 lcpNo = req->nextLCP;
6573  Uint32 fragCount = req->totalFragments;
6574  Uint32 requestInfo = req->requestInfo;
6575  Uint32 startGci = req->startGci;
6576  Uint32 logPart = req->logPartId;
6577  Uint32 changeMask = req->changeMask;
6578 
6579  ndbrequire(node == getOwnNodeId());
6580 
6581  SchemaOpPtr op_ptr;
6582  TableRecordPtr tabPtr;
6583  if (AlterTableReq::getAddFragFlag(changeMask))
6584  {
6585  c_tableRecordPool.getPtr(tabPtr, tableId);
6586  if (DictTabInfo::isTable(tabPtr.p->tableType))
6587  {
6588  jam();
6589  AlterTableRecPtr alterTabPtr;
6590  findSchemaOp(op_ptr, alterTabPtr, senderData);
6591  ndbrequire(!op_ptr.isNull());
6592  alterTabPtr.p->m_dihAddFragPtr = dihPtr;
6593  tabPtr = alterTabPtr.p->m_newTablePtr;
6594  }
6595  else
6596  {
6597  jam();
6598  ndbrequire(DictTabInfo::isOrderedIndex(tabPtr.p->tableType));
6599  AlterIndexRecPtr alterIndexPtr;
6600  findSchemaOp(op_ptr, alterIndexPtr, senderData);
6601  ndbrequire(!op_ptr.isNull());
6602  alterIndexPtr.p->m_dihAddFragPtr = dihPtr;
6603  }
6604  }
6605  else
6606  {
6607  jam();
6608  CreateTableRecPtr createTabPtr;
6609  findSchemaOp(op_ptr, createTabPtr, senderData);
6610  ndbrequire(!op_ptr.isNull());
6611  createTabPtr.p->m_dihAddFragPtr = dihPtr;
6612  c_tableRecordPool.getPtr(tabPtr, tableId);
6613  }
6614 
6615 #if 0
6616  tabPtr.p->gciTableCreated = (startGci > tabPtr.p->gciTableCreated ? startGci:
6617  startGci > tabPtr.p->gciTableCreated);
6618 #endif
6619 
6623  Uint32 lhDistrBits = 0;
6624  Uint32 lhPageBits = 0;
6625  ::calcLHbits(&lhPageBits, &lhDistrBits, fragId, fragCount, this);
6626 
6627  Uint64 maxRows = tabPtr.p->maxRowsLow +
6628  (((Uint64)tabPtr.p->maxRowsHigh) << 32);
6629  Uint64 minRows = tabPtr.p->minRowsLow +
6630  (((Uint64)tabPtr.p->minRowsHigh) << 32);
6631  maxRows = (maxRows + fragCount - 1) / fragCount;
6632  minRows = (minRows + fragCount - 1) / fragCount;
6633 
6634  {
6635  LqhFragReq* req = (LqhFragReq*)signal->getDataPtrSend();
6636  req->senderData = senderData;
6637  req->senderRef = reference();
6638  req->fragmentId = fragId;
6639  req->requestInfo = requestInfo;
6640  req->tableId = tableId;
6641  req->localKeyLength = tabPtr.p->localKeyLen;
6642  req->maxLoadFactor = tabPtr.p->maxLoadFactor;
6643  req->minLoadFactor = tabPtr.p->minLoadFactor;
6644  req->kValue = tabPtr.p->kValue;
6645  req->lh3DistrBits = 0; //lhDistrBits;
6646  req->lh3PageBits = 0; //lhPageBits;
6647  req->maxRowsLow = (Uint32)(maxRows & 0xFFFFFFFF);
6648  req->maxRowsHigh = (Uint32)(maxRows >> 32);
6649  req->minRowsLow = (Uint32)(minRows & 0xFFFFFFFF);
6650  req->minRowsHigh = (Uint32)(minRows >> 32);
6651  Uint32 keyLen = tabPtr.p->tupKeyLength;
6652  req->keyLength = keyLen; // wl-2066 no more "long keys"
6653  req->nextLCP = lcpNo;
6654 
6655  req->startGci = startGci;
6656  req->tablespace_id= tabPtr.p->m_tablespace_id;
6657  req->tablespace_id = tabPtr.p->m_tablespace_id;
6658  req->logPartId = logPart;
6659  req->changeMask = changeMask;
6660  sendSignal(DBLQH_REF, GSN_LQHFRAGREQ, signal,
6661  LqhFragReq::SignalLength, JBB);
6662  }
6663 }
6664 
6665 void
6666 Dbdict::execLQHFRAGCONF(Signal * signal)
6667 {
6668  jamEntry();
6669  LqhFragConf * const conf = (LqhFragConf*)signal->getDataPtr();
6670 
6671  Uint32 dihPtr;
6672  Uint32 fragId = conf->fragId;
6673  Uint32 tableId = conf->tableId;
6674 
6675  if (AlterTableReq::getAddFragFlag(conf->changeMask))
6676  {
6677  jam();
6678  SchemaOpPtr op_ptr;
6679  Ptr<TableRecord> tabPtr;
6680  c_tableRecordPool.getPtr(tabPtr, tableId);
6681  if (DictTabInfo::isTable(tabPtr.p->tableType))
6682  {
6683  AlterTableRecPtr alterTabPtr;
6684  findSchemaOp(op_ptr, alterTabPtr, conf->senderData);
6685  ndbrequire(!op_ptr.isNull());
6686  dihPtr = alterTabPtr.p->m_dihAddFragPtr;
6687  }
6688  else
6689  {
6690  jam();
6691  ndbrequire(DictTabInfo::isOrderedIndex(tabPtr.p->tableType));
6692  AlterIndexRecPtr alterIndexPtr;
6693  findSchemaOp(op_ptr, alterIndexPtr, conf->senderData);
6694  ndbrequire(!op_ptr.isNull());
6695  dihPtr = alterIndexPtr.p->m_dihAddFragPtr;
6696  }
6697  }
6698  else
6699  {
6700  jam();
6701  SchemaOpPtr op_ptr;
6702  CreateTableRecPtr createTabPtr;
6703  findSchemaOp(op_ptr, createTabPtr, conf->senderData);
6704  ndbrequire(!op_ptr.isNull());
6705 
6706  createTabPtr.p->m_lqhFragPtr = conf->lqhFragPtr;
6707  dihPtr = createTabPtr.p->m_dihAddFragPtr;
6708  }
6709 
6710  {
6711  AddFragConf * const conf = (AddFragConf*)signal->getDataPtr();
6712  conf->dihPtr = dihPtr;
6713  conf->fragId = fragId;
6714  sendSignal(DBDIH_REF, GSN_ADD_FRAGCONF, signal,
6715  AddFragConf::SignalLength, JBB);
6716  }
6717 }
6718 
6719 void
6720 Dbdict::execLQHFRAGREF(Signal * signal)
6721 {
6722  jamEntry();
6723  LqhFragRef * const ref = (LqhFragRef*)signal->getDataPtr();
6724 
6725  Uint32 dihPtr;
6726  Uint32 tableId = ref->tableId;
6727  Uint32 fragId = ref->fragId;
6728  if (AlterTableReq::getAddFragFlag(ref->changeMask))
6729  {
6730  jam();
6731  SchemaOpPtr op_ptr;
6732  Ptr<TableRecord> tabPtr;
6733  c_tableRecordPool.getPtr(tabPtr, tableId);
6734  if (DictTabInfo::isTable(tabPtr.p->tableType))
6735  {
6736  jam();
6737  AlterTableRecPtr alterTabPtr;
6738  findSchemaOp(op_ptr, alterTabPtr, ref->senderData);
6739  ndbrequire(!op_ptr.isNull());
6740  setError(op_ptr, ref->errorCode, __LINE__);
6741  dihPtr = alterTabPtr.p->m_dihAddFragPtr;
6742  }
6743  else
6744  {
6745  jam();
6746  AlterIndexRecPtr alterIndexPtr;
6747  findSchemaOp(op_ptr, alterIndexPtr, ref->senderData);
6748  ndbrequire(!op_ptr.isNull());
6749  setError(op_ptr, ref->errorCode, __LINE__);
6750  dihPtr = alterIndexPtr.p->m_dihAddFragPtr;
6751  }
6752  }
6753  else
6754  {
6755  jam();
6756  SchemaOpPtr op_ptr;
6757  CreateTableRecPtr createTabPtr;
6758  findSchemaOp(op_ptr, createTabPtr, ref->senderData);
6759  ndbrequire(!op_ptr.isNull());
6760  setError(op_ptr, ref->errorCode, __LINE__);
6761  dihPtr = createTabPtr.p->m_dihAddFragPtr;
6762  }
6763 
6764  {
6765  AddFragRef * const ref = (AddFragRef*)signal->getDataPtr();
6766  ref->dihPtr = dihPtr;
6767  ref->fragId = fragId;
6768  sendSignal(DBDIH_REF, GSN_ADD_FRAGREF, signal,
6769  AddFragRef::SignalLength, JBB);
6770  }
6771 }
6772 
6773 void
6774 Dbdict::execDIADDTABCONF(Signal* signal)
6775 {
6776  jam();
6777 
6778  DiAddTabConf * const conf = (DiAddTabConf*)signal->getDataPtr();
6779 
6780  SchemaOpPtr op_ptr;
6781  CreateTableRecPtr createTabPtr;
6782  findSchemaOp(op_ptr, createTabPtr, conf->senderData);
6783  ndbrequire(!op_ptr.isNull());
6784 
6785  signal->theData[0] = op_ptr.p->op_key;
6786  signal->theData[1] = reference();
6787  signal->theData[2] = createTabPtr.p->m_request.tableId;
6788 
6789  sendSignal(DBLQH_REF, GSN_TAB_COMMITREQ, signal, 3, JBB);
6790 }
6791 
6792 void
6793 Dbdict::execDIADDTABREF(Signal* signal)
6794 {
6795  jam();
6796 
6797  DiAddTabRef * const ref = (DiAddTabRef*)signal->getDataPtr();
6798 
6799  SchemaOpPtr op_ptr;
6800  CreateTableRecPtr createTabPtr;
6801  findSchemaOp(op_ptr, createTabPtr, ref->senderData);
6802  ndbrequire(!op_ptr.isNull());
6803 
6804  setError(op_ptr, ref->errorCode, __LINE__);
6805  execute(signal, createTabPtr.p->m_callback, 0);
6806 }
6807 
6808 // wl3600_todo split into 2 methods for prepare/commit
6809 void
6810 Dbdict::execTAB_COMMITCONF(Signal* signal)
6811 {
6812  jamEntry();
6813 
6814  SchemaOpPtr op_ptr;
6815  CreateTableRecPtr createTabPtr;
6816  findSchemaOp(op_ptr, createTabPtr, signal->theData[0]);
6817  ndbrequire(!op_ptr.isNull());
6818  //const CreateTabReq* impl_req = &createTabPtr.p->m_request;
6819 
6820  TableRecordPtr tabPtr;
6821  c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_request.tableId);
6822 
6823  if (refToBlock(signal->getSendersBlockRef()) == DBLQH) {
6824  jam();
6825  // prepare table in DBTC
6826  TcSchVerReq * req = (TcSchVerReq*)signal->getDataPtr();
6827  req->tableId = tabPtr.i;
6828  req->tableVersion = tabPtr.p->tableVersion;
6829  req->tableLogged = (Uint32)!!(tabPtr.p->m_bits & TableRecord::TR_Logged);
6830  req->senderRef = reference();
6831  req->tableType = (Uint32)tabPtr.p->tableType;
6832  req->senderData = op_ptr.p->op_key;
6833  req->noOfPrimaryKeys = (Uint32)tabPtr.p->noOfPrimkey;
6834  req->singleUserMode = (Uint32)tabPtr.p->singleUserMode;
6835  req->userDefinedPartition = (tabPtr.p->fragmentType == DictTabInfo::UserDefined);
6836 
6837  if (DictTabInfo::isOrderedIndex(tabPtr.p->tableType))
6838  {
6839  jam();
6840  TableRecordPtr basePtr;
6841  c_tableRecordPool.getPtr(basePtr, tabPtr.p->primaryTableId);
6842  req->userDefinedPartition = (basePtr.p->fragmentType == DictTabInfo::UserDefined);
6843  }
6844 
6845  sendSignal(DBTC_REF, GSN_TC_SCHVERREQ, signal,
6846  TcSchVerReq::SignalLength, JBB);
6847  return;
6848  }
6849 
6850  if (refToBlock(signal->getSendersBlockRef()) == DBDIH) {
6851  jam();
6852  // commit table in DBTC
6853  signal->theData[0] = op_ptr.p->op_key;
6854  signal->theData[1] = reference();
6855  signal->theData[2] = tabPtr.i;
6856 
6857  sendSignal(DBTC_REF, GSN_TAB_COMMITREQ, signal, 3, JBB);
6858  return;
6859  }
6860 
6861  if (refToBlock(signal->getSendersBlockRef()) == DBTC) {
6862  jam();
6863  execute(signal, createTabPtr.p->m_callback, 0);
6864  return;
6865  }
6866 
6867  ndbrequire(false);
6868 }
6869 
6870 void
6871 Dbdict::execTAB_COMMITREF(Signal* signal) {
6872  jamEntry();
6873  ndbrequire(false);
6874 }//execTAB_COMMITREF()
6875 
6876 void
6877 Dbdict::createTab_localComplete(Signal* signal,
6878  Uint32 op_key,
6879  Uint32 ret)
6880 {
6881  jam();
6882 
6883  SchemaOpPtr op_ptr;
6884  CreateTableRecPtr createTabPtr;
6885  findSchemaOp(op_ptr, createTabPtr, op_key);
6886  ndbrequire(!op_ptr.isNull());
6887  //const CreateTabReq* impl_req = &createTabPtr.p->m_request;
6888 
6889  //@todo check for master failed
6890 
6891  if (ERROR_INSERTED(6131)) {
6892  jam();
6893  CLEAR_ERROR_INSERT_VALUE;
6894  setError(op_ptr.p->m_error, 9131, __LINE__);
6895  }
6896 
6897  if (!hasError(op_ptr.p->m_error)) {
6898  jam();
6899  // prepare done
6900  sendTransConf(signal, op_ptr);
6901  } else {
6902  jam();
6903  sendTransRef(signal, op_ptr);
6904  }
6905 }
6906 
6907 // CreateTable: COMMIT
6908 
6909 void
6910 Dbdict::createTable_commit(Signal* signal, SchemaOpPtr op_ptr)
6911 {
6912  jam();
6913  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
6914 
6915  CreateTableRecPtr createTabPtr;
6916  getOpRec(op_ptr, createTabPtr);
6917 
6918  Uint32 tableId = createTabPtr.p->m_request.tableId;
6919  TableRecordPtr tabPtr;
6920  c_tableRecordPool.getPtr(tabPtr, tableId);
6921 
6922  D("createTable_commit" << *op_ptr.p);
6923 
6924  Callback c;
6925  c.m_callbackData = op_ptr.p->op_key;
6926  c.m_callbackFunction = safe_cast(&Dbdict::createTab_alterComplete);
6927  createTab_activate(signal, op_ptr, &c);
6928 
6929  if (DictTabInfo::isIndex(tabPtr.p->tableType))
6930  {
6931  Ptr<TableRecord> basePtr;
6932  c_tableRecordPool.getPtr(basePtr, tabPtr.p->primaryTableId);
6933 
6934  LocalDLFifoList<TableRecord> list(c_tableRecordPool, basePtr.p->m_indexes);
6935  list.add(tabPtr);
6936  }
6937 }
6938 
6939 void
6940 Dbdict::createTab_activate(Signal* signal, SchemaOpPtr op_ptr,
6941  Callback * c)
6942 {
6943  CreateTableRecPtr createTabPtr;
6944  getOpRec(op_ptr, createTabPtr);
6945  createTabPtr.p->m_callback = * c;
6946 
6947  signal->theData[0] = op_ptr.p->op_key;
6948  signal->theData[1] = reference();
6949  signal->theData[2] = createTabPtr.p->m_request.tableId;
6950  sendSignal(DBDIH_REF, GSN_TAB_COMMITREQ, signal, 3, JBB);
6951 }
6952 
6953 void
6954 Dbdict::execTC_SCHVERCONF(Signal* signal)
6955 {
6956  jamEntry();
6957 
6958  SchemaOpPtr op_ptr;
6959  CreateTableRecPtr createTabPtr;
6960  findSchemaOp(op_ptr, createTabPtr, signal->theData[1]);
6961  ndbrequire(!op_ptr.isNull());
6962 
6963  execute(signal, createTabPtr.p->m_callback, 0);
6964 }
6965 
6966 void
6967 Dbdict::createTab_alterComplete(Signal* signal,
6968  Uint32 op_key,
6969  Uint32 ret)
6970 {
6971  jam();
6972 
6973  SchemaOpPtr op_ptr;
6974  CreateTableRecPtr createTabPtr;
6975  findSchemaOp(op_ptr, createTabPtr, op_key);
6976  ndbrequire(!op_ptr.isNull());
6977  const CreateTabReq* impl_req = &createTabPtr.p->m_request;
6978 
6979  TableRecordPtr tabPtr;
6980  c_tableRecordPool.getPtr(tabPtr, impl_req->tableId);
6981 
6982  D("createTab_alterComplete" << *op_ptr.p);
6983 
6984  //@todo check error
6985  //@todo check master failed
6986 
6987  // inform SUMA
6988  {
6989  CreateTabConf* conf = (CreateTabConf*)signal->getDataPtrSend();
6990  conf->senderRef = reference();
6991  conf->senderData = impl_req->tableId; // special usage
6992 #if 0
6993  signal->header.m_noOfSections = 1;
6994  SegmentedSectionPtr tabInfoPtr;
6995  getSection(tabInfoPtr, createTabPtr.p->m_tabInfoPtrI);
6996  signal->setSection(tabInfoPtr, 0);
6997 #endif
6998  sendSignal(SUMA_REF, GSN_CREATE_TAB_CONF, signal,
6999  CreateTabConf::SignalLength, JBB);
7000 #if 0
7001  signal->header.m_noOfSections = 0;
7002 #endif
7003  }
7004 
7005  sendTransConf(signal, op_ptr);
7006 }
7007 
7008 // CreateTable: COMPLETE
7009 
7010 void
7011 Dbdict::createTable_complete(Signal* signal, SchemaOpPtr op_ptr)
7012 {
7013  jam();
7014  sendTransConf(signal, op_ptr);
7015 }
7016 
7017 void
7018 Dbdict::createTable_abortParse(Signal* signal, SchemaOpPtr op_ptr)
7019 {
7020  CreateTableRecPtr createTabPtr;
7021  getOpRec(op_ptr, createTabPtr);
7022  const CreateTabReq* impl_req = &createTabPtr.p->m_request;
7023  const Uint32 tableId = impl_req->tableId;
7024 
7025  D("createTable_abortParse" << V(tableId) << *op_ptr.p);
7026 
7027  do {
7028  if (createTabPtr.p->m_abortPrepareDone)
7029  {
7030  jam();
7031  D("done by abort prepare");
7032  break;
7033  }
7034 
7035  if (tableId == RNIL) {
7036  jam();
7037  D("no table allocated");
7038  break;
7039  }
7040 
7041  TableRecordPtr tabPtr;
7042  c_tableRecordPool.getPtr(tabPtr, tableId);
7043 
7044  // any link was to a new object
7045  if (hasDictObject(op_ptr)) {
7046  jam();
7047  unlinkDictObject(op_ptr);
7048  releaseTableObject(tableId, true);
7049  }
7050  } while (0);
7051 
7052  sendTransConf(signal, op_ptr);
7053 }
7054 
7055 void
7056 Dbdict::createTable_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
7057 {
7058  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
7059  CreateTableRecPtr createTabPtr;
7060  getOpRec(op_ptr, createTabPtr);
7061  const CreateTabReq* impl_req = &createTabPtr.p->m_request;
7062  //const Uint32 tableId = impl_req->tableId;
7063 
7064  D("createTable_abortPrepare" << *op_ptr.p);
7065 
7066  TableRecordPtr tabPtr;
7067  c_tableRecordPool.getPtr(tabPtr, impl_req->tableId);
7068 
7069  // create drop table operation wl3600_todo must pre-allocate
7070 
7071  SchemaOpPtr& oplnk_ptr = op_ptr.p->m_oplnk_ptr;
7072  ndbrequire(oplnk_ptr.isNull());
7073  DropTableRecPtr dropTabPtr;
7074  seizeSchemaOp(oplnk_ptr, dropTabPtr);
7075  ndbrequire(!oplnk_ptr.isNull());
7076  DropTabReq* aux_impl_req = &dropTabPtr.p->m_request;
7077 
7078  aux_impl_req->senderRef = impl_req->senderRef;
7079  aux_impl_req->senderData = impl_req->senderData;
7080  aux_impl_req->requestType = DropTabReq::CreateTabDrop;
7081  aux_impl_req->tableId = impl_req->tableId;
7082  aux_impl_req->tableVersion = impl_req->tableVersion;
7083 
7084  // link other way too
7085  oplnk_ptr.p->m_opbck_ptr = op_ptr;
7086 
7087  // wl3600_todo use ref count
7088  unlinkDictObject(op_ptr);
7089 
7090  dropTabPtr.p->m_block = 0;
7091  dropTabPtr.p->m_blockNo[0] = DBTC;
7092  dropTabPtr.p->m_blockNo[1] = DBLQH; // wait usage + LCP
7093  dropTabPtr.p->m_blockNo[2] = DBDIH; //
7094  dropTabPtr.p->m_blockNo[3] = DBLQH; // release
7095  dropTabPtr.p->m_blockNo[4] = 0;
7096 
7097  dropTabPtr.p->m_callback.m_callbackData =
7098  oplnk_ptr.p->op_key;
7099  dropTabPtr.p->m_callback.m_callbackFunction =
7100  safe_cast(&Dbdict::createTable_abortLocalConf);
7101 
7102  // invoke the "complete" phase of drop table
7103  dropTable_complete_nextStep(signal, oplnk_ptr);
7104 
7105  if (tabPtr.p->m_tablespace_id != RNIL) {
7106  FilegroupPtr ptr;
7107  ndbrequire(c_filegroup_hash.find(ptr, tabPtr.p->m_tablespace_id));
7108  decrease_ref_count(ptr.p->m_obj_ptr_i);
7109  }
7110 }
7111 
7112 void
7113 Dbdict::createTable_abortLocalConf(Signal* signal,
7114  Uint32 oplnk_key,
7115  Uint32 ret)
7116 {
7117  jam();
7118  D("createTable_abortLocalConf" << V(oplnk_key));
7119 
7120  SchemaOpPtr oplnk_ptr;
7121  DropTableRecPtr dropTabPtr;
7122  findSchemaOp(oplnk_ptr, dropTabPtr, oplnk_key);
7123  ndbrequire(!oplnk_ptr.isNull());
7124 
7125  SchemaOpPtr op_ptr = oplnk_ptr.p->m_opbck_ptr;
7126  CreateTableRecPtr createTabPtr;
7127  getOpRec(op_ptr, createTabPtr);
7128  const CreateTabReq* impl_req = &createTabPtr.p->m_request;
7129  Uint32 tableId = impl_req->tableId;
7130 
7131  TableRecordPtr tablePtr;
7132  c_tableRecordPool.getPtr(tablePtr, tableId);
7133 
7134  releaseTableObject(tableId);
7135 
7136  createTabPtr.p->m_abortPrepareDone = true;
7137  sendTransConf(signal, op_ptr);
7138 }
7139 
7140 // CreateTable: MISC
7141 
7142 void
7143 Dbdict::execCREATE_FRAGMENTATION_REF(Signal * signal)
7144 {
7145  // currently not received
7146  ndbrequire(false);
7147 }
7148 
7149 void
7150 Dbdict::execCREATE_FRAGMENTATION_CONF(Signal* signal)
7151 {
7152  // currently not received
7153  ndbrequire(false);
7154 }
7155 
7156 void
7157 Dbdict::execCREATE_TAB_REQ(Signal* signal)
7158 {
7159  // no longer received
7160  ndbrequire(false);
7161 }
7162 
7163 void Dbdict::execCREATE_TABLE_CONF(Signal* signal)
7164 {
7165  jamEntry();
7166  const CreateTableConf* conf = (const CreateTableConf*)signal->getDataPtr();
7167  handleDictConf(signal, conf);
7168 }
7169 
7170 void Dbdict::execCREATE_TABLE_REF(Signal* signal)
7171 {
7172  jamEntry();
7173  const CreateTableRef* ref = (const CreateTableRef*)signal->getDataPtr();
7174  handleDictRef(signal, ref);
7175 }
7176 
7177 void Dbdict::releaseTableObject(Uint32 tableId, bool removeFromHash)
7178 {
7179  TableRecordPtr tablePtr;
7180  c_tableRecordPool.getPtr(tablePtr, tableId);
7181  if (removeFromHash)
7182  {
7183  jam();
7184  release_object(tablePtr.p->m_obj_ptr_i);
7185  tablePtr.p->m_obj_ptr_i = RNIL;
7186  }
7187  else
7188  {
7189  Rope tmp(c_rope_pool, tablePtr.p->tableName);
7190  tmp.erase();
7191  }
7192 
7193  {
7194  Rope tmp(c_rope_pool, tablePtr.p->frmData);
7195  tmp.erase();
7196  }
7197 
7198  {
7199  Rope tmp(c_rope_pool, tablePtr.p->ngData);
7200  tmp.erase();
7201  }
7202 
7203  {
7204  Rope tmp(c_rope_pool, tablePtr.p->rangeData);
7205  tmp.erase();
7206  }
7207 
7208  LocalDLFifoList<AttributeRecord> list(c_attributeRecordPool,
7209  tablePtr.p->m_attributes);
7210  AttributeRecordPtr attrPtr;
7211  for(list.first(attrPtr); !attrPtr.isNull(); list.next(attrPtr)){
7212  Rope name(c_rope_pool, attrPtr.p->attributeName);
7213  Rope def(c_rope_pool, attrPtr.p->defaultValue);
7214  name.erase();
7215  def.erase();
7216  }
7217  list.release();
7218 
7219  {
7220  if (tablePtr.p->m_upgrade_trigger_handling.m_upgrade)
7221  {
7222  jam();
7223  Uint32 triggerId;
7224 
7225  triggerId = tablePtr.p->m_upgrade_trigger_handling.updateTriggerId;
7226  if (triggerId != RNIL)
7227  {
7228  jam();
7229  TriggerRecordPtr triggerPtr;
7230  c_triggerRecordPool.getPtr(triggerPtr, triggerId);
7231  triggerPtr.p->triggerState = TriggerRecord::TS_NOT_DEFINED;
7232  release_object(triggerPtr.p->m_obj_ptr_i);
7233  }
7234 
7235  triggerId = tablePtr.p->m_upgrade_trigger_handling.deleteTriggerId;
7236  if (triggerId != RNIL)
7237  {
7238  jam();
7239  TriggerRecordPtr triggerPtr;
7240  c_triggerRecordPool.getPtr(triggerPtr, triggerId);
7241  triggerPtr.p->triggerState = TriggerRecord::TS_NOT_DEFINED;
7242  release_object(triggerPtr.p->m_obj_ptr_i);
7243  }
7244  }
7245  }
7246 
7247 }//releaseTableObject()
7248 
7249 // CreateTable: END
7250 
7251 // MODULE: DropTable
7252 
7253 const Dbdict::OpInfo
7254 Dbdict::DropTableRec::g_opInfo = {
7255  { 'D', 'T', 'a', 0 },
7256  GSN_DROP_TAB_REQ,
7257  DropTabReq::SignalLength,
7258  //
7259  &Dbdict::dropTable_seize,
7260  &Dbdict::dropTable_release,
7261  //
7262  &Dbdict::dropTable_parse,
7263  &Dbdict::dropTable_subOps,
7264  &Dbdict::dropTable_reply,
7265  //
7266  &Dbdict::dropTable_prepare,
7267  &Dbdict::dropTable_commit,
7268  &Dbdict::dropTable_complete,
7269  //
7270  &Dbdict::dropTable_abortParse,
7271  &Dbdict::dropTable_abortPrepare
7272 };
7273 
7274 bool
7275 Dbdict::dropTable_seize(SchemaOpPtr op_ptr)
7276 {
7277  return seizeOpRec<DropTableRec>(op_ptr);
7278 }
7279 
7280 void
7281 Dbdict::dropTable_release(SchemaOpPtr op_ptr)
7282 {
7283  releaseOpRec<DropTableRec>(op_ptr);
7284 }
7285 
7286 void
7287 Dbdict::execDROP_TABLE_REQ(Signal* signal)
7288 {
7289  jamEntry();
7290  if (!assembleFragments(signal)) {
7291  jam();
7292  return;
7293  }
7294  SectionHandle handle(this, signal);
7295 
7296  if (check_sender_version(signal, MAKE_VERSION(6,4,0)) < 0)
7297  {
7298  jam();
7303  DropTableReq * tmp = (DropTableReq*)signal->getDataPtr();
7304  do_swap(tmp->senderRef, tmp->senderData);
7305  }
7306 
7307  const DropTableReq req_copy =
7308  *(const DropTableReq*)signal->getDataPtr();
7309  const DropTableReq* req = &req_copy;
7310 
7311  ErrorInfo error;
7312  do {
7313  SchemaOpPtr op_ptr;
7314  DropTableRecPtr dropTabPtr;
7315  DropTabReq* impl_req;
7316 
7317  startClientReq(op_ptr, dropTabPtr, req, impl_req, error);
7318  if (hasError(error)) {
7319  jam();
7320  break;
7321  }
7322 
7323  impl_req->tableId = req->tableId;
7324  impl_req->tableVersion = req->tableVersion;
7325 
7326  handleClientReq(signal, op_ptr, handle);
7327  return;
7328  } while (0);
7329 
7330  releaseSections(handle);
7331 
7332  DropTableRef* ref = (DropTableRef*)signal->getDataPtrSend();
7333  ref->senderRef = reference();
7334  ref->clientData = req->clientData;
7335  ref->transId = req->transId;
7336  ref->tableId = req->tableId;
7337  ref->tableVersion = req->tableVersion;
7338  getError(error, ref);
7339  sendSignal(req->clientRef, GSN_DROP_TABLE_REF, signal,
7340  DropTableRef::SignalLength, JBB);
7341 }
7342 
7343 // DropTable: PARSE
7344 
7345 void
7346 Dbdict::dropTable_parse(Signal* signal, bool master,
7347  SchemaOpPtr op_ptr,
7348  SectionHandle& handle, ErrorInfo& error)
7349 {
7350  D("dropTable_parse" << V(op_ptr.i) << *op_ptr.p);
7351 
7352  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
7353  DropTableRecPtr dropTabPtr;
7354  getOpRec(op_ptr, dropTabPtr);
7355  DropTabReq* impl_req = &dropTabPtr.p->m_request;
7356  Uint32 tableId = impl_req->tableId;
7357 
7358  TableRecordPtr tablePtr;
7359  if (!(tableId < c_tableRecordPool.getSize())) {
7360  jam();
7361  setError(error, DropTableRef::NoSuchTable, __LINE__);
7362  return;
7363  }
7364  c_tableRecordPool.getPtr(tablePtr, impl_req->tableId);
7365 
7366  // check version first (api will retry)
7367  if (tablePtr.p->tableVersion != impl_req->tableVersion) {
7368  jam();
7369  setError(error, DropTableRef::InvalidTableVersion, __LINE__);
7370  return;
7371  }
7372 
7373  if (tablePtr.p->m_read_locked)
7374  {
7375  jam();
7376  setError(error, DropTableRef::BackupInProgress, __LINE__);
7377  return;
7378  }
7379 
7380  if (check_write_obj(tablePtr.i,
7381  trans_ptr.p->m_transId,
7382  SchemaFile::SF_DROP, error))
7383  {
7384  jam();
7385  return;
7386  }
7387 
7388  // link operation to object
7389  {
7390  DictObjectPtr obj_ptr;
7391  Uint32 obj_ptr_i = tablePtr.p->m_obj_ptr_i;
7392  bool ok = findDictObject(op_ptr, obj_ptr, obj_ptr_i);
7393  ndbrequire(ok);
7394  }
7395 
7396  if (ERROR_INSERTED(6121)) {
7397  jam();
7398  CLEAR_ERROR_INSERT_VALUE;
7399  setError(error, 9121, __LINE__);
7400  return;
7401  }
7402 
7403  SchemaFile::TableEntry te; te.init();
7404  te.m_tableState = SchemaFile::SF_DROP;
7405  te.m_transId = trans_ptr.p->m_transId;
7406  Uint32 err = trans_log_schema_op(op_ptr, tableId, &te);
7407  if (err)
7408  {
7409  jam();
7410  setError(error, err, __LINE__);
7411  return;
7412  }
7413 }
7414 
7415 bool
7416 Dbdict::dropTable_subOps(Signal* signal, SchemaOpPtr op_ptr)
7417 {
7418  D("dropTable_subOps" << V(op_ptr.i) << *op_ptr.p);
7419  // wl3600_todo blobs, indexes, events
7420  return false;
7421 }
7422 
7423 void
7424 Dbdict::dropTable_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
7425 {
7426  jam();
7427  D("dropTable_reply" << V(op_ptr.i) << *op_ptr.p);
7428 
7429  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
7430 
7431  DropTableRecPtr dropTabPtr;
7432  getOpRec(op_ptr, dropTabPtr);
7433 
7434  if (!hasError(error)) {
7435  DropTableConf* conf = (DropTableConf*)signal->getDataPtrSend();
7436  conf->senderRef = reference();
7437  conf->clientData = op_ptr.p->m_clientData;
7438  conf->transId = trans_ptr.p->m_transId;
7439  conf->tableId = dropTabPtr.p->m_request.tableId;
7440  conf->tableVersion = dropTabPtr.p->m_request.tableVersion;
7441 
7442  D(V(conf->tableId) << V(conf->tableVersion));
7443 
7444  Uint32 clientRef = op_ptr.p->m_clientRef;
7445  sendSignal(clientRef, GSN_DROP_TABLE_CONF, signal,
7446  DropTableConf::SignalLength, JBB);
7447  } else {
7448  jam();
7449  DropTableRef* ref = (DropTableRef*)signal->getDataPtrSend();
7450  ref->senderRef = reference();
7451  ref->clientData = op_ptr.p->m_clientData;
7452  ref->transId = trans_ptr.p->m_transId;
7453  ref->tableId = dropTabPtr.p->m_request.tableId;
7454  ref->tableVersion = dropTabPtr.p->m_request.tableVersion;
7455  getError(error, ref);
7456 
7457  Uint32 clientRef = op_ptr.p->m_clientRef;
7458  sendSignal(clientRef, GSN_DROP_TABLE_REF, signal,
7459  DropTableRef::SignalLength, JBB);
7460  }
7461 }
7462 
7463 // DropTable: PREPARE
7464 
7465 void
7466 Dbdict::dropTable_prepare(Signal* signal, SchemaOpPtr op_ptr)
7467 {
7468  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
7469 
7470  DropTableRecPtr dropTabPtr;
7471  getOpRec(op_ptr, dropTabPtr);
7472 
7473  D("dropTable_prepare" << *op_ptr.p);
7474 
7475  Mutex mutex(signal, c_mutexMgr, dropTabPtr.p->m_define_backup_mutex);
7476  Callback c = {
7477  safe_cast(&Dbdict::dropTable_backup_mutex_locked),
7478  op_ptr.p->op_key
7479  };
7480  bool ok = mutex.lock(c);
7481  ndbrequire(ok);
7482  return;
7483 }
7484 
7485 void
7486 Dbdict::dropTable_backup_mutex_locked(Signal* signal,
7487  Uint32 op_key,
7488  Uint32 ret)
7489 {
7490  jamEntry();
7491  D("dropTable_backup_mutex_locked");
7492 
7493  ndbrequire(ret == 0);
7494 
7495  SchemaOpPtr op_ptr;
7496  DropTableRecPtr dropTabPtr;
7497  findSchemaOp(op_ptr, dropTabPtr, op_key);
7498  ndbrequire(!op_ptr.isNull());
7499  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
7500  const DropTabReq* impl_req = &dropTabPtr.p->m_request;
7501 
7502  TableRecordPtr tablePtr;
7503  c_tableRecordPool.getPtr(tablePtr, impl_req->tableId);
7504 
7505  Mutex mutex(signal, c_mutexMgr, dropTabPtr.p->m_define_backup_mutex);
7506  mutex.unlock(); // ignore response
7507 
7508  if (tablePtr.p->m_read_locked)
7509  {
7510  jam();
7511  setError(op_ptr, AlterTableRef::BackupInProgress, __LINE__);
7512  sendTransRef(signal, op_ptr);
7513  return;
7514  }
7515 
7516  sendTransConf(signal, op_ptr);
7517 }
7518 // DropTable: COMMIT
7519 
7520 void
7521 Dbdict::dropTable_commit(Signal* signal, SchemaOpPtr op_ptr)
7522 {
7523  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
7524 
7525  DropTableRecPtr dropTabPtr;
7526  getOpRec(op_ptr, dropTabPtr);
7527 
7528  D("dropTable_commit" << *op_ptr.p);
7529 
7530  TableRecordPtr tablePtr;
7531  c_tableRecordPool.getPtr(tablePtr, dropTabPtr.p->m_request.tableId);
7532 
7533  if (tablePtr.p->m_tablespace_id != RNIL)
7534  {
7535  FilegroupPtr ptr;
7536  ndbrequire(c_filegroup_hash.find(ptr, tablePtr.p->m_tablespace_id));
7537  decrease_ref_count(ptr.p->m_obj_ptr_i);
7538  }
7539 
7540  if (g_trace)
7541  // from a newer execDROP_TAB_REQ version
7542  {
7543  char buf[1024];
7544  Rope name(c_rope_pool, tablePtr.p->tableName);
7545  name.copy(buf);
7546  g_eventLogger->info("Dbdict: drop name=%s,id=%u,obj_id=%u", buf, tablePtr.i,
7547  tablePtr.p->m_obj_ptr_i);
7548  }
7549 
7550  send_event(signal, trans_ptr,
7551  NDB_LE_DropSchemaObject,
7552  tablePtr.i,
7553  tablePtr.p->tableVersion,
7554  tablePtr.p->tableType);
7555 
7556  if (DictTabInfo::isIndex(tablePtr.p->tableType))
7557  {
7558  Ptr<TableRecord> basePtr;
7559  c_tableRecordPool.getPtr(basePtr, tablePtr.p->primaryTableId);
7560 
7561  LocalDLFifoList<TableRecord> list(c_tableRecordPool, basePtr.p->m_indexes);
7562  list.remove(tablePtr);
7563  }
7564  dropTabPtr.p->m_block = 0;
7565  dropTabPtr.p->m_blockNo[0] = DBLQH;
7566  dropTabPtr.p->m_blockNo[1] = DBTC;
7567  dropTabPtr.p->m_blockNo[2] = DBDIH;
7568  dropTabPtr.p->m_blockNo[3] = 0;
7569  dropTable_commit_nextStep(signal, op_ptr);
7570 }
7571 
7572 
7573 void
7574 Dbdict::dropTable_commit_nextStep(Signal* signal, SchemaOpPtr op_ptr)
7575 {
7576  DropTableRecPtr dropTabPtr;
7577  getOpRec(op_ptr, dropTabPtr);
7578  const DropTabReq* impl_req = &dropTabPtr.p->m_request;
7579 
7583  ndbrequire(!hasError(op_ptr.p->m_error));
7584 
7585  Uint32 block = dropTabPtr.p->m_block;
7586  Uint32 blockNo = dropTabPtr.p->m_blockNo[block];
7587  D("dropTable_commit_nextStep" << hex << V(blockNo) << *op_ptr.p);
7588 
7589  if (blockNo == 0)
7590  {
7591  jam();
7592  dropTable_commit_done(signal, op_ptr);
7593  return;
7594  }
7595 
7596  if (ERROR_INSERTED(6131) &&
7597  blockNo == DBDIH) {
7598  jam();
7599  CLEAR_ERROR_INSERT_VALUE;
7600 
7601  PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
7602  ref->senderRef = numberToRef(block, getOwnNodeId());
7603  ref->senderData = op_ptr.p->op_key;
7604  ref->tableId = impl_req->tableId;
7605  ref->errorCode = 9131;
7606  sendSignal(reference(), GSN_PREP_DROP_TAB_REF, signal,
7607  PrepDropTabRef::SignalLength, JBB);
7608  return;
7609  }
7610 
7611 
7612  PrepDropTabReq* prep = (PrepDropTabReq*)signal->getDataPtrSend();
7613  prep->senderRef = reference();
7614  prep->senderData = op_ptr.p->op_key;
7615  prep->tableId = impl_req->tableId;
7616  prep->requestType = impl_req->requestType;
7617 
7618  BlockReference ref = numberToRef(blockNo, getOwnNodeId());
7619  sendSignal(ref, GSN_PREP_DROP_TAB_REQ, signal,
7620  PrepDropTabReq::SignalLength, JBB);
7621 }
7622 
7623 void
7624 Dbdict::execPREP_DROP_TAB_REQ(Signal* signal)
7625 {
7626  // no longer received
7627  ndbrequire(false);
7628 }
7629 
7630 void
7631 Dbdict::execPREP_DROP_TAB_CONF(Signal * signal)
7632 {
7633  jamEntry();
7634  const PrepDropTabConf* conf = (const PrepDropTabConf*)signal->getDataPtr();
7635 
7636  Uint32 nodeId = refToNode(conf->senderRef);
7637  Uint32 block = refToBlock(conf->senderRef);
7638  ndbrequire(nodeId == getOwnNodeId() && block != DBDICT);
7639 
7640  dropTable_commit_fromLocal(signal, conf->senderData, 0);
7641 }
7642 
7643 void
7644 Dbdict::execPREP_DROP_TAB_REF(Signal* signal)
7645 {
7646  jamEntry();
7647  const PrepDropTabRef* ref = (const PrepDropTabRef*)signal->getDataPtr();
7648 
7649  Uint32 nodeId = refToNode(ref->senderRef);
7650  Uint32 block = refToBlock(ref->senderRef);
7651  ndbrequire(nodeId == getOwnNodeId() && block != DBDICT);
7652 
7653  Uint32 errorCode = ref->errorCode;
7654  ndbrequire(errorCode != 0);
7655 
7656  if (errorCode == PrepDropTabRef::NoSuchTable && block == DBLQH)
7657  {
7658  jam();
7663  errorCode = 0;
7664  }
7665  dropTable_commit_fromLocal(signal, ref->senderData, errorCode);
7666 }
7667 
7668 void
7669 Dbdict::dropTable_commit_fromLocal(Signal* signal, Uint32 op_key, Uint32 errorCode)
7670 {
7671  SchemaOpPtr op_ptr;
7672  DropTableRecPtr dropTabPtr;
7673  findSchemaOp(op_ptr, dropTabPtr, op_key);
7674  ndbrequire(!op_ptr.isNull());
7675 
7676  if (errorCode != 0)
7677  {
7678  jam();
7679  setError(op_ptr, errorCode, __LINE__);
7680  }
7681 
7682  dropTabPtr.p->m_block++;
7683  dropTable_commit_nextStep(signal, op_ptr);
7684 }
7685 
7686 void
7687 Dbdict::dropTable_commit_done(Signal* signal, SchemaOpPtr op_ptr)
7688 {
7689  jam();
7690  D("dropTable_commit_done");
7691 
7692  sendTransConf(signal, op_ptr);
7693 }
7694 
7695 // DropTable: COMPLETE
7696 
7697 void
7698 Dbdict::dropTable_complete(Signal* signal, SchemaOpPtr op_ptr)
7699 {
7700  jam();
7701 
7702  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
7703 
7704  DropTableRecPtr dropTabPtr;
7705  getOpRec(op_ptr, dropTabPtr);
7706 
7707  TableRecordPtr tablePtr;
7708  c_tableRecordPool.getPtr(tablePtr, dropTabPtr.p->m_request.tableId);
7709 
7710  dropTabPtr.p->m_block = 0;
7711  dropTabPtr.p->m_blockNo[0] = DBTC;
7712  dropTabPtr.p->m_blockNo[1] = DBLQH; // wait usage + LCP
7713  dropTabPtr.p->m_blockNo[2] = DBDIH; //
7714  dropTabPtr.p->m_blockNo[3] = DBLQH; // release
7715  dropTabPtr.p->m_blockNo[4] = 0;
7716  dropTabPtr.p->m_callback.m_callbackData =
7717  op_ptr.p->op_key;
7718  dropTabPtr.p->m_callback.m_callbackFunction =
7719  safe_cast(&Dbdict::dropTable_complete_done);
7720 
7721  dropTable_complete_nextStep(signal, op_ptr);
7722 }
7723 
7724 void
7725 Dbdict::dropTable_complete_nextStep(Signal* signal, SchemaOpPtr op_ptr)
7726 {
7727  DropTableRecPtr dropTabPtr;
7728  getOpRec(op_ptr, dropTabPtr);
7729  const DropTabReq* impl_req = &dropTabPtr.p->m_request;
7730 
7734  ndbrequire(!hasError(op_ptr.p->m_error));
7735 
7736  TableRecordPtr tablePtr;
7737  c_tableRecordPool.getPtr(tablePtr, impl_req->tableId);
7738 
7739  Uint32 block = dropTabPtr.p->m_block;
7740  Uint32 blockNo = dropTabPtr.p->m_blockNo[block];
7741  D("dropTable_complete_nextStep" << hex << V(blockNo) << *op_ptr.p);
7742 
7743  if (blockNo == 0)
7744  {
7745  jam();
7746  execute(signal, dropTabPtr.p->m_callback, 0);
7747  return;
7748  }
7749 
7750  DropTabReq* req = (DropTabReq*)signal->getDataPtrSend();
7751  req->senderRef = reference();
7752  req->senderData = op_ptr.p->op_key;
7753  req->tableId = impl_req->tableId;
7754  req->requestType = impl_req->requestType;
7755 
7756  BlockReference ref = numberToRef(blockNo, getOwnNodeId());
7757  sendSignal(ref, GSN_DROP_TAB_REQ, signal,
7758  DropTabReq::SignalLength, JBB);
7759 }
7760 
7761 void
7762 Dbdict::execDROP_TAB_CONF(Signal* signal)
7763 {
7764  jamEntry();
7765  const DropTabConf* conf = (const DropTabConf*)signal->getDataPtr();
7766 
7767  Uint32 nodeId = refToNode(conf->senderRef);
7768  Uint32 block = refToBlock(conf->senderRef);
7769  ndbrequire(nodeId == getOwnNodeId() && block != DBDICT);
7770 
7771  dropTable_complete_fromLocal(signal, conf->senderData);
7772 }
7773 
7774 void
7775 Dbdict::execDROP_TAB_REF(Signal* signal)
7776 {
7777  jamEntry();
7778  const DropTabRef* ref = (const DropTabRef*)signal->getDataPtr();
7779 
7780  Uint32 nodeId = refToNode(ref->senderRef);
7781  Uint32 block = refToBlock(ref->senderRef);
7782  ndbrequire(nodeId == getOwnNodeId() && block != DBDICT);
7783  ndbrequire(ref->errorCode == DropTabRef::NoSuchTable);
7784 
7785  dropTable_complete_fromLocal(signal, ref->senderData);
7786 }
7787 
7788 void
7789 Dbdict::dropTable_complete_fromLocal(Signal* signal, Uint32 op_key)
7790 {
7791  jamEntry();
7792 
7793  SchemaOpPtr op_ptr;
7794  DropTableRecPtr dropTabPtr;
7795  findSchemaOp(op_ptr, dropTabPtr, op_key);
7796  ndbrequire(!op_ptr.isNull());
7797  //const DropTabReq* impl_req = &dropTabPtr.p->m_request;
7798 
7799  D("dropTable_complete_fromLocal" << *op_ptr.p);
7800 
7801  dropTabPtr.p->m_block++;
7802  dropTable_complete_nextStep(signal, op_ptr);
7803 }
7804 
7805 void
7806 Dbdict::dropTable_complete_done(Signal* signal,
7807  Uint32 op_key,
7808  Uint32 ret)
7809 {
7810  jam();
7811 
7812  SchemaOpPtr op_ptr;
7813  DropTableRecPtr dropTabPtr;
7814  findSchemaOp(op_ptr, dropTabPtr, op_key);
7815  ndbrequire(!op_ptr.isNull());
7816  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
7817 
7818  Uint32 tableId = dropTabPtr.p->m_request.tableId;
7819 
7820  unlinkDictObject(op_ptr);
7821  releaseTableObject(tableId);
7822 
7823  // inform SUMA
7824  {
7825  DropTabConf* conf = (DropTabConf*)signal->getDataPtrSend();
7826 
7827  // special use of senderRef
7828  if (trans_ptr.p->m_isMaster) {
7829  jam();
7830  conf->senderRef = trans_ptr.p->m_clientRef;
7831  } else {
7832  jam();
7833  conf->senderRef = 0;
7834  }
7835  conf->senderData = op_key;
7836  conf->tableId = tableId;
7837  sendSignal(SUMA_REF, GSN_DROP_TAB_CONF, signal,
7838  DropTabConf::SignalLength, JBB);
7839  }
7840 
7841  sendTransConf(signal, trans_ptr);
7842 }
7843 
7844 // DropTable: ABORT
7845 
7846 void
7847 Dbdict::dropTable_abortParse(Signal* signal, SchemaOpPtr op_ptr)
7848 {
7849  D("dropTable_abortParse" << *op_ptr.p);
7850 
7851  sendTransConf(signal, op_ptr);
7852 }
7853 
7854 void
7855 Dbdict::dropTable_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
7856 {
7857  D("dropTable_abortPrepare" << *op_ptr.p);
7858 
7859  sendTransConf(signal, op_ptr);
7860 }
7861 
7862 // DropTable: MISC
7863 
7864 void Dbdict::execDROP_TABLE_CONF(Signal* signal)
7865 {
7866  jamEntry();
7867  const DropTableConf* conf = (const DropTableConf*)signal->getDataPtr();
7868  handleDictConf(signal, conf);
7869 }
7870 
7871 void Dbdict::execDROP_TABLE_REF(Signal* signal)
7872 {
7873  jamEntry();
7874  const DropTableRef* ref = (const DropTableRef*)signal->getDataPtr();
7875  handleDictRef(signal, ref);
7876 }
7877 
7878 // DropTable: END
7879 
7880 // MODULE: AlterTable
7881 
7882 const Dbdict::OpInfo
7883 Dbdict::AlterTableRec::g_opInfo = {
7884  { 'A', 'T', 'a', 0 },
7885  GSN_ALTER_TAB_REQ,
7886  AlterTabReq::SignalLength,
7887  //
7888  &Dbdict::alterTable_seize,
7889  &Dbdict::alterTable_release,
7890  //
7891  &Dbdict::alterTable_parse,
7892  &Dbdict::alterTable_subOps,
7893  &Dbdict::alterTable_reply,
7894  //
7895  &Dbdict::alterTable_prepare,
7896  &Dbdict::alterTable_commit,
7897  &Dbdict::alterTable_complete,
7898  //
7899  &Dbdict::alterTable_abortParse,
7900  &Dbdict::alterTable_abortPrepare
7901 };
7902 
7903 bool
7904 Dbdict::alterTable_seize(SchemaOpPtr op_ptr)
7905 {
7906  return seizeOpRec<AlterTableRec>(op_ptr);
7907 }
7908 
7909 void
7910 Dbdict::alterTable_release(SchemaOpPtr op_ptr)
7911 {
7912  AlterTableRecPtr alterTabPtr;
7913  getOpRec(op_ptr, alterTabPtr);
7914  {
7915  Rope r(c_rope_pool, alterTabPtr.p->m_oldTableName);
7916  r.erase();
7917  }
7918  {
7919  Rope r(c_rope_pool, alterTabPtr.p->m_oldFrmData);
7920  r.erase();
7921  }
7922  releaseOpRec<AlterTableRec>(op_ptr);
7923 }
7924 
7925 bool
7926 Dbdict::check_ndb_versions() const
7927 {
7928  Uint32 node = 0;
7929  Uint32 version = getNodeInfo(getOwnNodeId()).m_version;
7930  while((node = c_aliveNodes.find(node + 1)) != BitmaskImpl::NotFound)
7931  {
7932  if(getNodeInfo(node).m_version != version)
7933  {
7934  return false;
7935  }
7936  }
7937  return true;
7938 }
7939 
7940 int
7941 Dbdict::check_sender_version(const Signal* signal, Uint32 version) const
7942 {
7943  Uint32 ver = getNodeInfo(refToNode(signal->getSendersBlockRef())).m_version;
7944  if (ver < version)
7945  return -1;
7946  else if (ver > version)
7947  return 1;
7948  return 0;
7949 }
7950 
7951 void
7952 Dbdict::execALTER_TABLE_REQ(Signal* signal)
7953 {
7954  jamEntry();
7955 
7956  if (!assembleFragments(signal)) {
7957  jam();
7958  return;
7959  }
7960  SectionHandle handle(this, signal);
7961 
7962  if (check_sender_version(signal, MAKE_VERSION(6,4,0)) < 0)
7963  {
7964  jam();
7969  AlterTableReq * tmp = (AlterTableReq*)signal->getDataPtr();
7970  do_swap(tmp->clientRef, tmp->clientData);
7971  }
7972 
7973  const AlterTableReq req_copy =
7974  *(const AlterTableReq*)signal->getDataPtr();
7975  const AlterTableReq* req = &req_copy;
7976 
7977  ErrorInfo error;
7978  do {
7979  SchemaOpPtr op_ptr;
7980  AlterTableRecPtr alterTabPtr;
7981  AlterTabReq* impl_req;
7982 
7983  startClientReq(op_ptr, alterTabPtr, req, impl_req, error);
7984  if (hasError(error)) {
7985  jam();
7986  break;
7987  }
7988 
7989  impl_req->tableId = req->tableId;
7990  impl_req->tableVersion = req->tableVersion;
7991  impl_req->newTableVersion = 0; // set in master parse
7992  impl_req->gci = 0;
7993  impl_req->changeMask = req->changeMask;
7994  impl_req->connectPtr = RNIL; // set from TUP
7995  impl_req->noOfNewAttr = 0; // set these in master parse
7996  impl_req->newNoOfCharsets = 0;
7997  impl_req->newNoOfKeyAttrs = 0;
7998 
7999  handleClientReq(signal, op_ptr, handle);
8000  return;
8001  } while (0);
8002 
8003  releaseSections(handle);
8004 
8005  AlterTableRef* ref = (AlterTableRef*)signal->getDataPtrSend();
8006  ref->senderRef = reference();
8007  ref->clientData = req->clientData;
8008  ref->transId = req->transId;
8009  getError(error, ref);
8010  sendSignal(req->clientRef, GSN_ALTER_TABLE_REF, signal,
8011  AlterTableRef::SignalLength, JBB);
8012 }
8013 
8014 // AlterTable: PARSE
8015 
8016 void
8017 Dbdict::alterTable_parse(Signal* signal, bool master,
8018  SchemaOpPtr op_ptr,
8019  SectionHandle& handle, ErrorInfo& error)
8020 {
8021  D("alterTable_parse");
8022 
8023  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
8024  AlterTableRecPtr alterTabPtr;
8025  getOpRec(op_ptr, alterTabPtr);
8026  AlterTabReq* impl_req = &alterTabPtr.p->m_request;
8027 
8028  if (AlterTableReq::getReorgSubOp(impl_req->changeMask))
8029  {
8033  if (master && op_ptr.p->m_base_op_ptr_i == RNIL)
8034  {
8035  jam();
8036  setError(error, AlterTableRef::Inconsistency, __LINE__);
8037  return;
8038  }
8039 
8040  return;
8041  }
8042 
8043  // get table definition
8044  TableRecordPtr tablePtr;
8045  if (!(impl_req->tableId < c_tableRecordPool.getSize())) {
8046  jam();
8047  setError(error, AlterTableRef::NoSuchTable, __LINE__);
8048  return;
8049  }
8050  c_tableRecordPool.getPtr(tablePtr, impl_req->tableId);
8051 
8052  if (tablePtr.p->m_read_locked)
8053  {
8054  jam();
8055  setError(error, tablePtr.p->m_read_locked, __LINE__);
8056  return;
8057  }
8058 
8059  if (check_write_obj(tablePtr.i, trans_ptr.p->m_transId,
8060  SchemaFile::SF_ALTER, error))
8061  {
8062  jam();
8063  return;
8064  }
8065 
8066  // save it for abort code
8067  alterTabPtr.p->m_tablePtr = tablePtr;
8068 
8069  if (tablePtr.p->tableVersion != impl_req->tableVersion) {
8070  jam();
8071  setError(error, AlterTableRef::InvalidTableVersion, __LINE__);
8072  return;
8073  }
8074 
8075  // parse new table definition into new table record
8076  TableRecordPtr& newTablePtr = alterTabPtr.p->m_newTablePtr; // ref
8077  {
8078  ParseDictTabInfoRecord parseRecord;
8079  parseRecord.requestType = DictTabInfo::AlterTableFromAPI;
8080  parseRecord.errorCode = 0;
8081 
8082  SegmentedSectionPtr ptr;
8083  bool ok = handle.getSection(ptr, AlterTableReq::DICT_TAB_INFO);
8084  ndbrequire(ok);
8085  SimplePropertiesSectionReader r(ptr, getSectionSegmentPool());
8086 
8087  handleTabInfoInit(signal,
8088  trans_ptr, r, &parseRecord, false); // Will not save info
8089 
8090  if (parseRecord.errorCode != 0) {
8091  jam();
8092  setError(error, parseRecord);
8093  return;
8094  }
8095 
8096  // the new temporary table record seized from pool
8097  newTablePtr = parseRecord.tablePtr;
8098  alterTabPtr.p->m_newTable_realObjectId = newTablePtr.p->tableId;
8099  newTablePtr.p->tableId = impl_req->tableId; // set correct table id...(not the temporary)
8100  }
8101 
8102 
8103  {
8108  SchemaFile::TableEntry * objEntry =
8109  objEntry = getTableEntry(alterTabPtr.p->m_newTable_realObjectId);
8110  objEntry->m_tableType = DictTabInfo::SchemaTransaction;
8111  objEntry->m_tableState = SchemaFile::SF_STARTED;
8112  objEntry->m_transId = trans_ptr.p->m_transId + 1;
8113  }
8114 
8115  // set the new version now
8116  impl_req->newTableVersion =
8117  newTablePtr.p->tableVersion =
8118  alter_obj_inc_schema_version(tablePtr.p->tableVersion);
8119 
8120  // rename stuff
8121  {
8122  ConstRope r1(c_rope_pool, tablePtr.p->tableName);
8123  ConstRope r2(c_rope_pool, newTablePtr.p->tableName);
8124 
8125  char name[MAX_TAB_NAME_SIZE];
8126  r2.copy(name);
8127 
8128  if (r1.compare(name) != 0)
8129  {
8130  jam();
8131  if (get_object(name) != 0)
8132  {
8133  jam();
8134  setError(error, CreateTableRef::TableAlreadyExist, __LINE__);
8135  return;
8136  }
8137 
8138  if (master)
8139  {
8140  jam();
8141  AlterTableReq::setNameFlag(impl_req->changeMask, 1);
8142  }
8143  else if (!AlterTableReq::getNameFlag(impl_req->changeMask))
8144  {
8145  jam();
8146  setError(error, AlterTableRef::Inconsistency, __LINE__);
8147  return;
8148  }
8149  }
8150  else if (AlterTableReq::getNameFlag(impl_req->changeMask))
8151  {
8152  jam();
8153  setError(error, AlterTableRef::Inconsistency, __LINE__);
8154  return;
8155  }
8156  }
8157 
8158  // frm stuff
8159  {
8160  ConstRope r1(c_rope_pool, tablePtr.p->frmData);
8161  ConstRope r2(c_rope_pool, newTablePtr.p->frmData);
8162  if (!r1.equal(r2))
8163  {
8164  if (master)
8165  {
8166  jam();
8167  AlterTableReq::setFrmFlag(impl_req->changeMask, 1);
8168  }
8169  else if (!AlterTableReq::getFrmFlag(impl_req->changeMask))
8170  {
8171  jam();
8172  setError(error, AlterTableRef::Inconsistency, __LINE__);
8173  return;
8174  }
8175  }
8176  else if (AlterTableReq::getFrmFlag(impl_req->changeMask))
8177  {
8178  jam();
8179  setError(error, AlterTableRef::Inconsistency, __LINE__);
8180  return;
8181  }
8182  }
8183 
8184  // add attribute stuff
8185  {
8186  const Uint32 noOfNewAttr =
8187  newTablePtr.p->noOfAttributes - tablePtr.p->noOfAttributes;
8188 
8189  if (newTablePtr.p->noOfAttributes > tablePtr.p->noOfAttributes)
8190  {
8191  if (master)
8192  {
8193  jam();
8194  AlterTableReq::setAddAttrFlag(impl_req->changeMask, 1);
8195  }
8196  else if (!AlterTableReq::getAddAttrFlag(impl_req->changeMask))
8197  {
8198  jam();
8199  setError(error, AlterTableRef::Inconsistency, __LINE__);
8200  return;
8201  }
8202  }
8203  else if (AlterTableReq::getAddAttrFlag(impl_req->changeMask))
8204  {
8205  jam();
8206  setError(error, AlterTableRef::Inconsistency, __LINE__);
8207  return;
8208  }
8209  else if (newTablePtr.p->noOfAttributes < tablePtr.p->noOfAttributes)
8210  {
8211  jam();
8212  setError(error, AlterTableRef::UnsupportedChange, __LINE__);
8213  return;
8214  }
8215 
8216  if (master)
8217  {
8218  jam();
8219  impl_req->noOfNewAttr = noOfNewAttr;
8220  impl_req->newNoOfCharsets = newTablePtr.p->noOfCharsets;
8221  impl_req->newNoOfKeyAttrs = newTablePtr.p->noOfPrimkey;
8222  }
8223  else if (impl_req->noOfNewAttr != noOfNewAttr)
8224  {
8225  jam();
8226  setError(error, AlterTableRef::Inconsistency, __LINE__);
8227  return;
8228  }
8229 
8231  list(c_attributeRecordPool, newTablePtr.p->m_attributes);
8232  AttributeRecordPtr attrPtr;
8233  list.first(attrPtr);
8234  Uint32 i = 0;
8235  for (i = 0; i < newTablePtr.p->noOfAttributes; i++) {
8236  if (i >= tablePtr.p->noOfAttributes) {
8237  jam();
8238  Uint32 j = 2 * (i - tablePtr.p->noOfAttributes);
8239  alterTabPtr.p->m_newAttrData[j + 0] = attrPtr.p->attributeDescriptor;
8240  alterTabPtr.p->m_newAttrData[j + 1] = attrPtr.p->extPrecision & ~0xFFFF;
8241  }
8242  list.next(attrPtr);
8243  }
8244  }
8245 
8246  if (AlterTableReq::getAddFragFlag(impl_req->changeMask))
8247  {
8248  if (newTablePtr.p->fragmentType != DictTabInfo::HashMapPartition)
8249  {
8250  jam();
8251  setError(error, AlterTableRef::UnsupportedChange, __LINE__);
8252  return;
8253  }
8254 
8258  if (ERROR_INSERTED(6212))
8259  {
8260  CLEAR_ERROR_INSERT_VALUE;
8261  setError(error, 1, __LINE__);
8262  return;
8263  }
8264 
8265  Uint32 err;
8266  if ((err = check_supported_reorg(tablePtr.p->hashMapObjectId,
8267  newTablePtr.p->hashMapObjectId)))
8268  {
8269  jam();
8270  setError(error, AlterTableRef::UnsupportedChange, __LINE__);
8271  return;
8272  }
8273 
8274  if (tablePtr.p->hashMapObjectId != newTablePtr.p->hashMapObjectId)
8275  {
8276  jam();
8277  AlterTableReq::setReorgFragFlag(impl_req->changeMask, 1);
8278  }
8279 
8280  if (master)
8281  {
8288  jam();
8289  Uint32 save0 = newTablePtr.p->fragmentType;
8290  newTablePtr.p->fragmentType = DictTabInfo::DistrKeyHash;
8291 
8297  Uint32 cnt = c_fragDataLen / 2;
8298  for (Uint32 i = cnt; i<newTablePtr.p->fragmentCount; i++)
8299  {
8300  jam();
8301  c_fragData[i] = NDB_UNDEF_NODEGROUP;
8302  }
8303  c_fragDataLen = 2 * newTablePtr.p->fragmentCount;
8304  Uint32 save1 = newTablePtr.p->primaryTableId;
8305  Uint32 flags = 0;
8306  if (save1 == RNIL)
8307  {
8313  flags = CreateFragmentationReq::RI_ADD_PARTITION;
8314  newTablePtr.p->primaryTableId = tablePtr.p->tableId;
8315  }
8316  err = create_fragmentation(signal, newTablePtr,
8317  c_fragData, c_fragDataLen / 2,
8318  flags);
8319  newTablePtr.p->fragmentType = (DictTabInfo::FragmentType)save0;
8320  newTablePtr.p->primaryTableId = save1;
8321 
8322  if (err)
8323  {
8324  jam();
8325  setError(error, err, __LINE__);
8326  return;
8327  }
8328 
8329  Uint16* data = (Uint16*)(signal->theData+25);
8330  Uint32 count = 2 + (1 + data[0]) * data[1];
8331  memcpy(c_fragData, data, 2*count);
8332 
8333  err = get_fragmentation(signal, tablePtr.p->tableId);
8334  if (err)
8335  {
8336  jam();
8337  setError(error, err, __LINE__);
8338  return;
8339  }
8340 
8341  err = check_supported_add_fragment(c_fragData,
8342  (Uint16*)(signal->theData+25));
8343  if (err)
8344  {
8345  jam();
8346  setError(error, err, __LINE__);
8347  return;
8348  }
8349 
8350  count = 2 + (1 + c_fragData[0]) * c_fragData[1];
8351  c_fragDataLen = sizeof(Uint16)*count;
8352  }
8353  }
8354 
8355  D("alterTable_parse " << V(newTablePtr.i) << hex << V(newTablePtr.p->tableVersion));
8356 
8357  if (ERROR_INSERTED(6121)) {
8358  jam();
8359  CLEAR_ERROR_INSERT_VALUE;
8360  setError(error, 9121, __LINE__);
8361  return;
8362  }
8363 
8364  // master rewrites DictTabInfo (it is re-parsed only on slaves)
8365  if (master)
8366  {
8367  jam();
8368  releaseSections(handle);
8370  packTableIntoPages(w, alterTabPtr.p->m_newTablePtr);
8371 
8372  SegmentedSectionPtr tabInfoPtr;
8373  w.getPtr(tabInfoPtr);
8374  handle.m_ptr[AlterTabReq::DICT_TAB_INFO] = tabInfoPtr;
8375  handle.m_cnt = 1;
8376 
8377  if (AlterTableReq::getAddFragFlag(impl_req->changeMask))
8378  {
8379  jam();
8380  SegmentedSectionPtr ss_ptr;
8381  ndbrequire(import(ss_ptr, c_fragData_align32, (c_fragDataLen+1)/2));
8382  handle.m_ptr[AlterTabReq::FRAGMENTATION] = ss_ptr;
8383  handle.m_cnt = 2;
8384  }
8385  }
8386 
8387 
8388  {
8389  SegmentedSectionPtr ptr;
8390  handle.getSection(ptr, AlterTabReq::DICT_TAB_INFO);
8391  if (ptr.sz > MAX_WORDS_META_FILE)
8392  {
8393  jam();
8394  setError(error, AlterTableRef::TableDefinitionTooBig, __LINE__);
8395  return;
8396  }
8397  }
8398 
8399  // save sections
8400  saveOpSection(op_ptr, handle, AlterTabReq::DICT_TAB_INFO);
8401  if (AlterTableReq::getAddFragFlag(impl_req->changeMask))
8402  {
8403  jam();
8404  saveOpSection(op_ptr, handle, AlterTabReq::FRAGMENTATION);
8405  }
8406 
8407  SchemaFile::TableEntry te; te.init();
8408  te.m_tableState = SchemaFile::SF_ALTER;
8409  te.m_tableVersion = newTablePtr.p->tableVersion;
8410  te.m_info_words = getOpSection(op_ptr, AlterTabReq::DICT_TAB_INFO).getSize();
8411  te.m_gcp = 0;
8412  te.m_transId = trans_ptr.p->m_transId;
8413 
8414  Uint32 err = trans_log_schema_op(op_ptr, impl_req->tableId, &te);
8415  if (err)
8416  {
8417  jam();
8418  setError(error, err, __LINE__);
8419  return;
8420  }
8421 }
8422 
8423 Uint32
8424 Dbdict::check_supported_reorg(Uint32 org_map_id, Uint32 new_map_id)
8425 {
8426  if (org_map_id == new_map_id)
8427  {
8428  jam();
8429  return 0;
8430  }
8431 
8432  HashMapPtr orgmap_ptr;
8433  ndbrequire(c_hash_map_hash.find(orgmap_ptr, org_map_id));
8434 
8435  HashMapPtr newmap_ptr;
8436  ndbrequire(c_hash_map_hash.find(newmap_ptr, new_map_id));
8437 
8438  Ptr<Hash2FragmentMap> orgptr;
8439  g_hash_map.getPtr(orgptr, orgmap_ptr.p->m_map_ptr_i);
8440 
8441  Ptr<Hash2FragmentMap> newptr;
8442  g_hash_map.getPtr(newptr, newmap_ptr.p->m_map_ptr_i);
8443 
8444  if (newptr.p->m_cnt < orgptr.p->m_cnt)
8445  {
8446  jam();
8447  return AlterTableRef::UnsupportedChange;
8448  }
8449 
8450  for (Uint32 i = 0; i<orgptr.p->m_cnt; i++)
8451  {
8452  jam();
8453  if (orgptr.p->m_map[i] == newptr.p->m_map[i])
8454  continue;
8455 
8456  if (newptr.p->m_map[i] < orgptr.p->m_fragments)
8457  {
8462  jam();
8463  return AlterTableRef::UnsupportedChange;
8464  }
8465  }
8466  return 0;
8467 }
8468 
8469 Uint32
8470 Dbdict::check_supported_add_fragment(Uint16* newdata, const Uint16* olddata)
8471 {
8472  Uint32 replicas = newdata[0];
8473  if (replicas != olddata[0])
8474  {
8475  jam();
8476  return AlterTableRef::UnsupportedChange;
8477  }
8478 
8479  Uint32 fragments = newdata[1];
8480  if (fragments < olddata[1])
8481  {
8482  jam();
8483  return AlterTableRef::UnsupportedChange;
8484  }
8485 
8486  Uint32 oldFragments = olddata[1];
8487 #ifdef TODO_XXX
8488 
8494  // Check that all the old has the same properties...
8495  // Only compare prefered primary, as replicas come in any order
8496  for (Uint32 i = 0; i<oldFragments; i++)
8497  {
8498  Uint32 idx = 2 + (1 + replicas) * i + 1;
8499  if (newdata[idx] != olddata[idx])
8500  {
8501  jam();
8502  return AlterTableRef::UnsupportedChange;
8503  }
8504  }
8505 #endif
8506 
8507  memmove(newdata + 2,
8508  newdata + 2 + (1 + replicas) * oldFragments,
8509  sizeof(short) * (1 + replicas) * (fragments - oldFragments));
8510 
8511  newdata[1] = (fragments - oldFragments);
8512 
8513  return 0;
8514 }
8515 
8516 bool
8517 Dbdict::alterTable_subOps(Signal* signal, SchemaOpPtr op_ptr)
8518 {
8519  D("alterTable_subOps" << V(op_ptr.i) << *op_ptr.p);
8520 
8521  AlterTableRecPtr alterTabPtr;
8522  getOpRec(op_ptr, alterTabPtr);
8523  const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
8524 
8525  if (AlterTableReq::getAddFragFlag(impl_req->changeMask))
8526  {
8527  jam();
8528  if (alterTabPtr.p->m_sub_add_frag == false)
8529  {
8530  jam();
8531  TableRecordPtr tabPtr;
8532  TableRecordPtr indexPtr;
8533  c_tableRecordPool.getPtr(tabPtr, impl_req->tableId);
8534  LocalDLFifoList<TableRecord> list(c_tableRecordPool, tabPtr.p->m_indexes);
8535  Uint32 ptrI = alterTabPtr.p->m_sub_add_frag_index_ptr;
8536 
8537  if (ptrI == RNIL)
8538  {
8539  jam();
8540  list.first(indexPtr);
8541  }
8542  else
8543  {
8544  jam();
8545  list.getPtr(indexPtr, ptrI);
8546  list.next(indexPtr);
8547  }
8548 
8549  for (; !indexPtr.isNull(); list.next(indexPtr))
8550  {
8551  if (DictTabInfo::isOrderedIndex(indexPtr.p->tableType))
8552  {
8553  jam();
8554  break;
8555  }
8556  }
8557  if (indexPtr.isNull())
8558  {
8559  jam();
8560  alterTabPtr.p->m_sub_add_frag = true;
8561  }
8562  else
8563  {
8564  jam();
8565  Callback c = {
8566  safe_cast(&Dbdict::alterTable_fromAlterIndex),
8567  op_ptr.p->op_key
8568  };
8569  op_ptr.p->m_callback = c;
8570 
8571  alterTabPtr.p->m_sub_add_frag_index_ptr = indexPtr.i;
8572  alterTable_toAlterIndex(signal, op_ptr);
8573  return true;
8574  }
8575  }
8576  }
8577 
8578  if (AlterTableReq::getReorgFragFlag(impl_req->changeMask))
8579  {
8580  if (alterTabPtr.p->m_sub_reorg_commit == false)
8581  {
8582  jam();
8583  Callback c = {
8584  safe_cast(&Dbdict::alterTable_fromReorgTable),
8585  op_ptr.p->op_key
8586  };
8587  op_ptr.p->m_callback = c;
8588 
8589  alterTabPtr.p->m_sub_reorg_commit = true;
8590  alterTable_toReorgTable(signal, op_ptr, 0);
8591  return true;
8592  }
8593 
8594  if (alterTabPtr.p->m_sub_suma_enable == false)
8595  {
8596  jam();
8597  Callback c = {
8598  safe_cast(&Dbdict::alterTable_fromReorgTable),
8599  op_ptr.p->op_key
8600  };
8601  op_ptr.p->m_callback = c;
8602 
8603  alterTabPtr.p->m_sub_suma_enable = true;
8604  alterTable_toSumaSync(signal, op_ptr, 0);
8605  return true;
8606  }
8607 
8608 
8609  if (alterTabPtr.p->m_sub_suma_filter == false)
8610  {
8611  jam();
8612  Callback c = {
8613  safe_cast(&Dbdict::alterTable_fromReorgTable),
8614  op_ptr.p->op_key
8615  };
8616  op_ptr.p->m_callback = c;
8617 
8618  alterTabPtr.p->m_sub_suma_filter = true;
8619  alterTable_toSumaSync(signal, op_ptr, 1);
8620  return true;
8621  }
8622 
8623  if (alterTabPtr.p->m_sub_trigger == false)
8624  {
8625  jam();
8626  Callback c = {
8627  safe_cast(&Dbdict::alterTable_fromCreateTrigger),
8628  op_ptr.p->op_key
8629  };
8630  op_ptr.p->m_callback = c;
8631 
8632  alterTable_toCreateTrigger(signal, op_ptr);
8633 
8634  alterTabPtr.p->m_sub_trigger = true;
8635  return true;
8636  }
8637 
8638  if (alterTabPtr.p->m_sub_copy_data == false)
8639  {
8640  jam();
8641  Callback c = {
8642  safe_cast(&Dbdict::alterTable_fromCopyData),
8643  op_ptr.p->op_key
8644  };
8645  op_ptr.p->m_callback = c;
8646 
8647  alterTable_toCopyData(signal, op_ptr);
8648 
8649  alterTabPtr.p->m_sub_copy_data = true;
8650  return true;
8651  }
8652 
8653  if (alterTabPtr.p->m_sub_reorg_complete == false)
8654  {
8655  jam();
8656  Callback c = {
8657  safe_cast(&Dbdict::alterTable_fromReorgTable),
8658  op_ptr.p->op_key
8659  };
8660  op_ptr.p->m_callback = c;
8661 
8662  alterTabPtr.p->m_sub_reorg_complete = true;
8663  alterTable_toReorgTable(signal, op_ptr, 1);
8664  return true;
8665  }
8666  }
8667 
8668  return false;
8669 }
8670 
8671 void
8672 Dbdict::alterTable_toAlterIndex(Signal* signal,
8673  SchemaOpPtr op_ptr)
8674 {
8675  jam();
8676  AlterTableRecPtr alterTabPtr;
8677  getOpRec(op_ptr, alterTabPtr);
8678  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
8679 
8680  TableRecordPtr indexPtr;
8681  c_tableRecordPool.getPtr(indexPtr, alterTabPtr.p->m_sub_add_frag_index_ptr);
8682 
8683  AlterIndxReq* req = (AlterIndxReq*)signal->getDataPtrSend();
8684  req->clientRef = reference();
8685  req->clientData = op_ptr.p->op_key;
8686  req->transId = trans_ptr.p->m_transId;
8687  req->transKey = trans_ptr.p->trans_key;
8688  req->requestInfo = 0;
8689  req->indexId = indexPtr.p->tableId;
8690  req->indexVersion = indexPtr.p->tableVersion;
8691  DictSignal::setRequestType(req->requestInfo,
8692  AlterIndxImplReq::AlterIndexAddPartition);
8693  sendSignal(reference(), GSN_ALTER_INDX_REQ, signal,
8694  AlterIndxReq::SignalLength, JBB);
8695 }
8696 
8697 void
8698 Dbdict::alterTable_fromAlterIndex(Signal* signal,
8699  Uint32 op_key,
8700  Uint32 ret)
8701 {
8702  jamEntry();
8703 
8704  SchemaOpPtr op_ptr;
8705  AlterTableRecPtr alterTablePtr;
8706 
8707  findSchemaOp(op_ptr, alterTablePtr, op_key);
8708  ndbrequire(!op_ptr.isNull());
8709  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
8710 
8711  if (ret == 0) {
8712  const AlterIndxConf* conf =
8713  (const AlterIndxConf*)signal->getDataPtr();
8714 
8715  ndbrequire(conf->transId == trans_ptr.p->m_transId);
8716  createSubOps(signal, op_ptr);
8717  } else {
8718  jam();
8719  const AlterIndxRef* ref =
8720  (const AlterIndxRef*)signal->getDataPtr();
8721  ErrorInfo error;
8722  setError(error, ref);
8723  abortSubOps(signal, op_ptr, error);
8724  }
8725 }
8726 
8727 void
8728 Dbdict::alterTable_toReorgTable(Signal* signal,
8729  SchemaOpPtr op_ptr,
8730  Uint32 step)
8731 {
8732  jam();
8733  AlterTableRecPtr alterTabPtr;
8734  getOpRec(op_ptr, alterTabPtr);
8735  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
8736  const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
8737 
8738  AlterTableReq* req = (AlterTableReq*)signal->getDataPtrSend();
8739  req->clientRef = reference();
8740  req->clientData = op_ptr.p->op_key;
8741  req->transId = trans_ptr.p->m_transId;
8742  req->transKey = trans_ptr.p->trans_key;
8743  req->requestInfo = 0;
8744  req->tableId = impl_req->tableId;
8745  req->tableVersion = impl_req->tableVersion;
8746  req->changeMask = 0;
8747  if (step == 0)
8748  {
8749  jam();
8750  AlterTableReq::setReorgCommitFlag(req->changeMask, 1);
8751  }
8752  else if (step == 1)
8753  {
8754  jam();
8755  AlterTableReq::setReorgCompleteFlag(req->changeMask, 1);
8756  }
8757  else
8758  {
8759  jamLine(step);
8760  ndbrequire(false);
8761  }
8762  sendSignal(reference(), GSN_ALTER_TABLE_REQ, signal,
8763  AlterTableReq::SignalLength, JBB);
8764 }
8765 
8766 void
8767 Dbdict::alterTable_fromReorgTable(Signal* signal,
8768  Uint32 op_key,
8769  Uint32 ret)
8770 {
8771  jamEntry();
8772 
8773  SchemaOpPtr op_ptr;
8774  AlterTableRecPtr alterTablePtr;
8775 
8776  findSchemaOp(op_ptr, alterTablePtr, op_key);
8777  ndbrequire(!op_ptr.isNull());
8778  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
8779 
8780  if (ret == 0)
8781  {
8782  jam();
8783  const AlterTableConf* conf =
8784  (const AlterTableConf*)signal->getDataPtr();
8785 
8786  ndbrequire(conf->transId == trans_ptr.p->m_transId);
8787  createSubOps(signal, op_ptr);
8788  } else {
8789  jam();
8790  const AlterTableRef* ref =
8791  (const AlterTableRef*)signal->getDataPtr();
8792  ErrorInfo error;
8793  setError(error, ref);
8794  abortSubOps(signal, op_ptr, error);
8795  }
8796 }
8797 
8798 void
8799 Dbdict::alterTable_toCreateTrigger(Signal* signal,
8800  SchemaOpPtr op_ptr)
8801 {
8802  jam();
8803 
8804  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
8805  AlterTableRecPtr alterTablePtr;
8806  getOpRec(op_ptr, alterTablePtr);
8807  const AlterTabReq* impl_req = &alterTablePtr.p->m_request;
8808  TableRecordPtr tablePtr;
8809  c_tableRecordPool.getPtr(tablePtr, impl_req->tableId);
8810 
8811  const TriggerTmpl& triggerTmpl = g_reorgTriggerTmpl[0];
8812 
8813  CreateTrigReq* req = (CreateTrigReq*)signal->getDataPtrSend();
8814 
8815  Uint32 requestInfo = 0;
8816  DictSignal::setRequestType(requestInfo, CreateTrigReq::CreateTriggerOnline);
8817 
8818  req->clientRef = reference();
8819  req->clientData = op_ptr.p->op_key;
8820  req->transId = trans_ptr.p->m_transId;
8821  req->transKey = trans_ptr.p->trans_key;
8822  req->requestInfo = requestInfo;
8823  req->tableId = impl_req->tableId;
8824  req->tableVersion = impl_req->tableVersion;
8825  req->indexId = RNIL;
8826  req->indexVersion = RNIL;
8827  req->triggerNo = 0;
8828  req->forceTriggerId = RNIL;
8829 
8830  TriggerInfo::packTriggerInfo(req->triggerInfo, triggerTmpl.triggerInfo);
8831 
8832  req->receiverRef = 0;
8833 
8834  char triggerName[MAX_TAB_NAME_SIZE];
8835  sprintf(triggerName, triggerTmpl.nameFormat, impl_req->tableId);
8836 
8837  // name section
8838  Uint32 buffer[2 + ((MAX_TAB_NAME_SIZE + 3) >> 2)]; // SP string
8839  LinearWriter w(buffer, sizeof(buffer) >> 2);
8840  w.reset();
8841  w.add(DictTabInfo::TableName, triggerName);
8842  LinearSectionPtr lsPtr[3];
8843  lsPtr[0].p = buffer;
8844  lsPtr[0].sz = w.getWordsUsed();
8845 
8846  AttributeMask mask;
8847  mask.clear();
8848  lsPtr[1].p = mask.rep.data;
8849  lsPtr[1].sz = mask.getSizeInWords();
8850 
8851  sendSignal(reference(), GSN_CREATE_TRIG_REQ, signal,
8852  CreateTrigReq::SignalLength, JBB, lsPtr, 2);
8853 }
8854 
8855 void
8856 Dbdict::alterTable_fromCreateTrigger(Signal* signal, Uint32 op_key, Uint32 ret)
8857 {
8858  alterTable_fromAlterIndex(signal, op_key, ret);
8859 }
8860 
8861 void
8862 Dbdict::alterTable_toCopyData(Signal* signal, SchemaOpPtr op_ptr)
8863 {
8864  jam();
8865 
8866  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
8867  AlterTableRecPtr alterTablePtr;
8868  getOpRec(op_ptr, alterTablePtr);
8869  const AlterTabReq* impl_req = &alterTablePtr.p->m_request;
8870  TableRecordPtr tablePtr;
8871  c_tableRecordPool.getPtr(tablePtr, impl_req->tableId);
8872 
8873  CopyDataReq* req = (CopyDataReq*)signal->getDataPtrSend();
8874 
8875  req->clientRef = reference();
8876  req->clientData = op_ptr.p->op_key;
8877  req->transId = trans_ptr.p->m_transId;
8878  req->transKey = trans_ptr.p->trans_key;
8879  req->requestInfo = 0;
8880  req->requestType = 0;
8881  req->srcTableId = impl_req->tableId;
8882  req->dstTableId = impl_req->tableId;
8883  req->srcFragments = tablePtr.p->fragmentCount;
8884 
8885  sendSignal(reference(), GSN_COPY_DATA_REQ, signal,
8886  CopyDataReq::SignalLength, JBB);
8887 }
8888 
8889 void
8890 Dbdict::alterTable_fromCopyData(Signal* signal, Uint32 op_key, Uint32 ret)
8891 {
8892  alterTable_fromAlterIndex(signal, op_key, ret);
8893 }
8894 
8895 void
8896 Dbdict::alterTable_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
8897 {
8898  jam();
8899  D("alterTable_reply" << V(op_ptr.i) << *op_ptr.p);
8900 
8901  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
8902 
8903  AlterTableRecPtr alterTabPtr;
8904  getOpRec(op_ptr, alterTabPtr);
8905  const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
8906 
8907  if (!hasError(error)) {
8908  AlterTableConf* conf = (AlterTableConf*)signal->getDataPtrSend();
8909  conf->senderRef = reference();
8910  conf->clientData = op_ptr.p->m_clientData;
8911  conf->transId = trans_ptr.p->m_transId;
8912  conf->tableId = impl_req->tableId;
8913  conf->tableVersion = impl_req->tableVersion;
8914  conf->newTableVersion = impl_req->newTableVersion;
8915 
8916  Uint32 clientRef = op_ptr.p->m_clientRef;
8917  sendSignal(clientRef, GSN_ALTER_TABLE_CONF, signal,
8918  AlterTableConf::SignalLength, JBB);
8919  } else {
8920  jam();
8921  AlterTableRef* ref = (AlterTableRef*)signal->getDataPtrSend();
8922  ref->senderRef = reference();
8923  ref->clientData = op_ptr.p->m_clientData;
8924  ref->transId = trans_ptr.p->m_transId;
8925  getError(error, ref);
8926  ref->errorStatus = error.errorStatus;
8927  ref->errorKey = error.errorKey;
8928 
8929  Uint32 clientRef = op_ptr.p->m_clientRef;
8930  sendSignal(clientRef, GSN_ALTER_TABLE_REF, signal,
8931  AlterTableRef::SignalLength, JBB);
8932  }
8933 }
8934 
8935 void
8936 Dbdict::alterTable_toSumaSync(Signal* signal,
8937  SchemaOpPtr op_ptr,
8938  Uint32 step)
8939 {
8940  jam();
8941  AlterTableRecPtr alterTabPtr;
8942  getOpRec(op_ptr, alterTabPtr);
8943  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
8944  const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
8945 
8946  AlterTableReq* req = (AlterTableReq*)signal->getDataPtrSend();
8947  req->clientRef = reference();
8948  req->clientData = op_ptr.p->op_key;
8949  req->transId = trans_ptr.p->m_transId;
8950  req->transKey = trans_ptr.p->trans_key;
8951  req->requestInfo = 0;
8952  req->tableId = impl_req->tableId;
8953  req->tableVersion = impl_req->tableVersion;
8954  req->changeMask = 0;
8955  if (step == 0)
8956  {
8957  jam();
8958  AlterTableReq::setReorgSumaEnableFlag(req->changeMask, 1);
8959  }
8960  else if (step == 1)
8961  {
8962  AlterTableReq::setReorgSumaFilterFlag(req->changeMask, 1);
8963  }
8964  else
8965  {
8966  jamLine(step);
8967  ndbrequire(false);
8968  }
8969  sendSignal(reference(), GSN_ALTER_TABLE_REQ, signal,
8970  AlterTableReq::SignalLength, JBB);
8971 }
8972 
8973 
8974 // AlterTable: PREPARE
8975 
8976 void
8977 Dbdict::alterTable_prepare(Signal* signal, SchemaOpPtr op_ptr)
8978 {
8979  jam();
8980  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
8981 
8982  AlterTableRecPtr alterTabPtr;
8983  getOpRec(op_ptr, alterTabPtr);
8984  const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
8985 
8986  D("alterTable_prepare" << *op_ptr.p);
8987 
8988  if (AlterTableReq::getReorgSubOp(impl_req->changeMask))
8989  {
8990  jam();
8991 
8995  {
8996  Ptr<SchemaOp> tmp = op_ptr;
8997  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
8998  for (list.prev(tmp); !tmp.isNull(); list.prev(tmp))
8999  {
9000  jam();
9001  if (&tmp.p->m_oprec_ptr.p->m_opInfo== &Dbdict::AlterTableRec::g_opInfo)
9002  {
9003  jam();
9004  break;
9005  }
9006  }
9007  ndbrequire(!tmp.isNull());
9008  alterTabPtr.p->m_dihAddFragPtr =
9009  ((AlterTableRec*)tmp.p->m_oprec_ptr.p)->m_dihAddFragPtr;
9010  alterTabPtr.p->m_lqhFragPtr =
9011  ((AlterTableRec*)tmp.p->m_oprec_ptr.p)->m_lqhFragPtr;
9012  }
9013 
9014  sendTransConf(signal, op_ptr);
9015  return;
9016  }
9017 
9018  Mutex mutex(signal, c_mutexMgr, alterTabPtr.p->m_define_backup_mutex);
9019  Callback c = {
9020  safe_cast(&Dbdict::alterTable_backup_mutex_locked),
9021  op_ptr.p->op_key
9022  };
9023  bool ok = mutex.lock(c);
9024  ndbrequire(ok);
9025  return;
9026 }
9027 
9028 void
9029 Dbdict::alterTable_backup_mutex_locked(Signal* signal,
9030  Uint32 op_key,
9031  Uint32 ret)
9032 {
9033  jamEntry();
9034  D("alterTable_backup_mutex_locked");
9035 
9036  ndbrequire(ret == 0);
9037 
9038  SchemaOpPtr op_ptr;
9039  AlterTableRecPtr alterTabPtr;
9040  findSchemaOp(op_ptr, alterTabPtr, op_key);
9041  ndbrequire(!op_ptr.isNull());
9042  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
9043  const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
9044 
9045  TableRecordPtr tablePtr;
9046  c_tableRecordPool.getPtr(tablePtr, impl_req->tableId);
9047 
9048  Mutex mutex(signal, c_mutexMgr, alterTabPtr.p->m_define_backup_mutex);
9049  mutex.unlock(); // ignore response
9050 
9051  if (tablePtr.p->m_read_locked)
9052  {
9053  jam();
9054  setError(op_ptr, tablePtr.p->m_read_locked, __LINE__);
9055  sendTransRef(signal, op_ptr);
9056  return;
9057  }
9058 
9062  Callback callback = {
9063  safe_cast(&Dbdict::alterTab_writeTableConf),
9064  callback.m_callbackData = op_ptr.p->op_key
9065  };
9066 
9067  const OpSection& tabInfoSec =
9068  getOpSection(op_ptr, CreateTabReq::DICT_TAB_INFO);
9069 
9070  bool savetodisk = !(tablePtr.p->m_bits & TableRecord::TR_Temporary);
9071  if (savetodisk) {
9072  writeTableFile(signal, impl_req->tableId, tabInfoSec, &callback);
9073  } else {
9074  execute(signal, callback, 0);
9075  }
9076 }
9077 
9078 void
9079 Dbdict::alterTab_writeTableConf(Signal* signal, Uint32 op_key, Uint32 ret)
9080 {
9081  jam();
9082  ndbrequire(ret == 0);
9083 
9084  SchemaOpPtr op_ptr;
9085  AlterTableRecPtr alterTabPtr;
9086  findSchemaOp(op_ptr, alterTabPtr, op_key);
9087 
9088  alterTable_toLocal(signal, op_ptr);
9089 }
9090 
9091 void
9092 Dbdict::alterTable_toLocal(Signal* signal, SchemaOpPtr op_ptr)
9093 {
9094  AlterTableRecPtr alterTabPtr;
9095  getOpRec(op_ptr, alterTabPtr);
9096  const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
9097 
9098  const Uint32 blockIndex = alterTabPtr.p->m_blockIndex;
9099  if (blockIndex == AlterTableRec::BlockCount)
9100  {
9101  jam();
9102  sendTransConf(signal, op_ptr);
9103  return;
9104  }
9105 
9106  ndbrequire(blockIndex < AlterTableRec::BlockCount);
9107  const Uint32 blockNo = alterTabPtr.p->m_blockNo[blockIndex];
9108 
9109  D("alterTable_toLocal" << V(blockIndex) << V(getBlockName(blockNo)));
9110 
9111  AlterTabReq* req = (AlterTabReq*)signal->getDataPtrSend();
9112  req->senderRef = reference();
9113  req->senderData = op_ptr.p->op_key;
9114  req->requestType = AlterTabReq::AlterTablePrepare;
9115  req->tableId = impl_req->tableId;
9116  req->tableVersion = impl_req->tableVersion;
9117  req->newTableVersion = impl_req->newTableVersion;
9118  req->gci = impl_req->gci;
9119  req->changeMask = impl_req->changeMask;
9120  req->connectPtr = RNIL;
9121  req->noOfNewAttr = impl_req->noOfNewAttr;
9122  req->newNoOfCharsets = impl_req->newNoOfCharsets;
9123  req->newNoOfKeyAttrs = impl_req->newNoOfKeyAttrs;
9124 
9125  Callback c = {
9126  safe_cast(&Dbdict::alterTable_fromLocal),
9127  op_ptr.p->op_key
9128  };
9129  op_ptr.p->m_callback = c;
9130 
9131  if (ERROR_INSERTED(6131) &&
9132  blockIndex + 1 == AlterTableRec::BlockCount) {
9133  jam();
9134  CLEAR_ERROR_INSERT_VALUE;
9135  AlterTabRef* ref = (AlterTabRef*)signal->getDataPtrSend();
9136  ref->senderRef = reference();
9137  ref->senderData = op_ptr.p->op_key;
9138  ref->errorCode = 9131;
9139  sendSignal(reference(), GSN_ALTER_TAB_REF, signal,
9140  AlterTabRef::SignalLength, JBB);
9141  return;
9142  }
9143 
9144  BlockReference blockRef = numberToRef(blockNo, getOwnNodeId());
9145 
9146  if (blockNo == DBLQH && req->noOfNewAttr > 0)
9147  {
9148  jam();
9149  LinearSectionPtr ptr[3];
9150  ptr[0].p = alterTabPtr.p->m_newAttrData;
9151  ptr[0].sz = 2 * impl_req->noOfNewAttr;
9152  sendSignal(blockRef, GSN_ALTER_TAB_REQ, signal,
9153  AlterTabReq::SignalLength, JBB, ptr, 1);
9154  }
9155  else if (blockNo == DBDIH && AlterTableReq::getAddFragFlag(req->changeMask))
9156  {
9157  jam();
9158  const OpSection& fragInfoSec =
9159  getOpSection(op_ptr, AlterTabReq::FRAGMENTATION);
9160  SegmentedSectionPtr fragInfoPtr;
9161  bool ok = copyOut(fragInfoSec, fragInfoPtr);
9162  ndbrequire(ok);
9163 
9164  if (AlterTableReq::getReorgFragFlag(req->changeMask))
9165  {
9166  jam();
9167  HashMapPtr hm_ptr;
9168  ndbrequire(c_hash_map_hash.find(hm_ptr,
9169  alterTabPtr.p->m_newTablePtr.p->hashMapObjectId));
9170  req->new_map_ptr_i = hm_ptr.p->m_map_ptr_i;
9171  }
9172 
9173  SectionHandle handle(this, fragInfoPtr.i);
9174  sendSignal(blockRef, GSN_ALTER_TAB_REQ, signal,
9175  AlterTabReq::SignalLength, JBB, &handle);
9176  }
9177  else
9178  {
9179  jam();
9180  sendSignal(blockRef, GSN_ALTER_TAB_REQ, signal,
9181  AlterTabReq::SignalLength, JBB);
9182  }
9183 }
9184 
9185 void
9186 Dbdict::alterTable_fromLocal(Signal* signal,
9187  Uint32 op_key,
9188  Uint32 ret)
9189 {
9190  D("alterTable_fromLocal");
9191 
9192  SchemaOpPtr op_ptr;
9193  AlterTableRecPtr alterTabPtr;
9194  findSchemaOp(op_ptr, alterTabPtr, op_key);
9195  ndbrequire(!op_ptr.isNull());
9196 
9197  Uint32& blockIndex = alterTabPtr.p->m_blockIndex; //ref
9198  ndbrequire(blockIndex < AlterTableRec::BlockCount);
9199  const Uint32 blockNo = alterTabPtr.p->m_blockNo[blockIndex];
9200 
9201  if (ret)
9202  {
9203  jam();
9204  setError(op_ptr, ret, __LINE__);
9205  sendTransRef(signal, op_ptr);
9206  return;
9207  }
9208 
9209  const AlterTabConf* conf = (const AlterTabConf*)signal->getDataPtr();
9210 
9211  // save TUP operation record for commit/abort
9212  switch(blockNo){
9213  case DBLQH:
9214  jam();
9215  alterTabPtr.p->m_lqhFragPtr = conf->connectPtr;
9216  break;
9217  case DBDIH:
9218  jam();
9219  alterTabPtr.p->m_dihAddFragPtr = conf->connectPtr;
9220  break;
9221  }
9222 
9223  blockIndex += 1;
9224  alterTable_toLocal(signal, op_ptr);
9225 }
9226 
9227 // AlterTable: COMMIT
9228 
9229 void
9230 Dbdict::alterTable_commit(Signal* signal, SchemaOpPtr op_ptr)
9231 {
9232  AlterTableRecPtr alterTabPtr;
9233  getOpRec(op_ptr, alterTabPtr);
9234  const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
9235 
9236  D("alterTable_commit" << *op_ptr.p);
9237 
9238  TableRecordPtr tablePtr;
9239  c_tableRecordPool.getPtr(tablePtr, impl_req->tableId);
9240 
9241  if (op_ptr.p->m_sections)
9242  {
9243  jam();
9244  // main-op
9245  ndbrequire(AlterTableReq::getReorgSubOp(impl_req->changeMask) == false);
9246 
9247  const OpSection& tabInfoSec =
9248  getOpSection(op_ptr, CreateTabReq::DICT_TAB_INFO);
9249  const Uint32 size = tabInfoSec.getSize();
9250 
9251  // update table record
9252  tablePtr.p->packedSize = size;
9253  tablePtr.p->tableVersion = impl_req->newTableVersion;
9254  tablePtr.p->gciTableCreated = impl_req->gci;
9255 
9256  TableRecordPtr newTablePtr = alterTabPtr.p->m_newTablePtr;
9257 
9258  const Uint32 changeMask = impl_req->changeMask;
9259 
9260  // perform DICT memory changes
9261  if (AlterTableReq::getNameFlag(changeMask))
9262  {
9263  jam();
9264  const Uint32 sz = MAX_TAB_NAME_SIZE;
9265  D("alter name:"
9266  << " old=" << copyRope<sz>(tablePtr.p->tableName)
9267  << " new=" << copyRope<sz>(newTablePtr.p->tableName));
9268 
9269  Ptr<DictObject> obj_ptr;
9270  c_obj_pool.getPtr(obj_ptr, tablePtr.p->m_obj_ptr_i);
9271 
9272  // remove old name from hash
9273  c_obj_hash.remove(obj_ptr);
9274 
9275  // save old name and replace it by new
9276  bool ok =
9277  copyRope<sz>(alterTabPtr.p->m_oldTableName, tablePtr.p->tableName) &&
9278  copyRope<sz>(tablePtr.p->tableName, newTablePtr.p->tableName);
9279  ndbrequire(ok);
9280 
9281  // add new name to object hash
9282  obj_ptr.p->m_name = tablePtr.p->tableName;
9283  c_obj_hash.add(obj_ptr);
9284  }
9285 
9286  if (AlterTableReq::getFrmFlag(changeMask))
9287  {
9288  jam();
9289  // save old frm and replace it by new
9290  const Uint32 sz = MAX_FRM_DATA_SIZE;
9291  bool ok =
9292  copyRope<sz>(alterTabPtr.p->m_oldFrmData, tablePtr.p->frmData) &&
9293  copyRope<sz>(tablePtr.p->frmData, newTablePtr.p->frmData);
9294  ndbrequire(ok);
9295  }
9296 
9297  if (AlterTableReq::getAddAttrFlag(changeMask))
9298  {
9299  jam();
9300 
9301  /* Move the column definitions to the real table definitions. */
9303  list(c_attributeRecordPool, tablePtr.p->m_attributes);
9305  newlist(c_attributeRecordPool, newTablePtr.p->m_attributes);
9306 
9307  const Uint32 noOfNewAttr = impl_req->noOfNewAttr;
9308  ndbrequire(noOfNewAttr > 0);
9309  Uint32 i;
9310 
9311  /* Move back to find the first column to move. */
9312  AttributeRecordPtr pPtr;
9313  ndbrequire(newlist.last(pPtr));
9314  for (i = 1; i < noOfNewAttr; i++) {
9315  jam();
9316  ndbrequire(newlist.prev(pPtr));
9317  }
9318 
9319  /* Move columns. */
9320  for (i = 0; i < noOfNewAttr; i++) {
9321  AttributeRecordPtr qPtr = pPtr;
9322  newlist.next(pPtr);
9323  newlist.remove(qPtr);
9324  list.addLast(qPtr);
9325  }
9326  tablePtr.p->noOfAttributes += noOfNewAttr;
9327  }
9328 
9329  if (AlterTableReq::getAddFragFlag(changeMask))
9330  {
9331  jam();
9332  Uint32 save = tablePtr.p->fragmentCount;
9333  tablePtr.p->fragmentCount = newTablePtr.p->fragmentCount;
9334  newTablePtr.p->fragmentCount = save;
9335  }
9336  }
9337 
9338  alterTabPtr.p->m_blockIndex = 0;
9339  alterTabPtr.p->m_blockNo[0] = DBLQH;
9340  alterTabPtr.p->m_blockNo[1] = DBDIH;
9341  alterTabPtr.p->m_blockNo[2] = DBTC;
9342 
9343  if (AlterTableReq::getReorgFragFlag(impl_req->changeMask))
9344  {
9348  TableRecordPtr newTablePtr = alterTabPtr.p->m_newTablePtr;
9349  tablePtr.p->hashMapObjectId = newTablePtr.p->hashMapObjectId;
9350  tablePtr.p->hashMapVersion = newTablePtr.p->hashMapVersion;
9351  alterTabPtr.p->m_blockNo[1] = RNIL;
9352  }
9353  else if (AlterTableReq::getReorgCommitFlag(impl_req->changeMask))
9354  {
9355  jam();
9359  alterTabPtr.p->m_blockNo[0] = RNIL;
9360  alterTabPtr.p->m_blockNo[2] = RNIL;
9361  }
9362  else if (AlterTableReq::getReorgCompleteFlag(impl_req->changeMask) ||
9363  AlterTableReq::getReorgSumaEnableFlag(impl_req->changeMask) ||
9364  AlterTableReq::getReorgSumaFilterFlag(impl_req->changeMask))
9365  {
9366  jam();
9367  sendTransConf(signal, op_ptr);
9368  return;
9369  }
9370 
9371  alterTable_toCommitComplete(signal, op_ptr);
9372 }
9373 
9374 void
9375 Dbdict::alterTable_toCommitComplete(Signal* signal,
9376  SchemaOpPtr op_ptr,
9377  Uint32 type)
9378 {
9379  D("alterTable_toTupCommit");
9380 
9381  AlterTableRecPtr alterTabPtr;
9382  getOpRec(op_ptr, alterTabPtr);
9383  const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
9384 
9385  AlterTabReq* req = (AlterTabReq*)signal->getDataPtrSend();
9386  req->senderRef = reference();
9387  req->senderData = op_ptr.p->op_key;
9388  if (type == ~Uint32(0))
9389  {
9390  jam();
9391  switch(op_ptr.p->m_state){
9392  case SchemaOp::OS_COMMITTING:
9393  jam();
9394  req->requestType = AlterTabReq::AlterTableCommit;
9395  break;
9396  case SchemaOp::OS_COMPLETING:
9397  jam();
9398  req->requestType = AlterTabReq::AlterTableComplete;
9399  break;
9400  default:
9401  jamLine(op_ptr.p->m_state);
9402  ndbrequire(false);
9403  }
9404  }
9405  else
9406  {
9407  jam();
9408  jamLine(type);
9409  req->requestType = type;
9410  }
9411 
9412  req->tableId = impl_req->tableId;
9413  req->tableVersion = impl_req->tableVersion;
9414  req->newTableVersion = impl_req->newTableVersion;
9415  req->gci = impl_req->gci;
9416  req->changeMask = impl_req->changeMask;
9417  req->noOfNewAttr = impl_req->noOfNewAttr;
9418  req->newNoOfCharsets = impl_req->newNoOfCharsets;
9419  req->newNoOfKeyAttrs = impl_req->newNoOfKeyAttrs;
9420  req->connectPtr = RNIL;
9421 
9422  Uint32 blockIndex = alterTabPtr.p->m_blockIndex; //ref
9423  const Uint32 blockNo = alterTabPtr.p->m_blockNo[blockIndex];
9424  switch(blockNo){
9425  case DBDIH:
9426  jam();
9427  req->connectPtr = alterTabPtr.p->m_dihAddFragPtr;
9428  break;
9429  case DBLQH:
9430  req->connectPtr = alterTabPtr.p->m_lqhFragPtr;
9431  break;
9432  case RNIL:
9433  alterTable_fromCommitComplete(signal, op_ptr.p->op_key, 0);
9434  return;
9435  }
9436 
9437  Callback c = {
9438  safe_cast(&Dbdict::alterTable_fromCommitComplete),
9439  op_ptr.p->op_key
9440  };
9441  op_ptr.p->m_callback = c;
9442 
9443  sendSignal(numberToRef(blockNo, getOwnNodeId()),
9444  GSN_ALTER_TAB_REQ, signal,
9445  AlterTabReq::SignalLength, JBB);
9446 }
9447 
9448 void
9449 Dbdict::alterTable_fromCommitComplete(Signal* signal,
9450  Uint32 op_key,
9451  Uint32 ret)
9452 {
9453  D("alterTable_fromCommit");
9454 
9455  SchemaOpPtr op_ptr;
9456  AlterTableRecPtr alterTabPtr;
9457  findSchemaOp(op_ptr, alterTabPtr, op_key);
9458  ndbrequire(!op_ptr.isNull());
9459  const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
9460 
9461  ndbrequire(ret == 0); // Failure during commit is not allowed
9462  if (++ alterTabPtr.p->m_blockIndex < AlterTableRec::BlockCount)
9463  {
9464  jam();
9465  alterTable_toCommitComplete(signal, op_ptr);
9466  return;
9467  }
9468 
9469  if (AlterTableReq::getReorgSubOp(impl_req->changeMask))
9470  {
9471  jam();
9472  sendTransConf(signal, op_ptr);
9473  return;
9474  }
9475 
9476  if (op_ptr.p->m_state == SchemaOp::OS_COMPLETING)
9477  {
9478  jam();
9479  sendTransConf(signal, op_ptr);
9480  return;
9481  }
9482 
9483  const Uint32 tableId = impl_req->tableId;
9484  TableRecordPtr tablePtr;
9485  c_tableRecordPool.getPtr(tablePtr, tableId);
9486 
9487  // inform Suma so it can send events to any subscribers of the table
9488  {
9489  AlterTabReq* req = (AlterTabReq*)signal->getDataPtrSend();
9490 
9491  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
9492 
9493  // special use of senderRef
9494  if (trans_ptr.p->m_isMaster)
9495  req->senderRef = trans_ptr.p->m_clientRef;
9496  else
9497  req->senderRef = 0;
9498  req->senderData = op_key;
9499  req->tableId = impl_req->tableId;
9500  req->tableVersion = impl_req->tableVersion;
9501  req->newTableVersion = impl_req->newTableVersion;
9502  req->gci = tablePtr.p->gciTableCreated;
9503  req->requestType = 0;
9504  req->changeMask = impl_req->changeMask;
9505  req->connectPtr = RNIL;
9506  req->noOfNewAttr = impl_req->noOfNewAttr;
9507  req->newNoOfCharsets = impl_req->newNoOfCharsets;
9508  req->newNoOfKeyAttrs = impl_req->newNoOfKeyAttrs;
9509 
9510  const OpSection& tabInfoSec =
9511  getOpSection(op_ptr, AlterTabReq::DICT_TAB_INFO);
9512  SegmentedSectionPtr tabInfoPtr;
9513  bool ok = copyOut(tabInfoSec, tabInfoPtr);
9514  ndbrequire(ok);
9515 
9516  SectionHandle handle(this, tabInfoPtr.i);
9517  sendSignal(SUMA_REF, GSN_ALTER_TAB_REQ, signal,
9518  AlterTabReq::SignalLength, JBB, &handle);
9519  }
9520 
9521  // older way to notify wl3600_todo disable to find SUMA problems
9522  {
9523  ApiBroadcastRep* api= (ApiBroadcastRep*)signal->getDataPtrSend();
9524  api->gsn = GSN_ALTER_TABLE_REP;
9525  api->minVersion = MAKE_VERSION(4,1,15);
9526 
9527  AlterTableRep* rep = (AlterTableRep*)api->theData;
9528  rep->tableId = tablePtr.p->tableId;
9529  // wl3600_todo wants old version?
9530  rep->tableVersion = impl_req->tableVersion;
9531  rep->changeType = AlterTableRep::CT_ALTERED;
9532 
9533  char oldTableName[MAX_TAB_NAME_SIZE];
9534  memset(oldTableName, 0, sizeof(oldTableName));
9535  {
9536  const RopeHandle& rh =
9537  AlterTableReq::getNameFlag(impl_req->changeMask)
9538  ? alterTabPtr.p->m_oldTableName
9539  : tablePtr.p->tableName;
9540  ConstRope r(c_rope_pool, rh);
9541  r.copy(oldTableName);
9542  }
9543 
9544  LinearSectionPtr ptr[3];
9545  ptr[0].p = (Uint32*)oldTableName;
9546  ptr[0].sz = (sizeof(oldTableName) + 3) >> 2;
9547 
9548  sendSignal(QMGR_REF, GSN_API_BROADCAST_REP, signal,
9549  ApiBroadcastRep::SignalLength + AlterTableRep::SignalLength,
9550  JBB, ptr, 1);
9551  }
9552 
9553  {
9554  // Remark object as free
9555  SchemaFile::TableEntry * objEntry =
9556  objEntry = getTableEntry(alterTabPtr.p->m_newTable_realObjectId);
9557  objEntry->m_tableType = DictTabInfo::UndefTableType;
9558  objEntry->m_tableState = SchemaFile::SF_UNUSED;
9559  objEntry->m_transId = 0;
9560  }
9561 
9562  releaseTableObject(alterTabPtr.p->m_newTablePtr.i, false);
9563  sendTransConf(signal, op_ptr);
9564 }
9565 
9566 // AlterTable: COMPLETE
9567 
9568 void
9569 Dbdict::alterTable_complete(Signal* signal, SchemaOpPtr op_ptr)
9570 {
9571  jam();
9572  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
9573 
9574  AlterTableRecPtr alterTabPtr;
9575  getOpRec(op_ptr, alterTabPtr);
9576  const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
9577 
9578  alterTabPtr.p->m_blockIndex = 0;
9579  alterTabPtr.p->m_blockNo[0] = RNIL;
9580  alterTabPtr.p->m_blockNo[1] = RNIL;
9581  alterTabPtr.p->m_blockNo[2] = RNIL;
9582 
9583  if (AlterTableReq::getReorgCommitFlag(impl_req->changeMask))
9584  {
9585  jam();
9586  alterTabPtr.p->m_blockNo[0] = DBDIH;
9587  alterTable_toCommitComplete(signal, op_ptr,
9588  AlterTabReq::AlterTableWaitScan);
9589  return;
9590  }
9591  else if (AlterTableReq::getReorgCompleteFlag(impl_req->changeMask))
9592  {
9593  jam();
9594 
9598  alterTabPtr.p->m_blockNo[0] = DBDIH;
9599  alterTabPtr.p->m_blockNo[1] = DBLQH;
9600  alterTable_toCommitComplete(signal, op_ptr);
9601  return;
9602  }
9603  else if (AlterTableReq::getReorgSumaEnableFlag(impl_req->changeMask))
9604  {
9605  jam();
9606  alterTabPtr.p->m_blockNo[0] = DBLQH;
9607  alterTable_toCommitComplete(signal, op_ptr,
9608  AlterTabReq::AlterTableSumaEnable);
9609  return;
9610  }
9611  else if (AlterTableReq::getReorgSumaFilterFlag(impl_req->changeMask))
9612  {
9613  jam();
9614  alterTabPtr.p->m_blockNo[0] = DBLQH;
9615  alterTable_toCommitComplete(signal, op_ptr,
9616  AlterTabReq::AlterTableSumaFilter);
9617  return;
9618  }
9619  sendTransConf(signal, op_ptr);
9620 }
9621 
9622 // AlterTable: ABORT
9623 
9624 void
9625 Dbdict::alterTable_abortParse(Signal* signal, SchemaOpPtr op_ptr)
9626 {
9627  D("alterTable_abortParse" << *op_ptr.p);
9628 
9629  AlterTableRecPtr alterTabPtr;
9630  getOpRec(op_ptr, alterTabPtr);
9631  const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
9632 
9633  if (AlterTableReq::getReorgSubOp(impl_req->changeMask))
9634  {
9635  jam();
9636  sendTransConf(signal, op_ptr);
9637  return;
9638  }
9639 
9640  TableRecordPtr& newTablePtr = alterTabPtr.p->m_newTablePtr; // ref
9641  if (!newTablePtr.isNull()) {
9642  jam();
9643  // release the temporary work table
9644 
9645  {
9646  // Remark object as free
9647  SchemaFile::TableEntry * objEntry =
9648  objEntry = getTableEntry(alterTabPtr.p->m_newTable_realObjectId);
9649  objEntry->m_tableType = DictTabInfo::UndefTableType;
9650  objEntry->m_tableState = SchemaFile::SF_UNUSED;
9651  objEntry->m_transId = 0;
9652  }
9653 
9654  releaseTableObject(newTablePtr.i, false);
9655  newTablePtr.setNull();
9656  }
9657 
9658  TableRecordPtr& tablePtr = alterTabPtr.p->m_tablePtr; // ref
9659  if (!tablePtr.isNull()) {
9660  jam();
9661  tablePtr.setNull();
9662  }
9663 
9664  sendTransConf(signal, op_ptr);
9665 }
9666 
9667 void
9668 Dbdict::alterTable_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
9669 {
9670  D("alterTable_abortPrepare" << *op_ptr.p);
9671 
9672  AlterTableRecPtr alterTabPtr;
9673  getOpRec(op_ptr, alterTabPtr);
9674  const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
9675 
9676  if (AlterTableReq::getReorgSubOp(impl_req->changeMask))
9677  {
9678  jam();
9679 
9683  sendTransConf(signal, op_ptr);
9684  return;
9685  }
9686 
9687  if (alterTabPtr.p->m_blockIndex > 0)
9688  {
9689  jam();
9690  /*
9691  * Local blocks have only updated table version.
9692  * Reset it to original in reverse block order.
9693  */
9694  alterTable_abortToLocal(signal, op_ptr);
9695  return;
9696  }
9697  else
9698  {
9699  jam();
9700  sendTransConf(signal, op_ptr);
9701  return;
9702  }
9703 }
9704 
9705 void
9706 Dbdict::alterTable_abortToLocal(Signal* signal, SchemaOpPtr op_ptr)
9707 {
9708  AlterTableRecPtr alterTabPtr;
9709  getOpRec(op_ptr, alterTabPtr);
9710  const AlterTabReq* impl_req = &alterTabPtr.p->m_request;
9711 
9712  const Uint32 blockCount = alterTabPtr.p->m_blockIndex;
9713  ndbrequire(blockCount != 0 && blockCount <= AlterTableRec::BlockCount);
9714  const Uint32 blockIndex = blockCount - 1;
9715  const Uint32 blockNo = alterTabPtr.p->m_blockNo[blockIndex];
9716 
9717  D("alterTable_abortToLocal" << V(blockIndex) << V(getBlockName(blockNo)));
9718 
9719  Uint32 connectPtr = RNIL;
9720  switch(blockNo){
9721  case DBLQH:
9722  jam();
9723  connectPtr = alterTabPtr.p->m_lqhFragPtr;
9724  break;
9725  case DBDIH:
9726  jam();
9727  connectPtr = alterTabPtr.p->m_dihAddFragPtr;
9728  break;
9729  }
9730 
9731  AlterTabReq* req = (AlterTabReq*)signal->getDataPtrSend();
9732  req->senderRef = reference();
9733  req->senderData = op_ptr.p->op_key;
9734  req->requestType = AlterTabReq::AlterTableRevert;
9735  req->tableId = impl_req->tableId;
9736  req->tableVersion = impl_req->tableVersion;
9737  req->newTableVersion = impl_req->newTableVersion;
9738  req->gci = impl_req->gci;
9739  req->changeMask = impl_req->changeMask;
9740  req->connectPtr = connectPtr;
9741  req->noOfNewAttr = impl_req->noOfNewAttr;
9742  req->newNoOfCharsets = impl_req->newNoOfCharsets;
9743  req->newNoOfKeyAttrs = impl_req->newNoOfKeyAttrs;
9744 
9745  Callback c = {
9746  safe_cast(&Dbdict::alterTable_abortFromLocal),
9747  op_ptr.p->op_key
9748  };
9749  op_ptr.p->m_callback = c;
9750 
9751  BlockReference blockRef = numberToRef(blockNo, getOwnNodeId());
9752  sendSignal(blockRef, GSN_ALTER_TAB_REQ, signal,
9753  AlterTabReq::SignalLength, JBB);
9754 }
9755 
9756 void
9757 Dbdict::alterTable_abortFromLocal(Signal*signal, Uint32 op_key, Uint32 ret)
9758 {
9759  SchemaOpPtr op_ptr;
9760  AlterTableRecPtr alterTabPtr;
9761  findSchemaOp(op_ptr, alterTabPtr, op_key);
9762  ndbrequire(!op_ptr.isNull());
9763 
9764  const Uint32 blockCount = alterTabPtr.p->m_blockIndex;
9765  ndbrequire(blockCount != 0 && blockCount <= AlterTableRec::BlockCount);
9766  const Uint32 blockIndex = blockCount - 1;
9767  alterTabPtr.p->m_blockIndex = blockIndex;
9768 
9769  ndbrequire(ret == 0); // abort is not allowed to fail
9770 
9771  if (blockIndex > 0)
9772  {
9773  jam();
9774  alterTable_abortToLocal(signal, op_ptr);
9775  return;
9776  }
9777  else
9778  {
9779  jam();
9780  sendTransConf(signal, op_ptr);
9781  }
9782 }
9783 
9784 // AlterTable: MISC
9785 
9786 void
9787 Dbdict::execALTER_TAB_CONF(Signal* signal)
9788 {
9789  jamEntry();
9790  const AlterTabConf* conf = (const AlterTabConf*)signal->getDataPtr();
9791  ndbrequire(refToNode(conf->senderRef) == getOwnNodeId());
9792  handleDictConf(signal, conf);
9793 }
9794 
9795 void
9796 Dbdict::execALTER_TAB_REF(Signal* signal)
9797 {
9798  jamEntry();
9799  const AlterTabRef* ref = (const AlterTabRef*)signal->getDataPtr();
9800  ndbrequire(refToNode(ref->senderRef) == getOwnNodeId());
9801  handleDictRef(signal, ref);
9802 }
9803 
9804 void
9805 Dbdict::execALTER_TABLE_CONF(Signal* signal)
9806 {
9807  jamEntry();
9808  const AlterTableConf* conf = (const AlterTableConf*)signal->getDataPtr();
9809  ndbrequire(refToNode(conf->senderRef) == getOwnNodeId());
9810  handleDictConf(signal, conf);
9811 }
9812 
9813 void
9814 Dbdict::execALTER_TABLE_REF(Signal* signal)
9815 {
9816  jamEntry();
9817  const AlterTableRef* ref = (const AlterTableRef*)signal->getDataPtr();
9818  ndbrequire(refToNode(ref->senderRef) == getOwnNodeId());
9819  handleDictRef(signal, ref);
9820 }
9821 
9822 // AlterTable: END
9823 
9824 /* **************************************************************** */
9825 /* ---------------------------------------------------------------- */
9826 /* MODULE: EXTERNAL INTERFACE TO DATA -------------------- */
9827 /* ---------------------------------------------------------------- */
9828 /* */
9829 /* This module contains the code that is used by other modules to. */
9830 /* access the data within DBDICT. */
9831 /* ---------------------------------------------------------------- */
9832 /* **************************************************************** */
9833 
9834 void Dbdict::execGET_TABLEDID_REQ(Signal * signal)
9835 {
9836  jamEntry();
9837  ndbrequire(signal->getNoOfSections() == 1);
9838  GetTableIdReq const * req = (GetTableIdReq *)signal->getDataPtr();
9839  Uint32 senderData = req->senderData;
9840  Uint32 senderRef = req->senderRef;
9841  Uint32 len = req->len;
9842 
9843  if(len>PATH_MAX)
9844  {
9845  jam();
9846  sendGET_TABLEID_REF((Signal*)signal,
9847  (GetTableIdReq *)req,
9848  GetTableIdRef::TableNameTooLong);
9849  return;
9850  }
9851 
9852  char tableName[PATH_MAX];
9853  SectionHandle handle(this, signal);
9854  SegmentedSectionPtr ssPtr;
9855  handle.getSection(ssPtr,GetTableIdReq::TABLE_NAME);
9856  copy((Uint32*)tableName, ssPtr);
9857  releaseSections(handle);
9858 
9859  DictObject * obj_ptr_p = get_object(tableName, len);
9860  if(obj_ptr_p == 0 || !DictTabInfo::isTable(obj_ptr_p->m_type)){
9861  jam();
9862  sendGET_TABLEID_REF(signal,
9863  (GetTableIdReq *)req,
9864  GetTableIdRef::TableNotDefined);
9865  return;
9866  }
9867 
9868  TableRecordPtr tablePtr;
9869  c_tableRecordPool.getPtr(tablePtr, obj_ptr_p->m_id);
9870 
9871  GetTableIdConf * conf = (GetTableIdConf *)req;
9872  conf->tableId = tablePtr.p->tableId;
9873  conf->schemaVersion = tablePtr.p->tableVersion;
9874  conf->senderData = senderData;
9875  sendSignal(senderRef, GSN_GET_TABLEID_CONF, signal,
9876  GetTableIdConf::SignalLength, JBB);
9877 }
9878 
9879 
9880 void Dbdict::sendGET_TABLEID_REF(Signal* signal,
9881  GetTableIdReq * req,
9882  GetTableIdRef::ErrorCode errorCode)
9883 {
9884  GetTableIdRef * const ref = (GetTableIdRef *)req;
9888  BlockReference retRef = req->senderRef;
9889  ref->err = errorCode;
9890  sendSignal(retRef, GSN_GET_TABLEID_REF, signal,
9891  GetTableIdRef::SignalLength, JBB);
9892 }
9893 
9894 /* ---------------------------------------------------------------- */
9895 // Get a full table description.
9896 /* ---------------------------------------------------------------- */
9897 void Dbdict::execGET_TABINFOREQ(Signal* signal)
9898 {
9899  jamEntry();
9900  if(!assembleFragments(signal))
9901  {
9902  return;
9903  }
9904 
9905  GetTabInfoReq * const req = (GetTabInfoReq *)&signal->theData[0];
9906  SectionHandle handle(this, signal);
9907 
9912  bool fromTimeQueue = (signal->senderBlockRef() == reference());
9913 
9914  if (c_retrieveRecord.busyState && fromTimeQueue == true) {
9915  jam();
9916 
9917  sendSignalWithDelay(reference(), GSN_GET_TABINFOREQ, signal, 30,
9918  signal->length(),
9919  &handle);
9920  return;
9921  }//if
9922 
9923  const Uint32 MAX_WAITERS = 5;
9924 
9925  if(c_retrieveRecord.busyState && fromTimeQueue == false)
9926  {
9927  jam();
9928  if(c_retrieveRecord.noOfWaiters < MAX_WAITERS){
9929  jam();
9930  c_retrieveRecord.noOfWaiters++;
9931 
9932  sendSignalWithDelay(reference(), GSN_GET_TABINFOREQ, signal, 30,
9933  signal->length(),
9934  &handle);
9935  return;
9936  }
9937  releaseSections(handle);
9938  sendGET_TABINFOREF(signal, req, GetTabInfoRef::Busy, __LINE__);
9939  return;
9940  }
9941 
9942  if(fromTimeQueue){
9943  jam();
9944  c_retrieveRecord.noOfWaiters--;
9945  }
9946 
9947  const bool useLongSig = (req->requestType & GetTabInfoReq::LongSignalConf);
9948  const bool byName = (req->requestType & GetTabInfoReq::RequestByName);
9949  const Uint32 transId = req->schemaTransId;
9950 
9951  Uint32 obj_id = RNIL;
9952  if (byName) {
9953  jam();
9954  ndbrequire(handle.m_cnt == 1);
9955  const Uint32 len = req->tableNameLen;
9956 
9957  if(len > PATH_MAX){
9958  jam();
9959  releaseSections(handle);
9960  sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNameTooLong, __LINE__);
9961  return;
9962  }
9963 
9964  Uint32 tableName[(PATH_MAX + 3) / 4];
9965  SegmentedSectionPtr ssPtr;
9966  handle.getSection(ssPtr,GetTabInfoReq::TABLE_NAME);
9967  copy(tableName, ssPtr);
9968 
9969  DictObject * old_ptr_p = get_object((char*)tableName, len);
9970  if(old_ptr_p)
9971  obj_id = old_ptr_p->m_id;
9972  } else {
9973  jam();
9974  obj_id = req->tableId;
9975  }
9976  releaseSections(handle);
9977 
9978  SchemaFile::TableEntry *objEntry = 0;
9979  if(obj_id != RNIL)
9980  {
9981  XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
9982  objEntry = getTableEntry(xsf, obj_id);
9983  }
9984 
9985  // The table seached for was not found
9986  if(objEntry == 0)
9987  {
9988  jam();
9989  sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNotDefined, __LINE__);
9990  return;
9991  }//if
9992 
9993  // If istable/index, allow ADD_STARTED (not to ref)
9994 
9995  D("execGET_TABINFOREQ" << V(transId) << " " << *objEntry);
9996 
9997  if (transId != 0 && transId == objEntry->m_transId)
9998  {
9999  jam();
10000  // see own trans always
10001  }
10002  else if (refToBlock(req->senderRef) != DBUTIL &&
10003  refToBlock(req->senderRef) != SUMA)
10004  {
10005  jam();
10006  Uint32 err;
10007  if ((err = check_read_obj(objEntry)))
10008  {
10009  jam();
10010  // cannot see another uncommitted trans
10011  sendGET_TABINFOREF(signal, req, (GetTabInfoRef::ErrorCode)err, __LINE__);
10012  return;
10013  }
10014  }
10015 
10016  c_retrieveRecord.busyState = true;
10017  c_retrieveRecord.blockRef = req->senderRef;
10018  c_retrieveRecord.m_senderData = req->senderData;
10019  c_retrieveRecord.tableId = obj_id;
10020  c_retrieveRecord.currentSent = 0;
10021  c_retrieveRecord.m_useLongSig = useLongSig;
10022  c_retrieveRecord.m_table_type = objEntry->m_tableType;
10023  c_retrieveRecord.schemaTransId = transId;
10024  c_retrieveRecord.requestType = req->requestType;
10025  c_packTable.m_state = PackTable::PTS_GET_TAB;
10026 
10027  Uint32 len = 4;
10028  if(objEntry->m_tableType == DictTabInfo::Datafile)
10029  {
10030  jam();
10031 
10032  if (objEntry->m_tableState != SchemaFile::SF_CREATE)
10033  {
10034  jam();
10035 
10036  GetTabInfoReq *req= (GetTabInfoReq*)signal->getDataPtrSend();
10037  req->senderData= c_retrieveRecord.retrievePage;
10038  req->senderRef= reference();
10039  req->requestType= GetTabInfoReq::RequestById;
10040  req->tableId= obj_id;
10041  req->schemaTransId = 0;
10042 
10043  sendSignal(TSMAN_REF, GSN_GET_TABINFOREQ, signal,
10044  GetTabInfoReq::SignalLength, JBB);
10045  return;
10046  }
10047  else
10048  {
10049  jam();
10053  len = 5;
10054  signal->theData[4] = 0;
10055  }
10056  }
10057  else if(objEntry->m_tableType == DictTabInfo::LogfileGroup)
10058  {
10059  jam();
10060  if (objEntry->m_tableState != SchemaFile::SF_CREATE)
10061  {
10062  jam();
10063  GetTabInfoReq *req= (GetTabInfoReq*)signal->getDataPtrSend();
10064  req->senderData= c_retrieveRecord.retrievePage;
10065  req->senderRef= reference();
10066  req->requestType= GetTabInfoReq::RequestById;
10067  req->tableId= obj_id;
10068  req->schemaTransId = 0;
10069 
10070  sendSignal(LGMAN_REF, GSN_GET_TABINFOREQ, signal,
10071  GetTabInfoReq::SignalLength, JBB);
10072  return;
10073  }
10074  else
10075  {
10076  jam();
10080  len = 6;
10081  signal->theData[4] = 0;
10082  signal->theData[5] = 0;
10083  }
10084  }
10085 
10086  jam();
10087  signal->theData[0] = ZPACK_TABLE_INTO_PAGES;
10088  signal->theData[1] = obj_id;
10089  signal->theData[2] = objEntry->m_tableType;
10090  signal->theData[3] = c_retrieveRecord.retrievePage;
10091  sendSignal(reference(), GSN_CONTINUEB, signal, len, JBB);
10092 }//execGET_TABINFOREQ()
10093 
10094 void Dbdict::sendGetTabResponse(Signal* signal)
10095 {
10096  PageRecordPtr pagePtr;
10097  DictTabInfo * const conf = (DictTabInfo *)&signal->theData[0];
10098  conf->senderRef = reference();
10099  conf->senderData = c_retrieveRecord.m_senderData;
10100  conf->requestType = DictTabInfo::GetTabInfoConf;
10101  conf->totalLen = c_retrieveRecord.retrievedNoOfWords;
10102 
10103  c_pageRecordArray.getPtr(pagePtr, c_retrieveRecord.retrievePage);
10104  Uint32* pagePointer = (Uint32*)&pagePtr.p->word[0] + ZPAGE_HEADER_SIZE;
10105 
10106  if(c_retrieveRecord.m_useLongSig){
10107  jam();
10108  GetTabInfoConf* conf = (GetTabInfoConf*)signal->getDataPtr();
10109  conf->gci = 0;
10110  conf->tableId = c_retrieveRecord.tableId;
10111  conf->senderData = c_retrieveRecord.m_senderData;
10112  conf->totalLen = c_retrieveRecord.retrievedNoOfWords;
10113  conf->tableType = c_retrieveRecord.m_table_type;
10114 
10115  Callback c = { safe_cast(&Dbdict::initRetrieveRecord), 0 };
10116  LinearSectionPtr ptr[3];
10117  ptr[0].p = pagePointer;
10118  ptr[0].sz = c_retrieveRecord.retrievedNoOfWords;
10119  sendFragmentedSignal(c_retrieveRecord.blockRef,
10120  GSN_GET_TABINFO_CONF,
10121  signal,
10122  GetTabInfoConf::SignalLength,
10123  JBB,
10124  ptr,
10125  1,
10126  c);
10127  return;
10128  }
10129 
10130  ndbrequire(false);
10131 }//sendGetTabResponse()
10132 
10133 void Dbdict::sendGET_TABINFOREF(Signal* signal,
10134  GetTabInfoReq * req,
10135  GetTabInfoRef::ErrorCode errorCode,
10136  Uint32 errorLine)
10137 {
10138  jamEntry();
10139  const GetTabInfoReq req_copy = *req;
10140  GetTabInfoRef * const ref = (GetTabInfoRef *)&signal->theData[0];
10141 
10142  ref->senderData = req_copy.senderData;
10143  ref->senderRef = reference();
10144  ref->requestType = req_copy.requestType;
10145  ref->tableId = req_copy.tableId;
10146  ref->schemaTransId = req_copy.schemaTransId;
10147  ref->errorCode = (Uint32)errorCode;
10148  ref->errorLine = errorLine;
10149 
10150  BlockReference retRef = req_copy.senderRef;
10151  sendSignal(retRef, GSN_GET_TABINFOREF, signal,
10152  GetTabInfoRef::SignalLength, JBB);
10153 }
10154 
10155 void
10156 Dbdict::execLIST_TABLES_REQ(Signal* signal)
10157 {
10158  jamEntry();
10159  ListTablesReq * req = (ListTablesReq*)signal->getDataPtr();
10160 
10161  Uint32 senderRef = req->senderRef;
10162  Uint32 receiverVersion = getNodeInfo(refToNode(senderRef)).m_version;
10163 
10164  if (ndbd_LIST_TABLES_CONF_long_signal(receiverVersion))
10165  sendLIST_TABLES_CONF(signal, req);
10166  else
10167  sendOLD_LIST_TABLES_CONF(signal, req);
10168 }
10169 
10170 void Dbdict::sendOLD_LIST_TABLES_CONF(Signal* signal, ListTablesReq* req)
10171 {
10172  Uint32 senderRef = req->senderRef;
10173  Uint32 senderData = req->senderData;
10174  // save req flags
10175  const Uint32 reqTableId = req->oldGetTableId();
10176  const Uint32 reqTableType = req->oldGetTableType();
10177  const bool reqListNames = req->getListNames();
10178  const bool reqListIndexes = req->getListIndexes();
10179  XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
10180  // init the confs
10181  OldListTablesConf * conf = (OldListTablesConf *)signal->getDataPtrSend();
10182  conf->senderData = senderData;
10183  conf->counter = 0;
10184  Uint32 pos = 0;
10185 
10187  bool ok = c_obj_hash.first(iter);
10188  for(; ok; ok = c_obj_hash.next(iter)){
10189  Uint32 type = iter.curr.p->m_type;
10190  if ((reqTableType != (Uint32)0) && (reqTableType != type))
10191  continue;
10192 
10193  if (reqListIndexes && !DictTabInfo::isIndex(type))
10194  continue;
10195 
10196  TableRecordPtr tablePtr;
10197  if (DictTabInfo::isTable(type) || DictTabInfo::isIndex(type)){
10198  c_tableRecordPool.getPtr(tablePtr, iter.curr.p->m_id);
10199 
10200  if(reqListIndexes && (reqTableId != tablePtr.p->primaryTableId))
10201  continue;
10202 
10203  conf->tableData[pos] = 0;
10204  conf->setTableId(pos, tablePtr.i); // id
10205  conf->setTableType(pos, type); // type
10206  // state
10207 
10208  if(DictTabInfo::isTable(type))
10209  {
10210  SchemaFile::TableEntry * te = getTableEntry(xsf, tablePtr.i);
10211  switch(te->m_tableState){
10212  case SchemaFile::SF_CREATE:
10213  jam();
10214  conf->setTableState(pos, DictTabInfo::StateBuilding);
10215  break;
10216  case SchemaFile::SF_ALTER:
10217  jam();
10218  conf->setTableState(pos, DictTabInfo::StateOnline);
10219  break;
10220  case SchemaFile::SF_DROP:
10221  jam();
10222  conf->setTableState(pos, DictTabInfo::StateDropping);
10223  break;
10224  case SchemaFile::SF_IN_USE:
10225  {
10226  if (tablePtr.p->m_read_locked)
10227  {
10228  jam();
10229  conf->setTableState(pos, DictTabInfo::StateBackup);
10230  }
10231  else
10232  {
10233  jam();
10234  conf->setTableState(pos, DictTabInfo::StateOnline);
10235  }
10236  break;
10237  }
10238  default:
10239  conf->setTableState(pos, DictTabInfo::StateBroken);
10240  break;
10241  }
10242  }
10243  if (tablePtr.p->isIndex()) {
10244  switch (tablePtr.p->indexState) {
10245  case TableRecord::IS_OFFLINE:
10246  conf->setTableState(pos, DictTabInfo::StateOffline);
10247  break;
10248  case TableRecord::IS_BUILDING:
10249  conf->setTableState(pos, DictTabInfo::StateBuilding);
10250  break;
10251  case TableRecord::IS_DROPPING:
10252  conf->setTableState(pos, DictTabInfo::StateDropping);
10253  break;
10254  case TableRecord::IS_ONLINE:
10255  conf->setTableState(pos, DictTabInfo::StateOnline);
10256  break;
10257  default:
10258  conf->setTableState(pos, DictTabInfo::StateBroken);
10259  break;
10260  }
10261  }
10262  // Logging status
10263  if (! (tablePtr.p->m_bits & TableRecord::TR_Logged)) {
10264  conf->setTableStore(pos, DictTabInfo::StoreNotLogged);
10265  } else {
10266  conf->setTableStore(pos, DictTabInfo::StorePermanent);
10267  }
10268  // Temporary status
10269  if (tablePtr.p->m_bits & TableRecord::TR_Temporary) {
10270  conf->setTableTemp(pos, NDB_TEMP_TAB_TEMPORARY);
10271  } else {
10272  conf->setTableTemp(pos, NDB_TEMP_TAB_PERMANENT);
10273  }
10274  pos++;
10275  }
10276  if(DictTabInfo::isTrigger(type)){
10277  TriggerRecordPtr triggerPtr;
10278  c_triggerRecordPool.getPtr(triggerPtr, iter.curr.p->m_id);
10279 
10280  conf->tableData[pos] = 0;
10281  conf->setTableId(pos, triggerPtr.i);
10282  conf->setTableType(pos, type);
10283  switch (triggerPtr.p->triggerState) {
10284  case TriggerRecord::TS_DEFINING:
10285  conf->setTableState(pos, DictTabInfo::StateBuilding);
10286  break;
10287  case TriggerRecord::TS_OFFLINE:
10288  conf->setTableState(pos, DictTabInfo::StateOffline);
10289  break;
10290  case TriggerRecord::TS_ONLINE:
10291  conf->setTableState(pos, DictTabInfo::StateOnline);
10292  break;
10293  default:
10294  conf->setTableState(pos, DictTabInfo::StateBroken);
10295  break;
10296  }
10297  conf->setTableStore(pos, DictTabInfo::StoreNotLogged);
10298  pos++;
10299  }
10300  if (DictTabInfo::isFilegroup(type)){
10301  jam();
10302  conf->tableData[pos] = 0;
10303  conf->setTableId(pos, iter.curr.p->m_id);
10304  conf->setTableType(pos, type); // type
10305  conf->setTableState(pos, DictTabInfo::StateOnline); // XXX todo
10306  pos++;
10307  }
10308  if (DictTabInfo::isFile(type)){
10309  jam();
10310  conf->tableData[pos] = 0;
10311  conf->setTableId(pos, iter.curr.p->m_id);
10312  conf->setTableType(pos, type); // type
10313  conf->setTableState(pos, DictTabInfo::StateOnline); // XXX todo
10314  pos++;
10315  }
10316 
10317  if (pos >= OldListTablesConf::DataLength) {
10318  sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
10319  OldListTablesConf::SignalLength, JBB);
10320  conf->counter++;
10321  pos = 0;
10322  }
10323 
10324  if (! reqListNames)
10325  continue;
10326 
10327  Rope name(c_rope_pool, iter.curr.p->m_name);
10328  const Uint32 size = name.size();
10329  conf->tableData[pos] = size;
10330  pos++;
10331  if (pos >= OldListTablesConf::DataLength) {
10332  sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
10333  OldListTablesConf::SignalLength, JBB);
10334  conf->counter++;
10335  pos = 0;
10336  }
10337  Uint32 i = 0;
10338  char tmp[PATH_MAX];
10339  name.copy(tmp);
10340  while (i < size) {
10341  char* p = (char*)&conf->tableData[pos];
10342  for (Uint32 j = 0; j < 4; j++) {
10343  if (i < size)
10344  *p++ = tmp[i++];
10345  else
10346  *p++ = 0;
10347  }
10348  pos++;
10349  if (pos >= OldListTablesConf::DataLength) {
10350  sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
10351  OldListTablesConf::SignalLength, JBB);
10352  conf->counter++;
10353  pos = 0;
10354  }
10355  }
10356  }
10357  // last signal must have less than max length
10358  sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
10359  OldListTablesConf::HeaderLength + pos, JBB);
10360 }
10361 
10363 {
10364  Uint32 senderRef = req->senderRef;
10365  Uint32 senderData = req->senderData;
10366  // save req flags
10367  const Uint32 reqTableId = req->getTableId();
10368  const Uint32 reqTableType = req->getTableType();
10369  const bool reqListNames = req->getListNames();
10370  const bool reqListIndexes = req->getListIndexes();
10371  XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
10372  NodeReceiverGroup rg(senderRef);
10373 
10375  bool done = !c_obj_hash.first(iter);
10376 
10377  if (done)
10378  {
10379  /*
10380  * Empty hashtable, send empty signal
10381  */
10382  jam();
10383  ListTablesConf * const conf = (ListTablesConf*)signal->getDataPtrSend();
10384  conf->senderData = senderData;
10385  conf->noOfTables = 0;
10386  sendSignal(rg, GSN_LIST_TABLES_CONF, signal,
10387  ListTablesConf::SignalLength, JBB);
10388  return;
10389  }
10390 
10391  /*
10392  Pack table data and table names (if requested) in
10393  two signal segments and send it in one long fragmented
10394  signal
10395  */
10396  ListTablesData ltd;
10397  const Uint32 listTablesDataSizeInWords = (sizeof(ListTablesData) + 3) / 4;
10398  char tname[PATH_MAX];
10399  SimplePropertiesSectionWriter tableDataWriter(* this);
10400  SimplePropertiesSectionWriter tableNamesWriter(* this);
10401 
10402  Uint32 count = 0;
10403  Uint32 fragId = rand();
10404  Uint32 fragInfo = 0;
10405  const Uint32 fragSize = 240;
10406 
10407  tableDataWriter.first();
10408  tableNamesWriter.first();
10409  while(true)
10410  {
10411  Uint32 type = iter.curr.p->m_type;
10412 
10413  if ((reqTableType != (Uint32)0) && (reqTableType != type))
10414  goto flush;
10415 
10416  if (reqListIndexes && !DictTabInfo::isIndex(type))
10417  goto flush;
10418 
10419  TableRecordPtr tablePtr;
10420  if (DictTabInfo::isTable(type) || DictTabInfo::isIndex(type)){
10421  c_tableRecordPool.getPtr(tablePtr, iter.curr.p->m_id);
10422 
10423  if(reqListIndexes && (reqTableId != tablePtr.p->primaryTableId))
10424  goto flush;
10425 
10426  ltd.requestData = 0; // clear
10427  ltd.setTableId(tablePtr.i); // id
10428  ltd.setTableType(type); // type
10429  // state
10430 
10431  if(DictTabInfo::isTable(type)){
10432  SchemaFile::TableEntry * te = getTableEntry(xsf, tablePtr.i);
10433  switch(te->m_tableState){
10434  case SchemaFile::SF_CREATE:
10435  jam();
10436  ltd.setTableState(DictTabInfo::StateBuilding);
10437  break;
10438  case SchemaFile::SF_ALTER:
10439  jam();
10440  ltd.setTableState(DictTabInfo::StateOnline);
10441  break;
10442  case SchemaFile::SF_DROP:
10443  jam();
10444  ltd.setTableState(DictTabInfo::StateDropping);
10445  break;
10446  case SchemaFile::SF_IN_USE:
10447  {
10448  if (tablePtr.p->m_read_locked)
10449  {
10450  jam();
10451  ltd.setTableState(DictTabInfo::StateBackup);
10452  }
10453  else
10454  {
10455  jam();
10456  ltd.setTableState(DictTabInfo::StateOnline);
10457  }
10458  break;
10459  }
10460  default:
10461  ltd.setTableState(DictTabInfo::StateBroken);
10462  break;
10463  }
10464  }
10465  if (tablePtr.p->isIndex()) {
10466  switch (tablePtr.p->indexState) {
10467  case TableRecord::IS_OFFLINE:
10468  ltd.setTableState(DictTabInfo::StateOffline);
10469  break;
10470  case TableRecord::IS_BUILDING:
10471  ltd.setTableState(DictTabInfo::StateBuilding);
10472  break;
10473  case TableRecord::IS_DROPPING:
10474  ltd.setTableState(DictTabInfo::StateDropping);
10475  break;
10476  case TableRecord::IS_ONLINE:
10477  ltd.setTableState(DictTabInfo::StateOnline);
10478  break;
10479  default:
10480  ltd.setTableState(DictTabInfo::StateBroken);
10481  break;
10482  }
10483  }
10484  // Logging status
10485  if (! (tablePtr.p->m_bits & TableRecord::TR_Logged)) {
10486  ltd.setTableStore(DictTabInfo::StoreNotLogged);
10487  } else {
10488  ltd.setTableStore(DictTabInfo::StorePermanent);
10489  }
10490  // Temporary status
10491  if (tablePtr.p->m_bits & TableRecord::TR_Temporary) {
10492  ltd.setTableTemp(NDB_TEMP_TAB_TEMPORARY);
10493  } else {
10494  ltd.setTableTemp(NDB_TEMP_TAB_PERMANENT);
10495  }
10496  }
10497  if(DictTabInfo::isTrigger(type)){
10498  TriggerRecordPtr triggerPtr;
10499  c_triggerRecordPool.getPtr(triggerPtr, iter.curr.p->m_id);
10500 
10501  ltd.requestData = 0;
10502  ltd.setTableId(triggerPtr.i);
10503  ltd.setTableType(type);
10504  switch (triggerPtr.p->triggerState) {
10505  case TriggerRecord::TS_DEFINING:
10506  ltd.setTableState(DictTabInfo::StateBuilding);
10507  break;
10508  case TriggerRecord::TS_OFFLINE:
10509  ltd.setTableState(DictTabInfo::StateOffline);
10510  break;
10511  case TriggerRecord::TS_ONLINE:
10512  ltd.setTableState(DictTabInfo::StateOnline);
10513  break;
10514  default:
10515  ltd.setTableState(DictTabInfo::StateBroken);
10516  break;
10517  }
10518  ltd.setTableStore(DictTabInfo::StoreNotLogged);
10519  }
10520  if (DictTabInfo::isFilegroup(type)){
10521  jam();
10522  ltd.requestData = 0;
10523  ltd.setTableId(iter.curr.p->m_id);
10524  ltd.setTableType(type); // type
10525  ltd.setTableState(DictTabInfo::StateOnline); // XXX todo
10526  }
10527  if (DictTabInfo::isFile(type)){
10528  jam();
10529  ltd.requestData = 0;
10530  ltd.setTableId(iter.curr.p->m_id);
10531  ltd.setTableType(type); // type
10532  ltd.setTableState(DictTabInfo::StateOnline); // XXX todo
10533  }
10534  if (DictTabInfo::isHashMap(type))
10535  {
10536  jam();
10537  ltd.setTableId(iter.curr.p->m_id);
10538  ltd.setTableType(type); // type
10539  ltd.setTableState(DictTabInfo::StateOnline); // XXX todo
10540  }
10541  tableDataWriter.putWords((Uint32 *) &ltd, listTablesDataSizeInWords);
10542  count++;
10543 
10544  if (reqListNames)
10545  {
10546  jam();
10547  Rope name(c_rope_pool, iter.curr.p->m_name);
10548  const Uint32 size = name.size(); // String length including \0
10549  const Uint32 wsize = (size + 3) / 4;
10550  tableNamesWriter.putWord(size);
10551  name.copy(tname);
10552  tableNamesWriter.putWords((Uint32 *) tname, wsize);
10553  }
10554 
10555 flush:
10556  Uint32 tableDataWords = tableDataWriter.getWordsUsed();
10557  Uint32 tableNameWords = tableNamesWriter.getWordsUsed();
10558 
10559  done = !c_obj_hash.next(iter);
10560  if ((tableDataWords + tableNameWords) > fragSize || done)
10561  {
10562  jam();
10563 
10564  /*
10565  * Flush signal fragment to keep memory usage down
10566  */
10567  Uint32 sigLen = ListTablesConf::SignalLength;
10568  Uint32 secs = 0;
10569  if (tableDataWords != 0)
10570  {
10571  jam();
10572  secs++;
10573  }
10574  if (tableNameWords != 0)
10575  {
10576  jam();
10577  secs++;
10578  }
10579  Uint32 * secNos = &signal->theData[sigLen];
10580  signal->theData[sigLen + secs] = fragId;
10581  SectionHandle handle(this);
10582  switch (secs) {
10583  case(0):
10584  jam();
10585  sigLen++; // + fragId;
10586  handle.m_cnt = 0;
10587  break;
10588  case(1):
10589  {
10590  jam();
10591  SegmentedSectionPtr segSecPtr;
10592  sigLen += 2; // 1 sections + fragid
10593  if (tableNameWords == 0)
10594  {
10595  tableDataWriter.getPtr(segSecPtr);
10596  secNos[0] = ListTablesConf::TABLE_DATA;;
10597  }
10598  else
10599  {
10600  tableNamesWriter.getPtr(segSecPtr);
10601  secNos[0] = ListTablesConf::TABLE_NAMES;
10602  }
10603  handle.m_ptr[0] = segSecPtr;
10604  handle.m_cnt = 1;
10605  break;
10606  }
10607  case(2):
10608  {
10609  jam();
10610  sigLen += 3; // 2 sections + fragid
10611  SegmentedSectionPtr tableDataPtr;
10612  tableDataWriter.getPtr(tableDataPtr);
10613  SegmentedSectionPtr tableNamesPtr;
10614  tableNamesWriter.getPtr(tableNamesPtr);
10615  handle.m_ptr[0] = tableDataPtr;
10616  handle.m_ptr[1] = tableNamesPtr;
10617  handle.m_cnt = 2;
10618  secNos[0] = ListTablesConf::TABLE_DATA;
10619  secNos[1] = ListTablesConf::TABLE_NAMES;
10620  break;
10621  }
10622  }
10623 
10624  if (done)
10625  {
10626  jam();
10627  if (fragInfo)
10628  {
10629  jam();
10630  fragInfo = 3;
10631  }
10632  }
10633  else
10634  {
10635  jam();
10636  if (fragInfo == 0)
10637  {
10638  jam();
10639  fragInfo = 1;
10640  }
10641  else
10642  {
10643  jam();
10644  fragInfo = 2;
10645  }
10646  }
10647  signal->header.m_fragmentInfo = fragInfo;
10648 
10649  ListTablesConf * const conf = (ListTablesConf*)signal->getDataPtrSend();
10650  conf->senderData = senderData;
10651  conf->noOfTables = count;
10652  sendSignal(rg, GSN_LIST_TABLES_CONF, signal,
10653  sigLen, JBB, &handle);
10654 
10655  signal->header.m_noOfSections = 0;
10656  signal->header.m_fragmentInfo = 0;
10657 
10658  if (done)
10659  {
10660  jam();
10661  return;
10662  }
10663 
10668  count = 0;
10669  tableDataWriter.first();
10670  tableNamesWriter.first();
10671  }
10672  }
10673 }
10674 
10675 // MODULE: CreateIndex
10676 
10677 const Dbdict::OpInfo
10678 Dbdict::CreateIndexRec::g_opInfo = {
10679  { 'C', 'I', 'n', 0 },
10680  GSN_CREATE_INDX_IMPL_REQ,
10681  CreateIndxImplReq::SignalLength,
10682  //
10683  &Dbdict::createIndex_seize,
10684  &Dbdict::createIndex_release,
10685  //
10686  &Dbdict::createIndex_parse,
10687  &Dbdict::createIndex_subOps,
10688  &Dbdict::createIndex_reply,
10689  //
10690  &Dbdict::createIndex_prepare,
10691  &Dbdict::createIndex_commit,
10692  &Dbdict::createIndex_complete,
10693  //
10694  &Dbdict::createIndex_abortParse,
10695  &Dbdict::createIndex_abortPrepare
10696 };
10697 
10698 bool
10699 Dbdict::createIndex_seize(SchemaOpPtr op_ptr)
10700 {
10701  return seizeOpRec<CreateIndexRec>(op_ptr);
10702 }
10703 
10704 void
10705 Dbdict::createIndex_release(SchemaOpPtr op_ptr)
10706 {
10707  releaseOpRec<CreateIndexRec>(op_ptr);
10708 }
10709 
10710 void
10711 Dbdict::execCREATE_INDX_REQ(Signal* signal)
10712 {
10713  jamEntry();
10714  if (!assembleFragments(signal)) {
10715  jam();
10716  return;
10717  }
10718  SectionHandle handle(this, signal);
10719 
10720  if (check_sender_version(signal, MAKE_VERSION(6,4,0)) < 0)
10721  {
10722  jam();
10727  CreateIndxReq * tmp = (CreateIndxReq*)signal->getDataPtr();
10728  do_swap(tmp->clientRef, tmp->clientData);
10729  }
10730 
10731  const CreateIndxReq req_copy =
10732  *(const CreateIndxReq*)signal->getDataPtr();
10733  const CreateIndxReq* req = &req_copy;
10734 
10735  ErrorInfo error;
10736  do {
10737  SchemaOpPtr op_ptr;
10738  CreateIndexRecPtr createIndexPtr;
10739  CreateIndxImplReq* impl_req;
10740 
10741  startClientReq(op_ptr, createIndexPtr, req, impl_req, error);
10742  if (hasError(error)) {
10743  jam();
10744  break;
10745  }
10746 
10747  impl_req->tableId = req->tableId;
10748  impl_req->tableVersion = req->tableVersion;
10749  impl_req->indexType = req->indexType;
10750  // these are set in sub-operation create table
10751  impl_req->indexId = RNIL;
10752  impl_req->indexVersion = 0;
10753 
10754  handleClientReq(signal, op_ptr, handle);
10755  return;
10756  } while (0);
10757 
10758  releaseSections(handle);
10759 
10760  CreateIndxRef* ref = (CreateIndxRef*)signal->getDataPtrSend();
10761 
10762  ref->senderRef = reference();
10763  ref->clientData = req->clientData;
10764  ref->transId = req->transId;
10765  getError(error, ref);
10766 
10767  sendSignal(req->clientRef, GSN_CREATE_INDX_REF, signal,
10768  CreateIndxRef::SignalLength, JBB);
10769 }
10770 
10771 // CreateIndex: PARSE
10772 
10773 void
10774 Dbdict::createIndex_parse(Signal* signal, bool master,
10775  SchemaOpPtr op_ptr,
10776  SectionHandle& handle, ErrorInfo& error)
10777 {
10778  D("createIndex_parse");
10779 
10780  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
10781  CreateIndexRecPtr createIndexPtr;
10782  getOpRec(op_ptr, createIndexPtr);
10783  CreateIndxImplReq* impl_req = &createIndexPtr.p->m_request;
10784 
10785  // save attribute list
10786  IndexAttributeList& attrList = createIndexPtr.p->m_attrList;
10787  {
10788  SegmentedSectionPtr ss_ptr;
10789  handle.getSection(ss_ptr, CreateIndxReq::ATTRIBUTE_LIST_SECTION);
10790  SimplePropertiesSectionReader r(ss_ptr, getSectionSegmentPool());
10791  r.reset(); // undo implicit first()
10792  if (!r.getWord(&attrList.sz) ||
10793  r.getSize() != 1 + attrList.sz ||
10794  attrList.sz == 0 ||
10795  attrList.sz > MAX_ATTRIBUTES_IN_INDEX ||
10796  !r.getWords(attrList.id, attrList.sz)) {
10797  jam();
10798  setError(error, CreateIndxRef::InvalidIndexType, __LINE__);
10799  return;
10800  }
10801  }
10802 
10803  // save name and some index table properties
10804  Uint32& bits = createIndexPtr.p->m_bits;
10805  bits = TableRecord::TR_RowChecksum;
10806  {
10807  SegmentedSectionPtr ss_ptr;
10808  handle.getSection(ss_ptr, CreateIndxReq::INDEX_NAME_SECTION);
10809  SimplePropertiesSectionReader r(ss_ptr, getSectionSegmentPool());
10810  DictTabInfo::Table tableDesc;
10811  tableDesc.init();
10813  SimpleProperties::unpack(
10814  r, &tableDesc,
10815  DictTabInfo::TableMapping, DictTabInfo::TableMappingSize,
10816  true, true);
10817  if (status != SimpleProperties::Eof ||
10818  tableDesc.TableName[0] == 0)
10819  {
10820  ndbassert(false);
10821  setError(error, CreateIndxRef::InvalidName, __LINE__);
10822  return;
10823  }
10824  const Uint32 bytesize = sizeof(createIndexPtr.p->m_indexName);
10825  memcpy(createIndexPtr.p->m_indexName, tableDesc.TableName, bytesize);
10826  if (tableDesc.TableLoggedFlag) {
10827  jam();
10828  bits |= TableRecord::TR_Logged;
10829  }
10830  if (tableDesc.TableTemporaryFlag) {
10831  jam();
10832  bits |= TableRecord::TR_Temporary;
10833  }
10834  D("index " << createIndexPtr.p->m_indexName);
10835  }
10836 
10837  // check primary table
10838  TableRecordPtr tablePtr;
10839  {
10840  if (!(impl_req->tableId < c_tableRecordPool.getSize())) {
10841  jam();
10842  setError(error, CreateIndxRef::InvalidPrimaryTable, __LINE__);
10843  return;
10844  }
10845  c_tableRecordPool.getPtr(tablePtr, impl_req->tableId);
10846 
10847  if (!tablePtr.p->isTable()) {
10848  jam();
10849  setError(error, CreateIndxRef::InvalidPrimaryTable, __LINE__);
10850  return;
10851  }
10852 
10853  Uint32 err;
10854  if ((err = check_read_obj(tablePtr.i, trans_ptr.p->m_transId)))
10855  {
10856  jam();
10857  setError(error, err, __LINE__);
10858  return;
10859  }
10860  }
10861 
10862  // check index type and set more properties
10863  {
10864  switch (impl_req->indexType) {
10865  case DictTabInfo::UniqueHashIndex:
10866  jam();
10867  createIndexPtr.p->m_fragmentType = DictTabInfo::HashMapPartition;
10868  break;
10869  case DictTabInfo::OrderedIndex:
10870  jam();
10871  if (bits & TableRecord::TR_Logged) {
10872  jam();
10873  setError(error, CreateIndxRef::InvalidIndexType, __LINE__);
10874  return;
10875  }
10876  createIndexPtr.p->m_fragmentType = DictTabInfo::DistrKeyOrderedIndex;
10877  // hash case is computed later from attribute list
10878  createIndexPtr.p->m_indexKeyLength = MAX_TTREE_NODE_SIZE;
10879  break;
10880  default:
10881  setError(error, CreateIndxRef::InvalidIndexType, __LINE__);
10882  return;
10883  }
10884  }
10885 
10886  // check that the temporary status of index is compatible with table
10887  {
10888  if (!(bits & TableRecord::TR_Temporary) &&
10889  (tablePtr.p->m_bits & TableRecord::TR_Temporary))
10890  {
10891  jam();
10892  setError(error, CreateIndxRef::TableIsTemporary, __LINE__);
10893  return;
10894  }
10895  if ((bits & TableRecord::TR_Temporary) &&
10896  !(tablePtr.p->m_bits & TableRecord::TR_Temporary))
10897  {
10898  // This could be implemented later, but mysqld does currently not detect
10899  // that the index disappears after SR, and it appears not too useful.
10900  jam();
10901  setError(error, CreateIndxRef::TableIsNotTemporary, __LINE__);
10902  return;
10903  }
10904  if ((bits & TableRecord::TR_Temporary) &&
10905  (bits & TableRecord::TR_Logged))
10906  {
10907  jam();
10908  setError(error, CreateIndxRef::NoLoggingTemporaryIndex, __LINE__);
10909  return;
10910  }
10911  }
10912 
10913  // check attribute list
10914  AttributeMask& attrMask = createIndexPtr.p->m_attrMask;
10915  AttributeMap& attrMap = createIndexPtr.p->m_attrMap;
10916  {
10917  Uint32 k;
10918  for (k = 0; k < attrList.sz; k++) {
10919  jam();
10920  Uint32 current_id = attrList.id[k];
10921  AttributeRecordPtr attrPtr;
10922 
10923  // find the attribute
10924  {
10926  list(c_attributeRecordPool, tablePtr.p->m_attributes);
10927  list.first(attrPtr);
10928  while (!attrPtr.isNull()) {
10929  jam();
10930  if (attrPtr.p->attributeId == current_id) {
10931  jam();
10932  break;
10933  }
10934  list.next(attrPtr);
10935  }
10936  }
10937  if (attrPtr.isNull()) {
10938  jam();
10939  ndbassert(false);
10940  setError(error, CreateIndxRef::BadRequestType, __LINE__);
10941  return;
10942  }
10943 
10944  // add attribute to mask
10945  if (attrMask.get(current_id)) {
10946  jam();
10947  setError(error, CreateIndxRef::DuplicateAttributes, __LINE__);
10948  return;
10949  }
10950  attrMask.set(current_id);
10951 
10952  // check disk based
10953  const Uint32 attrDesc = attrPtr.p->attributeDescriptor;
10954  if (AttributeDescriptor::getDiskBased(attrDesc)) {
10955  jam();
10956  setError(error, CreateIndxRef::IndexOnDiskAttributeError, __LINE__);
10957  return;
10958  }
10959 
10960  // re-order hash index by attribute id
10961  Uint32 new_index = k;
10962  if (impl_req->indexType == DictTabInfo::UniqueHashIndex) {
10963  jam();
10964  // map contains (old_index,attr_id) ordered by attr_id
10965  while (new_index > 0) {
10966  jam();
10967  if (current_id >= attrMap[new_index - 1].attr_id) {
10968  jam();
10969  break;
10970  }
10971  attrMap[new_index] = attrMap[new_index - 1];
10972  new_index--;
10973  }
10974  }
10975  attrMap[new_index].old_index = k;
10976  attrMap[new_index].attr_id = current_id;
10977  attrMap[new_index].attr_ptr_i = attrPtr.i;
10978 
10979  // add key size for hash index (ordered case was handled before)
10980  if (impl_req->indexType == DictTabInfo::UniqueHashIndex) {
10981  jam();
10982  const Uint32 s1 = AttributeDescriptor::getSize(attrDesc);
10983  const Uint32 s2 = AttributeDescriptor::getArraySize(attrDesc);
10984  createIndexPtr.p->m_indexKeyLength += ((1 << s1) * s2 + 31) >> 5;
10985  }
10986  }
10987  }
10988 
10989  if (master)
10990  {
10991  jam();
10992  impl_req->indexId = getFreeObjId(0);
10993  }
10994 
10995  if (impl_req->indexId == RNIL)
10996  {
10997  jam();
10998  setError(error, CreateTableRef::NoMoreTableRecords, __LINE__);
10999  return;
11000  }
11001 
11002  if (impl_req->indexId >= c_tableRecordPool.getSize())
11003  {
11004  jam();
11005  setError(error, CreateTableRef::NoMoreTableRecords, __LINE__);
11006  return;
11007  }
11008 
11009  if (ERROR_INSERTED(6122)) {
11010  jam();
11011  CLEAR_ERROR_INSERT_VALUE;
11012  setError(error, 9122, __LINE__);
11013  return;
11014  }
11015 }
11016 
11017 bool
11018 Dbdict::createIndex_subOps(Signal* signal, SchemaOpPtr op_ptr)
11019 {
11020  D("createIndex_subOps" << V(op_ptr.i) << *op_ptr.p);
11021 
11022  CreateIndexRecPtr createIndexPtr;
11023  getOpRec(op_ptr, createIndexPtr);
11024 
11025  // op to create index table
11026  if (!createIndexPtr.p->m_sub_create_table) {
11027  jam();
11028  Callback c = {
11029  safe_cast(&Dbdict::createIndex_fromCreateTable),
11030  op_ptr.p->op_key
11031  };
11032  op_ptr.p->m_callback = c;
11033  createIndex_toCreateTable(signal, op_ptr);
11034  return true;
11035  }
11036  // op to alter index online
11037  if (!createIndexPtr.p->m_sub_alter_index) {
11038  jam();
11039  Callback c = {
11040  safe_cast(&Dbdict::createIndex_fromAlterIndex),
11041  op_ptr.p->op_key
11042  };
11043  op_ptr.p->m_callback = c;
11044  createIndex_toAlterIndex(signal, op_ptr);
11045  return true;
11046  }
11047  return false;
11048 }
11049 
11050 void
11051 Dbdict::createIndex_toCreateTable(Signal* signal, SchemaOpPtr op_ptr)
11052 {
11053  D("createIndex_toCreateTable");
11054 
11055  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
11056  CreateIndexRecPtr createIndexPtr;
11057  getOpRec(op_ptr, createIndexPtr);
11058 
11059  TableRecordPtr tablePtr;
11060  c_tableRecordPool.getPtr(tablePtr, createIndexPtr.p->m_request.tableId);
11061  ndbrequire(tablePtr.i == tablePtr.p->tableId);
11062 
11063  // signal data writer
11064  Uint32* wbuffer = &c_indexPage.word[0];
11065  LinearWriter w(wbuffer, sizeof(c_indexPage) >> 2);
11066  w.first();
11067 
11068  //indexPtr.p->noOfPrimkey = indexPtr.p->noOfAttributes;
11069  // plus concatenated primary table key attribute
11070  //indexPtr.p->noOfAttributes += 1;
11071  //indexPtr.p->noOfNullAttr = 0;
11072 
11073  w.add(DictTabInfo::TableId, createIndexPtr.p->m_request.indexId);
11074  w.add(DictTabInfo::TableName, createIndexPtr.p->m_indexName);
11075  { bool flag = createIndexPtr.p->m_bits & TableRecord::TR_Logged;
11076  w.add(DictTabInfo::TableLoggedFlag, (Uint32)flag);
11077  }
11078  { bool flag = createIndexPtr.p->m_bits & TableRecord::TR_Temporary;
11079  w.add(DictTabInfo::TableTemporaryFlag, (Uint32)flag);
11080  }
11081  w.add(DictTabInfo::FragmentTypeVal, createIndexPtr.p->m_fragmentType);
11082  w.add(DictTabInfo::TableTypeVal, createIndexPtr.p->m_request.indexType);
11083  { Rope name(c_rope_pool, tablePtr.p->tableName);
11084  char tableName[MAX_TAB_NAME_SIZE];
11085  name.copy(tableName);
11086  w.add(DictTabInfo::PrimaryTable, tableName);
11087  }
11088  w.add(DictTabInfo::PrimaryTableId, tablePtr.p->tableId);
11089  w.add(DictTabInfo::NoOfAttributes, createIndexPtr.p->m_attrList.sz + 1);
11090  w.add(DictTabInfo::NoOfKeyAttr, createIndexPtr.p->m_attrList.sz);//XXX ordered??
11091  w.add(DictTabInfo::NoOfNullable, (Uint32)0);
11092  w.add(DictTabInfo::KeyLength, createIndexPtr.p->m_indexKeyLength);
11093  w.add(DictTabInfo::SingleUserMode, (Uint32)NDB_SUM_READ_WRITE);
11094 
11095  // write index key attributes
11096 
11097  //const IndexAttributeList& attrList = createIndexPtr.p->m_attrList;
11098  const AttributeMap& attrMap = createIndexPtr.p->m_attrMap;
11099  Uint32 k;
11100  for (k = 0; k < createIndexPtr.p->m_attrList.sz; k++) {
11101  jam();
11102  // insert the attributes in the order decided before in attrMap
11103  // TODO: make sure "old_index" is stored with the table and
11104  // passed up to NdbDictionary
11105  AttributeRecordPtr attrPtr;
11106  c_attributeRecordPool.getPtr(attrPtr, attrMap[k].attr_ptr_i);
11107 
11108  { Rope attrName(c_rope_pool, attrPtr.p->attributeName);
11109  char attributeName[MAX_ATTR_NAME_SIZE];
11110  attrName.copy(attributeName);
11111  w.add(DictTabInfo::AttributeName, attributeName);
11112  }
11113 
11114  const Uint32 attrDesc = attrPtr.p->attributeDescriptor;
11115  const bool isNullable = AttributeDescriptor::getNullable(attrDesc);
11116  const Uint32 arrayType = AttributeDescriptor::getArrayType(attrDesc);
11117  const Uint32 attrType = AttributeDescriptor::getType(attrDesc);
11118 
11119  w.add(DictTabInfo::AttributeId, k);
11120  if (createIndexPtr.p->m_request.indexType == DictTabInfo::UniqueHashIndex) {
11121  jam();
11122  w.add(DictTabInfo::AttributeKeyFlag, (Uint32)true);
11123  w.add(DictTabInfo::AttributeNullableFlag, (Uint32)false);
11124  }
11125  if (createIndexPtr.p->m_request.indexType == DictTabInfo::OrderedIndex) {
11126  jam();
11127  w.add(DictTabInfo::AttributeKeyFlag, (Uint32)false);
11128  w.add(DictTabInfo::AttributeNullableFlag, (Uint32)isNullable);
11129  }
11130  w.add(DictTabInfo::AttributeArrayType, arrayType);
11131  w.add(DictTabInfo::AttributeExtType, attrType);
11132  w.add(DictTabInfo::AttributeExtPrecision, attrPtr.p->extPrecision);
11133  w.add(DictTabInfo::AttributeExtScale, attrPtr.p->extScale);
11134  w.add(DictTabInfo::AttributeExtLength, attrPtr.p->extLength);
11135  w.add(DictTabInfo::AttributeEnd, (Uint32)true);
11136  }
11137 
11138  if (createIndexPtr.p->m_request.indexType == DictTabInfo::UniqueHashIndex) {
11139  jam();
11140  Uint32 key_type = NDB_ARRAYTYPE_FIXED;
11141  AttributeRecordPtr attrPtr;
11142  LocalDLFifoList<AttributeRecord> list(c_attributeRecordPool,
11143  tablePtr.p->m_attributes);
11144  // XXX move to parse
11145  for (list.first(attrPtr); !attrPtr.isNull(); list.next(attrPtr))
11146  {
11147  const Uint32 desc = attrPtr.p->attributeDescriptor;
11148  if (AttributeDescriptor::getPrimaryKey(desc) &&
11149  AttributeDescriptor::getArrayType(desc) != NDB_ARRAYTYPE_FIXED)
11150  {
11151  key_type = NDB_ARRAYTYPE_MEDIUM_VAR;
11152  if (NDB_VERSION_D >= MAKE_VERSION(7,1,0))
11153  {
11154  jam();
11163  key_type = NDB_ARRAYTYPE_NONE_VAR;
11164  }
11165  break;
11166  }
11167  }
11168 
11169  // write concatenated primary table key attribute i.e. keyinfo
11170  w.add(DictTabInfo::AttributeName, "NDB$PK");
11171  w.add(DictTabInfo::AttributeId, createIndexPtr.p->m_attrList.sz);
11172  w.add(DictTabInfo::AttributeArrayType, key_type);
11173  w.add(DictTabInfo::AttributeKeyFlag, (Uint32)false);
11174  w.add(DictTabInfo::AttributeNullableFlag, (Uint32)false);
11175  w.add(DictTabInfo::AttributeExtType, (Uint32)DictTabInfo::ExtUnsigned);
11176  w.add(DictTabInfo::AttributeExtLength, tablePtr.p->tupKeyLength+1);
11177  w.add(DictTabInfo::AttributeEnd, (Uint32)true);
11178  }
11179  if (createIndexPtr.p->m_request.indexType == DictTabInfo::OrderedIndex) {
11180  jam();
11181  // write index tree node as Uint32 array attribute
11182  w.add(DictTabInfo::AttributeName, "NDB$TNODE");
11183  w.add(DictTabInfo::AttributeId, createIndexPtr.p->m_attrList.sz);
11184  // should not matter but VAR crashes in TUP
11185  w.add(DictTabInfo::AttributeArrayType, (Uint32)NDB_ARRAYTYPE_FIXED);
11186  w.add(DictTabInfo::AttributeKeyFlag, (Uint32)true);
11187  w.add(DictTabInfo::AttributeNullableFlag, (Uint32)false);
11188  w.add(DictTabInfo::AttributeExtType, (Uint32)DictTabInfo::ExtUnsigned);
11189  w.add(DictTabInfo::AttributeExtLength, createIndexPtr.p->m_indexKeyLength);
11190  w.add(DictTabInfo::AttributeEnd, (Uint32)true);
11191  }
11192  // finish
11193  w.add(DictTabInfo::TableEnd, (Uint32)true);
11194 
11195  CreateTableReq* req = (CreateTableReq*)signal->getDataPtrSend();
11196 
11197  Uint32 requestInfo = 0;
11198  DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
11199 
11200  req->clientRef = reference();
11201  req->clientData = op_ptr.p->op_key;
11202  req->transId = trans_ptr.p->m_transId;
11203  req->transKey = trans_ptr.p->trans_key;
11204  req->requestInfo = requestInfo;
11205 
11206  LinearSectionPtr lsPtr[3];
11207  lsPtr[0].p = wbuffer;
11208  lsPtr[0].sz = w.getWordsUsed();
11209  sendSignal(reference(), GSN_CREATE_TABLE_REQ, signal,
11210  CreateTableReq::SignalLength, JBB, lsPtr, 1);
11211 }
11212 
11213 void
11214 Dbdict::createIndex_fromCreateTable(Signal* signal, Uint32 op_key, Uint32 ret)
11215 {
11216  jam();
11217  D("createIndex_fromCreateTable" << dec << V(op_key) << V(ret));
11218 
11219  SchemaOpPtr op_ptr;
11220  CreateIndexRecPtr createIndexPtr;
11221 
11222  findSchemaOp(op_ptr, createIndexPtr, op_key);
11223  ndbrequire(!op_ptr.isNull());
11224  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
11225  CreateIndxImplReq* impl_req = &createIndexPtr.p->m_request;
11226 
11227  if (ret == 0) {
11228  const CreateTableConf* conf =
11229  (const CreateTableConf*)signal->getDataPtr();
11230 
11231  ndbrequire(conf->transId == trans_ptr.p->m_transId);
11232  impl_req->indexVersion = conf->tableVersion;
11233  createIndexPtr.p->m_sub_create_table = true;
11234 
11235  createSubOps(signal, op_ptr);
11236  } else {
11237  jam();
11238  const CreateTableRef* ref =
11239  (const CreateTableRef*)signal->getDataPtr();
11240  ErrorInfo error;
11241  setError(error, ref);
11242  abortSubOps(signal, op_ptr, error);
11243  }
11244 }
11245 
11246 void
11247 Dbdict::createIndex_toAlterIndex(Signal* signal, SchemaOpPtr op_ptr)
11248 {
11249  D("createIndex_toAlterIndex");
11250 
11251  AlterIndxReq* req = (AlterIndxReq*)signal->getDataPtrSend();
11252 
11253  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
11254  CreateIndexRecPtr createIndexPtr;
11255  getOpRec(op_ptr, createIndexPtr);
11256 
11257  Uint32 requestInfo = 0;
11258  DictSignal::setRequestType(requestInfo, AlterIndxImplReq::AlterIndexOnline);
11259  DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
11260 
11261  if (op_ptr.p->m_requestInfo & CreateIndxReq::RF_BUILD_OFFLINE)
11262  {
11263  jam();
11264  requestInfo |= AlterIndxReq::RF_BUILD_OFFLINE;
11265  }
11266 
11267  req->clientRef = reference();
11268  req->clientData = op_ptr.p->op_key;
11269  req->transId = trans_ptr.p->m_transId;
11270  req->transKey = trans_ptr.p->trans_key;
11271  req->requestInfo = requestInfo;
11272  req->indexId = createIndexPtr.p->m_request.indexId;
11273  req->indexVersion = createIndexPtr.p->m_request.indexVersion;
11274 
11275  sendSignal(reference(), GSN_ALTER_INDX_REQ, signal,
11276  AlterIndxReq::SignalLength, JBB);
11277 }
11278 
11279 void
11280 Dbdict::createIndex_fromAlterIndex(Signal* signal, Uint32 op_key, Uint32 ret)
11281 {
11282  jam();
11283  D("createIndex_fromAlterIndex");
11284 
11285  SchemaOpPtr op_ptr;
11286  CreateIndexRecPtr createIndexPtr;
11287 
11288  findSchemaOp(op_ptr, createIndexPtr, op_key);
11289  ndbrequire(!op_ptr.isNull());
11290  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
11291 
11292  //Uint32 errorCode = 0;
11293  if (ret == 0) {
11294  const AlterIndxConf* conf =
11295  (const AlterIndxConf*)signal->getDataPtr();
11296 
11297  ndbrequire(conf->transId == trans_ptr.p->m_transId);
11298  createIndexPtr.p->m_sub_alter_index = true;
11299  createSubOps(signal, op_ptr);
11300  } else {
11301  jam();
11302  const AlterIndxRef* ref =
11303  (const AlterIndxRef*)signal->getDataPtr();
11304 
11305  ErrorInfo error;
11306  setError(error, ref);
11307  abortSubOps(signal, op_ptr, error);
11308  }
11309 }
11310 
11311 void
11312 Dbdict::createIndex_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
11313 {
11314  jam();
11315  D("createIndex_reply");
11316 
11317  SchemaTransPtr& trans_ptr = op_ptr.p->m_trans_ptr;
11318  CreateIndexRecPtr createIndexPtr;
11319  getOpRec(op_ptr, createIndexPtr);
11320  const CreateIndxImplReq* impl_req = &createIndexPtr.p->m_request;
11321 
11322  if (!hasError(error)) {
11323  CreateIndxConf* conf = (CreateIndxConf*)signal->getDataPtrSend();
11324  conf->senderRef = reference();
11325  conf->clientData = op_ptr.p->m_clientData;
11326  conf->transId = trans_ptr.p->m_transId;
11327  conf->indexId = impl_req->indexId;
11328  conf->indexVersion = impl_req->indexVersion;
11329 
11330  D(V(conf->indexId) << V(conf->indexVersion));
11331 
11332  Uint32 clientRef = op_ptr.p->m_clientRef;
11333  sendSignal(clientRef, GSN_CREATE_INDX_CONF, signal,
11334  CreateIndxConf::SignalLength, JBB);
11335  } else {
11336  jam();
11337  CreateIndxRef* ref = (CreateIndxRef*)signal->getDataPtrSend();
11338  ref->senderRef = reference();
11339  ref->clientData = op_ptr.p->m_clientData;
11340  ref->transId = trans_ptr.p->m_transId;
11341  getError(error, ref);
11342 
11343  Uint32 clientRef = op_ptr.p->m_clientRef;
11344  sendSignal(clientRef, GSN_CREATE_INDX_REF, signal,
11345  CreateIndxRef::SignalLength, JBB);
11346  }
11347 }
11348 
11349 // CreateIndex: PREPARE
11350 
11351 void
11352 Dbdict::createIndex_prepare(Signal* signal, SchemaOpPtr op_ptr)
11353 {
11354  jam();
11355  D("createIndex_prepare");
11356 
11357  CreateIndexRecPtr createIndexPtr;
11358  getOpRec(op_ptr, createIndexPtr);
11359 
11360  sendTransConf(signal, op_ptr);
11361 }
11362 
11363 // CreateIndex: COMMIT
11364 
11365 void
11366 Dbdict::createIndex_commit(Signal* signal, SchemaOpPtr op_ptr)
11367 {
11368  jam();
11369  D("createIndex_commit");
11370 
11371  sendTransConf(signal, op_ptr);
11372 }
11373 
11374 // CreateIndex: COMPLETE
11375 
11376 void
11377 Dbdict::createIndex_complete(Signal* signal, SchemaOpPtr op_ptr)
11378 {
11379  jam();
11380  sendTransConf(signal, op_ptr);
11381 }
11382 
11383 // CreateIndex: ABORT
11384 
11385 void
11386 Dbdict::createIndex_abortParse(Signal* signal, SchemaOpPtr op_ptr)
11387 {
11388  D("createIndex_abortParse" << *op_ptr.p);
11389 
11390  // wl3600_todo probably nothing..
11391 
11392  sendTransConf(signal, op_ptr);
11393 }
11394 
11395 void
11396 Dbdict::createIndex_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
11397 {
11398  D("createIndex_abortPrepare" << *op_ptr.p);
11399  // wl3600_todo
11400 
11401  CreateIndexRecPtr createIndexPtr;
11402  getOpRec(op_ptr, createIndexPtr);
11403 
11404  sendTransConf(signal, op_ptr);
11405 }
11406 
11407 // CreateIndex: MISC
11408 
11409 void
11410 Dbdict::execCREATE_INDX_IMPL_CONF(Signal* signal)
11411 {
11412  jamEntry();
11413  const CreateIndxImplConf* conf = (const CreateIndxImplConf*)signal->getDataPtr();
11414  ndbrequire(refToNode(conf->senderRef) == getOwnNodeId());
11415  handleDictConf(signal, conf);
11416 }
11417 
11418 void
11419 Dbdict::execCREATE_INDX_IMPL_REF(Signal* signal)
11420 {
11421  jamEntry();
11422  const CreateIndxImplRef* ref = (const CreateIndxImplRef*)signal->getDataPtr();
11423  ndbrequire(refToNode(ref->senderRef) == getOwnNodeId());
11424  handleDictRef(signal, ref);
11425 }
11426 
11427 // CreateIndex: END
11428 
11429 // MODULE: DropIndex
11430 
11431 const Dbdict::OpInfo
11432 Dbdict::DropIndexRec::g_opInfo = {
11433  { 'D', 'I', 'n', 0 },
11434  GSN_DROP_INDX_IMPL_REQ,
11435  DropIndxImplReq::SignalLength,
11436  //
11437  &Dbdict::dropIndex_seize,
11438  &Dbdict::dropIndex_release,
11439  //
11440  &Dbdict::dropIndex_parse,
11441  &Dbdict::dropIndex_subOps,
11442  &Dbdict::dropIndex_reply,
11443  //
11444  &Dbdict::dropIndex_prepare,
11445  &Dbdict::dropIndex_commit,
11446  &Dbdict::dropIndex_complete,
11447  //
11448  &Dbdict::dropIndex_abortParse,
11449  &Dbdict::dropIndex_abortPrepare
11450 };
11451 
11452 bool
11453 Dbdict::dropIndex_seize(SchemaOpPtr op_ptr)
11454 {
11455  return seizeOpRec<DropIndexRec>(op_ptr);
11456 }
11457 
11458 void
11459 Dbdict::dropIndex_release(SchemaOpPtr op_ptr)
11460 {
11461  releaseOpRec<DropIndexRec>(op_ptr);
11462 }
11463 
11464 void
11465 Dbdict::execDROP_INDX_REQ(Signal* signal)
11466 {
11467  jamEntry();
11468  if (!assembleFragments(signal)) {
11469  jam();
11470  return;
11471  }
11472  SectionHandle handle(this, signal);
11473 
11474  if (check_sender_version(signal, MAKE_VERSION(6,4,0)) < 0)
11475  {
11476  jam();
11481  DropIndxReq * tmp = (DropIndxReq*)signal->getDataPtr();
11482  do_swap(tmp->clientRef, tmp->clientData);
11483  }
11484 
11485  const DropIndxReq req_copy =
11486  *(const DropIndxReq*)signal->getDataPtr();
11487  const DropIndxReq* req = &req_copy;
11488 
11489  ErrorInfo error;
11490  do {
11491  SchemaOpPtr op_ptr;
11492  DropIndexRecPtr dropIndexPtr;
11493  DropIndxImplReq* impl_req;
11494 
11495  startClientReq(op_ptr, dropIndexPtr, req, impl_req, error);
11496  if (hasError(error)) {
11497  jam();
11498  break;
11499  }
11500 
11501  impl_req->tableId = RNIL; // wl3600_todo fill in in parse
11502  impl_req->tableVersion = 0;
11503  impl_req->indexId = req->indexId;
11504  impl_req->indexVersion = req->indexVersion;
11505 
11506  handleClientReq(signal, op_ptr, handle);
11507  return;
11508  } while (0);
11509 
11510  releaseSections(handle);
11511 
11512  DropIndxRef* ref = (DropIndxRef*)signal->getDataPtrSend();
11513  ref->senderRef = reference();
11514  ref->clientData = req->clientData;
11515  ref->transId = req->transId;
11516  ref->indexId = req->indexId;
11517  ref->indexVersion = req->indexVersion;
11518  getError(error, ref);
11519 
11520  sendSignal(req->clientRef, GSN_DROP_INDX_REF, signal,
11521  DropIndxRef::SignalLength, JBB);
11522 }
11523 
11524 // DropIndex: PARSE
11525 
11526 void
11527 Dbdict::dropIndex_parse(Signal* signal, bool master,
11528  SchemaOpPtr op_ptr,
11529  SectionHandle& handle, ErrorInfo& error)
11530 {
11531  D("dropIndex_parse" << V(op_ptr.i) << *op_ptr.p);
11532 
11533  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
11534  DropIndexRecPtr dropIndexPtr;
11535  getOpRec(op_ptr, dropIndexPtr);
11536  DropIndxImplReq* impl_req = &dropIndexPtr.p->m_request;
11537 
11538  TableRecordPtr indexPtr;
11539  if (!(impl_req->indexId < c_tableRecordPool.getSize())) {
11540  jam();
11541  setError(error, DropIndxRef::IndexNotFound, __LINE__);
11542  return;
11543  }
11544  c_tableRecordPool.getPtr(indexPtr, impl_req->indexId);
11545 
11546  if (!indexPtr.p->isIndex())
11547  {
11548  jam();
11549  setError(error, DropIndxRef::NotAnIndex, __LINE__);
11550  return;
11551  }
11552 
11553  if (indexPtr.p->tableVersion != impl_req->indexVersion)
11554  {
11555  jam();
11556  setError(error, DropIndxRef::InvalidIndexVersion, __LINE__);
11557  return;
11558  }
11559 
11560  if (check_write_obj(indexPtr.i, trans_ptr.p->m_transId,
11561  SchemaFile::SF_DROP, error))
11562  {
11563  jam();
11564  return;
11565  }
11566 
11567  ndbrequire(indexPtr.p->primaryTableId != RNIL);
11568  TableRecordPtr tablePtr;
11569  c_tableRecordPool.getPtr(tablePtr, indexPtr.p->primaryTableId);
11570 
11571  // master sets primary table, slave verifies it agrees
11572  if (master)
11573  {
11574  jam();
11575  impl_req->tableId = tablePtr.p->tableId;
11576  impl_req->tableVersion = tablePtr.p->tableVersion;
11577  }
11578  else
11579  {
11580  if (impl_req->tableId != tablePtr.p->tableId)
11581  {
11582  jam(); // wl3600_todo better error code
11583  setError(error, DropIndxRef::InvalidIndexVersion, __LINE__);
11584  return;
11585  }
11586  if (impl_req->tableVersion != tablePtr.p->tableVersion)
11587  {
11588  jam(); // wl3600_todo better error code
11589  setError(error, DropIndxRef::InvalidIndexVersion, __LINE__);
11590  return;
11591  }
11592  }
11593 
11594  if (ERROR_INSERTED(6122)) {
11595  jam();
11596  CLEAR_ERROR_INSERT_VALUE;
11597  setError(error, 9122, __LINE__);
11598  return;
11599  }
11600 }
11601 
11602 bool
11603 Dbdict::dropIndex_subOps(Signal* signal, SchemaOpPtr op_ptr)
11604 {
11605  D("dropIndex_subOps" << V(op_ptr.i) << *op_ptr.p);
11606 
11607  DropIndexRecPtr dropIndexPtr;
11608  getOpRec(op_ptr, dropIndexPtr);
11609 
11610  // op to alter index offline
11611  if (!dropIndexPtr.p->m_sub_alter_index) {
11612  jam();
11613  Callback c = {
11614  safe_cast(&Dbdict::dropIndex_fromAlterIndex),
11615  op_ptr.p->op_key
11616  };
11617  op_ptr.p->m_callback = c;
11618  dropIndex_toAlterIndex(signal, op_ptr);
11619  return true;
11620  }
11621 
11622  // op to drop index table
11623  if (!dropIndexPtr.p->m_sub_drop_table) {
11624  jam();
11625  Callback c = {
11626  safe_cast(&Dbdict::dropIndex_fromDropTable),
11627  op_ptr.p->op_key
11628  };
11629  op_ptr.p->m_callback = c;
11630  dropIndex_toDropTable(signal, op_ptr);
11631  return true;
11632  }
11633 
11634  return false;
11635 }
11636 
11637 void
11638 Dbdict::dropIndex_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
11639 {
11640  jam();
11641  D("dropIndex_reply" << V(op_ptr.i) << *op_ptr.p);
11642 
11643  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
11644 
11645  DropIndexRecPtr dropIndexPtr;
11646  getOpRec(op_ptr, dropIndexPtr);
11647  const DropIndxImplReq* impl_req = &dropIndexPtr.p->m_request;
11648 
11649  if (!hasError(error)) {
11650  DropIndxConf* conf = (DropIndxConf*)signal->getDataPtrSend();
11651  conf->senderRef = reference();
11652  conf->clientData = op_ptr.p->m_clientData;
11653  conf->transId = trans_ptr.p->m_transId;
11654  // wl3600_todo why send redundant fields?
11655  conf->indexId = impl_req->indexId;
11656  conf->indexVersion = impl_req->indexVersion;
11657 
11658  Uint32 clientRef = op_ptr.p->m_clientRef;
11659  sendSignal(clientRef, GSN_DROP_INDX_CONF, signal,
11660  DropIndxConf::SignalLength, JBB);
11661  } else {
11662  jam();
11663  DropIndxRef* ref = (DropIndxRef*)signal->getDataPtrSend();
11664  ref->senderRef = reference();
11665  ref->clientData = op_ptr.p->m_clientData;
11666  ref->transId = trans_ptr.p->m_transId;
11667  // wl3600_todo why send redundant fields?
11668  ref->indexId = impl_req->indexId;
11669  ref->indexVersion = impl_req->indexVersion;
11670  getError(error, ref);
11671 
11672  Uint32 clientRef = op_ptr.p->m_clientRef;
11673  sendSignal(clientRef, GSN_DROP_INDX_REF, signal,
11674  DropIndxRef::SignalLength, JBB);
11675  }
11676 }
11677 
11678 // DropIndex: PREPARE
11679 
11680 void
11681 Dbdict::dropIndex_prepare(Signal* signal, SchemaOpPtr op_ptr)
11682 {
11683  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
11684 
11685  DropIndexRecPtr dropIndexPtr;
11686  getOpRec(op_ptr, dropIndexPtr);
11687 
11688  D("dropIndex_prepare" << *op_ptr.p);
11689 
11690  sendTransConf(signal, op_ptr);
11691 }
11692 
11693 // DropIndex: COMMIT
11694 
11695 void
11696 Dbdict::dropIndex_commit(Signal* signal, SchemaOpPtr op_ptr)
11697 {
11698  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
11699 
11700  DropIndexRecPtr dropIndexPtr;
11701  getOpRec(op_ptr, dropIndexPtr);
11702 
11703  D("dropIndex_commit" << *op_ptr.p);
11704 
11705  sendTransConf(signal, op_ptr);
11706 }
11707 
11708 // DropIndex: COMPLETE
11709 
11710 void
11711 Dbdict::dropIndex_complete(Signal* signal, SchemaOpPtr op_ptr)
11712 {
11713  jam();
11714  sendTransConf(signal, op_ptr);
11715 }
11716 
11717 // DropIndex: ABORT
11718 
11719 void
11720 Dbdict::dropIndex_abortParse(Signal* signal, SchemaOpPtr op_ptr)
11721 {
11722  D("dropIndex_abortParse" << *op_ptr.p);
11723  // wl3600_todo
11724  sendTransConf(signal, op_ptr);
11725 }
11726 
11727 void
11728 Dbdict::dropIndex_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
11729 {
11730  D("dropIndex_abortPrepare" << *op_ptr.p);
11731  ndbrequire(false);
11732  sendTransConf(signal, op_ptr);
11733 }
11734 
11735 void
11736 Dbdict::dropIndex_toAlterIndex(Signal* signal, SchemaOpPtr op_ptr)
11737 {
11738  D("dropIndex_toAlterIndex");
11739 
11740  AlterIndxReq* req = (AlterIndxReq*)signal->getDataPtrSend();
11741 
11742  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
11743  DropIndexRecPtr dropIndexPtr;
11744  getOpRec(op_ptr, dropIndexPtr);
11745 
11746  Uint32 requestInfo = 0;
11747  DictSignal::setRequestType(requestInfo, AlterIndxImplReq::AlterIndexOffline);
11748  DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
11749 
11750  req->clientRef = reference();
11751  req->clientData = op_ptr.p->op_key;
11752  req->transId = trans_ptr.p->m_transId;
11753  req->transKey = trans_ptr.p->trans_key;
11754  req->requestInfo = requestInfo;
11755  req->indexId = dropIndexPtr.p->m_request.indexId;
11756  req->indexVersion = dropIndexPtr.p->m_request.indexVersion;
11757 
11758  sendSignal(reference(), GSN_ALTER_INDX_REQ, signal,
11759  AlterIndxReq::SignalLength, JBB);
11760 }
11761 
11762 void
11763 Dbdict::dropIndex_fromAlterIndex(Signal* signal, Uint32 op_key, Uint32 ret)
11764 {
11765  jam();
11766  D("dropIndex_fromAlterIndex");
11767 
11768  SchemaOpPtr op_ptr;
11769  DropIndexRecPtr dropIndexPtr;
11770 
11771  findSchemaOp(op_ptr, dropIndexPtr, op_key);
11772  ndbrequire(!op_ptr.isNull());
11773  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
11774 
11775  if (ret == 0) {
11776  const AlterIndxConf* conf =
11777  (const AlterIndxConf*)signal->getDataPtr();
11778 
11779  ndbrequire(conf->transId == trans_ptr.p->m_transId);
11780  dropIndexPtr.p->m_sub_alter_index = true;
11781  createSubOps(signal, op_ptr);
11782  } else {
11783  jam();
11784  const AlterIndxRef* ref =
11785  (const AlterIndxRef*)signal->getDataPtr();
11786 
11787  ErrorInfo error;
11788  setError(error, ref);
11789  abortSubOps(signal, op_ptr, error);
11790  }
11791 }
11792 
11793 void
11794 Dbdict::dropIndex_toDropTable(Signal* signal, SchemaOpPtr op_ptr)
11795 {
11796  D("dropIndex_toDropTable");
11797 
11798  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
11799  DropIndexRecPtr dropIndexPtr;
11800  getOpRec(op_ptr, dropIndexPtr);
11801  const DropIndxImplReq* impl_req = &dropIndexPtr.p->m_request;
11802 
11803  DropTableReq* req = (DropTableReq*)signal->getDataPtrSend();
11804 
11805  Uint32 requestInfo = 0;
11806  DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
11807 
11808  req->clientRef = reference();
11809  req->clientData = op_ptr.p->op_key;
11810  req->transId = trans_ptr.p->m_transId;
11811  req->transKey = trans_ptr.p->trans_key;
11812  req->requestInfo = requestInfo;
11813  req->tableId = impl_req->indexId;
11814  req->tableVersion = impl_req->indexVersion;
11815  sendSignal(reference(), GSN_DROP_TABLE_REQ, signal,
11816  DropTableReq::SignalLength, JBB);
11817 }
11818 
11819 void
11820 Dbdict::dropIndex_fromDropTable(Signal* signal, Uint32 op_key, Uint32 ret)
11821 {
11822  jam();
11823  D("dropIndex_fromDropTable" << dec << V(op_key) << V(ret));
11824 
11825  SchemaOpPtr op_ptr;
11826  DropIndexRecPtr dropIndexPtr;
11827 
11828  findSchemaOp(op_ptr, dropIndexPtr, op_key);
11829  ndbrequire(!op_ptr.isNull());
11830  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
11831 
11832  if (ret == 0) {
11833  jam();
11834  const DropTableConf* conf =
11835  (const DropTableConf*)signal->getDataPtr();
11836 
11837  ndbrequire(conf->transId == trans_ptr.p->m_transId);
11838  dropIndexPtr.p->m_sub_drop_table = true;
11839  createSubOps(signal, op_ptr);
11840  } else {
11841  jam();
11842  const DropTableRef* ref =
11843  (const DropTableRef*)signal->getDataPtr();
11844  ErrorInfo error;
11845  setError(error, ref);
11846  abortSubOps(signal, op_ptr, error);
11847  }
11848 }
11849 
11850 // DropIndex: MISC
11851 
11852 void
11853 Dbdict::execDROP_INDX_IMPL_CONF(Signal* signal)
11854 {
11855  jamEntry();
11856  const DropIndxImplConf* conf = (const DropIndxImplConf*)signal->getDataPtr();
11857  ndbrequire(refToNode(conf->senderRef) == getOwnNodeId());
11858  handleDictConf(signal, conf);
11859 }
11860 
11861 void
11862 Dbdict::execDROP_INDX_IMPL_REF(Signal* signal)
11863 {
11864  jamEntry();
11865  const DropIndxImplRef* ref = (const DropIndxImplRef*)signal->getDataPtr();
11866  ndbrequire(refToNode(ref->senderRef) == getOwnNodeId());
11867  handleDictRef(signal, ref);
11868 }
11869 
11870 // DropIndex: END
11871 
11872 // MODULE: AlterIndex
11873 
11874 const Dbdict::OpInfo
11875 Dbdict::AlterIndexRec::g_opInfo = {
11876  { 'A', 'I', 'n', 0 },
11877  GSN_ALTER_INDX_IMPL_REQ,
11878  AlterIndxImplReq::SignalLength,
11879  //
11880  &Dbdict::alterIndex_seize,
11881  &Dbdict::alterIndex_release,
11882  //
11883  &Dbdict::alterIndex_parse,
11884  &Dbdict::alterIndex_subOps,
11885  &Dbdict::alterIndex_reply,
11886  //
11887  &Dbdict::alterIndex_prepare,
11888  &Dbdict::alterIndex_commit,
11889  &Dbdict::alterIndex_complete,
11890  //
11891  &Dbdict::alterIndex_abortParse,
11892  &Dbdict::alterIndex_abortPrepare
11893 };
11894 
11895 bool
11896 Dbdict::alterIndex_seize(SchemaOpPtr op_ptr)
11897 {
11898  return seizeOpRec<AlterIndexRec>(op_ptr);
11899 }
11900 
11901 void
11902 Dbdict::alterIndex_release(SchemaOpPtr op_ptr)
11903 {
11904  releaseOpRec<AlterIndexRec>(op_ptr);
11905 }
11906 
11907 void
11908 Dbdict::execALTER_INDX_REQ(Signal* signal)
11909 {
11910  jamEntry();
11911  if (!assembleFragments(signal)) {
11912  jam();
11913  return;
11914  }
11915  SectionHandle handle(this, signal);
11916 
11917  const AlterIndxReq req_copy =
11918  *(const AlterIndxReq*)signal->getDataPtr();
11919  const AlterIndxReq* req = &req_copy;
11920 
11921  ErrorInfo error;
11922  do {
11923  SchemaOpPtr op_ptr;
11924  AlterIndexRecPtr alterIndexPtr;
11925  AlterIndxImplReq* impl_req;
11926 
11927  startClientReq(op_ptr, alterIndexPtr, req, impl_req, error);
11928  if (hasError(error)) {
11929  jam();
11930  break;
11931  }
11932 
11933  impl_req->tableId = RNIL; // wl3600_todo fill in in parse
11934  impl_req->tableVersion = 0;
11935  impl_req->indexId = req->indexId;
11936  impl_req->indexVersion = req->indexVersion;
11937  impl_req->indexType = 0; // fill in parse
11938 
11939  handleClientReq(signal, op_ptr, handle);
11940  return;
11941  } while (0);
11942 
11943  releaseSections(handle);
11944 
11945  AlterIndxRef* ref = (AlterIndxRef*)signal->getDataPtrSend();
11946  ref->senderRef = reference();
11947  ref->clientData = req->clientData;
11948  ref->transId = req->transId;
11949  ref->indexId = req->indexId;
11950  ref->indexVersion = req->indexVersion;
11951  getError(error, ref);
11952 
11953  sendSignal(req->clientRef, GSN_ALTER_INDX_REF, signal,
11954  AlterIndxRef::SignalLength, JBB);
11955 }
11956 
11957 const Dbdict::TriggerTmpl
11958 Dbdict::g_hashIndexTriggerTmpl[1] = {
11959  { "NDB$INDEX_%u_UI",
11960  {
11961  TriggerType::SECONDARY_INDEX,
11962  TriggerActionTime::TA_AFTER,
11963  TriggerEvent::TE_CUSTOM,
11964  false, false, true // monitor replicas, monitor all, report all
11965  }
11966  }
11967 };
11968 
11969 const Dbdict::TriggerTmpl
11970 Dbdict::g_orderedIndexTriggerTmpl[1] = {
11971  { "NDB$INDEX_%u_CUSTOM",
11972  {
11973  TriggerType::ORDERED_INDEX,
11974  TriggerActionTime::TA_CUSTOM,
11975  TriggerEvent::TE_CUSTOM,
11976  true, false, true
11977  }
11978  }
11979 };
11980 
11981 const Dbdict::TriggerTmpl
11982 Dbdict::g_buildIndexConstraintTmpl[1] = {
11983  { "NDB$INDEX_%u_BUILD",
11984  {
11985  TriggerType::READ_ONLY_CONSTRAINT,
11986  TriggerActionTime::TA_AFTER,
11987  TriggerEvent::TE_UPDATE,
11988  false, true, false
11989  }
11990  }
11991 };
11992 
11993 const Dbdict::TriggerTmpl
11994 Dbdict::g_reorgTriggerTmpl[1] = {
11995  { "NDB$REORG_%u",
11996  {
11997  TriggerType::REORG_TRIGGER,
11998  TriggerActionTime::TA_AFTER,
11999  TriggerEvent::TE_CUSTOM,
12000  false, true, false
12001  }
12002  }
12003 };
12004 
12005 // AlterIndex: PARSE
12006 
12007 void
12008 Dbdict::alterIndex_parse(Signal* signal, bool master,
12009  SchemaOpPtr op_ptr,
12010  SectionHandle& handle, ErrorInfo& error)
12011 {
12012  D("alterIndex_parse" << V(op_ptr.i) << *op_ptr.p);
12013 
12014  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12015  AlterIndexRecPtr alterIndexPtr;
12016  getOpRec(op_ptr, alterIndexPtr);
12017  AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
12018 
12019  TableRecordPtr indexPtr;
12020  if (!(impl_req->indexId < c_tableRecordPool.getSize())) {
12021  jam();
12022  setError(error, AlterIndxRef::IndexNotFound, __LINE__);
12023  return;
12024  }
12025  c_tableRecordPool.getPtr(indexPtr, impl_req->indexId);
12026 
12027  // get name for system index check later
12028  char indexName[MAX_TAB_NAME_SIZE];
12029  memset(indexName, 0, sizeof(indexName));
12030  {
12031  ConstRope r(c_rope_pool, indexPtr.p->tableName);
12032  r.copy(indexName);
12033  }
12034  D("index " << indexName);
12035 
12036  if (indexPtr.p->tableVersion != impl_req->indexVersion) {
12037  jam();
12038  setError(error, AlterIndxRef::InvalidIndexVersion, __LINE__);
12039  return;
12040  }
12041 
12042  if (check_write_obj(indexPtr.i, trans_ptr.p->m_transId,
12043  SchemaFile::SF_ALTER, error))
12044  {
12045  jam();
12046  return;
12047  }
12048 
12049  // check it is an index and set trigger info for sub-ops
12050  switch (indexPtr.p->tableType) {
12051  case DictTabInfo::UniqueHashIndex:
12052  jam();
12053  alterIndexPtr.p->m_triggerTmpl = g_hashIndexTriggerTmpl;
12054  break;
12055  case DictTabInfo::OrderedIndex:
12056  jam();
12057  alterIndexPtr.p->m_triggerTmpl = g_orderedIndexTriggerTmpl;
12058  break;
12059  default:
12060  jam();
12061  setError(error, AlterIndxRef::NotAnIndex, __LINE__);
12062  return;
12063  }
12064 
12065  if (master)
12066  {
12067  jam();
12068  impl_req->indexType = indexPtr.p->tableType;
12069  }
12070  else
12071  {
12072  jam();
12073  ndbrequire(impl_req->indexType == (Uint32)indexPtr.p->tableType);
12074  }
12075 
12076  ndbrequire(indexPtr.p->primaryTableId != RNIL);
12077  TableRecordPtr tablePtr;
12078  c_tableRecordPool.getPtr(tablePtr, indexPtr.p->primaryTableId);
12079 
12080  // master sets primary table, participant verifies it agrees
12081  if (master)
12082  {
12083  jam();
12084  impl_req->tableId = tablePtr.p->tableId;
12085  impl_req->tableVersion = tablePtr.p->tableVersion;
12086  }
12087  else
12088  {
12089  if (impl_req->tableId != tablePtr.p->tableId)
12090  {
12091  jam(); // wl3600_todo better error code
12092  setError(error, AlterIndxRef::InvalidIndexVersion, __LINE__);
12093  return;
12094  }
12095  if (impl_req->tableVersion != tablePtr.p->tableVersion)
12096  {
12097  jam(); // wl3600_todo better error code
12098  setError(error, AlterIndxRef::InvalidIndexVersion, __LINE__);
12099  return;
12100  }
12101  }
12102 
12103  // check request type
12104  Uint32 requestType = impl_req->requestType;
12105  switch (requestType) {
12106  case AlterIndxImplReq::AlterIndexOnline:
12107  jam();
12108  indexPtr.p->indexState = TableRecord::IS_BUILDING;
12109  break;
12110  case AlterIndxImplReq::AlterIndexOffline:
12111  jam();
12112  indexPtr.p->indexState = TableRecord::IS_DROPPING;
12113  break;
12114  case AlterIndxImplReq::AlterIndexAddPartition:
12115  jam();
12116  if (indexPtr.p->tableType == DictTabInfo::OrderedIndex)
12117  {
12118  jam();
12125  Ptr<SchemaOp> baseop = op_ptr;
12126  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
12127  ndbrequire(list.prev(baseop));
12128  Uint32 sz = sizeof(baseop.p->m_oprec_ptr.p->m_opType);
12129  const char * opType = baseop.p->m_oprec_ptr.p->m_opType;
12130  if (memcmp(opType, AlterTableRec::g_opInfo.m_opType, sz) == 0)
12131  {
12132  jam();
12133  op_ptr.p->m_base_op_ptr_i = baseop.i;
12134  }
12135  else
12136  {
12137  jam();
12138  ndbrequire(memcmp(opType, AlterIndexRec::g_opInfo.m_opType, sz) == 0);
12139  op_ptr.p->m_base_op_ptr_i = baseop.p->m_base_op_ptr_i;
12140  }
12141  break;
12142  }
12143  // else invalid request type
12144  default:
12145  ndbassert(false);
12146  setError(error, AlterIndxRef::BadRequestType, __LINE__);
12147  return;
12148  }
12149 
12150  // set attribute mask (of primary table attribute ids)
12151  getIndexAttrMask(indexPtr, alterIndexPtr.p->m_attrMask);
12152 
12153  // ordered index stats
12154  if (indexPtr.p->tableType == DictTabInfo::OrderedIndex) {
12155  jam();
12156 
12157  // always compute monitored replica
12158  if (requestType == AlterIndxImplReq::AlterIndexOnline) {
12159  jam();
12160  set_index_stat_frag(signal, indexPtr);
12161  }
12162 
12163  // skip system indexes (at least index stats indexes)
12164  if (strstr(indexName, "/" NDB_INDEX_STAT_PREFIX) != 0) {
12165  jam();
12166  D("skip index stats operations for system index");
12167  alterIndexPtr.p->m_sub_index_stat_dml = true;
12168  alterIndexPtr.p->m_sub_index_stat_mon = true;
12169  }
12170 
12171  // disable update/delete if db not up
12172  if (getNodeState().startLevel != NodeState::SL_STARTED &&
12173  getNodeState().startLevel != NodeState::SL_SINGLEUSER) {
12174  jam();
12175  alterIndexPtr.p->m_sub_index_stat_dml = true;
12176  }
12177 
12178  // disable update on create if not auto
12179  if (requestType == AlterIndxImplReq::AlterIndexOnline &&
12180  !c_indexStatAutoCreate) {
12181  jam();
12182  alterIndexPtr.p->m_sub_index_stat_dml = true;
12183  }
12184 
12185  // always delete on drop because manual update may have been done
12186  if (requestType == AlterIndxImplReq::AlterIndexOffline) {
12187  jam();
12188  }
12189 
12190  // always assign/remove monitored replica in TUX instances
12191  }
12192 
12193  if (ERROR_INSERTED(6123)) {
12194  jam();
12195  CLEAR_ERROR_INSERT_VALUE;
12196  setError(error, 9123, __LINE__);
12197  return;
12198  }
12199 }
12200 
12201 void
12202 Dbdict::set_index_stat_frag(Signal* signal, TableRecordPtr indexPtr)
12203 {
12204  jam();
12205  const Uint32 indexId = indexPtr.i;
12206  Uint32 err = get_fragmentation(signal, indexId);
12207  ndbrequire(err == 0);
12208  // format: R F { fragId node1 .. nodeR } x { F }
12209  // fragId: 0 1 2 .. (or whatever)
12210  const Uint16* frag_data = (Uint16*)(signal->theData+25);
12211  const Uint32 noOfFragments = frag_data[1];
12212  const Uint32 noOfReplicas = frag_data[0];
12213  ndbrequire(noOfFragments != 0 && noOfReplicas != 0);
12214 
12215  // distribute by table and index id
12216  const Uint32 value = indexPtr.p->primaryTableId + indexPtr.i;
12217  const Uint32 fragId = value % noOfFragments;
12218  const Uint32 fragIndex = 2 + (1 + noOfReplicas) * fragId;
12219  const Uint32 nodeIndex = value % noOfReplicas;
12220  const Uint32 nodeId = frag_data[fragIndex + 1 + nodeIndex];
12221 
12222  D("set_index_stat_frag" << V(indexId) << V(fragId) << V(nodeId));
12223  indexPtr.p->indexStatFragId = fragId;
12224  indexPtr.p->indexStatNodeId = nodeId;
12225 }
12226 
12227 bool
12228 Dbdict::alterIndex_subOps(Signal* signal, SchemaOpPtr op_ptr)
12229 {
12230  D("alterIndex_subOps" << V(op_ptr.i) << *op_ptr.p);
12231 
12232  AlterIndexRecPtr alterIndexPtr;
12233  getOpRec(op_ptr, alterIndexPtr);
12234  const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
12235  Uint32 requestType = impl_req->requestType;
12236  TableRecordPtr indexPtr;
12237  c_tableRecordPool.getPtr(indexPtr, impl_req->indexId);
12238 
12239  // ops to create or drop triggers
12240  if (alterIndexPtr.p->m_sub_trigger == false)
12241  {
12242  jam();
12243  alterIndexPtr.p->m_sub_trigger = true;
12244  switch (requestType) {
12245  case AlterIndxImplReq::AlterIndexOnline:
12246  jam();
12247  {
12248  Callback c = {
12249  safe_cast(&Dbdict::alterIndex_fromCreateTrigger),
12250  op_ptr.p->op_key
12251  };
12252  op_ptr.p->m_callback = c;
12253  alterIndex_toCreateTrigger(signal, op_ptr);
12254  }
12255  break;
12256  case AlterIndxImplReq::AlterIndexOffline:
12257  jam();
12258  {
12259  Callback c = {
12260  safe_cast(&Dbdict::alterIndex_fromDropTrigger),
12261  op_ptr.p->op_key
12262  };
12263  op_ptr.p->m_callback = c;
12264  alterIndex_toDropTrigger(signal, op_ptr);
12265  }
12266  break;
12267  case AlterIndxImplReq::AlterIndexAddPartition:
12268  jam();
12269  return false;
12270  default:
12271  ndbrequire(false);
12272  break;
12273  }
12274  return true;
12275  }
12276 
12277  if (requestType == AlterIndxImplReq::AlterIndexOnline &&
12278  !alterIndexPtr.p->m_sub_build_index) {
12279  jam();
12280  Callback c = {
12281  safe_cast(&Dbdict::alterIndex_fromBuildIndex),
12282  op_ptr.p->op_key
12283  };
12284  op_ptr.p->m_callback = c;
12285  alterIndex_toBuildIndex(signal, op_ptr);
12286  return true;
12287  }
12288 
12289  if (indexPtr.p->isOrderedIndex() &&
12290  (!alterIndexPtr.p->m_sub_index_stat_dml ||
12291  !alterIndexPtr.p->m_sub_index_stat_mon)) {
12292  jam();
12293  Callback c = {
12294  safe_cast(&Dbdict::alterIndex_fromIndexStat),
12295  op_ptr.p->op_key
12296  };
12297  op_ptr.p->m_callback = c;
12298  alterIndex_toIndexStat(signal, op_ptr);
12299  return true;
12300  }
12301 
12302  return false;
12303 }
12304 
12305 void
12306 Dbdict::alterIndex_toCreateTrigger(Signal* signal, SchemaOpPtr op_ptr)
12307 {
12308  D("alterIndex_toCreateTrigger");
12309 
12310  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12311  AlterIndexRecPtr alterIndexPtr;
12312  getOpRec(op_ptr, alterIndexPtr);
12313  const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
12314  TableRecordPtr indexPtr;
12315  c_tableRecordPool.getPtr(indexPtr, impl_req->indexId);
12316 
12317  const TriggerTmpl& triggerTmpl = alterIndexPtr.p->m_triggerTmpl[0];
12318 
12319  CreateTrigReq* req = (CreateTrigReq*)signal->getDataPtrSend();
12320 
12321  Uint32 requestInfo = 0;
12322  DictSignal::setRequestType(requestInfo, CreateTrigReq::CreateTriggerOnline);
12323  DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
12324 
12325  req->clientRef = reference();
12326  req->clientData = op_ptr.p->op_key;
12327  req->transId = trans_ptr.p->m_transId;
12328  req->transKey = trans_ptr.p->trans_key;
12329  req->requestInfo = requestInfo;
12330  req->tableId = impl_req->tableId;
12331  req->tableVersion = impl_req->tableVersion;
12332  req->indexId = impl_req->indexId;
12333  req->indexVersion = impl_req->indexVersion;
12334  req->triggerNo = 0;
12335 
12336  Uint32 forceTriggerId = indexPtr.p->triggerId;
12337  D(V(getNodeState().startLevel) << V(NodeState::SL_STARTED));
12338  if (getNodeState().startLevel == NodeState::SL_STARTED)
12339  {
12340  ndbrequire(forceTriggerId == RNIL);
12341  }
12342  req->forceTriggerId = forceTriggerId;
12343 
12344  TriggerInfo::packTriggerInfo(req->triggerInfo, triggerTmpl.triggerInfo);
12345 
12346  req->receiverRef = 0;
12347 
12348  char triggerName[MAX_TAB_NAME_SIZE];
12349  sprintf(triggerName, triggerTmpl.nameFormat, impl_req->indexId);
12350 
12351  // name section
12352  Uint32 buffer[2 + ((MAX_TAB_NAME_SIZE + 3) >> 2)]; // SP string
12353  LinearWriter w(buffer, sizeof(buffer) >> 2);
12354  w.reset();
12355  w.add(DictTabInfo::TableName, triggerName);
12356  LinearSectionPtr lsPtr[3];
12357  lsPtr[0].p = buffer;
12358  lsPtr[0].sz = w.getWordsUsed();
12359 
12360  lsPtr[1].p = alterIndexPtr.p->m_attrMask.rep.data;
12361  lsPtr[1].sz = alterIndexPtr.p->m_attrMask.getSizeInWords();
12362 
12363  sendSignal(reference(), GSN_CREATE_TRIG_REQ, signal,
12364  CreateTrigReq::SignalLength, JBB, lsPtr, 2);
12365 }
12366 
12367 void
12368 Dbdict::alterIndex_fromCreateTrigger(Signal* signal, Uint32 op_key, Uint32 ret)
12369 {
12370  jam();
12371 
12372  SchemaOpPtr op_ptr;
12373  AlterIndexRecPtr alterIndexPtr;
12374 
12375  findSchemaOp(op_ptr, alterIndexPtr, op_key);
12376  ndbrequire(!op_ptr.isNull());
12377  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12378  //const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
12379 
12380  D("alterIndex_fromCreateTrigger" << dec << V(op_key) << V(ret));
12381 
12382  if (ret == 0) {
12383  jam();
12384  const CreateTrigConf* conf =
12385  (const CreateTrigConf*)signal->getDataPtr();
12386 
12387  ndbrequire(conf->transId == trans_ptr.p->m_transId);
12388  createSubOps(signal, op_ptr);
12389  } else {
12390  const CreateTrigRef* ref =
12391  (const CreateTrigRef*)signal->getDataPtr();
12392  ErrorInfo error;
12393  setError(error, ref);
12394  abortSubOps(signal, op_ptr, error);
12395  }
12396 }
12397 
12398 void
12399 Dbdict::alterIndex_toDropTrigger(Signal* signal, SchemaOpPtr op_ptr)
12400 {
12401  D("alterIndex_toDropTrigger");
12402 
12403  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12404  AlterIndexRecPtr alterIndexPtr;
12405  getOpRec(op_ptr, alterIndexPtr);
12406  const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
12407 
12408  TableRecordPtr indexPtr;
12409  c_tableRecordPool.getPtr(indexPtr, impl_req->indexId);
12410 
12411  //const TriggerTmpl& triggerTmpl = alterIndexPtr.p->m_triggerTmpl[0];
12412 
12413  DropTrigReq* req = (DropTrigReq*)signal->getDataPtrSend();
12414 
12415  Uint32 requestInfo = 0;
12416  DictSignal::setRequestType(requestInfo, 0);
12417  DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
12418 
12419  req->clientRef = reference();
12420  req->clientData = op_ptr.p->op_key;
12421  req->transId = trans_ptr.p->m_transId;
12422  req->transKey = trans_ptr.p->trans_key;
12423  req->requestInfo = requestInfo;
12424  req->tableId = impl_req->tableId;
12425  req->tableVersion = impl_req->tableVersion;
12426  req->indexId = impl_req->indexId;
12427  req->indexVersion = impl_req->indexVersion;
12428  req->triggerNo = 0;
12429  req->triggerId = indexPtr.p->triggerId;
12430 
12431  sendSignal(reference(), GSN_DROP_TRIG_REQ, signal,
12432  DropTrigReq::SignalLength, JBB);
12433 }
12434 
12435 void
12436 Dbdict::alterIndex_fromDropTrigger(Signal* signal, Uint32 op_key, Uint32 ret)
12437 {
12438  jam();
12439 
12440  SchemaOpPtr op_ptr;
12441  AlterIndexRecPtr alterIndexPtr;
12442 
12443  findSchemaOp(op_ptr, alterIndexPtr, op_key);
12444  ndbrequire(!op_ptr.isNull());
12445  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12446  //const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
12447 
12448  D("alterIndex_fromDropTrigger" << dec << V(op_key) << V(ret));
12449 
12450  if (ret == 0) {
12451  const DropTrigConf* conf =
12452  (const DropTrigConf*)signal->getDataPtr();
12453 
12454  ndbrequire(conf->transId == trans_ptr.p->m_transId);
12455  createSubOps(signal, op_ptr);
12456  } else {
12457  jam();
12458  const DropTrigRef* ref =
12459  (const DropTrigRef*)signal->getDataPtr();
12460  ErrorInfo error;
12461  setError(error, ref);
12462  abortSubOps(signal, op_ptr, error);
12463  }
12464 }
12465 
12466 void
12467 Dbdict::alterIndex_toBuildIndex(Signal* signal, SchemaOpPtr op_ptr)
12468 {
12469  D("alterIndex_toBuildIndex");
12470 
12471  BuildIndxReq* req = (BuildIndxReq*)signal->getDataPtrSend();
12472 
12473  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12474  AlterIndexRecPtr alterIndexPtr;
12475  getOpRec(op_ptr, alterIndexPtr);
12476  const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
12477 
12478  Uint32 requestInfo = 0;
12479  DictSignal::setRequestType(requestInfo, BuildIndxReq::MainOp);
12480  DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
12481 
12482  if (op_ptr.p->m_requestInfo & AlterIndxReq::RF_BUILD_OFFLINE)
12483  {
12484  jam();
12485  requestInfo |= BuildIndxReq::RF_BUILD_OFFLINE;
12486  }
12487 
12488  req->clientRef = reference();
12489  req->clientData = op_ptr.p->op_key;
12490  req->transId = trans_ptr.p->m_transId;
12491  req->transKey = trans_ptr.p->trans_key;
12492  req->requestInfo = requestInfo;
12493  req->buildId = 0; // not used
12494  req->buildKey = 0; // not used
12495  req->tableId = impl_req->tableId;
12496  req->indexId = impl_req->indexId;
12497  req->indexType = impl_req->indexType;
12498  req->parallelism = 16;
12499 
12500  sendSignal(reference(), GSN_BUILDINDXREQ, signal,
12501  BuildIndxReq::SignalLength, JBB);
12502 }
12503 
12504 void
12505 Dbdict::alterIndex_fromBuildIndex(Signal* signal, Uint32 op_key, Uint32 ret)
12506 {
12507  jam();
12508  D("alterIndex_fromBuildIndex");
12509 
12510  SchemaOpPtr op_ptr;
12511  AlterIndexRecPtr alterIndexPtr;
12512 
12513  findSchemaOp(op_ptr, alterIndexPtr, op_key);
12514  ndbrequire(!op_ptr.isNull());
12515  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12516 
12517  if (ret == 0) {
12518  jam();
12519  const BuildIndxConf* conf =
12520  (const BuildIndxConf*)signal->getDataPtr();
12521 
12522  ndbrequire(conf->transId == trans_ptr.p->m_transId);
12523  alterIndexPtr.p->m_sub_build_index = true;
12524  createSubOps(signal, op_ptr);
12525  } else {
12526  jam();
12527  const BuildIndxRef* ref =
12528  (const BuildIndxRef*)signal->getDataPtr();
12529 
12530  ErrorInfo error;
12531  setError(error, ref);
12532  abortSubOps(signal, op_ptr, error);
12533  }
12534 }
12535 
12536 void
12537 Dbdict::alterIndex_toIndexStat(Signal* signal, SchemaOpPtr op_ptr)
12538 {
12539  D("alterIndex_toIndexStat");
12540 
12541  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12542  AlterIndexRecPtr alterIndexPtr;
12543  getOpRec(op_ptr, alterIndexPtr);
12544  const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
12545 
12546  IndexStatReq* req = (IndexStatReq*)signal->getDataPtrSend();
12547 
12548  Uint32 requestType = 0;
12549  switch (impl_req->requestType) {
12550  case AlterIndxImplReq::AlterIndexOnline:
12551  if (!alterIndexPtr.p->m_sub_index_stat_dml)
12552  requestType = IndexStatReq::RT_UPDATE_STAT;
12553  else
12554  requestType = IndexStatReq::RT_START_MON;
12555  break;
12556  case AlterIndxImplReq::AlterIndexOffline:
12557  if (!alterIndexPtr.p->m_sub_index_stat_dml)
12558  requestType = IndexStatReq::RT_DELETE_STAT;
12559  else
12560  requestType = IndexStatReq::RT_STOP_MON;
12561  break;
12562  default:
12563  ndbrequire(false);
12564  break;
12565  }
12566 
12567  Uint32 requestInfo = 0;
12568  DictSignal::setRequestType(requestInfo, requestType);
12569  DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
12570 
12571  TableRecordPtr indexPtr;
12572  c_tableRecordPool.getPtr(indexPtr, impl_req->indexId);
12573 
12574  req->clientRef = reference();
12575  req->clientData = op_ptr.p->op_key;
12576  req->transId = trans_ptr.p->m_transId;
12577  req->transKey = trans_ptr.p->trans_key;
12578  req->requestInfo = requestInfo;
12579  req->requestFlag = 0;
12580  req->indexId = impl_req->indexId;
12581  req->indexVersion = indexPtr.p->tableVersion;
12582  req->tableId = impl_req->tableId;
12583 
12584  sendSignal(reference(), GSN_INDEX_STAT_REQ,
12585  signal, IndexStatReq::SignalLength, JBB);
12586 }
12587 
12588 void
12589 Dbdict::alterIndex_fromIndexStat(Signal* signal, Uint32 op_key, Uint32 ret)
12590 {
12591  jam();
12592  D("alterIndex_fromIndexStat");
12593 
12594  SchemaOpPtr op_ptr;
12595  AlterIndexRecPtr alterIndexPtr;
12596 
12597  findSchemaOp(op_ptr, alterIndexPtr, op_key);
12598  ndbrequire(!op_ptr.isNull());
12599  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12600 
12601  if (ret == 0) {
12602  jam();
12603  const IndexStatConf* conf =
12604  (const IndexStatConf*)signal->getDataPtr();
12605 
12606  ndbrequire(conf->transId == trans_ptr.p->m_transId);
12607  ndbrequire(!alterIndexPtr.p->m_sub_index_stat_dml ||
12608  !alterIndexPtr.p->m_sub_index_stat_mon);
12609  alterIndexPtr.p->m_sub_index_stat_dml = true;
12610  alterIndexPtr.p->m_sub_index_stat_mon = true;
12611  createSubOps(signal, op_ptr);
12612  } else {
12613  jam();
12614  const IndexStatRef* ref =
12615  (const IndexStatRef*)signal->getDataPtr();
12616 
12617  ErrorInfo error;
12618  setError(error, ref);
12619  abortSubOps(signal, op_ptr, error);
12620  }
12621 }
12622 
12623 void
12624 Dbdict::alterIndex_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
12625 {
12626  D("alterIndex_reply" << V(op_ptr.i) << *op_ptr.p);
12627 
12628  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12629 
12630  AlterIndexRecPtr alterIndexPtr;
12631  getOpRec(op_ptr, alterIndexPtr);
12632  const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
12633 
12634  if (!hasError(error)) {
12635  AlterIndxConf* conf = (AlterIndxConf*)signal->getDataPtrSend();
12636  conf->senderRef = reference();
12637  conf->clientData = op_ptr.p->m_clientData;
12638  conf->transId = trans_ptr.p->m_transId;
12639  conf->indexId = impl_req->indexId;
12640  conf->indexVersion = impl_req->indexVersion;
12641 
12642  Uint32 clientRef = op_ptr.p->m_clientRef;
12643  sendSignal(clientRef, GSN_ALTER_INDX_CONF,
12644  signal, AlterIndxConf::SignalLength, JBB);
12645  } else {
12646  jam();
12647  AlterIndxRef* ref = (AlterIndxRef*)signal->getDataPtrSend();
12648  ref->senderRef = reference();
12649  ref->clientData = op_ptr.p->m_clientData;
12650  ref->transId = trans_ptr.p->m_transId;
12651  // wl3600_todo requestType (fix all at once)
12652  // wl3600_todo next 2 redundant (fix all at once)
12653  ref->indexId = impl_req->indexId;
12654  ref->indexVersion = impl_req->indexVersion;
12655  getError(error, ref);
12656 
12657  Uint32 clientRef = op_ptr.p->m_clientRef;
12658  sendSignal(clientRef, GSN_ALTER_INDX_REF,
12659  signal, AlterIndxRef::SignalLength, JBB);
12660  }
12661 }
12662 
12663 // AlterIndex: PREPARE
12664 
12665 void
12666 Dbdict::alterIndex_prepare(Signal* signal, SchemaOpPtr op_ptr)
12667 {
12668  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12669 
12670  AlterIndexRecPtr alterIndexPtr;
12671  getOpRec(op_ptr, alterIndexPtr);
12672  const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
12673  Uint32 requestType = impl_req->requestType;
12674 
12675  TableRecordPtr indexPtr;
12676  c_tableRecordPool.getPtr(indexPtr, impl_req->indexId);
12677 
12678  D("alterIndex_prepare" << *op_ptr.p);
12679 
12680  /*
12681  * Create table creates index table in all blocks. DBTC has
12682  * an additional entry for hash index. It is created (offline)
12683  * and dropped here. wl3600_todo redesign
12684  */
12685 
12686  switch (indexPtr.p->tableType) {
12687  case DictTabInfo::UniqueHashIndex:
12688  {
12689  Callback c = {
12690  safe_cast(&Dbdict::alterIndex_fromLocal),
12691  op_ptr.p->op_key
12692  };
12693  op_ptr.p->m_callback = c;
12694 
12695  switch (requestType) {
12696  case AlterIndxImplReq::AlterIndexOnline:
12697  alterIndex_toCreateLocal(signal, op_ptr);
12698  break;
12699  case AlterIndxImplReq::AlterIndexOffline:
12700  alterIndex_toDropLocal(signal, op_ptr);
12701  break;
12702  default:
12703  ndbrequire(false);
12704  break;
12705  }
12706  }
12707  break;
12708  case DictTabInfo::OrderedIndex:
12709  if (requestType == AlterIndxImplReq::AlterIndexAddPartition)
12710  {
12711  jam();
12712  Callback c = {
12713  safe_cast(&Dbdict::alterIndex_fromAddPartitions),
12714  op_ptr.p->op_key
12715  };
12716  op_ptr.p->m_callback = c;
12717  alterIndex_toAddPartitions(signal, op_ptr);
12718  return;
12719  }
12720  sendTransConf(signal, op_ptr);
12721  break;
12722  default:
12723  ndbrequire(false);
12724  break;
12725  }
12726 }
12727 
12728 void
12729 Dbdict::alterIndex_toCreateLocal(Signal* signal, SchemaOpPtr op_ptr)
12730 {
12731  AlterIndexRecPtr alterIndexPtr;
12732  getOpRec(op_ptr, alterIndexPtr);
12733  const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
12734 
12735  TableRecordPtr indexPtr;
12736  c_tableRecordPool.getPtr(indexPtr, impl_req->indexId);
12737 
12738  D("alterIndex_toCreateLocal" << *op_ptr.p);
12739 
12740  CreateIndxImplReq* req = (CreateIndxImplReq*)signal->getDataPtrSend();
12741 
12742  req->senderRef = reference();
12743  req->senderData = op_ptr.p->op_key;
12744  req->requestType = 0;
12745  req->tableId = impl_req->tableId;
12746  req->tableVersion = 0; // not used
12747  req->indexType = indexPtr.p->tableType;
12748  req->indexId = impl_req->indexId;
12749  req->indexVersion = 0; // not used
12750 
12751  // attribute list
12752  getIndexAttrList(indexPtr, alterIndexPtr.p->m_attrList);
12753  LinearSectionPtr ls_ptr[3];
12754  ls_ptr[0].p = (Uint32*)&alterIndexPtr.p->m_attrList;
12755  ls_ptr[0].sz = 1 + alterIndexPtr.p->m_attrList.sz;
12756 
12757  BlockReference ref = DBTC_REF;
12758  sendSignal(ref, GSN_CREATE_INDX_IMPL_REQ, signal,
12759  CreateIndxImplReq::SignalLength, JBB, ls_ptr, 1);
12760 }
12761 
12762 void
12763 Dbdict::alterIndex_toDropLocal(Signal* signal, SchemaOpPtr op_ptr)
12764 {
12765  AlterIndexRecPtr alterIndexPtr;
12766  getOpRec(op_ptr, alterIndexPtr);
12767  const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
12768 
12769  TableRecordPtr indexPtr;
12770  c_tableRecordPool.getPtr(indexPtr, impl_req->indexId);
12771 
12772  D("alterIndex_toDropLocal" << *op_ptr.p);
12773 
12774  DropIndxImplReq* req = (DropIndxImplReq*)signal->getDataPtrSend();
12775 
12776  req->senderRef = reference();
12777  req->senderData = op_ptr.p->op_key;
12778  req->tableId = impl_req->tableId;
12779  req->tableVersion = 0; // not used
12780  req->indexId = impl_req->indexId;
12781  req->indexVersion = 0; // not used
12782 
12783  BlockReference ref = DBTC_REF;
12784  sendSignal(ref, GSN_DROP_INDX_IMPL_REQ, signal,
12785  DropIndxImplReq::SignalLength, JBB);
12786 }
12787 
12788 void
12789 Dbdict::alterIndex_fromLocal(Signal* signal, Uint32 op_key, Uint32 ret)
12790 {
12791  SchemaOpPtr op_ptr;
12792  AlterIndexRecPtr alterIndexPtr;
12793  findSchemaOp(op_ptr, alterIndexPtr, op_key);
12794  ndbrequire(!op_ptr.isNull());
12795 
12796  D("alterIndex_fromLocal" << *op_ptr.p << V(ret));
12797 
12798  if (ret == 0) {
12799  jam();
12800  alterIndexPtr.p->m_tc_index_done = true;
12801  sendTransConf(signal, op_ptr);
12802  } else {
12803  jam();
12804  setError(op_ptr, ret, __LINE__);
12805  sendTransRef(signal, op_ptr);
12806  }
12807 }
12808 
12809 void
12810 Dbdict::alterIndex_toAddPartitions(Signal* signal, SchemaOpPtr op_ptr)
12811 {
12812  AlterIndexRecPtr alterIndexPtr;
12813  getOpRec(op_ptr, alterIndexPtr);
12814  const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
12815 
12819  SchemaOpPtr base_op;
12820  c_schemaOpPool.getPtr(base_op, op_ptr.p->m_base_op_ptr_i);
12821 
12822  const OpSection& fragInfoSec =
12823  getOpSection(base_op, AlterTabReq::FRAGMENTATION);
12824  SegmentedSectionPtr fragInfoPtr;
12825  bool ok = copyOut(fragInfoSec, fragInfoPtr);
12826  ndbrequire(ok);
12827  SectionHandle handle(this, fragInfoPtr.i);
12828 
12829  AlterTabReq* req = (AlterTabReq*)signal->getDataPtrSend();
12830  req->senderRef = reference();
12831  req->senderData = op_ptr.p->op_key;
12832  req->requestType = AlterTabReq::AlterTablePrepare;
12833  req->tableId = impl_req->indexId;
12834  req->tableVersion = impl_req->indexVersion;
12835  req->newTableVersion = impl_req->indexVersion;
12836  req->gci = 0;
12837  req->changeMask = 0;
12838  req->connectPtr = RNIL;
12839  req->noOfNewAttr = 0;
12840  req->newNoOfCharsets = 0;
12841  req->newNoOfKeyAttrs = 0;
12842  AlterTableReq::setAddFragFlag(req->changeMask, 1);
12843 
12844  sendSignal(DBDIH_REF, GSN_ALTER_TAB_REQ, signal,
12845  AlterTabReq::SignalLength, JBB, &handle);
12846 }
12847 
12848 void
12849 Dbdict::alterIndex_fromAddPartitions(Signal* signal, Uint32 op_key, Uint32 ret)
12850 {
12851  SchemaOpPtr op_ptr;
12852  AlterIndexRecPtr alterIndexPtr;
12853  findSchemaOp(op_ptr, alterIndexPtr, op_key);
12854  ndbrequire(!op_ptr.isNull());
12855 
12856  if (ret == 0) {
12857  jam();
12858 
12859  const AlterTabConf* conf =
12860  (const AlterTabConf*)signal->getDataPtr();
12861 
12862  alterIndexPtr.p->m_dihAddFragPtr = conf->connectPtr;
12863 
12864  sendTransConf(signal, op_ptr);
12865  } else {
12866  jam();
12867  setError(op_ptr, ret, __LINE__);
12868  sendTransRef(signal, op_ptr);
12869  }
12870 }
12871 
12872 // AlterIndex: COMMIT
12873 
12874 void
12875 Dbdict::alterIndex_commit(Signal* signal, SchemaOpPtr op_ptr)
12876 {
12877  jam();
12878  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12879 
12880  AlterIndexRecPtr alterIndexPtr;
12881  getOpRec(op_ptr, alterIndexPtr);
12882  const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
12883 
12884  if (impl_req->requestType == AlterIndxImplReq::AlterIndexAddPartition)
12885  {
12886  AlterTabReq* req = (AlterTabReq*)signal->getDataPtrSend();
12887  req->senderRef = reference();
12888  req->senderData = op_ptr.p->op_key;
12889  req->requestType = AlterTabReq::AlterTableCommit;
12890  req->tableId = impl_req->indexId;
12891  req->tableVersion = impl_req->indexVersion;
12892  req->newTableVersion = impl_req->indexVersion;
12893  req->gci = 0;
12894  req->changeMask = 0;
12895  req->connectPtr = RNIL;
12896  req->noOfNewAttr = 0;
12897  req->newNoOfCharsets = 0;
12898  req->newNoOfKeyAttrs = 0;
12899  req->connectPtr = alterIndexPtr.p->m_dihAddFragPtr;
12900 
12901  Callback c = {
12902  safe_cast(&Dbdict::alterIndex_fromLocal),
12903  op_ptr.p->op_key
12904  };
12905  op_ptr.p->m_callback = c;
12906 
12907  sendSignal(DBDIH_REF,
12908  GSN_ALTER_TAB_REQ, signal,
12909  AlterTabReq::SignalLength, JBB);
12910  return;
12911  }
12912 
12913  sendTransConf(signal, op_ptr);
12914 }
12915 
12916 // AlterIndex: COMPLETE
12917 
12918 void
12919 Dbdict::alterIndex_complete(Signal* signal, SchemaOpPtr op_ptr)
12920 {
12921  jam();
12922  sendTransConf(signal, op_ptr);
12923 }
12924 
12925 // AlterIndex: ABORT
12926 
12927 void
12928 Dbdict::alterIndex_abortParse(Signal* signal, SchemaOpPtr op_ptr)
12929 {
12930  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12931  AlterIndexRecPtr alterIndexPtr;
12932  getOpRec(op_ptr, alterIndexPtr);
12933  const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
12934  Uint32 requestType = impl_req->requestType;
12935  Uint32 indexId = impl_req->indexId;
12936 
12937  D("alterIndex_abortParse" << *op_ptr.p);
12938 
12939  do {
12940  if (!(impl_req->indexId < c_tableRecordPool.getSize())) {
12941  jam();
12942  D("invalid index id" << V(indexId));
12943  break;
12944  }
12945 
12946  TableRecordPtr indexPtr;
12947  c_tableRecordPool.getPtr(indexPtr, indexId);
12948 
12949  switch (requestType) {
12950  case AlterIndxImplReq::AlterIndexOnline:
12951  jam();
12952  indexPtr.p->indexState = TableRecord::IS_OFFLINE;
12953  break;
12954  case AlterIndxImplReq::AlterIndexOffline:
12955  jam();
12956  indexPtr.p->indexState = TableRecord::IS_ONLINE;
12957  break;
12958  default:
12959  break;
12960  }
12961  } while (0);
12962 
12963  sendTransConf(signal, op_ptr);
12964 }
12965 
12966 void
12967 Dbdict::alterIndex_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
12968 {
12969  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
12970  AlterIndexRecPtr alterIndexPtr;
12971  getOpRec(op_ptr, alterIndexPtr);
12972  const AlterIndxImplReq* impl_req = &alterIndexPtr.p->m_request;
12973  Uint32 requestType = impl_req->requestType;
12974 
12975  D("alterIndex_abortPrepare" << *op_ptr.p);
12976 
12977  if (impl_req->requestType == AlterIndxImplReq::AlterIndexAddPartition)
12978  {
12979  AlterTabReq* req = (AlterTabReq*)signal->getDataPtrSend();
12980  req->senderRef = reference();
12981  req->senderData = op_ptr.p->op_key;
12982  req->requestType = AlterTabReq::AlterTableRevert;
12983  req->tableId = impl_req->indexId;
12984  req->tableVersion = impl_req->indexVersion;
12985  req->newTableVersion = impl_req->indexVersion;
12986  req->gci = 0;
12987  req->changeMask = 0;
12988  req->connectPtr = RNIL;
12989  req->noOfNewAttr = 0;
12990  req->newNoOfCharsets = 0;
12991  req->newNoOfKeyAttrs = 0;
12992  req->connectPtr = alterIndexPtr.p->m_dihAddFragPtr;
12993  AlterTableReq::setAddFragFlag(req->changeMask, 1);
12994 
12995  Callback c = {
12996  safe_cast(&Dbdict::alterIndex_fromLocal),
12997  op_ptr.p->op_key
12998  };
12999  op_ptr.p->m_callback = c;
13000 
13001  sendSignal(DBDIH_REF,
13002  GSN_ALTER_TAB_REQ, signal,
13003  AlterTabReq::SignalLength, JBB);
13004  return;
13005  }
13006 
13007  if (!alterIndexPtr.p->m_tc_index_done) {
13008  jam();
13009  sendTransConf(signal, op_ptr);
13010  return;
13011  }
13012 
13013  Callback c = {
13014  safe_cast(&Dbdict::alterIndex_abortFromLocal),
13015  op_ptr.p->op_key
13016  };
13017  op_ptr.p->m_callback = c;
13018 
13019  switch (requestType) {
13020  case AlterIndxImplReq::AlterIndexOnline:
13021  jam();
13022  alterIndex_toDropLocal(signal, op_ptr);
13023  break;
13024  case AlterIndxImplReq::AlterIndexOffline:
13025  jam();
13026  alterIndex_toCreateLocal(signal, op_ptr);
13027  break;
13028  default:
13029  ndbrequire(false);
13030  break;
13031  }
13032 }
13033 
13034 void
13035 Dbdict::alterIndex_abortFromLocal(Signal* signal,
13036  Uint32 op_key,
13037  Uint32 ret)
13038 {
13039  SchemaOpPtr op_ptr;
13040  AlterIndexRecPtr alterIndexPtr;
13041  findSchemaOp(op_ptr, alterIndexPtr, op_key);
13042  ndbrequire(!op_ptr.isNull());
13043 
13044  D("alterIndex_abortFromLocal" << V(ret) << *op_ptr.p);
13045 
13046  if (ret == 0) {
13047  jam();
13048  alterIndexPtr.p->m_tc_index_done = false;
13049  sendTransConf(signal, op_ptr);
13050  } else {
13051  // abort is not allowed to fail
13052  ndbrequire(false);
13053  }
13054 }
13055 
13056 // AlterIndex: MISC
13057 
13058 void
13059 Dbdict::execALTER_INDX_CONF(Signal* signal)
13060 {
13061  jamEntry();
13062  const AlterIndxConf* conf = (const AlterIndxConf*)signal->getDataPtr();
13063  handleDictConf(signal, conf);
13064 }
13065 
13066 void
13067 Dbdict::execALTER_INDX_REF(Signal* signal)
13068 {
13069  jamEntry();
13070  const AlterIndxRef* ref = (const AlterIndxRef*)signal->getDataPtr();
13071  handleDictRef(signal, ref);
13072 }
13073 
13074 void
13075 Dbdict::execALTER_INDX_IMPL_CONF(Signal* signal)
13076 {
13077  jamEntry();
13078  const AlterIndxImplConf* conf = (const AlterIndxImplConf*)signal->getDataPtr();
13079  handleDictConf(signal, conf);
13080 }
13081 
13082 void
13083 Dbdict::execALTER_INDX_IMPL_REF(Signal* signal)
13084 {
13085  jamEntry();
13086  const AlterIndxImplRef* ref = (const AlterIndxImplRef*)signal->getDataPtr();
13087  handleDictRef(signal, ref);
13088 }
13089 
13090 // AlterIndex: END
13091 
13092 // MODULE: BuildIndex
13093 
13094 const Dbdict::OpInfo
13095 Dbdict::BuildIndexRec::g_opInfo = {
13096  { 'B', 'I', 'n', 0 },
13097  GSN_BUILD_INDX_IMPL_REQ,
13098  BuildIndxImplReq::SignalLength,
13099  //
13100  &Dbdict::buildIndex_seize,
13101  &Dbdict::buildIndex_release,
13102  //
13103  &Dbdict::buildIndex_parse,
13104  &Dbdict::buildIndex_subOps,
13105  &Dbdict::buildIndex_reply,
13106  //
13107  &Dbdict::buildIndex_prepare,
13108  &Dbdict::buildIndex_commit,
13109  &Dbdict::buildIndex_complete,
13110  //
13111  &Dbdict::buildIndex_abortParse,
13112  &Dbdict::buildIndex_abortPrepare
13113 };
13114 
13115 bool
13116 Dbdict::buildIndex_seize(SchemaOpPtr op_ptr)
13117 {
13118  return seizeOpRec<BuildIndexRec>(op_ptr);
13119 }
13120 
13121 void
13122 Dbdict::buildIndex_release(SchemaOpPtr op_ptr)
13123 {
13124  releaseOpRec<BuildIndexRec>(op_ptr);
13125 }
13126 
13127 void
13128 Dbdict::execBUILDINDXREQ(Signal* signal)
13129 {
13130  jamEntry();
13131  if (!assembleFragments(signal)) {
13132  jam();
13133  return;
13134  }
13135  SectionHandle handle(this, signal);
13136 
13137  const BuildIndxReq req_copy =
13138  *(const BuildIndxReq*)signal->getDataPtr();
13139  const BuildIndxReq* req = &req_copy;
13140 
13141  ErrorInfo error;
13142  do {
13143  SchemaOpPtr op_ptr;
13144  BuildIndexRecPtr buildIndexPtr;
13145  BuildIndxImplReq* impl_req;
13146 
13147  startClientReq(op_ptr, buildIndexPtr, req, impl_req, error);
13148  if (hasError(error)) {
13149  jam();
13150  break;
13151  }
13152 
13153  impl_req->buildId = req->buildId; //wl3600_todo remove from client sig
13154  impl_req->buildKey = req->buildKey;
13155  impl_req->tableId = req->tableId;
13156  impl_req->indexId = req->indexId;
13157  impl_req->indexType = req->indexType; //wl3600_todo remove from client sig
13158  impl_req->parallelism = req->parallelism;
13159 
13160  handleClientReq(signal, op_ptr, handle);
13161  return;
13162  } while (0);
13163 
13164  releaseSections(handle);
13165 
13166  BuildIndxRef* ref = (BuildIndxRef*)signal->getDataPtrSend();
13167  ref->senderRef = reference();
13168  ref->clientData = req->clientData;
13169  ref->transId = req->transId;
13170  ref->tableId = req->tableId;
13171  ref->indexId = req->indexId;
13172  ref->indexType = req->indexType;
13173  getError(error, ref);
13174 
13175  sendSignal(req->clientRef, GSN_BUILDINDXREF, signal,
13176  BuildIndxRef::SignalLength, JBB);
13177 }
13178 
13179 // BuildIndex: PARSE
13180 
13181 void
13182 Dbdict::buildIndex_parse(Signal* signal, bool master,
13183  SchemaOpPtr op_ptr,
13184  SectionHandle& handle, ErrorInfo& error)
13185 {
13186  D("buildIndex_parse");
13187 
13188  BuildIndexRecPtr buildIndexPtr;
13189  getOpRec(op_ptr, buildIndexPtr);
13190  BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
13191 
13192  // get index
13193  TableRecordPtr indexPtr;
13194  if (!(impl_req->indexId < c_tableRecordPool.getSize())) {
13195  jam();
13196  setError(error, BuildIndxRef::IndexNotFound, __LINE__);
13197  return;
13198  }
13199  c_tableRecordPool.getPtr(indexPtr, impl_req->indexId);
13200 
13201  ndbrequire(indexPtr.p->primaryTableId == impl_req->tableId);
13202 
13203  // get primary table
13204  TableRecordPtr tablePtr;
13205  if (!(impl_req->tableId < c_tableRecordPool.getSize())) {
13206  jam();
13207  setError(error, BuildIndxRef::IndexNotFound, __LINE__);
13208  return;
13209  }
13210  c_tableRecordPool.getPtr(tablePtr, impl_req->tableId);
13211 
13212  // set attribute lists
13213  getIndexAttrList(indexPtr, buildIndexPtr.p->m_indexKeyList);
13214  getTableKeyList(tablePtr, buildIndexPtr.p->m_tableKeyList);
13215 
13216  Uint32 requestType = impl_req->requestType;
13217  switch (requestType) {
13218  case BuildIndxReq::MainOp:
13219  case BuildIndxReq::SubOp:
13220  break;
13221  default:
13222  jam();
13223  ndbassert(false);
13224  setError(error, BuildIndxRef::BadRequestType, __LINE__);
13225  return;
13226  }
13227 
13228  // set build constraint info and attribute mask
13229  switch (indexPtr.p->tableType) {
13230  case DictTabInfo::UniqueHashIndex:
13231  jam();
13232  if (requestType == BuildIndxReq::MainOp) {
13233  buildIndexPtr.p->m_triggerTmpl = g_buildIndexConstraintTmpl;
13234  buildIndexPtr.p->m_subOpCount = 3;
13235  buildIndexPtr.p->m_subOpIndex = 0;
13236 
13237  // mask is NDB$PK (last attribute)
13238  Uint32 attrId = indexPtr.p->noOfAttributes - 1;
13239  buildIndexPtr.p->m_attrMask.clear();
13240  buildIndexPtr.p->m_attrMask.set(attrId);
13241  break;
13242  }
13243  /*FALLTHRU*/
13244  default:
13245  jam();
13246  {
13247  buildIndexPtr.p->m_triggerTmpl = 0;
13248  buildIndexPtr.p->m_subOpCount = 0;
13249  buildIndexPtr.p->m_doBuild = true;
13250  }
13251  break;
13252  }
13253 
13254  if (ERROR_INSERTED(6126)) {
13255  jam();
13256  CLEAR_ERROR_INSERT_VALUE;
13257  setError(error, 9126, __LINE__);
13258  return;
13259  }
13260 }
13261 
13262 bool
13263 Dbdict::buildIndex_subOps(Signal* signal, SchemaOpPtr op_ptr)
13264 {
13265  D("buildIndex_subOps" << V(op_ptr.i) << *op_ptr.p);
13266 
13267  BuildIndexRecPtr buildIndexPtr;
13268  getOpRec(op_ptr, buildIndexPtr);
13269  //const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
13270 
13271  if (buildIndexPtr.p->m_subOpIndex < buildIndexPtr.p->m_subOpCount) {
13272  jam();
13273  switch (buildIndexPtr.p->m_subOpIndex) {
13274  case 0:
13275  jam();
13276  {
13277  Callback c = {
13278  safe_cast(&Dbdict::buildIndex_fromCreateConstraint),
13279  op_ptr.p->op_key
13280  };
13281  op_ptr.p->m_callback = c;
13282  buildIndex_toCreateConstraint(signal, op_ptr);
13283  return true;
13284  }
13285  break;
13286  case 1:
13287  jam();
13288  // the sub-op that does the actual hash index build
13289  {
13290  Callback c = {
13291  safe_cast(&Dbdict::buildIndex_fromBuildIndex),
13292  op_ptr.p->op_key
13293  };
13294  op_ptr.p->m_callback = c;
13295  buildIndex_toBuildIndex(signal, op_ptr);
13296  return true;
13297  }
13298  break;
13299  case 2:
13300  jam();
13301  {
13302  Callback c = {
13303  safe_cast(&Dbdict::buildIndex_fromDropConstraint),
13304  op_ptr.p->op_key
13305  };
13306  op_ptr.p->m_callback = c;
13307  buildIndex_toDropConstraint(signal, op_ptr);
13308  return true;
13309  }
13310  break;
13311  default:
13312  ndbrequire(false);
13313  break;
13314  }
13315  }
13316 
13317  return false;
13318 }
13319 
13320 void
13321 Dbdict::buildIndex_toCreateConstraint(Signal* signal, SchemaOpPtr op_ptr)
13322 {
13323  D("buildIndex_toCreateConstraint");
13324 
13325  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
13326  BuildIndexRecPtr buildIndexPtr;
13327  getOpRec(op_ptr, buildIndexPtr);
13328  const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
13329 
13330  const TriggerTmpl& triggerTmpl = buildIndexPtr.p->m_triggerTmpl[0];
13331 
13332  CreateTrigReq* req = (CreateTrigReq*)signal->getDataPtrSend();
13333 
13334  Uint32 requestInfo = 0;
13335  DictSignal::setRequestType(requestInfo, CreateTrigReq::CreateTriggerOnline);
13336  DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
13337 
13338  req->clientRef = reference();
13339  req->clientData = op_ptr.p->op_key;
13340  req->transId = trans_ptr.p->m_transId;
13341  req->transKey = trans_ptr.p->trans_key;
13342  req->requestInfo = requestInfo;
13343  req->tableId = impl_req->indexId; // constraint is on index table
13344  req->tableVersion = 0;
13345  req->indexId = RNIL;
13346  req->indexVersion = 0;
13347  req->triggerNo = 0;
13348  req->forceTriggerId = RNIL;
13349 
13350  TriggerInfo::packTriggerInfo(req->triggerInfo, triggerTmpl.triggerInfo);
13351 
13352  req->receiverRef = 0;
13353 
13354  char triggerName[MAX_TAB_NAME_SIZE];
13355  sprintf(triggerName, triggerTmpl.nameFormat, impl_req->indexId);
13356 
13357  // name section
13358  Uint32 buffer[2 + ((MAX_TAB_NAME_SIZE + 3) >> 2)]; // SP string
13359  LinearWriter w(buffer, sizeof(buffer) >> 2);
13360  w.reset();
13361  w.add(DictTabInfo::TableName, triggerName);
13362  LinearSectionPtr ls_ptr[3];
13363  ls_ptr[0].p = buffer;
13364  ls_ptr[0].sz = w.getWordsUsed();
13365 
13366  ls_ptr[1].p = buildIndexPtr.p->m_attrMask.rep.data;
13367  ls_ptr[1].sz = buildIndexPtr.p->m_attrMask.getSizeInWords();
13368 
13369  sendSignal(reference(), GSN_CREATE_TRIG_REQ, signal,
13370  CreateTrigReq::SignalLength, JBB, ls_ptr, 2);
13371 }
13372 
13373 void
13374 Dbdict::buildIndex_fromCreateConstraint(Signal* signal, Uint32 op_key, Uint32 ret)
13375 {
13376  jam();
13377 
13378  SchemaOpPtr op_ptr;
13379  BuildIndexRecPtr buildIndexPtr;
13380 
13381  findSchemaOp(op_ptr, buildIndexPtr, op_key);
13382  ndbrequire(!op_ptr.isNull());
13383  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
13384  //const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
13385 
13386  D("buildIndex_fromCreateConstraint" << dec << V(op_key) << V(ret));
13387 
13388  if (ret == 0) {
13389  jam();
13390  const CreateTrigConf* conf =
13391  (const CreateTrigConf*)signal->getDataPtr();
13392 
13393  ndbrequire(conf->transId == trans_ptr.p->m_transId);
13394  ndbrequire(buildIndexPtr.p->m_subOpIndex < buildIndexPtr.p->m_subOpCount);
13395  buildIndexPtr.p->m_subOpIndex += 1;
13396  createSubOps(signal, op_ptr);
13397  } else {
13398  const CreateTrigRef* ref =
13399  (const CreateTrigRef*)signal->getDataPtr();
13400 
13401  ErrorInfo error;
13402  setError(error, ref);
13403  abortSubOps(signal, op_ptr, error);
13404  }
13405 }
13406 
13407 void
13408 Dbdict::buildIndex_toBuildIndex(Signal* signal, SchemaOpPtr op_ptr)
13409 {
13410  D("buildIndex_toBuildIndex");
13411 
13412  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
13413  BuildIndexRecPtr buildIndexPtr;
13414  getOpRec(op_ptr, buildIndexPtr);
13415  const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
13416 
13417  BuildIndxReq* req = (BuildIndxReq*)signal->getDataPtrSend();
13418 
13419  Uint32 requestInfo = 0;
13420  DictSignal::setRequestType(requestInfo, BuildIndxReq::SubOp);
13421  DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
13422 
13423  req->clientRef = reference();
13424  req->clientData = op_ptr.p->op_key;
13425  req->transId = trans_ptr.p->m_transId;
13426  req->transKey = trans_ptr.p->trans_key;
13427  req->requestInfo = requestInfo;
13428  req->buildId = 0;
13429  req->buildKey = 0;
13430  req->tableId = impl_req->tableId;
13431  req->indexId = impl_req->indexId;
13432  req->indexType = impl_req->indexType;
13433  req->parallelism = impl_req->parallelism;
13434 
13435  sendSignal(reference(), GSN_BUILDINDXREQ, signal,
13436  BuildIndxReq::SignalLength, JBB);
13437 }
13438 
13439 void
13440 Dbdict::buildIndex_fromBuildIndex(Signal* signal, Uint32 op_key, Uint32 ret)
13441 {
13442  jam();
13443  D("buildIndex_fromBuildIndex");
13444 
13445  SchemaOpPtr op_ptr;
13446  BuildIndexRecPtr buildIndexPtr;
13447 
13448  findSchemaOp(op_ptr, buildIndexPtr, op_key);
13449  ndbrequire(!op_ptr.isNull());
13450  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
13451 
13452  if (ret == 0) {
13453  jam();
13454  const BuildIndxConf* conf =
13455  (const BuildIndxConf*)signal->getDataPtr();
13456 
13457  ndbrequire(conf->transId == trans_ptr.p->m_transId);
13458  ndbrequire(buildIndexPtr.p->m_subOpIndex < buildIndexPtr.p->m_subOpCount);
13459  buildIndexPtr.p->m_subOpIndex += 1;
13460  createSubOps(signal, op_ptr);
13461  } else {
13462  jam();
13463  const BuildIndxRef* ref =
13464  (const BuildIndxRef*)signal->getDataPtr();
13465 
13466  ErrorInfo error;
13467  setError(error, ref);
13468  abortSubOps(signal, op_ptr, error);
13469  }
13470 }
13471 
13472 void
13473 Dbdict::buildIndex_toDropConstraint(Signal* signal, SchemaOpPtr op_ptr)
13474 {
13475  D("buildIndex_toDropConstraint");
13476 
13477  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
13478  BuildIndexRecPtr buildIndexPtr;
13479  getOpRec(op_ptr, buildIndexPtr);
13480  const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
13481 
13482  TableRecordPtr indexPtr;
13483  c_tableRecordPool.getPtr(indexPtr, impl_req->indexId);
13484 
13485  const TriggerTmpl& triggerTmpl = buildIndexPtr.p->m_triggerTmpl[0];
13486 
13487  DropTrigReq* req = (DropTrigReq*)signal->getDataPtrSend();
13488 
13489  Uint32 requestInfo = 0;
13490  DictSignal::setRequestType(requestInfo, 0);
13491  DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
13492 
13493  req->clientRef = reference();
13494  req->clientData = op_ptr.p->op_key;
13495  req->transId = trans_ptr.p->m_transId;
13496  req->transKey = trans_ptr.p->trans_key;
13497  req->requestInfo = requestInfo;
13498  req->tableId = impl_req->indexId; // constraint is on index table
13499  req->tableVersion = 0;
13500  req->indexId = RNIL;
13501  req->indexVersion = 0;
13502  req->triggerNo = 0;
13503  req->triggerId = RNIL;
13504 
13505  // wl3600_todo use name now, connect by tree walk later
13506 
13507  char triggerName[MAX_TAB_NAME_SIZE];
13508  sprintf(triggerName, triggerTmpl.nameFormat, impl_req->indexId);
13509 
13510  // name section
13511  Uint32 buffer[2 + ((MAX_TAB_NAME_SIZE + 3) >> 2)]; // SP string
13512  LinearWriter w(buffer, sizeof(buffer) >> 2);
13513  w.reset();
13514  w.add(DictTabInfo::TableName, triggerName);
13515  LinearSectionPtr ls_ptr[3];
13516  ls_ptr[0].p = buffer;
13517  ls_ptr[0].sz = w.getWordsUsed();
13518 
13519  sendSignal(reference(), GSN_DROP_TRIG_REQ, signal,
13520  DropTrigReq::SignalLength, JBB, ls_ptr, 1);
13521 }
13522 
13523 void
13524 Dbdict::buildIndex_fromDropConstraint(Signal* signal, Uint32 op_key, Uint32 ret)
13525 {
13526  jam();
13527 
13528  SchemaOpPtr op_ptr;
13529  BuildIndexRecPtr buildIndexPtr;
13530 
13531  findSchemaOp(op_ptr, buildIndexPtr, op_key);
13532  ndbrequire(!op_ptr.isNull());
13533  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
13534  //const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
13535 
13536  D("buildIndex_fromDropConstraint" << dec << V(op_key) << V(ret));
13537 
13538  if (ret == 0) {
13539  const DropTrigConf* conf =
13540  (const DropTrigConf*)signal->getDataPtr();
13541 
13542  ndbrequire(conf->transId == trans_ptr.p->m_transId);
13543  ndbrequire(buildIndexPtr.p->m_subOpIndex < buildIndexPtr.p->m_subOpCount);
13544  buildIndexPtr.p->m_subOpIndex += 1;
13545  createSubOps(signal, op_ptr);
13546  } else {
13547  jam();
13548  const DropTrigRef* ref =
13549  (const DropTrigRef*)signal->getDataPtr();
13550 
13551  ErrorInfo error;
13552  setError(error, ref);
13553  abortSubOps(signal, op_ptr, error);
13554  }
13555 }
13556 
13557 void
13558 Dbdict::buildIndex_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
13559 {
13560  jam();
13561 
13562  SchemaTransPtr& trans_ptr = op_ptr.p->m_trans_ptr;
13563  BuildIndexRecPtr buildIndexPtr;
13564  getOpRec(op_ptr, buildIndexPtr);
13565  const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
13566 
13567  D("buildIndex_reply" << V(impl_req->indexId));
13568 
13569  TableRecordPtr indexPtr;
13570  c_tableRecordPool.getPtr(indexPtr, impl_req->indexId);
13571 
13572  if (!hasError(error)) {
13573  BuildIndxConf* conf = (BuildIndxConf*)signal->getDataPtrSend();
13574  conf->senderRef = reference();
13575  conf->clientData = op_ptr.p->m_clientData;
13576  conf->transId = trans_ptr.p->m_transId;
13577  conf->tableId = impl_req->tableId;
13578  conf->indexId = impl_req->indexId;
13579  conf->indexType = impl_req->indexType;
13580 
13581  Uint32 clientRef = op_ptr.p->m_clientRef;
13582  sendSignal(clientRef, GSN_BUILDINDXCONF, signal,
13583  BuildIndxConf::SignalLength, JBB);
13584  } else {
13585  jam();
13586  BuildIndxRef* ref = (BuildIndxRef*)signal->getDataPtrSend();
13587  ref->senderRef = reference();
13588  ref->clientData = op_ptr.p->m_clientData;
13589  ref->transId = trans_ptr.p->m_transId;
13590  ref->tableId = impl_req->tableId;
13591  ref->indexId = impl_req->indexId;
13592  ref->indexType = impl_req->indexType;
13593  getError(error, ref);
13594 
13595  Uint32 clientRef = op_ptr.p->m_clientRef;
13596  sendSignal(clientRef, GSN_BUILDINDXREF, signal,
13597  BuildIndxRef::SignalLength, JBB);
13598  }
13599 }
13600 
13601 // BuildIndex: PREPARE
13602 
13603 void
13604 Dbdict::buildIndex_prepare(Signal* signal, SchemaOpPtr op_ptr)
13605 {
13606  jam();
13607  BuildIndexRecPtr buildIndexPtr;
13608  getOpRec(op_ptr, buildIndexPtr);
13609  //const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
13610 
13611  Uint32 requestInfo = op_ptr.p->m_requestInfo;
13612  bool noBuild = (requestInfo & DictSignal::RF_NO_BUILD);
13613 
13614  D("buildIndex_prepare" << hex << V(requestInfo));
13615 
13616  if (noBuild || !buildIndexPtr.p->m_doBuild) {
13617  jam();
13618  sendTransConf(signal, op_ptr);
13619  return;
13620  }
13621 
13622  buildIndex_toLocalBuild(signal, op_ptr);
13623 }
13624 
13625 void
13626 Dbdict:: buildIndex_toLocalBuild(Signal* signal, SchemaOpPtr op_ptr)
13627 {
13628  BuildIndexRecPtr buildIndexPtr;
13629  getOpRec(op_ptr, buildIndexPtr);
13630  const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
13631  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
13632 
13633  TableRecordPtr indexPtr;
13634  c_tableRecordPool.getPtr(indexPtr, impl_req->indexId);
13635 
13636  D("buildIndex_toLocalBuild");
13637 
13638  BuildIndxImplReq* req = (BuildIndxImplReq*)signal->getDataPtrSend();
13639 
13640  req->senderRef = reference();
13641  req->senderData = op_ptr.p->op_key;
13642  req->requestType = impl_req->requestType;
13643  req->transId = trans_ptr.p->m_transId;
13644  req->buildId = impl_req->buildId;
13645  req->buildKey = impl_req->buildKey;
13646  req->tableId = impl_req->tableId;
13647  req->indexId = impl_req->indexId;
13648  req->indexType = indexPtr.p->tableType;
13649  req->parallelism = impl_req->parallelism;
13650 
13651  /* All indexed columns must be in memory currently */
13652  req->requestType |= BuildIndxImplReq::RF_NO_DISK;
13653 
13654  Callback c = {
13655  safe_cast(&Dbdict::buildIndex_fromLocalBuild),
13656  op_ptr.p->op_key
13657  };
13658  op_ptr.p->m_callback = c;
13659 
13660  switch (indexPtr.p->tableType) {
13661  case DictTabInfo::UniqueHashIndex:
13662  jam();
13663  {
13664  LinearSectionPtr ls_ptr[3];
13665  ls_ptr[0].sz = buildIndexPtr.p->m_indexKeyList.sz;
13666  ls_ptr[0].p = buildIndexPtr.p->m_indexKeyList.id;
13667  ls_ptr[1].sz = buildIndexPtr.p->m_tableKeyList.sz;
13668  ls_ptr[1].p = buildIndexPtr.p->m_tableKeyList.id;
13669 
13670  sendSignal(TRIX_REF, GSN_BUILD_INDX_IMPL_REQ, signal,
13671  BuildIndxImplReq::SignalLength, JBB, ls_ptr, 2);
13672  }
13673  break;
13674  case DictTabInfo::OrderedIndex:
13675  jam();
13676  if (op_ptr.p->m_requestInfo & BuildIndxReq::RF_BUILD_OFFLINE)
13677  {
13678  jam();
13679  req->requestType |= BuildIndxImplReq::RF_BUILD_OFFLINE;
13680  }
13681 
13682  {
13683  sendSignal(DBTUP_REF, GSN_BUILD_INDX_IMPL_REQ, signal,
13684  BuildIndxImplReq::SignalLength, JBB);
13685  }
13686  break;
13687  default:
13688  ndbrequire(false);
13689  break;
13690  }
13691 }
13692 
13693 void
13694 Dbdict::buildIndex_fromLocalBuild(Signal* signal, Uint32 op_key, Uint32 ret)
13695 {
13696  SchemaOpPtr op_ptr;
13697  BuildIndexRecPtr buildIndexPtr;
13698  findSchemaOp(op_ptr, buildIndexPtr, op_key);
13699  ndbrequire(!op_ptr.isNull());
13700 
13701  D("buildIndex_fromLocalBuild");
13702 
13703  if (ret == 0) {
13704  jam();
13705  sendTransConf(signal, op_ptr);
13706  } else {
13707  jam();
13708  setError(op_ptr, ret, __LINE__);
13709  sendTransRef(signal, op_ptr);
13710  }
13711 }
13712 
13713 // BuildIndex: COMMIT
13714 
13715 void
13716 Dbdict::buildIndex_commit(Signal* signal, SchemaOpPtr op_ptr)
13717 {
13718  jam();
13719  BuildIndexRecPtr buildIndexPtr;
13720  getOpRec(op_ptr, buildIndexPtr);
13721 
13722  D("buildIndex_commit" << *op_ptr.p);
13723 
13724  buildIndex_toLocalOnline(signal, op_ptr);
13725 }
13726 
13727 void
13728 Dbdict::buildIndex_toLocalOnline(Signal* signal, SchemaOpPtr op_ptr)
13729 {
13730  BuildIndexRecPtr buildIndexPtr;
13731  getOpRec(op_ptr, buildIndexPtr);
13732  const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
13733 
13734  TableRecordPtr indexPtr;
13735  c_tableRecordPool.getPtr(indexPtr, impl_req->indexId);
13736 
13737  D("buildIndex_toLocalOnline");
13738 
13739  AlterIndxImplReq* req = (AlterIndxImplReq*)signal->getDataPtrSend();
13740 
13741  req->senderRef = reference();
13742  req->senderData = op_ptr.p->op_key;
13743  req->requestType = impl_req->requestType;
13744  req->tableId = impl_req->tableId;
13745  req->tableVersion = 0; // not used
13746  req->indexId = impl_req->indexId;
13747  req->indexVersion = 0; // not used
13748 
13749  Callback c = {
13750  safe_cast(&Dbdict::buildIndex_fromLocalOnline),
13751  op_ptr.p->op_key
13752  };
13753  op_ptr.p->m_callback = c;
13754 
13755  switch (indexPtr.p->tableType) {
13756  case DictTabInfo::UniqueHashIndex:
13757  jam();
13758  {
13759  sendSignal(DBTC_REF, GSN_ALTER_INDX_IMPL_REQ, signal,
13760  AlterIndxImplReq::SignalLength, JBB);
13761  }
13762  break;
13763  case DictTabInfo::OrderedIndex:
13764  jam();
13765  {
13766  sendSignal(DBTUX_REF, GSN_ALTER_INDX_IMPL_REQ, signal,
13767  AlterIndxImplReq::SignalLength, JBB);
13768  }
13769  break;
13770  default:
13771  ndbrequire(false);
13772  break;
13773  }
13774 }
13775 
13776 void
13777 Dbdict::buildIndex_fromLocalOnline(Signal* signal, Uint32 op_key, Uint32 ret)
13778 {
13779  SchemaOpPtr op_ptr;
13780  BuildIndexRecPtr buildIndexPtr;
13781  findSchemaOp(op_ptr, buildIndexPtr, op_key);
13782  ndbrequire(!op_ptr.isNull());
13783  const BuildIndxImplReq* impl_req = &buildIndexPtr.p->m_request;
13784 
13785  TableRecordPtr indexPtr;
13786  c_tableRecordPool.getPtr(indexPtr, impl_req->indexId);
13787 
13788  D("buildIndex_fromLocalOnline");
13789 
13790  if (ret == 0) {
13791  jam();
13792  // set index online
13793  indexPtr.p->indexState = TableRecord::IS_ONLINE;
13794  sendTransConf(signal, op_ptr);
13795  } else {
13796  //wl3600_todo
13797  ndbrequire(false);
13798  }
13799 }
13800 
13801 // BuildIndex: COMPLETE
13802 
13803 void
13804 Dbdict::buildIndex_complete(Signal* signal, SchemaOpPtr op_ptr)
13805 {
13806  jam();
13807  sendTransConf(signal, op_ptr);
13808 }
13809 
13810 // BuildIndex: ABORT
13811 
13812 void
13813 Dbdict::buildIndex_abortParse(Signal* signal, SchemaOpPtr op_ptr)
13814 {
13815  D("buildIndex_abortParse" << *op_ptr.p);
13816  // wl3600_todo
13817  sendTransConf(signal, op_ptr);
13818 }
13819 
13820 void
13821 Dbdict::buildIndex_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
13822 {
13823  D("buildIndex_abortPrepare" << *op_ptr.p);
13824 
13825  // nothing to do, entire index table will be dropped
13826  sendTransConf(signal, op_ptr);
13827 }
13828 
13829 // BuildIndex: MISC
13830 
13831 void
13832 Dbdict::execBUILDINDXCONF(Signal* signal)
13833 {
13834  jamEntry();
13835  const BuildIndxConf* conf = (const BuildIndxConf*)signal->getDataPtr();
13836  handleDictConf(signal, conf);
13837 }
13838 
13839 void
13840 Dbdict::execBUILDINDXREF(Signal* signal)
13841 {
13842  jamEntry();
13843  const BuildIndxRef* ref = (const BuildIndxRef*)signal->getDataPtr();
13844  handleDictRef(signal, ref);
13845 }
13846 
13847 void
13848 Dbdict::execBUILD_INDX_IMPL_CONF(Signal* signal)
13849 {
13850  jamEntry();
13851  const BuildIndxImplConf* conf = (const BuildIndxImplConf*)signal->getDataPtr();
13852  handleDictConf(signal, conf);
13853 }
13854 
13855 void
13856 Dbdict::execBUILD_INDX_IMPL_REF(Signal* signal)
13857 {
13858  jamEntry();
13859  const BuildIndxImplRef* ref = (const BuildIndxImplRef*)signal->getDataPtr();
13860  handleDictRef(signal, ref);
13861 }
13862 
13863 // BuildIndex: END
13864 
13865 // MODULE: IndexStat
13866 
13867 const Dbdict::OpInfo
13868 Dbdict::IndexStatRec::g_opInfo = {
13869  { 'S', 'I', 'n', 0 },
13870  GSN_INDEX_STAT_IMPL_REQ,
13871  IndexStatImplReq::SignalLength,
13872  //
13873  &Dbdict::indexStat_seize,
13874  &Dbdict::indexStat_release,
13875  //
13876  &Dbdict::indexStat_parse,
13877  &Dbdict::indexStat_subOps,
13878  &Dbdict::indexStat_reply,
13879  //
13880  &Dbdict::indexStat_prepare,
13881  &Dbdict::indexStat_commit,
13882  &Dbdict::indexStat_complete,
13883  //
13884  &Dbdict::indexStat_abortParse,
13885  &Dbdict::indexStat_abortPrepare
13886 };
13887 
13888 bool
13889 Dbdict::indexStat_seize(SchemaOpPtr op_ptr)
13890 {
13891  return seizeOpRec<IndexStatRec>(op_ptr);
13892 }
13893 
13894 void
13895 Dbdict::indexStat_release(SchemaOpPtr op_ptr)
13896 {
13897  releaseOpRec<IndexStatRec>(op_ptr);
13898 }
13899 
13900 void
13901 Dbdict::execINDEX_STAT_REQ(Signal* signal)
13902 {
13903  jamEntry();
13904  if (!assembleFragments(signal)) {
13905  jam();
13906  return;
13907  }
13908  SectionHandle handle(this, signal);
13909 
13910  const IndexStatReq req_copy =
13911  *(const IndexStatReq*)signal->getDataPtr();
13912  const IndexStatReq* req = &req_copy;
13913 
13914  ErrorInfo error;
13915  do {
13916  SchemaOpPtr op_ptr;
13917  IndexStatRecPtr indexStatPtr;
13918  IndexStatImplReq* impl_req;
13919 
13920  startClientReq(op_ptr, indexStatPtr, req, impl_req, error);
13921  if (hasError(error)) {
13922  jam();
13923  break;
13924  }
13925 
13926  // senderRef, senderData, requestType have been set already
13927  impl_req->transId = req->transId;
13928  impl_req->requestFlag = req->requestFlag;
13929  impl_req->indexId = req->indexId;
13930  impl_req->indexVersion = req->indexVersion;
13931  impl_req->tableId = req->tableId;
13932  impl_req->fragId = ZNIL;
13933  impl_req->fragCount = ZNIL;
13934 
13935  handleClientReq(signal, op_ptr, handle);
13936  return;
13937  } while (0);
13938 
13939  releaseSections(handle);
13940 
13941  IndexStatRef* ref = (IndexStatRef*)signal->getDataPtrSend();
13942  ref->senderRef = reference();
13943  ref->clientData = req->clientData;
13944  ref->transId = req->transId;
13945  getError(error, ref);
13946 
13947  sendSignal(req->clientRef, GSN_INDEX_STAT_REF, signal,
13948  IndexStatRef::SignalLength, JBB);
13949 }
13950 
13951 // IndexStat: PARSE
13952 
13953 void
13954 Dbdict::indexStat_parse(Signal* signal, bool master,
13955  SchemaOpPtr op_ptr,
13956  SectionHandle& handle, ErrorInfo& error)
13957 {
13958  D("indexStat_parse");
13959 
13960  IndexStatRecPtr indexStatPtr;
13961  getOpRec(op_ptr, indexStatPtr);
13962  IndexStatImplReq* impl_req = &indexStatPtr.p->m_request;
13963 
13964  // get index
13965  TableRecordPtr indexPtr;
13966  if (!(impl_req->indexId < c_tableRecordPool.getSize())) {
13967  jam();
13968  setError(error, IndexStatRef::InvalidIndex, __LINE__);
13969  return;
13970  }
13971  c_tableRecordPool.getPtr(indexPtr, impl_req->indexId);
13972 
13973  if (!indexPtr.p->isOrderedIndex()) {
13974  jam();
13975  setError(error, IndexStatRef::InvalidIndex, __LINE__);
13976  return;
13977  }
13978 
13979  XSchemaFile* xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
13980  const SchemaFile::TableEntry* te = getTableEntry(xsf, impl_req->indexId);
13981  if (te->m_tableState != SchemaFile::SF_CREATE &&
13982  te->m_tableState != SchemaFile::SF_IN_USE) {
13983  jam();
13984  setError(error, IndexStatRef::InvalidIndex, __LINE__);
13985  return;
13986  }
13987 
13988  // fragmentId is defined only in signals from DICT to TRIX,TUX
13989  if (impl_req->fragId != ZNIL) {
13990  jam();
13991  setError(error, IndexStatRef::InvalidRequest, __LINE__);
13992  return;
13993  }
13994  impl_req->fragCount = indexPtr.p->fragmentCount;
13995 
13996  switch (impl_req->requestType) {
13997  case IndexStatReq::RT_UPDATE_STAT:
13998  jam();
13999  // clean new samples, scan, clean old samples, start frag monitor
14000  indexStatPtr.p->m_subOpCount = 4;
14001  indexStatPtr.p->m_subOpIndex = 0;
14002  break;
14003  case IndexStatReq::RT_DELETE_STAT:
14004  jam();
14005  // stop frag monitor, delete head, clean all samples
14006  indexStatPtr.p->m_subOpCount = 3;
14007  indexStatPtr.p->m_subOpIndex = 0;
14008  break;
14009  case IndexStatReq::RT_SCAN_FRAG:
14010  case IndexStatReq::RT_CLEAN_NEW:
14011  case IndexStatReq::RT_CLEAN_OLD:
14012  case IndexStatReq::RT_CLEAN_ALL:
14013  case IndexStatReq::RT_DROP_HEAD:
14014  case IndexStatReq::RT_START_MON:
14015  case IndexStatReq::RT_STOP_MON:
14016  jam();
14017  // sub-operations can be invoked only by DICT
14018  if (master && refToBlock(op_ptr.p->m_clientRef) != DBDICT) {
14019  jam();
14020  setError(error, IndexStatRef::InvalidRequest, __LINE__);
14021  return;
14022  }
14023  indexStatPtr.p->m_subOpCount = 0;
14024  indexStatPtr.p->m_subOpIndex = 0;
14025  break;
14026  default:
14027  jam();
14028  setError(error, IndexStatRef::InvalidRequest, __LINE__);
14029  return;
14030  }
14031 }
14032 
14033 bool
14034 Dbdict::indexStat_subOps(Signal* signal, SchemaOpPtr op_ptr)
14035 {
14036  D("indexStat_subOps" << V(op_ptr.i) << V(*op_ptr.p));
14037 
14038  IndexStatRecPtr indexStatPtr;
14039  getOpRec(op_ptr, indexStatPtr);
14040  const IndexStatImplReq* impl_req = &indexStatPtr.p->m_request;
14041 
14042  const Uint32 subOpIndex = indexStatPtr.p->m_subOpIndex;
14043  const Uint32 subOpCount = indexStatPtr.p->m_subOpCount;
14044  if (subOpIndex >= subOpCount) {
14045  jam();
14046  ndbrequire(subOpIndex == subOpCount);
14047  return false;
14048  }
14049 
14050  Uint32 requestType = 0;
14051 
14052  switch (impl_req->requestType) {
14053  case IndexStatReq::RT_UPDATE_STAT:
14054  if (subOpIndex == 0)
14055  requestType = IndexStatReq::RT_CLEAN_NEW;
14056  else if (subOpIndex == 1)
14057  requestType = IndexStatReq::RT_SCAN_FRAG;
14058  else if (subOpIndex == 2)
14059  requestType = IndexStatReq::RT_CLEAN_OLD;
14060  else if (subOpIndex == 3)
14061  requestType = IndexStatReq::RT_START_MON;
14062  break;
14063 
14064  case IndexStatReq::RT_DELETE_STAT:
14065  jam();
14066  if (subOpIndex == 0)
14067  requestType = IndexStatReq::RT_STOP_MON;
14068  else if (subOpIndex == 1)
14069  requestType = IndexStatReq::RT_DROP_HEAD;
14070  else if (subOpIndex == 2)
14071  requestType = IndexStatReq::RT_CLEAN_ALL;
14072  break;
14073  };
14074 
14075  ndbrequire(requestType != 0);
14076  Callback c = {
14077  safe_cast(&Dbdict::indexStat_fromIndexStat),
14078  op_ptr.p->op_key
14079  };
14080  op_ptr.p->m_callback = c;
14081  indexStat_toIndexStat(signal, op_ptr, requestType);
14082  return true;
14083 }
14084 
14085 void
14086 Dbdict::indexStat_toIndexStat(Signal* signal, SchemaOpPtr op_ptr,
14087  Uint32 requestType)
14088 {
14089  D("indexStat_toIndexStat");
14090 
14091  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
14092  IndexStatRecPtr indexStatPtr;
14093  getOpRec(op_ptr, indexStatPtr);
14094  const IndexStatImplReq* impl_req = &indexStatPtr.p->m_request;
14095 
14096  IndexStatReq* req = (IndexStatReq*)signal->getDataPtrSend();
14097 
14098  Uint32 requestInfo = 0;
14099  DictSignal::setRequestType(requestInfo, requestType);
14100  DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
14101 
14102  TableRecordPtr indexPtr;
14103  c_tableRecordPool.getPtr(indexPtr, impl_req->indexId);
14104 
14105  req->clientRef = reference();
14106  req->clientData = op_ptr.p->op_key;
14107  req->transId = trans_ptr.p->m_transId;
14108  req->transKey = trans_ptr.p->trans_key;
14109  req->requestInfo = requestInfo;
14110  req->requestFlag = 0;
14111  req->indexId = impl_req->indexId;
14112  req->indexVersion = indexPtr.p->tableVersion;
14113  req->tableId = impl_req->tableId;
14114 
14115  sendSignal(reference(), GSN_INDEX_STAT_REQ,
14116  signal, IndexStatReq::SignalLength, JBB);
14117 }
14118 
14119 void
14120 Dbdict::indexStat_fromIndexStat(Signal* signal, Uint32 op_key, Uint32 ret)
14121 {
14122  jam();
14123  D("indexStat_fromIndexStat");
14124 
14125  SchemaOpPtr op_ptr;
14126  IndexStatRecPtr indexStatPtr;
14127 
14128  findSchemaOp(op_ptr, indexStatPtr, op_key);
14129  ndbrequire(!op_ptr.isNull());
14130  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
14131 
14132  if (ret == 0) {
14133  jam();
14134  const IndexStatConf* conf =
14135  (const IndexStatConf*)signal->getDataPtr();
14136 
14137  ndbrequire(conf->transId == trans_ptr.p->m_transId);
14138  ndbrequire(indexStatPtr.p->m_subOpIndex < indexStatPtr.p->m_subOpCount);
14139  indexStatPtr.p->m_subOpIndex += 1;
14140  createSubOps(signal, op_ptr);
14141  } else {
14142  jam();
14143  const IndexStatRef* ref =
14144  (const IndexStatRef*)signal->getDataPtr();
14145 
14146  ErrorInfo error;
14147  setError(error, ref);
14148  abortSubOps(signal, op_ptr, error);
14149  }
14150 }
14151 
14152 void
14153 Dbdict::indexStat_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
14154 {
14155  jam();
14156 
14157  SchemaTransPtr& trans_ptr = op_ptr.p->m_trans_ptr;
14158  IndexStatRecPtr indexStatPtr;
14159  getOpRec(op_ptr, indexStatPtr);
14160  const IndexStatImplReq* impl_req = &indexStatPtr.p->m_request;
14161 
14162  D("indexStat_reply" << V(impl_req->indexId));
14163 
14164  TableRecordPtr indexPtr;
14165  c_tableRecordPool.getPtr(indexPtr, impl_req->indexId);
14166 
14167  if (!hasError(error)) {
14168  IndexStatConf* conf = (IndexStatConf*)signal->getDataPtrSend();
14169  conf->senderRef = reference();
14170  conf->clientData = op_ptr.p->m_clientData;
14171  conf->transId = trans_ptr.p->m_transId;
14172 
14173  Uint32 clientRef = op_ptr.p->m_clientRef;
14174  sendSignal(clientRef, GSN_INDEX_STAT_CONF, signal,
14175  IndexStatConf::SignalLength, JBB);
14176  } else {
14177  jam();
14178  IndexStatRef* ref = (IndexStatRef*)signal->getDataPtrSend();
14179  ref->senderRef = reference();
14180  ref->clientData = op_ptr.p->m_clientData;
14181  ref->transId = trans_ptr.p->m_transId;
14182  getError(error, ref);
14183 
14184  Uint32 clientRef = op_ptr.p->m_clientRef;
14185  sendSignal(clientRef, GSN_INDEX_STAT_REF, signal,
14186  IndexStatRef::SignalLength, JBB);
14187  }
14188 }
14189 
14190 // IndexStat: PREPARE
14191 
14192 void
14193 Dbdict::indexStat_prepare(Signal* signal, SchemaOpPtr op_ptr)
14194 {
14195  jam();
14196  IndexStatRecPtr indexStatPtr;
14197  getOpRec(op_ptr, indexStatPtr);
14198  const IndexStatImplReq* impl_req = &indexStatPtr.p->m_request;
14199 
14200  D("indexStat_prepare" << V(*op_ptr.p));
14201 
14202  if (impl_req->requestType == IndexStatReq::RT_UPDATE_STAT ||
14203  impl_req->requestType == IndexStatReq::RT_DELETE_STAT) {
14204  // the main op of stat update or delete does nothing
14205  sendTransConf(signal, op_ptr);
14206  return;
14207  }
14208 
14209  indexStat_toLocalStat(signal, op_ptr);
14210 }
14211 
14212 void
14213 Dbdict::indexStat_toLocalStat(Signal* signal, SchemaOpPtr op_ptr)
14214 {
14215  IndexStatRecPtr indexStatPtr;
14216  getOpRec(op_ptr, indexStatPtr);
14217  const IndexStatImplReq* impl_req = &indexStatPtr.p->m_request;
14218  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
14219 
14220  D("indexStat_toLocalStat");
14221 
14222  TableRecordPtr indexPtr;
14223  c_tableRecordPool.getPtr(indexPtr, impl_req->indexId);
14224  ndbrequire(indexPtr.p->isOrderedIndex());
14225 
14226  Callback c = {
14227  safe_cast(&Dbdict::indexStat_fromLocalStat),
14228  op_ptr.p->op_key
14229  };
14230  op_ptr.p->m_callback = c;
14231 
14232  IndexStatImplReq* req = (IndexStatImplReq*)signal->getDataPtrSend();
14233  *req = *impl_req;
14234  req->senderRef = reference();
14235  req->senderData = op_ptr.p->op_key;
14236  ndbrequire(req->fragId == ZNIL);
14237  ndbrequire(indexPtr.p->indexStatFragId != ZNIL);
14238  BlockReference ref = 0;
14239 
14240  switch (impl_req->requestType) {
14241  case IndexStatReq::RT_SCAN_FRAG:
14242  req->fragId = indexPtr.p->indexStatFragId;
14243  if (indexPtr.p->indexStatNodeId != getOwnNodeId()) {
14244  jam();
14245  D("skip" << V(impl_req->requestType));
14246  execute(signal, c, 0);
14247  return;
14248  }
14249  ref = TRIX_REF;
14250  break;
14251 
14252  case IndexStatReq::RT_CLEAN_NEW:
14253  case IndexStatReq::RT_CLEAN_OLD:
14254  case IndexStatReq::RT_CLEAN_ALL:
14255  /*
14256  * Index stats "v4" does scan deletes via TRIX-SUMA. But SUMA does
14257  * only local scans so do it on all nodes.
14258  */
14259  req->fragId = ZNIL;
14260  ref = TRIX_REF;
14261  break;
14262 
14263  case IndexStatReq::RT_DROP_HEAD:
14264  req->fragId = indexPtr.p->indexStatFragId;
14265  if (indexPtr.p->indexStatNodeId != getOwnNodeId()) {
14266  jam();
14267  D("skip" << V(impl_req->requestType));
14268  execute(signal, c, 0);
14269  return;
14270  }
14271  ref = TRIX_REF;
14272  break;
14273 
14274  case IndexStatReq::RT_START_MON:
14275  req->fragId = indexPtr.p->indexStatFragId;
14276  if (indexPtr.p->indexStatNodeId != getOwnNodeId()) {
14277  jam();
14278  req->fragId = ZNIL;
14279  }
14280  ref = DBTUX_REF;
14281  break;
14282 
14283  case IndexStatReq::RT_STOP_MON:
14284  req->fragId = ZNIL;
14285  ref = DBTUX_REF;
14286  break;
14287 
14288  default:
14289  ndbrequire(false); // only sub-ops seen here
14290  break;
14291  }
14292 
14293  sendSignal(ref, GSN_INDEX_STAT_IMPL_REQ,
14294  signal, IndexStatImplReq::SignalLength, JBB);
14295 }
14296 
14297 void
14298 Dbdict::indexStat_fromLocalStat(Signal* signal, Uint32 op_key, Uint32 ret)
14299 {
14300  SchemaOpPtr op_ptr;
14301  IndexStatRecPtr indexStatPtr;
14302  findSchemaOp(op_ptr, indexStatPtr, op_key);
14303  ndbrequire(!op_ptr.isNull());
14304  const IndexStatImplReq* impl_req = &indexStatPtr.p->m_request;
14305 
14306  if (ret != 0) {
14307  jam();
14308  if (impl_req->requestType != IndexStatReq::RT_CLEAN_OLD &&
14309  impl_req->requestType != IndexStatReq::RT_CLEAN_ALL &&
14310  impl_req->requestType != IndexStatReq::RT_DROP_HEAD) {
14311  jam();
14312  setError(op_ptr, ret, __LINE__);
14313  sendTransRef(signal, op_ptr);
14314  return;
14315  }
14316  D("ignore failed index stat cleanup");
14317  }
14318  sendTransConf(signal, op_ptr);
14319 }
14320 
14321 // IndexStat: COMMIT
14322 
14323 void
14324 Dbdict::indexStat_commit(Signal* signal, SchemaOpPtr op_ptr)
14325 {
14326  jam();
14327  IndexStatRecPtr indexStatPtr;
14328  getOpRec(op_ptr, indexStatPtr);
14329  D("indexStat_commit" << *op_ptr.p);
14330  sendTransConf(signal, op_ptr);
14331 }
14332 
14333 // IndexStat: COMPLETE
14334 
14335 void
14336 Dbdict::indexStat_complete(Signal* signal, SchemaOpPtr op_ptr)
14337 {
14338  jam();
14339  IndexStatRecPtr indexStatPtr;
14340  getOpRec(op_ptr, indexStatPtr);
14341  D("indexStat_complete" << *op_ptr.p);
14342  sendTransConf(signal, op_ptr);
14343 }
14344 
14345 // IndexStat: ABORT
14346 
14347 void
14348 Dbdict::indexStat_abortParse(Signal* signal, SchemaOpPtr op_ptr)
14349 {
14350  D("indexStat_abortParse" << *op_ptr.p);
14351  // wl3600_todo
14352  sendTransConf(signal, op_ptr);
14353 }
14354 
14355 void
14356 Dbdict::indexStat_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
14357 {
14358  D("indexStat_abortPrepare" << *op_ptr.p);
14359 
14360  // nothing to do, entire index table will be dropped
14361  sendTransConf(signal, op_ptr);
14362 }
14363 
14364 // IndexStat: MISC
14365 
14366 void
14367 Dbdict::execINDEX_STAT_CONF(Signal* signal)
14368 {
14369  jamEntry();
14370  const IndexStatConf* conf = (const IndexStatConf*)signal->getDataPtr();
14371  handleDictConf(signal, conf);
14372 }
14373 
14374 void
14375 Dbdict::execINDEX_STAT_REF(Signal* signal)
14376 {
14377  jamEntry();
14378  const IndexStatRef* ref = (const IndexStatRef*)signal->getDataPtr();
14379  handleDictRef(signal, ref);
14380 }
14381 
14382 void
14383 Dbdict::execINDEX_STAT_IMPL_CONF(Signal* signal)
14384 {
14385  jamEntry();
14386  const IndexStatImplConf* conf = (const IndexStatImplConf*)signal->getDataPtr();
14387  handleDictConf(signal, conf);
14388 }
14389 
14390 void
14391 Dbdict::execINDEX_STAT_IMPL_REF(Signal* signal)
14392 {
14393  jamEntry();
14394  const IndexStatImplRef* ref = (const IndexStatImplRef*)signal->getDataPtr();
14395  handleDictRef(signal, ref);
14396 }
14397 
14398 // IndexStat: background processing
14399 
14400 /*
14401  * Receive report that an index needs stats update. Request to
14402  * non-master is sent to master. Index is marked for stats update.
14403  * Invalid request is simply ignored. Master-NF really need not be
14404  * handled but could be, by broadcasting all reports to all DICTs.
14405  */
14406 void
14407 Dbdict::execINDEX_STAT_REP(Signal* signal)
14408 {
14409  const IndexStatRep* rep = (const IndexStatRep*)signal->getDataPtr();
14410 
14411  // non-master
14412  if (c_masterNodeId != getOwnNodeId()) {
14413  jam();
14414  BlockReference dictRef = calcDictBlockRef(c_masterNodeId);
14415  sendSignal(dictRef, GSN_INDEX_STAT_REP, signal,
14416  IndexStatRep::SignalLength, JBB);
14417  return;
14418  }
14419 
14420  // check
14421  TableRecordPtr indexPtr;
14422  if (rep->indexId >= c_tableRecordPool.getSize()) {
14423  jam();
14424  return;
14425  }
14426  XSchemaFile* xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
14427  const SchemaFile::TableEntry* te = getTableEntry(xsf, rep->indexId);
14428  if (te->m_tableState != SchemaFile::SF_IN_USE) {
14429  jam();
14430  return;
14431  }
14432  c_tableRecordPool.getPtr(indexPtr, rep->indexId);
14433  if (rep->indexVersion != 0 &&
14434  rep->indexVersion != indexPtr.p->tableVersion) {
14435  jam();
14436  return;
14437  }
14438  if (!indexPtr.p->isOrderedIndex()) {
14439  jam();
14440  return;
14441  }
14442  if (rep->requestType != IndexStatRep::RT_UPDATE_REQ) {
14443  jam();
14444  return;
14445  }
14446 
14447  D("index stat: " << copyRope<MAX_TAB_NAME_SIZE>(indexPtr.p->tableName)
14448  << " request type:" << rep->requestType);
14449 
14450  infoEvent("DICT: index %u stats auto-update requested", indexPtr.i);
14451  indexPtr.p->indexStatBgRequest = rep->requestType;
14452 }
14453 
14454 void
14455 Dbdict::indexStatBg_process(Signal* signal)
14456 {
14457  if (!c_indexStatAutoUpdate ||
14458  c_masterNodeId != getOwnNodeId() ||
14459  getNodeState().startLevel != NodeState::SL_STARTED) {
14460  jam();
14461  indexStatBg_sendContinueB(signal);
14462  return;
14463  }
14464 
14465  D("indexStatBg_process" << V(c_indexStatBgId));
14466  const uint maxloop = 32;
14467  uint loop;
14468  for (loop = 0; loop < maxloop; loop++, c_indexStatBgId++) {
14469  jam();
14470  c_indexStatBgId %= c_tableRecordPool.getSize();
14471 
14472  // check
14473  TableRecordPtr indexPtr;
14474  XSchemaFile* xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
14475  const SchemaFile::TableEntry* te = getTableEntry(xsf, c_indexStatBgId);
14476  if (te->m_tableState != SchemaFile::SF_IN_USE) {
14477  jam();
14478  continue;
14479  }
14480  c_tableRecordPool.getPtr(indexPtr, c_indexStatBgId);
14481  if (!indexPtr.p->isOrderedIndex()) {
14482  jam();
14483  continue;
14484  }
14485  if (indexPtr.p->indexStatBgRequest == 0) {
14486  jam();
14487  continue;
14488  }
14489  ndbrequire(indexPtr.p->indexStatBgRequest == IndexStatRep::RT_UPDATE_REQ);
14490 
14491  TxHandlePtr tx_ptr;
14492  if (!seizeTxHandle(tx_ptr)) {
14493  jam();
14494  return; // wait for one
14495  }
14496  Callback c = {
14497  safe_cast(&Dbdict::indexStatBg_fromBeginTrans),
14498  tx_ptr.p->tx_key
14499  };
14500  tx_ptr.p->m_callback = c;
14501  beginSchemaTrans(signal, tx_ptr);
14502  return;
14503  }
14504 
14505  indexStatBg_sendContinueB(signal);
14506 }
14507 
14508 void
14509 Dbdict::indexStatBg_fromBeginTrans(Signal* signal, Uint32 tx_key, Uint32 ret)
14510 {
14511  D("indexStatBg_fromBeginTrans" << V(c_indexStatBgId) << V(tx_key) << V(ret));
14512 
14513  TxHandlePtr tx_ptr;
14514  findTxHandle(tx_ptr, tx_key);
14515  ndbrequire(!tx_ptr.isNull());
14516 
14517  TableRecordPtr indexPtr;
14518  c_tableRecordPool.getPtr(indexPtr, c_indexStatBgId);
14519 
14520  if (ret != 0) {
14521  jam();
14522  indexStatBg_sendContinueB(signal);
14523  return;
14524  }
14525 
14526  Callback c = {
14527  safe_cast(&Dbdict::indexStatBg_fromIndexStat),
14528  tx_ptr.p->tx_key
14529  };
14530  tx_ptr.p->m_callback = c;
14531 
14532  IndexStatReq* req = (IndexStatReq*)signal->getDataPtrSend();
14533  req->clientRef = reference();
14534  req->clientData = tx_ptr.p->tx_key;
14535  req->transId = tx_ptr.p->m_transId;
14536  req->transKey = tx_ptr.p->m_transKey;
14537  req->requestInfo = IndexStatReq::RT_UPDATE_STAT;
14538  req->requestFlag = 0;
14539  req->indexId = c_indexStatBgId;
14540  req->indexVersion = indexPtr.p->tableVersion;
14541  req->tableId = indexPtr.p->primaryTableId;
14542  sendSignal(reference(), GSN_INDEX_STAT_REQ,
14543  signal, IndexStatReq::SignalLength, JBB);
14544 }
14545 
14546 void
14547 Dbdict::indexStatBg_fromIndexStat(Signal* signal, Uint32 tx_key, Uint32 ret)
14548 {
14549  D("indexStatBg_fromIndexStat" << V(c_indexStatBgId) << V(tx_key) << (ret));
14550 
14551  TxHandlePtr tx_ptr;
14552  findTxHandle(tx_ptr, tx_key);
14553  ndbrequire(!tx_ptr.isNull());
14554 
14555  TableRecordPtr indexPtr;
14556  c_tableRecordPool.getPtr(indexPtr, c_indexStatBgId);
14557 
14558  if (ret != 0) {
14559  jam();
14560  setError(tx_ptr.p->m_error, ret, __LINE__);
14561  warningEvent("DICT: index %u stats auto-update error: %d", indexPtr.i, ret);
14562  }
14563 
14564  Callback c = {
14565  safe_cast(&Dbdict::indexStatBg_fromEndTrans),
14566  tx_ptr.p->tx_key
14567  };
14568  tx_ptr.p->m_callback = c;
14569 
14570  Uint32 flags = 0;
14571  if (hasError(tx_ptr.p->m_error))
14572  flags |= SchemaTransEndReq::SchemaTransAbort;
14573  endSchemaTrans(signal, tx_ptr, flags);
14574 }
14575 
14576 void
14577 Dbdict::indexStatBg_fromEndTrans(Signal* signal, Uint32 tx_key, Uint32 ret)
14578 {
14579  D("indexStatBg_fromEndTrans" << V(c_indexStatBgId) << V(tx_key) << (ret));
14580 
14581  TxHandlePtr tx_ptr;
14582  findTxHandle(tx_ptr, tx_key);
14583  ndbrequire(!tx_ptr.isNull());
14584 
14585  TableRecordPtr indexPtr;
14586  c_tableRecordPool.getPtr(indexPtr, c_indexStatBgId);
14587 
14588  if (ret != 0) {
14589  jam();
14590  // skip over but leave the request on
14591  warningEvent("DICT: index %u stats auto-update error: %d", indexPtr.i, ret);
14592  } else {
14593  jam();
14594  // mark request done
14595  indexPtr.p->indexStatBgRequest = 0;
14596  infoEvent("DICT: index %u stats auto-update done", indexPtr.i);
14597  }
14598 
14599  releaseTxHandle(tx_ptr);
14600  c_indexStatBgId++;
14601  indexStatBg_sendContinueB(signal);
14602 }
14603 
14604 void
14605 Dbdict::indexStatBg_sendContinueB(Signal* signal)
14606 {
14607  D("indexStatBg_sendContinueB" << V(c_indexStatBgId));
14608  signal->theData[0] = ZINDEX_STAT_BG_PROCESS;
14609  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 1000, 1);
14610 }
14611 
14612 // IndexStat: END
14613 
14614 // MODULE: CopyData
14615 
14616 const Dbdict::OpInfo
14617 Dbdict::CopyDataRec::g_opInfo = {
14618  { 'D', 'C', 'D', 0 },
14619  GSN_COPY_DATA_IMPL_REQ,
14620  CopyDataImplReq::SignalLength,
14621 
14622  //
14623  &Dbdict::copyData_seize,
14624  &Dbdict::copyData_release,
14625  //
14626  &Dbdict::copyData_parse,
14627  &Dbdict::copyData_subOps,
14628  &Dbdict::copyData_reply,
14629  //
14630  &Dbdict::copyData_prepare,
14631  &Dbdict::copyData_commit,
14632  &Dbdict::copyData_complete,
14633  //
14634  &Dbdict::copyData_abortParse,
14635  &Dbdict::copyData_abortPrepare
14636 };
14637 
14638 bool
14639 Dbdict::copyData_seize(SchemaOpPtr op_ptr)
14640 {
14641  return seizeOpRec<CopyDataRec>(op_ptr);
14642 }
14643 
14644 void
14645 Dbdict::copyData_release(SchemaOpPtr op_ptr)
14646 {
14647  releaseOpRec<CopyDataRec>(op_ptr);
14648 }
14649 
14650 void
14651 Dbdict::execCOPY_DATA_REQ(Signal* signal)
14652 {
14653  jamEntry();
14654  if (!assembleFragments(signal)) {
14655  jam();
14656  return;
14657  }
14658  SectionHandle handle(this, signal);
14659 
14660  const CopyDataReq req_copy =
14661  *(const CopyDataReq*)signal->getDataPtr();
14662  const CopyDataReq* req = &req_copy;
14663 
14664  ErrorInfo error;
14665  do {
14666  SchemaOpPtr op_ptr;
14667  CopyDataRecPtr copyDataPtr;
14668  CopyDataImplReq* impl_req;
14669 
14670  startClientReq(op_ptr, copyDataPtr, req, impl_req, error);
14671  if (hasError(error)) {
14672  jam();
14673  break;
14674  }
14675 
14676  impl_req->srcTableId = req->srcTableId;
14677  impl_req->dstTableId = req->dstTableId;
14678  impl_req->srcFragments = req->srcFragments;
14679 
14680  handleClientReq(signal, op_ptr, handle);
14681  return;
14682  } while (0);
14683 
14684  releaseSections(handle);
14685 
14686  CopyDataRef* ref = (CopyDataRef*)signal->getDataPtrSend();
14687  ref->senderRef = reference();
14688  ref->senderData = req->clientData;
14689  ref->transId = req->transId;
14690  getError(error, ref);
14691 
14692  sendSignal(req->clientRef, GSN_COPY_DATA_REF, signal,
14693  CopyDataRef::SignalLength, JBB);
14694 }
14695 
14696 // CopyData: PARSE
14697 
14698 void
14699 Dbdict::copyData_parse(Signal* signal, bool master,
14700  SchemaOpPtr op_ptr,
14701  SectionHandle& handle, ErrorInfo& error)
14702 {
14703  D("copyData_parse");
14704 
14708 }
14709 
14710 bool
14711 Dbdict::copyData_subOps(Signal* signal, SchemaOpPtr op_ptr)
14712 {
14713  D("copyData_subOps" << V(op_ptr.i) << *op_ptr.p);
14714 
14715  return false;
14716 }
14717 
14718 void
14719 Dbdict::copyData_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
14720 {
14721  jam();
14722 
14723  SchemaTransPtr& trans_ptr = op_ptr.p->m_trans_ptr;
14724  CopyDataRecPtr copyDataPtr;
14725  getOpRec(op_ptr, copyDataPtr);
14726  //const CopyDataImplReq* impl_req = &copyDataPtr.p->m_request;
14727 
14728  if (!hasError(error)) {
14729  CopyDataConf* conf = (CopyDataConf*)signal->getDataPtrSend();
14730  conf->senderRef = reference();
14731  conf->senderData = op_ptr.p->m_clientData;
14732  conf->transId = trans_ptr.p->m_transId;
14733 
14734  Uint32 clientRef = op_ptr.p->m_clientRef;
14735  sendSignal(clientRef, GSN_COPY_DATA_CONF, signal,
14736  CopyDataConf::SignalLength, JBB);
14737  } else {
14738  jam();
14739  CopyDataRef* ref = (CopyDataRef*)signal->getDataPtrSend();
14740  ref->senderRef = reference();
14741  ref->senderData = op_ptr.p->m_clientData;
14742  ref->transId = trans_ptr.p->m_transId;
14743  getError(error, ref);
14744 
14745  Uint32 clientRef = op_ptr.p->m_clientRef;
14746  sendSignal(clientRef, GSN_COPY_DATA_REF, signal,
14747  CopyDataRef::SignalLength, JBB);
14748  }
14749 }
14750 
14751 // CopyData: PREPARE
14752 
14753 void
14754 Dbdict::copyData_prepare(Signal* signal, SchemaOpPtr op_ptr)
14755 {
14756  jam();
14757 
14758  CopyDataRecPtr copyDataPtr;
14759  getOpRec(op_ptr, copyDataPtr);
14760  const CopyDataImplReq* impl_req = &copyDataPtr.p->m_request;
14761  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
14762 
14763  CopyDataImplReq* req = (CopyDataImplReq*)signal->getDataPtrSend();
14764  * req = * impl_req;
14765  req->senderRef = reference();
14766  req->senderData = op_ptr.p->op_key;
14767  req->transId = trans_ptr.p->m_transId;
14768  req->srcFragments = 0; // All
14769 
14770  Callback c = {
14771  safe_cast(&Dbdict::copyData_fromLocal),
14772  op_ptr.p->op_key
14773  };
14774  op_ptr.p->m_callback = c;
14775 
14776  Uint32 cnt =0;
14777  Uint32 tmp[MAX_ATTRIBUTES_IN_TABLE];
14778  bool tabHasDiskCols = false;
14779  TableRecordPtr tabPtr;
14780  c_tableRecordPool.getPtr(tabPtr, impl_req->srcTableId);
14781  {
14782  LocalDLFifoList<AttributeRecord> alist(c_attributeRecordPool,
14783  tabPtr.p->m_attributes);
14784  AttributeRecordPtr attrPtr;
14785  for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr))
14786  {
14787  if (AttributeDescriptor::getPrimaryKey(attrPtr.p->attributeDescriptor))
14788  tmp[cnt++] = attrPtr.p->attributeId;
14789  }
14790  for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr))
14791  {
14792  if (!AttributeDescriptor::getPrimaryKey(attrPtr.p->attributeDescriptor))
14793  {
14794  tmp[cnt++] = attrPtr.p->attributeId;
14795 
14796  if (AttributeDescriptor::getDiskBased(attrPtr.p->attributeDescriptor))
14797  tabHasDiskCols = true;
14798  }
14799  }
14800  }
14801 
14802  /* Request Tup-ordered copy when we have disk columns for efficiency */
14803  if (tabHasDiskCols)
14804  {
14805  jam();
14806  req->requestInfo |= CopyDataReq::TupOrder;
14807  }
14808 
14809  LinearSectionPtr ls_ptr[3];
14810  ls_ptr[0].sz = cnt;
14811  ls_ptr[0].p = tmp;
14812 
14813  sendSignal(TRIX_REF, GSN_COPY_DATA_IMPL_REQ, signal,
14814  CopyDataImplReq::SignalLength, JBB, ls_ptr, 1);
14815 }
14816 
14817 void
14818 Dbdict::copyData_fromLocal(Signal* signal, Uint32 op_key, Uint32 ret)
14819 {
14820  SchemaOpPtr op_ptr;
14821  CopyDataRecPtr copyDataPtr;
14822  findSchemaOp(op_ptr, copyDataPtr, op_key);
14823  ndbrequire(!op_ptr.isNull());
14824 
14825  if (ERROR_INSERTED(6214))
14826  {
14827  CLEAR_ERROR_INSERT_VALUE;
14828  ret = 1;
14829  }
14830 
14831  if (ret == 0) {
14832  jam();
14833  sendTransConf(signal, op_ptr);
14834  } else {
14835  jam();
14836  setError(op_ptr, ret, __LINE__);
14837  sendTransRef(signal, op_ptr);
14838  }
14839 }
14840 
14841 
14842 // CopyData: COMMIT
14843 
14844 void
14845 Dbdict::copyData_commit(Signal* signal, SchemaOpPtr op_ptr)
14846 {
14847  jam();
14848 
14849  sendTransConf(signal, op_ptr);
14850 }
14851 
14852 // CopyData: COMPLETE
14853 
14854 void
14855 Dbdict::copyData_complete(Signal* signal, SchemaOpPtr op_ptr)
14856 {
14857  jam();
14858 
14859  CopyDataRecPtr copyDataPtr;
14860  getOpRec(op_ptr, copyDataPtr);
14861  const CopyDataImplReq* impl_req = &copyDataPtr.p->m_request;
14862  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
14863 
14864  CopyDataImplReq* req = (CopyDataImplReq*)signal->getDataPtrSend();
14865  * req = * impl_req;
14866  req->senderRef = reference();
14867  req->senderData = op_ptr.p->op_key;
14868  req->transId = trans_ptr.p->m_transId;
14869  req->requestType = CopyDataImplReq::ReorgDelete;
14870 
14871  Callback c = {
14872  safe_cast(&Dbdict::copyData_fromLocal),
14873  op_ptr.p->op_key
14874  };
14875  op_ptr.p->m_callback = c;
14876 
14877  Uint32 cnt =0;
14878  Uint32 tmp[MAX_ATTRIBUTES_IN_TABLE];
14879  bool tabHasDiskCols = false;
14880  TableRecordPtr tabPtr;
14881  c_tableRecordPool.getPtr(tabPtr, impl_req->srcTableId);
14882  {
14883  LocalDLFifoList<AttributeRecord> alist(c_attributeRecordPool,
14884  tabPtr.p->m_attributes);
14885  AttributeRecordPtr attrPtr;
14886  for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr))
14887  {
14888  if (AttributeDescriptor::getPrimaryKey(attrPtr.p->attributeDescriptor))
14889  tmp[cnt++] = attrPtr.p->attributeId;
14890  else
14891  {
14892  if (AttributeDescriptor::getDiskBased(attrPtr.p->attributeDescriptor))
14893  tabHasDiskCols = true;
14894  }
14895  }
14896  }
14897 
14898  /* Request Tup-ordered delete when we have disk columns for efficiency */
14899  if (tabHasDiskCols)
14900  {
14901  jam();
14902  req->requestInfo |= CopyDataReq::TupOrder;
14903  }
14904 
14905  LinearSectionPtr ls_ptr[3];
14906  ls_ptr[0].sz = cnt;
14907  ls_ptr[0].p = tmp;
14908 
14909  sendSignal(TRIX_REF, GSN_COPY_DATA_IMPL_REQ, signal,
14910  CopyDataImplReq::SignalLength, JBB, ls_ptr, 1);
14911 }
14912 
14913 // CopyData: ABORT
14914 
14915 void
14916 Dbdict::copyData_abortParse(Signal* signal, SchemaOpPtr op_ptr)
14917 {
14918  D("copyData_abortParse" << *op_ptr.p);
14919  // wl3600_todo
14920  sendTransConf(signal, op_ptr);
14921 }
14922 
14923 void
14924 Dbdict::copyData_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
14925 {
14926  D("copyData_abortPrepare" << *op_ptr.p);
14927 
14928  // nothing to do, entire index table will be dropped
14929  sendTransConf(signal, op_ptr);
14930 }
14931 
14932 void
14933 Dbdict::execCOPY_DATA_CONF(Signal* signal)
14934 {
14935  jamEntry();
14936  const CopyDataConf* conf = (const CopyDataConf*)signal->getDataPtr();
14937  handleDictConf(signal, conf);
14938 }
14939 
14940 void
14941 Dbdict::execCOPY_DATA_REF(Signal* signal)
14942 {
14943  jamEntry();
14944  const CopyDataRef* ref = (const CopyDataRef*)signal->getDataPtr();
14945  handleDictRef(signal, ref);
14946 }
14947 
14948 void
14949 Dbdict::execCOPY_DATA_IMPL_CONF(Signal* signal)
14950 {
14951  jamEntry();
14952  const CopyDataImplConf* conf = (const CopyDataImplConf*)signal->getDataPtr();
14953  ndbrequire(refToNode(conf->senderRef) == getOwnNodeId());
14954  handleDictConf(signal, conf);
14955 }
14956 
14957 void
14958 Dbdict::execCOPY_DATA_IMPL_REF(Signal* signal)
14959 {
14960  jamEntry();
14961  const CopyDataImplRef* ref = (const CopyDataImplRef*)signal->getDataPtr();
14962  ndbrequire(refToNode(ref->senderRef) == getOwnNodeId());
14963  handleDictRef(signal, ref);
14964 }
14965 
14966 
14967 // CopyData: END
14968 
14969 
14970 /*****************************************************
14971  *
14972  * MODULE: Util signalling
14973  *
14974  *****************************************************/
14975 
14976 int
14977 Dbdict::sendSignalUtilReq(Callback *pcallback,
14978  BlockReference ref,
14979  GlobalSignalNumber gsn,
14980  Signal* signal,
14981  Uint32 length,
14982  JobBufferLevel jbuf,
14983  LinearSectionPtr ptr[3],
14984  Uint32 noOfSections)
14985 {
14986  jam();
14987  EVENT_TRACE;
14988  OpSignalUtilPtr utilRecPtr;
14989 
14990  // Seize a Util Send record
14991  if (!c_opSignalUtil.seize(utilRecPtr)) {
14992  // Failed to allocate util record
14993  return -1;
14994  }
14995  utilRecPtr.p->m_callback = *pcallback;
14996 
14997  // should work for all util signal classes
14998  UtilPrepareReq *req = (UtilPrepareReq*)signal->getDataPtrSend();
14999  utilRecPtr.p->m_userData = req->getSenderData();
15000  req->setSenderData(utilRecPtr.i);
15001 
15002  if (ptr) {
15003  jam();
15004  sendSignal(ref, gsn, signal, length, jbuf, ptr, noOfSections);
15005  } else {
15006  jam();
15007  sendSignal(ref, gsn, signal, length, jbuf);
15008  }
15009 
15010  return 0;
15011 }
15012 
15013 int
15014 Dbdict::recvSignalUtilReq(Signal* signal, Uint32 returnCode)
15015 {
15016  jam();
15017  EVENT_TRACE;
15018  UtilPrepareConf * const req = (UtilPrepareConf*)signal->getDataPtr();
15019  OpSignalUtilPtr utilRecPtr;
15020  utilRecPtr.i = req->getSenderData();
15021  if ((utilRecPtr.p = c_opSignalUtil.getPtr(utilRecPtr.i)) == NULL) {
15022  jam();
15023  return -1;
15024  }
15025 
15026  req->setSenderData(utilRecPtr.p->m_userData);
15027  Callback c = utilRecPtr.p->m_callback;
15028  c_opSignalUtil.release(utilRecPtr);
15029 
15030  execute(signal, c, returnCode);
15031  return 0;
15032 }
15033 
15034 void Dbdict::execUTIL_PREPARE_CONF(Signal *signal)
15035 {
15036  jamEntry();
15037  EVENT_TRACE;
15038  ndbrequire(recvSignalUtilReq(signal, 0) == 0);
15039 }
15040 
15041 void
15042 Dbdict::execUTIL_PREPARE_REF(Signal *signal)
15043 {
15044  jamEntry();
15045  const UtilPrepareRef * ref = CAST_CONSTPTR(UtilPrepareRef,
15046  signal->getDataPtr());
15047  Uint32 code = ref->errorCode;
15048  if (code == UtilPrepareRef::DICT_TAB_INFO_ERROR)
15049  code = ref->dictErrCode;
15050  EVENT_TRACE;
15051  ndbrequire(recvSignalUtilReq(signal, code) == 0);
15052 }
15053 
15054 void Dbdict::execUTIL_EXECUTE_CONF(Signal *signal)
15055 {
15056  jamEntry();
15057  EVENT_TRACE;
15058  ndbrequire(recvSignalUtilReq(signal, 0) == 0);
15059 }
15060 
15061 void Dbdict::execUTIL_EXECUTE_REF(Signal *signal)
15062 {
15063  jamEntry();
15064  EVENT_TRACE;
15065 
15066 #ifdef EVENT_DEBUG
15067  UtilExecuteRef * ref = (UtilExecuteRef *)signal->getDataPtrSend();
15068 
15069  ndbout_c("execUTIL_EXECUTE_REF");
15070  ndbout_c("senderData %u",ref->getSenderData());
15071  ndbout_c("errorCode %u",ref->getErrorCode());
15072  ndbout_c("TCErrorCode %u",ref->getTCErrorCode());
15073 #endif
15074 
15075  ndbrequire(recvSignalUtilReq(signal, 1) == 0);
15076 }
15077 void Dbdict::execUTIL_RELEASE_CONF(Signal *signal)
15078 {
15079  jamEntry();
15080  EVENT_TRACE;
15081  ndbrequire(false);
15082  ndbrequire(recvSignalUtilReq(signal, 0) == 0);
15083 }
15084 void Dbdict::execUTIL_RELEASE_REF(Signal *signal)
15085 {
15086  jamEntry();
15087  EVENT_TRACE;
15088  ndbrequire(false);
15089  ndbrequire(recvSignalUtilReq(signal, 1) == 0);
15090 }
15091 
15104 /*****************************************************************
15105  *
15106  * Systable stuff
15107  *
15108  */
15109 
15110 static const
15111 Uint32
15112 sysTab_NDBEVENTS_0_szs[] =
15113 {
15114  sizeof(((sysTab_NDBEVENTS_0*)0)->NAME),
15115  sizeof(((sysTab_NDBEVENTS_0*)0)->EVENT_TYPE),
15116  sizeof(((sysTab_NDBEVENTS_0*)0)->TABLEID),
15117  sizeof(((sysTab_NDBEVENTS_0*)0)->TABLEVERSION),
15118  sizeof(((sysTab_NDBEVENTS_0*)0)->TABLE_NAME),
15119  sizeof(((sysTab_NDBEVENTS_0*)0)->ATTRIBUTE_MASK),
15120  sizeof(((sysTab_NDBEVENTS_0*)0)->SUBID),
15121  sizeof(((sysTab_NDBEVENTS_0*)0)->SUBKEY),
15122  sizeof(((sysTab_NDBEVENTS_0*)0)->ATTRIBUTE_MASK2)
15123 };
15124 
15125 static const
15126 UintPtr
15127 sysTab_NDBEVENTS_0_offsets[] =
15128 {
15129  (UintPtr)&(((sysTab_NDBEVENTS_0*)0)->NAME),
15130  (UintPtr)&(((sysTab_NDBEVENTS_0*)0)->EVENT_TYPE),
15131  (UintPtr)&(((sysTab_NDBEVENTS_0*)0)->TABLEID),
15132  (UintPtr)&(((sysTab_NDBEVENTS_0*)0)->TABLEVERSION),
15133  (UintPtr)&(((sysTab_NDBEVENTS_0*)0)->TABLE_NAME),
15134  (UintPtr)&(((sysTab_NDBEVENTS_0*)0)->ATTRIBUTE_MASK),
15135  (UintPtr)&(((sysTab_NDBEVENTS_0*)0)->SUBID),
15136  (UintPtr)&(((sysTab_NDBEVENTS_0*)0)->SUBKEY),
15137  (UintPtr)&(((sysTab_NDBEVENTS_0*)0)->ATTRIBUTE_MASK2)
15138 };
15139 
15140 void
15141 Dbdict::prepareTransactionEventSysTable (Callback *pcallback,
15142  Signal* signal,
15143  Uint32 senderData,
15144  UtilPrepareReq::OperationTypeValue prepReq)
15145 {
15146  // find table id for event system table
15147  DictObject * opj_ptr_p = get_object(EVENT_SYSTEM_TABLE_NAME,
15148  sizeof(EVENT_SYSTEM_TABLE_NAME));
15149 
15150  ndbrequire(opj_ptr_p != 0);
15151  TableRecordPtr tablePtr;
15152  c_tableRecordPool.getPtr(tablePtr, opj_ptr_p->m_id);
15153  ndbrequire(tablePtr.i != RNIL); // system table must exist
15154 
15155  Uint32 tableId = tablePtr.p->tableId; /* System table */
15156  Uint32 noAttr = tablePtr.p->noOfAttributes;
15157  if (noAttr > EVENT_SYSTEM_TABLE_LENGTH)
15158  {
15159  jam();
15160  noAttr = EVENT_SYSTEM_TABLE_LENGTH;
15161  }
15162 
15163  switch (prepReq) {
15164  case UtilPrepareReq::Update:
15165  case UtilPrepareReq::Insert:
15166  case UtilPrepareReq::Write:
15167  case UtilPrepareReq::Read:
15168  jam();
15169  break;
15170  case UtilPrepareReq::Delete:
15171  jam();
15172  noAttr = 1; // only involves Primary key which should be the first
15173  break;
15174  }
15175  prepareUtilTransaction(pcallback, signal, senderData, tableId, NULL,
15176  prepReq, noAttr, NULL, NULL);
15177 }
15178 
15179 void
15180 Dbdict::prepareUtilTransaction(Callback *pcallback,
15181  Signal* signal,
15182  Uint32 senderData,
15183  Uint32 tableId,
15184  const char* tableName,
15185  UtilPrepareReq::OperationTypeValue prepReq,
15186  Uint32 noAttr,
15187  Uint32 attrIds[],
15188  const char *attrNames[])
15189 {
15190  jam();
15191  EVENT_TRACE;
15192 
15193  UtilPrepareReq * utilPrepareReq =
15194  (UtilPrepareReq *)signal->getDataPtrSend();
15195 
15196  utilPrepareReq->setSenderRef(reference());
15197  utilPrepareReq->setSenderData(senderData);
15198 
15199  const Uint32 pageSizeInWords = 128;
15200  Uint32 propPage[pageSizeInWords];
15201  LinearWriter w(&propPage[0],128);
15202  w.first();
15204  w.add(UtilPrepareReq::OperationType, prepReq);
15205  if (tableName) {
15206  jam();
15207  w.add(UtilPrepareReq::TableName, tableName);
15208  } else {
15209  jam();
15210  w.add(UtilPrepareReq::TableId, tableId);
15211  }
15212  for(Uint32 i = 0; i < noAttr; i++)
15213  if (tableName) {
15214  jam();
15215  w.add(UtilPrepareReq::AttributeName, attrNames[i]);
15216  } else {
15217  if (attrIds) {
15218  jam();
15219  w.add(UtilPrepareReq::AttributeId, attrIds[i]);
15220  } else {
15221  jam();
15222  w.add(UtilPrepareReq::AttributeId, i);
15223  }
15224  }
15225 #ifdef EVENT_DEBUG
15226  // Debugging
15227  SimplePropertiesLinearReader reader(propPage, w.getWordsUsed());
15228  printf("Dict::prepareInsertTransactions: Sent SimpleProperties:\n");
15229  reader.printAll(ndbout);
15230 #endif
15231 
15232  struct LinearSectionPtr sectionsPtr[UtilPrepareReq::NoOfSections];
15233  sectionsPtr[UtilPrepareReq::PROPERTIES_SECTION].p = propPage;
15234  sectionsPtr[UtilPrepareReq::PROPERTIES_SECTION].sz = w.getWordsUsed();
15235 
15236  sendSignalUtilReq(pcallback, DBUTIL_REF, GSN_UTIL_PREPARE_REQ, signal,
15237  UtilPrepareReq::SignalLength, JBB,
15238  sectionsPtr, UtilPrepareReq::NoOfSections);
15239 }
15240 
15241 /*****************************************************************
15242  *
15243  * CREATE_EVNT_REQ has three types RT_CREATE, RT_GET (from user)
15244  * and RT_DICT_AFTER_GET send from master DICT to slaves
15245  *
15246  * This function just dscpaches these to
15247  *
15248  * createEvent_RT_USER_CREATE
15249  * createEvent_RT_USER_GET
15250  * createEvent_RT_DICT_AFTER_GET
15251  *
15252  * repectively
15253  *
15254  */
15255 
15256 void
15257 Dbdict::execCREATE_EVNT_REQ(Signal* signal)
15258 {
15259  jamEntry();
15260 
15261 #if 0
15262  {
15263  SafeCounterHandle handle;
15264  {
15265  SafeCounter tmp(c_counterMgr, handle);
15266  tmp.init<CreateEvntRef>(CMVMI, GSN_DUMP_STATE_ORD, /* senderData */ 13);
15267  tmp.clearWaitingFor();
15268  tmp.setWaitingFor(3);
15269  ndbrequire(!tmp.done());
15270  ndbout_c("Allocted");
15271  }
15272  ndbrequire(!handle.done());
15273  {
15274  SafeCounter tmp(c_counterMgr, handle);
15275  tmp.clearWaitingFor(3);
15276  ndbrequire(tmp.done());
15277  ndbout_c("Deallocted");
15278  }
15279  ndbrequire(handle.done());
15280  }
15281  {
15282  NodeBitmask nodes;
15283  nodes.clear();
15284 
15285  nodes.set(2);
15286  nodes.set(3);
15287  nodes.set(4);
15288  nodes.set(5);
15289 
15290  {
15291  Uint32 i = 0;
15292  while((i = nodes.find(i)) != NodeBitmask::NotFound){
15293  ndbout_c("1 Node id = %u", i);
15294  i++;
15295  }
15296  }
15297 
15298  NodeReceiverGroup rg(DBDICT, nodes);
15299  RequestTracker rt2;
15300  ndbrequire(rt2.done());
15301  ndbrequire(!rt2.hasRef());
15302  ndbrequire(!rt2.hasConf());
15303  rt2.init<CreateEvntRef>(c_counterMgr, rg, GSN_CREATE_EVNT_REF, 13);
15304 
15305  RequestTracker rt3;
15306  rt3.init<CreateEvntRef>(c_counterMgr, rg, GSN_CREATE_EVNT_REF, 13);
15307 
15308  ndbrequire(!rt2.done());
15309  ndbrequire(!rt3.done());
15310 
15311  rt2.reportRef(c_counterMgr, 2);
15312  rt3.reportConf(c_counterMgr, 2);
15313 
15314  ndbrequire(!rt2.done());
15315  ndbrequire(!rt3.done());
15316 
15317  rt2.reportConf(c_counterMgr, 3);
15318  rt3.reportConf(c_counterMgr, 3);
15319 
15320  ndbrequire(!rt2.done());
15321  ndbrequire(!rt3.done());
15322 
15323  rt2.reportConf(c_counterMgr, 4);
15324  rt3.reportConf(c_counterMgr, 4);
15325 
15326  ndbrequire(!rt2.done());
15327  ndbrequire(!rt3.done());
15328 
15329  rt2.reportConf(c_counterMgr, 5);
15330  rt3.reportConf(c_counterMgr, 5);
15331 
15332  ndbrequire(rt2.done());
15333  ndbrequire(rt3.done());
15334  }
15335 #endif
15336 
15337  CreateEvntReq *req = (CreateEvntReq*)signal->getDataPtr();
15338 
15339  if (! assembleFragments(signal)) {
15340  jam();
15341  return;
15342  }
15343 
15344  const CreateEvntReq::RequestType requestType = req->getRequestType();
15345  const Uint32 requestFlag = req->getRequestFlag();
15346  SectionHandle handle(this, signal);
15347 
15348  if (refToBlock(signal->senderBlockRef()) != DBDICT &&
15349  getOwnNodeId() != c_masterNodeId)
15350  {
15351  jam();
15352  releaseSections(handle);
15353 
15354  CreateEvntRef * ref = (CreateEvntRef *)signal->getDataPtrSend();
15355  ref->setUserRef(reference());
15356  ref->setErrorCode(CreateEvntRef::NotMaster);
15357  ref->setErrorLine(__LINE__);
15358  ref->setErrorNode(reference());
15359  ref->setMasterNode(c_masterNodeId);
15360  sendSignal(signal->senderBlockRef(), GSN_CREATE_EVNT_REF, signal,
15361  CreateEvntRef::SignalLength2, JBB);
15362  return;
15363  }
15364 
15365  OpCreateEventPtr evntRecPtr;
15366  // Seize a Create Event record
15367  if (!c_opCreateEvent.seize(evntRecPtr)) {
15368  // Failed to allocate event record
15369  jam();
15370  releaseSections(handle);
15371 
15372  CreateEvntRef * ret = (CreateEvntRef *)signal->getDataPtrSend();
15373  ret->senderRef = reference();
15374  ret->setErrorCode(747);
15375  ret->setErrorLine(__LINE__);
15376  ret->setErrorNode(reference());
15377  sendSignal(signal->senderBlockRef(), GSN_CREATE_EVNT_REF, signal,
15378  CreateEvntRef::SignalLength, JBB);
15379  return;
15380  }
15381 
15382 #ifdef EVENT_DEBUG
15383  ndbout_c("DBDICT::execCREATE_EVNT_REQ from %u evntRecId = (%d)", refToNode(signal->getSendersBlockRef()), evntRecPtr.i);
15384 #endif
15385 
15386  ndbrequire(req->getUserRef() == signal->getSendersBlockRef());
15387 
15388  evntRecPtr.p->init(req,this);
15389 
15390  if (requestFlag & (Uint32)CreateEvntReq::RT_DICT_AFTER_GET) {
15391  jam();
15392  EVENT_TRACE;
15393  releaseSections(handle);
15394 
15395  if (ERROR_INSERTED(6023))
15396  {
15397  jam();
15398  signal->theData[0] = 9999;
15399  sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 1000, 1);
15400  return;
15401  }
15402 
15403  createEvent_RT_DICT_AFTER_GET(signal, evntRecPtr);
15404  return;
15405  }
15406  if (requestType == CreateEvntReq::RT_USER_GET) {
15407  jam();
15408  EVENT_TRACE;
15409  createEvent_RT_USER_GET(signal, evntRecPtr, handle);
15410  return;
15411  }
15412  if (requestType == CreateEvntReq::RT_USER_CREATE) {
15413  jam();
15414  EVENT_TRACE;
15415  createEvent_RT_USER_CREATE(signal, evntRecPtr, handle);
15416  return;
15417  }
15418 
15419 #ifdef EVENT_DEBUG
15420  ndbout << "Dbdict.cpp: Dbdict::execCREATE_EVNT_REQ other" << endl;
15421 #endif
15422  jam();
15423  releaseSections(handle);
15424 
15425  evntRecPtr.p->m_errorCode = 1;
15426  evntRecPtr.p->m_errorLine = __LINE__;
15427  evntRecPtr.p->m_errorNode = reference();
15428 
15429  createEvent_sendReply(signal, evntRecPtr);
15430 }
15431 
15432 /********************************************************************
15433  *
15434  * Event creation
15435  *
15436  *****************************************************************/
15437 
15438 void
15439 Dbdict::createEvent_RT_USER_CREATE(Signal* signal,
15440  OpCreateEventPtr evntRecPtr,
15441  SectionHandle& handle)
15442 {
15443  jam();
15444  DBUG_ENTER("Dbdict::createEvent_RT_USER_CREATE");
15445  evntRecPtr.p->m_request.setUserRef(signal->senderBlockRef());
15446 
15447 #ifdef EVENT_DEBUG
15448  ndbout << "Dbdict.cpp: Dbdict::execCREATE_EVNT_REQ RT_USER" << endl;
15449  char buf[128] = {0};
15450  AttributeMask mask = evntRecPtr.p->m_request.getAttrListBitmask();
15451  mask.getText(buf);
15452  ndbout_c("mask = %s", buf);
15453 #endif
15454 
15455  // Interpret the long signal
15456 
15457  SegmentedSectionPtr ssPtr;
15458  // save name and event properties
15459  ndbrequire(handle.getSection(ssPtr, CreateEvntReq::EVENT_NAME_SECTION));
15460 
15461  SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
15462 #ifdef EVENT_DEBUG
15463  r0.printAll(ndbout);
15464 #endif
15465  // event name
15466  if ((!r0.first()) ||
15467  (r0.getValueType() != SimpleProperties::StringValue) ||
15468  (r0.getValueLen() <= 0)) {
15469  jam();
15470  releaseSections(handle);
15471 
15472  evntRecPtr.p->m_errorCode = 1;
15473  evntRecPtr.p->m_errorLine = __LINE__;
15474  evntRecPtr.p->m_errorNode = reference();
15475 
15476  createEvent_sendReply(signal, evntRecPtr);
15477  DBUG_VOID_RETURN;
15478  }
15479  r0.getString(evntRecPtr.p->m_eventRec.NAME);
15480  {
15481  int len = strlen(evntRecPtr.p->m_eventRec.NAME);
15482  memset(evntRecPtr.p->m_eventRec.NAME+len, 0, MAX_TAB_NAME_SIZE-len);
15483 #ifdef EVENT_DEBUG
15484  printf("CreateEvntReq::RT_USER_CREATE; EventName %s, len %u\n",
15485  evntRecPtr.p->m_eventRec.NAME, len);
15486  for(int i = 0; i < MAX_TAB_NAME_SIZE/4; i++)
15487  printf("H'%.8x ", ((Uint32*)evntRecPtr.p->m_eventRec.NAME)[i]);
15488  printf("\n");
15489 #endif
15490  }
15491  // table name
15492  if ((!r0.next()) ||
15493  (r0.getValueType() != SimpleProperties::StringValue) ||
15494  (r0.getValueLen() <= 0)) {
15495  jam();
15496 
15497  evntRecPtr.p->m_errorCode = 1;
15498 sendref:
15499  evntRecPtr.p->m_errorLine = __LINE__;
15500  evntRecPtr.p->m_errorNode = reference();
15501 
15502  releaseSections(handle);
15503 
15504  createEvent_sendReply(signal, evntRecPtr);
15505  DBUG_VOID_RETURN;
15506  }
15507  r0.getString(evntRecPtr.p->m_eventRec.TABLE_NAME);
15508  {
15509  int len = strlen(evntRecPtr.p->m_eventRec.TABLE_NAME);
15510  memset(evntRecPtr.p->m_eventRec.TABLE_NAME+len, 0, MAX_TAB_NAME_SIZE-len);
15511  }
15512 
15513  if (handle.m_cnt >= CreateEvntReq::ATTRIBUTE_MASK)
15514  {
15515  jam();
15516  handle.getSection(ssPtr, CreateEvntReq::ATTRIBUTE_MASK);
15517  if (ssPtr.sz >= NDB_ARRAY_SIZE(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2))
15518  {
15519  jam();
15520  evntRecPtr.p->m_errorCode = 1;
15521  goto sendref;
15522  }
15523  bzero(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2,
15524  sizeof(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2));
15525  copy(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2, ssPtr);
15526  memcpy(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK,
15527  evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2,
15528  sizeof(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK));
15529  }
15530  else
15531  {
15532  jam();
15533  AttributeMask_OLD m = evntRecPtr.p->m_request.getAttrListBitmask();
15534  Uint32 sz0 = m.getSizeInWords();
15535  Uint32 sz1 = NDB_ARRAY_SIZE(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK);
15536  ndbrequire(sz1 == sz0);
15537  bzero(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK,
15538  sizeof(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK));
15539  bzero(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2,
15540  sizeof(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2));
15541  BitmaskImpl::assign(sz0, evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK,
15542  m.rep.data);
15543  BitmaskImpl::assign(sz0, evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2,
15544  m.rep.data);
15545  }
15546 
15547  releaseSections(handle);
15548 
15549  // Send request to SUMA
15550 
15551  CreateSubscriptionIdReq * sumaIdReq =
15552  (CreateSubscriptionIdReq *)signal->getDataPtrSend();
15553 
15554  // make sure we save the original sender for later
15555  sumaIdReq->senderRef = reference();
15556  sumaIdReq->senderData = evntRecPtr.i;
15557 #ifdef EVENT_DEBUG
15558  ndbout << "sumaIdReq->senderData = " << sumaIdReq->senderData << endl;
15559 #endif
15560  sendSignal(SUMA_REF, GSN_CREATE_SUBID_REQ, signal,
15561  CreateSubscriptionIdReq::SignalLength, JBB);
15562  // we should now return in either execCREATE_SUBID_CONF
15563  // or execCREATE_SUBID_REF
15564  DBUG_VOID_RETURN;
15565 }
15566 
15567 void Dbdict::execCREATE_SUBID_REF(Signal* signal)
15568 {
15569  jamEntry();
15570  DBUG_ENTER("Dbdict::execCREATE_SUBID_REF");
15571  CreateSubscriptionIdRef * const ref =
15572  (CreateSubscriptionIdRef *)signal->getDataPtr();
15573  OpCreateEventPtr evntRecPtr;
15574 
15575  evntRecPtr.i = ref->senderData;
15576  ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
15577 
15578  if (ref->errorCode)
15579  {
15580  evntRecPtr.p->m_errorCode = ref->errorCode;
15581  evntRecPtr.p->m_errorLine = __LINE__;
15582  }
15583  else
15584  {
15585  evntRecPtr.p->m_errorCode = 1;
15586  evntRecPtr.p->m_errorLine = __LINE__;
15587  }
15588  evntRecPtr.p->m_errorNode = reference();
15589 
15590  createEvent_sendReply(signal, evntRecPtr);
15591  DBUG_VOID_RETURN;
15592 }
15593 
15594 void Dbdict::execCREATE_SUBID_CONF(Signal* signal)
15595 {
15596  jamEntry();
15597  DBUG_ENTER("Dbdict::execCREATE_SUBID_CONF");
15598 
15599  CreateSubscriptionIdConf const * sumaIdConf =
15600  (CreateSubscriptionIdConf *)signal->getDataPtr();
15601 
15602  Uint32 evntRecId = sumaIdConf->senderData;
15603  OpCreateEvent *evntRec;
15604 
15605  ndbrequire((evntRec = c_opCreateEvent.getPtr(evntRecId)) != NULL);
15606 
15607  evntRec->m_request.setEventId(sumaIdConf->subscriptionId);
15608  evntRec->m_request.setEventKey(sumaIdConf->subscriptionKey);
15609 
15610  Callback c = { safe_cast(&Dbdict::createEventUTIL_PREPARE), 0 };
15611 
15612  prepareTransactionEventSysTable(&c, signal, evntRecId,
15613  UtilPrepareReq::Insert);
15614  DBUG_VOID_RETURN;
15615 }
15616 
15617 void
15618 Dbdict::createEventComplete_RT_USER_CREATE(Signal* signal,
15619  OpCreateEventPtr evntRecPtr){
15620  jam();
15621  createEvent_sendReply(signal, evntRecPtr);
15622 }
15623 
15624 /*********************************************************************
15625  *
15626  * UTIL_PREPARE, UTIL_EXECUTE
15627  *
15628  * insert or read systable NDB$EVENTS_0
15629  */
15630 
15631 void interpretUtilPrepareErrorCode(UtilPrepareRef::ErrorCode errorCode,
15632  Uint32& error, Uint32& line,
15633  const Dbdict *dict)
15634 {
15635  DBUG_ENTER("interpretUtilPrepareErrorCode");
15636  switch (errorCode) {
15637  case UtilPrepareRef::NO_ERROR:
15638  jamBlock(dict);
15639  error = 1;
15640  line = __LINE__;
15641  DBUG_VOID_RETURN;
15642  case UtilPrepareRef::PREPARE_SEIZE_ERROR:
15643  jamBlock(dict);
15644  error = 748;
15645  line = __LINE__;
15646  DBUG_VOID_RETURN;
15647  case UtilPrepareRef::PREPARE_PAGES_SEIZE_ERROR:
15648  jamBlock(dict);
15649  error = 748;
15650  line = __LINE__;
15651  DBUG_VOID_RETURN;
15652  case UtilPrepareRef::PREPARED_OPERATION_SEIZE_ERROR:
15653  jamBlock(dict);
15654  error = 748;
15655  line = __LINE__;
15656  DBUG_VOID_RETURN;
15657  case UtilPrepareRef::DICT_TAB_INFO_ERROR:
15658  jamBlock(dict);
15659  error = 748;
15660  line = __LINE__;
15661  DBUG_VOID_RETURN;
15662  case UtilPrepareRef::MISSING_PROPERTIES_SECTION:
15663  jamBlock(dict);
15664  error = 1;
15665  line = __LINE__;
15666  DBUG_VOID_RETURN;
15667  default:
15668  jamBlock(dict);
15669  error = 1;
15670  line = __LINE__;
15671  DBUG_VOID_RETURN;
15672  }
15673  DBUG_VOID_RETURN;
15674 }
15675 
15676 void
15677 Dbdict::createEventUTIL_PREPARE(Signal* signal,
15678  Uint32 callbackData,
15679  Uint32 returnCode)
15680 {
15681  jam();
15682  EVENT_TRACE;
15683  if (returnCode == 0) {
15684  UtilPrepareConf* const req = (UtilPrepareConf*)signal->getDataPtr();
15685  OpCreateEventPtr evntRecPtr;
15686  jam();
15687  evntRecPtr.i = req->getSenderData();
15688  const Uint32 prepareId = req->getPrepareId();
15689 
15690  ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
15691 
15692  Callback c = { safe_cast(&Dbdict::createEventUTIL_EXECUTE), 0 };
15693 
15694  switch (evntRecPtr.p->m_requestType) {
15695  case CreateEvntReq::RT_USER_GET:
15696  jam();
15697  executeTransEventSysTable(&c, signal,
15698  evntRecPtr.i, evntRecPtr.p->m_eventRec,
15699  prepareId, UtilPrepareReq::Read);
15700  break;
15701  case CreateEvntReq::RT_USER_CREATE:
15702  {
15703  evntRecPtr.p->m_eventRec.EVENT_TYPE =
15704  evntRecPtr.p->m_request.getEventType() | evntRecPtr.p->m_request.getReportFlags();
15705  evntRecPtr.p->m_eventRec.TABLEID = evntRecPtr.p->m_request.getTableId();
15706  evntRecPtr.p->m_eventRec.TABLEVERSION=evntRecPtr.p->m_request.getTableVersion();
15707  evntRecPtr.p->m_eventRec.SUBID = evntRecPtr.p->m_request.getEventId();
15708  evntRecPtr.p->m_eventRec.SUBKEY = evntRecPtr.p->m_request.getEventKey();
15709  DBUG_PRINT("info",
15710  ("CREATE: event name: %s table name: %s table id: %u table version: %u",
15711  evntRecPtr.p->m_eventRec.NAME,
15712  evntRecPtr.p->m_eventRec.TABLE_NAME,
15713  evntRecPtr.p->m_eventRec.TABLEID,
15714  evntRecPtr.p->m_eventRec.TABLEVERSION));
15715 
15716  }
15717  jam();
15718  executeTransEventSysTable(&c, signal,
15719  evntRecPtr.i, evntRecPtr.p->m_eventRec,
15720  prepareId, UtilPrepareReq::Insert);
15721  break;
15722  default:
15723 #ifdef EVENT_DEBUG
15724  printf("type = %d\n", evntRecPtr.p->m_requestType);
15725  printf("bet type = %d\n", CreateEvntReq::RT_USER_GET);
15726  printf("create type = %d\n", CreateEvntReq::RT_USER_CREATE);
15727 #endif
15728  ndbrequire(false);
15729  }
15730  } else { // returnCode != 0
15731  UtilPrepareRef* const ref = (UtilPrepareRef*)signal->getDataPtr();
15732 
15733  const UtilPrepareRef::ErrorCode errorCode =
15734  (UtilPrepareRef::ErrorCode)ref->getErrorCode();
15735 
15736  OpCreateEventPtr evntRecPtr;
15737  evntRecPtr.i = ref->getSenderData();
15738  ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
15739 
15740  interpretUtilPrepareErrorCode(errorCode, evntRecPtr.p->m_errorCode,
15741  evntRecPtr.p->m_errorLine, this);
15742  evntRecPtr.p->m_errorNode = reference();
15743 
15744  createEvent_sendReply(signal, evntRecPtr);
15745  }
15746 }
15747 
15748 static
15749 Uint32
15750 countPrefixBytes(Uint32 len, const Uint8 * mask)
15751 {
15752  while (len && mask[len - 1] == 0)
15753  len--;
15754  return len;
15755 }
15756 
15757 void Dbdict::executeTransEventSysTable(Callback *pcallback, Signal *signal,
15758  const Uint32 ptrI,
15759  sysTab_NDBEVENTS_0& m_eventRec,
15760  const Uint32 prepareId,
15761  UtilPrepareReq::OperationTypeValue prepReq)
15762 {
15763  jam();
15764 
15765  DictObject * opj_ptr_p = get_object(EVENT_SYSTEM_TABLE_NAME,
15766  sizeof(EVENT_SYSTEM_TABLE_NAME));
15767 
15768  ndbrequire(opj_ptr_p != 0);
15769  TableRecordPtr tablePtr;
15770  c_tableRecordPool.getPtr(tablePtr, opj_ptr_p->m_id);
15771  ndbrequire(tablePtr.i != RNIL); // system table must exist
15772 
15773  Uint32 noAttr = tablePtr.p->noOfAttributes;
15774  if (noAttr > EVENT_SYSTEM_TABLE_LENGTH)
15775  {
15776  jam();
15777  noAttr = EVENT_SYSTEM_TABLE_LENGTH;
15778  }
15779 
15780  Uint32 total_len = 0;
15781 
15782  Uint32* attrHdr = signal->theData + 25;
15783  Uint32* attrPtr = attrHdr;
15784  Uint32* dataPtr = attrHdr + noAttr;
15785 
15786  Uint32 id=0;
15787  // attribute 0 event name: Primary Key
15788  {
15789  char *base = (char*)&m_eventRec;
15790  Uint32 sz = sysTab_NDBEVENTS_0_szs[id];
15791  const Uint32 *src = (const Uint32*)(base +sysTab_NDBEVENTS_0_offsets[id]);
15792  memcpy(dataPtr, src, sz);
15793  dataPtr += (sz / 4);
15794 
15795  AttributeHeader::init(attrPtr, id, sz);
15796  total_len += sz;
15797  attrPtr++; id++;
15798  }
15799 
15800  switch (prepReq) {
15801  case UtilPrepareReq::Read:
15802  jam();
15803  EVENT_TRACE;
15804 
15805  // clear it, since NDB$EVENTS_0.ATTRIBUTE_MASK2 might not be present
15806  bzero(m_eventRec.ATTRIBUTE_MASK2, sizeof(m_eventRec.ATTRIBUTE_MASK2));
15807 
15808  // no more
15809  while ( id < noAttr )
15810  AttributeHeader::init(attrPtr++, id++, 0);
15811  ndbrequire(id == noAttr);
15812  break;
15813  case UtilPrepareReq::Insert:
15814  {
15815  jam();
15816  EVENT_TRACE;
15817  char *base = (char*)&m_eventRec;
15818  while ( id < noAttr )
15819  {
15820  if (id != EVENT_SYSTEM_TABLE_ATTRIBUTE_MASK2_ID)
15821  {
15822  jam();
15823  Uint32 sz = sysTab_NDBEVENTS_0_szs[id];
15824  AttributeHeader::init(attrPtr, id, sz);
15825  const Uint32 *src = (const Uint32*)(base +sysTab_NDBEVENTS_0_offsets[id]);
15826  memcpy(dataPtr, src, sz);
15827  dataPtr += (sz / 4);
15828  total_len += sysTab_NDBEVENTS_0_szs[id];
15829  }
15830  else
15831  {
15832  jam();
15833  Uint32 szBytes = countPrefixBytes(sizeof(m_eventRec.ATTRIBUTE_MASK2) - 4,
15834  (Uint8*)m_eventRec.ATTRIBUTE_MASK2);
15835  AttributeHeader::init(attrPtr, id, 2 + szBytes);
15836 
15837  Uint8 * lenbytes = (Uint8*)dataPtr;
15838  lenbytes[0] = (szBytes & 0xFF);
15839  lenbytes[1] = (szBytes / 256);
15840  memcpy(lenbytes + 2, m_eventRec.ATTRIBUTE_MASK2, szBytes);
15841  if (szBytes & 3)
15842  {
15843  bzero(lenbytes + 2 + szBytes, 4 - (szBytes & 3));
15844  }
15845  szBytes += 2;
15846  dataPtr += (szBytes + 3) / 4;
15847  total_len += 4 * ((szBytes + 3) / 4);
15848  }
15849  attrPtr++; id++;
15850  }
15851  break;
15852  }
15853  case UtilPrepareReq::Delete:
15854  ndbrequire(id == 1);
15855  break;
15856  default:
15857  ndbrequire(false);
15858  }
15859 
15860  LinearSectionPtr headerPtr;
15861  LinearSectionPtr lsdataPtr;
15862 
15863  headerPtr.p = attrHdr;
15864  headerPtr.sz = id;
15865 
15866  lsdataPtr.p = attrHdr + noAttr;
15867  lsdataPtr.sz = total_len/4;
15868 
15869 #if 0
15870  printf("Header size %u\n", headerPtr.sz);
15871  for(int i = 0; i < (int)headerPtr.sz; i++)
15872  printf("H'%.8x ", attrHdr[i]);
15873  printf("\n");
15874 
15875  printf("Data size %u\n", lsdataPtr.sz);
15876  for(int i = 0; i < (int)lsdataPtr.sz; i++)
15877  printf("H'%.8x ", dataPage[i]);
15878  printf("\n");
15879 #endif
15880 
15881  executeTransaction(pcallback, signal,
15882  ptrI,
15883  prepareId,
15884  id,
15885  headerPtr,
15886  lsdataPtr);
15887 }
15888 
15889 void Dbdict::executeTransaction(Callback *pcallback,
15890  Signal* signal,
15891  Uint32 senderData,
15892  Uint32 prepareId,
15893  Uint32 noAttr,
15894  LinearSectionPtr headerPtr,
15895  LinearSectionPtr dataPtr)
15896 {
15897  jam();
15898  EVENT_TRACE;
15899 
15900  UtilExecuteReq * utilExecuteReq =
15901  (UtilExecuteReq *)signal->getDataPtrSend();
15902 
15903  utilExecuteReq->setSenderRef(reference());
15904  utilExecuteReq->setSenderData(senderData);
15905  utilExecuteReq->setPrepareId(prepareId);
15906  utilExecuteReq->setReleaseFlag(); // must be done after setting prepareId
15907 
15908 #if 0
15909  printf("Header size %u\n", headerPtr.sz);
15910  for(int i = 0; i < (int)headerPtr.sz; i++)
15911  printf("H'%.8x ", headerBuffer[i]);
15912  printf("\n");
15913 
15914  printf("Data size %u\n", dataPtr.sz);
15915  for(int i = 0; i < (int)dataPtr.sz; i++)
15916  printf("H'%.8x ", dataBuffer[i]);
15917  printf("\n");
15918 #endif
15919 
15920  struct LinearSectionPtr sectionsPtr[UtilExecuteReq::NoOfSections];
15921  sectionsPtr[UtilExecuteReq::HEADER_SECTION].p = headerPtr.p;
15922  sectionsPtr[UtilExecuteReq::HEADER_SECTION].sz = noAttr;
15923  sectionsPtr[UtilExecuteReq::DATA_SECTION].p = dataPtr.p;
15924  sectionsPtr[UtilExecuteReq::DATA_SECTION].sz = dataPtr.sz;
15925 
15926  sendSignalUtilReq(pcallback, DBUTIL_REF, GSN_UTIL_EXECUTE_REQ, signal,
15927  UtilExecuteReq::SignalLength, JBB,
15928  sectionsPtr, UtilExecuteReq::NoOfSections);
15929 }
15930 
15931 void Dbdict::parseReadEventSys(Signal* signal, sysTab_NDBEVENTS_0& m_eventRec)
15932 {
15933  jam();
15934  SectionHandle handle(this, signal);
15935  SegmentedSectionPtr headerPtr, dataPtr;
15936 
15937  handle.getSection(headerPtr, UtilExecuteReq::HEADER_SECTION);
15938  SectionReader headerReader(headerPtr, getSectionSegmentPool());
15939 
15940  handle.getSection(dataPtr, UtilExecuteReq::DATA_SECTION);
15941  SectionReader dataReader(dataPtr, getSectionSegmentPool());
15942 
15943  char *base = (char*)&m_eventRec;
15944 
15945  DictObject * opj_ptr_p = get_object(EVENT_SYSTEM_TABLE_NAME,
15946  sizeof(EVENT_SYSTEM_TABLE_NAME));
15947 
15948  ndbrequire(opj_ptr_p != 0);
15949  TableRecordPtr tablePtr;
15950  c_tableRecordPool.getPtr(tablePtr, opj_ptr_p->m_id);
15951  ndbrequire(tablePtr.i != RNIL); // system table must exist
15952 
15953  Uint32 noAttr = tablePtr.p->noOfAttributes;
15954  if (noAttr > EVENT_SYSTEM_TABLE_LENGTH)
15955  {
15956  jam();
15957  noAttr = EVENT_SYSTEM_TABLE_LENGTH;
15958  }
15959 
15960  for (Uint32 i = 0; i < noAttr; i++)
15961  {
15962  jam();
15963  Uint32 headerWord;
15964  headerReader.getWord(&headerWord);
15965  Uint32 sz = AttributeHeader::getDataSize(headerWord);
15966  ndbrequire(4 * sz <= sysTab_NDBEVENTS_0_szs[i]);
15967  Uint32 * dst = (Uint32*)(base + sysTab_NDBEVENTS_0_offsets[i]);
15968  for (Uint32 j = 0; j < sz; j++)
15969  dataReader.getWord(dst++);
15970  }
15971 
15972  releaseSections(handle);
15973 
15974  if (noAttr < EVENT_SYSTEM_TABLE_LENGTH)
15975  {
15976  jam();
15977  bzero(m_eventRec.ATTRIBUTE_MASK2, sizeof(m_eventRec.ATTRIBUTE_MASK2));
15978  memcpy(m_eventRec.ATTRIBUTE_MASK2, m_eventRec.ATTRIBUTE_MASK,
15979  sizeof(m_eventRec.ATTRIBUTE_MASK));
15980  }
15981  else
15982  {
15983  jam();
15984  Uint8* lenbytes = (Uint8*)m_eventRec.ATTRIBUTE_MASK2;
15985  Uint32 szBytes = lenbytes[0] + (lenbytes[1] * 256);
15986  memmove(lenbytes, lenbytes + 2, szBytes);
15987  bzero(lenbytes + szBytes, sizeof(m_eventRec.ATTRIBUTE_MASK2) - szBytes);
15988  }
15989 }
15990 
15991 void Dbdict::createEventUTIL_EXECUTE(Signal *signal,
15992  Uint32 callbackData,
15993  Uint32 returnCode)
15994 {
15995  jam();
15996  EVENT_TRACE;
15997  if (returnCode == 0) {
15998  // Entry into system table all set
15999  UtilExecuteConf* const conf = (UtilExecuteConf*)signal->getDataPtr();
16000  jam();
16001  OpCreateEventPtr evntRecPtr;
16002  evntRecPtr.i = conf->getSenderData();
16003 
16004  ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
16005  OpCreateEvent *evntRec = evntRecPtr.p;
16006 
16007  switch (evntRec->m_requestType) {
16008  case CreateEvntReq::RT_USER_GET: {
16009  parseReadEventSys(signal, evntRecPtr.p->m_eventRec);
16010 
16011  evntRec->m_request.setEventType(evntRecPtr.p->m_eventRec.EVENT_TYPE);
16012  evntRec->m_request.setReportFlags(evntRecPtr.p->m_eventRec.EVENT_TYPE);
16013  evntRec->m_request.setTableId(evntRecPtr.p->m_eventRec.TABLEID);
16014  evntRec->m_request.setTableVersion(evntRecPtr.p->m_eventRec.TABLEVERSION);
16015  Uint32 sz = NDB_ARRAY_SIZE(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK);
16016  evntRec->m_request.setAttrListBitmask(sz, evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK);
16017  evntRec->m_request.setEventId(evntRecPtr.p->m_eventRec.SUBID);
16018  evntRec->m_request.setEventKey(evntRecPtr.p->m_eventRec.SUBKEY);
16019 
16020  DBUG_PRINT("info",
16021  ("GET: event name: %s table name: %s table id: %u table version: %u",
16022  evntRecPtr.p->m_eventRec.NAME,
16023  evntRecPtr.p->m_eventRec.TABLE_NAME,
16024  evntRecPtr.p->m_eventRec.TABLEID,
16025  evntRecPtr.p->m_eventRec.TABLEVERSION));
16026 
16027  // find table id for event table
16028  DictObject* obj_ptr_p = get_object(evntRecPtr.p->m_eventRec.TABLE_NAME);
16029  if(!obj_ptr_p){
16030  jam();
16031  evntRecPtr.p->m_errorCode = 723;
16032  evntRecPtr.p->m_errorLine = __LINE__;
16033  evntRecPtr.p->m_errorNode = reference();
16034 
16035  createEvent_sendReply(signal, evntRecPtr);
16036  return;
16037  }
16038 
16039  TableRecordPtr tablePtr;
16040  c_tableRecordPool.getPtr(tablePtr, obj_ptr_p->m_id);
16041  evntRec->m_request.setTableId(tablePtr.p->tableId);
16042  evntRec->m_request.setTableVersion(tablePtr.p->tableVersion);
16043 
16044  createEventComplete_RT_USER_GET(signal, evntRecPtr);
16045  return;
16046  }
16047  case CreateEvntReq::RT_USER_CREATE: {
16048 #ifdef EVENT_DEBUG
16049  printf("create type = %d\n", CreateEvntReq::RT_USER_CREATE);
16050 #endif
16051  jam();
16052  createEventComplete_RT_USER_CREATE(signal, evntRecPtr);
16053  return;
16054  }
16055  break;
16056  default:
16057  ndbrequire(false);
16058  }
16059  } else { // returnCode != 0
16060  UtilExecuteRef * const ref = (UtilExecuteRef *)signal->getDataPtr();
16061  OpCreateEventPtr evntRecPtr;
16062  evntRecPtr.i = ref->getSenderData();
16063  ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
16064  jam();
16065  evntRecPtr.p->m_errorNode = reference();
16066  evntRecPtr.p->m_errorLine = __LINE__;
16067 
16068  switch (ref->getErrorCode()) {
16069  case UtilExecuteRef::TCError:
16070  switch (ref->getTCErrorCode()) {
16071  case ZNOT_FOUND:
16072  jam();
16073  evntRecPtr.p->m_errorCode = 4710;
16074  break;
16075  case ZALREADYEXIST:
16076  jam();
16077  evntRecPtr.p->m_errorCode = 746;
16078  break;
16079  default:
16080  jam();
16081  evntRecPtr.p->m_errorCode = ref->getTCErrorCode();
16082  break;
16083  }
16084  break;
16085  default:
16086  jam();
16087  evntRecPtr.p->m_errorCode = ref->getErrorCode();
16088  break;
16089  }
16090 
16091  createEvent_sendReply(signal, evntRecPtr);
16092  }
16093 }
16094 
16095 /***********************************************************************
16096  *
16097  * NdbEventOperation, reading systable, creating event in suma
16098  *
16099  */
16100 
16101 void
16102 Dbdict::createEvent_RT_USER_GET(Signal* signal,
16103  OpCreateEventPtr evntRecPtr,
16104  SectionHandle& handle){
16105  jam();
16106  EVENT_TRACE;
16107 #ifdef EVENT_PH2_DEBUG
16108  ndbout_c("DBDICT(Coordinator) got GSN_CREATE_EVNT_REQ::RT_USER_GET evntRecPtr.i = (%d), ref = %u", evntRecPtr.i, evntRecPtr.p->m_request.getUserRef());
16109 #endif
16110 
16111  SegmentedSectionPtr ssPtr;
16112 
16113  handle.getSection(ssPtr, 0);
16114 
16115  SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
16116 #ifdef EVENT_DEBUG
16117  r0.printAll(ndbout);
16118 #endif
16119  if ((!r0.first()) ||
16120  (r0.getValueType() != SimpleProperties::StringValue) ||
16121  (r0.getValueLen() <= 0)) {
16122  jam();
16123  releaseSections(handle);
16124 
16125  evntRecPtr.p->m_errorCode = 1;
16126  evntRecPtr.p->m_errorLine = __LINE__;
16127  evntRecPtr.p->m_errorNode = reference();
16128 
16129  createEvent_sendReply(signal, evntRecPtr);
16130  return;
16131  }
16132 
16133  r0.getString(evntRecPtr.p->m_eventRec.NAME);
16134  int len = strlen(evntRecPtr.p->m_eventRec.NAME);
16135  memset(evntRecPtr.p->m_eventRec.NAME+len, 0, MAX_TAB_NAME_SIZE-len);
16136 
16137  releaseSections(handle);
16138 
16139  Callback c = { safe_cast(&Dbdict::createEventUTIL_PREPARE), 0 };
16140 
16141  prepareTransactionEventSysTable(&c, signal, evntRecPtr.i,
16142  UtilPrepareReq::Read);
16143  /*
16144  * Will read systable and fill an OpCreateEventPtr
16145  * and return below
16146  */
16147 }
16148 
16149 void
16150 Dbdict::createEventComplete_RT_USER_GET(Signal* signal,
16151  OpCreateEventPtr evntRecPtr){
16152  jam();
16153 
16154  // Send to oneself and the other DICT's
16155  CreateEvntReq * req = (CreateEvntReq *)signal->getDataPtrSend();
16156 
16157  *req = evntRecPtr.p->m_request;
16158  req->senderRef = reference();
16159  req->senderData = evntRecPtr.i;
16160 
16161  req->addRequestFlag(CreateEvntReq::RT_DICT_AFTER_GET);
16162 
16163 #ifdef EVENT_PH2_DEBUG
16164  ndbout_c("DBDICT(Coordinator) sending GSN_CREATE_EVNT_REQ::RT_DICT_AFTER_GET to DBDICT participants evntRecPtr.i = (%d)", evntRecPtr.i);
16165 #endif
16166 
16167  NodeReceiverGroup rg(DBDICT, c_aliveNodes);
16168  RequestTracker & p = evntRecPtr.p->m_reqTracker;
16169  if (!p.init<CreateEvntRef>(c_counterMgr, rg, GSN_CREATE_EVNT_REF,
16170  evntRecPtr.i))
16171  {
16172  jam();
16173  evntRecPtr.p->m_errorCode = 701;
16174  createEvent_sendReply(signal, evntRecPtr);
16175  return;
16176  }
16177 
16178  sendSignal(rg, GSN_CREATE_EVNT_REQ, signal, CreateEvntReq::SignalLength, JBB);
16179  return;
16180 }
16181 
16182 void
16183 Dbdict::createEvent_nodeFailCallback(Signal* signal, Uint32 eventRecPtrI,
16184  Uint32 returnCode){
16185  OpCreateEventPtr evntRecPtr;
16186  c_opCreateEvent.getPtr(evntRecPtr, eventRecPtrI);
16187  createEvent_sendReply(signal, evntRecPtr);
16188 }
16189 
16190 void Dbdict::execCREATE_EVNT_REF(Signal* signal)
16191 {
16192  jamEntry();
16193  EVENT_TRACE;
16194  CreateEvntRef * const ref = (CreateEvntRef *)signal->getDataPtr();
16195  OpCreateEventPtr evntRecPtr;
16196 
16197  evntRecPtr.i = ref->getUserData();
16198  ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
16199 
16200 #ifdef EVENT_PH2_DEBUG
16201  ndbout_c("DBDICT(Coordinator) got GSN_CREATE_EVNT_REF evntRecPtr.i = (%d)", evntRecPtr.i);
16202 #endif
16203 
16204  LinearSectionPtr ptr[2];
16205 
16206  int noLSP = 0;
16207  LinearSectionPtr *ptr0 = NULL;
16208  if (ref->errorCode == CreateEvntRef::NF_FakeErrorREF)
16209  {
16210  jam();
16211  evntRecPtr.p->m_reqTracker.ignoreRef(c_counterMgr,
16212  refToNode(ref->senderRef));
16213 
16219  if (evntRecPtr.p->m_reqTracker.done())
16220  {
16221  jam();
16227  ptr[0].p = (Uint32 *)evntRecPtr.p->m_eventRec.TABLE_NAME;
16228  ptr[0].sz = Uint32((strlen(evntRecPtr.p->m_eventRec.TABLE_NAME)+4)/4);
16229  ptr[1].p = evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2;
16230  ptr[1].sz = NDB_ARRAY_SIZE(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2) - 1;
16231  ptr0 = ptr;
16232  noLSP = 2;
16233  }
16234  }
16235  else
16236  {
16237  jam();
16238  evntRecPtr.p->m_errorCode = ref->errorCode;
16239  evntRecPtr.p->m_reqTracker.reportRef(c_counterMgr,
16240  refToNode(ref->senderRef));
16241  }
16242 
16243  createEvent_sendReply(signal, evntRecPtr, ptr0, noLSP);
16244 
16245  return;
16246 }
16247 
16248 void Dbdict::execCREATE_EVNT_CONF(Signal* signal)
16249 {
16250  jamEntry();
16251  EVENT_TRACE;
16252  CreateEvntConf * const conf = (CreateEvntConf *)signal->getDataPtr();
16253  OpCreateEventPtr evntRecPtr;
16254 
16255  evntRecPtr.i = conf->getUserData();
16256 
16257  ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
16258 
16259 #ifdef EVENT_PH2_DEBUG
16260  ndbout_c("DBDICT(Coordinator) got GSN_CREATE_EVNT_CONF evntRecPtr.i = (%d)", evntRecPtr.i);
16261 #endif
16262 
16263  evntRecPtr.p->m_reqTracker.reportConf(c_counterMgr, refToNode(conf->senderRef));
16264 
16265  // we will only have a valid tablename if it the master DICT sending this
16266  // but that's ok
16267  LinearSectionPtr ptr[2];
16268  ptr[0].p = (Uint32 *)evntRecPtr.p->m_eventRec.TABLE_NAME;
16269  ptr[0].sz =
16270  Uint32(strlen(evntRecPtr.p->m_eventRec.TABLE_NAME)+4)/4; // to make sure we have a null
16271  ptr[1].p = evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2;
16272  ptr[1].sz = NDB_ARRAY_SIZE(evntRecPtr.p->m_eventRec.ATTRIBUTE_MASK2) - 1;
16273 
16274  createEvent_sendReply(signal, evntRecPtr, ptr, 2);
16275 
16276  return;
16277 }
16278 
16279 /************************************************
16280  *
16281  * Participant stuff
16282  *
16283  */
16284 
16285 void
16286 Dbdict::createEvent_RT_DICT_AFTER_GET(Signal* signal, OpCreateEventPtr evntRecPtr){
16287  DBUG_ENTER("Dbdict::createEvent_RT_DICT_AFTER_GET");
16288  jam();
16289  evntRecPtr.p->m_request.setUserRef(signal->senderBlockRef());
16290 
16291 #ifdef EVENT_PH2_DEBUG
16292  ndbout_c("DBDICT(Participant) got CREATE_EVNT_REQ::RT_DICT_AFTER_GET evntRecPtr.i = (%d)", evntRecPtr.i);
16293 #endif
16294 
16295  // the signal comes from the DICT block that got the first user request!
16296  // This code runs on all DICT nodes, including oneself
16297 
16298  // Seize a Create Event record, the Coordinator will now have two seized
16299  // but that's ok, it's like a recursion
16300 
16301  CRASH_INSERTION2(6009, getOwnNodeId() != c_masterNodeId);
16302 
16303  SubCreateReq * sumaReq = (SubCreateReq *)signal->getDataPtrSend();
16304 
16305  sumaReq->senderRef = reference(); // reference to DICT
16306  sumaReq->senderData = evntRecPtr.i;
16307  sumaReq->subscriptionId = evntRecPtr.p->m_request.getEventId();
16308  sumaReq->subscriptionKey = evntRecPtr.p->m_request.getEventKey();
16309  sumaReq->subscriptionType = SubCreateReq::TableEvent;
16310  if (evntRecPtr.p->m_request.getReportAll())
16311  sumaReq->subscriptionType|= SubCreateReq::ReportAll;
16312  if (evntRecPtr.p->m_request.getReportSubscribe())
16313  sumaReq->subscriptionType|= SubCreateReq::ReportSubscribe;
16314  if (! evntRecPtr.p->m_request.getReportDDL())
16315  {
16316  sumaReq->subscriptionType |= SubCreateReq::NoReportDDL;
16317  }
16318  sumaReq->tableId = evntRecPtr.p->m_request.getTableId();
16319  sumaReq->schemaTransId = 0;
16320 
16321 #ifdef EVENT_PH2_DEBUG
16322  ndbout_c("sending GSN_SUB_CREATE_REQ");
16323 #endif
16324 
16325  sendSignal(SUMA_REF, GSN_SUB_CREATE_REQ, signal,
16326  SubCreateReq::SignalLength, JBB);
16327  DBUG_VOID_RETURN;
16328 }
16329 
16330 void Dbdict::execSUB_CREATE_REF(Signal* signal)
16331 {
16332  jamEntry();
16333  DBUG_ENTER("Dbdict::execSUB_CREATE_REF");
16334 
16335  SubCreateRef * const ref = (SubCreateRef *)signal->getDataPtr();
16336  OpCreateEventPtr evntRecPtr;
16337 
16338  evntRecPtr.i = ref->senderData;
16339  ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
16340 
16341  if (ref->errorCode == SubCreateRef::NotStarted)
16342  {
16343  jam();
16344  // ignore (was previously NF_FakeErrorREF)
16345  // NOTE: different handling then rest of execSUB_XXX_REF
16346  // note to mess with GSN_CREATE_EVNT
16347  }
16348  else if (ref->errorCode)
16349  {
16350  jam();
16351  evntRecPtr.p->m_errorCode = ref->errorCode;
16352  evntRecPtr.p->m_errorLine = __LINE__;
16353  evntRecPtr.p->m_errorNode = reference();
16354  }
16355  else
16356  {
16357  jam();
16358  evntRecPtr.p->m_errorCode = 1;
16359  evntRecPtr.p->m_errorLine = __LINE__;
16360  evntRecPtr.p->m_errorNode = reference();
16361  }
16362 
16363  createEvent_sendReply(signal, evntRecPtr);
16364  DBUG_VOID_RETURN;
16365 }
16366 
16367 void Dbdict::execSUB_CREATE_CONF(Signal* signal)
16368 {
16369  jamEntry();
16370  DBUG_ENTER("Dbdict::execSUB_CREATE_CONF");
16371  EVENT_TRACE;
16372 
16373  SubCreateConf * const sumaConf = (SubCreateConf *)signal->getDataPtr();
16374  OpCreateEventPtr evntRecPtr;
16375  evntRecPtr.i = sumaConf->senderData;
16376  ndbrequire((evntRecPtr.p = c_opCreateEvent.getPtr(evntRecPtr.i)) != NULL);
16377 
16378  createEvent_sendReply(signal, evntRecPtr);
16379 
16380  DBUG_VOID_RETURN;
16381 }
16382 
16383 /****************************************************
16384  *
16385  * common create reply method
16386  *
16387  *******************************************************/
16388 
16389 void Dbdict::createEvent_sendReply(Signal* signal,
16390  OpCreateEventPtr evntRecPtr,
16391  LinearSectionPtr *ptr, int noLSP)
16392 {
16393  jam();
16394  EVENT_TRACE;
16395 
16396  // check if we're ready to sent reply
16397  // if we are the master dict we might be waiting for conf/ref
16398 
16399  if (!evntRecPtr.p->m_reqTracker.done()) {
16400  jam();
16401  return; // there's more to come
16402  }
16403 
16404  if (evntRecPtr.p->m_reqTracker.hasRef()) {
16405  ptr = NULL; // we don't want to return anything if there's an error
16406  if (!evntRecPtr.p->hasError()) {
16407  evntRecPtr.p->m_errorCode = 1;
16408  evntRecPtr.p->m_errorLine = __LINE__;
16409  evntRecPtr.p->m_errorNode = reference();
16410  jam();
16411  } else
16412  jam();
16413  }
16414 
16415  // reference to API if master DICT
16416  // else reference to master DICT
16417  Uint32 senderRef = evntRecPtr.p->m_request.getUserRef();
16418  Uint32 signalLength;
16419  Uint32 gsn;
16420 
16421  if (evntRecPtr.p->hasError()) {
16422  jam();
16423  EVENT_TRACE;
16424  CreateEvntRef * ret = (CreateEvntRef *)signal->getDataPtrSend();
16425 
16426  ret->setEventId(evntRecPtr.p->m_request.getEventId());
16427  ret->setEventKey(evntRecPtr.p->m_request.getEventKey());
16428  ret->setUserData(evntRecPtr.p->m_request.getUserData());
16429  ret->senderRef = reference();
16430  ret->setTableId(evntRecPtr.p->m_request.getTableId());
16431  ret->setTableVersion(evntRecPtr.p->m_request.getTableVersion());
16432  ret->setEventType(evntRecPtr.p->m_request.getEventType());
16433  ret->setRequestType(evntRecPtr.p->m_request.getRequestType());
16434 
16435  ret->setErrorCode(evntRecPtr.p->m_errorCode);
16436  ret->setErrorLine(evntRecPtr.p->m_errorLine);
16437  ret->setErrorNode(evntRecPtr.p->m_errorNode);
16438 
16439  signalLength = CreateEvntRef::SignalLength;
16440 #ifdef EVENT_PH2_DEBUG
16441  ndbout_c("DBDICT sending GSN_CREATE_EVNT_REF to evntRecPtr.i = (%d) node = %u ref = %u", evntRecPtr.i, refToNode(senderRef), senderRef);
16442  ndbout_c("errorCode = %u", evntRecPtr.p->m_errorCode);
16443  ndbout_c("errorLine = %u", evntRecPtr.p->m_errorLine);
16444 #endif
16445  gsn = GSN_CREATE_EVNT_REF;
16446 
16447  } else {
16448  jam();
16449  EVENT_TRACE;
16450  CreateEvntConf * evntConf = (CreateEvntConf *)signal->getDataPtrSend();
16451 
16452  evntConf->setEventId(evntRecPtr.p->m_request.getEventId());
16453  evntConf->setEventKey(evntRecPtr.p->m_request.getEventKey());
16454  evntConf->setUserData(evntRecPtr.p->m_request.getUserData());
16455  evntConf->senderRef = reference();
16456  evntConf->setTableId(evntRecPtr.p->m_request.getTableId());
16457  evntConf->setTableVersion(evntRecPtr.p->m_request.getTableVersion());
16458  evntConf->setAttrListBitmask(evntRecPtr.p->m_request.getAttrListBitmask());
16459  evntConf->setEventType(evntRecPtr.p->m_request.getEventType());
16460  evntConf->setRequestType(evntRecPtr.p->m_request.getRequestType());
16461 
16462  signalLength = CreateEvntConf::SignalLength;
16463 #ifdef EVENT_PH2_DEBUG
16464  ndbout_c("DBDICT sending GSN_CREATE_EVNT_CONF to evntRecPtr.i = (%d) node = %u ref = %u", evntRecPtr.i, refToNode(senderRef), senderRef);
16465 #endif
16466  gsn = GSN_CREATE_EVNT_CONF;
16467  }
16468 
16469  if (ptr) {
16470  jam();
16471  sendSignal(senderRef, gsn, signal, signalLength, JBB, ptr, noLSP);
16472  } else {
16473  jam();
16474  sendSignal(senderRef, gsn, signal, signalLength, JBB);
16475  }
16476 
16477  c_opCreateEvent.release(evntRecPtr);
16478 }
16479 
16480 /*************************************************************/
16481 
16482 /********************************************************************
16483  *
16484  * Start event
16485  *
16486  *******************************************************************/
16487 
16488 void Dbdict::execSUB_START_REQ(Signal* signal)
16489 {
16490  jamEntry();
16491 
16492  Uint32 origSenderRef = signal->senderBlockRef();
16493 
16494  if (refToBlock(origSenderRef) != DBDICT &&
16495  getOwnNodeId() != c_masterNodeId)
16496  {
16497  /*
16498  * Coordinator but not master
16499  */
16500  SubStartRef * ref = (SubStartRef *)signal->getDataPtrSend();
16501  ref->senderRef = reference();
16502  ref->errorCode = SubStartRef::NotMaster;
16503  ref->m_masterNodeId = c_masterNodeId;
16504  sendSignal(origSenderRef, GSN_SUB_START_REF, signal,
16505  SubStartRef::SignalLength2, JBB);
16506  return;
16507  }
16508  OpSubEventPtr subbPtr;
16509  Uint32 errCode = 0;
16510 
16511  if (!c_opSubEvent.seize(subbPtr)) {
16512  errCode = SubStartRef::Busy;
16513 busy:
16514  jam();
16515  SubStartRef * ref = (SubStartRef *)signal->getDataPtrSend();
16516 
16517  { // fix
16518  Uint32 subcriberRef = ((SubStartReq*)signal->getDataPtr())->subscriberRef;
16519  ref->subscriberRef = subcriberRef;
16520  }
16521  jam();
16522  // ret->setErrorCode(SubStartRef::SeizeError);
16523  // ret->setErrorLine(__LINE__);
16524  // ret->setErrorNode(reference());
16525  ref->senderRef = reference();
16526  ref->errorCode = errCode;
16527  ref->m_masterNodeId = c_masterNodeId;
16528 
16529  sendSignal(origSenderRef, GSN_SUB_START_REF, signal,
16530  SubStartRef::SL_MasterNode, JBB);
16531  return;
16532  }
16533 
16534  {
16535  const SubStartReq* req = (SubStartReq*) signal->getDataPtr();
16536  subbPtr.p->m_senderRef = req->senderRef;
16537  subbPtr.p->m_senderData = req->senderData;
16538  subbPtr.p->m_errorCode = 0;
16539  subbPtr.p->m_gsn = GSN_SUB_START_REQ;
16540  subbPtr.p->m_subscriptionId = req->subscriptionId;
16541  subbPtr.p->m_subscriptionKey = req->subscriptionKey;
16542  subbPtr.p->m_subscriberRef = req->subscriberRef;
16543  subbPtr.p->m_subscriberData = req->subscriberData;
16544  bzero(subbPtr.p->m_buckets_per_ng, sizeof(subbPtr.p->m_buckets_per_ng));
16545  }
16546 
16547  if (refToBlock(origSenderRef) != DBDICT) {
16548  /*
16549  * Coordinator
16550  */
16551  jam();
16552 
16553  if (c_masterNodeId != getOwnNodeId())
16554  {
16555  jam();
16556  c_opSubEvent.release(subbPtr);
16557  errCode = SubStartRef::NotMaster;
16558  goto busy;
16559  }
16560 
16561  if (!c_sub_startstop_lock.isclear())
16562  {
16563  jam();
16564  c_opSubEvent.release(subbPtr);
16565  errCode = SubStartRef::BusyWithNR;
16566  goto busy;
16567  }
16568 
16569  subbPtr.p->m_senderRef = origSenderRef; // not sure if API sets correctly
16570  NodeReceiverGroup rg(DBDICT, c_aliveNodes);
16571 
16572  RequestTracker & p = subbPtr.p->m_reqTracker;
16573  if (!p.init<SubStartRef>(c_counterMgr, rg, GSN_SUB_START_REF, subbPtr.i))
16574  {
16575  c_opSubEvent.release(subbPtr);
16576  errCode = SubStartRef::Busy;
16577  goto busy;
16578  }
16579 
16580  SubStartReq* req = (SubStartReq*) signal->getDataPtrSend();
16581 
16582  req->senderRef = reference();
16583  req->senderData = subbPtr.i;
16584 
16585 #ifdef EVENT_PH3_DEBUG
16586  ndbout_c("DBDICT(Coordinator) sending GSN_SUB_START_REQ to DBDICT participants subbPtr.i = (%d)", subbPtr.i);
16587 #endif
16588 
16589  if (ERROR_INSERTED(6011))
16590  {
16591  ndbout_c("sending delayed to self...");
16592  if (ERROR_INSERTED(6011))
16593  {
16594  rg.m_nodes.clear(getOwnNodeId());
16595  }
16596  sendSignal(rg, GSN_SUB_START_REQ, signal,
16597  SubStartReq::SignalLength, JBB);
16598  sendSignalWithDelay(reference(),
16599  GSN_SUB_START_REQ,
16600  signal, 5000, SubStartReq::SignalLength);
16601  }
16602  else
16603  {
16604  c_outstanding_sub_startstop++;
16605  sendSignal(rg, GSN_SUB_START_REQ, signal,
16606  SubStartReq::SignalLength, JBB);
16607  }
16608  return;
16609  }
16610  /*
16611  * Participant
16612  */
16613  ndbrequire(refToBlock(origSenderRef) == DBDICT);
16614 
16615  CRASH_INSERTION(6007);
16616 
16617  {
16618  SubStartReq* req = (SubStartReq*) signal->getDataPtrSend();
16619 
16620  req->senderRef = reference();
16621  req->senderData = subbPtr.i;
16622 
16623 #ifdef EVENT_PH3_DEBUG
16624  ndbout_c("DBDICT(Participant) sending GSN_SUB_START_REQ to SUMA subbPtr.i = (%d)", subbPtr.i);
16625 #endif
16626  sendSignal(SUMA_REF, GSN_SUB_START_REQ, signal, SubStartReq::SignalLength, JBB);
16627  }
16628 }
16629 
16630 bool
16631 Dbdict::upgrade_suma_NotStarted(Uint32 err, Uint32 ref) const
16632 {
16637  if (err == 1428)
16638  {
16639  jam();
16640  if (!ndb_suma_not_started_ref(getNodeInfo(refToNode(ref)).m_version))
16641  return true;
16642  }
16643  return false;
16644 }
16645 
16646 void Dbdict::execSUB_START_REF(Signal* signal)
16647 {
16648  jamEntry();
16649 
16650  const SubStartRef* ref = (SubStartRef*) signal->getDataPtr();
16651  Uint32 senderRef = ref->senderRef;
16652  Uint32 err = ref->errorCode;
16653 
16654  OpSubEventPtr subbPtr;
16655  c_opSubEvent.getPtr(subbPtr, ref->senderData);
16656 
16657  if (refToBlock(senderRef) == SUMA)
16658  {
16659  /*
16660  * Participant
16661  */
16662  jam();
16663 
16664 #ifdef EVENT_PH3_DEBUG
16665  ndbout_c("DBDICT(Participant) got GSN_SUB_START_REF = (%d)", subbPtr.i);
16666 #endif
16667 
16668  if (upgrade_suma_NotStarted(err, subbPtr.p->m_senderRef))
16669  {
16670  jam();
16671  err = SubStartRef::NF_FakeErrorREF;
16672  }
16673 
16674  SubStartRef* ref = (SubStartRef*) signal->getDataPtrSend();
16675  ref->senderRef = reference();
16676  ref->senderData = subbPtr.p->m_senderData;
16677  ref->errorCode = err;
16678  sendSignal(subbPtr.p->m_senderRef, GSN_SUB_START_REF,
16679  signal, SubStartRef::SignalLength2, JBB);
16680  c_opSubEvent.release(subbPtr);
16681  return;
16682  }
16683  /*
16684  * Coordinator
16685  */
16686  ndbrequire(refToBlock(senderRef) == DBDICT);
16687 #ifdef EVENT_PH3_DEBUG
16688  ndbout_c("DBDICT(Coordinator) got GSN_SUB_START_REF = (%d)", subbPtr.i);
16689 #endif
16690  if (err == SubStartRef::NotStarted)
16691  {
16692  jam();
16693  subbPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(senderRef));
16694  }
16695  else
16696  {
16697  if (err == SubStartRef::NF_FakeErrorREF)
16698  {
16699  jam();
16700  err = SubStartRef::NodeDied;
16701  }
16702 
16703  if (subbPtr.p->m_errorCode == 0)
16704  {
16705  subbPtr.p->m_errorCode= err ? err : 1;
16706  }
16707  subbPtr.p->m_reqTracker.reportRef(c_counterMgr, refToNode(senderRef));
16708  }
16709  completeSubStartReq(signal,subbPtr.i,0);
16710 }
16711 
16712 void Dbdict::execSUB_START_CONF(Signal* signal)
16713 {
16714  jamEntry();
16715 
16716  const SubStartConf* conf = (SubStartConf*) signal->getDataPtr();
16717  Uint32 senderRef = conf->senderRef;
16718  Uint32 buckets = conf->bucketCount;
16719  Uint32 nodegroup = conf->nodegroup;
16720 
16721  OpSubEventPtr subbPtr;
16722  c_opSubEvent.getPtr(subbPtr, conf->senderData);
16723 
16724  if (refToBlock(senderRef) == SUMA) {
16725  /*
16726  * Participant
16727  */
16728  jam();
16729  SubStartConf* conf = (SubStartConf*) signal->getDataPtrSend();
16730 
16731 #ifdef EVENT_PH3_DEBUG
16732  ndbout_c("DBDICT(Participant) got GSN_SUB_START_CONF = (%d)", subbPtr.i);
16733 #endif
16734 
16735  conf->senderRef = reference();
16736  conf->senderData = subbPtr.p->m_senderData;
16737  conf->bucketCount = buckets;
16738  conf->nodegroup = nodegroup;
16739 
16740  sendSignal(subbPtr.p->m_senderRef, GSN_SUB_START_CONF,
16741  signal, SubStartConf::SignalLength, JBB);
16742  c_opSubEvent.release(subbPtr);
16743  return;
16744  }
16745  /*
16746  * Coordinator
16747  */
16748  ndbrequire(refToBlock(senderRef) == DBDICT);
16749 #ifdef EVENT_PH3_DEBUG
16750  ndbout_c("DBDICT(Coordinator) got GSN_SUB_START_CONF = (%d)", subbPtr.i);
16751 #endif
16752 #define ARRAY_SIZE(x) (sizeof(x)/(sizeof(x[0])))
16753 
16754  if (buckets)
16755  {
16756  jam();
16757  ndbrequire(nodegroup < ARRAY_SIZE(subbPtr.p->m_buckets_per_ng));
16758  ndbrequire(subbPtr.p->m_buckets_per_ng[nodegroup] == 0 ||
16759  subbPtr.p->m_buckets_per_ng[nodegroup] == buckets);
16760  subbPtr.p->m_buckets_per_ng[nodegroup] = buckets;
16761  }
16762  subbPtr.p->m_sub_start_conf = *conf;
16763  subbPtr.p->m_reqTracker.reportConf(c_counterMgr, refToNode(senderRef));
16764  completeSubStartReq(signal,subbPtr.i,0);
16765 }
16766 
16767 /*
16768  * Coordinator
16769  */
16770 void Dbdict::completeSubStartReq(Signal* signal,
16771  Uint32 ptrI,
16772  Uint32 returnCode){
16773  jam();
16774 
16775  OpSubEventPtr subbPtr;
16776  c_opSubEvent.getPtr(subbPtr, ptrI);
16777 
16778  if (!subbPtr.p->m_reqTracker.done()){
16779  jam();
16780  return;
16781  }
16782 
16783  if (subbPtr.p->m_reqTracker.hasRef())
16784  {
16785  jam();
16786 #ifdef EVENT_DEBUG
16787  ndbout_c("SUB_START_REF");
16788 #endif
16789 
16790  if (subbPtr.p->m_reqTracker.hasConf())
16791  {
16792  jam();
16793  NodeReceiverGroup rg(DBDICT, subbPtr.p->m_reqTracker.m_confs);
16794  RequestTracker & p = subbPtr.p->m_reqTracker;
16795  ndbrequire(p.init<SubStopRef>(c_counterMgr, rg, GSN_SUB_STOP_REF,
16796  subbPtr.i));
16797 
16798  SubStopReq* req = (SubStopReq*) signal->getDataPtrSend();
16799 
16800  req->senderRef = reference();
16801  req->senderData = subbPtr.i;
16802  req->subscriptionId = subbPtr.p->m_subscriptionId;
16803  req->subscriptionKey = subbPtr.p->m_subscriptionKey;
16804  req->subscriberRef = subbPtr.p->m_subscriberRef;
16805  req->subscriberData = subbPtr.p->m_subscriberData;
16806  req->requestInfo = SubStopReq::RI_ABORT_START;
16807  sendSignal(rg, GSN_SUB_STOP_REQ, signal, SubStopReq::SignalLength, JBB);
16808  return;
16809  }
16810  else
16811  {
16812  jam();
16813  completeSubStopReq(signal, subbPtr.i, 0);
16814  return;
16815  }
16816  }
16817 #ifdef EVENT_DEBUG
16818  ndbout_c("SUB_START_CONF");
16819 #endif
16820 
16821  ndbrequire(c_outstanding_sub_startstop);
16822  c_outstanding_sub_startstop--;
16823  SubStartConf* conf = (SubStartConf*)signal->getDataPtrSend();
16824  * conf = subbPtr.p->m_sub_start_conf;
16825 
16826  Uint32 cnt = 0;
16827  for (Uint32 i = 0; i<ARRAY_SIZE(subbPtr.p->m_buckets_per_ng); i++)
16828  cnt += subbPtr.p->m_buckets_per_ng[i];
16829  conf->bucketCount = cnt;
16830 
16831  sendSignal(subbPtr.p->m_senderRef, GSN_SUB_START_CONF,
16832  signal, SubStartConf::SignalLength, JBB);
16833  c_opSubEvent.release(subbPtr);
16834 }
16835 
16836 /********************************************************************
16837  *
16838  * Stop event
16839  *
16840  *******************************************************************/
16841 
16842 void Dbdict::execSUB_STOP_REQ(Signal* signal)
16843 {
16844  jamEntry();
16845 
16846  Uint32 origSenderRef = signal->senderBlockRef();
16847 
16848  OpSubEventPtr subbPtr;
16849  Uint32 errCode = 0;
16850  if (!c_opSubEvent.seize(subbPtr)) {
16851  errCode = SubStopRef::Busy;
16852 busy:
16853  SubStopRef * ref = (SubStopRef *)signal->getDataPtrSend();
16854  jam();
16855  // ret->setErrorCode(SubStartRef::SeizeError);
16856  // ret->setErrorLine(__LINE__);
16857  // ret->setErrorNode(reference());
16858  ref->senderRef = reference();
16859  ref->errorCode = errCode;
16860  ref->m_masterNodeId = c_masterNodeId;
16861 
16862  sendSignal(origSenderRef, GSN_SUB_STOP_REF, signal,
16863  SubStopRef::SL_MasterNode, JBB);
16864  return;
16865  }
16866 
16867  {
16868  SubStopReq* req = (SubStopReq*) signal->getDataPtr();
16869  subbPtr.p->m_senderRef = req->senderRef;
16870  subbPtr.p->m_senderData = req->senderData;
16871  subbPtr.p->m_errorCode = 0;
16872  subbPtr.p->m_gsn = GSN_SUB_STOP_REQ;
16873  subbPtr.p->m_subscriptionId = req->subscriptionId;
16874  subbPtr.p->m_subscriptionKey = req->subscriptionKey;
16875  subbPtr.p->m_subscriberRef = req->subscriberRef;
16876  subbPtr.p->m_subscriberData = req->subscriberData;
16877  bzero(&subbPtr.p->m_sub_stop_conf, sizeof(subbPtr.p->m_sub_stop_conf));
16878 
16879  if (signal->getLength() < SubStopReq::SignalLength)
16880  {
16881  jam();
16882  req->requestInfo = 0;
16883  }
16884  }
16885 
16886  if (refToBlock(origSenderRef) != DBDICT) {
16887  /*
16888  * Coordinator
16889  */
16890  jam();
16891 
16892  if (c_masterNodeId != getOwnNodeId())
16893  {
16894  jam();
16895  c_opSubEvent.release(subbPtr);
16896  errCode = SubStopRef::NotMaster;
16897  goto busy;
16898  }
16899 
16900  if (!c_sub_startstop_lock.isclear())
16901  {
16902  jam();
16903  c_opSubEvent.release(subbPtr);
16904  errCode = SubStopRef::BusyWithNR;
16905  goto busy;
16906  }
16907 
16908 #ifdef EVENT_DEBUG
16909  ndbout_c("SUB_STOP_REQ 1");
16910 #endif
16911  subbPtr.p->m_senderRef = origSenderRef; // not sure if API sets correctly
16912  NodeReceiverGroup rg(DBDICT, c_aliveNodes);
16913  RequestTracker & p = subbPtr.p->m_reqTracker;
16914  if (!p.init<SubStopRef>(c_counterMgr, rg, GSN_SUB_STOP_REF, subbPtr.i))
16915  {
16916  jam();
16917  c_opSubEvent.release(subbPtr);
16918  errCode = SubStopRef::Busy;
16919  goto busy;
16920  }
16921 
16922  SubStopReq* req = (SubStopReq*) signal->getDataPtrSend();
16923 
16924  req->senderRef = reference();
16925  req->senderData = subbPtr.i;
16926 
16927  c_outstanding_sub_startstop++;
16928  sendSignal(rg, GSN_SUB_STOP_REQ, signal, SubStopReq::SignalLength, JBB);
16929  return;
16930  }
16931  /*
16932  * Participant
16933  */
16934 #ifdef EVENT_DEBUG
16935  ndbout_c("SUB_STOP_REQ 2");
16936 #endif
16937  ndbrequire(refToBlock(origSenderRef) == DBDICT);
16938 
16939  CRASH_INSERTION(6008);
16940 
16941  {
16942  SubStopReq* req = (SubStopReq*) signal->getDataPtrSend();
16943 
16944  req->senderRef = reference();
16945  req->senderData = subbPtr.i;
16946 
16947  sendSignal(SUMA_REF, GSN_SUB_STOP_REQ, signal, SubStopReq::SignalLength, JBB);
16948  }
16949 }
16950 
16951 void Dbdict::execSUB_STOP_REF(Signal* signal)
16952 {
16953  jamEntry();
16954  const SubStopRef* ref = (SubStopRef*) signal->getDataPtr();
16955  Uint32 senderRef = ref->senderRef;
16956  Uint32 err = ref->errorCode;
16957 
16958  OpSubEventPtr subbPtr;
16959  c_opSubEvent.getPtr(subbPtr, ref->senderData);
16960 
16961  if (refToBlock(senderRef) == SUMA)
16962  {
16963  /*
16964  * Participant
16965  */
16966  jam();
16967 
16968  if (upgrade_suma_NotStarted(err, subbPtr.p->m_senderRef))
16969  {
16970  jam();
16971  err = SubStopRef::NF_FakeErrorREF;
16972  }
16973 
16974  SubStopRef* ref = (SubStopRef*) signal->getDataPtrSend();
16975  ref->senderRef = reference();
16976  ref->senderData = subbPtr.p->m_senderData;
16977  ref->errorCode = err;
16978  sendSignal(subbPtr.p->m_senderRef, GSN_SUB_STOP_REF,
16979  signal, SubStopRef::SignalLength, JBB);
16980  c_opSubEvent.release(subbPtr);
16981  return;
16982  }
16983  /*
16984  * Coordinator
16985  */
16986  ndbrequire(refToBlock(senderRef) == DBDICT);
16987  if (err == SubStopRef::NF_FakeErrorREF || err == SubStopRef::NotStarted)
16988  {
16989  jam();
16990  subbPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(senderRef));
16991  }
16992  else
16993  {
16994  jam();
16995  if (subbPtr.p->m_errorCode == 0)
16996  {
16997  subbPtr.p->m_errorCode= err ? err : 1;
16998  }
16999  subbPtr.p->m_reqTracker.reportRef(c_counterMgr, refToNode(senderRef));
17000  }
17001  completeSubStopReq(signal,subbPtr.i,0);
17002 }
17003 
17004 void Dbdict::execSUB_STOP_CONF(Signal* signal)
17005 {
17006  jamEntry();
17007 
17008  const SubStopConf* conf = (SubStopConf*) signal->getDataPtr();
17009  Uint32 senderRef = conf->senderRef;
17010 
17011  OpSubEventPtr subbPtr;
17012  c_opSubEvent.getPtr(subbPtr, conf->senderData);
17013 
17014  if (refToBlock(senderRef) == SUMA) {
17015  /*
17016  * Participant
17017  */
17018  jam();
17019  SubStopConf* conf = (SubStopConf*) signal->getDataPtrSend();
17020 
17021  conf->senderRef = reference();
17022  conf->senderData = subbPtr.p->m_senderData;
17023 
17024  sendSignal(subbPtr.p->m_senderRef, GSN_SUB_STOP_CONF,
17025  signal, SubStopConf::SignalLength, JBB);
17026  c_opSubEvent.release(subbPtr);
17027  return;
17028  }
17029  /*
17030  * Coordinator
17031  */
17032  ndbrequire(refToBlock(senderRef) == DBDICT);
17033  Uint64 old_gci, new_gci = 0;
17034  {
17035  Uint32 old_gci_hi = subbPtr.p->m_sub_stop_conf.gci_hi;
17036  Uint32 old_gci_lo = subbPtr.p->m_sub_stop_conf.gci_lo;
17037  old_gci = old_gci_lo | (Uint64(old_gci_hi) << 32);
17038  if (signal->getLength() >= SubStopConf::SignalLengthWithGci)
17039  {
17040  Uint32 new_gci_hi = conf->gci_hi;
17041  Uint32 new_gci_lo = conf->gci_lo;
17042  new_gci = new_gci_lo | (Uint64(new_gci_hi) << 32);
17043  }
17044  }
17045  subbPtr.p->m_sub_stop_conf = *conf;
17046  if (old_gci > new_gci)
17047  {
17048  subbPtr.p->m_sub_stop_conf.gci_hi= Uint32(old_gci>>32);
17049  subbPtr.p->m_sub_stop_conf.gci_lo= Uint32(old_gci);
17050  }
17051  subbPtr.p->m_reqTracker.reportConf(c_counterMgr, refToNode(senderRef));
17052  completeSubStopReq(signal,subbPtr.i,0);
17053 }
17054 
17055 /*
17056  * Coordinator
17057  */
17058 void Dbdict::completeSubStopReq(Signal* signal,
17059  Uint32 ptrI,
17060  Uint32 returnCode){
17061  OpSubEventPtr subbPtr;
17062  c_opSubEvent.getPtr(subbPtr, ptrI);
17063 
17064  if (!subbPtr.p->m_reqTracker.done()){
17065  jam();
17066  return;
17067  }
17068 
17069  ndbrequire(c_outstanding_sub_startstop);
17070  c_outstanding_sub_startstop--;
17071 
17072  if (subbPtr.p->m_gsn == GSN_SUB_START_REQ)
17073  {
17074  jam();
17075  SubStartRef* ref = (SubStartRef*)signal->getDataPtrSend();
17076  ref->senderRef = reference();
17077  ref->senderData = subbPtr.p->m_senderData;
17078  ref->errorCode = subbPtr.p->m_errorCode;
17079 
17080  sendSignal(subbPtr.p->m_senderRef, GSN_SUB_START_REF,
17081  signal, SubStartRef::SignalLength, JBB);
17082  c_opSubEvent.release(subbPtr);
17083  return;
17084  }
17085 
17086  if (subbPtr.p->m_reqTracker.hasRef()) {
17087  jam();
17088 #ifdef EVENT_DEBUG
17089  ndbout_c("SUB_STOP_REF");
17090 #endif
17091  SubStopRef* ref = (SubStopRef*)signal->getDataPtrSend();
17092 
17093  ref->senderRef = reference();
17094  ref->senderData = subbPtr.p->m_senderData;
17095  ref->errorCode = subbPtr.p->m_errorCode;
17096 
17097  sendSignal(subbPtr.p->m_senderRef, GSN_SUB_STOP_REF,
17098  signal, SubStopRef::SignalLength, JBB);
17099  if (subbPtr.p->m_reqTracker.hasConf()) {
17100  // stopStartedNodes(signal);
17101  }
17102  c_opSubEvent.release(subbPtr);
17103  return;
17104  }
17105 #ifdef EVENT_DEBUG
17106  ndbout_c("SUB_STOP_CONF");
17107 #endif
17108  SubStopConf* conf = (SubStopConf*)signal->getDataPtrSend();
17109  * conf = subbPtr.p->m_sub_stop_conf;
17110  sendSignal(subbPtr.p->m_senderRef, GSN_SUB_STOP_CONF,
17111  signal, SubStopConf::SignalLength, JBB);
17112  c_opSubEvent.release(subbPtr);
17113 }
17114 
17115 /***************************************************************
17116  * MODULE: Drop event.
17117  *
17118  * Drop event.
17119  *
17120  * TODO
17121  */
17122 
17123 void
17124 Dbdict::execDROP_EVNT_REQ(Signal* signal)
17125 {
17126  jamEntry();
17127  DBUG_ENTER("Dbdict::execDROP_EVNT_REQ");
17128 
17129  DropEvntReq *req = (DropEvntReq*)signal->getDataPtr();
17130  const Uint32 senderRef = signal->senderBlockRef();
17131  OpDropEventPtr evntRecPtr;
17132  SectionHandle handle(this, signal);
17133 
17134  if (refToBlock(senderRef) != DBDICT &&
17135  getOwnNodeId() != c_masterNodeId)
17136  {
17137  jam();
17138  releaseSections(handle);
17139 
17140  DropEvntRef * ref = (DropEvntRef *)signal->getDataPtrSend();
17141  ref->setUserRef(reference());
17142  ref->setErrorCode(DropEvntRef::NotMaster);
17143  ref->setErrorLine(__LINE__);
17144  ref->setErrorNode(reference());
17145  ref->setMasterNode(c_masterNodeId);
17146  sendSignal(senderRef, GSN_DROP_EVNT_REF, signal,
17147  DropEvntRef::SignalLength2, JBB);
17148  DBUG_VOID_RETURN;
17149  }
17150 
17151  // Seize a Create Event record
17152  if (!c_opDropEvent.seize(evntRecPtr)) {
17153  // Failed to allocate event record
17154  jam();
17155  releaseSections(handle);
17156 
17157  DropEvntRef * ret = (DropEvntRef *)signal->getDataPtrSend();
17158  ret->setErrorCode(747);
17159  ret->setErrorLine(__LINE__);
17160  ret->setErrorNode(reference());
17161  sendSignal(senderRef, GSN_DROP_EVNT_REF, signal,
17162  DropEvntRef::SignalLength, JBB);
17163  DBUG_VOID_RETURN;
17164  }
17165 
17166 #ifdef EVENT_DEBUG
17167  ndbout_c("DBDICT::execDROP_EVNT_REQ evntRecId = (%d)", evntRecPtr.i);
17168 #endif
17169 
17170  OpDropEvent* evntRec = evntRecPtr.p;
17171  evntRec->init(req);
17172 
17173  SegmentedSectionPtr ssPtr;
17174 
17175  handle.getSection(ssPtr, 0);
17176 
17177  SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
17178 #ifdef EVENT_DEBUG
17179  r0.printAll(ndbout);
17180 #endif
17181  // event name
17182  if ((!r0.first()) ||
17183  (r0.getValueType() != SimpleProperties::StringValue) ||
17184  (r0.getValueLen() <= 0)) {
17185  jam();
17186  releaseSections(handle);
17187 
17188  evntRecPtr.p->m_errorCode = 1;
17189  evntRecPtr.p->m_errorLine = __LINE__;
17190  evntRecPtr.p->m_errorNode = reference();
17191 
17192  dropEvent_sendReply(signal, evntRecPtr);
17193  DBUG_VOID_RETURN;
17194  }
17195  r0.getString(evntRecPtr.p->m_eventRec.NAME);
17196  {
17197  int len = strlen(evntRecPtr.p->m_eventRec.NAME);
17198  memset(evntRecPtr.p->m_eventRec.NAME+len, 0, MAX_TAB_NAME_SIZE-len);
17199 #ifdef EVENT_DEBUG
17200  printf("DropEvntReq; EventName %s, len %u\n",
17201  evntRecPtr.p->m_eventRec.NAME, len);
17202  for(int i = 0; i < MAX_TAB_NAME_SIZE/4; i++)
17203  printf("H'%.8x ", ((Uint32*)evntRecPtr.p->m_eventRec.NAME)[i]);
17204  printf("\n");
17205 #endif
17206  }
17207 
17208  releaseSections(handle);
17209 
17210  Callback c = { safe_cast(&Dbdict::dropEventUTIL_PREPARE_READ), 0 };
17211 
17212  prepareTransactionEventSysTable(&c, signal, evntRecPtr.i,
17213  UtilPrepareReq::Read);
17214  DBUG_VOID_RETURN;
17215 }
17216 
17217 void
17218 Dbdict::dropEventUTIL_PREPARE_READ(Signal* signal,
17219  Uint32 callbackData,
17220  Uint32 returnCode)
17221 {
17222  jam();
17223  EVENT_TRACE;
17224  if (returnCode != 0) {
17225  EVENT_TRACE;
17226  dropEventUtilPrepareRef(signal, callbackData, returnCode);
17227  return;
17228  }
17229 
17230  UtilPrepareConf* const req = (UtilPrepareConf*)signal->getDataPtr();
17231  OpDropEventPtr evntRecPtr;
17232  evntRecPtr.i = req->getSenderData();
17233  const Uint32 prepareId = req->getPrepareId();
17234 
17235  ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
17236 
17237  Callback c = { safe_cast(&Dbdict::dropEventUTIL_EXECUTE_READ), 0 };
17238 
17239  executeTransEventSysTable(&c, signal,
17240  evntRecPtr.i, evntRecPtr.p->m_eventRec,
17241  prepareId, UtilPrepareReq::Read);
17242 }
17243 
17244 void
17245 Dbdict::dropEventUTIL_EXECUTE_READ(Signal* signal,
17246  Uint32 callbackData,
17247  Uint32 returnCode)
17248 {
17249  jam();
17250  EVENT_TRACE;
17251  if (returnCode != 0) {
17252  EVENT_TRACE;
17253  dropEventUtilExecuteRef(signal, callbackData, returnCode);
17254  return;
17255  }
17256 
17257  OpDropEventPtr evntRecPtr;
17258  UtilExecuteConf * const ref = (UtilExecuteConf *)signal->getDataPtr();
17259  jam();
17260  evntRecPtr.i = ref->getSenderData();
17261  ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
17262 
17263  parseReadEventSys(signal, evntRecPtr.p->m_eventRec);
17264 
17265  NodeReceiverGroup rg(DBDICT, c_aliveNodes);
17266  RequestTracker & p = evntRecPtr.p->m_reqTracker;
17267  if (!p.init<SubRemoveRef>(c_counterMgr, rg, GSN_SUB_REMOVE_REF,
17268  evntRecPtr.i))
17269  {
17270  evntRecPtr.p->m_errorCode = 701;
17271  dropEvent_sendReply(signal, evntRecPtr);
17272  return;
17273  }
17274 
17275  SubRemoveReq* req = (SubRemoveReq*) signal->getDataPtrSend();
17276 
17277  req->senderRef = reference();
17278  req->senderData = evntRecPtr.i;
17279  req->subscriptionId = evntRecPtr.p->m_eventRec.SUBID;
17280  req->subscriptionKey = evntRecPtr.p->m_eventRec.SUBKEY;
17281 
17282  sendSignal(rg, GSN_SUB_REMOVE_REQ, signal, SubRemoveReq::SignalLength, JBB);
17283 }
17284 
17285 /*
17286  * Participant
17287  */
17288 
17289 void
17290 Dbdict::execSUB_REMOVE_REQ(Signal* signal)
17291 {
17292  jamEntry();
17293  DBUG_ENTER("Dbdict::execSUB_REMOVE_REQ");
17294 
17295  Uint32 origSenderRef = signal->senderBlockRef();
17296 
17297  OpSubEventPtr subbPtr;
17298  if (!c_opSubEvent.seize(subbPtr)) {
17299  SubRemoveRef * ref = (SubRemoveRef *)signal->getDataPtrSend();
17300  jam();
17301  ref->senderRef = reference();
17302  ref->errorCode = SubRemoveRef::Busy;
17303 
17304  sendSignal(origSenderRef, GSN_SUB_REMOVE_REF, signal,
17305  SubRemoveRef::SignalLength, JBB);
17306  DBUG_VOID_RETURN;
17307  }
17308 
17309  {
17310  const SubRemoveReq* req = (SubRemoveReq*) signal->getDataPtr();
17311  subbPtr.p->m_senderRef = req->senderRef;
17312  subbPtr.p->m_senderData = req->senderData;
17313  subbPtr.p->m_errorCode = 0;
17314  subbPtr.p->m_gsn = GSN_SUB_REMOVE_REQ;
17315  subbPtr.p->m_subscriptionId = req->subscriptionId;
17316  subbPtr.p->m_subscriptionKey = req->subscriptionKey;
17317  subbPtr.p->m_subscriberRef = RNIL;
17318  subbPtr.p->m_subscriberData = RNIL;
17319  }
17320 
17321  CRASH_INSERTION2(6010, getOwnNodeId() != c_masterNodeId);
17322 
17323  SubRemoveReq* req = (SubRemoveReq*) signal->getDataPtrSend();
17324  req->senderRef = reference();
17325  req->senderData = subbPtr.i;
17326 
17327  sendSignal(SUMA_REF, GSN_SUB_REMOVE_REQ, signal, SubRemoveReq::SignalLength, JBB);
17328  DBUG_VOID_RETURN;
17329 }
17330 
17331 /*
17332  * Coordintor/Participant
17333  */
17334 
17335 void
17336 Dbdict::execSUB_REMOVE_REF(Signal* signal)
17337 {
17338  jamEntry();
17339  DBUG_ENTER("Dbdict::execSUB_REMOVE_REF");
17340 
17341  const SubRemoveRef* ref = (SubRemoveRef*) signal->getDataPtr();
17342  Uint32 senderRef = ref->senderRef;
17343  Uint32 err= ref->errorCode;
17344 
17345  if (refToBlock(senderRef) == SUMA)
17346  {
17347  /*
17348  * Participant
17349  */
17350  jam();
17351  OpSubEventPtr subbPtr;
17352  c_opSubEvent.getPtr(subbPtr, ref->senderData);
17353  if (err == SubRemoveRef::NoSuchSubscription)
17354  {
17355  jam();
17356  // conf this since this may occur if a nodefailure has occured
17357  // earlier so that the systable was not cleared
17358  SubRemoveConf* conf = (SubRemoveConf*) signal->getDataPtrSend();
17359  conf->senderRef = reference();
17360  conf->senderData = subbPtr.p->m_senderData;
17361  sendSignal(subbPtr.p->m_senderRef, GSN_SUB_REMOVE_CONF,
17362  signal, SubRemoveConf::SignalLength, JBB);
17363  }
17364  else
17365  {
17366  jam();
17367 
17368  if (upgrade_suma_NotStarted(err, subbPtr.p->m_senderRef))
17369  {
17370  jam();
17371  err = SubRemoveRef::NF_FakeErrorREF;
17372  }
17373 
17374  SubRemoveRef* ref = (SubRemoveRef*) signal->getDataPtrSend();
17375  ref->senderRef = reference();
17376  ref->senderData = subbPtr.p->m_senderData;
17377  ref->errorCode = err;
17378  sendSignal(subbPtr.p->m_senderRef, GSN_SUB_REMOVE_REF,
17379  signal, SubRemoveRef::SignalLength, JBB);
17380  }
17381  c_opSubEvent.release(subbPtr);
17382  DBUG_VOID_RETURN;
17383  }
17384  /*
17385  * Coordinator
17386  */
17387  ndbrequire(refToBlock(senderRef) == DBDICT);
17388  OpDropEventPtr eventRecPtr;
17389  c_opDropEvent.getPtr(eventRecPtr, ref->senderData);
17390  if (err == SubRemoveRef::NF_FakeErrorREF || err == SubRemoveRef::NotStarted)
17391  {
17392  jam();
17393  eventRecPtr.p->m_reqTracker.ignoreRef(c_counterMgr, refToNode(senderRef));
17394  }
17395  else
17396  {
17397  jam();
17398  if (eventRecPtr.p->m_errorCode == 0)
17399  {
17400  eventRecPtr.p->m_errorCode= err ? err : 1;
17401  eventRecPtr.p->m_errorLine= __LINE__;
17402  eventRecPtr.p->m_errorNode= reference();
17403  }
17404  eventRecPtr.p->m_reqTracker.reportRef(c_counterMgr, refToNode(senderRef));
17405  }
17406  completeSubRemoveReq(signal,eventRecPtr.i,0);
17407  DBUG_VOID_RETURN;
17408 }
17409 
17410 void
17411 Dbdict::execSUB_REMOVE_CONF(Signal* signal)
17412 {
17413  jamEntry();
17414  const SubRemoveConf* conf = (SubRemoveConf*) signal->getDataPtr();
17415  Uint32 senderRef = conf->senderRef;
17416 
17417  if (refToBlock(senderRef) == SUMA) {
17418  /*
17419  * Participant
17420  */
17421  jam();
17422  OpSubEventPtr subbPtr;
17423  c_opSubEvent.getPtr(subbPtr, conf->senderData);
17424  SubRemoveConf* conf = (SubRemoveConf*) signal->getDataPtrSend();
17425  conf->senderRef = reference();
17426  conf->senderData = subbPtr.p->m_senderData;
17427  sendSignal(subbPtr.p->m_senderRef, GSN_SUB_REMOVE_CONF,
17428  signal, SubRemoveConf::SignalLength, JBB);
17429  c_opSubEvent.release(subbPtr);
17430  return;
17431  }
17432  /*
17433  * Coordinator
17434  */
17435  ndbrequire(refToBlock(senderRef) == DBDICT);
17436  OpDropEventPtr eventRecPtr;
17437  c_opDropEvent.getPtr(eventRecPtr, conf->senderData);
17438  eventRecPtr.p->m_reqTracker.reportConf(c_counterMgr, refToNode(senderRef));
17439  completeSubRemoveReq(signal,eventRecPtr.i,0);
17440 }
17441 
17442 void
17443 Dbdict::completeSubRemoveReq(Signal* signal, Uint32 ptrI, Uint32 xxx)
17444 {
17445  OpDropEventPtr evntRecPtr;
17446  c_opDropEvent.getPtr(evntRecPtr, ptrI);
17447 
17448  if (!evntRecPtr.p->m_reqTracker.done()){
17449  jam();
17450  return;
17451  }
17452 
17453  if (evntRecPtr.p->m_reqTracker.hasRef()) {
17454  jam();
17455  if ( evntRecPtr.p->m_errorCode == 0 )
17456  {
17457  evntRecPtr.p->m_errorNode = reference();
17458  evntRecPtr.p->m_errorLine = __LINE__;
17459  evntRecPtr.p->m_errorCode = 1;
17460  }
17461  dropEvent_sendReply(signal, evntRecPtr);
17462  return;
17463  }
17464 
17465  Callback c = { safe_cast(&Dbdict::dropEventUTIL_PREPARE_DELETE), 0 };
17466 
17467  prepareTransactionEventSysTable(&c, signal, evntRecPtr.i,
17468  UtilPrepareReq::Delete);
17469 }
17470 
17471 void
17472 Dbdict::dropEventUTIL_PREPARE_DELETE(Signal* signal,
17473  Uint32 callbackData,
17474  Uint32 returnCode)
17475 {
17476  jam();
17477  EVENT_TRACE;
17478  if (returnCode != 0) {
17479  EVENT_TRACE;
17480  dropEventUtilPrepareRef(signal, callbackData, returnCode);
17481  return;
17482  }
17483 
17484  UtilPrepareConf* const req = (UtilPrepareConf*)signal->getDataPtr();
17485  OpDropEventPtr evntRecPtr;
17486  jam();
17487  evntRecPtr.i = req->getSenderData();
17488  const Uint32 prepareId = req->getPrepareId();
17489 
17490  ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
17491 #ifdef EVENT_DEBUG
17492  printf("DropEvntUTIL_PREPARE; evntRecPtr.i len %u\n",evntRecPtr.i);
17493 #endif
17494 
17495  Callback c = { safe_cast(&Dbdict::dropEventUTIL_EXECUTE_DELETE), 0 };
17496 
17497  executeTransEventSysTable(&c, signal,
17498  evntRecPtr.i, evntRecPtr.p->m_eventRec,
17499  prepareId, UtilPrepareReq::Delete);
17500 }
17501 
17502 void
17503 Dbdict::dropEventUTIL_EXECUTE_DELETE(Signal* signal,
17504  Uint32 callbackData,
17505  Uint32 returnCode)
17506 {
17507  jam();
17508  EVENT_TRACE;
17509  if (returnCode != 0) {
17510  EVENT_TRACE;
17511  dropEventUtilExecuteRef(signal, callbackData, returnCode);
17512  return;
17513  }
17514 
17515  OpDropEventPtr evntRecPtr;
17516  UtilExecuteConf * const ref = (UtilExecuteConf *)signal->getDataPtr();
17517  jam();
17518  evntRecPtr.i = ref->getSenderData();
17519  ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
17520 
17521  dropEvent_sendReply(signal, evntRecPtr);
17522 }
17523 
17524 void
17525 Dbdict::dropEventUtilPrepareRef(Signal* signal,
17526  Uint32 callbackData,
17527  Uint32 returnCode)
17528 {
17529  jam();
17530  EVENT_TRACE;
17531  UtilPrepareRef * const ref = (UtilPrepareRef *)signal->getDataPtr();
17532  OpDropEventPtr evntRecPtr;
17533  evntRecPtr.i = ref->getSenderData();
17534  ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
17535 
17536  interpretUtilPrepareErrorCode((UtilPrepareRef::ErrorCode)ref->getErrorCode(),
17537  evntRecPtr.p->m_errorCode,
17538  evntRecPtr.p->m_errorLine, this);
17539  evntRecPtr.p->m_errorNode = reference();
17540 
17541  dropEvent_sendReply(signal, evntRecPtr);
17542 }
17543 
17544 void
17545 Dbdict::dropEventUtilExecuteRef(Signal* signal,
17546  Uint32 callbackData,
17547  Uint32 returnCode)
17548 {
17549  jam();
17550  EVENT_TRACE;
17551  OpDropEventPtr evntRecPtr;
17552  UtilExecuteRef * const ref = (UtilExecuteRef *)signal->getDataPtr();
17553  jam();
17554  evntRecPtr.i = ref->getSenderData();
17555  ndbrequire((evntRecPtr.p = c_opDropEvent.getPtr(evntRecPtr.i)) != NULL);
17556 
17557  evntRecPtr.p->m_errorNode = reference();
17558  evntRecPtr.p->m_errorLine = __LINE__;
17559 
17560  switch (ref->getErrorCode()) {
17561  case UtilExecuteRef::TCError:
17562  switch (ref->getTCErrorCode()) {
17563  case ZNOT_FOUND:
17564  jam();
17565  evntRecPtr.p->m_errorCode = 4710;
17566  break;
17567  default:
17568  jam();
17569  evntRecPtr.p->m_errorCode = ref->getTCErrorCode();
17570  break;
17571  }
17572  break;
17573  default:
17574  jam();
17575  evntRecPtr.p->m_errorCode = ref->getErrorCode();
17576  break;
17577  }
17578  dropEvent_sendReply(signal, evntRecPtr);
17579 }
17580 
17581 void Dbdict::dropEvent_sendReply(Signal* signal,
17582  OpDropEventPtr evntRecPtr)
17583 {
17584  jam();
17585  EVENT_TRACE;
17586  Uint32 senderRef = evntRecPtr.p->m_request.getUserRef();
17587 
17588  if (evntRecPtr.p->hasError()) {
17589  jam();
17590  DropEvntRef * ret = (DropEvntRef *)signal->getDataPtrSend();
17591 
17592  ret->setUserData(evntRecPtr.p->m_request.getUserData());
17593  ret->setUserRef(evntRecPtr.p->m_request.getUserRef());
17594 
17595  ret->setErrorCode(evntRecPtr.p->m_errorCode);
17596  ret->setErrorLine(evntRecPtr.p->m_errorLine);
17597  ret->setErrorNode(evntRecPtr.p->m_errorNode);
17598 
17599  sendSignal(senderRef, GSN_DROP_EVNT_REF, signal,
17600  DropEvntRef::SignalLength, JBB);
17601  } else {
17602  jam();
17603  DropEvntConf * evntConf = (DropEvntConf *)signal->getDataPtrSend();
17604 
17605  evntConf->setUserData(evntRecPtr.p->m_request.getUserData());
17606  evntConf->setUserRef(evntRecPtr.p->m_request.getUserRef());
17607 
17608  sendSignal(senderRef, GSN_DROP_EVNT_CONF, signal,
17609  DropEvntConf::SignalLength, JBB);
17610  }
17611 
17612  c_opDropEvent.release(evntRecPtr);
17613 }
17614 
17615 // MODULE: CreateTrigger
17616 
17617 const Dbdict::OpInfo
17618 Dbdict::CreateTriggerRec::g_opInfo = {
17619  { 'C', 'T', 'r', 0 },
17620  GSN_CREATE_TRIG_IMPL_REQ,
17621  CreateTrigImplReq::SignalLength,
17622  //
17623  &Dbdict::createTrigger_seize,
17624  &Dbdict::createTrigger_release,
17625  //
17626  &Dbdict::createTrigger_parse,
17627  &Dbdict::createTrigger_subOps,
17628  &Dbdict::createTrigger_reply,
17629  //
17630  &Dbdict::createTrigger_prepare,
17631  &Dbdict::createTrigger_commit,
17632  &Dbdict::createTrigger_complete,
17633  //
17634  &Dbdict::createTrigger_abortParse,
17635  &Dbdict::createTrigger_abortPrepare
17636 };
17637 
17638 bool
17639 Dbdict::createTrigger_seize(SchemaOpPtr op_ptr)
17640 {
17641  return seizeOpRec<CreateTriggerRec>(op_ptr);
17642 }
17643 
17644 void
17645 Dbdict::createTrigger_release(SchemaOpPtr op_ptr)
17646 {
17647  releaseOpRec<CreateTriggerRec>(op_ptr);
17648 }
17649 
17650 void
17651 Dbdict::execCREATE_TRIG_REQ(Signal* signal)
17652 {
17653  jamEntry();
17654  if (!assembleFragments(signal)) {
17655  jam();
17656  return;
17657  }
17658  SectionHandle handle(this, signal);
17659 
17660  const CreateTrigReq req_copy =
17661  *(const CreateTrigReq*)signal->getDataPtr();
17662  const CreateTrigReq* req = &req_copy;
17663 
17664  ErrorInfo error;
17665  do {
17666  SchemaOpPtr op_ptr;
17667  CreateTriggerRecPtr createTriggerPtr;
17668  CreateTrigImplReq* impl_req;
17669 
17670  startClientReq(op_ptr, createTriggerPtr, req, impl_req, error);
17671  if (hasError(error)) {
17672  jam();
17673  break;
17674  }
17675 
17676  impl_req->tableId = req->tableId;
17677  impl_req->tableVersion = req->tableVersion;
17678  impl_req->indexId = req->indexId;
17679  impl_req->indexVersion = req->indexVersion;
17680  impl_req->triggerNo = req->triggerNo;
17681  impl_req->triggerId = req->forceTriggerId;
17682  impl_req->triggerInfo = req->triggerInfo;
17683  impl_req->receiverRef = req->receiverRef;
17684 
17685  handleClientReq(signal, op_ptr, handle);
17686  return;
17687  } while (0);
17688 
17689  releaseSections(handle);
17690 
17691  CreateTrigRef* ref = (CreateTrigRef*)signal->getDataPtrSend();
17692 
17693  ref->senderRef = reference();
17694  ref->clientData = req->clientData;
17695  ref->transId = req->transId;
17696  ref->tableId = req->tableId;
17697  ref->indexId = req->indexId;
17698  ref->triggerInfo = req->triggerInfo;
17699  getError(error, ref);
17700 
17701  sendSignal(req->clientRef, GSN_CREATE_TRIG_REF, signal,
17702  CreateTrigRef::SignalLength, JBB);
17703 }
17704 
17705 // CreateTrigger: PARSE
17706 
17707 void
17708 Dbdict::createTrigger_parse(Signal* signal, bool master,
17709  SchemaOpPtr op_ptr,
17710  SectionHandle& handle, ErrorInfo& error)
17711 {
17712  D("createTrigger_parse" << V(op_ptr.i) << *op_ptr.p);
17713 
17714  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
17715  CreateTriggerRecPtr createTriggerPtr;
17716  getOpRec(op_ptr, createTriggerPtr);
17717  CreateTrigImplReq* impl_req = &createTriggerPtr.p->m_request;
17718 
17719  // check request type
17720  Uint32 requestType = impl_req->requestType;
17721  switch (CreateTrigReq::getOnlineFlag(requestType)) {
17722  case CreateTrigImplReq::CreateTriggerOnline:
17723  break;
17724  case CreateTrigImplReq::CreateTriggerOffline:
17725  jam();
17726  default:
17727  ndbassert(false);
17728  setError(error, CreateTrigRef::BadRequestType, __LINE__);
17729  return;
17730  }
17731 
17732  // check the table
17733  {
17734  const Uint32 tableId = impl_req->tableId;
17735  if (! (tableId < c_tableRecordPool.getSize()))
17736  {
17737  jam();
17738  setError(error, CreateTrigRef::InvalidTable, __LINE__);
17739  return;
17740  }
17741 
17742  Uint32 err;
17743  if ((err = check_read_obj(tableId, trans_ptr.p->m_transId)))
17744  {
17745  jam();
17746  setError(error, err, __LINE__);
17747  return;
17748  }
17749  }
17750 
17751  switch(CreateTrigReq::getEndpointFlag(requestType)){
17752  case CreateTrigReq::MainTrigger:
17753  jam();
17754  createTriggerPtr.p->m_main_op = true;
17755  break;
17756  case CreateTrigReq::TriggerDst:
17757  jam();
17758  case CreateTrigReq::TriggerSrc:
17759  jam();
17760  if (handle.m_cnt)
17761  {
17762  jam();
17763  ndbassert(false);
17764  setError(error, CreateTrigRef::BadRequestType, __LINE__);
17765  return;
17766  }
17767  createTriggerPtr.p->m_main_op = false;
17768  createTrigger_parse_endpoint(signal, op_ptr, error);
17769  return;
17770  }
17771 
17772  SegmentedSectionPtr ss_ptr;
17773  handle.getSection(ss_ptr, CreateTrigReq::TRIGGER_NAME_SECTION);
17774  SimplePropertiesSectionReader r(ss_ptr, getSectionSegmentPool());
17775  DictTabInfo::Table tableDesc;
17776  tableDesc.init();
17778  SimpleProperties::unpack(r, &tableDesc,
17779  DictTabInfo::TableMapping,
17780  DictTabInfo::TableMappingSize,
17781  true, true);
17782 
17783  if (status != SimpleProperties::Eof ||
17784  tableDesc.TableName[0] == 0)
17785  {
17786  jam();
17787  ndbassert(false);
17788  setError(error, CreateTrigRef::InvalidName, __LINE__);
17789  return;
17790  }
17791  const Uint32 bytesize = sizeof(createTriggerPtr.p->m_triggerName);
17792  memcpy(createTriggerPtr.p->m_triggerName, tableDesc.TableName, bytesize);
17793  D("trigger " << createTriggerPtr.p->m_triggerName);
17794 
17795  // check name is unique
17796  if (get_object(createTriggerPtr.p->m_triggerName) != 0) {
17797  jam();
17798  D("duplicate trigger name " << createTriggerPtr.p->m_triggerName);
17799  setError(error, CreateTrigRef::TriggerExists, __LINE__);
17800  return;
17801  }
17802 
17803  TriggerRecordPtr triggerPtr;
17804  if (master)
17805  {
17806  jam();
17807  if (impl_req->triggerId == RNIL)
17808  {
17809  jam();
17810  impl_req->triggerId = getFreeTriggerRecord();
17811  if (impl_req->triggerId == RNIL)
17812  {
17813  jam();
17814  setError(error, CreateTrigRef::TooManyTriggers, __LINE__);
17815  return;
17816  }
17817  c_triggerRecordPool.getPtr(triggerPtr, impl_req->triggerId);
17818  ndbrequire(triggerPtr.p->triggerState == TriggerRecord::TS_NOT_DEFINED);
17819  D("master allocated triggerId " << impl_req->triggerId);
17820  }
17821  else
17822  {
17823  if (!(impl_req->triggerId < c_triggerRecordPool.getSize()))
17824  {
17825  jam();
17826  setError(error, CreateTrigRef::TooManyTriggers, __LINE__);
17827  return;
17828  }
17829  c_triggerRecordPool.getPtr(triggerPtr, impl_req->triggerId);
17830  if (triggerPtr.p->triggerState != TriggerRecord::TS_NOT_DEFINED)
17831  {
17832  jam();
17833  setError(error, CreateTrigRef::TriggerExists, __LINE__);
17834  return;
17835  }
17836  D("master forced triggerId " << impl_req->triggerId);
17837  }
17838  }
17839  else
17840  {
17841  jam();
17842  // slave receives trigger id from master
17843  if (! (impl_req->triggerId < c_triggerRecordPool.getSize()))
17844  {
17845  jam();
17846  setError(error, CreateTrigRef::TooManyTriggers, __LINE__);
17847  return;
17848  }
17849  c_triggerRecordPool.getPtr(triggerPtr, impl_req->triggerId);
17850  if (triggerPtr.p->triggerState != TriggerRecord::TS_NOT_DEFINED)
17851  {
17852  jam();
17853  setError(error, CreateTrigRef::TriggerExists, __LINE__);
17854  return;
17855  }
17856  D("slave allocated triggerId " << hex << impl_req->triggerId);
17857  }
17858 
17859  initialiseTriggerRecord(triggerPtr);
17860 
17861  triggerPtr.p->triggerId = impl_req->triggerId;
17862  triggerPtr.p->tableId = impl_req->tableId;
17863  triggerPtr.p->indexId = RNIL; // feedback method connects to index
17864  triggerPtr.p->triggerInfo = impl_req->triggerInfo;
17865  triggerPtr.p->receiverRef = impl_req->receiverRef;
17866  triggerPtr.p->triggerState = TriggerRecord::TS_DEFINING;
17867 
17868  if (handle.m_cnt >= 2)
17869  {
17870  jam();
17871  SegmentedSectionPtr mask_ptr;
17872  handle.getSection(mask_ptr, CreateTrigReq::ATTRIBUTE_MASK_SECTION);
17873  if (mask_ptr.sz > triggerPtr.p->attributeMask.getSizeInWords())
17874  {
17875  jam();
17876  setError(error, CreateTrigRef::BadRequestType, __LINE__);
17877  return;
17878  }
17879  ::copy(triggerPtr.p->attributeMask.rep.data, mask_ptr);
17880  if (mask_ptr.sz < triggerPtr.p->attributeMask.getSizeInWords())
17881  {
17882  jam();
17883  Uint32 len = triggerPtr.p->attributeMask.getSizeInWords() - mask_ptr.sz;
17884  bzero(triggerPtr.p->attributeMask.rep.data + mask_ptr.sz,
17885  4 * len);
17886  }
17887  }
17888  else
17889  {
17890  jam();
17891  setError(error, CreateTrigRef::BadRequestType, __LINE__);
17892  return;
17893  }
17894 
17895  {
17896  Rope name(c_rope_pool, triggerPtr.p->triggerName);
17897  if (!name.assign(createTriggerPtr.p->m_triggerName)) {
17898  jam();
17899  setError(error, CreateTrigRef::OutOfStringBuffer, __LINE__);
17900  return;
17901  }
17902  }
17903 
17904  // connect to new DictObject
17905  {
17906  Ptr<DictObject> obj_ptr;
17907  seizeDictObject(op_ptr, obj_ptr, triggerPtr.p->triggerName);
17908 
17909  obj_ptr.p->m_id = impl_req->triggerId; // wl3600_todo id
17910  obj_ptr.p->m_type =
17911  TriggerInfo::getTriggerType(triggerPtr.p->triggerInfo);
17912  triggerPtr.p->m_obj_ptr_i = obj_ptr.i;
17913  }
17914 
17915  {
17916  TriggerType::Value type =
17917  TriggerInfo::getTriggerType(triggerPtr.p->triggerInfo);
17918  switch(type){
17919  case TriggerType::REORG_TRIGGER:
17920  jam();
17921  createTrigger_create_drop_trigger_operation(signal, op_ptr, error);
17922  case TriggerType::SECONDARY_INDEX:
17923  jam();
17924  createTriggerPtr.p->m_sub_dst = false;
17925  createTriggerPtr.p->m_sub_src = false;
17926  break;
17927  case TriggerType::ORDERED_INDEX:
17928  case TriggerType::READ_ONLY_CONSTRAINT:
17929  jam();
17930  createTriggerPtr.p->m_sub_dst = true; // Only need LQH
17931  createTriggerPtr.p->m_sub_src = false;
17932  break;
17933  default:
17934  case TriggerType::SUBSCRIPTION:
17935  case TriggerType::SUBSCRIPTION_BEFORE:
17936  ndbassert(false);
17937  setError(error, CreateTrigRef::UnsupportedTriggerType, __LINE__);
17938  return;
17939  }
17940  }
17941 
17942  if (ERROR_INSERTED(6124))
17943  {
17944  jam();
17945  CLEAR_ERROR_INSERT_VALUE;
17946  setError(error, 9124, __LINE__);
17947  return;
17948  }
17949 
17950  if (impl_req->indexId != RNIL)
17951  {
17952  TableRecordPtr indexPtr;
17953  c_tableRecordPool.getPtr(indexPtr, impl_req->indexId);
17954  triggerPtr.p->indexId = impl_req->indexId;
17955  indexPtr.p->triggerId = impl_req->triggerId;
17956  }
17957 }
17958 
17959 void
17960 Dbdict::createTrigger_parse_endpoint(Signal* signal,
17961  SchemaOpPtr op_ptr,
17962  ErrorInfo& error)
17963 {
17964  jam();
17965 
17966  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
17967  CreateTriggerRecPtr createTriggerPtr;
17968  getOpRec(op_ptr, createTriggerPtr);
17969  CreateTrigImplReq* impl_req = &createTriggerPtr.p->m_request;
17970 
17971  // check request type
17972  Uint32 requestType = impl_req->requestType;
17973  switch(CreateTrigReq::getEndpointFlag(requestType)){
17974  case CreateTrigReq::TriggerDst:
17975  jam();
17976  createTriggerPtr.p->m_block_list[0] = DBTC_REF;
17977  break;
17978  case CreateTrigReq::TriggerSrc:
17979  jam();
17980  createTriggerPtr.p->m_block_list[0] = DBLQH_REF;
17981  break;
17982  default:
17983  ndbassert(false);
17984  setError(error, CreateTrigRef::BadRequestType, __LINE__);
17985  return;
17986  }
17987 
17988  Ptr<TriggerRecord> triggerPtr;
17989  c_triggerRecordPool.getPtr(triggerPtr, impl_req->triggerId);
17990  switch(TriggerInfo::getTriggerType(triggerPtr.p->triggerInfo)){
17991  case TriggerType::REORG_TRIGGER:
17992  jam();
17993  createTrigger_create_drop_trigger_operation(signal, op_ptr, error);
17994  return;
17995  default:
17996  return;
17997  }
17998 }
17999 
18000 void
18001 Dbdict::createTrigger_create_drop_trigger_operation(Signal* signal,
18002  SchemaOpPtr op_ptr,
18003  ErrorInfo& error)
18004 {
18005  jam();
18006 
18007  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
18008  CreateTriggerRecPtr createTriggerPtr;
18009  getOpRec(op_ptr, createTriggerPtr);
18010  CreateTrigImplReq* impl_req = &createTriggerPtr.p->m_request;
18011 
18015  SchemaOpPtr& oplnk_ptr = op_ptr.p->m_oplnk_ptr;
18016  ndbrequire(oplnk_ptr.isNull());
18017  DropTriggerRecPtr dropTriggerPtr;
18018  seizeSchemaOp(oplnk_ptr, dropTriggerPtr);
18019  if (oplnk_ptr.isNull())
18020  {
18021  jam();
18022  setError(error, CreateTrigRef::TooManyTriggers, __LINE__);
18023  return;
18024  }
18025 
18026 
18027  DropTrigImplReq* aux_impl_req = &dropTriggerPtr.p->m_request;
18028  aux_impl_req->senderRef = reference();
18029  aux_impl_req->senderData = op_ptr.p->op_key;
18030  aux_impl_req->requestType = 0;
18031  aux_impl_req->tableId = impl_req->tableId;
18032  aux_impl_req->tableVersion = 0; // not used
18033  aux_impl_req->indexId = 0;
18034  aux_impl_req->indexVersion = 0; // not used
18035  aux_impl_req->triggerNo = 0;
18036  aux_impl_req->triggerId = impl_req->triggerId;
18037  aux_impl_req->triggerInfo = impl_req->triggerInfo;
18038 
18039  // link other way too
18040  oplnk_ptr.p->m_opbck_ptr = op_ptr;
18041  oplnk_ptr.p->m_trans_ptr = trans_ptr;
18042  dropTriggerPtr.p->m_main_op = createTriggerPtr.p->m_main_op;
18043 
18044  if (createTriggerPtr.p->m_main_op)
18045  {
18046  jam();
18047  return;
18048  }
18049 
18050  switch(refToBlock(createTriggerPtr.p->m_block_list[0])){
18051  case DBTC:
18052  jam();
18053  dropTriggerPtr.p->m_block_list[0] = DBLQH_REF;
18054  break;
18055  case DBLQH:
18056  jam();
18057  dropTriggerPtr.p->m_block_list[0] = DBTC_REF;
18058  break;
18059  default:
18060  ndbassert(false);
18061  setError(error, CreateTrigRef::BadRequestType, __LINE__);
18062  return;
18063  }
18064 }
18065 
18066 bool
18067 Dbdict::createTrigger_subOps(Signal* signal, SchemaOpPtr op_ptr)
18068 {
18069  D("createTrigger_subOps" << V(op_ptr.i) << *op_ptr.p);
18070 
18071  CreateTriggerRecPtr createTriggerPtr;
18072  getOpRec(op_ptr, createTriggerPtr);
18073 
18074  Uint32 requestType =
18075  DictSignal::getRequestType(createTriggerPtr.p->m_request.requestType);
18076  switch(CreateTrigReq::getEndpointFlag(requestType)){
18077  case CreateTrigReq::MainTrigger:
18078  jam();
18079  break;
18080  case CreateTrigReq::TriggerDst:
18081  case CreateTrigReq::TriggerSrc:
18082  jam();
18083  return false;
18084  }
18085 
18089  if (!createTriggerPtr.p->m_sub_dst)
18090  {
18091  jam();
18092  createTriggerPtr.p->m_sub_dst = true;
18093  Callback c = {
18094  safe_cast(&Dbdict::createTrigger_fromCreateEndpoint),
18095  op_ptr.p->op_key
18096  };
18097  op_ptr.p->m_callback = c;
18098  createTrigger_toCreateEndpoint(signal, op_ptr,
18099  CreateTrigReq::TriggerDst);
18100  return true;
18101  }
18102 
18103  if (!createTriggerPtr.p->m_sub_src)
18104  {
18105  jam();
18106  createTriggerPtr.p->m_sub_src = true;
18107  Callback c = {
18108  safe_cast(&Dbdict::createTrigger_fromCreateEndpoint),
18109  op_ptr.p->op_key
18110  };
18111  op_ptr.p->m_callback = c;
18112  createTrigger_toCreateEndpoint(signal, op_ptr,
18113  CreateTrigReq::TriggerSrc);
18114  return true;
18115  }
18116 
18117  return false;
18118 }
18119 
18120 void
18121 Dbdict::createTrigger_toCreateEndpoint(Signal* signal,
18122  SchemaOpPtr op_ptr,
18123  CreateTrigReq::EndpointFlag endpoint)
18124 {
18125  D("alterIndex_toCreateTrigger");
18126 
18127  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
18128  CreateTriggerRecPtr createTriggerPtr;
18129  getOpRec(op_ptr, createTriggerPtr);
18130  const CreateTrigImplReq* impl_req = &createTriggerPtr.p->m_request;
18131 
18132  CreateTrigReq* req = (CreateTrigReq*)signal->getDataPtrSend();
18133 
18134  Uint32 type = 0;
18135  CreateTrigReq::setOnlineFlag(type, CreateTrigReq::CreateTriggerOnline);
18136  CreateTrigReq::setEndpointFlag(type, endpoint);
18137 
18138  Uint32 requestInfo = 0;
18139  DictSignal::setRequestType(requestInfo, type);
18140  DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
18141 
18142  req->clientRef = reference();
18143  req->clientData = op_ptr.p->op_key;
18144  req->transId = trans_ptr.p->m_transId;
18145  req->transKey = trans_ptr.p->trans_key;
18146  req->requestInfo = requestInfo;
18147  req->tableId = impl_req->tableId;
18148  req->tableVersion = impl_req->tableVersion;
18149  req->indexId = impl_req->indexId;
18150  req->indexVersion = impl_req->indexVersion;
18151  req->forceTriggerId = impl_req->triggerId;
18152  req->triggerInfo = impl_req->triggerInfo;
18153 
18154  sendSignal(reference(), GSN_CREATE_TRIG_REQ, signal,
18155  CreateTrigReq::SignalLength, JBB);
18156 }
18157 
18158 void
18159 Dbdict::createTrigger_fromCreateEndpoint(Signal* signal,
18160  Uint32 op_key, Uint32 ret)
18161 {
18162  SchemaOpPtr op_ptr;
18163  CreateTriggerRecPtr createTriggerPtr;
18164  findSchemaOp(op_ptr, createTriggerPtr, op_key);
18165  ndbrequire(!op_ptr.isNull());
18166  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
18167 
18168  if (ret == 0)
18169  {
18170  jam();
18171  const CreateTrigConf* conf =
18172  (const CreateTrigConf*)signal->getDataPtr();
18173 
18174  ndbrequire(conf->transId == trans_ptr.p->m_transId);
18175  createSubOps(signal, op_ptr);
18176  }
18177  else
18178  {
18179  jam();
18180  const CreateTrigRef* ref =
18181  (const CreateTrigRef*)signal->getDataPtr();
18182  ErrorInfo error;
18183  setError(error, ref);
18184  abortSubOps(signal, op_ptr, error);
18185  }
18186 }
18187 
18188 void
18189 Dbdict::createTrigger_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
18190 {
18191  jam();
18192 
18193  SchemaTransPtr& trans_ptr = op_ptr.p->m_trans_ptr;
18194  CreateTriggerRecPtr createTriggerPtr;
18195  getOpRec(op_ptr, createTriggerPtr);
18196  const CreateTrigImplReq* impl_req = &createTriggerPtr.p->m_request;
18197 
18198  D("createTrigger_reply" << V(impl_req->triggerId) << *op_ptr.p);
18199 
18200  if (!hasError(error)) {
18201  CreateTrigConf* conf = (CreateTrigConf*)signal->getDataPtrSend();
18202  conf->senderRef = reference();
18203  conf->clientData = op_ptr.p->m_clientData;
18204  conf->transId = trans_ptr.p->m_transId;
18205  conf->tableId = impl_req->tableId;
18206  conf->indexId = impl_req->indexId;
18207  conf->triggerId = impl_req->triggerId;
18208  conf->triggerInfo = impl_req->triggerInfo;
18209 
18210  Uint32 clientRef = op_ptr.p->m_clientRef;
18211  sendSignal(clientRef, GSN_CREATE_TRIG_CONF, signal,
18212  CreateTrigConf::SignalLength, JBB);
18213  } else {
18214  jam();
18215  CreateTrigRef* ref = (CreateTrigRef*)signal->getDataPtrSend();
18216  ref->senderRef = reference();
18217  ref->clientData = op_ptr.p->m_clientData;
18218  ref->transId = trans_ptr.p->m_transId;
18219  ref->tableId = impl_req->tableId;
18220  ref->indexId = impl_req->indexId;
18221  ref->triggerInfo =impl_req->triggerInfo;
18222  getError(error, ref);
18223 
18224  Uint32 clientRef = op_ptr.p->m_clientRef;
18225  sendSignal(clientRef, GSN_CREATE_TRIG_REF, signal,
18226  CreateTrigRef::SignalLength, JBB);
18227  }
18228 }
18229 
18230 // CreateTrigger: PREPARE
18231 
18232 void
18233 Dbdict::createTrigger_prepare(Signal* signal, SchemaOpPtr op_ptr)
18234 {
18235  jam();
18236  CreateTriggerRecPtr createTriggerPtr;
18237  getOpRec(op_ptr, createTriggerPtr);
18238 
18239  if (createTriggerPtr.p->m_main_op)
18240  {
18241  jam();
18242  sendTransConf(signal, op_ptr);
18243  return;
18244  }
18245 
18246  if (ERROR_INSERTED(6213))
18247  {
18248  CLEAR_ERROR_INSERT_VALUE;
18249  setError(op_ptr, 1, __LINE__);
18250  sendTransRef(signal, op_ptr);
18251  return;
18252  }
18253 
18254  Callback c = { safe_cast(&Dbdict::createTrigger_prepare_fromLocal),
18255  op_ptr.p->op_key
18256  };
18257 
18258  op_ptr.p->m_callback = c;
18259  send_create_trig_req(signal, op_ptr);
18260 }
18261 
18262 void
18263 Dbdict::createTrigger_prepare_fromLocal(Signal* signal,
18264  Uint32 op_key, Uint32 ret)
18265 {
18266  SchemaOpPtr op_ptr;
18267  CreateTriggerRecPtr createTriggerPtr;
18268  findSchemaOp(op_ptr, createTriggerPtr, op_key);
18269  ndbrequire(!op_ptr.isNull());
18270  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
18271 
18272  if (ret == 0)
18273  {
18274  jam();
18275  createTriggerPtr.p->m_created = true;
18276  sendTransConf(signal, op_ptr);
18277  }
18278  else
18279  {
18280  jam();
18281  setError(op_ptr, ret, __LINE__);
18282  sendTransRef(signal, op_ptr);
18283  }
18284 }
18285 
18286 // CreateTrigger: COMMIT
18287 
18288 void
18289 Dbdict::createTrigger_commit(Signal* signal, SchemaOpPtr op_ptr)
18290 {
18291  jam();
18292 
18293  CreateTriggerRecPtr createTriggerPtr;
18294  getOpRec(op_ptr, createTriggerPtr);
18295  const CreateTrigImplReq* impl_req = &createTriggerPtr.p->m_request;
18296 
18297  if (!op_ptr.p->m_oplnk_ptr.isNull())
18298  {
18299  jam();
18300  sendTransConf(signal, op_ptr);
18301  return;
18302  }
18303 
18304  if (createTriggerPtr.p->m_main_op)
18305  {
18306  jam();
18307 
18308  Uint32 triggerId = impl_req->triggerId;
18309  TriggerRecordPtr triggerPtr;
18310  c_triggerRecordPool.getPtr(triggerPtr, triggerId);
18311 
18312  triggerPtr.p->triggerState = TriggerRecord::TS_ONLINE;
18313  unlinkDictObject(op_ptr);
18314  }
18315 
18316  sendTransConf(signal, op_ptr);
18317 }
18318 
18319 // CreateTrigger: COMPLETE
18320 
18321 void
18322 Dbdict::createTrigger_complete(Signal* signal, SchemaOpPtr op_ptr)
18323 {
18324  jam();
18325 
18326  CreateTriggerRecPtr createTriggerPtr;
18327  getOpRec(op_ptr, createTriggerPtr);
18328 
18329  if (!op_ptr.p->m_oplnk_ptr.isNull())
18330  {
18331  jam();
18332 
18336  if (hasDictObject(op_ptr))
18337  {
18338  jam();
18339  DictObjectPtr obj_ptr;
18340  getDictObject(op_ptr, obj_ptr);
18341  unlinkDictObject(op_ptr);
18342  linkDictObject(op_ptr.p->m_oplnk_ptr, obj_ptr);
18343  }
18344  op_ptr.p->m_oplnk_ptr.p->m_state = SchemaOp::OS_COMPLETING;
18345  dropTrigger_commit(signal, op_ptr.p->m_oplnk_ptr);
18346  return;
18347  }
18348 
18349  sendTransConf(signal, op_ptr);
18350 }
18351 
18352 // CreateTrigger: ABORT
18353 
18354 void
18355 Dbdict::createTrigger_abortParse(Signal* signal, SchemaOpPtr op_ptr)
18356 {
18357  D("createTrigger_abortParse" << *op_ptr.p);
18358 
18359  CreateTriggerRecPtr createTriggerPtr;
18360  getOpRec(op_ptr, createTriggerPtr);
18361  CreateTrigImplReq* impl_req = &createTriggerPtr.p->m_request;
18362  Uint32 triggerId = impl_req->triggerId;
18363 
18364  if (createTriggerPtr.p->m_main_op)
18365  {
18366  jam();
18367 
18368  TriggerRecordPtr triggerPtr;
18369  if (! (triggerId < c_triggerRecordPool.getSize()))
18370  {
18371  jam();
18372  goto done;
18373  }
18374 
18375  c_triggerRecordPool.getPtr(triggerPtr, triggerId);
18376 
18377  if (triggerPtr.p->triggerState == TriggerRecord::TS_DEFINING)
18378  {
18379  jam();
18380  triggerPtr.p->triggerState = TriggerRecord::TS_NOT_DEFINED;
18381  }
18382 
18383  if (triggerPtr.p->indexId != RNIL)
18384  {
18385  TableRecordPtr indexPtr;
18386  c_tableRecordPool.getPtr(indexPtr, triggerPtr.p->indexId);
18387  triggerPtr.p->indexId = RNIL;
18388  indexPtr.p->triggerId = RNIL;
18389  }
18390 
18391  // ignore Feedback for now (referencing object will be dropped too)
18392 
18393  if (hasDictObject(op_ptr))
18394  {
18395  jam();
18396  releaseDictObject(op_ptr);
18397  }
18398  }
18399 
18400 done:
18401 
18402  sendTransConf(signal, op_ptr);
18403 }
18404 
18405 void
18406 Dbdict::createTrigger_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
18407 {
18408  D("createTrigger_abortPrepare" << *op_ptr.p);
18409 
18410  CreateTriggerRecPtr createTriggerPtr;
18411  getOpRec(op_ptr, createTriggerPtr);
18412  const CreateTrigImplReq* impl_req = &createTriggerPtr.p->m_request;
18413 
18414  if (createTriggerPtr.p->m_main_op)
18415  {
18416  jam();
18417  sendTransConf(signal, op_ptr);
18418  return;
18419  }
18420 
18421  if (createTriggerPtr.p->m_created == false)
18422  {
18423  jam();
18424  sendTransConf(signal, op_ptr);
18425  return;
18426  }
18427 
18428  Callback c = { safe_cast(&Dbdict::createTrigger_abortPrepare_fromLocal),
18429  op_ptr.p->op_key
18430  };
18431  op_ptr.p->m_callback = c;
18432 
18433  DropTrigImplReq* req = (DropTrigImplReq*)signal->getDataPtrSend();
18434  req->senderRef = reference();
18435  req->senderData = op_ptr.p->op_key;
18436  req->requestType = 0;
18437  req->tableId = impl_req->tableId;
18438  req->tableVersion = 0; // not used
18439  req->indexId = impl_req->indexId;
18440  req->indexVersion = 0; // not used
18441  req->triggerNo = 0;
18442  req->triggerId = impl_req->triggerId;
18443  req->triggerInfo = impl_req->triggerInfo;
18444  req->receiverRef = impl_req->receiverRef;
18445 
18446  BlockReference ref = createTriggerPtr.p->m_block_list[0];
18447  sendSignal(ref, GSN_DROP_TRIG_IMPL_REQ, signal,
18448  DropTrigImplReq::SignalLength, JBB);
18449 }
18450 
18451 void
18452 Dbdict::createTrigger_abortPrepare_fromLocal(Signal* signal,
18453  Uint32 op_key, Uint32 ret)
18454 {
18455  SchemaOpPtr op_ptr;
18456  CreateTriggerRecPtr createTriggerPtr;
18457  findSchemaOp(op_ptr, createTriggerPtr, op_key);
18458  ndbrequire(!op_ptr.isNull());
18459 
18460  ndbrequire(ret == 0); // abort can't fail
18461 
18462  sendTransConf(signal, op_ptr);
18463 }
18464 
18465 void
18466 Dbdict::send_create_trig_req(Signal* signal,
18467  SchemaOpPtr op_ptr)
18468 {
18469  CreateTriggerRecPtr createTriggerPtr;
18470  getOpRec(op_ptr, createTriggerPtr);
18471  const CreateTrigImplReq* impl_req = &createTriggerPtr.p->m_request;
18472 
18473  TriggerRecordPtr triggerPtr;
18474  c_triggerRecordPool.getPtr(triggerPtr, impl_req->triggerId);
18475 
18476  D("send_create_trig_req");
18477 
18478  CreateTrigImplReq* req = (CreateTrigImplReq*)signal->getDataPtrSend();
18479 
18480  req->senderRef = reference();
18481  req->senderData = op_ptr.p->op_key;
18482  req->requestType = 0;
18483  req->tableId = triggerPtr.p->tableId;
18484  req->tableVersion = 0; // not used
18485  req->indexId = triggerPtr.p->indexId;
18486  req->indexVersion = 0; // not used
18487  req->triggerNo = 0; // not used
18488  req->triggerId = triggerPtr.p->triggerId;
18489  req->triggerInfo = triggerPtr.p->triggerInfo;
18490  req->receiverRef = triggerPtr.p->receiverRef;
18491 
18492  {
18496  Uint32 tmp[3];
18497  tmp[0] = triggerPtr.p->triggerId;
18498  tmp[1] = triggerPtr.p->triggerId;
18499  tmp[2] = triggerPtr.p->triggerId;
18500 
18501  TableRecordPtr indexPtr;
18502  if (triggerPtr.p->indexId != RNIL)
18503  {
18504  jam();
18505  c_tableRecordPool.getPtr(indexPtr, triggerPtr.p->indexId);
18506  if (indexPtr.p->m_upgrade_trigger_handling.m_upgrade)
18507  {
18508  jam();
18509  tmp[0] = indexPtr.p->m_upgrade_trigger_handling.insertTriggerId;
18510  tmp[1] = indexPtr.p->m_upgrade_trigger_handling.updateTriggerId;
18511  tmp[2] = indexPtr.p->m_upgrade_trigger_handling.deleteTriggerId;
18512  }
18513  }
18514  req->upgradeExtra[0] = tmp[0];
18515  req->upgradeExtra[1] = tmp[1];
18516  req->upgradeExtra[2] = tmp[2];
18517  }
18518 
18519  LinearSectionPtr ptr[3];
18520  ptr[0].p = triggerPtr.p->attributeMask.rep.data;
18521  ptr[0].sz = triggerPtr.p->attributeMask.getSizeInWords();
18522 
18523  BlockReference ref = createTriggerPtr.p->m_block_list[0];
18524  sendSignal(ref, GSN_CREATE_TRIG_IMPL_REQ, signal,
18525  CreateTrigImplReq::SignalLength, JBB, ptr, 1);
18526 }
18527 
18528 // CreateTrigger: MISC
18529 
18530 void
18531 Dbdict::execCREATE_TRIG_CONF(Signal* signal)
18532 {
18533  jamEntry();
18534  const CreateTrigConf* conf = (const CreateTrigConf*)signal->getDataPtr();
18535  handleDictConf(signal, conf);
18536 }
18537 
18538 void
18539 Dbdict::execCREATE_TRIG_REF(Signal* signal)
18540 {
18541  jamEntry();
18542  const CreateTrigRef* ref = (const CreateTrigRef*)signal->getDataPtr();
18543  handleDictRef(signal, ref);
18544 }
18545 
18546 void
18547 Dbdict::execCREATE_TRIG_IMPL_CONF(Signal* signal)
18548 {
18549  jamEntry();
18550  const CreateTrigImplConf* conf = (const CreateTrigImplConf*)signal->getDataPtr();
18551  ndbrequire(refToNode(conf->senderRef) == getOwnNodeId());
18552  handleDictConf(signal, conf);
18553 }
18554 
18555 void
18556 Dbdict::execCREATE_TRIG_IMPL_REF(Signal* signal)
18557 {
18558  jamEntry();
18559  const CreateTrigImplRef* ref = (const CreateTrigImplRef*)signal->getDataPtr();
18560  ndbrequire(refToNode(ref->senderRef) == getOwnNodeId());
18561  handleDictRef(signal, ref);
18562 }
18563 
18564 // CreateTrigger: END
18565 
18566 // MODULE: DropTrigger
18567 
18568 const Dbdict::OpInfo
18569 Dbdict::DropTriggerRec::g_opInfo = {
18570  { 'D', 'T', 'r', 0 },
18571  GSN_DROP_TRIG_IMPL_REQ,
18572  DropTrigImplReq::SignalLength,
18573  //
18574  &Dbdict::dropTrigger_seize,
18575  &Dbdict::dropTrigger_release,
18576  //
18577  &Dbdict::dropTrigger_parse,
18578  &Dbdict::dropTrigger_subOps,
18579  &Dbdict::dropTrigger_reply,
18580  //
18581  &Dbdict::dropTrigger_prepare,
18582  &Dbdict::dropTrigger_commit,
18583  &Dbdict::dropTrigger_complete,
18584  //
18585  &Dbdict::dropTrigger_abortParse,
18586  &Dbdict::dropTrigger_abortPrepare
18587 };
18588 
18589 bool
18590 Dbdict::dropTrigger_seize(SchemaOpPtr op_ptr)
18591 {
18592  return seizeOpRec<DropTriggerRec>(op_ptr);
18593 }
18594 
18595 void
18596 Dbdict::dropTrigger_release(SchemaOpPtr op_ptr)
18597 {
18598  releaseOpRec<DropTriggerRec>(op_ptr);
18599 }
18600 
18601 void
18602 Dbdict::execDROP_TRIG_REQ(Signal* signal)
18603 {
18604  jamEntry();
18605  if (!assembleFragments(signal)) {
18606  jam();
18607  return;
18608  }
18609  SectionHandle handle(this, signal);
18610 
18611  const DropTrigReq req_copy =
18612  *(const DropTrigReq*)signal->getDataPtr();
18613  const DropTrigReq* req = &req_copy;
18614 
18615  ErrorInfo error;
18616  do {
18617  SchemaOpPtr op_ptr;
18618  DropTriggerRecPtr dropTriggerPtr;
18619  DropTrigImplReq* impl_req;
18620 
18621  startClientReq(op_ptr, dropTriggerPtr, req, impl_req, error);
18622  if (hasError(error)) {
18623  jam();
18624  break;
18625  }
18626 
18627  impl_req->tableId = req->tableId;
18628  impl_req->tableVersion = req->tableVersion;
18629  impl_req->indexId = req->indexId;
18630  impl_req->indexVersion = req->indexVersion;
18631  impl_req->triggerNo = req->triggerNo;
18632  impl_req->triggerId = req->triggerId;
18633  impl_req->triggerInfo = ~(Uint32)0;
18634 
18635  handleClientReq(signal, op_ptr, handle);
18636  return;
18637  } while (0);
18638 
18639  releaseSections(handle);
18640 
18641  DropTrigRef* ref = (DropTrigRef*)signal->getDataPtrSend();
18642 
18643  ref->senderRef = reference();
18644  ref->clientData = req->clientData;
18645  ref->transId = req->transId;
18646  ref->tableId = req->tableId;
18647  ref->indexId = req->indexId;
18648  getError(error, ref);
18649 
18650  sendSignal(req->clientRef, GSN_DROP_TRIG_REF, signal,
18651  DropTrigRef::SignalLength, JBB);
18652 }
18653 
18654 // DropTrigger: PARSE
18655 
18656 void
18657 Dbdict::dropTrigger_parse(Signal* signal, bool master,
18658  SchemaOpPtr op_ptr,
18659  SectionHandle& handle, ErrorInfo& error)
18660 {
18661  D("dropTrigger_parse" << V(op_ptr.i) << *op_ptr.p);
18662 
18663  DropTriggerRecPtr dropTriggerPtr;
18664  getOpRec(op_ptr, dropTriggerPtr);
18665  DropTrigImplReq* impl_req = &dropTriggerPtr.p->m_request;
18666 
18667  bool reqByName = false;
18668  if (handle.m_cnt > 0) { // wl3600_todo use requestType
18669  jam();
18670  ndbrequire(handle.m_cnt == 1);
18671  reqByName = true;
18672  }
18673 
18674  if (reqByName) {
18675  jam();
18676  SegmentedSectionPtr ss_ptr;
18677  handle.getSection(ss_ptr, DropTrigImplReq::TRIGGER_NAME_SECTION);
18678  SimplePropertiesSectionReader r(ss_ptr, getSectionSegmentPool());
18679  DictTabInfo::Table tableDesc;
18680  tableDesc.init();
18682  SimpleProperties::unpack(
18683  r, &tableDesc,
18684  DictTabInfo::TableMapping, DictTabInfo::TableMappingSize,
18685  true, true);
18686 
18687  if (status != SimpleProperties::Eof ||
18688  tableDesc.TableName[0] == 0)
18689  {
18690  jam();
18691  ndbassert(false);
18692  setError(error, DropTrigRef::InvalidName, __LINE__);
18693  return;
18694  }
18695  const Uint32 bytesize = sizeof(dropTriggerPtr.p->m_triggerName);
18696  memcpy(dropTriggerPtr.p->m_triggerName, tableDesc.TableName, bytesize);
18697  D("parsed trigger name: " << dropTriggerPtr.p->m_triggerName);
18698 
18699  // find object by name and link it to operation
18700  DictObjectPtr obj_ptr;
18701  if (!findDictObject(op_ptr, obj_ptr, dropTriggerPtr.p->m_triggerName)) {
18702  jam();
18703  setError(error, DropTrigRef::TriggerNotFound, __LINE__);
18704  return;
18705  }
18706  if (impl_req->triggerId != RNIL &&
18707  impl_req->triggerId != obj_ptr.p->m_id) {
18708  jam();
18709  // inconsistency in request
18710  setError(error, DropTrigRef::TriggerNotFound, __LINE__);
18711  return;
18712  }
18713  impl_req->triggerId = obj_ptr.p->m_id;
18714  }
18715 
18716  // check trigger id from user or via name
18717  TriggerRecordPtr triggerPtr;
18718  {
18719  if (!(impl_req->triggerId < c_triggerRecordPool.getSize())) {
18720  jam();
18721  setError(error, DropTrigImplRef::TriggerNotFound, __LINE__);
18722  return;
18723  }
18724  c_triggerRecordPool.getPtr(triggerPtr, impl_req->triggerId);
18725  // wl3600_todo state check
18726  }
18727 
18728  D("trigger " << copyRope<MAX_TAB_NAME_SIZE>(triggerPtr.p->triggerName));
18729  impl_req->triggerInfo = triggerPtr.p->triggerInfo;
18730  Uint32 requestType = impl_req->requestType;
18731 
18732  switch(DropTrigReq::getEndpointFlag(requestType)){
18733  case DropTrigReq::MainTrigger:
18734  jam();
18735  dropTriggerPtr.p->m_main_op = true;
18736  break;
18737  case DropTrigReq::TriggerDst:
18738  case DropTrigReq::TriggerSrc:
18739  jam();
18740  if (handle.m_cnt)
18741  {
18742  jam();
18743  ndbassert(false);
18744  setError(error, DropTrigRef::BadRequestType, __LINE__);
18745  return;
18746  }
18747  dropTriggerPtr.p->m_main_op = false;
18748  dropTrigger_parse_endpoint(signal, op_ptr, error);
18749  return;
18750  }
18751 
18752  // connect to object in request by id
18753  if (!reqByName) {
18754  jam();
18755  DictObjectPtr obj_ptr;
18756  if (!findDictObject(op_ptr, obj_ptr, triggerPtr.p->m_obj_ptr_i)) {
18757  jam();
18758  // broken trigger object wl3600_todo bad error code
18759  setError(error, DropTrigRef::TriggerNotFound, __LINE__);
18760  return;
18761  }
18762  ndbrequire(obj_ptr.p->m_id == triggerPtr.p->triggerId);
18763 
18764  // fill in name just to be complete
18765  ConstRope name(c_rope_pool, triggerPtr.p->triggerName);
18766  name.copy(dropTriggerPtr.p->m_triggerName); //wl3600_todo length check
18767  }
18768 
18769  // check the table (must match trigger record)
18770  {
18771  if (impl_req->tableId != triggerPtr.p->tableId) {
18772  jam();
18773  setError(error, DropTrigRef::InvalidTable, __LINE__);
18774  return;
18775  }
18776  }
18777 
18778  // check the index (must match trigger record, maybe both RNIL)
18779  {
18780  if (impl_req->indexId != triggerPtr.p->indexId) {
18781  jam(); // wl3600_todo wrong error code
18782  setError(error, DropTrigRef::InvalidTable, __LINE__);
18783  return;
18784  }
18785  }
18786 
18787  {
18788  TriggerType::Value type =
18789  TriggerInfo::getTriggerType(triggerPtr.p->triggerInfo);
18790  switch(type){
18791  case TriggerType::SECONDARY_INDEX:
18792  jam();
18793  dropTriggerPtr.p->m_sub_dst = false;
18794  dropTriggerPtr.p->m_sub_src = false;
18795  break;
18796  case TriggerType::ORDERED_INDEX:
18797  case TriggerType::READ_ONLY_CONSTRAINT:
18798  jam();
18799  dropTriggerPtr.p->m_sub_dst = true; // Only need LQH
18800  dropTriggerPtr.p->m_sub_src = false;
18801  break;
18802  default:
18803  case TriggerType::SUBSCRIPTION:
18804  case TriggerType::SUBSCRIPTION_BEFORE:
18805  ndbassert(false);
18806  setError(error, DropTrigRef::UnsupportedTriggerType, __LINE__);
18807  return;
18808  }
18809  }
18810 
18811  if (ERROR_INSERTED(6124)) {
18812  jam();
18813  CLEAR_ERROR_INSERT_VALUE;
18814  setError(error, 9124, __LINE__);
18815  return;
18816  }
18817 }
18818 
18819 void
18820 Dbdict::dropTrigger_parse_endpoint(Signal* signal,
18821  SchemaOpPtr op_ptr,
18822  ErrorInfo& error)
18823 {
18824  DropTriggerRecPtr dropTriggerPtr;
18825  getOpRec(op_ptr, dropTriggerPtr);
18826  DropTrigImplReq* impl_req = &dropTriggerPtr.p->m_request;
18827 
18828  // check request type
18829  Uint32 requestType = impl_req->requestType;
18830  switch(DropTrigReq::getEndpointFlag(requestType)){
18831  case DropTrigReq::TriggerDst:
18832  jam();
18833  dropTriggerPtr.p->m_block_list[0] = DBTC_REF;
18834  break;
18835  case DropTrigReq::TriggerSrc:
18836  jam();
18837  dropTriggerPtr.p->m_block_list[0] = DBLQH_REF;
18838  break;
18839  default:
18840  ndbassert(false);
18841  setError(error, DropTrigRef::BadRequestType, __LINE__);
18842  return;
18843  }
18844 }
18845 
18846 bool
18847 Dbdict::dropTrigger_subOps(Signal* signal, SchemaOpPtr op_ptr)
18848 {
18849  D("dropTrigger_subOps" << V(op_ptr.i) << *op_ptr.p);
18850 
18851  DropTriggerRecPtr dropTriggerPtr;
18852  getOpRec(op_ptr, dropTriggerPtr);
18853 
18854  Uint32 requestType = dropTriggerPtr.p->m_request.requestType;
18855  switch(DropTrigReq::getEndpointFlag(requestType)){
18856  case DropTrigReq::MainTrigger:
18857  jam();
18858  break;
18859  case DropTrigReq::TriggerDst:
18860  case DropTrigReq::TriggerSrc:
18861  jam();
18862  return false;
18863  }
18864 
18868  if (!dropTriggerPtr.p->m_sub_src)
18869  {
18870  jam();
18871  dropTriggerPtr.p->m_sub_src = true;
18872  Callback c = {
18873  safe_cast(&Dbdict::dropTrigger_fromDropEndpoint),
18874  op_ptr.p->op_key
18875  };
18876  op_ptr.p->m_callback = c;
18877  dropTrigger_toDropEndpoint(signal, op_ptr,
18878  DropTrigReq::TriggerSrc);
18879  return true;
18880  }
18881 
18882  if (!dropTriggerPtr.p->m_sub_dst)
18883  {
18884  jam();
18885  dropTriggerPtr.p->m_sub_dst = true;
18886  Callback c = {
18887  safe_cast(&Dbdict::dropTrigger_fromDropEndpoint),
18888  op_ptr.p->op_key
18889  };
18890  op_ptr.p->m_callback = c;
18891  dropTrigger_toDropEndpoint(signal, op_ptr,
18892  DropTrigReq::TriggerDst);
18893  return true;
18894  }
18895 
18896  return false;
18897 }
18898 
18899 void
18900 Dbdict::dropTrigger_toDropEndpoint(Signal* signal,
18901  SchemaOpPtr op_ptr,
18902  DropTrigReq::EndpointFlag endpoint)
18903 {
18904  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
18905  DropTriggerRecPtr dropTriggerPtr;
18906  getOpRec(op_ptr, dropTriggerPtr);
18907  const DropTrigImplReq* impl_req = &dropTriggerPtr.p->m_request;
18908 
18909  DropTrigReq* req = (DropTrigReq*)signal->getDataPtrSend();
18910 
18911  Uint32 requestType = 0;
18912  DropTrigReq::setEndpointFlag(requestType, endpoint);
18913 
18914  Uint32 requestInfo = 0;
18915  DictSignal::setRequestType(requestInfo, requestType);
18916  DictSignal::addRequestFlagsGlobal(requestInfo, op_ptr.p->m_requestInfo);
18917 
18918  req->clientRef = reference();
18919  req->clientData = op_ptr.p->op_key;
18920  req->transId = trans_ptr.p->m_transId;
18921  req->transKey = trans_ptr.p->trans_key;
18922  req->requestInfo = requestInfo;
18923  req->tableId = impl_req->tableId;
18924  req->tableVersion = impl_req->tableVersion;
18925  req->indexId = impl_req->indexId;
18926  req->indexVersion = impl_req->indexVersion;
18927  req->triggerId = impl_req->triggerId;
18928  req->triggerNo = 0;
18929 
18930  sendSignal(reference(), GSN_DROP_TRIG_REQ, signal,
18931  DropTrigReq::SignalLength, JBB);
18932 }
18933 
18934 void
18935 Dbdict::dropTrigger_fromDropEndpoint(Signal* signal,
18936  Uint32 op_key, Uint32 ret)
18937 {
18938  SchemaOpPtr op_ptr;
18939  DropTriggerRecPtr dropTriggerPtr;
18940  findSchemaOp(op_ptr, dropTriggerPtr, op_key);
18941  ndbrequire(!op_ptr.isNull());
18942  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
18943 
18944  if (ret == 0)
18945  {
18946  jam();
18947  const DropTrigConf* conf =
18948  (const DropTrigConf*)signal->getDataPtr();
18949 
18950  ndbrequire(conf->transId == trans_ptr.p->m_transId);
18951  createSubOps(signal, op_ptr);
18952  }
18953  else
18954  {
18955  jam();
18956  const DropTrigRef* ref =
18957  (const DropTrigRef*)signal->getDataPtr();
18958  ErrorInfo error;
18959  setError(error, ref);
18960  abortSubOps(signal, op_ptr, error);
18961  }
18962 }
18963 
18964 void
18965 Dbdict::dropTrigger_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
18966 {
18967  jam();
18968  SchemaTransPtr& trans_ptr = op_ptr.p->m_trans_ptr;
18969  DropTriggerRecPtr dropTriggerPtr;
18970  getOpRec(op_ptr, dropTriggerPtr);
18971  const DropTrigImplReq* impl_req = &dropTriggerPtr.p->m_request;
18972 
18973  D("dropTrigger_reply" << V(impl_req->triggerId));
18974 
18975  if (!hasError(error)) {
18976  DropTrigConf* conf = (DropTrigConf*)signal->getDataPtrSend();
18977  conf->senderRef = reference();
18978  conf->clientData = op_ptr.p->m_clientData;
18979  conf->transId = trans_ptr.p->m_transId;
18980  conf->tableId = impl_req->tableId;
18981  conf->indexId = impl_req->indexId;
18982  conf->triggerId = impl_req->triggerId;
18983 
18984  Uint32 clientRef = op_ptr.p->m_clientRef;
18985  sendSignal(clientRef, GSN_DROP_TRIG_CONF, signal,
18986  DropTrigConf::SignalLength, JBB);
18987  } else {
18988  jam();
18989  DropTrigRef* ref = (DropTrigRef*)signal->getDataPtrSend();
18990  ref->senderRef = reference();
18991  ref->clientData = op_ptr.p->m_clientData;
18992  ref->transId = trans_ptr.p->m_transId;
18993  ref->tableId = impl_req->tableId;
18994  ref->indexId = impl_req->indexId;
18995  ref->triggerId = impl_req->triggerId;
18996  getError(error, ref);
18997 
18998  Uint32 clientRef = op_ptr.p->m_clientRef;
18999  sendSignal(clientRef, GSN_DROP_TRIG_REF, signal,
19000  DropTrigRef::SignalLength, JBB);
19001  }
19002 }
19003 
19004 // DropTrigger: PREPARE
19005 
19006 void
19007 Dbdict::dropTrigger_prepare(Signal* signal, SchemaOpPtr op_ptr)
19008 {
19009  jam();
19010  D("dropTrigger_prepare");
19011 
19016  sendTransConf(signal, op_ptr);
19017 }
19018 
19019 // DropTrigger: COMMIT
19020 
19021 void
19022 Dbdict::dropTrigger_commit(Signal* signal, SchemaOpPtr op_ptr)
19023 {
19024  jam();
19025  DropTriggerRecPtr dropTriggerPtr;
19026  getOpRec(op_ptr, dropTriggerPtr);
19027 
19028  if (dropTriggerPtr.p->m_main_op)
19029  {
19030  jam();
19031 
19032  Uint32 triggerId = dropTriggerPtr.p->m_request.triggerId;
19033 
19034  TriggerRecordPtr triggerPtr;
19035  c_triggerRecordPool.getPtr(triggerPtr, triggerId);
19036 
19037  if (triggerPtr.p->indexId != RNIL)
19038  {
19039  TableRecordPtr indexPtr;
19040  c_tableRecordPool.getPtr(indexPtr, triggerPtr.p->indexId);
19041  triggerPtr.p->indexId = RNIL;
19042  indexPtr.p->triggerId = RNIL;
19043  }
19044 
19045  // remove trigger
19046  releaseDictObject(op_ptr);
19047  triggerPtr.p->triggerState = TriggerRecord::TS_NOT_DEFINED;
19048 
19049  sendTransConf(signal, op_ptr);
19050  return;
19051  }
19052 
19053  Callback c = { safe_cast(&Dbdict::dropTrigger_commit_fromLocal),
19054  op_ptr.p->op_key
19055  };
19056 
19057  op_ptr.p->m_callback = c;
19058  send_drop_trig_req(signal, op_ptr);
19059 }
19060 
19061 void
19062 Dbdict::dropTrigger_commit_fromLocal(Signal* signal,
19063  Uint32 op_key, Uint32 ret)
19064 {
19065  SchemaOpPtr op_ptr;
19066  DropTriggerRecPtr dropTriggerPtr;
19067  findSchemaOp(op_ptr, dropTriggerPtr, op_key);
19068  ndbrequire(!op_ptr.isNull());
19069  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
19070 
19071  if (ret)
19072  {
19073  jam();
19074  warningEvent("Got error code %u from %x (DROP_TRIG_IMPL_REQ)",
19075  ret,
19076  dropTriggerPtr.p->m_block_list[0]);
19077  }
19078 
19079  sendTransConf(signal, op_ptr);
19080 }
19081 
19082 void
19083 Dbdict::send_drop_trig_req(Signal* signal, SchemaOpPtr op_ptr)
19084 {
19085  DropTriggerRecPtr dropTriggerPtr;
19086  getOpRec(op_ptr, dropTriggerPtr);
19087  const DropTrigImplReq* impl_req = &dropTriggerPtr.p->m_request;
19088 
19089  DropTrigImplReq* req = (DropTrigImplReq*)signal->getDataPtrSend();
19090 
19091  req->senderRef = reference();
19092  req->senderData = op_ptr.p->op_key;
19093  req->requestType = impl_req->requestType;
19094  req->tableId = impl_req->tableId;
19095  req->tableVersion = 0; // not used
19096  req->indexId = impl_req->indexId;
19097  req->indexVersion = 0; // not used
19098  req->triggerNo = 0;
19099  req->triggerId = impl_req->triggerId;
19100  req->triggerInfo = impl_req->triggerInfo;
19101  req->receiverRef = impl_req->receiverRef;
19102 
19103  BlockReference ref = dropTriggerPtr.p->m_block_list[0];
19104  sendSignal(ref, GSN_DROP_TRIG_IMPL_REQ, signal,
19105  DropTrigImplReq::SignalLength, JBB);
19106 }
19107 
19108 // DropTrigger: COMPLETE
19109 
19110 void
19111 Dbdict::dropTrigger_complete(Signal* signal, SchemaOpPtr op_ptr)
19112 {
19113  jam();
19114  sendTransConf(signal, op_ptr);
19115 }
19116 
19117 // DropTrigger: ABORT
19118 
19119 void
19120 Dbdict::dropTrigger_abortParse(Signal* signal, SchemaOpPtr op_ptr)
19121 {
19122  DropTriggerRecPtr dropTriggerPtr;
19123  getOpRec(op_ptr, dropTriggerPtr);
19124 
19125  D("dropTrigger_abortParse" << *op_ptr.p);
19126 
19127  if (hasDictObject(op_ptr)) {
19128  jam();
19129  unlinkDictObject(op_ptr);
19130  }
19131  sendTransConf(signal, op_ptr);
19132 }
19133 
19134 void
19135 Dbdict::dropTrigger_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
19136 {
19137  D("dropTrigger_abortPrepare" << *op_ptr.p);
19138 
19139  sendTransConf(signal, op_ptr);
19140 }
19141 
19142 // DropTrigger: MISC
19143 
19144 void
19145 Dbdict::execDROP_TRIG_CONF(Signal* signal)
19146 {
19147  jamEntry();
19148  const DropTrigConf* conf = (const DropTrigConf*)signal->getDataPtr();
19149  handleDictConf(signal, conf);
19150 }
19151 
19152 void
19153 Dbdict::execDROP_TRIG_REF(Signal* signal)
19154 {
19155  jamEntry();
19156  const DropTrigRef* ref = (const DropTrigRef*)signal->getDataPtr();
19157  handleDictRef(signal, ref);
19158 }
19159 
19160 void
19161 Dbdict::execDROP_TRIG_IMPL_CONF(Signal* signal)
19162 {
19163  jamEntry();
19164  const DropTrigImplConf* conf = (const DropTrigImplConf*)signal->getDataPtr();
19165  ndbrequire(refToNode(conf->senderRef) == getOwnNodeId());
19166  handleDictConf(signal, conf);
19167 }
19168 
19169 void
19170 Dbdict::execDROP_TRIG_IMPL_REF(Signal* signal)
19171 {
19172  jamEntry();
19173  const DropTrigImplRef* ref = (const DropTrigImplRef*)signal->getDataPtr();
19174  ndbrequire(refToNode(ref->senderRef) == getOwnNodeId());
19175  handleDictRef(signal, ref);
19176 }
19177 
19178 // DropTrigger: END
19179 
19180 
19185 /*
19186  This routine is used to set-up the primary key attributes of the unique
19187  hash index. Since we store fragment id as part of the primary key here
19188  we insert the pseudo column for getting fragment id first in the array.
19189  This routine is used as part of the building of the index.
19190 */
19191 
19192 void
19193 Dbdict::getTableKeyList(TableRecordPtr tablePtr,
19195 {
19196  jam();
19197  list.sz = 0;
19198  list.id[list.sz++] = AttributeHeader::FRAGMENT;
19199  LocalDLFifoList<AttributeRecord> alist(c_attributeRecordPool,
19200  tablePtr.p->m_attributes);
19201  AttributeRecordPtr attrPtr;
19202  for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr)) {
19203  if (attrPtr.p->tupleKey) {
19204  list.id[list.sz++] = attrPtr.p->attributeId;
19205  }
19206  }
19207  ndbrequire(list.sz == (uint)(tablePtr.p->noOfPrimkey + 1));
19208  ndbrequire(list.sz <= MAX_ATTRIBUTES_IN_INDEX + 1);
19209 }
19210 
19211 // XXX should store the primary attribute id
19212 void
19213 Dbdict::getIndexAttr(TableRecordPtr indexPtr, Uint32 itAttr, Uint32* id)
19214 {
19215  jam();
19216 
19217  Uint32 len;
19218  char name[MAX_ATTR_NAME_SIZE];
19219  TableRecordPtr tablePtr;
19220  AttributeRecordPtr attrPtr;
19221 
19222  c_tableRecordPool.getPtr(tablePtr, indexPtr.p->primaryTableId);
19223  AttributeRecord* iaRec = c_attributeRecordPool.getPtr(itAttr);
19224  {
19225  ConstRope tmp(c_rope_pool, iaRec->attributeName);
19226  tmp.copy(name);
19227  len = tmp.size();
19228  }
19229  LocalDLFifoList<AttributeRecord> alist(c_attributeRecordPool,
19230  tablePtr.p->m_attributes);
19231  for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr)){
19232  ConstRope tmp(c_rope_pool, attrPtr.p->attributeName);
19233  if(tmp.compare(name, len) == 0){
19234  id[0] = attrPtr.p->attributeId;
19235  return;
19236  }
19237  }
19238  ndbrequire(false);
19239 }
19240 
19241 void
19242 Dbdict::getIndexAttrList(TableRecordPtr indexPtr, IndexAttributeList& list)
19243 {
19244  jam();
19245  list.sz = 0;
19246  memset(list.id, 0, sizeof(list.id));
19247  ndbrequire(indexPtr.p->noOfAttributes >= 2);
19248 
19249  LocalDLFifoList<AttributeRecord> alist(c_attributeRecordPool,
19250  indexPtr.p->m_attributes);
19251  AttributeRecordPtr attrPtr;
19252  for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr)) {
19253  // skip last
19254  AttributeRecordPtr tempPtr = attrPtr;
19255  if (! alist.next(tempPtr))
19256  break;
19261  getIndexAttr(indexPtr, attrPtr.i, &list.id[list.sz]);
19262  list.sz++;
19263  }
19264  ndbrequire(indexPtr.p->noOfAttributes == list.sz + 1);
19265 }
19266 
19267 void
19268 Dbdict::getIndexAttrMask(TableRecordPtr indexPtr, AttributeMask& mask)
19269 {
19270  jam();
19271  mask.clear();
19272  ndbrequire(indexPtr.p->noOfAttributes >= 2);
19273 
19274  AttributeRecordPtr attrPtr, currPtr;
19275  LocalDLFifoList<AttributeRecord> alist(c_attributeRecordPool,
19276  indexPtr.p->m_attributes);
19277 
19278 
19279  for (alist.first(attrPtr); currPtr = attrPtr, alist.next(attrPtr); ){
19280  Uint32 id;
19281  getIndexAttr(indexPtr, currPtr.i, &id);
19282  mask.set(id);
19283  }
19284 }
19285 
19286 // DICT lock master
19287 
19288 const Dbdict::DictLockType*
19289 Dbdict::getDictLockType(Uint32 lockType)
19290 {
19291  static const DictLockType lt[] = {
19292  { DictLockReq::NodeRestartLock, "NodeRestart" }
19293  ,{ DictLockReq::SchemaTransLock, "SchemaTransLock" }
19294  ,{ DictLockReq::CreateFileLock, "CreateFile" }
19295  ,{ DictLockReq::CreateFilegroupLock, "CreateFilegroup" }
19296  ,{ DictLockReq::DropFileLock, "DropFile" }
19297  ,{ DictLockReq::DropFilegroupLock, "DropFilegroup" }
19298  };
19299  for (unsigned int i = 0; i < sizeof(lt)/sizeof(lt[0]); i++) {
19300  if ((Uint32) lt[i].lockType == lockType)
19301  return &lt[i];
19302  }
19303  return NULL;
19304 }
19305 
19306 void
19307 Dbdict::sendDictLockInfoEvent(Signal*, const UtilLockReq* req, const char* text)
19308 {
19309  const Dbdict::DictLockType* lt = getDictLockType(req->extra);
19310 
19311  infoEvent("DICT: %s %u for %s",
19312  text,
19313  (unsigned)refToNode(req->senderRef), lt->text);
19314 }
19315 
19316 void
19317 Dbdict::execDICT_LOCK_REQ(Signal* signal)
19318 {
19319  jamEntry();
19320  const DictLockReq req = *(DictLockReq*)&signal->theData[0];
19321 
19322  UtilLockReq lockReq;
19323  lockReq.senderRef = req.userRef;
19324  lockReq.senderData = req.userPtr;
19325  lockReq.lockId = 0;
19326  lockReq.requestInfo = 0;
19327  lockReq.extra = req.lockType;
19328 
19329  const DictLockType* lt = getDictLockType(req.lockType);
19330 
19331  Uint32 err;
19332  if (req.lockType == DictLockReq::SumaStartMe ||
19333  req.lockType == DictLockReq::SumaHandOver)
19334  {
19335  jam();
19336 
19337  if (c_outstanding_sub_startstop)
19338  {
19339  jam();
19340  g_eventLogger->info("refing dict lock to %u", refToNode(req.userRef));
19341  err = DictLockRef::TooManyRequests;
19342  goto ref;
19343  }
19344 
19345  if (req.lockType == DictLockReq::SumaHandOver &&
19346  !c_sub_startstop_lock.isclear())
19347  {
19348  g_eventLogger->info("refing dict lock to %u", refToNode(req.userRef));
19349  err = DictLockRef::TooManyRequests;
19350  goto ref;
19351  }
19352 
19353  c_sub_startstop_lock.set(refToNode(req.userRef));
19354 
19355  g_eventLogger->info("granting dict lock to %u", refToNode(req.userRef));
19356  DictLockConf* conf = (DictLockConf*)signal->getDataPtrSend();
19357  conf->userPtr = req.userPtr;
19358  conf->lockType = req.lockType;
19359  conf->lockPtr = 0;
19360  sendSignal(req.userRef, GSN_DICT_LOCK_CONF, signal,
19361  DictLockConf::SignalLength, JBB);
19362  return;
19363  }
19364 
19365  if (req.lockType == DictLockReq::NodeRestartLock)
19366  {
19367  jam();
19368  lockReq.requestInfo |= UtilLockReq::SharedLock;
19369  }
19370 
19371  // make sure bad request crashes slave, not master (us)
19372  Uint32 res;
19373  if (getOwnNodeId() != c_masterNodeId)
19374  {
19375  jam();
19376  err = DictLockRef::NotMaster;
19377  goto ref;
19378  }
19379 
19380  if (lt == NULL)
19381  {
19382  jam();
19383  err = DictLockRef::InvalidLockType;
19384  goto ref;
19385  }
19386 
19387  if (req.userRef != signal->getSendersBlockRef() ||
19388  getNodeInfo(refToNode(req.userRef)).m_type != NodeInfo::DB)
19389  {
19390  jam();
19391  err = DictLockRef::BadUserRef;
19392  goto ref;
19393  }
19394 
19395  if (c_aliveNodes.get(refToNode(req.userRef)))
19396  {
19397  jam();
19398  err = DictLockRef::TooLate;
19399  goto ref;
19400  }
19401 
19402  res = m_dict_lock.lock(this, m_dict_lock_pool, &lockReq, 0);
19403  switch(res){
19404  case 0:
19405  jam();
19406  sendDictLockInfoEvent(signal, &lockReq, "locked by node");
19407  goto conf;
19408  break;
19409  case UtilLockRef::OutOfLockRecords:
19410  jam();
19411  err = DictLockRef::TooManyRequests;
19412  goto ref;
19413  break;
19414  default:
19415  jam();
19416  sendDictLockInfoEvent(signal, &lockReq, "lock request by node");
19417  break;
19418  }
19419  return;
19420 
19421 ref:
19422  {
19423  DictLockRef* ref = (DictLockRef*)signal->getDataPtrSend();
19424  ref->userPtr = lockReq.senderData;
19425  ref->lockType = lockReq.extra;
19426  ref->errorCode = err;
19427 
19428  sendSignal(lockReq.senderRef, GSN_DICT_LOCK_REF, signal,
19429  DictLockRef::SignalLength, JBB);
19430  }
19431  return;
19432 
19433 conf:
19434  {
19435  DictLockConf* conf = (DictLockConf*)signal->getDataPtrSend();
19436 
19437  conf->userPtr = lockReq.senderData;
19438  conf->lockType = lockReq.extra;
19439  conf->lockPtr = lockReq.senderData;
19440 
19441  sendSignal(lockReq.senderRef, GSN_DICT_LOCK_CONF, signal,
19442  DictLockConf::SignalLength, JBB);
19443  }
19444  return;
19445 }
19446 
19447 void
19448 Dbdict::execDICT_UNLOCK_ORD(Signal* signal)
19449 {
19450  jamEntry();
19451  const DictUnlockOrd* ord = (const DictUnlockOrd*)&signal->theData[0];
19452 
19453  DictLockReq req;
19454  req.userPtr = ord->senderData;
19455  req.userRef = ord->senderRef;
19456 
19457  if (signal->getLength() < DictUnlockOrd::SignalLength)
19458  {
19459  jam();
19460  req.userPtr = ord->lockPtr;
19461  req.userRef = signal->getSendersBlockRef();
19462  }
19463 
19464  if (ord->lockType == DictLockReq::SumaStartMe ||
19465  ord->lockType == DictLockReq::SumaHandOver)
19466  {
19467  jam();
19468  g_eventLogger->info("clearing dict lock for %u", refToNode(ord->senderRef));
19469  c_sub_startstop_lock.clear(refToNode(ord->senderRef));
19470  return;
19471  }
19472 
19473  UtilLockReq lockReq;
19474  lockReq.senderData = req.userPtr;
19475  lockReq.senderRef = req.userRef;
19476  lockReq.extra = DictLockReq::NodeRestartLock; // Should check...
19477  Uint32 res = dict_lock_unlock(signal, &req);
19478  switch(res){
19479  case UtilUnlockRef::OK:
19480  jam();
19481  sendDictLockInfoEvent(signal, &lockReq, "unlocked by node");
19482  return;
19483  case UtilUnlockRef::NotLockOwner:
19484  jam();
19485  sendDictLockInfoEvent(signal, &lockReq, "lock request removed by node");
19486  return;
19487  default:
19488  ndbassert(false);
19489  }
19490 }
19491 
19492 // Master take-over
19493 
19494 void
19495 Dbdict::execDICT_TAKEOVER_REQ(Signal* signal)
19496  {
19497  jamEntry();
19498 
19499  if (!checkNodeFailSequence(signal))
19500  {
19501  jam();
19502  return;
19503  }
19504 
19505  DictTakeoverReq* req = (DictTakeoverReq*)signal->getDataPtr();
19506  Uint32 masterRef = req->senderRef;
19507  Uint32 op_count = 0;
19508  Uint32 rollforward_op = 0;
19509  Uint32 rollforward_op_state = SchemaOp::OS_COMPLETED;
19510  Uint32 rollback_op = 0;
19511  Uint32 rollback_op_state = SchemaOp::OS_INITIAL;
19512  Uint32 lowest_op = 0;
19513  Uint32 lowest_op_state = SchemaOp::OS_COMPLETED;
19514  Uint32 lowest_op_impl_req_gsn = 0;
19515  Uint32 highest_op = 0;
19516  Uint32 highest_op_state = SchemaOp::OS_INITIAL;
19517  Uint32 highest_op_impl_req_gsn = 0;
19518  SchemaTransPtr trans_ptr;
19519  bool ending = false;
19520 
19521  jam();
19522  bool pending_trans = c_schemaTransList.first(trans_ptr);
19523  if (!pending_trans)
19524  {
19525  /*
19526  Slave has no pending transaction
19527  */
19528  jam();
19529  DictTakeoverRef* ref = (DictTakeoverRef*)signal->getDataPtrSend();
19530  ref->senderRef = reference();
19531  ref->masterRef = masterRef;
19532  ref->errorCode = DictTakeoverRef::NoTransaction;
19533  sendSignal(masterRef, GSN_DICT_TAKEOVER_REF, signal,
19534  DictTakeoverRef::SignalLength, JBB);
19535  return;
19536  }
19537  while (pending_trans)
19538  {
19539  trans_ptr.p->m_masterRef = masterRef;
19540 #ifdef VM_TRACE
19541  ndbout_c("Dbdict::execDICT_TAKEOVER_REQ: trans %u(0x%8x), state %u, op_list %s", trans_ptr.i, (uint)trans_ptr.p->trans_key, trans_ptr.p->m_state, (trans_ptr.p->m_op_list.in_use)?"yes":"no");
19542 #endif
19543 
19544  SchemaOpPtr op_ptr;
19545  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
19546  bool pending_op = list.first(op_ptr);
19547  if (pending_op &&
19548  (trans_ptr.p->m_state == SchemaTrans::TS_COMPLETING ||
19549  trans_ptr.p->m_state == SchemaTrans::TS_ENDING))
19550  {
19551  jam();
19552  /*
19553  We were ending (releasing) operations, check how
19554  far slave got by finding lowest operation.
19555  */
19556  ending = true;
19557  lowest_op = op_ptr.p->op_key;
19558  lowest_op_state = op_ptr.p->m_state;
19559  /*
19560  Find the OpInfo gsn for the next operation to
19561  be removed,
19562  this might be needed by new master to create missing operation.
19563  */
19564  lowest_op_impl_req_gsn = getOpInfo(op_ptr).m_impl_req_gsn;
19565  }
19566  while (pending_op)
19567  {
19568  jam();
19569  op_count++;
19570  ndbrequire(!op_ptr.isNull());
19571  ndbrequire(trans_ptr.i == op_ptr.p->m_trans_ptr.i);
19572 #ifdef VM_TRACE
19573  ndbout_c("Dbdict::execDICT_TAKEOVER_REQ: op %u state %u", op_ptr.p->op_key, op_ptr.p->m_state);
19574 #endif
19575 
19576  /*
19577  Check if operation is busy
19578  */
19579  switch(op_ptr.p->m_state) {
19580  case SchemaOp::OS_PARSING:
19581  case SchemaOp::OS_PREPARING:
19582  case SchemaOp::OS_ABORTING_PREPARE:
19583  case SchemaOp::OS_ABORTING_PARSE:
19584  case SchemaOp::OS_COMMITTING:
19585  case SchemaOp::OS_COMPLETING:
19586  {
19587  jam();
19588  Uint32* data = &signal->theData[0];
19589  data[0] = ZDICT_TAKEOVER_REQ;
19590  memmove(&data[1], &data[0], DictTakeoverReq::SignalLength << 2);
19591  sendSignal(reference(), GSN_CONTINUEB, signal,
19592  1 + DictTakeoverReq::SignalLength, JBB);
19593  return;
19594  }
19595  default:
19596  break;
19597  }
19598  if (ending)
19599  {
19600  pending_op = list.next(op_ptr);
19601  continue;
19602  }
19603  if (trans_ptr.p->m_state == SchemaTrans::TS_STARTED || // master
19604  trans_ptr.p->m_state == SchemaTrans::TS_PARSING)
19605  {
19606  jam();
19607  /*
19608  We were parsing operations from client, check how
19609  far slave got by finding highest operation.
19610  */
19611  highest_op = op_ptr.p->op_key;
19612  highest_op_state = op_ptr.p->m_state;
19613  /*
19614  Find the OpInfo gsn for the latest created operation,
19615  this might be needed by new master to create missing operation.
19616  */
19617  highest_op_impl_req_gsn = getOpInfo(op_ptr).m_impl_req_gsn;
19618  }
19619  else
19620  {
19621  jam();
19622 #ifdef VM_TRACE
19623  ndbout_c("Op %u, state %u, rollforward %u/%u, rollback %u/%u",op_ptr.p->op_key,op_ptr.p->m_state, rollforward_op, rollforward_op_state, rollback_op, rollback_op_state);
19624 #endif
19625  /*
19626  Find the starting point for a roll forward, the first
19627  operation found with a lower state than the previous.
19628  */
19629  if (SchemaOp::weight(op_ptr.p->m_state) <
19630  SchemaOp::weight(rollforward_op_state))
19631  {
19632  rollforward_op = op_ptr.p->op_key;
19633  rollforward_op_state = op_ptr.p->m_state;
19634  }
19635  /*
19636  Find the starting point for a rollback, the last
19637  operation found that changed state.
19638  */
19639  if (SchemaOp::weight(op_ptr.p->m_state) >=
19640  SchemaOp::weight(rollback_op_state))
19641  {
19642  rollback_op = op_ptr.p->op_key;
19643  rollback_op_state = op_ptr.p->m_state;
19644  }
19645  }
19646  pending_op = list.next(op_ptr);
19647  }
19648 #ifdef VM_TRACE
19649  ndbout_c("Slave transaction %u has %u schema operations, rf %u/%u, rb %u/%u", trans_ptr.p->trans_key, op_count, rollforward_op, rollforward_op_state, rollback_op, rollback_op_state);
19650 #endif
19651  DictTakeoverConf* conf = (DictTakeoverConf*)signal->getDataPtrSend();
19652  conf->senderRef = reference();
19653  conf->clientRef = trans_ptr.p->m_clientRef;
19654  conf->trans_key = trans_ptr.p->trans_key;
19655  conf->trans_state = trans_ptr.p->m_state;
19656  conf->op_count = op_count;
19657  conf->rollforward_op = rollforward_op;
19658  conf->rollforward_op_state = rollforward_op_state;
19659  conf->rollback_op = rollback_op;
19660  conf->rollback_op_state = rollback_op_state;
19661  if (trans_ptr.p->m_state == SchemaTrans::TS_STARTED ||
19662  trans_ptr.p->m_state == SchemaTrans::TS_PARSING)
19663  {
19664  /*
19665  New master might not have parsed highest found operation yet.
19666  */
19667  conf->highest_op = highest_op;
19668  conf->highest_op_state = highest_op_state;
19669  conf->highest_op_impl_req_gsn = highest_op_impl_req_gsn;
19670  }
19671  if (ending)
19672  {
19673  /*
19674  New master might already have released lowest operation found.
19675  */
19676  conf->lowest_op = lowest_op;
19677  conf->lowest_op_state = lowest_op_state;
19678  conf->lowest_op_impl_req_gsn = lowest_op_impl_req_gsn;
19679  }
19680  sendSignal(masterRef, GSN_DICT_TAKEOVER_CONF, signal,
19681  DictTakeoverConf::SignalLength, JBB);
19682  ndbrequire(!(pending_trans = c_schemaTransList.next(trans_ptr)));
19683  }
19684  }
19685 
19686 void
19687 Dbdict::execDICT_TAKEOVER_REF(Signal* signal)
19688 {
19689  DictTakeoverRef* ref = (DictTakeoverRef*)signal->getDataPtr();
19690  Uint32 senderRef = ref->senderRef;
19691  Uint32 nodeId = refToNode(senderRef);
19692  Uint32 masterRef = ref->masterRef;
19693  NodeRecordPtr masterNodePtr;
19694  jamEntry();
19695 #ifdef VM_TRACE
19696  ndbout_c("Dbdict::execDICT_TAKEOVER_REF: error %u, from %u", ref->errorCode, nodeId);
19697 #endif
19698  /*
19699  Slave has died (didn't reply) or doesn't not have any transaction
19700  Ignore it during rest of master takeover.
19701  */
19702  ndbassert(refToNode(masterRef) == c_masterNodeId);
19703  c_nodes.getPtr(masterNodePtr, c_masterNodeId);
19704  masterNodePtr.p->m_nodes.clear(nodeId);
19705  /*
19706  Check if we got replies from all nodes
19707  */
19708  {
19709  SafeCounter sc(c_counterMgr, masterNodePtr.p->m_counter);
19710  if (!sc.clearWaitingFor(nodeId)) {
19711  jam();
19712  return;
19713  }
19714  }
19715  check_takeover_replies(signal);
19716 }
19717 
19718 void
19719 Dbdict::execDICT_TAKEOVER_CONF(Signal* signal)
19720 {
19721  jamEntry();
19722  DictTakeoverConf* conf = (DictTakeoverConf*)signal->getDataPtr();
19723  jamEntry();
19724  Uint32 senderRef = conf->senderRef;
19725  Uint32 nodeId = refToNode(senderRef);
19726  //Uint32 clientRef = conf->clientRef;
19727  //Uint32 op_count = conf->op_count;
19728  //Uint32 trans_key = conf->trans_key;
19729  //Uint32 rollforward_op = conf->rollforward_op;
19730  //Uint32 rollforward_op_state = conf->rollforward_op_state;
19731  //Uint32 rollback_op = conf->rollback_op;
19732  //Uint32 rollback_op_state = conf->rollback_op_state;
19733  NodeRecordPtr masterNodePtr;
19734 
19735  /*
19736  Accumulate all responses
19737  */
19738  NodeRecordPtr nodePtr;
19739  c_nodes.getPtr(nodePtr, nodeId);
19740  nodePtr.p->takeOverConf = *conf;
19741 
19742  ndbassert(getOwnNodeId() == c_masterNodeId);
19743  c_nodes.getPtr(masterNodePtr, c_masterNodeId);
19744 #ifdef VM_TRACE
19745  ndbout_c("execDICT_TAKEOVER_CONF: Node %u, trans %u(%u), count %u, rollf %u/%u, rb %u/%u",
19746  nodeId, conf->trans_key, conf->trans_state, conf->op_count, conf->rollforward_op,
19747  conf->rollforward_op_state, conf->rollback_op, conf->rollback_op_state);
19748 #endif
19749 
19750  /*
19751  Check that we got reply from all nodes
19752  */
19753  {
19754  SafeCounter sc(c_counterMgr, masterNodePtr.p->m_counter);
19755  if (!sc.clearWaitingFor(nodeId)) {
19756  jam();
19757  return;
19758  }
19759  }
19760  check_takeover_replies(signal);
19761 }
19762 
19763 void Dbdict::check_takeover_replies(Signal* signal)
19764 {
19765  SchemaTransPtr trans_ptr;
19766  NodeRecordPtr masterNodePtr;
19767  ErrorInfo error;
19768 
19769  c_nodes.getPtr(masterNodePtr, c_masterNodeId); // this node
19770  if (masterNodePtr.p->m_nodes.isclear())
19771  {
19772  /*
19773  No slave found any pending transactions, we are done
19774  */
19775  jam();
19776  send_nf_complete_rep(signal, &masterNodePtr.p->nodeFailRep);
19777  return;
19778  }
19779  /*
19780  Take schema trans lock.
19781  Set initial values for rollforward/rollback points
19782  and highest/lowest transaction states
19783  */
19784  bool pending_trans = c_schemaTransList.first(trans_ptr);
19785  while (pending_trans) {
19786  jam();
19787  Uint32 trans_key = trans_ptr.p->trans_key;
19788  DictLockReq& lockReq = trans_ptr.p->m_lockReq;
19789  lockReq.userPtr = trans_key;
19790  lockReq.userRef = reference();
19791  lockReq.lockType = DictLockReq::SchemaTransLock;
19792  int lockError = dict_lock_trylock(&lockReq);
19793  if (lockError != 0)
19794  {
19795  jam();
19796 #ifdef VM_TRACE
19797  ndbout_c("New master failed locking transaction %u, error %u", trans_key, lockError);
19798 #endif
19799  ndbassert(false);
19800  }
19801  else
19802  {
19803  jam();
19804 #ifdef VM_TRACE
19805  ndbout_c("New master locked transaction %u", trans_key);
19806 #endif
19807  }
19808  trans_ptr.p->m_isMaster = true;
19809  trans_ptr.p->m_nodes.clear();
19810  trans_ptr.p->m_rollforward_op = -1;
19811  trans_ptr.p->m_rollforward_op_state = SchemaOp::OS_COMPLETED;
19812  trans_ptr.p->m_rollback_op = 0;
19813  trans_ptr.p->m_rollback_op_state = SchemaOp::OS_INITIAL;
19814  trans_ptr.p->m_lowest_trans_state = SchemaTrans::TS_ENDING;
19815  trans_ptr.p->m_highest_trans_state = SchemaTrans::TS_INITIAL;
19816  trans_ptr.p->check_partial_rollforward = false;
19817  trans_ptr.p->ressurected_op = false;
19818  pending_trans = c_schemaTransList.next(trans_ptr);
19819  }
19820  /*
19821  Find rollforward/rollback operations and highest/lowest transaction state
19822  */
19823  for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
19824  jam();
19825  NodeRecordPtr nodePtr;
19826  if (masterNodePtr.p->m_nodes.get(i))
19827  {
19828  jam();
19829  c_nodes.getPtr(nodePtr, i);
19830  {
19831  DictTakeoverConf* conf = &nodePtr.p->takeOverConf;
19832  Uint32 clientRef = conf->clientRef;
19833  Uint32 rollforward_op = conf->rollforward_op;
19834  Uint32 rollforward_op_state = conf->rollforward_op_state;
19835  Uint32 rollback_op = conf->highest_op;
19836  Uint32 rollback_op_state = conf->rollback_op_state;
19837  Uint32 trans_key = conf->trans_key;
19838  Uint32 trans_state = conf->trans_state;
19839  SchemaTransPtr trans_ptr;
19840 
19841  if (!findSchemaTrans(trans_ptr, trans_key))
19842  {
19843  jam();
19844  /*
19845  New master doesn't know about the transaction.
19846  */
19847  if (!seizeSchemaTrans(trans_ptr, trans_key))
19848  {
19849  jam();
19850  ndbassert(false);
19851  }
19852 #ifdef VM_TRACE
19853  ndbout_c("New master seized transaction %u", trans_key);
19854 #endif
19855  /*
19856  Take schema trans lock.
19857  */
19858  DictLockReq& lockReq = trans_ptr.p->m_lockReq;
19859  lockReq.userPtr = trans_ptr.p->trans_key;
19860  lockReq.userRef = reference();
19861  lockReq.lockType = DictLockReq::SchemaTransLock;
19862  int lockError = dict_lock_trylock(&lockReq);
19863  if (lockError != 0)
19864  {
19865  jam();
19866 #ifdef VM_TRACE
19867  ndbout_c("New master failed locking transaction %u, error %u", trans_key, lockError);
19868 #endif
19869  ndbassert(false);
19870  }
19871  else
19872  {
19873  jam();
19874 #ifdef VM_TRACE
19875  ndbout_c("New master locked transaction %u", trans_key);
19876 #endif
19877  }
19878  trans_ptr.p->m_rollforward_op = -1;
19879  trans_ptr.p->m_rollforward_op_state = SchemaOp::OS_COMPLETED;
19880  trans_ptr.p->m_rollback_op = 0;
19881  trans_ptr.p->m_rollback_op_state = SchemaOp::OS_INITIAL;
19882  trans_ptr.p->m_lowest_trans_state = SchemaTrans::TS_ENDING;
19883  trans_ptr.p->m_highest_trans_state = SchemaTrans::TS_INITIAL;
19884  }
19885 
19886  trans_ptr.p->m_isMaster = true;
19887  trans_ptr.p->m_masterRef = reference();
19888  trans_ptr.p->m_clientRef = clientRef;
19889  trans_ptr.p->m_nodes.set(i);
19890 #ifdef VM_TRACE
19891  ndbout_c("Adding node %u to transaction %u", i, trans_ptr.p->trans_key);
19892 #endif
19893  /*
19894  Save the operation with lowest state and lowest key
19895  for roll forward
19896  */
19897  if ((SchemaOp::weight(rollforward_op_state) <
19898  SchemaOp::weight(trans_ptr.p->m_rollforward_op_state)) ||
19899  ((rollforward_op_state ==
19900  trans_ptr.p->m_rollforward_op_state &&
19901  rollforward_op < trans_ptr.p->m_rollforward_op)))
19902  {
19903  jam();
19904  trans_ptr.p->m_rollforward_op = rollforward_op;
19905  trans_ptr.p->m_rollforward_op_state = rollforward_op_state;
19906  }
19907 
19908  /*
19909  Save operation with the highest state and the highest key
19910  for rollback
19911  */
19912  if ((SchemaOp::weight(rollback_op_state) >
19913  SchemaOp::weight(trans_ptr.p->m_rollback_op_state)) ||
19914  ((rollback_op_state ==
19915  trans_ptr.p->m_rollback_op_state &&
19916  rollback_op > trans_ptr.p->m_rollback_op)))
19917  {
19918  jam();
19919  trans_ptr.p->m_rollback_op = rollback_op;
19920  trans_ptr.p->m_rollback_op_state = rollback_op_state;
19921  }
19922 
19923  if (SchemaTrans::weight(trans_state) <
19924  SchemaTrans::weight(trans_ptr.p->m_lowest_trans_state))
19925  {
19926  jam();
19927  trans_ptr.p->m_lowest_trans_state = trans_state;
19928  }
19929  if (SchemaTrans::weight(trans_state) >
19930  SchemaTrans::weight(trans_ptr.p->m_highest_trans_state))
19931  {
19932  jam();
19933  trans_ptr.p->m_highest_trans_state = trans_state;
19934  }
19935  }
19936  }
19937  }
19938 
19939  /*
19940  Check the progress of transactions.
19941  */
19942  pending_trans = c_schemaTransList.first(trans_ptr);
19943  while (pending_trans)
19944  {
19945  jam();
19946 #ifdef VM_TRACE
19947  ndbout_c("Analyzing transaction progress, trans %u/%u, lowest/highest %u/%u", trans_ptr.p->trans_key, trans_ptr.p->m_state, trans_ptr.p->m_lowest_trans_state, trans_ptr.p->m_highest_trans_state);
19948 #endif
19949  switch(trans_ptr.p->m_highest_trans_state) {
19950  case SchemaTrans::TS_INITIAL:
19951  case SchemaTrans::TS_STARTING:
19952  case SchemaTrans::TS_STARTED:
19953  case SchemaTrans::TS_PARSING:
19954  case SchemaTrans::TS_SUBOP:
19955  case SchemaTrans::TS_ROLLBACK_SP:
19956  case SchemaTrans::TS_FLUSH_PREPARE:
19957  case SchemaTrans::TS_PREPARING:
19958  case SchemaTrans::TS_ABORTING_PREPARE:
19959  case SchemaTrans::TS_ABORTING_PARSE:
19960  jam();
19961  trans_ptr.p->m_master_recovery_state = SchemaTrans::TRS_ROLLBACK;
19962  break;
19963  case SchemaTrans::TS_FLUSH_COMMIT:
19964  case SchemaTrans::TS_COMMITTING:
19965  case SchemaTrans::TS_FLUSH_COMPLETE:
19966  case SchemaTrans::TS_COMPLETING:
19967  case SchemaTrans::TS_ENDING:
19968  jam();
19969  trans_ptr.p->m_master_recovery_state = SchemaTrans::TRS_ROLLFORWARD;
19970  break;
19971  }
19972 
19973  if (trans_ptr.p->m_master_recovery_state == SchemaTrans::TRS_ROLLFORWARD)
19974  {
19975  /*
19976  We must start rolling forward from lowest state of any slave
19977  and partially skip more progressed slaves.
19978  */
19979  jam();
19980  infoEvent("Pending schema transaction %u will be rolled forward", trans_ptr.p->trans_key);
19981  trans_ptr.p->check_partial_rollforward = true;
19982  trans_ptr.p->m_state = trans_ptr.p->m_lowest_trans_state;
19983 #ifdef VM_TRACE
19984  ndbout_c("Setting transaction state to %u for rollforward", trans_ptr.p->m_state);
19985 #endif
19986  }
19987  else
19988  {
19989  /*
19990  We must start rolling back from highest state of any slave
19991  and partially skip less progressed slaves.
19992  */
19993  jam();
19994  infoEvent("Pending schema transaction %u will be rolled back", trans_ptr.p->trans_key);
19995  trans_ptr.p->m_state = trans_ptr.p->m_highest_trans_state;
19996 #ifdef VM_TRACE
19997  ndbout_c("Setting transaction state to %u for rollback", trans_ptr.p->m_state);
19998 #endif
19999  }
20000 #ifdef VM_TRACE
20001  ndbout_c("Setting start state for transaction %u to %u", trans_ptr.p->trans_key, trans_ptr.p->m_state);
20002 #endif
20003  pending_trans = c_schemaTransList.next(trans_ptr);
20004  }
20005 
20006  /*
20007  Initialize all node recovery states
20008  */
20009  for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
20010  jam();
20011  NodeRecordPtr nodePtr;
20012  c_nodes.getPtr(nodePtr, i);
20013  nodePtr.p->recoveryState = NodeRecord::RS_NORMAL;
20014  }
20015 
20016  pending_trans = c_schemaTransList.first(trans_ptr);
20017  while (pending_trans)
20018  {
20019  /*
20020  Find nodes that need partial rollforward/rollback,
20021  create any missing operations on new master
20022  */
20023 
20024  for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
20025  jam();
20026  NodeRecordPtr nodePtr;
20027  if (trans_ptr.p->m_nodes.get(i))
20028  {
20029  jam();
20030  c_nodes.getPtr(nodePtr, i);
20031 #ifdef VM_TRACE
20032  ndbout_c("Node %u had %u operations, master has %u",i , nodePtr.p->takeOverConf.op_count, masterNodePtr.p->takeOverConf.op_count);
20033 #endif
20034  if (nodePtr.p->takeOverConf.op_count == 0)
20035  {
20036  if (SchemaTrans::weight(trans_ptr.p->m_state)
20037  < SchemaTrans::weight(SchemaTrans::TS_PREPARING))
20038  {
20039  /*
20040  Node didn't parse any operations,
20041  remove, skip it when aborting parse.
20042  */
20043  jam();
20044 #ifdef VM_TRACE
20045  ndbout_c("Node %u had no operations for transaction %u, ignore it when aborting", i, trans_ptr.p->trans_key);
20046 #endif
20047  nodePtr.p->start_op = 0;
20048  nodePtr.p->start_op_state = SchemaOp::OS_PARSED;
20049  }
20050  else
20051  {
20052  /*
20053  Node is ended
20054  */
20055  jam();
20056  // Is this possible??
20057  }
20058  }
20059  else if (nodePtr.p->takeOverConf.op_count <
20060  masterNodePtr.p->takeOverConf.op_count)
20061  {
20062  jam();
20063  /*
20064  Operation is missing on slave
20065  */
20066  if (SchemaTrans::weight(trans_ptr.p->m_state) <
20067  SchemaTrans::weight(SchemaTrans::TS_PREPARING))
20068  {
20069  /*
20070  Last parsed operation is missing on slave, skip it
20071  when aborting parse.
20072  */
20073  jam();
20074 #ifdef VM_TRACE
20075  ndbout_c("Node %u did not have all operations for transaction %u, skip > %u", i, trans_ptr.p->trans_key, nodePtr.p->takeOverConf.highest_op);
20076 #endif
20077  nodePtr.p->recoveryState = NodeRecord::RS_PARTIAL_ROLLBACK;
20078  nodePtr.p->start_op = nodePtr.p->takeOverConf.highest_op;
20079  nodePtr.p->start_op_state = nodePtr.p->takeOverConf.highest_op_state;
20080  }
20081  else
20082  {
20083  /*
20084  Slave has already ended some operations
20085  */
20086  jam();
20087 #ifdef VM_TRACE
20088  ndbout_c("Node %u did not have all operations for transaction %u, skip < %u", i, trans_ptr.p->trans_key, nodePtr.p->takeOverConf.lowest_op);
20089 #endif
20090  nodePtr.p->recoveryState = NodeRecord::RS_PARTIAL_ROLLFORWARD;
20091  nodePtr.p->start_op = nodePtr.p->takeOverConf.lowest_op;
20092  nodePtr.p->start_op_state = nodePtr.p->takeOverConf.lowest_op_state;
20093  }
20094  }
20095  else if (nodePtr.p->takeOverConf.op_count >
20096  masterNodePtr.p->takeOverConf.op_count)
20097  {
20098  /*
20099  Operation missing on new master
20100  */
20101  jam();
20102  if (SchemaTrans::weight(trans_ptr.p->m_state)
20103  < SchemaTrans::weight(SchemaTrans::TS_PREPARING))
20104  {
20105  /*
20106  Last parsed operation is missing on new master
20107  */
20108  jam();
20109  if (masterNodePtr.p->recoveryState !=
20110  NodeRecord::RS_PARTIAL_ROLLBACK)
20111  {
20112  /*
20113  We haven't decided to partially rollback master yet.
20114  Operation is missing on new master (not yet parsed).
20115  Create it so new master can tell slaves to abort it,
20116  but skip it on master.
20117  */
20118  jam();
20119  SchemaOpPtr missing_op_ptr;
20120  const OpInfo& info =
20121  *findOpInfo(nodePtr.p->takeOverConf.highest_op_impl_req_gsn);
20122  if (seizeSchemaOp(missing_op_ptr,
20123  nodePtr.p->takeOverConf.highest_op,
20124  info))
20125  {
20126  jam();
20127 #ifdef VM_TRACE
20128  ndbout_c("Created missing operation %u, on new master", missing_op_ptr.p->op_key);
20129 #endif
20130  addSchemaOp(trans_ptr, missing_op_ptr);
20131  missing_op_ptr.p->m_state = nodePtr.p->takeOverConf.highest_op_state;
20132  masterNodePtr.p->recoveryState = NodeRecord::RS_PARTIAL_ROLLBACK;
20133  masterNodePtr.p->start_op = masterNodePtr.p->takeOverConf.highest_op;
20134  masterNodePtr.p->start_op_state = masterNodePtr.p->takeOverConf.highest_op_state;
20135  }
20136  else
20137  {
20138  jam();
20139  ndbassert(false);
20140  }
20141  trans_ptr.p->m_nodes.set(c_masterNodeId);
20142 #ifdef VM_TRACE
20143  ndbout_c("Adding master node %u to transaction %u", c_masterNodeId, trans_ptr.p->trans_key);
20144 #endif
20145  }
20146  }
20147  else if (SchemaTrans::weight(trans_ptr.p->m_state)
20148  >= SchemaTrans::weight(SchemaTrans::TS_PREPARING) &&
20149  (!trans_ptr.p->ressurected_op))
20150  {
20151  /*
20152  New master has already ended some operation,
20153  create it again so we can tell slaves to end it.
20154  Note: we don't add node to transaction since the
20155  ressurected operation cannot be completed. Instead
20156  we need to release it explicitly when transaction is
20157  ended.
20158  */
20159  jam();
20160  SchemaOpPtr missing_op_ptr;
20161  Uint32 op_key = nodePtr.p->takeOverConf.lowest_op;
20162  Uint32 op_state = nodePtr.p->takeOverConf.lowest_op_state;
20163  const OpInfo& info =
20164  *findOpInfo(nodePtr.p->takeOverConf.lowest_op_impl_req_gsn);
20165  if (seizeSchemaOp(missing_op_ptr,
20166  op_key,
20167  info))
20168  {
20169  jam();
20170 #ifdef VM_TRACE
20171  ndbout_c("Created ressurected operation %u, on new master", op_key);
20172 #endif
20173  addSchemaOp(trans_ptr, missing_op_ptr);
20174  trans_ptr.p->ressurected_op = true;
20175  missing_op_ptr.p->m_state = op_state;
20176  nodePtr.p->recoveryState = NodeRecord::RS_PARTIAL_ROLLFORWARD;
20177  nodePtr.p->start_op = op_key;
20178  nodePtr.p->start_op_state = op_state;
20179 
20180  }
20181  else
20182  {
20183  jam();
20184  assert(false);
20185  }
20186  continue;
20187  }
20188  }
20189  }
20190  }
20191 
20192  /*
20193  Compare node progress
20194  */
20195  for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
20196  jam();
20197  NodeRecordPtr nodePtr;
20198  if (trans_ptr.p->m_nodes.get(i))
20199  {
20200  jam();
20201  c_nodes.getPtr(nodePtr, i);
20202 #ifdef VM_TRACE
20203  ndbout_c("Comparing node %u rollforward(%u(%u)<%u(%u))/rollback(%u(%u)<%u(%u))", i, nodePtr.p->takeOverConf.rollforward_op_state, nodePtr.p->takeOverConf.rollforward_op, trans_ptr.p->m_rollforward_op_state, trans_ptr.p->m_rollforward_op, nodePtr.p->takeOverConf.rollback_op_state, nodePtr.p->takeOverConf.rollback_op, trans_ptr.p->m_rollback_op_state, trans_ptr.p->m_rollback_op);
20204 #endif
20205  if (trans_ptr.p->m_master_recovery_state == SchemaTrans::TRS_ROLLFORWARD)
20206  {
20207  jam();
20208  if (trans_ptr.p->m_lowest_trans_state == SchemaTrans::TS_PREPARING &&
20209  nodePtr.p->takeOverConf.trans_state == SchemaTrans::TS_COMMITTING)
20210  {
20211  /*
20212  Some slave have flushed the commit start, but not all.
20213  Flushed slaves need to be partially rolled forward.
20214  */
20215  jam();
20216  nodePtr.p->recoveryState = NodeRecord::RS_PARTIAL_ROLLFORWARD;
20217 #ifdef VM_TRACE
20218  ndbout_c("Node %u will be partially rolled forward, skipping RT_FLUSH_COMMIT", nodePtr.i);
20219 #endif
20220  }
20221  else if (SchemaOp::weight(nodePtr.p->takeOverConf.rollforward_op_state) >
20222  SchemaOp::weight(trans_ptr.p->m_rollforward_op_state) ||
20223  nodePtr.p->takeOverConf.rollforward_op >
20224  trans_ptr.p->m_rollforward_op)
20225  {
20226  /*
20227  Slave has started committing, but other slaves have non-committed
20228  operations. Node needs to be partially rollforward.
20229  */
20230  jam();
20231  nodePtr.p->recoveryState = NodeRecord::RS_PARTIAL_ROLLFORWARD;
20232  nodePtr.p->start_op = nodePtr.p->takeOverConf.rollforward_op;
20233  nodePtr.p->start_op_state = nodePtr.p->takeOverConf.rollforward_op_state;
20234 #ifdef VM_TRACE
20235  ndbout_c("Node %u will be partially rolled forward to operation %u, state %u", nodePtr.i, nodePtr.p->start_op, nodePtr.p->start_op_state);
20236 #endif
20237  if (i == c_masterNodeId)
20238  {
20239  /*
20240  New master is ahead of other slaves
20241  Change operation state back to rollforward
20242  other slaves.
20243  */
20244  jam();
20245  SchemaOpPtr op_ptr;
20246  ndbrequire(findSchemaOp(op_ptr,
20247  trans_ptr.p->m_rollforward_op));
20248 #ifdef VM_TRACE
20249  ndbout_c("Changed op %u from state %u to %u", trans_ptr.p->m_rollforward_op, op_ptr.p->m_state, trans_ptr.p->m_rollforward_op_state);
20250 #endif
20251  op_ptr.p->m_state = trans_ptr.p->m_rollforward_op_state;
20252  }
20253  }
20254  else if (trans_ptr.p->m_lowest_trans_state == SchemaTrans::TS_COMMITTING &&
20255  nodePtr.p->takeOverConf.trans_state >= SchemaTrans::TS_FLUSH_COMPLETE)
20256  {
20257  /*
20258  Some slave have flushed the commit complete, but not all.
20259  Flushed slaves need to be partially rolled forward.
20260  */
20261  jam();
20262  nodePtr.p->recoveryState = NodeRecord::RS_PARTIAL_ROLLFORWARD;
20263 #ifdef VM_TRACE
20264  ndbout_c("Node %u will be partially rolled forward, skipping RT_FLUSH_COMPLETE", nodePtr.i);
20265 #endif
20266  }
20267  }
20268  else // if (trans_ptr.p->m_master_recovery_state == SchemaTrans::TRS_ROLLBACK)
20269  {
20270  jam();
20271  if (SchemaOp::weight(nodePtr.p->takeOverConf.rollback_op_state) <
20272  SchemaOp::weight(trans_ptr.p->m_rollback_op_state) ||
20273  nodePtr.p->takeOverConf.rollback_op <
20274  trans_ptr.p->m_rollback_op)
20275  {
20276  /*
20277  Slave is behind. Other nodes have further
20278  progress, or has already started aborting.
20279  Node needs to be partially rolled back.
20280  */
20281  jam();
20282  nodePtr.p->recoveryState = NodeRecord::RS_PARTIAL_ROLLBACK;
20283  nodePtr.p->start_op = nodePtr.p->takeOverConf.rollback_op;
20284  nodePtr.p->start_op_state = nodePtr.p->takeOverConf.rollback_op_state;
20285 #ifdef VM_TRACE
20286  ndbout_c("Node %u will be partially rolled back from operation %u, state %u", nodePtr.i, nodePtr.p->start_op, nodePtr.p->start_op_state);
20287 #endif
20288  if (i == c_masterNodeId &&
20289  (SchemaTrans::weight(trans_ptr.p->m_state) <=
20290  SchemaTrans::weight(SchemaTrans::TS_PREPARING)))
20291  {
20292  /*
20293  New master is behind of other slaves
20294  Change operation state forward to rollback
20295  other slaves.
20296  */
20297  jam();
20298  SchemaOpPtr op_ptr;
20299  ndbrequire(findSchemaOp(op_ptr,
20300  trans_ptr.p->m_rollback_op));
20301 #ifdef VM_TRACE
20302  ndbout_c("Changed op %u from state %u to %u", trans_ptr.p->m_rollback_op, op_ptr.p->m_state, trans_ptr.p->m_rollback_op_state);
20303 #endif
20304  op_ptr.p->m_state = trans_ptr.p->m_rollback_op_state;
20305  }
20306  }
20307  }
20308  }
20309  }
20310  /*
20311  Set current op to the lowest/highest reported by slaves
20312  depending on if decision is to rollforward/rollback.
20313  */
20314  if (trans_ptr.p->m_master_recovery_state == SchemaTrans::TRS_ROLLFORWARD)
20315  {
20316  jam();
20317  SchemaOpPtr rollforward_op_ptr;
20318  ndbrequire(findSchemaOp(rollforward_op_ptr, trans_ptr.p->m_rollforward_op));
20319  trans_ptr.p->m_curr_op_ptr_i = rollforward_op_ptr.i;
20320 #ifdef VM_TRACE
20321  ndbout_c("execDICT_TAKEOVER_CONF: Transaction %u rolled forward starting at %u(%u)", trans_ptr.p->trans_key, trans_ptr.p->m_rollforward_op, trans_ptr.p->m_curr_op_ptr_i);
20322 #endif
20323  }
20324  else // if (trans_ptr.p->master_recovery_state == SchemaTrans::TRS_ROLLBACK)
20325  {
20326  jam();
20327  if (trans_ptr.p->m_state >= SchemaTrans::TS_PARSING)
20328  {
20329  /*
20330  Some slave had at least started parsing operations
20331  */
20332  jam();
20333  SchemaOpPtr rollback_op_ptr;
20334  ndbrequire(findSchemaOp(rollback_op_ptr, trans_ptr.p->m_rollback_op));
20335  trans_ptr.p->m_curr_op_ptr_i = rollback_op_ptr.i;
20336 #ifdef VM_TRACE
20337  ndbout_c("execDICT_TAKEOVER_CONF: Transaction %u rolled back starting at %u(%u)", trans_ptr.p->trans_key, trans_ptr.p->m_rollback_op, trans_ptr.p->m_curr_op_ptr_i);
20338 #endif
20339  }
20340  }
20341 
20342  trans_recover(signal, trans_ptr);
20343  pending_trans = c_schemaTransList.next(trans_ptr);
20344  }
20345 }
20346 
20347 
20348 // NF handling
20349 
20350 void
20351 Dbdict::removeStaleDictLocks(Signal* signal, const Uint32* theFailedNodes)
20352 {
20353  LockQueue::Iterator iter;
20354  if (m_dict_lock.first(this, m_dict_lock_pool, iter))
20355  {
20356 #ifdef MARTIN
20357  infoEvent("Iterating lock queue");
20358 #endif
20359  do {
20360  if (NodeBitmask::get(theFailedNodes,
20361  refToNode(iter.m_curr.p->m_req.senderRef)))
20362  {
20363  if (iter.m_curr.p->m_req.requestInfo & UtilLockReq::Granted)
20364  {
20365  jam();
20366  infoEvent("Removed lock for node %u", refToNode(iter.m_curr.p->m_req.senderRef));
20367  sendDictLockInfoEvent(signal, &iter.m_curr.p->m_req,
20368  "remove lock by failed node");
20369  }
20370  else
20371  {
20372  jam();
20373  infoEvent("Removed lock request for node %u", refToNode(iter.m_curr.p->m_req.senderRef));
20374  sendDictLockInfoEvent(signal, &iter.m_curr.p->m_req,
20375  "remove lock request by failed node");
20376  }
20377  DictUnlockOrd* ord = (DictUnlockOrd*)signal->getDataPtrSend();
20378  ord->senderRef = iter.m_curr.p->m_req.senderRef;
20379  ord->senderData = iter.m_curr.p->m_req.senderData;
20380  ord->lockPtr = iter.m_curr.p->m_req.senderData;
20381  ord->lockType = iter.m_curr.p->m_req.extra;
20382  sendSignal(reference(), GSN_DICT_UNLOCK_ORD, signal,
20383  DictUnlockOrd::SignalLength, JBB);
20384  }
20385  } while (m_dict_lock.next(iter));
20386  }
20387 }
20388 
20389 Uint32
20391 {
20392  UtilLockReq req;
20393  const UtilLockReq *lockOwner;
20394  req.senderData = _req->userPtr;
20395  req.senderRef = _req->userRef;
20396  req.extra = _req->lockType;
20397  req.requestInfo = UtilLockReq::TryLock | UtilLockReq::Notify;
20398 
20399  Uint32 res = m_dict_lock.lock(this, m_dict_lock_pool, &req, &lockOwner);
20400  switch(res){
20401  case UtilLockRef::OK:
20402  jam();
20403  return 0;
20404  case UtilLockRef::LockAlreadyHeld:
20405  jam();
20406  if (lockOwner->extra == DictLockReq::NodeRestartLock)
20407  {
20408  jam();
20409  return SchemaTransBeginRef::BusyWithNR;
20410  }
20411  break;
20412  case UtilLockRef::OutOfLockRecords:
20413  jam();
20414  break;
20415  case UtilLockRef::InLockQueue:
20416  jam();
20420  ndbassert(false);
20421  break;
20422  }
20423 #ifdef MARTIN
20424  infoEvent("Busy with schema transaction");
20425 #endif
20426  return SchemaTransBeginRef::Busy;
20427 }
20428 
20429 Uint32
20431 {
20432  UtilUnlockReq req;
20433  req.senderData = _req->userPtr;
20434  req.senderRef = _req->userRef;
20435 
20436  Uint32 res = m_dict_lock.unlock(this, m_dict_lock_pool, &req);
20437  switch(res){
20438  case UtilUnlockRef::OK:
20439  case UtilUnlockRef::NotLockOwner:
20440  break;
20441  case UtilUnlockRef::NotInLockQueue:
20442  ndbassert(false);
20443  return res;
20444  }
20445 
20446  UtilLockReq lockReq;
20447  LockQueue::Iterator iter;
20448  if (m_dict_lock.first(this, m_dict_lock_pool, iter))
20449  {
20450  int res;
20451  while ((res = m_dict_lock.checkLockGrant(iter, &lockReq)) > 0)
20452  {
20453  jam();
20457  if (res == 2)
20458  {
20459  jam();
20460  DictLockConf* conf = (DictLockConf*)signal->getDataPtrSend();
20461  conf->userPtr = lockReq.senderData;
20462  conf->lockPtr = lockReq.senderData;
20463  conf->lockType = lockReq.extra;
20464  sendSignal(lockReq.senderRef, GSN_DICT_LOCK_CONF, signal,
20465  DictLockConf::SignalLength, JBB);
20466  }
20467 
20468  if (!m_dict_lock.next(iter))
20469  break;
20470  }
20471  }
20472 
20473  return res;
20474 }
20475 
20476 void
20477 Dbdict::execBACKUP_LOCK_TAB_REQ(Signal* signal)
20478 {
20479  jamEntry();
20480  BackupLockTab *req = (BackupLockTab *)signal->getDataPtrSend();
20481  Uint32 senderRef = req->m_senderRef;
20482  Uint32 tableId = req->m_tableId;
20483  Uint32 lock = req->m_lock_unlock;
20484 
20485  TableRecordPtr tablePtr;
20486  c_tableRecordPool.getPtr(tablePtr, tableId, true);
20487 
20488  Uint32 err = 0;
20489  if(lock == BackupLockTab::LOCK_TABLE)
20490  {
20491  jam();
20492  if ((err = check_write_obj(tableId)) == 0)
20493  {
20494  jam();
20495  tablePtr.p->m_read_locked = 1;
20496  }
20497  }
20498  else
20499  {
20500  jam();
20501  tablePtr.p->m_read_locked = 0;
20502  }
20503 
20504  req->errorCode = err;
20505  sendSignal(senderRef, GSN_BACKUP_LOCK_TAB_CONF, signal,
20506  BackupLockTab::SignalLength, JBB);
20507 }
20508 
20509 /* **************************************************************** */
20510 /* ---------------------------------------------------------------- */
20511 /* MODULE: STORE/RESTORE SCHEMA FILE---------------------- */
20512 /* ---------------------------------------------------------------- */
20513 /* */
20514 /* General module used to store the schema file on disk and */
20515 /* similar function to restore it from disk. */
20516 /* ---------------------------------------------------------------- */
20517 /* **************************************************************** */
20518 
20519 void
20520 Dbdict::initSchemaFile(XSchemaFile * xsf, Uint32 firstPage, Uint32 lastPage,
20521  bool initEntries)
20522 {
20523  ndbrequire(lastPage <= xsf->noOfPages);
20524  for (Uint32 n = firstPage; n < lastPage; n++) {
20525  SchemaFile * sf = &xsf->schemaPage[n];
20526  if (initEntries)
20527  memset(sf, 0, NDB_SF_PAGE_SIZE);
20528 
20529  Uint32 ndb_version = NDB_VERSION;
20530  if (ndb_version < NDB_SF_VERSION_5_0_6)
20531  ndb_version = NDB_SF_VERSION_5_0_6;
20532 
20533  memcpy(sf->Magic, NDB_SF_MAGIC, sizeof(sf->Magic));
20534  sf->ByteOrder = 0x12345678;
20535  sf->NdbVersion = ndb_version;
20536  sf->FileSize = xsf->noOfPages * NDB_SF_PAGE_SIZE;
20537  sf->PageNumber = n;
20538  sf->CheckSum = 0;
20539  sf->NoOfTableEntries = NDB_SF_PAGE_ENTRIES;
20540 
20541  computeChecksum(xsf, n);
20542  }
20543 }
20544 
20545 void
20546 Dbdict::resizeSchemaFile(XSchemaFile * xsf, Uint32 noOfPages)
20547 {
20548  ndbrequire(noOfPages <= NDB_SF_MAX_PAGES);
20549  if (xsf->noOfPages < noOfPages) {
20550  jam();
20551  Uint32 firstPage = xsf->noOfPages;
20552  xsf->noOfPages = noOfPages;
20553  initSchemaFile(xsf, 0, firstPage, false);
20554  initSchemaFile(xsf, firstPage, xsf->noOfPages, true);
20555  }
20556  if (xsf->noOfPages > noOfPages) {
20557  jam();
20558  Uint32 tableId = noOfPages * NDB_SF_PAGE_ENTRIES;
20559  while (tableId < xsf->noOfPages * NDB_SF_PAGE_ENTRIES) {
20560  SchemaFile::TableEntry * te = getTableEntry(xsf, tableId);
20561  if (te->m_tableState != SchemaFile::SF_UNUSED)
20562  {
20563  ndbrequire(false);
20564  }
20565  tableId++;
20566  }
20567  xsf->noOfPages = noOfPages;
20568  initSchemaFile(xsf, 0, xsf->noOfPages, false);
20569  }
20570 }
20571 
20572 void
20573 Dbdict::computeChecksum(XSchemaFile * xsf, Uint32 pageNo){
20574  SchemaFile * sf = &xsf->schemaPage[pageNo];
20575  sf->CheckSum = 0;
20576  sf->CheckSum = computeChecksum((Uint32*)sf, NDB_SF_PAGE_SIZE_IN_WORDS);
20577 }
20578 
20579 bool
20580 Dbdict::validateChecksum(const XSchemaFile * xsf){
20581 
20582  for (Uint32 n = 0; n < xsf->noOfPages; n++) {
20583  SchemaFile * sf = &xsf->schemaPage[n];
20584  Uint32 c = computeChecksum((Uint32*)sf, NDB_SF_PAGE_SIZE_IN_WORDS);
20585  if ( c != 0)
20586  return false;
20587  }
20588  return true;
20589 }
20590 
20591 Uint32
20592 Dbdict::computeChecksum(const Uint32 * src, Uint32 len){
20593  Uint32 ret = 0;
20594  for(Uint32 i = 0; i<len; i++)
20595  ret ^= src[i];
20596  return ret;
20597 }
20598 
20600 Dbdict::getTableEntry(Uint32 tableId)
20601 {
20602  return getTableEntry(&c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE], tableId);
20603 }
20604 
20606 Dbdict::getTableEntry(XSchemaFile * xsf, Uint32 tableId)
20607 {
20608  Uint32 n = tableId / NDB_SF_PAGE_ENTRIES;
20609  Uint32 i = tableId % NDB_SF_PAGE_ENTRIES;
20610  ndbrequire(n < xsf->noOfPages);
20611 
20612  SchemaFile * sf = &xsf->schemaPage[n];
20613  return &sf->TableEntries[i];
20614 }
20615 
20616 const SchemaFile::TableEntry *
20617 Dbdict::getTableEntry(const XSchemaFile * xsf, Uint32 tableId)
20618 {
20619  Uint32 n = tableId / NDB_SF_PAGE_ENTRIES;
20620  Uint32 i = tableId % NDB_SF_PAGE_ENTRIES;
20621  ndbrequire(n < xsf->noOfPages);
20622 
20623  SchemaFile * sf = &xsf->schemaPage[n];
20624  return &sf->TableEntries[i];
20625 }
20626 
20627 //******************************************
20628 
20629 // MODULE: CreateFile
20630 
20631 const Dbdict::OpInfo
20632 Dbdict::CreateFileRec::g_opInfo = {
20633  { 'C', 'F', 'l', 0 },
20634  GSN_CREATE_FILE_IMPL_REQ,
20635  CreateFileImplReq::SignalLength,
20636  //
20637  &Dbdict::createFile_seize,
20638  &Dbdict::createFile_release,
20639  //
20640  &Dbdict::createFile_parse,
20641  &Dbdict::createFile_subOps,
20642  &Dbdict::createFile_reply,
20643  //
20644  &Dbdict::createFile_prepare,
20645  &Dbdict::createFile_commit,
20646  &Dbdict::createFile_complete,
20647  //
20648  &Dbdict::createFile_abortParse,
20649  &Dbdict::createFile_abortPrepare
20650 };
20651 
20652 void
20653 Dbdict::execCREATE_FILE_REQ(Signal* signal)
20654 {
20655  jamEntry();
20656  if (!assembleFragments(signal)) {
20657  jam();
20658  return;
20659  }
20660  SectionHandle handle(this, signal);
20661 
20662  const CreateFileReq req_copy =
20663  *(const CreateFileReq*)signal->getDataPtr();
20664  const CreateFileReq* req = &req_copy;
20665 
20666  ErrorInfo error;
20667  do {
20668  SchemaOpPtr op_ptr;
20669  CreateFileRecPtr createFilePtr;
20670  CreateFileImplReq* impl_req;
20671 
20672  startClientReq(op_ptr, createFilePtr, req, impl_req, error);
20673  if (hasError(error)) {
20674  jam();
20675  break;
20676  }
20677 
20678  impl_req->file_id = RNIL;
20679  impl_req->file_version = 0;
20680  impl_req->requestInfo = CreateFileImplReq::Create;
20681  if (req->requestInfo & CreateFileReq::ForceCreateFile)
20682  {
20683  jam();
20684  impl_req->requestInfo = CreateFileImplReq::CreateForce;
20685  }
20686 
20687  handleClientReq(signal, op_ptr, handle);
20688  return;
20689  } while (0);
20690 
20691  releaseSections(handle);
20692 
20693  CreateFileRef* ref = (CreateFileRef*)signal->getDataPtrSend();
20694  ref->senderRef = reference();
20695  ref->transId = req->transId;
20696  ref->senderData = req->senderData;
20697  getError(error, ref);
20698 
20699  sendSignal(req->senderRef, GSN_CREATE_FILE_REF, signal,
20700  CreateFileRef::SignalLength, JBB);
20701 }
20702 
20703 bool
20704 Dbdict::createFile_seize(SchemaOpPtr op_ptr)
20705 {
20706  return seizeOpRec<CreateFileRec>(op_ptr);
20707 }
20708 
20709 void
20710 Dbdict::createFile_release(SchemaOpPtr op_ptr)
20711 {
20712  releaseOpRec<CreateFileRec>(op_ptr);
20713 }
20714 
20715 // CreateFile: PARSE
20716 
20717 void
20718 Dbdict::createFile_parse(Signal* signal, bool master,
20719  SchemaOpPtr op_ptr,
20720  SectionHandle& handle, ErrorInfo& error)
20721 {
20722  jam();
20723 
20724  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
20725  CreateFileRecPtr createFilePtr;
20726  getOpRec(op_ptr, createFilePtr);
20727  CreateFileImplReq* impl_req = &createFilePtr.p->m_request;
20728 
20729  SegmentedSectionPtr objInfoPtr;
20730  {
20731  bool ok = handle.getSection(objInfoPtr, 0);
20732  if (!ok)
20733  {
20734  jam();
20735  setError(error, CreateTableRef::InvalidFormat, __LINE__);
20736  return;
20737  }
20738  }
20739  SimplePropertiesSectionReader it(objInfoPtr, getSectionSegmentPool());
20740 
20741  Ptr<DictObject> obj_ptr; obj_ptr.setNull();
20742  FilePtr filePtr; filePtr.setNull();
20743 
20744  DictFilegroupInfo::File f; f.init();
20746  status = SimpleProperties::unpack(it, &f,
20747  DictFilegroupInfo::FileMapping,
20748  DictFilegroupInfo::FileMappingSize,
20749  true, true);
20750 
20751  if (status != SimpleProperties::Eof)
20752  {
20753  jam();
20754  setError(error, CreateFileRef::InvalidFormat, __LINE__);
20755  return;
20756  }
20757 
20761  if (f.FilegroupId == RNIL && f.FilegroupVersion == RNIL)
20762  {
20763  jam();
20764  Filegroup_hash::Iterator it;
20765  c_filegroup_hash.first(it);
20766  while (!it.isNull())
20767  {
20768  jam();
20769  if ((f.FileType == DictTabInfo::Undofile &&
20770  it.curr.p->m_type == DictTabInfo::LogfileGroup) ||
20771  (f.FileType == DictTabInfo::Datafile &&
20772  it.curr.p->m_type == DictTabInfo::Tablespace))
20773  {
20774  jam();
20775  f.FilegroupId = it.curr.p->key;
20776  f.FilegroupVersion = it.curr.p->m_version;
20777  break;
20778  }
20779  c_filegroup_hash.next(it);
20780  }
20781  }
20782 
20783  // Get Filegroup
20784  FilegroupPtr fg_ptr;
20785  if(!c_filegroup_hash.find(fg_ptr, f.FilegroupId))
20786  {
20787  jam();
20788  setError(error, CreateFileRef::NoSuchFilegroup, __LINE__, f.FileName);
20789  return;
20790  }
20791 
20792  if(fg_ptr.p->m_version != f.FilegroupVersion)
20793  {
20794  jam();
20795  setError(error, CreateFileRef::InvalidFilegroupVersion, __LINE__,
20796  f.FileName);
20797  return;
20798  }
20799 
20800  switch(f.FileType){
20801  case DictTabInfo::Datafile:
20802  {
20803  if(fg_ptr.p->m_type != DictTabInfo::Tablespace)
20804  {
20805  jam();
20806  setError(error, CreateFileRef::InvalidFileType, __LINE__, f.FileName);
20807  return;
20808  }
20809  break;
20810  }
20811  case DictTabInfo::Undofile:
20812  {
20813  if(fg_ptr.p->m_type != DictTabInfo::LogfileGroup)
20814  {
20815  jam();
20816  setError(error, CreateFileRef::InvalidFileType, __LINE__, f.FileName);
20817  return;
20818  }
20819  break;
20820  }
20821  default:
20822  jam();
20823  setError(error, CreateFileRef::InvalidFileType, __LINE__, f.FileName);
20824  return;
20825  }
20826 
20827  Uint32 len = Uint32(strlen(f.FileName) + 1);
20828  Uint32 hash = Rope::hash(f.FileName, len);
20829  if(get_object(f.FileName, len, hash) != 0)
20830  {
20831  jam();
20832  setError(error, CreateFileRef::FilenameAlreadyExists, __LINE__, f.FileName);
20833  return;
20834  }
20835 
20836  {
20837  Uint32 dl;
20838  const ndb_mgm_configuration_iterator * p =
20839  m_ctx.m_config.getOwnConfigIterator();
20840  if(!ndb_mgm_get_int_parameter(p, CFG_DB_DISCLESS, &dl) && dl)
20841  {
20842  jam();
20843  setError(error, CreateFileRef::NotSupportedWhenDiskless, __LINE__,
20844  f.FileName);
20845  return;
20846  }
20847  }
20848 
20849  if (fg_ptr.p->m_type == DictTabInfo::Tablespace &&
20850  f.FileSizeHi == 0 &&
20851  f.FileSizeLo < fg_ptr.p->m_tablespace.m_extent_size)
20852  {
20853  jam();
20854  setError(error, CreateFileRef::FileSizeTooSmall, __LINE__, f.FileName);
20855  return;
20856  }
20857 
20858  if(!c_obj_pool.seize(obj_ptr))
20859  {
20860  jam();
20861  setError(error, CreateTableRef::NoMoreTableRecords, __LINE__, f.FileName);
20862  goto error;
20863  }
20864  new (obj_ptr.p) DictObject;
20865 
20866  if (! c_file_pool.seize(filePtr))
20867  {
20868  jam();
20869  setError(error, CreateFileRef::OutOfFileRecords, __LINE__, f.FileName);
20870  goto error;
20871  }
20872 
20873  new (filePtr.p) File();
20874 
20875  {
20876  Rope name(c_rope_pool, obj_ptr.p->m_name);
20877  if(!name.assign(f.FileName, len, hash))
20878  {
20879  jam();
20880  setError(error, CreateTableRef::OutOfStringBuffer, __LINE__, f.FileName);
20881  goto error;
20882  }
20883  }
20884 
20885  if (master)
20886  {
20887  jam();
20888 
20889  Uint32 objId = getFreeObjId(0);
20890  if (objId == RNIL)
20891  {
20892  jam();
20893  setError(error, CreateFilegroupRef::NoMoreObjectRecords, __LINE__,
20894  f.FileName);
20895  goto error;
20896  }
20897  Uint32 version = getTableEntry(objId)->m_tableVersion;
20898 
20899  impl_req->file_id = objId;
20900  impl_req->file_version = create_obj_inc_schema_version(version);
20901  }
20902  else if (op_ptr.p->m_restart)
20903  {
20904  jam();
20905  impl_req->file_id = c_restartRecord.activeTable;
20906  impl_req->file_version = c_restartRecord.m_entry.m_tableVersion;
20907  switch(op_ptr.p->m_restart){
20908  case 1:
20909  jam();
20910  impl_req->requestInfo = CreateFileImplReq::Open;
20911  break;
20912  case 2:
20913  impl_req->requestInfo = CreateFileImplReq::CreateForce;
20914  break;
20915  }
20916  }
20917 
20921  filePtr.p->key = impl_req->file_id;
20922  filePtr.p->m_file_size = ((Uint64)f.FileSizeHi) << 32 | f.FileSizeLo;
20923  if (fg_ptr.p->m_type == DictTabInfo::Tablespace)
20924  {
20925  // round down to page size and up to extent size - Tsman::open_file
20926  const Uint64 page_size = (Uint64)File_formats::NDB_PAGE_SIZE;
20927  const Uint64 extent_size = (Uint64)fg_ptr.p->m_tablespace.m_extent_size;
20928  ndbrequire(extent_size != 0);
20929  if (filePtr.p->m_file_size % page_size != 0 &&
20930  !ERROR_INSERTED(6030))
20931  {
20932  jam();
20933  filePtr.p->m_file_size /= page_size;
20934  filePtr.p->m_file_size *= page_size;
20935  createFilePtr.p->m_warningFlags |= CreateFileConf::WarnDatafileRoundDown;
20936  }
20937  if (filePtr.p->m_file_size % extent_size != 0 &&
20938  !ERROR_INSERTED(6030))
20939  {
20940  jam();
20941  filePtr.p->m_file_size +=
20942  extent_size - filePtr.p->m_file_size % extent_size;
20943  createFilePtr.p->m_warningFlags |= CreateFileConf::WarnDatafileRoundUp;
20944  }
20945  }
20946  if (fg_ptr.p->m_type == DictTabInfo::LogfileGroup)
20947  {
20948  // round down to page size - Lgman::Undofile::Undofile
20949  const Uint64 page_size = (Uint64)File_formats::NDB_PAGE_SIZE;
20950  if (filePtr.p->m_file_size % page_size != 0 &&
20951  !ERROR_INSERTED(6030))
20952  {
20953  jam();
20954  filePtr.p->m_file_size /= page_size;
20955  filePtr.p->m_file_size *= page_size;
20956  createFilePtr.p->m_warningFlags |= CreateFileConf::WarnUndofileRoundDown;
20957  }
20958  }
20959  filePtr.p->m_path = obj_ptr.p->m_name;
20960  filePtr.p->m_obj_ptr_i = obj_ptr.i;
20961  filePtr.p->m_filegroup_id = f.FilegroupId;
20962  filePtr.p->m_type = f.FileType;
20963  filePtr.p->m_version = impl_req->file_version;
20964 
20965  obj_ptr.p->m_id = impl_req->file_id;
20966  obj_ptr.p->m_type = f.FileType;
20967  obj_ptr.p->m_ref_count = 0;
20968 
20969  {
20970  SchemaFile::TableEntry te; te.init();
20971  te.m_tableState = SchemaFile::SF_CREATE;
20972  te.m_tableVersion = filePtr.p->m_version;
20973  te.m_tableType = filePtr.p->m_type;
20974  te.m_info_words = objInfoPtr.sz;
20975  te.m_gcp = 0;
20976  te.m_transId = trans_ptr.p->m_transId;
20977 
20978  Uint32 err = trans_log_schema_op(op_ptr, impl_req->file_id, &te);
20979  if (err)
20980  {
20981  jam();
20982  setError(error, err, __LINE__);
20983  goto error;
20984  }
20985  }
20986 
20987  c_obj_hash.add(obj_ptr);
20988  c_file_hash.add(filePtr);
20989 
20990  // save sections to DICT memory
20991  saveOpSection(op_ptr, handle, 0);
20992 
20993  switch(fg_ptr.p->m_type){
20995  {
20996  jam();
20997  increase_ref_count(fg_ptr.p->m_obj_ptr_i);
20998  break;
20999  }
21001  {
21002  jam();
21003  Local_file_list list(c_file_pool, fg_ptr.p->m_logfilegroup.m_files);
21004  list.add(filePtr);
21005  break;
21006  }
21007  default:
21008  ndbrequire(false);
21009  }
21010 
21011  createFilePtr.p->m_parsed = true;
21012 
21013 
21014  if (g_trace)
21015  {
21016  g_eventLogger->info("Dbdict: create name=%s,id=%u,obj_ptr_i=%d,"
21017  "type=%s,bytes=%llu,warn=0x%x",
21018  f.FileName,
21019  impl_req->file_id,
21020  filePtr.p->m_obj_ptr_i,
21021  f.FileType == DictTabInfo::Datafile ? "datafile" :
21022  f.FileType == DictTabInfo::Undofile ? "undofile" :
21023  "<unknown>",
21024  filePtr.p->m_file_size,
21025  createFilePtr.p->m_warningFlags);
21026  }
21027 
21028  send_event(signal, trans_ptr,
21029  NDB_LE_CreateSchemaObject,
21030  impl_req->file_id,
21031  impl_req->file_version,
21032  f.FileType);
21033 
21034  return;
21035 error:
21036  if (!filePtr.isNull())
21037  {
21038  jam();
21039  c_file_pool.release(filePtr);
21040  }
21041 
21042  if (!obj_ptr.isNull())
21043  {
21044  jam();
21045  release_object(obj_ptr.i, obj_ptr.p);
21046  }
21047 }
21048 
21049 void
21050 Dbdict::createFile_abortParse(Signal* signal, SchemaOpPtr op_ptr)
21051 {
21052  CreateFileRecPtr createFilePtr;
21053  getOpRec(op_ptr, createFilePtr);
21054  CreateFileImplReq* impl_req = &createFilePtr.p->m_request;
21055 
21056  if (createFilePtr.p->m_parsed)
21057  {
21058  FilePtr f_ptr;
21059  FilegroupPtr fg_ptr;
21060  ndbrequire(c_file_hash.find(f_ptr, impl_req->file_id));
21061  ndbrequire(c_filegroup_hash.find(fg_ptr, f_ptr.p->m_filegroup_id));
21062  if (f_ptr.p->m_type == DictTabInfo::Datafile)
21063  {
21064  jam();
21065  decrease_ref_count(fg_ptr.p->m_obj_ptr_i);
21066  }
21067  else if (f_ptr.p->m_type == DictTabInfo::Undofile)
21068  {
21069  jam();
21070  Local_file_list list(c_file_pool, fg_ptr.p->m_logfilegroup.m_files);
21071  list.remove(f_ptr);
21072  }
21073 
21074  release_object(f_ptr.p->m_obj_ptr_i);
21075  c_file_hash.release(f_ptr);
21076  }
21077 
21078  sendTransConf(signal, op_ptr);
21079 }
21080 
21081 bool
21082 Dbdict::createFile_subOps(Signal* signal, SchemaOpPtr op_ptr)
21083 {
21084  return false;
21085 }
21086 
21087 void
21088 Dbdict::createFile_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
21089 {
21090  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
21091  CreateFileRecPtr createFileRecPtr;
21092  getOpRec(op_ptr, createFileRecPtr);
21093  CreateFileImplReq* impl_req = &createFileRecPtr.p->m_request;
21094 
21095  if (!hasError(error))
21096  {
21097  jam();
21098  CreateFileConf* conf = (CreateFileConf*)signal->getDataPtrSend();
21099  conf->senderRef = reference();
21100  conf->senderData = op_ptr.p->m_clientData;
21101  conf->transId = trans_ptr.p->m_transId;
21102  conf->fileId = impl_req->file_id;
21103  conf->fileVersion = impl_req->file_version;
21104  conf->warningFlags = createFileRecPtr.p->m_warningFlags;
21105  Uint32 clientRef = op_ptr.p->m_clientRef;
21106  sendSignal(clientRef, GSN_CREATE_FILE_CONF, signal,
21107  CreateFileConf::SignalLength, JBB);
21108  }
21109  else
21110  {
21111  jam();
21112  CreateFileRef* ref = (CreateFileRef*)signal->getDataPtrSend();
21113  ref->senderRef = reference();
21114  ref->senderData = op_ptr.p->m_clientData;
21115  ref->transId = trans_ptr.p->m_transId;
21116  getError(error, ref);
21117 
21118  Uint32 clientRef = op_ptr.p->m_clientRef;
21119  sendSignal(clientRef, GSN_CREATE_FILE_REF, signal,
21120  CreateFileRef::SignalLength, JBB);
21121  }
21122 }
21123 
21124 // CreateFile: PREPARE
21125 
21126 void
21127 Dbdict::createFile_prepare(Signal* signal, SchemaOpPtr op_ptr)
21128 {
21129  jam();
21130 
21131  CreateFileRecPtr createFileRecPtr;
21132  getOpRec(op_ptr, createFileRecPtr);
21133  CreateFileImplReq* impl_req = &createFileRecPtr.p->m_request;
21134 
21135  Callback cb = {
21136  safe_cast(&Dbdict::createFile_fromWriteObjInfo), op_ptr.p->op_key
21137  };
21138 
21139  if (ZRESTART_NO_WRITE_AFTER_READ && op_ptr.p->m_restart == 1)
21140  {
21141  jam();
21145  execute(signal, cb, 0);
21146  return;
21147  }
21148 
21149  const OpSection& objInfoSec = getOpSection(op_ptr, 0);
21150  writeTableFile(signal, impl_req->file_id, objInfoSec, &cb);
21151 }
21152 
21153 void
21154 Dbdict::createFile_fromWriteObjInfo(Signal* signal,
21155  Uint32 op_key,
21156  Uint32 ret)
21157 {
21158  SchemaOpPtr op_ptr;
21159  CreateFileRecPtr createFileRecPtr;
21160  ndbrequire(findSchemaOp(op_ptr, createFileRecPtr, op_key));
21161  CreateFileImplReq* impl_req = &createFileRecPtr.p->m_request;
21162 
21163  if (ret)
21164  {
21165  jam();
21166  setError(op_ptr, ret, __LINE__);
21167  sendTransRef(signal, op_ptr);
21168  return;
21169  }
21170 
21174  CreateFileImplReq* req = (CreateFileImplReq*)signal->getDataPtrSend();
21175  FilePtr f_ptr;
21176  FilegroupPtr fg_ptr;
21177 
21178  ndbrequire(c_file_hash.find(f_ptr, impl_req->file_id));
21179  ndbrequire(c_filegroup_hash.find(fg_ptr, f_ptr.p->m_filegroup_id));
21180 
21181  req->senderData = op_ptr.p->op_key;
21182  req->senderRef = reference();
21183 
21184  req->file_id = f_ptr.p->key;
21185  req->filegroup_id = f_ptr.p->m_filegroup_id;
21186  req->filegroup_version = fg_ptr.p->m_version;
21187  req->file_size_hi = (Uint32)(f_ptr.p->m_file_size >> 32);
21188  req->file_size_lo = (Uint32)(f_ptr.p->m_file_size & 0xFFFFFFFF);
21189  req->requestInfo = impl_req->requestInfo;
21190 
21191  Uint32 ref= 0;
21192  Uint32 len= 0;
21193  switch(f_ptr.p->m_type){
21194  case DictTabInfo::Datafile:
21195  {
21196  jam();
21197  ref = TSMAN_REF;
21198  len = CreateFileImplReq::DatafileLength;
21199  req->tablespace.extent_size = fg_ptr.p->m_tablespace.m_extent_size;
21200  break;
21201  }
21202  case DictTabInfo::Undofile:
21203  {
21204  jam();
21205  ref = LGMAN_REF;
21206  len = CreateFileImplReq::UndofileLength;
21207  break;
21208  }
21209  default:
21210  ndbrequire(false);
21211  }
21212 
21213  char name[PATH_MAX];
21214  ConstRope tmp(c_rope_pool, f_ptr.p->m_path);
21215  tmp.copy(name);
21216  LinearSectionPtr ptr[3];
21217  ptr[0].p = (Uint32*)&name[0];
21218  ptr[0].sz = Uint32(strlen(name)+1+3)/4;
21219  sendSignal(ref, GSN_CREATE_FILE_IMPL_REQ, signal, len, JBB, ptr, 1);
21220 
21221  Callback c = {
21222  safe_cast(&Dbdict::createFile_fromLocal), op_ptr.p->op_key
21223  };
21224  op_ptr.p->m_callback = c;
21225 }
21226 
21227 void
21228 Dbdict::createFile_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
21229 {
21230  CreateFileImplReq* req = (CreateFileImplReq*)signal->getDataPtrSend();
21231  FilePtr f_ptr;
21232  FilegroupPtr fg_ptr;
21233 
21234  CreateFileRecPtr createFileRecPtr;
21235  getOpRec(op_ptr, createFileRecPtr);
21236  CreateFileImplReq* impl_req = &createFileRecPtr.p->m_request;
21237 
21238  ndbrequire(c_file_hash.find(f_ptr, impl_req->file_id));
21239  ndbrequire(c_filegroup_hash.find(fg_ptr, f_ptr.p->m_filegroup_id));
21240 
21241  req->senderData = op_ptr.p->op_key;
21242  req->senderRef = reference();
21243  req->requestInfo = CreateFileImplReq::Abort;
21244  req->file_id = f_ptr.p->key;
21245  req->filegroup_id = f_ptr.p->m_filegroup_id;
21246  req->filegroup_version = fg_ptr.p->m_version;
21247 
21248  Uint32 ref= 0;
21249  switch(f_ptr.p->m_type){
21250  case DictTabInfo::Datafile:
21251  {
21252  jam();
21253  ref = TSMAN_REF;
21254  break;
21255  }
21256  case DictTabInfo::Undofile:
21257  {
21258  jam();
21259  ref = LGMAN_REF;
21260  break;
21261  }
21262  default:
21263  ndbrequire(false);
21264  }
21265 
21266  sendSignal(ref, GSN_CREATE_FILE_IMPL_REQ, signal,
21267  CreateFileImplReq::AbortLength, JBB);
21268 
21269  Callback c = {
21270  safe_cast(&Dbdict::createFile_fromLocal), op_ptr.p->op_key
21271  };
21272  op_ptr.p->m_callback = c;
21273 }
21274 
21275 // CreateFile: COMMIT
21276 
21277 void
21278 Dbdict::createFile_commit(Signal* signal, SchemaOpPtr op_ptr)
21279 {
21280  jam();
21281 
21282  CreateFileRecPtr createFileRecPtr;
21283  getOpRec(op_ptr, createFileRecPtr);
21284  CreateFileImplReq* impl_req = &createFileRecPtr.p->m_request;
21285 
21289  CreateFileImplReq* req = (CreateFileImplReq*)signal->getDataPtrSend();
21290  FilePtr f_ptr;
21291  FilegroupPtr fg_ptr;
21292 
21293  jam();
21294  ndbrequire(c_file_hash.find(f_ptr, impl_req->file_id));
21295  ndbrequire(c_filegroup_hash.find(fg_ptr, f_ptr.p->m_filegroup_id));
21296 
21297  req->senderData = op_ptr.p->op_key;
21298  req->senderRef = reference();
21299  req->requestInfo = CreateFileImplReq::Commit;
21300 
21301  req->file_id = f_ptr.p->key;
21302  req->filegroup_id = f_ptr.p->m_filegroup_id;
21303  req->filegroup_version = fg_ptr.p->m_version;
21304 
21305  Uint32 ref= 0;
21306  switch(f_ptr.p->m_type){
21307  case DictTabInfo::Datafile:
21308  {
21309  jam();
21310  ref = TSMAN_REF;
21311  break;
21312  }
21313  case DictTabInfo::Undofile:
21314  {
21315  jam();
21316  ref = LGMAN_REF;
21317  break;
21318  }
21319  default:
21320  ndbrequire(false);
21321  }
21322  sendSignal(ref, GSN_CREATE_FILE_IMPL_REQ, signal,
21323  CreateFileImplReq::CommitLength, JBB);
21324 
21325  Callback c = {
21326  safe_cast(&Dbdict::createFile_fromLocal), op_ptr.p->op_key
21327  };
21328  op_ptr.p->m_callback = c;
21329 }
21330 
21331 // CreateFile: COMPLETE
21332 
21333 void
21334 Dbdict::createFile_complete(Signal* signal, SchemaOpPtr op_ptr)
21335 {
21336  jam();
21337  sendTransConf(signal, op_ptr);
21338 }
21339 
21340 void
21341 Dbdict::createFile_fromLocal(Signal* signal, Uint32 op_key, Uint32 ret)
21342 {
21343  jam();
21344  SchemaOpPtr op_ptr;
21345  CreateFileRecPtr createFilePtr;
21346  ndbrequire(findSchemaOp(op_ptr, createFilePtr, op_key));
21347 
21348  if (ret == 0)
21349  {
21350  jam();
21351  sendTransConf(signal, op_ptr);
21352  }
21353  else
21354  {
21355  jam();
21356  setError(op_ptr, ret, __LINE__);
21357  sendTransRef(signal, op_ptr);
21358  }
21359 }
21360 
21361 void
21362 Dbdict::execCREATE_FILE_IMPL_REF(Signal* signal)
21363 {
21364  jamEntry();
21365  CreateFileImplRef * ref = (CreateFileImplRef*)signal->getDataPtr();
21366  handleDictRef(signal, ref);
21367 }
21368 
21369 void
21370 Dbdict::execCREATE_FILE_IMPL_CONF(Signal* signal)
21371 {
21372  jamEntry();
21373  CreateFileImplConf * conf = (CreateFileImplConf*)signal->getDataPtr();
21374  handleDictConf(signal, conf);
21375 }
21376 
21377 // CreateFile: END
21378 
21379 // MODULE: CreateFilegroup
21380 
21381 const Dbdict::OpInfo
21382 Dbdict::CreateFilegroupRec::g_opInfo = {
21383  { 'C', 'F', 'G', 0 },
21384  GSN_CREATE_FILEGROUP_IMPL_REQ,
21385  CreateFilegroupImplReq::SignalLength,
21386  //
21387  &Dbdict::createFilegroup_seize,
21388  &Dbdict::createFilegroup_release,
21389  //
21390  &Dbdict::createFilegroup_parse,
21391  &Dbdict::createFilegroup_subOps,
21392  &Dbdict::createFilegroup_reply,
21393  //
21394  &Dbdict::createFilegroup_prepare,
21395  &Dbdict::createFilegroup_commit,
21396  &Dbdict::createFilegroup_complete,
21397  //
21398  &Dbdict::createFilegroup_abortParse,
21399  &Dbdict::createFilegroup_abortPrepare
21400 };
21401 
21402 void
21403 Dbdict::execCREATE_FILEGROUP_REQ(Signal* signal)
21404 {
21405  jamEntry();
21406  if (!assembleFragments(signal)) {
21407  jam();
21408  return;
21409  }
21410  SectionHandle handle(this, signal);
21411 
21412  const CreateFilegroupReq req_copy =
21413  *(const CreateFilegroupReq*)signal->getDataPtr();
21414  const CreateFilegroupReq* req = &req_copy;
21415 
21416  ErrorInfo error;
21417  do {
21418  SchemaOpPtr op_ptr;
21419  CreateFilegroupRecPtr createFilegroupPtr;
21420  CreateFilegroupImplReq* impl_req;
21421 
21422  startClientReq(op_ptr, createFilegroupPtr, req, impl_req, error);
21423  if (hasError(error)) {
21424  jam();
21425  break;
21426  }
21427 
21428  impl_req->filegroup_id = RNIL;
21429  impl_req->filegroup_version = 0;
21430 
21431  handleClientReq(signal, op_ptr, handle);
21432  return;
21433  } while (0);
21434 
21435  releaseSections(handle);
21436 
21437  CreateFilegroupRef* ref = (CreateFilegroupRef*)signal->getDataPtrSend();
21438  ref->senderRef = reference();
21439  ref->transId = req->transId;
21440  ref->senderData = req->senderData;
21441  getError(error, ref);
21442 
21443  sendSignal(req->senderRef, GSN_CREATE_FILEGROUP_REF, signal,
21444  CreateFilegroupRef::SignalLength, JBB);
21445 }
21446 
21447 bool
21448 Dbdict::createFilegroup_seize(SchemaOpPtr op_ptr)
21449 {
21450  return seizeOpRec<CreateFilegroupRec>(op_ptr);
21451 }
21452 
21453 void
21454 Dbdict::createFilegroup_release(SchemaOpPtr op_ptr)
21455 {
21456  releaseOpRec<CreateFilegroupRec>(op_ptr);
21457 }
21458 
21459 // CreateFilegroup: PARSE
21460 
21461 void
21462 Dbdict::createFilegroup_parse(Signal* signal, bool master,
21463  SchemaOpPtr op_ptr,
21464  SectionHandle& handle, ErrorInfo& error)
21465 {
21466  jam();
21467 
21468  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
21469  CreateFilegroupRecPtr createFilegroupPtr;
21470  getOpRec(op_ptr, createFilegroupPtr);
21471  CreateFilegroupImplReq* impl_req = &createFilegroupPtr.p->m_request;
21472 
21473  SegmentedSectionPtr objInfoPtr;
21474  {
21475  bool ok = handle.getSection(objInfoPtr, 0);
21476  if (!ok)
21477  {
21478  jam();
21479  setError(error, CreateTableRef::InvalidFormat, __LINE__);
21480  return;
21481  }
21482  }
21483  SimplePropertiesSectionReader it(objInfoPtr, getSectionSegmentPool());
21484 
21485  Ptr<DictObject> obj_ptr; obj_ptr.setNull();
21486  FilegroupPtr fg_ptr; fg_ptr.setNull();
21487 
21488  DictFilegroupInfo::Filegroup fg; fg.init();
21490  SimpleProperties::unpack(it, &fg,
21491  DictFilegroupInfo::Mapping,
21492  DictFilegroupInfo::MappingSize,
21493  true, true);
21494 
21495  if(status != SimpleProperties::Eof)
21496  {
21497  jam();
21498  setError(error, CreateTableRef::InvalidFormat, __LINE__);
21499  return;
21500  }
21501 
21502  if(fg.FilegroupType == DictTabInfo::Tablespace)
21503  {
21504  if(!fg.TS_ExtentSize)
21505  {
21506  jam();
21507  setError(error, CreateFilegroupRef::InvalidExtentSize, __LINE__);
21508  return;
21509  }
21510 
21514  if (fg.TS_LogfileGroupId == RNIL && fg.TS_LogfileGroupVersion == RNIL)
21515  {
21516  jam();
21517  Filegroup_hash::Iterator it;
21518  if (c_filegroup_hash.first(it))
21519  {
21520  jam();
21521  fg.TS_LogfileGroupId = it.curr.p->key;
21522  fg.TS_LogfileGroupVersion = it.curr.p->m_version;
21523  }
21524  }
21525  }
21526  else if(fg.FilegroupType == DictTabInfo::LogfileGroup)
21527  {
21531  if(fg.LF_UndoBufferSize < 3 * File_formats::NDB_PAGE_SIZE)
21532  {
21533  jam();
21534  setError(error, CreateFilegroupRef::InvalidUndoBufferSize, __LINE__);
21535  return;
21536  }
21537  }
21538 
21539  Uint32 len = Uint32(strlen(fg.FilegroupName) + 1);
21540  Uint32 hash = Rope::hash(fg.FilegroupName, len);
21541  if(get_object(fg.FilegroupName, len, hash) != 0)
21542  {
21543  jam();
21544  setError(error, CreateTableRef::TableAlreadyExist, __LINE__);
21545  return;
21546  }
21547 
21548  if(!c_obj_pool.seize(obj_ptr))
21549  {
21550  jam();
21551  setError(error, CreateTableRef::NoMoreTableRecords, __LINE__);
21552  return;
21553  }
21554  new (obj_ptr.p) DictObject;
21555 
21556  Uint32 inc_obj_ptr_i = RNIL;
21557  if(!c_filegroup_pool.seize(fg_ptr))
21558  {
21559  jam();
21560  setError(error, CreateTableRef::NoMoreTableRecords, __LINE__);
21561  goto error;
21562  }
21563 
21564  new (fg_ptr.p) Filegroup();
21565 
21566  {
21567  Rope name(c_rope_pool, obj_ptr.p->m_name);
21568  if(!name.assign(fg.FilegroupName, len, hash))
21569  {
21570  jam();
21571  setError(error, CreateTableRef::OutOfStringBuffer, __LINE__);
21572  goto error;
21573  }
21574  }
21575 
21576  switch(fg.FilegroupType){
21578  {
21579  //fg.TS_DataGrow = group.m_grow_spec;
21580  fg_ptr.p->m_tablespace.m_extent_size = fg.TS_ExtentSize;
21581  // round up to page size - Tsman::Tablespace::Tablespace
21582  const Uint32 page_size = (Uint32)File_formats::NDB_PAGE_SIZE;
21583  if (fg_ptr.p->m_tablespace.m_extent_size % page_size != 0 &&
21584  !ERROR_INSERTED(6030))
21585  {
21586  jam();
21587  fg_ptr.p->m_tablespace.m_extent_size +=
21588  page_size - fg_ptr.p->m_tablespace.m_extent_size % page_size;
21589  createFilegroupPtr.p->m_warningFlags |= CreateFilegroupConf::WarnExtentRoundUp;
21590  }
21591 #if defined VM_TRACE || defined ERROR_INSERT
21592  ndbout << "DD dict: ts id:" << "?" << " extent bytes:" << fg_ptr.p->m_tablespace.m_extent_size << " warn:" << hex << createFilegroupPtr.p->m_warningFlags << endl;
21593 #endif
21594  fg_ptr.p->m_tablespace.m_default_logfile_group_id = fg.TS_LogfileGroupId;
21595 
21596  Ptr<Filegroup> lg_ptr;
21597  if (!c_filegroup_hash.find(lg_ptr, fg.TS_LogfileGroupId))
21598  {
21599  jam();
21600  setError(error, CreateFilegroupRef::NoSuchLogfileGroup, __LINE__);
21601  goto error;
21602  }
21603 
21604  if (lg_ptr.p->m_version != fg.TS_LogfileGroupVersion)
21605  {
21606  jam();
21607  setError(error, CreateFilegroupRef::InvalidFilegroupVersion, __LINE__);
21608  goto error;
21609  }
21610  inc_obj_ptr_i = lg_ptr.p->m_obj_ptr_i;
21611  break;
21612  }
21614  {
21615  jam();
21616  fg_ptr.p->m_logfilegroup.m_undo_buffer_size = fg.LF_UndoBufferSize;
21617  // round up to page size - Lgman::alloc_logbuffer_memory
21618  const Uint32 page_size = (Uint32)File_formats::NDB_PAGE_SIZE;
21619  if (fg_ptr.p->m_logfilegroup.m_undo_buffer_size % page_size != 0 &&
21620  !ERROR_INSERTED(6030))
21621  {
21622  jam();
21623  fg_ptr.p->m_logfilegroup.m_undo_buffer_size +=
21624  page_size - fg_ptr.p->m_logfilegroup.m_undo_buffer_size % page_size;
21625  createFilegroupPtr.p->m_warningFlags |= CreateFilegroupConf::WarnUndobufferRoundUp;
21626  }
21627 #if defined VM_TRACE || defined ERROR_INSERT
21628  ndbout << "DD dict: fg id:" << "?" << " undo buffer bytes:" << fg_ptr.p->m_logfilegroup.m_undo_buffer_size << " warn:" << hex << createFilegroupPtr.p->m_warningFlags << endl;
21629 #endif
21630  fg_ptr.p->m_logfilegroup.m_files.init();
21631  //fg.LF_UndoGrow = ;
21632  break;
21633  }
21634  default:
21635  ndbrequire(false);
21636  }
21637 
21638  if (master)
21639  {
21640  jam();
21641 
21642  Uint32 objId = getFreeObjId(0);
21643  if (objId == RNIL)
21644  {
21645  jam();
21646  setError(error, CreateFilegroupRef::NoMoreObjectRecords, __LINE__);
21647  goto error;
21648  }
21649  Uint32 version = getTableEntry(objId)->m_tableVersion;
21650 
21651  impl_req->filegroup_id = objId;
21652  impl_req->filegroup_version = create_obj_inc_schema_version(version);
21653  }
21654  else if (op_ptr.p->m_restart)
21655  {
21656  jam();
21657  impl_req->filegroup_id = c_restartRecord.activeTable;
21658  impl_req->filegroup_version = c_restartRecord.m_entry.m_tableVersion;
21659  }
21660 
21661  fg_ptr.p->key = impl_req->filegroup_id;
21662  fg_ptr.p->m_obj_ptr_i = obj_ptr.i;
21663  fg_ptr.p->m_type = fg.FilegroupType;
21664  fg_ptr.p->m_version = impl_req->filegroup_version;
21665  fg_ptr.p->m_name = obj_ptr.p->m_name;
21666 
21667  obj_ptr.p->m_id = impl_req->filegroup_id;
21668  obj_ptr.p->m_type = fg.FilegroupType;
21669  obj_ptr.p->m_ref_count = 0;
21670 
21671  if (master)
21672  {
21673  jam();
21674  releaseSections(handle);
21676  packFilegroupIntoPages(w, fg_ptr, 0, 0);
21677  w.getPtr(objInfoPtr);
21678  handle.m_ptr[0] = objInfoPtr;
21679  handle.m_cnt = 1;
21680  }
21681 
21682  {
21683  SchemaFile::TableEntry te; te.init();
21684  te.m_tableState = SchemaFile::SF_CREATE;
21685  te.m_tableVersion = fg_ptr.p->m_version;
21686  te.m_tableType = fg_ptr.p->m_type;
21687  te.m_info_words = objInfoPtr.sz;
21688  te.m_gcp = 0;
21689  te.m_transId = trans_ptr.p->m_transId;
21690 
21691  Uint32 err = trans_log_schema_op(op_ptr, impl_req->filegroup_id, &te);
21692  if (err)
21693  {
21694  jam();
21695  setError(error, err, __LINE__);
21696  goto error;
21697  }
21698  }
21699 
21700  c_obj_hash.add(obj_ptr);
21701  c_filegroup_hash.add(fg_ptr);
21702 
21703  // save sections to DICT memory
21704  saveOpSection(op_ptr, handle, 0);
21705 
21706  if (inc_obj_ptr_i != RNIL)
21707  {
21708  jam();
21709  increase_ref_count(inc_obj_ptr_i);
21710  }
21711  createFilegroupPtr.p->m_parsed = true;
21712 
21713 #if defined VM_TRACE || defined ERROR_INSERT
21714  ndbout_c("Dbdict: create name=%s,id=%u,obj_ptr_i=%d",
21715  fg.FilegroupName, impl_req->filegroup_id, fg_ptr.p->m_obj_ptr_i);
21716 #endif
21717 
21718  return;
21719 
21720 error:
21721  jam();
21722  if (!fg_ptr.isNull())
21723  {
21724  jam();
21725  c_filegroup_pool.release(fg_ptr);
21726  }
21727 
21728  if (!obj_ptr.isNull())
21729  {
21730  jam();
21731  release_object(obj_ptr.i, obj_ptr.p);
21732  }
21733 }
21734 
21735 void
21736 Dbdict::createFilegroup_abortParse(Signal* signal, SchemaOpPtr op_ptr)
21737 {
21738  CreateFilegroupRecPtr createFilegroupPtr;
21739  getOpRec(op_ptr, createFilegroupPtr);
21740 
21741  if (createFilegroupPtr.p->m_parsed)
21742  {
21743  jam();
21744  CreateFilegroupImplReq* impl_req = &createFilegroupPtr.p->m_request;
21745 
21746  FilegroupPtr fg_ptr;
21747  ndbrequire(c_filegroup_hash.find(fg_ptr, impl_req->filegroup_id));
21748 
21749  if (fg_ptr.p->m_type == DictTabInfo::Tablespace)
21750  {
21751  jam();
21752  FilegroupPtr lg_ptr;
21753  ndbrequire(c_filegroup_hash.find
21754  (lg_ptr, fg_ptr.p->m_tablespace.m_default_logfile_group_id));
21755  decrease_ref_count(lg_ptr.p->m_obj_ptr_i);
21756  }
21757 
21758  release_object(fg_ptr.p->m_obj_ptr_i);
21759  c_filegroup_hash.release(fg_ptr);
21760  }
21761 
21762  sendTransConf(signal, op_ptr);
21763 }
21764 
21765 
21766 bool
21767 Dbdict::createFilegroup_subOps(Signal* signal, SchemaOpPtr op_ptr)
21768 {
21769  return false;
21770 }
21771 
21772 void
21773 Dbdict::createFilegroup_reply(Signal* signal,
21774  SchemaOpPtr op_ptr,
21775  ErrorInfo error)
21776 {
21777  jam();
21778 
21779  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
21780  CreateFilegroupRecPtr createFilegroupRecPtr;
21781  getOpRec(op_ptr, createFilegroupRecPtr);
21782  CreateFilegroupImplReq* impl_req = &createFilegroupRecPtr.p->m_request;
21783 
21784  if (!hasError(error))
21785  {
21786  jam();
21787  CreateFilegroupConf* conf = (CreateFilegroupConf*)signal->getDataPtrSend();
21788  conf->senderRef = reference();
21789  conf->senderData = op_ptr.p->m_clientData;
21790  conf->transId = trans_ptr.p->m_transId;
21791  conf->filegroupId = impl_req->filegroup_id;
21792  conf->filegroupVersion = impl_req->filegroup_version;
21793  conf->warningFlags = createFilegroupRecPtr.p->m_warningFlags;
21794  Uint32 clientRef = op_ptr.p->m_clientRef;
21795  sendSignal(clientRef, GSN_CREATE_FILEGROUP_CONF, signal,
21796  CreateFilegroupConf::SignalLength, JBB);
21797  } else {
21798  jam();
21799  CreateFilegroupRef* ref = (CreateFilegroupRef*)signal->getDataPtrSend();
21800  ref->senderRef = reference();
21801  ref->senderData = op_ptr.p->m_clientData;
21802  ref->transId = trans_ptr.p->m_transId;
21803  getError(error, ref);
21804 
21805  Uint32 clientRef = op_ptr.p->m_clientRef;
21806  sendSignal(clientRef, GSN_CREATE_FILEGROUP_REF, signal,
21807  CreateFilegroupRef::SignalLength, JBB);
21808  }
21809 }
21810 
21811 // CreateFilegroup: PREPARE
21812 
21813 void
21814 Dbdict::createFilegroup_prepare(Signal* signal, SchemaOpPtr op_ptr)
21815 {
21816  jam();
21817 
21818  CreateFilegroupRecPtr createFilegroupRecPtr;
21819  getOpRec(op_ptr, createFilegroupRecPtr);
21820  CreateFilegroupImplReq* impl_req = &createFilegroupRecPtr.p->m_request;
21821 
21822  Callback cb = {
21823  safe_cast(&Dbdict::createFilegroup_fromWriteObjInfo), op_ptr.p->op_key
21824  };
21825 
21826  if (ZRESTART_NO_WRITE_AFTER_READ && op_ptr.p->m_restart == 1)
21827  {
21828  jam();
21832  execute(signal, cb, 0);
21833  return;
21834  }
21835 
21836  const OpSection& objInfoSec = getOpSection(op_ptr, 0);
21837  writeTableFile(signal, impl_req->filegroup_id, objInfoSec, &cb);
21838 }
21839 
21840 void
21841 Dbdict::createFilegroup_fromWriteObjInfo(Signal* signal,
21842  Uint32 op_key,
21843  Uint32 ret)
21844 {
21845  SchemaOpPtr op_ptr;
21846  CreateFilegroupRecPtr createFilegroupRecPtr;
21847  ndbrequire(findSchemaOp(op_ptr, createFilegroupRecPtr, op_key));
21848 
21849  if (ret)
21850  {
21851  setError(op_ptr, ret, __LINE__);
21852  sendTransRef(signal, op_ptr);
21853  return;
21854  }
21855 
21859  CreateFilegroupImplReq* impl_req = &createFilegroupRecPtr.p->m_request;
21860 
21861  CreateFilegroupImplReq* req =
21862  (CreateFilegroupImplReq*)signal->getDataPtrSend();
21863  jam();
21864  req->senderData = op_ptr.p->op_key;
21865  req->senderRef = reference();
21866  req->filegroup_id = impl_req->filegroup_id;
21867  req->filegroup_version = impl_req->filegroup_version;
21868 
21869  FilegroupPtr fg_ptr;
21870  ndbrequire(c_filegroup_hash.find(fg_ptr, impl_req->filegroup_id));
21871 
21872  Uint32 ref= 0;
21873  Uint32 len= 0;
21874  switch(fg_ptr.p->m_type){
21876  {
21877  jam();
21878  ref = TSMAN_REF;
21879  len = CreateFilegroupImplReq::TablespaceLength;
21880  req->tablespace.extent_size = fg_ptr.p->m_tablespace.m_extent_size;
21881  req->tablespace.logfile_group_id =
21882  fg_ptr.p->m_tablespace.m_default_logfile_group_id;
21883  break;
21884  }
21886  {
21887  jam();
21888  ref = LGMAN_REF;
21889  len = CreateFilegroupImplReq::LogfileGroupLength;
21890  req->logfile_group.buffer_size =
21891  fg_ptr.p->m_logfilegroup.m_undo_buffer_size;
21892  break;
21893  }
21894  default:
21895  ndbrequire(false);
21896  }
21897 
21898  sendSignal(ref, GSN_CREATE_FILEGROUP_IMPL_REQ, signal, len, JBB);
21899 
21900  Callback c = {
21901  safe_cast(&Dbdict::createFilegroup_fromLocal), op_ptr.p->op_key
21902  };
21903  op_ptr.p->m_callback = c;
21904 }
21905 
21906 // CreateFilegroup: COMMIT
21907 
21908 void
21909 Dbdict::createFilegroup_commit(Signal* signal, SchemaOpPtr op_ptr)
21910 {
21911  jam();
21912 
21916  sendTransConf(signal, op_ptr);
21917 }
21918 
21919 // CreateFilegroup: COMPLETE
21920 
21921 void
21922 Dbdict::createFilegroup_complete(Signal* signal, SchemaOpPtr op_ptr)
21923 {
21924  jam();
21925  sendTransConf(signal, op_ptr);
21926 }
21927 
21928 void
21929 Dbdict::createFilegroup_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
21930 {
21931  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
21932  CreateFilegroupRecPtr createFilegroupRecPtr;
21933  getOpRec(op_ptr, createFilegroupRecPtr);
21934  CreateFilegroupImplReq* impl_req = &createFilegroupRecPtr.p->m_request;
21935 
21936  if (createFilegroupRecPtr.p->m_prepared)
21937  {
21938  Callback c = {
21939  safe_cast(&Dbdict::createFilegroup_fromLocal), op_ptr.p->op_key
21940  };
21941  op_ptr.p->m_callback = c;
21942 
21943  send_drop_fg(signal, op_ptr.p->op_key, impl_req->filegroup_id,
21944  DropFilegroupImplReq::Prepare);
21945  }
21946 
21947  sendTransConf(signal, op_ptr);
21948 }
21949 
21950 void
21951 Dbdict::createFilegroup_fromLocal(Signal* signal, Uint32 op_key, Uint32 ret)
21952 {
21953  jam();
21954  SchemaOpPtr op_ptr;
21955  CreateFilegroupRecPtr createFilegroupPtr;
21956  ndbrequire(findSchemaOp(op_ptr, createFilegroupPtr, op_key));
21957  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
21958 
21959  if (ret == 0)
21960  {
21961  jam();
21962  createFilegroupPtr.p->m_prepared = true;
21963  sendTransConf(signal, op_ptr);
21964  }
21965  else
21966  {
21967  jam();
21968  setError(op_ptr, ret, __LINE__);
21969  sendTransRef(signal, op_ptr);
21970  }
21971 }
21972 
21973 void
21974 Dbdict::execCREATE_FILEGROUP_IMPL_REF(Signal* signal)
21975 {
21976  jamEntry();
21977  CreateFilegroupImplRef * ref = (CreateFilegroupImplRef*)signal->getDataPtr();
21978  handleDictRef(signal, ref);
21979 }
21980 
21981 void
21982 Dbdict::execCREATE_FILEGROUP_IMPL_CONF(Signal* signal)
21983 {
21984  jamEntry();
21985  CreateFilegroupImplConf * conf =
21986  (CreateFilegroupImplConf*)signal->getDataPtr();
21987  handleDictConf(signal, conf);
21988 }
21989 
21990 // CreateFilegroup: END
21991 
21992 // MODULE: DropFile
21993 
21994 const Dbdict::OpInfo
21995 Dbdict::DropFileRec::g_opInfo = {
21996  { 'D', 'F', 'l', 0 },
21997  GSN_DROP_FILE_IMPL_REQ,
21998  DropFileImplReq::SignalLength,
21999  //
22000  &Dbdict::dropFile_seize,
22001  &Dbdict::dropFile_release,
22002  //
22003  &Dbdict::dropFile_parse,
22004  &Dbdict::dropFile_subOps,
22005  &Dbdict::dropFile_reply,
22006  //
22007  &Dbdict::dropFile_prepare,
22008  &Dbdict::dropFile_commit,
22009  &Dbdict::dropFile_complete,
22010  //
22011  &Dbdict::dropFile_abortParse,
22012  &Dbdict::dropFile_abortPrepare
22013 };
22014 
22015 void
22016 Dbdict::execDROP_FILE_REQ(Signal* signal)
22017 {
22018  jamEntry();
22019  if (!assembleFragments(signal)) {
22020  jam();
22021  return;
22022  }
22023  SectionHandle handle(this, signal);
22024 
22025  const DropFileReq req_copy =
22026  *(const DropFileReq*)signal->getDataPtr();
22027  const DropFileReq* req = &req_copy;
22028 
22029  ErrorInfo error;
22030  do {
22031  SchemaOpPtr op_ptr;
22032  DropFileRecPtr dropFilePtr;
22033  DropFileImplReq* impl_req;
22034 
22035  startClientReq(op_ptr, dropFilePtr, req, impl_req, error);
22036  if (hasError(error)) {
22037  jam();
22038  break;
22039  }
22040 
22041  impl_req->file_id = req->file_id;
22042  impl_req->file_version = req->file_version;
22043 
22044  handleClientReq(signal, op_ptr, handle);
22045  return;
22046  } while (0);
22047 
22048  releaseSections(handle);
22049 
22050  DropFileRef* ref = (DropFileRef*)signal->getDataPtrSend();
22051  ref->senderRef = reference();
22052  ref->transId = req->transId;
22053  ref->senderData = req->senderData;
22054  getError(error, ref);
22055 
22056  sendSignal(req->senderRef, GSN_DROP_FILE_REF, signal,
22057  DropFileRef::SignalLength, JBB);
22058 }
22059 
22060 bool
22061 Dbdict::dropFile_seize(SchemaOpPtr op_ptr)
22062 {
22063  return seizeOpRec<DropFileRec>(op_ptr);
22064 }
22065 
22066 void
22067 Dbdict::dropFile_release(SchemaOpPtr op_ptr)
22068 {
22069  releaseOpRec<DropFileRec>(op_ptr);
22070 }
22071 
22072 // DropFile: PARSE
22073 
22074 void
22075 Dbdict::dropFile_parse(Signal* signal, bool master,
22076  SchemaOpPtr op_ptr,
22077  SectionHandle& handle, ErrorInfo& error)
22078 {
22079  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
22080  DropFileRecPtr dropFileRecPtr;
22081  getOpRec(op_ptr, dropFileRecPtr);
22082  DropFileImplReq* impl_req = &dropFileRecPtr.p->m_request;
22083 
22084  FilePtr f_ptr;
22085  if (!c_file_hash.find(f_ptr, impl_req->file_id))
22086  {
22087  jam();
22088  setError(error, DropFileRef::NoSuchFile, __LINE__);
22089  return;
22090  }
22091 
22092  if (f_ptr.p->m_version != impl_req->file_version)
22093  {
22094  jam();
22095  setError(error, DropFileRef::InvalidSchemaObjectVersion, __LINE__);
22096  return;
22097  }
22098 
22099  if (f_ptr.p->m_type == DictTabInfo::Undofile)
22100  {
22101  jam();
22102  setError(error, DropFileRef::DropUndoFileNotSupported, __LINE__);
22103  return;
22104  }
22105 
22106  if (check_write_obj(impl_req->file_id,
22107  trans_ptr.p->m_transId,
22108  SchemaFile::SF_DROP, error))
22109  {
22110  jam();
22111  return;
22112  }
22113 
22114  SchemaFile::TableEntry te; te.init();
22115  te.m_tableState = SchemaFile::SF_DROP;
22116  te.m_transId = trans_ptr.p->m_transId;
22117  Uint32 err = trans_log_schema_op(op_ptr, impl_req->file_id, &te);
22118  if (err)
22119  {
22120  jam();
22121  setError(error, err, __LINE__);
22122  return;
22123  }
22124 
22125 #if defined VM_TRACE || defined ERROR_INSERT
22126  {
22127  char buf[1024];
22128  Rope name(c_rope_pool, f_ptr.p->m_path);
22129  name.copy(buf);
22130  ndbout_c("Dbdict: drop name=%s,id=%u,obj_id=%u", buf,
22131  impl_req->file_id,
22132  f_ptr.p->m_obj_ptr_i);
22133  }
22134 #endif
22135 }
22136 
22137 void
22138 Dbdict::dropFile_abortParse(Signal* signal, SchemaOpPtr op_ptr)
22139 {
22140  jam();
22141  sendTransConf(signal, op_ptr);
22142 }
22143 
22144 bool
22145 Dbdict::dropFile_subOps(Signal* signal, SchemaOpPtr op_ptr)
22146 {
22147  return false;
22148 }
22149 
22150 void
22151 Dbdict::dropFile_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
22152 {
22153  jam();
22154  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
22155  DropFileRecPtr dropFileRecPtr;
22156  getOpRec(op_ptr, dropFileRecPtr);
22157  DropFileImplReq* impl_req = &dropFileRecPtr.p->m_request;
22158 
22159  if (!hasError(error))
22160  {
22161  jam();
22162  DropFileConf* conf = (DropFileConf*)signal->getDataPtrSend();
22163  conf->senderRef = reference();
22164  conf->senderData = op_ptr.p->m_clientData;
22165  conf->transId = trans_ptr.p->m_transId;
22166  conf->fileId = impl_req->file_id;
22167  conf->fileVersion = impl_req->file_version;
22168  Uint32 clientRef = op_ptr.p->m_clientRef;
22169  sendSignal(clientRef, GSN_DROP_FILE_CONF, signal,
22170  DropFileConf::SignalLength, JBB);
22171  }
22172  else
22173  {
22174  jam();
22175  DropFileRef* ref = (DropFileRef*)signal->getDataPtrSend();
22176  ref->senderRef = reference();
22177  ref->senderData = op_ptr.p->m_clientData;
22178  ref->transId = trans_ptr.p->m_transId;
22179  getError(error, ref);
22180 
22181  Uint32 clientRef = op_ptr.p->m_clientRef;
22182  sendSignal(clientRef, GSN_DROP_FILE_REF, signal,
22183  DropFileRef::SignalLength, JBB);
22184  }
22185 }
22186 
22187 // DropFile: PREPARE
22188 
22189 void
22190 Dbdict::dropFile_prepare(Signal* signal, SchemaOpPtr op_ptr)
22191 {
22192  jam();
22193 
22194  DropFileRecPtr dropFileRecPtr;
22195  getOpRec(op_ptr, dropFileRecPtr);
22196  DropFileImplReq* impl_req = &dropFileRecPtr.p->m_request;
22197 
22198  Callback c = {
22199  safe_cast(&Dbdict::dropFile_fromLocal), op_ptr.p->op_key
22200  };
22201  op_ptr.p->m_callback = c;
22202 
22203  send_drop_file(signal, op_ptr.p->op_key, impl_req->file_id,
22204  DropFileImplReq::Prepare);
22205 }
22206 
22207 void
22208 Dbdict::dropFile_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
22209 {
22210  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
22211  DropFileRecPtr dropFilePtr;
22212  getOpRec(op_ptr, dropFilePtr);
22213  DropFileImplReq* impl_req = &dropFilePtr.p->m_request;
22214 
22215  Callback c = {
22216  safe_cast(&Dbdict::dropFile_fromLocal), op_ptr.p->op_key
22217  };
22218  op_ptr.p->m_callback = c;
22219 
22220  send_drop_file(signal, op_ptr.p->op_key, impl_req->file_id,
22221  DropFileImplReq::Abort);
22222 }
22223 
22224 // DropFile: COMMIT
22225 
22226 void
22227 Dbdict::dropFile_commit(Signal* signal, SchemaOpPtr op_ptr)
22228 {
22229  jam();
22230 
22231  DropFileRecPtr dropFileRecPtr;
22232  getOpRec(op_ptr, dropFileRecPtr);
22233  DropFileImplReq* impl_req = &dropFileRecPtr.p->m_request;
22234 
22235  Callback c = {
22236  safe_cast(&Dbdict::dropFile_fromLocal), op_ptr.p->op_key
22237  };
22238  op_ptr.p->m_callback = c;
22239 
22240 
22241  send_drop_file(signal, op_ptr.p->op_key, impl_req->file_id,
22242  DropFileImplReq::Commit);
22243 }
22244 
22245 // DropFile: COMPLETE
22246 
22247 void
22248 Dbdict::dropFile_complete(Signal* signal, SchemaOpPtr op_ptr)
22249 {
22250  jam();
22251 
22252  DropFileRecPtr dropFileRecPtr;
22253  getOpRec(op_ptr, dropFileRecPtr);
22254  DropFileImplReq* impl_req = &dropFileRecPtr.p->m_request;
22255 
22256  FilePtr f_ptr;
22257  FilegroupPtr fg_ptr;
22258 
22259  jam();
22260  ndbrequire(c_file_hash.find(f_ptr, impl_req->file_id));
22261  ndbrequire(c_filegroup_hash.find(fg_ptr, f_ptr.p->m_filegroup_id));
22262  decrease_ref_count(fg_ptr.p->m_obj_ptr_i);
22263  release_object(f_ptr.p->m_obj_ptr_i);
22264  c_file_hash.release(f_ptr);
22265 
22266  sendTransConf(signal, op_ptr);
22267 }
22268 
22269 void
22270 Dbdict::dropFile_fromLocal(Signal* signal, Uint32 op_key, Uint32 ret)
22271 {
22272  jam();
22273  SchemaOpPtr op_ptr;
22274  DropFileRecPtr dropFilePtr;
22275  ndbrequire(findSchemaOp(op_ptr, dropFilePtr, op_key));
22276 
22277  if (ret == 0)
22278  {
22279  jam();
22280  sendTransConf(signal, op_ptr);
22281  }
22282  else
22283  {
22284  jam();
22285  setError(op_ptr, ret, __LINE__);
22286  sendTransRef(signal, op_ptr);
22287  }
22288 }
22289 
22290 void
22291 Dbdict::execDROP_FILE_IMPL_REF(Signal* signal)
22292 {
22293  jamEntry();
22294  DropFileImplRef * ref = (DropFileImplRef*)signal->getDataPtr();
22295  handleDictRef(signal, ref);
22296 }
22297 
22298 void
22299 Dbdict::execDROP_FILE_IMPL_CONF(Signal* signal)
22300 {
22301  jamEntry();
22302  DropFileImplConf * conf = (DropFileImplConf*)signal->getDataPtr();
22303  handleDictConf(signal, conf);
22304 }
22305 
22306 void
22307 Dbdict::send_drop_file(Signal* signal, Uint32 op_key, Uint32 fileId,
22308  DropFileImplReq::RequestInfo type)
22309 {
22310  DropFileImplReq* req = (DropFileImplReq*)signal->getDataPtrSend();
22311  FilePtr f_ptr;
22312  FilegroupPtr fg_ptr;
22313 
22314  jam();
22315  ndbrequire(c_file_hash.find(f_ptr, fileId));
22316  ndbrequire(c_filegroup_hash.find(fg_ptr, f_ptr.p->m_filegroup_id));
22317 
22318  req->senderData = op_key;
22319  req->senderRef = reference();
22320  req->requestInfo = type;
22321 
22322  req->file_id = f_ptr.p->key;
22323  req->filegroup_id = f_ptr.p->m_filegroup_id;
22324  req->filegroup_version = fg_ptr.p->m_version;
22325 
22326  Uint32 ref= 0;
22327  switch(f_ptr.p->m_type){
22328  case DictTabInfo::Datafile:
22329  {
22330  jam();
22331  ref = TSMAN_REF;
22332  break;
22333  }
22334  case DictTabInfo::Undofile:
22335  {
22336  jam();
22337  ref = LGMAN_REF;
22338  break;
22339  }
22340  default:
22341  ndbrequire(false);
22342  }
22343  sendSignal(ref, GSN_DROP_FILE_IMPL_REQ, signal,
22344  DropFileImplReq::SignalLength, JBB);
22345 }
22346 
22347 // DropFile: END
22348 
22349 // MODULE: DropFilegroup
22350 
22351 const Dbdict::OpInfo
22352 Dbdict::DropFilegroupRec::g_opInfo = {
22353  { 'D', 'F', 'g', 0 },
22354  GSN_DROP_FILEGROUP_IMPL_REQ,
22355  DropFilegroupImplReq::SignalLength,
22356  //
22357  &Dbdict::dropFilegroup_seize,
22358  &Dbdict::dropFilegroup_release,
22359  //
22360  &Dbdict::dropFilegroup_parse,
22361  &Dbdict::dropFilegroup_subOps,
22362  &Dbdict::dropFilegroup_reply,
22363  //
22364  &Dbdict::dropFilegroup_prepare,
22365  &Dbdict::dropFilegroup_commit,
22366  &Dbdict::dropFilegroup_complete,
22367  //
22368  &Dbdict::dropFilegroup_abortParse,
22369  &Dbdict::dropFilegroup_abortPrepare
22370 };
22371 
22372 void
22373 Dbdict::execDROP_FILEGROUP_REQ(Signal* signal)
22374 {
22375  jamEntry();
22376  if (!assembleFragments(signal)) {
22377  jam();
22378  return;
22379  }
22380  SectionHandle handle(this, signal);
22381 
22382  const DropFilegroupReq req_copy =
22383  *(const DropFilegroupReq*)signal->getDataPtr();
22384  const DropFilegroupReq* req = &req_copy;
22385 
22386  ErrorInfo error;
22387  do {
22388  SchemaOpPtr op_ptr;
22389  DropFilegroupRecPtr dropFilegroupPtr;
22390  DropFilegroupImplReq* impl_req;
22391 
22392  startClientReq(op_ptr, dropFilegroupPtr, req, impl_req, error);
22393  if (hasError(error)) {
22394  jam();
22395  break;
22396  }
22397 
22398  impl_req->filegroup_id = req->filegroup_id;
22399  impl_req->filegroup_version = req->filegroup_version;
22400 
22401  handleClientReq(signal, op_ptr, handle);
22402  return;
22403  } while (0);
22404 
22405  releaseSections(handle);
22406 
22407  DropFilegroupRef* ref = (DropFilegroupRef*)signal->getDataPtrSend();
22408  ref->senderRef = reference();
22409  ref->transId = req->transId;
22410  ref->senderData = req->senderData;
22411  getError(error, ref);
22412 
22413  sendSignal(req->senderRef, GSN_DROP_FILEGROUP_REF, signal,
22414  DropFilegroupRef::SignalLength, JBB);
22415 }
22416 
22417 bool
22418 Dbdict::dropFilegroup_seize(SchemaOpPtr op_ptr)
22419 {
22420  return seizeOpRec<DropFilegroupRec>(op_ptr);
22421 }
22422 
22423 void
22424 Dbdict::dropFilegroup_release(SchemaOpPtr op_ptr)
22425 {
22426  releaseOpRec<DropFilegroupRec>(op_ptr);
22427 }
22428 
22429 // DropFilegroup: PARSE
22430 
22431 void
22432 Dbdict::dropFilegroup_parse(Signal* signal, bool master,
22433  SchemaOpPtr op_ptr,
22434  SectionHandle& handle, ErrorInfo& error)
22435 {
22436  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
22437  DropFilegroupRecPtr dropFilegroupRecPtr;
22438  getOpRec(op_ptr, dropFilegroupRecPtr);
22439  DropFilegroupImplReq* impl_req = &dropFilegroupRecPtr.p->m_request;
22440 
22441  FilegroupPtr fg_ptr;
22442  if (!c_filegroup_hash.find(fg_ptr, impl_req->filegroup_id))
22443  {
22444  jam();
22445  setError(error, DropFilegroupRef::NoSuchFilegroup, __LINE__);
22446  return;
22447  }
22448 
22449  if (fg_ptr.p->m_version != impl_req->filegroup_version)
22450  {
22451  jam();
22452  setError(error, DropFilegroupRef::InvalidSchemaObjectVersion, __LINE__);
22453  return;
22454  }
22455 
22456  DictObject * obj = c_obj_pool.getPtr(fg_ptr.p->m_obj_ptr_i);
22457  if (obj->m_ref_count)
22458  {
22459  jam();
22460  setError(error, DropFilegroupRef::FilegroupInUse, __LINE__);
22461  return;
22462  }
22463 
22464  if (check_write_obj(impl_req->filegroup_id,
22465  trans_ptr.p->m_transId,
22466  SchemaFile::SF_DROP, error))
22467  {
22468  jam();
22469  return;
22470  }
22471 
22472  SchemaFile::TableEntry te; te.init();
22473  te.m_tableState = SchemaFile::SF_DROP;
22474  te.m_transId = trans_ptr.p->m_transId;
22475  Uint32 err = trans_log_schema_op(op_ptr, impl_req->filegroup_id, &te);
22476  if (err)
22477  {
22478  jam();
22479  setError(error, err, __LINE__);
22480  return;
22481  }
22482 
22483 #if defined VM_TRACE || defined ERROR_INSERT
22484  {
22485  char buf[1024];
22486  Rope name(c_rope_pool, fg_ptr.p->m_name);
22487  name.copy(buf);
22488  ndbout_c("Dbdict: drop name=%s,id=%u,obj_id=%u", buf,
22489  impl_req->filegroup_id,
22490  fg_ptr.p->m_obj_ptr_i);
22491  }
22492 #endif
22493 }
22494 
22495 void
22496 Dbdict::dropFilegroup_abortParse(Signal* signal, SchemaOpPtr op_ptr)
22497 {
22498  jam();
22499  sendTransConf(signal, op_ptr);
22500 }
22501 
22502 bool
22503 Dbdict::dropFilegroup_subOps(Signal* signal, SchemaOpPtr op_ptr)
22504 {
22505  return false;
22506 }
22507 
22508 void
22509 Dbdict::dropFilegroup_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
22510 {
22511  jam();
22512  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
22513  DropFilegroupRecPtr dropFilegroupRecPtr;
22514  getOpRec(op_ptr, dropFilegroupRecPtr);
22515  DropFilegroupImplReq* impl_req = &dropFilegroupRecPtr.p->m_request;
22516 
22517  if (!hasError(error))
22518  {
22519  jam();
22520  DropFilegroupConf* conf = (DropFilegroupConf*)signal->getDataPtrSend();
22521  conf->senderRef = reference();
22522  conf->senderData = op_ptr.p->m_clientData;
22523  conf->transId = trans_ptr.p->m_transId;
22524  conf->filegroupId = impl_req->filegroup_id;
22525  conf->filegroupVersion = impl_req->filegroup_version;
22526  Uint32 clientRef = op_ptr.p->m_clientRef;
22527  sendSignal(clientRef, GSN_DROP_FILEGROUP_CONF, signal,
22528  DropFilegroupConf::SignalLength, JBB);
22529  }
22530  else
22531  {
22532  jam();
22533  DropFilegroupRef* ref = (DropFilegroupRef*)signal->getDataPtrSend();
22534  ref->senderRef = reference();
22535  ref->senderData = op_ptr.p->m_clientData;
22536  ref->transId = trans_ptr.p->m_transId;
22537  getError(error, ref);
22538 
22539  Uint32 clientRef = op_ptr.p->m_clientRef;
22540  sendSignal(clientRef, GSN_DROP_FILEGROUP_REF, signal,
22541  DropFilegroupRef::SignalLength, JBB);
22542  }
22543 }
22544 
22545 // DropFilegroup: PREPARE
22546 
22547 void
22548 Dbdict::dropFilegroup_prepare(Signal* signal, SchemaOpPtr op_ptr)
22549 {
22550  jam();
22551  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
22552  DropFilegroupRecPtr dropFilegroupRecPtr;
22553  getOpRec(op_ptr, dropFilegroupRecPtr);
22554  DropFilegroupImplReq* impl_req = &dropFilegroupRecPtr.p->m_request;
22555 
22556  Callback c = {
22557  safe_cast(&Dbdict::dropFilegroup_fromLocal), op_ptr.p->op_key
22558  };
22559  op_ptr.p->m_callback = c;
22560 
22561  send_drop_fg(signal, op_ptr.p->op_key, impl_req->filegroup_id,
22562  DropFilegroupImplReq::Prepare);
22563 
22564  FilegroupPtr fg_ptr;
22565  ndbrequire(c_filegroup_hash.find(fg_ptr, impl_req->filegroup_id));
22566 
22567  if (fg_ptr.p->m_type == DictTabInfo::LogfileGroup)
22568  {
22569  XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
22570  Ptr<File> filePtr;
22571  Local_file_list list(c_file_pool, fg_ptr.p->m_logfilegroup.m_files);
22572  for(list.first(filePtr); !filePtr.isNull(); list.next(filePtr))
22573  {
22574  jam();
22575 
22576  DictObjectPtr objPtr;
22577  c_obj_pool.getPtr(objPtr, filePtr.p->m_obj_ptr_i);
22578  SchemaFile::TableEntry * entry = getTableEntry(xsf, objPtr.p->m_id);
22579  entry->m_tableState = SchemaFile::SF_DROP;
22580  entry->m_transId = trans_ptr.p->m_transId;
22581  }
22582  }
22583 }
22584 
22585 void
22586 Dbdict::dropFilegroup_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
22587 {
22588  ndbrequire(false);
22589  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
22590  DropFilegroupRecPtr dropFilegroupPtr;
22591  getOpRec(op_ptr, dropFilegroupPtr);
22592  DropFilegroupImplReq* impl_req = &dropFilegroupPtr.p->m_request;
22593 
22594  Callback c = {
22595  safe_cast(&Dbdict::dropFilegroup_fromLocal), op_ptr.p->op_key
22596  };
22597  op_ptr.p->m_callback = c;
22598 
22599  send_drop_fg(signal, op_ptr.p->op_key, impl_req->filegroup_id,
22600  DropFilegroupImplReq::Abort);
22601 
22602  FilegroupPtr fg_ptr;
22603  ndbrequire(c_filegroup_hash.find(fg_ptr, impl_req->filegroup_id));
22604 
22605  if (fg_ptr.p->m_type == DictTabInfo::LogfileGroup)
22606  {
22607  jam();
22608  XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
22609  Ptr<File> filePtr;
22610  Local_file_list list(c_file_pool, fg_ptr.p->m_logfilegroup.m_files);
22611  for(list.first(filePtr); !filePtr.isNull(); list.next(filePtr))
22612  {
22613  jam();
22614 
22615  DictObjectPtr objPtr;
22616  c_obj_pool.getPtr(objPtr, filePtr.p->m_obj_ptr_i);
22617  SchemaFile::TableEntry * entry = getTableEntry(xsf, objPtr.p->m_id);
22618  entry->m_tableState = SchemaFile::SF_IN_USE;
22619  entry->m_transId = 0;
22620  }
22621  }
22622 }
22623 
22624 // DropFilegroup: COMMIT
22625 
22626 void
22627 Dbdict::dropFilegroup_commit(Signal* signal, SchemaOpPtr op_ptr)
22628 {
22629  jam();
22630  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
22631  DropFilegroupRecPtr dropFilegroupRecPtr;
22632  getOpRec(op_ptr, dropFilegroupRecPtr);
22633  DropFilegroupImplReq* impl_req = &dropFilegroupRecPtr.p->m_request;
22634 
22635  Callback c = {
22636  safe_cast(&Dbdict::dropFilegroup_fromLocal), op_ptr.p->op_key
22637  };
22638  op_ptr.p->m_callback = c;
22639 
22640  send_drop_fg(signal, op_ptr.p->op_key, impl_req->filegroup_id,
22641  DropFilegroupImplReq::Commit);
22642 
22643  FilegroupPtr fg_ptr;
22644  ndbrequire(c_filegroup_hash.find(fg_ptr, impl_req->filegroup_id));
22645 
22646  if (fg_ptr.p->m_type == DictTabInfo::LogfileGroup)
22647  {
22648  jam();
22652  XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
22653 
22654  Ptr<File> filePtr;
22655  Local_file_list list(c_file_pool, fg_ptr.p->m_logfilegroup.m_files);
22656  for(list.first(filePtr); !filePtr.isNull(); list.next(filePtr))
22657  {
22658  jam();
22659 
22660  DictObjectPtr objPtr;
22661  c_obj_pool.getPtr(objPtr, filePtr.p->m_obj_ptr_i);
22662  SchemaFile::TableEntry * entry = getTableEntry(xsf, objPtr.p->m_id);
22663  entry->m_tableState = SchemaFile::SF_UNUSED;
22664  entry->m_transId = 0;
22665 
22666  release_object(objPtr.i, objPtr.p);
22667  c_file_hash.remove(filePtr);
22668  }
22669  list.release();
22670  }
22671  else if(fg_ptr.p->m_type == DictTabInfo::Tablespace)
22672  {
22673  jam();
22674  FilegroupPtr lg_ptr;
22675  ndbrequire(c_filegroup_hash.
22676  find(lg_ptr,
22677  fg_ptr.p->m_tablespace.m_default_logfile_group_id));
22678 
22679  decrease_ref_count(lg_ptr.p->m_obj_ptr_i);
22680  }
22681 }
22682 
22683 // DropFilegroup: COMPLETE
22684 
22685 void
22686 Dbdict::dropFilegroup_complete(Signal* signal, SchemaOpPtr op_ptr)
22687 {
22688  jam();
22689 
22690  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
22691  DropFilegroupRecPtr dropFilegroupRecPtr;
22692  getOpRec(op_ptr, dropFilegroupRecPtr);
22693  DropFilegroupImplReq* impl_req = &dropFilegroupRecPtr.p->m_request;
22694 
22695  FilegroupPtr fg_ptr;
22696  ndbrequire(c_filegroup_hash.find(fg_ptr, impl_req->filegroup_id));
22697 
22698  release_object(fg_ptr.p->m_obj_ptr_i);
22699  c_filegroup_hash.release(fg_ptr);
22700 
22701  sendTransConf(signal, op_ptr);
22702 }
22703 
22704 void
22705 Dbdict::dropFilegroup_fromLocal(Signal* signal, Uint32 op_key, Uint32 ret)
22706 {
22707  jam();
22708  SchemaOpPtr op_ptr;
22709  DropFilegroupRecPtr dropFilegroupPtr;
22710  ndbrequire(findSchemaOp(op_ptr, dropFilegroupPtr, op_key));
22711 
22712  if (ret == 0)
22713  {
22714  jam();
22715  sendTransConf(signal, op_ptr);
22716  }
22717  else
22718  {
22719  jam();
22720  setError(op_ptr, ret, __LINE__);
22721  sendTransRef(signal, op_ptr);
22722  }
22723 }
22724 
22725 void
22726 Dbdict::execDROP_FILEGROUP_IMPL_REF(Signal* signal)
22727 {
22728  jamEntry();
22729  DropFilegroupImplRef * ref = (DropFilegroupImplRef*)signal->getDataPtr();
22730  handleDictRef(signal, ref);
22731 }
22732 
22733 void
22734 Dbdict::execDROP_FILEGROUP_IMPL_CONF(Signal* signal)
22735 {
22736  jamEntry();
22737  DropFilegroupImplConf * conf = (DropFilegroupImplConf*)signal->getDataPtr();
22738  handleDictConf(signal, conf);
22739 }
22740 
22741 
22742 void
22743 Dbdict::send_drop_fg(Signal* signal, Uint32 op_key, Uint32 filegroupId,
22744  DropFilegroupImplReq::RequestInfo type)
22745 {
22746  DropFilegroupImplReq* req = (DropFilegroupImplReq*)signal->getDataPtrSend();
22747 
22748  FilegroupPtr fg_ptr;
22749  ndbrequire(c_filegroup_hash.find(fg_ptr, filegroupId));
22750 
22751  req->senderData = op_key;
22752  req->senderRef = reference();
22753  req->requestInfo = type;
22754 
22755  req->filegroup_id = fg_ptr.p->key;
22756  req->filegroup_version = fg_ptr.p->m_version;
22757 
22758  Uint32 ref= 0;
22759  switch(fg_ptr.p->m_type){
22761  ref = TSMAN_REF;
22762  break;
22764  ref = LGMAN_REF;
22765  break;
22766  default:
22767  ndbrequire(false);
22768  }
22769 
22770  sendSignal(ref, GSN_DROP_FILEGROUP_IMPL_REQ, signal,
22771  DropFilegroupImplReq::SignalLength, JBB);
22772 }
22773 
22774 // DropFilegroup: END
22775 
22776 // MODULE: CreateNodegroup
22777 
22778 const Dbdict::OpInfo
22779 Dbdict::CreateNodegroupRec::g_opInfo = {
22780  { 'C', 'N', 'G', 0 },
22781  GSN_CREATE_NODEGROUP_IMPL_REQ,
22782  CreateNodegroupImplReq::SignalLength,
22783  //
22784  &Dbdict::createNodegroup_seize,
22785  &Dbdict::createNodegroup_release,
22786  //
22787  &Dbdict::createNodegroup_parse,
22788  &Dbdict::createNodegroup_subOps,
22789  &Dbdict::createNodegroup_reply,
22790  //
22791  &Dbdict::createNodegroup_prepare,
22792  &Dbdict::createNodegroup_commit,
22793  &Dbdict::createNodegroup_complete,
22794  //
22795  &Dbdict::createNodegroup_abortParse,
22796  &Dbdict::createNodegroup_abortPrepare
22797 };
22798 
22799 void
22800 Dbdict::execCREATE_NODEGROUP_REQ(Signal* signal)
22801 {
22802  jamEntry();
22803  if (!assembleFragments(signal)) {
22804  jam();
22805  return;
22806  }
22807  SectionHandle handle(this, signal);
22808 
22809  const CreateNodegroupReq req_copy =
22810  *(const CreateNodegroupReq*)signal->getDataPtr();
22811  const CreateNodegroupReq* req = &req_copy;
22812 
22813  ErrorInfo error;
22814  do {
22815  SchemaOpPtr op_ptr;
22816  CreateNodegroupRecPtr createNodegroupRecPtr;
22817  CreateNodegroupImplReq* impl_req;
22818 
22819  startClientReq(op_ptr, createNodegroupRecPtr, req, impl_req, error);
22820  if (hasError(error)) {
22821  jam();
22822  break;
22823  }
22824 
22825  impl_req->nodegroupId = req->nodegroupId;
22826  for (Uint32 i = 0; i<NDB_ARRAY_SIZE(req->nodes) &&
22827  i<NDB_ARRAY_SIZE(impl_req->nodes); i++)
22828  {
22829  impl_req->nodes[i] = req->nodes[i];
22830  }
22831 
22832  handleClientReq(signal, op_ptr, handle);
22833  return;
22834  } while (0);
22835 
22836  releaseSections(handle);
22837 
22838  CreateNodegroupRef* ref = (CreateNodegroupRef*)signal->getDataPtrSend();
22839  ref->senderRef = reference();
22840  ref->transId = req->transId;
22841  ref->senderData = req->senderData;
22842  getError(error, ref);
22843 
22844  sendSignal(req->senderRef, GSN_CREATE_NODEGROUP_REF, signal,
22845  CreateNodegroupRef::SignalLength, JBB);
22846 }
22847 
22848 bool
22849 Dbdict::createNodegroup_seize(SchemaOpPtr op_ptr)
22850 {
22851  return seizeOpRec<CreateNodegroupRec>(op_ptr);
22852 }
22853 
22854 void
22855 Dbdict::createNodegroup_release(SchemaOpPtr op_ptr)
22856 {
22857  releaseOpRec<CreateNodegroupRec>(op_ptr);
22858 }
22859 
22860 // CreateNodegroup: PARSE
22861 
22862 void
22863 Dbdict::createNodegroup_parse(Signal* signal, bool master,
22864  SchemaOpPtr op_ptr,
22865  SectionHandle& handle, ErrorInfo& error)
22866 {
22867  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
22868  CreateNodegroupRecPtr createNodegroupRecPtr;
22869  getOpRec(op_ptr, createNodegroupRecPtr);
22870  CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
22871 
22872  jam();
22873 
22874  Uint32 save = impl_req->requestType;
22875  impl_req->requestType = CreateNodegroupImplReq::RT_PARSE;
22876  memcpy(signal->theData, impl_req, 4*CreateNodegroupImplReq::SignalLength);
22877  impl_req->requestType = save;
22878 
22879  EXECUTE_DIRECT(DBDIH, GSN_CREATE_NODEGROUP_IMPL_REQ, signal,
22880  CreateNodegroupImplReq::SignalLength);
22881  jamEntry();
22882 
22883  Uint32 ret = signal->theData[0];
22884  if (ret)
22885  {
22886  jam();
22887  setError(error, ret, __LINE__);
22888  return ;
22889  }
22890 
22891  impl_req->senderRef = reference();
22892  impl_req->senderData = op_ptr.p->op_key;
22893  impl_req->nodegroupId = signal->theData[1];
22894 
22899  trans_ptr.p->m_wait_gcp_on_commit = false;
22900 }
22901 
22902 void
22903 Dbdict::createNodegroup_abortParse(Signal* signal, SchemaOpPtr op_ptr)
22904 {
22905  jam();
22906  sendTransConf(signal, op_ptr);
22907 }
22908 
22909 bool
22910 Dbdict::createNodegroup_subOps(Signal* signal, SchemaOpPtr op_ptr)
22911 {
22912  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
22913  CreateNodegroupRecPtr createNodegroupRecPtr;
22914  getOpRec(op_ptr, createNodegroupRecPtr);
22915  //CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
22916 
22917  if (createNodegroupRecPtr.p->m_map_created == false)
22918  {
22919  jam();
22920  createNodegroupRecPtr.p->m_map_created = true;
22921 
22928  Uint32 buckets = 240;
22929  Uint32 fragments = get_default_fragments(signal, 1);
22930  char buf[MAX_TAB_NAME_SIZE+1];
22931  BaseString::snprintf(buf, sizeof(buf), "DEFAULT-HASHMAP-%u-%u",
22932  buckets,
22933  fragments);
22934 
22935  if (get_object(buf) != 0)
22936  {
22937  jam();
22938  return false;
22939  }
22940 
22941 
22942  Callback c = {
22943  safe_cast(&Dbdict::createNodegroup_fromCreateHashMap),
22944  op_ptr.p->op_key
22945  };
22946  op_ptr.p->m_callback = c;
22947 
22948  CreateHashMapReq* const req = (CreateHashMapReq*)signal->getDataPtrSend();
22949  req->clientRef = reference();
22950  req->clientData = op_ptr.p->op_key;
22951  req->requestInfo = 0;
22952  req->transId = trans_ptr.p->m_transId;
22953  req->transKey = trans_ptr.p->trans_key;
22954  req->buckets = buckets;
22955  req->fragments = fragments;
22956  sendSignal(DBDICT_REF, GSN_CREATE_HASH_MAP_REQ, signal,
22957  CreateHashMapReq::SignalLength, JBB);
22958  return true;
22959  }
22960 
22961  return false;
22962 }
22963 
22964 void
22965 Dbdict::createNodegroup_fromCreateHashMap(Signal* signal,
22966  Uint32 op_key,
22967  Uint32 ret)
22968 {
22969  SchemaOpPtr op_ptr;
22970  CreateNodegroupRecPtr createNodegroupRecPtr;
22971  findSchemaOp(op_ptr, createNodegroupRecPtr, op_key);
22972  ndbrequire(!op_ptr.isNull());
22973 
22974  if (ret == 0)
22975  {
22976  jam();
22977  createSubOps(signal, op_ptr);
22978  }
22979  else
22980  {
22981  jam();
22982  const CreateHashMapRef* ref = (const CreateHashMapRef*)signal->getDataPtr();
22983 
22984  ErrorInfo error;
22985  setError(error, ref);
22986  abortSubOps(signal, op_ptr, error);
22987  }
22988 }
22989 
22990 void
22991 Dbdict::createNodegroup_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
22992 {
22993  jam();
22994  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
22995  CreateNodegroupRecPtr createNodegroupRecPtr;
22996  getOpRec(op_ptr, createNodegroupRecPtr);
22997  CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
22998 
22999  if (!hasError(error))
23000  {
23001  jam();
23002  CreateNodegroupConf* conf = (CreateNodegroupConf*)signal->getDataPtrSend();
23003  conf->senderRef = reference();
23004  conf->senderData = op_ptr.p->m_clientData;
23005  conf->transId = trans_ptr.p->m_transId;
23006  conf->nodegroupId = impl_req->nodegroupId;
23007  Uint32 clientRef = op_ptr.p->m_clientRef;
23008  sendSignal(clientRef, GSN_CREATE_NODEGROUP_CONF, signal,
23009  CreateNodegroupConf::SignalLength, JBB);
23010  }
23011  else
23012  {
23013  jam();
23014  CreateNodegroupRef* ref = (CreateNodegroupRef*)signal->getDataPtrSend();
23015  ref->senderRef = reference();
23016  ref->senderData = op_ptr.p->m_clientData;
23017  ref->transId = trans_ptr.p->m_transId;
23018  getError(error, ref);
23019 
23020  Uint32 clientRef = op_ptr.p->m_clientRef;
23021  sendSignal(clientRef, GSN_CREATE_NODEGROUP_REF, signal,
23022  CreateNodegroupRef::SignalLength, JBB);
23023  }
23024 }
23025 
23026 // CreateNodegroup: PREPARE
23027 
23028 void
23029 Dbdict::createNodegroup_prepare(Signal* signal, SchemaOpPtr op_ptr)
23030 {
23031  jam();
23032  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23033  CreateNodegroupRecPtr createNodegroupRecPtr;
23034  getOpRec(op_ptr, createNodegroupRecPtr);
23035  CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
23036 
23037  impl_req->requestType = CreateNodegroupImplReq::RT_PREPARE;
23038  createNodegroupRecPtr.p->m_blockCnt = 2;
23039  createNodegroupRecPtr.p->m_blockIndex = 0;
23040  createNodegroupRecPtr.p->m_blockNo[0] = DBDIH_REF;
23041  createNodegroupRecPtr.p->m_blockNo[1] = SUMA_REF;
23042 
23043  Callback c = {
23044  safe_cast(&Dbdict::createNodegroup_fromBlockSubStartStop),
23045  op_ptr.p->op_key
23046  };
23047  op_ptr.p->m_callback = c;
23048 
23049  block_substartstop(signal, op_ptr);
23050 }
23051 
23052 void
23053 Dbdict::createNodegroup_fromBlockSubStartStop(Signal* signal,
23054  Uint32 op_key,
23055  Uint32 ret)
23056 {
23057  SchemaOpPtr op_ptr;
23058  CreateNodegroupRecPtr createNodegroupRecPtr;
23059  findSchemaOp(op_ptr, createNodegroupRecPtr, op_key);
23060  ndbrequire(!op_ptr.isNull());
23061  //CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
23062 
23063  if (ret == 0)
23064  {
23065  jam();
23066  createNodegroupRecPtr.p->m_substartstop_blocked = true;
23067  createNodegroup_toLocal(signal, op_ptr);
23068  }
23069  else
23070  {
23071  jam();
23072  setError(op_ptr, ret, __LINE__);
23073  sendTransRef(signal, op_ptr);
23074  }
23075 }
23076 
23077 void
23078 Dbdict::createNodegroup_toLocal(Signal* signal, SchemaOpPtr op_ptr)
23079 {
23080  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23081  CreateNodegroupRecPtr createNodegroupRecPtr;
23082  getOpRec(op_ptr, createNodegroupRecPtr);
23083  CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
23084 
23085  const Uint32 blockIndex = createNodegroupRecPtr.p->m_blockIndex;
23086  if (blockIndex == createNodegroupRecPtr.p->m_blockCnt)
23087  {
23088  jam();
23089 
23090  if (op_ptr.p->m_state == SchemaOp::OS_PREPARING)
23091  {
23092  jam();
23093 
23097  Callback c = {
23098  safe_cast(&Dbdict::createNodegroup_fromWaitGCP),
23099  op_ptr.p->op_key
23100  };
23101  op_ptr.p->m_callback = c;
23102 
23103  createNodegroupRecPtr.p->m_cnt_waitGCP = 0;
23104  createNodegroupRecPtr.p->m_wait_gcp_type = WaitGCPReq::BlockStartGcp;
23105  wait_gcp(signal, op_ptr, WaitGCPReq::BlockStartGcp);
23106  return;
23107  }
23108 
23109  if (op_ptr.p->m_state == SchemaOp::OS_COMPLETING)
23110  {
23111  jam();
23115  Callback c = {
23116  safe_cast(&Dbdict::createNodegroup_fromWaitGCP),
23117  op_ptr.p->op_key
23118  };
23119  op_ptr.p->m_callback = c;
23120 
23121  createNodegroupRecPtr.p->m_cnt_waitGCP = 0;
23122  createNodegroupRecPtr.p->m_wait_gcp_type = WaitGCPReq::UnblockStartGcp;
23123  wait_gcp(signal, op_ptr, WaitGCPReq::UnblockStartGcp);
23124  return;
23125  }
23126 
23127  sendTransConf(signal, op_ptr);
23128  return;
23129  }
23130 
23131  Callback c = {
23132  safe_cast(&Dbdict::createNodegroup_fromLocal),
23133  op_ptr.p->op_key
23134  };
23135  op_ptr.p->m_callback = c;
23136 
23137  Uint32 ref = createNodegroupRecPtr.p->m_blockNo[blockIndex];
23138  CreateNodegroupImplReq * req = (CreateNodegroupImplReq*)signal->getDataPtrSend();
23139  memcpy(req, impl_req, 4*CreateNodegroupImplReq::SignalLength);
23140  sendSignal(ref, GSN_CREATE_NODEGROUP_IMPL_REQ, signal,
23141  CreateNodegroupImplReq::SignalLength, JBB);
23142 }
23143 
23144 void
23145 Dbdict::createNodegroup_fromLocal(Signal* signal,
23146  Uint32 op_key,
23147  Uint32 ret)
23148 {
23149  SchemaOpPtr op_ptr;
23150  CreateNodegroupRecPtr createNodegroupRecPtr;
23151  findSchemaOp(op_ptr, createNodegroupRecPtr, op_key);
23152  ndbrequire(!op_ptr.isNull());
23153  CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
23154 
23155  Uint32 blockIndex = createNodegroupRecPtr.p->m_blockIndex;
23156  ndbrequire(blockIndex < createNodegroupRecPtr.p->m_blockCnt);
23157  if (ret)
23158  {
23159  jam();
23160  setError(op_ptr, ret, __LINE__);
23161  sendTransRef(signal, op_ptr);
23162  return;
23163  }
23164 
23165  Uint32 idx = createNodegroupRecPtr.p->m_blockIndex;
23166  if (op_ptr.p->m_state == SchemaOp::OS_COMPLETING &&
23167  createNodegroupRecPtr.p->m_blockNo[idx] == DBDIH_REF)
23168  {
23169  jam();
23170 
23171  CreateNodegroupImplConf * conf =
23172  (CreateNodegroupImplConf*)signal->getDataPtr();
23173  impl_req->gci_hi = conf->gci_hi;
23174  impl_req->gci_lo = conf->gci_lo;
23175  }
23176 
23177  createNodegroupRecPtr.p->m_blockIndex++;
23178  createNodegroup_toLocal(signal, op_ptr);
23179 }
23180 
23181 void
23182 Dbdict::createNodegroup_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
23183 {
23184  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23185  CreateNodegroupRecPtr createNodegroupRecPtr;
23186  getOpRec(op_ptr, createNodegroupRecPtr);
23187  //CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
23188 
23189  if (createNodegroupRecPtr.p->m_substartstop_blocked)
23190  {
23191  jam();
23192  unblock_substartstop();
23193  }
23194 
23195  if (createNodegroupRecPtr.p->m_gcp_blocked)
23196  {
23197  jam();
23198 
23199  Callback c = {
23200  safe_cast(&Dbdict::createNodegroup_fromWaitGCP),
23201  op_ptr.p->op_key
23202  };
23203  op_ptr.p->m_callback = c;
23204 
23205  createNodegroupRecPtr.p->m_cnt_waitGCP = 0;
23206  createNodegroupRecPtr.p->m_wait_gcp_type = WaitGCPReq::UnblockStartGcp;
23207  wait_gcp(signal, op_ptr, WaitGCPReq::UnblockStartGcp);
23208  return;
23209  }
23210 
23211  sendTransConf(signal, op_ptr);
23212 }
23213 
23214 // CreateNodegroup: COMMIT
23215 
23216 void
23217 Dbdict::createNodegroup_commit(Signal* signal, SchemaOpPtr op_ptr)
23218 {
23219  jam();
23220  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23221  CreateNodegroupRecPtr createNodegroupRecPtr;
23222  getOpRec(op_ptr, createNodegroupRecPtr);
23223  CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
23224 
23225  impl_req->requestType = CreateNodegroupImplReq::RT_COMMIT;
23226  createNodegroupRecPtr.p->m_blockCnt = 2;
23227  createNodegroupRecPtr.p->m_blockIndex = 0;
23228  createNodegroupRecPtr.p->m_blockNo[0] = DBDIH_REF;
23229  createNodegroupRecPtr.p->m_blockNo[1] = NDBCNTR_REF;
23230 
23231  Callback c = {
23232  safe_cast(&Dbdict::createNodegroup_fromWaitGCP),
23233  op_ptr.p->op_key
23234  };
23235  op_ptr.p->m_callback = c;
23236 
23237  createNodegroupRecPtr.p->m_cnt_waitGCP = 0;
23238  createNodegroupRecPtr.p->m_wait_gcp_type = WaitGCPReq::WaitEpoch;
23239  wait_gcp(signal, op_ptr, WaitGCPReq::WaitEpoch);
23240 }
23241 
23242 void
23243 Dbdict::createNodegroup_fromWaitGCP(Signal* signal,
23244  Uint32 op_key,
23245  Uint32 ret)
23246 {
23247  jam();
23248  SchemaOpPtr op_ptr;
23249  CreateNodegroupRecPtr createNodegroupRecPtr;
23250  findSchemaOp(op_ptr, createNodegroupRecPtr, op_key);
23251  ndbrequire(!op_ptr.isNull());
23252 
23253  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23254  //CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
23255 
23256  if (ret == 0)
23257  {
23258  jam();
23259 
23260  Uint32 wait_type = createNodegroupRecPtr.p->m_wait_gcp_type;
23261  if (op_ptr.p->m_state == SchemaOp::OS_ABORTED_PREPARE)
23262  {
23263  jam();
23264  ndbrequire(wait_type == WaitGCPReq::UnblockStartGcp);
23265  sendTransConf(signal, op_ptr);
23266  return;
23267  }
23268  else if (op_ptr.p->m_state == SchemaOp::OS_PREPARING)
23269  {
23270  jam();
23271  ndbrequire(wait_type == WaitGCPReq::BlockStartGcp);
23272  createNodegroupRecPtr.p->m_gcp_blocked = true;
23273  sendTransConf(signal, op_ptr);
23274  return;
23275  }
23276  else if (op_ptr.p->m_state == SchemaOp::OS_COMMITTING)
23277  {
23278  jam();
23279  ndbrequire(wait_type == WaitGCPReq::WaitEpoch);
23280  createNodegroup_toLocal(signal, op_ptr);
23281  return;
23282  }
23283  else
23284  {
23285  jam();
23286  ndbrequire(op_ptr.p->m_state == SchemaOp::OS_COMPLETING);
23287 
23288  if (wait_type == WaitGCPReq::UnblockStartGcp)
23289  {
23290  jam();
23291  wait_type = WaitGCPReq::CompleteForceStart;
23292  createNodegroupRecPtr.p->m_wait_gcp_type = wait_type;
23293  goto retry;
23294  }
23295  else
23296  {
23297  jam();
23298  ndbrequire(wait_type == WaitGCPReq::CompleteForceStart);
23299  unblock_substartstop();
23300  }
23301 
23302  sendTransConf(signal, op_ptr);
23303  return;
23304  }
23305  }
23306 
23307  createNodegroupRecPtr.p->m_cnt_waitGCP++;
23308  switch(ret){
23309  case WaitGCPRef::NoWaitGCPRecords:
23310  jam();
23311  case WaitGCPRef::NF_CausedAbortOfProcedure:
23312  jam();
23313  case WaitGCPRef::NF_MasterTakeOverInProgress:
23314  jam();
23315  }
23316 
23317 retry:
23318  wait_gcp(signal, op_ptr, createNodegroupRecPtr.p->m_wait_gcp_type);
23319 }
23320 
23321 // CreateNodegroup: COMPLETE
23322 
23323 void
23324 Dbdict::createNodegroup_complete(Signal* signal, SchemaOpPtr op_ptr)
23325 {
23326  jam();
23327  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23328  CreateNodegroupRecPtr createNodegroupRecPtr;
23329  getOpRec(op_ptr, createNodegroupRecPtr);
23330  CreateNodegroupImplReq* impl_req = &createNodegroupRecPtr.p->m_request;
23331 
23332  impl_req->requestType = CreateNodegroupImplReq::RT_COMPLETE;
23333  createNodegroupRecPtr.p->m_blockCnt = 2;
23334  createNodegroupRecPtr.p->m_blockIndex = 0;
23335  createNodegroupRecPtr.p->m_blockNo[0] = DBDIH_REF;
23336  createNodegroupRecPtr.p->m_blockNo[1] = SUMA_REF;
23337 
23338  createNodegroup_toLocal(signal, op_ptr);
23339 }
23340 
23341 void
23342 Dbdict::execCREATE_NODEGROUP_IMPL_REF(Signal* signal)
23343 {
23344  jamEntry();
23345  CreateNodegroupImplRef * ref = (CreateNodegroupImplRef*)signal->getDataPtr();
23346  handleDictRef(signal, ref);
23347 }
23348 
23349 void
23350 Dbdict::execCREATE_NODEGROUP_IMPL_CONF(Signal* signal)
23351 {
23352  jamEntry();
23353  CreateNodegroupImplConf * conf = (CreateNodegroupImplConf*)signal->getDataPtr();
23354  handleDictConf(signal, conf);
23355 }
23356 
23357 void
23358 Dbdict::execCREATE_HASH_MAP_REF(Signal* signal)
23359 {
23360  jamEntry();
23361  CreateHashMapRef * ref = (CreateHashMapRef*)signal->getDataPtr();
23362  handleDictRef(signal, ref);
23363 }
23364 
23365 void
23366 Dbdict::execCREATE_HASH_MAP_CONF(Signal* signal)
23367 {
23368  jamEntry();
23369  CreateHashMapConf * conf = (CreateHashMapConf*)signal->getDataPtr();
23370  handleDictConf(signal, conf);
23371 }
23372 
23373 // CreateNodegroup: END
23374 
23375 // MODULE: DropNodegroup
23376 
23377 const Dbdict::OpInfo
23378 Dbdict::DropNodegroupRec::g_opInfo = {
23379  { 'D', 'N', 'G', 0 },
23380  GSN_DROP_NODEGROUP_IMPL_REQ,
23381  DropNodegroupImplReq::SignalLength,
23382  //
23383  &Dbdict::dropNodegroup_seize,
23384  &Dbdict::dropNodegroup_release,
23385  //
23386  &Dbdict::dropNodegroup_parse,
23387  &Dbdict::dropNodegroup_subOps,
23388  &Dbdict::dropNodegroup_reply,
23389  //
23390  &Dbdict::dropNodegroup_prepare,
23391  &Dbdict::dropNodegroup_commit,
23392  &Dbdict::dropNodegroup_complete,
23393  //
23394  &Dbdict::dropNodegroup_abortParse,
23395  &Dbdict::dropNodegroup_abortPrepare
23396 };
23397 
23398 void
23399 Dbdict::execDROP_NODEGROUP_REQ(Signal* signal)
23400 {
23401  jamEntry();
23402  if (!assembleFragments(signal)) {
23403  jam();
23404  return;
23405  }
23406  SectionHandle handle(this, signal);
23407 
23408  const DropNodegroupReq req_copy =
23409  *(const DropNodegroupReq*)signal->getDataPtr();
23410  const DropNodegroupReq* req = &req_copy;
23411 
23412  ErrorInfo error;
23413  do {
23414  SchemaOpPtr op_ptr;
23415  DropNodegroupRecPtr dropNodegroupRecPtr;
23416  DropNodegroupImplReq* impl_req;
23417 
23418  startClientReq(op_ptr, dropNodegroupRecPtr, req, impl_req, error);
23419  if (hasError(error)) {
23420  jam();
23421  break;
23422  }
23423 
23424  impl_req->nodegroupId = req->nodegroupId;
23425 
23426  handleClientReq(signal, op_ptr, handle);
23427  return;
23428  } while (0);
23429 
23430  releaseSections(handle);
23431 
23432  DropNodegroupRef* ref = (DropNodegroupRef*)signal->getDataPtrSend();
23433  ref->senderRef = reference();
23434  ref->transId = req->transId;
23435  ref->senderData = req->senderData;
23436  getError(error, ref);
23437 
23438  sendSignal(req->senderRef, GSN_DROP_NODEGROUP_REF, signal,
23439  DropNodegroupRef::SignalLength, JBB);
23440 }
23441 
23442 bool
23443 Dbdict::dropNodegroup_seize(SchemaOpPtr op_ptr)
23444 {
23445  return seizeOpRec<DropNodegroupRec>(op_ptr);
23446 }
23447 
23448 void
23449 Dbdict::dropNodegroup_release(SchemaOpPtr op_ptr)
23450 {
23451  releaseOpRec<DropNodegroupRec>(op_ptr);
23452 }
23453 
23454 // DropNodegroup: PARSE
23455 
23456 void
23457 Dbdict::dropNodegroup_parse(Signal* signal, bool master,
23458  SchemaOpPtr op_ptr,
23459  SectionHandle& handle, ErrorInfo& error)
23460 {
23461  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23462  DropNodegroupRecPtr dropNodegroupRecPtr;
23463  getOpRec(op_ptr, dropNodegroupRecPtr);
23464  DropNodegroupImplReq* impl_req = &dropNodegroupRecPtr.p->m_request;
23465 
23466  impl_req->senderRef = reference();
23467  impl_req->senderData = op_ptr.p->op_key;
23468 
23473  trans_ptr.p->m_wait_gcp_on_commit = false;
23474 }
23475 
23476 void
23477 Dbdict::dropNodegroup_abortParse(Signal* signal, SchemaOpPtr op_ptr)
23478 {
23479  jam();
23480  sendTransConf(signal, op_ptr);
23481 }
23482 
23483 bool
23484 Dbdict::dropNodegroup_subOps(Signal* signal, SchemaOpPtr op_ptr)
23485 {
23486  return false;
23487 }
23488 
23489 void
23490 Dbdict::dropNodegroup_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
23491 {
23492  jam();
23493  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23494  DropNodegroupRecPtr dropNodegroupRecPtr;
23495  getOpRec(op_ptr, dropNodegroupRecPtr);
23496  //DropNodegroupImplReq* impl_req = &dropNodegroupRecPtr.p->m_request;
23497 
23498  if (!hasError(error))
23499  {
23500  jam();
23501  DropNodegroupConf* conf = (DropNodegroupConf*)signal->getDataPtrSend();
23502  conf->senderRef = reference();
23503  conf->senderData = op_ptr.p->m_clientData;
23504  conf->transId = trans_ptr.p->m_transId;
23505  Uint32 clientRef = op_ptr.p->m_clientRef;
23506  sendSignal(clientRef, GSN_DROP_NODEGROUP_CONF, signal,
23507  DropNodegroupConf::SignalLength, JBB);
23508  }
23509  else
23510  {
23511  jam();
23512  DropNodegroupRef* ref = (DropNodegroupRef*)signal->getDataPtrSend();
23513  ref->senderRef = reference();
23514  ref->senderData = op_ptr.p->m_clientData;
23515  ref->transId = trans_ptr.p->m_transId;
23516  getError(error, ref);
23517 
23518  Uint32 clientRef = op_ptr.p->m_clientRef;
23519  sendSignal(clientRef, GSN_DROP_NODEGROUP_REF, signal,
23520  DropNodegroupRef::SignalLength, JBB);
23521  }
23522 }
23523 
23524 // DropNodegroup: PREPARE
23525 
23526 void
23527 Dbdict::dropNodegroup_prepare(Signal* signal, SchemaOpPtr op_ptr)
23528 {
23529  jam();
23530  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23531  DropNodegroupRecPtr dropNodegroupRecPtr;
23532  getOpRec(op_ptr, dropNodegroupRecPtr);
23533  DropNodegroupImplReq* impl_req = &dropNodegroupRecPtr.p->m_request;
23534 
23535  impl_req->requestType = DropNodegroupImplReq::RT_PREPARE;
23536  dropNodegroupRecPtr.p->m_blockCnt = 2;
23537  dropNodegroupRecPtr.p->m_blockIndex = 0;
23538  dropNodegroupRecPtr.p->m_blockNo[0] = DBDIH_REF;
23539  dropNodegroupRecPtr.p->m_blockNo[1] = SUMA_REF;
23540 
23541  Callback c = {
23542  safe_cast(&Dbdict::dropNodegroup_fromBlockSubStartStop),
23543  op_ptr.p->op_key
23544  };
23545  op_ptr.p->m_callback = c;
23546 
23547  block_substartstop(signal, op_ptr);
23548 }
23549 
23550 void
23551 Dbdict::dropNodegroup_fromBlockSubStartStop(Signal* signal,
23552  Uint32 op_key,
23553  Uint32 ret)
23554 {
23555  SchemaOpPtr op_ptr;
23556  DropNodegroupRecPtr dropNodegroupRecPtr;
23557  findSchemaOp(op_ptr, dropNodegroupRecPtr, op_key);
23558  ndbrequire(!op_ptr.isNull());
23559  //DropNodegroupImplReq* impl_req = &dropNodegroupRecPtr.p->m_request;
23560 
23561  if (ret == 0)
23562  {
23563  jam();
23564  dropNodegroupRecPtr.p->m_substartstop_blocked = true;
23565  dropNodegroup_toLocal(signal, op_ptr);
23566  }
23567  else
23568  {
23569  jam();
23570  setError(op_ptr, ret, __LINE__);
23571  sendTransRef(signal, op_ptr);
23572  }
23573 }
23574 
23575 void
23576 Dbdict::dropNodegroup_toLocal(Signal* signal, SchemaOpPtr op_ptr)
23577 {
23578  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23579  DropNodegroupRecPtr dropNodegroupRecPtr;
23580  getOpRec(op_ptr, dropNodegroupRecPtr);
23581  DropNodegroupImplReq* impl_req = &dropNodegroupRecPtr.p->m_request;
23582 
23583  const Uint32 blockIndex = dropNodegroupRecPtr.p->m_blockIndex;
23584  if (blockIndex == dropNodegroupRecPtr.p->m_blockCnt)
23585  {
23586  jam();
23587 
23588  if (op_ptr.p->m_state == SchemaOp::OS_PREPARING)
23589  {
23590  jam();
23591 
23595  Callback c = {
23596  safe_cast(&Dbdict::dropNodegroup_fromWaitGCP),
23597  op_ptr.p->op_key
23598  };
23599  op_ptr.p->m_callback = c;
23600 
23601  dropNodegroupRecPtr.p->m_cnt_waitGCP = 0;
23602  dropNodegroupRecPtr.p->m_wait_gcp_type = WaitGCPReq::BlockStartGcp;
23603  wait_gcp(signal, op_ptr, WaitGCPReq::BlockStartGcp);
23604  return;
23605  }
23606 
23607  if (op_ptr.p->m_state == SchemaOp::OS_COMPLETING)
23608  {
23609  jam();
23613  Callback c = {
23614  safe_cast(&Dbdict::dropNodegroup_fromWaitGCP),
23615  op_ptr.p->op_key
23616  };
23617  op_ptr.p->m_callback = c;
23618 
23619  dropNodegroupRecPtr.p->m_cnt_waitGCP = 0;
23620  dropNodegroupRecPtr.p->m_wait_gcp_type = WaitGCPReq::UnblockStartGcp;
23621  wait_gcp(signal, op_ptr, WaitGCPReq::UnblockStartGcp);
23622  return;
23623  }
23624 
23625  sendTransConf(signal, op_ptr);
23626  return;
23627  }
23628 
23629  Callback c = {
23630  safe_cast(&Dbdict::dropNodegroup_fromLocal),
23631  op_ptr.p->op_key
23632  };
23633  op_ptr.p->m_callback = c;
23634 
23635  Uint32 ref = dropNodegroupRecPtr.p->m_blockNo[blockIndex];
23636  DropNodegroupImplReq * req = (DropNodegroupImplReq*)signal->getDataPtrSend();
23637  memcpy(req, impl_req, 4*DropNodegroupImplReq::SignalLength);
23638  sendSignal(ref, GSN_DROP_NODEGROUP_IMPL_REQ, signal,
23639  DropNodegroupImplReq::SignalLength, JBB);
23640 }
23641 
23642 void
23643 Dbdict::dropNodegroup_fromLocal(Signal* signal,
23644  Uint32 op_key,
23645  Uint32 ret)
23646 {
23647  SchemaOpPtr op_ptr;
23648  DropNodegroupRecPtr dropNodegroupRecPtr;
23649  findSchemaOp(op_ptr, dropNodegroupRecPtr, op_key);
23650  ndbrequire(!op_ptr.isNull());
23651  DropNodegroupImplReq* impl_req = &dropNodegroupRecPtr.p->m_request;
23652 
23653  Uint32 blockIndex = dropNodegroupRecPtr.p->m_blockIndex;
23654  ndbrequire(blockIndex < dropNodegroupRecPtr.p->m_blockCnt);
23655 
23656  if (ret)
23657  {
23658  jam();
23659  setError(op_ptr, ret, __LINE__);
23660  sendTransRef(signal, op_ptr);
23661  return;
23662  }
23663 
23664  Uint32 idx = dropNodegroupRecPtr.p->m_blockIndex;
23665  if (op_ptr.p->m_state == SchemaOp::OS_COMMITTING &&
23666  dropNodegroupRecPtr.p->m_blockNo[idx] == DBDIH_REF)
23667  {
23668  jam();
23669 
23670  DropNodegroupImplConf * conf =
23671  (DropNodegroupImplConf*)signal->getDataPtr();
23672  impl_req->gci_hi = conf->gci_hi;
23673  impl_req->gci_lo = conf->gci_lo;
23674  }
23675 
23676 
23677  dropNodegroupRecPtr.p->m_blockIndex++;
23678  dropNodegroup_toLocal(signal, op_ptr);
23679 }
23680 
23681 
23682 void
23683 Dbdict::dropNodegroup_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
23684 {
23685  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23686  DropNodegroupRecPtr dropNodegroupRecPtr;
23687  getOpRec(op_ptr, dropNodegroupRecPtr);
23688  //DropNodegroupImplReq* impl_req = &dropNodegroupRecPtr.p->m_request;
23689 
23690  if (dropNodegroupRecPtr.p->m_substartstop_blocked)
23691  {
23692  jam();
23693  unblock_substartstop();
23694  }
23695 
23696  if (dropNodegroupRecPtr.p->m_gcp_blocked)
23697  {
23698  jam();
23699 
23700  Callback c = {
23701  safe_cast(&Dbdict::dropNodegroup_fromWaitGCP),
23702  op_ptr.p->op_key
23703  };
23704  op_ptr.p->m_callback = c;
23705 
23706  dropNodegroupRecPtr.p->m_cnt_waitGCP = 0;
23707  dropNodegroupRecPtr.p->m_wait_gcp_type = WaitGCPReq::UnblockStartGcp;
23708  wait_gcp(signal, op_ptr, WaitGCPReq::UnblockStartGcp);
23709  return;
23710  }
23711 
23712  sendTransConf(signal, op_ptr);
23713 }
23714 
23715 // DropNodegroup: COMMIT
23716 
23717 void
23718 Dbdict::dropNodegroup_commit(Signal* signal, SchemaOpPtr op_ptr)
23719 {
23720  jam();
23721  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23722  DropNodegroupRecPtr dropNodegroupRecPtr;
23723  getOpRec(op_ptr, dropNodegroupRecPtr);
23724  DropNodegroupImplReq* impl_req = &dropNodegroupRecPtr.p->m_request;
23725 
23726  impl_req->requestType = DropNodegroupImplReq::RT_COMMIT;
23727 
23728  dropNodegroupRecPtr.p->m_blockIndex = 0;
23729  dropNodegroupRecPtr.p->m_blockCnt = 1;
23730  dropNodegroupRecPtr.p->m_blockNo[0] = DBDIH_REF;
23731 
23732  Callback c = {
23733  safe_cast(&Dbdict::dropNodegroup_fromWaitGCP),
23734  op_ptr.p->op_key
23735  };
23736  op_ptr.p->m_callback = c;
23737 
23738  dropNodegroupRecPtr.p->m_cnt_waitGCP = 0;
23739  dropNodegroupRecPtr.p->m_wait_gcp_type = WaitGCPReq::WaitEpoch;
23740  wait_gcp(signal, op_ptr, WaitGCPReq::WaitEpoch);
23741 }
23742 
23743 void
23744 Dbdict::dropNodegroup_fromWaitGCP(Signal* signal,
23745  Uint32 op_key,
23746  Uint32 ret)
23747 {
23748  jam();
23749  SchemaOpPtr op_ptr;
23750  DropNodegroupRecPtr dropNodegroupRecPtr;
23751  findSchemaOp(op_ptr, dropNodegroupRecPtr, op_key);
23752  ndbrequire(!op_ptr.isNull());
23753 
23754  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23755  //DropNodegroupImplReq* impl_req = &dropNodegroupRecPtr.p->m_request;
23756 
23757  if (ret == 0)
23758  {
23759  jam();
23760 
23761  Uint32 wait_type = dropNodegroupRecPtr.p->m_wait_gcp_type;
23762  if (op_ptr.p->m_state == SchemaOp::OS_ABORTING_PREPARE)
23763  {
23764  jam();
23765  ndbrequire(wait_type == WaitGCPReq::UnblockStartGcp);
23766  sendTransConf(signal, op_ptr);
23767  return;
23768  }
23769  else if (op_ptr.p->m_state == SchemaOp::OS_PREPARING)
23770  {
23771  jam();
23772  ndbrequire(wait_type == WaitGCPReq::BlockStartGcp);
23773  dropNodegroupRecPtr.p->m_gcp_blocked = true;
23774  sendTransConf(signal, op_ptr);
23775  return;
23776  }
23777  else if (op_ptr.p->m_state == SchemaOp::OS_COMMITTING)
23778  {
23779  jam();
23780  ndbrequire(wait_type == WaitGCPReq::WaitEpoch);
23781  dropNodegroup_toLocal(signal, op_ptr);
23782  return;
23783  }
23784  else
23785  {
23786  jam();
23787 
23788  ndbrequire(op_ptr.p->m_state == SchemaOp::OS_COMPLETING);
23789  if (wait_type == WaitGCPReq::UnblockStartGcp)
23790  {
23794  jam();
23795  dropNodegroupRecPtr.p->m_wait_gcp_type = WaitGCPReq::CompleteForceStart;
23796  goto retry;
23797  }
23798  else
23799  {
23800  jam();
23801  ndbrequire(wait_type == WaitGCPReq::CompleteForceStart);
23802  unblock_substartstop();
23803  }
23804  sendTransConf(signal, op_ptr);
23805  return;
23806  }
23807  }
23808 
23809  dropNodegroupRecPtr.p->m_cnt_waitGCP++;
23810  switch(ret){
23811  case WaitGCPRef::NoWaitGCPRecords:
23812  jam();
23813  case WaitGCPRef::NF_CausedAbortOfProcedure:
23814  jam();
23815  case WaitGCPRef::NF_MasterTakeOverInProgress:
23816  jam();
23817  }
23818 
23819 retry:
23820  wait_gcp(signal, op_ptr, dropNodegroupRecPtr.p->m_wait_gcp_type);
23821 }
23822 
23823 // DropNodegroup: COMPLETE
23824 
23825 void
23826 Dbdict::dropNodegroup_complete(Signal* signal, SchemaOpPtr op_ptr)
23827 {
23828  jam();
23829 
23830  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23831  DropNodegroupRecPtr dropNodegroupRecPtr;
23832  getOpRec(op_ptr, dropNodegroupRecPtr);
23833  DropNodegroupImplReq* impl_req = &dropNodegroupRecPtr.p->m_request;
23834 
23835  impl_req->requestType = DropNodegroupImplReq::RT_COMPLETE;
23836  dropNodegroupRecPtr.p->m_blockIndex = 0;
23837  dropNodegroupRecPtr.p->m_blockCnt = 3;
23838  dropNodegroupRecPtr.p->m_blockNo[0] = SUMA_REF;
23839  dropNodegroupRecPtr.p->m_blockNo[1] = DBDIH_REF;
23840  dropNodegroupRecPtr.p->m_blockNo[2] = NDBCNTR_REF;
23841 
23842  dropNodegroup_toLocal(signal, op_ptr);
23843 }
23844 
23845 void
23846 Dbdict::execDROP_NODEGROUP_IMPL_REF(Signal* signal)
23847 {
23848  jamEntry();
23849  DropNodegroupImplRef * ref = (DropNodegroupImplRef*)signal->getDataPtr();
23850  handleDictRef(signal, ref);
23851 }
23852 
23853 void
23854 Dbdict::execDROP_NODEGROUP_IMPL_CONF(Signal* signal)
23855 {
23856  jamEntry();
23857  DropNodegroupImplConf * conf = (DropNodegroupImplConf*)signal->getDataPtr();
23858  handleDictConf(signal, conf);
23859 }
23860 
23861 // DropNodegroup: END
23862 
23863 /*
23864  return 1 if all of the below is true
23865  a) node in single user mode
23866  b) senderRef is not a db node
23867  c) senderRef nodeid is not the singleUserApi
23868 */
23869 int Dbdict::checkSingleUserMode(Uint32 senderRef)
23870 {
23871  Uint32 nodeId = refToNode(senderRef);
23872  return
23874  (getNodeInfo(nodeId).m_type != NodeInfo::DB) &&
23875  (nodeId != getNodeState().getSingleUserApi());
23876 }
23877 
23878 // MODULE: SchemaTrans
23879 
23880 // ErrorInfo
23881 
23882 void
23883 Dbdict::setError(ErrorInfo& e,
23884  Uint32 code,
23885  Uint32 line,
23886  Uint32 nodeId,
23887  Uint32 status,
23888  Uint32 key,
23889  const char * name)
23890 {
23891  D("setError" << V(code) << V(line) << V(nodeId) << V(e.errorCount));
23892 
23893  // can only store details for first error
23894  if (e.errorCount == 0) {
23895  e.errorCode = code;
23896  e.errorLine = line;
23897  e.errorNodeId = nodeId ? nodeId : getOwnNodeId();
23898  e.errorStatus = status;
23899  e.errorKey = key;
23900  BaseString::snprintf(e.errorObjectName, sizeof(e.errorObjectName), "%s",
23901  name ? name : "");
23902  }
23903  e.errorCount++;
23904 }
23905 
23906 void
23907 Dbdict::setError(ErrorInfo& e,
23908  Uint32 code,
23909  Uint32 line,
23910  const char * name)
23911 {
23912  setError(e, code, line, 0, 0, 0, name);
23913 }
23914 
23915 void
23916 Dbdict::setError(ErrorInfo& e, const ErrorInfo& e2)
23917 {
23918  setError(e, e2.errorCode, e2.errorLine, e2.errorNodeId);
23919 }
23920 
23921 void
23922 Dbdict::setError(ErrorInfo& e, const ParseDictTabInfoRecord& e2)
23923 {
23924  setError(e, e2.errorCode, e2.errorLine, 0, e2.status, e2.errorKey);
23925 }
23926 
23927 void
23928 Dbdict::setError(SchemaOpPtr op_ptr, Uint32 code, Uint32 line, Uint32 nodeId)
23929 {
23930  D("setError" << *op_ptr.p << V(code) << V(line) << V(nodeId));
23931  setError(op_ptr.p->m_error, code, line, nodeId);
23932 
23933  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
23934  // wl3600_todo remove the check
23935  if (!trans_ptr.isNull()) {
23936  setError(trans_ptr.p->m_error, op_ptr.p->m_error);
23937  }
23938 }
23939 
23940 void
23941 Dbdict::setError(SchemaOpPtr op_ptr, const ErrorInfo& e2)
23942 {
23943  setError(op_ptr, e2.errorCode, e2.errorLine, e2.errorNodeId);
23944 }
23945 
23946 void
23947 Dbdict::setError(SchemaTransPtr trans_ptr, Uint32 code, Uint32 line, Uint32 nodeId)
23948 {
23949  D("setError" << *trans_ptr.p << V(code) << V(line) << V(nodeId));
23950  setError(trans_ptr.p->m_error, code, line, nodeId);
23951 }
23952 
23953 void
23954 Dbdict::setError(SchemaTransPtr trans_ptr, const ErrorInfo& e2)
23955 {
23956  setError(trans_ptr, e2.errorCode, e2.errorLine, e2.errorNodeId);
23957 }
23958 
23959 void
23960 Dbdict::setError(TxHandlePtr tx_ptr, Uint32 code, Uint32 line, Uint32 nodeId)
23961 {
23962  D("setError" << *tx_ptr.p << V(code) << V(line) << V(nodeId));
23963  setError(tx_ptr.p->m_error, code, line, nodeId);
23964 }
23965 
23966 void
23967 Dbdict::setError(TxHandlePtr tx_ptr, const ErrorInfo& e2)
23968 {
23969  setError(tx_ptr, e2.errorCode, e2.errorLine, e2.errorNodeId);
23970 }
23971 
23972 bool
23973 Dbdict::hasError(const ErrorInfo& e)
23974 {
23975  return e.errorCount != 0;
23976 }
23977 
23978 void
23979 Dbdict::resetError(ErrorInfo& e)
23980 {
23981  new (&e) ErrorInfo();
23982 }
23983 
23984 void
23985 Dbdict::resetError(SchemaOpPtr op_ptr)
23986 {
23987  if (hasError(op_ptr.p->m_error)) {
23988  jam();
23989  D("resetError" << *op_ptr.p);
23990  resetError(op_ptr.p->m_error);
23991  }
23992 }
23993 
23994 void
23995 Dbdict::resetError(SchemaTransPtr trans_ptr)
23996 {
23997  if (hasError(trans_ptr.p->m_error)) {
23998  jam();
23999  D("resetError" << *trans_ptr.p);
24000  resetError(trans_ptr.p->m_error);
24001  }
24002 }
24003 
24004 void
24005 Dbdict::resetError(TxHandlePtr tx_ptr)
24006 {
24007  if (hasError(tx_ptr.p->m_error)) {
24008  jam();
24009  D("resetError" << *tx_ptr.p);
24010  resetError(tx_ptr.p->m_error);
24011  }
24012 }
24013 
24014 // OpInfo
24015 
24016 const Dbdict::OpInfo*
24017 Dbdict::g_opInfoList[] = {
24018  &Dbdict::CreateTableRec::g_opInfo,
24019  &Dbdict::DropTableRec::g_opInfo,
24020  &Dbdict::AlterTableRec::g_opInfo,
24021  &Dbdict::CreateTriggerRec::g_opInfo,
24022  &Dbdict::DropTriggerRec::g_opInfo,
24023  &Dbdict::CreateIndexRec::g_opInfo,
24024  &Dbdict::DropIndexRec::g_opInfo,
24025  &Dbdict::AlterIndexRec::g_opInfo,
24026  &Dbdict::BuildIndexRec::g_opInfo,
24027  &Dbdict::IndexStatRec::g_opInfo,
24028  &Dbdict::CreateFilegroupRec::g_opInfo,
24029  &Dbdict::CreateFileRec::g_opInfo,
24030  &Dbdict::DropFilegroupRec::g_opInfo,
24031  &Dbdict::DropFileRec::g_opInfo,
24032  &Dbdict::CreateHashMapRec::g_opInfo,
24033  &Dbdict::CopyDataRec::g_opInfo,
24034  &Dbdict::CreateNodegroupRec::g_opInfo,
24035  &Dbdict::DropNodegroupRec::g_opInfo,
24036  0
24037 };
24038 
24039 const Dbdict::OpInfo*
24040 Dbdict::findOpInfo(Uint32 gsn)
24041 {
24042  Uint32 i = 0;
24043  while (g_opInfoList[i]) {
24044  const OpInfo* info = g_opInfoList[i];
24045  if (info->m_impl_req_gsn == 0)
24046  break;
24047  if (info->m_impl_req_gsn == gsn)
24048  return info;
24049  i++;
24050  }
24051  ndbrequire(false);
24052  return 0;
24053 }
24054 
24055 // OpRec
24056 
24057 // OpSection
24058 
24059 bool
24060 Dbdict::copyIn(OpSection& op_sec, const SegmentedSectionPtr& ss_ptr)
24061 {
24062  const Uint32 size = 1024;
24063  Uint32 buf[size];
24064 
24065  SegmentedSectionPtr tmp = ss_ptr;
24066  SectionReader reader(tmp, getSectionSegmentPool());
24067  Uint32 len = ss_ptr.sz;
24068  while (len > size)
24069  {
24070  jam();
24071  ndbrequire(reader.getWords(buf, size));
24072  if (!copyIn(op_sec, buf, size))
24073  {
24074  jam();
24075  return false;
24076  }
24077  len -= size;
24078  }
24079 
24080  ndbrequire(reader.getWords(buf, len));
24081  if (!copyIn(op_sec, buf, len))
24082  {
24083  jam();
24084  return false;
24085  }
24086 
24087  return true;
24088 }
24089 
24090 bool
24091 Dbdict::copyIn(OpSection& op_sec, const Uint32* src, Uint32 srcSize)
24092 {
24093  OpSectionBuffer buffer(c_opSectionBufferPool, op_sec.m_head);
24094  if (!buffer.append(src, srcSize)) {
24095  jam();
24096  return false;
24097  }
24098  return true;
24099 }
24100 
24101 bool
24102 Dbdict::copyOut(Dbdict::OpSectionBuffer & buffer,
24104  Uint32 * dst,
24105  Uint32 len)
24106 {
24107  Uint32 n = 0;
24108  for(; !iter.isNull() && n < len; buffer.next(iter))
24109  {
24110  dst[n] = *iter.data;
24111  n++;
24112  }
24113 
24114  return n == len;
24115 }
24116 
24117 bool
24118 Dbdict::copyOut(const OpSection& op_sec, SegmentedSectionPtr& ss_ptr)
24119 {
24120  const Uint32 size = 1024;
24121  Uint32 buf[size];
24122 
24123  Uint32 len = op_sec.getSize();
24124  OpSectionBufferHead tmp_head = op_sec.m_head;
24125  OpSectionBuffer buffer(c_opSectionBufferPool, tmp_head);
24126 
24127  OpSectionBufferConstIterator iter;
24128  buffer.first(iter);
24129  Uint32 ptrI = RNIL;
24130  while (len > size)
24131  {
24132  if (!copyOut(buffer, iter, buf, size))
24133  {
24134  jam();
24135  goto fail;
24136  }
24137  if (!appendToSection(ptrI, buf, size))
24138  {
24139  jam();
24140  goto fail;
24141  }
24142  len -= size;
24143  }
24144 
24145  if (!copyOut(buffer, iter, buf, len))
24146  {
24147  jam();
24148  goto fail;
24149  }
24150 
24151  if (!appendToSection(ptrI, buf, len))
24152  {
24153  jam();
24154  goto fail;
24155  }
24156 
24157  getSection(ss_ptr, ptrI);
24158  return true;
24159 
24160 fail:
24161  releaseSection(ptrI);
24162  return false;
24163 }
24164 
24165 bool
24166 Dbdict::copyOut(const OpSection& op_sec, Uint32* dst, Uint32 dstSize)
24167 {
24168  if (op_sec.getSize() > dstSize) {
24169  jam();
24170  return false;
24171  }
24172 
24173  // there is no const version of LocalDataBuffer
24174  OpSectionBufferHead tmp_head = op_sec.m_head;
24175  OpSectionBuffer buffer(c_opSectionBufferPool, tmp_head);
24176 
24177  OpSectionBufferConstIterator iter;
24178  Uint32 n = 0;
24179  for(buffer.first(iter); !iter.isNull(); buffer.next(iter)) {
24180  jam();
24181  dst[n] = *iter.data;
24182  n++;
24183  }
24184  ndbrequire(n == op_sec.getSize());
24185  return true;
24186 }
24187 
24188 void
24189 Dbdict::release(OpSection& op_sec)
24190 {
24191  OpSectionBuffer buffer(c_opSectionBufferPool, op_sec.m_head);
24192  buffer.release();
24193 }
24194 
24195 // SchemaOp
24196 
24197 const Dbdict::OpInfo&
24198 Dbdict::getOpInfo(SchemaOpPtr op_ptr)
24199 {
24200  ndbrequire(!op_ptr.isNull());
24201  OpRecPtr oprec_ptr = op_ptr.p->m_oprec_ptr;
24202  ndbrequire(!oprec_ptr.isNull());
24203  return oprec_ptr.p->m_opInfo;
24204 }
24205 
24206 bool
24207 Dbdict::seizeSchemaOp(SchemaOpPtr& op_ptr, Uint32 op_key, const OpInfo& info)
24208 {
24209  if ((ERROR_INSERTED(6111) &&
24210  (info.m_impl_req_gsn == GSN_CREATE_TAB_REQ ||
24211  info.m_impl_req_gsn == GSN_DROP_TAB_REQ ||
24212  info.m_impl_req_gsn == GSN_ALTER_TAB_REQ)) ||
24213  (ERROR_INSERTED(6112) &&
24214  (info.m_impl_req_gsn == GSN_CREATE_INDX_IMPL_REQ ||
24215  info.m_impl_req_gsn == GSN_DROP_INDX_IMPL_REQ)) ||
24216  (ERROR_INSERTED(6113) &&
24217  (info.m_impl_req_gsn == GSN_ALTER_INDX_IMPL_REQ)) ||
24218  (ERROR_INSERTED(6114) &&
24219  (info.m_impl_req_gsn == GSN_CREATE_TRIG_IMPL_REQ ||
24220  info.m_impl_req_gsn == GSN_DROP_TRIG_IMPL_REQ)) ||
24221  (ERROR_INSERTED(6116) &&
24222  (info.m_impl_req_gsn == GSN_BUILD_INDX_IMPL_REQ)))
24223  {
24224  jam();
24225  CLEAR_ERROR_INSERT_VALUE;
24226  op_ptr.setNull();
24227  return false;
24228  }
24229 
24230  if (!findSchemaOp(op_ptr, op_key)) {
24231  jam();
24232  if (c_schemaOpHash.seize(op_ptr)) {
24233  jam();
24234  new (op_ptr.p) SchemaOp();
24235  op_ptr.p->op_key = op_key;
24236  if ((this->*(info.m_seize))(op_ptr)) {
24237  jam();
24238  c_schemaOpHash.add(op_ptr);
24239  op_ptr.p->m_magic = SchemaOp::DICT_MAGIC;
24240  D("seizeSchemaOp" << V(op_key) << V(info.m_opType));
24241  return true;
24242  }
24243  c_schemaOpPool.release(op_ptr);
24244  }
24245  }
24246  op_ptr.setNull();
24247  return false;
24248 }
24249 
24250 bool
24251 Dbdict::findSchemaOp(SchemaOpPtr& op_ptr, Uint32 op_key)
24252 {
24253  SchemaOp op_rec(op_key);
24254  if (c_schemaOpHash.find(op_ptr, op_rec)) {
24255  jam();
24256  const OpRecPtr& oprec_ptr = op_ptr.p->m_oprec_ptr;
24257  ndbrequire(!oprec_ptr.isNull());
24258  ndbrequire(op_ptr.p->m_magic == SchemaOp::DICT_MAGIC);
24259  D("findSchemaOp" << V(op_key));
24260  return true;
24261  }
24262  return false;
24263 }
24264 
24265 void
24266 Dbdict::releaseSchemaOp(SchemaOpPtr& op_ptr)
24267 {
24268  D("releaseSchemaOp" << V(op_ptr.p->op_key));
24269 
24270  const OpInfo& info = getOpInfo(op_ptr);
24271  (this->*(info.m_release))(op_ptr);
24272 
24273  while (op_ptr.p->m_sections != 0) {
24274  jam();
24275  releaseOpSection(op_ptr, op_ptr.p->m_sections - 1);
24276  }
24277 
24278  OpRecPtr oprec_ptr = op_ptr.p->m_oprec_ptr;
24279  Uint32 obj_ptr_i = oprec_ptr.p->m_obj_ptr_i;
24280  if (obj_ptr_i != RNIL) {
24281  jam();
24282  unlinkDictObject(op_ptr);
24283  }
24284 
24285  if (!op_ptr.p->m_oplnk_ptr.isNull()) {
24286  jam();
24287  releaseSchemaOp(op_ptr.p->m_oplnk_ptr);
24288  }
24289 
24290  ndbrequire(op_ptr.p->m_magic == SchemaOp::DICT_MAGIC);
24291  op_ptr.p->m_magic = 0;
24292  c_schemaOpHash.release(op_ptr);
24293  op_ptr.setNull();
24294 }
24295 
24296 // save signal sections
24297 
24298 const Dbdict::OpSection&
24299 Dbdict::getOpSection(SchemaOpPtr op_ptr, Uint32 ss_no)
24300 {
24301  ndbrequire(ss_no < op_ptr.p->m_sections);
24302  return op_ptr.p->m_section[ss_no];
24303 }
24304 
24305 bool
24306 Dbdict::saveOpSection(SchemaOpPtr op_ptr,
24307  SectionHandle& handle, Uint32 ss_no)
24308 {
24309  SegmentedSectionPtr ss_ptr;
24310  bool ok = handle.getSection(ss_ptr, ss_no);
24311  ndbrequire(ok);
24312  return saveOpSection(op_ptr, ss_ptr, ss_no);
24313 }
24314 
24315 bool
24316 Dbdict::saveOpSection(SchemaOpPtr op_ptr,
24317  SegmentedSectionPtr ss_ptr, Uint32 ss_no)
24318 {
24319  ndbrequire(ss_no <= 2 && op_ptr.p->m_sections == ss_no);
24320  OpSection& op_sec = op_ptr.p->m_section[ss_no];
24321  op_ptr.p->m_sections++;
24322 
24323  bool ok = copyIn(op_sec, ss_ptr);
24324  ndbrequire(ok);
24325  return true;
24326 }
24327 
24328 void
24329 Dbdict::releaseOpSection(SchemaOpPtr op_ptr, Uint32 ss_no)
24330 {
24331  ndbrequire(ss_no + 1 == op_ptr.p->m_sections);
24332  OpSection& op_sec = op_ptr.p->m_section[ss_no];
24333  release(op_sec);
24334  op_ptr.p->m_sections = ss_no;
24335 }
24336 
24337 // add schema op to trans during parse phase
24338 
24339 void
24340 Dbdict::addSchemaOp(SchemaTransPtr trans_ptr, SchemaOpPtr& op_ptr)
24341 {
24342  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
24343  list.addLast(op_ptr);
24344 
24345  op_ptr.p->m_trans_ptr = trans_ptr;
24346 
24347  // jonas_todo REMOVE side effect
24348  // add global flags from trans
24349  const Uint32& src_info = trans_ptr.p->m_requestInfo;
24350  DictSignal::addRequestFlagsGlobal(op_ptr.p->m_requestInfo, src_info);
24351 }
24352 
24353 // update op step after successful execution
24354 
24355 // the link SchemaOp -> DictObject -> SchemaTrans
24356 
24357 // check if link to dict object exists
24358 bool
24359 Dbdict::hasDictObject(SchemaOpPtr op_ptr)
24360 {
24361  OpRecPtr oprec_ptr = op_ptr.p->m_oprec_ptr;
24362  return oprec_ptr.p->m_obj_ptr_i != RNIL;
24363 }
24364 
24365 // get dict object for existing link
24366 void
24367 Dbdict::getDictObject(SchemaOpPtr op_ptr, DictObjectPtr& obj_ptr)
24368 {
24369  OpRecPtr oprec_ptr = op_ptr.p->m_oprec_ptr;
24370  ndbrequire(oprec_ptr.p->m_obj_ptr_i != RNIL);
24371  c_obj_pool.getPtr(obj_ptr, oprec_ptr.p->m_obj_ptr_i);
24372 }
24373 
24374 // create link from schema op to dict object
24375 void
24376 Dbdict::linkDictObject(SchemaOpPtr op_ptr, DictObjectPtr obj_ptr)
24377 {
24378  ndbrequire(!obj_ptr.isNull());
24379  D("linkDictObject" << V(op_ptr.p->op_key) << V(obj_ptr.i));
24380 
24381  OpRecPtr oprec_ptr = op_ptr.p->m_oprec_ptr;
24382  ndbrequire(oprec_ptr.p->m_obj_ptr_i == RNIL);
24383  oprec_ptr.p->m_obj_ptr_i = obj_ptr.i;
24384 
24385  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
24386  if (!trans_ptr.isNull()) {
24387  jam();
24388  ndbrequire(trans_ptr.p->trans_key != 0);
24389  if (obj_ptr.p->m_op_ref_count == 0) {
24390  jam();
24391  obj_ptr.p->m_trans_key = trans_ptr.p->trans_key;
24392  } else {
24393  ndbrequire(obj_ptr.p->m_trans_key == trans_ptr.p->trans_key);
24394  }
24395  } else {
24396  jam();
24397  // restart table uses no trans (yet)
24398  ndbrequire(memcmp(oprec_ptr.p->m_opType, "CTa", 4) == 0);
24399  ndbrequire(getNodeState().startLevel != NodeState::SL_STARTED);
24400  }
24401 
24402  obj_ptr.p->m_op_ref_count += 1;
24403  D("linkDictObject done" << *obj_ptr.p);
24404 }
24405 
24406 // drop link from schema op to dict object
24407 void
24408 Dbdict::unlinkDictObject(SchemaOpPtr op_ptr)
24409 {
24410  DictObjectPtr obj_ptr;
24411  OpRecPtr oprec_ptr = op_ptr.p->m_oprec_ptr;
24412  ndbrequire(oprec_ptr.p->m_obj_ptr_i != RNIL);
24413  c_obj_pool.getPtr(obj_ptr, oprec_ptr.p->m_obj_ptr_i);
24414 
24415  D("unlinkDictObject" << V(op_ptr.p->op_key) << V(obj_ptr.i));
24416 
24417  oprec_ptr.p->m_obj_ptr_i = RNIL;
24418  ndbrequire(obj_ptr.p->m_op_ref_count != 0);
24419  obj_ptr.p->m_op_ref_count -= 1;
24420  ndbrequire(obj_ptr.p->m_trans_key != 0);
24421  if (obj_ptr.p->m_op_ref_count == 0) {
24422  jam();
24423  obj_ptr.p->m_trans_key = 0;
24424  }
24425  D("unlinkDictObject done" << *obj_ptr.p);
24426 }
24427 
24428 // add new dict object and link schema op to it
24429 void
24430 Dbdict::seizeDictObject(SchemaOpPtr op_ptr,
24431  DictObjectPtr& obj_ptr,
24432  const RopeHandle& name)
24433 {
24434  D("seizeDictObject" << *op_ptr.p);
24435 
24436  bool ok = c_obj_hash.seize(obj_ptr);
24437  ndbrequire(ok);
24438  new (obj_ptr.p) DictObject();
24439 
24440  obj_ptr.p->m_name = name;
24441  c_obj_hash.add(obj_ptr);
24442  obj_ptr.p->m_ref_count = 0;
24443 
24444  linkDictObject(op_ptr, obj_ptr);
24445  D("seizeDictObject done" << *obj_ptr.p);
24446 }
24447 
24448 // find dict object by name and link schema op to it
24449 bool
24450 Dbdict::findDictObject(SchemaOpPtr op_ptr,
24451  DictObjectPtr& obj_ptr,
24452  const char* name)
24453 {
24454  D("findDictObject" << *op_ptr.p << V(name));
24455  if (get_object(obj_ptr, name)) {
24456  jam();
24457  linkDictObject(op_ptr, obj_ptr);
24458  return true;
24459  }
24460  return false;
24461 }
24462 
24463 // find dict object by i-value and link schema op to it
24464 bool
24465 Dbdict::findDictObject(SchemaOpPtr op_ptr,
24466  DictObjectPtr& obj_ptr,
24467  Uint32 obj_ptr_i)
24468 {
24469  D("findDictObject" << *op_ptr.p << V(obj_ptr.i));
24470  if (obj_ptr_i != RNIL) {
24471  jam();
24472  c_obj_pool.getPtr(obj_ptr, obj_ptr_i);
24473  linkDictObject(op_ptr, obj_ptr);
24474  return true;
24475  }
24476  return false;
24477 }
24478 
24479 // remove link to dict object and release the dict object
24480 void
24481 Dbdict::releaseDictObject(SchemaOpPtr op_ptr)
24482 {
24483  DictObjectPtr obj_ptr;
24484  getDictObject(op_ptr, obj_ptr);
24485 
24486  D("releaseDictObject" << *op_ptr.p << V(obj_ptr.i) << *obj_ptr.p);
24487 
24488  unlinkDictObject(op_ptr);
24489 
24490  // check no other object or operation references it
24491  ndbrequire(obj_ptr.p->m_ref_count == 0);
24492  if (obj_ptr.p->m_op_ref_count == 0) {
24493  jam();
24494  release_object(obj_ptr.i);
24495  }
24496 }
24497 
24498 // find last op on dict object
24499 void
24500 Dbdict::findDictObjectOp(SchemaOpPtr& op_ptr, DictObjectPtr obj_ptr)
24501 {
24502  D("findDictObjectOp" << *obj_ptr.p);
24503  op_ptr.setNull();
24504 
24505  Uint32 trans_key = obj_ptr.p->m_trans_key;
24506  do {
24507  if (trans_key == 0) {
24508  jam();
24509  D("no trans_key");
24510  break;
24511  }
24512 
24513  SchemaTransPtr trans_ptr;
24514  findSchemaTrans(trans_ptr, trans_key);
24515  if (trans_ptr.isNull()) {
24516  jam();
24517  D("trans not found");
24518  break;
24519  }
24520  D("found" << *trans_ptr.p);
24521 
24522  {
24523  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
24524  SchemaOpPtr loop_ptr;
24525  list.first(loop_ptr);
24526  while (!loop_ptr.isNull()) {
24527  jam();
24528  OpRecPtr oprec_ptr = loop_ptr.p->m_oprec_ptr;
24529  if (oprec_ptr.p->m_obj_ptr_i == obj_ptr.i) {
24530  jam();
24531  op_ptr = loop_ptr;
24532  D("found candidate" << *op_ptr.p);
24533  }
24534  list.next(loop_ptr);
24535  }
24536  }
24537  } while (0);
24538 }
24539 
24540 // trans state
24541 
24542 
24543 // SchemaTrans
24544 
24545 bool
24546 Dbdict::seizeSchemaTrans(SchemaTransPtr& trans_ptr, Uint32 trans_key)
24547 {
24548  if (ERROR_INSERTED(6101)) {
24549  jam();
24550  CLEAR_ERROR_INSERT_VALUE;
24551  trans_ptr.setNull();
24552  return false;
24553  }
24554  if (!findSchemaTrans(trans_ptr, trans_key)) {
24555  jam();
24556  if (c_schemaTransHash.seize(trans_ptr)) {
24557  jam();
24558  new (trans_ptr.p) SchemaTrans();
24559  trans_ptr.p->trans_key = trans_key;
24560  c_schemaTransHash.add(trans_ptr);
24561  c_schemaTransList.addLast(trans_ptr);
24562  c_schemaTransCount++;
24563  trans_ptr.p->m_magic = SchemaTrans::DICT_MAGIC;
24564  D("seizeSchemaTrans" << V(trans_key));
24565  return true;
24566  }
24567  }
24568  trans_ptr.setNull();
24569  return false;
24570 }
24571 
24572 bool
24573 Dbdict::seizeSchemaTrans(SchemaTransPtr& trans_ptr)
24574 {
24575  Uint32 trans_key = c_opRecordSequence + 1;
24576  if (seizeSchemaTrans(trans_ptr, trans_key)) {
24577 #ifdef MARTIN
24578  ndbout_c("Dbdict::seizeSchemaTrans: Seized schema trans %u", trans_key);
24579 #endif
24580  c_opRecordSequence = trans_key;
24581  return true;
24582  }
24583 #ifdef MARTIN
24584  ndbout_c("Dbdict::seizeSchemaTrans: Failed to seize schema trans");
24585 #endif
24586  return false;
24587 }
24588 
24589 bool
24590 Dbdict::findSchemaTrans(SchemaTransPtr& trans_ptr, Uint32 trans_key)
24591 {
24592  SchemaTrans trans_rec(trans_key);
24593  if (c_schemaTransHash.find(trans_ptr, trans_rec)) {
24594  jam();
24595  ndbrequire(trans_ptr.p->m_magic == SchemaTrans::DICT_MAGIC);
24596  D("findSchemaTrans" << V(trans_key));
24597  return true;
24598  }
24599  trans_ptr.setNull();
24600  return false;
24601 }
24602 
24603 void
24604 Dbdict::releaseSchemaTrans(SchemaTransPtr& trans_ptr)
24605 {
24606  D("releaseSchemaTrans" << V(trans_ptr.p->trans_key));
24607 
24608  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
24609  SchemaOpPtr op_ptr;
24610  while (list.first(op_ptr)) {
24611  list.remove(op_ptr);
24612  releaseSchemaOp(op_ptr);
24613  }
24614  ndbrequire(trans_ptr.p->m_magic == SchemaTrans::DICT_MAGIC);
24615  trans_ptr.p->m_magic = 0;
24616  ndbrequire(c_schemaTransCount != 0);
24617  c_schemaTransCount--;
24618  c_schemaTransList.remove(trans_ptr);
24619  c_schemaTransHash.release(trans_ptr);
24620  trans_ptr.setNull();
24621 
24622  if (c_schemaTransCount == 0)
24623  {
24624  jam();
24625 
24626  ndbrequire(c_schemaOpPool.getNoOfFree() == c_schemaOpPool.getSize());
24627  ndbrequire(c_opSectionBufferPool.getNoOfFree() == c_opSectionBufferPool.getSize());
24628 #ifdef VM_TRACE
24630  check_consistency();
24631 #endif
24632  }
24633 }
24634 
24635 // client requests
24636 
24637 void
24638 Dbdict::execSCHEMA_TRANS_BEGIN_REQ(Signal* signal)
24639 {
24640  jamEntry();
24641  const SchemaTransBeginReq* req =
24642  (const SchemaTransBeginReq*)signal->getDataPtr();
24643  Uint32 clientRef = req->clientRef;
24644 #ifdef MARTIN
24645  ndbout_c("Dbdict::execSCHEMA_TRANS_BEGIN_REQ: received GSN_SCHEMA_TRANS_BEGIN_REQ from 0x%8x", clientRef);
24646 #endif
24647 
24648  Uint32 transId = req->transId;
24649  Uint32 requestInfo = req->requestInfo;
24650 
24651  bool localTrans = (requestInfo & DictSignal::RF_LOCAL_TRANS);
24652 
24653  SchemaTransPtr trans_ptr;
24654  ErrorInfo error;
24655  do {
24656  if (getOwnNodeId() != c_masterNodeId && !localTrans) {
24657  jam();
24658  setError(error, SchemaTransBeginRef::NotMaster, __LINE__);
24659  break;
24660  }
24661 
24662  if (!check_ndb_versions() && !localTrans)
24663  {
24664  jam();
24665  setError(error, SchemaTransBeginRef::IncompatibleVersions, __LINE__);
24666  break;
24667  }
24668 
24669  if (!seizeSchemaTrans(trans_ptr)) {
24670  jam();
24671  // future when more than 1 tx allowed
24672  setError(error, SchemaTransBeginRef::TooManySchemaTrans, __LINE__);
24673  break;
24674  }
24675 
24676  trans_ptr.p->m_isMaster = true;
24677  trans_ptr.p->m_masterRef = reference();
24678  trans_ptr.p->m_clientRef = clientRef;
24679  trans_ptr.p->m_transId = transId;
24680  trans_ptr.p->m_requestInfo = requestInfo;
24681  trans_ptr.p->m_obj_id = getFreeObjId(0);
24682  if (localTrans)
24683  {
24691  trans_ptr.p->m_obj_id = getFreeObjId(0, true);
24692  }
24693 
24694  if (!localTrans)
24695  {
24696  jam();
24697  trans_ptr.p->m_nodes = c_aliveNodes;
24698  }
24699  else
24700  {
24701  jam();
24702  trans_ptr.p->m_nodes.clear();
24703  trans_ptr.p->m_nodes.set(getOwnNodeId());
24704  }
24705  trans_ptr.p->m_clientState = TransClient::BeginReq;
24706 
24707  // lock
24708  DictLockReq& lockReq = trans_ptr.p->m_lockReq;
24709  lockReq.userPtr = trans_ptr.p->trans_key;
24710  lockReq.userRef = reference();
24711  lockReq.lockType = DictLockReq::SchemaTransLock;
24712  int lockError = dict_lock_trylock(&lockReq);
24713  if (lockError != 0)
24714  {
24715  // remove the trans
24716  releaseSchemaTrans(trans_ptr);
24717  setError(error, lockError, __LINE__);
24718  break;
24719  }
24720 
24721  // begin tx on all participants
24722  trans_ptr.p->m_state = SchemaTrans::TS_STARTING;
24723 
24727  {
24728  trans_ptr.p->m_ref_nodes.clear();
24729  NodeReceiverGroup rg(DBDICT, trans_ptr.p->m_nodes);
24730  {
24731  SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
24732  bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
24733  ndbrequire(ok);
24734  }
24735 
24736  if (ERROR_INSERTED(6140))
24737  {
24738  /*
24739  Simulate slave missing start
24740  */
24741  jam();
24742  Uint32 nodeId = rand() % MAX_NDB_NODES;
24743  while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
24744  nodeId = rand() % MAX_NDB_NODES;
24745 
24746  infoEvent("Simulating node %u missing RT_START", nodeId);
24747  rg.m_nodes.clear(nodeId);
24748  signal->theData[0] = 9999;
24749  signal->theData[1] = ERROR_INSERT_VALUE;
24750  CLEAR_ERROR_INSERT_VALUE;
24751  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
24752  5000, 2);
24753  }
24754 
24755  SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
24756  req->senderRef = reference();
24757  req->transKey = trans_ptr.p->trans_key;
24758  req->opKey = RNIL;
24759  req->requestInfo = SchemaTransImplReq::RT_START;
24760  req->start.clientRef = trans_ptr.p->m_clientRef;
24761  req->start.objectId = trans_ptr.p->m_obj_id;
24762  req->transId = trans_ptr.p->m_transId;
24763  sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
24764  SchemaTransImplReq::SignalLengthStart, JBB);
24765  }
24766 
24767  if (ERROR_INSERTED(6102)) {
24768  jam();
24769  CLEAR_ERROR_INSERT_VALUE;
24770  signal->theData[0] = refToNode(clientRef);
24771  sendSignal(QMGR_REF, GSN_API_FAILREQ, signal, 1, JBB);
24772  }
24773  return;
24774  } while(0);
24775 
24776  SchemaTrans tmp_trans;
24777  trans_ptr.i = RNIL;
24778  trans_ptr.p = &tmp_trans;
24779  trans_ptr.p->trans_key = 0;
24780  trans_ptr.p->m_clientRef = clientRef;
24781  trans_ptr.p->m_transId = transId;
24782  trans_ptr.p->m_clientState = TransClient::BeginReq;
24783  setError(trans_ptr.p->m_error, error);
24784  sendTransClientReply(signal, trans_ptr);
24785 }
24786 
24787 void
24788 Dbdict::trans_start_recv_reply(Signal* signal, SchemaTransPtr trans_ptr)
24789 {
24790  jam();
24791 
24792  switch(trans_ptr.p->m_state){
24793  case SchemaTrans::TS_STARTING:
24794  if (hasError(trans_ptr.p->m_error))
24795  {
24796  jam();
24797 
24801  trans_ptr.p->m_nodes.bitANDC(trans_ptr.p->m_ref_nodes);
24802 
24806  trans_end_start(signal, trans_ptr);
24807  return;
24808  }
24809  else
24810  {
24811  jam();
24812  sendTransClientReply(signal, trans_ptr);
24813  return;
24814  }
24815  break;
24816  default:
24817  jamLine(trans_ptr.p->m_state);
24818  ndbrequire(false);
24819  }
24820 }
24821 
24822 void
24823 Dbdict::execSCHEMA_TRANS_END_REQ(Signal* signal)
24824 {
24825  jamEntry();
24826  const SchemaTransEndReq* req =
24827  (const SchemaTransEndReq*)signal->getDataPtr();
24828  Uint32 clientRef = req->clientRef;
24829  Uint32 transId = req->transId;
24830  Uint32 trans_key = req->transKey;
24831  Uint32 requestInfo = req->requestInfo;
24832  Uint32 flags = req->flags;
24833 
24834  SchemaTransPtr trans_ptr;
24835  ErrorInfo error;
24836  do {
24837  findSchemaTrans(trans_ptr, trans_key);
24838  if (trans_ptr.isNull()) {
24839  jam();
24840  ndbassert(false);
24841  setError(error, SchemaTransEndRef::InvalidTransKey, __LINE__);
24842  break;
24843  }
24844 
24845  if (trans_ptr.p->m_transId != transId) {
24846  jam();
24847  ndbassert(false);
24848  setError(error, SchemaTransEndRef::InvalidTransId, __LINE__);
24849  break;
24850  }
24851 
24852  bool localTrans = (trans_ptr.p->m_requestInfo & DictSignal::RF_LOCAL_TRANS);
24853 
24854  if (getOwnNodeId() != c_masterNodeId && !localTrans) {
24855  jam();
24856  // future when MNF is handled
24857  //ndbassert(false);
24858  setError(error, SchemaTransEndRef::NotMaster, __LINE__);
24859  break;
24860  }
24861 #ifdef MARTIN
24862  ndbout_c("Dbdict::execSCHEMA_TRANS_END_REQ: trans %u, state %u", trans_ptr.i, trans_ptr.p->m_state);
24863 #endif
24864 
24865  //XXX Check state
24866 
24867  if (hasError(trans_ptr.p->m_error))
24868  {
24869  jam();
24870  ndbassert(false);
24871  setError(error, SchemaTransEndRef::InvalidTransState, __LINE__);
24872  break;
24873  }
24874 
24875  bool localTrans2 = requestInfo & DictSignal::RF_LOCAL_TRANS;
24876  if (localTrans != localTrans2)
24877  {
24878  jam();
24879  ndbassert(false);
24880  setError(error, SchemaTransEndRef::InvalidTransState, __LINE__);
24881  break;
24882  }
24883 
24884  trans_ptr.p->m_clientState = TransClient::EndReq;
24885 
24886  const bool doBackground = flags & SchemaTransEndReq::SchemaTransBackground;
24887  if (doBackground)
24888  {
24889  jam();
24890  // send reply to original client and restore EndReq state
24891  sendTransClientReply(signal, trans_ptr);
24892  trans_ptr.p->m_clientState = TransClient::EndReq;
24893 
24894  // take over client role via internal trans
24895  trans_ptr.p->m_clientFlags |= TransClient::Background;
24896  takeOverTransClient(signal, trans_ptr);
24897  }
24898 
24899  if (flags & SchemaTransEndReq::SchemaTransAbort)
24900  {
24901  jam();
24902  trans_abort_prepare_start(signal, trans_ptr);
24903  return;
24904  }
24905  else if ((flags & SchemaTransEndReq::SchemaTransPrepare) == 0)
24906  {
24907  jam();
24908  trans_ptr.p->m_clientFlags |= TransClient::Commit;
24909  }
24910 
24911  trans_prepare_start(signal, trans_ptr);
24912  return;
24913  } while (0);
24914 
24915  SchemaTrans tmp_trans;
24916  trans_ptr.i = RNIL;
24917  trans_ptr.p = &tmp_trans;
24918  trans_ptr.p->trans_key = trans_key;
24919  trans_ptr.p->m_clientRef = clientRef;
24920  trans_ptr.p->m_transId = transId;
24921  trans_ptr.p->m_clientState = TransClient::EndReq;
24922  setError(trans_ptr.p->m_error, error);
24923  sendTransClientReply(signal, trans_ptr);
24924 }
24925 
24926 // coordinator
24927 
24928 void
24929 Dbdict::handleClientReq(Signal* signal, SchemaOpPtr op_ptr,
24930  SectionHandle& handle)
24931 {
24932  D("handleClientReq" << *op_ptr.p);
24933 
24934  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
24935 
24936  if (trans_ptr.p->m_state == SchemaTrans::TS_SUBOP)
24937  {
24938  jam();
24939  SchemaOpPtr baseOp;
24940  c_schemaOpPool.getPtr(baseOp, trans_ptr.p->m_curr_op_ptr_i);
24941  op_ptr.p->m_base_op_ptr_i = baseOp.i;
24942  }
24943 
24944  trans_ptr.p->m_curr_op_ptr_i = op_ptr.i;
24945  op_ptr.p->m_state = SchemaOp::OS_PARSE_MASTER;
24946 
24947  ErrorInfo error;
24948  const OpInfo& info = getOpInfo(op_ptr);
24949 
24950  if (checkSingleUserMode(trans_ptr.p->m_clientRef))
24951  {
24952  jam();
24953  setError(error, AlterTableRef::SingleUser, __LINE__);
24954  }
24955  else
24956  {
24957  jam();
24958  (this->*(info.m_parse))(signal, true, op_ptr, handle, error);
24959  }
24960 
24961  if (hasError(error))
24962  {
24963  jam();
24964  setError(trans_ptr, error);
24965  releaseSections(handle);
24966  trans_rollback_sp_start(signal, trans_ptr);
24967  return;
24968  }
24969 
24970  trans_ptr.p->m_state = SchemaTrans::TS_PARSING;
24971  op_ptr.p->m_state = SchemaOp::OS_PARSING;
24972 
24973  Uint32 gsn = info.m_impl_req_gsn;
24974  const Uint32* src = op_ptr.p->m_oprec_ptr.p->m_impl_req_data;
24975 
24976  Uint32* data = signal->getDataPtrSend();
24977  Uint32 skip = SchemaTransImplReq::SignalLength;
24978  Uint32 extra_length = info.m_impl_req_length;
24979  ndbrequire(skip + extra_length <= 25);
24980 
24981  Uint32 i;
24982  for (i = 0; i < extra_length; i++)
24983  data[skip + i] = src[i];
24984 
24985  Uint32 requestInfo = 0;
24986  DictSignal::setRequestType(requestInfo, SchemaTransImplReq::RT_PARSE);
24987  DictSignal::addRequestFlags(requestInfo, op_ptr.p->m_requestInfo);
24988  DictSignal::addRequestExtra(requestInfo, op_ptr.p->m_requestInfo);
24989 
24990  trans_ptr.p->m_ref_nodes.clear();
24991  trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
24992  NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
24993 
24994  NodeReceiverGroup rg(DBDICT, nodes);
24995  {
24996  SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
24997  bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
24998  ndbrequire(ok);
24999  }
25000 
25001  if (ERROR_INSERTED(6141))
25002  {
25003  /*
25004  Simulate slave missing parsing last (this) op
25005  */
25006  jam();
25007  Uint32 nodeId = rand() % MAX_NDB_NODES;
25008  while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
25009  nodeId = rand() % MAX_NDB_NODES;
25010 
25011  infoEvent("Simulating node %u missing RT_PARSE", nodeId);
25012  rg.m_nodes.clear(nodeId);
25013  signal->theData[0] = 9999;
25014  signal->theData[1] = ERROR_INSERT_VALUE;
25015  CLEAR_ERROR_INSERT_VALUE;
25016  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
25017  5000, 2);
25018  }
25019 
25020  SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
25021  req->senderRef = reference();
25022  req->transKey = trans_ptr.p->trans_key;
25023  req->opKey = op_ptr.p->op_key;
25024  req->requestInfo = requestInfo;
25025  req->transId = trans_ptr.p->m_transId;
25026  req->parse.gsn = gsn;
25027  sendFragmentedSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
25028  SchemaTransImplReq::SignalLength + extra_length, JBB,
25029  &handle);
25030 }
25031 
25032 void
25033 Dbdict::trans_parse_recv_reply(Signal* signal, SchemaTransPtr trans_ptr)
25034 {
25035  SchemaOpPtr op_ptr;
25036  c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
25037 
25038  op_ptr.p->m_state = SchemaOp::OS_PARSED;
25039 
25040  if (hasError(trans_ptr.p->m_error))
25041  {
25042  jam();
25043  trans_rollback_sp_start(signal, trans_ptr);
25044  return;
25045  }
25046 
25047  const OpInfo& info = getOpInfo(op_ptr);
25048  if ((this->*(info.m_subOps))(signal, op_ptr))
25049  {
25050  jam();
25051  // more sub-ops on the way
25052  trans_ptr.p->m_curr_op_ptr_i = op_ptr.i;
25053  trans_ptr.p->m_state = SchemaTrans::TS_SUBOP;
25054  return;
25055  }
25056 
25060  ErrorInfo error;
25061  (this->*(info.m_reply))(signal, op_ptr, error);
25062 
25063  trans_ptr.p->m_clientState = TransClient::ParseReply;
25064  trans_ptr.p->m_state = SchemaTrans::TS_STARTED;
25065 }
25066 
25067 void
25068 Dbdict::execSCHEMA_TRANS_IMPL_CONF(Signal* signal)
25069 {
25070  jamEntry();
25071  ndbrequire(signal->getNoOfSections() == 0);
25072 
25073  const SchemaTransImplConf* conf =
25074  (const SchemaTransImplConf*)signal->getDataPtr();
25075 
25076  SchemaTransPtr trans_ptr;
25077  ndbrequire(findSchemaTrans(trans_ptr, conf->transKey));
25078 
25079  Uint32 senderRef = conf->senderRef;
25080  Uint32 nodeId = refToNode(senderRef);
25081 
25082  {
25083  SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
25084  if (!sc.clearWaitingFor(nodeId)) {
25085  jam();
25086  return;
25087  }
25088  }
25089 
25090  trans_recv_reply(signal, trans_ptr);
25091 }
25092 
25093 void
25094 Dbdict::execSCHEMA_TRANS_IMPL_REF(Signal* signal)
25095 {
25096  jamEntry();
25097  ndbrequire(signal->getNoOfSections() == 0);
25098 
25099  const SchemaTransImplRef* ref =
25100  (const SchemaTransImplRef*)signal->getDataPtr();
25101 
25102  SchemaTransPtr trans_ptr;
25103  ndbrequire(findSchemaTrans(trans_ptr, ref->transKey));
25104 
25105  Uint32 senderRef = ref->senderRef;
25106  Uint32 nodeId = refToNode(senderRef);
25107 
25108 #ifdef MARTIN
25109  ndbout_c("Got SCHEMA_TRANS_IMPL_REF from node %u, error %u", nodeId, ref->errorCode);
25110 #endif
25111  if (ref->errorCode == SchemaTransImplRef::NF_FakeErrorREF)
25112  {
25113  jam();
25114  // trans_ptr.p->m_nodes.clear(nodeId);
25115  // No need to clear, will be cleared when next REQ is set
25116  }
25117  else
25118  {
25119  jam();
25120  ErrorInfo error;
25121  setError(error, ref);
25122  setError(trans_ptr, error);
25123  switch(trans_ptr.p->m_state){
25124  case SchemaTrans::TS_STARTING:
25125  jam();
25126  trans_ptr.p->m_ref_nodes.set(nodeId);
25127  break;
25128  case SchemaTrans::TS_PARSING:
25129  jam();
25130  if (ref->errorCode == SchemaTransImplRef::SeizeFailed)
25131  {
25132  jam();
25133  trans_ptr.p->m_ref_nodes.set(nodeId);
25134  }
25135  break;
25136  default:
25137  jam();
25138  }
25139  }
25140 
25141  {
25142  SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
25143  if (!sc.clearWaitingFor(nodeId)) {
25144  jam();
25145  return;
25146  }
25147  }
25148 
25149  trans_recv_reply(signal, trans_ptr);
25150 }
25151 
25152 void
25153 Dbdict::trans_recv_reply(Signal* signal, SchemaTransPtr trans_ptr)
25154 {
25155  switch(trans_ptr.p->m_state){
25156  case SchemaTrans::TS_INITIAL:
25157  ndbrequire(false);
25158  case SchemaTrans::TS_STARTING:
25159  jam();
25160  trans_start_recv_reply(signal, trans_ptr);
25161  return;
25162  case SchemaTrans::TS_PARSING:
25163  jam();
25164  trans_parse_recv_reply(signal, trans_ptr);
25165  return;
25166  case SchemaTrans::TS_SUBOP:
25167  ndbrequire(false);
25168  case SchemaTrans::TS_ROLLBACK_SP:
25169  trans_rollback_sp_recv_reply(signal, trans_ptr);
25170  return;
25171  case SchemaTrans::TS_FLUSH_PREPARE:
25172  trans_prepare_first(signal, trans_ptr);
25173  return;
25174  case SchemaTrans::TS_PREPARING:
25175  jam();
25176  trans_prepare_recv_reply(signal, trans_ptr);
25177  return;
25178  case SchemaTrans::TS_ABORTING_PREPARE:
25179  jam();
25180  trans_abort_prepare_recv_reply(signal, trans_ptr);
25181  return;
25182  case SchemaTrans::TS_ABORTING_PARSE:
25183  jam();
25184  trans_abort_parse_recv_reply(signal, trans_ptr);
25185  return;
25186  case SchemaTrans::TS_FLUSH_COMMIT:
25187  jam();
25188  trans_commit_first(signal, trans_ptr);
25189  return;
25190  case SchemaTrans::TS_COMMITTING:
25191  trans_commit_recv_reply(signal, trans_ptr);
25192  return;
25193  case SchemaTrans::TS_FLUSH_COMPLETE:
25194  jam();
25195  trans_complete_first(signal, trans_ptr);
25196  return;
25197  case SchemaTrans::TS_COMPLETING:
25198  trans_complete_recv_reply(signal, trans_ptr);
25199  return;
25200  case SchemaTrans::TS_ENDING:
25201  trans_end_recv_reply(signal, trans_ptr);
25202  return;
25203  case SchemaTrans::TS_STARTED: // These states are waiting for client
25204  jam(); // And should not get a "internal" reply
25205  ndbrequire(false);
25206  }
25207 }
25208 
25209 #if 0
25210 void
25211 Dbdict::handleTransReply(Signal* signal, SchemaTransPtr trans_ptr)
25212 {
25213  TransLoc& tLoc = trans_ptr.p->m_transLoc;
25214  SchemaOpPtr op_ptr;
25215  getOpPtr(tLoc, op_ptr);
25216 
25217  //const Uint32 trans_key = trans_ptr.p->trans_key;
25218  //const Uint32 clientRef = trans_ptr.p->m_clientRef;
25219  //const Uint32 transId = trans_ptr.p->m_transId;
25220 
25221  D("handleTransReply" << tLoc);
25222  if (!op_ptr.isNull())
25223  D("have op" << *op_ptr.p);
25224 
25225  if (hasError(trans_ptr.p->m_error)) {
25226  jam();
25227  if (tLoc.m_mode == TransMode::Normal) {
25228  if (tLoc.m_phase == TransPhase::Parse) {
25229  jam();
25230  setTransMode(trans_ptr, TransMode::Rollback, true);
25231  } else {
25232  jam();
25233  setTransMode(trans_ptr, TransMode::Abort, true);
25234  }
25235  }
25236  }
25237 
25238  if (tLoc.m_mode == TransMode::Normal) {
25239  if (tLoc.m_phase == TransPhase::Begin) {
25240  jam();
25241  sendTransClientReply(signal, trans_ptr);
25242  }
25243  else if (tLoc.m_phase == TransPhase::Parse) {
25244  jam();
25245  /*
25246  * Create any sub-operations via client signals. This is
25247  * a recursive process. When done at current level, sends reply
25248  * to client. On inner levels the client is us (dict master).
25249  */
25250  createSubOps(signal, op_ptr, true);
25251  }
25252  else if (tLoc.m_phase == TransPhase::Prepare) {
25253  jam();
25254  runTransMaster(signal, trans_ptr);
25255  }
25256  else if (tLoc.m_phase == TransPhase::Commit) {
25257  jam();
25258  runTransMaster(signal, trans_ptr);
25259  }
25260  else if (tLoc.m_phase == TransPhase::End)
25261  {
25262  jam();
25263  trans_commit_done(signal, trans_ptr);
25264  return;
25265  }
25266  else {
25267  ndbrequire(false);
25268  }
25269  }
25270  else if (tLoc.m_mode == TransMode::Rollback) {
25271  if (tLoc.m_phase == TransPhase::Parse) {
25272  jam();
25273  /*
25274  * Rolling back current client op and its sub-ops.
25275  * We do not follow the signal train of master REQs back.
25276  * Instead we simply run backwards in abort mode until
25277  * (and including) first op of depth zero. All ops involved
25278  * are removed. On master this is done here.
25279  */
25280  ndbrequire(hasError(trans_ptr.p->m_error));
25281  ndbrequire(!op_ptr.isNull());
25282  if (tLoc.m_hold) {
25283  jam();
25284  // error seen first time, re-run current op
25285  runTransMaster(signal, trans_ptr);
25286  }
25287  else {
25288  if (op_ptr.p->m_opDepth != 0) {
25289  jam();
25290  runTransMaster(signal, trans_ptr);
25291  }
25292  else {
25293  jam();
25294  // reached original client op
25295  const OpInfo& info = getOpInfo(op_ptr);
25296  (this->*(info.m_reply))(signal, op_ptr, trans_ptr.p->m_error);
25297  resetError(trans_ptr);
25298 
25299  // restore depth counter
25300  trans_ptr.p->m_opDepth = 0;
25301  trans_ptr.p->m_clientState = TransClient::ParseReply;
25302  }
25303  iteratorRemoveLastOp(tLoc, op_ptr);
25304  }
25305  }
25306  else {
25307  ndbrequire(false);
25308  }
25309  }
25310  else if (tLoc.m_mode == TransMode::Abort) {
25311  if (tLoc.m_phase == TransPhase::Begin) {
25312  jam();
25313  sendTransClientReply(signal, trans_ptr);
25314  // unlock
25315  const DictLockReq& lockReq = trans_ptr.p->m_lockReq;
25316  dict_lock_unlock(signal, &lockReq);
25317  releaseSchemaTrans(trans_ptr);
25318  }
25319  else if (tLoc.m_phase == TransPhase::Parse) {
25320  jam();
25321  runTransMaster(signal, trans_ptr);
25322  }
25323  else if (tLoc.m_phase == TransPhase::Prepare) {
25324  jam();
25325  runTransMaster(signal, trans_ptr);
25326  }
25327  else {
25328  ndbrequire(false);
25329  }
25330  }
25331  else {
25332  ndbrequire(false);
25333  }
25334 }
25335 #endif
25336 
25337 void
25338 Dbdict::createSubOps(Signal* signal, SchemaOpPtr op_ptr, bool first)
25339 {
25340  D("createSubOps" << *op_ptr.p);
25341 
25342  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
25343 
25344  const OpInfo& info = getOpInfo(op_ptr);
25345  if ((this->*(info.m_subOps))(signal, op_ptr)) {
25346  jam();
25347  // more sub-ops on the way
25348  trans_ptr.p->m_curr_op_ptr_i = op_ptr.i;
25349  trans_ptr.p->m_state = SchemaTrans::TS_SUBOP;
25350  return;
25351  }
25352 
25353  ErrorInfo error;
25354  (this->*(info.m_reply))(signal, op_ptr, error);
25355 
25356  trans_ptr.p->m_clientState = TransClient::ParseReply;
25357  trans_ptr.p->m_state = SchemaTrans::TS_STARTED;
25358 }
25359 
25360 // a sub-op create failed, roll back and send REF to client
25361 void
25362 Dbdict::abortSubOps(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
25363 {
25364  D("abortSubOps" << *op_ptr.p << error);
25365  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
25366  setError(trans_ptr, error);
25367  trans_rollback_sp_start(signal, trans_ptr);
25368 }
25369 
25370 void
25371 Dbdict::trans_prepare_start(Signal* signal, SchemaTransPtr trans_ptr)
25372 {
25373  trans_ptr.p->m_state = SchemaTrans::TS_FLUSH_PREPARE;
25374 
25375  trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
25376  NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
25377  NodeReceiverGroup rg(DBDICT, nodes);
25378  {
25379  SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
25380  bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
25381  ndbrequire(ok);
25382  }
25383 
25384  if (ERROR_INSERTED(6013))
25385  {
25386  jam();
25387  CRASH_INSERTION(6013);
25388  }
25389 
25390  if (ERROR_INSERTED(6022))
25391  {
25392  jam();
25393  NodeReceiverGroup rg(CMVMI, c_aliveNodes);
25394  signal->theData[0] = 9999;
25395  sendSignal(rg, GSN_NDB_TAMPER, signal, 1, JBB);
25396  return;
25397  }
25398 
25399  if (ERROR_INSERTED(6142))
25400  {
25401  /*
25402  Simulate slave missing flush prepare
25403  */
25404  jam();
25405  Uint32 nodeId = rand() % MAX_NDB_NODES;
25406  while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
25407  nodeId = rand() % MAX_NDB_NODES;
25408 
25409  infoEvent("Simulating node %u missing RT_FLUSH_PREPARE", nodeId);
25410  rg.m_nodes.clear(nodeId);
25411  signal->theData[0] = 9999;
25412  signal->theData[1] = ERROR_INSERT_VALUE;
25413  CLEAR_ERROR_INSERT_VALUE;
25414  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
25415  5000, 2);
25416  }
25417 
25418  SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
25419  req->senderRef = reference();
25420  req->transKey = trans_ptr.p->trans_key;
25421  req->opKey = RNIL;
25422  req->requestInfo = SchemaTransImplReq::RT_FLUSH_PREPARE;
25423  req->transId = trans_ptr.p->m_transId;
25424  sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
25425  SchemaTransImplReq::SignalLength, JBB);
25426 }
25427 
25428 void
25429 Dbdict::trans_prepare_first(Signal* signal, SchemaTransPtr trans_ptr)
25430 {
25431  if (ERROR_INSERTED(6021))
25432  {
25433  jam();
25434  NodeReceiverGroup rg(CMVMI, c_aliveNodes);
25435  signal->theData[0] = 9999;
25436  sendSignal(rg, GSN_NDB_TAMPER, signal, 1, JBB);
25437  return;
25438  }
25439 
25440  trans_ptr.p->m_state = SchemaTrans::TS_PREPARING;
25441 
25442  SchemaOpPtr op_ptr;
25443  {
25444  bool first;
25445  {
25446  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
25447  first = list.first(op_ptr);
25448  }
25449  if (first)
25450  {
25451  jam();
25452  trans_prepare_next(signal, trans_ptr, op_ptr);
25453  return;
25454  }
25455  }
25456 
25457  trans_prepare_done(signal, trans_ptr);
25458 }
25459 
25460 void
25461 Dbdict::trans_prepare_next(Signal* signal,
25462  SchemaTransPtr trans_ptr,
25463  SchemaOpPtr op_ptr)
25464 {
25465  ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_PREPARING);
25466 
25467  trans_ptr.p->m_curr_op_ptr_i = op_ptr.i;
25468  op_ptr.p->m_state = SchemaOp::OS_PREPARING;
25469 
25470  trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
25471  NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
25472  NodeReceiverGroup rg(DBDICT, nodes);
25473  {
25474  SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
25475  bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
25476  ndbrequire(ok);
25477  }
25478 
25479  if (ERROR_INSERTED(6143))
25480  {
25481  jam();
25482  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
25483  if (!list.hasNext(op_ptr))
25484  {
25485  /*
25486  Simulate slave missing preparing last op
25487  */
25488  jam();
25489  Uint32 nodeId = rand() % MAX_NDB_NODES;
25490  while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
25491  nodeId = rand() % MAX_NDB_NODES;
25492 
25493  infoEvent("Simulating node %u missing RT_PREPARE", nodeId);
25494  rg.m_nodes.clear(nodeId);
25495  signal->theData[0] = 9999;
25496  signal->theData[1] = ERROR_INSERT_VALUE;
25497  CLEAR_ERROR_INSERT_VALUE;
25498  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
25499  5000, 2);
25500  }
25501  }
25502 
25503  SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
25504  req->senderRef = reference();
25505  req->transKey = trans_ptr.p->trans_key;
25506  req->opKey = op_ptr.p->op_key;
25507  req->requestInfo = SchemaTransImplReq::RT_PREPARE;
25508  req->transId = trans_ptr.p->m_transId;
25509  sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
25510  SchemaTransImplReq::SignalLength, JBB);
25511 }
25512 
25513 void
25514 Dbdict::trans_prepare_recv_reply(Signal* signal, SchemaTransPtr trans_ptr)
25515 {
25516  jam();
25517 
25518  SchemaOpPtr op_ptr;
25519  c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
25520  if (hasError(trans_ptr.p->m_error))
25521  {
25522  jam();
25523  trans_ptr.p->m_state = SchemaTrans::TS_ABORTING_PREPARE;
25524  trans_abort_prepare_next(signal, trans_ptr, op_ptr);
25525  return;
25526  }
25527 
25528  {
25529  bool next;
25530  {
25531  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
25532  next = list.next(op_ptr);
25533  }
25534  if (next)
25535  {
25536  jam();
25537  trans_prepare_next(signal, trans_ptr, op_ptr);
25538  return;
25539  }
25540  }
25541 
25542  trans_prepare_done(signal, trans_ptr);
25543  return;
25544 }
25545 
25546 void
25547 Dbdict::trans_prepare_done(Signal* signal, SchemaTransPtr trans_ptr)
25548 {
25549  ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_PREPARING);
25550 
25551  if (ERROR_INSERTED(6145))
25552  {
25553  jam();
25554  trans_abort_prepare_start(signal, trans_ptr);
25555  return;
25556  }
25557 
25558  if (trans_ptr.p->m_clientFlags & TransClient::Commit)
25559  {
25560  jam();
25561  trans_commit_start(signal, trans_ptr);
25562  return;
25563  }
25564 
25565  // prepare not currently implemted (fully)
25566  ndbrequire(false);
25567 }
25568 
25569 void
25570 Dbdict::trans_abort_parse_start(Signal* signal, SchemaTransPtr trans_ptr)
25571 {
25572  trans_ptr.p->m_state = SchemaTrans::TS_ABORTING_PARSE;
25573 
25574  SchemaOpPtr op_ptr;
25575  bool last = false;
25576  {
25577  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
25578  last = list.last(op_ptr);
25579  }
25580 
25581  if (last)
25582  {
25583  jam();
25584  trans_abort_parse_next(signal, trans_ptr, op_ptr);
25585  return;
25586  }
25587 
25588  trans_abort_parse_done(signal, trans_ptr);
25589 
25590 }
25591 
25592 void
25593 Dbdict::trans_abort_parse_recv_reply(Signal* signal, SchemaTransPtr trans_ptr)
25594 {
25595  SchemaOpPtr op_ptr;
25596  c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
25597 
25598  {
25599  SchemaOpPtr last_op = op_ptr;
25600  bool prev = false;
25601  {
25602  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
25603  prev = list.prev(op_ptr);
25604  list.remove(last_op); // Release aborted op
25605  }
25606  releaseSchemaOp(last_op);
25607 
25608  if (prev)
25609  {
25610  jam();
25611  trans_abort_parse_next(signal, trans_ptr, op_ptr);
25612  return;
25613  }
25614  }
25615 
25616  trans_abort_parse_done(signal, trans_ptr);
25617 }
25618 
25619 void
25620 Dbdict::check_partial_trans_abort_parse_next(SchemaTransPtr trans_ptr,
25621  NdbNodeBitmask &nodes,
25622  SchemaOpPtr op_ptr)
25623 {
25624  jam();
25625  NodeRecordPtr ownNodePtr;
25626  c_nodes.getPtr(ownNodePtr, getOwnNodeId());
25627  if (ownNodePtr.p->nodeState == NodeRecord::NDB_MASTER_TAKEOVER)
25628  {
25629  /*
25630  A new master is in the process of aborting a
25631  transaction taken over from the failed master.
25632  Check if any nodes should be skipped because they
25633  have not parsed the operation to be aborted
25634  */
25635  jam();
25636  for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
25637  NodeRecordPtr nodePtr;
25638  if (trans_ptr.p->m_nodes.get(i))
25639  {
25640  jam();
25641  c_nodes.getPtr(nodePtr, i);
25642 #ifdef VM_TRACE
25643  ndbout_c("Checking node %u(%u), %u(%u)<%u", nodePtr.i, nodePtr.p->recoveryState, nodePtr.p->start_op, nodePtr.p->start_op_state, op_ptr.p->op_key);
25644 #endif
25645  if (nodePtr.p->recoveryState == NodeRecord::RS_PARTIAL_ROLLBACK &&
25646  //nodePtr.p->start_op_state == SchemaOp::OS_PARSED &&
25647  nodePtr.p->start_op < op_ptr.p->op_key)
25648  {
25649  jam();
25650 #ifdef VM_TRACE
25651  ndbout_c("Skip aborting operation %u on node %u", op_ptr.p->op_key, i);
25652 #endif
25653  nodes.clear(i);
25654  nodePtr.p->recoveryState = NodeRecord::RS_NORMAL;
25655  }
25656  }
25657  }
25658  }
25659 }
25660 
25661 void
25662 Dbdict::trans_abort_parse_next(Signal* signal,
25663  SchemaTransPtr trans_ptr,
25664  SchemaOpPtr op_ptr)
25665 {
25666  jam();
25667  ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_ABORTING_PARSE);
25668 #ifdef MARTIN
25669  ndbout_c("Dbdict::trans_abort_parse_next: op %u state %u", op_ptr.i,op_ptr.p->m_state);
25670 #endif
25671  trans_ptr.p->m_curr_op_ptr_i = op_ptr.i;
25672  op_ptr.p->m_state = SchemaOp::OS_ABORTING_PARSE;
25673 
25674  trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
25675  NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
25676  check_partial_trans_abort_parse_next(trans_ptr, nodes, op_ptr);
25677  NodeReceiverGroup rg(DBDICT, nodes);
25678  {
25679  SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
25680  bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
25681  ndbrequire(ok);
25682  }
25683 
25684  if (ERROR_INSERTED(6144))
25685  {
25686  jam();
25687  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
25688  if (!list.hasNext(op_ptr))
25689  {
25690  /*
25691  Simulate slave missing aborting parse for last op
25692  */
25693  jam();
25694  Uint32 nodeId = rand() % MAX_NDB_NODES;
25695  while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
25696  nodeId = rand() % MAX_NDB_NODES;
25697 
25698  infoEvent("Simulating node %u missing RT_ABORT_PARSE", nodeId);
25699  rg.m_nodes.clear(nodeId);
25700  signal->theData[0] = 9999;
25701  signal->theData[1] = ERROR_INSERT_VALUE;
25702  CLEAR_ERROR_INSERT_VALUE;
25703  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
25704  5000, 2);
25705  }
25706  }
25707 
25708  SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
25709  req->senderRef = reference();
25710  req->transKey = trans_ptr.p->trans_key;
25711  req->opKey = op_ptr.p->op_key;
25712  req->requestInfo = SchemaTransImplReq::RT_ABORT_PARSE;
25713  req->transId = trans_ptr.p->m_transId;
25714  sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
25715  SchemaTransImplReq::SignalLength, JBB);
25716 }
25717 
25718 void
25719 Dbdict::trans_abort_parse_done(Signal* signal, SchemaTransPtr trans_ptr)
25720 {
25721  ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_ABORTING_PARSE);
25722 
25723  trans_end_start(signal, trans_ptr);
25724 }
25725 
25726 void
25727 Dbdict::trans_abort_prepare_start(Signal* signal, SchemaTransPtr trans_ptr)
25728 {
25729  trans_ptr.p->m_state = SchemaTrans::TS_ABORTING_PREPARE;
25730 
25731  bool last = false;
25732  SchemaOpPtr op_ptr;
25733  {
25734  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
25735  last = list.last(op_ptr);
25736  }
25737 
25738  if (last)
25739  {
25740  jam();
25741  trans_abort_prepare_next(signal, trans_ptr, op_ptr);
25742  }
25743  else
25744  {
25745  jam();
25746  trans_abort_prepare_done(signal, trans_ptr);
25747  }
25748 }
25749 
25750 void
25751 Dbdict::trans_abort_prepare_recv_reply(Signal* signal, SchemaTransPtr trans_ptr)
25752 {
25753  // XXX error states
25754 
25755  SchemaOpPtr op_ptr;
25756  c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
25757 
25758  op_ptr.p->m_state = SchemaOp::OS_ABORTED_PREPARE;
25759 
25760  bool prev = false;
25761  {
25762  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
25763  prev = list.prev(op_ptr);
25764  }
25765 
25766  if (prev)
25767  {
25768  jam();
25769  trans_abort_prepare_next(signal, trans_ptr, op_ptr);
25770  }
25771  else
25772  {
25773  jam();
25774  trans_abort_prepare_done(signal, trans_ptr);
25775  }
25776 }
25777 
25778 void
25779 Dbdict::check_partial_trans_abort_prepare_next(SchemaTransPtr trans_ptr,
25780  NdbNodeBitmask &nodes,
25781  SchemaOpPtr op_ptr)
25782 {
25783  jam();
25784  NodeRecordPtr ownNodePtr;
25785  c_nodes.getPtr(ownNodePtr, getOwnNodeId());
25786  if (ownNodePtr.p->nodeState == NodeRecord::NDB_MASTER_TAKEOVER)
25787  {
25788  /*
25789  A new master is in the process of aborting a
25790  transaction taken over from the failed master.
25791  Check if any nodes should be skipped because they
25792  have already aborted the operation.
25793  */
25794  for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
25795  NodeRecordPtr nodePtr;
25796  if (trans_ptr.p->m_nodes.get(i))
25797  {
25798  c_nodes.getPtr(nodePtr, i);
25799 #ifdef VM_TRACE
25800  ndbout_c("Checking node %u(%u), %u(%u)<%u", nodePtr.i, nodePtr.p->recoveryState, nodePtr.p->start_op, nodePtr.p->start_op_state, op_ptr.p->op_key);
25801 #endif
25802  if (nodePtr.p->recoveryState == NodeRecord::RS_PARTIAL_ROLLBACK &&
25803  ((nodePtr.p->start_op_state == SchemaOp::OS_PARSED &&
25804  nodePtr.p->start_op <= op_ptr.p->op_key) ||
25805  (nodePtr.p->start_op_state == SchemaOp::OS_PREPARED &&
25806  nodePtr.p->start_op < op_ptr.p->op_key) ||
25807  (nodePtr.p->start_op_state == SchemaOp::OS_ABORTED_PREPARE &&
25808  nodePtr.p->start_op >= op_ptr.p->op_key)))
25809  {
25810 #ifdef VM_TRACE
25811  ndbout_c("Skip aborting operation %u on node %u", op_ptr.p->op_key, i);
25812 #endif
25813  nodes.clear(i);
25814  nodePtr.p->recoveryState = NodeRecord::RS_NORMAL;
25815  }
25816  }
25817  }
25818  }
25819 }
25820 
25821 void
25822 Dbdict::trans_abort_prepare_next(Signal* signal,
25823  SchemaTransPtr trans_ptr,
25824  SchemaOpPtr op_ptr)
25825 {
25826  jam();
25827  ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_ABORTING_PREPARE);
25828 #ifdef MARTIN
25829  ndbout_c("Dbdict::trans_abort_prepare_next: op %u state %u", op_ptr.p->op_key, op_ptr.p->m_state);
25830 #endif
25831  trans_ptr.p->m_curr_op_ptr_i = op_ptr.i;
25832 
25833  switch(op_ptr.p->m_state){
25834  case SchemaOp::OS_PARSED:
25835  jam();
25840  trans_abort_prepare_recv_reply(signal, trans_ptr);
25841  return;
25842  case SchemaOp::OS_PREPARING:
25843  case SchemaOp::OS_PREPARED:
25844  break;
25845  case SchemaOp::OS_INITIAL:
25846  case SchemaOp::OS_PARSE_MASTER:
25847  case SchemaOp::OS_PARSING:
25848  case SchemaOp::OS_ABORTING_PREPARE:
25849  case SchemaOp::OS_ABORTED_PREPARE:
25850  case SchemaOp::OS_ABORTING_PARSE:
25851  //case SchemaOp::OS_ABORTED_PARSE:
25852  case SchemaOp::OS_COMMITTING:
25853  case SchemaOp::OS_COMMITTED:
25854 #ifndef VM_TRACE
25855  default:
25856 #endif
25857  jamLine(op_ptr.p->m_state);
25858  ndbrequire(false);
25859  }
25860 
25861  op_ptr.p->m_state = SchemaOp::OS_ABORTING_PREPARE;
25862 
25863  trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
25864  NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
25865  check_partial_trans_abort_prepare_next(trans_ptr, nodes, op_ptr);
25866  NodeReceiverGroup rg(DBDICT, nodes);
25867  {
25868  SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
25869  bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
25870  ndbrequire(ok);
25871  }
25872 
25873  if (ERROR_INSERTED(6145))
25874  {
25875  jam();
25876  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
25877  if (!list.hasPrev(op_ptr))
25878  {
25879  /*
25880  Simulate slave missing aborting prepare of last op
25881  */
25882  jam();
25883  Uint32 nodeId = rand() % MAX_NDB_NODES;
25884  while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
25885  nodeId = rand() % MAX_NDB_NODES;
25886 
25887  infoEvent("Simulating node %u missing RT_ABORT_PREPARE", nodeId);
25888  rg.m_nodes.clear(nodeId);
25889  signal->theData[0] = 9999;
25890  signal->theData[1] = ERROR_INSERT_VALUE;
25891  CLEAR_ERROR_INSERT_VALUE;
25892  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
25893  5000, 2);
25894  }
25895  }
25896 
25897  SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
25898  req->senderRef = reference();
25899  req->transKey = trans_ptr.p->trans_key;
25900  req->opKey = op_ptr.p->op_key;
25901  req->requestInfo = SchemaTransImplReq::RT_ABORT_PREPARE;
25902  req->transId = trans_ptr.p->m_transId;
25903  sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
25904  SchemaTransImplReq::SignalLength, JBB);
25905 }
25906 
25907 void
25908 Dbdict::trans_abort_prepare_done(Signal* signal, SchemaTransPtr trans_ptr)
25909 {
25910  jam();
25911  ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_ABORTING_PREPARE);
25912 #ifdef MARTIN
25913  ndbout_c("Dbdict::trans_abort_prepare_done");
25914 #endif
25915 
25918  trans_abort_parse_start(signal, trans_ptr);
25919 }
25920 
25925 void
25926 Dbdict::trans_rollback_sp_start(Signal* signal, SchemaTransPtr trans_ptr)
25927 {
25928  SchemaOpPtr op_ptr;
25929 
25930  {
25931  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
25932  ndbrequire(list.last(op_ptr));
25933  }
25934 
25935  trans_ptr.p->m_state = SchemaTrans::TS_ROLLBACK_SP;
25936 
25937  if (op_ptr.p->m_state == SchemaOp::OS_PARSE_MASTER)
25938  {
25939  jam();
25944  NdbNodeBitmask nodes;
25945  nodes.set(getOwnNodeId());
25946  NodeReceiverGroup rg(DBDICT, nodes);
25947  SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
25948  bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
25949  ndbrequire(ok);
25950 
25951  const OpInfo& info = getOpInfo(op_ptr);
25952  (this->*(info.m_abortParse))(signal, op_ptr);
25953  trans_log_schema_op_abort(op_ptr);
25954  return;
25955  }
25956 
25957  trans_rollback_sp_next(signal, trans_ptr, op_ptr);
25958 }
25959 
25960 void
25961 Dbdict::trans_rollback_sp_recv_reply(Signal* signal, SchemaTransPtr trans_ptr)
25962 {
25963  // TODO split trans error from op_error...?
25964 
25965  SchemaOpPtr op_ptr;
25966  c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
25967 
25968  if (op_ptr.p->m_base_op_ptr_i == RNIL)
25969  {
25973  trans_rollback_sp_done(signal, trans_ptr, op_ptr);
25974  return;
25975  }
25976 
25977  {
25978  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
25979 
25980  SchemaOpPtr last_op = op_ptr;
25981  ndbrequire(list.prev(op_ptr)); // Must have prev, as not SP
25982  list.remove(last_op); // Release aborted op
25983  releaseSchemaOp(last_op);
25984  }
25985 
25986  trans_rollback_sp_next(signal, trans_ptr, op_ptr);
25987 }
25988 
25989 void
25990 Dbdict::trans_rollback_sp_next(Signal* signal,
25991  SchemaTransPtr trans_ptr,
25992  SchemaOpPtr op_ptr)
25993 {
25994  trans_ptr.p->m_curr_op_ptr_i = op_ptr.i;
25995 
25996  trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
25997  NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
25998  nodes.bitANDC(trans_ptr.p->m_ref_nodes);
25999  trans_ptr.p->m_ref_nodes.clear();
26000  NodeReceiverGroup rg(DBDICT, nodes);
26001  {
26002  SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
26003  bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
26004  ndbrequire(ok);
26005  }
26006 
26007  if (ERROR_INSERTED(6144))
26008  {
26009  jam();
26010  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
26011  if (!list.hasPrev(op_ptr))
26012  {
26013  /*
26014  Simulate slave missing aborting parsing of last op
26015  */
26016  jam();
26017  Uint32 nodeId = rand() % MAX_NDB_NODES;
26018  while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
26019  nodeId = rand() % MAX_NDB_NODES;
26020 
26021  infoEvent("Simulating node %u missing RT_ABORT_PARSE", nodeId);
26022  rg.m_nodes.clear(nodeId);
26023  signal->theData[0] = 9999;
26024  signal->theData[1] = ERROR_INSERT_VALUE;
26025  CLEAR_ERROR_INSERT_VALUE;
26026  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
26027  5000, 2);
26028  }
26029  }
26030 
26031  SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
26032  req->senderRef = reference();
26033  req->transKey = trans_ptr.p->trans_key;
26034  req->opKey = op_ptr.p->op_key;
26035  req->requestInfo = SchemaTransImplReq::RT_ABORT_PARSE;
26036  req->transId = trans_ptr.p->m_transId;
26037  sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
26038  SchemaTransImplReq::SignalLength, JBB);
26039 
26040 }
26041 
26042 void
26043 Dbdict::trans_rollback_sp_done(Signal* signal,
26044  SchemaTransPtr trans_ptr,
26045  SchemaOpPtr op_ptr)
26046 {
26047 
26048  ErrorInfo error = trans_ptr.p->m_error;
26049  const OpInfo info = getOpInfo(op_ptr);
26050  (this->*(info.m_reply))(signal, op_ptr, error);
26051 
26052  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
26053  list.remove(op_ptr);
26054  releaseSchemaOp(op_ptr);
26055 
26056  resetError(trans_ptr);
26057  trans_ptr.p->m_clientState = TransClient::ParseReply;
26058  trans_ptr.p->m_state = SchemaTrans::TS_STARTED;
26059 }
26060 
26061 void Dbdict::check_partial_trans_commit_start(SchemaTransPtr trans_ptr,
26062  NdbNodeBitmask &nodes)
26063 {
26064  jam();
26065  NodeRecordPtr ownNodePtr;
26066  c_nodes.getPtr(ownNodePtr, getOwnNodeId());
26067  if (ownNodePtr.p->nodeState == NodeRecord::NDB_MASTER_TAKEOVER)
26068  {
26069  /*
26070  A new master is in the process of commiting a
26071  transaction taken over from the failed master.
26072  Check if some slave have already flushed the commit.
26073  */
26074  jam();
26075  for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
26076  NodeRecordPtr nodePtr;
26077  if (trans_ptr.p->m_nodes.get(i))
26078  {
26079  jam();
26080  c_nodes.getPtr(nodePtr, i);
26081  if (nodePtr.p->recoveryState == NodeRecord::RS_PARTIAL_ROLLFORWARD)
26082  {
26083  jam();
26084 #ifdef VM_TRACE
26085  ndbout_c("Skip flushing commit on node %u", i);
26086 #endif
26087  nodes.clear(i);
26088  nodePtr.p->recoveryState = NodeRecord::RS_NORMAL;
26089  }
26090  }
26091  }
26092  }
26093 }
26094 
26095 void
26096 Dbdict::trans_commit_start(Signal* signal, SchemaTransPtr trans_ptr)
26097 {
26098  if (ERROR_INSERTED(6016) || ERROR_INSERTED(6017))
26099  {
26100  jam();
26101  signal->theData[0] = 9999;
26102  NdbNodeBitmask mask = c_aliveNodes;
26103  if (c_masterNodeId == getOwnNodeId())
26104  {
26105  jam();
26106  mask.clear(getOwnNodeId());
26107  sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 1000, 1);
26108  if (mask.isclear())
26109  {
26110  return;
26111  }
26112  }
26113  NodeReceiverGroup rg(CMVMI, mask);
26114  sendSignal(rg, GSN_NDB_TAMPER, signal, 1, JBB);
26115  return;
26116  }
26117 
26118  trans_ptr.p->m_state = SchemaTrans::TS_FLUSH_COMMIT;
26119 
26120  trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
26121  NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
26122  check_partial_trans_commit_start(trans_ptr, nodes);
26123  NodeReceiverGroup rg(DBDICT, nodes);
26124  {
26125  SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
26126  bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
26127  ndbrequire(ok);
26128  }
26129 
26130  if (ERROR_INSERTED(6146))
26131  {
26132  jam();
26133  /*
26134  Simulate slave missing flushing commit
26135  */
26136  jam();
26137  Uint32 nodeId = rand() % MAX_NDB_NODES;
26138  while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
26139  nodeId = rand() % MAX_NDB_NODES;
26140 
26141  infoEvent("Simulating node %u missing RT_FLUSH_COMMIT", nodeId);
26142  rg.m_nodes.clear(nodeId);
26143  signal->theData[0] = 9999;
26144  signal->theData[1] = ERROR_INSERT_VALUE;
26145  CLEAR_ERROR_INSERT_VALUE;
26146  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
26147  5000, 2);
26148  }
26149 
26150  SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
26151  req->senderRef = reference();
26152  req->transKey = trans_ptr.p->trans_key;
26153  req->opKey = RNIL;
26154  req->requestInfo = SchemaTransImplReq::RT_FLUSH_COMMIT;
26155  req->transId = trans_ptr.p->m_transId;
26156  sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
26157  SchemaTransImplReq::SignalLength, JBB);
26158 }
26159 
26160 void
26161 Dbdict::trans_commit_first(Signal* signal, SchemaTransPtr trans_ptr)
26162 {
26163  jam();
26164 
26165  if (ERROR_INSERTED(6018))
26166  {
26167  jam();
26168  NodeReceiverGroup rg(CMVMI, c_aliveNodes);
26169  signal->theData[0] = 9999;
26170  sendSignal(rg, GSN_NDB_TAMPER, signal, 1, JBB);
26171  return;
26172  }
26173 
26174 #ifdef MARTIN
26175  ndbout_c("trans_commit");
26176 #endif
26177 
26178  trans_ptr.p->m_state = SchemaTrans::TS_COMMITTING;
26179 
26180  NodeRecordPtr ownNodePtr;
26181  c_nodes.getPtr(ownNodePtr, getOwnNodeId());
26182  if (ownNodePtr.p->nodeState == NodeRecord::NDB_MASTER_TAKEOVER &&
26183  ownNodePtr.p->takeOverConf.trans_state >= SchemaTrans::TS_COMMITTING)
26184  {
26185  /*
26186  Master take-over, new master already has lock.
26187  */
26188  jam();
26189  trans_commit_mutex_locked(signal, trans_ptr.i, 0);
26190  }
26191  else if (trans_ptr.p->m_wait_gcp_on_commit)
26192  {
26193  jam();
26194 
26195  signal->theData[0] = 0; // user ptr
26196  signal->theData[1] = 0; // Execute direct
26197  signal->theData[2] = 1; // Current
26198  EXECUTE_DIRECT(DBDIH, GSN_GETGCIREQ, signal, 3);
26199 
26200  jamEntry();
26201  Uint32 gci_hi = signal->theData[1];
26202  Uint32 gci_lo = signal->theData[2];
26203 
26204  signal->theData[0] = ZCOMMIT_WAIT_GCI;
26205  signal->theData[1] = trans_ptr.i;
26206  signal->theData[2] = gci_hi;
26207  signal->theData[3] = gci_lo;
26208  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 20, 4);
26209 
26210  signal->theData[0] = 6099;
26211  sendSignal(DBDIH_REF, GSN_DUMP_STATE_ORD, signal, 1, JBB);
26212  }
26213  else
26214  {
26215  jam();
26216  Mutex mutex(signal, c_mutexMgr, trans_ptr.p->m_commit_mutex);
26217  Callback c = { safe_cast(&Dbdict::trans_commit_mutex_locked), trans_ptr.i };
26218 
26219  // Todo should alloc mutex on SCHEMA_BEGIN
26220  bool ok = mutex.lock(c);
26221  ndbrequire(ok);
26222  }
26223 }
26224 
26225 void
26226 Dbdict::trans_commit_wait_gci(Signal* signal)
26227 {
26228  jam();
26229  SchemaTransPtr trans_ptr;
26230  c_schemaTransPool.getPtr(trans_ptr, signal->theData[1]);
26231 
26232  ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_COMMITTING);
26233 
26234  Uint32 gci_hi = signal->theData[2];
26235  Uint32 gci_lo = signal->theData[3];
26236 
26237  signal->theData[0] = 0; // user ptr
26238  signal->theData[1] = 0; // Execute direct
26239  signal->theData[2] = 1; // Current
26240  EXECUTE_DIRECT(DBDIH, GSN_GETGCIREQ, signal, 3);
26241 
26242  jamEntry();
26243  Uint32 curr_gci_hi = signal->theData[1];
26244  Uint32 curr_gci_lo = signal->theData[2];
26245 
26246  if (!getNodeState().getStarted())
26247  {
26248  jam();
26252  }
26253  else if (curr_gci_hi == gci_hi && curr_gci_lo == gci_lo)
26254  {
26255  jam();
26256  signal->theData[0] = ZCOMMIT_WAIT_GCI;
26257  signal->theData[1] = trans_ptr.i;
26258  signal->theData[2] = gci_hi;
26259  signal->theData[3] = gci_lo;
26260  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 20, 4);
26261  return;
26262  }
26263 
26264  Mutex mutex(signal, c_mutexMgr, trans_ptr.p->m_commit_mutex);
26265  Callback c = { safe_cast(&Dbdict::trans_commit_mutex_locked), trans_ptr.i };
26266 
26267  // Todo should alloc mutex on SCHEMA_BEGIN
26268  bool ok = mutex.lock(c);
26269  ndbrequire(ok);
26270 }
26271 
26272 void
26273 Dbdict::trans_commit_mutex_locked(Signal* signal,
26274  Uint32 transPtrI,
26275  Uint32 ret)
26276 {
26277  jamEntry();
26278 #ifdef MARTIN
26279  ndbout_c("trans_commit_mutex_locked");
26280 #endif
26281  SchemaTransPtr trans_ptr;
26282  c_schemaTransPool.getPtr(trans_ptr, transPtrI);
26283 
26284  ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_COMMITTING);
26285 
26286  bool first = false;
26287  SchemaOpPtr op_ptr;
26288  {
26289  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
26290  first = list.first(op_ptr);
26291  }
26292 
26293  if (first)
26294  {
26295  jam();
26296  trans_commit_next(signal, trans_ptr, op_ptr);
26297  if (ERROR_INSERTED(6014)) {
26298  jam();
26299  CRASH_INSERTION(6014);
26300  }
26301  }
26302  else
26303  {
26304  jam();
26305  trans_commit_done(signal, trans_ptr);
26306  if (ERROR_INSERTED(6015)) {
26307  jam();
26308  CRASH_INSERTION(6015);
26309  }
26310  }
26311 }
26312 
26313 void Dbdict::check_partial_trans_commit_next(SchemaTransPtr trans_ptr,
26314  NdbNodeBitmask &nodes,
26315  SchemaOpPtr op_ptr)
26316 {
26317  jam();
26318  NodeRecordPtr ownNodePtr;
26319  c_nodes.getPtr(ownNodePtr, getOwnNodeId());
26320  if (ownNodePtr.p->nodeState == NodeRecord::NDB_MASTER_TAKEOVER &&
26321  trans_ptr.p->check_partial_rollforward)
26322  {
26323  /*
26324  A new master is in the process of committing a
26325  transaction taken over from the failed master.
26326  Check if any nodes should be skipped because they
26327  have already commited the operation
26328  */
26329  for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
26330  NodeRecordPtr nodePtr;
26331 #ifdef VM_TRACE
26332  ndbout_c("Node %u", i);
26333 #endif
26334  if (trans_ptr.p->m_nodes.get(i))
26335  {
26336  c_nodes.getPtr(nodePtr, i);
26337 #ifdef VM_TRACE
26338  ndbout_c("Checking node %u(%u), %u<%u", nodePtr.i, nodePtr.p->recoveryState, nodePtr.p->start_op, op_ptr.p->op_key);
26339 #endif
26340  if (nodePtr.p->recoveryState == NodeRecord::RS_PARTIAL_ROLLFORWARD &&
26341  (nodePtr.p->start_op > op_ptr.p->op_key ||
26342  nodePtr.p->start_op_state > op_ptr.p->m_state))
26343  {
26344 #ifdef VM_TRACE
26345  ndbout_c("Skipping commit of operation %u on node %u", op_ptr.p->op_key, i);
26346 #endif
26347  nodes.clear(i);
26348  nodePtr.p->recoveryState = NodeRecord::RS_NORMAL;
26349  }
26350  }
26351  }
26352  trans_ptr.p->check_partial_rollforward = false;
26353  }
26354 
26355 }
26356 void
26357 Dbdict::trans_commit_next(Signal* signal,
26358  SchemaTransPtr trans_ptr,
26359  SchemaOpPtr op_ptr)
26360 {
26361  jam();
26362 #ifdef MARTIN
26363  ndbout_c("Dbdict::trans_commit_next: op %u state %u", op_ptr.i,op_ptr.p->m_state);
26364 #endif
26365  op_ptr.p->m_state = SchemaOp::OS_COMMITTING;
26366  trans_ptr.p->m_curr_op_ptr_i = op_ptr.i;
26367 
26368  trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
26369  NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
26370  check_partial_trans_commit_next(trans_ptr, nodes, op_ptr);
26371  NodeReceiverGroup rg(DBDICT, nodes);
26372  {
26373  SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
26374  bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
26375  ndbrequire(ok);
26376  }
26377 
26378  if (ERROR_INSERTED(6147))
26379  {
26380  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
26381  if (!list.hasNext(op_ptr))
26382  {
26383  jam();
26384  /*
26385  Simulate slave missing committing last op
26386  */
26387  jam();
26388  Uint32 nodeId = rand() % MAX_NDB_NODES;
26389  while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
26390  nodeId = rand() % MAX_NDB_NODES;
26391 
26392  infoEvent("Simulating node %u missing RT_COMMIT", nodeId);
26393  rg.m_nodes.clear(nodeId);
26394  signal->theData[0] = 9999;
26395  signal->theData[1] = ERROR_INSERT_VALUE;
26396  CLEAR_ERROR_INSERT_VALUE;
26397  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
26398  5000, 2);
26399  }
26400  }
26401 
26402  SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
26403  req->senderRef = reference();
26404  req->transKey = trans_ptr.p->trans_key;
26405  req->opKey = op_ptr.p->op_key;
26406  req->requestInfo = SchemaTransImplReq::RT_COMMIT;
26407  req->transId = trans_ptr.p->m_transId;
26408 
26409  if (rg.m_nodes.get(getOwnNodeId()))
26410  {
26411  /*
26412  To ensure that slave participants register the commit
26413  first we mask out the master node and send commit signal
26414  to master last. This is necessary to handle master node
26415  failure where one of the slaves take over and need to know
26416  that transaction is to be committed.
26417  */
26418  rg.m_nodes.clear(getOwnNodeId());
26419 
26420  sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
26421  SchemaTransImplReq::SignalLength, JBB);
26422  sendSignal(reference(), GSN_SCHEMA_TRANS_IMPL_REQ, signal,
26423  SchemaTransImplReq::SignalLength, JBB);
26424  }
26425  else
26426  {
26427  /*
26428  New master had already committed operation
26429  */
26430  sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
26431  SchemaTransImplReq::SignalLength, JBB);
26432  }
26433 }
26434 
26435 void
26436 Dbdict::trans_commit_recv_reply(Signal* signal, SchemaTransPtr trans_ptr)
26437 {
26438  if (hasError(trans_ptr.p->m_error))
26439  {
26440  jam();
26441  // kill nodes that failed COMMIT
26442  ndbrequire(false);
26443  return;
26444  }
26445 
26446  SchemaOpPtr op_ptr;
26447  c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
26448 
26449  bool next = false;
26450  {
26451  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
26452  next = list.next(op_ptr);
26453  }
26454 
26455  if (next)
26456  {
26457  jam();
26458  trans_commit_next(signal, trans_ptr, op_ptr);
26459  if (ERROR_INSERTED(6014)) {
26460  jam();
26461  CRASH_INSERTION(6014);
26462  }
26463  return;
26464  }
26465  else
26466  {
26467  jam();
26468  trans_commit_done(signal, trans_ptr);
26469  if (ERROR_INSERTED(6015)) {
26470  jam();
26471  CRASH_INSERTION(6015);
26472  }
26473  }
26474  return;
26475 }
26476 
26477 void
26478 Dbdict::trans_commit_done(Signal* signal, SchemaTransPtr trans_ptr)
26479 {
26480 #ifdef MARTIN
26481  ndbout_c("trans_commit_done");
26482 #endif
26483 
26484  Mutex mutex(signal, c_mutexMgr, trans_ptr.p->m_commit_mutex);
26485  Callback c = { safe_cast(&Dbdict::trans_commit_mutex_unlocked), trans_ptr.i };
26486  mutex.unlock(c);
26487 }
26488 
26489 void
26490 Dbdict::trans_commit_mutex_unlocked(Signal* signal,
26491  Uint32 transPtrI,
26492  Uint32 ret)
26493 {
26494  jamEntry();
26495 #ifdef MARTIN
26496  ndbout_c("trans_commit_mutex_unlocked");
26497 #endif
26498  SchemaTransPtr trans_ptr;
26499  c_schemaTransPool.getPtr(trans_ptr, transPtrI);
26500 
26501  trans_ptr.p->m_commit_mutex.release(c_mutexMgr);
26502 
26508  trans_complete_start(signal, trans_ptr);
26509 }
26510 
26511 void
26512 Dbdict::check_partial_trans_complete_start(SchemaTransPtr trans_ptr,
26513  NdbNodeBitmask &nodes)
26514 {
26515  jam();
26516  NodeRecordPtr ownNodePtr;
26517  c_nodes.getPtr(ownNodePtr, getOwnNodeId());
26518  if (ownNodePtr.p->nodeState == NodeRecord::NDB_MASTER_TAKEOVER)
26519  {
26520  /*
26521  A new master is in the process of committing a
26522  transaction taken over from the failed master.
26523  Check if any nodes should be skipped because they
26524  have already completed the operation
26525  */
26526  for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
26527  NodeRecordPtr nodePtr;
26528 #ifdef VM_TRACE
26529  ndbout_c("Node %u", i);
26530 #endif
26531  if (trans_ptr.p->m_nodes.get(i))
26532  {
26533  c_nodes.getPtr(nodePtr, i);
26534 #ifdef VM_TRACE
26535  ndbout_c("Checking node %u(%u,%u)", nodePtr.i, nodePtr.p->recoveryState, nodePtr.p->takeOverConf.trans_state);
26536 #endif
26537  if (nodePtr.p->takeOverConf.trans_state >= SchemaTrans::TS_FLUSH_COMPLETE)
26538  {
26539 #ifdef VM_TRACE
26540  ndbout_c("Skipping TS_FLUSH_COMPLETE of node %u", i);
26541 #endif
26542  nodes.clear(i);
26543  }
26544  }
26545  }
26546  }
26547 }
26548 
26549 void
26550 Dbdict::trans_complete_start(Signal* signal, SchemaTransPtr trans_ptr)
26551 {
26552  jam();
26553 
26554  if (ERROR_INSERTED(6019))
26555  {
26556  jam();
26557  NodeReceiverGroup rg(CMVMI, c_aliveNodes);
26558  signal->theData[0] = 9999;
26559  sendSignal(rg, GSN_NDB_TAMPER, signal, 1, JBB);
26560  return;
26561  }
26562 
26563 #ifdef MARTIN
26564  ndbout_c("trans_complete_start %u", trans_ptr.p->trans_key);
26565 #endif
26566  trans_ptr.p->m_state = SchemaTrans::TS_FLUSH_COMPLETE;
26567 
26568  trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
26569  NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
26570  check_partial_trans_complete_start(trans_ptr, nodes);
26571  NodeReceiverGroup rg(DBDICT, nodes);
26572  {
26573  SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
26574  bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
26575  ndbrequire(ok);
26576  }
26577 
26578  if (ERROR_INSERTED(6148))
26579  {
26580  jam();
26581  /*
26582  Simulate slave missing flushing complete last op
26583  */
26584  jam();
26585  Uint32 nodeId = rand() % MAX_NDB_NODES;
26586  while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
26587  nodeId = rand() % MAX_NDB_NODES;
26588 
26589  infoEvent("Simulating node %u missing RT_FLUSH_COMPLETE", nodeId);
26590  rg.m_nodes.clear(nodeId);
26591  signal->theData[0] = 9999;
26592  signal->theData[1] = ERROR_INSERT_VALUE;
26593  CLEAR_ERROR_INSERT_VALUE;
26594  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
26595  5000, 2);
26596  }
26597 
26598  SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
26599  req->senderRef = reference();
26600  req->transKey = trans_ptr.p->trans_key;
26601  req->opKey = RNIL;
26602  req->requestInfo = SchemaTransImplReq::RT_FLUSH_COMPLETE;
26603  req->transId = trans_ptr.p->m_transId;
26604  sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
26605  SchemaTransImplReq::SignalLength, JBB);
26606 }
26607 
26608 void
26609 Dbdict::trans_complete_first(Signal * signal, SchemaTransPtr trans_ptr)
26610 {
26611  jam();
26612 
26613  if (ERROR_INSERTED(6020))
26614  {
26615  jam();
26616  NodeReceiverGroup rg(CMVMI, c_aliveNodes);
26617  signal->theData[0] = 9999;
26618  sendSignal(rg, GSN_NDB_TAMPER, signal, 1, JBB);
26619  return;
26620  }
26621 
26622  trans_ptr.p->m_state = SchemaTrans::TS_COMPLETING;
26623 
26624  bool first = false;
26625  SchemaOpPtr op_ptr;
26626  {
26627  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
26628  first = list.first(op_ptr);
26629  }
26630 
26631  if (first)
26632  {
26633  jam();
26634  trans_complete_next(signal, trans_ptr, op_ptr);
26635  }
26636  else
26637  {
26638  jam();
26639  trans_complete_done(signal, trans_ptr);
26640  }
26641 }
26642 
26643 void
26644 Dbdict::trans_complete_next(Signal* signal,
26645  SchemaTransPtr trans_ptr, SchemaOpPtr op_ptr)
26646 {
26647  op_ptr.p->m_state = SchemaOp::OS_COMPLETING;
26648  trans_ptr.p->m_curr_op_ptr_i = op_ptr.i;
26649 
26650  trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
26651  NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
26652  NodeReceiverGroup rg(DBDICT, nodes);
26653  {
26654  SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
26655  bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
26656  ndbrequire(ok);
26657  }
26658 
26659  if (ERROR_INSERTED(6149))
26660  {
26661  jam();
26662  /*
26663  Simulate slave missing completing last op
26664  */
26665  jam();
26666  Uint32 nodeId = rand() % MAX_NDB_NODES;
26667  while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
26668  nodeId = rand() % MAX_NDB_NODES;
26669 
26670  infoEvent("Simulating node %u missing RT_COMPLETE", nodeId);
26671  rg.m_nodes.clear(nodeId);
26672  signal->theData[0] = 9999;
26673  signal->theData[1] = ERROR_INSERT_VALUE;
26674  CLEAR_ERROR_INSERT_VALUE;
26675  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
26676  5000, 2);
26677  }
26678 
26679  SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
26680  req->senderRef = reference();
26681  req->transKey = trans_ptr.p->trans_key;
26682  req->opKey = op_ptr.p->op_key;
26683  req->requestInfo = SchemaTransImplReq::RT_COMPLETE;
26684  req->transId = trans_ptr.p->m_transId;
26685  sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
26686  SchemaTransImplReq::SignalLength, JBB);
26687 }
26688 
26689 void
26690 Dbdict::trans_complete_recv_reply(Signal* signal, SchemaTransPtr trans_ptr)
26691 {
26692  if (hasError(trans_ptr.p->m_error))
26693  {
26694  jam();
26695  // kill nodes that failed COMMIT
26696  ndbrequire(false);
26697  return;
26698  }
26699 
26700  SchemaOpPtr op_ptr;
26701  c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
26702 
26703  bool next = false;
26704  {
26705  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
26706  next = list.next(op_ptr);
26707  }
26708 
26709  if (next)
26710  {
26711  jam();
26712  trans_complete_next(signal, trans_ptr, op_ptr);
26713  return;
26714  }
26715  else
26716  {
26717  jam();
26718  trans_complete_done(signal, trans_ptr);
26719  }
26720  return;
26721 }
26722 
26723 void
26724 Dbdict::trans_complete_done(Signal* signal, SchemaTransPtr trans_ptr)
26725 {
26726  jam();
26727  trans_end_start(signal, trans_ptr);
26728 }
26729 
26730 void
26731 Dbdict::trans_end_start(Signal* signal, SchemaTransPtr trans_ptr)
26732 {
26733  ndbrequire(trans_ptr.p->m_state != SchemaTrans::TS_ENDING);
26734  trans_ptr.p->m_state = SchemaTrans::TS_ENDING;
26735 
26736  trans_ptr.p->m_nodes.bitAND(c_aliveNodes);
26737  NdbNodeBitmask nodes = trans_ptr.p->m_nodes;
26738  NodeReceiverGroup rg(DBDICT, nodes);
26739  {
26740  SafeCounter sc(c_counterMgr, trans_ptr.p->m_counter);
26741  bool ok = sc.init<SchemaTransImplRef>(rg, trans_ptr.p->trans_key);
26742  ndbrequire(ok);
26743  }
26744 
26745  if (ERROR_INSERTED(6150))
26746  {
26747  jam();
26748  /*
26749  Simulate slave missing ending transaction
26750  */
26751  jam();
26752  Uint32 nodeId = rand() % MAX_NDB_NODES;
26753  while(nodeId == c_masterNodeId || (!rg.m_nodes.get(nodeId)))
26754  nodeId = rand() % MAX_NDB_NODES;
26755 
26756  infoEvent("Simulating node %u missing RT_END", nodeId);
26757  rg.m_nodes.clear(nodeId);
26758  signal->theData[0] = 9999;
26759  signal->theData[1] = ERROR_INSERT_VALUE;
26760  CLEAR_ERROR_INSERT_VALUE;
26761  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
26762  5000, 2);
26763  }
26764 
26765  SchemaTransImplReq* req = (SchemaTransImplReq*)signal->getDataPtrSend();
26766  req->senderRef = reference();
26767  req->transKey = trans_ptr.p->trans_key;
26768  req->opKey = RNIL;
26769  req->requestInfo = SchemaTransImplReq::RT_END;
26770  req->transId = trans_ptr.p->m_transId;
26771  sendSignal(rg, GSN_SCHEMA_TRANS_IMPL_REQ, signal,
26772  SchemaTransImplReq::SignalLength, JBB);
26773 }
26774 
26775 void
26776 Dbdict::check_partial_trans_end_recv_reply(SchemaTransPtr trans_ptr)
26777 {
26778  jam();
26779  NodeRecordPtr ownNodePtr;
26780  c_nodes.getPtr(ownNodePtr, getOwnNodeId());
26781  if (ownNodePtr.p->nodeState == NodeRecord::NDB_MASTER_TAKEOVER &&
26782  trans_ptr.p->check_partial_rollforward &&
26783  trans_ptr.p->ressurected_op)
26784  {
26785  /*
26786  We created an operation in new master just to able to
26787  complete operation on other slaves. We need to release
26788  this ressurected operation explictely.
26789  */
26790  jam();
26791  SchemaOpPtr op_ptr;
26792  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
26793  list.remove(op_ptr);
26794 #ifdef VM_TRACE
26795  ndbout_c("Releasing ressurected op %u", op_ptr.p->op_key);
26796 #endif
26797  releaseSchemaOp(op_ptr);
26798  trans_ptr.p->check_partial_rollforward = false;
26799  }
26800 }
26801 
26802 void
26803 Dbdict::trans_end_recv_reply(Signal* signal, SchemaTransPtr trans_ptr)
26804 {
26805  // unlock
26806  const DictLockReq& lockReq = trans_ptr.p->m_lockReq;
26807  dict_lock_unlock(signal, &lockReq);
26808 
26809  sendTransClientReply(signal, trans_ptr);
26810  check_partial_trans_end_recv_reply(trans_ptr);
26811  releaseSchemaTrans(trans_ptr);
26812 }
26813 
26814 void Dbdict::trans_recover(Signal* signal, SchemaTransPtr trans_ptr)
26815 {
26816  ErrorInfo error;
26817 
26818  jam();
26819 #ifdef VM_TRACE
26820  ndbout_c("Dbdict::trans_recover trans %u, state %u", trans_ptr.p->trans_key, trans_ptr.p->m_state);
26821 #endif
26822 
26823  switch(trans_ptr.p->m_state) {
26824  case SchemaTrans::TS_INITIAL:
26825  jam();
26826  case SchemaTrans::TS_STARTING:
26827  jam();
26828  case SchemaTrans::TS_STARTED:
26829  jam();
26830  if (trans_ptr.p->m_rollback_op == 0)
26831  {
26832  /*
26833  No parsed operations found
26834  */
26835  jam();
26836 #ifdef VM_TRACE
26837  ndbout_c("Dbdict::trans_recover: ENDING START, trans %u(0x%8x), state %u", trans_ptr.i, (uint)trans_ptr.p->trans_key, trans_ptr.p->m_state);
26838 #endif
26839  setError(trans_ptr.p->m_error, SchemaTransEndRep::TransAborted, __LINE__);
26840  trans_end_start(signal, trans_ptr);
26841  return;
26842  }
26843  case SchemaTrans::TS_PARSING:
26844  jam();
26845  setError(trans_ptr.p->m_error, SchemaTransEndRep::TransAborted, __LINE__);
26846  trans_abort_parse_start(signal, trans_ptr);
26847  return;
26848  case SchemaTrans::TS_ABORTING_PARSE:
26849  {
26850  jam();
26851 #ifdef VM_TRACE
26852  ndbout_c("Dbdict::trans_recover: ABORTING_PARSE, trans %u(0x%8x), state %u", trans_ptr.i, (uint)trans_ptr.p->trans_key, trans_ptr.p->m_state);
26853 #endif
26854  setError(trans_ptr.p->m_error, SchemaTransEndRep::TransAborted, __LINE__);
26855  SchemaOpPtr op_ptr;
26856  c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
26857  // Revert operation state to restart abort
26858  op_ptr.p->m_state = SchemaOp::OS_PREPARED;
26859  trans_abort_parse_next(signal, trans_ptr, op_ptr);
26860  return;
26861  }
26862  case SchemaTrans::TS_PREPARING:
26863  jam();
26864  if (trans_ptr.p->m_master_recovery_state == SchemaTrans::TRS_ROLLFORWARD)
26865  goto flush_commit;
26866  setError(trans_ptr.p->m_error, SchemaTransEndRep::TransAborted, __LINE__);
26867  trans_abort_prepare_start(signal, trans_ptr);
26868  return;
26869  case SchemaTrans::TS_ABORTING_PREPARE:
26870  {
26871  jam();
26872 #ifdef VM_TRACE
26873  ndbout_c("Dbdict::trans_recover: ABORTING PREPARE, trans %u(0x%8x), state %u", trans_ptr.i, (uint)trans_ptr.p->trans_key, trans_ptr.p->m_state);
26874 #endif
26875  setError(trans_ptr.p->m_error, SchemaTransEndRep::TransAborted, __LINE__);
26876  SchemaOpPtr op_ptr;
26877  c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
26878  // Revert operation state to restart abort
26879  op_ptr.p->m_state = SchemaOp::OS_PREPARED;
26880  trans_abort_prepare_next(signal, trans_ptr, op_ptr);
26881  return;
26882  }
26883  case SchemaTrans::TS_FLUSH_COMMIT:
26884  flush_commit:
26885  /*
26886  Flush commit any unflushed slaves
26887  */
26888  jam();
26889  trans_commit_start(signal, trans_ptr);
26890  return;
26891  case SchemaTrans::TS_COMMITTING:
26892  {
26893  if (trans_ptr.p->m_highest_trans_state <= SchemaTrans::TS_COMMITTING)
26894  {
26895  jam();
26896  /*
26897  Commit any uncommited operations
26898  */
26899  jam();
26900  SchemaOpPtr op_ptr;
26901  c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
26902  if (op_ptr.p->m_state < SchemaOp::OS_COMMITTED)
26903  {
26904  jam();
26905  trans_commit_next(signal, trans_ptr, op_ptr);
26906  return;
26907  }
26908  }
26909  /*
26910  We have started flushing commits
26911  */
26912  jam();
26913  NodeRecordPtr masterNodePtr;
26914  c_nodes.getPtr(masterNodePtr, c_masterNodeId);
26915  if (masterNodePtr.p->recoveryState
26916  == NodeRecord::RS_PARTIAL_ROLLFORWARD)
26917  {
26918  /*
26919  New master has flushed commit and
26920  thus have released commit mutex
26921  */
26922  jam();
26923  trans_commit_mutex_unlocked(signal, trans_ptr.i, 0);
26924  return;
26925  }
26926  else
26927  {
26928  /*
26929  New master has not flushed commit and
26930  thus have to release commit mutex
26931  */
26932  jam();
26933  trans_commit_done(signal, trans_ptr);
26934  return;
26935  }
26936  }
26937  case SchemaTrans::TS_FLUSH_COMPLETE:
26938  jam();
26939 #ifdef VM_TRACE
26940  ndbout_c("Dbdict::trans_recover: COMMITTING DONE, trans %u(0x%8x), state %u", trans_ptr.i, (uint)trans_ptr.p->trans_key, trans_ptr.p->m_state);
26941 #endif
26942  trans_complete_done(signal, trans_ptr);
26943  return;
26944  case SchemaTrans::TS_COMPLETING:
26945  {
26946  /*
26947  Complete any uncommited operations
26948  */
26949  jam();
26950 #ifdef VM_TRACE
26951  ndbout_c("Dbdict::trans_recover: COMPLETING, trans %u(0x%8x), state %u", trans_ptr.i, (uint)trans_ptr.p->trans_key, trans_ptr.p->m_state);
26952 #endif
26953  SchemaOpPtr op_ptr;
26954  c_schemaOpPool.getPtr(op_ptr, trans_ptr.p->m_curr_op_ptr_i);
26955  if (op_ptr.p->m_state < SchemaOp::OS_COMPLETED)
26956  {
26957  jam();
26958  trans_complete_next(signal, trans_ptr, op_ptr);
26959  return;
26960  }
26961  }
26962  case SchemaTrans::TS_ENDING:
26963  /*
26964  End any pending slaves
26965  */
26966  jam();
26967 #ifdef VM_TRACE
26968  ndbout_c("Dbdict::trans_recover: ENDING, trans %u(0x%8x), state %u", trans_ptr.i, (uint)trans_ptr.p->trans_key, trans_ptr.p->m_state);
26969 #endif
26970  trans_end_start(signal, trans_ptr);
26971  return;
26972  default:
26973  jam();
26974  }
26975  ndbassert(false);
26976 }
26977 
26978 
26979 // participant
26980 
26981 void
26982 Dbdict::execSCHEMA_TRANS_IMPL_REQ(Signal* signal)
26983 {
26984  jamEntry();
26985  if (!assembleFragments(signal)) {
26986  jam();
26987  return;
26988  }
26989  SchemaTransImplReq reqCopy =
26990  *(const SchemaTransImplReq*)signal->getDataPtr();
26991  const SchemaTransImplReq *req = &reqCopy;
26992  const Uint32 rt = DictSignal::getRequestType(req->requestInfo);
26993 
26994  if (rt == SchemaTransImplReq::RT_START)
26995  {
26996  jam();
26997  if (signal->getLength() < SchemaTransImplReq::SignalLengthStart)
26998  {
26999  jam();
27000  reqCopy.start.objectId = getFreeObjId(0);
27001  }
27002  slave_run_start(signal, req);
27003  return;
27004  }
27005 
27006  ErrorInfo error;
27007  SchemaTransPtr trans_ptr;
27008  const Uint32 trans_key = req->transKey;
27009  if (!findSchemaTrans(trans_ptr, trans_key))
27010  {
27011  jam();
27012  setError(error, SchemaTransImplRef::InvalidTransKey, __LINE__);
27013  goto err;
27014  }
27015 
27016 #ifdef MARTIN
27017  char buf[256];
27018  switch(rt) {
27019  case(SchemaTransImplReq::RT_START):
27020  sprintf(buf, " RequestType: RT_START");
27021  break;
27022  case(SchemaTransImplReq::RT_PARSE):
27023  sprintf(buf, " RequestType: RT_PARSE");
27024  break;
27025  case(SchemaTransImplReq::RT_FLUSH_PREPARE):
27026  sprintf(buf, " RequestType: RT_FLUSH_PREPARE");
27027  break;
27028  case(SchemaTransImplReq::RT_PREPARE):
27029  sprintf(buf, " RequestType: RT_PREPARE");
27030  break;
27031  case(SchemaTransImplReq::RT_ABORT_PARSE):
27032  sprintf(buf, " RequestType: RT_ABORT_PARSE");
27033  break;
27034  case(SchemaTransImplReq::RT_ABORT_PREPARE):
27035  sprintf(buf, " RequestType: RT_ABORT_PREPARE");
27036  break;
27037  case(SchemaTransImplReq::RT_FLUSH_COMMIT):
27038  sprintf(buf, " RequestType: RT_FLUSH_COMMIT");
27039  break;
27040  case(SchemaTransImplReq::RT_COMMIT):
27041  sprintf(buf, " RequestType: RT_COMMIT");
27042  break;
27043  case(SchemaTransImplReq::RT_FLUSH_COMPLETE):
27044  sprintf(buf, " RequestType: RT_FLUSH_COMPLETE");
27045  break;
27046  case(SchemaTransImplReq::RT_COMPLETE):
27047  sprintf(buf, " RequestType: RT_COMPLETE");
27048  break;
27049  case(SchemaTransImplReq::RT_END):
27050  sprintf(buf, " RequestType: RT_END");
27051  break;
27052  }
27053  infoEvent("Dbdict::execSCHEMA_TRANS_IMPL_REQ: %s", buf);
27054 #endif
27055 
27059  switch(rt){
27060  case SchemaTransImplReq::RT_PARSE:
27061  jam();
27062  slave_run_parse(signal, trans_ptr, req);
27063  return;
27064  case SchemaTransImplReq::RT_END:
27065  case SchemaTransImplReq::RT_FLUSH_PREPARE:
27066  case SchemaTransImplReq::RT_FLUSH_COMMIT:
27067  case SchemaTransImplReq::RT_FLUSH_COMPLETE:
27068  jam();
27069  jamLine(rt);
27070  slave_run_flush(signal, trans_ptr, req);
27071  return;
27072  default:
27073  break;
27074  }
27075 
27076  SchemaOpPtr op_ptr;
27077  if (!findSchemaOp(op_ptr, req->opKey))
27078  {
27079  jam();
27080  // wl3600_todo better error no
27081  setError(error, SchemaTransImplRef::InvalidTransKey, __LINE__);
27082  goto err;
27083  }
27084 
27085  {
27086  const OpInfo info = getOpInfo(op_ptr);
27087  switch(rt){
27088  case SchemaTransImplReq::RT_START:
27089  case SchemaTransImplReq::RT_PARSE:
27090  case SchemaTransImplReq::RT_FLUSH_PREPARE:
27091  case SchemaTransImplReq::RT_FLUSH_COMMIT:
27092  case SchemaTransImplReq::RT_FLUSH_COMPLETE:
27093  ndbrequire(false); // handled above
27094  case SchemaTransImplReq::RT_PREPARE:
27095  jam();
27096  op_ptr.p->m_state = SchemaOp::OS_PREPARING;
27097  (this->*(info.m_prepare))(signal, op_ptr);
27098  return;
27099  case SchemaTransImplReq::RT_ABORT_PARSE:
27100  jam();
27101  ndbrequire(op_ptr.p->nextList == RNIL);
27102  op_ptr.p->m_state = SchemaOp::OS_ABORTING_PARSE;
27103  (this->*(info.m_abortParse))(signal, op_ptr);
27104  trans_log_schema_op_abort(op_ptr);
27105  if (!trans_ptr.p->m_isMaster)
27106  {
27107  trans_ptr.p->m_state = SchemaTrans::TS_ABORTING_PARSE;
27111  LocalDLFifoList<SchemaOp> list(c_schemaOpPool, trans_ptr.p->m_op_list);
27112  list.remove(op_ptr);
27113  releaseSchemaOp(op_ptr);
27114  }
27115  return;
27116  case SchemaTransImplReq::RT_ABORT_PREPARE:
27117  jam();
27118  op_ptr.p->m_state = SchemaOp::OS_ABORTING_PREPARE;
27119  (this->*(info.m_abortPrepare))(signal, op_ptr);
27120  if (!trans_ptr.p->m_isMaster)
27121  trans_ptr.p->m_state = SchemaTrans::TS_ABORTING_PREPARE;
27122  return;
27123  case SchemaTransImplReq::RT_COMMIT:
27124  jam();
27125  op_ptr.p->m_state = SchemaOp::OS_COMMITTING;
27126  (this->*(info.m_commit))(signal, op_ptr);
27127  return;
27128  case SchemaTransImplReq::RT_COMPLETE:
27129  jam();
27130  op_ptr.p->m_state = SchemaOp::OS_COMPLETING;
27131  (this->*(info.m_complete))(signal, op_ptr);
27132  trans_log_schema_op_complete(op_ptr);
27133  return;
27134  }
27135  }
27136 
27137  return;
27138 err:
27139  ndbrequire(false);
27140 }
27141 
27142 void
27143 Dbdict::slave_run_start(Signal *signal, const SchemaTransImplReq* req)
27144 {
27145  ErrorInfo error;
27146  SchemaTransPtr trans_ptr;
27147  const Uint32 trans_key = req->transKey;
27148 
27149  Uint32 objId = getFreeObjId(req->start.objectId);
27150  if (objId != req->start.objectId)
27151  {
27152  jam();
27153  setError(error, CreateTableRef::NoMoreTableRecords, __LINE__);
27154  goto err;
27155  }
27156 
27157  if (req->senderRef != reference())
27158  {
27159  jam();
27160  if (!seizeSchemaTrans(trans_ptr, trans_key))
27161  {
27162  jam();
27163  setError(error, SchemaTransImplRef::TooManySchemaTrans, __LINE__);
27164  goto err;
27165  }
27166  trans_ptr.p->m_clientRef = req->start.clientRef;
27167  trans_ptr.p->m_transId = req->transId;
27168  trans_ptr.p->m_isMaster = false;
27169  trans_ptr.p->m_masterRef = req->senderRef;
27170  trans_ptr.p->m_requestInfo = req->requestInfo;
27171  trans_ptr.p->m_state = SchemaTrans::TS_STARTED;
27172  }
27173  else
27174  {
27175  jam();
27176  // this branch does nothing but is convenient for signal pong
27177  ndbrequire(findSchemaTrans(trans_ptr, req->transKey));
27178  }
27179 
27180  trans_ptr.p->m_obj_id = objId;
27181  trans_log(trans_ptr);
27182 
27183  sendTransConf(signal, trans_ptr);
27184  return;
27185 
27186 err:
27187  SchemaTrans tmp_trans;
27188  trans_ptr.i = RNIL;
27189  trans_ptr.p = &tmp_trans;
27190  trans_ptr.p->trans_key = trans_key;
27191  trans_ptr.p->m_masterRef = req->senderRef;
27192  setError(trans_ptr.p->m_error, error);
27193  sendTransRef(signal, trans_ptr);
27194 }
27195 
27196 void
27197 Dbdict::slave_run_parse(Signal *signal,
27198  SchemaTransPtr trans_ptr,
27199  const SchemaTransImplReq* req)
27200 {
27201  SchemaOpPtr op_ptr;
27202  D("slave_run_parse");
27203 
27204  const Uint32 op_key = req->opKey;
27205  const Uint32 gsn = req->parse.gsn;
27206  const Uint32 requestInfo = req->requestInfo;
27207  const OpInfo& info = *findOpInfo(gsn);
27208 
27209  // signal data contains impl_req
27210  const Uint32* src = signal->getDataPtr() + SchemaTransImplReq::SignalLength;
27211  const Uint32 len = info.m_impl_req_length;
27212 
27213  SectionHandle handle(this, signal);
27214 
27215  ndbrequire(op_key != RNIL);
27216  ErrorInfo error;
27217  if (trans_ptr.p->m_isMaster)
27218  {
27219  jam();
27220  // this branch does nothing but is convenient for signal pong
27221 
27222  //XXX Check if op == last op in trans
27223  findSchemaOp(op_ptr, op_key);
27224  ndbrequire(!op_ptr.isNull());
27225 
27226  OpRecPtr oprec_ptr = op_ptr.p->m_oprec_ptr;
27227  const Uint32* dst = oprec_ptr.p->m_impl_req_data;
27228  ndbrequire(memcmp(dst, src, len << 2) == 0);
27229  }
27230  else
27231  {
27232  if (checkSingleUserMode(trans_ptr.p->m_clientRef))
27233  {
27234  jam();
27235  setError(error, AlterTableRef::SingleUser, __LINE__);
27236  }
27237  else if (seizeSchemaOp(op_ptr, op_key, info))
27238  {
27239  jam();
27240 
27241  DictSignal::addRequestExtra(op_ptr.p->m_requestInfo, requestInfo);
27242  DictSignal::addRequestFlags(op_ptr.p->m_requestInfo, requestInfo);
27243 
27244  OpRecPtr oprec_ptr = op_ptr.p->m_oprec_ptr;
27245  Uint32* dst = oprec_ptr.p->m_impl_req_data;
27246  memcpy(dst, src, len << 2);
27247 
27248  addSchemaOp(trans_ptr, op_ptr);
27249  op_ptr.p->m_state = SchemaOp::OS_PARSING;
27250  (this->*(info.m_parse))(signal, false, op_ptr, handle, error);
27251  } else {
27252  jam();
27253  setError(error, SchemaTransImplRef::TooManySchemaOps, __LINE__);
27254  }
27255  }
27256 
27257  // parse must consume but not release signal sections
27258  releaseSections(handle);
27259 
27260  if (hasError(error))
27261  {
27262  jam();
27263  setError(trans_ptr, error);
27264  sendTransRef(signal, trans_ptr);
27265  return;
27266  }
27267  sendTransConf(signal, op_ptr);
27268 }
27269 
27270 void
27271 Dbdict::slave_run_flush(Signal *signal,
27272  SchemaTransPtr trans_ptr,
27273  const SchemaTransImplReq* req)
27274 {
27275  bool do_flush = false;
27276  const Uint32 rt = DictSignal::getRequestType(req->requestInfo);
27277  const bool master = trans_ptr.p->m_isMaster;
27278 
27279  jamLine(trans_ptr.p->m_state);
27280  switch(rt){
27281  case SchemaTransImplReq::RT_FLUSH_PREPARE:
27282  if (master)
27283  {
27284  jam();
27285  ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_FLUSH_PREPARE);
27286  }
27287  else
27288  {
27289  jam();
27290  ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_STARTED ||
27291  trans_ptr.p->m_state == SchemaTrans::TS_ABORTING_PARSE);
27292  trans_ptr.p->m_state = SchemaTrans::TS_FLUSH_PREPARE;
27293  }
27294  do_flush = trans_ptr.p->m_flush_prepare;
27295  break;
27296  case SchemaTransImplReq::RT_FLUSH_COMMIT:
27297  if (master)
27298  {
27299  jam();
27300  ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_FLUSH_COMMIT);
27301  }
27302  else
27303  {
27304  jam();
27305  ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_PREPARING);
27306  trans_ptr.p->m_state = SchemaTrans::TS_FLUSH_COMMIT;
27307  }
27308  do_flush = trans_ptr.p->m_flush_commit;
27309  break;
27310  case SchemaTransImplReq::RT_FLUSH_COMPLETE:
27311  if (master)
27312  {
27313  jam();
27314  ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_FLUSH_COMPLETE);
27315  }
27316  else
27317  {
27318  jam();
27319  ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_COMMITTING);
27320  trans_ptr.p->m_state = SchemaTrans::TS_FLUSH_COMPLETE;
27321  }
27322  do_flush = trans_ptr.p->m_flush_complete;
27323  break;
27324  case SchemaTransImplReq::RT_END:
27329  trans_ptr.p->m_state = SchemaTrans::TS_ENDING;
27330  do_flush = trans_ptr.p->m_flush_end;
27331  break;
27332  default:
27333  ndbrequire(false);
27334  }
27335 
27336  trans_log(trans_ptr);
27337 
27338 #if 1
27339  if (do_flush == false)
27340  {
27347  slave_writeSchema_conf(signal, trans_ptr.p->trans_key, 0);
27348  return;
27349  }
27350 #endif
27351 
27352  XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
27353  ndbrequire(c_writeSchemaRecord.inUse == false);
27354  c_writeSchemaRecord.inUse = true;
27355  c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
27356  c_writeSchemaRecord.newFile = false;
27357  c_writeSchemaRecord.firstPage = 0;
27358  c_writeSchemaRecord.noOfPages = xsf->noOfPages;
27359 
27360  c_writeSchemaRecord.m_callback.m_callbackData = trans_ptr.p->trans_key;
27361  c_writeSchemaRecord.m_callback.m_callbackFunction =
27362  safe_cast(&Dbdict::slave_writeSchema_conf);
27363 
27364  for(Uint32 i = 0; i<xsf->noOfPages; i++)
27365  computeChecksum(xsf, i);
27366 
27367  startWriteSchemaFile(signal);
27368 }
27369 
27370 void
27371 Dbdict::slave_writeSchema_conf(Signal* signal,
27372  Uint32 trans_key,
27373  Uint32 ret)
27374 {
27375  jamEntry();
27376  ndbrequire(ret == 0);
27377  SchemaTransPtr trans_ptr;
27378  ndbrequire(findSchemaTrans(trans_ptr, trans_key));
27379 
27380  bool release = false;
27381  if (!trans_ptr.p->m_isMaster)
27382  {
27383  switch(trans_ptr.p->m_state){
27384  case SchemaTrans::TS_FLUSH_PREPARE:
27385  jam();
27386  trans_ptr.p->m_state = SchemaTrans::TS_PREPARING;
27387  break;
27388  case SchemaTrans::TS_FLUSH_COMMIT:
27389  {
27390  jam();
27391  trans_ptr.p->m_state = SchemaTrans::TS_COMMITTING;
27392  // Take commit lock
27393  Mutex mutex(signal, c_mutexMgr, trans_ptr.p->m_commit_mutex);
27394  Callback c = { safe_cast(&Dbdict::slave_commit_mutex_locked), trans_ptr.i };
27395  bool ok = mutex.lock(c);
27396  ndbrequire(ok);
27397  return;
27398  }
27399  case SchemaTrans::TS_FLUSH_COMPLETE:
27400  {
27401  jam();
27402  trans_ptr.p->m_state = SchemaTrans::TS_COMPLETING;
27403  // Release commit lock
27404  Mutex mutex(signal, c_mutexMgr, trans_ptr.p->m_commit_mutex);
27405  Callback c = { safe_cast(&Dbdict::slave_commit_mutex_unlocked), trans_ptr.i };
27406  mutex.unlock(c);
27407  return;
27408  }
27409  case SchemaTrans::TS_ENDING:
27410  jam();
27411  release = true;
27412  break;
27413  default:
27414  jamLine(trans_ptr.p->m_state);
27415  ndbrequire(false);
27416  }
27417  }
27418 
27419  sendTransConfRelease(signal, trans_ptr);
27420 }
27421 
27422 void
27423 Dbdict::slave_commit_mutex_locked(Signal* signal,
27424  Uint32 transPtrI,
27425  Uint32 ret)
27426 {
27427  jamEntry();
27428 #ifdef MARTIN
27429  ndbout_c("slave_commit_mutex_locked");
27430 #endif
27431  SchemaTransPtr trans_ptr;
27432  c_schemaTransPool.getPtr(trans_ptr, transPtrI);
27433 
27434  ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_COMMITTING);
27435  sendTransConfRelease(signal, trans_ptr);
27436 }
27437 
27438 void
27439 Dbdict::slave_commit_mutex_unlocked(Signal* signal,
27440  Uint32 transPtrI,
27441  Uint32 ret)
27442 {
27443  jamEntry();
27444 #ifdef MARTIN
27445  ndbout_c("slave_commit_mutex_unlocked");
27446 #endif
27447  SchemaTransPtr trans_ptr;
27448  c_schemaTransPool.getPtr(trans_ptr, transPtrI);
27449 
27450  trans_ptr.p->m_commit_mutex.release(c_mutexMgr);
27451 
27452  ndbrequire(trans_ptr.p->m_state == SchemaTrans::TS_COMPLETING);
27453  sendTransConfRelease(signal, trans_ptr);
27454 }
27455 
27456 void Dbdict::sendTransConfRelease(Signal*signal, SchemaTransPtr trans_ptr)
27457 {
27458  jam();
27459  sendTransConf(signal, trans_ptr);
27460 
27461  if ((!trans_ptr.p->m_isMaster) &&
27462  trans_ptr.p->m_state == SchemaTrans::TS_ENDING)
27463  {
27464  jam();
27465  releaseSchemaTrans(trans_ptr);
27466  }
27467 }
27468 
27469 void
27470 Dbdict::update_op_state(SchemaOpPtr op_ptr)
27471 {
27472  switch(op_ptr.p->m_state){
27473  case SchemaOp::OS_PARSE_MASTER:
27474  break;
27475  case SchemaOp::OS_PARSING:
27476  op_ptr.p->m_state = SchemaOp::OS_PARSED;
27477  break;
27478  case SchemaOp::OS_PARSED:
27479  ndbrequire(false);
27480  case SchemaOp::OS_PREPARING:
27481  op_ptr.p->m_state = SchemaOp::OS_PREPARED;
27482  break;
27483  case SchemaOp::OS_PREPARED:
27484  ndbrequire(false);
27485  case SchemaOp::OS_ABORTING_PREPARE:
27486  op_ptr.p->m_state = SchemaOp::OS_ABORTED_PREPARE;
27487  break;
27488  case SchemaOp::OS_ABORTED_PREPARE:
27489  ndbrequire(false);
27490  case SchemaOp::OS_ABORTING_PARSE:
27491  break;
27492  //case SchemaOp::OS_ABORTED_PARSE: // Not used, op released
27493  case SchemaOp::OS_COMMITTING:
27494  op_ptr.p->m_state = SchemaOp::OS_COMMITTED;
27495  break;
27496  case SchemaOp::OS_COMMITTED:
27497  ndbrequire(false);
27498  case SchemaOp::OS_COMPLETING:
27499  op_ptr.p->m_state = SchemaOp::OS_COMPLETED;
27500  break;
27501  case SchemaOp::OS_COMPLETED:
27502  ndbrequire(false);
27503  }
27504 }
27505 
27506 void
27507 Dbdict::sendTransConf(Signal* signal, SchemaOpPtr op_ptr)
27508 {
27509  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
27510  update_op_state(op_ptr);
27511  sendTransConf(signal, trans_ptr);
27512 }
27513 
27514 void
27515 Dbdict::sendTransConf(Signal* signal, SchemaTransPtr trans_ptr)
27516 {
27517  ndbrequire(!trans_ptr.isNull());
27518  ndbrequire(signal->getNoOfSections() == 0);
27519 
27520  SchemaTransImplConf* conf =
27521  (SchemaTransImplConf*)signal->getDataPtrSend();
27522  conf->senderRef = reference();
27523  conf->transKey = trans_ptr.p->trans_key;
27524 
27525  const Uint32 masterRef = trans_ptr.p->m_masterRef;
27526 
27527  if (ERROR_INSERTED(6103)) {
27528  jam();
27529  CLEAR_ERROR_INSERT_VALUE;
27530 
27531  // delay CONF
27532 
27533  Uint32* data = &signal->theData[0];
27534  memmove(&data[2], &data[0], SchemaTransImplConf::SignalLength << 2);
27535  data[0] = 6103;
27536  data[1] = masterRef;
27537  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal,
27538  5000, 2 + SchemaTransImplConf::SignalLength);
27539  return;
27540  }
27541 
27542  sendSignal(masterRef, GSN_SCHEMA_TRANS_IMPL_CONF, signal,
27543  SchemaTransImplConf::SignalLength, JBB);
27544 }
27545 
27546 void
27547 Dbdict::sendTransRef(Signal* signal, SchemaOpPtr op_ptr)
27548 {
27549  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
27550  // must have error and already propagated to trans
27551  ndbrequire(hasError(op_ptr.p->m_error));
27552  ndbrequire(hasError(trans_ptr.p->m_error));
27553 
27554  update_op_state(op_ptr);
27555 
27556  sendTransRef(signal, trans_ptr);
27557 }
27558 
27559 void
27560 Dbdict::sendTransRef(Signal* signal, SchemaTransPtr trans_ptr)
27561 {
27562  D("sendTransRef");
27563  ndbrequire(hasError(trans_ptr.p->m_error));
27564 
27565  // trans is not defined on RT_BEGIN REF
27566 
27567  SchemaTransImplRef* ref =
27568  (SchemaTransImplRef*)signal->getDataPtrSend();
27569  ref->senderRef = reference();
27570  ref->transKey = trans_ptr.p->trans_key;
27571  getError(trans_ptr.p->m_error, ref);
27572 
27573  // erro has been reported, clear it
27574  resetError(trans_ptr.p->m_error);
27575 
27576  const Uint32 masterRef = trans_ptr.p->m_masterRef;
27577  sendSignal(masterRef, GSN_SCHEMA_TRANS_IMPL_REF, signal,
27578  SchemaTransImplRef::SignalLength, JBB);
27579 }
27580 
27581 void
27582 Dbdict::trans_log(SchemaTransPtr trans_ptr)
27583 {
27584  Uint32 objectId = trans_ptr.p->m_obj_id;
27585  XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
27586  SchemaFile::TableEntry * entry = getTableEntry(xsf, objectId);
27587 
27588  jam();
27589  jamLine(trans_ptr.p->m_state);
27590  jamLine(entry->m_tableState);
27591  switch(trans_ptr.p->m_state){
27592  case SchemaTrans::TS_STARTED:
27593  case SchemaTrans::TS_STARTING:{
27594  jam();
27595  Uint32 version = entry->m_tableVersion;
27596  Uint32 new_version = create_obj_inc_schema_version(version);
27597  entry->init();
27598  entry->m_tableState = SchemaFile::SF_STARTED;
27599  entry->m_tableVersion = new_version;
27600  entry->m_tableType = DictTabInfo::SchemaTransaction;
27601  entry->m_info_words = 0;
27602  entry->m_gcp = 0;
27603  entry->m_transId = trans_ptr.p->m_transId;
27604  break;
27605  }
27606  case SchemaTrans::TS_FLUSH_PREPARE:
27607  jam();
27608  ndbrequire(entry->m_tableState == SchemaFile::SF_STARTED);
27609  entry->m_tableState = SchemaFile::SF_PREPARE;
27610  break;
27611  case SchemaTrans::TS_ABORTING_PREPARE:
27612  jam();
27613  ndbrequire(entry->m_tableState == SchemaFile::SF_PREPARE);
27614  entry->m_tableState = SchemaFile::SF_ABORT;
27615  break;
27616  case SchemaTrans::TS_FLUSH_COMMIT:
27617  jam();
27618  ndbrequire(entry->m_tableState == SchemaFile::SF_PREPARE);
27619  entry->m_tableState = SchemaFile::SF_COMMIT;
27620  break;
27621  case SchemaTrans::TS_FLUSH_COMPLETE:
27622  jam();
27623  ndbrequire(entry->m_tableState == SchemaFile::SF_COMMIT);
27624  entry->m_tableState = SchemaFile::SF_COMPLETE;
27625  break;
27626  case SchemaTrans::TS_ENDING:
27627  jam();
27628  entry->m_transId = 0;
27629  entry->m_tableState = SchemaFile::SF_UNUSED;
27630  break;
27631  default:
27632  ndbrequire(false);
27633  }
27634 }
27635 
27639 Uint32
27640 Dbdict::trans_log_schema_op(SchemaOpPtr op_ptr,
27641  Uint32 objectId,
27642  const SchemaFile::TableEntry * newEntry)
27643 {
27644  jam();
27645 
27646  XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
27647  SchemaFile::TableEntry * oldEntry = getTableEntry(xsf, objectId);
27648 
27649  if (oldEntry->m_transId != 0)
27650  {
27651  jam();
27652  return DropTableRef::ActiveSchemaTrans; // XXX todo add general code
27653  }
27654 
27655  SchemaFile::TableEntry tmp = * newEntry;
27656  bool restart = op_ptr.p->m_restart;
27657  switch((SchemaFile::EntryState)newEntry->m_tableState){
27658  case SchemaFile::SF_CREATE:
27659  ndbrequire(restart || oldEntry->m_tableState == SchemaFile::SF_UNUSED);
27660  break;
27661  case SchemaFile::SF_ALTER:
27662  ndbrequire(restart || oldEntry->m_tableState == SchemaFile::SF_IN_USE);
27663  tmp = * oldEntry;
27664  tmp.m_info_words = newEntry->m_info_words;
27665  tmp.m_tableVersion = newEntry->m_tableVersion;
27666  break;
27667  case SchemaFile::SF_DROP:
27668  ndbrequire(restart || oldEntry->m_tableState == SchemaFile::SF_IN_USE);
27669  tmp = *oldEntry;
27670  tmp.m_tableState = SchemaFile::SF_DROP;
27671  break;
27672  default:
27673  jamLine(newEntry->m_tableState);
27674  ndbrequire(false);
27675  }
27676 
27677  tmp.m_tableState = newEntry->m_tableState;
27678  tmp.m_transId = newEntry->m_transId;
27679  op_ptr.p->m_orig_entry_id = objectId;
27680  op_ptr.p->m_orig_entry = * oldEntry;
27681 
27682  * oldEntry = tmp;
27683 
27684  if (op_ptr.p->m_restart != 1)
27685  {
27686  jam();
27687 
27688  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
27689  trans_ptr.p->m_flush_prepare |= true;
27690  trans_ptr.p->m_flush_commit |= true;
27691  }
27692 
27693  return 0;
27694 }
27695 
27696 void
27697 Dbdict::trans_log_schema_op_abort(SchemaOpPtr op_ptr)
27698 {
27699  Uint32 objectId = op_ptr.p->m_orig_entry_id;
27700  if (objectId != RNIL)
27701  {
27702  jam();
27703  op_ptr.p->m_orig_entry_id = RNIL;
27704  XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
27705  SchemaFile::TableEntry * entry = getTableEntry(xsf, objectId);
27706  * entry = op_ptr.p->m_orig_entry;
27707  }
27708 }
27709 
27710 void
27711 Dbdict::trans_log_schema_op_complete(SchemaOpPtr op_ptr)
27712 {
27713  Uint32 objectId = op_ptr.p->m_orig_entry_id;
27714  if (objectId != RNIL)
27715  {
27716  jam();
27717  op_ptr.p->m_orig_entry_id = RNIL;
27718  XSchemaFile * xsf = &c_schemaFile[SchemaRecord::NEW_SCHEMA_FILE];
27719  SchemaFile::TableEntry * entry = getTableEntry(xsf, objectId);
27720  switch((SchemaFile::EntryState)entry->m_tableState){
27721  case SchemaFile::SF_CREATE:
27722  entry->m_tableState = SchemaFile::SF_IN_USE;
27723  break;
27724  case SchemaFile::SF_ALTER:
27725  entry->m_tableState = SchemaFile::SF_IN_USE;
27726  break;
27727  case SchemaFile::SF_DROP:
27728  entry->m_tableState = SchemaFile::SF_UNUSED;
27729  break;
27730  default:
27731  jamLine(entry->m_tableState);
27732  ndbrequire(false);
27733  }
27734  entry->m_transId = 0;
27735  }
27736 }
27737 
27738 // reply to trans client for begin/end trans
27739 
27740 void
27741 Dbdict::sendTransClientReply(Signal* signal, SchemaTransPtr trans_ptr)
27742 {
27743  const Uint32 clientFlags = trans_ptr.p->m_clientFlags;
27744  D("sendTransClientReply" << hex << V(clientFlags));
27745  D("c_rope_pool free: " << c_rope_pool.getNoOfFree());
27746 
27747  Uint32 receiverRef = 0;
27748  Uint32 transId = 0;
27749  NodeRecordPtr ownNodePtr;
27750 
27751  c_nodes.getPtr(ownNodePtr, getOwnNodeId());
27752 
27753  if (!(clientFlags & TransClient::TakeOver)) {
27754  receiverRef = trans_ptr.p->m_clientRef;
27755  transId = trans_ptr.p->m_transId;
27756  } else {
27757  jam();
27758  receiverRef = reference();
27759  transId = trans_ptr.p->m_takeOverTxKey;
27760  }
27761 
27762  if (trans_ptr.p->m_clientState == TransClient::BeginReq) {
27763  if (!hasError(trans_ptr.p->m_error)) {
27764  jam();
27765  SchemaTransBeginConf* conf =
27766  (SchemaTransBeginConf*)signal->getDataPtrSend();
27767  conf->senderRef = reference();
27768  conf->transId = transId;
27769  conf->transKey = trans_ptr.p->trans_key;
27770  sendSignal(receiverRef, GSN_SCHEMA_TRANS_BEGIN_CONF, signal,
27771  SchemaTransBeginConf::SignalLength, JBB);
27772  } else {
27773  jam();
27774  SchemaTransBeginRef* ref =
27775  (SchemaTransBeginRef*)signal->getDataPtrSend();
27776  ref->senderRef = reference();
27777  ref->transId = transId;
27778  getError(trans_ptr.p->m_error, ref);
27779  sendSignal(receiverRef, GSN_SCHEMA_TRANS_BEGIN_REF, signal,
27780  SchemaTransBeginRef::SignalLength, JBB);
27781  }
27782  resetError(trans_ptr);
27783  trans_ptr.p->m_clientState = TransClient::BeginReply;
27784  return;
27785  }
27786 
27787  if (trans_ptr.p->m_clientState == TransClient::EndReq) {
27788  if (!hasError(trans_ptr.p->m_error)) {
27789  jam();
27790  SchemaTransEndConf* conf =
27791  (SchemaTransEndConf*)signal->getDataPtrSend();
27792  conf->senderRef = reference();
27793  conf->transId = transId;
27794  sendSignal(receiverRef, GSN_SCHEMA_TRANS_END_CONF, signal,
27795  SchemaTransEndConf::SignalLength, JBB);
27796  } else {
27797  jam();
27798  SchemaTransEndRef* ref =
27799  (SchemaTransEndRef*)signal->getDataPtrSend();
27800  ref->senderRef = reference();
27801  ref->transId = transId;
27802  getError(trans_ptr.p->m_error, ref);
27803  ref->masterNodeId = c_masterNodeId;
27804  sendSignal(receiverRef, GSN_SCHEMA_TRANS_END_REF, signal,
27805  SchemaTransEndRef::SignalLength, JBB);
27806  }
27807  resetError(trans_ptr);
27808  trans_ptr.p->m_clientState = TransClient::EndReply;
27809  if (ownNodePtr.p->nodeState == NodeRecord::NDB_MASTER_TAKEOVER)
27810  {
27811  /*
27812  New master was taking over transaction
27813  */
27814  jam();
27815  goto send_node_fail_rep;
27816  }
27817  return;
27818  }
27819 
27820  if (ownNodePtr.p->nodeState == NodeRecord::NDB_MASTER_TAKEOVER)
27821  {
27822  /*
27823  New master was taking over transaction
27824  Report transaction outcome to client
27825  */
27826  jam();
27827  {
27828  SchemaTransEndRep* rep =
27829  (SchemaTransEndRep*)signal->getDataPtrSend();
27830  rep->senderRef = reference();
27831  rep->transId = transId;
27832  if (hasError(trans_ptr.p->m_error))
27833  getError(trans_ptr.p->m_error, rep);
27834  else
27835  {
27836  rep->errorCode = 0;
27837  rep->errorLine = 0;
27838  rep->errorNodeId = 0;
27839  }
27840  rep->masterNodeId = c_masterNodeId;
27841 #ifdef VM_TRACE
27842  ndbout_c("Dbdict::sendTransClientReply: sending GSN_SCHEMA_TRANS_END_REP to 0x%8x", receiverRef);
27843 #endif
27844  sendSignal(receiverRef, GSN_SCHEMA_TRANS_END_REP, signal,
27845  SchemaTransEndRep::SignalLength, JBB);
27846  }
27847 send_node_fail_rep:
27848  /*
27849  Continue with NODE_FAILREP
27850  */
27851  send_nf_complete_rep(signal, &ownNodePtr.p->nodeFailRep);
27852  }
27853 }
27854 
27855 
27856 // DICT as schema trans client
27857 
27858 bool
27859 Dbdict::seizeTxHandle(TxHandlePtr& tx_ptr)
27860 {
27861  Uint32 tx_key = c_opRecordSequence + 1;
27862  if (c_txHandleHash.seize(tx_ptr)) {
27863  jam();
27864  new (tx_ptr.p) TxHandle();
27865  tx_ptr.p->tx_key = tx_key;
27866  c_txHandleHash.add(tx_ptr);
27867  tx_ptr.p->m_magic = TxHandle::DICT_MAGIC;
27868  D("seizeTxHandle" << V(tx_key));
27869  c_opRecordSequence = tx_key;
27870  return true;
27871  }
27872  tx_ptr.setNull();
27873  return false;
27874 }
27875 
27876 bool
27877 Dbdict::findTxHandle(TxHandlePtr& tx_ptr, Uint32 tx_key)
27878 {
27879  TxHandle tx_rec(tx_key);
27880  if (c_txHandleHash.find(tx_ptr, tx_rec)) {
27881  jam();
27882  ndbrequire(tx_ptr.p->m_magic == TxHandle::DICT_MAGIC);
27883  D("findTxHandle" << V(tx_key));
27884  return true;
27885  }
27886  tx_ptr.setNull();
27887  return false;
27888 }
27889 
27890 void
27891 Dbdict::releaseTxHandle(TxHandlePtr& tx_ptr)
27892 {
27893  D("releaseTxHandle" << V(tx_ptr.p->tx_key));
27894 
27895  ndbrequire(tx_ptr.p->m_magic == TxHandle::DICT_MAGIC);
27896  tx_ptr.p->m_magic = 0;
27897  c_txHandleHash.release(tx_ptr);
27898 }
27899 
27900 void
27901 Dbdict::beginSchemaTrans(Signal* signal, TxHandlePtr tx_ptr)
27902 {
27903  D("beginSchemaTrans");
27904  tx_ptr.p->m_transId = tx_ptr.p->tx_key;
27905 
27906  SchemaTransBeginReq* req =
27907  (SchemaTransBeginReq*)signal->getDataPtrSend();
27908 
27909  Uint32 requestInfo = 0;
27910  DictSignal::addRequestFlags(requestInfo, tx_ptr.p->m_requestInfo);
27911 
27912  const Uint32 clientFlags = tx_ptr.p->m_clientFlags;
27913  ndbrequire(!(clientFlags & TransClient::TakeOver));
27914  req->clientRef = reference();
27915  req->transId = tx_ptr.p->m_transId;
27916  req->requestInfo = requestInfo;
27917  sendSignal(reference(), GSN_SCHEMA_TRANS_BEGIN_REQ, signal,
27918  SchemaTransBeginReq::SignalLength, JBB);
27919 }
27920 
27921 void
27922 Dbdict::endSchemaTrans(Signal* signal, TxHandlePtr tx_ptr, Uint32 flags)
27923 {
27924  D("endSchemaTrans" << hex << V(flags));
27925 
27926  SchemaTransEndReq* req =
27927  (SchemaTransEndReq*)signal->getDataPtrSend();
27928 
27929  Uint32 requestInfo = 0;
27930  DictSignal::addRequestFlags(requestInfo, tx_ptr.p->m_requestInfo);
27931 
27932  const Uint32 clientFlags = tx_ptr.p->m_clientFlags;
27933  Uint32 transId = 0;
27934  if (!(clientFlags & TransClient::TakeOver)) {
27935  transId = tx_ptr.p->m_transId;
27936  } else {
27937  jam();
27938  transId = tx_ptr.p->m_takeOverTransId;
27939  D("take over mode" << hex << V(transId));
27940  }
27941 
27942  req->clientRef = reference();
27943  req->transId = transId;
27944  req->transKey = tx_ptr.p->m_transKey;
27945  req->requestInfo = requestInfo;
27946  req->flags = flags;
27947  sendSignal(reference(), GSN_SCHEMA_TRANS_END_REQ, signal,
27948  SchemaTransEndReq::SignalLength, JBB);
27949 }
27950 
27951 void
27952 Dbdict::execSCHEMA_TRANS_BEGIN_CONF(Signal* signal)
27953 {
27954  jamEntry();
27955  const SchemaTransBeginConf* conf =
27956  (const SchemaTransBeginConf*)signal->getDataPtr();
27957 
27958  TxHandlePtr tx_ptr;
27959  findTxHandle(tx_ptr, conf->transId);
27960  ndbrequire(!tx_ptr.isNull());
27961 
27962  // record trans key
27963  tx_ptr.p->m_transKey = conf->transKey;
27964 
27965  execute(signal, tx_ptr.p->m_callback, 0);
27966 }
27967 
27968 void
27969 Dbdict::execSCHEMA_TRANS_BEGIN_REF(Signal* signal)
27970 {
27971  jamEntry();
27972  const SchemaTransBeginRef* ref =
27973  (const SchemaTransBeginRef*)signal->getDataPtr();
27974 
27975  TxHandlePtr tx_ptr;
27976  findTxHandle(tx_ptr, ref->transId);
27977  ndbrequire(!tx_ptr.isNull());
27978 
27979  setError(tx_ptr.p->m_error, ref);
27980  ndbrequire(ref->errorCode != 0);
27981  execute(signal, tx_ptr.p->m_callback, ref->errorCode);
27982 }
27983 
27984 void
27985 Dbdict::execSCHEMA_TRANS_END_CONF(Signal* signal)
27986 {
27987  jamEntry();
27988  const SchemaTransEndConf* conf =
27989  (const SchemaTransEndConf*)signal->getDataPtr();
27990 
27991  TxHandlePtr tx_ptr;
27992  findTxHandle(tx_ptr, conf->transId);
27993  ndbrequire(!tx_ptr.isNull());
27994 
27995  execute(signal, tx_ptr.p->m_callback, 0);
27996 }
27997 
27998 void
27999 Dbdict::execSCHEMA_TRANS_END_REF(Signal* signal)
28000 {
28001  jamEntry();
28002  const SchemaTransEndRef* ref =
28003  (const SchemaTransEndRef*)signal->getDataPtr();
28004 
28005  TxHandlePtr tx_ptr;
28006  findTxHandle(tx_ptr, ref->transId);
28007  ndbrequire(!tx_ptr.isNull());
28008 
28009  setError(tx_ptr.p->m_error, ref);
28010  ndbrequire(ref->errorCode != 0);
28011  execute(signal, tx_ptr.p->m_callback, ref->errorCode);
28012 }
28013 
28014 void
28015 Dbdict::execSCHEMA_TRANS_END_REP(Signal* signal)
28016 {
28017  jamEntry();
28018  const SchemaTransEndRep* rep =
28019  (const SchemaTransEndRep*)signal->getDataPtr();
28020 
28021  TxHandlePtr tx_ptr;
28022  findTxHandle(tx_ptr, rep->transId);
28023  ndbrequire(!tx_ptr.isNull());
28024 
28025  if (rep->errorCode != 0)
28026  setError(tx_ptr.p->m_error, rep);
28027  execute(signal, tx_ptr.p->m_callback, rep->errorCode);
28028 }
28029 
28030 // trans client takeover
28031 
28032 /*
28033  * API node failure. Each trans is taken over by a new TxHandle,
28034  * unless already running in background by api request (unlikely).
28035  * All transes are marked with ApiFail. API node failure handling
28036  * is complete when last such trans completes. This is checked
28037  * in finishApiFail.
28038  */
28039 void
28040 Dbdict::handleApiFail(Signal* signal,
28041  Uint32 failedApiNode)
28042 {
28043  D("handleApiFail" << V(failedApiNode));
28044 
28045  Uint32 takeOvers = 0;
28046  SchemaTransPtr trans_ptr;
28047  c_schemaTransList.first(trans_ptr);
28048  while (trans_ptr.i != RNIL) {
28049  jam();
28050  D("check" << *trans_ptr.p);
28051  Uint32 clientRef = trans_ptr.p->m_clientRef;
28052 
28053  if (refToNode(clientRef) == failedApiNode)
28054  {
28055  jam();
28056  D("failed" << hex << V(clientRef));
28057 
28058  ndbrequire(!(trans_ptr.p->m_clientFlags & TransClient::ApiFail));
28059  trans_ptr.p->m_clientFlags |= TransClient::ApiFail;
28060 
28061  if (trans_ptr.p->m_isMaster)
28062  {
28063  jam();
28064  if (trans_ptr.p->m_clientFlags & TransClient::TakeOver)
28065  {
28066  // maybe already running in background
28067  jam();
28068  ndbrequire(trans_ptr.p->m_clientFlags & TransClient::Background);
28069  }
28070  else
28071  {
28072  takeOverTransClient(signal, trans_ptr);
28073  }
28074 
28075  TxHandlePtr tx_ptr;
28076  bool ok = findTxHandle(tx_ptr, trans_ptr.p->m_takeOverTxKey);
28077  ndbrequire(ok);
28078 
28079  tx_ptr.p->m_clientFlags |= TransClient::ApiFail;
28080  takeOvers++;
28081  }
28082  }
28083 
28084  c_schemaTransList.next(trans_ptr);
28085  }
28086 
28087  D("handleApiFail" << V(takeOvers));
28088 
28089  if (takeOvers == 0) {
28090  jam();
28091  apiFailBlockHandling(signal, failedApiNode);
28092  }
28093 }
28094 
28095 /*
28096  * Take over client trans, either by background request or at API
28097  * node failure. Continue to the callback routine.
28098  */
28099 void
28100 Dbdict::takeOverTransClient(Signal* signal, SchemaTransPtr trans_ptr)
28101 {
28102  D("takeOverTransClient" << *trans_ptr.p);
28103 
28104  TxHandlePtr tx_ptr;
28105  bool ok = seizeTxHandle(tx_ptr);
28106  ndbrequire(ok);
28107 
28108  ndbrequire(!(trans_ptr.p->m_clientFlags & TransClient::TakeOver));
28109  trans_ptr.p->m_clientFlags |= TransClient::TakeOver;
28110  trans_ptr.p->m_takeOverTxKey = tx_ptr.p->tx_key;
28111 
28112  tx_ptr.p->m_transId = tx_ptr.p->tx_key;
28113  tx_ptr.p->m_transKey = trans_ptr.p->trans_key;
28114  // start with SchemaTrans point of view
28115  tx_ptr.p->m_clientState = trans_ptr.p->m_clientState;
28116  tx_ptr.p->m_clientFlags = trans_ptr.p->m_clientFlags;
28117  tx_ptr.p->m_takeOverRef = trans_ptr.p->m_clientRef;
28118  tx_ptr.p->m_takeOverTransId = trans_ptr.p->m_transId;
28119 
28120  runTransClientTakeOver(signal, tx_ptr.p->tx_key, 0);
28121 }
28122 
28123 /*
28124  * Run one step in client takeover. If not waiting for a signal,
28125  * send end trans abort. The only commit case is when takeover
28126  * takes place in client state EndReq. At the end, send an info
28127  * event and check if the trans was from API node failure.
28128  */
28129 void
28130 Dbdict::runTransClientTakeOver(Signal* signal,
28131  Uint32 tx_key,
28132  Uint32 ret)
28133 {
28134  TxHandlePtr tx_ptr;
28135  bool ok = findTxHandle(tx_ptr, tx_key);
28136  ndbrequire(ok);
28137  D("runClientTakeOver" << *tx_ptr.p << V(ret));
28138 
28139  if (ret != 0) {
28140  jam();
28141  setError(tx_ptr, ret, __LINE__);
28142  }
28143 
28144  const TransClient::State oldState = tx_ptr.p->m_clientState;
28145  const Uint32 clientFlags = tx_ptr.p->m_clientFlags;
28146  ndbrequire(clientFlags & TransClient::TakeOver);
28147 
28148  TransClient::State newState = oldState;
28149  bool wait_sig = false;
28150  bool at_end = false;
28151 
28152  switch (oldState) {
28153  case TransClient::BeginReq:
28154  jam();
28155  newState = TransClient::BeginReply;
28156  wait_sig = true;
28157  break;
28158  case TransClient::BeginReply:
28159  jam();
28160  newState = TransClient::EndReply;
28161  break;
28162  case TransClient::ParseReq:
28163  jam();
28164  newState = TransClient::ParseReply;
28165  wait_sig = true;
28166  break;
28167  case TransClient::ParseReply:
28168  jam();
28169  newState = TransClient::EndReply;
28170  break;
28171  case TransClient::EndReq:
28172  jam();
28173  newState = TransClient::EndReply;
28174  wait_sig = true;
28175  break;
28176  case TransClient::EndReply:
28177  jam();
28178  newState = TransClient::StateUndef;
28179  at_end = true;
28180  break;
28181  default:
28182  ndbrequire(false);
28183  break;
28184  }
28185 
28186  D("set" << V(oldState) << " -> " << V(newState));
28187  tx_ptr.p->m_clientState = newState;
28188 
28189  if (!at_end) {
28190  jam();
28191  Callback c = {
28192  safe_cast(&Dbdict::runTransClientTakeOver),
28193  tx_ptr.p->tx_key
28194  };
28195  tx_ptr.p->m_callback = c;
28196 
28197  if (!wait_sig) {
28198  jam();
28199  Uint32 flags = 0;
28200  flags |= SchemaTransEndReq::SchemaTransAbort;
28201  endSchemaTrans(signal, tx_ptr, flags);
28202  }
28203  return;
28204  }
28205 
28206  if (!hasError(tx_ptr.p->m_error)) {
28207  jam();
28208  infoEvent("DICT: api:0x%8x trans:0x%8x takeover completed",
28209  tx_ptr.p->m_takeOverRef, tx_ptr.p->m_takeOverTransId);
28210  } else {
28211  jam();
28212  infoEvent("DICT: api:0x%8x trans:0x%8x takeover failed, error:%u line:%u",
28213  tx_ptr.p->m_takeOverRef, tx_ptr.p->m_takeOverTransId,
28214  tx_ptr.p->m_error.errorCode, tx_ptr.p->m_error.errorLine);
28215  }
28216 
28217  // if from API fail, check if finished
28218  if (clientFlags & TransClient::ApiFail) {
28219  jam();
28220  finishApiFail(signal, tx_ptr);
28221  }
28222  releaseTxHandle(tx_ptr);
28223 }
28224 
28225 void
28226 Dbdict::finishApiFail(Signal* signal, TxHandlePtr tx_ptr)
28227 {
28228  D("finishApiFail" << *tx_ptr.p);
28229  const Uint32 failedApiNode = refToNode(tx_ptr.p->m_takeOverRef);
28230 
28231  Uint32 takeOvers = 0;
28232  SchemaTransPtr trans_ptr;
28233  c_schemaTransList.first(trans_ptr);
28234  while (trans_ptr.i != RNIL) {
28235  jam();
28236  D("check" << *trans_ptr.p);
28237  const BlockReference clientRef = trans_ptr.p->m_clientRef;
28238 
28239  if (refToNode(clientRef) == failedApiNode) {
28240  jam();
28241  const Uint32 clientFlags = trans_ptr.p->m_clientFlags;
28242  D("failed" << hex << V(clientRef) << dec << V(clientFlags));
28243  ndbrequire(clientFlags & TransClient::ApiFail);
28244  takeOvers++;
28245  }
28246  c_schemaTransList.next(trans_ptr);
28247  }
28248 
28249  D("finishApiFail" << V(takeOvers));
28250 
28251  if (takeOvers == 0) {
28252  jam();
28253  apiFailBlockHandling(signal, failedApiNode);
28254  }
28255 }
28256 
28257 void
28258 Dbdict::apiFailBlockHandling(Signal* signal,
28259  Uint32 failedApiNode)
28260 {
28261  Callback cb = { safe_cast(&Dbdict::handleApiFailureCallback),
28262  failedApiNode };
28263  simBlockNodeFailure(signal, failedApiNode, cb);
28264 }
28265 
28266 // find callback for any key
28267 
28268 bool
28269 Dbdict::findCallback(Callback& callback, Uint32 any_key)
28270 {
28271  SchemaOpPtr op_ptr;
28272  SchemaTransPtr trans_ptr;
28273  TxHandlePtr tx_ptr;
28274 
28275  bool ok1 = findSchemaOp(op_ptr, any_key);
28276  bool ok2 = findSchemaTrans(trans_ptr, any_key);
28277  bool ok3 = findTxHandle(tx_ptr, any_key);
28278  ndbrequire(ok1 + ok2 + ok3 <= 1);
28279 
28280  if (ok1) {
28281  callback = op_ptr.p->m_callback;
28282  return true;
28283  }
28284  if (ok2) {
28285  callback = trans_ptr.p->m_callback;
28286  return true;
28287  }
28288  if (ok3) {
28289  callback = tx_ptr.p->m_callback;
28290  return true;
28291  }
28292  callback.m_callbackFunction = 0;
28293  callback.m_callbackData = 0;
28294  return false;
28295 }
28296 
28297 // MODULE: CreateHashMap
28298 
28299 ArrayPool<Hash2FragmentMap> g_hash_map;
28300 
28301 const Dbdict::OpInfo
28302 Dbdict::CreateHashMapRec::g_opInfo = {
28303  { 'C', 'H', 'M', 0 },
28304  GSN_CREATE_HASH_MAP_REQ,
28305  CreateHashMapReq::SignalLength,
28306  //
28307  &Dbdict::createHashMap_seize,
28308  &Dbdict::createHashMap_release,
28309  //
28310  &Dbdict::createHashMap_parse,
28311  &Dbdict::createHashMap_subOps,
28312  &Dbdict::createHashMap_reply,
28313  //
28314  &Dbdict::createHashMap_prepare,
28315  &Dbdict::createHashMap_commit,
28316  &Dbdict::createHashMap_complete,
28317  //
28318  &Dbdict::createHashMap_abortParse,
28319  &Dbdict::createHashMap_abortPrepare
28320 };
28321 
28322 bool
28323 Dbdict::createHashMap_seize(SchemaOpPtr op_ptr)
28324 {
28325  return seizeOpRec<CreateHashMapRec>(op_ptr);
28326 }
28327 
28328 void
28329 Dbdict::createHashMap_release(SchemaOpPtr op_ptr)
28330 {
28331  releaseOpRec<CreateHashMapRec>(op_ptr);
28332 }
28333 
28334 void
28335 Dbdict::execCREATE_HASH_MAP_REQ(Signal* signal)
28336 {
28337  jamEntry();
28338  if (!assembleFragments(signal)) {
28339  jam();
28340  return;
28341  }
28342  SectionHandle handle(this, signal);
28343 
28344  const CreateHashMapReq req_copy =
28345  *(const CreateHashMapReq*)signal->getDataPtr();
28346  const CreateHashMapReq* req = &req_copy;
28347 
28348  ErrorInfo error;
28349  do {
28350  SchemaOpPtr op_ptr;
28351  CreateHashMapRecPtr createHashMapPtr;
28352  CreateHashMapImplReq* impl_req;
28353 
28354  startClientReq(op_ptr, createHashMapPtr, req, impl_req, error);
28355  if (hasError(error)) {
28356  jam();
28357  break;
28358  }
28359 
28360  impl_req->objectId = RNIL;
28361  impl_req->objectVersion = 0;
28362  impl_req->buckets = req->buckets;
28363  impl_req->fragments = req->fragments;
28364 
28365  handleClientReq(signal, op_ptr, handle);
28366  return;
28367  } while (0);
28368 
28369  releaseSections(handle);
28370 
28371  CreateHashMapRef* ref = (CreateHashMapRef*)signal->getDataPtrSend();
28372 
28373  ref->senderRef = reference();
28374  ref->senderData= req->clientData;
28375  ref->transId = req->transId;
28376  getError(error, ref);
28377 
28378  sendSignal(req->clientRef, GSN_CREATE_HASH_MAP_REF, signal,
28379  CreateHashMapRef::SignalLength, JBB);
28380 }
28381 
28382 // CreateHashMap: PARSE
28383 
28384 Uint32
28385 Dbdict::get_default_fragments(Signal* signal, Uint32 extranodegroups)
28386 {
28387  jam();
28388 
28389  CheckNodeGroups * sd = CAST_PTR(CheckNodeGroups, signal->getDataPtrSend());
28390  sd->extraNodeGroups = extranodegroups;
28391  sd->requestType = CheckNodeGroups::Direct | CheckNodeGroups::GetDefaultFragments;
28392  EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal,
28393  CheckNodeGroups::SignalLength);
28394  jamEntry();
28395  return sd->output;
28396 }
28397 
28398 void
28399 Dbdict::createHashMap_parse(Signal* signal, bool master,
28400  SchemaOpPtr op_ptr,
28401  SectionHandle& handle, ErrorInfo& error)
28402 {
28403 
28404  SchemaTransPtr trans_ptr = op_ptr.p->m_trans_ptr;
28405  CreateHashMapRecPtr createHashMapPtr;
28406  getOpRec(op_ptr, createHashMapPtr);
28407  CreateHashMapImplReq* impl_req = &createHashMapPtr.p->m_request;
28408 
28409  jam();
28410 
28411  SegmentedSectionPtr objInfoPtr;
28412  DictHashMapInfo::HashMap hm; hm.init();
28413  if (handle.m_cnt)
28414  {
28416 
28417  handle.getSection(objInfoPtr, CreateHashMapReq::INFO);
28418  SimplePropertiesSectionReader it(objInfoPtr, getSectionSegmentPool());
28419  status = SimpleProperties::unpack(it, &hm,
28421  DictHashMapInfo::MappingSize,
28422  true, true);
28423 
28424  if (ERROR_INSERTED(6204))
28425  {
28426  jam();
28427  CLEAR_ERROR_INSERT_VALUE;
28428  setError(error, 1, __LINE__);
28429  return;
28430  }
28431 
28432  if (status != SimpleProperties::Eof)
28433  {
28434  jam();
28435  setError(error, CreateTableRef::InvalidFormat, __LINE__);
28436  return;
28437  }
28438  }
28439  else if (!master)
28440  {
28441  jam();
28442  setError(error, CreateTableRef::InvalidFormat, __LINE__);
28443  return;
28444  }
28445  else
28446  {
28451  jam();
28452  if (impl_req->requestType & CreateHashMapReq::CreateDefault)
28453  {
28454  jam();
28455  impl_req->buckets = NDB_DEFAULT_HASHMAP_BUCKTETS;
28456  impl_req->fragments = 0;
28457  }
28458 
28459  Uint32 buckets = impl_req->buckets;
28460  Uint32 fragments = impl_req->fragments;
28461  if (fragments == 0)
28462  {
28463  jam();
28464 
28465  fragments = get_default_fragments(signal);
28466  }
28467 
28468  BaseString::snprintf(hm.HashMapName, sizeof(hm.HashMapName),
28469  "DEFAULT-HASHMAP-%u-%u",
28470  buckets,
28471  fragments);
28472 
28473  if (buckets == 0 || buckets > Hash2FragmentMap::MAX_MAP)
28474  {
28475  jam();
28476  setError(error, CreateTableRef::InvalidFormat, __LINE__);
28477  return;
28478  }
28479 
28480  hm.HashMapBuckets = buckets;
28481  for (Uint32 i = 0; i<buckets; i++)
28482  {
28483  hm.HashMapValues[i] = (i % fragments);
28484  }
28485 
28490  hm.HashMapBuckets *= sizeof(Uint16);
28493  s = SimpleProperties::pack(w,
28494  &hm,
28496  DictHashMapInfo::MappingSize, true);
28497  ndbrequire(s == SimpleProperties::Eof);
28498  w.getPtr(objInfoPtr);
28499 
28500  handle.m_cnt = 1;
28501  handle.m_ptr[CreateHashMapReq::INFO] = objInfoPtr;
28502  }
28503 
28504  Uint32 len = Uint32(strlen(hm.HashMapName) + 1);
28505  Uint32 hash = Rope::hash(hm.HashMapName, len);
28506 
28507  if (ERROR_INSERTED(6205))
28508  {
28509  jam();
28510  CLEAR_ERROR_INSERT_VALUE;
28511  setError(error, 1, __LINE__);
28512  return;
28513  }
28514 
28515  DictObject * objptr = get_object(hm.HashMapName, len, hash);
28516  if(objptr != 0)
28517  {
28518  jam();
28519 
28520  if (! (impl_req->requestType & CreateHashMapReq::CreateIfNotExists))
28521  {
28522  jam();
28523  setError(error, CreateTableRef::TableAlreadyExist, __LINE__);
28524  return;
28525  }
28526 
28531  if (objptr->m_type != DictTabInfo::HashMap)
28532  {
28533  jam();
28534  setError(error, CreateTableRef::TableAlreadyExist, __LINE__);
28535  return;
28536  }
28537 
28538  if (check_write_obj(objptr->m_id,
28539  trans_ptr.p->m_transId,
28540  SchemaFile::SF_CREATE, error))
28541  {
28542  jam();
28543  return;
28544  }
28545 
28546  HashMapPtr hm_ptr;
28547  ndbrequire(c_hash_map_hash.find(hm_ptr, objptr->m_id));
28548 
28549  impl_req->objectId = objptr->m_id;
28550  impl_req->objectVersion = hm_ptr.p->m_object_version;
28551  return;
28552  }
28553  else
28554  {
28555  jam();
28559  impl_req->requestType &= ~Uint32(CreateHashMapReq::CreateIfNotExists);
28560  }
28561 
28562  if (ERROR_INSERTED(6206))
28563  {
28564  jam();
28565  CLEAR_ERROR_INSERT_VALUE;
28566  setError(error, 1, __LINE__);
28567  return;
28568  }
28569 
28570  RopeHandle name;
28571  {
28572  Rope tmp(c_rope_pool, name);
28573  if(!tmp.assign(hm.HashMapName, len, hash))
28574  {
28575  jam();
28576  setError(error, CreateTableRef::OutOfStringBuffer, __LINE__);
28577  return;
28578  }
28579  }
28580 
28581  Uint32 objId = RNIL;
28582  Uint32 objVersion = RNIL;
28583  Uint32 errCode = 0;
28584  Uint32 errLine = 0;
28585  DictObjectPtr obj_ptr; obj_ptr.setNull();
28586  HashMapPtr hm_ptr; hm_ptr.setNull();
28587  Ptr<Hash2FragmentMap> map_ptr; map_ptr.setNull();
28588 
28589  if (master)
28590  {
28591  jam();
28592 
28593  if (ERROR_INSERTED(6207))
28594  {
28595  jam();
28596  CLEAR_ERROR_INSERT_VALUE;
28597  setError(error, 1, __LINE__);
28598  goto error;
28599  }
28600 
28601  objId = impl_req->objectId = getFreeObjId(0);
28602  if (objId == RNIL)
28603  {
28604  jam();
28605  errCode = CreateTableRef::NoMoreTableRecords;
28606  errLine = __LINE__;
28607  goto error;
28608  }
28609 
28610  Uint32 version = getTableEntry(impl_req->objectId)->m_tableVersion;
28611  impl_req->objectVersion = create_obj_inc_schema_version(version);
28612  }
28613  else if (op_ptr.p->m_restart)
28614  {
28615  impl_req->objectId = c_restartRecord.activeTable;
28616  impl_req->objectVersion=c_restartRecord.m_entry.m_tableVersion;
28617  }
28618 
28619  objId = impl_req->objectId;
28620  objVersion = impl_req->objectVersion;
28621 
28622  if (ERROR_INSERTED(6208))
28623  {
28624  jam();
28625  CLEAR_ERROR_INSERT_VALUE;
28626  setError(error, 1, __LINE__);
28627  goto error;
28628  }
28629 
28630  if(!c_obj_pool.seize(obj_ptr))
28631  {
28632  jam();
28633  errCode = CreateTableRef::NoMoreTableRecords;
28634  errLine = __LINE__;
28635  goto error;
28636  }
28637 
28638  new (obj_ptr.p) DictObject;
28639  obj_ptr.p->m_id = objId;
28640  obj_ptr.p->m_type = DictTabInfo::HashMap;
28641  obj_ptr.p->m_ref_count = 0;
28642  obj_ptr.p->m_name = name;
28643  c_obj_hash.add(obj_ptr);
28644 
28645  if (ERROR_INSERTED(6209))
28646  {
28647  jam();
28648  CLEAR_ERROR_INSERT_VALUE;
28649  setError(error, 1, __LINE__);
28650  goto error;
28651  }
28652 
28653  if (!g_hash_map.seize(map_ptr))
28654  {
28655  jam();
28656  errCode = CreateTableRef::NoMoreTableRecords;
28657  errLine = __LINE__;
28658  goto error;
28659  }
28660 
28661  if (ERROR_INSERTED(6210))
28662  {
28663  jam();
28664  CLEAR_ERROR_INSERT_VALUE;
28665  setError(error, 1, __LINE__);
28666  goto error;
28667  }
28668 
28669  if(!c_hash_map_pool.seize(hm_ptr))
28670  {
28671  jam();
28672  errCode = CreateTableRef::NoMoreTableRecords;
28673  errLine = __LINE__;
28674  goto error;
28675  }
28676 
28677  new (hm_ptr.p) HashMapRecord();
28678 
28679  hm_ptr.p->m_object_id = objId;
28680  hm_ptr.p->m_object_version = objVersion;
28681  hm_ptr.p->m_name = name;
28682  hm_ptr.p->m_obj_ptr_i = obj_ptr.i;
28683  hm_ptr.p->m_map_ptr_i = map_ptr.i;
28684  c_hash_map_hash.add(hm_ptr);
28685 
28690  hm.HashMapBuckets /= sizeof(Uint16);
28691 
28692  map_ptr.p->m_cnt = hm.HashMapBuckets;
28693  map_ptr.p->m_object_id = objId;
28694  {
28695  Uint32 tmp = 0;
28696  for (Uint32 i = 0; i<hm.HashMapBuckets; i++)
28697  {
28698  ndbrequire(hm.HashMapValues[i] < 256);
28699  map_ptr.p->m_map[i] = (Uint8)hm.HashMapValues[i];
28700  if (hm.HashMapValues[i] > tmp)
28701  tmp = hm.HashMapValues[i];
28702  }
28703  map_ptr.p->m_fragments = tmp + 1;
28704  }
28705 
28706  if (ERROR_INSERTED(6211))
28707  {
28708  jam();
28709  CLEAR_ERROR_INSERT_VALUE;
28710  setError(error, 1, __LINE__);
28711  goto error;
28712  }
28713 
28714  {
28715  SchemaFile::TableEntry te; te.init();
28716  te.m_tableState = SchemaFile::SF_CREATE;
28717  te.m_tableVersion = objVersion;
28718  te.m_tableType = obj_ptr.p->m_type;
28719  te.m_info_words = objInfoPtr.sz;
28720  te.m_gcp = 0;
28721  te.m_transId = trans_ptr.p->m_transId;
28722 
28723  Uint32 err = trans_log_schema_op(op_ptr, objId, &te);
28724  ndbrequire(err == 0);
28725  }
28726 
28727  saveOpSection(op_ptr, objInfoPtr, 0);
28728  handle.m_ptr[CreateHashMapReq::INFO] = objInfoPtr;
28729  handle.m_cnt = 1;
28730 
28731 #if defined VM_TRACE || defined ERROR_INSERT
28732  ndbout_c("Dbdict: create name=%s,id=%u,obj_ptr_i=%d",
28733  hm.HashMapName, objId, hm_ptr.p->m_obj_ptr_i);
28734 #endif
28735 
28736  return;
28737 
28738 error:
28739  ndbrequire(hasError(error));
28740 
28741  if (!hm_ptr.isNull())
28742  {
28743  jam();
28744  c_hash_map_hash.release(hm_ptr);
28745  }
28746 
28747  if (!map_ptr.isNull())
28748  {
28749  jam();
28750  g_hash_map.release(map_ptr);
28751  }
28752 
28753  if (!obj_ptr.isNull())
28754  {
28755  jam();
28756  release_object(obj_ptr.i);
28757  }
28758  else
28759  {
28760  jam();
28761  Rope tmp(c_rope_pool, name);
28762  tmp.erase();
28763  }
28764 }
28765 
28766 void
28767 Dbdict::createHashMap_abortParse(Signal* signal, SchemaOpPtr op_ptr)
28768 {
28769  D("createHashMap_abortParse" << *op_ptr.p);
28770 
28771  CreateHashMapRecPtr createHashMapPtr;
28772  getOpRec(op_ptr, createHashMapPtr);
28773  CreateHashMapImplReq* impl_req = &createHashMapPtr.p->m_request;
28774 
28775  if (impl_req->requestType & CreateHashMapReq::CreateIfNotExists)
28776  {
28777  jam();
28778  ndbrequire(op_ptr.p->m_orig_entry_id == RNIL);
28779  }
28780 
28781  if (op_ptr.p->m_orig_entry_id != RNIL)
28782  {
28783  jam();
28784 
28785  Ptr<HashMapRecord> hm_ptr;
28786  ndbrequire(c_hash_map_hash.find(hm_ptr, impl_req->objectId));
28787 
28788  release_object(hm_ptr.p->m_obj_ptr_i);
28789  g_hash_map.release(hm_ptr.p->m_map_ptr_i);
28790  c_hash_map_hash.release(hm_ptr);
28791  }
28792 
28793  // wl3600_todo probably nothing..
28794 
28795  sendTransConf(signal, op_ptr);
28796 }
28797 
28798 bool
28799 Dbdict::createHashMap_subOps(Signal* signal, SchemaOpPtr op_ptr)
28800 {
28801  return false;
28802 }
28803 
28804 void
28805 Dbdict::createHashMap_reply(Signal* signal, SchemaOpPtr op_ptr, ErrorInfo error)
28806 {
28807  jam();
28808  D("createHashMap_reply");
28809 
28810  SchemaTransPtr& trans_ptr = op_ptr.p->m_trans_ptr;
28811  CreateHashMapRecPtr createHashMapPtr;
28812  getOpRec(op_ptr, createHashMapPtr);
28813  const CreateHashMapImplReq* impl_req = &createHashMapPtr.p->m_request;
28814 
28815  if (!hasError(error)) {
28816  CreateHashMapConf* conf = (CreateHashMapConf*)signal->getDataPtrSend();
28817  conf->senderRef = reference();
28818  conf->senderData = op_ptr.p->m_clientData;
28819  conf->transId = trans_ptr.p->m_transId;
28820  conf->objectId = impl_req->objectId;
28821  conf->objectVersion = impl_req->objectVersion;
28822 
28823  D(V(conf->objectId) << V(conf->objectVersion));
28824 
28825  Uint32 clientRef = op_ptr.p->m_clientRef;
28826  sendSignal(clientRef, GSN_CREATE_HASH_MAP_CONF, signal,
28827  CreateHashMapConf::SignalLength, JBB);
28828  } else {
28829  jam();
28830  CreateHashMapRef* ref = (CreateHashMapRef*)signal->getDataPtrSend();
28831  ref->senderRef = reference();
28832  ref->senderData = op_ptr.p->m_clientData;
28833  ref->transId = trans_ptr.p->m_transId;
28834  getError(error, ref);
28835 
28836  Uint32 clientRef = op_ptr.p->m_clientRef;
28837  sendSignal(clientRef, GSN_CREATE_HASH_MAP_REF, signal,
28838  CreateHashMapRef::SignalLength, JBB);
28839  }
28840 }
28841 
28842 // CreateHashMap: PREPARE
28843 
28844 void
28845 Dbdict::createHashMap_prepare(Signal* signal, SchemaOpPtr op_ptr)
28846 {
28847  jam();
28848  D("createHashMap_prepare");
28849 
28850  CreateHashMapRecPtr createHashMapPtr;
28851  getOpRec(op_ptr, createHashMapPtr);
28852  CreateHashMapImplReq* impl_req = &createHashMapPtr.p->m_request;
28853 
28854  if (impl_req->requestType & CreateHashMapReq::CreateIfNotExists)
28855  {
28856  jam();
28857  sendTransConf(signal, op_ptr);
28858  return;
28859  }
28860 
28861  Callback cb;
28862  cb.m_callbackData = op_ptr.p->op_key;
28863  cb.m_callbackFunction = safe_cast(&Dbdict::createHashMap_writeObjConf);
28864 
28865  const OpSection& tabInfoSec = getOpSection(op_ptr, 0);
28866  writeTableFile(signal, impl_req->objectId, tabInfoSec, &cb);
28867 }
28868 
28869 void
28870 Dbdict::createHashMap_writeObjConf(Signal* signal, Uint32 op_key, Uint32 ret)
28871 {
28872  SchemaOpPtr op_ptr;
28873  CreateHashMapRecPtr createHashMapPtr;
28874  findSchemaOp(op_ptr, createHashMapPtr, op_key);
28875 
28876  ndbrequire(!op_ptr.isNull());
28877 
28878  sendTransConf(signal, op_ptr);
28879 }
28880 
28881 // CreateHashMap: COMMIT
28882 
28883 void
28884 Dbdict::createHashMap_commit(Signal* signal, SchemaOpPtr op_ptr)
28885 {
28886  jam();
28887  D("createHashMap_commit");
28888 
28889  CreateHashMapRecPtr createHashMapPtr;
28890  getOpRec(op_ptr, createHashMapPtr);
28891 
28892  sendTransConf(signal, op_ptr);
28893 }
28894 
28895 // CreateHashMap: COMPLETE
28896 
28897 void
28898 Dbdict::createHashMap_complete(Signal* signal, SchemaOpPtr op_ptr)
28899 {
28900  jam();
28901  sendTransConf(signal, op_ptr);
28902 }
28903 
28904 // CreateHashMap: ABORT
28905 
28906 void
28907 Dbdict::createHashMap_abortPrepare(Signal* signal, SchemaOpPtr op_ptr)
28908 {
28909  D("createHashMap_abortPrepare" << *op_ptr.p);
28910  // wl3600_todo
28911  sendTransConf(signal, op_ptr);
28912 }
28913 
28914 void
28915 Dbdict::packHashMapIntoPages(SimpleProperties::Writer & w,
28916  Ptr<HashMapRecord> hm_ptr)
28917 {
28918  DictHashMapInfo::HashMap hm; hm.init();
28919 
28920  Ptr<Hash2FragmentMap> map_ptr;
28921  g_hash_map.getPtr(map_ptr, hm_ptr.p->m_map_ptr_i);
28922 
28923  ConstRope r(c_rope_pool, hm_ptr.p->m_name);
28924  r.copy(hm.HashMapName);
28925  hm.HashMapBuckets = map_ptr.p->m_cnt;
28926  hm.HashMapObjectId = hm_ptr.p->m_object_id;
28927  hm.HashMapVersion = hm_ptr.p->m_object_version;
28928 
28929  for (Uint32 i = 0; i<hm.HashMapBuckets; i++)
28930  {
28931  hm.HashMapValues[i] = map_ptr.p->m_map[i];
28932  }
28933 
28938  hm.HashMapBuckets *= sizeof(Uint16);
28940  s = SimpleProperties::pack(w,
28941  &hm,
28943  DictHashMapInfo::MappingSize, true);
28944 
28945  ndbrequire(s == SimpleProperties::Eof);
28946 }
28947 
28948 // CreateHashMap: END
28949 
28950 
28951 // MODULE: debug
28952 
28953 // ErrorInfo
28954 
28955 NdbOut&
28956 operator<<(NdbOut& out, const Dbdict::ErrorInfo& a)
28957 {
28958  a.print(out);
28959  return out;
28960 }
28961 
28962 void
28963 Dbdict::ErrorInfo::print(NdbOut& out) const
28964 {
28965  out << "[";
28966  out << " code: " << errorCode;
28967  out << " line: " << errorLine;
28968  out << " node: " << errorNodeId;
28969  out << " count: " << errorCount;
28970  out << " status: " << errorStatus;
28971  out << " key: " << errorKey;
28972  out << " name: '" << errorObjectName << "'";
28973  out << " ]";
28974 }
28975 
28976 #ifdef VM_TRACE
28977 
28978 // DictObject
28979 
28980 NdbOut&
28981 operator<<(NdbOut& out, const Dbdict::DictObject& a)
28982 {
28983  a.print(out);
28984  return out;
28985 }
28986 
28987 void
28988 Dbdict::DictObject::print(NdbOut& out) const
28989 {
28990  Dbdict* dict = (Dbdict*)globalData.getBlock(DBDICT);
28991  out << " (DictObject";
28992  out << dec << V(m_id);
28993  out << dec << V(m_type);
28994  out << " name:" << dict->copyRope<PATH_MAX>(m_name);
28995  out << dec << V(m_ref_count);
28996  out << dec << V(m_trans_key);
28997  out << dec << V(m_op_ref_count);
28998  out << ")";
28999 }
29000 
29001 
29002 // SchemaOp
29003 
29004 NdbOut&
29005 operator<<(NdbOut& out, const Dbdict::SchemaOp& a)
29006 {
29007  a.print(out);
29008  return out;
29009 }
29010 
29011 void
29012 Dbdict::SchemaOp::print(NdbOut& out) const
29013 {
29014  //Dbdict* dict = (Dbdict*)globalData.getBlock(DBDICT);
29015  const Dbdict::OpInfo& info = m_oprec_ptr.p->m_opInfo;
29016  out << " (SchemaOp";
29017  out << " " << info.m_opType;
29018  out << dec << V(op_key);
29019  if (m_error.errorCode != 0)
29020  out << m_error;
29021  if (m_sections != 0)
29022  out << dec << V(m_sections);
29023  if (m_base_op_ptr_i == RNIL)
29024  out << "-> RNIL";
29025  else
29026  {
29027  out << "-> " << m_base_op_ptr_i;
29028  }
29029 
29030  out << ")";
29031 }
29032 
29033 
29034 
29035 // SchemaTrans
29036 
29037 NdbOut&
29038 operator<<(NdbOut& out, const Dbdict::SchemaTrans& a)
29039 {
29040  a.print(out);
29041  return out;
29042 }
29043 
29044 void
29045 Dbdict::SchemaTrans::print(NdbOut& out) const
29046 {
29047  out << " (SchemaTrans";
29048  out << dec << V(m_state);
29049  out << dec << V(trans_key);
29050  out << dec << V(m_isMaster);
29051  out << hex << V(m_clientRef);
29052  out << hex << V(m_transId);
29053  out << dec << V(m_clientState);
29054  out << hex << V(m_clientFlags);
29055  out << ")";
29056 }
29057 
29058 // TxHandle
29059 
29060 NdbOut&
29061 operator<<(NdbOut& out, const Dbdict::TxHandle& a)
29062 {
29063  a.print(out);
29064  return out;
29065 }
29066 
29067 void
29068 Dbdict::TxHandle::print(NdbOut& out) const
29069 {
29070  out << " (TxHandle";
29071  out << dec << V(tx_key);
29072  out << hex << V(m_transId);
29073  out << dec << V(m_transKey);
29074  out << dec << V(m_clientState);
29075  out << hex << V(m_clientFlags);
29076  out << hex << V(m_takeOverRef);
29077  out << hex << V(m_takeOverTransId);
29078  out << ")";
29079 }
29080 
29081 // check consistency when no schema trans is active
29082 
29083 #undef SZ
29084 #define SZ PATH_MAX
29085 
29086 void
29087 Dbdict::check_consistency()
29088 {
29089  D("check_consistency");
29090 
29091 #if 0
29092  // schema file entries // mis-named "tables"
29093  TableRecordPtr tablePtr;
29094  for (tablePtr.i = 0;
29095  tablePtr.i < c_tableRecordPool.getSize();
29096  tablePtr.i++) {
29097  if (check_read_obj(tablePtr.i,
29098 
29099  c_tableRecordPool.getPtr(tablePtr);
29100 
29101  switch (tablePtr.p->tabState) {
29102  case TableRecord::NOT_DEFINED:
29103  continue;
29104  default:
29105  break;
29106  }
29107  check_consistency_entry(tablePtr);
29108  }
29109 #endif
29110 
29111  // triggers // should be in schema file
29112  TriggerRecordPtr triggerPtr;
29113  for (triggerPtr.i = 0;
29114  triggerPtr.i < c_triggerRecordPool.getSize();
29115  triggerPtr.i++) {
29116  c_triggerRecordPool.getPtr(triggerPtr);
29117  switch (triggerPtr.p->triggerState) {
29118  case TriggerRecord::TS_NOT_DEFINED:
29119  continue;
29120  default:
29121  break;
29122  }
29123  check_consistency_trigger(triggerPtr);
29124  }
29125 }
29126 
29127 void
29128 Dbdict::check_consistency_entry(TableRecordPtr tablePtr)
29129 {
29130  switch (tablePtr.p->tableType) {
29131  case DictTabInfo::SystemTable:
29132  jam();
29133  check_consistency_table(tablePtr);
29134  break;
29135  case DictTabInfo::UserTable:
29136  jam();
29137  check_consistency_table(tablePtr);
29138  break;
29139  case DictTabInfo::UniqueHashIndex:
29140  jam();
29141  check_consistency_index(tablePtr);
29142  break;
29143  case DictTabInfo::OrderedIndex:
29144  jam();
29145  check_consistency_index(tablePtr);
29146  break;
29149  case DictTabInfo::Datafile:
29150  case DictTabInfo::Undofile:
29151  jam();
29152  break;
29153  default:
29154  ndbrequire(false);
29155  break;
29156  }
29157 }
29158 
29159 void
29160 Dbdict::check_consistency_table(TableRecordPtr tablePtr)
29161 {
29162  D("table " << copyRope<SZ>(tablePtr.p->tableName));
29163  ndbrequire(tablePtr.p->tableId == tablePtr.i);
29164 
29165  switch (tablePtr.p->tableType) {
29166  case DictTabInfo::SystemTable: // should just be "Table"
29167  jam();
29168  break;
29169  case DictTabInfo::UserTable: // should just be "Table"
29170  jam();
29171  break;
29172  default:
29173  ndbrequire(false);
29174  break;
29175  }
29176 
29177  DictObjectPtr obj_ptr;
29178  obj_ptr.i = tablePtr.p->m_obj_ptr_i;
29179  ndbrequire(obj_ptr.i != RNIL);
29180  c_obj_pool.getPtr(obj_ptr);
29181  check_consistency_object(obj_ptr);
29182 
29183  ndbrequire(obj_ptr.p->m_id == tablePtr.p->tableId);
29184  ndbrequire(!strcmp(
29185  copyRope<SZ>(obj_ptr.p->m_name),
29186  copyRope<SZ>(tablePtr.p->tableName)));
29187 }
29188 
29189 void
29190 Dbdict::check_consistency_index(TableRecordPtr indexPtr)
29191 {
29192  D("index " << copyRope<SZ>(indexPtr.p->tableName));
29193  ndbrequire(indexPtr.p->tableId == indexPtr.i);
29194 
29195  switch (indexPtr.p->indexState) { // these states are non-sense
29196  case TableRecord::IS_ONLINE:
29197  jam();
29198  break;
29199  default:
29200  ndbrequire(false);
29201  break;
29202  }
29203 
29204  TableRecordPtr tablePtr;
29205  tablePtr.i = indexPtr.p->primaryTableId;
29206  ndbrequire(tablePtr.i != RNIL);
29207  c_tableRecordPool.getPtr(tablePtr);
29208  check_consistency_table(tablePtr);
29209 
29210  bool is_unique_index = false;
29211  switch (indexPtr.p->tableType) {
29212  case DictTabInfo::UniqueHashIndex:
29213  jam();
29214  is_unique_index = true;
29215  break;
29216  case DictTabInfo::OrderedIndex:
29217  jam();
29218  break;
29219  default:
29220  ndbrequire(false);
29221  break;
29222  }
29223 
29224  Ptr<TriggerRecord> triggerPtr;
29225  triggerPtr.i = indexPtr.p->triggerId;
29226  ndbrequire(triggerPtr.i != RNIL);
29227  c_triggerRecordPool.getPtr(triggerPtr);
29228 
29229  ndbrequire(triggerPtr.p->tableId == tablePtr.p->tableId);
29230  ndbrequire(triggerPtr.p->indexId == indexPtr.p->tableId);
29231  ndbrequire(triggerPtr.p->triggerId == triggerPtr.i);
29232 
29233  check_consistency_trigger(triggerPtr);
29234 
29235  TriggerInfo ti;
29236  TriggerInfo::unpackTriggerInfo(triggerPtr.p->triggerInfo, ti);
29237  ndbrequire(ti.triggerEvent == TriggerEvent::TE_CUSTOM);
29238 
29239  DictObjectPtr obj_ptr;
29240  obj_ptr.i = triggerPtr.p->m_obj_ptr_i;
29241  ndbrequire(obj_ptr.i != RNIL);
29242  c_obj_pool.getPtr(obj_ptr);
29243  check_consistency_object(obj_ptr);
29244 
29245  ndbrequire(obj_ptr.p->m_id == triggerPtr.p->triggerId);
29246  ndbrequire(!strcmp(copyRope<SZ>(obj_ptr.p->m_name),
29247  copyRope<SZ>(triggerPtr.p->triggerName)));
29248 }
29249 
29250 void
29251 Dbdict::check_consistency_trigger(TriggerRecordPtr triggerPtr)
29252 {
29253  if (! (triggerPtr.p->triggerState == TriggerRecord::TS_FAKE_UPGRADE))
29254  {
29255  ndbrequire(triggerPtr.p->triggerState == TriggerRecord::TS_ONLINE);
29256  }
29257  ndbrequire(triggerPtr.p->triggerId == triggerPtr.i);
29258 
29259  TableRecordPtr tablePtr;
29260  tablePtr.i = triggerPtr.p->tableId;
29261  ndbrequire(tablePtr.i != RNIL);
29262  c_tableRecordPool.getPtr(tablePtr);
29263  check_consistency_table(tablePtr);
29264 
29265  if (triggerPtr.p->indexId != RNIL)
29266  {
29267  jam();
29268  TableRecordPtr indexPtr;
29269  indexPtr.i = triggerPtr.p->indexId;
29270  c_tableRecordPool.getPtr(indexPtr);
29271  ndbrequire(check_read_obj(indexPtr.i) == 0);
29272  ndbrequire(indexPtr.p->indexState == TableRecord::IS_ONLINE);
29273  TriggerInfo ti;
29274  TriggerInfo::unpackTriggerInfo(triggerPtr.p->triggerInfo, ti);
29275  switch (ti.triggerEvent) {
29276  case TriggerEvent::TE_CUSTOM:
29277  if (! (triggerPtr.p->triggerState == TriggerRecord::TS_FAKE_UPGRADE))
29278  {
29279  ndbrequire(triggerPtr.i == indexPtr.p->triggerId);
29280  }
29281  break;
29282  default:
29283  ndbrequire(false);
29284  break;
29285  }
29286  } else {
29287  TriggerInfo ti;
29288  TriggerInfo::unpackTriggerInfo(triggerPtr.p->triggerInfo, ti);
29289  ndbrequire(ti.triggerType == TriggerType::REORG_TRIGGER);
29290  }
29291 }
29292 
29293 void
29294 Dbdict::check_consistency_object(DictObjectPtr obj_ptr)
29295 {
29296  ndbrequire(obj_ptr.p->m_trans_key == 0);
29297  ndbrequire(obj_ptr.p->m_op_ref_count == 0);
29298 }
29299 
29300 #endif
29301 
29302 void
29303 Dbdict::send_event(Signal* signal,
29304  SchemaTransPtr& trans_ptr,
29305  Uint32 ev,
29306  Uint32 id,
29307  Uint32 version,
29308  Uint32 type)
29309 {
29310  if (!trans_ptr.p->m_isMaster)
29311  {
29312  return;
29313  }
29314 
29315  switch(ev){
29316  case NDB_LE_CreateSchemaObject:
29317  case NDB_LE_AlterSchemaObject:
29318  case NDB_LE_DropSchemaObject:
29319  break;
29320  default:
29321  ndbassert(false);
29322  return;
29323  }
29324  signal->theData[0] = ev;
29325  signal->theData[1] = id;
29326  signal->theData[2] = version;
29327  signal->theData[3] = type;
29328  signal->theData[4] = refToNode(trans_ptr.p->m_clientRef);
29329  sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 5, JBB);
29330 }