~vlad-lesin/percona-server/mysql-5.0.33-original

« back to all changes in this revision

Viewing changes to ndb/src/kernel/blocks/dbdict/Dbdict.cpp

  • Committer: Vlad Lesin
  • Date: 2012-07-31 09:21:34 UTC
  • Revision ID: vladislav.lesin@percona.com-20120731092134-zfodx022b7992wsi
VirginĀ 5.0.33

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2003 MySQL AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; either version 2 of the License, or
 
6
   (at your option) any later version.
 
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
16
 
 
17
#include <ndb_global.h>
 
18
#include <my_sys.h>
 
19
 
 
20
#define DBDICT_C
 
21
#include "Dbdict.hpp"
 
22
 
 
23
#include <ndb_limits.h>
 
24
#include <NdbOut.hpp>
 
25
#include <Properties.hpp>
 
26
#include <Configuration.hpp>
 
27
#include <SectionReader.hpp>
 
28
#include <SimpleProperties.hpp>
 
29
#include <AttributeHeader.hpp>
 
30
#include <KeyDescriptor.hpp>
 
31
#include <signaldata/DictSchemaInfo.hpp>
 
32
#include <signaldata/DictTabInfo.hpp>
 
33
#include <signaldata/DropTabFile.hpp>
 
34
 
 
35
#include <signaldata/EventReport.hpp>
 
36
#include <signaldata/FsCloseReq.hpp>
 
37
#include <signaldata/FsConf.hpp>
 
38
#include <signaldata/FsOpenReq.hpp>
 
39
#include <signaldata/FsReadWriteReq.hpp>
 
40
#include <signaldata/FsRef.hpp>
 
41
#include <signaldata/GetTabInfo.hpp>
 
42
#include <signaldata/GetTableId.hpp>
 
43
#include <signaldata/HotSpareRep.hpp>
 
44
#include <signaldata/NFCompleteRep.hpp>
 
45
#include <signaldata/NodeFailRep.hpp>
 
46
#include <signaldata/ReadNodesConf.hpp>
 
47
#include <signaldata/RelTabMem.hpp>
 
48
#include <signaldata/WaitGCP.hpp>
 
49
#include <signaldata/ListTables.hpp>
 
50
 
 
51
#include <signaldata/CreateTrig.hpp>
 
52
#include <signaldata/AlterTrig.hpp>
 
53
#include <signaldata/DropTrig.hpp>
 
54
#include <signaldata/CreateIndx.hpp>
 
55
#include <signaldata/DropIndx.hpp>
 
56
#include <signaldata/BuildIndx.hpp>
 
57
 
 
58
#include <signaldata/CreateEvnt.hpp>
 
59
#include <signaldata/UtilPrepare.hpp>
 
60
#include <signaldata/UtilExecute.hpp>
 
61
#include <signaldata/UtilRelease.hpp>
 
62
#include <signaldata/SumaImpl.hpp> 
 
63
#include <GrepError.hpp>
 
64
//#include <signaldata/DropEvnt.hpp>
 
65
 
 
66
#include <signaldata/LqhFrag.hpp>
 
67
 
 
68
#include <signaldata/DiAddTab.hpp>
 
69
#include <signaldata/DihStartTab.hpp>
 
70
 
 
71
#include <signaldata/DropTable.hpp>
 
72
#include <signaldata/DropTab.hpp>
 
73
#include <signaldata/PrepDropTab.hpp>
 
74
 
 
75
#include <signaldata/CreateTable.hpp>
 
76
#include <signaldata/AlterTable.hpp>
 
77
#include <signaldata/AlterTab.hpp>
 
78
#include <signaldata/CreateFragmentation.hpp>
 
79
#include <signaldata/CreateTab.hpp>
 
80
#include <NdbSleep.h>
 
81
#include <signaldata/ApiBroadcast.hpp>
 
82
 
 
83
#define ZNOT_FOUND 626
 
84
#define ZALREADYEXIST 630
 
85
 
 
86
//#define EVENT_PH2_DEBUG
 
87
//#define EVENT_PH3_DEBUG
 
88
//#define EVENT_DEBUG
 
89
 
 
90
#define EVENT_TRACE \
 
91
//  ndbout_c("Event debug trace: File: %s Line: %u", __FILE__, __LINE__)
 
92
 
 
93
#define DIV(x,y) (((x)+(y)-1)/(y))
 
94
#include <ndb_version.h>
 
95
 
 
96
static
 
97
Uint32
 
98
alter_table_inc_schema_version(Uint32 old)
 
99
{
 
100
   return (old & 0x00FFFFFF) + ((old + 0x1000000) & 0xFF000000);
 
101
}
 
102
 
 
103
static
 
104
Uint32
 
105
alter_table_dec_schema_version(Uint32 old)
 
106
{
 
107
  return (old & 0x00FFFFFF) + ((old - 0x1000000) & 0xFF000000);
 
108
}
 
109
 
 
110
static
 
111
Uint32
 
112
create_table_inc_schema_version(Uint32 old)
 
113
{
 
114
  return (old + 0x00000001) & 0x00FFFFFF;
 
115
}
 
116
 
 
117
/* **************************************************************** */
 
118
/* ---------------------------------------------------------------- */
 
119
/* MODULE:          GENERAL MODULE -------------------------------- */
 
120
/* ---------------------------------------------------------------- */
 
121
/*                                                                  */
 
122
/* This module contains general stuff. Mostly debug signals and     */
 
123
/* general signals that go into a specific module after checking a  */
 
124
/* state variable. Also general subroutines used by many.           */
 
125
/* ---------------------------------------------------------------- */
 
126
/* **************************************************************** */
 
127
 
 
128
/* ---------------------------------------------------------------- */
 
129
// This signal is used to dump states of various variables in the
 
130
// block by command.
 
131
/* ---------------------------------------------------------------- */
 
132
void
 
133
Dbdict::execDUMP_STATE_ORD(Signal* signal)
 
134
{
 
135
  jamEntry();
 
136
 
 
137
#ifdef VM_TRACE
 
138
  if(signal->theData[0] == 1222){
 
139
    const Uint32 tab = signal->theData[1];
 
140
    PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
 
141
    req->senderRef = reference();
 
142
    req->senderData = 1222;
 
143
    req->tableId = tab;
 
144
    sendSignal(DBLQH_REF, GSN_PREP_DROP_TAB_REQ, signal,
 
145
               PrepDropTabReq::SignalLength, JBB);
 
146
  }
 
147
 
 
148
  if(signal->theData[0] == 1223){
 
149
    const Uint32 tab = signal->theData[1];
 
150
    PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
 
151
    req->senderRef = reference();
 
152
    req->senderData = 1222;
 
153
    req->tableId = tab;
 
154
    sendSignal(DBTC_REF, GSN_PREP_DROP_TAB_REQ, signal,
 
155
               PrepDropTabReq::SignalLength, JBB);
 
156
  }
 
157
 
 
158
  if(signal->theData[0] == 1224){
 
159
    const Uint32 tab = signal->theData[1];
 
160
    PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
 
161
    req->senderRef = reference();
 
162
    req->senderData = 1222;
 
163
    req->tableId = tab;
 
164
    sendSignal(DBDIH_REF, GSN_PREP_DROP_TAB_REQ, signal,
 
165
               PrepDropTabReq::SignalLength, JBB);
 
166
  }
 
167
 
 
168
  if(signal->theData[0] == 1225){
 
169
    const Uint32 tab = signal->theData[1];
 
170
    const Uint32 ver = signal->theData[2];
 
171
    TableRecordPtr tabRecPtr;
 
172
    c_tableRecordPool.getPtr(tabRecPtr, tab);
 
173
    DropTableReq * req = (DropTableReq*)signal->getDataPtr();
 
174
    req->senderData = 1225;
 
175
    req->senderRef = numberToRef(1,1);
 
176
    req->tableId = tab;
 
177
    req->tableVersion = tabRecPtr.p->tableVersion + ver;
 
178
    sendSignal(DBDICT_REF, GSN_DROP_TABLE_REQ, signal,
 
179
               DropTableReq::SignalLength, JBB);
 
180
  }
 
181
#endif  
 
182
  
 
183
  return;
 
184
}//Dbdict::execDUMP_STATE_ORD()
 
185
 
 
186
/* ---------------------------------------------------------------- */
 
187
/* ---------------------------------------------------------------- */
 
188
// CONTINUEB is used when a real-time break is needed for long
 
189
// processes.
 
190
/* ---------------------------------------------------------------- */
 
191
/* ---------------------------------------------------------------- */
 
192
void Dbdict::execCONTINUEB(Signal* signal) 
 
193
{
 
194
  jamEntry();
 
195
  switch (signal->theData[0]) {
 
196
  case ZPACK_TABLE_INTO_PAGES :
 
197
    jam();
 
198
    packTableIntoPages(signal, signal->theData[1], signal->theData[2]);
 
199
    break;
 
200
 
 
201
  case ZSEND_GET_TAB_RESPONSE :
 
202
    jam();
 
203
    sendGetTabResponse(signal);
 
204
    break;
 
205
 
 
206
  case ZDICT_LOCK_POLL:
 
207
    jam();
 
208
    checkDictLockQueue(signal, true);
 
209
    break;
 
210
 
 
211
  default :
 
212
    ndbrequire(false);
 
213
    break;
 
214
  }//switch
 
215
  return;
 
216
}//execCONTINUEB()
 
217
 
 
218
/* ---------------------------------------------------------------- */
 
219
/* ---------------------------------------------------------------- */
 
220
// Routine to handle pack table into pages.
 
221
/* ---------------------------------------------------------------- */
 
222
/* ---------------------------------------------------------------- */
 
223
 
 
224
void Dbdict::packTableIntoPages(Signal* signal, Uint32 tableId, Uint32 pageId)
 
225
{
 
226
 
 
227
  PageRecordPtr pagePtr;
 
228
  TableRecordPtr tablePtr;
 
229
  c_pageRecordArray.getPtr(pagePtr, pageId);
 
230
  
 
231
  memset(&pagePtr.p->word[0], 0, 4 * ZPAGE_HEADER_SIZE);
 
232
  c_tableRecordPool.getPtr(tablePtr, tableId);
 
233
  LinearWriter w(&pagePtr.p->word[ZPAGE_HEADER_SIZE], 
 
234
                 8 * ZSIZE_OF_PAGES_IN_WORDS);
 
235
 
 
236
  w.first();
 
237
  packTableIntoPagesImpl(w, tablePtr, signal);
 
238
    
 
239
  Uint32 wordsOfTable = w.getWordsUsed();
 
240
  Uint32 pagesUsed = 
 
241
    DIV(wordsOfTable + ZPAGE_HEADER_SIZE, ZSIZE_OF_PAGES_IN_WORDS);
 
242
  pagePtr.p->word[ZPOS_CHECKSUM] = 
 
243
    computeChecksum(&pagePtr.p->word[0], pagesUsed * ZSIZE_OF_PAGES_IN_WORDS);
 
244
  
 
245
  switch (c_packTable.m_state) {
 
246
  case PackTable::PTS_IDLE:
 
247
  case PackTable::PTS_ADD_TABLE_MASTER:
 
248
  case PackTable::PTS_ADD_TABLE_SLAVE:
 
249
  case PackTable::PTS_RESTART:
 
250
    ndbrequire(false);
 
251
    break;
 
252
  case PackTable::PTS_GET_TAB:
 
253
    jam();
 
254
    c_retrieveRecord.retrievedNoOfPages = pagesUsed;
 
255
    c_retrieveRecord.retrievedNoOfWords = wordsOfTable;
 
256
    sendGetTabResponse(signal);
 
257
    return;
 
258
    break;
 
259
  }//switch
 
260
  ndbrequire(false);
 
261
  return;
 
262
}//packTableIntoPages()
 
263
 
 
264
void
 
265
Dbdict::packTableIntoPagesImpl(SimpleProperties::Writer & w,
 
266
                               TableRecordPtr tablePtr,
 
267
                               Signal* signal){
 
268
  
 
269
  w.add(DictTabInfo::TableName, tablePtr.p->tableName);
 
270
  w.add(DictTabInfo::TableId, tablePtr.i);
 
271
#ifdef HAVE_TABLE_REORG
 
272
  w.add(DictTabInfo::SecondTableId, tablePtr.p->secondTable);
 
273
#else
 
274
  w.add(DictTabInfo::SecondTableId, (Uint32)0);
 
275
#endif
 
276
  w.add(DictTabInfo::TableVersion, tablePtr.p->tableVersion);
 
277
  w.add(DictTabInfo::NoOfKeyAttr, tablePtr.p->noOfPrimkey);
 
278
  w.add(DictTabInfo::NoOfAttributes, tablePtr.p->noOfAttributes);
 
279
  w.add(DictTabInfo::NoOfNullable, tablePtr.p->noOfNullAttr);
 
280
  w.add(DictTabInfo::NoOfVariable, (Uint32)0);
 
281
  w.add(DictTabInfo::KeyLength, tablePtr.p->tupKeyLength);
 
282
  
 
283
  w.add(DictTabInfo::TableLoggedFlag, tablePtr.p->storedTable);
 
284
  w.add(DictTabInfo::MinLoadFactor, tablePtr.p->minLoadFactor);
 
285
  w.add(DictTabInfo::MaxLoadFactor, tablePtr.p->maxLoadFactor);
 
286
  w.add(DictTabInfo::TableKValue, tablePtr.p->kValue);
 
287
  w.add(DictTabInfo::FragmentTypeVal, tablePtr.p->fragmentType);
 
288
  w.add(DictTabInfo::TableTypeVal, tablePtr.p->tableType);
 
289
  w.add(DictTabInfo::MaxRowsLow, tablePtr.p->maxRowsLow);
 
290
  w.add(DictTabInfo::MaxRowsHigh, tablePtr.p->maxRowsHigh);
 
291
  w.add(DictTabInfo::MinRowsLow, tablePtr.p->minRowsLow);
 
292
  w.add(DictTabInfo::MinRowsHigh, tablePtr.p->minRowsHigh);
 
293
  
 
294
  if(!signal)
 
295
  {
 
296
    w.add(DictTabInfo::FragmentCount, tablePtr.p->fragmentCount);
 
297
  }
 
298
  else
 
299
  {
 
300
    Uint32 * theData = signal->getDataPtrSend();
 
301
    CreateFragmentationReq * const req = (CreateFragmentationReq*)theData;
 
302
    req->senderRef = 0;
 
303
    req->senderData = RNIL;
 
304
    req->fragmentationType = tablePtr.p->fragmentType;
 
305
    req->noOfFragments = 0;
 
306
    req->fragmentNode = 0;
 
307
    req->primaryTableId = tablePtr.i;
 
308
    EXECUTE_DIRECT(DBDIH, GSN_CREATE_FRAGMENTATION_REQ, signal,
 
309
                   CreateFragmentationReq::SignalLength);
 
310
    if(signal->theData[0] == 0)
 
311
    {
 
312
      Uint16 *data = (Uint16*)&signal->theData[25];
 
313
      Uint32 count = 2 + data[0] * data[1];
 
314
      w.add(DictTabInfo::FragmentDataLen, 2*count);
 
315
      w.add(DictTabInfo::FragmentData, data, 2*count);
 
316
    }
 
317
  }
 
318
  
 
319
  if (tablePtr.p->primaryTableId != RNIL){
 
320
    TableRecordPtr primTab;
 
321
    c_tableRecordPool.getPtr(primTab, tablePtr.p->primaryTableId);
 
322
    w.add(DictTabInfo::PrimaryTable, primTab.p->tableName);
 
323
    w.add(DictTabInfo::PrimaryTableId, tablePtr.p->primaryTableId);
 
324
    w.add(DictTabInfo::IndexState, tablePtr.p->indexState);
 
325
    w.add(DictTabInfo::InsertTriggerId, tablePtr.p->insertTriggerId);
 
326
    w.add(DictTabInfo::UpdateTriggerId, tablePtr.p->updateTriggerId);
 
327
    w.add(DictTabInfo::DeleteTriggerId, tablePtr.p->deleteTriggerId);
 
328
    w.add(DictTabInfo::CustomTriggerId, tablePtr.p->customTriggerId);
 
329
  }
 
330
  w.add(DictTabInfo::FrmLen, tablePtr.p->frmLen);
 
331
  w.add(DictTabInfo::FrmData, tablePtr.p->frmData, tablePtr.p->frmLen);
 
332
  
 
333
  Uint32 nextAttribute = tablePtr.p->firstAttribute;
 
334
  AttributeRecordPtr attrPtr;
 
335
  do {
 
336
    jam();
 
337
    c_attributeRecordPool.getPtr(attrPtr, nextAttribute);
 
338
    
 
339
    w.add(DictTabInfo::AttributeName, attrPtr.p->attributeName);
 
340
    w.add(DictTabInfo::AttributeId, attrPtr.p->attributeId);
 
341
    w.add(DictTabInfo::AttributeKeyFlag, attrPtr.p->tupleKey > 0);
 
342
    
 
343
    const Uint32 desc = attrPtr.p->attributeDescriptor;
 
344
    const Uint32 attrType = AttributeDescriptor::getType(desc);
 
345
    const Uint32 attrSize = AttributeDescriptor::getSize(desc);
 
346
    const Uint32 arraySize = AttributeDescriptor::getArraySize(desc);
 
347
    const Uint32 nullable = AttributeDescriptor::getNullable(desc);
 
348
    const Uint32 DKey = AttributeDescriptor::getDKey(desc);
 
349
 
 
350
    // AttributeType deprecated
 
351
    w.add(DictTabInfo::AttributeSize, attrSize);
 
352
    w.add(DictTabInfo::AttributeArraySize, arraySize);
 
353
    w.add(DictTabInfo::AttributeNullableFlag, nullable);
 
354
    w.add(DictTabInfo::AttributeDKey, DKey);
 
355
    w.add(DictTabInfo::AttributeExtType, attrType);
 
356
    w.add(DictTabInfo::AttributeExtPrecision, attrPtr.p->extPrecision);
 
357
    w.add(DictTabInfo::AttributeExtScale, attrPtr.p->extScale);
 
358
    w.add(DictTabInfo::AttributeExtLength, attrPtr.p->extLength);
 
359
    w.add(DictTabInfo::AttributeAutoIncrement, 
 
360
          (Uint32)attrPtr.p->autoIncrement);
 
361
    w.add(DictTabInfo::AttributeDefaultValue, attrPtr.p->defaultValue);
 
362
    
 
363
    w.add(DictTabInfo::AttributeEnd, 1);
 
364
    nextAttribute = attrPtr.p->nextAttrInTable;
 
365
  } while (nextAttribute != RNIL);
 
366
  
 
367
  w.add(DictTabInfo::TableEnd, 1);
 
368
}
 
369
 
 
370
/* ---------------------------------------------------------------- */
 
371
/* ---------------------------------------------------------------- */
 
372
// The routines to handle responses from file system.
 
373
/* ---------------------------------------------------------------- */
 
374
/* ---------------------------------------------------------------- */
 
375
 
 
376
/* ---------------------------------------------------------------- */
 
377
// A file was successfully closed.
 
378
/* ---------------------------------------------------------------- */
 
379
void Dbdict::execFSCLOSECONF(Signal* signal) 
 
380
{
 
381
  FsConnectRecordPtr fsPtr;
 
382
  FsConf * const fsConf = (FsConf *)&signal->theData[0];
 
383
  jamEntry();
 
384
  c_fsConnectRecordPool.getPtr(fsPtr, fsConf->userPointer);
 
385
  switch (fsPtr.p->fsState) {
 
386
  case FsConnectRecord::CLOSE_WRITE_SCHEMA:
 
387
    jam();
 
388
    closeWriteSchemaConf(signal, fsPtr);
 
389
    break;
 
390
  case FsConnectRecord::CLOSE_READ_SCHEMA:
 
391
    jam();
 
392
    closeReadSchemaConf(signal, fsPtr);
 
393
    break;
 
394
  case FsConnectRecord::CLOSE_READ_TAB_FILE:
 
395
    jam();
 
396
    closeReadTableConf(signal, fsPtr);
 
397
    break;
 
398
  case FsConnectRecord::CLOSE_WRITE_TAB_FILE:
 
399
    jam();
 
400
    closeWriteTableConf(signal, fsPtr);
 
401
    break;
 
402
  case FsConnectRecord::OPEN_READ_SCHEMA2:
 
403
    openSchemaFile(signal, 1, fsPtr.i, false, false);
 
404
    break;
 
405
  default:
 
406
    jamLine((fsPtr.p->fsState & 0xFFF));
 
407
    ndbrequire(false);
 
408
    break;
 
409
  }//switch
 
410
}//execFSCLOSECONF()
 
411
 
 
412
 
 
413
/* ---------------------------------------------------------------- */
 
414
// A file was successfully opened.
 
415
/* ---------------------------------------------------------------- */
 
416
void Dbdict::execFSOPENCONF(Signal* signal) 
 
417
{
 
418
  FsConnectRecordPtr fsPtr;
 
419
  jamEntry();
 
420
  FsConf * const fsConf = (FsConf *)&signal->theData[0];
 
421
  c_fsConnectRecordPool.getPtr(fsPtr, fsConf->userPointer);
 
422
 
 
423
  Uint32 filePointer = fsConf->filePointer;
 
424
  fsPtr.p->filePtr = filePointer;
 
425
  switch (fsPtr.p->fsState) {
 
426
  case FsConnectRecord::OPEN_WRITE_SCHEMA:
 
427
    jam();
 
428
    fsPtr.p->fsState = FsConnectRecord::WRITE_SCHEMA;
 
429
    writeSchemaFile(signal, filePointer, fsPtr.i);
 
430
    break;
 
431
  case FsConnectRecord::OPEN_READ_SCHEMA1:
 
432
    jam();
 
433
    fsPtr.p->fsState = FsConnectRecord::READ_SCHEMA1;
 
434
    readSchemaFile(signal, filePointer, fsPtr.i);
 
435
    break;
 
436
  case FsConnectRecord::OPEN_READ_SCHEMA2:
 
437
    jam();
 
438
    fsPtr.p->fsState = FsConnectRecord::READ_SCHEMA2;
 
439
    readSchemaFile(signal, filePointer, fsPtr.i);
 
440
    break;
 
441
  case FsConnectRecord::OPEN_READ_TAB_FILE1:
 
442
    jam();
 
443
    fsPtr.p->fsState = FsConnectRecord::READ_TAB_FILE1;
 
444
    readTableFile(signal, filePointer, fsPtr.i);
 
445
    break;
 
446
  case FsConnectRecord::OPEN_READ_TAB_FILE2:
 
447
    jam();
 
448
    fsPtr.p->fsState = FsConnectRecord::READ_TAB_FILE2;
 
449
    readTableFile(signal, filePointer, fsPtr.i);
 
450
    break;
 
451
  case FsConnectRecord::OPEN_WRITE_TAB_FILE:
 
452
    jam();
 
453
    fsPtr.p->fsState = FsConnectRecord::WRITE_TAB_FILE;
 
454
    writeTableFile(signal, filePointer, fsPtr.i);
 
455
    break;
 
456
  default:
 
457
    jamLine((fsPtr.p->fsState & 0xFFF));
 
458
    ndbrequire(false);
 
459
    break;
 
460
  }//switch
 
461
}//execFSOPENCONF()
 
462
 
 
463
/* ---------------------------------------------------------------- */
 
464
// An open file was refused.
 
465
/* ---------------------------------------------------------------- */
 
466
void Dbdict::execFSOPENREF(Signal* signal) 
 
467
{
 
468
  jamEntry();
 
469
  FsRef * const fsRef = (FsRef *)&signal->theData[0];
 
470
  FsConnectRecordPtr fsPtr;
 
471
  c_fsConnectRecordPool.getPtr(fsPtr, fsRef->userPointer);
 
472
  switch (fsPtr.p->fsState) {
 
473
  case FsConnectRecord::OPEN_READ_SCHEMA1:
 
474
    jam();
 
475
    openReadSchemaRef(signal, fsPtr);
 
476
    return;
 
477
  case FsConnectRecord::OPEN_READ_TAB_FILE1:
 
478
    jam();
 
479
    openReadTableRef(signal, fsPtr);
 
480
    return;
 
481
  default:
 
482
    break;
 
483
  }//switch
 
484
  {
 
485
    char msg[100];
 
486
    sprintf(msg, "File system open failed during FsConnectRecord state %d", (Uint32)fsPtr.p->fsState);
 
487
    fsRefError(signal,__LINE__,msg);
 
488
  }
 
489
}//execFSOPENREF()
 
490
 
 
491
/* ---------------------------------------------------------------- */
 
492
// A file was successfully read.
 
493
/* ---------------------------------------------------------------- */
 
494
void Dbdict::execFSREADCONF(Signal* signal) 
 
495
{
 
496
  jamEntry();
 
497
  FsConf * const fsConf = (FsConf *)&signal->theData[0];
 
498
  FsConnectRecordPtr fsPtr;
 
499
  c_fsConnectRecordPool.getPtr(fsPtr, fsConf->userPointer);
 
500
  switch (fsPtr.p->fsState) {
 
501
  case FsConnectRecord::READ_SCHEMA1:
 
502
  case FsConnectRecord::READ_SCHEMA2:
 
503
    readSchemaConf(signal ,fsPtr);
 
504
    break;
 
505
  case FsConnectRecord::READ_TAB_FILE1:
 
506
  case FsConnectRecord::READ_TAB_FILE2:
 
507
    jam();
 
508
    readTableConf(signal ,fsPtr);
 
509
    break;
 
510
  default:
 
511
    jamLine((fsPtr.p->fsState & 0xFFF));
 
512
    ndbrequire(false);
 
513
    break;
 
514
  }//switch
 
515
}//execFSREADCONF()
 
516
 
 
517
/* ---------------------------------------------------------------- */
 
518
// A read file was refused.
 
519
/* ---------------------------------------------------------------- */
 
520
void Dbdict::execFSREADREF(Signal* signal) 
 
521
{
 
522
  jamEntry();
 
523
  FsRef * const fsRef = (FsRef *)&signal->theData[0];
 
524
  FsConnectRecordPtr fsPtr;
 
525
  c_fsConnectRecordPool.getPtr(fsPtr, fsRef->userPointer);
 
526
  switch (fsPtr.p->fsState) {
 
527
  case FsConnectRecord::READ_SCHEMA1:
 
528
    jam();
 
529
    readSchemaRef(signal, fsPtr);
 
530
    return;
 
531
  case FsConnectRecord::READ_TAB_FILE1:
 
532
    jam();
 
533
    readTableRef(signal, fsPtr);
 
534
    return;
 
535
  default:
 
536
    break;
 
537
  }//switch
 
538
  {
 
539
    char msg[100];
 
540
    sprintf(msg, "File system read failed during FsConnectRecord state %d", (Uint32)fsPtr.p->fsState);
 
541
    fsRefError(signal,__LINE__,msg);
 
542
  }
 
543
}//execFSREADREF()
 
544
 
 
545
/* ---------------------------------------------------------------- */
 
546
// A file was successfully written.
 
547
/* ---------------------------------------------------------------- */
 
548
void Dbdict::execFSWRITECONF(Signal* signal) 
 
549
{
 
550
  FsConf * const fsConf = (FsConf *)&signal->theData[0];
 
551
  FsConnectRecordPtr fsPtr;
 
552
  jamEntry();
 
553
  c_fsConnectRecordPool.getPtr(fsPtr, fsConf->userPointer);
 
554
  switch (fsPtr.p->fsState) {
 
555
  case FsConnectRecord::WRITE_TAB_FILE:
 
556
    writeTableConf(signal, fsPtr);
 
557
    break;
 
558
  case FsConnectRecord::WRITE_SCHEMA:
 
559
    jam();
 
560
    writeSchemaConf(signal, fsPtr);
 
561
    break;
 
562
  default:
 
563
    jamLine((fsPtr.p->fsState & 0xFFF));
 
564
    ndbrequire(false);
 
565
    break;
 
566
  }//switch
 
567
}//execFSWRITECONF()
 
568
 
 
569
 
 
570
/* ---------------------------------------------------------------- */
 
571
// Routines to handle Read/Write of Table Files
 
572
/* ---------------------------------------------------------------- */
 
573
void
 
574
Dbdict::writeTableFile(Signal* signal, Uint32 tableId, 
 
575
                       SegmentedSectionPtr tabInfoPtr, Callback* callback){
 
576
  
 
577
  ndbrequire(c_writeTableRecord.tableWriteState == WriteTableRecord::IDLE);
 
578
  
 
579
  Uint32 sz = tabInfoPtr.sz + ZPAGE_HEADER_SIZE;
 
580
 
 
581
  c_writeTableRecord.noOfPages = DIV(sz, ZSIZE_OF_PAGES_IN_WORDS);
 
582
  c_writeTableRecord.tableWriteState = WriteTableRecord::TWR_CALLBACK;
 
583
  c_writeTableRecord.m_callback = * callback;
 
584
 
 
585
  c_writeTableRecord.pageId = 0;
 
586
  ndbrequire(c_writeTableRecord.noOfPages < 8);
 
587
 
 
588
  PageRecordPtr pageRecPtr;
 
589
  c_pageRecordArray.getPtr(pageRecPtr, c_writeTableRecord.pageId);
 
590
  copy(&pageRecPtr.p->word[ZPAGE_HEADER_SIZE], tabInfoPtr);
 
591
  
 
592
  memset(&pageRecPtr.p->word[0], 0, 4 * ZPAGE_HEADER_SIZE);
 
593
  pageRecPtr.p->word[ZPOS_CHECKSUM] = 
 
594
    computeChecksum(&pageRecPtr.p->word[0], 
 
595
                    c_writeTableRecord.noOfPages * ZSIZE_OF_PAGES_IN_WORDS);
 
596
  
 
597
  startWriteTableFile(signal, tableId);
 
598
 
 
599
}
 
600
 
 
601
void Dbdict::startWriteTableFile(Signal* signal, Uint32 tableId)
 
602
{
 
603
  FsConnectRecordPtr fsPtr;
 
604
  c_writeTableRecord.tableId = tableId;
 
605
  c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
 
606
  fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_TAB_FILE;
 
607
  openTableFile(signal, 0, fsPtr.i, tableId, true);
 
608
  c_writeTableRecord.noOfTableFilesHandled = 0;
 
609
}//Dbdict::startWriteTableFile()
 
610
 
 
611
void Dbdict::openTableFile(Signal* signal,
 
612
                           Uint32 fileNo,
 
613
                           Uint32 fsConPtr,
 
614
                           Uint32 tableId,
 
615
                           bool   writeFlag) 
 
616
{
 
617
  TableRecordPtr tablePtr;
 
618
  FsOpenReq * const fsOpenReq = (FsOpenReq *)&signal->theData[0];
 
619
  c_tableRecordPool.getPtr(tablePtr, tableId);
 
620
 
 
621
  fsOpenReq->userReference = reference();
 
622
  fsOpenReq->userPointer = fsConPtr;
 
623
  if (writeFlag) {
 
624
    jam();
 
625
    fsOpenReq->fileFlags = 
 
626
      FsOpenReq::OM_WRITEONLY | 
 
627
      FsOpenReq::OM_TRUNCATE | 
 
628
      FsOpenReq::OM_CREATE | 
 
629
      FsOpenReq::OM_SYNC;
 
630
  } else {
 
631
    jam();
 
632
    fsOpenReq->fileFlags = FsOpenReq::OM_READONLY;
 
633
  }//if
 
634
 
 
635
  fsOpenReq->fileNumber[3] = 0; // Initialise before byte changes
 
636
  FsOpenReq::setVersion(fsOpenReq->fileNumber, 1);
 
637
  FsOpenReq::setSuffix(fsOpenReq->fileNumber, FsOpenReq::S_TABLELIST);
 
638
  FsOpenReq::v1_setDisk(fsOpenReq->fileNumber, (fileNo + 1));
 
639
  FsOpenReq::v1_setTable(fsOpenReq->fileNumber, tableId);
 
640
  FsOpenReq::v1_setFragment(fsOpenReq->fileNumber, (Uint32)-1);
 
641
  FsOpenReq::v1_setS(fsOpenReq->fileNumber, tablePtr.p->tableVersion);
 
642
  FsOpenReq::v1_setP(fsOpenReq->fileNumber, 255);
 
643
/* ---------------------------------------------------------------- */
 
644
// File name : D1/DBDICT/T0/S1.TableList
 
645
// D1 means Disk 1 (set by fileNo + 1)
 
646
// T0 means table id = 0
 
647
// S1 means tableVersion 1
 
648
// TableList indicates that this is a file for a table description.
 
649
/* ---------------------------------------------------------------- */
 
650
  sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
 
651
}//openTableFile()
 
652
 
 
653
void Dbdict::writeTableFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr) 
 
654
{
 
655
  FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
 
656
 
 
657
  fsRWReq->filePointer = filePtr;
 
658
  fsRWReq->userReference = reference();
 
659
  fsRWReq->userPointer = fsConPtr;
 
660
  fsRWReq->operationFlag = 0; // Initialise before bit changes
 
661
  FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 1);
 
662
  FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag, 
 
663
                                FsReadWriteReq::fsFormatArrayOfPages);
 
664
  fsRWReq->varIndex = ZBAT_TABLE_FILE;
 
665
  fsRWReq->numberOfPages = c_writeTableRecord.noOfPages;
 
666
  fsRWReq->data.arrayOfPages.varIndex = c_writeTableRecord.pageId;
 
667
  fsRWReq->data.arrayOfPages.fileOffset = 0; // Write to file page 0
 
668
  sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
 
669
}//writeTableFile()
 
670
 
 
671
void Dbdict::writeTableConf(Signal* signal,
 
672
                                FsConnectRecordPtr fsPtr)
 
673
{
 
674
  fsPtr.p->fsState = FsConnectRecord::CLOSE_WRITE_TAB_FILE;
 
675
  closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
 
676
  return;
 
677
}//Dbdict::writeTableConf()
 
678
 
 
679
void Dbdict::closeWriteTableConf(Signal* signal,
 
680
                                 FsConnectRecordPtr fsPtr)
 
681
{
 
682
  c_writeTableRecord.noOfTableFilesHandled++;
 
683
  if (c_writeTableRecord.noOfTableFilesHandled < 2) {
 
684
    jam();
 
685
    fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_TAB_FILE;
 
686
    openTableFile(signal, 1, fsPtr.i, c_writeTableRecord.tableId, true);
 
687
    return;
 
688
  } 
 
689
  ndbrequire(c_writeTableRecord.noOfTableFilesHandled == 2);
 
690
  c_fsConnectRecordPool.release(fsPtr);
 
691
  WriteTableRecord::TableWriteState state = c_writeTableRecord.tableWriteState;
 
692
  c_writeTableRecord.tableWriteState = WriteTableRecord::IDLE;
 
693
  switch (state) {
 
694
  case WriteTableRecord::IDLE:
 
695
  case WriteTableRecord::WRITE_ADD_TABLE_MASTER :
 
696
  case WriteTableRecord::WRITE_ADD_TABLE_SLAVE :
 
697
  case WriteTableRecord::WRITE_RESTART_FROM_MASTER :
 
698
  case WriteTableRecord::WRITE_RESTART_FROM_OWN :
 
699
    ndbrequire(false);
 
700
    break;
 
701
  case WriteTableRecord::TWR_CALLBACK:
 
702
    jam();
 
703
    execute(signal, c_writeTableRecord.m_callback, 0);
 
704
    return;
 
705
  }
 
706
  ndbrequire(false);
 
707
}//Dbdict::closeWriteTableConf()
 
708
 
 
709
void Dbdict::startReadTableFile(Signal* signal, Uint32 tableId)
 
710
{
 
711
  //globalSignalLoggers.log(number(), "startReadTableFile");
 
712
  ndbrequire(!c_readTableRecord.inUse);
 
713
  
 
714
  FsConnectRecordPtr fsPtr;
 
715
  c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
 
716
  c_readTableRecord.inUse = true;
 
717
  c_readTableRecord.tableId = tableId;
 
718
  fsPtr.p->fsState = FsConnectRecord::OPEN_READ_TAB_FILE1;
 
719
  openTableFile(signal, 0, fsPtr.i, tableId, false);
 
720
}//Dbdict::startReadTableFile()
 
721
 
 
722
void Dbdict::openReadTableRef(Signal* signal,
 
723
                              FsConnectRecordPtr fsPtr) 
 
724
{
 
725
  fsPtr.p->fsState = FsConnectRecord::OPEN_READ_TAB_FILE2;
 
726
  openTableFile(signal, 1, fsPtr.i, c_readTableRecord.tableId, false);
 
727
  return;
 
728
}//Dbdict::openReadTableConf()
 
729
 
 
730
void Dbdict::readTableFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr) 
 
731
{
 
732
  FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
 
733
 
 
734
  fsRWReq->filePointer = filePtr;
 
735
  fsRWReq->userReference = reference();
 
736
  fsRWReq->userPointer = fsConPtr;
 
737
  fsRWReq->operationFlag = 0; // Initialise before bit changes
 
738
  FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 0);
 
739
  FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag, 
 
740
                                FsReadWriteReq::fsFormatArrayOfPages);
 
741
  fsRWReq->varIndex = ZBAT_TABLE_FILE;
 
742
  fsRWReq->numberOfPages = c_readTableRecord.noOfPages;
 
743
  fsRWReq->data.arrayOfPages.varIndex = c_readTableRecord.pageId;
 
744
  fsRWReq->data.arrayOfPages.fileOffset = 0; // Write to file page 0
 
745
  sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 8, JBA);
 
746
}//readTableFile()
 
747
 
 
748
void Dbdict::readTableConf(Signal* signal,
 
749
                           FsConnectRecordPtr fsPtr)
 
750
{
 
751
  /* ---------------------------------------------------------------- */
 
752
  // Verify the data read from disk
 
753
  /* ---------------------------------------------------------------- */
 
754
  bool crashInd;
 
755
  if (fsPtr.p->fsState == FsConnectRecord::READ_TAB_FILE1) {
 
756
    jam();
 
757
    crashInd = false;
 
758
  } else {
 
759
    jam();
 
760
    crashInd = true;
 
761
  }//if
 
762
 
 
763
  PageRecordPtr tmpPagePtr;
 
764
  c_pageRecordArray.getPtr(tmpPagePtr, c_readTableRecord.pageId);
 
765
  Uint32 sz = c_readTableRecord.noOfPages * ZSIZE_OF_PAGES_IN_WORDS;
 
766
  Uint32 chk = computeChecksum((const Uint32*)tmpPagePtr.p, sz);
 
767
  
 
768
  ndbrequire((chk == 0) || !crashInd);
 
769
  if(chk != 0){
 
770
    jam();
 
771
    ndbrequire(fsPtr.p->fsState == FsConnectRecord::READ_TAB_FILE1);
 
772
    readTableRef(signal, fsPtr);
 
773
    return;
 
774
  }//if
 
775
  
 
776
  fsPtr.p->fsState = FsConnectRecord::CLOSE_READ_TAB_FILE;
 
777
  closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
 
778
  return;
 
779
}//Dbdict::readTableConf()
 
780
 
 
781
void Dbdict::readTableRef(Signal* signal,
 
782
                          FsConnectRecordPtr fsPtr)
 
783
{
 
784
  fsPtr.p->fsState = FsConnectRecord::OPEN_READ_TAB_FILE2;
 
785
  openTableFile(signal, 1, fsPtr.i, c_readTableRecord.tableId, false);
 
786
  return;
 
787
}//Dbdict::readTableRef()
 
788
 
 
789
void Dbdict::closeReadTableConf(Signal* signal,
 
790
                                FsConnectRecordPtr fsPtr)
 
791
{
 
792
  c_fsConnectRecordPool.release(fsPtr);
 
793
  c_readTableRecord.inUse = false;
 
794
  
 
795
  execute(signal, c_readTableRecord.m_callback, 0);
 
796
  return;
 
797
}//Dbdict::closeReadTableConf()
 
798
 
 
799
/* ---------------------------------------------------------------- */
 
800
// Routines to handle Read/Write of Schema Files
 
801
/* ---------------------------------------------------------------- */
 
802
void
 
803
Dbdict::updateSchemaState(Signal* signal, Uint32 tableId, 
 
804
                          SchemaFile::TableEntry* te, Callback* callback){
 
805
 
 
806
  jam();
 
807
  ndbrequire(tableId < c_tableRecordPool.getSize());
 
808
  XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
 
809
  SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, tableId);
 
810
  
 
811
  SchemaFile::TableState newState = 
 
812
    (SchemaFile::TableState)te->m_tableState;
 
813
  SchemaFile::TableState oldState = 
 
814
    (SchemaFile::TableState)tableEntry->m_tableState;
 
815
  
 
816
  Uint32 newVersion = te->m_tableVersion;
 
817
  Uint32 oldVersion = tableEntry->m_tableVersion;
 
818
  
 
819
  bool ok = false;
 
820
  switch(newState){
 
821
  case SchemaFile::ADD_STARTED:
 
822
    jam();
 
823
    ok = true;
 
824
    ndbrequire(create_table_inc_schema_version(oldVersion) == newVersion);
 
825
    ndbrequire(oldState == SchemaFile::INIT ||
 
826
               oldState == SchemaFile::DROP_TABLE_COMMITTED);
 
827
    break;
 
828
  case SchemaFile::TABLE_ADD_COMMITTED:
 
829
    jam();
 
830
    ok = true;
 
831
    ndbrequire(newVersion == oldVersion);
 
832
    ndbrequire(oldState == SchemaFile::ADD_STARTED);
 
833
    break;
 
834
  case SchemaFile::ALTER_TABLE_COMMITTED:
 
835
    jam();
 
836
    ok = true;
 
837
    ndbrequire(alter_table_inc_schema_version(oldVersion) == newVersion);
 
838
    ndbrequire(oldState == SchemaFile::TABLE_ADD_COMMITTED ||
 
839
               oldState == SchemaFile::ALTER_TABLE_COMMITTED);
 
840
    break;
 
841
  case SchemaFile::DROP_TABLE_STARTED:
 
842
    jam();
 
843
  case SchemaFile::DROP_TABLE_COMMITTED:
 
844
    jam();
 
845
    ok = true;
 
846
    ndbrequire(false);
 
847
    break;
 
848
  case SchemaFile::INIT:
 
849
    jam();
 
850
    ok = true;
 
851
    ndbrequire((oldState == SchemaFile::ADD_STARTED));
 
852
  }//if
 
853
  ndbrequire(ok);
 
854
  
 
855
  * tableEntry = * te;
 
856
  computeChecksum(xsf, tableId / NDB_SF_PAGE_ENTRIES);
 
857
 
 
858
  ndbrequire(c_writeSchemaRecord.inUse == false);
 
859
  c_writeSchemaRecord.inUse = true;
 
860
  
 
861
  c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
 
862
  c_writeSchemaRecord.newFile = false;
 
863
  c_writeSchemaRecord.firstPage = tableId / NDB_SF_PAGE_ENTRIES;
 
864
  c_writeSchemaRecord.noOfPages = 1;
 
865
  c_writeSchemaRecord.m_callback = * callback;
 
866
 
 
867
  startWriteSchemaFile(signal);
 
868
}
 
869
 
 
870
void Dbdict::startWriteSchemaFile(Signal* signal)
 
871
{
 
872
  FsConnectRecordPtr fsPtr;
 
873
  c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
 
874
  fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_SCHEMA;
 
875
  openSchemaFile(signal, 0, fsPtr.i, true, c_writeSchemaRecord.newFile);
 
876
  c_writeSchemaRecord.noOfSchemaFilesHandled = 0;
 
877
}//Dbdict::startWriteSchemaFile()
 
878
 
 
879
void Dbdict::openSchemaFile(Signal* signal,
 
880
                            Uint32 fileNo,
 
881
                            Uint32 fsConPtr,
 
882
                            bool writeFlag,
 
883
                            bool newFile)
 
884
{
 
885
  FsOpenReq * const fsOpenReq = (FsOpenReq *)&signal->theData[0];
 
886
  fsOpenReq->userReference = reference();
 
887
  fsOpenReq->userPointer = fsConPtr;
 
888
  if (writeFlag) {
 
889
    jam();
 
890
    fsOpenReq->fileFlags = 
 
891
      FsOpenReq::OM_WRITEONLY | 
 
892
      FsOpenReq::OM_SYNC;
 
893
    if (newFile)
 
894
      fsOpenReq->fileFlags |=
 
895
        FsOpenReq::OM_TRUNCATE | 
 
896
        FsOpenReq::OM_CREATE;
 
897
  } else {
 
898
    jam();
 
899
    fsOpenReq->fileFlags = FsOpenReq::OM_READONLY;
 
900
  }//if
 
901
  fsOpenReq->fileNumber[3] = 0; // Initialise before byte changes
 
902
  FsOpenReq::setVersion(fsOpenReq->fileNumber, 1);
 
903
  FsOpenReq::setSuffix(fsOpenReq->fileNumber, FsOpenReq::S_SCHEMALOG);
 
904
  FsOpenReq::v1_setDisk(fsOpenReq->fileNumber, (fileNo + 1));
 
905
  FsOpenReq::v1_setTable(fsOpenReq->fileNumber, (Uint32)-1);
 
906
  FsOpenReq::v1_setFragment(fsOpenReq->fileNumber, (Uint32)-1);
 
907
  FsOpenReq::v1_setS(fsOpenReq->fileNumber, (Uint32)-1);
 
908
  FsOpenReq::v1_setP(fsOpenReq->fileNumber, 0);
 
909
/* ---------------------------------------------------------------- */
 
910
// File name : D1/DBDICT/P0.SchemaLog
 
911
// D1 means Disk 1 (set by fileNo + 1). Writes to both D1 and D2
 
912
// SchemaLog indicates that this is a file giving a list of current tables.
 
913
/* ---------------------------------------------------------------- */
 
914
  sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength, JBA);
 
915
}//openSchemaFile()
 
916
 
 
917
void Dbdict::writeSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr) 
 
918
{
 
919
  FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
 
920
 
 
921
  // check write record
 
922
  WriteSchemaRecord & wr = c_writeSchemaRecord;
 
923
  ndbrequire(wr.pageId == (wr.pageId != 0) * NDB_SF_MAX_PAGES);
 
924
  ndbrequire(wr.noOfPages != 0);
 
925
  ndbrequire(wr.firstPage + wr.noOfPages <= NDB_SF_MAX_PAGES);
 
926
 
 
927
  fsRWReq->filePointer = filePtr;
 
928
  fsRWReq->userReference = reference();
 
929
  fsRWReq->userPointer = fsConPtr;
 
930
  fsRWReq->operationFlag = 0; // Initialise before bit changes
 
931
  FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 1);
 
932
  FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag, 
 
933
                                FsReadWriteReq::fsFormatArrayOfPages);
 
934
  fsRWReq->varIndex = ZBAT_SCHEMA_FILE;
 
935
  fsRWReq->numberOfPages = wr.noOfPages;
 
936
  // Write from memory page
 
937
  fsRWReq->data.arrayOfPages.varIndex = wr.pageId + wr.firstPage;
 
938
  fsRWReq->data.arrayOfPages.fileOffset = wr.firstPage;
 
939
  sendSignal(NDBFS_REF, GSN_FSWRITEREQ, signal, 8, JBA);
 
940
}//writeSchemaFile()
 
941
 
 
942
void Dbdict::writeSchemaConf(Signal* signal,
 
943
                                FsConnectRecordPtr fsPtr)
 
944
{
 
945
  fsPtr.p->fsState = FsConnectRecord::CLOSE_WRITE_SCHEMA;
 
946
  closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
 
947
  return;
 
948
}//Dbdict::writeSchemaConf()
 
949
 
 
950
void Dbdict::closeFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr) 
 
951
{
 
952
  FsCloseReq * const fsCloseReq = (FsCloseReq *)&signal->theData[0];
 
953
  fsCloseReq->filePointer = filePtr;
 
954
  fsCloseReq->userReference = reference();
 
955
  fsCloseReq->userPointer = fsConPtr;
 
956
  FsCloseReq::setRemoveFileFlag(fsCloseReq->fileFlag, false);
 
957
  sendSignal(NDBFS_REF, GSN_FSCLOSEREQ, signal, FsCloseReq::SignalLength, JBA);
 
958
  return;
 
959
}//closeFile()
 
960
 
 
961
void Dbdict::closeWriteSchemaConf(Signal* signal,
 
962
                                     FsConnectRecordPtr fsPtr)
 
963
{
 
964
  c_writeSchemaRecord.noOfSchemaFilesHandled++;
 
965
  if (c_writeSchemaRecord.noOfSchemaFilesHandled < 2) {
 
966
    jam();
 
967
    fsPtr.p->fsState = FsConnectRecord::OPEN_WRITE_SCHEMA;
 
968
    openSchemaFile(signal, 1, fsPtr.i, true, c_writeSchemaRecord.newFile);
 
969
    return;
 
970
  } 
 
971
  ndbrequire(c_writeSchemaRecord.noOfSchemaFilesHandled == 2);
 
972
  
 
973
  c_fsConnectRecordPool.release(fsPtr);
 
974
 
 
975
  c_writeSchemaRecord.inUse = false;
 
976
  execute(signal, c_writeSchemaRecord.m_callback, 0);
 
977
  return;
 
978
}//Dbdict::closeWriteSchemaConf()
 
979
 
 
980
void Dbdict::startReadSchemaFile(Signal* signal)
 
981
{
 
982
  //globalSignalLoggers.log(number(), "startReadSchemaFile");
 
983
  FsConnectRecordPtr fsPtr;
 
984
  c_fsConnectRecordPool.getPtr(fsPtr, getFsConnRecord());
 
985
  fsPtr.p->fsState = FsConnectRecord::OPEN_READ_SCHEMA1;
 
986
  openSchemaFile(signal, 0, fsPtr.i, false, false);
 
987
}//Dbdict::startReadSchemaFile()
 
988
 
 
989
void Dbdict::openReadSchemaRef(Signal* signal,
 
990
                               FsConnectRecordPtr fsPtr) 
 
991
{
 
992
  fsPtr.p->fsState = FsConnectRecord::OPEN_READ_SCHEMA2;
 
993
  openSchemaFile(signal, 1, fsPtr.i, false, false);
 
994
}//Dbdict::openReadSchemaRef()
 
995
 
 
996
void Dbdict::readSchemaFile(Signal* signal, Uint32 filePtr, Uint32 fsConPtr) 
 
997
{
 
998
  FsReadWriteReq * const fsRWReq = (FsReadWriteReq *)&signal->theData[0];
 
999
 
 
1000
  // check read record
 
1001
  ReadSchemaRecord & rr = c_readSchemaRecord;
 
1002
  ndbrequire(rr.pageId == (rr.pageId != 0) * NDB_SF_MAX_PAGES);
 
1003
  ndbrequire(rr.noOfPages != 0);
 
1004
  ndbrequire(rr.firstPage + rr.noOfPages <= NDB_SF_MAX_PAGES);
 
1005
 
 
1006
  fsRWReq->filePointer = filePtr;
 
1007
  fsRWReq->userReference = reference();
 
1008
  fsRWReq->userPointer = fsConPtr;
 
1009
  fsRWReq->operationFlag = 0; // Initialise before bit changes
 
1010
  FsReadWriteReq::setSyncFlag(fsRWReq->operationFlag, 0);
 
1011
  FsReadWriteReq::setFormatFlag(fsRWReq->operationFlag, 
 
1012
                                FsReadWriteReq::fsFormatArrayOfPages);
 
1013
  fsRWReq->varIndex = ZBAT_SCHEMA_FILE;
 
1014
  fsRWReq->numberOfPages = rr.noOfPages;
 
1015
  fsRWReq->data.arrayOfPages.varIndex = rr.pageId + rr.firstPage;
 
1016
  fsRWReq->data.arrayOfPages.fileOffset = rr.firstPage;
 
1017
  sendSignal(NDBFS_REF, GSN_FSREADREQ, signal, 8, JBA);
 
1018
}//readSchemaFile()
 
1019
 
 
1020
void Dbdict::readSchemaConf(Signal* signal,
 
1021
                            FsConnectRecordPtr fsPtr)
 
1022
{
 
1023
/* ---------------------------------------------------------------- */
 
1024
// Verify the data read from disk
 
1025
/* ---------------------------------------------------------------- */
 
1026
  bool crashInd;
 
1027
  if (fsPtr.p->fsState == FsConnectRecord::READ_SCHEMA1) {
 
1028
    jam();
 
1029
    crashInd = false;
 
1030
  } else {
 
1031
    jam();
 
1032
    crashInd = true;
 
1033
  }//if
 
1034
 
 
1035
  ReadSchemaRecord & rr = c_readSchemaRecord;
 
1036
  XSchemaFile * xsf = &c_schemaFile[rr.pageId != 0];
 
1037
 
 
1038
  if (rr.schemaReadState == ReadSchemaRecord::INITIAL_READ_HEAD) {
 
1039
    jam();
 
1040
    ndbrequire(rr.firstPage == 0);
 
1041
    SchemaFile * sf = &xsf->schemaPage[0];
 
1042
    Uint32 noOfPages;
 
1043
    if (sf->NdbVersion < NDB_SF_VERSION_5_0_6) {
 
1044
      jam();
 
1045
      const Uint32 pageSize_old = 32 * 1024;
 
1046
      noOfPages = pageSize_old / NDB_SF_PAGE_SIZE - 1;
 
1047
    } else {
 
1048
      noOfPages = sf->FileSize / NDB_SF_PAGE_SIZE - 1;
 
1049
    }
 
1050
    rr.schemaReadState = ReadSchemaRecord::INITIAL_READ;
 
1051
    if (noOfPages != 0) {
 
1052
      rr.firstPage = 1;
 
1053
      rr.noOfPages = noOfPages;
 
1054
      readSchemaFile(signal, fsPtr.p->filePtr, fsPtr.i);
 
1055
      return;
 
1056
    }
 
1057
  }
 
1058
 
 
1059
  SchemaFile * sf0 = &xsf->schemaPage[0];
 
1060
  xsf->noOfPages = sf0->FileSize / NDB_SF_PAGE_SIZE;
 
1061
 
 
1062
  if (sf0->NdbVersion < NDB_SF_VERSION_5_0_6 &&
 
1063
      ! convertSchemaFileTo_5_0_6(xsf)) {
 
1064
    jam();
 
1065
    ndbrequire(! crashInd);
 
1066
    ndbrequire(fsPtr.p->fsState == FsConnectRecord::READ_SCHEMA1);
 
1067
    readSchemaRef(signal, fsPtr);
 
1068
    return;
 
1069
  }
 
1070
 
 
1071
  for (Uint32 n = 0; n < xsf->noOfPages; n++) {
 
1072
    SchemaFile * sf = &xsf->schemaPage[n];
 
1073
    bool ok =
 
1074
      memcmp(sf->Magic, NDB_SF_MAGIC, sizeof(sf->Magic)) == 0 &&
 
1075
      sf->FileSize != 0 &&
 
1076
      sf->FileSize % NDB_SF_PAGE_SIZE == 0 &&
 
1077
      sf->FileSize == sf0->FileSize &&
 
1078
      sf->PageNumber == n &&
 
1079
      computeChecksum((Uint32*)sf, NDB_SF_PAGE_SIZE_IN_WORDS) == 0;
 
1080
    ndbrequire(ok || !crashInd);
 
1081
    if (! ok) {
 
1082
      jam();
 
1083
      ndbrequire(fsPtr.p->fsState == FsConnectRecord::READ_SCHEMA1);
 
1084
      readSchemaRef(signal, fsPtr);
 
1085
      return;
 
1086
    }
 
1087
  }
 
1088
 
 
1089
  fsPtr.p->fsState = FsConnectRecord::CLOSE_READ_SCHEMA;
 
1090
  closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
 
1091
  return;
 
1092
}//Dbdict::readSchemaConf()
 
1093
 
 
1094
void Dbdict::readSchemaRef(Signal* signal,
 
1095
                           FsConnectRecordPtr fsPtr)
 
1096
{
 
1097
  /**
 
1098
   * First close corrupt file
 
1099
   */
 
1100
  fsPtr.p->fsState = FsConnectRecord::OPEN_READ_SCHEMA2;
 
1101
  closeFile(signal, fsPtr.p->filePtr, fsPtr.i);
 
1102
  return;
 
1103
}
 
1104
 
 
1105
void Dbdict::closeReadSchemaConf(Signal* signal,
 
1106
                                 FsConnectRecordPtr fsPtr)
 
1107
{
 
1108
  c_fsConnectRecordPool.release(fsPtr);
 
1109
  ReadSchemaRecord::SchemaReadState state = c_readSchemaRecord.schemaReadState;
 
1110
  c_readSchemaRecord.schemaReadState = ReadSchemaRecord::IDLE;
 
1111
 
 
1112
  switch(state) {
 
1113
  case ReadSchemaRecord::INITIAL_READ :
 
1114
    jam();
 
1115
    {
 
1116
      // write back both copies
 
1117
      
 
1118
      ndbrequire(c_writeSchemaRecord.inUse == false);
 
1119
      XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0 ];
 
1120
      Uint32 noOfPages =
 
1121
        (c_tableRecordPool.getSize() + NDB_SF_PAGE_ENTRIES - 1) /
 
1122
        NDB_SF_PAGE_ENTRIES;
 
1123
      resizeSchemaFile(xsf, noOfPages);
 
1124
 
 
1125
      c_writeSchemaRecord.inUse = true;
 
1126
      c_writeSchemaRecord.pageId = c_schemaRecord.oldSchemaPage;
 
1127
      c_writeSchemaRecord.newFile = true;
 
1128
      c_writeSchemaRecord.firstPage = 0;
 
1129
      c_writeSchemaRecord.noOfPages = xsf->noOfPages;
 
1130
 
 
1131
      c_writeSchemaRecord.m_callback.m_callbackFunction = 
 
1132
        safe_cast(&Dbdict::initSchemaFile_conf);
 
1133
 
 
1134
      startWriteSchemaFile(signal);
 
1135
    }
 
1136
    break;
 
1137
 
 
1138
  default :
 
1139
    ndbrequire(false);
 
1140
    break;
 
1141
 
 
1142
  }//switch
 
1143
}//Dbdict::closeReadSchemaConf()
 
1144
 
 
1145
bool
 
1146
Dbdict::convertSchemaFileTo_5_0_6(XSchemaFile * xsf)
 
1147
{
 
1148
  const Uint32 pageSize_old = 32 * 1024;
 
1149
  Uint32 page_old[pageSize_old >> 2];
 
1150
  SchemaFile * sf_old = (SchemaFile *)page_old;
 
1151
 
 
1152
  if (xsf->noOfPages * NDB_SF_PAGE_SIZE != pageSize_old)
 
1153
    return false;
 
1154
  SchemaFile * sf0 = &xsf->schemaPage[0];
 
1155
  memcpy(sf_old, sf0, pageSize_old);
 
1156
 
 
1157
  // init max number new pages needed
 
1158
  xsf->noOfPages = (sf_old->NoOfTableEntries + NDB_SF_PAGE_ENTRIES - 1) /
 
1159
                   NDB_SF_PAGE_ENTRIES;
 
1160
  initSchemaFile(xsf, 0, xsf->noOfPages, true);
 
1161
 
 
1162
  Uint32 noOfPages = 1;
 
1163
  Uint32 n, i, j;
 
1164
  for (n = 0; n < xsf->noOfPages; n++) {
 
1165
    jam();
 
1166
    for (i = 0; i < NDB_SF_PAGE_ENTRIES; i++) {
 
1167
      j = n * NDB_SF_PAGE_ENTRIES + i;
 
1168
      if (j >= sf_old->NoOfTableEntries)
 
1169
        continue;
 
1170
      const SchemaFile::TableEntry_old & te_old = sf_old->TableEntries_old[j];
 
1171
      if (te_old.m_tableState == SchemaFile::INIT ||
 
1172
          te_old.m_tableState == SchemaFile::DROP_TABLE_COMMITTED ||
 
1173
          te_old.m_noOfPages == 0)
 
1174
        continue;
 
1175
      SchemaFile * sf = &xsf->schemaPage[n];
 
1176
      SchemaFile::TableEntry & te = sf->TableEntries[i];
 
1177
      te.m_tableState = te_old.m_tableState;
 
1178
      te.m_tableVersion = te_old.m_tableVersion;
 
1179
      te.m_tableType = te_old.m_tableType;
 
1180
      te.m_info_words = te_old.m_noOfPages * ZSIZE_OF_PAGES_IN_WORDS -
 
1181
                        ZPAGE_HEADER_SIZE;
 
1182
      te.m_gcp = te_old.m_gcp;
 
1183
      if (noOfPages < n)
 
1184
        noOfPages = n;
 
1185
    }
 
1186
  }
 
1187
  xsf->noOfPages = noOfPages;
 
1188
  initSchemaFile(xsf, 0, xsf->noOfPages, false);
 
1189
 
 
1190
  return true;
 
1191
}
 
1192
 
 
1193
/* **************************************************************** */
 
1194
/* ---------------------------------------------------------------- */
 
1195
/* MODULE:          INITIALISATION MODULE ------------------------- */
 
1196
/* ---------------------------------------------------------------- */
 
1197
/*                                                                  */
 
1198
/* This module contains initialisation of data at start/restart.    */
 
1199
/* ---------------------------------------------------------------- */
 
1200
/* **************************************************************** */
 
1201
 
 
1202
Dbdict::Dbdict(const class Configuration & conf):
 
1203
  SimulatedBlock(DBDICT, conf),
 
1204
  c_tableRecordHash(c_tableRecordPool),
 
1205
  c_attributeRecordHash(c_attributeRecordPool),
 
1206
  c_triggerRecordHash(c_triggerRecordPool),
 
1207
  c_opCreateTable(c_opRecordPool),
 
1208
  c_opDropTable(c_opRecordPool),
 
1209
  c_opCreateIndex(c_opRecordPool),
 
1210
  c_opDropIndex(c_opRecordPool),
 
1211
  c_opAlterIndex(c_opRecordPool),
 
1212
  c_opBuildIndex(c_opRecordPool),
 
1213
  c_opCreateTrigger(c_opRecordPool),
 
1214
  c_opDropTrigger(c_opRecordPool),
 
1215
  c_opAlterTrigger(c_opRecordPool),
 
1216
  c_opRecordSequence(0),
 
1217
  c_dictLockQueue(c_dictLockPool),
 
1218
  c_dictLockPoll(false)
 
1219
{
 
1220
  BLOCK_CONSTRUCTOR(Dbdict);
 
1221
  
 
1222
  const ndb_mgm_configuration_iterator * p = conf.getOwnConfigIterator();
 
1223
  ndbrequire(p != 0);
 
1224
 
 
1225
  ndb_mgm_get_int_parameter(p, CFG_DB_NO_TRIGGERS, &c_maxNoOfTriggers);
 
1226
  // Transit signals
 
1227
  addRecSignal(GSN_DUMP_STATE_ORD, &Dbdict::execDUMP_STATE_ORD);
 
1228
  addRecSignal(GSN_GET_TABINFOREQ, &Dbdict::execGET_TABINFOREQ);
 
1229
  addRecSignal(GSN_GET_TABLEID_REQ, &Dbdict::execGET_TABLEDID_REQ);
 
1230
  addRecSignal(GSN_GET_TABINFO_CONF, &Dbdict::execGET_TABINFO_CONF);
 
1231
  addRecSignal(GSN_CONTINUEB, &Dbdict::execCONTINUEB);
 
1232
 
 
1233
  addRecSignal(GSN_CREATE_TABLE_REQ, &Dbdict::execCREATE_TABLE_REQ);
 
1234
  addRecSignal(GSN_CREATE_TAB_REQ, &Dbdict::execCREATE_TAB_REQ);
 
1235
  addRecSignal(GSN_CREATE_TAB_REF, &Dbdict::execCREATE_TAB_REF);
 
1236
  addRecSignal(GSN_CREATE_TAB_CONF, &Dbdict::execCREATE_TAB_CONF);
 
1237
  addRecSignal(GSN_CREATE_FRAGMENTATION_REF, &Dbdict::execCREATE_FRAGMENTATION_REF);
 
1238
  addRecSignal(GSN_CREATE_FRAGMENTATION_CONF, &Dbdict::execCREATE_FRAGMENTATION_CONF);
 
1239
  addRecSignal(GSN_DIADDTABCONF, &Dbdict::execDIADDTABCONF);
 
1240
  addRecSignal(GSN_DIADDTABREF, &Dbdict::execDIADDTABREF);
 
1241
  addRecSignal(GSN_ADD_FRAGREQ, &Dbdict::execADD_FRAGREQ);
 
1242
  addRecSignal(GSN_TAB_COMMITCONF, &Dbdict::execTAB_COMMITCONF);
 
1243
  addRecSignal(GSN_TAB_COMMITREF, &Dbdict::execTAB_COMMITREF);
 
1244
  addRecSignal(GSN_ALTER_TABLE_REQ, &Dbdict::execALTER_TABLE_REQ);
 
1245
  addRecSignal(GSN_ALTER_TAB_REQ, &Dbdict::execALTER_TAB_REQ);
 
1246
  addRecSignal(GSN_ALTER_TAB_REF, &Dbdict::execALTER_TAB_REF);
 
1247
  addRecSignal(GSN_ALTER_TAB_CONF, &Dbdict::execALTER_TAB_CONF);
 
1248
 
 
1249
  // Index signals
 
1250
  addRecSignal(GSN_CREATE_INDX_REQ, &Dbdict::execCREATE_INDX_REQ);
 
1251
  addRecSignal(GSN_CREATE_INDX_CONF, &Dbdict::execCREATE_INDX_CONF);
 
1252
  addRecSignal(GSN_CREATE_INDX_REF, &Dbdict::execCREATE_INDX_REF);
 
1253
 
 
1254
  addRecSignal(GSN_ALTER_INDX_REQ, &Dbdict::execALTER_INDX_REQ);
 
1255
  addRecSignal(GSN_ALTER_INDX_CONF, &Dbdict::execALTER_INDX_CONF);
 
1256
  addRecSignal(GSN_ALTER_INDX_REF, &Dbdict::execALTER_INDX_REF);
 
1257
 
 
1258
  addRecSignal(GSN_CREATE_TABLE_CONF, &Dbdict::execCREATE_TABLE_CONF);
 
1259
  addRecSignal(GSN_CREATE_TABLE_REF, &Dbdict::execCREATE_TABLE_REF);
 
1260
 
 
1261
  addRecSignal(GSN_DROP_INDX_REQ, &Dbdict::execDROP_INDX_REQ);
 
1262
  addRecSignal(GSN_DROP_INDX_CONF, &Dbdict::execDROP_INDX_CONF);
 
1263
  addRecSignal(GSN_DROP_INDX_REF, &Dbdict::execDROP_INDX_REF);
 
1264
 
 
1265
  addRecSignal(GSN_DROP_TABLE_CONF, &Dbdict::execDROP_TABLE_CONF);
 
1266
  addRecSignal(GSN_DROP_TABLE_REF, &Dbdict::execDROP_TABLE_REF);
 
1267
 
 
1268
  addRecSignal(GSN_BUILDINDXREQ, &Dbdict::execBUILDINDXREQ);
 
1269
  addRecSignal(GSN_BUILDINDXCONF, &Dbdict::execBUILDINDXCONF);
 
1270
  addRecSignal(GSN_BUILDINDXREF, &Dbdict::execBUILDINDXREF);
 
1271
 
 
1272
  // Trigger signals
 
1273
  addRecSignal(GSN_CREATE_TRIG_REQ, &Dbdict::execCREATE_TRIG_REQ);
 
1274
  addRecSignal(GSN_CREATE_TRIG_CONF, &Dbdict::execCREATE_TRIG_CONF);
 
1275
  addRecSignal(GSN_CREATE_TRIG_REF, &Dbdict::execCREATE_TRIG_REF);
 
1276
  addRecSignal(GSN_ALTER_TRIG_REQ, &Dbdict::execALTER_TRIG_REQ);
 
1277
  addRecSignal(GSN_ALTER_TRIG_CONF, &Dbdict::execALTER_TRIG_CONF);
 
1278
  addRecSignal(GSN_ALTER_TRIG_REF, &Dbdict::execALTER_TRIG_REF);
 
1279
  addRecSignal(GSN_DROP_TRIG_REQ, &Dbdict::execDROP_TRIG_REQ);
 
1280
  addRecSignal(GSN_DROP_TRIG_CONF, &Dbdict::execDROP_TRIG_CONF);
 
1281
  addRecSignal(GSN_DROP_TRIG_REF, &Dbdict::execDROP_TRIG_REF);
 
1282
 
 
1283
  // Received signals
 
1284
  addRecSignal(GSN_HOT_SPAREREP, &Dbdict::execHOT_SPAREREP);
 
1285
  addRecSignal(GSN_GET_SCHEMA_INFOREQ, &Dbdict::execGET_SCHEMA_INFOREQ);
 
1286
  addRecSignal(GSN_SCHEMA_INFO, &Dbdict::execSCHEMA_INFO);
 
1287
  addRecSignal(GSN_SCHEMA_INFOCONF, &Dbdict::execSCHEMA_INFOCONF);
 
1288
  addRecSignal(GSN_DICTSTARTREQ, &Dbdict::execDICTSTARTREQ);
 
1289
  addRecSignal(GSN_READ_NODESCONF, &Dbdict::execREAD_NODESCONF);
 
1290
  addRecSignal(GSN_FSOPENCONF, &Dbdict::execFSOPENCONF);
 
1291
  addRecSignal(GSN_FSOPENREF, &Dbdict::execFSOPENREF, true);
 
1292
  addRecSignal(GSN_FSCLOSECONF, &Dbdict::execFSCLOSECONF);
 
1293
  addRecSignal(GSN_FSWRITECONF, &Dbdict::execFSWRITECONF);
 
1294
  addRecSignal(GSN_FSREADCONF, &Dbdict::execFSREADCONF);
 
1295
  addRecSignal(GSN_FSREADREF, &Dbdict::execFSREADREF, true);
 
1296
  addRecSignal(GSN_LQHFRAGCONF, &Dbdict::execLQHFRAGCONF);
 
1297
  addRecSignal(GSN_LQHADDATTCONF, &Dbdict::execLQHADDATTCONF);
 
1298
  addRecSignal(GSN_LQHADDATTREF, &Dbdict::execLQHADDATTREF);
 
1299
  addRecSignal(GSN_LQHFRAGREF, &Dbdict::execLQHFRAGREF);
 
1300
  addRecSignal(GSN_NDB_STTOR, &Dbdict::execNDB_STTOR);
 
1301
  addRecSignal(GSN_READ_CONFIG_REQ, &Dbdict::execREAD_CONFIG_REQ, true);
 
1302
  addRecSignal(GSN_STTOR, &Dbdict::execSTTOR);
 
1303
  addRecSignal(GSN_TC_SCHVERCONF, &Dbdict::execTC_SCHVERCONF);
 
1304
  addRecSignal(GSN_NODE_FAILREP, &Dbdict::execNODE_FAILREP);
 
1305
  addRecSignal(GSN_INCL_NODEREQ, &Dbdict::execINCL_NODEREQ);
 
1306
  addRecSignal(GSN_API_FAILREQ, &Dbdict::execAPI_FAILREQ);
 
1307
 
 
1308
  addRecSignal(GSN_WAIT_GCP_REF, &Dbdict::execWAIT_GCP_REF);
 
1309
  addRecSignal(GSN_WAIT_GCP_CONF, &Dbdict::execWAIT_GCP_CONF);
 
1310
 
 
1311
  addRecSignal(GSN_LIST_TABLES_REQ, &Dbdict::execLIST_TABLES_REQ);
 
1312
 
 
1313
  addRecSignal(GSN_DROP_TABLE_REQ, &Dbdict::execDROP_TABLE_REQ);
 
1314
  
 
1315
  addRecSignal(GSN_PREP_DROP_TAB_REQ, &Dbdict::execPREP_DROP_TAB_REQ);
 
1316
  addRecSignal(GSN_PREP_DROP_TAB_REF, &Dbdict::execPREP_DROP_TAB_REF);
 
1317
  addRecSignal(GSN_PREP_DROP_TAB_CONF, &Dbdict::execPREP_DROP_TAB_CONF);
 
1318
  
 
1319
  addRecSignal(GSN_DROP_TAB_REQ, &Dbdict::execDROP_TAB_REQ);
 
1320
  addRecSignal(GSN_DROP_TAB_REF, &Dbdict::execDROP_TAB_REF);
 
1321
  addRecSignal(GSN_DROP_TAB_CONF, &Dbdict::execDROP_TAB_CONF);
 
1322
 
 
1323
  addRecSignal(GSN_BACKUP_FRAGMENT_REQ, &Dbdict::execBACKUP_FRAGMENT_REQ);
 
1324
 
 
1325
  addRecSignal(GSN_DICT_LOCK_REQ, &Dbdict::execDICT_LOCK_REQ);
 
1326
  addRecSignal(GSN_DICT_UNLOCK_ORD, &Dbdict::execDICT_UNLOCK_ORD);
 
1327
}//Dbdict::Dbdict()
 
1328
 
 
1329
Dbdict::~Dbdict() 
 
1330
{
 
1331
}//Dbdict::~Dbdict()
 
1332
 
 
1333
BLOCK_FUNCTIONS(Dbdict)
 
1334
 
 
1335
void Dbdict::initCommonData() 
 
1336
{
 
1337
/* ---------------------------------------------------------------- */
 
1338
// Initialise all common variables.
 
1339
/* ---------------------------------------------------------------- */
 
1340
  initRetrieveRecord(0, 0, 0);
 
1341
  initSchemaRecord();
 
1342
  initRestartRecord();
 
1343
  initSendSchemaRecord();
 
1344
  initReadTableRecord();
 
1345
  initWriteTableRecord();
 
1346
  initReadSchemaRecord();
 
1347
  initWriteSchemaRecord();
 
1348
 
 
1349
  c_masterNodeId = ZNIL;
 
1350
  c_numberNode = 0;
 
1351
  c_noNodesFailed = 0;
 
1352
  c_failureNr = 0;
 
1353
  c_blockState = BS_IDLE;
 
1354
  c_packTable.m_state = PackTable::PTS_IDLE;
 
1355
  c_startPhase = 0;
 
1356
  c_restartType = 255; //Ensure not used restartType
 
1357
  c_tabinfoReceived = 0;
 
1358
  c_initialStart = false;
 
1359
  c_systemRestart = false;
 
1360
  c_initialNodeRestart = false;
 
1361
  c_nodeRestart = false;
 
1362
}//Dbdict::initCommonData()
 
1363
 
 
1364
void Dbdict::initRecords() 
 
1365
{
 
1366
  initNodeRecords();
 
1367
  initPageRecords();
 
1368
  initTableRecords();
 
1369
  initTriggerRecords();
 
1370
}//Dbdict::initRecords()
 
1371
 
 
1372
void Dbdict::initSendSchemaRecord() 
 
1373
{
 
1374
  c_sendSchemaRecord.noOfWords = (Uint32)-1;
 
1375
  c_sendSchemaRecord.pageId = RNIL;
 
1376
  c_sendSchemaRecord.noOfWordsCurrentlySent = 0;
 
1377
  c_sendSchemaRecord.noOfSignalsSentSinceDelay = 0;
 
1378
  c_sendSchemaRecord.inUse = false;
 
1379
  //c_sendSchemaRecord.sendSchemaState = SendSchemaRecord::IDLE;
 
1380
}//initSendSchemaRecord()
 
1381
 
 
1382
void Dbdict::initReadTableRecord() 
 
1383
{
 
1384
  c_readTableRecord.noOfPages = (Uint32)-1;
 
1385
  c_readTableRecord.pageId = RNIL;
 
1386
  c_readTableRecord.tableId = ZNIL;
 
1387
  c_readTableRecord.inUse = false;
 
1388
}//initReadTableRecord()
 
1389
 
 
1390
void Dbdict::initWriteTableRecord() 
 
1391
{
 
1392
  c_writeTableRecord.noOfPages = (Uint32)-1;
 
1393
  c_writeTableRecord.pageId = RNIL;
 
1394
  c_writeTableRecord.noOfTableFilesHandled = 3;
 
1395
  c_writeTableRecord.tableId = ZNIL;
 
1396
  c_writeTableRecord.tableWriteState = WriteTableRecord::IDLE;
 
1397
}//initWriteTableRecord()
 
1398
 
 
1399
void Dbdict::initReadSchemaRecord() 
 
1400
{
 
1401
  c_readSchemaRecord.pageId = RNIL;
 
1402
  c_readSchemaRecord.schemaReadState = ReadSchemaRecord::IDLE;
 
1403
}//initReadSchemaRecord()
 
1404
 
 
1405
void Dbdict::initWriteSchemaRecord() 
 
1406
{
 
1407
  c_writeSchemaRecord.inUse = false;
 
1408
  c_writeSchemaRecord.pageId = RNIL;
 
1409
  c_writeSchemaRecord.noOfSchemaFilesHandled = 3;
 
1410
}//initWriteSchemaRecord()
 
1411
 
 
1412
void Dbdict::initRetrieveRecord(Signal* signal, Uint32 i, Uint32 returnCode) 
 
1413
{
 
1414
  c_retrieveRecord.busyState = false;
 
1415
  c_retrieveRecord.blockRef = 0;
 
1416
  c_retrieveRecord.m_senderData = RNIL;
 
1417
  c_retrieveRecord.tableId = RNIL;
 
1418
  c_retrieveRecord.currentSent = 0;
 
1419
  c_retrieveRecord.retrievedNoOfPages = 0;
 
1420
  c_retrieveRecord.retrievedNoOfWords = 0;
 
1421
  c_retrieveRecord.m_useLongSig = false;
 
1422
}//initRetrieveRecord()
 
1423
 
 
1424
void Dbdict::initSchemaRecord() 
 
1425
{
 
1426
  c_schemaRecord.schemaPage = RNIL;
 
1427
  c_schemaRecord.oldSchemaPage = RNIL;
 
1428
}//Dbdict::initSchemaRecord()
 
1429
 
 
1430
void Dbdict::initRestartRecord() 
 
1431
{
 
1432
  c_restartRecord.gciToRestart = 0;
 
1433
  c_restartRecord.activeTable = ZNIL;
 
1434
}//Dbdict::initRestartRecord()
 
1435
 
 
1436
void Dbdict::initNodeRecords() 
 
1437
{
 
1438
  jam();
 
1439
  for (unsigned i = 1; i < MAX_NODES; i++) {
 
1440
    NodeRecordPtr nodePtr;
 
1441
    c_nodes.getPtr(nodePtr, i);
 
1442
    nodePtr.p->hotSpare = false;
 
1443
    nodePtr.p->nodeState = NodeRecord::API_NODE;
 
1444
  }//for
 
1445
}//Dbdict::initNodeRecords()
 
1446
 
 
1447
void Dbdict::initPageRecords() 
 
1448
{
 
1449
  c_retrieveRecord.retrievePage =  ZMAX_PAGES_OF_TABLE_DEFINITION;
 
1450
  ndbrequire(ZNUMBER_OF_PAGES >= (ZMAX_PAGES_OF_TABLE_DEFINITION + 1));
 
1451
  c_schemaRecord.schemaPage = 0;
 
1452
  c_schemaRecord.oldSchemaPage = NDB_SF_MAX_PAGES;
 
1453
}//Dbdict::initPageRecords()
 
1454
 
 
1455
void Dbdict::initTableRecords() 
 
1456
{
 
1457
  TableRecordPtr tablePtr;
 
1458
  while (1) {
 
1459
    jam();
 
1460
    refresh_watch_dog();
 
1461
    c_tableRecordPool.seize(tablePtr);
 
1462
    if (tablePtr.i == RNIL) {
 
1463
      jam();
 
1464
      break;
 
1465
    }//if
 
1466
    initialiseTableRecord(tablePtr);
 
1467
  }//while
 
1468
}//Dbdict::initTableRecords()
 
1469
 
 
1470
void Dbdict::initialiseTableRecord(TableRecordPtr tablePtr) 
 
1471
{
 
1472
  tablePtr.p->activePage = RNIL;
 
1473
  tablePtr.p->filePtr[0] = RNIL;
 
1474
  tablePtr.p->filePtr[1] = RNIL;
 
1475
  tablePtr.p->firstAttribute = RNIL;
 
1476
  tablePtr.p->firstPage = RNIL;
 
1477
  tablePtr.p->lastAttribute = RNIL;
 
1478
  tablePtr.p->tableId = tablePtr.i;
 
1479
  tablePtr.p->tableVersion = (Uint32)-1;
 
1480
  tablePtr.p->tabState = TableRecord::NOT_DEFINED;
 
1481
  tablePtr.p->tabReturnState = TableRecord::TRS_IDLE;
 
1482
  tablePtr.p->fragmentType = DictTabInfo::AllNodesSmallTable;
 
1483
  memset(tablePtr.p->tableName, 0, sizeof(tablePtr.p->tableName));
 
1484
  tablePtr.p->gciTableCreated = 0;
 
1485
  tablePtr.p->noOfAttributes = ZNIL;
 
1486
  tablePtr.p->noOfNullAttr = 0;
 
1487
  tablePtr.p->frmLen = 0;
 
1488
  memset(tablePtr.p->frmData, 0, sizeof(tablePtr.p->frmData));
 
1489
  /*
 
1490
    tablePtr.p->lh3PageIndexBits = 0;
 
1491
    tablePtr.p->lh3DistrBits = 0;
 
1492
    tablePtr.p->lh3PageBits = 6;
 
1493
  */
 
1494
  tablePtr.p->kValue = 6;
 
1495
  tablePtr.p->localKeyLen = 1;
 
1496
  tablePtr.p->maxLoadFactor = 80;
 
1497
  tablePtr.p->minLoadFactor = 70;
 
1498
  tablePtr.p->noOfPrimkey = 1;
 
1499
  tablePtr.p->tupKeyLength = 1;
 
1500
  tablePtr.p->maxRowsLow = 0;
 
1501
  tablePtr.p->maxRowsHigh = 0;
 
1502
  tablePtr.p->minRowsLow = 0;
 
1503
  tablePtr.p->minRowsHigh = 0;
 
1504
  tablePtr.p->storedTable = true;
 
1505
  tablePtr.p->tableType = DictTabInfo::UserTable;
 
1506
  tablePtr.p->primaryTableId = RNIL;
 
1507
  // volatile elements
 
1508
  tablePtr.p->indexState = TableRecord::IS_UNDEFINED;
 
1509
  tablePtr.p->insertTriggerId = RNIL;
 
1510
  tablePtr.p->updateTriggerId = RNIL;
 
1511
  tablePtr.p->deleteTriggerId = RNIL;
 
1512
  tablePtr.p->customTriggerId = RNIL;
 
1513
  tablePtr.p->buildTriggerId = RNIL;
 
1514
  tablePtr.p->indexLocal = 0;
 
1515
}//Dbdict::initialiseTableRecord()
 
1516
 
 
1517
void Dbdict::initTriggerRecords()
 
1518
{
 
1519
  TriggerRecordPtr triggerPtr;
 
1520
  while (1) {
 
1521
    jam();
 
1522
    refresh_watch_dog();
 
1523
    c_triggerRecordPool.seize(triggerPtr);
 
1524
    if (triggerPtr.i == RNIL) {
 
1525
      jam();
 
1526
      break;
 
1527
    }//if
 
1528
    initialiseTriggerRecord(triggerPtr);
 
1529
  }//while
 
1530
}
 
1531
 
 
1532
void Dbdict::initialiseTriggerRecord(TriggerRecordPtr triggerPtr)
 
1533
{
 
1534
  triggerPtr.p->triggerState = TriggerRecord::TS_NOT_DEFINED;
 
1535
  triggerPtr.p->triggerLocal = 0;
 
1536
  memset(triggerPtr.p->triggerName, 0, sizeof(triggerPtr.p->triggerName));
 
1537
  triggerPtr.p->triggerId = RNIL;
 
1538
  triggerPtr.p->tableId = RNIL;
 
1539
  triggerPtr.p->triggerType = (TriggerType::Value)~0;
 
1540
  triggerPtr.p->triggerActionTime = (TriggerActionTime::Value)~0;
 
1541
  triggerPtr.p->triggerEvent = (TriggerEvent::Value)~0;
 
1542
  triggerPtr.p->monitorReplicas = false;
 
1543
  triggerPtr.p->monitorAllAttributes = false;
 
1544
  triggerPtr.p->attributeMask.clear();
 
1545
  triggerPtr.p->indexId = RNIL;
 
1546
}
 
1547
 
 
1548
Uint32 Dbdict::getFsConnRecord() 
 
1549
{
 
1550
  FsConnectRecordPtr fsPtr;
 
1551
  c_fsConnectRecordPool.seize(fsPtr);
 
1552
  ndbrequire(fsPtr.i != RNIL);
 
1553
  fsPtr.p->filePtr = (Uint32)-1;
 
1554
  fsPtr.p->ownerPtr = RNIL;
 
1555
  fsPtr.p->fsState = FsConnectRecord::IDLE;
 
1556
  return fsPtr.i;
 
1557
}//Dbdict::getFsConnRecord()
 
1558
 
 
1559
Uint32 Dbdict::getFreeTableRecord(Uint32 primaryTableId) 
 
1560
{
 
1561
  Uint32 minId = (primaryTableId == RNIL ? 0 : primaryTableId + 1);
 
1562
  TableRecordPtr tablePtr;
 
1563
  TableRecordPtr firstTablePtr;
 
1564
  bool firstFound = false;
 
1565
  Uint32 tabSize = c_tableRecordPool.getSize();
 
1566
  for (tablePtr.i = minId; tablePtr.i < tabSize ; tablePtr.i++) {
 
1567
    jam();
 
1568
    c_tableRecordPool.getPtr(tablePtr);
 
1569
    if (tablePtr.p->tabState == TableRecord::NOT_DEFINED) {
 
1570
      jam();
 
1571
      initialiseTableRecord(tablePtr);
 
1572
      tablePtr.p->tabState = TableRecord::DEFINING;
 
1573
      firstFound = true;
 
1574
      firstTablePtr.i = tablePtr.i;
 
1575
      firstTablePtr.p = tablePtr.p;
 
1576
      break;
 
1577
    }//if
 
1578
  }//for
 
1579
  if (!firstFound) {
 
1580
    jam();
 
1581
    return RNIL;
 
1582
  }//if
 
1583
#ifdef HAVE_TABLE_REORG
 
1584
  bool secondFound = false;
 
1585
  for (tablePtr.i = firstTablePtr.i + 1; tablePtr.i < tabSize ; tablePtr.i++) {
 
1586
    jam();
 
1587
    c_tableRecordPool.getPtr(tablePtr);
 
1588
    if (tablePtr.p->tabState == TableRecord::NOT_DEFINED) {
 
1589
      jam();
 
1590
      initialiseTableRecord(tablePtr);
 
1591
      tablePtr.p->tabState = TableRecord::REORG_TABLE_PREPARED;
 
1592
      tablePtr.p->secondTable = firstTablePtr.i;
 
1593
      firstTablePtr.p->secondTable = tablePtr.i;
 
1594
      secondFound = true;
 
1595
      break;
 
1596
    }//if
 
1597
  }//for
 
1598
  if (!secondFound) {
 
1599
    jam();
 
1600
    firstTablePtr.p->tabState = TableRecord::NOT_DEFINED;
 
1601
    return RNIL;
 
1602
  }//if
 
1603
#endif
 
1604
  return firstTablePtr.i;
 
1605
}//Dbdict::getFreeTableRecord()
 
1606
 
 
1607
Uint32 Dbdict::getFreeTriggerRecord()
 
1608
{
 
1609
  const Uint32 size = c_triggerRecordPool.getSize();
 
1610
  TriggerRecordPtr triggerPtr;
 
1611
  for (triggerPtr.i = 0; triggerPtr.i < size; triggerPtr.i++) {
 
1612
    jam();
 
1613
    c_triggerRecordPool.getPtr(triggerPtr);
 
1614
    if (triggerPtr.p->triggerState == TriggerRecord::TS_NOT_DEFINED) {
 
1615
      jam();
 
1616
      initialiseTriggerRecord(triggerPtr);
 
1617
      return triggerPtr.i;
 
1618
    }
 
1619
  }
 
1620
  return RNIL;
 
1621
}
 
1622
 
 
1623
bool
 
1624
Dbdict::getNewAttributeRecord(TableRecordPtr tablePtr, 
 
1625
                              AttributeRecordPtr & attrPtr) 
 
1626
{
 
1627
  c_attributeRecordPool.seize(attrPtr);
 
1628
  if(attrPtr.i == RNIL){
 
1629
    return false;
 
1630
  }
 
1631
  
 
1632
  memset(attrPtr.p->attributeName, 0, sizeof(attrPtr.p->attributeName));
 
1633
  attrPtr.p->attributeDescriptor = 0x00012255; //Default value
 
1634
  attrPtr.p->attributeId = ZNIL;
 
1635
  attrPtr.p->nextAttrInTable = RNIL;
 
1636
  attrPtr.p->tupleKey = 0;
 
1637
  memset(attrPtr.p->defaultValue, 0, sizeof(attrPtr.p->defaultValue));
 
1638
  
 
1639
  /* ---------------------------------------------------------------- */
 
1640
  // A free attribute record has been acquired. We will now link it
 
1641
  // to the table record.
 
1642
  /* ---------------------------------------------------------------- */
 
1643
  if (tablePtr.p->lastAttribute == RNIL) {
 
1644
    jam();
 
1645
    tablePtr.p->firstAttribute = attrPtr.i;
 
1646
  } else {
 
1647
    jam();
 
1648
    AttributeRecordPtr lastAttrPtr;
 
1649
    c_attributeRecordPool.getPtr(lastAttrPtr, tablePtr.p->lastAttribute);
 
1650
    lastAttrPtr.p->nextAttrInTable = attrPtr.i;
 
1651
  }//if
 
1652
  tablePtr.p->lastAttribute = attrPtr.i;
 
1653
  return true;
 
1654
}//Dbdict::getNewAttributeRecord()
 
1655
 
 
1656
/* **************************************************************** */
 
1657
/* ---------------------------------------------------------------- */
 
1658
/* MODULE:          START/RESTART HANDLING ------------------------ */
 
1659
/* ---------------------------------------------------------------- */
 
1660
/*                                                                  */
 
1661
/* This module contains the code that is common for all             */
 
1662
/* start/restart types.                                             */
 
1663
/* ---------------------------------------------------------------- */
 
1664
/* **************************************************************** */
 
1665
 
 
1666
/* ---------------------------------------------------------------- */
 
1667
// This is sent as the first signal during start/restart.
 
1668
/* ---------------------------------------------------------------- */
 
1669
void Dbdict::execSTTOR(Signal* signal) 
 
1670
{
 
1671
  jamEntry();
 
1672
  c_startPhase = signal->theData[1];
 
1673
  switch (c_startPhase) {
 
1674
  case 1:
 
1675
    break;
 
1676
  case 3:
 
1677
    c_restartType = signal->theData[7];         /* valid if 3 */
 
1678
    ndbrequire(c_restartType == NodeState::ST_INITIAL_START ||
 
1679
               c_restartType == NodeState::ST_SYSTEM_RESTART ||
 
1680
               c_restartType == NodeState::ST_INITIAL_NODE_RESTART ||
 
1681
               c_restartType == NodeState::ST_NODE_RESTART);
 
1682
    break;
 
1683
  }
 
1684
  sendSTTORRY(signal);
 
1685
}//execSTTOR()
 
1686
 
 
1687
void Dbdict::sendSTTORRY(Signal* signal)
 
1688
{
 
1689
  signal->theData[0] = 0;       /* garbage SIGNAL KEY */
 
1690
  signal->theData[1] = 0;       /* garbage SIGNAL VERSION NUMBER  */
 
1691
  signal->theData[2] = 0;       /* garbage */
 
1692
  signal->theData[3] = 1;       /* first wanted start phase */
 
1693
  signal->theData[4] = 3;       /* get type of start */
 
1694
  signal->theData[5] = ZNOMOREPHASES;
 
1695
  sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 6, JBB);
 
1696
}
 
1697
 
 
1698
/* ---------------------------------------------------------------- */
 
1699
// We receive information about sizes of records.
 
1700
/* ---------------------------------------------------------------- */
 
1701
void Dbdict::execREAD_CONFIG_REQ(Signal* signal) 
 
1702
{
 
1703
  const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
 
1704
  Uint32 ref = req->senderRef;
 
1705
  Uint32 senderData = req->senderData;
 
1706
  ndbrequire(req->noOfParameters == 0);
 
1707
 
 
1708
  jamEntry();
 
1709
 
 
1710
  const ndb_mgm_configuration_iterator * p = 
 
1711
    theConfiguration.getOwnConfigIterator();
 
1712
  ndbrequire(p != 0);
 
1713
  
 
1714
  Uint32 attributesize, tablerecSize;
 
1715
  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DICT_ATTRIBUTE,&attributesize));
 
1716
  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DICT_TABLE, &tablerecSize));
 
1717
 
 
1718
  c_attributeRecordPool.setSize(attributesize);
 
1719
  c_attributeRecordHash.setSize(64);
 
1720
  c_fsConnectRecordPool.setSize(ZFS_CONNECT_SIZE);
 
1721
  c_nodes.setSize(MAX_NODES);
 
1722
  c_pageRecordArray.setSize(ZNUMBER_OF_PAGES);
 
1723
  c_schemaPageRecordArray.setSize(2 * NDB_SF_MAX_PAGES);
 
1724
  c_tableRecordPool.setSize(tablerecSize);
 
1725
  c_tableRecordHash.setSize(tablerecSize);
 
1726
  g_key_descriptor_pool.setSize(tablerecSize);
 
1727
  c_triggerRecordPool.setSize(c_maxNoOfTriggers);
 
1728
  c_triggerRecordHash.setSize(c_maxNoOfTriggers);
 
1729
  c_opRecordPool.setSize(256);   // XXX need config params
 
1730
  c_opCreateTable.setSize(8);
 
1731
  c_opDropTable.setSize(8);
 
1732
  c_opCreateIndex.setSize(8);
 
1733
  c_opDropIndex.setSize(8);
 
1734
  c_opAlterIndex.setSize(8);
 
1735
  c_opBuildIndex.setSize(8);
 
1736
  c_opCreateTrigger.setSize(8);
 
1737
  c_opDropTrigger.setSize(8);
 
1738
  c_opAlterTrigger.setSize(8);
 
1739
 
 
1740
  c_dictLockPool.setSize(32);
 
1741
  
 
1742
  // Initialize schema file copies
 
1743
  c_schemaFile[0].schemaPage =
 
1744
    (SchemaFile*)c_schemaPageRecordArray.getPtr(0 * NDB_SF_MAX_PAGES);
 
1745
  c_schemaFile[0].noOfPages = 0;
 
1746
  c_schemaFile[1].schemaPage =
 
1747
    (SchemaFile*)c_schemaPageRecordArray.getPtr(1 * NDB_SF_MAX_PAGES);
 
1748
  c_schemaFile[1].noOfPages = 0;
 
1749
 
 
1750
  // Initialize BAT for interface to file system
 
1751
  NewVARIABLE* bat = allocateBat(2);
 
1752
  bat[0].WA = &c_schemaPageRecordArray.getPtr(0)->word[0];
 
1753
  bat[0].nrr = 2 * NDB_SF_MAX_PAGES;
 
1754
  bat[0].ClusterSize = NDB_SF_PAGE_SIZE;
 
1755
  bat[0].bits.q = NDB_SF_PAGE_SIZE_IN_WORDS_LOG2;
 
1756
  bat[0].bits.v = 5;  // 32 bits per element
 
1757
  bat[1].WA = &c_pageRecordArray.getPtr(0)->word[0];
 
1758
  bat[1].nrr = ZNUMBER_OF_PAGES;
 
1759
  bat[1].ClusterSize = ZSIZE_OF_PAGES_IN_WORDS * 4;
 
1760
  bat[1].bits.q = ZLOG_SIZE_OF_PAGES_IN_WORDS; // 2**13 = 8192 elements
 
1761
  bat[1].bits.v = 5;  // 32 bits per element
 
1762
 
 
1763
  initCommonData();
 
1764
  initRecords();
 
1765
 
 
1766
  ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
 
1767
  conf->senderRef = reference();
 
1768
  conf->senderData = senderData;
 
1769
  sendSignal(ref, GSN_READ_CONFIG_CONF, signal, 
 
1770
             ReadConfigConf::SignalLength, JBB);
 
1771
}//execSIZEALT_REP()
 
1772
 
 
1773
/* ---------------------------------------------------------------- */
 
1774
// Start phase signals sent by CNTR. We reply with NDB_STTORRY when
 
1775
// we completed this phase.
 
1776
/* ---------------------------------------------------------------- */
 
1777
void Dbdict::execNDB_STTOR(Signal* signal) 
 
1778
{
 
1779
  jamEntry();
 
1780
  c_startPhase = signal->theData[2];
 
1781
  const Uint32 restartType = signal->theData[3];
 
1782
  if (restartType == NodeState::ST_INITIAL_START) {
 
1783
    jam();
 
1784
    c_initialStart = true;
 
1785
  } else if (restartType == NodeState::ST_SYSTEM_RESTART) {
 
1786
    jam();
 
1787
    c_systemRestart = true;
 
1788
  } else if (restartType == NodeState::ST_INITIAL_NODE_RESTART) {
 
1789
    jam();
 
1790
    c_initialNodeRestart = true;
 
1791
  } else if (restartType == NodeState::ST_NODE_RESTART) {
 
1792
    jam();
 
1793
    c_nodeRestart = true;
 
1794
  } else {
 
1795
    ndbrequire(false);
 
1796
  }//if
 
1797
  switch (c_startPhase) {
 
1798
  case 1:
 
1799
    jam();
 
1800
    initSchemaFile(signal);
 
1801
    break;
 
1802
  case 3:
 
1803
    jam();
 
1804
    signal->theData[0] = reference();
 
1805
    sendSignal(NDBCNTR_REF, GSN_READ_NODESREQ, signal, 1, JBB);
 
1806
    break;
 
1807
  case 6:
 
1808
    jam();
 
1809
    c_initialStart = false;
 
1810
    c_systemRestart = false;
 
1811
    c_initialNodeRestart = false;
 
1812
    c_nodeRestart = false;
 
1813
    sendNDB_STTORRY(signal);
 
1814
    break;
 
1815
  case 7:
 
1816
    // uses c_restartType
 
1817
    if(restartType == NodeState::ST_SYSTEM_RESTART &&
 
1818
       c_masterNodeId == getOwnNodeId()){
 
1819
      rebuildIndexes(signal, 0);
 
1820
      return;
 
1821
    }
 
1822
    sendNDB_STTORRY(signal);
 
1823
    break;
 
1824
  default:
 
1825
    jam();
 
1826
    sendNDB_STTORRY(signal);
 
1827
    break;
 
1828
  }//switch
 
1829
}//execNDB_STTOR()
 
1830
 
 
1831
void Dbdict::sendNDB_STTORRY(Signal* signal) 
 
1832
{
 
1833
  signal->theData[0] = reference();
 
1834
  sendSignal(NDBCNTR_REF, GSN_NDB_STTORRY, signal, 1, JBB);
 
1835
  return;
 
1836
}//sendNDB_STTORRY()
 
1837
 
 
1838
/* ---------------------------------------------------------------- */
 
1839
// We receive the information about which nodes that are up and down.
 
1840
/* ---------------------------------------------------------------- */
 
1841
void Dbdict::execREAD_NODESCONF(Signal* signal) 
 
1842
{
 
1843
  jamEntry();
 
1844
 
 
1845
  ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
 
1846
  c_numberNode   = readNodes->noOfNodes;
 
1847
  c_masterNodeId = readNodes->masterNodeId;
 
1848
 
 
1849
  c_noNodesFailed = 0;
 
1850
  c_aliveNodes.clear();
 
1851
  for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
 
1852
    jam();
 
1853
    NodeRecordPtr nodePtr;
 
1854
    c_nodes.getPtr(nodePtr, i);
 
1855
 
 
1856
    if (NodeBitmask::get(readNodes->allNodes, i)) {
 
1857
      jam();
 
1858
      nodePtr.p->nodeState = NodeRecord::NDB_NODE_ALIVE;
 
1859
      if (NodeBitmask::get(readNodes->inactiveNodes, i)) {
 
1860
        jam();
 
1861
        /**-------------------------------------------------------------------
 
1862
         *
 
1863
         * THIS NODE IS DEFINED IN THE CLUSTER BUT IS NOT ALIVE CURRENTLY.
 
1864
         * WE ADD THE NODE TO THE SET OF FAILED NODES AND ALSO SET THE
 
1865
         * BLOCKSTATE TO BUSY TO AVOID ADDING TABLES WHILE NOT ALL NODES ARE
 
1866
         * ALIVE.
 
1867
         *------------------------------------------------------------------*/
 
1868
        nodePtr.p->nodeState = NodeRecord::NDB_NODE_DEAD;
 
1869
        c_noNodesFailed++;
 
1870
      } else {
 
1871
        c_aliveNodes.set(i);
 
1872
      }
 
1873
    }//if
 
1874
  }//for
 
1875
  sendNDB_STTORRY(signal);
 
1876
}//execREAD_NODESCONF()
 
1877
 
 
1878
/* ---------------------------------------------------------------- */
 
1879
// HOT_SPAREREP informs DBDICT about which nodes that have become
 
1880
// hot spare nodes.
 
1881
/* ---------------------------------------------------------------- */
 
1882
void Dbdict::execHOT_SPAREREP(Signal* signal) 
 
1883
{
 
1884
  Uint32 hotSpareNodes = 0;
 
1885
  jamEntry();
 
1886
  HotSpareRep * const hotSpare = (HotSpareRep*)&signal->theData[0];
 
1887
  for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
 
1888
    if (NodeBitmask::get(hotSpare->theHotSpareNodes, i)) {
 
1889
      NodeRecordPtr nodePtr;
 
1890
      c_nodes.getPtr(nodePtr, i);
 
1891
      nodePtr.p->hotSpare = true;
 
1892
      hotSpareNodes++;
 
1893
    }//if
 
1894
  }//for
 
1895
  ndbrequire(hotSpareNodes == hotSpare->noHotSpareNodes);
 
1896
  c_noHotSpareNodes = hotSpareNodes;
 
1897
  return;
 
1898
}//execHOT_SPAREREP()
 
1899
 
 
1900
void Dbdict::initSchemaFile(Signal* signal) 
 
1901
{
 
1902
  XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
 
1903
  xsf->noOfPages = (c_tableRecordPool.getSize() + NDB_SF_PAGE_ENTRIES - 1)
 
1904
                   / NDB_SF_PAGE_ENTRIES;
 
1905
  initSchemaFile(xsf, 0, xsf->noOfPages, true);
 
1906
  // init alt copy too for INR
 
1907
  XSchemaFile * oldxsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0];
 
1908
  oldxsf->noOfPages = xsf->noOfPages;
 
1909
  memcpy(&oldxsf->schemaPage[0], &xsf->schemaPage[0], xsf->schemaPage[0].FileSize);
 
1910
  
 
1911
  if (c_initialStart || c_initialNodeRestart) {    
 
1912
    jam();
 
1913
    ndbrequire(c_writeSchemaRecord.inUse == false);
 
1914
    c_writeSchemaRecord.inUse = true;
 
1915
    c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
 
1916
    c_writeSchemaRecord.newFile = true;
 
1917
    c_writeSchemaRecord.firstPage = 0;
 
1918
    c_writeSchemaRecord.noOfPages = xsf->noOfPages;
 
1919
 
 
1920
    c_writeSchemaRecord.m_callback.m_callbackFunction = 
 
1921
      safe_cast(&Dbdict::initSchemaFile_conf);
 
1922
    
 
1923
    startWriteSchemaFile(signal);
 
1924
  } else if (c_systemRestart || c_nodeRestart) {
 
1925
    jam();
 
1926
    ndbrequire(c_readSchemaRecord.schemaReadState == ReadSchemaRecord::IDLE);
 
1927
    c_readSchemaRecord.pageId = c_schemaRecord.oldSchemaPage;
 
1928
    c_readSchemaRecord.firstPage = 0;
 
1929
    c_readSchemaRecord.noOfPages = 1;
 
1930
    c_readSchemaRecord.schemaReadState = ReadSchemaRecord::INITIAL_READ_HEAD;
 
1931
    startReadSchemaFile(signal);
 
1932
  } else {
 
1933
    ndbrequire(false);
 
1934
  }//if
 
1935
}//Dbdict::initSchemaFile()
 
1936
 
 
1937
void
 
1938
Dbdict::initSchemaFile_conf(Signal* signal, Uint32 callbackData, Uint32 rv){
 
1939
  jam();
 
1940
  sendNDB_STTORRY(signal);
 
1941
}
 
1942
 
 
1943
void
 
1944
Dbdict::activateIndexes(Signal* signal, Uint32 i)
 
1945
{
 
1946
  AlterIndxReq* req = (AlterIndxReq*)signal->getDataPtrSend();
 
1947
  TableRecordPtr tablePtr;
 
1948
  for (; i < c_tableRecordPool.getSize(); i++) {
 
1949
    tablePtr.i = i;
 
1950
    c_tableRecordPool.getPtr(tablePtr);
 
1951
    if (tablePtr.p->tabState != TableRecord::DEFINED)
 
1952
      continue;
 
1953
    if (! tablePtr.p->isIndex())
 
1954
      continue;
 
1955
    jam();
 
1956
    req->setUserRef(reference());
 
1957
    req->setConnectionPtr(i);
 
1958
    req->setTableId(tablePtr.p->primaryTableId);
 
1959
    req->setIndexId(tablePtr.i);
 
1960
    req->setIndexVersion(tablePtr.p->tableVersion);
 
1961
    req->setOnline(true);
 
1962
    if (c_restartType == NodeState::ST_SYSTEM_RESTART) {
 
1963
      if (c_masterNodeId != getOwnNodeId())
 
1964
        continue;
 
1965
      // from file index state is not defined currently
 
1966
      req->setRequestType(AlterIndxReq::RT_SYSTEMRESTART);
 
1967
      req->addRequestFlag((Uint32)RequestFlag::RF_NOBUILD);
 
1968
    }
 
1969
    else if (
 
1970
        c_restartType == NodeState::ST_NODE_RESTART ||
 
1971
        c_restartType == NodeState::ST_INITIAL_NODE_RESTART) {
 
1972
      // from master index must be online
 
1973
      if (tablePtr.p->indexState != TableRecord::IS_ONLINE)
 
1974
        continue;
 
1975
      req->setRequestType(AlterIndxReq::RT_NODERESTART);
 
1976
      // activate locally, rebuild not needed
 
1977
      req->addRequestFlag((Uint32)RequestFlag::RF_LOCAL);
 
1978
      req->addRequestFlag((Uint32)RequestFlag::RF_NOBUILD);
 
1979
    } else {
 
1980
      ndbrequire(false);
 
1981
    }
 
1982
    sendSignal(reference(), GSN_ALTER_INDX_REQ,
 
1983
      signal, AlterIndxReq::SignalLength, JBB);
 
1984
    return;
 
1985
  }
 
1986
  signal->theData[0] = reference();
 
1987
  sendSignal(c_restartRecord.returnBlockRef, GSN_DICTSTARTCONF,
 
1988
             signal, 1, JBB);
 
1989
}
 
1990
 
 
1991
void
 
1992
Dbdict::rebuildIndexes(Signal* signal, Uint32 i){
 
1993
  BuildIndxReq* const req = (BuildIndxReq*)signal->getDataPtrSend();
 
1994
  
 
1995
  TableRecordPtr indexPtr;
 
1996
  for (; i < c_tableRecordPool.getSize(); i++) {
 
1997
    indexPtr.i = i;
 
1998
    c_tableRecordPool.getPtr(indexPtr);
 
1999
    if (indexPtr.p->tabState != TableRecord::DEFINED)
 
2000
      continue;
 
2001
    if (! indexPtr.p->isIndex())
 
2002
      continue;
 
2003
 
 
2004
    jam();
 
2005
 
 
2006
    req->setUserRef(reference());
 
2007
    req->setConnectionPtr(i);
 
2008
    req->setRequestType(BuildIndxReq::RT_SYSTEMRESTART);
 
2009
    req->setBuildId(0);   // not used
 
2010
    req->setBuildKey(0);  // not used
 
2011
    req->setIndexType(indexPtr.p->tableType);
 
2012
    req->setIndexId(indexPtr.i);
 
2013
    req->setTableId(indexPtr.p->primaryTableId);
 
2014
    req->setParallelism(16);
 
2015
 
 
2016
    // from file index state is not defined currently
 
2017
    if (indexPtr.p->storedTable) {
 
2018
      // rebuild not needed
 
2019
      req->addRequestFlag((Uint32)RequestFlag::RF_NOBUILD);
 
2020
    }
 
2021
    
 
2022
    // send
 
2023
    sendSignal(reference(), GSN_BUILDINDXREQ,
 
2024
               signal, BuildIndxReq::SignalLength, JBB);
 
2025
    return;
 
2026
  }
 
2027
  sendNDB_STTORRY(signal);
 
2028
}
 
2029
 
 
2030
 
 
2031
/* **************************************************************** */
 
2032
/* ---------------------------------------------------------------- */
 
2033
/* MODULE:          SYSTEM RESTART MODULE ------------------------- */
 
2034
/* ---------------------------------------------------------------- */
 
2035
/*                                                                  */
 
2036
/* This module contains code specific for system restart            */
 
2037
/* ---------------------------------------------------------------- */
 
2038
/* **************************************************************** */
 
2039
 
 
2040
/* ---------------------------------------------------------------- */
 
2041
// DIH asks DICT to read in table data from disk during system
 
2042
// restart. DIH also asks DICT to send information about which
 
2043
// tables that should be started as part of this system restart.
 
2044
// DICT will also activate the tables in TC as part of this process.
 
2045
/* ---------------------------------------------------------------- */
 
2046
void Dbdict::execDICTSTARTREQ(Signal* signal) 
 
2047
{
 
2048
  jamEntry();
 
2049
  c_restartRecord.gciToRestart = signal->theData[0];
 
2050
  c_restartRecord.returnBlockRef = signal->theData[1];
 
2051
  if (c_nodeRestart || c_initialNodeRestart) {
 
2052
    jam();   
 
2053
 
 
2054
    CRASH_INSERTION(6000);
 
2055
 
 
2056
    BlockReference dictRef = calcDictBlockRef(c_masterNodeId);
 
2057
    signal->theData[0] = getOwnNodeId();
 
2058
    sendSignal(dictRef, GSN_GET_SCHEMA_INFOREQ, signal, 1, JBB);
 
2059
    return;
 
2060
  }
 
2061
  ndbrequire(c_systemRestart);
 
2062
  ndbrequire(c_masterNodeId == getOwnNodeId());
 
2063
 
 
2064
  c_schemaRecord.m_callback.m_callbackData = 0;
 
2065
  c_schemaRecord.m_callback.m_callbackFunction = 
 
2066
    safe_cast(&Dbdict::masterRestart_checkSchemaStatusComplete);
 
2067
 
 
2068
  c_restartRecord.activeTable = 0;
 
2069
  c_schemaRecord.schemaPage = c_schemaRecord.oldSchemaPage; // ugly
 
2070
  checkSchemaStatus(signal);
 
2071
}//execDICTSTARTREQ()
 
2072
 
 
2073
void
 
2074
Dbdict::masterRestart_checkSchemaStatusComplete(Signal* signal,
 
2075
                                                Uint32 callbackData,
 
2076
                                                Uint32 returnCode){
 
2077
 
 
2078
  c_schemaRecord.schemaPage = 0; // ugly
 
2079
  XSchemaFile * oldxsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0];
 
2080
  ndbrequire(oldxsf->noOfPages != 0);
 
2081
 
 
2082
  LinearSectionPtr ptr[3];
 
2083
  ptr[0].p = (Uint32*)&oldxsf->schemaPage[0];
 
2084
  ptr[0].sz = oldxsf->noOfPages * NDB_SF_PAGE_SIZE_IN_WORDS;
 
2085
 
 
2086
  c_sendSchemaRecord.m_SCHEMAINFO_Counter = c_aliveNodes;
 
2087
  NodeReceiverGroup rg(DBDICT, c_aliveNodes);
 
2088
 
 
2089
  rg.m_nodes.clear(getOwnNodeId());
 
2090
  Callback c = { 0, 0 };
 
2091
  sendFragmentedSignal(rg,
 
2092
                       GSN_SCHEMA_INFO,
 
2093
                       signal, 
 
2094
                       1, //SchemaInfo::SignalLength,
 
2095
                       JBB,
 
2096
                       ptr,
 
2097
                       1,
 
2098
                       c);
 
2099
 
 
2100
  XSchemaFile * newxsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
 
2101
  newxsf->noOfPages = oldxsf->noOfPages;
 
2102
  memcpy(&newxsf->schemaPage[0], &oldxsf->schemaPage[0],
 
2103
         oldxsf->noOfPages * NDB_SF_PAGE_SIZE);
 
2104
 
 
2105
  signal->theData[0] = getOwnNodeId();
 
2106
  sendSignal(reference(), GSN_SCHEMA_INFOCONF, signal, 1, JBB);
 
2107
}
 
2108
 
 
2109
void 
 
2110
Dbdict::execGET_SCHEMA_INFOREQ(Signal* signal){
 
2111
 
 
2112
  const Uint32 ref = signal->getSendersBlockRef();
 
2113
  //const Uint32 senderData = signal->theData[0];
 
2114
  
 
2115
  ndbrequire(c_sendSchemaRecord.inUse == false);
 
2116
  c_sendSchemaRecord.inUse = true;
 
2117
 
 
2118
  LinearSectionPtr ptr[3];
 
2119
  
 
2120
  XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
 
2121
  ndbrequire(xsf->noOfPages != 0);
 
2122
  
 
2123
  ptr[0].p = (Uint32*)&xsf->schemaPage[0];
 
2124
  ptr[0].sz = xsf->noOfPages * NDB_SF_PAGE_SIZE_IN_WORDS;
 
2125
 
 
2126
  Callback c = { safe_cast(&Dbdict::sendSchemaComplete), 0 };
 
2127
  sendFragmentedSignal(ref,
 
2128
                       GSN_SCHEMA_INFO,
 
2129
                       signal, 
 
2130
                       1, //GetSchemaInfoConf::SignalLength,
 
2131
                       JBB,
 
2132
                       ptr,
 
2133
                       1,
 
2134
                       c);
 
2135
}//Dbdict::execGET_SCHEMA_INFOREQ()
 
2136
 
 
2137
void
 
2138
Dbdict::sendSchemaComplete(Signal * signal, 
 
2139
                           Uint32 callbackData,
 
2140
                           Uint32 returnCode){
 
2141
  ndbrequire(c_sendSchemaRecord.inUse == true);
 
2142
  c_sendSchemaRecord.inUse = false;
 
2143
 
 
2144
}
 
2145
 
 
2146
 
 
2147
/* ---------------------------------------------------------------- */
 
2148
// We receive the schema info from master as part of all restarts
 
2149
// except the initial start where no tables exists.
 
2150
/* ---------------------------------------------------------------- */
 
2151
void Dbdict::execSCHEMA_INFO(Signal* signal) 
 
2152
{
 
2153
  jamEntry();
 
2154
  if(!assembleFragments(signal)){
 
2155
    jam();
 
2156
    return;
 
2157
  }
 
2158
 
 
2159
  if(getNodeState().getNodeRestartInProgress()){
 
2160
    CRASH_INSERTION(6001);
 
2161
  }
 
2162
 
 
2163
  SegmentedSectionPtr schemaDataPtr;
 
2164
  signal->getSection(schemaDataPtr, 0);
 
2165
 
 
2166
  XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
 
2167
  ndbrequire(schemaDataPtr.sz % NDB_SF_PAGE_SIZE_IN_WORDS == 0);
 
2168
  xsf->noOfPages = schemaDataPtr.sz / NDB_SF_PAGE_SIZE_IN_WORDS;
 
2169
  copy((Uint32*)&xsf->schemaPage[0], schemaDataPtr);
 
2170
  releaseSections(signal);
 
2171
  
 
2172
  SchemaFile * sf0 = &xsf->schemaPage[0];
 
2173
  if (sf0->NdbVersion < NDB_SF_VERSION_5_0_6) {
 
2174
    bool ok = convertSchemaFileTo_5_0_6(xsf);
 
2175
    ndbrequire(ok);
 
2176
  }
 
2177
    
 
2178
  validateChecksum(xsf);
 
2179
 
 
2180
  XSchemaFile * oldxsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0];
 
2181
  resizeSchemaFile(xsf, oldxsf->noOfPages);
 
2182
 
 
2183
  ndbrequire(signal->getSendersBlockRef() != reference());
 
2184
    
 
2185
  /* ---------------------------------------------------------------- */
 
2186
  // Synchronise our view on data with other nodes in the cluster.
 
2187
  // This is an important part of restart handling where we will handle
 
2188
  // cases where the table have been added but only partially, where
 
2189
  // tables have been deleted but not completed the deletion yet and
 
2190
  // other scenarios needing synchronisation.
 
2191
  /* ---------------------------------------------------------------- */
 
2192
  c_schemaRecord.m_callback.m_callbackData = 0;
 
2193
  c_schemaRecord.m_callback.m_callbackFunction = 
 
2194
    safe_cast(&Dbdict::restart_checkSchemaStatusComplete);
 
2195
  c_restartRecord.activeTable = 0;
 
2196
  checkSchemaStatus(signal);
 
2197
}//execSCHEMA_INFO()
 
2198
 
 
2199
void
 
2200
Dbdict::restart_checkSchemaStatusComplete(Signal * signal, 
 
2201
                                          Uint32 callbackData,
 
2202
                                          Uint32 returnCode){
 
2203
 
 
2204
  ndbrequire(c_writeSchemaRecord.inUse == false);
 
2205
  c_writeSchemaRecord.inUse = true;
 
2206
  XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
 
2207
  c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
 
2208
  c_writeSchemaRecord.newFile = true;
 
2209
  c_writeSchemaRecord.firstPage = 0;
 
2210
  c_writeSchemaRecord.noOfPages = xsf->noOfPages;
 
2211
  c_writeSchemaRecord.m_callback.m_callbackData = 0;
 
2212
  c_writeSchemaRecord.m_callback.m_callbackFunction = 
 
2213
    safe_cast(&Dbdict::restart_writeSchemaConf);
 
2214
  
 
2215
  startWriteSchemaFile(signal);
 
2216
}
 
2217
 
 
2218
void
 
2219
Dbdict::restart_writeSchemaConf(Signal * signal, 
 
2220
                                Uint32 callbackData,
 
2221
                                Uint32 returnCode){
 
2222
 
 
2223
  if(c_systemRestart){
 
2224
    jam();
 
2225
    signal->theData[0] = getOwnNodeId();
 
2226
    sendSignal(calcDictBlockRef(c_masterNodeId), GSN_SCHEMA_INFOCONF,
 
2227
               signal, 1, JBB);
 
2228
    return;
 
2229
  }
 
2230
  
 
2231
  ndbrequire(c_nodeRestart || c_initialNodeRestart);
 
2232
  c_blockState = BS_IDLE;
 
2233
  activateIndexes(signal, 0);
 
2234
  return;
 
2235
}
 
2236
 
 
2237
void Dbdict::execSCHEMA_INFOCONF(Signal* signal) 
 
2238
{
 
2239
  jamEntry();
 
2240
  ndbrequire(signal->getNoOfSections() == 0);
 
2241
 
 
2242
/* ---------------------------------------------------------------- */
 
2243
// This signal is received in the master as part of system restart
 
2244
// from all nodes (including the master) after they have synchronised
 
2245
// their data with the master node's schema information.
 
2246
/* ---------------------------------------------------------------- */
 
2247
  const Uint32 nodeId = signal->theData[0];
 
2248
  c_sendSchemaRecord.m_SCHEMAINFO_Counter.clearWaitingFor(nodeId);
 
2249
 
 
2250
  if (!c_sendSchemaRecord.m_SCHEMAINFO_Counter.done()){
 
2251
    jam();
 
2252
    return;
 
2253
  }//if
 
2254
  activateIndexes(signal, 0);
 
2255
}//execSCHEMA_INFOCONF()
 
2256
 
 
2257
void Dbdict::checkSchemaStatus(Signal* signal) 
 
2258
{
 
2259
  XSchemaFile * newxsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
 
2260
  XSchemaFile * oldxsf = &c_schemaFile[c_schemaRecord.oldSchemaPage != 0];
 
2261
  ndbrequire(newxsf->noOfPages == oldxsf->noOfPages);
 
2262
  const Uint32 noOfEntries = newxsf->noOfPages * NDB_SF_PAGE_ENTRIES;
 
2263
 
 
2264
  for (; c_restartRecord.activeTable < noOfEntries;
 
2265
       c_restartRecord.activeTable++) {
 
2266
    jam();
 
2267
 
 
2268
    Uint32 tableId = c_restartRecord.activeTable;
 
2269
    SchemaFile::TableEntry *newEntry = getTableEntry(newxsf, tableId);
 
2270
    SchemaFile::TableEntry *oldEntry = getTableEntry(oldxsf, tableId);
 
2271
    SchemaFile::TableState schemaState = 
 
2272
      (SchemaFile::TableState)newEntry->m_tableState;
 
2273
    SchemaFile::TableState oldSchemaState = 
 
2274
      (SchemaFile::TableState)oldEntry->m_tableState;
 
2275
 
 
2276
    if (c_restartRecord.activeTable >= c_tableRecordPool.getSize()) {
 
2277
      jam();
 
2278
      ndbrequire(schemaState == SchemaFile::INIT);
 
2279
      ndbrequire(oldSchemaState == SchemaFile::INIT);
 
2280
      continue;
 
2281
    }//if
 
2282
 
 
2283
    switch(schemaState){
 
2284
    case SchemaFile::INIT:{
 
2285
      jam();
 
2286
      bool ok = false;
 
2287
      switch(oldSchemaState) {
 
2288
      case SchemaFile::INIT:
 
2289
        jam();
 
2290
      case SchemaFile::DROP_TABLE_COMMITTED:
 
2291
        jam();
 
2292
        ok = true;
 
2293
        jam();
 
2294
        break;
 
2295
 
 
2296
      case SchemaFile::ADD_STARTED:
 
2297
        jam();
 
2298
      case SchemaFile::TABLE_ADD_COMMITTED:
 
2299
        jam();
 
2300
      case SchemaFile::DROP_TABLE_STARTED:
 
2301
        jam();
 
2302
      case SchemaFile::ALTER_TABLE_COMMITTED:
 
2303
        jam();
 
2304
        ok = true;
 
2305
        jam();
 
2306
        newEntry->m_tableState = SchemaFile::INIT;
 
2307
        restartDropTab(signal, tableId);
 
2308
        return;
 
2309
      }//switch
 
2310
      ndbrequire(ok);
 
2311
      break;
 
2312
    }
 
2313
    case SchemaFile::ADD_STARTED:{
 
2314
      jam();
 
2315
      bool ok = false;
 
2316
      switch(oldSchemaState) {
 
2317
      case SchemaFile::INIT:
 
2318
        jam();
 
2319
      case SchemaFile::DROP_TABLE_COMMITTED:
 
2320
        jam();
 
2321
        ok = true;
 
2322
        break;
 
2323
      case SchemaFile::ADD_STARTED: 
 
2324
        jam();
 
2325
      case SchemaFile::DROP_TABLE_STARTED:
 
2326
        jam();
 
2327
      case SchemaFile::TABLE_ADD_COMMITTED:
 
2328
        jam();
 
2329
      case SchemaFile::ALTER_TABLE_COMMITTED:
 
2330
        jam();
 
2331
        ok = true;
 
2332
        //------------------------------------------------------------------
 
2333
        // Add Table was started but not completed. Will be dropped in all
 
2334
        // nodes. Update schema information (restore table version).
 
2335
        //------------------------------------------------------------------
 
2336
        newEntry->m_tableState = SchemaFile::INIT;
 
2337
        restartDropTab(signal, tableId);
 
2338
        return;
 
2339
      }
 
2340
      ndbrequire(ok);
 
2341
      break;
 
2342
    }
 
2343
    case SchemaFile::TABLE_ADD_COMMITTED:{
 
2344
      jam();
 
2345
      bool ok = false;
 
2346
      switch(oldSchemaState) {
 
2347
      case SchemaFile::INIT:
 
2348
        jam();
 
2349
      case SchemaFile::ADD_STARTED:
 
2350
        jam();
 
2351
      case SchemaFile::DROP_TABLE_STARTED:
 
2352
        jam();
 
2353
      case SchemaFile::DROP_TABLE_COMMITTED:
 
2354
        jam();
 
2355
        ok = true;
 
2356
        //------------------------------------------------------------------
 
2357
        // Table was added in the master node but not in our node. We can
 
2358
        // retrieve the table definition from the master.
 
2359
        //------------------------------------------------------------------
 
2360
        restartCreateTab(signal, tableId, oldEntry, false);
 
2361
        return;
 
2362
        break;
 
2363
      case SchemaFile::TABLE_ADD_COMMITTED:
 
2364
        jam();
 
2365
      case SchemaFile::ALTER_TABLE_COMMITTED:
 
2366
        jam();
 
2367
        ok = true;
 
2368
        //------------------------------------------------------------------
 
2369
        // Table was added in both our node and the master node. We can
 
2370
        // retrieve the table definition from our own disk.
 
2371
        //------------------------------------------------------------------
 
2372
        if(* newEntry == * oldEntry){
 
2373
          jam();
 
2374
          
 
2375
          TableRecordPtr tablePtr;
 
2376
          c_tableRecordPool.getPtr(tablePtr, tableId);
 
2377
          tablePtr.p->tableVersion = oldEntry->m_tableVersion;
 
2378
          tablePtr.p->tableType = (DictTabInfo::TableType)oldEntry->m_tableType;
 
2379
          
 
2380
          // On NR get index from master because index state is not on file
 
2381
          const bool file = c_systemRestart || tablePtr.p->isTable();
 
2382
          restartCreateTab(signal, tableId, oldEntry, file);
 
2383
 
 
2384
          return;
 
2385
        } else {
 
2386
          //------------------------------------------------------------------
 
2387
          // Must be a new version of the table if anything differs. Both table
 
2388
          // version and global checkpoint must be different.
 
2389
          // This should not happen for the master node. This can happen after
 
2390
          // drop table followed by add table or after change table.
 
2391
          // Not supported in this version.
 
2392
          //------------------------------------------------------------------
 
2393
          ndbrequire(c_masterNodeId != getOwnNodeId());
 
2394
          ndbrequire(newEntry->m_tableVersion != oldEntry->m_tableVersion);
 
2395
          jam();
 
2396
          
 
2397
          restartCreateTab(signal, tableId, oldEntry, false);
 
2398
          return;
 
2399
        }//if
 
2400
      }
 
2401
      ndbrequire(ok);
 
2402
      break;
 
2403
    }
 
2404
    case SchemaFile::DROP_TABLE_STARTED:
 
2405
      jam();
 
2406
    case SchemaFile::DROP_TABLE_COMMITTED:{
 
2407
      jam();
 
2408
      bool ok = false;
 
2409
      switch(oldSchemaState){
 
2410
      case SchemaFile::INIT:
 
2411
        jam();
 
2412
      case SchemaFile::DROP_TABLE_COMMITTED:
 
2413
        jam();
 
2414
        ok = true;
 
2415
        break;
 
2416
      case SchemaFile::ADD_STARTED:
 
2417
        jam();
 
2418
      case SchemaFile::TABLE_ADD_COMMITTED:
 
2419
        jam();
 
2420
      case SchemaFile::DROP_TABLE_STARTED:
 
2421
        jam();
 
2422
      case SchemaFile::ALTER_TABLE_COMMITTED:
 
2423
        jam();
 
2424
        newEntry->m_tableState = SchemaFile::INIT;
 
2425
        restartDropTab(signal, tableId);
 
2426
        return;
 
2427
      }
 
2428
      ndbrequire(ok);
 
2429
      break;
 
2430
    }
 
2431
    case SchemaFile::ALTER_TABLE_COMMITTED: {
 
2432
      jam();
 
2433
      bool ok = false;
 
2434
      switch(oldSchemaState) {
 
2435
      case SchemaFile::INIT:
 
2436
        jam();
 
2437
      case SchemaFile::ADD_STARTED:
 
2438
        jam();
 
2439
      case SchemaFile::DROP_TABLE_STARTED:
 
2440
        jam();
 
2441
      case SchemaFile::DROP_TABLE_COMMITTED:
 
2442
        jam();
 
2443
      case SchemaFile::TABLE_ADD_COMMITTED:
 
2444
        jam();
 
2445
        ok = true;
 
2446
        //------------------------------------------------------------------
 
2447
        // Table was altered in the master node but not in our node. We can
 
2448
        // retrieve the altered table definition from the master.
 
2449
        //------------------------------------------------------------------
 
2450
        restartCreateTab(signal, tableId, oldEntry, false);
 
2451
        return;
 
2452
        break;
 
2453
      case SchemaFile::ALTER_TABLE_COMMITTED:
 
2454
        jam();
 
2455
        ok = true;
 
2456
        
 
2457
        //------------------------------------------------------------------
 
2458
        // Table was altered in both our node and the master node. We can
 
2459
        // retrieve the table definition from our own disk.
 
2460
        //------------------------------------------------------------------
 
2461
        TableRecordPtr tablePtr;
 
2462
        c_tableRecordPool.getPtr(tablePtr, tableId);
 
2463
        tablePtr.p->tableVersion = oldEntry->m_tableVersion;
 
2464
        tablePtr.p->tableType = (DictTabInfo::TableType)oldEntry->m_tableType;
 
2465
        
 
2466
        // On NR get index from master because index state is not on file
 
2467
        const bool file = (* newEntry == * oldEntry) &&
 
2468
          (c_systemRestart || tablePtr.p->isTable());
 
2469
        restartCreateTab(signal, tableId, oldEntry, file);
 
2470
 
 
2471
        return;
 
2472
      }
 
2473
      ndbrequire(ok);
 
2474
      break;
 
2475
    }
 
2476
    }
 
2477
  }
 
2478
  
 
2479
  execute(signal, c_schemaRecord.m_callback, 0);
 
2480
}//checkSchemaStatus()
 
2481
 
 
2482
void
 
2483
Dbdict::restartCreateTab(Signal* signal, Uint32 tableId, 
 
2484
                      const SchemaFile::TableEntry * te, bool file){
 
2485
  jam();
 
2486
  
 
2487
  CreateTableRecordPtr createTabPtr;  
 
2488
  c_opCreateTable.seize(createTabPtr);
 
2489
  ndbrequire(!createTabPtr.isNull());
 
2490
 
 
2491
  createTabPtr.p->key = ++c_opRecordSequence;
 
2492
  c_opCreateTable.add(createTabPtr);
 
2493
  
 
2494
  createTabPtr.p->m_errorCode = 0;
 
2495
  createTabPtr.p->m_tablePtrI = tableId;
 
2496
  createTabPtr.p->m_coordinatorRef = reference();
 
2497
  createTabPtr.p->m_senderRef = 0;
 
2498
  createTabPtr.p->m_senderData = RNIL;
 
2499
  createTabPtr.p->m_tabInfoPtrI = RNIL;
 
2500
  createTabPtr.p->m_dihAddFragPtr = RNIL;
 
2501
 
 
2502
  if(file && !ERROR_INSERTED(6002)){
 
2503
    jam();
 
2504
    
 
2505
    c_readTableRecord.noOfPages =
 
2506
      DIV(te->m_info_words + ZPAGE_HEADER_SIZE, ZSIZE_OF_PAGES_IN_WORDS);
 
2507
    c_readTableRecord.pageId = 0;
 
2508
    c_readTableRecord.m_callback.m_callbackData = createTabPtr.p->key;
 
2509
    c_readTableRecord.m_callback.m_callbackFunction = 
 
2510
      safe_cast(&Dbdict::restartCreateTab_readTableConf);
 
2511
    
 
2512
    startReadTableFile(signal, tableId);
 
2513
    return;
 
2514
  } else {
 
2515
    
 
2516
    ndbrequire(c_masterNodeId != getOwnNodeId());
 
2517
    
 
2518
    /**
 
2519
     * Get from master
 
2520
     */
 
2521
    GetTabInfoReq * const req = (GetTabInfoReq *)&signal->theData[0];
 
2522
    req->senderRef = reference();
 
2523
    req->senderData = createTabPtr.p->key;
 
2524
    req->requestType = GetTabInfoReq::RequestById |
 
2525
      GetTabInfoReq::LongSignalConf;
 
2526
    req->tableId = tableId;
 
2527
    sendSignal(calcDictBlockRef(c_masterNodeId), GSN_GET_TABINFOREQ, signal,
 
2528
               GetTabInfoReq::SignalLength, JBB);
 
2529
 
 
2530
    if(ERROR_INSERTED(6002)){
 
2531
      NdbSleep_MilliSleep(10);
 
2532
      CRASH_INSERTION(6002);
 
2533
    }
 
2534
  }
 
2535
}
 
2536
 
 
2537
void
 
2538
Dbdict::restartCreateTab_readTableConf(Signal* signal, 
 
2539
                                       Uint32 callbackData,
 
2540
                                       Uint32 returnCode){
 
2541
  jam();
 
2542
  
 
2543
  PageRecordPtr pageRecPtr;
 
2544
  c_pageRecordArray.getPtr(pageRecPtr, c_readTableRecord.pageId);
 
2545
 
 
2546
  ParseDictTabInfoRecord parseRecord;
 
2547
  parseRecord.requestType = DictTabInfo::GetTabInfoConf;
 
2548
  parseRecord.errorCode = 0;
 
2549
  
 
2550
  Uint32 sz = c_readTableRecord.noOfPages * ZSIZE_OF_PAGES_IN_WORDS; 
 
2551
  SimplePropertiesLinearReader r(&pageRecPtr.p->word[0], sz);
 
2552
  handleTabInfoInit(r, &parseRecord);
 
2553
  if (parseRecord.errorCode != 0)
 
2554
  {
 
2555
    char buf[255];
 
2556
    BaseString::snprintf(buf, sizeof(buf), 
 
2557
                         "Unable to restart, fail while creating table %d"
 
2558
                         " error: %d. Most likely change of configuration",
 
2559
                         c_readTableRecord.tableId,
 
2560
                         parseRecord.errorCode);
 
2561
    progError(__LINE__, 
 
2562
              NDBD_EXIT_INVALID_CONFIG,
 
2563
              buf);
 
2564
    ndbrequire(parseRecord.errorCode == 0);
 
2565
  }
 
2566
  
 
2567
  /* ---------------------------------------------------------------- */
 
2568
  // We have read the table description from disk as part of system restart.
 
2569
  // We will also write it back again to ensure that both copies are ok.
 
2570
  /* ---------------------------------------------------------------- */
 
2571
  ndbrequire(c_writeTableRecord.tableWriteState == WriteTableRecord::IDLE);
 
2572
  c_writeTableRecord.noOfPages = c_readTableRecord.noOfPages;
 
2573
  c_writeTableRecord.pageId = c_readTableRecord.pageId;
 
2574
  c_writeTableRecord.tableWriteState = WriteTableRecord::TWR_CALLBACK;
 
2575
  c_writeTableRecord.m_callback.m_callbackData = callbackData;
 
2576
  c_writeTableRecord.m_callback.m_callbackFunction = 
 
2577
    safe_cast(&Dbdict::restartCreateTab_writeTableConf);
 
2578
  startWriteTableFile(signal, c_readTableRecord.tableId);
 
2579
}
 
2580
 
 
2581
void
 
2582
Dbdict::execGET_TABINFO_CONF(Signal* signal){
 
2583
  jamEntry();
 
2584
 
 
2585
  if(!assembleFragments(signal)){
 
2586
    jam();
 
2587
    return;
 
2588
  }
 
2589
  
 
2590
  GetTabInfoConf * const conf = (GetTabInfoConf*)signal->getDataPtr();
 
2591
 
 
2592
  const Uint32 tableId = conf->tableId;
 
2593
  const Uint32 senderData = conf->senderData;
 
2594
  
 
2595
  SegmentedSectionPtr tabInfoPtr;
 
2596
  signal->getSection(tabInfoPtr, GetTabInfoConf::DICT_TAB_INFO);
 
2597
 
 
2598
  CreateTableRecordPtr createTabPtr;  
 
2599
  ndbrequire(c_opCreateTable.find(createTabPtr, senderData));
 
2600
  ndbrequire(!createTabPtr.isNull());
 
2601
  ndbrequire(createTabPtr.p->m_tablePtrI == tableId);
 
2602
 
 
2603
  /**
 
2604
   * Put data into table record
 
2605
   */
 
2606
  ParseDictTabInfoRecord parseRecord;
 
2607
  parseRecord.requestType = DictTabInfo::GetTabInfoConf;
 
2608
  parseRecord.errorCode = 0;
 
2609
  
 
2610
  SimplePropertiesSectionReader r(tabInfoPtr, getSectionSegmentPool());
 
2611
  handleTabInfoInit(r, &parseRecord);
 
2612
  ndbrequire(parseRecord.errorCode == 0);
 
2613
  
 
2614
  Callback callback;
 
2615
  callback.m_callbackData = createTabPtr.p->key;
 
2616
  callback.m_callbackFunction = 
 
2617
    safe_cast(&Dbdict::restartCreateTab_writeTableConf);
 
2618
  
 
2619
  signal->header.m_noOfSections = 0;
 
2620
  writeTableFile(signal, createTabPtr.p->m_tablePtrI, tabInfoPtr, &callback);
 
2621
  signal->setSection(tabInfoPtr, 0);
 
2622
  releaseSections(signal);
 
2623
}
 
2624
 
 
2625
void
 
2626
Dbdict::restartCreateTab_writeTableConf(Signal* signal, 
 
2627
                                        Uint32 callbackData,
 
2628
                                        Uint32 returnCode){
 
2629
  jam();
 
2630
 
 
2631
  CreateTableRecordPtr createTabPtr;  
 
2632
  ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
 
2633
 
 
2634
  Callback callback;
 
2635
  callback.m_callbackData = callbackData;
 
2636
  callback.m_callbackFunction = 
 
2637
    safe_cast(&Dbdict::restartCreateTab_dihComplete);
 
2638
  
 
2639
  SegmentedSectionPtr fragDataPtr; 
 
2640
  fragDataPtr.sz = 0;
 
2641
  fragDataPtr.setNull();
 
2642
  createTab_dih(signal, createTabPtr, fragDataPtr, &callback);
 
2643
}
 
2644
 
 
2645
void
 
2646
Dbdict::restartCreateTab_dihComplete(Signal* signal, 
 
2647
                                     Uint32 callbackData,
 
2648
                                     Uint32 returnCode){
 
2649
  jam();
 
2650
  
 
2651
  CreateTableRecordPtr createTabPtr;  
 
2652
  ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
 
2653
  
 
2654
  //@todo check error
 
2655
  ndbrequire(createTabPtr.p->m_errorCode == 0);
 
2656
 
 
2657
  Callback callback;
 
2658
  callback.m_callbackData = callbackData;
 
2659
  callback.m_callbackFunction = 
 
2660
    safe_cast(&Dbdict::restartCreateTab_activateComplete);
 
2661
  
 
2662
  alterTab_activate(signal, createTabPtr, &callback);
 
2663
}
 
2664
 
 
2665
void
 
2666
Dbdict::restartCreateTab_activateComplete(Signal* signal, 
 
2667
                                          Uint32 callbackData,
 
2668
                                          Uint32 returnCode){
 
2669
  jam();
 
2670
  
 
2671
  CreateTableRecordPtr createTabPtr;  
 
2672
  ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
 
2673
 
 
2674
  TableRecordPtr tabPtr;
 
2675
  c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
 
2676
  tabPtr.p->tabState = TableRecord::DEFINED;
 
2677
  
 
2678
  c_opCreateTable.release(createTabPtr);
 
2679
 
 
2680
  c_restartRecord.activeTable++;
 
2681
  checkSchemaStatus(signal);
 
2682
}
 
2683
 
 
2684
void
 
2685
Dbdict::restartDropTab(Signal* signal, Uint32 tableId){
 
2686
 
 
2687
  const Uint32 key = ++c_opRecordSequence;
 
2688
 
 
2689
  DropTableRecordPtr dropTabPtr;  
 
2690
  ndbrequire(c_opDropTable.seize(dropTabPtr));
 
2691
  
 
2692
  dropTabPtr.p->key = key;
 
2693
  c_opDropTable.add(dropTabPtr);
 
2694
  
 
2695
  dropTabPtr.p->m_errorCode = 0;
 
2696
  dropTabPtr.p->m_request.tableId = tableId;
 
2697
  dropTabPtr.p->m_coordinatorRef = 0;
 
2698
  dropTabPtr.p->m_requestType = DropTabReq::RestartDropTab;
 
2699
  dropTabPtr.p->m_participantData.m_gsn = GSN_DROP_TAB_REQ;
 
2700
  
 
2701
 
 
2702
  dropTabPtr.p->m_participantData.m_block = 0;
 
2703
  dropTabPtr.p->m_participantData.m_callback.m_callbackData = key;
 
2704
  dropTabPtr.p->m_participantData.m_callback.m_callbackFunction = 
 
2705
    safe_cast(&Dbdict::restartDropTab_complete);
 
2706
  dropTab_nextStep(signal, dropTabPtr);  
 
2707
}
 
2708
 
 
2709
void
 
2710
Dbdict::restartDropTab_complete(Signal* signal, 
 
2711
                                Uint32 callbackData,
 
2712
                                Uint32 returnCode){
 
2713
  jam();
 
2714
 
 
2715
  DropTableRecordPtr dropTabPtr;
 
2716
  ndbrequire(c_opDropTable.find(dropTabPtr, callbackData));
 
2717
  
 
2718
  //@todo check error
 
2719
 
 
2720
  c_opDropTable.release(dropTabPtr);
 
2721
 
 
2722
  c_restartRecord.activeTable++;
 
2723
  checkSchemaStatus(signal);
 
2724
}
 
2725
 
 
2726
/* **************************************************************** */
 
2727
/* ---------------------------------------------------------------- */
 
2728
/* MODULE:          NODE FAILURE HANDLING ------------------------- */
 
2729
/* ---------------------------------------------------------------- */
 
2730
/*                                                                  */
 
2731
/* This module contains the code that is used when nodes            */
 
2732
/* (kernel/api) fails.                                              */
 
2733
/* ---------------------------------------------------------------- */
 
2734
/* **************************************************************** */
 
2735
 
 
2736
/* ---------------------------------------------------------------- */
 
2737
// We receive a report of an API that failed.
 
2738
/* ---------------------------------------------------------------- */
 
2739
void Dbdict::execAPI_FAILREQ(Signal* signal) 
 
2740
{
 
2741
  jamEntry();
 
2742
  Uint32 failedApiNode = signal->theData[0];
 
2743
  BlockReference retRef = signal->theData[1];
 
2744
 
 
2745
#if 0
 
2746
  Uint32 userNode = refToNode(c_connRecord.userBlockRef);
 
2747
  if (userNode == failedApiNode) {
 
2748
    jam();
 
2749
    c_connRecord.userBlockRef = (Uint32)-1;
 
2750
  }//if
 
2751
#endif
 
2752
 
 
2753
  signal->theData[0] = failedApiNode;
 
2754
  signal->theData[1] = reference();
 
2755
  sendSignal(retRef, GSN_API_FAILCONF, signal, 2, JBB);
 
2756
}//execAPI_FAILREQ()
 
2757
 
 
2758
/* ---------------------------------------------------------------- */
 
2759
// We receive a report of one or more node failures of kernel nodes.
 
2760
/* ---------------------------------------------------------------- */
 
2761
void Dbdict::execNODE_FAILREP(Signal* signal) 
 
2762
{
 
2763
  jamEntry();
 
2764
  NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
 
2765
 
 
2766
  c_failureNr    = nodeFail->failNo;
 
2767
  const Uint32 numberOfFailedNodes  = nodeFail->noOfNodes;
 
2768
  const bool masterFailed = (c_masterNodeId != nodeFail->masterNodeId);
 
2769
  c_masterNodeId = nodeFail->masterNodeId;
 
2770
 
 
2771
  c_noNodesFailed += numberOfFailedNodes;
 
2772
  Uint32 theFailedNodes[NodeBitmask::Size];
 
2773
  memcpy(theFailedNodes, nodeFail->theNodes, sizeof(theFailedNodes));
 
2774
 
 
2775
  c_counterMgr.execNODE_FAILREP(signal);
 
2776
  
 
2777
  bool ok = false;
 
2778
  switch(c_blockState){
 
2779
  case BS_IDLE:
 
2780
    jam();
 
2781
    ok = true;
 
2782
    if(c_opRecordPool.getSize() != c_opRecordPool.getNoOfFree()){
 
2783
      jam();
 
2784
      c_blockState = BS_NODE_FAILURE;
 
2785
    }
 
2786
    break;
 
2787
  case BS_CREATE_TAB:
 
2788
    jam();
 
2789
    ok = true;
 
2790
    if(!masterFailed)
 
2791
      break;
 
2792
    // fall through
 
2793
  case BS_BUSY:
 
2794
  case BS_NODE_FAILURE:
 
2795
    jam();
 
2796
    c_blockState = BS_NODE_FAILURE;
 
2797
    ok = true;
 
2798
    break;
 
2799
  case BS_NODE_RESTART:
 
2800
    jam();
 
2801
    ok = true;
 
2802
    break;
 
2803
  }
 
2804
  ndbrequire(ok);
 
2805
  
 
2806
  for(unsigned i = 1; i < MAX_NDB_NODES; i++) {
 
2807
    jam();
 
2808
    if(NodeBitmask::get(theFailedNodes, i)) {
 
2809
      jam();
 
2810
      NodeRecordPtr nodePtr;
 
2811
      c_nodes.getPtr(nodePtr, i);
 
2812
 
 
2813
      nodePtr.p->nodeState = NodeRecord::NDB_NODE_DEAD;
 
2814
      NFCompleteRep * const nfCompRep = (NFCompleteRep *)&signal->theData[0];
 
2815
      nfCompRep->blockNo      = DBDICT;
 
2816
      nfCompRep->nodeId       = getOwnNodeId();
 
2817
      nfCompRep->failedNodeId = nodePtr.i;
 
2818
      sendSignal(DBDIH_REF, GSN_NF_COMPLETEREP, signal, 
 
2819
                 NFCompleteRep::SignalLength, JBB);
 
2820
      
 
2821
      c_aliveNodes.clear(i);
 
2822
    }//if
 
2823
  }//for
 
2824
 
 
2825
  /*
 
2826
   * NODE_FAILREP guarantees that no "in flight" signal from
 
2827
   * a dead node is accepted, and also that the job buffer contains
 
2828
   * no such (un-executed) signals.  Therefore no DICT_UNLOCK_ORD
 
2829
   * from a dead node (leading to master crash) is possible after
 
2830
   * this clean-up removes the lock record.
 
2831
   */
 
2832
  removeStaleDictLocks(signal, theFailedNodes);
 
2833
 
 
2834
}//execNODE_FAILREP()
 
2835
 
 
2836
 
 
2837
/* **************************************************************** */
 
2838
/* ---------------------------------------------------------------- */
 
2839
/* MODULE:          NODE START HANDLING --------------------------- */
 
2840
/* ---------------------------------------------------------------- */
 
2841
/*                                                                  */
 
2842
/* This module contains the code that is used when kernel nodes     */
 
2843
/* starts.                                                          */
 
2844
/* ---------------------------------------------------------------- */
 
2845
/* **************************************************************** */
 
2846
 
 
2847
/* ---------------------------------------------------------------- */
 
2848
// Include a starting node in list of nodes to be part of adding
 
2849
// and dropping tables.
 
2850
/* ---------------------------------------------------------------- */
 
2851
void Dbdict::execINCL_NODEREQ(Signal* signal) 
 
2852
{
 
2853
  jamEntry();
 
2854
  NodeRecordPtr nodePtr;
 
2855
  BlockReference retRef = signal->theData[0];
 
2856
  nodePtr.i = signal->theData[1];
 
2857
 
 
2858
  ndbrequire(c_noNodesFailed > 0);
 
2859
  c_noNodesFailed--;
 
2860
 
 
2861
  c_nodes.getPtr(nodePtr);
 
2862
  ndbrequire(nodePtr.p->nodeState == NodeRecord::NDB_NODE_DEAD);
 
2863
  nodePtr.p->nodeState = NodeRecord::NDB_NODE_ALIVE;
 
2864
  signal->theData[0] = reference();
 
2865
  sendSignal(retRef, GSN_INCL_NODECONF, signal, 1, JBB);
 
2866
 
 
2867
  c_aliveNodes.set(nodePtr.i);
 
2868
}//execINCL_NODEREQ()
 
2869
 
 
2870
/* **************************************************************** */
 
2871
/* ---------------------------------------------------------------- */
 
2872
/* MODULE:          ADD TABLE HANDLING ---------------------------- */
 
2873
/* ---------------------------------------------------------------- */
 
2874
/*                                                                  */
 
2875
/* This module contains the code that is used when adding a table.  */
 
2876
/* ---------------------------------------------------------------- */
 
2877
/* **************************************************************** */
 
2878
 
 
2879
/* ---------------------------------------------------------------- */
 
2880
// This signal receives information about a table from either:
 
2881
// API, Ndbcntr or from other DICT.
 
2882
/* ---------------------------------------------------------------- */
 
2883
void
 
2884
Dbdict::execCREATE_TABLE_REQ(Signal* signal){
 
2885
  jamEntry();
 
2886
  if(!assembleFragments(signal)){
 
2887
    return;
 
2888
  }
 
2889
  
 
2890
  CreateTableReq* const req = (CreateTableReq*)signal->getDataPtr();
 
2891
  const Uint32 senderRef = req->senderRef;
 
2892
  const Uint32 senderData = req->senderData;
 
2893
  
 
2894
  ParseDictTabInfoRecord parseRecord;
 
2895
  do {
 
2896
    if(getOwnNodeId() != c_masterNodeId){
 
2897
      jam();
 
2898
      parseRecord.errorCode = CreateTableRef::NotMaster;
 
2899
      break;
 
2900
    }
 
2901
    
 
2902
    if (c_blockState == BS_NODE_RESTART){
 
2903
      jam();
 
2904
      parseRecord.errorCode = CreateTableRef::BusyWithNR;
 
2905
      break;
 
2906
    }
 
2907
    
 
2908
    if (c_blockState != BS_IDLE){
 
2909
      jam();
 
2910
      parseRecord.errorCode = CreateTableRef::Busy;
 
2911
      break;
 
2912
    }
 
2913
 
 
2914
    CreateTableRecordPtr createTabPtr;
 
2915
    c_opCreateTable.seize(createTabPtr);
 
2916
    
 
2917
    if(createTabPtr.isNull()){
 
2918
      jam();
 
2919
      parseRecord.errorCode = CreateTableRef::Busy;
 
2920
      break;
 
2921
    }
 
2922
    
 
2923
    parseRecord.requestType = DictTabInfo::CreateTableFromAPI;
 
2924
    parseRecord.errorCode = 0;
 
2925
    
 
2926
    SegmentedSectionPtr ptr;
 
2927
    signal->getSection(ptr, CreateTableReq::DICT_TAB_INFO);
 
2928
    SimplePropertiesSectionReader r(ptr, getSectionSegmentPool());
 
2929
    
 
2930
    handleTabInfoInit(r, &parseRecord);
 
2931
    releaseSections(signal);
 
2932
    
 
2933
    if(parseRecord.errorCode != 0){
 
2934
      jam();
 
2935
      c_opCreateTable.release(createTabPtr);
 
2936
      break;
 
2937
    }
 
2938
    
 
2939
    createTabPtr.p->key = ++c_opRecordSequence;
 
2940
    c_opCreateTable.add(createTabPtr);
 
2941
    createTabPtr.p->m_errorCode = 0;
 
2942
    createTabPtr.p->m_senderRef = senderRef;
 
2943
    createTabPtr.p->m_senderData = senderData;
 
2944
    createTabPtr.p->m_tablePtrI = parseRecord.tablePtr.i;
 
2945
    createTabPtr.p->m_coordinatorRef = reference();
 
2946
    createTabPtr.p->m_fragmentsPtrI = RNIL;
 
2947
    createTabPtr.p->m_dihAddFragPtr = RNIL;
 
2948
 
 
2949
    Uint32 * theData = signal->getDataPtrSend();
 
2950
    CreateFragmentationReq * const req = (CreateFragmentationReq*)theData;
 
2951
    req->senderRef = reference();
 
2952
    req->senderData = createTabPtr.p->key;
 
2953
    req->fragmentationType = parseRecord.tablePtr.p->fragmentType;
 
2954
    req->noOfFragments = 0;
 
2955
    req->fragmentNode = 0;
 
2956
    req->primaryTableId = RNIL;
 
2957
    if (parseRecord.tablePtr.p->isOrderedIndex()) {
 
2958
      // ordered index has same fragmentation as the table
 
2959
      const Uint32 primaryTableId = parseRecord.tablePtr.p->primaryTableId;
 
2960
      TableRecordPtr primaryTablePtr;
 
2961
      c_tableRecordPool.getPtr(primaryTablePtr, primaryTableId);
 
2962
      // fragmentationType must be consistent
 
2963
      req->fragmentationType = primaryTablePtr.p->fragmentType;
 
2964
      req->primaryTableId = primaryTableId;
 
2965
    }
 
2966
    sendSignal(DBDIH_REF, GSN_CREATE_FRAGMENTATION_REQ, signal,
 
2967
               CreateFragmentationReq::SignalLength, JBB);
 
2968
    
 
2969
    c_blockState = BS_CREATE_TAB;
 
2970
    return;
 
2971
  } while(0);
 
2972
  
 
2973
  /**
 
2974
   * Something went wrong
 
2975
   */
 
2976
  releaseSections(signal);
 
2977
 
 
2978
  CreateTableRef * ref = (CreateTableRef*)signal->getDataPtrSend();
 
2979
  ref->senderData = senderData;
 
2980
  ref->senderRef = reference();
 
2981
  ref->masterNodeId = c_masterNodeId;
 
2982
  ref->errorCode = parseRecord.errorCode;
 
2983
  ref->errorLine = parseRecord.errorLine;
 
2984
  ref->errorKey = parseRecord.errorKey;
 
2985
  ref->status = parseRecord.status;
 
2986
  sendSignal(senderRef, GSN_CREATE_TABLE_REF, signal, 
 
2987
             CreateTableRef::SignalLength, JBB);
 
2988
}
 
2989
 
 
2990
void
 
2991
Dbdict::execBACKUP_FRAGMENT_REQ(Signal* signal)
 
2992
{
 
2993
  jamEntry();
 
2994
  Uint32 tableId = signal->theData[0];
 
2995
  Uint32 lock = signal->theData[1];
 
2996
 
 
2997
  TableRecordPtr tablePtr;
 
2998
  c_tableRecordPool.getPtr(tablePtr, tableId, true);
 
2999
 
 
3000
  if(lock)
 
3001
  {
 
3002
    ndbrequire(tablePtr.p->tabState == TableRecord::DEFINED);
 
3003
    tablePtr.p->tabState = TableRecord::BACKUP_ONGOING;
 
3004
  }
 
3005
  else if(tablePtr.p->tabState == TableRecord::BACKUP_ONGOING)
 
3006
  {
 
3007
    tablePtr.p->tabState = TableRecord::DEFINED;
 
3008
  }
 
3009
}
 
3010
 
 
3011
bool
 
3012
Dbdict::check_ndb_versions() const
 
3013
{
 
3014
  Uint32 node = 0;
 
3015
  Uint32 version = getNodeInfo(getOwnNodeId()).m_version;
 
3016
  while((node = c_aliveNodes.find(node + 1)) != BitmaskImpl::NotFound)
 
3017
  {
 
3018
    if(getNodeInfo(node).m_version != version)
 
3019
    {
 
3020
      return false;
 
3021
    }
 
3022
  }
 
3023
  return true;
 
3024
}
 
3025
 
 
3026
void
 
3027
Dbdict::execALTER_TABLE_REQ(Signal* signal)
 
3028
{
 
3029
  // Received by master
 
3030
  jamEntry();
 
3031
  if(!assembleFragments(signal)){
 
3032
    return;
 
3033
  }
 
3034
  AlterTableReq* const req = (AlterTableReq*)signal->getDataPtr();
 
3035
  const Uint32 senderRef = req->senderRef;
 
3036
  const Uint32 senderData = req->senderData;
 
3037
  const Uint32 changeMask = req->changeMask;
 
3038
  const Uint32 tableId = req->tableId;
 
3039
  const Uint32 tableVersion = req->tableVersion;
 
3040
  ParseDictTabInfoRecord* aParseRecord;
 
3041
  
 
3042
  // Get table definition
 
3043
  TableRecordPtr tablePtr;
 
3044
  c_tableRecordPool.getPtr(tablePtr, tableId, false);
 
3045
  if(tablePtr.isNull()){
 
3046
    jam();
 
3047
    alterTableRef(signal, req, AlterTableRef::NoSuchTable);
 
3048
    return;
 
3049
  }
 
3050
  
 
3051
  if(getOwnNodeId() != c_masterNodeId){
 
3052
    jam();
 
3053
    alterTableRef(signal, req, AlterTableRef::NotMaster);
 
3054
    return;
 
3055
  }
 
3056
  
 
3057
  if(c_blockState == BS_NODE_RESTART){
 
3058
    jam();
 
3059
    alterTableRef(signal, req, AlterTableRef::BusyWithNR);
 
3060
    return;
 
3061
  }
 
3062
  
 
3063
  if(c_blockState != BS_IDLE){
 
3064
    jam();
 
3065
    alterTableRef(signal, req, AlterTableRef::Busy);
 
3066
    return;
 
3067
  }
 
3068
 
 
3069
  if (!check_ndb_versions())
 
3070
  {
 
3071
    jam();
 
3072
    alterTableRef(signal, req, AlterTableRef::IncompatibleVersions);
 
3073
    return;
 
3074
  }
 
3075
  
 
3076
  const TableRecord::TabState tabState = tablePtr.p->tabState;
 
3077
  bool ok = false;
 
3078
  switch(tabState){
 
3079
  case TableRecord::NOT_DEFINED:
 
3080
  case TableRecord::REORG_TABLE_PREPARED:
 
3081
  case TableRecord::DEFINING:
 
3082
  case TableRecord::CHECKED:
 
3083
    jam();
 
3084
    alterTableRef(signal, req, AlterTableRef::NoSuchTable);
 
3085
    return;
 
3086
  case TableRecord::DEFINED:
 
3087
    ok = true;
 
3088
    jam();
 
3089
    break;
 
3090
  case TableRecord::BACKUP_ONGOING:
 
3091
    jam();
 
3092
    alterTableRef(signal, req, AlterTableRef::BackupInProgress);
 
3093
    return;
 
3094
  case TableRecord::PREPARE_DROPPING:
 
3095
  case TableRecord::DROPPING:
 
3096
    jam();
 
3097
    alterTableRef(signal, req, AlterTableRef::DropInProgress);
 
3098
    return;
 
3099
  }
 
3100
  ndbrequire(ok);
 
3101
 
 
3102
  if(tablePtr.p->tableVersion != tableVersion){
 
3103
    jam();
 
3104
    alterTableRef(signal, req, AlterTableRef::InvalidTableVersion);
 
3105
    return;
 
3106
  }
 
3107
  // Parse new table defintion
 
3108
  ParseDictTabInfoRecord parseRecord;
 
3109
  aParseRecord = &parseRecord;
 
3110
    
 
3111
  CreateTableRecordPtr alterTabPtr; // Reuse create table records
 
3112
  c_opCreateTable.seize(alterTabPtr);
 
3113
  
 
3114
  if(alterTabPtr.isNull()){
 
3115
    jam();
 
3116
    alterTableRef(signal, req, AlterTableRef::Busy);
 
3117
    return;
 
3118
  }
 
3119
 
 
3120
  alterTabPtr.p->m_changeMask = changeMask;
 
3121
  parseRecord.requestType = DictTabInfo::AlterTableFromAPI;
 
3122
  parseRecord.errorCode = 0;
 
3123
  
 
3124
  SegmentedSectionPtr ptr;
 
3125
  signal->getSection(ptr, AlterTableReq::DICT_TAB_INFO);
 
3126
  SimplePropertiesSectionReader r(ptr, getSectionSegmentPool());
 
3127
 
 
3128
  handleTabInfoInit(r, &parseRecord, false); // Will not save info
 
3129
  
 
3130
  if(parseRecord.errorCode != 0){
 
3131
    jam();
 
3132
    c_opCreateTable.release(alterTabPtr);
 
3133
    alterTableRef(signal, req, 
 
3134
                  (AlterTableRef::ErrorCode) parseRecord.errorCode, 
 
3135
                  aParseRecord);
 
3136
    return;
 
3137
  }
 
3138
  
 
3139
  releaseSections(signal);
 
3140
  alterTabPtr.p->key = ++c_opRecordSequence;
 
3141
  c_opCreateTable.add(alterTabPtr);
 
3142
  ndbrequire(c_opCreateTable.find(alterTabPtr, alterTabPtr.p->key));
 
3143
  alterTabPtr.p->m_errorCode = 0;
 
3144
  alterTabPtr.p->m_senderRef = senderRef;
 
3145
  alterTabPtr.p->m_senderData = senderData;
 
3146
  alterTabPtr.p->m_tablePtrI = parseRecord.tablePtr.i;
 
3147
  alterTabPtr.p->m_alterTableFailed = false;
 
3148
  alterTabPtr.p->m_coordinatorRef = reference();
 
3149
  alterTabPtr.p->m_fragmentsPtrI = RNIL;
 
3150
  alterTabPtr.p->m_dihAddFragPtr = RNIL;
 
3151
  alterTabPtr.p->m_alterTableId = tablePtr.p->tableId;
 
3152
 
 
3153
  // Send prepare request to all alive nodes
 
3154
  SimplePropertiesSectionWriter w(getSectionSegmentPool());
 
3155
  packTableIntoPagesImpl(w, parseRecord.tablePtr);
 
3156
  
 
3157
  SegmentedSectionPtr tabInfoPtr;
 
3158
  w.getPtr(tabInfoPtr);
 
3159
  
 
3160
  alterTabPtr.p->m_tabInfoPtrI = tabInfoPtr.i;
 
3161
 
 
3162
  // Alter table on all nodes
 
3163
  c_blockState = BS_BUSY;
 
3164
 
 
3165
  Mutex mutex(signal, c_mutexMgr, alterTabPtr.p->m_startLcpMutex);
 
3166
  Callback c = { safe_cast(&Dbdict::alterTable_backup_mutex_locked),
 
3167
                 alterTabPtr.p->key };
 
3168
  
 
3169
  ndbrequire(mutex.lock(c));
 
3170
}
 
3171
 
 
3172
void
 
3173
Dbdict::alterTable_backup_mutex_locked(Signal* signal,
 
3174
                                       Uint32 callbackData,
 
3175
                                       Uint32 retValue)
 
3176
{
 
3177
  jamEntry();
 
3178
  
 
3179
  ndbrequire(retValue == 0);
 
3180
  
 
3181
  CreateTableRecordPtr alterTabPtr;
 
3182
  ndbrequire(c_opCreateTable.find(alterTabPtr, callbackData));
 
3183
 
 
3184
  TableRecordPtr tablePtr;
 
3185
  c_tableRecordPool.getPtr(tablePtr, alterTabPtr.p->m_alterTableId, true);
 
3186
 
 
3187
  Mutex mutex(signal, c_mutexMgr, alterTabPtr.p->m_startLcpMutex);
 
3188
  mutex.unlock(); // ignore response
 
3189
 
 
3190
  SegmentedSectionPtr tabInfoPtr;
 
3191
  getSection(tabInfoPtr, alterTabPtr.p->m_tabInfoPtrI);
 
3192
  signal->setSection(tabInfoPtr, AlterTabReq::DICT_TAB_INFO);
 
3193
  
 
3194
  alterTabPtr.p->m_tabInfoPtrI = RNIL;
 
3195
  
 
3196
  if(tablePtr.p->tabState == TableRecord::BACKUP_ONGOING)
 
3197
  {
 
3198
    jam();
 
3199
    AlterTableReq* req = (AlterTableReq*)signal->getDataPtr();
 
3200
    req->senderData = alterTabPtr.p->m_senderData;
 
3201
    req->senderRef = alterTabPtr.p->m_senderRef;
 
3202
    alterTableRef(signal, req, AlterTableRef::BackupInProgress);
 
3203
 
 
3204
    c_tableRecordPool.getPtr(tablePtr, alterTabPtr.p->m_tablePtrI);  
 
3205
    releaseTableObject(tablePtr.i, false);
 
3206
 
 
3207
    c_opCreateTable.release(alterTabPtr);
 
3208
    c_blockState = BS_IDLE;
 
3209
    return;
 
3210
  }
 
3211
  
 
3212
  NodeReceiverGroup rg(DBDICT, c_aliveNodes);
 
3213
  alterTabPtr.p->m_coordinatorData.m_gsn = GSN_ALTER_TAB_REQ;
 
3214
  SafeCounter safeCounter(c_counterMgr, 
 
3215
                          alterTabPtr.p->m_coordinatorData.m_counter);
 
3216
  safeCounter.init<AlterTabRef>(rg, alterTabPtr.p->key);
 
3217
 
 
3218
  AlterTabReq * const lreq = (AlterTabReq*)signal->getDataPtrSend();
 
3219
  lreq->senderRef = reference();
 
3220
  lreq->senderData = alterTabPtr.p->key;
 
3221
  lreq->clientRef = alterTabPtr.p->m_senderRef;
 
3222
  lreq->clientData = alterTabPtr.p->m_senderData;
 
3223
  lreq->changeMask = alterTabPtr.p->m_changeMask;
 
3224
  lreq->tableId = tablePtr.p->tableId;
 
3225
  lreq->tableVersion = alter_table_inc_schema_version(tablePtr.p->tableVersion);
 
3226
  lreq->gci = tablePtr.p->gciTableCreated;
 
3227
  lreq->requestType = AlterTabReq::AlterTablePrepare;
 
3228
  
 
3229
  sendFragmentedSignal(rg, GSN_ALTER_TAB_REQ, signal, 
 
3230
                       AlterTabReq::SignalLength, JBB);
 
3231
}
 
3232
 
 
3233
void Dbdict::alterTableRef(Signal * signal, 
 
3234
                           AlterTableReq * req, 
 
3235
                           AlterTableRef::ErrorCode errCode,
 
3236
                           ParseDictTabInfoRecord* parseRecord)
 
3237
{
 
3238
  jam();
 
3239
  releaseSections(signal);
 
3240
  AlterTableRef * ref = (AlterTableRef*)signal->getDataPtrSend();
 
3241
  Uint32 senderRef = req->senderRef;
 
3242
  ref->senderData = req->senderData;
 
3243
  ref->senderRef = reference();
 
3244
  ref->masterNodeId = c_masterNodeId;
 
3245
  if (parseRecord) {
 
3246
    ref->errorCode = parseRecord->errorCode;
 
3247
    ref->errorLine = parseRecord->errorLine;
 
3248
    ref->errorKey = parseRecord->errorKey;
 
3249
    ref->status = parseRecord->status;
 
3250
  }
 
3251
  else {
 
3252
    ref->errorCode = errCode;
 
3253
    ref->errorLine = 0;
 
3254
    ref->errorKey = 0;
 
3255
    ref->status = 0;
 
3256
  }
 
3257
  sendSignal(senderRef, GSN_ALTER_TABLE_REF, signal, 
 
3258
             AlterTableRef::SignalLength, JBB);
 
3259
}
 
3260
 
 
3261
void
 
3262
Dbdict::execALTER_TAB_REQ(Signal * signal) 
 
3263
{
 
3264
  // Received in all nodes to handle change locally
 
3265
  jamEntry();
 
3266
 
 
3267
  if(!assembleFragments(signal)){
 
3268
    return;
 
3269
  }
 
3270
  AlterTabReq* const req = (AlterTabReq*)signal->getDataPtr();
 
3271
  const Uint32 senderRef = req->senderRef;
 
3272
  const Uint32 senderData = req->senderData;
 
3273
  const Uint32 changeMask = req->changeMask;
 
3274
  const Uint32 tableId = req->tableId;
 
3275
  const Uint32 tableVersion = req->tableVersion;
 
3276
  const Uint32 gci = req->gci;
 
3277
  AlterTabReq::RequestType requestType = 
 
3278
    (AlterTabReq::RequestType) req->requestType;
 
3279
 
 
3280
  SegmentedSectionPtr tabInfoPtr;
 
3281
  signal->getSection(tabInfoPtr, AlterTabReq::DICT_TAB_INFO);
 
3282
 
 
3283
  CreateTableRecordPtr alterTabPtr; // Reuse create table records
 
3284
 
 
3285
  if (senderRef != reference()) {
 
3286
    jam();
 
3287
    c_blockState = BS_BUSY;
 
3288
  }
 
3289
  if ((requestType == AlterTabReq::AlterTablePrepare)
 
3290
      && (senderRef != reference())) {
 
3291
    jam();
 
3292
    c_opCreateTable.seize(alterTabPtr);
 
3293
    if(!alterTabPtr.isNull())
 
3294
      alterTabPtr.p->m_changeMask = changeMask;
 
3295
  }
 
3296
  else {
 
3297
    jam();
 
3298
    ndbrequire(c_opCreateTable.find(alterTabPtr, senderData));
 
3299
  }
 
3300
  if(alterTabPtr.isNull()){
 
3301
    jam();
 
3302
    alterTabRef(signal, req, AlterTableRef::Busy);
 
3303
    return;
 
3304
  }
 
3305
 
 
3306
  if (!check_ndb_versions())
 
3307
  {
 
3308
    jam();
 
3309
    alterTabRef(signal, req, AlterTableRef::IncompatibleVersions);
 
3310
    return;
 
3311
  }
 
3312
 
 
3313
  alterTabPtr.p->m_alterTableId = tableId;
 
3314
  alterTabPtr.p->m_coordinatorRef = senderRef;
 
3315
  
 
3316
  // Get table definition
 
3317
  TableRecordPtr tablePtr;
 
3318
  c_tableRecordPool.getPtr(tablePtr, tableId, false);
 
3319
  if(tablePtr.isNull()){
 
3320
    jam();
 
3321
    alterTabRef(signal, req, AlterTableRef::NoSuchTable);
 
3322
    return;
 
3323
  }
 
3324
    
 
3325
  switch(requestType) {
 
3326
  case(AlterTabReq::AlterTablePrepare): {
 
3327
    ParseDictTabInfoRecord* aParseRecord;
 
3328
  
 
3329
    const TableRecord::TabState tabState = tablePtr.p->tabState;
 
3330
    bool ok = false;
 
3331
    switch(tabState){
 
3332
    case TableRecord::NOT_DEFINED:
 
3333
    case TableRecord::REORG_TABLE_PREPARED:
 
3334
    case TableRecord::DEFINING:
 
3335
    case TableRecord::CHECKED:
 
3336
      jam();
 
3337
      alterTabRef(signal, req, AlterTableRef::NoSuchTable);
 
3338
      return;
 
3339
    case TableRecord::DEFINED:
 
3340
      ok = true;
 
3341
      jam();
 
3342
      break;
 
3343
    case TableRecord::PREPARE_DROPPING:
 
3344
    case TableRecord::DROPPING:
 
3345
      jam();
 
3346
      alterTabRef(signal, req, AlterTableRef::DropInProgress);
 
3347
      return;
 
3348
    case TableRecord::BACKUP_ONGOING:
 
3349
      jam();
 
3350
      alterTabRef(signal, req, AlterTableRef::BackupInProgress);
 
3351
      return;
 
3352
    }
 
3353
    ndbrequire(ok);
 
3354
 
 
3355
    if(alter_table_inc_schema_version(tablePtr.p->tableVersion) != tableVersion){
 
3356
      jam();
 
3357
      alterTabRef(signal, req, AlterTableRef::InvalidTableVersion);
 
3358
      return;
 
3359
    }
 
3360
    TableRecordPtr newTablePtr;
 
3361
    if (senderRef  != reference()) {
 
3362
      jam();
 
3363
      // Parse altered table defintion
 
3364
      ParseDictTabInfoRecord parseRecord;
 
3365
      aParseRecord = &parseRecord;
 
3366
      
 
3367
      parseRecord.requestType = DictTabInfo::AlterTableFromAPI;
 
3368
      parseRecord.errorCode = 0;
 
3369
      
 
3370
      SimplePropertiesSectionReader r(tabInfoPtr, getSectionSegmentPool());
 
3371
      
 
3372
      handleTabInfoInit(r, &parseRecord, false); // Will not save info
 
3373
      
 
3374
      if(parseRecord.errorCode != 0){
 
3375
        jam();
 
3376
        c_opCreateTable.release(alterTabPtr);
 
3377
        alterTabRef(signal, req, 
 
3378
                    (AlterTableRef::ErrorCode) parseRecord.errorCode, 
 
3379
                    aParseRecord);
 
3380
        return;
 
3381
      }
 
3382
      alterTabPtr.p->key = senderData;
 
3383
      c_opCreateTable.add(alterTabPtr);
 
3384
      alterTabPtr.p->m_errorCode = 0;
 
3385
      alterTabPtr.p->m_senderRef = senderRef;
 
3386
      alterTabPtr.p->m_senderData = senderData;
 
3387
      alterTabPtr.p->m_tablePtrI = parseRecord.tablePtr.i;
 
3388
      alterTabPtr.p->m_fragmentsPtrI = RNIL;
 
3389
      alterTabPtr.p->m_dihAddFragPtr = RNIL;
 
3390
      newTablePtr = parseRecord.tablePtr;
 
3391
      newTablePtr.p->tableVersion = tableVersion;
 
3392
    }
 
3393
    else { // (req->senderRef  == reference())
 
3394
      jam();
 
3395
      c_tableRecordPool.getPtr(newTablePtr, alterTabPtr.p->m_tablePtrI);
 
3396
      newTablePtr.p->tableVersion = tableVersion;
 
3397
    }
 
3398
    if (handleAlterTab(req, alterTabPtr.p, tablePtr, newTablePtr) == -1) {
 
3399
      jam();
 
3400
      c_opCreateTable.release(alterTabPtr);
 
3401
      alterTabRef(signal, req, AlterTableRef::UnsupportedChange);
 
3402
      return;
 
3403
    }
 
3404
    releaseSections(signal);
 
3405
    // Propagate alter table to other local blocks
 
3406
    AlterTabReq * req = (AlterTabReq*)signal->getDataPtrSend();
 
3407
    req->senderRef = reference();
 
3408
    req->senderData = senderData;
 
3409
    req->changeMask = changeMask;
 
3410
    req->tableId = tableId;
 
3411
    req->tableVersion = tableVersion;
 
3412
    req->gci = gci;
 
3413
    req->requestType = requestType;
 
3414
    sendSignal(DBLQH_REF, GSN_ALTER_TAB_REQ, signal, 
 
3415
               AlterTabReq::SignalLength, JBB); 
 
3416
    return;
 
3417
  }
 
3418
  case(AlterTabReq::AlterTableCommit): {
 
3419
    jam();
 
3420
    // Write schema for altered table to disk
 
3421
    SegmentedSectionPtr tabInfoPtr;
 
3422
    signal->getSection(tabInfoPtr, AlterTabReq::DICT_TAB_INFO);
 
3423
    alterTabPtr.p->m_tabInfoPtrI = tabInfoPtr.i;
 
3424
    
 
3425
    signal->header.m_noOfSections = 0;
 
3426
 
 
3427
    // Update table record
 
3428
    tablePtr.p->packedSize = tabInfoPtr.sz;
 
3429
    tablePtr.p->tableVersion = tableVersion;
 
3430
    tablePtr.p->gciTableCreated = gci;
 
3431
 
 
3432
    SchemaFile::TableEntry tabEntry;
 
3433
    tabEntry.m_tableVersion = tableVersion;
 
3434
    tabEntry.m_tableType    = tablePtr.p->tableType;
 
3435
    tabEntry.m_tableState   = SchemaFile::ALTER_TABLE_COMMITTED;
 
3436
    tabEntry.m_gcp          = gci;
 
3437
    tabEntry.m_info_words   = tabInfoPtr.sz;
 
3438
    memset(tabEntry.m_unused, 0, sizeof(tabEntry.m_unused));
 
3439
    
 
3440
    Callback callback;
 
3441
    callback.m_callbackData = senderData;
 
3442
    callback.m_callbackFunction = 
 
3443
      safe_cast(&Dbdict::alterTab_writeSchemaConf);
 
3444
    
 
3445
    updateSchemaState(signal, tableId, &tabEntry, &callback);
 
3446
    break;
 
3447
  }
 
3448
  case(AlterTabReq::AlterTableRevert): {
 
3449
    jam();
 
3450
    // Revert failed alter table
 
3451
    revertAlterTable(signal, changeMask, tableId, alterTabPtr.p);
 
3452
    // Acknowledge the reverted alter table
 
3453
    AlterTabConf * conf = (AlterTabConf*)signal->getDataPtrSend();
 
3454
    conf->senderRef = reference();
 
3455
    conf->senderData = senderData;
 
3456
    conf->changeMask = changeMask;
 
3457
    conf->tableId = tableId;
 
3458
    conf->tableVersion = tableVersion;
 
3459
    conf->gci = gci;
 
3460
    conf->requestType = requestType;
 
3461
    sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal, 
 
3462
               AlterTabConf::SignalLength, JBB);
 
3463
    break;
 
3464
  }
 
3465
  default: ndbrequire(false);
 
3466
  }
 
3467
}
 
3468
 
 
3469
void Dbdict::alterTabRef(Signal * signal, 
 
3470
                         AlterTabReq * req, 
 
3471
                         AlterTableRef::ErrorCode errCode,
 
3472
                         ParseDictTabInfoRecord* parseRecord)
 
3473
{
 
3474
  jam();
 
3475
  releaseSections(signal);
 
3476
  AlterTabRef * ref = (AlterTabRef*)signal->getDataPtrSend();
 
3477
  Uint32 senderRef = req->senderRef;
 
3478
  ref->senderData = req->senderData;
 
3479
  ref->senderRef = reference();
 
3480
  if (parseRecord) {
 
3481
    jam();
 
3482
    ref->errorCode = parseRecord->errorCode;
 
3483
    ref->errorLine = parseRecord->errorLine;
 
3484
    ref->errorKey = parseRecord->errorKey;
 
3485
    ref->errorStatus = parseRecord->status;
 
3486
  }
 
3487
  else {
 
3488
    jam();
 
3489
    ref->errorCode = errCode;
 
3490
    ref->errorLine = 0;
 
3491
    ref->errorKey = 0;
 
3492
    ref->errorStatus = 0;
 
3493
  }
 
3494
  sendSignal(senderRef, GSN_ALTER_TAB_REF, signal, 
 
3495
             AlterTabRef::SignalLength, JBB);
 
3496
  
 
3497
  c_blockState = BS_IDLE;
 
3498
}
 
3499
 
 
3500
void Dbdict::execALTER_TAB_REF(Signal * signal){
 
3501
  jamEntry();
 
3502
 
 
3503
  AlterTabRef * ref = (AlterTabRef*)signal->getDataPtr();
 
3504
 
 
3505
  Uint32 senderRef = ref->senderRef;
 
3506
  Uint32 senderData = ref->senderData;
 
3507
  Uint32 errorCode = ref->errorCode;
 
3508
  Uint32 errorLine = ref->errorLine;
 
3509
  Uint32 errorKey = ref->errorKey;
 
3510
  Uint32 errorStatus = ref->errorStatus;
 
3511
  AlterTabReq::RequestType requestType = 
 
3512
    (AlterTabReq::RequestType) ref->requestType;
 
3513
  CreateTableRecordPtr alterTabPtr;  
 
3514
  ndbrequire(c_opCreateTable.find(alterTabPtr, senderData));
 
3515
  Uint32 changeMask = alterTabPtr.p->m_changeMask;
 
3516
  SafeCounter safeCounter(c_counterMgr, alterTabPtr.p->m_coordinatorData.m_counter);
 
3517
  safeCounter.clearWaitingFor(refToNode(senderRef));
 
3518
  switch (requestType) {
 
3519
  case(AlterTabReq::AlterTablePrepare): {
 
3520
    if (safeCounter.done()) {
 
3521
      jam();
 
3522
      // Send revert request to all alive nodes
 
3523
      TableRecordPtr tablePtr;
 
3524
      c_tableRecordPool.getPtr(tablePtr, alterTabPtr.p->m_alterTableId);
 
3525
      Uint32 tableId = tablePtr.p->tableId;
 
3526
      Uint32 tableVersion = tablePtr.p->tableVersion;
 
3527
      Uint32 gci = tablePtr.p->gciTableCreated;
 
3528
      SimplePropertiesSectionWriter w(getSectionSegmentPool());
 
3529
      packTableIntoPagesImpl(w, tablePtr);
 
3530
      SegmentedSectionPtr spDataPtr;
 
3531
      w.getPtr(spDataPtr);
 
3532
      signal->setSection(spDataPtr, AlterTabReq::DICT_TAB_INFO);
 
3533
      
 
3534
      NodeReceiverGroup rg(DBDICT, c_aliveNodes);
 
3535
      alterTabPtr.p->m_coordinatorData.m_gsn = GSN_ALTER_TAB_REQ;
 
3536
      safeCounter.init<AlterTabRef>(rg, alterTabPtr.p->key);
 
3537
  
 
3538
      AlterTabReq * const lreq = (AlterTabReq*)signal->getDataPtrSend();
 
3539
      lreq->senderRef = reference();
 
3540
      lreq->senderData = alterTabPtr.p->key;
 
3541
      lreq->clientRef = alterTabPtr.p->m_senderRef;
 
3542
      lreq->clientData = alterTabPtr.p->m_senderData;
 
3543
      lreq->changeMask = changeMask;
 
3544
      lreq->tableId = tableId;
 
3545
      lreq->tableVersion = tableVersion;
 
3546
      lreq->gci = gci;
 
3547
      lreq->requestType = AlterTabReq::AlterTableRevert;
 
3548
      
 
3549
      sendSignal(rg, GSN_ALTER_TAB_REQ, signal, 
 
3550
                 AlterTabReq::SignalLength, JBB);
 
3551
    }
 
3552
    else {
 
3553
      jam();
 
3554
      alterTabPtr.p->m_alterTableFailed = true;
 
3555
    }
 
3556
    break;
 
3557
  }
 
3558
  case(AlterTabReq::AlterTableCommit):
 
3559
    jam();
 
3560
  case(AlterTabReq::AlterTableRevert): {
 
3561
    AlterTableRef * apiRef = (AlterTableRef*)signal->getDataPtrSend();
 
3562
    
 
3563
    apiRef->senderData = senderData;
 
3564
    apiRef->senderRef = reference();
 
3565
    apiRef->masterNodeId = c_masterNodeId;
 
3566
    apiRef->errorCode = errorCode;
 
3567
    apiRef->errorLine = errorLine;
 
3568
    apiRef->errorKey = errorKey;
 
3569
    apiRef->status = errorStatus;
 
3570
    if (safeCounter.done()) {
 
3571
      jam();
 
3572
      sendSignal(senderRef, GSN_ALTER_TABLE_REF, signal, 
 
3573
                 AlterTableRef::SignalLength, JBB);
 
3574
      c_blockState = BS_IDLE;
 
3575
    }
 
3576
    else {
 
3577
      jam();
 
3578
      alterTabPtr.p->m_alterTableFailed = true;
 
3579
      alterTabPtr.p->m_alterTableRef = *apiRef;
 
3580
    }
 
3581
    break;
 
3582
  } 
 
3583
  default: ndbrequire(false);
 
3584
  }
 
3585
}
 
3586
 
 
3587
void
 
3588
Dbdict::execALTER_TAB_CONF(Signal * signal){
 
3589
  jamEntry();
 
3590
  AlterTabConf * const conf = (AlterTabConf*)signal->getDataPtr();
 
3591
  Uint32 senderRef = conf->senderRef;
 
3592
  Uint32 senderData = conf->senderData;
 
3593
  Uint32 changeMask = conf->changeMask;
 
3594
  Uint32 tableId = conf->tableId;
 
3595
  Uint32 tableVersion = conf->tableVersion;
 
3596
  Uint32 gci = conf->gci;
 
3597
  AlterTabReq::RequestType requestType = 
 
3598
    (AlterTabReq::RequestType) conf->requestType;
 
3599
  CreateTableRecordPtr alterTabPtr;  
 
3600
  ndbrequire(c_opCreateTable.find(alterTabPtr, senderData));
 
3601
 
 
3602
  switch (requestType) {
 
3603
  case(AlterTabReq::AlterTablePrepare): {
 
3604
    switch(refToBlock(signal->getSendersBlockRef())) {
 
3605
    case DBLQH: {
 
3606
      jam();
 
3607
      AlterTabReq * req = (AlterTabReq*)signal->getDataPtrSend();
 
3608
      req->senderRef = reference();
 
3609
      req->senderData = senderData;
 
3610
      req->changeMask = changeMask;
 
3611
      req->tableId = tableId;
 
3612
      req->tableVersion = tableVersion;
 
3613
      req->gci = gci;
 
3614
      req->requestType = requestType;
 
3615
      sendSignal(DBDIH_REF, GSN_ALTER_TAB_REQ, signal, 
 
3616
                 AlterTabReq::SignalLength, JBB);       
 
3617
      return;
 
3618
    }
 
3619
    case DBDIH: {
 
3620
      jam();
 
3621
      AlterTabReq * req = (AlterTabReq*)signal->getDataPtrSend();
 
3622
      req->senderRef = reference();
 
3623
      req->senderData = senderData;
 
3624
      req->changeMask = changeMask;
 
3625
      req->tableId = tableId;
 
3626
      req->tableVersion = tableVersion;
 
3627
      req->gci = gci;
 
3628
      req->requestType = requestType;
 
3629
      sendSignal(DBTC_REF, GSN_ALTER_TAB_REQ, signal, 
 
3630
                 AlterTabReq::SignalLength, JBB);       
 
3631
      return;
 
3632
    }
 
3633
    case DBTC: {
 
3634
      jam();
 
3635
      // Participant is done with prepare phase, send conf to coordinator
 
3636
      AlterTabConf * conf = (AlterTabConf*)signal->getDataPtrSend();
 
3637
      conf->senderRef = reference();
 
3638
      conf->senderData = senderData;
 
3639
      conf->changeMask = changeMask;
 
3640
      conf->tableId = tableId;
 
3641
      conf->tableVersion = tableVersion;
 
3642
      conf->gci = gci;
 
3643
      conf->requestType = requestType;
 
3644
      sendSignal(alterTabPtr.p->m_coordinatorRef, GSN_ALTER_TAB_CONF, signal, 
 
3645
                 AlterTabConf::SignalLength, JBB);
 
3646
      return;
 
3647
    }
 
3648
    default :break;
 
3649
    }
 
3650
    // Coordinator only
 
3651
    SafeCounter safeCounter(c_counterMgr, alterTabPtr.p->m_coordinatorData.m_counter);
 
3652
    safeCounter.clearWaitingFor(refToNode(senderRef));
 
3653
    if (safeCounter.done()) {
 
3654
      jam();
 
3655
      // We have received all local confirmations
 
3656
      if (alterTabPtr.p->m_alterTableFailed) {
 
3657
        jam();
 
3658
        // Send revert request to all alive nodes
 
3659
        TableRecordPtr tablePtr;
 
3660
        c_tableRecordPool.getPtr(tablePtr, alterTabPtr.p->m_alterTableId);
 
3661
        Uint32 tableId = tablePtr.p->tableId;
 
3662
        Uint32 tableVersion = tablePtr.p->tableVersion;
 
3663
        Uint32 gci = tablePtr.p->gciTableCreated;
 
3664
        SimplePropertiesSectionWriter w(getSectionSegmentPool());
 
3665
        packTableIntoPagesImpl(w, tablePtr);
 
3666
        SegmentedSectionPtr spDataPtr;
 
3667
        w.getPtr(spDataPtr);
 
3668
        signal->setSection(spDataPtr, AlterTabReq::DICT_TAB_INFO);
 
3669
        
 
3670
        NodeReceiverGroup rg(DBDICT, c_aliveNodes);
 
3671
        alterTabPtr.p->m_coordinatorData.m_gsn = GSN_ALTER_TAB_REQ;
 
3672
        safeCounter.init<AlterTabRef>(rg, alterTabPtr.p->key);
 
3673
        
 
3674
        AlterTabReq * const lreq = (AlterTabReq*)signal->getDataPtrSend();
 
3675
        lreq->senderRef = reference();
 
3676
        lreq->senderData = alterTabPtr.p->key;
 
3677
        lreq->clientRef = alterTabPtr.p->m_senderRef;
 
3678
        lreq->clientData = alterTabPtr.p->m_senderData;
 
3679
        lreq->changeMask = changeMask;
 
3680
        lreq->tableId = tableId;
 
3681
        lreq->tableVersion = tableVersion;
 
3682
        lreq->gci = gci;
 
3683
        lreq->requestType = AlterTabReq::AlterTableRevert;
 
3684
        
 
3685
        sendSignal(rg, GSN_ALTER_TAB_REQ, signal, 
 
3686
                   AlterTabReq::SignalLength, JBB);
 
3687
      }
 
3688
      else {
 
3689
        jam();
 
3690
        // Send commit request to all alive nodes
 
3691
        TableRecordPtr tablePtr;
 
3692
        c_tableRecordPool.getPtr(tablePtr, tableId);
 
3693
        SimplePropertiesSectionWriter w(getSectionSegmentPool());
 
3694
        packTableIntoPagesImpl(w, tablePtr);
 
3695
        SegmentedSectionPtr spDataPtr;
 
3696
        w.getPtr(spDataPtr);
 
3697
        signal->setSection(spDataPtr, AlterTabReq::DICT_TAB_INFO);
 
3698
        
 
3699
        NodeReceiverGroup rg(DBDICT, c_aliveNodes);
 
3700
        alterTabPtr.p->m_coordinatorData.m_gsn = GSN_ALTER_TAB_REQ;
 
3701
        safeCounter.init<AlterTabRef>(rg, alterTabPtr.p->key);
 
3702
        
 
3703
        AlterTabReq * const lreq = (AlterTabReq*)signal->getDataPtrSend();
 
3704
        lreq->senderRef = reference();
 
3705
        lreq->senderData = alterTabPtr.p->key;
 
3706
        lreq->clientRef = alterTabPtr.p->m_senderRef;
 
3707
        lreq->clientData = alterTabPtr.p->m_senderData;
 
3708
        lreq->changeMask = changeMask;
 
3709
        lreq->tableId = tableId;
 
3710
        lreq->tableVersion = tableVersion;
 
3711
        lreq->gci = gci;
 
3712
        lreq->requestType = AlterTabReq::AlterTableCommit;
 
3713
        
 
3714
        sendFragmentedSignal(rg, GSN_ALTER_TAB_REQ, signal, 
 
3715
                             AlterTabReq::SignalLength, JBB);
 
3716
      }
 
3717
    }
 
3718
    else {
 
3719
      // (!safeCounter.done())
 
3720
      jam();
 
3721
    }
 
3722
    break;
 
3723
  }
 
3724
  case(AlterTabReq::AlterTableRevert):
 
3725
    jam();
 
3726
  case(AlterTabReq::AlterTableCommit): {
 
3727
    SafeCounter safeCounter(c_counterMgr, alterTabPtr.p->m_coordinatorData.m_counter);
 
3728
    safeCounter.clearWaitingFor(refToNode(senderRef));
 
3729
    if (safeCounter.done()) {
 
3730
      jam();
 
3731
      // We have received all local confirmations
 
3732
      releaseSections(signal);
 
3733
      if (alterTabPtr.p->m_alterTableFailed) {
 
3734
        jam();
 
3735
        AlterTableRef * apiRef = 
 
3736
          (AlterTableRef*)signal->getDataPtrSend();
 
3737
        *apiRef = alterTabPtr.p->m_alterTableRef;
 
3738
        sendSignal(alterTabPtr.p->m_senderRef, GSN_ALTER_TABLE_REF, signal, 
 
3739
                   AlterTableRef::SignalLength, JBB);   
 
3740
      }
 
3741
      else {
 
3742
        jam();
 
3743
        // Alter table completed, inform API
 
3744
        AlterTableConf * const apiConf = 
 
3745
          (AlterTableConf*)signal->getDataPtrSend();
 
3746
        apiConf->senderRef = reference();
 
3747
        apiConf->senderData = alterTabPtr.p->m_senderData;
 
3748
        apiConf->tableId = tableId;
 
3749
        apiConf->tableVersion = tableVersion;
 
3750
        
 
3751
        //@todo check api failed
 
3752
        sendSignal(alterTabPtr.p->m_senderRef, GSN_ALTER_TABLE_CONF, signal,
 
3753
                   AlterTableConf::SignalLength, JBB);
 
3754
      }
 
3755
      
 
3756
      // Release resources
 
3757
      TableRecordPtr tabPtr;
 
3758
      c_tableRecordPool.getPtr(tabPtr, alterTabPtr.p->m_tablePtrI);  
 
3759
      releaseTableObject(tabPtr.i, false);
 
3760
      c_opCreateTable.release(alterTabPtr);
 
3761
      c_blockState = BS_IDLE;
 
3762
    }
 
3763
    else {
 
3764
      // (!safeCounter.done())
 
3765
      jam();
 
3766
    }
 
3767
    break;
 
3768
  }
 
3769
  default: ndbrequire(false);
 
3770
  }
 
3771
}
 
3772
 
 
3773
// For debugging
 
3774
inline
 
3775
void Dbdict::printTables()
 
3776
{
 
3777
  DLHashTable<TableRecord>::Iterator iter;
 
3778
  bool moreTables = c_tableRecordHash.first(iter);
 
3779
  printf("TABLES IN DICT:\n");
 
3780
  while (moreTables) {
 
3781
    TableRecordPtr tablePtr = iter.curr;
 
3782
    printf("%s ", tablePtr.p->tableName);
 
3783
    moreTables = c_tableRecordHash.next(iter);
 
3784
  }
 
3785
  printf("\n");
 
3786
}
 
3787
 
 
3788
int Dbdict::handleAlterTab(AlterTabReq * req,
 
3789
                           CreateTableRecord * alterTabPtrP,
 
3790
                           TableRecordPtr origTablePtr,
 
3791
                           TableRecordPtr newTablePtr)
 
3792
{
 
3793
  Uint32 changeMask = req->changeMask;
 
3794
  
 
3795
  if (AlterTableReq::getNameFlag(changeMask)) {
 
3796
    jam();
 
3797
    // Table rename
 
3798
    // Remove from hashtable
 
3799
#ifdef VM_TRACE
 
3800
    TableRecordPtr tmp;
 
3801
    ndbrequire(c_tableRecordHash.find(tmp, *origTablePtr.p));
 
3802
#endif
 
3803
    c_tableRecordHash.remove(origTablePtr);
 
3804
    strcpy(alterTabPtrP->previousTableName, origTablePtr.p->tableName);
 
3805
    strcpy(origTablePtr.p->tableName, newTablePtr.p->tableName);
 
3806
    // Set new schema version
 
3807
    origTablePtr.p->tableVersion = newTablePtr.p->tableVersion;
 
3808
    // Put it back
 
3809
#ifdef VM_TRACE
 
3810
    ndbrequire(!c_tableRecordHash.find(tmp, *origTablePtr.p));
 
3811
#endif
 
3812
    c_tableRecordHash.add(origTablePtr);         
 
3813
    
 
3814
    return 0;
 
3815
  }
 
3816
  jam();
 
3817
  return -1;
 
3818
}
 
3819
 
 
3820
void Dbdict::revertAlterTable(Signal * signal, 
 
3821
                              Uint32 changeMask, 
 
3822
                              Uint32 tableId,
 
3823
                              CreateTableRecord * alterTabPtrP)
 
3824
{
 
3825
  if (AlterTableReq::getNameFlag(changeMask)) {
 
3826
    jam();
 
3827
    // Table rename
 
3828
    // Restore previous name
 
3829
    TableRecordPtr tablePtr;
 
3830
    c_tableRecordPool.getPtr(tablePtr, tableId);
 
3831
    // Remove from hashtable
 
3832
#ifdef VM_TRACE
 
3833
    TableRecordPtr tmp;
 
3834
    ndbrequire(c_tableRecordHash.find(tmp, * tablePtr.p));
 
3835
#endif
 
3836
    c_tableRecordHash.remove(tablePtr);
 
3837
    // Restore name
 
3838
    strcpy(tablePtr.p->tableName, alterTabPtrP->previousTableName);
 
3839
    // Revert schema version
 
3840
    tablePtr.p->tableVersion = alter_table_dec_schema_version(tablePtr.p->tableVersion);
 
3841
    // Put it back
 
3842
#ifdef VM_TRACE
 
3843
    ndbrequire(!c_tableRecordHash.find(tmp, * tablePtr.p));
 
3844
#endif
 
3845
    c_tableRecordHash.add(tablePtr);     
 
3846
 
 
3847
    return;
 
3848
  }
 
3849
 
 
3850
  ndbrequire(false);
 
3851
}
 
3852
 
 
3853
void
 
3854
Dbdict::alterTab_writeSchemaConf(Signal* signal, 
 
3855
                                 Uint32 callbackData,
 
3856
                                 Uint32 returnCode)
 
3857
{
 
3858
  jam();
 
3859
  Uint32 key = callbackData;
 
3860
  CreateTableRecordPtr alterTabPtr;  
 
3861
  ndbrequire(c_opCreateTable.find(alterTabPtr, key));
 
3862
  Uint32 tableId = alterTabPtr.p->m_alterTableId;
 
3863
 
 
3864
  Callback callback;
 
3865
  callback.m_callbackData = alterTabPtr.p->key;
 
3866
  callback.m_callbackFunction = 
 
3867
    safe_cast(&Dbdict::alterTab_writeTableConf);
 
3868
  
 
3869
  SegmentedSectionPtr tabInfoPtr;
 
3870
  getSection(tabInfoPtr, alterTabPtr.p->m_tabInfoPtrI);
 
3871
  
 
3872
  writeTableFile(signal, tableId, tabInfoPtr, &callback);
 
3873
 
 
3874
  signal->setSection(tabInfoPtr, 0);
 
3875
  releaseSections(signal);
 
3876
}
 
3877
 
 
3878
void
 
3879
Dbdict::alterTab_writeTableConf(Signal* signal, 
 
3880
                                Uint32 callbackData,
 
3881
                                Uint32 returnCode)
 
3882
{
 
3883
  jam();
 
3884
  CreateTableRecordPtr alterTabPtr;  
 
3885
  ndbrequire(c_opCreateTable.find(alterTabPtr, callbackData));
 
3886
  Uint32 coordinatorRef = alterTabPtr.p->m_coordinatorRef;
 
3887
  TableRecordPtr tabPtr;
 
3888
  c_tableRecordPool.getPtr(tabPtr, alterTabPtr.p->m_alterTableId);
 
3889
 
 
3890
  // Alter table commit request handled successfully 
 
3891
  AlterTabConf * conf = (AlterTabConf*)signal->getDataPtrSend();
 
3892
  conf->senderRef = reference();
 
3893
  conf->senderData = callbackData;
 
3894
  conf->tableId = tabPtr.p->tableId;
 
3895
  conf->tableVersion = tabPtr.p->tableVersion;
 
3896
  conf->gci = tabPtr.p->gciTableCreated;
 
3897
  conf->requestType = AlterTabReq::AlterTableCommit;
 
3898
  sendSignal(coordinatorRef, GSN_ALTER_TAB_CONF, signal, 
 
3899
               AlterTabConf::SignalLength, JBB);
 
3900
 
 
3901
 
 
3902
  {
 
3903
    ApiBroadcastRep* api= (ApiBroadcastRep*)signal->getDataPtrSend();
 
3904
    api->gsn = GSN_ALTER_TABLE_REP;
 
3905
    api->minVersion = MAKE_VERSION(4,1,15);
 
3906
 
 
3907
    AlterTableRep* rep = (AlterTableRep*)api->theData;
 
3908
    rep->tableId = tabPtr.p->tableId;
 
3909
    rep->tableVersion = alter_table_dec_schema_version(tabPtr.p->tableVersion);
 
3910
    rep->changeType = AlterTableRep::CT_ALTERED;
 
3911
    
 
3912
    LinearSectionPtr ptr[3];
 
3913
    ptr[0].p = (Uint32*)alterTabPtr.p->previousTableName;
 
3914
    ptr[0].sz = (sizeof(alterTabPtr.p->previousTableName) + 3) >> 2;
 
3915
    
 
3916
    sendSignal(QMGR_REF, GSN_API_BROADCAST_REP, signal, 
 
3917
               ApiBroadcastRep::SignalLength + AlterTableRep::SignalLength,
 
3918
               JBB, ptr,1);
 
3919
  }
 
3920
 
 
3921
  if(coordinatorRef != reference()) {
 
3922
    jam();
 
3923
    // Release resources
 
3924
    c_tableRecordPool.getPtr(tabPtr, alterTabPtr.p->m_tablePtrI);  
 
3925
    releaseTableObject(tabPtr.i, false);
 
3926
    c_opCreateTable.release(alterTabPtr);
 
3927
    c_blockState = BS_IDLE;
 
3928
  }
 
3929
}
 
3930
 
 
3931
void
 
3932
Dbdict::execCREATE_FRAGMENTATION_REF(Signal * signal){
 
3933
  jamEntry();
 
3934
  const Uint32 * theData = signal->getDataPtr();
 
3935
  CreateFragmentationRef * const ref = (CreateFragmentationRef*)theData;
 
3936
  (void)ref;
 
3937
  ndbrequire(false);
 
3938
}
 
3939
 
 
3940
void
 
3941
Dbdict::execCREATE_FRAGMENTATION_CONF(Signal* signal){
 
3942
  jamEntry();
 
3943
  const Uint32 * theData = signal->getDataPtr();
 
3944
  CreateFragmentationConf * const conf = (CreateFragmentationConf*)theData;
 
3945
 
 
3946
  CreateTableRecordPtr createTabPtr;
 
3947
  ndbrequire(c_opCreateTable.find(createTabPtr, conf->senderData));
 
3948
 
 
3949
  ndbrequire(signal->getNoOfSections() == 1);
 
3950
 
 
3951
  SegmentedSectionPtr fragDataPtr;
 
3952
  signal->getSection(fragDataPtr, CreateFragmentationConf::FRAGMENTS);
 
3953
  signal->header.m_noOfSections = 0;
 
3954
 
 
3955
  /**
 
3956
   * Get table
 
3957
   */
 
3958
  TableRecordPtr tabPtr;
 
3959
  c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
 
3960
 
 
3961
  /**
 
3962
   * Save fragment count
 
3963
   */
 
3964
  tabPtr.p->fragmentCount = conf->noOfFragments;
 
3965
 
 
3966
  /**
 
3967
   * Update table version
 
3968
   */
 
3969
  XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
 
3970
  SchemaFile::TableEntry * tabEntry = getTableEntry(xsf, tabPtr.i);
 
3971
 
 
3972
  tabPtr.p->tableVersion = create_table_inc_schema_version(tabEntry->m_tableVersion);
 
3973
 
 
3974
  /**
 
3975
   * Pack
 
3976
   */
 
3977
  SimplePropertiesSectionWriter w(getSectionSegmentPool());
 
3978
  packTableIntoPagesImpl(w, tabPtr);
 
3979
  
 
3980
  SegmentedSectionPtr spDataPtr;
 
3981
  w.getPtr(spDataPtr);
 
3982
  
 
3983
  signal->setSection(spDataPtr, CreateTabReq::DICT_TAB_INFO);
 
3984
  signal->setSection(fragDataPtr, CreateTabReq::FRAGMENTATION);
 
3985
  
 
3986
  NodeReceiverGroup rg(DBDICT, c_aliveNodes);
 
3987
  SafeCounter tmp(c_counterMgr, createTabPtr.p->m_coordinatorData.m_counter);
 
3988
  createTabPtr.p->m_coordinatorData.m_gsn = GSN_CREATE_TAB_REQ;
 
3989
  createTabPtr.p->m_coordinatorData.m_requestType = CreateTabReq::CreateTablePrepare;
 
3990
  tmp.init<CreateTabRef>(rg, GSN_CREATE_TAB_REF, createTabPtr.p->key);
 
3991
  
 
3992
  CreateTabReq * const req = (CreateTabReq*)theData;
 
3993
  req->senderRef = reference();
 
3994
  req->senderData = createTabPtr.p->key;
 
3995
  req->clientRef = createTabPtr.p->m_senderRef;
 
3996
  req->clientData = createTabPtr.p->m_senderData;
 
3997
  req->requestType = CreateTabReq::CreateTablePrepare;
 
3998
 
 
3999
  req->gci = 0;
 
4000
  req->tableId = tabPtr.i;
 
4001
  req->tableVersion = create_table_inc_schema_version(tabEntry->m_tableVersion);
 
4002
  
 
4003
  sendFragmentedSignal(rg, GSN_CREATE_TAB_REQ, signal, 
 
4004
                       CreateTabReq::SignalLength, JBB);
 
4005
 
 
4006
  return;
 
4007
}
 
4008
 
 
4009
void
 
4010
Dbdict::execCREATE_TAB_REF(Signal* signal){
 
4011
  jamEntry();
 
4012
 
 
4013
  CreateTabRef * const ref = (CreateTabRef*)signal->getDataPtr();
 
4014
  
 
4015
  CreateTableRecordPtr createTabPtr;
 
4016
  ndbrequire(c_opCreateTable.find(createTabPtr, ref->senderData));
 
4017
  
 
4018
  ndbrequire(createTabPtr.p->m_coordinatorRef == reference());
 
4019
  ndbrequire(createTabPtr.p->m_coordinatorData.m_gsn == GSN_CREATE_TAB_REQ);
 
4020
 
 
4021
  if(ref->errorCode != CreateTabRef::NF_FakeErrorREF){
 
4022
    createTabPtr.p->setErrorCode(ref->errorCode);
 
4023
  }
 
4024
  createTab_reply(signal, createTabPtr, refToNode(ref->senderRef));
 
4025
}
 
4026
 
 
4027
void
 
4028
Dbdict::execCREATE_TAB_CONF(Signal* signal){
 
4029
  jamEntry();
 
4030
 
 
4031
  ndbrequire(signal->getNoOfSections() == 0);
 
4032
 
 
4033
  CreateTabConf * const conf = (CreateTabConf*)signal->getDataPtr();
 
4034
  
 
4035
  CreateTableRecordPtr createTabPtr;
 
4036
  ndbrequire(c_opCreateTable.find(createTabPtr, conf->senderData));
 
4037
  
 
4038
  ndbrequire(createTabPtr.p->m_coordinatorRef == reference());
 
4039
  ndbrequire(createTabPtr.p->m_coordinatorData.m_gsn == GSN_CREATE_TAB_REQ);
 
4040
 
 
4041
  createTab_reply(signal, createTabPtr, refToNode(conf->senderRef));
 
4042
}
 
4043
 
 
4044
void
 
4045
Dbdict::createTab_reply(Signal* signal, 
 
4046
                        CreateTableRecordPtr createTabPtr, 
 
4047
                        Uint32 nodeId)
 
4048
{
 
4049
 
 
4050
  SafeCounter tmp(c_counterMgr, createTabPtr.p->m_coordinatorData.m_counter);
 
4051
  if(!tmp.clearWaitingFor(nodeId)){
 
4052
    jam();
 
4053
    return;
 
4054
  }
 
4055
  
 
4056
  switch(createTabPtr.p->m_coordinatorData.m_requestType){
 
4057
  case CreateTabReq::CreateTablePrepare:{
 
4058
 
 
4059
    if(createTabPtr.p->m_errorCode != 0){
 
4060
      jam();
 
4061
      /**
 
4062
       * Failed to prepare on atleast one node -> abort on all
 
4063
       */
 
4064
      NodeReceiverGroup rg(DBDICT, c_aliveNodes);
 
4065
      createTabPtr.p->m_coordinatorData.m_gsn = GSN_CREATE_TAB_REQ;
 
4066
      createTabPtr.p->m_coordinatorData.m_requestType = CreateTabReq::CreateTableDrop;
 
4067
      ndbrequire(tmp.init<CreateTabRef>(rg, createTabPtr.p->key));
 
4068
      
 
4069
      CreateTabReq * const req = (CreateTabReq*)signal->getDataPtrSend();
 
4070
      req->senderRef = reference();
 
4071
      req->senderData = createTabPtr.p->key;
 
4072
      req->requestType = CreateTabReq::CreateTableDrop;
 
4073
      
 
4074
      sendSignal(rg, GSN_CREATE_TAB_REQ, signal, 
 
4075
                 CreateTabReq::SignalLength, JBB);
 
4076
      return;
 
4077
    }
 
4078
    
 
4079
    /**
 
4080
     * Lock mutex before commiting table
 
4081
     */
 
4082
    Mutex mutex(signal, c_mutexMgr, createTabPtr.p->m_startLcpMutex);
 
4083
    Callback c = { safe_cast(&Dbdict::createTab_startLcpMutex_locked),
 
4084
                   createTabPtr.p->key};
 
4085
 
 
4086
    ndbrequire(mutex.lock(c));
 
4087
    return;
 
4088
  }
 
4089
  case CreateTabReq::CreateTableCommit:{
 
4090
    jam();
 
4091
    ndbrequire(createTabPtr.p->m_errorCode == 0);
 
4092
    
 
4093
    /**
 
4094
     * Unlock mutex before commiting table
 
4095
     */
 
4096
    Mutex mutex(signal, c_mutexMgr, createTabPtr.p->m_startLcpMutex);
 
4097
    Callback c = { safe_cast(&Dbdict::createTab_startLcpMutex_unlocked),
 
4098
                   createTabPtr.p->key};
 
4099
    mutex.unlock(c);
 
4100
    return;
 
4101
  }
 
4102
  case CreateTabReq::CreateTableDrop:{
 
4103
    jam();
 
4104
    CreateTableRef * const ref = (CreateTableRef*)signal->getDataPtr();
 
4105
    ref->senderRef = reference();
 
4106
    ref->senderData = createTabPtr.p->m_senderData;
 
4107
    ref->errorCode = createTabPtr.p->m_errorCode;
 
4108
    ref->masterNodeId = c_masterNodeId;
 
4109
    ref->status = 0;
 
4110
    ref->errorKey = 0;
 
4111
    ref->errorLine = 0;
 
4112
    
 
4113
    //@todo check api failed
 
4114
    sendSignal(createTabPtr.p->m_senderRef, GSN_CREATE_TABLE_REF, signal, 
 
4115
               CreateTableRef::SignalLength, JBB);
 
4116
    c_opCreateTable.release(createTabPtr);
 
4117
    c_blockState = BS_IDLE;
 
4118
    return;
 
4119
  }
 
4120
  }
 
4121
  ndbrequire(false);
 
4122
}
 
4123
 
 
4124
void
 
4125
Dbdict::createTab_startLcpMutex_locked(Signal* signal, 
 
4126
                                       Uint32 callbackData,
 
4127
                                       Uint32 retValue){
 
4128
  jamEntry();
 
4129
 
 
4130
  ndbrequire(retValue == 0);
 
4131
  
 
4132
  CreateTableRecordPtr createTabPtr;  
 
4133
  ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
 
4134
  
 
4135
  NodeReceiverGroup rg(DBDICT, c_aliveNodes);
 
4136
  createTabPtr.p->m_coordinatorData.m_gsn = GSN_CREATE_TAB_REQ;
 
4137
  createTabPtr.p->m_coordinatorData.m_requestType = CreateTabReq::CreateTableCommit;
 
4138
  SafeCounter tmp(c_counterMgr, createTabPtr.p->m_coordinatorData.m_counter);
 
4139
  tmp.init<CreateTabRef>(rg, GSN_CREATE_TAB_REF, createTabPtr.p->key);
 
4140
  
 
4141
  CreateTabReq * const req = (CreateTabReq*)signal->getDataPtrSend();
 
4142
  req->senderRef = reference();
 
4143
  req->senderData = createTabPtr.p->key;
 
4144
  req->requestType = CreateTabReq::CreateTableCommit;
 
4145
  
 
4146
  sendSignal(rg, GSN_CREATE_TAB_REQ, signal, 
 
4147
             CreateTabReq::SignalLength, JBB);
 
4148
}
 
4149
 
 
4150
void
 
4151
Dbdict::createTab_startLcpMutex_unlocked(Signal* signal, 
 
4152
                                         Uint32 callbackData,
 
4153
                                         Uint32 retValue){
 
4154
  jamEntry();
 
4155
  
 
4156
  ndbrequire(retValue == 0);
 
4157
  
 
4158
  CreateTableRecordPtr createTabPtr;  
 
4159
  ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
 
4160
 
 
4161
  createTabPtr.p->m_startLcpMutex.release(c_mutexMgr);
 
4162
  
 
4163
  TableRecordPtr tabPtr;
 
4164
  c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
 
4165
  
 
4166
  CreateTableConf * const conf = (CreateTableConf*)signal->getDataPtr();
 
4167
  conf->senderRef = reference();
 
4168
  conf->senderData = createTabPtr.p->m_senderData;
 
4169
  conf->tableId = createTabPtr.p->m_tablePtrI;
 
4170
  conf->tableVersion = tabPtr.p->tableVersion;
 
4171
  
 
4172
  //@todo check api failed
 
4173
  sendSignal(createTabPtr.p->m_senderRef, GSN_CREATE_TABLE_CONF, signal, 
 
4174
             CreateTableConf::SignalLength, JBB);
 
4175
  c_opCreateTable.release(createTabPtr);
 
4176
  c_blockState = BS_IDLE;
 
4177
  return;
 
4178
}
 
4179
 
 
4180
/***********************************************************
 
4181
 * CreateTable participant code
 
4182
 **********************************************************/
 
4183
void
 
4184
Dbdict::execCREATE_TAB_REQ(Signal* signal){
 
4185
  jamEntry();
 
4186
 
 
4187
  if(!assembleFragments(signal)){
 
4188
    jam();
 
4189
    return;
 
4190
  }
 
4191
 
 
4192
  CreateTabReq * const req = (CreateTabReq*)signal->getDataPtr();
 
4193
 
 
4194
  CreateTabReq::RequestType rt = (CreateTabReq::RequestType)req->requestType;
 
4195
  switch(rt){
 
4196
  case CreateTabReq::CreateTablePrepare:
 
4197
    CRASH_INSERTION2(6003, getOwnNodeId() != c_masterNodeId);
 
4198
    createTab_prepare(signal, req);
 
4199
    return;
 
4200
  case CreateTabReq::CreateTableCommit:
 
4201
    CRASH_INSERTION2(6004, getOwnNodeId() != c_masterNodeId);
 
4202
    createTab_commit(signal, req);
 
4203
    return;
 
4204
  case CreateTabReq::CreateTableDrop:
 
4205
    CRASH_INSERTION2(6005, getOwnNodeId() != c_masterNodeId);
 
4206
    createTab_drop(signal, req);
 
4207
    return;
 
4208
  }
 
4209
  ndbrequire(false);
 
4210
}
 
4211
 
 
4212
void
 
4213
Dbdict::createTab_prepare(Signal* signal, CreateTabReq * req){
 
4214
 
 
4215
  const Uint32 gci = req->gci;
 
4216
  const Uint32 tableId = req->tableId;
 
4217
  const Uint32 tableVersion = req->tableVersion;
 
4218
 
 
4219
  SegmentedSectionPtr tabInfoPtr;
 
4220
  signal->getSection(tabInfoPtr, CreateTabReq::DICT_TAB_INFO);
 
4221
  
 
4222
  CreateTableRecordPtr createTabPtr;  
 
4223
  if(req->senderRef == reference()){
 
4224
    jam();
 
4225
    ndbrequire(c_opCreateTable.find(createTabPtr, req->senderData));
 
4226
  } else {
 
4227
    jam();
 
4228
    c_opCreateTable.seize(createTabPtr);
 
4229
    
 
4230
    ndbrequire(!createTabPtr.isNull());
 
4231
    
 
4232
    createTabPtr.p->key = req->senderData;
 
4233
    c_opCreateTable.add(createTabPtr);
 
4234
    createTabPtr.p->m_errorCode = 0;
 
4235
    createTabPtr.p->m_tablePtrI = tableId;
 
4236
    createTabPtr.p->m_coordinatorRef = req->senderRef;
 
4237
    createTabPtr.p->m_senderRef = req->clientRef;
 
4238
    createTabPtr.p->m_senderData = req->clientData;
 
4239
    createTabPtr.p->m_dihAddFragPtr = RNIL;
 
4240
    
 
4241
    /**
 
4242
     * Put data into table record
 
4243
     */
 
4244
    ParseDictTabInfoRecord parseRecord;
 
4245
    parseRecord.requestType = DictTabInfo::AddTableFromDict;
 
4246
    parseRecord.errorCode = 0;
 
4247
    
 
4248
    SimplePropertiesSectionReader r(tabInfoPtr, getSectionSegmentPool());
 
4249
    
 
4250
    handleTabInfoInit(r, &parseRecord);
 
4251
 
 
4252
    ndbrequire(parseRecord.errorCode == 0);
 
4253
  }
 
4254
  
 
4255
  ndbrequire(!createTabPtr.isNull());
 
4256
 
 
4257
  SegmentedSectionPtr fragPtr;
 
4258
  signal->getSection(fragPtr, CreateTabReq::FRAGMENTATION);
 
4259
 
 
4260
  createTabPtr.p->m_tabInfoPtrI = tabInfoPtr.i;
 
4261
  createTabPtr.p->m_fragmentsPtrI = fragPtr.i;
 
4262
  
 
4263
  signal->header.m_noOfSections = 0;
 
4264
  
 
4265
  TableRecordPtr tabPtr;
 
4266
  c_tableRecordPool.getPtr(tabPtr, tableId);
 
4267
  tabPtr.p->packedSize = tabInfoPtr.sz;
 
4268
  tabPtr.p->tableVersion = tableVersion;
 
4269
  tabPtr.p->gciTableCreated = gci;
 
4270
 
 
4271
  SchemaFile::TableEntry tabEntry;
 
4272
  tabEntry.m_tableVersion = tableVersion;
 
4273
  tabEntry.m_tableType    = tabPtr.p->tableType;
 
4274
  tabEntry.m_tableState   = SchemaFile::ADD_STARTED;
 
4275
  tabEntry.m_gcp          = gci;
 
4276
  tabEntry.m_info_words   = tabInfoPtr.sz;
 
4277
  memset(tabEntry.m_unused, 0, sizeof(tabEntry.m_unused));
 
4278
  
 
4279
  Callback callback;
 
4280
  callback.m_callbackData = createTabPtr.p->key;
 
4281
  callback.m_callbackFunction = 
 
4282
    safe_cast(&Dbdict::createTab_writeSchemaConf1);
 
4283
  
 
4284
  updateSchemaState(signal, tableId, &tabEntry, &callback);
 
4285
}
 
4286
 
 
4287
void getSection(SegmentedSectionPtr & ptr, Uint32 i);
 
4288
 
 
4289
void
 
4290
Dbdict::createTab_writeSchemaConf1(Signal* signal, 
 
4291
                                   Uint32 callbackData,
 
4292
                                   Uint32 returnCode){
 
4293
  jam();
 
4294
 
 
4295
  CreateTableRecordPtr createTabPtr;  
 
4296
  ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
 
4297
 
 
4298
  Callback callback;
 
4299
  callback.m_callbackData = createTabPtr.p->key;
 
4300
  callback.m_callbackFunction = 
 
4301
    safe_cast(&Dbdict::createTab_writeTableConf);
 
4302
  
 
4303
  SegmentedSectionPtr tabInfoPtr;
 
4304
  getSection(tabInfoPtr, createTabPtr.p->m_tabInfoPtrI);
 
4305
  writeTableFile(signal, createTabPtr.p->m_tablePtrI, tabInfoPtr, &callback);
 
4306
 
 
4307
  createTabPtr.p->m_tabInfoPtrI = RNIL;
 
4308
  signal->setSection(tabInfoPtr, 0);
 
4309
  releaseSections(signal);
 
4310
}
 
4311
 
 
4312
void
 
4313
Dbdict::createTab_writeTableConf(Signal* signal, 
 
4314
                                 Uint32 callbackData,
 
4315
                                 Uint32 returnCode){
 
4316
  jam();
 
4317
 
 
4318
  CreateTableRecordPtr createTabPtr;  
 
4319
  ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
 
4320
 
 
4321
  SegmentedSectionPtr fragDataPtr;
 
4322
  getSection(fragDataPtr, createTabPtr.p->m_fragmentsPtrI);
 
4323
  
 
4324
  Callback callback;
 
4325
  callback.m_callbackData = callbackData;
 
4326
  callback.m_callbackFunction = 
 
4327
    safe_cast(&Dbdict::createTab_dihComplete);
 
4328
  
 
4329
  createTab_dih(signal, createTabPtr, fragDataPtr, &callback);
 
4330
}
 
4331
 
 
4332
void
 
4333
Dbdict::createTab_dih(Signal* signal, 
 
4334
                      CreateTableRecordPtr createTabPtr, 
 
4335
                      SegmentedSectionPtr fragDataPtr,
 
4336
                      Callback * c){
 
4337
  jam();
 
4338
  
 
4339
  createTabPtr.p->m_callback = * c;
 
4340
 
 
4341
  TableRecordPtr tabPtr;
 
4342
  c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
 
4343
  
 
4344
  DiAddTabReq * req = (DiAddTabReq*)signal->getDataPtrSend();
 
4345
  req->connectPtr = createTabPtr.p->key;
 
4346
  req->tableId = tabPtr.i;
 
4347
  req->fragType = tabPtr.p->fragmentType;
 
4348
  req->kValue = tabPtr.p->kValue;
 
4349
  req->noOfReplicas = 0;
 
4350
  req->storedTable = tabPtr.p->storedTable;
 
4351
  req->tableType = tabPtr.p->tableType;
 
4352
  req->schemaVersion = tabPtr.p->tableVersion;
 
4353
  req->primaryTableId = tabPtr.p->primaryTableId;
 
4354
 
 
4355
  if(!fragDataPtr.isNull()){
 
4356
    signal->setSection(fragDataPtr, DiAddTabReq::FRAGMENTATION);
 
4357
  }
 
4358
 
 
4359
  sendSignal(DBDIH_REF, GSN_DIADDTABREQ, signal, 
 
4360
             DiAddTabReq::SignalLength, JBB);
 
4361
 
 
4362
  /**
 
4363
   * Create KeyDescriptor
 
4364
   */
 
4365
  KeyDescriptor* desc= g_key_descriptor_pool.getPtr(tabPtr.i);
 
4366
  new (desc) KeyDescriptor();
 
4367
 
 
4368
  Uint32 key = 0;
 
4369
  Uint32 tAttr = tabPtr.p->firstAttribute;
 
4370
  while (tAttr != RNIL) 
 
4371
  {
 
4372
    jam();
 
4373
    AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr);
 
4374
    if (aRec->tupleKey) 
 
4375
    {
 
4376
      desc->noOfKeyAttr ++;
 
4377
      desc->keyAttr[key].attributeDescriptor = aRec->attributeDescriptor;
 
4378
      
 
4379
      Uint32 csNumber = (aRec->extPrecision >> 16);
 
4380
      if(csNumber)
 
4381
      {
 
4382
        desc->keyAttr[key].charsetInfo = all_charsets[csNumber];
 
4383
        ndbrequire(all_charsets[csNumber]);
 
4384
        desc->hasCharAttr = 1;
 
4385
      }
 
4386
      else
 
4387
      {
 
4388
        desc->keyAttr[key].charsetInfo = 0;       
 
4389
      }
 
4390
      if(AttributeDescriptor::getDKey(aRec->attributeDescriptor))
 
4391
      {
 
4392
        desc->noOfDistrKeys ++;
 
4393
      }
 
4394
      key++;
 
4395
    }
 
4396
    tAttr = aRec->nextAttrInTable;
 
4397
  }
 
4398
  ndbrequire(key == tabPtr.p->noOfPrimkey);
 
4399
}
 
4400
 
 
4401
static
 
4402
void
 
4403
calcLHbits(Uint32 * lhPageBits, Uint32 * lhDistrBits, 
 
4404
           Uint32 fid, Uint32 totalFragments) 
 
4405
{
 
4406
  Uint32 distrBits = 0;
 
4407
  Uint32 pageBits = 0;
 
4408
  
 
4409
  Uint32 tmp = 1;
 
4410
  while (tmp < totalFragments) {
 
4411
    jam();
 
4412
    tmp <<= 1;
 
4413
    distrBits++;
 
4414
  }//while
 
4415
#ifdef ndb_classical_lhdistrbits
 
4416
  if (tmp != totalFragments) {
 
4417
    tmp >>= 1;
 
4418
    if ((fid >= (totalFragments - tmp)) && (fid < (tmp - 1))) {
 
4419
      distrBits--;
 
4420
    }//if
 
4421
  }//if
 
4422
#endif
 
4423
  * lhPageBits = pageBits;
 
4424
  * lhDistrBits = distrBits;
 
4425
 
 
4426
}//calcLHbits()
 
4427
 
 
4428
 
 
4429
void 
 
4430
Dbdict::execADD_FRAGREQ(Signal* signal) {
 
4431
  jamEntry();
 
4432
 
 
4433
  AddFragReq * const req = (AddFragReq*)signal->getDataPtr();
 
4434
  
 
4435
  Uint32 dihPtr = req->dihPtr;
 
4436
  Uint32 senderData = req->senderData;
 
4437
  Uint32 tableId = req->tableId;
 
4438
  Uint32 fragId = req->fragmentId;
 
4439
  Uint32 node = req->nodeId;
 
4440
  Uint32 lcpNo = req->nextLCP;
 
4441
  Uint32 fragCount = req->totalFragments;
 
4442
  Uint32 requestInfo = req->requestInfo;
 
4443
  Uint32 startGci = req->startGci;
 
4444
 
 
4445
  ndbrequire(node == getOwnNodeId());
 
4446
 
 
4447
  CreateTableRecordPtr createTabPtr;  
 
4448
  ndbrequire(c_opCreateTable.find(createTabPtr, senderData));
 
4449
  
 
4450
  createTabPtr.p->m_dihAddFragPtr = dihPtr;
 
4451
  
 
4452
  TableRecordPtr tabPtr;
 
4453
  c_tableRecordPool.getPtr(tabPtr, tableId);
 
4454
 
 
4455
#if 0
 
4456
  tabPtr.p->gciTableCreated = (startGci > tabPtr.p->gciTableCreated ? startGci:
 
4457
                               startGci > tabPtr.p->gciTableCreated);
 
4458
#endif
 
4459
  
 
4460
  /**
 
4461
   * Calc lh3PageBits
 
4462
   */
 
4463
  Uint32 lhDistrBits = 0;
 
4464
  Uint32 lhPageBits = 0;
 
4465
  ::calcLHbits(&lhPageBits, &lhDistrBits, fragId, fragCount);
 
4466
 
 
4467
  Uint64 maxRows = tabPtr.p->maxRowsLow +
 
4468
    (((Uint64)tabPtr.p->maxRowsHigh) << 32);
 
4469
  Uint64 minRows = tabPtr.p->minRowsLow +
 
4470
    (((Uint64)tabPtr.p->minRowsHigh) << 32);
 
4471
  maxRows = (maxRows + fragCount - 1) / fragCount;
 
4472
  minRows = (minRows + fragCount - 1) / fragCount;
 
4473
 
 
4474
  {  
 
4475
    LqhFragReq* req = (LqhFragReq*)signal->getDataPtrSend();
 
4476
    req->senderData = senderData;
 
4477
    req->senderRef = reference();
 
4478
    req->fragmentId = fragId;
 
4479
    req->requestInfo = requestInfo;
 
4480
    req->tableId = tableId;
 
4481
    req->localKeyLength = tabPtr.p->localKeyLen;
 
4482
    req->maxLoadFactor = tabPtr.p->maxLoadFactor;
 
4483
    req->minLoadFactor = tabPtr.p->minLoadFactor;
 
4484
    req->kValue = tabPtr.p->kValue;
 
4485
    req->lh3DistrBits = 0; //lhDistrBits;
 
4486
    req->lh3PageBits = 0; //lhPageBits;
 
4487
    req->noOfAttributes = tabPtr.p->noOfAttributes;
 
4488
    req->noOfNullAttributes = tabPtr.p->noOfNullBits;
 
4489
    req->maxRowsLow = maxRows & 0xFFFFFFFF;
 
4490
    req->maxRowsHigh = maxRows >> 32;
 
4491
    req->minRowsLow = minRows & 0xFFFFFFFF;
 
4492
    req->minRowsHigh = minRows >> 32;
 
4493
    req->schemaVersion = tabPtr.p->tableVersion;
 
4494
    Uint32 keyLen = tabPtr.p->tupKeyLength;
 
4495
    req->keyLength = keyLen; // wl-2066 no more "long keys"
 
4496
    req->nextLCP = lcpNo;
 
4497
 
 
4498
    req->noOfKeyAttr = tabPtr.p->noOfPrimkey;
 
4499
    req->noOfNewAttr = 0;
 
4500
    req->noOfCharsets = tabPtr.p->noOfCharsets;
 
4501
    req->checksumIndicator = 1;
 
4502
    req->noOfAttributeGroups = 1;
 
4503
    req->GCPIndicator = 0;
 
4504
    req->startGci = startGci;
 
4505
    req->tableType = tabPtr.p->tableType;
 
4506
    req->primaryTableId = tabPtr.p->primaryTableId;
 
4507
    sendSignal(DBLQH_REF, GSN_LQHFRAGREQ, signal, 
 
4508
               LqhFragReq::SignalLength, JBB);
 
4509
  }
 
4510
}
 
4511
 
 
4512
void
 
4513
Dbdict::execLQHFRAGREF(Signal * signal){
 
4514
  jamEntry();
 
4515
  LqhFragRef * const ref = (LqhFragRef*)signal->getDataPtr();
 
4516
 
 
4517
  CreateTableRecordPtr createTabPtr;  
 
4518
  ndbrequire(c_opCreateTable.find(createTabPtr, ref->senderData));
 
4519
  
 
4520
  createTabPtr.p->setErrorCode(ref->errorCode);
 
4521
  
 
4522
  {
 
4523
    AddFragRef * const ref = (AddFragRef*)signal->getDataPtr();
 
4524
    ref->dihPtr = createTabPtr.p->m_dihAddFragPtr;
 
4525
    sendSignal(DBDIH_REF, GSN_ADD_FRAGREF, signal, 
 
4526
               AddFragRef::SignalLength, JBB);
 
4527
  }
 
4528
}
 
4529
 
 
4530
void
 
4531
Dbdict::execLQHFRAGCONF(Signal * signal){
 
4532
  jamEntry();
 
4533
  LqhFragConf * const conf = (LqhFragConf*)signal->getDataPtr();
 
4534
 
 
4535
  CreateTableRecordPtr createTabPtr;  
 
4536
  ndbrequire(c_opCreateTable.find(createTabPtr, conf->senderData));
 
4537
  
 
4538
  createTabPtr.p->m_lqhFragPtr = conf->lqhFragPtr;
 
4539
  
 
4540
  TableRecordPtr tabPtr;
 
4541
  c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
 
4542
  sendLQHADDATTRREQ(signal, createTabPtr, tabPtr.p->firstAttribute);
 
4543
}
 
4544
 
 
4545
void
 
4546
Dbdict::sendLQHADDATTRREQ(Signal* signal,
 
4547
                          CreateTableRecordPtr createTabPtr,
 
4548
                          Uint32 attributePtrI){
 
4549
  jam();
 
4550
  TableRecordPtr tabPtr;
 
4551
  c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
 
4552
  LqhAddAttrReq * const req = (LqhAddAttrReq*)signal->getDataPtrSend();
 
4553
  Uint32 i = 0;
 
4554
  for(i = 0; i<LqhAddAttrReq::MAX_ATTRIBUTES && attributePtrI != RNIL; i++){
 
4555
    jam();
 
4556
    AttributeRecordPtr attrPtr;
 
4557
    c_attributeRecordPool.getPtr(attrPtr, attributePtrI);
 
4558
    LqhAddAttrReq::Entry& entry = req->attributes[i];
 
4559
    entry.attrId = attrPtr.p->attributeId;
 
4560
    entry.attrDescriptor = attrPtr.p->attributeDescriptor;
 
4561
    entry.extTypeInfo = 0;
 
4562
    // charset number passed to TUP, TUX in upper half
 
4563
    entry.extTypeInfo |= (attrPtr.p->extPrecision & ~0xFFFF);
 
4564
    if (tabPtr.p->isIndex()) {
 
4565
      Uint32 primaryAttrId;
 
4566
      if (attrPtr.p->nextAttrInTable != RNIL) {
 
4567
        getIndexAttr(tabPtr, attributePtrI, &primaryAttrId);
 
4568
      } else {
 
4569
        primaryAttrId = ZNIL;
 
4570
        if (tabPtr.p->isOrderedIndex())
 
4571
          entry.attrId = 0;     // attribute goes to TUP
 
4572
      }
 
4573
      entry.attrId |= (primaryAttrId << 16);
 
4574
    }
 
4575
    attributePtrI = attrPtr.p->nextAttrInTable;
 
4576
  }
 
4577
  req->lqhFragPtr = createTabPtr.p->m_lqhFragPtr;
 
4578
  req->senderData = createTabPtr.p->key;
 
4579
  req->senderAttrPtr = attributePtrI;
 
4580
  req->noOfAttributes = i;
 
4581
  
 
4582
  sendSignal(DBLQH_REF, GSN_LQHADDATTREQ, signal, 
 
4583
             LqhAddAttrReq::HeaderLength + LqhAddAttrReq::EntryLength * i, JBB);
 
4584
}
 
4585
 
 
4586
void
 
4587
Dbdict::execLQHADDATTREF(Signal * signal){
 
4588
  jamEntry();
 
4589
  LqhAddAttrRef * const ref = (LqhAddAttrRef*)signal->getDataPtr();
 
4590
 
 
4591
  CreateTableRecordPtr createTabPtr;  
 
4592
  ndbrequire(c_opCreateTable.find(createTabPtr, ref->senderData));
 
4593
  
 
4594
  createTabPtr.p->setErrorCode(ref->errorCode);
 
4595
  
 
4596
  {
 
4597
    AddFragRef * const ref = (AddFragRef*)signal->getDataPtr();
 
4598
    ref->dihPtr = createTabPtr.p->m_dihAddFragPtr;
 
4599
    sendSignal(DBDIH_REF, GSN_ADD_FRAGREF, signal, 
 
4600
               AddFragRef::SignalLength, JBB);
 
4601
  }
 
4602
  
 
4603
}
 
4604
 
 
4605
void
 
4606
Dbdict::execLQHADDATTCONF(Signal * signal){
 
4607
  jamEntry();
 
4608
  LqhAddAttrConf * const conf = (LqhAddAttrConf*)signal->getDataPtr();
 
4609
 
 
4610
  CreateTableRecordPtr createTabPtr;
 
4611
  ndbrequire(c_opCreateTable.find(createTabPtr, conf->senderData));
 
4612
  
 
4613
  const Uint32 fragId = conf->fragId;
 
4614
  const Uint32 nextAttrPtr = conf->senderAttrPtr;
 
4615
  if(nextAttrPtr != RNIL){
 
4616
    jam();
 
4617
    sendLQHADDATTRREQ(signal, createTabPtr, nextAttrPtr);
 
4618
    return;
 
4619
  }
 
4620
 
 
4621
  {
 
4622
    AddFragConf * const conf = (AddFragConf*)signal->getDataPtr();
 
4623
    conf->dihPtr = createTabPtr.p->m_dihAddFragPtr;
 
4624
    conf->fragId = fragId;
 
4625
    sendSignal(DBDIH_REF, GSN_ADD_FRAGCONF, signal, 
 
4626
               AddFragConf::SignalLength, JBB);
 
4627
  }
 
4628
}
 
4629
 
 
4630
void
 
4631
Dbdict::execDIADDTABREF(Signal* signal){
 
4632
  jam();
 
4633
  
 
4634
  DiAddTabRef * const ref = (DiAddTabRef*)signal->getDataPtr();
 
4635
  
 
4636
  CreateTableRecordPtr createTabPtr;  
 
4637
  ndbrequire(c_opCreateTable.find(createTabPtr, ref->senderData));
 
4638
  
 
4639
  createTabPtr.p->setErrorCode(ref->errorCode);  
 
4640
  execute(signal, createTabPtr.p->m_callback, 0);
 
4641
}
 
4642
 
 
4643
void
 
4644
Dbdict::execDIADDTABCONF(Signal* signal){
 
4645
  jam();
 
4646
  
 
4647
  DiAddTabConf * const conf = (DiAddTabConf*)signal->getDataPtr();
 
4648
  
 
4649
  CreateTableRecordPtr createTabPtr;  
 
4650
  ndbrequire(c_opCreateTable.find(createTabPtr, conf->senderData));
 
4651
 
 
4652
  signal->theData[0] = createTabPtr.p->key;
 
4653
  signal->theData[1] = reference();
 
4654
  signal->theData[2] = createTabPtr.p->m_tablePtrI;
 
4655
 
 
4656
  if(createTabPtr.p->m_dihAddFragPtr != RNIL){
 
4657
    jam();
 
4658
 
 
4659
    /**
 
4660
     * We did perform at least one LQHFRAGREQ
 
4661
     */
 
4662
    sendSignal(DBLQH_REF, GSN_TAB_COMMITREQ, signal, 3, JBB);
 
4663
    return;
 
4664
  } else {
 
4665
    /**
 
4666
     * No local fragment (i.e. no LQHFRAGREQ)
 
4667
     */
 
4668
    execute(signal, createTabPtr.p->m_callback, 0);
 
4669
    return;
 
4670
    //sendSignal(DBDIH_REF, GSN_TAB_COMMITREQ, signal, 3, JBB);
 
4671
  }
 
4672
}
 
4673
 
 
4674
void 
 
4675
Dbdict::execTAB_COMMITREF(Signal* signal) {
 
4676
  jamEntry();
 
4677
  ndbrequire(false);
 
4678
}//execTAB_COMMITREF()
 
4679
 
 
4680
void
 
4681
Dbdict::execTAB_COMMITCONF(Signal* signal){
 
4682
  jamEntry();
 
4683
 
 
4684
  CreateTableRecordPtr createTabPtr;  
 
4685
  ndbrequire(c_opCreateTable.find(createTabPtr, signal->theData[0]));
 
4686
  
 
4687
  if(refToBlock(signal->getSendersBlockRef()) == DBLQH){
 
4688
 
 
4689
    execute(signal, createTabPtr.p->m_callback, 0);
 
4690
    return;
 
4691
  }
 
4692
 
 
4693
  if(refToBlock(signal->getSendersBlockRef()) == DBDIH){
 
4694
    TableRecordPtr tabPtr;
 
4695
    c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
 
4696
    
 
4697
    signal->theData[0] = tabPtr.i;
 
4698
    signal->theData[1] = tabPtr.p->tableVersion;
 
4699
    signal->theData[2] = (Uint32)tabPtr.p->storedTable;     
 
4700
    signal->theData[3] = reference();
 
4701
    signal->theData[4] = (Uint32)tabPtr.p->tableType;
 
4702
    signal->theData[5] = createTabPtr.p->key;
 
4703
    signal->theData[6] = (Uint32)tabPtr.p->noOfPrimkey;
 
4704
    
 
4705
    sendSignal(DBTC_REF, GSN_TC_SCHVERREQ, signal, 7, JBB);
 
4706
    return;
 
4707
  }
 
4708
  
 
4709
  ndbrequire(false);
 
4710
}
 
4711
 
 
4712
void
 
4713
Dbdict::createTab_dihComplete(Signal* signal, 
 
4714
                              Uint32 callbackData,
 
4715
                              Uint32 returnCode){
 
4716
  jam();
 
4717
 
 
4718
  CreateTableRecordPtr createTabPtr;  
 
4719
  ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
 
4720
 
 
4721
  //@todo check for master failed
 
4722
  
 
4723
  if(createTabPtr.p->m_errorCode == 0){
 
4724
    jam();
 
4725
 
 
4726
    CreateTabConf * const conf = (CreateTabConf*)signal->getDataPtr();
 
4727
    conf->senderRef = reference();
 
4728
    conf->senderData = createTabPtr.p->key;
 
4729
    sendSignal(createTabPtr.p->m_coordinatorRef, GSN_CREATE_TAB_CONF,
 
4730
               signal, CreateTabConf::SignalLength, JBB);
 
4731
    return;
 
4732
  }
 
4733
 
 
4734
  CreateTabRef * const ref = (CreateTabRef*)signal->getDataPtr();
 
4735
  ref->senderRef = reference();
 
4736
  ref->senderData = createTabPtr.p->key;
 
4737
  ref->errorCode = createTabPtr.p->m_errorCode;
 
4738
  ref->errorLine = 0;
 
4739
  ref->errorKey = 0;
 
4740
  ref->errorStatus = 0;
 
4741
 
 
4742
  sendSignal(createTabPtr.p->m_coordinatorRef, GSN_CREATE_TAB_REF,
 
4743
             signal, CreateTabRef::SignalLength, JBB);
 
4744
}
 
4745
 
 
4746
void
 
4747
Dbdict::createTab_commit(Signal * signal, CreateTabReq * req){
 
4748
  jam();
 
4749
  
 
4750
  CreateTableRecordPtr createTabPtr;  
 
4751
  ndbrequire(c_opCreateTable.find(createTabPtr, req->senderData));
 
4752
 
 
4753
  TableRecordPtr tabPtr;
 
4754
  c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
 
4755
  
 
4756
  SchemaFile::TableEntry tabEntry;
 
4757
  tabEntry.m_tableVersion = tabPtr.p->tableVersion;
 
4758
  tabEntry.m_tableType    = tabPtr.p->tableType;
 
4759
  tabEntry.m_tableState   = SchemaFile::TABLE_ADD_COMMITTED;
 
4760
  tabEntry.m_gcp          = tabPtr.p->gciTableCreated;
 
4761
  tabEntry.m_info_words   = tabPtr.p->packedSize;
 
4762
  memset(tabEntry.m_unused, 0, sizeof(tabEntry.m_unused));
 
4763
  
 
4764
  Callback callback;
 
4765
  callback.m_callbackData = createTabPtr.p->key;
 
4766
  callback.m_callbackFunction = 
 
4767
    safe_cast(&Dbdict::createTab_writeSchemaConf2);
 
4768
  
 
4769
  updateSchemaState(signal, tabPtr.i, &tabEntry, &callback);
 
4770
}
 
4771
 
 
4772
void
 
4773
Dbdict::createTab_writeSchemaConf2(Signal* signal, 
 
4774
                                   Uint32 callbackData,
 
4775
                                   Uint32 returnCode){
 
4776
  jam();
 
4777
  
 
4778
  CreateTableRecordPtr createTabPtr;  
 
4779
  ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
 
4780
  
 
4781
  Callback c;
 
4782
  c.m_callbackData = callbackData;
 
4783
  c.m_callbackFunction = safe_cast(&Dbdict::createTab_alterComplete);
 
4784
  alterTab_activate(signal, createTabPtr, &c);
 
4785
}
 
4786
 
 
4787
void
 
4788
Dbdict::createTab_alterComplete(Signal* signal, 
 
4789
                                Uint32 callbackData,
 
4790
                                Uint32 returnCode){
 
4791
  jam();
 
4792
 
 
4793
  CreateTableRecordPtr createTabPtr;  
 
4794
  ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
 
4795
  
 
4796
  TableRecordPtr tabPtr;
 
4797
  c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
 
4798
  tabPtr.p->tabState = TableRecord::DEFINED;
 
4799
  
 
4800
  //@todo check error
 
4801
  //@todo check master failed
 
4802
  
 
4803
  CreateTabConf * const conf = (CreateTabConf*)signal->getDataPtr();
 
4804
  conf->senderRef = reference();
 
4805
  conf->senderData = createTabPtr.p->key;
 
4806
  sendSignal(createTabPtr.p->m_coordinatorRef, GSN_CREATE_TAB_CONF,
 
4807
             signal, CreateTabConf::SignalLength, JBB);
 
4808
 
 
4809
  if(createTabPtr.p->m_coordinatorRef != reference()){
 
4810
    jam();
 
4811
    c_opCreateTable.release(createTabPtr);
 
4812
  }
 
4813
}
 
4814
 
 
4815
void
 
4816
Dbdict::createTab_drop(Signal* signal, CreateTabReq * req){
 
4817
  jam();
 
4818
 
 
4819
  const Uint32 key = req->senderData;
 
4820
 
 
4821
  CreateTableRecordPtr createTabPtr;  
 
4822
  ndbrequire(c_opCreateTable.find(createTabPtr, key));
 
4823
  
 
4824
  TableRecordPtr tabPtr;
 
4825
  c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
 
4826
  tabPtr.p->tabState = TableRecord::DROPPING;
 
4827
 
 
4828
  DropTableRecordPtr dropTabPtr;  
 
4829
  ndbrequire(c_opDropTable.seize(dropTabPtr));
 
4830
  
 
4831
  dropTabPtr.p->key = key;
 
4832
  c_opDropTable.add(dropTabPtr);
 
4833
  
 
4834
  dropTabPtr.p->m_errorCode = 0;
 
4835
  dropTabPtr.p->m_request.tableId = createTabPtr.p->m_tablePtrI;
 
4836
  dropTabPtr.p->m_requestType = DropTabReq::CreateTabDrop;
 
4837
  dropTabPtr.p->m_coordinatorRef = createTabPtr.p->m_coordinatorRef;
 
4838
  dropTabPtr.p->m_participantData.m_gsn = GSN_DROP_TAB_REQ;
 
4839
  
 
4840
  dropTabPtr.p->m_participantData.m_block = 0;
 
4841
  dropTabPtr.p->m_participantData.m_callback.m_callbackData = req->senderData;
 
4842
  dropTabPtr.p->m_participantData.m_callback.m_callbackFunction = 
 
4843
    safe_cast(&Dbdict::createTab_dropComplete);
 
4844
  dropTab_nextStep(signal, dropTabPtr);  
 
4845
}
 
4846
 
 
4847
void
 
4848
Dbdict::createTab_dropComplete(Signal* signal, 
 
4849
                               Uint32 callbackData,
 
4850
                               Uint32 returnCode){
 
4851
  jam();
 
4852
 
 
4853
  CreateTableRecordPtr createTabPtr;  
 
4854
  ndbrequire(c_opCreateTable.find(createTabPtr, callbackData));
 
4855
  
 
4856
  DropTableRecordPtr dropTabPtr;
 
4857
  ndbrequire(c_opDropTable.find(dropTabPtr, callbackData));
 
4858
 
 
4859
  TableRecordPtr tabPtr;
 
4860
  c_tableRecordPool.getPtr(tabPtr, createTabPtr.p->m_tablePtrI);
 
4861
  
 
4862
  releaseTableObject(tabPtr.i);
 
4863
 
 
4864
  XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
 
4865
  SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, tabPtr.i);
 
4866
  tableEntry->m_tableState = SchemaFile::DROP_TABLE_COMMITTED;
 
4867
  
 
4868
  //@todo check error
 
4869
  //@todo check master failed
 
4870
  
 
4871
  CreateTabConf * const conf = (CreateTabConf*)signal->getDataPtr();
 
4872
  conf->senderRef = reference();
 
4873
  conf->senderData = createTabPtr.p->key;
 
4874
  sendSignal(createTabPtr.p->m_coordinatorRef, GSN_CREATE_TAB_CONF,
 
4875
             signal, CreateTabConf::SignalLength, JBB);
 
4876
 
 
4877
  if(createTabPtr.p->m_coordinatorRef != reference()){
 
4878
    jam();
 
4879
    c_opCreateTable.release(createTabPtr);
 
4880
  }
 
4881
 
 
4882
  c_opDropTable.release(dropTabPtr);
 
4883
}
 
4884
 
 
4885
void
 
4886
Dbdict::alterTab_activate(Signal* signal, CreateTableRecordPtr createTabPtr,
 
4887
                          Callback * c){
 
4888
 
 
4889
  createTabPtr.p->m_callback = * c;
 
4890
  
 
4891
  signal->theData[0] = createTabPtr.p->key;
 
4892
  signal->theData[1] = reference();
 
4893
  signal->theData[2] = createTabPtr.p->m_tablePtrI;
 
4894
  sendSignal(DBDIH_REF, GSN_TAB_COMMITREQ, signal, 3, JBB);
 
4895
}
 
4896
 
 
4897
void
 
4898
Dbdict::execTC_SCHVERCONF(Signal* signal){
 
4899
  jamEntry();
 
4900
 
 
4901
  CreateTableRecordPtr createTabPtr;  
 
4902
  ndbrequire(c_opCreateTable.find(createTabPtr, signal->theData[1]));
 
4903
 
 
4904
  execute(signal, createTabPtr.p->m_callback, 0);
 
4905
}
 
4906
 
 
4907
#define tabRequire(cond, error) \
 
4908
  if (!(cond)) { \
 
4909
    jam();    \
 
4910
    parseP->errorCode = error; parseP->errorLine = __LINE__; \
 
4911
    parseP->errorKey = it.getKey(); \
 
4912
    return;   \
 
4913
  }//if
 
4914
 
 
4915
// handleAddTableFailure(signal, __LINE__, allocatedTable);
 
4916
 
 
4917
void Dbdict::handleTabInfoInit(SimpleProperties::Reader & it,
 
4918
                               ParseDictTabInfoRecord * parseP,
 
4919
                               bool checkExist) 
 
4920
{
 
4921
/* ---------------------------------------------------------------- */
 
4922
// We always start by handling table name since this must be the first
 
4923
// item in the list. Through the table name we can derive if it is a
 
4924
// correct name, a new name or an already existing table.
 
4925
/* ---------------------------------------------------------------- */
 
4926
 
 
4927
  it.first();
 
4928
 
 
4929
  SimpleProperties::UnpackStatus status;
 
4930
  DictTabInfo::Table tableDesc; tableDesc.init();
 
4931
  status = SimpleProperties::unpack(it, &tableDesc, 
 
4932
                                    DictTabInfo::TableMapping, 
 
4933
                                    DictTabInfo::TableMappingSize, 
 
4934
                                    true, true);
 
4935
  
 
4936
  if(status != SimpleProperties::Break){
 
4937
    parseP->errorCode = CreateTableRef::InvalidFormat;
 
4938
    parseP->status    = status;
 
4939
    parseP->errorKey  = it.getKey();
 
4940
    parseP->errorLine = __LINE__;
 
4941
    return;
 
4942
  }
 
4943
 
 
4944
  if(parseP->requestType == DictTabInfo::AlterTableFromAPI)
 
4945
  {  
 
4946
    ndbrequire(!checkExist);
 
4947
  }
 
4948
  if(!checkExist)
 
4949
  {
 
4950
    ndbrequire(parseP->requestType == DictTabInfo::AlterTableFromAPI);
 
4951
  }
 
4952
  
 
4953
  /* ---------------------------------------------------------------- */
 
4954
  // Verify that table name is an allowed table name.
 
4955
  // TODO
 
4956
  /* ---------------------------------------------------------------- */
 
4957
  const Uint32 tableNameLength = strlen(tableDesc.TableName) + 1;
 
4958
 
 
4959
  TableRecord keyRecord;
 
4960
  tabRequire(tableNameLength <= sizeof(keyRecord.tableName),
 
4961
             CreateTableRef::TableNameTooLong);
 
4962
  strcpy(keyRecord.tableName, tableDesc.TableName);
 
4963
  
 
4964
  TableRecordPtr tablePtr;
 
4965
  c_tableRecordHash.find(tablePtr, keyRecord);
 
4966
  
 
4967
  if (checkExist){
 
4968
    jam();
 
4969
    /* ---------------------------------------------------------------- */
 
4970
    // Check if table already existed.
 
4971
    /* ---------------------------------------------------------------- */
 
4972
    tabRequire(tablePtr.i == RNIL, CreateTableRef::TableAlreadyExist);
 
4973
  }
 
4974
 
 
4975
  switch (parseP->requestType) {
 
4976
  case DictTabInfo::CreateTableFromAPI: {
 
4977
    jam();
 
4978
  }
 
4979
  case DictTabInfo::AlterTableFromAPI:{
 
4980
    jam();
 
4981
    tablePtr.i = getFreeTableRecord(tableDesc.PrimaryTableId);
 
4982
    /* ---------------------------------------------------------------- */
 
4983
    // Check if no free tables existed.
 
4984
    /* ---------------------------------------------------------------- */
 
4985
    tabRequire(tablePtr.i != RNIL, CreateTableRef::NoMoreTableRecords);
 
4986
    
 
4987
    c_tableRecordPool.getPtr(tablePtr);
 
4988
    break;
 
4989
  }
 
4990
  case DictTabInfo::AddTableFromDict:
 
4991
  case DictTabInfo::ReadTableFromDiskSR:
 
4992
  case DictTabInfo::GetTabInfoConf:
 
4993
  {
 
4994
/* ---------------------------------------------------------------- */
 
4995
// Get table id and check that table doesn't already exist
 
4996
/* ---------------------------------------------------------------- */
 
4997
    tablePtr.i = tableDesc.TableId;
 
4998
    
 
4999
    if (parseP->requestType == DictTabInfo::ReadTableFromDiskSR) {
 
5000
      ndbrequire(tablePtr.i == c_restartRecord.activeTable);
 
5001
    }//if
 
5002
    if (parseP->requestType == DictTabInfo::GetTabInfoConf) {
 
5003
      ndbrequire(tablePtr.i == c_restartRecord.activeTable);
 
5004
    }//if
 
5005
    
 
5006
    c_tableRecordPool.getPtr(tablePtr);
 
5007
    ndbrequire(tablePtr.p->tabState == TableRecord::NOT_DEFINED);
 
5008
    
 
5009
    //Uint32 oldTableVersion = tablePtr.p->tableVersion;
 
5010
    initialiseTableRecord(tablePtr);
 
5011
    if (parseP->requestType == DictTabInfo::AddTableFromDict) {
 
5012
      jam();
 
5013
      tablePtr.p->tabState = TableRecord::DEFINING;
 
5014
    }//if
 
5015
#ifdef HAVE_TABLE_REORG
 
5016
/* ---------------------------------------------------------------- */
 
5017
// Get id of second table id and check that table doesn't already exist
 
5018
// and set up links between first and second table.
 
5019
/* ---------------------------------------------------------------- */
 
5020
    TableRecordPtr secondTablePtr;
 
5021
    secondTablePtr.i = tableDesc.SecondTableId;
 
5022
    c_tableRecordPool.getPtr(secondTablePtr);
 
5023
    ndbrequire(secondTablePtr.p->tabState == TableRecord::NOT_DEFINED);
 
5024
    
 
5025
    initialiseTableRecord(secondTablePtr);
 
5026
    secondTablePtr.p->tabState = TableRecord::REORG_TABLE_PREPARED;
 
5027
    secondTablePtr.p->secondTable = tablePtr.i;
 
5028
    tablePtr.p->secondTable = secondTablePtr.i;
 
5029
#endif
 
5030
/* ---------------------------------------------------------------- */
 
5031
// Set table version
 
5032
/* ---------------------------------------------------------------- */
 
5033
    Uint32 tableVersion = tableDesc.TableVersion;
 
5034
    tablePtr.p->tableVersion = tableVersion;
 
5035
    
 
5036
    break;
 
5037
  }
 
5038
  default:
 
5039
    ndbrequire(false);
 
5040
    break;
 
5041
  }//switch
 
5042
  parseP->tablePtr = tablePtr;
 
5043
  
 
5044
  strcpy(tablePtr.p->tableName, keyRecord.tableName);  
 
5045
  if (parseP->requestType != DictTabInfo::AlterTableFromAPI) {
 
5046
    jam();
 
5047
#ifdef VM_TRACE
 
5048
    ndbout_c("Dbdict: name=%s,id=%u", tablePtr.p->tableName, tablePtr.i);
 
5049
    TableRecordPtr tmp;
 
5050
    ndbrequire(!c_tableRecordHash.find(tmp, * tablePtr.p));
 
5051
#endif
 
5052
    c_tableRecordHash.add(tablePtr);
 
5053
  }
 
5054
  
 
5055
  //tablePtr.p->noOfPrimkey = tableDesc.NoOfKeyAttr;
 
5056
  //tablePtr.p->noOfNullAttr = tableDesc.NoOfNullable;
 
5057
  //tablePtr.p->tupKeyLength = tableDesc.KeyLength;
 
5058
  tablePtr.p->noOfAttributes = tableDesc.NoOfAttributes;
 
5059
  tablePtr.p->storedTable = tableDesc.TableLoggedFlag;
 
5060
  tablePtr.p->minLoadFactor = tableDesc.MinLoadFactor;
 
5061
  tablePtr.p->maxLoadFactor = tableDesc.MaxLoadFactor;
 
5062
  tablePtr.p->fragmentType = (DictTabInfo::FragmentType)tableDesc.FragmentType;
 
5063
  tablePtr.p->tableType = (DictTabInfo::TableType)tableDesc.TableType;
 
5064
  tablePtr.p->kValue = tableDesc.TableKValue;
 
5065
  tablePtr.p->fragmentCount = tableDesc.FragmentCount;
 
5066
  tablePtr.p->maxRowsLow = tableDesc.MaxRowsLow;
 
5067
  tablePtr.p->maxRowsHigh = tableDesc.MaxRowsHigh;
 
5068
  tablePtr.p->minRowsLow = tableDesc.MinRowsLow;
 
5069
  tablePtr.p->minRowsHigh = tableDesc.MinRowsHigh;
 
5070
 
 
5071
  Uint64 maxRows =
 
5072
    (((Uint64)tablePtr.p->maxRowsHigh) << 32) + tablePtr.p->maxRowsLow;
 
5073
  Uint64 minRows =
 
5074
    (((Uint64)tablePtr.p->minRowsHigh) << 32) + tablePtr.p->minRowsLow;
 
5075
 
 
5076
  tablePtr.p->frmLen = tableDesc.FrmLen;
 
5077
  memcpy(tablePtr.p->frmData, tableDesc.FrmData, tableDesc.FrmLen);  
 
5078
 
 
5079
  if(tableDesc.PrimaryTableId != RNIL) {
 
5080
    
 
5081
    tablePtr.p->primaryTableId = tableDesc.PrimaryTableId;
 
5082
    tablePtr.p->indexState = (TableRecord::IndexState)tableDesc.IndexState;
 
5083
    tablePtr.p->insertTriggerId = tableDesc.InsertTriggerId;
 
5084
    tablePtr.p->updateTriggerId = tableDesc.UpdateTriggerId;
 
5085
    tablePtr.p->deleteTriggerId = tableDesc.DeleteTriggerId;
 
5086
    tablePtr.p->customTriggerId = tableDesc.CustomTriggerId;
 
5087
  } else {
 
5088
    tablePtr.p->primaryTableId = RNIL;
 
5089
    tablePtr.p->indexState = TableRecord::IS_UNDEFINED;
 
5090
    tablePtr.p->insertTriggerId = RNIL;
 
5091
    tablePtr.p->updateTriggerId = RNIL;
 
5092
    tablePtr.p->deleteTriggerId = RNIL;
 
5093
    tablePtr.p->customTriggerId = RNIL;
 
5094
  }
 
5095
  tablePtr.p->buildTriggerId = RNIL;
 
5096
  tablePtr.p->indexLocal = 0;
 
5097
  
 
5098
  handleTabInfo(it, parseP);
 
5099
 
 
5100
  if(parseP->errorCode != 0)
 
5101
  {
 
5102
    /**
 
5103
     * Release table
 
5104
     */
 
5105
    releaseTableObject(tablePtr.i, checkExist);
 
5106
  }
 
5107
}//handleTabInfoInit()
 
5108
 
 
5109
void Dbdict::handleTabInfo(SimpleProperties::Reader & it,
 
5110
                           ParseDictTabInfoRecord * parseP)
 
5111
{
 
5112
  TableRecordPtr tablePtr = parseP->tablePtr;
 
5113
  
 
5114
  SimpleProperties::UnpackStatus status;
 
5115
  
 
5116
  Uint32 keyCount = 0;
 
5117
  Uint32 keyLength = 0;
 
5118
  Uint32 attrCount = tablePtr.p->noOfAttributes;
 
5119
  Uint32 nullCount = 0;
 
5120
  Uint32 nullBits = 0;
 
5121
  Uint32 noOfCharsets = 0;
 
5122
  Uint16 charsets[128];
 
5123
  Uint32 recordLength = 0;
 
5124
  AttributeRecordPtr attrPtr;
 
5125
  c_attributeRecordHash.removeAll();
 
5126
  
 
5127
  for(Uint32 i = 0; i<attrCount; i++){
 
5128
    /**
 
5129
     * Attribute Name
 
5130
     */
 
5131
    DictTabInfo::Attribute attrDesc; attrDesc.init();
 
5132
    status = SimpleProperties::unpack(it, &attrDesc, 
 
5133
                                      DictTabInfo::AttributeMapping, 
 
5134
                                      DictTabInfo::AttributeMappingSize, 
 
5135
                                      true, true);
 
5136
    if(status != SimpleProperties::Break){
 
5137
      parseP->errorCode = CreateTableRef::InvalidFormat;
 
5138
      parseP->status    = status;
 
5139
      parseP->errorKey  = it.getKey();
 
5140
      parseP->errorLine = __LINE__;
 
5141
      return;
 
5142
    }
 
5143
 
 
5144
    /**
 
5145
     * Check that attribute is not defined twice
 
5146
     */
 
5147
    AttributeRecord tmpAttr;
 
5148
    {
 
5149
      strcpy(tmpAttr.attributeName, attrDesc.AttributeName); 
 
5150
      
 
5151
      AttributeRecordPtr attrPtr;
 
5152
      c_attributeRecordHash.find(attrPtr, tmpAttr);
 
5153
      
 
5154
      if(attrPtr.i != RNIL){
 
5155
        parseP->errorCode = CreateTableRef::AttributeNameTwice;
 
5156
        return;
 
5157
      }
 
5158
    }
 
5159
    
 
5160
    if(!getNewAttributeRecord(tablePtr, attrPtr)){
 
5161
      jam();
 
5162
      parseP->errorCode = CreateTableRef::NoMoreAttributeRecords;
 
5163
      return;
 
5164
    }
 
5165
    
 
5166
    /**
 
5167
     * TmpAttrib to Attribute mapping
 
5168
     */
 
5169
    strcpy(attrPtr.p->attributeName, attrDesc.AttributeName);
 
5170
    attrPtr.p->attributeId = attrDesc.AttributeId;
 
5171
    attrPtr.p->tupleKey = (keyCount + 1) * attrDesc.AttributeKeyFlag;
 
5172
 
 
5173
    attrPtr.p->extPrecision = attrDesc.AttributeExtPrecision;
 
5174
    attrPtr.p->extScale = attrDesc.AttributeExtScale;
 
5175
    attrPtr.p->extLength = attrDesc.AttributeExtLength;
 
5176
    // charset in upper half of precision
 
5177
    unsigned csNumber = (attrPtr.p->extPrecision >> 16);
 
5178
    if (csNumber != 0) {
 
5179
      /*
 
5180
       * A new charset is first accessed here on this node.
 
5181
       * TODO use separate thread (e.g. via NDBFS) if need to load from file
 
5182
       */
 
5183
      CHARSET_INFO* cs = get_charset(csNumber, MYF(0));
 
5184
      if (cs == NULL) {
 
5185
        parseP->errorCode = CreateTableRef::InvalidCharset;
 
5186
        parseP->errorLine = __LINE__;
 
5187
        return;
 
5188
      }
 
5189
      // XXX should be done somewhere in mysql
 
5190
      all_charsets[cs->number] = cs;
 
5191
      unsigned i = 0;
 
5192
      while (i < noOfCharsets) {
 
5193
        if (charsets[i] == csNumber)
 
5194
          break;
 
5195
        i++;
 
5196
      }
 
5197
      if (i == noOfCharsets) {
 
5198
        noOfCharsets++;
 
5199
        if (noOfCharsets > sizeof(charsets)/sizeof(charsets[0])) {
 
5200
          parseP->errorCode = CreateTableRef::InvalidFormat;
 
5201
          parseP->errorLine = __LINE__;
 
5202
          return;
 
5203
        }
 
5204
        charsets[i] = csNumber;
 
5205
      }
 
5206
    }
 
5207
 
 
5208
    // compute attribute size and array size
 
5209
    bool translateOk = attrDesc.translateExtType();
 
5210
    tabRequire(translateOk, CreateTableRef::Inconsistency);
 
5211
 
 
5212
    if(attrDesc.AttributeArraySize > 65535){
 
5213
      parseP->errorCode = CreateTableRef::ArraySizeTooBig;
 
5214
      parseP->status    = status;
 
5215
      parseP->errorKey  = it.getKey();
 
5216
      parseP->errorLine = __LINE__;
 
5217
      return;
 
5218
    }
 
5219
    
 
5220
    Uint32 desc = 0;
 
5221
    AttributeDescriptor::setType(desc, attrDesc.AttributeExtType);
 
5222
    AttributeDescriptor::setSize(desc, attrDesc.AttributeSize);
 
5223
    AttributeDescriptor::setArray(desc, attrDesc.AttributeArraySize);
 
5224
    AttributeDescriptor::setNullable(desc, attrDesc.AttributeNullableFlag);
 
5225
    AttributeDescriptor::setDKey(desc, attrDesc.AttributeDKey);
 
5226
    AttributeDescriptor::setPrimaryKey(desc, attrDesc.AttributeKeyFlag);
 
5227
    attrPtr.p->attributeDescriptor = desc;
 
5228
    attrPtr.p->autoIncrement = attrDesc.AttributeAutoIncrement;
 
5229
    strcpy(attrPtr.p->defaultValue, attrDesc.AttributeDefaultValue);
 
5230
    
 
5231
    tabRequire(attrDesc.AttributeId == i, CreateTableRef::InvalidFormat);
 
5232
    
 
5233
    attrCount ++;
 
5234
    keyCount += attrDesc.AttributeKeyFlag;
 
5235
    nullCount += attrDesc.AttributeNullableFlag;
 
5236
    
 
5237
    const Uint32 aSz = (1 << attrDesc.AttributeSize);
 
5238
    Uint32 sz;
 
5239
    if(aSz != 1)
 
5240
    {
 
5241
      sz = ((aSz * attrDesc.AttributeArraySize) + 31) >> 5;
 
5242
    }    
 
5243
    else
 
5244
    {
 
5245
      sz = 0;
 
5246
      nullBits += attrDesc.AttributeArraySize;      
 
5247
    }
 
5248
    
 
5249
    if(attrDesc.AttributeArraySize == 0)
 
5250
    {
 
5251
      parseP->errorCode = CreateTableRef::InvalidArraySize;
 
5252
      parseP->status    = status;
 
5253
      parseP->errorKey  = it.getKey();
 
5254
      parseP->errorLine = __LINE__;
 
5255
      return;
 
5256
    }
 
5257
    
 
5258
    recordLength += sz;
 
5259
    if(attrDesc.AttributeKeyFlag){
 
5260
      keyLength += sz;
 
5261
 
 
5262
      if(attrDesc.AttributeNullableFlag){
 
5263
        parseP->errorCode = CreateTableRef::NullablePrimaryKey;
 
5264
        parseP->status    = status;
 
5265
        parseP->errorKey  = it.getKey();
 
5266
        parseP->errorLine = __LINE__;
 
5267
        return;
 
5268
      }
 
5269
    }
 
5270
    
 
5271
    if (parseP->requestType != DictTabInfo::AlterTableFromAPI)
 
5272
      c_attributeRecordHash.add(attrPtr);
 
5273
    
 
5274
    if(!it.next())
 
5275
      break;
 
5276
    
 
5277
    if(it.getKey() != DictTabInfo::AttributeName)
 
5278
      break;
 
5279
  }//while
 
5280
  
 
5281
  tablePtr.p->noOfPrimkey = keyCount;
 
5282
  tablePtr.p->noOfNullAttr = nullCount;
 
5283
  tablePtr.p->noOfCharsets = noOfCharsets;
 
5284
  tablePtr.p->tupKeyLength = keyLength;
 
5285
  tablePtr.p->noOfNullBits = nullCount + nullBits;
 
5286
 
 
5287
  tabRequire(recordLength<= MAX_TUPLE_SIZE_IN_WORDS, 
 
5288
             CreateTableRef::RecordTooBig);
 
5289
  tabRequire(keyLength <= MAX_KEY_SIZE_IN_WORDS, 
 
5290
             CreateTableRef::InvalidPrimaryKeySize);
 
5291
  tabRequire(keyLength > 0, 
 
5292
             CreateTableRef::InvalidPrimaryKeySize);
 
5293
  
 
5294
}//handleTabInfo()
 
5295
 
 
5296
 
 
5297
/* ---------------------------------------------------------------- */
 
5298
// DICTTABCONF is sent when participants have received all DICTTABINFO
 
5299
// and successfully handled it.
 
5300
// Also sent to self (DICT master) when index table creation ready.
 
5301
/* ---------------------------------------------------------------- */
 
5302
void Dbdict::execCREATE_TABLE_CONF(Signal* signal) 
 
5303
{
 
5304
  jamEntry();
 
5305
  ndbrequire(signal->getNoOfSections() == 0);
 
5306
 
 
5307
  CreateTableConf * const conf = (CreateTableConf *)signal->getDataPtr();
 
5308
  // assume part of create index operation
 
5309
  OpCreateIndexPtr opPtr;
 
5310
  c_opCreateIndex.find(opPtr, conf->senderData);
 
5311
  ndbrequire(! opPtr.isNull());
 
5312
  opPtr.p->m_request.setIndexId(conf->tableId);
 
5313
  opPtr.p->m_request.setIndexVersion(conf->tableVersion);
 
5314
  createIndex_fromCreateTable(signal, opPtr);
 
5315
}//execCREATE_TABLE_CONF()
 
5316
 
 
5317
void Dbdict::execCREATE_TABLE_REF(Signal* signal) 
 
5318
{
 
5319
  jamEntry();
 
5320
 
 
5321
  CreateTableRef * const ref = (CreateTableRef *)signal->getDataPtr();
 
5322
  // assume part of create index operation
 
5323
  OpCreateIndexPtr opPtr;
 
5324
  c_opCreateIndex.find(opPtr, ref->senderData);
 
5325
  ndbrequire(! opPtr.isNull());
 
5326
  opPtr.p->setError(ref);
 
5327
  createIndex_fromCreateTable(signal, opPtr);
 
5328
}//execCREATE_TABLE_REF()
 
5329
 
 
5330
/* ---------------------------------------------------------------- */
 
5331
// New global checkpoint created.
 
5332
/* ---------------------------------------------------------------- */
 
5333
void Dbdict::execWAIT_GCP_CONF(Signal* signal) 
 
5334
{
 
5335
#if 0
 
5336
  TableRecordPtr tablePtr;
 
5337
  jamEntry();
 
5338
  WaitGCPConf* const conf = (WaitGCPConf*)&signal->theData[0];
 
5339
  c_tableRecordPool.getPtr(tablePtr, c_connRecord.connTableId);
 
5340
  tablePtr.p->gciTableCreated = conf->gcp;
 
5341
  sendUpdateSchemaState(signal,
 
5342
                        tablePtr.i,
 
5343
                        SchemaFile::TABLE_ADD_COMMITTED,
 
5344
                        c_connRecord.noOfPagesForTable,
 
5345
                        conf->gcp);
 
5346
#endif
 
5347
}//execWAIT_GCP_CONF()
 
5348
 
 
5349
/* ---------------------------------------------------------------- */
 
5350
// Refused new global checkpoint.
 
5351
/* ---------------------------------------------------------------- */
 
5352
void Dbdict::execWAIT_GCP_REF(Signal* signal) 
 
5353
{
 
5354
  jamEntry();
 
5355
  WaitGCPRef* const ref = (WaitGCPRef*)&signal->theData[0];
 
5356
/* ---------------------------------------------------------------- */
 
5357
// Error Handling code needed
 
5358
/* ---------------------------------------------------------------- */
 
5359
  char buf[32];
 
5360
  BaseString::snprintf(buf, sizeof(buf), "WAIT_GCP_REF ErrorCode=%d",
 
5361
                       ref->errorCode);
 
5362
  progError(__LINE__, NDBD_EXIT_NDBREQUIRE, buf);
 
5363
}//execWAIT_GCP_REF()
 
5364
 
 
5365
 
 
5366
/* **************************************************************** */
 
5367
/* ---------------------------------------------------------------- */
 
5368
/* MODULE:          DROP TABLE                 -------------------- */
 
5369
/* ---------------------------------------------------------------- */
 
5370
/*                                                                  */
 
5371
/* This module contains the code used to drop a table.              */
 
5372
/* ---------------------------------------------------------------- */
 
5373
/* **************************************************************** */
 
5374
void
 
5375
Dbdict::execDROP_TABLE_REQ(Signal* signal){
 
5376
  jamEntry();
 
5377
  DropTableReq* req = (DropTableReq*)signal->getDataPtr();
 
5378
 
 
5379
  TableRecordPtr tablePtr;
 
5380
  c_tableRecordPool.getPtr(tablePtr, req->tableId, false);
 
5381
  if(tablePtr.isNull()){
 
5382
    jam();
 
5383
    dropTableRef(signal, req, DropTableRef::NoSuchTable);
 
5384
    return;
 
5385
  }
 
5386
 
 
5387
  if(getOwnNodeId() != c_masterNodeId){
 
5388
    jam();
 
5389
    dropTableRef(signal, req, DropTableRef::NotMaster);
 
5390
    return;
 
5391
  }
 
5392
 
 
5393
  if(c_blockState == BS_NODE_RESTART){
 
5394
    jam();
 
5395
    dropTableRef(signal, req, DropTableRef::BusyWithNR);
 
5396
    return;
 
5397
  }
 
5398
 
 
5399
  if(c_blockState != BS_IDLE){
 
5400
    jam();
 
5401
    dropTableRef(signal, req, DropTableRef::Busy);
 
5402
    return;
 
5403
  }
 
5404
  
 
5405
  const TableRecord::TabState tabState = tablePtr.p->tabState;
 
5406
  bool ok = false;
 
5407
  switch(tabState){
 
5408
  case TableRecord::NOT_DEFINED:
 
5409
  case TableRecord::REORG_TABLE_PREPARED:
 
5410
  case TableRecord::DEFINING:
 
5411
  case TableRecord::CHECKED:
 
5412
    jam();
 
5413
    dropTableRef(signal, req, DropTableRef::NoSuchTable);
 
5414
    return;
 
5415
  case TableRecord::DEFINED:
 
5416
    ok = true;
 
5417
    jam();
 
5418
    break;
 
5419
  case TableRecord::PREPARE_DROPPING:
 
5420
  case TableRecord::DROPPING:
 
5421
    jam();
 
5422
    dropTableRef(signal, req, DropTableRef::DropInProgress);
 
5423
    return;
 
5424
  case TableRecord::BACKUP_ONGOING:
 
5425
    jam();
 
5426
    dropTableRef(signal, req, DropTableRef::BackupInProgress);
 
5427
    return;
 
5428
  }
 
5429
  ndbrequire(ok);
 
5430
 
 
5431
  if(tablePtr.p->tableVersion != req->tableVersion){
 
5432
    jam();
 
5433
    dropTableRef(signal, req, DropTableRef::InvalidTableVersion);
 
5434
    return;
 
5435
  }
 
5436
 
 
5437
  /**
 
5438
   * Seems ok
 
5439
   */
 
5440
  DropTableRecordPtr dropTabPtr;
 
5441
  c_opDropTable.seize(dropTabPtr);
 
5442
  
 
5443
  if(dropTabPtr.isNull()){
 
5444
    jam();
 
5445
    dropTableRef(signal, req, DropTableRef::NoDropTableRecordAvailable);
 
5446
    return;
 
5447
  }
 
5448
 
 
5449
  c_blockState = BS_BUSY;
 
5450
  
 
5451
  dropTabPtr.p->key = ++c_opRecordSequence;
 
5452
  c_opDropTable.add(dropTabPtr);
 
5453
 
 
5454
  dropTabPtr.p->m_request = * req;
 
5455
  dropTabPtr.p->m_errorCode = 0;
 
5456
  dropTabPtr.p->m_requestType = DropTabReq::OnlineDropTab;
 
5457
  dropTabPtr.p->m_coordinatorRef = reference();
 
5458
  dropTabPtr.p->m_coordinatorData.m_gsn = GSN_PREP_DROP_TAB_REQ;
 
5459
  dropTabPtr.p->m_coordinatorData.m_block = 0;
 
5460
  
 
5461
  Mutex mutex(signal, c_mutexMgr, dropTabPtr.p->m_define_backup_mutex);
 
5462
  Callback c = { safe_cast(&Dbdict::dropTable_backup_mutex_locked),
 
5463
                 dropTabPtr.p->key};
 
5464
  
 
5465
  ndbrequire(mutex.lock(c));
 
5466
 
 
5467
}
 
5468
 
 
5469
void
 
5470
Dbdict::dropTable_backup_mutex_locked(Signal* signal, 
 
5471
                                      Uint32 callbackData,
 
5472
                                      Uint32 retValue){
 
5473
  jamEntry();
 
5474
  
 
5475
  ndbrequire(retValue == 0);
 
5476
  
 
5477
  DropTableRecordPtr dropTabPtr;
 
5478
  ndbrequire(c_opDropTable.find(dropTabPtr, callbackData));
 
5479
  
 
5480
  TableRecordPtr tablePtr;
 
5481
  c_tableRecordPool.getPtr(tablePtr, dropTabPtr.p->m_request.tableId, true);
 
5482
  
 
5483
  Mutex mutex(signal, c_mutexMgr, dropTabPtr.p->m_define_backup_mutex);
 
5484
  mutex.unlock(); // ignore response
 
5485
  
 
5486
  if(tablePtr.p->tabState == TableRecord::BACKUP_ONGOING)
 
5487
  {
 
5488
    jam();
 
5489
    dropTableRef(signal, &dropTabPtr.p->m_request,
 
5490
                 DropTableRef::BackupInProgress);
 
5491
    
 
5492
    c_blockState = BS_IDLE;
 
5493
    c_opDropTable.release(dropTabPtr);
 
5494
  }
 
5495
  else
 
5496
  {
 
5497
    jam();
 
5498
    tablePtr.p->tabState = TableRecord::PREPARE_DROPPING;
 
5499
    prepDropTab_nextStep(signal, dropTabPtr);
 
5500
  }
 
5501
}
 
5502
 
 
5503
void
 
5504
Dbdict::dropTableRef(Signal * signal, 
 
5505
                     DropTableReq * req, DropTableRef::ErrorCode errCode){
 
5506
 
 
5507
  Uint32 tableId = req->tableId;
 
5508
  Uint32 tabVersion = req->tableVersion;
 
5509
  Uint32 senderData = req->senderData;
 
5510
  Uint32 senderRef = req->senderRef;
 
5511
  
 
5512
  DropTableRef * ref = (DropTableRef*)signal->getDataPtrSend();
 
5513
  ref->tableId = tableId;
 
5514
  ref->tableVersion = tabVersion;
 
5515
  ref->senderData = senderData;
 
5516
  ref->senderRef = reference();
 
5517
  ref->errorCode = errCode;
 
5518
  ref->masterNodeId = c_masterNodeId;
 
5519
  sendSignal(senderRef, GSN_DROP_TABLE_REF, signal, 
 
5520
             DropTableRef::SignalLength, JBB);
 
5521
}
 
5522
 
 
5523
void
 
5524
Dbdict::prepDropTab_nextStep(Signal* signal, DropTableRecordPtr dropTabPtr){
 
5525
  
 
5526
  /**
 
5527
   * No errors currently allowed
 
5528
   */
 
5529
  ndbrequire(dropTabPtr.p->m_errorCode == 0);
 
5530
 
 
5531
  Uint32 block = 0;
 
5532
  switch(dropTabPtr.p->m_coordinatorData.m_block){
 
5533
  case 0:
 
5534
    jam();
 
5535
    block = dropTabPtr.p->m_coordinatorData.m_block = DBDICT;
 
5536
    break;
 
5537
  case DBDICT:
 
5538
    jam();
 
5539
    block = dropTabPtr.p->m_coordinatorData.m_block = DBLQH;
 
5540
    break;
 
5541
  case DBLQH:
 
5542
    jam();
 
5543
    block = dropTabPtr.p->m_coordinatorData.m_block = DBTC;
 
5544
    break;
 
5545
  case DBTC:
 
5546
    jam();
 
5547
    block = dropTabPtr.p->m_coordinatorData.m_block = DBDIH;
 
5548
    break;
 
5549
  case DBDIH:
 
5550
    jam();
 
5551
    prepDropTab_complete(signal, dropTabPtr);
 
5552
    return;
 
5553
  default:
 
5554
    ndbrequire(false);
 
5555
  }
 
5556
 
 
5557
  PrepDropTabReq * prep = (PrepDropTabReq*)signal->getDataPtrSend();
 
5558
  prep->senderRef = reference();
 
5559
  prep->senderData = dropTabPtr.p->key;
 
5560
  prep->tableId = dropTabPtr.p->m_request.tableId;
 
5561
  prep->requestType = dropTabPtr.p->m_requestType;
 
5562
  
 
5563
  dropTabPtr.p->m_coordinatorData.m_signalCounter = c_aliveNodes;
 
5564
  NodeReceiverGroup rg(block, c_aliveNodes);
 
5565
  sendSignal(rg, GSN_PREP_DROP_TAB_REQ, signal, 
 
5566
             PrepDropTabReq::SignalLength, JBB);
 
5567
  
 
5568
#if 0  
 
5569
  for (Uint32 i = 1; i < MAX_NDB_NODES; i++){
 
5570
    if(c_aliveNodes.get(i)){
 
5571
      jam();
 
5572
      BlockReference ref = numberToRef(block, i);
 
5573
      
 
5574
      dropTabPtr.p->m_coordinatorData.m_signalCounter.setWaitingFor(i);
 
5575
    }
 
5576
  }
 
5577
#endif
 
5578
}
 
5579
 
 
5580
void
 
5581
Dbdict::execPREP_DROP_TAB_CONF(Signal * signal){
 
5582
  jamEntry();
 
5583
 
 
5584
  PrepDropTabConf * prep = (PrepDropTabConf*)signal->getDataPtr();
 
5585
 
 
5586
  DropTableRecordPtr dropTabPtr;  
 
5587
  ndbrequire(c_opDropTable.find(dropTabPtr, prep->senderData));
 
5588
  
 
5589
  ndbrequire(dropTabPtr.p->m_coordinatorRef == reference());
 
5590
  ndbrequire(dropTabPtr.p->m_request.tableId == prep->tableId);
 
5591
  ndbrequire(dropTabPtr.p->m_coordinatorData.m_gsn == GSN_PREP_DROP_TAB_REQ);
 
5592
  
 
5593
  Uint32 nodeId = refToNode(prep->senderRef);
 
5594
  dropTabPtr.p->m_coordinatorData.m_signalCounter.clearWaitingFor(nodeId);
 
5595
  
 
5596
  if(!dropTabPtr.p->m_coordinatorData.m_signalCounter.done()){
 
5597
    jam();
 
5598
    return;
 
5599
  }
 
5600
  prepDropTab_nextStep(signal, dropTabPtr);
 
5601
}
 
5602
 
 
5603
void
 
5604
Dbdict::execPREP_DROP_TAB_REF(Signal* signal){
 
5605
  jamEntry();
 
5606
 
 
5607
  PrepDropTabRef * prep = (PrepDropTabRef*)signal->getDataPtr();
 
5608
 
 
5609
  DropTableRecordPtr dropTabPtr;  
 
5610
  ndbrequire(c_opDropTable.find(dropTabPtr, prep->senderData));
 
5611
  
 
5612
  ndbrequire(dropTabPtr.p->m_coordinatorRef == reference());
 
5613
  ndbrequire(dropTabPtr.p->m_request.tableId == prep->tableId);
 
5614
  ndbrequire(dropTabPtr.p->m_coordinatorData.m_gsn == GSN_PREP_DROP_TAB_REQ);
 
5615
  
 
5616
  Uint32 nodeId = refToNode(prep->senderRef);
 
5617
  dropTabPtr.p->m_coordinatorData.m_signalCounter.clearWaitingFor(nodeId);
 
5618
  
 
5619
  Uint32 block = refToBlock(prep->senderRef);
 
5620
  if((prep->errorCode == PrepDropTabRef::NoSuchTable && block == DBLQH) ||
 
5621
     (prep->errorCode == PrepDropTabRef::NF_FakeErrorREF)){
 
5622
    jam();
 
5623
    /**
 
5624
     * Ignore errors:
 
5625
     * 1) no such table and LQH, it might not exists in different LQH's
 
5626
     * 2) node failure...
 
5627
     */
 
5628
  } else {
 
5629
    dropTabPtr.p->setErrorCode((Uint32)prep->errorCode);
 
5630
  }
 
5631
  
 
5632
  if(!dropTabPtr.p->m_coordinatorData.m_signalCounter.done()){
 
5633
    jam();
 
5634
    return;
 
5635
  }
 
5636
  prepDropTab_nextStep(signal, dropTabPtr);
 
5637
}
 
5638
 
 
5639
void
 
5640
Dbdict::prepDropTab_complete(Signal* signal, DropTableRecordPtr dropTabPtr){
 
5641
  jam();
 
5642
 
 
5643
  dropTabPtr.p->m_coordinatorData.m_gsn = GSN_DROP_TAB_REQ;
 
5644
  dropTabPtr.p->m_coordinatorData.m_block = DBDICT;
 
5645
  
 
5646
  DropTabReq * req = (DropTabReq*)signal->getDataPtrSend();
 
5647
  req->senderRef = reference();
 
5648
  req->senderData = dropTabPtr.p->key;
 
5649
  req->tableId = dropTabPtr.p->m_request.tableId;
 
5650
  req->requestType = dropTabPtr.p->m_requestType;
 
5651
 
 
5652
  dropTabPtr.p->m_coordinatorData.m_signalCounter = c_aliveNodes;
 
5653
  NodeReceiverGroup rg(DBDICT, c_aliveNodes);
 
5654
  sendSignal(rg, GSN_DROP_TAB_REQ, signal, 
 
5655
             DropTabReq::SignalLength, JBB);
 
5656
}
 
5657
 
 
5658
void
 
5659
Dbdict::execDROP_TAB_REF(Signal* signal){
 
5660
  jamEntry();
 
5661
 
 
5662
  DropTabRef * const req = (DropTabRef*)signal->getDataPtr();
 
5663
 
 
5664
  Uint32 block = refToBlock(req->senderRef);
 
5665
  ndbrequire(req->errorCode == DropTabRef::NF_FakeErrorREF ||
 
5666
             (req->errorCode == DropTabRef::NoSuchTable &&
 
5667
              (block == DBTUP || block == DBACC || block == DBLQH)));
 
5668
  
 
5669
  if(block != DBDICT){
 
5670
    jam();
 
5671
    ndbrequire(refToNode(req->senderRef) == getOwnNodeId());
 
5672
    dropTab_localDROP_TAB_CONF(signal);
 
5673
    return;
 
5674
  }
 
5675
  ndbrequire(false);
 
5676
}
 
5677
 
 
5678
void
 
5679
Dbdict::execDROP_TAB_CONF(Signal* signal){
 
5680
  jamEntry();
 
5681
 
 
5682
  DropTabConf * const req = (DropTabConf*)signal->getDataPtr();
 
5683
 
 
5684
  if(refToBlock(req->senderRef) != DBDICT){
 
5685
    jam();
 
5686
    ndbrequire(refToNode(req->senderRef) == getOwnNodeId());
 
5687
    dropTab_localDROP_TAB_CONF(signal);
 
5688
    return;
 
5689
  }
 
5690
 
 
5691
  DropTableRecordPtr dropTabPtr;  
 
5692
  ndbrequire(c_opDropTable.find(dropTabPtr, req->senderData));
 
5693
  
 
5694
  ndbrequire(dropTabPtr.p->m_coordinatorRef == reference());
 
5695
  ndbrequire(dropTabPtr.p->m_request.tableId == req->tableId);
 
5696
  ndbrequire(dropTabPtr.p->m_coordinatorData.m_gsn == GSN_DROP_TAB_REQ);
 
5697
 
 
5698
  Uint32 nodeId = refToNode(req->senderRef);
 
5699
  dropTabPtr.p->m_coordinatorData.m_signalCounter.clearWaitingFor(nodeId);
 
5700
  
 
5701
  if(!dropTabPtr.p->m_coordinatorData.m_signalCounter.done()){
 
5702
    jam();
 
5703
    return;
 
5704
  }
 
5705
  
 
5706
  DropTableConf* conf = (DropTableConf*)signal->getDataPtrSend();
 
5707
  conf->senderRef = reference();
 
5708
  conf->senderData = dropTabPtr.p->m_request.senderData;
 
5709
  conf->tableId = dropTabPtr.p->m_request.tableId;
 
5710
  conf->tableVersion = dropTabPtr.p->m_request.tableVersion;
 
5711
  
 
5712
  Uint32 ref = dropTabPtr.p->m_request.senderRef;
 
5713
  sendSignal(ref, GSN_DROP_TABLE_CONF, signal, 
 
5714
             DropTableConf::SignalLength, JBB);
 
5715
 
 
5716
  c_opDropTable.release(dropTabPtr);
 
5717
  c_blockState = BS_IDLE;
 
5718
}
 
5719
 
 
5720
/**
 
5721
 * DROP TABLE PARTICIPANT CODE
 
5722
 */
 
5723
void
 
5724
Dbdict::execPREP_DROP_TAB_REQ(Signal* signal){
 
5725
  jamEntry();
 
5726
  PrepDropTabReq * prep = (PrepDropTabReq*)signal->getDataPtrSend();  
 
5727
 
 
5728
  DropTableRecordPtr dropTabPtr;  
 
5729
  if(prep->senderRef == reference()){
 
5730
    jam();
 
5731
    ndbrequire(c_opDropTable.find(dropTabPtr, prep->senderData));
 
5732
    ndbrequire(dropTabPtr.p->m_requestType == prep->requestType);
 
5733
  } else {
 
5734
    jam();
 
5735
    c_opDropTable.seize(dropTabPtr);
 
5736
    if(!dropTabPtr.isNull()){
 
5737
      dropTabPtr.p->key = prep->senderData;
 
5738
      c_opDropTable.add(dropTabPtr);
 
5739
    }
 
5740
  }
 
5741
  
 
5742
  ndbrequire(!dropTabPtr.isNull());
 
5743
 
 
5744
  dropTabPtr.p->m_errorCode = 0;
 
5745
  dropTabPtr.p->m_request.tableId = prep->tableId;
 
5746
  dropTabPtr.p->m_requestType = prep->requestType;
 
5747
  dropTabPtr.p->m_coordinatorRef = prep->senderRef;
 
5748
  dropTabPtr.p->m_participantData.m_gsn = GSN_PREP_DROP_TAB_REQ;
 
5749
 
 
5750
  TableRecordPtr tablePtr;
 
5751
  c_tableRecordPool.getPtr(tablePtr, prep->tableId);
 
5752
  tablePtr.p->tabState = TableRecord::PREPARE_DROPPING;
 
5753
  
 
5754
  /**
 
5755
   * Modify schema
 
5756
   */
 
5757
  XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
 
5758
  SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, tablePtr.i);
 
5759
  SchemaFile::TableState tabState = 
 
5760
    (SchemaFile::TableState)tableEntry->m_tableState;
 
5761
  ndbrequire(tabState == SchemaFile::TABLE_ADD_COMMITTED ||
 
5762
             tabState == SchemaFile::ALTER_TABLE_COMMITTED);
 
5763
  tableEntry->m_tableState   = SchemaFile::DROP_TABLE_STARTED;
 
5764
  computeChecksum(xsf, tablePtr.i / NDB_SF_PAGE_ENTRIES);
 
5765
  
 
5766
  ndbrequire(c_writeSchemaRecord.inUse == false);
 
5767
  c_writeSchemaRecord.inUse = true;
 
5768
  
 
5769
  c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
 
5770
  c_writeSchemaRecord.newFile = false;
 
5771
  c_writeSchemaRecord.firstPage = tablePtr.i / NDB_SF_PAGE_ENTRIES;
 
5772
  c_writeSchemaRecord.noOfPages = 1;
 
5773
  c_writeSchemaRecord.m_callback.m_callbackData = dropTabPtr.p->key;
 
5774
  c_writeSchemaRecord.m_callback.m_callbackFunction = 
 
5775
    safe_cast(&Dbdict::prepDropTab_writeSchemaConf);
 
5776
  startWriteSchemaFile(signal);
 
5777
}
 
5778
 
 
5779
void
 
5780
Dbdict::prepDropTab_writeSchemaConf(Signal* signal, 
 
5781
                                    Uint32 dropTabPtrI,
 
5782
                                    Uint32 returnCode){
 
5783
  jam();
 
5784
 
 
5785
  DropTableRecordPtr dropTabPtr;  
 
5786
  ndbrequire(c_opDropTable.find(dropTabPtr, dropTabPtrI));
 
5787
 
 
5788
  ndbrequire(dropTabPtr.p->m_participantData.m_gsn == GSN_PREP_DROP_TAB_REQ);
 
5789
  
 
5790
  /**
 
5791
   * There probably should be node fail handlign here
 
5792
   *
 
5793
   * To check that coordinator hasn't died
 
5794
   */
 
5795
  
 
5796
  PrepDropTabConf * prep = (PrepDropTabConf*)signal->getDataPtr();  
 
5797
  prep->senderRef = reference();
 
5798
  prep->senderData = dropTabPtrI;
 
5799
  prep->tableId = dropTabPtr.p->m_request.tableId;
 
5800
  
 
5801
  dropTabPtr.p->m_participantData.m_gsn = GSN_PREP_DROP_TAB_CONF;
 
5802
  sendSignal(dropTabPtr.p->m_coordinatorRef, GSN_PREP_DROP_TAB_CONF, signal, 
 
5803
             PrepDropTabConf::SignalLength, JBB);
 
5804
}
 
5805
 
 
5806
void
 
5807
Dbdict::execDROP_TAB_REQ(Signal* signal){
 
5808
  jamEntry();
 
5809
  DropTabReq * req = (DropTabReq*)signal->getDataPtrSend();  
 
5810
 
 
5811
  DropTableRecordPtr dropTabPtr;  
 
5812
  ndbrequire(c_opDropTable.find(dropTabPtr, req->senderData));
 
5813
 
 
5814
  ndbrequire(dropTabPtr.p->m_participantData.m_gsn == GSN_PREP_DROP_TAB_CONF);
 
5815
  dropTabPtr.p->m_participantData.m_gsn = GSN_DROP_TAB_REQ;
 
5816
 
 
5817
  ndbrequire(dropTabPtr.p->m_requestType == req->requestType);
 
5818
 
 
5819
  TableRecordPtr tablePtr;
 
5820
  c_tableRecordPool.getPtr(tablePtr, dropTabPtr.p->m_request.tableId);
 
5821
  tablePtr.p->tabState = TableRecord::DROPPING;
 
5822
 
 
5823
  dropTabPtr.p->m_participantData.m_block = 0;
 
5824
  dropTabPtr.p->m_participantData.m_callback.m_callbackData = dropTabPtr.p->key;
 
5825
  dropTabPtr.p->m_participantData.m_callback.m_callbackFunction = 
 
5826
    safe_cast(&Dbdict::dropTab_complete);
 
5827
  dropTab_nextStep(signal, dropTabPtr);  
 
5828
}
 
5829
 
 
5830
#include <DebuggerNames.hpp>
 
5831
 
 
5832
void
 
5833
Dbdict::dropTab_nextStep(Signal* signal, DropTableRecordPtr dropTabPtr){
 
5834
 
 
5835
  /**
 
5836
   * No errors currently allowed
 
5837
   */
 
5838
  ndbrequire(dropTabPtr.p->m_errorCode == 0);
 
5839
 
 
5840
  TableRecordPtr tablePtr;
 
5841
  c_tableRecordPool.getPtr(tablePtr, dropTabPtr.p->m_request.tableId);
 
5842
 
 
5843
  Uint32 block = 0;
 
5844
  switch(dropTabPtr.p->m_participantData.m_block){
 
5845
  case 0:
 
5846
    jam();
 
5847
    block = DBTC;
 
5848
    break;
 
5849
  case DBTC:
 
5850
    jam();
 
5851
    if (tablePtr.p->isTable() || tablePtr.p->isHashIndex())
 
5852
      block = DBACC;
 
5853
    if (tablePtr.p->isOrderedIndex())
 
5854
      block = DBTUP;
 
5855
    break;
 
5856
  case DBACC:
 
5857
    jam();
 
5858
    block = DBTUP;
 
5859
    break;
 
5860
  case DBTUP:
 
5861
    jam();
 
5862
    if (tablePtr.p->isTable() || tablePtr.p->isHashIndex())
 
5863
      block = DBLQH;
 
5864
    if (tablePtr.p->isOrderedIndex())
 
5865
      block = DBTUX;
 
5866
    break;
 
5867
  case DBTUX:
 
5868
    jam();
 
5869
    block = DBLQH;
 
5870
    break;
 
5871
  case DBLQH:
 
5872
    jam();
 
5873
    block = DBDIH;
 
5874
    break;
 
5875
  case DBDIH:
 
5876
    jam();
 
5877
    execute(signal, dropTabPtr.p->m_participantData.m_callback, 0);
 
5878
    return;
 
5879
  }
 
5880
  ndbrequire(block != 0);
 
5881
  dropTabPtr.p->m_participantData.m_block = block;
 
5882
 
 
5883
  DropTabReq * req = (DropTabReq*)signal->getDataPtrSend();
 
5884
  req->senderRef = reference();
 
5885
  req->senderData = dropTabPtr.p->key;
 
5886
  req->tableId = dropTabPtr.p->m_request.tableId;
 
5887
  req->requestType = dropTabPtr.p->m_requestType;
 
5888
  
 
5889
  const Uint32 nodeId = getOwnNodeId();
 
5890
  dropTabPtr.p->m_participantData.m_signalCounter.clearWaitingFor();
 
5891
  dropTabPtr.p->m_participantData.m_signalCounter.setWaitingFor(nodeId);
 
5892
  BlockReference ref = numberToRef(block, 0);
 
5893
  sendSignal(ref, GSN_DROP_TAB_REQ, signal, DropTabReq::SignalLength, JBB);
 
5894
}
 
5895
 
 
5896
void
 
5897
Dbdict::dropTab_localDROP_TAB_CONF(Signal* signal){
 
5898
  jamEntry();
 
5899
  
 
5900
  DropTabConf * conf = (DropTabConf*)signal->getDataPtr();
 
5901
 
 
5902
  DropTableRecordPtr dropTabPtr;  
 
5903
  ndbrequire(c_opDropTable.find(dropTabPtr, conf->senderData));
 
5904
  
 
5905
  ndbrequire(dropTabPtr.p->m_request.tableId == conf->tableId);
 
5906
  ndbrequire(dropTabPtr.p->m_participantData.m_gsn == GSN_DROP_TAB_REQ);
 
5907
  
 
5908
  Uint32 nodeId = refToNode(conf->senderRef);
 
5909
  dropTabPtr.p->m_participantData.m_signalCounter.clearWaitingFor(nodeId);
 
5910
  
 
5911
  if(!dropTabPtr.p->m_participantData.m_signalCounter.done()){
 
5912
    jam();
 
5913
    ndbrequire(false);
 
5914
    return;
 
5915
  }
 
5916
  dropTab_nextStep(signal, dropTabPtr);
 
5917
}
 
5918
 
 
5919
void
 
5920
Dbdict::dropTab_complete(Signal* signal, 
 
5921
                         Uint32 dropTabPtrI,
 
5922
                         Uint32 returnCode){
 
5923
  jam();
 
5924
 
 
5925
  DropTableRecordPtr dropTabPtr;  
 
5926
  ndbrequire(c_opDropTable.find(dropTabPtr, dropTabPtrI));
 
5927
  
 
5928
  Uint32 tableId = dropTabPtr.p->m_request.tableId;
 
5929
  
 
5930
  /**
 
5931
   * Write to schema file
 
5932
   */
 
5933
  XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
 
5934
  SchemaFile::TableEntry * tableEntry = getTableEntry(xsf, tableId);
 
5935
  SchemaFile::TableState tabState = 
 
5936
    (SchemaFile::TableState)tableEntry->m_tableState;
 
5937
  ndbrequire(tabState == SchemaFile::DROP_TABLE_STARTED);
 
5938
  tableEntry->m_tableState = SchemaFile::DROP_TABLE_COMMITTED;
 
5939
  computeChecksum(xsf, tableId / NDB_SF_PAGE_ENTRIES);
 
5940
  
 
5941
  ndbrequire(c_writeSchemaRecord.inUse == false);
 
5942
  c_writeSchemaRecord.inUse = true;
 
5943
 
 
5944
  c_writeSchemaRecord.pageId = c_schemaRecord.schemaPage;
 
5945
  c_writeSchemaRecord.firstPage = tableId / NDB_SF_PAGE_ENTRIES;
 
5946
  c_writeSchemaRecord.noOfPages = 1;
 
5947
  c_writeSchemaRecord.m_callback.m_callbackData = dropTabPtr.p->key;
 
5948
  c_writeSchemaRecord.m_callback.m_callbackFunction = 
 
5949
    safe_cast(&Dbdict::dropTab_writeSchemaConf);
 
5950
  startWriteSchemaFile(signal);
 
5951
}
 
5952
 
 
5953
void
 
5954
Dbdict::dropTab_writeSchemaConf(Signal* signal, 
 
5955
                                Uint32 dropTabPtrI,
 
5956
                                Uint32 returnCode){
 
5957
  jam();
 
5958
 
 
5959
  DropTableRecordPtr dropTabPtr;  
 
5960
  ndbrequire(c_opDropTable.find(dropTabPtr, dropTabPtrI));
 
5961
 
 
5962
  ndbrequire(dropTabPtr.p->m_participantData.m_gsn == GSN_DROP_TAB_REQ);
 
5963
 
 
5964
  dropTabPtr.p->m_participantData.m_gsn = GSN_DROP_TAB_CONF;
 
5965
 
 
5966
  releaseTableObject(dropTabPtr.p->m_request.tableId);
 
5967
 
 
5968
  DropTabConf * conf = (DropTabConf*)signal->getDataPtr();  
 
5969
  conf->senderRef = reference();
 
5970
  conf->senderData = dropTabPtrI;
 
5971
  conf->tableId = dropTabPtr.p->m_request.tableId;
 
5972
  
 
5973
  dropTabPtr.p->m_participantData.m_gsn = GSN_DROP_TAB_CONF;
 
5974
  sendSignal(dropTabPtr.p->m_coordinatorRef, GSN_DROP_TAB_CONF, signal, 
 
5975
             DropTabConf::SignalLength, JBB);
 
5976
  
 
5977
  if(dropTabPtr.p->m_coordinatorRef != reference()){
 
5978
    c_opDropTable.release(dropTabPtr);
 
5979
  }
 
5980
}
 
5981
 
 
5982
void Dbdict::releaseTableObject(Uint32 tableId, bool removeFromHash) 
 
5983
{
 
5984
  TableRecordPtr tablePtr;
 
5985
  AttributeRecordPtr attrPtr;
 
5986
  c_tableRecordPool.getPtr(tablePtr, tableId);
 
5987
  if (removeFromHash)
 
5988
  {
 
5989
#ifdef VM_TRACE
 
5990
    TableRecordPtr tmp;
 
5991
    ndbrequire(c_tableRecordHash.find(tmp, * tablePtr.p));
 
5992
#endif
 
5993
    c_tableRecordHash.remove(tablePtr);
 
5994
  }
 
5995
  tablePtr.p->tabState = TableRecord::NOT_DEFINED;
 
5996
 
 
5997
  Uint32 nextAttrRecord = tablePtr.p->firstAttribute;
 
5998
  while (nextAttrRecord != RNIL) {
 
5999
    jam();
 
6000
/* ---------------------------------------------------------------- */
 
6001
// Release all attribute records
 
6002
/* ---------------------------------------------------------------- */
 
6003
    c_attributeRecordPool.getPtr(attrPtr, nextAttrRecord);
 
6004
    nextAttrRecord = attrPtr.p->nextAttrInTable;
 
6005
    c_attributeRecordPool.release(attrPtr);
 
6006
  }//if
 
6007
#ifdef HAVE_TABLE_REORG
 
6008
  Uint32 secondTableId = tablePtr.p->secondTable;
 
6009
  initialiseTableRecord(tablePtr);
 
6010
  c_tableRecordPool.getPtr(tablePtr, secondTableId);
 
6011
  initialiseTableRecord(tablePtr);
 
6012
#endif
 
6013
  return; 
 
6014
}//releaseTableObject()
 
6015
 
 
6016
/**
 
6017
 * DICT receives these on index create and drop.
 
6018
 */
 
6019
void Dbdict::execDROP_TABLE_CONF(Signal* signal) 
 
6020
{
 
6021
  jamEntry();
 
6022
  ndbrequire(signal->getNoOfSections() == 0);
 
6023
 
 
6024
  DropTableConf * const conf = (DropTableConf *)signal->getDataPtr();
 
6025
  // assume part of drop index operation
 
6026
  OpDropIndexPtr opPtr;
 
6027
  c_opDropIndex.find(opPtr, conf->senderData);
 
6028
  ndbrequire(! opPtr.isNull());
 
6029
  ndbrequire(opPtr.p->m_request.getIndexId() == conf->tableId);
 
6030
  ndbrequire(opPtr.p->m_request.getIndexVersion() == conf->tableVersion);
 
6031
  dropIndex_fromDropTable(signal, opPtr);
 
6032
}
 
6033
 
 
6034
void Dbdict::execDROP_TABLE_REF(Signal* signal) 
 
6035
{
 
6036
  jamEntry();
 
6037
 
 
6038
  DropTableRef * const ref = (DropTableRef *)signal->getDataPtr();
 
6039
  // assume part of drop index operation
 
6040
  OpDropIndexPtr opPtr;
 
6041
  c_opDropIndex.find(opPtr, ref->senderData);
 
6042
  ndbrequire(! opPtr.isNull());
 
6043
  opPtr.p->setError(ref);
 
6044
  opPtr.p->m_errorLine = __LINE__;
 
6045
  dropIndex_fromDropTable(signal, opPtr);
 
6046
}
 
6047
 
 
6048
/* **************************************************************** */
 
6049
/* ---------------------------------------------------------------- */
 
6050
/* MODULE:          EXTERNAL INTERFACE TO DATA -------------------- */
 
6051
/* ---------------------------------------------------------------- */
 
6052
/*                                                                  */
 
6053
/* This module contains the code that is used by other modules to.  */
 
6054
/* access the data within DBDICT.                                   */
 
6055
/* ---------------------------------------------------------------- */
 
6056
/* **************************************************************** */
 
6057
 
 
6058
void Dbdict::execGET_TABLEDID_REQ(Signal * signal) 
 
6059
{
 
6060
  jamEntry();
 
6061
  ndbrequire(signal->getNoOfSections() == 1);  
 
6062
  GetTableIdReq const * req = (GetTableIdReq *)signal->getDataPtr();
 
6063
  Uint32 senderData = req->senderData;
 
6064
  Uint32 senderRef = req->senderRef;
 
6065
  Uint32 len = req->len;
 
6066
 
 
6067
  if(len>MAX_TAB_NAME_SIZE)
 
6068
  {
 
6069
    jam();
 
6070
    sendGET_TABLEID_REF((Signal*)signal, 
 
6071
                        (GetTableIdReq *)req, 
 
6072
                        GetTableIdRef::TableNameTooLong);
 
6073
    return;
 
6074
  }
 
6075
 
 
6076
  char tableName[MAX_TAB_NAME_SIZE];
 
6077
  TableRecord keyRecord;
 
6078
  SegmentedSectionPtr ssPtr;
 
6079
  signal->getSection(ssPtr,GetTableIdReq::TABLE_NAME);
 
6080
  copy((Uint32*)tableName, ssPtr);
 
6081
  strcpy(keyRecord.tableName, tableName);
 
6082
  releaseSections(signal);
 
6083
 
 
6084
  if(len > sizeof(keyRecord.tableName)){
 
6085
    jam();
 
6086
    sendGET_TABLEID_REF((Signal*)signal, 
 
6087
                        (GetTableIdReq *)req, 
 
6088
                        GetTableIdRef::TableNameTooLong);
 
6089
    return;
 
6090
  }
 
6091
  
 
6092
  TableRecordPtr tablePtr;
 
6093
  if(!c_tableRecordHash.find(tablePtr, keyRecord)) {
 
6094
    jam();
 
6095
    sendGET_TABLEID_REF((Signal*)signal, 
 
6096
                        (GetTableIdReq *)req, 
 
6097
                        GetTableIdRef::TableNotDefined);
 
6098
    return;
 
6099
  }
 
6100
  GetTableIdConf * conf = (GetTableIdConf *)req;
 
6101
  conf->tableId               = tablePtr.p->tableId;
 
6102
  conf->schemaVersion         = tablePtr.p->tableVersion;
 
6103
  conf->senderData            = senderData;
 
6104
  sendSignal(senderRef, GSN_GET_TABLEID_CONF, signal,
 
6105
             GetTableIdConf::SignalLength, JBB);  
 
6106
  
 
6107
}
 
6108
 
 
6109
 
 
6110
void Dbdict::sendGET_TABLEID_REF(Signal* signal, 
 
6111
                                 GetTableIdReq * req,
 
6112
                                 GetTableIdRef::ErrorCode errorCode) 
 
6113
{
 
6114
  GetTableIdRef * const ref = (GetTableIdRef *)req;
 
6115
  /**
 
6116
   * The format of GetTabInfo Req/Ref is the same
 
6117
   */
 
6118
  BlockReference retRef = req->senderRef;
 
6119
  ref->err  = errorCode;
 
6120
  sendSignal(retRef, GSN_GET_TABLEID_REF, signal, 
 
6121
             GetTableIdRef::SignalLength, JBB);
 
6122
}//sendGET_TABINFOREF()
 
6123
 
 
6124
/* ---------------------------------------------------------------- */
 
6125
// Get a full table description.
 
6126
/* ---------------------------------------------------------------- */
 
6127
void Dbdict::execGET_TABINFOREQ(Signal* signal) 
 
6128
{
 
6129
  jamEntry();
 
6130
  if(!assembleFragments(signal)) 
 
6131
  { 
 
6132
    return;
 
6133
  }  
 
6134
 
 
6135
  GetTabInfoReq * const req = (GetTabInfoReq *)&signal->theData[0];
 
6136
 
 
6137
  /**
 
6138
   * If I get a GET_TABINFO_REQ from myself
 
6139
   * it's is a one from the time queue
 
6140
   */
 
6141
  bool fromTimeQueue = (signal->senderBlockRef() == reference());
 
6142
  
 
6143
  if (c_retrieveRecord.busyState && fromTimeQueue == true) {
 
6144
    jam();
 
6145
    
 
6146
    sendSignalWithDelay(reference(), GSN_GET_TABINFOREQ, signal, 30, 
 
6147
                        signal->length());
 
6148
    return;
 
6149
  }//if
 
6150
 
 
6151
  const Uint32 MAX_WAITERS = 5;
 
6152
  
 
6153
  if(c_retrieveRecord.busyState && fromTimeQueue == false){
 
6154
    jam();
 
6155
    if(c_retrieveRecord.noOfWaiters < MAX_WAITERS){
 
6156
      jam();
 
6157
      c_retrieveRecord.noOfWaiters++;
 
6158
      
 
6159
      sendSignalWithDelay(reference(), GSN_GET_TABINFOREQ, signal, 30, 
 
6160
                          signal->length());
 
6161
      return;
 
6162
    }
 
6163
    
 
6164
    sendGET_TABINFOREF(signal, req, GetTabInfoRef::Busy);
 
6165
    return;
 
6166
  }
 
6167
  
 
6168
  if(fromTimeQueue){
 
6169
    jam();
 
6170
    c_retrieveRecord.noOfWaiters--;
 
6171
  } 
 
6172
 
 
6173
  const bool useLongSig = (req->requestType & GetTabInfoReq::LongSignalConf);
 
6174
  const Uint32 reqType = req->requestType & (~GetTabInfoReq::LongSignalConf);
 
6175
  
 
6176
  TableRecordPtr tablePtr;
 
6177
  if(reqType == GetTabInfoReq::RequestByName){
 
6178
    jam();
 
6179
    ndbrequire(signal->getNoOfSections() == 1);  
 
6180
    const Uint32 len = req->tableNameLen;
 
6181
    
 
6182
    TableRecord keyRecord;
 
6183
    if(len > sizeof(keyRecord.tableName)){
 
6184
      jam();
 
6185
      releaseSections(signal);
 
6186
      sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNameTooLong);
 
6187
      return;
 
6188
    }
 
6189
 
 
6190
    char tableName[MAX_TAB_NAME_SIZE];
 
6191
    SegmentedSectionPtr ssPtr;
 
6192
    signal->getSection(ssPtr,GetTabInfoReq::TABLE_NAME);
 
6193
    SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
 
6194
    r0.reset(); // undo implicit first()
 
6195
    if(r0.getWords((Uint32*)tableName, ((len + 3)/4)))
 
6196
      memcpy(keyRecord.tableName, tableName, len);
 
6197
    else {
 
6198
      jam();
 
6199
      releaseSections(signal);
 
6200
      sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNotDefined);
 
6201
      return;
 
6202
    }
 
6203
    releaseSections(signal);
 
6204
    //    memcpy(keyRecord.tableName, req->tableName, len);
 
6205
    //ntohS(&keyRecord.tableName[0], len);
 
6206
   
 
6207
    c_tableRecordHash.find(tablePtr, keyRecord);
 
6208
  } else {
 
6209
    jam();
 
6210
    c_tableRecordPool.getPtr(tablePtr, req->tableId, false);
 
6211
  }
 
6212
  
 
6213
  // The table seached for was not found
 
6214
  if(tablePtr.i == RNIL){
 
6215
    jam();
 
6216
    sendGET_TABINFOREF(signal, req, GetTabInfoRef::InvalidTableId);
 
6217
    return;
 
6218
  }//if
 
6219
  
 
6220
  if (! (tablePtr.p->tabState == TableRecord::DEFINED ||
 
6221
         tablePtr.p->tabState == TableRecord::BACKUP_ONGOING)) {
 
6222
    jam();
 
6223
    sendGET_TABINFOREF(signal, req, GetTabInfoRef::TableNotDefined);
 
6224
    return;
 
6225
  }//if
 
6226
  
 
6227
  c_retrieveRecord.busyState = true;
 
6228
  c_retrieveRecord.blockRef = req->senderRef;
 
6229
  c_retrieveRecord.m_senderData = req->senderData;
 
6230
  c_retrieveRecord.tableId = tablePtr.i;
 
6231
  c_retrieveRecord.currentSent = 0;
 
6232
  c_retrieveRecord.m_useLongSig = useLongSig;
 
6233
  
 
6234
  c_packTable.m_state = PackTable::PTS_GET_TAB;
 
6235
  
 
6236
  signal->theData[0] = ZPACK_TABLE_INTO_PAGES;
 
6237
  signal->theData[1] = tablePtr.i;
 
6238
  signal->theData[2] = c_retrieveRecord.retrievePage;  
 
6239
  sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
 
6240
}//execGET_TABINFOREQ()
 
6241
 
 
6242
void Dbdict::sendGetTabResponse(Signal* signal) 
 
6243
{
 
6244
  PageRecordPtr pagePtr;
 
6245
  DictTabInfo * const conf = (DictTabInfo *)&signal->theData[0];
 
6246
  conf->senderRef   = reference();
 
6247
  conf->senderData  = c_retrieveRecord.m_senderData;
 
6248
  conf->requestType = DictTabInfo::GetTabInfoConf;
 
6249
  conf->totalLen    = c_retrieveRecord.retrievedNoOfWords;
 
6250
 
 
6251
  c_pageRecordArray.getPtr(pagePtr, c_retrieveRecord.retrievePage);
 
6252
  Uint32* pagePointer = (Uint32*)&pagePtr.p->word[0] + ZPAGE_HEADER_SIZE;
 
6253
  
 
6254
  if(c_retrieveRecord.m_useLongSig){
 
6255
    jam();
 
6256
    GetTabInfoConf* conf = (GetTabInfoConf*)signal->getDataPtr();
 
6257
    conf->gci = 0;
 
6258
    conf->tableId = c_retrieveRecord.tableId;
 
6259
    conf->senderData = c_retrieveRecord.m_senderData;
 
6260
    conf->totalLen = c_retrieveRecord.retrievedNoOfWords;
 
6261
    
 
6262
    Callback c = { safe_cast(&Dbdict::initRetrieveRecord), 0 };
 
6263
    LinearSectionPtr ptr[3];
 
6264
    ptr[0].p = pagePointer;
 
6265
    ptr[0].sz = c_retrieveRecord.retrievedNoOfWords;
 
6266
    sendFragmentedSignal(c_retrieveRecord.blockRef,
 
6267
                         GSN_GET_TABINFO_CONF,
 
6268
                         signal, 
 
6269
                         GetTabInfoConf::SignalLength,
 
6270
                         JBB,
 
6271
                         ptr,
 
6272
                         1,
 
6273
                         c);
 
6274
    return;
 
6275
  }
 
6276
 
 
6277
  ndbrequire(false);
 
6278
}//sendGetTabResponse()
 
6279
 
 
6280
void Dbdict::sendGET_TABINFOREF(Signal* signal, 
 
6281
                                GetTabInfoReq * req,
 
6282
                                GetTabInfoRef::ErrorCode errorCode) 
 
6283
{
 
6284
  jamEntry();
 
6285
  GetTabInfoRef * const ref = (GetTabInfoRef *)&signal->theData[0];
 
6286
  /**
 
6287
   * The format of GetTabInfo Req/Ref is the same
 
6288
   */
 
6289
  BlockReference retRef = req->senderRef;
 
6290
  ref->errorCode = errorCode;
 
6291
  
 
6292
  sendSignal(retRef, GSN_GET_TABINFOREF, signal, signal->length(), JBB);
 
6293
}//sendGET_TABINFOREF()
 
6294
 
 
6295
Uint32 convertEndian(Uint32 in) {
 
6296
#ifdef WORDS_BIGENDIAN
 
6297
  Uint32 ut = 0;
 
6298
  ut += ((in >> 24) & 255);
 
6299
  ut += (((in >> 16) & 255) << 8);
 
6300
  ut += (((in >> 8) & 255) << 16);
 
6301
  ut += ((in & 255) << 24);
 
6302
  return ut;
 
6303
#else
 
6304
  return in;
 
6305
#endif
 
6306
}
 
6307
void
 
6308
Dbdict::execLIST_TABLES_REQ(Signal* signal)
 
6309
{
 
6310
  jamEntry();
 
6311
  Uint32 i;
 
6312
  ListTablesReq * req = (ListTablesReq*)signal->getDataPtr();
 
6313
  Uint32 senderRef  = req->senderRef;
 
6314
  Uint32 senderData = req->senderData;
 
6315
  // save req flags
 
6316
  const Uint32 reqTableId = req->getTableId();
 
6317
  const Uint32 reqTableType = req->getTableType();
 
6318
  const bool reqListNames = req->getListNames();
 
6319
  const bool reqListIndexes = req->getListIndexes();
 
6320
  // init the confs
 
6321
  ListTablesConf * conf = (ListTablesConf *)signal->getDataPtrSend();
 
6322
  conf->senderData = senderData;
 
6323
  conf->counter = 0;
 
6324
  Uint32 pos = 0;
 
6325
  for (i = 0; i < c_tableRecordPool.getSize(); i++) {
 
6326
    TableRecordPtr tablePtr;
 
6327
    c_tableRecordPool.getPtr(tablePtr, i);
 
6328
    // filter
 
6329
    if (tablePtr.p->tabState == TableRecord::NOT_DEFINED ||
 
6330
        tablePtr.p->tabState == TableRecord::REORG_TABLE_PREPARED)
 
6331
      continue;
 
6332
 
 
6333
 
 
6334
    if ((reqTableType != (Uint32)0) && (reqTableType != (unsigned)tablePtr.p->tableType))
 
6335
      continue;
 
6336
    if (reqListIndexes && reqTableId != tablePtr.p->primaryTableId)
 
6337
      continue;
 
6338
    conf->tableData[pos] = 0;
 
6339
    // id
 
6340
    conf->setTableId(pos, tablePtr.i);
 
6341
    // type
 
6342
    conf->setTableType(pos, tablePtr.p->tableType);
 
6343
    // state
 
6344
    if (tablePtr.p->isTable()) {
 
6345
      switch (tablePtr.p->tabState) {
 
6346
      case TableRecord::DEFINING:
 
6347
      case TableRecord::CHECKED:
 
6348
        conf->setTableState(pos, DictTabInfo::StateBuilding);
 
6349
        break;
 
6350
      case TableRecord::PREPARE_DROPPING:
 
6351
      case TableRecord::DROPPING:
 
6352
        conf->setTableState(pos, DictTabInfo::StateDropping);
 
6353
        break;
 
6354
      case TableRecord::DEFINED:
 
6355
        conf->setTableState(pos, DictTabInfo::StateOnline);
 
6356
        break;
 
6357
      case TableRecord::BACKUP_ONGOING:
 
6358
        conf->setTableState(pos, DictTabInfo::StateBackup);
 
6359
        break;
 
6360
      default:
 
6361
        conf->setTableState(pos, DictTabInfo::StateBroken);
 
6362
        break;
 
6363
      }
 
6364
    }
 
6365
    if (tablePtr.p->isIndex()) {
 
6366
      switch (tablePtr.p->indexState) {
 
6367
      case TableRecord::IS_OFFLINE:
 
6368
        conf->setTableState(pos, DictTabInfo::StateOffline);
 
6369
        break;
 
6370
      case TableRecord::IS_BUILDING:
 
6371
        conf->setTableState(pos, DictTabInfo::StateBuilding);
 
6372
        break;
 
6373
      case TableRecord::IS_DROPPING:
 
6374
        conf->setTableState(pos, DictTabInfo::StateDropping);
 
6375
        break;
 
6376
      case TableRecord::IS_ONLINE:
 
6377
        conf->setTableState(pos, DictTabInfo::StateOnline);
 
6378
        break;
 
6379
      default:
 
6380
        conf->setTableState(pos, DictTabInfo::StateBroken);
 
6381
        break;
 
6382
      }
 
6383
    }
 
6384
    // store
 
6385
    if (! tablePtr.p->storedTable) {
 
6386
      conf->setTableStore(pos, DictTabInfo::StoreTemporary);
 
6387
    } else {
 
6388
      conf->setTableStore(pos, DictTabInfo::StorePermanent);
 
6389
    }
 
6390
    pos++;
 
6391
    if (pos >= ListTablesConf::DataLength) {
 
6392
      sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
 
6393
                 ListTablesConf::SignalLength, JBB);
 
6394
      conf->counter++;
 
6395
      pos = 0;
 
6396
    }
 
6397
    if (! reqListNames)
 
6398
      continue;
 
6399
    const Uint32 size = strlen(tablePtr.p->tableName) + 1;
 
6400
    conf->tableData[pos] = size;
 
6401
    pos++;
 
6402
    if (pos >= ListTablesConf::DataLength) {
 
6403
      sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
 
6404
                 ListTablesConf::SignalLength, JBB);
 
6405
      conf->counter++;
 
6406
      pos = 0;
 
6407
    }
 
6408
    Uint32 k = 0;
 
6409
    while (k < size) {
 
6410
      char* p = (char*)&conf->tableData[pos];
 
6411
      for (Uint32 j = 0; j < 4; j++) {
 
6412
        if (k < size)
 
6413
          *p++ = tablePtr.p->tableName[k++];
 
6414
        else
 
6415
          *p++ = 0;
 
6416
      }
 
6417
      pos++;
 
6418
      if (pos >= ListTablesConf::DataLength) {
 
6419
        sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
 
6420
                   ListTablesConf::SignalLength, JBB);
 
6421
        conf->counter++;
 
6422
        pos = 0;
 
6423
      }
 
6424
    }
 
6425
  }
 
6426
  // XXX merge with above somehow
 
6427
  for (i = 0; i < c_triggerRecordPool.getSize(); i++) {
 
6428
    if (reqListIndexes)
 
6429
      break;
 
6430
    TriggerRecordPtr triggerPtr;
 
6431
    c_triggerRecordPool.getPtr(triggerPtr, i);
 
6432
    if (triggerPtr.p->triggerState == TriggerRecord::TS_NOT_DEFINED)
 
6433
      continue;
 
6434
    // constant 10 hardcoded
 
6435
    Uint32 type = 10 + triggerPtr.p->triggerType;
 
6436
    if (reqTableType != 0 && reqTableType != type)
 
6437
      continue;
 
6438
    conf->tableData[pos] = 0;
 
6439
    conf->setTableId(pos, triggerPtr.i);
 
6440
    conf->setTableType(pos, type);
 
6441
    switch (triggerPtr.p->triggerState) {
 
6442
    case TriggerRecord::TS_OFFLINE:
 
6443
      conf->setTableState(pos, DictTabInfo::StateOffline);
 
6444
      break;
 
6445
    case TriggerRecord::TS_ONLINE:
 
6446
      conf->setTableState(pos, DictTabInfo::StateOnline);
 
6447
      break;
 
6448
    default:
 
6449
      conf->setTableState(pos, DictTabInfo::StateBroken);
 
6450
      break;
 
6451
    }
 
6452
    conf->setTableStore(pos, DictTabInfo::StoreTemporary);
 
6453
    pos++;
 
6454
    if (pos >= ListTablesConf::DataLength) {
 
6455
      sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
 
6456
        ListTablesConf::SignalLength, JBB);
 
6457
      conf->counter++;
 
6458
      pos = 0;
 
6459
    }
 
6460
    if (! reqListNames)
 
6461
      continue;
 
6462
    const Uint32 size = strlen(triggerPtr.p->triggerName) + 1;
 
6463
    conf->tableData[pos] = size;
 
6464
    pos++;
 
6465
    if (pos >= ListTablesConf::DataLength) {
 
6466
      sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
 
6467
                 ListTablesConf::SignalLength, JBB);
 
6468
      conf->counter++;
 
6469
      pos = 0;
 
6470
    }
 
6471
    Uint32 k = 0;
 
6472
    while (k < size) {
 
6473
      char* p = (char*)&conf->tableData[pos];
 
6474
      for (Uint32 j = 0; j < 4; j++) {
 
6475
        if (k < size)
 
6476
          *p++ = triggerPtr.p->triggerName[k++];
 
6477
        else
 
6478
          *p++ = 0;
 
6479
      }
 
6480
      pos++;
 
6481
      if (pos >= ListTablesConf::DataLength) {
 
6482
        sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
 
6483
                   ListTablesConf::SignalLength, JBB);
 
6484
        conf->counter++;
 
6485
        pos = 0;
 
6486
      }
 
6487
    }
 
6488
  }
 
6489
  // last signal must have less than max length
 
6490
  sendSignal(senderRef, GSN_LIST_TABLES_CONF, signal,
 
6491
             ListTablesConf::HeaderLength + pos, JBB);
 
6492
}
 
6493
 
 
6494
/**
 
6495
 * MODULE: Create index
 
6496
 *
 
6497
 * Create index in DICT via create table operation.  Then invoke alter
 
6498
 * index opearation to online the index.
 
6499
 *
 
6500
 * Request type in CREATE_INDX signals:
 
6501
 *
 
6502
 * RT_USER - from API to DICT master
 
6503
 * RT_DICT_PREPARE - prepare participants
 
6504
 * RT_DICT_COMMIT - commit participants
 
6505
 * RT_TC - create index in TC (part of alter index operation)
 
6506
 */
 
6507
 
 
6508
void
 
6509
Dbdict::execCREATE_INDX_REQ(Signal* signal)
 
6510
{
 
6511
  jamEntry();
 
6512
  CreateIndxReq* const req = (CreateIndxReq*)signal->getDataPtrSend();
 
6513
  OpCreateIndexPtr opPtr;
 
6514
  const Uint32 senderRef = signal->senderBlockRef();
 
6515
  const CreateIndxReq::RequestType requestType = req->getRequestType();
 
6516
  if (requestType == CreateIndxReq::RT_USER) {
 
6517
    jam();
 
6518
    if (! assembleFragments(signal)) {
 
6519
      jam();
 
6520
      return;
 
6521
    }
 
6522
    if (signal->getLength() == CreateIndxReq::SignalLength) {
 
6523
      jam();
 
6524
      CreateIndxRef::ErrorCode tmperr = CreateIndxRef::NoError;
 
6525
      if (getOwnNodeId() != c_masterNodeId) {
 
6526
        jam();
 
6527
        tmperr = CreateIndxRef::NotMaster;
 
6528
      } else if (c_blockState == BS_NODE_RESTART) {
 
6529
        jam();
 
6530
        tmperr = CreateIndxRef::BusyWithNR;
 
6531
      } else if (c_blockState != BS_IDLE) {
 
6532
        jam();
 
6533
        tmperr = CreateIndxRef::Busy;
 
6534
      }
 
6535
      if (tmperr != CreateIndxRef::NoError) {
 
6536
        releaseSections(signal);
 
6537
        OpCreateIndex opBusy;
 
6538
        opPtr.p = &opBusy;
 
6539
        opPtr.p->save(req);
 
6540
        opPtr.p->m_isMaster = (senderRef == reference());
 
6541
        opPtr.p->key = 0;
 
6542
        opPtr.p->m_requestType = CreateIndxReq::RT_DICT_PREPARE;
 
6543
        opPtr.p->m_errorCode = tmperr;
 
6544
        opPtr.p->m_errorLine = __LINE__;
 
6545
        opPtr.p->m_errorNode = c_masterNodeId;
 
6546
        createIndex_sendReply(signal, opPtr, true);
 
6547
        return;
 
6548
      }
 
6549
      // forward initial request plus operation key to all
 
6550
      req->setOpKey(++c_opRecordSequence);
 
6551
      NodeReceiverGroup rg(DBDICT, c_aliveNodes);
 
6552
      sendSignal(rg, GSN_CREATE_INDX_REQ,
 
6553
          signal, CreateIndxReq::SignalLength + 1, JBB);
 
6554
      return;
 
6555
    }
 
6556
    // seize operation record
 
6557
    ndbrequire(signal->getLength() == CreateIndxReq::SignalLength + 1);
 
6558
    const Uint32 opKey = req->getOpKey();
 
6559
    OpCreateIndex opBusy;
 
6560
    if (! c_opCreateIndex.seize(opPtr))
 
6561
      opPtr.p = &opBusy;
 
6562
    opPtr.p->save(req);
 
6563
    opPtr.p->m_coordinatorRef = senderRef;
 
6564
    opPtr.p->m_isMaster = (senderRef == reference());
 
6565
    opPtr.p->key = opKey;
 
6566
    opPtr.p->m_requestType = CreateIndxReq::RT_DICT_PREPARE;
 
6567
    if (opPtr.p == &opBusy) {
 
6568
      jam();
 
6569
      opPtr.p->m_errorCode = CreateIndxRef::Busy;
 
6570
      opPtr.p->m_errorLine = __LINE__;
 
6571
      releaseSections(signal);
 
6572
      createIndex_sendReply(signal, opPtr, opPtr.p->m_isMaster);
 
6573
      return;
 
6574
    }
 
6575
    c_opCreateIndex.add(opPtr);
 
6576
    // save attribute list
 
6577
    SegmentedSectionPtr ssPtr;
 
6578
    signal->getSection(ssPtr, CreateIndxReq::ATTRIBUTE_LIST_SECTION);
 
6579
    SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
 
6580
    r0.reset(); // undo implicit first()
 
6581
    if (! r0.getWord(&opPtr.p->m_attrList.sz) ||
 
6582
        ! r0.getWords(opPtr.p->m_attrList.id, opPtr.p->m_attrList.sz)) {
 
6583
      jam();
 
6584
      opPtr.p->m_errorCode = CreateIndxRef::InvalidName;
 
6585
      opPtr.p->m_errorLine = __LINE__;
 
6586
      releaseSections(signal);
 
6587
      createIndex_sendReply(signal, opPtr, opPtr.p->m_isMaster);
 
6588
      return;
 
6589
    }
 
6590
    // save name and index table properties
 
6591
    signal->getSection(ssPtr, CreateIndxReq::INDEX_NAME_SECTION);
 
6592
    SimplePropertiesSectionReader r1(ssPtr, getSectionSegmentPool());
 
6593
    DictTabInfo::Table tableDesc;
 
6594
    tableDesc.init();
 
6595
    SimpleProperties::UnpackStatus status = SimpleProperties::unpack(
 
6596
        r1, &tableDesc,
 
6597
        DictTabInfo::TableMapping, DictTabInfo::TableMappingSize,
 
6598
        true, true);
 
6599
    if (status != SimpleProperties::Eof) {
 
6600
      opPtr.p->m_errorCode = CreateIndxRef::InvalidName;
 
6601
      opPtr.p->m_errorLine = __LINE__;
 
6602
      releaseSections(signal);
 
6603
      createIndex_sendReply(signal, opPtr, opPtr.p->m_isMaster);
 
6604
      return;
 
6605
    }
 
6606
    memcpy(opPtr.p->m_indexName, tableDesc.TableName, MAX_TAB_NAME_SIZE);
 
6607
    opPtr.p->m_storedIndex = tableDesc.TableLoggedFlag;
 
6608
    releaseSections(signal);
 
6609
    // master expects to hear from all
 
6610
    if (opPtr.p->m_isMaster)
 
6611
      opPtr.p->m_signalCounter = c_aliveNodes;
 
6612
    createIndex_slavePrepare(signal, opPtr);
 
6613
    createIndex_sendReply(signal, opPtr, false);
 
6614
    return;
 
6615
  }
 
6616
  c_opCreateIndex.find(opPtr, req->getConnectionPtr());
 
6617
  if (! opPtr.isNull()) {
 
6618
    opPtr.p->m_requestType = requestType;
 
6619
    if (requestType == CreateIndxReq::RT_DICT_COMMIT ||
 
6620
        requestType == CreateIndxReq::RT_DICT_ABORT) {
 
6621
      jam();
 
6622
      if (requestType == CreateIndxReq::RT_DICT_COMMIT) {
 
6623
        opPtr.p->m_request.setIndexId(req->getIndexId());
 
6624
        opPtr.p->m_request.setIndexVersion(req->getIndexVersion());
 
6625
        createIndex_slaveCommit(signal, opPtr);
 
6626
      } else {
 
6627
        createIndex_slaveAbort(signal, opPtr);
 
6628
      }
 
6629
      createIndex_sendReply(signal, opPtr, false);
 
6630
      // done in slave
 
6631
      if (! opPtr.p->m_isMaster)
 
6632
        c_opCreateIndex.release(opPtr);
 
6633
      return;
 
6634
    }
 
6635
  }
 
6636
  jam();
 
6637
  // return to sender
 
6638
  releaseSections(signal);
 
6639
  OpCreateIndex opBad;
 
6640
  opPtr.p = &opBad;
 
6641
  opPtr.p->save(req);
 
6642
  opPtr.p->m_errorCode = CreateIndxRef::BadRequestType;
 
6643
  opPtr.p->m_errorLine = __LINE__;
 
6644
  createIndex_sendReply(signal, opPtr, true);
 
6645
}
 
6646
 
 
6647
void
 
6648
Dbdict::execCREATE_INDX_CONF(Signal* signal)
 
6649
{
 
6650
  jamEntry();
 
6651
  ndbrequire(signal->getNoOfSections() == 0);
 
6652
  CreateIndxConf* conf = (CreateIndxConf*)signal->getDataPtrSend();
 
6653
  createIndex_recvReply(signal, conf, 0);
 
6654
}
 
6655
 
 
6656
void
 
6657
Dbdict::execCREATE_INDX_REF(Signal* signal) 
 
6658
{
 
6659
  jamEntry();      
 
6660
  CreateIndxRef* ref = (CreateIndxRef*)signal->getDataPtrSend();
 
6661
  createIndex_recvReply(signal, ref->getConf(), ref);
 
6662
}
 
6663
 
 
6664
void
 
6665
Dbdict::createIndex_recvReply(Signal* signal, const CreateIndxConf* conf,
 
6666
    const CreateIndxRef* ref)
 
6667
{
 
6668
  jam();
 
6669
  const Uint32 senderRef = signal->senderBlockRef();
 
6670
  const CreateIndxReq::RequestType requestType = conf->getRequestType();
 
6671
  const Uint32 key = conf->getConnectionPtr();
 
6672
  if (requestType == CreateIndxReq::RT_TC) {
 
6673
    jam();
 
6674
    // part of alter index operation
 
6675
    OpAlterIndexPtr opPtr;
 
6676
    c_opAlterIndex.find(opPtr, key);
 
6677
    ndbrequire(! opPtr.isNull());
 
6678
    opPtr.p->setError(ref);
 
6679
    alterIndex_fromCreateTc(signal, opPtr);
 
6680
    return;
 
6681
  }
 
6682
  OpCreateIndexPtr opPtr;
 
6683
  c_opCreateIndex.find(opPtr, key);
 
6684
  ndbrequire(! opPtr.isNull());
 
6685
  ndbrequire(opPtr.p->m_isMaster);
 
6686
  ndbrequire(opPtr.p->m_requestType == requestType);
 
6687
  opPtr.p->setError(ref);
 
6688
  opPtr.p->m_signalCounter.clearWaitingFor(refToNode(senderRef));
 
6689
  if (! opPtr.p->m_signalCounter.done()) {
 
6690
    jam();
 
6691
    return;
 
6692
  }
 
6693
  if (requestType == CreateIndxReq::RT_DICT_COMMIT ||
 
6694
      requestType == CreateIndxReq::RT_DICT_ABORT) {
 
6695
    jam();
 
6696
    // send reply to user
 
6697
    createIndex_sendReply(signal, opPtr, true);
 
6698
    c_opCreateIndex.release(opPtr);
 
6699
    return;
 
6700
  }
 
6701
  if (opPtr.p->hasError()) {
 
6702
    jam();
 
6703
    opPtr.p->m_requestType = CreateIndxReq::RT_DICT_ABORT;
 
6704
    createIndex_sendSlaveReq(signal, opPtr);
 
6705
    return;
 
6706
  }
 
6707
  if (requestType == CreateIndxReq::RT_DICT_PREPARE) {
 
6708
    jam();
 
6709
    // start index table create
 
6710
    createIndex_toCreateTable(signal, opPtr);
 
6711
    if (opPtr.p->hasError()) {
 
6712
      jam();
 
6713
      opPtr.p->m_requestType = CreateIndxReq::RT_DICT_ABORT;
 
6714
      createIndex_sendSlaveReq(signal, opPtr);
 
6715
      return;
 
6716
    }
 
6717
    return;
 
6718
  }
 
6719
  ndbrequire(false);
 
6720
}
 
6721
 
 
6722
void
 
6723
Dbdict::createIndex_slavePrepare(Signal* signal, OpCreateIndexPtr opPtr)
 
6724
{
 
6725
  jam();
 
6726
  if (ERROR_INSERTED(6006) && ! opPtr.p->m_isMaster) {
 
6727
    ndbrequire(false);
 
6728
  }
 
6729
}
 
6730
 
 
6731
void
 
6732
Dbdict::createIndex_toCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
 
6733
{
 
6734
  Uint32 attrid_map[MAX_ATTRIBUTES_IN_INDEX];
 
6735
  Uint32 k;
 
6736
  jam();
 
6737
  const CreateIndxReq* const req = &opPtr.p->m_request;
 
6738
  // signal data writer
 
6739
  Uint32* wbuffer = &c_indexPage.word[0];
 
6740
  LinearWriter w(wbuffer, sizeof(c_indexPage) >> 2);
 
6741
  w.first();
 
6742
  // get table being indexed
 
6743
  if (! (req->getTableId() < c_tableRecordPool.getSize())) {
 
6744
    jam();
 
6745
    opPtr.p->m_errorCode = CreateIndxRef::InvalidPrimaryTable;
 
6746
    opPtr.p->m_errorLine = __LINE__;
 
6747
    return;
 
6748
  }
 
6749
  TableRecordPtr tablePtr;
 
6750
  c_tableRecordPool.getPtr(tablePtr, req->getTableId());
 
6751
  if (tablePtr.p->tabState != TableRecord::DEFINED &&
 
6752
      tablePtr.p->tabState != TableRecord::BACKUP_ONGOING) {
 
6753
    jam();
 
6754
    opPtr.p->m_errorCode = CreateIndxRef::InvalidPrimaryTable;
 
6755
    opPtr.p->m_errorLine = __LINE__;
 
6756
    return;
 
6757
  }
 
6758
  if (! tablePtr.p->isTable()) {
 
6759
    jam();
 
6760
    opPtr.p->m_errorCode = CreateIndxRef::InvalidPrimaryTable;
 
6761
    opPtr.p->m_errorLine = __LINE__;
 
6762
    return;
 
6763
  }
 
6764
  // compute index table record
 
6765
  TableRecord indexRec;
 
6766
  TableRecordPtr indexPtr;
 
6767
  indexPtr.i = RNIL;            // invalid
 
6768
  indexPtr.p = &indexRec;
 
6769
  initialiseTableRecord(indexPtr);
 
6770
  if (req->getIndexType() == DictTabInfo::UniqueHashIndex) {
 
6771
    indexPtr.p->storedTable = opPtr.p->m_storedIndex;
 
6772
    indexPtr.p->fragmentType = tablePtr.p->fragmentType;
 
6773
  } else if (req->getIndexType() == DictTabInfo::OrderedIndex) {
 
6774
    // first version will not supported logging
 
6775
    if (opPtr.p->m_storedIndex) {
 
6776
      jam();
 
6777
      opPtr.p->m_errorCode = CreateIndxRef::InvalidIndexType;
 
6778
      opPtr.p->m_errorLine = __LINE__;
 
6779
      return;
 
6780
    }
 
6781
    indexPtr.p->storedTable = false;
 
6782
    // follows table fragmentation
 
6783
    indexPtr.p->fragmentType = tablePtr.p->fragmentType;
 
6784
  } else {
 
6785
    jam();
 
6786
    opPtr.p->m_errorCode = CreateIndxRef::InvalidIndexType;
 
6787
    opPtr.p->m_errorLine = __LINE__;
 
6788
    return;
 
6789
  }
 
6790
  indexPtr.p->tableType = (DictTabInfo::TableType)req->getIndexType();
 
6791
  indexPtr.p->primaryTableId = req->getTableId();
 
6792
  indexPtr.p->noOfAttributes = opPtr.p->m_attrList.sz;
 
6793
  indexPtr.p->tupKeyLength = 0;
 
6794
  if (indexPtr.p->noOfAttributes == 0) {
 
6795
    jam();
 
6796
    opPtr.p->m_errorCode = CreateIndxRef::InvalidIndexType;
 
6797
    opPtr.p->m_errorLine = __LINE__;
 
6798
    return;
 
6799
  }
 
6800
  if (indexPtr.p->isOrderedIndex()) {
 
6801
    // tree node size in words (make configurable later)
 
6802
    indexPtr.p->tupKeyLength = MAX_TTREE_NODE_SIZE;
 
6803
  }
 
6804
 
 
6805
  AttributeMask mask;
 
6806
  mask.clear();
 
6807
  for (k = 0; k < opPtr.p->m_attrList.sz; k++) {
 
6808
    jam();
 
6809
    unsigned current_id= opPtr.p->m_attrList.id[k];
 
6810
    AttributeRecord* aRec= NULL;
 
6811
    Uint32 tAttr= tablePtr.p->firstAttribute;
 
6812
    for (; tAttr != RNIL; tAttr= aRec->nextAttrInTable)
 
6813
    {
 
6814
      aRec = c_attributeRecordPool.getPtr(tAttr);
 
6815
      if (aRec->attributeId != current_id)
 
6816
        continue;
 
6817
      jam();
 
6818
      break;
 
6819
    }
 
6820
    if (tAttr == RNIL) {
 
6821
      jam();
 
6822
      opPtr.p->m_errorCode = CreateIndxRef::BadRequestType;
 
6823
      opPtr.p->m_errorLine = __LINE__;
 
6824
      return;
 
6825
    }
 
6826
    if (mask.get(current_id))
 
6827
    {
 
6828
      jam();
 
6829
      opPtr.p->m_errorCode = CreateIndxRef::DuplicateAttributes;
 
6830
      opPtr.p->m_errorLine = __LINE__;
 
6831
      return;
 
6832
    }
 
6833
    mask.set(current_id);
 
6834
 
 
6835
    const Uint32 a = aRec->attributeDescriptor;
 
6836
    unsigned kk= k;
 
6837
    if (indexPtr.p->isHashIndex()) {
 
6838
      const Uint32 s1 = AttributeDescriptor::getSize(a);
 
6839
      const Uint32 s2 = AttributeDescriptor::getArraySize(a);
 
6840
      indexPtr.p->tupKeyLength += ((1 << s1) * s2 + 31) >> 5;
 
6841
      // reorder the attributes according to the tableid order
 
6842
      // for unque indexes
 
6843
      for (; kk > 0 && current_id < attrid_map[kk-1]>>16; kk--)
 
6844
        attrid_map[kk]= attrid_map[kk-1];
 
6845
    }
 
6846
    attrid_map[kk]= k | (current_id << 16);
 
6847
  }
 
6848
  indexPtr.p->noOfPrimkey = indexPtr.p->noOfAttributes;
 
6849
  // plus concatenated primary table key attribute
 
6850
  indexPtr.p->noOfAttributes += 1;
 
6851
  indexPtr.p->noOfNullAttr = 0;
 
6852
  // write index table
 
6853
  w.add(DictTabInfo::TableName, opPtr.p->m_indexName);
 
6854
  w.add(DictTabInfo::TableLoggedFlag, indexPtr.p->storedTable);
 
6855
  w.add(DictTabInfo::FragmentTypeVal, indexPtr.p->fragmentType);
 
6856
  w.add(DictTabInfo::TableTypeVal, indexPtr.p->tableType);
 
6857
  w.add(DictTabInfo::PrimaryTable, tablePtr.p->tableName);
 
6858
  w.add(DictTabInfo::PrimaryTableId, tablePtr.i);
 
6859
  w.add(DictTabInfo::NoOfAttributes, indexPtr.p->noOfAttributes);
 
6860
  w.add(DictTabInfo::NoOfKeyAttr, indexPtr.p->noOfPrimkey);
 
6861
  w.add(DictTabInfo::NoOfNullable, indexPtr.p->noOfNullAttr);
 
6862
  w.add(DictTabInfo::KeyLength, indexPtr.p->tupKeyLength);
 
6863
  // write index key attributes
 
6864
  AttributeRecordPtr aRecPtr;
 
6865
  c_attributeRecordPool.getPtr(aRecPtr, tablePtr.p->firstAttribute);
 
6866
  for (k = 0; k < opPtr.p->m_attrList.sz; k++) {
 
6867
    // insert the attributes in the order decided above in attrid_map
 
6868
    // k is new order, current_id is in previous order
 
6869
    // ToDo: make sure "current_id" is stored with the table and
 
6870
    // passed up to NdbDictionary
 
6871
    unsigned current_id= opPtr.p->m_attrList.id[attrid_map[k] & 0xffff];
 
6872
    jam();
 
6873
    for (Uint32 tAttr = tablePtr.p->firstAttribute; tAttr != RNIL; ) {
 
6874
      AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr);
 
6875
      tAttr = aRec->nextAttrInTable;
 
6876
      if (aRec->attributeId != current_id)
 
6877
        continue;
 
6878
      jam();
 
6879
      const Uint32 a = aRec->attributeDescriptor;
 
6880
      bool isNullable = AttributeDescriptor::getNullable(a);
 
6881
      Uint32 attrType = AttributeDescriptor::getType(a);
 
6882
      w.add(DictTabInfo::AttributeName, aRec->attributeName);
 
6883
      w.add(DictTabInfo::AttributeId, k);
 
6884
      if (indexPtr.p->isHashIndex()) {
 
6885
        w.add(DictTabInfo::AttributeKeyFlag, (Uint32)true);
 
6886
        w.add(DictTabInfo::AttributeNullableFlag, (Uint32)false);
 
6887
      }
 
6888
      if (indexPtr.p->isOrderedIndex()) {
 
6889
        w.add(DictTabInfo::AttributeKeyFlag, (Uint32)false);
 
6890
        w.add(DictTabInfo::AttributeNullableFlag, (Uint32)isNullable);
 
6891
      }
 
6892
      w.add(DictTabInfo::AttributeExtType, attrType);
 
6893
      w.add(DictTabInfo::AttributeExtPrecision, aRec->extPrecision);
 
6894
      w.add(DictTabInfo::AttributeExtScale, aRec->extScale);
 
6895
      w.add(DictTabInfo::AttributeExtLength, aRec->extLength);
 
6896
      w.add(DictTabInfo::AttributeEnd, (Uint32)true);
 
6897
    }
 
6898
  }
 
6899
  if (indexPtr.p->isHashIndex()) {
 
6900
    jam();
 
6901
    // write concatenated primary table key attribute
 
6902
    w.add(DictTabInfo::AttributeName, "NDB$PK");
 
6903
    w.add(DictTabInfo::AttributeId, opPtr.p->m_attrList.sz);
 
6904
    w.add(DictTabInfo::AttributeKeyFlag, (Uint32)false);
 
6905
    w.add(DictTabInfo::AttributeNullableFlag, (Uint32)false);
 
6906
    w.add(DictTabInfo::AttributeExtType, (Uint32)DictTabInfo::ExtUnsigned);
 
6907
    w.add(DictTabInfo::AttributeExtLength, tablePtr.p->tupKeyLength);
 
6908
    w.add(DictTabInfo::AttributeEnd, (Uint32)true);
 
6909
  }
 
6910
  if (indexPtr.p->isOrderedIndex()) {
 
6911
    jam();
 
6912
    // write index tree node as Uint32 array attribute
 
6913
    w.add(DictTabInfo::AttributeName, "NDB$TNODE");
 
6914
    w.add(DictTabInfo::AttributeId, opPtr.p->m_attrList.sz);
 
6915
    w.add(DictTabInfo::AttributeKeyFlag, (Uint32)true);
 
6916
    w.add(DictTabInfo::AttributeNullableFlag, (Uint32)false);
 
6917
    w.add(DictTabInfo::AttributeExtType, (Uint32)DictTabInfo::ExtUnsigned);
 
6918
    w.add(DictTabInfo::AttributeExtLength, indexPtr.p->tupKeyLength);
 
6919
    w.add(DictTabInfo::AttributeEnd, (Uint32)true);
 
6920
  }
 
6921
  // finish
 
6922
  w.add(DictTabInfo::TableEnd, (Uint32)true);
 
6923
  // remember to...
 
6924
  releaseSections(signal);
 
6925
  // send create index table request
 
6926
  CreateTableReq * const cre = (CreateTableReq*)signal->getDataPtrSend();
 
6927
  cre->senderRef = reference();
 
6928
  cre->senderData = opPtr.p->key;
 
6929
  LinearSectionPtr lsPtr[3];
 
6930
  lsPtr[0].p = wbuffer;
 
6931
  lsPtr[0].sz = w.getWordsUsed();
 
6932
  sendSignal(DBDICT_REF, GSN_CREATE_TABLE_REQ,
 
6933
      signal, CreateTableReq::SignalLength, JBB, lsPtr, 1);
 
6934
}
 
6935
 
 
6936
void
 
6937
Dbdict::createIndex_fromCreateTable(Signal* signal, OpCreateIndexPtr opPtr)
 
6938
{
 
6939
  jam();
 
6940
  if (opPtr.p->hasError()) {
 
6941
    jam();
 
6942
    opPtr.p->m_requestType = CreateIndxReq::RT_DICT_ABORT;
 
6943
    createIndex_sendSlaveReq(signal, opPtr);
 
6944
    return;
 
6945
  }
 
6946
  if (! opPtr.p->m_request.getOnline()) {
 
6947
    jam();
 
6948
    opPtr.p->m_requestType = CreateIndxReq::RT_DICT_COMMIT;
 
6949
    createIndex_sendSlaveReq(signal, opPtr);
 
6950
    return;
 
6951
  }
 
6952
  createIndex_toAlterIndex(signal, opPtr);
 
6953
}
 
6954
 
 
6955
void
 
6956
Dbdict::createIndex_toAlterIndex(Signal* signal, OpCreateIndexPtr opPtr)
 
6957
{
 
6958
  jam();
 
6959
  AlterIndxReq* const req = (AlterIndxReq*)signal->getDataPtrSend();
 
6960
  req->setUserRef(reference());
 
6961
  req->setConnectionPtr(opPtr.p->key);
 
6962
  req->setRequestType(AlterIndxReq::RT_CREATE_INDEX);
 
6963
  req->addRequestFlag(opPtr.p->m_requestFlag);
 
6964
  req->setTableId(opPtr.p->m_request.getTableId());
 
6965
  req->setIndexId(opPtr.p->m_request.getIndexId());
 
6966
  req->setIndexVersion(opPtr.p->m_request.getIndexVersion());
 
6967
  req->setOnline(true);
 
6968
  sendSignal(reference(), GSN_ALTER_INDX_REQ,
 
6969
      signal, AlterIndxReq::SignalLength, JBB);
 
6970
}
 
6971
 
 
6972
void
 
6973
Dbdict::createIndex_fromAlterIndex(Signal* signal, OpCreateIndexPtr opPtr)
 
6974
{
 
6975
  jam();
 
6976
  if (opPtr.p->hasError()) {
 
6977
    jam();
 
6978
    opPtr.p->m_requestType = CreateIndxReq::RT_DICT_ABORT;
 
6979
    createIndex_sendSlaveReq(signal, opPtr);
 
6980
    return;
 
6981
  }
 
6982
  opPtr.p->m_requestType = CreateIndxReq::RT_DICT_COMMIT;
 
6983
  createIndex_sendSlaveReq(signal, opPtr);
 
6984
}
 
6985
 
 
6986
void
 
6987
Dbdict::createIndex_slaveCommit(Signal* signal, OpCreateIndexPtr opPtr)
 
6988
{
 
6989
  jam();
 
6990
  const Uint32 indexId = opPtr.p->m_request.getIndexId();
 
6991
  TableRecordPtr indexPtr;
 
6992
  c_tableRecordPool.getPtr(indexPtr, indexId);
 
6993
  if (! opPtr.p->m_request.getOnline()) {
 
6994
    ndbrequire(indexPtr.p->indexState == TableRecord::IS_UNDEFINED);
 
6995
    indexPtr.p->indexState = TableRecord::IS_OFFLINE;
 
6996
  } else {
 
6997
    ndbrequire(indexPtr.p->indexState == TableRecord::IS_ONLINE);
 
6998
  }
 
6999
}
 
7000
 
 
7001
void
 
7002
Dbdict::createIndex_slaveAbort(Signal* signal, OpCreateIndexPtr opPtr)
 
7003
{
 
7004
  jam();
 
7005
  CreateIndxReq* const req = &opPtr.p->m_request;
 
7006
  const Uint32 indexId = req->getIndexId();
 
7007
  if (indexId >= c_tableRecordPool.getSize()) {
 
7008
    jam();
 
7009
    return;
 
7010
  }
 
7011
  TableRecordPtr indexPtr;
 
7012
  c_tableRecordPool.getPtr(indexPtr, indexId);
 
7013
  if (! indexPtr.p->isIndex()) {
 
7014
    jam();
 
7015
    return;
 
7016
  }
 
7017
  indexPtr.p->indexState = TableRecord::IS_BROKEN;
 
7018
}
 
7019
 
 
7020
void
 
7021
Dbdict::createIndex_sendSlaveReq(Signal* signal, OpCreateIndexPtr opPtr)
 
7022
{
 
7023
  jam();
 
7024
  CreateIndxReq* const req = (CreateIndxReq*)signal->getDataPtrSend();
 
7025
  *req = opPtr.p->m_request;
 
7026
  req->setUserRef(opPtr.p->m_coordinatorRef);
 
7027
  req->setConnectionPtr(opPtr.p->key);
 
7028
  req->setRequestType(opPtr.p->m_requestType);
 
7029
  req->addRequestFlag(opPtr.p->m_requestFlag);
 
7030
  opPtr.p->m_signalCounter = c_aliveNodes;
 
7031
  NodeReceiverGroup rg(DBDICT, c_aliveNodes);
 
7032
  sendSignal(rg, GSN_CREATE_INDX_REQ,
 
7033
      signal, CreateIndxReq::SignalLength, JBB);
 
7034
}
 
7035
 
 
7036
void
 
7037
Dbdict::createIndex_sendReply(Signal* signal, OpCreateIndexPtr opPtr,
 
7038
    bool toUser)
 
7039
{
 
7040
  CreateIndxRef* rep = (CreateIndxRef*)signal->getDataPtrSend();
 
7041
  Uint32 gsn = GSN_CREATE_INDX_CONF;
 
7042
  Uint32 length = CreateIndxConf::InternalLength;
 
7043
  bool sendRef;
 
7044
  if (! toUser) {
 
7045
    sendRef = opPtr.p->hasLastError();
 
7046
    rep->setUserRef(opPtr.p->m_coordinatorRef);
 
7047
    rep->setConnectionPtr(opPtr.p->key);
 
7048
    rep->setRequestType(opPtr.p->m_requestType);
 
7049
    if (opPtr.p->m_requestType == CreateIndxReq::RT_DICT_ABORT)
 
7050
      sendRef = false;
 
7051
  } else {
 
7052
    sendRef = opPtr.p->hasError();
 
7053
    rep->setUserRef(opPtr.p->m_request.getUserRef());
 
7054
    rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
 
7055
    rep->setRequestType(opPtr.p->m_request.getRequestType());
 
7056
    length = CreateIndxConf::SignalLength;
 
7057
  }
 
7058
  rep->setTableId(opPtr.p->m_request.getTableId());
 
7059
  rep->setIndexId(opPtr.p->m_request.getIndexId());
 
7060
  rep->setIndexVersion(opPtr.p->m_request.getIndexVersion());
 
7061
  if (sendRef) {
 
7062
    if (opPtr.p->m_errorNode == 0)
 
7063
      opPtr.p->m_errorNode = getOwnNodeId();
 
7064
    rep->setErrorCode(opPtr.p->m_errorCode);
 
7065
    rep->setErrorLine(opPtr.p->m_errorLine);
 
7066
    rep->setErrorNode(opPtr.p->m_errorNode);
 
7067
    gsn = GSN_CREATE_INDX_REF;
 
7068
    length = CreateIndxRef::SignalLength;
 
7069
  }
 
7070
  sendSignal(rep->getUserRef(), gsn, signal, length, JBB);
 
7071
}
 
7072
 
 
7073
/**
 
7074
 * MODULE: Drop index.
 
7075
 *
 
7076
 * Drop index.  First alters the index offline (i.e.  drops metadata in
 
7077
 * other blocks) and then drops the index table.
 
7078
 */
 
7079
 
 
7080
void
 
7081
Dbdict::execDROP_INDX_REQ(Signal* signal)
 
7082
{
 
7083
  jamEntry();
 
7084
  DropIndxReq* const req = (DropIndxReq*)signal->getDataPtrSend();
 
7085
  OpDropIndexPtr opPtr;
 
7086
 
 
7087
  int err = DropIndxRef::BadRequestType;
 
7088
  const Uint32 senderRef = signal->senderBlockRef();
 
7089
  const DropIndxReq::RequestType requestType = req->getRequestType();
 
7090
  if (requestType == DropIndxReq::RT_USER) {
 
7091
    jam();
 
7092
    if (signal->getLength() == DropIndxReq::SignalLength) {
 
7093
      jam();
 
7094
      DropIndxRef::ErrorCode tmperr = DropIndxRef::NoError;
 
7095
      if (getOwnNodeId() != c_masterNodeId) {
 
7096
        jam();
 
7097
        tmperr = DropIndxRef::NotMaster;
 
7098
      } else if (c_blockState == BS_NODE_RESTART) {
 
7099
        jam();
 
7100
        tmperr = DropIndxRef::BusyWithNR;
 
7101
      } else if (c_blockState != BS_IDLE) {
 
7102
        jam();
 
7103
        tmperr = DropIndxRef::Busy;
 
7104
      }
 
7105
      if (tmperr != DropIndxRef::NoError) {
 
7106
        err = tmperr;
 
7107
        goto error;
 
7108
      }
 
7109
      // forward initial request plus operation key to all
 
7110
      Uint32 indexId= req->getIndexId();
 
7111
      Uint32 indexVersion= req->getIndexVersion();
 
7112
      TableRecordPtr tmp;
 
7113
      int res = getMetaTablePtr(tmp, indexId,  indexVersion);
 
7114
      switch(res){
 
7115
      case MetaData::InvalidArgument:
 
7116
        err = DropIndxRef::IndexNotFound;
 
7117
        goto error;
 
7118
      case MetaData::TableNotFound:
 
7119
      case MetaData::InvalidTableVersion:
 
7120
        err = DropIndxRef::InvalidIndexVersion;
 
7121
        goto error;
 
7122
      }
 
7123
 
 
7124
      if (! tmp.p->isIndex()) {
 
7125
        jam();
 
7126
        err = DropIndxRef::NotAnIndex;
 
7127
        goto error;
 
7128
      }
 
7129
 
 
7130
      if (tmp.p->indexState != TableRecord::IS_ONLINE)
 
7131
        req->addRequestFlag(RequestFlag::RF_FORCE);
 
7132
 
 
7133
      tmp.p->indexState = TableRecord::IS_DROPPING;
 
7134
 
 
7135
      req->setOpKey(++c_opRecordSequence);
 
7136
      NodeReceiverGroup rg(DBDICT, c_aliveNodes);
 
7137
      sendSignal(rg, GSN_DROP_INDX_REQ,
 
7138
          signal, DropIndxReq::SignalLength + 1, JBB);
 
7139
      return;
 
7140
    }
 
7141
    // seize operation record
 
7142
    ndbrequire(signal->getLength() == DropIndxReq::SignalLength + 1);
 
7143
    const Uint32 opKey = req->getOpKey();
 
7144
    OpDropIndex opBusy;
 
7145
    if (! c_opDropIndex.seize(opPtr))
 
7146
      opPtr.p = &opBusy;
 
7147
    opPtr.p->save(req);
 
7148
    opPtr.p->m_coordinatorRef = senderRef;
 
7149
    opPtr.p->m_isMaster = (senderRef == reference());
 
7150
    opPtr.p->key = opKey;
 
7151
    opPtr.p->m_requestType = DropIndxReq::RT_DICT_PREPARE;
 
7152
    if (opPtr.p == &opBusy) {
 
7153
      jam();
 
7154
      opPtr.p->m_errorCode = DropIndxRef::Busy;
 
7155
      opPtr.p->m_errorLine = __LINE__;
 
7156
      dropIndex_sendReply(signal, opPtr, opPtr.p->m_isMaster);
 
7157
      return;
 
7158
    }
 
7159
    c_opDropIndex.add(opPtr);
 
7160
    // master expects to hear from all
 
7161
    if (opPtr.p->m_isMaster)
 
7162
      opPtr.p->m_signalCounter = c_aliveNodes;
 
7163
    dropIndex_slavePrepare(signal, opPtr);
 
7164
    dropIndex_sendReply(signal, opPtr, false);
 
7165
    return;
 
7166
  }
 
7167
  c_opDropIndex.find(opPtr, req->getConnectionPtr());
 
7168
  if (! opPtr.isNull()) {
 
7169
    opPtr.p->m_requestType = requestType;
 
7170
    if (requestType == DropIndxReq::RT_DICT_COMMIT ||
 
7171
        requestType == DropIndxReq::RT_DICT_ABORT) {
 
7172
      jam();
 
7173
      if (requestType == DropIndxReq::RT_DICT_COMMIT)
 
7174
        dropIndex_slaveCommit(signal, opPtr);
 
7175
      else
 
7176
        dropIndex_slaveAbort(signal, opPtr);
 
7177
      dropIndex_sendReply(signal, opPtr, false);
 
7178
      // done in slave
 
7179
      if (! opPtr.p->m_isMaster)
 
7180
        c_opDropIndex.release(opPtr);
 
7181
      return;
 
7182
    }
 
7183
  }
 
7184
error:
 
7185
  jam();
 
7186
  // return to sender
 
7187
  OpDropIndex opBad;
 
7188
  opPtr.p = &opBad;
 
7189
  opPtr.p->save(req);
 
7190
  opPtr.p->m_errorCode = (DropIndxRef::ErrorCode)err;
 
7191
  opPtr.p->m_errorLine = __LINE__;
 
7192
  opPtr.p->m_errorNode = c_masterNodeId;
 
7193
  dropIndex_sendReply(signal, opPtr, true);
 
7194
}
 
7195
 
 
7196
void
 
7197
Dbdict::execDROP_INDX_CONF(Signal* signal)
 
7198
{
 
7199
  jamEntry();
 
7200
  DropIndxConf* conf = (DropIndxConf*)signal->getDataPtrSend();
 
7201
  dropIndex_recvReply(signal, conf, 0);
 
7202
}
 
7203
 
 
7204
void
 
7205
Dbdict::execDROP_INDX_REF(Signal* signal) 
 
7206
{
 
7207
  jamEntry();
 
7208
  DropIndxRef* ref = (DropIndxRef*)signal->getDataPtrSend();
 
7209
  dropIndex_recvReply(signal, ref->getConf(), ref);
 
7210
}
 
7211
 
 
7212
void
 
7213
Dbdict::dropIndex_recvReply(Signal* signal, const DropIndxConf* conf,
 
7214
    const DropIndxRef* ref)
 
7215
{
 
7216
  jam();
 
7217
  const Uint32 senderRef = signal->senderBlockRef();
 
7218
  const DropIndxReq::RequestType requestType = conf->getRequestType();
 
7219
  const Uint32 key = conf->getConnectionPtr();
 
7220
  if (requestType == DropIndxReq::RT_TC) {
 
7221
    jam();
 
7222
    // part of alter index operation
 
7223
    OpAlterIndexPtr opPtr;
 
7224
    c_opAlterIndex.find(opPtr, key);
 
7225
    ndbrequire(! opPtr.isNull());
 
7226
    opPtr.p->setError(ref);
 
7227
    alterIndex_fromDropTc(signal, opPtr);
 
7228
    return;
 
7229
  }
 
7230
  OpDropIndexPtr opPtr;
 
7231
  c_opDropIndex.find(opPtr, key);
 
7232
  ndbrequire(! opPtr.isNull());
 
7233
  ndbrequire(opPtr.p->m_isMaster);
 
7234
  ndbrequire(opPtr.p->m_requestType == requestType);
 
7235
  opPtr.p->setError(ref);
 
7236
  opPtr.p->m_signalCounter.clearWaitingFor(refToNode(senderRef));
 
7237
  if (! opPtr.p->m_signalCounter.done()) {
 
7238
    jam();
 
7239
    return;
 
7240
  }
 
7241
  if (requestType == DropIndxReq::RT_DICT_COMMIT ||
 
7242
      requestType == DropIndxReq::RT_DICT_ABORT) {
 
7243
    jam();
 
7244
    // send reply to user
 
7245
    dropIndex_sendReply(signal, opPtr, true);
 
7246
    c_opDropIndex.release(opPtr);
 
7247
    return;
 
7248
  }
 
7249
  if (opPtr.p->hasError()) {
 
7250
    jam();
 
7251
    opPtr.p->m_requestType = DropIndxReq::RT_DICT_ABORT;
 
7252
    dropIndex_sendSlaveReq(signal, opPtr);
 
7253
    return;
 
7254
  }
 
7255
  if (requestType == DropIndxReq::RT_DICT_PREPARE) {
 
7256
    jam();
 
7257
    // start alter offline
 
7258
    dropIndex_toAlterIndex(signal, opPtr);
 
7259
    return;
 
7260
  }
 
7261
  ndbrequire(false);
 
7262
}
 
7263
 
 
7264
void
 
7265
Dbdict::dropIndex_slavePrepare(Signal* signal, OpDropIndexPtr opPtr)
 
7266
{
 
7267
  jam();
 
7268
  DropIndxReq* const req = &opPtr.p->m_request;
 
7269
  // check index exists
 
7270
  TableRecordPtr indexPtr;
 
7271
  if (! (req->getIndexId() < c_tableRecordPool.getSize())) {
 
7272
    jam();
 
7273
    opPtr.p->m_errorCode = DropIndxRef::IndexNotFound;
 
7274
    opPtr.p->m_errorLine = __LINE__;
 
7275
    return;
 
7276
  }
 
7277
  c_tableRecordPool.getPtr(indexPtr, req->getIndexId());
 
7278
  if (indexPtr.p->tabState != TableRecord::DEFINED) {
 
7279
    jam();
 
7280
    opPtr.p->m_errorCode = DropIndxRef::IndexNotFound;
 
7281
    opPtr.p->m_errorLine = __LINE__;
 
7282
    return;
 
7283
  }
 
7284
  if (! indexPtr.p->isIndex()) {
 
7285
    jam();
 
7286
    opPtr.p->m_errorCode = DropIndxRef::NotAnIndex;
 
7287
    opPtr.p->m_errorLine = __LINE__;
 
7288
    return;
 
7289
  }
 
7290
  // ignore incoming primary table id
 
7291
  req->setTableId(indexPtr.p->primaryTableId);
 
7292
}
 
7293
 
 
7294
void
 
7295
Dbdict::dropIndex_toAlterIndex(Signal* signal, OpDropIndexPtr opPtr)
 
7296
{
 
7297
  jam();
 
7298
  AlterIndxReq* const req = (AlterIndxReq*)signal->getDataPtrSend();
 
7299
  req->setUserRef(reference());
 
7300
  req->setConnectionPtr(opPtr.p->key);
 
7301
  req->setRequestType(AlterIndxReq::RT_DROP_INDEX);
 
7302
  req->addRequestFlag(opPtr.p->m_requestFlag);
 
7303
  req->setTableId(opPtr.p->m_request.getTableId());
 
7304
  req->setIndexId(opPtr.p->m_request.getIndexId());
 
7305
  req->setIndexVersion(opPtr.p->m_request.getIndexVersion());
 
7306
  req->setOnline(false);
 
7307
  sendSignal(reference(), GSN_ALTER_INDX_REQ,
 
7308
      signal, AlterIndxReq::SignalLength, JBB);
 
7309
}
 
7310
 
 
7311
void
 
7312
Dbdict::dropIndex_fromAlterIndex(Signal* signal, OpDropIndexPtr opPtr)
 
7313
{
 
7314
  jam();
 
7315
  if (opPtr.p->hasError()) {
 
7316
    jam();
 
7317
    opPtr.p->m_requestType = DropIndxReq::RT_DICT_ABORT;
 
7318
    dropIndex_sendSlaveReq(signal, opPtr);
 
7319
    return;
 
7320
  }
 
7321
  dropIndex_toDropTable(signal, opPtr);
 
7322
}
 
7323
 
 
7324
void
 
7325
Dbdict::dropIndex_toDropTable(Signal* signal, OpDropIndexPtr opPtr)
 
7326
{
 
7327
  jam();
 
7328
  DropTableReq* const req = (DropTableReq*)signal->getDataPtrSend();
 
7329
  req->senderRef = reference();
 
7330
  req->senderData = opPtr.p->key;
 
7331
  req->tableId = opPtr.p->m_request.getIndexId();
 
7332
  req->tableVersion = opPtr.p->m_request.getIndexVersion();
 
7333
  sendSignal(reference(), GSN_DROP_TABLE_REQ,
 
7334
      signal,DropTableReq::SignalLength, JBB);
 
7335
}
 
7336
 
 
7337
void
 
7338
Dbdict::dropIndex_fromDropTable(Signal* signal, OpDropIndexPtr opPtr)
 
7339
{
 
7340
  jam();
 
7341
  if (opPtr.p->hasError()) {
 
7342
    jam();
 
7343
    opPtr.p->m_requestType = DropIndxReq::RT_DICT_ABORT;
 
7344
    dropIndex_sendSlaveReq(signal, opPtr);
 
7345
    return;
 
7346
  }
 
7347
  opPtr.p->m_requestType = DropIndxReq::RT_DICT_COMMIT;
 
7348
  dropIndex_sendSlaveReq(signal, opPtr);
 
7349
}
 
7350
 
 
7351
void
 
7352
Dbdict::dropIndex_slaveCommit(Signal* signal, OpDropIndexPtr opPtr)
 
7353
{
 
7354
  jam();
 
7355
}
 
7356
 
 
7357
void
 
7358
Dbdict::dropIndex_slaveAbort(Signal* signal, OpDropIndexPtr opPtr)
 
7359
{
 
7360
  jam();
 
7361
  DropIndxReq* const req = &opPtr.p->m_request;
 
7362
  const Uint32 indexId = req->getIndexId();
 
7363
  if (indexId >= c_tableRecordPool.getSize()) {
 
7364
    jam();
 
7365
    return;
 
7366
  }
 
7367
  TableRecordPtr indexPtr;
 
7368
  c_tableRecordPool.getPtr(indexPtr, indexId);
 
7369
  indexPtr.p->indexState = TableRecord::IS_BROKEN;
 
7370
}
 
7371
 
 
7372
void
 
7373
Dbdict::dropIndex_sendSlaveReq(Signal* signal, OpDropIndexPtr opPtr)
 
7374
{
 
7375
  DropIndxReq* const req = (DropIndxReq*)signal->getDataPtrSend();
 
7376
  *req = opPtr.p->m_request;
 
7377
  req->setUserRef(opPtr.p->m_coordinatorRef);
 
7378
  req->setConnectionPtr(opPtr.p->key);
 
7379
  req->setRequestType(opPtr.p->m_requestType);
 
7380
  req->addRequestFlag(opPtr.p->m_requestFlag);
 
7381
  opPtr.p->m_signalCounter = c_aliveNodes;
 
7382
  NodeReceiverGroup rg(DBDICT, c_aliveNodes);
 
7383
  sendSignal(rg, GSN_DROP_INDX_REQ,
 
7384
      signal, DropIndxReq::SignalLength, JBB);
 
7385
}
 
7386
 
 
7387
void
 
7388
Dbdict::dropIndex_sendReply(Signal* signal, OpDropIndexPtr opPtr,
 
7389
    bool toUser)
 
7390
{
 
7391
  DropIndxRef* rep = (DropIndxRef*)signal->getDataPtrSend();
 
7392
  Uint32 gsn = GSN_DROP_INDX_CONF;
 
7393
  Uint32 length = DropIndxConf::InternalLength;
 
7394
  bool sendRef;
 
7395
  if (! toUser) {
 
7396
    sendRef = opPtr.p->hasLastError();
 
7397
    rep->setUserRef(opPtr.p->m_coordinatorRef);
 
7398
    rep->setConnectionPtr(opPtr.p->key);
 
7399
    rep->setRequestType(opPtr.p->m_requestType);
 
7400
    if (opPtr.p->m_requestType == DropIndxReq::RT_DICT_ABORT)
 
7401
      sendRef = false;
 
7402
  } else {
 
7403
    sendRef = opPtr.p->hasError();
 
7404
    rep->setUserRef(opPtr.p->m_request.getUserRef());
 
7405
    rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
 
7406
    rep->setRequestType(opPtr.p->m_request.getRequestType());
 
7407
    length = DropIndxConf::SignalLength;
 
7408
  }
 
7409
  rep->setTableId(opPtr.p->m_request.getTableId());
 
7410
  rep->setIndexId(opPtr.p->m_request.getIndexId());
 
7411
  rep->setIndexVersion(opPtr.p->m_request.getIndexVersion());
 
7412
  if (sendRef) {
 
7413
    if (opPtr.p->m_errorNode == 0)
 
7414
      opPtr.p->m_errorNode = getOwnNodeId();
 
7415
    rep->setErrorCode(opPtr.p->m_errorCode);
 
7416
    rep->setErrorLine(opPtr.p->m_errorLine);
 
7417
    rep->setErrorNode(opPtr.p->m_errorNode);
 
7418
    gsn = GSN_DROP_INDX_REF;
 
7419
    length = DropIndxRef::SignalLength;
 
7420
  }
 
7421
  sendSignal(rep->getUserRef(), gsn, signal, length, JBB);
 
7422
}
 
7423
 
 
7424
 
 
7425
/**
 
7426
 * MODULE: Alter index
 
7427
 *
 
7428
 * Alter index state.  Alter online creates the index in each TC and
 
7429
 * then invokes create trigger and alter trigger protocols to activate
 
7430
 * the 3 triggers.  Alter offline does the opposite.
 
7431
 *
 
7432
 * Request type received in REQ and returned in CONF/REF:
 
7433
 *
 
7434
 * RT_USER - from API to DICT master
 
7435
 * RT_CREATE_INDEX - part of create index operation
 
7436
 * RT_DROP_INDEX - part of drop index operation
 
7437
 * RT_NODERESTART - node restart, activate locally only
 
7438
 * RT_SYSTEMRESTART - system restart, activate and build if not logged
 
7439
 * RT_DICT_PREPARE - prepare participants
 
7440
 * RT_DICT_TC - to local TC via each participant
 
7441
 * RT_DICT_COMMIT - commit in each participant
 
7442
 */
 
7443
 
 
7444
void
 
7445
Dbdict::execALTER_INDX_REQ(Signal* signal)
 
7446
{
 
7447
  jamEntry();
 
7448
  AlterIndxReq* const req = (AlterIndxReq*)signal->getDataPtrSend();
 
7449
  OpAlterIndexPtr opPtr;
 
7450
  const Uint32 senderRef = signal->senderBlockRef();
 
7451
  const AlterIndxReq::RequestType requestType = req->getRequestType();
 
7452
  if (requestType == AlterIndxReq::RT_USER ||
 
7453
      requestType == AlterIndxReq::RT_CREATE_INDEX ||
 
7454
      requestType == AlterIndxReq::RT_DROP_INDEX ||
 
7455
      requestType == AlterIndxReq::RT_NODERESTART ||
 
7456
      requestType == AlterIndxReq::RT_SYSTEMRESTART) {
 
7457
    jam();
 
7458
    const bool isLocal = req->getRequestFlag() & RequestFlag::RF_LOCAL;
 
7459
    NdbNodeBitmask receiverNodes = c_aliveNodes;
 
7460
    if (isLocal) {
 
7461
      receiverNodes.clear();
 
7462
      receiverNodes.set(getOwnNodeId());
 
7463
    }
 
7464
    if (signal->getLength() == AlterIndxReq::SignalLength) {
 
7465
      jam();
 
7466
      if (! isLocal && getOwnNodeId() != c_masterNodeId) {
 
7467
        jam();
 
7468
 
 
7469
        releaseSections(signal);
 
7470
        OpAlterIndex opBad;
 
7471
        opPtr.p = &opBad;
 
7472
        opPtr.p->save(req);
 
7473
        opPtr.p->m_errorCode = AlterIndxRef::NotMaster;
 
7474
        opPtr.p->m_errorLine = __LINE__;
 
7475
        opPtr.p->m_errorNode = c_masterNodeId;
 
7476
        alterIndex_sendReply(signal, opPtr, true);
 
7477
        return;
 
7478
      }
 
7479
      // forward initial request plus operation key to all
 
7480
      req->setOpKey(++c_opRecordSequence);
 
7481
      NodeReceiverGroup rg(DBDICT, receiverNodes);
 
7482
      sendSignal(rg, GSN_ALTER_INDX_REQ,
 
7483
          signal, AlterIndxReq::SignalLength + 1, JBB);
 
7484
      return;
 
7485
    }
 
7486
    // seize operation record
 
7487
    ndbrequire(signal->getLength() == AlterIndxReq::SignalLength + 1);
 
7488
    const Uint32 opKey = req->getOpKey();
 
7489
    OpAlterIndex opBusy;
 
7490
    if (! c_opAlterIndex.seize(opPtr))
 
7491
      opPtr.p = &opBusy;
 
7492
    opPtr.p->save(req);
 
7493
    opPtr.p->m_coordinatorRef = senderRef;
 
7494
    opPtr.p->m_isMaster = (senderRef == reference());
 
7495
    opPtr.p->key = opKey;
 
7496
    opPtr.p->m_requestType = AlterIndxReq::RT_DICT_PREPARE;
 
7497
    if (opPtr.p == &opBusy) {
 
7498
      jam();
 
7499
      opPtr.p->m_errorCode = AlterIndxRef::Busy;
 
7500
      opPtr.p->m_errorLine = __LINE__;
 
7501
      alterIndex_sendReply(signal, opPtr, opPtr.p->m_isMaster);
 
7502
      return;
 
7503
    }
 
7504
    c_opAlterIndex.add(opPtr);
 
7505
    // master expects to hear from all
 
7506
    if (opPtr.p->m_isMaster)
 
7507
      opPtr.p->m_signalCounter = receiverNodes;
 
7508
    // check request in all participants
 
7509
    alterIndex_slavePrepare(signal, opPtr);
 
7510
    alterIndex_sendReply(signal, opPtr, false);
 
7511
    return;
 
7512
  }
 
7513
  c_opAlterIndex.find(opPtr, req->getConnectionPtr());
 
7514
  if (! opPtr.isNull()) {
 
7515
    opPtr.p->m_requestType = requestType;
 
7516
    if (requestType == AlterIndxReq::RT_DICT_TC) {
 
7517
      jam();
 
7518
      if (opPtr.p->m_request.getOnline())
 
7519
        alterIndex_toCreateTc(signal, opPtr);
 
7520
      else
 
7521
        alterIndex_toDropTc(signal, opPtr);
 
7522
      return;
 
7523
    }
 
7524
    if (requestType == AlterIndxReq::RT_DICT_COMMIT ||
 
7525
        requestType == AlterIndxReq::RT_DICT_ABORT) {
 
7526
      jam();
 
7527
      if (requestType == AlterIndxReq::RT_DICT_COMMIT)
 
7528
        alterIndex_slaveCommit(signal, opPtr);
 
7529
      else
 
7530
        alterIndex_slaveAbort(signal, opPtr);
 
7531
      alterIndex_sendReply(signal, opPtr, false);
 
7532
      // done in slave
 
7533
      if (! opPtr.p->m_isMaster)
 
7534
        c_opAlterIndex.release(opPtr);
 
7535
      return;
 
7536
    }
 
7537
  }
 
7538
  jam();
 
7539
  // return to sender
 
7540
  OpAlterIndex opBad;
 
7541
  opPtr.p = &opBad;
 
7542
  opPtr.p->save(req);
 
7543
  opPtr.p->m_errorCode = AlterIndxRef::BadRequestType;
 
7544
  opPtr.p->m_errorLine = __LINE__;
 
7545
  alterIndex_sendReply(signal, opPtr, true);
 
7546
}
 
7547
 
 
7548
void
 
7549
Dbdict::execALTER_INDX_CONF(Signal* signal)
 
7550
{
 
7551
  jamEntry();
 
7552
  ndbrequire(signal->getNoOfSections() == 0);
 
7553
  AlterIndxConf* conf = (AlterIndxConf*)signal->getDataPtrSend();
 
7554
  alterIndex_recvReply(signal, conf, 0);
 
7555
}
 
7556
 
 
7557
void
 
7558
Dbdict::execALTER_INDX_REF(Signal* signal)
 
7559
{
 
7560
  jamEntry();
 
7561
  AlterIndxRef* ref = (AlterIndxRef*)signal->getDataPtrSend();
 
7562
  alterIndex_recvReply(signal, ref->getConf(), ref);
 
7563
}
 
7564
 
 
7565
void
 
7566
Dbdict::alterIndex_recvReply(Signal* signal, const AlterIndxConf* conf,
 
7567
    const AlterIndxRef* ref)
 
7568
{
 
7569
  jam();
 
7570
  const Uint32 senderRef = signal->senderBlockRef();
 
7571
  const AlterIndxReq::RequestType requestType = conf->getRequestType();
 
7572
  const Uint32 key = conf->getConnectionPtr();
 
7573
  if (requestType == AlterIndxReq::RT_CREATE_INDEX) {
 
7574
    jam();
 
7575
    // part of create index operation
 
7576
    OpCreateIndexPtr opPtr;
 
7577
    c_opCreateIndex.find(opPtr, key);
 
7578
    ndbrequire(! opPtr.isNull());
 
7579
    opPtr.p->setError(ref);
 
7580
    createIndex_fromAlterIndex(signal, opPtr);
 
7581
    return;
 
7582
  }
 
7583
  if (requestType == AlterIndxReq::RT_DROP_INDEX) {
 
7584
    jam();
 
7585
    // part of drop index operation
 
7586
    OpDropIndexPtr opPtr;
 
7587
    c_opDropIndex.find(opPtr, key);
 
7588
    ndbrequire(! opPtr.isNull());
 
7589
    opPtr.p->setError(ref);
 
7590
    dropIndex_fromAlterIndex(signal, opPtr);
 
7591
    return;
 
7592
  }
 
7593
  if (requestType == AlterIndxReq::RT_TC ||
 
7594
      requestType == AlterIndxReq::RT_TUX) {
 
7595
    jam();
 
7596
    // part of build index operation
 
7597
    OpBuildIndexPtr opPtr;
 
7598
    c_opBuildIndex.find(opPtr, key);
 
7599
    ndbrequire(! opPtr.isNull());
 
7600
    opPtr.p->setError(ref);
 
7601
    buildIndex_fromOnline(signal, opPtr);
 
7602
    return;
 
7603
  }
 
7604
  if (requestType == AlterIndxReq::RT_NODERESTART) {
 
7605
    jam();
 
7606
    if (ref == 0) {
 
7607
      infoEvent("DICT: index %u activated", (unsigned)key);
 
7608
    } else {
 
7609
      warningEvent("DICT: index %u activation failed: code=%d line=%d",
 
7610
          (unsigned)key,
 
7611
          ref->getErrorCode(), ref->getErrorLine());
 
7612
    }
 
7613
    activateIndexes(signal, key + 1);
 
7614
    return;
 
7615
  }
 
7616
  if (requestType == AlterIndxReq::RT_SYSTEMRESTART) {
 
7617
    jam();
 
7618
    if (ref == 0) {
 
7619
      infoEvent("DICT: index %u activated done", (unsigned)key);
 
7620
    } else {
 
7621
      warningEvent("DICT: index %u activated failed: code=%d line=%d node=%d",
 
7622
          (unsigned)key,
 
7623
          ref->getErrorCode(), ref->getErrorLine(), ref->getErrorNode());
 
7624
    }
 
7625
    activateIndexes(signal, key + 1);
 
7626
    return;
 
7627
  }
 
7628
  OpAlterIndexPtr opPtr;
 
7629
  c_opAlterIndex.find(opPtr, key);
 
7630
  ndbrequire(! opPtr.isNull());
 
7631
  ndbrequire(opPtr.p->m_isMaster);
 
7632
  ndbrequire(opPtr.p->m_requestType == requestType);
 
7633
  opPtr.p->setError(ref);
 
7634
  opPtr.p->m_signalCounter.clearWaitingFor(refToNode(senderRef));
 
7635
  if (! opPtr.p->m_signalCounter.done()) {
 
7636
    jam();
 
7637
    return;
 
7638
  }
 
7639
  if (requestType == AlterIndxReq::RT_DICT_COMMIT ||
 
7640
      requestType == AlterIndxReq::RT_DICT_ABORT) {
 
7641
    jam();
 
7642
    // send reply to user
 
7643
    alterIndex_sendReply(signal, opPtr, true);
 
7644
    c_opAlterIndex.release(opPtr);
 
7645
    return;
 
7646
  }
 
7647
  if (opPtr.p->hasError()) {
 
7648
    jam();
 
7649
    opPtr.p->m_requestType = AlterIndxReq::RT_DICT_ABORT;
 
7650
    alterIndex_sendSlaveReq(signal, opPtr);
 
7651
    return;
 
7652
  }
 
7653
  TableRecordPtr indexPtr;
 
7654
  c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
 
7655
  if (indexPtr.p->isHashIndex()) {
 
7656
    if (requestType == AlterIndxReq::RT_DICT_PREPARE) {
 
7657
      jam();
 
7658
      if (opPtr.p->m_request.getOnline()) {
 
7659
        opPtr.p->m_requestType = AlterIndxReq::RT_DICT_TC;
 
7660
        alterIndex_sendSlaveReq(signal, opPtr);
 
7661
      } else {
 
7662
        // start drop triggers
 
7663
        alterIndex_toDropTrigger(signal, opPtr);
 
7664
      }
 
7665
      return;
 
7666
    }
 
7667
    if (requestType == AlterIndxReq::RT_DICT_TC) {
 
7668
      jam();
 
7669
      if (opPtr.p->m_request.getOnline()) {
 
7670
        // start create triggers
 
7671
        alterIndex_toCreateTrigger(signal, opPtr);
 
7672
      } else {
 
7673
        opPtr.p->m_requestType = AlterIndxReq::RT_DICT_COMMIT;
 
7674
        alterIndex_sendSlaveReq(signal, opPtr);
 
7675
      }
 
7676
      return;
 
7677
    }
 
7678
  }
 
7679
  if (indexPtr.p->isOrderedIndex()) {
 
7680
    if (requestType == AlterIndxReq::RT_DICT_PREPARE) {
 
7681
      jam();
 
7682
      if (opPtr.p->m_request.getOnline()) {
 
7683
        // start create triggers
 
7684
        alterIndex_toCreateTrigger(signal, opPtr);
 
7685
      } else {
 
7686
        // start drop triggers
 
7687
        alterIndex_toDropTrigger(signal, opPtr);
 
7688
      }
 
7689
      return;
 
7690
    }
 
7691
  }
 
7692
  ndbrequire(false);
 
7693
}
 
7694
 
 
7695
void
 
7696
Dbdict::alterIndex_slavePrepare(Signal* signal, OpAlterIndexPtr opPtr)
 
7697
{
 
7698
  jam();
 
7699
  const AlterIndxReq* const req = &opPtr.p->m_request;
 
7700
  if (! (req->getIndexId() < c_tableRecordPool.getSize())) {
 
7701
    jam();
 
7702
    opPtr.p->m_errorCode = AlterIndxRef::Inconsistency;
 
7703
    opPtr.p->m_errorLine = __LINE__;
 
7704
    return;
 
7705
  }
 
7706
  TableRecordPtr indexPtr;
 
7707
  c_tableRecordPool.getPtr(indexPtr, req->getIndexId());
 
7708
  if (indexPtr.p->tabState != TableRecord::DEFINED) {
 
7709
    jam();
 
7710
    opPtr.p->m_errorCode = AlterIndxRef::IndexNotFound;
 
7711
    opPtr.p->m_errorLine = __LINE__;
 
7712
    return;
 
7713
  }
 
7714
  if (! indexPtr.p->isIndex()) {
 
7715
    jam();
 
7716
    opPtr.p->m_errorCode = AlterIndxRef::NotAnIndex;
 
7717
    opPtr.p->m_errorLine = __LINE__;
 
7718
    return;
 
7719
  }
 
7720
  if (req->getOnline())
 
7721
    indexPtr.p->indexState = TableRecord::IS_BUILDING;
 
7722
  else
 
7723
    indexPtr.p->indexState = TableRecord::IS_DROPPING;
 
7724
}
 
7725
 
 
7726
void
 
7727
Dbdict::alterIndex_toCreateTc(Signal* signal, OpAlterIndexPtr opPtr)
 
7728
{
 
7729
  jam();
 
7730
  TableRecordPtr indexPtr;
 
7731
  c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
 
7732
  // request to create index in local TC
 
7733
  CreateIndxReq* const req = (CreateIndxReq*)signal->getDataPtrSend();
 
7734
  req->setUserRef(reference());
 
7735
  req->setConnectionPtr(opPtr.p->key);
 
7736
  req->setRequestType(CreateIndxReq::RT_TC);
 
7737
  req->setIndexType(indexPtr.p->tableType);
 
7738
  req->setTableId(indexPtr.p->primaryTableId);
 
7739
  req->setIndexId(indexPtr.i);
 
7740
  req->setOnline(true);
 
7741
  getIndexAttrList(indexPtr, opPtr.p->m_attrList);
 
7742
  // send
 
7743
  LinearSectionPtr lsPtr[3];
 
7744
  lsPtr[0].p = (Uint32*)&opPtr.p->m_attrList;
 
7745
  lsPtr[0].sz = 1 + opPtr.p->m_attrList.sz;
 
7746
  sendSignal(calcTcBlockRef(getOwnNodeId()), GSN_CREATE_INDX_REQ,
 
7747
      signal, CreateIndxReq::SignalLength, JBB, lsPtr, 1);
 
7748
}
 
7749
 
 
7750
void
 
7751
Dbdict::alterIndex_fromCreateTc(Signal* signal, OpAlterIndexPtr opPtr)
 
7752
{
 
7753
  jam();
 
7754
  // mark created in local TC
 
7755
  if (! opPtr.p->hasLastError()) {
 
7756
    TableRecordPtr indexPtr;
 
7757
    c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
 
7758
    indexPtr.p->indexLocal |= TableRecord::IL_CREATED_TC;
 
7759
  }
 
7760
  // forward CONF or REF to master
 
7761
  ndbrequire(opPtr.p->m_requestType == AlterIndxReq::RT_DICT_TC);
 
7762
  alterIndex_sendReply(signal, opPtr, false);
 
7763
}
 
7764
 
 
7765
void
 
7766
Dbdict::alterIndex_toDropTc(Signal* signal, OpAlterIndexPtr opPtr)
 
7767
{
 
7768
  jam();
 
7769
  TableRecordPtr indexPtr;
 
7770
  c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
 
7771
  // broken index allowed if force
 
7772
  if (! (indexPtr.p->indexLocal & TableRecord::IL_CREATED_TC)) {
 
7773
    jam();
 
7774
    ndbassert(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
 
7775
    alterIndex_sendReply(signal, opPtr, false);
 
7776
    return;
 
7777
  }
 
7778
  // request to drop in local TC
 
7779
  DropIndxReq* const req = (DropIndxReq*)signal->getDataPtrSend();
 
7780
  req->setUserRef(reference());
 
7781
  req->setConnectionPtr(opPtr.p->key);
 
7782
  req->setRequestType(DropIndxReq::RT_TC);
 
7783
  req->setTableId(indexPtr.p->primaryTableId);
 
7784
  req->setIndexId(indexPtr.i);
 
7785
  req->setIndexVersion(indexPtr.p->tableVersion);
 
7786
  // send
 
7787
  sendSignal(calcTcBlockRef(getOwnNodeId()), GSN_DROP_INDX_REQ,
 
7788
      signal, DropIndxReq::SignalLength, JBB);
 
7789
}
 
7790
 
 
7791
void
 
7792
Dbdict::alterIndex_fromDropTc(Signal* signal, OpAlterIndexPtr opPtr)
 
7793
{
 
7794
  jam();
 
7795
  ndbrequire(opPtr.p->m_requestType == AlterIndxReq::RT_DICT_TC);
 
7796
  // mark dropped locally
 
7797
  if (! opPtr.p->hasLastError()) {
 
7798
    TableRecordPtr indexPtr;
 
7799
    c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
 
7800
    indexPtr.p->indexLocal &= ~TableRecord::IL_CREATED_TC;
 
7801
  }
 
7802
  // forward CONF or REF to master
 
7803
  alterIndex_sendReply(signal, opPtr, false);
 
7804
}
 
7805
 
 
7806
void
 
7807
Dbdict::alterIndex_toCreateTrigger(Signal* signal, OpAlterIndexPtr opPtr)
 
7808
{
 
7809
  jam();
 
7810
  TableRecordPtr indexPtr;
 
7811
  c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
 
7812
  // start creation of index triggers
 
7813
  CreateTrigReq* const req = (CreateTrigReq*)signal->getDataPtrSend();
 
7814
  req->setUserRef(reference());
 
7815
  req->setConnectionPtr(opPtr.p->key);
 
7816
  req->setRequestType(CreateTrigReq::RT_ALTER_INDEX);
 
7817
  req->addRequestFlag(opPtr.p->m_requestFlag);
 
7818
  req->setTableId(opPtr.p->m_request.getTableId());
 
7819
  req->setIndexId(opPtr.p->m_request.getIndexId());
 
7820
  req->setTriggerId(RNIL);
 
7821
  req->setTriggerActionTime(TriggerActionTime::TA_AFTER);
 
7822
  req->setMonitorAllAttributes(false);
 
7823
  req->setOnline(true);         // alter online after create
 
7824
  req->setReceiverRef(0);       // implicit for index triggers
 
7825
  getIndexAttrMask(indexPtr, req->getAttributeMask());
 
7826
  // name section
 
7827
  char triggerName[MAX_TAB_NAME_SIZE];
 
7828
  Uint32 buffer[2 + ((MAX_TAB_NAME_SIZE + 3) >> 2)];    // SP string
 
7829
  LinearWriter w(buffer, sizeof(buffer) >> 2);
 
7830
  LinearSectionPtr lsPtr[3];
 
7831
  if (indexPtr.p->isHashIndex()) {
 
7832
    req->setTriggerType(TriggerType::SECONDARY_INDEX);
 
7833
    req->setMonitorReplicas(false);
 
7834
    // insert
 
7835
    if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL)
 
7836
      req->setTriggerId(indexPtr.p->insertTriggerId);
 
7837
    req->setTriggerEvent(TriggerEvent::TE_INSERT);
 
7838
    sprintf(triggerName, "NDB$INDEX_%u_INSERT", opPtr.p->m_request.getIndexId());
 
7839
    w.reset();
 
7840
    w.add(CreateTrigReq::TriggerNameKey, triggerName);
 
7841
    lsPtr[0].p = buffer;
 
7842
    lsPtr[0].sz = w.getWordsUsed();
 
7843
    sendSignal(reference(), GSN_CREATE_TRIG_REQ, 
 
7844
        signal, CreateTrigReq::SignalLength, JBB, lsPtr, 1);
 
7845
    // update
 
7846
    if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL)
 
7847
      req->setTriggerId(indexPtr.p->updateTriggerId);
 
7848
    req->setTriggerEvent(TriggerEvent::TE_UPDATE);
 
7849
    sprintf(triggerName, "NDB$INDEX_%u_UPDATE", opPtr.p->m_request.getIndexId());
 
7850
    w.reset();
 
7851
    w.add(CreateTrigReq::TriggerNameKey, triggerName);
 
7852
    lsPtr[0].p = buffer;
 
7853
    lsPtr[0].sz = w.getWordsUsed();
 
7854
    sendSignal(reference(), GSN_CREATE_TRIG_REQ, 
 
7855
        signal, CreateTrigReq::SignalLength, JBB, lsPtr, 1);
 
7856
    // delete
 
7857
    if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL)
 
7858
      req->setTriggerId(indexPtr.p->deleteTriggerId);
 
7859
    req->setTriggerEvent(TriggerEvent::TE_DELETE);
 
7860
    sprintf(triggerName, "NDB$INDEX_%u_DELETE", opPtr.p->m_request.getIndexId());
 
7861
    w.reset();
 
7862
    w.add(CreateTrigReq::TriggerNameKey, triggerName);
 
7863
    lsPtr[0].p = buffer;
 
7864
    lsPtr[0].sz = w.getWordsUsed();
 
7865
    sendSignal(reference(), GSN_CREATE_TRIG_REQ, 
 
7866
        signal, CreateTrigReq::SignalLength, JBB, lsPtr, 1);
 
7867
    // triggers left to create
 
7868
    opPtr.p->m_triggerCounter = 3;
 
7869
    return;
 
7870
  }
 
7871
  if (indexPtr.p->isOrderedIndex()) {
 
7872
    req->addRequestFlag(RequestFlag::RF_NOTCTRIGGER);
 
7873
    req->setTriggerType(TriggerType::ORDERED_INDEX);
 
7874
    req->setTriggerActionTime(TriggerActionTime::TA_CUSTOM);
 
7875
    req->setMonitorReplicas(true);
 
7876
    // one trigger for 5 events (insert, update, delete, commit, abort)
 
7877
    if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL)
 
7878
      req->setTriggerId(indexPtr.p->customTriggerId);
 
7879
    req->setTriggerEvent(TriggerEvent::TE_CUSTOM);
 
7880
    sprintf(triggerName, "NDB$INDEX_%u_CUSTOM", opPtr.p->m_request.getIndexId());
 
7881
    w.reset();
 
7882
    w.add(CreateTrigReq::TriggerNameKey, triggerName);
 
7883
    lsPtr[0].p = buffer;
 
7884
    lsPtr[0].sz = w.getWordsUsed();
 
7885
    sendSignal(reference(), GSN_CREATE_TRIG_REQ, 
 
7886
        signal, CreateTrigReq::SignalLength, JBB, lsPtr, 1);
 
7887
    // triggers left to create
 
7888
    opPtr.p->m_triggerCounter = 1;
 
7889
    return;
 
7890
  }
 
7891
  ndbrequire(false);
 
7892
}
 
7893
 
 
7894
void
 
7895
Dbdict::alterIndex_fromCreateTrigger(Signal* signal, OpAlterIndexPtr opPtr)
 
7896
{
 
7897
  jam();
 
7898
  ndbrequire(opPtr.p->m_triggerCounter != 0);
 
7899
  if (--opPtr.p->m_triggerCounter != 0) {
 
7900
    jam();
 
7901
    return;
 
7902
  }
 
7903
  if (opPtr.p->hasError()) {
 
7904
    jam();
 
7905
    opPtr.p->m_requestType = AlterIndxReq::RT_DICT_ABORT;
 
7906
    alterIndex_sendSlaveReq(signal, opPtr);
 
7907
    return;
 
7908
  }
 
7909
  if(opPtr.p->m_requestType != AlterIndxReq::RT_SYSTEMRESTART){
 
7910
    // send build request
 
7911
    alterIndex_toBuildIndex(signal, opPtr);
 
7912
    return;
 
7913
  }
 
7914
  
 
7915
  /**
 
7916
   * During system restart, 
 
7917
   *   leave index in activated but not build state.
 
7918
   *
 
7919
   * Build a bit later when REDO has been run
 
7920
   */
 
7921
  alterIndex_sendReply(signal, opPtr, true);
 
7922
}
 
7923
 
 
7924
void
 
7925
Dbdict::alterIndex_toDropTrigger(Signal* signal, OpAlterIndexPtr opPtr)
 
7926
{
 
7927
  jam();
 
7928
  TableRecordPtr indexPtr;
 
7929
  c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
 
7930
  // start drop of index triggers
 
7931
  DropTrigReq* const req = (DropTrigReq*)signal->getDataPtrSend();
 
7932
  req->setUserRef(reference());
 
7933
  req->setConnectionPtr(opPtr.p->key);
 
7934
  req->setRequestType(DropTrigReq::RT_ALTER_INDEX);
 
7935
  req->addRequestFlag(opPtr.p->m_requestFlag);
 
7936
  req->setTableId(opPtr.p->m_request.getTableId());
 
7937
  req->setIndexId(opPtr.p->m_request.getIndexId());
 
7938
  req->setTriggerInfo(0);       // not used
 
7939
  opPtr.p->m_triggerCounter = 0;
 
7940
  if (indexPtr.p->isHashIndex()) {
 
7941
    // insert
 
7942
    req->setTriggerId(indexPtr.p->insertTriggerId);
 
7943
    sendSignal(reference(), GSN_DROP_TRIG_REQ, 
 
7944
        signal, DropTrigReq::SignalLength, JBB);
 
7945
    opPtr.p->m_triggerCounter++;
 
7946
    // update
 
7947
    req->setTriggerId(indexPtr.p->updateTriggerId);
 
7948
    sendSignal(reference(), GSN_DROP_TRIG_REQ, 
 
7949
        signal, DropTrigReq::SignalLength, JBB);
 
7950
    opPtr.p->m_triggerCounter++;
 
7951
    // delete
 
7952
    req->setTriggerId(indexPtr.p->deleteTriggerId);
 
7953
    sendSignal(reference(), GSN_DROP_TRIG_REQ, 
 
7954
        signal, DropTrigReq::SignalLength, JBB);
 
7955
    opPtr.p->m_triggerCounter++;
 
7956
    // build
 
7957
    if (indexPtr.p->buildTriggerId != RNIL) {
 
7958
      req->setTriggerId(indexPtr.p->buildTriggerId);
 
7959
      sendSignal(reference(), GSN_DROP_TRIG_REQ, 
 
7960
          signal, DropTrigReq::SignalLength, JBB);
 
7961
      opPtr.p->m_triggerCounter++;
 
7962
    }
 
7963
    return;
 
7964
  }
 
7965
  if (indexPtr.p->isOrderedIndex()) {
 
7966
    // custom
 
7967
    req->addRequestFlag(RequestFlag::RF_NOTCTRIGGER);
 
7968
    req->setTriggerId(indexPtr.p->customTriggerId);
 
7969
    sendSignal(reference(), GSN_DROP_TRIG_REQ, 
 
7970
        signal, DropTrigReq::SignalLength, JBB);
 
7971
    opPtr.p->m_triggerCounter++;
 
7972
    return;
 
7973
  }
 
7974
  ndbrequire(false);
 
7975
}
 
7976
 
 
7977
void
 
7978
Dbdict::alterIndex_fromDropTrigger(Signal* signal, OpAlterIndexPtr opPtr)
 
7979
{
 
7980
  jam();
 
7981
  ndbrequire(opPtr.p->m_triggerCounter != 0);
 
7982
  if (--opPtr.p->m_triggerCounter != 0) {
 
7983
    jam();
 
7984
    return;
 
7985
  }
 
7986
  // finally drop index in each TC
 
7987
  TableRecordPtr indexPtr;
 
7988
  c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
 
7989
  const bool isHashIndex = indexPtr.p->isHashIndex();
 
7990
  const bool isOrderedIndex = indexPtr.p->isOrderedIndex();
 
7991
  ndbrequire(isHashIndex != isOrderedIndex);    // xor
 
7992
  if (isHashIndex)
 
7993
    opPtr.p->m_requestType = AlterIndxReq::RT_DICT_TC;
 
7994
  if (isOrderedIndex)
 
7995
    opPtr.p->m_requestType = AlterIndxReq::RT_DICT_COMMIT;
 
7996
  alterIndex_sendSlaveReq(signal, opPtr);
 
7997
}
 
7998
 
 
7999
void
 
8000
Dbdict::alterIndex_toBuildIndex(Signal* signal, OpAlterIndexPtr opPtr)
 
8001
{
 
8002
  jam();
 
8003
  // get index and table records
 
8004
  TableRecordPtr indexPtr;
 
8005
  c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
 
8006
  TableRecordPtr tablePtr;
 
8007
  c_tableRecordPool.getPtr(tablePtr, indexPtr.p->primaryTableId);
 
8008
  // build request to self (short signal)
 
8009
  BuildIndxReq* const req = (BuildIndxReq*)signal->getDataPtrSend();
 
8010
  req->setUserRef(reference());
 
8011
  req->setConnectionPtr(opPtr.p->key);
 
8012
  req->setRequestType(BuildIndxReq::RT_ALTER_INDEX);
 
8013
  req->addRequestFlag(opPtr.p->m_requestFlag);
 
8014
  req->setBuildId(0);   // not used
 
8015
  req->setBuildKey(0);  // not used
 
8016
  req->setIndexType(indexPtr.p->tableType);
 
8017
  req->setIndexId(indexPtr.i);
 
8018
  req->setTableId(indexPtr.p->primaryTableId);
 
8019
  req->setParallelism(16);
 
8020
  // send
 
8021
  sendSignal(reference(), GSN_BUILDINDXREQ,
 
8022
      signal, BuildIndxReq::SignalLength, JBB);
 
8023
}
 
8024
 
 
8025
void
 
8026
Dbdict::alterIndex_fromBuildIndex(Signal* signal, OpAlterIndexPtr opPtr)
 
8027
{
 
8028
  jam();
 
8029
  if (opPtr.p->hasError()) {
 
8030
    jam();
 
8031
    opPtr.p->m_requestType = AlterIndxReq::RT_DICT_ABORT;
 
8032
    alterIndex_sendSlaveReq(signal, opPtr);
 
8033
    return;
 
8034
  }
 
8035
  opPtr.p->m_requestType = AlterIndxReq::RT_DICT_COMMIT;
 
8036
  alterIndex_sendSlaveReq(signal, opPtr);
 
8037
}
 
8038
 
 
8039
void
 
8040
Dbdict::alterIndex_slaveCommit(Signal* signal, OpAlterIndexPtr opPtr)
 
8041
{
 
8042
  jam();
 
8043
  // get index record
 
8044
  TableRecordPtr indexPtr;
 
8045
  c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
 
8046
  indexPtr.p->indexState = TableRecord::IS_ONLINE;
 
8047
}
 
8048
 
 
8049
void
 
8050
Dbdict::alterIndex_slaveAbort(Signal* signal, OpAlterIndexPtr opPtr)
 
8051
{
 
8052
  jam();
 
8053
  // find index record
 
8054
  const Uint32 indexId = opPtr.p->m_request.getIndexId();
 
8055
  if (indexId >= c_tableRecordPool.getSize())
 
8056
    return;
 
8057
  TableRecordPtr indexPtr;
 
8058
  c_tableRecordPool.getPtr(indexPtr, indexId);
 
8059
  if (! indexPtr.p->isIndex())
 
8060
    return;
 
8061
  // mark broken
 
8062
  indexPtr.p->indexState = TableRecord::IS_BROKEN;
 
8063
}
 
8064
 
 
8065
void
 
8066
Dbdict::alterIndex_sendSlaveReq(Signal* signal, OpAlterIndexPtr opPtr)
 
8067
{
 
8068
  AlterIndxReq* const req = (AlterIndxReq*)signal->getDataPtrSend();
 
8069
  *req = opPtr.p->m_request;
 
8070
  req->setUserRef(opPtr.p->m_coordinatorRef);
 
8071
  req->setConnectionPtr(opPtr.p->key);
 
8072
  req->setRequestType(opPtr.p->m_requestType);
 
8073
  req->addRequestFlag(opPtr.p->m_requestFlag);
 
8074
  NdbNodeBitmask receiverNodes = c_aliveNodes;
 
8075
  if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL) {
 
8076
    receiverNodes.clear();
 
8077
    receiverNodes.set(getOwnNodeId());
 
8078
  }
 
8079
  opPtr.p->m_signalCounter = receiverNodes;
 
8080
  NodeReceiverGroup rg(DBDICT, receiverNodes);
 
8081
  sendSignal(rg, GSN_ALTER_INDX_REQ,
 
8082
      signal, AlterIndxReq::SignalLength, JBB);
 
8083
}
 
8084
 
 
8085
void
 
8086
Dbdict::alterIndex_sendReply(Signal* signal, OpAlterIndexPtr opPtr,
 
8087
    bool toUser)
 
8088
{
 
8089
  AlterIndxRef* rep = (AlterIndxRef*)signal->getDataPtrSend();
 
8090
  Uint32 gsn = GSN_ALTER_INDX_CONF;
 
8091
  Uint32 length = AlterIndxConf::InternalLength;
 
8092
  bool sendRef;
 
8093
  if (! toUser) {
 
8094
    sendRef = opPtr.p->hasLastError();
 
8095
    rep->setUserRef(opPtr.p->m_coordinatorRef);
 
8096
    rep->setConnectionPtr(opPtr.p->key);
 
8097
    rep->setRequestType(opPtr.p->m_requestType);
 
8098
    if (opPtr.p->m_requestType == AlterIndxReq::RT_DICT_ABORT)
 
8099
      sendRef = false;
 
8100
  } else {
 
8101
    sendRef = opPtr.p->hasError();
 
8102
    rep->setUserRef(opPtr.p->m_request.getUserRef());
 
8103
    rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
 
8104
    rep->setRequestType(opPtr.p->m_request.getRequestType());
 
8105
    length = AlterIndxConf::SignalLength;
 
8106
  }
 
8107
  rep->setTableId(opPtr.p->m_request.getTableId());
 
8108
  rep->setIndexId(opPtr.p->m_request.getIndexId());
 
8109
  if (sendRef) {
 
8110
    if (opPtr.p->m_errorNode == 0)
 
8111
      opPtr.p->m_errorNode = getOwnNodeId();
 
8112
    rep->setErrorCode(opPtr.p->m_errorCode);
 
8113
    rep->setErrorLine(opPtr.p->m_errorLine);
 
8114
    rep->setErrorNode(opPtr.p->m_errorNode);
 
8115
    gsn = GSN_ALTER_INDX_REF;
 
8116
    length = AlterIndxRef::SignalLength;
 
8117
  }
 
8118
  sendSignal(rep->getUserRef(), gsn, signal, length, JBB);
 
8119
}
 
8120
 
 
8121
/**
 
8122
 * MODULE: Build index
 
8123
 *
 
8124
 * Build index or all indexes on a table.  Request type:
 
8125
 *
 
8126
 * RT_USER - normal user request, not yet used
 
8127
 * RT_ALTER_INDEX - from alter index
 
8128
 * RT_SYSTEM_RESTART - 
 
8129
 * RT_DICT_PREPARE - prepare participants
 
8130
 * RT_DICT_TRIX - to participant on way to local TRIX
 
8131
 * RT_DICT_COMMIT - commit in each participant
 
8132
 * RT_DICT_ABORT - abort
 
8133
 * RT_TRIX - to local TRIX
 
8134
 */
 
8135
 
 
8136
void
 
8137
Dbdict::execBUILDINDXREQ(Signal* signal)
 
8138
{
 
8139
  jamEntry();
 
8140
  BuildIndxReq* const req = (BuildIndxReq*)signal->getDataPtrSend();
 
8141
  OpBuildIndexPtr opPtr;
 
8142
  const Uint32 senderRef = signal->senderBlockRef();
 
8143
  const BuildIndxReq::RequestType requestType = req->getRequestType();
 
8144
  if (requestType == BuildIndxReq::RT_USER ||
 
8145
      requestType == BuildIndxReq::RT_ALTER_INDEX ||
 
8146
      requestType == BuildIndxReq::RT_SYSTEMRESTART) {
 
8147
    jam();
 
8148
 
 
8149
    const bool isLocal = req->getRequestFlag() & RequestFlag::RF_LOCAL;
 
8150
    NdbNodeBitmask receiverNodes = c_aliveNodes;
 
8151
    if (isLocal) {
 
8152
      receiverNodes.clear();
 
8153
      receiverNodes.set(getOwnNodeId());
 
8154
    }
 
8155
    
 
8156
    if (signal->getLength() == BuildIndxReq::SignalLength) {
 
8157
      jam();
 
8158
      
 
8159
      if (!isLocal && getOwnNodeId() != c_masterNodeId) {
 
8160
        jam();
 
8161
        
 
8162
        releaseSections(signal);
 
8163
        OpBuildIndex opBad;
 
8164
        opPtr.p = &opBad;
 
8165
        opPtr.p->save(req);
 
8166
        opPtr.p->m_errorCode = BuildIndxRef::NotMaster;
 
8167
        opPtr.p->m_errorLine = __LINE__;
 
8168
        opPtr.p->m_errorNode = c_masterNodeId;
 
8169
        buildIndex_sendReply(signal, opPtr, true);
 
8170
        return;
 
8171
      }
 
8172
      // forward initial request plus operation key to all
 
8173
      req->setOpKey(++c_opRecordSequence);
 
8174
      NodeReceiverGroup rg(DBDICT, receiverNodes);
 
8175
      sendSignal(rg, GSN_BUILDINDXREQ,
 
8176
                 signal, BuildIndxReq::SignalLength + 1, JBB);
 
8177
      return;
 
8178
    }
 
8179
    // seize operation record
 
8180
    ndbrequire(signal->getLength() == BuildIndxReq::SignalLength + 1);
 
8181
    const Uint32 opKey = req->getOpKey();
 
8182
    OpBuildIndex opBusy;
 
8183
    if (! c_opBuildIndex.seize(opPtr))
 
8184
      opPtr.p = &opBusy;
 
8185
    opPtr.p->save(req);
 
8186
    opPtr.p->m_coordinatorRef = senderRef;
 
8187
    opPtr.p->m_isMaster = (senderRef == reference());
 
8188
    opPtr.p->key = opKey;
 
8189
    opPtr.p->m_requestType = BuildIndxReq::RT_DICT_PREPARE;
 
8190
    if (opPtr.p == &opBusy) {
 
8191
      jam();
 
8192
      opPtr.p->m_errorCode = BuildIndxRef::Busy;
 
8193
      opPtr.p->m_errorLine = __LINE__;
 
8194
      buildIndex_sendReply(signal, opPtr, opPtr.p->m_isMaster);
 
8195
      return;
 
8196
    }
 
8197
    c_opBuildIndex.add(opPtr);
 
8198
    // master expects to hear from all
 
8199
    opPtr.p->m_signalCounter = receiverNodes;
 
8200
    buildIndex_sendReply(signal, opPtr, false);
 
8201
    return;
 
8202
  }
 
8203
  c_opBuildIndex.find(opPtr, req->getConnectionPtr());
 
8204
  if (! opPtr.isNull()) {
 
8205
    opPtr.p->m_requestType = requestType;
 
8206
    if (requestType == BuildIndxReq::RT_DICT_TRIX) {
 
8207
      jam();
 
8208
      buildIndex_buildTrix(signal, opPtr);
 
8209
      return;
 
8210
    }
 
8211
    if (requestType == BuildIndxReq::RT_DICT_TC ||
 
8212
        requestType == BuildIndxReq::RT_DICT_TUX) {
 
8213
      jam();
 
8214
      buildIndex_toOnline(signal, opPtr);
 
8215
      return;
 
8216
    }
 
8217
    if (requestType == BuildIndxReq::RT_DICT_COMMIT ||
 
8218
        requestType == BuildIndxReq::RT_DICT_ABORT) {
 
8219
      jam();
 
8220
      buildIndex_sendReply(signal, opPtr, false);
 
8221
      // done in slave
 
8222
      if (! opPtr.p->m_isMaster)
 
8223
        c_opBuildIndex.release(opPtr);
 
8224
      return;
 
8225
    }
 
8226
  }
 
8227
  jam();
 
8228
  // return to sender
 
8229
  OpBuildIndex opBad;
 
8230
  opPtr.p = &opBad;
 
8231
  opPtr.p->save(req);
 
8232
  opPtr.p->m_errorCode = BuildIndxRef::BadRequestType;
 
8233
  opPtr.p->m_errorLine = __LINE__;
 
8234
  buildIndex_sendReply(signal, opPtr, true);
 
8235
}
 
8236
 
 
8237
void
 
8238
Dbdict::execBUILDINDXCONF(Signal* signal)
 
8239
{
 
8240
  jamEntry();
 
8241
  ndbrequire(signal->getNoOfSections() == 0);
 
8242
  BuildIndxConf* conf = (BuildIndxConf*)signal->getDataPtrSend();
 
8243
  buildIndex_recvReply(signal, conf, 0);
 
8244
}
 
8245
 
 
8246
void
 
8247
Dbdict::execBUILDINDXREF(Signal* signal)
 
8248
{
 
8249
  jamEntry();
 
8250
  BuildIndxRef* ref = (BuildIndxRef*)signal->getDataPtrSend();
 
8251
  buildIndex_recvReply(signal, ref->getConf(), ref);
 
8252
}
 
8253
 
 
8254
void
 
8255
Dbdict::buildIndex_recvReply(Signal* signal, const BuildIndxConf* conf,
 
8256
    const BuildIndxRef* ref)
 
8257
{
 
8258
  jam();
 
8259
  const Uint32 senderRef = signal->senderBlockRef();
 
8260
  const BuildIndxReq::RequestType requestType = conf->getRequestType();
 
8261
  const Uint32 key = conf->getConnectionPtr();
 
8262
  if (requestType == BuildIndxReq::RT_ALTER_INDEX) {
 
8263
    jam();
 
8264
    // part of alter index operation
 
8265
    OpAlterIndexPtr opPtr;
 
8266
    c_opAlterIndex.find(opPtr, key);
 
8267
    ndbrequire(! opPtr.isNull());
 
8268
    opPtr.p->setError(ref);
 
8269
    alterIndex_fromBuildIndex(signal, opPtr);
 
8270
    return;
 
8271
  }
 
8272
 
 
8273
  if (requestType == BuildIndxReq::RT_SYSTEMRESTART) {
 
8274
    jam();
 
8275
    if (ref == 0) {
 
8276
      infoEvent("DICT: index %u rebuild done", (unsigned)key);
 
8277
    } else {
 
8278
      warningEvent("DICT: index %u rebuild failed: code=%d line=%d node=%d",
 
8279
                   (unsigned)key, ref->getErrorCode());
 
8280
    }
 
8281
    rebuildIndexes(signal, key + 1);
 
8282
    return;
 
8283
  }
 
8284
 
 
8285
  OpBuildIndexPtr opPtr;
 
8286
  c_opBuildIndex.find(opPtr, key);
 
8287
  ndbrequire(! opPtr.isNull());
 
8288
  opPtr.p->setError(ref);
 
8289
  if (requestType == BuildIndxReq::RT_TRIX) {
 
8290
    jam();
 
8291
    // forward to master
 
8292
    opPtr.p->m_requestType = BuildIndxReq::RT_DICT_TRIX;
 
8293
    buildIndex_sendReply(signal, opPtr, false);
 
8294
    return;
 
8295
  }
 
8296
  ndbrequire(opPtr.p->m_isMaster);
 
8297
  ndbrequire(opPtr.p->m_requestType == requestType);
 
8298
  opPtr.p->m_signalCounter.clearWaitingFor(refToNode(senderRef));
 
8299
  if (! opPtr.p->m_signalCounter.done()) {
 
8300
    jam();
 
8301
    return;
 
8302
  }
 
8303
  if (requestType == BuildIndxReq::RT_DICT_COMMIT ||
 
8304
      requestType == BuildIndxReq::RT_DICT_ABORT) {
 
8305
    jam();
 
8306
    // send reply to user
 
8307
    buildIndex_sendReply(signal, opPtr, true);
 
8308
    c_opBuildIndex.release(opPtr);
 
8309
    return;
 
8310
  }
 
8311
  if (opPtr.p->hasError()) {
 
8312
    jam();
 
8313
    opPtr.p->m_requestType = BuildIndxReq::RT_DICT_ABORT;
 
8314
    buildIndex_sendSlaveReq(signal, opPtr);
 
8315
    return;
 
8316
  }
 
8317
  TableRecordPtr indexPtr;
 
8318
  c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
 
8319
  if (indexPtr.p->isHashIndex()) {
 
8320
    if (requestType == BuildIndxReq::RT_DICT_PREPARE) {
 
8321
      jam();
 
8322
      if (! (opPtr.p->m_requestFlag & RequestFlag::RF_NOBUILD)) {
 
8323
        buildIndex_toCreateConstr(signal, opPtr);
 
8324
      } else {
 
8325
        opPtr.p->m_requestType = BuildIndxReq::RT_DICT_TC;
 
8326
        buildIndex_sendSlaveReq(signal, opPtr);
 
8327
      }
 
8328
      return;
 
8329
    }
 
8330
    if (requestType == BuildIndxReq::RT_DICT_TRIX) {
 
8331
      jam();
 
8332
      ndbrequire(! (opPtr.p->m_requestFlag & RequestFlag::RF_NOBUILD));
 
8333
      buildIndex_toDropConstr(signal, opPtr);
 
8334
      return;
 
8335
    }
 
8336
    if (requestType == BuildIndxReq::RT_DICT_TC) {
 
8337
      jam();
 
8338
      opPtr.p->m_requestType = BuildIndxReq::RT_DICT_COMMIT;
 
8339
      buildIndex_sendSlaveReq(signal, opPtr);
 
8340
      return;
 
8341
    }
 
8342
  }
 
8343
  if (indexPtr.p->isOrderedIndex()) {
 
8344
    if (requestType == BuildIndxReq::RT_DICT_PREPARE) {
 
8345
      jam();
 
8346
      if (! (opPtr.p->m_requestFlag & RequestFlag::RF_NOBUILD)) {
 
8347
        opPtr.p->m_requestType = BuildIndxReq::RT_DICT_TRIX;
 
8348
        buildIndex_sendSlaveReq(signal, opPtr);
 
8349
      } else {
 
8350
        opPtr.p->m_requestType = BuildIndxReq::RT_DICT_TUX;
 
8351
        buildIndex_sendSlaveReq(signal, opPtr);
 
8352
      }
 
8353
      return;
 
8354
    }
 
8355
    if (requestType == BuildIndxReq::RT_DICT_TRIX) {
 
8356
      jam();
 
8357
      ndbrequire(! (opPtr.p->m_requestFlag & RequestFlag::RF_NOBUILD));
 
8358
      opPtr.p->m_requestType = BuildIndxReq::RT_DICT_TUX;
 
8359
      buildIndex_sendSlaveReq(signal, opPtr);
 
8360
      return;
 
8361
    }
 
8362
    if (requestType == BuildIndxReq::RT_DICT_TUX) {
 
8363
      jam();
 
8364
      opPtr.p->m_requestType = BuildIndxReq::RT_DICT_COMMIT;
 
8365
      buildIndex_sendSlaveReq(signal, opPtr);
 
8366
      return;
 
8367
    }
 
8368
  }
 
8369
  ndbrequire(false);
 
8370
 
8371
 
 
8372
void
 
8373
Dbdict::buildIndex_toCreateConstr(Signal* signal, OpBuildIndexPtr opPtr)
 
8374
{
 
8375
  jam();
 
8376
  TableRecordPtr indexPtr;
 
8377
  c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
 
8378
  // request to create constraint trigger
 
8379
  CreateTrigReq* req = (CreateTrigReq*)signal->getDataPtrSend();
 
8380
  req->setUserRef(reference());
 
8381
  req->setConnectionPtr(opPtr.p->key);
 
8382
  req->setRequestType(CreateTrigReq::RT_BUILD_INDEX);
 
8383
  req->addRequestFlag(0);       // none
 
8384
  req->setTableId(indexPtr.i);
 
8385
  req->setIndexId(RNIL);
 
8386
  req->setTriggerId(RNIL);
 
8387
  req->setTriggerType(TriggerType::READ_ONLY_CONSTRAINT);
 
8388
  req->setTriggerActionTime(TriggerActionTime::TA_AFTER);
 
8389
  req->setTriggerEvent(TriggerEvent::TE_UPDATE);
 
8390
  req->setMonitorReplicas(false);
 
8391
  req->setMonitorAllAttributes(false);
 
8392
  req->setOnline(true);         // alter online after create
 
8393
  req->setReceiverRef(0);       // no receiver, REF-ed by TUP
 
8394
  req->getAttributeMask().clear();
 
8395
  // NDB$PK is last attribute
 
8396
  req->getAttributeMask().set(indexPtr.p->noOfAttributes - 1);
 
8397
  // name section
 
8398
  char triggerName[MAX_TAB_NAME_SIZE];
 
8399
  Uint32 buffer[2 + ((MAX_TAB_NAME_SIZE + 3) >> 2)];    // SP string
 
8400
  LinearWriter w(buffer, sizeof(buffer) >> 2);
 
8401
  LinearSectionPtr lsPtr[3];
 
8402
  sprintf(triggerName, "NDB$INDEX_%u_BUILD", indexPtr.i);
 
8403
  w.reset();
 
8404
  w.add(CreateTrigReq::TriggerNameKey, triggerName);
 
8405
  lsPtr[0].p = buffer;
 
8406
  lsPtr[0].sz = w.getWordsUsed();
 
8407
  sendSignal(reference(), GSN_CREATE_TRIG_REQ,
 
8408
      signal, CreateTrigReq::SignalLength, JBB, lsPtr, 1);
 
8409
}
 
8410
 
 
8411
void
 
8412
Dbdict::buildIndex_fromCreateConstr(Signal* signal, OpBuildIndexPtr opPtr)
 
8413
{
 
8414
  jam();
 
8415
  if (opPtr.p->hasError()) {
 
8416
    jam();
 
8417
    opPtr.p->m_requestType = BuildIndxReq::RT_DICT_ABORT;
 
8418
    buildIndex_sendSlaveReq(signal, opPtr);
 
8419
    return;
 
8420
  }
 
8421
  opPtr.p->m_requestType = BuildIndxReq::RT_DICT_TRIX;
 
8422
  buildIndex_sendSlaveReq(signal, opPtr);
 
8423
}
 
8424
 
 
8425
void
 
8426
Dbdict::buildIndex_buildTrix(Signal* signal, OpBuildIndexPtr opPtr)
 
8427
{
 
8428
  jam();
 
8429
  TableRecordPtr indexPtr;
 
8430
  c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
 
8431
  TableRecordPtr tablePtr;
 
8432
  c_tableRecordPool.getPtr(tablePtr, indexPtr.p->primaryTableId);
 
8433
  // build request
 
8434
  BuildIndxReq* const req = (BuildIndxReq*)signal->getDataPtrSend();
 
8435
  req->setUserRef(reference());
 
8436
  req->setConnectionPtr(opPtr.p->key);
 
8437
  req->setRequestType(BuildIndxReq::RT_TRIX);
 
8438
  req->setBuildId(0);   // not yet..
 
8439
  req->setBuildKey(0);  // ..in use
 
8440
  req->setIndexType(indexPtr.p->tableType);
 
8441
  req->setIndexId(indexPtr.i);
 
8442
  req->setTableId(indexPtr.p->primaryTableId);
 
8443
  req->setParallelism(16);
 
8444
  if (indexPtr.p->isHashIndex()) {
 
8445
    jam();
 
8446
    getIndexAttrList(indexPtr, opPtr.p->m_attrList);
 
8447
    getTableKeyList(tablePtr, opPtr.p->m_tableKeyList);
 
8448
    // send
 
8449
    LinearSectionPtr lsPtr[3];
 
8450
    lsPtr[0].sz = opPtr.p->m_attrList.sz;
 
8451
    lsPtr[0].p = opPtr.p->m_attrList.id;
 
8452
    lsPtr[1].sz = opPtr.p->m_tableKeyList.sz;
 
8453
    lsPtr[1].p = opPtr.p->m_tableKeyList.id;
 
8454
    sendSignal(calcTrixBlockRef(getOwnNodeId()), GSN_BUILDINDXREQ,
 
8455
        signal, BuildIndxReq::SignalLength, JBB, lsPtr, 2);
 
8456
    return;
 
8457
  }
 
8458
  if (indexPtr.p->isOrderedIndex()) {
 
8459
    jam();
 
8460
    sendSignal(calcTupBlockRef(getOwnNodeId()), GSN_BUILDINDXREQ,
 
8461
        signal, BuildIndxReq::SignalLength, JBB);
 
8462
    return;
 
8463
  }
 
8464
  ndbrequire(false);
 
8465
}
 
8466
 
 
8467
void
 
8468
Dbdict::buildIndex_toDropConstr(Signal* signal, OpBuildIndexPtr opPtr)
 
8469
{
 
8470
  jam();
 
8471
  TableRecordPtr indexPtr;
 
8472
  c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
 
8473
  // request to drop constraint trigger
 
8474
  DropTrigReq* req = (DropTrigReq*)signal->getDataPtrSend();
 
8475
  req->setUserRef(reference());
 
8476
  req->setConnectionPtr(opPtr.p->key);
 
8477
  req->setRequestType(DropTrigReq::RT_BUILD_INDEX);
 
8478
  req->addRequestFlag(0);       // none
 
8479
  req->setTableId(indexPtr.i);
 
8480
  req->setIndexId(RNIL);
 
8481
  req->setTriggerId(opPtr.p->m_constrTriggerId);
 
8482
  req->setTriggerInfo(0);       // not used
 
8483
  sendSignal(reference(), GSN_DROP_TRIG_REQ,
 
8484
      signal, DropTrigReq::SignalLength, JBB);
 
8485
}
 
8486
 
 
8487
void
 
8488
Dbdict::buildIndex_fromDropConstr(Signal* signal, OpBuildIndexPtr opPtr)
 
8489
{
 
8490
  jam();
 
8491
  if (opPtr.p->hasError()) {
 
8492
    jam();
 
8493
    opPtr.p->m_requestType = BuildIndxReq::RT_DICT_ABORT;
 
8494
    buildIndex_sendSlaveReq(signal, opPtr);
 
8495
    return;
 
8496
  }
 
8497
  opPtr.p->m_requestType = BuildIndxReq::RT_DICT_TC;
 
8498
  buildIndex_sendSlaveReq(signal, opPtr);
 
8499
}
 
8500
 
 
8501
void
 
8502
Dbdict::buildIndex_toOnline(Signal* signal, OpBuildIndexPtr opPtr)
 
8503
{
 
8504
  jam();
 
8505
  TableRecordPtr indexPtr;
 
8506
  c_tableRecordPool.getPtr(indexPtr, opPtr.p->m_request.getIndexId());
 
8507
  TableRecordPtr tablePtr;
 
8508
  c_tableRecordPool.getPtr(tablePtr, indexPtr.p->primaryTableId);
 
8509
  // request to set index online in TC or TUX
 
8510
  AlterIndxReq* const req = (AlterIndxReq*)signal->getDataPtrSend();
 
8511
  req->setUserRef(reference());
 
8512
  req->setConnectionPtr(opPtr.p->key);
 
8513
  if (opPtr.p->m_requestType == BuildIndxReq::RT_DICT_TC) {
 
8514
    jam();
 
8515
    req->setRequestType(AlterIndxReq::RT_TC);
 
8516
  } else if (opPtr.p->m_requestType == BuildIndxReq::RT_DICT_TUX) {
 
8517
    jam();
 
8518
    req->setRequestType(AlterIndxReq::RT_TUX);
 
8519
  } else {
 
8520
    ndbrequire(false);
 
8521
  }
 
8522
  req->setTableId(tablePtr.i);
 
8523
  req->setIndexId(indexPtr.i);
 
8524
  req->setIndexVersion(indexPtr.p->tableVersion);
 
8525
  req->setOnline(true);
 
8526
  BlockReference blockRef = 0;
 
8527
  if (opPtr.p->m_requestType == BuildIndxReq::RT_DICT_TC) {
 
8528
    jam();
 
8529
    blockRef = calcTcBlockRef(getOwnNodeId());
 
8530
  } else if (opPtr.p->m_requestType == BuildIndxReq::RT_DICT_TUX) {
 
8531
    jam();
 
8532
    blockRef = calcTuxBlockRef(getOwnNodeId());
 
8533
  } else {
 
8534
    ndbrequire(false);
 
8535
  }
 
8536
  // send
 
8537
  sendSignal(blockRef, GSN_ALTER_INDX_REQ,
 
8538
      signal, BuildIndxReq::SignalLength, JBB);
 
8539
}
 
8540
 
 
8541
void
 
8542
Dbdict::buildIndex_fromOnline(Signal* signal, OpBuildIndexPtr opPtr)
 
8543
{
 
8544
  jam();
 
8545
  // forward to master
 
8546
  buildIndex_sendReply(signal, opPtr, false);
 
8547
}
 
8548
 
 
8549
void
 
8550
Dbdict::buildIndex_sendSlaveReq(Signal* signal, OpBuildIndexPtr opPtr)
 
8551
{
 
8552
  BuildIndxReq* const req = (BuildIndxReq*)signal->getDataPtrSend();
 
8553
  *req = opPtr.p->m_request;
 
8554
  req->setUserRef(opPtr.p->m_coordinatorRef);
 
8555
  req->setConnectionPtr(opPtr.p->key);
 
8556
  req->setRequestType(opPtr.p->m_requestType);
 
8557
  req->addRequestFlag(opPtr.p->m_requestFlag);
 
8558
  if(opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL) {
 
8559
    jam();
 
8560
    opPtr.p->m_signalCounter.clearWaitingFor();
 
8561
    opPtr.p->m_signalCounter.setWaitingFor(getOwnNodeId());
 
8562
    sendSignal(reference(), GSN_BUILDINDXREQ,
 
8563
               signal, BuildIndxReq::SignalLength, JBB);
 
8564
  } else {
 
8565
    jam();
 
8566
    opPtr.p->m_signalCounter = c_aliveNodes;
 
8567
    NodeReceiverGroup rg(DBDICT, c_aliveNodes);
 
8568
    sendSignal(rg, GSN_BUILDINDXREQ,
 
8569
               signal, BuildIndxReq::SignalLength, JBB);
 
8570
  }
 
8571
}
 
8572
 
 
8573
void
 
8574
Dbdict::buildIndex_sendReply(Signal* signal, OpBuildIndexPtr opPtr,
 
8575
    bool toUser)
 
8576
{
 
8577
  BuildIndxRef* rep = (BuildIndxRef*)signal->getDataPtrSend();
 
8578
  Uint32 gsn = GSN_BUILDINDXCONF;
 
8579
  Uint32 length = BuildIndxConf::InternalLength;
 
8580
  bool sendRef;
 
8581
  if (! toUser) {
 
8582
    sendRef = opPtr.p->hasLastError();
 
8583
    rep->setUserRef(opPtr.p->m_coordinatorRef);
 
8584
    rep->setConnectionPtr(opPtr.p->key);
 
8585
    rep->setRequestType(opPtr.p->m_requestType);
 
8586
    if (opPtr.p->m_requestType == BuildIndxReq::RT_DICT_ABORT)
 
8587
      sendRef = false;
 
8588
  } else {
 
8589
    sendRef = opPtr.p->hasError();
 
8590
    rep->setUserRef(opPtr.p->m_request.getUserRef());
 
8591
    rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
 
8592
    rep->setRequestType(opPtr.p->m_request.getRequestType());
 
8593
    length = BuildIndxConf::SignalLength;
 
8594
  }
 
8595
  rep->setIndexType(opPtr.p->m_request.getIndexType());
 
8596
  rep->setTableId(opPtr.p->m_request.getTableId());
 
8597
  rep->setIndexId(opPtr.p->m_request.getIndexId());
 
8598
  if (sendRef) {
 
8599
    rep->setErrorCode(opPtr.p->m_errorCode);
 
8600
    rep->masterNodeId = opPtr.p->m_errorNode;
 
8601
    gsn = GSN_BUILDINDXREF;
 
8602
    length = BuildIndxRef::SignalLength;
 
8603
  }
 
8604
  sendSignal(rep->getUserRef(), gsn, signal, length, JBB);
 
8605
}
 
8606
 
 
8607
/**
 
8608
 * MODULE: Create trigger
 
8609
 *
 
8610
 * Create trigger in all DICT blocks.  Optionally start alter trigger
 
8611
 * operation to set the trigger online.
 
8612
 *
 
8613
 * Request type received in REQ and returned in CONF/REF:
 
8614
 *
 
8615
 * RT_USER - normal user e.g. BACKUP
 
8616
 * RT_ALTER_INDEX - from alter index online
 
8617
 * RT_DICT_PREPARE - seize operation in each DICT
 
8618
 * RT_DICT_COMMIT - commit create in each DICT
 
8619
 * RT_TC - sending to TC (operation alter trigger)
 
8620
 * RT_LQH - sending to LQH (operation alter trigger)
 
8621
 */
 
8622
 
 
8623
void
 
8624
Dbdict::execCREATE_TRIG_REQ(Signal* signal) 
 
8625
{
 
8626
  jamEntry();
 
8627
  CreateTrigReq* const req = (CreateTrigReq*)signal->getDataPtrSend();
 
8628
  OpCreateTriggerPtr opPtr;
 
8629
  const Uint32 senderRef = signal->senderBlockRef();
 
8630
  const CreateTrigReq::RequestType requestType = req->getRequestType();
 
8631
  if (requestType == CreateTrigReq::RT_USER ||
 
8632
      requestType == CreateTrigReq::RT_ALTER_INDEX ||
 
8633
      requestType == CreateTrigReq::RT_BUILD_INDEX) {
 
8634
    jam();
 
8635
    if (! assembleFragments(signal)) {
 
8636
      jam();
 
8637
      return;
 
8638
    }
 
8639
    const bool isLocal = req->getRequestFlag() & RequestFlag::RF_LOCAL;
 
8640
    NdbNodeBitmask receiverNodes = c_aliveNodes;
 
8641
    if (isLocal) {
 
8642
      receiverNodes.clear();
 
8643
      receiverNodes.set(getOwnNodeId());
 
8644
    }
 
8645
    if (signal->getLength() == CreateTrigReq::SignalLength) {
 
8646
      jam();
 
8647
      if (! isLocal && getOwnNodeId() != c_masterNodeId) {
 
8648
        jam();
 
8649
 
 
8650
        releaseSections(signal);
 
8651
        OpCreateTrigger opBad;
 
8652
        opPtr.p = &opBad;
 
8653
        opPtr.p->save(req);
 
8654
        opPtr.p->m_errorCode = CreateTrigRef::NotMaster;
 
8655
        opPtr.p->m_errorLine = __LINE__;
 
8656
        opPtr.p->m_errorNode = c_masterNodeId;
 
8657
        createTrigger_sendReply(signal,  opPtr, true);
 
8658
        return;
 
8659
      }
 
8660
      // forward initial request plus operation key to all
 
8661
      req->setOpKey(++c_opRecordSequence);
 
8662
      NodeReceiverGroup rg(DBDICT, receiverNodes);
 
8663
      sendSignal(rg, GSN_CREATE_TRIG_REQ,
 
8664
          signal, CreateTrigReq::SignalLength + 1, JBB);
 
8665
      return;
 
8666
    }
 
8667
    // seize operation record
 
8668
    ndbrequire(signal->getLength() == CreateTrigReq::SignalLength + 1);
 
8669
    const Uint32 opKey = req->getOpKey();
 
8670
    OpCreateTrigger opBusy;
 
8671
    if (! c_opCreateTrigger.seize(opPtr))
 
8672
      opPtr.p = &opBusy;
 
8673
    opPtr.p->save(req);
 
8674
    opPtr.p->m_coordinatorRef = senderRef;
 
8675
    opPtr.p->m_isMaster = (senderRef == reference());
 
8676
    opPtr.p->key = opKey;
 
8677
    opPtr.p->m_requestType = CreateTrigReq::RT_DICT_PREPARE;
 
8678
    if (opPtr.p == &opBusy) {
 
8679
      jam();
 
8680
      opPtr.p->m_errorCode = CreateTrigRef::Busy;
 
8681
      opPtr.p->m_errorLine = __LINE__;
 
8682
      releaseSections(signal);
 
8683
      createTrigger_sendReply(signal, opPtr, opPtr.p->m_isMaster);
 
8684
      return;
 
8685
    }
 
8686
    c_opCreateTrigger.add(opPtr);
 
8687
    {
 
8688
      // save name
 
8689
      SegmentedSectionPtr ssPtr;
 
8690
      signal->getSection(ssPtr, CreateTrigReq::TRIGGER_NAME_SECTION);
 
8691
      SimplePropertiesSectionReader ssReader(ssPtr, getSectionSegmentPool());
 
8692
      if (ssReader.getKey() != CreateTrigReq::TriggerNameKey ||
 
8693
          ! ssReader.getString(opPtr.p->m_triggerName)) {
 
8694
        jam();
 
8695
        opPtr.p->m_errorCode = CreateTrigRef::InvalidName;
 
8696
        opPtr.p->m_errorLine = __LINE__;
 
8697
        releaseSections(signal);
 
8698
        createTrigger_sendReply(signal, opPtr, opPtr.p->m_isMaster);
 
8699
        return;
 
8700
      }
 
8701
    }
 
8702
    releaseSections(signal);
 
8703
    {
 
8704
      // check that trigger name is unique
 
8705
      TriggerRecordPtr triggerPtr;
 
8706
      TriggerRecord keyRecord;
 
8707
      strcpy(keyRecord.triggerName, opPtr.p->m_triggerName);
 
8708
      c_triggerRecordHash.find(triggerPtr, keyRecord);
 
8709
      if (triggerPtr.i != RNIL) {
 
8710
        jam();
 
8711
        opPtr.p->m_errorCode = CreateTrigRef::TriggerExists;
 
8712
        opPtr.p->m_errorLine = __LINE__;
 
8713
        createTrigger_sendReply(signal, opPtr, opPtr.p->m_isMaster);
 
8714
        return;
 
8715
      }
 
8716
    }
 
8717
 
 
8718
    // master expects to hear from all
 
8719
    if (opPtr.p->m_isMaster)
 
8720
      opPtr.p->m_signalCounter = receiverNodes;
 
8721
    // check request in all participants
 
8722
    createTrigger_slavePrepare(signal, opPtr);
 
8723
    createTrigger_sendReply(signal, opPtr, false);
 
8724
    return;
 
8725
  }
 
8726
  c_opCreateTrigger.find(opPtr, req->getConnectionPtr());
 
8727
  if (! opPtr.isNull()) {
 
8728
    opPtr.p->m_requestType = requestType;
 
8729
    if (requestType == CreateTrigReq::RT_DICT_CREATE) {
 
8730
      jam();
 
8731
      // master has set trigger id
 
8732
      opPtr.p->m_request.setTriggerId(req->getTriggerId());
 
8733
      createTrigger_slaveCreate(signal, opPtr);
 
8734
      createTrigger_sendReply(signal, opPtr, false);
 
8735
      return;
 
8736
    }
 
8737
    if (requestType == CreateTrigReq::RT_DICT_COMMIT ||
 
8738
        requestType == CreateTrigReq::RT_DICT_ABORT) {
 
8739
      jam();
 
8740
      if (requestType == CreateTrigReq::RT_DICT_COMMIT)
 
8741
        createTrigger_slaveCommit(signal, opPtr);
 
8742
      else
 
8743
        createTrigger_slaveAbort(signal, opPtr);
 
8744
      createTrigger_sendReply(signal, opPtr, false);
 
8745
      // done in slave
 
8746
      if (! opPtr.p->m_isMaster)
 
8747
        c_opCreateTrigger.release(opPtr);
 
8748
      return;
 
8749
    }
 
8750
  }
 
8751
  jam();
 
8752
  // return to sender
 
8753
  releaseSections(signal);
 
8754
  OpCreateTrigger opBad;
 
8755
  opPtr.p = &opBad;
 
8756
  opPtr.p->save(req);
 
8757
  opPtr.p->m_errorCode = CreateTrigRef::BadRequestType;
 
8758
  opPtr.p->m_errorLine = __LINE__;
 
8759
  createTrigger_sendReply(signal,  opPtr, true);
 
8760
}
 
8761
 
 
8762
void
 
8763
Dbdict::execCREATE_TRIG_CONF(Signal* signal) 
 
8764
{
 
8765
  jamEntry();
 
8766
  ndbrequire(signal->getNoOfSections() == 0);
 
8767
  CreateTrigConf* conf = (CreateTrigConf*)signal->getDataPtrSend();
 
8768
  createTrigger_recvReply(signal, conf, 0);
 
8769
}
 
8770
 
 
8771
void
 
8772
Dbdict::execCREATE_TRIG_REF(Signal* signal) 
 
8773
{
 
8774
  jamEntry();
 
8775
  CreateTrigRef* ref = (CreateTrigRef*)signal->getDataPtrSend();
 
8776
  createTrigger_recvReply(signal, ref->getConf(), ref);
 
8777
}
 
8778
 
 
8779
void
 
8780
Dbdict::createTrigger_recvReply(Signal* signal, const CreateTrigConf* conf,
 
8781
    const CreateTrigRef* ref)
 
8782
{
 
8783
  jam();
 
8784
  const Uint32 senderRef = signal->senderBlockRef();
 
8785
  const CreateTrigReq::RequestType requestType = conf->getRequestType();
 
8786
  const Uint32 key = conf->getConnectionPtr();
 
8787
  if (requestType == CreateTrigReq::RT_ALTER_INDEX) {
 
8788
    jam();
 
8789
    // part of alter index operation
 
8790
    OpAlterIndexPtr opPtr;
 
8791
    c_opAlterIndex.find(opPtr, key);
 
8792
    ndbrequire(! opPtr.isNull());
 
8793
    opPtr.p->setError(ref);
 
8794
    alterIndex_fromCreateTrigger(signal, opPtr);
 
8795
    return;
 
8796
  }
 
8797
  if (requestType == CreateTrigReq::RT_BUILD_INDEX) {
 
8798
    jam();
 
8799
    // part of build index operation
 
8800
    OpBuildIndexPtr opPtr;
 
8801
    c_opBuildIndex.find(opPtr, key);
 
8802
    ndbrequire(! opPtr.isNull());
 
8803
    opPtr.p->setError(ref);
 
8804
    // fill in trigger id
 
8805
    opPtr.p->m_constrTriggerId = conf->getTriggerId();
 
8806
    buildIndex_fromCreateConstr(signal, opPtr);
 
8807
    return;
 
8808
  }
 
8809
  if (requestType == CreateTrigReq::RT_TC ||
 
8810
      requestType == CreateTrigReq::RT_LQH) {
 
8811
    jam();
 
8812
    // part of alter trigger operation
 
8813
    OpAlterTriggerPtr opPtr;
 
8814
    c_opAlterTrigger.find(opPtr, key);
 
8815
    ndbrequire(! opPtr.isNull());
 
8816
    opPtr.p->setError(ref);
 
8817
    alterTrigger_fromCreateLocal(signal, opPtr);
 
8818
    return;
 
8819
  }
 
8820
  OpCreateTriggerPtr opPtr;
 
8821
  c_opCreateTrigger.find(opPtr, key);
 
8822
  ndbrequire(! opPtr.isNull());
 
8823
  ndbrequire(opPtr.p->m_isMaster);
 
8824
  ndbrequire(opPtr.p->m_requestType == requestType);
 
8825
  opPtr.p->setError(ref);
 
8826
  opPtr.p->m_signalCounter.clearWaitingFor(refToNode(senderRef));
 
8827
  if (! opPtr.p->m_signalCounter.done()) {
 
8828
    jam();
 
8829
    return;
 
8830
  }
 
8831
  if (requestType == CreateTrigReq::RT_DICT_COMMIT ||
 
8832
      requestType == CreateTrigReq::RT_DICT_ABORT) {
 
8833
    jam();
 
8834
    // send reply to user
 
8835
    createTrigger_sendReply(signal, opPtr, true);
 
8836
    c_opCreateTrigger.release(opPtr);
 
8837
    return;
 
8838
  }
 
8839
  if (opPtr.p->hasError()) {
 
8840
    jam();
 
8841
    opPtr.p->m_requestType = CreateTrigReq::RT_DICT_ABORT;
 
8842
    createTrigger_sendSlaveReq(signal, opPtr);
 
8843
    return;
 
8844
  }
 
8845
  if (requestType == CreateTrigReq::RT_DICT_PREPARE) {
 
8846
    jam();
 
8847
    // seize trigger id in master
 
8848
    createTrigger_masterSeize(signal, opPtr);
 
8849
    if (opPtr.p->hasError()) {
 
8850
      jam();
 
8851
      opPtr.p->m_requestType = CreateTrigReq::RT_DICT_ABORT;
 
8852
      createTrigger_sendSlaveReq(signal, opPtr);
 
8853
      return;
 
8854
    }
 
8855
    opPtr.p->m_requestType = CreateTrigReq::RT_DICT_CREATE;
 
8856
    createTrigger_sendSlaveReq(signal, opPtr);
 
8857
    return;
 
8858
  }
 
8859
  if (requestType == CreateTrigReq::RT_DICT_CREATE) {
 
8860
    jam();
 
8861
    if (opPtr.p->m_request.getOnline()) {
 
8862
      jam();
 
8863
      // start alter online
 
8864
      createTrigger_toAlterTrigger(signal, opPtr);
 
8865
      return;
 
8866
    }
 
8867
    opPtr.p->m_requestType = CreateTrigReq::RT_DICT_COMMIT;
 
8868
    createTrigger_sendSlaveReq(signal, opPtr);
 
8869
    return;
 
8870
  }
 
8871
  ndbrequire(false);
 
8872
}
 
8873
 
 
8874
void
 
8875
Dbdict::createTrigger_slavePrepare(Signal* signal, OpCreateTriggerPtr opPtr)
 
8876
{
 
8877
  jam();
 
8878
  const CreateTrigReq* const req = &opPtr.p->m_request;
 
8879
  // check trigger type
 
8880
  if (req->getRequestType() == CreateTrigReq::RT_USER &&
 
8881
      req->getTriggerType() == TriggerType::SUBSCRIPTION ||
 
8882
      req->getRequestType() == CreateTrigReq::RT_ALTER_INDEX &&
 
8883
      req->getTriggerType() == TriggerType::SECONDARY_INDEX ||
 
8884
      req->getRequestType() == CreateTrigReq::RT_ALTER_INDEX &&
 
8885
      req->getTriggerType() == TriggerType::ORDERED_INDEX ||
 
8886
      req->getRequestType() == CreateTrigReq::RT_BUILD_INDEX &&
 
8887
      req->getTriggerType() == TriggerType::READ_ONLY_CONSTRAINT) {
 
8888
    ;
 
8889
  } else {
 
8890
    jam();
 
8891
    opPtr.p->m_errorCode = CreateTrigRef::UnsupportedTriggerType;
 
8892
    opPtr.p->m_errorLine = __LINE__;
 
8893
    return;
 
8894
  }
 
8895
  // check the table
 
8896
  const Uint32 tableId = req->getTableId();
 
8897
  if (! (tableId < c_tableRecordPool.getSize())) {
 
8898
    jam();
 
8899
    opPtr.p->m_errorCode = CreateTrigRef::InvalidTable;
 
8900
    opPtr.p->m_errorLine = __LINE__;
 
8901
    return;
 
8902
  }
 
8903
  TableRecordPtr tablePtr;
 
8904
  c_tableRecordPool.getPtr(tablePtr, tableId);
 
8905
  if (tablePtr.p->tabState != TableRecord::DEFINED &&
 
8906
      tablePtr.p->tabState != TableRecord::BACKUP_ONGOING) {
 
8907
    jam();
 
8908
    opPtr.p->m_errorCode = CreateTrigRef::InvalidTable;
 
8909
    opPtr.p->m_errorLine = __LINE__;
 
8910
    return;
 
8911
  }
 
8912
}
 
8913
 
 
8914
void
 
8915
Dbdict::createTrigger_masterSeize(Signal* signal, OpCreateTriggerPtr opPtr)
 
8916
{
 
8917
  TriggerRecordPtr triggerPtr;
 
8918
  if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL) {
 
8919
    triggerPtr.i = opPtr.p->m_request.getTriggerId();
 
8920
  } else {
 
8921
    triggerPtr.i = getFreeTriggerRecord();
 
8922
    if (triggerPtr.i == RNIL) {
 
8923
      jam();
 
8924
      opPtr.p->m_errorCode = CreateTrigRef::TooManyTriggers;
 
8925
      opPtr.p->m_errorLine = __LINE__;
 
8926
      return;
 
8927
    }
 
8928
  }
 
8929
  c_triggerRecordPool.getPtr(triggerPtr);
 
8930
  initialiseTriggerRecord(triggerPtr);
 
8931
  triggerPtr.p->triggerState = TriggerRecord::TS_DEFINING;
 
8932
  opPtr.p->m_request.setTriggerId(triggerPtr.i);
 
8933
}
 
8934
 
 
8935
void
 
8936
Dbdict::createTrigger_slaveCreate(Signal* signal, OpCreateTriggerPtr opPtr)
 
8937
{
 
8938
  jam();
 
8939
  const CreateTrigReq* const req = &opPtr.p->m_request;
 
8940
  // get the trigger record
 
8941
  const Uint32 triggerId = req->getTriggerId();
 
8942
  TriggerRecordPtr triggerPtr;
 
8943
  c_triggerRecordPool.getPtr(triggerPtr, triggerId);
 
8944
  initialiseTriggerRecord(triggerPtr);
 
8945
  // fill in trigger data
 
8946
  strcpy(triggerPtr.p->triggerName, opPtr.p->m_triggerName);
 
8947
  triggerPtr.p->triggerId = triggerId;
 
8948
  triggerPtr.p->tableId = req->getTableId();
 
8949
  triggerPtr.p->indexId = RNIL;
 
8950
  triggerPtr.p->triggerType = req->getTriggerType();
 
8951
  triggerPtr.p->triggerActionTime = req->getTriggerActionTime();
 
8952
  triggerPtr.p->triggerEvent = req->getTriggerEvent();
 
8953
  triggerPtr.p->monitorReplicas = req->getMonitorReplicas();
 
8954
  triggerPtr.p->monitorAllAttributes = req->getMonitorAllAttributes();
 
8955
  triggerPtr.p->attributeMask = req->getAttributeMask();
 
8956
  triggerPtr.p->triggerState = TriggerRecord::TS_OFFLINE;
 
8957
  // add to hash table
 
8958
  //  ndbout_c("++++++++++++ Adding trigger id %u, %s", triggerPtr.p->triggerId, triggerPtr.p->triggerName);
 
8959
  c_triggerRecordHash.add(triggerPtr);
 
8960
  if (triggerPtr.p->triggerType == TriggerType::SECONDARY_INDEX ||
 
8961
      triggerPtr.p->triggerType == TriggerType::ORDERED_INDEX) {
 
8962
    jam();
 
8963
    // connect to index record  XXX should be done in caller instead
 
8964
    triggerPtr.p->indexId = req->getIndexId();
 
8965
    TableRecordPtr indexPtr;
 
8966
    c_tableRecordPool.getPtr(indexPtr, triggerPtr.p->indexId);
 
8967
    switch (triggerPtr.p->triggerEvent) {
 
8968
    case TriggerEvent::TE_INSERT:
 
8969
      indexPtr.p->insertTriggerId = triggerPtr.p->triggerId;
 
8970
      break;
 
8971
    case TriggerEvent::TE_UPDATE:
 
8972
      indexPtr.p->updateTriggerId = triggerPtr.p->triggerId;
 
8973
      break;
 
8974
    case TriggerEvent::TE_DELETE:
 
8975
      indexPtr.p->deleteTriggerId = triggerPtr.p->triggerId;
 
8976
      break;
 
8977
    case TriggerEvent::TE_CUSTOM:
 
8978
      indexPtr.p->customTriggerId = triggerPtr.p->triggerId;
 
8979
      break;
 
8980
    default:
 
8981
      ndbrequire(false);
 
8982
      break;
 
8983
    }
 
8984
  }
 
8985
  if (triggerPtr.p->triggerType == TriggerType::READ_ONLY_CONSTRAINT) {
 
8986
    jam();
 
8987
    // connect to index record  XXX should be done in caller instead
 
8988
    triggerPtr.p->indexId = req->getTableId();
 
8989
    TableRecordPtr indexPtr;
 
8990
    c_tableRecordPool.getPtr(indexPtr, triggerPtr.p->indexId);
 
8991
    indexPtr.p->buildTriggerId = triggerPtr.p->triggerId;
 
8992
  }
 
8993
}
 
8994
 
 
8995
void
 
8996
Dbdict::createTrigger_toAlterTrigger(Signal* signal, OpCreateTriggerPtr opPtr)
 
8997
{
 
8998
  jam();
 
8999
  AlterTrigReq* req = (AlterTrigReq*)signal->getDataPtrSend();
 
9000
  req->setUserRef(reference());
 
9001
  req->setConnectionPtr(opPtr.p->key);
 
9002
  req->setRequestType(AlterTrigReq::RT_CREATE_TRIGGER);
 
9003
  req->addRequestFlag(opPtr.p->m_requestFlag);
 
9004
  req->setTableId(opPtr.p->m_request.getTableId());
 
9005
  req->setTriggerId(opPtr.p->m_request.getTriggerId());
 
9006
  req->setTriggerInfo(0);       // not used
 
9007
  req->setOnline(true);
 
9008
  req->setReceiverRef(opPtr.p->m_request.getReceiverRef());
 
9009
  sendSignal(reference(), GSN_ALTER_TRIG_REQ,
 
9010
      signal, AlterTrigReq::SignalLength, JBB);
 
9011
}
 
9012
 
 
9013
void
 
9014
Dbdict::createTrigger_fromAlterTrigger(Signal* signal, OpCreateTriggerPtr opPtr)
 
9015
{
 
9016
  jam();
 
9017
  if (opPtr.p->hasError()) {
 
9018
    jam();
 
9019
    opPtr.p->m_requestType = CreateTrigReq::RT_DICT_ABORT;
 
9020
    createTrigger_sendSlaveReq(signal, opPtr);
 
9021
    return;
 
9022
  }
 
9023
  opPtr.p->m_requestType = CreateTrigReq::RT_DICT_COMMIT;
 
9024
  createTrigger_sendSlaveReq(signal, opPtr);
 
9025
}
 
9026
 
 
9027
void
 
9028
Dbdict::createTrigger_slaveCommit(Signal* signal, OpCreateTriggerPtr opPtr)
 
9029
{
 
9030
  jam();
 
9031
  const CreateTrigReq* const req = &opPtr.p->m_request;
 
9032
  // get the trigger record
 
9033
  const Uint32 triggerId = req->getTriggerId();
 
9034
  TriggerRecordPtr triggerPtr;
 
9035
  c_triggerRecordPool.getPtr(triggerPtr, triggerId);
 
9036
  if (! req->getOnline()) {
 
9037
    triggerPtr.p->triggerState = TriggerRecord::TS_OFFLINE;
 
9038
  } else {
 
9039
    ndbrequire(triggerPtr.p->triggerState == TriggerRecord::TS_ONLINE);
 
9040
  }
 
9041
}
 
9042
 
 
9043
void
 
9044
Dbdict::createTrigger_slaveAbort(Signal* signal, OpCreateTriggerPtr opPtr)
 
9045
{
 
9046
  jam();
 
9047
}
 
9048
 
 
9049
void
 
9050
Dbdict::createTrigger_sendSlaveReq(Signal* signal, OpCreateTriggerPtr opPtr)
 
9051
{
 
9052
  CreateTrigReq* const req = (CreateTrigReq*)signal->getDataPtrSend();
 
9053
  *req = opPtr.p->m_request;
 
9054
  req->setUserRef(opPtr.p->m_coordinatorRef);
 
9055
  req->setConnectionPtr(opPtr.p->key);
 
9056
  req->setRequestType(opPtr.p->m_requestType);
 
9057
  req->addRequestFlag(opPtr.p->m_requestFlag);
 
9058
  NdbNodeBitmask receiverNodes = c_aliveNodes;
 
9059
  if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL) {
 
9060
    receiverNodes.clear();
 
9061
    receiverNodes.set(getOwnNodeId());
 
9062
  }
 
9063
  opPtr.p->m_signalCounter = receiverNodes;
 
9064
  NodeReceiverGroup rg(DBDICT, receiverNodes);
 
9065
  sendSignal(rg, GSN_CREATE_TRIG_REQ,
 
9066
      signal, CreateTrigReq::SignalLength, JBB);
 
9067
}
 
9068
 
 
9069
void
 
9070
Dbdict::createTrigger_sendReply(Signal* signal, OpCreateTriggerPtr opPtr,
 
9071
    bool toUser)
 
9072
{
 
9073
  CreateTrigRef* rep = (CreateTrigRef*)signal->getDataPtrSend();
 
9074
  Uint32 gsn = GSN_CREATE_TRIG_CONF;
 
9075
  Uint32 length = CreateTrigConf::InternalLength;
 
9076
  bool sendRef;
 
9077
  if (! toUser) {
 
9078
    sendRef = opPtr.p->hasLastError();
 
9079
    rep->setUserRef(opPtr.p->m_coordinatorRef);
 
9080
    rep->setConnectionPtr(opPtr.p->key);
 
9081
    rep->setRequestType(opPtr.p->m_requestType);
 
9082
    if (opPtr.p->m_requestType == CreateTrigReq::RT_DICT_ABORT)
 
9083
      sendRef = false;
 
9084
  } else {
 
9085
    sendRef = opPtr.p->hasError();
 
9086
    rep->setUserRef(opPtr.p->m_request.getUserRef());
 
9087
    rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
 
9088
    rep->setRequestType(opPtr.p->m_request.getRequestType());
 
9089
    length = CreateTrigConf::SignalLength;
 
9090
  }
 
9091
  rep->setTableId(opPtr.p->m_request.getTableId());
 
9092
  rep->setIndexId(opPtr.p->m_request.getIndexId());
 
9093
  rep->setTriggerId(opPtr.p->m_request.getTriggerId());
 
9094
  rep->setTriggerInfo(opPtr.p->m_request.getTriggerInfo());
 
9095
  if (sendRef) {
 
9096
    if (opPtr.p->m_errorNode == 0)
 
9097
      opPtr.p->m_errorNode = getOwnNodeId();
 
9098
    rep->setErrorCode(opPtr.p->m_errorCode);
 
9099
    rep->setErrorLine(opPtr.p->m_errorLine);
 
9100
    rep->setErrorNode(opPtr.p->m_errorNode);
 
9101
    gsn = GSN_CREATE_TRIG_REF;
 
9102
    length = CreateTrigRef::SignalLength;
 
9103
  }
 
9104
  sendSignal(rep->getUserRef(), gsn, signal, length, JBB);
 
9105
}
 
9106
 
 
9107
/**
 
9108
 * MODULE: Drop trigger.
 
9109
 */
 
9110
 
 
9111
void
 
9112
Dbdict::execDROP_TRIG_REQ(Signal* signal) 
 
9113
{
 
9114
  jamEntry();
 
9115
  DropTrigReq* const req = (DropTrigReq*)signal->getDataPtrSend();
 
9116
  OpDropTriggerPtr opPtr;
 
9117
  const Uint32 senderRef = signal->senderBlockRef();
 
9118
  const DropTrigReq::RequestType requestType = req->getRequestType();
 
9119
 
 
9120
  if (signal->getNoOfSections() > 0) {
 
9121
    ndbrequire(signal->getNoOfSections() == 1);
 
9122
    jam();
 
9123
    TriggerRecord keyRecord;
 
9124
    OpDropTrigger opTmp;
 
9125
    opPtr.p=&opTmp;
 
9126
 
 
9127
    SegmentedSectionPtr ssPtr;
 
9128
    signal->getSection(ssPtr, DropTrigReq::TRIGGER_NAME_SECTION);
 
9129
    SimplePropertiesSectionReader ssReader(ssPtr, getSectionSegmentPool());
 
9130
    if (ssReader.getKey() != DropTrigReq::TriggerNameKey ||
 
9131
        ! ssReader.getString(keyRecord.triggerName)) {
 
9132
      jam();
 
9133
      opPtr.p->m_errorCode = DropTrigRef::InvalidName;
 
9134
      opPtr.p->m_errorLine = __LINE__;
 
9135
      releaseSections(signal);
 
9136
      dropTrigger_sendReply(signal, opPtr, opPtr.p->m_isMaster);
 
9137
      return;
 
9138
    }
 
9139
    releaseSections(signal);
 
9140
 
 
9141
    TriggerRecordPtr triggerPtr;
 
9142
 
 
9143
    //    ndbout_c("++++++++++++++ Looking for trigger %s", keyRecord.triggerName);
 
9144
    c_triggerRecordHash.find(triggerPtr, keyRecord);
 
9145
    if (triggerPtr.i == RNIL) {
 
9146
      jam();
 
9147
      req->setTriggerId(RNIL);
 
9148
    } else {
 
9149
      jam();
 
9150
      //      ndbout_c("++++++++++ Found trigger %s", triggerPtr.p->triggerName);
 
9151
      req->setTriggerId(triggerPtr.p->triggerId);
 
9152
      req->setTableId(triggerPtr.p->tableId);
 
9153
    }
 
9154
  }
 
9155
  if (requestType == DropTrigReq::RT_USER ||
 
9156
      requestType == DropTrigReq::RT_ALTER_INDEX ||
 
9157
      requestType == DropTrigReq::RT_BUILD_INDEX) {
 
9158
    jam();
 
9159
    if (signal->getLength() == DropTrigReq::SignalLength) {
 
9160
      if (getOwnNodeId() != c_masterNodeId) {
 
9161
        jam();
 
9162
        // forward to DICT master
 
9163
        sendSignal(calcDictBlockRef(c_masterNodeId), GSN_DROP_TRIG_REQ,
 
9164
                   signal, signal->getLength(), JBB);
 
9165
        return;
 
9166
      }
 
9167
      if (!c_triggerRecordPool.findId(req->getTriggerId())) {
 
9168
        jam();
 
9169
        // return to sender
 
9170
        OpDropTrigger opBad;
 
9171
        opPtr.p = &opBad;
 
9172
        opPtr.p->save(req);
 
9173
        if (! (req->getRequestFlag() & RequestFlag::RF_FORCE)) {
 
9174
          opPtr.p->m_errorCode = DropTrigRef::TriggerNotFound;
 
9175
          opPtr.p->m_errorLine = __LINE__;
 
9176
        }
 
9177
        dropTrigger_sendReply(signal,  opPtr, true);
 
9178
        return;
 
9179
      }
 
9180
      // forward initial request plus operation key to all
 
9181
      req->setOpKey(++c_opRecordSequence);
 
9182
      NodeReceiverGroup rg(DBDICT, c_aliveNodes);
 
9183
      sendSignal(rg, GSN_DROP_TRIG_REQ,
 
9184
                 signal, DropTrigReq::SignalLength + 1, JBB);
 
9185
      return;
 
9186
    }
 
9187
    // seize operation record
 
9188
    ndbrequire(signal->getLength() == DropTrigReq::SignalLength + 1);
 
9189
    const Uint32 opKey = req->getOpKey();
 
9190
    OpDropTrigger opBusy;
 
9191
    if (! c_opDropTrigger.seize(opPtr))
 
9192
      opPtr.p = &opBusy;
 
9193
    opPtr.p->save(req);
 
9194
    opPtr.p->m_coordinatorRef = senderRef;
 
9195
    opPtr.p->m_isMaster = (senderRef == reference());
 
9196
    opPtr.p->key = opKey;
 
9197
    opPtr.p->m_requestType = DropTrigReq::RT_DICT_PREPARE;
 
9198
    if (opPtr.p == &opBusy) {
 
9199
      jam();
 
9200
      opPtr.p->m_errorCode = DropTrigRef::Busy;
 
9201
      opPtr.p->m_errorLine = __LINE__;
 
9202
      dropTrigger_sendReply(signal, opPtr, opPtr.p->m_isMaster);
 
9203
      return;
 
9204
    }
 
9205
    c_opDropTrigger.add(opPtr);
 
9206
      // master expects to hear from all
 
9207
    if (opPtr.p->m_isMaster)
 
9208
        opPtr.p->m_signalCounter = c_aliveNodes;
 
9209
    dropTrigger_slavePrepare(signal, opPtr);
 
9210
    dropTrigger_sendReply(signal, opPtr, false);
 
9211
    return;
 
9212
  }
 
9213
  c_opDropTrigger.find(opPtr, req->getConnectionPtr());
 
9214
  if (! opPtr.isNull()) {
 
9215
    opPtr.p->m_requestType = requestType;
 
9216
    if (requestType == DropTrigReq::RT_DICT_COMMIT ||
 
9217
        requestType == DropTrigReq::RT_DICT_ABORT) {
 
9218
      jam();
 
9219
      if (requestType == DropTrigReq::RT_DICT_COMMIT)
 
9220
        dropTrigger_slaveCommit(signal, opPtr);
 
9221
      else
 
9222
        dropTrigger_slaveAbort(signal, opPtr);
 
9223
      dropTrigger_sendReply(signal, opPtr, false);
 
9224
      // done in slave
 
9225
      if (! opPtr.p->m_isMaster)
 
9226
        c_opDropTrigger.release(opPtr);
 
9227
      return;
 
9228
    }
 
9229
  }
 
9230
  jam();
 
9231
  // return to sender
 
9232
  OpDropTrigger opBad;
 
9233
  opPtr.p = &opBad;
 
9234
  opPtr.p->save(req);
 
9235
  opPtr.p->m_errorCode = DropTrigRef::BadRequestType;
 
9236
  opPtr.p->m_errorLine = __LINE__;
 
9237
  dropTrigger_sendReply(signal,  opPtr, true);
 
9238
}
 
9239
 
 
9240
void
 
9241
Dbdict::execDROP_TRIG_CONF(Signal* signal) 
 
9242
{
 
9243
  jamEntry();
 
9244
  DropTrigConf* conf = (DropTrigConf*)signal->getDataPtrSend();
 
9245
  dropTrigger_recvReply(signal, conf, 0);
 
9246
}
 
9247
 
 
9248
void
 
9249
Dbdict::execDROP_TRIG_REF(Signal* signal) 
 
9250
{
 
9251
  jamEntry();
 
9252
  DropTrigRef* ref = (DropTrigRef*)signal->getDataPtrSend();
 
9253
  dropTrigger_recvReply(signal, ref->getConf(), ref);
 
9254
}
 
9255
 
 
9256
void
 
9257
Dbdict::dropTrigger_recvReply(Signal* signal, const DropTrigConf* conf,
 
9258
    const DropTrigRef* ref)
 
9259
{
 
9260
  jam();
 
9261
  const Uint32 senderRef = signal->senderBlockRef();
 
9262
  const DropTrigReq::RequestType requestType = conf->getRequestType();
 
9263
  const Uint32 key = conf->getConnectionPtr();
 
9264
  if (requestType == DropTrigReq::RT_ALTER_INDEX) {
 
9265
    jam();
 
9266
    // part of alter index operation
 
9267
    OpAlterIndexPtr opPtr;
 
9268
    c_opAlterIndex.find(opPtr, key);
 
9269
    ndbrequire(! opPtr.isNull());
 
9270
    opPtr.p->setError(ref);
 
9271
    alterIndex_fromDropTrigger(signal, opPtr);
 
9272
    return;
 
9273
  }
 
9274
  if (requestType == DropTrigReq::RT_BUILD_INDEX) {
 
9275
    jam();
 
9276
    // part of build index operation
 
9277
    OpBuildIndexPtr opPtr;
 
9278
    c_opBuildIndex.find(opPtr, key);
 
9279
    ndbrequire(! opPtr.isNull());
 
9280
    opPtr.p->setError(ref);
 
9281
    buildIndex_fromDropConstr(signal, opPtr);
 
9282
    return;
 
9283
  }
 
9284
  if (requestType == DropTrigReq::RT_TC ||
 
9285
      requestType == DropTrigReq::RT_LQH) {
 
9286
    jam();
 
9287
    // part of alter trigger operation
 
9288
    OpAlterTriggerPtr opPtr;
 
9289
    c_opAlterTrigger.find(opPtr, key);
 
9290
    ndbrequire(! opPtr.isNull());
 
9291
    opPtr.p->setError(ref);
 
9292
    alterTrigger_fromDropLocal(signal, opPtr);
 
9293
    return;
 
9294
  }
 
9295
  OpDropTriggerPtr opPtr;
 
9296
  c_opDropTrigger.find(opPtr, key);
 
9297
  ndbrequire(! opPtr.isNull());
 
9298
  ndbrequire(opPtr.p->m_isMaster);
 
9299
  ndbrequire(opPtr.p->m_requestType == requestType);
 
9300
  opPtr.p->setError(ref);
 
9301
  opPtr.p->m_signalCounter.clearWaitingFor(refToNode(senderRef));
 
9302
  if (! opPtr.p->m_signalCounter.done()) {
 
9303
    jam();
 
9304
    return;
 
9305
  }
 
9306
  if (requestType == DropTrigReq::RT_DICT_COMMIT ||
 
9307
      requestType == DropTrigReq::RT_DICT_ABORT) {
 
9308
    jam();
 
9309
    // send reply to user
 
9310
    dropTrigger_sendReply(signal, opPtr, true);
 
9311
    c_opDropTrigger.release(opPtr);
 
9312
    return;
 
9313
  }
 
9314
  if (opPtr.p->hasError()) {
 
9315
    jam();
 
9316
    opPtr.p->m_requestType = DropTrigReq::RT_DICT_ABORT;
 
9317
    dropTrigger_sendSlaveReq(signal, opPtr);
 
9318
    return;
 
9319
  }
 
9320
  if (requestType == DropTrigReq::RT_DICT_PREPARE) {
 
9321
    jam();
 
9322
    // start alter offline
 
9323
    dropTrigger_toAlterTrigger(signal, opPtr);
 
9324
    return;
 
9325
  }
 
9326
  ndbrequire(false);
 
9327
}
 
9328
 
 
9329
void
 
9330
Dbdict::dropTrigger_slavePrepare(Signal* signal, OpDropTriggerPtr opPtr)
 
9331
{
 
9332
  jam();
 
9333
}
 
9334
 
 
9335
void
 
9336
Dbdict::dropTrigger_toAlterTrigger(Signal* signal, OpDropTriggerPtr opPtr)
 
9337
{
 
9338
  jam();
 
9339
  AlterTrigReq* req = (AlterTrigReq*)signal->getDataPtrSend();
 
9340
  req->setUserRef(reference());
 
9341
  req->setConnectionPtr(opPtr.p->key);
 
9342
  req->setRequestType(AlterTrigReq::RT_DROP_TRIGGER);
 
9343
  req->addRequestFlag(opPtr.p->m_requestFlag);
 
9344
  req->setTableId(opPtr.p->m_request.getTableId());
 
9345
  req->setTriggerId(opPtr.p->m_request.getTriggerId());
 
9346
  req->setTriggerInfo(0);       // not used
 
9347
  req->setOnline(false);
 
9348
  req->setReceiverRef(0);
 
9349
  sendSignal(reference(), GSN_ALTER_TRIG_REQ,
 
9350
      signal, AlterTrigReq::SignalLength, JBB);
 
9351
}
 
9352
 
 
9353
void
 
9354
Dbdict::dropTrigger_fromAlterTrigger(Signal* signal, OpDropTriggerPtr opPtr)
 
9355
{
 
9356
  jam();
 
9357
  // remove in all
 
9358
  opPtr.p->m_requestType = DropTrigReq::RT_DICT_COMMIT;
 
9359
  dropTrigger_sendSlaveReq(signal, opPtr);
 
9360
}
 
9361
 
 
9362
void
 
9363
Dbdict::dropTrigger_sendSlaveReq(Signal* signal, OpDropTriggerPtr opPtr)
 
9364
{
 
9365
  DropTrigReq* const req = (DropTrigReq*)signal->getDataPtrSend();
 
9366
  *req = opPtr.p->m_request;
 
9367
  req->setUserRef(opPtr.p->m_coordinatorRef);
 
9368
  req->setConnectionPtr(opPtr.p->key);
 
9369
  req->setRequestType(opPtr.p->m_requestType);
 
9370
  req->addRequestFlag(opPtr.p->m_requestFlag);
 
9371
  opPtr.p->m_signalCounter = c_aliveNodes;
 
9372
  NodeReceiverGroup rg(DBDICT, c_aliveNodes);
 
9373
  sendSignal(rg, GSN_DROP_TRIG_REQ,
 
9374
      signal, DropTrigReq::SignalLength, JBB);
 
9375
}
 
9376
 
 
9377
void
 
9378
Dbdict::dropTrigger_slaveCommit(Signal* signal, OpDropTriggerPtr opPtr)
 
9379
{
 
9380
  jam();
 
9381
  const DropTrigReq* const req = &opPtr.p->m_request;
 
9382
  // get trigger record
 
9383
  const Uint32 triggerId = req->getTriggerId();
 
9384
  TriggerRecordPtr triggerPtr;
 
9385
  c_triggerRecordPool.getPtr(triggerPtr, triggerId);
 
9386
  if (triggerPtr.p->triggerType == TriggerType::SECONDARY_INDEX ||
 
9387
      triggerPtr.p->triggerType == TriggerType::ORDERED_INDEX) {
 
9388
    jam();
 
9389
    // disconnect from index if index trigger  XXX move to drop index
 
9390
    triggerPtr.p->indexId = req->getIndexId();
 
9391
    TableRecordPtr indexPtr;
 
9392
    c_tableRecordPool.getPtr(indexPtr, triggerPtr.p->indexId);
 
9393
    ndbrequire(! indexPtr.isNull());
 
9394
    switch (triggerPtr.p->triggerEvent) {
 
9395
    case TriggerEvent::TE_INSERT:
 
9396
      indexPtr.p->insertTriggerId = RNIL;
 
9397
      break;
 
9398
    case TriggerEvent::TE_UPDATE:
 
9399
      indexPtr.p->updateTriggerId = RNIL;
 
9400
      break;
 
9401
    case TriggerEvent::TE_DELETE:
 
9402
      indexPtr.p->deleteTriggerId = RNIL;
 
9403
      break;
 
9404
    case TriggerEvent::TE_CUSTOM:
 
9405
      indexPtr.p->customTriggerId = RNIL;
 
9406
      break;
 
9407
    default:
 
9408
      ndbrequire(false);
 
9409
      break;
 
9410
    }
 
9411
  }
 
9412
  if (triggerPtr.p->triggerType == TriggerType::READ_ONLY_CONSTRAINT) {
 
9413
    jam();
 
9414
    // disconnect from index record  XXX should be done in caller instead
 
9415
    triggerPtr.p->indexId = req->getTableId();
 
9416
    TableRecordPtr indexPtr;
 
9417
    c_tableRecordPool.getPtr(indexPtr, triggerPtr.p->indexId);
 
9418
    indexPtr.p->buildTriggerId = RNIL;
 
9419
  }
 
9420
  // remove trigger
 
9421
  //  ndbout_c("++++++++++++ Removing trigger id %u, %s", triggerPtr.p->triggerId, triggerPtr.p->triggerName);
 
9422
  c_triggerRecordHash.remove(triggerPtr);
 
9423
  triggerPtr.p->triggerState = TriggerRecord::TS_NOT_DEFINED;
 
9424
}
 
9425
 
 
9426
void
 
9427
Dbdict::dropTrigger_slaveAbort(Signal* signal, OpDropTriggerPtr opPtr)
 
9428
{
 
9429
  jam();
 
9430
}
 
9431
 
 
9432
void
 
9433
Dbdict::dropTrigger_sendReply(Signal* signal, OpDropTriggerPtr opPtr,
 
9434
    bool toUser)
 
9435
{
 
9436
  DropTrigRef* rep = (DropTrigRef*)signal->getDataPtrSend();
 
9437
  Uint32 gsn = GSN_DROP_TRIG_CONF;
 
9438
  Uint32 length = DropTrigConf::InternalLength;
 
9439
  bool sendRef;
 
9440
  if (! toUser) {
 
9441
    sendRef = opPtr.p->hasLastError();
 
9442
    rep->setUserRef(opPtr.p->m_coordinatorRef);
 
9443
    rep->setConnectionPtr(opPtr.p->key);
 
9444
    rep->setRequestType(opPtr.p->m_requestType);
 
9445
    if (opPtr.p->m_requestType == DropTrigReq::RT_DICT_ABORT)
 
9446
      sendRef = false;
 
9447
  } else {
 
9448
    sendRef = opPtr.p->hasError();
 
9449
    rep->setUserRef(opPtr.p->m_request.getUserRef());
 
9450
    rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
 
9451
    rep->setRequestType(opPtr.p->m_request.getRequestType());
 
9452
    length = DropTrigConf::SignalLength;
 
9453
  }
 
9454
  rep->setTableId(opPtr.p->m_request.getTableId());
 
9455
  rep->setIndexId(opPtr.p->m_request.getIndexId());
 
9456
  rep->setTriggerId(opPtr.p->m_request.getTriggerId());
 
9457
  if (sendRef) {
 
9458
    if (opPtr.p->m_errorNode == 0)
 
9459
      opPtr.p->m_errorNode = getOwnNodeId();
 
9460
    rep->setErrorCode(opPtr.p->m_errorCode);
 
9461
    rep->setErrorLine(opPtr.p->m_errorLine);
 
9462
    rep->setErrorNode(opPtr.p->m_errorNode);
 
9463
    gsn = GSN_DROP_TRIG_REF;
 
9464
    length = CreateTrigRef::SignalLength;
 
9465
  }
 
9466
  sendSignal(rep->getUserRef(), gsn, signal, length, JBB);
 
9467
}
 
9468
 
 
9469
/**
 
9470
 * MODULE: Alter trigger.
 
9471
 *
 
9472
 * Alter trigger state.  Alter online creates the trigger first in all
 
9473
 * TC (if index trigger) and then in all LQH-TUP.
 
9474
 *
 
9475
 * Request type received in REQ and returned in CONF/REF:
 
9476
 *
 
9477
 * RT_USER - normal user e.g. BACKUP
 
9478
 * RT_CREATE_TRIGGER - from create trigger
 
9479
 * RT_DROP_TRIGGER - from drop trigger
 
9480
 * RT_DICT_PREPARE - seize operations and check request
 
9481
 * RT_DICT_TC - master to each DICT on way to TC
 
9482
 * RT_DICT_LQH - master to each DICT on way to LQH-TUP
 
9483
 * RT_DICT_COMMIT - commit state change in each DICT (no reply)
 
9484
 */
 
9485
 
 
9486
void
 
9487
Dbdict::execALTER_TRIG_REQ(Signal* signal) 
 
9488
{
 
9489
  jamEntry();
 
9490
  AlterTrigReq* const req = (AlterTrigReq*)signal->getDataPtrSend();
 
9491
  OpAlterTriggerPtr opPtr;
 
9492
  const Uint32 senderRef = signal->senderBlockRef();
 
9493
  const AlterTrigReq::RequestType requestType = req->getRequestType();
 
9494
  if (requestType == AlterTrigReq::RT_USER ||
 
9495
      requestType == AlterTrigReq::RT_CREATE_TRIGGER ||
 
9496
      requestType == AlterTrigReq::RT_DROP_TRIGGER) {
 
9497
    jam();
 
9498
    const bool isLocal = req->getRequestFlag() & RequestFlag::RF_LOCAL;
 
9499
    NdbNodeBitmask receiverNodes = c_aliveNodes;
 
9500
    if (isLocal) {
 
9501
      receiverNodes.clear();
 
9502
      receiverNodes.set(getOwnNodeId());
 
9503
    }
 
9504
    if (signal->getLength() == AlterTrigReq::SignalLength) {
 
9505
      jam();
 
9506
      if (! isLocal && getOwnNodeId() != c_masterNodeId) {
 
9507
        jam();
 
9508
        // forward to DICT master
 
9509
        sendSignal(calcDictBlockRef(c_masterNodeId), GSN_ALTER_TRIG_REQ,
 
9510
            signal, AlterTrigReq::SignalLength, JBB);
 
9511
        return;
 
9512
      }
 
9513
      // forward initial request plus operation key to all
 
9514
      req->setOpKey(++c_opRecordSequence);
 
9515
      NodeReceiverGroup rg(DBDICT, receiverNodes);
 
9516
      sendSignal(rg, GSN_ALTER_TRIG_REQ,
 
9517
          signal, AlterTrigReq::SignalLength + 1, JBB);
 
9518
      return;
 
9519
    }
 
9520
    // seize operation record
 
9521
    ndbrequire(signal->getLength() == AlterTrigReq::SignalLength + 1);
 
9522
    const Uint32 opKey = req->getOpKey();
 
9523
    OpAlterTrigger opBusy;
 
9524
    if (! c_opAlterTrigger.seize(opPtr))
 
9525
      opPtr.p = &opBusy;
 
9526
    opPtr.p->save(req);
 
9527
    opPtr.p->m_coordinatorRef = senderRef;
 
9528
    opPtr.p->m_isMaster = (senderRef == reference());
 
9529
    opPtr.p->key = opKey;
 
9530
    opPtr.p->m_requestType = AlterTrigReq::RT_DICT_PREPARE;
 
9531
    if (opPtr.p == &opBusy) {
 
9532
      jam();
 
9533
      opPtr.p->m_errorCode = AlterTrigRef::Busy;
 
9534
      opPtr.p->m_errorLine = __LINE__;
 
9535
      alterTrigger_sendReply(signal, opPtr, opPtr.p->m_isMaster);
 
9536
      return;
 
9537
    }
 
9538
    c_opAlterTrigger.add(opPtr);
 
9539
    // master expects to hear from all
 
9540
    if (opPtr.p->m_isMaster) {
 
9541
      opPtr.p->m_nodes = receiverNodes;
 
9542
      opPtr.p->m_signalCounter = receiverNodes;
 
9543
    }
 
9544
    alterTrigger_slavePrepare(signal, opPtr);
 
9545
    alterTrigger_sendReply(signal, opPtr, false);
 
9546
    return;
 
9547
  }
 
9548
  c_opAlterTrigger.find(opPtr, req->getConnectionPtr());
 
9549
  if (! opPtr.isNull()) {
 
9550
    opPtr.p->m_requestType = requestType;
 
9551
    if (requestType == AlterTrigReq::RT_DICT_TC ||
 
9552
        requestType == AlterTrigReq::RT_DICT_LQH) {
 
9553
      jam();
 
9554
      if (req->getOnline())
 
9555
        alterTrigger_toCreateLocal(signal, opPtr);
 
9556
      else
 
9557
        alterTrigger_toDropLocal(signal, opPtr);
 
9558
      return;
 
9559
    }
 
9560
    if (requestType == AlterTrigReq::RT_DICT_COMMIT ||
 
9561
        requestType == AlterTrigReq::RT_DICT_ABORT) {
 
9562
      jam();
 
9563
      if (requestType == AlterTrigReq::RT_DICT_COMMIT)
 
9564
        alterTrigger_slaveCommit(signal, opPtr);
 
9565
      else
 
9566
        alterTrigger_slaveAbort(signal, opPtr);
 
9567
      alterTrigger_sendReply(signal, opPtr, false);
 
9568
      // done in slave
 
9569
      if (! opPtr.p->m_isMaster)
 
9570
        c_opAlterTrigger.release(opPtr);
 
9571
      return;
 
9572
    }
 
9573
  }
 
9574
  jam();
 
9575
  // return to sender
 
9576
  OpAlterTrigger opBad;
 
9577
  opPtr.p = &opBad;
 
9578
  opPtr.p->save(req);
 
9579
  opPtr.p->m_errorCode = AlterTrigRef::BadRequestType;
 
9580
  opPtr.p->m_errorLine = __LINE__;
 
9581
  alterTrigger_sendReply(signal, opPtr, true);
 
9582
  return;
 
9583
}
 
9584
 
 
9585
void
 
9586
Dbdict::execALTER_TRIG_CONF(Signal* signal) 
 
9587
{
 
9588
  jamEntry();
 
9589
  AlterTrigConf* conf = (AlterTrigConf*)signal->getDataPtrSend();
 
9590
  alterTrigger_recvReply(signal, conf, 0);
 
9591
}
 
9592
 
 
9593
void
 
9594
Dbdict::execALTER_TRIG_REF(Signal* signal) 
 
9595
{
 
9596
  jamEntry();
 
9597
  AlterTrigRef* ref = (AlterTrigRef*)signal->getDataPtrSend();
 
9598
  alterTrigger_recvReply(signal, ref->getConf(), ref);
 
9599
}
 
9600
 
 
9601
void
 
9602
Dbdict::alterTrigger_recvReply(Signal* signal, const AlterTrigConf* conf,
 
9603
    const AlterTrigRef* ref)
 
9604
{
 
9605
  jam();
 
9606
  const Uint32 senderRef = signal->senderBlockRef();
 
9607
  const AlterTrigReq::RequestType requestType = conf->getRequestType();
 
9608
  const Uint32 key = conf->getConnectionPtr();
 
9609
  if (requestType == AlterTrigReq::RT_CREATE_TRIGGER) {
 
9610
    jam();
 
9611
    // part of create trigger operation
 
9612
    OpCreateTriggerPtr opPtr;
 
9613
    c_opCreateTrigger.find(opPtr, key);
 
9614
    ndbrequire(! opPtr.isNull());
 
9615
    opPtr.p->setError(ref);
 
9616
    createTrigger_fromAlterTrigger(signal, opPtr);
 
9617
    return;
 
9618
  }
 
9619
  if (requestType == AlterTrigReq::RT_DROP_TRIGGER) {
 
9620
    jam();
 
9621
    // part of drop trigger operation
 
9622
    OpDropTriggerPtr opPtr;
 
9623
    c_opDropTrigger.find(opPtr, key);
 
9624
    ndbrequire(! opPtr.isNull());
 
9625
    opPtr.p->setError(ref);
 
9626
    dropTrigger_fromAlterTrigger(signal, opPtr);
 
9627
    return;
 
9628
  }
 
9629
  OpAlterTriggerPtr opPtr;
 
9630
  c_opAlterTrigger.find(opPtr, key);
 
9631
  ndbrequire(! opPtr.isNull());
 
9632
  ndbrequire(opPtr.p->m_isMaster);
 
9633
  ndbrequire(opPtr.p->m_requestType == requestType);
 
9634
  /* 
 
9635
   * If refuse on drop trig, because of non-existent trigger,
 
9636
   * comes from anyone but the master node - ignore it and
 
9637
   * remove the node from forter ALTER_TRIG communication
 
9638
   * This will happen if a new node has started since the
 
9639
   * trigger whas created.
 
9640
   */
 
9641
  if (ref &&
 
9642
      refToNode(senderRef) != refToNode(reference()) &&
 
9643
      opPtr.p->m_request.getRequestType() == AlterTrigReq::RT_DROP_TRIGGER &&
 
9644
      ref->getErrorCode() == AlterTrigRef::TriggerNotFound) {
 
9645
    jam();
 
9646
    ref = 0;                                      // ignore this error
 
9647
    opPtr.p->m_nodes.clear(refToNode(senderRef)); // remove this from group
 
9648
  }
 
9649
  opPtr.p->setError(ref);
 
9650
  opPtr.p->m_signalCounter.clearWaitingFor(refToNode(senderRef));
 
9651
  if (! opPtr.p->m_signalCounter.done()) {
 
9652
    jam();
 
9653
    return;
 
9654
  }
 
9655
  if (requestType == AlterTrigReq::RT_DICT_COMMIT ||
 
9656
      requestType == AlterTrigReq::RT_DICT_ABORT) {
 
9657
    jam();
 
9658
    // send reply to user
 
9659
    alterTrigger_sendReply(signal, opPtr, true);
 
9660
    c_opAlterTrigger.release(opPtr);
 
9661
    return;
 
9662
  }
 
9663
  if (opPtr.p->hasError()) {
 
9664
    jam();
 
9665
    opPtr.p->m_requestType = AlterTrigReq::RT_DICT_ABORT;
 
9666
    alterTrigger_sendSlaveReq(signal, opPtr);
 
9667
    return;
 
9668
  }
 
9669
  if (! (opPtr.p->m_request.getRequestFlag() & RequestFlag::RF_NOTCTRIGGER)) {
 
9670
    if (requestType == AlterTrigReq::RT_DICT_PREPARE) {
 
9671
      jam();
 
9672
      if (opPtr.p->m_request.getOnline()) {
 
9673
        jam();
 
9674
        opPtr.p->m_requestType = AlterTrigReq::RT_DICT_TC;
 
9675
      } else {
 
9676
        jam();
 
9677
        opPtr.p->m_requestType = AlterTrigReq::RT_DICT_LQH;
 
9678
      }
 
9679
      alterTrigger_sendSlaveReq(signal, opPtr);
 
9680
      return;
 
9681
    }
 
9682
    if (requestType == AlterTrigReq::RT_DICT_TC) {
 
9683
      jam();
 
9684
      if (opPtr.p->m_request.getOnline()) {
 
9685
        jam();
 
9686
        opPtr.p->m_requestType = AlterTrigReq::RT_DICT_LQH;
 
9687
      } else {
 
9688
        jam();
 
9689
        opPtr.p->m_requestType = AlterTrigReq::RT_DICT_COMMIT;
 
9690
      }
 
9691
      alterTrigger_sendSlaveReq(signal, opPtr);
 
9692
      return;
 
9693
    }
 
9694
    if (requestType == AlterTrigReq::RT_DICT_LQH) {
 
9695
      jam();
 
9696
      if (opPtr.p->m_request.getOnline()) {
 
9697
        jam();
 
9698
        opPtr.p->m_requestType = AlterTrigReq::RT_DICT_COMMIT;
 
9699
      } else {
 
9700
        jam();
 
9701
        opPtr.p->m_requestType = AlterTrigReq::RT_DICT_TC;
 
9702
      }
 
9703
      alterTrigger_sendSlaveReq(signal, opPtr);
 
9704
      return;
 
9705
    }
 
9706
  } else {
 
9707
    if (requestType == AlterTrigReq::RT_DICT_PREPARE) {
 
9708
      jam();
 
9709
      opPtr.p->m_requestType = AlterTrigReq::RT_DICT_LQH;
 
9710
      alterTrigger_sendSlaveReq(signal, opPtr);
 
9711
      return;
 
9712
    }
 
9713
    if (requestType == AlterTrigReq::RT_DICT_LQH) {
 
9714
      jam();
 
9715
      opPtr.p->m_requestType = AlterTrigReq::RT_DICT_COMMIT;
 
9716
      alterTrigger_sendSlaveReq(signal, opPtr);
 
9717
      return;
 
9718
    }
 
9719
  }
 
9720
  ndbrequire(false);
 
9721
}
 
9722
 
 
9723
void
 
9724
Dbdict::alterTrigger_slavePrepare(Signal* signal, OpAlterTriggerPtr opPtr)
 
9725
{
 
9726
  jam();
 
9727
  const AlterTrigReq* const req = &opPtr.p->m_request;
 
9728
  const Uint32 triggerId = req->getTriggerId();
 
9729
  TriggerRecordPtr triggerPtr;
 
9730
  if (! (triggerId < c_triggerRecordPool.getSize())) {
 
9731
    jam();
 
9732
    opPtr.p->m_errorCode = AlterTrigRef::TriggerNotFound;
 
9733
    opPtr.p->m_errorLine = __LINE__;
 
9734
    return;
 
9735
  }
 
9736
  c_triggerRecordPool.getPtr(triggerPtr, triggerId);
 
9737
  if (triggerPtr.p->triggerState == TriggerRecord::TS_NOT_DEFINED) {
 
9738
    jam();
 
9739
    opPtr.p->m_errorCode = AlterTrigRef::TriggerNotFound;
 
9740
    opPtr.p->m_errorLine = __LINE__;
 
9741
    return;
 
9742
  }
 
9743
 
 
9744
  if (triggerPtr.p->triggerType == TriggerType::SUBSCRIPTION)
 
9745
  {
 
9746
    opPtr.p->m_request.addRequestFlag(RequestFlag::RF_NOTCTRIGGER);
 
9747
  }
 
9748
}
 
9749
 
 
9750
void
 
9751
Dbdict::alterTrigger_toCreateLocal(Signal* signal, OpAlterTriggerPtr opPtr)
 
9752
{
 
9753
  jam();
 
9754
  // find trigger record
 
9755
  const Uint32 triggerId = opPtr.p->m_request.getTriggerId();
 
9756
  TriggerRecordPtr triggerPtr;
 
9757
  c_triggerRecordPool.getPtr(triggerPtr, triggerId);
 
9758
  CreateTrigReq* const req = (CreateTrigReq*)signal->getDataPtrSend();
 
9759
  req->setUserRef(reference());
 
9760
  req->setConnectionPtr(opPtr.p->key);
 
9761
  if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
 
9762
    jam();
 
9763
    req->setRequestType(CreateTrigReq::RT_TC);
 
9764
  } else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
 
9765
    jam();
 
9766
    req->setRequestType(CreateTrigReq::RT_LQH);
 
9767
  } else {
 
9768
    ndbassert(false);
 
9769
  }
 
9770
  req->setTableId(triggerPtr.p->tableId);
 
9771
  req->setIndexId(triggerPtr.p->indexId);
 
9772
  req->setTriggerId(triggerPtr.i);
 
9773
  req->setTriggerType(triggerPtr.p->triggerType);
 
9774
  req->setTriggerActionTime(triggerPtr.p->triggerActionTime);
 
9775
  req->setTriggerEvent(triggerPtr.p->triggerEvent);
 
9776
  req->setMonitorReplicas(triggerPtr.p->monitorReplicas);
 
9777
  req->setMonitorAllAttributes(triggerPtr.p->monitorAllAttributes);
 
9778
  req->setOnline(true);
 
9779
  req->setReceiverRef(opPtr.p->m_request.getReceiverRef());
 
9780
  BlockReference blockRef = 0;
 
9781
  if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
 
9782
    jam();
 
9783
    blockRef = calcTcBlockRef(getOwnNodeId());
 
9784
  } else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
 
9785
    jam();
 
9786
    blockRef = calcLqhBlockRef(getOwnNodeId());
 
9787
  } else {
 
9788
    ndbassert(false);
 
9789
  }
 
9790
  req->setAttributeMask(triggerPtr.p->attributeMask);
 
9791
  sendSignal(blockRef, GSN_CREATE_TRIG_REQ,
 
9792
      signal, CreateTrigReq::SignalLength, JBB);
 
9793
}
 
9794
 
 
9795
void
 
9796
Dbdict::alterTrigger_fromCreateLocal(Signal* signal, OpAlterTriggerPtr opPtr)
 
9797
{
 
9798
  jam();
 
9799
  if (! opPtr.p->hasLastError()) {
 
9800
    // mark created locally
 
9801
    TriggerRecordPtr triggerPtr;
 
9802
    c_triggerRecordPool.getPtr(triggerPtr, opPtr.p->m_request.getTriggerId());
 
9803
    if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
 
9804
      jam();
 
9805
      triggerPtr.p->triggerLocal |= TriggerRecord::TL_CREATED_TC;
 
9806
    } else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
 
9807
      jam();
 
9808
      triggerPtr.p->triggerLocal |= TriggerRecord::TL_CREATED_LQH;
 
9809
    } else {
 
9810
      ndbrequire(false);
 
9811
    }
 
9812
  }
 
9813
  // forward CONF or REF to master
 
9814
  alterTrigger_sendReply(signal, opPtr, false);
 
9815
}
 
9816
 
 
9817
void
 
9818
Dbdict::alterTrigger_toDropLocal(Signal* signal, OpAlterTriggerPtr opPtr)
 
9819
{
 
9820
  jam();
 
9821
  TriggerRecordPtr triggerPtr;
 
9822
  c_triggerRecordPool.getPtr(triggerPtr, opPtr.p->m_request.getTriggerId());
 
9823
  DropTrigReq* const req = (DropTrigReq*)signal->getDataPtrSend();
 
9824
  req->setUserRef(reference());
 
9825
  req->setConnectionPtr(opPtr.p->key);
 
9826
  if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
 
9827
    jam();
 
9828
    // broken trigger allowed if force
 
9829
    if (! (triggerPtr.p->triggerLocal & TriggerRecord::TL_CREATED_TC)) {
 
9830
      jam();
 
9831
      ndbassert(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
 
9832
      alterTrigger_sendReply(signal, opPtr, false);
 
9833
      return;
 
9834
    }
 
9835
    req->setRequestType(DropTrigReq::RT_TC);
 
9836
  } else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
 
9837
    jam();
 
9838
    // broken trigger allowed if force
 
9839
    if (! (triggerPtr.p->triggerLocal & TriggerRecord::TL_CREATED_LQH)) {
 
9840
      jam();
 
9841
      ndbassert(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE);
 
9842
      alterTrigger_sendReply(signal, opPtr, false);
 
9843
      return;
 
9844
    }
 
9845
    req->setRequestType(DropTrigReq::RT_LQH);
 
9846
  } else {
 
9847
    ndbassert(false);
 
9848
  }
 
9849
  req->setTableId(triggerPtr.p->tableId);
 
9850
  req->setIndexId(triggerPtr.p->indexId);
 
9851
  req->setTriggerId(triggerPtr.i);
 
9852
  req->setTriggerType(triggerPtr.p->triggerType);
 
9853
  req->setTriggerActionTime(triggerPtr.p->triggerActionTime);
 
9854
  req->setTriggerEvent(triggerPtr.p->triggerEvent);
 
9855
  req->setMonitorReplicas(triggerPtr.p->monitorReplicas);
 
9856
  req->setMonitorAllAttributes(triggerPtr.p->monitorAllAttributes);
 
9857
  BlockReference blockRef = 0;
 
9858
  if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
 
9859
    jam();
 
9860
    blockRef = calcTcBlockRef(getOwnNodeId());
 
9861
  } else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
 
9862
    jam();
 
9863
    blockRef = calcLqhBlockRef(getOwnNodeId());
 
9864
  } else {
 
9865
    ndbassert(false);
 
9866
  }
 
9867
  sendSignal(blockRef, GSN_DROP_TRIG_REQ,
 
9868
      signal, DropTrigReq::SignalLength, JBB);
 
9869
}
 
9870
 
 
9871
void
 
9872
Dbdict::alterTrigger_fromDropLocal(Signal* signal, OpAlterTriggerPtr opPtr)
 
9873
{
 
9874
  jam();
 
9875
  if (! opPtr.p->hasLastError()) {
 
9876
    // mark dropped locally
 
9877
    TriggerRecordPtr triggerPtr;
 
9878
    c_triggerRecordPool.getPtr(triggerPtr, opPtr.p->m_request.getTriggerId());
 
9879
    if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_TC) {
 
9880
      jam();
 
9881
      triggerPtr.p->triggerLocal &= ~TriggerRecord::TL_CREATED_TC;
 
9882
    } else if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_LQH) {
 
9883
      jam();
 
9884
      triggerPtr.p->triggerLocal &= ~TriggerRecord::TL_CREATED_LQH;
 
9885
    } else {
 
9886
      ndbrequire(false);
 
9887
    }
 
9888
  }
 
9889
  // forward CONF or REF to master
 
9890
  alterTrigger_sendReply(signal, opPtr, false);
 
9891
}
 
9892
 
 
9893
void
 
9894
Dbdict::alterTrigger_slaveCommit(Signal* signal, OpAlterTriggerPtr opPtr)
 
9895
{
 
9896
  jam();
 
9897
  TriggerRecordPtr triggerPtr;
 
9898
  c_triggerRecordPool.getPtr(triggerPtr, opPtr.p->m_request.getTriggerId());
 
9899
  // set state
 
9900
  triggerPtr.p->triggerState = TriggerRecord::TS_ONLINE;
 
9901
}
 
9902
 
 
9903
void
 
9904
Dbdict::alterTrigger_slaveAbort(Signal* signal, OpAlterTriggerPtr opPtr)
 
9905
{
 
9906
  jam();
 
9907
}
 
9908
 
 
9909
void
 
9910
Dbdict::alterTrigger_sendSlaveReq(Signal* signal, OpAlterTriggerPtr opPtr)
 
9911
{
 
9912
  AlterTrigReq* const req = (AlterTrigReq*)signal->getDataPtrSend();
 
9913
  *req = opPtr.p->m_request;
 
9914
  req->setUserRef(opPtr.p->m_coordinatorRef);
 
9915
  req->setConnectionPtr(opPtr.p->key);
 
9916
  req->setRequestType(opPtr.p->m_requestType);
 
9917
  req->addRequestFlag(opPtr.p->m_requestFlag);
 
9918
  NdbNodeBitmask receiverNodes = c_aliveNodes;
 
9919
  if (opPtr.p->m_requestFlag & RequestFlag::RF_LOCAL) {
 
9920
    receiverNodes.clear();
 
9921
    receiverNodes.set(getOwnNodeId());
 
9922
  } else {
 
9923
    opPtr.p->m_nodes.bitAND(receiverNodes);
 
9924
    receiverNodes = opPtr.p->m_nodes;
 
9925
  }
 
9926
  opPtr.p->m_signalCounter = receiverNodes;
 
9927
  NodeReceiverGroup rg(DBDICT, receiverNodes);
 
9928
  sendSignal(rg, GSN_ALTER_TRIG_REQ,
 
9929
      signal, AlterTrigReq::SignalLength, JBB);
 
9930
}
 
9931
 
 
9932
void
 
9933
Dbdict::alterTrigger_sendReply(Signal* signal, OpAlterTriggerPtr opPtr,
 
9934
    bool toUser)
 
9935
{
 
9936
  jam();
 
9937
  AlterTrigRef* rep = (AlterTrigRef*)signal->getDataPtrSend();
 
9938
  Uint32 gsn = GSN_ALTER_TRIG_CONF;
 
9939
  Uint32 length = AlterTrigConf::InternalLength;
 
9940
  bool sendRef;
 
9941
  if (! toUser) {
 
9942
    sendRef = opPtr.p->hasLastError();
 
9943
    rep->setUserRef(opPtr.p->m_coordinatorRef);
 
9944
    rep->setConnectionPtr(opPtr.p->key);
 
9945
    rep->setRequestType(opPtr.p->m_requestType);
 
9946
    if (opPtr.p->m_requestType == AlterTrigReq::RT_DICT_ABORT) {
 
9947
      jam();
 
9948
      sendRef = false;
 
9949
    } else {
 
9950
      jam();
 
9951
    }
 
9952
  } else {
 
9953
    sendRef = opPtr.p->hasError();
 
9954
    jam();
 
9955
    rep->setUserRef(opPtr.p->m_request.getUserRef());
 
9956
    rep->setConnectionPtr(opPtr.p->m_request.getConnectionPtr());
 
9957
    rep->setRequestType(opPtr.p->m_request.getRequestType());
 
9958
    length = AlterTrigConf::SignalLength;
 
9959
  }
 
9960
  rep->setTableId(opPtr.p->m_request.getTableId());
 
9961
  rep->setTriggerId(opPtr.p->m_request.getTriggerId());
 
9962
  if (sendRef) {
 
9963
    if (opPtr.p->m_errorNode == 0) {
 
9964
      jam();
 
9965
      opPtr.p->m_errorNode = getOwnNodeId();
 
9966
    } else {
 
9967
      jam();
 
9968
    }
 
9969
    rep->setErrorCode(opPtr.p->m_errorCode);
 
9970
    rep->setErrorLine(opPtr.p->m_errorLine);
 
9971
    rep->setErrorNode(opPtr.p->m_errorNode);
 
9972
    gsn = GSN_ALTER_TRIG_REF;
 
9973
    length = AlterTrigRef::SignalLength;
 
9974
  }
 
9975
  sendSignal(rep->getUserRef(), gsn, signal, length, JBB);
 
9976
}
 
9977
 
 
9978
/**
 
9979
 * MODULE: Support routines for index and trigger.
 
9980
 */
 
9981
 
 
9982
void
 
9983
Dbdict::getTableKeyList(TableRecordPtr tablePtr, AttributeList& list)
 
9984
{
 
9985
  jam();
 
9986
  list.sz = 0;
 
9987
  for (Uint32 tAttr = tablePtr.p->firstAttribute; tAttr != RNIL; ) {
 
9988
    AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr);
 
9989
    if (aRec->tupleKey)
 
9990
      list.id[list.sz++] = aRec->attributeId;
 
9991
    tAttr = aRec->nextAttrInTable;
 
9992
  }
 
9993
}
 
9994
 
 
9995
// XXX should store the primary attribute id
 
9996
void
 
9997
Dbdict::getIndexAttr(TableRecordPtr indexPtr, Uint32 itAttr, Uint32* id)
 
9998
{
 
9999
  jam();
 
10000
  TableRecordPtr tablePtr;
 
10001
  c_tableRecordPool.getPtr(tablePtr, indexPtr.p->primaryTableId);
 
10002
  AttributeRecord* iaRec = c_attributeRecordPool.getPtr(itAttr);
 
10003
  for (Uint32 tAttr = tablePtr.p->firstAttribute; tAttr != RNIL; ) {
 
10004
    AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr);
 
10005
    if (iaRec->equal(*aRec)) {
 
10006
      id[0] = aRec->attributeId;
 
10007
      return;
 
10008
    }
 
10009
    tAttr = aRec->nextAttrInTable;
 
10010
  }
 
10011
  ndbrequire(false);
 
10012
}
 
10013
 
 
10014
void
 
10015
Dbdict::getIndexAttrList(TableRecordPtr indexPtr, AttributeList& list)
 
10016
{
 
10017
  jam();
 
10018
  TableRecordPtr tablePtr;
 
10019
  c_tableRecordPool.getPtr(tablePtr, indexPtr.p->primaryTableId);
 
10020
  list.sz = 0;
 
10021
  memset(list.id, 0, sizeof(list.id));
 
10022
  ndbrequire(indexPtr.p->noOfAttributes >= 2);
 
10023
  Uint32 itAttr = indexPtr.p->firstAttribute;
 
10024
  for (Uint32 i = 0; i < (Uint32)indexPtr.p->noOfAttributes - 1; i++) {
 
10025
    getIndexAttr(indexPtr, itAttr, &list.id[list.sz++]);
 
10026
    AttributeRecord* iaRec = c_attributeRecordPool.getPtr(itAttr);
 
10027
    itAttr = iaRec->nextAttrInTable;
 
10028
  }
 
10029
}
 
10030
 
 
10031
void
 
10032
Dbdict::getIndexAttrMask(TableRecordPtr indexPtr, AttributeMask& mask)
 
10033
{
 
10034
  jam();
 
10035
  TableRecordPtr tablePtr;
 
10036
  c_tableRecordPool.getPtr(tablePtr, indexPtr.p->primaryTableId);
 
10037
  mask.clear();
 
10038
  ndbrequire(indexPtr.p->noOfAttributes >= 2);
 
10039
  Uint32 itAttr = indexPtr.p->firstAttribute;
 
10040
  for (Uint32 i = 0; i < (Uint32)indexPtr.p->noOfAttributes - 1; i++) {
 
10041
    Uint32 id;
 
10042
    getIndexAttr(indexPtr, itAttr, &id);
 
10043
    mask.set(id);
 
10044
    AttributeRecord* iaRec = c_attributeRecordPool.getPtr(itAttr);
 
10045
    itAttr = iaRec->nextAttrInTable;
 
10046
  }
 
10047
}
 
10048
 
 
10049
// DICT lock master
 
10050
 
 
10051
const Dbdict::DictLockType*
 
10052
Dbdict::getDictLockType(Uint32 lockType)
 
10053
{
 
10054
  static const DictLockType lt[] = {
 
10055
    { DictLockReq::NodeRestartLock, BS_NODE_RESTART, "NodeRestart" }
 
10056
  };
 
10057
  for (unsigned int i = 0; i < sizeof(lt)/sizeof(lt[0]); i++) {
 
10058
    if ((Uint32) lt[i].lockType == lockType)
 
10059
      return &lt[i];
 
10060
  }
 
10061
  return NULL;
 
10062
}
 
10063
 
 
10064
void
 
10065
Dbdict::sendDictLockInfoEvent(Uint32 pollCount)
 
10066
{
 
10067
  DictLockPtr loopPtr;
 
10068
  c_dictLockQueue.first(loopPtr);
 
10069
  unsigned count = 0;
 
10070
 
 
10071
  char queue_buf[100];
 
10072
  char *p = &queue_buf[0];
 
10073
  const char *const q = &queue_buf[sizeof(queue_buf)];
 
10074
  *p = 0;
 
10075
 
 
10076
  while (loopPtr.i != RNIL) {
 
10077
    jam();
 
10078
    my_snprintf(p, q-p, "%s%u%s",
 
10079
                ++count == 1 ? "" : " ",
 
10080
                (unsigned)refToNode(loopPtr.p->req.userRef),
 
10081
                loopPtr.p->locked ? "L" : "");
 
10082
    p += strlen(p);
 
10083
    c_dictLockQueue.next(loopPtr);
 
10084
  }
 
10085
 
 
10086
  infoEvent("DICT: lock bs: %d ops: %d poll: %d cnt: %d queue: %s",
 
10087
      (int)c_blockState,
 
10088
      c_opRecordPool.getSize() - c_opRecordPool.getNoOfFree(),
 
10089
      c_dictLockPoll, (int)pollCount, queue_buf);
 
10090
}
 
10091
 
 
10092
void
 
10093
Dbdict::sendDictLockInfoEvent(DictLockPtr lockPtr, const char* text)
 
10094
{
 
10095
  infoEvent("DICT: %s %u for %s",
 
10096
      text,
 
10097
      (unsigned)refToNode(lockPtr.p->req.userRef), lockPtr.p->lt->text);
 
10098
}
 
10099
 
 
10100
void
 
10101
Dbdict::execDICT_LOCK_REQ(Signal* signal)
 
10102
{
 
10103
  jamEntry();
 
10104
  const DictLockReq* req = (const DictLockReq*)&signal->theData[0];
 
10105
 
 
10106
  // make sure bad request crashes slave, not master (us)
 
10107
 
 
10108
  if (getOwnNodeId() != c_masterNodeId) {
 
10109
    jam();
 
10110
    sendDictLockRef(signal, *req, DictLockRef::NotMaster);
 
10111
    return;
 
10112
  }
 
10113
 
 
10114
  const DictLockType* lt = getDictLockType(req->lockType);
 
10115
  if (lt == NULL) {
 
10116
    jam();
 
10117
    sendDictLockRef(signal, *req, DictLockRef::InvalidLockType);
 
10118
    return;
 
10119
  }
 
10120
 
 
10121
  if (req->userRef != signal->getSendersBlockRef() ||
 
10122
      getNodeInfo(refToNode(req->userRef)).m_type != NodeInfo::DB) {
 
10123
    jam();
 
10124
    sendDictLockRef(signal, *req, DictLockRef::BadUserRef);
 
10125
    return;
 
10126
  }
 
10127
 
 
10128
  if (c_aliveNodes.get(refToNode(req->userRef))) {
 
10129
    jam();
 
10130
    sendDictLockRef(signal, *req, DictLockRef::TooLate);
 
10131
    return;
 
10132
  }
 
10133
 
 
10134
  DictLockPtr lockPtr;
 
10135
  if (! c_dictLockQueue.seize(lockPtr)) {
 
10136
    jam();
 
10137
    sendDictLockRef(signal, *req, DictLockRef::TooManyRequests);
 
10138
    return;
 
10139
  }
 
10140
 
 
10141
  lockPtr.p->req = *req;
 
10142
  lockPtr.p->locked = false;
 
10143
  lockPtr.p->lt = lt;
 
10144
 
 
10145
  checkDictLockQueue(signal, false);
 
10146
 
 
10147
  if (! lockPtr.p->locked)
 
10148
    sendDictLockInfoEvent(lockPtr, "lock request by node");
 
10149
}
 
10150
 
 
10151
// only table and index ops are checked
 
10152
bool
 
10153
Dbdict::hasDictLockSchemaOp()
 
10154
{
 
10155
  return
 
10156
    ! c_opCreateTable.isEmpty() ||
 
10157
    ! c_opDropTable.isEmpty() ||
 
10158
    ! c_opCreateIndex.isEmpty() ||
 
10159
    ! c_opDropIndex.isEmpty();
 
10160
}
 
10161
 
 
10162
void
 
10163
Dbdict::checkDictLockQueue(Signal* signal, bool poll)
 
10164
{
 
10165
  Uint32 pollCount = ! poll ? 0 : signal->theData[1];
 
10166
 
 
10167
  DictLockPtr lockPtr;
 
10168
 
 
10169
  do {
 
10170
    if (! c_dictLockQueue.first(lockPtr)) {
 
10171
      jam();
 
10172
      setDictLockPoll(signal, false, pollCount);
 
10173
      return;
 
10174
    }
 
10175
 
 
10176
    if (lockPtr.p->locked) {
 
10177
      jam();
 
10178
      ndbrequire(c_blockState == lockPtr.p->lt->blockState);
 
10179
      break;
 
10180
    }
 
10181
 
 
10182
    if (hasDictLockSchemaOp()) {
 
10183
      jam();
 
10184
      break;
 
10185
    }
 
10186
 
 
10187
    if (c_blockState != BS_IDLE)
 
10188
    {
 
10189
      /**
 
10190
       * If state is BS_NODE_FAILURE, it might be that no op is running
 
10191
       */
 
10192
      jam();
 
10193
      break;
 
10194
    }
 
10195
 
 
10196
    ndbrequire(c_blockState == BS_IDLE);
 
10197
    lockPtr.p->locked = true;
 
10198
    c_blockState = lockPtr.p->lt->blockState;
 
10199
    sendDictLockConf(signal, lockPtr);
 
10200
 
 
10201
    sendDictLockInfoEvent(lockPtr, "locked by node");
 
10202
  } while (0);
 
10203
 
 
10204
  // poll while first request is open
 
10205
  // this routine is called again when it is removed for any reason
 
10206
 
 
10207
  bool on = ! lockPtr.p->locked;
 
10208
  setDictLockPoll(signal, on, pollCount);
 
10209
}
 
10210
 
 
10211
void
 
10212
Dbdict::execDICT_UNLOCK_ORD(Signal* signal)
 
10213
{
 
10214
  jamEntry();
 
10215
  const DictUnlockOrd* ord = (const DictUnlockOrd*)&signal->theData[0];
 
10216
 
 
10217
  DictLockPtr lockPtr;
 
10218
  c_dictLockQueue.getPtr(lockPtr, ord->lockPtr);
 
10219
  ndbrequire((Uint32) lockPtr.p->lt->lockType == ord->lockType);
 
10220
 
 
10221
  if (lockPtr.p->locked) {
 
10222
    jam();
 
10223
    ndbrequire(c_blockState == lockPtr.p->lt->blockState);
 
10224
    ndbrequire(! hasDictLockSchemaOp());
 
10225
    ndbrequire(! c_dictLockQueue.hasPrev(lockPtr));
 
10226
 
 
10227
    c_blockState = BS_IDLE;
 
10228
    sendDictLockInfoEvent(lockPtr, "unlocked by node");
 
10229
  } else {
 
10230
    sendDictLockInfoEvent(lockPtr, "lock request removed by node");
 
10231
  }
 
10232
 
 
10233
  c_dictLockQueue.release(lockPtr);
 
10234
 
 
10235
  checkDictLockQueue(signal, false);
 
10236
}
 
10237
 
 
10238
void
 
10239
Dbdict::sendDictLockConf(Signal* signal, DictLockPtr lockPtr)
 
10240
{
 
10241
  DictLockConf* conf = (DictLockConf*)&signal->theData[0];
 
10242
  const DictLockReq& req = lockPtr.p->req;
 
10243
 
 
10244
  conf->userPtr = req.userPtr;
 
10245
  conf->lockType = req.lockType;
 
10246
  conf->lockPtr = lockPtr.i;
 
10247
 
 
10248
  sendSignal(req.userRef, GSN_DICT_LOCK_CONF, signal,
 
10249
      DictLockConf::SignalLength, JBB);
 
10250
}
 
10251
 
 
10252
void
 
10253
Dbdict::sendDictLockRef(Signal* signal, DictLockReq req, Uint32 errorCode)
 
10254
{
 
10255
  DictLockRef* ref = (DictLockRef*)&signal->theData[0];
 
10256
 
 
10257
  ref->userPtr = req.userPtr;
 
10258
  ref->lockType = req.lockType;
 
10259
  ref->errorCode = errorCode;
 
10260
 
 
10261
  sendSignal(req.userRef, GSN_DICT_LOCK_REF, signal,
 
10262
      DictLockRef::SignalLength, JBB);
 
10263
}
 
10264
 
 
10265
// control polling
 
10266
 
 
10267
void
 
10268
Dbdict::setDictLockPoll(Signal* signal, bool on, Uint32 pollCount)
 
10269
{
 
10270
  if (on) {
 
10271
    jam();
 
10272
    signal->theData[0] = ZDICT_LOCK_POLL;
 
10273
    signal->theData[1] = pollCount + 1;
 
10274
    sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 2);
 
10275
  }
 
10276
 
 
10277
  bool change = (c_dictLockPoll != on);
 
10278
 
 
10279
  if (change) {
 
10280
    jam();
 
10281
    c_dictLockPoll = on;
 
10282
  }
 
10283
 
 
10284
  // avoid too many messages if master is stuck busy (BS_NODE_FAILURE)
 
10285
  bool periodic =
 
10286
    pollCount < 8 ||
 
10287
    pollCount < 64 && pollCount % 8 == 0 ||
 
10288
    pollCount < 512 && pollCount % 64 == 0 ||
 
10289
    pollCount < 4096 && pollCount % 512 == 0 ||
 
10290
    pollCount % 4096 == 0; // about every 6 minutes
 
10291
 
 
10292
  if (change || periodic)
 
10293
    sendDictLockInfoEvent(pollCount);
 
10294
}
 
10295
 
 
10296
// NF handling
 
10297
 
 
10298
void
 
10299
Dbdict::removeStaleDictLocks(Signal* signal, const Uint32* theFailedNodes)
 
10300
{
 
10301
  DictLockPtr loopPtr;
 
10302
  c_dictLockQueue.first(loopPtr);
 
10303
 
 
10304
  if (getOwnNodeId() != c_masterNodeId) {
 
10305
    ndbrequire(loopPtr.i == RNIL);
 
10306
    return;
 
10307
  }
 
10308
 
 
10309
  while (loopPtr.i != RNIL) {
 
10310
    jam();
 
10311
    DictLockPtr lockPtr = loopPtr;
 
10312
    c_dictLockQueue.next(loopPtr);
 
10313
 
 
10314
    Uint32 nodeId = refToNode(lockPtr.p->req.userRef);
 
10315
 
 
10316
    if (NodeBitmask::get(theFailedNodes, nodeId)) {
 
10317
      if (lockPtr.p->locked) {
 
10318
        jam();
 
10319
        ndbrequire(c_blockState == lockPtr.p->lt->blockState);
 
10320
        ndbrequire(! hasDictLockSchemaOp());
 
10321
        ndbrequire(! c_dictLockQueue.hasPrev(lockPtr));
 
10322
 
 
10323
        c_blockState = BS_IDLE;
 
10324
 
 
10325
        sendDictLockInfoEvent(lockPtr, "remove lock by failed node");
 
10326
      } else {
 
10327
        sendDictLockInfoEvent(lockPtr, "remove lock request by failed node");
 
10328
      }
 
10329
 
 
10330
      c_dictLockQueue.release(lockPtr);
 
10331
    }
 
10332
  }
 
10333
 
 
10334
  checkDictLockQueue(signal, false);
 
10335
}
 
10336
 
 
10337
 
 
10338
/* **************************************************************** */
 
10339
/* ---------------------------------------------------------------- */
 
10340
/* MODULE:          STORE/RESTORE SCHEMA FILE---------------------- */
 
10341
/* ---------------------------------------------------------------- */
 
10342
/*                                                                  */
 
10343
/* General module used to store the schema file on disk and         */
 
10344
/* similar function to restore it from disk.                        */
 
10345
/* ---------------------------------------------------------------- */
 
10346
/* **************************************************************** */
 
10347
 
 
10348
void
 
10349
Dbdict::initSchemaFile(XSchemaFile * xsf, Uint32 firstPage, Uint32 lastPage,
 
10350
                       bool initEntries)
 
10351
{
 
10352
  ndbrequire(lastPage <= xsf->noOfPages);
 
10353
  for (Uint32 n = firstPage; n < lastPage; n++) {
 
10354
    SchemaFile * sf = &xsf->schemaPage[n];
 
10355
    if (initEntries)
 
10356
      memset(sf, 0, NDB_SF_PAGE_SIZE);
 
10357
 
 
10358
    Uint32 ndb_version = NDB_VERSION;
 
10359
    if (ndb_version < NDB_SF_VERSION_5_0_6)
 
10360
      ndb_version = NDB_SF_VERSION_5_0_6;
 
10361
 
 
10362
    memcpy(sf->Magic, NDB_SF_MAGIC, sizeof(sf->Magic));
 
10363
    sf->ByteOrder = 0x12345678;
 
10364
    sf->NdbVersion =  ndb_version;
 
10365
    sf->FileSize = xsf->noOfPages * NDB_SF_PAGE_SIZE;
 
10366
    sf->PageNumber = n;
 
10367
    sf->CheckSum = 0;
 
10368
    sf->NoOfTableEntries = NDB_SF_PAGE_ENTRIES;
 
10369
 
 
10370
    computeChecksum(xsf, n);
 
10371
  }
 
10372
}
 
10373
 
 
10374
void
 
10375
Dbdict::resizeSchemaFile(XSchemaFile * xsf, Uint32 noOfPages)
 
10376
{
 
10377
  ndbrequire(noOfPages <= NDB_SF_MAX_PAGES);
 
10378
  if (xsf->noOfPages < noOfPages) {
 
10379
    jam();
 
10380
    Uint32 firstPage = xsf->noOfPages;
 
10381
    xsf->noOfPages = noOfPages;
 
10382
    initSchemaFile(xsf, 0, firstPage, false);
 
10383
    initSchemaFile(xsf, firstPage, xsf->noOfPages, true);
 
10384
  }
 
10385
  if (xsf->noOfPages > noOfPages) {
 
10386
    jam();
 
10387
    Uint32 tableId = noOfPages * NDB_SF_PAGE_ENTRIES;
 
10388
    while (tableId < xsf->noOfPages * NDB_SF_PAGE_ENTRIES) {
 
10389
      SchemaFile::TableEntry * te = getTableEntry(xsf, tableId);
 
10390
      if (te->m_tableState != SchemaFile::INIT &&
 
10391
          te->m_tableState != SchemaFile::DROP_TABLE_COMMITTED) {
 
10392
        ndbrequire(false);
 
10393
      }
 
10394
      tableId++;
 
10395
    }
 
10396
    xsf->noOfPages = noOfPages;
 
10397
    initSchemaFile(xsf, 0, xsf->noOfPages, false);
 
10398
  }
 
10399
}
 
10400
 
 
10401
void
 
10402
Dbdict::computeChecksum(XSchemaFile * xsf, Uint32 pageNo){ 
 
10403
  SchemaFile * sf = &xsf->schemaPage[pageNo];
 
10404
  sf->CheckSum = 0;
 
10405
  sf->CheckSum = computeChecksum((Uint32*)sf, NDB_SF_PAGE_SIZE_IN_WORDS);
 
10406
}
 
10407
 
 
10408
bool 
 
10409
Dbdict::validateChecksum(const XSchemaFile * xsf){
 
10410
  
 
10411
  for (Uint32 n = 0; n < xsf->noOfPages; n++) {
 
10412
    SchemaFile * sf = &xsf->schemaPage[n];
 
10413
    Uint32 c = computeChecksum((Uint32*)sf, NDB_SF_PAGE_SIZE_IN_WORDS);
 
10414
    if ( c != 0)
 
10415
      return false;
 
10416
  }
 
10417
  return true;
 
10418
}
 
10419
 
 
10420
Uint32
 
10421
Dbdict::computeChecksum(const Uint32 * src, Uint32 len){
 
10422
  Uint32 ret = 0;
 
10423
  for(Uint32 i = 0; i<len; i++)
 
10424
    ret ^= src[i];
 
10425
  return ret;
 
10426
}
 
10427
 
 
10428
SchemaFile::TableEntry * 
 
10429
Dbdict::getTableEntry(XSchemaFile * xsf, Uint32 tableId)
 
10430
{
 
10431
  Uint32 n = tableId / NDB_SF_PAGE_ENTRIES;
 
10432
  Uint32 i = tableId % NDB_SF_PAGE_ENTRIES;
 
10433
  ndbrequire(n < xsf->noOfPages);
 
10434
 
 
10435
  SchemaFile * sf = &xsf->schemaPage[n];
 
10436
  return &sf->TableEntries[i];
 
10437
}
 
10438
 
 
10439
// global metadata support
 
10440
 
 
10441
int
 
10442
Dbdict::getMetaTablePtr(TableRecordPtr& tablePtr, Uint32 tableId, Uint32 tableVersion)
 
10443
{
 
10444
  if (tableId >= c_tableRecordPool.getSize()) {
 
10445
    return MetaData::InvalidArgument;
 
10446
  }
 
10447
  c_tableRecordPool.getPtr(tablePtr, tableId);
 
10448
  if (tablePtr.p->tabState == TableRecord::NOT_DEFINED) {
 
10449
    return MetaData::TableNotFound;
 
10450
  }
 
10451
  if (tablePtr.p->tableVersion != tableVersion) {
 
10452
    return MetaData::InvalidTableVersion;
 
10453
  }
 
10454
  // online flag is not maintained by DICT
 
10455
  tablePtr.p->online =
 
10456
    tablePtr.p->isTable() && 
 
10457
    (tablePtr.p->tabState == TableRecord::DEFINED ||
 
10458
     tablePtr.p->tabState == TableRecord::BACKUP_ONGOING) ||
 
10459
    tablePtr.p->isIndex() && tablePtr.p->indexState == TableRecord::IS_ONLINE;
 
10460
  return 0;
 
10461
}
 
10462
 
 
10463
int
 
10464
Dbdict::getMetaTable(MetaData::Table& table, Uint32 tableId, Uint32 tableVersion)
 
10465
{
 
10466
  int ret;
 
10467
  TableRecordPtr tablePtr;
 
10468
  if ((ret = getMetaTablePtr(tablePtr, tableId, tableVersion)) < 0) {
 
10469
    return ret;
 
10470
  }
 
10471
  new (&table) MetaData::Table(*tablePtr.p);
 
10472
  return 0;
 
10473
}
 
10474
 
 
10475
int
 
10476
Dbdict::getMetaTable(MetaData::Table& table, const char* tableName)
 
10477
{
 
10478
  int ret;
 
10479
  TableRecordPtr tablePtr;
 
10480
  if (strlen(tableName) + 1 > MAX_TAB_NAME_SIZE) {
 
10481
    return MetaData::InvalidArgument;
 
10482
  }
 
10483
  TableRecord keyRecord;
 
10484
  strcpy(keyRecord.tableName, tableName);
 
10485
  c_tableRecordHash.find(tablePtr, keyRecord);
 
10486
  if (tablePtr.i == RNIL) {
 
10487
    return MetaData::TableNotFound;
 
10488
  }
 
10489
  if ((ret = getMetaTablePtr(tablePtr, tablePtr.i, tablePtr.p->tableVersion)) < 0) {
 
10490
    return ret;
 
10491
  }
 
10492
  new (&table) MetaData::Table(*tablePtr.p);
 
10493
  return 0;
 
10494
}
 
10495
 
 
10496
int
 
10497
Dbdict::getMetaAttribute(MetaData::Attribute& attr, const MetaData::Table& table, Uint32 attributeId)
 
10498
{
 
10499
  int ret;
 
10500
  TableRecordPtr tablePtr;
 
10501
  if ((ret = getMetaTablePtr(tablePtr, table.tableId, table.tableVersion)) < 0) {
 
10502
    return ret;
 
10503
  }
 
10504
  AttributeRecordPtr attrPtr;
 
10505
  attrPtr.i = tablePtr.p->firstAttribute;
 
10506
  while (attrPtr.i != RNIL) {
 
10507
    c_attributeRecordPool.getPtr(attrPtr);
 
10508
    if (attrPtr.p->attributeId == attributeId)
 
10509
      break;
 
10510
    attrPtr.i = attrPtr.p->nextAttrInTable;
 
10511
  }
 
10512
  if (attrPtr.i == RNIL) {
 
10513
    return MetaData::AttributeNotFound;
 
10514
  }
 
10515
  new (&attr) MetaData::Attribute(*attrPtr.p);
 
10516
  return 0;
 
10517
}
 
10518
 
 
10519
int
 
10520
Dbdict::getMetaAttribute(MetaData::Attribute& attr, const MetaData::Table& table, const char* attributeName)
 
10521
{
 
10522
  int ret;
 
10523
  TableRecordPtr tablePtr;
 
10524
  if ((ret = getMetaTablePtr(tablePtr, table.tableId, table.tableVersion)) < 0) {
 
10525
    return ret;
 
10526
  }
 
10527
  AttributeRecordPtr attrPtr;
 
10528
  attrPtr.i = tablePtr.p->firstAttribute;
 
10529
  while (attrPtr.i != RNIL) {
 
10530
    c_attributeRecordPool.getPtr(attrPtr);
 
10531
    if (strcmp(attrPtr.p->attributeName, attributeName) == 0)
 
10532
      break;
 
10533
    attrPtr.i = attrPtr.p->nextAttrInTable;
 
10534
  }
 
10535
  if (attrPtr.i == RNIL) {
 
10536
    return MetaData::AttributeNotFound;
 
10537
  }
 
10538
  new (&attr) MetaData::Attribute(*attrPtr.p);
 
10539
  return 0;
 
10540
}
 
10541
 
 
10542
CArray<KeyDescriptor> g_key_descriptor_pool;