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 (®FragPtr.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 (®FragPtr.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