MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DbtupMeta.cpp
1 /*
2  Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 
19 #define DBTUP_C
20 #define DBTUP_META_CPP
21 #include "Dbtup.hpp"
22 #include <RefConvert.hpp>
23 #include <ndb_limits.h>
24 #include <pc.hpp>
25 // Error codes
26 #include <signaldata/CreateTable.hpp>
27 #include <signaldata/CreateTab.hpp>
28 #include <signaldata/TupFrag.hpp>
29 #include <signaldata/FsRef.hpp>
30 #include <signaldata/FsConf.hpp>
31 #include <signaldata/FsRemoveReq.hpp>
32 #include <signaldata/DropTab.hpp>
33 #include <signaldata/AlterTab.hpp>
34 #include <signaldata/AlterTable.hpp>
35 #include <signaldata/CreateFilegroupImpl.hpp>
36 #include <AttributeDescriptor.hpp>
37 #include "AttributeOffset.hpp"
38 #include <my_sys.h>
39 #include <signaldata/LqhFrag.hpp>
40 #include <signaldata/AttrInfo.hpp>
41 
42 #include <EventLogger.hpp>
43 extern EventLogger * g_eventLogger;
44 
45 void
46 Dbtup::execCREATE_TAB_REQ(Signal* signal)
47 {
48  jamEntry();
49 
50  CreateTabReq reqCopy = *(CreateTabReq*)signal->getDataPtr();
51  CreateTabReq* req = &reqCopy;
52 
53  TablerecPtr regTabPtr;
54  regTabPtr.i = req->tableId;
55  ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
56 
57  if (regTabPtr.p->tableStatus != NOT_DEFINED)
58  {
59  jam();
60  ndbout_c("regTabPtr.p->tableStatus : %u", regTabPtr.p->tableStatus);
61  terrorCode = CreateTableRef::TableAlreadyExist;
62  goto sendref;
63  }
64 
65  if (cfirstfreeFragopr == RNIL)
66  {
67  jam();
68  terrorCode = ZNOFREE_FRAGOP_ERROR;
69  goto sendref;
70  }
71 
72  FragoperrecPtr fragOperPtr;
73  seizeFragoperrec(fragOperPtr);
74  fragOperPtr.p->tableidFrag = regTabPtr.i;
75  fragOperPtr.p->attributeCount = req->noOfAttributes;
76  memset(fragOperPtr.p->m_null_bits, 0, sizeof(fragOperPtr.p->m_null_bits));
77  fragOperPtr.p->charsetIndex = 0;
78  fragOperPtr.p->lqhBlockrefFrag = req->senderRef;
79  fragOperPtr.p->m_extra_row_gci_bits =
80  req->GCPIndicator > 1 ? req->GCPIndicator - 1 : 0;
81  fragOperPtr.p->m_extra_row_author_bits = req->extraRowAuthorBits;
82 
83  regTabPtr.p->m_createTable.m_fragOpPtrI = fragOperPtr.i;
84  regTabPtr.p->m_createTable.defValSectionI = RNIL;
85  regTabPtr.p->tableStatus= DEFINING;
86  regTabPtr.p->m_bits = 0;
87  regTabPtr.p->m_bits |= (req->checksumIndicator ? Tablerec::TR_Checksum : 0);
88  regTabPtr.p->m_bits |= (req->GCPIndicator ? Tablerec::TR_RowGCI : 0);
89  regTabPtr.p->m_bits |= (req->forceVarPartFlag? Tablerec::TR_ForceVarPart : 0);
90  regTabPtr.p->m_bits |=
91  (req->GCPIndicator > 1 ? Tablerec::TR_ExtraRowGCIBits : 0);
92  regTabPtr.p->m_bits |= (req->extraRowAuthorBits ? Tablerec::TR_ExtraRowAuthorBits : 0);
93 
94  regTabPtr.p->m_offsets[MM].m_disk_ref_offset= 0;
95  regTabPtr.p->m_offsets[MM].m_null_words= 0;
96  regTabPtr.p->m_offsets[MM].m_fix_header_size= 0;
97  regTabPtr.p->m_offsets[MM].m_max_var_offset= 0;
98  regTabPtr.p->m_offsets[MM].m_max_dyn_offset= 0;
99  regTabPtr.p->m_offsets[MM].m_dyn_null_words= 0;
100 
101  regTabPtr.p->m_offsets[DD].m_disk_ref_offset= 0;
102  regTabPtr.p->m_offsets[DD].m_null_words= 0;
103  regTabPtr.p->m_offsets[DD].m_fix_header_size= 0;
104  regTabPtr.p->m_offsets[DD].m_max_var_offset= 0;
105  regTabPtr.p->m_offsets[DD].m_max_dyn_offset= 0;
106  regTabPtr.p->m_offsets[DD].m_dyn_null_words= 0;
107 
108  regTabPtr.p->m_attributes[MM].m_no_of_fixsize= 0;
109  regTabPtr.p->m_attributes[MM].m_no_of_varsize= 0;
110  regTabPtr.p->m_attributes[MM].m_no_of_dynamic= 0;
111  regTabPtr.p->m_attributes[MM].m_no_of_dyn_fix= 0;
112  regTabPtr.p->m_attributes[MM].m_no_of_dyn_var= 0;
113  regTabPtr.p->m_attributes[DD].m_no_of_fixsize= 0;
114  regTabPtr.p->m_attributes[DD].m_no_of_varsize= 0;
115  regTabPtr.p->m_attributes[DD].m_no_of_dynamic= 0;
116  regTabPtr.p->m_attributes[DD].m_no_of_dyn_fix= 0;
117  regTabPtr.p->m_attributes[DD].m_no_of_dyn_var= 0;
118 
119  // Reserve space for bitmap length
120  regTabPtr.p->m_dyn_null_bits[MM]= DYN_BM_LEN_BITS;
121  regTabPtr.p->m_dyn_null_bits[DD]= DYN_BM_LEN_BITS;
122  regTabPtr.p->noOfKeyAttr= req->noOfKeyAttr;
123  regTabPtr.p->noOfCharsets= req->noOfCharsets;
124  regTabPtr.p->m_no_of_attributes= req->noOfAttributes;
125  regTabPtr.p->dynTabDescriptor[MM]= RNIL;
126  regTabPtr.p->dynTabDescriptor[DD]= RNIL;
127  regTabPtr.p->m_no_of_extra_columns = 0;
128 
129  if (regTabPtr.p->m_bits & Tablerec::TR_ExtraRowGCIBits)
130  {
131  jam();
132  regTabPtr.p->m_no_of_extra_columns++;
133  }
134 
135  if (regTabPtr.p->m_bits & Tablerec::TR_ExtraRowAuthorBits)
136  {
137  jam();
138  regTabPtr.p->m_no_of_extra_columns++;
139  }
140 
141  {
142  Uint32 offset[10];
143  Uint32 allocSize= getTabDescrOffsets(req->noOfAttributes,
144  req->noOfCharsets,
145  req->noOfKeyAttr,
146  regTabPtr.p->m_no_of_extra_columns,
147  offset);
148  Uint32 tableDescriptorRef= allocTabDescr(allocSize);
149  if (tableDescriptorRef == RNIL)
150  {
151  jam();
152  goto error;
153  }
154  setUpDescriptorReferences(tableDescriptorRef, regTabPtr.p, offset);
155  }
156 
157  {
158  CreateTabConf* conf = (CreateTabConf*)signal->getDataPtrSend();
159  conf->senderData = req->senderData;
160  conf->senderRef = reference();
161  conf->tupConnectPtr = fragOperPtr.i;
162  sendSignal(req->senderRef, GSN_CREATE_TAB_CONF, signal,
163  CreateTabConf::SignalLength, JBB);
164  }
165 
166  return;
167 
168 error:
169  regTabPtr.p->tableStatus = NOT_DEFINED;
170  releaseFragoperrec(fragOperPtr);
171 
172 sendref:
173  CreateTabRef* ref = (CreateTabRef*)signal->getDataPtrSend();
174  ref->senderData = req->senderData;
175  ref->senderRef = reference();
176  ref->errorCode = terrorCode;
177  sendSignal(req->senderRef, GSN_CREATE_TAB_REF, signal,
178  CreateTabRef::SignalLength, JBB);
179 }
180 
181 void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
182 {
183  FragoperrecPtr fragOperPtr;
184  TablerecPtr regTabPtr;
185 
186  jamEntry();
187  fragOperPtr.i= signal->theData[0];
188  ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
189  Uint32 attrId = signal->theData[2];
190  Uint32 attrDescriptor = signal->theData[3];
191  // DICT sends charset number in upper half
192  Uint32 csNumber = (signal->theData[4] >> 16);
193 
194  regTabPtr.i= fragOperPtr.p->tableidFrag;
195  ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
196 
197  ndbrequire(fragOperPtr.p->attributeCount > 0);
198  fragOperPtr.p->attributeCount--;
199  const bool lastAttr = (fragOperPtr.p->attributeCount == 0);
200 
201  Uint32 extraAttrId = 0;
202 
203  Uint32 firstTabDesIndex= regTabPtr.p->tabDescriptor + (attrId * ZAD_SIZE);
204  setTabDescrWord(firstTabDesIndex, attrDescriptor);
205  Uint32 attrLen = AttributeDescriptor::getSize(attrDescriptor);
206 
207  Uint32 attrDes2= 0;
208  Uint32 bytes= AttributeDescriptor::getSizeInBytes(attrDescriptor);
209  Uint32 words= (bytes + 3) / 4;
210  Uint32 ind= AttributeDescriptor::getDiskBased(attrDescriptor);
211  if (!AttributeDescriptor::getDynamic(attrDescriptor)) {
212  jam();
213  Uint32 null_pos;
214  ndbrequire(ind <= 1);
215  null_pos= fragOperPtr.p->m_null_bits[ind];
216 
217  if (AttributeDescriptor::getNullable(attrDescriptor))
218  {
219  jam();
220  fragOperPtr.p->m_null_bits[ind]++;
221  }
222 
223  if (AttributeDescriptor::getArrayType(attrDescriptor)==NDB_ARRAYTYPE_FIXED
224  || ind==DD)
225  {
226  jam();
227  regTabPtr.p->m_attributes[ind].m_no_of_fixsize++;
228  if(attrLen == 0)
229  {
230  /* Static bit type. */
231  jam();
232  Uint32 bitCount = AttributeDescriptor::getArraySize(attrDescriptor);
233  fragOperPtr.p->m_null_bits[ind] += bitCount;
234  }
235  }
236  else
237  {
238  jam();
239  regTabPtr.p->m_attributes[ind].m_no_of_varsize++;
240  }
241  if (null_pos > AO_NULL_FLAG_POS_MASK)
242  {
243  jam();
244  terrorCode = ZTOO_MANY_BITS_ERROR;
245  goto error;
246  }
247  AttributeOffset::setNullFlagPos(attrDes2, null_pos);
248  } else {
249  /* A dynamic attribute. */
250  ndbrequire(ind==MM);
251  regTabPtr.p->m_attributes[ind].m_no_of_dynamic++;
252  /*
253  * The dynamic attribute format always require a 'null' bit. So
254  * storing NOT NULL attributes as dynamic is not all that useful
255  * (but not harmful in any way either).
256  * Later we might implement NOT NULL DEFAULT xxx by storing the value
257  * xxx internally as 'null'.
258  */
259 
260  Uint32 null_pos= regTabPtr.p->m_dyn_null_bits[ind];
261 
262  if (AttributeDescriptor::getArrayType(attrDescriptor)==NDB_ARRAYTYPE_FIXED)
263  {
264  /* A fixed-size dynamic attribute. */
265  jam();
266  if (AttributeDescriptor::getSize(attrDescriptor)==0)
267  {
273  Uint32 bits= AttributeDescriptor::getArraySize(attrDescriptor);
278  null_pos+= bits;
279  regTabPtr.p->m_dyn_null_bits[ind]+= bits+1;
280  }
281  else
282  {
283  jam();
284  /*
285  * We use one NULL bit per 4 bytes of dynamic fixed-size attribute. So
286  * for dynamic fixsize longer than 64 bytes (16 null bits), it is more
287  * efficient to store them as dynamic varsize internally.
288  */
289  if(words > InternalMaxDynFix)
290  goto treat_as_varsize;
291 
292  regTabPtr.p->m_attributes[ind].m_no_of_dyn_fix++;
293  Uint32 null_bits= (bytes+3) >> 2;
294  regTabPtr.p->m_dyn_null_bits[ind]+= null_bits;
295  }
296  }
297  else
298  {
299  /* A variable-sized dynamic attribute. */
300  treat_as_varsize:
301  jam();
302  regTabPtr.p->m_attributes[ind].m_no_of_dyn_var++;
303  regTabPtr.p->m_dyn_null_bits[ind]++;
304  }
305  AttributeOffset::setNullFlagPos(attrDes2, null_pos);
306 
307  ndbassert((regTabPtr.p->m_attributes[ind].m_no_of_dyn_var +
308  regTabPtr.p->m_attributes[ind].m_no_of_dyn_fix) <=
309  regTabPtr.p->m_attributes[ind].m_no_of_dynamic);
310  }
311  handleCharsetPos(csNumber, regTabPtr.p->charsetArray,
312  regTabPtr.p->noOfCharsets,
313  fragOperPtr.p->charsetIndex, attrDes2);
314  setTabDescrWord(firstTabDesIndex + 1, attrDes2);
315 
316  if ((ERROR_INSERTED(4009) && attrId == 0) ||
317  (ERROR_INSERTED(4010) && lastAttr))
318  {
319  jam();
320  CLEAR_ERROR_INSERT_VALUE;
321  terrorCode = 1;
322  goto error;
323  }
324 
325  if (!receive_defvalue(signal, regTabPtr))
326  goto error;
327 
328  if ((ERROR_INSERTED(4032) && (attrId == 0)) ||
329  (ERROR_INSERTED(4033) && lastAttr))
330  {
331  jam();
332  CLEAR_ERROR_INSERT_VALUE;
333  terrorCode = 1;
334  goto error;
335  }
336 
337  if (! lastAttr)
338  {
339  jam();
340  signal->theData[0] = fragOperPtr.p->lqhPtrFrag;
341  signal->theData[1] = lastAttr;
342  sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUP_ADD_ATTCONF,
343  signal, 2, JBB);
344  return;
345  }
346 
347  if (fragOperPtr.p->m_extra_row_gci_bits)
348  {
349  jam();
350 
351  const Uint32 bits = fragOperPtr.p->m_extra_row_gci_bits;
352 
356  Uint32 desc = 0;
357  Uint32 off = 0;
358 
359  AttributeDescriptor::setSize(desc, 0); // bit
360  AttributeDescriptor::setArraySize(desc, bits);
361  AttributeOffset::setNullFlagPos(off, fragOperPtr.p->m_null_bits[MM]);
362  fragOperPtr.p->m_null_bits[MM] += bits;
363 
364  if (fragOperPtr.p->m_null_bits[MM] > AO_NULL_FLAG_POS_MASK)
365  {
366  jam();
367  terrorCode = ZTOO_MANY_BITS_ERROR;
368  goto error;
369  }
370 
371  Uint32 idx = regTabPtr.p->tabDescriptor;
372  idx += ZAD_SIZE * (regTabPtr.p->m_no_of_attributes + extraAttrId);
373  setTabDescrWord(idx, desc);
374  setTabDescrWord(idx + 1, off);
375 
376  extraAttrId++;
377  }
378 
379  if (fragOperPtr.p->m_extra_row_author_bits)
380  {
381  jam();
382 
383  const Uint32 bits = fragOperPtr.p->m_extra_row_author_bits;
384 
388  Uint32 desc = 0;
389  Uint32 off = 0;
390 
391  AttributeDescriptor::setSize(desc, 0); // bit
392  AttributeDescriptor::setArraySize(desc, bits);
393  AttributeOffset::setNullFlagPos(off, fragOperPtr.p->m_null_bits[MM]);
394  fragOperPtr.p->m_null_bits[MM] += bits;
395 
396  if (fragOperPtr.p->m_null_bits[MM] > AO_NULL_FLAG_POS_MASK)
397  {
398  jam();
399  terrorCode = ZTOO_MANY_BITS_ERROR;
400  goto error;
401  }
402 
403  Uint32 idx = regTabPtr.p->tabDescriptor;
404  idx += ZAD_SIZE * (regTabPtr.p->m_no_of_attributes + extraAttrId);
405  setTabDescrWord(idx, desc);
406  setTabDescrWord(idx + 1, off);
407 
408  extraAttrId++;
409  }
410 
411 #define BTW(x) ((x+31) >> 5)
412  regTabPtr.p->m_offsets[MM].m_null_words= BTW(fragOperPtr.p->m_null_bits[MM]);
413  regTabPtr.p->m_offsets[DD].m_null_words= BTW(fragOperPtr.p->m_null_bits[DD]);
414 #undef BTW
415 
416  {
417  /* Allocate dynamic descriptors. */
418  for (Uint32 i = 0; i < NO_DYNAMICS; ++i)
419  {
420 
421  Uint32 offset[3];
422  Uint32 allocSize= getDynTabDescrOffsets(
423  (regTabPtr.p->m_dyn_null_bits[i]+31)>>5,
424  offset);
425  Uint32 dynTableDescriptorRef= allocTabDescr(allocSize);
426  if (dynTableDescriptorRef == RNIL)
427  {
428  jam();
429  goto error;
430  }
431  setupDynDescriptorReferences(dynTableDescriptorRef,
432  regTabPtr.p, offset, i);
433  }
434  }
435 
436  /* Compute table aggregate metadata. */
437  terrorCode = computeTableMetaData(regTabPtr.p);
438  if (terrorCode)
439  {
440  jam();
441  goto error;
442  }
443 
444 #if 0
445  ndbout << *regTabPtr.p << endl;
446  Uint32 idx= regTabPtr.p->tabDescriptor;
447  for(Uint32 i = 0; i<regTabPtr.p->m_no_of_attributes; i++)
448  {
449  ndbout << i << ": " << endl;
450  ndbout << *(AttributeDescriptor*)(tableDescriptor+idx) << endl;
451  ndbout << *(AttributeOffset*)(tableDescriptor+idx+1) << endl;
452  idx += 2;
453  }
454 #endif
455 
456 #if SYNC_TABLE
457  if (regTabPtr.p->m_no_of_disk_attributes)
458  {
459  jam();
460  if(!(getNodeState().startLevel == NodeState::SL_STARTING &&
461  getNodeState().starting.startPhase <= 4))
462  {
463  CallbackPtr cb;
464  jam();
465 
466  cb.m_callbackData= fragOperPtr.i;
467  cb.m_callbackIndex = UNDO_CREATETABLE_CALLBACK;
468  Uint32 sz= sizeof(Disk_undo::Create) >> 2;
469 
470  D("Logfile_client - execTUP_ADD_ATTRREQ");
471  Logfile_client lgman(this, c_lgman, regFragPtr.p->m_logfile_group_id);
472  if((terrorCode = lgman.alloc_log_space(sz)))
473  {
474  jamEntry();
475  addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
476  return;
477  }
478 
479  jamEntry();
480  int res= lgman.get_log_buffer(signal, sz, &cb);
481  jamEntry();
482  switch(res){
483  case 0:
484  jam();
485  signal->theData[0] = 1;
486  return;
487  case -1:
488  ndbrequire("NOT YET IMPLEMENTED" == 0);
489  break;
490  }
491  execute(signal, cb, regFragPtr.p->m_logfile_group_id);
492  return;
493  }
494  }
495 #endif
496 
497  if (store_default_record(regTabPtr) < 0)
498  {
499  jam();
500  goto error;
501  }
502 
503  ndbrequire(regTabPtr.p->tableStatus == DEFINING);
504  regTabPtr.p->tableStatus= DEFINED;
505 
506  signal->theData[0] = fragOperPtr.p->lqhPtrFrag;
507  signal->theData[1] = lastAttr;
508  sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUP_ADD_ATTCONF,
509  signal, 2, JBB);
510 
511  releaseFragoperrec(fragOperPtr);
512  return;
513 error:
514  {
515  /* Release any unprocessed sections */
516  SectionHandle handle(this, signal);
517  releaseSections(handle);
518  }
519  /* Release segmented section used to receive Attr default value */
520  releaseSection(regTabPtr.p->m_createTable.defValSectionI);
521  regTabPtr.p->m_createTable.defValSectionI = RNIL;
522  free_var_part(DefaultValuesFragment.p, regTabPtr.p, &regTabPtr.p->m_default_value_location);
523  regTabPtr.p->m_default_value_location.setNull();
524 
525  signal->theData[0]= fragOperPtr.p->lqhPtrFrag;
526  signal->theData[1]= terrorCode;
527  sendSignal(fragOperPtr.p->lqhBlockrefFrag,
528  GSN_TUP_ADD_ATTRREF, signal, 2, JBB);
529 
530  return;
531 }
532 
533 bool Dbtup::receive_defvalue(Signal* signal, const TablerecPtr& regTabPtr)
534 {
535  jam();
536  Uint32 defValueBytes = 0;
537  Uint32 defValueWords = 0;
538  Uint32 attrId = signal->theData[2];
539  Uint32 attrDescriptor = signal->theData[3];
540 
541  Uint32 attrLen = AttributeDescriptor::getSize(attrDescriptor);
542  Uint32 arrayType = AttributeDescriptor::getArrayType(attrDescriptor);
543  Uint32 arraySize = AttributeDescriptor::getArraySize(attrDescriptor);
544 
545  const Uint32 numSections = signal->getNoOfSections();
546 
547  if (numSections == 0)
548  return true;
549 
550  jam();
551  SectionHandle handle(this, signal);
553  handle.getSection(ptr, TupAddAttrReq::DEFAULT_VALUE_SECTION_NUM);
554 
555  SimplePropertiesSectionReader r(ptr, getSectionSegmentPool());
556  r.reset();
557 
558  Uint32 ahIn;
559  ndbrequire(r.getWord(&ahIn));
560 
561  defValueBytes = AttributeHeader::getByteSize(ahIn);
562  defValueWords = (defValueBytes + 3) / 4;
563 
564  Uint32 *dst = NULL;
565  AttributeHeader ah(attrId, defValueBytes);
566 
567  if (defValueBytes == 0)
568  {
569  jam();
570  releaseSections(handle);
571  return true;
572  }
573 
574  /* We have a default value, double check to be sure this is not
575  * a primary key
576  */
577  if (AttributeDescriptor::getPrimaryKey(attrDescriptor))
578  {
579  jam();
580  releaseSections(handle);
581  /* Default value for primary key column not supported */
582  terrorCode = 792;
583  return false;
584  }
585 
586  Uint32 bytes;
587  if (attrLen)
588  bytes= AttributeDescriptor::getSizeInBytes(attrDescriptor);
589  else
590  bytes= ((arraySize + AD_SIZE_IN_WORDS_OFFSET)
591  >> AD_SIZE_IN_WORDS_SHIFT) * 4;
592 
593  terrorCode= 0;
594 
595  if (attrLen)
596  {
597  if (arrayType == NDB_ARRAYTYPE_FIXED)
598  {
599  if (defValueBytes != bytes)
600  {
601  terrorCode = ZBAD_DEFAULT_VALUE_LEN;
602  }
603  }
604  else
605  {
606  if (defValueBytes > bytes)
607  {
608  terrorCode = ZBAD_DEFAULT_VALUE_LEN;
609  }
610  }
611  }
612  else
613  {
614  /*
615  * The condition is for BIT type.
616  * Even though it is fixed, the compare operator should be > rather than ==,
617  * for the 4-byte alignemnt, the space for BIT type occupied 4 bytes at least.
618  * yet the bytes of default value can be 1, 2, 3, 4, 5, 6, 7, 8 bytes.
619  */
620  if (defValueBytes > bytes)
621  {
622  terrorCode = ZBAD_DEFAULT_VALUE_LEN;
623  }
624  }
625 
626  jam();
627 
628  if (likely( !terrorCode ))
629  {
630  dst = cinBuffer;
631 
632  ndbrequire(r.getWords(dst, defValueWords));
633 
634  /* Check that VAR types have valid inline length */
635  if ((attrLen) &&
636  (arrayType != NDB_ARRAYTYPE_FIXED))
637  {
638  jam();
639  const uchar* valPtr = (const uchar*) dst;
640  Uint32 internalVarSize = 0;
641 
642  if (arrayType == NDB_ARRAYTYPE_SHORT_VAR)
643  {
644  internalVarSize = 1 + valPtr[0];
645  }
646  else if (arrayType == NDB_ARRAYTYPE_MEDIUM_VAR)
647  {
648  internalVarSize = 2 + valPtr[0] + (256 * Uint32(valPtr[1]));
649  }
650  else
651  {
652  ndbrequire(false);
653  }
654 
655  if (unlikely(internalVarSize != defValueBytes))
656  {
657  jam();
658  terrorCode = ZBAD_DEFAULT_VALUE_LEN;
659  releaseSections(handle);
660  return false;
661  }
662  }
663 
664  if (likely( appendToSection(regTabPtr.p->m_createTable.defValSectionI,
665  (const Uint32 *)&ah, 1) ))
666  {
667  if (likely( appendToSection(regTabPtr.p->m_createTable.defValSectionI,
668  (const Uint32*)dst,
669  defValueWords)))
670  {
671  jam();
672  releaseSections(handle);
673  return true;
674  }
675  }
676  terrorCode = ZMEM_NOMEM_ERROR;
677  }
678 
679  releaseSections(handle);
680  return false;
681 }
682 
683 void Dbtup::execTUPFRAGREQ(Signal* signal)
684 {
685  jamEntry();
686 
687  TupFragReq copy = *(TupFragReq*)signal->getDataPtr();
688  TupFragReq* req = &copy;
689 
690  FragrecordPtr regFragPtr;
691 
692  Uint32 tableId = req->tableId;
693  Uint32 userptr = req->userPtr;
694  Uint32 userRef = req->userRef;
695  Uint32 reqinfo = req->reqInfo;
696  Uint32 fragId = req->fragId;
697  Uint32 tablespace_id = req->tablespaceid;
698  Uint32 changeMask = req->changeMask;
699 
700  Uint64 maxRows =
701  (((Uint64)req->maxRowsHigh) << 32) + req->maxRowsLow;
702  Uint64 minRows =
703  (((Uint64)req->minRowsHigh) << 32) + req->minRowsLow;
704 
705  (void)reqinfo;
706  (void)maxRows;
707  (void)minRows;
708 
709  if (req->userPtr == (Uint32)-1)
710  {
711  jam();
712  abortAddFragOp(signal);
713  return;
714  }
715 
716 #ifndef VM_TRACE
717  // config mismatch - do not crash if release compiled
718  if (tableId >= cnoOfTablerec)
719  {
720  jam();
721  terrorCode = 800;
722  goto sendref;
723  }
724 #endif
725 
726  TablerecPtr regTabPtr;
727  regTabPtr.i = tableId;
728  ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
729 
730  getFragmentrec(regFragPtr, fragId, regTabPtr.p);
731  if (regFragPtr.i != RNIL)
732  {
733  jam();
734  terrorCode= ZEXIST_FRAG_ERROR;
735  goto sendref;
736  }
737 
738  if (cfirstfreefrag != RNIL)
739  {
740  jam();
741  seizeFragrecord(regFragPtr);
742  }
743  else
744  {
745  jam();
746  terrorCode= ZFULL_FRAGRECORD_ERROR;
747  goto sendref;
748  }
749 
750  {
751 #ifdef MIN_ROWS_NOT_SUPPORTED
752  Uint32 fix_tupheader = regTabPtr.p->m_offsets[MM].m_fix_header_size;
753  ndbassert(fix_tupheader > 0);
754  Uint32 noRowsPerPage = ZWORDS_ON_PAGE / fix_tupheader;
755  Uint32 noAllocatedPages = (minRows + noRowsPerPage - 1 )/ noRowsPerPage;
756  if (minRows == 0)
757  noAllocatedPages = 2;
758  else if (noAllocatedPages == 0)
759  noAllocatedPages = 2;
760 #endif
761 
762  Uint32 noAllocatedPages = 1; //allocFragPage(regFragPtr.p);
763 
764  if (noAllocatedPages == 0)
765  {
766  jam();
767  releaseFragrec(regFragPtr);
768  terrorCode = ZNO_PAGES_ALLOCATED_ERROR;
769  goto sendref;
770  }
771  }
772 
773  if (!addfragtotab(regTabPtr.p, fragId, regFragPtr.i))
774  {
775  jam();
776  releaseFragrec(regFragPtr);
777  terrorCode= ZNO_FREE_TAB_ENTRY_ERROR;
778  goto sendref;
779  }
780 
781  if ((ERROR_INSERTED(4007) && regTabPtr.p->fragid[0] == fragId) ||
782  (ERROR_INSERTED(4008) && regTabPtr.p->fragid[1] == fragId) ||
783  ERROR_INSERTED(4050))
784  {
785  jam();
786  CLEAR_ERROR_INSERT_VALUE;
787  terrorCode = 1;
788  goto sendref;
789  }
790 
791  regFragPtr.p->fragStatus = Fragrecord::FS_ONLINE;
792  regFragPtr.p->fragTableId= regTabPtr.i;
793  regFragPtr.p->fragmentId= fragId;
794  regFragPtr.p->m_tablespace_id= tablespace_id;
795  regFragPtr.p->m_undo_complete= false;
796  regFragPtr.p->m_lcp_scan_op = RNIL;
797  regFragPtr.p->m_lcp_keep_list_head.setNull();
798  regFragPtr.p->m_lcp_keep_list_tail.setNull();
799  regFragPtr.p->noOfPages = 0;
800  regFragPtr.p->noOfVarPages = 0;
801  regFragPtr.p->m_max_page_no = 0;
802  regFragPtr.p->m_free_page_id_list = FREE_PAGE_RNIL;
803  ndbrequire(regFragPtr.p->m_page_map.isEmpty());
804  regFragPtr.p->m_restore_lcp_id = RNIL;
805  for (Uint32 i = 0; i<MAX_FREE_LIST+1; i++)
806  ndbrequire(regFragPtr.p->free_var_page_array[i].isEmpty());
807 
809  bzero(&rep,sizeof(rep));
810  if(regTabPtr.p->m_no_of_disk_attributes)
811  {
812  D("Tablespace_client - execTUPFRAGREQ");
813  Tablespace_client tsman(0, this, c_tsman, 0, 0,
814  regFragPtr.p->m_tablespace_id);
815  ndbrequire(tsman.get_tablespace_info(&rep) == 0);
816  regFragPtr.p->m_logfile_group_id= rep.tablespace.logfile_group_id;
817  }
818  else
819  {
820  jam();
821  regFragPtr.p->m_logfile_group_id = RNIL;
822  }
823  new (&regFragPtr.p->m_disk_alloc_info)
824  Disk_alloc_info(regTabPtr.p, rep.tablespace.extent_size);
825 
826  if (AlterTableReq::getReorgFragFlag(changeMask))
827  {
828  jam();
829  regFragPtr.p->fragStatus = Fragrecord::FS_REORG_NEW;
830  }
831 
832  signal->theData[0]= userptr;
833  signal->theData[1]= fragId;
834  signal->theData[2]= regFragPtr.i;
835  sendSignal(userRef, GSN_TUPFRAGCONF, signal, 3, JBB);
836 
837  return;
838 
839 sendref:
840  signal->theData[0]= userptr;
841  signal->theData[1]= terrorCode;
842  sendSignal(userRef, GSN_TUPFRAGREF, signal, 2, JBB);
843 }
844 
845 /*
846  Store the default values for a table, as the ATTRINFO "program"
847  (i.e AttributeHeader|Data AttributeHeader|Data...)
848  in varsize memory associated with the dummy fragment(DefaultValuesFragment).
849  There is a DBTUP global set of defaults records in DefaultValuesFragment.
850  One record per table stored on varsize pages.
851 
852  Each Table_record has a Local_key pointing to start of its default values
853  in TUP's default values fragment.
854 */
855 int Dbtup::store_default_record(const TablerecPtr& regTabPtr)
856 {
857  Uint32 RdefValSectionI = regTabPtr.p->m_createTable.defValSectionI;
858  jam();
859 
860  if (RdefValSectionI == RNIL) //No default values are stored for the table
861  {
862  jam();
863  if (ERROR_INSERTED(4034))
864  {
865  jam();
866  CLEAR_ERROR_INSERT_VALUE;
867  terrorCode = 1;
868  return -1;
869  }
870 
871  return 0;
872  }
873 
874  SegmentedSectionPtr defValSection;
875  getSection(defValSection, RdefValSectionI);
876  Uint32 sizes = defValSection.p->m_sz;
880  Uint32* var_data_ptr= alloc_var_part(&terrorCode,
881  DefaultValuesFragment.p,
882  regTabPtr.p,
883  sizes,
884  &regTabPtr.p->m_default_value_location);
885  if (unlikely( var_data_ptr == 0 ))
886  {
887  jam();
888  /* Caller releases the default values section */
889  return -1;
890  }
891 
892  if (ERROR_INSERTED(4034))
893  {
894  jam();
895  CLEAR_ERROR_INSERT_VALUE;
896  terrorCode = 1;
897  return -1;
898  }
899 
900 
901  copy(var_data_ptr, RdefValSectionI);
902  releaseSection(RdefValSectionI);
903  regTabPtr.p->m_createTable.defValSectionI= RNIL;
904 
905  return 0;
906 }
907 
908 
909 bool Dbtup::addfragtotab(Tablerec* const regTabPtr,
910  Uint32 fragId,
911  Uint32 fragIndex)
912 {
913  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
914  jam();
915  if (regTabPtr->fragid[i] == RNIL) {
916  jam();
917  regTabPtr->fragid[i]= fragId;
918  regTabPtr->fragrec[i]= fragIndex;
919  return true;
920  }
921  }
922  return false;
923 }
924 
925 void Dbtup::getFragmentrec(FragrecordPtr& regFragPtr,
926  Uint32 fragId,
927  Tablerec* const regTabPtr)
928 {
929  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
930  jam();
931  if (regTabPtr->fragid[i] == fragId) {
932  jam();
933  regFragPtr.i= regTabPtr->fragrec[i];
934  ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
935  return;
936  }
937  }
938  regFragPtr.i= RNIL;
939  ptrNull(regFragPtr);
940 }
941 
942 void Dbtup::seizeFragrecord(FragrecordPtr& regFragPtr)
943 {
944  regFragPtr.i= cfirstfreefrag;
945  ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
946  cfirstfreefrag= regFragPtr.p->nextfreefrag;
947  regFragPtr.p->nextfreefrag= RNIL;
948  RSS_OP_ALLOC(cnoOfFreeFragrec);
949 }
950 
951 void Dbtup::seizeFragoperrec(FragoperrecPtr& fragOperPtr)
952 {
953  fragOperPtr.i= cfirstfreeFragopr;
954  ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
955  cfirstfreeFragopr = fragOperPtr.p->nextFragoprec;
956  fragOperPtr.p->nextFragoprec = RNIL;
957  fragOperPtr.p->inUse = true;
958  RSS_OP_ALLOC(cnoOfFreeFragoprec);
959 }//Dbtup::seizeFragoperrec()
960 
961 void Dbtup::seizeAlterTabOperation(AlterTabOperationPtr& alterTabOpPtr)
962 {
963  alterTabOpPtr.i= cfirstfreeAlterTabOp;
964  ptrCheckGuard(alterTabOpPtr, cnoOfAlterTabOps, alterTabOperRec);
965  cfirstfreeAlterTabOp= alterTabOpPtr.p->nextAlterTabOp;
966  alterTabOpPtr.p->nextAlterTabOp= RNIL;
967 }
968 
969 void
970 Dbtup::execALTER_TAB_REQ(Signal *signal)
971 {
972  jamEntry();
973 
974  AlterTabReq copy= *(AlterTabReq *)signal->getDataPtr();
975  AlterTabReq * req = &copy;
976 
977  TablerecPtr regTabPtr;
978  regTabPtr.i= req->tableId;
979  ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
980 
981  switch((AlterTabReq::RequestType)req->requestType){
982  case AlterTabReq::AlterTablePrepare:
983  {
984  jam();
985 
986  if (AlterTableReq::getAddAttrFlag(req->changeMask))
987  {
988  jam();
989  SectionHandle handle(this, signal);
990  ndbrequire(handle.m_cnt == 1);
991  ::copy(signal->theData+25, handle.m_ptr[0]);
992  releaseSections(handle);
993  }
994  handleAlterTablePrepare(signal, req, regTabPtr.p);
995  return;
996  }
997  case AlterTabReq::AlterTableCommit:
998  {
999  jam();
1000  handleAlterTableCommit(signal, req, regTabPtr.p);
1001  return;
1002  }
1003  case AlterTabReq::AlterTableRevert:
1004  {
1005  jam();
1006  handleAlterTableAbort(signal, req, regTabPtr.p);
1007  return;
1008  }
1009  case AlterTabReq::AlterTableComplete:
1010  {
1011  jam();
1012  handleAlterTableComplete(signal, req, regTabPtr.p);
1013  return;
1014  }
1015  case AlterTabReq::AlterTableSumaEnable:
1016  {
1017  FragrecordPtr regFragPtr;
1018  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++)
1019  {
1020  jam();
1021  if ((regFragPtr.i = regTabPtr.p->fragrec[i]) != RNIL)
1022  {
1023  jam();
1024  ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
1025  switch(regFragPtr.p->fragStatus){
1026  case Fragrecord::FS_REORG_COMMIT_NEW:
1027  jam();
1028  if (0)
1029  ndbout_c("tab: %u frag: %u toggle fragstate from %s to %s",
1030  regFragPtr.p->fragTableId, regFragPtr.p->fragmentId,
1031  "FS_REORG_COMMIT_NEW", "FS_REORG_COMPLETE_NEW");
1032  regFragPtr.p->fragStatus = Fragrecord::FS_REORG_COMPLETE_NEW;
1033  break;
1034  default:
1035  break;
1036  }
1037  }
1038  }
1039  sendAlterTabConf(signal, RNIL);
1040  return;
1041  }
1042  case AlterTabReq::AlterTableSumaFilter:
1043  {
1044  Uint32 gci = signal->theData[signal->getLength() - 1];
1045  regTabPtr.p->m_reorg_suma_filter.m_gci_hi = gci;
1046  FragrecordPtr regFragPtr;
1047  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++)
1048  {
1049  jam();
1050  if ((regFragPtr.i = regTabPtr.p->fragrec[i]) != RNIL)
1051  {
1052  jam();
1053  ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
1054  switch(regFragPtr.p->fragStatus){
1055  case Fragrecord::FS_REORG_COMMIT:
1056  jam();
1057  if (0)
1058  ndbout_c("tab: %u frag: %u toggle fragstate from %s to %s (gci: %u)",
1059  regFragPtr.p->fragTableId, regFragPtr.p->fragmentId,
1060  "FS_REORG_COMMIT", "FS_REORG_COMPLETE",
1061  gci);
1062  regFragPtr.p->fragStatus = Fragrecord::FS_REORG_COMPLETE;
1063  break;
1064  default:
1065  break;
1066  }
1067  }
1068  }
1069  signal->theData[0] = ~Uint32(0);
1070  return;
1071  }
1072  case AlterTabReq::AlterTableReadOnly:
1073  case AlterTabReq::AlterTableReadWrite:
1074  signal->theData[0] = 0;
1075  signal->theData[1] = RNIL;
1076  return;
1077  default:
1078  break;
1079  }
1080  ndbrequire(false);
1081 }
1082 
1083 void
1084 Dbtup::handleAlterTablePrepare(Signal *signal,
1085  const AlterTabReq *req,
1086  const Tablerec *regTabPtr)
1087 {
1088  Uint32 connectPtr = RNIL;
1089  if (AlterTableReq::getAddAttrFlag(req->changeMask))
1090  {
1091  jam();
1092 
1093  Uint32 noOfNewAttr= req->noOfNewAttr;
1094  Uint32 newNoOfCharsets= req->newNoOfCharsets;
1095  Uint32 newNoOfKeyAttrs= req->newNoOfKeyAttrs;
1096 
1097  Uint32 *attrInfo= signal->theData+25;
1098 
1099  Uint32 oldNoOfAttr= regTabPtr->m_no_of_attributes;
1100  Uint32 newNoOfAttr= oldNoOfAttr+noOfNewAttr;
1101 
1102  /* Can only add attributes if varpart already present. */
1103  if((regTabPtr->m_attributes[MM].m_no_of_varsize +
1104  regTabPtr->m_attributes[MM].m_no_of_dynamic +
1105  (regTabPtr->m_bits & Tablerec::TR_ForceVarPart)) == 0)
1106  {
1107  sendAlterTabRef(signal, ZINVALID_ALTER_TAB);
1108  return;
1109  }
1110 
1111  AlterTabOperationPtr regAlterTabOpPtr;
1112  seizeAlterTabOperation(regAlterTabOpPtr);
1113 
1114  regAlterTabOpPtr.p->newNoOfAttrs= newNoOfAttr;
1115  regAlterTabOpPtr.p->newNoOfCharsets= newNoOfCharsets;
1116  regAlterTabOpPtr.p->newNoOfKeyAttrs= newNoOfKeyAttrs;
1117 
1118  /* Allocate a new (possibly larger) table descriptor buffer. */
1119  Uint32 allocSize= getTabDescrOffsets(newNoOfAttr, newNoOfCharsets,
1120  newNoOfKeyAttrs,
1121  regTabPtr->m_no_of_extra_columns,
1122  regAlterTabOpPtr.p->tabDesOffset);
1123  Uint32 tableDescriptorRef= allocTabDescr(allocSize);
1124  if (tableDescriptorRef == RNIL) {
1125  jam();
1126  releaseAlterTabOpRec(regAlterTabOpPtr);
1127  sendAlterTabRef(signal, terrorCode);
1128  return;
1129  }
1130  regAlterTabOpPtr.p->tableDescriptor= tableDescriptorRef;
1131 
1132  /*
1133  Get new pointers into tableDescriptor, and copy over old data.
1134  (Rest will be recomputed in computeTableMetaData() in case of
1135  ALTER_TAB_REQ[commit]).
1136  */
1137  Uint32* desc= &tableDescriptor[tableDescriptorRef].tabDescr;
1138  CHARSET_INFO** CharsetArray=
1139  (CHARSET_INFO**)(desc + regAlterTabOpPtr.p->tabDesOffset[2]);
1140  memcpy(CharsetArray, regTabPtr->charsetArray,
1141  sizeof(*CharsetArray)*regTabPtr->noOfCharsets);
1142  Uint32 * const attrDesPtrStart = desc + regAlterTabOpPtr.p->tabDesOffset[4];
1143  Uint32 * attrDesPtr = attrDesPtrStart;
1144  memcpy(attrDesPtr,
1145  &tableDescriptor[regTabPtr->tabDescriptor].tabDescr,
1146  4 * ZAD_SIZE * oldNoOfAttr);
1147 
1151  {
1152  const Uint32 * src = &tableDescriptor[regTabPtr->tabDescriptor].tabDescr;
1153  src += ZAD_SIZE * oldNoOfAttr;
1154 
1155  Uint32 * dst = attrDesPtr + (ZAD_SIZE * newNoOfAttr);
1156  memcpy(dst, src, 4 * ZAD_SIZE * regTabPtr->m_no_of_extra_columns);
1157  }
1158 
1159  attrDesPtr+= ZAD_SIZE * oldNoOfAttr;
1160 
1161  /*
1162  Loop over the new attributes to add.
1163  - Save AttributeDescriptor word in new TabDescriptor record.
1164  - Compute charset pos, as we will not save original csNumber.
1165  - Compute size needed for dynamic bitmap mask allocation.
1166  - Compute number of dynamic varsize, needed for fixsize offset calculation
1167  in ALTER_TAB_REQ[commit];
1168  */
1169  Uint32 charsetIndex= regTabPtr->noOfCharsets;
1170  Uint32 dyn_nullbits= regTabPtr->m_dyn_null_bits[MM];
1171  if (dyn_nullbits == 0)
1172  {
1173  jam();
1174  dyn_nullbits = DYN_BM_LEN_BITS;
1175  }
1176 
1177  Uint32 noDynFix= regTabPtr->m_attributes[MM].m_no_of_dyn_fix;
1178  Uint32 noDynVar= regTabPtr->m_attributes[MM].m_no_of_dyn_var;
1179  Uint32 noDynamic= regTabPtr->m_attributes[MM].m_no_of_dynamic;
1180  for (Uint32 i= 0; i<noOfNewAttr; i++)
1181  {
1182  Uint32 attrDescriptor= *attrInfo++;
1183  Uint32 csNumber= (*attrInfo++ >> 16);
1184  Uint32 attrDes2= 0;
1185 
1186  /* Only dynamic attributes possible for add attr */
1187  ndbrequire(AttributeDescriptor::getDynamic(attrDescriptor));
1188  ndbrequire(!AttributeDescriptor::getDiskBased(attrDescriptor));
1189 
1190  handleCharsetPos(csNumber, CharsetArray, newNoOfCharsets,
1191  charsetIndex, attrDes2);
1192 
1193  Uint32 null_pos= dyn_nullbits;
1194  Uint32 arrType= AttributeDescriptor::getArrayType(attrDescriptor);
1195  noDynamic++;
1196  if (arrType==NDB_ARRAYTYPE_FIXED)
1197  {
1198  Uint32 words= AttributeDescriptor::getSizeInWords(attrDescriptor);
1199 
1200  if(AttributeDescriptor::getSize(attrDescriptor) > 0)
1201  {
1202  jam();
1203  if(words > InternalMaxDynFix)
1204  goto treat_as_varsize;
1205  noDynFix++;
1206  dyn_nullbits+= words;
1207  }
1208  else
1209  {
1210  /* Bit type. */
1211  jam();
1212  Uint32 bits= AttributeDescriptor::getArraySize(attrDescriptor);
1213  null_pos+= bits;
1214  dyn_nullbits+= bits+1;
1215  }
1216  }
1217  else
1218  {
1219  jam();
1220  treat_as_varsize:
1221  noDynVar++;
1222  dyn_nullbits++;
1223  }
1224  AttributeOffset::setNullFlagPos(attrDes2, null_pos);
1225 
1226  *attrDesPtr++= attrDescriptor;
1227  *attrDesPtr++= attrDes2;
1228  }
1229  ndbassert(newNoOfCharsets==charsetIndex);
1230  ndbrequire(attrDesPtr == attrDesPtrStart + (ZAD_SIZE * newNoOfAttr));
1231 
1232  regAlterTabOpPtr.p->noOfDynNullBits= dyn_nullbits;
1233  ndbassert(noDynamic ==
1234  regTabPtr->m_attributes[MM].m_no_of_dynamic + noOfNewAttr);
1235  regAlterTabOpPtr.p->noOfDynFix= noDynFix;
1236  regAlterTabOpPtr.p->noOfDynVar= noDynVar;
1237  regAlterTabOpPtr.p->noOfDynamic= noDynamic;
1238 
1239  /* Allocate the new (possibly larger) dynamic descriptor. */
1240  allocSize= getDynTabDescrOffsets((dyn_nullbits+31)>>5,
1241  regAlterTabOpPtr.p->dynTabDesOffset);
1242  Uint32 dynTableDescriptorRef = RNIL;
1243  if (ERROR_INSERTED(4029))
1244  {
1245  jam();
1246  dynTableDescriptorRef = RNIL;
1247  terrorCode = ZMEM_NOTABDESCR_ERROR;
1248  CLEAR_ERROR_INSERT_VALUE;
1249  }
1250  else
1251  {
1252  jam();
1253  dynTableDescriptorRef = allocTabDescr(allocSize);
1254  }
1255  if (dynTableDescriptorRef == RNIL) {
1256  jam();
1257  releaseTabDescr(tableDescriptorRef);
1258  releaseAlterTabOpRec(regAlterTabOpPtr);
1259  sendAlterTabRef(signal, terrorCode);
1260  return;
1261  }
1262  regAlterTabOpPtr.p->dynTableDescriptor= dynTableDescriptorRef;
1263  connectPtr = regAlterTabOpPtr.i;
1264  }
1265 
1266  sendAlterTabConf(signal, connectPtr);
1267 }
1268 
1269 void
1270 Dbtup::sendAlterTabRef(Signal *signal, Uint32 errorCode)
1271 {
1272  signal->theData[0] = errorCode;
1273  signal->theData[1] = RNIL;
1274 }
1275 
1276 void
1277 Dbtup::sendAlterTabConf(Signal *signal, Uint32 connectPtr)
1278 {
1279  signal->theData[0] = 0;
1280  signal->theData[1] = connectPtr;
1281 }
1282 
1283 void
1284 Dbtup::handleAlterTableCommit(Signal *signal,
1285  const AlterTabReq* req,
1286  Tablerec *regTabPtr)
1287 {
1288  if (AlterTableReq::getAddAttrFlag(req->changeMask))
1289  {
1290  AlterTabOperationPtr regAlterTabOpPtr;
1291  regAlterTabOpPtr.i= req->connectPtr;
1292  ptrCheckGuard(regAlterTabOpPtr, cnoOfAlterTabOps, alterTabOperRec);
1293 
1294  /* Free old table descriptors. */
1295  releaseTabDescr(regTabPtr);
1296 
1297  /* Set new attribute counts. */
1298  regTabPtr->m_no_of_attributes= regAlterTabOpPtr.p->newNoOfAttrs;
1299  regTabPtr->noOfCharsets= regAlterTabOpPtr.p->newNoOfCharsets;
1300  regTabPtr->noOfKeyAttr= regAlterTabOpPtr.p->newNoOfKeyAttrs;
1301  regTabPtr->m_attributes[MM].m_no_of_dyn_fix= regAlterTabOpPtr.p->noOfDynFix;
1302  regTabPtr->m_attributes[MM].m_no_of_dyn_var= regAlterTabOpPtr.p->noOfDynVar;
1303  regTabPtr->m_attributes[MM].m_no_of_dynamic= regAlterTabOpPtr.p->noOfDynamic;
1304  regTabPtr->m_dyn_null_bits[MM]= regAlterTabOpPtr.p->noOfDynNullBits;
1305 
1306  /* Install the new (larger) table descriptors. */
1307  setUpDescriptorReferences(regAlterTabOpPtr.p->tableDescriptor,
1308  regTabPtr,
1309  regAlterTabOpPtr.p->tabDesOffset);
1310  setupDynDescriptorReferences(regAlterTabOpPtr.p->dynTableDescriptor,
1311  regTabPtr,
1312  regAlterTabOpPtr.p->dynTabDesOffset);
1313 
1314  releaseAlterTabOpRec(regAlterTabOpPtr);
1315 
1316  /* Recompute aggregate table meta data. */
1317  computeTableMetaData(regTabPtr);
1318  }
1319 
1320  if (AlterTableReq::getReorgFragFlag(req->changeMask))
1321  {
1322  FragrecordPtr regFragPtr;
1323  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++)
1324  {
1325  jam();
1326  if ((regFragPtr.i = regTabPtr->fragrec[i]) != RNIL)
1327  {
1328  jam();
1329  ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
1330  switch(regFragPtr.p->fragStatus){
1331  case Fragrecord::FS_ONLINE:
1332  jam();
1333  regFragPtr.p->fragStatus = Fragrecord::FS_REORG_COMMIT;
1334  if (0)
1335  ndbout_c("tab: %u frag: %u toggle fragstate from %s to %s",
1336  regFragPtr.p->fragTableId, regFragPtr.p->fragmentId,
1337  "FS_ONLINE", "FS_REORG_COMMIT");
1338  break;
1339  case Fragrecord::FS_REORG_NEW:
1340  jam();
1341  regFragPtr.p->fragStatus = Fragrecord::FS_REORG_COMMIT_NEW;
1342  if (0)
1343  ndbout_c("tab: %u frag: %u toggle fragstate from %s to %s",
1344  regFragPtr.p->fragTableId, regFragPtr.p->fragmentId,
1345  "FS_REORG_NEW", "FS_REORG_COMMIT_NEW");
1346  break;
1347  default:
1348  jamLine(regFragPtr.p->fragStatus);
1349  ndbrequire(false);
1350  }
1351  }
1352  }
1353  }
1354 
1355  sendAlterTabConf(signal, RNIL);
1356 }
1357 
1358 void
1359 Dbtup::handleAlterTableComplete(Signal *signal,
1360  const AlterTabReq* req,
1361  Tablerec *regTabPtr)
1362 {
1363  if (AlterTableReq::getReorgCompleteFlag(req->changeMask))
1364  {
1365  FragrecordPtr regFragPtr;
1366  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++)
1367  {
1368  jam();
1369  if ((regFragPtr.i = regTabPtr->fragrec[i]) != RNIL)
1370  {
1371  jam();
1372  ptrCheckGuard(regFragPtr, cnoOfFragrec, fragrecord);
1373  switch(regFragPtr.p->fragStatus){
1374  case Fragrecord::FS_REORG_COMPLETE:
1375  jam();
1376  if (0)
1377  ndbout_c("tab: %u frag: %u toggle fragstate from %s to %s",
1378  regFragPtr.p->fragTableId, regFragPtr.p->fragmentId,
1379  "FS_REORG_COMPLETE", "FS_ONLINE");
1380  regFragPtr.p->fragStatus = Fragrecord::FS_ONLINE;
1381  break;
1382  case Fragrecord::FS_REORG_COMPLETE_NEW:
1383  jam();
1384  if (0)
1385  ndbout_c("tab: %u frag: %u toggle fragstate from %s to %s",
1386  regFragPtr.p->fragTableId, regFragPtr.p->fragmentId,
1387  "FS_REORG_COMPLETE_NEW", "FS_ONLINE");
1388  regFragPtr.p->fragStatus = Fragrecord::FS_ONLINE;
1389  break;
1390  default:
1391  jamLine(regFragPtr.p->fragStatus);
1392  ndbrequire(false);
1393  }
1394  }
1395  }
1396  }
1397 
1398  sendAlterTabConf(signal, RNIL);
1399 }
1400 
1401 void
1402 Dbtup::handleAlterTableAbort(Signal *signal,
1403  const AlterTabReq* req,
1404  const Tablerec *regTabPtr)
1405 {
1406  if (AlterTableReq::getAddAttrFlag(req->changeMask))
1407  {
1408  jam();
1409  if (req->connectPtr != RNIL)
1410  {
1411  jam();
1412  AlterTabOperationPtr regAlterTabOpPtr;
1413  regAlterTabOpPtr.i= req->connectPtr;
1414  ptrCheckGuard(regAlterTabOpPtr, cnoOfAlterTabOps, alterTabOperRec);
1415 
1416  releaseTabDescr(regAlterTabOpPtr.p->tableDescriptor);
1417  releaseTabDescr(regAlterTabOpPtr.p->dynTableDescriptor);
1418  releaseAlterTabOpRec(regAlterTabOpPtr);
1419  }
1420  }
1421 
1422  sendAlterTabConf(signal, RNIL);
1423 }
1424 
1425 /*
1426  Update information for charset for a new attribute.
1427  If needed, attrDes2 will be updated with the correct charsetPos and
1428  charsetIndex will be updated to point to next free charsetPos slot.
1429 */
1430 void
1431 Dbtup::handleCharsetPos(Uint32 csNumber, CHARSET_INFO** charsetArray,
1432  Uint32 noOfCharsets,
1433  Uint32 & charsetIndex, Uint32 & attrDes2)
1434 {
1435  if (csNumber != 0)
1436  {
1437  CHARSET_INFO* cs = all_charsets[csNumber];
1438  ndbrequire(cs != NULL);
1439  Uint32 i= 0;
1440  while (i < charsetIndex)
1441  {
1442  jam();
1443  if (charsetArray[i] == cs)
1444  break;
1445  i++;
1446  }
1447  if (i == charsetIndex) {
1448  jam();
1449  ndbrequire(i < noOfCharsets);
1450  charsetArray[i]= cs;
1451  charsetIndex++;
1452  }
1453  AttributeOffset::setCharsetPos(attrDes2, i);
1454  }
1455 }
1456 
1457 /*
1458  This function (re-)computes aggregated metadata. It is called for
1459  both ALTER TABLE and CREATE TABLE.
1460  */
1461 Uint32
1462 Dbtup::computeTableMetaData(Tablerec *regTabPtr)
1463 {
1464  Uint32 dyn_null_words[2];
1465 
1466  for (Uint32 i = 0; i < NO_DYNAMICS; ++i)
1467  {
1468  if (regTabPtr->m_dyn_null_bits[i] == DYN_BM_LEN_BITS)
1469  {
1470  regTabPtr->m_dyn_null_bits[i] = 0;
1471  }
1472  dyn_null_words[i] = (regTabPtr->m_dyn_null_bits[i]+31)>>5;
1473  regTabPtr->m_offsets[i].m_dyn_null_words = dyn_null_words[i];
1474  }
1475 
1476  /* Compute the size of the static headers. */
1477  Uint32 pos[2] = { 0, 0 };
1478  if (regTabPtr->m_bits & Tablerec::TR_Checksum)
1479  {
1480  pos[MM]++;
1481  }
1482 
1483  if (regTabPtr->m_bits & Tablerec::TR_RowGCI)
1484  {
1485  pos[MM]++;
1486  pos[DD]++;
1487  }
1488 
1489  regTabPtr->m_no_of_disk_attributes=
1490  regTabPtr->m_attributes[DD].m_no_of_fixsize +
1491  regTabPtr->m_attributes[DD].m_no_of_varsize;
1492  if(regTabPtr->m_no_of_disk_attributes > 0)
1493  {
1494  /* Room for disk part location. */
1495  regTabPtr->m_offsets[MM].m_disk_ref_offset= pos[MM];
1496  pos[MM] += Disk_part_ref::SZ32; // 8 bytes
1497  regTabPtr->m_bits |= Tablerec::TR_DiskPart;
1498  }
1499  else
1500  {
1501  regTabPtr->m_offsets[MM].m_disk_ref_offset= pos[MM] - Disk_part_ref::SZ32;
1502  }
1503 
1504  if (regTabPtr->m_attributes[MM].m_no_of_varsize ||
1505  regTabPtr->m_attributes[MM].m_no_of_dynamic)
1506  {
1507  pos[MM] += Var_part_ref::SZ32;
1508  regTabPtr->m_bits &= ~(Uint32)Tablerec::TR_ForceVarPart;
1509  }
1510  else if (regTabPtr->m_bits & Tablerec::TR_ForceVarPart)
1511  {
1512  pos[MM] += Var_part_ref::SZ32;
1513  }
1514 
1515  regTabPtr->m_offsets[MM].m_null_offset= pos[MM];
1516  regTabPtr->m_offsets[DD].m_null_offset= pos[DD];
1517  pos[MM]+= regTabPtr->m_offsets[MM].m_null_words;
1518  pos[DD]+= regTabPtr->m_offsets[DD].m_null_words;
1519 
1520  /*
1521  Compute the offsets for the attributes.
1522  For static fixed-size, this is the offset from the tuple pointer of the
1523  actual data.
1524  For static var-size and dynamic, this is the index into the offset array.
1525 
1526  We also compute the dynamic bitmasks here.
1527  */
1528  Uint32 *tabDesc= (Uint32*)(tableDescriptor+regTabPtr->tabDescriptor);
1529  Uint32 fix_size[2]= {0, 0};
1530  Uint32 var_size[2]= {0, 0};
1531  Uint32 dyn_size[2]= {0, 0};
1532  Uint32 statvar_count= 0;
1533  Uint32 dynfix_count= 0;
1534  Uint32 dynvar_count= 0;
1535  Uint32 dynamic_count= 0;
1536  regTabPtr->blobAttributeMask.clear();
1537  regTabPtr->notNullAttributeMask.clear();
1538  for (Uint32 i = 0; i < NO_DYNAMICS; ++i)
1539  {
1540  bzero(regTabPtr->dynVarSizeMask[i], dyn_null_words[i]<<2);
1541  bzero(regTabPtr->dynFixSizeMask[i], dyn_null_words[i]<<2);
1542  }
1543 
1544  for(Uint32 i= 0; i<regTabPtr->m_no_of_attributes; i++)
1545  {
1546  Uint32 attrDescriptor= *tabDesc++;
1547  Uint32 attrDes2= *tabDesc;
1548  Uint32 ind= AttributeDescriptor::getDiskBased(attrDescriptor);
1549  Uint32 attrLen = AttributeDescriptor::getSize(attrDescriptor);
1550  Uint32 arr= AttributeDescriptor::getArrayType(attrDescriptor);
1551  Uint32 size_in_words= AttributeDescriptor::getSizeInWords(attrDescriptor);
1552  Uint32 size_in_bytes= AttributeDescriptor::getSizeInBytes(attrDescriptor);
1553  Uint32 extType = AttributeDescriptor::getType(attrDescriptor);
1554  Uint32 off;
1555 
1556  if (extType == NDB_TYPE_BLOB || extType == NDB_TYPE_TEXT)
1557  regTabPtr->blobAttributeMask.set(i);
1558  if(!AttributeDescriptor::getNullable(attrDescriptor))
1559  regTabPtr->notNullAttributeMask.set(i);
1560  if (!AttributeDescriptor::getDynamic(attrDescriptor))
1561  {
1562  if(arr == NDB_ARRAYTYPE_FIXED || ind==DD)
1563  {
1564  if (attrLen!=0)
1565  {
1566  off= fix_size[ind] + pos[ind];
1567  fix_size[ind]+= size_in_words;
1568  }
1569  else
1570  off= 0; // Bit type
1571  }
1572  else
1573  {
1574  /* Static varsize. */
1575  ndbassert(ind==MM);
1576  off= statvar_count++;
1577  var_size[ind]+= size_in_bytes;
1578  }
1579  }
1580  else
1581  {
1582  /* Dynamic attribute. */
1583  dynamic_count++;
1584  ndbrequire(ind==MM);
1585  Uint32 null_pos= AttributeOffset::getNullFlagPos(attrDes2);
1586  dyn_size[ind]+= (size_in_words<<2);
1587  if(arr == NDB_ARRAYTYPE_FIXED)
1588  {
1589  jam();
1590  //if (extType == NDB_TYPE_BLOB || extType == NDB_TYPE_TEXT)
1591  //regTabPtr->blobAttributeMask.set(i);
1592  // ToDo: I wonder what else is needed to handle BLOB/TEXT, if anything?
1593 
1594  if (attrLen!=0)
1595  {
1596  jam();
1597  if(size_in_words>InternalMaxDynFix)
1598  goto treat_as_varsize;
1599 
1600  off= dynfix_count++ + regTabPtr->m_attributes[ind].m_no_of_dyn_var;
1601  while(size_in_words-- > 0)
1602  {
1603  BitmaskImpl::set(dyn_null_words[ind],
1604  regTabPtr->dynFixSizeMask[ind], null_pos++);
1605  }
1606  }
1607  else
1608  off= 0; // Bit type
1609  }
1610  else
1611  {
1612  treat_as_varsize:
1613  jam();
1614  off= dynvar_count++;
1615  BitmaskImpl::set(dyn_null_words[ind], regTabPtr->dynVarSizeMask[ind], null_pos);
1616  }
1617  }
1618  if (off > AttributeOffset::getMaxOffset())
1619  {
1620  return ZTOO_LARGE_TUPLE_ERROR;
1621  }
1622  AttributeOffset::setOffset(attrDes2, off);
1623  *tabDesc++= attrDes2;
1624  }
1625  ndbassert(dynvar_count==regTabPtr->m_attributes[MM].m_no_of_dyn_var);
1626  ndbassert(dynfix_count==regTabPtr->m_attributes[MM].m_no_of_dyn_fix);
1627  ndbassert(dynamic_count==regTabPtr->m_attributes[MM].m_no_of_dynamic);
1628  ndbassert(statvar_count==regTabPtr->m_attributes[MM].m_no_of_varsize);
1629 
1630  regTabPtr->m_offsets[MM].m_fix_header_size=
1631  Tuple_header::HeaderSize + fix_size[MM] + pos[MM];
1632  regTabPtr->m_offsets[DD].m_fix_header_size=
1633  fix_size[DD] + pos[DD];
1634 
1635  if(regTabPtr->m_attributes[DD].m_no_of_varsize == 0 &&
1636  regTabPtr->m_attributes[DD].m_no_of_fixsize > 0)
1637  regTabPtr->m_offsets[DD].m_fix_header_size += Tuple_header::HeaderSize;
1638 
1639  Uint32 mm_vars= regTabPtr->m_attributes[MM].m_no_of_varsize;
1640  Uint32 mm_dyns= regTabPtr->m_attributes[MM].m_no_of_dyn_fix +
1641  regTabPtr->m_attributes[MM].m_no_of_dyn_var;
1642  Uint32 dd_vars= regTabPtr->m_attributes[MM].m_no_of_varsize;
1643  Uint32 dd_dyns= regTabPtr->m_attributes[DD].m_no_of_dynamic;
1644 
1645  regTabPtr->m_offsets[MM].m_max_var_offset= var_size[MM];
1646  /*
1647  Size of the expanded dynamic part. Needs room for bitmap, (N+1) 16-bit
1648  offset words with 32-bit padding, and all attribute data.
1649  */
1650  regTabPtr->m_offsets[MM].m_max_dyn_offset=
1651  (regTabPtr->m_offsets[MM].m_dyn_null_words<<2) + 4*((mm_dyns+2)>>1) +
1652  dyn_size[MM];
1653 
1654  regTabPtr->m_offsets[DD].m_max_var_offset= var_size[DD];
1655  regTabPtr->m_offsets[DD].m_max_dyn_offset=
1656  (regTabPtr->m_offsets[DD].m_dyn_null_words<<2) + 4*((dd_dyns+2)>>1) +
1657  dyn_size[DD];
1658 
1659  /* Room for data for all the attributes. */
1660  Uint32 total_rec_size=
1661  pos[MM] + fix_size[MM] + pos[DD] + fix_size[DD] +
1662  ((var_size[MM] + 3) >> 2) + ((dyn_size[MM] + 3) >> 2) +
1663  ((var_size[DD] + 3) >> 2) + ((dyn_size[DD] + 3) >> 2);
1664  /*
1665  Room for offset arrays and dynamic bitmaps. There is one extra 16-bit
1666  offset in each offset array (for easy computation of final length).
1667  Also one word for storing total length of varsize+dynamic part
1668  */
1669  if(mm_vars + regTabPtr->m_attributes[MM].m_no_of_dynamic)
1670  {
1671  total_rec_size+= (mm_vars + 2) >> 1;
1672  total_rec_size+= regTabPtr->m_offsets[MM].m_dyn_null_words;
1673  total_rec_size+= (mm_dyns + 2) >> 1;
1674  total_rec_size+= 1;
1675  }
1676  /* Disk data varsize offset array (not currently used). */
1677  if(dd_vars)
1678  total_rec_size+= (dd_vars + 2) >> 1;
1679  /* Room for the header. */
1680  total_rec_size+= Tuple_header::HeaderSize;
1681  if(regTabPtr->m_no_of_disk_attributes)
1682  total_rec_size+= Tuple_header::HeaderSize;
1683 
1684  /* Room for changemask */
1685  total_rec_size += 1 + ((regTabPtr->m_no_of_attributes + 31) >> 5);
1686 
1687  total_rec_size += COPY_TUPLE_HEADER32;
1688 
1689  regTabPtr->total_rec_size= total_rec_size;
1690 
1691  setUpQueryRoutines(regTabPtr);
1692  setUpKeyArray(regTabPtr);
1693  return 0;
1694 }
1695 
1696 void
1697 Dbtup::undo_createtable_callback(Signal* signal, Uint32 opPtrI, Uint32 unused)
1698 {
1699  FragrecordPtr regFragPtr;
1700  FragoperrecPtr fragOperPtr;
1701  TablerecPtr regTabPtr;
1702 
1703  fragOperPtr.i= opPtrI;
1704  ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
1705 
1706  regTabPtr.i= fragOperPtr.p->tableidFrag;
1707  ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
1708 
1709  getFragmentrec(regFragPtr, fragOperPtr.p->fragidFrag, regTabPtr.p);
1710  ndbrequire(regFragPtr.i != RNIL);
1711 
1712  D("Logfile_client - undo_createtable_callback");
1713  Logfile_client lgman(this, c_lgman, regFragPtr.p->m_logfile_group_id);
1714 
1715  Disk_undo::Create create;
1716  create.m_type_length= Disk_undo::UNDO_CREATE << 16 | (sizeof(create) >> 2);
1717  create.m_table = regTabPtr.i;
1718 
1719  Logfile_client::Change c[1] = {{ &create, sizeof(create) >> 2 } };
1720 
1721  Uint64 lsn= lgman.add_entry(c, 1);
1722  jamEntry();
1723 
1725  req.m_callback.m_callbackData= fragOperPtr.i;
1726  req.m_callback.m_callbackIndex = UNDO_CREATETABLE_LOGSYNC_CALLBACK;
1727 
1728  int ret = lgman.sync_lsn(signal, lsn, &req, 0);
1729  jamEntry();
1730  switch(ret){
1731  case 0:
1732  return;
1733  case -1:
1734  warningEvent("Failed to sync log for create of table: %u", regTabPtr.i);
1735  default:
1736  execute(signal, req.m_callback, regFragPtr.p->m_logfile_group_id);
1737  }
1738 }
1739 
1740 void
1741 Dbtup::undo_createtable_logsync_callback(Signal* signal, Uint32 ptrI,
1742  Uint32 res)
1743 {
1744  jamEntry();
1745  FragoperrecPtr fragOperPtr;
1746  fragOperPtr.i= ptrI;
1747  ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
1748 
1749  signal->theData[0] = fragOperPtr.p->lqhPtrFrag;
1750  signal->theData[1] = 1;
1751  sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUP_ADD_ATTCONF,
1752  signal, 2, JBB);
1753 
1754  releaseFragoperrec(fragOperPtr);
1755 }
1756 
1757 /*
1758  * Descriptor has these parts:
1759  *
1760  * 0 readFunctionArray ( one for each attribute )
1761  * 1 updateFunctionArray ( ditto )
1762  * 2 charsetArray ( pointers to distinct CHARSET_INFO )
1763  * 3 readKeyArray ( attribute ids of keys )
1764  * 5 tabDescriptor ( attribute descriptors, each ZAD_SIZE )
1765  */
1766 void Dbtup::setUpDescriptorReferences(Uint32 descriptorReference,
1767  Tablerec* const regTabPtr,
1768  const Uint32* offset)
1769 {
1770  Uint32* desc= &tableDescriptor[descriptorReference].tabDescr;
1771  regTabPtr->readFunctionArray= (ReadFunction*)(desc + offset[0]);
1772  regTabPtr->updateFunctionArray= (UpdateFunction*)(desc + offset[1]);
1773  regTabPtr->charsetArray= (CHARSET_INFO**)(desc + offset[2]);
1774  regTabPtr->readKeyArray= descriptorReference + offset[3];
1775  regTabPtr->tabDescriptor= descriptorReference + offset[4];
1776  regTabPtr->m_real_order_descriptor = descriptorReference + offset[5];
1777 }
1778 
1779 void Dbtup::setupDynDescriptorReferences(Uint32 dynDescr,
1780  Tablerec* const regTabPtr,
1781  const Uint32* offset,
1782  Uint32 ind)
1783 {
1784  regTabPtr->dynTabDescriptor[ind]= dynDescr;
1785  Uint32* desc= &tableDescriptor[dynDescr].tabDescr;
1786  regTabPtr->dynVarSizeMask[ind] = desc+offset[0];
1787  regTabPtr->dynFixSizeMask[ind] = desc+offset[1];
1788 }
1789 
1790 Uint32
1791 Dbtup::sizeOfReadFunction()
1792 {
1793  ReadFunction* tmp= (ReadFunction*)&tableDescriptor[0];
1794  TableDescriptor* start= &tableDescriptor[0];
1795  TableDescriptor * end= (TableDescriptor*)(tmp + 1);
1796  return (Uint32)(end - start);
1797 }
1798 
1799 void Dbtup::setUpKeyArray(Tablerec* const regTabPtr)
1800 {
1801  ndbrequire((regTabPtr->readKeyArray + regTabPtr->noOfKeyAttr) <
1802  cnoOfTabDescrRec);
1803  Uint32* keyArray= &tableDescriptor[regTabPtr->readKeyArray].tabDescr;
1804  Uint32 countKeyAttr= 0;
1805  for (Uint32 i= 0; i < regTabPtr->m_no_of_attributes; i++) {
1806  jam();
1807  Uint32 refAttr= regTabPtr->tabDescriptor + (i * ZAD_SIZE);
1808  Uint32 attrDescriptor= getTabDescrWord(refAttr);
1809  if (AttributeDescriptor::getPrimaryKey(attrDescriptor)) {
1810  jam();
1811  AttributeHeader::init(&keyArray[countKeyAttr], i, 0);
1812  countKeyAttr++;
1813  }
1814  }
1815  ndbrequire(countKeyAttr == regTabPtr->noOfKeyAttr);
1816 
1822  const Uint32 off= regTabPtr->m_real_order_descriptor;
1823  const Uint32 sz= (regTabPtr->m_no_of_attributes + 1) >> 1;
1824  ndbrequire((off + sz) < cnoOfTabDescrRec);
1825 
1826  Uint32 cnt= 0;
1827  Uint16* order= (Uint16*)&tableDescriptor[off].tabDescr;
1828  for (Uint32 type = 0; type < 5; type++)
1829  {
1830  for (Uint32 i= 0; i < regTabPtr->m_no_of_attributes; i++)
1831  {
1832  jam();
1833  Uint32 refAttr= regTabPtr->tabDescriptor + (i * ZAD_SIZE);
1834  Uint32 desc = getTabDescrWord(refAttr);
1835  Uint32 t = 0;
1836 
1837  if (AttributeDescriptor::getDynamic(desc) &&
1838  AttributeDescriptor::getArrayType(desc) == NDB_ARRAYTYPE_FIXED &&
1839  AttributeDescriptor::getSize(desc) == 0)
1840  {
1841  /*
1842  Dynamic bit types are stored inside the dynamic NULL bitmap, and are
1843  never expanded. So we do not need any real_order_descriptor for
1844  them.
1845  */
1846  jam();
1847  if(type==0)
1848  cnt++;
1849  continue;
1850  }
1851 
1852  if ((AttributeDescriptor::getArrayType(desc) != NDB_ARRAYTYPE_FIXED
1853  && !AttributeDescriptor::getDiskBased(desc)) ||
1854  (AttributeDescriptor::getDynamic(desc) &&
1855  AttributeDescriptor::getArrayType(desc) == NDB_ARRAYTYPE_FIXED &&
1856  AttributeDescriptor::getSizeInWords(desc) > InternalMaxDynFix))
1857  {
1858  t += 1;
1859  }
1860  if (AttributeDescriptor::getDynamic(desc))
1861  {
1862  t += 2;
1863  }
1864  if (AttributeDescriptor::getDiskBased(desc))
1865  {
1866  t += 4;
1867  }
1868  ndbrequire(t < 5); // Disk data currently only static/fixed
1869  if(t == type)
1870  {
1871  * order++ = i << ZAD_LOG_SIZE;
1872  cnt++;
1873  }
1874  }
1875  }
1876  ndbrequire(cnt == regTabPtr->m_no_of_attributes);
1877 }
1878 
1879 void Dbtup::releaseFragoperrec(FragoperrecPtr fragOperPtr)
1880 {
1881  fragOperPtr.p->inUse = false;
1882  fragOperPtr.p->nextFragoprec = cfirstfreeFragopr;
1883  cfirstfreeFragopr = fragOperPtr.i;
1884  RSS_OP_FREE(cnoOfFreeFragoprec);
1885 }//Dbtup::releaseFragoperrec()
1886 
1887 void Dbtup::releaseAlterTabOpRec(AlterTabOperationPtr regAlterTabOpPtr)
1888 {
1889  regAlterTabOpPtr.p->nextAlterTabOp= cfirstfreeAlterTabOp;
1890  cfirstfreeAlterTabOp= regAlterTabOpPtr.i;
1891 }
1892 
1893 void Dbtup::deleteFragTab(Tablerec* const regTabPtr, Uint32 fragId)
1894 {
1895  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
1896  jam();
1897  if (regTabPtr->fragid[i] == fragId) {
1898  jam();
1899  regTabPtr->fragid[i]= RNIL;
1900  regTabPtr->fragrec[i]= RNIL;
1901  return;
1902  }
1903  }
1904  ndbrequire(false);
1905 }
1906 
1907 /*
1908  * LQH aborts on-going create table operation. The table is later
1909  * dropped by DICT.
1910  */
1911 void Dbtup::abortAddFragOp(Signal* signal)
1912 {
1913  FragoperrecPtr fragOperPtr;
1914 
1915  fragOperPtr.i = signal->theData[1];
1916  ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
1917  ndbrequire(fragOperPtr.p->inUse);
1918  releaseFragoperrec(fragOperPtr);
1919 }
1920 
1921 void
1922 Dbtup::execDROP_TAB_REQ(Signal* signal)
1923 {
1924  jamEntry();
1925  if (ERROR_INSERTED(4013)) {
1926 #if defined VM_TRACE || defined ERROR_INSERT
1927  verifytabdes();
1928 #endif
1929  }
1930  DropTabReq* req= (DropTabReq*)signal->getDataPtr();
1931 
1932  TablerecPtr tabPtr;
1933  tabPtr.i= req->tableId;
1934  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
1935 
1936  tabPtr.p->m_dropTable.tabUserRef = req->senderRef;
1937  tabPtr.p->m_dropTable.tabUserPtr = req->senderData;
1938  tabPtr.p->tableStatus = DROPPING;
1939 
1940  signal->theData[0]= ZREL_FRAG;
1941  signal->theData[1]= tabPtr.i;
1942  signal->theData[2]= RNIL;
1943  sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
1944 }
1945 
1946 void Dbtup::releaseTabDescr(Tablerec* const regTabPtr)
1947 {
1948  Uint32 descriptor= regTabPtr->readKeyArray;
1949  if (descriptor != RNIL) {
1950  jam();
1951  Uint32 offset[10];
1952  getTabDescrOffsets(regTabPtr->m_no_of_attributes,
1953  regTabPtr->noOfCharsets,
1954  regTabPtr->noOfKeyAttr,
1955  regTabPtr->m_no_of_extra_columns,
1956  offset);
1957 
1958  regTabPtr->tabDescriptor= RNIL;
1959  regTabPtr->readKeyArray= RNIL;
1960  regTabPtr->readFunctionArray= NULL;
1961  regTabPtr->updateFunctionArray= NULL;
1962  regTabPtr->charsetArray= NULL;
1963 
1964  // move to start of descriptor
1965  descriptor -= offset[3];
1966  releaseTabDescr(descriptor);
1967  }
1968 
1969  /* Release dynamic descriptor, etc for mm and disk data. */
1970 
1971  for (Uint16 i = 0; i < NO_DYNAMICS; ++i)
1972  {
1973  jam();
1974  descriptor= regTabPtr->dynTabDescriptor[i];
1975  if(descriptor != RNIL)
1976  {
1977  regTabPtr->dynTabDescriptor[i]= RNIL;
1978  regTabPtr->dynVarSizeMask[i]= NULL;
1979  regTabPtr->dynFixSizeMask[i]= NULL;
1980  releaseTabDescr(descriptor);
1981  }
1982  }
1983 }
1984 
1985 void Dbtup::releaseFragment(Signal* signal, Uint32 tableId,
1986  Uint32 logfile_group_id)
1987 {
1988  TablerecPtr tabPtr;
1989  tabPtr.i= tableId;
1990  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
1991  Uint32 fragIndex = RNIL;
1992  Uint32 fragId = RNIL;
1993  Uint32 i = 0;
1994  for (i = 0; i < MAX_FRAG_PER_NODE; i++) {
1995  jam();
1996  if (tabPtr.p->fragid[i] != RNIL) {
1997  jam();
1998  fragIndex= tabPtr.p->fragrec[i];
1999  fragId= tabPtr.p->fragid[i];
2000  break;
2001  }
2002  }
2003  if (fragIndex != RNIL) {
2004  jam();
2005 
2006  signal->theData[0] = ZUNMAP_PAGES;
2007  signal->theData[1] = tabPtr.i;
2008  signal->theData[2] = fragIndex;
2009  signal->theData[3] = 0;
2010  sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
2011  return;
2012  }
2013 
2014  if (logfile_group_id != RNIL)
2015  {
2016  CallbackPtr cb;
2017  cb.m_callbackData= tabPtr.i;
2018  cb.m_callbackIndex = DROP_TABLE_LOG_BUFFER_CALLBACK;
2019  Uint32 sz= sizeof(Disk_undo::Drop) >> 2;
2020  D("Logfile_client - releaseFragment");
2021  Logfile_client lgman(this, c_lgman, logfile_group_id);
2022  int r0 = lgman.alloc_log_space(sz);
2023  jamEntry();
2024  if (r0)
2025  {
2026  jam();
2027  warningEvent("Failed to alloc log space for drop table: %u",
2028  tabPtr.i);
2029  goto done;
2030  }
2031 
2032  int res= lgman.get_log_buffer(signal, sz, &cb);
2033  jamEntry();
2034  switch(res){
2035  case 0:
2036  jam();
2037  return;
2038  case -1:
2039  warningEvent("Failed to get log buffer for drop table: %u",
2040  tabPtr.i);
2041  lgman.free_log_space(sz);
2042  jamEntry();
2043  goto done;
2044  break;
2045  default:
2046  execute(signal, cb, logfile_group_id);
2047  return;
2048  }
2049  }
2050 
2051 done:
2052  drop_table_logsync_callback(signal, tabPtr.i, RNIL);
2053 }
2054 
2055 void
2056 Dbtup::drop_fragment_unmap_pages(Signal *signal,
2057  TablerecPtr tabPtr,
2058  FragrecordPtr fragPtr,
2059  Uint32 pos)
2060 {
2061  if (tabPtr.p->m_no_of_disk_attributes)
2062  {
2063  jam();
2064  Disk_alloc_info& alloc_info= fragPtr.p->m_disk_alloc_info;
2065 
2066  if (!alloc_info.m_unmap_pages.isEmpty())
2067  {
2068  jam();
2069  signal->theData[0] = ZUNMAP_PAGES;
2070  signal->theData[1] = tabPtr.i;
2071  signal->theData[2] = fragPtr.i;
2072  signal->theData[3] = pos;
2073  sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
2074  return;
2075  }
2076  while(alloc_info.m_dirty_pages[pos].isEmpty() && pos < MAX_FREE_LIST)
2077  pos++;
2078 
2079  if (pos == MAX_FREE_LIST)
2080  {
2081  if(alloc_info.m_curr_extent_info_ptr_i != RNIL)
2082  {
2083  Local_extent_info_list
2084  list(c_extent_pool, alloc_info.m_free_extents[0]);
2085  Ptr<Extent_info> ext_ptr;
2086  c_extent_pool.getPtr(ext_ptr, alloc_info.m_curr_extent_info_ptr_i);
2087  list.add(ext_ptr);
2088  alloc_info.m_curr_extent_info_ptr_i= RNIL;
2089  }
2090 
2091  drop_fragment_free_extent(signal, tabPtr, fragPtr, 0);
2092  return;
2093  }
2094 
2095  Ptr<Page> pagePtr;
2096  ArrayPool<Page> *pool= (ArrayPool<Page>*)&m_global_page_pool;
2097  {
2098  LocalDLList<Page> list(*pool, alloc_info.m_dirty_pages[pos]);
2099  list.first(pagePtr);
2100  list.remove(pagePtr);
2101  }
2102 
2104  req.m_page.m_page_no = pagePtr.p->m_page_no;
2105  req.m_page.m_file_no = pagePtr.p->m_file_no;
2106 
2107  req.m_callback.m_callbackData= pos;
2108  req.m_callback.m_callbackFunction =
2109  safe_cast(&Dbtup::drop_fragment_unmap_page_callback);
2110 
2111  int flags= Page_cache_client::COMMIT_REQ;
2112  Page_cache_client pgman(this, c_pgman);
2113  int res= pgman.get_page(signal, req, flags);
2114  jamEntry();
2115  m_pgman_ptr = pgman.m_ptr;
2116  switch(res)
2117  {
2118  case 0:
2119  case -1:
2120  break;
2121  default:
2122  ndbrequire((Uint32)res == pagePtr.i);
2123  drop_fragment_unmap_page_callback(signal, pos, res);
2124  }
2125  return;
2126  }
2127  drop_fragment_free_extent(signal, tabPtr, fragPtr, 0);
2128 }
2129 
2130 void
2131 Dbtup::drop_fragment_unmap_page_callback(Signal* signal,
2132  Uint32 pos, Uint32 page_id)
2133 {
2135  m_global_page_pool.getPtr(page, page_id);
2136 
2137  Local_key key;
2138  key.m_page_no = ((Page*)page.p)->m_page_no;
2139  key.m_file_no = ((Page*)page.p)->m_file_no;
2140 
2141  Uint32 fragId = ((Page*)page.p)->m_fragment_id;
2142  Uint32 tableId = ((Page*)page.p)->m_table_id;
2143  Page_cache_client pgman(this, c_pgman);
2144  pgman.drop_page(key, page_id);
2145  jamEntry();
2146 
2147  TablerecPtr tabPtr;
2148  tabPtr.i= tableId;
2149  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
2150 
2151  FragrecordPtr fragPtr;
2152  getFragmentrec(fragPtr, fragId, tabPtr.p);
2153 
2154  signal->theData[0] = ZUNMAP_PAGES;
2155  signal->theData[1] = tabPtr.i;
2156  signal->theData[2] = fragPtr.i;
2157  signal->theData[3] = pos;
2158  sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
2159 }
2160 
2161 void
2162 Dbtup::drop_fragment_free_extent(Signal *signal,
2163  TablerecPtr tabPtr,
2164  FragrecordPtr fragPtr,
2165  Uint32 pos)
2166 {
2167  if (tabPtr.p->m_no_of_disk_attributes)
2168  {
2169  Disk_alloc_info& alloc_info= fragPtr.p->m_disk_alloc_info;
2170  for(; pos<EXTENT_SEARCH_MATRIX_SIZE; pos++)
2171  {
2172  if(!alloc_info.m_free_extents[pos].isEmpty())
2173  {
2174  jam();
2175  CallbackPtr cb;
2176  cb.m_callbackData= fragPtr.i;
2177  cb.m_callbackIndex = DROP_FRAGMENT_FREE_EXTENT_LOG_BUFFER_CALLBACK;
2178 #if NOT_YET_UNDO_FREE_EXTENT
2179  Uint32 sz= sizeof(Disk_undo::FreeExtent) >> 2;
2180  (void) c_lgman->alloc_log_space(fragPtr.p->m_logfile_group_id, sz);
2181  jamEntry();
2182 
2183  Logfile_client lgman(this, c_lgman, fragPtr.p->m_logfile_group_id);
2184 
2185  int res= lgman.get_log_buffer(signal, sz, &cb);
2186  jamEntry();
2187  switch(res){
2188  case 0:
2189  jam();
2190  return;
2191  case -1:
2192  ndbrequire("NOT YET IMPLEMENTED" == 0);
2193  break;
2194  default:
2195  execute(signal, cb, fragPtr.p->m_logfile_group_id);
2196  return;
2197  }
2198 #else
2199  execute(signal, cb, fragPtr.p->m_logfile_group_id);
2200  return;
2201 #endif
2202  }
2203  }
2204 
2205  ArrayPool<Page> *cheat_pool= (ArrayPool<Page>*)&m_global_page_pool;
2206  for(pos= 0; pos<MAX_FREE_LIST; pos++)
2207  {
2208  ndbrequire(alloc_info.m_page_requests[pos].isEmpty());
2209  LocalDLList<Page> list(* cheat_pool, alloc_info.m_dirty_pages[pos]);
2210  list.remove();
2211  }
2212  }
2213 
2214  signal->theData[0] = ZFREE_VAR_PAGES;
2215  signal->theData[1] = tabPtr.i;
2216  signal->theData[2] = fragPtr.i;
2217  sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
2218 }
2219 
2220 void
2221 Dbtup::drop_table_log_buffer_callback(Signal* signal, Uint32 tablePtrI,
2222  Uint32 logfile_group_id)
2223 {
2224  TablerecPtr tabPtr;
2225  tabPtr.i = tablePtrI;
2226  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
2227 
2228  ndbrequire(tabPtr.p->m_no_of_disk_attributes);
2229 
2230  Disk_undo::Drop drop;
2231  drop.m_table = tabPtr.i;
2232  drop.m_type_length =
2233  (Disk_undo::UNDO_DROP << 16) | (sizeof(drop) >> 2);
2234  D("Logfile_client - drop_table_log_buffer_callback");
2235  Logfile_client lgman(this, c_lgman, logfile_group_id);
2236 
2237  Logfile_client::Change c[1] = {{ &drop, sizeof(drop) >> 2 } };
2238  Uint64 lsn = lgman.add_entry(c, 1);
2239  jamEntry();
2240 
2242  req.m_callback.m_callbackData= tablePtrI;
2243  req.m_callback.m_callbackIndex = DROP_TABLE_LOGSYNC_CALLBACK;
2244 
2245  int ret = lgman.sync_lsn(signal, lsn, &req, 0);
2246  jamEntry();
2247  switch(ret){
2248  case 0:
2249  return;
2250  case -1:
2251  warningEvent("Failed to syn log for drop of table: %u", tablePtrI);
2252  default:
2253  execute(signal, req.m_callback, logfile_group_id);
2254  }
2255 }
2256 
2257 void
2258 Dbtup::drop_table_logsync_callback(Signal* signal,
2259  Uint32 tabPtrI,
2260  Uint32 logfile_group_id)
2261 {
2262  TablerecPtr tabPtr;
2263  tabPtr.i = tabPtrI;
2264  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
2265 
2266  DropTabConf * const dropConf= (DropTabConf *)signal->getDataPtrSend();
2267  dropConf->senderRef= reference();
2268  dropConf->senderData= tabPtr.p->m_dropTable.tabUserPtr;
2269  dropConf->tableId= tabPtr.i;
2270  sendSignal(tabPtr.p->m_dropTable.tabUserRef, GSN_DROP_TAB_CONF,
2271  signal, DropTabConf::SignalLength, JBB);
2272 
2273  releaseTabDescr(tabPtr.p);
2274  free_var_part(DefaultValuesFragment.p, tabPtr.p, &tabPtr.p->m_default_value_location);
2275  tabPtr.p->m_default_value_location.setNull();
2276  initTab(tabPtr.p);
2277 }
2278 
2279 void
2280 Dbtup::drop_fragment_free_extent_log_buffer_callback(Signal* signal,
2281  Uint32 fragPtrI,
2282  Uint32 unused)
2283 {
2284  FragrecordPtr fragPtr;
2285  fragPtr.i = fragPtrI;
2286  ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
2287 
2288  TablerecPtr tabPtr;
2289  tabPtr.i = fragPtr.p->fragTableId;
2290  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
2291 
2292  ndbrequire(tabPtr.p->m_no_of_disk_attributes);
2293  Disk_alloc_info& alloc_info= fragPtr.p->m_disk_alloc_info;
2294 
2295  for(Uint32 pos = 0; pos<EXTENT_SEARCH_MATRIX_SIZE; pos++)
2296  {
2297  if(!alloc_info.m_free_extents[pos].isEmpty())
2298  {
2299  jam();
2300  Local_extent_info_list
2301  list(c_extent_pool, alloc_info.m_free_extents[pos]);
2302  Ptr<Extent_info> ext_ptr;
2303  list.first(ext_ptr);
2304 
2305 #if NOT_YET_UNDO_FREE_EXTENT
2306 #error "This code is complete"
2307 #error "but not needed until we do dealloc of empty extents"
2308  Disk_undo::FreeExtent free;
2309  free.m_table = tabPtr.i;
2310  free.m_fragment = fragPtr.p->fragmentId;
2311  free.m_file_no = ext_ptr.p->m_key.m_file_no;
2312  free.m_page_no = ext_ptr.p->m_key.m_page_no;
2313  free.m_type_length =
2314  (Disk_undo::UNDO_FREE_EXTENT << 16) | (sizeof(free) >> 2);
2315  Logfile_client lgman(this, c_lgman, fragPtr.p->m_logfile_group_id);
2316 
2317  Logfile_client::Change c[1] = {{ &free, sizeof(free) >> 2 } };
2318  Uint64 lsn = lgman.add_entry(c, 1);
2319  jamEntry();
2320 #else
2321  Uint64 lsn = 0;
2322 #endif
2323 
2324  D("Tablespace_client - drop_fragment_free_extent_log_buffer_callback");
2325  Tablespace_client tsman(signal, this, c_tsman, tabPtr.i,
2326  fragPtr.p->fragmentId,
2327  fragPtr.p->m_tablespace_id);
2328 
2329  tsman.free_extent(&ext_ptr.p->m_key, lsn);
2330  jamEntry();
2331  c_extent_hash.remove(ext_ptr);
2332  list.release(ext_ptr);
2333 
2334  signal->theData[0] = ZFREE_EXTENT;
2335  signal->theData[1] = tabPtr.i;
2336  signal->theData[2] = fragPtr.i;
2337  signal->theData[3] = pos;
2338  sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
2339  return;
2340  }
2341  }
2342  ndbrequire(false);
2343 }
2344 
2345 void
2346 Dbtup::drop_fragment_free_var_pages(Signal* signal)
2347 {
2348  jam();
2349  Uint32 tableId = signal->theData[1];
2350  Uint32 fragPtrI = signal->theData[2];
2351 
2352  TablerecPtr tabPtr;
2353  tabPtr.i= tableId;
2354  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
2355 
2356  FragrecordPtr fragPtr;
2357  fragPtr.i = fragPtrI;
2358  ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
2359 
2360  PagePtr pagePtr;
2361  for (Uint32 i = 0; i<MAX_FREE_LIST+1; i++)
2362  {
2363  if (! fragPtr.p->free_var_page_array[i].isEmpty())
2364  {
2365  LocalDLList<Page> list(c_page_pool, fragPtr.p->free_var_page_array[i]);
2366  ndbrequire(list.first(pagePtr));
2367  list.remove(pagePtr);
2368  returnCommonArea(pagePtr.i, 1);
2369 
2370  signal->theData[0] = ZFREE_VAR_PAGES;
2371  signal->theData[1] = tabPtr.i;
2372  signal->theData[2] = fragPtr.i;
2373  sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
2374  return;
2375  }
2376  }
2377 
2379  DynArr256 map(c_page_map_pool, fragPtr.p->m_page_map);
2380  map.init(iter);
2381  signal->theData[0] = ZFREE_PAGES;
2382  signal->theData[1] = tabPtr.i;
2383  signal->theData[2] = fragPtrI;
2384  memcpy(signal->theData+3, &iter, sizeof(iter));
2385  sendSignal(reference(), GSN_CONTINUEB, signal, 3 + sizeof(iter)/4, JBB);
2386 }
2387 
2388 void
2389 Dbtup::drop_fragment_free_pages(Signal* signal)
2390 {
2391  Uint32 i;
2392  Uint32 tableId = signal->theData[1];
2393  Uint32 fragPtrI = signal->theData[2];
2395  memcpy(&iter, signal->theData+3, sizeof(iter));
2396 
2397  FragrecordPtr fragPtr;
2398  fragPtr.i = fragPtrI;
2399  ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
2400 
2401  DynArr256 map(c_page_map_pool, fragPtr.p->m_page_map);
2402  Uint32 realpid;
2403  for (i = 0; i<16; i++)
2404  {
2405  switch(map.release(iter, &realpid)){
2406  case 0:
2407  jam();
2408  goto done;
2409  case 1:
2410  if (realpid != RNIL && ((realpid & FREE_PAGE_BIT) == 0))
2411  {
2412  jam();
2413  returnCommonArea(realpid, 1);
2414  }
2415  break;
2416  case 2:
2417  jam();
2418  break;
2419  }
2420  }
2421 
2422  signal->theData[0] = ZFREE_PAGES;
2423  signal->theData[1] = tableId;
2424  signal->theData[2] = fragPtrI;
2425  memcpy(signal->theData+3, &iter, sizeof(iter));
2426  sendSignal(reference(), GSN_CONTINUEB, signal, 3 + sizeof(iter)/4, JBB);
2427  return;
2428 
2429 done:
2430  for (i = 0; i<MAX_FREE_LIST+1; i++)
2431  {
2432  ndbassert(fragPtr.p->free_var_page_array[i].isEmpty());
2433  }
2434 
2435  {
2436  LocalDLFifoList<Page> tmp(c_page_pool, fragPtr.p->thFreeFirst);
2437  tmp.remove();
2438  }
2439 
2443  TablerecPtr tabPtr;
2444  tabPtr.i= tableId;
2445  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
2446 
2450  tabPtr.p->m_dropTable.m_lcpno = 0;
2451  tabPtr.p->m_dropTable.m_fragPtrI = fragPtr.i;
2452  drop_fragment_fsremove(signal, tabPtr, fragPtr);
2453 }
2454 
2455 void
2456 Dbtup::drop_fragment_fsremove_done(Signal* signal,
2457  TablerecPtr tabPtr,
2458  FragrecordPtr fragPtr)
2459 {
2464  Uint32 logfile_group_id = fragPtr.p->m_logfile_group_id ;
2465 
2466  Uint32 i;
2467  for(i= 0; i<MAX_FRAG_PER_NODE; i++)
2468  if(tabPtr.p->fragrec[i] == fragPtr.i)
2469  break;
2470 
2471  ndbrequire(i != MAX_FRAG_PER_NODE);
2472  tabPtr.p->fragid[i]= RNIL;
2473  tabPtr.p->fragrec[i]= RNIL;
2474  releaseFragrec(fragPtr);
2475 
2476  if (tabPtr.p->tableStatus == DROPPING)
2477  {
2478  jam();
2479  signal->theData[0]= ZREL_FRAG;
2480  signal->theData[1]= tabPtr.i;
2481  signal->theData[2]= logfile_group_id;
2482  sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
2483  }
2484  else
2485  {
2486  jam();
2487  DropFragConf* conf = (DropFragConf*)signal->getDataPtrSend();
2488  conf->senderRef = reference();
2489  conf->senderData = tabPtr.p->m_dropTable.tabUserPtr;
2490  conf->tableId = tabPtr.i;
2491  sendSignal(tabPtr.p->m_dropTable.tabUserRef, GSN_DROP_FRAG_CONF,
2492  signal, DropFragConf::SignalLength, JBB);
2493  return;
2494  }
2495 }
2496 
2497 // Remove LCP
2498 void
2499 Dbtup::drop_fragment_fsremove(Signal* signal,
2500  TablerecPtr tabPtr,
2501  FragrecordPtr fragPtr)
2502 {
2503  FsRemoveReq* req = (FsRemoveReq*)signal->getDataPtrSend();
2504  req->userReference = reference();
2505  req->userPointer = tabPtr.i;
2506  req->directory = 0;
2507  req->ownDirectory = 0;
2508 
2509  Uint32 lcpno = tabPtr.p->m_dropTable.m_lcpno;
2510  Uint32 fragId = fragPtr.p->fragmentId;
2511  Uint32 tableId = fragPtr.p->fragTableId;
2512 
2513  FsOpenReq::setVersion(req->fileNumber, 5);
2514  FsOpenReq::setSuffix(req->fileNumber, FsOpenReq::S_DATA);
2515  FsOpenReq::v5_setLcpNo(req->fileNumber, lcpno);
2516  FsOpenReq::v5_setTableId(req->fileNumber, tableId);
2517  FsOpenReq::v5_setFragmentId(req->fileNumber, fragId);
2518  sendSignal(NDBFS_REF, GSN_FSREMOVEREQ, signal,
2519  FsRemoveReq::SignalLength, JBB);
2520 }
2521 
2522 void
2523 Dbtup::execFSREMOVEREF(Signal* signal)
2524 {
2525  jamEntry();
2526  FsRef* ref = (FsRef*)signal->getDataPtr();
2527  Uint32 userPointer = ref->userPointer;
2528  FsConf* conf = (FsConf*)signal->getDataPtrSend();
2529  conf->userPointer = userPointer;
2530  execFSREMOVECONF(signal);
2531 }
2532 
2533 void
2534 Dbtup::execFSREMOVECONF(Signal* signal)
2535 {
2536  jamEntry();
2537  FsConf* conf = (FsConf*)signal->getDataPtrSend();
2538 
2539  TablerecPtr tabPtr;
2540  FragrecordPtr fragPtr;
2541 
2542  tabPtr.i = conf->userPointer;
2543  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
2544 
2545  fragPtr.i = tabPtr.p->m_dropTable.m_fragPtrI;
2546  ptrCheckGuard(fragPtr, cnoOfFragrec, fragrecord);
2547 
2548  tabPtr.p->m_dropTable.m_lcpno++;
2549  if (tabPtr.p->m_dropTable.m_lcpno < 3)
2550  {
2551  jam();
2552  drop_fragment_fsremove(signal, tabPtr, fragPtr);
2553  }
2554  else
2555  {
2556  jam();
2557  drop_fragment_fsremove_done(signal, tabPtr, fragPtr);
2558  }
2559 }
2560 
2561 Uint32
2562 Dbtup::get_max_lcp_record_size(Uint32 tableId)
2563 {
2564  TablerecPtr tabPtr;
2565  tabPtr.i= tableId;
2566  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
2567 
2568  return tabPtr.p->total_rec_size;
2569 }
2570 // End remove LCP
2571 
2572 void
2573 Dbtup::start_restore_lcp(Uint32 tableId, Uint32 fragId)
2574 {
2575  TablerecPtr tabPtr;
2576  tabPtr.i= tableId;
2577  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
2578 
2579  ndbassert(Uint16(tabPtr.p->m_attributes[DD].m_no_of_fixsize << 16) == 0);
2580  ndbassert(Uint16(tabPtr.p->m_attributes[DD].m_no_of_varsize << 16) == 0);
2581 
2582  Uint32 saveAttrCounts =
2583  (Uint32(tabPtr.p->m_attributes[DD].m_no_of_fixsize) << 16) |
2584  (Uint32(tabPtr.p->m_attributes[DD].m_no_of_varsize) << 0);
2585 
2586  tabPtr.p->m_dropTable.tabUserPtr= saveAttrCounts;
2587  tabPtr.p->m_dropTable.tabUserRef= (tabPtr.p->m_bits & Tablerec::TR_RowGCI)? 1 : 0;
2588  tabPtr.p->m_createTable.defValLocation = tabPtr.p->m_default_value_location;
2589 
2590  Uint32 *tabDesc = (Uint32*)(tableDescriptor+tabPtr.p->tabDescriptor);
2591  for(Uint32 i= 0; i<tabPtr.p->m_no_of_attributes; i++)
2592  {
2593  Uint32 disk= AttributeDescriptor::getDiskBased(* tabDesc);
2594  Uint32 null= AttributeDescriptor::getNullable(* tabDesc);
2595 
2596  ndbrequire(tabPtr.p->notNullAttributeMask.get(i) != null);
2597  if(disk)
2598  tabPtr.p->notNullAttributeMask.clear(i);
2599  tabDesc += 2;
2600  }
2601 
2602  tabPtr.p->m_no_of_disk_attributes = 0;
2603  tabPtr.p->m_attributes[DD].m_no_of_fixsize = 0;
2604  tabPtr.p->m_attributes[DD].m_no_of_varsize = 0;
2605  /* Avoid LQH trampling GCI restored in raw format */
2606  tabPtr.p->m_bits &= ~((Uint16) Tablerec::TR_RowGCI);
2607  tabPtr.p->m_default_value_location.setNull();
2608 }
2609 void
2611  Uint32 senderRef, Uint32 senderData,
2612  Uint32 tableId, Uint32 fragId)
2613 {
2614  TablerecPtr tabPtr;
2615  tabPtr.i= tableId;
2616  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
2617 
2618  Uint32 restoreAttrCounts = tabPtr.p->m_dropTable.tabUserPtr;
2619 
2620  tabPtr.p->m_attributes[DD].m_no_of_fixsize= restoreAttrCounts >> 16;
2621  tabPtr.p->m_attributes[DD].m_no_of_varsize= restoreAttrCounts & 0xffff;
2622  tabPtr.p->m_bits |= ((tabPtr.p->m_dropTable.tabUserRef & 1) ? Tablerec::TR_RowGCI : 0);
2623 
2624  tabPtr.p->m_no_of_disk_attributes =
2625  tabPtr.p->m_attributes[DD].m_no_of_fixsize +
2626  tabPtr.p->m_attributes[DD].m_no_of_varsize;
2627  tabPtr.p->m_default_value_location = tabPtr.p->m_createTable.defValLocation;
2628 
2629  Uint32 *tabDesc = (Uint32*)(tableDescriptor+tabPtr.p->tabDescriptor);
2630  for(Uint32 i= 0; i<tabPtr.p->m_no_of_attributes; i++)
2631  {
2632  Uint32 disk= AttributeDescriptor::getDiskBased(* tabDesc);
2633  Uint32 null= AttributeDescriptor::getNullable(* tabDesc);
2634 
2635  if(disk && !null)
2636  tabPtr.p->notNullAttributeMask.set(i);
2637 
2638  tabDesc += 2;
2639  }
2640 
2644  Ptr<Fragoperrec> fragOpPtr;
2645  seizeFragoperrec(fragOpPtr);
2646  fragOpPtr.p->m_senderRef = senderRef;
2647  fragOpPtr.p->m_senderData = senderData;
2648  Ptr<Fragrecord> fragPtr;
2649  getFragmentrec(fragPtr, fragId, tabPtr.p);
2650  fragOpPtr.p->fragPointer = fragPtr.i;
2651 
2652  signal->theData[0] = ZREBUILD_FREE_PAGE_LIST;
2653  signal->theData[1] = fragOpPtr.i;
2654  signal->theData[2] = 0; // start page
2655  signal->theData[3] = RNIL; // tail
2656  rebuild_page_free_list(signal);
2657 }
2658 
2659 bool
2660 Dbtup::get_frag_info(Uint32 tableId, Uint32 fragId, Uint32* maxPage)
2661 {
2662  jamEntry();
2663  TablerecPtr tabPtr;
2664  tabPtr.i= tableId;
2665  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
2666 
2667  FragrecordPtr fragPtr;
2668  getFragmentrec(fragPtr, fragId, tabPtr.p);
2669 
2670  if (maxPage)
2671  {
2672  * maxPage = fragPtr.p->m_max_page_no;
2673  }
2674 
2675  return true;
2676 }
2677 
2678 void
2679 Dbtup::execDROP_FRAG_REQ(Signal* signal)
2680 {
2681  jamEntry();
2682  if (ERROR_INSERTED(4013)) {
2683 #if defined VM_TRACE || defined ERROR_INSERT
2684  verifytabdes();
2685 #endif
2686  }
2687  DropFragReq* req= (DropFragReq*)signal->getDataPtr();
2688 
2689  TablerecPtr tabPtr;
2690  tabPtr.i= req->tableId;
2691  ptrCheckGuard(tabPtr, cnoOfTablerec, tablerec);
2692 
2693  tabPtr.p->m_dropTable.tabUserRef = req->senderRef;
2694  tabPtr.p->m_dropTable.tabUserPtr = req->senderData;
2695 
2696  Uint32 fragIndex = RNIL;
2697  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++)
2698  {
2699  jam();
2700  if (tabPtr.p->fragid[i] == req->fragId)
2701  {
2702  jam();
2703  fragIndex= tabPtr.p->fragrec[i];
2704  break;
2705  }
2706  }
2707  if (fragIndex != RNIL)
2708  {
2709  jam();
2710 
2711  signal->theData[0] = ZUNMAP_PAGES;
2712  signal->theData[1] = tabPtr.i;
2713  signal->theData[2] = fragIndex;
2714  signal->theData[3] = 0;
2715  sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
2716  return;
2717  }
2718 
2719  DropFragConf* conf = (DropFragConf*)signal->getDataPtrSend();
2720  conf->senderRef = reference();
2721  conf->senderData = tabPtr.p->m_dropTable.tabUserPtr;
2722  conf->tableId = tabPtr.i;
2723  sendSignal(tabPtr.p->m_dropTable.tabUserRef, GSN_DROP_FRAG_CONF,
2724  signal, DropFragConf::SignalLength, JBB);
2725 }
2726