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