MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DbaccMain.cpp
1 /*
2  Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #define DBACC_C
19 #include "Dbacc.hpp"
20 
21 #include <AttributeHeader.hpp>
22 #include <signaldata/AccFrag.hpp>
23 #include <signaldata/AccScan.hpp>
24 #include <signaldata/NextScan.hpp>
25 #include <signaldata/AccLock.hpp>
26 #include <signaldata/EventReport.hpp>
27 #include <signaldata/FsConf.hpp>
28 #include <signaldata/FsRef.hpp>
29 #include <signaldata/FsRemoveReq.hpp>
30 #include <signaldata/DropTab.hpp>
31 #include <signaldata/DumpStateOrd.hpp>
32 #include <signaldata/TuxMaint.hpp>
33 #include <signaldata/DbinfoScan.hpp>
34 #include <signaldata/TransIdAI.hpp>
35 #include <KeyDescriptor.hpp>
36 
37 #ifdef VM_TRACE
38 #define DEBUG(x) ndbout << "DBACC: "<< x << endl;
39 #else
40 #define DEBUG(x)
41 #endif
42 
43 #ifdef ACC_SAFE_QUEUE
44 #define vlqrequire(x) do { if (unlikely(!(x))) {\
45  dump_lock_queue(loPtr); \
46  ndbrequire(false); } } while(0)
47 #else
48 #define vlqrequire(x) ndbrequire(x)
49 #define dump_lock_queue(x)
50 #endif
51 
52 
53 // primary key is stored in TUP
54 #include "../dbtup/Dbtup.hpp"
55 #include "../dblqh/Dblqh.hpp"
56 
57 
58 // Signal entries and statement blocks
59 /* --------------------------------------------------------------------------------- */
60 /* --------------------------------------------------------------------------------- */
61 /* --------------------------------------------------------------------------------- */
62 /* */
63 /* COMMON SIGNAL RECEPTION MODULE */
64 /* */
65 /* --------------------------------------------------------------------------------- */
66 
67 /* --------------------------------------------------------------------------------- */
68 /* ******************--------------------------------------------------------------- */
69 /* CONTINUEB CONTINUE SIGNAL */
70 /* ******************------------------------------+ */
71 /* SENDER: ACC, LEVEL B */
72 void Dbacc::execCONTINUEB(Signal* signal)
73 {
74  Uint32 tcase;
75 
76  jamEntry();
77  tcase = signal->theData[0];
78  tdata0 = signal->theData[1];
79  tresult = 0;
80  switch (tcase) {
81  case ZINITIALISE_RECORDS:
82  jam();
83  initialiseRecordsLab(signal, signal->theData[3], signal->theData[4]);
84  return;
85  break;
86  case ZREL_ROOT_FRAG:
87  {
88  jam();
89  Uint32 tableId = signal->theData[1];
90  releaseRootFragResources(signal, tableId);
91  break;
92  }
93  case ZREL_FRAG:
94  {
95  jam();
96  Uint32 fragIndex = signal->theData[1];
97  releaseFragResources(signal, fragIndex);
98  break;
99  }
100  case ZREL_DIR:
101  {
102  jam();
103  Uint32 fragIndex = signal->theData[1];
104  Uint32 dirIndex = signal->theData[2];
105  Uint32 startIndex = signal->theData[3];
106  releaseDirResources(signal, fragIndex, dirIndex, startIndex);
107  break;
108  }
109 
110  default:
111  ndbrequire(false);
112  break;
113  }//switch
114  return;
115 }//Dbacc::execCONTINUEB()
116 
117 /* ------------------------------------------------------------------------- */
118 /* ------------------------------------------------------------------------- */
119 /* ------------------------------------------------------------------------- */
120 /* */
121 /* END OF COMMON SIGNAL RECEPTION MODULE */
122 /* */
123 /* ------------------------------------------------------------------------- */
124 /* ------------------------------------------------------------------------- */
125 /* ------------------------------------------------------------------------- */
126 /* ------------------------------------------------------------------------- */
127 /* ------------------------------------------------------------------------- */
128 /* */
129 /* SYSTEM RESTART MODULE */
130 /* */
131 /* ------------------------------------------------------------------------- */
132 /* ------------------------------------------------------------------------- */
133 /* ------------------------------------------------------------------------- */
134 void Dbacc::execNDB_STTOR(Signal* signal)
135 {
136  Uint32 tstartphase;
137  Uint32 tStartType;
138 
139  jamEntry();
140  cndbcntrRef = signal->theData[0];
141  cmynodeid = signal->theData[1];
142  tstartphase = signal->theData[2];
143  tStartType = signal->theData[3];
144  switch (tstartphase) {
145  case ZSPH1:
146  jam();
147  ndbsttorryLab(signal);
148  return;
149  break;
150  case ZSPH2:
151  ndbsttorryLab(signal);
152  return;
153  break;
154  case ZSPH3:
155  break;
156  case ZSPH6:
157  jam();
158  break;
159  default:
160  jam();
161  /*empty*/;
162  break;
163  }//switch
164  ndbsttorryLab(signal);
165  return;
166 }//Dbacc::execNDB_STTOR()
167 
168 /* ******************--------------------------------------------------------------- */
169 /* STTOR START / RESTART */
170 /* ******************------------------------------+ */
171 /* SENDER: ANY, LEVEL B */
172 void Dbacc::execSTTOR(Signal* signal)
173 {
174  jamEntry();
175  Uint32 tstartphase = signal->theData[1];
176  switch (tstartphase) {
177  case 1:
178  jam();
179  ndbrequire((c_tup = (Dbtup*)globalData.getBlock(DBTUP, instance())) != 0);
180  ndbrequire((c_lqh = (Dblqh*)globalData.getBlock(DBLQH, instance())) != 0);
181  break;
182  }
183  tuserblockref = signal->theData[3];
184  csignalkey = signal->theData[6];
185  sttorrysignalLab(signal);
186  return;
187 }//Dbacc::execSTTOR()
188 
189 /* --------------------------------------------------------------------------------- */
190 /* ZSPH1 */
191 /* --------------------------------------------------------------------------------- */
192 void Dbacc::ndbrestart1Lab(Signal* signal)
193 {
194  cmynodeid = globalData.ownId;
195  cownBlockref = calcInstanceBlockRef(DBACC);
196  czero = 0;
197  cminusOne = czero - 1;
198  ctest = 0;
199  return;
200 }//Dbacc::ndbrestart1Lab()
201 
202 void Dbacc::initialiseRecordsLab(Signal* signal, Uint32 ref, Uint32 data)
203 {
204  switch (tdata0) {
205  case 0:
206  jam();
207  initialiseTableRec(signal);
208  break;
209  case 1:
210  case 2:
211  break;
212  case 3:
213  jam();
214  break;
215  case 4:
216  jam();
217  initialiseDirRec(signal);
218  break;
219  case 5:
220  jam();
221  initialiseDirRangeRec(signal);
222  break;
223  case 6:
224  jam();
225  initialiseFragRec(signal);
226  break;
227  case 7:
228  jam();
229  initialiseOverflowRec(signal);
230  break;
231  case 8:
232  jam();
233  initialiseOperationRec(signal);
234  break;
235  case 9:
236  jam();
237  initialisePageRec(signal);
238  break;
239  case 10:
240  jam();
241  break;
242  case 11:
243  jam();
244  initialiseScanRec(signal);
245  break;
246  case 12:
247  jam();
248 
249  {
250  ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
251  conf->senderRef = reference();
252  conf->senderData = data;
253  sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
254  ReadConfigConf::SignalLength, JBB);
255  }
256  return;
257  break;
258  default:
259  ndbrequire(false);
260  break;
261  }//switch
262 
263  signal->theData[0] = ZINITIALISE_RECORDS;
264  signal->theData[1] = tdata0 + 1;
265  signal->theData[2] = 0;
266  signal->theData[3] = ref;
267  signal->theData[4] = data;
268  sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);
269  return;
270 }//Dbacc::initialiseRecordsLab()
271 
272 /* *********************************<< */
273 /* NDB_STTORRY */
274 /* *********************************<< */
275 void Dbacc::ndbsttorryLab(Signal* signal)
276 {
277  signal->theData[0] = cownBlockref;
278  sendSignal(cndbcntrRef, GSN_NDB_STTORRY, signal, 1, JBB);
279  return;
280 }//Dbacc::ndbsttorryLab()
281 
282 /* *********************************<< */
283 /* SIZEALT_REP SIZE ALTERATION */
284 /* *********************************<< */
285 void Dbacc::execREAD_CONFIG_REQ(Signal* signal)
286 {
287  const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
288  Uint32 ref = req->senderRef;
289  Uint32 senderData = req->senderData;
290  ndbrequire(req->noOfParameters == 0);
291 
292  jamEntry();
293 
294  const ndb_mgm_configuration_iterator * p =
295  m_ctx.m_config.getOwnConfigIterator();
296  ndbrequire(p != 0);
297 
298  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_DIR_RANGE, &cdirrangesize));
299  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_DIR_ARRAY, &cdirarraysize));
300  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_FRAGMENT, &cfragmentsize));
301  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_OP_RECS, &coprecsize));
302  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_OVERFLOW_RECS,
303  &coverflowrecsize));
304  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_PAGE8, &cpagesize));
305  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_TABLE, &ctablesize));
306  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_ACC_SCAN, &cscanRecSize));
307  initRecords();
308  ndbrestart1Lab(signal);
309 
310  c_memusage_report_frequency = 0;
311  ndb_mgm_get_int_parameter(p, CFG_DB_MEMREPORT_FREQUENCY,
312  &c_memusage_report_frequency);
313 
314  tdata0 = 0;
315  initialiseRecordsLab(signal, ref, senderData);
316  return;
317 }//Dbacc::execSIZEALT_REP()
318 
319 /* *********************************<< */
320 /* STTORRY */
321 /* *********************************<< */
322 void Dbacc::sttorrysignalLab(Signal* signal)
323 {
324  signal->theData[0] = csignalkey;
325  signal->theData[1] = 3;
326  /* BLOCK CATEGORY */
327  signal->theData[2] = 2;
328  /* SIGNAL VERSION NUMBER */
329  signal->theData[3] = ZSPH1;
330  signal->theData[4] = 255;
331  BlockReference cntrRef = !isNdbMtLqh() ? NDBCNTR_REF : DBACC_REF;
332  sendSignal(cntrRef, GSN_STTORRY, signal, 5, JBB);
333  /* END OF START PHASES */
334  return;
335 }//Dbacc::sttorrysignalLab()
336 
337 /* --------------------------------------------------------------------------------- */
338 /* INITIALISE_DIR_REC */
339 /* INITIALATES THE DIRECTORY RECORDS. */
340 /* --------------------------------------------------------------------------------- */
341 void Dbacc::initialiseDirRec(Signal* signal)
342 {
343  DirectoryarrayPtr idrDirptr;
344  ndbrequire(cdirarraysize > 0);
345  for (idrDirptr.i = 0; idrDirptr.i < cdirarraysize; idrDirptr.i++) {
347  ptrAss(idrDirptr, directoryarray);
348  for (Uint32 i = 0; i <= 255; i++) {
349  idrDirptr.p->pagep[i] = RNIL;
350  }//for
351  }//for
352  cdirmemory = 0;
353  cfirstfreedir = RNIL;
354 }//Dbacc::initialiseDirRec()
355 
356 /* --------------------------------------------------------------------------------- */
357 /* INITIALISE_DIR_RANGE_REC */
358 /* INITIALATES THE DIR_RANGE RECORDS. */
359 /* --------------------------------------------------------------------------------- */
360 void Dbacc::initialiseDirRangeRec(Signal* signal)
361 {
362  DirRangePtr idrDirRangePtr;
363 
364  ndbrequire(cdirrangesize > 0);
365  for (idrDirRangePtr.i = 0; idrDirRangePtr.i < cdirrangesize; idrDirRangePtr.i++) {
367  ptrAss(idrDirRangePtr, dirRange);
368  idrDirRangePtr.p->dirArray[0] = idrDirRangePtr.i + 1;
369  for (Uint32 i = 1; i < 256; i++) {
370  idrDirRangePtr.p->dirArray[i] = RNIL;
371  }//for
372  }//for
373  idrDirRangePtr.i = cdirrangesize - 1;
374  ptrAss(idrDirRangePtr, dirRange);
375  idrDirRangePtr.p->dirArray[0] = RNIL;
376  cfirstfreeDirrange = 0;
377 }//Dbacc::initialiseDirRangeRec()
378 
379 /* --------------------------------------------------------------------------------- */
380 /* INITIALISE_FRAG_REC */
381 /* INITIALATES THE FRAGMENT RECORDS. */
382 /* --------------------------------------------------------------------------------- */
383 void Dbacc::initialiseFragRec(Signal* signal)
384 {
385  FragmentrecPtr regFragPtr;
386  ndbrequire(cfragmentsize > 0);
387  for (regFragPtr.i = 0; regFragPtr.i < cfragmentsize; regFragPtr.i++) {
388  jam();
390  ptrAss(regFragPtr, fragmentrec);
391  initFragGeneral(regFragPtr);
392  regFragPtr.p->nextfreefrag = regFragPtr.i + 1;
393  }//for
394  regFragPtr.i = cfragmentsize - 1;
395  ptrAss(regFragPtr, fragmentrec);
396  regFragPtr.p->nextfreefrag = RNIL;
397  cfirstfreefrag = 0;
398 }//Dbacc::initialiseFragRec()
399 
400 /* --------------------------------------------------------------------------------- */
401 /* INITIALISE_OPERATION_REC */
402 /* INITIALATES THE OPERATION RECORDS. */
403 /* --------------------------------------------------------------------------------- */
404 void Dbacc::initialiseOperationRec(Signal* signal)
405 {
406  ndbrequire(coprecsize > 0);
407  for (operationRecPtr.i = 0; operationRecPtr.i < coprecsize; operationRecPtr.i++) {
409  ptrAss(operationRecPtr, operationrec);
410  operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
411  operationRecPtr.p->nextOp = operationRecPtr.i + 1;
412  }//for
413  operationRecPtr.i = coprecsize - 1;
414  ptrAss(operationRecPtr, operationrec);
415  operationRecPtr.p->nextOp = RNIL;
416  cfreeopRec = 0;
417 }//Dbacc::initialiseOperationRec()
418 
419 /* --------------------------------------------------------------------------------- */
420 /* INITIALISE_OVERFLOW_REC */
421 /* INITIALATES THE OVERFLOW RECORDS */
422 /* --------------------------------------------------------------------------------- */
423 void Dbacc::initialiseOverflowRec(Signal* signal)
424 {
425  OverflowRecordPtr iorOverflowRecPtr;
426 
427  ndbrequire(coverflowrecsize > 0);
428  for (iorOverflowRecPtr.i = 0; iorOverflowRecPtr.i < coverflowrecsize; iorOverflowRecPtr.i++) {
430  ptrAss(iorOverflowRecPtr, overflowRecord);
431  iorOverflowRecPtr.p->nextfreeoverrec = iorOverflowRecPtr.i + 1;
432  }//for
433  iorOverflowRecPtr.i = coverflowrecsize - 1;
434  ptrAss(iorOverflowRecPtr, overflowRecord);
435  iorOverflowRecPtr.p->nextfreeoverrec = RNIL;
436  cfirstfreeoverrec = 0;
437 }//Dbacc::initialiseOverflowRec()
438 
439 /* --------------------------------------------------------------------------------- */
440 /* INITIALISE_PAGE_REC */
441 /* INITIALATES THE PAGE RECORDS. */
442 /* --------------------------------------------------------------------------------- */
443 void Dbacc::initialisePageRec(Signal* signal)
444 {
445  ndbrequire(cpagesize > 0);
446  cnoOfAllocatedPages = 0;
447  cnoOfAllocatedPagesMax = 0;
448 }//Dbacc::initialisePageRec()
449 
450 
451 /* --------------------------------------------------------------------------------- */
452 /* INITIALISE_ROOTFRAG_REC */
453 /* INITIALATES THE ROOTFRAG RECORDS. */
454 /* --------------------------------------------------------------------------------- */
455 /* --------------------------------------------------------------------------------- */
456 /* INITIALISE_SCAN_REC */
457 /* INITIALATES THE QUE_SCAN RECORDS. */
458 /* --------------------------------------------------------------------------------- */
459 void Dbacc::initialiseScanRec(Signal* signal)
460 {
461  ndbrequire(cscanRecSize > 0);
462  for (scanPtr.i = 0; scanPtr.i < cscanRecSize; scanPtr.i++) {
463  ptrAss(scanPtr, scanRec);
464  scanPtr.p->scanNextfreerec = scanPtr.i + 1;
465  scanPtr.p->scanState = ScanRec::SCAN_DISCONNECT;
466  }//for
467  scanPtr.i = cscanRecSize - 1;
468  ptrAss(scanPtr, scanRec);
469  scanPtr.p->scanNextfreerec = RNIL;
470  cfirstFreeScanRec = 0;
471 }//Dbacc::initialiseScanRec()
472 
473 
474 /* --------------------------------------------------------------------------------- */
475 /* INITIALISE_TABLE_REC */
476 /* INITIALATES THE TABLE RECORDS. */
477 /* --------------------------------------------------------------------------------- */
478 void Dbacc::initialiseTableRec(Signal* signal)
479 {
480  ndbrequire(ctablesize > 0);
481  for (tabptr.i = 0; tabptr.i < ctablesize; tabptr.i++) {
483  ptrAss(tabptr, tabrec);
484  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
485  tabptr.p->fragholder[i] = RNIL;
486  tabptr.p->fragptrholder[i] = RNIL;
487  }//for
488  }//for
489 }//Dbacc::initialiseTableRec()
490 
491 /* --------------------------------------------------------------------------------- */
492 /* --------------------------------------------------------------------------------- */
493 /* --------------------------------------------------------------------------------- */
494 /* */
495 /* END OF SYSTEM RESTART MODULE */
496 /* */
497 /* --------------------------------------------------------------------------------- */
498 /* --------------------------------------------------------------------------------- */
499 /* --------------------------------------------------------------------------------- */
500 /* --------------------------------------------------------------------------------- */
501 /* --------------------------------------------------------------------------------- */
502 /* */
503 /* ADD/DELETE FRAGMENT MODULE */
504 /* */
505 /* --------------------------------------------------------------------------------- */
506 /* --------------------------------------------------------------------------------- */
507 
508 // JONAS This methods "aer ett saall"
509 void Dbacc::execACCFRAGREQ(Signal* signal)
510 {
511  const AccFragReq * const req = (AccFragReq*)&signal->theData[0];
512  jamEntry();
513  if (ERROR_INSERTED(3001)) {
514  jam();
515  addFragRefuse(signal, 1);
516  CLEAR_ERROR_INSERT_VALUE;
517  return;
518  }
519  tabptr.i = req->tableId;
520 #ifndef VM_TRACE
521  // config mismatch - do not crash if release compiled
522  if (tabptr.i >= ctablesize) {
523  jam();
524  addFragRefuse(signal, 640);
525  return;
526  }
527 #endif
528  ptrCheckGuard(tabptr, ctablesize, tabrec);
529  ndbrequire((req->reqInfo & 0xF) == ZADDFRAG);
530  ndbrequire(!getfragmentrec(signal, fragrecptr, req->fragId));
531  if (cfirstfreefrag == RNIL) {
532  jam();
533  addFragRefuse(signal, ZFULL_FRAGRECORD_ERROR);
534  return;
535  }//if
536 
537  seizeFragrec(signal);
538  initFragGeneral(fragrecptr);
539  initFragAdd(signal, fragrecptr);
540 
541  if (!addfragtotab(signal, fragrecptr.i, req->fragId)) {
542  jam();
543  releaseFragRecord(signal, fragrecptr);
544  addFragRefuse(signal, ZFULL_FRAGRECORD_ERROR);
545  return;
546  }//if
547  if (cfirstfreeDirrange == RNIL) {
548  jam();
549  releaseFragRecord(signal, fragrecptr);
550  addFragRefuse(signal, ZDIR_RANGE_ERROR);
551  return;
552  } else {
553  jam();
554  seizeDirrange(signal);
555  }//if
556 
557  fragrecptr.p->directory = newDirRangePtr.i;
558  seizeDirectory(signal);
559  if (tresult < ZLIMIT_OF_ERROR) {
560  jam();
561  newDirRangePtr.p->dirArray[0] = sdDirptr.i;
562  } else {
563  jam();
564  addFragRefuse(signal, tresult);
565  return;
566  }//if
567 
568  seizePage(signal);
569  if (tresult > ZLIMIT_OF_ERROR) {
570  jam();
571  addFragRefuse(signal, tresult);
572  return;
573  }//if
574  sdDirptr.p->pagep[0] = spPageptr.i;
575  tipPageId = 0;
576  inpPageptr = spPageptr;
577  initPage(signal);
578  if (cfirstfreeDirrange == RNIL) {
579  jam();
580  addFragRefuse(signal, ZDIR_RANGE_ERROR);
581  return;
582  } else {
583  jam();
584  seizeDirrange(signal);
585  }//if
586  fragrecptr.p->overflowdir = newDirRangePtr.i;
587  seizeDirectory(signal);
588  if (tresult < ZLIMIT_OF_ERROR) {
589  jam();
590  newDirRangePtr.p->dirArray[0] = sdDirptr.i;
591  } else {
592  jam();
593  addFragRefuse(signal, tresult);
594  return;
595  }//if
596 
597  Uint32 userPtr = req->userPtr;
598  BlockReference retRef = req->userRef;
599  fragrecptr.p->rootState = ACTIVEROOT;
600 
601  AccFragConf * const conf = (AccFragConf*)&signal->theData[0];
602  conf->userPtr = userPtr;
603  conf->rootFragPtr = RNIL;
604  conf->fragId[0] = fragrecptr.p->fragmentid;
605  conf->fragId[1] = RNIL;
606  conf->fragPtr[0] = fragrecptr.i;
607  conf->fragPtr[1] = RNIL;
608  conf->rootHashCheck = fragrecptr.p->roothashcheck;
609  sendSignal(retRef, GSN_ACCFRAGCONF, signal, AccFragConf::SignalLength, JBB);
610 }//Dbacc::execACCFRAGREQ()
611 
612 void Dbacc::addFragRefuse(Signal* signal, Uint32 errorCode)
613 {
614  const AccFragReq * const req = (AccFragReq*)&signal->theData[0];
615  AccFragRef * const ref = (AccFragRef*)&signal->theData[0];
616  Uint32 userPtr = req->userPtr;
617  BlockReference retRef = req->userRef;
618 
619  ref->userPtr = userPtr;
620  ref->errorCode = errorCode;
621  sendSignal(retRef, GSN_ACCFRAGREF, signal, AccFragRef::SignalLength, JBB);
622  return;
623 }//Dbacc::addFragRefuseEarly()
624 
625 void
626 Dbacc::execDROP_TAB_REQ(Signal* signal){
627  jamEntry();
628  DropTabReq* req = (DropTabReq*)signal->getDataPtr();
629 
630  TabrecPtr tabPtr;
631  tabPtr.i = req->tableId;
632  ptrCheckGuard(tabPtr, ctablesize, tabrec);
633 
634  tabPtr.p->tabUserRef = req->senderRef;
635  tabPtr.p->tabUserPtr = req->senderData;
636  tabPtr.p->tabUserGsn = GSN_DROP_TAB_REQ;
637 
638  signal->theData[0] = ZREL_ROOT_FRAG;
639  signal->theData[1] = tabPtr.i;
640  sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB);
641 }
642 
643 void
644 Dbacc::execDROP_FRAG_REQ(Signal* signal){
645  jamEntry();
646  DropFragReq* req = (DropFragReq*)signal->getDataPtr();
647 
648  TabrecPtr tabPtr;
649  tabPtr.i = req->tableId;
650  ptrCheckGuard(tabPtr, ctablesize, tabrec);
651 
652  tabPtr.p->tabUserRef = req->senderRef;
653  tabPtr.p->tabUserPtr = req->senderData;
654  tabPtr.p->tabUserGsn = GSN_DROP_FRAG_REQ;
655 
656  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++)
657  {
658  jam();
659  if (tabPtr.p->fragholder[i] == req->fragId)
660  {
661  jam();
662  tabPtr.p->fragholder[i] = RNIL;
663  releaseFragResources(signal, tabPtr.p->fragptrholder[i]);
664  return;
665  }//if
666  }//for
667 
668  releaseRootFragResources(signal, req->tableId);
669 }
670 
671 void Dbacc::releaseRootFragResources(Signal* signal, Uint32 tableId)
672 {
673  TabrecPtr tabPtr;
674  tabPtr.i = tableId;
675  ptrCheckGuard(tabPtr, ctablesize, tabrec);
676 
677  if (tabPtr.p->tabUserGsn == GSN_DROP_TAB_REQ)
678  {
679  jam();
680  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++)
681  {
682  jam();
683  if (tabPtr.p->fragholder[i] != RNIL)
684  {
685  jam();
686  tabPtr.p->fragholder[i] = RNIL;
687  releaseFragResources(signal, tabPtr.p->fragptrholder[i]);
688  return;
689  }
690  }
691 
695  DropTabConf * const dropConf = (DropTabConf *)signal->getDataPtrSend();
696  dropConf->senderRef = reference();
697  dropConf->senderData = tabPtr.p->tabUserPtr;
698  dropConf->tableId = tabPtr.i;
699  sendSignal(tabPtr.p->tabUserRef, GSN_DROP_TAB_CONF,
700  signal, DropTabConf::SignalLength, JBB);
701  }
702  else
703  {
704  ndbrequire(tabPtr.p->tabUserGsn == GSN_DROP_FRAG_REQ);
705 
706  DropFragConf * conf = (DropFragConf *)signal->getDataPtrSend();
707  conf->senderRef = reference();
708  conf->senderData = tabPtr.p->tabUserPtr;
709  conf->tableId = tabPtr.i;
710  sendSignal(tabPtr.p->tabUserRef, GSN_DROP_FRAG_CONF,
711  signal, DropFragConf::SignalLength, JBB);
712  }
713 
714  tabPtr.p->tabUserPtr = RNIL;
715  tabPtr.p->tabUserRef = 0;
716  tabPtr.p->tabUserGsn = 0;
717 }//Dbacc::releaseRootFragResources()
718 
719 void Dbacc::releaseFragResources(Signal* signal, Uint32 fragIndex)
720 {
721  FragmentrecPtr regFragPtr;
722  regFragPtr.i = fragIndex;
723  ptrCheckGuard(regFragPtr, cfragmentsize, fragmentrec);
724  verifyFragCorrect(regFragPtr);
725  if (regFragPtr.p->directory != RNIL) {
726  jam();
727  releaseDirResources(signal, regFragPtr.i, regFragPtr.p->directory, 0);
728  regFragPtr.p->directory = RNIL;
729  } else if (regFragPtr.p->overflowdir != RNIL) {
730  jam();
731  releaseDirResources(signal, regFragPtr.i, regFragPtr.p->overflowdir, 0);
732  regFragPtr.p->overflowdir = RNIL;
733  } else if (regFragPtr.p->firstOverflowRec != RNIL) {
734  jam();
735  releaseOverflowResources(signal, regFragPtr);
736  } else if (regFragPtr.p->firstFreeDirindexRec != RNIL) {
737  jam();
738  releaseDirIndexResources(signal, regFragPtr);
739  } else {
740  jam();
741  Uint32 tab = regFragPtr.p->mytabptr;
742  releaseFragRecord(signal, regFragPtr);
743  signal->theData[0] = ZREL_ROOT_FRAG;
744  signal->theData[1] = tab;
745  sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB);
746  }//if
747 }//Dbacc::releaseFragResources()
748 
749 void Dbacc::verifyFragCorrect(FragmentrecPtr regFragPtr)
750 {
751  ndbrequire(regFragPtr.p->lockOwnersList == RNIL);
752 }//Dbacc::verifyFragCorrect()
753 
754 void Dbacc::releaseDirResources(Signal* signal,
755  Uint32 fragIndex,
756  Uint32 dirIndex,
757  Uint32 startIndex)
758 {
759  DirRangePtr regDirRangePtr;
760  regDirRangePtr.i = dirIndex;
761  ptrCheckGuard(regDirRangePtr, cdirrangesize, dirRange);
762  for (Uint32 i = startIndex; i < 256; i++) {
763  jam();
764  if (regDirRangePtr.p->dirArray[i] != RNIL) {
765  jam();
766  Uint32 directoryIndex = regDirRangePtr.p->dirArray[i];
767  regDirRangePtr.p->dirArray[i] = RNIL;
768  releaseDirectoryResources(signal, fragIndex, dirIndex, (i + 1), directoryIndex);
769  return;
770  }//if
771  }//for
772  rdDirRangePtr = regDirRangePtr;
773  releaseDirrange(signal);
774  signal->theData[0] = ZREL_FRAG;
775  signal->theData[1] = fragIndex;
776  sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB);
777 }//Dbacc::releaseDirResources()
778 
779 void Dbacc::releaseDirectoryResources(Signal* signal,
780  Uint32 fragIndex,
781  Uint32 dirIndex,
782  Uint32 startIndex,
783  Uint32 directoryIndex)
784 {
785  DirectoryarrayPtr regDirPtr;
786  regDirPtr.i = directoryIndex;
787  ptrCheckGuard(regDirPtr, cdirarraysize, directoryarray);
788  for (Uint32 i = 0; i < 256; i++) {
789  jam();
790  if (regDirPtr.p->pagep[i] != RNIL) {
791  jam();
792  rpPageptr.i = regDirPtr.p->pagep[i];
793  ptrCheckGuard(rpPageptr, cpagesize, page8);
794  releasePage(signal);
795  regDirPtr.p->pagep[i] = RNIL;
796  }//if
797  }//for
798  rdDirptr = regDirPtr;
799  releaseDirectory(signal);
800  signal->theData[0] = ZREL_DIR;
801  signal->theData[1] = fragIndex;
802  signal->theData[2] = dirIndex;
803  signal->theData[3] = startIndex;
804  sendSignal(cownBlockref, GSN_CONTINUEB, signal, 4, JBB);
805 }//Dbacc::releaseDirectoryResources()
806 
807 void Dbacc::releaseOverflowResources(Signal* signal, FragmentrecPtr regFragPtr)
808 {
809  Uint32 loopCount = 0;
810  OverflowRecordPtr regOverflowRecPtr;
811  while ((regFragPtr.p->firstOverflowRec != RNIL) &&
812  (loopCount < 1)) {
813  jam();
814  regOverflowRecPtr.i = regFragPtr.p->firstOverflowRec;
815  ptrCheckGuard(regOverflowRecPtr, coverflowrecsize, overflowRecord);
816  regFragPtr.p->firstOverflowRec = regOverflowRecPtr.p->nextOverRec;
817  rorOverflowRecPtr = regOverflowRecPtr;
818  releaseOverflowRec(signal);
819  loopCount++;
820  }//while
821  signal->theData[0] = ZREL_FRAG;
822  signal->theData[1] = regFragPtr.i;
823  sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB);
824 }//Dbacc::releaseOverflowResources()
825 
826 void Dbacc::releaseDirIndexResources(Signal* signal, FragmentrecPtr regFragPtr)
827 {
828  Uint32 loopCount = 0;
829  OverflowRecordPtr regOverflowRecPtr;
830  while ((regFragPtr.p->firstFreeDirindexRec != RNIL) &&
831  (loopCount < 1)) {
832  jam();
833  regOverflowRecPtr.i = regFragPtr.p->firstFreeDirindexRec;
834  ptrCheckGuard(regOverflowRecPtr, coverflowrecsize, overflowRecord);
835  regFragPtr.p->firstFreeDirindexRec = regOverflowRecPtr.p->nextOverList;
836  rorOverflowRecPtr = regOverflowRecPtr;
837  releaseOverflowRec(signal);
838  loopCount++;
839  }//while
840  signal->theData[0] = ZREL_FRAG;
841  signal->theData[1] = regFragPtr.i;
842  sendSignal(cownBlockref, GSN_CONTINUEB, signal, 2, JBB);
843 }//Dbacc::releaseDirIndexResources()
844 
845 void Dbacc::releaseFragRecord(Signal* signal, FragmentrecPtr regFragPtr)
846 {
847  regFragPtr.p->nextfreefrag = cfirstfreefrag;
848  cfirstfreefrag = regFragPtr.i;
849  initFragGeneral(regFragPtr);
850  RSS_OP_FREE(cnoOfFreeFragrec);
851 }//Dbacc::releaseFragRecord()
852 
853 /* -------------------------------------------------------------------------- */
854 /* ADDFRAGTOTAB */
855 /* DESCRIPTION: PUTS A FRAGMENT ID AND A POINTER TO ITS RECORD INTO */
856 /* TABLE ARRRAY OF THE TABLE RECORD. */
857 /* -------------------------------------------------------------------------- */
858 bool Dbacc::addfragtotab(Signal* signal, Uint32 rootIndex, Uint32 fid)
859 {
860  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
861  jam();
862  if (tabptr.p->fragholder[i] == RNIL) {
863  jam();
864  tabptr.p->fragholder[i] = fid;
865  tabptr.p->fragptrholder[i] = rootIndex;
866  return true;
867  }//if
868  }//for
869  return false;
870 }//Dbacc::addfragtotab()
871 
872 /* --------------------------------------------------------------------------------- */
873 /* --------------------------------------------------------------------------------- */
874 /* --------------------------------------------------------------------------------- */
875 /* */
876 /* END OF ADD/DELETE FRAGMENT MODULE */
877 /* */
878 /* --------------------------------------------------------------------------------- */
879 /* --------------------------------------------------------------------------------- */
880 /* --------------------------------------------------------------------------------- */
881 /* --------------------------------------------------------------------------------- */
882 /* --------------------------------------------------------------------------------- */
883 /* */
884 /* CONNECTION MODULE */
885 /* */
886 /* --------------------------------------------------------------------------------- */
887 /* --------------------------------------------------------------------------------- */
888 /* ******************--------------------------------------------------------------- */
889 /* ACCSEIZEREQ SEIZE REQ */
890 /* SENDER: LQH, LEVEL B */
891 /* ENTER ACCSEIZEREQ WITH */
892 /* TUSERPTR , CONECTION PTR OF LQH */
893 /* TUSERBLOCKREF BLOCK REFERENCE OF LQH */
894 /* ******************--------------------------------------------------------------- */
895 /* ******************--------------------------------------------------------------- */
896 /* ACCSEIZEREQ SEIZE REQ */
897 /* ******************------------------------------+ */
898 /* SENDER: LQH, LEVEL B */
899 void Dbacc::execACCSEIZEREQ(Signal* signal)
900 {
901  jamEntry();
902  tuserptr = signal->theData[0];
903  /* CONECTION PTR OF LQH */
904  tuserblockref = signal->theData[1];
905  /* BLOCK REFERENCE OF LQH */
906  tresult = 0;
907  if (cfreeopRec == RNIL) {
908  jam();
909  refaccConnectLab(signal);
910  return;
911  }//if
912  seizeOpRec(signal);
913  ptrGuard(operationRecPtr);
914  operationRecPtr.p->userptr = tuserptr;
915  operationRecPtr.p->userblockref = tuserblockref;
916  operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
917  /* ******************************< */
918  /* ACCSEIZECONF */
919  /* ******************************< */
920  signal->theData[0] = tuserptr;
921  signal->theData[1] = operationRecPtr.i;
922  sendSignal(tuserblockref, GSN_ACCSEIZECONF, signal, 2, JBB);
923  return;
924 }//Dbacc::execACCSEIZEREQ()
925 
926 void Dbacc::refaccConnectLab(Signal* signal)
927 {
928  tresult = ZCONNECT_SIZE_ERROR;
929  /* ******************************< */
930  /* ACCSEIZEREF */
931  /* ******************************< */
932  signal->theData[0] = tuserptr;
933  signal->theData[1] = tresult;
934  sendSignal(tuserblockref, GSN_ACCSEIZEREF, signal, 2, JBB);
935  return;
936 }//Dbacc::refaccConnectLab()
937 
938 /* --------------------------------------------------------------------------------- */
939 /* --------------------------------------------------------------------------------- */
940 /* --------------------------------------------------------------------------------- */
941 /* */
942 /* END OF CONNECTION MODULE */
943 /* */
944 /* --------------------------------------------------------------------------------- */
945 /* --------------------------------------------------------------------------------- */
946 /* --------------------------------------------------------------------------------- */
947 /* --------------------------------------------------------------------------------- */
948 /* --------------------------------------------------------------------------------- */
949 /* */
950 /* EXECUTE OPERATION MODULE */
951 /* */
952 /* --------------------------------------------------------------------------------- */
953 /* --------------------------------------------------------------------------------- */
954 /* --------------------------------------------------------------------------------- */
955 /* INIT_OP_REC */
956 /* INFORMATION WHICH IS RECIEVED BY ACCKEYREQ WILL BE SAVED */
957 /* IN THE OPERATION RECORD. */
958 /* --------------------------------------------------------------------------------- */
959 void Dbacc::initOpRec(Signal* signal)
960 {
961  register Uint32 Treqinfo;
962 
963  Treqinfo = signal->theData[2];
964 
965  operationRecPtr.p->hashValue = signal->theData[3];
966  operationRecPtr.p->tupkeylen = signal->theData[4];
967  operationRecPtr.p->xfrmtupkeylen = signal->theData[4];
968  operationRecPtr.p->transId1 = signal->theData[5];
969  operationRecPtr.p->transId2 = signal->theData[6];
970 
971  Uint32 readFlag = (((Treqinfo >> 4) & 0x3) == 0); // Only 1 if Read
972  Uint32 dirtyFlag = (((Treqinfo >> 6) & 0x1) == 1); // Only 1 if Dirty
973  Uint32 dirtyReadFlag = readFlag & dirtyFlag;
974  Uint32 operation = Treqinfo & 0xf;
975  if (operation == ZREFRESH)
976  operation = ZWRITE; /* Insert if !exist, otherwise lock */
977 
978  Uint32 opbits = 0;
979  opbits |= operation;
980  opbits |= ((Treqinfo >> 4) & 0x3) ? (Uint32) Operationrec::OP_LOCK_MODE : 0;
981  opbits |= ((Treqinfo >> 4) & 0x3) ? (Uint32) Operationrec::OP_ACC_LOCK_MODE : 0;
982  opbits |= (dirtyReadFlag) ? (Uint32) Operationrec::OP_DIRTY_READ : 0;
983  if ((Treqinfo >> 31) & 0x1)
984  {
985  opbits |= Operationrec::OP_LOCK_REQ; // TUX LOCK_REQ
986 
992  opbits |= Operationrec::OP_COMMIT_DELETE_CHECK;
993 
998  }
999 
1000  //operationRecPtr.p->nodeType = (Treqinfo >> 7) & 0x3;
1001  operationRecPtr.p->fid = fragrecptr.p->myfid;
1002  operationRecPtr.p->fragptr = fragrecptr.i;
1003  operationRecPtr.p->nextParallelQue = RNIL;
1004  operationRecPtr.p->prevParallelQue = RNIL;
1005  operationRecPtr.p->nextSerialQue = RNIL;
1006  operationRecPtr.p->prevSerialQue = RNIL;
1007  operationRecPtr.p->elementPage = RNIL;
1008  operationRecPtr.p->scanRecPtr = RNIL;
1009  operationRecPtr.p->m_op_bits = opbits;
1010 
1011  // bit to mark lock operation
1012  // undo log is not run via ACCKEYREQ
1013 
1014  if (operationRecPtr.p->tupkeylen == 0)
1015  {
1016  ndbassert(signal->getLength() == 9);
1017  }
1018 }//Dbacc::initOpRec()
1019 
1020 /* --------------------------------------------------------------------------------- */
1021 /* SEND_ACCKEYCONF */
1022 /* --------------------------------------------------------------------------------- */
1023 void Dbacc::sendAcckeyconf(Signal* signal)
1024 {
1025  signal->theData[0] = operationRecPtr.p->userptr;
1026  signal->theData[1] = operationRecPtr.p->m_op_bits & Operationrec::OP_MASK;
1027  signal->theData[2] = operationRecPtr.p->fid;
1028  signal->theData[3] = operationRecPtr.p->localdata[0];
1029  signal->theData[4] = operationRecPtr.p->localdata[1];
1030 }//Dbacc::sendAcckeyconf()
1031 
1032 void
1033 Dbacc::ACCKEY_error(Uint32 fromWhere)
1034 {
1035  switch(fromWhere) {
1036  case 0:
1037  ndbrequire(false);
1038  case 1:
1039  ndbrequire(false);
1040  case 2:
1041  ndbrequire(false);
1042  case 3:
1043  ndbrequire(false);
1044  case 4:
1045  ndbrequire(false);
1046  case 5:
1047  ndbrequire(false);
1048  case 6:
1049  ndbrequire(false);
1050  case 7:
1051  ndbrequire(false);
1052  case 8:
1053  ndbrequire(false);
1054  case 9:
1055  ndbrequire(false);
1056  default:
1057  ndbrequire(false);
1058  }//switch
1059 }//Dbacc::ACCKEY_error()
1060 
1061 /* ******************--------------------------------------------------------------- */
1062 /* ACCKEYREQ REQUEST FOR INSERT, DELETE, */
1063 /* RERAD AND UPDATE, A TUPLE. */
1064 /* SENDER: LQH, LEVEL B */
1065 /* SIGNAL DATA: OPERATION_REC_PTR, CONNECTION PTR */
1066 /* TABPTR, TABLE ID = TABLE RECORD POINTER */
1067 /* TREQINFO, */
1068 /* THASHVALUE, HASH VALUE OF THE TUP */
1069 /* TKEYLEN, LENGTH OF THE PRIMARY KEYS */
1070 /* TKEY1, PRIMARY KEY 1 */
1071 /* TKEY2, PRIMARY KEY 2 */
1072 /* TKEY3, PRIMARY KEY 3 */
1073 /* TKEY4, PRIMARY KEY 4 */
1074 /* ******************--------------------------------------------------------------- */
1075 void Dbacc::execACCKEYREQ(Signal* signal)
1076 {
1077  jamEntry();
1078  operationRecPtr.i = signal->theData[0]; /* CONNECTION PTR */
1079  fragrecptr.i = signal->theData[1]; /* FRAGMENT RECORD POINTER */
1080  if (!((operationRecPtr.i < coprecsize) ||
1081  (fragrecptr.i < cfragmentsize))) {
1082  ACCKEY_error(0);
1083  return;
1084  }//if
1085  ptrAss(operationRecPtr, operationrec);
1086  ptrAss(fragrecptr, fragmentrec);
1087 
1088  ndbrequire(operationRecPtr.p->m_op_bits == Operationrec::OP_INITIAL);
1089 
1090  initOpRec(signal);
1091  // normalize key if any char attr
1092  if (operationRecPtr.p->tupkeylen && fragrecptr.p->hasCharAttr)
1093  xfrmKeyData(signal);
1094 
1095  /*---------------------------------------------------------------*/
1096  /* */
1097  /* WE WILL USE THE HASH VALUE TO LOOK UP THE PROPER MEMORY */
1098  /* PAGE AND MEMORY PAGE INDEX TO START THE SEARCH WITHIN. */
1099  /* WE REMEMBER THESE ADDRESS IF WE LATER NEED TO INSERT */
1100  /* THE ITEM AFTER NOT FINDING THE ITEM. */
1101  /*---------------------------------------------------------------*/
1102  OperationrecPtr lockOwnerPtr;
1103  const Uint32 found = getElement(signal, lockOwnerPtr);
1104 
1105  Uint32 opbits = operationRecPtr.p->m_op_bits;
1106  Uint32 op = opbits & Operationrec::OP_MASK;
1107  if (found == ZTRUE)
1108  {
1109  switch (op) {
1110  case ZREAD:
1111  case ZUPDATE:
1112  case ZDELETE:
1113  case ZWRITE:
1114  case ZSCAN_OP:
1115  if (!lockOwnerPtr.p)
1116  {
1117  if(op == ZWRITE)
1118  {
1119  jam();
1120  opbits &= ~(Uint32)Operationrec::OP_MASK;
1121  opbits |= (op = ZUPDATE);
1122  operationRecPtr.p->m_op_bits = opbits; // store to get correct ACCKEYCONF
1123  }
1124  opbits |= Operationrec::OP_STATE_RUNNING;
1125  opbits |= Operationrec::OP_RUN_QUEUE;
1126  sendAcckeyconf(signal);
1127  if (! (opbits & Operationrec::OP_DIRTY_READ)) {
1128  /*---------------------------------------------------------------*/
1129  // It is not a dirty read. We proceed by locking and continue with
1130  // the operation.
1131  /*---------------------------------------------------------------*/
1132  Uint32 eh = gePageptr.p->word32[tgeElementptr];
1133  operationRecPtr.p->scanBits = ElementHeader::getScanBits(eh);
1134  operationRecPtr.p->hashvaluePart = ElementHeader::getHashValuePart(eh);
1135  operationRecPtr.p->elementPage = gePageptr.i;
1136  operationRecPtr.p->elementContainer = tgeContainerptr;
1137  operationRecPtr.p->elementPointer = tgeElementptr;
1138  operationRecPtr.p->elementIsforward = tgeForward;
1139 
1140  eh = ElementHeader::setLocked(operationRecPtr.i);
1141  dbgWord32(gePageptr, tgeElementptr, eh);
1142  gePageptr.p->word32[tgeElementptr] = eh;
1143 
1144  opbits |= Operationrec::OP_LOCK_OWNER;
1145  insertLockOwnersList(signal, operationRecPtr);
1146  } else {
1147  jam();
1148  /*---------------------------------------------------------------*/
1149  // It is a dirty read. We do not lock anything. Set state to
1150  // IDLE since no COMMIT call will come.
1151  /*---------------------------------------------------------------*/
1152  opbits = Operationrec::OP_EXECUTED_DIRTY_READ;
1153  }//if
1154  operationRecPtr.p->m_op_bits = opbits;
1155  return;
1156  } else {
1157  jam();
1158  accIsLockedLab(signal, lockOwnerPtr);
1159  return;
1160  }//if
1161  break;
1162  case ZINSERT:
1163  jam();
1164  insertExistElemLab(signal, lockOwnerPtr);
1165  return;
1166  break;
1167  default:
1168  ndbrequire(false);
1169  break;
1170  }//switch
1171  } else if (found == ZFALSE) {
1172  switch (op){
1173  case ZWRITE:
1174  opbits &= ~(Uint32)Operationrec::OP_MASK;
1175  opbits |= (op = ZINSERT);
1176  case ZINSERT:
1177  jam();
1178  opbits |= Operationrec::OP_INSERT_IS_DONE;
1179  opbits |= Operationrec::OP_STATE_RUNNING;
1180  opbits |= Operationrec::OP_RUN_QUEUE;
1181  operationRecPtr.p->m_op_bits = opbits;
1182  insertelementLab(signal);
1183  return;
1184  break;
1185  case ZREAD:
1186  case ZUPDATE:
1187  case ZDELETE:
1188  case ZSCAN_OP:
1189  jam();
1190  acckeyref1Lab(signal, ZREAD_ERROR);
1191  return;
1192  break;
1193  default:
1194  ndbrequire(false);
1195  break;
1196  }//switch
1197  } else {
1198  jam();
1199  acckeyref1Lab(signal, found);
1200  return;
1201  }//if
1202  return;
1203 }//Dbacc::execACCKEYREQ()
1204 
1205 void
1206 Dbacc::execACCKEY_ORD(Signal* signal, Uint32 opPtrI)
1207 {
1208  jamEntry();
1209  OperationrecPtr lastOp;
1210  lastOp.i = opPtrI;
1211  ptrCheckGuard(lastOp, coprecsize, operationrec);
1212  Uint32 opbits = lastOp.p->m_op_bits;
1213  Uint32 opstate = opbits & Operationrec::OP_STATE_MASK;
1214 
1215  if (likely(opbits == Operationrec::OP_EXECUTED_DIRTY_READ))
1216  {
1217  jam();
1218  lastOp.p->m_op_bits = Operationrec::OP_INITIAL;
1219  return;
1220  }
1221  else if (likely(opstate == Operationrec::OP_STATE_RUNNING))
1222  {
1223  opbits |= Operationrec::OP_STATE_EXECUTED;
1224  lastOp.p->m_op_bits = opbits;
1225  startNext(signal, lastOp);
1226  return;
1227  }
1228  else
1229  {
1230  }
1231 
1232  ndbout_c("bits: %.8x state: %.8x", opbits, opstate);
1233  ndbrequire(false);
1234 }
1235 
1236 void
1238 {
1239  jam();
1240  OperationrecPtr nextOp;
1241  OperationrecPtr loPtr;
1242  nextOp.i = lastOp.p->nextParallelQue;
1243  loPtr.i = lastOp.p->m_lock_owner_ptr_i;
1244  Uint32 opbits = lastOp.p->m_op_bits;
1245 
1246  if ((opbits & Operationrec::OP_STATE_MASK)!= Operationrec::OP_STATE_EXECUTED)
1247  {
1248  jam();
1249  return;
1250  }
1251 
1252  Uint32 nextbits;
1253  if (nextOp.i != RNIL)
1254  {
1255  jam();
1256  ptrCheckGuard(nextOp, coprecsize, operationrec);
1257  nextbits = nextOp.p->m_op_bits;
1258  goto checkop;
1259  }
1260 
1261  if ((opbits & Operationrec::OP_LOCK_OWNER) == 0)
1262  {
1263  jam();
1264  ptrCheckGuard(loPtr, coprecsize, operationrec);
1265  }
1266  else
1267  {
1268  jam();
1269  loPtr = lastOp;
1270  }
1271 
1272  nextOp.i = loPtr.p->nextSerialQue;
1273  ndbassert(loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
1274 
1275  if (nextOp.i == RNIL)
1276  {
1277  jam();
1278  return;
1279  }
1280 
1285  ptrCheckGuard(nextOp, coprecsize, operationrec);
1286  nextbits = nextOp.p->m_op_bits;
1287 
1288  {
1289  const bool same = nextOp.p->is_same_trans(lastOp.p);
1290 
1291  if (!same && ((opbits & Operationrec::OP_ACC_LOCK_MODE) ||
1292  (nextbits & Operationrec::OP_LOCK_MODE)))
1293  {
1294  jam();
1300  return;
1301  }
1302 
1306  if (same && (opbits & Operationrec::OP_ACC_LOCK_MODE))
1307  {
1308  jam();
1309  goto upgrade;
1310  }
1311  }
1312 
1316  if ((opbits & Operationrec::OP_ACC_LOCK_MODE) == 0 &&
1317  (nextbits & Operationrec::OP_LOCK_MODE) == 0)
1318  {
1319  jam();
1320  goto upgrade;
1321  }
1322 
1326  ndbassert((opbits & Operationrec::OP_ACC_LOCK_MODE) == 0 &&
1327  (nextbits & Operationrec::OP_LOCK_MODE));
1328 
1332  OperationrecPtr tmp;
1333  tmp= loPtr;
1334  while (tmp.i != RNIL)
1335  {
1336  ptrCheckGuard(tmp, coprecsize, operationrec);
1337  if (!nextOp.p->is_same_trans(tmp.p))
1338  {
1339  jam();
1343  return;
1344  }
1345  tmp.i = tmp.p->nextParallelQue;
1346  }
1347 
1348 upgrade:
1353  tmp.i = loPtr.p->nextSerialQue = nextOp.p->nextSerialQue;
1354  loPtr.p->m_lo_last_parallel_op_ptr_i = nextOp.i;
1355  nextOp.p->nextSerialQue = RNIL;
1356  nextOp.p->prevSerialQue = RNIL;
1357  nextOp.p->m_lock_owner_ptr_i = loPtr.i;
1358  nextOp.p->prevParallelQue = lastOp.i;
1359  lastOp.p->nextParallelQue = nextOp.i;
1360 
1361  if (tmp.i != RNIL)
1362  {
1363  jam();
1364  ptrCheckGuard(tmp, coprecsize, operationrec);
1365  tmp.p->prevSerialQue = loPtr.i;
1366  }
1367  else
1368  {
1369  jam();
1370  loPtr.p->m_lo_last_serial_op_ptr_i = RNIL;
1371  }
1372 
1373  nextbits |= Operationrec::OP_RUN_QUEUE;
1374 
1378  ndbrequire(nextOp.p->nextParallelQue == RNIL);
1379 
1380 checkop:
1381  Uint32 errCode = 0;
1382  OperationrecPtr save = operationRecPtr;
1383  operationRecPtr = nextOp;
1384 
1385  Uint32 lastop = opbits & Operationrec::OP_MASK;
1386  Uint32 nextop = nextbits & Operationrec::OP_MASK;
1387 
1388  nextbits &= nextbits & ~(Uint32)Operationrec::OP_STATE_MASK;
1389  nextbits |= Operationrec::OP_STATE_RUNNING;
1390 
1391  if (lastop == ZDELETE)
1392  {
1393  jam();
1394  if (nextop != ZINSERT && nextop != ZWRITE)
1395  {
1396  errCode = ZREAD_ERROR;
1397  goto ref;
1398  }
1399 
1400  nextbits &= ~(Uint32)Operationrec::OP_MASK;
1401  nextbits &= ~(Uint32)Operationrec::OP_ELEMENT_DISAPPEARED;
1402  nextbits |= (nextop = ZINSERT);
1403  goto conf;
1404  }
1405  else if (nextop == ZINSERT)
1406  {
1407  jam();
1408  errCode = ZWRITE_ERROR;
1409  goto ref;
1410  }
1411  else if (nextop == ZWRITE)
1412  {
1413  jam();
1414  nextbits &= ~(Uint32)Operationrec::OP_MASK;
1415  nextbits |= (nextop = ZUPDATE);
1416  goto conf;
1417  }
1418  else
1419  {
1420  jam();
1421  }
1422 
1423 conf:
1424  nextOp.p->m_op_bits = nextbits;
1425  nextOp.p->localdata[0] = lastOp.p->localdata[0];
1426  nextOp.p->localdata[1] = lastOp.p->localdata[1];
1427 
1428  if (nextop == ZSCAN_OP && (nextbits & Operationrec::OP_LOCK_REQ) == 0)
1429  {
1430  jam();
1431  takeOutScanLockQueue(nextOp.p->scanRecPtr);
1432  putReadyScanQueue(signal, nextOp.p->scanRecPtr);
1433  }
1434  else
1435  {
1436  jam();
1437  fragrecptr.i = nextOp.p->fragptr;
1438  ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
1439 
1440  sendAcckeyconf(signal);
1441  sendSignal(nextOp.p->userblockref, GSN_ACCKEYCONF,
1442  signal, 6, JBB);
1443  }
1444 
1445  operationRecPtr = save;
1446  return;
1447 
1448 ref:
1449  nextOp.p->m_op_bits = nextbits;
1450 
1451  if (nextop == ZSCAN_OP && (nextbits & Operationrec::OP_LOCK_REQ) == 0)
1452  {
1453  jam();
1454  nextOp.p->m_op_bits |= Operationrec::OP_ELEMENT_DISAPPEARED;
1455  takeOutScanLockQueue(nextOp.p->scanRecPtr);
1456  putReadyScanQueue(signal, nextOp.p->scanRecPtr);
1457  }
1458  else
1459  {
1460  jam();
1461  signal->theData[0] = nextOp.p->userptr;
1462  signal->theData[1] = errCode;
1463  sendSignal(nextOp.p->userblockref, GSN_ACCKEYREF, signal,
1464  2, JBB);
1465  }
1466 
1467  operationRecPtr = save;
1468  return;
1469 }
1470 
1471 
1472 #if 0
1473 void
1474 Dbacc::execACCKEY_REP_REF(Signal* signal, Uint32 opPtrI)
1475 {
1476 }
1477 #endif
1478 
1479 void
1480 Dbacc::xfrmKeyData(Signal* signal)
1481 {
1482  Uint32 table = fragrecptr.p->myTableId;
1483  Uint32 dst[MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY];
1484  Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
1485  Uint32* src = &signal->theData[7];
1486  Uint32 len = xfrm_key(table, src, dst, sizeof(dst) >> 2, keyPartLen);
1487  ndbrequire(len); // 0 means error
1488  memcpy(src, dst, len << 2);
1489  operationRecPtr.p->xfrmtupkeylen = len;
1490 }
1491 
1492 void
1493 Dbacc::accIsLockedLab(Signal* signal, OperationrecPtr lockOwnerPtr)
1494 {
1495  Uint32 bits = operationRecPtr.p->m_op_bits;
1496  validate_lock_queue(lockOwnerPtr);
1497 
1498  if ((bits & Operationrec::OP_DIRTY_READ) == 0){
1499  Uint32 return_result;
1500  if ((bits & Operationrec::OP_LOCK_MODE) == ZREADLOCK) {
1501  jam();
1502  return_result = placeReadInLockQueue(lockOwnerPtr);
1503  } else {
1504  jam();
1505  return_result = placeWriteInLockQueue(lockOwnerPtr);
1506  }//if
1507  if (return_result == ZPARALLEL_QUEUE) {
1508  jam();
1509  sendAcckeyconf(signal);
1510  return;
1511  } else if (return_result == ZSERIAL_QUEUE) {
1512  jam();
1513  signal->theData[0] = RNIL;
1514  return;
1515  } else {
1516  jam();
1517  acckeyref1Lab(signal, return_result);
1518  return;
1519  }//if
1520  ndbrequire(false);
1521  }
1522  else
1523  {
1524  if (! (lockOwnerPtr.p->m_op_bits & Operationrec::OP_ELEMENT_DISAPPEARED) &&
1525  ! Local_key::isInvalid(lockOwnerPtr.p->localdata[0],
1526  lockOwnerPtr.p->localdata[1]))
1527  {
1528  jam();
1529  /* ---------------------------------------------------------------
1530  * It is a dirty read. We do not lock anything. Set state to
1531  *IDLE since no COMMIT call will arrive.
1532  * ---------------------------------------------------------------*/
1533  sendAcckeyconf(signal);
1534  operationRecPtr.p->m_op_bits = Operationrec::OP_EXECUTED_DIRTY_READ;
1535  return;
1536  }
1537  else
1538  {
1539  jam();
1540  /*---------------------------------------------------------------*/
1541  // The tuple does not exist in the committed world currently.
1542  // Report read error.
1543  /*---------------------------------------------------------------*/
1544  acckeyref1Lab(signal, ZREAD_ERROR);
1545  return;
1546  }//if
1547  }//if
1548 }//Dbacc::accIsLockedLab()
1549 
1550 /* ------------------------------------------------------------------------ */
1551 /* I N S E R T E X I S T E L E M E N T */
1552 /* ------------------------------------------------------------------------ */
1553 void Dbacc::insertExistElemLab(Signal* signal, OperationrecPtr lockOwnerPtr)
1554 {
1555  if (!lockOwnerPtr.p)
1556  {
1557  jam();
1558  acckeyref1Lab(signal, ZWRITE_ERROR);/* THE ELEMENT ALREADY EXIST */
1559  return;
1560  }//if
1561  accIsLockedLab(signal, lockOwnerPtr);
1562 }//Dbacc::insertExistElemLab()
1563 
1564 /* --------------------------------------------------------------------------------- */
1565 /* INSERTELEMENT */
1566 /* --------------------------------------------------------------------------------- */
1567 void Dbacc::insertelementLab(Signal* signal)
1568 {
1569  if (unlikely(fragrecptr.p->dirRangeFull))
1570  {
1571  jam();
1572  acckeyref1Lab(signal, ZDIR_RANGE_FULL_ERROR);
1573  return;
1574  }
1575  if (fragrecptr.p->firstOverflowRec == RNIL) {
1576  jam();
1577  allocOverflowPage(signal);
1578  if (tresult > ZLIMIT_OF_ERROR) {
1579  jam();
1580  acckeyref1Lab(signal, tresult);
1581  return;
1582  }//if
1583  }//if
1584  ndbrequire(operationRecPtr.p->tupkeylen <= fragrecptr.p->keyLength);
1585  ndbassert(!(operationRecPtr.p->m_op_bits & Operationrec::OP_LOCK_REQ));
1586  Uint32 localKey = ~(Uint32)0;
1587 
1588  insertLockOwnersList(signal, operationRecPtr);
1589 
1590  const Uint32 tmp = fragrecptr.p->k + fragrecptr.p->lhfragbits;
1591  operationRecPtr.p->hashvaluePart =
1592  (operationRecPtr.p->hashValue >> tmp) & 0xFFFF;
1593  operationRecPtr.p->scanBits = 0; /* NOT ANY ACTIVE SCAN */
1594  tidrElemhead = ElementHeader::setLocked(operationRecPtr.i);
1595  idrPageptr = gdiPageptr;
1596  tidrPageindex = tgdiPageindex;
1597  tidrForward = ZTRUE;
1598  idrOperationRecPtr = operationRecPtr;
1599  clocalkey[0] = localKey;
1600  clocalkey[1] = localKey;
1601  operationRecPtr.p->localdata[0] = localKey;
1602  operationRecPtr.p->localdata[1] = localKey;
1603  /* ----------------------------------------------------------------------- */
1604  /* WE SET THE LOCAL KEY TO MINUS ONE TO INDICATE IT IS NOT YET VALID. */
1605  /* ----------------------------------------------------------------------- */
1606  insertElement(signal);
1607  sendAcckeyconf(signal);
1608  return;
1609 }//Dbacc::insertelementLab()
1610 
1611 
1612 /* ------------------------------------------------------------------------ */
1613 /* GET_NO_PARALLEL_TRANSACTION */
1614 /* ------------------------------------------------------------------------ */
1615 Uint32
1616 Dbacc::getNoParallelTransaction(const Operationrec * op)
1617 {
1618  OperationrecPtr tmp;
1619 
1620  tmp.i= op->nextParallelQue;
1621  Uint32 transId[2] = { op->transId1, op->transId2 };
1622  while (tmp.i != RNIL)
1623  {
1624  jam();
1625  ptrCheckGuard(tmp, coprecsize, operationrec);
1626  if (tmp.p->transId1 == transId[0] && tmp.p->transId2 == transId[1])
1627  tmp.i = tmp.p->nextParallelQue;
1628  else
1629  return 2;
1630  }
1631  return 1;
1632 }//Dbacc::getNoParallelTransaction()
1633 
1634 #ifdef VM_TRACE
1635 Uint32
1636 Dbacc::getNoParallelTransactionFull(const Operationrec * op)
1637 {
1639 
1640  tmp.p = op;
1641  while ((tmp.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0)
1642  {
1643  tmp.i = tmp.p->prevParallelQue;
1644  if (tmp.i != RNIL)
1645  {
1646  ptrCheckGuard(tmp, coprecsize, operationrec);
1647  }
1648  else
1649  {
1650  break;
1651  }
1652  }
1653 
1654  return getNoParallelTransaction(tmp.p);
1655 }
1656 #endif
1657 
1658 #ifdef ACC_SAFE_QUEUE
1659 
1660 Uint32
1661 Dbacc::get_parallel_head(OperationrecPtr opPtr)
1662 {
1663  while ((opPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0 &&
1664  opPtr.p->prevParallelQue != RNIL)
1665  {
1666  opPtr.i = opPtr.p->prevParallelQue;
1667  ptrCheckGuard(opPtr, coprecsize, operationrec);
1668  }
1669 
1670  return opPtr.i;
1671 }
1672 
1673 bool
1674 Dbacc::validate_lock_queue(OperationrecPtr opPtr)
1675 {
1676  OperationrecPtr loPtr;
1677  loPtr.i = get_parallel_head(opPtr);
1678  ptrCheckGuard(loPtr, coprecsize, operationrec);
1679 
1680  while((loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0 &&
1681  loPtr.p->prevSerialQue != RNIL)
1682  {
1683  loPtr.i = loPtr.p->prevSerialQue;
1684  ptrCheckGuard(loPtr, coprecsize, operationrec);
1685  }
1686 
1687  // Now we have lock owner...
1688  vlqrequire(loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
1689  vlqrequire(loPtr.p->m_op_bits & Operationrec::OP_RUN_QUEUE);
1690 
1691  // 1 Validate page pointer
1692  {
1693  Page8Ptr pagePtr;
1694  pagePtr.i = loPtr.p->elementPage;
1695  ptrCheckGuard(pagePtr, cpagesize, page8);
1696  arrGuard(loPtr.p->elementPointer, 2048);
1697  Uint32 eh = pagePtr.p->word32[loPtr.p->elementPointer];
1698  vlqrequire(ElementHeader::getLocked(eh));
1699  vlqrequire(ElementHeader::getOpPtrI(eh) == loPtr.i);
1700  }
1701 
1702  // 2 Lock owner should always have same LOCK_MODE and ACC_LOCK_MODE
1703  if (loPtr.p->m_op_bits & Operationrec::OP_LOCK_MODE)
1704  {
1705  vlqrequire(loPtr.p->m_op_bits & Operationrec::OP_ACC_LOCK_MODE);
1706  }
1707  else
1708  {
1709  vlqrequire((loPtr.p->m_op_bits & Operationrec::OP_ACC_LOCK_MODE) == 0);
1710  }
1711 
1712  // 3 Lock owner should never be waiting...
1713  bool running = false;
1714  {
1715  Uint32 opstate = loPtr.p->m_op_bits & Operationrec::OP_STATE_MASK;
1716  if (opstate == Operationrec::OP_STATE_RUNNING)
1717  running = true;
1718  else
1719  {
1720  vlqrequire(opstate == Operationrec::OP_STATE_EXECUTED);
1721  }
1722  }
1723 
1724  // Validate parallel queue
1725  {
1726  bool many = false;
1727  bool orlockmode = loPtr.p->m_op_bits & Operationrec::OP_LOCK_MODE;
1728  OperationrecPtr lastP = loPtr;
1729 
1730  while (lastP.p->nextParallelQue != RNIL)
1731  {
1732  Uint32 prev = lastP.i;
1733  lastP.i = lastP.p->nextParallelQue;
1734  ptrCheckGuard(lastP, coprecsize, operationrec);
1735 
1736  vlqrequire(lastP.p->prevParallelQue == prev);
1737 
1738  Uint32 opbits = lastP.p->m_op_bits;
1739  many |= loPtr.p->is_same_trans(lastP.p) ? 0 : 1;
1740  orlockmode |= !!(opbits & Operationrec::OP_LOCK_MODE);
1741 
1742  vlqrequire(opbits & Operationrec::OP_RUN_QUEUE);
1743  vlqrequire((opbits & Operationrec::OP_LOCK_OWNER) == 0);
1744 
1745  Uint32 opstate = opbits & Operationrec::OP_STATE_MASK;
1746  if (running)
1747  {
1748  // If I found a running operation,
1749  // all following should be waiting
1750  vlqrequire(opstate == Operationrec::OP_STATE_WAITING);
1751  }
1752  else
1753  {
1754  if (opstate == Operationrec::OP_STATE_RUNNING)
1755  running = true;
1756  else
1757  vlqrequire(opstate == Operationrec::OP_STATE_EXECUTED);
1758  }
1759 
1760  if (lastP.p->m_op_bits & Operationrec::OP_LOCK_MODE)
1761  {
1762  vlqrequire(lastP.p->m_op_bits & Operationrec::OP_ACC_LOCK_MODE);
1763  }
1764  else
1765  {
1766  vlqrequire((lastP.p->m_op_bits && orlockmode) == orlockmode);
1767  vlqrequire((lastP.p->m_op_bits & Operationrec::OP_MASK) == ZREAD ||
1768  (lastP.p->m_op_bits & Operationrec::OP_MASK) == ZSCAN_OP);
1769  }
1770 
1771  if (many)
1772  {
1773  vlqrequire(orlockmode == 0);
1774  }
1775  }
1776 
1777  if (lastP.i != loPtr.i)
1778  {
1779  vlqrequire(loPtr.p->m_lo_last_parallel_op_ptr_i == lastP.i);
1780  vlqrequire(lastP.p->m_lock_owner_ptr_i == loPtr.i);
1781  }
1782  else
1783  {
1784  vlqrequire(loPtr.p->m_lo_last_parallel_op_ptr_i == RNIL);
1785  }
1786  }
1787 
1788  // Validate serie queue
1789  if (loPtr.p->nextSerialQue != RNIL)
1790  {
1791  Uint32 prev = loPtr.i;
1792  OperationrecPtr lastS;
1793  lastS.i = loPtr.p->nextSerialQue;
1794  while (true)
1795  {
1796  ptrCheckGuard(lastS, coprecsize, operationrec);
1797  vlqrequire(lastS.p->prevSerialQue == prev);
1798  vlqrequire(getNoParallelTransaction(lastS.p) == 1);
1799  vlqrequire((lastS.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0);
1800  vlqrequire((lastS.p->m_op_bits & Operationrec::OP_RUN_QUEUE) == 0);
1801  vlqrequire((lastS.p->m_op_bits & Operationrec::OP_STATE_MASK) == Operationrec::OP_STATE_WAITING);
1802  if (lastS.p->nextSerialQue == RNIL)
1803  break;
1804  prev = lastS.i;
1805  lastS.i = lastS.p->nextSerialQue;
1806  }
1807 
1808  vlqrequire(loPtr.p->m_lo_last_serial_op_ptr_i == lastS.i);
1809  }
1810  else
1811  {
1812  vlqrequire(loPtr.p->m_lo_last_serial_op_ptr_i == RNIL);
1813  }
1814  return true;
1815 }
1816 
1817 NdbOut&
1818 operator<<(NdbOut & out, Dbacc::OperationrecPtr ptr)
1819 {
1820  Uint32 opbits = ptr.p->m_op_bits;
1821  out << "[ " << dec << ptr.i
1822  << " [ " << hex << ptr.p->transId1
1823  << " " << hex << ptr.p->transId2 << "] "
1824  << " bits: H'" << hex << opbits << " ";
1825 
1826  bool read = false;
1827  switch(opbits & Dbacc::Operationrec::OP_MASK){
1828  case ZREAD: out << "READ "; read = true; break;
1829  case ZINSERT: out << "INSERT "; break;
1830  case ZUPDATE: out << "UPDATE "; break;
1831  case ZDELETE: out << "DELETE "; break;
1832  case ZWRITE: out << "WRITE "; break;
1833  case ZSCAN_OP: out << "SCAN "; read = true; break;
1834  default:
1835  out << "<Unknown: H'"
1836  << hex << (opbits & Dbacc::Operationrec::OP_MASK)
1837  << "> ";
1838  }
1839 
1840  if (read)
1841  {
1842  if (opbits & Dbacc::Operationrec::OP_LOCK_MODE)
1843  out << "(X)";
1844  else
1845  out << "(S)";
1846  if (opbits & Dbacc::Operationrec::OP_ACC_LOCK_MODE)
1847  out << "(X)";
1848  else
1849  out << "(S)";
1850  }
1851 
1852  if (opbits)
1853  {
1854  out << "(RQ)";
1855  }
1856 
1857  switch(opbits & Dbacc::Operationrec::OP_STATE_MASK){
1858  case Dbacc::Operationrec::OP_STATE_WAITING:
1859  out << " WAITING "; break;
1860  case Dbacc::Operationrec::OP_STATE_RUNNING:
1861  out << " RUNNING "; break;
1862  case Dbacc::Operationrec::OP_STATE_EXECUTED:
1863  out << " EXECUTED "; break;
1864  case Dbacc::Operationrec::OP_STATE_IDLE:
1865  out << " IDLE "; break;
1866  default:
1867  out << " <Unknown: H'"
1868  << hex << (opbits & Dbacc::Operationrec::OP_STATE_MASK)
1869  << "> ";
1870  }
1871 
1872 /*
1873  OP_MASK = 0x000F // 4 bits for operation type
1874  ,OP_LOCK_MODE = 0x0010 // 0 - shared lock, 1 = exclusive lock
1875  ,OP_ACC_LOCK_MODE = 0x0020 // Or:de lock mode of all operation
1876  // before me
1877  ,OP_LOCK_OWNER = 0x0040
1878  ,OP_DIRTY_READ = 0x0080
1879  ,OP_LOCK_REQ = 0x0100 // isAccLockReq
1880  ,OP_COMMIT_DELETE_CHECK = 0x0200
1881  ,OP_INSERT_IS_DONE = 0x0400
1882  ,OP_ELEMENT_DISAPPEARED = 0x0800
1883 
1884  ,OP_STATE_MASK = 0xF000
1885  ,OP_STATE_IDLE = 0xF000
1886  ,OP_STATE_WAITING = 0x0000
1887  ,OP_STATE_RUNNING = 0x1000
1888  ,OP_STATE_EXECUTED = 0x3000
1889  };
1890 */
1891  if (opbits & Dbacc::Operationrec::OP_LOCK_OWNER)
1892  out << "LO ";
1893 
1894  if (opbits & Dbacc::Operationrec::OP_DIRTY_READ)
1895  out << "DR ";
1896 
1897  if (opbits & Dbacc::Operationrec::OP_LOCK_REQ)
1898  out << "LOCK_REQ ";
1899 
1900  if (opbits & Dbacc::Operationrec::OP_COMMIT_DELETE_CHECK)
1901  out << "COMMIT_DELETE_CHECK ";
1902 
1903  if (opbits & Dbacc::Operationrec::OP_INSERT_IS_DONE)
1904  out << "INSERT_IS_DONE ";
1905 
1906  if (opbits & Dbacc::Operationrec::OP_ELEMENT_DISAPPEARED)
1907  out << "ELEMENT_DISAPPEARED ";
1908 
1909  if (opbits & Dbacc::Operationrec::OP_LOCK_OWNER)
1910  {
1911  out << "last_parallel: " << dec << ptr.p->m_lo_last_parallel_op_ptr_i << " ";
1912  out << "last_serial: " << dec << ptr.p->m_lo_last_serial_op_ptr_i << " ";
1913  }
1914 
1915  out << "]";
1916  return out;
1917 }
1918 
1919 void
1920 Dbacc::dump_lock_queue(OperationrecPtr loPtr)
1921 {
1922  if ((loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0)
1923  {
1924  while ((loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0 &&
1925  loPtr.p->prevParallelQue != RNIL)
1926  {
1927  loPtr.i = loPtr.p->prevParallelQue;
1928  ptrCheckGuard(loPtr, coprecsize, operationrec);
1929  }
1930 
1931  while ((loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0 &&
1932  loPtr.p->prevSerialQue != RNIL)
1933  {
1934  loPtr.i = loPtr.p->prevSerialQue;
1935  ptrCheckGuard(loPtr, coprecsize, operationrec);
1936  }
1937 
1938  ndbassert(loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
1939  }
1940 
1941  ndbout << "-- HEAD --" << endl;
1942  OperationrecPtr tmp = loPtr;
1943  while (tmp.i != RNIL)
1944  {
1945  ptrCheckGuard(tmp, coprecsize, operationrec);
1946  ndbout << tmp << " ";
1947  tmp.i = tmp.p->nextParallelQue;
1948 
1949  if (tmp.i == loPtr.i)
1950  {
1951  ndbout << " <LOOP>";
1952  break;
1953  }
1954  }
1955  ndbout << endl;
1956 
1957  tmp.i = loPtr.p->nextSerialQue;
1958  while (tmp.i != RNIL)
1959  {
1960  ptrCheckGuard(tmp, coprecsize, operationrec);
1961  OperationrecPtr tmp2 = tmp;
1962 
1963  if (tmp.i == loPtr.i)
1964  {
1965  ndbout << "<LOOP S>" << endl;
1966  break;
1967  }
1968 
1969  while (tmp2.i != RNIL)
1970  {
1971  ptrCheckGuard(tmp2, coprecsize, operationrec);
1972  ndbout << tmp2 << " ";
1973  tmp2.i = tmp2.p->nextParallelQue;
1974 
1975  if (tmp2.i == tmp.i)
1976  {
1977  ndbout << "<LOOP 3>";
1978  break;
1979  }
1980  }
1981  ndbout << endl;
1982  tmp.i = tmp.p->nextSerialQue;
1983  }
1984 }
1985 #endif
1986 
1987 /* -------------------------------------------------------------------------
1988  * PLACE_WRITE_IN_LOCK_QUEUE
1989  * INPUT: OPERATION_REC_PTR OUR OPERATION POINTER
1990  * QUE_OPER_PTR LOCK QUEUE OWNER OPERATION POINTER
1991  * PWI_PAGEPTR PAGE POINTER OF ELEMENT
1992  * TPWI_ELEMENTPTR ELEMENT POINTER OF ELEMENT
1993  * OUTPUT TRESULT =
1994  * ZPARALLEL_QUEUE OPERATION PLACED IN PARALLEL QUEUE
1995  * OPERATION CAN PROCEED NOW.
1996  * ZSERIAL_QUEUE OPERATION PLACED IN SERIAL QUEUE
1997  * ERROR CODE OPERATION NEEDS ABORTING
1998  * ------------------------------------------------------------------------- */
1999 Uint32
2000 Dbacc::placeWriteInLockQueue(OperationrecPtr lockOwnerPtr)
2001 {
2002  OperationrecPtr lastOpPtr;
2003  lastOpPtr.i = lockOwnerPtr.p->m_lo_last_parallel_op_ptr_i;
2004  Uint32 opbits = operationRecPtr.p->m_op_bits;
2005 
2006  if (lastOpPtr.i == RNIL)
2007  {
2008  lastOpPtr = lockOwnerPtr;
2009  }
2010  else
2011  {
2012  ptrCheckGuard(lastOpPtr, coprecsize, operationrec);
2013  }
2014 
2015  ndbassert(get_parallel_head(lastOpPtr) == lockOwnerPtr.i);
2016 
2017  Uint32 lastbits = lastOpPtr.p->m_op_bits;
2018  if (lastbits & Operationrec::OP_ACC_LOCK_MODE)
2019  {
2020  if(operationRecPtr.p->is_same_trans(lastOpPtr.p))
2021  {
2022  goto checkop;
2023  }
2024  }
2025  else
2026  {
2031  jam();
2032 
2036  OperationrecPtr loopPtr = lockOwnerPtr;
2037  do
2038  {
2039  ptrCheckGuard(loopPtr, coprecsize, operationrec);
2040  if (!loopPtr.p->is_same_trans(operationRecPtr.p))
2041  {
2042  goto serial;
2043  }
2044  loopPtr.i = loopPtr.p->nextParallelQue;
2045  } while (loopPtr.i != RNIL);
2046 
2047  goto checkop;
2048  }
2049 
2050 serial:
2051  jam();
2052  placeSerialQueue(lockOwnerPtr, operationRecPtr);
2053 
2054  validate_lock_queue(lockOwnerPtr);
2055 
2056  return ZSERIAL_QUEUE;
2057 
2058 checkop:
2059  /*
2060  WE ARE PERFORMING AN READ EXCLUSIVE, INSERT, UPDATE OR DELETE IN THE SAME
2061  TRANSACTION WHERE WE PREVIOUSLY HAVE EXECUTED AN OPERATION.
2062  Read-All, Update-All, Insert-All and Delete-Insert are allowed
2063  combinations.
2064  Delete-Read, Delete-Update and Delete-Delete are not an allowed
2065  combination and will result in tuple not found error.
2066  */
2067  Uint32 lstate = lastbits & Operationrec::OP_STATE_MASK;
2068 
2069  Uint32 retValue = ZSERIAL_QUEUE; // So that it gets blocked...
2070  if (lstate == Operationrec::OP_STATE_EXECUTED)
2071  {
2072  jam();
2073 
2078  Uint32 op = opbits & Operationrec::OP_MASK;
2079  Uint32 lop = lastbits & Operationrec::OP_MASK;
2080  if (op == ZINSERT && lop != ZDELETE)
2081  {
2082  jam();
2083  return ZWRITE_ERROR;
2084  }//if
2085 
2090 #if 0
2091  if (lop == ZDELETE && (op != ZINSERT && op != ZWRITE))
2092  {
2093  jam();
2094  return ZREAD_ERROR;
2095  }
2096 #else
2097  if (lop == ZDELETE && (op == ZUPDATE && op == ZDELETE))
2098  {
2099  jam();
2100  return ZREAD_ERROR;
2101  }
2102 #endif
2103 
2104  if(op == ZWRITE)
2105  {
2106  opbits &= ~(Uint32)Operationrec::OP_MASK;
2107  opbits |= (lop == ZDELETE) ? ZINSERT : ZUPDATE;
2108  }
2109 
2110  opbits |= Operationrec::OP_STATE_RUNNING;
2111  operationRecPtr.p->localdata[0] = lastOpPtr.p->localdata[0];
2112  operationRecPtr.p->localdata[1] = lastOpPtr.p->localdata[1];
2113  retValue = ZPARALLEL_QUEUE;
2114  }
2115 
2116  opbits |= Operationrec::OP_RUN_QUEUE;
2117  operationRecPtr.p->m_op_bits = opbits;
2118  operationRecPtr.p->prevParallelQue = lastOpPtr.i;
2119  operationRecPtr.p->m_lock_owner_ptr_i = lockOwnerPtr.i;
2120  lastOpPtr.p->nextParallelQue = operationRecPtr.i;
2121  lockOwnerPtr.p->m_lo_last_parallel_op_ptr_i = operationRecPtr.i;
2122 
2123  validate_lock_queue(lockOwnerPtr);
2124 
2125  return retValue;
2126 }//Dbacc::placeWriteInLockQueue()
2127 
2128 Uint32
2129 Dbacc::placeReadInLockQueue(OperationrecPtr lockOwnerPtr)
2130 {
2131  OperationrecPtr lastOpPtr;
2132  OperationrecPtr loopPtr = lockOwnerPtr;
2133  lastOpPtr.i = lockOwnerPtr.p->m_lo_last_parallel_op_ptr_i;
2134  Uint32 opbits = operationRecPtr.p->m_op_bits;
2135 
2136  if (lastOpPtr.i == RNIL)
2137  {
2138  lastOpPtr = lockOwnerPtr;
2139  }
2140  else
2141  {
2142  ptrCheckGuard(lastOpPtr, coprecsize, operationrec);
2143  }
2144 
2145  ndbassert(get_parallel_head(lastOpPtr) == lockOwnerPtr.i);
2146 
2151  Uint32 lastbits = lastOpPtr.p->m_op_bits;
2152  bool same = operationRecPtr.p->is_same_trans(lastOpPtr.p);
2153  if (same && (lastbits & Operationrec::OP_ACC_LOCK_MODE))
2154  {
2155  jam();
2156  opbits |= Operationrec::OP_LOCK_MODE; // Upgrade to X-lock
2157  goto checkop;
2158  }
2159 
2160  if ((lastbits & Operationrec::OP_ACC_LOCK_MODE) && !same)
2161  {
2162  jam();
2166  goto serial;
2167  }
2168 
2169  if (lockOwnerPtr.p->nextSerialQue == RNIL)
2170  {
2171  jam();
2172  goto checkop;
2173  }
2174 
2178  do
2179  {
2180  ptrCheckGuard(loopPtr, coprecsize, operationrec);
2181  if (loopPtr.p->is_same_trans(operationRecPtr.p))
2182  goto checkop;
2183  loopPtr.i = loopPtr.p->nextParallelQue;
2184  } while (loopPtr.i != RNIL);
2185 
2186 serial:
2187  placeSerialQueue(lockOwnerPtr, operationRecPtr);
2188 
2189  validate_lock_queue(lockOwnerPtr);
2190 
2191  return ZSERIAL_QUEUE;
2192 
2193 checkop:
2194  Uint32 lstate = lastbits & Operationrec::OP_STATE_MASK;
2195 
2196  Uint32 retValue = ZSERIAL_QUEUE; // So that it gets blocked...
2197  if (lstate == Operationrec::OP_STATE_EXECUTED)
2198  {
2199  jam();
2200 
2206 #if 0
2207 
2211  if (lop == ZDELETE)
2212  {
2213  jam();
2214  return ZREAD_ERROR;
2215  }
2216 #endif
2217 
2218  opbits |= Operationrec::OP_STATE_RUNNING;
2219  operationRecPtr.p->localdata[0] = lastOpPtr.p->localdata[0];
2220  operationRecPtr.p->localdata[1] = lastOpPtr.p->localdata[1];
2221  retValue = ZPARALLEL_QUEUE;
2222  }
2223  opbits |= (lastbits & Operationrec::OP_ACC_LOCK_MODE);
2224  opbits |= Operationrec::OP_RUN_QUEUE;
2225  operationRecPtr.p->m_op_bits = opbits;
2226 
2227  operationRecPtr.p->prevParallelQue = lastOpPtr.i;
2228  operationRecPtr.p->m_lock_owner_ptr_i = lockOwnerPtr.i;
2229  lastOpPtr.p->nextParallelQue = operationRecPtr.i;
2230  lockOwnerPtr.p->m_lo_last_parallel_op_ptr_i = operationRecPtr.i;
2231 
2232  validate_lock_queue(lockOwnerPtr);
2233 
2234  return retValue;
2235 }//Dbacc::placeReadInLockQueue
2236 
2237 void Dbacc::placeSerialQueue(OperationrecPtr lockOwnerPtr,
2238  OperationrecPtr opPtr)
2239 {
2240  OperationrecPtr lastOpPtr;
2241  lastOpPtr.i = lockOwnerPtr.p->m_lo_last_serial_op_ptr_i;
2242 
2243  if (lastOpPtr.i == RNIL)
2244  {
2245  // Lock owner is last...
2246  ndbrequire(lockOwnerPtr.p->nextSerialQue == RNIL);
2247  lastOpPtr = lockOwnerPtr;
2248  }
2249  else
2250  {
2251  ptrCheckGuard(lastOpPtr, coprecsize, operationrec);
2252  }
2253 
2254  operationRecPtr.p->prevSerialQue = lastOpPtr.i;
2255  lastOpPtr.p->nextSerialQue = opPtr.i;
2256  lockOwnerPtr.p->m_lo_last_serial_op_ptr_i = opPtr.i;
2257 }
2258 
2259 /* ------------------------------------------------------------------------- */
2260 /* ACC KEYREQ END */
2261 /* ------------------------------------------------------------------------- */
2262 void Dbacc::acckeyref1Lab(Signal* signal, Uint32 result_code)
2263 {
2264  operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
2265  /* ************************<< */
2266  /* ACCKEYREF */
2267  /* ************************<< */
2268  signal->theData[0] = cminusOne;
2269  signal->theData[1] = result_code;
2270  return;
2271 }//Dbacc::acckeyref1Lab()
2272 
2273 /* ******************----------------------------------------------------- */
2274 /* ACCMINUPDATE UPDATE LOCAL KEY REQ */
2275 /* DESCRIPTION: UPDATES LOCAL KEY OF AN ELEMENTS IN THE HASH TABLE */
2276 /* THIS SIGNAL IS WAITED AFTER ANY INSERT REQ */
2277 /* ENTER ACCMINUPDATE WITH SENDER: LQH, LEVEL B */
2278 /* OPERATION_REC_PTR, OPERATION RECORD PTR */
2279 /* CLOCALKEY(0), LOCAL KEY 1 */
2280 /* CLOCALKEY(1) LOCAL KEY 2 */
2281 /* ******************----------------------------------------------------- */
2282 void Dbacc::execACCMINUPDATE(Signal* signal)
2283 {
2284  Page8Ptr ulkPageidptr;
2285  Uint32 tulkLocalPtr;
2286  Uint32 tlocalkey1, tlocalkey2;
2287 
2288  jamEntry();
2289  operationRecPtr.i = signal->theData[0];
2290  tlocalkey1 = signal->theData[1];
2291  tlocalkey2 = signal->theData[2];
2292  Uint32 localref = Local_key::ref(tlocalkey1, tlocalkey2);
2293  ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
2294  Uint32 opbits = operationRecPtr.p->m_op_bits;
2295  fragrecptr.i = operationRecPtr.p->fragptr;
2296  ulkPageidptr.i = operationRecPtr.p->elementPage;
2297  tulkLocalPtr = operationRecPtr.p->elementPointer +
2298  operationRecPtr.p->elementIsforward;
2299 
2300  if ((opbits & Operationrec::OP_STATE_MASK) == Operationrec::OP_STATE_RUNNING)
2301  {
2302  ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
2303  ptrCheckGuard(ulkPageidptr, cpagesize, page8);
2304  dbgWord32(ulkPageidptr, tulkLocalPtr, tlocalkey1);
2305  arrGuard(tulkLocalPtr, 2048);
2306  operationRecPtr.p->localdata[0] = tlocalkey1;
2307  operationRecPtr.p->localdata[1] = tlocalkey2;
2308  if (likely(fragrecptr.p->localkeylen == 1))
2309  {
2310  ulkPageidptr.p->word32[tulkLocalPtr] = localref;
2311  return;
2312  }
2313  else if (fragrecptr.p->localkeylen == 2)
2314  {
2315  jam();
2316  ulkPageidptr.p->word32[tulkLocalPtr] = tlocalkey1;
2317  tulkLocalPtr = tulkLocalPtr + operationRecPtr.p->elementIsforward;
2318  dbgWord32(ulkPageidptr, tulkLocalPtr, tlocalkey2);
2319  arrGuard(tulkLocalPtr, 2048);
2320  ulkPageidptr.p->word32[tulkLocalPtr] = tlocalkey2;
2321  return;
2322  } else {
2323  jam();
2324  }//if
2325  }//if
2326  ndbrequire(false);
2327 }//Dbacc::execACCMINUPDATE()
2328 
2329 void
2330 Dbacc::removerow(Uint32 opPtrI, const Local_key* key)
2331 {
2332  jamEntry();
2333  operationRecPtr.i = opPtrI;
2334  ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
2335  Uint32 opbits = operationRecPtr.p->m_op_bits;
2336  fragrecptr.i = operationRecPtr.p->fragptr;
2337 
2338  /* Mark element disappeared */
2339  opbits |= Operationrec::OP_ELEMENT_DISAPPEARED;
2340  opbits &= ~Uint32(Operationrec::OP_COMMIT_DELETE_CHECK);
2341  operationRecPtr.p->m_op_bits = opbits;
2342 
2343 #ifdef VM_TRACE
2344  ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
2345  ndbrequire(operationRecPtr.p->localdata[0] == key->m_page_no);
2346  ndbrequire(operationRecPtr.p->localdata[1] == key->m_page_idx);
2347 #endif
2348 }//Dbacc::execACCMINUPDATE()
2349 
2350 /* ******************--------------------------------------------------------------- */
2351 /* ACC_COMMITREQ COMMIT TRANSACTION */
2352 /* SENDER: LQH, LEVEL B */
2353 /* INPUT: OPERATION_REC_PTR , */
2354 /* ******************--------------------------------------------------------------- */
2355 void Dbacc::execACC_COMMITREQ(Signal* signal)
2356 {
2357  Uint8 Toperation;
2358  jamEntry();
2359  Uint32 tmp = operationRecPtr.i = signal->theData[0];
2360  ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
2361  void* ptr = operationRecPtr.p;
2362  Uint32 opbits = operationRecPtr.p->m_op_bits;
2363  fragrecptr.i = operationRecPtr.p->fragptr;
2364  ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
2365  Toperation = opbits & Operationrec::OP_MASK;
2366  commitOperation(signal);
2367  ndbassert(operationRecPtr.i == tmp);
2368  ndbassert(operationRecPtr.p == ptr);
2369  operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
2370  if((Toperation != ZREAD) &&
2371  (Toperation != ZSCAN_OP))
2372  {
2373  fragrecptr.p->m_commit_count++;
2374  if (Toperation != ZINSERT) {
2375  if (Toperation != ZDELETE) {
2376  return;
2377  } else {
2378  jam();
2379  fragrecptr.p->noOfElements--;
2380  fragrecptr.p->slack += fragrecptr.p->elementLength;
2381  if (fragrecptr.p->slack > fragrecptr.p->slackCheck) {
2382  /* TIME FOR JOIN BUCKETS PROCESS */
2383  if (fragrecptr.p->expandCounter > 0) {
2384  if (fragrecptr.p->expandFlag < 2) {
2385  jam();
2386  signal->theData[0] = fragrecptr.i;
2387  signal->theData[1] = fragrecptr.p->p;
2388  signal->theData[2] = fragrecptr.p->maxp;
2389  signal->theData[3] = fragrecptr.p->expandFlag;
2390  fragrecptr.p->expandFlag = 2;
2391  sendSignal(cownBlockref, GSN_SHRINKCHECK2, signal, 4, JBB);
2392  }//if
2393  }//if
2394  }//if
2395  }//if
2396  } else {
2397  jam(); /* EXPAND PROCESS HANDLING */
2398  if (unlikely(opbits & Operationrec::OP_ELEMENT_DISAPPEARED))
2399  {
2400  jam();
2401  /* Commit of refresh of non existing tuple.
2402  * ZREFRESH->ZWRITE->ZINSERT
2403  * Do not affect element count
2404  */
2405  ndbrequire((opbits & Operationrec::OP_MASK) == ZINSERT);
2406  return;
2407  }
2408  fragrecptr.p->noOfElements++;
2409  fragrecptr.p->slack -= fragrecptr.p->elementLength;
2410  if (fragrecptr.p->slack >= (1u << 31)) {
2411  /* IT MEANS THAT IF SLACK < ZERO */
2412  if (fragrecptr.p->expandFlag == 0) {
2413  jam();
2414  fragrecptr.p->expandFlag = 2;
2415  signal->theData[0] = fragrecptr.i;
2416  signal->theData[1] = fragrecptr.p->p;
2417  signal->theData[2] = fragrecptr.p->maxp;
2418  sendSignal(cownBlockref, GSN_EXPANDCHECK2, signal, 3, JBB);
2419  }//if
2420  }//if
2421  }
2422  }
2423  return;
2424 }//Dbacc::execACC_COMMITREQ()
2425 
2426 /* ******************------------------------------------------------------- */
2427 /* ACC ABORT REQ ABORT ALL OPERATION OF THE TRANSACTION */
2428 /* ******************------------------------------+ */
2429 /* SENDER: LQH, LEVEL B */
2430 /* ******************------------------------------------------------------- */
2431 /* ACC ABORT REQ ABORT TRANSACTION */
2432 /* ******************------------------------------+ */
2433 /* SENDER: LQH, LEVEL B */
2434 void Dbacc::execACC_ABORTREQ(Signal* signal)
2435 {
2436  jamEntry();
2437  operationRecPtr.i = signal->theData[0];
2438  Uint32 sendConf = signal->theData[1];
2439  ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
2440  fragrecptr.i = operationRecPtr.p->fragptr;
2441  Uint32 opbits = operationRecPtr.p->m_op_bits;
2442  Uint32 opstate = opbits & Operationrec::OP_STATE_MASK;
2443  tresult = 0; /* ZFALSE */
2444 
2445  if (opbits == Operationrec::OP_EXECUTED_DIRTY_READ)
2446  {
2447  jam();
2448  }
2449  else if (opstate == Operationrec::OP_STATE_EXECUTED ||
2450  opstate == Operationrec::OP_STATE_WAITING ||
2451  opstate == Operationrec::OP_STATE_RUNNING)
2452  {
2453  jam();
2454  ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
2455  abortOperation(signal);
2456  }
2457 
2458  operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
2459 
2460  signal->theData[0] = operationRecPtr.p->userptr;
2461  signal->theData[1] = 0;
2462  switch(sendConf){
2463  case 0:
2464  return;
2465  case 2:
2466  if (opstate != Operationrec::OP_STATE_RUNNING)
2467  {
2468  return;
2469  }
2470  case 1:
2471  sendSignal(operationRecPtr.p->userblockref, GSN_ACC_ABORTCONF,
2472  signal, 1, JBB);
2473  }
2474 
2475  signal->theData[1] = RNIL;
2476 }
2477 
2478 /*
2479  * Lock or unlock tuple.
2480  */
2481 void Dbacc::execACC_LOCKREQ(Signal* signal)
2482 {
2483  jamEntry();
2484  AccLockReq* sig = (AccLockReq*)signal->getDataPtrSend();
2485  AccLockReq reqCopy = *sig;
2486  AccLockReq* const req = &reqCopy;
2487  Uint32 lockOp = (req->requestInfo & 0xFF);
2488  if (lockOp == AccLockReq::LockShared ||
2489  lockOp == AccLockReq::LockExclusive) {
2490  jam();
2491  // find table
2492  tabptr.i = req->tableId;
2493  ptrCheckGuard(tabptr, ctablesize, tabrec);
2494  // find fragment (TUX will know it)
2495  if (req->fragPtrI == RNIL) {
2496  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
2497  jam();
2498  if (tabptr.p->fragholder[i] == req->fragId){
2499  jam();
2500  req->fragPtrI = tabptr.p->fragptrholder[i];
2501  break;
2502  }
2503  }
2504  }
2505  fragrecptr.i = req->fragPtrI;
2506  ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
2507  ndbrequire(req->fragId == fragrecptr.p->myfid);
2508  // caller must be explicit here
2509  ndbrequire(req->accOpPtr == RNIL);
2510  // seize operation to hold the lock
2511  if (cfreeopRec != RNIL) {
2512  jam();
2513  seizeOpRec(signal);
2514  // init as in ACCSEIZEREQ
2515  operationRecPtr.p->userptr = req->userPtr;
2516  operationRecPtr.p->userblockref = req->userRef;
2517  operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
2518  operationRecPtr.p->scanRecPtr = RNIL;
2519  // do read with lock via ACCKEYREQ
2520  Uint32 lockMode = (lockOp == AccLockReq::LockShared) ? 0 : 1;
2521  Uint32 opCode = ZSCAN_OP;
2522  signal->theData[0] = operationRecPtr.i;
2523  signal->theData[1] = fragrecptr.i;
2524  signal->theData[2] = opCode | (lockMode << 4) | (1u << 31);
2525  signal->theData[3] = req->hashValue;
2526  signal->theData[4] = 0; // search local key
2527  signal->theData[5] = req->transId1;
2528  signal->theData[6] = req->transId2;
2529  // enter local key in place of PK
2530  signal->theData[7] = req->page_id;
2531  signal->theData[8] = req->page_idx;
2532  EXECUTE_DIRECT(DBACC, GSN_ACCKEYREQ, signal, 9);
2533  // translate the result
2534  if (signal->theData[0] < RNIL) {
2535  jam();
2536  req->returnCode = AccLockReq::Success;
2537  req->accOpPtr = operationRecPtr.i;
2538  } else if (signal->theData[0] == RNIL) {
2539  jam();
2540  req->returnCode = AccLockReq::IsBlocked;
2541  req->accOpPtr = operationRecPtr.i;
2542  } else {
2543  ndbrequire(signal->theData[0] == (UintR)-1);
2544  releaseOpRec(signal);
2545  req->returnCode = AccLockReq::Refused;
2546  req->accOpPtr = RNIL;
2547  }
2548  } else {
2549  jam();
2550  req->returnCode = AccLockReq::NoFreeOp;
2551  }
2552  *sig = *req;
2553  return;
2554  }
2555  if (lockOp == AccLockReq::Unlock) {
2556  jam();
2557  // do unlock via ACC_COMMITREQ (immediate)
2558  signal->theData[0] = req->accOpPtr;
2559  EXECUTE_DIRECT(DBACC, GSN_ACC_COMMITREQ, signal, 1);
2560  releaseOpRec(signal);
2561  req->returnCode = AccLockReq::Success;
2562  *sig = *req;
2563  return;
2564  }
2565  if (lockOp == AccLockReq::Abort) {
2566  jam();
2567  // do abort via ACC_ABORTREQ (immediate)
2568  signal->theData[0] = req->accOpPtr;
2569  signal->theData[1] = 0; // Dont send abort
2570  execACC_ABORTREQ(signal);
2571  releaseOpRec(signal);
2572  req->returnCode = AccLockReq::Success;
2573  *sig = *req;
2574  return;
2575  }
2576  if (lockOp == AccLockReq::AbortWithConf) {
2577  jam();
2578  // do abort via ACC_ABORTREQ (with conf signal)
2579  signal->theData[0] = req->accOpPtr;
2580  signal->theData[1] = 1; // send abort
2581  execACC_ABORTREQ(signal);
2582  releaseOpRec(signal);
2583  req->returnCode = AccLockReq::Success;
2584  *sig = *req;
2585  return;
2586  }
2587  ndbrequire(false);
2588 }
2589 
2590 /* --------------------------------------------------------------------------------- */
2591 /* --------------------------------------------------------------------------------- */
2592 /* --------------------------------------------------------------------------------- */
2593 /* */
2594 /* END OF EXECUTE OPERATION MODULE */
2595 /* */
2596 /* --------------------------------------------------------------------------------- */
2597 /* --------------------------------------------------------------------------------- */
2598 /* --------------------------------------------------------------------------------- */
2599 /* --------------------------------------------------------------------------------- */
2600 /* */
2601 /* MODULE: INSERT */
2602 /* THE FOLLOWING SUBROUTINES ARE ONLY USED BY INSERT_ELEMENT. THIS */
2603 /* ROUTINE IS THE SOLE INTERFACE TO INSERT ELEMENTS INTO THE INDEX. */
2604 /* CURRENT USERS ARE INSERT REQUESTS, EXPAND CONTAINER AND SHRINK */
2605 /* CONTAINER. */
2606 /* */
2607 /* THE FOLLOWING SUBROUTINES ARE INCLUDED IN THIS MODULE: */
2608 /* INSERT_ELEMENT */
2609 /* INSERT_CONTAINER */
2610 /* ADDNEWCONTAINER */
2611 /* GETFREELIST */
2612 /* INCREASELISTCONT */
2613 /* SEIZE_LEFTLIST */
2614 /* SEIZE_RIGHTLIST */
2615 /* */
2616 /* THESE ROUTINES ARE ONLY USED BY THIS MODULE AND BY NO ONE ELSE. */
2617 /* ALSO THE ROUTINES MAKE NO USE OF ROUTINES IN OTHER MODULES. */
2618 /* TAKE_REC_OUT_OF_FREE_OVERPAGE AND RELEASE_OVERFLOW_REC ARE */
2619 /* EXCEPTIONS TO THIS RULE. */
2620 /* */
2621 /* THE ONLY SHORT-LIVED VARIABLES USED IN OTHER PARTS OF THE BLOCK ARE */
2622 /* THOSE DEFINED AS INPUT AND OUTPUT IN INSERT_ELEMENT */
2623 /* SHORT-LIVED VARIABLES INCLUDE TEMPORARY VARIABLES, COMMON VARIABLES */
2624 /* AND POINTER VARIABLES. */
2625 /* THE ONLY EXCEPTION TO THIS RULE IS FRAGRECPTR WHICH POINTS TO THE */
2626 /* FRAGMENT RECORD. THIS IS MORE LESS STATIC ALWAYS DURING A SIGNAL */
2627 /* EXECUTION. */
2628 /* */
2629 /* --------------------------------------------------------------------------------- */
2630 /* --------------------------------------------------------------------------------- */
2631 /* --------------------------------------------------------------------------------- */
2632 /* INSERT_ELEMENT */
2633 /* INPUT: */
2634 /* IDR_PAGEPTR (POINTER TO THE ACTIVE PAGE REC) */
2635 /* TIDR_PAGEINDEX (INDEX OF THE CONTAINER) */
2636 /* TIDR_FORWARD (DIRECTION FORWARD OR BACKWARD) */
2637 /* TIDR_ELEMHEAD (HEADER OF ELEMENT TO BE INSERTED */
2638 /* CIDR_KEYS(ARRAY OF TUPLE KEYS) */
2639 /* CLOCALKEY(ARRAY OF LOCAL KEYS). */
2640 /* FRAGRECPTR */
2641 /* IDR_OPERATION_REC_PTR */
2642 /* TIDR_KEY_LEN */
2643 /* */
2644 /* OUTPUT: */
2645 /* TIDR_PAGEINDEX (PAGE INDEX OF INSERTED ELEMENT) */
2646 /* IDR_PAGEPTR (PAGE POINTER OF INSERTED ELEMENT) */
2647 /* TIDR_FORWARD (CONTAINER DIRECTION OF INSERTED ELEMENT) */
2648 /* NONE */
2649 /* --------------------------------------------------------------------------------- */
2650 void Dbacc::insertElement(Signal* signal)
2651 {
2652  DirRangePtr inrOverflowrangeptr;
2653  DirectoryarrayPtr inrOverflowDirptr;
2654  OverflowRecordPtr inrOverflowRecPtr;
2655  Page8Ptr inrNewPageptr;
2656  Uint32 tinrNextSamePage;
2657  Uint32 tinrTmp;
2658 
2659  do {
2660  insertContainer(signal);
2661  if (tidrResult != ZFALSE) {
2662  jam();
2663  return;
2664  /* INSERTION IS DONE, OR */
2665  /* AN ERROR IS DETECTED */
2666  }//if
2667  if (((tidrContainerhead >> 7) & 0x3) != 0) {
2668  tinrNextSamePage = (tidrContainerhead >> 9) & 0x1; /* CHECK BIT FOR CHECKING WHERE */
2669  /* THE NEXT CONTAINER IS IN THE SAME PAGE */
2670  tidrPageindex = tidrContainerhead & 0x7f; /* NEXT CONTAINER PAGE INDEX 7 BITS */
2671  if (((tidrContainerhead >> 7) & 3) == ZLEFT) {
2672  jam();
2673  tidrForward = ZTRUE;
2674  } else if (((tidrContainerhead >> 7) & 3) == ZRIGHT) {
2675  jam();
2676  tidrForward = cminusOne;
2677  } else {
2678  ndbrequire(false);
2679  return;
2680  }//if
2681  if (tinrNextSamePage == ZFALSE) {
2682  jam(); /* NEXT CONTAINER IS IN AN OVERFLOW PAGE */
2683  tinrTmp = idrPageptr.p->word32[tidrContainerptr + 1];
2684  inrOverflowrangeptr.i = fragrecptr.p->overflowdir;
2685  ptrCheckGuard(inrOverflowrangeptr, cdirrangesize, dirRange);
2686  arrGuard((tinrTmp >> 8), 256);
2687  inrOverflowDirptr.i = inrOverflowrangeptr.p->dirArray[tinrTmp >> 8];
2688  ptrCheckGuard(inrOverflowDirptr, cdirarraysize, directoryarray);
2689  idrPageptr.i = inrOverflowDirptr.p->pagep[tinrTmp & 0xff];
2690  ptrCheckGuard(idrPageptr, cpagesize, page8);
2691  }//if
2692  ndbrequire(tidrPageindex < ZEMPTYLIST);
2693  } else {
2694  break;
2695  }//if
2696  } while (1);
2697  gflPageptr.p = idrPageptr.p;
2698  getfreelist(signal);
2699  if (tgflPageindex == ZEMPTYLIST) {
2700  jam();
2701  /* NO FREE BUFFER IS FOUND */
2702  if (fragrecptr.p->firstOverflowRec == RNIL) {
2703  jam();
2704  allocOverflowPage(signal);
2705  ndbrequire(tresult <= ZLIMIT_OF_ERROR);
2706  }//if
2707  inrOverflowRecPtr.i = fragrecptr.p->firstOverflowRec;
2708  ptrCheckGuard(inrOverflowRecPtr, coverflowrecsize, overflowRecord);
2709  inrNewPageptr.i = inrOverflowRecPtr.p->overpage;
2710  ptrCheckGuard(inrNewPageptr, cpagesize, page8);
2711  gflPageptr.p = inrNewPageptr.p;
2712  getfreelist(signal);
2713  ndbrequire(tgflPageindex != ZEMPTYLIST);
2714  tancNext = 0;
2715  } else {
2716  jam();
2717  inrNewPageptr = idrPageptr;
2718  tancNext = 1;
2719  }//if
2720  tslUpdateHeader = ZTRUE;
2721  tslPageindex = tgflPageindex;
2722  slPageptr.p = inrNewPageptr.p;
2723  if (tgflBufType == ZLEFT) {
2724  seizeLeftlist(signal);
2725  tidrForward = ZTRUE;
2726  } else {
2727  seizeRightlist(signal);
2728  tidrForward = cminusOne;
2729  }//if
2730  tancPageindex = tgflPageindex;
2731  tancPageid = inrNewPageptr.p->word32[ZPOS_PAGE_ID];
2732  tancBufType = tgflBufType;
2733  tancContainerptr = tidrContainerptr;
2734  ancPageptr.p = idrPageptr.p;
2735  addnewcontainer(signal);
2736 
2737  idrPageptr = inrNewPageptr;
2738  tidrPageindex = tgflPageindex;
2739  insertContainer(signal);
2740  ndbrequire(tidrResult == ZTRUE);
2741 }//Dbacc::insertElement()
2742 
2743 /* --------------------------------------------------------------------------------- */
2744 /* INSERT_CONTAINER */
2745 /* INPUT: */
2746 /* IDR_PAGEPTR (POINTER TO THE ACTIVE PAGE REC) */
2747 /* TIDR_PAGEINDEX (INDEX OF THE CONTAINER) */
2748 /* TIDR_FORWARD (DIRECTION FORWARD OR BACKWARD) */
2749 /* TIDR_ELEMHEAD (HEADER OF ELEMENT TO BE INSERTED */
2750 /* CKEYS(ARRAY OF TUPLE KEYS) */
2751 /* CLOCALKEY(ARRAY 0F LOCAL KEYS). */
2752 /* TIDR_KEY_LEN */
2753 /* FRAGRECPTR */
2754 /* IDR_OPERATION_REC_PTR */
2755 /* OUTPUT: */
2756 /* TIDR_RESULT (ZTRUE FOR SUCCESS AND ZFALSE OTHERWISE) */
2757 /* TIDR_CONTAINERHEAD (HEADER OF CONTAINER) */
2758 /* TIDR_CONTAINERPTR (POINTER TO CONTAINER HEADER) */
2759 /* */
2760 /* DESCRIPTION: */
2761 /* THE FREE AREA OF THE CONTAINER WILL BE CALCULATED. IF IT IS */
2762 /* LARGER THAN OR EQUAL THE ELEMENT LENGTH. THE ELEMENT WILL BE */
2763 /* INSERT IN THE CONTAINER AND CONTAINER HEAD WILL BE UPDATED. */
2764 /* THIS ROUTINE ALWAYS DEALS WITH ONLY ONE CONTAINER AND DO NEVER */
2765 /* START ANYTHING OUTSIDE OF THIS CONTAINER. */
2766 /* */
2767 /* SHORT FORM: IDR */
2768 /* --------------------------------------------------------------------------------- */
2769 void Dbacc::insertContainer(Signal* signal)
2770 {
2771  Uint32 tidrContainerlen;
2772  Uint32 tidrConfreelen;
2773  Uint32 tidrNextSide;
2774  Uint32 tidrNextConLen;
2775  Uint32 tidrIndex;
2776  Uint32 tidrInputIndex;
2777  Uint32 tidrContLen;
2778  Uint32 guard26;
2779 
2780  tidrResult = ZFALSE;
2781  tidrContainerptr = (tidrPageindex << ZSHIFT_PLUS) - (tidrPageindex << ZSHIFT_MINUS);
2782  tidrContainerptr = tidrContainerptr + ZHEAD_SIZE;
2783  /* --------------------------------------------------------------------------------- */
2784  /* CALCULATE THE POINTER TO THE ELEMENT TO BE INSERTED AND THE POINTER TO THE */
2785  /* CONTAINER HEADER OF THE OTHER SIDE OF THE BUFFER. */
2786  /* --------------------------------------------------------------------------------- */
2787  if (tidrForward == ZTRUE) {
2788  jam();
2789  tidrNextSide = tidrContainerptr + (ZBUF_SIZE - ZCON_HEAD_SIZE);
2790  arrGuard(tidrNextSide + 1, 2048);
2791  tidrContainerhead = idrPageptr.p->word32[tidrContainerptr];
2792  tidrContainerlen = tidrContainerhead >> 26;
2793  tidrIndex = tidrContainerptr + tidrContainerlen;
2794  } else {
2795  jam();
2796  tidrNextSide = tidrContainerptr;
2797  tidrContainerptr = tidrContainerptr + (ZBUF_SIZE - ZCON_HEAD_SIZE);
2798  arrGuard(tidrContainerptr + 1, 2048);
2799  tidrContainerhead = idrPageptr.p->word32[tidrContainerptr];
2800  tidrContainerlen = tidrContainerhead >> 26;
2801  tidrIndex = (tidrContainerptr - tidrContainerlen) + (ZCON_HEAD_SIZE - 1);
2802  }//if
2803  if (tidrContainerlen > (ZBUF_SIZE - 3)) {
2804  return;
2805  }//if
2806  tidrConfreelen = ZBUF_SIZE - tidrContainerlen;
2807  /* --------------------------------------------------------------------------------- */
2808  /* WE CALCULATE THE TOTAL LENGTH THE CONTAINER CAN EXPAND TO */
2809  /* THIS INCLUDES THE OTHER SIDE OF THE BUFFER IF POSSIBLE TO EXPAND THERE. */
2810  /* --------------------------------------------------------------------------------- */
2811  if (((tidrContainerhead >> 10) & 1) == 0) {
2812  jam();
2813  /* --------------------------------------------------------------------------------- */
2814  /* WE HAVE NOT EXPANDED TO THE ENTIRE BUFFER YET. WE CAN THUS READ THE OTHER */
2815  /* SIDE'S CONTAINER HEADER TO READ HIS LENGTH. */
2816  /* --------------------------------------------------------------------------------- */
2817  tidrNextConLen = idrPageptr.p->word32[tidrNextSide] >> 26;
2818  tidrConfreelen = tidrConfreelen - tidrNextConLen;
2819  if (tidrConfreelen > ZBUF_SIZE) {
2820  ndbrequire(false);
2821  /* --------------------------------------------------------------------------------- */
2822  /* THE BUFFERS ARE PLACED ON TOP OF EACH OTHER. THIS SHOULD NEVER OCCUR. */
2823  /* --------------------------------------------------------------------------------- */
2824  return;
2825  }//if
2826  } else {
2827  jam();
2828  tidrNextConLen = 1; /* INDICATE OTHER SIDE IS NOT PART OF FREE LIST */
2829  }//if
2830  if (tidrConfreelen < fragrecptr.p->elementLength) {
2831  jam();
2832  /* --------------------------------------------------------------------------------- */
2833  /* THE CONTAINER COULD NOT BE EXPANDED TO FIT THE NEW ELEMENT. WE HAVE TO */
2834  /* RETURN AND FIND A NEW CONTAINER TO INSERT IT INTO. */
2835  /* --------------------------------------------------------------------------------- */
2836  return;
2837  }//if
2838  tidrContainerlen = tidrContainerlen + fragrecptr.p->elementLength;
2839  if (tidrNextConLen == 0) {
2840  /* EACH SIDE OF THE BUFFER WHICH BELONG TO A FREE */
2841  /* LIST, HAS ZERO AS LENGTH. */
2842  if (tidrContainerlen > ZUP_LIMIT) {
2843  dbgWord32(idrPageptr, tidrContainerptr, idrPageptr.p->word32[tidrContainerptr] | (1 << 10));
2844  idrPageptr.p->word32[tidrContainerptr] = idrPageptr.p->word32[tidrContainerptr] | (1 << 10);
2845  tslUpdateHeader = ZFALSE;
2846  tslPageindex = tidrPageindex;
2847  slPageptr.p = idrPageptr.p;
2848  if (tidrForward == ZTRUE) {
2849  jam();
2850  seizeRightlist(signal); /* REMOVE THE RIGHT SIDE OF THE BUFFER FROM THE LIST */
2851  } else {
2852  jam();
2853  /* OF THE FREE CONTAINERS */
2854  seizeLeftlist(signal); /* REMOVE THE LEFT SIDE OF THE BUFFER FROM THE LIST */
2855  }//if
2856  }//if
2857  }//if
2858  /* OF THE FREE CONTAINERS */
2859  /* --------------------------------------------------------------------------------- */
2860  /* WE HAVE NOW FOUND A FREE SPOT IN THE CURRENT CONTAINER. WE INSERT THE */
2861  /* ELEMENT HERE. THE ELEMENT CONTAINS A HEADER, A LOCAL KEY AND A TUPLE KEY. */
2862  /* BEFORE INSERTING THE ELEMENT WE WILL UPDATE THE OPERATION RECORD WITH THE */
2863  /* DATA CONCERNING WHERE WE INSERTED THE ELEMENT. THIS MAKES IT EASY TO FIND */
2864  /* THIS INFORMATION WHEN WE RETURN TO UPDATE THE LOCAL KEY OR RETURN TO COMMIT */
2865  /* OR ABORT THE INSERT. IF NO OPERATION RECORD EXIST IT MEANS THAT WE ARE */
2866  /* PERFORMING THIS AS A PART OF THE EXPAND OR SHRINK PROCESS. */
2867  /* --------------------------------------------------------------------------------- */
2868  if (idrOperationRecPtr.i != RNIL) {
2869  jam();
2870  idrOperationRecPtr.p->elementIsforward = tidrForward;
2871  idrOperationRecPtr.p->elementPage = idrPageptr.i;
2872  idrOperationRecPtr.p->elementContainer = tidrContainerptr;
2873  idrOperationRecPtr.p->elementPointer = tidrIndex;
2874  }//if
2875  /* --------------------------------------------------------------------------------- */
2876  /* WE CHOOSE TO UNDO LOG INSERTS BY WRITING THE BEFORE VALUE TO THE UNDO LOG. */
2877  /* WE COULD ALSO HAVE DONE THIS BY WRITING THIS BEFORE VALUE WHEN DELETING */
2878  /* ELEMENTS. WE CHOOSE TO PUT IT HERE SINCE WE THEREBY ENSURE THAT WE ALWAYS */
2879  /* UNDO LOG ALL WRITES TO PAGE MEMORY. IT SHOULD BE EASIER TO MAINTAIN SUCH A */
2880  /* STRUCTURE. IT IS RATHER DIFFICULT TO MAINTAIN A LOGICAL STRUCTURE WHERE */
2881  /* DELETES ARE INSERTS AND INSERTS ARE PURELY DELETES. */
2882  /* --------------------------------------------------------------------------------- */
2883  dbgWord32(idrPageptr, tidrIndex, tidrElemhead);
2884  idrPageptr.p->word32[tidrIndex] = tidrElemhead; /* INSERTS THE HEAD OF THE ELEMENT */
2885  tidrIndex += tidrForward;
2886  guard26 = fragrecptr.p->localkeylen - 1;
2887  arrGuard(guard26, 2);
2888  for (tidrInputIndex = 0; tidrInputIndex <= guard26; tidrInputIndex++) {
2889  dbgWord32(idrPageptr, tidrIndex, clocalkey[tidrInputIndex]);
2890  arrGuard(tidrIndex, 2048);
2891  idrPageptr.p->word32[tidrIndex] = clocalkey[tidrInputIndex]; /* INSERTS LOCALKEY */
2892  tidrIndex += tidrForward;
2893  }//for
2894  tidrContLen = idrPageptr.p->word32[tidrContainerptr] << 6;
2895  tidrContLen = tidrContLen >> 6;
2896  dbgWord32(idrPageptr, tidrContainerptr, (tidrContainerlen << 26) | tidrContLen);
2897  idrPageptr.p->word32[tidrContainerptr] = (tidrContainerlen << 26) | tidrContLen;
2898  tidrResult = ZTRUE;
2899 }//Dbacc::insertContainer()
2900 
2901 /* --------------------------------------------------------------------------------- */
2902 /* ADDNEWCONTAINER */
2903 /* INPUT: */
2904 /* TANC_CONTAINERPTR */
2905 /* ANC_PAGEPTR */
2906 /* TANC_NEXT */
2907 /* TANC_PAGEINDEX */
2908 /* TANC_BUF_TYPE */
2909 /* TANC_PAGEID */
2910 /* OUTPUT: */
2911 /* NONE */
2912 /* */
2913 /* --------------------------------------------------------------------------------- */
2914 void Dbacc::addnewcontainer(Signal* signal)
2915 {
2916  Uint32 tancTmp1;
2917 
2918  /* THE OLD DATA IS STORED ON AN UNDO PAGE */
2919  /* --------------------------------------------------------------------------------- */
2920  /* KEEP LENGTH INFORMATION IN BIT 26-31. */
2921  /* SET BIT 9 INDICATING IF NEXT BUFFER IN THE SAME PAGE USING TANC_NEXT. */
2922  /* SET TYPE OF NEXT CONTAINER IN BIT 7-8. */
2923  /* SET PAGE INDEX OF NEXT CONTAINER IN BIT 0-6. */
2924  /* KEEP INDICATOR OF OWNING OTHER SIDE OF BUFFER IN BIT 10. */
2925  /* --------------------------------------------------------------------------------- */
2926  tancTmp1 = ancPageptr.p->word32[tancContainerptr] >> 10;
2927  tancTmp1 = tancTmp1 << 1;
2928  tancTmp1 = tancTmp1 | tancNext;
2929  tancTmp1 = tancTmp1 << 2;
2930  tancTmp1 = tancTmp1 | tancBufType; /* TYPE OF THE NEXT CONTAINER */
2931  tancTmp1 = tancTmp1 << 7;
2932  tancTmp1 = tancTmp1 | tancPageindex;
2933  dbgWord32(ancPageptr, tancContainerptr, tancTmp1);
2934  ancPageptr.p->word32[tancContainerptr] = tancTmp1; /* HEAD OF THE CONTAINER IS UPDATED */
2935  dbgWord32(ancPageptr, tancContainerptr + 1, tancPageid);
2936  ancPageptr.p->word32[tancContainerptr + 1] = tancPageid;
2937 }//Dbacc::addnewcontainer()
2938 
2939 /* --------------------------------------------------------------------------------- */
2940 /* GETFREELIST */
2941 /* INPUT: */
2942 /* GFL_PAGEPTR (POINTER TO A PAGE RECORD). */
2943 /* OUTPUT: */
2944 /* TGFL_PAGEINDEX(POINTER TO A FREE BUFFER IN THE FREEPAGE), AND */
2945 /* TGFL_BUF_TYPE( TYPE OF THE FREE BUFFER). */
2946 /* DESCRIPTION: SEARCHS IN THE FREE LIST OF THE FREE BUFFER IN THE PAGE HEAD */
2947 /* (WORD32(1)),AND RETURN ADDRESS OF A FREE BUFFER OR NIL. */
2948 /* THE FREE BUFFER CAN BE A RIGHT CONTAINER OR A LEFT ONE */
2949 /* THE KIND OF THE CONTAINER IS NOTED BY TGFL_BUF_TYPE. */
2950 /* --------------------------------------------------------------------------------- */
2951 void Dbacc::getfreelist(Signal* signal)
2952 {
2953  Uint32 tgflTmp;
2954 
2955  tgflTmp = gflPageptr.p->word32[ZPOS_EMPTY_LIST];
2956  tgflPageindex = (tgflTmp >> 7) & 0x7f; /* LEFT FREE LIST */
2957  tgflBufType = ZLEFT;
2958  if (tgflPageindex == ZEMPTYLIST) {
2959  jam();
2960  tgflPageindex = tgflTmp & 0x7f; /* RIGHT FREE LIST */
2961  tgflBufType = ZRIGHT;
2962  }//if
2963  ndbrequire(tgflPageindex <= ZEMPTYLIST);
2964 }//Dbacc::getfreelist()
2965 
2966 /* --------------------------------------------------------------------------------- */
2967 /* INCREASELISTCONT */
2968 /* INPUT: */
2969 /* ILC_PAGEPTR PAGE POINTER TO INCREASE NUMBER OF CONTAINERS IN */
2970 /* A CONTAINER OF AN OVERFLOW PAGE (FREEPAGEPTR) IS ALLOCATED, NR OF */
2971 /* ALLOCATED CONTAINER HAVE TO BE INCRESE BY ONE . */
2972 /* IF THE NUMBER OF ALLOCATED CONTAINERS IS ABOVE THE FREE LIMIT WE WILL */
2973 /* REMOVE THE PAGE FROM THE FREE LIST. */
2974 /* --------------------------------------------------------------------------------- */
2975 void Dbacc::increaselistcont(Signal* signal)
2976 {
2977  OverflowRecordPtr ilcOverflowRecPtr;
2978 
2979  dbgWord32(ilcPageptr, ZPOS_ALLOC_CONTAINERS, ilcPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] + 1);
2980  ilcPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] = ilcPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] + 1;
2981  if (ilcPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] > ZFREE_LIMIT) {
2982  if (ilcPageptr.p->word32[ZPOS_OVERFLOWREC] != RNIL) {
2983  jam();
2984  ilcOverflowRecPtr.i = ilcPageptr.p->word32[ZPOS_OVERFLOWREC];
2985  dbgWord32(ilcPageptr, ZPOS_OVERFLOWREC, RNIL);
2986  ilcPageptr.p->word32[ZPOS_OVERFLOWREC] = RNIL;
2987  ptrCheckGuard(ilcOverflowRecPtr, coverflowrecsize, overflowRecord);
2988  tfoOverflowRecPtr = ilcOverflowRecPtr;
2989  takeRecOutOfFreeOverpage(signal);
2990  rorOverflowRecPtr = ilcOverflowRecPtr;
2991  releaseOverflowRec(signal);
2992  }//if
2993  }//if
2994 }//Dbacc::increaselistcont()
2995 
2996 /* --------------------------------------------------------------------------------- */
2997 /* SEIZE_LEFTLIST */
2998 /* INPUT: */
2999 /* TSL_PAGEINDEX PAGE INDEX OF CONTAINER TO SEIZE */
3000 /* SL_PAGEPTR PAGE POINTER OF CONTAINER TO SEIZE */
3001 /* TSL_UPDATE_HEADER SHOULD WE UPDATE THE CONTAINER HEADER */
3002 /* */
3003 /* OUTPUT: */
3004 /* NONE */
3005 /* DESCRIPTION: THE BUFFER NOTED BY TSL_PAGEINDEX WILL BE REMOVED FROM THE */
3006 /* LIST OF LEFT FREE CONTAINER, IN THE HEADER OF THE PAGE */
3007 /* (FREEPAGEPTR). PREVIOUS AND NEXT BUFFER OF REMOVED BUFFER */
3008 /* WILL BE UPDATED. */
3009 /* --------------------------------------------------------------------------------- */
3010 void Dbacc::seizeLeftlist(Signal* signal)
3011 {
3012  Uint32 tsllTmp1;
3013  Uint32 tsllNewHead;
3014  Uint32 tsllHeadIndex;
3015  Uint32 tsllTmp;
3016 
3017  tsllHeadIndex = ((tslPageindex << ZSHIFT_PLUS) - (tslPageindex << ZSHIFT_MINUS)) + ZHEAD_SIZE;
3018  arrGuard(tsllHeadIndex + 1, 2048);
3019  tslNextfree = slPageptr.p->word32[tsllHeadIndex];
3020  tslPrevfree = slPageptr.p->word32[tsllHeadIndex + 1];
3021  if (tslPrevfree == ZEMPTYLIST) {
3022  jam();
3023  /* UPDATE FREE LIST OF LEFT CONTAINER IN PAGE HEAD */
3024  tsllTmp1 = slPageptr.p->word32[ZPOS_EMPTY_LIST];
3025  tsllTmp = tsllTmp1 & 0x7f;
3026  tsllTmp1 = (tsllTmp1 >> 14) << 14;
3027  tsllTmp1 = (tsllTmp1 | (tslNextfree << 7)) | tsllTmp;
3028  dbgWord32(slPageptr, ZPOS_EMPTY_LIST, tsllTmp1);
3029  slPageptr.p->word32[ZPOS_EMPTY_LIST] = tsllTmp1;
3030  } else {
3031  ndbrequire(tslPrevfree < ZEMPTYLIST);
3032  jam();
3033  tsllTmp = ((tslPrevfree << ZSHIFT_PLUS) - (tslPrevfree << ZSHIFT_MINUS)) + ZHEAD_SIZE;
3034  dbgWord32(slPageptr, tsllTmp, tslNextfree);
3035  slPageptr.p->word32[tsllTmp] = tslNextfree;
3036  }//if
3037  if (tslNextfree < ZEMPTYLIST) {
3038  jam();
3039  tsllTmp = (((tslNextfree << ZSHIFT_PLUS) - (tslNextfree << ZSHIFT_MINUS)) + ZHEAD_SIZE) + 1;
3040  dbgWord32(slPageptr, tsllTmp, tslPrevfree);
3041  slPageptr.p->word32[tsllTmp] = tslPrevfree;
3042  } else {
3043  ndbrequire(tslNextfree == ZEMPTYLIST);
3044  jam();
3045  }//if
3046  /* --------------------------------------------------------------------------------- */
3047  /* IF WE ARE UPDATING THE HEADER WE ARE CREATING A NEW CONTAINER IN THE PAGE. */
3048  /* TO BE ABLE TO FIND ALL LOCKED ELEMENTS WE KEEP ALL CONTAINERS IN LINKED */
3049  /* LISTS IN THE PAGE. */
3050  /* */
3051  /* ZPOS_EMPTY_LIST CONTAINS A NEXT POINTER IN BIT 16-22 THAT REFERS TO THE */
3052  /* FIRST CONTAINER IN A LIST OF USED RIGHT CONTAINERS IN THE PAGE. */
3053  /* ZPOS_EMPTY_LIST CONTAINS A NEXT POINTER IN BIT 23-29 THAT REFERS TO THE */
3054  /* FIRST CONTAINER IN A LIST OF USED LEFT CONTAINERS IN THE PAGE. */
3055  /* EACH CONTAINER IN THE LIST CONTAINS A NEXT POINTER IN BIT 11-17 AND IT */
3056  /* CONTAINS A PREVIOUS POINTER IN BIT 18-24. */
3057  /* WE ALSO SET BIT 25 TO INDICATE THAT IT IS A CONTAINER HEADER. */
3058  /* --------------------------------------------------------------------------------- */
3059  if (tslUpdateHeader == ZTRUE) {
3060  jam();
3061  tslNextfree = (slPageptr.p->word32[ZPOS_EMPTY_LIST] >> 23) & 0x7f;
3062  tsllNewHead = ZCON_HEAD_SIZE;
3063  tsllNewHead = ((tsllNewHead << 8) + ZEMPTYLIST) + (1 << 7);
3064  tsllNewHead = (tsllNewHead << 7) + tslNextfree;
3065  tsllNewHead = tsllNewHead << 11;
3066  dbgWord32(slPageptr, tsllHeadIndex, tsllNewHead);
3067  slPageptr.p->word32[tsllHeadIndex] = tsllNewHead;
3068  tsllTmp = slPageptr.p->word32[ZPOS_EMPTY_LIST] & 0xc07fffff;
3069  tsllTmp = tsllTmp | (tslPageindex << 23);
3070  dbgWord32(slPageptr, ZPOS_EMPTY_LIST, tsllTmp);
3071  slPageptr.p->word32[ZPOS_EMPTY_LIST] = tsllTmp;
3072  if (tslNextfree < ZEMPTYLIST) {
3073  jam();
3074  tsllTmp = ((tslNextfree << ZSHIFT_PLUS) - (tslNextfree << ZSHIFT_MINUS)) + ZHEAD_SIZE;
3075  tsllTmp1 = slPageptr.p->word32[tsllTmp] & 0xfe03ffff;
3076  tsllTmp1 = tsllTmp1 | (tslPageindex << 18);
3077  dbgWord32(slPageptr, tsllTmp, tsllTmp1);
3078  slPageptr.p->word32[tsllTmp] = tsllTmp1;
3079  } else {
3080  ndbrequire(tslNextfree == ZEMPTYLIST);
3081  jam();
3082  }//if
3083  }//if
3084  ilcPageptr.p = slPageptr.p;
3085  increaselistcont(signal);
3086 }//Dbacc::seizeLeftlist()
3087 
3088 /* --------------------------------------------------------------------------------- */
3089 /* SEIZE_RIGHTLIST */
3090 /* DESCRIPTION: THE BUFFER NOTED BY TSL_PAGEINDEX WILL BE REMOVED FROM THE */
3091 /* LIST OF RIGHT FREE CONTAINER, IN THE HEADER OF THE PAGE */
3092 /* (SL_PAGEPTR). PREVIOUS AND NEXT BUFFER OF REMOVED BUFFER */
3093 /* WILL BE UPDATED. */
3094 /* --------------------------------------------------------------------------------- */
3095 void Dbacc::seizeRightlist(Signal* signal)
3096 {
3097  Uint32 tsrlTmp1;
3098  Uint32 tsrlNewHead;
3099  Uint32 tsrlHeadIndex;
3100  Uint32 tsrlTmp;
3101 
3102  tsrlHeadIndex = ((tslPageindex << ZSHIFT_PLUS) - (tslPageindex << ZSHIFT_MINUS)) + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
3103  arrGuard(tsrlHeadIndex + 1, 2048);
3104  tslNextfree = slPageptr.p->word32[tsrlHeadIndex];
3105  tslPrevfree = slPageptr.p->word32[tsrlHeadIndex + 1];
3106  if (tslPrevfree == ZEMPTYLIST) {
3107  jam();
3108  tsrlTmp = slPageptr.p->word32[ZPOS_EMPTY_LIST];
3109  dbgWord32(slPageptr, ZPOS_EMPTY_LIST, ((tsrlTmp >> 7) << 7) | tslNextfree);
3110  slPageptr.p->word32[ZPOS_EMPTY_LIST] = ((tsrlTmp >> 7) << 7) | tslNextfree;
3111  } else {
3112  ndbrequire(tslPrevfree < ZEMPTYLIST);
3113  jam();
3114  tsrlTmp = ((tslPrevfree << ZSHIFT_PLUS) - (tslPrevfree << ZSHIFT_MINUS)) + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
3115  dbgWord32(slPageptr, tsrlTmp, tslNextfree);
3116  slPageptr.p->word32[tsrlTmp] = tslNextfree;
3117  }//if
3118  if (tslNextfree < ZEMPTYLIST) {
3119  jam();
3120  tsrlTmp = ((tslNextfree << ZSHIFT_PLUS) - (tslNextfree << ZSHIFT_MINUS)) + ((ZHEAD_SIZE + ZBUF_SIZE) - (ZCON_HEAD_SIZE - 1));
3121  dbgWord32(slPageptr, tsrlTmp, tslPrevfree);
3122  slPageptr.p->word32[tsrlTmp] = tslPrevfree;
3123  } else {
3124  ndbrequire(tslNextfree == ZEMPTYLIST);
3125  jam();
3126  }//if
3127  /* --------------------------------------------------------------------------------- */
3128  /* IF WE ARE UPDATING THE HEADER WE ARE CREATING A NEW CONTAINER IN THE PAGE. */
3129  /* TO BE ABLE TO FIND ALL LOCKED ELEMENTS WE KEEP ALL CONTAINERS IN LINKED */
3130  /* LISTS IN THE PAGE. */
3131  /* */
3132  /* ZPOS_EMPTY_LIST CONTAINS A NEXT POINTER IN BIT 16-22 THAT REFERS TO THE */
3133  /* FIRST CONTAINER IN A LIST OF USED RIGHT CONTAINERS IN THE PAGE. */
3134  /* ZPOS_EMPTY_LIST CONTAINS A NEXT POINTER IN BIT 23-29 THAT REFERS TO THE */
3135  /* FIRST CONTAINER IN A LIST OF USED LEFT CONTAINERS IN THE PAGE. */
3136  /* EACH CONTAINER IN THE LIST CONTAINS A NEXT POINTER IN BIT 11-17 AND IT */
3137  /* CONTAINS A PREVIOUS POINTER IN BIT 18-24. */
3138  /* --------------------------------------------------------------------------------- */
3139  if (tslUpdateHeader == ZTRUE) {
3140  jam();
3141  tslNextfree = (slPageptr.p->word32[ZPOS_EMPTY_LIST] >> 16) & 0x7f;
3142  tsrlNewHead = ZCON_HEAD_SIZE;
3143  tsrlNewHead = ((tsrlNewHead << 8) + ZEMPTYLIST) + (1 << 7);
3144  tsrlNewHead = (tsrlNewHead << 7) + tslNextfree;
3145  tsrlNewHead = tsrlNewHead << 11;
3146  dbgWord32(slPageptr, tsrlHeadIndex, tsrlNewHead);
3147  slPageptr.p->word32[tsrlHeadIndex] = tsrlNewHead;
3148  tsrlTmp = slPageptr.p->word32[ZPOS_EMPTY_LIST] & 0xff80ffff;
3149  dbgWord32(slPageptr, ZPOS_EMPTY_LIST, tsrlTmp | (tslPageindex << 16));
3150  slPageptr.p->word32[ZPOS_EMPTY_LIST] = tsrlTmp | (tslPageindex << 16);
3151  if (tslNextfree < ZEMPTYLIST) {
3152  jam();
3153  tsrlTmp = ((tslNextfree << ZSHIFT_PLUS) - (tslNextfree << ZSHIFT_MINUS)) + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
3154  tsrlTmp1 = slPageptr.p->word32[tsrlTmp] & 0xfe03ffff;
3155  dbgWord32(slPageptr, tsrlTmp, tsrlTmp1 | (tslPageindex << 18));
3156  slPageptr.p->word32[tsrlTmp] = tsrlTmp1 | (tslPageindex << 18);
3157  } else {
3158  ndbrequire(tslNextfree == ZEMPTYLIST);
3159  jam();
3160  }//if
3161  }//if
3162  ilcPageptr.p = slPageptr.p;
3163  increaselistcont(signal);
3164 }//Dbacc::seizeRightlist()
3165 
3166 /* --------------------------------------------------------------------------------- */
3167 /* --------------------------------------------------------------------------------- */
3168 /* --------------------------------------------------------------------------------- */
3169 /* */
3170 /* END OF INSERT_ELEMENT MODULE */
3171 /* */
3172 /* --------------------------------------------------------------------------------- */
3173 /* --------------------------------------------------------------------------------- */
3174 /* --------------------------------------------------------------------------------- */
3175 /* --------------------------------------------------------------------------------- */
3176 /* --------------------------------------------------------------------------------- */
3177 /* */
3178 /* MODULE: GET_ELEMENT */
3179 /* THE FOLLOWING SUBROUTINES ARE ONLY USED BY GET_ELEMENT AND */
3180 /* GETDIRINDEX. THIS ROUTINE IS THE SOLE INTERFACE TO GET ELEMENTS */
3181 /* FROM THE INDEX. CURRENT USERS ARE ALL REQUESTS AND EXECUTE UNDO LOG */
3182 /* */
3183 /* THE FOLLOWING SUBROUTINES ARE INCLUDED IN THIS MODULE: */
3184 /* GET_ELEMENT */
3185 /* GET_DIRINDEX */
3186 /* SEARCH_LONG_KEY */
3187 /* */
3188 /* THESE ROUTINES ARE ONLY USED BY THIS MODULE AND BY NO ONE ELSE. */
3189 /* ALSO THE ROUTINES MAKE NO USE OF ROUTINES IN OTHER MODULES. */
3190 /* THE ONLY SHORT-LIVED VARIABLES USED IN OTHER PARTS OF THE BLOCK ARE */
3191 /* THOSE DEFINED AS INPUT AND OUTPUT IN GET_ELEMENT AND GETDIRINDEX */
3192 /* SHORT-LIVED VARIABLES INCLUDE TEMPORARY VARIABLES, COMMON VARIABLES */
3193 /* AND POINTER VARIABLES. */
3194 /* THE ONLY EXCEPTION TO THIS RULE IS FRAGRECPTR WHICH POINTS TO THE */
3195 /* FRAGMENT RECORD. THIS IS MORE LESS STATIC ALWAYS DURING A SIGNAL */
3196 /* EXECUTION. */
3197 /* */
3198 /* --------------------------------------------------------------------------------- */
3199 /* --------------------------------------------------------------------------------- */
3200 /* --------------------------------------------------------------------------------- */
3201 /* GETDIRINDEX */
3202 /* SUPPORT ROUTINE FOR INSERT ELEMENT, GET ELEMENT AND COMMITDELETE */
3203 /* INPUT:FRAGRECPTR ( POINTER TO THE ACTIVE FRAGMENT REC) */
3204 /* OPERATION_REC_PTR (POINTER TO THE OPERATION REC). */
3205 /* */
3206 /* OUTPUT:GDI_PAGEPTR ( POINTER TO THE PAGE OF THE ELEMENT) */
3207 /* TGDI_PAGEINDEX ( INDEX OF THE ELEMENT IN THE PAGE). */
3208 /* */
3209 /* DESCRIPTION: CHECK THE HASH VALUE OF THE OPERATION REC AND CALCULATE THE */
3210 /* THE ADDRESS OF THE ELEMENT IN THE HASH TABLE,(GDI_PAGEPTR, */
3211 /* TGDI_PAGEINDEX) ACCORDING TO LH3. */
3212 /* --------------------------------------------------------------------------------- */
3213 void Dbacc::getdirindex(Signal* signal)
3214 {
3215  DirRangePtr gdiDirRangePtr;
3216  DirectoryarrayPtr gdiDirptr;
3217  Uint32 tgdiTmp;
3218  Uint32 tgdiAddress;
3219 
3220  tgdiTmp = fragrecptr.p->k + fragrecptr.p->lhfragbits; /* OBS K = 6 */
3221  tgdiPageindex = operationRecPtr.p->hashValue & ((1 << fragrecptr.p->k) - 1);
3222  tgdiTmp = operationRecPtr.p->hashValue >> tgdiTmp;
3223  tgdiTmp = (tgdiTmp << fragrecptr.p->k) | tgdiPageindex;
3224  tgdiAddress = tgdiTmp & fragrecptr.p->maxp;
3225  gdiDirRangePtr.i = fragrecptr.p->directory;
3226  ptrCheckGuard(gdiDirRangePtr, cdirrangesize, dirRange);
3227  if (tgdiAddress < fragrecptr.p->p) {
3228  jam();
3229  tgdiAddress = tgdiTmp & ((fragrecptr.p->maxp << 1) | 1);
3230  }//if
3231  tgdiTmp = tgdiAddress >> fragrecptr.p->k;
3232  arrGuard((tgdiTmp >> 8), 256);
3233  gdiDirptr.i = gdiDirRangePtr.p->dirArray[tgdiTmp >> 8];
3234  ptrCheckGuard(gdiDirptr, cdirarraysize, directoryarray);
3235  gdiPageptr.i = gdiDirptr.p->pagep[tgdiTmp & 0xff]; /* DIRECTORY INDEX OF SEND BUCKET PAGE */
3236  ptrCheckGuard(gdiPageptr, cpagesize, page8);
3237 }//Dbacc::getdirindex()
3238 
3239 Uint32
3240 Dbacc::readTablePk(Uint32 localkey1, Uint32 localkey2,
3241  Uint32 eh, Ptr<Operationrec> opPtr)
3242 {
3243  int ret;
3244  Uint32 tableId = fragrecptr.p->myTableId;
3245  Uint32 fragId = fragrecptr.p->myfid;
3246  bool xfrm = fragrecptr.p->hasCharAttr;
3247 
3248 #ifdef VM_TRACE
3249  memset(ckeys, 0x1f, (fragrecptr.p->keyLength * MAX_XFRM_MULTIPLY) << 2);
3250 #endif
3251 
3252  if (likely(! Local_key::isInvalid(localkey1, localkey2)))
3253  {
3254  ret = c_tup->accReadPk(tableId, fragId, localkey1, localkey2,
3255  ckeys, true);
3256  }
3257  else
3258  {
3259  ndbrequire(ElementHeader::getLocked(eh));
3260  if (unlikely((opPtr.p->m_op_bits & Operationrec::OP_MASK) == ZSCAN_OP))
3261  {
3262  dump_lock_queue(opPtr);
3263  ndbrequire(opPtr.p->nextParallelQue == RNIL);
3264  ndbrequire(opPtr.p->m_op_bits & Operationrec::OP_ELEMENT_DISAPPEARED);
3265  ndbrequire(opPtr.p->m_op_bits & Operationrec::OP_COMMIT_DELETE_CHECK);
3266  ndbrequire((opPtr.p->m_op_bits & Operationrec::OP_STATE_MASK) == Operationrec::OP_STATE_RUNNING);
3267  return 0;
3268  }
3269  ret = c_lqh->readPrimaryKeys(opPtr.p->userptr, ckeys, xfrm);
3270  }
3271  jamEntry();
3272  ndbrequire(ret >= 0);
3273  return ret;
3274 }
3275 
3276 /* --------------------------------------------------------------------------------- */
3277 /* GET_ELEMENT */
3278 /* INPUT: */
3279 /* OPERATION_REC_PTR */
3280 /* FRAGRECPTR */
3281 /* OUTPUT: */
3282 /* TGE_RESULT RESULT SUCCESS = ZTRUE OTHERWISE ZFALSE */
3283 /* TGE_LOCKED LOCK INFORMATION IF SUCCESSFUL RESULT */
3284 /* GE_PAGEPTR PAGE POINTER OF FOUND ELEMENT */
3285 /* TGE_CONTAINERPTR CONTAINER INDEX OF FOUND ELEMENT */
3286 /* TGE_ELEMENTPTR ELEMENT INDEX OF FOUND ELEMENT */
3287 /* TGE_FORWARD DIRECTION OF CONTAINER WHERE ELEMENT FOUND */
3288 /* */
3289 /* DESCRIPTION: THE SUBROUTIN GOES THROUGH ALL CONTAINERS OF THE ACTIVE */
3290 /* BUCKET, AND SERCH FOR ELEMENT.THE PRIMARY KEYS WHICH IS SAVED */
3291 /* IN THE OPERATION REC ARE THE CHECK ITEMS IN THE SEARCHING. */
3292 /* --------------------------------------------------------------------------------- */
3293 
3294 #if __ia64 == 1
3295 #if __INTEL_COMPILER == 810
3296 int ndb_acc_ia64_icc810_dummy_var = 0;
3297 void ndb_acc_ia64_icc810_dummy_func()
3298 {
3299  ndb_acc_ia64_icc810_dummy_var++;
3300 }
3301 #endif
3302 #endif
3303 
3304 Uint32
3305 Dbacc::getElement(Signal* signal, OperationrecPtr& lockOwnerPtr)
3306 {
3307  Uint32 errcode;
3308  DirRangePtr geOverflowrangeptr;
3309  DirectoryarrayPtr geOverflowDirptr;
3310  Uint32 tgeElementHeader;
3311  Uint32 tgeElemStep;
3312  Uint32 tgeContainerhead;
3313  Uint32 tgePageindex;
3314  Uint32 tgeActivePageDir;
3315  Uint32 tgeNextptrtype;
3316  register Uint32 tgeKeyptr;
3317  register Uint32 tgeRemLen;
3318  register Uint32 TelemLen = fragrecptr.p->elementLength;
3319  register Uint32* Tkeydata = (Uint32*)&signal->theData[7];
3320  const Uint32 localkeylen = fragrecptr.p->localkeylen;
3321 
3322  getdirindex(signal);
3323  tgePageindex = tgdiPageindex;
3324  gePageptr = gdiPageptr;
3325  /*
3326  * The value seached is
3327  * - table key for ACCKEYREQ, stored in TUP
3328  * - local key (1 word) for ACC_LOCKREQ and UNDO, stored in ACC
3329  */
3330  const bool searchLocalKey = operationRecPtr.p->tupkeylen == 0;
3331 
3332  ndbrequire(TelemLen == ZELEM_HEAD_SIZE + localkeylen);
3333  tgeNextptrtype = ZLEFT;
3334 
3335  const Uint32 tmp = fragrecptr.p->k + fragrecptr.p->lhfragbits;
3336  const Uint32 opHashValuePart = (operationRecPtr.p->hashValue >> tmp) &0xFFFF;
3337  do {
3338  tgeContainerptr = (tgePageindex << ZSHIFT_PLUS) - (tgePageindex << ZSHIFT_MINUS);
3339  if (tgeNextptrtype == ZLEFT) {
3340  jam();
3341  tgeContainerptr = tgeContainerptr + ZHEAD_SIZE;
3342  tgeElementptr = tgeContainerptr + ZCON_HEAD_SIZE;
3343  tgeKeyptr = (tgeElementptr + ZELEM_HEAD_SIZE) + localkeylen;
3344  tgeElemStep = TelemLen;
3345  tgeForward = 1;
3346  if (unlikely(tgeContainerptr >= 2048))
3347  {
3348  errcode = 4;
3349  goto error;
3350  }
3351  tgeRemLen = gePageptr.p->word32[tgeContainerptr] >> 26;
3352  if (unlikely(((tgeContainerptr + tgeRemLen - 1) >= 2048)))
3353  {
3354  errcode = 5;
3355  goto error;
3356  }
3357  } else if (tgeNextptrtype == ZRIGHT) {
3358  jam();
3359  tgeContainerptr = tgeContainerptr + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
3360  tgeElementptr = tgeContainerptr - 1;
3361  tgeKeyptr = (tgeElementptr - ZELEM_HEAD_SIZE) - localkeylen;
3362  tgeElemStep = 0 - TelemLen;
3363  tgeForward = (Uint32)-1;
3364  if (unlikely(tgeContainerptr >= 2048))
3365  {
3366  errcode = 4;
3367  goto error;
3368  }
3369  tgeRemLen = gePageptr.p->word32[tgeContainerptr] >> 26;
3370  if (unlikely((tgeContainerptr - tgeRemLen) >= 2048))
3371  {
3372  errcode = 5;
3373  goto error;
3374  }
3375  } else {
3376  errcode = 6;
3377  goto error;
3378  }//if
3379  if (tgeRemLen >= ZCON_HEAD_SIZE + TelemLen) {
3380  if (unlikely(tgeRemLen > ZBUF_SIZE))
3381  {
3382  errcode = 7;
3383  goto error;
3384  }//if
3385  /* ------------------------------------------------------------------- */
3386  // There is at least one element in this container.
3387  // Check if it is the element searched for.
3388  /* ------------------------------------------------------------------- */
3389  do {
3390  tgeElementHeader = gePageptr.p->word32[tgeElementptr];
3391  tgeRemLen = tgeRemLen - TelemLen;
3392  Uint32 hashValuePart;
3393  Uint32 localkey1, localkey2;
3394  lockOwnerPtr.i = RNIL;
3395  lockOwnerPtr.p = NULL;
3396  if (ElementHeader::getLocked(tgeElementHeader)) {
3397  jam();
3398  lockOwnerPtr.i = ElementHeader::getOpPtrI(tgeElementHeader);
3399  ptrCheckGuard(lockOwnerPtr, coprecsize, operationrec);
3400  hashValuePart = lockOwnerPtr.p->hashvaluePart;
3401  localkey1 = lockOwnerPtr.p->localdata[0];
3402  localkey2 = lockOwnerPtr.p->localdata[1];
3403  } else {
3404  jam();
3405  Uint32 pos = tgeElementptr + tgeForward;
3406  hashValuePart = ElementHeader::getHashValuePart(tgeElementHeader);
3407  localkey1 = gePageptr.p->word32[pos];
3408  if (likely(localkeylen == 1))
3409  {
3410  localkey2 = Local_key::ref2page_idx(localkey1);
3411  localkey1 = Local_key::ref2page_id(localkey1);
3412  }
3413  else
3414  {
3415  localkey2 = gePageptr.p->word32[pos + tgeForward];
3416  }
3417  }
3418  if (hashValuePart == opHashValuePart) {
3419  jam();
3420  bool found;
3421  if (! searchLocalKey)
3422  {
3423  Uint32 len = readTablePk(localkey1, localkey2, tgeElementHeader,
3424  lockOwnerPtr);
3425  found = (len == operationRecPtr.p->xfrmtupkeylen) &&
3426  (memcmp(Tkeydata, ckeys, len << 2) == 0);
3427  } else {
3428  jam();
3429  found = (localkey1 == Tkeydata[0] && localkey2 == Tkeydata[1]);
3430  }
3431  if (found)
3432  {
3433  jam();
3434  operationRecPtr.p->localdata[0] = localkey1;
3435  operationRecPtr.p->localdata[1] = localkey2;
3436  return ZTRUE;
3437  }
3438  }
3439  if (tgeRemLen <= ZCON_HEAD_SIZE) {
3440  break;
3441  }
3442  tgeElementptr = tgeElementptr + tgeElemStep;
3443  } while (true);
3444  }//if
3445  if (unlikely(tgeRemLen != ZCON_HEAD_SIZE))
3446  {
3447  errcode = 8;
3448  goto error;
3449  }//if
3450  tgeContainerhead = gePageptr.p->word32[tgeContainerptr];
3451  tgeNextptrtype = (tgeContainerhead >> 7) & 0x3;
3452  if (tgeNextptrtype == 0) {
3453  jam();
3454  return ZFALSE; /* NO MORE CONTAINER */
3455  }//if
3456  tgePageindex = tgeContainerhead & 0x7f; /* NEXT CONTAINER PAGE INDEX 7 BITS */
3457  if (unlikely(tgePageindex > ZEMPTYLIST))
3458  {
3459  errcode = 9;
3460  goto error;
3461  }//if
3462  if (((tgeContainerhead >> 9) & 1) == ZFALSE) {
3463  jam();
3464  tgeActivePageDir = gePageptr.p->word32[tgeContainerptr + 1]; /* NEXT PAGE ID */
3465  geOverflowrangeptr.i = fragrecptr.p->overflowdir;
3466  ptrCheckGuard(geOverflowrangeptr, cdirrangesize, dirRange);
3467  arrGuard((tgeActivePageDir >> 8), 256);
3468  geOverflowDirptr.i = geOverflowrangeptr.p->dirArray[tgeActivePageDir >> 8];
3469  ptrCheckGuard(geOverflowDirptr, cdirarraysize, directoryarray);
3470  gePageptr.i = geOverflowDirptr.p->pagep[tgeActivePageDir & 0xff];
3471  ptrCheckGuard(gePageptr, cpagesize, page8);
3472  }//if
3473  } while (1);
3474 
3475  return ZFALSE;
3476 
3477 error:
3478  ACCKEY_error(errcode);
3479  return ~0;
3480 }//Dbacc::getElement()
3481 
3482 /* ------------------------------------------------------------------------- */
3483 /* ------------------------------------------------------------------------- */
3484 /* ------------------------------------------------------------------------- */
3485 /* */
3486 /* END OF GET_ELEMENT MODULE */
3487 /* */
3488 /* ------------------------------------------------------------------------- */
3489 /* ------------------------------------------------------------------------- */
3490 /* ------------------------------------------------------------------------- */
3491 /* ------------------------------------------------------------------------- */
3492 /* ------------------------------------------------------------------------- */
3493 /* */
3494 /* MODULE: DELETE */
3495 /* */
3496 /* ------------------------------------------------------------------------- */
3497 /* ------------------------------------------------------------------------- */
3498 /* ------------------------------------------------------------------------- */
3499 /* COMMITDELETE */
3500 /* INPUT: OPERATION_REC_PTR, PTR TO AN OPERATION RECORD. */
3501 /* FRAGRECPTR, PTR TO A FRAGMENT RECORD */
3502 /* */
3503 /* OUTPUT: */
3504 /* NONE */
3505 /* DESCRIPTION: DELETE OPERATIONS WILL BE COMPLETED AT THE
3506  * COMMIT OF TRANSACTION. THIS SUBROUTINE SEARCHS FOR ELEMENT AND
3507  * DELETES IT. IT DOES SO BY REPLACING IT WITH THE LAST
3508  * ELEMENT IN THE BUCKET. IF THE DELETED ELEMENT IS ALSO THE LAST
3509  * ELEMENT THEN IT IS ONLY NECESSARY TO REMOVE THE ELEMENT
3510  * ------------------------------------------------------------------------- */
3511 void
3512 Dbacc::report_dealloc(Signal* signal, const Operationrec* opPtrP)
3513 {
3514  Uint32 localKey1 = opPtrP->localdata[0];
3515  Uint32 localKey2 = opPtrP->localdata[1];
3516  Uint32 opbits = opPtrP->m_op_bits;
3517  Uint32 userptr= opPtrP->userptr;
3518  Uint32 scanInd =
3519  ((opbits & Operationrec::OP_MASK) == ZSCAN_OP) ||
3520  (opbits & Operationrec::OP_LOCK_REQ);
3521 
3522  if (! Local_key::isInvalid(localKey1, localKey2))
3523  {
3524  signal->theData[0] = fragrecptr.p->myfid;
3525  signal->theData[1] = fragrecptr.p->myTableId;
3526  signal->theData[2] = localKey1;
3527  signal->theData[3] = localKey2;
3528  signal->theData[4] = userptr;
3529  signal->theData[5] = scanInd;
3530  EXECUTE_DIRECT(DBLQH, GSN_TUP_DEALLOCREQ, signal, 6);
3531  jamEntry();
3532  }
3533 }
3534 
3535 void Dbacc::commitdelete(Signal* signal)
3536 {
3537  jam();
3538  report_dealloc(signal, operationRecPtr.p);
3539 
3540  getdirindex(signal);
3541  tlastPageindex = tgdiPageindex;
3542  lastPageptr.i = gdiPageptr.i;
3543  lastPageptr.p = gdiPageptr.p;
3544  tlastForward = ZTRUE;
3545  tlastContainerptr = (tlastPageindex << ZSHIFT_PLUS) - (tlastPageindex << ZSHIFT_MINUS);
3546  tlastContainerptr = tlastContainerptr + ZHEAD_SIZE;
3547  arrGuard(tlastContainerptr, 2048);
3548  tlastContainerhead = lastPageptr.p->word32[tlastContainerptr];
3549  tlastContainerlen = tlastContainerhead >> 26;
3550  lastPrevpageptr.i = RNIL;
3551  ptrNull(lastPrevpageptr);
3552  tlastPrevconptr = 0;
3553  getLastAndRemove(signal);
3554 
3555  delPageptr.i = operationRecPtr.p->elementPage;
3556  ptrCheckGuard(delPageptr, cpagesize, page8);
3557  tdelElementptr = operationRecPtr.p->elementPointer;
3558  /* --------------------------------------------------------------------------------- */
3559  // Here we have to take extreme care since we do not want locks to end up after the
3560  // log execution. Thus it is necessary to put back the element in unlocked shape.
3561  // We thus update the element header to ensure we log an unlocked element. We do not
3562  // need to restore it later since it is deleted immediately anyway.
3563  /* --------------------------------------------------------------------------------- */
3564  const Uint32 hv = operationRecPtr.p->hashvaluePart;
3565  const Uint32 eh = ElementHeader::setUnlocked(hv, 0);
3566  delPageptr.p->word32[tdelElementptr] = eh;
3567  if (operationRecPtr.p->elementPage == lastPageptr.i) {
3568  if (operationRecPtr.p->elementPointer == tlastElementptr) {
3569  jam();
3570  /* --------------------------------------------------------------------------------- */
3571  /* THE LAST ELEMENT WAS THE ELEMENT TO BE DELETED. WE NEED NOT COPY IT. */
3572  /* --------------------------------------------------------------------------------- */
3573  return;
3574  }//if
3575  }//if
3576  /* --------------------------------------------------------------------------------- */
3577  /* THE DELETED ELEMENT IS NOT THE LAST. WE READ THE LAST ELEMENT AND OVERWRITE THE */
3578  /* DELETED ELEMENT. */
3579  /* --------------------------------------------------------------------------------- */
3580  tdelContainerptr = operationRecPtr.p->elementContainer;
3581  tdelForward = operationRecPtr.p->elementIsforward;
3582  deleteElement(signal);
3583 }//Dbacc::commitdelete()
3584 
3585 /* --------------------------------------------------------------------------------- */
3586 /* DELETE_ELEMENT */
3587 /* INPUT: FRAGRECPTR, POINTER TO A FRAGMENT RECORD */
3588 /* LAST_PAGEPTR, POINTER TO THE PAGE OF THE LAST ELEMENT */
3589 /* DEL_PAGEPTR, POINTER TO THE PAGE OF THE DELETED ELEMENT */
3590 /* TLAST_ELEMENTPTR, ELEMENT POINTER OF THE LAST ELEMENT */
3591 /* TDEL_ELEMENTPTR, ELEMENT POINTER OF THE DELETED ELEMENT */
3592 /* TLAST_FORWARD, DIRECTION OF LAST ELEMENT */
3593 /* TDEL_FORWARD, DIRECTION OF DELETED ELEMENT */
3594 /* TDEL_CONTAINERPTR, CONTAINER POINTER OF DELETED ELEMENT */
3595 /* DESCRIPTION: COPY LAST ELEMENT TO DELETED ELEMENT AND UPDATE UNDO LOG AND */
3596 /* UPDATE ANY ACTIVE OPERATION ON THE MOVED ELEMENT. */
3597 /* --------------------------------------------------------------------------------- */
3598 void Dbacc::deleteElement(Signal* signal)
3599 {
3600  OperationrecPtr deOperationRecPtr;
3601  Uint32 tdeIndex;
3602  Uint32 tlastMoveElemptr;
3603  Uint32 tdelMoveElemptr;
3604  Uint32 guard31;
3605 
3606  if (tlastElementptr >= 2048)
3607  goto deleteElement_index_error1;
3608  {
3609  const Uint32 tdeElemhead = lastPageptr.p->word32[tlastElementptr];
3610  tlastMoveElemptr = tlastElementptr;
3611  tdelMoveElemptr = tdelElementptr;
3612  guard31 = fragrecptr.p->elementLength - 1;
3613  for (tdeIndex = 0; tdeIndex <= guard31; tdeIndex++) {
3614  dbgWord32(delPageptr, tdelMoveElemptr, lastPageptr.p->word32[tlastMoveElemptr]);
3615  if ((tlastMoveElemptr >= 2048) ||
3616  (tdelMoveElemptr >= 2048))
3617  goto deleteElement_index_error2;
3618  delPageptr.p->word32[tdelMoveElemptr] = lastPageptr.p->word32[tlastMoveElemptr];
3619  tdelMoveElemptr = tdelMoveElemptr + tdelForward;
3620  tlastMoveElemptr = tlastMoveElemptr + tlastForward;
3621  }//for
3622  if (ElementHeader::getLocked(tdeElemhead)) {
3623  /* --------------------------------------------------------------------------------- */
3624  /* THE LAST ELEMENT IS LOCKED AND IS THUS REFERENCED BY AN OPERATION RECORD. WE NEED */
3625  /* TO UPDATE THE OPERATION RECORD WITH THE NEW REFERENCE TO THE ELEMENT. */
3626  /* --------------------------------------------------------------------------------- */
3627  deOperationRecPtr.i = ElementHeader::getOpPtrI(tdeElemhead);
3628  ptrCheckGuard(deOperationRecPtr, coprecsize, operationrec);
3629  deOperationRecPtr.p->elementPage = delPageptr.i;
3630  deOperationRecPtr.p->elementContainer = tdelContainerptr;
3631  deOperationRecPtr.p->elementPointer = tdelElementptr;
3632  deOperationRecPtr.p->elementIsforward = tdelForward;
3633  /* --------------------------------------------------------------------------------- */
3634  // We need to take extreme care to not install locked records after system restart.
3635  // An undo of the delete will reinstall the moved record. We have to ensure that the
3636  // lock is removed to ensure that no such thing happen.
3637  /* --------------------------------------------------------------------------------- */
3638  Uint32 eh = ElementHeader::setUnlocked(deOperationRecPtr.p->hashvaluePart,
3639  0);
3640  lastPageptr.p->word32[tlastElementptr] = eh;
3641  }//if
3642  return;
3643  }
3644 
3645  deleteElement_index_error1:
3646  arrGuard(tlastElementptr, 2048);
3647  return;
3648 
3649  deleteElement_index_error2:
3650  arrGuard(tdelMoveElemptr + guard31, 2048);
3651  arrGuard(tlastMoveElemptr, 2048);
3652  return;
3653 
3654 }//Dbacc::deleteElement()
3655 
3656 /* --------------------------------------------------------------------------------- */
3657 /* GET_LAST_AND_REMOVE */
3658 /* INPUT: */
3659 /* LAST_PAGEPTR PAGE POINTER OF FIRST CONTAINER IN SEARCH OF LAST*/
3660 /* TLAST_CONTAINERPTR CONTAINER INDEX OF THE SAME */
3661 /* TLAST_CONTAINERHEAD CONTAINER HEADER OF THE SAME */
3662 /* TLAST_PAGEINDEX PAGE INDEX OF THE SAME */
3663 /* TLAST_FORWARD CONTAINER DIRECTION OF THE SAME */
3664 /* TLAST_CONTAINERLEN CONTAINER LENGTH OF THE SAME */
3665 /* LAST_PREVPAGEPTR PAGE POINTER OF PREVIOUS CONTAINER OF THE SAME */
3666 /* TLAST_PREVCONPTR CONTAINER INDEX OF PREVIOUS CONTAINER OF THE SAME*/
3667 /* */
3668 /* OUTPUT: */
3669 /* ALL VARIABLES FROM INPUT BUT NOW CONTAINING INFO ABOUT LAST */
3670 /* CONTAINER. */
3671 /* TLAST_ELEMENTPTR LAST ELEMENT POINTER IN LAST CONTAINER */
3672 /* --------------------------------------------------------------------------------- */
3673 void Dbacc::getLastAndRemove(Signal* signal)
3674 {
3675  DirRangePtr glrOverflowrangeptr;
3676  DirectoryarrayPtr glrOverflowDirptr;
3677  Uint32 tglrHead;
3678  Uint32 tglrTmp;
3679 
3680  GLR_LOOP_10:
3681  if (((tlastContainerhead >> 7) & 0x3) != 0) {
3682  jam();
3683  lastPrevpageptr.i = lastPageptr.i;
3684  lastPrevpageptr.p = lastPageptr.p;
3685  tlastPrevconptr = tlastContainerptr;
3686  tlastPageindex = tlastContainerhead & 0x7f;
3687  if (((tlastContainerhead >> 9) & 0x1) == ZFALSE) {
3688  jam();
3689  arrGuard(tlastContainerptr + 1, 2048);
3690  tglrTmp = lastPageptr.p->word32[tlastContainerptr + 1];
3691  glrOverflowrangeptr.i = fragrecptr.p->overflowdir;
3692  ptrCheckGuard(glrOverflowrangeptr, cdirrangesize, dirRange);
3693  arrGuard((tglrTmp >> 8), 256);
3694  glrOverflowDirptr.i = glrOverflowrangeptr.p->dirArray[tglrTmp >> 8];
3695  ptrCheckGuard(glrOverflowDirptr, cdirarraysize, directoryarray);
3696  lastPageptr.i = glrOverflowDirptr.p->pagep[tglrTmp & 0xff];
3697  ptrCheckGuard(lastPageptr, cpagesize, page8);
3698  }//if
3699  tlastContainerptr = (tlastPageindex << ZSHIFT_PLUS) - (tlastPageindex << ZSHIFT_MINUS);
3700  if (((tlastContainerhead >> 7) & 3) == ZLEFT) {
3701  jam();
3702  tlastForward = ZTRUE;
3703  tlastContainerptr = tlastContainerptr + ZHEAD_SIZE;
3704  } else if (((tlastContainerhead >> 7) & 3) == ZRIGHT) {
3705  jam();
3706  tlastForward = cminusOne;
3707  tlastContainerptr = ((tlastContainerptr + ZHEAD_SIZE) + ZBUF_SIZE) - ZCON_HEAD_SIZE;
3708  } else {
3709  ndbrequire(false);
3710  return;
3711  }//if
3712  arrGuard(tlastContainerptr, 2048);
3713  tlastContainerhead = lastPageptr.p->word32[tlastContainerptr];
3714  tlastContainerlen = tlastContainerhead >> 26;
3715  ndbrequire(tlastContainerlen >= ((Uint32)ZCON_HEAD_SIZE + fragrecptr.p->elementLength));
3716  goto GLR_LOOP_10;
3717  }//if
3718  tlastContainerlen = tlastContainerlen - fragrecptr.p->elementLength;
3719  if (tlastForward == ZTRUE) {
3720  jam();
3721  tlastElementptr = tlastContainerptr + tlastContainerlen;
3722  } else {
3723  jam();
3724  tlastElementptr = (tlastContainerptr + (ZCON_HEAD_SIZE - 1)) - tlastContainerlen;
3725  }//if
3726  rlPageptr.i = lastPageptr.i;
3727  rlPageptr.p = lastPageptr.p;
3728  trlPageindex = tlastPageindex;
3729  if (((tlastContainerhead >> 10) & 1) == 1) {
3730  /* --------------------------------------------------------------------------------- */
3731  /* WE HAVE OWNERSHIP OF BOTH PARTS OF THE CONTAINER ENDS. */
3732  /* --------------------------------------------------------------------------------- */
3733  if (tlastContainerlen < ZDOWN_LIMIT) {
3734  /* --------------------------------------------------------------------------------- */
3735  /* WE HAVE DECREASED THE SIZE BELOW THE DOWN LIMIT, WE MUST GIVE UP THE OTHER */
3736  /* SIDE OF THE BUFFER. */
3737  /* --------------------------------------------------------------------------------- */
3738  tlastContainerhead = tlastContainerhead ^ (1 << 10);
3739  trlRelCon = ZFALSE;
3740  if (tlastForward == ZTRUE) {
3741  jam();
3742  turlIndex = tlastContainerptr + (ZBUF_SIZE - ZCON_HEAD_SIZE);
3743  releaseRightlist(signal);
3744  } else {
3745  jam();
3746  tullIndex = tlastContainerptr - (ZBUF_SIZE - ZCON_HEAD_SIZE);
3747  releaseLeftlist(signal);
3748  }//if
3749  }//if
3750  }//if
3751  if (tlastContainerlen <= 2) {
3752  ndbrequire(tlastContainerlen == 2);
3753  if (lastPrevpageptr.i != RNIL) {
3754  jam();
3755  /* --------------------------------------------------------------------------------- */
3756  /* THE LAST CONTAINER IS EMPTY AND IS NOT THE FIRST CONTAINER WHICH IS NOT REMOVED. */
3757  /* DELETE THE LAST CONTAINER AND UPDATE THE PREVIOUS CONTAINER. ALSO PUT THIS */
3758  /* CONTAINER IN FREE CONTAINER LIST OF THE PAGE. */
3759  /* --------------------------------------------------------------------------------- */
3760  ndbrequire(tlastPrevconptr < 2048);
3761  tglrTmp = lastPrevpageptr.p->word32[tlastPrevconptr] >> 9;
3762  dbgWord32(lastPrevpageptr, tlastPrevconptr, tglrTmp << 9);
3763  lastPrevpageptr.p->word32[tlastPrevconptr] = tglrTmp << 9;
3764  trlRelCon = ZTRUE;
3765  if (tlastForward == ZTRUE) {
3766  jam();
3767  tullIndex = tlastContainerptr;
3768  releaseLeftlist(signal);
3769  } else {
3770  jam();
3771  turlIndex = tlastContainerptr;
3772  releaseRightlist(signal);
3773  }//if
3774  return;
3775  }//if
3776  }//if
3777  tglrHead = tlastContainerhead << 6;
3778  tglrHead = tglrHead >> 6;
3779  tglrHead = tglrHead | (tlastContainerlen << 26);
3780  dbgWord32(lastPageptr, tlastContainerptr, tglrHead);
3781  arrGuard(tlastContainerptr, 2048);
3782  lastPageptr.p->word32[tlastContainerptr] = tglrHead;
3783 }//Dbacc::getLastAndRemove()
3784 
3785 /* --------------------------------------------------------------------------------- */
3786 /* RELEASE_LEFTLIST */
3787 /* INPUT: */
3788 /* RL_PAGEPTR PAGE POINTER OF CONTAINER TO BE RELEASED */
3789 /* TRL_PAGEINDEX PAGE INDEX OF CONTAINER TO BE RELEASED */
3790 /* TURL_INDEX INDEX OF CONTAINER TO BE RELEASED */
3791 /* TRL_REL_CON TRUE IF CONTAINER RELEASED OTHERWISE ONLY */
3792 /* A PART IS RELEASED. */
3793 /* */
3794 /* OUTPUT: */
3795 /* NONE */
3796 /* */
3797 /* THE FREE LIST OF LEFT FREE BUFFER IN THE PAGE WILL BE UPDATE */
3798 /* TULL_INDEX IS INDEX TO THE FIRST WORD IN THE LEFT SIDE OF THE BUFFER */
3799 /* --------------------------------------------------------------------------------- */
3800 void Dbacc::releaseLeftlist(Signal* signal)
3801 {
3802  Uint32 tullTmp;
3803  Uint32 tullTmp1;
3804 
3805  /* --------------------------------------------------------------------------------- */
3806  /* IF A CONTAINER IS RELEASED AND NOT ONLY A PART THEN WE HAVE TO REMOVE IT */
3807  /* FROM THE LIST OF USED CONTAINERS IN THE PAGE. THIS IN ORDER TO ENSURE THAT */
3808  /* WE CAN FIND ALL LOCKED ELEMENTS DURING LOCAL CHECKPOINT. */
3809  /* --------------------------------------------------------------------------------- */
3810  if (trlRelCon == ZTRUE) {
3811  arrGuard(tullIndex, 2048);
3812  trlHead = rlPageptr.p->word32[tullIndex];
3813  trlNextused = (trlHead >> 11) & 0x7f;
3814  trlPrevused = (trlHead >> 18) & 0x7f;
3815  if (trlNextused < ZEMPTYLIST) {
3816  jam();
3817  tullTmp1 = (trlNextused << ZSHIFT_PLUS) - (trlNextused << ZSHIFT_MINUS);
3818  tullTmp1 = tullTmp1 + ZHEAD_SIZE;
3819  tullTmp = rlPageptr.p->word32[tullTmp1] & 0xfe03ffff;
3820  dbgWord32(rlPageptr, tullTmp1, tullTmp | (trlPrevused << 18));
3821  rlPageptr.p->word32[tullTmp1] = tullTmp | (trlPrevused << 18);
3822  } else {
3823  ndbrequire(trlNextused == ZEMPTYLIST);
3824  jam();
3825  }//if
3826  if (trlPrevused < ZEMPTYLIST) {
3827  jam();
3828  tullTmp1 = (trlPrevused << ZSHIFT_PLUS) - (trlPrevused << ZSHIFT_MINUS);
3829  tullTmp1 = tullTmp1 + ZHEAD_SIZE;
3830  tullTmp = rlPageptr.p->word32[tullTmp1] & 0xfffc07ff;
3831  dbgWord32(rlPageptr, tullTmp1, tullTmp | (trlNextused << 11));
3832  rlPageptr.p->word32[tullTmp1] = tullTmp | (trlNextused << 11);
3833  } else {
3834  ndbrequire(trlPrevused == ZEMPTYLIST);
3835  jam();
3836  /* --------------------------------------------------------------------------------- */
3837  /* WE ARE FIRST IN THE LIST AND THUS WE NEED TO UPDATE THE FIRST POINTER. */
3838  /* --------------------------------------------------------------------------------- */
3839  tullTmp = rlPageptr.p->word32[ZPOS_EMPTY_LIST] & 0xc07fffff;
3840  dbgWord32(rlPageptr, ZPOS_EMPTY_LIST, tullTmp | (trlNextused << 23));
3841  rlPageptr.p->word32[ZPOS_EMPTY_LIST] = tullTmp | (trlNextused << 23);
3842  }//if
3843  }//if
3844  dbgWord32(rlPageptr, tullIndex + 1, ZEMPTYLIST);
3845  arrGuard(tullIndex + 1, 2048);
3846  rlPageptr.p->word32[tullIndex + 1] = ZEMPTYLIST;
3847  tullTmp1 = (rlPageptr.p->word32[ZPOS_EMPTY_LIST] >> 7) & 0x7f;
3848  dbgWord32(rlPageptr, tullIndex, tullTmp1);
3849  arrGuard(tullIndex, 2048);
3850  rlPageptr.p->word32[tullIndex] = tullTmp1;
3851  if (tullTmp1 < ZEMPTYLIST) {
3852  jam();
3853  tullTmp1 = (tullTmp1 << ZSHIFT_PLUS) - (tullTmp1 << ZSHIFT_MINUS);
3854  tullTmp1 = (tullTmp1 + ZHEAD_SIZE) + 1;
3855  dbgWord32(rlPageptr, tullTmp1, trlPageindex);
3856  rlPageptr.p->word32[tullTmp1] = trlPageindex; /* UPDATES PREV POINTER IN THE NEXT FREE */
3857  } else {
3858  ndbrequire(tullTmp1 == ZEMPTYLIST);
3859  }//if
3860  tullTmp = rlPageptr.p->word32[ZPOS_EMPTY_LIST];
3861  tullTmp = (((tullTmp >> 14) << 14) | (trlPageindex << 7)) | (tullTmp & 0x7f);
3862  dbgWord32(rlPageptr, ZPOS_EMPTY_LIST, tullTmp);
3863  rlPageptr.p->word32[ZPOS_EMPTY_LIST] = tullTmp;
3864  dbgWord32(rlPageptr, ZPOS_ALLOC_CONTAINERS, rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] - 1);
3865  rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] = rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] - 1;
3866  ndbrequire(rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] <= ZNIL);
3867  if (((rlPageptr.p->word32[ZPOS_EMPTY_LIST] >> ZPOS_PAGE_TYPE_BIT) & 3) == 1) {
3868  jam();
3869  colPageptr.i = rlPageptr.i;
3870  colPageptr.p = rlPageptr.p;
3871  ptrCheck(colPageptr, cpagesize, page8);
3872  checkoverfreelist(signal);
3873  }//if
3874 }//Dbacc::releaseLeftlist()
3875 
3876 /* --------------------------------------------------------------------------------- */
3877 /* RELEASE_RIGHTLIST */
3878 /* INPUT: */
3879 /* RL_PAGEPTR PAGE POINTER OF CONTAINER TO BE RELEASED */
3880 /* TRL_PAGEINDEX PAGE INDEX OF CONTAINER TO BE RELEASED */
3881 /* TURL_INDEX INDEX OF CONTAINER TO BE RELEASED */
3882 /* TRL_REL_CON TRUE IF CONTAINER RELEASED OTHERWISE ONLY */
3883 /* A PART IS RELEASED. */
3884 /* */
3885 /* OUTPUT: */
3886 /* NONE */
3887 /* */
3888 /* THE FREE LIST OF RIGHT FREE BUFFER IN THE PAGE WILL BE UPDATE. */
3889 /* TURL_INDEX IS INDEX TO THE FIRST WORD IN THE RIGHT SIDE OF */
3890 /* THE BUFFER, WHICH IS THE LAST WORD IN THE BUFFER. */
3891 /* --------------------------------------------------------------------------------- */
3892 void Dbacc::releaseRightlist(Signal* signal)
3893 {
3894  Uint32 turlTmp1;
3895  Uint32 turlTmp;
3896 
3897  /* --------------------------------------------------------------------------------- */
3898  /* IF A CONTAINER IS RELEASED AND NOT ONLY A PART THEN WE HAVE TO REMOVE IT */
3899  /* FROM THE LIST OF USED CONTAINERS IN THE PAGE. THIS IN ORDER TO ENSURE THAT */
3900  /* WE CAN FIND ALL LOCKED ELEMENTS DURING LOCAL CHECKPOINT. */
3901  /* --------------------------------------------------------------------------------- */
3902  if (trlRelCon == ZTRUE) {
3903  jam();
3904  arrGuard(turlIndex, 2048);
3905  trlHead = rlPageptr.p->word32[turlIndex];
3906  trlNextused = (trlHead >> 11) & 0x7f;
3907  trlPrevused = (trlHead >> 18) & 0x7f;
3908  if (trlNextused < ZEMPTYLIST) {
3909  jam();
3910  turlTmp1 = (trlNextused << ZSHIFT_PLUS) - (trlNextused << ZSHIFT_MINUS);
3911  turlTmp1 = turlTmp1 + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
3912  turlTmp = rlPageptr.p->word32[turlTmp1] & 0xfe03ffff;
3913  dbgWord32(rlPageptr, turlTmp1, turlTmp | (trlPrevused << 18));
3914  rlPageptr.p->word32[turlTmp1] = turlTmp | (trlPrevused << 18);
3915  } else {
3916  ndbrequire(trlNextused == ZEMPTYLIST);
3917  jam();
3918  }//if
3919  if (trlPrevused < ZEMPTYLIST) {
3920  jam();
3921  turlTmp1 = (trlPrevused << ZSHIFT_PLUS) - (trlPrevused << ZSHIFT_MINUS);
3922  turlTmp1 = turlTmp1 + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
3923  turlTmp = rlPageptr.p->word32[turlTmp1] & 0xfffc07ff;
3924  dbgWord32(rlPageptr, turlTmp1, turlTmp | (trlNextused << 11));
3925  rlPageptr.p->word32[turlTmp1] = turlTmp | (trlNextused << 11);
3926  } else {
3927  ndbrequire(trlPrevused == ZEMPTYLIST);
3928  jam();
3929  /* --------------------------------------------------------------------------------- */
3930  /* WE ARE FIRST IN THE LIST AND THUS WE NEED TO UPDATE THE FIRST POINTER */
3931  /* OF THE RIGHT CONTAINER LIST. */
3932  /* --------------------------------------------------------------------------------- */
3933  turlTmp = rlPageptr.p->word32[ZPOS_EMPTY_LIST] & 0xff80ffff;
3934  dbgWord32(rlPageptr, ZPOS_EMPTY_LIST, turlTmp | (trlNextused << 16));
3935  rlPageptr.p->word32[ZPOS_EMPTY_LIST] = turlTmp | (trlNextused << 16);
3936  }//if
3937  }//if
3938  dbgWord32(rlPageptr, turlIndex + 1, ZEMPTYLIST);
3939  arrGuard(turlIndex + 1, 2048);
3940  rlPageptr.p->word32[turlIndex + 1] = ZEMPTYLIST;
3941  turlTmp1 = rlPageptr.p->word32[ZPOS_EMPTY_LIST] & 0x7f;
3942  dbgWord32(rlPageptr, turlIndex, turlTmp1);
3943  arrGuard(turlIndex, 2048);
3944  rlPageptr.p->word32[turlIndex] = turlTmp1;
3945  if (turlTmp1 < ZEMPTYLIST) {
3946  jam();
3947  turlTmp = (turlTmp1 << ZSHIFT_PLUS) - (turlTmp1 << ZSHIFT_MINUS);
3948  turlTmp = turlTmp + ((ZHEAD_SIZE + ZBUF_SIZE) - (ZCON_HEAD_SIZE - 1));
3949  dbgWord32(rlPageptr, turlTmp, trlPageindex);
3950  rlPageptr.p->word32[turlTmp] = trlPageindex; /* UPDATES PREV POINTER IN THE NEXT FREE */
3951  } else {
3952  ndbrequire(turlTmp1 == ZEMPTYLIST);
3953  }//if
3954  turlTmp = rlPageptr.p->word32[ZPOS_EMPTY_LIST];
3955  dbgWord32(rlPageptr, ZPOS_EMPTY_LIST, ((turlTmp >> 7) << 7) | trlPageindex);
3956  rlPageptr.p->word32[ZPOS_EMPTY_LIST] = ((turlTmp >> 7) << 7) | trlPageindex;
3957  dbgWord32(rlPageptr, ZPOS_ALLOC_CONTAINERS, rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] - 1);
3958  rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] = rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] - 1;
3959  ndbrequire(rlPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] <= ZNIL);
3960  if (((rlPageptr.p->word32[ZPOS_EMPTY_LIST] >> ZPOS_PAGE_TYPE_BIT) & 3) == 1) {
3961  jam();
3962  colPageptr.i = rlPageptr.i;
3963  colPageptr.p = rlPageptr.p;
3964  checkoverfreelist(signal);
3965  }//if
3966 }//Dbacc::releaseRightlist()
3967 
3968 /* --------------------------------------------------------------------------------- */
3969 /* CHECKOVERFREELIST */
3970 /* INPUT: COL_PAGEPTR, POINTER OF AN OVERFLOW PAGE RECORD. */
3971 /* DESCRIPTION: CHECKS IF THE PAGE HAVE TO PUT IN FREE LIST OF OVER FLOW */
3972 /* PAGES. WHEN IT HAVE TO, AN OVERFLOW REC PTR WILL BE ALLOCATED */
3973 /* TO KEEP NFORMATION ABOUT THE PAGE. */
3974 /* --------------------------------------------------------------------------------- */
3975 void Dbacc::checkoverfreelist(Signal* signal)
3976 {
3977  Uint32 tcolTmp;
3978 
3979  tcolTmp = colPageptr.p->word32[ZPOS_ALLOC_CONTAINERS];
3980  if (tcolTmp <= ZFREE_LIMIT) {
3981  if (tcolTmp == 0) {
3982  jam();
3983  ropPageptr = colPageptr;
3984  releaseOverpage(signal);
3985  } else {
3986  jam();
3987  if (colPageptr.p->word32[ZPOS_OVERFLOWREC] == RNIL) {
3988  ndbrequire(cfirstfreeoverrec != RNIL);
3989  jam();
3990  seizeOverRec(signal);
3991  sorOverflowRecPtr.p->dirindex = colPageptr.p->word32[ZPOS_PAGE_ID];
3992  sorOverflowRecPtr.p->overpage = colPageptr.i;
3993  dbgWord32(colPageptr, ZPOS_OVERFLOWREC, sorOverflowRecPtr.i);
3994  colPageptr.p->word32[ZPOS_OVERFLOWREC] = sorOverflowRecPtr.i;
3995  porOverflowRecPtr = sorOverflowRecPtr;
3996  putOverflowRecInFrag(signal);
3997  }//if
3998  }//if
3999  }//if
4000 }//Dbacc::checkoverfreelist()
4001 
4002 /* ------------------------------------------------------------------------- */
4003 /* ------------------------------------------------------------------------- */
4004 /* ------------------------------------------------------------------------- */
4005 /* */
4006 /* END OF DELETE MODULE */
4007 /* */
4008 /* ------------------------------------------------------------------------- */
4009 /* ------------------------------------------------------------------------- */
4010 /* ------------------------------------------------------------------------- */
4011 /* ------------------------------------------------------------------------- */
4012 /* ------------------------------------------------------------------------- */
4013 /* ------------------------------------------------------------------------- */
4014 /* */
4015 /* COMMIT AND ABORT MODULE */
4016 /* */
4017 /* ------------------------------------------------------------------------- */
4018 /* ------------------------------------------------------------------------- */
4019 /* ------------------------------------------------------------------------- */
4020 /* ------------------------------------------------------------------------- */
4021 /* ABORT_OPERATION */
4022 /*DESCRIPTION: AN OPERATION RECORD CAN BE IN A LOCK QUEUE OF AN ELEMENT OR */
4023 /*OWNS THE LOCK. BY THIS SUBROUTINE THE LOCK STATE OF THE OPERATION WILL */
4024 /*BE CHECKED. THE OPERATION RECORD WILL BE REMOVED FROM THE QUEUE IF IT */
4025 /*BELONGED TO ANY ONE, OTHERWISE THE ELEMENT HEAD WILL BE UPDATED. */
4026 /* ------------------------------------------------------------------------- */
4027 
4035 void
4036 Dbacc::abortParallelQueueOperation(Signal* signal, OperationrecPtr opPtr)
4037 {
4038  jam();
4039  OperationrecPtr nextP;
4040  OperationrecPtr prevP;
4041  OperationrecPtr loPtr;
4042 
4043  Uint32 opbits = opPtr.p->m_op_bits;
4044  Uint32 opstate = opbits & Operationrec::OP_STATE_MASK;
4045  nextP.i = opPtr.p->nextParallelQue;
4046  prevP.i = opPtr.p->prevParallelQue;
4047  loPtr.i = opPtr.p->m_lock_owner_ptr_i;
4048 
4049  ndbassert(! (opbits & Operationrec::OP_LOCK_OWNER));
4050  ndbassert(opbits & Operationrec::OP_RUN_QUEUE);
4051 
4052  ptrCheckGuard(prevP, coprecsize, operationrec);
4053  ndbassert(prevP.p->nextParallelQue == opPtr.i);
4054  prevP.p->nextParallelQue = nextP.i;
4055 
4056  if (nextP.i != RNIL)
4057  {
4058  ptrCheckGuard(nextP, coprecsize, operationrec);
4059  ndbassert(nextP.p->prevParallelQue == opPtr.i);
4060  nextP.p->prevParallelQue = prevP.i;
4061  }
4062  else if (prevP.i != loPtr.i)
4063  {
4064  jam();
4065  ptrCheckGuard(loPtr, coprecsize, operationrec);
4066  ndbassert(loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
4067  ndbassert(loPtr.p->m_lo_last_parallel_op_ptr_i == opPtr.i);
4068  loPtr.p->m_lo_last_parallel_op_ptr_i = prevP.i;
4069  prevP.p->m_lock_owner_ptr_i = loPtr.i;
4070 
4074  startNext(signal, prevP);
4075  validate_lock_queue(prevP);
4076  return;
4077  }
4078  else
4079  {
4080  jam();
4086  ndbassert(prevP.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
4087  prevP.p->m_lo_last_parallel_op_ptr_i = RNIL;
4088  startNext(signal, prevP);
4089  validate_lock_queue(prevP);
4090  return;
4091  }
4092 
4096  if (opbits & Operationrec::OP_LOCK_MODE)
4097  {
4098  Uint32 nextbits = nextP.p->m_op_bits;
4099  while ((nextbits & Operationrec::OP_LOCK_MODE) == 0)
4100  {
4101  ndbassert(nextbits & Operationrec::OP_ACC_LOCK_MODE);
4102  nextbits &= ~(Uint32)Operationrec::OP_ACC_LOCK_MODE;
4103  nextP.p->m_op_bits = nextbits;
4104 
4105  if (nextP.p->nextParallelQue != RNIL)
4106  {
4107  nextP.i = nextP.p->nextParallelQue;
4108  ptrCheckGuard(nextP, coprecsize, operationrec);
4109  nextbits = nextP.p->m_op_bits;
4110  }
4111  else
4112  {
4113  break;
4114  }
4115  }
4116  }
4117 
4121  if (opstate == Operationrec::OP_STATE_RUNNING)
4122  {
4123  jam();
4124  startNext(signal, prevP);
4125  validate_lock_queue(prevP);
4126  return;
4127  }
4128 
4129  ndbassert(opstate == Operationrec::OP_STATE_EXECUTED ||
4130  opstate == Operationrec::OP_STATE_WAITING);
4131 
4135  while (nextP.p->nextParallelQue != RNIL)
4136  {
4137  jam();
4138  nextP.i = nextP.p->nextParallelQue;
4139  ptrCheckGuard(nextP, coprecsize, operationrec);
4140  }
4141 
4142 #ifdef VM_TRACE
4143  loPtr.i = nextP.p->m_lock_owner_ptr_i;
4144  ptrCheckGuard(loPtr, coprecsize, operationrec);
4145  ndbassert(loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
4146  ndbassert(loPtr.p->m_lo_last_parallel_op_ptr_i == nextP.i);
4147 #endif
4148  startNext(signal, nextP);
4149  validate_lock_queue(nextP);
4150 
4151  return;
4152 }
4153 
4154 void
4155 Dbacc::abortSerieQueueOperation(Signal* signal, OperationrecPtr opPtr)
4156 {
4157  jam();
4158  OperationrecPtr prevS, nextS;
4159  OperationrecPtr prevP, nextP;
4160  OperationrecPtr loPtr;
4161 
4162  Uint32 opbits = opPtr.p->m_op_bits;
4163 
4164  prevS.i = opPtr.p->prevSerialQue;
4165  nextS.i = opPtr.p->nextSerialQue;
4166 
4167  prevP.i = opPtr.p->prevParallelQue;
4168  nextP.i = opPtr.p->nextParallelQue;
4169 
4170  ndbassert((opbits & Operationrec::OP_LOCK_OWNER) == 0);
4171  ndbassert((opbits & Operationrec::OP_RUN_QUEUE) == 0);
4172 
4173  if (prevP.i != RNIL)
4174  {
4178  ptrCheckGuard(prevP, coprecsize, operationrec);
4179  ndbassert(prevP.p->nextParallelQue == opPtr.i);
4180  prevP.p->nextParallelQue = nextP.i;
4181 
4182  if (nextP.i != RNIL)
4183  {
4184  ptrCheckGuard(nextP, coprecsize, operationrec);
4185  ndbassert(nextP.p->prevParallelQue == opPtr.i);
4186  ndbassert((nextP.p->m_op_bits & Operationrec::OP_STATE_MASK) ==
4187  Operationrec::OP_STATE_WAITING);
4188  nextP.p->prevParallelQue = prevP.i;
4189 
4190  if ((prevP.p->m_op_bits & Operationrec::OP_ACC_LOCK_MODE) == 0 &&
4191  opbits & Operationrec::OP_LOCK_MODE)
4192  {
4196  while ((nextP.p->m_op_bits & Operationrec::OP_LOCK_MODE) == 0)
4197  {
4198  ndbassert(nextP.p->m_op_bits & Operationrec::OP_ACC_LOCK_MODE);
4199  nextP.p->m_op_bits &= ~(Uint32)Operationrec::OP_ACC_LOCK_MODE;
4200  nextP.i = nextP.p->nextParallelQue;
4201  if (nextP.i == RNIL)
4202  break;
4203  ptrCheckGuard(nextP, coprecsize, operationrec);
4204  }
4205  }
4206  }
4207  validate_lock_queue(prevP);
4208  return;
4209  }
4210  else
4211  {
4215  ptrCheckGuard(prevS, coprecsize, operationrec);
4216  ndbassert(prevS.p->nextSerialQue == opPtr.i);
4217 
4218  if (nextP.i != RNIL)
4219  {
4223  ptrCheckGuard(nextP, coprecsize, operationrec);
4224  ndbassert(nextP.p->prevParallelQue == opPtr.i);
4225  prevS.p->nextSerialQue = nextP.i;
4226  nextP.p->prevParallelQue = RNIL;
4227  nextP.p->nextSerialQue = nextS.i;
4228  if (nextS.i != RNIL)
4229  {
4230  jam();
4231  ptrCheckGuard(nextS, coprecsize, operationrec);
4232  ndbassert(nextS.p->prevSerialQue == opPtr.i);
4233  nextS.p->prevSerialQue = nextP.i;
4234  validate_lock_queue(prevS);
4235  return;
4236  }
4237  else
4238  {
4239  // nextS is RNIL, i.e we're last in serie queue...
4240  // we must update lockOwner.m_lo_last_serial_op_ptr_i
4241  loPtr = prevS;
4242  while ((loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0)
4243  {
4244  loPtr.i = loPtr.p->prevSerialQue;
4245  ptrCheckGuard(loPtr, coprecsize, operationrec);
4246  }
4247  ndbassert(loPtr.p->m_lo_last_serial_op_ptr_i == opPtr.i);
4248  loPtr.p->m_lo_last_serial_op_ptr_i = nextP.i;
4249  validate_lock_queue(loPtr);
4250  return;
4251  }
4252  }
4253 
4254  if (nextS.i == RNIL)
4255  {
4260  // nextS is RNIL, i.e we're last in serie queue...
4261  // and we have no parallel queue,
4262  // we must update lockOwner.m_lo_last_serial_op_ptr_i
4263  prevS.p->nextSerialQue = RNIL;
4264 
4265  loPtr = prevS;
4266  while ((loPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) == 0)
4267  {
4268  loPtr.i = loPtr.p->prevSerialQue;
4269  ptrCheckGuard(loPtr, coprecsize, operationrec);
4270  }
4271  ndbassert(loPtr.p->m_lo_last_serial_op_ptr_i == opPtr.i);
4272  if (prevS.i != loPtr.i)
4273  {
4274  jam();
4275  loPtr.p->m_lo_last_serial_op_ptr_i = prevS.i;
4276  }
4277  else
4278  {
4279  loPtr.p->m_lo_last_serial_op_ptr_i = RNIL;
4280  }
4281  validate_lock_queue(loPtr);
4282  }
4283  else if (nextP.i == RNIL)
4284  {
4285  ptrCheckGuard(nextS, coprecsize, operationrec);
4286  ndbassert(nextS.p->prevSerialQue == opPtr.i);
4287  prevS.p->nextSerialQue = nextS.i;
4288  nextS.p->prevSerialQue = prevS.i;
4289 
4290  if (prevS.p->m_op_bits & Operationrec::OP_LOCK_OWNER)
4291  {
4295  OperationrecPtr lastOp;
4296  lastOp.i = prevS.p->m_lo_last_parallel_op_ptr_i;
4297  if (lastOp.i != RNIL)
4298  {
4299  jam();
4300  ptrCheckGuard(lastOp, coprecsize, operationrec);
4301  ndbassert(lastOp.p->m_lock_owner_ptr_i == prevS.i);
4302  }
4303  else
4304  {
4305  jam();
4306  lastOp = prevS;
4307  }
4308  startNext(signal, lastOp);
4309  validate_lock_queue(lastOp);
4310  }
4311  else
4312  {
4313  validate_lock_queue(prevS);
4314  }
4315  }
4316  }
4317 }
4318 
4319 
4320 void Dbacc::abortOperation(Signal* signal)
4321 {
4322  Uint32 opbits = operationRecPtr.p->m_op_bits;
4323 
4324  validate_lock_queue(operationRecPtr);
4325 
4326  if (opbits & Operationrec::OP_LOCK_OWNER)
4327  {
4328  takeOutLockOwnersList(signal, operationRecPtr);
4329  opbits &= ~(Uint32)Operationrec::OP_LOCK_OWNER;
4330  if (opbits & Operationrec::OP_INSERT_IS_DONE)
4331  {
4332  jam();
4333  opbits |= Operationrec::OP_ELEMENT_DISAPPEARED;
4334  }//if
4335  operationRecPtr.p->m_op_bits = opbits;
4336  const bool queue = (operationRecPtr.p->nextParallelQue != RNIL ||
4337  operationRecPtr.p->nextSerialQue != RNIL);
4338 
4339  if (queue)
4340  {
4341  jam();
4342  release_lockowner(signal, operationRecPtr, false);
4343  }
4344  else
4345  {
4346  /* -------------------------------------------------------------------
4347  * WE ARE OWNER OF THE LOCK AND NO OTHER OPERATIONS ARE QUEUED.
4348  * IF INSERT OR STANDBY WE DELETE THE ELEMENT OTHERWISE WE REMOVE
4349  * THE LOCK FROM THE ELEMENT.
4350  * ------------------------------------------------------------------ */
4351  if ((opbits & Operationrec::OP_ELEMENT_DISAPPEARED) == 0)
4352  {
4353  jam();
4354  Page8Ptr aboPageidptr;
4355  Uint32 taboElementptr;
4356  Uint32 tmp2Olq;
4357 
4358  taboElementptr = operationRecPtr.p->elementPointer;
4359  aboPageidptr.i = operationRecPtr.p->elementPage;
4360  tmp2Olq = ElementHeader::setUnlocked(operationRecPtr.p->hashvaluePart,
4361  operationRecPtr.p->scanBits);
4362  ptrCheckGuard(aboPageidptr, cpagesize, page8);
4363  dbgWord32(aboPageidptr, taboElementptr, tmp2Olq);
4364  arrGuard(taboElementptr, 2048);
4365  aboPageidptr.p->word32[taboElementptr] = tmp2Olq;
4366  return;
4367  }
4368  else
4369  {
4370  jam();
4371  commitdelete(signal);
4372  }//if
4373  }//if
4374  }
4375  else if (opbits & Operationrec::OP_RUN_QUEUE)
4376  {
4377  abortParallelQueueOperation(signal, operationRecPtr);
4378  }
4379  else
4380  {
4381  abortSerieQueueOperation(signal, operationRecPtr);
4382  }
4383 }
4384 
4385 void
4386 Dbacc::commitDeleteCheck()
4387 {
4388  OperationrecPtr opPtr;
4389  OperationrecPtr lastOpPtr;
4390  OperationrecPtr deleteOpPtr;
4391  Uint32 elementDeleted = 0;
4392  bool deleteCheckOngoing = true;
4393  Uint32 hashValue = 0;
4394  lastOpPtr = operationRecPtr;
4395  opPtr.i = operationRecPtr.p->nextParallelQue;
4396  while (opPtr.i != RNIL) {
4397  jam();
4398  ptrCheckGuard(opPtr, coprecsize, operationrec);
4399  lastOpPtr = opPtr;
4400  opPtr.i = opPtr.p->nextParallelQue;
4401  }//while
4402  deleteOpPtr = lastOpPtr;
4403  do {
4404  Uint32 opbits = deleteOpPtr.p->m_op_bits;
4405  Uint32 op = opbits & Operationrec::OP_MASK;
4406  if (op == ZDELETE) {
4407  jam();
4408  /* -------------------------------------------------------------------
4409  * IF THE CURRENT OPERATION TO BE COMMITTED IS A DELETE OPERATION DUE TO
4410  * A SCAN-TAKEOVER THE ACTUAL DELETE WILL BE PERFORMED BY THE PREVIOUS
4411  * OPERATION (SCAN) IN THE PARALLEL QUEUE WHICH OWNS THE LOCK.
4412  * THE PROBLEM IS THAT THE SCAN OPERATION DOES NOT HAVE A HASH VALUE
4413  * ASSIGNED TO IT SO WE COPY IT FROM THIS OPERATION.
4414  *
4415  * WE ASSUME THAT THIS SOLUTION WILL WORK BECAUSE THE ONLY WAY A
4416  * SCAN CAN PERFORM A DELETE IS BY BEING FOLLOWED BY A NORMAL
4417  * DELETE-OPERATION THAT HAS A HASH VALUE.
4418  * ----------------------------------------------------------------- */
4419  hashValue = deleteOpPtr.p->hashValue;
4420  elementDeleted = Operationrec::OP_ELEMENT_DISAPPEARED;
4421  deleteCheckOngoing = false;
4422  } else if (op == ZREAD || op == ZSCAN_OP) {
4423  /* -------------------------------------------------------------------
4424  * We are trying to find out whether the commit will in the end delete
4425  * the tuple. Normally the delete will be the last operation in the
4426  * list of operations on this. It is however possible to issue reads
4427  * and scans in the same savepoint as the delete operation was issued
4428  * and these can end up after the delete in the list of operations
4429  * in the parallel queue. Thus if we discover a read or a scan
4430  * we have to continue scanning the list looking for a delete operation.
4431  */
4432  deleteOpPtr.i = deleteOpPtr.p->prevParallelQue;
4433  if (opbits & Operationrec::OP_LOCK_OWNER) {
4434  jam();
4435  deleteCheckOngoing = false;
4436  } else {
4437  jam();
4438  ptrCheckGuard(deleteOpPtr, coprecsize, operationrec);
4439  }//if
4440  } else {
4441  jam();
4442  /* ------------------------------------------------------------------ */
4443  /* Finding an UPDATE or INSERT before finding a DELETE
4444  * means we cannot be deleting as the end result of this transaction.
4445  */
4446  deleteCheckOngoing = false;
4447  }//if
4448  } while (deleteCheckOngoing);
4449  opPtr = lastOpPtr;
4450  do {
4451  jam();
4452  opPtr.p->m_op_bits |= Operationrec::OP_COMMIT_DELETE_CHECK;
4453  if (elementDeleted) {
4454  jam();
4455  opPtr.p->m_op_bits |= elementDeleted;
4456  opPtr.p->hashValue = hashValue;
4457  }//if
4458  opPtr.i = opPtr.p->prevParallelQue;
4459  if (opPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER) {
4460  jam();
4461  break;
4462  }//if
4463  ptrCheckGuard(opPtr, coprecsize, operationrec);
4464  } while (true);
4465 }//Dbacc::commitDeleteCheck()
4466 
4467 /* ------------------------------------------------------------------------- */
4468 /* COMMIT_OPERATION */
4469 /* INPUT: OPERATION_REC_PTR, POINTER TO AN OPERATION RECORD */
4470 /* DESCRIPTION: THE OPERATION RECORD WILL BE TAKE OUT OF ANY LOCK QUEUE. */
4471 /* IF IT OWNS THE ELEMENT LOCK. HEAD OF THE ELEMENT WILL BE UPDATED. */
4472 /* ------------------------------------------------------------------------- */
4473 void Dbacc::commitOperation(Signal* signal)
4474 {
4475  validate_lock_queue(operationRecPtr);
4476 
4477  Uint32 opbits = operationRecPtr.p->m_op_bits;
4478  Uint32 op = opbits & Operationrec::OP_MASK;
4479  ndbrequire((opbits & Operationrec::OP_STATE_MASK) == Operationrec::OP_STATE_EXECUTED);
4480  if ((opbits & Operationrec::OP_COMMIT_DELETE_CHECK) == 0 &&
4481  (op != ZREAD && op != ZSCAN_OP))
4482  {
4483  jam();
4484  /* This method is used to check whether the end result of the transaction
4485  will be to delete the tuple. In this case all operation will be marked
4486  with elementIsDisappeared = true to ensure that the last operation
4487  committed will remove the tuple. We only run this once per transaction
4488  (commitDeleteCheckFlag = true if performed earlier) and we don't
4489  execute this code when committing a scan operation since committing
4490  a scan operation only means that the scan is continuing and the scan
4491  lock is released.
4492  */
4493  commitDeleteCheck();
4494  opbits = operationRecPtr.p->m_op_bits;
4495  }//if
4496 
4497  ndbassert(opbits & Operationrec::OP_RUN_QUEUE);
4498 
4499  if (opbits & Operationrec::OP_LOCK_OWNER)
4500  {
4501  takeOutLockOwnersList(signal, operationRecPtr);
4502  opbits &= ~(Uint32)Operationrec::OP_LOCK_OWNER;
4503  operationRecPtr.p->m_op_bits = opbits;
4504 
4505  const bool queue = (operationRecPtr.p->nextParallelQue != RNIL ||
4506  operationRecPtr.p->nextSerialQue != RNIL);
4507 
4508  if (!queue && (opbits & Operationrec::OP_ELEMENT_DISAPPEARED) == 0)
4509  {
4510  /*
4511  * This is the normal path through the commit for operations owning the
4512  * lock without any queues and not a delete operation.
4513  */
4514  Page8Ptr coPageidptr;
4515  Uint32 tcoElementptr;
4516  Uint32 tmp2Olq;
4517 
4518  coPageidptr.i = operationRecPtr.p->elementPage;
4519  tcoElementptr = operationRecPtr.p->elementPointer;
4520  tmp2Olq = ElementHeader::setUnlocked(operationRecPtr.p->hashvaluePart,
4521  operationRecPtr.p->scanBits);
4522  ptrCheckGuard(coPageidptr, cpagesize, page8);
4523  dbgWord32(coPageidptr, tcoElementptr, tmp2Olq);
4524  arrGuard(tcoElementptr, 2048);
4525  coPageidptr.p->word32[tcoElementptr] = tmp2Olq;
4526  return;
4527  }
4528  else if (queue)
4529  {
4530  jam();
4531  /*
4532  * The case when there is a queue lined up.
4533  * Release the lock and pass it to the next operation lined up.
4534  */
4535  release_lockowner(signal, operationRecPtr, true);
4536  return;
4537  }
4538  else
4539  {
4540  jam();
4541  /*
4542  * No queue and elementIsDisappeared is true.
4543  * We perform the actual delete operation.
4544  */
4545  commitdelete(signal);
4546  return;
4547  }//if
4548  }
4549  else
4550  {
4555  jam();
4556  OperationrecPtr prev, next, lockOwner;
4557  prev.i = operationRecPtr.p->prevParallelQue;
4558  next.i = operationRecPtr.p->nextParallelQue;
4559  lockOwner.i = operationRecPtr.p->m_lock_owner_ptr_i;
4560  ptrCheckGuard(prev, coprecsize, operationrec);
4561 
4562  prev.p->nextParallelQue = next.i;
4563  if (next.i != RNIL)
4564  {
4565  jam();
4566  ptrCheckGuard(next, coprecsize, operationrec);
4567  next.p->prevParallelQue = prev.i;
4568  }
4569  else if (prev.p->m_op_bits & Operationrec::OP_LOCK_OWNER)
4570  {
4571  jam();
4572  ndbassert(lockOwner.i == prev.i);
4573  prev.p->m_lo_last_parallel_op_ptr_i = RNIL;
4574  next = prev;
4575  }
4576  else
4577  {
4578  jam();
4582  ndbassert(prev.i != lockOwner.i);
4583  ptrCheckGuard(lockOwner, coprecsize, operationrec);
4584  ndbassert(lockOwner.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
4585  lockOwner.p->m_lo_last_parallel_op_ptr_i = prev.i;
4586  prev.p->m_lock_owner_ptr_i = lockOwner.i;
4587  next = prev;
4588  }
4589 
4593  if(opbits & Operationrec::OP_ACC_LOCK_MODE)
4594  {
4595  jam();
4596 
4614  validate_lock_queue(prev);
4615  return;
4616  }
4617 
4622  while(next.p->nextParallelQue != RNIL)
4623  {
4624  jam();
4625  next.i = next.p->nextParallelQue;
4626  ptrCheckGuard(next, coprecsize, operationrec);
4627 
4628  if ((next.p->m_op_bits & Operationrec::OP_STATE_MASK) !=
4629  Operationrec::OP_STATE_EXECUTED)
4630  {
4631  jam();
4632  return;
4633  }
4634  }
4635 
4636  startNext(signal, next);
4637 
4638  validate_lock_queue(prev);
4639  }
4640 }//Dbacc::commitOperation()
4641 
4642 void
4643 Dbacc::release_lockowner(Signal* signal, OperationrecPtr opPtr, bool commit)
4644 {
4645  OperationrecPtr nextP;
4646  OperationrecPtr nextS;
4647  OperationrecPtr newOwner;
4648  OperationrecPtr lastP;
4649 
4650  Uint32 opbits = opPtr.p->m_op_bits;
4651  nextP.i = opPtr.p->nextParallelQue;
4652  nextS.i = opPtr.p->nextSerialQue;
4653  lastP.i = opPtr.p->m_lo_last_parallel_op_ptr_i;
4654  Uint32 lastS = opPtr.p->m_lo_last_serial_op_ptr_i;
4655 
4656  ndbassert(lastP.i != RNIL || lastS != RNIL);
4657  ndbassert(nextP.i != RNIL || nextS.i != RNIL);
4658 
4659  enum {
4660  NOTHING,
4661  CHECK_LOCK_UPGRADE,
4662  START_NEW
4663  } action = NOTHING;
4664 
4665  if (nextP.i != RNIL)
4666  {
4667  jam();
4668  ptrCheckGuard(nextP, coprecsize, operationrec);
4669  newOwner = nextP;
4670 
4671  if (lastP.i == newOwner.i)
4672  {
4673  newOwner.p->m_lo_last_parallel_op_ptr_i = RNIL;
4674  lastP = nextP;
4675  }
4676  else
4677  {
4678  ptrCheckGuard(lastP, coprecsize, operationrec);
4679  newOwner.p->m_lo_last_parallel_op_ptr_i = lastP.i;
4680  lastP.p->m_lock_owner_ptr_i = newOwner.i;
4681  }
4682 
4683  newOwner.p->m_lo_last_serial_op_ptr_i = lastS;
4684  newOwner.p->nextSerialQue = nextS.i;
4685 
4686  if (nextS.i != RNIL)
4687  {
4688  jam();
4689  ptrCheckGuard(nextS, coprecsize, operationrec);
4690  ndbassert(nextS.p->prevSerialQue == opPtr.i);
4691  nextS.p->prevSerialQue = newOwner.i;
4692  }
4693 
4694  if (commit)
4695  {
4696  if ((opbits & Operationrec::OP_ACC_LOCK_MODE) == ZREADLOCK)
4697  {
4698  jam();
4716  action = CHECK_LOCK_UPGRADE;
4717  }
4718  else
4719  {
4720  jam();
4721  newOwner.p->m_op_bits |= Operationrec::OP_LOCK_MODE;
4722  }
4723  }
4724  else
4725  {
4729  action = CHECK_LOCK_UPGRADE;
4730  Uint32 opstate = opbits & Operationrec::OP_STATE_MASK;
4731  if (opstate != Operationrec::OP_STATE_EXECUTED)
4732  {
4733  ndbassert(opstate == Operationrec::OP_STATE_RUNNING);
4734  if (opbits & Operationrec::OP_ELEMENT_DISAPPEARED)
4735  {
4736  jam();
4737  report_dealloc(signal, opPtr.p);
4738  newOwner.p->localdata[0] = ~(Uint32)0;
4739  newOwner.p->localdata[1] = ~(Uint32)0;
4740  }
4741  else
4742  {
4743  jam();
4744  newOwner.p->localdata[0] = opPtr.p->localdata[0];
4745  newOwner.p->localdata[1] = opPtr.p->localdata[1];
4746  }
4747  action = START_NEW;
4748  }
4749 
4753  if (opbits & Operationrec::OP_LOCK_MODE)
4754  {
4755  Uint32 nextbits = nextP.p->m_op_bits;
4756  while ((nextbits & Operationrec::OP_LOCK_MODE) == 0)
4757  {
4758  ndbassert(nextbits & Operationrec::OP_ACC_LOCK_MODE);
4759  nextbits &= ~(Uint32)Operationrec::OP_ACC_LOCK_MODE;
4760  nextP.p->m_op_bits = nextbits;
4761 
4762  if (nextP.p->nextParallelQue != RNIL)
4763  {
4764  nextP.i = nextP.p->nextParallelQue;
4765  ptrCheckGuard(nextP, coprecsize, operationrec);
4766  nextbits = nextP.p->m_op_bits;
4767  }
4768  else
4769  {
4770  break;
4771  }
4772  }
4773  }
4774  }
4775  }
4776  else
4777  {
4778  jam();
4779  ptrCheckGuard(nextS, coprecsize, operationrec);
4780  newOwner = nextS;
4781 
4782  newOwner.p->m_op_bits |= Operationrec::OP_RUN_QUEUE;
4783 
4784  if (opbits & Operationrec::OP_ELEMENT_DISAPPEARED)
4785  {
4786  report_dealloc(signal, opPtr.p);
4787  newOwner.p->localdata[0] = ~(Uint32)0;
4788  newOwner.p->localdata[1] = ~(Uint32)0;
4789  }
4790  else
4791  {
4792  jam();
4793  newOwner.p->localdata[0] = opPtr.p->localdata[0];
4794  newOwner.p->localdata[1] = opPtr.p->localdata[1];
4795  }
4796 
4797  lastP = newOwner;
4798  while (lastP.p->nextParallelQue != RNIL)
4799  {
4800  lastP.i = lastP.p->nextParallelQue;
4801  ptrCheckGuard(lastP, coprecsize, operationrec);
4802  lastP.p->m_op_bits |= Operationrec::OP_RUN_QUEUE;
4803  }
4804 
4805  if (newOwner.i != lastP.i)
4806  {
4807  jam();
4808  newOwner.p->m_lo_last_parallel_op_ptr_i = lastP.i;
4809  }
4810  else
4811  {
4812  jam();
4813  newOwner.p->m_lo_last_parallel_op_ptr_i = RNIL;
4814  }
4815 
4816  if (newOwner.i != lastS)
4817  {
4818  jam();
4819  newOwner.p->m_lo_last_serial_op_ptr_i = lastS;
4820  }
4821  else
4822  {
4823  jam();
4824  newOwner.p->m_lo_last_serial_op_ptr_i = RNIL;
4825  }
4826 
4827  action = START_NEW;
4828  }
4829 
4830  insertLockOwnersList(signal, newOwner);
4831 
4836  {
4837  newOwner.p->elementPage = opPtr.p->elementPage;
4838  newOwner.p->elementIsforward = opPtr.p->elementIsforward;
4839  newOwner.p->elementPointer = opPtr.p->elementPointer;
4840  newOwner.p->elementContainer = opPtr.p->elementContainer;
4841  newOwner.p->scanBits = opPtr.p->scanBits;
4842  newOwner.p->hashvaluePart = opPtr.p->hashvaluePart;
4843  newOwner.p->m_op_bits |= (opbits & Operationrec::OP_ELEMENT_DISAPPEARED);
4844  if (opbits & Operationrec::OP_ELEMENT_DISAPPEARED)
4845  {
4846  /* ------------------------------------------------------------------- */
4847  // If the elementIsDisappeared is set then we know that the
4848  // hashValue is also set since it always originates from a
4849  // committing abort or a aborting insert.
4850  // Scans do not initialise the hashValue and must have this
4851  // value initialised if they are
4852  // to successfully commit the delete.
4853  /* ------------------------------------------------------------------- */
4854  jam();
4855  newOwner.p->hashValue = opPtr.p->hashValue;
4856  }//if
4857 
4858  Page8Ptr pagePtr;
4859  pagePtr.i = newOwner.p->elementPage;
4860  ptrCheckGuard(pagePtr, cpagesize, page8);
4861  const Uint32 tmp = ElementHeader::setLocked(newOwner.i);
4862  arrGuard(newOwner.p->elementPointer, 2048);
4863  pagePtr.p->word32[newOwner.p->elementPointer] = tmp;
4864  }
4865 
4866  switch(action){
4867  case NOTHING:
4868  validate_lock_queue(newOwner);
4869  return;
4870  case START_NEW:
4871  startNew(signal, newOwner);
4872  validate_lock_queue(newOwner);
4873  return;
4874  case CHECK_LOCK_UPGRADE:
4875  startNext(signal, lastP);
4876  validate_lock_queue(lastP);
4877  break;
4878  }
4879 
4880 }
4881 
4882 void
4883 Dbacc::startNew(Signal* signal, OperationrecPtr newOwner)
4884 {
4885  OperationrecPtr save = operationRecPtr;
4886  operationRecPtr = newOwner;
4887 
4888  Uint32 opbits = newOwner.p->m_op_bits;
4889  Uint32 op = opbits & Operationrec::OP_MASK;
4890  Uint32 opstate = (opbits & Operationrec::OP_STATE_MASK);
4891  ndbassert(opstate == Operationrec::OP_STATE_WAITING);
4892  ndbassert(opbits & Operationrec::OP_LOCK_OWNER);
4893  const bool deleted = opbits & Operationrec::OP_ELEMENT_DISAPPEARED;
4894  Uint32 errCode = 0;
4895 
4896  opbits &= opbits & ~(Uint32)Operationrec::OP_STATE_MASK;
4897  opbits |= Operationrec::OP_STATE_RUNNING;
4898 
4899  if (op == ZSCAN_OP && (opbits & Operationrec::OP_LOCK_REQ) == 0)
4900  goto scan;
4901 
4902  if (deleted)
4903  {
4904  jam();
4905  if (op != ZINSERT && op != ZWRITE)
4906  {
4907  errCode = ZREAD_ERROR;
4908  goto ref;
4909  }
4910 
4911  opbits &= ~(Uint32)Operationrec::OP_MASK;
4912  opbits &= ~(Uint32)Operationrec::OP_ELEMENT_DISAPPEARED;
4913  opbits |= (op = ZINSERT);
4914  opbits |= Operationrec::OP_INSERT_IS_DONE;
4915  goto conf;
4916  }
4917  else if (op == ZINSERT)
4918  {
4919  jam();
4920  errCode = ZWRITE_ERROR;
4921  goto ref;
4922  }
4923  else if (op == ZWRITE)
4924  {
4925  jam();
4926  opbits &= ~(Uint32)Operationrec::OP_MASK;
4927  opbits |= (op = ZUPDATE);
4928  goto conf;
4929  }
4930 
4931 conf:
4932  newOwner.p->m_op_bits = opbits;
4933 
4934  sendAcckeyconf(signal);
4935  sendSignal(newOwner.p->userblockref, GSN_ACCKEYCONF,
4936  signal, 6, JBB);
4937 
4938  operationRecPtr = save;
4939  return;
4940 
4941 scan:
4942  jam();
4943  newOwner.p->m_op_bits = opbits;
4944 
4945  takeOutScanLockQueue(newOwner.p->scanRecPtr);
4946  putReadyScanQueue(signal, newOwner.p->scanRecPtr);
4947 
4948  operationRecPtr = save;
4949  return;
4950 
4951 ref:
4952  newOwner.p->m_op_bits = opbits;
4953 
4954  signal->theData[0] = newOwner.p->userptr;
4955  signal->theData[1] = errCode;
4956  sendSignal(newOwner.p->userblockref, GSN_ACCKEYREF, signal,
4957  2, JBB);
4958 
4959  operationRecPtr = save;
4960  return;
4961 }
4962 
4970 void Dbacc::takeOutLockOwnersList(Signal* signal,
4971  const OperationrecPtr& outOperPtr)
4972 {
4973  const Uint32 Tprev = outOperPtr.p->prevLockOwnerOp;
4974  const Uint32 Tnext = outOperPtr.p->nextLockOwnerOp;
4975 #ifdef VM_TRACE
4976  // Check that operation is already in the list
4977  OperationrecPtr tmpOperPtr;
4978  bool inList = false;
4979  tmpOperPtr.i = fragrecptr.p->lockOwnersList;
4980  while (tmpOperPtr.i != RNIL){
4981  ptrCheckGuard(tmpOperPtr, coprecsize, operationrec);
4982  if (tmpOperPtr.i == outOperPtr.i)
4983  inList = true;
4984  tmpOperPtr.i = tmpOperPtr.p->nextLockOwnerOp;
4985  }
4986  ndbrequire(inList == true);
4987 #endif
4988 
4989  ndbassert(outOperPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER);
4990 
4991  // Fast path through the code for the common case.
4992  if ((Tprev == RNIL) && (Tnext == RNIL)) {
4993  ndbrequire(fragrecptr.p->lockOwnersList == outOperPtr.i);
4994  fragrecptr.p->lockOwnersList = RNIL;
4995  return;
4996  }
4997 
4998  // Check previous operation
4999  if (Tprev != RNIL) {
5000  jam();
5001  arrGuard(Tprev, coprecsize);
5002  operationrec[Tprev].nextLockOwnerOp = Tnext;
5003  } else {
5004  fragrecptr.p->lockOwnersList = Tnext;
5005  }//if
5006 
5007  // Check next operation
5008  if (Tnext == RNIL) {
5009  return;
5010  } else {
5011  jam();
5012  arrGuard(Tnext, coprecsize);
5013  operationrec[Tnext].prevLockOwnerOp = Tprev;
5014  }//if
5015 
5016  return;
5017 }//Dbacc::takeOutLockOwnersList()
5018 
5026 void Dbacc::insertLockOwnersList(Signal* signal,
5027  const OperationrecPtr& insOperPtr)
5028 {
5029  OperationrecPtr tmpOperPtr;
5030 #ifdef VM_TRACE
5031  // Check that operation is not already in list
5032  tmpOperPtr.i = fragrecptr.p->lockOwnersList;
5033  while(tmpOperPtr.i != RNIL){
5034  ptrCheckGuard(tmpOperPtr, coprecsize, operationrec);
5035  ndbrequire(tmpOperPtr.i != insOperPtr.i);
5036  tmpOperPtr.i = tmpOperPtr.p->nextLockOwnerOp;
5037  }
5038 #endif
5039  tmpOperPtr.i = fragrecptr.p->lockOwnersList;
5040 
5041  ndbrequire(! (insOperPtr.p->m_op_bits & Operationrec::OP_LOCK_OWNER));
5042 
5043  insOperPtr.p->m_op_bits |= Operationrec::OP_LOCK_OWNER;
5044  insOperPtr.p->prevLockOwnerOp = RNIL;
5045  insOperPtr.p->nextLockOwnerOp = tmpOperPtr.i;
5046 
5047  fragrecptr.p->lockOwnersList = insOperPtr.i;
5048  if (tmpOperPtr.i == RNIL) {
5049  return;
5050  } else {
5051  jam();
5052  ptrCheckGuard(tmpOperPtr, coprecsize, operationrec);
5053  tmpOperPtr.p->prevLockOwnerOp = insOperPtr.i;
5054  }//if
5055 }//Dbacc::insertLockOwnersList()
5056 
5057 
5058 /* --------------------------------------------------------------------------------- */
5059 /* --------------------------------------------------------------------------------- */
5060 /* --------------------------------------------------------------------------------- */
5061 /* */
5062 /* END OF COMMIT AND ABORT MODULE */
5063 /* */
5064 /* --------------------------------------------------------------------------------- */
5065 /* --------------------------------------------------------------------------------- */
5066 /* --------------------------------------------------------------------------------- */
5067 /* --------------------------------------------------------------------------------- */
5068 /* --------------------------------------------------------------------------------- */
5069 /* ALLOC_OVERFLOW_PAGE */
5070 /* DESCRIPTION: */
5071 /* --------------------------------------------------------------------------------- */
5072 void Dbacc::allocOverflowPage(Signal* signal)
5073 {
5074  DirRangePtr aopDirRangePtr;
5075  DirectoryarrayPtr aopOverflowDirptr;
5076  OverflowRecordPtr aopOverflowRecPtr;
5077  Uint32 taopTmp1;
5078  Uint32 taopTmp2;
5079  Uint32 taopTmp3;
5080 
5081  tresult = 0;
5082  if (cfirstfreepage == RNIL)
5083  {
5084  jam();
5085  zpagesize_error("Dbacc::allocOverflowPage");
5086  tresult = ZPAGESIZE_ERROR;
5087  return;
5088  }//if
5089  if (fragrecptr.p->firstFreeDirindexRec != RNIL) {
5090  jam();
5091  /* FRAGRECPTR:FIRST_FREE_DIRINDEX_REC POINTS */
5092  /* TO THE FIRST ELEMENT IN A FREE LIST OF THE */
5093  /* DIRECTORY INDEX WICH HAVE NULL AS PAGE */
5094  aopOverflowRecPtr.i = fragrecptr.p->firstFreeDirindexRec;
5095  ptrCheckGuard(aopOverflowRecPtr, coverflowrecsize, overflowRecord);
5096  troOverflowRecPtr.p = aopOverflowRecPtr.p;
5097  takeRecOutOfFreeOverdir(signal);
5098  } else if (cfirstfreeoverrec == RNIL) {
5099  jam();
5100  tresult = ZOVER_REC_ERROR;
5101  return;
5102  } else if ((cfirstfreedir == RNIL) &&
5103  (cdirarraysize <= cdirmemory)) {
5104  jam();
5105  tresult = ZDIRSIZE_ERROR;
5106  return;
5107  } else {
5108  jam();
5109  seizeOverRec(signal);
5110  aopOverflowRecPtr = sorOverflowRecPtr;
5111  aopOverflowRecPtr.p->dirindex = fragrecptr.p->lastOverIndex;
5112  }//if
5113  aopOverflowRecPtr.p->nextOverRec = RNIL;
5114  aopOverflowRecPtr.p->prevOverRec = RNIL;
5115  fragrecptr.p->firstOverflowRec = aopOverflowRecPtr.i;
5116  fragrecptr.p->lastOverflowRec = aopOverflowRecPtr.i;
5117  taopTmp1 = aopOverflowRecPtr.p->dirindex;
5118  aopDirRangePtr.i = fragrecptr.p->overflowdir;
5119  taopTmp2 = taopTmp1 >> 8;
5120  taopTmp3 = taopTmp1 & 0xff;
5121  ptrCheckGuard(aopDirRangePtr, cdirrangesize, dirRange);
5122  arrGuard(taopTmp2, 256);
5123  if (aopDirRangePtr.p->dirArray[taopTmp2] == RNIL) {
5124  jam();
5125  seizeDirectory(signal);
5126  ndbrequire(tresult <= ZLIMIT_OF_ERROR);
5127  aopDirRangePtr.p->dirArray[taopTmp2] = sdDirptr.i;
5128  }//if
5129  aopOverflowDirptr.i = aopDirRangePtr.p->dirArray[taopTmp2];
5130  seizePage(signal);
5131  ndbrequire(tresult <= ZLIMIT_OF_ERROR);
5132  ptrCheckGuard(aopOverflowDirptr, cdirarraysize, directoryarray);
5133  aopOverflowDirptr.p->pagep[taopTmp3] = spPageptr.i;
5134  tiopPageId = aopOverflowRecPtr.p->dirindex;
5135  iopOverflowRecPtr = aopOverflowRecPtr;
5136  iopPageptr = spPageptr;
5137  initOverpage(signal);
5138  aopOverflowRecPtr.p->overpage = spPageptr.i;
5139  if (fragrecptr.p->lastOverIndex <= aopOverflowRecPtr.p->dirindex) {
5140  jam();
5141  ndbrequire(fragrecptr.p->lastOverIndex == aopOverflowRecPtr.p->dirindex);
5142  fragrecptr.p->lastOverIndex++;
5143  }//if
5144 }//Dbacc::allocOverflowPage()
5145 
5146 /* --------------------------------------------------------------------------------- */
5147 /* --------------------------------------------------------------------------------- */
5148 /* --------------------------------------------------------------------------------- */
5149 /* */
5150 /* EXPAND/SHRINK MODULE */
5151 /* */
5152 /* --------------------------------------------------------------------------------- */
5153 /* --------------------------------------------------------------------------------- */
5154 /* ******************--------------------------------------------------------------- */
5155 /*EXPANDCHECK EXPAND BUCKET ORD */
5156 /* SENDER: ACC, LEVEL B */
5157 /* INPUT: FRAGRECPTR, POINTS TO A FRAGMENT RECORD. */
5158 /* DESCRIPTION: A BUCKET OF A FRAGMENT PAGE WILL BE EXPAND INTO TWO BUCKETS */
5159 /* ACCORDING TO LH3. */
5160 /* ******************--------------------------------------------------------------- */
5161 /* ******************--------------------------------------------------------------- */
5162 /* EXPANDCHECK EXPAND BUCKET ORD */
5163 /* ******************------------------------------+ */
5164 /* SENDER: ACC, LEVEL B */
5165 /* A BUCKET OF THE FRAGMENT WILL */
5166 /* BE EXPANDED ACORDING TO LH3, */
5167 /* AND COMMIT TRANSACTION PROCESS */
5168 /* WILL BE CONTINUED */
5169 Uint32 Dbacc::checkScanExpand(Signal* signal)
5170 {
5171  Uint32 Ti;
5172  Uint32 TreturnCode = 0;
5173  Uint32 TPageIndex;
5174  Uint32 TDirInd;
5175  Uint32 TSplit;
5176  Uint32 TreleaseInd = 0;
5177  Uint32 TreleaseScanBucket;
5178  Uint32 TreleaseScanIndicator[MAX_PARALLEL_SCANS_PER_FRAG];
5179  DirectoryarrayPtr TDirptr;
5180  DirRangePtr TDirRangePtr;
5181  Page8Ptr TPageptr;
5182  ScanRecPtr TscanPtr;
5183 
5184  TSplit = fragrecptr.p->p;
5185  for (Ti = 0; Ti < MAX_PARALLEL_SCANS_PER_FRAG; Ti++) {
5186  TreleaseScanIndicator[Ti] = 0;
5187  if (fragrecptr.p->scan[Ti] != RNIL) {
5188  //-------------------------------------------------------------
5189  // A scan is ongoing on this particular local fragment. We have
5190  // to check its current state.
5191  //-------------------------------------------------------------
5192  TscanPtr.i = fragrecptr.p->scan[Ti];
5193  ptrCheckGuard(TscanPtr, cscanRecSize, scanRec);
5194  if (TscanPtr.p->activeLocalFrag == fragrecptr.i) {
5195  if (TscanPtr.p->scanBucketState == ScanRec::FIRST_LAP) {
5196  if (TSplit == TscanPtr.p->nextBucketIndex) {
5197  jam();
5198  //-------------------------------------------------------------
5199  // We are currently scanning this bucket. We cannot split it
5200  // simultaneously with the scan. We have to pass this offer for
5201  // splitting the bucket.
5202  //-------------------------------------------------------------
5203  TreturnCode = 1;
5204  return TreturnCode;
5205  } else if (TSplit > TscanPtr.p->nextBucketIndex) {
5206  jam();
5207  //-------------------------------------------------------------
5208  // This bucket has not yet been scanned. We must reset the scanned
5209  // bit indicator for this scan on this bucket.
5210  //-------------------------------------------------------------
5211  TreleaseScanIndicator[Ti] = 1;
5212  TreleaseInd = 1;
5213  } else {
5214  jam();
5215  }//if
5216  } else if (TscanPtr.p->scanBucketState == ScanRec::SECOND_LAP) {
5217  jam();
5218  //-------------------------------------------------------------
5219  // We are performing a second lap to handle buckets that was
5220  // merged during the first lap of scanning. During this second
5221  // lap we do not allow any splits or merges.
5222  //-------------------------------------------------------------
5223  TreturnCode = 1;
5224  return TreturnCode;
5225  } else {
5226  ndbrequire(TscanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED);
5227  jam();
5228  //-------------------------------------------------------------
5229  // The scan is completed and we can thus go ahead and perform
5230  // the split.
5231  //-------------------------------------------------------------
5232  }//if
5233  }//if
5234  }//if
5235  }//for
5236  if (TreleaseInd == 1) {
5237  TreleaseScanBucket = TSplit;
5238  TDirRangePtr.i = fragrecptr.p->directory;
5239  TPageIndex = TreleaseScanBucket & ((1 << fragrecptr.p->k) - 1); /* PAGE INDEX OBS K = 6 */
5240  TDirInd = TreleaseScanBucket >> fragrecptr.p->k; /* DIRECTORY INDEX OBS K = 6 */
5241  ptrCheckGuard(TDirRangePtr, cdirrangesize, dirRange);
5242  arrGuard((TDirInd >> 8), 256);
5243  TDirptr.i = TDirRangePtr.p->dirArray[TDirInd >> 8];
5244  ptrCheckGuard(TDirptr, cdirarraysize, directoryarray);
5245  TPageptr.i = TDirptr.p->pagep[TDirInd & 0xff];
5246  ptrCheckGuard(TPageptr, cpagesize, page8);
5247  for (Ti = 0; Ti < MAX_PARALLEL_SCANS_PER_FRAG; Ti++) {
5248  if (TreleaseScanIndicator[Ti] == 1) {
5249  jam();
5250  scanPtr.i = fragrecptr.p->scan[Ti];
5251  ptrCheckGuard(scanPtr, cscanRecSize, scanRec);
5252  rsbPageidptr = TPageptr;
5253  trsbPageindex = TPageIndex;
5254  releaseScanBucket(signal);
5255  }//if
5256  }//for
5257  }//if
5258  return TreturnCode;
5259 }//Dbacc::checkScanExpand()
5260 
5261 void Dbacc::execEXPANDCHECK2(Signal* signal)
5262 {
5263  jamEntry();
5264 
5265  if(refToBlock(signal->getSendersBlockRef()) == DBLQH)
5266  {
5267  jam();
5268  return;
5269  }
5270 
5271  DirectoryarrayPtr newDirptr;
5272 
5273  fragrecptr.i = signal->theData[0];
5274  tresult = 0; /* 0= FALSE,1= TRUE,> ZLIMIT_OF_ERROR =ERRORCODE */
5275  Uint32 tmp = 1;
5276  tmp = tmp << 31;
5277  ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
5278  fragrecptr.p->expandFlag = 0;
5279  if (fragrecptr.p->slack < tmp) {
5280  jam();
5281  /* IT MEANS THAT IF SLACK > ZERO */
5282  /*--------------------------------------------------------------*/
5283  /* THE SLACK HAS IMPROVED AND IS NOW ACCEPTABLE AND WE */
5284  /* CAN FORGET ABOUT THE EXPAND PROCESS. */
5285  /*--------------------------------------------------------------*/
5286  if (ERROR_INSERTED(3002))
5287  debug_lh_vars("SLK");
5288  if (fragrecptr.p->dirRangeFull == ZTRUE) {
5289  jam();
5290  fragrecptr.p->dirRangeFull = ZFALSE;
5291  }
5292  return;
5293  }//if
5294  if (fragrecptr.p->firstOverflowRec == RNIL) {
5295  jam();
5296  allocOverflowPage(signal);
5297  if (tresult > ZLIMIT_OF_ERROR) {
5298  jam();
5299  /*--------------------------------------------------------------*/
5300  /* WE COULD NOT ALLOCATE ANY OVERFLOW PAGE. THUS WE HAVE TO STOP*/
5301  /* THE EXPAND SINCE WE CANNOT GUARANTEE ITS COMPLETION. */
5302  /*--------------------------------------------------------------*/
5303  return;
5304  }//if
5305  }//if
5306  if (cfirstfreepage == RNIL)
5307  {
5308  /*--------------------------------------------------------------*/
5309  /* WE HAVE TO STOP THE EXPAND PROCESS SINCE THERE ARE NO FREE */
5310  /* PAGES. THIS MEANS THAT WE COULD BE FORCED TO CRASH SINCE WE */
5311  /* CANNOT COMPLETE THE EXPAND. TO AVOID THE CRASH WE EXIT HERE. */
5312  /*--------------------------------------------------------------*/
5313  return;
5314  }//if
5315  if (checkScanExpand(signal) == 1) {
5316  jam();
5317  /*--------------------------------------------------------------*/
5318  // A scan state was inconsistent with performing an expand
5319  // operation.
5320  /*--------------------------------------------------------------*/
5321  return;
5322  }//if
5323 
5324  /*--------------------------------------------------------------------------*/
5325  /* WE START BY FINDING THE PAGE, THE PAGE INDEX AND THE PAGE DIRECTORY*/
5326  /* OF THE NEW BUCKET WHICH SHALL RECEIVE THE ELEMENT WHICH HAVE A 1 IN*/
5327  /* THE NEXT HASH BIT. THIS BIT IS USED IN THE SPLIT MECHANISM TO */
5328  /* DECIDE WHICH ELEMENT GOES WHERE. */
5329  /*--------------------------------------------------------------------------*/
5330  expDirRangePtr.i = fragrecptr.p->directory;
5331  texpReceivedBucket = (fragrecptr.p->maxp + fragrecptr.p->p) + 1; /* RECEIVED BUCKET */
5332  texpDirInd = texpReceivedBucket >> fragrecptr.p->k;
5333  newDirptr.i = RNIL;
5334  ptrNull(newDirptr);
5335  texpDirRangeIndex = texpDirInd >> 8;
5336  ptrCheckGuard(expDirRangePtr, cdirrangesize, dirRange);
5337  Uint32 max_dir_range_size = 256;
5338  if (ERROR_INSERTED(3002)) {
5339  debug_lh_vars("EXP");
5340  max_dir_range_size = 2;
5341  }
5342  if (texpDirRangeIndex >= max_dir_range_size) {
5343  jam();
5344  ndbrequire(texpDirRangeIndex == max_dir_range_size);
5345  if (fragrecptr.p->dirRangeFull == ZFALSE) {
5346  jam();
5347  fragrecptr.p->dirRangeFull = ZTRUE;
5348  }
5349  return;
5350  }
5351  expDirptr.i = expDirRangePtr.p->dirArray[texpDirRangeIndex];
5352  if (expDirptr.i == RNIL) {
5353  jam();
5354  seizeDirectory(signal);
5355  if (tresult > ZLIMIT_OF_ERROR) {
5356  jam();
5357  return;
5358  } else {
5359  jam();
5360  newDirptr = sdDirptr;
5361  expDirptr = sdDirptr;
5362  expDirRangePtr.p->dirArray[texpDirRangeIndex] = sdDirptr.i;
5363  }//if
5364  } else {
5365  ptrCheckGuard(expDirptr, cdirarraysize, directoryarray);
5366  }//if
5367  texpDirPageIndex = texpDirInd & 0xff;
5368  expPageptr.i = expDirptr.p->pagep[texpDirPageIndex];
5369  if (expPageptr.i == RNIL) {
5370  jam();
5371  seizePage(signal);
5372  if (tresult > ZLIMIT_OF_ERROR) {
5373  jam();
5374  if (newDirptr.i != RNIL) {
5375  jam();
5376  rdDirptr.i = newDirptr.i;
5377  releaseDirectory(signal);
5378  }//if
5379  return;
5380  }//if
5381  expDirptr.p->pagep[texpDirPageIndex] = spPageptr.i;
5382  tipPageId = texpDirInd;
5383  inpPageptr = spPageptr;
5384  initPage(signal);
5385  fragrecptr.p->dirsize++;
5386  expPageptr = spPageptr;
5387  } else {
5388  ptrCheckGuard(expPageptr, cpagesize, page8);
5389  }//if
5390 
5391  fragrecptr.p->expReceivePageptr = expPageptr.i;
5392  fragrecptr.p->expReceiveIndex = texpReceivedBucket & ((1 << fragrecptr.p->k) - 1);
5393  /*--------------------------------------------------------------------------*/
5394  /* THE NEXT ACTION IS TO FIND THE PAGE, THE PAGE INDEX AND THE PAGE */
5395  /* DIRECTORY OF THE BUCKET TO BE SPLIT. */
5396  /*--------------------------------------------------------------------------*/
5397  expDirRangePtr.i = fragrecptr.p->directory;
5398  cexcPageindex = fragrecptr.p->p & ((1 << fragrecptr.p->k) - 1); /* PAGE INDEX OBS K = 6 */
5399  texpDirInd = fragrecptr.p->p >> fragrecptr.p->k; /* DIRECTORY INDEX OBS K = 6 */
5400  ptrCheckGuard(expDirRangePtr, cdirrangesize, dirRange);
5401  arrGuard((texpDirInd >> 8), 256);
5402  expDirptr.i = expDirRangePtr.p->dirArray[texpDirInd >> 8];
5403  ptrCheckGuard(expDirptr, cdirarraysize, directoryarray);
5404  excPageptr.i = expDirptr.p->pagep[texpDirInd & 0xff];
5405  fragrecptr.p->expSenderIndex = cexcPageindex;
5406  fragrecptr.p->expSenderPageptr = excPageptr.i;
5407  if (excPageptr.i == RNIL) {
5408  jam();
5409  endofexpLab(signal); /* EMPTY BUCKET */
5410  return;
5411  }//if
5412  fragrecptr.p->expReceiveForward = ZTRUE;
5413  ptrCheckGuard(excPageptr, cpagesize, page8);
5414  expandcontainer(signal);
5415  endofexpLab(signal);
5416  return;
5417 }//Dbacc::execEXPANDCHECK2()
5418 
5419 void Dbacc::endofexpLab(Signal* signal)
5420 {
5421  fragrecptr.p->p++;
5422  fragrecptr.p->slack += fragrecptr.p->maxloadfactor;
5423  fragrecptr.p->expandCounter++;
5424  if (fragrecptr.p->p > fragrecptr.p->maxp) {
5425  jam();
5426  fragrecptr.p->maxp = (fragrecptr.p->maxp << 1) | 1;
5427  fragrecptr.p->lhdirbits++;
5428  fragrecptr.p->hashcheckbit++;
5429  fragrecptr.p->p = 0;
5430  }//if
5431  Uint32 noOfBuckets = (fragrecptr.p->maxp + 1) + fragrecptr.p->p;
5432  Uint32 Thysteres = fragrecptr.p->maxloadfactor - fragrecptr.p->minloadfactor;
5433  fragrecptr.p->slackCheck = noOfBuckets * Thysteres;
5434  if (fragrecptr.p->slack > (1u << 31)) {
5435  jam();
5436  /* IT MEANS THAT IF SLACK < ZERO */
5437  /* --------------------------------------------------------------------------------- */
5438  /* IT IS STILL NECESSARY TO EXPAND THE FRAGMENT EVEN MORE. START IT FROM HERE */
5439  /* WITHOUT WAITING FOR NEXT COMMIT ON THE FRAGMENT. */
5440  /* --------------------------------------------------------------------------------- */
5441  fragrecptr.p->expandFlag = 2;
5442  signal->theData[0] = fragrecptr.i;
5443  signal->theData[1] = fragrecptr.p->p;
5444  signal->theData[2] = fragrecptr.p->maxp;
5445  sendSignal(cownBlockref, GSN_EXPANDCHECK2, signal, 3, JBB);
5446  }//if
5447  return;
5448 }//Dbacc::endofexpLab()
5449 
5450 void Dbacc::reenable_expand_after_redo_log_exection_complete(Signal* signal){
5451 
5452  tabptr.i = signal->theData[0];
5453  Uint32 fragId = signal->theData[1];
5454 
5455  ptrCheckGuard(tabptr, ctablesize, tabrec);
5456  ndbrequire(getfragmentrec(signal, fragrecptr, fragId));
5457 #if 0
5458  ndbout_c("reenable expand check for table %d fragment: %d",
5459  tabptr.i, fragId);
5460 #endif
5461 
5462  switch(fragrecptr.p->expandFlag){
5463  case 0:
5467  fragrecptr.p->expandFlag = 1;
5468  break;
5469  case 1:
5473  case 2:
5478  fragrecptr.p->expandFlag = 2;
5479  signal->theData[0] = fragrecptr.i;
5480  signal->theData[1] = fragrecptr.p->p;
5481  signal->theData[2] = fragrecptr.p->maxp;
5482  sendSignal(cownBlockref, GSN_EXPANDCHECK2, signal, 3, JBB);
5483  break;
5484  }
5485 }
5486 
5487 void Dbacc::execDEBUG_SIG(Signal* signal)
5488 {
5489  jamEntry();
5490  expPageptr.i = signal->theData[0];
5491 
5492  progError(__LINE__, NDBD_EXIT_SR_UNDOLOG);
5493  return;
5494 }//Dbacc::execDEBUG_SIG()
5495 
5496 /* --------------------------------------------------------------------------------- */
5497 /* EXPANDCONTAINER */
5498 /* INPUT: EXC_PAGEPTR (POINTER TO THE ACTIVE PAGE RECORD) */
5499 /* CEXC_PAGEINDEX (INDEX OF THE BUCKET). */
5500 /* */
5501 /* DESCRIPTION: THE HASH VALUE OF ALL ELEMENTS IN THE CONTAINER WILL BE */
5502 /* CHECKED. SOME OF THIS ELEMENTS HAVE TO MOVE TO THE NEW CONTAINER */
5503 /* --------------------------------------------------------------------------------- */
5504 void Dbacc::expandcontainer(Signal* signal)
5505 {
5506  Uint32 texcHashvalue;
5507  Uint32 texcTmp;
5508  Uint32 texcIndex;
5509  Uint32 guard20;
5510 
5511  cexcPrevpageptr = RNIL;
5512  cexcPrevconptr = 0;
5513  cexcForward = ZTRUE;
5514  EXP_CONTAINER_LOOP:
5515  cexcContainerptr = (cexcPageindex << ZSHIFT_PLUS) - (cexcPageindex << ZSHIFT_MINUS);
5516  if (cexcForward == ZTRUE) {
5517  jam();
5518  cexcContainerptr = cexcContainerptr + ZHEAD_SIZE;
5519  cexcElementptr = cexcContainerptr + ZCON_HEAD_SIZE;
5520  } else {
5521  jam();
5522  cexcContainerptr = ((cexcContainerptr + ZHEAD_SIZE) + ZBUF_SIZE) - ZCON_HEAD_SIZE;
5523  cexcElementptr = cexcContainerptr - 1;
5524  }//if
5525  arrGuard(cexcContainerptr, 2048);
5526  cexcContainerhead = excPageptr.p->word32[cexcContainerptr];
5527  cexcContainerlen = cexcContainerhead >> 26;
5528  cexcMovedLen = ZCON_HEAD_SIZE;
5529  if (cexcContainerlen <= ZCON_HEAD_SIZE) {
5530  ndbrequire(cexcContainerlen >= ZCON_HEAD_SIZE);
5531  jam();
5532  goto NEXT_ELEMENT;
5533  }//if
5534  NEXT_ELEMENT_LOOP:
5535  idrOperationRecPtr.i = RNIL;
5536  ptrNull(idrOperationRecPtr);
5537  /* --------------------------------------------------------------------------------- */
5538  /* CEXC_PAGEINDEX PAGE INDEX OF CURRENT CONTAINER BEING EXAMINED. */
5539  /* CEXC_CONTAINERPTR INDEX OF CURRENT CONTAINER BEING EXAMINED. */
5540  /* CEXC_ELEMENTPTR INDEX OF CURRENT ELEMENT BEING EXAMINED. */
5541  /* EXC_PAGEPTR PAGE WHERE CURRENT ELEMENT RESIDES. */
5542  /* CEXC_PREVPAGEPTR PAGE OF PREVIOUS CONTAINER. */
5543  /* CEXC_PREVCONPTR INDEX OF PREVIOUS CONTAINER */
5544  /* CEXC_FORWARD DIRECTION OF CURRENT CONTAINER */
5545  /* --------------------------------------------------------------------------------- */
5546  arrGuard(cexcElementptr, 2048);
5547  tidrElemhead = excPageptr.p->word32[cexcElementptr];
5548  if (ElementHeader::getUnlocked(tidrElemhead)){
5549  jam();
5550  texcHashvalue = ElementHeader::getHashValuePart(tidrElemhead);
5551  } else {
5552  jam();
5553  idrOperationRecPtr.i = ElementHeader::getOpPtrI(tidrElemhead);
5554  ptrCheckGuard(idrOperationRecPtr, coprecsize, operationrec);
5555  texcHashvalue = idrOperationRecPtr.p->hashvaluePart;
5556  }//if
5557  if (((texcHashvalue >> fragrecptr.p->hashcheckbit) & 1) == 0) {
5558  jam();
5559  /* --------------------------------------------------------------------------------- */
5560  /* THIS ELEMENT IS NOT TO BE MOVED. WE CALCULATE THE WHEREABOUTS OF THE NEXT */
5561  /* ELEMENT AND PROCEED WITH THAT OR END THE SEARCH IF THERE ARE NO MORE */
5562  /* ELEMENTS IN THIS CONTAINER. */
5563  /* --------------------------------------------------------------------------------- */
5564  goto NEXT_ELEMENT;
5565  }//if
5566  /* --------------------------------------------------------------------------------- */
5567  /* THE HASH BIT WAS SET AND WE SHALL MOVE THIS ELEMENT TO THE NEW BUCKET. */
5568  /* WE START BY READING THE ELEMENT TO BE ABLE TO INSERT IT INTO THE NEW BUCKET.*/
5569  /* THEN WE INSERT THE ELEMENT INTO THE NEW BUCKET. THE NEXT STEP IS TO DELETE */
5570  /* THE ELEMENT FROM THIS BUCKET. THIS IS PERFORMED BY REPLACING IT WITH THE */
5571  /* LAST ELEMENT IN THE BUCKET. IF THIS ELEMENT IS TO BE MOVED WE MOVE IT AND */
5572  /* GET THE LAST ELEMENT AGAIN UNTIL WE EITHER FIND ONE THAT STAYS OR THIS */
5573  /* ELEMENT IS THE LAST ELEMENT. */
5574  /* --------------------------------------------------------------------------------- */
5575  texcTmp = cexcElementptr + cexcForward;
5576  guard20 = fragrecptr.p->localkeylen - 1;
5577  for (texcIndex = 0; texcIndex <= guard20; texcIndex++) {
5578  arrGuard(texcIndex, 2);
5579  arrGuard(texcTmp, 2048);
5580  clocalkey[texcIndex] = excPageptr.p->word32[texcTmp];
5581  texcTmp = texcTmp + cexcForward;
5582  }//for
5583  tidrPageindex = fragrecptr.p->expReceiveIndex;
5584  idrPageptr.i = fragrecptr.p->expReceivePageptr;
5585  ptrCheckGuard(idrPageptr, cpagesize, page8);
5586  tidrForward = fragrecptr.p->expReceiveForward;
5587  insertElement(signal);
5588  fragrecptr.p->expReceiveIndex = tidrPageindex;
5589  fragrecptr.p->expReceivePageptr = idrPageptr.i;
5590  fragrecptr.p->expReceiveForward = tidrForward;
5591  REMOVE_LAST_LOOP:
5592  jam();
5593  lastPageptr.i = excPageptr.i;
5594  lastPageptr.p = excPageptr.p;
5595  tlastContainerptr = cexcContainerptr;
5596  lastPrevpageptr.i = cexcPrevpageptr;
5597  ptrCheck(lastPrevpageptr, cpagesize, page8);
5598  tlastPrevconptr = cexcPrevconptr;
5599  arrGuard(tlastContainerptr, 2048);
5600  tlastContainerhead = lastPageptr.p->word32[tlastContainerptr];
5601  tlastContainerlen = tlastContainerhead >> 26;
5602  tlastForward = cexcForward;
5603  tlastPageindex = cexcPageindex;
5604  getLastAndRemove(signal);
5605  if (excPageptr.i == lastPageptr.i) {
5606  if (cexcElementptr == tlastElementptr) {
5607  jam();
5608  /* --------------------------------------------------------------------------------- */
5609  /* THE CURRENT ELEMENT WAS ALSO THE LAST ELEMENT. */
5610  /* --------------------------------------------------------------------------------- */
5611  return;
5612  }//if
5613  }//if
5614  /* --------------------------------------------------------------------------------- */
5615  /* THE CURRENT ELEMENT WAS NOT THE LAST ELEMENT. IF THE LAST ELEMENT SHOULD */
5616  /* STAY WE COPY IT TO THE POSITION OF THE CURRENT ELEMENT, OTHERWISE WE INSERT */
5617  /* INTO THE NEW BUCKET, REMOVE IT AND TRY WITH THE NEW LAST ELEMENT. */
5618  /* --------------------------------------------------------------------------------- */
5619  idrOperationRecPtr.i = RNIL;
5620  ptrNull(idrOperationRecPtr);
5621  arrGuard(tlastElementptr, 2048);
5622  tidrElemhead = lastPageptr.p->word32[tlastElementptr];
5623  if (ElementHeader::getUnlocked(tidrElemhead)) {
5624  jam();
5625  texcHashvalue = ElementHeader::getHashValuePart(tidrElemhead);
5626  } else {
5627  jam();
5628  idrOperationRecPtr.i = ElementHeader::getOpPtrI(tidrElemhead);
5629  ptrCheckGuard(idrOperationRecPtr, coprecsize, operationrec);
5630  texcHashvalue = idrOperationRecPtr.p->hashvaluePart;
5631  }//if
5632  if (((texcHashvalue >> fragrecptr.p->hashcheckbit) & 1) == 0) {
5633  jam();
5634  /* --------------------------------------------------------------------------------- */
5635  /* THE LAST ELEMENT IS NOT TO BE MOVED. WE COPY IT TO THE CURRENT ELEMENT. */
5636  /* --------------------------------------------------------------------------------- */
5637  delPageptr = excPageptr;
5638  tdelContainerptr = cexcContainerptr;
5639  tdelForward = cexcForward;
5640  tdelElementptr = cexcElementptr;
5641  deleteElement(signal);
5642  } else {
5643  jam();
5644  /* --------------------------------------------------------------------------------- */
5645  /* THE LAST ELEMENT IS ALSO TO BE MOVED. */
5646  /* --------------------------------------------------------------------------------- */
5647  texcTmp = tlastElementptr + tlastForward;
5648  for (texcIndex = 0; texcIndex < fragrecptr.p->localkeylen; texcIndex++) {
5649  arrGuard(texcIndex, 2);
5650  arrGuard(texcTmp, 2048);
5651  clocalkey[texcIndex] = lastPageptr.p->word32[texcTmp];
5652  texcTmp = texcTmp + tlastForward;
5653  }//for
5654  tidrPageindex = fragrecptr.p->expReceiveIndex;
5655  idrPageptr.i = fragrecptr.p->expReceivePageptr;
5656  ptrCheckGuard(idrPageptr, cpagesize, page8);
5657  tidrForward = fragrecptr.p->expReceiveForward;
5658  insertElement(signal);
5659  fragrecptr.p->expReceiveIndex = tidrPageindex;
5660  fragrecptr.p->expReceivePageptr = idrPageptr.i;
5661  fragrecptr.p->expReceiveForward = tidrForward;
5662  goto REMOVE_LAST_LOOP;
5663  }//if
5664  NEXT_ELEMENT:
5665  arrGuard(cexcContainerptr, 2048);
5666  cexcContainerhead = excPageptr.p->word32[cexcContainerptr];
5667  cexcMovedLen = cexcMovedLen + fragrecptr.p->elementLength;
5668  if ((cexcContainerhead >> 26) > cexcMovedLen) {
5669  jam();
5670  /* --------------------------------------------------------------------------------- */
5671  /* WE HAVE NOT YET MOVED THE COMPLETE CONTAINER. WE PROCEED WITH THE NEXT */
5672  /* ELEMENT IN THE CONTAINER. IT IS IMPORTANT TO READ THE CONTAINER LENGTH */
5673  /* FROM THE CONTAINER HEADER SINCE IT MIGHT CHANGE BY REMOVING THE LAST */
5674  /* ELEMENT IN THE BUCKET. */
5675  /* --------------------------------------------------------------------------------- */
5676  cexcElementptr = cexcElementptr + (cexcForward * fragrecptr.p->elementLength);
5677  goto NEXT_ELEMENT_LOOP;
5678  }//if
5679  if (((cexcContainerhead >> 7) & 3) != 0) {
5680  jam();
5681  /* --------------------------------------------------------------------------------- */
5682  /* WE PROCEED TO THE NEXT CONTAINER IN THE BUCKET. */
5683  /* --------------------------------------------------------------------------------- */
5684  cexcPrevpageptr = excPageptr.i;
5685  cexcPrevconptr = cexcContainerptr;
5686  nextcontainerinfoExp(signal);
5687  goto EXP_CONTAINER_LOOP;
5688  }//if
5689 }//Dbacc::expandcontainer()
5690 
5691 /* ******************--------------------------------------------------------------- */
5692 /* SHRINKCHECK JOIN BUCKET ORD */
5693 /* SENDER: ACC, LEVEL B */
5694 /* INPUT: FRAGRECPTR, POINTS TO A FRAGMENT RECORD. */
5695 /* DESCRIPTION: TWO BUCKET OF A FRAGMENT PAGE WILL BE JOINED TOGETHER */
5696 /* ACCORDING TO LH3. */
5697 /* ******************--------------------------------------------------------------- */
5698 /* ******************--------------------------------------------------------------- */
5699 /* SHRINKCHECK JOIN BUCKET ORD */
5700 /* ******************------------------------------+ */
5701 /* SENDER: ACC, LEVEL B */
5702 /* TWO BUCKETS OF THE FRAGMENT */
5703 /* WILL BE JOINED ACORDING TO LH3 */
5704 /* AND COMMIT TRANSACTION PROCESS */
5705 /* WILL BE CONTINUED */
5706 Uint32 Dbacc::checkScanShrink(Signal* signal)
5707 {
5708  Uint32 Ti;
5709  Uint32 TreturnCode = 0;
5710  Uint32 TPageIndex;
5711  Uint32 TDirInd;
5712  Uint32 TmergeDest;
5713  Uint32 TmergeSource;
5714  Uint32 TreleaseScanBucket;
5715  Uint32 TreleaseInd = 0;
5716  Uint32 TreleaseScanIndicator[MAX_PARALLEL_SCANS_PER_FRAG];
5717  DirectoryarrayPtr TDirptr;
5718  DirRangePtr TDirRangePtr;
5719  Page8Ptr TPageptr;
5720  ScanRecPtr TscanPtr;
5721 
5722  if (fragrecptr.p->p == 0) {
5723  jam();
5724  TmergeDest = fragrecptr.p->maxp >> 1;
5725  } else {
5726  jam();
5727  TmergeDest = fragrecptr.p->p - 1;
5728  }//if
5729  TmergeSource = fragrecptr.p->maxp + fragrecptr.p->p;
5730  for (Ti = 0; Ti < MAX_PARALLEL_SCANS_PER_FRAG; Ti++) {
5731  TreleaseScanIndicator[Ti] = 0;
5732  if (fragrecptr.p->scan[Ti] != RNIL) {
5733  TscanPtr.i = fragrecptr.p->scan[Ti];
5734  ptrCheckGuard(TscanPtr, cscanRecSize, scanRec);
5735  if (TscanPtr.p->activeLocalFrag == fragrecptr.i) {
5736  //-------------------------------------------------------------
5737  // A scan is ongoing on this particular local fragment. We have
5738  // to check its current state.
5739  //-------------------------------------------------------------
5740  if (TscanPtr.p->scanBucketState == ScanRec::FIRST_LAP) {
5741  jam();
5742  if ((TmergeDest == TscanPtr.p->nextBucketIndex) ||
5743  (TmergeSource == TscanPtr.p->nextBucketIndex)) {
5744  jam();
5745  //-------------------------------------------------------------
5746  // We are currently scanning one of the buckets involved in the
5747  // merge. We cannot merge while simultaneously performing a scan.
5748  // We have to pass this offer for merging the buckets.
5749  //-------------------------------------------------------------
5750  TreturnCode = 1;
5751  return TreturnCode;
5752  } else if (TmergeDest < TscanPtr.p->nextBucketIndex) {
5753  jam();
5754  TreleaseScanIndicator[Ti] = 1;
5755  TreleaseInd = 1;
5756  }//if
5757  } else if (TscanPtr.p->scanBucketState == ScanRec::SECOND_LAP) {
5758  jam();
5759  //-------------------------------------------------------------
5760  // We are performing a second lap to handle buckets that was
5761  // merged during the first lap of scanning. During this second
5762  // lap we do not allow any splits or merges.
5763  //-------------------------------------------------------------
5764  TreturnCode = 1;
5765  return TreturnCode;
5766  } else if (TscanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED) {
5767  jam();
5768  //-------------------------------------------------------------
5769  // The scan is completed and we can thus go ahead and perform
5770  // the split.
5771  //-------------------------------------------------------------
5772  } else {
5773  jam();
5774  sendSystemerror(signal, __LINE__);
5775  return TreturnCode;
5776  }//if
5777  }//if
5778  }//if
5779  }//for
5780  if (TreleaseInd == 1) {
5781  jam();
5782  TreleaseScanBucket = TmergeSource;
5783  TDirRangePtr.i = fragrecptr.p->directory;
5784  TPageIndex = TreleaseScanBucket & ((1 << fragrecptr.p->k) - 1); /* PAGE INDEX OBS K = 6 */
5785  TDirInd = TreleaseScanBucket >> fragrecptr.p->k; /* DIRECTORY INDEX OBS K = 6 */
5786  ptrCheckGuard(TDirRangePtr, cdirrangesize, dirRange);
5787  arrGuard((TDirInd >> 8), 256);
5788  TDirptr.i = TDirRangePtr.p->dirArray[TDirInd >> 8];
5789  ptrCheckGuard(TDirptr, cdirarraysize, directoryarray);
5790  TPageptr.i = TDirptr.p->pagep[TDirInd & 0xff];
5791  ptrCheckGuard(TPageptr, cpagesize, page8);
5792  for (Ti = 0; Ti < MAX_PARALLEL_SCANS_PER_FRAG; Ti++) {
5793  if (TreleaseScanIndicator[Ti] == 1) {
5794  jam();
5795  scanPtr.i = fragrecptr.p->scan[Ti];
5796  ptrCheckGuard(scanPtr, cscanRecSize, scanRec);
5797  rsbPageidptr.i = TPageptr.i;
5798  rsbPageidptr.p = TPageptr.p;
5799  trsbPageindex = TPageIndex;
5800  releaseScanBucket(signal);
5801  if (TmergeDest < scanPtr.p->minBucketIndexToRescan) {
5802  jam();
5803  //-------------------------------------------------------------
5804  // We have to keep track of the starting bucket to Rescan in the
5805  // second lap.
5806  //-------------------------------------------------------------
5807  scanPtr.p->minBucketIndexToRescan = TmergeDest;
5808  }//if
5809  if (TmergeDest > scanPtr.p->maxBucketIndexToRescan) {
5810  jam();
5811  //-------------------------------------------------------------
5812  // We have to keep track of the ending bucket to Rescan in the
5813  // second lap.
5814  //-------------------------------------------------------------
5815  scanPtr.p->maxBucketIndexToRescan = TmergeDest;
5816  }//if
5817  }//if
5818  }//for
5819  }//if
5820  return TreturnCode;
5821 }//Dbacc::checkScanShrink()
5822 
5823 void Dbacc::execSHRINKCHECK2(Signal* signal)
5824 {
5825  Uint32 tshrTmp1;
5826 
5827  jamEntry();
5828  fragrecptr.i = signal->theData[0];
5829  Uint32 oldFlag = signal->theData[3];
5830  ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
5831  fragrecptr.p->expandFlag = oldFlag;
5832  tresult = 0; /* 0= FALSE,1= TRUE,> ZLIMIT_OF_ERROR =ERRORCODE */
5833  if (fragrecptr.p->slack <= fragrecptr.p->slackCheck) {
5834  jam();
5835  /* TIME FOR JOIN BUCKETS PROCESS */
5836  /*--------------------------------------------------------------*/
5837  /* NO LONGER NECESSARY TO SHRINK THE FRAGMENT. */
5838  /*--------------------------------------------------------------*/
5839  return;
5840  }//if
5841  if (fragrecptr.p->slack > (1u << 31)) {
5842  jam();
5843  /*--------------------------------------------------------------*/
5844  /* THE SLACK IS NEGATIVE, IN THIS CASE WE WILL NOT NEED ANY */
5845  /* SHRINK. */
5846  /*--------------------------------------------------------------*/
5847  return;
5848  }//if
5849  texpDirInd = (fragrecptr.p->maxp + fragrecptr.p->p) >> fragrecptr.p->k;
5850  if (fragrecptr.p->firstOverflowRec == RNIL) {
5851  jam();
5852  allocOverflowPage(signal);
5853  if (tresult > ZLIMIT_OF_ERROR) {
5854  jam();
5855  return;
5856  }//if
5857  }//if
5858  if (cfirstfreepage == RNIL)
5859  {
5860  jam();
5861  /*--------------------------------------------------------------*/
5862  /* WE HAVE TO STOP THE SHRINK PROCESS SINCE THERE ARE NO FREE */
5863  /* PAGES. THIS MEANS THAT WE COULD BE FORCED TO CRASH SINCE WE */
5864  /* CANNOT COMPLETE THE SHRINK. TO AVOID THE CRASH WE EXIT HERE. */
5865  /*--------------------------------------------------------------*/
5866  return;
5867  }//if
5868  if (checkScanShrink(signal) == 1) {
5869  jam();
5870  /*--------------------------------------------------------------*/
5871  // A scan state was inconsistent with performing a shrink
5872  // operation.
5873  /*--------------------------------------------------------------*/
5874  return;
5875  }//if
5876  if (fragrecptr.p->p == 0) {
5877  jam();
5878  fragrecptr.p->maxp = fragrecptr.p->maxp >> 1;
5879  fragrecptr.p->p = fragrecptr.p->maxp;
5880  fragrecptr.p->lhdirbits--;
5881  fragrecptr.p->hashcheckbit--;
5882  } else {
5883  jam();
5884  fragrecptr.p->p--;
5885  }//if
5886 
5887  if (ERROR_INSERTED(3002))
5888  debug_lh_vars("SHR");
5889  if (fragrecptr.p->dirRangeFull == ZTRUE) {
5890  jam();
5891  fragrecptr.p->dirRangeFull = ZFALSE;
5892  }
5893 
5894  /*--------------------------------------------------------------------------*/
5895  /* WE START BY FINDING THE NECESSARY INFORMATION OF THE BUCKET TO BE */
5896  /* REMOVED WHICH WILL SEND ITS ELEMENTS TO THE RECEIVING BUCKET. */
5897  /*--------------------------------------------------------------------------*/
5898  expDirRangePtr.i = fragrecptr.p->directory;
5899  cexcPageindex = ((fragrecptr.p->maxp + fragrecptr.p->p) + 1) & ((1 << fragrecptr.p->k) - 1);
5900  texpDirInd = ((fragrecptr.p->maxp + fragrecptr.p->p) + 1) >> fragrecptr.p->k;
5901  texpDirRangeIndex = texpDirInd >> 8;
5902  texpDirPageIndex = texpDirInd & 0xff;
5903  ptrCheckGuard(expDirRangePtr, cdirrangesize, dirRange);
5904  arrGuard(texpDirRangeIndex, 256);
5905  expDirptr.i = expDirRangePtr.p->dirArray[texpDirRangeIndex];
5906  ptrCheckGuard(expDirptr, cdirarraysize, directoryarray);
5907  excPageptr.i = expDirptr.p->pagep[texpDirPageIndex];
5908  fragrecptr.p->expSenderDirptr = expDirptr.i;
5909  fragrecptr.p->expSenderIndex = cexcPageindex;
5910  fragrecptr.p->expSenderPageptr = excPageptr.i;
5911  fragrecptr.p->expSenderDirIndex = texpDirInd;
5912  /*--------------------------------------------------------------------------*/
5913  /* WE NOW PROCEED BY FINDING THE NECESSARY INFORMATION ABOUT THE */
5914  /* RECEIVING BUCKET. */
5915  /*--------------------------------------------------------------------------*/
5916  expDirRangePtr.i = fragrecptr.p->directory;
5917  texpReceivedBucket = fragrecptr.p->p >> fragrecptr.p->k;
5918  ptrCheckGuard(expDirRangePtr, cdirrangesize, dirRange);
5919  arrGuard((texpReceivedBucket >> 8), 256);
5920  expDirptr.i = expDirRangePtr.p->dirArray[texpReceivedBucket >> 8];
5921  ptrCheckGuard(expDirptr, cdirarraysize, directoryarray);
5922  fragrecptr.p->expReceivePageptr = expDirptr.p->pagep[texpReceivedBucket & 0xff];
5923  fragrecptr.p->expReceiveIndex = fragrecptr.p->p & ((1 << fragrecptr.p->k) - 1);
5924  fragrecptr.p->expReceiveForward = ZTRUE;
5925  if (excPageptr.i == RNIL) {
5926  jam();
5927  endofshrinkbucketLab(signal); /* EMPTY BUCKET */
5928  return;
5929  }//if
5930  /*--------------------------------------------------------------------------*/
5931  /* INITIALISE THE VARIABLES FOR THE SHRINK PROCESS. */
5932  /*--------------------------------------------------------------------------*/
5933  ptrCheckGuard(excPageptr, cpagesize, page8);
5934  cexcForward = ZTRUE;
5935  cexcContainerptr = (cexcPageindex << ZSHIFT_PLUS) - (cexcPageindex << ZSHIFT_MINUS);
5936  cexcContainerptr = cexcContainerptr + ZHEAD_SIZE;
5937  arrGuard(cexcContainerptr, 2048);
5938  cexcContainerhead = excPageptr.p->word32[cexcContainerptr];
5939  cexcContainerlen = cexcContainerhead >> 26;
5940  if (cexcContainerlen <= ZCON_HEAD_SIZE) {
5941  ndbrequire(cexcContainerlen == ZCON_HEAD_SIZE);
5942  } else {
5943  jam();
5944  shrinkcontainer(signal);
5945  }//if
5946  /*--------------------------------------------------------------------------*/
5947  /* THIS CONTAINER IS NOT YET EMPTY AND WE REMOVE ALL THE ELEMENTS. */
5948  /*--------------------------------------------------------------------------*/
5949  if (((cexcContainerhead >> 10) & 1) == 1) {
5950  jam();
5951  rlPageptr = excPageptr;
5952  trlPageindex = cexcPageindex;
5953  trlRelCon = ZFALSE;
5954  turlIndex = cexcContainerptr + (ZBUF_SIZE - ZCON_HEAD_SIZE);
5955  releaseRightlist(signal);
5956  }//if
5957  tshrTmp1 = ZCON_HEAD_SIZE;
5958  tshrTmp1 = tshrTmp1 << 26;
5959  dbgWord32(excPageptr, cexcContainerptr, tshrTmp1);
5960  arrGuard(cexcContainerptr, 2048);
5961  excPageptr.p->word32[cexcContainerptr] = tshrTmp1;
5962  if (((cexcContainerhead >> 7) & 0x3) == 0) {
5963  jam();
5964  endofshrinkbucketLab(signal);
5965  return;
5966  }//if
5967  nextcontainerinfoExp(signal);
5968  do {
5969  cexcContainerptr = (cexcPageindex << ZSHIFT_PLUS) - (cexcPageindex << ZSHIFT_MINUS);
5970  if (cexcForward == ZTRUE) {
5971  jam();
5972  cexcContainerptr = cexcContainerptr + ZHEAD_SIZE;
5973  } else {
5974  jam();
5975  cexcContainerptr = ((cexcContainerptr + ZHEAD_SIZE) + ZBUF_SIZE) - ZCON_HEAD_SIZE;
5976  }//if
5977  arrGuard(cexcContainerptr, 2048);
5978  cexcContainerhead = excPageptr.p->word32[cexcContainerptr];
5979  cexcContainerlen = cexcContainerhead >> 26;
5980  ndbrequire(cexcContainerlen > ZCON_HEAD_SIZE);
5981  /*--------------------------------------------------------------------------*/
5982  /* THIS CONTAINER IS NOT YET EMPTY AND WE REMOVE ALL THE ELEMENTS. */
5983  /*--------------------------------------------------------------------------*/
5984  shrinkcontainer(signal);
5985  cexcPrevpageptr = excPageptr.i;
5986  cexcPrevpageindex = cexcPageindex;
5987  cexcPrevforward = cexcForward;
5988  if (((cexcContainerhead >> 7) & 0x3) != 0) {
5989  jam();
5990  /*--------------------------------------------------------------------------*/
5991  /* WE MUST CALL THE NEXT CONTAINER INFO ROUTINE BEFORE WE RELEASE THE */
5992  /* CONTAINER SINCE THE RELEASE WILL OVERWRITE THE NEXT POINTER. */
5993  /*--------------------------------------------------------------------------*/
5994  nextcontainerinfoExp(signal);
5995  }//if
5996  rlPageptr.i = cexcPrevpageptr;
5997  ptrCheckGuard(rlPageptr, cpagesize, page8);
5998  trlPageindex = cexcPrevpageindex;
5999  if (cexcPrevforward == ZTRUE) {
6000  jam();
6001  if (((cexcContainerhead >> 10) & 1) == 1) {
6002  jam();
6003  trlRelCon = ZFALSE;
6004  turlIndex = cexcContainerptr + (ZBUF_SIZE - ZCON_HEAD_SIZE);
6005  releaseRightlist(signal);
6006  }//if
6007  trlRelCon = ZTRUE;
6008  tullIndex = cexcContainerptr;
6009  releaseLeftlist(signal);
6010  } else {
6011  jam();
6012  if (((cexcContainerhead >> 10) & 1) == 1) {
6013  jam();
6014  trlRelCon = ZFALSE;
6015  tullIndex = cexcContainerptr - (ZBUF_SIZE - ZCON_HEAD_SIZE);
6016  releaseLeftlist(signal);
6017  }//if
6018  trlRelCon = ZTRUE;
6019  turlIndex = cexcContainerptr;
6020  releaseRightlist(signal);
6021  }//if
6022  } while (((cexcContainerhead >> 7) & 0x3) != 0);
6023  endofshrinkbucketLab(signal);
6024  return;
6025 }//Dbacc::execSHRINKCHECK2()
6026 
6027 void Dbacc::endofshrinkbucketLab(Signal* signal)
6028 {
6029  fragrecptr.p->expandCounter--;
6030  fragrecptr.p->slack -= fragrecptr.p->maxloadfactor;
6031  if (fragrecptr.p->expSenderIndex == 0) {
6032  jam();
6033  fragrecptr.p->dirsize--;
6034  if (fragrecptr.p->expSenderPageptr != RNIL) {
6035  jam();
6036  rpPageptr.i = fragrecptr.p->expSenderPageptr;
6037  ptrCheckGuard(rpPageptr, cpagesize, page8);
6038  releasePage(signal);
6039  expDirptr.i = fragrecptr.p->expSenderDirptr;
6040  ptrCheckGuard(expDirptr, cdirarraysize, directoryarray);
6041  expDirptr.p->pagep[fragrecptr.p->expSenderDirIndex & 0xff] = RNIL;
6042  }//if
6043  if (((((fragrecptr.p->p + fragrecptr.p->maxp) + 1) >> fragrecptr.p->k) & 0xff) == 0) {
6044  jam();
6045  rdDirptr.i = fragrecptr.p->expSenderDirptr;
6046  releaseDirectory(signal);
6047  expDirRangePtr.i = fragrecptr.p->directory;
6048  ptrCheckGuard(expDirRangePtr, cdirrangesize, dirRange);
6049  arrGuard((fragrecptr.p->expSenderDirIndex >> 8), 256);
6050  expDirRangePtr.p->dirArray[fragrecptr.p->expSenderDirIndex >> 8] = RNIL;
6051  }//if
6052  }//if
6053  if (fragrecptr.p->slack < (1u << 31)) {
6054  jam();
6055  /*--------------------------------------------------------------*/
6056  /* THE SLACK IS POSITIVE, IN THIS CASE WE WILL CHECK WHETHER */
6057  /* WE WILL CONTINUE PERFORM ANOTHER SHRINK. */
6058  /*--------------------------------------------------------------*/
6059  Uint32 noOfBuckets = (fragrecptr.p->maxp + 1) + fragrecptr.p->p;
6060  Uint32 Thysteresis = fragrecptr.p->maxloadfactor - fragrecptr.p->minloadfactor;
6061  fragrecptr.p->slackCheck = noOfBuckets * Thysteresis;
6062  if (fragrecptr.p->slack > Thysteresis) {
6063  /*--------------------------------------------------------------*/
6064  /* IT IS STILL NECESSARY TO SHRINK THE FRAGMENT MORE. THIS*/
6065  /* CAN HAPPEN WHEN A NUMBER OF SHRINKS GET REJECTED */
6066  /* DURING A LOCAL CHECKPOINT. WE START A NEW SHRINK */
6067  /* IMMEDIATELY FROM HERE WITHOUT WAITING FOR A COMMIT TO */
6068  /* START IT. */
6069  /*--------------------------------------------------------------*/
6070  if (fragrecptr.p->expandCounter > 0) {
6071  jam();
6072  /*--------------------------------------------------------------*/
6073  /* IT IS VERY IMPORTANT TO NOT TRY TO SHRINK MORE THAN */
6074  /* WAS EXPANDED. IF MAXP IS SET TO A VALUE BELOW 63 THEN */
6075  /* WE WILL LOSE RECORDS SINCE GETDIRINDEX CANNOT HANDLE */
6076  /* SHRINKING BELOW 2^K - 1 (NOW 63). THIS WAS A BUG THAT */
6077  /* WAS REMOVED 2000-05-12. */
6078  /*--------------------------------------------------------------*/
6079  signal->theData[0] = fragrecptr.i;
6080  signal->theData[1] = fragrecptr.p->p;
6081  signal->theData[2] = fragrecptr.p->maxp;
6082  signal->theData[3] = fragrecptr.p->expandFlag;
6083  ndbrequire(fragrecptr.p->expandFlag < 2);
6084  fragrecptr.p->expandFlag = 2;
6085  sendSignal(cownBlockref, GSN_SHRINKCHECK2, signal, 4, JBB);
6086  }//if
6087  }//if
6088  }//if
6089  ndbrequire(fragrecptr.p->maxp >= (Uint32)((1 << fragrecptr.p->k) - 1));
6090  return;
6091 }//Dbacc::endofshrinkbucketLab()
6092 
6093 /* --------------------------------------------------------------------------------- */
6094 /* SHRINKCONTAINER */
6095 /* INPUT: EXC_PAGEPTR (POINTER TO THE ACTIVE PAGE RECORD) */
6096 /* CEXC_CONTAINERLEN (LENGTH OF THE CONTAINER). */
6097 /* CEXC_CONTAINERPTR (ARRAY INDEX OF THE CONTAINER). */
6098 /* CEXC_FORWARD (CONTAINER FORWARD (+1) OR BACKWARD (-1)) */
6099 /* */
6100 /* DESCRIPTION: ALL ELEMENTS OF THE ACTIVE CONTAINER HAVE TO MOVE TO THE NEW */
6101 /* CONTAINER. */
6102 /* --------------------------------------------------------------------------------- */
6103 void Dbacc::shrinkcontainer(Signal* signal)
6104 {
6105  Uint32 tshrElementptr;
6106  Uint32 tshrRemLen;
6107  Uint32 tshrInc;
6108  Uint32 tshrTmp;
6109  Uint32 tshrIndex;
6110  Uint32 guard21;
6111 
6112  tshrRemLen = cexcContainerlen - ZCON_HEAD_SIZE;
6113  tshrInc = fragrecptr.p->elementLength;
6114  if (cexcForward == ZTRUE) {
6115  jam();
6116  tshrElementptr = cexcContainerptr + ZCON_HEAD_SIZE;
6117  } else {
6118  jam();
6119  tshrElementptr = cexcContainerptr - 1;
6120  }//if
6121  SHR_LOOP:
6122  idrOperationRecPtr.i = RNIL;
6123  ptrNull(idrOperationRecPtr);
6124  /* --------------------------------------------------------------------------------- */
6125  /* THE CODE BELOW IS ALL USED TO PREPARE FOR THE CALL TO INSERT_ELEMENT AND */
6126  /* HANDLE THE RESULT FROM INSERT_ELEMENT. INSERT_ELEMENT INSERTS THE ELEMENT */
6127  /* INTO ANOTHER BUCKET. */
6128  /* --------------------------------------------------------------------------------- */
6129  arrGuard(tshrElementptr, 2048);
6130  tidrElemhead = excPageptr.p->word32[tshrElementptr];
6131  if (ElementHeader::getLocked(tidrElemhead)) {
6132  jam();
6133  /* --------------------------------------------------------------------------------- */
6134  /* IF THE ELEMENT IS LOCKED WE MUST UPDATE THE ELEMENT INFO IN THE OPERATION */
6135  /* RECORD OWNING THE LOCK. WE DO THIS BY READING THE OPERATION RECORD POINTER */
6136  /* FROM THE ELEMENT HEADER. */
6137  /* --------------------------------------------------------------------------------- */
6138  idrOperationRecPtr.i = ElementHeader::getOpPtrI(tidrElemhead);
6139  ptrCheckGuard(idrOperationRecPtr, coprecsize, operationrec);
6140  }//if
6141  tshrTmp = tshrElementptr + cexcForward;
6142  guard21 = fragrecptr.p->localkeylen - 1;
6143  for (tshrIndex = 0; tshrIndex <= guard21; tshrIndex++) {
6144  arrGuard(tshrIndex, 2);
6145  arrGuard(tshrTmp, 2048);
6146  clocalkey[tshrIndex] = excPageptr.p->word32[tshrTmp];
6147  tshrTmp = tshrTmp + cexcForward;
6148  }//for
6149  tidrPageindex = fragrecptr.p->expReceiveIndex;
6150  idrPageptr.i = fragrecptr.p->expReceivePageptr;
6151  ptrCheckGuard(idrPageptr, cpagesize, page8);
6152  tidrForward = fragrecptr.p->expReceiveForward;
6153  insertElement(signal);
6154  /* --------------------------------------------------------------------------------- */
6155  /* TAKE CARE OF RESULT FROM INSERT_ELEMENT. */
6156  /* --------------------------------------------------------------------------------- */
6157  fragrecptr.p->expReceiveIndex = tidrPageindex;
6158  fragrecptr.p->expReceivePageptr = idrPageptr.i;
6159  fragrecptr.p->expReceiveForward = tidrForward;
6160  if (tshrRemLen < tshrInc) {
6161  jam();
6162  sendSystemerror(signal, __LINE__);
6163  }//if
6164  tshrRemLen = tshrRemLen - tshrInc;
6165  if (tshrRemLen != 0) {
6166  jam();
6167  tshrElementptr = tshrTmp;
6168  goto SHR_LOOP;
6169  }//if
6170 }//Dbacc::shrinkcontainer()
6171 
6172 /* --------------------------------------------------------------------------------- */
6173 /* NEXTCONTAINERINFO_EXP */
6174 /* DESCRIPTION:THE CONTAINER HEAD WILL BE CHECKED TO CALCULATE INFORMATION */
6175 /* ABOUT NEXT CONTAINER IN THE BUCKET. */
6176 /* INPUT: CEXC_CONTAINERHEAD */
6177 /* CEXC_CONTAINERPTR */
6178 /* EXC_PAGEPTR */
6179 /* OUTPUT: */
6180 /* CEXC_PAGEINDEX (INDEX FROM WHICH PAGE INDEX CAN BE CALCULATED. */
6181 /* EXC_PAGEPTR (PAGE REFERENCE OF NEXT CONTAINER) */
6182 /* CEXC_FORWARD */
6183 /* --------------------------------------------------------------------------------- */
6184 void Dbacc::nextcontainerinfoExp(Signal* signal)
6185 {
6186  tnciNextSamePage = (cexcContainerhead >> 9) & 0x1; /* CHECK BIT FOR CHECKING WHERE */
6187  /* THE NEXT CONTAINER IS IN THE SAME PAGE */
6188  cexcPageindex = cexcContainerhead & 0x7f; /* NEXT CONTAINER PAGE INDEX 7 BITS */
6189  if (((cexcContainerhead >> 7) & 3) == ZLEFT) {
6190  jam();
6191  cexcForward = ZTRUE;
6192  } else if (((cexcContainerhead >> 7) & 3) == ZRIGHT) {
6193  jam();
6194  cexcForward = cminusOne;
6195  } else {
6196  jam();
6197  sendSystemerror(signal, __LINE__);
6198  cexcForward = 0; /* DUMMY FOR COMPILER */
6199  }//if
6200  if (tnciNextSamePage == ZFALSE) {
6201  jam();
6202  /* NEXT CONTAINER IS IN AN OVERFLOW PAGE */
6203  arrGuard(cexcContainerptr + 1, 2048);
6204  tnciTmp = excPageptr.p->word32[cexcContainerptr + 1];
6205  nciOverflowrangeptr.i = fragrecptr.p->overflowdir;
6206  ptrCheckGuard(nciOverflowrangeptr, cdirrangesize, dirRange);
6207  arrGuard((tnciTmp >> 8), 256);
6208  nciOverflowDirptr.i = nciOverflowrangeptr.p->dirArray[tnciTmp >> 8];
6209  ptrCheckGuard(nciOverflowDirptr, cdirarraysize, directoryarray);
6210  excPageptr.i = nciOverflowDirptr.p->pagep[tnciTmp & 0xff];
6211  ptrCheckGuard(excPageptr, cpagesize, page8);
6212  }//if
6213 }//Dbacc::nextcontainerinfoExp()
6214 
6215 void Dbacc::initFragAdd(Signal* signal,
6216  FragmentrecPtr regFragPtr)
6217 {
6218  const AccFragReq * const req = (AccFragReq*)&signal->theData[0];
6219  Uint32 lhFragBits = req->lhFragBits + 1;
6220  Uint32 minLoadFactor = (req->minLoadFactor * ZBUF_SIZE) / 100;
6221  Uint32 maxLoadFactor = (req->maxLoadFactor * ZBUF_SIZE) / 100;
6222  if (minLoadFactor >= maxLoadFactor) {
6223  jam();
6224  minLoadFactor = maxLoadFactor - 1;
6225  }//if
6226  regFragPtr.p->fragState = ACTIVEFRAG;
6227  // NOTE: next line must match calculation in Dblqh::execLQHFRAGREQ
6228  regFragPtr.p->myfid = req->fragId;
6229  regFragPtr.p->myTableId = req->tableId;
6230  ndbrequire(req->kValue == 6);
6231  regFragPtr.p->k = req->kValue; /* TK_SIZE = 6 IN THIS VERSION */
6232  regFragPtr.p->expandCounter = 0;
6233 
6240  regFragPtr.p->expandFlag = 0;
6241  regFragPtr.p->p = 0;
6242  regFragPtr.p->maxp = (1 << req->kValue) - 1;
6243  regFragPtr.p->minloadfactor = minLoadFactor;
6244  regFragPtr.p->maxloadfactor = maxLoadFactor;
6245  regFragPtr.p->slack = (regFragPtr.p->maxp + 1) * maxLoadFactor;
6246  regFragPtr.p->lhfragbits = lhFragBits;
6247  regFragPtr.p->lhdirbits = 0;
6248  regFragPtr.p->hashcheckbit = 0; //lhFragBits;
6249  regFragPtr.p->localkeylen = req->localKeyLen;
6250  regFragPtr.p->nodetype = (req->reqInfo >> 4) & 0x3;
6251  regFragPtr.p->lastOverIndex = 0;
6252  regFragPtr.p->dirsize = 1;
6253  regFragPtr.p->keyLength = req->keyLength;
6254  ndbrequire(req->keyLength != 0);
6255  regFragPtr.p->elementLength = ZELEM_HEAD_SIZE + regFragPtr.p->localkeylen;
6256  Uint32 Tmp1 = (regFragPtr.p->maxp + 1) + regFragPtr.p->p;
6257  Uint32 Tmp2 = regFragPtr.p->maxloadfactor - regFragPtr.p->minloadfactor;
6258  Tmp2 = Tmp1 * Tmp2;
6259  regFragPtr.p->slackCheck = Tmp2;
6260  regFragPtr.p->mytabptr = req->tableId;
6261  regFragPtr.p->roothashcheck = req->kValue + req->lhFragBits;
6262  regFragPtr.p->noOfElements = 0;
6263  regFragPtr.p->m_commit_count = 0; // stable results
6264  for (Uint32 i = 0; i < MAX_PARALLEL_SCANS_PER_FRAG; i++) {
6265  regFragPtr.p->scan[i] = RNIL;
6266  }//for
6267 
6268  Uint32 hasCharAttr = g_key_descriptor_pool.getPtr(req->tableId)->hasCharAttr;
6269  regFragPtr.p->hasCharAttr = hasCharAttr;
6270 }//Dbacc::initFragAdd()
6271 
6272 void Dbacc::initFragGeneral(FragmentrecPtr regFragPtr)
6273 {
6274  regFragPtr.p->directory = RNIL;
6275  regFragPtr.p->overflowdir = RNIL;
6276  regFragPtr.p->firstOverflowRec = RNIL;
6277  regFragPtr.p->lastOverflowRec = RNIL;
6278  regFragPtr.p->lockOwnersList = RNIL;
6279  regFragPtr.p->firstFreeDirindexRec = RNIL;
6280 
6281  regFragPtr.p->activeDataPage = 0;
6282  regFragPtr.p->hasCharAttr = ZFALSE;
6283  regFragPtr.p->dirRangeFull = ZFALSE;
6284  regFragPtr.p->nextAllocPage = 0;
6285  regFragPtr.p->fragState = FREEFRAG;
6286 }//Dbacc::initFragGeneral()
6287 
6288 
6289 void
6290 Dbacc::releaseLogicalPage(Fragmentrec * fragP, Uint32 logicalPageId){
6291  Ptr<struct DirRange> dirRangePtr;
6292  dirRangePtr.i = fragP->directory;
6293  ptrCheckGuard(dirRangePtr, cdirrangesize, dirRange);
6294 
6295  const Uint32 lp1 = logicalPageId >> 8;
6296  const Uint32 lp2 = logicalPageId & 0xFF;
6297  ndbrequire(lp1 < 256);
6298 
6299  Ptr<struct Directoryarray> dirArrPtr;
6300  dirArrPtr.i = dirRangePtr.p->dirArray[lp1];
6301  ptrCheckGuard(dirArrPtr, cdirarraysize, directoryarray);
6302 
6303  const Uint32 physicalPageId = dirArrPtr.p->pagep[lp2];
6304 
6305  rpPageptr.i = physicalPageId;
6306  ptrCheckGuard(rpPageptr, cpagesize, page8);
6307  releasePage(0);
6308 
6309  dirArrPtr.p->pagep[lp2] = RNIL;
6310 }
6311 
6312 void Dbacc::execACC_SCANREQ(Signal* signal)
6313 {
6314  jamEntry();
6315  AccScanReq * req = (AccScanReq*)&signal->theData[0];
6316  tuserptr = req->senderData;
6317  tuserblockref = req->senderRef;
6318  tabptr.i = req->tableId;
6319  tfid = req->fragmentNo;
6320  tscanFlag = req->requestInfo;
6321  tscanTrid1 = req->transId1;
6322  tscanTrid2 = req->transId2;
6323 
6324  tresult = 0;
6325  ptrCheckGuard(tabptr, ctablesize, tabrec);
6326  ndbrequire(getfragmentrec(signal, fragrecptr, tfid));
6327 
6328  Uint32 i;
6329  for (i = 0; i < MAX_PARALLEL_SCANS_PER_FRAG; i++) {
6330  jam();
6331  if (fragrecptr.p->scan[i] == RNIL) {
6332  jam();
6333  break;
6334  }
6335  }
6336  ndbrequire(i != MAX_PARALLEL_SCANS_PER_FRAG);
6337  ndbrequire(cfirstFreeScanRec != RNIL);
6338  seizeScanRec(signal);
6339 
6340  fragrecptr.p->scan[i] = scanPtr.i;
6341  scanPtr.p->scanBucketState = ScanRec::FIRST_LAP;
6342  scanPtr.p->scanLockMode = AccScanReq::getLockMode(tscanFlag);
6343  scanPtr.p->scanReadCommittedFlag = AccScanReq::getReadCommittedFlag(tscanFlag);
6344 
6345  /* TWELVE BITS OF THE ELEMENT HEAD ARE SCAN */
6346  /* CHECK BITS. THE MASK NOTES WHICH BIT IS */
6347  /* ALLOCATED FOR THE ACTIVE SCAN */
6348  scanPtr.p->scanMask = 1 << i;
6349  scanPtr.p->scanUserptr = tuserptr;
6350  scanPtr.p->scanUserblockref = tuserblockref;
6351  scanPtr.p->scanTrid1 = tscanTrid1;
6352  scanPtr.p->scanTrid2 = tscanTrid2;
6353  scanPtr.p->scanLockHeld = 0;
6354  scanPtr.p->scanOpsAllocated = 0;
6355  scanPtr.p->scanFirstActiveOp = RNIL;
6356  scanPtr.p->scanFirstQueuedOp = RNIL;
6357  scanPtr.p->scanLastQueuedOp = RNIL;
6358  scanPtr.p->scanFirstLockedOp = RNIL;
6359  scanPtr.p->scanLastLockedOp = RNIL;
6360  scanPtr.p->scanState = ScanRec::WAIT_NEXT;
6361  initScanFragmentPart(signal);
6362 
6363  /* ************************ */
6364  /* ACC_SCANCONF */
6365  /* ************************ */
6366  signal->theData[0] = scanPtr.p->scanUserptr;
6367  signal->theData[1] = scanPtr.i;
6368  signal->theData[2] = 1; /* NR OF LOCAL FRAGMENT */
6369  signal->theData[3] = fragrecptr.p->fragmentid;
6370  signal->theData[4] = RNIL;
6371  signal->theData[7] = AccScanConf::ZNOT_EMPTY_FRAGMENT;
6372  sendSignal(scanPtr.p->scanUserblockref, GSN_ACC_SCANCONF, signal, 8, JBB);
6373  /* NOT EMPTY FRAGMENT */
6374  return;
6375 }//Dbacc::execACC_SCANREQ()
6376 
6377 /* ******************--------------------------------------------------------------- */
6378 /* NEXT_SCANREQ REQUEST FOR NEXT ELEMENT OF */
6379 /* ******************------------------------------+ A FRAGMENT. */
6380 /* SENDER: LQH, LEVEL B */
6381 void Dbacc::execNEXT_SCANREQ(Signal* signal)
6382 {
6383  Uint32 tscanNextFlag;
6384  jamEntry();
6385  scanPtr.i = signal->theData[0];
6386  operationRecPtr.i = signal->theData[1];
6387  tscanNextFlag = signal->theData[2];
6388  /* ------------------------------------------ */
6389  /* 1 = ZCOPY_NEXT GET NEXT ELEMENT */
6390  /* 2 = ZCOPY_NEXT_COMMIT COMMIT THE */
6391  /* ACTIVE ELEMENT AND GET THE NEXT ONE */
6392  /* 3 = ZCOPY_COMMIT COMMIT THE ACTIVE ELEMENT */
6393  /* 4 = ZCOPY_REPEAT GET THE ACTIVE ELEMENT */
6394  /* 5 = ZCOPY_ABORT RELOCK THE ACTIVE ELEMENT */
6395  /* 6 = ZCOPY_CLOSE THE SCAN PROCESS IS READY */
6396  /* ------------------------------------------ */
6397  tresult = 0;
6398  ptrCheckGuard(scanPtr, cscanRecSize, scanRec);
6399  ndbrequire(scanPtr.p->scanState == ScanRec::WAIT_NEXT);
6400 
6401  switch (tscanNextFlag) {
6402  case NextScanReq::ZSCAN_NEXT:
6403  jam();
6404  /*empty*/;
6405  break;
6406  case NextScanReq::ZSCAN_NEXT_COMMIT:
6407  case NextScanReq::ZSCAN_COMMIT:
6408  jam();
6409  /* --------------------------------------------------------------------- */
6410  /* COMMIT ACTIVE OPERATION.
6411  * SEND NEXT SCAN ELEMENT IF IT IS ZCOPY_NEXT_COMMIT.
6412  * --------------------------------------------------------------------- */
6413  ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
6414  fragrecptr.i = operationRecPtr.p->fragptr;
6415  ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
6416  if (!scanPtr.p->scanReadCommittedFlag) {
6417  commitOperation(signal);
6418  }//if
6419  operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
6420  takeOutActiveScanOp(signal);
6421  releaseOpRec(signal);
6422  scanPtr.p->scanOpsAllocated--;
6423  if (tscanNextFlag == NextScanReq::ZSCAN_COMMIT) {
6424  jam();
6425  signal->theData[0] = scanPtr.p->scanUserptr;
6426  Uint32 blockNo = refToMain(scanPtr.p->scanUserblockref);
6427  EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 1);
6428  return;
6429  }//if
6430  break;
6431  case NextScanReq::ZSCAN_CLOSE:
6432  jam();
6433  fragrecptr.i = scanPtr.p->activeLocalFrag;
6434  ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
6435  /* ---------------------------------------------------------------------
6436  * THE SCAN PROCESS IS FINISHED. RELOCK ALL LOCKED EL.
6437  * RELESE ALL INVOLVED REC.
6438  * ------------------------------------------------------------------- */
6439  releaseScanLab(signal);
6440  return;
6441  break;
6442  default:
6443  ndbrequire(false);
6444  break;
6445  }//switch
6446  signal->theData[0] = scanPtr.i;
6447  signal->theData[1] = AccCheckScan::ZNOT_CHECK_LCP_STOP;
6448  execACC_CHECK_SCAN(signal);
6449  return;
6450 }//Dbacc::execNEXT_SCANREQ()
6451 
6452 void Dbacc::checkNextBucketLab(Signal* signal)
6453 {
6454  DirRangePtr cscDirRangePtr;
6455  DirectoryarrayPtr cscDirptr;
6456  DirectoryarrayPtr tnsDirptr;
6457  Page8Ptr nsPageptr;
6458  Page8Ptr cscPageidptr;
6459  Page8Ptr gnsPageidptr;
6460  Page8Ptr tnsPageidptr;
6461  Uint32 tnsElementptr;
6462  Uint32 tnsContainerptr;
6463  Uint32 tnsIsLocked;
6464  Uint32 tnsTmp1;
6465  Uint32 tnsTmp2;
6466  Uint32 tnsCopyIndex1;
6467  Uint32 tnsCopyIndex2;
6468  Uint32 tnsCopyDir;
6469 
6470  tnsCopyDir = scanPtr.p->nextBucketIndex >> fragrecptr.p->k;
6471  tnsCopyIndex1 = tnsCopyDir >> 8;
6472  tnsCopyIndex2 = tnsCopyDir & 0xff;
6473  arrGuard(tnsCopyIndex1, 256);
6474  tnsDirptr.i = gnsDirRangePtr.p->dirArray[tnsCopyIndex1];
6475  ptrCheckGuard(tnsDirptr, cdirarraysize, directoryarray);
6476  tnsPageidptr.i = tnsDirptr.p->pagep[tnsCopyIndex2];
6477  ptrCheckGuard(tnsPageidptr, cpagesize, page8);
6478  gnsPageidptr.i = tnsPageidptr.i;
6479  gnsPageidptr.p = tnsPageidptr.p;
6480  tnsTmp1 = (1 << fragrecptr.p->k) - 1;
6481  tgsePageindex = scanPtr.p->nextBucketIndex & tnsTmp1;
6482  gsePageidptr.i = gnsPageidptr.i;
6483  gsePageidptr.p = gnsPageidptr.p;
6484  if (!getScanElement(signal)) {
6485  scanPtr.p->nextBucketIndex++;
6486  if (scanPtr.p->scanBucketState == ScanRec::SECOND_LAP) {
6487  if (scanPtr.p->nextBucketIndex > scanPtr.p->maxBucketIndexToRescan) {
6488  /* ---------------------------------------------------------------- */
6489  // We have finished the rescan phase.
6490  // We are ready to proceed with the next fragment part.
6491  /* ---------------------------------------------------------------- */
6492  jam();
6493  checkNextFragmentLab(signal);
6494  return;
6495  }//if
6496  } else if (scanPtr.p->scanBucketState == ScanRec::FIRST_LAP) {
6497  if ((fragrecptr.p->p + fragrecptr.p->maxp) < scanPtr.p->nextBucketIndex) {
6498  /* ---------------------------------------------------------------- */
6499  // All buckets have been scanned a first time.
6500  /* ---------------------------------------------------------------- */
6501  if (scanPtr.p->minBucketIndexToRescan == 0xFFFFFFFF) {
6502  jam();
6503  /* -------------------------------------------------------------- */
6504  // We have not had any merges behind the scan.
6505  // Thus it is not necessary to perform any rescan any buckets
6506  // and we can proceed immediately with the next fragment part.
6507  /* --------------------------------------------------------------- */
6508  checkNextFragmentLab(signal);
6509  return;
6510  } else {
6511  jam();
6512  /* --------------------------------------------------------------------------------- */
6513  // Some buckets are in the need of rescanning due to merges that have moved records
6514  // from in front of the scan to behind the scan. During the merges we kept track of
6515  // which buckets that need a rescan. We start with the minimum and end with maximum.
6516  /* --------------------------------------------------------------------------------- */
6517  scanPtr.p->nextBucketIndex = scanPtr.p->minBucketIndexToRescan;
6518  scanPtr.p->scanBucketState = ScanRec::SECOND_LAP;
6519  if (scanPtr.p->maxBucketIndexToRescan > (fragrecptr.p->p + fragrecptr.p->maxp)) {
6520  jam();
6521  /* --------------------------------------------------------------------------------- */
6522  // If we have had so many merges that the maximum is bigger than the number of buckets
6523  // then we will simply satisfy ourselves with scanning to the end. This can only happen
6524  // after bringing down the total of buckets to less than half and the minimum should
6525  // be 0 otherwise there is some problem.
6526  /* --------------------------------------------------------------------------------- */
6527  if (scanPtr.p->minBucketIndexToRescan != 0) {
6528  jam();
6529  sendSystemerror(signal, __LINE__);
6530  return;
6531  }//if
6532  scanPtr.p->maxBucketIndexToRescan = fragrecptr.p->p + fragrecptr.p->maxp;
6533  }//if
6534  }//if
6535  }//if
6536  }//if
6537  if ((scanPtr.p->scanBucketState == ScanRec::FIRST_LAP) &&
6538  (scanPtr.p->nextBucketIndex <= scanPtr.p->startNoOfBuckets)) {
6539  /* --------------------------------------------------------------------------------- */
6540  // We will only reset the scan indicator on the buckets that existed at the start of the
6541  // scan. The others will be handled by the split and merge code.
6542  /* --------------------------------------------------------------------------------- */
6543  tnsTmp2 = (1 << fragrecptr.p->k) - 1;
6544  trsbPageindex = scanPtr.p->nextBucketIndex & tnsTmp2;
6545  if (trsbPageindex != 0) {
6546  jam();
6547  rsbPageidptr.i = gnsPageidptr.i;
6548  rsbPageidptr.p = gnsPageidptr.p;
6549  } else {
6550  jam();
6551  cscDirRangePtr.i = fragrecptr.p->directory;
6552  tmpP = scanPtr.p->nextBucketIndex >> fragrecptr.p->k;
6553  tmpP2 = tmpP >> 8;
6554  tmpP = tmpP & 0xff;
6555  ptrCheckGuard(cscDirRangePtr, cdirrangesize, dirRange);
6556  arrGuard(tmpP2, 256);
6557  cscDirptr.i = cscDirRangePtr.p->dirArray[tmpP2];
6558  ptrCheckGuard(cscDirptr, cdirarraysize, directoryarray);
6559  cscPageidptr.i = cscDirptr.p->pagep[tmpP];
6560  ptrCheckGuard(cscPageidptr, cpagesize, page8);
6561  tmp1 = (1 << fragrecptr.p->k) - 1;
6562  trsbPageindex = scanPtr.p->nextBucketIndex & tmp1;
6563  rsbPageidptr.i = cscPageidptr.i;
6564  rsbPageidptr.p = cscPageidptr.p;
6565  }//if
6566  releaseScanBucket(signal);
6567  }//if
6568  signal->theData[0] = scanPtr.i;
6569  signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
6570  sendSignal(cownBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB);
6571  return;
6572  }//if
6573  /* ----------------------------------------------------------------------- */
6574  /* AN ELEMENT WHICH HAVE NOT BEEN SCANNED WAS FOUND. WE WILL PREPARE IT */
6575  /* TO BE SENT TO THE LQH BLOCK FOR FURTHER PROCESSING. */
6576  /* WE ASSUME THERE ARE OPERATION RECORDS AVAILABLE SINCE LQH SHOULD HAVE*/
6577  /* GUARANTEED THAT THROUGH EARLY BOOKING. */
6578  /* ----------------------------------------------------------------------- */
6579  tnsIsLocked = tgseIsLocked;
6580  tnsElementptr = tgseElementptr;
6581  tnsContainerptr = tgseContainerptr;
6582  nsPageptr.i = gsePageidptr.i;
6583  nsPageptr.p = gsePageidptr.p;
6584  seizeOpRec(signal);
6585  tisoIsforward = tgseIsforward;
6586  tisoContainerptr = tnsContainerptr;
6587  tisoElementptr = tnsElementptr;
6588  isoPageptr.i = nsPageptr.i;
6589  isoPageptr.p = nsPageptr.p;
6590  initScanOpRec(signal);
6591 
6592  if (!tnsIsLocked){
6593  if (!scanPtr.p->scanReadCommittedFlag) {
6594  jam();
6595  slPageidptr = nsPageptr;
6596  tslElementptr = tnsElementptr;
6597  setlock(signal);
6598  insertLockOwnersList(signal, operationRecPtr);
6599  operationRecPtr.p->m_op_bits |=
6600  Operationrec::OP_STATE_RUNNING | Operationrec::OP_RUN_QUEUE;
6601  }//if
6602  } else {
6603  arrGuard(tnsElementptr, 2048);
6604  queOperPtr.i =
6605  ElementHeader::getOpPtrI(nsPageptr.p->word32[tnsElementptr]);
6606  ptrCheckGuard(queOperPtr, coprecsize, operationrec);
6607  if (queOperPtr.p->m_op_bits & Operationrec::OP_ELEMENT_DISAPPEARED ||
6608  Local_key::isInvalid(queOperPtr.p->localdata[0],
6609  queOperPtr.p->localdata[1]))
6610  {
6611  jam();
6612  /* ------------------------------------------------------------------ */
6613  // If the lock owner indicates the element is disappeared then
6614  // we will not report this tuple. We will continue with the next tuple.
6615  /* ------------------------------------------------------------------ */
6616  operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
6617  releaseOpRec(signal);
6618  scanPtr.p->scanOpsAllocated--;
6619  signal->theData[0] = scanPtr.i;
6620  signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
6621  sendSignal(cownBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB);
6622  return;
6623  }//if
6624  if (!scanPtr.p->scanReadCommittedFlag) {
6625  Uint32 return_result;
6626  if (scanPtr.p->scanLockMode == ZREADLOCK) {
6627  jam();
6628  return_result = placeReadInLockQueue(queOperPtr);
6629  } else {
6630  jam();
6631  return_result = placeWriteInLockQueue(queOperPtr);
6632  }//if
6633  if (return_result == ZSERIAL_QUEUE) {
6634  /* -----------------------------------------------------------------
6635  * WE PLACED THE OPERATION INTO A SERIAL QUEUE AND THUS WE HAVE TO
6636  * WAIT FOR THE LOCK TO BE RELEASED. WE CONTINUE WITH THE NEXT ELEMENT
6637  * ----------------------------------------------------------------- */
6638  putOpScanLockQue(); /* PUT THE OP IN A QUE IN THE SCAN REC */
6639  signal->theData[0] = scanPtr.i;
6640  signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
6641  sendSignal(cownBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB);
6642  return;
6643  } else if (return_result != ZPARALLEL_QUEUE) {
6644  jam();
6645  /* ----------------------------------------------------------------- */
6646  // The tuple is either not committed yet or a delete in
6647  // the same transaction (not possible here since we are a scan).
6648  // Thus we simply continue with the next tuple.
6649  /* ----------------------------------------------------------------- */
6650  operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
6651  releaseOpRec(signal);
6652  scanPtr.p->scanOpsAllocated--;
6653  signal->theData[0] = scanPtr.i;
6654  signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
6655  sendSignal(cownBlockref, GSN_ACC_CHECK_SCAN, signal, 2, JBB);
6656  return;
6657  }//if
6658  ndbassert(return_result == ZPARALLEL_QUEUE);
6659  }//if
6660  }//if
6661  /* ----------------------------------------------------------------------- */
6662  // Committed read proceed without caring for locks immediately
6663  // down here except when the tuple was deleted permanently
6664  // and no new operation has inserted it again.
6665  /* ----------------------------------------------------------------------- */
6666  putActiveScanOp(signal);
6667  sendNextScanConf(signal);
6668  return;
6669 }//Dbacc::checkNextBucketLab()
6670 
6671 
6672 void Dbacc::checkNextFragmentLab(Signal* signal)
6673 {
6674  scanPtr.p->scanBucketState = ScanRec::SCAN_COMPLETED;
6675  // The scan is completed. ACC_CHECK_SCAN will perform all the necessary
6676  // checks to see
6677  // what the next step is.
6678  signal->theData[0] = scanPtr.i;
6679  signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
6680  execACC_CHECK_SCAN(signal);
6681  return;
6682 }//Dbacc::checkNextFragmentLab()
6683 
6684 void Dbacc::initScanFragmentPart(Signal* signal)
6685 {
6686  DirRangePtr cnfDirRangePtr;
6687  DirectoryarrayPtr cnfDirptr;
6688  Page8Ptr cnfPageidptr;
6689  /* ----------------------------------------------------------------------- */
6690  // Set the active fragment part.
6691  // Set the current bucket scanned to the first.
6692  // Start with the first lap.
6693  // Remember the number of buckets at start of the scan.
6694  // Set the minimum and maximum to values that will always be smaller and
6695  // larger than.
6696  // Reset the scan indicator on the first bucket.
6697  /* ----------------------------------------------------------------------- */
6698  scanPtr.p->activeLocalFrag = fragrecptr.i;
6699  scanPtr.p->nextBucketIndex = 0; /* INDEX OF SCAN BUCKET */
6700  scanPtr.p->scanBucketState = ScanRec::FIRST_LAP;
6701  scanPtr.p->startNoOfBuckets = fragrecptr.p->p + fragrecptr.p->maxp;
6702  scanPtr.p->minBucketIndexToRescan = 0xFFFFFFFF;
6703  scanPtr.p->maxBucketIndexToRescan = 0;
6704  cnfDirRangePtr.i = fragrecptr.p->directory;
6705  ptrCheckGuard(cnfDirRangePtr, cdirrangesize, dirRange);
6706  cnfDirptr.i = cnfDirRangePtr.p->dirArray[0];
6707  ptrCheckGuard(cnfDirptr, cdirarraysize, directoryarray);
6708  cnfPageidptr.i = cnfDirptr.p->pagep[0];
6709  ptrCheckGuard(cnfPageidptr, cpagesize, page8);
6710  trsbPageindex = scanPtr.p->nextBucketIndex & ((1 << fragrecptr.p->k) - 1);
6711  rsbPageidptr.i = cnfPageidptr.i;
6712  rsbPageidptr.p = cnfPageidptr.p;
6713  releaseScanBucket(signal);
6714 }//Dbacc::initScanFragmentPart()
6715 
6716 /* -------------------------------------------------------------------------
6717  * FLAG = 6 = ZCOPY_CLOSE THE SCAN PROCESS IS READY OR ABORTED.
6718  * ALL OPERATION IN THE ACTIVE OR WAIT QUEUE ARE RELEASED,
6719  * SCAN FLAG OF ROOT FRAG IS RESET AND THE SCAN RECORD IS RELEASED.
6720  * ------------------------------------------------------------------------ */
6721 void Dbacc::releaseScanLab(Signal* signal)
6722 {
6723  releaseAndCommitActiveOps(signal);
6724  releaseAndCommitQueuedOps(signal);
6725  releaseAndAbortLockedOps(signal);
6726 
6727  fragrecptr.i = scanPtr.p->activeLocalFrag;
6728  ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
6729  for (tmp = 0; tmp < MAX_PARALLEL_SCANS_PER_FRAG; tmp++) {
6730  jam();
6731  if (fragrecptr.p->scan[tmp] == scanPtr.i) {
6732  jam();
6733  fragrecptr.p->scan[tmp] = RNIL;
6734  }//if
6735  }//for
6736  // Stops the heartbeat.
6737  signal->theData[0] = scanPtr.p->scanUserptr;
6738  signal->theData[1] = RNIL;
6739  signal->theData[2] = RNIL;
6740  sendSignal(scanPtr.p->scanUserblockref, GSN_NEXT_SCANCONF, signal, 3, JBB);
6741  releaseScanRec(signal);
6742  return;
6743 }//Dbacc::releaseScanLab()
6744 
6745 
6746 void Dbacc::releaseAndCommitActiveOps(Signal* signal)
6747 {
6748  OperationrecPtr trsoOperPtr;
6749  operationRecPtr.i = scanPtr.p->scanFirstActiveOp;
6750  while (operationRecPtr.i != RNIL) {
6751  jam();
6752  ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
6753  trsoOperPtr.i = operationRecPtr.p->nextOp;
6754  fragrecptr.i = operationRecPtr.p->fragptr;
6755  ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
6756  if (!scanPtr.p->scanReadCommittedFlag) {
6757  jam();
6758  if ((operationRecPtr.p->m_op_bits & Operationrec::OP_STATE_MASK) ==
6759  Operationrec::OP_STATE_EXECUTED)
6760  {
6761  commitOperation(signal);
6762  }
6763  else
6764  {
6765  abortOperation(signal);
6766  }
6767  }//if
6768  operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
6769  takeOutActiveScanOp(signal);
6770  releaseOpRec(signal);
6771  scanPtr.p->scanOpsAllocated--;
6772  operationRecPtr.i = trsoOperPtr.i;
6773  }//if
6774 }//Dbacc::releaseAndCommitActiveOps()
6775 
6776 
6777 void Dbacc::releaseAndCommitQueuedOps(Signal* signal)
6778 {
6779  OperationrecPtr trsoOperPtr;
6780  operationRecPtr.i = scanPtr.p->scanFirstQueuedOp;
6781  while (operationRecPtr.i != RNIL) {
6782  jam();
6783  ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
6784  trsoOperPtr.i = operationRecPtr.p->nextOp;
6785  fragrecptr.i = operationRecPtr.p->fragptr;
6786  ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
6787  if (!scanPtr.p->scanReadCommittedFlag) {
6788  jam();
6789  if ((operationRecPtr.p->m_op_bits & Operationrec::OP_STATE_MASK) ==
6790  Operationrec::OP_STATE_EXECUTED)
6791  {
6792  commitOperation(signal);
6793  }
6794  else
6795  {
6796  abortOperation(signal);
6797  }
6798  }//if
6799  operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
6800  takeOutReadyScanQueue(signal);
6801  releaseOpRec(signal);
6802  scanPtr.p->scanOpsAllocated--;
6803  operationRecPtr.i = trsoOperPtr.i;
6804  }//if
6805 }//Dbacc::releaseAndCommitQueuedOps()
6806 
6807 void Dbacc::releaseAndAbortLockedOps(Signal* signal) {
6808 
6809  OperationrecPtr trsoOperPtr;
6810  operationRecPtr.i = scanPtr.p->scanFirstLockedOp;
6811  while (operationRecPtr.i != RNIL) {
6812  jam();
6813  ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
6814  trsoOperPtr.i = operationRecPtr.p->nextOp;
6815  fragrecptr.i = operationRecPtr.p->fragptr;
6816  ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
6817  if (!scanPtr.p->scanReadCommittedFlag) {
6818  jam();
6819  abortOperation(signal);
6820  }//if
6821  takeOutScanLockQueue(scanPtr.i);
6822  operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
6823  releaseOpRec(signal);
6824  scanPtr.p->scanOpsAllocated--;
6825  operationRecPtr.i = trsoOperPtr.i;
6826  }//if
6827 }//Dbacc::releaseAndAbortLockedOps()
6828 
6829 /* 3.18.3 ACC_CHECK_SCAN */
6830 /* ******************--------------------------------------------------------------- */
6831 /* ACC_CHECK_SCAN */
6832 /* ENTER ACC_CHECK_SCAN WITH */
6833 /* SCAN_PTR */
6834 /* ******************--------------------------------------------------------------- */
6835 /* ******************--------------------------------------------------------------- */
6836 /* ACC_CHECK_SCAN */
6837 /* ******************------------------------------+ */
6838 void Dbacc::execACC_CHECK_SCAN(Signal* signal)
6839 {
6840  Uint32 TcheckLcpStop;
6841  jamEntry();
6842  scanPtr.i = signal->theData[0];
6843  TcheckLcpStop = signal->theData[1];
6844  ptrCheckGuard(scanPtr, cscanRecSize, scanRec);
6845  while (scanPtr.p->scanFirstQueuedOp != RNIL) {
6846  jam();
6847  //---------------------------------------------------------------------
6848  // An operation has been released from the lock queue.
6849  // We are in the parallel queue of this tuple. We are
6850  // ready to report the tuple now.
6851  //------------------------------------------------------------------------
6852  operationRecPtr.i = scanPtr.p->scanFirstQueuedOp;
6853  ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
6854  takeOutReadyScanQueue(signal);
6855  fragrecptr.i = operationRecPtr.p->fragptr;
6856  ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
6857  if (operationRecPtr.p->m_op_bits & Operationrec::OP_ELEMENT_DISAPPEARED)
6858  {
6859  jam();
6860  abortOperation(signal);
6861  operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
6862  releaseOpRec(signal);
6863  scanPtr.p->scanOpsAllocated--;
6864  continue;
6865  }//if
6866  putActiveScanOp(signal);
6867  sendNextScanConf(signal);
6868  return;
6869  }//while
6870 
6871 
6872  if ((scanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED) &&
6873  (scanPtr.p->scanLockHeld == 0)) {
6874  jam();
6875  //----------------------------------------------------------------------------
6876  // The scan is now completed and there are no more locks outstanding. Thus we
6877  // we will report the scan as completed to LQH.
6878  //----------------------------------------------------------------------------
6879  signal->theData[0] = scanPtr.p->scanUserptr;
6880  signal->theData[1] = RNIL;
6881  signal->theData[2] = RNIL;
6882  sendSignal(scanPtr.p->scanUserblockref, GSN_NEXT_SCANCONF, signal, 3, JBB);
6883  return;
6884  }//if
6885  if (TcheckLcpStop == AccCheckScan::ZCHECK_LCP_STOP) {
6886  //---------------------------------------------------------------------------
6887  // To ensure that the block of the fragment occurring at the start of a local
6888  // checkpoint is not held for too long we insert a release and reacquiring of
6889  // that lock here. This is performed in LQH. If we are blocked or if we have
6890  // requested a sleep then we will receive RNIL in the returning signal word.
6891  //---------------------------------------------------------------------------
6892  signal->theData[0] = scanPtr.p->scanUserptr;
6893  signal->theData[1] =
6894  ((scanPtr.p->scanLockHeld >= ZSCAN_MAX_LOCK) ||
6895  (scanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED));
6896  EXECUTE_DIRECT(DBLQH, GSN_CHECK_LCP_STOP, signal, 2);
6897  jamEntry();
6898  if (signal->theData[0] == RNIL) {
6899  jam();
6900  return;
6901  }//if
6902  }//if
6908  if ((scanPtr.p->scanLockHeld >= ZSCAN_MAX_LOCK) ||
6909  (cfreeopRec == RNIL) ||
6910  ((scanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED) &&
6911  (scanPtr.p->scanLockHeld > 0))) {
6912  jam();
6913  signal->theData[0] = scanPtr.p->scanUserptr;
6914  signal->theData[1] = RNIL; // No operation is returned
6915  signal->theData[2] = 512; // MASV
6916  sendSignal(scanPtr.p->scanUserblockref, GSN_NEXT_SCANCONF, signal, 3, JBB);
6917  return;
6918  }
6919  if (scanPtr.p->scanBucketState == ScanRec::SCAN_COMPLETED) {
6920  jam();
6921  signal->theData[0] = scanPtr.i;
6922  signal->theData[1] = AccCheckScan::ZCHECK_LCP_STOP;
6923  execACC_CHECK_SCAN(signal);
6924  return;
6925  }//if
6926 
6927  fragrecptr.i = scanPtr.p->activeLocalFrag;
6928  ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
6929  gnsDirRangePtr.i = fragrecptr.p->directory;
6930  ptrCheckGuard(gnsDirRangePtr, cdirrangesize, dirRange);
6931  checkNextBucketLab(signal);
6932  return;
6933 }//Dbacc::execACC_CHECK_SCAN()
6934 
6935 /* ******************---------------------------------------------------- */
6936 /* ACC_TO_REQ PERFORM A TAKE OVER */
6937 /* ******************-------------------+ */
6938 /* SENDER: LQH, LEVEL B */
6939 void Dbacc::execACC_TO_REQ(Signal* signal)
6940 {
6941  OperationrecPtr tatrOpPtr;
6942 
6943  jamEntry();
6944  tatrOpPtr.i = signal->theData[1]; /* OPER PTR OF ACC */
6945  ptrCheckGuard(tatrOpPtr, coprecsize, operationrec);
6946  if ((tatrOpPtr.p->m_op_bits & Operationrec::OP_MASK) == ZSCAN_OP)
6947  {
6948  tatrOpPtr.p->transId1 = signal->theData[2];
6949  tatrOpPtr.p->transId2 = signal->theData[3];
6950  validate_lock_queue(tatrOpPtr);
6951  } else {
6952  jam();
6953  signal->theData[0] = cminusOne;
6954  signal->theData[1] = ZTO_OP_STATE_ERROR;
6955  }//if
6956  return;
6957 }//Dbacc::execACC_TO_REQ()
6958 
6959 /* --------------------------------------------------------------------------------- */
6960 /* CONTAINERINFO */
6961 /* INPUT: */
6962 /* CI_PAGEIDPTR (PAGE POINTER WHERE CONTAINER RESIDES) */
6963 /* TCI_PAGEINDEX (INDEX OF CONTAINER, USED TO CALCULATE PAGE INDEX) */
6964 /* TCI_ISFORWARD (DIRECTION OF CONTAINER FORWARD OR BACKWARD) */
6965 /* */
6966 /* OUTPUT: */
6967 /* TCI_CONTAINERPTR (A POINTER TO THE HEAD OF THE CONTAINER) */
6968 /* TCI_CONTAINERLEN (LENGTH OF THE CONTAINER */
6969 /* TCI_CONTAINERHEAD (THE HEADER OF THE CONTAINER) */
6970 /* */
6971 /* DESCRIPTION: THE ADDRESS OF THE CONTAINER WILL BE CALCULATED AND */
6972 /* ALL INFORMATION ABOUT THE CONTAINER WILL BE READ */
6973 /* --------------------------------------------------------------------------------- */
6974 void Dbacc::containerinfo(Signal* signal)
6975 {
6976  tciContainerptr = (tciPageindex << ZSHIFT_PLUS) - (tciPageindex << ZSHIFT_MINUS);
6977  if (tciIsforward == ZTRUE) {
6978  jam();
6979  tciContainerptr = tciContainerptr + ZHEAD_SIZE;
6980  } else {
6981  jam();
6982  tciContainerptr = ((tciContainerptr + ZHEAD_SIZE) + ZBUF_SIZE) - ZCON_HEAD_SIZE;
6983  }//if
6984  arrGuard(tciContainerptr, 2048);
6985  tciContainerhead = ciPageidptr.p->word32[tciContainerptr];
6986  tciContainerlen = tciContainerhead >> 26;
6987 }//Dbacc::containerinfo()
6988 
6989 /* --------------------------------------------------------------------------------- */
6990 /* GET_SCAN_ELEMENT */
6991 /* INPUT: GSE_PAGEIDPTR */
6992 /* TGSE_PAGEINDEX */
6993 /* OUTPUT: TGSE_IS_LOCKED (IF TRESULT /= ZFALSE) */
6994 /* GSE_PAGEIDPTR */
6995 /* TGSE_PAGEINDEX */
6996 /* --------------------------------------------------------------------------------- */
6997 bool Dbacc::getScanElement(Signal* signal)
6998 {
6999  tgseIsforward = ZTRUE;
7000  NEXTSEARCH_SCAN_LOOP:
7001  ciPageidptr.i = gsePageidptr.i;
7002  ciPageidptr.p = gsePageidptr.p;
7003  tciPageindex = tgsePageindex;
7004  tciIsforward = tgseIsforward;
7005  containerinfo(signal);
7006  sscPageidptr.i = gsePageidptr.i;
7007  sscPageidptr.p = gsePageidptr.p;
7008  tsscContainerlen = tciContainerlen;
7009  tsscContainerptr = tciContainerptr;
7010  tsscIsforward = tciIsforward;
7011  if (searchScanContainer(signal)) {
7012  jam();
7013  tgseIsLocked = tsscIsLocked;
7014  tgseElementptr = tsscElementptr;
7015  tgseContainerptr = tsscContainerptr;
7016  return true;
7017  }//if
7018  if (((tciContainerhead >> 7) & 0x3) != 0) {
7019  jam();
7020  nciPageidptr.i = gsePageidptr.i;
7021  nciPageidptr.p = gsePageidptr.p;
7022  tnciContainerhead = tciContainerhead;
7023  tnciContainerptr = tciContainerptr;
7024  nextcontainerinfo(signal);
7025  tgsePageindex = tnciPageindex;
7026  gsePageidptr.i = nciPageidptr.i;
7027  gsePageidptr.p = nciPageidptr.p;
7028  tgseIsforward = tnciIsforward;
7029  goto NEXTSEARCH_SCAN_LOOP;
7030  }//if
7031  return false;
7032 }//Dbacc::getScanElement()
7033 
7034 /* --------------------------------------------------------------------------------- */
7035 /* INIT_SCAN_OP_REC */
7036 /* --------------------------------------------------------------------------------- */
7037 void Dbacc::initScanOpRec(Signal* signal)
7038 {
7039  Uint32 tisoLocalPtr;
7040  Uint32 localkeylen = fragrecptr.p->localkeylen;
7041 
7042  scanPtr.p->scanOpsAllocated++;
7043 
7044  Uint32 opbits = 0;
7045  opbits |= ZSCAN_OP;
7046  opbits |= scanPtr.p->scanLockMode ? (Uint32) Operationrec::OP_LOCK_MODE : 0;
7047  opbits |= scanPtr.p->scanLockMode ? (Uint32) Operationrec::OP_ACC_LOCK_MODE : 0;
7048  opbits |= (scanPtr.p->scanReadCommittedFlag ?
7049  (Uint32) Operationrec::OP_EXECUTED_DIRTY_READ : 0);
7050  opbits |= Operationrec::OP_COMMIT_DELETE_CHECK;
7051  operationRecPtr.p->userptr = RNIL;
7052  operationRecPtr.p->scanRecPtr = scanPtr.i;
7053  operationRecPtr.p->fid = fragrecptr.p->myfid;
7054  operationRecPtr.p->fragptr = fragrecptr.i;
7055  operationRecPtr.p->nextParallelQue = RNIL;
7056  operationRecPtr.p->prevParallelQue = RNIL;
7057  operationRecPtr.p->nextSerialQue = RNIL;
7058  operationRecPtr.p->prevSerialQue = RNIL;
7059  operationRecPtr.p->transId1 = scanPtr.p->scanTrid1;
7060  operationRecPtr.p->transId2 = scanPtr.p->scanTrid2;
7061  operationRecPtr.p->elementIsforward = tisoIsforward;
7062  operationRecPtr.p->elementContainer = tisoContainerptr;
7063  operationRecPtr.p->elementPointer = tisoElementptr;
7064  operationRecPtr.p->elementPage = isoPageptr.i;
7065  operationRecPtr.p->m_op_bits = opbits;
7066  tisoLocalPtr = tisoElementptr + tisoIsforward;
7067 
7068  arrGuard(tisoLocalPtr, 2048);
7069  Uint32 Tkey1 = isoPageptr.p->word32[tisoLocalPtr];
7070  tisoLocalPtr = tisoLocalPtr + tisoIsforward;
7071  if (localkeylen == 1)
7072  {
7073  operationRecPtr.p->localdata[0] = Local_key::ref2page_id(Tkey1);
7074  operationRecPtr.p->localdata[1] = Local_key::ref2page_idx(Tkey1);
7075  }
7076  else
7077  {
7078  arrGuard(tisoLocalPtr, 2048);
7079  operationRecPtr.p->localdata[0] = Tkey1;
7080  operationRecPtr.p->localdata[1] = isoPageptr.p->word32[tisoLocalPtr];
7081  }
7082  operationRecPtr.p->tupkeylen = fragrecptr.p->keyLength;
7083  operationRecPtr.p->xfrmtupkeylen = 0; // not used
7084 }//Dbacc::initScanOpRec()
7085 
7086 /* --------------------------------------------------------------------------------- */
7087 /* NEXTCONTAINERINFO */
7088 /* DESCRIPTION:THE CONTAINER HEAD WILL BE CHECKED TO CALCULATE INFORMATION */
7089 /* ABOUT NEXT CONTAINER IN THE BUCKET. */
7090 /* INPUT: TNCI_CONTAINERHEAD */
7091 /* NCI_PAGEIDPTR */
7092 /* TNCI_CONTAINERPTR */
7093 /* OUTPUT: */
7094 /* TNCI_PAGEINDEX (INDEX FROM WHICH PAGE INDEX CAN BE CALCULATED). */
7095 /* TNCI_ISFORWARD (IS THE NEXT CONTAINER FORWARD (+1) OR BACKWARD (-1) */
7096 /* NCI_PAGEIDPTR (PAGE REFERENCE OF NEXT CONTAINER) */
7097 /* --------------------------------------------------------------------------------- */
7098 void Dbacc::nextcontainerinfo(Signal* signal)
7099 {
7100  tnciNextSamePage = (tnciContainerhead >> 9) & 0x1; /* CHECK BIT FOR CHECKING WHERE */
7101  /* THE NEXT CONTAINER IS IN THE SAME PAGE */
7102  tnciPageindex = tnciContainerhead & 0x7f; /* NEXT CONTAINER PAGE INDEX 7 BITS */
7103  if (((tnciContainerhead >> 7) & 3) == ZLEFT) {
7104  jam();
7105  tnciIsforward = ZTRUE;
7106  } else {
7107  jam();
7108  tnciIsforward = cminusOne;
7109  }//if
7110  if (tnciNextSamePage == ZFALSE) {
7111  jam();
7112  /* NEXT CONTAINER IS IN AN OVERFLOW PAGE */
7113  arrGuard(tnciContainerptr + 1, 2048);
7114  tnciTmp = nciPageidptr.p->word32[tnciContainerptr + 1];
7115  nciOverflowrangeptr.i = fragrecptr.p->overflowdir;
7116  ptrCheckGuard(nciOverflowrangeptr, cdirrangesize, dirRange);
7117  arrGuard((tnciTmp >> 8), 256);
7118  nciOverflowDirptr.i = nciOverflowrangeptr.p->dirArray[tnciTmp >> 8];
7119  ptrCheckGuard(nciOverflowDirptr, cdirarraysize, directoryarray);
7120  nciPageidptr.i = nciOverflowDirptr.p->pagep[tnciTmp & 0xff];
7121  ptrCheckGuard(nciPageidptr, cpagesize, page8);
7122  }//if
7123 }//Dbacc::nextcontainerinfo()
7124 
7125 /* --------------------------------------------------------------------------------- */
7126 /* PUT_ACTIVE_SCAN_OP */
7127 /* --------------------------------------------------------------------------------- */
7128 void Dbacc::putActiveScanOp(Signal* signal)
7129 {
7130  OperationrecPtr pasOperationRecPtr;
7131  pasOperationRecPtr.i = scanPtr.p->scanFirstActiveOp;
7132  if (pasOperationRecPtr.i != RNIL) {
7133  jam();
7134  ptrCheckGuard(pasOperationRecPtr, coprecsize, operationrec);
7135  pasOperationRecPtr.p->prevOp = operationRecPtr.i;
7136  }//if
7137  operationRecPtr.p->nextOp = pasOperationRecPtr.i;
7138  operationRecPtr.p->prevOp = RNIL;
7139  scanPtr.p->scanFirstActiveOp = operationRecPtr.i;
7140 }//Dbacc::putActiveScanOp()
7141 
7155 void Dbacc::putOpScanLockQue()
7156 {
7157 
7158 #ifdef VM_TRACE
7159  // DEBUG CODE
7160  // Check that there are as many operations in the lockqueue as
7161  // scanLockHeld indicates
7162  OperationrecPtr tmpOp;
7163  int numLockedOpsBefore = 0;
7164  tmpOp.i = scanPtr.p->scanFirstLockedOp;
7165  while(tmpOp.i != RNIL){
7166  numLockedOpsBefore++;
7167  ptrCheckGuard(tmpOp, coprecsize, operationrec);
7168  if (tmpOp.p->nextOp == RNIL)
7169  {
7170  ndbrequire(tmpOp.i == scanPtr.p->scanLastLockedOp);
7171  }
7172  tmpOp.i = tmpOp.p->nextOp;
7173  }
7174  ndbrequire(numLockedOpsBefore==scanPtr.p->scanLockHeld);
7175 #endif
7176 
7177  OperationrecPtr pslOperationRecPtr;
7178  ScanRec theScanRec;
7179  theScanRec = *scanPtr.p;
7180 
7181  pslOperationRecPtr.i = scanPtr.p->scanLastLockedOp;
7182  operationRecPtr.p->prevOp = pslOperationRecPtr.i;
7183  operationRecPtr.p->nextOp = RNIL;
7184  if (pslOperationRecPtr.i != RNIL) {
7185  jam();
7186  ptrCheckGuard(pslOperationRecPtr, coprecsize, operationrec);
7187  pslOperationRecPtr.p->nextOp = operationRecPtr.i;
7188  } else {
7189  jam();
7190  scanPtr.p->scanFirstLockedOp = operationRecPtr.i;
7191  }//if
7192  scanPtr.p->scanLastLockedOp = operationRecPtr.i;
7193  scanPtr.p->scanLockHeld++;
7194 
7195 }//Dbacc::putOpScanLockQue()
7196 
7197 /* --------------------------------------------------------------------------------- */
7198 /* PUT_READY_SCAN_QUEUE */
7199 /* --------------------------------------------------------------------------------- */
7200 void Dbacc::putReadyScanQueue(Signal* signal, Uint32 scanRecIndex)
7201 {
7202  OperationrecPtr prsOperationRecPtr;
7203  ScanRecPtr TscanPtr;
7204 
7205  TscanPtr.i = scanRecIndex;
7206  ptrCheckGuard(TscanPtr, cscanRecSize, scanRec);
7207 
7208  prsOperationRecPtr.i = TscanPtr.p->scanLastQueuedOp;
7209  operationRecPtr.p->prevOp = prsOperationRecPtr.i;
7210  operationRecPtr.p->nextOp = RNIL;
7211  TscanPtr.p->scanLastQueuedOp = operationRecPtr.i;
7212  if (prsOperationRecPtr.i != RNIL) {
7213  jam();
7214  ptrCheckGuard(prsOperationRecPtr, coprecsize, operationrec);
7215  prsOperationRecPtr.p->nextOp = operationRecPtr.i;
7216  } else {
7217  jam();
7218  TscanPtr.p->scanFirstQueuedOp = operationRecPtr.i;
7219  }//if
7220 }//Dbacc::putReadyScanQueue()
7221 
7222 /* --------------------------------------------------------------------------------- */
7223 /* RELEASE_SCAN_BUCKET */
7224 // Input:
7225 // rsbPageidptr.i Index to page where buckets starts
7226 // rsbPageidptr.p Pointer to page where bucket starts
7227 // trsbPageindex Page index of starting container in bucket
7228 /* --------------------------------------------------------------------------------- */
7229 void Dbacc::releaseScanBucket(Signal* signal)
7230 {
7231  Uint32 trsbIsforward;
7232 
7233  trsbIsforward = ZTRUE;
7234  NEXTRELEASESCANLOOP:
7235  ciPageidptr.i = rsbPageidptr.i;
7236  ciPageidptr.p = rsbPageidptr.p;
7237  tciPageindex = trsbPageindex;
7238  tciIsforward = trsbIsforward;
7239  containerinfo(signal);
7240  rscPageidptr.i = rsbPageidptr.i;
7241  rscPageidptr.p = rsbPageidptr.p;
7242  trscContainerlen = tciContainerlen;
7243  trscContainerptr = tciContainerptr;
7244  trscIsforward = trsbIsforward;
7245  releaseScanContainer(signal);
7246  if (((tciContainerhead >> 7) & 0x3) != 0) {
7247  jam();
7248  nciPageidptr.i = rsbPageidptr.i;
7249  nciPageidptr.p = rsbPageidptr.p;
7250  tnciContainerhead = tciContainerhead;
7251  tnciContainerptr = tciContainerptr;
7252  nextcontainerinfo(signal);
7253  rsbPageidptr.i = nciPageidptr.i;
7254  rsbPageidptr.p = nciPageidptr.p;
7255  trsbPageindex = tnciPageindex;
7256  trsbIsforward = tnciIsforward;
7257  goto NEXTRELEASESCANLOOP;
7258  }//if
7259 }//Dbacc::releaseScanBucket()
7260 
7261 /* --------------------------------------------------------------------------------- */
7262 /* RELEASE_SCAN_CONTAINER */
7263 /* INPUT: TRSC_CONTAINERLEN */
7264 /* RSC_PAGEIDPTR */
7265 /* TRSC_CONTAINERPTR */
7266 /* TRSC_ISFORWARD */
7267 /* SCAN_PTR */
7268 /* */
7269 /* DESCRIPTION: SEARCHS IN A CONTAINER, AND THE SCAN BIT OF THE ELEMENTS */
7270 /* OF THE CONTAINER IS RESET */
7271 /* --------------------------------------------------------------------------------- */
7272 void Dbacc::releaseScanContainer(Signal* signal)
7273 {
7274  OperationrecPtr rscOperPtr;
7275  Uint32 trscElemStep;
7276  Uint32 trscElementptr;
7277  Uint32 trscElemlens;
7278  Uint32 trscElemlen;
7279 
7280  if (trscContainerlen < 4) {
7281  if (trscContainerlen != ZCON_HEAD_SIZE) {
7282  jam();
7283  sendSystemerror(signal, __LINE__);
7284  }//if
7285  return; /* 2 IS THE MINIMUM SIZE OF THE ELEMENT */
7286  }//if
7287  trscElemlens = trscContainerlen - ZCON_HEAD_SIZE;
7288  trscElemlen = fragrecptr.p->elementLength;
7289  if (trscIsforward == 1) {
7290  jam();
7291  trscElementptr = trscContainerptr + ZCON_HEAD_SIZE;
7292  trscElemStep = trscElemlen;
7293  } else {
7294  jam();
7295  trscElementptr = trscContainerptr - 1;
7296  trscElemStep = 0 - trscElemlen;
7297  }//if
7298  do {
7299  arrGuard(trscElementptr, 2048);
7300  const Uint32 eh = rscPageidptr.p->word32[trscElementptr];
7301  const Uint32 scanMask = scanPtr.p->scanMask;
7302  if (ElementHeader::getUnlocked(eh)) {
7303  jam();
7304  const Uint32 tmp = ElementHeader::clearScanBit(eh, scanMask);
7305  dbgWord32(rscPageidptr, trscElementptr, tmp);
7306  rscPageidptr.p->word32[trscElementptr] = tmp;
7307  } else {
7308  jam();
7309  rscOperPtr.i = ElementHeader::getOpPtrI(eh);
7310  ptrCheckGuard(rscOperPtr, coprecsize, operationrec);
7311  rscOperPtr.p->scanBits &= ~scanMask;
7312  }//if
7313  trscElemlens = trscElemlens - trscElemlen;
7314  trscElementptr = trscElementptr + trscElemStep;
7315  } while (trscElemlens > 1);
7316  if (trscElemlens != 0) {
7317  jam();
7318  sendSystemerror(signal, __LINE__);
7319  }//if
7320 }//Dbacc::releaseScanContainer()
7321 
7322 /* --------------------------------------------------------------------------------- */
7323 /* RELEASE_SCAN_REC */
7324 /* --------------------------------------------------------------------------------- */
7325 void Dbacc::releaseScanRec(Signal* signal)
7326 {
7327  // Check that all ops this scan has allocated have been
7328  // released
7329  ndbrequire(scanPtr.p->scanOpsAllocated==0);
7330 
7331  // Check that all locks this scan might have aquired
7332  // have been properly released
7333  ndbrequire(scanPtr.p->scanLockHeld == 0);
7334  ndbrequire(scanPtr.p->scanFirstLockedOp == RNIL);
7335  ndbrequire(scanPtr.p->scanLastLockedOp == RNIL);
7336 
7337  // Check that all active operations have been
7338  // properly released
7339  ndbrequire(scanPtr.p->scanFirstActiveOp == RNIL);
7340 
7341  // Check that all queued operations have been
7342  // properly released
7343  ndbrequire(scanPtr.p->scanFirstQueuedOp == RNIL);
7344  ndbrequire(scanPtr.p->scanLastQueuedOp == RNIL);
7345 
7346  // Put scan record in free list
7347  scanPtr.p->scanNextfreerec = cfirstFreeScanRec;
7348  scanPtr.p->scanState = ScanRec::SCAN_DISCONNECT;
7349  cfirstFreeScanRec = scanPtr.i;
7350 
7351 }//Dbacc::releaseScanRec()
7352 
7353 /* --------------------------------------------------------------------------------- */
7354 /* SEARCH_SCAN_CONTAINER */
7355 /* INPUT: TSSC_CONTAINERLEN */
7356 /* TSSC_CONTAINERPTR */
7357 /* TSSC_ISFORWARD */
7358 /* SSC_PAGEIDPTR */
7359 /* SCAN_PTR */
7360 /* OUTPUT: TSSC_IS_LOCKED */
7361 /* */
7362 /* DESCRIPTION: SEARCH IN A CONTAINER TO FIND THE NEXT SCAN ELEMENT. */
7363 /* TO DO THIS THE SCAN BIT OF THE ELEMENT HEADER IS CHECKED. IF */
7364 /* THIS BIT IS ZERO, IT IS SET TO ONE AND THE ELEMENT IS RETURNED.*/
7365 /* --------------------------------------------------------------------------------- */
7366 bool Dbacc::searchScanContainer(Signal* signal)
7367 {
7368  OperationrecPtr sscOperPtr;
7369  Uint32 tsscScanBits;
7370  Uint32 tsscElemlens;
7371  Uint32 tsscElemlen;
7372  Uint32 tsscElemStep;
7373 
7374  if (tsscContainerlen < 4) {
7375  jam();
7376  return false; /* 2 IS THE MINIMUM SIZE OF THE ELEMENT */
7377  }//if
7378  tsscElemlens = tsscContainerlen - ZCON_HEAD_SIZE;
7379  tsscElemlen = fragrecptr.p->elementLength;
7380  /* LENGTH OF THE ELEMENT */
7381  if (tsscIsforward == 1) {
7382  jam();
7383  tsscElementptr = tsscContainerptr + ZCON_HEAD_SIZE;
7384  tsscElemStep = tsscElemlen;
7385  } else {
7386  jam();
7387  tsscElementptr = tsscContainerptr - 1;
7388  tsscElemStep = 0 - tsscElemlen;
7389  }//if
7390  SCANELEMENTLOOP001:
7391  arrGuard(tsscElementptr, 2048);
7392  const Uint32 eh = sscPageidptr.p->word32[tsscElementptr];
7393  tsscIsLocked = ElementHeader::getLocked(eh);
7394  if (!tsscIsLocked){
7395  jam();
7396  tsscScanBits = ElementHeader::getScanBits(eh);
7397  if ((scanPtr.p->scanMask & tsscScanBits) == 0) {
7398  jam();
7399  const Uint32 tmp = ElementHeader::setScanBit(eh, scanPtr.p->scanMask);
7400  dbgWord32(sscPageidptr, tsscElementptr, tmp);
7401  sscPageidptr.p->word32[tsscElementptr] = tmp;
7402  return true;
7403  }//if
7404  } else {
7405  jam();
7406  sscOperPtr.i = ElementHeader::getOpPtrI(eh);
7407  ptrCheckGuard(sscOperPtr, coprecsize, operationrec);
7408  if ((sscOperPtr.p->scanBits & scanPtr.p->scanMask) == 0) {
7409  jam();
7410  sscOperPtr.p->scanBits |= scanPtr.p->scanMask;
7411  return true;
7412  }//if
7413  }//if
7414  /* THE ELEMENT IS ALREADY SENT. */
7415  /* SEARCH FOR NEXT ONE */
7416  tsscElemlens = tsscElemlens - tsscElemlen;
7417  if (tsscElemlens > 1) {
7418  jam();
7419  tsscElementptr = tsscElementptr + tsscElemStep;
7420  goto SCANELEMENTLOOP001;
7421  }//if
7422  return false;
7423 }//Dbacc::searchScanContainer()
7424 
7425 /* --------------------------------------------------------------------------------- */
7426 /* SEND THE RESPONSE NEXT_SCANCONF AND POSSIBLE KEYINFO SIGNALS AS WELL. */
7427 /* --------------------------------------------------------------------------------- */
7428 void Dbacc::sendNextScanConf(Signal* signal)
7429 {
7430  Uint32 blockNo = refToMain(scanPtr.p->scanUserblockref);
7431 
7432  jam();
7437  signal->theData[0] = scanPtr.p->scanUserptr;
7438  signal->theData[1] = operationRecPtr.i;
7439  signal->theData[2] = operationRecPtr.p->fid;
7440  signal->theData[3] = operationRecPtr.p->localdata[0];
7441  signal->theData[4] = operationRecPtr.p->localdata[1];
7442  EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 5);
7443  return;
7444 }//Dbacc::sendNextScanConf()
7445 
7446 /* --------------------------------------------------------------------------------- */
7447 /* SETLOCK */
7448 /* DESCRIPTION:SETS LOCK ON AN ELEMENT. INFORMATION ABOUT THE ELEMENT IS */
7449 /* SAVED IN THE ELEMENT HEAD.A COPY OF THIS INFORMATION WILL */
7450 /* BE PUT IN THE OPERATION RECORD. A FIELD IN THE HEADER OF */
7451 /* THE ELEMENT POINTS TO THE OPERATION RECORD. */
7452 /* --------------------------------------------------------------------------------- */
7453 void Dbacc::setlock(Signal* signal)
7454 {
7455  Uint32 tselTmp1;
7456 
7457  arrGuard(tslElementptr, 2048);
7458  tselTmp1 = slPageidptr.p->word32[tslElementptr];
7459  operationRecPtr.p->scanBits = ElementHeader::getScanBits(tselTmp1);
7460  operationRecPtr.p->hashvaluePart = ElementHeader::getHashValuePart(tselTmp1);
7461 
7462  tselTmp1 = ElementHeader::setLocked(operationRecPtr.i);
7463  dbgWord32(slPageidptr, tslElementptr, tselTmp1);
7464  slPageidptr.p->word32[tslElementptr] = tselTmp1;
7465 }//Dbacc::setlock()
7466 
7467 /* --------------------------------------------------------------------------------- */
7468 /* TAKE_OUT_ACTIVE_SCAN_OP */
7469 /* DESCRIPTION: AN ACTIVE SCAN OPERATION IS BELOGED TO AN ACTIVE LIST OF THE */
7470 /* SCAN RECORD. BY THIS SUBRUTIN THE LIST IS UPDATED. */
7471 /* --------------------------------------------------------------------------------- */
7472 void Dbacc::takeOutActiveScanOp(Signal* signal)
7473 {
7474  OperationrecPtr tasOperationRecPtr;
7475 
7476  if (operationRecPtr.p->prevOp != RNIL) {
7477  jam();
7478  tasOperationRecPtr.i = operationRecPtr.p->prevOp;
7479  ptrCheckGuard(tasOperationRecPtr, coprecsize, operationrec);
7480  tasOperationRecPtr.p->nextOp = operationRecPtr.p->nextOp;
7481  } else {
7482  jam();
7483  scanPtr.p->scanFirstActiveOp = operationRecPtr.p->nextOp;
7484  }//if
7485  if (operationRecPtr.p->nextOp != RNIL) {
7486  jam();
7487  tasOperationRecPtr.i = operationRecPtr.p->nextOp;
7488  ptrCheckGuard(tasOperationRecPtr, coprecsize, operationrec);
7489  tasOperationRecPtr.p->prevOp = operationRecPtr.p->prevOp;
7490  }//if
7491 }//Dbacc::takeOutActiveScanOp()
7492 
7503 void Dbacc::takeOutScanLockQueue(Uint32 scanRecIndex)
7504 {
7505  OperationrecPtr tslOperationRecPtr;
7506  ScanRecPtr TscanPtr;
7507 
7508  TscanPtr.i = scanRecIndex;
7509  ptrCheckGuard(TscanPtr, cscanRecSize, scanRec);
7510 
7511  if (operationRecPtr.p->prevOp != RNIL) {
7512  jam();
7513  tslOperationRecPtr.i = operationRecPtr.p->prevOp;
7514  ptrCheckGuard(tslOperationRecPtr, coprecsize, operationrec);
7515  tslOperationRecPtr.p->nextOp = operationRecPtr.p->nextOp;
7516  } else {
7517  jam();
7518  // Check that first are pointing at operation to take out
7519  ndbrequire(TscanPtr.p->scanFirstLockedOp==operationRecPtr.i);
7520  TscanPtr.p->scanFirstLockedOp = operationRecPtr.p->nextOp;
7521  }//if
7522  if (operationRecPtr.p->nextOp != RNIL) {
7523  jam();
7524  tslOperationRecPtr.i = operationRecPtr.p->nextOp;
7525  ptrCheckGuard(tslOperationRecPtr, coprecsize, operationrec);
7526  tslOperationRecPtr.p->prevOp = operationRecPtr.p->prevOp;
7527  } else {
7528  jam();
7529  // Check that last are pointing at operation to take out
7530  ndbrequire(TscanPtr.p->scanLastLockedOp==operationRecPtr.i);
7531  TscanPtr.p->scanLastLockedOp = operationRecPtr.p->prevOp;
7532  }//if
7533  TscanPtr.p->scanLockHeld--;
7534 
7535 #ifdef VM_TRACE
7536  // DEBUG CODE
7537  // Check that there are as many operations in the lockqueue as
7538  // scanLockHeld indicates
7539  OperationrecPtr tmpOp;
7540  int numLockedOps = 0;
7541  tmpOp.i = TscanPtr.p->scanFirstLockedOp;
7542  while(tmpOp.i != RNIL){
7543  numLockedOps++;
7544  ptrCheckGuard(tmpOp, coprecsize, operationrec);
7545  if (tmpOp.p->nextOp == RNIL)
7546  {
7547  ndbrequire(tmpOp.i == TscanPtr.p->scanLastLockedOp);
7548  }
7549  tmpOp.i = tmpOp.p->nextOp;
7550  }
7551  ndbrequire(numLockedOps==TscanPtr.p->scanLockHeld);
7552 #endif
7553 }//Dbacc::takeOutScanLockQueue()
7554 
7555 /* --------------------------------------------------------------------------------- */
7556 /* TAKE_OUT_READY_SCAN_QUEUE */
7557 /* --------------------------------------------------------------------------------- */
7558 void Dbacc::takeOutReadyScanQueue(Signal* signal)
7559 {
7560  OperationrecPtr trsOperationRecPtr;
7561 
7562  if (operationRecPtr.p->prevOp != RNIL) {
7563  jam();
7564  trsOperationRecPtr.i = operationRecPtr.p->prevOp;
7565  ptrCheckGuard(trsOperationRecPtr, coprecsize, operationrec);
7566  trsOperationRecPtr.p->nextOp = operationRecPtr.p->nextOp;
7567  } else {
7568  jam();
7569  scanPtr.p->scanFirstQueuedOp = operationRecPtr.p->nextOp;
7570  }//if
7571  if (operationRecPtr.p->nextOp != RNIL) {
7572  jam();
7573  trsOperationRecPtr.i = operationRecPtr.p->nextOp;
7574  ptrCheckGuard(trsOperationRecPtr, coprecsize, operationrec);
7575  trsOperationRecPtr.p->prevOp = operationRecPtr.p->prevOp;
7576  } else {
7577  jam();
7578  scanPtr.p->scanLastQueuedOp = operationRecPtr.p->nextOp;
7579  }//if
7580 }//Dbacc::takeOutReadyScanQueue()
7581 
7582 /* --------------------------------------------------------------------------------- */
7583 /* --------------------------------------------------------------------------------- */
7584 /* --------------------------------------------------------------------------------- */
7585 /* */
7586 /* END OF SCAN MODULE */
7587 /* */
7588 /* --------------------------------------------------------------------------------- */
7589 /* --------------------------------------------------------------------------------- */
7590 
7591 bool Dbacc::getfragmentrec(Signal* signal, FragmentrecPtr& rootPtr, Uint32 fid)
7592 {
7593  for (Uint32 i = 0; i < MAX_FRAG_PER_NODE; i++) {
7594  jam();
7595  if (tabptr.p->fragholder[i] == fid) {
7596  jam();
7597  fragrecptr.i = tabptr.p->fragptrholder[i];
7598  ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
7599  return true;
7600  }//if
7601  }//for
7602  return false;
7603 }//Dbacc::getrootfragmentrec()
7604 
7605 /* --------------------------------------------------------------------------------- */
7606 /* INIT_OVERPAGE */
7607 /* INPUT. IOP_PAGEPTR, POINTER TO AN OVERFLOW PAGE RECORD */
7608 /* DESCRIPTION: CONTAINERS AND FREE LISTS OF THE PAGE, GET INITIALE VALUE */
7609 /* ACCORDING TO LH3 AND PAGE STRUCTOR DESCRIPTION OF NDBACC BLOCK */
7610 /* --------------------------------------------------------------------------------- */
7611 void Dbacc::initOverpage(Signal* signal)
7612 {
7613  Uint32 tiopTmp;
7614  Uint32 tiopPrevFree;
7615  Uint32 tiopNextFree;
7616 
7617  for (tiopIndex = 0; tiopIndex <= 2047; tiopIndex++) {
7618  iopPageptr.p->word32[tiopIndex] = 0;
7619  }//for
7620  iopPageptr.p->word32[ZPOS_OVERFLOWREC] = iopOverflowRecPtr.i;
7621  iopPageptr.p->word32[ZPOS_CHECKSUM] = 0;
7622  iopPageptr.p->word32[ZPOS_PAGE_ID] = tiopPageId;
7623  iopPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] = 0;
7624  tiopTmp = ZEMPTYLIST;
7625  tiopTmp = (tiopTmp << 16) + (tiopTmp << 23);
7626  iopPageptr.p->word32[ZPOS_EMPTY_LIST] = tiopTmp + (1 << ZPOS_PAGE_TYPE_BIT);
7627  /* --------------------------------------------------------------------------------- */
7628  /* INITIALISE PREVIOUS PART OF DOUBLY LINKED LIST FOR LEFT CONTAINERS. */
7629  /* --------------------------------------------------------------------------------- */
7630  tiopIndex = ZHEAD_SIZE + 1;
7631  iopPageptr.p->word32[tiopIndex] = ZEMPTYLIST;
7632  for (tiopPrevFree = 0; tiopPrevFree <= ZEMPTYLIST - 2; tiopPrevFree++) {
7633  tiopIndex = tiopIndex + ZBUF_SIZE;
7634  iopPageptr.p->word32[tiopIndex] = tiopPrevFree;
7635  }//for
7636  /* --------------------------------------------------------------------------------- */
7637  /* INITIALISE NEXT PART OF DOUBLY LINKED LIST FOR LEFT CONTAINERS. */
7638  /* --------------------------------------------------------------------------------- */
7639  tiopIndex = ZHEAD_SIZE;
7640  for (tiopNextFree = 1; tiopNextFree <= ZEMPTYLIST - 1; tiopNextFree++) {
7641  iopPageptr.p->word32[tiopIndex] = tiopNextFree;
7642  tiopIndex = tiopIndex + ZBUF_SIZE;
7643  }//for
7644  iopPageptr.p->word32[tiopIndex] = ZEMPTYLIST; /* LEFT_LIST IS UPDATED */
7645  /* --------------------------------------------------------------------------------- */
7646  /* INITIALISE PREVIOUS PART OF DOUBLY LINKED LIST FOR RIGHT CONTAINERS. */
7647  /* --------------------------------------------------------------------------------- */
7648  tiopIndex = (ZBUF_SIZE + ZHEAD_SIZE) - 1;
7649  iopPageptr.p->word32[tiopIndex] = ZEMPTYLIST;
7650  for (tiopPrevFree = 0; tiopPrevFree <= ZEMPTYLIST - 2; tiopPrevFree++) {
7651  tiopIndex = tiopIndex + ZBUF_SIZE;
7652  iopPageptr.p->word32[tiopIndex] = tiopPrevFree;
7653  }//for
7654  /* --------------------------------------------------------------------------------- */
7655  /* INITIALISE NEXT PART OF DOUBLY LINKED LIST FOR RIGHT CONTAINERS. */
7656  /* --------------------------------------------------------------------------------- */
7657  tiopIndex = (ZBUF_SIZE + ZHEAD_SIZE) - 2;
7658  for (tiopNextFree = 1; tiopNextFree <= ZEMPTYLIST - 1; tiopNextFree++) {
7659  iopPageptr.p->word32[tiopIndex] = tiopNextFree;
7660  tiopIndex = tiopIndex + ZBUF_SIZE;
7661  }//for
7662  iopPageptr.p->word32[tiopIndex] = ZEMPTYLIST; /* RIGHT_LIST IS UPDATED */
7663 }//Dbacc::initOverpage()
7664 
7665 /* --------------------------------------------------------------------------------- */
7666 /* INIT_PAGE */
7667 /* INPUT. INP_PAGEPTR, POINTER TO A PAGE RECORD */
7668 /* DESCRIPTION: CONTAINERS AND FREE LISTS OF THE PAGE, GET INITIALE VALUE */
7669 /* ACCORDING TO LH3 AND PAGE STRUCTOR DISACRIPTION OF NDBACC BLOCK */
7670 /* --------------------------------------------------------------------------------- */
7671 void Dbacc::initPage(Signal* signal)
7672 {
7673  Uint32 tinpTmp1;
7674  Uint32 tinpIndex;
7675  Uint32 tinpTmp;
7676  Uint32 tinpPrevFree;
7677  Uint32 tinpNextFree;
7678 
7679  for (tiopIndex = 0; tiopIndex <= 2047; tiopIndex++) {
7680  inpPageptr.p->word32[tiopIndex] = 0;
7681  }//for
7682  /* --------------------------------------------------------------------------------- */
7683  /* SET PAGE ID FOR USE OF CHECKPOINTER. */
7684  /* PREPARE CONTAINER HEADERS INDICATING EMPTY CONTAINERS WITHOUT NEXT. */
7685  /* --------------------------------------------------------------------------------- */
7686  inpPageptr.p->word32[ZPOS_PAGE_ID] = tipPageId;
7687  tinpTmp1 = ZCON_HEAD_SIZE;
7688  tinpTmp1 = tinpTmp1 << 26;
7689  /* --------------------------------------------------------------------------------- */
7690  /* INITIALISE ZNO_CONTAINERS PREDEFINED HEADERS ON LEFT SIZE. */
7691  /* --------------------------------------------------------------------------------- */
7692  tinpIndex = ZHEAD_SIZE;
7693  for (tinpTmp = 0; tinpTmp <= ZNO_CONTAINERS - 1; tinpTmp++) {
7694  inpPageptr.p->word32[tinpIndex] = tinpTmp1;
7695  tinpIndex = tinpIndex + ZBUF_SIZE;
7696  }//for
7697  /* WORD32(ZPOS_EMPTY_LIST) DATA STRUCTURE:*/
7698  /*--------------------------------------- */
7699  /*| PAGE TYPE|LEFT FREE|RIGHT FREE */
7700  /*| 1 | LIST | LIST */
7701  /*| BIT | 7 BITS | 7 BITS */
7702  /*--------------------------------------- */
7703  /* --------------------------------------------------------------------------------- */
7704  /* INITIALISE FIRST POINTER TO DOUBLY LINKED LIST OF FREE CONTAINERS. */
7705  /* INITIALISE EMPTY LISTS OF USED CONTAINERS. */
7706  /* INITIALISE LEFT FREE LIST TO 64 AND RIGHT FREE LIST TO ZERO. */
7707  /* ALSO INITIALISE PAGE TYPE TO NOT OVERFLOW PAGE. */
7708  /* --------------------------------------------------------------------------------- */
7709  tinpTmp = ZEMPTYLIST;
7710  tinpTmp = (tinpTmp << 16) + (tinpTmp << 23);
7711  tinpTmp = tinpTmp + (ZNO_CONTAINERS << 7);
7712  inpPageptr.p->word32[ZPOS_EMPTY_LIST] = tinpTmp;
7713  /* --------------------------------------------------------------------------------- */
7714  /* INITIALISE PREVIOUS PART OF DOUBLY LINKED LIST FOR RIGHT CONTAINERS. */
7715  /* --------------------------------------------------------------------------------- */
7716  tinpIndex = (ZHEAD_SIZE + ZBUF_SIZE) - 1;
7717  inpPageptr.p->word32[tinpIndex] = ZEMPTYLIST;
7718  for (tinpPrevFree = 0; tinpPrevFree <= ZEMPTYLIST - 2; tinpPrevFree++) {
7719  tinpIndex = tinpIndex + ZBUF_SIZE;
7720  inpPageptr.p->word32[tinpIndex] = tinpPrevFree;
7721  }//for
7722  /* --------------------------------------------------------------------------------- */
7723  /* INITIALISE NEXT PART OF DOUBLY LINKED LIST FOR RIGHT CONTAINERS. */
7724  /* --------------------------------------------------------------------------------- */
7725  tinpIndex = (ZHEAD_SIZE + ZBUF_SIZE) - 2;
7726  for (tinpNextFree = 1; tinpNextFree <= ZEMPTYLIST - 1; tinpNextFree++) {
7727  inpPageptr.p->word32[tinpIndex] = tinpNextFree;
7728  tinpIndex = tinpIndex + ZBUF_SIZE;
7729  }//for
7730  inpPageptr.p->word32[tinpIndex] = ZEMPTYLIST;
7731  /* --------------------------------------------------------------------------------- */
7732  /* INITIALISE PREVIOUS PART OF DOUBLY LINKED LIST FOR LEFT CONTAINERS. */
7733  /* THE FIRST ZNO_CONTAINERS ARE NOT PUT INTO FREE LIST SINCE THEY ARE */
7734  /* PREDEFINED AS OCCUPIED. */
7735  /* --------------------------------------------------------------------------------- */
7736  tinpIndex = (ZNO_CONTAINERS * ZBUF_SIZE) + ZHEAD_SIZE;
7737  for (tinpNextFree = ZNO_CONTAINERS + 1; tinpNextFree <= ZEMPTYLIST - 1; tinpNextFree++) {
7738  inpPageptr.p->word32[tinpIndex] = tinpNextFree;
7739  tinpIndex = tinpIndex + ZBUF_SIZE;
7740  }//for
7741  inpPageptr.p->word32[tinpIndex] = ZEMPTYLIST;
7742  /* --------------------------------------------------------------------------------- */
7743  /* INITIALISE NEXT PART OF DOUBLY LINKED LIST FOR LEFT CONTAINERS. */
7744  /* THE FIRST ZNO_CONTAINERS ARE NOT PUT INTO FREE LIST SINCE THEY ARE */
7745  /* PREDEFINED AS OCCUPIED. */
7746  /* --------------------------------------------------------------------------------- */
7747  tinpIndex = ((ZNO_CONTAINERS * ZBUF_SIZE) + ZHEAD_SIZE) + 1;
7748  inpPageptr.p->word32[tinpIndex] = ZEMPTYLIST;
7749  for (tinpPrevFree = ZNO_CONTAINERS; tinpPrevFree <= ZEMPTYLIST - 2; tinpPrevFree++) {
7750  tinpIndex = tinpIndex + ZBUF_SIZE;
7751  inpPageptr.p->word32[tinpIndex] = tinpPrevFree;
7752  }//for
7753  /* --------------------------------------------------------------------------------- */
7754  /* INITIALISE HEADER POSITIONS NOT CURRENTLY USED AND ENSURE USE OF OVERFLOW */
7755  /* RECORD POINTER ON THIS PAGE LEADS TO ERROR. */
7756  /* --------------------------------------------------------------------------------- */
7757  inpPageptr.p->word32[ZPOS_CHECKSUM] = 0;
7758  inpPageptr.p->word32[ZPOS_ALLOC_CONTAINERS] = 0;
7759  inpPageptr.p->word32[ZPOS_OVERFLOWREC] = RNIL;
7760 }//Dbacc::initPage()
7761 
7762 /* --------------------------------------------------------------------------------- */
7763 /* PUT_OVERFLOW_REC_IN_FRAG */
7764 /* DESCRIPTION: AN OVERFLOW RECORD WITCH IS USED TO KEEP INFORMATION ABOUT */
7765 /* OVERFLOW PAGE WILL BE PUT IN A LIST OF OVERFLOW RECORDS IN */
7766 /* THE FRAGMENT RECORD. */
7767 /* --------------------------------------------------------------------------------- */
7768 void Dbacc::putOverflowRecInFrag(Signal* signal)
7769 {
7770  OverflowRecordPtr tpifNextOverrecPtr;
7771  OverflowRecordPtr tpifPrevOverrecPtr;
7772 
7773  tpifNextOverrecPtr.i = fragrecptr.p->firstOverflowRec;
7774  LINT_INIT(tpifPrevOverrecPtr.p);
7775  tpifPrevOverrecPtr.i = RNIL;
7776  while (tpifNextOverrecPtr.i != RNIL) {
7777  ptrCheckGuard(tpifNextOverrecPtr, coverflowrecsize, overflowRecord);
7778  if (tpifNextOverrecPtr.p->dirindex < porOverflowRecPtr.p->dirindex) {
7779  jam();
7780  /* --------------------------------------------------------------------------------- */
7781  /* PROCEED IN LIST TO THE NEXT IN THE LIST SINCE THE ENTRY HAD A LOWER PAGE ID.*/
7782  /* WE WANT TO ENSURE THAT LOWER PAGE ID'S ARE KEPT FULL RATHER THAN THE */
7783  /* OPPOSITE TO ENSURE THAT HIGH PAGE ID'S CAN BE REMOVED WHEN SHRINKS ARE */
7784  /* PERFORMED. */
7785  /* --------------------------------------------------------------------------------- */
7786  tpifPrevOverrecPtr = tpifNextOverrecPtr;
7787  tpifNextOverrecPtr.i = tpifNextOverrecPtr.p->nextOverRec;
7788  } else {
7789  jam();
7790  ndbrequire(tpifNextOverrecPtr.p->dirindex != porOverflowRecPtr.p->dirindex);
7791  /* --------------------------------------------------------------------------------- */
7792  /* TRYING TO INSERT THE SAME PAGE TWICE. SYSTEM ERROR. */
7793  /* --------------------------------------------------------------------------------- */
7794  break;
7795  }//if
7796  }//while
7797  if (tpifNextOverrecPtr.i == RNIL) {
7798  jam();
7799  fragrecptr.p->lastOverflowRec = porOverflowRecPtr.i;
7800  } else {
7801  jam();
7802  tpifNextOverrecPtr.p->prevOverRec = porOverflowRecPtr.i;
7803  }//if
7804  if (tpifPrevOverrecPtr.i == RNIL) {
7805  jam();
7806  fragrecptr.p->firstOverflowRec = porOverflowRecPtr.i;
7807  } else {
7808  jam();
7809  tpifPrevOverrecPtr.p->nextOverRec = porOverflowRecPtr.i;
7810  }//if
7811  porOverflowRecPtr.p->prevOverRec = tpifPrevOverrecPtr.i;
7812  porOverflowRecPtr.p->nextOverRec = tpifNextOverrecPtr.i;
7813 }//Dbacc::putOverflowRecInFrag()
7814 
7815 /* --------------------------------------------------------------------------------- */
7816 /* PUT_REC_IN_FREE_OVERDIR */
7817 /* --------------------------------------------------------------------------------- */
7818 void Dbacc::putRecInFreeOverdir(Signal* signal)
7819 {
7820  OverflowRecordPtr tpfoNextOverrecPtr;
7821  OverflowRecordPtr tpfoPrevOverrecPtr;
7822 
7823  tpfoNextOverrecPtr.i = fragrecptr.p->firstFreeDirindexRec;
7824  LINT_INIT(tpfoPrevOverrecPtr.p);
7825  tpfoPrevOverrecPtr.i = RNIL;
7826  while (tpfoNextOverrecPtr.i != RNIL) {
7827  ptrCheckGuard(tpfoNextOverrecPtr, coverflowrecsize, overflowRecord);
7828  if (tpfoNextOverrecPtr.p->dirindex < priOverflowRecPtr.p->dirindex) {
7829  jam();
7830  /* --------------------------------------------------------------------------------- */
7831  /* PROCEED IN LIST TO THE NEXT IN THE LIST SINCE THE ENTRY HAD A LOWER PAGE ID.*/
7832  /* WE WANT TO ENSURE THAT LOWER PAGE ID'S ARE KEPT FULL RATHER THAN THE */
7833  /* OPPOSITE TO ENSURE THAT HIGH PAGE ID'S CAN BE REMOVED WHEN SHRINKS ARE */
7834  /* PERFORMED. */
7835  /* --------------------------------------------------------------------------------- */
7836  tpfoPrevOverrecPtr = tpfoNextOverrecPtr;
7837  tpfoNextOverrecPtr.i = tpfoNextOverrecPtr.p->nextOverList;
7838  } else {
7839  jam();
7840  ndbrequire(tpfoNextOverrecPtr.p->dirindex != priOverflowRecPtr.p->dirindex);
7841  /* --------------------------------------------------------------------------------- */
7842  /* ENSURE WE ARE NOT TRYING TO INSERT THE SAME PAGE TWICE. */
7843  /* --------------------------------------------------------------------------------- */
7844  break;
7845  }//if
7846  }//while
7847  if (tpfoNextOverrecPtr.i != RNIL) {
7848  jam();
7849  tpfoNextOverrecPtr.p->prevOverList = priOverflowRecPtr.i;
7850  }//if
7851  if (tpfoPrevOverrecPtr.i == RNIL) {
7852  jam();
7853  fragrecptr.p->firstFreeDirindexRec = priOverflowRecPtr.i;
7854  } else {
7855  jam();
7856  tpfoPrevOverrecPtr.p->nextOverList = priOverflowRecPtr.i;
7857  }//if
7858  priOverflowRecPtr.p->prevOverList = tpfoPrevOverrecPtr.i;
7859  priOverflowRecPtr.p->nextOverList = tpfoNextOverrecPtr.i;
7860 }//Dbacc::putRecInFreeOverdir()
7861 
7862 /* --------------------------------------------------------------------------------- */
7863 /* RELEASE_DIRECTORY */
7864 /* --------------------------------------- ----------------------------------------- */
7865 void Dbacc::releaseDirectory(Signal* signal)
7866 {
7867  ptrCheckGuard(rdDirptr, cdirarraysize, directoryarray);
7868  rdDirptr.p->pagep[0] = cfirstfreedir;
7869  cfirstfreedir = rdDirptr.i;
7870 }//Dbacc::releaseDirectory()
7871 
7872 /* --------------------------------------------------------------------------------- */
7873 /* RELEASE_DIRRANGE */
7874 /* --------------------------------------------------------------------------------- */
7875 void Dbacc::releaseDirrange(Signal* signal)
7876 {
7877  ptrCheckGuard(rdDirRangePtr, cdirrangesize, dirRange);
7878  rdDirRangePtr.p->dirArray[0] = cfirstfreeDirrange;
7879  cfirstfreeDirrange = rdDirRangePtr.i;
7880 }//Dbacc::releaseDirrange()
7881 
7882 /* --------------------------------------------------------------------------------- */
7883 /* RELEASE OP RECORD */
7884 /* PUT A FREE OPERATION IN A FREE LIST OF THE OPERATIONS */
7885 /* --------------------------------------------------------------------------------- */
7886 void Dbacc::releaseOpRec(Signal* signal)
7887 {
7888 #if 0
7889  // DEBUG CODE
7890  // Check that the operation to be released isn't
7891  // already in the list of free operations
7892  // Since this code loops through the entire list of free operations
7893  // it's only enabled in VM_TRACE mode
7894  OperationrecPtr opRecPtr;
7895  bool opInList = false;
7896  opRecPtr.i = cfreeopRec;
7897  while (opRecPtr.i != RNIL){
7898  if (opRecPtr.i == operationRecPtr.i){
7899  opInList = true;
7900  break;
7901  }
7902  ptrCheckGuard(opRecPtr, coprecsize, operationrec);
7903  opRecPtr.i = opRecPtr.p->nextOp;
7904  }
7905  ndbrequire(opInList == false);
7906 #endif
7907  ndbrequire(operationRecPtr.p->m_op_bits == Operationrec::OP_INITIAL);
7908 
7909  operationRecPtr.p->nextOp = cfreeopRec;
7910  cfreeopRec = operationRecPtr.i; /* UPDATE FREE LIST OF OP RECORDS */
7911  operationRecPtr.p->prevOp = RNIL;
7912  operationRecPtr.p->m_op_bits = Operationrec::OP_INITIAL;
7913 }//Dbacc::releaseOpRec()
7914 
7915 /* --------------------------------------------------------------------------------- */
7916 /* RELEASE_OVERFLOW_REC */
7917 /* PUT A FREE OVERFLOW REC IN A FREE LIST OF THE OVERFLOW RECORDS */
7918 /* --------------------------------------------------------------------------------- */
7919 void Dbacc::releaseOverflowRec(Signal* signal)
7920 {
7921  rorOverflowRecPtr.p->nextfreeoverrec = cfirstfreeoverrec;
7922  cfirstfreeoverrec = rorOverflowRecPtr.i;
7923 }//Dbacc::releaseOverflowRec()
7924 
7925 /* --------------------------------------------------------------------------------- */
7926 /* RELEASE_OVERPAGE */
7927 /* --------------------------------------------------------------------------------- */
7928 void Dbacc::releaseOverpage(Signal* signal)
7929 {
7930  DirRangePtr ropOverflowrangeptr;
7931  DirectoryarrayPtr ropOverflowDirptr;
7932  OverflowRecordPtr ropOverflowRecPtr;
7933  OverflowRecordPtr tuodOverflowRecPtr;
7934  Uint32 tropTmp;
7935  Uint32 tropTmp1;
7936  Uint32 tropTmp2;
7937 
7938  ropOverflowRecPtr.i = ropPageptr.p->word32[ZPOS_OVERFLOWREC];
7939  ndbrequire(ropOverflowRecPtr.i != RNIL);
7940  /* THE OVERFLOW REC WILL BE TAKEN OUT OF THE */
7941  /* FREELIST OF OVERFLOW PAGE WITH FREE */
7942  /* CONTAINER AND WILL BE PUT IN THE FREE LIST */
7943  /* OF THE FREE DIRECTORY INDEXES. */
7944  if ((fragrecptr.p->lastOverflowRec == ropOverflowRecPtr.i) &&
7945  (fragrecptr.p->firstOverflowRec == ropOverflowRecPtr.i)) {
7946  jam();
7947  return; /* THERE IS ONLY ONE OVERFLOW PAGE */
7948  }//if
7949 #if kalle
7950  logicalPage = 0;
7951 
7952  i = fragrecptr.p->directory;
7953  p = dirRange.getPtr(i);
7954 
7955  i1 = logicalPage >> 8;
7956  i2 = logicalPage & 0xFF;
7957 
7958  ndbrequire(i1 < 256);
7959 
7960  i = p->dirArray[i1];
7961  p = directoryarray.getPtr(i);
7962 
7963  physicPageId = p->pagep[i2];
7964  physicPageP = page8.getPtr(physicPageId);
7965 
7966  p->pagep[i2] = RNIL;
7967  rpPageptr = { physicPageId, physicPageP };
7968  releasePage(signal);
7969 
7970 #endif
7971 
7972  /* ----------------------------------------------------------------------- */
7973  /* IT WAS OK TO RELEASE THE PAGE. */
7974  /* ----------------------------------------------------------------------- */
7975  ptrCheckGuard(ropOverflowRecPtr, coverflowrecsize, overflowRecord);
7976  tfoOverflowRecPtr = ropOverflowRecPtr;
7977  takeRecOutOfFreeOverpage(signal);
7978  ropOverflowRecPtr.p->overpage = RNIL;
7979  priOverflowRecPtr = ropOverflowRecPtr;
7980  putRecInFreeOverdir(signal);
7981  tropTmp = ropPageptr.p->word32[ZPOS_PAGE_ID];
7982  ropOverflowrangeptr.i = fragrecptr.p->overflowdir;
7983  tropTmp1 = tropTmp >> 8;
7984  tropTmp2 = tropTmp & 0xff;
7985  ptrCheckGuard(ropOverflowrangeptr, cdirrangesize, dirRange);
7986  arrGuard(tropTmp1, 256);
7987  ropOverflowDirptr.i = ropOverflowrangeptr.p->dirArray[tropTmp1];
7988  ptrCheckGuard(ropOverflowDirptr, cdirarraysize, directoryarray);
7989  ropOverflowDirptr.p->pagep[tropTmp2] = RNIL;
7990  rpPageptr = ropPageptr;
7991  releasePage(signal);
7992  if (ropOverflowRecPtr.p->dirindex != (fragrecptr.p->lastOverIndex - 1)) {
7993  jam();
7994  return;
7995  }//if
7996  /* ----------------------------------------------------------------------- */
7997  /* THE LAST PAGE IN THE DIRECTORY WAS RELEASED IT IS NOW NECESSARY
7998  * TO REMOVE ALL RELEASED OVERFLOW DIRECTORIES AT THE END OF THE LIST.
7999  * ---------------------------------------------------------------------- */
8000  do {
8001  fragrecptr.p->lastOverIndex--;
8002  if (tropTmp2 == 0) {
8003  jam();
8004  ndbrequire(tropTmp1 != 0);
8005  ropOverflowrangeptr.p->dirArray[tropTmp1] = RNIL;
8006  rdDirptr.i = ropOverflowDirptr.i;
8007  releaseDirectory(signal);
8008  tropTmp1--;
8009  tropTmp2 = 255;
8010  } else {
8011  jam();
8012  tropTmp2--;
8013  }//if
8014  ropOverflowDirptr.i = ropOverflowrangeptr.p->dirArray[tropTmp1];
8015  ptrCheckGuard(ropOverflowDirptr, cdirarraysize, directoryarray);
8016  } while (ropOverflowDirptr.p->pagep[tropTmp2] == RNIL);
8017  /* ----------------------------------------------------------------------- */
8018  /* RELEASE ANY OVERFLOW RECORDS THAT ARE PART OF THE FREE INDEX LIST WHICH */
8019  /* DIRECTORY INDEX NOW HAS BEEN RELEASED. */
8020  /* ----------------------------------------------------------------------- */
8021  tuodOverflowRecPtr.i = fragrecptr.p->firstFreeDirindexRec;
8022  jam();
8023  while (tuodOverflowRecPtr.i != RNIL) {
8024  jam();
8025  ptrCheckGuard(tuodOverflowRecPtr, coverflowrecsize, overflowRecord);
8026  if (tuodOverflowRecPtr.p->dirindex >= fragrecptr.p->lastOverIndex) {
8027  jam();
8028  rorOverflowRecPtr = tuodOverflowRecPtr;
8029  troOverflowRecPtr.p = tuodOverflowRecPtr.p;
8030  tuodOverflowRecPtr.i = troOverflowRecPtr.p->nextOverList;
8031  takeRecOutOfFreeOverdir(signal);
8032  releaseOverflowRec(signal);
8033  } else {
8034  jam();
8035  tuodOverflowRecPtr.i = tuodOverflowRecPtr.p->nextOverList;
8036  }//if
8037  }//while
8038 }//Dbacc::releaseOverpage()
8039 
8040 
8041 extern Uint32 g_acc_pages_used[MAX_NDBMT_LQH_WORKERS];
8042 
8043 /* ------------------------------------------------------------------------- */
8044 /* RELEASE_PAGE */
8045 /* ------------------------------------------------------------------------- */
8046 void Dbacc::releasePage(Signal* signal)
8047 {
8048 #ifdef VM_TRACE
8049  bool inList = false;
8050  Uint32 numInList = 0;
8051  Page8Ptr tmpPagePtr;
8052  tmpPagePtr.i = cfirstfreepage;
8053  while (tmpPagePtr.i != RNIL){
8054  ptrCheckGuard(tmpPagePtr, cpagesize, page8);
8055  if (tmpPagePtr.i == rpPageptr.i){
8056  jam(); inList = true;
8057  break;
8058  }
8059  numInList++;
8060  tmpPagePtr.i = tmpPagePtr.p->word32[0];
8061  }
8062  ndbrequire(inList == false);
8063  // ndbrequire(numInList == cnoOfAllocatedPages);
8064 #endif
8065  rpPageptr.p->word32[0] = cfirstfreepage;
8066  cfirstfreepage = rpPageptr.i;
8067  cnoOfAllocatedPages--;
8068 
8069  g_acc_pages_used[instance()] = cnoOfAllocatedPages;
8070 
8071 }//Dbacc::releasePage()
8072 
8073 /* --------------------------------------------------------------------------------- */
8074 /* SEIZE_DIRECTORY */
8075 /* DESCRIPTION: A DIRECTORY BLOCK (ZDIRBLOCKSIZE NUMBERS OF DIRECTORY */
8076 /* RECORDS WILL BE ALLOCATED AND RETURNED. */
8077 /* SIZE OF DIRECTORY ERROR_CODE, WILL BE RETURNED IF THERE IS NO ANY */
8078 /* FREE BLOCK */
8079 /* --------------------------------------------------------------------------------- */
8080 void Dbacc::seizeDirectory(Signal* signal)
8081 {
8082  Uint32 tsdyIndex;
8083 
8084  if (cfirstfreedir == RNIL) {
8085  jam();
8086  if (cdirarraysize <= cdirmemory) {
8087  jam();
8088  tresult = ZDIRSIZE_ERROR;
8089  return;
8090  } else {
8091  jam();
8092  sdDirptr.i = cdirmemory;
8093  ptrCheckGuard(sdDirptr, cdirarraysize, directoryarray);
8094  cdirmemory = cdirmemory + 1;
8095  }//if
8096  } else {
8097  jam();
8098  sdDirptr.i = cfirstfreedir;
8099  ptrCheckGuard(sdDirptr, cdirarraysize, directoryarray);
8100  cfirstfreedir = sdDirptr.p->pagep[0];
8101  sdDirptr.p->pagep[0] = RNIL;
8102  }//if
8103  for (tsdyIndex = 0; tsdyIndex <= 255; tsdyIndex++) {
8104  sdDirptr.p->pagep[tsdyIndex] = RNIL;
8105  }//for
8106 }//Dbacc::seizeDirectory()
8107 
8108 /* --------------------------------------------------------------------------------- */
8109 /* SEIZE_DIRRANGE */
8110 /* --------------------------------------------------------------------------------- */
8111 void Dbacc::seizeDirrange(Signal* signal)
8112 {
8113  Uint32 tsdeIndex;
8114 
8115  newDirRangePtr.i = cfirstfreeDirrange;
8116  ptrCheckGuard(newDirRangePtr, cdirrangesize, dirRange);
8117  cfirstfreeDirrange = newDirRangePtr.p->dirArray[0];
8118  for (tsdeIndex = 0; tsdeIndex <= 255; tsdeIndex++) {
8119  newDirRangePtr.p->dirArray[tsdeIndex] = RNIL;
8120  }//for
8121 }//Dbacc::seizeDirrange()
8122 
8123 /* --------------------------------------------------------------------------------- */
8124 /* SEIZE FRAGREC */
8125 /* --------------------------------------------------------------------------------- */
8126 void Dbacc::seizeFragrec(Signal* signal)
8127 {
8128  RSS_OP_ALLOC(cnoOfFreeFragrec);
8129  fragrecptr.i = cfirstfreefrag;
8130  ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
8131  cfirstfreefrag = fragrecptr.p->nextfreefrag;
8132  fragrecptr.p->nextfreefrag = RNIL;
8133 }//Dbacc::seizeFragrec()
8134 
8135 /* --------------------------------------------------------------------------------- */
8136 /* SEIZE_OP_REC */
8137 /* --------------------------------------------------------------------------------- */
8138 void Dbacc::seizeOpRec(Signal* signal)
8139 {
8140  operationRecPtr.i = cfreeopRec;
8141  ptrCheckGuard(operationRecPtr, coprecsize, operationrec);
8142  cfreeopRec = operationRecPtr.p->nextOp; /* UPDATE FREE LIST OF OP RECORDS */
8143  /* PUTS OPERTION RECORD PTR IN THE LIST */
8144  /* OF OPERATION IN CONNECTION RECORD */
8145  operationRecPtr.p->nextOp = RNIL;
8146 }//Dbacc::seizeOpRec()
8147 
8148 /* --------------------------------------------------------------------------------- */
8149 /* SEIZE OVERFLOW RECORD */
8150 /* --------------------------------------------------------------------------------- */
8151 void Dbacc::seizeOverRec(Signal* signal) {
8152  sorOverflowRecPtr.i = cfirstfreeoverrec;
8153  ptrCheckGuard(sorOverflowRecPtr, coverflowrecsize, overflowRecord);
8154  cfirstfreeoverrec = sorOverflowRecPtr.p->nextfreeoverrec;
8155  sorOverflowRecPtr.p->nextfreeoverrec = RNIL;
8156  sorOverflowRecPtr.p->prevOverRec = RNIL;
8157  sorOverflowRecPtr.p->nextOverRec = RNIL;
8158 }//Dbacc::seizeOverRec()
8159 
8160 
8165 void Dbacc::zpagesize_error(const char* where){
8166  DEBUG(where << endl
8167  << " ZPAGESIZE_ERROR" << endl
8168  << " cfirstfreepage=" << cfirstfreepage << endl
8169  << " cpagesize=" <<cpagesize<<endl
8170  << " cnoOfAllocatedPages="<<cnoOfAllocatedPages);
8171 }
8172 
8173 
8174 /* --------------------------------------------------------------------------------- */
8175 /* SEIZE_PAGE */
8176 /* --------------------------------------------------------------------------------- */
8177 void Dbacc::seizePage(Signal* signal)
8178 {
8179  tresult = 0;
8180  if (cfirstfreepage == RNIL)
8181  {
8182  jam();
8183  zpagesize_error("Dbacc::seizePage");
8184  tresult = ZPAGESIZE_ERROR;
8185  }
8186  else
8187  {
8188  jam();
8189  spPageptr.i = cfirstfreepage;
8190  ptrCheckGuard(spPageptr, cpagesize, page8);
8191  cfirstfreepage = spPageptr.p->word32[0];
8192  cnoOfAllocatedPages++;
8193 
8194  if (cnoOfAllocatedPages > cnoOfAllocatedPagesMax)
8195  cnoOfAllocatedPagesMax = cnoOfAllocatedPages;
8196 
8197  g_acc_pages_used[instance()] = cnoOfAllocatedPages;
8198 
8199  }
8200 
8201 }//Dbacc::seizePage()
8202 
8203 /* --------------------------------------------------------------------------------- */
8204 /* SEIZE_ROOTFRAGREC */
8205 /* --------------------------------------------------------------------------------- */
8206 
8207 /* --------------------------------------------------------------------------------- */
8208 /* SEIZE_SCAN_REC */
8209 /* --------------------------------------------------------------------------------- */
8210 void Dbacc::seizeScanRec(Signal* signal)
8211 {
8212  scanPtr.i = cfirstFreeScanRec;
8213  ptrCheckGuard(scanPtr, cscanRecSize, scanRec);
8214  ndbrequire(scanPtr.p->scanState == ScanRec::SCAN_DISCONNECT);
8215  cfirstFreeScanRec = scanPtr.p->scanNextfreerec;
8216 }//Dbacc::seizeScanRec()
8217 
8218 /* --------------------------------------------------------------------------------- */
8219 /* SEIZE_SR_VERSION_REC */
8220 /* --------------------------------------------------------------------------------- */
8221 /* --------------------------------------------------------------------------------- */
8222 /* SEND_SYSTEMERROR */
8223 /* --------------------------------------------------------------------------------- */
8224 void Dbacc::sendSystemerror(Signal* signal, int line)
8225 {
8226  progError(line, NDBD_EXIT_PRGERR);
8227 }//Dbacc::sendSystemerror()
8228 
8229 /* --------------------------------------------------------------------------------- */
8230 /* TAKE_REC_OUT_OF_FREE_OVERDIR */
8231 /* --------------------------------------------------------------------------------- */
8232 void Dbacc::takeRecOutOfFreeOverdir(Signal* signal)
8233 {
8234  OverflowRecordPtr tofoOverrecPtr;
8235  if (troOverflowRecPtr.p->nextOverList != RNIL) {
8236  jam();
8237  tofoOverrecPtr.i = troOverflowRecPtr.p->nextOverList;
8238  ptrCheckGuard(tofoOverrecPtr, coverflowrecsize, overflowRecord);
8239  tofoOverrecPtr.p->prevOverList = troOverflowRecPtr.p->prevOverList;
8240  }//if
8241  if (troOverflowRecPtr.p->prevOverList != RNIL) {
8242  jam();
8243  tofoOverrecPtr.i = troOverflowRecPtr.p->prevOverList;
8244  ptrCheckGuard(tofoOverrecPtr, coverflowrecsize, overflowRecord);
8245  tofoOverrecPtr.p->nextOverList = troOverflowRecPtr.p->nextOverList;
8246  } else {
8247  jam();
8248  fragrecptr.p->firstFreeDirindexRec = troOverflowRecPtr.p->nextOverList;
8249  }//if
8250 }//Dbacc::takeRecOutOfFreeOverdir()
8251 
8252 /* --------------------------------------------------------------------------------- */
8253 /* TAKE_REC_OUT_OF_FREE_OVERPAGE */
8254 /* DESCRIPTION: AN OVERFLOW PAGE WHICH IS EMPTY HAVE TO BE TAKE OUT OF THE */
8255 /* FREE LIST OF OVERFLOW PAGE. BY THIS SUBROUTINE THIS LIST */
8256 /* WILL BE UPDATED. */
8257 /* --------------------------------------------------------------------------------- */
8258 void Dbacc::takeRecOutOfFreeOverpage(Signal* signal)
8259 {
8260  OverflowRecordPtr tfoNextOverflowRecPtr;
8261  OverflowRecordPtr tfoPrevOverflowRecPtr;
8262 
8263  if (tfoOverflowRecPtr.p->nextOverRec != RNIL) {
8264  jam();
8265  tfoNextOverflowRecPtr.i = tfoOverflowRecPtr.p->nextOverRec;
8266  ptrCheckGuard(tfoNextOverflowRecPtr, coverflowrecsize, overflowRecord);
8267  tfoNextOverflowRecPtr.p->prevOverRec = tfoOverflowRecPtr.p->prevOverRec;
8268  } else {
8269  ndbrequire(fragrecptr.p->lastOverflowRec == tfoOverflowRecPtr.i);
8270  jam();
8271  fragrecptr.p->lastOverflowRec = tfoOverflowRecPtr.p->prevOverRec;
8272  }//if
8273  if (tfoOverflowRecPtr.p->prevOverRec != RNIL) {
8274  jam();
8275  tfoPrevOverflowRecPtr.i = tfoOverflowRecPtr.p->prevOverRec;
8276  ptrCheckGuard(tfoPrevOverflowRecPtr, coverflowrecsize, overflowRecord);
8277  tfoPrevOverflowRecPtr.p->nextOverRec = tfoOverflowRecPtr.p->nextOverRec;
8278  } else {
8279  ndbrequire(fragrecptr.p->firstOverflowRec == tfoOverflowRecPtr.i);
8280  jam();
8281  fragrecptr.p->firstOverflowRec = tfoOverflowRecPtr.p->nextOverRec;
8282  }//if
8283 }//Dbacc::takeRecOutOfFreeOverpage()
8284 
8285 
8286 void Dbacc::execDBINFO_SCANREQ(Signal *signal)
8287 {
8288  jamEntry();
8289  DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
8290  const Ndbinfo::ScanCursor* cursor =
8291  CAST_CONSTPTR(Ndbinfo::ScanCursor, DbinfoScan::getCursorPtr(&req));
8292 
8293  Ndbinfo::Ratelimit rl;
8294 
8295  switch(req.tableId){
8296  case Ndbinfo::POOLS_TABLEID:
8297  {
8298  jam();
8299 
8300  Ndbinfo::pool_entry pools[] =
8301  {
8302  { "Index memory",
8303  cnoOfAllocatedPages,
8304  cpageCount,
8305  sizeof(Page8),
8306  cnoOfAllocatedPagesMax,
8307  { CFG_DB_INDEX_MEM,0,0,0 }},
8308  { NULL, 0,0,0,0,{ 0,0,0,0 }}
8309  };
8310 
8311  static const size_t num_config_params =
8312  sizeof(pools[0].config_params)/sizeof(pools[0].config_params[0]);
8313  Uint32 pool = cursor->data[0];
8314  BlockNumber bn = blockToMain(number());
8315  while(pools[pool].poolname)
8316  {
8317  jam();
8318  Ndbinfo::Row row(signal, req);
8319  row.write_uint32(getOwnNodeId());
8320  row.write_uint32(bn); // block number
8321  row.write_uint32(instance()); // block instance
8322  row.write_string(pools[pool].poolname);
8323 
8324  row.write_uint64(pools[pool].used);
8325  row.write_uint64(pools[pool].total);
8326  row.write_uint64(pools[pool].used_hi);
8327  row.write_uint64(pools[pool].entry_size);
8328  for (size_t i = 0; i < num_config_params; i++)
8329  row.write_uint32(pools[pool].config_params[i]);
8330  ndbinfo_send_row(signal, req, row, rl);
8331  pool++;
8332  if (rl.need_break(req))
8333  {
8334  jam();
8335  ndbinfo_send_scan_break(signal, req, rl, pool);
8336  return;
8337  }
8338  }
8339  }
8340  default:
8341  break;
8342  }
8343 
8344  ndbinfo_send_scan_conf(signal, req, rl);
8345 }
8346 
8347 void
8348 Dbacc::execDUMP_STATE_ORD(Signal* signal)
8349 {
8350  DumpStateOrd * const dumpState = (DumpStateOrd *)&signal->theData[0];
8351  if (dumpState->args[0] == DumpStateOrd::AccDumpOneScanRec){
8352  Uint32 recordNo = RNIL;
8353  if (signal->length() == 2)
8354  recordNo = dumpState->args[1];
8355  else
8356  return;
8357 
8358  if (recordNo >= cscanRecSize)
8359  return;
8360 
8361  scanPtr.i = recordNo;
8362  ptrAss(scanPtr, scanRec);
8363  infoEvent("Dbacc::ScanRec[%d]: state=%d, transid(0x%x, 0x%x)",
8364  scanPtr.i, scanPtr.p->scanState,scanPtr.p->scanTrid1,
8365  scanPtr.p->scanTrid2);
8366  infoEvent(" activeLocalFrag=%d, nextBucketIndex=%d",
8367  scanPtr.p->activeLocalFrag,
8368  scanPtr.p->nextBucketIndex);
8369  infoEvent(" scanNextfreerec=%d firstActOp=%d firstLockedOp=%d, "
8370  "scanLastLockedOp=%d firstQOp=%d lastQOp=%d",
8371  scanPtr.p->scanNextfreerec,
8372  scanPtr.p->scanFirstActiveOp,
8373  scanPtr.p->scanFirstLockedOp,
8374  scanPtr.p->scanLastLockedOp,
8375  scanPtr.p->scanFirstQueuedOp,
8376  scanPtr.p->scanLastQueuedOp);
8377  infoEvent(" scanUserP=%d, startNoBuck=%d, minBucketIndexToRescan=%d, "
8378  "maxBucketIndexToRescan=%d",
8379  scanPtr.p->scanUserptr,
8380  scanPtr.p->startNoOfBuckets,
8381  scanPtr.p->minBucketIndexToRescan,
8382  scanPtr.p->maxBucketIndexToRescan);
8383  infoEvent(" scanBucketState=%d, scanLockHeld=%d, userBlockRef=%d, "
8384  "scanMask=%d scanLockMode=%d",
8385  scanPtr.p->scanBucketState,
8386  scanPtr.p->scanLockHeld,
8387  scanPtr.p->scanUserblockref,
8388  scanPtr.p->scanMask,
8389  scanPtr.p->scanLockMode);
8390  return;
8391  }
8392 
8393  // Dump all ScanRec(ords)
8394  if (dumpState->args[0] == DumpStateOrd::AccDumpAllScanRec){
8395  Uint32 recordNo = 0;
8396  if (signal->length() == 1)
8397  infoEvent("ACC: Dump all ScanRec - size: %d",
8398  cscanRecSize);
8399  else if (signal->length() == 2)
8400  recordNo = dumpState->args[1];
8401  else
8402  return;
8403 
8404  dumpState->args[0] = DumpStateOrd::AccDumpOneScanRec;
8405  dumpState->args[1] = recordNo;
8406  execDUMP_STATE_ORD(signal);
8407 
8408  if (recordNo < cscanRecSize-1){
8409  dumpState->args[0] = DumpStateOrd::AccDumpAllScanRec;
8410  dumpState->args[1] = recordNo+1;
8411  sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
8412  }
8413  return;
8414  }
8415 
8416  // Dump all active ScanRec(ords)
8417  if (dumpState->args[0] == DumpStateOrd::AccDumpAllActiveScanRec){
8418  Uint32 recordNo = 0;
8419  if (signal->length() == 1)
8420  infoEvent("ACC: Dump active ScanRec - size: %d",
8421  cscanRecSize);
8422  else if (signal->length() == 2)
8423  recordNo = dumpState->args[1];
8424  else
8425  return;
8426 
8427  ScanRecPtr sp;
8428  sp.i = recordNo;
8429  ptrAss(sp, scanRec);
8430  if (sp.p->scanState != ScanRec::SCAN_DISCONNECT){
8431  dumpState->args[0] = DumpStateOrd::AccDumpOneScanRec;
8432  dumpState->args[1] = recordNo;
8433  execDUMP_STATE_ORD(signal);
8434  }
8435 
8436  if (recordNo < cscanRecSize-1){
8437  dumpState->args[0] = DumpStateOrd::AccDumpAllActiveScanRec;
8438  dumpState->args[1] = recordNo+1;
8439  sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
8440  }
8441  return;
8442  }
8443 
8444  if(dumpState->args[0] == DumpStateOrd::EnableUndoDelayDataWrite){
8445  ndbout << "Dbacc:: delay write of datapages for table = "
8446  << dumpState->args[1]<< endl;
8447  c_errorInsert3000_TableId = dumpState->args[1];
8448  SET_ERROR_INSERT_VALUE(3000);
8449  return;
8450  }
8451 
8452  if(dumpState->args[0] == DumpStateOrd::AccDumpOneOperationRec){
8453  Uint32 recordNo = RNIL;
8454  if (signal->length() == 2)
8455  recordNo = dumpState->args[1];
8456  else
8457  return;
8458 
8459  if (recordNo >= coprecsize)
8460  return;
8461 
8462  OperationrecPtr tmpOpPtr;
8463  tmpOpPtr.i = recordNo;
8464  ptrAss(tmpOpPtr, operationrec);
8465  infoEvent("Dbacc::operationrec[%d]: transid(0x%x, 0x%x)",
8466  tmpOpPtr.i, tmpOpPtr.p->transId1,
8467  tmpOpPtr.p->transId2);
8468  infoEvent("elementIsforward=%d, elementPage=%d, elementPointer=%d ",
8469  tmpOpPtr.p->elementIsforward, tmpOpPtr.p->elementPage,
8470  tmpOpPtr.p->elementPointer);
8471  infoEvent("fid=%d, fragptr=%d, hashvaluePart=%d ",
8472  tmpOpPtr.p->fid, tmpOpPtr.p->fragptr,
8473  tmpOpPtr.p->hashvaluePart);
8474  infoEvent("hashValue=%d", tmpOpPtr.p->hashValue);
8475  infoEvent("nextLockOwnerOp=%d, nextOp=%d, nextParallelQue=%d ",
8476  tmpOpPtr.p->nextLockOwnerOp, tmpOpPtr.p->nextOp,
8477  tmpOpPtr.p->nextParallelQue);
8478  infoEvent("nextSerialQue=%d, prevOp=%d ",
8479  tmpOpPtr.p->nextSerialQue,
8480  tmpOpPtr.p->prevOp);
8481  infoEvent("prevLockOwnerOp=%d, prevParallelQue=%d",
8482  tmpOpPtr.p->prevLockOwnerOp, tmpOpPtr.p->nextParallelQue);
8483  infoEvent("prevSerialQue=%d, scanRecPtr=%d",
8484  tmpOpPtr.p->prevSerialQue, tmpOpPtr.p->scanRecPtr);
8485  infoEvent("m_op_bits=0x%x, scanBits=%d ",
8486  tmpOpPtr.p->m_op_bits, tmpOpPtr.p->scanBits);
8487  return;
8488  }
8489 
8490  if(dumpState->args[0] == DumpStateOrd::AccDumpNumOpRecs){
8491 
8492  Uint32 freeOpRecs = 0;
8493  OperationrecPtr opRecPtr;
8494  opRecPtr.i = cfreeopRec;
8495  while (opRecPtr.i != RNIL){
8496  freeOpRecs++;
8497  ptrCheckGuard(opRecPtr, coprecsize, operationrec);
8498  opRecPtr.i = opRecPtr.p->nextOp;
8499  }
8500 
8501  infoEvent("Dbacc::OperationRecords: num=%d, free=%d",
8502  coprecsize, freeOpRecs);
8503 
8504  return;
8505  }
8506  if(dumpState->args[0] == DumpStateOrd::AccDumpFreeOpRecs){
8507 
8508  OperationrecPtr opRecPtr;
8509  opRecPtr.i = cfreeopRec;
8510  while (opRecPtr.i != RNIL){
8511 
8512  dumpState->args[0] = DumpStateOrd::AccDumpOneOperationRec;
8513  dumpState->args[1] = opRecPtr.i;
8514  execDUMP_STATE_ORD(signal);
8515 
8516  ptrCheckGuard(opRecPtr, coprecsize, operationrec);
8517  opRecPtr.i = opRecPtr.p->nextOp;
8518  }
8519 
8520 
8521  return;
8522  }
8523 
8524  if(dumpState->args[0] == DumpStateOrd::AccDumpNotFreeOpRecs){
8525  Uint32 recordStart = RNIL;
8526  if (signal->length() == 2)
8527  recordStart = dumpState->args[1];
8528  else
8529  return;
8530 
8531  if (recordStart >= coprecsize)
8532  return;
8533 
8534  for (Uint32 i = recordStart; i < coprecsize; i++){
8535 
8536  bool inFreeList = false;
8537  OperationrecPtr opRecPtr;
8538  opRecPtr.i = cfreeopRec;
8539  while (opRecPtr.i != RNIL){
8540  if (opRecPtr.i == i){
8541  inFreeList = true;
8542  break;
8543  }
8544  ptrCheckGuard(opRecPtr, coprecsize, operationrec);
8545  opRecPtr.i = opRecPtr.p->nextOp;
8546  }
8547  if (inFreeList == false){
8548  dumpState->args[0] = DumpStateOrd::AccDumpOneOperationRec;
8549  dumpState->args[1] = i;
8550  execDUMP_STATE_ORD(signal);
8551  }
8552  }
8553  return;
8554  }
8555 
8556 #if 0
8557  if (type == 100) {
8558  RelTabMemReq * const req = (RelTabMemReq *)signal->getDataPtrSend();
8559  req->primaryTableId = 2;
8560  req->secondaryTableId = RNIL;
8561  req->userPtr = 2;
8562  req->userRef = DBDICT_REF;
8563  sendSignal(cownBlockref, GSN_REL_TABMEMREQ, signal,
8564  RelTabMemReq::SignalLength, JBB);
8565  return;
8566  }//if
8567  if (type == 101) {
8568  RelTabMemReq * const req = (RelTabMemReq *)signal->getDataPtrSend();
8569  req->primaryTableId = 4;
8570  req->secondaryTableId = 5;
8571  req->userPtr = 4;
8572  req->userRef = DBDICT_REF;
8573  sendSignal(cownBlockref, GSN_REL_TABMEMREQ, signal,
8574  RelTabMemReq::SignalLength, JBB);
8575  return;
8576  }//if
8577  if (type == 102) {
8578  RelTabMemReq * const req = (RelTabMemReq *)signal->getDataPtrSend();
8579  req->primaryTableId = 6;
8580  req->secondaryTableId = 8;
8581  req->userPtr = 6;
8582  req->userRef = DBDICT_REF;
8583  sendSignal(cownBlockref, GSN_REL_TABMEMREQ, signal,
8584  RelTabMemReq::SignalLength, JBB);
8585  return;
8586  }//if
8587  if (type == 103) {
8588  DropTabFileReq * const req = (DropTabFileReq *)signal->getDataPtrSend();
8589  req->primaryTableId = 2;
8590  req->secondaryTableId = RNIL;
8591  req->userPtr = 2;
8592  req->userRef = DBDICT_REF;
8593  sendSignal(cownBlockref, GSN_DROP_TABFILEREQ, signal,
8594  DropTabFileReq::SignalLength, JBB);
8595  return;
8596  }//if
8597  if (type == 104) {
8598  DropTabFileReq * const req = (DropTabFileReq *)signal->getDataPtrSend();
8599  req->primaryTableId = 4;
8600  req->secondaryTableId = 5;
8601  req->userPtr = 4;
8602  req->userRef = DBDICT_REF;
8603  sendSignal(cownBlockref, GSN_DROP_TABFILEREQ, signal,
8604  DropTabFileReq::SignalLength, JBB);
8605  return;
8606  }//if
8607  if (type == 105) {
8608  DropTabFileReq * const req = (DropTabFileReq *)signal->getDataPtrSend();
8609  req->primaryTableId = 6;
8610  req->secondaryTableId = 8;
8611  req->userPtr = 6;
8612  req->userRef = DBDICT_REF;
8613  sendSignal(cownBlockref, GSN_DROP_TABFILEREQ, signal,
8614  DropTabFileReq::SignalLength, JBB);
8615  return;
8616  }//if
8617 #endif
8618 
8619  if (signal->theData[0] == DumpStateOrd::SchemaResourceSnapshot)
8620  {
8621  RSS_OP_SNAPSHOT_SAVE(cnoOfFreeFragrec);
8622  return;
8623  }
8624 
8625  if (signal->theData[0] == DumpStateOrd::SchemaResourceCheckLeak)
8626  {
8627  RSS_OP_SNAPSHOT_CHECK(cnoOfFreeFragrec);
8628  return;
8629  }
8630 }//Dbacc::execDUMP_STATE_ORD()
8631 
8632 void
8633 Dbacc::execREAD_PSEUDO_REQ(Signal* signal){
8634  jamEntry();
8635  fragrecptr.i = signal->theData[0];
8636  Uint32 attrId = signal->theData[1];
8637  ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
8638  Uint64 tmp;
8639  switch(attrId){
8640  case AttributeHeader::ROW_COUNT:
8641  tmp = fragrecptr.p->noOfElements;
8642  break;
8643  case AttributeHeader::COMMIT_COUNT:
8644  tmp = fragrecptr.p->m_commit_count;
8645  break;
8646  default:
8647  tmp = 0;
8648  }
8649  memcpy(signal->theData, &tmp, 8); /* must be memcpy, gives strange results on
8650  * ithanium gcc (GCC) 3.4.1 smp linux 2.4
8651  * otherwise
8652  */
8653  // Uint32 * src = (Uint32*)&tmp;
8654  // signal->theData[0] = src[0];
8655  // signal->theData[1] = src[1];
8656 }
8657 
8658 #ifdef VM_TRACE
8659 void
8660 Dbacc::debug_lh_vars(const char* where)
8661 {
8662  Uint32 b = fragrecptr.p->maxp + fragrecptr.p->p;
8663  Uint32 di = b >> fragrecptr.p->k;
8664  Uint32 ri = di >> 8;
8665  ndbout
8666  << "DBACC: " << where << ":"
8667  << " frag:" << fragrecptr.p->myTableId
8668  << "/" << fragrecptr.p->myfid
8669  << " slack:" << (Int32)fragrecptr.p->slack
8670  << "/" << fragrecptr.p->slackCheck
8671  << " maxp:" << fragrecptr.p->maxp
8672  << " p:" << fragrecptr.p->p
8673  << " di:" << di
8674  << " ri:" << ri
8675  << " full:" << fragrecptr.p->dirRangeFull
8676  << "\n";
8677 }
8678 #endif