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