~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to storage/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

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; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
 
 
17
#define DBTUP_C
 
18
#define DBTUP_META_CPP
 
19
#include "Dbtup.hpp"
 
20
#include <RefConvert.hpp>
 
21
#include <ndb_limits.h>
 
22
#include <pc.hpp>
 
23
#include <signaldata/TupFrag.hpp>
 
24
#include <signaldata/FsRef.hpp>
 
25
#include <signaldata/FsConf.hpp>
 
26
#include <signaldata/FsRemoveReq.hpp>
 
27
#include <signaldata/DropTab.hpp>
 
28
#include <signaldata/AlterTab.hpp>
 
29
#include <signaldata/CreateFilegroupImpl.hpp>
 
30
#include <AttributeDescriptor.hpp>
 
31
#include "AttributeOffset.hpp"
 
32
#include <my_sys.h>
 
33
 
 
34
void Dbtup::execTUPFRAGREQ(Signal* signal)
 
35
{
 
36
  jamEntry();
 
37
 
 
38
  TupFragReq* tupFragReq = (TupFragReq*)signal->getDataPtr();
 
39
  if (tupFragReq->userPtr == (Uint32)-1) {
 
40
    jam();
 
41
    abortAddFragOp(signal);
 
42
    return;
 
43
  }
 
44
 
 
45
  FragoperrecPtr fragOperPtr;
 
46
  FragrecordPtr regFragPtr;
 
47
  TablerecPtr regTabPtr;
 
48
 
 
49
  Uint32 userptr        = tupFragReq->userPtr;
 
50
  Uint32 userblockref   = tupFragReq->userRef;
 
51
  Uint32 reqinfo        = tupFragReq->reqInfo;
 
52
  regTabPtr.i           = tupFragReq->tableId;
 
53
  Uint32 noOfAttributes = tupFragReq->noOfAttr;
 
54
  Uint32 fragId         = tupFragReq->fragId;
 
55
  /*  Uint32 schemaVersion = tupFragReq->schemaVersion;*/
 
56
  Uint32 noOfKeyAttr = tupFragReq->noOfKeyAttr;
 
57
  Uint32 noOfCharsets = tupFragReq->noOfCharsets;
 
58
 
 
59
  Uint32 checksumIndicator = tupFragReq->checksumIndicator;
 
60
  Uint32 gcpIndicator = tupFragReq->globalCheckpointIdIndicator;
 
61
  Uint32 tablespace_id= tupFragReq->tablespaceid;
 
62
  Uint32 forceVarPart = tupFragReq->forceVarPartFlag;
 
63
 
 
64
  Uint64 maxRows =
 
65
    (((Uint64)tupFragReq->maxRowsHigh) << 32) + tupFragReq->maxRowsLow;
 
66
  Uint64 minRows =
 
67
    (((Uint64)tupFragReq->minRowsHigh) << 32) + tupFragReq->minRowsLow;
 
68
 
 
69
#ifndef VM_TRACE
 
70
  // config mismatch - do not crash if release compiled
 
71
  if (regTabPtr.i >= cnoOfTablerec) {
 
72
    jam();
 
73
    tupFragReq->userPtr = userptr;
 
74
    tupFragReq->userRef = 800;
 
75
    sendSignal(userblockref, GSN_TUPFRAGREF, signal, 2, JBB);
 
76
    return;
 
77
  }
 
78
#endif
 
79
 
 
80
  ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
 
81
  if (cfirstfreeFragopr == RNIL) {
 
82
    jam();
 
83
    tupFragReq->userPtr = userptr;
 
84
    tupFragReq->userRef = ZNOFREE_FRAGOP_ERROR;
 
85
    sendSignal(userblockref, GSN_TUPFRAGREF, signal, 2, JBB);
 
86
    return;
 
87
  }
 
88
  seizeFragoperrec(fragOperPtr);
 
89
 
 
90
  fragOperPtr.p->nextFragoprec = RNIL;
 
91
  fragOperPtr.p->lqhBlockrefFrag = userblockref;
 
92
  fragOperPtr.p->lqhPtrFrag = userptr;
 
93
  fragOperPtr.p->fragidFrag = fragId;
 
94
  fragOperPtr.p->tableidFrag = regTabPtr.i;
 
95
  fragOperPtr.p->attributeCount = noOfAttributes;
 
96
  
 
97
  memset(fragOperPtr.p->m_null_bits, 0, sizeof(fragOperPtr.p->m_null_bits));
 
98
  memset(fragOperPtr.p->m_fix_attributes_size, 0, 
 
99
         sizeof(fragOperPtr.p->m_fix_attributes_size));
 
100
  memset(fragOperPtr.p->m_var_attributes_size, 0, 
 
101
         sizeof(fragOperPtr.p->m_var_attributes_size));
 
102
 
 
103
  fragOperPtr.p->charsetIndex = 0;
 
104
  fragOperPtr.p->minRows = minRows;
 
105
  fragOperPtr.p->maxRows = maxRows;
 
106
 
 
107
  ndbrequire(reqinfo == ZADDFRAG);
 
108
 
 
109
  getFragmentrec(regFragPtr, fragId, regTabPtr.p);
 
110
  if (regFragPtr.i != RNIL) {
 
111
    jam();
 
112
    terrorCode= ZEXIST_FRAG_ERROR;
 
113
    fragrefuse1Lab(signal, fragOperPtr);
 
114
    return;
 
115
  }
 
116
  if (cfirstfreefrag != RNIL) {
 
117
    jam();
 
118
    seizeFragrecord(regFragPtr);
 
119
  } else {
 
120
    jam();
 
121
    terrorCode= ZFULL_FRAGRECORD_ERROR;
 
122
    fragrefuse1Lab(signal, fragOperPtr);
 
123
    return;
 
124
  }
 
125
  initFragRange(regFragPtr.p);
 
126
  if (!addfragtotab(regTabPtr.p, fragId, regFragPtr.i)) {
 
127
    jam();
 
128
    terrorCode= ZNO_FREE_TAB_ENTRY_ERROR;
 
129
    fragrefuse2Lab(signal, fragOperPtr, regFragPtr);
 
130
    return;
 
131
  }
 
132
  if (cfirstfreerange == RNIL) {
 
133
    jam();
 
134
    terrorCode= ZNO_FREE_PAGE_RANGE_ERROR;
 
135
    fragrefuse3Lab(signal, fragOperPtr, regFragPtr, regTabPtr.p, fragId);
 
136
    return;
 
137
  }
 
138
 
 
139
  regFragPtr.p->fragTableId= regTabPtr.i;
 
140
  regFragPtr.p->fragmentId= fragId;
 
141
  regFragPtr.p->m_tablespace_id= tablespace_id;
 
142
  regFragPtr.p->m_undo_complete= false;
 
143
  regFragPtr.p->m_lcp_scan_op = RNIL; 
 
144
  regFragPtr.p->m_lcp_keep_list = RNIL;
 
145
  regFragPtr.p->m_var_page_chunks = RNIL;  
 
146
  regFragPtr.p->m_restore_lcp_id = RNIL;
 
147
 
 
148
  if (ERROR_INSERTED(4007) && regTabPtr.p->fragid[0] == fragId ||
 
149
      ERROR_INSERTED(4008) && regTabPtr.p->fragid[1] == fragId) {
 
150
    jam();
 
151
    terrorCode = 1;
 
152
    fragrefuse4Lab(signal, fragOperPtr, regFragPtr, regTabPtr.p, fragId);
 
153
    CLEAR_ERROR_INSERT_VALUE;
 
154
    return;
 
155
  }
 
156
 
 
157
  if (regTabPtr.p->tableStatus == NOT_DEFINED) {
 
158
    jam();
 
159
//-----------------------------------------------------------------------------
 
160
// We are setting up references to the header of the tuple.
 
161
// Active operation  This word contains a reference to the operation active
 
162
//                   on the tuple at the moment. RNIL means no one active at
 
163
//                   all.  Not optional.
 
164
// Tuple version     Uses only low 16 bits.  Not optional.
 
165
// Checksum          The third header word is optional and contains a checksum
 
166
//                   of the tuple header.
 
167
// Null-bits         A number of words to contain null bits for all
 
168
//                   non-dynamic attributes. Each word contains upto 32 null
 
169
//                   bits. Each time a new word is needed we allocate the
 
170
//                   complete word. Zero nullable attributes means that there
 
171
//                   is no word at all
 
172
//-----------------------------------------------------------------------------
 
173
    fragOperPtr.p->definingFragment= true;
 
174
    regTabPtr.p->tableStatus= DEFINING;
 
175
    regTabPtr.p->m_bits = 0;
 
176
    regTabPtr.p->m_bits |= (checksumIndicator ? Tablerec::TR_Checksum : 0);
 
177
    regTabPtr.p->m_bits |= (gcpIndicator ? Tablerec::TR_RowGCI : 0);
 
178
    regTabPtr.p->m_bits |= (forceVarPart ? Tablerec::TR_ForceVarPart : 0);
 
179
    
 
180
    regTabPtr.p->m_offsets[MM].m_disk_ref_offset= 0;
 
181
    regTabPtr.p->m_offsets[MM].m_null_words= 0;
 
182
    regTabPtr.p->m_offsets[MM].m_fix_header_size= 0;
 
183
    regTabPtr.p->m_offsets[MM].m_max_var_offset= 0;
 
184
 
 
185
    regTabPtr.p->m_offsets[DD].m_disk_ref_offset= 0;
 
186
    regTabPtr.p->m_offsets[DD].m_null_words= 0;
 
187
    regTabPtr.p->m_offsets[DD].m_fix_header_size= 0;
 
188
    regTabPtr.p->m_offsets[DD].m_max_var_offset= 0;
 
189
 
 
190
    regTabPtr.p->m_attributes[MM].m_no_of_fixsize= 0;
 
191
    regTabPtr.p->m_attributes[MM].m_no_of_varsize= 0;
 
192
    regTabPtr.p->m_attributes[DD].m_no_of_fixsize= 0;
 
193
    regTabPtr.p->m_attributes[DD].m_no_of_varsize= 0;
 
194
 
 
195
    regTabPtr.p->noOfKeyAttr= noOfKeyAttr;
 
196
    regTabPtr.p->noOfCharsets= noOfCharsets;
 
197
    regTabPtr.p->m_no_of_attributes= noOfAttributes;
 
198
    
 
199
    regTabPtr.p->notNullAttributeMask.clear();
 
200
    regTabPtr.p->blobAttributeMask.clear();
 
201
    
 
202
    Uint32 offset[10];
 
203
    Uint32 tableDescriptorRef= allocTabDescr(regTabPtr.p, offset);
 
204
    if (tableDescriptorRef == RNIL) {
 
205
      jam();
 
206
      fragrefuse4Lab(signal, fragOperPtr, regFragPtr, regTabPtr.p, fragId);
 
207
      return;
 
208
    }
 
209
    setUpDescriptorReferences(tableDescriptorRef, regTabPtr.p, offset);
 
210
  } else {
 
211
    jam();
 
212
    fragOperPtr.p->definingFragment= false;
 
213
  }
 
214
  signal->theData[0]= fragOperPtr.p->lqhPtrFrag;
 
215
  signal->theData[1]= fragOperPtr.i;
 
216
  signal->theData[2]= regFragPtr.i;
 
217
  signal->theData[3]= fragId;
 
218
  sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUPFRAGCONF, signal, 4, JBB);
 
219
  return;
 
220
}
 
221
 
 
222
bool Dbtup::addfragtotab(Tablerec* const regTabPtr,
 
223
                         Uint32 fragId,
 
224
                         Uint32 fragIndex) 
 
225
{
 
226
  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
 
227
    jam();
 
228
    if (regTabPtr->fragid[i] == RNIL) {
 
229
      jam();
 
230
      regTabPtr->fragid[i]= fragId;
 
231
      regTabPtr->fragrec[i]= fragIndex;
 
232
      return true;
 
233
    }
 
234
  }
 
235
  return false;
 
236
}
 
237
 
 
238
void Dbtup::getFragmentrec(FragrecordPtr& regFragPtr,
 
239
                           Uint32 fragId,
 
240
                           Tablerec* const regTabPtr) 
 
241
{
 
242
  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
 
243
    jam();
 
244
    if (regTabPtr->fragid[i] == fragId) {
 
245
      jam();
 
246
      regFragPtr.i= regTabPtr->fragrec[i];
 
247
      ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
 
248
      return;
 
249
    }
 
250
  }
 
251
  regFragPtr.i= RNIL;
 
252
  ptrNull(regFragPtr);
 
253
}
 
254
 
 
255
void Dbtup::seizeFragrecord(FragrecordPtr& regFragPtr) 
 
256
{
 
257
  regFragPtr.i= cfirstfreefrag;
 
258
  ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
 
259
  cfirstfreefrag= regFragPtr.p->nextfreefrag;
 
260
  regFragPtr.p->nextfreefrag= RNIL;
 
261
}
 
262
 
 
263
void Dbtup::seizeFragoperrec(FragoperrecPtr& fragOperPtr) 
 
264
{
 
265
  fragOperPtr.i= cfirstfreeFragopr;
 
266
  ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
 
267
  cfirstfreeFragopr = fragOperPtr.p->nextFragoprec;
 
268
  fragOperPtr.p->nextFragoprec = RNIL;
 
269
  fragOperPtr.p->inUse = true;
 
270
}//Dbtup::seizeFragoperrec()
 
271
 
 
272
/* **************************************************************** */
 
273
/* **************          TUP_ADD_ATTRREQ       ****************** */
 
274
/* **************************************************************** */
 
275
void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
 
276
{
 
277
  FragrecordPtr regFragPtr;
 
278
  FragoperrecPtr fragOperPtr;
 
279
  TablerecPtr regTabPtr;
 
280
 
 
281
  jamEntry();
 
282
  fragOperPtr.i= signal->theData[0];
 
283
  ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
 
284
  Uint32 attrId = signal->theData[2];
 
285
  Uint32 attrDescriptor = signal->theData[3];
 
286
  Uint32 extType = AttributeDescriptor::getType(attrDescriptor);
 
287
  // DICT sends charset number in upper half
 
288
  Uint32 csNumber = (signal->theData[4] >> 16);
 
289
 
 
290
  regTabPtr.i= fragOperPtr.p->tableidFrag;
 
291
  ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
 
292
 
 
293
  Uint32 fragId= fragOperPtr.p->fragidFrag;
 
294
 
 
295
  getFragmentrec(regFragPtr, fragId, regTabPtr.p);
 
296
  ndbrequire(regFragPtr.i != RNIL);
 
297
 
 
298
  ndbrequire(fragOperPtr.p->attributeCount > 0);
 
299
  fragOperPtr.p->attributeCount--;
 
300
  const bool lastAttr = (fragOperPtr.p->attributeCount == 0);
 
301
 
 
302
  if (regTabPtr.p->tableStatus != DEFINING)
 
303
  {
 
304
    ndbrequire(regTabPtr.p->tableStatus == DEFINED);
 
305
    signal->theData[0] = fragOperPtr.p->lqhPtrFrag;
 
306
    signal->theData[1] = lastAttr;
 
307
    sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUP_ADD_ATTCONF, 
 
308
               signal, 2, JBB);
 
309
    
 
310
    if(lastAttr)
 
311
    {
 
312
      jam();
 
313
      /**
 
314
       * Init Disk_alloc_info
 
315
       */
 
316
      CreateFilegroupImplReq rep;
 
317
      if(regTabPtr.p->m_no_of_disk_attributes)
 
318
      {
 
319
        Tablespace_client tsman(0, c_tsman, 0, 0, 
 
320
                                regFragPtr.p->m_tablespace_id);
 
321
        ndbrequire(tsman.get_tablespace_info(&rep) == 0);
 
322
        regFragPtr.p->m_logfile_group_id= rep.tablespace.logfile_group_id;
 
323
      }
 
324
      else
 
325
      {
 
326
        jam();
 
327
        regFragPtr.p->m_logfile_group_id = RNIL;
 
328
      }
 
329
      new (&regFragPtr.p->m_disk_alloc_info)
 
330
        Disk_alloc_info(regTabPtr.p, rep.tablespace.extent_size);
 
331
      releaseFragoperrec(fragOperPtr);      
 
332
    }
 
333
    return;
 
334
  }
 
335
    
 
336
  Uint32 firstTabDesIndex= regTabPtr.p->tabDescriptor + (attrId * ZAD_SIZE);
 
337
  setTabDescrWord(firstTabDesIndex, attrDescriptor);
 
338
  Uint32 attrLen = AttributeDescriptor::getSize(attrDescriptor);
 
339
  
 
340
  Uint32 attrDes2= 0;
 
341
  if (!AttributeDescriptor::getDynamic(attrDescriptor)) {
 
342
    jam();
 
343
    Uint32 pos= 0, null_pos;
 
344
    Uint32 bytes= AttributeDescriptor::getSizeInBytes(attrDescriptor);
 
345
    Uint32 words= (bytes + 3) / 4;
 
346
    Uint32 ind= AttributeDescriptor::getDiskBased(attrDescriptor);
 
347
    ndbrequire(ind <= 1);
 
348
    null_pos= fragOperPtr.p->m_null_bits[ind];
 
349
 
 
350
    if (AttributeDescriptor::getNullable(attrDescriptor)) 
 
351
    {
 
352
      jam();
 
353
      fragOperPtr.p->m_null_bits[ind]++;
 
354
    } 
 
355
    else 
 
356
    {
 
357
      regTabPtr.p->notNullAttributeMask.set(attrId);
 
358
    }
 
359
 
 
360
    if (extType == NDB_TYPE_BLOB || extType == NDB_TYPE_TEXT) {
 
361
      regTabPtr.p->blobAttributeMask.set(attrId);
 
362
    }
 
363
 
 
364
    switch (AttributeDescriptor::getArrayType(attrDescriptor)) {
 
365
    case NDB_ARRAYTYPE_FIXED:
 
366
    {
 
367
      jam();
 
368
      regTabPtr.p->m_attributes[ind].m_no_of_fixsize++;
 
369
      if(attrLen != 0)
 
370
      {
 
371
        jam();
 
372
        pos= fragOperPtr.p->m_fix_attributes_size[ind];
 
373
        fragOperPtr.p->m_fix_attributes_size[ind] += words;
 
374
      }
 
375
      else
 
376
      {
 
377
        jam();
 
378
        Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
 
379
        fragOperPtr.p->m_null_bits[ind] += bitCount;
 
380
      }
 
381
      break;
 
382
    }
 
383
    default:
 
384
    {
 
385
      jam();
 
386
      fragOperPtr.p->m_var_attributes_size[ind] += bytes;
 
387
      pos= regTabPtr.p->m_attributes[ind].m_no_of_varsize++;
 
388
      break;
 
389
    }
 
390
    }//switch
 
391
    
 
392
    AttributeOffset::setOffset(attrDes2, pos);
 
393
    AttributeOffset::setNullFlagPos(attrDes2, null_pos);
 
394
  } else {
 
395
    ndbrequire(false);
 
396
  }
 
397
  if (csNumber != 0) { 
 
398
    CHARSET_INFO* cs = all_charsets[csNumber];
 
399
    ndbrequire(cs != NULL);
 
400
    Uint32 i = 0;
 
401
    while (i < fragOperPtr.p->charsetIndex) {
 
402
      jam();
 
403
      if (regTabPtr.p->charsetArray[i] == cs)
 
404
        break;
 
405
      i++;
 
406
    }
 
407
    if (i == fragOperPtr.p->charsetIndex) {
 
408
      jam();
 
409
      fragOperPtr.p->charsetIndex++;
 
410
    }
 
411
    ndbrequire(i < regTabPtr.p->noOfCharsets);
 
412
    regTabPtr.p->charsetArray[i]= cs;
 
413
    AttributeOffset::setCharsetPos(attrDes2, i);
 
414
  }
 
415
  setTabDescrWord(firstTabDesIndex + 1, attrDes2);
 
416
 
 
417
  if (ERROR_INSERTED(4009) && regTabPtr.p->fragid[0] == fragId && attrId == 0||
 
418
      ERROR_INSERTED(4010) && regTabPtr.p->fragid[0] == fragId && lastAttr ||
 
419
      ERROR_INSERTED(4011) && regTabPtr.p->fragid[1] == fragId && attrId == 0||
 
420
      ERROR_INSERTED(4012) && regTabPtr.p->fragid[1] == fragId && lastAttr) {
 
421
    jam();
 
422
    terrorCode = 1;
 
423
    addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
 
424
    CLEAR_ERROR_INSERT_VALUE;
 
425
    return;
 
426
  }
 
427
 
 
428
/* **************************************************************** */
 
429
/* **************          TUP_ADD_ATTCONF       ****************** */
 
430
/* **************************************************************** */
 
431
  if (! lastAttr) {
 
432
    jam();
 
433
    signal->theData[0] = fragOperPtr.p->lqhPtrFrag;
 
434
    signal->theData[1] = lastAttr;
 
435
    sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUP_ADD_ATTCONF, 
 
436
               signal, 2, JBB);
 
437
    return;
 
438
  }
 
439
  
 
440
  ndbrequire(regTabPtr.p->tableStatus == DEFINING);
 
441
  regTabPtr.p->tableStatus= DEFINED;
 
442
  regFragPtr.p->fragStatus= ACTIVE;
 
443
  
 
444
#define BTW(x) ((x+31) >> 5)
 
445
  regTabPtr.p->m_offsets[MM].m_null_words= BTW(fragOperPtr.p->m_null_bits[MM]);
 
446
  regTabPtr.p->m_offsets[DD].m_null_words= BTW(fragOperPtr.p->m_null_bits[DD]);
 
447
 
 
448
  /**
 
449
   * Fix offsets
 
450
   */
 
451
  Uint32 pos[2] = { 0, 0 };
 
452
  if (regTabPtr.p->m_bits & Tablerec::TR_Checksum)
 
453
  {
 
454
    pos[0]= 1; 
 
455
  }
 
456
 
 
457
  if (regTabPtr.p->m_bits & Tablerec::TR_RowGCI)
 
458
  {
 
459
    pos[MM]++;
 
460
    pos[DD]++;
 
461
  }
 
462
  
 
463
  regTabPtr.p->m_no_of_disk_attributes= 
 
464
    regTabPtr.p->m_attributes[DD].m_no_of_fixsize +
 
465
    regTabPtr.p->m_attributes[DD].m_no_of_varsize;
 
466
  
 
467
  if(regTabPtr.p->m_no_of_disk_attributes > 0)
 
468
  {
 
469
    regTabPtr.p->m_offsets[MM].m_disk_ref_offset= pos[MM];
 
470
    pos[MM] += Disk_part_ref::SZ32; // 8 bytes
 
471
  }
 
472
  else
 
473
  {
 
474
    /**
 
475
     * var part ref is stored at m_disk_ref_offset + Disk_part_ref::SZ32
 
476
     */
 
477
    regTabPtr.p->m_offsets[MM].m_disk_ref_offset= pos[MM]-Disk_part_ref::SZ32;
 
478
  }
 
479
 
 
480
  if (regTabPtr.p->m_attributes[MM].m_no_of_varsize)
 
481
  {
 
482
    pos[MM] += Var_part_ref::SZ32;
 
483
    regTabPtr.p->m_bits &= ~(Uint32)Tablerec::TR_ForceVarPart;
 
484
  }
 
485
  else if (regTabPtr.p->m_bits & Tablerec::TR_ForceVarPart)
 
486
  {
 
487
    pos[MM] += Var_part_ref::SZ32;
 
488
  }
 
489
  
 
490
  regTabPtr.p->m_offsets[MM].m_null_offset= pos[MM];
 
491
  regTabPtr.p->m_offsets[DD].m_null_offset= pos[DD];
 
492
  
 
493
  pos[MM]+= regTabPtr.p->m_offsets[MM].m_null_words;
 
494
  pos[DD]+= regTabPtr.p->m_offsets[DD].m_null_words;
 
495
 
 
496
  Uint32 *tabDesc = (Uint32*)(tableDescriptor+regTabPtr.p->tabDescriptor);
 
497
  for(Uint32 i= 0; i<regTabPtr.p->m_no_of_attributes; i++)
 
498
  {
 
499
    Uint32 ind= AttributeDescriptor::getDiskBased(* tabDesc);
 
500
    Uint32 arr= AttributeDescriptor::getArrayType(* tabDesc++);
 
501
 
 
502
    if(arr == NDB_ARRAYTYPE_FIXED)
 
503
    {
 
504
      Uint32 desc= * tabDesc;
 
505
      Uint32 off= AttributeOffset::getOffset(desc) + pos[ind];
 
506
      AttributeOffset::setOffset(desc, off);
 
507
      * tabDesc= desc;
 
508
    }
 
509
    tabDesc++;
 
510
  }
 
511
 
 
512
  regTabPtr.p->m_offsets[MM].m_fix_header_size= 
 
513
    Tuple_header::HeaderSize + 
 
514
    fragOperPtr.p->m_fix_attributes_size[MM] + 
 
515
    pos[MM];
 
516
  
 
517
  regTabPtr.p->m_offsets[DD].m_fix_header_size= 
 
518
    fragOperPtr.p->m_fix_attributes_size[DD] + 
 
519
    pos[DD];
 
520
 
 
521
  if(regTabPtr.p->m_attributes[DD].m_no_of_varsize == 0 &&
 
522
     regTabPtr.p->m_attributes[DD].m_no_of_fixsize > 0)
 
523
    regTabPtr.p->m_offsets[DD].m_fix_header_size += Tuple_header::HeaderSize;
 
524
  
 
525
  regTabPtr.p->m_offsets[MM].m_max_var_offset= 
 
526
    fragOperPtr.p->m_var_attributes_size[MM];
 
527
  
 
528
  regTabPtr.p->m_offsets[DD].m_max_var_offset= 
 
529
    fragOperPtr.p->m_var_attributes_size[DD];
 
530
 
 
531
  regTabPtr.p->total_rec_size= 
 
532
    pos[MM] + fragOperPtr.p->m_fix_attributes_size[MM] +
 
533
    pos[DD] + fragOperPtr.p->m_fix_attributes_size[DD] +
 
534
    ((fragOperPtr.p->m_var_attributes_size[MM] + 3) >> 2) +
 
535
    ((fragOperPtr.p->m_var_attributes_size[DD] + 3) >> 2) +
 
536
    (regTabPtr.p->m_attributes[MM].m_no_of_varsize ? 
 
537
     (regTabPtr.p->m_attributes[MM].m_no_of_varsize + 2) >> 1 : 0) +
 
538
    (regTabPtr.p->m_attributes[DD].m_no_of_varsize ? 
 
539
     (regTabPtr.p->m_attributes[DD].m_no_of_varsize + 2) >> 1 : 0) +
 
540
    Tuple_header::HeaderSize +
 
541
    (regTabPtr.p->m_no_of_disk_attributes ? Tuple_header::HeaderSize : 0);
 
542
  
 
543
  setUpQueryRoutines(regTabPtr.p);
 
544
  setUpKeyArray(regTabPtr.p);
 
545
 
 
546
#if 0
 
547
  ndbout << *regTabPtr.p << endl;
 
548
  Uint32 idx= regTabPtr.p->tabDescriptor;
 
549
  for(Uint32 i = 0; i<regTabPtr.p->m_no_of_attributes; i++)
 
550
  {
 
551
    ndbout << i << ": " << endl;
 
552
    ndbout << *(AttributeDescriptor*)(tableDescriptor+idx) << endl;
 
553
    ndbout << *(AttributeOffset*)(tableDescriptor+idx+1) << endl;
 
554
    idx += 2;
 
555
  }
 
556
#endif
 
557
  
 
558
  {
 
559
    Uint32 fix_tupheader = regTabPtr.p->m_offsets[MM].m_fix_header_size;
 
560
    ndbassert(fix_tupheader > 0);
 
561
    Uint32 noRowsPerPage = ZWORDS_ON_PAGE / fix_tupheader;
 
562
    Uint32 noAllocatedPages =
 
563
      (fragOperPtr.p->minRows + noRowsPerPage - 1 )/ noRowsPerPage;
 
564
    if (fragOperPtr.p->minRows == 0)
 
565
      noAllocatedPages = 2;
 
566
    else if (noAllocatedPages == 0)
 
567
      noAllocatedPages = 2;
 
568
    noAllocatedPages = allocFragPages(regFragPtr.p, noAllocatedPages);
 
569
 
 
570
    if (noAllocatedPages == 0) {
 
571
      jam();
 
572
      terrorCode = ZNO_PAGES_ALLOCATED_ERROR;
 
573
      addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
 
574
      return;
 
575
    }//if
 
576
  }
 
577
 
 
578
  CreateFilegroupImplReq rep;
 
579
  if(regTabPtr.p->m_no_of_disk_attributes)
 
580
  {
 
581
    jam();
 
582
    Tablespace_client tsman(0, c_tsman, 0, 0, 
 
583
                            regFragPtr.p->m_tablespace_id);
 
584
    ndbrequire(tsman.get_tablespace_info(&rep) == 0);
 
585
    regFragPtr.p->m_logfile_group_id= rep.tablespace.logfile_group_id;
 
586
  }
 
587
  else
 
588
  {
 
589
    jam();
 
590
    regFragPtr.p->m_logfile_group_id = RNIL;
 
591
  }
 
592
 
 
593
  new (&regFragPtr.p->m_disk_alloc_info)
 
594
    Disk_alloc_info(regTabPtr.p, rep.tablespace.extent_size); 
 
595
  
 
596
  if (regTabPtr.p->m_no_of_disk_attributes)
 
597
  {
 
598
    jam();
 
599
    if(!(getNodeState().startLevel == NodeState::SL_STARTING && 
 
600
         getNodeState().starting.startPhase <= 4))
 
601
    {
 
602
      Callback cb;
 
603
      jam();
 
604
 
 
605
      cb.m_callbackData= fragOperPtr.i;
 
606
      cb.m_callbackFunction = 
 
607
        safe_cast(&Dbtup::undo_createtable_callback);
 
608
      Uint32 sz= sizeof(Disk_undo::Create) >> 2;
 
609
      
 
610
      Logfile_client lgman(this, c_lgman, regFragPtr.p->m_logfile_group_id);
 
611
      if((terrorCode = 
 
612
          c_lgman->alloc_log_space(regFragPtr.p->m_logfile_group_id, sz)))
 
613
      {
 
614
        addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
 
615
        return;
 
616
      }
 
617
      
 
618
      int res= lgman.get_log_buffer(signal, sz, &cb);
 
619
      switch(res){
 
620
      case 0:
 
621
        jam();
 
622
        signal->theData[0] = 1;
 
623
        return;
 
624
      case -1:
 
625
        ndbrequire("NOT YET IMPLEMENTED" == 0);
 
626
        break;
 
627
      }
 
628
      execute(signal, cb, regFragPtr.p->m_logfile_group_id);
 
629
      return;
 
630
    }
 
631
  }
 
632
  
 
633
  signal->theData[0] = fragOperPtr.p->lqhPtrFrag;
 
634
  signal->theData[1] = lastAttr;
 
635
  sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUP_ADD_ATTCONF, 
 
636
             signal, 2, JBB);
 
637
 
 
638
  releaseFragoperrec(fragOperPtr);
 
639
 
 
640
  return;
 
641
}
 
642
 
 
643
void
 
644
Dbtup::undo_createtable_callback(Signal* signal, Uint32 opPtrI, Uint32 unused)
 
645
{
 
646
  FragrecordPtr regFragPtr;
 
647
  FragoperrecPtr fragOperPtr;
 
648
  TablerecPtr regTabPtr;
 
649
 
 
650
  fragOperPtr.i= opPtrI;
 
651
  ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
 
652
 
 
653
  regTabPtr.i= fragOperPtr.p->tableidFrag;
 
654
  ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
 
655
 
 
656
  getFragmentrec(regFragPtr, fragOperPtr.p->fragidFrag, regTabPtr.p);
 
657
  ndbrequire(regFragPtr.i != RNIL);
 
658
  
 
659
  Logfile_client lgman(this, c_lgman, regFragPtr.p->m_logfile_group_id);
 
660
 
 
661
  Disk_undo::Create create;
 
662
  create.m_type_length= Disk_undo::UNDO_CREATE << 16 | (sizeof(create) >> 2);
 
663
  create.m_table = regTabPtr.i;
 
664
  
 
665
  Logfile_client::Change c[1] = {{ &create, sizeof(create) >> 2 } };
 
666
  
 
667
  Uint64 lsn= lgman.add_entry(c, 1);
 
668
 
 
669
  Logfile_client::Request req;
 
670
  req.m_callback.m_callbackData= fragOperPtr.i;
 
671
  req.m_callback.m_callbackFunction = 
 
672
    safe_cast(&Dbtup::undo_createtable_logsync_callback);
 
673
  
 
674
  int ret = lgman.sync_lsn(signal, lsn, &req, 0);
 
675
  switch(ret){
 
676
  case 0:
 
677
    return;
 
678
  case -1:
 
679
    warningEvent("Failed to sync log for create of table: %u", regTabPtr.i);
 
680
  default:
 
681
    execute(signal, req.m_callback, regFragPtr.p->m_logfile_group_id);
 
682
  }
 
683
}
 
684
 
 
685
void
 
686
Dbtup::undo_createtable_logsync_callback(Signal* signal, Uint32 ptrI, 
 
687
                                         Uint32 res)
 
688
{
 
689
  jamEntry();
 
690
  FragoperrecPtr fragOperPtr;
 
691
  fragOperPtr.i= ptrI;
 
692
  ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
 
693
  
 
694
  signal->theData[0] = fragOperPtr.p->lqhPtrFrag;
 
695
  signal->theData[1] = 1;
 
696
  sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUP_ADD_ATTCONF, 
 
697
             signal, 2, JBB);
 
698
  
 
699
  releaseFragoperrec(fragOperPtr);  
 
700
}
 
701
 
 
702
/*
 
703
 * Descriptor has these parts:
 
704
 *
 
705
 * 0 readFunctionArray ( one for each attribute )
 
706
 * 1 updateFunctionArray ( ditto )
 
707
 * 2 charsetArray ( pointers to distinct CHARSET_INFO )
 
708
 * 3 readKeyArray ( attribute ids of keys )
 
709
 * 5 tabDescriptor ( attribute descriptors, each ZAD_SIZE )
 
710
 */
 
711
void Dbtup::setUpDescriptorReferences(Uint32 descriptorReference,
 
712
                                      Tablerec* const regTabPtr,
 
713
                                      const Uint32* offset)
 
714
{
 
715
  Uint32* desc= &tableDescriptor[descriptorReference].tabDescr;
 
716
  regTabPtr->readFunctionArray= (ReadFunction*)(desc + offset[0]);
 
717
  regTabPtr->updateFunctionArray= (UpdateFunction*)(desc + offset[1]);
 
718
  regTabPtr->charsetArray= (CHARSET_INFO**)(desc + offset[2]);
 
719
  regTabPtr->readKeyArray= descriptorReference + offset[3];
 
720
  regTabPtr->tabDescriptor= descriptorReference + offset[4];
 
721
  regTabPtr->m_real_order_descriptor = descriptorReference + offset[5];
 
722
}
 
723
 
 
724
Uint32
 
725
Dbtup::sizeOfReadFunction()
 
726
{
 
727
  ReadFunction* tmp= (ReadFunction*)&tableDescriptor[0];
 
728
  TableDescriptor* start= &tableDescriptor[0];
 
729
  TableDescriptor * end= (TableDescriptor*)(tmp + 1);
 
730
  return (Uint32)(end - start);
 
731
}
 
732
 
 
733
void Dbtup::setUpKeyArray(Tablerec* const regTabPtr)
 
734
{
 
735
  ndbrequire((regTabPtr->readKeyArray + regTabPtr->noOfKeyAttr) <
 
736
              cnoOfTabDescrRec);
 
737
  Uint32* keyArray= &tableDescriptor[regTabPtr->readKeyArray].tabDescr;
 
738
  Uint32 countKeyAttr= 0;
 
739
  for (Uint32 i= 0; i < regTabPtr->m_no_of_attributes; i++) {
 
740
    jam();
 
741
    Uint32 refAttr= regTabPtr->tabDescriptor + (i * ZAD_SIZE);
 
742
    Uint32 attrDescriptor= getTabDescrWord(refAttr);
 
743
    if (AttributeDescriptor::getPrimaryKey(attrDescriptor)) {
 
744
      jam();
 
745
      AttributeHeader::init(&keyArray[countKeyAttr], i, 0);
 
746
      countKeyAttr++;
 
747
    }
 
748
  }
 
749
  ndbrequire(countKeyAttr == regTabPtr->noOfKeyAttr);
 
750
 
 
751
  /**
 
752
   * Setup real order array (16 bit per column)
 
753
   */
 
754
  const Uint32 off= regTabPtr->m_real_order_descriptor;
 
755
  const Uint32 sz= (regTabPtr->m_no_of_attributes + 1) >> 1;
 
756
  ndbrequire((off + sz) < cnoOfTabDescrRec);
 
757
  
 
758
  Uint32 cnt= 0;
 
759
  Uint16* order= (Uint16*)&tableDescriptor[off].tabDescr;
 
760
  for (Uint32 type = 0; type < 4; type++)
 
761
  {
 
762
    for (Uint32 i= 0; i < regTabPtr->m_no_of_attributes; i++) 
 
763
    {
 
764
      jam();
 
765
      Uint32 refAttr= regTabPtr->tabDescriptor + (i * ZAD_SIZE);
 
766
      Uint32 desc = getTabDescrWord(refAttr);
 
767
      Uint32 t = 0;
 
768
 
 
769
      if (AttributeDescriptor::getArrayType(desc) != NDB_ARRAYTYPE_FIXED) 
 
770
      {
 
771
        t += 1;
 
772
      }
 
773
      if (AttributeDescriptor::getDiskBased(desc))
 
774
      {
 
775
        t += 2;
 
776
      }
 
777
      ndbrequire(t < 4);
 
778
      if(t == type)
 
779
      {
 
780
        * order++ = i << ZAD_LOG_SIZE;
 
781
        cnt++;
 
782
      }
 
783
    }
 
784
  }
 
785
  ndbrequire(cnt == regTabPtr->m_no_of_attributes);
 
786
}
 
787
 
 
788
void Dbtup::addattrrefuseLab(Signal* signal,
 
789
                             FragrecordPtr regFragPtr,
 
790
                             FragoperrecPtr fragOperPtr,
 
791
                             Tablerec* const regTabPtr,
 
792
                             Uint32 fragId) 
 
793
{
 
794
  releaseFragPages(regFragPtr.p);
 
795
  deleteFragTab(regTabPtr, fragId);
 
796
  releaseFragrec(regFragPtr);
 
797
  releaseTabDescr(regTabPtr);
 
798
  initTab(regTabPtr);
 
799
 
 
800
  signal->theData[0]= fragOperPtr.p->lqhPtrFrag;
 
801
  signal->theData[1]= terrorCode;
 
802
  sendSignal(fragOperPtr.p->lqhBlockrefFrag,
 
803
              GSN_TUP_ADD_ATTRREF, signal, 2, JBB);
 
804
  releaseFragoperrec(fragOperPtr);
 
805
}
 
806
 
 
807
void Dbtup::fragrefuse4Lab(Signal* signal,
 
808
                           FragoperrecPtr fragOperPtr,
 
809
                           FragrecordPtr regFragPtr,
 
810
                           Tablerec* const regTabPtr,
 
811
                           Uint32 fragId) 
 
812
{
 
813
  releaseFragPages(regFragPtr.p);
 
814
  fragrefuse3Lab(signal, fragOperPtr, regFragPtr, regTabPtr, fragId);
 
815
  initTab(regTabPtr);
 
816
}
 
817
 
 
818
void Dbtup::fragrefuse3Lab(Signal* signal,
 
819
                           FragoperrecPtr fragOperPtr,
 
820
                           FragrecordPtr regFragPtr,
 
821
                           Tablerec* const regTabPtr,
 
822
                           Uint32 fragId) 
 
823
{
 
824
  fragrefuse2Lab(signal, fragOperPtr, regFragPtr);
 
825
  deleteFragTab(regTabPtr, fragId);
 
826
}
 
827
 
 
828
void Dbtup::fragrefuse2Lab(Signal* signal,
 
829
                           FragoperrecPtr fragOperPtr,
 
830
                           FragrecordPtr regFragPtr) 
 
831
{
 
832
  fragrefuse1Lab(signal, fragOperPtr);
 
833
  releaseFragrec(regFragPtr);
 
834
}
 
835
 
 
836
void Dbtup::fragrefuse1Lab(Signal* signal, FragoperrecPtr fragOperPtr) 
 
837
{
 
838
  fragrefuseLab(signal, fragOperPtr);
 
839
  releaseFragoperrec(fragOperPtr);
 
840
}
 
841
 
 
842
void Dbtup::fragrefuseLab(Signal* signal, FragoperrecPtr fragOperPtr) 
 
843
{
 
844
  signal->theData[0]= fragOperPtr.p->lqhPtrFrag;
 
845
  signal->theData[1]= terrorCode;
 
846
  sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUPFRAGREF, signal, 2, JBB);
 
847
}
 
848
 
 
849
void Dbtup::releaseFragoperrec(FragoperrecPtr fragOperPtr) 
 
850
{
 
851
  fragOperPtr.p->inUse = false;
 
852
  fragOperPtr.p->nextFragoprec = cfirstfreeFragopr;
 
853
  cfirstfreeFragopr = fragOperPtr.i;
 
854
}//Dbtup::releaseFragoperrec()
 
855
 
 
856
void Dbtup::deleteFragTab(Tablerec* const regTabPtr, Uint32 fragId) 
 
857
{
 
858
  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
 
859
    jam();
 
860
    if (regTabPtr->fragid[i] == fragId) {
 
861
      jam();
 
862
      regTabPtr->fragid[i]= RNIL;
 
863
      regTabPtr->fragrec[i]= RNIL;
 
864
      return;
 
865
    }
 
866
  }
 
867
  ndbrequire(false);
 
868
}
 
869
 
 
870
/*
 
871
 * LQH aborts on-going create table operation.  The table is later
 
872
 * dropped by DICT.
 
873
 */
 
874
void Dbtup::abortAddFragOp(Signal* signal)
 
875
{
 
876
  FragoperrecPtr fragOperPtr;
 
877
 
 
878
  fragOperPtr.i = signal->theData[1];
 
879
  ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
 
880
  ndbrequire(fragOperPtr.p->inUse);
 
881
  releaseFragoperrec(fragOperPtr);
 
882
}
 
883
 
 
884
void
 
885
Dbtup::execDROP_TAB_REQ(Signal* signal)
 
886
{
 
887
  jamEntry();
 
888
  if (ERROR_INSERTED(4013)) {
 
889
#ifdef VM_TRACE
 
890
    verifytabdes();
 
891
#endif
 
892
  }
 
893
  DropTabReq* req= (DropTabReq*)signal->getDataPtr();
 
894
  
 
895
  TablerecPtr tabPtr;
 
896
  tabPtr.i= req->tableId;
 
897
  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
 
898
  
 
899
  tabPtr.p->m_dropTable.tabUserRef = req->senderRef;
 
900
  tabPtr.p->m_dropTable.tabUserPtr = req->senderData;
 
901
  tabPtr.p->tableStatus = DROPPING;
 
902
 
 
903
  signal->theData[0]= ZREL_FRAG;
 
904
  signal->theData[1]= tabPtr.i;
 
905
  signal->theData[2]= RNIL;
 
906
  sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
 
907
}
 
908
 
 
909
void Dbtup::releaseTabDescr(Tablerec* const regTabPtr) 
 
910
{
 
911
  Uint32 descriptor= regTabPtr->readKeyArray;
 
912
  if (descriptor != RNIL) {
 
913
    jam();
 
914
    Uint32 offset[10];
 
915
    getTabDescrOffsets(regTabPtr, offset);
 
916
 
 
917
    regTabPtr->tabDescriptor= RNIL;
 
918
    regTabPtr->readKeyArray= RNIL;
 
919
    regTabPtr->readFunctionArray= NULL;
 
920
    regTabPtr->updateFunctionArray= NULL;
 
921
    regTabPtr->charsetArray= NULL;
 
922
 
 
923
    // move to start of descriptor
 
924
    descriptor -= offset[3];
 
925
    Uint32 retNo= getTabDescrWord(descriptor + ZTD_DATASIZE);
 
926
    ndbrequire(getTabDescrWord(descriptor + ZTD_HEADER) == ZTD_TYPE_NORMAL);
 
927
    ndbrequire(retNo == getTabDescrWord((descriptor + retNo) - ZTD_TR_SIZE));
 
928
    ndbrequire(ZTD_TYPE_NORMAL ==
 
929
               getTabDescrWord((descriptor + retNo) - ZTD_TR_TYPE));
 
930
    freeTabDescr(descriptor, retNo);
 
931
  }
 
932
}
 
933
 
 
934
void Dbtup::releaseFragment(Signal* signal, Uint32 tableId, 
 
935
                            Uint32 logfile_group_id)
 
936
{
 
937
  TablerecPtr tabPtr;
 
938
  tabPtr.i= tableId;
 
939
  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
 
940
  Uint32 fragIndex = RNIL;
 
941
  Uint32 fragId = RNIL;
 
942
  Uint32 i = 0;
 
943
  for (i = 0; i < MAX_FRAG_PER_NODE; i++) {
 
944
    jam();
 
945
    if (tabPtr.p->fragid[i] != RNIL) {
 
946
      jam();
 
947
      fragIndex= tabPtr.p->fragrec[i];
 
948
      fragId= tabPtr.p->fragid[i];
 
949
      break;
 
950
    }
 
951
  }
 
952
  if (fragIndex != RNIL) {
 
953
    jam();
 
954
    
 
955
    signal->theData[0] = ZUNMAP_PAGES;
 
956
    signal->theData[1] = tabPtr.i;
 
957
    signal->theData[2] = fragIndex;
 
958
    signal->theData[3] = 0;
 
959
    sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);  
 
960
    return;
 
961
  }
 
962
 
 
963
  if (logfile_group_id != RNIL)
 
964
  {
 
965
    Callback cb;
 
966
    cb.m_callbackData= tabPtr.i;
 
967
    cb.m_callbackFunction = 
 
968
      safe_cast(&Dbtup::drop_table_log_buffer_callback);
 
969
    Uint32 sz= sizeof(Disk_undo::Drop) >> 2;
 
970
    int r0 = c_lgman->alloc_log_space(logfile_group_id, sz);
 
971
    if (r0)
 
972
    {
 
973
      jam();
 
974
      warningEvent("Failed to alloc log space for drop table: %u",
 
975
                   tabPtr.i);
 
976
      goto done;
 
977
    }
 
978
 
 
979
    Logfile_client lgman(this, c_lgman, logfile_group_id);
 
980
    int res= lgman.get_log_buffer(signal, sz, &cb);
 
981
    switch(res){
 
982
    case 0:
 
983
      jam();
 
984
      return;
 
985
    case -1:
 
986
      warningEvent("Failed to get log buffer for drop table: %u",
 
987
                   tabPtr.i);
 
988
      c_lgman->free_log_space(logfile_group_id, sz);
 
989
      goto done;
 
990
      break;
 
991
    default:
 
992
      execute(signal, cb, logfile_group_id);
 
993
      return;
 
994
    }
 
995
  }
 
996
 
 
997
done:
 
998
  drop_table_logsync_callback(signal, tabPtr.i, RNIL);
 
999
}
 
1000
 
 
1001
void
 
1002
Dbtup::drop_fragment_unmap_pages(Signal *signal, 
 
1003
                                 TablerecPtr tabPtr, 
 
1004
                                 FragrecordPtr fragPtr,
 
1005
                                 Uint32 pos)
 
1006
{
 
1007
  if (tabPtr.p->m_no_of_disk_attributes)
 
1008
  {
 
1009
    jam();
 
1010
    Disk_alloc_info& alloc_info= fragPtr.p->m_disk_alloc_info;
 
1011
 
 
1012
    if (!alloc_info.m_unmap_pages.isEmpty())
 
1013
    {
 
1014
      jam();
 
1015
      ndbout_c("waiting for unmape pages");
 
1016
      signal->theData[0] = ZUNMAP_PAGES;
 
1017
      signal->theData[1] = tabPtr.i;
 
1018
      signal->theData[2] = fragPtr.i;
 
1019
      signal->theData[3] = pos;
 
1020
      sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);  
 
1021
      return;
 
1022
    }
 
1023
    while(alloc_info.m_dirty_pages[pos].isEmpty() && pos < MAX_FREE_LIST)
 
1024
      pos++;
 
1025
    
 
1026
    if (pos == MAX_FREE_LIST)
 
1027
    {
 
1028
      if(alloc_info.m_curr_extent_info_ptr_i != RNIL)
 
1029
      {
 
1030
        Local_extent_info_list
 
1031
          list(c_extent_pool, alloc_info.m_free_extents[0]);
 
1032
        Ptr<Extent_info> ext_ptr;
 
1033
        c_extent_pool.getPtr(ext_ptr, alloc_info.m_curr_extent_info_ptr_i);
 
1034
        list.add(ext_ptr);
 
1035
        alloc_info.m_curr_extent_info_ptr_i= RNIL;
 
1036
      }
 
1037
      
 
1038
      drop_fragment_free_extent(signal, tabPtr, fragPtr, 0);
 
1039
      return;
 
1040
    }
 
1041
    
 
1042
    Ptr<Page> pagePtr;
 
1043
    ArrayPool<Page> *pool= (ArrayPool<Page>*)&m_global_page_pool;
 
1044
    {
 
1045
      LocalDLList<Page> list(*pool, alloc_info.m_dirty_pages[pos]);
 
1046
      list.first(pagePtr);
 
1047
      list.remove(pagePtr);
 
1048
    }
 
1049
    
 
1050
    Page_cache_client::Request req;
 
1051
    req.m_page.m_page_no = pagePtr.p->m_page_no;
 
1052
    req.m_page.m_file_no = pagePtr.p->m_file_no;
 
1053
    
 
1054
    req.m_callback.m_callbackData= pos;
 
1055
    req.m_callback.m_callbackFunction = 
 
1056
      safe_cast(&Dbtup::drop_fragment_unmap_page_callback);
 
1057
    
 
1058
    int flags= Page_cache_client::COMMIT_REQ;
 
1059
    int res= m_pgman.get_page(signal, req, flags);
 
1060
    switch(res)
 
1061
    {
 
1062
    case 0:
 
1063
    case -1:
 
1064
      break;
 
1065
    default:
 
1066
      ndbrequire((Uint32)res == pagePtr.i);
 
1067
      drop_fragment_unmap_page_callback(signal, pos, res);
 
1068
    }
 
1069
    return;
 
1070
  }
 
1071
  drop_fragment_free_extent(signal, tabPtr, fragPtr, 0);  
 
1072
}
 
1073
 
 
1074
void
 
1075
Dbtup::drop_fragment_unmap_page_callback(Signal* signal, 
 
1076
                                         Uint32 pos, Uint32 page_id)
 
1077
{
 
1078
  Ptr<GlobalPage> page;
 
1079
  m_global_page_pool.getPtr(page, page_id);
 
1080
  
 
1081
  Local_key key;
 
1082
  key.m_page_no = ((Page*)page.p)->m_page_no;
 
1083
  key.m_file_no = ((Page*)page.p)->m_file_no;
 
1084
 
 
1085
  Uint32 fragId = ((Page*)page.p)->m_fragment_id;
 
1086
  Uint32 tableId = ((Page*)page.p)->m_table_id;
 
1087
  m_pgman.drop_page(key, page_id);
 
1088
 
 
1089
  TablerecPtr tabPtr;
 
1090
  tabPtr.i= tableId;
 
1091
  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
 
1092
  
 
1093
  FragrecordPtr fragPtr;
 
1094
  getFragmentrec(fragPtr, fragId, tabPtr.p);
 
1095
  
 
1096
  signal->theData[0] = ZUNMAP_PAGES;
 
1097
  signal->theData[1] = tabPtr.i;
 
1098
  signal->theData[2] = fragPtr.i;
 
1099
  signal->theData[3] = pos;
 
1100
  sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);  
 
1101
}
 
1102
 
 
1103
void
 
1104
Dbtup::drop_fragment_free_extent(Signal *signal, 
 
1105
                                 TablerecPtr tabPtr, 
 
1106
                                 FragrecordPtr fragPtr,
 
1107
                                 Uint32 pos)
 
1108
{
 
1109
  if (tabPtr.p->m_no_of_disk_attributes)
 
1110
  {
 
1111
    Disk_alloc_info& alloc_info= fragPtr.p->m_disk_alloc_info;
 
1112
    for(; pos<EXTENT_SEARCH_MATRIX_SIZE; pos++)
 
1113
    {
 
1114
      if(!alloc_info.m_free_extents[pos].isEmpty())
 
1115
      {
 
1116
        jam();
 
1117
        Callback cb;
 
1118
        cb.m_callbackData= fragPtr.i;
 
1119
        cb.m_callbackFunction = 
 
1120
          safe_cast(&Dbtup::drop_fragment_free_extent_log_buffer_callback);
 
1121
#if NOT_YET_UNDO_FREE_EXTENT
 
1122
        Uint32 sz= sizeof(Disk_undo::FreeExtent) >> 2;
 
1123
        (void) c_lgman->alloc_log_space(fragPtr.p->m_logfile_group_id, sz);
 
1124
        
 
1125
        Logfile_client lgman(this, c_lgman, fragPtr.p->m_logfile_group_id);
 
1126
        
 
1127
        int res= lgman.get_log_buffer(signal, sz, &cb);
 
1128
        switch(res){
 
1129
        case 0:
 
1130
          jam();
 
1131
          return;
 
1132
        case -1:
 
1133
          ndbrequire("NOT YET IMPLEMENTED" == 0);
 
1134
          break;
 
1135
        default:
 
1136
          execute(signal, cb, fragPtr.p->m_logfile_group_id);
 
1137
          return;
 
1138
        }
 
1139
#else
 
1140
        execute(signal, cb, fragPtr.p->m_logfile_group_id);     
 
1141
        return;
 
1142
#endif
 
1143
      }
 
1144
    }
 
1145
    
 
1146
    ArrayPool<Page> *cheat_pool= (ArrayPool<Page>*)&m_global_page_pool;
 
1147
    for(pos= 0; pos<MAX_FREE_LIST; pos++)
 
1148
    {
 
1149
      ndbrequire(alloc_info.m_page_requests[pos].isEmpty());
 
1150
      LocalDLList<Page> list(* cheat_pool, alloc_info.m_dirty_pages[pos]);
 
1151
      list.remove();
 
1152
    }
 
1153
  }
 
1154
  
 
1155
  signal->theData[0] = ZFREE_VAR_PAGES;
 
1156
  signal->theData[1] = tabPtr.i;
 
1157
  signal->theData[2] = fragPtr.i;
 
1158
  sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);  
 
1159
}
 
1160
 
 
1161
void
 
1162
Dbtup::drop_table_log_buffer_callback(Signal* signal, Uint32 tablePtrI,
 
1163
                                      Uint32 logfile_group_id)
 
1164
{
 
1165
  TablerecPtr tabPtr;
 
1166
  tabPtr.i = tablePtrI;
 
1167
  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
 
1168
  
 
1169
  ndbrequire(tabPtr.p->m_no_of_disk_attributes);
 
1170
 
 
1171
  Disk_undo::Drop drop;
 
1172
  drop.m_table = tabPtr.i;
 
1173
  drop.m_type_length = 
 
1174
    (Disk_undo::UNDO_DROP << 16) | (sizeof(drop) >> 2);
 
1175
  Logfile_client lgman(this, c_lgman, logfile_group_id);
 
1176
  
 
1177
  Logfile_client::Change c[1] = {{ &drop, sizeof(drop) >> 2 } };
 
1178
  Uint64 lsn = lgman.add_entry(c, 1);
 
1179
 
 
1180
  Logfile_client::Request req;
 
1181
  req.m_callback.m_callbackData= tablePtrI;
 
1182
  req.m_callback.m_callbackFunction = 
 
1183
    safe_cast(&Dbtup::drop_table_logsync_callback);
 
1184
  
 
1185
  int ret = lgman.sync_lsn(signal, lsn, &req, 0);
 
1186
  switch(ret){
 
1187
  case 0:
 
1188
    return;
 
1189
  case -1:
 
1190
    warningEvent("Failed to syn log for drop of table: %u", tablePtrI);
 
1191
  default:
 
1192
    execute(signal, req.m_callback, logfile_group_id);
 
1193
  }
 
1194
}
 
1195
 
 
1196
void
 
1197
Dbtup::drop_table_logsync_callback(Signal* signal, 
 
1198
                                   Uint32 tabPtrI, 
 
1199
                                   Uint32 logfile_group_id)
 
1200
{
 
1201
  TablerecPtr tabPtr;
 
1202
  tabPtr.i = tabPtrI;
 
1203
  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
 
1204
  
 
1205
  DropTabConf * const dropConf= (DropTabConf *)signal->getDataPtrSend();
 
1206
  dropConf->senderRef= reference();
 
1207
  dropConf->senderData= tabPtr.p->m_dropTable.tabUserPtr;
 
1208
  dropConf->tableId= tabPtr.i;
 
1209
  sendSignal(tabPtr.p->m_dropTable.tabUserRef, GSN_DROP_TAB_CONF,
 
1210
             signal, DropTabConf::SignalLength, JBB);
 
1211
  
 
1212
  releaseTabDescr(tabPtr.p);
 
1213
  initTab(tabPtr.p);
 
1214
}
 
1215
 
 
1216
void
 
1217
Dbtup::drop_fragment_free_extent_log_buffer_callback(Signal* signal,
 
1218
                                                     Uint32 fragPtrI,
 
1219
                                                     Uint32 unused)
 
1220
{
 
1221
  FragrecordPtr fragPtr;
 
1222
  fragPtr.i = fragPtrI;
 
1223
  ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
 
1224
 
 
1225
  TablerecPtr tabPtr;
 
1226
  tabPtr.i = fragPtr.p->fragTableId;
 
1227
  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
 
1228
 
 
1229
  ndbrequire(tabPtr.p->m_no_of_disk_attributes);
 
1230
  Disk_alloc_info& alloc_info= fragPtr.p->m_disk_alloc_info;  
 
1231
 
 
1232
  for(Uint32 pos = 0; pos<EXTENT_SEARCH_MATRIX_SIZE; pos++)
 
1233
  {
 
1234
    if(!alloc_info.m_free_extents[pos].isEmpty())
 
1235
    {
 
1236
      jam();
 
1237
      Local_extent_info_list
 
1238
        list(c_extent_pool, alloc_info.m_free_extents[pos]);
 
1239
      Ptr<Extent_info> ext_ptr;
 
1240
      list.first(ext_ptr);
 
1241
 
 
1242
#if NOT_YET_UNDO_FREE_EXTENT
 
1243
#error "This code is complete"
 
1244
#error "but not needed until we do dealloc of empty extents"
 
1245
      Disk_undo::FreeExtent free;
 
1246
      free.m_table = tabPtr.i;
 
1247
      free.m_fragment = fragPtr.p->fragmentId;
 
1248
      free.m_file_no = ext_ptr.p->m_key.m_file_no;
 
1249
      free.m_page_no = ext_ptr.p->m_key.m_page_no;
 
1250
      free.m_type_length = 
 
1251
        (Disk_undo::UNDO_FREE_EXTENT << 16) | (sizeof(free) >> 2);
 
1252
      Logfile_client lgman(this, c_lgman, fragPtr.p->m_logfile_group_id);
 
1253
      
 
1254
      Logfile_client::Change c[1] = {{ &free, sizeof(free) >> 2 } };
 
1255
      Uint64 lsn = lgman.add_entry(c, 1);
 
1256
#else
 
1257
      Uint64 lsn = 0;
 
1258
#endif
 
1259
      
 
1260
      Tablespace_client tsman(signal, c_tsman, tabPtr.i, 
 
1261
                              fragPtr.p->fragmentId,
 
1262
                              fragPtr.p->m_tablespace_id);
 
1263
      
 
1264
      tsman.free_extent(&ext_ptr.p->m_key, lsn);
 
1265
      c_extent_hash.remove(ext_ptr);
 
1266
      list.release(ext_ptr);
 
1267
      
 
1268
      signal->theData[0] = ZFREE_EXTENT;
 
1269
      signal->theData[1] = tabPtr.i;
 
1270
      signal->theData[2] = fragPtr.i;
 
1271
      signal->theData[3] = pos;
 
1272
      sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);  
 
1273
      return;
 
1274
    }
 
1275
  }
 
1276
  ndbrequire(false);
 
1277
}
 
1278
 
 
1279
void
 
1280
Dbtup::drop_fragment_free_var_pages(Signal* signal)
 
1281
{
 
1282
  jam();
 
1283
  Uint32 tableId = signal->theData[1];
 
1284
  Uint32 fragPtrI = signal->theData[2];
 
1285
  
 
1286
  TablerecPtr tabPtr;
 
1287
  tabPtr.i= tableId;
 
1288
  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
 
1289
  
 
1290
  FragrecordPtr fragPtr;
 
1291
  fragPtr.i = fragPtrI;
 
1292
  ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
 
1293
  
 
1294
  PagePtr pagePtr;
 
1295
  if ((pagePtr.i = fragPtr.p->m_var_page_chunks) != RNIL)
 
1296
  {
 
1297
    c_page_pool.getPtr(pagePtr);
 
1298
    Var_page* page = (Var_page*)pagePtr.p;
 
1299
    fragPtr.p->m_var_page_chunks = page->next_chunk;
 
1300
 
 
1301
    Uint32 sz = page->chunk_size;
 
1302
    returnCommonArea(pagePtr.i, sz);
 
1303
    
 
1304
    signal->theData[0] = ZFREE_VAR_PAGES;
 
1305
    signal->theData[1] = tabPtr.i;
 
1306
    signal->theData[2] = fragPtr.i;
 
1307
    sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);  
 
1308
    return;
 
1309
  }
 
1310
 
 
1311
  /**
 
1312
   * Remove LCP's for fragment
 
1313
   */
 
1314
  tabPtr.p->m_dropTable.m_lcpno = 0;
 
1315
  tabPtr.p->m_dropTable.m_fragPtrI = fragPtr.i;
 
1316
  drop_fragment_fsremove(signal, tabPtr, fragPtr);
 
1317
}
 
1318
 
 
1319
void
 
1320
Dbtup::drop_fragment_fsremove_done(Signal* signal, 
 
1321
                                   TablerecPtr tabPtr,
 
1322
                                   FragrecordPtr fragPtr)
 
1323
{
 
1324
  /**
 
1325
   * LCP's removed...
 
1326
   *   now continue with "next"
 
1327
   */
 
1328
  Uint32 logfile_group_id = fragPtr.p->m_logfile_group_id ;
 
1329
  releaseFragPages(fragPtr.p);
 
1330
  Uint32 i;
 
1331
  for(i= 0; i<MAX_FRAG_PER_NODE; i++)
 
1332
    if(tabPtr.p->fragrec[i] == fragPtr.i)
 
1333
      break;
 
1334
  
 
1335
  ndbrequire(i != MAX_FRAG_PER_NODE);
 
1336
  tabPtr.p->fragid[i]= RNIL;
 
1337
  tabPtr.p->fragrec[i]= RNIL;
 
1338
  releaseFragrec(fragPtr);
 
1339
  
 
1340
  signal->theData[0]= ZREL_FRAG;
 
1341
  signal->theData[1]= tabPtr.i;
 
1342
  signal->theData[2]= logfile_group_id;
 
1343
  sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);  
 
1344
  return;
 
1345
}
 
1346
 
 
1347
// Remove LCP
 
1348
 
 
1349
void
 
1350
Dbtup::drop_fragment_fsremove(Signal* signal, 
 
1351
                              TablerecPtr tabPtr, 
 
1352
                              FragrecordPtr fragPtr)
 
1353
{
 
1354
  FsRemoveReq* req = (FsRemoveReq*)signal->getDataPtrSend();
 
1355
  req->userReference = reference();
 
1356
  req->userPointer = tabPtr.i;
 
1357
  req->directory = 0;
 
1358
  req->ownDirectory = 0;
 
1359
  
 
1360
  Uint32 lcpno = tabPtr.p->m_dropTable.m_lcpno;
 
1361
  Uint32 fragId = fragPtr.p->fragmentId;
 
1362
  Uint32 tableId = fragPtr.p->fragTableId;
 
1363
 
 
1364
  FsOpenReq::setVersion(req->fileNumber, 5);
 
1365
  FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_DATA);
 
1366
  FsOpenReq::v5_setLcpNo(req->fileNumber, lcpno);
 
1367
  FsOpenReq::v5_setTableId(req->fileNumber, tableId);
 
1368
  FsOpenReq::v5_setFragmentId(req->fileNumber, fragId);
 
1369
  sendSignal(NDBFS_REF, GSN_FSREMOVEREQ, signal, 
 
1370
             FsRemoveReq::SignalLength, JBB);
 
1371
}
 
1372
 
 
1373
void
 
1374
Dbtup::execFSREMOVEREF(Signal* signal)
 
1375
{
 
1376
  jamEntry();
 
1377
  FsRef* ref = (FsRef*)signal->getDataPtr();
 
1378
  Uint32 userPointer = ref->userPointer;
 
1379
  FsConf* conf = (FsConf*)signal->getDataPtrSend();
 
1380
  conf->userPointer = userPointer;
 
1381
  execFSREMOVECONF(signal);
 
1382
}
 
1383
 
 
1384
void
 
1385
Dbtup::execFSREMOVECONF(Signal* signal)
 
1386
{
 
1387
  jamEntry();
 
1388
  FsConf* conf = (FsConf*)signal->getDataPtrSend();
 
1389
  
 
1390
  TablerecPtr tabPtr; 
 
1391
  FragrecordPtr fragPtr;
 
1392
 
 
1393
  tabPtr.i = conf->userPointer;
 
1394
  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
 
1395
 
 
1396
  ndbrequire(tabPtr.p->tableStatus == DROPPING);
 
1397
  
 
1398
  fragPtr.i = tabPtr.p->m_dropTable.m_fragPtrI;
 
1399
  ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
 
1400
 
 
1401
  tabPtr.p->m_dropTable.m_lcpno++;
 
1402
  if (tabPtr.p->m_dropTable.m_lcpno < 3)
 
1403
  {
 
1404
    jam();
 
1405
    drop_fragment_fsremove(signal, tabPtr, fragPtr);
 
1406
  }
 
1407
  else
 
1408
  {
 
1409
    jam();
 
1410
    drop_fragment_fsremove_done(signal, tabPtr, fragPtr);
 
1411
  }
 
1412
}
 
1413
// End remove LCP
 
1414
 
 
1415
void
 
1416
Dbtup::start_restore_lcp(Uint32 tableId, Uint32 fragId)
 
1417
{
 
1418
  TablerecPtr tabPtr;
 
1419
  tabPtr.i= tableId;
 
1420
  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
 
1421
  
 
1422
  tabPtr.p->m_dropTable.tabUserPtr= tabPtr.p->m_attributes[DD].m_no_of_fixsize;
 
1423
  tabPtr.p->m_dropTable.tabUserRef= tabPtr.p->m_attributes[DD].m_no_of_varsize;
 
1424
  
 
1425
  Uint32 *tabDesc = (Uint32*)(tableDescriptor+tabPtr.p->tabDescriptor);
 
1426
  for(Uint32 i= 0; i<tabPtr.p->m_no_of_attributes; i++)
 
1427
  {
 
1428
    Uint32 disk= AttributeDescriptor::getDiskBased(* tabDesc);
 
1429
    Uint32 null= AttributeDescriptor::getNullable(* tabDesc);
 
1430
 
 
1431
    ndbrequire(tabPtr.p->notNullAttributeMask.get(i) != null);
 
1432
    if(disk)
 
1433
      tabPtr.p->notNullAttributeMask.clear(i);
 
1434
    tabDesc += 2;
 
1435
  }
 
1436
  
 
1437
  tabPtr.p->m_no_of_disk_attributes = 0;
 
1438
  tabPtr.p->m_attributes[DD].m_no_of_fixsize = 0;
 
1439
  tabPtr.p->m_attributes[DD].m_no_of_varsize = 0;
 
1440
}
 
1441
void
 
1442
Dbtup::complete_restore_lcp(Uint32 tableId, Uint32 fragId)
 
1443
{
 
1444
  TablerecPtr tabPtr;
 
1445
  tabPtr.i= tableId;
 
1446
  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
 
1447
  
 
1448
  tabPtr.p->m_attributes[DD].m_no_of_fixsize= tabPtr.p->m_dropTable.tabUserPtr;
 
1449
  tabPtr.p->m_attributes[DD].m_no_of_varsize= tabPtr.p->m_dropTable.tabUserRef;
 
1450
  
 
1451
  tabPtr.p->m_no_of_disk_attributes = 
 
1452
    tabPtr.p->m_attributes[DD].m_no_of_fixsize + 
 
1453
    tabPtr.p->m_attributes[DD].m_no_of_varsize;
 
1454
  
 
1455
  Uint32 *tabDesc = (Uint32*)(tableDescriptor+tabPtr.p->tabDescriptor);
 
1456
  for(Uint32 i= 0; i<tabPtr.p->m_no_of_attributes; i++)
 
1457
  {
 
1458
    Uint32 disk= AttributeDescriptor::getDiskBased(* tabDesc);
 
1459
    Uint32 null= AttributeDescriptor::getNullable(* tabDesc);
 
1460
    
 
1461
    if(disk && !null)
 
1462
      tabPtr.p->notNullAttributeMask.set(i);
 
1463
    
 
1464
    tabDesc += 2;
 
1465
  }
 
1466
}
 
1467
 
 
1468
bool
 
1469
Dbtup::get_frag_info(Uint32 tableId, Uint32 fragId, Uint32* maxPage)
 
1470
{
 
1471
  jamEntry();
 
1472
  TablerecPtr tabPtr;
 
1473
  tabPtr.i= tableId;
 
1474
  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
 
1475
 
 
1476
  FragrecordPtr fragPtr;
 
1477
  getFragmentrec(fragPtr, fragId, tabPtr.p);
 
1478
  
 
1479
  if (maxPage)
 
1480
  {
 
1481
    * maxPage = fragPtr.p->noOfPages;
 
1482
  }
 
1483
 
 
1484
  return true;
 
1485
}