1 /*
2 Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #define DBACC_C
26 #include "Dbacc.hpp"
27
28 #include <AttributeHeader.hpp>
29 #include <signaldata/AccFrag.hpp>
30 #include <signaldata/AccScan.hpp>
31 #include <signaldata/NextScan.hpp>
32 #include <signaldata/AccLock.hpp>
33 #include <signaldata/EventReport.hpp>
34 #include <signaldata/FsConf.hpp>
35 #include <signaldata/FsRef.hpp>
36 #include <signaldata/FsRemoveReq.hpp>
37 #include <signaldata/DropTab.hpp>
38 #include <signaldata/DumpStateOrd.hpp>
39 #include <signaldata/TuxMaint.hpp>
40 #include <signaldata/DbinfoScan.hpp>
41 #include <signaldata/TransIdAI.hpp>
42 #include <KeyDescriptor.hpp>
43
44 #ifdef VM_TRACE
45 #define DEBUG(x) ndbout << "DBACC: "<< x << endl;
46 #else
47 #define DEBUG(x)
48 #endif
49
50 #ifdef ACC_SAFE_QUEUE
51 #define vlqrequire(x) do { if (unlikely(!(x))) {\
52 dump_lock_queue(loPtr); \
53 ndbrequire(false); } } while(0)
54 #else
55 #define vlqrequire(x) ndbrequire(x)
56 #define dump_lock_queue(x)
57 #endif
58
59
60 // primary key is stored in TUP
61 #include "../dbtup/Dbtup.hpp"
62 #include "../dblqh/Dblqh.hpp"
63
64
65 // Signal entries and statement blocks
66 /* --------------------------------------------------------------------------------- */
67 /* --------------------------------------------------------------------------------- */
68 /* --------------------------------------------------------------------------------- */
69 /* */
70 /* COMMON SIGNAL RECEPTION MODULE */
71 /* */
72 /* --------------------------------------------------------------------------------- */
73
74 /* --------------------------------------------------------------------------------- */
75 /* ******************--------------------------------------------------------------- */
76 /* CONTINUEB CONTINUE SIGNAL */
77 /* ******************------------------------------+ */
78 /* SENDER: ACC, LEVEL B */
execCONTINUEB(Signal * signal)79 void Dbacc::execCONTINUEB(Signal* signal)
80 {
81 Uint32 tcase;
82
83 jamEntry();
84 tcase = signal->theData[0];
85 tdata0 = signal->theData[1];
86 tresult = 0;
87 switch (tcase) {
88 case ZINITIALISE_RECORDS:
89 jam();
90 initialiseRecordsLab(signal, signal->theData[3], signal->theData[4]);
91 return;
92 break;
93 case ZREL_ROOT_FRAG:
94 {
95 jam();
96 Uint32 tableId = signal->theData[1];
97 releaseRootFragResources(signal, tableId);
98 break;
99 }
100 case ZREL_FRAG:
101 {
102 jam();
103 Uint32 fragIndex = signal->theData[1];
104 releaseFragResources(signal, fragIndex);
105 break;
106 }
107 case ZREL_DIR:
108 {
109 jam();
110 Uint32 fragIndex = signal->theData[1];
111 Uint32 dirIndex = signal->theData[2];
112 Uint32 startIndex = signal->theData[3];
113 releaseDirResources(signal, fragIndex, dirIndex, startIndex);
114 break;
115 }
116
117 default:
118 ndbrequire(false);
119 break;
120 }//switch
121 return;
122 }//Dbacc::execCONTINUEB()
123
124 /* ------------------------------------------------------------------------- */
125 /* ------------------------------------------------------------------------- */
126 /* ------------------------------------------------------------------------- */
127 /* */
128 /* END OF COMMON SIGNAL RECEPTION MODULE */
129 /* */
130 /* ------------------------------------------------------------------------- */
131 /* ------------------------------------------------------------------------- */
132 /* ------------------------------------------------------------------------- */
133 /* ------------------------------------------------------------------------- */
134 /* ------------------------------------------------------------------------- */
135 /* */
136 /* SYSTEM RESTART MODULE */
137 /* */
138 /* ------------------------------------------------------------------------- */
139 /* ------------------------------------------------------------------------- */
140 /* ------------------------------------------------------------------------- */
execNDB_STTOR(Signal * signal)141 void Dbacc::execNDB_STTOR(Signal* signal)
142 {
143 Uint32 tstartphase;
144 Uint32 tStartType;
145
146 jamEntry();
147 cndbcntrRef = signal->theData[0];
148 cmynodeid = signal->theData[1];
149 tstartphase = signal->theData[2];
150 tStartType = signal->theData[3];
151 switch (tstartphase) {
152 case ZSPH1:
153 jam();
154 ndbsttorryLab(signal);
155 return;
156 break;
157 case ZSPH2:
158 ndbsttorryLab(signal);
159 return;
160 break;
161 case ZSPH3:
162 break;
163 case ZSPH6:
164 jam();
165 break;
166 default:
167 jam();
168 /*empty*/;
169 break;
170 }//switch
171 ndbsttorryLab(signal);
172 return;
173 }//Dbacc::execNDB_STTOR()
174
175 /* ******************--------------------------------------------------------------- */
176 /* STTOR START / RESTART */
177 /* ******************------------------------------+ */
178 /* SENDER: ANY, LEVEL B */
execSTTOR(Signal * signal)179 void Dbacc::execSTTOR(Signal* signal)
180 {
181 jamEntry();
182 Uint32 tstartphase = signal->theData[1];
183 switch (tstartphase) {
184 case 1:
185 jam();
186 ndbrequire((c_tup = (Dbtup*)globalData.getBlock(DBTUP, instance())) != 0);
187 ndbrequire((c_lqh = (Dblqh*)globalData.getBlock(DBLQH, instance())) != 0);
188 break;
189 }
190 tuserblockref = signal->theData[3];
191 csignalkey = signal->theData[6];
192 sttorrysignalLab(signal);
193 return;
194 }//Dbacc::execSTTOR()
195
196 /* --------------------------------------------------------------------------------- */
197 /* ZSPH1 */
198 /* --------------------------------------------------------------------------------- */
ndbrestart1Lab(Signal * signal)199 void Dbacc::ndbrestart1Lab(Signal* signal)
200 {
201 cmynodeid = globalData.ownId;
202 cownBlockref = calcInstanceBlockRef(DBACC);
203 czero = 0;
204 cminusOne = czero - 1;
205 ctest = 0;
206 return;
207 }//Dbacc::ndbrestart1Lab()
208
initialiseRecordsLab(Signal * signal,Uint32 ref,Uint32 data)209 void Dbacc::initialiseRecordsLab(Signal* signal, Uint32 ref, Uint32 data)
210 {
211 switch (tdata0) {
212 case 0:
213 jam();
214 initialiseTableRec(signal);
215 break;
216 case 1:
217 case 2:
218 break;
219 case 3:
220 jam();
221 break;
222 case 4:
223 jam();
224 initialiseDirRec(signal);
225 break;
226 case 5:
227 jam();
228 initialiseDirRangeRec(signal);
229 break;
230 case 6:
231 jam();
232 initialiseFragRec(signal);
233 break;
234 case 7:
235 jam();
236 initialiseOverflowRec(signal);
237 break;
238 case 8:
239 jam();
240 initialiseOperationRec(signal);
241 break;
242 case 9:
243 jam();
244 initialisePageRec(signal);
245 break;
246 case 10:
247 jam();
248 break;
249 case 11:
250 jam();
251 initialiseScanRec(signal);
252 break;
253 case 12:
254 jam();
255
256 {
257 ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
258 conf->senderRef = reference();
259 conf->senderData = data;
260 sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
261 ReadConfigConf::SignalLength, JBB);
262 }
263 return;
264 break;
265 default:
266 ndbrequire(false);
267 break;
268 }//switch
269
270 signal->theData[0] = ZINITIALISE_RECORDS;
271 signal->theData[1] = tdata0 + 1;
272 signal->theData[2] = 0;
273 signal->theData[3] = ref;
274 signal->theData[4] = data;
275 sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);
276 return;
277 }//Dbacc::initialiseRecordsLab()
278
279 /* *********************************<< */
280 /* NDB_STTORRY */
281 /* *********************************<< */
ndbsttorryLab(Signal * signal)282 void Dbacc::ndbsttorryLab(Signal* signal)
283 {
284 signal->theData[0] = cownBlockref;
285 sendSignal(cndbcntrRef, GSN_NDB_STTORRY, signal, 1, JBB);
286 return;
287 }//Dbacc::ndbsttorryLab()
288
289 /* *********************************<< */
290 /* SIZEALT_REP SIZE ALTERATION */
291 /* *********************************<< */
execREAD_CONFIG_REQ(Signal * signal)292 void Dbacc::execREAD_CONFIG_REQ(Signal* signal)
293 {
294 const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
295 Uint32 ref = req->senderRef;
296 Uint32 senderData = req->senderData;
297 ndbrequire(req->noOfParameters == 0);
298
299 jamEntry();
300
301 const ndb_mgm_configuration_iterator * p =
302 m_ctx.m_config.getOwnConfigIterator();
303 ndbrequire(p != 0);
304
305 ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_DIR_RANGE, &cdirrangesize));
306 ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_DIR_ARRAY, &cdirarraysize));
307 ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_FRAGMENT, &cfragmentsize));
308 ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_OP_RECS, &coprecsize));
309 ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_OVERFLOW_RECS,
310 &coverflowrecsize));
311 ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_PAGE8, &cpagesize));
312 ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_TABLE, &ctablesize));
313 ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_SCAN, &cscanRecSize));
314 initRecords();
315 ndbrestart1Lab(signal);
316
317 c_memusage_report_frequency = 0;
318 ndb_mgm_get_int_parameter(p, CFG_DB_MEMREPORT_FREQUENCY,
319 &c_memusage_report_frequency);
320
321 tdata0 = 0;
322 initialiseRecordsLab(signal, ref, senderData);
323 return;
324 }//Dbacc::execSIZEALT_REP()
325
326 /* *********************************<< */
327 /* STTORRY */
328 /* *********************************<< */
sttorrysignalLab(Signal * signal)329 void Dbacc::sttorrysignalLab(Signal* signal)
330 {
331 signal->theData[0] = csignalkey;
332 signal->theData[1] = 3;
333 /* BLOCK CATEGORY */
334 signal->theData[2] = 2;
335 /* SIGNAL VERSION NUMBER */
336 signal->theData[3] = ZSPH1;
337 signal->theData[4] = 255;
338 BlockReference cntrRef = !isNdbMtLqh() ? NDBCNTR_REF : DBACC_REF;
339 sendSignal(cntrRef, GSN_STTORRY, signal, 5, JBB);
340 /* END OF START PHASES */
341 return;
342 }//Dbacc::sttorrysignalLab()
343
344 /* --------------------------------------------------------------------------------- */
345 /* INITIALISE_DIR_REC */
346 /* INITIALATES THE DIRECTORY RECORDS. */
347 /* --------------------------------------------------------------------------------- */
initialiseDirRec(Signal * signal)348 void Dbacc::initialiseDirRec(Signal* signal)
349 {
350 DirectoryarrayPtr idrDirptr;
351 ndbrequire(cdirarraysize > 0);
352 for (idrDirptr.i = 0; idrDirptr.i < cdirarraysize; idrDirptr.i++) {
353 refresh_watch_dog();
354 ptrAss(idrDirptr, directoryarray);
355 for (Uint32 i = 0; i <= 255; i++) {
356 idrDirptr.p->pagep[i] = RNIL;
357 }//for
358 }//for
359 cdirmemory = 0;
360 cfirstfreedir = RNIL;
361 }//Dbacc::initialiseDirRec()
362
363 /* --------------------------------------------------------------------------------- */
364 /* INITIALISE_DIR_RANGE_REC */
365 /* INITIALATES THE DIR_RANGE RECORDS. */
366 /* --------------------------------------------------------------------------------- */
initialiseDirRangeRec(Signal * signal)367 void Dbacc::initialiseDirRangeRec(Signal* signal)
368 {
369 DirRangePtr idrDirRangePtr;
370
371 ndbrequire(cdirrangesize > 0);
372 for (idrDirRangePtr.i = 0; idrDirRangePtr.i < cdirrangesize; idrDirRangePtr.i++) {
373 refresh_watch_dog();
374 ptrAss(idrDirRangePtr, dirRange);
375 idrDirRangePtr.p->dirArray[0] = idrDirRangePtr.i + 1;
376 for (Uint32 i = 1; i < 256; i++) {
377 idrDirRangePtr.p->dirArray[i] = RNIL;
378 }//for
379 }//for
380 idrDirRangePtr.i = cdirrangesize - 1;
381 ptrAss(idrDirRangePtr, dirRange);
382 idrDirRangePtr.p->dirArray[0] = RNIL;
383 cfirstfreeDirrange = 0;
384 }//Dbacc::initialiseDirRangeRec()
385
386 /* --------------------------------------------------------------------------------- */
387 /* INITIALISE_FRAG_REC */
388 /* INITIALATES THE FRAGMENT RECORDS. */
389 /* --------------------------------------------------------------------------------- */
initialiseFragRec(Signal * signal)390 void Dbacc::initialiseFragRec(Signal* signal)
391 {
392 FragmentrecPtr regFragPtr;
393 ndbrequire(cfragmentsize > 0);
394 for (regFragPtr.i = 0; regFragPtr.i < cfragmentsize; regFragPtr.i++) {
395 jam();
396 refresh_watch_dog();
397 ptrAss(regFragPtr, fragmentrec);
398 initFragGeneral(regFragPtr);
399 regFragPtr.p->nextfreefrag = regFragPtr.i + 1;
400 }//for
401 regFragPtr.i = cfragmentsize - 1;
402 ptrAss(regFragPtr, fragmentrec);
403 regFragPtr.p->nextfreefrag = RNIL;
404 cfirstfreefrag = 0;
405 }//Dbacc::initialiseFragRec()
406
407 /* --------------------------------------------------------------------------------- */
408 /* INITIALISE_OPERATION_REC */
409 /* INITIALATES THE OPERATION RECORDS. */
410 /* --------------------------------------------------------------------------------- */
initialiseOperationRec(Signal * signal)411 void Dbacc::initialiseOperationRec(Signal* signal)
412 {
413 ndbrequire(coprecsize > 0);
414 for (operationRecPtr.i = 0; operationRecPtr.i < coprecsize; operationRecPtr.i++) {
415 refresh_watch_dog();
416 ptrAss(operationRecPtr, operationrec);
417 operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
418 operationRecPtr.p->nextOp = operationRecPtr.i + 1;
419 }//for
420 operationRecPtr.i = coprecsize - 1;
421 ptrAss(operationRecPtr, operationrec);
422 operationRecPtr.p->nextOp = RNIL;
423 cfreeopRec = 0;
424 }//Dbacc::initialiseOperationRec()
425
426 /* --------------------------------------------------------------------------------- */
427 /* INITIALISE_OVERFLOW_REC */
428 /* INITIALATES THE OVERFLOW RECORDS */
429 /* --------------------------------------------------------------------------------- */
initialiseOverflowRec(Signal * signal)430 void Dbacc::initialiseOverflowRec(Signal* signal)
431 {
432 OverflowRecordPtr iorOverflowRecPtr;
433
434 ndbrequire(coverflowrecsize > 0);
435 for (iorOverflowRecPtr.i = 0; iorOverflowRecPtr.i < coverflowrecsize; iorOverflowRecPtr.i++) {
436 refresh_watch_dog();
437 ptrAss(iorOverflowRecPtr, overflowRecord);
438 iorOverflowRecPtr.p->nextfreeoverrec = iorOverflowRecPtr.i + 1;
439 }//for
440 iorOverflowRecPtr.i = coverflowrecsize - 1;
441 ptrAss(iorOverflowRecPtr, overflowRecord);
442 iorOverflowRecPtr.p->nextfreeoverrec = RNIL;
443 cfirstfreeoverrec = 0;
444 }//Dbacc::initialiseOverflowRec()
445
446 /* --------------------------------------------------------------------------------- */
447 /* INITIALISE_PAGE_REC */
448 /* INITIALATES THE PAGE RECORDS. */
449 /* --------------------------------------------------------------------------------- */
initialisePageRec(Signal * signal)450 void Dbacc::initialisePageRec(Signal* signal)
451 {
452 ndbrequire(cpagesize > 0);
453 cnoOfAllocatedPages = 0;
454 cnoOfAllocatedPagesMax = 0;
455 }//Dbacc::initialisePageRec()
456
457
458 /* --------------------------------------------------------------------------------- */
459 /* INITIALISE_ROOTFRAG_REC */
460 /* INITIALATES THE ROOTFRAG RECORDS. */
461 /* --------------------------------------------------------------------------------- */
462 /* --------------------------------------------------------------------------------- */
463 /* INITIALISE_SCAN_REC */
464 /* INITIALATES THE QUE_SCAN RECORDS. */
465 /* --------------------------------------------------------------------------------- */
initialiseScanRec(Signal * signal)466 void Dbacc::initialiseScanRec(Signal* signal)
467 {
468 ndbrequire(cscanRecSize > 0);
469 for (scanPtr.i = 0; scanPtr.i < cscanRecSize; scanPtr.i++) {
470 ptrAss(scanPtr, scanRec);
471 scanPtr.p->scanNextfreerec = scanPtr.i + 1;
472 scanPtr.p->scanState = ScanRec::SCAN_DISCONNECT;
473 }//for
474 scanPtr.i = cscanRecSize - 1;
475 ptrAss(scanPtr, scanRec);
476 scanPtr.p->scanNextfreerec = RNIL;
477 cfirstFreeScanRec = 0;
478 }//Dbacc::initialiseScanRec()
479
480
481 /* --------------------------------------------------------------------------------- */
482 /* INITIALISE_TABLE_REC */
483 /* INITIALATES THE TABLE RECORDS. */
484 /* --------------------------------------------------------------------------------- */
initialiseTableRec(Signal * signal)485 void Dbacc::initialiseTableRec(Signal* signal)
486 {
487 ndbrequire(ctablesize > 0);
488 for (tabptr.i = 0; tabptr.i < ctablesize; tabptr.i++) {
489 refresh_watch_dog();
490 ptrAss(tabptr, tabrec);
491 for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
492 tabptr.p->fragholder[i] = RNIL;
493 tabptr.p->fragptrholder[i] = RNIL;
494 }//for
495 }//for
496 }//Dbacc::initialiseTableRec()
497
498 /* --------------------------------------------------------------------------------- */
499 /* --------------------------------------------------------------------------------- */
500 /* --------------------------------------------------------------------------------- */
501 /* */
502 /* END OF SYSTEM RESTART MODULE */
503 /* */
504 /* --------------------------------------------------------------------------------- */
505 /* --------------------------------------------------------------------------------- */
506 /* --------------------------------------------------------------------------------- */
507 /* --------------------------------------------------------------------------------- */
508 /* --------------------------------------------------------------------------------- */
509 /* */
510 /* ADD/DELETE FRAGMENT MODULE */
511 /* */
512 /* --------------------------------------------------------------------------------- */
513 /* --------------------------------------------------------------------------------- */
514
515 // JONAS This methods "aer ett saall"
execACCFRAGREQ(Signal * signal)516 void Dbacc::execACCFRAGREQ(Signal* signal)
517 {
518 const AccFragReq * const req = (AccFragReq*)&signal->theData[0];
519 jamEntry();
520 if (ERROR_INSERTED(3001)) {
521 jam();
522 addFragRefuse(signal, 1);
523 CLEAR_ERROR_INSERT_VALUE;
524 return;
525 }
526 tabptr.i = req->tableId;
527 #ifndef VM_TRACE
528 // config mismatch - do not crash if release compiled
529 if (tabptr.i >= ctablesize) {
530 jam();
531 addFragRefuse(signal, 640);
532 return;
533 }
534 #endif
535 ptrCheckGuard(tabptr, ctablesize, tabrec);
536 ndbrequire((req->reqInfo & 0xF) == ZADDFRAG);
537 ndbrequire(!getfragmentrec(signal, fragrecptr, req->fragId));
538 if (cfirstfreefrag == RNIL) {
539 jam();
540 addFragRefuse(signal, ZFULL_FRAGRECORD_ERROR);
541 return;
542 }//if
543
544 seizeFragrec(signal);
545 initFragGeneral(fragrecptr);
546 initFragAdd(signal, fragrecptr);
547
548 if (!addfragtotab(signal, fragrecptr.i, req->fragId)) {
549 jam();
550 releaseFragRecord(signal, fragrecptr);
551 addFragRefuse(signal, ZFULL_FRAGRECORD_ERROR);
552 return;
553 }//if
554 if (cfirstfreeDirrange == RNIL) {
555 jam();
556 releaseFragRecord(signal, fragrecptr);
557 addFragRefuse(signal, ZDIR_RANGE_ERROR);
558 return;
559 } else {
560 jam();
561 seizeDirrange(signal);
562 }//if
563
564 fragrecptr.p->directory = newDirRangePtr.i;
565 seizeDirectory(signal);
566 if (tresult < ZLIMIT_OF_ERROR) {
567 jam();
568 newDirRangePtr.p->dirArray[0] = sdDirptr.i;
569 } else {
570 jam();
571 addFragRefuse(signal, tresult);
572 return;
573 }//if
574
575 seizePage(signal);
576 if (tresult > ZLIMIT_OF_ERROR) {
577 jam();
578 addFragRefuse(signal, tresult);
579 return;
580 }//if
581 sdDirptr.p->pagep[0] = spPageptr.i;
582 tipPageId = 0;
583 inpPageptr = spPageptr;
584 initPage(signal);
585 if (cfirstfreeDirrange == RNIL) {
586 jam();
587 addFragRefuse(signal, ZDIR_RANGE_ERROR);
588 return;
589 } else {
590 jam();
591 seizeDirrange(signal);
592 }//if
593 fragrecptr.p->overflowdir = newDirRangePtr.i;
594 seizeDirectory(signal);
595 if (tresult < ZLIMIT_OF_ERROR) {
596 jam();
597 newDirRangePtr.p->dirArray[0] = sdDirptr.i;
598 } else {
599 jam();
600 addFragRefuse(signal, tresult);
601 return;
602 }//if
603
604 Uint32 userPtr = req->userPtr;
605 BlockReference retRef = req->userRef;
606 fragrecptr.p->rootState = ACTIVEROOT;
607
608 AccFragConf * const conf = (AccFragConf*)&signal->theData[0];
609 conf->userPtr = userPtr;
610 conf->rootFragPtr = RNIL;
611 conf->fragId[0] = fragrecptr.p->fragmentid;
612 conf->fragId[1] = RNIL;
613 conf->fragPtr[0] = fragrecptr.i;
614 conf->fragPtr[1] = RNIL;
615 conf->rootHashCheck = fragrecptr.p->roothashcheck;
616 sendSignal(retRef, GSN_ACCFRAGCONF, signal, AccFragConf::SignalLength, JBB);
617 }//Dbacc::execACCFRAGREQ()
618
addFragRefuse(Signal * signal,Uint32 errorCode)619 void Dbacc::addFragRefuse(Signal* signal, Uint32 errorCode)
620 {
621 const AccFragReq * const req = (AccFragReq*)&signal->theData[0];
622 AccFragRef * const ref = (AccFragRef*)&signal->theData[0];
623 Uint32 userPtr = req->userPtr;
624 BlockReference retRef = req->userRef;
625
626 ref->userPtr = userPtr;
627 ref->errorCode = errorCode;
628 sendSignal(retRef, GSN_ACCFRAGREF, signal, AccFragRef::SignalLength, JBB);
629 return;
630 }//Dbacc::addFragRefuseEarly()
631
632 void
execDROP_TAB_REQ(Signal * signal)633 Dbacc::execDROP_TAB_REQ(Signal* signal){
634 jamEntry();
635 DropTabReq* req = (DropTabReq*)signal->getDataPtr();
636
637 TabrecPtr tabPtr;
638 tabPtr.i = req->tableId;
639 ptrCheckGuard(tabPtr, ctablesize, tabrec);
640
641 tabPtr.p->tabUserRef = req->senderRef;
642 tabPtr.p->tabUserPtr = req->senderData;
643 tabPtr.p->tabUserGsn = GSN_DROP_TAB_REQ;
644
645 signal->theData[0] = ZREL_ROOT_FRAG;
646 signal->theData[1] = tabPtr.i;
647 sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB);
648 }
649
650 void
execDROP_FRAG_REQ(Signal * signal)651 Dbacc::execDROP_FRAG_REQ(Signal* signal){
652 jamEntry();
653 DropFragReq* req = (DropFragReq*)signal->getDataPtr();
654
655 TabrecPtr tabPtr;
656 tabPtr.i = req->tableId;
657 ptrCheckGuard(tabPtr, ctablesize, tabrec);
658
659 tabPtr.p->tabUserRef = req->senderRef;
660 tabPtr.p->tabUserPtr = req->senderData;
661 tabPtr.p->tabUserGsn = GSN_DROP_FRAG_REQ;
662
663 for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++)
664 {
665 jam();
666 if (tabPtr.p->fragholder[i] == req->fragId)
667 {
668 jam();
669 tabPtr.p->fragholder[i] = RNIL;
670 releaseFragResources(signal, tabPtr.p->fragptrholder[i]);
671 return;
672 }//if
673 }//for
674
675 releaseRootFragResources(signal, req->tableId);
676 }
677
releaseRootFragResources(Signal * signal,Uint32 tableId)678 void Dbacc::releaseRootFragResources(Signal* signal, Uint32 tableId)
679 {
680 TabrecPtr tabPtr;
681 tabPtr.i = tableId;
682 ptrCheckGuard(tabPtr, ctablesize, tabrec);
683
684 if (tabPtr.p->tabUserGsn == GSN_DROP_TAB_REQ)
685 {
686 jam();
687 for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++)
688 {
689 jam();
690 if (tabPtr.p->fragholder[i] != RNIL)
691 {
692 jam();
693 tabPtr.p->fragholder[i] = RNIL;
694 releaseFragResources(signal, tabPtr.p->fragptrholder[i]);
695 return;
696 }
697 }
698
699 /**
700 * Finished...
701 */
702 DropTabConf * const dropConf = (DropTabConf *)signal->getDataPtrSend();
703 dropConf->senderRef = reference();
704 dropConf->senderData = tabPtr.p->tabUserPtr;
705 dropConf->tableId = tabPtr.i;
706 sendSignal(tabPtr.p->tabUserRef, GSN_DROP_TAB_CONF,
707 signal, DropTabConf::SignalLength, JBB);
708 }
709 else
710 {
711 ndbrequire(tabPtr.p->tabUserGsn == GSN_DROP_FRAG_REQ);
712
713 DropFragConf * conf = (DropFragConf *)signal->getDataPtrSend();
714 conf->senderRef = reference();
715 conf->senderData = tabPtr.p->tabUserPtr;
716 conf->tableId = tabPtr.i;
717 sendSignal(tabPtr.p->tabUserRef, GSN_DROP_FRAG_CONF,
718 signal, DropFragConf::SignalLength, JBB);
719 }
720
721 tabPtr.p->tabUserPtr = RNIL;
722 tabPtr.p->tabUserRef = 0;
723 tabPtr.p->tabUserGsn = 0;
724 }//Dbacc::releaseRootFragResources()
725
releaseFragResources(Signal * signal,Uint32 fragIndex)726 void Dbacc::releaseFragResources(Signal* signal, Uint32 fragIndex)
727 {
728 FragmentrecPtr regFragPtr;
729 regFragPtr.i = fragIndex;
730 ptrCheckGuard(regFragPtr, cfragmentsize, fragmentrec);
731 verifyFragCorrect(regFragPtr);
732 if (regFragPtr.p->directory != RNIL) {
733 jam();
734 releaseDirResources(signal, regFragPtr.i, regFragPtr.p->directory, 0);
735 regFragPtr.p->directory = RNIL;
736 } else if (regFragPtr.p->overflowdir != RNIL) {
737 jam();
738 releaseDirResources(signal, regFragPtr.i, regFragPtr.p->overflowdir, 0);
739 regFragPtr.p->overflowdir = RNIL;
740 } else if (regFragPtr.p->firstOverflowRec != RNIL) {
741 jam();
742 releaseOverflowResources(signal, regFragPtr);
743 } else if (regFragPtr.p->firstFreeDirindexRec != RNIL) {
744 jam();
745 releaseDirIndexResources(signal, regFragPtr);
746 } else {
747 jam();
748 Uint32 tab = regFragPtr.p->mytabptr;
749 releaseFragRecord(signal, regFragPtr);
750 signal->theData[0] = ZREL_ROOT_FRAG;
751 signal->theData[1] = tab;
752 sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB);
753 }//if
754 }//Dbacc::releaseFragResources()
755
verifyFragCorrect(FragmentrecPtr regFragPtr)756 void Dbacc::verifyFragCorrect(FragmentrecPtr regFragPtr)
757 {
758 ndbrequire(regFragPtr.p->lockOwnersList == RNIL);
759 }//Dbacc::verifyFragCorrect()
760
releaseDirResources(Signal * signal,Uint32 fragIndex,Uint32 dirIndex,Uint32 startIndex)761 void Dbacc::releaseDirResources(Signal* signal,
762 Uint32 fragIndex,
763 Uint32 dirIndex,
764 Uint32 startIndex)
765 {
766 DirRangePtr regDirRangePtr;
767 regDirRangePtr.i = dirIndex;
768 ptrCheckGuard(regDirRangePtr, cdirrangesize, dirRange);
769 for (Uint32 i = startIndex; i < 256; i++) {
770 jam();
771 if (regDirRangePtr.p->dirArray[i] != RNIL) {
772 jam();
773 Uint32 directoryIndex = regDirRangePtr.p->dirArray[i];
774 regDirRangePtr.p->dirArray[i] = RNIL;
775 releaseDirectoryResources(signal, fragIndex, dirIndex, (i + 1), directoryIndex);
776 return;
777 }//if
778 }//for
779 rdDirRangePtr = regDirRangePtr;
780 releaseDirrange(signal);
781 signal->theData[0] = ZREL_FRAG;
782 signal->theData[1] = fragIndex;
783 sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB);
784 }//Dbacc::releaseDirResources()
785
releaseDirectoryResources(Signal * signal,Uint32 fragIndex,Uint32 dirIndex,Uint32 startIndex,Uint32 directoryIndex)786 void Dbacc::releaseDirectoryResources(Signal* signal,
787 Uint32 fragIndex,
788 Uint32 dirIndex,
789 Uint32 startIndex,
790 Uint32 directoryIndex)
791 {
792 DirectoryarrayPtr regDirPtr;
793 regDirPtr.i = directoryIndex;
794 ptrCheckGuard(regDirPtr, cdirarraysize, directoryarray);
795 for (Uint32 i = 0; i < 256; i++) {
796 jam();
797 if (regDirPtr.p->pagep[i] != RNIL) {
798 jam();
799 rpPageptr.i = regDirPtr.p->pagep[i];
800 ptrCheckGuard(rpPageptr, cpagesize, page8);
801 releasePage(signal);
802 regDirPtr.p->pagep[i] = RNIL;
803 }//if
804 }//for
805 rdDirptr = regDirPtr;
806 releaseDirectory(signal);
807 signal->theData[0] = ZREL_DIR;
808 signal->theData[1] = fragIndex;
809 signal->theData[2] = dirIndex;
810 signal->theData[3] = startIndex;
811 sendSignal(cownBlockref, GSN_CONTINUEB, signal, 4, JBB);
812 }//Dbacc::releaseDirectoryResources()
813
releaseOverflowResources(Signal * signal,FragmentrecPtr regFragPtr)814 void Dbacc::releaseOverflowResources(Signal* signal, FragmentrecPtr regFragPtr)
815 {
816 Uint32 loopCount = 0;
817 OverflowRecordPtr regOverflowRecPtr;
818 while ((regFragPtr.p->firstOverflowRec != RNIL) &&
819 (loopCount < 1)) {
820 jam();
821 regOverflowRecPtr.i = regFragPtr.p->firstOverflowRec;
822 ptrCheckGuard(regOverflowRecPtr, coverflowrecsize, overflowRecord);
823 regFragPtr.p->firstOverflowRec = regOverflowRecPtr.p->nextOverRec;
824 rorOverflowRecPtr = regOverflowRecPtr;
825 releaseOverflowRec(signal);
826 loopCount++;
827 }//while
828 signal->theData[0] = ZREL_FRAG;
829 signal->theData[1] = regFragPtr.i;
830 sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB);
831 }//Dbacc::releaseOverflowResources()
832
releaseDirIndexResources(Signal * signal,FragmentrecPtr regFragPtr)833 void Dbacc::releaseDirIndexResources(Signal* signal, FragmentrecPtr regFragPtr)
834 {
835 Uint32 loopCount = 0;
836 OverflowRecordPtr regOverflowRecPtr;
837 while ((regFragPtr.p->firstFreeDirindexRec != RNIL) &&
838 (loopCount < 1)) {
839 jam();
840 regOverflowRecPtr.i = regFragPtr.p->firstFreeDirindexRec;
841 ptrCheckGuard(regOverflowRecPtr, coverflowrecsize, overflowRecord);
842 regFragPtr.p->firstFreeDirindexRec = regOverflowRecPtr.p->nextOverList;
843 rorOverflowRecPtr = regOverflowRecPtr;
844 releaseOverflowRec(signal);
845 loopCount++;
846 }//while
847 signal->theData[0] = ZREL_FRAG;
848 signal->theData[1] = regFragPtr.i;
849 sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB);
850 }//Dbacc::releaseDirIndexResources()
851
releaseFragRecord(Signal * signal,FragmentrecPtr regFragPtr)852 void Dbacc::releaseFragRecord(Signal* signal, FragmentrecPtr regFragPtr)
853 {
854 regFragPtr.p->nextfreefrag = cfirstfreefrag;
855 cfirstfreefrag = regFragPtr.i;
856 initFragGeneral(regFragPtr);
857 RSS_OP_FREE(cnoOfFreeFragrec);
858 }//Dbacc::releaseFragRecord()
859
860 /* -------------------------------------------------------------------------- */
861 /* ADDFRAGTOTAB */
862 /* DESCRIPTION: PUTS A FRAGMENT ID AND A POINTER TO ITS RECORD INTO */
863 /* TABLE ARRRAY OF THE TABLE RECORD. */
864 /* -------------------------------------------------------------------------- */
addfragtotab(Signal * signal,Uint32 rootIndex,Uint32 fid)865 bool Dbacc::addfragtotab(Signal* signal, Uint32 rootIndex, Uint32 fid)
866 {
867 for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
868 jam();
869 if (tabptr.p->fragholder[i] == RNIL) {
870 jam();
871 tabptr.p->fragholder[i] = fid;
872 tabptr.p->fragptrholder[i] = rootIndex;
873 return true;
874 }//if
875 }//for
876 return false;
877 }//Dbacc::addfragtotab()
878
879 /* --------------------------------------------------------------------------------- */
880 /* --------------------------------------------------------------------------------- */
881 /* --------------------------------------------------------------------------------- */
882 /* */
883 /* END OF ADD/DELETE FRAGMENT MODULE */
884 /* */
885 /* --------------------------------------------------------------------------------- */
886 /* --------------------------------------------------------------------------------- */
887 /* --------------------------------------------------------------------------------- */
888 /* --------------------------------------------------------------------------------- */
889 /* --------------------------------------------------------------------------------- */
890 /* */
891 /* CONNECTION MODULE */
892 /* */
893 /* --------------------------------------------------------------------------------- */
894 /* --------------------------------------------------------------------------------- */
895 /* ******************--------------------------------------------------------------- */
896 /* ACCSEIZEREQ SEIZE REQ */
897 /* SENDER: LQH, LEVEL B */
898 /* ENTER ACCSEIZEREQ WITH */
899 /* TUSERPTR , CONECTION PTR OF LQH */
900 /* TUSERBLOCKREF BLOCK REFERENCE OF LQH */
901 /* ******************--------------------------------------------------------------- */
902 /* ******************--------------------------------------------------------------- */
903 /* ACCSEIZEREQ SEIZE REQ */
904 /* ******************------------------------------+ */
905 /* SENDER: LQH, LEVEL B */
execACCSEIZEREQ(Signal * signal)906 void Dbacc::execACCSEIZEREQ(Signal* signal)
907 {
908 jamEntry();
909 tuserptr = signal->theData[0];
910 /* CONECTION PTR OF LQH */
911 tuserblockref = signal->theData[1];
912 /* BLOCK REFERENCE OF LQH */
913 tresult = 0;
914 if (cfreeopRec == RNIL) {
915 jam();
916 refaccConnectLab(signal);
917 return;
918 }//if
919 seizeOpRec(signal);
920 ptrGuard(operationRecPtr);
921 operationRecPtr.p->userptr = tuserptr;
922 operationRecPtr.p->userblockref = tuserblockref;
923 operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
924 /* ******************************< */
925 /* ACCSEIZECONF */
926 /* ******************************< */
927 signal->theData[0] = tuserptr;
928 signal->theData[1] = operationRecPtr.i;
929 sendSignal(tuserblockref, GSN_ACCSEIZECONF, signal, 2, JBB);
930 return;
931 }//Dbacc::execACCSEIZEREQ()
932
refaccConnectLab(Signal * signal)933 void Dbacc::refaccConnectLab(Signal* signal)
934 {
935 tresult = ZCONNECT_SIZE_ERROR;
936 /* ******************************< */
937 /* ACCSEIZEREF */
938 /* ******************************< */
939 signal->theData[0] = tuserptr;
940 signal->theData[1] = tresult;
941 sendSignal(tuserblockref, GSN_ACCSEIZEREF, signal, 2, JBB);
942 return;
943 }//Dbacc::refaccConnectLab()
944
945 /* --------------------------------------------------------------------------------- */
946 /* --------------------------------------------------------------------------------- */
947 /* --------------------------------------------------------------------------------- */
948 /* */
949 /* END OF CONNECTION MODULE */
950 /* */
951 /* --------------------------------------------------------------------------------- */
952 /* --------------------------------------------------------------------------------- */
953 /* --------------------------------------------------------------------------------- */
954 /* --------------------------------------------------------------------------------- */
955 /* --------------------------------------------------------------------------------- */
956 /* */
957 /* EXECUTE OPERATION MODULE */
958 /* */
959 /* --------------------------------------------------------------------------------- */
960 /* --------------------------------------------------------------------------------- */
961 /* --------------------------------------------------------------------------------- */
962 /* INIT_OP_REC */
963 /* INFORMATION WHICH IS RECIEVED BY ACCKEYREQ WILL BE SAVED */
964 /* IN THE OPERATION RECORD. */
965 /* --------------------------------------------------------------------------------- */
initOpRec(Signal * signal)966 void Dbacc::initOpRec(Signal* signal)
967 {
968 register Uint32 Treqinfo;
969
970 Treqinfo = signal->theData[2];
971
972 operationRecPtr.p->hashValue = signal->theData[3];
973 operationRecPtr.p->tupkeylen = signal->theData[4];
974 operationRecPtr.p->xfrmtupkeylen = signal->theData[4];
975 operationRecPtr.p->transId1 = signal->theData[5];
976 operationRecPtr.p->transId2 = signal->theData[6];
977
978 Uint32 readFlag = (((Treqinfo >> 4) & 0x3) == 0); // Only 1 if Read
979 Uint32 dirtyFlag = (((Treqinfo >> 6) & 0x1) == 1); // Only 1 if Dirty
980 Uint32 dirtyReadFlag = readFlag & dirtyFlag;
981 Uint32 operation = Treqinfo & 0xf;
982 if (operation == ZREFRESH)
983 operation = ZWRITE; /* Insert if !exist, otherwise lock */
984
985 Uint32 opbits = 0;
986 opbits |= operation;
987 opbits |= ((Treqinfo >> 4) & 0x3) ? (Uint32) Operationrec::OP_LOCK_MODE : 0;
988 opbits |= ((Treqinfo >> 4) & 0x3) ? (Uint32) Operationrec::OP_ACC_LOCK_MODE : 0;
989 opbits |= (dirtyReadFlag) ? (Uint32) Operationrec::OP_DIRTY_READ : 0;
990 if ((Treqinfo >> 31) & 0x1)
991 {
992 opbits |= Operationrec::OP_LOCK_REQ; // TUX LOCK_REQ
993
994 /**
995 * A lock req has SCAN_OP, it can't delete a row,
996 * so OP_COMMIT_DELETE_CHECK is set like for SCAN
997 * see initScanOpRec
998 */
999 opbits |= Operationrec::OP_COMMIT_DELETE_CHECK;
1000
1001 /**
1002 * TODO: Looking at it now, I think it would be more natural
1003 * to treat it as a ZREAD...
1004 */
1005 }
1006
1007 //operationRecPtr.p->nodeType = (Treqinfo >> 7) & 0x3;
1008 operationRecPtr.p->fid = fragrecptr.p->myfid;
1009 operationRecPtr.p->fragptr = fragrecptr.i;
1010 operationRecPtr.p->nextParallelQue = RNIL;
1011 operationRecPtr.p->prevParallelQue = RNIL;
1012 operationRecPtr.p->nextSerialQue = RNIL;
1013 operationRecPtr.p->prevSerialQue = RNIL;
1014 operationRecPtr.p->elementPage = RNIL;
1015 operationRecPtr.p->scanRecPtr = RNIL;
1016 operationRecPtr.p->m_op_bits = opbits;
1017
1018 // bit to mark lock operation
1019 // undo log is not run via ACCKEYREQ
1020
1021 if (operationRecPtr.p->tupkeylen == 0)
1022 {
1023 ndbassert(signal->getLength() == 9);
1024 }
1025 }//Dbacc::initOpRec()
1026
1027 /* --------------------------------------------------------------------------------- */
1028 /* SEND_ACCKEYCONF */
1029 /* --------------------------------------------------------------------------------- */
sendAcckeyconf(Signal * signal)1030 void Dbacc::sendAcckeyconf(Signal* signal)
1031 {
1032 signal->theData[0] = operationRecPtr.p->userptr;
1033 signal->theData[1] = operationRecPtr.p->m_op_bits & Operationrec::OP_MASK;
1034 signal->theData[2] = operationRecPtr.p->fid;
1035 signal->theData[3] = operationRecPtr.p->localdata[0];
1036 signal->theData[4] = operationRecPtr.p->localdata[1];
1037 }//Dbacc::sendAcckeyconf()
1038
1039 void
ACCKEY_error(Uint32 fromWhere)1040 Dbacc::ACCKEY_error(Uint32 fromWhere)
1041 {
1042 switch(fromWhere) {
1043 case 0:
1044 ndbrequire(false);
1045 case 1:
1046 ndbrequire(false);
1047 case 2:
1048 ndbrequire(false);
1049 case 3:
1050 ndbrequire(false);
1051 case 4:
1052 ndbrequire(false);
1053 case 5:
1054 ndbrequire(false);
1055 case 6:
1056 ndbrequire(false);
1057 case 7:
1058 ndbrequire(false);
1059 case 8:
1060 ndbrequire(false);
1061 case 9:
1062 ndbrequire(false);
1063 default:
1064 ndbrequire(false);
1065 }//switch
1066 }//Dbacc::ACCKEY_error()
1067
1068 /* ******************--------------------------------------------------------------- */
1069 /* ACCKEYREQ REQUEST FOR INSERT, DELETE, */
1070 /* RERAD AND UPDATE, A TUPLE. */
1071 /* SENDER: LQH, LEVEL B */
1072 /* SIGNAL DATA: OPERATION_REC_PTR, CONNECTION PTR */
1073 /* TABPTR, TABLE ID = TABLE RECORD POINTER */
1074 /* TREQINFO, */
1075 /* THASHVALUE, HASH VALUE OF THE TUP */
1076 /* TKEYLEN, LENGTH OF THE PRIMARY KEYS */
1077 /* TKEY1, PRIMARY KEY 1 */
1078 /* TKEY2, PRIMARY KEY 2 */
1079 /* TKEY3, PRIMARY KEY 3 */
1080 /* TKEY4, PRIMARY KEY 4 */
1081 /* ******************--------------------------------------------------------------- */
execACCKEYREQ(Signal * signal)1082 void Dbacc::execACCKEYREQ(Signal* signal)
1083 {
1084 jamEntry();
1085 operationRecPtr.i = signal->theData[0]; /* CONNECTION PTR */
1086 fragrecptr.i = signal->theData[1]; /* FRAGMENT RECORD POINTER */
1087 if (!((operationRecPtr.i < coprecsize) ||
1088 (fragrecptr.i < cfragmentsize))) {
1089 ACCKEY_error(0);
1090 return;
1091 }//if
1092 ptrAss(operationRecPtr, operationrec);
1093 ptrAss(fragrecptr, fragmentrec);
1094
1095 ndbrequire(operationRecPtr.p->m_op_bits == Operationrec::OP_INITIAL);
1096
1097 initOpRec(signal);
1098 // normalize key if any char attr
1099 if (operationRecPtr.p->tupkeylen && fragrecptr.p->hasCharAttr)
1100 xfrmKeyData(signal);
1101
1102 /*---------------------------------------------------------------*/
1103 /* */
1104 /* WE WILL USE THE HASH VALUE TO LOOK UP THE PROPER MEMORY */
1105 /* PAGE AND MEMORY PAGE INDEX TO START THE SEARCH WITHIN. */
1106 /* WE REMEMBER THESE ADDRESS IF WE LATER NEED TO INSERT */
1107 /* THE ITEM AFTER NOT FINDING THE ITEM. */
1108 /*---------------------------------------------------------------*/
1109 OperationrecPtr lockOwnerPtr;
1110 const Uint32 found = getElement(signal, lockOwnerPtr);
1111
1112 Uint32 opbits = operationRecPtr.p->m_op_bits;
1113 Uint32 op = opbits & Operationrec::OP_MASK;
1114 if (found == ZTRUE)
1115 {
1116 switch (op) {
1117 case ZREAD:
1118 case ZUPDATE:
1119 case ZDELETE:
1120 case ZWRITE:
1121 case ZSCAN_OP:
1122 if (!lockOwnerPtr.p)
1123 {
1124 if(op == ZWRITE)
1125 {
1126 jam();
1127 opbits &= ~(Uint32)Operationrec::OP_MASK;
1128 opbits |= (op = ZUPDATE);
1129 operationRecPtr.p->m_op_bits = opbits; // store to get correct ACCKEYCONF
1130 }
1131 opbits |= Operationrec::OP_STATE_RUNNING;
1132 opbits |= Operationrec::OP_RUN_QUEUE;
1133 sendAcckeyconf(signal);
1134 if (! (opbits & Operationrec::OP_DIRTY_READ)) {
1135 /*---------------------------------------------------------------*/
1136 // It is not a dirty read. We proceed by locking and continue with
1137 // the operation.
1138 /*---------------------------------------------------------------*/
1139 Uint32 eh = gePageptr.p->word32[tgeElementptr];
1140 operationRecPtr.p->scanBits = ElementHeader::getScanBits(eh);
1141 operationRecPtr.p->hashvaluePart = ElementHeader::getHashValuePart(eh);
1142 operationRecPtr.p->elementPage = gePageptr.i;
1143 operationRecPtr.p->elementContainer = tgeContainerptr;
1144 operationRecPtr.p->elementPointer = tgeElementptr;
1145 operationRecPtr.p->elementIsforward = tgeForward;
1146
1147 eh = ElementHeader::setLocked(operationRecPtr.i);
1148 dbgWord32(gePageptr, tgeElementptr, eh);
1149 gePageptr.p->word32[tgeElementptr] = eh;
1150
1151 opbits |= Operationrec::OP_LOCK_OWNER;
1152 insertLockOwnersList(signal, operationRecPtr);
1153 } else {
1154 jam();
1155 /*---------------------------------------------------------------*/
1156 // It is a dirty read. We do not lock anything. Set state to
1157 // IDLE since no COMMIT call will come.
1158 /*---------------------------------------------------------------*/
1159 opbits = Operationrec::OP_EXECUTED_DIRTY_READ;
1160 }//if
1161 operationRecPtr.p->m_op_bits = opbits;
1162 return;
1163 } else {
1164 jam();
1165 accIsLockedLab(signal, lockOwnerPtr);
1166 return;
1167 }//if
1168 break;
1169 case ZINSERT:
1170 jam();
1171 insertExistElemLab(signal, lockOwnerPtr);
1172 return;
1173 break;
1174 default:
1175 ndbrequire(false);
1176 break;
1177 }//switch
1178 } else if (found == ZFALSE) {
1179 switch (op){
1180 case ZWRITE:
1181 opbits &= ~(Uint32)Operationrec::OP_MASK;
1182 opbits |= (op = ZINSERT);
1183 case ZINSERT:
1184 jam();
1185 opbits |= Operationrec::OP_INSERT_IS_DONE;
1186 opbits |= Operationrec::OP_STATE_RUNNING;
1187 opbits |= Operationrec::OP_RUN_QUEUE;
1188 operationRecPtr.p->m_op_bits = opbits;
1189 insertelementLab(signal);
1190 return;
1191 break;
1192 case ZREAD:
1193 case ZUPDATE:
1194 case ZDELETE:
1195 case ZSCAN_OP:
1196 jam();
1197 acckeyref1Lab(signal, ZREAD_ERROR);
1198 return;
1199 break;
1200 default:
1201 ndbrequire(false);
1202 break;
1203 }//switch
1204 } else {
1205 jam();
1206 acckeyref1Lab(signal, found);
1207 return;
1208 }//if
1209 return;
1210 }//Dbacc::execACCKEYREQ()
1211
1212 void
execACCKEY_ORD(Signal * signal,Uint32 opPtrI)1213 Dbacc::execACCKEY_ORD(Signal* signal, Uint32 opPtrI)
1214 {
1215 jamEntry();
1216 OperationrecPtr lastOp;
1217 lastOp.i = opPtrI;
1218 ptrCheckGuard(lastOp, coprecsize, operationrec);
1219 Uint32 opbits = lastOp.p->m_op_bits;
1220 Uint32 opstate = opbits & Operationrec::OP_STATE_MASK;
1221
1222 if (likely(opbits == Operationrec::OP_EXECUTED_DIRTY_READ))
1223 {
1224 jam();
1225 lastOp.p->m_op_bits = Operationrec::OP_INITIAL;
1226 return;
1227 }
1228 else if (likely(opstate == Operationrec::OP_STATE_RUNNING))
1229 {
1230 opbits |= Operationrec::OP_STATE_EXECUTED;
1231 lastOp.p->m_op_bits = opbits;
1232 startNext(signal, lastOp);
1233 return;
1234 }
1235 else
1236 {
1237 }
1238
1239 ndbout_c("bits: %.8x state: %.8x", opbits, opstate);
1240 ndbrequire(false);
1241 }
1242
1243 void
startNext(Signal * signal,OperationrecPtr lastOp)1244 Dbacc::startNext(Signal* signal, OperationrecPtr lastOp)
1245 {
1246 jam();
1247 OperationrecPtr nextOp;
1248 OperationrecPtr loPtr;
1249 nextOp.i = lastOp.p->nextParallelQue;
1250 loPtr.i = lastOp.p->m_lock_owner_ptr_i;
1251 Uint32 opbits = lastOp.p->m_op_bits;
1252
1253 if ((opbits & Operationrec::OP_STATE_MASK)!= Operationrec::OP_STATE_EXECUTED)
1254 {
1255 jam();
1256 return;
1257 }
1258
1259 Uint32 nextbits;
1260 if (nextOp.i != RNIL)
1261 {
1262 jam();
1263 ptrCheckGuard(nextOp, coprecsize, operationrec);
1264 nextbits = nextOp.p->m_op_bits;
1265 goto checkop;
1266 }
1267
1268 if ((opbits & Operationrec::OP_LOCK_OWNER) == 0)
1269 {
1270 jam();
1271 ptrCheckGuard(loPtr, coprecsize, operationrec);
1272 }
1273 else
1274 {
1275 jam();
1276 loPtr = lastOp;
1277 }
1278
1279 nextOp.i = loPtr.p->nextSerialQue;
1280 ndbassert(loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
1281
1282 if (nextOp.i == RNIL)
1283 {
1284 jam();
1285 return;
1286 }
1287
1288 /**
1289 * There is an op in serie queue...
1290 * Check if it can run
1291 */
1292 ptrCheckGuard(nextOp, coprecsize, operationrec);
1293 nextbits = nextOp.p->m_op_bits;
1294
1295 {
1296 const bool same = nextOp.p->is_same_trans(lastOp.p);
1297
1298 if (!same && ((opbits & Operationrec::OP_ACC_LOCK_MODE) ||
1299 (nextbits & Operationrec::OP_LOCK_MODE)))
1300 {
1301 jam();
1302 /**
1303 * Not same transaction
1304 * and either last had exclusive lock
1305 * or next had exclusive lock
1306 */
1307 return;
1308 }
1309
1310 /**
1311 * same trans and X-lock
1312 */
1313 if (same && (opbits & Operationrec::OP_ACC_LOCK_MODE))
1314 {
1315 jam();
1316 goto upgrade;
1317 }
1318 }
1319
1320 /**
1321 * all shared lock...
1322 */
1323 if ((opbits & Operationrec::OP_ACC_LOCK_MODE) == 0 &&
1324 (nextbits & Operationrec::OP_LOCK_MODE) == 0)
1325 {
1326 jam();
1327 goto upgrade;
1328 }
1329
1330 /**
1331 * There is a shared parallell queue & and exclusive op is first in queue
1332 */
1333 ndbassert((opbits & Operationrec::OP_ACC_LOCK_MODE) == 0 &&
1334 (nextbits & Operationrec::OP_LOCK_MODE));
1335
1336 /**
1337 * We must check if there are many transactions in parallel queue...
1338 */
1339 OperationrecPtr tmp;
1340 tmp= loPtr;
1341 while (tmp.i != RNIL)
1342 {
1343 ptrCheckGuard(tmp, coprecsize, operationrec);
1344 if (!nextOp.p->is_same_trans(tmp.p))
1345 {
1346 jam();
1347 /**
1348 * parallel queue contained another transaction, dont let it run
1349 */
1350 return;
1351 }
1352 tmp.i = tmp.p->nextParallelQue;
1353 }
1354
1355 upgrade:
1356 /**
1357 * Move first op in serie queue to end of parallell queue
1358 */
1359
1360 tmp.i = loPtr.p->nextSerialQue = nextOp.p->nextSerialQue;
1361 loPtr.p->m_lo_last_parallel_op_ptr_i = nextOp.i;
1362 nextOp.p->nextSerialQue = RNIL;
1363 nextOp.p->prevSerialQue = RNIL;
1364 nextOp.p->m_lock_owner_ptr_i = loPtr.i;
1365 nextOp.p->prevParallelQue = lastOp.i;
1366 lastOp.p->nextParallelQue = nextOp.i;
1367
1368 if (tmp.i != RNIL)
1369 {
1370 jam();
1371 ptrCheckGuard(tmp, coprecsize, operationrec);
1372 tmp.p->prevSerialQue = loPtr.i;
1373 }
1374 else
1375 {
1376 jam();
1377 loPtr.p->m_lo_last_serial_op_ptr_i = RNIL;
1378 }
1379
1380 nextbits |= Operationrec::OP_RUN_QUEUE;
1381
1382 /**
1383 * Currently no grouping of ops in serie queue
1384 */
1385 ndbrequire(nextOp.p->nextParallelQue == RNIL);
1386
1387 checkop:
1388 Uint32 errCode = 0;
1389 OperationrecPtr save = operationRecPtr;
1390 operationRecPtr = nextOp;
1391
1392 Uint32 lastop = opbits & Operationrec::OP_MASK;
1393 Uint32 nextop = nextbits & Operationrec::OP_MASK;
1394
1395 nextbits &= nextbits & ~(Uint32)Operationrec::OP_STATE_MASK;
1396 nextbits |= Operationrec::OP_STATE_RUNNING;
1397
1398 if (lastop == ZDELETE)
1399 {
1400 jam();
1401 if (nextop != ZINSERT && nextop != ZWRITE)
1402 {
1403 errCode = ZREAD_ERROR;
1404 goto ref;
1405 }
1406
1407 nextbits &= ~(Uint32)Operationrec::OP_MASK;
1408 nextbits &= ~(Uint32)Operationrec::OP_ELEMENT_DISAPPEARED;
1409 nextbits |= (nextop = ZINSERT);
1410 goto conf;
1411 }
1412 else if (nextop == ZINSERT)
1413 {
1414 jam();
1415 errCode = ZWRITE_ERROR;
1416 goto ref;
1417 }
1418 else if (nextop == ZWRITE)
1419 {
1420 jam();
1421 nextbits &= ~(Uint32)Operationrec::OP_MASK;
1422 nextbits |= (nextop = ZUPDATE);
1423 goto conf;
1424 }
1425 else
1426 {
1427 jam();
1428 }
1429
1430 conf:
1431 nextOp.p->m_op_bits = nextbits;
1432 nextOp.p->localdata[0] = lastOp.p->localdata[0];
1433 nextOp.p->localdata[1] = lastOp.p->localdata[1];
1434
1435 if (nextop == ZSCAN_OP && (nextbits & Operationrec::OP_LOCK_REQ) == 0)
1436 {
1437 jam();
1438 takeOutScanLockQueue(nextOp.p->scanRecPtr);
1439 putReadyScanQueue(signal, nextOp.p->scanRecPtr);
1440 }
1441 else
1442 {
1443 jam();
1444 fragrecptr.i = nextOp.p->fragptr;
1445 ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
1446
1447 sendAcckeyconf(signal);
1448 sendSignal(nextOp.p->userblockref, GSN_ACCKEYCONF,
1449 signal, 6, JBB);
1450 }
1451
1452 operationRecPtr = save;
1453 return;
1454
1455 ref:
1456 nextOp.p->m_op_bits = nextbits;
1457
1458 if (nextop == ZSCAN_OP && (nextbits & Operationrec::OP_LOCK_REQ) == 0)
1459 {
1460 jam();
1461 nextOp.p->m_op_bits |= Operationrec::OP_ELEMENT_DISAPPEARED;
1462 takeOutScanLockQueue(nextOp.p->scanRecPtr);
1463 putReadyScanQueue(signal, nextOp.p->scanRecPtr);
1464 }
1465 else
1466 {
1467 jam();
1468 signal->theData[0] = nextOp.p->userptr;
1469 signal->theData[1] = errCode;
1470 sendSignal(nextOp.p->userblockref, GSN_ACCKEYREF, signal,
1471 2, JBB);
1472 }
1473
1474 operationRecPtr = save;
1475 return;
1476 }
1477
1478
1479 #if 0
1480 void
1481 Dbacc::execACCKEY_REP_REF(Signal* signal, Uint32 opPtrI)
1482 {
1483 }
1484 #endif
1485
1486 void
xfrmKeyData(Signal * signal)1487 Dbacc::xfrmKeyData(Signal* signal)
1488 {
1489 Uint32 table = fragrecptr.p->myTableId;
1490 Uint32 dst[MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY];
1491 Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
1492 Uint32* src = &signal->theData[7];
1493 Uint32 len = xfrm_key(table, src, dst, sizeof(dst) >> 2, keyPartLen);
1494 ndbrequire(len); // 0 means error
1495 memcpy(src, dst, len << 2);
1496 operationRecPtr.p->xfrmtupkeylen = len;
1497 }
1498
1499 void
accIsLockedLab(Signal * signal,OperationrecPtr lockOwnerPtr)1500 Dbacc::accIsLockedLab(Signal* signal, OperationrecPtr lockOwnerPtr)
1501 {
1502 Uint32 bits = operationRecPtr.p->m_op_bits;
1503 validate_lock_queue(lockOwnerPtr);
1504
1505 if ((bits & Operationrec::OP_DIRTY_READ) == 0){
1506 Uint32 return_result;
1507 if ((bits & Operationrec::OP_LOCK_MODE) == ZREADLOCK) {
1508 jam();
1509 return_result = placeReadInLockQueue(lockOwnerPtr);
1510 } else {
1511 jam();
1512 return_result = placeWriteInLockQueue(lockOwnerPtr);
1513 }//if
1514 if (return_result == ZPARALLEL_QUEUE) {
1515 jam();
1516 sendAcckeyconf(signal);
1517 return;
1518 } else if (return_result == ZSERIAL_QUEUE) {
1519 jam();
1520 signal->theData[0] = RNIL;
1521 return;
1522 } else {
1523 jam();
1524 acckeyref1Lab(signal, return_result);
1525 return;
1526 }//if
1527 ndbrequire(false);
1528 }
1529 else
1530 {
1531 if (! (lockOwnerPtr.p->m_op_bits & Operationrec::OP_ELEMENT_DISAPPEARED) &&
1532 ! Local_key::isInvalid(lockOwnerPtr.p->localdata[0],
1533 lockOwnerPtr.p->localdata[1]))
1534 {
1535 jam();
1536 /* ---------------------------------------------------------------
1537 * It is a dirty read. We do not lock anything. Set state to
1538 *IDLE since no COMMIT call will arrive.
1539 * ---------------------------------------------------------------*/
1540 sendAcckeyconf(signal);
1541 operationRecPtr.p->m_op_bits = Operationrec::OP_EXECUTED_DIRTY_READ;
1542 return;
1543 }
1544 else
1545 {
1546 jam();
1547 /*---------------------------------------------------------------*/
1548 // The tuple does not exist in the committed world currently.
1549 // Report read error.
1550 /*---------------------------------------------------------------*/
1551 acckeyref1Lab(signal, ZREAD_ERROR);
1552 return;
1553 }//if
1554 }//if
1555 }//Dbacc::accIsLockedLab()
1556
1557 /* ------------------------------------------------------------------------ */
1558 /* I N S E R T E X I S T E L E M E N T */
1559 /* ------------------------------------------------------------------------ */
insertExistElemLab(Signal * signal,OperationrecPtr lockOwnerPtr)1560 void Dbacc::insertExistElemLab(Signal* signal, OperationrecPtr lockOwnerPtr)
1561 {
1562 if (!lockOwnerPtr.p)
1563 {
1564 jam();
1565 acckeyref1Lab(signal, ZWRITE_ERROR);/* THE ELEMENT ALREADY EXIST */
1566 return;
1567 }//if
1568 accIsLockedLab(signal, lockOwnerPtr);
1569 }//Dbacc::insertExistElemLab()
1570
1571 /* --------------------------------------------------------------------------------- */
1572 /* INSERTELEMENT */
1573 /* --------------------------------------------------------------------------------- */
insertelementLab(Signal * signal)1574 void Dbacc::insertelementLab(Signal* signal)
1575 {
1576 if (unlikely(fragrecptr.p->dirRangeFull))
1577 {
1578 jam();
1579 acckeyref1Lab(signal, ZDIR_RANGE_FULL_ERROR);
1580 return;
1581 }
1582 if (fragrecptr.p->firstOverflowRec == RNIL) {
1583 jam();
1584 allocOverflowPage(signal);
1585 if (tresult > ZLIMIT_OF_ERROR) {
1586 jam();
1587 acckeyref1Lab(signal, tresult);
1588 return;
1589 }//if
1590 }//if
1591 ndbrequire(operationRecPtr.p->tupkeylen <= fragrecptr.p->keyLength);
1592 ndbassert(!(operationRecPtr.p->m_op_bits & Operationrec::OP_LOCK_REQ));
1593 Uint32 localKey = ~(Uint32)0;
1594
1595 insertLockOwnersList(signal, operationRecPtr);
1596
1597 const Uint32 tmp = fragrecptr.p->k + fragrecptr.p->lhfragbits;
1598 operationRecPtr.p->hashvaluePart =
1599 (operationRecPtr.p->hashValue >> tmp) & 0xFFFF;
1600 operationRecPtr.p->scanBits = 0; /* NOT ANY ACTIVE SCAN */
1601 tidrElemhead = ElementHeader::setLocked(operationRecPtr.i);
1602 idrPageptr = gdiPageptr;
1603 tidrPageindex = tgdiPageindex;
1604 tidrForward = ZTRUE;
1605 idrOperationRecPtr = operationRecPtr;
1606 clocalkey[0] = localKey;
1607 clocalkey[1] = localKey;
1608 operationRecPtr.p->localdata[0] = localKey;
1609 operationRecPtr.p->localdata[1] = localKey;
1610 /* ----------------------------------------------------------------------- */
1611 /* WE SET THE LOCAL KEY TO MINUS ONE TO INDICATE IT IS NOT YET VALID. */
1612 /* ----------------------------------------------------------------------- */
1613 insertElement(signal);
1614 sendAcckeyconf(signal);
1615 return;
1616 }//Dbacc::insertelementLab()
1617
1618
1619 /* ------------------------------------------------------------------------ */
1620 /* GET_NO_PARALLEL_TRANSACTION */
1621 /* ------------------------------------------------------------------------ */
1622 Uint32
getNoParallelTransaction(const Operationrec * op)1623 Dbacc::getNoParallelTransaction(const Operationrec * op)
1624 {
1625 OperationrecPtr tmp;
1626
1627 tmp.i= op->nextParallelQue;
1628 Uint32 transId[2] = { op->transId1, op->transId2 };
1629 while (tmp.i != RNIL)
1630 {
1631 jam();
1632 ptrCheckGuard(tmp, coprecsize, operationrec);
1633 if (tmp.p->transId1 == transId[0] && tmp.p->transId2 == transId[1])
1634 tmp.i = tmp.p->nextParallelQue;
1635 else
1636 return 2;
1637 }
1638 return 1;
1639 }//Dbacc::getNoParallelTransaction()
1640
1641 #ifdef VM_TRACE
1642 Uint32
getNoParallelTransactionFull(const Operationrec * op)1643 Dbacc::getNoParallelTransactionFull(const Operationrec * op)
1644 {
1645 ConstPtr<Operationrec> tmp;
1646
1647 tmp.p = op;
1648 while ((tmp.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0)
1649 {
1650 tmp.i = tmp.p->prevParallelQue;
1651 if (tmp.i != RNIL)
1652 {
1653 ptrCheckGuard(tmp, coprecsize, operationrec);
1654 }
1655 else
1656 {
1657 break;
1658 }
1659 }
1660
1661 return getNoParallelTransaction(tmp.p);
1662 }
1663 #endif
1664
1665 #ifdef ACC_SAFE_QUEUE
1666
1667 Uint32
get_parallel_head(OperationrecPtr opPtr)1668 Dbacc::get_parallel_head(OperationrecPtr opPtr)
1669 {
1670 while ((opPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0 &&
1671 opPtr.p->prevParallelQue != RNIL)
1672 {
1673 opPtr.i = opPtr.p->prevParallelQue;
1674 ptrCheckGuard(opPtr, coprecsize, operationrec);
1675 }
1676
1677 return opPtr.i;
1678 }
1679
1680 bool
validate_lock_queue(OperationrecPtr opPtr)1681 Dbacc::validate_lock_queue(OperationrecPtr opPtr)
1682 {
1683 OperationrecPtr loPtr;
1684 loPtr.i = get_parallel_head(opPtr);
1685 ptrCheckGuard(loPtr, coprecsize, operationrec);
1686
1687 while((loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0 &&
1688 loPtr.p->prevSerialQue != RNIL)
1689 {
1690 loPtr.i = loPtr.p->prevSerialQue;
1691 ptrCheckGuard(loPtr, coprecsize, operationrec);
1692 }
1693
1694 // Now we have lock owner...
1695 vlqrequire(loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
1696 vlqrequire(loPtr.p->m_op_bits & Operationrec::OP_RUN_QUEUE);
1697
1698 // 1 Validate page pointer
1699 {
1700 Page8Ptr pagePtr;
1701 pagePtr.i = loPtr.p->elementPage;
1702 ptrCheckGuard(pagePtr, cpagesize, page8);
1703 arrGuard(loPtr.p->elementPointer, 2048);
1704 Uint32 eh = pagePtr.p->word32[loPtr.p->elementPointer];
1705 vlqrequire(ElementHeader::getLocked(eh));
1706 vlqrequire(ElementHeader::getOpPtrI(eh) == loPtr.i);
1707 }
1708
1709 // 2 Lock owner should always have same LOCK_MODE and ACC_LOCK_MODE
1710 if (loPtr.p->m_op_bits & Operationrec::OP_LOCK_MODE)
1711 {
1712 vlqrequire(loPtr.p->m_op_bits & Operationrec::OP_ACC_LOCK_MODE);
1713 }
1714 else
1715 {
1716 vlqrequire((loPtr.p->m_op_bits & Operationrec::OP_ACC_LOCK_MODE) == 0);
1717 }
1718
1719 // 3 Lock owner should never be waiting...
1720 bool running = false;
1721 {
1722 Uint32 opstate = loPtr.p->m_op_bits & Operationrec::OP_STATE_MASK;
1723 if (opstate == Operationrec::OP_STATE_RUNNING)
1724 running = true;
1725 else
1726 {
1727 vlqrequire(opstate == Operationrec::OP_STATE_EXECUTED);
1728 }
1729 }
1730
1731 // Validate parallel queue
1732 {
1733 bool many = false;
1734 bool orlockmode = loPtr.p->m_op_bits & Operationrec::OP_LOCK_MODE;
1735 OperationrecPtr lastP = loPtr;
1736
1737 while (lastP.p->nextParallelQue != RNIL)
1738 {
1739 Uint32 prev = lastP.i;
1740 lastP.i = lastP.p->nextParallelQue;
1741 ptrCheckGuard(lastP, coprecsize, operationrec);
1742
1743 vlqrequire(lastP.p->prevParallelQue == prev);
1744
1745 Uint32 opbits = lastP.p->m_op_bits;
1746 many |= loPtr.p->is_same_trans(lastP.p) ? 0 : 1;
1747 orlockmode |= !!(opbits & Operationrec::OP_LOCK_MODE);
1748
1749 vlqrequire(opbits & Operationrec::OP_RUN_QUEUE);
1750 vlqrequire((opbits & Operationrec::OP_LOCK_OWNER) == 0);
1751
1752 Uint32 opstate = opbits & Operationrec::OP_STATE_MASK;
1753 if (running)
1754 {
1755 // If I found a running operation,
1756 // all following should be waiting
1757 vlqrequire(opstate == Operationrec::OP_STATE_WAITING);
1758 }
1759 else
1760 {
1761 if (opstate == Operationrec::OP_STATE_RUNNING)
1762 running = true;
1763 else
1764 vlqrequire(opstate == Operationrec::OP_STATE_EXECUTED);
1765 }
1766
1767 if (lastP.p->m_op_bits & Operationrec::OP_LOCK_MODE)
1768 {
1769 vlqrequire(lastP.p->m_op_bits & Operationrec::OP_ACC_LOCK_MODE);
1770 }
1771 else
1772 {
1773 vlqrequire((lastP.p->m_op_bits && orlockmode) == orlockmode);
1774 vlqrequire((lastP.p->m_op_bits & Operationrec::OP_MASK) == ZREAD ||
1775 (lastP.p->m_op_bits & Operationrec::OP_MASK) == ZSCAN_OP);
1776 }
1777
1778 if (many)
1779 {
1780 vlqrequire(orlockmode == 0);
1781 }
1782 }
1783
1784 if (lastP.i != loPtr.i)
1785 {
1786 vlqrequire(loPtr.p->m_lo_last_parallel_op_ptr_i == lastP.i);
1787 vlqrequire(lastP.p->m_lock_owner_ptr_i == loPtr.i);
1788 }
1789 else
1790 {
1791 vlqrequire(loPtr.p->m_lo_last_parallel_op_ptr_i == RNIL);
1792 }
1793 }
1794
1795 // Validate serie queue
1796 if (loPtr.p->nextSerialQue != RNIL)
1797 {
1798 Uint32 prev = loPtr.i;
1799 OperationrecPtr lastS;
1800 lastS.i = loPtr.p->nextSerialQue;
1801 while (true)
1802 {
1803 ptrCheckGuard(lastS, coprecsize, operationrec);
1804 vlqrequire(lastS.p->prevSerialQue == prev);
1805 vlqrequire(getNoParallelTransaction(lastS.p) == 1);
1806 vlqrequire((lastS.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0);
1807 vlqrequire((lastS.p->m_op_bits & Operationrec::OP_RUN_QUEUE) == 0);
1808 vlqrequire((lastS.p->m_op_bits & Operationrec::OP_STATE_MASK) == Operationrec::OP_STATE_WAITING);
1809 if (lastS.p->nextSerialQue == RNIL)
1810 break;
1811 prev = lastS.i;
1812 lastS.i = lastS.p->nextSerialQue;
1813 }
1814
1815 vlqrequire(loPtr.p->m_lo_last_serial_op_ptr_i == lastS.i);
1816 }
1817 else
1818 {
1819 vlqrequire(loPtr.p->m_lo_last_serial_op_ptr_i == RNIL);
1820 }
1821 return true;
1822 }
1823
1824 NdbOut&
operator <<(NdbOut & out,Dbacc::OperationrecPtr ptr)1825 operator<<(NdbOut & out, Dbacc::OperationrecPtr ptr)
1826 {
1827 Uint32 opbits = ptr.p->m_op_bits;
1828 out << "[ " << dec << ptr.i
1829 << " [ " << hex << ptr.p->transId1
1830 << " " << hex << ptr.p->transId2 << "] "
1831 << " bits: H'" << hex << opbits << " ";
1832
1833 bool read = false;
1834 switch(opbits & Dbacc::Operationrec::OP_MASK){
1835 case ZREAD: out << "READ "; read = true; break;
1836 case ZINSERT: out << "INSERT "; break;
1837 case ZUPDATE: out << "UPDATE "; break;
1838 case ZDELETE: out << "DELETE "; break;
1839 case ZWRITE: out << "WRITE "; break;
1840 case ZSCAN_OP: out << "SCAN "; read = true; break;
1841 default:
1842 out << "<Unknown: H'"
1843 << hex << (opbits & Dbacc::Operationrec::OP_MASK)
1844 << "> ";
1845 }
1846
1847 if (read)
1848 {
1849 if (opbits & Dbacc::Operationrec::OP_LOCK_MODE)
1850 out << "(X)";
1851 else
1852 out << "(S)";
1853 if (opbits & Dbacc::Operationrec::OP_ACC_LOCK_MODE)
1854 out << "(X)";
1855 else
1856 out << "(S)";
1857 }
1858
1859 if (opbits)
1860 {
1861 out << "(RQ)";
1862 }
1863
1864 switch(opbits & Dbacc::Operationrec::OP_STATE_MASK){
1865 case Dbacc::Operationrec::OP_STATE_WAITING:
1866 out << " WAITING "; break;
1867 case Dbacc::Operationrec::OP_STATE_RUNNING:
1868 out << " RUNNING "; break;
1869 case Dbacc::Operationrec::OP_STATE_EXECUTED:
1870 out << " EXECUTED "; break;
1871 case Dbacc::Operationrec::OP_STATE_IDLE:
1872 out << " IDLE "; break;
1873 default:
1874 out << " <Unknown: H'"
1875 << hex << (opbits & Dbacc::Operationrec::OP_STATE_MASK)
1876 << "> ";
1877 }
1878
1879 /*
1880 OP_MASK = 0x000F // 4 bits for operation type
1881 ,OP_LOCK_MODE = 0x0010 // 0 - shared lock, 1 = exclusive lock
1882 ,OP_ACC_LOCK_MODE = 0x0020 // Or:de lock mode of all operation
1883 // before me
1884 ,OP_LOCK_OWNER = 0x0040
1885 ,OP_DIRTY_READ = 0x0080
1886 ,OP_LOCK_REQ = 0x0100 // isAccLockReq
1887 ,OP_COMMIT_DELETE_CHECK = 0x0200
1888 ,OP_INSERT_IS_DONE = 0x0400
1889 ,OP_ELEMENT_DISAPPEARED = 0x0800
1890
1891 ,OP_STATE_MASK = 0xF000
1892 ,OP_STATE_IDLE = 0xF000
1893 ,OP_STATE_WAITING = 0x0000
1894 ,OP_STATE_RUNNING = 0x1000
1895 ,OP_STATE_EXECUTED = 0x3000
1896 };
1897 */
1898 if (opbits & Dbacc::Operationrec::OP_LOCK_OWNER)
1899 out << "LO ";
1900
1901 if (opbits & Dbacc::Operationrec::OP_DIRTY_READ)
1902 out << "DR ";
1903
1904 if (opbits & Dbacc::Operationrec::OP_LOCK_REQ)
1905 out << "LOCK_REQ ";
1906
1907 if (opbits & Dbacc::Operationrec::OP_COMMIT_DELETE_CHECK)
1908 out << "COMMIT_DELETE_CHECK ";
1909
1910 if (opbits & Dbacc::Operationrec::OP_INSERT_IS_DONE)
1911 out << "INSERT_IS_DONE ";
1912
1913 if (opbits & Dbacc::Operationrec::OP_ELEMENT_DISAPPEARED)
1914 out << "ELEMENT_DISAPPEARED ";
1915
1916 if (opbits & Dbacc::Operationrec::OP_LOCK_OWNER)
1917 {
1918 out << "last_parallel: " << dec << ptr.p->m_lo_last_parallel_op_ptr_i << " ";
1919 out << "last_serial: " << dec << ptr.p->m_lo_last_serial_op_ptr_i << " ";
1920 }
1921
1922 out << "]";
1923 return out;
1924 }
1925
1926 void
dump_lock_queue(OperationrecPtr loPtr)1927 Dbacc::dump_lock_queue(OperationrecPtr loPtr)
1928 {
1929 if ((loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0)
1930 {
1931 while ((loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0 &&
1932 loPtr.p->prevParallelQue != RNIL)
1933 {
1934 loPtr.i = loPtr.p->prevParallelQue;
1935 ptrCheckGuard(loPtr, coprecsize, operationrec);
1936 }
1937
1938 while ((loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0 &&
1939 loPtr.p->prevSerialQue != RNIL)
1940 {
1941 loPtr.i = loPtr.p->prevSerialQue;
1942 ptrCheckGuard(loPtr, coprecsize, operationrec);
1943 }
1944
1945 ndbassert(loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
1946 }
1947
1948 ndbout << "-- HEAD --" << endl;
1949 OperationrecPtr tmp = loPtr;
1950 while (tmp.i != RNIL)
1951 {
1952 ptrCheckGuard(tmp, coprecsize, operationrec);
1953 ndbout << tmp << " ";
1954 tmp.i = tmp.p->nextParallelQue;
1955
1956 if (tmp.i == loPtr.i)
1957 {
1958 ndbout << " <LOOP>";
1959 break;
1960 }
1961 }
1962 ndbout << endl;
1963
1964 tmp.i = loPtr.p->nextSerialQue;
1965 while (tmp.i != RNIL)
1966 {
1967 ptrCheckGuard(tmp, coprecsize, operationrec);
1968 OperationrecPtr tmp2 = tmp;
1969
1970 if (tmp.i == loPtr.i)
1971 {
1972 ndbout << "<LOOP S>" << endl;
1973 break;
1974 }
1975
1976 while (tmp2.i != RNIL)
1977 {
1978 ptrCheckGuard(tmp2, coprecsize, operationrec);
1979 ndbout << tmp2 << " ";
1980 tmp2.i = tmp2.p->nextParallelQue;
1981
1982 if (tmp2.i == tmp.i)
1983 {
1984 ndbout << "<LOOP 3>";
1985 break;
1986 }
1987 }
1988 ndbout << endl;
1989 tmp.i = tmp.p->nextSerialQue;
1990 }
1991 }
1992 #endif
1993
1994 /* -------------------------------------------------------------------------
1995 * PLACE_WRITE_IN_LOCK_QUEUE
1996 * INPUT: OPERATION_REC_PTR OUR OPERATION POINTER
1997 * QUE_OPER_PTR LOCK QUEUE OWNER OPERATION POINTER
1998 * PWI_PAGEPTR PAGE POINTER OF ELEMENT
1999 * TPWI_ELEMENTPTR ELEMENT POINTER OF ELEMENT
2000 * OUTPUT TRESULT =
2001 * ZPARALLEL_QUEUE OPERATION PLACED IN PARALLEL QUEUE
2002 * OPERATION CAN PROCEED NOW.
2003 * ZSERIAL_QUEUE OPERATION PLACED IN SERIAL QUEUE
2004 * ERROR CODE OPERATION NEEDS ABORTING
2005 * ------------------------------------------------------------------------- */
2006 Uint32
placeWriteInLockQueue(OperationrecPtr lockOwnerPtr)2007 Dbacc::placeWriteInLockQueue(OperationrecPtr lockOwnerPtr)
2008 {
2009 OperationrecPtr lastOpPtr;
2010 lastOpPtr.i = lockOwnerPtr.p->m_lo_last_parallel_op_ptr_i;
2011 Uint32 opbits = operationRecPtr.p->m_op_bits;
2012
2013 if (lastOpPtr.i == RNIL)
2014 {
2015 lastOpPtr = lockOwnerPtr;
2016 }
2017 else
2018 {
2019 ptrCheckGuard(lastOpPtr, coprecsize, operationrec);
2020 }
2021
2022 ndbassert(get_parallel_head(lastOpPtr) == lockOwnerPtr.i);
2023
2024 Uint32 lastbits = lastOpPtr.p->m_op_bits;
2025 if (lastbits & Operationrec::OP_ACC_LOCK_MODE)
2026 {
2027 if(operationRecPtr.p->is_same_trans(lastOpPtr.p))
2028 {
2029 goto checkop;
2030 }
2031 }
2032 else
2033 {
2034 /**
2035 * We dont have an exclusive lock on operation and
2036 *
2037 */
2038 jam();
2039
2040 /**
2041 * Scan parallell queue to see if we are the only one
2042 */
2043 OperationrecPtr loopPtr = lockOwnerPtr;
2044 do
2045 {
2046 ptrCheckGuard(loopPtr, coprecsize, operationrec);
2047 if (!loopPtr.p->is_same_trans(operationRecPtr.p))
2048 {
2049 goto serial;
2050 }
2051 loopPtr.i = loopPtr.p->nextParallelQue;
2052 } while (loopPtr.i != RNIL);
2053
2054 goto checkop;
2055 }
2056
2057 serial:
2058 jam();
2059 placeSerialQueue(lockOwnerPtr, operationRecPtr);
2060
2061 validate_lock_queue(lockOwnerPtr);
2062
2063 return ZSERIAL_QUEUE;
2064
2065 checkop:
2066 /*
2067 WE ARE PERFORMING AN READ EXCLUSIVE, INSERT, UPDATE OR DELETE IN THE SAME
2068 TRANSACTION WHERE WE PREVIOUSLY HAVE EXECUTED AN OPERATION.
2069 Read-All, Update-All, Insert-All and Delete-Insert are allowed
2070 combinations.
2071 Delete-Read, Delete-Update and Delete-Delete are not an allowed
2072 combination and will result in tuple not found error.
2073 */
2074 Uint32 lstate = lastbits & Operationrec::OP_STATE_MASK;
2075
2076 Uint32 retValue = ZSERIAL_QUEUE; // So that it gets blocked...
2077 if (lstate == Operationrec::OP_STATE_EXECUTED)
2078 {
2079 jam();
2080
2081 /**
2082 * Since last operation has executed...we can now check operation types
2083 * if not, we have to wait until it has executed
2084 */
2085 Uint32 op = opbits & Operationrec::OP_MASK;
2086 Uint32 lop = lastbits & Operationrec::OP_MASK;
2087 if (op == ZINSERT && lop != ZDELETE)
2088 {
2089 jam();
2090 return ZWRITE_ERROR;
2091 }//if
2092
2093 /**
2094 * NOTE. No checking op operation types, as one can read different save
2095 * points...
2096 */
2097 #if 0
2098 if (lop == ZDELETE && (op != ZINSERT && op != ZWRITE))
2099 {
2100 jam();
2101 return ZREAD_ERROR;
2102 }
2103 #else
2104 if (lop == ZDELETE && (op == ZUPDATE && op == ZDELETE))
2105 {
2106 jam();
2107 return ZREAD_ERROR;
2108 }
2109 #endif
2110
2111 if(op == ZWRITE)
2112 {
2113 opbits &= ~(Uint32)Operationrec::OP_MASK;
2114 opbits |= (lop == ZDELETE) ? ZINSERT : ZUPDATE;
2115 }
2116
2117 opbits |= Operationrec::OP_STATE_RUNNING;
2118 operationRecPtr.p->localdata[0] = lastOpPtr.p->localdata[0];
2119 operationRecPtr.p->localdata[1] = lastOpPtr.p->localdata[1];
2120 retValue = ZPARALLEL_QUEUE;
2121 }
2122
2123 opbits |= Operationrec::OP_RUN_QUEUE;
2124 operationRecPtr.p->m_op_bits = opbits;
2125 operationRecPtr.p->prevParallelQue = lastOpPtr.i;
2126 operationRecPtr.p->m_lock_owner_ptr_i = lockOwnerPtr.i;
2127 lastOpPtr.p->nextParallelQue = operationRecPtr.i;
2128 lockOwnerPtr.p->m_lo_last_parallel_op_ptr_i = operationRecPtr.i;
2129
2130 validate_lock_queue(lockOwnerPtr);
2131
2132 return retValue;
2133 }//Dbacc::placeWriteInLockQueue()
2134
2135 Uint32
placeReadInLockQueue(OperationrecPtr lockOwnerPtr)2136 Dbacc::placeReadInLockQueue(OperationrecPtr lockOwnerPtr)
2137 {
2138 OperationrecPtr lastOpPtr;
2139 OperationrecPtr loopPtr = lockOwnerPtr;
2140 lastOpPtr.i = lockOwnerPtr.p->m_lo_last_parallel_op_ptr_i;
2141 Uint32 opbits = operationRecPtr.p->m_op_bits;
2142
2143 if (lastOpPtr.i == RNIL)
2144 {
2145 lastOpPtr = lockOwnerPtr;
2146 }
2147 else
2148 {
2149 ptrCheckGuard(lastOpPtr, coprecsize, operationrec);
2150 }
2151
2152 ndbassert(get_parallel_head(lastOpPtr) == lockOwnerPtr.i);
2153
2154 /**
2155 * Last operation in parallell queue of lock owner is same trans
2156 * and ACC_LOCK_MODE is exlusive, then we can proceed
2157 */
2158 Uint32 lastbits = lastOpPtr.p->m_op_bits;
2159 bool same = operationRecPtr.p->is_same_trans(lastOpPtr.p);
2160 if (same && (lastbits & Operationrec::OP_ACC_LOCK_MODE))
2161 {
2162 jam();
2163 opbits |= Operationrec::OP_LOCK_MODE; // Upgrade to X-lock
2164 goto checkop;
2165 }
2166
2167 if ((lastbits & Operationrec::OP_ACC_LOCK_MODE) && !same)
2168 {
2169 jam();
2170 /**
2171 * Last op in serial queue had X-lock and was not our transaction...
2172 */
2173 goto serial;
2174 }
2175
2176 if (lockOwnerPtr.p->nextSerialQue == RNIL)
2177 {
2178 jam();
2179 goto checkop;
2180 }
2181
2182 /**
2183 * Scan parallell queue to see if we are already there...
2184 */
2185 do
2186 {
2187 ptrCheckGuard(loopPtr, coprecsize, operationrec);
2188 if (loopPtr.p->is_same_trans(operationRecPtr.p))
2189 goto checkop;
2190 loopPtr.i = loopPtr.p->nextParallelQue;
2191 } while (loopPtr.i != RNIL);
2192
2193 serial:
2194 placeSerialQueue(lockOwnerPtr, operationRecPtr);
2195
2196 validate_lock_queue(lockOwnerPtr);
2197
2198 return ZSERIAL_QUEUE;
2199
2200 checkop:
2201 Uint32 lstate = lastbits & Operationrec::OP_STATE_MASK;
2202
2203 Uint32 retValue = ZSERIAL_QUEUE; // So that it gets blocked...
2204 if (lstate == Operationrec::OP_STATE_EXECUTED)
2205 {
2206 jam();
2207
2208 /**
2209 * NOTE. No checking op operation types, as one can read different save
2210 * points...
2211 */
2212
2213 #if 0
2214 /**
2215 * Since last operation has executed...we can now check operation types
2216 * if not, we have to wait until it has executed
2217 */
2218 if (lop == ZDELETE)
2219 {
2220 jam();
2221 return ZREAD_ERROR;
2222 }
2223 #endif
2224
2225 opbits |= Operationrec::OP_STATE_RUNNING;
2226 operationRecPtr.p->localdata[0] = lastOpPtr.p->localdata[0];
2227 operationRecPtr.p->localdata[1] = lastOpPtr.p->localdata[1];
2228 retValue = ZPARALLEL_QUEUE;
2229 }
2230 opbits |= (lastbits & Operationrec::OP_ACC_LOCK_MODE);
2231 opbits |= Operationrec::OP_RUN_QUEUE;
2232 operationRecPtr.p->m_op_bits = opbits;
2233
2234 operationRecPtr.p->prevParallelQue = lastOpPtr.i;
2235 operationRecPtr.p->m_lock_owner_ptr_i = lockOwnerPtr.i;
2236 lastOpPtr.p->nextParallelQue = operationRecPtr.i;
2237 lockOwnerPtr.p->m_lo_last_parallel_op_ptr_i = operationRecPtr.i;
2238
2239 validate_lock_queue(lockOwnerPtr);
2240
2241 return retValue;
2242 }//Dbacc::placeReadInLockQueue
2243
placeSerialQueue(OperationrecPtr lockOwnerPtr,OperationrecPtr opPtr)2244 void Dbacc::placeSerialQueue(OperationrecPtr lockOwnerPtr,
2245 OperationrecPtr opPtr)
2246 {
2247 OperationrecPtr lastOpPtr;
2248 lastOpPtr.i = lockOwnerPtr.p->m_lo_last_serial_op_ptr_i;
2249
2250 if (lastOpPtr.i == RNIL)
2251 {
2252 // Lock owner is last...
2253 ndbrequire(lockOwnerPtr.p->nextSerialQue == RNIL);
2254 lastOpPtr = lockOwnerPtr;
2255 }
2256 else
2257 {
2258 ptrCheckGuard(lastOpPtr, coprecsize, operationrec);
2259 }
2260
2261 operationRecPtr.p->prevSerialQue = lastOpPtr.i;
2262 lastOpPtr.p->nextSerialQue = opPtr.i;
2263 lockOwnerPtr.p->m_lo_last_serial_op_ptr_i = opPtr.i;
2264 }
2265
2266 /* ------------------------------------------------------------------------- */
2267 /* ACC KEYREQ END */
2268 /* ------------------------------------------------------------------------- */
acckeyref1Lab(Signal * signal,Uint32 result_code)2269 void Dbacc::acckeyref1Lab(Signal* signal, Uint32 result_code)
2270 {
2271 operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
2272 /* ************************<< */
2273 /* ACCKEYREF */
2274 /* ************************<< */
2275 signal->theData[0] = cminusOne;
2276 signal->theData[1] = result_code;
2277 return;
2278 }//Dbacc::acckeyref1Lab()
2279
2280 /* ******************----------------------------------------------------- */
2281 /* ACCMINUPDATE UPDATE LOCAL KEY REQ */
2282 /* DESCRIPTION: UPDATES LOCAL KEY OF AN ELEMENTS IN THE HASH TABLE */
2283 /* THIS SIGNAL IS WAITED AFTER ANY INSERT REQ */
2284 /* ENTER ACCMINUPDATE WITH SENDER: LQH, LEVEL B */
2285 /* OPERATION_REC_PTR, OPERATION RECORD PTR */
2286 /* CLOCALKEY(0), LOCAL KEY 1 */
2287 /* CLOCALKEY(1) LOCAL KEY 2 */
2288 /* ******************----------------------------------------------------- */
execACCMINUPDATE(Signal * signal)2289 void Dbacc::execACCMINUPDATE(Signal* signal)
2290 {
2291 Page8Ptr ulkPageidptr;
2292 Uint32 tulkLocalPtr;
2293 Uint32 tlocalkey1, tlocalkey2;
2294
2295 jamEntry();
2296 operationRecPtr.i = signal->theData[0];
2297 tlocalkey1 = signal->theData[1];
2298 tlocalkey2 = signal->theData[2];
2299 Uint32 localref = Local_key::ref(tlocalkey1, tlocalkey2);
2300 ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
2301 Uint32 opbits = operationRecPtr.p->m_op_bits;
2302 fragrecptr.i = operationRecPtr.p->fragptr;
2303 ulkPageidptr.i = operationRecPtr.p->elementPage;
2304 tulkLocalPtr = operationRecPtr.p->elementPointer +
2305 operationRecPtr.p->elementIsforward;
2306
2307 if ((opbits & Operationrec::OP_STATE_MASK) == Operationrec::OP_STATE_RUNNING)
2308 {
2309 ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
2310 ptrCheckGuard(ulkPageidptr, cpagesize, page8);
2311 dbgWord32(ulkPageidptr, tulkLocalPtr, tlocalkey1);
2312 arrGuard(tulkLocalPtr, 2048);
2313 operationRecPtr.p->localdata[0] = tlocalkey1;
2314 operationRecPtr.p->localdata[1] = tlocalkey2;
2315 if (likely(fragrecptr.p->localkeylen == 1))
2316 {
2317 ulkPageidptr.p->word32[tulkLocalPtr] = localref;
2318 return;
2319 }
2320 else if (fragrecptr.p->localkeylen == 2)
2321 {
2322 jam();
2323 ulkPageidptr.p->word32[tulkLocalPtr] = tlocalkey1;
2324 tulkLocalPtr = tulkLocalPtr + operationRecPtr.p->elementIsforward;
2325 dbgWord32(ulkPageidptr, tulkLocalPtr, tlocalkey2);
2326 arrGuard(tulkLocalPtr, 2048);
2327 ulkPageidptr.p->word32[tulkLocalPtr] = tlocalkey2;
2328 return;
2329 } else {
2330 jam();
2331 }//if
2332 }//if
2333 ndbrequire(false);
2334 }//Dbacc::execACCMINUPDATE()
2335
2336 void
removerow(Uint32 opPtrI,const Local_key * key)2337 Dbacc::removerow(Uint32 opPtrI, const Local_key* key)
2338 {
2339 jamEntry();
2340 operationRecPtr.i = opPtrI;
2341 ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
2342 Uint32 opbits = operationRecPtr.p->m_op_bits;
2343 fragrecptr.i = operationRecPtr.p->fragptr;
2344
2345 /* Mark element disappeared */
2346 opbits |= Operationrec::OP_ELEMENT_DISAPPEARED;
2347 opbits &= ~Uint32(Operationrec::OP_COMMIT_DELETE_CHECK);
2348 operationRecPtr.p->m_op_bits = opbits;
2349
2350 #ifdef VM_TRACE
2351 ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
2352 ndbrequire(operationRecPtr.p->localdata[0] == key->m_page_no);
2353 ndbrequire(operationRecPtr.p->localdata[1] == key->m_page_idx);
2354 #endif
2355 }//Dbacc::execACCMINUPDATE()
2356
2357 /* ******************--------------------------------------------------------------- */
2358 /* ACC_COMMITREQ COMMIT TRANSACTION */
2359 /* SENDER: LQH, LEVEL B */
2360 /* INPUT: OPERATION_REC_PTR , */
2361 /* ******************--------------------------------------------------------------- */
execACC_COMMITREQ(Signal * signal)2362 void Dbacc::execACC_COMMITREQ(Signal* signal)
2363 {
2364 Uint8 Toperation;
2365 jamEntry();
2366 Uint32 tmp = operationRecPtr.i = signal->theData[0];
2367 ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
2368 void* ptr = operationRecPtr.p;
2369 Uint32 opbits = operationRecPtr.p->m_op_bits;
2370 fragrecptr.i = operationRecPtr.p->fragptr;
2371 ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
2372 Toperation = opbits & Operationrec::OP_MASK;
2373 commitOperation(signal);
2374 ndbassert(operationRecPtr.i == tmp);
2375 ndbassert(operationRecPtr.p == ptr);
2376 operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
2377 if((Toperation != ZREAD) &&
2378 (Toperation != ZSCAN_OP))
2379 {
2380 fragrecptr.p->m_commit_count++;
2381 if (Toperation != ZINSERT) {
2382 if (Toperation != ZDELETE) {
2383 return;
2384 } else {
2385 jam();
2386 fragrecptr.p->noOfElements--;
2387 fragrecptr.p->slack += fragrecptr.p->elementLength;
2388 if (fragrecptr.p->slack > fragrecptr.p->slackCheck) {
2389 /* TIME FOR JOIN BUCKETS PROCESS */
2390 if (fragrecptr.p->expandCounter > 0) {
2391 if (fragrecptr.p->expandFlag < 2) {
2392 jam();
2393 signal->theData[0] = fragrecptr.i;
2394 signal->theData[1] = fragrecptr.p->p;
2395 signal->theData[2] = fragrecptr.p->maxp;
2396 signal->theData[3] = fragrecptr.p->expandFlag;
2397 fragrecptr.p->expandFlag = 2;
2398 sendSignal(cownBlockref, GSN_SHRINKCHECK2, signal, 4, JBB);
2399 }//if
2400 }//if
2401 }//if
2402 }//if
2403 } else {
2404 jam(); /* EXPAND PROCESS HANDLING */
2405 if (unlikely(opbits & Operationrec::OP_ELEMENT_DISAPPEARED))
2406 {
2407 jam();
2408 /* Commit of refresh of non existing tuple.
2409 * ZREFRESH->ZWRITE->ZINSERT
2410 * Do not affect element count
2411 */
2412 ndbrequire((opbits & Operationrec::OP_MASK) == ZINSERT);
2413 return;
2414 }
2415 fragrecptr.p->noOfElements++;
2416 fragrecptr.p->slack -= fragrecptr.p->elementLength;
2417 if (fragrecptr.p->slack >= (1u << 31)) {
2418 /* IT MEANS THAT IF SLACK < ZERO */
2419 if (fragrecptr.p->expandFlag == 0) {
2420 jam();
2421 fragrecptr.p->expandFlag = 2;
2422 signal->theData[0] = fragrecptr.i;
2423 signal->theData[1] = fragrecptr.p->p;
2424 signal->theData[2] = fragrecptr.p->maxp;
2425 sendSignal(cownBlockref, GSN_EXPANDCHECK2, signal, 3, JBB);
2426 }//if
2427 }//if
2428 }
2429 }
2430 return;
2431 }//Dbacc::execACC_COMMITREQ()
2432
2433 /* ******************------------------------------------------------------- */
2434 /* ACC ABORT REQ ABORT ALL OPERATION OF THE TRANSACTION */
2435 /* ******************------------------------------+ */
2436 /* SENDER: LQH, LEVEL B */
2437 /* ******************------------------------------------------------------- */
2438 /* ACC ABORT REQ ABORT TRANSACTION */
2439 /* ******************------------------------------+ */
2440 /* SENDER: LQH, LEVEL B */
execACC_ABORTREQ(Signal * signal)2441 void Dbacc::execACC_ABORTREQ(Signal* signal)
2442 {
2443 jamEntry();
2444 operationRecPtr.i = signal->theData[0];
2445 Uint32 sendConf = signal->theData[1];
2446 ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
2447 fragrecptr.i = operationRecPtr.p->fragptr;
2448 Uint32 opbits = operationRecPtr.p->m_op_bits;
2449 Uint32 opstate = opbits & Operationrec::OP_STATE_MASK;
2450 tresult = 0; /* ZFALSE */
2451
2452 if (opbits == Operationrec::OP_EXECUTED_DIRTY_READ)
2453 {
2454 jam();
2455 }
2456 else if (opstate == Operationrec::OP_STATE_EXECUTED ||
2457 opstate == Operationrec::OP_STATE_WAITING ||
2458 opstate == Operationrec::OP_STATE_RUNNING)
2459 {
2460 jam();
2461 ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
2462 abortOperation(signal);
2463 }
2464
2465 operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
2466
2467 signal->theData[0] = operationRecPtr.p->userptr;
2468 signal->theData[1] = 0;
2469 switch(sendConf){
2470 case 0:
2471 return;
2472 case 2:
2473 if (opstate != Operationrec::OP_STATE_RUNNING)
2474 {
2475 return;
2476 }
2477 case 1:
2478 sendSignal(operationRecPtr.p->userblockref, GSN_ACC_ABORTCONF,
2479 signal, 1, JBB);
2480 }
2481
2482 signal->theData[1] = RNIL;
2483 }
2484
2485 /*
2486 * Lock or unlock tuple.
2487 */
execACC_LOCKREQ(Signal * signal)2488 void Dbacc::execACC_LOCKREQ(Signal* signal)
2489 {
2490 jamEntry();
2491 AccLockReq* sig = (AccLockReq*)signal->getDataPtrSend();
2492 AccLockReq reqCopy = *sig;
2493 AccLockReq* const req = &reqCopy;
2494 Uint32 lockOp = (req->requestInfo & 0xFF);
2495 if (lockOp == AccLockReq::LockShared ||
2496 lockOp == AccLockReq::LockExclusive) {
2497 jam();
2498 // find table
2499 tabptr.i = req->tableId;
2500 ptrCheckGuard(tabptr, ctablesize, tabrec);
2501 // find fragment (TUX will know it)
2502 if (req->fragPtrI == RNIL) {
2503 for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
2504 jam();
2505 if (tabptr.p->fragholder[i] == req->fragId){
2506 jam();
2507 req->fragPtrI = tabptr.p->fragptrholder[i];
2508 break;
2509 }
2510 }
2511 }
2512 fragrecptr.i = req->fragPtrI;
2513 ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
2514 ndbrequire(req->fragId == fragrecptr.p->myfid);
2515 // caller must be explicit here
2516 ndbrequire(req->accOpPtr == RNIL);
2517 // seize operation to hold the lock
2518 if (cfreeopRec != RNIL) {
2519 jam();
2520 seizeOpRec(signal);
2521 // init as in ACCSEIZEREQ
2522 operationRecPtr.p->userptr = req->userPtr;
2523 operationRecPtr.p->userblockref = req->userRef;
2524 operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
2525 operationRecPtr.p->scanRecPtr = RNIL;
2526 // do read with lock via ACCKEYREQ
2527 Uint32 lockMode = (lockOp == AccLockReq::LockShared) ? 0 : 1;
2528 Uint32 opCode = ZSCAN_OP;
2529 signal->theData[0] = operationRecPtr.i;
2530 signal->theData[1] = fragrecptr.i;
2531 signal->theData[2] = opCode | (lockMode << 4) | (1u << 31);
2532 signal->theData[3] = req->hashValue;
2533 signal->theData[4] = 0; // search local key
2534 signal->theData[5] = req->transId1;
2535 signal->theData[6] = req->transId2;
2536 // enter local key in place of PK
2537 signal->theData[7] = req->page_id;
2538 signal->theData[8] = req->page_idx;
2539 EXECUTE_DIRECT(DBACC, GSN_ACCKEYREQ, signal, 9);
2540 // translate the result
2541 if (signal->theData[0] < RNIL) {
2542 jam();
2543 req->returnCode = AccLockReq::Success;
2544 req->accOpPtr = operationRecPtr.i;
2545 } else if (signal->theData[0] == RNIL) {
2546 jam();
2547 req->returnCode = AccLockReq::IsBlocked;
2548 req->accOpPtr = operationRecPtr.i;
2549 } else {
2550 ndbrequire(signal->theData[0] == (UintR)-1);
2551 releaseOpRec(signal);
2552 req->returnCode = AccLockReq::Refused;
2553 req->accOpPtr = RNIL;
2554 }
2555 } else {
2556 jam();
2557 req->returnCode = AccLockReq::NoFreeOp;
2558 }
2559 *sig = *req;
2560 return;
2561 }
2562 if (lockOp == AccLockReq::Unlock) {
2563 jam();
2564 // do unlock via ACC_COMMITREQ (immediate)
2565 signal->theData[0] = req->accOpPtr;
2566 EXECUTE_DIRECT(DBACC, GSN_ACC_COMMITREQ, signal, 1);
2567 releaseOpRec(signal);
2568 req->returnCode = AccLockReq::Success;
2569 *sig = *req;
2570 return;
2571 }
2572 if (lockOp == AccLockReq::Abort) {
2573 jam();
2574 // do abort via ACC_ABORTREQ (immediate)
2575 signal->theData[0] = req->accOpPtr;
2576 signal->theData[1] = 0; // Dont send abort
2577 execACC_ABORTREQ(signal);
2578 releaseOpRec(signal);
2579 req->returnCode = AccLockReq::Success;
2580 *sig = *req;
2581 return;
2582 }
2583 if (lockOp == AccLockReq::AbortWithConf) {
2584 jam();
2585 // do abort via ACC_ABORTREQ (with conf signal)
2586 signal->theData[0] = req->accOpPtr;
2587 signal->theData[1] = 1; // send abort
2588 execACC_ABORTREQ(signal);
2589 releaseOpRec(signal);
2590 req->returnCode = AccLockReq::Success;
2591 *sig = *req;
2592 return;
2593 }
2594 ndbrequire(false);
2595 }
2596
2597 /* --------------------------------------------------------------------------------- */
2598 /* --------------------------------------------------------------------------------- */
2599 /* --------------------------------------------------------------------------------- */
2600 /* */
2601 /* END OF EXECUTE OPERATION MODULE */
2602 /* */
2603 /* --------------------------------------------------------------------------------- */
2604 /* --------------------------------------------------------------------------------- */
2605 /* --------------------------------------------------------------------------------- */
2606 /* --------------------------------------------------------------------------------- */
2607 /* */
2608 /* MODULE: INSERT */
2609 /* THE FOLLOWING SUBROUTINES ARE ONLY USED BY INSERT_ELEMENT. THIS */
2610 /* ROUTINE IS THE SOLE INTERFACE TO INSERT ELEMENTS INTO THE INDEX. */
2611 /* CURRENT USERS ARE INSERT REQUESTS, EXPAND CONTAINER AND SHRINK */
2612 /* CONTAINER. */
2613 /* */
2614 /* THE FOLLOWING SUBROUTINES ARE INCLUDED IN THIS MODULE: */
2615 /* INSERT_ELEMENT */
2616 /* INSERT_CONTAINER */
2617 /* ADDNEWCONTAINER */
2618 /* GETFREELIST */
2619 /* INCREASELISTCONT */
2620 /* SEIZE_LEFTLIST */
2621 /* SEIZE_RIGHTLIST */
2622 /* */
2623 /* THESE ROUTINES ARE ONLY USED BY THIS MODULE AND BY NO ONE ELSE. */
2624 /* ALSO THE ROUTINES MAKE NO USE OF ROUTINES IN OTHER MODULES. */
2625 /* TAKE_REC_OUT_OF_FREE_OVERPAGE AND RELEASE_OVERFLOW_REC ARE */
2626 /* EXCEPTIONS TO THIS RULE. */
2627 /* */
2628 /* THE ONLY SHORT-LIVED VARIABLES USED IN OTHER PARTS OF THE BLOCK ARE */
2629 /* THOSE DEFINED AS INPUT AND OUTPUT IN INSERT_ELEMENT */
2630 /* SHORT-LIVED VARIABLES INCLUDE TEMPORARY VARIABLES, COMMON VARIABLES */
2631 /* AND POINTER VARIABLES. */
2632 /* THE ONLY EXCEPTION TO THIS RULE IS FRAGRECPTR WHICH POINTS TO THE */
2633 /* FRAGMENT RECORD. THIS IS MORE LESS STATIC ALWAYS DURING A SIGNAL */
2634 /* EXECUTION. */
2635 /* */
2636 /* --------------------------------------------------------------------------------- */
2637 /* --------------------------------------------------------------------------------- */
2638 /* --------------------------------------------------------------------------------- */
2639 /* INSERT_ELEMENT */
2640 /* INPUT: */
2641 /* IDR_PAGEPTR (POINTER TO THE ACTIVE PAGE REC) */
2642 /* TIDR_PAGEINDEX (INDEX OF THE CONTAINER) */
2643 /* TIDR_FORWARD (DIRECTION FORWARD OR BACKWARD) */
2644 /* TIDR_ELEMHEAD (HEADER OF ELEMENT TO BE INSERTED */
2645 /* CIDR_KEYS(ARRAY OF TUPLE KEYS) */
2646 /* CLOCALKEY(ARRAY OF LOCAL KEYS). */
2647 /* FRAGRECPTR */
2648 /* IDR_OPERATION_REC_PTR */
2649 /* TIDR_KEY_LEN */
2650 /* */
2651 /* OUTPUT: */
2652 /* TIDR_PAGEINDEX (PAGE INDEX OF INSERTED ELEMENT) */
2653 /* IDR_PAGEPTR (PAGE POINTER OF INSERTED ELEMENT) */
2654 /* TIDR_FORWARD (CONTAINER DIRECTION OF INSERTED ELEMENT) */
2655 /* NONE */
2656 /* --------------------------------------------------------------------------------- */
insertElement(Signal * signal)2657 void Dbacc::insertElement(Signal* signal)
2658 {
2659 DirRangePtr inrOverflowrangeptr;
2660 DirectoryarrayPtr inrOverflowDirptr;
2661 OverflowRecordPtr inrOverflowRecPtr;
2662 Page8Ptr inrNewPageptr;
2663 Uint32 tinrNextSamePage;
2664 Uint32 tinrTmp;
2665
2666 do {
2667 insertContainer(signal);
2668 if (tidrResult != ZFALSE) {
2669 jam();
2670 return;
2671 /* INSERTION IS DONE, OR */
2672 /* AN ERROR IS DETECTED */
2673 }//if
2674 if (((tidrContainerhead >> 7) & 0x3) != 0) {
2675 tinrNextSamePage = (tidrContainerhead >> 9) & 0x1; /* CHECK BIT FOR CHECKING WHERE */
2676 /* THE NEXT CONTAINER IS IN THE SAME PAGE */
2677 tidrPageindex = tidrContainerhead & 0x7f; /* NEXT CONTAINER PAGE INDEX 7 BITS */
2678 if (((tidrContainerhead >> 7) & 3) == ZLEFT) {
2679 jam();
2680 tidrForward = ZTRUE;
2681 } else if (((tidrContainerhead >> 7) & 3) == ZRIGHT) {
2682 jam();
2683 tidrForward = cminusOne;
2684 } else {
2685 ndbrequire(false);
2686 return;
2687 }//if
2688 if (tinrNextSamePage == ZFALSE) {
2689 jam(); /* NEXT CONTAINER IS IN AN OVERFLOW PAGE */
2690 tinrTmp = idrPageptr.p->word32[tidrContainerptr + 1];
2691 inrOverflowrangeptr.i = fragrecptr.p->overflowdir;
2692 ptrCheckGuard(inrOverflowrangeptr, cdirrangesize, dirRange);
2693 arrGuard((tinrTmp >> 8), 256);
2694 inrOverflowDirptr.i = inrOverflowrangeptr.p->dirArray[tinrTmp >> 8];
2695 ptrCheckGuard(inrOverflowDirptr, cdirarraysize, directoryarray);
2696 idrPageptr.i = inrOverflowDirptr.p->pagep[tinrTmp & 0xff];
2697 ptrCheckGuard(idrPageptr, cpagesize, page8);
2698 }//if
2699 ndbrequire(tidrPageindex < ZEMPTYLIST);
2700 } else {
2701 break;
2702 }//if
2703 } while (1);
2704 gflPageptr.p = idrPageptr.p;
2705 getfreelist(signal);
2706 if (tgflPageindex == ZEMPTYLIST) {
2707 jam();
2708 /* NO FREE BUFFER IS FOUND */
2709 if (fragrecptr.p->firstOverflowRec == RNIL) {
2710 jam();
2711 allocOverflowPage(signal);
2712 ndbrequire(tresult <= ZLIMIT_OF_ERROR);
2713 }//if
2714 inrOverflowRecPtr.i = fragrecptr.p->firstOverflowRec;
2715 ptrCheckGuard(inrOverflowRecPtr, coverflowrecsize, overflowRecord);
2716 inrNewPageptr.i = inrOverflowRecPtr.p->overpage;
2717 ptrCheckGuard(inrNewPageptr, cpagesize, page8);
2718 gflPageptr.p = inrNewPageptr.p;
2719 getfreelist(signal);
2720 ndbrequire(tgflPageindex != ZEMPTYLIST);
2721 tancNext = 0;
2722 } else {
2723 jam();
2724 inrNewPageptr = idrPageptr;
2725 tancNext = 1;
2726 }//if
2727 tslUpdateHeader = ZTRUE;
2728 tslPageindex = tgflPageindex;
2729 slPageptr.p = inrNewPageptr.p;
2730 if (tgflBufType == ZLEFT) {
2731 seizeLeftlist(signal);
2732 tidrForward = ZTRUE;
2733 } else {
2734 seizeRightlist(signal);
2735 tidrForward = cminusOne;
2736 }//if
2737 tancPageindex = tgflPageindex;
2738 tancPageid = inrNewPageptr.p->word32[ZPOS_PAGE_ID];
2739 tancBufType = tgflBufType;
2740 tancContainerptr = tidrContainerptr;
2741 ancPageptr.p = idrPageptr.p;
2742 addnewcontainer(signal);
2743
2744 idrPageptr = inrNewPageptr;
2745 tidrPageindex = tgflPageindex;
2746 insertContainer(signal);
2747 ndbrequire(tidrResult == ZTRUE);
2748 }//Dbacc::insertElement()
2749
2750 /* --------------------------------------------------------------------------------- */
2751 /* INSERT_CONTAINER */
2752 /* INPUT: */
2753 /* IDR_PAGEPTR (POINTER TO THE ACTIVE PAGE REC) */
2754 /* TIDR_PAGEINDEX (INDEX OF THE CONTAINER) */
2755 /* TIDR_FORWARD (DIRECTION FORWARD OR BACKWARD) */
2756 /* TIDR_ELEMHEAD (HEADER OF ELEMENT TO BE INSERTED */
2757 /* CKEYS(ARRAY OF TUPLE KEYS) */
2758 /* CLOCALKEY(ARRAY 0F LOCAL KEYS). */
2759 /* TIDR_KEY_LEN */
2760 /* FRAGRECPTR */
2761 /* IDR_OPERATION_REC_PTR */
2762 /* OUTPUT: */
2763 /* TIDR_RESULT (ZTRUE FOR SUCCESS AND ZFALSE OTHERWISE) */
2764 /* TIDR_CONTAINERHEAD (HEADER OF CONTAINER) */
2765 /* TIDR_CONTAINERPTR (POINTER TO CONTAINER HEADER) */
2766 /* */
2767 /* DESCRIPTION: */
2768 /* THE FREE AREA OF THE CONTAINER WILL BE CALCULATED. IF IT IS */
2769 /* LARGER THAN OR EQUAL THE ELEMENT LENGTH. THE ELEMENT WILL BE */
2770 /* INSERT IN THE CONTAINER AND CONTAINER HEAD WILL BE UPDATED. */
2771 /* THIS ROUTINE ALWAYS DEALS WITH ONLY ONE CONTAINER AND DO NEVER */
2772 /* START ANYTHING OUTSIDE OF THIS CONTAINER. */
2773 /* */
2774 /* SHORT FORM: IDR */
2775 /* --------------------------------------------------------------------------------- */
insertContainer(Signal * signal)2776 void Dbacc::insertContainer(Signal* signal)
2777 {
2778 Uint32 tidrContainerlen;
2779 Uint32 tidrConfreelen;
2780 Uint32 tidrNextSide;
2781 Uint32 tidrNextConLen;
2782 Uint32 tidrIndex;
2783 Uint32 tidrInputIndex;
2784 Uint32 tidrContLen;
2785 Uint32 guard26;
2786
2787 tidrResult = ZFALSE;
2788 tidrContainerptr = (tidrPageindex << ZSHIFT_PLUS) - (tidrPageindex << ZSHIFT_MINUS);
2789 tidrContainerptr = tidrContainerptr + ZHEAD_SIZE;
2790 /* --------------------------------------------------------------------------------- */
2791 /* CALCULATE THE POINTER TO THE ELEMENT TO BE INSERTED AND THE POINTER TO THE */
2792 /* CONTAINER HEADER OF THE OTHER SIDE OF THE BUFFER. */
2793 /* --------------------------------------------------------------------------------- */
2794 if (tidrForward == ZTRUE) {
2795 jam();
2796 tidrNextSide = tidrContainerptr + (ZBUF_SIZE - ZCON_HEAD_SIZE);
2797 arrGuard(tidrNextSide + 1, 2048);
2798 tidrContainerhead = idrPageptr.p->word32[tidrContainerptr];
2799 tidrContainerlen = tidrContainerhead >> 26;
2800 tidrIndex = tidrContainerptr + tidrContainerlen;
2801 } else {
2802 jam();
2803 tidrNextSide = tidrContainerptr;
2804 tidrContainerptr = tidrContainerptr + (ZBUF_SIZE - ZCON_HEAD_SIZE);
2805 arrGuard(tidrContainerptr + 1, 2048);
2806 tidrContainerhead = idrPageptr.p->word32[tidrContainerptr];
2807 tidrContainerlen = tidrContainerhead >> 26;
2808 tidrIndex = (tidrContainerptr - tidrContainerlen) + (ZCON_HEAD_SIZE - 1);
2809 }//if
2810 if (tidrContainerlen > (ZBUF_SIZE - 3)) {
2811 return;
2812 }//if
2813 tidrConfreelen = ZBUF_SIZE - tidrContainerlen;
2814 /* --------------------------------------------------------------------------------- */
2815 /* WE CALCULATE THE TOTAL LENGTH THE CONTAINER CAN EXPAND TO */
2816 /* THIS INCLUDES THE OTHER SIDE OF THE BUFFER IF POSSIBLE TO EXPAND THERE. */
2817 /* --------------------------------------------------------------------------------- */
2818 if (((tidrContainerhead >> 10) & 1) == 0) {
2819 jam();
2820 /* --------------------------------------------------------------------------------- */
2821 /* WE HAVE NOT EXPANDED TO THE ENTIRE BUFFER YET. WE CAN THUS READ THE OTHER */
2822 /* SIDE'S CONTAINER HEADER TO READ HIS LENGTH. */
2823 /* --------------------------------------------------------------------------------- */
2824 tidrNextConLen = idrPageptr.p->word32[tidrNextSide] >> 26;
2825 tidrConfreelen = tidrConfreelen - tidrNextConLen;
2826 if (tidrConfreelen > ZBUF_SIZE) {
2827 ndbrequire(false);
2828 /* --------------------------------------------------------------------------------- */
2829 /* THE BUFFERS ARE PLACED ON TOP OF EACH OTHER. THIS SHOULD NEVER OCCUR. */
2830 /* --------------------------------------------------------------------------------- */
2831 return;
2832 }//if
2833 } else {
2834 jam();
2835 tidrNextConLen = 1; /* INDICATE OTHER SIDE IS NOT PART OF FREE LIST */
2836 }//if
2837 if (tidrConfreelen < fragrecptr.p->elementLength) {
2838 jam();
2839 /* --------------------------------------------------------------------------------- */
2840 /* THE CONTAINER COULD NOT BE EXPANDED TO FIT THE NEW ELEMENT. WE HAVE TO */
2841 /* RETURN AND FIND A NEW CONTAINER TO INSERT IT INTO. */
2842 /* --------------------------------------------------------------------------------- */
2843 return;
2844 }//if
2845 tidrContainerlen = tidrContainerlen + fragrecptr.p->elementLength;
2846 if (tidrNextConLen == 0) {
2847 /* EACH SIDE OF THE BUFFER WHICH BELONG TO A FREE */
2848 /* LIST, HAS ZERO AS LENGTH. */
2849 if (tidrContainerlen > ZUP_LIMIT) {
2850 dbgWord32(idrPageptr, tidrContainerptr, idrPageptr.p->word32[tidrContainerptr] | (1 << 10));
2851 idrPageptr.p->word32[tidrContainerptr] = idrPageptr.p->word32[tidrContainerptr] | (1 << 10);
2852 tslUpdateHeader = ZFALSE;
2853 tslPageindex = tidrPageindex;
2854 slPageptr.p = idrPageptr.p;
2855 if (tidrForward == ZTRUE) {
2856 jam();
2857 seizeRightlist(signal); /* REMOVE THE RIGHT SIDE OF THE BUFFER FROM THE LIST */
2858 } else {
2859 jam();
2860 /* OF THE FREE CONTAINERS */
2861 seizeLeftlist(signal); /* REMOVE THE LEFT SIDE OF THE BUFFER FROM THE LIST */
2862 }//if
2863 }//if
2864 }//if
2865 /* OF THE FREE CONTAINERS */
2866 /* --------------------------------------------------------------------------------- */
2867 /* WE HAVE NOW FOUND A FREE SPOT IN THE CURRENT CONTAINER. WE INSERT THE */
2868 /* ELEMENT HERE. THE ELEMENT CONTAINS A HEADER, A LOCAL KEY AND A TUPLE KEY. */
2869 /* BEFORE INSERTING THE ELEMENT WE WILL UPDATE THE OPERATION RECORD WITH THE */
2870 /* DATA CONCERNING WHERE WE INSERTED THE ELEMENT. THIS MAKES IT EASY TO FIND */
2871 /* THIS INFORMATION WHEN WE RETURN TO UPDATE THE LOCAL KEY OR RETURN TO COMMIT */
2872 /* OR ABORT THE INSERT. IF NO OPERATION RECORD EXIST IT MEANS THAT WE ARE */
2873 /* PERFORMING THIS AS A PART OF THE EXPAND OR SHRINK PROCESS. */
2874 /* --------------------------------------------------------------------------------- */
2875 if (idrOperationRecPtr.i != RNIL) {
2876 jam();
2877 idrOperationRecPtr.p->elementIsforward = tidrForward;
2878 idrOperationRecPtr.p->elementPage = idrPageptr.i;
2879 idrOperationRecPtr.p->elementContainer = tidrContainerptr;
2880 idrOperationRecPtr.p->elementPointer = tidrIndex;
2881 }//if
2882 /* --------------------------------------------------------------------------------- */
2883 /* WE CHOOSE TO UNDO LOG INSERTS BY WRITING THE BEFORE VALUE TO THE UNDO LOG. */
2884 /* WE COULD ALSO HAVE DONE THIS BY WRITING THIS BEFORE VALUE WHEN DELETING */
2885 /* ELEMENTS. WE CHOOSE TO PUT IT HERE SINCE WE THEREBY ENSURE THAT WE ALWAYS */
2886 /* UNDO LOG ALL WRITES TO PAGE MEMORY. IT SHOULD BE EASIER TO MAINTAIN SUCH A */
2887 /* STRUCTURE. IT IS RATHER DIFFICULT TO MAINTAIN A LOGICAL STRUCTURE WHERE */
2888 /* DELETES ARE INSERTS AND INSERTS ARE PURELY DELETES. */
2889 /* --------------------------------------------------------------------------------- */
2890 dbgWord32(idrPageptr, tidrIndex, tidrElemhead);
2891 idrPageptr.p->word32[tidrIndex] = tidrElemhead; /* INSERTS THE HEAD OF THE ELEMENT */
2892 tidrIndex += tidrForward;
2893 guard26 = fragrecptr.p->localkeylen - 1;
2894 arrGuard(guard26, 2);
2895 for (tidrInputIndex = 0; tidrInputIndex <= guard26; tidrInputIndex++) {
2896 dbgWord32(idrPageptr, tidrIndex, clocalkey[tidrInputIndex]);
2897 arrGuard(tidrIndex, 2048);
2898 idrPageptr.p->word32[tidrIndex] = clocalkey[tidrInputIndex]; /* INSERTS LOCALKEY */
2899 tidrIndex += tidrForward;
2900 }//for
2901 tidrContLen = idrPageptr.p->word32[tidrContainerptr] << 6;
2902 tidrContLen = tidrContLen >> 6;
2903 dbgWord32(idrPageptr, tidrContainerptr, (tidrContainerlen << 26) | tidrContLen);
2904 idrPageptr.p->word32[tidrContainerptr] = (tidrContainerlen << 26) | tidrContLen;
2905 tidrResult = ZTRUE;
2906 }//Dbacc::insertContainer()
2907
2908 /* --------------------------------------------------------------------------------- */
2909 /* ADDNEWCONTAINER */
2910 /* INPUT: */
2911 /* TANC_CONTAINERPTR */
2912 /* ANC_PAGEPTR */
2913 /* TANC_NEXT */
2914 /* TANC_PAGEINDEX */
2915 /* TANC_BUF_TYPE */
2916 /* TANC_PAGEID */
2917 /* OUTPUT: */
2918 /* NONE */
2919 /* */
2920 /* --------------------------------------------------------------------------------- */
addnewcontainer(Signal * signal)2921 void Dbacc::addnewcontainer(Signal* signal)
2922 {
2923 Uint32 tancTmp1;
2924
2925 /* THE OLD DATA IS STORED ON AN UNDO PAGE */
2926 /* --------------------------------------------------------------------------------- */
2927 /* KEEP LENGTH INFORMATION IN BIT 26-31. */
2928 /* SET BIT 9 INDICATING IF NEXT BUFFER IN THE SAME PAGE USING TANC_NEXT. */
2929 /* SET TYPE OF NEXT CONTAINER IN BIT 7-8. */
2930 /* SET PAGE INDEX OF NEXT CONTAINER IN BIT 0-6. */
2931 /* KEEP INDICATOR OF OWNING OTHER SIDE OF BUFFER IN BIT 10. */
2932 /* --------------------------------------------------------------------------------- */
2933 tancTmp1 = ancPageptr.p->word32[tancContainerptr] >> 10;
2934 tancTmp1 = tancTmp1 << 1;
2935 tancTmp1 = tancTmp1 | tancNext;
2936 tancTmp1 = tancTmp1 << 2;
2937 tancTmp1 = tancTmp1 | tancBufType; /* TYPE OF THE NEXT CONTAINER */
2938 tancTmp1 = tancTmp1 << 7;
2939 tancTmp1 = tancTmp1 | tancPageindex;
2940 dbgWord32(ancPageptr, tancContainerptr, tancTmp1);
2941 ancPageptr.p->word32[tancContainerptr] = tancTmp1; /* HEAD OF THE CONTAINER IS UPDATED */
2942 dbgWord32(ancPageptr, tancContainerptr + 1, tancPageid);
2943 ancPageptr.p->word32[tancContainerptr + 1] = tancPageid;
2944 }//Dbacc::addnewcontainer()
2945
2946 /* --------------------------------------------------------------------------------- */
2947 /* GETFREELIST */
2948 /* INPUT: */
2949 /* GFL_PAGEPTR (POINTER TO A PAGE RECORD). */
2950 /* OUTPUT: */
2951 /* TGFL_PAGEINDEX(POINTER TO A FREE BUFFER IN THE FREEPAGE), AND */
2952 /* TGFL_BUF_TYPE( TYPE OF THE FREE BUFFER). */
2953 /* DESCRIPTION: SEARCHS IN THE FREE LIST OF THE FREE BUFFER IN THE PAGE HEAD */
2954 /* (WORD32(1)),AND RETURN ADDRESS OF A FREE BUFFER OR NIL. */
2955 /* THE FREE BUFFER CAN BE A RIGHT CONTAINER OR A LEFT ONE */
2956 /* THE KIND OF THE CONTAINER IS NOTED BY TGFL_BUF_TYPE. */
2957 /* --------------------------------------------------------------------------------- */
getfreelist(Signal * signal)2958 void Dbacc::getfreelist(Signal* signal)
2959 {
2960 Uint32 tgflTmp;
2961
2962 tgflTmp = gflPageptr.p->word32[ZPOS_EMPTY_LIST];
2963 tgflPageindex = (tgflTmp >> 7) & 0x7f; /* LEFT FREE LIST */
2964 tgflBufType = ZLEFT;
2965 if (tgflPageindex == ZEMPTYLIST) {
2966 jam();
2967 tgflPageindex = tgflTmp & 0x7f; /* RIGHT FREE LIST */
2968 tgflBufType = ZRIGHT;
2969 }//if
2970 ndbrequire(tgflPageindex <= ZEMPTYLIST);
2971 }//Dbacc::getfreelist()
2972
2973 /* --------------------------------------------------------------------------------- */
2974 /* INCREASELISTCONT */
2975 /* INPUT: */
2976 /* ILC_PAGEPTR PAGE POINTER TO INCREASE NUMBER OF CONTAINERS IN */
2977 /* A CONTAINER OF AN OVERFLOW PAGE (FREEPAGEPTR) IS ALLOCATED, NR OF */
2978 /* ALLOCATED CONTAINER HAVE TO BE INCRESE BY ONE . */
2979 /* IF THE NUMBER OF ALLOCATED CONTAINERS IS ABOVE THE FREE LIMIT WE WILL */
2980 /* REMOVE THE PAGE FROM THE FREE LIST. */
2981 /* --------------------------------------------------------------------------------- */
increaselistcont(Signal * signal)2982 void Dbacc::increaselistcont(Signal* signal)
2983 {
2984 OverflowRecordPtr ilcOverflowRecPtr;
2985
2986 dbgWord32(ilcPageptr, ZPOS_ALLOC_CONTAINERS, ilcPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] + 1);
2987 ilcPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] = ilcPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] + 1;
2988 if (ilcPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] > ZFREE_LIMIT) {
2989 if (ilcPageptr.p->word32[ZPOS_OVERFLOWREC] != RNIL) {
2990 jam();
2991 ilcOverflowRecPtr.i = ilcPageptr.p->word32[ZPOS_OVERFLOWREC];
2992 dbgWord32(ilcPageptr, ZPOS_OVERFLOWREC, RNIL);
2993 ilcPageptr.p->word32[ZPOS_OVERFLOWREC] = RNIL;
2994 ptrCheckGuard(ilcOverflowRecPtr, coverflowrecsize, overflowRecord);
2995 tfoOverflowRecPtr = ilcOverflowRecPtr;
2996 takeRecOutOfFreeOverpage(signal);
2997 rorOverflowRecPtr = ilcOverflowRecPtr;
2998 releaseOverflowRec(signal);
2999 }//if
3000 }//if
3001 }//Dbacc::increaselistcont()
3002
3003 /* --------------------------------------------------------------------------------- */
3004 /* SEIZE_LEFTLIST */
3005 /* INPUT: */
3006 /* TSL_PAGEINDEX PAGE INDEX OF CONTAINER TO SEIZE */
3007 /* SL_PAGEPTR PAGE POINTER OF CONTAINER TO SEIZE */
3008 /* TSL_UPDATE_HEADER SHOULD WE UPDATE THE CONTAINER HEADER */
3009 /* */
3010 /* OUTPUT: */
3011 /* NONE */
3012 /* DESCRIPTION: THE BUFFER NOTED BY TSL_PAGEINDEX WILL BE REMOVED FROM THE */
3013 /* LIST OF LEFT FREE CONTAINER, IN THE HEADER OF THE PAGE */
3014 /* (FREEPAGEPTR). PREVIOUS AND NEXT BUFFER OF REMOVED BUFFER */
3015 /* WILL BE UPDATED. */
3016 /* --------------------------------------------------------------------------------- */
seizeLeftlist(Signal * signal)3017 void Dbacc::seizeLeftlist(Signal* signal)
3018 {
3019 Uint32 tsllTmp1;
3020 Uint32 tsllNewHead;
3021 Uint32 tsllHeadIndex;
3022 Uint32 tsllTmp;
3023
3024 tsllHeadIndex = ((tslPageindex << ZSHIFT_PLUS) - (tslPageindex << ZSHIFT_MINUS)) + ZHEAD_SIZE;
3025 arrGuard(tsllHeadIndex + 1, 2048);
3026 tslNextfree = slPageptr.p->word32[tsllHeadIndex];
3027 tslPrevfree = slPageptr.p->word32[tsllHeadIndex + 1];
3028 if (tslPrevfree == ZEMPTYLIST) {
3029 jam();
3030 /* UPDATE FREE LIST OF LEFT CONTAINER IN PAGE HEAD */
3031 tsllTmp1 = slPageptr.p->word32[ZPOS_EMPTY_LIST];
3032 tsllTmp = tsllTmp1 & 0x7f;
3033 tsllTmp1 = (tsllTmp1 >> 14) << 14;
3034 tsllTmp1 = (tsllTmp1 | (tslNextfree << 7)) | tsllTmp;
3035 dbgWord32(slPageptr, ZPOS_EMPTY_LIST, tsllTmp1);
3036 slPageptr.p->word32[ZPOS_EMPTY_LIST] = tsllTmp1;
3037 } else {
3038 ndbrequire(tslPrevfree < ZEMPTYLIST);
3039 jam();
3040 tsllTmp = ((tslPrevfree << ZSHIFT_PLUS) - (tslPrevfree << ZSHIFT_MINUS)) + ZHEAD_SIZE;
3041 dbgWord32(slPageptr, tsllTmp, tslNextfree);
3042 slPageptr.p->word32[tsllTmp] = tslNextfree;
3043 }//if
3044 if (tslNextfree < ZEMPTYLIST) {
3045 jam();
3046 tsllTmp = (((tslNextfree << ZSHIFT_PLUS) - (tslNextfree << ZSHIFT_MINUS)) + ZHEAD_SIZE) + 1;
3047 dbgWord32(slPageptr, tsllTmp, tslPrevfree);
3048 slPageptr.p->word32[tsllTmp] = tslPrevfree;
3049 } else {
3050 ndbrequire(tslNextfree == ZEMPTYLIST);
3051 jam();
3052 }//if
3053 /* --------------------------------------------------------------------------------- */
3054 /* IF WE ARE UPDATING THE HEADER WE ARE CREATING A NEW CONTAINER IN THE PAGE. */
3055 /* TO BE ABLE TO FIND ALL LOCKED ELEMENTS WE KEEP ALL CONTAINERS IN LINKED */
3056 /* LISTS IN THE PAGE. */
3057 /* */
3058 /* ZPOS_EMPTY_LIST CONTAINS A NEXT POINTER IN BIT 16-22 THAT REFERS TO THE */
3059 /* FIRST CONTAINER IN A LIST OF USED RIGHT CONTAINERS IN THE PAGE. */
3060 /* ZPOS_EMPTY_LIST CONTAINS A NEXT POINTER IN BIT 23-29 THAT REFERS TO THE */
3061 /* FIRST CONTAINER IN A LIST OF USED LEFT CONTAINERS IN THE PAGE. */
3062 /* EACH CONTAINER IN THE LIST CONTAINS A NEXT POINTER IN BIT 11-17 AND IT */
3063 /* CONTAINS A PREVIOUS POINTER IN BIT 18-24. */
3064 /* WE ALSO SET BIT 25 TO INDICATE THAT IT IS A CONTAINER HEADER. */
3065 /* --------------------------------------------------------------------------------- */
3066 if (tslUpdateHeader == ZTRUE) {
3067 jam();
3068 tslNextfree = (slPageptr.p->word32[ZPOS_EMPTY_LIST] >> 23) & 0x7f;
3069 tsllNewHead = ZCON_HEAD_SIZE;
3070 tsllNewHead = ((tsllNewHead << 8) + ZEMPTYLIST) + (1 << 7);
3071 tsllNewHead = (tsllNewHead << 7) + tslNextfree;
3072 tsllNewHead = tsllNewHead << 11;
3073 dbgWord32(slPageptr, tsllHeadIndex, tsllNewHead);
3074 slPageptr.p->word32[tsllHeadIndex] = tsllNewHead;
3075 tsllTmp = slPageptr.p->word32[ZPOS_EMPTY_LIST] & 0xc07fffff;
3076 tsllTmp = tsllTmp | (tslPageindex << 23);
3077 dbgWord32(slPageptr, ZPOS_EMPTY_LIST, tsllTmp);
3078 slPageptr.p->word32[ZPOS_EMPTY_LIST] = tsllTmp;
3079 if (tslNextfree < ZEMPTYLIST) {
3080 jam();
3081 tsllTmp = ((tslNextfree << ZSHIFT_PLUS) - (tslNextfree << ZSHIFT_MINUS)) + ZHEAD_SIZE;
3082 tsllTmp1 = slPageptr.p->word32[tsllTmp] & 0xfe03ffff;
3083 tsllTmp1 = tsllTmp1 | (tslPageindex << 18);
3084 dbgWord32(slPageptr, tsllTmp, tsllTmp1);
3085 slPageptr.p->word32[tsllTmp] = tsllTmp1;
3086 } else {
3087 ndbrequire(tslNextfree == ZEMPTYLIST);
3088 jam();
3089 }//if
3090 }//if
3091 ilcPageptr.p = slPageptr.p;
3092 increaselistcont(signal);
3093 }//Dbacc::seizeLeftlist()
3094
3095 /* --------------------------------------------------------------------------------- */
3096 /* SEIZE_RIGHTLIST */
3097 /* DESCRIPTION: THE BUFFER NOTED BY TSL_PAGEINDEX WILL BE REMOVED FROM THE */
3098 /* LIST OF RIGHT FREE CONTAINER, IN THE HEADER OF THE PAGE */
3099 /* (SL_PAGEPTR). PREVIOUS AND NEXT BUFFER OF REMOVED BUFFER */
3100 /* WILL BE UPDATED. */
3101 /* --------------------------------------------------------------------------------- */
seizeRightlist(Signal * signal)3102 void Dbacc::seizeRightlist(Signal* signal)
3103 {
3104 Uint32 tsrlTmp1;
3105 Uint32 tsrlNewHead;
3106 Uint32 tsrlHeadIndex;
3107 Uint32 tsrlTmp;
3108
3109 tsrlHeadIndex = ((tslPageindex << ZSHIFT_PLUS) - (tslPageindex << ZSHIFT_MINUS)) + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
3110 arrGuard(tsrlHeadIndex + 1, 2048);
3111 tslNextfree = slPageptr.p->word32[tsrlHeadIndex];
3112 tslPrevfree = slPageptr.p->word32[tsrlHeadIndex + 1];
3113 if (tslPrevfree == ZEMPTYLIST) {
3114 jam();
3115 tsrlTmp = slPageptr.p->word32[ZPOS_EMPTY_LIST];
3116 dbgWord32(slPageptr, ZPOS_EMPTY_LIST, ((tsrlTmp >> 7) << 7) | tslNextfree);
3117 slPageptr.p->word32[ZPOS_EMPTY_LIST] = ((tsrlTmp >> 7) << 7) | tslNextfree;
3118 } else {
3119 ndbrequire(tslPrevfree < ZEMPTYLIST);
3120 jam();
3121 tsrlTmp = ((tslPrevfree << ZSHIFT_PLUS) - (tslPrevfree << ZSHIFT_MINUS)) + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
3122 dbgWord32(slPageptr, tsrlTmp, tslNextfree);
3123 slPageptr.p->word32[tsrlTmp] = tslNextfree;
3124 }//if
3125 if (tslNextfree < ZEMPTYLIST) {
3126 jam();
3127 tsrlTmp = ((tslNextfree << ZSHIFT_PLUS) - (tslNextfree << ZSHIFT_MINUS)) + ((ZHEAD_SIZE + ZBUF_SIZE) - (ZCON_HEAD_SIZE - 1));
3128 dbgWord32(slPageptr, tsrlTmp, tslPrevfree);
3129 slPageptr.p->word32[tsrlTmp] = tslPrevfree;
3130 } else {
3131 ndbrequire(tslNextfree == ZEMPTYLIST);
3132 jam();
3133 }//if
3134 /* --------------------------------------------------------------------------------- */
3135 /* IF WE ARE UPDATING THE HEADER WE ARE CREATING A NEW CONTAINER IN THE PAGE. */
3136 /* TO BE ABLE TO FIND ALL LOCKED ELEMENTS WE KEEP ALL CONTAINERS IN LINKED */
3137 /* LISTS IN THE PAGE. */
3138 /* */
3139 /* ZPOS_EMPTY_LIST CONTAINS A NEXT POINTER IN BIT 16-22 THAT REFERS TO THE */
3140 /* FIRST CONTAINER IN A LIST OF USED RIGHT CONTAINERS IN THE PAGE. */
3141 /* ZPOS_EMPTY_LIST CONTAINS A NEXT POINTER IN BIT 23-29 THAT REFERS TO THE */
3142 /* FIRST CONTAINER IN A LIST OF USED LEFT CONTAINERS IN THE PAGE. */
3143 /* EACH CONTAINER IN THE LIST CONTAINS A NEXT POINTER IN BIT 11-17 AND IT */
3144 /* CONTAINS A PREVIOUS POINTER IN BIT 18-24. */
3145 /* --------------------------------------------------------------------------------- */
3146 if (tslUpdateHeader == ZTRUE) {
3147 jam();
3148 tslNextfree = (slPageptr.p->word32[ZPOS_EMPTY_LIST] >> 16) & 0x7f;
3149 tsrlNewHead = ZCON_HEAD_SIZE;
3150 tsrlNewHead = ((tsrlNewHead << 8) + ZEMPTYLIST) + (1 << 7);
3151 tsrlNewHead = (tsrlNewHead << 7) + tslNextfree;
3152 tsrlNewHead = tsrlNewHead << 11;
3153 dbgWord32(slPageptr, tsrlHeadIndex, tsrlNewHead);
3154 slPageptr.p->word32[tsrlHeadIndex] = tsrlNewHead;
3155 tsrlTmp = slPageptr.p->word32[ZPOS_EMPTY_LIST] & 0xff80ffff;
3156 dbgWord32(slPageptr, ZPOS_EMPTY_LIST, tsrlTmp | (tslPageindex << 16));
3157 slPageptr.p->word32[ZPOS_EMPTY_LIST] = tsrlTmp | (tslPageindex << 16);
3158 if (tslNextfree < ZEMPTYLIST) {
3159 jam();
3160 tsrlTmp = ((tslNextfree << ZSHIFT_PLUS) - (tslNextfree << ZSHIFT_MINUS)) + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
3161 tsrlTmp1 = slPageptr.p->word32[tsrlTmp] & 0xfe03ffff;
3162 dbgWord32(slPageptr, tsrlTmp, tsrlTmp1 | (tslPageindex << 18));
3163 slPageptr.p->word32[tsrlTmp] = tsrlTmp1 | (tslPageindex << 18);
3164 } else {
3165 ndbrequire(tslNextfree == ZEMPTYLIST);
3166 jam();
3167 }//if
3168 }//if
3169 ilcPageptr.p = slPageptr.p;
3170 increaselistcont(signal);
3171 }//Dbacc::seizeRightlist()
3172
3173 /* --------------------------------------------------------------------------------- */
3174 /* --------------------------------------------------------------------------------- */
3175 /* --------------------------------------------------------------------------------- */
3176 /* */
3177 /* END OF INSERT_ELEMENT MODULE */
3178 /* */
3179 /* --------------------------------------------------------------------------------- */
3180 /* --------------------------------------------------------------------------------- */
3181 /* --------------------------------------------------------------------------------- */
3182 /* --------------------------------------------------------------------------------- */
3183 /* --------------------------------------------------------------------------------- */
3184 /* */
3185 /* MODULE: GET_ELEMENT */
3186 /* THE FOLLOWING SUBROUTINES ARE ONLY USED BY GET_ELEMENT AND */
3187 /* GETDIRINDEX. THIS ROUTINE IS THE SOLE INTERFACE TO GET ELEMENTS */
3188 /* FROM THE INDEX. CURRENT USERS ARE ALL REQUESTS AND EXECUTE UNDO LOG */
3189 /* */
3190 /* THE FOLLOWING SUBROUTINES ARE INCLUDED IN THIS MODULE: */
3191 /* GET_ELEMENT */
3192 /* GET_DIRINDEX */
3193 /* SEARCH_LONG_KEY */
3194 /* */
3195 /* THESE ROUTINES ARE ONLY USED BY THIS MODULE AND BY NO ONE ELSE. */
3196 /* ALSO THE ROUTINES MAKE NO USE OF ROUTINES IN OTHER MODULES. */
3197 /* THE ONLY SHORT-LIVED VARIABLES USED IN OTHER PARTS OF THE BLOCK ARE */
3198 /* THOSE DEFINED AS INPUT AND OUTPUT IN GET_ELEMENT AND GETDIRINDEX */
3199 /* SHORT-LIVED VARIABLES INCLUDE TEMPORARY VARIABLES, COMMON VARIABLES */
3200 /* AND POINTER VARIABLES. */
3201 /* THE ONLY EXCEPTION TO THIS RULE IS FRAGRECPTR WHICH POINTS TO THE */
3202 /* FRAGMENT RECORD. THIS IS MORE LESS STATIC ALWAYS DURING A SIGNAL */
3203 /* EXECUTION. */
3204 /* */
3205 /* --------------------------------------------------------------------------------- */
3206 /* --------------------------------------------------------------------------------- */
3207 /* --------------------------------------------------------------------------------- */
3208 /* GETDIRINDEX */
3209 /* SUPPORT ROUTINE FOR INSERT ELEMENT, GET ELEMENT AND COMMITDELETE */
3210 /* INPUT:FRAGRECPTR ( POINTER TO THE ACTIVE FRAGMENT REC) */
3211 /* OPERATION_REC_PTR (POINTER TO THE OPERATION REC). */
3212 /* */
3213 /* OUTPUT:GDI_PAGEPTR ( POINTER TO THE PAGE OF THE ELEMENT) */
3214 /* TGDI_PAGEINDEX ( INDEX OF THE ELEMENT IN THE PAGE). */
3215 /* */
3216 /* DESCRIPTION: CHECK THE HASH VALUE OF THE OPERATION REC AND CALCULATE THE */
3217 /* THE ADDRESS OF THE ELEMENT IN THE HASH TABLE,(GDI_PAGEPTR, */
3218 /* TGDI_PAGEINDEX) ACCORDING TO LH3. */
3219 /* --------------------------------------------------------------------------------- */
getdirindex(Signal * signal)3220 void Dbacc::getdirindex(Signal* signal)
3221 {
3222 DirRangePtr gdiDirRangePtr;
3223 DirectoryarrayPtr gdiDirptr;
3224 Uint32 tgdiTmp;
3225 Uint32 tgdiAddress;
3226
3227 tgdiTmp = fragrecptr.p->k + fragrecptr.p->lhfragbits; /* OBS K = 6 */
3228 tgdiPageindex = operationRecPtr.p->hashValue & ((1 << fragrecptr.p->k) - 1);
3229 tgdiTmp = operationRecPtr.p->hashValue >> tgdiTmp;
3230 tgdiTmp = (tgdiTmp << fragrecptr.p->k) | tgdiPageindex;
3231 tgdiAddress = tgdiTmp & fragrecptr.p->maxp;
3232 gdiDirRangePtr.i = fragrecptr.p->directory;
3233 ptrCheckGuard(gdiDirRangePtr, cdirrangesize, dirRange);
3234 if (tgdiAddress < fragrecptr.p->p) {
3235 jam();
3236 tgdiAddress = tgdiTmp & ((fragrecptr.p->maxp << 1) | 1);
3237 }//if
3238 tgdiTmp = tgdiAddress >> fragrecptr.p->k;
3239 arrGuard((tgdiTmp >> 8), 256);
3240 gdiDirptr.i = gdiDirRangePtr.p->dirArray[tgdiTmp >> 8];
3241 ptrCheckGuard(gdiDirptr, cdirarraysize, directoryarray);
3242 gdiPageptr.i = gdiDirptr.p->pagep[tgdiTmp & 0xff]; /* DIRECTORY INDEX OF SEND BUCKET PAGE */
3243 ptrCheckGuard(gdiPageptr, cpagesize, page8);
3244 }//Dbacc::getdirindex()
3245
3246 Uint32
readTablePk(Uint32 localkey1,Uint32 localkey2,Uint32 eh,Ptr<Operationrec> opPtr)3247 Dbacc::readTablePk(Uint32 localkey1, Uint32 localkey2,
3248 Uint32 eh, Ptr<Operationrec> opPtr)
3249 {
3250 int ret;
3251 Uint32 tableId = fragrecptr.p->myTableId;
3252 Uint32 fragId = fragrecptr.p->myfid;
3253 bool xfrm = fragrecptr.p->hasCharAttr;
3254
3255 #ifdef VM_TRACE
3256 memset(ckeys, 0x1f, (fragrecptr.p->keyLength * MAX_XFRM_MULTIPLY) << 2);
3257 #endif
3258
3259 if (likely(! Local_key::isInvalid(localkey1, localkey2)))
3260 {
3261 ret = c_tup->accReadPk(tableId, fragId, localkey1, localkey2,
3262 ckeys, true);
3263 }
3264 else
3265 {
3266 ndbrequire(ElementHeader::getLocked(eh));
3267 if (unlikely((opPtr.p->m_op_bits & Operationrec::OP_MASK) == ZSCAN_OP))
3268 {
3269 dump_lock_queue(opPtr);
3270 ndbrequire(opPtr.p->nextParallelQue == RNIL);
3271 ndbrequire(opPtr.p->m_op_bits & Operationrec::OP_ELEMENT_DISAPPEARED);
3272 ndbrequire(opPtr.p->m_op_bits & Operationrec::OP_COMMIT_DELETE_CHECK);
3273 ndbrequire((opPtr.p->m_op_bits & Operationrec::OP_STATE_MASK) == Operationrec::OP_STATE_RUNNING);
3274 return 0;
3275 }
3276 ret = c_lqh->readPrimaryKeys(opPtr.p->userptr, ckeys, xfrm);
3277 }
3278 jamEntry();
3279 ndbrequire(ret >= 0);
3280 return ret;
3281 }
3282
3283 /* --------------------------------------------------------------------------------- */
3284 /* GET_ELEMENT */
3285 /* INPUT: */
3286 /* OPERATION_REC_PTR */
3287 /* FRAGRECPTR */
3288 /* OUTPUT: */
3289 /* TGE_RESULT RESULT SUCCESS = ZTRUE OTHERWISE ZFALSE */
3290 /* TGE_LOCKED LOCK INFORMATION IF SUCCESSFUL RESULT */
3291 /* GE_PAGEPTR PAGE POINTER OF FOUND ELEMENT */
3292 /* TGE_CONTAINERPTR CONTAINER INDEX OF FOUND ELEMENT */
3293 /* TGE_ELEMENTPTR ELEMENT INDEX OF FOUND ELEMENT */
3294 /* TGE_FORWARD DIRECTION OF CONTAINER WHERE ELEMENT FOUND */
3295 /* */
3296 /* DESCRIPTION: THE SUBROUTIN GOES THROUGH ALL CONTAINERS OF THE ACTIVE */
3297 /* BUCKET, AND SERCH FOR ELEMENT.THE PRIMARY KEYS WHICH IS SAVED */
3298 /* IN THE OPERATION REC ARE THE CHECK ITEMS IN THE SEARCHING. */
3299 /* --------------------------------------------------------------------------------- */
3300
3301 #if __ia64 == 1
3302 #if __INTEL_COMPILER == 810
3303 int ndb_acc_ia64_icc810_dummy_var = 0;
ndb_acc_ia64_icc810_dummy_func()3304 void ndb_acc_ia64_icc810_dummy_func()
3305 {
3306 ndb_acc_ia64_icc810_dummy_var++;
3307 }
3308 #endif
3309 #endif
3310
3311 Uint32
getElement(Signal * signal,OperationrecPtr & lockOwnerPtr)3312 Dbacc::getElement(Signal* signal, OperationrecPtr& lockOwnerPtr)
3313 {
3314 Uint32 errcode;
3315 DirRangePtr geOverflowrangeptr;
3316 DirectoryarrayPtr geOverflowDirptr;
3317 Uint32 tgeElementHeader;
3318 Uint32 tgeElemStep;
3319 Uint32 tgeContainerhead;
3320 Uint32 tgePageindex;
3321 Uint32 tgeActivePageDir;
3322 Uint32 tgeNextptrtype;
3323 register Uint32 tgeKeyptr;
3324 register Uint32 tgeRemLen;
3325 register Uint32 TelemLen = fragrecptr.p->elementLength;
3326 register Uint32* Tkeydata = (Uint32*)&signal->theData[7];
3327 const Uint32 localkeylen = fragrecptr.p->localkeylen;
3328
3329 getdirindex(signal);
3330 tgePageindex = tgdiPageindex;
3331 gePageptr = gdiPageptr;
3332 /*
3333 * The value seached is
3334 * - table key for ACCKEYREQ, stored in TUP
3335 * - local key (1 word) for ACC_LOCKREQ and UNDO, stored in ACC
3336 */
3337 const bool searchLocalKey = operationRecPtr.p->tupkeylen == 0;
3338
3339 ndbrequire(TelemLen == ZELEM_HEAD_SIZE + localkeylen);
3340 tgeNextptrtype = ZLEFT;
3341
3342 const Uint32 tmp = fragrecptr.p->k + fragrecptr.p->lhfragbits;
3343 const Uint32 opHashValuePart = (operationRecPtr.p->hashValue >> tmp) &0xFFFF;
3344 do {
3345 tgeContainerptr = (tgePageindex << ZSHIFT_PLUS) - (tgePageindex << ZSHIFT_MINUS);
3346 if (tgeNextptrtype == ZLEFT) {
3347 jam();
3348 tgeContainerptr = tgeContainerptr + ZHEAD_SIZE;
3349 tgeElementptr = tgeContainerptr + ZCON_HEAD_SIZE;
3350 tgeKeyptr = (tgeElementptr + ZELEM_HEAD_SIZE) + localkeylen;
3351 tgeElemStep = TelemLen;
3352 tgeForward = 1;
3353 if (unlikely(tgeContainerptr >= 2048))
3354 {
3355 errcode = 4;
3356 goto error;
3357 }
3358 tgeRemLen = gePageptr.p->word32[tgeContainerptr] >> 26;
3359 if (unlikely(((tgeContainerptr + tgeRemLen - 1) >= 2048)))
3360 {
3361 errcode = 5;
3362 goto error;
3363 }
3364 } else if (tgeNextptrtype == ZRIGHT) {
3365 jam();
3366 tgeContainerptr = tgeContainerptr + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
3367 tgeElementptr = tgeContainerptr - 1;
3368 tgeKeyptr = (tgeElementptr - ZELEM_HEAD_SIZE) - localkeylen;
3369 tgeElemStep = 0 - TelemLen;
3370 tgeForward = (Uint32)-1;
3371 if (unlikely(tgeContainerptr >= 2048))
3372 {
3373 errcode = 4;
3374 goto error;
3375 }
3376 tgeRemLen = gePageptr.p->word32[tgeContainerptr] >> 26;
3377 if (unlikely((tgeContainerptr - tgeRemLen) >= 2048))
3378 {
3379 errcode = 5;
3380 goto error;
3381 }
3382 } else {
3383 errcode = 6;
3384 goto error;
3385 }//if
3386 if (tgeRemLen >= ZCON_HEAD_SIZE + TelemLen) {
3387 if (unlikely(tgeRemLen > ZBUF_SIZE))
3388 {
3389 errcode = 7;
3390 goto error;
3391 }//if
3392 /* ------------------------------------------------------------------- */
3393 // There is at least one element in this container.
3394 // Check if it is the element searched for.
3395 /* ------------------------------------------------------------------- */
3396 do {
3397 tgeElementHeader = gePageptr.p->word32[tgeElementptr];
3398 tgeRemLen = tgeRemLen - TelemLen;
3399 Uint32 hashValuePart;
3400 Uint32 localkey1, localkey2;
3401 lockOwnerPtr.i = RNIL;
3402 lockOwnerPtr.p = NULL;
3403 if (ElementHeader::getLocked(tgeElementHeader)) {
3404 jam();
3405 lockOwnerPtr.i = ElementHeader::getOpPtrI(tgeElementHeader);
3406 ptrCheckGuard(lockOwnerPtr, coprecsize, operationrec);
3407 hashValuePart = lockOwnerPtr.p->hashvaluePart;
3408 localkey1 = lockOwnerPtr.p->localdata[0];
3409 localkey2 = lockOwnerPtr.p->localdata[1];
3410 } else {
3411 jam();
3412 Uint32 pos = tgeElementptr + tgeForward;
3413 hashValuePart = ElementHeader::getHashValuePart(tgeElementHeader);
3414 localkey1 = gePageptr.p->word32[pos];
3415 if (likely(localkeylen == 1))
3416 {
3417 localkey2 = Local_key::ref2page_idx(localkey1);
3418 localkey1 = Local_key::ref2page_id(localkey1);
3419 }
3420 else
3421 {
3422 localkey2 = gePageptr.p->word32[pos + tgeForward];
3423 }
3424 }
3425 if (hashValuePart == opHashValuePart) {
3426 jam();
3427 bool found;
3428 if (! searchLocalKey)
3429 {
3430 Uint32 len = readTablePk(localkey1, localkey2, tgeElementHeader,
3431 lockOwnerPtr);
3432 found = (len == operationRecPtr.p->xfrmtupkeylen) &&
3433 (memcmp(Tkeydata, ckeys, len << 2) == 0);
3434 } else {
3435 jam();
3436 found = (localkey1 == Tkeydata[0] && localkey2 == Tkeydata[1]);
3437 }
3438 if (found)
3439 {
3440 jam();
3441 operationRecPtr.p->localdata[0] = localkey1;
3442 operationRecPtr.p->localdata[1] = localkey2;
3443 return ZTRUE;
3444 }
3445 }
3446 if (tgeRemLen <= ZCON_HEAD_SIZE) {
3447 break;
3448 }
3449 tgeElementptr = tgeElementptr + tgeElemStep;
3450 } while (true);
3451 }//if
3452 if (unlikely(tgeRemLen != ZCON_HEAD_SIZE))
3453 {
3454 errcode = 8;
3455 goto error;
3456 }//if
3457 tgeContainerhead = gePageptr.p->word32[tgeContainerptr];
3458 tgeNextptrtype = (tgeContainerhead >> 7) & 0x3;
3459 if (tgeNextptrtype == 0) {
3460 jam();
3461 return ZFALSE; /* NO MORE CONTAINER */
3462 }//if
3463 tgePageindex = tgeContainerhead & 0x7f; /* NEXT CONTAINER PAGE INDEX 7 BITS */
3464 if (unlikely(tgePageindex > ZEMPTYLIST))
3465 {
3466 errcode = 9;
3467 goto error;
3468 }//if
3469 if (((tgeContainerhead >> 9) & 1) == ZFALSE) {
3470 jam();
3471 tgeActivePageDir = gePageptr.p->word32[tgeContainerptr + 1]; /* NEXT PAGE ID */
3472 geOverflowrangeptr.i = fragrecptr.p->overflowdir;
3473 ptrCheckGuard(geOverflowrangeptr, cdirrangesize, dirRange);
3474 arrGuard((tgeActivePageDir >> 8), 256);
3475 geOverflowDirptr.i = geOverflowrangeptr.p->dirArray[tgeActivePageDir >> 8];
3476 ptrCheckGuard(geOverflowDirptr, cdirarraysize, directoryarray);
3477 gePageptr.i = geOverflowDirptr.p->pagep[tgeActivePageDir & 0xff];
3478 ptrCheckGuard(gePageptr, cpagesize, page8);
3479 }//if
3480 } while (1);
3481
3482 return ZFALSE;
3483
3484 error:
3485 ACCKEY_error(errcode);
3486 return ~0;
3487 }//Dbacc::getElement()
3488
3489 /* ------------------------------------------------------------------------- */
3490 /* ------------------------------------------------------------------------- */
3491 /* ------------------------------------------------------------------------- */
3492 /* */
3493 /* END OF GET_ELEMENT MODULE */
3494 /* */
3495 /* ------------------------------------------------------------------------- */
3496 /* ------------------------------------------------------------------------- */
3497 /* ------------------------------------------------------------------------- */
3498 /* ------------------------------------------------------------------------- */
3499 /* ------------------------------------------------------------------------- */
3500 /* */
3501 /* MODULE: DELETE */
3502 /* */
3503 /* ------------------------------------------------------------------------- */
3504 /* ------------------------------------------------------------------------- */
3505 /* ------------------------------------------------------------------------- */
3506 /* COMMITDELETE */
3507 /* INPUT: OPERATION_REC_PTR, PTR TO AN OPERATION RECORD. */
3508 /* FRAGRECPTR, PTR TO A FRAGMENT RECORD */
3509 /* */
3510 /* OUTPUT: */
3511 /* NONE */
3512 /* DESCRIPTION: DELETE OPERATIONS WILL BE COMPLETED AT THE
3513 * COMMIT OF TRANSACTION. THIS SUBROUTINE SEARCHS FOR ELEMENT AND
3514 * DELETES IT. IT DOES SO BY REPLACING IT WITH THE LAST
3515 * ELEMENT IN THE BUCKET. IF THE DELETED ELEMENT IS ALSO THE LAST
3516 * ELEMENT THEN IT IS ONLY NECESSARY TO REMOVE THE ELEMENT
3517 * ------------------------------------------------------------------------- */
3518 void
report_dealloc(Signal * signal,const Operationrec * opPtrP)3519 Dbacc::report_dealloc(Signal* signal, const Operationrec* opPtrP)
3520 {
3521 Uint32 localKey1 = opPtrP->localdata[0];
3522 Uint32 localKey2 = opPtrP->localdata[1];
3523 Uint32 opbits = opPtrP->m_op_bits;
3524 Uint32 userptr= opPtrP->userptr;
3525 Uint32 scanInd =
3526 ((opbits & Operationrec::OP_MASK) == ZSCAN_OP) ||
3527 (opbits & Operationrec::OP_LOCK_REQ);
3528
3529 if (! Local_key::isInvalid(localKey1, localKey2))
3530 {
3531 signal->theData[0] = fragrecptr.p->myfid;
3532 signal->theData[1] = fragrecptr.p->myTableId;
3533 signal->theData[2] = localKey1;
3534 signal->theData[3] = localKey2;
3535 signal->theData[4] = userptr;
3536 signal->theData[5] = scanInd;
3537 EXECUTE_DIRECT(DBLQH, GSN_TUP_DEALLOCREQ, signal, 6);
3538 jamEntry();
3539 }
3540 }
3541
commitdelete(Signal * signal)3542 void Dbacc::commitdelete(Signal* signal)
3543 {
3544 jam();
3545 report_dealloc(signal, operationRecPtr.p);
3546
3547 getdirindex(signal);
3548 tlastPageindex = tgdiPageindex;
3549 lastPageptr.i = gdiPageptr.i;
3550 lastPageptr.p = gdiPageptr.p;
3551 tlastForward = ZTRUE;
3552 tlastContainerptr = (tlastPageindex << ZSHIFT_PLUS) - (tlastPageindex << ZSHIFT_MINUS);
3553 tlastContainerptr = tlastContainerptr + ZHEAD_SIZE;
3554 arrGuard(tlastContainerptr, 2048);
3555 tlastContainerhead = lastPageptr.p->word32[tlastContainerptr];
3556 tlastContainerlen = tlastContainerhead >> 26;
3557 lastPrevpageptr.i = RNIL;
3558 ptrNull(lastPrevpageptr);
3559 tlastPrevconptr = 0;
3560 getLastAndRemove(signal);
3561
3562 delPageptr.i = operationRecPtr.p->elementPage;
3563 ptrCheckGuard(delPageptr, cpagesize, page8);
3564 tdelElementptr = operationRecPtr.p->elementPointer;
3565 /* --------------------------------------------------------------------------------- */
3566 // Here we have to take extreme care since we do not want locks to end up after the
3567 // log execution. Thus it is necessary to put back the element in unlocked shape.
3568 // We thus update the element header to ensure we log an unlocked element. We do not
3569 // need to restore it later since it is deleted immediately anyway.
3570 /* --------------------------------------------------------------------------------- */
3571 const Uint32 hv = operationRecPtr.p->hashvaluePart;
3572 const Uint32 eh = ElementHeader::setUnlocked(hv, 0);
3573 delPageptr.p->word32[tdelElementptr] = eh;
3574 if (operationRecPtr.p->elementPage == lastPageptr.i) {
3575 if (operationRecPtr.p->elementPointer == tlastElementptr) {
3576 jam();
3577 /* --------------------------------------------------------------------------------- */
3578 /* THE LAST ELEMENT WAS THE ELEMENT TO BE DELETED. WE NEED NOT COPY IT. */
3579 /* --------------------------------------------------------------------------------- */
3580 return;
3581 }//if
3582 }//if
3583 /* --------------------------------------------------------------------------------- */
3584 /* THE DELETED ELEMENT IS NOT THE LAST. WE READ THE LAST ELEMENT AND OVERWRITE THE */
3585 /* DELETED ELEMENT. */
3586 /* --------------------------------------------------------------------------------- */
3587 tdelContainerptr = operationRecPtr.p->elementContainer;
3588 tdelForward = operationRecPtr.p->elementIsforward;
3589 deleteElement(signal);
3590 }//Dbacc::commitdelete()
3591
3592 /* --------------------------------------------------------------------------------- */
3593 /* DELETE_ELEMENT */
3594 /* INPUT: FRAGRECPTR, POINTER TO A FRAGMENT RECORD */
3595 /* LAST_PAGEPTR, POINTER TO THE PAGE OF THE LAST ELEMENT */
3596 /* DEL_PAGEPTR, POINTER TO THE PAGE OF THE DELETED ELEMENT */
3597 /* TLAST_ELEMENTPTR, ELEMENT POINTER OF THE LAST ELEMENT */
3598 /* TDEL_ELEMENTPTR, ELEMENT POINTER OF THE DELETED ELEMENT */
3599 /* TLAST_FORWARD, DIRECTION OF LAST ELEMENT */
3600 /* TDEL_FORWARD, DIRECTION OF DELETED ELEMENT */
3601 /* TDEL_CONTAINERPTR, CONTAINER POINTER OF DELETED ELEMENT */
3602 /* DESCRIPTION: COPY LAST ELEMENT TO DELETED ELEMENT AND UPDATE UNDO LOG AND */
3603 /* UPDATE ANY ACTIVE OPERATION ON THE MOVED ELEMENT. */
3604 /* --------------------------------------------------------------------------------- */
deleteElement(Signal * signal)3605 void Dbacc::deleteElement(Signal* signal)
3606 {
3607 OperationrecPtr deOperationRecPtr;
3608 Uint32 tdeIndex;
3609 Uint32 tlastMoveElemptr;
3610 Uint32 tdelMoveElemptr;
3611 Uint32 guard31;
3612
3613 if (tlastElementptr >= 2048)
3614 goto deleteElement_index_error1;
3615 {
3616 const Uint32 tdeElemhead = lastPageptr.p->word32[tlastElementptr];
3617 tlastMoveElemptr = tlastElementptr;
3618 tdelMoveElemptr = tdelElementptr;
3619 guard31 = fragrecptr.p->elementLength - 1;
3620 for (tdeIndex = 0; tdeIndex <= guard31; tdeIndex++) {
3621 dbgWord32(delPageptr, tdelMoveElemptr, lastPageptr.p->word32[tlastMoveElemptr]);
3622 if ((tlastMoveElemptr >= 2048) ||
3623 (tdelMoveElemptr >= 2048))
3624 goto deleteElement_index_error2;
3625 delPageptr.p->word32[tdelMoveElemptr] = lastPageptr.p->word32[tlastMoveElemptr];
3626 tdelMoveElemptr = tdelMoveElemptr + tdelForward;
3627 tlastMoveElemptr = tlastMoveElemptr + tlastForward;
3628 }//for
3629 if (ElementHeader::getLocked(tdeElemhead)) {
3630 /* --------------------------------------------------------------------------------- */
3631 /* THE LAST ELEMENT IS LOCKED AND IS THUS REFERENCED BY AN OPERATION RECORD. WE NEED */
3632 /* TO UPDATE THE OPERATION RECORD WITH THE NEW REFERENCE TO THE ELEMENT. */
3633 /* --------------------------------------------------------------------------------- */
3634 deOperationRecPtr.i = ElementHeader::getOpPtrI(tdeElemhead);
3635 ptrCheckGuard(deOperationRecPtr, coprecsize, operationrec);
3636 deOperationRecPtr.p->elementPage = delPageptr.i;
3637 deOperationRecPtr.p->elementContainer = tdelContainerptr;
3638 deOperationRecPtr.p->elementPointer = tdelElementptr;
3639 deOperationRecPtr.p->elementIsforward = tdelForward;
3640 /* --------------------------------------------------------------------------------- */
3641 // We need to take extreme care to not install locked records after system restart.
3642 // An undo of the delete will reinstall the moved record. We have to ensure that the
3643 // lock is removed to ensure that no such thing happen.
3644 /* --------------------------------------------------------------------------------- */
3645 Uint32 eh = ElementHeader::setUnlocked(deOperationRecPtr.p->hashvaluePart,
3646 0);
3647 lastPageptr.p->word32[tlastElementptr] = eh;
3648 }//if
3649 return;
3650 }
3651
3652 deleteElement_index_error1:
3653 arrGuard(tlastElementptr, 2048);
3654 return;
3655
3656 deleteElement_index_error2:
3657 arrGuard(tdelMoveElemptr + guard31, 2048);
3658 arrGuard(tlastMoveElemptr, 2048);
3659 return;
3660
3661 }//Dbacc::deleteElement()
3662
3663 /* --------------------------------------------------------------------------------- */
3664 /* GET_LAST_AND_REMOVE */
3665 /* INPUT: */
3666 /* LAST_PAGEPTR PAGE POINTER OF FIRST CONTAINER IN SEARCH OF LAST*/
3667 /* TLAST_CONTAINERPTR CONTAINER INDEX OF THE SAME */
3668 /* TLAST_CONTAINERHEAD CONTAINER HEADER OF THE SAME */
3669 /* TLAST_PAGEINDEX PAGE INDEX OF THE SAME */
3670 /* TLAST_FORWARD CONTAINER DIRECTION OF THE SAME */
3671 /* TLAST_CONTAINERLEN CONTAINER LENGTH OF THE SAME */
3672 /* LAST_PREVPAGEPTR PAGE POINTER OF PREVIOUS CONTAINER OF THE SAME */
3673 /* TLAST_PREVCONPTR CONTAINER INDEX OF PREVIOUS CONTAINER OF THE SAME*/
3674 /* */
3675 /* OUTPUT: */
3676 /* ALL VARIABLES FROM INPUT BUT NOW CONTAINING INFO ABOUT LAST */
3677 /* CONTAINER. */
3678 /* TLAST_ELEMENTPTR LAST ELEMENT POINTER IN LAST CONTAINER */
3679 /* --------------------------------------------------------------------------------- */
getLastAndRemove(Signal * signal)3680 void Dbacc::getLastAndRemove(Signal* signal)
3681 {
3682 DirRangePtr glrOverflowrangeptr;
3683 DirectoryarrayPtr glrOverflowDirptr;
3684 Uint32 tglrHead;
3685 Uint32 tglrTmp;
3686
3687 GLR_LOOP_10:
3688 if (((tlastContainerhead >> 7) & 0x3) != 0) {
3689 jam();
3690 lastPrevpageptr.i = lastPageptr.i;
3691 lastPrevpageptr.p = lastPageptr.p;
3692 tlastPrevconptr = tlastContainerptr;
3693 tlastPageindex = tlastContainerhead & 0x7f;
3694 if (((tlastContainerhead >> 9) & 0x1) == ZFALSE) {
3695 jam();
3696 arrGuard(tlastContainerptr + 1, 2048);
3697 tglrTmp = lastPageptr.p->word32[tlastContainerptr + 1];
3698 glrOverflowrangeptr.i = fragrecptr.p->overflowdir;
3699 ptrCheckGuard(glrOverflowrangeptr, cdirrangesize, dirRange);
3700 arrGuard((tglrTmp >> 8), 256);
3701 glrOverflowDirptr.i = glrOverflowrangeptr.p->dirArray[tglrTmp >> 8];
3702 ptrCheckGuard(glrOverflowDirptr, cdirarraysize, directoryarray);
3703 lastPageptr.i = glrOverflowDirptr.p->pagep[tglrTmp & 0xff];
3704 ptrCheckGuard(lastPageptr, cpagesize, page8);
3705 }//if
3706 tlastContainerptr = (tlastPageindex << ZSHIFT_PLUS) - (tlastPageindex << ZSHIFT_MINUS);
3707 if (((tlastContainerhead >> 7) & 3) == ZLEFT) {
3708 jam();
3709 tlastForward = ZTRUE;
3710 tlastContainerptr = tlastContainerptr + ZHEAD_SIZE;
3711 } else if (((tlastContainerhead >> 7) & 3) == ZRIGHT) {
3712 jam();
3713 tlastForward = cminusOne;
3714 tlastContainerptr = ((tlastContainerptr + ZHEAD_SIZE) + ZBUF_SIZE) - ZCON_HEAD_SIZE;
3715 } else {
3716 ndbrequire(false);
3717 return;
3718 }//if
3719 arrGuard(tlastContainerptr, 2048);
3720 tlastContainerhead = lastPageptr.p->word32[tlastContainerptr];
3721 tlastContainerlen = tlastContainerhead >> 26;
3722 ndbrequire(tlastContainerlen >= ((Uint32)ZCON_HEAD_SIZE + fragrecptr.p->elementLength));
3723 goto GLR_LOOP_10;
3724 }//if
3725 tlastContainerlen = tlastContainerlen - fragrecptr.p->elementLength;
3726 if (tlastForward == ZTRUE) {
3727 jam();
3728 tlastElementptr = tlastContainerptr + tlastContainerlen;
3729 } else {
3730 jam();
3731 tlastElementptr = (tlastContainerptr + (ZCON_HEAD_SIZE - 1)) - tlastContainerlen;
3732 }//if
3733 rlPageptr.i = lastPageptr.i;
3734 rlPageptr.p = lastPageptr.p;
3735 trlPageindex = tlastPageindex;
3736 if (((tlastContainerhead >> 10) & 1) == 1) {
3737 /* --------------------------------------------------------------------------------- */
3738 /* WE HAVE OWNERSHIP OF BOTH PARTS OF THE CONTAINER ENDS. */
3739 /* --------------------------------------------------------------------------------- */
3740 if (tlastContainerlen < ZDOWN_LIMIT) {
3741 /* --------------------------------------------------------------------------------- */
3742 /* WE HAVE DECREASED THE SIZE BELOW THE DOWN LIMIT, WE MUST GIVE UP THE OTHER */
3743 /* SIDE OF THE BUFFER. */
3744 /* --------------------------------------------------------------------------------- */
3745 tlastContainerhead = tlastContainerhead ^ (1 << 10);
3746 trlRelCon = ZFALSE;
3747 if (tlastForward == ZTRUE) {
3748 jam();
3749 turlIndex = tlastContainerptr + (ZBUF_SIZE - ZCON_HEAD_SIZE);
3750 releaseRightlist(signal);
3751 } else {
3752 jam();
3753 tullIndex = tlastContainerptr - (ZBUF_SIZE - ZCON_HEAD_SIZE);
3754 releaseLeftlist(signal);
3755 }//if
3756 }//if
3757 }//if
3758 if (tlastContainerlen <= 2) {
3759 ndbrequire(tlastContainerlen == 2);
3760 if (lastPrevpageptr.i != RNIL) {
3761 jam();
3762 /* --------------------------------------------------------------------------------- */
3763 /* THE LAST CONTAINER IS EMPTY AND IS NOT THE FIRST CONTAINER WHICH IS NOT REMOVED. */
3764 /* DELETE THE LAST CONTAINER AND UPDATE THE PREVIOUS CONTAINER. ALSO PUT THIS */
3765 /* CONTAINER IN FREE CONTAINER LIST OF THE PAGE. */
3766 /* --------------------------------------------------------------------------------- */
3767 ndbrequire(tlastPrevconptr < 2048);
3768 tglrTmp = lastPrevpageptr.p->word32[tlastPrevconptr] >> 9;
3769 dbgWord32(lastPrevpageptr, tlastPrevconptr, tglrTmp << 9);
3770 lastPrevpageptr.p->word32[tlastPrevconptr] = tglrTmp << 9;
3771 trlRelCon = ZTRUE;
3772 if (tlastForward == ZTRUE) {
3773 jam();
3774 tullIndex = tlastContainerptr;
3775 releaseLeftlist(signal);
3776 } else {
3777 jam();
3778 turlIndex = tlastContainerptr;
3779 releaseRightlist(signal);
3780 }//if
3781 return;
3782 }//if
3783 }//if
3784 tglrHead = tlastContainerhead << 6;
3785 tglrHead = tglrHead >> 6;
3786 tglrHead = tglrHead | (tlastContainerlen << 26);
3787 dbgWord32(lastPageptr, tlastContainerptr, tglrHead);
3788 arrGuard(tlastContainerptr, 2048);
3789 lastPageptr.p->word32[tlastContainerptr] = tglrHead;
3790 }//Dbacc::getLastAndRemove()
3791
3792 /* --------------------------------------------------------------------------------- */
3793 /* RELEASE_LEFTLIST */
3794 /* INPUT: */
3795 /* RL_PAGEPTR PAGE POINTER OF CONTAINER TO BE RELEASED */
3796 /* TRL_PAGEINDEX PAGE INDEX OF CONTAINER TO BE RELEASED */
3797 /* TURL_INDEX INDEX OF CONTAINER TO BE RELEASED */
3798 /* TRL_REL_CON TRUE IF CONTAINER RELEASED OTHERWISE ONLY */
3799 /* A PART IS RELEASED. */
3800 /* */
3801 /* OUTPUT: */
3802 /* NONE */
3803 /* */
3804 /* THE FREE LIST OF LEFT FREE BUFFER IN THE PAGE WILL BE UPDATE */
3805 /* TULL_INDEX IS INDEX TO THE FIRST WORD IN THE LEFT SIDE OF THE BUFFER */
3806 /* --------------------------------------------------------------------------------- */
releaseLeftlist(Signal * signal)3807 void Dbacc::releaseLeftlist(Signal* signal)
3808 {
3809 Uint32 tullTmp;
3810 Uint32 tullTmp1;
3811
3812 /* --------------------------------------------------------------------------------- */
3813 /* IF A CONTAINER IS RELEASED AND NOT ONLY A PART THEN WE HAVE TO REMOVE IT */
3814 /* FROM THE LIST OF USED CONTAINERS IN THE PAGE. THIS IN ORDER TO ENSURE THAT */
3815 /* WE CAN FIND ALL LOCKED ELEMENTS DURING LOCAL CHECKPOINT. */
3816 /* --------------------------------------------------------------------------------- */
3817 if (trlRelCon == ZTRUE) {
3818 arrGuard(tullIndex, 2048);
3819 trlHead = rlPageptr.p->word32[tullIndex];
3820 trlNextused = (trlHead >> 11) & 0x7f;
3821 trlPrevused = (trlHead >> 18) & 0x7f;
3822 if (trlNextused < ZEMPTYLIST) {
3823 jam();
3824 tullTmp1 = (trlNextused << ZSHIFT_PLUS) - (trlNextused << ZSHIFT_MINUS);
3825 tullTmp1 = tullTmp1 + ZHEAD_SIZE;
3826 tullTmp = rlPageptr.p->word32[tullTmp1] & 0xfe03ffff;
3827 dbgWord32(rlPageptr, tullTmp1, tullTmp | (trlPrevused << 18));
3828 rlPageptr.p->word32[tullTmp1] = tullTmp | (trlPrevused << 18);
3829 } else {
3830 ndbrequire(trlNextused == ZEMPTYLIST);
3831 jam();
3832 }//if
3833 if (trlPrevused < ZEMPTYLIST) {
3834 jam();
3835 tullTmp1 = (trlPrevused << ZSHIFT_PLUS) - (trlPrevused << ZSHIFT_MINUS);
3836 tullTmp1 = tullTmp1 + ZHEAD_SIZE;
3837 tullTmp = rlPageptr.p->word32[tullTmp1] & 0xfffc07ff;
3838 dbgWord32(rlPageptr, tullTmp1, tullTmp | (trlNextused << 11));
3839 rlPageptr.p->word32[tullTmp1] = tullTmp | (trlNextused << 11);
3840 } else {
3841 ndbrequire(trlPrevused == ZEMPTYLIST);
3842 jam();
3843 /* --------------------------------------------------------------------------------- */
3844 /* WE ARE FIRST IN THE LIST AND THUS WE NEED TO UPDATE THE FIRST POINTER. */
3845 /* --------------------------------------------------------------------------------- */
3846 tullTmp = rlPageptr.p->word32[ZPOS_EMPTY_LIST] & 0xc07fffff;
3847 dbgWord32(rlPageptr, ZPOS_EMPTY_LIST, tullTmp | (trlNextused << 23));
3848 rlPageptr.p->word32[ZPOS_EMPTY_LIST] = tullTmp | (trlNextused << 23);
3849 }//if
3850 }//if
3851 dbgWord32(rlPageptr, tullIndex + 1, ZEMPTYLIST);
3852 arrGuard(tullIndex + 1, 2048);
3853 rlPageptr.p->word32[tullIndex + 1] = ZEMPTYLIST;
3854 tullTmp1 = (rlPageptr.p->word32[ZPOS_EMPTY_LIST] >> 7) & 0x7f;
3855 dbgWord32(rlPageptr, tullIndex, tullTmp1);
3856 arrGuard(tullIndex, 2048);
3857 rlPageptr.p->word32[tullIndex] = tullTmp1;
3858 if (tullTmp1 < ZEMPTYLIST) {
3859 jam();
3860 tullTmp1 = (tullTmp1 << ZSHIFT_PLUS) - (tullTmp1 << ZSHIFT_MINUS);
3861 tullTmp1 = (tullTmp1 + ZHEAD_SIZE) + 1;
3862 dbgWord32(rlPageptr, tullTmp1, trlPageindex);
3863 rlPageptr.p->word32[tullTmp1] = trlPageindex; /* UPDATES PREV POINTER IN THE NEXT FREE */
3864 } else {
3865 ndbrequire(tullTmp1 == ZEMPTYLIST);
3866 }//if
3867 tullTmp = rlPageptr.p->word32[ZPOS_EMPTY_LIST];
3868 tullTmp = (((tullTmp >> 14) << 14) | (trlPageindex << 7)) | (tullTmp & 0x7f);
3869 dbgWord32(rlPageptr, ZPOS_EMPTY_LIST, tullTmp);
3870 rlPageptr.p->word32[ZPOS_EMPTY_LIST] = tullTmp;
3871 dbgWord32(rlPageptr, ZPOS_ALLOC_CONTAINERS, rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] - 1);
3872 rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] = rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] - 1;
3873 ndbrequire(rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] <= ZNIL);
3874 if (((rlPageptr.p->word32[ZPOS_EMPTY_LIST] >> ZPOS_PAGE_TYPE_BIT) & 3) == 1) {
3875 jam();
3876 colPageptr.i = rlPageptr.i;
3877 colPageptr.p = rlPageptr.p;
3878 ptrCheck(colPageptr, cpagesize, page8);
3879 checkoverfreelist(signal);
3880 }//if
3881 }//Dbacc::releaseLeftlist()
3882
3883 /* --------------------------------------------------------------------------------- */
3884 /* RELEASE_RIGHTLIST */
3885 /* INPUT: */
3886 /* RL_PAGEPTR PAGE POINTER OF CONTAINER TO BE RELEASED */
3887 /* TRL_PAGEINDEX PAGE INDEX OF CONTAINER TO BE RELEASED */
3888 /* TURL_INDEX INDEX OF CONTAINER TO BE RELEASED */
3889 /* TRL_REL_CON TRUE IF CONTAINER RELEASED OTHERWISE ONLY */
3890 /* A PART IS RELEASED. */
3891 /* */
3892 /* OUTPUT: */
3893 /* NONE */
3894 /* */
3895 /* THE FREE LIST OF RIGHT FREE BUFFER IN THE PAGE WILL BE UPDATE. */
3896 /* TURL_INDEX IS INDEX TO THE FIRST WORD IN THE RIGHT SIDE OF */
3897 /* THE BUFFER, WHICH IS THE LAST WORD IN THE BUFFER. */
3898 /* --------------------------------------------------------------------------------- */
releaseRightlist(Signal * signal)3899 void Dbacc::releaseRightlist(Signal* signal)
3900 {
3901 Uint32 turlTmp1;
3902 Uint32 turlTmp;
3903
3904 /* --------------------------------------------------------------------------------- */
3905 /* IF A CONTAINER IS RELEASED AND NOT ONLY A PART THEN WE HAVE TO REMOVE IT */
3906 /* FROM THE LIST OF USED CONTAINERS IN THE PAGE. THIS IN ORDER TO ENSURE THAT */
3907 /* WE CAN FIND ALL LOCKED ELEMENTS DURING LOCAL CHECKPOINT. */
3908 /* --------------------------------------------------------------------------------- */
3909 if (trlRelCon == ZTRUE) {
3910 jam();
3911 arrGuard(turlIndex, 2048);
3912 trlHead = rlPageptr.p->word32[turlIndex];
3913 trlNextused = (trlHead >> 11) & 0x7f;
3914 trlPrevused = (trlHead >> 18) & 0x7f;
3915 if (trlNextused < ZEMPTYLIST) {
3916 jam();
3917 turlTmp1 = (trlNextused << ZSHIFT_PLUS) - (trlNextused << ZSHIFT_MINUS);
3918 turlTmp1 = turlTmp1 + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
3919 turlTmp = rlPageptr.p->word32[turlTmp1] & 0xfe03ffff;
3920 dbgWord32(rlPageptr, turlTmp1, turlTmp | (trlPrevused << 18));
3921 rlPageptr.p->word32[turlTmp1] = turlTmp | (trlPrevused << 18);
3922 } else {
3923 ndbrequire(trlNextused == ZEMPTYLIST);
3924 jam();
3925 }//if
3926 if (trlPrevused < ZEMPTYLIST) {
3927 jam();
3928 turlTmp1 = (trlPrevused << ZSHIFT_PLUS) - (trlPrevused << ZSHIFT_MINUS);
3929 turlTmp1 = turlTmp1 + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
3930 turlTmp = rlPageptr.p->word32[turlTmp1] & 0xfffc07ff;
3931 dbgWord32(rlPageptr, turlTmp1, turlTmp | (trlNextused << 11));
3932 rlPageptr.p->word32[turlTmp1] = turlTmp | (trlNextused << 11);
3933 } else {
3934 ndbrequire(trlPrevused == ZEMPTYLIST);
3935 jam();
3936 /* --------------------------------------------------------------------------------- */
3937 /* WE ARE FIRST IN THE LIST AND THUS WE NEED TO UPDATE THE FIRST POINTER */
3938 /* OF THE RIGHT CONTAINER LIST. */
3939 /* --------------------------------------------------------------------------------- */
3940 turlTmp = rlPageptr.p->word32[ZPOS_EMPTY_LIST] & 0xff80ffff;
3941 dbgWord32(rlPageptr, ZPOS_EMPTY_LIST, turlTmp | (trlNextused << 16));
3942 rlPageptr.p->word32[ZPOS_EMPTY_LIST] = turlTmp | (trlNextused << 16);
3943 }//if
3944 }//if
3945 dbgWord32(rlPageptr, turlIndex + 1, ZEMPTYLIST);
3946 arrGuard(turlIndex + 1, 2048);
3947 rlPageptr.p->word32[turlIndex + 1] = ZEMPTYLIST;
3948 turlTmp1 = rlPageptr.p->word32[ZPOS_EMPTY_LIST] & 0x7f;
3949 dbgWord32(rlPageptr, turlIndex, turlTmp1);
3950 arrGuard(turlIndex, 2048);
3951 rlPageptr.p->word32[turlIndex] = turlTmp1;
3952 if (turlTmp1 < ZEMPTYLIST) {
3953 jam();
3954 turlTmp = (turlTmp1 << ZSHIFT_PLUS) - (turlTmp1 << ZSHIFT_MINUS);
3955 turlTmp = turlTmp + ((ZHEAD_SIZE + ZBUF_SIZE) - (ZCON_HEAD_SIZE - 1));
3956 dbgWord32(rlPageptr, turlTmp, trlPageindex);
3957 rlPageptr.p->word32[turlTmp] = trlPageindex; /* UPDATES PREV POINTER IN THE NEXT FREE */
3958 } else {
3959 ndbrequire(turlTmp1 == ZEMPTYLIST);
3960 }//if
3961 turlTmp = rlPageptr.p->word32[ZPOS_EMPTY_LIST];
3962 dbgWord32(rlPageptr, ZPOS_EMPTY_LIST, ((turlTmp >> 7) << 7) | trlPageindex);
3963 rlPageptr.p->word32[ZPOS_EMPTY_LIST] = ((turlTmp >> 7) << 7) | trlPageindex;
3964 dbgWord32(rlPageptr, ZPOS_ALLOC_CONTAINERS, rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] - 1);
3965 rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] = rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] - 1;
3966 ndbrequire(rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] <= ZNIL);
3967 if (((rlPageptr.p->word32[ZPOS_EMPTY_LIST] >> ZPOS_PAGE_TYPE_BIT) & 3) == 1) {
3968 jam();
3969 colPageptr.i = rlPageptr.i;
3970 colPageptr.p = rlPageptr.p;
3971 checkoverfreelist(signal);
3972 }//if
3973 }//Dbacc::releaseRightlist()
3974
3975 /* --------------------------------------------------------------------------------- */
3976 /* CHECKOVERFREELIST */
3977 /* INPUT: COL_PAGEPTR, POINTER OF AN OVERFLOW PAGE RECORD. */
3978 /* DESCRIPTION: CHECKS IF THE PAGE HAVE TO PUT IN FREE LIST OF OVER FLOW */
3979 /* PAGES. WHEN IT HAVE TO, AN OVERFLOW REC PTR WILL BE ALLOCATED */
3980 /* TO KEEP NFORMATION ABOUT THE PAGE. */
3981 /* --------------------------------------------------------------------------------- */
checkoverfreelist(Signal * signal)3982 void Dbacc::checkoverfreelist(Signal* signal)
3983 {
3984 Uint32 tcolTmp;
3985
3986 tcolTmp = colPageptr.p->word32[ZPOS_ALLOC_CONTAINERS];
3987 if (tcolTmp <= ZFREE_LIMIT) {
3988 if (tcolTmp == 0) {
3989 jam();
3990 ropPageptr = colPageptr;
3991 releaseOverpage(signal);
3992 } else {
3993 jam();
3994 if (colPageptr.p->word32[ZPOS_OVERFLOWREC] == RNIL) {
3995 ndbrequire(cfirstfreeoverrec != RNIL);
3996 jam();
3997 seizeOverRec(signal);
3998 sorOverflowRecPtr.p->dirindex = colPageptr.p->word32[ZPOS_PAGE_ID];
3999 sorOverflowRecPtr.p->overpage = colPageptr.i;
4000 dbgWord32(colPageptr, ZPOS_OVERFLOWREC, sorOverflowRecPtr.i);
4001 colPageptr.p->word32[ZPOS_OVERFLOWREC] = sorOverflowRecPtr.i;
4002 porOverflowRecPtr = sorOverflowRecPtr;
4003 putOverflowRecInFrag(signal);
4004 }//if
4005 }//if
4006 }//if
4007 }//Dbacc::checkoverfreelist()
4008
4009 /* ------------------------------------------------------------------------- */
4010 /* ------------------------------------------------------------------------- */
4011 /* ------------------------------------------------------------------------- */
4012 /* */
4013 /* END OF DELETE MODULE */
4014 /* */
4015 /* ------------------------------------------------------------------------- */
4016 /* ------------------------------------------------------------------------- */
4017 /* ------------------------------------------------------------------------- */
4018 /* ------------------------------------------------------------------------- */
4019 /* ------------------------------------------------------------------------- */
4020 /* ------------------------------------------------------------------------- */
4021 /* */
4022 /* COMMIT AND ABORT MODULE */
4023 /* */
4024 /* ------------------------------------------------------------------------- */
4025 /* ------------------------------------------------------------------------- */
4026 /* ------------------------------------------------------------------------- */
4027 /* ------------------------------------------------------------------------- */
4028 /* ABORT_OPERATION */
4029 /*DESCRIPTION: AN OPERATION RECORD CAN BE IN A LOCK QUEUE OF AN ELEMENT OR */
4030 /*OWNS THE LOCK. BY THIS SUBROUTINE THE LOCK STATE OF THE OPERATION WILL */
4031 /*BE CHECKED. THE OPERATION RECORD WILL BE REMOVED FROM THE QUEUE IF IT */
4032 /*BELONGED TO ANY ONE, OTHERWISE THE ELEMENT HEAD WILL BE UPDATED. */
4033 /* ------------------------------------------------------------------------- */
4034
4035 /**
4036 *
4037 * P0 - P1 - P2 - P3
4038 * S0
4039 * S1
4040 * S2
4041 */
4042 void
abortParallelQueueOperation(Signal * signal,OperationrecPtr opPtr)4043 Dbacc::abortParallelQueueOperation(Signal* signal, OperationrecPtr opPtr)
4044 {
4045 jam();
4046 OperationrecPtr nextP;
4047 OperationrecPtr prevP;
4048 OperationrecPtr loPtr;
4049
4050 Uint32 opbits = opPtr.p->m_op_bits;
4051 Uint32 opstate = opbits & Operationrec::OP_STATE_MASK;
4052 nextP.i = opPtr.p->nextParallelQue;
4053 prevP.i = opPtr.p->prevParallelQue;
4054 loPtr.i = opPtr.p->m_lock_owner_ptr_i;
4055
4056 ndbassert(! (opbits & Operationrec::OP_LOCK_OWNER));
4057 ndbassert(opbits & Operationrec::OP_RUN_QUEUE);
4058
4059 ptrCheckGuard(prevP, coprecsize, operationrec);
4060 ndbassert(prevP.p->nextParallelQue == opPtr.i);
4061 prevP.p->nextParallelQue = nextP.i;
4062
4063 if (nextP.i != RNIL)
4064 {
4065 ptrCheckGuard(nextP, coprecsize, operationrec);
4066 ndbassert(nextP.p->prevParallelQue == opPtr.i);
4067 nextP.p->prevParallelQue = prevP.i;
4068 }
4069 else if (prevP.i != loPtr.i)
4070 {
4071 jam();
4072 ptrCheckGuard(loPtr, coprecsize, operationrec);
4073 ndbassert(loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
4074 ndbassert(loPtr.p->m_lo_last_parallel_op_ptr_i == opPtr.i);
4075 loPtr.p->m_lo_last_parallel_op_ptr_i = prevP.i;
4076 prevP.p->m_lock_owner_ptr_i = loPtr.i;
4077
4078 /**
4079 * Abort P3...check start next
4080 */
4081 startNext(signal, prevP);
4082 validate_lock_queue(prevP);
4083 return;
4084 }
4085 else
4086 {
4087 jam();
4088 /**
4089 * P0 - P1
4090 *
4091 * Abort P1, check start next
4092 */
4093 ndbassert(prevP.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
4094 prevP.p->m_lo_last_parallel_op_ptr_i = RNIL;
4095 startNext(signal, prevP);
4096 validate_lock_queue(prevP);
4097 return;
4098 }
4099
4100 /**
4101 * Abort P1/P2
4102 */
4103 if (opbits & Operationrec::OP_LOCK_MODE)
4104 {
4105 Uint32 nextbits = nextP.p->m_op_bits;
4106 while ((nextbits & Operationrec::OP_LOCK_MODE) == 0)
4107 {
4108 ndbassert(nextbits & Operationrec::OP_ACC_LOCK_MODE);
4109 nextbits &= ~(Uint32)Operationrec::OP_ACC_LOCK_MODE;
4110 nextP.p->m_op_bits = nextbits;
4111
4112 if (nextP.p->nextParallelQue != RNIL)
4113 {
4114 nextP.i = nextP.p->nextParallelQue;
4115 ptrCheckGuard(nextP, coprecsize, operationrec);
4116 nextbits = nextP.p->m_op_bits;
4117 }
4118 else
4119 {
4120 break;
4121 }
4122 }
4123 }
4124
4125 /**
4126 * Abort P1, P2
4127 */
4128 if (opstate == Operationrec::OP_STATE_RUNNING)
4129 {
4130 jam();
4131 startNext(signal, prevP);
4132 validate_lock_queue(prevP);
4133 return;
4134 }
4135
4136 ndbassert(opstate == Operationrec::OP_STATE_EXECUTED ||
4137 opstate == Operationrec::OP_STATE_WAITING);
4138
4139 /**
4140 * Scan to last of run queue
4141 */
4142 while (nextP.p->nextParallelQue != RNIL)
4143 {
4144 jam();
4145 nextP.i = nextP.p->nextParallelQue;
4146 ptrCheckGuard(nextP, coprecsize, operationrec);
4147 }
4148
4149 #ifdef VM_TRACE
4150 loPtr.i = nextP.p->m_lock_owner_ptr_i;
4151 ptrCheckGuard(loPtr, coprecsize, operationrec);
4152 ndbassert(loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
4153 ndbassert(loPtr.p->m_lo_last_parallel_op_ptr_i == nextP.i);
4154 #endif
4155 startNext(signal, nextP);
4156 validate_lock_queue(nextP);
4157
4158 return;
4159 }
4160
4161 void
abortSerieQueueOperation(Signal * signal,OperationrecPtr opPtr)4162 Dbacc::abortSerieQueueOperation(Signal* signal, OperationrecPtr opPtr)
4163 {
4164 jam();
4165 OperationrecPtr prevS, nextS;
4166 OperationrecPtr prevP, nextP;
4167 OperationrecPtr loPtr;
4168
4169 Uint32 opbits = opPtr.p->m_op_bits;
4170
4171 prevS.i = opPtr.p->prevSerialQue;
4172 nextS.i = opPtr.p->nextSerialQue;
4173
4174 prevP.i = opPtr.p->prevParallelQue;
4175 nextP.i = opPtr.p->nextParallelQue;
4176
4177 ndbassert((opbits & Operationrec::OP_LOCK_OWNER) == 0);
4178 ndbassert((opbits & Operationrec::OP_RUN_QUEUE) == 0);
4179
4180 if (prevP.i != RNIL)
4181 {
4182 /**
4183 * We're not list head...
4184 */
4185 ptrCheckGuard(prevP, coprecsize, operationrec);
4186 ndbassert(prevP.p->nextParallelQue == opPtr.i);
4187 prevP.p->nextParallelQue = nextP.i;
4188
4189 if (nextP.i != RNIL)
4190 {
4191 ptrCheckGuard(nextP, coprecsize, operationrec);
4192 ndbassert(nextP.p->prevParallelQue == opPtr.i);
4193 ndbassert((nextP.p->m_op_bits & Operationrec::OP_STATE_MASK) ==
4194 Operationrec::OP_STATE_WAITING);
4195 nextP.p->prevParallelQue = prevP.i;
4196
4197 if ((prevP.p->m_op_bits & Operationrec::OP_ACC_LOCK_MODE) == 0 &&
4198 opbits & Operationrec::OP_LOCK_MODE)
4199 {
4200 /**
4201 * Scan right in parallel queue to fix OP_ACC_LOCK_MODE
4202 */
4203 while ((nextP.p->m_op_bits & Operationrec::OP_LOCK_MODE) == 0)
4204 {
4205 ndbassert(nextP.p->m_op_bits & Operationrec::OP_ACC_LOCK_MODE);
4206 nextP.p->m_op_bits &= ~(Uint32)Operationrec::OP_ACC_LOCK_MODE;
4207 nextP.i = nextP.p->nextParallelQue;
4208 if (nextP.i == RNIL)
4209 break;
4210 ptrCheckGuard(nextP, coprecsize, operationrec);
4211 }
4212 }
4213 }
4214 validate_lock_queue(prevP);
4215 return;
4216 }
4217 else
4218 {
4219 /**
4220 * We're a list head
4221 */
4222 ptrCheckGuard(prevS, coprecsize, operationrec);
4223 ndbassert(prevS.p->nextSerialQue == opPtr.i);
4224
4225 if (nextP.i != RNIL)
4226 {
4227 /**
4228 * Promote nextP to list head
4229 */
4230 ptrCheckGuard(nextP, coprecsize, operationrec);
4231 ndbassert(nextP.p->prevParallelQue == opPtr.i);
4232 prevS.p->nextSerialQue = nextP.i;
4233 nextP.p->prevParallelQue = RNIL;
4234 nextP.p->nextSerialQue = nextS.i;
4235 if (nextS.i != RNIL)
4236 {
4237 jam();
4238 ptrCheckGuard(nextS, coprecsize, operationrec);
4239 ndbassert(nextS.p->prevSerialQue == opPtr.i);
4240 nextS.p->prevSerialQue = nextP.i;
4241 validate_lock_queue(prevS);
4242 return;
4243 }
4244 else
4245 {
4246 // nextS is RNIL, i.e we're last in serie queue...
4247 // we must update lockOwner.m_lo_last_serial_op_ptr_i
4248 loPtr = prevS;
4249 while ((loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0)
4250 {
4251 loPtr.i = loPtr.p->prevSerialQue;
4252 ptrCheckGuard(loPtr, coprecsize, operationrec);
4253 }
4254 ndbassert(loPtr.p->m_lo_last_serial_op_ptr_i == opPtr.i);
4255 loPtr.p->m_lo_last_serial_op_ptr_i = nextP.i;
4256 validate_lock_queue(loPtr);
4257 return;
4258 }
4259 }
4260
4261 if (nextS.i == RNIL)
4262 {
4263 /**
4264 * Abort S2
4265 */
4266
4267 // nextS is RNIL, i.e we're last in serie queue...
4268 // and we have no parallel queue,
4269 // we must update lockOwner.m_lo_last_serial_op_ptr_i
4270 prevS.p->nextSerialQue = RNIL;
4271
4272 loPtr = prevS;
4273 while ((loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0)
4274 {
4275 loPtr.i = loPtr.p->prevSerialQue;
4276 ptrCheckGuard(loPtr, coprecsize, operationrec);
4277 }
4278 ndbassert(loPtr.p->m_lo_last_serial_op_ptr_i == opPtr.i);
4279 if (prevS.i != loPtr.i)
4280 {
4281 jam();
4282 loPtr.p->m_lo_last_serial_op_ptr_i = prevS.i;
4283 }
4284 else
4285 {
4286 loPtr.p->m_lo_last_serial_op_ptr_i = RNIL;
4287 }
4288 validate_lock_queue(loPtr);
4289 }
4290 else if (nextP.i == RNIL)
4291 {
4292 ptrCheckGuard(nextS, coprecsize, operationrec);
4293 ndbassert(nextS.p->prevSerialQue == opPtr.i);
4294 prevS.p->nextSerialQue = nextS.i;
4295 nextS.p->prevSerialQue = prevS.i;
4296
4297 if (prevS.p->m_op_bits & Operationrec::OP_LOCK_OWNER)
4298 {
4299 /**
4300 * Abort S0
4301 */
4302 OperationrecPtr lastOp;
4303 lastOp.i = prevS.p->m_lo_last_parallel_op_ptr_i;
4304 if (lastOp.i != RNIL)
4305 {
4306 jam();
4307 ptrCheckGuard(lastOp, coprecsize, operationrec);
4308 ndbassert(lastOp.p->m_lock_owner_ptr_i == prevS.i);
4309 }
4310 else
4311 {
4312 jam();
4313 lastOp = prevS;
4314 }
4315 startNext(signal, lastOp);
4316 validate_lock_queue(lastOp);
4317 }
4318 else
4319 {
4320 validate_lock_queue(prevS);
4321 }
4322 }
4323 }
4324 }
4325
4326
abortOperation(Signal * signal)4327 void Dbacc::abortOperation(Signal* signal)
4328 {
4329 Uint32 opbits = operationRecPtr.p->m_op_bits;
4330
4331 validate_lock_queue(operationRecPtr);
4332
4333 if (opbits & Operationrec::OP_LOCK_OWNER)
4334 {
4335 takeOutLockOwnersList(signal, operationRecPtr);
4336 opbits &= ~(Uint32)Operationrec::OP_LOCK_OWNER;
4337 if (opbits & Operationrec::OP_INSERT_IS_DONE)
4338 {
4339 jam();
4340 opbits |= Operationrec::OP_ELEMENT_DISAPPEARED;
4341 }//if
4342 operationRecPtr.p->m_op_bits = opbits;
4343 const bool queue = (operationRecPtr.p->nextParallelQue != RNIL ||
4344 operationRecPtr.p->nextSerialQue != RNIL);
4345
4346 if (queue)
4347 {
4348 jam();
4349 release_lockowner(signal, operationRecPtr, false);
4350 }
4351 else
4352 {
4353 /* -------------------------------------------------------------------
4354 * WE ARE OWNER OF THE LOCK AND NO OTHER OPERATIONS ARE QUEUED.
4355 * IF INSERT OR STANDBY WE DELETE THE ELEMENT OTHERWISE WE REMOVE
4356 * THE LOCK FROM THE ELEMENT.
4357 * ------------------------------------------------------------------ */
4358 if ((opbits & Operationrec::OP_ELEMENT_DISAPPEARED) == 0)
4359 {
4360 jam();
4361 Page8Ptr aboPageidptr;
4362 Uint32 taboElementptr;
4363 Uint32 tmp2Olq;
4364
4365 taboElementptr = operationRecPtr.p->elementPointer;
4366 aboPageidptr.i = operationRecPtr.p->elementPage;
4367 tmp2Olq = ElementHeader::setUnlocked(operationRecPtr.p->hashvaluePart,
4368 operationRecPtr.p->scanBits);
4369 ptrCheckGuard(aboPageidptr, cpagesize, page8);
4370 dbgWord32(aboPageidptr, taboElementptr, tmp2Olq);
4371 arrGuard(taboElementptr, 2048);
4372 aboPageidptr.p->word32[taboElementptr] = tmp2Olq;
4373 return;
4374 }
4375 else
4376 {
4377 jam();
4378 commitdelete(signal);
4379 }//if
4380 }//if
4381 }
4382 else if (opbits & Operationrec::OP_RUN_QUEUE)
4383 {
4384 abortParallelQueueOperation(signal, operationRecPtr);
4385 }
4386 else
4387 {
4388 abortSerieQueueOperation(signal, operationRecPtr);
4389 }
4390 }
4391
4392 void
commitDeleteCheck()4393 Dbacc::commitDeleteCheck()
4394 {
4395 OperationrecPtr opPtr;
4396 OperationrecPtr lastOpPtr;
4397 OperationrecPtr deleteOpPtr;
4398 Uint32 elementDeleted = 0;
4399 bool deleteCheckOngoing = true;
4400 Uint32 hashValue = 0;
4401 lastOpPtr = operationRecPtr;
4402 opPtr.i = operationRecPtr.p->nextParallelQue;
4403 while (opPtr.i != RNIL) {
4404 jam();
4405 ptrCheckGuard(opPtr, coprecsize, operationrec);
4406 lastOpPtr = opPtr;
4407 opPtr.i = opPtr.p->nextParallelQue;
4408 }//while
4409 deleteOpPtr = lastOpPtr;
4410 do {
4411 Uint32 opbits = deleteOpPtr.p->m_op_bits;
4412 Uint32 op = opbits & Operationrec::OP_MASK;
4413 if (op == ZDELETE) {
4414 jam();
4415 /* -------------------------------------------------------------------
4416 * IF THE CURRENT OPERATION TO BE COMMITTED IS A DELETE OPERATION DUE TO
4417 * A SCAN-TAKEOVER THE ACTUAL DELETE WILL BE PERFORMED BY THE PREVIOUS
4418 * OPERATION (SCAN) IN THE PARALLEL QUEUE WHICH OWNS THE LOCK.
4419 * THE PROBLEM IS THAT THE SCAN OPERATION DOES NOT HAVE A HASH VALUE
4420 * ASSIGNED TO IT SO WE COPY IT FROM THIS OPERATION.
4421 *
4422 * WE ASSUME THAT THIS SOLUTION WILL WORK BECAUSE THE ONLY WAY A
4423 * SCAN CAN PERFORM A DELETE IS BY BEING FOLLOWED BY A NORMAL
4424 * DELETE-OPERATION THAT HAS A HASH VALUE.
4425 * ----------------------------------------------------------------- */
4426 hashValue = deleteOpPtr.p->hashValue;
4427 elementDeleted = Operationrec::OP_ELEMENT_DISAPPEARED;
4428 deleteCheckOngoing = false;
4429 } else if (op == ZREAD || op == ZSCAN_OP) {
4430 /* -------------------------------------------------------------------
4431 * We are trying to find out whether the commit will in the end delete
4432 * the tuple. Normally the delete will be the last operation in the
4433 * list of operations on this. It is however possible to issue reads
4434 * and scans in the same savepoint as the delete operation was issued
4435 * and these can end up after the delete in the list of operations
4436 * in the parallel queue. Thus if we discover a read or a scan
4437 * we have to continue scanning the list looking for a delete operation.
4438 */
4439 deleteOpPtr.i = deleteOpPtr.p->prevParallelQue;
4440 if (opbits & Operationrec::OP_LOCK_OWNER) {
4441 jam();
4442 deleteCheckOngoing = false;
4443 } else {
4444 jam();
4445 ptrCheckGuard(deleteOpPtr, coprecsize, operationrec);
4446 }//if
4447 } else {
4448 jam();
4449 /* ------------------------------------------------------------------ */
4450 /* Finding an UPDATE or INSERT before finding a DELETE
4451 * means we cannot be deleting as the end result of this transaction.
4452 */
4453 deleteCheckOngoing = false;
4454 }//if
4455 } while (deleteCheckOngoing);
4456 opPtr = lastOpPtr;
4457 do {
4458 jam();
4459 opPtr.p->m_op_bits |= Operationrec::OP_COMMIT_DELETE_CHECK;
4460 if (elementDeleted) {
4461 jam();
4462 opPtr.p->m_op_bits |= elementDeleted;
4463 opPtr.p->hashValue = hashValue;
4464 }//if
4465 opPtr.i = opPtr.p->prevParallelQue;
4466 if (opPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) {
4467 jam();
4468 break;
4469 }//if
4470 ptrCheckGuard(opPtr, coprecsize, operationrec);
4471 } while (true);
4472 }//Dbacc::commitDeleteCheck()
4473
4474 /* ------------------------------------------------------------------------- */
4475 /* COMMIT_OPERATION */
4476 /* INPUT: OPERATION_REC_PTR, POINTER TO AN OPERATION RECORD */
4477 /* DESCRIPTION: THE OPERATION RECORD WILL BE TAKE OUT OF ANY LOCK QUEUE. */
4478 /* IF IT OWNS THE ELEMENT LOCK. HEAD OF THE ELEMENT WILL BE UPDATED. */
4479 /* ------------------------------------------------------------------------- */
commitOperation(Signal * signal)4480 void Dbacc::commitOperation(Signal* signal)
4481 {
4482 validate_lock_queue(operationRecPtr);
4483
4484 Uint32 opbits = operationRecPtr.p->m_op_bits;
4485 Uint32 op = opbits & Operationrec::OP_MASK;
4486 ndbrequire((opbits & Operationrec::OP_STATE_MASK) == Operationrec::OP_STATE_EXECUTED);
4487 if ((opbits & Operationrec::OP_COMMIT_DELETE_CHECK) == 0 &&
4488 (op != ZREAD && op != ZSCAN_OP))
4489 {
4490 jam();
4491 /* This method is used to check whether the end result of the transaction
4492 will be to delete the tuple. In this case all operation will be marked
4493 with elementIsDisappeared = true to ensure that the last operation
4494 committed will remove the tuple. We only run this once per transaction
4495 (commitDeleteCheckFlag = true if performed earlier) and we don't
4496 execute this code when committing a scan operation since committing
4497 a scan operation only means that the scan is continuing and the scan
4498 lock is released.
4499 */
4500 commitDeleteCheck();
4501 opbits = operationRecPtr.p->m_op_bits;
4502 }//if
4503
4504 ndbassert(opbits & Operationrec::OP_RUN_QUEUE);
4505
4506 if (opbits & Operationrec::OP_LOCK_OWNER)
4507 {
4508 takeOutLockOwnersList(signal, operationRecPtr);
4509 opbits &= ~(Uint32)Operationrec::OP_LOCK_OWNER;
4510 operationRecPtr.p->m_op_bits = opbits;
4511
4512 const bool queue = (operationRecPtr.p->nextParallelQue != RNIL ||
4513 operationRecPtr.p->nextSerialQue != RNIL);
4514
4515 if (!queue && (opbits & Operationrec::OP_ELEMENT_DISAPPEARED) == 0)
4516 {
4517 /*
4518 * This is the normal path through the commit for operations owning the
4519 * lock without any queues and not a delete operation.
4520 */
4521 Page8Ptr coPageidptr;
4522 Uint32 tcoElementptr;
4523 Uint32 tmp2Olq;
4524
4525 coPageidptr.i = operationRecPtr.p->elementPage;
4526 tcoElementptr = operationRecPtr.p->elementPointer;
4527 tmp2Olq = ElementHeader::setUnlocked(operationRecPtr.p->hashvaluePart,
4528 operationRecPtr.p->scanBits);
4529 ptrCheckGuard(coPageidptr, cpagesize, page8);
4530 dbgWord32(coPageidptr, tcoElementptr, tmp2Olq);
4531 arrGuard(tcoElementptr, 2048);
4532 coPageidptr.p->word32[tcoElementptr] = tmp2Olq;
4533 return;
4534 }
4535 else if (queue)
4536 {
4537 jam();
4538 /*
4539 * The case when there is a queue lined up.
4540 * Release the lock and pass it to the next operation lined up.
4541 */
4542 release_lockowner(signal, operationRecPtr, true);
4543 return;
4544 }
4545 else
4546 {
4547 jam();
4548 /*
4549 * No queue and elementIsDisappeared is true.
4550 * We perform the actual delete operation.
4551 */
4552 commitdelete(signal);
4553 return;
4554 }//if
4555 }
4556 else
4557 {
4558 /**
4559 * THE OPERATION DOES NOT OWN THE LOCK. IT MUST BE IN A LOCK QUEUE OF THE
4560 * ELEMENT.
4561 */
4562 jam();
4563 OperationrecPtr prev, next, lockOwner;
4564 prev.i = operationRecPtr.p->prevParallelQue;
4565 next.i = operationRecPtr.p->nextParallelQue;
4566 lockOwner.i = operationRecPtr.p->m_lock_owner_ptr_i;
4567 ptrCheckGuard(prev, coprecsize, operationrec);
4568
4569 prev.p->nextParallelQue = next.i;
4570 if (next.i != RNIL)
4571 {
4572 jam();
4573 ptrCheckGuard(next, coprecsize, operationrec);
4574 next.p->prevParallelQue = prev.i;
4575 }
4576 else if (prev.p->m_op_bits & Operationrec::OP_LOCK_OWNER)
4577 {
4578 jam();
4579 ndbassert(lockOwner.i == prev.i);
4580 prev.p->m_lo_last_parallel_op_ptr_i = RNIL;
4581 next = prev;
4582 }
4583 else
4584 {
4585 jam();
4586 /**
4587 * Last operation in parallell queue
4588 */
4589 ndbassert(prev.i != lockOwner.i);
4590 ptrCheckGuard(lockOwner, coprecsize, operationrec);
4591 ndbassert(lockOwner.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
4592 lockOwner.p->m_lo_last_parallel_op_ptr_i = prev.i;
4593 prev.p->m_lock_owner_ptr_i = lockOwner.i;
4594 next = prev;
4595 }
4596
4597 /**
4598 * Check possible lock upgrade
4599 */
4600 if(opbits & Operationrec::OP_ACC_LOCK_MODE)
4601 {
4602 jam();
4603
4604 /**
4605 * Not lock owner...committing a exclusive operation...
4606 *
4607 * e.g
4608 * T1(R) T1(X)
4609 * T2(R/X)
4610 *
4611 * If T1(X) commits T2(R/X) is not supposed to run
4612 * as T1(R) should also commit
4613 *
4614 * e.g
4615 * T1(R) T1(X) T1*(R)
4616 * T2(R/X)
4617 *
4618 * If T1*(R) commits T2(R/X) is not supposed to run
4619 * as T1(R),T2(x) should also commit
4620 */
4621 validate_lock_queue(prev);
4622 return;
4623 }
4624
4625 /**
4626 * We committed a shared lock
4627 * Check if we can start next...
4628 */
4629 while(next.p->nextParallelQue != RNIL)
4630 {
4631 jam();
4632 next.i = next.p->nextParallelQue;
4633 ptrCheckGuard(next, coprecsize, operationrec);
4634
4635 if ((next.p->m_op_bits & Operationrec::OP_STATE_MASK) !=
4636 Operationrec::OP_STATE_EXECUTED)
4637 {
4638 jam();
4639 return;
4640 }
4641 }
4642
4643 startNext(signal, next);
4644
4645 validate_lock_queue(prev);
4646 }
4647 }//Dbacc::commitOperation()
4648
4649 void
release_lockowner(Signal * signal,OperationrecPtr opPtr,bool commit)4650 Dbacc::release_lockowner(Signal* signal, OperationrecPtr opPtr, bool commit)
4651 {
4652 OperationrecPtr nextP;
4653 OperationrecPtr nextS;
4654 OperationrecPtr newOwner;
4655 OperationrecPtr lastP;
4656
4657 Uint32 opbits = opPtr.p->m_op_bits;
4658 nextP.i = opPtr.p->nextParallelQue;
4659 nextS.i = opPtr.p->nextSerialQue;
4660 lastP.i = opPtr.p->m_lo_last_parallel_op_ptr_i;
4661 Uint32 lastS = opPtr.p->m_lo_last_serial_op_ptr_i;
4662
4663 ndbassert(lastP.i != RNIL || lastS != RNIL);
4664 ndbassert(nextP.i != RNIL || nextS.i != RNIL);
4665
4666 enum {
4667 NOTHING,
4668 CHECK_LOCK_UPGRADE,
4669 START_NEW
4670 } action = NOTHING;
4671
4672 if (nextP.i != RNIL)
4673 {
4674 jam();
4675 ptrCheckGuard(nextP, coprecsize, operationrec);
4676 newOwner = nextP;
4677
4678 if (lastP.i == newOwner.i)
4679 {
4680 newOwner.p->m_lo_last_parallel_op_ptr_i = RNIL;
4681 lastP = nextP;
4682 }
4683 else
4684 {
4685 ptrCheckGuard(lastP, coprecsize, operationrec);
4686 newOwner.p->m_lo_last_parallel_op_ptr_i = lastP.i;
4687 lastP.p->m_lock_owner_ptr_i = newOwner.i;
4688 }
4689
4690 newOwner.p->m_lo_last_serial_op_ptr_i = lastS;
4691 newOwner.p->nextSerialQue = nextS.i;
4692
4693 if (nextS.i != RNIL)
4694 {
4695 jam();
4696 ptrCheckGuard(nextS, coprecsize, operationrec);
4697 ndbassert(nextS.p->prevSerialQue == opPtr.i);
4698 nextS.p->prevSerialQue = newOwner.i;
4699 }
4700
4701 if (commit)
4702 {
4703 if ((opbits & Operationrec::OP_ACC_LOCK_MODE) == ZREADLOCK)
4704 {
4705 jam();
4706 /**
4707 * Lock owner...committing a shared operation...
4708 * this can be a lock upgrade
4709 *
4710 * e.g
4711 * T1(R) T2(R)
4712 * T2(X)
4713 *
4714 * If T1(R) commits T2(X) is supposed to run
4715 *
4716 * e.g
4717 * T1(X) T1(R)
4718 * T2(R)
4719 *
4720 * If T1(X) commits, then T1(R) _should_ commit before T2(R) is
4721 * allowed to proceed
4722 */
4723 action = CHECK_LOCK_UPGRADE;
4724 }
4725 else
4726 {
4727 jam();
4728 newOwner.p->m_op_bits |= Operationrec::OP_LOCK_MODE;
4729 }
4730 }
4731 else
4732 {
4733 /**
4734 * Aborting an operation can *always* lead to lock upgrade
4735 */
4736 action = CHECK_LOCK_UPGRADE;
4737 Uint32 opstate = opbits & Operationrec::OP_STATE_MASK;
4738 if (opstate != Operationrec::OP_STATE_EXECUTED)
4739 {
4740 ndbassert(opstate == Operationrec::OP_STATE_RUNNING);
4741 if (opbits & Operationrec::OP_ELEMENT_DISAPPEARED)
4742 {
4743 jam();
4744 report_dealloc(signal, opPtr.p);
4745 newOwner.p->localdata[0] = ~(Uint32)0;
4746 newOwner.p->localdata[1] = ~(Uint32)0;
4747 }
4748 else
4749 {
4750 jam();
4751 newOwner.p->localdata[0] = opPtr.p->localdata[0];
4752 newOwner.p->localdata[1] = opPtr.p->localdata[1];
4753 }
4754 action = START_NEW;
4755 }
4756
4757 /**
4758 * Update ACC_LOCK_MODE
4759 */
4760 if (opbits & Operationrec::OP_LOCK_MODE)
4761 {
4762 Uint32 nextbits = nextP.p->m_op_bits;
4763 while ((nextbits & Operationrec::OP_LOCK_MODE) == 0)
4764 {
4765 ndbassert(nextbits & Operationrec::OP_ACC_LOCK_MODE);
4766 nextbits &= ~(Uint32)Operationrec::OP_ACC_LOCK_MODE;
4767 nextP.p->m_op_bits = nextbits;
4768
4769 if (nextP.p->nextParallelQue != RNIL)
4770 {
4771 nextP.i = nextP.p->nextParallelQue;
4772 ptrCheckGuard(nextP, coprecsize, operationrec);
4773 nextbits = nextP.p->m_op_bits;
4774 }
4775 else
4776 {
4777 break;
4778 }
4779 }
4780 }
4781 }
4782 }
4783 else
4784 {
4785 jam();
4786 ptrCheckGuard(nextS, coprecsize, operationrec);
4787 newOwner = nextS;
4788
4789 newOwner.p->m_op_bits |= Operationrec::OP_RUN_QUEUE;
4790
4791 if (opbits & Operationrec::OP_ELEMENT_DISAPPEARED)
4792 {
4793 report_dealloc(signal, opPtr.p);
4794 newOwner.p->localdata[0] = ~(Uint32)0;
4795 newOwner.p->localdata[1] = ~(Uint32)0;
4796 }
4797 else
4798 {
4799 jam();
4800 newOwner.p->localdata[0] = opPtr.p->localdata[0];
4801 newOwner.p->localdata[1] = opPtr.p->localdata[1];
4802 }
4803
4804 lastP = newOwner;
4805 while (lastP.p->nextParallelQue != RNIL)
4806 {
4807 lastP.i = lastP.p->nextParallelQue;
4808 ptrCheckGuard(lastP, coprecsize, operationrec);
4809 lastP.p->m_op_bits |= Operationrec::OP_RUN_QUEUE;
4810 }
4811
4812 if (newOwner.i != lastP.i)
4813 {
4814 jam();
4815 newOwner.p->m_lo_last_parallel_op_ptr_i = lastP.i;
4816 }
4817 else
4818 {
4819 jam();
4820 newOwner.p->m_lo_last_parallel_op_ptr_i = RNIL;
4821 }
4822
4823 if (newOwner.i != lastS)
4824 {
4825 jam();
4826 newOwner.p->m_lo_last_serial_op_ptr_i = lastS;
4827 }
4828 else
4829 {
4830 jam();
4831 newOwner.p->m_lo_last_serial_op_ptr_i = RNIL;
4832 }
4833
4834 action = START_NEW;
4835 }
4836
4837 insertLockOwnersList(signal, newOwner);
4838
4839 /**
4840 * Copy op info, and store op in element
4841 *
4842 */
4843 {
4844 newOwner.p->elementPage = opPtr.p->elementPage;
4845 newOwner.p->elementIsforward = opPtr.p->elementIsforward;
4846 newOwner.p->elementPointer = opPtr.p->elementPointer;
4847 newOwner.p->elementContainer = opPtr.p->elementContainer;
4848 newOwner.p->scanBits = opPtr.p->scanBits;
4849 newOwner.p->hashvaluePart = opPtr.p->hashvaluePart;
4850 newOwner.p->m_op_bits |= (opbits & Operationrec::OP_ELEMENT_DISAPPEARED);
4851 if (opbits & Operationrec::OP_ELEMENT_DISAPPEARED)
4852 {
4853 /* ------------------------------------------------------------------- */
4854 // If the elementIsDisappeared is set then we know that the
4855 // hashValue is also set since it always originates from a
4856 // committing abort or a aborting insert.
4857 // Scans do not initialise the hashValue and must have this
4858 // value initialised if they are
4859 // to successfully commit the delete.
4860 /* ------------------------------------------------------------------- */
4861 jam();
4862 newOwner.p->hashValue = opPtr.p->hashValue;
4863 }//if
4864
4865 Page8Ptr pagePtr;
4866 pagePtr.i = newOwner.p->elementPage;
4867 ptrCheckGuard(pagePtr, cpagesize, page8);
4868 const Uint32 tmp = ElementHeader::setLocked(newOwner.i);
4869 arrGuard(newOwner.p->elementPointer, 2048);
4870 pagePtr.p->word32[newOwner.p->elementPointer] = tmp;
4871 }
4872
4873 switch(action){
4874 case NOTHING:
4875 validate_lock_queue(newOwner);
4876 return;
4877 case START_NEW:
4878 startNew(signal, newOwner);
4879 validate_lock_queue(newOwner);
4880 return;
4881 case CHECK_LOCK_UPGRADE:
4882 startNext(signal, lastP);
4883 validate_lock_queue(lastP);
4884 break;
4885 }
4886
4887 }
4888
4889 void
startNew(Signal * signal,OperationrecPtr newOwner)4890 Dbacc::startNew(Signal* signal, OperationrecPtr newOwner)
4891 {
4892 OperationrecPtr save = operationRecPtr;
4893 operationRecPtr = newOwner;
4894
4895 Uint32 opbits = newOwner.p->m_op_bits;
4896 Uint32 op = opbits & Operationrec::OP_MASK;
4897 Uint32 opstate = (opbits & Operationrec::OP_STATE_MASK);
4898 ndbassert(opstate == Operationrec::OP_STATE_WAITING);
4899 ndbassert(opbits & Operationrec::OP_LOCK_OWNER);
4900 const bool deleted = opbits & Operationrec::OP_ELEMENT_DISAPPEARED;
4901 Uint32 errCode = 0;
4902
4903 opbits &= opbits & ~(Uint32)Operationrec::OP_STATE_MASK;
4904 opbits |= Operationrec::OP_STATE_RUNNING;
4905
4906 if (op == ZSCAN_OP && (opbits & Operationrec::OP_LOCK_REQ) == 0)
4907 goto scan;
4908
4909 if (deleted)
4910 {
4911 jam();
4912 if (op != ZINSERT && op != ZWRITE)
4913 {
4914 errCode = ZREAD_ERROR;
4915 goto ref;
4916 }
4917
4918 opbits &= ~(Uint32)Operationrec::OP_MASK;
4919 opbits &= ~(Uint32)Operationrec::OP_ELEMENT_DISAPPEARED;
4920 opbits |= (op = ZINSERT);
4921 opbits |= Operationrec::OP_INSERT_IS_DONE;
4922 goto conf;
4923 }
4924 else if (op == ZINSERT)
4925 {
4926 jam();
4927 errCode = ZWRITE_ERROR;
4928 goto ref;
4929 }
4930 else if (op == ZWRITE)
4931 {
4932 jam();
4933 opbits &= ~(Uint32)Operationrec::OP_MASK;
4934 opbits |= (op = ZUPDATE);
4935 goto conf;
4936 }
4937
4938 conf:
4939 newOwner.p->m_op_bits = opbits;
4940
4941 sendAcckeyconf(signal);
4942 sendSignal(newOwner.p->userblockref, GSN_ACCKEYCONF,
4943 signal, 6, JBB);
4944
4945 operationRecPtr = save;
4946 return;
4947
4948 scan:
4949 jam();
4950 newOwner.p->m_op_bits = opbits;
4951
4952 takeOutScanLockQueue(newOwner.p->scanRecPtr);
4953 putReadyScanQueue(signal, newOwner.p->scanRecPtr);
4954
4955 operationRecPtr = save;
4956 return;
4957
4958 ref:
4959 newOwner.p->m_op_bits = opbits;
4960
4961 signal->theData[0] = newOwner.p->userptr;
4962 signal->theData[1] = errCode;
4963 sendSignal(newOwner.p->userblockref, GSN_ACCKEYREF, signal,
4964 2, JBB);
4965
4966 operationRecPtr = save;
4967 return;
4968 }
4969
4970 /**
4971 * takeOutLockOwnersList
4972 *
4973 * Description: Take out an operation from the doubly linked
4974 * lock owners list on the fragment.
4975 *
4976 */
takeOutLockOwnersList(Signal * signal,const OperationrecPtr & outOperPtr)4977 void Dbacc::takeOutLockOwnersList(Signal* signal,
4978 const OperationrecPtr& outOperPtr)
4979 {
4980 const Uint32 Tprev = outOperPtr.p->prevLockOwnerOp;
4981 const Uint32 Tnext = outOperPtr.p->nextLockOwnerOp;
4982 #ifdef VM_TRACE
4983 // Check that operation is already in the list
4984 OperationrecPtr tmpOperPtr;
4985 bool inList = false;
4986 tmpOperPtr.i = fragrecptr.p->lockOwnersList;
4987 while (tmpOperPtr.i != RNIL){
4988 ptrCheckGuard(tmpOperPtr, coprecsize, operationrec);
4989 if (tmpOperPtr.i == outOperPtr.i)
4990 inList = true;
4991 tmpOperPtr.i = tmpOperPtr.p->nextLockOwnerOp;
4992 }
4993 ndbrequire(inList == true);
4994 #endif
4995
4996 ndbassert(outOperPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
4997
4998 // Fast path through the code for the common case.
4999 if ((Tprev == RNIL) && (Tnext == RNIL)) {
5000 ndbrequire(fragrecptr.p->lockOwnersList == outOperPtr.i);
5001 fragrecptr.p->lockOwnersList = RNIL;
5002 return;
5003 }
5004
5005 // Check previous operation
5006 if (Tprev != RNIL) {
5007 jam();
5008 arrGuard(Tprev, coprecsize);
5009 operationrec[Tprev].nextLockOwnerOp = Tnext;
5010 } else {
5011 fragrecptr.p->lockOwnersList = Tnext;
5012 }//if
5013
5014 // Check next operation
5015 if (Tnext == RNIL) {
5016 return;
5017 } else {
5018 jam();
5019 arrGuard(Tnext, coprecsize);
5020 operationrec[Tnext].prevLockOwnerOp = Tprev;
5021 }//if
5022
5023 return;
5024 }//Dbacc::takeOutLockOwnersList()
5025
5026 /**
5027 * insertLockOwnersList
5028 *
5029 * Description: Insert an operation first in the dubly linked lock owners
5030 * list on the fragment.
5031 *
5032 */
insertLockOwnersList(Signal * signal,const OperationrecPtr & insOperPtr)5033 void Dbacc::insertLockOwnersList(Signal* signal,
5034 const OperationrecPtr& insOperPtr)
5035 {
5036 OperationrecPtr tmpOperPtr;
5037 #ifdef VM_TRACE
5038 // Check that operation is not already in list
5039 tmpOperPtr.i = fragrecptr.p->lockOwnersList;
5040 while(tmpOperPtr.i != RNIL){
5041 ptrCheckGuard(tmpOperPtr, coprecsize, operationrec);
5042 ndbrequire(tmpOperPtr.i != insOperPtr.i);
5043 tmpOperPtr.i = tmpOperPtr.p->nextLockOwnerOp;
5044 }
5045 #endif
5046 tmpOperPtr.i = fragrecptr.p->lockOwnersList;
5047
5048 ndbrequire(! (insOperPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER));
5049
5050 insOperPtr.p->m_op_bits |= Operationrec::OP_LOCK_OWNER;
5051 insOperPtr.p->prevLockOwnerOp = RNIL;
5052 insOperPtr.p->nextLockOwnerOp = tmpOperPtr.i;
5053
5054 fragrecptr.p->lockOwnersList = insOperPtr.i;
5055 if (tmpOperPtr.i == RNIL) {
5056 return;
5057 } else {
5058 jam();
5059 ptrCheckGuard(tmpOperPtr, coprecsize, operationrec);
5060 tmpOperPtr.p->prevLockOwnerOp = insOperPtr.i;
5061 }//if
5062 }//Dbacc::insertLockOwnersList()
5063
5064
5065 /* --------------------------------------------------------------------------------- */
5066 /* --------------------------------------------------------------------------------- */
5067 /* --------------------------------------------------------------------------------- */
5068 /* */
5069 /* END OF COMMIT AND ABORT MODULE */
5070 /* */
5071 /* --------------------------------------------------------------------------------- */
5072 /* --------------------------------------------------------------------------------- */
5073 /* --------------------------------------------------------------------------------- */
5074 /* --------------------------------------------------------------------------------- */
5075 /* --------------------------------------------------------------------------------- */
5076 /* ALLOC_OVERFLOW_PAGE */
5077 /* DESCRIPTION: */
5078 /* --------------------------------------------------------------------------------- */
allocOverflowPage(Signal * signal)5079 void Dbacc::allocOverflowPage(Signal* signal)
5080 {
5081 DirRangePtr aopDirRangePtr;
5082 DirectoryarrayPtr aopOverflowDirptr;
5083 OverflowRecordPtr aopOverflowRecPtr;
5084 Uint32 taopTmp1;
5085 Uint32 taopTmp2;
5086 Uint32 taopTmp3;
5087
5088 tresult = 0;
5089 if (cfirstfreepage == RNIL)
5090 {
5091 jam();
5092 zpagesize_error("Dbacc::allocOverflowPage");
5093 tresult = ZPAGESIZE_ERROR;
5094 return;
5095 }//if
5096 if (fragrecptr.p->firstFreeDirindexRec != RNIL) {
5097 jam();
5098 /* FRAGRECPTR:FIRST_FREE_DIRINDEX_REC POINTS */
5099 /* TO THE FIRST ELEMENT IN A FREE LIST OF THE */
5100 /* DIRECTORY INDEX WICH HAVE NULL AS PAGE */
5101 aopOverflowRecPtr.i = fragrecptr.p->firstFreeDirindexRec;
5102 ptrCheckGuard(aopOverflowRecPtr, coverflowrecsize, overflowRecord);
5103 troOverflowRecPtr.p = aopOverflowRecPtr.p;
5104 takeRecOutOfFreeOverdir(signal);
5105 } else if (cfirstfreeoverrec == RNIL) {
5106 jam();
5107 tresult = ZOVER_REC_ERROR;
5108 return;
5109 } else if ((cfirstfreedir == RNIL) &&
5110 (cdirarraysize <= cdirmemory)) {
5111 jam();
5112 tresult = ZDIRSIZE_ERROR;
5113 return;
5114 } else {
5115 jam();
5116 seizeOverRec(signal);
5117 aopOverflowRecPtr = sorOverflowRecPtr;
5118 aopOverflowRecPtr.p->dirindex = fragrecptr.p->lastOverIndex;
5119 }//if
5120 aopOverflowRecPtr.p->nextOverRec = RNIL;
5121 aopOverflowRecPtr.p->prevOverRec = RNIL;
5122 fragrecptr.p->firstOverflowRec = aopOverflowRecPtr.i;
5123 fragrecptr.p->lastOverflowRec = aopOverflowRecPtr.i;
5124 taopTmp1 = aopOverflowRecPtr.p->dirindex;
5125 aopDirRangePtr.i = fragrecptr.p->overflowdir;
5126 taopTmp2 = taopTmp1 >> 8;
5127 taopTmp3 = taopTmp1 & 0xff;
5128 ptrCheckGuard(aopDirRangePtr, cdirrangesize, dirRange);
5129 arrGuard(taopTmp2, 256);
5130 if (aopDirRangePtr.p->dirArray[taopTmp2] == RNIL) {
5131 jam();
5132 seizeDirectory(signal);
5133 ndbrequire(tresult <= ZLIMIT_OF_ERROR);
5134 aopDirRangePtr.p->dirArray[taopTmp2] = sdDirptr.i;
5135 }//if
5136 aopOverflowDirptr.i = aopDirRangePtr.p->dirArray[taopTmp2];
5137 seizePage(signal);
5138 ndbrequire(tresult <= ZLIMIT_OF_ERROR);
5139 ptrCheckGuard(aopOverflowDirptr, cdirarraysize, directoryarray);
5140 aopOverflowDirptr.p->pagep[taopTmp3] = spPageptr.i;
5141 tiopPageId = aopOverflowRecPtr.p->dirindex;
5142 iopOverflowRecPtr = aopOverflowRecPtr;
5143 iopPageptr = spPageptr;
5144 initOverpage(signal);
5145 aopOverflowRecPtr.p->overpage = spPageptr.i;
5146 if (fragrecptr.p->lastOverIndex <= aopOverflowRecPtr.p->dirindex) {
5147 jam();
5148 ndbrequire(fragrecptr.p->lastOverIndex == aopOverflowRecPtr.p->dirindex);
5149 fragrecptr.p->lastOverIndex++;
5150 }//if
5151 }//Dbacc::allocOverflowPage()
5152
5153 /* --------------------------------------------------------------------------------- */
5154 /* --------------------------------------------------------------------------------- */
5155 /* --------------------------------------------------------------------------------- */
5156 /* */
5157 /* EXPAND/SHRINK MODULE */
5158 /* */
5159 /* --------------------------------------------------------------------------------- */
5160 /* --------------------------------------------------------------------------------- */
5161 /* ******************--------------------------------------------------------------- */
5162 /*EXPANDCHECK EXPAND BUCKET ORD */
5163 /* SENDER: ACC, LEVEL B */
5164 /* INPUT: FRAGRECPTR, POINTS TO A FRAGMENT RECORD. */
5165 /* DESCRIPTION: A BUCKET OF A FRAGMENT PAGE WILL BE EXPAND INTO TWO BUCKETS */
5166 /* ACCORDING TO LH3. */
5167 /* ******************--------------------------------------------------------------- */
5168 /* ******************--------------------------------------------------------------- */
5169 /* EXPANDCHECK EXPAND BUCKET ORD */
5170 /* ******************------------------------------+ */
5171 /* SENDER: ACC, LEVEL B */
5172 /* A BUCKET OF THE FRAGMENT WILL */
5173 /* BE EXPANDED ACORDING TO LH3, */
5174 /* AND COMMIT TRANSACTION PROCESS */
5175 /* WILL BE CONTINUED */
checkScanExpand(Signal * signal)5176 Uint32 Dbacc::checkScanExpand(Signal* signal)
5177 {
5178 Uint32 Ti;
5179 Uint32 TreturnCode = 0;
5180 Uint32 TPageIndex;
5181 Uint32 TDirInd;
5182 Uint32 TSplit;
5183 Uint32 TreleaseInd = 0;
5184 Uint32 TreleaseScanBucket;
5185 Uint32 TreleaseScanIndicator[MAX_PARALLEL_SCANS_PER_FRAG];
5186 DirectoryarrayPtr TDirptr;
5187 DirRangePtr TDirRangePtr;
5188 Page8Ptr TPageptr;
5189 ScanRecPtr TscanPtr;
5190
5191 TSplit = fragrecptr.p->p;
5192 for (Ti = 0; Ti < MAX_PARALLEL_SCANS_PER_FRAG; Ti++) {
5193 TreleaseScanIndicator[Ti] = 0;
5194 if (fragrecptr.p->scan[Ti] != RNIL) {
5195 //-------------------------------------------------------------
5196 // A scan is ongoing on this particular local fragment. We have
5197 // to check its current state.
5198 //-------------------------------------------------------------
5199 TscanPtr.i = fragrecptr.p->scan[Ti];
5200 ptrCheckGuard(TscanPtr, cscanRecSize, scanRec);
5201 if (TscanPtr.p->activeLocalFrag == fragrecptr.i) {
5202 if (TscanPtr.p->scanBucketState == ScanRec::FIRST_LAP) {
5203 if (TSplit == TscanPtr.p->nextBucketIndex) {
5204 jam();
5205 //-------------------------------------------------------------
5206 // We are currently scanning this bucket. We cannot split it
5207 // simultaneously with the scan. We have to pass this offer for
5208 // splitting the bucket.
5209 //-------------------------------------------------------------
5210 TreturnCode = 1;
5211 return TreturnCode;
5212 } else if (TSplit > TscanPtr.p->nextBucketIndex) {
5213 jam();
5214 //-------------------------------------------------------------
5215 // This bucket has not yet been scanned. We must reset the scanned
5216 // bit indicator for this scan on this bucket.
5217 //-------------------------------------------------------------
5218 TreleaseScanIndicator[Ti] = 1;
5219 TreleaseInd = 1;
5220 } else {
5221 jam();
5222 }//if
5223 } else if (TscanPtr.p->scanBucketState == ScanRec::SECOND_LAP) {
5224 jam();
5225 //-------------------------------------------------------------
5226 // We are performing a second lap to handle buckets that was
5227 // merged during the first lap of scanning. During this second
5228 // lap we do not allow any splits or merges.
5229 //-------------------------------------------------------------
5230 TreturnCode = 1;
5231 return TreturnCode;
5232 } else {
5233 ndbrequire(TscanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED);
5234 jam();
5235 //-------------------------------------------------------------
5236 // The scan is completed and we can thus go ahead and perform
5237 // the split.
5238 //-------------------------------------------------------------
5239 }//if
5240 }//if
5241 }//if
5242 }//for
5243 if (TreleaseInd == 1) {
5244 TreleaseScanBucket = TSplit;
5245 TDirRangePtr.i = fragrecptr.p->directory;
5246 TPageIndex = TreleaseScanBucket & ((1 << fragrecptr.p->k) - 1); /* PAGE INDEX OBS K = 6 */
5247 TDirInd = TreleaseScanBucket >> fragrecptr.p->k; /* DIRECTORY INDEX OBS K = 6 */
5248 ptrCheckGuard(TDirRangePtr, cdirrangesize, dirRange);
5249 arrGuard((TDirInd >> 8), 256);
5250 TDirptr.i = TDirRangePtr.p->dirArray[TDirInd >> 8];
5251 ptrCheckGuard(TDirptr, cdirarraysize, directoryarray);
5252 TPageptr.i = TDirptr.p->pagep[TDirInd & 0xff];
5253 ptrCheckGuard(TPageptr, cpagesize, page8);
5254 for (Ti = 0; Ti < MAX_PARALLEL_SCANS_PER_FRAG; Ti++) {
5255 if (TreleaseScanIndicator[Ti] == 1) {
5256 jam();
5257 scanPtr.i = fragrecptr.p->scan[Ti];
5258 ptrCheckGuard(scanPtr, cscanRecSize, scanRec);
5259 rsbPageidptr = TPageptr;
5260 trsbPageindex = TPageIndex;
5261 releaseScanBucket(signal);
5262 }//if
5263 }//for
5264 }//if
5265 return TreturnCode;
5266 }//Dbacc::checkScanExpand()
5267
execEXPANDCHECK2(Signal * signal)5268 void Dbacc::execEXPANDCHECK2(Signal* signal)
5269 {
5270 jamEntry();
5271
5272 if(refToBlock(signal->getSendersBlockRef()) == DBLQH)
5273 {
5274 jam();
5275 return;
5276 }
5277
5278 DirectoryarrayPtr newDirptr;
5279
5280 fragrecptr.i = signal->theData[0];
5281 tresult = 0; /* 0= FALSE,1= TRUE,> ZLIMIT_OF_ERROR =ERRORCODE */
5282 Uint32 tmp = 1;
5283 tmp = tmp << 31;
5284 ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
5285 fragrecptr.p->expandFlag = 0;
5286 if (fragrecptr.p->slack < tmp) {
5287 jam();
5288 /* IT MEANS THAT IF SLACK > ZERO */
5289 /*--------------------------------------------------------------*/
5290 /* THE SLACK HAS IMPROVED AND IS NOW ACCEPTABLE AND WE */
5291 /* CAN FORGET ABOUT THE EXPAND PROCESS. */
5292 /*--------------------------------------------------------------*/
5293 if (ERROR_INSERTED(3002))
5294 debug_lh_vars("SLK");
5295 if (fragrecptr.p->dirRangeFull == ZTRUE) {
5296 jam();
5297 fragrecptr.p->dirRangeFull = ZFALSE;
5298 }
5299 return;
5300 }//if
5301 if (fragrecptr.p->firstOverflowRec == RNIL) {
5302 jam();
5303 allocOverflowPage(signal);
5304 if (tresult > ZLIMIT_OF_ERROR) {
5305 jam();
5306 /*--------------------------------------------------------------*/
5307 /* WE COULD NOT ALLOCATE ANY OVERFLOW PAGE. THUS WE HAVE TO STOP*/
5308 /* THE EXPAND SINCE WE CANNOT GUARANTEE ITS COMPLETION. */
5309 /*--------------------------------------------------------------*/
5310 return;
5311 }//if
5312 }//if
5313 if (cfirstfreepage == RNIL)
5314 {
5315 /*--------------------------------------------------------------*/
5316 /* WE HAVE TO STOP THE EXPAND PROCESS SINCE THERE ARE NO FREE */
5317 /* PAGES. THIS MEANS THAT WE COULD BE FORCED TO CRASH SINCE WE */
5318 /* CANNOT COMPLETE THE EXPAND. TO AVOID THE CRASH WE EXIT HERE. */
5319 /*--------------------------------------------------------------*/
5320 return;
5321 }//if
5322 if (checkScanExpand(signal) == 1) {
5323 jam();
5324 /*--------------------------------------------------------------*/
5325 // A scan state was inconsistent with performing an expand
5326 // operation.
5327 /*--------------------------------------------------------------*/
5328 return;
5329 }//if
5330
5331 /*--------------------------------------------------------------------------*/
5332 /* WE START BY FINDING THE PAGE, THE PAGE INDEX AND THE PAGE DIRECTORY*/
5333 /* OF THE NEW BUCKET WHICH SHALL RECEIVE THE ELEMENT WHICH HAVE A 1 IN*/
5334 /* THE NEXT HASH BIT. THIS BIT IS USED IN THE SPLIT MECHANISM TO */
5335 /* DECIDE WHICH ELEMENT GOES WHERE. */
5336 /*--------------------------------------------------------------------------*/
5337 expDirRangePtr.i = fragrecptr.p->directory;
5338 texpReceivedBucket = (fragrecptr.p->maxp + fragrecptr.p->p) + 1; /* RECEIVED BUCKET */
5339 texpDirInd = texpReceivedBucket >> fragrecptr.p->k;
5340 newDirptr.i = RNIL;
5341 ptrNull(newDirptr);
5342 texpDirRangeIndex = texpDirInd >> 8;
5343 ptrCheckGuard(expDirRangePtr, cdirrangesize, dirRange);
5344 Uint32 max_dir_range_size = 256;
5345 if (ERROR_INSERTED(3002)) {
5346 debug_lh_vars("EXP");
5347 max_dir_range_size = 2;
5348 }
5349 if (texpDirRangeIndex >= max_dir_range_size) {
5350 jam();
5351 ndbrequire(texpDirRangeIndex == max_dir_range_size);
5352 if (fragrecptr.p->dirRangeFull == ZFALSE) {
5353 jam();
5354 fragrecptr.p->dirRangeFull = ZTRUE;
5355 }
5356 return;
5357 }
5358 expDirptr.i = expDirRangePtr.p->dirArray[texpDirRangeIndex];
5359 if (expDirptr.i == RNIL) {
5360 jam();
5361 seizeDirectory(signal);
5362 if (tresult > ZLIMIT_OF_ERROR) {
5363 jam();
5364 return;
5365 } else {
5366 jam();
5367 newDirptr = sdDirptr;
5368 expDirptr = sdDirptr;
5369 expDirRangePtr.p->dirArray[texpDirRangeIndex] = sdDirptr.i;
5370 }//if
5371 } else {
5372 ptrCheckGuard(expDirptr, cdirarraysize, directoryarray);
5373 }//if
5374 texpDirPageIndex = texpDirInd & 0xff;
5375 expPageptr.i = expDirptr.p->pagep[texpDirPageIndex];
5376 if (expPageptr.i == RNIL) {
5377 jam();
5378 seizePage(signal);
5379 if (tresult > ZLIMIT_OF_ERROR) {
5380 jam();
5381 if (newDirptr.i != RNIL) {
5382 jam();
5383 rdDirptr.i = newDirptr.i;
5384 releaseDirectory(signal);
5385 }//if
5386 return;
5387 }//if
5388 expDirptr.p->pagep[texpDirPageIndex] = spPageptr.i;
5389 tipPageId = texpDirInd;
5390 inpPageptr = spPageptr;
5391 initPage(signal);
5392 fragrecptr.p->dirsize++;
5393 expPageptr = spPageptr;
5394 } else {
5395 ptrCheckGuard(expPageptr, cpagesize, page8);
5396 }//if
5397
5398 fragrecptr.p->expReceivePageptr = expPageptr.i;
5399 fragrecptr.p->expReceiveIndex = texpReceivedBucket & ((1 << fragrecptr.p->k) - 1);
5400 /*--------------------------------------------------------------------------*/
5401 /* THE NEXT ACTION IS TO FIND THE PAGE, THE PAGE INDEX AND THE PAGE */
5402 /* DIRECTORY OF THE BUCKET TO BE SPLIT. */
5403 /*--------------------------------------------------------------------------*/
5404 expDirRangePtr.i = fragrecptr.p->directory;
5405 cexcPageindex = fragrecptr.p->p & ((1 << fragrecptr.p->k) - 1); /* PAGE INDEX OBS K = 6 */
5406 texpDirInd = fragrecptr.p->p >> fragrecptr.p->k; /* DIRECTORY INDEX OBS K = 6 */
5407 ptrCheckGuard(expDirRangePtr, cdirrangesize, dirRange);
5408 arrGuard((texpDirInd >> 8), 256);
5409 expDirptr.i = expDirRangePtr.p->dirArray[texpDirInd >> 8];
5410 ptrCheckGuard(expDirptr, cdirarraysize, directoryarray);
5411 excPageptr.i = expDirptr.p->pagep[texpDirInd & 0xff];
5412 fragrecptr.p->expSenderIndex = cexcPageindex;
5413 fragrecptr.p->expSenderPageptr = excPageptr.i;
5414 if (excPageptr.i == RNIL) {
5415 jam();
5416 endofexpLab(signal); /* EMPTY BUCKET */
5417 return;
5418 }//if
5419 fragrecptr.p->expReceiveForward = ZTRUE;
5420 ptrCheckGuard(excPageptr, cpagesize, page8);
5421 expandcontainer(signal);
5422 endofexpLab(signal);
5423 return;
5424 }//Dbacc::execEXPANDCHECK2()
5425
endofexpLab(Signal * signal)5426 void Dbacc::endofexpLab(Signal* signal)
5427 {
5428 fragrecptr.p->p++;
5429 fragrecptr.p->slack += fragrecptr.p->maxloadfactor;
5430 fragrecptr.p->expandCounter++;
5431 if (fragrecptr.p->p > fragrecptr.p->maxp) {
5432 jam();
5433 fragrecptr.p->maxp = (fragrecptr.p->maxp << 1) | 1;
5434 fragrecptr.p->lhdirbits++;
5435 fragrecptr.p->hashcheckbit++;
5436 fragrecptr.p->p = 0;
5437 }//if
5438 Uint32 noOfBuckets = (fragrecptr.p->maxp + 1) + fragrecptr.p->p;
5439 Uint32 Thysteres = fragrecptr.p->maxloadfactor - fragrecptr.p->minloadfactor;
5440 fragrecptr.p->slackCheck = noOfBuckets * Thysteres;
5441 if (fragrecptr.p->slack > (1u << 31)) {
5442 jam();
5443 /* IT MEANS THAT IF SLACK < ZERO */
5444 /* --------------------------------------------------------------------------------- */
5445 /* IT IS STILL NECESSARY TO EXPAND THE FRAGMENT EVEN MORE. START IT FROM HERE */
5446 /* WITHOUT WAITING FOR NEXT COMMIT ON THE FRAGMENT. */
5447 /* --------------------------------------------------------------------------------- */
5448 fragrecptr.p->expandFlag = 2;
5449 signal->theData[0] = fragrecptr.i;
5450 signal->theData[1] = fragrecptr.p->p;
5451 signal->theData[2] = fragrecptr.p->maxp;
5452 sendSignal(cownBlockref, GSN_EXPANDCHECK2, signal, 3, JBB);
5453 }//if
5454 return;
5455 }//Dbacc::endofexpLab()
5456
reenable_expand_after_redo_log_exection_complete(Signal * signal)5457 void Dbacc::reenable_expand_after_redo_log_exection_complete(Signal* signal){
5458
5459 tabptr.i = signal->theData[0];
5460 Uint32 fragId = signal->theData[1];
5461
5462 ptrCheckGuard(tabptr, ctablesize, tabrec);
5463 ndbrequire(getfragmentrec(signal, fragrecptr, fragId));
5464 #if 0
5465 ndbout_c("reenable expand check for table %d fragment: %d",
5466 tabptr.i, fragId);
5467 #endif
5468
5469 switch(fragrecptr.p->expandFlag){
5470 case 0:
5471 /**
5472 * Hmm... this means that it's alreay has been reenabled...
5473 */
5474 fragrecptr.p->expandFlag = 1;
5475 break;
5476 case 1:
5477 /**
5478 * Nothing is going on start expand check
5479 */
5480 case 2:
5481 /**
5482 * A shrink is running, do expand check anyway
5483 * (to reset expandFlag)
5484 */
5485 fragrecptr.p->expandFlag = 2;
5486 signal->theData[0] = fragrecptr.i;
5487 signal->theData[1] = fragrecptr.p->p;
5488 signal->theData[2] = fragrecptr.p->maxp;
5489 sendSignal(cownBlockref, GSN_EXPANDCHECK2, signal, 3, JBB);
5490 break;
5491 }
5492 }
5493
execDEBUG_SIG(Signal * signal)5494 void Dbacc::execDEBUG_SIG(Signal* signal)
5495 {
5496 jamEntry();
5497 expPageptr.i = signal->theData[0];
5498
5499 progError(__LINE__, NDBD_EXIT_SR_UNDOLOG);
5500 return;
5501 }//Dbacc::execDEBUG_SIG()
5502
5503 /* --------------------------------------------------------------------------------- */
5504 /* EXPANDCONTAINER */
5505 /* INPUT: EXC_PAGEPTR (POINTER TO THE ACTIVE PAGE RECORD) */
5506 /* CEXC_PAGEINDEX (INDEX OF THE BUCKET). */
5507 /* */
5508 /* DESCRIPTION: THE HASH VALUE OF ALL ELEMENTS IN THE CONTAINER WILL BE */
5509 /* CHECKED. SOME OF THIS ELEMENTS HAVE TO MOVE TO THE NEW CONTAINER */
5510 /* --------------------------------------------------------------------------------- */
expandcontainer(Signal * signal)5511 void Dbacc::expandcontainer(Signal* signal)
5512 {
5513 Uint32 texcHashvalue;
5514 Uint32 texcTmp;
5515 Uint32 texcIndex;
5516 Uint32 guard20;
5517
5518 cexcPrevpageptr = RNIL;
5519 cexcPrevconptr = 0;
5520 cexcForward = ZTRUE;
5521 EXP_CONTAINER_LOOP:
5522 cexcContainerptr = (cexcPageindex << ZSHIFT_PLUS) - (cexcPageindex << ZSHIFT_MINUS);
5523 if (cexcForward == ZTRUE) {
5524 jam();
5525 cexcContainerptr = cexcContainerptr + ZHEAD_SIZE;
5526 cexcElementptr = cexcContainerptr + ZCON_HEAD_SIZE;
5527 } else {
5528 jam();
5529 cexcContainerptr = ((cexcContainerptr + ZHEAD_SIZE) + ZBUF_SIZE) - ZCON_HEAD_SIZE;
5530 cexcElementptr = cexcContainerptr - 1;
5531 }//if
5532 arrGuard(cexcContainerptr, 2048);
5533 cexcContainerhead = excPageptr.p->word32[cexcContainerptr];
5534 cexcContainerlen = cexcContainerhead >> 26;
5535 cexcMovedLen = ZCON_HEAD_SIZE;
5536 if (cexcContainerlen <= ZCON_HEAD_SIZE) {
5537 ndbrequire(cexcContainerlen >= ZCON_HEAD_SIZE);
5538 jam();
5539 goto NEXT_ELEMENT;
5540 }//if
5541 NEXT_ELEMENT_LOOP:
5542 idrOperationRecPtr.i = RNIL;
5543 ptrNull(idrOperationRecPtr);
5544 /* --------------------------------------------------------------------------------- */
5545 /* CEXC_PAGEINDEX PAGE INDEX OF CURRENT CONTAINER BEING EXAMINED. */
5546 /* CEXC_CONTAINERPTR INDEX OF CURRENT CONTAINER BEING EXAMINED. */
5547 /* CEXC_ELEMENTPTR INDEX OF CURRENT ELEMENT BEING EXAMINED. */
5548 /* EXC_PAGEPTR PAGE WHERE CURRENT ELEMENT RESIDES. */
5549 /* CEXC_PREVPAGEPTR PAGE OF PREVIOUS CONTAINER. */
5550 /* CEXC_PREVCONPTR INDEX OF PREVIOUS CONTAINER */
5551 /* CEXC_FORWARD DIRECTION OF CURRENT CONTAINER */
5552 /* --------------------------------------------------------------------------------- */
5553 arrGuard(cexcElementptr, 2048);
5554 tidrElemhead = excPageptr.p->word32[cexcElementptr];
5555 if (ElementHeader::getUnlocked(tidrElemhead)){
5556 jam();
5557 texcHashvalue = ElementHeader::getHashValuePart(tidrElemhead);
5558 } else {
5559 jam();
5560 idrOperationRecPtr.i = ElementHeader::getOpPtrI(tidrElemhead);
5561 ptrCheckGuard(idrOperationRecPtr, coprecsize, operationrec);
5562 texcHashvalue = idrOperationRecPtr.p->hashvaluePart;
5563 }//if
5564 if (((texcHashvalue >> fragrecptr.p->hashcheckbit) & 1) == 0) {
5565 jam();
5566 /* --------------------------------------------------------------------------------- */
5567 /* THIS ELEMENT IS NOT TO BE MOVED. WE CALCULATE THE WHEREABOUTS OF THE NEXT */
5568 /* ELEMENT AND PROCEED WITH THAT OR END THE SEARCH IF THERE ARE NO MORE */
5569 /* ELEMENTS IN THIS CONTAINER. */
5570 /* --------------------------------------------------------------------------------- */
5571 goto NEXT_ELEMENT;
5572 }//if
5573 /* --------------------------------------------------------------------------------- */
5574 /* THE HASH BIT WAS SET AND WE SHALL MOVE THIS ELEMENT TO THE NEW BUCKET. */
5575 /* WE START BY READING THE ELEMENT TO BE ABLE TO INSERT IT INTO THE NEW BUCKET.*/
5576 /* THEN WE INSERT THE ELEMENT INTO THE NEW BUCKET. THE NEXT STEP IS TO DELETE */
5577 /* THE ELEMENT FROM THIS BUCKET. THIS IS PERFORMED BY REPLACING IT WITH THE */
5578 /* LAST ELEMENT IN THE BUCKET. IF THIS ELEMENT IS TO BE MOVED WE MOVE IT AND */
5579 /* GET THE LAST ELEMENT AGAIN UNTIL WE EITHER FIND ONE THAT STAYS OR THIS */
5580 /* ELEMENT IS THE LAST ELEMENT. */
5581 /* --------------------------------------------------------------------------------- */
5582 texcTmp = cexcElementptr + cexcForward;
5583 guard20 = fragrecptr.p->localkeylen - 1;
5584 for (texcIndex = 0; texcIndex <= guard20; texcIndex++) {
5585 arrGuard(texcIndex, 2);
5586 arrGuard(texcTmp, 2048);
5587 clocalkey[texcIndex] = excPageptr.p->word32[texcTmp];
5588 texcTmp = texcTmp + cexcForward;
5589 }//for
5590 tidrPageindex = fragrecptr.p->expReceiveIndex;
5591 idrPageptr.i = fragrecptr.p->expReceivePageptr;
5592 ptrCheckGuard(idrPageptr, cpagesize, page8);
5593 tidrForward = fragrecptr.p->expReceiveForward;
5594 insertElement(signal);
5595 fragrecptr.p->expReceiveIndex = tidrPageindex;
5596 fragrecptr.p->expReceivePageptr = idrPageptr.i;
5597 fragrecptr.p->expReceiveForward = tidrForward;
5598 REMOVE_LAST_LOOP:
5599 jam();
5600 lastPageptr.i = excPageptr.i;
5601 lastPageptr.p = excPageptr.p;
5602 tlastContainerptr = cexcContainerptr;
5603 lastPrevpageptr.i = cexcPrevpageptr;
5604 ptrCheck(lastPrevpageptr, cpagesize, page8);
5605 tlastPrevconptr = cexcPrevconptr;
5606 arrGuard(tlastContainerptr, 2048);
5607 tlastContainerhead = lastPageptr.p->word32[tlastContainerptr];
5608 tlastContainerlen = tlastContainerhead >> 26;
5609 tlastForward = cexcForward;
5610 tlastPageindex = cexcPageindex;
5611 getLastAndRemove(signal);
5612 if (excPageptr.i == lastPageptr.i) {
5613 if (cexcElementptr == tlastElementptr) {
5614 jam();
5615 /* --------------------------------------------------------------------------------- */
5616 /* THE CURRENT ELEMENT WAS ALSO THE LAST ELEMENT. */
5617 /* --------------------------------------------------------------------------------- */
5618 return;
5619 }//if
5620 }//if
5621 /* --------------------------------------------------------------------------------- */
5622 /* THE CURRENT ELEMENT WAS NOT THE LAST ELEMENT. IF THE LAST ELEMENT SHOULD */
5623 /* STAY WE COPY IT TO THE POSITION OF THE CURRENT ELEMENT, OTHERWISE WE INSERT */
5624 /* INTO THE NEW BUCKET, REMOVE IT AND TRY WITH THE NEW LAST ELEMENT. */
5625 /* --------------------------------------------------------------------------------- */
5626 idrOperationRecPtr.i = RNIL;
5627 ptrNull(idrOperationRecPtr);
5628 arrGuard(tlastElementptr, 2048);
5629 tidrElemhead = lastPageptr.p->word32[tlastElementptr];
5630 if (ElementHeader::getUnlocked(tidrElemhead)) {
5631 jam();
5632 texcHashvalue = ElementHeader::getHashValuePart(tidrElemhead);
5633 } else {
5634 jam();
5635 idrOperationRecPtr.i = ElementHeader::getOpPtrI(tidrElemhead);
5636 ptrCheckGuard(idrOperationRecPtr, coprecsize, operationrec);
5637 texcHashvalue = idrOperationRecPtr.p->hashvaluePart;
5638 }//if
5639 if (((texcHashvalue >> fragrecptr.p->hashcheckbit) & 1) == 0) {
5640 jam();
5641 /* --------------------------------------------------------------------------------- */
5642 /* THE LAST ELEMENT IS NOT TO BE MOVED. WE COPY IT TO THE CURRENT ELEMENT. */
5643 /* --------------------------------------------------------------------------------- */
5644 delPageptr = excPageptr;
5645 tdelContainerptr = cexcContainerptr;
5646 tdelForward = cexcForward;
5647 tdelElementptr = cexcElementptr;
5648 deleteElement(signal);
5649 } else {
5650 jam();
5651 /* --------------------------------------------------------------------------------- */
5652 /* THE LAST ELEMENT IS ALSO TO BE MOVED. */
5653 /* --------------------------------------------------------------------------------- */
5654 texcTmp = tlastElementptr + tlastForward;
5655 for (texcIndex = 0; texcIndex < fragrecptr.p->localkeylen; texcIndex++) {
5656 arrGuard(texcIndex, 2);
5657 arrGuard(texcTmp, 2048);
5658 clocalkey[texcIndex] = lastPageptr.p->word32[texcTmp];
5659 texcTmp = texcTmp + tlastForward;
5660 }//for
5661 tidrPageindex = fragrecptr.p->expReceiveIndex;
5662 idrPageptr.i = fragrecptr.p->expReceivePageptr;
5663 ptrCheckGuard(idrPageptr, cpagesize, page8);
5664 tidrForward = fragrecptr.p->expReceiveForward;
5665 insertElement(signal);
5666 fragrecptr.p->expReceiveIndex = tidrPageindex;
5667 fragrecptr.p->expReceivePageptr = idrPageptr.i;
5668 fragrecptr.p->expReceiveForward = tidrForward;
5669 goto REMOVE_LAST_LOOP;
5670 }//if
5671 NEXT_ELEMENT:
5672 arrGuard(cexcContainerptr, 2048);
5673 cexcContainerhead = excPageptr.p->word32[cexcContainerptr];
5674 cexcMovedLen = cexcMovedLen + fragrecptr.p->elementLength;
5675 if ((cexcContainerhead >> 26) > cexcMovedLen) {
5676 jam();
5677 /* --------------------------------------------------------------------------------- */
5678 /* WE HAVE NOT YET MOVED THE COMPLETE CONTAINER. WE PROCEED WITH THE NEXT */
5679 /* ELEMENT IN THE CONTAINER. IT IS IMPORTANT TO READ THE CONTAINER LENGTH */
5680 /* FROM THE CONTAINER HEADER SINCE IT MIGHT CHANGE BY REMOVING THE LAST */
5681 /* ELEMENT IN THE BUCKET. */
5682 /* --------------------------------------------------------------------------------- */
5683 cexcElementptr = cexcElementptr + (cexcForward * fragrecptr.p->elementLength);
5684 goto NEXT_ELEMENT_LOOP;
5685 }//if
5686 if (((cexcContainerhead >> 7) & 3) != 0) {
5687 jam();
5688 /* --------------------------------------------------------------------------------- */
5689 /* WE PROCEED TO THE NEXT CONTAINER IN THE BUCKET. */
5690 /* --------------------------------------------------------------------------------- */
5691 cexcPrevpageptr = excPageptr.i;
5692 cexcPrevconptr = cexcContainerptr;
5693 nextcontainerinfoExp(signal);
5694 goto EXP_CONTAINER_LOOP;
5695 }//if
5696 }//Dbacc::expandcontainer()
5697
5698 /* ******************--------------------------------------------------------------- */
5699 /* SHRINKCHECK JOIN BUCKET ORD */
5700 /* SENDER: ACC, LEVEL B */
5701 /* INPUT: FRAGRECPTR, POINTS TO A FRAGMENT RECORD. */
5702 /* DESCRIPTION: TWO BUCKET OF A FRAGMENT PAGE WILL BE JOINED TOGETHER */
5703 /* ACCORDING TO LH3. */
5704 /* ******************--------------------------------------------------------------- */
5705 /* ******************--------------------------------------------------------------- */
5706 /* SHRINKCHECK JOIN BUCKET ORD */
5707 /* ******************------------------------------+ */
5708 /* SENDER: ACC, LEVEL B */
5709 /* TWO BUCKETS OF THE FRAGMENT */
5710 /* WILL BE JOINED ACORDING TO LH3 */
5711 /* AND COMMIT TRANSACTION PROCESS */
5712 /* WILL BE CONTINUED */
checkScanShrink(Signal * signal)5713 Uint32 Dbacc::checkScanShrink(Signal* signal)
5714 {
5715 Uint32 Ti;
5716 Uint32 TreturnCode = 0;
5717 Uint32 TPageIndex;
5718 Uint32 TDirInd;
5719 Uint32 TmergeDest;
5720 Uint32 TmergeSource;
5721 Uint32 TreleaseScanBucket;
5722 Uint32 TreleaseInd = 0;
5723 Uint32 TreleaseScanIndicator[MAX_PARALLEL_SCANS_PER_FRAG];
5724 DirectoryarrayPtr TDirptr;
5725 DirRangePtr TDirRangePtr;
5726 Page8Ptr TPageptr;
5727 ScanRecPtr TscanPtr;
5728
5729 if (fragrecptr.p->p == 0) {
5730 jam();
5731 TmergeDest = fragrecptr.p->maxp >> 1;
5732 } else {
5733 jam();
5734 TmergeDest = fragrecptr.p->p - 1;
5735 }//if
5736 TmergeSource = fragrecptr.p->maxp + fragrecptr.p->p;
5737 for (Ti = 0; Ti < MAX_PARALLEL_SCANS_PER_FRAG; Ti++) {
5738 TreleaseScanIndicator[Ti] = 0;
5739 if (fragrecptr.p->scan[Ti] != RNIL) {
5740 TscanPtr.i = fragrecptr.p->scan[Ti];
5741 ptrCheckGuard(TscanPtr, cscanRecSize, scanRec);
5742 if (TscanPtr.p->activeLocalFrag == fragrecptr.i) {
5743 //-------------------------------------------------------------
5744 // A scan is ongoing on this particular local fragment. We have
5745 // to check its current state.
5746 //-------------------------------------------------------------
5747 if (TscanPtr.p->scanBucketState == ScanRec::FIRST_LAP) {
5748 jam();
5749 if ((TmergeDest == TscanPtr.p->nextBucketIndex) ||
5750 (TmergeSource == TscanPtr.p->nextBucketIndex)) {
5751 jam();
5752 //-------------------------------------------------------------
5753 // We are currently scanning one of the buckets involved in the
5754 // merge. We cannot merge while simultaneously performing a scan.
5755 // We have to pass this offer for merging the buckets.
5756 //-------------------------------------------------------------
5757 TreturnCode = 1;
5758 return TreturnCode;
5759 } else if (TmergeDest < TscanPtr.p->nextBucketIndex) {
5760 jam();
5761 TreleaseScanIndicator[Ti] = 1;
5762 TreleaseInd = 1;
5763 }//if
5764 } else if (TscanPtr.p->scanBucketState == ScanRec::SECOND_LAP) {
5765 jam();
5766 //-------------------------------------------------------------
5767 // We are performing a second lap to handle buckets that was
5768 // merged during the first lap of scanning. During this second
5769 // lap we do not allow any splits or merges.
5770 //-------------------------------------------------------------
5771 TreturnCode = 1;
5772 return TreturnCode;
5773 } else if (TscanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED) {
5774 jam();
5775 //-------------------------------------------------------------
5776 // The scan is completed and we can thus go ahead and perform
5777 // the split.
5778 //-------------------------------------------------------------
5779 } else {
5780 jam();
5781 sendSystemerror(signal, __LINE__);
5782 return TreturnCode;
5783 }//if
5784 }//if
5785 }//if
5786 }//for
5787 if (TreleaseInd == 1) {
5788 jam();
5789 TreleaseScanBucket = TmergeSource;
5790 TDirRangePtr.i = fragrecptr.p->directory;
5791 TPageIndex = TreleaseScanBucket & ((1 << fragrecptr.p->k) - 1); /* PAGE INDEX OBS K = 6 */
5792 TDirInd = TreleaseScanBucket >> fragrecptr.p->k; /* DIRECTORY INDEX OBS K = 6 */
5793 ptrCheckGuard(TDirRangePtr, cdirrangesize, dirRange);
5794 arrGuard((TDirInd >> 8), 256);
5795 TDirptr.i = TDirRangePtr.p->dirArray[TDirInd >> 8];
5796 ptrCheckGuard(TDirptr, cdirarraysize, directoryarray);
5797 TPageptr.i = TDirptr.p->pagep[TDirInd & 0xff];
5798 ptrCheckGuard(TPageptr, cpagesize, page8);
5799 for (Ti = 0; Ti < MAX_PARALLEL_SCANS_PER_FRAG; Ti++) {
5800 if (TreleaseScanIndicator[Ti] == 1) {
5801 jam();
5802 scanPtr.i = fragrecptr.p->scan[Ti];
5803 ptrCheckGuard(scanPtr, cscanRecSize, scanRec);
5804 rsbPageidptr.i = TPageptr.i;
5805 rsbPageidptr.p = TPageptr.p;
5806 trsbPageindex = TPageIndex;
5807 releaseScanBucket(signal);
5808 if (TmergeDest < scanPtr.p->minBucketIndexToRescan) {
5809 jam();
5810 //-------------------------------------------------------------
5811 // We have to keep track of the starting bucket to Rescan in the
5812 // second lap.
5813 //-------------------------------------------------------------
5814 scanPtr.p->minBucketIndexToRescan = TmergeDest;
5815 }//if
5816 if (TmergeDest > scanPtr.p->maxBucketIndexToRescan) {
5817 jam();
5818 //-------------------------------------------------------------
5819 // We have to keep track of the ending bucket to Rescan in the
5820 // second lap.
5821 //-------------------------------------------------------------
5822 scanPtr.p->maxBucketIndexToRescan = TmergeDest;
5823 }//if
5824 }//if
5825 }//for
5826 }//if
5827 return TreturnCode;
5828 }//Dbacc::checkScanShrink()
5829
execSHRINKCHECK2(Signal * signal)5830 void Dbacc::execSHRINKCHECK2(Signal* signal)
5831 {
5832 Uint32 tshrTmp1;
5833
5834 jamEntry();
5835 fragrecptr.i = signal->theData[0];
5836 Uint32 oldFlag = signal->theData[3];
5837 ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
5838 fragrecptr.p->expandFlag = oldFlag;
5839 tresult = 0; /* 0= FALSE,1= TRUE,> ZLIMIT_OF_ERROR =ERRORCODE */
5840 if (fragrecptr.p->slack <= fragrecptr.p->slackCheck) {
5841 jam();
5842 /* TIME FOR JOIN BUCKETS PROCESS */
5843 /*--------------------------------------------------------------*/
5844 /* NO LONGER NECESSARY TO SHRINK THE FRAGMENT. */
5845 /*--------------------------------------------------------------*/
5846 return;
5847 }//if
5848 if (fragrecptr.p->slack > (1u << 31)) {
5849 jam();
5850 /*--------------------------------------------------------------*/
5851 /* THE SLACK IS NEGATIVE, IN THIS CASE WE WILL NOT NEED ANY */
5852 /* SHRINK. */
5853 /*--------------------------------------------------------------*/
5854 return;
5855 }//if
5856 texpDirInd = (fragrecptr.p->maxp + fragrecptr.p->p) >> fragrecptr.p->k;
5857 if (fragrecptr.p->firstOverflowRec == RNIL) {
5858 jam();
5859 allocOverflowPage(signal);
5860 if (tresult > ZLIMIT_OF_ERROR) {
5861 jam();
5862 return;
5863 }//if
5864 }//if
5865 if (cfirstfreepage == RNIL)
5866 {
5867 jam();
5868 /*--------------------------------------------------------------*/
5869 /* WE HAVE TO STOP THE SHRINK PROCESS SINCE THERE ARE NO FREE */
5870 /* PAGES. THIS MEANS THAT WE COULD BE FORCED TO CRASH SINCE WE */
5871 /* CANNOT COMPLETE THE SHRINK. TO AVOID THE CRASH WE EXIT HERE. */
5872 /*--------------------------------------------------------------*/
5873 return;
5874 }//if
5875 if (checkScanShrink(signal) == 1) {
5876 jam();
5877 /*--------------------------------------------------------------*/
5878 // A scan state was inconsistent with performing a shrink
5879 // operation.
5880 /*--------------------------------------------------------------*/
5881 return;
5882 }//if
5883 if (fragrecptr.p->p == 0) {
5884 jam();
5885 fragrecptr.p->maxp = fragrecptr.p->maxp >> 1;
5886 fragrecptr.p->p = fragrecptr.p->maxp;
5887 fragrecptr.p->lhdirbits--;
5888 fragrecptr.p->hashcheckbit--;
5889 } else {
5890 jam();
5891 fragrecptr.p->p--;
5892 }//if
5893
5894 if (ERROR_INSERTED(3002))
5895 debug_lh_vars("SHR");
5896 if (fragrecptr.p->dirRangeFull == ZTRUE) {
5897 jam();
5898 fragrecptr.p->dirRangeFull = ZFALSE;
5899 }
5900
5901 /*--------------------------------------------------------------------------*/
5902 /* WE START BY FINDING THE NECESSARY INFORMATION OF THE BUCKET TO BE */
5903 /* REMOVED WHICH WILL SEND ITS ELEMENTS TO THE RECEIVING BUCKET. */
5904 /*--------------------------------------------------------------------------*/
5905 expDirRangePtr.i = fragrecptr.p->directory;
5906 cexcPageindex = ((fragrecptr.p->maxp + fragrecptr.p->p) + 1) & ((1 << fragrecptr.p->k) - 1);
5907 texpDirInd = ((fragrecptr.p->maxp + fragrecptr.p->p) + 1) >> fragrecptr.p->k;
5908 texpDirRangeIndex = texpDirInd >> 8;
5909 texpDirPageIndex = texpDirInd & 0xff;
5910 ptrCheckGuard(expDirRangePtr, cdirrangesize, dirRange);
5911 arrGuard(texpDirRangeIndex, 256);
5912 expDirptr.i = expDirRangePtr.p->dirArray[texpDirRangeIndex];
5913 ptrCheckGuard(expDirptr, cdirarraysize, directoryarray);
5914 excPageptr.i = expDirptr.p->pagep[texpDirPageIndex];
5915 fragrecptr.p->expSenderDirptr = expDirptr.i;
5916 fragrecptr.p->expSenderIndex = cexcPageindex;
5917 fragrecptr.p->expSenderPageptr = excPageptr.i;
5918 fragrecptr.p->expSenderDirIndex = texpDirInd;
5919 /*--------------------------------------------------------------------------*/
5920 /* WE NOW PROCEED BY FINDING THE NECESSARY INFORMATION ABOUT THE */
5921 /* RECEIVING BUCKET. */
5922 /*--------------------------------------------------------------------------*/
5923 expDirRangePtr.i = fragrecptr.p->directory;
5924 texpReceivedBucket = fragrecptr.p->p >> fragrecptr.p->k;
5925 ptrCheckGuard(expDirRangePtr, cdirrangesize, dirRange);
5926 arrGuard((texpReceivedBucket >> 8), 256);
5927 expDirptr.i = expDirRangePtr.p->dirArray[texpReceivedBucket >> 8];
5928 ptrCheckGuard(expDirptr, cdirarraysize, directoryarray);
5929 fragrecptr.p->expReceivePageptr = expDirptr.p->pagep[texpReceivedBucket & 0xff];
5930 fragrecptr.p->expReceiveIndex = fragrecptr.p->p & ((1 << fragrecptr.p->k) - 1);
5931 fragrecptr.p->expReceiveForward = ZTRUE;
5932 if (excPageptr.i == RNIL) {
5933 jam();
5934 endofshrinkbucketLab(signal); /* EMPTY BUCKET */
5935 return;
5936 }//if
5937 /*--------------------------------------------------------------------------*/
5938 /* INITIALISE THE VARIABLES FOR THE SHRINK PROCESS. */
5939 /*--------------------------------------------------------------------------*/
5940 ptrCheckGuard(excPageptr, cpagesize, page8);
5941 cexcForward = ZTRUE;
5942 cexcContainerptr = (cexcPageindex << ZSHIFT_PLUS) - (cexcPageindex << ZSHIFT_MINUS);
5943 cexcContainerptr = cexcContainerptr + ZHEAD_SIZE;
5944 arrGuard(cexcContainerptr, 2048);
5945 cexcContainerhead = excPageptr.p->word32[cexcContainerptr];
5946 cexcContainerlen = cexcContainerhead >> 26;
5947 if (cexcContainerlen <= ZCON_HEAD_SIZE) {
5948 ndbrequire(cexcContainerlen == ZCON_HEAD_SIZE);
5949 } else {
5950 jam();
5951 shrinkcontainer(signal);
5952 }//if
5953 /*--------------------------------------------------------------------------*/
5954 /* THIS CONTAINER IS NOT YET EMPTY AND WE REMOVE ALL THE ELEMENTS. */
5955 /*--------------------------------------------------------------------------*/
5956 if (((cexcContainerhead >> 10) & 1) == 1) {
5957 jam();
5958 rlPageptr = excPageptr;
5959 trlPageindex = cexcPageindex;
5960 trlRelCon = ZFALSE;
5961 turlIndex = cexcContainerptr + (ZBUF_SIZE - ZCON_HEAD_SIZE);
5962 releaseRightlist(signal);
5963 }//if
5964 tshrTmp1 = ZCON_HEAD_SIZE;
5965 tshrTmp1 = tshrTmp1 << 26;
5966 dbgWord32(excPageptr, cexcContainerptr, tshrTmp1);
5967 arrGuard(cexcContainerptr, 2048);
5968 excPageptr.p->word32[cexcContainerptr] = tshrTmp1;
5969 if (((cexcContainerhead >> 7) & 0x3) == 0) {
5970 jam();
5971 endofshrinkbucketLab(signal);
5972 return;
5973 }//if
5974 nextcontainerinfoExp(signal);
5975 do {
5976 cexcContainerptr = (cexcPageindex << ZSHIFT_PLUS) - (cexcPageindex << ZSHIFT_MINUS);
5977 if (cexcForward == ZTRUE) {
5978 jam();
5979 cexcContainerptr = cexcContainerptr + ZHEAD_SIZE;
5980 } else {
5981 jam();
5982 cexcContainerptr = ((cexcContainerptr + ZHEAD_SIZE) + ZBUF_SIZE) - ZCON_HEAD_SIZE;
5983 }//if
5984 arrGuard(cexcContainerptr, 2048);
5985 cexcContainerhead = excPageptr.p->word32[cexcContainerptr];
5986 cexcContainerlen = cexcContainerhead >> 26;
5987 ndbrequire(cexcContainerlen > ZCON_HEAD_SIZE);
5988 /*--------------------------------------------------------------------------*/
5989 /* THIS CONTAINER IS NOT YET EMPTY AND WE REMOVE ALL THE ELEMENTS. */
5990 /*--------------------------------------------------------------------------*/
5991 shrinkcontainer(signal);
5992 cexcPrevpageptr = excPageptr.i;
5993 cexcPrevpageindex = cexcPageindex;
5994 cexcPrevforward = cexcForward;
5995 if (((cexcContainerhead >> 7) & 0x3) != 0) {
5996 jam();
5997 /*--------------------------------------------------------------------------*/
5998 /* WE MUST CALL THE NEXT CONTAINER INFO ROUTINE BEFORE WE RELEASE THE */
5999 /* CONTAINER SINCE THE RELEASE WILL OVERWRITE THE NEXT POINTER. */
6000 /*--------------------------------------------------------------------------*/
6001 nextcontainerinfoExp(signal);
6002 }//if
6003 rlPageptr.i = cexcPrevpageptr;
6004 ptrCheckGuard(rlPageptr, cpagesize, page8);
6005 trlPageindex = cexcPrevpageindex;
6006 if (cexcPrevforward == ZTRUE) {
6007 jam();
6008 if (((cexcContainerhead >> 10) & 1) == 1) {
6009 jam();
6010 trlRelCon = ZFALSE;
6011 turlIndex = cexcContainerptr + (ZBUF_SIZE - ZCON_HEAD_SIZE);
6012 releaseRightlist(signal);
6013 }//if
6014 trlRelCon = ZTRUE;
6015 tullIndex = cexcContainerptr;
6016 releaseLeftlist(signal);
6017 } else {
6018 jam();
6019 if (((cexcContainerhead >> 10) & 1) == 1) {
6020 jam();
6021 trlRelCon = ZFALSE;
6022 tullIndex = cexcContainerptr - (ZBUF_SIZE - ZCON_HEAD_SIZE);
6023 releaseLeftlist(signal);
6024 }//if
6025 trlRelCon = ZTRUE;
6026 turlIndex = cexcContainerptr;
6027 releaseRightlist(signal);
6028 }//if
6029 } while (((cexcContainerhead >> 7) & 0x3) != 0);
6030 endofshrinkbucketLab(signal);
6031 return;
6032 }//Dbacc::execSHRINKCHECK2()
6033
endofshrinkbucketLab(Signal * signal)6034 void Dbacc::endofshrinkbucketLab(Signal* signal)
6035 {
6036 fragrecptr.p->expandCounter--;
6037 fragrecptr.p->slack -= fragrecptr.p->maxloadfactor;
6038 if (fragrecptr.p->expSenderIndex == 0) {
6039 jam();
6040 fragrecptr.p->dirsize--;
6041 if (fragrecptr.p->expSenderPageptr != RNIL) {
6042 jam();
6043 rpPageptr.i = fragrecptr.p->expSenderPageptr;
6044 ptrCheckGuard(rpPageptr, cpagesize, page8);
6045 releasePage(signal);
6046 expDirptr.i = fragrecptr.p->expSenderDirptr;
6047 ptrCheckGuard(expDirptr, cdirarraysize, directoryarray);
6048 expDirptr.p->pagep[fragrecptr.p->expSenderDirIndex & 0xff] = RNIL;
6049 }//if
6050 if (((((fragrecptr.p->p + fragrecptr.p->maxp) + 1) >> fragrecptr.p->k) & 0xff) == 0) {
6051 jam();
6052 rdDirptr.i = fragrecptr.p->expSenderDirptr;
6053 releaseDirectory(signal);
6054 expDirRangePtr.i = fragrecptr.p->directory;
6055 ptrCheckGuard(expDirRangePtr, cdirrangesize, dirRange);
6056 arrGuard((fragrecptr.p->expSenderDirIndex >> 8), 256);
6057 expDirRangePtr.p->dirArray[fragrecptr.p->expSenderDirIndex >> 8] = RNIL;
6058 }//if
6059 }//if
6060 if (fragrecptr.p->slack < (1u << 31)) {
6061 jam();
6062 /*--------------------------------------------------------------*/
6063 /* THE SLACK IS POSITIVE, IN THIS CASE WE WILL CHECK WHETHER */
6064 /* WE WILL CONTINUE PERFORM ANOTHER SHRINK. */
6065 /*--------------------------------------------------------------*/
6066 Uint32 noOfBuckets = (fragrecptr.p->maxp + 1) + fragrecptr.p->p;
6067 Uint32 Thysteresis = fragrecptr.p->maxloadfactor - fragrecptr.p->minloadfactor;
6068 fragrecptr.p->slackCheck = noOfBuckets * Thysteresis;
6069 if (fragrecptr.p->slack > Thysteresis) {
6070 /*--------------------------------------------------------------*/
6071 /* IT IS STILL NECESSARY TO SHRINK THE FRAGMENT MORE. THIS*/
6072 /* CAN HAPPEN WHEN A NUMBER OF SHRINKS GET REJECTED */
6073 /* DURING A LOCAL CHECKPOINT. WE START A NEW SHRINK */
6074 /* IMMEDIATELY FROM HERE WITHOUT WAITING FOR A COMMIT TO */
6075 /* START IT. */
6076 /*--------------------------------------------------------------*/
6077 if (fragrecptr.p->expandCounter > 0) {
6078 jam();
6079 /*--------------------------------------------------------------*/
6080 /* IT IS VERY IMPORTANT TO NOT TRY TO SHRINK MORE THAN */
6081 /* WAS EXPANDED. IF MAXP IS SET TO A VALUE BELOW 63 THEN */
6082 /* WE WILL LOSE RECORDS SINCE GETDIRINDEX CANNOT HANDLE */
6083 /* SHRINKING BELOW 2^K - 1 (NOW 63). THIS WAS A BUG THAT */
6084 /* WAS REMOVED 2000-05-12. */
6085 /*--------------------------------------------------------------*/
6086 signal->theData[0] = fragrecptr.i;
6087 signal->theData[1] = fragrecptr.p->p;
6088 signal->theData[2] = fragrecptr.p->maxp;
6089 signal->theData[3] = fragrecptr.p->expandFlag;
6090 ndbrequire(fragrecptr.p->expandFlag < 2);
6091 fragrecptr.p->expandFlag = 2;
6092 sendSignal(cownBlockref, GSN_SHRINKCHECK2, signal, 4, JBB);
6093 }//if
6094 }//if
6095 }//if
6096 ndbrequire(fragrecptr.p->maxp >= (Uint32)((1 << fragrecptr.p->k) - 1));
6097 return;
6098 }//Dbacc::endofshrinkbucketLab()
6099
6100 /* --------------------------------------------------------------------------------- */
6101 /* SHRINKCONTAINER */
6102 /* INPUT: EXC_PAGEPTR (POINTER TO THE ACTIVE PAGE RECORD) */
6103 /* CEXC_CONTAINERLEN (LENGTH OF THE CONTAINER). */
6104 /* CEXC_CONTAINERPTR (ARRAY INDEX OF THE CONTAINER). */
6105 /* CEXC_FORWARD (CONTAINER FORWARD (+1) OR BACKWARD (-1)) */
6106 /* */
6107 /* DESCRIPTION: ALL ELEMENTS OF THE ACTIVE CONTAINER HAVE TO MOVE TO THE NEW */
6108 /* CONTAINER. */
6109 /* --------------------------------------------------------------------------------- */
shrinkcontainer(Signal * signal)6110 void Dbacc::shrinkcontainer(Signal* signal)
6111 {
6112 Uint32 tshrElementptr;
6113 Uint32 tshrRemLen;
6114 Uint32 tshrInc;
6115 Uint32 tshrTmp;
6116 Uint32 tshrIndex;
6117 Uint32 guard21;
6118
6119 tshrRemLen = cexcContainerlen - ZCON_HEAD_SIZE;
6120 tshrInc = fragrecptr.p->elementLength;
6121 if (cexcForward == ZTRUE) {
6122 jam();
6123 tshrElementptr = cexcContainerptr + ZCON_HEAD_SIZE;
6124 } else {
6125 jam();
6126 tshrElementptr = cexcContainerptr - 1;
6127 }//if
6128 SHR_LOOP:
6129 idrOperationRecPtr.i = RNIL;
6130 ptrNull(idrOperationRecPtr);
6131 /* --------------------------------------------------------------------------------- */
6132 /* THE CODE BELOW IS ALL USED TO PREPARE FOR THE CALL TO INSERT_ELEMENT AND */
6133 /* HANDLE THE RESULT FROM INSERT_ELEMENT. INSERT_ELEMENT INSERTS THE ELEMENT */
6134 /* INTO ANOTHER BUCKET. */
6135 /* --------------------------------------------------------------------------------- */
6136 arrGuard(tshrElementptr, 2048);
6137 tidrElemhead = excPageptr.p->word32[tshrElementptr];
6138 if (ElementHeader::getLocked(tidrElemhead)) {
6139 jam();
6140 /* --------------------------------------------------------------------------------- */
6141 /* IF THE ELEMENT IS LOCKED WE MUST UPDATE THE ELEMENT INFO IN THE OPERATION */
6142 /* RECORD OWNING THE LOCK. WE DO THIS BY READING THE OPERATION RECORD POINTER */
6143 /* FROM THE ELEMENT HEADER. */
6144 /* --------------------------------------------------------------------------------- */
6145 idrOperationRecPtr.i = ElementHeader::getOpPtrI(tidrElemhead);
6146 ptrCheckGuard(idrOperationRecPtr, coprecsize, operationrec);
6147 }//if
6148 tshrTmp = tshrElementptr + cexcForward;
6149 guard21 = fragrecptr.p->localkeylen - 1;
6150 for (tshrIndex = 0; tshrIndex <= guard21; tshrIndex++) {
6151 arrGuard(tshrIndex, 2);
6152 arrGuard(tshrTmp, 2048);
6153 clocalkey[tshrIndex] = excPageptr.p->word32[tshrTmp];
6154 tshrTmp = tshrTmp + cexcForward;
6155 }//for
6156 tidrPageindex = fragrecptr.p->expReceiveIndex;
6157 idrPageptr.i = fragrecptr.p->expReceivePageptr;
6158 ptrCheckGuard(idrPageptr, cpagesize, page8);
6159 tidrForward = fragrecptr.p->expReceiveForward;
6160 insertElement(signal);
6161 /* --------------------------------------------------------------------------------- */
6162 /* TAKE CARE OF RESULT FROM INSERT_ELEMENT. */
6163 /* --------------------------------------------------------------------------------- */
6164 fragrecptr.p->expReceiveIndex = tidrPageindex;
6165 fragrecptr.p->expReceivePageptr = idrPageptr.i;
6166 fragrecptr.p->expReceiveForward = tidrForward;
6167 if (tshrRemLen < tshrInc) {
6168 jam();
6169 sendSystemerror(signal, __LINE__);
6170 }//if
6171 tshrRemLen = tshrRemLen - tshrInc;
6172 if (tshrRemLen != 0) {
6173 jam();
6174 tshrElementptr = tshrTmp;
6175 goto SHR_LOOP;
6176 }//if
6177 }//Dbacc::shrinkcontainer()
6178
6179 /* --------------------------------------------------------------------------------- */
6180 /* NEXTCONTAINERINFO_EXP */
6181 /* DESCRIPTION:THE CONTAINER HEAD WILL BE CHECKED TO CALCULATE INFORMATION */
6182 /* ABOUT NEXT CONTAINER IN THE BUCKET. */
6183 /* INPUT: CEXC_CONTAINERHEAD */
6184 /* CEXC_CONTAINERPTR */
6185 /* EXC_PAGEPTR */
6186 /* OUTPUT: */
6187 /* CEXC_PAGEINDEX (INDEX FROM WHICH PAGE INDEX CAN BE CALCULATED. */
6188 /* EXC_PAGEPTR (PAGE REFERENCE OF NEXT CONTAINER) */
6189 /* CEXC_FORWARD */
6190 /* --------------------------------------------------------------------------------- */
nextcontainerinfoExp(Signal * signal)6191 void Dbacc::nextcontainerinfoExp(Signal* signal)
6192 {
6193 tnciNextSamePage = (cexcContainerhead >> 9) & 0x1; /* CHECK BIT FOR CHECKING WHERE */
6194 /* THE NEXT CONTAINER IS IN THE SAME PAGE */
6195 cexcPageindex = cexcContainerhead & 0x7f; /* NEXT CONTAINER PAGE INDEX 7 BITS */
6196 if (((cexcContainerhead >> 7) & 3) == ZLEFT) {
6197 jam();
6198 cexcForward = ZTRUE;
6199 } else if (((cexcContainerhead >> 7) & 3) == ZRIGHT) {
6200 jam();
6201 cexcForward = cminusOne;
6202 } else {
6203 jam();
6204 sendSystemerror(signal, __LINE__);
6205 cexcForward = 0; /* DUMMY FOR COMPILER */
6206 }//if
6207 if (tnciNextSamePage == ZFALSE) {
6208 jam();
6209 /* NEXT CONTAINER IS IN AN OVERFLOW PAGE */
6210 arrGuard(cexcContainerptr + 1, 2048);
6211 tnciTmp = excPageptr.p->word32[cexcContainerptr + 1];
6212 nciOverflowrangeptr.i = fragrecptr.p->overflowdir;
6213 ptrCheckGuard(nciOverflowrangeptr, cdirrangesize, dirRange);
6214 arrGuard((tnciTmp >> 8), 256);
6215 nciOverflowDirptr.i = nciOverflowrangeptr.p->dirArray[tnciTmp >> 8];
6216 ptrCheckGuard(nciOverflowDirptr, cdirarraysize, directoryarray);
6217 excPageptr.i = nciOverflowDirptr.p->pagep[tnciTmp & 0xff];
6218 ptrCheckGuard(excPageptr, cpagesize, page8);
6219 }//if
6220 }//Dbacc::nextcontainerinfoExp()
6221
initFragAdd(Signal * signal,FragmentrecPtr regFragPtr)6222 void Dbacc::initFragAdd(Signal* signal,
6223 FragmentrecPtr regFragPtr)
6224 {
6225 const AccFragReq * const req = (AccFragReq*)&signal->theData[0];
6226 Uint32 lhFragBits = req->lhFragBits + 1;
6227 Uint32 minLoadFactor = (req->minLoadFactor * ZBUF_SIZE) / 100;
6228 Uint32 maxLoadFactor = (req->maxLoadFactor * ZBUF_SIZE) / 100;
6229 if (minLoadFactor >= maxLoadFactor) {
6230 jam();
6231 minLoadFactor = maxLoadFactor - 1;
6232 }//if
6233 regFragPtr.p->fragState = ACTIVEFRAG;
6234 // NOTE: next line must match calculation in Dblqh::execLQHFRAGREQ
6235 regFragPtr.p->myfid = req->fragId;
6236 regFragPtr.p->myTableId = req->tableId;
6237 ndbrequire(req->kValue == 6);
6238 regFragPtr.p->k = req->kValue; /* TK_SIZE = 6 IN THIS VERSION */
6239 regFragPtr.p->expandCounter = 0;
6240
6241 /**
6242 * Only allow shrink during SR
6243 * - to make sure we don't run out of pages during REDO log execution
6244 *
6245 * Is later restored to 0 by LQH at end of REDO log execution
6246 */
6247 regFragPtr.p->expandFlag = 0;
6248 regFragPtr.p->p = 0;
6249 regFragPtr.p->maxp = (1 << req->kValue) - 1;
6250 regFragPtr.p->minloadfactor = minLoadFactor;
6251 regFragPtr.p->maxloadfactor = maxLoadFactor;
6252 regFragPtr.p->slack = (regFragPtr.p->maxp + 1) * maxLoadFactor;
6253 regFragPtr.p->lhfragbits = lhFragBits;
6254 regFragPtr.p->lhdirbits = 0;
6255 regFragPtr.p->hashcheckbit = 0; //lhFragBits;
6256 regFragPtr.p->localkeylen = req->localKeyLen;
6257 regFragPtr.p->nodetype = (req->reqInfo >> 4) & 0x3;
6258 regFragPtr.p->lastOverIndex = 0;
6259 regFragPtr.p->dirsize = 1;
6260 regFragPtr.p->keyLength = req->keyLength;
6261 ndbrequire(req->keyLength != 0);
6262 regFragPtr.p->elementLength = ZELEM_HEAD_SIZE + regFragPtr.p->localkeylen;
6263 Uint32 Tmp1 = (regFragPtr.p->maxp + 1) + regFragPtr.p->p;
6264 Uint32 Tmp2 = regFragPtr.p->maxloadfactor - regFragPtr.p->minloadfactor;
6265 Tmp2 = Tmp1 * Tmp2;
6266 regFragPtr.p->slackCheck = Tmp2;
6267 regFragPtr.p->mytabptr = req->tableId;
6268 regFragPtr.p->roothashcheck = req->kValue + req->lhFragBits;
6269 regFragPtr.p->noOfElements = 0;
6270 regFragPtr.p->m_commit_count = 0; // stable results
6271 for (Uint32 i = 0; i < MAX_PARALLEL_SCANS_PER_FRAG; i++) {
6272 regFragPtr.p->scan[i] = RNIL;
6273 }//for
6274
6275 Uint32 hasCharAttr = g_key_descriptor_pool.getPtr(req->tableId)->hasCharAttr;
6276 regFragPtr.p->hasCharAttr = hasCharAttr;
6277 }//Dbacc::initFragAdd()
6278
initFragGeneral(FragmentrecPtr regFragPtr)6279 void Dbacc::initFragGeneral(FragmentrecPtr regFragPtr)
6280 {
6281 regFragPtr.p->directory = RNIL;
6282 regFragPtr.p->overflowdir = RNIL;
6283 regFragPtr.p->firstOverflowRec = RNIL;
6284 regFragPtr.p->lastOverflowRec = RNIL;
6285 regFragPtr.p->lockOwnersList = RNIL;
6286 regFragPtr.p->firstFreeDirindexRec = RNIL;
6287
6288 regFragPtr.p->activeDataPage = 0;
6289 regFragPtr.p->hasCharAttr = ZFALSE;
6290 regFragPtr.p->dirRangeFull = ZFALSE;
6291 regFragPtr.p->nextAllocPage = 0;
6292 regFragPtr.p->fragState = FREEFRAG;
6293 }//Dbacc::initFragGeneral()
6294
6295
6296 void
releaseLogicalPage(Fragmentrec * fragP,Uint32 logicalPageId)6297 Dbacc::releaseLogicalPage(Fragmentrec * fragP, Uint32 logicalPageId){
6298 Ptr<struct DirRange> dirRangePtr;
6299 dirRangePtr.i = fragP->directory;
6300 ptrCheckGuard(dirRangePtr, cdirrangesize, dirRange);
6301
6302 const Uint32 lp1 = logicalPageId >> 8;
6303 const Uint32 lp2 = logicalPageId & 0xFF;
6304 ndbrequire(lp1 < 256);
6305
6306 Ptr<struct Directoryarray> dirArrPtr;
6307 dirArrPtr.i = dirRangePtr.p->dirArray[lp1];
6308 ptrCheckGuard(dirArrPtr, cdirarraysize, directoryarray);
6309
6310 const Uint32 physicalPageId = dirArrPtr.p->pagep[lp2];
6311
6312 rpPageptr.i = physicalPageId;
6313 ptrCheckGuard(rpPageptr, cpagesize, page8);
6314 releasePage(0);
6315
6316 dirArrPtr.p->pagep[lp2] = RNIL;
6317 }
6318
execACC_SCANREQ(Signal * signal)6319 void Dbacc::execACC_SCANREQ(Signal* signal)
6320 {
6321 jamEntry();
6322 AccScanReq * req = (AccScanReq*)&signal->theData[0];
6323 tuserptr = req->senderData;
6324 tuserblockref = req->senderRef;
6325 tabptr.i = req->tableId;
6326 tfid = req->fragmentNo;
6327 tscanFlag = req->requestInfo;
6328 tscanTrid1 = req->transId1;
6329 tscanTrid2 = req->transId2;
6330
6331 tresult = 0;
6332 ptrCheckGuard(tabptr, ctablesize, tabrec);
6333 ndbrequire(getfragmentrec(signal, fragrecptr, tfid));
6334
6335 Uint32 i;
6336 for (i = 0; i < MAX_PARALLEL_SCANS_PER_FRAG; i++) {
6337 jam();
6338 if (fragrecptr.p->scan[i] == RNIL) {
6339 jam();
6340 break;
6341 }
6342 }
6343 ndbrequire(i != MAX_PARALLEL_SCANS_PER_FRAG);
6344 ndbrequire(cfirstFreeScanRec != RNIL);
6345 seizeScanRec(signal);
6346
6347 fragrecptr.p->scan[i] = scanPtr.i;
6348 scanPtr.p->scanBucketState = ScanRec::FIRST_LAP;
6349 scanPtr.p->scanLockMode = AccScanReq::getLockMode(tscanFlag);
6350 scanPtr.p->scanReadCommittedFlag = AccScanReq::getReadCommittedFlag(tscanFlag);
6351
6352 /* TWELVE BITS OF THE ELEMENT HEAD ARE SCAN */
6353 /* CHECK BITS. THE MASK NOTES WHICH BIT IS */
6354 /* ALLOCATED FOR THE ACTIVE SCAN */
6355 scanPtr.p->scanMask = 1 << i;
6356 scanPtr.p->scanUserptr = tuserptr;
6357 scanPtr.p->scanUserblockref = tuserblockref;
6358 scanPtr.p->scanTrid1 = tscanTrid1;
6359 scanPtr.p->scanTrid2 = tscanTrid2;
6360 scanPtr.p->scanLockHeld = 0;
6361 scanPtr.p->scanOpsAllocated = 0;
6362 scanPtr.p->scanFirstActiveOp = RNIL;
6363 scanPtr.p->scanFirstQueuedOp = RNIL;
6364 scanPtr.p->scanLastQueuedOp = RNIL;
6365 scanPtr.p->scanFirstLockedOp = RNIL;
6366 scanPtr.p->scanLastLockedOp = RNIL;
6367 scanPtr.p->scanState = ScanRec::WAIT_NEXT;
6368 initScanFragmentPart(signal);
6369
6370 /* ************************ */
6371 /* ACC_SCANCONF */
6372 /* ************************ */
6373 signal->theData[0] = scanPtr.p->scanUserptr;
6374 signal->theData[1] = scanPtr.i;
6375 signal->theData[2] = 1; /* NR OF LOCAL FRAGMENT */
6376 signal->theData[3] = fragrecptr.p->fragmentid;
6377 signal->theData[4] = RNIL;
6378 signal->theData[7] = AccScanConf::ZNOT_EMPTY_FRAGMENT;
6379 sendSignal(scanPtr.p->scanUserblockref, GSN_ACC_SCANCONF, signal, 8, JBB);
6380 /* NOT EMPTY FRAGMENT */
6381 return;
6382 }//Dbacc::execACC_SCANREQ()
6383
6384 /* ******************--------------------------------------------------------------- */
6385 /* NEXT_SCANREQ REQUEST FOR NEXT ELEMENT OF */
6386 /* ******************------------------------------+ A FRAGMENT. */
6387 /* SENDER: LQH, LEVEL B */
execNEXT_SCANREQ(Signal * signal)6388 void Dbacc::execNEXT_SCANREQ(Signal* signal)
6389 {
6390 Uint32 tscanNextFlag;
6391 jamEntry();
6392 scanPtr.i = signal->theData[0];
6393 operationRecPtr.i = signal->theData[1];
6394 tscanNextFlag = signal->theData[2];
6395 /* ------------------------------------------ */
6396 /* 1 = ZCOPY_NEXT GET NEXT ELEMENT */
6397 /* 2 = ZCOPY_NEXT_COMMIT COMMIT THE */
6398 /* ACTIVE ELEMENT AND GET THE NEXT ONE */
6399 /* 3 = ZCOPY_COMMIT COMMIT THE ACTIVE ELEMENT */
6400 /* 4 = ZCOPY_REPEAT GET THE ACTIVE ELEMENT */
6401 /* 5 = ZCOPY_ABORT RELOCK THE ACTIVE ELEMENT */
6402 /* 6 = ZCOPY_CLOSE THE SCAN PROCESS IS READY */
6403 /* ------------------------------------------ */
6404 tresult = 0;
6405 ptrCheckGuard(scanPtr, cscanRecSize, scanRec);
6406 ndbrequire(scanPtr.p->scanState == ScanRec::WAIT_NEXT);
6407
6408 switch (tscanNextFlag) {
6409 case NextScanReq::ZSCAN_NEXT:
6410 jam();
6411 /*empty*/;
6412 break;
6413 case NextScanReq::ZSCAN_NEXT_COMMIT:
6414 case NextScanReq::ZSCAN_COMMIT:
6415 jam();
6416 /* --------------------------------------------------------------------- */
6417 /* COMMIT ACTIVE OPERATION.
6418 * SEND NEXT SCAN ELEMENT IF IT IS ZCOPY_NEXT_COMMIT.
6419 * --------------------------------------------------------------------- */
6420 ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
6421 fragrecptr.i = operationRecPtr.p->fragptr;
6422 ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
6423 if (!scanPtr.p->scanReadCommittedFlag) {
6424 commitOperation(signal);
6425 }//if
6426 operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
6427 takeOutActiveScanOp(signal);
6428 releaseOpRec(signal);
6429 scanPtr.p->scanOpsAllocated--;
6430 if (tscanNextFlag == NextScanReq::ZSCAN_COMMIT) {
6431 jam();
6432 signal->theData[0] = scanPtr.p->scanUserptr;
6433 Uint32 blockNo = refToMain(scanPtr.p->scanUserblockref);
6434 EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 1);
6435 return;
6436 }//if
6437 break;
6438 case NextScanReq::ZSCAN_CLOSE:
6439 jam();
6440 fragrecptr.i = scanPtr.p->activeLocalFrag;
6441 ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
6442 /* ---------------------------------------------------------------------
6443 * THE SCAN PROCESS IS FINISHED. RELOCK ALL LOCKED EL.
6444 * RELESE ALL INVOLVED REC.
6445 * ------------------------------------------------------------------- */
6446 releaseScanLab(signal);
6447 return;
6448 break;
6449 default:
6450 ndbrequire(false);
6451 break;
6452 }//switch
6453 signal->theData[0] = scanPtr.i;
6454 signal->theData[1] = AccCheckScan::ZNOT_CHECK_LCP_STOP;
6455 execACC_CHECK_SCAN(signal);
6456 return;
6457 }//Dbacc::execNEXT_SCANREQ()
6458
checkNextBucketLab(Signal * signal)6459 void Dbacc::checkNextBucketLab(Signal* signal)
6460 {
6461 DirRangePtr cscDirRangePtr;
6462 DirectoryarrayPtr cscDirptr;
6463 DirectoryarrayPtr tnsDirptr;
6464 Page8Ptr nsPageptr;
6465 Page8Ptr cscPageidptr;
6466 Page8Ptr gnsPageidptr;
6467 Page8Ptr tnsPageidptr;
6468 Uint32 tnsElementptr;
6469 Uint32 tnsContainerptr;
6470 Uint32 tnsIsLocked;
6471 Uint32 tnsTmp1;
6472 Uint32 tnsTmp2;
6473 Uint32 tnsCopyIndex1;
6474 Uint32 tnsCopyIndex2;
6475 Uint32 tnsCopyDir;
6476
6477 tnsCopyDir = scanPtr.p->nextBucketIndex >> fragrecptr.p->k;
6478 tnsCopyIndex1 = tnsCopyDir >> 8;
6479 tnsCopyIndex2 = tnsCopyDir & 0xff;
6480 arrGuard(tnsCopyIndex1, 256);
6481 tnsDirptr.i = gnsDirRangePtr.p->dirArray[tnsCopyIndex1];
6482 ptrCheckGuard(tnsDirptr, cdirarraysize, directoryarray);
6483 tnsPageidptr.i = tnsDirptr.p->pagep[tnsCopyIndex2];
6484 ptrCheckGuard(tnsPageidptr, cpagesize, page8);
6485 gnsPageidptr.i = tnsPageidptr.i;
6486 gnsPageidptr.p = tnsPageidptr.p;
6487 tnsTmp1 = (1 << fragrecptr.p->k) - 1;
6488 tgsePageindex = scanPtr.p->nextBucketIndex & tnsTmp1;
6489 gsePageidptr.i = gnsPageidptr.i;
6490 gsePageidptr.p = gnsPageidptr.p;
6491 if (!getScanElement(signal)) {
6492 scanPtr.p->nextBucketIndex++;
6493 if (scanPtr.p->scanBucketState == ScanRec::SECOND_LAP) {
6494 if (scanPtr.p->nextBucketIndex > scanPtr.p->maxBucketIndexToRescan) {
6495 /* ---------------------------------------------------------------- */
6496 // We have finished the rescan phase.
6497 // We are ready to proceed with the next fragment part.
6498 /* ---------------------------------------------------------------- */
6499 jam();
6500 checkNextFragmentLab(signal);
6501 return;
6502 }//if
6503 } else if (scanPtr.p->scanBucketState == ScanRec::FIRST_LAP) {
6504 if ((fragrecptr.p->p + fragrecptr.p->maxp) < scanPtr.p->nextBucketIndex) {
6505 /* ---------------------------------------------------------------- */
6506 // All buckets have been scanned a first time.
6507 /* ---------------------------------------------------------------- */
6508 if (scanPtr.p->minBucketIndexToRescan == 0xFFFFFFFF) {
6509 jam();
6510 /* -------------------------------------------------------------- */
6511 // We have not had any merges behind the scan.
6512 // Thus it is not necessary to perform any rescan any buckets
6513 // and we can proceed immediately with the next fragment part.
6514 /* --------------------------------------------------------------- */
6515 checkNextFragmentLab(signal);
6516 return;
6517 } else {
6518 jam();
6519 /* --------------------------------------------------------------------------------- */
6520 // Some buckets are in the need of rescanning due to merges that have moved records
6521 // from in front of the scan to behind the scan. During the merges we kept track of
6522 // which buckets that need a rescan. We start with the minimum and end with maximum.
6523 /* --------------------------------------------------------------------------------- */
6524 scanPtr.p->nextBucketIndex = scanPtr.p->minBucketIndexToRescan;
6525 scanPtr.p->scanBucketState = ScanRec::SECOND_LAP;
6526 if (scanPtr.p->maxBucketIndexToRescan > (fragrecptr.p->p + fragrecptr.p->maxp)) {
6527 jam();
6528 /* --------------------------------------------------------------------------------- */
6529 // If we have had so many merges that the maximum is bigger than the number of buckets
6530 // then we will simply satisfy ourselves with scanning to the end. This can only happen
6531 // after bringing down the total of buckets to less than half and the minimum should
6532 // be 0 otherwise there is some problem.
6533 /* --------------------------------------------------------------------------------- */
6534 if (scanPtr.p->minBucketIndexToRescan != 0) {
6535 jam();
6536 sendSystemerror(signal, __LINE__);
6537 return;
6538 }//if
6539 scanPtr.p->maxBucketIndexToRescan = fragrecptr.p->p + fragrecptr.p->maxp;
6540 }//if
6541 }//if
6542 }//if
6543 }//if
6544 if ((scanPtr.p->scanBucketState == ScanRec::FIRST_LAP) &&
6545 (scanPtr.p->nextBucketIndex <= scanPtr.p->startNoOfBuckets)) {
6546 /* --------------------------------------------------------------------------------- */
6547 // We will only reset the scan indicator on the buckets that existed at the start of the
6548 // scan. The others will be handled by the split and merge code.
6549 /* --------------------------------------------------------------------------------- */
6550 tnsTmp2 = (1 << fragrecptr.p->k) - 1;
6551 trsbPageindex = scanPtr.p->nextBucketIndex & tnsTmp2;
6552 if (trsbPageindex != 0) {
6553 jam();
6554 rsbPageidptr.i = gnsPageidptr.i;
6555 rsbPageidptr.p = gnsPageidptr.p;
6556 } else {
6557 jam();
6558 cscDirRangePtr.i = fragrecptr.p->directory;
6559 tmpP = scanPtr.p->nextBucketIndex >> fragrecptr.p->k;
6560 tmpP2 = tmpP >> 8;
6561 tmpP = tmpP & 0xff;
6562 ptrCheckGuard(cscDirRangePtr, cdirrangesize, dirRange);
6563 arrGuard(tmpP2, 256);
6564 cscDirptr.i = cscDirRangePtr.p->dirArray[tmpP2];
6565 ptrCheckGuard(cscDirptr, cdirarraysize, directoryarray);
6566 cscPageidptr.i = cscDirptr.p->pagep[tmpP];
6567 ptrCheckGuard(cscPageidptr, cpagesize, page8);
6568 tmp1 = (1 << fragrecptr.p->k) - 1;
6569 trsbPageindex = scanPtr.p->nextBucketIndex & tmp1;
6570 rsbPageidptr.i = cscPageidptr.i;
6571 rsbPageidptr.p = cscPageidptr.p;
6572 }//if
6573 releaseScanBucket(signal);
6574 }//if
6575 signal->theData[0] = scanPtr.i;
6576 signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
6577 sendSignal(cownBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB);
6578 return;
6579 }//if
6580 /* ----------------------------------------------------------------------- */
6581 /* AN ELEMENT WHICH HAVE NOT BEEN SCANNED WAS FOUND. WE WILL PREPARE IT */
6582 /* TO BE SENT TO THE LQH BLOCK FOR FURTHER PROCESSING. */
6583 /* WE ASSUME THERE ARE OPERATION RECORDS AVAILABLE SINCE LQH SHOULD HAVE*/
6584 /* GUARANTEED THAT THROUGH EARLY BOOKING. */
6585 /* ----------------------------------------------------------------------- */
6586 tnsIsLocked = tgseIsLocked;
6587 tnsElementptr = tgseElementptr;
6588 tnsContainerptr = tgseContainerptr;
6589 nsPageptr.i = gsePageidptr.i;
6590 nsPageptr.p = gsePageidptr.p;
6591 seizeOpRec(signal);
6592 tisoIsforward = tgseIsforward;
6593 tisoContainerptr = tnsContainerptr;
6594 tisoElementptr = tnsElementptr;
6595 isoPageptr.i = nsPageptr.i;
6596 isoPageptr.p = nsPageptr.p;
6597 initScanOpRec(signal);
6598
6599 if (!tnsIsLocked){
6600 if (!scanPtr.p->scanReadCommittedFlag) {
6601 jam();
6602 slPageidptr = nsPageptr;
6603 tslElementptr = tnsElementptr;
6604 setlock(signal);
6605 insertLockOwnersList(signal, operationRecPtr);
6606 operationRecPtr.p->m_op_bits |=
6607 Operationrec::OP_STATE_RUNNING | Operationrec::OP_RUN_QUEUE;
6608 }//if
6609 } else {
6610 arrGuard(tnsElementptr, 2048);
6611 queOperPtr.i =
6612 ElementHeader::getOpPtrI(nsPageptr.p->word32[tnsElementptr]);
6613 ptrCheckGuard(queOperPtr, coprecsize, operationrec);
6614 if (queOperPtr.p->m_op_bits & Operationrec::OP_ELEMENT_DISAPPEARED ||
6615 Local_key::isInvalid(queOperPtr.p->localdata[0],
6616 queOperPtr.p->localdata[1]))
6617 {
6618 jam();
6619 /* ------------------------------------------------------------------ */
6620 // If the lock owner indicates the element is disappeared then
6621 // we will not report this tuple. We will continue with the next tuple.
6622 /* ------------------------------------------------------------------ */
6623 operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
6624 releaseOpRec(signal);
6625 scanPtr.p->scanOpsAllocated--;
6626 signal->theData[0] = scanPtr.i;
6627 signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
6628 sendSignal(cownBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB);
6629 return;
6630 }//if
6631 if (!scanPtr.p->scanReadCommittedFlag) {
6632 Uint32 return_result;
6633 if (scanPtr.p->scanLockMode == ZREADLOCK) {
6634 jam();
6635 return_result = placeReadInLockQueue(queOperPtr);
6636 } else {
6637 jam();
6638 return_result = placeWriteInLockQueue(queOperPtr);
6639 }//if
6640 if (return_result == ZSERIAL_QUEUE) {
6641 /* -----------------------------------------------------------------
6642 * WE PLACED THE OPERATION INTO A SERIAL QUEUE AND THUS WE HAVE TO
6643 * WAIT FOR THE LOCK TO BE RELEASED. WE CONTINUE WITH THE NEXT ELEMENT
6644 * ----------------------------------------------------------------- */
6645 putOpScanLockQue(); /* PUT THE OP IN A QUE IN THE SCAN REC */
6646 signal->theData[0] = scanPtr.i;
6647 signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
6648 sendSignal(cownBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB);
6649 return;
6650 } else if (return_result != ZPARALLEL_QUEUE) {
6651 jam();
6652 /* ----------------------------------------------------------------- */
6653 // The tuple is either not committed yet or a delete in
6654 // the same transaction (not possible here since we are a scan).
6655 // Thus we simply continue with the next tuple.
6656 /* ----------------------------------------------------------------- */
6657 operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
6658 releaseOpRec(signal);
6659 scanPtr.p->scanOpsAllocated--;
6660 signal->theData[0] = scanPtr.i;
6661 signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
6662 sendSignal(cownBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB);
6663 return;
6664 }//if
6665 ndbassert(return_result == ZPARALLEL_QUEUE);
6666 }//if
6667 }//if
6668 /* ----------------------------------------------------------------------- */
6669 // Committed read proceed without caring for locks immediately
6670 // down here except when the tuple was deleted permanently
6671 // and no new operation has inserted it again.
6672 /* ----------------------------------------------------------------------- */
6673 putActiveScanOp(signal);
6674 sendNextScanConf(signal);
6675 return;
6676 }//Dbacc::checkNextBucketLab()
6677
6678
checkNextFragmentLab(Signal * signal)6679 void Dbacc::checkNextFragmentLab(Signal* signal)
6680 {
6681 scanPtr.p->scanBucketState = ScanRec::SCAN_COMPLETED;
6682 // The scan is completed. ACC_CHECK_SCAN will perform all the necessary
6683 // checks to see
6684 // what the next step is.
6685 signal->theData[0] = scanPtr.i;
6686 signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
6687 execACC_CHECK_SCAN(signal);
6688 return;
6689 }//Dbacc::checkNextFragmentLab()
6690
initScanFragmentPart(Signal * signal)6691 void Dbacc::initScanFragmentPart(Signal* signal)
6692 {
6693 DirRangePtr cnfDirRangePtr;
6694 DirectoryarrayPtr cnfDirptr;
6695 Page8Ptr cnfPageidptr;
6696 /* ----------------------------------------------------------------------- */
6697 // Set the active fragment part.
6698 // Set the current bucket scanned to the first.
6699 // Start with the first lap.
6700 // Remember the number of buckets at start of the scan.
6701 // Set the minimum and maximum to values that will always be smaller and
6702 // larger than.
6703 // Reset the scan indicator on the first bucket.
6704 /* ----------------------------------------------------------------------- */
6705 scanPtr.p->activeLocalFrag = fragrecptr.i;
6706 scanPtr.p->nextBucketIndex = 0; /* INDEX OF SCAN BUCKET */
6707 scanPtr.p->scanBucketState = ScanRec::FIRST_LAP;
6708 scanPtr.p->startNoOfBuckets = fragrecptr.p->p + fragrecptr.p->maxp;
6709 scanPtr.p->minBucketIndexToRescan = 0xFFFFFFFF;
6710 scanPtr.p->maxBucketIndexToRescan = 0;
6711 cnfDirRangePtr.i = fragrecptr.p->directory;
6712 ptrCheckGuard(cnfDirRangePtr, cdirrangesize, dirRange);
6713 cnfDirptr.i = cnfDirRangePtr.p->dirArray[0];
6714 ptrCheckGuard(cnfDirptr, cdirarraysize, directoryarray);
6715 cnfPageidptr.i = cnfDirptr.p->pagep[0];
6716 ptrCheckGuard(cnfPageidptr, cpagesize, page8);
6717 trsbPageindex = scanPtr.p->nextBucketIndex & ((1 << fragrecptr.p->k) - 1);
6718 rsbPageidptr.i = cnfPageidptr.i;
6719 rsbPageidptr.p = cnfPageidptr.p;
6720 releaseScanBucket(signal);
6721 }//Dbacc::initScanFragmentPart()
6722
6723 /* -------------------------------------------------------------------------
6724 * FLAG = 6 = ZCOPY_CLOSE THE SCAN PROCESS IS READY OR ABORTED.
6725 * ALL OPERATION IN THE ACTIVE OR WAIT QUEUE ARE RELEASED,
6726 * SCAN FLAG OF ROOT FRAG IS RESET AND THE SCAN RECORD IS RELEASED.
6727 * ------------------------------------------------------------------------ */
releaseScanLab(Signal * signal)6728 void Dbacc::releaseScanLab(Signal* signal)
6729 {
6730 releaseAndCommitActiveOps(signal);
6731 releaseAndCommitQueuedOps(signal);
6732 releaseAndAbortLockedOps(signal);
6733
6734 fragrecptr.i = scanPtr.p->activeLocalFrag;
6735 ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
6736 for (tmp = 0; tmp < MAX_PARALLEL_SCANS_PER_FRAG; tmp++) {
6737 jam();
6738 if (fragrecptr.p->scan[tmp] == scanPtr.i) {
6739 jam();
6740 fragrecptr.p->scan[tmp] = RNIL;
6741 }//if
6742 }//for
6743 // Stops the heartbeat.
6744 signal->theData[0] = scanPtr.p->scanUserptr;
6745 signal->theData[1] = RNIL;
6746 signal->theData[2] = RNIL;
6747 sendSignal(scanPtr.p->scanUserblockref, GSN_NEXT_SCANCONF, signal, 3, JBB);
6748 releaseScanRec(signal);
6749 return;
6750 }//Dbacc::releaseScanLab()
6751
6752
releaseAndCommitActiveOps(Signal * signal)6753 void Dbacc::releaseAndCommitActiveOps(Signal* signal)
6754 {
6755 OperationrecPtr trsoOperPtr;
6756 operationRecPtr.i = scanPtr.p->scanFirstActiveOp;
6757 while (operationRecPtr.i != RNIL) {
6758 jam();
6759 ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
6760 trsoOperPtr.i = operationRecPtr.p->nextOp;
6761 fragrecptr.i = operationRecPtr.p->fragptr;
6762 ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
6763 if (!scanPtr.p->scanReadCommittedFlag) {
6764 jam();
6765 if ((operationRecPtr.p->m_op_bits & Operationrec::OP_STATE_MASK) ==
6766 Operationrec::OP_STATE_EXECUTED)
6767 {
6768 commitOperation(signal);
6769 }
6770 else
6771 {
6772 abortOperation(signal);
6773 }
6774 }//if
6775 operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
6776 takeOutActiveScanOp(signal);
6777 releaseOpRec(signal);
6778 scanPtr.p->scanOpsAllocated--;
6779 operationRecPtr.i = trsoOperPtr.i;
6780 }//if
6781 }//Dbacc::releaseAndCommitActiveOps()
6782
6783
releaseAndCommitQueuedOps(Signal * signal)6784 void Dbacc::releaseAndCommitQueuedOps(Signal* signal)
6785 {
6786 OperationrecPtr trsoOperPtr;
6787 operationRecPtr.i = scanPtr.p->scanFirstQueuedOp;
6788 while (operationRecPtr.i != RNIL) {
6789 jam();
6790 ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
6791 trsoOperPtr.i = operationRecPtr.p->nextOp;
6792 fragrecptr.i = operationRecPtr.p->fragptr;
6793 ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
6794 if (!scanPtr.p->scanReadCommittedFlag) {
6795 jam();
6796 if ((operationRecPtr.p->m_op_bits & Operationrec::OP_STATE_MASK) ==
6797 Operationrec::OP_STATE_EXECUTED)
6798 {
6799 commitOperation(signal);
6800 }
6801 else
6802 {
6803 abortOperation(signal);
6804 }
6805 }//if
6806 operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
6807 takeOutReadyScanQueue(signal);
6808 releaseOpRec(signal);
6809 scanPtr.p->scanOpsAllocated--;
6810 operationRecPtr.i = trsoOperPtr.i;
6811 }//if
6812 }//Dbacc::releaseAndCommitQueuedOps()
6813
releaseAndAbortLockedOps(Signal * signal)6814 void Dbacc::releaseAndAbortLockedOps(Signal* signal) {
6815
6816 OperationrecPtr trsoOperPtr;
6817 operationRecPtr.i = scanPtr.p->scanFirstLockedOp;
6818 while (operationRecPtr.i != RNIL) {
6819 jam();
6820 ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
6821 trsoOperPtr.i = operationRecPtr.p->nextOp;
6822 fragrecptr.i = operationRecPtr.p->fragptr;
6823 ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
6824 if (!scanPtr.p->scanReadCommittedFlag) {
6825 jam();
6826 abortOperation(signal);
6827 }//if
6828 takeOutScanLockQueue(scanPtr.i);
6829 operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
6830 releaseOpRec(signal);
6831 scanPtr.p->scanOpsAllocated--;
6832 operationRecPtr.i = trsoOperPtr.i;
6833 }//if
6834 }//Dbacc::releaseAndAbortLockedOps()
6835
6836 /* 3.18.3 ACC_CHECK_SCAN */
6837 /* ******************--------------------------------------------------------------- */
6838 /* ACC_CHECK_SCAN */
6839 /* ENTER ACC_CHECK_SCAN WITH */
6840 /* SCAN_PTR */
6841 /* ******************--------------------------------------------------------------- */
6842 /* ******************--------------------------------------------------------------- */
6843 /* ACC_CHECK_SCAN */
6844 /* ******************------------------------------+ */
execACC_CHECK_SCAN(Signal * signal)6845 void Dbacc::execACC_CHECK_SCAN(Signal* signal)
6846 {
6847 Uint32 TcheckLcpStop;
6848 jamEntry();
6849 scanPtr.i = signal->theData[0];
6850 TcheckLcpStop = signal->theData[1];
6851 ptrCheckGuard(scanPtr, cscanRecSize, scanRec);
6852 while (scanPtr.p->scanFirstQueuedOp != RNIL) {
6853 jam();
6854 //---------------------------------------------------------------------
6855 // An operation has been released from the lock queue.
6856 // We are in the parallel queue of this tuple. We are
6857 // ready to report the tuple now.
6858 //------------------------------------------------------------------------
6859 operationRecPtr.i = scanPtr.p->scanFirstQueuedOp;
6860 ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
6861 takeOutReadyScanQueue(signal);
6862 fragrecptr.i = operationRecPtr.p->fragptr;
6863 ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
6864 if (operationRecPtr.p->m_op_bits & Operationrec::OP_ELEMENT_DISAPPEARED)
6865 {
6866 jam();
6867 abortOperation(signal);
6868 operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
6869 releaseOpRec(signal);
6870 scanPtr.p->scanOpsAllocated--;
6871 continue;
6872 }//if
6873 putActiveScanOp(signal);
6874 sendNextScanConf(signal);
6875 return;
6876 }//while
6877
6878
6879 if ((scanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED) &&
6880 (scanPtr.p->scanLockHeld == 0)) {
6881 jam();
6882 //----------------------------------------------------------------------------
6883 // The scan is now completed and there are no more locks outstanding. Thus we
6884 // we will report the scan as completed to LQH.
6885 //----------------------------------------------------------------------------
6886 signal->theData[0] = scanPtr.p->scanUserptr;
6887 signal->theData[1] = RNIL;
6888 signal->theData[2] = RNIL;
6889 sendSignal(scanPtr.p->scanUserblockref, GSN_NEXT_SCANCONF, signal, 3, JBB);
6890 return;
6891 }//if
6892 if (TcheckLcpStop == AccCheckScan::ZCHECK_LCP_STOP) {
6893 //---------------------------------------------------------------------------
6894 // To ensure that the block of the fragment occurring at the start of a local
6895 // checkpoint is not held for too long we insert a release and reacquiring of
6896 // that lock here. This is performed in LQH. If we are blocked or if we have
6897 // requested a sleep then we will receive RNIL in the returning signal word.
6898 //---------------------------------------------------------------------------
6899 signal->theData[0] = scanPtr.p->scanUserptr;
6900 signal->theData[1] =
6901 ((scanPtr.p->scanLockHeld >= ZSCAN_MAX_LOCK) ||
6902 (scanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED));
6903 EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
6904 jamEntry();
6905 if (signal->theData[0] == RNIL) {
6906 jam();
6907 return;
6908 }//if
6909 }//if
6910 /**
6911 * If we have more than max locks held OR
6912 * scan is completed AND at least one lock held
6913 * - Inform LQH about this condition
6914 */
6915 if ((scanPtr.p->scanLockHeld >= ZSCAN_MAX_LOCK) ||
6916 (cfreeopRec == RNIL) ||
6917 ((scanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED) &&
6918 (scanPtr.p->scanLockHeld > 0))) {
6919 jam();
6920 signal->theData[0] = scanPtr.p->scanUserptr;
6921 signal->theData[1] = RNIL; // No operation is returned
6922 signal->theData[2] = 512; // MASV
6923 sendSignal(scanPtr.p->scanUserblockref, GSN_NEXT_SCANCONF, signal, 3, JBB);
6924 return;
6925 }
6926 if (scanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED) {
6927 jam();
6928 signal->theData[0] = scanPtr.i;
6929 signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
6930 execACC_CHECK_SCAN(signal);
6931 return;
6932 }//if
6933
6934 fragrecptr.i = scanPtr.p->activeLocalFrag;
6935 ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
6936 gnsDirRangePtr.i = fragrecptr.p->directory;
6937 ptrCheckGuard(gnsDirRangePtr, cdirrangesize, dirRange);
6938 checkNextBucketLab(signal);
6939 return;
6940 }//Dbacc::execACC_CHECK_SCAN()
6941
6942 /* ******************---------------------------------------------------- */
6943 /* ACC_TO_REQ PERFORM A TAKE OVER */
6944 /* ******************-------------------+ */
6945 /* SENDER: LQH, LEVEL B */
execACC_TO_REQ(Signal * signal)6946 void Dbacc::execACC_TO_REQ(Signal* signal)
6947 {
6948 OperationrecPtr tatrOpPtr;
6949
6950 jamEntry();
6951 tatrOpPtr.i = signal->theData[1]; /* OPER PTR OF ACC */
6952 ptrCheckGuard(tatrOpPtr, coprecsize, operationrec);
6953 if ((tatrOpPtr.p->m_op_bits & Operationrec::OP_MASK) == ZSCAN_OP)
6954 {
6955 tatrOpPtr.p->transId1 = signal->theData[2];
6956 tatrOpPtr.p->transId2 = signal->theData[3];
6957 validate_lock_queue(tatrOpPtr);
6958 } else {
6959 jam();
6960 signal->theData[0] = cminusOne;
6961 signal->theData[1] = ZTO_OP_STATE_ERROR;
6962 }//if
6963 return;
6964 }//Dbacc::execACC_TO_REQ()
6965
6966 /* --------------------------------------------------------------------------------- */
6967 /* CONTAINERINFO */
6968 /* INPUT: */
6969 /* CI_PAGEIDPTR (PAGE POINTER WHERE CONTAINER RESIDES) */
6970 /* TCI_PAGEINDEX (INDEX OF CONTAINER, USED TO CALCULATE PAGE INDEX) */
6971 /* TCI_ISFORWARD (DIRECTION OF CONTAINER FORWARD OR BACKWARD) */
6972 /* */
6973 /* OUTPUT: */
6974 /* TCI_CONTAINERPTR (A POINTER TO THE HEAD OF THE CONTAINER) */
6975 /* TCI_CONTAINERLEN (LENGTH OF THE CONTAINER */
6976 /* TCI_CONTAINERHEAD (THE HEADER OF THE CONTAINER) */
6977 /* */
6978 /* DESCRIPTION: THE ADDRESS OF THE CONTAINER WILL BE CALCULATED AND */
6979 /* ALL INFORMATION ABOUT THE CONTAINER WILL BE READ */
6980 /* --------------------------------------------------------------------------------- */
containerinfo(Signal * signal)6981 void Dbacc::containerinfo(Signal* signal)
6982 {
6983 tciContainerptr = (tciPageindex << ZSHIFT_PLUS) - (tciPageindex << ZSHIFT_MINUS);
6984 if (tciIsforward == ZTRUE) {
6985 jam();
6986 tciContainerptr = tciContainerptr + ZHEAD_SIZE;
6987 } else {
6988 jam();
6989 tciContainerptr = ((tciContainerptr + ZHEAD_SIZE) + ZBUF_SIZE) - ZCON_HEAD_SIZE;
6990 }//if
6991 arrGuard(tciContainerptr, 2048);
6992 tciContainerhead = ciPageidptr.p->word32[tciContainerptr];
6993 tciContainerlen = tciContainerhead >> 26;
6994 }//Dbacc::containerinfo()
6995
6996 /* --------------------------------------------------------------------------------- */
6997 /* GET_SCAN_ELEMENT */
6998 /* INPUT: GSE_PAGEIDPTR */
6999 /* TGSE_PAGEINDEX */
7000 /* OUTPUT: TGSE_IS_LOCKED (IF TRESULT /= ZFALSE) */
7001 /* GSE_PAGEIDPTR */
7002 /* TGSE_PAGEINDEX */
7003 /* --------------------------------------------------------------------------------- */
getScanElement(Signal * signal)7004 bool Dbacc::getScanElement(Signal* signal)
7005 {
7006 tgseIsforward = ZTRUE;
7007 NEXTSEARCH_SCAN_LOOP:
7008 ciPageidptr.i = gsePageidptr.i;
7009 ciPageidptr.p = gsePageidptr.p;
7010 tciPageindex = tgsePageindex;
7011 tciIsforward = tgseIsforward;
7012 containerinfo(signal);
7013 sscPageidptr.i = gsePageidptr.i;
7014 sscPageidptr.p = gsePageidptr.p;
7015 tsscContainerlen = tciContainerlen;
7016 tsscContainerptr = tciContainerptr;
7017 tsscIsforward = tciIsforward;
7018 if (searchScanContainer(signal)) {
7019 jam();
7020 tgseIsLocked = tsscIsLocked;
7021 tgseElementptr = tsscElementptr;
7022 tgseContainerptr = tsscContainerptr;
7023 return true;
7024 }//if
7025 if (((tciContainerhead >> 7) & 0x3) != 0) {
7026 jam();
7027 nciPageidptr.i = gsePageidptr.i;
7028 nciPageidptr.p = gsePageidptr.p;
7029 tnciContainerhead = tciContainerhead;
7030 tnciContainerptr = tciContainerptr;
7031 nextcontainerinfo(signal);
7032 tgsePageindex = tnciPageindex;
7033 gsePageidptr.i = nciPageidptr.i;
7034 gsePageidptr.p = nciPageidptr.p;
7035 tgseIsforward = tnciIsforward;
7036 goto NEXTSEARCH_SCAN_LOOP;
7037 }//if
7038 return false;
7039 }//Dbacc::getScanElement()
7040
7041 /* --------------------------------------------------------------------------------- */
7042 /* INIT_SCAN_OP_REC */
7043 /* --------------------------------------------------------------------------------- */
initScanOpRec(Signal * signal)7044 void Dbacc::initScanOpRec(Signal* signal)
7045 {
7046 Uint32 tisoLocalPtr;
7047 Uint32 localkeylen = fragrecptr.p->localkeylen;
7048
7049 scanPtr.p->scanOpsAllocated++;
7050
7051 Uint32 opbits = 0;
7052 opbits |= ZSCAN_OP;
7053 opbits |= scanPtr.p->scanLockMode ? (Uint32) Operationrec::OP_LOCK_MODE : 0;
7054 opbits |= scanPtr.p->scanLockMode ? (Uint32) Operationrec::OP_ACC_LOCK_MODE : 0;
7055 opbits |= (scanPtr.p->scanReadCommittedFlag ?
7056 (Uint32) Operationrec::OP_EXECUTED_DIRTY_READ : 0);
7057 opbits |= Operationrec::OP_COMMIT_DELETE_CHECK;
7058 operationRecPtr.p->userptr = RNIL;
7059 operationRecPtr.p->scanRecPtr = scanPtr.i;
7060 operationRecPtr.p->fid = fragrecptr.p->myfid;
7061 operationRecPtr.p->fragptr = fragrecptr.i;
7062 operationRecPtr.p->nextParallelQue = RNIL;
7063 operationRecPtr.p->prevParallelQue = RNIL;
7064 operationRecPtr.p->nextSerialQue = RNIL;
7065 operationRecPtr.p->prevSerialQue = RNIL;
7066 operationRecPtr.p->transId1 = scanPtr.p->scanTrid1;
7067 operationRecPtr.p->transId2 = scanPtr.p->scanTrid2;
7068 operationRecPtr.p->elementIsforward = tisoIsforward;
7069 operationRecPtr.p->elementContainer = tisoContainerptr;
7070 operationRecPtr.p->elementPointer = tisoElementptr;
7071 operationRecPtr.p->elementPage = isoPageptr.i;
7072 operationRecPtr.p->m_op_bits = opbits;
7073 tisoLocalPtr = tisoElementptr + tisoIsforward;
7074
7075 arrGuard(tisoLocalPtr, 2048);
7076 Uint32 Tkey1 = isoPageptr.p->word32[tisoLocalPtr];
7077 tisoLocalPtr = tisoLocalPtr + tisoIsforward;
7078 if (localkeylen == 1)
7079 {
7080 operationRecPtr.p->localdata[0] = Local_key::ref2page_id(Tkey1);
7081 operationRecPtr.p->localdata[1] = Local_key::ref2page_idx(Tkey1);
7082 }
7083 else
7084 {
7085 arrGuard(tisoLocalPtr, 2048);
7086 operationRecPtr.p->localdata[0] = Tkey1;
7087 operationRecPtr.p->localdata[1] = isoPageptr.p->word32[tisoLocalPtr];
7088 }
7089 operationRecPtr.p->tupkeylen = fragrecptr.p->keyLength;
7090 operationRecPtr.p->xfrmtupkeylen = 0; // not used
7091 }//Dbacc::initScanOpRec()
7092
7093 /* --------------------------------------------------------------------------------- */
7094 /* NEXTCONTAINERINFO */
7095 /* DESCRIPTION:THE CONTAINER HEAD WILL BE CHECKED TO CALCULATE INFORMATION */
7096 /* ABOUT NEXT CONTAINER IN THE BUCKET. */
7097 /* INPUT: TNCI_CONTAINERHEAD */
7098 /* NCI_PAGEIDPTR */
7099 /* TNCI_CONTAINERPTR */
7100 /* OUTPUT: */
7101 /* TNCI_PAGEINDEX (INDEX FROM WHICH PAGE INDEX CAN BE CALCULATED). */
7102 /* TNCI_ISFORWARD (IS THE NEXT CONTAINER FORWARD (+1) OR BACKWARD (-1) */
7103 /* NCI_PAGEIDPTR (PAGE REFERENCE OF NEXT CONTAINER) */
7104 /* --------------------------------------------------------------------------------- */
nextcontainerinfo(Signal * signal)7105 void Dbacc::nextcontainerinfo(Signal* signal)
7106 {
7107 tnciNextSamePage = (tnciContainerhead >> 9) & 0x1; /* CHECK BIT FOR CHECKING WHERE */
7108 /* THE NEXT CONTAINER IS IN THE SAME PAGE */
7109 tnciPageindex = tnciContainerhead & 0x7f; /* NEXT CONTAINER PAGE INDEX 7 BITS */
7110 if (((tnciContainerhead >> 7) & 3) == ZLEFT) {
7111 jam();
7112 tnciIsforward = ZTRUE;
7113 } else {
7114 jam();
7115 tnciIsforward = cminusOne;
7116 }//if
7117 if (tnciNextSamePage == ZFALSE) {
7118 jam();
7119 /* NEXT CONTAINER IS IN AN OVERFLOW PAGE */
7120 arrGuard(tnciContainerptr + 1, 2048);
7121 tnciTmp = nciPageidptr.p->word32[tnciContainerptr + 1];
7122 nciOverflowrangeptr.i = fragrecptr.p->overflowdir;
7123 ptrCheckGuard(nciOverflowrangeptr, cdirrangesize, dirRange);
7124 arrGuard((tnciTmp >> 8), 256);
7125 nciOverflowDirptr.i = nciOverflowrangeptr.p->dirArray[tnciTmp >> 8];
7126 ptrCheckGuard(nciOverflowDirptr, cdirarraysize, directoryarray);
7127 nciPageidptr.i = nciOverflowDirptr.p->pagep[tnciTmp & 0xff];
7128 ptrCheckGuard(nciPageidptr, cpagesize, page8);
7129 }//if
7130 }//Dbacc::nextcontainerinfo()
7131
7132 /* --------------------------------------------------------------------------------- */
7133 /* PUT_ACTIVE_SCAN_OP */
7134 /* --------------------------------------------------------------------------------- */
putActiveScanOp(Signal * signal)7135 void Dbacc::putActiveScanOp(Signal* signal)
7136 {
7137 OperationrecPtr pasOperationRecPtr;
7138 pasOperationRecPtr.i = scanPtr.p->scanFirstActiveOp;
7139 if (pasOperationRecPtr.i != RNIL) {
7140 jam();
7141 ptrCheckGuard(pasOperationRecPtr, coprecsize, operationrec);
7142 pasOperationRecPtr.p->prevOp = operationRecPtr.i;
7143 }//if
7144 operationRecPtr.p->nextOp = pasOperationRecPtr.i;
7145 operationRecPtr.p->prevOp = RNIL;
7146 scanPtr.p->scanFirstActiveOp = operationRecPtr.i;
7147 }//Dbacc::putActiveScanOp()
7148
7149 /**
7150 * putOpScanLockQueue
7151 *
7152 * Description: Put an operation in the doubly linked
7153 * lock list on a scan record. The list is used to
7154 * keep track of which operations belonging
7155 * to the scan are put in serial lock list of another
7156 * operation
7157 *
7158 * @note Use takeOutScanLockQueue to remove an operation
7159 * from the list
7160 *
7161 */
putOpScanLockQue()7162 void Dbacc::putOpScanLockQue()
7163 {
7164
7165 #ifdef VM_TRACE
7166 // DEBUG CODE
7167 // Check that there are as many operations in the lockqueue as
7168 // scanLockHeld indicates
7169 OperationrecPtr tmpOp;
7170 int numLockedOpsBefore = 0;
7171 tmpOp.i = scanPtr.p->scanFirstLockedOp;
7172 while(tmpOp.i != RNIL){
7173 numLockedOpsBefore++;
7174 ptrCheckGuard(tmpOp, coprecsize, operationrec);
7175 if (tmpOp.p->nextOp == RNIL)
7176 {
7177 ndbrequire(tmpOp.i == scanPtr.p->scanLastLockedOp);
7178 }
7179 tmpOp.i = tmpOp.p->nextOp;
7180 }
7181 ndbrequire(numLockedOpsBefore==scanPtr.p->scanLockHeld);
7182 #endif
7183
7184 OperationrecPtr pslOperationRecPtr;
7185 ScanRec theScanRec;
7186 theScanRec = *scanPtr.p;
7187
7188 pslOperationRecPtr.i = scanPtr.p->scanLastLockedOp;
7189 operationRecPtr.p->prevOp = pslOperationRecPtr.i;
7190 operationRecPtr.p->nextOp = RNIL;
7191 if (pslOperationRecPtr.i != RNIL) {
7192 jam();
7193 ptrCheckGuard(pslOperationRecPtr, coprecsize, operationrec);
7194 pslOperationRecPtr.p->nextOp = operationRecPtr.i;
7195 } else {
7196 jam();
7197 scanPtr.p->scanFirstLockedOp = operationRecPtr.i;
7198 }//if
7199 scanPtr.p->scanLastLockedOp = operationRecPtr.i;
7200 scanPtr.p->scanLockHeld++;
7201
7202 }//Dbacc::putOpScanLockQue()
7203
7204 /* --------------------------------------------------------------------------------- */
7205 /* PUT_READY_SCAN_QUEUE */
7206 /* --------------------------------------------------------------------------------- */
putReadyScanQueue(Signal * signal,Uint32 scanRecIndex)7207 void Dbacc::putReadyScanQueue(Signal* signal, Uint32 scanRecIndex)
7208 {
7209 OperationrecPtr prsOperationRecPtr;
7210 ScanRecPtr TscanPtr;
7211
7212 TscanPtr.i = scanRecIndex;
7213 ptrCheckGuard(TscanPtr, cscanRecSize, scanRec);
7214
7215 prsOperationRecPtr.i = TscanPtr.p->scanLastQueuedOp;
7216 operationRecPtr.p->prevOp = prsOperationRecPtr.i;
7217 operationRecPtr.p->nextOp = RNIL;
7218 TscanPtr.p->scanLastQueuedOp = operationRecPtr.i;
7219 if (prsOperationRecPtr.i != RNIL) {
7220 jam();
7221 ptrCheckGuard(prsOperationRecPtr, coprecsize, operationrec);
7222 prsOperationRecPtr.p->nextOp = operationRecPtr.i;
7223 } else {
7224 jam();
7225 TscanPtr.p->scanFirstQueuedOp = operationRecPtr.i;
7226 }//if
7227 }//Dbacc::putReadyScanQueue()
7228
7229 /* --------------------------------------------------------------------------------- */
7230 /* RELEASE_SCAN_BUCKET */
7231 // Input:
7232 // rsbPageidptr.i Index to page where buckets starts
7233 // rsbPageidptr.p Pointer to page where bucket starts
7234 // trsbPageindex Page index of starting container in bucket
7235 /* --------------------------------------------------------------------------------- */
releaseScanBucket(Signal * signal)7236 void Dbacc::releaseScanBucket(Signal* signal)
7237 {
7238 Uint32 trsbIsforward;
7239
7240 trsbIsforward = ZTRUE;
7241 NEXTRELEASESCANLOOP:
7242 ciPageidptr.i = rsbPageidptr.i;
7243 ciPageidptr.p = rsbPageidptr.p;
7244 tciPageindex = trsbPageindex;
7245 tciIsforward = trsbIsforward;
7246 containerinfo(signal);
7247 rscPageidptr.i = rsbPageidptr.i;
7248 rscPageidptr.p = rsbPageidptr.p;
7249 trscContainerlen = tciContainerlen;
7250 trscContainerptr = tciContainerptr;
7251 trscIsforward = trsbIsforward;
7252 releaseScanContainer(signal);
7253 if (((tciContainerhead >> 7) & 0x3) != 0) {
7254 jam();
7255 nciPageidptr.i = rsbPageidptr.i;
7256 nciPageidptr.p = rsbPageidptr.p;
7257 tnciContainerhead = tciContainerhead;
7258 tnciContainerptr = tciContainerptr;
7259 nextcontainerinfo(signal);
7260 rsbPageidptr.i = nciPageidptr.i;
7261 rsbPageidptr.p = nciPageidptr.p;
7262 trsbPageindex = tnciPageindex;
7263 trsbIsforward = tnciIsforward;
7264 goto NEXTRELEASESCANLOOP;
7265 }//if
7266 }//Dbacc::releaseScanBucket()
7267
7268 /* --------------------------------------------------------------------------------- */
7269 /* RELEASE_SCAN_CONTAINER */
7270 /* INPUT: TRSC_CONTAINERLEN */
7271 /* RSC_PAGEIDPTR */
7272 /* TRSC_CONTAINERPTR */
7273 /* TRSC_ISFORWARD */
7274 /* SCAN_PTR */
7275 /* */
7276 /* DESCRIPTION: SEARCHS IN A CONTAINER, AND THE SCAN BIT OF THE ELEMENTS */
7277 /* OF THE CONTAINER IS RESET */
7278 /* --------------------------------------------------------------------------------- */
releaseScanContainer(Signal * signal)7279 void Dbacc::releaseScanContainer(Signal* signal)
7280 {
7281 OperationrecPtr rscOperPtr;
7282 Uint32 trscElemStep;
7283 Uint32 trscElementptr;
7284 Uint32 trscElemlens;
7285 Uint32 trscElemlen;
7286
7287 if (trscContainerlen < 4) {
7288 if (trscContainerlen != ZCON_HEAD_SIZE) {
7289 jam();
7290 sendSystemerror(signal, __LINE__);
7291 }//if
7292 return; /* 2 IS THE MINIMUM SIZE OF THE ELEMENT */
7293 }//if
7294 trscElemlens = trscContainerlen - ZCON_HEAD_SIZE;
7295 trscElemlen = fragrecptr.p->elementLength;
7296 if (trscIsforward == 1) {
7297 jam();
7298 trscElementptr = trscContainerptr + ZCON_HEAD_SIZE;
7299 trscElemStep = trscElemlen;
7300 } else {
7301 jam();
7302 trscElementptr = trscContainerptr - 1;
7303 trscElemStep = 0 - trscElemlen;
7304 }//if
7305 do {
7306 arrGuard(trscElementptr, 2048);
7307 const Uint32 eh = rscPageidptr.p->word32[trscElementptr];
7308 const Uint32 scanMask = scanPtr.p->scanMask;
7309 if (ElementHeader::getUnlocked(eh)) {
7310 jam();
7311 const Uint32 tmp = ElementHeader::clearScanBit(eh, scanMask);
7312 dbgWord32(rscPageidptr, trscElementptr, tmp);
7313 rscPageidptr.p->word32[trscElementptr] = tmp;
7314 } else {
7315 jam();
7316 rscOperPtr.i = ElementHeader::getOpPtrI(eh);
7317 ptrCheckGuard(rscOperPtr, coprecsize, operationrec);
7318 rscOperPtr.p->scanBits &= ~scanMask;
7319 }//if
7320 trscElemlens = trscElemlens - trscElemlen;
7321 trscElementptr = trscElementptr + trscElemStep;
7322 } while (trscElemlens > 1);
7323 if (trscElemlens != 0) {
7324 jam();
7325 sendSystemerror(signal, __LINE__);
7326 }//if
7327 }//Dbacc::releaseScanContainer()
7328
7329 /* --------------------------------------------------------------------------------- */
7330 /* RELEASE_SCAN_REC */
7331 /* --------------------------------------------------------------------------------- */
releaseScanRec(Signal * signal)7332 void Dbacc::releaseScanRec(Signal* signal)
7333 {
7334 // Check that all ops this scan has allocated have been
7335 // released
7336 ndbrequire(scanPtr.p->scanOpsAllocated==0);
7337
7338 // Check that all locks this scan might have aquired
7339 // have been properly released
7340 ndbrequire(scanPtr.p->scanLockHeld == 0);
7341 ndbrequire(scanPtr.p->scanFirstLockedOp == RNIL);
7342 ndbrequire(scanPtr.p->scanLastLockedOp == RNIL);
7343
7344 // Check that all active operations have been
7345 // properly released
7346 ndbrequire(scanPtr.p->scanFirstActiveOp == RNIL);
7347
7348 // Check that all queued operations have been
7349 // properly released
7350 ndbrequire(scanPtr.p->scanFirstQueuedOp == RNIL);
7351 ndbrequire(scanPtr.p->scanLastQueuedOp == RNIL);
7352
7353 // Put scan record in free list
7354 scanPtr.p->scanNextfreerec = cfirstFreeScanRec;
7355 scanPtr.p->scanState = ScanRec::SCAN_DISCONNECT;
7356 cfirstFreeScanRec = scanPtr.i;
7357
7358 }//Dbacc::releaseScanRec()
7359
7360 /* --------------------------------------------------------------------------------- */
7361 /* SEARCH_SCAN_CONTAINER */
7362 /* INPUT: TSSC_CONTAINERLEN */
7363 /* TSSC_CONTAINERPTR */
7364 /* TSSC_ISFORWARD */
7365 /* SSC_PAGEIDPTR */
7366 /* SCAN_PTR */
7367 /* OUTPUT: TSSC_IS_LOCKED */
7368 /* */
7369 /* DESCRIPTION: SEARCH IN A CONTAINER TO FIND THE NEXT SCAN ELEMENT. */
7370 /* TO DO THIS THE SCAN BIT OF THE ELEMENT HEADER IS CHECKED. IF */
7371 /* THIS BIT IS ZERO, IT IS SET TO ONE AND THE ELEMENT IS RETURNED.*/
7372 /* --------------------------------------------------------------------------------- */
searchScanContainer(Signal * signal)7373 bool Dbacc::searchScanContainer(Signal* signal)
7374 {
7375 OperationrecPtr sscOperPtr;
7376 Uint32 tsscScanBits;
7377 Uint32 tsscElemlens;
7378 Uint32 tsscElemlen;
7379 Uint32 tsscElemStep;
7380
7381 if (tsscContainerlen < 4) {
7382 jam();
7383 return false; /* 2 IS THE MINIMUM SIZE OF THE ELEMENT */
7384 }//if
7385 tsscElemlens = tsscContainerlen - ZCON_HEAD_SIZE;
7386 tsscElemlen = fragrecptr.p->elementLength;
7387 /* LENGTH OF THE ELEMENT */
7388 if (tsscIsforward == 1) {
7389 jam();
7390 tsscElementptr = tsscContainerptr + ZCON_HEAD_SIZE;
7391 tsscElemStep = tsscElemlen;
7392 } else {
7393 jam();
7394 tsscElementptr = tsscContainerptr - 1;
7395 tsscElemStep = 0 - tsscElemlen;
7396 }//if
7397 SCANELEMENTLOOP001:
7398 arrGuard(tsscElementptr, 2048);
7399 const Uint32 eh = sscPageidptr.p->word32[tsscElementptr];
7400 tsscIsLocked = ElementHeader::getLocked(eh);
7401 if (!tsscIsLocked){
7402 jam();
7403 tsscScanBits = ElementHeader::getScanBits(eh);
7404 if ((scanPtr.p->scanMask & tsscScanBits) == 0) {
7405 jam();
7406 const Uint32 tmp = ElementHeader::setScanBit(eh, scanPtr.p->scanMask);
7407 dbgWord32(sscPageidptr, tsscElementptr, tmp);
7408 sscPageidptr.p->word32[tsscElementptr] = tmp;
7409 return true;
7410 }//if
7411 } else {
7412 jam();
7413 sscOperPtr.i = ElementHeader::getOpPtrI(eh);
7414 ptrCheckGuard(sscOperPtr, coprecsize, operationrec);
7415 if ((sscOperPtr.p->scanBits & scanPtr.p->scanMask) == 0) {
7416 jam();
7417 sscOperPtr.p->scanBits |= scanPtr.p->scanMask;
7418 return true;
7419 }//if
7420 }//if
7421 /* THE ELEMENT IS ALREADY SENT. */
7422 /* SEARCH FOR NEXT ONE */
7423 tsscElemlens = tsscElemlens - tsscElemlen;
7424 if (tsscElemlens > 1) {
7425 jam();
7426 tsscElementptr = tsscElementptr + tsscElemStep;
7427 goto SCANELEMENTLOOP001;
7428 }//if
7429 return false;
7430 }//Dbacc::searchScanContainer()
7431
7432 /* --------------------------------------------------------------------------------- */
7433 /* SEND THE RESPONSE NEXT_SCANCONF AND POSSIBLE KEYINFO SIGNALS AS WELL. */
7434 /* --------------------------------------------------------------------------------- */
sendNextScanConf(Signal * signal)7435 void Dbacc::sendNextScanConf(Signal* signal)
7436 {
7437 Uint32 blockNo = refToMain(scanPtr.p->scanUserblockref);
7438
7439 jam();
7440 /** ---------------------------------------------------------------------
7441 * LQH WILL NOT HAVE ANY USE OF THE TUPLE KEY LENGTH IN THIS CASE AND
7442 * SO WE DO NOT PROVIDE IT. IN THIS CASE THESE VALUES ARE UNDEFINED.
7443 * ---------------------------------------------------------------------- */
7444 signal->theData[0] = scanPtr.p->scanUserptr;
7445 signal->theData[1] = operationRecPtr.i;
7446 signal->theData[2] = operationRecPtr.p->fid;
7447 signal->theData[3] = operationRecPtr.p->localdata[0];
7448 signal->theData[4] = operationRecPtr.p->localdata[1];
7449 EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 5);
7450 return;
7451 }//Dbacc::sendNextScanConf()
7452
7453 /* --------------------------------------------------------------------------------- */
7454 /* SETLOCK */
7455 /* DESCRIPTION:SETS LOCK ON AN ELEMENT. INFORMATION ABOUT THE ELEMENT IS */
7456 /* SAVED IN THE ELEMENT HEAD.A COPY OF THIS INFORMATION WILL */
7457 /* BE PUT IN THE OPERATION RECORD. A FIELD IN THE HEADER OF */
7458 /* THE ELEMENT POINTS TO THE OPERATION RECORD. */
7459 /* --------------------------------------------------------------------------------- */
setlock(Signal * signal)7460 void Dbacc::setlock(Signal* signal)
7461 {
7462 Uint32 tselTmp1;
7463
7464 arrGuard(tslElementptr, 2048);
7465 tselTmp1 = slPageidptr.p->word32[tslElementptr];
7466 operationRecPtr.p->scanBits = ElementHeader::getScanBits(tselTmp1);
7467 operationRecPtr.p->hashvaluePart = ElementHeader::getHashValuePart(tselTmp1);
7468
7469 tselTmp1 = ElementHeader::setLocked(operationRecPtr.i);
7470 dbgWord32(slPageidptr, tslElementptr, tselTmp1);
7471 slPageidptr.p->word32[tslElementptr] = tselTmp1;
7472 }//Dbacc::setlock()
7473
7474 /* --------------------------------------------------------------------------------- */
7475 /* TAKE_OUT_ACTIVE_SCAN_OP */
7476 /* DESCRIPTION: AN ACTIVE SCAN OPERATION IS BELOGED TO AN ACTIVE LIST OF THE */
7477 /* SCAN RECORD. BY THIS SUBRUTIN THE LIST IS UPDATED. */
7478 /* --------------------------------------------------------------------------------- */
takeOutActiveScanOp(Signal * signal)7479 void Dbacc::takeOutActiveScanOp(Signal* signal)
7480 {
7481 OperationrecPtr tasOperationRecPtr;
7482
7483 if (operationRecPtr.p->prevOp != RNIL) {
7484 jam();
7485 tasOperationRecPtr.i = operationRecPtr.p->prevOp;
7486 ptrCheckGuard(tasOperationRecPtr, coprecsize, operationrec);
7487 tasOperationRecPtr.p->nextOp = operationRecPtr.p->nextOp;
7488 } else {
7489 jam();
7490 scanPtr.p->scanFirstActiveOp = operationRecPtr.p->nextOp;
7491 }//if
7492 if (operationRecPtr.p->nextOp != RNIL) {
7493 jam();
7494 tasOperationRecPtr.i = operationRecPtr.p->nextOp;
7495 ptrCheckGuard(tasOperationRecPtr, coprecsize, operationrec);
7496 tasOperationRecPtr.p->prevOp = operationRecPtr.p->prevOp;
7497 }//if
7498 }//Dbacc::takeOutActiveScanOp()
7499
7500 /**
7501 * takeOutScanLockQueue
7502 *
7503 * Description: Take out an operation from the doubly linked
7504 * lock list on a scan record.
7505 *
7506 * @note Use putOpScanLockQue to insert a operation in
7507 * the list
7508 *
7509 */
takeOutScanLockQueue(Uint32 scanRecIndex)7510 void Dbacc::takeOutScanLockQueue(Uint32 scanRecIndex)
7511 {
7512 OperationrecPtr tslOperationRecPtr;
7513 ScanRecPtr TscanPtr;
7514
7515 TscanPtr.i = scanRecIndex;
7516 ptrCheckGuard(TscanPtr, cscanRecSize, scanRec);
7517
7518 if (operationRecPtr.p->prevOp != RNIL) {
7519 jam();
7520 tslOperationRecPtr.i = operationRecPtr.p->prevOp;
7521 ptrCheckGuard(tslOperationRecPtr, coprecsize, operationrec);
7522 tslOperationRecPtr.p->nextOp = operationRecPtr.p->nextOp;
7523 } else {
7524 jam();
7525 // Check that first are pointing at operation to take out
7526 ndbrequire(TscanPtr.p->scanFirstLockedOp==operationRecPtr.i);
7527 TscanPtr.p->scanFirstLockedOp = operationRecPtr.p->nextOp;
7528 }//if
7529 if (operationRecPtr.p->nextOp != RNIL) {
7530 jam();
7531 tslOperationRecPtr.i = operationRecPtr.p->nextOp;
7532 ptrCheckGuard(tslOperationRecPtr, coprecsize, operationrec);
7533 tslOperationRecPtr.p->prevOp = operationRecPtr.p->prevOp;
7534 } else {
7535 jam();
7536 // Check that last are pointing at operation to take out
7537 ndbrequire(TscanPtr.p->scanLastLockedOp==operationRecPtr.i);
7538 TscanPtr.p->scanLastLockedOp = operationRecPtr.p->prevOp;
7539 }//if
7540 TscanPtr.p->scanLockHeld--;
7541
7542 #ifdef VM_TRACE
7543 // DEBUG CODE
7544 // Check that there are as many operations in the lockqueue as
7545 // scanLockHeld indicates
7546 OperationrecPtr tmpOp;
7547 int numLockedOps = 0;
7548 tmpOp.i = TscanPtr.p->scanFirstLockedOp;
7549 while(tmpOp.i != RNIL){
7550 numLockedOps++;
7551 ptrCheckGuard(tmpOp, coprecsize, operationrec);
7552 if (tmpOp.p->nextOp == RNIL)
7553 {
7554 ndbrequire(tmpOp.i == TscanPtr.p->scanLastLockedOp);
7555 }
7556 tmpOp.i = tmpOp.p->nextOp;
7557 }
7558 ndbrequire(numLockedOps==TscanPtr.p->scanLockHeld);
7559 #endif
7560 }//Dbacc::takeOutScanLockQueue()
7561
7562 /* --------------------------------------------------------------------------------- */
7563 /* TAKE_OUT_READY_SCAN_QUEUE */
7564 /* --------------------------------------------------------------------------------- */
takeOutReadyScanQueue(Signal * signal)7565 void Dbacc::takeOutReadyScanQueue(Signal* signal)
7566 {
7567 OperationrecPtr trsOperationRecPtr;
7568
7569 if (operationRecPtr.p->prevOp != RNIL) {
7570 jam();
7571 trsOperationRecPtr.i = operationRecPtr.p->prevOp;
7572 ptrCheckGuard(trsOperationRecPtr, coprecsize, operationrec);
7573 trsOperationRecPtr.p->nextOp = operationRecPtr.p->nextOp;
7574 } else {
7575 jam();
7576 scanPtr.p->scanFirstQueuedOp = operationRecPtr.p->nextOp;
7577 }//if
7578 if (operationRecPtr.p->nextOp != RNIL) {
7579 jam();
7580 trsOperationRecPtr.i = operationRecPtr.p->nextOp;
7581 ptrCheckGuard(trsOperationRecPtr, coprecsize, operationrec);
7582 trsOperationRecPtr.p->prevOp = operationRecPtr.p->prevOp;
7583 } else {
7584 jam();
7585 scanPtr.p->scanLastQueuedOp = operationRecPtr.p->nextOp;
7586 }//if
7587 }//Dbacc::takeOutReadyScanQueue()
7588
7589 /* --------------------------------------------------------------------------------- */
7590 /* --------------------------------------------------------------------------------- */
7591 /* --------------------------------------------------------------------------------- */
7592 /* */
7593 /* END OF SCAN MODULE */
7594 /* */
7595 /* --------------------------------------------------------------------------------- */
7596 /* --------------------------------------------------------------------------------- */
7597
getfragmentrec(Signal * signal,FragmentrecPtr & rootPtr,Uint32 fid)7598 bool Dbacc::getfragmentrec(Signal* signal, FragmentrecPtr& rootPtr, Uint32 fid)
7599 {
7600 for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
7601 jam();
7602 if (tabptr.p->fragholder[i] == fid) {
7603 jam();
7604 fragrecptr.i = tabptr.p->fragptrholder[i];
7605 ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
7606 return true;
7607 }//if
7608 }//for
7609 return false;
7610 }//Dbacc::getrootfragmentrec()
7611
7612 /* --------------------------------------------------------------------------------- */
7613 /* INIT_OVERPAGE */
7614 /* INPUT. IOP_PAGEPTR, POINTER TO AN OVERFLOW PAGE RECORD */
7615 /* DESCRIPTION: CONTAINERS AND FREE LISTS OF THE PAGE, GET INITIALE VALUE */
7616 /* ACCORDING TO LH3 AND PAGE STRUCTOR DESCRIPTION OF NDBACC BLOCK */
7617 /* --------------------------------------------------------------------------------- */
initOverpage(Signal * signal)7618 void Dbacc::initOverpage(Signal* signal)
7619 {
7620 Uint32 tiopTmp;
7621 Uint32 tiopPrevFree;
7622 Uint32 tiopNextFree;
7623
7624 for (tiopIndex = 0; tiopIndex <= 2047; tiopIndex++) {
7625 iopPageptr.p->word32[tiopIndex] = 0;
7626 }//for
7627 iopPageptr.p->word32[ZPOS_OVERFLOWREC] = iopOverflowRecPtr.i;
7628 iopPageptr.p->word32[ZPOS_CHECKSUM] = 0;
7629 iopPageptr.p->word32[ZPOS_PAGE_ID] = tiopPageId;
7630 iopPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] = 0;
7631 tiopTmp = ZEMPTYLIST;
7632 tiopTmp = (tiopTmp << 16) + (tiopTmp << 23);
7633 iopPageptr.p->word32[ZPOS_EMPTY_LIST] = tiopTmp + (1 << ZPOS_PAGE_TYPE_BIT);
7634 /* --------------------------------------------------------------------------------- */
7635 /* INITIALISE PREVIOUS PART OF DOUBLY LINKED LIST FOR LEFT CONTAINERS. */
7636 /* --------------------------------------------------------------------------------- */
7637 tiopIndex = ZHEAD_SIZE + 1;
7638 iopPageptr.p->word32[tiopIndex] = ZEMPTYLIST;
7639 for (tiopPrevFree = 0; tiopPrevFree <= ZEMPTYLIST - 2; tiopPrevFree++) {
7640 tiopIndex = tiopIndex + ZBUF_SIZE;
7641 iopPageptr.p->word32[tiopIndex] = tiopPrevFree;
7642 }//for
7643 /* --------------------------------------------------------------------------------- */
7644 /* INITIALISE NEXT PART OF DOUBLY LINKED LIST FOR LEFT CONTAINERS. */
7645 /* --------------------------------------------------------------------------------- */
7646 tiopIndex = ZHEAD_SIZE;
7647 for (tiopNextFree = 1; tiopNextFree <= ZEMPTYLIST - 1; tiopNextFree++) {
7648 iopPageptr.p->word32[tiopIndex] = tiopNextFree;
7649 tiopIndex = tiopIndex + ZBUF_SIZE;
7650 }//for
7651 iopPageptr.p->word32[tiopIndex] = ZEMPTYLIST; /* LEFT_LIST IS UPDATED */
7652 /* --------------------------------------------------------------------------------- */
7653 /* INITIALISE PREVIOUS PART OF DOUBLY LINKED LIST FOR RIGHT CONTAINERS. */
7654 /* --------------------------------------------------------------------------------- */
7655 tiopIndex = (ZBUF_SIZE + ZHEAD_SIZE) - 1;
7656 iopPageptr.p->word32[tiopIndex] = ZEMPTYLIST;
7657 for (tiopPrevFree = 0; tiopPrevFree <= ZEMPTYLIST - 2; tiopPrevFree++) {
7658 tiopIndex = tiopIndex + ZBUF_SIZE;
7659 iopPageptr.p->word32[tiopIndex] = tiopPrevFree;
7660 }//for
7661 /* --------------------------------------------------------------------------------- */
7662 /* INITIALISE NEXT PART OF DOUBLY LINKED LIST FOR RIGHT CONTAINERS. */
7663 /* --------------------------------------------------------------------------------- */
7664 tiopIndex = (ZBUF_SIZE + ZHEAD_SIZE) - 2;
7665 for (tiopNextFree = 1; tiopNextFree <= ZEMPTYLIST - 1; tiopNextFree++) {
7666 iopPageptr.p->word32[tiopIndex] = tiopNextFree;
7667 tiopIndex = tiopIndex + ZBUF_SIZE;
7668 }//for
7669 iopPageptr.p->word32[tiopIndex] = ZEMPTYLIST; /* RIGHT_LIST IS UPDATED */
7670 }//Dbacc::initOverpage()
7671
7672 /* --------------------------------------------------------------------------------- */
7673 /* INIT_PAGE */
7674 /* INPUT. INP_PAGEPTR, POINTER TO A PAGE RECORD */
7675 /* DESCRIPTION: CONTAINERS AND FREE LISTS OF THE PAGE, GET INITIALE VALUE */
7676 /* ACCORDING TO LH3 AND PAGE STRUCTOR DISACRIPTION OF NDBACC BLOCK */
7677 /* --------------------------------------------------------------------------------- */
initPage(Signal * signal)7678 void Dbacc::initPage(Signal* signal)
7679 {
7680 Uint32 tinpTmp1;
7681 Uint32 tinpIndex;
7682 Uint32 tinpTmp;
7683 Uint32 tinpPrevFree;
7684 Uint32 tinpNextFree;
7685
7686 for (tiopIndex = 0; tiopIndex <= 2047; tiopIndex++) {
7687 inpPageptr.p->word32[tiopIndex] = 0;
7688 }//for
7689 /* --------------------------------------------------------------------------------- */
7690 /* SET PAGE ID FOR USE OF CHECKPOINTER. */
7691 /* PREPARE CONTAINER HEADERS INDICATING EMPTY CONTAINERS WITHOUT NEXT. */
7692 /* --------------------------------------------------------------------------------- */
7693 inpPageptr.p->word32[ZPOS_PAGE_ID] = tipPageId;
7694 tinpTmp1 = ZCON_HEAD_SIZE;
7695 tinpTmp1 = tinpTmp1 << 26;
7696 /* --------------------------------------------------------------------------------- */
7697 /* INITIALISE ZNO_CONTAINERS PREDEFINED HEADERS ON LEFT SIZE. */
7698 /* --------------------------------------------------------------------------------- */
7699 tinpIndex = ZHEAD_SIZE;
7700 for (tinpTmp = 0; tinpTmp <= ZNO_CONTAINERS - 1; tinpTmp++) {
7701 inpPageptr.p->word32[tinpIndex] = tinpTmp1;
7702 tinpIndex = tinpIndex + ZBUF_SIZE;
7703 }//for
7704 /* WORD32(ZPOS_EMPTY_LIST) DATA STRUCTURE:*/
7705 /*--------------------------------------- */
7706 /*| PAGE TYPE|LEFT FREE|RIGHT FREE */
7707 /*| 1 | LIST | LIST */
7708 /*| BIT | 7 BITS | 7 BITS */
7709 /*--------------------------------------- */
7710 /* --------------------------------------------------------------------------------- */
7711 /* INITIALISE FIRST POINTER TO DOUBLY LINKED LIST OF FREE CONTAINERS. */
7712 /* INITIALISE EMPTY LISTS OF USED CONTAINERS. */
7713 /* INITIALISE LEFT FREE LIST TO 64 AND RIGHT FREE LIST TO ZERO. */
7714 /* ALSO INITIALISE PAGE TYPE TO NOT OVERFLOW PAGE. */
7715 /* --------------------------------------------------------------------------------- */
7716 tinpTmp = ZEMPTYLIST;
7717 tinpTmp = (tinpTmp << 16) + (tinpTmp << 23);
7718 tinpTmp = tinpTmp + (ZNO_CONTAINERS << 7);
7719 inpPageptr.p->word32[ZPOS_EMPTY_LIST] = tinpTmp;
7720 /* --------------------------------------------------------------------------------- */
7721 /* INITIALISE PREVIOUS PART OF DOUBLY LINKED LIST FOR RIGHT CONTAINERS. */
7722 /* --------------------------------------------------------------------------------- */
7723 tinpIndex = (ZHEAD_SIZE + ZBUF_SIZE) - 1;
7724 inpPageptr.p->word32[tinpIndex] = ZEMPTYLIST;
7725 for (tinpPrevFree = 0; tinpPrevFree <= ZEMPTYLIST - 2; tinpPrevFree++) {
7726 tinpIndex = tinpIndex + ZBUF_SIZE;
7727 inpPageptr.p->word32[tinpIndex] = tinpPrevFree;
7728 }//for
7729 /* --------------------------------------------------------------------------------- */
7730 /* INITIALISE NEXT PART OF DOUBLY LINKED LIST FOR RIGHT CONTAINERS. */
7731 /* --------------------------------------------------------------------------------- */
7732 tinpIndex = (ZHEAD_SIZE + ZBUF_SIZE) - 2;
7733 for (tinpNextFree = 1; tinpNextFree <= ZEMPTYLIST - 1; tinpNextFree++) {
7734 inpPageptr.p->word32[tinpIndex] = tinpNextFree;
7735 tinpIndex = tinpIndex + ZBUF_SIZE;
7736 }//for
7737 inpPageptr.p->word32[tinpIndex] = ZEMPTYLIST;
7738 /* --------------------------------------------------------------------------------- */
7739 /* INITIALISE PREVIOUS PART OF DOUBLY LINKED LIST FOR LEFT CONTAINERS. */
7740 /* THE FIRST ZNO_CONTAINERS ARE NOT PUT INTO FREE LIST SINCE THEY ARE */
7741 /* PREDEFINED AS OCCUPIED. */
7742 /* --------------------------------------------------------------------------------- */
7743 tinpIndex = (ZNO_CONTAINERS * ZBUF_SIZE) + ZHEAD_SIZE;
7744 for (tinpNextFree = ZNO_CONTAINERS + 1; tinpNextFree <= ZEMPTYLIST - 1; tinpNextFree++) {
7745 inpPageptr.p->word32[tinpIndex] = tinpNextFree;
7746 tinpIndex = tinpIndex + ZBUF_SIZE;
7747 }//for
7748 inpPageptr.p->word32[tinpIndex] = ZEMPTYLIST;
7749 /* --------------------------------------------------------------------------------- */
7750 /* INITIALISE NEXT PART OF DOUBLY LINKED LIST FOR LEFT CONTAINERS. */
7751 /* THE FIRST ZNO_CONTAINERS ARE NOT PUT INTO FREE LIST SINCE THEY ARE */
7752 /* PREDEFINED AS OCCUPIED. */
7753 /* --------------------------------------------------------------------------------- */
7754 tinpIndex = ((ZNO_CONTAINERS * ZBUF_SIZE) + ZHEAD_SIZE) + 1;
7755 inpPageptr.p->word32[tinpIndex] = ZEMPTYLIST;
7756 for (tinpPrevFree = ZNO_CONTAINERS; tinpPrevFree <= ZEMPTYLIST - 2; tinpPrevFree++) {
7757 tinpIndex = tinpIndex + ZBUF_SIZE;
7758 inpPageptr.p->word32[tinpIndex] = tinpPrevFree;
7759 }//for
7760 /* --------------------------------------------------------------------------------- */
7761 /* INITIALISE HEADER POSITIONS NOT CURRENTLY USED AND ENSURE USE OF OVERFLOW */
7762 /* RECORD POINTER ON THIS PAGE LEADS TO ERROR. */
7763 /* --------------------------------------------------------------------------------- */
7764 inpPageptr.p->word32[ZPOS_CHECKSUM] = 0;
7765 inpPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] = 0;
7766 inpPageptr.p->word32[ZPOS_OVERFLOWREC] = RNIL;
7767 }//Dbacc::initPage()
7768
7769 /* --------------------------------------------------------------------------------- */
7770 /* PUT_OVERFLOW_REC_IN_FRAG */
7771 /* DESCRIPTION: AN OVERFLOW RECORD WITCH IS USED TO KEEP INFORMATION ABOUT */
7772 /* OVERFLOW PAGE WILL BE PUT IN A LIST OF OVERFLOW RECORDS IN */
7773 /* THE FRAGMENT RECORD. */
7774 /* --------------------------------------------------------------------------------- */
putOverflowRecInFrag(Signal * signal)7775 void Dbacc::putOverflowRecInFrag(Signal* signal)
7776 {
7777 OverflowRecordPtr tpifNextOverrecPtr;
7778 OverflowRecordPtr tpifPrevOverrecPtr;
7779
7780 tpifNextOverrecPtr.i = fragrecptr.p->firstOverflowRec;
7781 LINT_INIT(tpifPrevOverrecPtr.p);
7782 tpifPrevOverrecPtr.i = RNIL;
7783 while (tpifNextOverrecPtr.i != RNIL) {
7784 ptrCheckGuard(tpifNextOverrecPtr, coverflowrecsize, overflowRecord);
7785 if (tpifNextOverrecPtr.p->dirindex < porOverflowRecPtr.p->dirindex) {
7786 jam();
7787 /* --------------------------------------------------------------------------------- */
7788 /* PROCEED IN LIST TO THE NEXT IN THE LIST SINCE THE ENTRY HAD A LOWER PAGE ID.*/
7789 /* WE WANT TO ENSURE THAT LOWER PAGE ID'S ARE KEPT FULL RATHER THAN THE */
7790 /* OPPOSITE TO ENSURE THAT HIGH PAGE ID'S CAN BE REMOVED WHEN SHRINKS ARE */
7791 /* PERFORMED. */
7792 /* --------------------------------------------------------------------------------- */
7793 tpifPrevOverrecPtr = tpifNextOverrecPtr;
7794 tpifNextOverrecPtr.i = tpifNextOverrecPtr.p->nextOverRec;
7795 } else {
7796 jam();
7797 ndbrequire(tpifNextOverrecPtr.p->dirindex != porOverflowRecPtr.p->dirindex);
7798 /* --------------------------------------------------------------------------------- */
7799 /* TRYING TO INSERT THE SAME PAGE TWICE. SYSTEM ERROR. */
7800 /* --------------------------------------------------------------------------------- */
7801 break;
7802 }//if
7803 }//while
7804 if (tpifNextOverrecPtr.i == RNIL) {
7805 jam();
7806 fragrecptr.p->lastOverflowRec = porOverflowRecPtr.i;
7807 } else {
7808 jam();
7809 tpifNextOverrecPtr.p->prevOverRec = porOverflowRecPtr.i;
7810 }//if
7811 if (tpifPrevOverrecPtr.i == RNIL) {
7812 jam();
7813 fragrecptr.p->firstOverflowRec = porOverflowRecPtr.i;
7814 } else {
7815 jam();
7816 tpifPrevOverrecPtr.p->nextOverRec = porOverflowRecPtr.i;
7817 }//if
7818 porOverflowRecPtr.p->prevOverRec = tpifPrevOverrecPtr.i;
7819 porOverflowRecPtr.p->nextOverRec = tpifNextOverrecPtr.i;
7820 }//Dbacc::putOverflowRecInFrag()
7821
7822 /* --------------------------------------------------------------------------------- */
7823 /* PUT_REC_IN_FREE_OVERDIR */
7824 /* --------------------------------------------------------------------------------- */
putRecInFreeOverdir(Signal * signal)7825 void Dbacc::putRecInFreeOverdir(Signal* signal)
7826 {
7827 OverflowRecordPtr tpfoNextOverrecPtr;
7828 OverflowRecordPtr tpfoPrevOverrecPtr;
7829
7830 tpfoNextOverrecPtr.i = fragrecptr.p->firstFreeDirindexRec;
7831 LINT_INIT(tpfoPrevOverrecPtr.p);
7832 tpfoPrevOverrecPtr.i = RNIL;
7833 while (tpfoNextOverrecPtr.i != RNIL) {
7834 ptrCheckGuard(tpfoNextOverrecPtr, coverflowrecsize, overflowRecord);
7835 if (tpfoNextOverrecPtr.p->dirindex < priOverflowRecPtr.p->dirindex) {
7836 jam();
7837 /* --------------------------------------------------------------------------------- */
7838 /* PROCEED IN LIST TO THE NEXT IN THE LIST SINCE THE ENTRY HAD A LOWER PAGE ID.*/
7839 /* WE WANT TO ENSURE THAT LOWER PAGE ID'S ARE KEPT FULL RATHER THAN THE */
7840 /* OPPOSITE TO ENSURE THAT HIGH PAGE ID'S CAN BE REMOVED WHEN SHRINKS ARE */
7841 /* PERFORMED. */
7842 /* --------------------------------------------------------------------------------- */
7843 tpfoPrevOverrecPtr = tpfoNextOverrecPtr;
7844 tpfoNextOverrecPtr.i = tpfoNextOverrecPtr.p->nextOverList;
7845 } else {
7846 jam();
7847 ndbrequire(tpfoNextOverrecPtr.p->dirindex != priOverflowRecPtr.p->dirindex);
7848 /* --------------------------------------------------------------------------------- */
7849 /* ENSURE WE ARE NOT TRYING TO INSERT THE SAME PAGE TWICE. */
7850 /* --------------------------------------------------------------------------------- */
7851 break;
7852 }//if
7853 }//while
7854 if (tpfoNextOverrecPtr.i != RNIL) {
7855 jam();
7856 tpfoNextOverrecPtr.p->prevOverList = priOverflowRecPtr.i;
7857 }//if
7858 if (tpfoPrevOverrecPtr.i == RNIL) {
7859 jam();
7860 fragrecptr.p->firstFreeDirindexRec = priOverflowRecPtr.i;
7861 } else {
7862 jam();
7863 tpfoPrevOverrecPtr.p->nextOverList = priOverflowRecPtr.i;
7864 }//if
7865 priOverflowRecPtr.p->prevOverList = tpfoPrevOverrecPtr.i;
7866 priOverflowRecPtr.p->nextOverList = tpfoNextOverrecPtr.i;
7867 }//Dbacc::putRecInFreeOverdir()
7868
7869 /* --------------------------------------------------------------------------------- */
7870 /* RELEASE_DIRECTORY */
7871 /* --------------------------------------- ----------------------------------------- */
releaseDirectory(Signal * signal)7872 void Dbacc::releaseDirectory(Signal* signal)
7873 {
7874 ptrCheckGuard(rdDirptr, cdirarraysize, directoryarray);
7875 rdDirptr.p->pagep[0] = cfirstfreedir;
7876 cfirstfreedir = rdDirptr.i;
7877 }//Dbacc::releaseDirectory()
7878
7879 /* --------------------------------------------------------------------------------- */
7880 /* RELEASE_DIRRANGE */
7881 /* --------------------------------------------------------------------------------- */
releaseDirrange(Signal * signal)7882 void Dbacc::releaseDirrange(Signal* signal)
7883 {
7884 ptrCheckGuard(rdDirRangePtr, cdirrangesize, dirRange);
7885 rdDirRangePtr.p->dirArray[0] = cfirstfreeDirrange;
7886 cfirstfreeDirrange = rdDirRangePtr.i;
7887 }//Dbacc::releaseDirrange()
7888
7889 /* --------------------------------------------------------------------------------- */
7890 /* RELEASE OP RECORD */
7891 /* PUT A FREE OPERATION IN A FREE LIST OF THE OPERATIONS */
7892 /* --------------------------------------------------------------------------------- */
releaseOpRec(Signal * signal)7893 void Dbacc::releaseOpRec(Signal* signal)
7894 {
7895 #if 0
7896 // DEBUG CODE
7897 // Check that the operation to be released isn't
7898 // already in the list of free operations
7899 // Since this code loops through the entire list of free operations
7900 // it's only enabled in VM_TRACE mode
7901 OperationrecPtr opRecPtr;
7902 bool opInList = false;
7903 opRecPtr.i = cfreeopRec;
7904 while (opRecPtr.i != RNIL){
7905 if (opRecPtr.i == operationRecPtr.i){
7906 opInList = true;
7907 break;
7908 }
7909 ptrCheckGuard(opRecPtr, coprecsize, operationrec);
7910 opRecPtr.i = opRecPtr.p->nextOp;
7911 }
7912 ndbrequire(opInList == false);
7913 #endif
7914 ndbrequire(operationRecPtr.p->m_op_bits == Operationrec::OP_INITIAL);
7915
7916 operationRecPtr.p->nextOp = cfreeopRec;
7917 cfreeopRec = operationRecPtr.i; /* UPDATE FREE LIST OF OP RECORDS */
7918 operationRecPtr.p->prevOp = RNIL;
7919 operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
7920 }//Dbacc::releaseOpRec()
7921
7922 /* --------------------------------------------------------------------------------- */
7923 /* RELEASE_OVERFLOW_REC */
7924 /* PUT A FREE OVERFLOW REC IN A FREE LIST OF THE OVERFLOW RECORDS */
7925 /* --------------------------------------------------------------------------------- */
releaseOverflowRec(Signal * signal)7926 void Dbacc::releaseOverflowRec(Signal* signal)
7927 {
7928 rorOverflowRecPtr.p->nextfreeoverrec = cfirstfreeoverrec;
7929 cfirstfreeoverrec = rorOverflowRecPtr.i;
7930 }//Dbacc::releaseOverflowRec()
7931
7932 /* --------------------------------------------------------------------------------- */
7933 /* RELEASE_OVERPAGE */
7934 /* --------------------------------------------------------------------------------- */
releaseOverpage(Signal * signal)7935 void Dbacc::releaseOverpage(Signal* signal)
7936 {
7937 DirRangePtr ropOverflowrangeptr;
7938 DirectoryarrayPtr ropOverflowDirptr;
7939 OverflowRecordPtr ropOverflowRecPtr;
7940 OverflowRecordPtr tuodOverflowRecPtr;
7941 Uint32 tropTmp;
7942 Uint32 tropTmp1;
7943 Uint32 tropTmp2;
7944
7945 ropOverflowRecPtr.i = ropPageptr.p->word32[ZPOS_OVERFLOWREC];
7946 ndbrequire(ropOverflowRecPtr.i != RNIL);
7947 /* THE OVERFLOW REC WILL BE TAKEN OUT OF THE */
7948 /* FREELIST OF OVERFLOW PAGE WITH FREE */
7949 /* CONTAINER AND WILL BE PUT IN THE FREE LIST */
7950 /* OF THE FREE DIRECTORY INDEXES. */
7951 if ((fragrecptr.p->lastOverflowRec == ropOverflowRecPtr.i) &&
7952 (fragrecptr.p->firstOverflowRec == ropOverflowRecPtr.i)) {
7953 jam();
7954 return; /* THERE IS ONLY ONE OVERFLOW PAGE */
7955 }//if
7956 #if kalle
7957 logicalPage = 0;
7958
7959 i = fragrecptr.p->directory;
7960 p = dirRange.getPtr(i);
7961
7962 i1 = logicalPage >> 8;
7963 i2 = logicalPage & 0xFF;
7964
7965 ndbrequire(i1 < 256);
7966
7967 i = p->dirArray[i1];
7968 p = directoryarray.getPtr(i);
7969
7970 physicPageId = p->pagep[i2];
7971 physicPageP = page8.getPtr(physicPageId);
7972
7973 p->pagep[i2] = RNIL;
7974 rpPageptr = { physicPageId, physicPageP };
7975 releasePage(signal);
7976
7977 #endif
7978
7979 /* ----------------------------------------------------------------------- */
7980 /* IT WAS OK TO RELEASE THE PAGE. */
7981 /* ----------------------------------------------------------------------- */
7982 ptrCheckGuard(ropOverflowRecPtr, coverflowrecsize, overflowRecord);
7983 tfoOverflowRecPtr = ropOverflowRecPtr;
7984 takeRecOutOfFreeOverpage(signal);
7985 ropOverflowRecPtr.p->overpage = RNIL;
7986 priOverflowRecPtr = ropOverflowRecPtr;
7987 putRecInFreeOverdir(signal);
7988 tropTmp = ropPageptr.p->word32[ZPOS_PAGE_ID];
7989 ropOverflowrangeptr.i = fragrecptr.p->overflowdir;
7990 tropTmp1 = tropTmp >> 8;
7991 tropTmp2 = tropTmp & 0xff;
7992 ptrCheckGuard(ropOverflowrangeptr, cdirrangesize, dirRange);
7993 arrGuard(tropTmp1, 256);
7994 ropOverflowDirptr.i = ropOverflowrangeptr.p->dirArray[tropTmp1];
7995 ptrCheckGuard(ropOverflowDirptr, cdirarraysize, directoryarray);
7996 ropOverflowDirptr.p->pagep[tropTmp2] = RNIL;
7997 rpPageptr = ropPageptr;
7998 releasePage(signal);
7999 if (ropOverflowRecPtr.p->dirindex != (fragrecptr.p->lastOverIndex - 1)) {
8000 jam();
8001 return;
8002 }//if
8003 /* ----------------------------------------------------------------------- */
8004 /* THE LAST PAGE IN THE DIRECTORY WAS RELEASED IT IS NOW NECESSARY
8005 * TO REMOVE ALL RELEASED OVERFLOW DIRECTORIES AT THE END OF THE LIST.
8006 * ---------------------------------------------------------------------- */
8007 do {
8008 fragrecptr.p->lastOverIndex--;
8009 if (tropTmp2 == 0) {
8010 jam();
8011 ndbrequire(tropTmp1 != 0);
8012 ropOverflowrangeptr.p->dirArray[tropTmp1] = RNIL;
8013 rdDirptr.i = ropOverflowDirptr.i;
8014 releaseDirectory(signal);
8015 tropTmp1--;
8016 tropTmp2 = 255;
8017 } else {
8018 jam();
8019 tropTmp2--;
8020 }//if
8021 ropOverflowDirptr.i = ropOverflowrangeptr.p->dirArray[tropTmp1];
8022 ptrCheckGuard(ropOverflowDirptr, cdirarraysize, directoryarray);
8023 } while (ropOverflowDirptr.p->pagep[tropTmp2] == RNIL);
8024 /* ----------------------------------------------------------------------- */
8025 /* RELEASE ANY OVERFLOW RECORDS THAT ARE PART OF THE FREE INDEX LIST WHICH */
8026 /* DIRECTORY INDEX NOW HAS BEEN RELEASED. */
8027 /* ----------------------------------------------------------------------- */
8028 tuodOverflowRecPtr.i = fragrecptr.p->firstFreeDirindexRec;
8029 jam();
8030 while (tuodOverflowRecPtr.i != RNIL) {
8031 jam();
8032 ptrCheckGuard(tuodOverflowRecPtr, coverflowrecsize, overflowRecord);
8033 if (tuodOverflowRecPtr.p->dirindex >= fragrecptr.p->lastOverIndex) {
8034 jam();
8035 rorOverflowRecPtr = tuodOverflowRecPtr;
8036 troOverflowRecPtr.p = tuodOverflowRecPtr.p;
8037 tuodOverflowRecPtr.i = troOverflowRecPtr.p->nextOverList;
8038 takeRecOutOfFreeOverdir(signal);
8039 releaseOverflowRec(signal);
8040 } else {
8041 jam();
8042 tuodOverflowRecPtr.i = tuodOverflowRecPtr.p->nextOverList;
8043 }//if
8044 }//while
8045 }//Dbacc::releaseOverpage()
8046
8047
8048 extern Uint32 g_acc_pages_used[MAX_NDBMT_LQH_WORKERS];
8049
8050 /* ------------------------------------------------------------------------- */
8051 /* RELEASE_PAGE */
8052 /* ------------------------------------------------------------------------- */
releasePage(Signal * signal)8053 void Dbacc::releasePage(Signal* signal)
8054 {
8055 #ifdef VM_TRACE
8056 bool inList = false;
8057 Uint32 numInList = 0;
8058 Page8Ptr tmpPagePtr;
8059 tmpPagePtr.i = cfirstfreepage;
8060 while (tmpPagePtr.i != RNIL){
8061 ptrCheckGuard(tmpPagePtr, cpagesize, page8);
8062 if (tmpPagePtr.i == rpPageptr.i){
8063 jam(); inList = true;
8064 break;
8065 }
8066 numInList++;
8067 tmpPagePtr.i = tmpPagePtr.p->word32[0];
8068 }
8069 ndbrequire(inList == false);
8070 // ndbrequire(numInList == cnoOfAllocatedPages);
8071 #endif
8072 rpPageptr.p->word32[0] = cfirstfreepage;
8073 cfirstfreepage = rpPageptr.i;
8074 cnoOfAllocatedPages--;
8075
8076 g_acc_pages_used[instance()] = cnoOfAllocatedPages;
8077
8078 }//Dbacc::releasePage()
8079
8080 /* --------------------------------------------------------------------------------- */
8081 /* SEIZE_DIRECTORY */
8082 /* DESCRIPTION: A DIRECTORY BLOCK (ZDIRBLOCKSIZE NUMBERS OF DIRECTORY */
8083 /* RECORDS WILL BE ALLOCATED AND RETURNED. */
8084 /* SIZE OF DIRECTORY ERROR_CODE, WILL BE RETURNED IF THERE IS NO ANY */
8085 /* FREE BLOCK */
8086 /* --------------------------------------------------------------------------------- */
seizeDirectory(Signal * signal)8087 void Dbacc::seizeDirectory(Signal* signal)
8088 {
8089 Uint32 tsdyIndex;
8090
8091 if (cfirstfreedir == RNIL) {
8092 jam();
8093 if (cdirarraysize <= cdirmemory) {
8094 jam();
8095 tresult = ZDIRSIZE_ERROR;
8096 return;
8097 } else {
8098 jam();
8099 sdDirptr.i = cdirmemory;
8100 ptrCheckGuard(sdDirptr, cdirarraysize, directoryarray);
8101 cdirmemory = cdirmemory + 1;
8102 }//if
8103 } else {
8104 jam();
8105 sdDirptr.i = cfirstfreedir;
8106 ptrCheckGuard(sdDirptr, cdirarraysize, directoryarray);
8107 cfirstfreedir = sdDirptr.p->pagep[0];
8108 sdDirptr.p->pagep[0] = RNIL;
8109 }//if
8110 for (tsdyIndex = 0; tsdyIndex <= 255; tsdyIndex++) {
8111 sdDirptr.p->pagep[tsdyIndex] = RNIL;
8112 }//for
8113 }//Dbacc::seizeDirectory()
8114
8115 /* --------------------------------------------------------------------------------- */
8116 /* SEIZE_DIRRANGE */
8117 /* --------------------------------------------------------------------------------- */
seizeDirrange(Signal * signal)8118 void Dbacc::seizeDirrange(Signal* signal)
8119 {
8120 Uint32 tsdeIndex;
8121
8122 newDirRangePtr.i = cfirstfreeDirrange;
8123 ptrCheckGuard(newDirRangePtr, cdirrangesize, dirRange);
8124 cfirstfreeDirrange = newDirRangePtr.p->dirArray[0];
8125 for (tsdeIndex = 0; tsdeIndex <= 255; tsdeIndex++) {
8126 newDirRangePtr.p->dirArray[tsdeIndex] = RNIL;
8127 }//for
8128 }//Dbacc::seizeDirrange()
8129
8130 /* --------------------------------------------------------------------------------- */
8131 /* SEIZE FRAGREC */
8132 /* --------------------------------------------------------------------------------- */
seizeFragrec(Signal * signal)8133 void Dbacc::seizeFragrec(Signal* signal)
8134 {
8135 RSS_OP_ALLOC(cnoOfFreeFragrec);
8136 fragrecptr.i = cfirstfreefrag;
8137 ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
8138 cfirstfreefrag = fragrecptr.p->nextfreefrag;
8139 fragrecptr.p->nextfreefrag = RNIL;
8140 }//Dbacc::seizeFragrec()
8141
8142 /* --------------------------------------------------------------------------------- */
8143 /* SEIZE_OP_REC */
8144 /* --------------------------------------------------------------------------------- */
seizeOpRec(Signal * signal)8145 void Dbacc::seizeOpRec(Signal* signal)
8146 {
8147 operationRecPtr.i = cfreeopRec;
8148 ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
8149 cfreeopRec = operationRecPtr.p->nextOp; /* UPDATE FREE LIST OF OP RECORDS */
8150 /* PUTS OPERTION RECORD PTR IN THE LIST */
8151 /* OF OPERATION IN CONNECTION RECORD */
8152 operationRecPtr.p->nextOp = RNIL;
8153 }//Dbacc::seizeOpRec()
8154
8155 /* --------------------------------------------------------------------------------- */
8156 /* SEIZE OVERFLOW RECORD */
8157 /* --------------------------------------------------------------------------------- */
seizeOverRec(Signal * signal)8158 void Dbacc::seizeOverRec(Signal* signal) {
8159 sorOverflowRecPtr.i = cfirstfreeoverrec;
8160 ptrCheckGuard(sorOverflowRecPtr, coverflowrecsize, overflowRecord);
8161 cfirstfreeoverrec = sorOverflowRecPtr.p->nextfreeoverrec;
8162 sorOverflowRecPtr.p->nextfreeoverrec = RNIL;
8163 sorOverflowRecPtr.p->prevOverRec = RNIL;
8164 sorOverflowRecPtr.p->nextOverRec = RNIL;
8165 }//Dbacc::seizeOverRec()
8166
8167
8168 /**
8169 * A ZPAGESIZE_ERROR has occured, out of index pages
8170 * Print some debug info if debug compiled
8171 */
zpagesize_error(const char * where)8172 void Dbacc::zpagesize_error(const char* where){
8173 DEBUG(where << endl
8174 << " ZPAGESIZE_ERROR" << endl
8175 << " cfirstfreepage=" << cfirstfreepage << endl
8176 << " cpagesize=" <<cpagesize<<endl
8177 << " cnoOfAllocatedPages="<<cnoOfAllocatedPages);
8178 }
8179
8180
8181 /* --------------------------------------------------------------------------------- */
8182 /* SEIZE_PAGE */
8183 /* --------------------------------------------------------------------------------- */
seizePage(Signal * signal)8184 void Dbacc::seizePage(Signal* signal)
8185 {
8186 tresult = 0;
8187 if (cfirstfreepage == RNIL)
8188 {
8189 jam();
8190 zpagesize_error("Dbacc::seizePage");
8191 tresult = ZPAGESIZE_ERROR;
8192 }
8193 else
8194 {
8195 jam();
8196 spPageptr.i = cfirstfreepage;
8197 ptrCheckGuard(spPageptr, cpagesize, page8);
8198 cfirstfreepage = spPageptr.p->word32[0];
8199 cnoOfAllocatedPages++;
8200
8201 if (cnoOfAllocatedPages > cnoOfAllocatedPagesMax)
8202 cnoOfAllocatedPagesMax = cnoOfAllocatedPages;
8203
8204 g_acc_pages_used[instance()] = cnoOfAllocatedPages;
8205
8206 }
8207
8208 }//Dbacc::seizePage()
8209
8210 /* --------------------------------------------------------------------------------- */
8211 /* SEIZE_ROOTFRAGREC */
8212 /* --------------------------------------------------------------------------------- */
8213
8214 /* --------------------------------------------------------------------------------- */
8215 /* SEIZE_SCAN_REC */
8216 /* --------------------------------------------------------------------------------- */
seizeScanRec(Signal * signal)8217 void Dbacc::seizeScanRec(Signal* signal)
8218 {
8219 scanPtr.i = cfirstFreeScanRec;
8220 ptrCheckGuard(scanPtr, cscanRecSize, scanRec);
8221 ndbrequire(scanPtr.p->scanState == ScanRec::SCAN_DISCONNECT);
8222 cfirstFreeScanRec = scanPtr.p->scanNextfreerec;
8223 }//Dbacc::seizeScanRec()
8224
8225 /* --------------------------------------------------------------------------------- */
8226 /* SEIZE_SR_VERSION_REC */
8227 /* --------------------------------------------------------------------------------- */
8228 /* --------------------------------------------------------------------------------- */
8229 /* SEND_SYSTEMERROR */
8230 /* --------------------------------------------------------------------------------- */
sendSystemerror(Signal * signal,int line)8231 void Dbacc::sendSystemerror(Signal* signal, int line)
8232 {
8233 progError(line, NDBD_EXIT_PRGERR);
8234 }//Dbacc::sendSystemerror()
8235
8236 /* --------------------------------------------------------------------------------- */
8237 /* TAKE_REC_OUT_OF_FREE_OVERDIR */
8238 /* --------------------------------------------------------------------------------- */
takeRecOutOfFreeOverdir(Signal * signal)8239 void Dbacc::takeRecOutOfFreeOverdir(Signal* signal)
8240 {
8241 OverflowRecordPtr tofoOverrecPtr;
8242 if (troOverflowRecPtr.p->nextOverList != RNIL) {
8243 jam();
8244 tofoOverrecPtr.i = troOverflowRecPtr.p->nextOverList;
8245 ptrCheckGuard(tofoOverrecPtr, coverflowrecsize, overflowRecord);
8246 tofoOverrecPtr.p->prevOverList = troOverflowRecPtr.p->prevOverList;
8247 }//if
8248 if (troOverflowRecPtr.p->prevOverList != RNIL) {
8249 jam();
8250 tofoOverrecPtr.i = troOverflowRecPtr.p->prevOverList;
8251 ptrCheckGuard(tofoOverrecPtr, coverflowrecsize, overflowRecord);
8252 tofoOverrecPtr.p->nextOverList = troOverflowRecPtr.p->nextOverList;
8253 } else {
8254 jam();
8255 fragrecptr.p->firstFreeDirindexRec = troOverflowRecPtr.p->nextOverList;
8256 }//if
8257 }//Dbacc::takeRecOutOfFreeOverdir()
8258
8259 /* --------------------------------------------------------------------------------- */
8260 /* TAKE_REC_OUT_OF_FREE_OVERPAGE */
8261 /* DESCRIPTION: AN OVERFLOW PAGE WHICH IS EMPTY HAVE TO BE TAKE OUT OF THE */
8262 /* FREE LIST OF OVERFLOW PAGE. BY THIS SUBROUTINE THIS LIST */
8263 /* WILL BE UPDATED. */
8264 /* --------------------------------------------------------------------------------- */
takeRecOutOfFreeOverpage(Signal * signal)8265 void Dbacc::takeRecOutOfFreeOverpage(Signal* signal)
8266 {
8267 OverflowRecordPtr tfoNextOverflowRecPtr;
8268 OverflowRecordPtr tfoPrevOverflowRecPtr;
8269
8270 if (tfoOverflowRecPtr.p->nextOverRec != RNIL) {
8271 jam();
8272 tfoNextOverflowRecPtr.i = tfoOverflowRecPtr.p->nextOverRec;
8273 ptrCheckGuard(tfoNextOverflowRecPtr, coverflowrecsize, overflowRecord);
8274 tfoNextOverflowRecPtr.p->prevOverRec = tfoOverflowRecPtr.p->prevOverRec;
8275 } else {
8276 ndbrequire(fragrecptr.p->lastOverflowRec == tfoOverflowRecPtr.i);
8277 jam();
8278 fragrecptr.p->lastOverflowRec = tfoOverflowRecPtr.p->prevOverRec;
8279 }//if
8280 if (tfoOverflowRecPtr.p->prevOverRec != RNIL) {
8281 jam();
8282 tfoPrevOverflowRecPtr.i = tfoOverflowRecPtr.p->prevOverRec;
8283 ptrCheckGuard(tfoPrevOverflowRecPtr, coverflowrecsize, overflowRecord);
8284 tfoPrevOverflowRecPtr.p->nextOverRec = tfoOverflowRecPtr.p->nextOverRec;
8285 } else {
8286 ndbrequire(fragrecptr.p->firstOverflowRec == tfoOverflowRecPtr.i);
8287 jam();
8288 fragrecptr.p->firstOverflowRec = tfoOverflowRecPtr.p->nextOverRec;
8289 }//if
8290 }//Dbacc::takeRecOutOfFreeOverpage()
8291
8292
execDBINFO_SCANREQ(Signal * signal)8293 void Dbacc::execDBINFO_SCANREQ(Signal *signal)
8294 {
8295 jamEntry();
8296 DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
8297 const Ndbinfo::ScanCursor* cursor =
8298 CAST_CONSTPTR(Ndbinfo::ScanCursor, DbinfoScan::getCursorPtr(&req));
8299
8300 Ndbinfo::Ratelimit rl;
8301
8302 switch(req.tableId){
8303 case Ndbinfo::POOLS_TABLEID:
8304 {
8305 jam();
8306
8307 Ndbinfo::pool_entry pools[] =
8308 {
8309 { "Index memory",
8310 cnoOfAllocatedPages,
8311 cpageCount,
8312 sizeof(Page8),
8313 cnoOfAllocatedPagesMax,
8314 { CFG_DB_INDEX_MEM,0,0,0 }},
8315 { NULL, 0,0,0,0,{ 0,0,0,0 }}
8316 };
8317
8318 static const size_t num_config_params =
8319 sizeof(pools[0].config_params)/sizeof(pools[0].config_params[0]);
8320 Uint32 pool = cursor->data[0];
8321 BlockNumber bn = blockToMain(number());
8322 while(pools[pool].poolname)
8323 {
8324 jam();
8325 Ndbinfo::Row row(signal, req);
8326 row.write_uint32(getOwnNodeId());
8327 row.write_uint32(bn); // block number
8328 row.write_uint32(instance()); // block instance
8329 row.write_string(pools[pool].poolname);
8330
8331 row.write_uint64(pools[pool].used);
8332 row.write_uint64(pools[pool].total);
8333 row.write_uint64(pools[pool].used_hi);
8334 row.write_uint64(pools[pool].entry_size);
8335 for (size_t i = 0; i < num_config_params; i++)
8336 row.write_uint32(pools[pool].config_params[i]);
8337 ndbinfo_send_row(signal, req, row, rl);
8338 pool++;
8339 if (rl.need_break(req))
8340 {
8341 jam();
8342 ndbinfo_send_scan_break(signal, req, rl, pool);
8343 return;
8344 }
8345 }
8346 }
8347 default:
8348 break;
8349 }
8350
8351 ndbinfo_send_scan_conf(signal, req, rl);
8352 }
8353
8354 void
execDUMP_STATE_ORD(Signal * signal)8355 Dbacc::execDUMP_STATE_ORD(Signal* signal)
8356 {
8357 DumpStateOrd * const dumpState = (DumpStateOrd *)&signal->theData[0];
8358 if (dumpState->args[0] == DumpStateOrd::AccDumpOneScanRec){
8359 Uint32 recordNo = RNIL;
8360 if (signal->length() == 2)
8361 recordNo = dumpState->args[1];
8362 else
8363 return;
8364
8365 if (recordNo >= cscanRecSize)
8366 return;
8367
8368 scanPtr.i = recordNo;
8369 ptrAss(scanPtr, scanRec);
8370 infoEvent("Dbacc::ScanRec[%d]: state=%d, transid(0x%x, 0x%x)",
8371 scanPtr.i, scanPtr.p->scanState,scanPtr.p->scanTrid1,
8372 scanPtr.p->scanTrid2);
8373 infoEvent(" activeLocalFrag=%d, nextBucketIndex=%d",
8374 scanPtr.p->activeLocalFrag,
8375 scanPtr.p->nextBucketIndex);
8376 infoEvent(" scanNextfreerec=%d firstActOp=%d firstLockedOp=%d, "
8377 "scanLastLockedOp=%d firstQOp=%d lastQOp=%d",
8378 scanPtr.p->scanNextfreerec,
8379 scanPtr.p->scanFirstActiveOp,
8380 scanPtr.p->scanFirstLockedOp,
8381 scanPtr.p->scanLastLockedOp,
8382 scanPtr.p->scanFirstQueuedOp,
8383 scanPtr.p->scanLastQueuedOp);
8384 infoEvent(" scanUserP=%d, startNoBuck=%d, minBucketIndexToRescan=%d, "
8385 "maxBucketIndexToRescan=%d",
8386 scanPtr.p->scanUserptr,
8387 scanPtr.p->startNoOfBuckets,
8388 scanPtr.p->minBucketIndexToRescan,
8389 scanPtr.p->maxBucketIndexToRescan);
8390 infoEvent(" scanBucketState=%d, scanLockHeld=%d, userBlockRef=%d, "
8391 "scanMask=%d scanLockMode=%d",
8392 scanPtr.p->scanBucketState,
8393 scanPtr.p->scanLockHeld,
8394 scanPtr.p->scanUserblockref,
8395 scanPtr.p->scanMask,
8396 scanPtr.p->scanLockMode);
8397 return;
8398 }
8399
8400 // Dump all ScanRec(ords)
8401 if (dumpState->args[0] == DumpStateOrd::AccDumpAllScanRec){
8402 Uint32 recordNo = 0;
8403 if (signal->length() == 1)
8404 infoEvent("ACC: Dump all ScanRec - size: %d",
8405 cscanRecSize);
8406 else if (signal->length() == 2)
8407 recordNo = dumpState->args[1];
8408 else
8409 return;
8410
8411 dumpState->args[0] = DumpStateOrd::AccDumpOneScanRec;
8412 dumpState->args[1] = recordNo;
8413 execDUMP_STATE_ORD(signal);
8414
8415 if (recordNo < cscanRecSize-1){
8416 dumpState->args[0] = DumpStateOrd::AccDumpAllScanRec;
8417 dumpState->args[1] = recordNo+1;
8418 sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
8419 }
8420 return;
8421 }
8422
8423 // Dump all active ScanRec(ords)
8424 if (dumpState->args[0] == DumpStateOrd::AccDumpAllActiveScanRec){
8425 Uint32 recordNo = 0;
8426 if (signal->length() == 1)
8427 infoEvent("ACC: Dump active ScanRec - size: %d",
8428 cscanRecSize);
8429 else if (signal->length() == 2)
8430 recordNo = dumpState->args[1];
8431 else
8432 return;
8433
8434 ScanRecPtr sp;
8435 sp.i = recordNo;
8436 ptrAss(sp, scanRec);
8437 if (sp.p->scanState != ScanRec::SCAN_DISCONNECT){
8438 dumpState->args[0] = DumpStateOrd::AccDumpOneScanRec;
8439 dumpState->args[1] = recordNo;
8440 execDUMP_STATE_ORD(signal);
8441 }
8442
8443 if (recordNo < cscanRecSize-1){
8444 dumpState->args[0] = DumpStateOrd::AccDumpAllActiveScanRec;
8445 dumpState->args[1] = recordNo+1;
8446 sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
8447 }
8448 return;
8449 }
8450
8451 if(dumpState->args[0] == DumpStateOrd::EnableUndoDelayDataWrite){
8452 ndbout << "Dbacc:: delay write of datapages for table = "
8453 << dumpState->args[1]<< endl;
8454 c_errorInsert3000_TableId = dumpState->args[1];
8455 SET_ERROR_INSERT_VALUE(3000);
8456 return;
8457 }
8458
8459 if(dumpState->args[0] == DumpStateOrd::AccDumpOneOperationRec){
8460 Uint32 recordNo = RNIL;
8461 if (signal->length() == 2)
8462 recordNo = dumpState->args[1];
8463 else
8464 return;
8465
8466 if (recordNo >= coprecsize)
8467 return;
8468
8469 OperationrecPtr tmpOpPtr;
8470 tmpOpPtr.i = recordNo;
8471 ptrAss(tmpOpPtr, operationrec);
8472 infoEvent("Dbacc::operationrec[%d]: transid(0x%x, 0x%x)",
8473 tmpOpPtr.i, tmpOpPtr.p->transId1,
8474 tmpOpPtr.p->transId2);
8475 infoEvent("elementIsforward=%d, elementPage=%d, elementPointer=%d ",
8476 tmpOpPtr.p->elementIsforward, tmpOpPtr.p->elementPage,
8477 tmpOpPtr.p->elementPointer);
8478 infoEvent("fid=%d, fragptr=%d, hashvaluePart=%d ",
8479 tmpOpPtr.p->fid, tmpOpPtr.p->fragptr,
8480 tmpOpPtr.p->hashvaluePart);
8481 infoEvent("hashValue=%d", tmpOpPtr.p->hashValue);
8482 infoEvent("nextLockOwnerOp=%d, nextOp=%d, nextParallelQue=%d ",
8483 tmpOpPtr.p->nextLockOwnerOp, tmpOpPtr.p->nextOp,
8484 tmpOpPtr.p->nextParallelQue);
8485 infoEvent("nextSerialQue=%d, prevOp=%d ",
8486 tmpOpPtr.p->nextSerialQue,
8487 tmpOpPtr.p->prevOp);
8488 infoEvent("prevLockOwnerOp=%d, prevParallelQue=%d",
8489 tmpOpPtr.p->prevLockOwnerOp, tmpOpPtr.p->nextParallelQue);
8490 infoEvent("prevSerialQue=%d, scanRecPtr=%d",
8491 tmpOpPtr.p->prevSerialQue, tmpOpPtr.p->scanRecPtr);
8492 infoEvent("m_op_bits=0x%x, scanBits=%d ",
8493 tmpOpPtr.p->m_op_bits, tmpOpPtr.p->scanBits);
8494 return;
8495 }
8496
8497 if(dumpState->args[0] == DumpStateOrd::AccDumpNumOpRecs){
8498
8499 Uint32 freeOpRecs = 0;
8500 OperationrecPtr opRecPtr;
8501 opRecPtr.i = cfreeopRec;
8502 while (opRecPtr.i != RNIL){
8503 freeOpRecs++;
8504 ptrCheckGuard(opRecPtr, coprecsize, operationrec);
8505 opRecPtr.i = opRecPtr.p->nextOp;
8506 }
8507
8508 infoEvent("Dbacc::OperationRecords: num=%d, free=%d",
8509 coprecsize, freeOpRecs);
8510
8511 return;
8512 }
8513 if(dumpState->args[0] == DumpStateOrd::AccDumpFreeOpRecs){
8514
8515 OperationrecPtr opRecPtr;
8516 opRecPtr.i = cfreeopRec;
8517 while (opRecPtr.i != RNIL){
8518
8519 dumpState->args[0] = DumpStateOrd::AccDumpOneOperationRec;
8520 dumpState->args[1] = opRecPtr.i;
8521 execDUMP_STATE_ORD(signal);
8522
8523 ptrCheckGuard(opRecPtr, coprecsize, operationrec);
8524 opRecPtr.i = opRecPtr.p->nextOp;
8525 }
8526
8527
8528 return;
8529 }
8530
8531 if(dumpState->args[0] == DumpStateOrd::AccDumpNotFreeOpRecs){
8532 Uint32 recordStart = RNIL;
8533 if (signal->length() == 2)
8534 recordStart = dumpState->args[1];
8535 else
8536 return;
8537
8538 if (recordStart >= coprecsize)
8539 return;
8540
8541 for (Uint32 i = recordStart; i < coprecsize; i++){
8542
8543 bool inFreeList = false;
8544 OperationrecPtr opRecPtr;
8545 opRecPtr.i = cfreeopRec;
8546 while (opRecPtr.i != RNIL){
8547 if (opRecPtr.i == i){
8548 inFreeList = true;
8549 break;
8550 }
8551 ptrCheckGuard(opRecPtr, coprecsize, operationrec);
8552 opRecPtr.i = opRecPtr.p->nextOp;
8553 }
8554 if (inFreeList == false){
8555 dumpState->args[0] = DumpStateOrd::AccDumpOneOperationRec;
8556 dumpState->args[1] = i;
8557 execDUMP_STATE_ORD(signal);
8558 }
8559 }
8560 return;
8561 }
8562
8563 #if 0
8564 if (type == 100) {
8565 RelTabMemReq * const req = (RelTabMemReq *)signal->getDataPtrSend();
8566 req->primaryTableId = 2;
8567 req->secondaryTableId = RNIL;
8568 req->userPtr = 2;
8569 req->userRef = DBDICT_REF;
8570 sendSignal(cownBlockref, GSN_REL_TABMEMREQ, signal,
8571 RelTabMemReq::SignalLength, JBB);
8572 return;
8573 }//if
8574 if (type == 101) {
8575 RelTabMemReq * const req = (RelTabMemReq *)signal->getDataPtrSend();
8576 req->primaryTableId = 4;
8577 req->secondaryTableId = 5;
8578 req->userPtr = 4;
8579 req->userRef = DBDICT_REF;
8580 sendSignal(cownBlockref, GSN_REL_TABMEMREQ, signal,
8581 RelTabMemReq::SignalLength, JBB);
8582 return;
8583 }//if
8584 if (type == 102) {
8585 RelTabMemReq * const req = (RelTabMemReq *)signal->getDataPtrSend();
8586 req->primaryTableId = 6;
8587 req->secondaryTableId = 8;
8588 req->userPtr = 6;
8589 req->userRef = DBDICT_REF;
8590 sendSignal(cownBlockref, GSN_REL_TABMEMREQ, signal,
8591 RelTabMemReq::SignalLength, JBB);
8592 return;
8593 }//if
8594 if (type == 103) {
8595 DropTabFileReq * const req = (DropTabFileReq *)signal->getDataPtrSend();
8596 req->primaryTableId = 2;
8597 req->secondaryTableId = RNIL;
8598 req->userPtr = 2;
8599 req->userRef = DBDICT_REF;
8600 sendSignal(cownBlockref, GSN_DROP_TABFILEREQ, signal,
8601 DropTabFileReq::SignalLength, JBB);
8602 return;
8603 }//if
8604 if (type == 104) {
8605 DropTabFileReq * const req = (DropTabFileReq *)signal->getDataPtrSend();
8606 req->primaryTableId = 4;
8607 req->secondaryTableId = 5;
8608 req->userPtr = 4;
8609 req->userRef = DBDICT_REF;
8610 sendSignal(cownBlockref, GSN_DROP_TABFILEREQ, signal,
8611 DropTabFileReq::SignalLength, JBB);
8612 return;
8613 }//if
8614 if (type == 105) {
8615 DropTabFileReq * const req = (DropTabFileReq *)signal->getDataPtrSend();
8616 req->primaryTableId = 6;
8617 req->secondaryTableId = 8;
8618 req->userPtr = 6;
8619 req->userRef = DBDICT_REF;
8620 sendSignal(cownBlockref, GSN_DROP_TABFILEREQ, signal,
8621 DropTabFileReq::SignalLength, JBB);
8622 return;
8623 }//if
8624 #endif
8625
8626 if (signal->theData[0] == DumpStateOrd::SchemaResourceSnapshot)
8627 {
8628 RSS_OP_SNAPSHOT_SAVE(cnoOfFreeFragrec);
8629 return;
8630 }
8631
8632 if (signal->theData[0] == DumpStateOrd::SchemaResourceCheckLeak)
8633 {
8634 RSS_OP_SNAPSHOT_CHECK(cnoOfFreeFragrec);
8635 return;
8636 }
8637 }//Dbacc::execDUMP_STATE_ORD()
8638
8639 void
execREAD_PSEUDO_REQ(Signal * signal)8640 Dbacc::execREAD_PSEUDO_REQ(Signal* signal){
8641 jamEntry();
8642 fragrecptr.i = signal->theData[0];
8643 Uint32 attrId = signal->theData[1];
8644 ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
8645 Uint64 tmp;
8646 switch(attrId){
8647 case AttributeHeader::ROW_COUNT:
8648 tmp = fragrecptr.p->noOfElements;
8649 break;
8650 case AttributeHeader::COMMIT_COUNT:
8651 tmp = fragrecptr.p->m_commit_count;
8652 break;
8653 default:
8654 tmp = 0;
8655 }
8656 memcpy(signal->theData, &tmp, 8); /* must be memcpy, gives strange results on
8657 * ithanium gcc (GCC) 3.4.1 smp linux 2.4
8658 * otherwise
8659 */
8660 // Uint32 * src = (Uint32*)&tmp;
8661 // signal->theData[0] = src[0];
8662 // signal->theData[1] = src[1];
8663 }
8664
8665 #ifdef VM_TRACE
8666 void
debug_lh_vars(const char * where)8667 Dbacc::debug_lh_vars(const char* where)
8668 {
8669 Uint32 b = fragrecptr.p->maxp + fragrecptr.p->p;
8670 Uint32 di = b >> fragrecptr.p->k;
8671 Uint32 ri = di >> 8;
8672 ndbout
8673 << "DBACC: " << where << ":"
8674 << " frag:" << fragrecptr.p->myTableId
8675 << "/" << fragrecptr.p->myfid
8676 << " slack:" << (Int32)fragrecptr.p->slack
8677 << "/" << fragrecptr.p->slackCheck
8678 << " maxp:" << fragrecptr.p->maxp
8679 << " p:" << fragrecptr.p->p
8680 << " di:" << di
8681 << " ri:" << ri
8682 << " full:" << fragrecptr.p->dirRangeFull
8683 << "\n";
8684 }
8685 #endif
8686