MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DbtcMain.cpp
1 /*
2  Copyright (c) 2003, 2011, 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 DBTC_C
19 
20 #include "Dbtc.hpp"
21 #include "md5_hash.hpp"
22 #include <RefConvert.hpp>
23 #include <ndb_limits.h>
24 #include <ndb_rand.h>
25 
26 #include <signaldata/DiGetNodes.hpp>
27 #include <signaldata/EventReport.hpp>
28 #include <signaldata/TcKeyReq.hpp>
29 #include <signaldata/TcKeyConf.hpp>
30 #include <signaldata/TcKeyRef.hpp>
31 #include <signaldata/KeyInfo.hpp>
32 #include <signaldata/AttrInfo.hpp>
33 #include <signaldata/TransIdAI.hpp>
34 #include <signaldata/TcRollbackRep.hpp>
35 #include <signaldata/NodeFailRep.hpp>
36 #include <signaldata/ReadNodesConf.hpp>
37 #include <signaldata/NFCompleteRep.hpp>
38 #include <signaldata/LqhKey.hpp>
39 #include <signaldata/TcCommit.hpp>
40 #include <signaldata/TcContinueB.hpp>
41 #include <signaldata/TcKeyFailConf.hpp>
42 #include <signaldata/AbortAll.hpp>
43 #include <signaldata/DihScanTab.hpp>
44 #include <signaldata/ScanFrag.hpp>
45 #include <signaldata/ScanTab.hpp>
46 #include <signaldata/PrepDropTab.hpp>
47 #include <signaldata/DropTab.hpp>
48 #include <signaldata/AlterTab.hpp>
49 #include <signaldata/CreateTrig.hpp>
50 #include <signaldata/CreateTrigImpl.hpp>
51 #include <signaldata/DropTrig.hpp>
52 #include <signaldata/DropTrigImpl.hpp>
53 #include <signaldata/FireTrigOrd.hpp>
54 #include <signaldata/TrigAttrInfo.hpp>
55 #include <signaldata/CreateIndx.hpp>
56 #include <signaldata/CreateIndxImpl.hpp>
57 #include <signaldata/DropIndx.hpp>
58 #include <signaldata/DropIndxImpl.hpp>
59 #include <signaldata/AlterIndx.hpp>
60 #include <signaldata/AlterIndxImpl.hpp>
61 #include <signaldata/ScanTab.hpp>
62 #include <signaldata/SystemError.hpp>
63 #include <signaldata/DumpStateOrd.hpp>
64 #include <signaldata/DisconnectRep.hpp>
65 #include <signaldata/TcHbRep.hpp>
66 
67 #include <signaldata/PrepDropTab.hpp>
68 #include <signaldata/DropTab.hpp>
69 #include <signaldata/TcIndx.hpp>
70 #include <signaldata/IndxKeyInfo.hpp>
71 #include <signaldata/IndxAttrInfo.hpp>
72 #include <signaldata/PackedSignal.hpp>
73 #include <signaldata/SignalDroppedRep.hpp>
74 #include <AttributeHeader.hpp>
75 #include <signaldata/DictTabInfo.hpp>
76 #include <AttributeDescriptor.hpp>
77 #include <SectionReader.hpp>
78 #include <KeyDescriptor.hpp>
79 
80 #include <NdbOut.hpp>
81 #include <DebuggerNames.hpp>
82 #include <signaldata/CheckNodeGroups.hpp>
83 
84 #include <signaldata/RouteOrd.hpp>
85 #include <signaldata/GCP.hpp>
86 
87 #include <signaldata/DbinfoScan.hpp>
88 #include <signaldata/TransIdAI.hpp>
89 #include <signaldata/CreateTab.hpp>
90 
91 // Use DEBUG to print messages that should be
92 // seen only when we debug the product
93 #ifdef VM_TRACE
94 #define DEBUG(x) ndbout << "DBTC: "<< x << endl;
95 #else
96 #define DEBUG(x)
97 #endif
98 
99 #define INTERNAL_TRIGGER_TCKEYREQ_JBA 0
100 
101 #ifdef VM_TRACE
102 NdbOut &
103 operator<<(NdbOut& out, Dbtc::ConnectionState state){
104  switch(state){
105  case Dbtc::CS_CONNECTED: out << "CS_CONNECTED"; break;
106  case Dbtc::CS_DISCONNECTED: out << "CS_DISCONNECTED"; break;
107  case Dbtc::CS_STARTED: out << "CS_STARTED"; break;
108  case Dbtc::CS_RECEIVING: out << "CS_RECEIVING"; break;
109  case Dbtc::CS_PREPARED: out << "CS_PREPARED"; break;
110  case Dbtc::CS_START_PREPARING: out << "CS_START_PREPARING"; break;
111  case Dbtc::CS_REC_PREPARING: out << "CS_REC_PREPARING"; break;
112  case Dbtc::CS_RESTART: out << "CS_RESTART"; break;
113  case Dbtc::CS_ABORTING: out << "CS_ABORTING"; break;
114  case Dbtc::CS_COMPLETING: out << "CS_COMPLETING"; break;
115  case Dbtc::CS_COMPLETE_SENT: out << "CS_COMPLETE_SENT"; break;
116  case Dbtc::CS_PREPARE_TO_COMMIT: out << "CS_PREPARE_TO_COMMIT"; break;
117  case Dbtc::CS_COMMIT_SENT: out << "CS_COMMIT_SENT"; break;
118  case Dbtc::CS_START_COMMITTING: out << "CS_START_COMMITTING"; break;
119  case Dbtc::CS_COMMITTING: out << "CS_COMMITTING"; break;
120  case Dbtc::CS_REC_COMMITTING: out << "CS_REC_COMMITTING"; break;
121  case Dbtc::CS_WAIT_ABORT_CONF: out << "CS_WAIT_ABORT_CONF"; break;
122  case Dbtc::CS_WAIT_COMPLETE_CONF: out << "CS_WAIT_COMPLETE_CONF"; break;
123  case Dbtc::CS_WAIT_COMMIT_CONF: out << "CS_WAIT_COMMIT_CONF"; break;
124  case Dbtc::CS_FAIL_ABORTING: out << "CS_FAIL_ABORTING"; break;
125  case Dbtc::CS_FAIL_ABORTED: out << "CS_FAIL_ABORTED"; break;
126  case Dbtc::CS_FAIL_PREPARED: out << "CS_FAIL_PREPARED"; break;
127  case Dbtc::CS_FAIL_COMMITTING: out << "CS_FAIL_COMMITTING"; break;
128  case Dbtc::CS_FAIL_COMMITTED: out << "CS_FAIL_COMMITTED"; break;
129  case Dbtc::CS_FAIL_COMPLETED: out << "CS_FAIL_COMPLETED"; break;
130  case Dbtc::CS_START_SCAN: out << "CS_START_SCAN"; break;
131  default:
132  out << "Unknown: " << (int)state; break;
133  }
134  return out;
135 }
136 NdbOut &
137 operator<<(NdbOut& out, Dbtc::OperationState state){
138  out << (int)state;
139  return out;
140 }
141 NdbOut &
142 operator<<(NdbOut& out, Dbtc::AbortState state){
143  out << (int)state;
144  return out;
145 }
146 NdbOut &
147 operator<<(NdbOut& out, Dbtc::ReturnSignal state){
148  out << (int)state;
149  return out;
150 }
151 NdbOut &
152 operator<<(NdbOut& out, Dbtc::ScanRecord::ScanState state){
153  out << (int)state;
154  return out;
155 }
156 NdbOut &
157 operator<<(NdbOut& out, Dbtc::ScanFragRec::ScanFragState state){
158  out << (int)state;
159  return out;
160 }
161 #endif
162 
163 extern int ErrorSignalReceive;
164 extern int ErrorMaxSegmentsToSeize;
165 
166 void
167 Dbtc::updateBuddyTimer(ApiConnectRecordPtr apiPtr)
168 {
169  if (apiPtr.p->buddyPtr != RNIL) {
170  jam();
171  ApiConnectRecordPtr buddyApiPtr;
172  buddyApiPtr.i = apiPtr.p->buddyPtr;
173  ptrCheckGuard(buddyApiPtr, capiConnectFilesize, apiConnectRecord);
174  if (getApiConTimer(buddyApiPtr.i) != 0) {
175  if ((apiPtr.p->transid[0] == buddyApiPtr.p->transid[0]) &&
176  (apiPtr.p->transid[1] == buddyApiPtr.p->transid[1])) {
177  jam();
178  setApiConTimer(buddyApiPtr.i, ctcTimer, __LINE__);
179  } else {
180  jam();
181  // Not a buddy anymore since not the same transid
182  apiPtr.p->buddyPtr = RNIL;
183  }//if
184  }//if
185  }//if
186 }
187 
188 static
189 inline
190 bool
191 tc_testbit(Uint32 flags, Uint32 flag)
192 {
193  return (flags & flag) != 0;
194 }
195 
196 static
197 inline
198 void
199 tc_clearbit(Uint32 & flags, Uint32 flag)
200 {
201  flags &= ~(Uint32)flag;
202 }
203 
204 void Dbtc::execCONTINUEB(Signal* signal)
205 {
206  UintR tcase;
207 
208  jamEntry();
209  tcase = signal->theData[0];
210  UintR Tdata0 = signal->theData[1];
211  UintR Tdata1 = signal->theData[2];
212  UintR Tdata2 = signal->theData[3];
213  switch (tcase) {
214  case TcContinueB::ZRETURN_FROM_QUEUED_DELIVERY:
215  jam();
216  ndbrequire(false);
217  return;
218  case TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER:
219  jam();
220  tcNodeFailptr.i = Tdata0;
221  ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
222  completeTransAtTakeOverLab(signal, Tdata1);
223  return;
224  case TcContinueB::ZCONTINUE_TIME_OUT_CONTROL:
225  jam();
226  timeOutLoopStartLab(signal, Tdata0);
227  return;
228  case TcContinueB::ZNODE_TAKE_OVER_COMPLETED:
229  jam();
230  tnodeid = Tdata0;
231  tcNodeFailptr.i = 0;
232  ptrAss(tcNodeFailptr, tcFailRecord);
233  nodeTakeOverCompletedLab(signal);
234  return;
235  case TcContinueB::ZINITIALISE_RECORDS:
236  jam();
237  initialiseRecordsLab(signal, Tdata0, Tdata2, signal->theData[4]);
238  return;
239  case TcContinueB::ZSEND_COMMIT_LOOP:
240  jam();
241  apiConnectptr.i = Tdata0;
242  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
243  tcConnectptr.i = Tdata1;
244  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
245  commit020Lab(signal);
246  return;
247  case TcContinueB::ZSEND_COMPLETE_LOOP:
248  jam();
249  apiConnectptr.i = Tdata0;
250  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
251  tcConnectptr.i = Tdata1;
252  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
253  complete010Lab(signal);
254  return;
255  case TcContinueB::ZHANDLE_FAILED_API_NODE:
256  jam();
257  handleFailedApiNode(signal, Tdata0, Tdata1);
258  return;
259  case TcContinueB::ZTRANS_EVENT_REP:
260  jam();
261  /* Send transaction counters report */
262  {
263  const Uint32 len = c_counters.build_event_rep(signal);
264  sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, len, JBB);
265  }
266 
267  {
268  const Uint32 report_interval = 5000;
269  const Uint32 len = c_counters.build_continueB(signal);
270  signal->theData[0] = TcContinueB::ZTRANS_EVENT_REP;
271  sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, report_interval, len);
272  }
273  return;
274  case TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL:
275  jam();
276  timeOutLoopStartFragLab(signal, Tdata0);
277  return;
278  case TcContinueB::ZABORT_BREAK:
279  jam();
280  tcConnectptr.i = Tdata0;
281  apiConnectptr.i = Tdata1;
282  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
283  apiConnectptr.p->counter--;
284  abort015Lab(signal);
285  return;
286  case TcContinueB::ZABORT_TIMEOUT_BREAK:
287  jam();
288  tcConnectptr.i = Tdata0;
289  apiConnectptr.i = Tdata1;
290  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
291  apiConnectptr.p->counter--;
292  sendAbortedAfterTimeout(signal, 1);
293  return;
294  case TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS:
295  jam();
296  removeMarkerForFailedAPI(signal, Tdata0, Tdata1);
297  return;
298  case TcContinueB::ZWAIT_ABORT_ALL:
299  jam();
300  checkAbortAllTimeout(signal, Tdata0);
301  return;
302  case TcContinueB::ZCHECK_SCAN_ACTIVE_FAILED_LQH:
303  jam();
304  checkScanActiveInFailedLqh(signal, Tdata0, Tdata1);
305  return;
306  case TcContinueB::ZNF_CHECK_TRANSACTIONS:
307  jam();
308  nodeFailCheckTransactions(signal, Tdata0, Tdata1);
309  return;
310  case TcContinueB::TRIGGER_PENDING:
311  jam();
312  ApiConnectRecordPtr transPtr;
313  transPtr.i = Tdata0;
314  ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
315 #ifdef ERROR_INSERT
316  if (ERROR_INSERTED(8082))
317  {
318  /* Max of 100000 TRIGGER_PENDING TcContinueBs to
319  * single ApiConnectRecord
320  * See testBlobs -bug 45768
321  */
322  if (++transPtr.p->continueBCount > 100000)
323  {
324  ndbrequire(false);
325  }
326  }
327 #endif
328  /* Check that ConnectRecord is for the same Trans Id */
329  if (likely((transPtr.p->transid[0] == Tdata1) &&
330  (transPtr.p->transid[1] == Tdata2)))
331  {
332  ndbrequire(tc_testbit(transPtr.p->m_flags,
333  ApiConnectRecord::TF_TRIGGER_PENDING));
334  tc_clearbit(transPtr.p->m_flags, ApiConnectRecord::TF_TRIGGER_PENDING);
335  /* Try executing triggers now */
336  executeTriggers(signal, &transPtr);
337  }
338  return;
339  case TcContinueB::DelayTCKEYCONF:
340  jam();
341  apiConnectptr.i = Tdata0;
342  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
343  sendtckeyconf(signal, Tdata1);
344  return;
345  case TcContinueB::ZSEND_FIRE_TRIG_REQ:
346  jam();
347  apiConnectptr.i = Tdata0;
348  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
349  if (unlikely(! (apiConnectptr.p->transid[0] == Tdata1 &&
350  apiConnectptr.p->transid[1] == Tdata2 &&
351  apiConnectptr.p->apiConnectstate == CS_SEND_FIRE_TRIG_REQ)))
352  {
353  warningReport(signal, 29);
354  return;
355  }
356  sendFireTrigReq(signal, apiConnectptr, signal->theData[4]);
357  return;
358  default:
359  ndbrequire(false);
360  }//switch
361 }
362 
363 void Dbtc::execDIGETNODESREF(Signal* signal)
364 {
365  jamEntry();
366  terrorCode = signal->theData[1];
367  releaseAtErrorLab(signal);
368 }
369 
370 void Dbtc::execINCL_NODEREQ(Signal* signal)
371 {
372  jamEntry();
373  tblockref = signal->theData[0];
374  hostptr.i = signal->theData[1];
375  ptrCheckGuard(hostptr, chostFilesize, hostRecord);
376  hostptr.p->hostStatus = HS_ALIVE;
377  c_alive_nodes.set(hostptr.i);
378 
379  signal->theData[0] = hostptr.i;
380  signal->theData[1] = cownref;
381 
382  if (ERROR_INSERTED(8039))
383  {
384  CLEAR_ERROR_INSERT_VALUE;
385  Uint32 save = signal->theData[0];
386  signal->theData[0] = 9999;
387  sendSignal(numberToRef(CMVMI, hostptr.i),
388  GSN_NDB_TAMPER, signal, 1, JBB);
389  signal->theData[0] = save;
390  sendSignalWithDelay(tblockref, GSN_INCL_NODECONF, signal, 5000, 2);
391  return;
392  }
393 
394  Uint32 Tnode = hostptr.i;
395  Uint32 lqhWorkers = getNodeInfo(Tnode).m_lqh_workers;
396  if (lqhWorkers == 1)
397  {
398  jam();
399  hostptr.p->hostLqhBlockRef = numberToRef(DBLQH, 1, Tnode);
400  }
401  else
402  {
403  jam();
404  hostptr.p->hostLqhBlockRef = numberToRef(DBLQH, Tnode);
405  }
406 
407  sendSignal(tblockref, GSN_INCL_NODECONF, signal, 2, JBB);
408 
409  if (m_deferred_enabled)
410  {
411  jam();
412  if (!ndbd_deferred_unique_constraints(getNodeInfo(Tnode).m_version))
413  {
414  jam();
415  m_deferred_enabled = 0;
416  }
417  }
418 }
419 
420 void Dbtc::execREAD_NODESREF(Signal* signal)
421 {
422  jamEntry();
423  ndbrequire(false);
424 }
425 
426 // create table prepare
427 void Dbtc::execTC_SCHVERREQ(Signal* signal)
428 {
429  jamEntry();
430  if (! assembleFragments(signal)) {
431  jam();
432  return;
433  }
434  const TcSchVerReq* req = CAST_CONSTPTR(TcSchVerReq, signal->getDataPtr());
435  tabptr.i = req->tableId;
436  ptrCheckGuard(tabptr, ctabrecFilesize, tableRecord);
437  tabptr.p->currentSchemaVersion = req->tableVersion;
438  tabptr.p->m_flags = 0;
439  tabptr.p->set_storedTable((bool)req->tableLogged);
440  BlockReference retRef = req->senderRef;
441  tabptr.p->tableType = (Uint8)req->tableType;
442  BlockReference retPtr = req->senderData;
443  Uint32 noOfKeyAttr = req->noOfPrimaryKeys;
444  tabptr.p->singleUserMode = (Uint8)req->singleUserMode;
445  Uint32 userDefinedPartitioning = (Uint8)req->userDefinedPartition;
446  ndbrequire(noOfKeyAttr <= MAX_ATTRIBUTES_IN_INDEX);
447 
448  const KeyDescriptor* desc = g_key_descriptor_pool.getPtr(tabptr.i);
449  ndbrequire(noOfKeyAttr == desc->noOfKeyAttr);
450 
451  ndbrequire(tabptr.p->get_prepared() == false);
452  ndbrequire(tabptr.p->get_enabled() == false);
453  tabptr.p->set_prepared(true);
454  tabptr.p->set_enabled(false);
455  tabptr.p->set_dropping(false);
456  tabptr.p->noOfKeyAttr = desc->noOfKeyAttr;
457  tabptr.p->hasCharAttr = desc->hasCharAttr;
458  tabptr.p->noOfDistrKeys = desc->noOfDistrKeys;
459  tabptr.p->hasVarKeys = desc->noOfVarKeys > 0;
460  tabptr.p->set_user_defined_partitioning(userDefinedPartitioning);
461 
462  TcSchVerConf * conf = (TcSchVerConf*)signal->getDataPtr();
463  conf->senderRef = reference();
464  conf->senderData = retPtr;
465  sendSignal(retRef, GSN_TC_SCHVERCONF, signal,
466  TcSchVerConf::SignalLength, JBB);
467 }//Dbtc::execTC_SCHVERREQ()
468 
469 // create table commit
470 void Dbtc::execTAB_COMMITREQ(Signal* signal)
471 {
472  jamEntry();
473  Uint32 senderData = signal->theData[0];
474  Uint32 senderRef = signal->theData[1];
475  tabptr.i = signal->theData[2];
476  ptrCheckGuard(tabptr, ctabrecFilesize, tableRecord);
477 
478  ndbrequire(tabptr.p->get_prepared() == true);
479  ndbrequire(tabptr.p->get_enabled() == false);
480  tabptr.p->set_enabled(true);
481  tabptr.p->set_prepared(false);
482  tabptr.p->set_dropping(false);
483 
484  signal->theData[0] = senderData;
485  signal->theData[1] = reference();
486  signal->theData[2] = tabptr.i;
487  sendSignal(senderRef, GSN_TAB_COMMITCONF, signal, 3, JBB);
488 }
489 
490 void
491 Dbtc::execPREP_DROP_TAB_REQ(Signal* signal)
492 {
493  jamEntry();
494 
495  PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
496 
497  TableRecordPtr tabPtr;
498  tabPtr.i = req->tableId;
499  ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
500 
501  Uint32 senderRef = req->senderRef;
502  Uint32 senderData = req->senderData;
503 
504  if(!tabPtr.p->get_enabled())
505  {
506  jam();
507  PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
508  ref->senderRef = reference();
509  ref->senderData = senderData;
510  ref->tableId = tabPtr.i;
511  ref->errorCode = PrepDropTabRef::NoSuchTable;
512  sendSignal(senderRef, GSN_PREP_DROP_TAB_REF, signal,
513  PrepDropTabRef::SignalLength, JBB);
514  return;
515  }
516 
517  if(tabPtr.p->get_dropping())
518  {
519  jam();
520  PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
521  ref->senderRef = reference();
522  ref->senderData = senderData;
523  ref->tableId = tabPtr.i;
524  ref->errorCode = PrepDropTabRef::DropInProgress;
525  sendSignal(senderRef, GSN_PREP_DROP_TAB_REF, signal,
526  PrepDropTabRef::SignalLength, JBB);
527  return;
528  }
529 
530  tabPtr.p->set_dropping(true);
531  tabPtr.p->set_prepared(false);
532 
533  PrepDropTabConf* conf = (PrepDropTabConf*)signal->getDataPtrSend();
534  conf->tableId = tabPtr.i;
535  conf->senderRef = reference();
536  conf->senderData = senderData;
537  sendSignal(senderRef, GSN_PREP_DROP_TAB_CONF, signal,
538  PrepDropTabConf::SignalLength, JBB);
539 }
540 
541 void
542 Dbtc::execDROP_TAB_REQ(Signal* signal)
543 {
544  jamEntry();
545 
546  DropTabReq* req = (DropTabReq*)signal->getDataPtr();
547 
548  TableRecordPtr tabPtr;
549  tabPtr.i = req->tableId;
550  ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
551 
552  Uint32 senderRef = req->senderRef;
553  Uint32 senderData = req->senderData;
554  DropTabReq::RequestType rt = (DropTabReq::RequestType)req->requestType;
555 
556  if(!tabPtr.p->get_enabled() && rt == DropTabReq::OnlineDropTab){
557  jam();
558  DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
559  ref->senderRef = reference();
560  ref->senderData = senderData;
561  ref->tableId = tabPtr.i;
562  ref->errorCode = DropTabRef::NoSuchTable;
563  sendSignal(senderRef, GSN_DROP_TAB_REF, signal,
564  DropTabRef::SignalLength, JBB);
565  return;
566  }
567 
568  if(!tabPtr.p->get_dropping() && rt == DropTabReq::OnlineDropTab){
569  jam();
570  DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
571  ref->senderRef = reference();
572  ref->senderData = senderData;
573  ref->tableId = tabPtr.i;
574  ref->errorCode = DropTabRef::DropWoPrep;
575  sendSignal(senderRef, GSN_DROP_TAB_REF, signal,
576  DropTabRef::SignalLength, JBB);
577  return;
578  }
579 
580  tabPtr.p->set_enabled(false);
581  tabPtr.p->set_prepared(false);
582  tabPtr.p->set_dropping(false);
583 
584  DropTabConf * conf = (DropTabConf*)signal->getDataPtrSend();
585  conf->tableId = tabPtr.i;
586  conf->senderRef = reference();
587  conf->senderData = senderData;
588  sendSignal(senderRef, GSN_DROP_TAB_CONF, signal,
589  PrepDropTabConf::SignalLength, JBB);
590 }
591 
592 void Dbtc::execALTER_TAB_REQ(Signal * signal)
593 {
594  const AlterTabReq* req = (const AlterTabReq*)signal->getDataPtr();
595  const Uint32 senderRef = req->senderRef;
596  const Uint32 senderData = req->senderData;
597  const Uint32 tableVersion = req->tableVersion;
598  const Uint32 newTableVersion = req->newTableVersion;
599  AlterTabReq::RequestType requestType =
600  (AlterTabReq::RequestType) req->requestType;
601 
602  TableRecordPtr tabPtr;
603  tabPtr.i = req->tableId;
604  ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
605 
606  switch (requestType) {
607  case AlterTabReq::AlterTablePrepare:
608  jam();
609  break;
610  case AlterTabReq::AlterTableRevert:
611  jam();
612  tabPtr.p->currentSchemaVersion = tableVersion;
613  break;
614  case AlterTabReq::AlterTableCommit:
615  jam();
616  tabPtr.p->currentSchemaVersion = newTableVersion;
617  break;
618  default:
619  ndbrequire(false);
620  break;
621  }
622 
623  // Request handled successfully
624  AlterTabConf* conf = (AlterTabConf*)signal->getDataPtrSend();
625  conf->senderRef = reference();
626  conf->senderData = senderData;
627  conf->connectPtr = RNIL;
628  sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal,
629  AlterTabConf::SignalLength, JBB);
630 }
631 
632 /* ***************************************************************************/
633 /* START / RESTART */
634 /* ***************************************************************************/
635 void Dbtc::execREAD_CONFIG_REQ(Signal* signal)
636 {
637  const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
638  Uint32 ref = req->senderRef;
639  Uint32 senderData = req->senderData;
640  ndbrequire(req->noOfParameters == 0);
641 
642  jamEntry();
643 
644  const ndb_mgm_configuration_iterator * p =
645  m_ctx.m_config.getOwnConfigIterator();
646  ndbrequire(p != 0);
647 
648  initData();
649 
650  UintR apiConnect;
651  UintR tcConnect;
652  UintR tables;
653  UintR localScan;
654  UintR tcScan;
655 
656  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_API_CONNECT, &apiConnect));
657  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_TC_CONNECT, &tcConnect));
658  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_TABLE, &tables));
659  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_LOCAL_SCAN, &localScan));
660  ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_SCAN, &tcScan));
661 
662  ccacheFilesize = (apiConnect/3) + 1;
663  capiConnectFilesize = apiConnect;
664  ctcConnectFilesize = tcConnect;
665  ctabrecFilesize = tables;
666  cscanrecFileSize = tcScan;
667  cscanFragrecFileSize = localScan;
668 
669  initRecords();
670  initialiseRecordsLab(signal, 0, ref, senderData);
671 
672  Uint32 val = 3000;
673  ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT, &val);
674  set_timeout_value(val);
675 
676  val = 1500;
677  ndb_mgm_get_int_parameter(p, CFG_DB_HEARTBEAT_INTERVAL, &val);
678  cDbHbInterval = (val < 10) ? 10 : val;
679 
680  val = 3000;
681  ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_INACTIVE_TIMEOUT, &val);
682  set_appl_timeout_value(val);
683 
684  val = 1;
685  //ndb_mgm_get_int_parameter(p, CFG_DB_PARALLEL_TRANSACTION_TAKEOVER, &val);
686  set_no_parallel_takeover(val);
687 
688  val = ~(Uint32)0;
689  ndb_mgm_get_int_parameter(p, CFG_DB_MAX_DML_OPERATIONS_PER_TRANSACTION, &val);
690  m_max_writes_per_trans = val;
691 
692  ctimeOutCheckDelay = 50; // 500ms
693 }//Dbtc::execSIZEALT_REP()
694 
695 void Dbtc::execSTTOR(Signal* signal)
696 {
697  Uint16 tphase;
698 
699  jamEntry();
700  /* START CASE */
701  tphase = signal->theData[1];
702  csignalKey = signal->theData[6];
703  c_sttor_ref = signal->getSendersBlockRef();
704  switch (tphase) {
705  case ZSPH1:
706  jam();
707  startphase1x010Lab(signal);
708  return;
709  default:
710  jam();
711  sttorryLab(signal); /* START PHASE 255 */
712  return;
713  }//switch
714 }//Dbtc::execSTTOR()
715 
716 void Dbtc::sttorryLab(Signal* signal)
717 {
718  signal->theData[0] = csignalKey;
719  signal->theData[1] = 3; /* BLOCK CATEGORY */
720  signal->theData[2] = 2; /* SIGNAL VERSION NUMBER */
721  signal->theData[3] = ZSPH1;
722  signal->theData[4] = 255;
723  sendSignal(c_sttor_ref, GSN_STTORRY, signal, 5, JBB);
724 }//Dbtc::sttorryLab()
725 
726 /* ***************************************************************************/
727 /* INTERNAL START / RESTART */
728 /*****************************************************************************/
729 void Dbtc::execNDB_STTOR(Signal* signal)
730 {
731  Uint16 tndbstartphase;
732  Uint16 tstarttype;
733 
734  jamEntry();
735  tusersblkref = signal->theData[0];
736  tnodeid = signal->theData[1];
737  tndbstartphase = signal->theData[2]; /* START PHASE */
738  tstarttype = signal->theData[3]; /* START TYPE */
739  c_sttor_ref = signal->getSendersBlockRef();
740  switch (tndbstartphase) {
741  case ZINTSPH1:
742  jam();
743  intstartphase1x010Lab(signal);
744  return;
745  case ZINTSPH2:
746  jam();
747  ndbsttorry010Lab(signal);
748  return;
749  case ZINTSPH3:
750  {
751  jam();
752  intstartphase3x010Lab(signal); /* SEIZE CONNECT RECORD IN EACH LQH*/
753 
754  /* Start transaction counters event reporting. */
755  const Uint32 len = c_counters.build_continueB(signal);
756  signal->theData[0] = TcContinueB::ZTRANS_EVENT_REP;
757  sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, len);
758  return;
759  }
760  case ZINTSPH6:
761  jam();
762  csystemStart = SSS_TRUE;
763  break;
764  default:
765  jam();
766  break;
767  }//switch
768  ndbsttorry010Lab(signal);
769  return;
770 }//Dbtc::execNDB_STTOR()
771 
772 void Dbtc::ndbsttorry010Lab(Signal* signal)
773 {
774  signal->theData[0] = cownref;
775  sendSignal(c_sttor_ref, GSN_NDB_STTORRY, signal, 1, JBB);
776 }//Dbtc::ndbsttorry010Lab()
777 
778 void
779 Dbtc::set_timeout_value(Uint32 timeOut)
780 {
781  timeOut = timeOut / 10;
782  if (timeOut < 2) {
783  jam();
784  timeOut = 100;
785  }//if
786  ctimeOutValue = timeOut;
787 }
788 
789 void
790 Dbtc::set_appl_timeout_value(Uint32 timeOut)
791 {
792  if (timeOut)
793  {
794  timeOut /= 10;
795  if (timeOut < ctimeOutValue) {
796  jam();
797  c_appl_timeout_value = ctimeOutValue;
798  }//if
799  }
800  c_appl_timeout_value = timeOut;
801 }
802 
803 void
804 Dbtc::set_no_parallel_takeover(Uint32 noParallelTakeOver)
805 {
806  if (noParallelTakeOver == 0) {
807  jam();
808  noParallelTakeOver = 1;
809  } else if (noParallelTakeOver > MAX_NDB_NODES) {
810  jam();
811  noParallelTakeOver = MAX_NDB_NODES;
812  }//if
813  cnoParallelTakeOver = noParallelTakeOver;
814 }
815 
816 /* ***************************************************************************/
817 /* S T A R T P H A S E 1 X */
818 /* INITIALISE BLOCKREF AND BLOCKNUMBERS */
819 /* ***************************************************************************/
820 void Dbtc::startphase1x010Lab(Signal* signal)
821 {
822  csystemStart = SSS_FALSE;
823  ctimeOutCheckCounter = 0;
824  ctimeOutCheckFragCounter = 0;
825  ctimeOutMissedHeartbeats = 0;
826  ctimeOutCheckHeartbeat = 0;
827  ctimeOutCheckLastHeartbeat = 0;
828  ctimeOutCheckActive = TOCS_FALSE;
829  ctimeOutCheckFragActive = TOCS_FALSE;
830  sttorryLab(signal);
831 }//Dbtc::startphase1x010Lab()
832 
833 /*****************************************************************************/
834 /* I N T S T A R T P H A S E 1 X */
835 /* INITIALISE ALL RECORDS. */
836 /*****************************************************************************/
837 void Dbtc::intstartphase1x010Lab(Signal* signal)
838 {
839  cownNodeid = tnodeid;
840  cownref = reference();
841  clqhblockref = calcLqhBlockRef(cownNodeid);
842  cdihblockref = calcDihBlockRef(cownNodeid);
843  cdictblockref = calcDictBlockRef(cownNodeid);
844  cndbcntrblockref = calcNdbCntrBlockRef(cownNodeid);
845  cerrorBlockref = calcNdbCntrBlockRef(cownNodeid);
846  coperationsize = 0;
847  cfailure_nr = 0;
848  ndbsttorry010Lab(signal);
849 }//Dbtc::intstartphase1x010Lab()
850 
851 /*****************************************************************************/
852 /* I N T S T A R T P H A S E 3 X */
853 /* PREPARE DISTRIBUTED CONNECTIONS */
854 /*****************************************************************************/
855 void Dbtc::intstartphase3x010Lab(Signal* signal)
856 {
857  signal->theData[0] = cownref;
858  sendSignal(cndbcntrblockref, GSN_READ_NODESREQ, signal, 1, JBB);
859 }//Dbtc::intstartphase3x010Lab()
860 
861 void Dbtc::execREAD_NODESCONF(Signal* signal)
862 {
863  UintR guard0;
864 
865  jamEntry();
866 
867  ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
868 
869  csystemnodes = readNodes->noOfNodes;
870  cmasterNodeId = readNodes->masterNodeId;
871 
872  con_lineNodes = 0;
873  arrGuard(csystemnodes, MAX_NDB_NODES);
874  guard0 = csystemnodes - 1;
875  arrGuard(guard0, MAX_NDB_NODES); // Check not zero nodes
876 
877  for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
878  jam();
879  if (NdbNodeBitmask::get(readNodes->allNodes, i)) {
880  hostptr.i = i;
881  ptrCheckGuard(hostptr, chostFilesize, hostRecord);
882 
883  if (NdbNodeBitmask::get(readNodes->inactiveNodes, i)) {
884  jam();
885  hostptr.p->hostStatus = HS_DEAD;
886  } else {
887  jam();
888  con_lineNodes++;
889  hostptr.p->hostStatus = HS_ALIVE;
890  c_alive_nodes.set(i);
891  if (getNodeInfo(i).m_lqh_workers == 1)
892  {
893  jam();
894  hostptr.p->hostLqhBlockRef = numberToRef(DBLQH, 1, i);
895  }
896  else
897  {
898  jam();
899  hostptr.p->hostLqhBlockRef = numberToRef(DBLQH, i);
900  }
901  if (!ndbd_deferred_unique_constraints(getNodeInfo(i).m_version))
902  {
903  jam();
904  m_deferred_enabled = 0;
905  }
906  }//if
907  }//if
908  }//for
909  ndbsttorry010Lab(signal);
910 }//Dbtc::execREAD_NODESCONF()
911 
912 /*****************************************************************************/
913 /* A P I _ F A I L R E Q */
914 // An API node has failed for some reason. We need to disconnect all API
915 // connections to the API node. This also includes
916 /*****************************************************************************/
917 void Dbtc::execAPI_FAILREQ(Signal* signal)
918 {
919  /***************************************************************************
920  * Set the block reference to return API_FAILCONF to. Set the number of api
921  * connects currently closing to one to indicate that we are still in the
922  * process of going through the api connect records. Thus checking for zero
923  * can only be true after all api connect records have been checked.
924  **************************************************************************/
925  jamEntry();
926 
927  if (ERROR_INSERTED(8056))
928  {
929  CLEAR_ERROR_INSERT_VALUE;
930  return;
931  }
932 #ifdef ERROR_INSERT
933  if (ERROR_INSERTED(8078))
934  {
935  c_lastFailedApi = signal->theData[0];
936  SET_ERROR_INSERT_VALUE(8079);
937  }
938 #endif
939 
940  capiFailRef = signal->theData[1];
941  arrGuard(signal->theData[0], MAX_NODES);
942  capiConnectClosing[signal->theData[0]] = 1;
943  handleFailedApiNode(signal, signal->theData[0], (UintR)0);
944 }
945 
946 void
947 Dbtc::handleFailedApiNode(Signal* signal,
948  UintR TapiFailedNode,
949  UintR TapiConnectPtr)
950 {
951  UintR TloopCount = 0;
952  arrGuard(TapiFailedNode, MAX_NODES);
953  apiConnectptr.i = TapiConnectPtr;
954  do {
955  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
956  const UintR TapiNode = refToNode(apiConnectptr.p->ndbapiBlockref);
957  if (TapiNode == TapiFailedNode) {
958 #ifdef VM_TRACE
959  if (apiConnectptr.p->apiFailState != ZFALSE) {
960  ndbout << "Error in previous API fail handling discovered" << endl
961  << " apiConnectptr.i = " << apiConnectptr.i << endl
962  << " apiConnectstate = " << apiConnectptr.p->apiConnectstate
963  << endl
964  << " ndbapiBlockref = " << hex
965  << apiConnectptr.p->ndbapiBlockref << endl
966  << " apiNode = " << refToNode(apiConnectptr.p->ndbapiBlockref)
967  << endl;
968  if (apiConnectptr.p->lastTcConnect != RNIL){
969  jam();
970  tcConnectptr.i = apiConnectptr.p->lastTcConnect;
971  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
972  ndbout << " tcConnectptr.i = " << tcConnectptr.i << endl
973  << " tcConnectstate = " << tcConnectptr.p->tcConnectstate
974  << endl;
975  }
976  }//if
977 #endif
978 
979  apiConnectptr.p->returnsignal = RS_NO_RETURN;
980  /***********************************************************************/
981  // The connected node is the failed node.
982  /**********************************************************************/
983  switch(apiConnectptr.p->apiConnectstate) {
984  case CS_DISCONNECTED:
985  /*********************************************************************/
986  // These states do not need any special handling.
987  // Simply continue with the next.
988  /*********************************************************************/
989  jam();
990  break;
991  case CS_ABORTING:
992  /*********************************************************************/
993  // This could actually mean that the API connection is already
994  // ready to release if the abortState is IDLE.
995  /*********************************************************************/
996  if (apiConnectptr.p->abortState == AS_IDLE) {
997  jam();
998  releaseApiCon(signal, apiConnectptr.i);
999  } else {
1000  jam();
1001  capiConnectClosing[TapiFailedNode]++;
1002  apiConnectptr.p->apiFailState = ZTRUE;
1003  }//if
1004  break;
1005  case CS_WAIT_ABORT_CONF:
1006  case CS_WAIT_COMMIT_CONF:
1007  case CS_START_COMMITTING:
1008  case CS_PREPARE_TO_COMMIT:
1009  case CS_COMMITTING:
1010  case CS_COMMIT_SENT:
1011  /*********************************************************************/
1012  // These states indicate that an abort process or commit process is
1013  // already ongoing. We will set a state in the api record indicating
1014  // that the API node has failed.
1015  // Also we will increase the number of outstanding api records to
1016  // wait for before we can respond with API_FAILCONF.
1017  /*********************************************************************/
1018  jam();
1019  capiConnectClosing[TapiFailedNode]++;
1020  apiConnectptr.p->apiFailState = ZTRUE;
1021  break;
1022  case CS_START_SCAN:
1023  /*********************************************************************/
1024  // The api record was performing a scan operation. We need to check
1025  // on the scan state. Since completing a scan process might involve
1026  // sending several signals we will increase the loop count by 64.
1027  /*********************************************************************/
1028  jam();
1029 
1030  apiConnectptr.p->apiFailState = ZTRUE;
1031  capiConnectClosing[TapiFailedNode]++;
1032 
1033  ScanRecordPtr scanPtr;
1034  scanPtr.i = apiConnectptr.p->apiScanRec;
1035  ptrCheckGuard(scanPtr, cscanrecFileSize, scanRecord);
1036  close_scan_req(signal, scanPtr, true);
1037 
1038  TloopCount += 64;
1039  break;
1040  case CS_CONNECTED:
1041  case CS_REC_COMMITTING:
1042  case CS_RECEIVING:
1043  case CS_STARTED:
1044  /*********************************************************************/
1045  // The api record was in the process of performing a transaction but
1046  // had not yet sent all information.
1047  // We need to initiate an ABORT since the API will not provide any
1048  // more information.
1049  // Since the abort can send many signals we will insert a real-time
1050  // break after checking this record.
1051  /*********************************************************************/
1052  jam();
1053  apiConnectptr.p->apiFailState = ZTRUE;
1054  capiConnectClosing[TapiFailedNode]++;
1055  abort010Lab(signal);
1056  TloopCount = 256;
1057  break;
1058  case CS_PREPARED:
1059  jam();
1060  case CS_REC_PREPARING:
1061  jam();
1062  case CS_START_PREPARING:
1063  jam();
1064  /*********************************************************************/
1065  // Not implemented yet.
1066  /*********************************************************************/
1067  systemErrorLab(signal, __LINE__);
1068  break;
1069  case CS_RESTART:
1070  jam();
1071  case CS_COMPLETING:
1072  jam();
1073  case CS_COMPLETE_SENT:
1074  jam();
1075  case CS_WAIT_COMPLETE_CONF:
1076  jam();
1077  case CS_FAIL_ABORTING:
1078  jam();
1079  case CS_FAIL_ABORTED:
1080  jam();
1081  case CS_FAIL_PREPARED:
1082  jam();
1083  case CS_FAIL_COMMITTING:
1084  jam();
1085  case CS_FAIL_COMMITTED:
1086  /*********************************************************************/
1087  // These states are only valid on copy and fail API connections.
1088  /*********************************************************************/
1089  default:
1090  jam();
1091  systemErrorLab(signal, __LINE__);
1092  break;
1093  }//switch
1094  } else {
1095  jam();
1096  }//if
1097  apiConnectptr.i++;
1098  if (apiConnectptr.i > ((capiConnectFilesize / 3) - 1)) {
1099  jam();
1105  removeMarkerForFailedAPI(signal, TapiFailedNode, 0);
1106  return;
1107  }//if
1108  } while (TloopCount++ < 256);
1109  signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE;
1110  signal->theData[1] = TapiFailedNode;
1111  signal->theData[2] = apiConnectptr.i;
1112  sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
1113 }//Dbtc::handleFailedApiNode()
1114 
1115 void
1116 Dbtc::removeMarkerForFailedAPI(Signal* signal,
1117  Uint32 nodeId,
1118  Uint32 startBucket)
1119 {
1120  TcFailRecordPtr node_fail_ptr;
1121  node_fail_ptr.i = 0;
1122  ptrAss(node_fail_ptr, tcFailRecord);
1123  if(node_fail_ptr.p->failStatus != FS_IDLE) {
1124  jam();
1125  DEBUG("Restarting removeMarkerForFailedAPI");
1131  signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS;
1132  signal->theData[1] = nodeId;
1133  signal->theData[2] = 0;
1134  sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 500, 3);
1135  return;
1136  }
1137 
1138  CommitAckMarkerIterator iter;
1139  m_commitAckMarkerHash.next(startBucket, iter);
1140 
1141  const Uint32 RT_BREAK = 256;
1142  for(Uint32 i = 0; i<RT_BREAK || iter.bucket == startBucket; i++){
1143  jam();
1144 
1145  if(iter.curr.i == RNIL){
1146  jam();
1150  capiConnectClosing[nodeId]--;
1151  if (capiConnectClosing[nodeId] == 0) {
1152  jam();
1153 
1154  /********************************************************************/
1155  // No outstanding ABORT or COMMIT's of this failed API node.
1156  // Perform SimulatedBlock level cleanup before sending
1157  // API_FAILCONF
1158  /********************************************************************/
1159  Callback cb = {safe_cast(&Dbtc::apiFailBlockCleanupCallback),
1160  nodeId};
1161  simBlockNodeFailure(signal, nodeId, cb);
1162  }
1163  return;
1164  }
1165 
1166  if(iter.curr.p->apiNodeId == nodeId){
1167  jam();
1168 
1173  ApiConnectRecordPtr apiConnectPtr;
1174  apiConnectPtr.i = iter.curr.p->apiConnectPtr;
1175  ptrCheckGuard(apiConnectPtr, capiConnectFilesize, apiConnectRecord);
1176  if(apiConnectPtr.p->commitAckMarker == iter.curr.i){
1177  jam();
1183  break;
1184  }
1185  sendRemoveMarkers(signal, iter.curr.p);
1186  m_commitAckMarkerHash.release(iter.curr);
1187 
1188  break;
1189  }
1190  m_commitAckMarkerHash.next(iter);
1191  }
1192 
1193  signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS;
1194  signal->theData[1] = nodeId;
1195  signal->theData[2] = iter.bucket;
1196  sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
1197 }
1198 
1199 void Dbtc::handleApiFailState(Signal* signal, UintR TapiConnectptr)
1200 {
1201  ApiConnectRecordPtr TlocalApiConnectptr;
1202  UintR TfailedApiNode;
1203 
1204  TlocalApiConnectptr.i = TapiConnectptr;
1205  ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
1206  TfailedApiNode = refToNode(TlocalApiConnectptr.p->ndbapiBlockref);
1207  arrGuard(TfailedApiNode, MAX_NODES);
1208  capiConnectClosing[TfailedApiNode]--;
1209  releaseApiCon(signal, TapiConnectptr);
1210  TlocalApiConnectptr.p->apiFailState = ZFALSE;
1211  if (capiConnectClosing[TfailedApiNode] == 0)
1212  {
1213  jam();
1214 
1218  Callback cb = {safe_cast(&Dbtc::apiFailBlockCleanupCallback),
1219  TfailedApiNode};
1220  simBlockNodeFailure(signal, TfailedApiNode, cb);
1221  }//if
1222 }//Dbtc::handleApiFailState()
1223 
1224 /****************************************************************************
1225  * T C S E I Z E R E Q
1226  * THE APPLICATION SENDS A REQUEST TO SEIZE A CONNECT RECORD TO CARRY OUT A
1227  * TRANSACTION
1228  * TC BLOCK TAKE OUT A CONNECT RECORD FROM THE FREE LIST AND ESTABLISHES ALL
1229  * NECESSARY CONNECTION BEFORE REPLYING TO THE APPLICATION BLOCK
1230  ****************************************************************************/
1231 void Dbtc::execTCSEIZEREQ(Signal* signal)
1232 {
1233  UintR tapiPointer;
1234  BlockReference tapiBlockref; /* SENDER BLOCK REFERENCE*/
1235 
1236  jamEntry();
1237  tapiPointer = signal->theData[0]; /* REQUEST SENDERS CONNECT RECORD POINTER*/
1238  tapiBlockref = signal->theData[1]; /* SENDERS BLOCK REFERENCE*/
1239 
1240  if (signal->getLength() > 2)
1241  {
1242  ndbassert(instance() == signal->theData[2]);
1243  }
1244 
1245  const NodeState::StartLevel sl =
1247 
1248  const NodeId senderNodeId = refToNode(tapiBlockref);
1249  const bool local = senderNodeId == getOwnNodeId() || senderNodeId == 0;
1250 
1251  {
1252  {
1253  if (!(sl == NodeState::SL_STARTED ||
1254  (sl == NodeState::SL_STARTING && local == true))) {
1255  jam();
1256 
1257  Uint32 errCode = 0;
1258  if(!local)
1259  {
1260  switch(sl){
1262  errCode = ZSYSTEM_NOT_STARTED_ERROR;
1263  break;
1266  if (getNodeState().getSingleUserMode())
1267  break;
1270  if(getNodeState().stopping.systemShutdown)
1271  errCode = ZCLUSTER_SHUTDOWN_IN_PROGRESS;
1272  else
1273  errCode = ZNODE_SHUTDOWN_IN_PROGRESS;
1274  break;
1275  case NodeState::SL_SINGLEUSER:
1276  break;
1277  default:
1278  errCode = ZWRONG_STATE;
1279  break;
1280  }
1281  if (errCode)
1282  {
1283  signal->theData[0] = tapiPointer;
1284  signal->theData[1] = errCode;
1285  sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB);
1286  return;
1287  }
1288  }//if (!(sl == SL_SINGLEUSER))
1289  } //if
1290  }
1291  }
1292 
1293  if (ERROR_INSERTED(8078) || ERROR_INSERTED(8079))
1294  {
1295  /* Clear testing of API_FAILREQ behaviour */
1296  CLEAR_ERROR_INSERT_VALUE;
1297  };
1298 
1299  seizeApiConnect(signal);
1300  if (terrorCode == ZOK) {
1301  jam();
1302  apiConnectptr.p->ndbapiConnect = tapiPointer;
1303  apiConnectptr.p->ndbapiBlockref = tapiBlockref;
1304  signal->theData[0] = apiConnectptr.p->ndbapiConnect;
1305  signal->theData[1] = apiConnectptr.i;
1306  signal->theData[2] = reference();
1307  sendSignal(tapiBlockref, GSN_TCSEIZECONF, signal, 3, JBB);
1308  return;
1309  }
1310 
1311  signal->theData[0] = tapiPointer;
1312  signal->theData[1] = terrorCode;
1313  sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB);
1314 }//Dbtc::execTCSEIZEREQ()
1315 
1316 /****************************************************************************/
1317 /* T C R E L E A S E Q */
1318 /* REQUEST TO RELEASE A CONNECT RECORD */
1319 /****************************************************************************/
1320 void Dbtc::execTCRELEASEREQ(Signal* signal)
1321 {
1322  UintR tapiPointer;
1323  BlockReference tapiBlockref; /* SENDER BLOCK REFERENCE*/
1324 
1325  jamEntry();
1326  tapiPointer = signal->theData[0]; /* REQUEST SENDERS CONNECT RECORD POINTER*/
1327  tapiBlockref = signal->theData[1];/* SENDERS BLOCK REFERENCE*/
1328  tuserpointer = signal->theData[2];
1329  if (tapiPointer >= capiConnectFilesize) {
1330  jam();
1331  signal->theData[0] = tuserpointer;
1332  signal->theData[1] = ZINVALID_CONNECTION;
1333  signal->theData[2] = __LINE__;
1334  sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 3, JBB);
1335  return;
1336  } else {
1337  jam();
1338  apiConnectptr.i = tapiPointer;
1339  }//if
1340  ptrAss(apiConnectptr, apiConnectRecord);
1341  if (apiConnectptr.p->apiConnectstate == CS_DISCONNECTED) {
1342  jam();
1343  signal->theData[0] = tuserpointer;
1344  sendSignal(tapiBlockref, GSN_TCRELEASECONF, signal, 1, JBB);
1345  } else {
1346  if (tapiBlockref == apiConnectptr.p->ndbapiBlockref) {
1347  if (apiConnectptr.p->apiConnectstate == CS_CONNECTED ||
1348  (apiConnectptr.p->apiConnectstate == CS_ABORTING &&
1349  apiConnectptr.p->abortState == AS_IDLE) ||
1350  (apiConnectptr.p->apiConnectstate == CS_STARTED &&
1351  apiConnectptr.p->firstTcConnect == RNIL))
1352  {
1353  jam(); /* JUST REPLY OK */
1354  apiConnectptr.p->m_transaction_nodes.clear();
1355  releaseApiCon(signal, apiConnectptr.i);
1356  signal->theData[0] = tuserpointer;
1357  sendSignal(tapiBlockref,
1358  GSN_TCRELEASECONF, signal, 1, JBB);
1359  } else {
1360  jam();
1361  signal->theData[0] = tuserpointer;
1362  signal->theData[1] = ZINVALID_CONNECTION;
1363  signal->theData[2] = __LINE__;
1364  signal->theData[3] = apiConnectptr.p->apiConnectstate;
1365  sendSignal(tapiBlockref,
1366  GSN_TCRELEASEREF, signal, 4, JBB);
1367  }
1368  } else {
1369  jam();
1370  signal->theData[0] = tuserpointer;
1371  signal->theData[1] = ZINVALID_CONNECTION;
1372  signal->theData[2] = __LINE__;
1373  signal->theData[3] = tapiBlockref;
1374  signal->theData[4] = apiConnectptr.p->ndbapiBlockref;
1375  sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 5, JBB);
1376  }//if
1377  }//if
1378 }//Dbtc::execTCRELEASEREQ()
1379 
1380 /****************************************************************************/
1381 // Error Handling for TCKEYREQ messages
1382 /****************************************************************************/
1383 void Dbtc::signalErrorRefuseLab(Signal* signal)
1384 {
1385  ptrGuard(apiConnectptr);
1386  if (apiConnectptr.p->apiConnectstate != CS_DISCONNECTED) {
1387  jam();
1388  apiConnectptr.p->abortState = AS_IDLE;
1389  apiConnectptr.p->apiConnectstate = CS_ABORTING;
1390  }//if
1391  sendSignalErrorRefuseLab(signal);
1392 }//Dbtc::signalErrorRefuseLab()
1393 
1394 void Dbtc::sendSignalErrorRefuseLab(Signal* signal)
1395 {
1396  ndbassert(false);
1397  ptrGuard(apiConnectptr);
1398  if (apiConnectptr.p->apiConnectstate != CS_DISCONNECTED) {
1399  jam();
1400  ndbrequire(false);
1401  signal->theData[0] = apiConnectptr.p->ndbapiConnect;
1402  signal->theData[1] = signal->theData[ttransid_ptr];
1403  signal->theData[2] = signal->theData[ttransid_ptr + 1];
1404  signal->theData[3] = ZSIGNAL_ERROR;
1405  sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREP,
1406  signal, 4, JBB);
1407  }
1408 }//Dbtc::sendSignalErrorRefuseLab()
1409 
1410 void Dbtc::abortBeginErrorLab(Signal* signal)
1411 {
1412  apiConnectptr.p->transid[0] = signal->theData[ttransid_ptr];
1413  apiConnectptr.p->transid[1] = signal->theData[ttransid_ptr + 1];
1414  abortErrorLab(signal);
1415 }//Dbtc::abortBeginErrorLab()
1416 
1417 void Dbtc::printState(Signal* signal, int place)
1418 {
1419 #ifdef VM_TRACE // Change to if 0 to disable these printouts
1420  ndbout << "-- Dbtc::printState -- " << endl;
1421  ndbout << "Received from place = " << place
1422  << " apiConnectptr.i = " << apiConnectptr.i
1423  << " apiConnectstate = " << apiConnectptr.p->apiConnectstate << endl;
1424  ndbout << "ctcTimer = " << ctcTimer
1425  << " ndbapiBlockref = " << hex <<apiConnectptr.p->ndbapiBlockref
1426  << " Transid = " << apiConnectptr.p->transid[0]
1427  << " " << apiConnectptr.p->transid[1] << endl;
1428  ndbout << " apiTimer = " << getApiConTimer(apiConnectptr.i)
1429  << " counter = " << apiConnectptr.p->counter
1430  << " lqhkeyconfrec = " << apiConnectptr.p->lqhkeyconfrec
1431  << " lqhkeyreqrec = " << apiConnectptr.p->lqhkeyreqrec << endl;
1432  ndbout << "abortState = " << apiConnectptr.p->abortState
1433  << " apiScanRec = " << apiConnectptr.p->apiScanRec
1434  << " returncode = " << apiConnectptr.p->returncode << endl;
1435  ndbout << "tckeyrec = " << apiConnectptr.p->tckeyrec
1436  << " returnsignal = " << apiConnectptr.p->returnsignal
1437  << " apiFailState = " << apiConnectptr.p->apiFailState << endl;
1438  if (apiConnectptr.p->cachePtr != RNIL) {
1439  jam();
1440  CacheRecord *localCacheRecord = cacheRecord;
1441  UintR TcacheFilesize = ccacheFilesize;
1442  UintR TcachePtr = apiConnectptr.p->cachePtr;
1443  if (TcachePtr < TcacheFilesize) {
1444  jam();
1445  CacheRecord * const regCachePtr = &localCacheRecord[TcachePtr];
1446  ndbout << "currReclenAi = " << regCachePtr->currReclenAi
1447  << " attrlength = " << regCachePtr->attrlength
1448  << " tableref = " << regCachePtr->tableref
1449  << " keylen = " << regCachePtr->keylen << endl;
1450  } else {
1451  jam();
1452  systemErrorLab(signal, __LINE__);
1453  }//if
1454  }//if
1455 #endif
1456  return;
1457 }//Dbtc::printState()
1458 
1459 void
1460 Dbtc::TCKEY_abort(Signal* signal, int place)
1461 {
1462  switch (place) {
1463  case 0:
1464  jam();
1465  terrorCode = ZSTATE_ERROR;
1466  apiConnectptr.p->firstTcConnect = RNIL;
1467  printState(signal, 4);
1468  abortBeginErrorLab(signal);
1469  return;
1470  case 1:
1471  jam();
1472  printState(signal, 3);
1473  sendSignalErrorRefuseLab(signal);
1474  return;
1475  case 2:{
1476  printState(signal, 6);
1477  const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
1478  const Uint32 t1 = tcKeyReq->transId1;
1479  const Uint32 t2 = tcKeyReq->transId2;
1480  signal->theData[0] = apiConnectptr.p->ndbapiConnect;
1481  signal->theData[1] = t1;
1482  signal->theData[2] = t2;
1483  signal->theData[3] = ZABORT_ERROR;
1484  ndbrequire(false);
1485  sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREP,
1486  signal, 4, JBB);
1487  return;
1488  }
1489  case 3:
1490  jam();
1491  printState(signal, 7);
1492  noFreeConnectionErrorLab(signal);
1493  return;
1494  case 4:
1495  jam();
1496  terrorCode = ZERO_KEYLEN_ERROR;
1497  releaseAtErrorLab(signal);
1498  return;
1499  case 5:
1500  jam();
1501  terrorCode = ZNO_AI_WITH_UPDATE;
1502  releaseAtErrorLab(signal);
1503  return;
1504  case 6:
1505  jam();
1506  warningHandlerLab(signal, __LINE__);
1507  return;
1508 
1509  case 7:
1510  jam();
1511  tabStateErrorLab(signal);
1512  return;
1513 
1514  case 8:
1515  jam();
1516  wrongSchemaVersionErrorLab(signal);
1517  return;
1518 
1519  case 9:
1520  jam();
1521  terrorCode = ZSTATE_ERROR;
1522  releaseAtErrorLab(signal);
1523  return;
1524 
1525  case 10:
1526  jam();
1527  systemErrorLab(signal, __LINE__);
1528  return;
1529 
1530  case 11:
1531  jam();
1532  terrorCode = ZMORE_AI_IN_TCKEYREQ_ERROR;
1533  releaseAtErrorLab(signal);
1534  return;
1535 
1536  case 12:
1537  jam();
1538  terrorCode = ZSIMPLE_READ_WITHOUT_AI;
1539  releaseAtErrorLab(signal);
1540  return;
1541 
1542  case 13:
1543  jam();
1544  switch (tcConnectptr.p->tcConnectstate) {
1545  case OS_WAIT_KEYINFO:
1546  jam();
1547  printState(signal, 8);
1548  terrorCode = ZSTATE_ERROR;
1549  abortErrorLab(signal);
1550  return;
1551  default:
1552  jam();
1553  /********************************************************************/
1554  /* MISMATCH BETWEEN STATE ON API CONNECTION AND THIS */
1555  /* PARTICULAR TC CONNECT RECORD. THIS MUST BE CAUSED BY NDB */
1556  /* INTERNAL ERROR. */
1557  /********************************************************************/
1558  systemErrorLab(signal, __LINE__);
1559  return;
1560  }//switch
1561  return;
1562 
1563  case 15:
1564  jam();
1565  terrorCode = ZSCAN_NODE_ERROR;
1566  releaseAtErrorLab(signal);
1567  return;
1568 
1569  case 16:
1570  jam();
1571  systemErrorLab(signal, __LINE__);
1572  return;
1573 
1574  case 17:
1575  jam();
1576  systemErrorLab(signal, __LINE__);
1577  return;
1578 
1579  case 18:
1580  jam();
1581  warningHandlerLab(signal, __LINE__);
1582  return;
1583 
1584  case 19:
1585  jam();
1586  return;
1587 
1588  case 20:
1589  jam();
1590  warningHandlerLab(signal, __LINE__);
1591  return;
1592 
1593  case 21:
1594  jam();
1595  systemErrorLab(signal, __LINE__);
1596  return;
1597 
1598  case 22:
1599  jam();
1600  systemErrorLab(signal, __LINE__);
1601  return;
1602 
1603  case 23:
1604  jam();
1605  systemErrorLab(signal, __LINE__);
1606  return;
1607 
1608  case 24:
1609  jam();
1610  appendToSectionErrorLab(signal);
1611  return;
1612 
1613  case 25:
1614  jam();
1615  warningHandlerLab(signal, __LINE__);
1616  return;
1617 
1618  case 26:
1619  jam();
1620  return;
1621 
1622  case 27:
1623  systemErrorLab(signal, __LINE__);
1624  jam();
1625  return;
1626 
1627  case 28:
1628  jam();
1629  // NOT USED
1630  return;
1631 
1632  case 29:
1633  jam();
1634  systemErrorLab(signal, __LINE__);
1635  return;
1636 
1637  case 30:
1638  jam();
1639  systemErrorLab(signal, __LINE__);
1640  return;
1641 
1642  case 31:
1643  jam();
1644  systemErrorLab(signal, __LINE__);
1645  return;
1646 
1647  case 32:
1648  jam();
1649  systemErrorLab(signal, __LINE__);
1650  return;
1651 
1652  case 33:
1653  jam();
1654  systemErrorLab(signal, __LINE__);
1655  return;
1656 
1657  case 34:
1658  jam();
1659  systemErrorLab(signal, __LINE__);
1660  return;
1661 
1662  case 35:
1663  jam();
1664  systemErrorLab(signal, __LINE__);
1665  return;
1666 
1667  case 36:
1668  jam();
1669  systemErrorLab(signal, __LINE__);
1670  return;
1671 
1672  case 37:
1673  jam();
1674  systemErrorLab(signal, __LINE__);
1675  return;
1676 
1677  case 38:
1678  jam();
1679  systemErrorLab(signal, __LINE__);
1680  return;
1681 
1682  case 39:
1683  jam();
1684  systemErrorLab(signal, __LINE__);
1685  return;
1686 
1687  case 40:
1688  jam();
1689  systemErrorLab(signal, __LINE__);
1690  return;
1691 
1692  case 41:
1693  jam();
1694  systemErrorLab(signal, __LINE__);
1695  return;
1696 
1697  case 42:
1698  jam();
1699  systemErrorLab(signal, __LINE__);
1700  return;
1701 
1702  case 43:
1703  jam();
1704  systemErrorLab(signal, __LINE__);
1705  return;
1706 
1707  case 44:
1708  jam();
1709  systemErrorLab(signal, __LINE__);
1710  return;
1711 
1712  case 45:
1713  jam();
1714  systemErrorLab(signal, __LINE__);
1715  return;
1716 
1717  case 46:
1718  jam();
1719  systemErrorLab(signal, __LINE__);
1720  return;
1721 
1722  case 47:
1723  jam();
1724  terrorCode = apiConnectptr.p->returncode;
1725  releaseAtErrorLab(signal);
1726  return;
1727 
1728  case 48:
1729  jam();
1730  terrorCode = ZCOMMIT_TYPE_ERROR;
1731  releaseAtErrorLab(signal);
1732  return;
1733 
1734  case 49:
1735  jam();
1736  abortErrorLab(signal);
1737  return;
1738 
1739  case 50:
1740  jam();
1741  systemErrorLab(signal, __LINE__);
1742  return;
1743 
1744  case 51:
1745  jam();
1746  abortErrorLab(signal);
1747  return;
1748 
1749  case 52:
1750  jam();
1751  abortErrorLab(signal);
1752  return;
1753 
1754  case 53:
1755  jam();
1756  abortErrorLab(signal);
1757  return;
1758 
1759  case 54:
1760  jam();
1761  abortErrorLab(signal);
1762  return;
1763 
1764  case 55:
1765  jam();
1766  printState(signal, 5);
1767  sendSignalErrorRefuseLab(signal);
1768  return;
1769 
1770  case 56:{
1771  jam();
1772  terrorCode = ZNO_FREE_TC_MARKER;
1773  abortErrorLab(signal);
1774  return;
1775  }
1776  case 57:{
1777  jam();
1781  initApiConnectRec(signal, apiConnectptr.p, true);
1782 start_failure:
1783  switch(getNodeState().startLevel){
1785  if (getNodeState().getSingleUserMode())
1786  {
1787  terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
1788  break;
1789  }
1792  if(getNodeState().stopping.systemShutdown)
1793  terrorCode = ZCLUSTER_SHUTDOWN_IN_PROGRESS;
1794  else
1795  terrorCode = ZNODE_SHUTDOWN_IN_PROGRESS;
1796  break;
1797  case NodeState::SL_SINGLEUSER:
1798  terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
1799  break;
1801  if (getNodeState().getSingleUserMode())
1802  {
1803  terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
1804  break;
1805  }
1806  default:
1807  terrorCode = ZWRONG_STATE;
1808  break;
1809  }
1810  abortErrorLab(signal);
1811  return;
1812  }
1813 
1814  case 58:{
1815  jam();
1816  releaseAtErrorLab(signal);
1817  return;
1818  }
1819 
1820  case 59:{
1821  jam();
1822  terrorCode = ZABORTINPROGRESS;
1823  abortErrorLab(signal);
1824  return;
1825  }
1826 
1827  case 60:
1828  {
1829  jam();
1830  initApiConnectRec(signal, apiConnectptr.p, true);
1831  apiConnectptr.p->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
1832  goto start_failure;
1833  }
1834  case 61:
1835  {
1836  jam();
1837  terrorCode = ZUNLOCKED_IVAL_TOO_HIGH;
1838  abortErrorLab(signal);
1839  return;
1840  }
1841  case 62:
1842  {
1843  jam();
1844  terrorCode = ZUNLOCKED_OP_HAS_BAD_STATE;
1845  abortErrorLab(signal);
1846  return;
1847  }
1848  case 63:
1849  {
1850  jam();
1851  /* Function not implemented yet */
1852  terrorCode = 4003;
1853  abortErrorLab(signal);
1854  return;
1855  }
1856  case 64:
1857  {
1858  jam();
1859  /* Invalid distribution key */
1860  terrorCode = ZBAD_DIST_KEY;
1861  abortErrorLab(signal);
1862  return;
1863  }
1864  case 65:
1865  {
1866  jam();
1867  terrorCode = ZTRANS_TOO_BIG;
1868  abortErrorLab(signal);
1869  return;
1870  }
1871  default:
1872  jam();
1873  systemErrorLab(signal, __LINE__);
1874  return;
1875  }//switch
1876 }
1877 
1878 static
1879 inline
1880 bool
1881 compare_transid(Uint32* val0, Uint32* val1)
1882 {
1883  Uint32 tmp0 = val0[0] ^ val1[0];
1884  Uint32 tmp1 = val0[1] ^ val1[1];
1885  return (tmp0 | tmp1) == 0;
1886 }
1887 
1888 void Dbtc::execKEYINFO(Signal* signal)
1889 {
1890  jamEntry();
1891  apiConnectptr.i = signal->theData[0];
1892  tmaxData = 20;
1893  if (apiConnectptr.i >= capiConnectFilesize) {
1894  TCKEY_abort(signal, 18);
1895  return;
1896  }//if
1897  ptrAss(apiConnectptr, apiConnectRecord);
1898  ttransid_ptr = 1;
1899  if (compare_transid(apiConnectptr.p->transid, signal->theData+1) == false)
1900  {
1901  TCKEY_abort(signal, 19);
1902  return;
1903  }//if
1904  switch (apiConnectptr.p->apiConnectstate) {
1905  case CS_RECEIVING:
1906  case CS_REC_COMMITTING:
1907  case CS_START_SCAN:
1908  jam();
1909  /*empty*/;
1910  break;
1911  /* OK */
1912  case CS_ABORTING:
1913  jam();
1914  return; /* IGNORE */
1915  case CS_CONNECTED:
1916  jam();
1917  /****************************************************************>*/
1918  /* MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND */
1919  /* SET STATE TO ABORTING. */
1920  /****************************************************************>*/
1921  printState(signal, 11);
1922  signalErrorRefuseLab(signal);
1923  return;
1924  case CS_STARTED:
1925  jam();
1926  /****************************************************************>*/
1927  /* MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND */
1928  /* SET STATE TO ABORTING. SINCE A TRANSACTION WAS STARTED */
1929  /* WE ALSO NEED TO ABORT THIS TRANSACTION. */
1930  /****************************************************************>*/
1931  terrorCode = ZSIGNAL_ERROR;
1932  printState(signal, 2);
1933  abortErrorLab(signal);
1934  return;
1935  default:
1936  jam();
1937  warningHandlerLab(signal, __LINE__);
1938  return;
1939  }//switch
1940 
1941  CacheRecord *localCacheRecord = cacheRecord;
1942  UintR TcacheFilesize = ccacheFilesize;
1943  UintR TcachePtr = apiConnectptr.p->cachePtr;
1944  UintR TtcTimer = ctcTimer;
1945  CacheRecord * const regCachePtr = &localCacheRecord[TcachePtr];
1946  if (TcachePtr >= TcacheFilesize) {
1947  TCKEY_abort(signal, 42);
1948  return;
1949  }//if
1950  setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
1951  cachePtr.i = TcachePtr;
1952  cachePtr.p = regCachePtr;
1953 
1954  tcConnectptr.i = apiConnectptr.p->lastTcConnect;
1955  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
1956  switch (tcConnectptr.p->tcConnectstate) {
1957  case OS_WAIT_KEYINFO:
1958  jam();
1959  tckeyreq020Lab(signal);
1960  return;
1961  case OS_WAIT_SCAN:
1962  jam();
1963  scanKeyinfoLab(signal);
1964  return;
1965  default:
1966  jam();
1967  terrorCode = ZSTATE_ERROR;
1968  abortErrorLab(signal);
1969  return;
1970  }//switch
1971 }//Dbtc::execKEYINFO()
1972 
1980 void Dbtc::sendKeyInfoTrain(Signal* signal,
1981  BlockReference TBRef,
1982  Uint32 connectPtr,
1983  Uint32 offset,
1984  Uint32 sectionIVal)
1985 {
1986  jam();
1987 
1988  signal->theData[0] = connectPtr;
1989  signal->theData[1] = apiConnectptr.p->transid[0];
1990  signal->theData[2] = apiConnectptr.p->transid[1];
1991  Uint32 * dst = signal->theData + KeyInfo::HeaderLength;
1992 
1993  ndbassert( sectionIVal != RNIL );
1994  SectionReader keyInfoReader(sectionIVal, getSectionSegmentPool());
1995 
1996  Uint32 totalLen= keyInfoReader.getSize();
1997 
1998  ndbassert( offset < totalLen );
1999 
2000  keyInfoReader.step(offset);
2001  totalLen-= offset;
2002 
2003  while(totalLen != 0)
2004  {
2005  Uint32 dataInSignal= MIN(KeyInfo::DataLength, totalLen);
2006  keyInfoReader.getWords(dst, dataInSignal);
2007  totalLen-= dataInSignal;
2008 
2009  sendSignal(TBRef, GSN_KEYINFO, signal,
2010  KeyInfo::HeaderLength + dataInSignal, JBB);
2011  }
2012 }//Dbtc::sendKeyInfoTrain()
2013 
2018 void Dbtc::tckeyreq020Lab(Signal* signal)
2019 {
2020  CacheRecord * const regCachePtr = cachePtr.p;
2021  UintR TkeyLen = regCachePtr->keylen;
2022  UintR Tlen = regCachePtr->save1;
2023  UintR wordsInSignal= MIN(KeyInfo::DataLength,
2024  (TkeyLen - Tlen));
2025 
2026  ndbassert(! regCachePtr->isLongTcKeyReq );
2027  ndbassert( regCachePtr->keyInfoSectionI != RNIL );
2028 
2029  /* Add received KeyInfo data to the existing KeyInfo section */
2030  if (! appendToSection(regCachePtr->keyInfoSectionI,
2031  &signal->theData[KeyInfo::HeaderLength],
2032  wordsInSignal))
2033  {
2034  jam();
2035  appendToSectionErrorLab(signal);
2036  return;
2037  }
2038  Tlen+= wordsInSignal;
2039 
2040  if (Tlen < TkeyLen)
2041  {
2042  /* More KeyInfo still to be read
2043  * Set timer and state and wait
2044  */
2045  jam();
2046  setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
2047  regCachePtr->save1 = Tlen;
2048  tcConnectptr.p->tcConnectstate = OS_WAIT_KEYINFO;
2049  return;
2050  }
2051  else
2052  {
2053  /* Have all the KeyInfo ... continue processing
2054  * TCKEYREQ
2055  */
2056  jam();
2057  tckeyreq050Lab(signal);
2058  return;
2059  }
2060 }//Dbtc::tckeyreq020Lab()
2061 
2062 void Dbtc::execATTRINFO(Signal* signal)
2063 {
2064  UintR Tdata1 = signal->theData[0];
2065  UintR Tlength = signal->length();
2066  UintR TapiConnectFilesize = capiConnectFilesize;
2067  ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
2068 
2069  jamEntry();
2070  apiConnectptr.i = Tdata1;
2071  ttransid_ptr = 1;
2072  if (Tdata1 >= TapiConnectFilesize) {
2073  DEBUG("Drop ATTRINFO, wrong apiConnectptr");
2074  TCKEY_abort(signal, 18);
2075  return;
2076  }//if
2077 
2078  ApiConnectRecord * const regApiPtr = &localApiConnectRecord[Tdata1];
2079  apiConnectptr.p = regApiPtr;
2080 
2081  if (compare_transid(regApiPtr->transid, signal->theData+1) == false)
2082  {
2083  DEBUG("Drop ATTRINFO, wrong transid, lenght="<<Tlength
2084  << " transid("<<hex<<signal->theData[1]<<", "<<signal->theData[2]);
2085  TCKEY_abort(signal, 19);
2086  return;
2087  }//if
2088  if (Tlength < 4) {
2089  DEBUG("Drop ATTRINFO, wrong length = " << Tlength);
2090  TCKEY_abort(signal, 20);
2091  return;
2092  }
2093  Tlength -= AttrInfo::HeaderLength;
2094  UintR TcompREC_COMMIT = (regApiPtr->apiConnectstate == CS_REC_COMMITTING);
2095  UintR TcompRECEIVING = (regApiPtr->apiConnectstate == CS_RECEIVING);
2096  UintR TcompBOTH = TcompREC_COMMIT | TcompRECEIVING;
2097 
2098  if (TcompBOTH) {
2099  jam();
2100  if (ERROR_INSERTED(8015)) {
2101  CLEAR_ERROR_INSERT_VALUE;
2102  return;
2103  }//if
2104  if (ERROR_INSERTED(8016)) {
2105  CLEAR_ERROR_INSERT_VALUE;
2106  return;
2107  }//if
2108  CacheRecord *localCacheRecord = cacheRecord;
2109  UintR TcacheFilesize = ccacheFilesize;
2110  UintR TcachePtr = regApiPtr->cachePtr;
2111  UintR TtcTimer = ctcTimer;
2112  CacheRecord * const regCachePtr = &localCacheRecord[TcachePtr];
2113  if (TcachePtr >= TcacheFilesize) {
2114  TCKEY_abort(signal, 43);
2115  return;
2116  }//if
2117 
2118  /* Update TC global cache ptr */
2119  cachePtr.i= TcachePtr;
2120  cachePtr.p= regCachePtr;
2121 
2122  regCachePtr->currReclenAi+= Tlength;
2123  int TattrlengthRemain = regCachePtr->attrlength -
2124  regCachePtr->currReclenAi;
2125 
2126  /* Setup tcConnectptr to ensure that error handling etc.
2127  * can access required state
2128  */
2129  tcConnectptr.i = regApiPtr->lastTcConnect;
2130  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
2131 
2132  /* Add AttrInfo to any existing AttrInfo we have
2133  * Some short TCKEYREQ signals have no ATTRINFO in
2134  * the TCKEYREQ itself
2135  */
2136  if (! appendToSection(regCachePtr->attrInfoSectionI,
2137  &signal->theData[AttrInfo::HeaderLength],
2138  Tlength))
2139  {
2140  DEBUG("No more section segments available");
2141  appendToSectionErrorLab(signal);
2142  return;
2143  }//if
2144 
2145  setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
2146 
2147  if (TattrlengthRemain == 0) {
2148  /****************************************************************>*/
2149  /* HERE WE HAVE FOUND THAT THE LAST SIGNAL BELONGING TO THIS */
2150  /* OPERATION HAVE BEEN RECEIVED. THIS MEANS THAT WE CAN NOW REUSE */
2151  /* THE API CONNECT RECORD. HOWEVER IF PREPARE OR COMMIT HAVE BEEN */
2152  /* RECEIVED THEN IT IS NOT ALLOWED TO RECEIVE ANY FURTHER */
2153  /* OPERATIONS. */
2154  /****************************************************************>*/
2155  if (TcompRECEIVING) {
2156  jam();
2157  regApiPtr->apiConnectstate = CS_STARTED;
2158  } else {
2159  jam();
2160  regApiPtr->apiConnectstate = CS_START_COMMITTING;
2161  }//if
2162  attrinfoDihReceivedLab(signal);
2163  } else if (TattrlengthRemain < 0) {
2164  jam();
2165  DEBUG("ATTRINFO wrong total length="<<Tlength
2166  <<", TattrlengthRemain="<<TattrlengthRemain
2167  <<", TattrLen="<< regCachePtr->attrlength
2168  <<", TcurrReclenAi="<< regCachePtr->currReclenAi);
2169  tcConnectptr.i = regApiPtr->lastTcConnect;
2170  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
2171  aiErrorLab(signal);
2172  }//if
2173  return;
2174  } else if (regApiPtr->apiConnectstate == CS_START_SCAN) {
2175  jam();
2176  scanAttrinfoLab(signal, Tlength);
2177  return;
2178  } else {
2179  switch (regApiPtr->apiConnectstate) {
2180  case CS_ABORTING:
2181  jam();
2182  /* JUST IGNORE THE SIGNAL*/
2183  // DEBUG("Drop ATTRINFO, CS_ABORTING");
2184  return;
2185  case CS_CONNECTED:
2186  jam();
2187  /* MOST LIKELY CAUSED BY A MISSED SIGNAL.*/
2188  // DEBUG("Drop ATTRINFO, CS_CONNECTED");
2189  return;
2190  case CS_STARTED:
2191  jam();
2192  /****************************************************************>*/
2193  /* MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND */
2194  /* SET STATE TO ABORTING. SINCE A TRANSACTION WAS STARTED */
2195  /* WE ALSO NEED TO ABORT THIS TRANSACTION. */
2196  /****************************************************************>*/
2197  terrorCode = ZSIGNAL_ERROR;
2198  printState(signal, 1);
2199  abortErrorLab(signal);
2200  return;
2201  default:
2202  jam();
2203  /****************************************************************>*/
2204  /* SIGNAL RECEIVED IN AN UNEXPECTED STATE. WE IGNORE SIGNAL */
2205  /* SINCE WE DO NOT REALLY KNOW WHERE THE ERROR OCCURRED. */
2206  /****************************************************************>*/
2207  DEBUG("Drop ATTRINFO, illegal state="<<regApiPtr->apiConnectstate);
2208  printState(signal, 9);
2209  return;
2210  }//switch
2211  }//if
2212 }//Dbtc::execATTRINFO()
2213 
2214 /* *********************************************************************>> */
2215 /* */
2216 /* MODULE: HASH MODULE */
2217 /* DESCRIPTION: CONTAINS THE HASH VALUE CALCULATION */
2218 /* *********************************************************************> */
2219 void Dbtc::hash(Signal* signal)
2220 {
2221  UintR* Tdata32;
2222 
2223  CacheRecord * const regCachePtr = cachePtr.p;
2224  SegmentedSectionPtr keyInfoSection;
2225  UintR keylen = (UintR)regCachePtr->keylen;
2226  Uint32 distKey = regCachePtr->distributionKeyIndicator;
2227 
2228  getSection(keyInfoSection, regCachePtr->keyInfoSectionI);
2229 
2230  ndbassert( keyInfoSection.sz <= MAX_KEY_SIZE_IN_WORDS );
2231  ndbassert( keyInfoSection.sz == keylen );
2232  /* Copy KeyInfo section from segmented storage into linear storage
2233  * in signal->theData
2234  */
2235  if (keylen <= SectionSegment::DataLength)
2236  {
2237  /* No need to copy keyinfo into a linear space
2238  * Note that we require that the data in the section is
2239  * 64-bit aligned for md5_hash below
2240  */
2241  ndbassert( keyInfoSection.p != NULL );
2242 
2243  Tdata32= &keyInfoSection.p->theData[0];
2244  }
2245  else
2246  {
2247  /* Copy segmented keyinfo into linear space in the signal */
2248  Tdata32= signal->theData;
2249  copy(Tdata32, keyInfoSection);
2250  }
2251 
2252  Uint32 tmp[4];
2253  if(!regCachePtr->m_special_hash)
2254  {
2255  md5_hash(tmp, (Uint64*)&Tdata32[0], keylen);
2256  }
2257  else
2258  {
2259  if (regCachePtr->m_no_hash)
2260  {
2261  /* No need for tuple key hash at LQH */
2262  ndbassert(distKey); /* User must supply distkey */
2263  Uint32 zero[4] = {0, 0, 0, 0};
2264  *tmp = *zero;
2265  }
2266  else
2267  {
2268  handle_special_hash(tmp, Tdata32, keylen, regCachePtr->tableref, !distKey);
2269  }
2270  }
2271 
2272  /* Primary key hash value is first word of hash on PK columns
2273  * Distribution key hash value is second word of hash on distribution
2274  * key columns, or a user defined value
2275  */
2276  thashValue = tmp[0];
2277  if (distKey){
2278  jam();
2279  tdistrHashValue = regCachePtr->distributionKey;
2280  } else {
2281  jam();
2282  tdistrHashValue = tmp[1];
2283  }//if
2284 }//Dbtc::hash()
2285 
2286 bool
2287 Dbtc::handle_special_hash(Uint32 dstHash[4],
2288  const Uint32* src, Uint32 srcLen,
2289  Uint32 tabPtrI,
2290  bool distr)
2291 {
2292  const Uint32 MAX_KEY_SIZE_IN_LONG_WORDS=
2293  (MAX_KEY_SIZE_IN_WORDS + 1) / 2;
2294  Uint64 alignedWorkspace[MAX_KEY_SIZE_IN_LONG_WORDS * MAX_XFRM_MULTIPLY];
2295  Uint32* workspace= (Uint32*)alignedWorkspace;
2296  const TableRecord* tabPtrP = &tableRecord[tabPtrI];
2297  const bool hasVarKeys = tabPtrP->hasVarKeys;
2298  const bool hasCharAttr = tabPtrP->hasCharAttr;
2299  const bool compute_distkey = distr && (tabPtrP->noOfDistrKeys > 0);
2300 
2301  const Uint32 *hashInput = workspace;
2302  Uint32 inputLen = 0;
2303  Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
2304  Uint32 * keyPartLenPtr;
2305 
2306  /* Normalise KeyInfo into workspace if necessary */
2307  if(hasCharAttr || (compute_distkey && hasVarKeys))
2308  {
2309  keyPartLenPtr = keyPartLen;
2310  inputLen = xfrm_key(tabPtrI,
2311  src,
2312  workspace,
2313  sizeof(alignedWorkspace) >> 2,
2314  keyPartLenPtr);
2315  if (unlikely(inputLen == 0))
2316  {
2317  goto error;
2318  }
2319  }
2320  else
2321  {
2322  /* Keyinfo already suitable for hash */
2323  hashInput = src;
2324  inputLen = srcLen;
2325  keyPartLenPtr = 0;
2326  }
2327 
2328  /* Calculate primary key hash */
2329  md5_hash(dstHash, (Uint64*)hashInput, inputLen);
2330 
2331  /* If the distribution key != primary key then we have to
2332  * form a distribution key from the primary key and calculate
2333  * a separate distribution hash based on this
2334  */
2335  if(compute_distkey)
2336  {
2337  jam();
2338 
2339  Uint32 distrKeyHash[4];
2340  /* Reshuffle primary key columns to get just distribution key */
2341  Uint32 len = create_distr_key(tabPtrI, hashInput, workspace, keyPartLenPtr);
2342  /* Calculate distribution key hash */
2343  md5_hash(distrKeyHash, (Uint64*) workspace, len);
2344 
2345  /* Just one word used for distribution */
2346  dstHash[1] = distrKeyHash[1];
2347  }
2348  return true; // success
2349 
2350 error:
2351  terrorCode = ZINVALID_KEY;
2352  return false;
2353 }
2354 
2355 /*
2356 INIT_API_CONNECT_REC
2357 ---------------------------
2358 */
2359 /* ========================================================================= */
2360 /* ======= INIT_API_CONNECT_REC ======= */
2361 /* */
2362 /* ========================================================================= */
2363 void Dbtc::initApiConnectRec(Signal* signal,
2364  ApiConnectRecord * const regApiPtr,
2365  bool releaseIndexOperations)
2366 {
2367  const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
2368  UintR TfailureNr = cfailure_nr;
2369  UintR Ttransid0 = tcKeyReq->transId1;
2370  UintR Ttransid1 = tcKeyReq->transId2;
2371 
2372  tc_clearbit(regApiPtr->m_flags, ApiConnectRecord::TF_EXEC_FLAG);
2373  regApiPtr->returncode = 0;
2374  regApiPtr->returnsignal = RS_TCKEYCONF;
2375  ndbassert(regApiPtr->firstTcConnect == RNIL);
2376  regApiPtr->firstTcConnect = RNIL;
2377  regApiPtr->lastTcConnect = RNIL;
2378  regApiPtr->globalcheckpointid = 0;
2379  regApiPtr->lqhkeyconfrec = 0;
2380  regApiPtr->lqhkeyreqrec = 0;
2381  regApiPtr->tckeyrec = 0;
2382  regApiPtr->tcindxrec = 0;
2383  tc_clearbit(regApiPtr->m_flags,
2384  ApiConnectRecord::TF_COMMIT_ACK_MARKER_RECEIVED);
2385  regApiPtr->no_commit_ack_markers = 0;
2386  regApiPtr->failureNr = TfailureNr;
2387  regApiPtr->transid[0] = Ttransid0;
2388  regApiPtr->transid[1] = Ttransid1;
2389  regApiPtr->commitAckMarker = RNIL;
2390  regApiPtr->buddyPtr = RNIL;
2391  regApiPtr->currSavePointId = 0;
2392  regApiPtr->m_transaction_nodes.clear();
2393  regApiPtr->singleUserMode = 0;
2394  regApiPtr->m_pre_commit_pass = 0;
2395  // Trigger data
2396  releaseFiredTriggerData(&regApiPtr->theFiredTriggers);
2397  // Index data
2398  tc_clearbit(regApiPtr->m_flags,
2399  ApiConnectRecord::TF_INDEX_OP_RETURN);
2400  regApiPtr->noIndexOp = 0;
2401  if(releaseIndexOperations)
2402  releaseAllSeizedIndexOperations(regApiPtr);
2403  regApiPtr->immediateTriggerId = RNIL;
2404 
2405  tc_clearbit(regApiPtr->m_flags,
2406  ApiConnectRecord::TF_DEFERRED_CONSTRAINTS);
2407  c_counters.ctransCount++;
2408 
2409 #ifdef ERROR_INSERT
2410  regApiPtr->continueBCount = 0;
2411 #endif
2412 
2413  regApiPtr->m_write_count = 0;
2414 }//Dbtc::initApiConnectRec()
2415 
2416 int
2417 Dbtc::seizeTcRecord(Signal* signal)
2418 {
2419  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
2420  TcConnectRecord *localTcConnectRecord = tcConnectRecord;
2421  UintR TfirstfreeTcConnect = cfirstfreeTcConnect;
2422  UintR TtcConnectFilesize = ctcConnectFilesize;
2423  tcConnectptr.i = TfirstfreeTcConnect;
2424  if (TfirstfreeTcConnect >= TtcConnectFilesize) {
2425  int place = 3;
2426  if (TfirstfreeTcConnect != RNIL) {
2427  place = 10;
2428  }//if
2429  TCKEY_abort(signal, place);
2430  return 1;
2431  }//if
2432  //--------------------------------------------------------------------------
2433  // Optimised version of ptrAss(tcConnectptr, tcConnectRecord)
2434  //--------------------------------------------------------------------------
2435  TcConnectRecord * const regTcPtr =
2436  &localTcConnectRecord[TfirstfreeTcConnect];
2437 
2438  UintR TlastTcConnect = regApiPtr->lastTcConnect;
2439  UintR TtcConnectptrIndex = tcConnectptr.i;
2440  TcConnectRecordPtr tmpTcConnectptr;
2441 
2442  cfirstfreeTcConnect = regTcPtr->nextTcConnect;
2443  tcConnectptr.p = regTcPtr;
2444 
2445  c_counters.cconcurrentOp++;
2446 
2447  regTcPtr->prevTcConnect = TlastTcConnect;
2448  regTcPtr->nextTcConnect = RNIL;
2449  regTcPtr->noFiredTriggers = 0;
2450  regTcPtr->noReceivedTriggers = 0;
2451  regTcPtr->triggerExecutionCount = 0;
2452  regTcPtr->triggeringOperation = RNIL;
2453  regTcPtr->m_special_op_flags = 0;
2454  regTcPtr->indexOp = RNIL;
2455  regTcPtr->currentTriggerId = RNIL;
2456  regTcPtr->tcConnectstate = OS_ABORTING;
2457  regTcPtr->noOfNodes = 0;
2458 
2459  regApiPtr->lastTcConnect = TtcConnectptrIndex;
2460 
2461  if (TlastTcConnect == RNIL) {
2462  jam();
2463  regApiPtr->firstTcConnect = TtcConnectptrIndex;
2464  } else {
2465  tmpTcConnectptr.i = TlastTcConnect;
2466  jam();
2467  ptrCheckGuard(tmpTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
2468  tmpTcConnectptr.p->nextTcConnect = TtcConnectptrIndex;
2469  }//if
2470  return 0;
2471 }//Dbtc::seizeTcRecord()
2472 
2473 int
2474 Dbtc::seizeCacheRecord(Signal* signal)
2475 {
2476  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
2477  UintR TfirstfreeCacheRec = cfirstfreeCacheRec;
2478  UintR TcacheFilesize = ccacheFilesize;
2479  CacheRecord *localCacheRecord = cacheRecord;
2480  if (TfirstfreeCacheRec >= TcacheFilesize) {
2481  TCKEY_abort(signal, 41);
2482  return 1;
2483  }//if
2484  CacheRecord * const regCachePtr = &localCacheRecord[TfirstfreeCacheRec];
2485 
2486  regApiPtr->cachePtr = TfirstfreeCacheRec;
2487  cfirstfreeCacheRec = regCachePtr->nextCacheRec;
2488  cachePtr.i = TfirstfreeCacheRec;
2489  cachePtr.p = regCachePtr;
2490 
2491  regCachePtr->currReclenAi = 0;
2492  regCachePtr->keyInfoSectionI = RNIL;
2493  regCachePtr->attrInfoSectionI = RNIL;
2494  return 0;
2495 }//Dbtc::seizeCacheRecord()
2496 
2497 /*****************************************************************************/
2498 /* T C K E Y R E Q */
2499 /* AFTER HAVING ESTABLISHED THE CONNECT, THE APPLICATION BLOCK SENDS AN */
2500 /* OPERATION REQUEST TO TC. ALL NECESSARY INFORMATION TO CARRY OUT REQUEST */
2501 /* IS FURNISHED IN PARAMETERS. TC STORES THIS INFORMATION AND ENQUIRES */
2502 /* FROM DIH ABOUT THE NODES WHICH MAY HAVE THE REQUESTED DATA */
2503 /*****************************************************************************/
2504 void Dbtc::execTCKEYREQ(Signal* signal)
2505 {
2506  Uint32 sendersNodeId = refToNode(signal->getSendersBlockRef());
2507  UintR compare_transid1, compare_transid2;
2508  const TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtr();
2509  UintR Treqinfo;
2510  SectionHandle handle(this, signal);
2511 
2512  jamEntry();
2513  /*-------------------------------------------------------------------------
2514  * Common error routines are used for several signals, they need to know
2515  * where to find the transaction identifier in the signal.
2516  *-------------------------------------------------------------------------*/
2517  const UintR TapiIndex = tcKeyReq->apiConnectPtr;
2518  const UintR TapiMaxIndex = capiConnectFilesize;
2519  const UintR TtabIndex = tcKeyReq->tableId;
2520  const UintR TtabMaxIndex = ctabrecFilesize;
2521  ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
2522 
2523  ttransid_ptr = 6;
2524  apiConnectptr.i = TapiIndex;
2525  if (TapiIndex >= TapiMaxIndex) {
2526  releaseSections(handle);
2527  TCKEY_abort(signal, 6);
2528  return;
2529  }//if
2530  if (TtabIndex >= TtabMaxIndex) {
2531  releaseSections(handle);
2532  TCKEY_abort(signal, 7);
2533  return;
2534  }//if
2535 
2536 #ifdef ERROR_INSERT
2537  if (ERROR_INSERTED(8079))
2538  {
2539  /* Test that no signals received after API_FAILREQ */
2540  if (sendersNodeId == c_lastFailedApi)
2541  {
2542  /* Signal from API node received *after* API_FAILREQ */
2543  ndbrequire(false);
2544  }
2545  }
2546 #endif
2547 
2548  Treqinfo = tcKeyReq->requestInfo;
2549  //--------------------------------------------------------------------------
2550  // Optimised version of ptrAss(tabptr, tableRecord)
2551  // Optimised version of ptrAss(apiConnectptr, apiConnectRecord)
2552  //--------------------------------------------------------------------------
2553  ApiConnectRecord * const regApiPtr = &localApiConnectRecord[TapiIndex];
2554  apiConnectptr.p = regApiPtr;
2555 
2556  Uint32 TstartFlag = TcKeyReq::getStartFlag(Treqinfo);
2557  Uint32 TexecFlag =
2558  TcKeyReq::getExecuteFlag(Treqinfo) ? ApiConnectRecord::TF_EXEC_FLAG : 0;
2559 
2560  Uint8 Tspecial_op_flags = regApiPtr->m_special_op_flags;
2561  bool isIndexOpReturn = tc_testbit(regApiPtr->m_flags,
2562  ApiConnectRecord::TF_INDEX_OP_RETURN);
2563  bool isExecutingTrigger = Tspecial_op_flags & TcConnectRecord::SOF_TRIGGER;
2564  regApiPtr->m_special_op_flags = 0; // Reset marker
2565  regApiPtr->m_flags |= TexecFlag;
2566  TableRecordPtr localTabptr;
2567  localTabptr.i = TtabIndex;
2568  localTabptr.p = &tableRecord[TtabIndex];
2569  switch (regApiPtr->apiConnectstate) {
2570  case CS_CONNECTED:{
2571  if (TstartFlag == 1 && getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == true){
2572  //---------------------------------------------------------------------
2573  // Initialise API connect record if transaction is started.
2574  //---------------------------------------------------------------------
2575  jam();
2576  initApiConnectRec(signal, regApiPtr);
2577  regApiPtr->m_flags |= TexecFlag;
2578  } else {
2579  releaseSections(handle);
2580  if(getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == true){
2581  /*------------------------------------------------------------------
2582  * WE EXPECTED A START TRANSACTION. SINCE NO OPERATIONS HAVE BEEN
2583  * RECEIVED WE INDICATE THIS BY SETTING FIRST_TC_CONNECT TO RNIL TO
2584  * ENSURE PROPER OPERATION OF THE COMMON ABORT HANDLING.
2585  *-----------------------------------------------------------------*/
2586  TCKEY_abort(signal, 0);
2587  return;
2588  } else {
2592  TCKEY_abort(signal, TexecFlag ? 60 : 57);
2593  return;
2594  }//if
2595  }
2596  }
2597  break;
2598  case CS_STARTED:
2599  if(TstartFlag == 1 && regApiPtr->firstTcConnect == RNIL)
2600  {
2606  jam();
2607  if (unlikely(getNodeState().getSingleUserMode()) &&
2608  getNodeState().getSingleUserApi() != sendersNodeId &&
2609  !localTabptr.p->singleUserMode)
2610  {
2611  releaseSections(handle);
2612  TCKEY_abort(signal, TexecFlag ? 60 : 57);
2613  return;
2614  }
2615  initApiConnectRec(signal, regApiPtr);
2616  regApiPtr->m_flags |= TexecFlag;
2617  } else {
2618  //----------------------------------------------------------------------
2619  // Transaction is started already.
2620  // Check that the operation is on the same transaction.
2621  //-----------------------------------------------------------------------
2622  compare_transid1 = regApiPtr->transid[0] ^ tcKeyReq->transId1;
2623  compare_transid2 = regApiPtr->transid[1] ^ tcKeyReq->transId2;
2624  jam();
2625  compare_transid1 = compare_transid1 | compare_transid2;
2626  if (compare_transid1 != 0) {
2627  releaseSections(handle);
2628  TCKEY_abort(signal, 1);
2629  return;
2630  }//if
2631  }
2632  break;
2633  case CS_ABORTING:
2634  if (regApiPtr->abortState == AS_IDLE) {
2635  if (TstartFlag == 1) {
2636  if(getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == false){
2637  releaseSections(handle);
2638  TCKEY_abort(signal, TexecFlag ? 60 : 57);
2639  return;
2640  }
2641  //--------------------------------------------------------------------
2642  // Previous transaction had been aborted and the abort was completed.
2643  // It is then OK to start a new transaction again.
2644  //--------------------------------------------------------------------
2645  jam();
2646  initApiConnectRec(signal, regApiPtr);
2647  regApiPtr->m_flags |= TexecFlag;
2648  } else if(TexecFlag) {
2649  releaseSections(handle);
2650  TCKEY_abort(signal, 59);
2651  return;
2652  } else {
2653  //--------------------------------------------------------------------
2654  // The current transaction was aborted successfully.
2655  // We will not do anything before we receive an operation
2656  // with a start indicator. We will ignore this signal.
2657  //--------------------------------------------------------------------
2658  jam();
2659  DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, ==AS_IDLE");
2660  releaseSections(handle);
2661  return;
2662  }//if
2663  } else {
2664  //----------------------------------------------------------------------
2665  // Previous transaction is still aborting
2666  //----------------------------------------------------------------------
2667  jam();
2668  releaseSections(handle);
2669  if (TstartFlag == 1) {
2670  //--------------------------------------------------------------------
2671  // If a new transaction tries to start while the old is
2672  // still aborting, we will report this to the starting API.
2673  //--------------------------------------------------------------------
2674  TCKEY_abort(signal, 2);
2675  return;
2676  } else if(TexecFlag) {
2677  TCKEY_abort(signal, 59);
2678  return;
2679  }
2680  //----------------------------------------------------------------------
2681  // Ignore signals without start indicator set when aborting transaction.
2682  //----------------------------------------------------------------------
2683  DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, !=AS_IDLE");
2684  return;
2685  }//if
2686  break;
2687  case CS_START_COMMITTING:
2688  case CS_SEND_FIRE_TRIG_REQ:
2689  case CS_WAIT_FIRE_TRIG_REQ:
2690  jam();
2691  if(isIndexOpReturn || isExecutingTrigger){
2692  break;
2693  }
2694  default:
2695  jam();
2696  /*----------------------------------------------------------------------
2697  * IN THIS CASE THE NDBAPI IS AN UNTRUSTED ENTITY THAT HAS SENT A SIGNAL
2698  * WHEN IT WAS NOT EXPECTED TO.
2699  * WE MIGHT BE IN A PROCESS TO RECEIVE, PREPARE,
2700  * COMMIT OR COMPLETE AND OBVIOUSLY THIS IS NOT A DESIRED EVENT.
2701  * WE WILL ALWAYS COMPLETE THE ABORT HANDLING BEFORE WE ALLOW
2702  * ANYTHING TO HAPPEN ON THIS CONNECTION AGAIN.
2703  * THUS THERE IS NO ACTION FROM THE API THAT CAN SPEED UP THIS PROCESS.
2704  *---------------------------------------------------------------------*/
2705  releaseSections(handle);
2706  TCKEY_abort(signal, 55);
2707  return;
2708  }//switch
2709 
2710  if (localTabptr.p->checkTable(tcKeyReq->tableSchemaVersion)) {
2711  ;
2712  } else {
2713  /*-----------------------------------------------------------------------*/
2714  /* THE API IS WORKING WITH AN OLD SCHEMA VERSION. IT NEEDS REPLACEMENT. */
2715  /* COULD ALSO BE THAT THE TABLE IS NOT DEFINED. */
2716  /*-----------------------------------------------------------------------*/
2717  releaseSections(handle);
2718  TCKEY_abort(signal, 8);
2719  return;
2720  }//if
2721 
2722  //-------------------------------------------------------------------------
2723  // Error Insertion for testing purposes. Test to see what happens when no
2724  // more TC records available.
2725  //-------------------------------------------------------------------------
2726  if (ERROR_INSERTED(8032)) {
2727  releaseSections(handle);
2728  TCKEY_abort(signal, 3);
2729  return;
2730  }//if
2731 
2732  if (seizeTcRecord(signal) != 0) {
2733  releaseSections(handle);
2734  return;
2735  }//if
2736 
2737  if (seizeCacheRecord(signal) != 0) {
2738  releaseSections(handle);
2739  return;
2740  }//if
2741 
2742  CRASH_INSERTION(8063);
2743 
2744  TcConnectRecord * const regTcPtr = tcConnectptr.p;
2745  CacheRecord * const regCachePtr = cachePtr.p;
2746 
2747  /*
2748  INIT_TC_CONNECT_REC
2749  -------------------------
2750  */
2751  /* ---------------------------------------------------------------------- */
2752  /* ------- INIT OPERATION RECORD WITH SIGNAL DATA AND RNILS ------- */
2753  /* */
2754  /* ---------------------------------------------------------------------- */
2755 
2756  UintR TapiVersionNo = TcKeyReq::getAPIVersion(tcKeyReq->attrLen);
2757  UintR Tlqhkeyreqrec = regApiPtr->lqhkeyreqrec;
2758  regApiPtr->lqhkeyreqrec = Tlqhkeyreqrec + 1;
2759  regCachePtr->apiVersionNo = TapiVersionNo;
2760 
2761  /* If we have any sections at all then this is a long TCKEYREQ */
2762  regCachePtr->isLongTcKeyReq= ( handle.m_cnt != 0 );
2763 
2764  UintR TapiConnectptrIndex = apiConnectptr.i;
2765  UintR TsenderData = tcKeyReq->senderData;
2766 
2767  if (ERROR_INSERTED(8065))
2768  {
2769  ErrorSignalReceive= 1;
2770  ErrorMaxSegmentsToSeize= 10;
2771  }
2772  if (ERROR_INSERTED(8066))
2773  {
2774  ErrorSignalReceive= 1;
2775  ErrorMaxSegmentsToSeize= 1;
2776  }
2777  if (ERROR_INSERTED(8067))
2778  {
2779  ErrorSignalReceive= 1;
2780  ErrorMaxSegmentsToSeize= 0;
2781  }
2782  if (ERROR_INSERTED(8068))
2783  {
2784  ErrorSignalReceive= 0;
2785  ErrorMaxSegmentsToSeize= 0;
2786  CLEAR_ERROR_INSERT_VALUE;
2787  DEBUG("Max segments to seize cleared");
2788  }
2789 #ifdef ERROR_INSERT
2790  if (ErrorSignalReceive)
2791  DEBUG("Max segments to seize : "
2792  << ErrorMaxSegmentsToSeize);
2793 #endif
2794 
2795  /* Key and attribute lengths are passed in the header for
2796  * short TCKEYREQ and passed as section lengths for long
2797  * TCKEYREQ
2798  */
2799  UintR TkeyLength = 0;
2800  UintR TattrLen = 0;
2801  UintR titcLenAiInTckeyreq = 0;
2802 
2803  if (regCachePtr->isLongTcKeyReq)
2804  {
2805  SegmentedSectionPtr keyInfoSec;
2806  if (handle.getSection(keyInfoSec, TcKeyReq::KeyInfoSectionNum))
2807  TkeyLength= keyInfoSec.sz;
2808 
2809  SegmentedSectionPtr attrInfoSec;
2810  if (handle.getSection(attrInfoSec, TcKeyReq::AttrInfoSectionNum))
2811  TattrLen= attrInfoSec.sz;
2812 
2813  if (TcKeyReq::getDeferredConstraints(Treqinfo))
2814  {
2815  regApiPtr->m_flags |= ApiConnectRecord::TF_DEFERRED_CONSTRAINTS;
2816  }
2817  }
2818  else
2819  {
2820  TkeyLength = TcKeyReq::getKeyLength(Treqinfo);
2821  TattrLen= TcKeyReq::getAttrinfoLen(tcKeyReq->attrLen);
2822  titcLenAiInTckeyreq = TcKeyReq::getAIInTcKeyReq(Treqinfo);
2823  }
2824 
2825  regCachePtr->keylen = TkeyLength;
2826  regCachePtr->lenAiInTckeyreq = titcLenAiInTckeyreq;
2827  regCachePtr->currReclenAi = titcLenAiInTckeyreq;
2828 
2829  regTcPtr->apiConnect = TapiConnectptrIndex;
2830  regTcPtr->clientData = TsenderData;
2831  regTcPtr->commitAckMarker = RNIL;
2832  regTcPtr->m_special_op_flags = Tspecial_op_flags;
2833  regTcPtr->indexOp = regApiPtr->executingIndexOp;
2834  regTcPtr->savePointId = regApiPtr->currSavePointId;
2835  regApiPtr->executingIndexOp = RNIL;
2836 
2837  regApiPtr->singleUserMode |= 1 << localTabptr.p->singleUserMode;
2838 
2839  if (isExecutingTrigger)
2840  {
2841  // Save the TcOperationPtr for fireing operation
2842  regTcPtr->triggeringOperation = TsenderData;
2843  // Grab trigger Id from ApiConnectRecord
2844  ndbrequire(regApiPtr->immediateTriggerId != RNIL);
2845  regTcPtr->currentTriggerId= regApiPtr->immediateTriggerId;
2846  }
2847  ndbassert(isExecutingTrigger ||
2848  (regApiPtr->immediateTriggerId == RNIL));
2849 
2850  if (TexecFlag){
2851  Uint32 currSPId = regApiPtr->currSavePointId;
2852  regApiPtr->currSavePointId = ++currSPId;
2853  }
2854 
2855  regCachePtr->attrlength = TattrLen;
2856  c_counters.cattrinfoCount += TattrLen;
2857 
2858  UintR TtabptrIndex = localTabptr.i;
2859  UintR TtableSchemaVersion = tcKeyReq->tableSchemaVersion;
2860  Uint8 TOperationType = TcKeyReq::getOperationType(Treqinfo);
2861  regCachePtr->tableref = TtabptrIndex;
2862  regCachePtr->schemaVersion = TtableSchemaVersion;
2863  regTcPtr->operation = TOperationType;
2864 
2865  Uint8 TSimpleFlag = TcKeyReq::getSimpleFlag(Treqinfo);
2866  Uint8 TDirtyFlag = TcKeyReq::getDirtyFlag(Treqinfo);
2867  Uint8 TInterpretedFlag = TcKeyReq::getInterpretedFlag(Treqinfo);
2868  Uint8 TDistrKeyFlag = TcKeyReq::getDistributionKeyFlag(Treqinfo);
2869  Uint8 TNoDiskFlag = TcKeyReq::getNoDiskFlag(Treqinfo);
2870  Uint8 TexecuteFlag = TexecFlag;
2871  Uint8 Treorg = TcKeyReq::getReorgFlag(Treqinfo);
2872  const Uint8 TViaSPJFlag = TcKeyReq::getViaSPJFlag(Treqinfo);
2873  const Uint8 Tqueue = TcKeyReq::getQueueOnRedoProblemFlag(Treqinfo);
2874 
2875  if (Treorg)
2876  {
2877  if (TOperationType == ZWRITE)
2878  regTcPtr->m_special_op_flags = TcConnectRecord::SOF_REORG_COPY;
2879  else if (TOperationType == ZDELETE)
2880  regTcPtr->m_special_op_flags = TcConnectRecord::SOF_REORG_DELETE;
2881  else
2882  {
2883  ndbassert(false);
2884  }
2885  }
2886 
2887  regTcPtr->dirtyOp = TDirtyFlag;
2888  regTcPtr->opSimple = TSimpleFlag;
2889  regCachePtr->opExec = TInterpretedFlag;
2890  regCachePtr->distributionKeyIndicator = TDistrKeyFlag;
2891  regCachePtr->m_no_disk_flag = TNoDiskFlag;
2892  regCachePtr->viaSPJFlag = TViaSPJFlag;
2893  regCachePtr->m_op_queue = Tqueue;
2894 
2895  //-------------------------------------------------------------
2896  // The next step is to read the upto three conditional words.
2897  //-------------------------------------------------------------
2898  Uint32 TkeyIndex;
2899  Uint32* TOptionalDataPtr = (Uint32*)&tcKeyReq->scanInfo;
2900  {
2901  Uint32 TDistrGHIndex = TcKeyReq::getScanIndFlag(Treqinfo);
2902  Uint32 TDistrKeyIndex = TDistrGHIndex;
2903 
2904  Uint32 TscanInfo = TcKeyReq::getTakeOverScanInfo(TOptionalDataPtr[0]);
2905 
2906  regCachePtr->scanTakeOverInd = TDistrGHIndex;
2907  regCachePtr->scanInfo = TscanInfo;
2908 
2909  regCachePtr->distributionKey = TOptionalDataPtr[TDistrKeyIndex];
2910 
2911  TkeyIndex = TDistrKeyIndex + TDistrKeyFlag;
2912  }
2913 
2914  regCachePtr->m_no_hash = false;
2915 
2916  if (TOperationType == ZUNLOCK)
2917  {
2918  /* Unlock op has distribution key containing
2919  * LQH nodeid and fragid
2920  */
2921  ndbassert( regCachePtr->distributionKeyIndicator );
2922  regCachePtr->m_no_hash = 1;
2923  regCachePtr->unlockNodeId = (regCachePtr->distributionKey >> 16);
2924  regCachePtr->distributionKey &= 0xffff;
2925  }
2926 
2927  regCachePtr->m_special_hash =
2928  localTabptr.p->hasCharAttr |
2929  (localTabptr.p->noOfDistrKeys > 0) |
2930  regCachePtr->m_no_hash;
2931 
2932  if (TkeyLength == 0)
2933  {
2934  releaseSections(handle);
2935  TCKEY_abort(signal, 4);
2936  return;
2937  }
2938 
2939  /* KeyInfo and AttrInfo are buffered in segmented sections
2940  * If they arrived in segmented sections then there's nothing to do
2941  * If they arrived in short signals then they are appended into
2942  * segmented sections
2943  */
2944  if (regCachePtr->isLongTcKeyReq)
2945  {
2946  ndbassert( titcLenAiInTckeyreq == 0);
2947  /* Long TcKeyReq - KI and AI already in sections */
2948  SegmentedSectionPtr keyInfoSection, attrInfoSection;
2949 
2950  /* Store i value for first long section of KeyInfo
2951  * and AttrInfo in Cache Record
2952  */
2953  handle.getSection(keyInfoSection,
2954  TcKeyReq::KeyInfoSectionNum);
2955 
2956  regCachePtr->keyInfoSectionI= keyInfoSection.i;
2957 
2958  if (regCachePtr->attrlength != 0)
2959  {
2960  ndbassert( handle.m_cnt == 2 );
2961  handle.getSection(attrInfoSection,
2962  TcKeyReq::AttrInfoSectionNum);
2963  regCachePtr->attrInfoSectionI= attrInfoSection.i;
2964  }
2965  else
2966  {
2967  ndbassert( handle.m_cnt == 1 );
2968  }
2969 
2970  /* Detach sections from the handle, we are now responsible
2971  * for always freeing them before returning
2972  * For a long TcKeyReq, they will be freed at the end
2973  * of the processing this signal.
2974  */
2975  handle.clear();
2976  }
2977  else
2978  {
2979  /* Short TcKeyReq - need to receive KI and AI into
2980  * segmented sections
2981  * We store any KI and AI from the TCKeyReq now and
2982  * will then wait for further signals if necessary
2983  */
2984  ndbassert( handle.m_cnt == 0 );
2985  Uint32 keyInfoInTCKeyReq= MIN(TkeyLength, TcKeyReq::MaxKeyInfo);
2986 
2987  bool ok= appendToSection(regCachePtr->keyInfoSectionI,
2988  &TOptionalDataPtr[TkeyIndex],
2989  keyInfoInTCKeyReq);
2990  if (!ok)
2991  {
2992  jam();
2993  appendToSectionErrorLab(signal);
2994  return;
2995  }
2996 
2997  if (titcLenAiInTckeyreq != 0)
2998  {
2999  Uint32 TAIDataIndex= TkeyIndex + keyInfoInTCKeyReq;
3000 
3001  ok= appendToSection(regCachePtr->attrInfoSectionI,
3002  &TOptionalDataPtr[TAIDataIndex],
3003  titcLenAiInTckeyreq);
3004  if (!ok)
3005  {
3006  jam();
3007  appendToSectionErrorLab(signal);
3008  return;
3009  }
3010  }
3011  }
3012 
3013  if (TOperationType == ZUNLOCK)
3014  {
3015  jam();
3016  // TODO : Consider adding counter for unlock operations
3017  }
3018  else if (TOperationType == ZREAD || TOperationType == ZREAD_EX) {
3019  jam();
3020  c_counters.creadCount++;
3021  }
3022  else
3023  {
3024  /* Insert, Update, Write, Delete */
3025  if (!tc_testbit(regApiPtr->m_flags,
3026  ApiConnectRecord::TF_COMMIT_ACK_MARKER_RECEIVED))
3027  {
3028  if(regApiPtr->commitAckMarker != RNIL)
3029  regTcPtr->commitAckMarker = regApiPtr->commitAckMarker;
3030  else
3031  {
3032  jam();
3033  CommitAckMarkerPtr tmp;
3034  if (ERROR_INSERTED(8087))
3035  {
3036  CLEAR_ERROR_INSERT_VALUE;
3037  TCKEY_abort(signal, 56);
3038  return;
3039  }
3040 
3041  if (!m_commitAckMarkerHash.seize(tmp))
3042  {
3043  TCKEY_abort(signal, 56);
3044  return;
3045  }
3046  else
3047  {
3048  regTcPtr->commitAckMarker = tmp.i;
3049  regApiPtr->commitAckMarker = tmp.i;
3050  tmp.p->transid1 = tcKeyReq->transId1;
3051  tmp.p->transid2 = tcKeyReq->transId2;
3052  tmp.p->apiNodeId = refToNode(regApiPtr->ndbapiBlockref);
3053  tmp.p->apiConnectPtr = TapiIndex;
3054  tmp.p->m_commit_ack_marker_nodes.clear();
3055 #if defined VM_TRACE || defined ERROR_INSERT
3056  {
3057  CommitAckMarkerPtr check;
3058  ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
3059  }
3060 #endif
3061  m_commitAckMarkerHash.add(tmp);
3062  }
3063  }
3064  regApiPtr->no_commit_ack_markers++;
3065  }
3066 
3067  UintR Toperationsize = coperationsize;
3068  /* --------------------------------------------------------------------
3069  * THIS IS A TEMPORARY TABLE, DON'T UPDATE coperationsize.
3070  * THIS VARIABLE CONTROLS THE INTERVAL BETWEEN LCP'S AND
3071  * TEMP TABLES DON'T PARTICIPATE.
3072  * -------------------------------------------------------------------- */
3073  if (localTabptr.p->get_storedTable()) {
3074  coperationsize = ((Toperationsize + TattrLen) + TkeyLength) + 17;
3075  }
3076  c_counters.cwriteCount++;
3077  switch (TOperationType) {
3078  case ZUPDATE:
3079  case ZINSERT:
3080  case ZDELETE:
3081  case ZWRITE:
3082  case ZREFRESH:
3083  jam();
3084  if (unlikely((++ regApiPtr->m_write_count) > m_max_writes_per_trans))
3085  {
3086  TCKEY_abort(signal, 65);
3087  return;
3088  }
3089  break;
3090  default:
3091  TCKEY_abort(signal, 9);
3092  return;
3093  }//switch
3094  }//if
3095 
3096  Uint32 TabortOption = TcKeyReq::getAbortOption(Treqinfo);
3097  regTcPtr->m_execAbortOption = TabortOption;
3098 
3099  /*-------------------------------------------------------------------------
3100  * Check error handling per operation
3101  * If CommitFlag is set state accordingly and check for early abort
3102  *------------------------------------------------------------------------*/
3103  if (TcKeyReq::getCommitFlag(Treqinfo) == 1) {
3104  ndbrequire(TexecuteFlag);
3105  regApiPtr->apiConnectstate = CS_REC_COMMITTING;
3106  } else {
3107  /* ---------------------------------------------------------------------
3108  * PREPARE TRANSACTION IS NOT IMPLEMENTED YET.
3109  * ---------------------------------------------------------------------
3110  * ELSIF (TREQINFO => 3) (*) 1 = 1 THEN
3111  * IF PREPARE TRANSACTION THEN
3112  * API_CONNECTPTR:API_CONNECTSTATE = REC_PREPARING
3113  * SET STATE TO PREPARING
3114  * --------------------------------------------------------------------- */
3115  if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
3116  jam();
3117  // Trigger execution at commit
3118  regApiPtr->apiConnectstate = CS_REC_COMMITTING;
3119  } else if (!regApiPtr->isExecutingDeferredTriggers()) {
3120  jam();
3121  regApiPtr->apiConnectstate = CS_RECEIVING;
3122  }//if
3123  }//if
3124 
3125  if (regCachePtr->isLongTcKeyReq)
3126  {
3127  jam();
3128  /* Have all the KeyInfo (and AttrInfo), process now */
3129  tckeyreq050Lab(signal);
3130  }
3131  else if (TkeyLength <= TcKeyReq::MaxKeyInfo)
3132  {
3133  jam();
3134  /* Have all the KeyInfo, get any extra AttrInfo */
3135  tckeyreq050Lab(signal);
3136  }
3137  else
3138  {
3139  jam();
3140  /* --------------------------------------------------------------------
3141  * THE TCKEYREQ DIDN'T CONTAIN ALL KEY DATA,
3142  * SAVE STATE AND WAIT FOR KEYINFO
3143  * --------------------------------------------------------------------*/
3144  setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
3145  regCachePtr->save1 = 8;
3146  regTcPtr->tcConnectstate = OS_WAIT_KEYINFO;
3147  return;
3148  }//if
3149 
3150  return;
3151 }//Dbtc::execTCKEYREQ()
3152 
3153 static
3154 void
3155 handle_reorg_trigger(DiGetNodesConf * conf)
3156 {
3157  if (conf->reqinfo & DiGetNodesConf::REORG_MOVING)
3158  {
3159  conf->fragId = conf->nodes[MAX_REPLICAS];
3160  conf->reqinfo = conf->nodes[MAX_REPLICAS+1];
3161  memcpy(conf->nodes, conf->nodes+MAX_REPLICAS+2, sizeof(conf->nodes));
3162  }
3163  else
3164  {
3165  conf->nodes[0] = 0; // Should not execute...
3166  }
3167 }
3168 
3169 bool
3170 Dbtc::isRefreshSupported() const
3171 {
3172  const NodeVersionInfo& nvi = getNodeVersionInfo();
3173  const Uint32 minVer = nvi.m_type[NodeInfo::DB].m_min_version;
3174  const Uint32 maxVer = nvi.m_type[NodeInfo::DB].m_max_version;
3175 
3176  if (likely (minVer == maxVer))
3177  {
3178  /* Normal case, use function */
3179  return ndb_refresh_tuple(minVer);
3180  }
3181 
3182  /* As refresh feature was introduced across three minor versions
3183  * we check that all data nodes support it. This slow path
3184  * should only be hit during upgrades between versions
3185  */
3186  for (Uint32 i=1; i < MAX_NODES; i++)
3187  {
3188  const NodeInfo& nodeInfo = getNodeInfo(i);
3189  if ((nodeInfo.m_type == NODE_TYPE_DB) &&
3190  (nodeInfo.m_connected) &&
3191  (! ndb_refresh_tuple(nodeInfo.m_version)))
3192  return false;
3193  }
3194  return true;
3195 }
3196 
3202 void Dbtc::tckeyreq050Lab(Signal* signal)
3203 {
3204  UintR tnoOfBackup;
3205  UintR tnoOfStandby;
3206  UintR tnodeinfo;
3207 
3208  terrorCode = 0;
3209 
3210  hash(signal); /* NOW IT IS TIME TO CALCULATE THE HASH VALUE*/
3211 
3212  CacheRecord * const regCachePtr = cachePtr.p;
3213  TcConnectRecord * const regTcPtr = tcConnectptr.p;
3214  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3215 
3216  UintR TtcTimer = ctcTimer;
3217  UintR ThashValue = thashValue;
3218  UintR TdistrHashValue = tdistrHashValue;
3219  UintR Ttableref = regCachePtr->tableref;
3220  Uint8 Tspecial_op_flags = regTcPtr->m_special_op_flags;
3221 
3222  TableRecordPtr localTabptr;
3223  localTabptr.i = Ttableref;
3224  localTabptr.p = &tableRecord[localTabptr.i];
3225  Uint32 schemaVersion = regCachePtr->schemaVersion;
3226  if(localTabptr.p->checkTable(schemaVersion)){
3227  ;
3228  } else {
3229  terrorCode = localTabptr.p->getErrorCode(schemaVersion);
3230  TCKEY_abort(signal, 58);
3231  return;
3232  }
3233 
3234  setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
3235  regCachePtr->hashValue = ThashValue;
3236 
3237  ndbassert( signal->getNoOfSections() == 0 );
3238 
3239  DiGetNodesReq * const req = (DiGetNodesReq *)&signal->theData[0];
3240  req->tableId = Ttableref;
3241  req->hashValue = TdistrHashValue;
3242  req->distr_key_indicator = regCachePtr->distributionKeyIndicator;
3243  * (EmulatedJamBuffer**)req->jamBuffer = jamBuffer();
3244 
3245  /*-------------------------------------------------------------*/
3246  /* FOR EFFICIENCY REASONS WE AVOID THE SIGNAL SENDING HERE AND */
3247  /* PROCEED IMMEDIATELY TO DIH. IN MULTI-THREADED VERSIONS WE */
3248  /* HAVE TO INSERT A MUTEX ON DIH TO ENSURE PROPER OPERATION. */
3249  /* SINCE THIS SIGNAL AND DIVERIFYREQ ARE THE ONLY SIGNALS SENT */
3250  /* TO DIH IN TRAFFIC IT SHOULD BE OK (3% OF THE EXECUTION TIME */
3251  /* IS SPENT IN DIH AND EVEN LESS IN REPLICATED NDB. */
3252  /*-------------------------------------------------------------*/
3253  EXECUTE_DIRECT(DBDIH, GSN_DIGETNODESREQ, signal,
3254  DiGetNodesReq::SignalLength, 0);
3255  DiGetNodesConf * conf = (DiGetNodesConf *)&signal->theData[0];
3256  UintR Tdata2 = conf->reqinfo;
3257  UintR TerrorIndicator = signal->theData[0];
3258  jamEntry();
3259  if (TerrorIndicator != 0) {
3260  execDIGETNODESREF(signal);
3261  return;
3262  }
3263 
3264  if((ERROR_INSERTED(8071) || ERROR_INSERTED(8072)) &&
3265  (regTcPtr->m_special_op_flags & TcConnectRecord::SOF_INDEX_TABLE_READ) &&
3266  signal->theData[3] != getOwnNodeId())
3267  {
3268  ndbassert(false);
3269  signal->theData[1] = 626;
3270  execDIGETNODESREF(signal);
3271  return;
3272  }
3273 
3274  if((ERROR_INSERTED(8050) || ERROR_INSERTED(8072)) &&
3275  refToBlock(regApiPtr->ndbapiBlockref) != DBUTIL &&
3276  regTcPtr->m_special_op_flags == 0 &&
3277  signal->theData[3] != getOwnNodeId())
3278  {
3279  ndbassert(false);
3280  signal->theData[1] = 626;
3281  execDIGETNODESREF(signal);
3282  return;
3283  }
3284 
3285  /****************>>*/
3286  /* DIGETNODESCONF >*/
3287  /* ***************>*/
3288  if (Tspecial_op_flags & TcConnectRecord::SOF_REORG_TRIGGER_BASE)
3289  {
3290  jam();
3291  handle_reorg_trigger(conf);
3292  Tdata2 = conf->reqinfo;
3293  }
3294  else if (Tspecial_op_flags & TcConnectRecord::SOF_REORG_DELETE)
3295  {
3296  jam();
3297  handle_reorg_trigger(conf);
3298  Tdata2 = conf->reqinfo;
3299  }
3300  else if (Tdata2 & DiGetNodesConf::REORG_MOVING)
3301  {
3302  jam();
3303  regTcPtr->m_special_op_flags |= TcConnectRecord::SOF_REORG_MOVING;
3304  }
3305  else if (Tspecial_op_flags & TcConnectRecord::SOF_REORG_COPY)
3306  {
3307  jam();
3308  conf->nodes[0] = 0;
3309  }
3310 
3311  UintR Tdata1 = conf->fragId;
3312  UintR Tdata3 = conf->nodes[0];
3313  UintR Tdata4 = conf->nodes[1];
3314  UintR Tdata5 = conf->nodes[2];
3315  UintR Tdata6 = conf->nodes[3];
3316 
3317  regCachePtr->fragmentid = Tdata1;
3318  tnodeinfo = Tdata2;
3319 
3320  regTcPtr->tcNodedata[0] = Tdata3;
3321  regTcPtr->tcNodedata[1] = Tdata4;
3322  regTcPtr->tcNodedata[2] = Tdata5;
3323  regTcPtr->tcNodedata[3] = Tdata6;
3324 
3325  regTcPtr->lqhInstanceKey = (Tdata2 >> 24) & 127;// 1 bit used for reorg moving
3326 
3327  Uint8 Toperation = regTcPtr->operation;
3328  Uint8 TopSimple = regTcPtr->opSimple;
3329  Uint8 TopDirty = regTcPtr->dirtyOp;
3330  tnoOfBackup = tnodeinfo & 3;
3331  tnoOfStandby = (tnodeinfo >> 8) & 3;
3332 
3333  regCachePtr->fragmentDistributionKey = (tnodeinfo >> 16) & 255;
3334  if (Toperation == ZREAD || Toperation == ZREAD_EX)
3335  {
3336  regTcPtr->m_special_op_flags &= ~TcConnectRecord::SOF_REORG_MOVING;
3337  if (TopSimple == 1 && TopDirty == 0){
3338  jam();
3339  /*-------------------------------------------------------------*/
3340  /* A SIMPLE READ CAN SELECT ANY OF THE PRIMARY AND */
3341  /* BACKUP NODES TO READ. WE WILL TRY TO SELECT THIS */
3342  /* NODE IF POSSIBLE TO AVOID UNNECESSARY COMMUNICATION */
3343  /* WITH SIMPLE READS. */
3344  /*-------------------------------------------------------------*/
3345  arrGuard(tnoOfBackup, MAX_REPLICAS);
3346  UintR Tindex;
3347  UintR TownNode = cownNodeid;
3348  for (Tindex = 1; Tindex <= tnoOfBackup; Tindex++) {
3349  UintR Tnode = regTcPtr->tcNodedata[Tindex];
3350  jam();
3351  if (Tnode == TownNode) {
3352  jam();
3353  regTcPtr->tcNodedata[0] = Tnode;
3354  }//if
3355  }//for
3356  if(ERROR_INSERTED(8048) || ERROR_INSERTED(8049))
3357  {
3358  for (Tindex = 0; Tindex <= tnoOfBackup; Tindex++)
3359  {
3360  UintR Tnode = regTcPtr->tcNodedata[Tindex];
3361  jam();
3362  if (Tnode != TownNode) {
3363  jam();
3364  regTcPtr->tcNodedata[0] = Tnode;
3365  ndbout_c("Choosing %d", Tnode);
3366  }//if
3367  }//for
3368  }
3369  }//if
3370  jam();
3371  regTcPtr->lastReplicaNo = 0;
3372  regTcPtr->noOfNodes = 1;
3373  }
3374  else if (Toperation == ZUNLOCK)
3375  {
3376  regTcPtr->m_special_op_flags &= ~TcConnectRecord::SOF_REORG_MOVING;
3377 
3378  const Uint32 numNodes = tnoOfBackup + 1;
3379  /* Check that node from dist key is one of the nodes returned */
3380  bool found = false;
3381  for (Uint32 idx = 0; idx < numNodes; idx ++)
3382  {
3383  Uint32 nodeId = regTcPtr->tcNodedata[ idx ];
3384  jam();
3385  if (nodeId == regCachePtr->unlockNodeId)
3386  {
3387  jam();
3388  found = true;
3389  break;
3390  }
3391  }
3392 
3393  if (unlikely(!found))
3394  {
3395  /* DIH says the specified node does not store the fragment
3396  * requested
3397  */
3398  jam();
3399  TCKEY_abort(signal, 64);
3400  return;
3401  }
3402 
3403  /* Check that the relevant LQH node can handle an unlock request */
3404  Uint32 lqhVersion = getNodeInfo(regCachePtr->unlockNodeId).m_version;
3405 
3406  if (unlikely( lqhVersion < NDBD_UNLOCK_OP_SUPPORTED ))
3407  {
3408  TCKEY_abort(signal, 63);
3409  return;
3410  }
3411 
3412  /* Select the specified node for the unlock op */
3413  regTcPtr->tcNodedata[0] = regCachePtr->unlockNodeId;
3414  regTcPtr->lastReplicaNo = 0;
3415  regTcPtr->noOfNodes = 1;
3416  }
3417  else {
3418  UintR TlastReplicaNo;
3419  jam();
3420  TlastReplicaNo = tnoOfBackup + tnoOfStandby;
3421  regTcPtr->lastReplicaNo = (Uint8)TlastReplicaNo;
3422  regTcPtr->noOfNodes = (Uint8)(TlastReplicaNo + 1);
3423 
3424  if (unlikely((Toperation == ZREFRESH) &&
3425  (! isRefreshSupported())))
3426  {
3427  /* Function not implemented yet */
3428  TCKEY_abort(signal,63);
3429  return;
3430  }
3431  }//if
3432 
3433  if (regCachePtr->isLongTcKeyReq ||
3434  (regCachePtr->lenAiInTckeyreq == regCachePtr->attrlength)) {
3435  /****************************************************************>*/
3436  /* HERE WE HAVE FOUND THAT THE LAST SIGNAL BELONGING TO THIS */
3437  /* OPERATION HAVE BEEN RECEIVED. THIS MEANS THAT WE CAN NOW REUSE */
3438  /* THE API CONNECT RECORD. HOWEVER IF PREPARE OR COMMIT HAVE BEEN */
3439  /* RECEIVED THEN IT IS NOT ALLOWED TO RECEIVE ANY FURTHER */
3440  /* OPERATIONS. WE KNOW THAT WE WILL WAIT FOR DICT NEXT. IT IS NOT */
3441  /* POSSIBLE FOR THE TC CONNECTION TO BE READY YET. */
3442  /****************************************************************>*/
3443  switch (regApiPtr->apiConnectstate) {
3444  case CS_RECEIVING:
3445  jam();
3446  regApiPtr->apiConnectstate = CS_STARTED;
3447  break;
3448  case CS_REC_COMMITTING:
3449  jam();
3450  regApiPtr->apiConnectstate = CS_START_COMMITTING;
3451  break;
3452  case CS_SEND_FIRE_TRIG_REQ:
3453  case CS_WAIT_FIRE_TRIG_REQ:
3454  jam();
3455  break;
3456  default:
3457  jam();
3458  systemErrorLab(signal, __LINE__);
3459  return;
3460  }//switch
3461  attrinfoDihReceivedLab(signal);
3462  return;
3463  } else {
3464  if (regCachePtr->lenAiInTckeyreq < regCachePtr->attrlength) {
3465  TtcTimer = ctcTimer;
3466  jam();
3467  setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
3468  regTcPtr->tcConnectstate = OS_WAIT_ATTR;
3469  return;
3470  } else {
3471  TCKEY_abort(signal, 11);
3472  return;
3473  }//if
3474  }//if
3475  return;
3476 }//Dbtc::tckeyreq050Lab()
3477 
3478 void Dbtc::attrinfoDihReceivedLab(Signal* signal)
3479 {
3480  CacheRecord * const regCachePtr = cachePtr.p;
3481  TcConnectRecord * const regTcPtr = tcConnectptr.p;
3482  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3483  Uint16 Tnode = regTcPtr->tcNodedata[0];
3484 
3485  TableRecordPtr localTabptr;
3486  localTabptr.i = regCachePtr->tableref;
3487  localTabptr.p = &tableRecord[localTabptr.i];
3488 
3489  if(localTabptr.p->checkTable(regCachePtr->schemaVersion)){
3490  ;
3491  } else {
3492  terrorCode = localTabptr.p->getErrorCode(regCachePtr->schemaVersion);
3493  TCKEY_abort(signal, 58);
3494  return;
3495  }
3496  if (Tnode != 0)
3497  {
3498  jam();
3499  arrGuard(Tnode, MAX_NDB_NODES);
3500  Uint32 instanceKey = regTcPtr->lqhInstanceKey;
3501  BlockReference lqhRef;
3502  if(regCachePtr->viaSPJFlag){
3503  //ndbout << "TC:Choosing SPJ." << endl;
3504  lqhRef = numberToRef(DBSPJ, Tnode); // Only 1 instance
3505  }else{
3506  //ndbout << "TC:Choosing LQH." << endl;
3507  lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
3508  }
3509  packLqhkeyreq(signal, lqhRef);
3510  }
3511  else
3512  {
3520  jam();
3521  Uint32 trigOp = regTcPtr->triggeringOperation;
3522  Uint32 TclientData = regTcPtr->clientData;
3523  releaseKeys();
3524  releaseAttrinfo();
3525  regApiPtr->lqhkeyreqrec--;
3526  unlinkReadyTcCon(signal);
3527  clearCommitAckMarker(regApiPtr, regTcPtr);
3528  releaseTcCon();
3529 
3530  if (trigOp != RNIL)
3531  {
3532  jam();
3533  //ndbassert(false); // see above
3534  TcConnectRecordPtr opPtr;
3535  opPtr.i = trigOp;
3536  ptrCheckGuard(opPtr, ctcConnectFilesize, tcConnectRecord);
3537  trigger_op_finished(signal, apiConnectptr, opPtr.p);
3538  return;
3539  }
3540  else
3541  {
3542  jam();
3543  Uint32 Ttckeyrec = regApiPtr->tckeyrec;
3544  regApiPtr->tcSendArray[Ttckeyrec] = TclientData;
3545  regApiPtr->tcSendArray[Ttckeyrec + 1] = 0;
3546  regApiPtr->tckeyrec = Ttckeyrec + 2;
3547  lqhKeyConf_checkTransactionState(signal, apiConnectptr);
3548  }
3549  }
3550 }//Dbtc::attrinfoDihReceivedLab()
3551 
3552 void Dbtc::packLqhkeyreq(Signal* signal,
3553  BlockReference TBRef)
3554 {
3555  CacheRecord * const regCachePtr = cachePtr.p;
3556  UintR Tkeylen = regCachePtr->keylen;
3557 
3558  ndbassert( signal->getNoOfSections() == 0 );
3559 
3560  sendlqhkeyreq(signal, TBRef);
3561 
3562  /* Do we need to send a KeyInfo signal train? */
3563  if ((! regCachePtr->useLongLqhKeyReq) &&
3564  (Tkeylen > LqhKeyReq::MaxKeyInfo))
3565  {
3566  /* Build KeyInfo train from KeyInfo long signal section */
3567  sendKeyInfoTrain(signal,
3568  TBRef,
3569  tcConnectptr.i,
3570  LqhKeyReq::MaxKeyInfo,
3571  regCachePtr->keyInfoSectionI);
3572  }//if
3573 
3574  /* Release key storage */
3575  releaseKeys();
3576  packLqhkeyreq040Lab(signal,
3577  TBRef);
3578 }//Dbtc::packLqhkeyreq()
3579 
3580 
3581 void Dbtc::sendlqhkeyreq(Signal* signal,
3582  BlockReference TBRef)
3583 {
3584  UintR tslrAttrLen;
3585  UintR Tdata10;
3586  TcConnectRecord * const regTcPtr = tcConnectptr.p;
3587  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3588  CacheRecord * const regCachePtr = cachePtr.p;
3589  Uint32 version = getNodeInfo(refToNode(TBRef)).m_version;
3590  UintR sig0, sig1, sig2, sig3, sig4, sig5, sig6;
3591 #ifdef ERROR_INSERT
3592  if (ERROR_INSERTED(8002)) {
3593  systemErrorLab(signal, __LINE__);
3594  }//if
3595  if (ERROR_INSERTED(8007)) {
3596  if (apiConnectptr.p->apiConnectstate == CS_STARTED) {
3597  CLEAR_ERROR_INSERT_VALUE;
3598  return;
3599  }//if
3600  }//if
3601  if (ERROR_INSERTED(8008)) {
3602  if (apiConnectptr.p->apiConnectstate == CS_START_COMMITTING) {
3603  CLEAR_ERROR_INSERT_VALUE;
3604  return;
3605  }//if
3606  }//if
3607  if (ERROR_INSERTED(8009)) {
3608  if (apiConnectptr.p->apiConnectstate == CS_STARTED) {
3609  return;
3610  }//if
3611  }//if
3612  if (ERROR_INSERTED(8010)) {
3613  if (apiConnectptr.p->apiConnectstate == CS_START_COMMITTING) {
3614  return;
3615  }//if
3616  }//if
3617 #endif
3618  Uint32 Tdeferred = tc_testbit(regApiPtr->m_flags,
3619  ApiConnectRecord::TF_DEFERRED_CONSTRAINTS);
3620  Uint32 reorg = 0;
3621  Uint32 Tspecial_op = regTcPtr->m_special_op_flags;
3622  if (Tspecial_op == 0)
3623  {
3624  }
3625  else if (Tspecial_op & (TcConnectRecord::SOF_REORG_TRIGGER_BASE |
3626  TcConnectRecord::SOF_REORG_DELETE))
3627  {
3628  reorg = 1;
3629  }
3630  else if (Tspecial_op & TcConnectRecord::SOF_REORG_MOVING)
3631  {
3632  reorg = 2;
3633  }
3634 
3635  Uint32 inlineKeyLen= 0;
3636  Uint32 inlineAttrLen= 0;
3637 
3638  /* We normally send long LQHKEYREQ unless the
3639  * destination cannot handle it or we are
3640  * testing
3641  */
3642  if (unlikely((version < NDBD_LONG_LQHKEYREQ) ||
3643  ERROR_INSERTED(8069)))
3644  {
3645  /* Short LQHKEYREQ, with some key/attr data inline */
3646  regCachePtr->useLongLqhKeyReq= 0;
3647  inlineKeyLen= regCachePtr->keylen;
3648  inlineAttrLen= regCachePtr->attrlength;
3649  }
3650  else
3651  /* Long LQHKEYREQ, with key/attr data in long sections */
3652  regCachePtr->useLongLqhKeyReq= 1;
3653 
3654  tslrAttrLen = 0;
3655  LqhKeyReq::setAttrLen(tslrAttrLen, inlineAttrLen);
3656  /* ---------------------------------------------------------------------- */
3657  // Bit16 == 0 since StoredProcedures are not yet supported.
3658  /* ---------------------------------------------------------------------- */
3659  LqhKeyReq::setDistributionKey(tslrAttrLen, regCachePtr->fragmentDistributionKey);
3660  LqhKeyReq::setScanTakeOverFlag(tslrAttrLen, regCachePtr->scanTakeOverInd);
3661  LqhKeyReq::setReorgFlag(tslrAttrLen, reorg);
3662 
3663  Tdata10 = 0;
3664  sig0 = regTcPtr->opSimple;
3665  sig1 = regTcPtr->operation;
3666  sig2 = regTcPtr->dirtyOp;
3667  bool dirtyRead = (sig1 == ZREAD && sig2 == ZTRUE);
3668  LqhKeyReq::setKeyLen(Tdata10, inlineKeyLen);
3669  LqhKeyReq::setLastReplicaNo(Tdata10, regTcPtr->lastReplicaNo);
3670  if (unlikely(version < NDBD_ROWID_VERSION))
3671  {
3672  Uint32 op = regTcPtr->operation;
3673  Uint32 lock = (Operation_t) op == ZREAD_EX ? ZUPDATE : (Operation_t) op == ZWRITE ? ZINSERT : (Operation_t) op;
3674  LqhKeyReq::setLockType(Tdata10, lock);
3675  }
3676  /* ---------------------------------------------------------------------- */
3677  // Indicate Application Reference is present in bit 15
3678  /* ---------------------------------------------------------------------- */
3679  LqhKeyReq::setApplicationAddressFlag(Tdata10, 1);
3680  LqhKeyReq::setDirtyFlag(Tdata10, sig2);
3681  LqhKeyReq::setInterpretedFlag(Tdata10, regCachePtr->opExec);
3682  LqhKeyReq::setSimpleFlag(Tdata10, sig0);
3683  LqhKeyReq::setOperation(Tdata10, sig1);
3684  LqhKeyReq::setNoDiskFlag(Tdata10, regCachePtr->m_no_disk_flag);
3685  LqhKeyReq::setQueueOnRedoProblemFlag(Tdata10, regCachePtr->m_op_queue);
3686  LqhKeyReq::setDeferredConstraints(Tdata10, (Tdeferred & m_deferred_enabled));
3687 
3688  /* -----------------------------------------------------------------------
3689  * If we are sending a short LQHKEYREQ, then there will be some AttrInfo
3690  * in the LQHKEYREQ.
3691  * Work out how much we'll send
3692  * ----------------------------------------------------------------------- */
3693  UintR aiInLqhKeyReq= 0;
3694 
3695  if (! regCachePtr->useLongLqhKeyReq)
3696  {
3697  /* Short LQHKEYREQ :
3698  * Send max 5 words of AttrInfo in LQHKEYREQ
3699  */
3700  aiInLqhKeyReq= MIN(LqhKeyReq::MaxAttrInfo, regCachePtr->attrlength);
3701  }
3702 
3703  LqhKeyReq::setAIInLqhKeyReq(Tdata10, aiInLqhKeyReq);
3704  /* -----------------------------------------------------------------------
3705  * Bit 27 == 0 since TC record is the same as the client record.
3706  * Bit 28 == 0 since readLenAi can only be set after reading in LQH.
3707  * ----------------------------------------------------------------------- */
3708  //LqhKeyReq::setAPIVersion(Tdata10, regCachePtr->apiVersionNo);
3709  LqhKeyReq::setMarkerFlag(Tdata10, regTcPtr->commitAckMarker != RNIL ? 1 : 0);
3710 
3711  /* ************************************************************> */
3712  /* NO READ LENGTH SENT FROM TC. SEQUENTIAL NUMBER IS 1 AND IT */
3713  /* IS SENT TO A PRIMARY NODE. */
3714  /* ************************************************************> */
3715 
3716  LqhKeyReq * const lqhKeyReq = (LqhKeyReq *)signal->getDataPtrSend();
3717 
3718  sig0 = tcConnectptr.i;
3719  sig2 = regCachePtr->hashValue;
3720  sig4 = cownref;
3721  sig5 = regTcPtr->savePointId;
3722 
3723  lqhKeyReq->clientConnectPtr = sig0;
3724  lqhKeyReq->attrLen = tslrAttrLen;
3725  lqhKeyReq->hashValue = sig2;
3726  lqhKeyReq->requestInfo = Tdata10;
3727  lqhKeyReq->tcBlockref = sig4;
3728  lqhKeyReq->savePointId = sig5;
3729 
3730  sig0 = regCachePtr->tableref + ((regCachePtr->schemaVersion << 16) & 0xFFFF0000);
3731  sig1 = regCachePtr->fragmentid + (regTcPtr->tcNodedata[1] << 16);
3732  sig2 = regApiPtr->transid[0];
3733  sig3 = regApiPtr->transid[1];
3734  sig4 =
3735  (regTcPtr->m_special_op_flags & TcConnectRecord::SOF_INDEX_TABLE_READ) ?
3736  reference() : regApiPtr->ndbapiBlockref;
3737  sig5 = regTcPtr->clientData;
3738  sig6 = regCachePtr->scanInfo;
3739 
3740  if (! dirtyRead)
3741  {
3742  regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[0]);
3743  regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[1]);
3744  regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[2]);
3745  regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[3]);
3746  }
3747 
3748  lqhKeyReq->tableSchemaVersion = sig0;
3749  lqhKeyReq->fragmentData = sig1;
3750  lqhKeyReq->transId1 = sig2;
3751  lqhKeyReq->transId2 = sig3;
3752  lqhKeyReq->scanInfo = sig6;
3753 
3754  lqhKeyReq->variableData[0] = sig4;
3755  lqhKeyReq->variableData[1] = sig5;
3756 
3757  UintR nextPos = 2;
3758 
3759  if (regTcPtr->lastReplicaNo > 1) {
3760  sig0 = (UintR)regTcPtr->tcNodedata[2] +
3761  (UintR)(regTcPtr->tcNodedata[3] << 16);
3762  lqhKeyReq->variableData[nextPos] = sig0;
3763  nextPos++;
3764  }//if
3765 
3766  // Reset trigger count
3767  regTcPtr->noFiredTriggers = 0;
3768  regTcPtr->triggerExecutionCount = 0;
3769 
3770  if (regCachePtr->useLongLqhKeyReq)
3771  {
3772  /* Build long LQHKeyReq using Key + AttrInfo sections */
3773  SectionHandle handle(this);
3774  SegmentedSectionPtr keyInfoSection;
3775 
3776  getSection(keyInfoSection, regCachePtr->keyInfoSectionI);
3777 
3778  handle.m_ptr[ LqhKeyReq::KeyInfoSectionNum ]= keyInfoSection;
3779  handle.m_cnt= 1;
3780 
3781  if (regCachePtr->attrlength != 0)
3782  {
3783  SegmentedSectionPtr attrInfoSection;
3784 
3785  ndbassert(regCachePtr->attrInfoSectionI != RNIL);
3786  getSection(attrInfoSection, regCachePtr->attrInfoSectionI);
3787 
3788  handle.m_ptr[ LqhKeyReq::AttrInfoSectionNum ]= attrInfoSection;
3789  handle.m_cnt= 2;
3790  }
3791 
3792  sendSignal(TBRef, GSN_LQHKEYREQ, signal,
3793  nextPos + LqhKeyReq::FixedSignalLength, JBB,
3794  &handle);
3795 
3796  /* Long sections were freed as part of sendSignal */
3797  ndbassert( handle.m_cnt == 0 );
3798  regCachePtr->keyInfoSectionI= RNIL;
3799  regCachePtr->attrInfoSectionI= RNIL;
3800  }
3801  else
3802  {
3803  /* Build short LQHKeyReq from Key + AttrInfo sections
3804  *
3805  * Read upto 4 words of KeyInfo from TCKEYREQ KeyInfo section into
3806  * LqhKeyReq signal
3807  */
3808  SegmentedSectionPtr keyInfoSection;
3809 
3810  getSection(keyInfoSection, regCachePtr->keyInfoSectionI);
3811  SectionReader keyInfoReader(keyInfoSection, getSectionSegmentPool());
3812 
3813  UintR keyLenInLqhKeyReq= MIN(LqhKeyReq::MaxKeyInfo, regCachePtr->keylen);
3814 
3815  keyInfoReader.getWords(&lqhKeyReq->variableData[nextPos], keyLenInLqhKeyReq);
3816 
3817  nextPos+= keyLenInLqhKeyReq;
3818 
3819  if (aiInLqhKeyReq != 0)
3820  {
3821  /* Read upto 5 words of AttrInfo from TCKEYREQ KeyInfo section into
3822  * LqhKeyReq signal
3823  */
3824  SegmentedSectionPtr attrInfoSection;
3825 
3826  ndbassert(regCachePtr->attrInfoSectionI != RNIL);
3827 
3828  getSection(attrInfoSection, regCachePtr->attrInfoSectionI);
3829  SectionReader attrInfoReader(attrInfoSection, getSectionSegmentPool());
3830 
3831  attrInfoReader.getWords(&lqhKeyReq->variableData[nextPos], aiInLqhKeyReq);
3832 
3833  nextPos+= aiInLqhKeyReq;
3834  }
3835 
3836  sendSignal(TBRef, GSN_LQHKEYREQ, signal,
3837  nextPos + LqhKeyReq::FixedSignalLength, JBB);
3838  }
3839 }//Dbtc::sendlqhkeyreq()
3840 
3841 void Dbtc::packLqhkeyreq040Lab(Signal* signal,
3842  BlockReference TBRef)
3843 {
3844  TcConnectRecord * const regTcPtr = tcConnectptr.p;
3845  CacheRecord * const regCachePtr = cachePtr.p;
3846 #ifdef ERROR_INSERT
3847  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3848 
3849  if (ERROR_INSERTED(8009)) {
3850  if (regApiPtr->apiConnectstate == CS_STARTED) {
3851  CLEAR_ERROR_INSERT_VALUE;
3852  return;
3853  }//if
3854  }//if
3855  if (ERROR_INSERTED(8010)) {
3856  if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
3857  CLEAR_ERROR_INSERT_VALUE;
3858  return;
3859  }//if
3860  }//if
3861 #endif
3862 
3863  /* Do we have an ATTRINFO train to send? */
3864  if (!regCachePtr->useLongLqhKeyReq)
3865  {
3866  /* Short LqhKeyReq */
3867  if (regCachePtr->attrlength > LqhKeyReq::MaxAttrInfo)
3868  {
3869  if (unlikely( !sendAttrInfoTrain(signal,
3870  TBRef,
3871  tcConnectptr.i,
3872  LqhKeyReq::MaxAttrInfo,
3873  regCachePtr->attrInfoSectionI)))
3874  {
3875  jam();
3876  TCKEY_abort(signal, 17);
3877  return;
3878  }
3879  }
3880  } // useLongLqhKeyReq
3881 
3882  /* Release AttrInfo related storage, and the Cache Record */
3883  releaseAttrinfo();
3884 
3885  UintR TtcTimer = ctcTimer;
3886  UintR Tread = (regTcPtr->operation == ZREAD);
3887  UintR Tdirty = (regTcPtr->dirtyOp == ZTRUE);
3888  UintR Tboth = Tread & Tdirty;
3889  setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
3890  jam();
3891  /*--------------------------------------------------------------------
3892  * WE HAVE SENT ALL THE SIGNALS OF THIS OPERATION. SET STATE AND EXIT.
3893  *---------------------------------------------------------------------*/
3894  if (Tboth) {
3895  jam();
3896  releaseDirtyRead(signal, apiConnectptr, tcConnectptr.p);
3897  return;
3898  }//if
3899  regTcPtr->tcConnectstate = OS_OPERATING;
3900  return;
3901 }//Dbtc::packLqhkeyreq040Lab()
3902 
3903 /* ========================================================================= */
3904 /* ------- RELEASE ALL ATTRINFO RECORDS IN AN OPERATION RECORD ------- */
3905 /* ========================================================================= */
3906 void Dbtc::releaseAttrinfo()
3907 {
3908  CacheRecord * const regCachePtr = cachePtr.p;
3909  Uint32 attrInfoSectionI= cachePtr.p->attrInfoSectionI;
3910 
3911  /* Release AttrInfo section if there is one */
3912  releaseSection( attrInfoSectionI );
3913  cachePtr.p->attrInfoSectionI= RNIL;
3914 
3915  //---------------------------------------------------
3916  // Now we will release the cache record at the same
3917  // time as releasing the attrinfo records.
3918  //---------------------------------------------------
3919  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3920  UintR TfirstfreeCacheRec = cfirstfreeCacheRec;
3921  UintR TCacheIndex = cachePtr.i;
3922  regCachePtr->nextCacheRec = TfirstfreeCacheRec;
3923  cfirstfreeCacheRec = TCacheIndex;
3924  regApiPtr->cachePtr = RNIL;
3925  return;
3926 }//Dbtc::releaseAttrinfo()
3927 
3928 /* ========================================================================= */
3929 /* ------- RELEASE ALL RECORDS CONNECTED TO A DIRTY OPERATION ------- */
3930 /* ========================================================================= */
3931 void Dbtc::releaseDirtyRead(Signal* signal,
3932  ApiConnectRecordPtr regApiPtr,
3933  TcConnectRecord* regTcPtr)
3934 {
3935  Uint32 Ttckeyrec = regApiPtr.p->tckeyrec;
3936  Uint32 TclientData = regTcPtr->clientData;
3937  Uint32 Tnode = regTcPtr->tcNodedata[0];
3938  Uint32 Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
3939  ConnectionState state = regApiPtr.p->apiConnectstate;
3940 
3941  regApiPtr.p->tcSendArray[Ttckeyrec] = TclientData;
3942  regApiPtr.p->tcSendArray[Ttckeyrec + 1] = TcKeyConf::DirtyReadBit | Tnode;
3943  regApiPtr.p->tckeyrec = Ttckeyrec + 2;
3944 
3945  unlinkReadyTcCon(signal);
3946  releaseTcCon();
3947 
3952  c_counters.csimpleReadCount++;
3953  regApiPtr.p->lqhkeyreqrec = --Tlqhkeyreqrec;
3954 
3955  if(Tlqhkeyreqrec == 0)
3956  {
3961  sendtckeyconf(signal, state == CS_START_COMMITTING);
3962  regApiPtr.p->apiConnectstate =
3963  (state == CS_START_COMMITTING ? CS_CONNECTED : state);
3964  setApiConTimer(regApiPtr.i, 0, __LINE__);
3965 
3966  return;
3967  }
3968 
3972  lqhKeyConf_checkTransactionState(signal, regApiPtr);
3973 }//Dbtc::releaseDirtyRead()
3974 
3975 /* ------------------------------------------------------------------------- */
3976 /* ------- CHECK IF ALL TC CONNECTIONS ARE COMPLETED ------- */
3977 /* ------------------------------------------------------------------------- */
3978 void Dbtc::unlinkReadyTcCon(Signal* signal)
3979 {
3980  TcConnectRecordPtr urtTcConnectptr;
3981 
3982  TcConnectRecord * const regTcPtr = tcConnectptr.p;
3983  TcConnectRecord *localTcConnectRecord = tcConnectRecord;
3984  UintR TtcConnectFilesize = ctcConnectFilesize;
3985  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3986  if (regTcPtr->prevTcConnect != RNIL) {
3987  jam();
3988  urtTcConnectptr.i = regTcPtr->prevTcConnect;
3989  ptrCheckGuard(urtTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
3990  urtTcConnectptr.p->nextTcConnect = regTcPtr->nextTcConnect;
3991  } else {
3992  jam();
3993  regApiPtr->firstTcConnect = regTcPtr->nextTcConnect;
3994  }//if
3995  if (regTcPtr->nextTcConnect != RNIL) {
3996  jam();
3997  urtTcConnectptr.i = regTcPtr->nextTcConnect;
3998  ptrCheckGuard(urtTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
3999  urtTcConnectptr.p->prevTcConnect = regTcPtr->prevTcConnect;
4000  } else {
4001  jam();
4002  regApiPtr->lastTcConnect = tcConnectptr.p->prevTcConnect;
4003  }//if
4004 }//Dbtc::unlinkReadyTcCon()
4005 
4006 void Dbtc::releaseTcCon()
4007 {
4008  TcConnectRecord * const regTcPtr = tcConnectptr.p;
4009  UintR TfirstfreeTcConnect = cfirstfreeTcConnect;
4010  UintR TtcConnectptrIndex = tcConnectptr.i;
4011 
4012  ndbrequire(regTcPtr->commitAckMarker == RNIL);
4013  regTcPtr->tcConnectstate = OS_CONNECTED;
4014  regTcPtr->nextTcConnect = TfirstfreeTcConnect;
4015  regTcPtr->apiConnect = RNIL;
4016  regTcPtr->m_special_op_flags = 0;
4017  regTcPtr->indexOp = RNIL;
4018  cfirstfreeTcConnect = TtcConnectptrIndex;
4019  c_counters.cconcurrentOp--;
4020 }//Dbtc::releaseTcCon()
4021 
4022 void Dbtc::execPACKED_SIGNAL(Signal* signal)
4023 {
4024  LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
4025 
4026  UintR Ti;
4027  UintR Tstep = 0;
4028  UintR Tlength;
4029  UintR TpackedData[28];
4030  UintR Tdata1, Tdata2, Tdata3, Tdata4;
4031 
4032  jamEntry();
4033  Tlength = signal->length();
4034  if (Tlength > 25) {
4035  jam();
4036  systemErrorLab(signal, __LINE__);
4037  return;
4038  }//if
4039  Uint32* TpackDataPtr;
4040  for (Ti = 0; Ti < Tlength; Ti += 4) {
4041  Uint32* TsigDataPtr = &signal->theData[Ti];
4042  Tdata1 = TsigDataPtr[0];
4043  Tdata2 = TsigDataPtr[1];
4044  Tdata3 = TsigDataPtr[2];
4045  Tdata4 = TsigDataPtr[3];
4046 
4047  TpackDataPtr = &TpackedData[Ti];
4048  TpackDataPtr[0] = Tdata1;
4049  TpackDataPtr[1] = Tdata2;
4050  TpackDataPtr[2] = Tdata3;
4051  TpackDataPtr[3] = Tdata4;
4052  }//for
4053  while (Tlength > Tstep) {
4054 
4055  TpackDataPtr = &TpackedData[Tstep];
4056  Tdata1 = TpackDataPtr[0];
4057  Tdata2 = TpackDataPtr[1];
4058  Tdata3 = TpackDataPtr[2];
4059 
4060  lqhKeyConf->connectPtr = Tdata1 & 0x0FFFFFFF;
4061  lqhKeyConf->opPtr = Tdata2;
4062  lqhKeyConf->userRef = Tdata3;
4063 
4064  switch (Tdata1 >> 28) {
4065  case ZCOMMITTED:
4066  signal->header.theLength = 3;
4067  execCOMMITTED(signal);
4068  Tstep += 3;
4069  break;
4070  case ZCOMPLETED:
4071  signal->header.theLength = 3;
4072  execCOMPLETED(signal);
4073  Tstep += 3;
4074  break;
4075  case ZLQHKEYCONF:
4076  jam();
4077  Tdata1 = TpackDataPtr[3];
4078  Tdata2 = TpackDataPtr[4];
4079  Tdata3 = TpackDataPtr[5];
4080  Tdata4 = TpackDataPtr[6];
4081 
4082  lqhKeyConf->readLen = Tdata1;
4083  lqhKeyConf->transId1 = Tdata2;
4084  lqhKeyConf->transId2 = Tdata3;
4085  lqhKeyConf->noFiredTriggers = Tdata4;
4086  signal->header.theLength = LqhKeyConf::SignalLength;
4087  execLQHKEYCONF(signal);
4088  Tstep += LqhKeyConf::SignalLength;
4089  break;
4090  case ZFIRE_TRIG_CONF:
4091  jam();
4092  signal->header.theLength = 4;
4093  signal->theData[3] = TpackDataPtr[3];
4094  execFIRE_TRIG_CONF(signal);
4095  Tstep += 4;
4096  break;
4097  default:
4098  systemErrorLab(signal, __LINE__);
4099  return;
4100  }//switch
4101  }//while
4102  return;
4103 }//Dbtc::execPACKED_SIGNAL()
4104 
4105 
4106 void Dbtc::execSIGNAL_DROPPED_REP(Signal* signal)
4107 {
4108  /* An incoming signal was dropped, handle it
4109  * Dropped signal really means that we ran out of
4110  * long signal buffering to store its sections
4111  */
4112  jamEntry();
4113 
4114  if (!assembleDroppedFragments(signal))
4115  {
4116  jam();
4117  return;
4118  }
4119 
4120  const SignalDroppedRep* rep = (SignalDroppedRep*) &signal->theData[0];
4121  Uint32 originalGSN= rep->originalGsn;
4122 
4123  DEBUG("SignalDroppedRep received for GSN " << originalGSN);
4124 
4125  switch(originalGSN) {
4126  case GSN_TCKEYREQ:
4127  jam();
4128  /* Fall through */
4129  case GSN_TCINDXREQ:
4130  {
4131  jam();
4132 
4133  /* Get original signal data - unfortunately it may
4134  * have been truncated. We must not read beyond
4135  * word # 22
4136  * We will send an Abort to the Api using info from
4137  * the received signal and clean up our transaction
4138  * state
4139  */
4140  const TcKeyReq * const truncatedTcKeyReq =
4141  (TcKeyReq *) &rep->originalData[0];
4142 
4143  const UintR apiIndex = truncatedTcKeyReq->apiConnectPtr;
4144 
4145  if (apiIndex >= capiConnectFilesize)
4146  {
4147  jam();
4148  warningHandlerLab(signal, __LINE__);
4149  return;
4150  }
4151 
4152  /* We have a valid Api ConnectPtr...
4153  * Ensure that we have the necessary information
4154  * to send a rollback to the client
4155  */
4156  apiConnectptr.i = apiIndex;
4157  ApiConnectRecord * const regApiPtr = &apiConnectRecord[apiIndex];
4158  apiConnectptr.p = regApiPtr;
4159  UintR transId1= truncatedTcKeyReq->transId1;
4160  UintR transId2= truncatedTcKeyReq->transId2;
4161 
4162  /* Ensure that the apiConnectptr global is initialised
4163  * may not be in cases where we drop the first signal of
4164  * a transaction
4165  */
4166  apiConnectptr.p->transid[0] = transId1;
4167  apiConnectptr.p->transid[1] = transId2;
4168  apiConnectptr.p->returncode = ZGET_DATAREC_ERROR;
4169 
4170  /* Set m_exec_flag according to the dropped request */
4171  apiConnectptr.p->m_flags |=
4172  TcKeyReq::getExecuteFlag(truncatedTcKeyReq->requestInfo) ?
4173  ApiConnectRecord::TF_EXEC_FLAG : 0;
4174 
4175  DEBUG(" Execute flag set to " << tc_testbit(apiConnectptr.p->m_flags,
4176  ApiConnectRecord::TF_EXEC_FLAG)
4177  );
4178 
4179  abortErrorLab(signal);
4180 
4181  break;
4182  }
4183  case GSN_SCAN_TABREQ:
4184  {
4185  jam();
4186  /* Get information necessary to send SCAN_TABREF back to client */
4187  // TODO : Handle dropped signal fragments
4188  const ScanTabReq * const truncatedScanTabReq =
4189  (ScanTabReq *) &rep->originalData[0];
4190 
4191  Uint32 apiConnectPtr= truncatedScanTabReq->apiConnectPtr;
4192  Uint32 transId1= truncatedScanTabReq->transId1;
4193  Uint32 transId2= truncatedScanTabReq->transId2;
4194 
4195  if (apiConnectPtr >= capiConnectFilesize)
4196  {
4197  jam();
4198  warningHandlerLab(signal, __LINE__);
4199  return;
4200  }//if
4201 
4202  apiConnectptr.i = apiConnectPtr;
4203  ptrAss(apiConnectptr, apiConnectRecord);
4204  ApiConnectRecord * transP = apiConnectptr.p;
4205 
4206  /* Now send the SCAN_TABREF */
4207  ScanTabRef* ref= (ScanTabRef*)&signal->theData[0];
4208  ref->apiConnectPtr = transP->ndbapiConnect;
4209  ref->transId1= transId1;
4210  ref->transId2= transId2;
4211  ref->errorCode= ZGET_ATTRBUF_ERROR;
4212  ref->closeNeeded= 0;
4213 
4214  sendSignal(transP->ndbapiBlockref, GSN_SCAN_TABREF,
4215  signal, ScanTabRef::SignalLength, JBB);
4216  break;
4217  }
4218  default:
4219  jam();
4220  /* Don't expect dropped signals for other GSNs,
4221  * default handling
4222  * TODO : Can TC get long TRANSID_AI as part of
4223  * Unique index operations?
4224  */
4225  SimulatedBlock::execSIGNAL_DROPPED_REP(signal);
4226  };
4227 
4228  return;
4229 }
4230 
4231 
4232 void Dbtc::execLQHKEYCONF(Signal* signal)
4233 {
4234  const LqhKeyConf * lqhKeyConf = CAST_CONSTPTR(LqhKeyConf,
4235  signal->getDataPtr());
4236 #ifdef UNUSED
4237  ndbout << "TC: Received LQHKEYCONF"
4238  << " transId1=" << lqhKeyConf-> transId1
4239  << " transId2=" << lqhKeyConf-> transId2
4240  << endl;
4241 #endif /*UNUSED*/
4242  UintR compare_transid1, compare_transid2;
4243  BlockReference tlastLqhBlockref;
4244  UintR tlastLqhConnect;
4245  UintR treadlenAi;
4246  UintR TtcConnectptrIndex;
4247  UintR TtcConnectFilesize = ctcConnectFilesize;
4248 
4249  tlastLqhConnect = lqhKeyConf->connectPtr;
4250  TtcConnectptrIndex = lqhKeyConf->opPtr;
4251  tlastLqhBlockref = lqhKeyConf->userRef;
4252  treadlenAi = lqhKeyConf->readLen;
4253  TcConnectRecord *localTcConnectRecord = tcConnectRecord;
4254 
4255  /*------------------------------------------------------------------------
4256  * NUMBER OF EXTERNAL TRIGGERS FIRED IN DATA[6]
4257  * OPERATION IS NOW COMPLETED. CHECK FOR CORRECT OPERATION POINTER
4258  * TO ENSURE NO CRASHES BECAUSE OF ERRONEUS NODES. CHECK STATE OF
4259  * OPERATION. THEN SET OPERATION STATE AND RETRIEVE ALL POINTERS
4260  * OF THIS OPERATION. PUT COMPLETED OPERATION IN LIST OF COMPLETED
4261  * OPERATIONS ON THE LQH CONNECT RECORD.
4262  *------------------------------------------------------------------------
4263  * THIS SIGNAL ALWAYS ARRIVE BEFORE THE ABORTED SIGNAL ARRIVES SINCE IT USES
4264  * THE SAME PATH BACK TO TC AS THE ABORTED SIGNAL DO. WE DO HOWEVER HAVE A
4265  * PROBLEM WHEN WE ENCOUNTER A TIME-OUT WAITING FOR THE ABORTED SIGNAL.
4266  * THEN THIS SIGNAL MIGHT ARRIVE WHEN THE TC CONNECT RECORD HAVE BEEN REUSED
4267  * BY OTHER TRANSACTION THUS WE CHECK THE TRANSACTION ID OF THE SIGNAL
4268  * BEFORE ACCEPTING THIS SIGNAL.
4269  * Due to packing of LQHKEYCONF the ABORTED signal can now arrive before
4270  * this.
4271  * This is more reason to ignore the signal if not all states are correct.
4272  *------------------------------------------------------------------------*/
4273  if (TtcConnectptrIndex >= TtcConnectFilesize) {
4274  TCKEY_abort(signal, 25);
4275  return;
4276  }//if
4277  TcConnectRecord* const regTcPtr = &localTcConnectRecord[TtcConnectptrIndex];
4278  OperationState TtcConnectstate = regTcPtr->tcConnectstate;
4279  tcConnectptr.i = TtcConnectptrIndex;
4280  tcConnectptr.p = regTcPtr;
4281  if (TtcConnectstate != OS_OPERATING) {
4282  warningReport(signal, 23);
4283  return;
4284  }//if
4285  ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
4286  UintR TapiConnectptrIndex = regTcPtr->apiConnect;
4287  UintR TapiConnectFilesize = capiConnectFilesize;
4288  UintR Ttrans1 = lqhKeyConf->transId1;
4289  UintR Ttrans2 = lqhKeyConf->transId2;
4290  Uint32 noFired = LqhKeyConf::getFiredCount(lqhKeyConf->noFiredTriggers);
4291  Uint32 deferred = LqhKeyConf::getDeferredBit(lqhKeyConf->noFiredTriggers);
4292 
4293  if (TapiConnectptrIndex >= TapiConnectFilesize) {
4294  TCKEY_abort(signal, 29);
4295  return;
4296  }//if
4297  Ptr<ApiConnectRecord> regApiPtr;
4298  regApiPtr.i = TapiConnectptrIndex;
4299  regApiPtr.p = &localApiConnectRecord[TapiConnectptrIndex];
4300  apiConnectptr.i = TapiConnectptrIndex;
4301  apiConnectptr.p = regApiPtr.p;
4302  compare_transid1 = regApiPtr.p->transid[0] ^ Ttrans1;
4303  compare_transid2 = regApiPtr.p->transid[1] ^ Ttrans2;
4304  compare_transid1 = compare_transid1 | compare_transid2;
4305  if (compare_transid1 != 0) {
4306  warningReport(signal, 24);
4307  return;
4308  }//if
4309 
4310 #ifdef ERROR_INSERT
4311  if (ERROR_INSERTED(8029)) {
4312  systemErrorLab(signal, __LINE__);
4313  }//if
4314  if (ERROR_INSERTED(8003)) {
4315  if (regApiPtr.p->apiConnectstate == CS_STARTED) {
4316  CLEAR_ERROR_INSERT_VALUE;
4317  return;
4318  }//if
4319  }//if
4320  if (ERROR_INSERTED(8004)) {
4321  if (regApiPtr.p->apiConnectstate == CS_RECEIVING) {
4322  CLEAR_ERROR_INSERT_VALUE;
4323  return;
4324  }//if
4325  }//if
4326  if (ERROR_INSERTED(8005)) {
4327  if (regApiPtr.p->apiConnectstate == CS_REC_COMMITTING) {
4328  CLEAR_ERROR_INSERT_VALUE;
4329  return;
4330  }//if
4331  }//if
4332  if (ERROR_INSERTED(8006)) {
4333  if (regApiPtr.p->apiConnectstate == CS_START_COMMITTING) {
4334  CLEAR_ERROR_INSERT_VALUE;
4335  return;
4336  }//if
4337  }//if
4338  if (ERROR_INSERTED(8023)) {
4339  SET_ERROR_INSERT_VALUE(8024);
4340  return;
4341  }//if
4342 #endif
4343  UintR TtcTimer = ctcTimer;
4344  regTcPtr->lastLqhCon = tlastLqhConnect;
4345  regTcPtr->lastLqhNodeId = refToNode(tlastLqhBlockref);
4346  regTcPtr->noFiredTriggers = noFired;
4347  regTcPtr->m_special_op_flags |= (deferred) ?
4348  TcConnectRecord::SOF_DEFERRED_TRIGGER : 0;
4349  regApiPtr.p->m_flags |= (deferred) ?
4350  ApiConnectRecord::TF_DEFERRED_TRIGGERS : 0;
4351 
4352  UintR Ttckeyrec = (UintR)regApiPtr.p->tckeyrec;
4353  UintR TclientData = regTcPtr->clientData;
4354  UintR TdirtyOp = regTcPtr->dirtyOp;
4355  Uint32 TopSimple = regTcPtr->opSimple;
4356  Uint32 Toperation = regTcPtr->operation;
4357  ConnectionState TapiConnectstate = regApiPtr.p->apiConnectstate;
4358 
4359  if (TapiConnectstate == CS_ABORTING) {
4360  warningReport(signal, 27);
4361  return;
4362  }//if
4363 
4364  Uint32 lockingOpI = RNIL;
4365  if (Toperation == ZUNLOCK)
4366  {
4367  /* For unlock operations readlen in TCKEYCONF carries
4368  * the locking operation TC reference
4369  */
4370  lockingOpI = treadlenAi;
4371  treadlenAi = 0;
4372  }
4373 
4374  Uint32 commitAckMarker = regTcPtr->commitAckMarker;
4375  regTcPtr->commitAckMarker = RNIL;
4376  setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
4377 
4378  if (commitAckMarker != RNIL)
4379  {
4380  const Uint32 noOfLqhs = regTcPtr->noOfNodes;
4381  CommitAckMarker * tmp = m_commitAckMarkerHash.getPtr(commitAckMarker);
4382  jam();
4383  regApiPtr.p->m_flags |= ApiConnectRecord::TF_COMMIT_ACK_MARKER_RECEIVED;
4387  for(Uint32 i = 0; i < noOfLqhs; i++)
4388  tmp->m_commit_ack_marker_nodes.set(regTcPtr->tcNodedata[i]);
4389  }
4390  if (regTcPtr->isIndexOp(regTcPtr->m_special_op_flags)) {
4391  jam();
4392  // This was an internal TCKEYREQ
4393  // will be returned unpacked
4394  regTcPtr->attrInfoLen = treadlenAi;
4395  } else {
4396  if (noFired == 0 && regTcPtr->triggeringOperation == RNIL) {
4397  jam();
4398 
4399  if (Ttckeyrec > (ZTCOPCONF_SIZE - 2)) {
4400  TCKEY_abort(signal, 30);
4401  return;
4402  }
4403 
4404  /*
4405  * Skip counting triggering operations the first round
4406  * since they will enter execLQHKEYCONF a second time
4407  * Skip counting internally generated TcKeyReq
4408  */
4409  regApiPtr.p->tcSendArray[Ttckeyrec] = TclientData;
4410  regApiPtr.p->tcSendArray[Ttckeyrec + 1] = treadlenAi;
4411  regApiPtr.p->tckeyrec = Ttckeyrec + 2;
4412  }//if
4413  }//if
4414  if (TdirtyOp == ZTRUE)
4415  {
4416  UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
4417  jam();
4418  releaseDirtyWrite(signal);
4419  regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
4420  }
4421  else if (Toperation == ZREAD && TopSimple)
4422  {
4423  UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
4424  jam();
4425  unlinkReadyTcCon(signal);
4426  releaseTcCon();
4427  regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
4428  }
4429  else if (Toperation == ZUNLOCK)
4430  {
4431  jam();
4432  /* We've unlocked and released a read operation in LQH
4433  * The readLenAi member contains the TC OP reference
4434  * for the unlocked operation.
4435  * So here we :
4436  * 1) Validate the TC OP reference
4437  * 2) Release the referenced TC op
4438  * 3) Send TCKEYCONF back to the user
4439  * 4) Release our own TC op
4440  */
4441  Uint32 unlockOpI = tcConnectptr.i;
4442 
4443  ndbrequire( noFired == 0 );
4444  ndbrequire( regTcPtr->triggeringOperation == RNIL );
4445 
4446  /* Switch to the original locking operation */
4447  if (unlikely( lockingOpI >= ctcConnectFilesize ))
4448  {
4449  jam();
4450  TCKEY_abort(signal, 61);
4451  return;
4452  }
4453  tcConnectptr.i = lockingOpI;
4454  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
4455 
4456  const TcConnectRecord * regLockTcPtr = tcConnectptr.p;
4457 
4458  /* Validate the locking operation's state */
4459  bool locking_op_ok =
4460  ( ( regLockTcPtr->apiConnect == regTcPtr->apiConnect ) &&
4461  ( ( regLockTcPtr->operation == ZREAD ) ||
4462  ( regLockTcPtr->operation == ZREAD_EX ) ) &&
4463  ( regLockTcPtr->tcConnectstate == OS_PREPARED ) &&
4464  ( ! regLockTcPtr->dirtyOp ) &&
4465  ( ! regLockTcPtr->opSimple ) &&
4466  ( ! TcConnectRecord::isIndexOp(regLockTcPtr->m_special_op_flags) ) &&
4467  ( regLockTcPtr->commitAckMarker == RNIL ) );
4468 
4469  if (unlikely (! locking_op_ok ))
4470  {
4471  jam();
4472  TCKEY_abort(signal, 63);
4473  return;
4474  }
4475 
4476  /* Ok, all checks passed, release the original locking op */
4477  unlinkReadyTcCon(signal);
4478  releaseTcCon();
4479 
4480  /* Remove record of original locking op's LQHKEYREQ/CONF
4481  * etc.
4482  */
4483  ndbrequire( regApiPtr.p->lqhkeyreqrec );
4484  ndbrequire( regApiPtr.p->lqhkeyconfrec );
4485  regApiPtr.p->lqhkeyreqrec -= 1;
4486  regApiPtr.p->lqhkeyconfrec -= 1;
4487 
4488  /* Switch back to the unlock operation */
4489  tcConnectptr.i = unlockOpI;
4490  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
4491 
4492  /* Release the unlock operation */
4493  unlinkReadyTcCon(signal);
4494  releaseTcCon();
4495 
4496  /* Remove record of unlock op's LQHKEYREQ */
4497  ndbrequire( regApiPtr.p->lqhkeyreqrec );
4498  regApiPtr.p->lqhkeyreqrec -= 1;
4499 
4500  /* TCKEYCONF sent below */
4501  }
4502  else
4503  {
4504  jam();
4505  if (noFired == 0) {
4506  jam();
4507  // No triggers to execute
4508  UintR Tlqhkeyconfrec = regApiPtr.p->lqhkeyconfrec;
4509  regApiPtr.p->lqhkeyconfrec = Tlqhkeyconfrec + 1;
4510  regTcPtr->tcConnectstate = OS_PREPARED;
4511  }
4512  }//if
4513 
4517  if (regTcPtr->triggeringOperation != RNIL &&
4518  !regApiPtr.p->isExecutingDeferredTriggers()) {
4519  jam();
4520  // This operation was created by a trigger execting operation
4521  // Restart it if we have executed all it's triggers
4522  TcConnectRecordPtr opPtr;
4523 
4524  opPtr.i = regTcPtr->triggeringOperation;
4525  ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
4526  trigger_op_finished(signal, regApiPtr, opPtr.p);
4527  } else if (noFired == 0) {
4528  // This operation did not fire any triggers, finish operation
4529  jam();
4530  if (regTcPtr->isIndexOp(regTcPtr->m_special_op_flags)) {
4531  jam();
4532  setupIndexOpReturn(regApiPtr.p, regTcPtr);
4533  }
4534  lqhKeyConf_checkTransactionState(signal, regApiPtr);
4535  } else {
4536  // We have fired triggers
4537  jam();
4538  saveTriggeringOpState(signal, regTcPtr);
4539  if (regTcPtr->noReceivedTriggers == noFired)
4540  {
4541  // We have received all data
4542  jam();
4543  executeTriggers(signal, &regApiPtr);
4544  }
4545  // else wait for more trigger data
4546  }
4547 }//Dbtc::execLQHKEYCONF()
4548 
4549 void Dbtc::setupIndexOpReturn(ApiConnectRecord* regApiPtr,
4550  TcConnectRecord* regTcPtr)
4551 {
4552  regApiPtr->m_flags |= ApiConnectRecord::TF_INDEX_OP_RETURN;
4553  regApiPtr->indexOp = regTcPtr->indexOp;
4554  regApiPtr->clientData = regTcPtr->clientData;
4555  regApiPtr->attrInfoLen = regTcPtr->attrInfoLen;
4556 }
4557 
4565 void
4566 Dbtc::lqhKeyConf_checkTransactionState(Signal * signal,
4567  Ptr<ApiConnectRecord> regApiPtr)
4568 {
4569 /*---------------------------------------------------------------*/
4570 /* IF THE COMMIT FLAG IS SET IN SIGNAL TCKEYREQ THEN DBTC HAS TO */
4571 /* SEND TCKEYCONF FOR ALL OPERATIONS EXCEPT THE LAST ONE. WHEN */
4572 /* THE TRANSACTION THEN IS COMMITTED TCKEYCONF IS SENT FOR THE */
4573 /* WHOLE TRANSACTION */
4574 /* IF THE COMMIT FLAG IS NOT RECECIVED DBTC WILL SEND TCKEYCONF */
4575 /* FOR ALL OPERATIONS, AND THEN WAIT FOR THE API TO CONCLUDE THE */
4576 /* TRANSACTION */
4577 /*---------------------------------------------------------------*/
4578  ConnectionState TapiConnectstate = regApiPtr.p->apiConnectstate;
4579  UintR Tlqhkeyconfrec = regApiPtr.p->lqhkeyconfrec;
4580  UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
4581  int TnoOfOutStanding = Tlqhkeyreqrec - Tlqhkeyconfrec;
4582 
4583  apiConnectptr = regApiPtr;
4584  switch (TapiConnectstate) {
4585  case CS_START_COMMITTING:
4586  if (TnoOfOutStanding == 0) {
4587  jam();
4588  diverify010Lab(signal);
4589  return;
4590  } else if (TnoOfOutStanding > 0) {
4591  if (regApiPtr.p->tckeyrec == ZTCOPCONF_SIZE) {
4592  jam();
4593  sendtckeyconf(signal, 0);
4594  return;
4595  }
4596  else if (tc_testbit(regApiPtr.p->m_flags,
4597  ApiConnectRecord::TF_INDEX_OP_RETURN))
4598  {
4599  jam();
4600  sendtckeyconf(signal, 0);
4601  return;
4602  }//if
4603  jam();
4604  return;
4605  } else {
4606  TCKEY_abort(signal, 44);
4607  return;
4608  }//if
4609  return;
4610  case CS_STARTED:
4611  case CS_RECEIVING:
4612  if (TnoOfOutStanding == 0) {
4613  jam();
4614  sendtckeyconf(signal, 2);
4615  return;
4616  } else {
4617  if (regApiPtr.p->tckeyrec == ZTCOPCONF_SIZE) {
4618  jam();
4619  sendtckeyconf(signal, 0);
4620  return;
4621  }
4622  else if (tc_testbit(regApiPtr.p->m_flags,
4623  ApiConnectRecord::TF_INDEX_OP_RETURN))
4624  {
4625  jam();
4626  sendtckeyconf(signal, 0);
4627  return;
4628  }//if
4629  jam();
4630  }//if
4631  return;
4632  case CS_REC_COMMITTING:
4633  if (TnoOfOutStanding > 0) {
4634  if (regApiPtr.p->tckeyrec == ZTCOPCONF_SIZE) {
4635  jam();
4636  sendtckeyconf(signal, 0);
4637  return;
4638  }
4639  else if (tc_testbit(regApiPtr.p->m_flags,
4640  ApiConnectRecord::TF_INDEX_OP_RETURN))
4641  {
4642  jam();
4643  sendtckeyconf(signal, 0);
4644  return;
4645  }//if
4646  jam();
4647  return;
4648  }//if
4649  TCKEY_abort(signal, 45);
4650  return;
4651  case CS_CONNECTED:
4652  jam();
4653 /*---------------------------------------------------------------*/
4654 /* WE HAVE CONCLUDED THE TRANSACTION SINCE IT WAS ONLY */
4655 /* CONSISTING OF DIRTY WRITES AND ALL OF THOSE WERE */
4656 /* COMPLETED. ENSURE TCKEYREC IS ZERO TO PREVENT ERRORS. */
4657 /*---------------------------------------------------------------*/
4658  regApiPtr.p->tckeyrec = 0;
4659  return;
4660  case CS_SEND_FIRE_TRIG_REQ:
4661  return;
4662  case CS_WAIT_FIRE_TRIG_REQ:
4663  if (TnoOfOutStanding == 0 && regApiPtr.p->pendingTriggers == 0)
4664  {
4665  jam();
4666  regApiPtr.p->apiConnectstate = CS_START_COMMITTING;
4667  diverify010Lab(signal);
4668  return;
4669  }
4670  return;
4671  default:
4672  TCKEY_abort(signal, 46);
4673  return;
4674  }//switch
4675 }//Dbtc::lqhKeyConf_checkTransactionState()
4676 
4677 void Dbtc::sendtckeyconf(Signal* signal, UintR TcommitFlag)
4678 {
4679  if(ERROR_INSERTED(8049)){
4680  CLEAR_ERROR_INSERT_VALUE;
4681  signal->theData[0] = TcContinueB::DelayTCKEYCONF;
4682  signal->theData[1] = apiConnectptr.i;
4683  signal->theData[2] = TcommitFlag;
4684  sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 3000, 3);
4685  return;
4686  }
4687 
4688  HostRecordPtr localHostptr;
4689  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4690  const UintR TopWords = (UintR)regApiPtr->tckeyrec;
4691  localHostptr.i = refToNode(regApiPtr->ndbapiBlockref);
4692  const Uint32 type = getNodeInfo(localHostptr.i).m_type;
4693  const bool is_api = (type >= NodeInfo::API && type <= NodeInfo::MGM);
4694  const BlockNumber TblockNum = refToBlock(regApiPtr->ndbapiBlockref);
4695  const Uint32 Tmarker = (regApiPtr->commitAckMarker == RNIL) ? 0 : 1;
4696  ptrAss(localHostptr, hostRecord);
4697  UintR TcurrLen = localHostptr.p->noOfWordsTCKEYCONF;
4698  UintR confInfo = 0;
4699  TcKeyConf::setCommitFlag(confInfo, TcommitFlag == 1);
4700  TcKeyConf::setMarkerFlag(confInfo, Tmarker);
4701  const UintR TpacketLen = 6 + TopWords;
4702  regApiPtr->tckeyrec = 0;
4703 
4704  if (tc_testbit(regApiPtr->m_flags, ApiConnectRecord::TF_INDEX_OP_RETURN))
4705  {
4706  jam();
4707  // Return internally generated TCKEY
4708  TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtrSend();
4709  TcKeyConf::setNoOfOperations(confInfo, 1);
4710  tcKeyConf->apiConnectPtr = regApiPtr->indexOp;
4711  tcKeyConf->gci_hi = Uint32(regApiPtr->globalcheckpointid >> 32);
4712  Uint32* gci_lo = (Uint32*)&tcKeyConf->operations[1];
4713  * gci_lo = Uint32(regApiPtr->globalcheckpointid);
4714  tcKeyConf->confInfo = confInfo;
4715  tcKeyConf->transId1 = regApiPtr->transid[0];
4716  tcKeyConf->transId2 = regApiPtr->transid[1];
4717  tcKeyConf->operations[0].apiOperationPtr = regApiPtr->clientData;
4718  tcKeyConf->operations[0].attrInfoLen = regApiPtr->attrInfoLen;
4719  Uint32 sigLen = 1 +
4720  TcKeyConf::StaticLength + TcKeyConf::OperationLength;
4721  EXECUTE_DIRECT(DBTC, GSN_TCKEYCONF, signal, sigLen);
4722  tc_clearbit(regApiPtr->m_flags, ApiConnectRecord::TF_INDEX_OP_RETURN);
4723  if (TopWords == 0) {
4724  jam();
4725  return; // No queued TcKeyConf
4726  }//if
4727  }//if
4728  if(TcommitFlag){
4729  jam();
4730  tc_clearbit(regApiPtr->m_flags, ApiConnectRecord::TF_EXEC_FLAG);
4731  }
4732  TcKeyConf::setNoOfOperations(confInfo, (TopWords >> 1));
4733  if ((TpacketLen + 1 > 25) || !is_api){
4734  TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtrSend();
4735 
4736  jam();
4737  tcKeyConf->apiConnectPtr = regApiPtr->ndbapiConnect;
4738  tcKeyConf->gci_hi = Uint32(regApiPtr->globalcheckpointid >> 32);
4739  Uint32* gci_lo = (Uint32*)&tcKeyConf->operations[TopWords >> 1];
4740  tcKeyConf->confInfo = confInfo;
4741  tcKeyConf->transId1 = regApiPtr->transid[0];
4742  tcKeyConf->transId2 = regApiPtr->transid[1];
4743  copyFromToLen(&regApiPtr->tcSendArray[0],
4744  (UintR*)&tcKeyConf->operations,
4745  (UintR)ZTCOPCONF_SIZE);
4746  * gci_lo = Uint32(regApiPtr->globalcheckpointid);
4747  sendSignal(regApiPtr->ndbapiBlockref,
4748  GSN_TCKEYCONF, signal, (TpacketLen - 1) + 1 , JBB);
4749  return;
4750  } else if (((TcurrLen + TpacketLen + 1 ) > 25) &&
4751  (TcurrLen > 0)) {
4752  jam();
4753  sendPackedTCKEYCONF(signal, localHostptr.p, localHostptr.i);
4754  TcurrLen = 0;
4755  } else {
4756  jam();
4757  updatePackedList(signal, localHostptr.p, localHostptr.i);
4758  }//if
4759  // -------------------------------------------------------------------------
4760  // The header contains the block reference of receiver plus the real signal
4761  // length - 3, since we have the real signal length plus one additional word
4762  // for the header we have to do - 4.
4763  // -------------------------------------------------------------------------
4764  UintR Tpack0 = (TblockNum << 16) + (TpacketLen - 4 + 1 );
4765  UintR Tpack1 = regApiPtr->ndbapiConnect;
4766  UintR Tpack2 = Uint32(regApiPtr->globalcheckpointid >> 32);
4767  UintR Tpack3 = confInfo;
4768  UintR Tpack4 = regApiPtr->transid[0];
4769  UintR Tpack5 = regApiPtr->transid[1];
4770  UintR Tpack6 = Uint32(regApiPtr->globalcheckpointid);
4771 
4772  localHostptr.p->noOfWordsTCKEYCONF = TcurrLen + TpacketLen + 1 ;
4773 
4774  localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 0] = Tpack0;
4775  localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 1] = Tpack1;
4776  localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 2] = Tpack2;
4777  localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 3] = Tpack3;
4778  localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 4] = Tpack4;
4779  localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 5] = Tpack5;
4780 
4781  UintR Ti;
4782  for (Ti = 6; Ti < TpacketLen; Ti++) {
4783  localHostptr.p->packedWordsTCKEYCONF[TcurrLen + Ti] =
4784  regApiPtr->tcSendArray[Ti - 6];
4785  }//for
4786  localHostptr.p->packedWordsTCKEYCONF[TcurrLen + TpacketLen] = Tpack6;
4787 
4788  if (unlikely(!ndb_check_micro_gcp(getNodeInfo(localHostptr.i).m_version)))
4789  {
4790  jam();
4791  ndbassert(Tpack6 == 0 ||
4792  getNodeInfo(localHostptr.i).m_version == 0); // Disconnected
4793  }
4794 }//Dbtc::sendtckeyconf()
4795 
4796 void Dbtc::copyFromToLen(UintR* sourceBuffer, UintR* destBuffer, UintR Tlen)
4797 {
4798  UintR Tindex = 0;
4799  UintR Ti;
4800  while (Tlen >= 4) {
4801  UintR Tdata0 = sourceBuffer[Tindex + 0];
4802  UintR Tdata1 = sourceBuffer[Tindex + 1];
4803  UintR Tdata2 = sourceBuffer[Tindex + 2];
4804  UintR Tdata3 = sourceBuffer[Tindex + 3];
4805  Tlen -= 4;
4806  destBuffer[Tindex + 0] = Tdata0;
4807  destBuffer[Tindex + 1] = Tdata1;
4808  destBuffer[Tindex + 2] = Tdata2;
4809  destBuffer[Tindex + 3] = Tdata3;
4810  Tindex += 4;
4811  }//while
4812  for (Ti = 0; Ti < Tlen; Ti++, Tindex++) {
4813  destBuffer[Tindex] = sourceBuffer[Tindex];
4814  }//for
4815 }//Dbtc::copyFromToLen()
4816 
4817 void Dbtc::execSEND_PACKED(Signal* signal)
4818 {
4819  HostRecordPtr Thostptr;
4820  HostRecord *localHostRecord = hostRecord;
4821  UintR i;
4822  UintR TpackedListIndex = cpackedListIndex;
4823  jamEntry();
4824  for (i = 0; i < TpackedListIndex; i++) {
4825  Thostptr.i = cpackedList[i];
4826  ptrAss(Thostptr, localHostRecord);
4827  arrGuard(Thostptr.i - 1, MAX_NODES - 1);
4828  UintR TnoOfPackedWordsLqh = Thostptr.p->noOfPackedWordsLqh;
4829  UintR TnoOfWordsTCKEYCONF = Thostptr.p->noOfWordsTCKEYCONF;
4830  jam();
4831  if (TnoOfPackedWordsLqh > 0) {
4832  jam();
4833  sendPackedSignalLqh(signal, Thostptr.p);
4834  }//if
4835  if (TnoOfWordsTCKEYCONF > 0) {
4836  jam();
4837  sendPackedTCKEYCONF(signal, Thostptr.p, (Uint32)Thostptr.i);
4838  }//if
4839  Thostptr.p->inPackedList = false;
4840  }//for
4841  cpackedListIndex = 0;
4842  return;
4843 }//Dbtc::execSEND_PACKED()
4844 
4845 void
4846 Dbtc::updatePackedList(Signal* signal, HostRecord* ahostptr, Uint16 ahostIndex)
4847 {
4848  if (ahostptr->inPackedList == false) {
4849  UintR TpackedListIndex = cpackedListIndex;
4850  jam();
4851  ahostptr->inPackedList = true;
4852  cpackedList[TpackedListIndex] = ahostIndex;
4853  cpackedListIndex = TpackedListIndex + 1;
4854  }//if
4855 }//Dbtc::updatePackedList()
4856 
4857 void Dbtc::sendPackedSignalLqh(Signal* signal, HostRecord * ahostptr)
4858 {
4859  UintR Tj;
4860  UintR TnoOfWords = ahostptr->noOfPackedWordsLqh;
4861  for (Tj = 0; Tj < TnoOfWords; Tj += 4) {
4862  UintR sig0 = ahostptr->packedWordsLqh[Tj + 0];
4863  UintR sig1 = ahostptr->packedWordsLqh[Tj + 1];
4864  UintR sig2 = ahostptr->packedWordsLqh[Tj + 2];
4865  UintR sig3 = ahostptr->packedWordsLqh[Tj + 3];
4866  signal->theData[Tj + 0] = sig0;
4867  signal->theData[Tj + 1] = sig1;
4868  signal->theData[Tj + 2] = sig2;
4869  signal->theData[Tj + 3] = sig3;
4870  }//for
4871  ahostptr->noOfPackedWordsLqh = 0;
4872  sendSignal(ahostptr->hostLqhBlockRef,
4873  GSN_PACKED_SIGNAL,
4874  signal,
4875  TnoOfWords,
4876  JBB);
4877 }//Dbtc::sendPackedSignalLqh()
4878 
4879 void Dbtc::sendPackedTCKEYCONF(Signal* signal,
4880  HostRecord * ahostptr,
4881  UintR hostId)
4882 {
4883  UintR Tj;
4884  UintR TnoOfWords = ahostptr->noOfWordsTCKEYCONF;
4885  BlockReference TBref = numberToRef(API_PACKED, hostId);
4886  for (Tj = 0; Tj < ahostptr->noOfWordsTCKEYCONF; Tj += 4) {
4887  UintR sig0 = ahostptr->packedWordsTCKEYCONF[Tj + 0];
4888  UintR sig1 = ahostptr->packedWordsTCKEYCONF[Tj + 1];
4889  UintR sig2 = ahostptr->packedWordsTCKEYCONF[Tj + 2];
4890  UintR sig3 = ahostptr->packedWordsTCKEYCONF[Tj + 3];
4891  signal->theData[Tj + 0] = sig0;
4892  signal->theData[Tj + 1] = sig1;
4893  signal->theData[Tj + 2] = sig2;
4894  signal->theData[Tj + 3] = sig3;
4895  }//for
4896  ahostptr->noOfWordsTCKEYCONF = 0;
4897  sendSignal(TBref, GSN_TCKEYCONF, signal, TnoOfWords, JBB);
4898 }//Dbtc::sendPackedTCKEYCONF()
4899 
4900 /*
4901 4.3.11 DIVERIFY
4902 ---------------
4903 */
4904 /*****************************************************************************/
4905 /* D I V E R I F Y */
4906 /* */
4907 /*****************************************************************************/
4908 void Dbtc::diverify010Lab(Signal* signal)
4909 {
4910  UintR TfirstfreeApiConnectCopy = cfirstfreeApiConnectCopy;
4911  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4912  signal->theData[0] = apiConnectptr.i;
4913  signal->theData[1] = instance() ? instance() - 1 : 0;
4914  if (ERROR_INSERTED(8022)) {
4915  jam();
4916  systemErrorLab(signal, __LINE__);
4917  }//if
4918 
4919  if (tc_testbit(regApiPtr->m_flags, ApiConnectRecord::TF_DEFERRED_TRIGGERS))
4920  {
4921  jam();
4926  regApiPtr->pendingTriggers = 0;
4927  tc_clearbit(regApiPtr->m_flags, ApiConnectRecord::TF_DEFERRED_TRIGGERS);
4928  sendFireTrigReq(signal, apiConnectptr, regApiPtr->firstTcConnect);
4929  return;
4930  }
4931 
4932  if (regApiPtr->lqhkeyreqrec)
4933  {
4934  if (TfirstfreeApiConnectCopy != RNIL) {
4935  seizeApiConnectCopy(signal);
4936  regApiPtr->apiConnectstate = CS_PREPARE_TO_COMMIT;
4937  /*-----------------------------------------------------------------------
4938  * WE COME HERE ONLY IF THE TRANSACTION IS PREPARED ON ALL TC CONNECTIONS
4939  * THUS WE CAN START THE COMMIT PHASE BY SENDING DIVERIFY ON ALL TC
4940  * CONNECTIONS AND THEN WHEN ALL DIVERIFYCONF HAVE BEEN RECEIVED THE
4941  * COMMIT MESSAGE CAN BE SENT TO ALL INVOLVED PARTS.
4942  *---------------------------------------------------------------------*/
4943  * (EmulatedJamBuffer**)(signal->theData+2) = jamBuffer();
4944  EXECUTE_DIRECT(DBDIH, GSN_DIVERIFYREQ, signal,
4945  2 + sizeof(void*)/sizeof(Uint32), 0);
4946  if (signal->theData[3] == 0) {
4947  execDIVERIFYCONF(signal);
4948  }
4949  return;
4950  } else {
4951  /*-----------------------------------------------------------------------
4952  * There were no free copy connections available. We must abort the
4953  * transaction since otherwise we will have a problem with the report
4954  * to the application.
4955  * This should more or less not happen but if it happens we do
4956  * not want to crash and we do not want to create code to handle it
4957  * properly since it is difficult to test it and will be complex to
4958  * handle a problem more or less not occurring.
4959  *---------------------------------------------------------------------*/
4960  terrorCode = ZSEIZE_API_COPY_ERROR;
4961  abortErrorLab(signal);
4962  return;
4963  }
4964  }
4965  else
4966  {
4967  jam();
4968  sendtckeyconf(signal, 1);
4969  regApiPtr->apiConnectstate = CS_CONNECTED;
4970  regApiPtr->m_transaction_nodes.clear();
4971  setApiConTimer(apiConnectptr.i, 0,__LINE__);
4972  }
4973 }//Dbtc::diverify010Lab()
4974 
4975 /* ------------------------------------------------------------------------- */
4976 /* ------- SEIZE_API_CONNECT ------- */
4977 /* SEIZE CONNECT RECORD FOR A REQUEST */
4978 /* ------------------------------------------------------------------------- */
4979 void Dbtc::seizeApiConnectCopy(Signal* signal)
4980 {
4981  ApiConnectRecordPtr locApiConnectptr;
4982 
4983  ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
4984  UintR TapiConnectFilesize = capiConnectFilesize;
4985  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4986 
4987  locApiConnectptr.i = cfirstfreeApiConnectCopy;
4988  ptrCheckGuard(locApiConnectptr, TapiConnectFilesize, localApiConnectRecord);
4989  cfirstfreeApiConnectCopy = locApiConnectptr.p->nextApiConnect;
4990  locApiConnectptr.p->nextApiConnect = RNIL;
4991  regApiPtr->apiCopyRecord = locApiConnectptr.i;
4992  tc_clearbit(regApiPtr->m_flags,
4993  ApiConnectRecord::TF_TRIGGER_PENDING);
4994  regApiPtr->m_special_op_flags = 0;
4995 }//Dbtc::seizeApiConnectCopy()
4996 
4997 void Dbtc::execDIVERIFYCONF(Signal* signal)
4998 {
4999  UintR TapiConnectptrIndex = signal->theData[0];
5000  UintR TapiConnectFilesize = capiConnectFilesize;
5001  UintR Tgci_hi = signal->theData[1];
5002  UintR Tgci_lo = signal->theData[2];
5003  Uint64 Tgci = Tgci_lo | (Uint64(Tgci_hi) << 32);
5004  ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5005 
5006  jamEntry();
5007  if (ERROR_INSERTED(8017)) {
5008  CLEAR_ERROR_INSERT_VALUE;
5009  return;
5010  }//if
5011  if (TapiConnectptrIndex >= TapiConnectFilesize) {
5012  TCKEY_abort(signal, 31);
5013  return;
5014  }//if
5015  ApiConnectRecord * const regApiPtr =
5016  &localApiConnectRecord[TapiConnectptrIndex];
5017  ConnectionState TapiConnectstate = regApiPtr->apiConnectstate;
5018  UintR TApifailureNr = regApiPtr->failureNr;
5019  UintR Tfailure_nr = cfailure_nr;
5020  apiConnectptr.i = TapiConnectptrIndex;
5021  apiConnectptr.p = regApiPtr;
5022  if (TapiConnectstate != CS_PREPARE_TO_COMMIT) {
5023  TCKEY_abort(signal, 32);
5024  return;
5025  }//if
5026  /*--------------------------------------------------------------------------
5027  * THIS IS THE COMMIT POINT. IF WE ARRIVE HERE THE TRANSACTION IS COMMITTED
5028  * UNLESS EVERYTHING CRASHES BEFORE WE HAVE BEEN ABLE TO REPORT THE COMMIT
5029  * DECISION. THERE IS NO TURNING BACK FROM THIS DECISION FROM HERE ON.
5030  * WE WILL INSERT THE TRANSACTION INTO ITS PROPER QUEUE OF
5031  * TRANSACTIONS FOR ITS GLOBAL CHECKPOINT.
5032  *-------------------------------------------------------------------------*/
5033  if (TApifailureNr != Tfailure_nr) {
5034  DIVER_node_fail_handling(signal, Tgci);
5035  return;
5036  }//if
5037  commitGciHandling(signal, Tgci);
5038 
5039  /**************************************************************************
5040  * C O M M I T
5041  * THE TRANSACTION HAVE NOW BEEN VERIFIED AND NOW THE COMMIT PHASE CAN START
5042  **************************************************************************/
5043 
5044  UintR TtcConnectptrIndex = regApiPtr->firstTcConnect;
5045  UintR TtcConnectFilesize = ctcConnectFilesize;
5046  TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5047 
5048  regApiPtr->counter = regApiPtr->lqhkeyconfrec;
5049  regApiPtr->apiConnectstate = CS_COMMITTING;
5050  if (TtcConnectptrIndex >= TtcConnectFilesize) {
5051  TCKEY_abort(signal, 33);
5052  return;
5053  }//if
5054  TcConnectRecord* const regTcPtr = &localTcConnectRecord[TtcConnectptrIndex];
5055  tcConnectptr.i = TtcConnectptrIndex;
5056  tcConnectptr.p = regTcPtr;
5057  commit020Lab(signal);
5058 }//Dbtc::execDIVERIFYCONF()
5059 
5060 /*--------------------------------------------------------------------------*/
5061 /* COMMIT_GCI_HANDLING */
5062 /* SET UP GLOBAL CHECKPOINT DATA STRUCTURE AT THE COMMIT POINT. */
5063 /*--------------------------------------------------------------------------*/
5064 void Dbtc::commitGciHandling(Signal* signal, Uint64 Tgci)
5065 {
5066  GcpRecordPtr localGcpPointer;
5067 
5068  UintR TgcpFilesize = cgcpFilesize;
5069  UintR Tfirstgcp = cfirstgcp;
5070  Ptr<ApiConnectRecord> regApiPtr = apiConnectptr;
5071  GcpRecord *localGcpRecord = gcpRecord;
5072 
5073  regApiPtr.p->globalcheckpointid = Tgci;
5074  if (Tfirstgcp != RNIL) {
5075  /* IF THIS GLOBAL CHECKPOINT ALREADY EXISTS */
5076  localGcpPointer.i = Tfirstgcp;
5077  ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord);
5078  do {
5079  if (regApiPtr.p->globalcheckpointid == localGcpPointer.p->gcpId) {
5080  jam();
5081  linkApiToGcp(localGcpPointer, regApiPtr);
5082  return;
5083  } else {
5084  if (unlikely(! (regApiPtr.p->globalcheckpointid > localGcpPointer.p->gcpId)))
5085  {
5086  ndbout_c("%u/%u %u/%u",
5087  Uint32(regApiPtr.p->globalcheckpointid >> 32),
5088  Uint32(regApiPtr.p->globalcheckpointid),
5089  Uint32(localGcpPointer.p->gcpId >> 32),
5090  Uint32(localGcpPointer.p->gcpId));
5091  crash_gcp(__LINE__);
5092  }
5093  localGcpPointer.i = localGcpPointer.p->nextGcp;
5094  jam();
5095  if (localGcpPointer.i != RNIL) {
5096  jam();
5097  ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord);
5098  continue;
5099  }//if
5100  }//if
5101  seizeGcp(localGcpPointer, Tgci);
5102  linkApiToGcp(localGcpPointer, regApiPtr);
5103  return;
5104  } while (1);
5105  } else {
5106  jam();
5107  seizeGcp(localGcpPointer, Tgci);
5108  linkApiToGcp(localGcpPointer, regApiPtr);
5109  }//if
5110 }//Dbtc::commitGciHandling()
5111 
5112 /* --------------------------------------------------------------------------*/
5113 /* -LINK AN API CONNECT RECORD IN STATE PREPARED INTO THE LIST WITH GLOBAL - */
5114 /* CHECKPOINTS. WHEN THE TRANSACTION I COMPLETED THE API CONNECT RECORD IS */
5115 /* LINKED OUT OF THE LIST. */
5116 /*---------------------------------------------------------------------------*/
5117 void Dbtc::linkApiToGcp(Ptr<GcpRecord> regGcpPtr,
5118  Ptr<ApiConnectRecord> regApiPtr)
5119 {
5120  ApiConnectRecordPtr localApiConnectptr;
5121  ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5122 
5123  regApiPtr.p->nextGcpConnect = RNIL;
5124  if (regGcpPtr.p->firstApiConnect == RNIL) {
5125  regGcpPtr.p->firstApiConnect = regApiPtr.i;
5126  jam();
5127  } else {
5128  UintR TapiConnectFilesize = capiConnectFilesize;
5129  localApiConnectptr.i = regGcpPtr.p->lastApiConnect;
5130  jam();
5131  ptrCheckGuard(localApiConnectptr,
5132  TapiConnectFilesize, localApiConnectRecord);
5133  localApiConnectptr.p->nextGcpConnect = regApiPtr.i;
5134  }//if
5135  UintR TlastApiConnect = regGcpPtr.p->lastApiConnect;
5136  regApiPtr.p->gcpPointer = regGcpPtr.i;
5137  regApiPtr.p->prevGcpConnect = TlastApiConnect;
5138  regGcpPtr.p->lastApiConnect = regApiPtr.i;
5139 }//Dbtc::linkApiToGcp()
5140 
5141 void
5142 Dbtc::crash_gcp(Uint32 line)
5143 {
5144  GcpRecordPtr localGcpPointer;
5145 
5146  localGcpPointer.i = cfirstgcp;
5147 
5148  while (localGcpPointer.i != RNIL)
5149  {
5150  ptrCheckGuard(localGcpPointer, cgcpFilesize, gcpRecord);
5151  ndbout_c("%u : %u/%u nomoretrans: %u api %u %u next: %u",
5152  localGcpPointer.i,
5153  Uint32(localGcpPointer.p->gcpId >> 32),
5154  Uint32(localGcpPointer.p->gcpId),
5155  localGcpPointer.p->gcpNomoretransRec,
5156  localGcpPointer.p->firstApiConnect,
5157  localGcpPointer.p->lastApiConnect,
5158  localGcpPointer.p->nextGcp);
5159  localGcpPointer.i = localGcpPointer.p->nextGcp;
5160  }
5161  progError(line, NDBD_EXIT_NDBREQUIRE);
5162  ndbrequire(false);
5163 }
5164 
5165 void Dbtc::seizeGcp(Ptr<GcpRecord> & dst, Uint64 Tgci)
5166 {
5167  GcpRecordPtr tmpGcpPointer;
5168  GcpRecordPtr localGcpPointer;
5169 
5170  UintR Tfirstgcp = cfirstgcp;
5171  UintR TgcpFilesize = cgcpFilesize;
5172  GcpRecord *localGcpRecord = gcpRecord;
5173 
5174  localGcpPointer.i = cfirstfreeGcp;
5175  if (unlikely(localGcpPointer.i > TgcpFilesize))
5176  {
5177  ndbout_c("%u/%u", Uint32(Tgci >> 32), Uint32(Tgci));
5178  crash_gcp(__LINE__);
5179  }
5180  ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord);
5181  UintR TfirstfreeGcp = localGcpPointer.p->nextGcp;
5182  localGcpPointer.p->gcpId = Tgci;
5183  localGcpPointer.p->nextGcp = RNIL;
5184  localGcpPointer.p->firstApiConnect = RNIL;
5185  localGcpPointer.p->lastApiConnect = RNIL;
5186  localGcpPointer.p->gcpNomoretransRec = ZFALSE;
5187  cfirstfreeGcp = TfirstfreeGcp;
5188 
5189  if (Tfirstgcp == RNIL) {
5190  jam();
5191  cfirstgcp = localGcpPointer.i;
5192  } else {
5193  tmpGcpPointer.i = clastgcp;
5194  jam();
5195  ptrCheckGuard(tmpGcpPointer, TgcpFilesize, localGcpRecord);
5196  tmpGcpPointer.p->nextGcp = localGcpPointer.i;
5197  }//if
5198  clastgcp = localGcpPointer.i;
5199  dst = localGcpPointer;
5200 }//Dbtc::seizeGcp()
5201 
5202 /*---------------------------------------------------------------------------*/
5203 // Send COMMIT messages to all LQH operations involved in the transaction.
5204 /*---------------------------------------------------------------------------*/
5205 void Dbtc::commit020Lab(Signal* signal)
5206 {
5207  TcConnectRecordPtr localTcConnectptr;
5208  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5209  UintR TtcConnectFilesize = ctcConnectFilesize;
5210  TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5211 
5212  localTcConnectptr.p = tcConnectptr.p;
5213  setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
5214  UintR Tcount = 0;
5215  do {
5216  /*-----------------------------------------------------------------------
5217  * WE ARE NOW READY TO RELEASE ALL OPERATIONS ON THE LQH
5218  *-----------------------------------------------------------------------*/
5219  /* *********< */
5220  /* COMMIT < */
5221  /* *********< */
5222  localTcConnectptr.i = localTcConnectptr.p->nextTcConnect;
5223  localTcConnectptr.p->tcConnectstate = OS_COMMITTING;
5224  Tcount += sendCommitLqh(signal, localTcConnectptr.p);
5225 
5226  if (localTcConnectptr.i != RNIL) {
5227  if (Tcount < 16 &&
5228  ! (ERROR_INSERTED(8057) ||
5229  ERROR_INSERTED(8073) ||
5230  ERROR_INSERTED(8089)))
5231  {
5232  ptrCheckGuard(localTcConnectptr,
5233  TtcConnectFilesize, localTcConnectRecord);
5234  jam();
5235  continue;
5236  } else {
5237  jam();
5238  if (ERROR_INSERTED(8014)) {
5239  CLEAR_ERROR_INSERT_VALUE;
5240  return;
5241  }//if
5242 
5243  if (ERROR_INSERTED(8073))
5244  {
5245  execSEND_PACKED(signal);
5246  signal->theData[0] = 9999;
5247  sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 100, 1);
5248  return;
5249  }
5250  signal->theData[0] = TcContinueB::ZSEND_COMMIT_LOOP;
5251  signal->theData[1] = apiConnectptr.i;
5252  signal->theData[2] = localTcConnectptr.i;
5253  if (ERROR_INSERTED(8089))
5254  {
5255  sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 100, 3);
5256  return;
5257  }
5258  sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
5259  return;
5260  }//if
5261  } else {
5262  jam();
5263  if (ERROR_INSERTED(8057))
5264  CLEAR_ERROR_INSERT_VALUE;
5265 
5266  if (ERROR_INSERTED(8089))
5267  CLEAR_ERROR_INSERT_VALUE;
5268 
5269  regApiPtr->apiConnectstate = CS_COMMIT_SENT;
5270  return;
5271  }//if
5272  } while (1);
5273 }//Dbtc::commit020Lab()
5274 
5275 Uint32
5276 Dbtc::sendCommitLqh(Signal* signal,
5277  TcConnectRecord * const regTcPtr)
5278 {
5279  HostRecordPtr Thostptr;
5280  UintR ThostFilesize = chostFilesize;
5281  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5282  Thostptr.i = regTcPtr->lastLqhNodeId;
5283  ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
5284 
5285  Uint32 Tnode = Thostptr.i;
5286  Uint32 self = getOwnNodeId();
5287  Uint32 ret = (Tnode == self) ? 4 : 1;
5288 
5289  Uint32 Tdata[5];
5290  Tdata[0] = regTcPtr->lastLqhCon;
5291  Tdata[1] = Uint32(regApiPtr->globalcheckpointid >> 32);
5292  Tdata[2] = regApiPtr->transid[0];
5293  Tdata[3] = regApiPtr->transid[1];
5294  Tdata[4] = Uint32(regApiPtr->globalcheckpointid);
5295  Uint32 len = 5;
5296 
5297  if (unlikely(!ndb_check_micro_gcp(getNodeInfo(Thostptr.i).m_version)))
5298  {
5299  jam();
5300  ndbassert(Tdata[4] == 0 || getNodeInfo(Thostptr.i).m_version == 0);
5301  len = 4;
5302  }
5303 
5304  // currently packed signal cannot address specific instance
5305  const bool send_unpacked = getNodeInfo(Thostptr.i).m_lqh_workers > 1;
5306  if (send_unpacked) {
5307  memcpy(&signal->theData[0], &Tdata[0], len << 2);
5308  Uint32 instanceKey = regTcPtr->lqhInstanceKey;
5309  BlockReference lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
5310  sendSignal(lqhRef, GSN_COMMIT, signal, len, JBB);
5311  return ret;
5312  }
5313 
5314  if (Thostptr.p->noOfPackedWordsLqh > 25 - 5) {
5315  jam();
5316  sendPackedSignalLqh(signal, Thostptr.p);
5317  } else {
5318  jam();
5319  ret = 1;
5320  updatePackedList(signal, Thostptr.p, Thostptr.i);
5321  }
5322 
5323  Tdata[0] |= (ZCOMMIT << 28);
5324  UintR Tindex = Thostptr.p->noOfPackedWordsLqh;
5325  UintR* TDataPtr = &Thostptr.p->packedWordsLqh[Tindex];
5326  memcpy(TDataPtr, &Tdata[0], len << 2);
5327  Thostptr.p->noOfPackedWordsLqh = Tindex + len;
5328  return ret;
5329 }
5330 
5331 void
5332 Dbtc::DIVER_node_fail_handling(Signal* signal, Uint64 Tgci)
5333 {
5334  /*------------------------------------------------------------------------
5335  * AT LEAST ONE NODE HAS FAILED DURING THE TRANSACTION. WE NEED TO CHECK IF
5336  * THIS IS SO SERIOUS THAT WE NEED TO ABORT THE TRANSACTION. IN BOTH THE
5337  * ABORT AND THE COMMIT CASES WE NEED TO SET-UP THE DATA FOR THE
5338  * ABORT/COMMIT/COMPLETE HANDLING AS ALSO USED BY TAKE OVER FUNCTIONALITY.
5339  *------------------------------------------------------------------------*/
5340  tabortInd = ZFALSE;
5341  setupFailData(signal);
5342  if (false && tabortInd == ZFALSE) {
5343  jam();
5344  commitGciHandling(signal, Tgci);
5345  toCommitHandlingLab(signal);
5346  } else {
5347  jam();
5348  apiConnectptr.p->returnsignal = RS_TCROLLBACKREP;
5349  apiConnectptr.p->returncode = ZNODEFAIL_BEFORE_COMMIT;
5350  toAbortHandlingLab(signal);
5351  }//if
5352  return;
5353 }//Dbtc::DIVER_node_fail_handling()
5354 
5355 
5356 /* ------------------------------------------------------------------------- */
5357 /* ------- ENTER COMMITTED ------- */
5358 /* */
5359 /* ------------------------------------------------------------------------- */
5360 void Dbtc::execCOMMITTED(Signal* signal)
5361 {
5362  TcConnectRecordPtr localTcConnectptr;
5363  ApiConnectRecordPtr localApiConnectptr;
5364  ApiConnectRecordPtr localCopyPtr;
5365 
5366  UintR TtcConnectFilesize = ctcConnectFilesize;
5367  UintR TapiConnectFilesize = capiConnectFilesize;
5368  TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5369  ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5370 
5371 #ifdef ERROR_INSERT
5372  if (ERROR_INSERTED(8018)) {
5373  CLEAR_ERROR_INSERT_VALUE;
5374  return;
5375  }//if
5376  CRASH_INSERTION(8030);
5377  if (ERROR_INSERTED(8025)) {
5378  SET_ERROR_INSERT_VALUE(8026);
5379  return;
5380  }//if
5381  if (ERROR_INSERTED(8041)) {
5382  CLEAR_ERROR_INSERT_VALUE;
5383  sendSignalWithDelay(cownref, GSN_COMMITTED, signal, 2000, 3);
5384  return;
5385  }//if
5386  if (ERROR_INSERTED(8042)) {
5387  SET_ERROR_INSERT_VALUE(8046);
5388  sendSignalWithDelay(cownref, GSN_COMMITTED, signal, 2000, 4);
5389  return;
5390  }//if
5391 #endif
5392  localTcConnectptr.i = signal->theData[0];
5393  jamEntry();
5394  ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
5395  localApiConnectptr.i = localTcConnectptr.p->apiConnect;
5396  if (localTcConnectptr.p->tcConnectstate != OS_COMMITTING) {
5397  warningReport(signal, 4);
5398  return;
5399  }//if
5400  ptrCheckGuard(localApiConnectptr, TapiConnectFilesize,
5401  localApiConnectRecord);
5402  UintR Tcounter = localApiConnectptr.p->counter - 1;
5403  ConnectionState TapiConnectstate = localApiConnectptr.p->apiConnectstate;
5404  UintR Tdata1 = localApiConnectptr.p->transid[0] - signal->theData[1];
5405  UintR Tdata2 = localApiConnectptr.p->transid[1] - signal->theData[2];
5406  Tdata1 = Tdata1 | Tdata2;
5407  bool TcheckCondition =
5408  (TapiConnectstate != CS_COMMIT_SENT) || (Tcounter != 0);
5409 
5410  setApiConTimer(localApiConnectptr.i, ctcTimer, __LINE__);
5411  localApiConnectptr.p->counter = Tcounter;
5412  localTcConnectptr.p->tcConnectstate = OS_COMMITTED;
5413  if (Tdata1 != 0) {
5414  warningReport(signal, 5);
5415  return;
5416  }//if
5417  if (TcheckCondition) {
5418  jam();
5419  /*-------------------------------------------------------*/
5420  // We have not sent all COMMIT requests yet. We could be
5421  // in the state that all sent are COMMITTED but we are
5422  // still waiting for a CONTINUEB to send the rest of the
5423  // COMMIT requests.
5424  /*-------------------------------------------------------*/
5425  return;
5426  }//if
5427  if (ERROR_INSERTED(8020)) {
5428  jam();
5429  systemErrorLab(signal, __LINE__);
5430  }//if
5431  /*-------------------------------------------------------*/
5432  /* THE ENTIRE TRANSACTION IS NOW COMMITED */
5433  /* NOW WE NEED TO SEND THE RESPONSE TO THE APPLICATION. */
5434  /* THE APPLICATION CAN THEN REUSE THE API CONNECTION AND */
5435  /* THEREFORE WE NEED TO MOVE THE API CONNECTION TO A */
5436  /* NEW API CONNECT RECORD. */
5437  /*-------------------------------------------------------*/
5438 
5439  apiConnectptr = localApiConnectptr;
5440  localCopyPtr = sendApiCommit(signal);
5441 
5442  localTcConnectptr.i = localCopyPtr.p->firstTcConnect;
5443  UintR Tlqhkeyconfrec = localCopyPtr.p->lqhkeyconfrec;
5444  ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
5445  localCopyPtr.p->counter = Tlqhkeyconfrec;
5446 
5447  apiConnectptr = localCopyPtr;
5448  tcConnectptr = localTcConnectptr;
5449  complete010Lab(signal);
5450  return;
5451 
5452 }//Dbtc::execCOMMITTED()
5453 
5454 /*-------------------------------------------------------*/
5455 /* SEND_API_COMMIT */
5456 /* SEND COMMIT DECISION TO THE API. */
5457 /*-------------------------------------------------------*/
5459 Dbtc::sendApiCommit(Signal* signal)
5460 {
5461  ApiConnectRecordPtr regApiPtr = apiConnectptr;
5462 
5463  if (ERROR_INSERTED(8055))
5464  {
5470  signal->theData[0] = 9999;
5471  sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 1000, 1);
5472  Uint32 node = refToNode(regApiPtr.p->ndbapiBlockref);
5473  signal->theData[0] = node;
5474  sendSignal(QMGR_REF, GSN_API_FAILREQ, signal, 1, JBB);
5475 
5476  SET_ERROR_INSERT_VALUE(8056);
5477 
5478  goto err8055;
5479  }
5480 
5481  if (regApiPtr.p->returnsignal == RS_TCKEYCONF)
5482  {
5483  if (ERROR_INSERTED(8054))
5484  {
5485  CLEAR_ERROR_INSERT_VALUE;
5486  signal->theData[0] = 9999;
5487  sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 5000, 1);
5488  }
5489  else
5490  {
5491  sendtckeyconf(signal, 1);
5492  }
5493  }
5494  else if (regApiPtr.p->returnsignal == RS_TC_COMMITCONF)
5495  {
5496  jam();
5497  TcCommitConf * const commitConf = (TcCommitConf *)&signal->theData[0];
5498  if(regApiPtr.p->commitAckMarker == RNIL)
5499  {
5500  jam();
5501  commitConf->apiConnectPtr = regApiPtr.p->ndbapiConnect;
5502  }
5503  else
5504  {
5505  jam();
5506  commitConf->apiConnectPtr = regApiPtr.p->ndbapiConnect | 1;
5507  }
5508  commitConf->transId1 = regApiPtr.p->transid[0];
5509  commitConf->transId2 = regApiPtr.p->transid[1];
5510  commitConf->gci_hi = Uint32(regApiPtr.p->globalcheckpointid >> 32);
5511  commitConf->gci_lo = Uint32(regApiPtr.p->globalcheckpointid);
5512 
5513  sendSignal(regApiPtr.p->ndbapiBlockref, GSN_TC_COMMITCONF, signal,
5514  TcCommitConf::SignalLength, JBB);
5515  }
5516  else if (regApiPtr.p->returnsignal == RS_NO_RETURN)
5517  {
5518  jam();
5519  }
5520  else
5521  {
5522  TCKEY_abort(signal, 37);
5523  return regApiPtr;
5524  }//if
5525 
5526 err8055:
5527  Ptr<ApiConnectRecord> copyPtr;
5528  UintR TapiConnectFilesize = capiConnectFilesize;
5529  copyPtr.i = regApiPtr.p->apiCopyRecord;
5530  UintR TapiFailState = regApiPtr.p->apiFailState;
5531  ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5532 
5533  c_counters.ccommitCount++;
5534  ptrCheckGuard(copyPtr, TapiConnectFilesize, localApiConnectRecord);
5535  copyApi(copyPtr, regApiPtr);
5536  if (TapiFailState != ZTRUE) {
5537  return copyPtr;
5538  } else {
5539  jam();
5540  handleApiFailState(signal, regApiPtr.i);
5541  return copyPtr;
5542  }//if
5543 }//Dbtc::sendApiCommit()
5544 
5545 /* ========================================================================= */
5546 /* ======= COPY_API ======= */
5547 /* COPY API RECORD ALSO RESET THE OLD API RECORD SO THAT IT */
5548 /* IS PREPARED TO RECEIVE A NEW TRANSACTION. */
5549 /*===========================================================================*/
5550 void Dbtc::copyApi(ApiConnectRecordPtr copyPtr, ApiConnectRecordPtr regApiPtr)
5551 {
5552  UintR TndbapiConnect = regApiPtr.p->ndbapiConnect;
5553  UintR TfirstTcConnect = regApiPtr.p->firstTcConnect;
5554  UintR Ttransid1 = regApiPtr.p->transid[0];
5555  UintR Ttransid2 = regApiPtr.p->transid[1];
5556  UintR Tlqhkeyconfrec = regApiPtr.p->lqhkeyconfrec;
5557  UintR TgcpPointer = regApiPtr.p->gcpPointer;
5558  UintR TgcpFilesize = cgcpFilesize;
5559  NdbNodeBitmask Tnodes = regApiPtr.p->m_transaction_nodes;
5560  GcpRecord *localGcpRecord = gcpRecord;
5561 
5562  copyPtr.p->ndbapiBlockref = regApiPtr.p->ndbapiBlockref;
5563  copyPtr.p->ndbapiConnect = TndbapiConnect;
5564  copyPtr.p->firstTcConnect = TfirstTcConnect;
5565  copyPtr.p->apiConnectstate = CS_COMPLETING;
5566  copyPtr.p->transid[0] = Ttransid1;
5567  copyPtr.p->transid[1] = Ttransid2;
5568  copyPtr.p->lqhkeyconfrec = Tlqhkeyconfrec;
5569  copyPtr.p->commitAckMarker = RNIL;
5570  copyPtr.p->m_transaction_nodes = Tnodes;
5571  copyPtr.p->singleUserMode = 0;
5572 
5573  Ptr<GcpRecord> gcpPtr;
5574  gcpPtr.i = TgcpPointer;
5575  ptrCheckGuard(gcpPtr, TgcpFilesize, localGcpRecord);
5576  unlinkApiConnect(gcpPtr, regApiPtr);
5577  linkApiToGcp(gcpPtr, copyPtr);
5578  setApiConTimer(regApiPtr.i, 0, __LINE__);
5579  regApiPtr.p->apiConnectstate = CS_CONNECTED;
5580  regApiPtr.p->commitAckMarker = RNIL;
5581  regApiPtr.p->firstTcConnect = RNIL;
5582  regApiPtr.p->lastTcConnect = RNIL;
5583  regApiPtr.p->m_transaction_nodes.clear();
5584  regApiPtr.p->singleUserMode = 0;
5585  releaseAllSeizedIndexOperations(regApiPtr.p);
5586 }//Dbtc::copyApi()
5587 
5588 void Dbtc::unlinkApiConnect(Ptr<GcpRecord> gcpPtr,
5589  Ptr<ApiConnectRecord> regApiPtr)
5590 {
5591  ApiConnectRecordPtr localApiConnectptr;
5592  UintR TapiConnectFilesize = capiConnectFilesize;
5593  UintR TprevGcpConnect = regApiPtr.p->prevGcpConnect;
5594  UintR TnextGcpConnect = regApiPtr.p->nextGcpConnect;
5595  ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5596 
5597  if (TprevGcpConnect == RNIL) {
5598  gcpPtr.p->firstApiConnect = TnextGcpConnect;
5599  jam();
5600  } else {
5601  localApiConnectptr.i = TprevGcpConnect;
5602  jam();
5603  ptrCheckGuard(localApiConnectptr,
5604  TapiConnectFilesize, localApiConnectRecord);
5605  localApiConnectptr.p->nextGcpConnect = TnextGcpConnect;
5606  }//if
5607  if (TnextGcpConnect == RNIL) {
5608  gcpPtr.p->lastApiConnect = TprevGcpConnect;
5609  jam();
5610  } else {
5611  localApiConnectptr.i = TnextGcpConnect;
5612  jam();
5613  ptrCheckGuard(localApiConnectptr,
5614  TapiConnectFilesize, localApiConnectRecord);
5615  localApiConnectptr.p->prevGcpConnect = TprevGcpConnect;
5616  }//if
5617 }//Dbtc::unlinkApiConnect()
5618 
5619 void Dbtc::complete010Lab(Signal* signal)
5620 {
5621  TcConnectRecordPtr localTcConnectptr;
5622  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5623  UintR TtcConnectFilesize = ctcConnectFilesize;
5624  TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5625 
5626  localTcConnectptr.p = tcConnectptr.p;
5627  setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
5628  UintR TapiConnectptrIndex = apiConnectptr.i;
5629  UintR Tcount = 0;
5630  do {
5631  localTcConnectptr.p->apiConnect = TapiConnectptrIndex;
5632  localTcConnectptr.p->tcConnectstate = OS_COMPLETING;
5633 
5634  /* ************ */
5635  /* COMPLETE < */
5636  /* ************ */
5637  const Uint32 nextTcConnect = localTcConnectptr.p->nextTcConnect;
5638  Tcount += sendCompleteLqh(signal, localTcConnectptr.p);
5639  localTcConnectptr.i = nextTcConnect;
5640  if (localTcConnectptr.i != RNIL) {
5641  if (Tcount < 16) {
5642  ptrCheckGuard(localTcConnectptr,
5643  TtcConnectFilesize, localTcConnectRecord);
5644  jam();
5645  continue;
5646  } else {
5647  jam();
5648  if (ERROR_INSERTED(8013)) {
5649  CLEAR_ERROR_INSERT_VALUE;
5650  return;
5651  }//if
5652  signal->theData[0] = TcContinueB::ZSEND_COMPLETE_LOOP;
5653  signal->theData[1] = apiConnectptr.i;
5654  signal->theData[2] = localTcConnectptr.i;
5655  sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
5656  return;
5657  }//if
5658  } else {
5659  jam();
5660  regApiPtr->apiConnectstate = CS_COMPLETE_SENT;
5661  return;
5662  }//if
5663  } while (1);
5664 }//Dbtc::complete010Lab()
5665 
5666 Uint32
5667 Dbtc::sendCompleteLqh(Signal* signal,
5668  TcConnectRecord * const regTcPtr)
5669 {
5670  HostRecordPtr Thostptr;
5671  UintR ThostFilesize = chostFilesize;
5672  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5673  Thostptr.i = regTcPtr->lastLqhNodeId; //last???
5674  ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
5675 
5676  Uint32 Tnode = Thostptr.i;
5677  Uint32 self = getOwnNodeId();
5678  Uint32 ret = (Tnode == self) ? 4 : 1;
5679 
5680  Uint32 Tdata[3];
5681  Tdata[0] = regTcPtr->lastLqhCon;
5682  Tdata[1] = regApiPtr->transid[0];
5683  Tdata[2] = regApiPtr->transid[1];
5684  Uint32 len = 3;
5685 
5686  // currently packed signal cannot address specific instance
5687  const bool send_unpacked = getNodeInfo(Thostptr.i).m_lqh_workers > 1;
5688  if (send_unpacked) {
5689  memcpy(&signal->theData[0], &Tdata[0], len << 2);
5690  Uint32 instanceKey = regTcPtr->lqhInstanceKey;
5691  BlockReference lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
5692  sendSignal(lqhRef, GSN_COMPLETE, signal, 3, JBB);
5693  return ret;
5694  }
5695 
5696  if (Thostptr.p->noOfPackedWordsLqh > 22) {
5697  jam();
5698  sendPackedSignalLqh(signal, Thostptr.p);
5699  } else {
5700  jam();
5701  ret = 1;
5702  updatePackedList(signal, Thostptr.p, Thostptr.i);
5703  }
5704 
5705  Tdata[0] |= (ZCOMPLETE << 28);
5706  UintR Tindex = Thostptr.p->noOfPackedWordsLqh;
5707  UintR* TDataPtr = &Thostptr.p->packedWordsLqh[Tindex];
5708  memcpy(TDataPtr, &Tdata[0], len << 2);
5709  Thostptr.p->noOfPackedWordsLqh = Tindex + len;
5710 
5711  return ret;
5712 }
5713 
5714 void
5715 Dbtc::sendFireTrigReq(Signal* signal,
5716  Ptr<ApiConnectRecord> regApiPtr,
5717  Uint32 TopPtrI)
5718 {
5719  UintR TtcConnectFilesize = ctcConnectFilesize;
5720  TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5721  TcConnectRecordPtr localTcConnectptr;
5722 
5723  setApiConTimer(regApiPtr.i, ctcTimer, __LINE__);
5724  regApiPtr.p->apiConnectstate = CS_SEND_FIRE_TRIG_REQ;
5725 
5726  localTcConnectptr.i = TopPtrI;
5727  ndbassert(TopPtrI != RNIL);
5728  Uint32 Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
5729  Uint32 pass = regApiPtr.p->m_pre_commit_pass;
5730  for (Uint32 i = 0; localTcConnectptr.i != RNIL && i < 16; i++)
5731  {
5732  ptrCheckGuard(localTcConnectptr,
5733  TtcConnectFilesize, localTcConnectRecord);
5734 
5735  const Uint32 nextTcConnect = localTcConnectptr.p->nextTcConnect;
5736  Uint32 flags = localTcConnectptr.p->m_special_op_flags;
5737  if (flags & TcConnectRecord::SOF_DEFERRED_TRIGGER)
5738  {
5739  jam();
5740  tc_clearbit(flags, TcConnectRecord::SOF_DEFERRED_TRIGGER);
5741  ndbrequire(localTcConnectptr.p->tcConnectstate == OS_PREPARED);
5742  localTcConnectptr.p->tcConnectstate = OS_FIRE_TRIG_REQ;
5743  localTcConnectptr.p->m_special_op_flags = flags;
5744  i += sendFireTrigReqLqh(signal, localTcConnectptr, pass);
5745  Tlqhkeyreqrec++;
5746  }
5747  localTcConnectptr.i = nextTcConnect;
5748  }
5749 
5750  regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec;
5751  if (localTcConnectptr.i == RNIL)
5752  {
5756  jam();
5757  regApiPtr.p->apiConnectstate = CS_WAIT_FIRE_TRIG_REQ;
5758  ndbrequire(pass < 255);
5759  regApiPtr.p->m_pre_commit_pass = (Uint8)(pass + 1);
5760  return;
5761  }
5762  else
5763  {
5764  jam();
5765  signal->theData[0] = TcContinueB::ZSEND_FIRE_TRIG_REQ;
5766  signal->theData[1] = regApiPtr.i;
5767  signal->theData[2] = regApiPtr.p->transid[0];
5768  signal->theData[3] = regApiPtr.p->transid[1];
5769  signal->theData[4] = localTcConnectptr.i;
5770  if (ERROR_INSERTED_CLEAR(8090))
5771  {
5772  sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 5000, 5);
5773  }
5774  else
5775  {
5776  sendSignal(cownref, GSN_CONTINUEB, signal, 5, JBB);
5777  }
5778  }
5779 }
5780 
5781 Uint32
5782 Dbtc::sendFireTrigReqLqh(Signal* signal,
5783  Ptr<TcConnectRecord> regTcPtr,
5784  Uint32 pass)
5785 {
5786  HostRecordPtr Thostptr;
5787  UintR ThostFilesize = chostFilesize;
5788  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5789  Thostptr.i = regTcPtr.p->tcNodedata[0];
5790  ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
5791 
5792  Uint32 Tnode = Thostptr.i;
5793  Uint32 self = getOwnNodeId();
5794  Uint32 ret = (Tnode == self) ? 4 : 1;
5795 
5796  Uint32 Tdata[FireTrigReq::SignalLength];
5797  FireTrigReq * req = CAST_PTR(FireTrigReq, Tdata);
5798  req->tcOpRec = regTcPtr.i;
5799  req->transId[0] = regApiPtr->transid[0];
5800  req->transId[1] = regApiPtr->transid[1];
5801  req->pass = pass;
5802  Uint32 len = FireTrigReq::SignalLength;
5803 
5804  // currently packed signal cannot address specific instance
5805  const bool send_unpacked = getNodeInfo(Thostptr.i).m_lqh_workers > 1;
5806  if (send_unpacked) {
5807  memcpy(signal->theData, Tdata, len << 2);
5808  Uint32 instanceKey = regTcPtr.p->lqhInstanceKey;
5809  BlockReference lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
5810  sendSignal(lqhRef, GSN_FIRE_TRIG_REQ, signal, len, JBB);
5811  return ret;
5812  }
5813 
5814  if (Thostptr.p->noOfPackedWordsLqh > 25 - len) {
5815  jam();
5816  sendPackedSignalLqh(signal, Thostptr.p);
5817  } else {
5818  jam();
5819  ret = 1;
5820  updatePackedList(signal, Thostptr.p, Thostptr.i);
5821  }
5822 
5823  Tdata[0] |= (ZFIRE_TRIG_REQ << 28);
5824  UintR Tindex = Thostptr.p->noOfPackedWordsLqh;
5825  UintR* TDataPtr = &Thostptr.p->packedWordsLqh[Tindex];
5826  memcpy(TDataPtr, Tdata, len << 2);
5827  Thostptr.p->noOfPackedWordsLqh = Tindex + len;
5828  return ret;
5829 }
5830 
5831 void
5832 Dbtc::execFIRE_TRIG_CONF(Signal* signal)
5833 {
5834  TcConnectRecordPtr localTcConnectptr;
5835  ApiConnectRecordPtr regApiPtr;
5836 
5837  UintR TtcConnectFilesize = ctcConnectFilesize;
5838  UintR TapiConnectFilesize = capiConnectFilesize;
5839  TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5840  ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5841 
5842  const FireTrigConf * conf = CAST_CONSTPTR(FireTrigConf, signal->theData);
5843  localTcConnectptr.i = conf->tcOpRec;
5844  jamEntry();
5845  ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
5846  regApiPtr.i = localTcConnectptr.p->apiConnect;
5847  if (localTcConnectptr.p->tcConnectstate != OS_FIRE_TRIG_REQ)
5848  {
5849  warningReport(signal, 28);
5850  return;
5851  }//if
5852  ptrCheckGuard(regApiPtr, TapiConnectFilesize,
5853  localApiConnectRecord);
5854 
5855  Uint32 Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
5856  Uint32 TapiConnectstate = regApiPtr.p->apiConnectstate;
5857  UintR Tdata1 = regApiPtr.p->transid[0] - conf->transId[0];
5858  UintR Tdata2 = regApiPtr.p->transid[1] - conf->transId[1];
5859  Uint32 TcheckCondition =
5860  (TapiConnectstate != CS_SEND_FIRE_TRIG_REQ) &&
5861  (TapiConnectstate != CS_WAIT_FIRE_TRIG_REQ);
5862 
5863  Tdata1 = Tdata1 | Tdata2 | TcheckCondition;
5864 
5865  if (Tdata1 != 0) {
5866  warningReport(signal, 28);
5867  return;
5868  }//if
5869 
5870  if (ERROR_INSERTED_CLEAR(8091))
5871  {
5872  jam();
5873  return;
5874  }
5875 
5876  CRASH_INSERTION(8092);
5877 
5878  setApiConTimer(regApiPtr.i, ctcTimer, __LINE__);
5879  ndbassert(Tlqhkeyreqrec > 0);
5880  regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
5881  localTcConnectptr.p->tcConnectstate = OS_PREPARED;
5882 
5883  Uint32 noFired = FireTrigConf::getFiredCount(conf->noFiredTriggers);
5884  Uint32 deferred = FireTrigConf::getDeferredBit(conf->noFiredTriggers);
5885 
5886  regApiPtr.p->pendingTriggers += noFired;
5887  regApiPtr.p->m_flags |= (deferred) ?
5888  ApiConnectRecord::TF_DEFERRED_TRIGGERS : 0;
5889  localTcConnectptr.p->m_special_op_flags |= (deferred) ?
5890  TcConnectRecord::SOF_DEFERRED_TRIGGER : 0;
5891 
5892  if (regApiPtr.p->pendingTriggers == 0)
5893  {
5894  jam();
5895  lqhKeyConf_checkTransactionState(signal, regApiPtr);
5896  }
5897 }
5898 
5899 void
5900 Dbtc::execFIRE_TRIG_REF(Signal* signal)
5901 {
5902  TcConnectRecordPtr localTcConnectptr;
5903  ApiConnectRecordPtr regApiPtr;
5904 
5905  UintR TtcConnectFilesize = ctcConnectFilesize;
5906  UintR TapiConnectFilesize = capiConnectFilesize;
5907  TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5908  ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5909 
5910  const FireTrigRef * ref = CAST_CONSTPTR(FireTrigRef, signal->theData);
5911  localTcConnectptr.i = ref->tcOpRec;
5912  jamEntry();
5913  ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
5914  regApiPtr.i = localTcConnectptr.p->apiConnect;
5915  if (localTcConnectptr.p->tcConnectstate != OS_FIRE_TRIG_REQ)
5916  {
5917  warningReport(signal, 28);
5918  return;
5919  }//if
5920  ptrCheckGuard(regApiPtr, TapiConnectFilesize,
5921  localApiConnectRecord);
5922 
5923  apiConnectptr = regApiPtr;
5924 
5925  UintR Tdata1 = regApiPtr.p->transid[0] - ref->transId[0];
5926  UintR Tdata2 = regApiPtr.p->transid[1] - ref->transId[1];
5927  Tdata1 = Tdata1 | Tdata2;
5928  if (Tdata1 != 0) {
5929  warningReport(signal, 28);
5930  return;
5931  }//if
5932 
5933  if (regApiPtr.p->apiConnectstate != CS_SEND_FIRE_TRIG_REQ &&
5934  regApiPtr.p->apiConnectstate != CS_WAIT_FIRE_TRIG_REQ)
5935  {
5936  jam();
5937  warningReport(signal, 28);
5938  return;
5939  }
5940 
5941  terrorCode = ref->errCode;
5942  abortErrorLab(signal);
5943 }
5944 
5945 void
5946 Dbtc::execTC_COMMIT_ACK(Signal* signal){
5947  jamEntry();
5948 
5949  CommitAckMarker key;
5950  key.transid1 = signal->theData[0];
5951  key.transid2 = signal->theData[1];
5952 
5953  CommitAckMarkerPtr removedMarker;
5954  m_commitAckMarkerHash.remove(removedMarker, key);
5955  if (removedMarker.i == RNIL) {
5956  jam();
5957  warningHandlerLab(signal, __LINE__);
5958  return;
5959  }//if
5960  sendRemoveMarkers(signal, removedMarker.p);
5961  m_commitAckMarkerPool.release(removedMarker);
5962 }
5963 
5964 void
5965 Dbtc::sendRemoveMarkers(Signal* signal, const CommitAckMarker * marker)
5966 {
5967  jam();
5968  const Uint32 transId1 = marker->transid1;
5969  const Uint32 transId2 = marker->transid2;
5970 
5971  for(Uint32 node_id = 1; node_id < MAX_NDB_NODES; node_id++)
5972  {
5973  jam();
5974  if (marker->m_commit_ack_marker_nodes.get(node_id))
5975  sendRemoveMarker(signal, node_id, transId1, transId2);
5976  }
5977 }
5978 
5979 void
5980 Dbtc::sendRemoveMarker(Signal* signal,
5981  NodeId nodeId,
5982  Uint32 transid1,
5983  Uint32 transid2){
5987  HostRecordPtr hostPtr;
5988  const UintR ThostFilesize = chostFilesize;
5989  hostPtr.i = nodeId;
5990  ptrCheckGuard(hostPtr, ThostFilesize, hostRecord);
5991 
5992  Uint32 Tdata[3];
5993  Tdata[0] = 0;
5994  Tdata[1] = transid1;
5995  Tdata[2] = transid2;
5996  Uint32 len = 3;
5997 
5998  // currently packed signals can not address specific instance
5999  bool send_unpacked = getNodeInfo(hostPtr.i).m_lqh_workers > 1;
6000  if (send_unpacked) {
6001  jam();
6002  // first word omitted
6003  memcpy(&signal->theData[0], &Tdata[1], (len - 1) << 2);
6004  Uint32 Tnode = hostPtr.i;
6005  Uint32 i;
6006  for (i = 0; i < MAX_NDBMT_LQH_WORKERS; i++) {
6007  // wl4391_todo skip workers not part of tx
6008  Uint32 instanceKey = 1 + i;
6009  BlockReference ref = numberToRef(DBLQH, instanceKey, Tnode);
6010  sendSignal(ref, GSN_REMOVE_MARKER_ORD, signal, len - 1, JBB);
6011  }
6012  return;
6013  }
6014 
6015  if (hostPtr.p->noOfPackedWordsLqh > (25 - 3)){
6016  jam();
6017  sendPackedSignalLqh(signal, hostPtr.p);
6018  } else {
6019  jam();
6020  updatePackedList(signal, hostPtr.p, hostPtr.i);
6021  }
6022 
6023  UintR numWord = hostPtr.p->noOfPackedWordsLqh;
6024  UintR* dataPtr = &hostPtr.p->packedWordsLqh[numWord];
6025 
6026  Tdata[0] |= (ZREMOVE_MARKER << 28);
6027  memcpy(dataPtr, &Tdata[0], len << 2);
6028  hostPtr.p->noOfPackedWordsLqh = numWord + 3;
6029 }
6030 
6031 void Dbtc::execCOMPLETED(Signal* signal)
6032 {
6033  TcConnectRecordPtr localTcConnectptr;
6034  ApiConnectRecordPtr localApiConnectptr;
6035 
6036  UintR TtcConnectFilesize = ctcConnectFilesize;
6037  UintR TapiConnectFilesize = capiConnectFilesize;
6038  TcConnectRecord *localTcConnectRecord = tcConnectRecord;
6039  ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
6040 
6041 #ifdef ERROR_INSERT
6042  if (ERROR_INSERTED(8031)) {
6043  systemErrorLab(signal, __LINE__);
6044  }//if
6045  if (ERROR_INSERTED(8019)) {
6046  CLEAR_ERROR_INSERT_VALUE;
6047  return;
6048  }//if
6049  if (ERROR_INSERTED(8027)) {
6050  SET_ERROR_INSERT_VALUE(8028);
6051  return;
6052  }//if
6053  if (ERROR_INSERTED(8043)) {
6054  CLEAR_ERROR_INSERT_VALUE;
6055  sendSignalWithDelay(cownref, GSN_COMPLETED, signal, 2000, 3);
6056  return;
6057  }//if
6058  if (ERROR_INSERTED(8044)) {
6059  SET_ERROR_INSERT_VALUE(8047);
6060  sendSignalWithDelay(cownref, GSN_COMPLETED, signal, 2000, 3);
6061  return;
6062  }//if
6063 #endif
6064  localTcConnectptr.i = signal->theData[0];
6065  jamEntry();
6066  ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
6067  bool Tcond1 = (localTcConnectptr.p->tcConnectstate != OS_COMPLETING);
6068  localApiConnectptr.i = localTcConnectptr.p->apiConnect;
6069  if (Tcond1) {
6070  warningReport(signal, 6);
6071  return;
6072  }//if
6073  ptrCheckGuard(localApiConnectptr, TapiConnectFilesize,
6074  localApiConnectRecord);
6075  UintR Tdata1 = localApiConnectptr.p->transid[0] - signal->theData[1];
6076  UintR Tdata2 = localApiConnectptr.p->transid[1] - signal->theData[2];
6077  UintR Tcounter = localApiConnectptr.p->counter - 1;
6078  ConnectionState TapiConnectstate = localApiConnectptr.p->apiConnectstate;
6079  Tdata1 = Tdata1 | Tdata2;
6080  bool TcheckCondition =
6081  (TapiConnectstate != CS_COMPLETE_SENT) || (Tcounter != 0);
6082  if (Tdata1 != 0) {
6083  warningReport(signal, 7);
6084  return;
6085  }//if
6086  setApiConTimer(localApiConnectptr.i, ctcTimer, __LINE__);
6087  localApiConnectptr.p->counter = Tcounter;
6088  localTcConnectptr.p->tcConnectstate = OS_COMPLETED;
6089  localTcConnectptr.p->noOfNodes = 0; // == releaseNodes(signal)
6090  if (TcheckCondition) {
6091  jam();
6092  /*-------------------------------------------------------*/
6093  // We have not sent all COMPLETE requests yet. We could be
6094  // in the state that all sent are COMPLETED but we are
6095  // still waiting for a CONTINUEB to send the rest of the
6096  // COMPLETE requests.
6097  /*-------------------------------------------------------*/
6098  return;
6099  }//if
6100  if (ERROR_INSERTED(8021)) {
6101  jam();
6102  systemErrorLab(signal, __LINE__);
6103  }//if
6104  apiConnectptr = localApiConnectptr;
6105  releaseTransResources(signal);
6106 }//Dbtc::execCOMPLETED()
6107 
6108 /*---------------------------------------------------------------------------*/
6109 /* RELEASE_TRANS_RESOURCES */
6110 /* RELEASE ALL RESOURCES THAT ARE CONNECTED TO THIS TRANSACTION. */
6111 /*---------------------------------------------------------------------------*/
6112 void Dbtc::releaseTransResources(Signal* signal)
6113 {
6114  TcConnectRecordPtr localTcConnectptr;
6115  UintR TtcConnectFilesize = ctcConnectFilesize;
6116  TcConnectRecord *localTcConnectRecord = tcConnectRecord;
6117  apiConnectptr.p->m_transaction_nodes.clear();
6118  localTcConnectptr.i = apiConnectptr.p->firstTcConnect;
6119  do {
6120  jam();
6121  ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
6122  UintR rtrTcConnectptrIndex = localTcConnectptr.p->nextTcConnect;
6123  tcConnectptr.i = localTcConnectptr.i;
6124  tcConnectptr.p = localTcConnectptr.p;
6125  localTcConnectptr.i = rtrTcConnectptrIndex;
6126  releaseTcCon();
6127  } while (localTcConnectptr.i != RNIL);
6128  handleGcp(signal, apiConnectptr);
6129  releaseFiredTriggerData(&apiConnectptr.p->theFiredTriggers);
6130  releaseAllSeizedIndexOperations(apiConnectptr.p);
6131  releaseApiConCopy(signal);
6132 }//Dbtc::releaseTransResources()
6133 
6134 /* *********************************************************************>> */
6135 /* MODULE: HANDLE_GCP */
6136 /* DESCRIPTION: HANDLES GLOBAL CHECKPOINT HANDLING AT THE COMPLETION */
6137 /* OF THE COMMIT PHASE AND THE ABORT PHASE. WE MUST ENSURE THAT TC */
6138 /* SENDS GCP_TCFINISHED WHEN ALL TRANSACTIONS BELONGING TO A CERTAIN */
6139 /* GLOBAL CHECKPOINT HAVE COMPLETED. */
6140 /* *********************************************************************>> */
6141 void Dbtc::handleGcp(Signal* signal, Ptr<ApiConnectRecord> regApiPtr)
6142 {
6143  GcpRecord *localGcpRecord = gcpRecord;
6144  GcpRecordPtr localGcpPtr;
6145  UintR TgcpFilesize = cgcpFilesize;
6146  localGcpPtr.i = apiConnectptr.p->gcpPointer;
6147  ptrCheckGuard(localGcpPtr, TgcpFilesize, localGcpRecord);
6148  unlinkApiConnect(localGcpPtr, regApiPtr);
6149  if (localGcpPtr.p->firstApiConnect == RNIL) {
6150  if (localGcpPtr.p->gcpNomoretransRec == ZTRUE) {
6151  if (c_ongoing_take_over_cnt == 0)
6152  {
6153  jam();
6154  gcpTcfinished(signal, localGcpPtr.p->gcpId);
6155  unlinkGcp(localGcpPtr);
6156  }
6157  }//if
6158  }
6159 }//Dbtc::handleGcp()
6160 
6161 void Dbtc::releaseApiConCopy(Signal* signal)
6162 {
6163  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
6164  UintR TfirstfreeApiConnectCopyOld = cfirstfreeApiConnectCopy;
6165  cfirstfreeApiConnectCopy = apiConnectptr.i;
6166  regApiPtr->nextApiConnect = TfirstfreeApiConnectCopyOld;
6167  setApiConTimer(apiConnectptr.i, 0, __LINE__);
6168  regApiPtr->apiConnectstate = CS_RESTART;
6169  ndbrequire(regApiPtr->commitAckMarker == RNIL);
6170 }//Dbtc::releaseApiConCopy()
6171 
6172 /* ========================================================================= */
6173 /* ------- RELEASE ALL RECORDS CONNECTED TO A DIRTY WRITE OPERATION ------- */
6174 /* ========================================================================= */
6175 void Dbtc::releaseDirtyWrite(Signal* signal)
6176 {
6177  unlinkReadyTcCon(signal);
6178  releaseTcCon();
6179  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
6180  if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
6181  if (regApiPtr->firstTcConnect == RNIL) {
6182  jam();
6183  regApiPtr->apiConnectstate = CS_CONNECTED;
6184  setApiConTimer(apiConnectptr.i, 0, __LINE__);
6185  sendtckeyconf(signal, 1);
6186  }//if
6187  }//if
6188 }//Dbtc::releaseDirtyWrite()
6189 
6190 /*****************************************************************************
6191  * L Q H K E Y R E F
6192  * WHEN LQHKEYREF IS RECEIVED DBTC WILL CHECK IF COMMIT FLAG WAS SENT FROM THE
6193  * APPLICATION. IF SO, THE WHOLE TRANSACTION WILL BE ROLLED BACK AND SIGNAL
6194  * TCROLLBACKREP WILL BE SENT TO THE API.
6195  *
6196  * OTHERWISE TC WILL CHECK THE ERRORCODE. IF THE ERRORCODE IS INDICATING THAT
6197  * THE "ROW IS NOT FOUND" FOR UPDATE/READ/DELETE OPERATIONS AND "ROW ALREADY
6198  * EXISTS" FOR INSERT OPERATIONS, DBTC WILL RELEASE THE OPERATION AND THEN
6199  * SEND RETURN SIGNAL TCKEYREF TO THE USER. THE USER THEN HAVE TO SEND
6200  * SIGNAL TC_COMMITREQ OR TC_ROLLBACKREQ TO CONCLUDE THE TRANSACTION.
6201  * IF ANY TCKEYREQ WITH COMMIT IS RECEIVED AND API_CONNECTSTATE EQUALS
6202  * "REC_LQHREFUSE",
6203  * THE OPERATION WILL BE TREATED AS AN OPERATION WITHOUT COMMIT. WHEN ANY
6204  * OTHER FAULTCODE IS RECEIVED THE WHOLE TRANSACTION MUST BE ROLLED BACK
6205  *****************************************************************************/
6206 void Dbtc::execLQHKEYREF(Signal* signal)
6207 {
6208  const LqhKeyRef * const lqhKeyRef = (LqhKeyRef *)signal->getDataPtr();
6209  Uint32 indexId = 0;
6210  jamEntry();
6211 
6212  UintR compare_transid1, compare_transid2;
6213  UintR TtcConnectFilesize = ctcConnectFilesize;
6214  /*-------------------------------------------------------------------------
6215  *
6216  * RELEASE NODE BUFFER(S) TO INDICATE THAT THIS OPERATION HAVE NO
6217  * TRANSACTION PARTS ACTIVE ANYMORE.
6218  * LQHKEYREF HAVE CLEARED ALL PARTS ON ITS PATH BACK TO TC.
6219  *-------------------------------------------------------------------------*/
6220  if (lqhKeyRef->connectPtr < TtcConnectFilesize) {
6221  /*-----------------------------------------------------------------------
6222  * WE HAVE TO CHECK THAT THE TRANSACTION IS STILL VALID. FIRST WE CHECK
6223  * THAT THE LQH IS STILL CONNECTED TO A TC, IF THIS HOLDS TRUE THEN THE
6224  * TC MUST BE CONNECTED TO AN API CONNECT RECORD.
6225  * WE MUST ENSURE THAT THE TRANSACTION ID OF THIS API CONNECT
6226  * RECORD IS STILL THE SAME AS THE ONE LQHKEYREF REFERS TO.
6227  * IF NOT SIMPLY EXIT AND FORGET THE SIGNAL SINCE THE TRANSACTION IS
6228  * ALREADY COMPLETED (ABORTED).
6229  *-----------------------------------------------------------------------*/
6230  tcConnectptr.i = lqhKeyRef->connectPtr;
6231  Uint32 errCode = terrorCode = lqhKeyRef->errorCode;
6232  ptrAss(tcConnectptr, tcConnectRecord);
6233  TcConnectRecord * const regTcPtr = tcConnectptr.p;
6234  if (regTcPtr->tcConnectstate == OS_OPERATING) {
6235  Uint32 save = apiConnectptr.i = regTcPtr->apiConnect;
6236  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
6237  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
6238  compare_transid1 = regApiPtr->transid[0] ^ lqhKeyRef->transId1;
6239  compare_transid2 = regApiPtr->transid[1] ^ lqhKeyRef->transId2;
6240  compare_transid1 = compare_transid1 | compare_transid2;
6241  if (compare_transid1 != 0) {
6242  warningReport(signal, 25);
6243  return;
6244  }//if
6245 
6246  const Uint32 triggeringOp = regTcPtr->triggeringOperation;
6247  if (triggeringOp != RNIL) {
6248  jam();
6249  // This operation was created by a trigger execting operation
6250  TcConnectRecordPtr opPtr;
6251  TcConnectRecord *localTcConnectRecord = tcConnectRecord;
6252 
6253  opPtr.i = triggeringOp;
6254  ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
6255 
6256  const Uint32 opType = regTcPtr->operation;
6257  Ptr<TcDefinedTriggerData> trigPtr;
6258  c_theDefinedTriggers.getPtr(trigPtr, regTcPtr->currentTriggerId);
6259  switch(trigPtr.p->triggerType){
6260  case TriggerType::SECONDARY_INDEX:{
6261  jam();
6262 
6263  // The operation executed an index trigger
6264  TcIndexData* indexData = c_theIndexes.getPtr(trigPtr.p->indexId);
6265  indexId = indexData->indexId;
6266  regApiPtr->errorData = indexId;
6267  if (errCode == ZALREADYEXIST)
6268  {
6269  jam();
6270  errCode = terrorCode = ZNOTUNIQUE;
6271  goto do_abort;
6272  }
6273  else if (!(opType == ZDELETE && errCode == ZNOT_FOUND)) {
6274  jam();
6278  goto do_abort;
6279  }
6280  else
6281  {
6282  jam();
6284  if (indexData->indexState != IS_BUILDING)
6285  {
6286  jam();
6287  goto do_abort;
6288  }
6289  }
6290  goto do_ignore;
6291  }
6292  case TriggerType::REORG_TRIGGER:
6293  jam();
6294  if (opType == ZINSERT && errCode == ZALREADYEXIST)
6295  {
6296  jam();
6297  ndbout_c("reorg, ignore ZALREADYEXIST");
6298  goto do_ignore;
6299  }
6300  else if (errCode == ZNOT_FOUND)
6301  {
6302  jam();
6303  ndbout_c("reorg, ignore ZNOT_FOUND");
6304  goto do_ignore;
6305  }
6306  else if (errCode == 839)
6307  {
6308  jam();
6309  ndbout_c("reorg, ignore 839");
6310  goto do_ignore;
6311  }
6312  else
6313  {
6314  ndbout_c("reorg: opType: %u errCode: %u", opType, errCode);
6315  }
6316  // fall-through
6317  default:
6318  jam();
6319  goto do_abort;
6320  }
6321 
6322  do_ignore:
6323  jam();
6327  regApiPtr->lqhkeyreqrec--;
6328 
6333  clearCommitAckMarker(regApiPtr, regTcPtr);
6334 
6335  unlinkReadyTcCon(signal);
6336  releaseTcCon();
6337 
6338  trigger_op_finished(signal, apiConnectptr, opPtr.p);
6339  return;
6340  }
6341 
6342  do_abort:
6343  markOperationAborted(regApiPtr, regTcPtr);
6344 
6345  if(regApiPtr->apiConnectstate == CS_ABORTING){
6349  jam();
6350  return;
6351  }
6352 
6353  const Uint32 abort = regTcPtr->m_execAbortOption;
6354  if (abort == TcKeyReq::AbortOnError || triggeringOp != RNIL) {
6358  TCKEY_abort(signal, 49);
6359  return;
6360  }//if
6361 
6362  /* *************** */
6363  /* TCKEYREF < */
6364  /* *************** */
6365  TcKeyRef * const tcKeyRef = (TcKeyRef *) signal->getDataPtrSend();
6366  tcKeyRef->transId[0] = regApiPtr->transid[0];
6367  tcKeyRef->transId[1] = regApiPtr->transid[1];
6368  tcKeyRef->errorCode = terrorCode;
6369  bool isIndexOp = regTcPtr->isIndexOp(regTcPtr->m_special_op_flags);
6370  Uint32 indexOp = tcConnectptr.p->indexOp;
6371  Uint32 clientData = regTcPtr->clientData;
6372  unlinkReadyTcCon(signal); /* LINK TC CONNECT RECORD OUT OF */
6373  releaseTcCon(); /* RELEASE THE TC CONNECT RECORD */
6374  setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
6375  if (isIndexOp) {
6376  jam();
6377  regApiPtr->lqhkeyreqrec--; // Compensate for extra during read
6378  tcKeyRef->connectPtr = indexOp;
6379  tcKeyRef->errorData = indexId;
6380  EXECUTE_DIRECT(DBTC, GSN_TCKEYREF, signal, TcKeyRef::SignalLength);
6381  apiConnectptr.i = save;
6382  apiConnectptr.p = regApiPtr;
6383  } else {
6384  jam();
6385  tcKeyRef->connectPtr = clientData;
6386  tcKeyRef->errorData = indexId;
6387  sendSignal(regApiPtr->ndbapiBlockref,
6388  GSN_TCKEYREF, signal, TcKeyRef::SignalLength, JBB);
6389  }//if
6390 
6391  /*---------------------------------------------------------------------
6392  * SINCE WE ARE NOT ABORTING WE NEED TO UPDATE THE COUNT OF HOW MANY
6393  * LQHKEYREQ THAT HAVE RETURNED.
6394  * IF NO MORE OUTSTANDING LQHKEYREQ'S THEN WE NEED TO
6395  * TCKEYCONF (IF THERE IS ANYTHING TO SEND).
6396  *---------------------------------------------------------------------*/
6397  regApiPtr->lqhkeyreqrec--;
6398  if (regApiPtr->lqhkeyconfrec == regApiPtr->lqhkeyreqrec) {
6399  if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
6400  jam();
6401  diverify010Lab(signal);
6402  return;
6403  }
6404  else if (regApiPtr->tckeyrec > 0 ||
6405  tc_testbit(regApiPtr->m_flags, ApiConnectRecord::TF_EXEC_FLAG))
6406  {
6407  jam();
6408  sendtckeyconf(signal, 2);
6409  return;
6410  }
6411  }//if
6412  return;
6413 
6414  } else {
6415  warningReport(signal, 26);
6416  }//if
6417  } else {
6418  errorReport(signal, 6);
6419  }//if
6420  return;
6421 }//Dbtc::execLQHKEYREF()
6422 
6423 void Dbtc::clearCommitAckMarker(ApiConnectRecord * const regApiPtr,
6424  TcConnectRecord * const regTcPtr)
6425 {
6426  const Uint32 commitAckMarker = regTcPtr->commitAckMarker;
6427  if (regApiPtr->commitAckMarker == RNIL)
6428  {
6429  ndbassert(commitAckMarker == RNIL);
6430  }
6431 
6432  if(commitAckMarker != RNIL)
6433  {
6434  jam();
6435  ndbassert(regApiPtr->commitAckMarker == commitAckMarker);
6436  ndbrequire(regApiPtr->no_commit_ack_markers > 0);
6437  regApiPtr->no_commit_ack_markers--;
6438  regTcPtr->commitAckMarker = RNIL;
6439  if (regApiPtr->no_commit_ack_markers == 0)
6440  {
6441  regApiPtr->commitAckMarker = RNIL;
6442  tc_clearbit(regApiPtr->m_flags,
6443  ApiConnectRecord::TF_COMMIT_ACK_MARKER_RECEIVED);
6444  m_commitAckMarkerHash.release(commitAckMarker);
6445  }
6446  }
6447 }
6448 
6449 void Dbtc::markOperationAborted(ApiConnectRecord * const regApiPtr,
6450  TcConnectRecord * const regTcPtr)
6451 {
6452  /*------------------------------------------------------------------------
6453  * RELEASE NODES TO INDICATE THAT THE OPERATION IS ALREADY ABORTED IN THE
6454  * LQH'S ALSO SET STATE TO ABORTING TO INDICATE THE ABORT IS
6455  * ALREADY COMPLETED.
6456  *------------------------------------------------------------------------*/
6457  regTcPtr->noOfNodes = 0; // == releaseNodes(signal)
6458  regTcPtr->tcConnectstate = OS_ABORTING;
6459  clearCommitAckMarker(regApiPtr, regTcPtr);
6460 }
6461 
6462 /*--------------------------------------*/
6463 /* EXIT AND WAIT FOR SIGNAL TCOMMITREQ */
6464 /* OR TCROLLBACKREQ FROM THE USER TO */
6465 /* CONTINUE THE TRANSACTION */
6466 /*--------------------------------------*/
6467 void Dbtc::execTC_COMMITREQ(Signal* signal)
6468 {
6469  UintR compare_transid1, compare_transid2;
6470 
6471  jamEntry();
6472  apiConnectptr.i = signal->theData[0];
6473  if (apiConnectptr.i < capiConnectFilesize) {
6474  ptrAss(apiConnectptr, apiConnectRecord);
6475  compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
6476  compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
6477  compare_transid1 = compare_transid1 | compare_transid2;
6478  if (compare_transid1 != 0) {
6479  jam();
6480  return;
6481  }//if
6482 
6483  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
6484 
6485  const Uint32 apiConnectPtr = regApiPtr->ndbapiConnect;
6486  const Uint32 apiBlockRef = regApiPtr->ndbapiBlockref;
6487  const Uint32 transId1 = regApiPtr->transid[0];
6488  const Uint32 transId2 = regApiPtr->transid[1];
6489  Uint32 errorCode = 0;
6490 
6491  regApiPtr->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
6492  switch (regApiPtr->apiConnectstate) {
6493  case CS_STARTED:
6494  tcConnectptr.i = regApiPtr->firstTcConnect;
6495  if (tcConnectptr.i != RNIL) {
6496  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
6497  if (regApiPtr->lqhkeyconfrec == regApiPtr->lqhkeyreqrec) {
6498  jam();
6499  /*******************************************************************/
6500  // The proper case where the application is waiting for commit or
6501  // abort order.
6502  // Start the commit order.
6503  /*******************************************************************/
6504  regApiPtr->returnsignal = RS_TC_COMMITCONF;
6505  setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
6506  diverify010Lab(signal);
6507  return;
6508  } else {
6509  jam();
6510  /*******************************************************************/
6511  // The transaction is started but not all operations are completed.
6512  // It is not possible to commit the transaction in this state.
6513  // We will abort it instead.
6514  /*******************************************************************/
6515  regApiPtr->returnsignal = RS_NO_RETURN;
6516  errorCode = ZTRANS_STATUS_ERROR;
6517  abort010Lab(signal);
6518  }//if
6519  } else {
6520  jam();
6524  TcCommitConf * const commitConf = (TcCommitConf *)&signal->theData[0];
6525  commitConf->apiConnectPtr = apiConnectPtr;
6526  commitConf->transId1 = transId1;
6527  commitConf->transId2 = transId2;
6528  commitConf->gci_hi = 0;
6529  commitConf->gci_lo = 0;
6530  sendSignal(apiBlockRef, GSN_TC_COMMITCONF, signal,
6531  TcCommitConf::SignalLength, JBB);
6532 
6533  regApiPtr->returnsignal = RS_NO_RETURN;
6534  releaseAbortResources(signal);
6535  return;
6536  }//if
6537  break;
6538  case CS_RECEIVING:
6539  jam();
6540  /***********************************************************************/
6541  // A transaction is still receiving data. We cannot commit an unfinished
6542  // transaction. We will abort it instead.
6543  /***********************************************************************/
6544  regApiPtr->returnsignal = RS_NO_RETURN;
6545  errorCode = ZPREPAREINPROGRESS;
6546  abort010Lab(signal);
6547  break;
6548 
6549  case CS_START_COMMITTING:
6550  case CS_COMMITTING:
6551  case CS_COMMIT_SENT:
6552  case CS_COMPLETING:
6553  case CS_COMPLETE_SENT:
6554  case CS_REC_COMMITTING:
6555  case CS_PREPARE_TO_COMMIT:
6556  jam();
6557  /***********************************************************************/
6558  // The transaction is already performing a commit but it is not concluded
6559  // yet.
6560  /***********************************************************************/
6561  errorCode = ZCOMMITINPROGRESS;
6562  break;
6563  case CS_ABORTING:
6564  jam();
6565  errorCode = regApiPtr->returncode ?
6566  regApiPtr->returncode : ZABORTINPROGRESS;
6567  break;
6568  case CS_START_SCAN:
6569  jam();
6570  /***********************************************************************/
6571  // The transaction is a scan. Scans cannot commit
6572  /***********************************************************************/
6573  errorCode = ZSCANINPROGRESS;
6574  break;
6575  case CS_PREPARED:
6576  jam();
6577  return;
6578  case CS_START_PREPARING:
6579  jam();
6580  return;
6581  case CS_REC_PREPARING:
6582  jam();
6583  return;
6584  break;
6585  default:
6586  warningHandlerLab(signal, __LINE__);
6587  return;
6588  }//switch
6589  TcCommitRef * const commitRef = (TcCommitRef*)&signal->theData[0];
6590  commitRef->apiConnectPtr = apiConnectPtr;
6591  commitRef->transId1 = transId1;
6592  commitRef->transId2 = transId2;
6593  commitRef->errorCode = errorCode;
6594  sendSignal(apiBlockRef, GSN_TC_COMMITREF, signal,
6595  TcCommitRef::SignalLength, JBB);
6596  return;
6597  } else {
6598  jam();
6599  warningHandlerLab(signal, __LINE__);
6600  return;
6601  }
6602 }//Dbtc::execTC_COMMITREQ()
6603 
6617 void Dbtc::execTCROLLBACKREQ(Signal* signal)
6618 {
6619  bool potentiallyBad= false;
6620  UintR compare_transid1, compare_transid2;
6621 
6622  jamEntry();
6623 
6624  if(unlikely((signal->getLength() >= 4) && (signal->theData[3] & 0x1)))
6625  {
6626  ndbout_c("Trying to roll back potentially bad txn\n");
6627  potentiallyBad= true;
6628  }
6629 
6630  apiConnectptr.i = signal->theData[0];
6631  if (apiConnectptr.i >= capiConnectFilesize) {
6632  goto TC_ROLL_warning;
6633  }//if
6634  ptrAss(apiConnectptr, apiConnectRecord);
6635  compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
6636  compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
6637  compare_transid1 = compare_transid1 | compare_transid2;
6638  if (compare_transid1 != 0) {
6639  jam();
6640  return;
6641  }//if
6642 
6643  apiConnectptr.p->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
6644  switch (apiConnectptr.p->apiConnectstate) {
6645  case CS_STARTED:
6646  case CS_RECEIVING:
6647  jam();
6648  apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
6649  abort010Lab(signal);
6650  return;
6651  case CS_CONNECTED:
6652  jam();
6653  signal->theData[0] = apiConnectptr.p->ndbapiConnect;
6654  signal->theData[1] = apiConnectptr.p->transid[0];
6655  signal->theData[2] = apiConnectptr.p->transid[1];
6656  sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKCONF,
6657  signal, 3, JBB);
6658  break;
6659  case CS_START_SCAN:
6660  case CS_PREPARE_TO_COMMIT:
6661  case CS_COMMITTING:
6662  case CS_COMMIT_SENT:
6663  case CS_COMPLETING:
6664  case CS_COMPLETE_SENT:
6665  case CS_WAIT_COMMIT_CONF:
6666  case CS_WAIT_COMPLETE_CONF:
6667  case CS_RESTART:
6668  case CS_DISCONNECTED:
6669  case CS_START_COMMITTING:
6670  case CS_REC_COMMITTING:
6671  jam();
6672  /* ***************< */
6673  /* TC_ROLLBACKREF < */
6674  /* ***************< */
6675  signal->theData[0] = apiConnectptr.p->ndbapiConnect;
6676  signal->theData[1] = apiConnectptr.p->transid[0];
6677  signal->theData[2] = apiConnectptr.p->transid[1];
6678  signal->theData[3] = ZROLLBACKNOTALLOWED;
6679  signal->theData[4] = apiConnectptr.p->apiConnectstate;
6680  sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREF,
6681  signal, 5, JBB);
6682  break;
6683  /* SEND A REFUSAL SIGNAL*/
6684  case CS_ABORTING:
6685  jam();
6686  if (apiConnectptr.p->abortState == AS_IDLE) {
6687  jam();
6688  signal->theData[0] = apiConnectptr.p->ndbapiConnect;
6689  signal->theData[1] = apiConnectptr.p->transid[0];
6690  signal->theData[2] = apiConnectptr.p->transid[1];
6691  sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKCONF,
6692  signal, 3, JBB);
6693  } else {
6694  jam();
6695  apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
6696  }//if
6697  break;
6698  case CS_WAIT_ABORT_CONF:
6699  jam();
6700  apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
6701  break;
6702  case CS_START_PREPARING:
6703  jam();
6704  case CS_PREPARED:
6705  jam();
6706  case CS_REC_PREPARING:
6707  jam();
6708  default:
6709  goto TC_ROLL_system_error;
6710  break;
6711  }//switch
6712  return;
6713 
6714 TC_ROLL_warning:
6715  jam();
6716  if(likely(potentiallyBad==false))
6717  warningHandlerLab(signal, __LINE__);
6718  return;
6719 
6720 TC_ROLL_system_error:
6721  jam();
6722  if(likely(potentiallyBad==false))
6723  systemErrorLab(signal, __LINE__);
6724  return;
6725 }//Dbtc::execTCROLLBACKREQ()
6726 
6727 void Dbtc::execTC_HBREP(Signal* signal)
6728 {
6729  const TcHbRep * const tcHbRep =
6730  (TcHbRep *)signal->getDataPtr();
6731 
6732  jamEntry();
6733  apiConnectptr.i = tcHbRep->apiConnectPtr;
6734  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
6735 
6736  if (apiConnectptr.p->transid[0] == tcHbRep->transId1 &&
6737  apiConnectptr.p->transid[1] == tcHbRep->transId2){
6738 
6739  if (getApiConTimer(apiConnectptr.i) != 0){
6740  setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
6741  } else {
6742  DEBUG("TCHBREP received when timer was off apiConnectptr.i="
6743  << apiConnectptr.i);
6744  }
6745  }
6746 }//Dbtc::execTCHBREP()
6747 
6748 /*
6749 4.3.15 ABORT
6750 -----------
6751 */
6752 /*****************************************************************************/
6753 /* A B O R T */
6754 /* */
6755 /*****************************************************************************/
6756 void Dbtc::warningReport(Signal* signal, int place)
6757 {
6758  switch (place) {
6759  case 0:
6760  jam();
6761 #ifdef ABORT_TRACE
6762  ndbout << "ABORTED to not active TC record" << endl;
6763 #endif
6764  break;
6765  case 1:
6766  jam();
6767 #ifdef ABORT_TRACE
6768  ndbout << "ABORTED to TC record active with new transaction" << endl;
6769 #endif
6770  break;
6771  case 2:
6772  jam();
6773 #ifdef ABORT_TRACE
6774  ndbout << "ABORTED to active TC record not expecting ABORTED" << endl;
6775 #endif
6776  break;
6777  case 3:
6778  jam();
6779 #ifdef ABORT_TRACE
6780  ndbout << "ABORTED to TC rec active with trans but wrong node" << endl;
6781  ndbout << "This is ok when aborting in node failure situations" << endl;
6782 #endif
6783  break;
6784  case 4:
6785  jam();
6786 #ifdef ABORT_TRACE
6787  ndbout << "Received COMMITTED in wrong state in Dbtc" << endl;
6788 #endif
6789  break;
6790  case 5:
6791  jam();
6792 #ifdef ABORT_TRACE
6793  ndbout << "Received COMMITTED with wrong transid in Dbtc" << endl;
6794 #endif
6795  break;
6796  case 6:
6797  jam();
6798 #ifdef ABORT_TRACE
6799  ndbout << "Received COMPLETED in wrong state in Dbtc" << endl;
6800 #endif
6801  break;
6802  case 7:
6803  jam();
6804 #ifdef ABORT_TRACE
6805  ndbout << "Received COMPLETED with wrong transid in Dbtc" << endl;
6806 #endif
6807  break;
6808  case 8:
6809  jam();
6810 #ifdef ABORT_TRACE
6811  ndbout << "Received COMMITCONF with tc-rec in wrong state in Dbtc" << endl;
6812 #endif
6813  break;
6814  case 9:
6815  jam();
6816 #ifdef ABORT_TRACE
6817  ndbout << "Received COMMITCONF with api-rec in wrong state in Dbtc" <<endl;
6818 #endif
6819  break;
6820  case 10:
6821  jam();
6822 #ifdef ABORT_TRACE
6823  ndbout << "Received COMMITCONF with wrong transid in Dbtc" << endl;
6824 #endif
6825  break;
6826  case 11:
6827  jam();
6828 #ifdef ABORT_TRACE
6829  ndbout << "Received COMMITCONF from wrong nodeid in Dbtc" << endl;
6830 #endif
6831  break;
6832  case 12:
6833  jam();
6834 #ifdef ABORT_TRACE
6835  ndbout << "Received COMPLETECONF, tc-rec in wrong state in Dbtc" << endl;
6836 #endif
6837  break;
6838  case 13:
6839  jam();
6840 #ifdef ABORT_TRACE
6841  ndbout << "Received COMPLETECONF, api-rec in wrong state in Dbtc" << endl;
6842 #endif
6843  break;
6844  case 14:
6845  jam();
6846 #ifdef ABORT_TRACE
6847  ndbout << "Received COMPLETECONF with wrong transid in Dbtc" << endl;
6848 #endif
6849  break;
6850  case 15:
6851  jam();
6852 #ifdef ABORT_TRACE
6853  ndbout << "Received COMPLETECONF from wrong nodeid in Dbtc" << endl;
6854 #endif
6855  break;
6856  case 16:
6857  jam();
6858 #ifdef ABORT_TRACE
6859  ndbout << "Received ABORTCONF, tc-rec in wrong state in Dbtc" << endl;
6860 #endif
6861  break;
6862  case 17:
6863  jam();
6864 #ifdef ABORT_TRACE
6865  ndbout << "Received ABORTCONF, api-rec in wrong state in Dbtc" << endl;
6866 #endif
6867  break;
6868  case 18:
6869  jam();
6870 #ifdef ABORT_TRACE
6871  ndbout << "Received ABORTCONF with wrong transid in Dbtc" << endl;
6872 #endif
6873  break;
6874  case 19:
6875  jam();
6876 #ifdef ABORT_TRACE
6877  ndbout << "Received ABORTCONF from wrong nodeid in Dbtc" << endl;
6878 #endif
6879  break;
6880  case 20:
6881  jam();
6882 #ifdef ABORT_TRACE
6883  ndbout << "Time-out waiting for ABORTCONF in Dbtc" << endl;
6884 #endif
6885  break;
6886  case 21:
6887  jam();
6888 #ifdef ABORT_TRACE
6889  ndbout << "Time-out waiting for COMMITCONF in Dbtc" << endl;
6890 #endif
6891  break;
6892  case 22:
6893  jam();
6894 #ifdef ABORT_TRACE
6895  ndbout << "Time-out waiting for COMPLETECONF in Dbtc" << endl;
6896 #endif
6897  break;
6898  case 23:
6899  jam();
6900 #ifdef ABORT_TRACE
6901  ndbout << "Received LQHKEYCONF in wrong tc-state in Dbtc" << endl;
6902 #endif
6903  break;
6904  case 24:
6905  jam();
6906 #ifdef ABORT_TRACE
6907  ndbout << "Received LQHKEYREF to wrong transid in Dbtc" << endl;
6908 #endif
6909  break;
6910  case 25:
6911  jam();
6912 #ifdef ABORT_TRACE
6913  ndbout << "Received LQHKEYREF in wrong state in Dbtc" << endl;
6914 #endif
6915  break;
6916  case 26:
6917  jam();
6918 #ifdef ABORT_TRACE
6919  ndbout << "Received LQHKEYCONF to wrong transid in Dbtc" << endl;
6920 #endif
6921  break;
6922  case 27:
6923  jam();
6924  // printState(signal, 27);
6925 #ifdef ABORT_TRACE
6926  ndbout << "Received LQHKEYCONF in wrong api-state in Dbtc" << endl;
6927 #endif
6928  break;
6929  case 28:
6930  jam();
6931 #ifdef ABORT_TRACE
6932  ndbout << "Discarding FIRE_TRIG_REF/CONF in Dbtc" << endl;
6933 #endif
6934  break;
6935  case 29:
6936  jam();
6937 #ifdef ABORT_TRACE
6938  ndbout << "Discarding TcContinueB::ZSEND_FIRE_TRIG_REQ in Dbtc" << endl;
6939 #endif
6940  break;
6941  default:
6942  jam();
6943  break;
6944  }//switch
6945  return;
6946 }//Dbtc::warningReport()
6947 
6948 void Dbtc::errorReport(Signal* signal, int place)
6949 {
6950  switch (place) {
6951  case 0:
6952  jam();
6953  break;
6954  case 1:
6955  jam();
6956  break;
6957  case 2:
6958  jam();
6959  break;
6960  case 3:
6961  jam();
6962  break;
6963  case 4:
6964  jam();
6965  break;
6966  case 5:
6967  jam();
6968  break;
6969  case 6:
6970  jam();
6971  break;
6972  default:
6973  jam();
6974  break;
6975  }//switch
6976  systemErrorLab(signal, __LINE__);
6977  return;
6978 }//Dbtc::errorReport()
6979 
6980 /* ------------------------------------------------------------------------- */
6981 /* ------- ENTER ABORTED ------- */
6982 /* */
6983 /*-------------------------------------------------------------------------- */
6984 void Dbtc::execABORTED(Signal* signal)
6985 {
6986  UintR compare_transid1, compare_transid2;
6987 
6988  jamEntry();
6989  tcConnectptr.i = signal->theData[0];
6990  UintR Tnodeid = signal->theData[3];
6991  UintR TlastLqhInd = signal->theData[4];
6992 
6993  if (ERROR_INSERTED(8040)) {
6994  CLEAR_ERROR_INSERT_VALUE;
6995  sendSignalWithDelay(cownref, GSN_ABORTED, signal, 2000, 5);
6996  return;
6997  }//if
6998  /*------------------------------------------------------------------------
6999  * ONE PARTICIPANT IN THE TRANSACTION HAS REPORTED THAT IT IS ABORTED.
7000  *------------------------------------------------------------------------*/
7001  if (tcConnectptr.i >= ctcConnectFilesize) {
7002  errorReport(signal, 0);
7003  return;
7004  }//if
7005  /*-------------------------------------------------------------------------
7006  * WE HAVE TO CHECK THAT THIS IS NOT AN OLD SIGNAL BELONGING TO A
7007  * TRANSACTION ALREADY ABORTED. THIS CAN HAPPEN WHEN TIME-OUT OCCURS
7008  * IN TC WAITING FOR ABORTED.
7009  *-------------------------------------------------------------------------*/
7010  ptrAss(tcConnectptr, tcConnectRecord);
7011  if (tcConnectptr.p->tcConnectstate != OS_ABORT_SENT) {
7012  warningReport(signal, 2);
7013  return;
7014  /*-----------------------------------------------------------------------*/
7015  // ABORTED reported on an operation not expecting ABORT.
7016  /*-----------------------------------------------------------------------*/
7017  }//if
7018  apiConnectptr.i = tcConnectptr.p->apiConnect;
7019  if (apiConnectptr.i >= capiConnectFilesize) {
7020  warningReport(signal, 0);
7021  return;
7022  }//if
7023  ptrAss(apiConnectptr, apiConnectRecord);
7024  compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
7025  compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
7026  compare_transid1 = compare_transid1 | compare_transid2;
7027  if (compare_transid1 != 0) {
7028  warningReport(signal, 1);
7029  return;
7030  }//if
7031  if (ERROR_INSERTED(8024)) {
7032  jam();
7033  systemErrorLab(signal, __LINE__);
7034  }//if
7035 
7039  clearCommitAckMarker(apiConnectptr.p, tcConnectptr.p);
7040 
7041  Uint32 i;
7042  Uint32 Tfound = 0;
7043  for (i = 0; i < tcConnectptr.p->noOfNodes; i++) {
7044  jam();
7045  if (tcConnectptr.p->tcNodedata[i] == Tnodeid) {
7046  /*---------------------------------------------------------------------
7047  * We have received ABORTED from one of the participants in this
7048  * operation in this aborted transaction.
7049  * Record all nodes that have completed abort.
7050  * If last indicator is set it means that no more replica has
7051  * heard of the operation and are thus also aborted.
7052  *---------------------------------------------------------------------*/
7053  jam();
7054  Tfound = 1;
7055  clearTcNodeData(signal, TlastLqhInd, i);
7056  }//if
7057  }//for
7058  if (Tfound == 0) {
7059  warningReport(signal, 3);
7060  return;
7061  }
7062  for (i = 0; i < tcConnectptr.p->noOfNodes; i++) {
7063  if (tcConnectptr.p->tcNodedata[i] != 0) {
7064  /*--------------------------------------------------------------------
7065  * There are still outstanding ABORTED's to wait for.
7066  *--------------------------------------------------------------------*/
7067  jam();
7068  return;
7069  }//if
7070  }//for
7071  tcConnectptr.p->noOfNodes = 0;
7072  tcConnectptr.p->tcConnectstate = OS_ABORTING;
7073  setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7074  apiConnectptr.p->counter--;
7075  if (apiConnectptr.p->counter > 0) {
7076  jam();
7077  /*----------------------------------------------------------------------
7078  * WE ARE STILL WAITING FOR MORE PARTICIPANTS TO SEND ABORTED.
7079  *----------------------------------------------------------------------*/
7080  return;
7081  }//if
7082  /*------------------------------------------------------------------------*/
7083  /* */
7084  /* WE HAVE NOW COMPLETED THE ABORT PROCESS. WE HAVE RECEIVED ABORTED */
7085  /* FROM ALL PARTICIPANTS IN THE TRANSACTION. WE CAN NOW RELEASE ALL */
7086  /* RESOURCES CONNECTED TO THE TRANSACTION AND SEND THE ABORT RESPONSE */
7087  /*------------------------------------------------------------------------*/
7088  releaseAbortResources(signal);
7089 }//Dbtc::execABORTED()
7090 
7091 void Dbtc::clearTcNodeData(Signal* signal,
7092  UintR TLastLqhIndicator,
7093  UintR Tstart)
7094 {
7095  UintR Ti;
7096  if (TLastLqhIndicator == ZTRUE) {
7097  for (Ti = Tstart ; Ti < tcConnectptr.p->noOfNodes; Ti++) {
7098  jam();
7099  tcConnectptr.p->tcNodedata[Ti] = 0;
7100  }//for
7101  } else {
7102  jam();
7103  tcConnectptr.p->tcNodedata[Tstart] = 0;
7104  }//for
7105 }//clearTcNodeData()
7106 
7107 void Dbtc::abortErrorLab(Signal* signal)
7108 {
7109  ptrGuard(apiConnectptr);
7110  ApiConnectRecord * transP = apiConnectptr.p;
7111  if (transP->apiConnectstate == CS_ABORTING && transP->abortState != AS_IDLE){
7112  jam();
7113  return;
7114  }
7115  transP->returnsignal = RS_TCROLLBACKREP;
7116  if(transP->returncode == 0){
7117  jam();
7118  transP->returncode = terrorCode;
7119  }
7120  abort010Lab(signal);
7121 }//Dbtc::abortErrorLab()
7122 
7123 void Dbtc::abort010Lab(Signal* signal)
7124 {
7125  ApiConnectRecord * transP = apiConnectptr.p;
7126  if (transP->apiConnectstate == CS_ABORTING && transP->abortState != AS_IDLE){
7127  jam();
7128  return;
7129  }
7130  transP->apiConnectstate = CS_ABORTING;
7131  /*------------------------------------------------------------------------*/
7132  /* AN ABORT DECISION HAS BEEN TAKEN FOR SOME REASON. WE NEED TO ABORT */
7133  /* ALL PARTICIPANTS IN THE TRANSACTION. */
7134  /*------------------------------------------------------------------------*/
7135  transP->abortState = AS_ACTIVE;
7136  transP->counter = 0;
7137 
7138  if (transP->firstTcConnect == RNIL) {
7139  jam();
7140  /*--------------------------------------------------------------------*/
7141  /* WE HAVE NO PARTICIPANTS IN THE TRANSACTION. */
7142  /*--------------------------------------------------------------------*/
7143  releaseAbortResources(signal);
7144  return;
7145  }//if
7146  tcConnectptr.i = transP->firstTcConnect;
7147  abort015Lab(signal);
7148 }//Dbtc::abort010Lab()
7149 
7150 /*--------------------------------------------------------------------------*/
7151 /* */
7152 /* WE WILL ABORT ONE NODE PER OPERATION AT A TIME. THIS IS TO KEEP */
7153 /* ERROR HANDLING OF THIS PROCESS FAIRLY SIMPLE AND TRACTABLE. */
7154 /* EVEN IF NO NODE OF THIS PARTICULAR NODE NUMBER NEEDS ABORTION WE */
7155 /* MUST ENSURE THAT ALL NODES ARE CHECKED. THUS A FAULTY NODE DOES */
7156 /* NOT MEAN THAT ALL NODES IN AN OPERATION IS ABORTED. FOR THIS REASON*/
7157 /* WE SET THE TCONTINUE_ABORT TO TRUE WHEN A FAULTY NODE IS DETECTED. */
7158 /*--------------------------------------------------------------------------*/
7159 void Dbtc::abort015Lab(Signal* signal)
7160 {
7161  Uint32 TloopCount = 0;
7162 ABORT020:
7163  jam();
7164  TloopCount++;
7165  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7166  switch (tcConnectptr.p->tcConnectstate) {
7167  case OS_WAIT_DIH:
7168  case OS_WAIT_KEYINFO:
7169  case OS_WAIT_ATTR:
7170  jam();
7171  /*----------------------------------------------------------------------*/
7172  /* WE ARE STILL WAITING FOR MORE KEYINFO/ATTRINFO. WE HAVE NOT CONTACTED*/
7173  /* ANY LQH YET AND SO WE CAN SIMPLY SET STATE TO ABORTING. */
7174  /*----------------------------------------------------------------------*/
7175  tcConnectptr.p->noOfNodes = 0; // == releaseAbort(signal)
7176  tcConnectptr.p->tcConnectstate = OS_ABORTING;
7177  break;
7178  case OS_CONNECTED:
7179  jam();
7180  /*-----------------------------------------------------------------------
7181  * WE ARE STILL IN THE INITIAL PHASE OF THIS OPERATION.
7182  * NEED NOT BOTHER ABOUT ANY LQH ABORTS.
7183  *-----------------------------------------------------------------------*/
7184  tcConnectptr.p->noOfNodes = 0; // == releaseAbort(signal)
7185  tcConnectptr.p->tcConnectstate = OS_ABORTING;
7186  break;
7187  case OS_PREPARED:
7188  jam();
7189  case OS_OPERATING:
7190  jam();
7191  case OS_FIRE_TRIG_REQ:
7192  jam();
7193  /*----------------------------------------------------------------------
7194  * WE HAVE SENT LQHKEYREQ AND ARE IN SOME STATE OF EITHER STILL
7195  * SENDING THE OPERATION, WAITING FOR REPLIES, WAITING FOR MORE
7196  * ATTRINFO OR OPERATION IS PREPARED. WE NEED TO ABORT ALL LQH'S.
7197  *----------------------------------------------------------------------*/
7198  releaseAndAbort(signal);
7199  tcConnectptr.p->tcConnectstate = OS_ABORT_SENT;
7200  TloopCount += 127;
7201  break;
7202  case OS_ABORTING:
7203  jam();
7204  break;
7205  case OS_ABORT_SENT:
7206  jam();
7207  DEBUG("ABORT_SENT state in abort015Lab(), not expected");
7208  systemErrorLab(signal, __LINE__);
7209  return;
7210  default:
7211  jam();
7212  DEBUG("tcConnectstate = " << tcConnectptr.p->tcConnectstate);
7213  systemErrorLab(signal, __LINE__);
7214  return;
7215  }//switch
7216 
7217  if (tcConnectptr.p->nextTcConnect != RNIL) {
7218  jam();
7219  tcConnectptr.i = tcConnectptr.p->nextTcConnect;
7220  if (TloopCount < 1024 && !
7221  (ERROR_INSERTED(8089)))
7222  {
7223  goto ABORT020;
7224  }
7225  else
7226  {
7227  jam();
7228  /*---------------------------------------------------------------------
7229  * Reset timer to avoid time-out in real-time break.
7230  * Increase counter to ensure that we don't think that all ABORTED have
7231  * been received before all have been sent.
7232  *---------------------------------------------------------------------*/
7233  apiConnectptr.p->counter++;
7234  setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7235  signal->theData[0] = TcContinueB::ZABORT_BREAK;
7236  signal->theData[1] = tcConnectptr.i;
7237  signal->theData[2] = apiConnectptr.i;
7238  if (ERROR_INSERTED(8089))
7239  {
7240  sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 100, 3);
7241  return;
7242  }
7243  sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
7244  return;
7245  }//if
7246  }//if
7247 
7248  if (ERROR_INSERTED(8089))
7249  {
7250  CLEAR_ERROR_INSERT_VALUE;
7251  }
7252 
7253  if (apiConnectptr.p->counter > 0) {
7254  jam();
7255  setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7256  return;
7257  }//if
7258  /*-----------------------------------------------------------------------
7259  * WE HAVE NOW COMPLETED THE ABORT PROCESS. WE HAVE RECEIVED ABORTED
7260  * FROM ALL PARTICIPANTS IN THE TRANSACTION. WE CAN NOW RELEASE ALL
7261  * RESOURCES CONNECTED TO THE TRANSACTION AND SEND THE ABORT RESPONSE
7262  *------------------------------------------------------------------------*/
7263  releaseAbortResources(signal);
7264 }//Dbtc::abort015Lab()
7265 
7266 /*--------------------------------------------------------------------------*/
7267 /* RELEASE KEY AND ATTRINFO OBJECTS AND SEND ABORT TO THE LQH BLOCK. */
7268 /*--------------------------------------------------------------------------*/
7269 int Dbtc::releaseAndAbort(Signal* signal)
7270 {
7271  HostRecordPtr localHostptr;
7272  UintR TnoLoops = tcConnectptr.p->noOfNodes;
7273 
7274  apiConnectptr.p->counter++;
7275  bool prevAlive = false;
7276  for (Uint32 Ti = 0; Ti < TnoLoops ; Ti++) {
7277  localHostptr.i = tcConnectptr.p->tcNodedata[Ti];
7278  ptrCheckGuard(localHostptr, chostFilesize, hostRecord);
7279  if (localHostptr.p->hostStatus == HS_ALIVE) {
7280  jam();
7281  if (prevAlive) {
7282  // if previous is alive, its LQH forwards abort to this node
7283  jam();
7284  continue;
7285  }
7286  /* ************< */
7287  /* ABORT < */
7288  /* ************< */
7289  Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
7290  tblockref = numberToRef(DBLQH, instanceKey, localHostptr.i);
7291  signal->theData[0] = tcConnectptr.i;
7292  signal->theData[1] = cownref;
7293  signal->theData[2] = apiConnectptr.p->transid[0];
7294  signal->theData[3] = apiConnectptr.p->transid[1];
7295  sendSignal(tblockref, GSN_ABORT, signal, 4, JBB);
7296  prevAlive = true;
7297  } else {
7298  jam();
7299  signal->theData[0] = tcConnectptr.i;
7300  signal->theData[1] = apiConnectptr.p->transid[0];
7301  signal->theData[2] = apiConnectptr.p->transid[1];
7302  signal->theData[3] = localHostptr.i;
7303  signal->theData[4] = ZFALSE;
7304  sendSignal(cownref, GSN_ABORTED, signal, 5, JBB);
7305  prevAlive = false;
7306  }//if
7307  }//for
7308  return 1;
7309 }//Dbtc::releaseAndAbort()
7310 
7311 /* ------------------------------------------------------------------------- */
7312 /* ------- ENTER TIME_SIGNAL ------- */
7313 /* */
7314 /* ------------------------------------------------------------------------- */
7315 void Dbtc::execTIME_SIGNAL(Signal* signal)
7316 {
7317 
7318  jamEntry();
7319  ctcTimer++;
7320  if (csystemStart != SSS_TRUE) {
7321  jam();
7322  return;
7323  }//if
7324  checkStartTimeout(signal);
7325  checkStartFragTimeout(signal);
7326 }//Dbtc::execTIME_SIGNAL()
7327 
7328 /*------------------------------------------------*/
7329 /* Start timeout handling if not already going on */
7330 /*------------------------------------------------*/
7331 void Dbtc::checkStartTimeout(Signal* signal)
7332 {
7333  ctimeOutCheckCounter++;
7334  if (ctimeOutCheckActive == TOCS_TRUE) {
7335  jam();
7336  // Check heartbeat of timeout loop
7337  if(ctimeOutCheckHeartbeat > ctimeOutCheckLastHeartbeat){
7338  jam();
7339  ctimeOutMissedHeartbeats = 0;
7340  }else{
7341  jam();
7342  ctimeOutMissedHeartbeats++;
7343  if (ctimeOutMissedHeartbeats > 100){
7344  jam();
7345  systemErrorLab(signal, __LINE__);
7346  }
7347  }
7348  ctimeOutCheckLastHeartbeat = ctimeOutCheckHeartbeat;
7349  return;
7350  }//if
7351  if (ctimeOutCheckCounter < ctimeOutCheckDelay) {
7352  jam();
7353  /*------------------------------------------------------------------*/
7354  /* */
7355  /* NO TIME-OUT CHECKED THIS TIME. WAIT MORE. */
7356  /*------------------------------------------------------------------*/
7357  return;
7358  }//if
7359  ctimeOutCheckActive = TOCS_TRUE;
7360  ctimeOutCheckCounter = 0;
7361  timeOutLoopStartLab(signal, 0); // 0 is first api connect record
7362  return;
7363 }//Dbtc::execTIME_SIGNAL()
7364 
7365 /*----------------------------------------------------------------*/
7366 /* Start fragment (scan) timeout handling if not already going on */
7367 /*----------------------------------------------------------------*/
7368 void Dbtc::checkStartFragTimeout(Signal* signal)
7369 {
7370  ctimeOutCheckFragCounter++;
7371  if (ctimeOutCheckFragActive == TOCS_TRUE) {
7372  jam();
7373  return;
7374  }//if
7375  if (ctimeOutCheckFragCounter < ctimeOutCheckDelay) {
7376  jam();
7377  /*------------------------------------------------------------------*/
7378  /* NO TIME-OUT CHECKED THIS TIME. WAIT MORE. */
7379  /*------------------------------------------------------------------*/
7380  return;
7381  }//if
7382 
7383  // Go through the fragment records and look for timeout in a scan.
7384  ctimeOutCheckFragActive = TOCS_TRUE;
7385  ctimeOutCheckFragCounter = 0;
7386  timeOutLoopStartFragLab(signal, 0); // 0 means first scan record
7387 }//checkStartFragTimeout()
7388 
7389 /*------------------------------------------------------------------*/
7390 /* IT IS NOW TIME TO CHECK WHETHER ANY TRANSACTIONS HAVE */
7391 /* BEEN DELAYED FOR SO LONG THAT WE ARE FORCED TO PERFORM */
7392 /* SOME ACTION, EITHER ABORT OR RESEND OR REMOVE A NODE FROM */
7393 /* THE WAITING PART OF A PROTOCOL. */
7394 /*
7395 The algorithm used here is to check 1024 transactions at a time before
7396 doing a real-time break.
7397 To avoid aborting both transactions in a deadlock detected by time-out
7398 we insert a random extra time-out of upto 630 ms by using the lowest
7399 six bits of the api connect reference.
7400 We spread it out from 0 to 630 ms if base time-out is larger than 3 sec,
7401 we spread it out from 0 to 70 ms if base time-out is smaller than 300 msec,
7402 and otherwise we spread it out 310 ms.
7403 */
7404 /*------------------------------------------------------------------*/
7405 void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 api_con_ptr)
7406 {
7407  Uint32 end_ptr, time_passed, time_out_value, mask_value;
7408  Uint32 old_mask_value= 0;
7409  const Uint32 api_con_sz= capiConnectFilesize;
7410  const Uint32 tc_timer= ctcTimer;
7411  const Uint32 time_out_param= ctimeOutValue;
7412  const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue;
7413 
7414  ctimeOutCheckHeartbeat = tc_timer;
7415 
7416  if (api_con_ptr + 1024 < api_con_sz) {
7417  jam();
7418  end_ptr= api_con_ptr + 1024;
7419  } else {
7420  jam();
7421  end_ptr= api_con_sz;
7422  }
7423  if (time_out_param > 300) {
7424  jam();
7425  mask_value= 63;
7426  } else if (time_out_param < 30) {
7427  jam();
7428  mask_value= 7;
7429  } else {
7430  jam();
7431  mask_value= 31;
7432  }
7433  if (time_out_param != old_time_out_param &&
7434  getNodeState().getSingleUserMode())
7435  {
7436  // abort during single user mode, use old_mask_value as flag
7437  // and calculate value to be used for connections with allowed api
7438  if (old_time_out_param > 300) {
7439  jam();
7440  old_mask_value= 63;
7441  } else if (old_time_out_param < 30) {
7442  jam();
7443  old_mask_value= 7;
7444  } else {
7445  jam();
7446  old_mask_value= 31;
7447  }
7448  }
7449  for ( ; api_con_ptr < end_ptr; api_con_ptr++) {
7450  Uint32 api_timer= getApiConTimer(api_con_ptr);
7451  jam();
7452  if (api_timer != 0) {
7453  Uint32 error= ZTIME_OUT_ERROR;
7454  time_out_value= time_out_param + (ndb_rand() & mask_value);
7455  if (unlikely(old_mask_value)) // abort during single user mode
7456  {
7457  apiConnectptr.i = api_con_ptr;
7458  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
7459  if ((getNodeState().getSingleUserApi() ==
7460  refToNode(apiConnectptr.p->ndbapiBlockref)) ||
7461  !(apiConnectptr.p->singleUserMode & (1 << NDB_SUM_LOCKED)))
7462  {
7463  // api allowed during single user, use original timeout
7464  time_out_value=
7465  old_time_out_param + (api_con_ptr & old_mask_value);
7466  }
7467  else
7468  {
7469  error= ZCLUSTER_IN_SINGLEUSER_MODE;
7470  }
7471  }
7472  time_passed= tc_timer - api_timer;
7473  if (time_passed > time_out_value)
7474  {
7475  jam();
7476  timeOutFoundLab(signal, api_con_ptr, error);
7477  api_con_ptr++;
7478  break;
7479  }
7480  }
7481  }
7482  if (api_con_ptr == api_con_sz) {
7483  jam();
7484  /*------------------------------------------------------------------*/
7485  /* */
7486  /* WE HAVE NOW CHECKED ALL TRANSACTIONS FOR TIME-OUT AND ALSO */
7487  /* STARTED TIME-OUT HANDLING OF THOSE WE FOUND. WE ARE NOW */
7488  /* READY AND CAN WAIT FOR THE NEXT TIME-OUT CHECK. */
7489  /*------------------------------------------------------------------*/
7490  ctimeOutCheckActive = TOCS_FALSE;
7491  } else {
7492  jam();
7493  sendContinueTimeOutControl(signal, api_con_ptr);
7494  }
7495  return;
7496 }//Dbtc::timeOutLoopStartLab()
7497 
7498 void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr, Uint32 errCode)
7499 {
7500  apiConnectptr.i = TapiConPtr;
7501  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
7502  /*------------------------------------------------------------------*/
7503  /* */
7504  /* THIS TRANSACTION HAVE EXPERIENCED A TIME-OUT AND WE NEED TO*/
7505  /* FIND OUT WHAT WE NEED TO DO BASED ON THE STATE INFORMATION.*/
7506  /*------------------------------------------------------------------*/
7507  DEBUG("[ H'" << hex << apiConnectptr.p->transid[0]
7508  << " H'" << apiConnectptr.p->transid[1] << "] " << dec
7509  << "Time-out in state = " << apiConnectptr.p->apiConnectstate
7510  << " apiConnectptr.i = " << apiConnectptr.i
7511  << " - exec: "
7512  << tc_testbit(apiConnectptr.p->m_flags, ApiConnectRecord::TF_EXEC_FLAG)
7513  << " - place: " << c_apiConTimer_line[apiConnectptr.i]
7514  << " code: " << errCode);
7515  switch (apiConnectptr.p->apiConnectstate) {
7516  case CS_STARTED:
7517  if(apiConnectptr.p->lqhkeyreqrec == apiConnectptr.p->lqhkeyconfrec &&
7518  errCode != ZCLUSTER_IN_SINGLEUSER_MODE){
7519  jam();
7520  /*
7521  We are waiting for application to continue the transaction. In this
7522  particular state we will use the application timeout parameter rather
7523  than the shorter Deadlock detection timeout.
7524  */
7525  if (c_appl_timeout_value == 0 ||
7526  (ctcTimer - getApiConTimer(apiConnectptr.i)) <= c_appl_timeout_value) {
7527  jam();
7528  return;
7529  }//if
7530  }
7531  apiConnectptr.p->returnsignal = RS_TCROLLBACKREP;
7532  apiConnectptr.p->returncode = errCode;
7533  abort010Lab(signal);
7534  return;
7535  case CS_RECEIVING:
7536  case CS_REC_COMMITTING:
7537  case CS_START_COMMITTING:
7538  case CS_WAIT_FIRE_TRIG_REQ:
7539  case CS_SEND_FIRE_TRIG_REQ:
7540  jam();
7541  /*------------------------------------------------------------------*/
7542  /* WE ARE STILL IN THE PREPARE PHASE AND THE TRANSACTION HAS */
7543  /* NOT YET REACHED ITS COMMIT POINT. THUS IT IS NOW OK TO */
7544  /* START ABORTING THE TRANSACTION. ALSO START CHECKING THE */
7545  /* REMAINING TRANSACTIONS. */
7546  /*------------------------------------------------------------------*/
7547  terrorCode = errCode;
7548  abortErrorLab(signal);
7549  return;
7550  case CS_COMMITTING:
7551  jam();
7552  /*------------------------------------------------------------------*/
7553  // We are simply waiting for a signal in the job buffer. Only extreme
7554  // conditions should get us here. We ignore it.
7555  /*------------------------------------------------------------------*/
7556  case CS_COMPLETING:
7557  jam();
7558  /*------------------------------------------------------------------*/
7559  // We are simply waiting for a signal in the job buffer. Only extreme
7560  // conditions should get us here. We ignore it.
7561  /*------------------------------------------------------------------*/
7562  case CS_PREPARE_TO_COMMIT:
7563  {
7564  jam();
7565  /*------------------------------------------------------------------*/
7566  /* WE ARE WAITING FOR DIH TO COMMIT THE TRANSACTION. WE SIMPLY*/
7567  /* KEEP WAITING SINCE THERE IS NO BETTER IDEA ON WHAT TO DO. */
7568  /* IF IT IS BLOCKED THEN NO TRANSACTION WILL PASS THIS GATE. */
7569  // To ensure against strange bugs we crash the system if we have passed
7570  // time-out period by a factor of 10 and it is also at least 5 seconds.
7571  /*------------------------------------------------------------------*/
7572  Uint32 time_passed = ctcTimer - getApiConTimer(apiConnectptr.i);
7573  if (time_passed > 500 &&
7574  time_passed > (5 * cDbHbInterval) &&
7575  time_passed > (10 * ctimeOutValue))
7576  {
7577  jam();
7578  ndbout_c("timeOutFoundLab trans: 0x%x 0x%x state: %u",
7579  apiConnectptr.p->transid[0],
7580  apiConnectptr.p->transid[1],
7581  (Uint32)apiConnectptr.p->apiConnectstate);
7582 
7583  // Reset timeout to not flood log...
7584  setApiConTimer(apiConnectptr.i, 0, __LINE__);
7585  }//if
7586  break;
7587  }
7588  case CS_COMMIT_SENT:
7589  jam();
7590  /*------------------------------------------------------------------*/
7591  /* WE HAVE SENT COMMIT TO A NUMBER OF NODES. WE ARE CURRENTLY */
7592  /* WAITING FOR THEIR REPLY. WITH NODE RECOVERY SUPPORTED WE */
7593  /* WILL CHECK FOR CRASHED NODES AND RESEND THE COMMIT SIGNAL */
7594  /* TO THOSE NODES THAT HAVE MISSED THE COMMIT SIGNAL DUE TO */
7595  /* A NODE FAILURE. */
7596  /*------------------------------------------------------------------*/
7597  tabortInd = ZCOMMIT_SETUP;
7598  setupFailData(signal);
7599  toCommitHandlingLab(signal);
7600  return;
7601  case CS_COMPLETE_SENT:
7602  jam();
7603  /*--------------------------------------------------------------------*/
7604  /* WE HAVE SENT COMPLETE TO A NUMBER OF NODES. WE ARE CURRENTLY */
7605  /* WAITING FOR THEIR REPLY. WITH NODE RECOVERY SUPPORTED WE */
7606  /* WILL CHECK FOR CRASHED NODES AND RESEND THE COMPLETE SIGNAL */
7607  /* TO THOSE NODES THAT HAVE MISSED THE COMPLETE SIGNAL DUE TO */
7608  /* A NODE FAILURE. */
7609  /*--------------------------------------------------------------------*/
7610  tabortInd = ZCOMMIT_SETUP;
7611  setupFailData(signal);
7612  toCompleteHandlingLab(signal);
7613  return;
7614  case CS_ABORTING:
7615  jam();
7616  /*------------------------------------------------------------------*/
7617  /* TIME-OUT DURING ABORT. WE NEED TO SEND ABORTED FOR ALL */
7618  /* NODES THAT HAVE FAILED BEFORE SENDING ABORTED. */
7619  /*------------------------------------------------------------------*/
7620  tcConnectptr.i = apiConnectptr.p->firstTcConnect;
7621  sendAbortedAfterTimeout(signal, 0);
7622  break;
7623  case CS_START_SCAN:{
7624  jam();
7625 
7626  /*
7627  We are waiting for application to continue the transaction. In this
7628  particular state we will use the application timeout parameter rather
7629  than the shorter Deadlock detection timeout.
7630  */
7631  if (c_appl_timeout_value == 0 ||
7632  (ctcTimer - getApiConTimer(apiConnectptr.i)) <= c_appl_timeout_value) {
7633  jam();
7634  return;
7635  }//if
7636 
7637  ScanRecordPtr scanPtr;
7638  scanPtr.i = apiConnectptr.p->apiScanRec;
7639  ptrCheckGuard(scanPtr, cscanrecFileSize, scanRecord);
7640  scanError(signal, scanPtr, ZSCANTIME_OUT_ERROR);
7641  break;
7642  }
7643  case CS_WAIT_ABORT_CONF:
7644  jam();
7645  tcConnectptr.i = apiConnectptr.p->currentTcConnect;
7646  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7647  arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
7648  hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
7649  ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7650  if (hostptr.p->hostStatus == HS_ALIVE) {
7651  /*------------------------------------------------------------------*/
7652  // Time-out waiting for ABORTCONF. We will resend the ABORTREQ just in
7653  // case.
7654  /*------------------------------------------------------------------*/
7655  warningReport(signal, 20);
7656  apiConnectptr.p->timeOutCounter++;
7657  if (apiConnectptr.p->timeOutCounter > 3) {
7658  /*------------------------------------------------------------------*/
7659  // 100 time-outs are not acceptable. We will shoot down the node
7660  // not responding.
7661  /*------------------------------------------------------------------*/
7662  reportNodeFailed(signal, hostptr.i);
7663  }//if
7664  apiConnectptr.p->currentReplicaNo++;
7665  }//if
7666  tcurrentReplicaNo = (Uint8)Z8NIL;
7667  toAbortHandlingLab(signal);
7668  return;
7669  case CS_WAIT_COMMIT_CONF:
7670  jam();
7671  CRASH_INSERTION(8053);
7672  tcConnectptr.i = apiConnectptr.p->currentTcConnect;
7673  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7674  arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
7675  hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
7676  ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7677  if (hostptr.p->hostStatus == HS_ALIVE) {
7678  /*------------------------------------------------------------------*/
7679  // Time-out waiting for COMMITCONF. We will resend the COMMITREQ just in
7680  // case.
7681  /*------------------------------------------------------------------*/
7682  warningReport(signal, 21);
7683  apiConnectptr.p->timeOutCounter++;
7684  if (apiConnectptr.p->timeOutCounter > 3) {
7685  /*------------------------------------------------------------------*/
7686  // 100 time-outs are not acceptable. We will shoot down the node
7687  // not responding.
7688  /*------------------------------------------------------------------*/
7689  reportNodeFailed(signal, hostptr.i);
7690  }//if
7691  apiConnectptr.p->currentReplicaNo++;
7692  }//if
7693  tcurrentReplicaNo = (Uint8)Z8NIL;
7694  toCommitHandlingLab(signal);
7695  return;
7696  case CS_WAIT_COMPLETE_CONF:
7697  jam();
7698  tcConnectptr.i = apiConnectptr.p->currentTcConnect;
7699  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7700  arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
7701  hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
7702  ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7703  if (hostptr.p->hostStatus == HS_ALIVE) {
7704  /*------------------------------------------------------------------*/
7705  // Time-out waiting for COMPLETECONF. We will resend the COMPLETEREQ
7706  // just in case.
7707  /*------------------------------------------------------------------*/
7708  warningReport(signal, 22);
7709  apiConnectptr.p->timeOutCounter++;
7710  if (apiConnectptr.p->timeOutCounter > 100) {
7711  /*------------------------------------------------------------------*/
7712  // 100 time-outs are not acceptable. We will shoot down the node
7713  // not responding.
7714  /*------------------------------------------------------------------*/
7715  reportNodeFailed(signal, hostptr.i);
7716  }//if
7717  apiConnectptr.p->currentReplicaNo++;
7718  }//if
7719  tcurrentReplicaNo = (Uint8)Z8NIL;
7720  toCompleteHandlingLab(signal);
7721  return;
7722  case CS_FAIL_PREPARED:
7723  jam();
7724  case CS_FAIL_COMMITTING:
7725  jam();
7726  case CS_FAIL_COMMITTED:
7727  jam();
7728  case CS_REC_PREPARING:
7729  jam();
7730  case CS_START_PREPARING:
7731  jam();
7732  case CS_PREPARED:
7733  jam();
7734  case CS_RESTART:
7735  jam();
7736  case CS_FAIL_ABORTED:
7737  jam();
7738  case CS_DISCONNECTED:
7739  jam();
7740  default:
7741  jam();
7742  /*------------------------------------------------------------------*/
7743  /* AN IMPOSSIBLE STATE IS SET. CRASH THE SYSTEM. */
7744  /*------------------------------------------------------------------*/
7745  DEBUG("State = " << apiConnectptr.p->apiConnectstate);
7746  systemErrorLab(signal, __LINE__);
7747  return;
7748  }//switch
7749  return;
7750 }//Dbtc::timeOutFoundLab()
7751 
7752 void Dbtc::sendAbortedAfterTimeout(Signal* signal, int Tcheck)
7753 {
7754  ApiConnectRecord * transP = apiConnectptr.p;
7755  if(transP->abortState == AS_IDLE){
7756  jam();
7757  warningEvent("TC: %d: %d state=%d abort==IDLE place: %d fop=%d t: %d",
7758  __LINE__,
7759  apiConnectptr.i,
7760  transP->apiConnectstate,
7761  c_apiConTimer_line[apiConnectptr.i],
7762  transP->firstTcConnect,
7763  c_apiConTimer[apiConnectptr.i]
7764  );
7765  ndbout_c("TC: %d: %d state=%d abort==IDLE place: %d fop=%d t: %d",
7766  __LINE__,
7767  apiConnectptr.i,
7768  transP->apiConnectstate,
7769  c_apiConTimer_line[apiConnectptr.i],
7770  transP->firstTcConnect,
7771  c_apiConTimer[apiConnectptr.i]
7772  );
7773  ndbrequire(false);
7774  setApiConTimer(apiConnectptr.i, 0, __LINE__);
7775  return;
7776  }
7777 
7778  bool found = false;
7779  OperationState tmp[16];
7780 
7781  Uint32 TloopCount = 0;
7782  do {
7783  jam();
7784  if (tcConnectptr.i == RNIL) {
7785  jam();
7786 
7787 #ifdef VM_TRACE
7788  ndbout_c("found: %d Tcheck: %d apiConnectptr.p->counter: %d",
7789  found, Tcheck, apiConnectptr.p->counter);
7790 #endif
7791  if (found || apiConnectptr.p->counter)
7792  {
7793  jam();
7799  return;
7800  }
7801 
7802  if (Tcheck == 1)
7803  {
7804  jam();
7805  releaseAbortResources(signal);
7806  return;
7807  }
7808 
7809  if (Tcheck == 0)
7810  {
7811  jam();
7812  /*------------------------------------------------------------------
7813  * All nodes had already reported ABORTED for all tcConnect records.
7814  * Crash since it is an error situation that we then received a
7815  * time-out.
7816  *------------------------------------------------------------------*/
7817  char buf[96]; buf[0] = 0;
7818  char buf2[96];
7819  BaseString::snprintf(buf, sizeof(buf), "TC %d: %d counter: %d ops:",
7820  __LINE__, apiConnectptr.i,
7821  apiConnectptr.p->counter);
7822  for(Uint32 i = 0; i<TloopCount; i++)
7823  {
7824  BaseString::snprintf(buf2, sizeof(buf2), "%s %d", buf, tmp[i]);
7825  BaseString::snprintf(buf, sizeof(buf), "%s", buf2);
7826  }
7827  warningEvent("%s", buf);
7828  ndbout_c("%s", buf);
7829  ndbrequire(false);
7830  releaseAbortResources(signal);
7831  return;
7832  }
7833 
7834  return;
7835  }//if
7836  TloopCount++;
7837  if (TloopCount >= 1024) {
7838  jam();
7839  /*------------------------------------------------------------------*/
7840  // Insert a real-time break for large transactions to avoid blowing
7841  // away the job buffer.
7842  /*------------------------------------------------------------------*/
7843  setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7844  apiConnectptr.p->counter++;
7845  signal->theData[0] = TcContinueB::ZABORT_TIMEOUT_BREAK;
7846  signal->theData[1] = tcConnectptr.i;
7847  signal->theData[2] = apiConnectptr.i;
7848  if (ERROR_INSERTED(8080))
7849  {
7850  ndbout_c("sending ZABORT_TIMEOUT_BREAK delayed (%d %d)",
7851  Tcheck, apiConnectptr.p->counter);
7852  sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 2000, 3);
7853  }
7854  else
7855  {
7856  sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
7857  }
7858  return;
7859  }//if
7860  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7861  if(TloopCount < 16){
7862  jam();
7863  tmp[TloopCount-1] = tcConnectptr.p->tcConnectstate;
7864  }
7865 
7866  if (tcConnectptr.p->tcConnectstate == OS_ABORT_SENT) {
7867  jam();
7868  /*------------------------------------------------------------------*/
7869  // We have sent an ABORT signal to this node but not yet received any
7870  // reply. We have to send an ABORTED signal on our own in some cases.
7871  // If the node is declared as up and running and still do not respond
7872  // in time to the ABORT signal we will declare it as dead.
7873  /*------------------------------------------------------------------*/
7874  UintR Ti = 0;
7875  arrGuard(tcConnectptr.p->noOfNodes, MAX_REPLICAS+1);
7876  for (Ti = 0; Ti < tcConnectptr.p->noOfNodes; Ti++) {
7877  jam();
7878  if (tcConnectptr.p->tcNodedata[Ti] != 0) {
7879  TloopCount += 31;
7880  found = true;
7881  hostptr.i = tcConnectptr.p->tcNodedata[Ti];
7882  ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7883  if (hostptr.p->hostStatus == HS_ALIVE) {
7884  jam();
7885  /*---------------------------------------------------------------
7886  * A backup replica has not sent ABORTED.
7887  * Could be that a node before him has crashed.
7888  * Send an ABORT signal specifically to this node.
7889  * We will not send to any more nodes after this
7890  * to avoid race problems.
7891  * To also ensure that we use this message also as a heartbeat
7892  * we will move this node to the primary replica seat.
7893  * The primary replica and any failed node after it will
7894  * be removed from the node list. Update also number of nodes.
7895  * Finally break the loop to ensure we don't mess
7896  * things up by executing another loop.
7897  * We also update the timer to ensure we don't get time-out
7898  * too early.
7899  *--------------------------------------------------------------*/
7900  Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
7901  BlockReference TBRef = numberToRef(DBLQH, instanceKey, hostptr.i);
7902  signal->theData[0] = tcConnectptr.i;
7903  signal->theData[1] = cownref;
7904  signal->theData[2] = apiConnectptr.p->transid[0];
7905  signal->theData[3] = apiConnectptr.p->transid[1];
7906  sendSignal(TBRef, GSN_ABORT, signal, 4, JBB);
7907  setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7908  break;
7909  } else {
7910  jam();
7911  /*--------------------------------------------------------------
7912  * The node we are waiting for is dead. We will send ABORTED to
7913  * ourselves vicarious for the failed node.
7914  *--------------------------------------------------------------*/
7915  setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7916  signal->theData[0] = tcConnectptr.i;
7917  signal->theData[1] = apiConnectptr.p->transid[0];
7918  signal->theData[2] = apiConnectptr.p->transid[1];
7919  signal->theData[3] = hostptr.i;
7920  signal->theData[4] = ZFALSE;
7921  sendSignal(cownref, GSN_ABORTED, signal, 5, JBB);
7922  }//if
7923  }//if
7924  }//for
7925  }//if
7926  tcConnectptr.i = tcConnectptr.p->nextTcConnect;
7927  } while (1);
7928 }//Dbtc::sendAbortedAfterTimeout()
7929 
7930 void Dbtc::reportNodeFailed(Signal* signal, Uint32 nodeId)
7931 {
7932  DisconnectRep * const rep = (DisconnectRep *)&signal->theData[0];
7933  rep->nodeId = nodeId;
7934  rep->err = DisconnectRep::TcReportNodeFailed;
7935  sendSignal(QMGR_REF, GSN_DISCONNECT_REP, signal,
7936  DisconnectRep::SignalLength, JBB);
7937 }//Dbtc::reportNodeFailed()
7938 
7939 /*-------------------------------------------------*/
7940 /* Timeout-loop for scanned fragments. */
7941 /*-------------------------------------------------*/
7942 void Dbtc::timeOutLoopStartFragLab(Signal* signal, Uint32 TscanConPtr)
7943 {
7944  ScanFragRecPtr timeOutPtr[8];
7945  UintR tfragTimer[8];
7946  UintR texpiredTime[8];
7947  UintR TloopCount = 0;
7948  Uint32 TtcTimer = ctcTimer;
7949 
7950  while ((TscanConPtr + 8) < cscanFragrecFileSize) {
7951  jam();
7952  timeOutPtr[0].i = TscanConPtr + 0;
7953  timeOutPtr[1].i = TscanConPtr + 1;
7954  timeOutPtr[2].i = TscanConPtr + 2;
7955  timeOutPtr[3].i = TscanConPtr + 3;
7956  timeOutPtr[4].i = TscanConPtr + 4;
7957  timeOutPtr[5].i = TscanConPtr + 5;
7958  timeOutPtr[6].i = TscanConPtr + 6;
7959  timeOutPtr[7].i = TscanConPtr + 7;
7960 
7961  c_scan_frag_pool.getPtrForce(timeOutPtr[0]);
7962  c_scan_frag_pool.getPtrForce(timeOutPtr[1]);
7963  c_scan_frag_pool.getPtrForce(timeOutPtr[2]);
7964  c_scan_frag_pool.getPtrForce(timeOutPtr[3]);
7965  c_scan_frag_pool.getPtrForce(timeOutPtr[4]);
7966  c_scan_frag_pool.getPtrForce(timeOutPtr[5]);
7967  c_scan_frag_pool.getPtrForce(timeOutPtr[6]);
7968  c_scan_frag_pool.getPtrForce(timeOutPtr[7]);
7969 
7970  tfragTimer[0] = timeOutPtr[0].p->scanFragTimer;
7971  tfragTimer[1] = timeOutPtr[1].p->scanFragTimer;
7972  tfragTimer[2] = timeOutPtr[2].p->scanFragTimer;
7973  tfragTimer[3] = timeOutPtr[3].p->scanFragTimer;
7974  tfragTimer[4] = timeOutPtr[4].p->scanFragTimer;
7975  tfragTimer[5] = timeOutPtr[5].p->scanFragTimer;
7976  tfragTimer[6] = timeOutPtr[6].p->scanFragTimer;
7977  tfragTimer[7] = timeOutPtr[7].p->scanFragTimer;
7978 
7979  texpiredTime[0] = TtcTimer - tfragTimer[0];
7980  texpiredTime[1] = TtcTimer - tfragTimer[1];
7981  texpiredTime[2] = TtcTimer - tfragTimer[2];
7982  texpiredTime[3] = TtcTimer - tfragTimer[3];
7983  texpiredTime[4] = TtcTimer - tfragTimer[4];
7984  texpiredTime[5] = TtcTimer - tfragTimer[5];
7985  texpiredTime[6] = TtcTimer - tfragTimer[6];
7986  texpiredTime[7] = TtcTimer - tfragTimer[7];
7987 
7988  for (Uint32 Ti = 0; Ti < 8; Ti++) {
7989  jam();
7990  if (tfragTimer[Ti] != 0) {
7991 
7992  if (texpiredTime[Ti] > ctimeOutValue) {
7993  jam();
7994  DEBUG("Fragment timeout found:"<<
7995  " ctimeOutValue=" <<ctimeOutValue
7996  <<", texpiredTime="<<texpiredTime[Ti]<<endl
7997  <<" tfragTimer="<<tfragTimer[Ti]
7998  <<", ctcTimer="<<ctcTimer);
7999  timeOutFoundFragLab(signal, TscanConPtr + Ti);
8000  return;
8001  }//if
8002  }//if
8003  }//for
8004  TscanConPtr += 8;
8005  /*----------------------------------------------------------------*/
8006  /* We split the process up checking 1024 fragmentrecords at a time*/
8007  /* to maintain real time behaviour. */
8008  /*----------------------------------------------------------------*/
8009  if (TloopCount++ > 128 ) {
8010  jam();
8011  signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL;
8012  signal->theData[1] = TscanConPtr;
8013  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
8014  return;
8015  }//if
8016  }//while
8017  for ( ; TscanConPtr < cscanFragrecFileSize; TscanConPtr++){
8018  jam();
8019  timeOutPtr[0].i = TscanConPtr;
8020  c_scan_frag_pool.getPtrForce(timeOutPtr[0]);
8021  if (timeOutPtr[0].p->scanFragTimer != 0) {
8022  texpiredTime[0] = ctcTimer - timeOutPtr[0].p->scanFragTimer;
8023  if (texpiredTime[0] > ctimeOutValue) {
8024  jam();
8025  DEBUG("Fragment timeout found:"<<
8026  " ctimeOutValue=" <<ctimeOutValue
8027  <<", texpiredTime="<<texpiredTime[0]<<endl
8028  <<" tfragTimer="<<tfragTimer[0]
8029  <<", ctcTimer="<<ctcTimer);
8030  timeOutFoundFragLab(signal, TscanConPtr);
8031  return;
8032  }//if
8033  }//if
8034  }//for
8035  ctimeOutCheckFragActive = TOCS_FALSE;
8036 
8037  return;
8038 }//timeOutLoopStartFragLab()
8039 
8040 /*--------------------------------------------------------------------------*/
8041 /*Handle the heartbeat signal from LQH in a scan process */
8042 // (Set timer on fragrec.)
8043 /*--------------------------------------------------------------------------*/
8044 void Dbtc::execSCAN_HBREP(Signal* signal)
8045 {
8046  jamEntry();
8047 
8048  scanFragptr.i = signal->theData[0];
8049  c_scan_frag_pool.getPtr(scanFragptr);
8050  switch (scanFragptr.p->scanFragState){
8051  case ScanFragRec::LQH_ACTIVE:
8052  break;
8053  default:
8054  DEBUG("execSCAN_HBREP: scanFragState="<<scanFragptr.p->scanFragState);
8055  systemErrorLab(signal, __LINE__);
8056  break;
8057  }
8058 
8059  ScanRecordPtr scanptr;
8060  scanptr.i = scanFragptr.p->scanRec;
8061  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
8062 
8063  apiConnectptr.i = scanptr.p->scanApiRec;
8064  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
8065 
8066  if (!(apiConnectptr.p->transid[0] == signal->theData[1] &&
8067  apiConnectptr.p->transid[1] == signal->theData[2])){
8068  jam();
8072  // Save original transid
8073  signal->theData[3] = signal->theData[0];
8074  signal->theData[4] = signal->theData[1];
8075  // Set transid to illegal values
8076  signal->theData[1] = RNIL;
8077  signal->theData[2] = RNIL;
8078 
8079  sendSignal(signal->senderBlockRef(), GSN_SCAN_HBREP, signal, 5, JBA);
8080  DEBUG("SCAN_HBREP with wrong transid("
8081  <<signal->theData[3]<<", "<<signal->theData[4]<<")");
8082  return;
8083  }//if
8084 
8085  // Update timer on ScanFragRec
8086  if (scanFragptr.p->scanFragTimer != 0){
8087  updateBuddyTimer(apiConnectptr);
8088  scanFragptr.p->startFragTimer(ctcTimer);
8089  } else {
8090  ndbassert(false);
8091  DEBUG("SCAN_HBREP when scanFragTimer was turned off");
8092  }
8093 }//execSCAN_HBREP()
8094 
8095 /*--------------------------------------------------------------------------*/
8096 /* Timeout has occured on a fragment which means a scan has timed out. */
8097 /* If this is true we have an error in LQH/ACC. */
8098 /*--------------------------------------------------------------------------*/
8099 void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr)
8100 {
8101  ScanFragRecPtr ptr;
8102  c_scan_frag_pool.getPtr(ptr, TscanConPtr);
8103 #ifdef VM_TRACE
8104  {
8105  ScanRecordPtr scanptr;
8106  scanptr.i = ptr.p->scanRec;
8107  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
8108  ApiConnectRecordPtr TlocalApiConnectptr;
8109  TlocalApiConnectptr.i = scanptr.p->scanApiRec;
8110  ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
8111 
8112  DEBUG("[ H'" << hex << TlocalApiConnectptr.p->transid[0]
8113  << " H'" << TlocalApiConnectptr.p->transid[1] << "] "
8114  << TscanConPtr << " timeOutFoundFragLab: scanFragState = "
8115  << ptr.p->scanFragState);
8116  }
8117 #endif
8118 
8119  const Uint32 time_out_param= ctimeOutValue;
8120  const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue;
8121 
8122  if (unlikely(time_out_param != old_time_out_param &&
8123  getNodeState().getSingleUserMode()))
8124  {
8125  jam();
8126  ScanRecordPtr scanptr;
8127  scanptr.i = ptr.p->scanRec;
8128  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
8129  ApiConnectRecordPtr TlocalApiConnectptr;
8130  TlocalApiConnectptr.i = scanptr.p->scanApiRec;
8131  ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
8132 
8133  if (refToNode(TlocalApiConnectptr.p->ndbapiBlockref) ==
8134  getNodeState().getSingleUserApi())
8135  {
8136  jam();
8137  Uint32 val = ctcTimer - ptr.p->scanFragTimer;
8138  if (val <= old_time_out_param)
8139  {
8140  jam();
8141  goto next;
8142  }
8143  }
8144  }
8145 
8146  /*-------------------------------------------------------------------------*/
8147  // The scan fragment has expired its timeout. Check its state to decide
8148  // what to do.
8149  /*-------------------------------------------------------------------------*/
8150  switch (ptr.p->scanFragState) {
8151  case ScanFragRec::WAIT_GET_PRIMCONF:
8152  jam();
8153  ndbrequire(false);
8154  break;
8155  case ScanFragRec::LQH_ACTIVE:{
8156  jam();
8157 
8161  Uint32 nodeId = refToNode(ptr.p->lqhBlockref);
8162  Uint32 connectCount = getNodeInfo(nodeId).m_connectCount;
8163  ScanRecordPtr scanptr;
8164  scanptr.i = ptr.p->scanRec;
8165  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
8166 
8167  if(connectCount != ptr.p->m_connectCount){
8168  jam();
8172  ptr.p->scanFragState = ScanFragRec::COMPLETED;
8173  ptr.p->stopFragTimer();
8174  {
8175  ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
8176  run.release(ptr);
8177  }
8178  }
8179 
8180  scanError(signal, scanptr, ZSCAN_FRAG_LQH_ERROR);
8181  break;
8182  }
8183  case ScanFragRec::DELIVERED:
8184  jam();
8185  case ScanFragRec::IDLE:
8186  jam();
8187  case ScanFragRec::QUEUED_FOR_DELIVERY:
8188  jam();
8189  /*-----------------------------------------------------------------------
8190  * Should never occur. We will simply report set the timer to zero and
8191  * continue. In a debug version we should crash here but not in a release
8192  * version. In a release version we will simply set the time-out to zero.
8193  *-----------------------------------------------------------------------*/
8194 #ifdef VM_TRACE
8195  systemErrorLab(signal, __LINE__);
8196 #endif
8197  scanFragptr.p->stopFragTimer();
8198  break;
8199  default:
8200  jam();
8201  /*-----------------------------------------------------------------------
8202  * Non-existent state. Crash.
8203  *-----------------------------------------------------------------------*/
8204  systemErrorLab(signal, __LINE__);
8205  break;
8206  }//switch
8207 
8208 next:
8209  signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL;
8210  signal->theData[1] = TscanConPtr + 1;
8211  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
8212  return;
8213 }//timeOutFoundFragLab()
8214 
8215 
8216 /*
8217  4.3.16 GCP_NOMORETRANS
8218  ----------------------
8219 */
8220 /*****************************************************************************
8221  * G C P _ N O M O R E T R A N S
8222  *
8223  * WHEN DBTC RECEIVES SIGNAL GCP_NOMORETRANS A CHECK IS DONE TO FIND OUT IF
8224  * THERE ARE ANY GLOBAL CHECKPOINTS GOING ON - CFIRSTGCP /= RNIL. DBTC THEN
8225  * SEARCHES THE GCP_RECORD FILE TO FIND OUT IF THERE ARE ANY TRANSACTIONS NOT
8226  * CONCLUDED WITH THIS SPECIFIC CHECKPOINT - GCP_PTR:GCP_ID = TCHECK_GCP_ID.
8227  * FOR EACH TRANSACTION WHERE API_CONNECTSTATE EQUALS PREPARED, COMMITTING,
8228  * COMMITTED OR COMPLETING SIGNAL CONTINUEB IS SENT WITH A DELAY OF 100 MS,
8229  * THE COUNTER GCP_PTR:OUTSTANDINGAPI IS INCREASED. WHEN CONTINUEB IS RECEIVED
8230  * THE COUNTER IS DECREASED AND A CHECK IS DONE TO FIND OUT IF ALL
8231  * TRANSACTIONS ARE CONCLUDED. IF SO, SIGNAL GCP_TCFINISHED IS SENT.
8232  *****************************************************************************/
8233 void Dbtc::execGCP_NOMORETRANS(Signal* signal)
8234 {
8235  jamEntry();
8236  GCPNoMoreTrans* req = (GCPNoMoreTrans*)signal->getDataPtr();
8237  c_gcp_ref = req->senderRef;
8238  c_gcp_data = req->senderData;
8239  Uint32 gci_lo = req->gci_lo;
8240  Uint32 gci_hi = req->gci_hi;
8241  tcheckGcpId = gci_lo | (Uint64(gci_hi) << 32);
8242 
8243  Ptr<GcpRecord> gcpPtr;
8244  if (cfirstgcp != RNIL) {
8245  jam();
8246  /* A GLOBAL CHECKPOINT IS GOING ON */
8247  gcpPtr.i = cfirstgcp; /* SET POINTER TO FIRST GCP IN QUEUE*/
8248  ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord);
8249  if (gcpPtr.p->gcpId == tcheckGcpId)
8250  {
8251  jam();
8252  bool empty = gcpPtr.p->firstApiConnect == RNIL;
8253  bool nfhandling = c_ongoing_take_over_cnt;
8254 
8255  if (empty && nfhandling)
8256  {
8257  jam();
8258  ndbout_c("NOT returning gcpTcfinished due to nfhandling %u/%u",
8259  gci_hi, gci_lo);
8260  }
8261 
8262  if (!empty || c_ongoing_take_over_cnt)
8263  {
8264  jam();
8265  gcpPtr.p->gcpNomoretransRec = ZTRUE;
8266  } else {
8267  jam();
8268  gcpTcfinished(signal, tcheckGcpId);
8269  unlinkGcp(gcpPtr);
8270  }//if
8271  }
8272  else if (c_ongoing_take_over_cnt == 0)
8273  {
8274  jam();
8275  /*------------------------------------------------------------*/
8276  /* IF IT IS NOT THE FIRST THEN THERE SHOULD BE NO */
8277  /* RECORD FOR THIS GLOBAL CHECKPOINT. WE ALWAYS REMOVE */
8278  /* THE GLOBAL CHECKPOINTS IN ORDER. */
8279  /*------------------------------------------------------------*/
8280  gcpTcfinished(signal, tcheckGcpId);
8281  }
8282  else
8283  {
8284  jam();
8285  goto outoforder;
8286  }
8287  }
8288  else if (c_ongoing_take_over_cnt == 0)
8289  {
8290  jam();
8291  gcpTcfinished(signal, tcheckGcpId);
8292  }
8293  else
8294  {
8295 seize:
8296  jam();
8297  ndbout_c("execGCP_NOMORETRANS(%u/%u) c_ongoing_take_over_cnt -> seize",
8298  gci_hi, gci_lo);
8299  seizeGcp(gcpPtr, tcheckGcpId);
8300  gcpPtr.p->gcpNomoretransRec = ZTRUE;
8301  }
8302  return;
8303 
8304 outoforder:
8305  printf("ooo: execGCP_NOMORETRANS tcheckGcpId: %u/%u cfirstgcp: %u/%u",
8306  gci_hi, gci_lo,
8307  Uint32(gcpPtr.p->gcpId >> 32), Uint32(gcpPtr.p->gcpId));
8308 
8309  if (tcheckGcpId < gcpPtr.p->gcpId)
8310  {
8311  jam();
8312 
8313  Ptr<GcpRecord> tmp;
8314  tmp.i = cfirstfreeGcp;
8315  ptrCheckGuard(tmp, cgcpFilesize, gcpRecord);
8316  cfirstfreeGcp = tmp.p->nextGcp;
8317 
8318  tmp.p->gcpId = tcheckGcpId;
8319  tmp.p->nextGcp = cfirstgcp;
8320  tmp.p->firstApiConnect = RNIL;
8321  tmp.p->lastApiConnect = RNIL;
8322  tmp.p->gcpNomoretransRec = ZTRUE;
8323  cfirstgcp = tmp.i;
8324  ndbout_c("LINK FIRST");
8325  return;
8326  }
8327  else
8328  {
8329  Ptr<GcpRecord> prev = gcpPtr;
8330  while (tcheckGcpId > gcpPtr.p->gcpId)
8331  {
8332  jam();
8333  if (gcpPtr.p->nextGcp == RNIL)
8334  {
8335  printf("nextGcp == RNIL -> ");
8336  goto seize;
8337  }
8338 
8339  prev = gcpPtr;
8340  gcpPtr.i = gcpPtr.p->nextGcp;
8341  ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord);
8342  }
8343 
8344  if (tcheckGcpId == gcpPtr.p->gcpId)
8345  {
8346  jam();
8347  gcpPtr.p->gcpNomoretransRec = ZTRUE;
8348  ndbout_c("found");
8349  return;
8350  }
8351  ndbrequire(prev.i != gcpPtr.i); // checked earlier with initial "<"
8352  ndbrequire(prev.p->gcpId < tcheckGcpId);
8353  ndbrequire(gcpPtr.p->gcpId > tcheckGcpId);
8354 
8355  Ptr<GcpRecord> tmp;
8356  tmp.i = cfirstfreeGcp;
8357  ptrCheckGuard(tmp, cgcpFilesize, gcpRecord);
8358  cfirstfreeGcp = tmp.p->nextGcp;
8359 
8360  tmp.p->gcpId = tcheckGcpId;
8361  tmp.p->nextGcp = gcpPtr.i;
8362  tmp.p->firstApiConnect = RNIL;
8363  tmp.p->lastApiConnect = RNIL;
8364  tmp.p->gcpNomoretransRec = ZTRUE;
8365  prev.p->nextGcp = tmp.i;
8366  ndbout_c("link middle %u/%u < %u/%u < %u/%u",
8367  Uint32(prev.p->gcpId >> 32), Uint32(prev.p->gcpId),
8368  gci_hi, gci_lo,
8369  Uint32(gcpPtr.p->gcpId >> 32), Uint32(gcpPtr.p->gcpId));
8370  return;
8371  }
8372 }//Dbtc::execGCP_NOMORETRANS()
8373 
8374 /*****************************************************************************/
8375 /* */
8376 /* TAKE OVER MODULE */
8377 /* */
8378 /*****************************************************************************/
8379 /* */
8380 /* THIS PART OF TC TAKES OVER THE COMMIT/ABORT OF TRANSACTIONS WHERE THE */
8381 /* NODE ACTING AS TC HAVE FAILED. IT STARTS BY QUERYING ALL NODES ABOUT */
8382 /* ANY OPERATIONS PARTICIPATING IN A TRANSACTION WHERE THE TC NODE HAVE */
8383 /* FAILED. */
8384 /* */
8385 /* AFTER RECEIVING INFORMATION FROM ALL NODES ABOUT OPERATION STATUS THIS */
8386 /* CODE WILL ENSURE THAT ALL AFFECTED TRANSACTIONS ARE PROPERLY ABORTED OR*/
8387 /* COMMITTED. THE ORIGINATING APPLICATION NODE WILL ALSO BE CONTACTED. */
8388 /* IF THE ORIGINATING APPLICATION ALSO FAILED THEN THERE IS CURRENTLY NO */
8389 /* WAY TO FIND OUT WHETHER A TRANSACTION WAS PERFORMED OR NOT. */
8390 /*****************************************************************************/
8391 void Dbtc::execNODE_FAILREP(Signal* signal)
8392 {
8393  jamEntry();
8394 
8395  NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
8396 
8397  cfailure_nr = nodeFail->failNo;
8398  const Uint32 tnoOfNodes = nodeFail->noOfNodes;
8399  const Uint32 tnewMasterId = nodeFail->masterNodeId;
8400 
8401  arrGuard(tnoOfNodes, MAX_NDB_NODES);
8402  Uint32 i;
8403  int index = 0;
8404  for (i = 1; i< MAX_NDB_NODES; i++)
8405  {
8406  if(NdbNodeBitmask::get(nodeFail->theNodes, i))
8407  {
8408  cdata[index] = i;
8409  index++;
8410  }//if
8411  }//for
8412 
8413  cmasterNodeId = tnewMasterId;
8414 
8415  HostRecordPtr myHostPtr;
8416 
8417  tcNodeFailptr.i = 0;
8418  ptrAss(tcNodeFailptr, tcFailRecord);
8419  for (i = 0; i < tnoOfNodes; i++)
8420  {
8421  jam();
8422  myHostPtr.i = cdata[i];
8423  ptrCheckGuard(myHostPtr, chostFilesize, hostRecord);
8424 
8425  /*------------------------------------------------------------*/
8426  /* SET STATUS OF THE FAILED NODE TO DEAD SINCE IT HAS */
8427  /* FAILED. */
8428  /*------------------------------------------------------------*/
8429  myHostPtr.p->hostStatus = HS_DEAD;
8430  myHostPtr.p->m_nf_bits = HostRecord::NF_NODE_FAIL_BITS;
8431  c_ongoing_take_over_cnt++;
8432  c_alive_nodes.clear(myHostPtr.i);
8433 
8434  if (tcNodeFailptr.p->failStatus == FS_LISTENING)
8435  {
8436  jam();
8437  /*------------------------------------------------------------*/
8438  /* THE CURRENT TAKE OVER CAN BE AFFECTED BY THIS NODE */
8439  /* FAILURE. */
8440  /*------------------------------------------------------------*/
8441  if (myHostPtr.p->lqhTransStatus == LTS_ACTIVE)
8442  {
8443  jam();
8444  /*------------------------------------------------------------*/
8445  /* WE WERE WAITING FOR THE FAILED NODE IN THE TAKE OVER */
8446  /* PROTOCOL FOR TC. */
8447  /*------------------------------------------------------------*/
8448  signal->theData[0] = TcContinueB::ZNODE_TAKE_OVER_COMPLETED;
8449  signal->theData[1] = myHostPtr.i;
8450  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
8451  }//if
8452  }//if
8453 
8454  jam();
8455  signal->theData[0] = myHostPtr.i;
8456  sendSignal(cownref, GSN_TAKE_OVERTCREQ, signal, 1, JBB);
8457 
8458  checkScanActiveInFailedLqh(signal, 0, myHostPtr.i);
8459  nodeFailCheckTransactions(signal, 0, myHostPtr.i);
8460  Callback cb = {safe_cast(&Dbtc::ndbdFailBlockCleanupCallback),
8461  myHostPtr.i};
8462  simBlockNodeFailure(signal, myHostPtr.i, cb);
8463  }
8464 
8465  if (m_deferred_enabled == 0)
8466  {
8467  jam();
8468  Uint32 ok = 1;
8469  for(Uint32 n = c_alive_nodes.find_first();
8470  n != c_alive_nodes.NotFound;
8471  n = c_alive_nodes.find_next(n+1))
8472  {
8473  if (!ndbd_deferred_unique_constraints(getNodeInfo(n).m_version))
8474  {
8475  jam();
8476  ok = 0;
8477  break;
8478  }
8479  }
8480  if (ok)
8481  {
8482  jam();
8483  m_deferred_enabled = ~Uint32(0);
8484  }
8485  }
8486 }//Dbtc::execNODE_FAILREP()
8487 
8488 void
8489 Dbtc::checkNodeFailComplete(Signal* signal,
8490  Uint32 failedNodeId,
8491  Uint32 bit)
8492 {
8493  hostptr.i = failedNodeId;
8494  ptrCheckGuard(hostptr, chostFilesize, hostRecord);
8495  hostptr.p->m_nf_bits &= ~bit;
8496  if (hostptr.p->m_nf_bits == 0)
8497  {
8498  NFCompleteRep * const nfRep = (NFCompleteRep *)&signal->theData[0];
8499  nfRep->blockNo = DBTC;
8500  nfRep->nodeId = cownNodeid;
8501  nfRep->failedNodeId = hostptr.i;
8502 
8503  if (instance() == 0)
8504  {
8505  jam();
8506  sendSignal(cdihblockref, GSN_NF_COMPLETEREP, signal,
8507  NFCompleteRep::SignalLength, JBB);
8508  sendSignal(QMGR_REF, GSN_NF_COMPLETEREP, signal,
8509  NFCompleteRep::SignalLength, JBB);
8510  }
8511  else
8512  {
8516  sendSignal(DBTC_REF, GSN_NF_COMPLETEREP, signal,
8517  NFCompleteRep::SignalLength, JBB);
8518  }
8519  }
8520 
8521  CRASH_INSERTION(8058);
8522  if (ERROR_INSERTED(8059))
8523  {
8524  signal->theData[0] = 9999;
8525  sendSignalWithDelay(numberToRef(CMVMI, hostptr.i),
8526  GSN_NDB_TAMPER, signal, 100, 1);
8527  }
8528 }
8529 
8530 void Dbtc::checkScanActiveInFailedLqh(Signal* signal,
8531  Uint32 scanPtrI,
8532  Uint32 failedNodeId){
8533 
8534  ScanRecordPtr scanptr;
8535  for (scanptr.i = scanPtrI; scanptr.i < cscanrecFileSize; scanptr.i++) {
8536  jam();
8537  ptrAss(scanptr, scanRecord);
8538  bool found = false;
8539  if (scanptr.p->scanState != ScanRecord::IDLE){
8540  jam();
8541  ScanFragRecPtr ptr;
8542  ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
8543 
8544  for(run.first(ptr); !ptr.isNull(); ){
8545  jam();
8546  ScanFragRecPtr curr = ptr;
8547  run.next(ptr);
8548  if (curr.p->scanFragState == ScanFragRec::LQH_ACTIVE &&
8549  refToNode(curr.p->lqhBlockref) == failedNodeId){
8550  jam();
8551 
8552  run.release(curr);
8553  curr.p->scanFragState = ScanFragRec::COMPLETED;
8554  curr.p->stopFragTimer();
8555  found = true;
8556  }
8557  }
8558 
8559  ScanFragList deliv(c_scan_frag_pool, scanptr.p->m_delivered_scan_frags);
8560  for(deliv.first(ptr); !ptr.isNull(); deliv.next(ptr))
8561  {
8562  jam();
8563  if (refToNode(ptr.p->lqhBlockref) == failedNodeId)
8564  {
8565  jam();
8566  found = true;
8567  break;
8568  }
8569  }
8570  }
8571  if(found){
8572  jam();
8573  scanError(signal, scanptr, ZSCAN_LQH_ERROR);
8574  }
8575 
8576  // Send CONTINUEB to continue later
8577  signal->theData[0] = TcContinueB::ZCHECK_SCAN_ACTIVE_FAILED_LQH;
8578  signal->theData[1] = scanptr.i + 1; // Check next scanptr
8579  signal->theData[2] = failedNodeId;
8580  sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
8581  return;
8582  }//for
8583 
8584  checkNodeFailComplete(signal, failedNodeId, HostRecord::NF_CHECK_SCAN);
8585 }
8586 
8587 void
8588 Dbtc::nodeFailCheckTransactions(Signal* signal,
8589  Uint32 transPtrI,
8590  Uint32 failedNodeId)
8591 {
8592  jam();
8593  Ptr<ApiConnectRecord> transPtr;
8594  Uint32 TtcTimer = ctcTimer;
8595  Uint32 TapplTimeout = c_appl_timeout_value;
8596  Uint32 RT_BREAK = 64;
8597  Uint32 endPtrI = transPtrI + RT_BREAK;
8598  if (endPtrI > capiConnectFilesize)
8599  {
8600  endPtrI = capiConnectFilesize;
8601  }
8602 
8603  for (transPtr.i = transPtrI; transPtr.i < endPtrI; transPtr.i++)
8604  {
8605  ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
8606  if (transPtr.p->m_transaction_nodes.get(failedNodeId))
8607  {
8608  jam();
8609 
8610  // Force timeout regardless of state
8611  c_appl_timeout_value = 1;
8612  setApiConTimer(transPtr.i, TtcTimer - 2, __LINE__);
8613  timeOutFoundLab(signal, transPtr.i, ZNODEFAIL_BEFORE_COMMIT);
8614  c_appl_timeout_value = TapplTimeout;
8615 
8616  transPtr.i++;
8617  break;
8618  }
8619  }
8620 
8621  if (transPtr.i == capiConnectFilesize)
8622  {
8623  jam();
8624  checkNodeFailComplete(signal, failedNodeId,
8625  HostRecord::NF_CHECK_TRANSACTION);
8626  }
8627  else
8628  {
8629  signal->theData[0] = TcContinueB::ZNF_CHECK_TRANSACTIONS;
8630  signal->theData[1] = transPtr.i;
8631  signal->theData[2] = failedNodeId;
8632  sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
8633  }
8634 }
8635 
8636 void
8637 Dbtc::ndbdFailBlockCleanupCallback(Signal* signal,
8638  Uint32 failedNodeId,
8639  Uint32 ignoredRc)
8640 {
8641  jamEntry();
8642 
8643  checkNodeFailComplete(signal, failedNodeId,
8644  HostRecord::NF_BLOCK_HANDLE);
8645 }
8646 
8647 void
8648 Dbtc::apiFailBlockCleanupCallback(Signal* signal,
8649  Uint32 failedNodeId,
8650  Uint32 ignoredRc)
8651 {
8652  jamEntry();
8653 
8654  signal->theData[0] = failedNodeId;
8655  signal->theData[1] = reference();
8656  sendSignal(capiFailRef, GSN_API_FAILCONF, signal, 2, JBB);
8657 }
8658 
8659 void
8660 Dbtc::checkScanFragList(Signal* signal,
8661  Uint32 failedNodeId,
8662  ScanRecord * scanP,
8663  ScanFragList::Head & head){
8664 
8665  DEBUG("checkScanActiveInFailedLqh: scanFragError");
8666 }
8667 
8668 void Dbtc::execTAKE_OVERTCCONF(Signal* signal)
8669 {
8670  jamEntry();
8671 
8672  if (!checkNodeFailSequence(signal))
8673  {
8674  jam();
8675  return;
8676  }
8677 
8678  tfailedNodeId = signal->theData[0];
8679  hostptr.i = tfailedNodeId;
8680  ptrCheckGuard(hostptr, chostFilesize, hostRecord);
8681 
8682  Uint32 senderRef = signal->theData[1];
8683  if (signal->getLength() < 2)
8684  {
8685  jam();
8686  senderRef = 0; // currently only used to see if it's from self
8687  }
8688 
8689  if (senderRef != reference())
8690  {
8691  jam();
8692 
8693  tcNodeFailptr.i = 0;
8694  ptrAss(tcNodeFailptr, tcFailRecord);
8695 
8699  Uint32 i = 0;
8700  Uint32 end = tcNodeFailptr.p->queueIndex;
8701  for (; i<end; i++)
8702  {
8703  jam();
8704  if (tcNodeFailptr.p->queueList[i] == hostptr.i)
8705  {
8706  jam();
8707  break;
8708  }
8709  }
8710  ndbrequire(i != end);
8711  tcNodeFailptr.p->queueList[i] = tcNodeFailptr.p->queueList[end-1];
8712  tcNodeFailptr.p->queueIndex = end - 1;
8713  }
8714 
8715  Uint32 cnt = c_ongoing_take_over_cnt;
8716  ndbrequire(cnt);
8717  c_ongoing_take_over_cnt = cnt - 1;
8718  checkNodeFailComplete(signal, hostptr.i, HostRecord::NF_TAKEOVER);
8719 
8720  if (cnt == 1 && cfirstgcp != RNIL)
8721  {
8725  GcpRecordPtr tmpGcpPointer;
8726  tmpGcpPointer.i = cfirstgcp;
8727  ptrCheckGuard(tmpGcpPointer, cgcpFilesize, gcpRecord);
8728  if (tmpGcpPointer.p->gcpNomoretransRec &&
8729  tmpGcpPointer.p->firstApiConnect == RNIL)
8730  {
8731  jam();
8732  ndbout_c("completing gcp %u/%u in execTAKE_OVERTCCONF",
8733  Uint32(tmpGcpPointer.p->gcpId >> 32),
8734  Uint32(tmpGcpPointer.p->gcpId));
8735  gcpTcfinished(signal, tmpGcpPointer.p->gcpId);
8736  unlinkGcp(tmpGcpPointer);
8737  }
8738  }
8739 }//Dbtc::execTAKE_OVERTCCONF()
8740 
8741 void Dbtc::execTAKE_OVERTCREQ(Signal* signal)
8742 {
8743  jamEntry();
8744  tfailedNodeId = signal->theData[0];
8745  tcNodeFailptr.i = 0;
8746  ptrAss(tcNodeFailptr, tcFailRecord);
8747  if (tcNodeFailptr.p->failStatus != FS_IDLE ||
8748  cmasterNodeId != getOwnNodeId() ||
8749  (! (instance() == 0 /* single TC */ ||
8750  instance() == TAKE_OVER_INSTANCE))) /* in mt-TC case let 1 instance
8751  do take-over */
8752  {
8753  jam();
8754  /*------------------------------------------------------------*/
8755  /* WE CAN CURRENTLY ONLY HANDLE ONE TAKE OVER AT A TIME */
8756  /*------------------------------------------------------------*/
8757  /* IF MORE THAN ONE TAKE OVER IS REQUESTED WE WILL */
8758  /* QUEUE THE TAKE OVER AND START IT AS SOON AS THE */
8759  /* PREVIOUS ARE COMPLETED. */
8760  /*------------------------------------------------------------*/
8761  arrGuard(tcNodeFailptr.p->queueIndex, MAX_NDB_NODES);
8762  tcNodeFailptr.p->queueList[tcNodeFailptr.p->queueIndex] = tfailedNodeId;
8763  tcNodeFailptr.p->queueIndex = tcNodeFailptr.p->queueIndex + 1;
8764  return;
8765  }//if
8766  ndbrequire(instance() == 0 || instance() == TAKE_OVER_INSTANCE);
8767  startTakeOverLab(signal);
8768 }//Dbtc::execTAKE_OVERTCREQ()
8769 
8770 /*------------------------------------------------------------*/
8771 /* INITIALISE THE HASH TABLES FOR STORING TRANSACTIONS */
8772 /* AND OPERATIONS DURING TC TAKE OVER. */
8773 /*------------------------------------------------------------*/
8774 void Dbtc::startTakeOverLab(Signal* signal)
8775 {
8776  for (tindex = 0; tindex <= 511; tindex++) {
8777  ctransidFailHash[tindex] = RNIL;
8778  }//for
8779  for (tindex = 0; tindex <= 1023; tindex++) {
8780  ctcConnectFailHash[tindex] = RNIL;
8781  }//for
8782  tcNodeFailptr.p->failStatus = FS_LISTENING;
8783  tcNodeFailptr.p->takeOverNode = tfailedNodeId;
8784  for (hostptr.i = 1; hostptr.i < MAX_NDB_NODES; hostptr.i++) {
8785  jam();
8786  ptrAss(hostptr, hostRecord);
8787  if (hostptr.p->hostStatus == HS_ALIVE) {
8788  jam();
8789  tblockref = calcLqhBlockRef(hostptr.i);
8790  hostptr.p->lqhTransStatus = LTS_ACTIVE;
8791  signal->theData[0] = tcNodeFailptr.i;
8792  signal->theData[1] = cownref;
8793  signal->theData[2] = tfailedNodeId;
8794  if (ERROR_INSERTED(8064) && hostptr.i == getOwnNodeId())
8795  {
8796  ndbout_c("sending delayed GSN_LQH_TRANSREQ to self");
8797  sendSignalWithDelay(tblockref, GSN_LQH_TRANSREQ, signal, 100, 3);
8798  CLEAR_ERROR_INSERT_VALUE;
8799  }
8800  else
8801  {
8802  sendSignal(tblockref, GSN_LQH_TRANSREQ, signal, 3, JBB);
8803  }
8804  }//if
8805  }//for
8806 }//Dbtc::startTakeOverLab()
8807 
8808 /*------------------------------------------------------------*/
8809 /* A REPORT OF AN OPERATION WHERE TC FAILED HAS ARRIVED.*/
8810 /*------------------------------------------------------------*/
8811 void Dbtc::execLQH_TRANSCONF(Signal* signal)
8812 {
8813  jamEntry();
8814  LqhTransConf * const lqhTransConf = (LqhTransConf *)&signal->theData[0];
8815 
8816  CRASH_INSERTION(8060);
8817 
8818  tcNodeFailptr.i = lqhTransConf->tcRef;
8819  ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
8820  tnodeid = lqhTransConf->lqhNodeId;
8821  ttransStatus = (LqhTransConf::OperationStatus)lqhTransConf->operationStatus;
8822  ttransid1 = lqhTransConf->transId1;
8823  ttransid2 = lqhTransConf->transId2;
8824  ttcOprec = lqhTransConf->oldTcOpRec;
8825  treqinfo = lqhTransConf->requestInfo;
8826  tgci = Uint64(lqhTransConf->gci_hi) << 32;
8827  cnodes[0] = lqhTransConf->nextNodeId1;
8828  cnodes[1] = lqhTransConf->nextNodeId2;
8829  cnodes[2] = lqhTransConf->nextNodeId3;
8830  const Uint32 ref = tapplRef = lqhTransConf->apiRef;
8831  tapplOprec = lqhTransConf->apiOpRec;
8832  const Uint32 tableId = lqhTransConf->tableId;
8833  Uint32 gci_lo = lqhTransConf->gci_lo;
8834  Uint32 fragId = lqhTransConf->fragId;
8835  if (ttransStatus == LqhTransConf::Committed &&
8836  unlikely(signal->getLength() < LqhTransConf::SignalLength_GCI_LO))
8837  {
8838  jam();
8839  gci_lo = 0;
8840  ndbassert(!ndb_check_micro_gcp(getNodeInfo(tnodeid).m_version));
8841  }
8842  tgci |= gci_lo;
8843 
8844  if (ttransStatus == LqhTransConf::LastTransConf){
8845  jam();
8846  /*------------------------------------------------------------*/
8847  /* A NODE HAS REPORTED COMPLETION OF TAKE OVER REPORTING*/
8848  /*------------------------------------------------------------*/
8849  nodeTakeOverCompletedLab(signal);
8850  return;
8851  }//if
8852  if (ttransStatus == LqhTransConf::Marker){
8853  jam();
8854  treqinfo = 0;
8855  LqhTransConf::setMarkerFlag(treqinfo, 1);
8856  } else {
8857  TableRecordPtr tabPtr;
8858  tabPtr.i = tableId;
8859  ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
8860  switch((DictTabInfo::TableType)tabPtr.p->tableType){
8861  case DictTabInfo::SystemTable:
8862  case DictTabInfo::UserTable:
8863  break;
8864  default:
8865  tapplRef = 0;
8866  tapplOprec = 0;
8867  }
8868  }
8869 
8870  findApiConnectFail(signal);
8871 
8872  if(apiConnectptr.p->ndbapiBlockref == 0 && tapplRef != 0){
8873  apiConnectptr.p->ndbapiBlockref = ref;
8874  apiConnectptr.p->ndbapiConnect = tapplOprec;
8875  }
8876 
8877  if (ttransStatus != LqhTransConf::Marker)
8878  {
8879  jam();
8880 
8881  Uint32 instanceKey;
8882 
8883  if (unlikely(signal->getLength() < LqhTransConf::SignalLength_FRAG_ID))
8884  {
8885  jam();
8886  instanceKey = 0;
8887  }
8888  else
8889  {
8890  jam();
8891  instanceKey = getInstanceKey(tableId, fragId);
8892  }
8893  findTcConnectFail(signal, instanceKey);
8894  }
8895 }//Dbtc::execLQH_TRANSCONF()
8896 
8897 /*------------------------------------------------------------*/
8898 /* A NODE HAS REPORTED COMPLETION OF TAKE OVER REPORTING*/
8899 /*------------------------------------------------------------*/
8900 void Dbtc::nodeTakeOverCompletedLab(Signal* signal)
8901 {
8902  Uint32 guard0;
8903 
8904  CRASH_INSERTION(8061);
8905 
8906  hostptr.i = tnodeid;
8907  ptrCheckGuard(hostptr, chostFilesize, hostRecord);
8908  hostptr.p->lqhTransStatus = LTS_IDLE;
8909  for (hostptr.i = 1; hostptr.i < MAX_NDB_NODES; hostptr.i++) {
8910  jam();
8911  ptrAss(hostptr, hostRecord);
8912  if (hostptr.p->hostStatus == HS_ALIVE) {
8913  if (hostptr.p->lqhTransStatus == LTS_ACTIVE) {
8914  jam();
8915  /*------------------------------------------------------------*/
8916  /* NOT ALL NODES ARE COMPLETED WITH REPORTING IN THE */
8917  /* TAKE OVER. */
8918  /*------------------------------------------------------------*/
8919  return;
8920  }//if
8921  }//if
8922  }//for
8923  /*------------------------------------------------------------*/
8924  /* ALL NODES HAVE REPORTED ON THE STATUS OF THE VARIOUS */
8925  /* OPERATIONS THAT WAS CONTROLLED BY THE FAILED TC. WE */
8926  /* ARE NOW IN A POSITION TO COMPLETE ALL OF THOSE */
8927  /* TRANSACTIONS EITHER IN A SUCCESSFUL WAY OR IN AN */
8928  /* UNSUCCESSFUL WAY. WE WILL ALSO REPORT THIS CONCLUSION*/
8929  /* TO THE APPLICATION IF THAT IS STILL ALIVE. */
8930  /*------------------------------------------------------------*/
8931  tcNodeFailptr.p->currentHashIndexTakeOver = 0;
8932  tcNodeFailptr.p->completedTakeOver = 0;
8933  tcNodeFailptr.p->failStatus = FS_COMPLETING;
8934  guard0 = cnoParallelTakeOver - 1;
8935  /*------------------------------------------------------------*/
8936  /* WE WILL COMPLETE THE TRANSACTIONS BY STARTING A */
8937  /* NUMBER OF PARALLEL ACTIVITIES. EACH ACTIVITY WILL */
8938  /* COMPLETE ONE TRANSACTION AT A TIME AND IN THAT */
8939  /* TRANSACTION IT WILL COMPLETE ONE OPERATION AT A TIME.*/
8940  /* WHEN ALL ACTIVITIES ARE COMPLETED THEN THE TAKE OVER */
8941  /* IS COMPLETED. */
8942  /*------------------------------------------------------------*/
8943  arrGuard(guard0, MAX_NDB_NODES);
8944  for (tindex = 0; tindex <= guard0; tindex++) {
8945  jam();
8946  tcNodeFailptr.p->takeOverProcState[tindex] = ZTAKE_OVER_ACTIVE;
8947  signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
8948  signal->theData[1] = tcNodeFailptr.i;
8949  signal->theData[2] = tindex;
8950  sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
8951  }//for
8952 }//Dbtc::nodeTakeOverCompletedLab()
8953 
8954 /*------------------------------------------------------------*/
8955 /* COMPLETE A NEW TRANSACTION FROM THE HASH TABLE OF */
8956 /* TRANSACTIONS TO COMPLETE. */
8957 /*------------------------------------------------------------*/
8958 void Dbtc::completeTransAtTakeOverLab(Signal* signal, UintR TtakeOverInd)
8959 {
8960  jam();
8961  while (tcNodeFailptr.p->currentHashIndexTakeOver < 512){
8962  jam();
8963  apiConnectptr.i =
8964  ctransidFailHash[tcNodeFailptr.p->currentHashIndexTakeOver];
8965  if (apiConnectptr.i != RNIL) {
8966  jam();
8967  /*------------------------------------------------------------*/
8968  /* WE HAVE FOUND A TRANSACTION THAT NEEDS TO BE */
8969  /* COMPLETED. REMOVE IT FROM THE HASH TABLE SUCH THAT */
8970  /* NOT ANOTHER ACTIVITY ALSO TRIES TO COMPLETE THIS */
8971  /* TRANSACTION. */
8972  /*------------------------------------------------------------*/
8973  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
8974  ctransidFailHash[tcNodeFailptr.p->currentHashIndexTakeOver] =
8975  apiConnectptr.p->nextApiConnect;
8976 
8977  completeTransAtTakeOverDoOne(signal, TtakeOverInd);
8978  // One transaction taken care of, return from this function
8979  // and wait for the next CONTINUEB to continue processing
8980  break;
8981 
8982  } else {
8983  if (tcNodeFailptr.p->currentHashIndexTakeOver < 511){
8984  jam();
8985  tcNodeFailptr.p->currentHashIndexTakeOver++;
8986  } else {
8987  jam();
8988  completeTransAtTakeOverDoLast(signal, TtakeOverInd);
8989  tcNodeFailptr.p->currentHashIndexTakeOver++;
8990  }//if
8991  }//if
8992  }//while
8993 }//Dbtc::completeTransAtTakeOverLab()
8994 
8995 
8996 
8997 
8998 void Dbtc::completeTransAtTakeOverDoLast(Signal* signal, UintR TtakeOverInd)
8999 {
9000  Uint32 guard0;
9001  /*------------------------------------------------------------*/
9002  /* THERE ARE NO MORE TRANSACTIONS TO COMPLETE. THIS */
9003  /* ACTIVITY IS COMPLETED. */
9004  /*------------------------------------------------------------*/
9005  arrGuard(TtakeOverInd, MAX_NDB_NODES);
9006  if (tcNodeFailptr.p->takeOverProcState[TtakeOverInd] != ZTAKE_OVER_ACTIVE) {
9007  jam();
9008  systemErrorLab(signal, __LINE__);
9009  return;
9010  }//if
9011  tcNodeFailptr.p->takeOverProcState[TtakeOverInd] = ZTAKE_OVER_IDLE;
9012  tcNodeFailptr.p->completedTakeOver++;
9013 
9014  CRASH_INSERTION(8062);
9015 
9016  if (tcNodeFailptr.p->completedTakeOver == cnoParallelTakeOver) {
9017  jam();
9018  /*------------------------------------------------------------*/
9019  /* WE WERE THE LAST ACTIVITY THAT WAS COMPLETED. WE NEED*/
9020  /* TO REPORT THE COMPLETION OF THE TAKE OVER TO ALL */
9021  /* NODES THAT ARE ALIVE. */
9022  /*------------------------------------------------------------*/
9023  NodeReceiverGroup rg(DBTC, c_alive_nodes);
9024  signal->theData[0] = tcNodeFailptr.p->takeOverNode;
9025  signal->theData[1] = reference();
9026  sendSignal(rg, GSN_TAKE_OVERTCCONF, signal, 2, JBB);
9027 
9028  if (tcNodeFailptr.p->queueIndex > 0) {
9029  jam();
9030  /*------------------------------------------------------------*/
9031  /* THERE ARE MORE NODES TO TAKE OVER. WE NEED TO START */
9032  /* THE TAKE OVER. */
9033  /*------------------------------------------------------------*/
9034  tfailedNodeId = tcNodeFailptr.p->queueList[0];
9035  guard0 = tcNodeFailptr.p->queueIndex - 1;
9036  arrGuard(guard0 + 1, MAX_NDB_NODES);
9037  for (tindex = 0; tindex <= guard0; tindex++) {
9038  jam();
9039  tcNodeFailptr.p->queueList[tindex] =
9040  tcNodeFailptr.p->queueList[tindex + 1];
9041  }//for
9042  tcNodeFailptr.p->queueIndex--;
9043  startTakeOverLab(signal);
9044  return;
9045  } else {
9046  jam();
9047  tcNodeFailptr.p->failStatus = FS_IDLE;
9048  }//if
9049  }//if
9050  return;
9051 }//Dbtc::completeTransAtTakeOverDoLast()
9052 
9053 void Dbtc::completeTransAtTakeOverDoOne(Signal* signal, UintR TtakeOverInd)
9054 {
9055  apiConnectptr.p->takeOverRec = (Uint8)tcNodeFailptr.i;
9056  apiConnectptr.p->takeOverInd = TtakeOverInd;
9057 
9058  switch (apiConnectptr.p->apiConnectstate) {
9059  case CS_FAIL_COMMITTED:
9060  jam();
9061  /*------------------------------------------------------------*/
9062  /* ALL PARTS OF THE TRANSACTIONS REPORTED COMMITTED. WE */
9063  /* HAVE THUS COMPLETED THE COMMIT PHASE. WE CAN REPORT */
9064  /* COMMITTED TO THE APPLICATION AND CONTINUE WITH THE */
9065  /* COMPLETE PHASE. */
9066  /*------------------------------------------------------------*/
9067  sendTCKEY_FAILCONF(signal, apiConnectptr.p);
9068  tcConnectptr.i = apiConnectptr.p->firstTcConnect;
9069  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9070  apiConnectptr.p->currentTcConnect = tcConnectptr.i;
9071  apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
9072  tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9073  commitGciHandling(signal, apiConnectptr.p->globalcheckpointid);
9074  toCompleteHandlingLab(signal);
9075  return;
9076  case CS_FAIL_COMMITTING:
9077  jam();
9078  /*------------------------------------------------------------*/
9079  /* AT LEAST ONE PART WAS ONLY PREPARED AND AT LEAST ONE */
9080  /* PART WAS COMMITTED. COMPLETE THE COMMIT PHASE FIRST. */
9081  /* THEN CONTINUE AS AFTER COMMITTED. */
9082  /*------------------------------------------------------------*/
9083  tcConnectptr.i = apiConnectptr.p->firstTcConnect;
9084  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9085  apiConnectptr.p->currentTcConnect = tcConnectptr.i;
9086  apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
9087  tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9088  commitGciHandling(signal, apiConnectptr.p->globalcheckpointid);
9089  toCommitHandlingLab(signal);
9090  return;
9091  case CS_FAIL_ABORTING:
9092  case CS_FAIL_PREPARED:
9093  jam();
9094  /*------------------------------------------------------------*/
9095  /* WE WILL ABORT THE TRANSACTION IF IT IS IN A PREPARED */
9096  /* STATE IN THIS VERSION. IN LATER VERSIONS WE WILL */
9097  /* HAVE TO ADD CODE FOR HANDLING OF PREPARED-TO-COMMIT */
9098  /* TRANSACTIONS. THESE ARE NOT ALLOWED TO ABORT UNTIL WE*/
9099  /* HAVE HEARD FROM THE TRANSACTION COORDINATOR. */
9100  /* */
9101  /* IT IS POSSIBLE TO COMMIT TRANSACTIONS THAT ARE */
9102  /* PREPARED ACTUALLY. WE WILL LEAVE THIS PROBLEM UNTIL */
9103  /* LATER VERSIONS. */
9104  /*------------------------------------------------------------*/
9105  tcConnectptr.i = apiConnectptr.p->firstTcConnect;
9106  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9107  apiConnectptr.p->currentTcConnect = tcConnectptr.i;
9108  apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
9109  tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9110  toAbortHandlingLab(signal);
9111  return;
9112  case CS_FAIL_ABORTED:
9113  jam();
9114  sendTCKEY_FAILREF(signal, apiConnectptr.p);
9115 
9116  signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
9117  signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
9118  signal->theData[2] = apiConnectptr.p->takeOverInd;
9119  sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
9120  releaseTakeOver(signal);
9121  break;
9122  case CS_FAIL_COMPLETED:
9123  jam();
9124  sendTCKEY_FAILCONF(signal, apiConnectptr.p);
9125 
9126  signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
9127  signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
9128  signal->theData[2] = apiConnectptr.p->takeOverInd;
9129  sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
9130  releaseApiConnectFail(signal);
9131  break;
9132  default:
9133  jam();
9134  systemErrorLab(signal, __LINE__);
9135  return;
9136  }//switch
9137 }//Dbtc::completeTransAtTakeOverDoOne()
9138 
9139 void
9140 Dbtc::sendTCKEY_FAILREF(Signal* signal, ApiConnectRecord * regApiPtr){
9141  jam();
9142 
9143  const Uint32 ref = regApiPtr->ndbapiBlockref;
9144  const Uint32 nodeId = refToNode(ref);
9145  if(ref != 0)
9146  {
9147  jam();
9148  bool connectedToNode = getNodeInfo(nodeId).m_connected;
9149  signal->theData[0] = regApiPtr->ndbapiConnect;
9150  signal->theData[1] = regApiPtr->transid[0];
9151  signal->theData[2] = regApiPtr->transid[1];
9152 
9153  if (likely(connectedToNode))
9154  {
9155  jam();
9156  sendSignal(ref, GSN_TCKEY_FAILREF, signal, 3, JBB);
9157  }
9158  else
9159  {
9160  routeTCKEY_FAILREFCONF(signal, regApiPtr, GSN_TCKEY_FAILREF, 3);
9161  }
9162  }
9163 
9164  const Uint32 marker = regApiPtr->commitAckMarker;
9165  if(marker != RNIL)
9166  {
9167  jam();
9168  m_commitAckMarkerHash.release(marker);
9169  regApiPtr->commitAckMarker = RNIL;
9170  }
9171 }
9172 
9173 void
9174 Dbtc::sendTCKEY_FAILCONF(Signal* signal, ApiConnectRecord * regApiPtr){
9175  jam();
9176  TcKeyFailConf * const failConf = (TcKeyFailConf *)&signal->theData[0];
9177 
9178  const Uint32 ref = regApiPtr->ndbapiBlockref;
9179  const Uint32 marker = regApiPtr->commitAckMarker;
9180  const Uint32 nodeId = refToNode(ref);
9181  if(ref != 0)
9182  {
9183  jam();
9184  failConf->apiConnectPtr = regApiPtr->ndbapiConnect | (marker != RNIL);
9185  failConf->transId1 = regApiPtr->transid[0];
9186  failConf->transId2 = regApiPtr->transid[1];
9187 
9188  bool connectedToNode = getNodeInfo(nodeId).m_connected;
9189  if (likely(connectedToNode))
9190  {
9191  jam();
9192  sendSignal(ref, GSN_TCKEY_FAILCONF, signal,
9193  TcKeyFailConf::SignalLength, JBB);
9194  }
9195  else
9196  {
9197  routeTCKEY_FAILREFCONF(signal, regApiPtr,
9198  GSN_TCKEY_FAILCONF, TcKeyFailConf::SignalLength);
9199  }
9200  }
9201  regApiPtr->commitAckMarker = RNIL;
9202 }
9203 
9204 void
9205 Dbtc::routeTCKEY_FAILREFCONF(Signal* signal, const ApiConnectRecord* regApiPtr,
9206  Uint32 gsn, Uint32 len)
9207 {
9208  jam();
9209 
9210  Uint32 ref = regApiPtr->ndbapiBlockref;
9211 
9217  tcNodeFailptr.i = regApiPtr->takeOverRec;
9218  ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
9219 
9223  Uint32 save[25];
9224  ndbrequire(len <= 25);
9225  memcpy(save, signal->theData, 4*len);
9226 
9227  Uint32 node = tcNodeFailptr.p->takeOverNode;
9228 
9229  CheckNodeGroups * sd = (CheckNodeGroups*)signal->getDataPtrSend();
9230  sd->blockRef = reference();
9231  sd->requestType =
9232  CheckNodeGroups::Direct |
9233  CheckNodeGroups::GetNodeGroupMembers;
9234  sd->nodeId = node;
9235  EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal,
9236  CheckNodeGroups::SignalLength);
9237  jamEntry();
9238 
9239  NdbNodeBitmask mask;
9240  mask.assign(sd->mask);
9241  mask.clear(getOwnNodeId());
9242  memcpy(signal->theData, save, 4*len);
9243 
9244  Uint32 i = 0;
9245  while((i = mask.find(i + 1)) != NdbNodeBitmask::NotFound)
9246  {
9247  jam();
9248  HostRecordPtr localHostptr;
9249  localHostptr.i = i;
9250  ptrCheckGuard(localHostptr, chostFilesize, hostRecord);
9251  if (localHostptr.p->hostStatus == HS_ALIVE)
9252  {
9253  jam();
9254  signal->theData[len] = gsn;
9255  signal->theData[len+1] = ref;
9256  sendSignal(calcTcBlockRef(i), GSN_TCKEY_FAILREFCONF_R,
9257  signal, len+2, JBB);
9258  return;
9259  }
9260  }
9261 
9262 
9268 #if 0
9269  ndbrequire(getNodeInfo(refToNode(ref)).m_type == NodeInfo::DB);
9270 #endif
9271 }
9272 
9273 void
9274 Dbtc::execTCKEY_FAILREFCONF_R(Signal* signal)
9275 {
9276  jamEntry();
9277  Uint32 len = signal->getLength();
9278  Uint32 gsn = signal->theData[len-2];
9279  Uint32 ref = signal->theData[len-1];
9280  sendSignal(ref, gsn, signal, len-2, JBB);
9281 }
9282 
9283 /*------------------------------------------------------------*/
9284 /* THIS PART HANDLES THE ABORT PHASE IN THE CASE OF A */
9285 /* NODE FAILURE BEFORE THE COMMIT DECISION. */
9286 /*------------------------------------------------------------*/
9287 /* ABORT REQUEST SUCCESSFULLY COMPLETED ON TNODEID */
9288 /*------------------------------------------------------------*/
9289 void Dbtc::execABORTCONF(Signal* signal)
9290 {
9291  UintR compare_transid1, compare_transid2;
9292 
9293  jamEntry();
9294  tcConnectptr.i = signal->theData[0];
9295  tnodeid = signal->theData[2];
9296  if (ERROR_INSERTED(8045)) {
9297  CLEAR_ERROR_INSERT_VALUE;
9298  sendSignalWithDelay(cownref, GSN_ABORTCONF, signal, 2000, 5);
9299  return;
9300  }//if
9301  if (tcConnectptr.i >= ctcConnectFilesize) {
9302  errorReport(signal, 5);
9303  return;
9304  }//if
9305  ptrAss(tcConnectptr, tcConnectRecord);
9306  if (tcConnectptr.p->tcConnectstate != OS_WAIT_ABORT_CONF) {
9307  warningReport(signal, 16);
9308  return;
9309  }//if
9310  apiConnectptr.i = tcConnectptr.p->apiConnect;
9311  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9312  if (apiConnectptr.p->apiConnectstate != CS_WAIT_ABORT_CONF) {
9313  warningReport(signal, 17);
9314  return;
9315  }//if
9316  compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[3];
9317  compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[4];
9318  compare_transid1 = compare_transid1 | compare_transid2;
9319  if (compare_transid1 != 0) {
9320  warningReport(signal, 18);
9321  return;
9322  }//if
9323  arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
9324  if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
9325  tnodeid) {
9326  warningReport(signal, 19);
9327  return;
9328  }//if
9329  tcurrentReplicaNo = (Uint8)Z8NIL;
9330  tcConnectptr.p->tcConnectstate = OS_ABORTING;
9331  toAbortHandlingLab(signal);
9332 }//Dbtc::execABORTCONF()
9333 
9334 void Dbtc::toAbortHandlingLab(Signal* signal)
9335 {
9336  do {
9337  if (tcurrentReplicaNo != (Uint8)Z8NIL) {
9338  jam();
9339  arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
9340  const LqhTransConf::OperationStatus stat =
9341  (LqhTransConf::OperationStatus)
9342  tcConnectptr.p->failData[tcurrentReplicaNo];
9343  switch(stat){
9344  case LqhTransConf::InvalidStatus:
9345  case LqhTransConf::Aborted:
9346  jam();
9347  /*empty*/;
9348  break;
9349  case LqhTransConf::Prepared:
9350  jam();
9351  hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
9352  ptrCheckGuard(hostptr, chostFilesize, hostRecord);
9353  if (hostptr.p->hostStatus == HS_ALIVE) {
9354  jam();
9355  Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
9356  tblockref = numberToRef(DBLQH, instanceKey, hostptr.i);
9357  setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
9358  tcConnectptr.p->tcConnectstate = OS_WAIT_ABORT_CONF;
9359  apiConnectptr.p->apiConnectstate = CS_WAIT_ABORT_CONF;
9360  apiConnectptr.p->timeOutCounter = 0;
9361  signal->theData[0] = tcConnectptr.i;
9362  signal->theData[1] = cownref;
9363  signal->theData[2] = apiConnectptr.p->transid[0];
9364  signal->theData[3] = apiConnectptr.p->transid[1];
9365  signal->theData[4] = apiConnectptr.p->tcBlockref;
9366  signal->theData[5] = tcConnectptr.p->tcOprec;
9367  sendSignal(tblockref, GSN_ABORTREQ, signal, 6, JBB);
9368  return;
9369  }//if
9370  break;
9371  default:
9372  jam();
9373  systemErrorLab(signal, __LINE__);
9374  return;
9375  }//switch
9376  }//if
9377  if (apiConnectptr.p->currentReplicaNo > 0) {
9378  jam();
9379  /*------------------------------------------------------------*/
9380  /* THERE IS STILL ANOTHER REPLICA THAT NEEDS TO BE */
9381  /* ABORTED. */
9382  /*------------------------------------------------------------*/
9383  apiConnectptr.p->currentReplicaNo--;
9384  tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
9385  } else {
9386  /*------------------------------------------------------------*/
9387  /* THE LAST REPLICA IN THIS OPERATION HAVE COMMITTED. */
9388  /*------------------------------------------------------------*/
9389  tcConnectptr.i = tcConnectptr.p->nextTcConnect;
9390  if (tcConnectptr.i == RNIL) {
9391  /*------------------------------------------------------------*/
9392  /* WE HAVE COMPLETED THE ABORT PHASE. WE CAN NOW REPORT */
9393  /* THE ABORT STATUS TO THE APPLICATION AND CONTINUE */
9394  /* WITH THE NEXT TRANSACTION. */
9395  /*------------------------------------------------------------*/
9396  if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
9397  jam();
9398  sendTCKEY_FAILREF(signal, apiConnectptr.p);
9399 
9400  /*------------------------------------------------------------*/
9401  /* WE HAVE COMPLETED THIS TRANSACTION NOW AND CAN */
9402  /* CONTINUE THE PROCESS WITH THE NEXT TRANSACTION. */
9403  /*------------------------------------------------------------*/
9404  signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
9405  signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
9406  signal->theData[2] = apiConnectptr.p->takeOverInd;
9407  sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
9408  releaseTakeOver(signal);
9409  } else {
9410  jam();
9411  releaseAbortResources(signal);
9412  }//if
9413  return;
9414  }//if
9415  apiConnectptr.p->currentTcConnect = tcConnectptr.i;
9416  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9417  apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
9418  tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9419  }//if
9420  } while (1);
9421 }//Dbtc::toAbortHandlingLab()
9422 
9423 /*------------------------------------------------------------*/
9424 /* THIS PART HANDLES THE COMMIT PHASE IN THE CASE OF A */
9425 /* NODE FAILURE IN THE MIDDLE OF THE COMMIT PHASE. */
9426 /*------------------------------------------------------------*/
9427 /* COMMIT REQUEST SUCCESSFULLY COMPLETED ON TNODEID */
9428 /*------------------------------------------------------------*/
9429 void Dbtc::execCOMMITCONF(Signal* signal)
9430 {
9431  UintR compare_transid1, compare_transid2;
9432 
9433  jamEntry();
9434  tcConnectptr.i = signal->theData[0];
9435  tnodeid = signal->theData[1];
9436  if (ERROR_INSERTED(8046)) {
9437  CLEAR_ERROR_INSERT_VALUE;
9438  sendSignalWithDelay(cownref, GSN_COMMITCONF, signal, 2000, 4);
9439  return;
9440  }//if
9441  if (tcConnectptr.i >= ctcConnectFilesize) {
9442  errorReport(signal, 4);
9443  return;
9444  }//if
9445  ptrAss(tcConnectptr, tcConnectRecord);
9446  if (tcConnectptr.p->tcConnectstate != OS_WAIT_COMMIT_CONF) {
9447  warningReport(signal, 8);
9448  return;
9449  }//if
9450  apiConnectptr.i = tcConnectptr.p->apiConnect;
9451  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9452  if (apiConnectptr.p->apiConnectstate != CS_WAIT_COMMIT_CONF) {
9453  warningReport(signal, 9);
9454  return;
9455  }//if
9456  compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[2];
9457  compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[3];
9458  compare_transid1 = compare_transid1 | compare_transid2;
9459  if (compare_transid1 != 0) {
9460  warningReport(signal, 10);
9461  return;
9462  }//if
9463  arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
9464  if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
9465  tnodeid) {
9466  warningReport(signal, 11);
9467  return;
9468  }//if
9469  if (ERROR_INSERTED(8026)) {
9470  jam();
9471  systemErrorLab(signal, __LINE__);
9472  }//if
9473  tcurrentReplicaNo = (Uint8)Z8NIL;
9474  tcConnectptr.p->tcConnectstate = OS_COMMITTED;
9475  toCommitHandlingLab(signal);
9476 }//Dbtc::execCOMMITCONF()
9477 
9478 void Dbtc::toCommitHandlingLab(Signal* signal)
9479 {
9480  do {
9481  if (tcurrentReplicaNo != (Uint8)Z8NIL) {
9482  jam();
9483  arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
9484  switch (tcConnectptr.p->failData[tcurrentReplicaNo]) {
9485  case LqhTransConf::InvalidStatus:
9486  jam();
9487  /*empty*/;
9488  break;
9489  case LqhTransConf::Committed:
9490  jam();
9491  /*empty*/;
9492  break;
9493  case LqhTransConf::Prepared:
9494  jam();
9495  /*------------------------------------------------------------*/
9496  /* THE NODE WAS PREPARED AND IS WAITING FOR ABORT OR */
9497  /* COMMIT REQUEST FROM TC. */
9498  /*------------------------------------------------------------*/
9499  hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
9500  ptrCheckGuard(hostptr, chostFilesize, hostRecord);
9501  if (hostptr.p->hostStatus == HS_ALIVE) {
9502  jam();
9503  Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
9504  tblockref = numberToRef(DBLQH, instanceKey, hostptr.i);
9505  setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
9506  apiConnectptr.p->apiConnectstate = CS_WAIT_COMMIT_CONF;
9507  apiConnectptr.p->timeOutCounter = 0;
9508  tcConnectptr.p->tcConnectstate = OS_WAIT_COMMIT_CONF;
9509  Uint64 gci = apiConnectptr.p->globalcheckpointid;
9510  signal->theData[0] = tcConnectptr.i;
9511  signal->theData[1] = cownref;
9512  signal->theData[2] = Uint32(gci >> 32); // XXX JON
9513  signal->theData[3] = apiConnectptr.p->transid[0];
9514  signal->theData[4] = apiConnectptr.p->transid[1];
9515  signal->theData[5] = apiConnectptr.p->tcBlockref;
9516  signal->theData[6] = tcConnectptr.p->tcOprec;
9517  signal->theData[7] = Uint32(gci);
9518  sendSignal(tblockref, GSN_COMMITREQ, signal, 8, JBB);
9519  return;
9520  }//if
9521  break;
9522  default:
9523  jam();
9524  systemErrorLab(signal, __LINE__);
9525  return;
9526  break;
9527  }//switch
9528  }//if
9529  if (apiConnectptr.p->currentReplicaNo > 0) {
9530  jam();
9531  /*------------------------------------------------------------*/
9532  /* THERE IS STILL ANOTHER REPLICA THAT NEEDS TO BE */
9533  /* COMMITTED. */
9534  /*------------------------------------------------------------*/
9535  apiConnectptr.p->currentReplicaNo--;
9536  tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
9537  } else {
9538  /*------------------------------------------------------------*/
9539  /* THE LAST REPLICA IN THIS OPERATION HAVE COMMITTED. */
9540  /*------------------------------------------------------------*/
9541  tcConnectptr.i = tcConnectptr.p->nextTcConnect;
9542  if (tcConnectptr.i == RNIL) {
9543  /*------------------------------------------------------------*/
9544  /* WE HAVE COMPLETED THE COMMIT PHASE. WE CAN NOW REPORT*/
9545  /* THE COMMIT STATUS TO THE APPLICATION AND CONTINUE */
9546  /* WITH THE COMPLETE PHASE. */
9547  /*------------------------------------------------------------*/
9548  if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
9549  jam();
9550  sendTCKEY_FAILCONF(signal, apiConnectptr.p);
9551  } else {
9552  jam();
9553  apiConnectptr = sendApiCommit(signal);
9554  }//if
9555  apiConnectptr.p->currentTcConnect = apiConnectptr.p->firstTcConnect;
9556  tcConnectptr.i = apiConnectptr.p->firstTcConnect;
9557  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9558  tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9559  apiConnectptr.p->currentReplicaNo = tcurrentReplicaNo;
9560  toCompleteHandlingLab(signal);
9561  return;
9562  }//if
9563  apiConnectptr.p->currentTcConnect = tcConnectptr.i;
9564  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9565  apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
9566  tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9567  }//if
9568  } while (1);
9569 }//Dbtc::toCommitHandlingLab()
9570 
9571 /*------------------------------------------------------------*/
9572 /* COMMON PART TO HANDLE COMPLETE PHASE WHEN ANY NODE */
9573 /* HAVE FAILED. */
9574 /*------------------------------------------------------------*/
9575 /* THE NODE WITH TNODEID HAVE COMPLETED THE OPERATION */
9576 /*------------------------------------------------------------*/
9577 void Dbtc::execCOMPLETECONF(Signal* signal)
9578 {
9579  UintR compare_transid1, compare_transid2;
9580 
9581  jamEntry();
9582  tcConnectptr.i = signal->theData[0];
9583  tnodeid = signal->theData[1];
9584  if (ERROR_INSERTED(8047)) {
9585  CLEAR_ERROR_INSERT_VALUE;
9586  sendSignalWithDelay(cownref, GSN_COMPLETECONF, signal, 2000, 4);
9587  return;
9588  }//if
9589  if (tcConnectptr.i >= ctcConnectFilesize) {
9590  errorReport(signal, 3);
9591  return;
9592  }//if
9593  ptrAss(tcConnectptr, tcConnectRecord);
9594  if (tcConnectptr.p->tcConnectstate != OS_WAIT_COMPLETE_CONF) {
9595  warningReport(signal, 12);
9596  return;
9597  }//if
9598  apiConnectptr.i = tcConnectptr.p->apiConnect;
9599  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9600  if (apiConnectptr.p->apiConnectstate != CS_WAIT_COMPLETE_CONF) {
9601  warningReport(signal, 13);
9602  return;
9603  }//if
9604  compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[2];
9605  compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[3];
9606  compare_transid1 = compare_transid1 | compare_transid2;
9607  if (compare_transid1 != 0) {
9608  warningReport(signal, 14);
9609  return;
9610  }//if
9611  arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
9612  if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
9613  tnodeid) {
9614  warningReport(signal, 15);
9615  return;
9616  }//if
9617  if (ERROR_INSERTED(8028)) {
9618  jam();
9619  systemErrorLab(signal, __LINE__);
9620  }//if
9621  tcConnectptr.p->tcConnectstate = OS_COMPLETED;
9622  tcurrentReplicaNo = (Uint8)Z8NIL;
9623  toCompleteHandlingLab(signal);
9624 }//Dbtc::execCOMPLETECONF()
9625 
9626 void Dbtc::toCompleteHandlingLab(Signal* signal)
9627 {
9628  do {
9629  if (tcurrentReplicaNo != (Uint8)Z8NIL) {
9630  jam();
9631  arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
9632  switch (tcConnectptr.p->failData[tcurrentReplicaNo]) {
9633  case LqhTransConf::InvalidStatus:
9634  jam();
9635  /*empty*/;
9636  break;
9637  default:
9638  jam();
9639  /*------------------------------------------------------------*/
9640  /* THIS NODE DID NOT REPORT ANYTHING FOR THIS OPERATION */
9641  /* IT MUST HAVE FAILED. */
9642  /*------------------------------------------------------------*/
9643  /*------------------------------------------------------------*/
9644  /* SEND COMPLETEREQ TO THE NEXT REPLICA. */
9645  /*------------------------------------------------------------*/
9646  hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
9647  ptrCheckGuard(hostptr, chostFilesize, hostRecord);
9648  if (hostptr.p->hostStatus == HS_ALIVE) {
9649  jam();
9650  Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
9651  tblockref = numberToRef(DBLQH, instanceKey, hostptr.i);
9652  setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
9653  tcConnectptr.p->tcConnectstate = OS_WAIT_COMPLETE_CONF;
9654  apiConnectptr.p->apiConnectstate = CS_WAIT_COMPLETE_CONF;
9655  apiConnectptr.p->timeOutCounter = 0;
9656  tcConnectptr.p->apiConnect = apiConnectptr.i;
9657  signal->theData[0] = tcConnectptr.i;
9658  signal->theData[1] = cownref;
9659  signal->theData[2] = apiConnectptr.p->transid[0];
9660  signal->theData[3] = apiConnectptr.p->transid[1];
9661  signal->theData[4] = apiConnectptr.p->tcBlockref;
9662  signal->theData[5] = tcConnectptr.p->tcOprec;
9663  sendSignal(tblockref, GSN_COMPLETEREQ, signal, 6, JBB);
9664  return;
9665  }//if
9666  break;
9667  }//switch
9668  }//if
9669  if (apiConnectptr.p->currentReplicaNo != 0) {
9670  jam();
9671  /*------------------------------------------------------------*/
9672  /* THERE ARE STILL MORE REPLICAS IN THIS OPERATION. WE */
9673  /* NEED TO CONTINUE WITH THOSE REPLICAS. */
9674  /*------------------------------------------------------------*/
9675  apiConnectptr.p->currentReplicaNo--;
9676  tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
9677  } else {
9678  tcConnectptr.i = tcConnectptr.p->nextTcConnect;
9679  if (tcConnectptr.i == RNIL) {
9680  /*------------------------------------------------------------*/
9681  /* WE HAVE COMPLETED THIS TRANSACTION NOW AND CAN */
9682  /* CONTINUE THE PROCESS WITH THE NEXT TRANSACTION. */
9683  /*------------------------------------------------------------*/
9684  if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
9685  jam();
9686  signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
9687  signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
9688  signal->theData[2] = apiConnectptr.p->takeOverInd;
9689  sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
9690  handleGcp(signal, apiConnectptr);
9691  releaseTakeOver(signal);
9692  } else {
9693  jam();
9694  releaseTransResources(signal);
9695  }//if
9696  return;
9697  }//if
9698  /*------------------------------------------------------------*/
9699  /* WE HAVE COMPLETED AN OPERATION AND THERE ARE MORE TO */
9700  /* COMPLETE. TAKE THE NEXT OPERATION AND START WITH THE */
9701  /* FIRST REPLICA SINCE IT IS THE COMPLETE PHASE. */
9702  /*------------------------------------------------------------*/
9703  apiConnectptr.p->currentTcConnect = tcConnectptr.i;
9704  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9705  tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9706  apiConnectptr.p->currentReplicaNo = tcurrentReplicaNo;
9707  }//if
9708  } while (1);
9709 }//Dbtc::toCompleteHandlingLab()
9710 
9711 /*------------------------------------------------------------*/
9712 /* */
9713 /* FIND THE API CONNECT RECORD FOR THIS TRANSACTION */
9714 /* DURING TAKE OVER FROM A FAILED TC. IF NONE EXISTS */
9715 /* YET THEN SEIZE A NEW API CONNECT RECORD AND LINK IT */
9716 /* INTO THE HASH TABLE. */
9717 /*------------------------------------------------------------*/
9718 void Dbtc::findApiConnectFail(Signal* signal)
9719 {
9720  ApiConnectRecordPtr fafPrevApiConnectptr;
9721  ApiConnectRecordPtr fafNextApiConnectptr;
9722  UintR tfafHashNumber;
9723 
9724  tfafHashNumber = ttransid1 & 511;
9725  fafPrevApiConnectptr.i = RNIL;
9726  ptrNull(fafPrevApiConnectptr);
9727  arrGuard(tfafHashNumber, 512);
9728  fafNextApiConnectptr.i = ctransidFailHash[tfafHashNumber];
9729  ptrCheck(fafNextApiConnectptr, capiConnectFilesize, apiConnectRecord);
9730 FAF_LOOP:
9731  jam();
9732  if (fafNextApiConnectptr.i == RNIL) {
9733  jam();
9734  if (cfirstfreeApiConnectFail == RNIL) {
9735  jam();
9736  systemErrorLab(signal, __LINE__);
9737  return;
9738  }//if
9739  seizeApiConnectFail(signal);
9740  if (fafPrevApiConnectptr.i == RNIL) {
9741  jam();
9742  ctransidFailHash[tfafHashNumber] = apiConnectptr.i;
9743  } else {
9744  jam();
9745  ptrGuard(fafPrevApiConnectptr);
9746  fafPrevApiConnectptr.p->nextApiConnect = apiConnectptr.i;
9747  }//if
9748  apiConnectptr.p->nextApiConnect = RNIL;
9749  initApiConnectFail(signal);
9750  } else {
9751  jam();
9752  fafPrevApiConnectptr.i = fafNextApiConnectptr.i;
9753  fafPrevApiConnectptr.p = fafNextApiConnectptr.p;
9754  apiConnectptr.i = fafNextApiConnectptr.i;
9755  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9756  fafNextApiConnectptr.i = apiConnectptr.p->nextApiConnect;
9757  ptrCheck(fafNextApiConnectptr, capiConnectFilesize, apiConnectRecord);
9758  if ((apiConnectptr.p->transid[1] != ttransid2) ||
9759  (apiConnectptr.p->transid[0] != ttransid1)) {
9760  goto FAF_LOOP;
9761  }//if
9762  updateApiStateFail(signal);
9763  }//if
9764 }//Dbtc::findApiConnectFail()
9765 
9766 /*----------------------------------------------------------*/
9767 /* FIND THE TC CONNECT AND IF NOT FOUND ALLOCATE A NEW */
9768 /*----------------------------------------------------------*/
9769 void Dbtc::findTcConnectFail(Signal* signal, Uint32 instanceKey)
9770 {
9771  UintR tftfHashNumber;
9772 
9773  tftfHashNumber = (ttransid1 ^ ttcOprec) & 1023;
9774  tcConnectptr.i = ctcConnectFailHash[tftfHashNumber];
9775  do {
9776  if (tcConnectptr.i == RNIL) {
9777  jam();
9778  if (cfirstfreeTcConnectFail == RNIL) {
9779  jam();
9780  systemErrorLab(signal, __LINE__);
9781  return;
9782  }//if
9783  seizeTcConnectFail(signal);
9784  linkTcInConnectionlist(signal);
9785  tcConnectptr.p->nextTcFailHash = ctcConnectFailHash[tftfHashNumber];
9786  ctcConnectFailHash[tftfHashNumber] = tcConnectptr.i;
9787  initTcConnectFail(signal, instanceKey);
9788  return;
9789  } else {
9790  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9791  if (tcConnectptr.p->tcOprec != ttcOprec) {
9792  jam(); /* FRAGMENTID = TC_OPREC HERE, LOOP ANOTHER TURN */
9793  tcConnectptr.i = tcConnectptr.p->nextTcFailHash;
9794  } else {
9795  updateTcStateFail(signal, instanceKey);
9796  return;
9797  }//if
9798  }//if
9799  } while (1);
9800 }//Dbtc::findTcConnectFail()
9801 
9802 /*----------------------------------------------------------*/
9803 /* INITIALISE AN API CONNECT FAIL RECORD */
9804 /*----------------------------------------------------------*/
9805 void Dbtc::initApiConnectFail(Signal* signal)
9806 {
9807  apiConnectptr.p->transid[0] = ttransid1;
9808  apiConnectptr.p->transid[1] = ttransid2;
9809  apiConnectptr.p->firstTcConnect = RNIL;
9810  apiConnectptr.p->currSavePointId = 0;
9811  apiConnectptr.p->lastTcConnect = RNIL;
9812  tblockref = calcTcBlockRef(tcNodeFailptr.p->takeOverNode);
9813 
9814  apiConnectptr.p->tcBlockref = tblockref;
9815  apiConnectptr.p->ndbapiBlockref = 0;
9816  apiConnectptr.p->ndbapiConnect = 0;
9817  apiConnectptr.p->buddyPtr = RNIL;
9818  apiConnectptr.p->m_transaction_nodes.clear();
9819  apiConnectptr.p->singleUserMode = 0;
9820  setApiConTimer(apiConnectptr.i, 0, __LINE__);
9821  switch(ttransStatus){
9822  case LqhTransConf::Committed:
9823  jam();
9824  apiConnectptr.p->globalcheckpointid = tgci;
9825  apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTED;
9826  break;
9827  case LqhTransConf::Prepared:
9828  jam();
9829  apiConnectptr.p->apiConnectstate = CS_FAIL_PREPARED;
9830  break;
9831  case LqhTransConf::Aborted:
9832  jam();
9833  apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTED;
9834  break;
9835  case LqhTransConf::Marker:
9836  jam();
9837  apiConnectptr.p->apiConnectstate = CS_FAIL_COMPLETED;
9838  break;
9839  default:
9840  jam();
9841  systemErrorLab(signal, __LINE__);
9842  }//if
9843  apiConnectptr.p->commitAckMarker = RNIL;
9844  if(LqhTransConf::getMarkerFlag(treqinfo)){
9845  jam();
9846  CommitAckMarkerPtr tmp;
9847  m_commitAckMarkerHash.seize(tmp);
9848 
9849  ndbrequire(tmp.i != RNIL);
9850 
9851  apiConnectptr.p->commitAckMarker = tmp.i;
9852  tmp.p->transid1 = ttransid1;
9853  tmp.p->transid2 = ttransid2;
9854  tmp.p->apiNodeId = refToNode(tapplRef);
9855  tmp.p->m_commit_ack_marker_nodes.clear();
9856  tmp.p->m_commit_ack_marker_nodes.set(tnodeid);
9857  tmp.p->apiConnectPtr = apiConnectptr.i;
9858 
9859 #if defined VM_TRACE || defined ERROR_INSERT
9860  {
9861  CommitAckMarkerPtr check;
9862  ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
9863  }
9864 #endif
9865  m_commitAckMarkerHash.add(tmp);
9866  }
9867 }//Dbtc::initApiConnectFail()
9868 
9869 /*------------------------------------------------------------*/
9870 /* INITIALISE AT TC CONNECT AT TAKE OVER WHEN ALLOCATING*/
9871 /* THE TC CONNECT RECORD. */
9872 /*------------------------------------------------------------*/
9873 void Dbtc::initTcConnectFail(Signal* signal, Uint32 instanceKey)
9874 {
9875  tcConnectptr.p->apiConnect = apiConnectptr.i;
9876  tcConnectptr.p->tcOprec = ttcOprec;
9877  Uint32 treplicaNo = LqhTransConf::getReplicaNo(treqinfo);
9878  for (Uint32 i = 0; i < MAX_REPLICAS; i++) {
9879  tcConnectptr.p->failData[i] = LqhTransConf::InvalidStatus;
9880  }//for
9881  tcConnectptr.p->tcNodedata[treplicaNo] = tnodeid;
9882  tcConnectptr.p->failData[treplicaNo] = ttransStatus;
9883  tcConnectptr.p->lastReplicaNo = LqhTransConf::getLastReplicaNo(treqinfo);
9884  tcConnectptr.p->dirtyOp = LqhTransConf::getDirtyFlag(treqinfo);
9885  tcConnectptr.p->lqhInstanceKey = instanceKey;
9886 
9887 }//Dbtc::initTcConnectFail()
9888 
9889 /*----------------------------------------------------------*/
9890 /* INITIALISE TC NODE FAIL RECORD. */
9891 /*----------------------------------------------------------*/
9892 void Dbtc::initTcFail(Signal* signal)
9893 {
9894  tcNodeFailptr.i = 0;
9895  ptrAss(tcNodeFailptr, tcFailRecord);
9896  tcNodeFailptr.p->queueIndex = 0;
9897  tcNodeFailptr.p->failStatus = FS_IDLE;
9898 }//Dbtc::initTcFail()
9899 
9900 /*----------------------------------------------------------*/
9901 /* RELEASE_TAKE_OVER */
9902 /*----------------------------------------------------------*/
9903 void Dbtc::releaseTakeOver(Signal* signal)
9904 {
9905  TcConnectRecordPtr rtoNextTcConnectptr;
9906 
9907  rtoNextTcConnectptr.i = apiConnectptr.p->firstTcConnect;
9908  do {
9909  jam();
9910  tcConnectptr.i = rtoNextTcConnectptr.i;
9911  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9912  rtoNextTcConnectptr.i = tcConnectptr.p->nextTcConnect;
9913  releaseTcConnectFail(signal);
9914  } while (rtoNextTcConnectptr.i != RNIL);
9915  releaseApiConnectFail(signal);
9916 }//Dbtc::releaseTakeOver()
9917 
9918 /*---------------------------------------------------------------------------*/
9919 /* SETUP_FAIL_DATA */
9920 /* SETUP DATA TO REUSE TAKE OVER CODE FOR HANDLING ABORT/COMMIT IN NODE */
9921 /* FAILURE SITUATIONS. */
9922 /*---------------------------------------------------------------------------*/
9923 void Dbtc::setupFailData(Signal* signal)
9924 {
9925  tcConnectptr.i = apiConnectptr.p->firstTcConnect;
9926  do {
9927  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9928  switch (tcConnectptr.p->tcConnectstate) {
9929  case OS_PREPARED:
9930  case OS_COMMITTING:
9931  jam();
9932  arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
9933  for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
9934  jam();
9935  /*-------------------------------------------------------------------
9936  * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
9937  * IN THIS CASE ALL LQH'S ARE PREPARED AND WAITING FOR
9938  * COMMIT/ABORT DECISION.
9939  *------------------------------------------------------------------*/
9940  tcConnectptr.p->failData[tindex] = LqhTransConf::Prepared;
9941  }//for
9942  break;
9943  case OS_COMMITTED:
9944  case OS_COMPLETING:
9945  jam();
9946  arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
9947  for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
9948  jam();
9949  /*-------------------------------------------------------------------
9950  * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
9951  * IN THIS CASE ALL LQH'S ARE COMMITTED AND WAITING FOR
9952  * COMPLETE MESSAGE.
9953  *------------------------------------------------------------------*/
9954  tcConnectptr.p->failData[tindex] = LqhTransConf::Committed;
9955  }//for
9956  break;
9957  case OS_COMPLETED:
9958  jam();
9959  arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
9960  for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
9961  jam();
9962  /*-------------------------------------------------------------------
9963  * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
9964  * IN THIS CASE ALL LQH'S ARE COMPLETED.
9965  *-------------------------------------------------------------------*/
9966  tcConnectptr.p->failData[tindex] = LqhTransConf::InvalidStatus;
9967  }//for
9968  break;
9969  default:
9970  jam();
9971  sendSystemError(signal, __LINE__);
9972  break;
9973  }//switch
9974  if (tabortInd != ZCOMMIT_SETUP) {
9975  jam();
9976  for (UintR Ti = 0; Ti <= tcConnectptr.p->lastReplicaNo; Ti++) {
9977  hostptr.i = tcConnectptr.p->tcNodedata[Ti];
9978  ptrCheckGuard(hostptr, chostFilesize, hostRecord);
9979  if (hostptr.p->hostStatus != HS_ALIVE) {
9980  jam();
9981  /*-----------------------------------------------------------------
9982  * FAILURE OF ANY INVOLVED NODE ALWAYS INVOKES AN ABORT DECISION.
9983  *-----------------------------------------------------------------*/
9984  tabortInd = ZTRUE;
9985  }//if
9986  }//for
9987  }//if
9988  tcConnectptr.p->tcConnectstate = OS_TAKE_OVER;
9989  tcConnectptr.p->tcOprec = tcConnectptr.i;
9990  tcConnectptr.i = tcConnectptr.p->nextTcConnect;
9991  } while (tcConnectptr.i != RNIL);
9992  apiConnectptr.p->tcBlockref = cownref;
9993  apiConnectptr.p->currentTcConnect = apiConnectptr.p->firstTcConnect;
9994  tcConnectptr.i = apiConnectptr.p->firstTcConnect;
9995  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9996  apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
9997  tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9998 }//Dbtc::setupFailData()
9999 
10000 /*----------------------------------------------------------*/
10001 /* UPDATE THE STATE OF THE API CONNECT FOR THIS PART. */
10002 /*----------------------------------------------------------*/
10003 void Dbtc::updateApiStateFail(Signal* signal)
10004 {
10005  if(LqhTransConf::getMarkerFlag(treqinfo))
10006  {
10007  CommitAckMarkerPtr tmp;
10008  const Uint32 marker = apiConnectptr.p->commitAckMarker;
10009  if (marker == RNIL)
10010  {
10011  jam();
10012 
10013  m_commitAckMarkerHash.seize(tmp);
10014  ndbrequire(tmp.i != RNIL);
10015 
10016  apiConnectptr.p->commitAckMarker = tmp.i;
10017  tmp.p->transid1 = ttransid1;
10018  tmp.p->transid2 = ttransid2;
10019  tmp.p->apiNodeId = refToNode(tapplRef);
10020  tmp.p->apiConnectPtr = apiConnectptr.i;
10021  tmp.p->m_commit_ack_marker_nodes.clear();
10022 #if defined VM_TRACE || defined ERROR_INSERT
10023  {
10024  CommitAckMarkerPtr check;
10025  ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
10026  }
10027 #endif
10028  m_commitAckMarkerHash.add(tmp);
10029  } else {
10030  jam();
10031  tmp.i = marker;
10032  tmp.p = m_commitAckMarkerHash.getPtr(marker);
10033 
10034  ndbassert(tmp.p->transid1 == ttransid1);
10035  ndbassert(tmp.p->transid2 == ttransid2);
10036  }
10037  tmp.p->m_commit_ack_marker_nodes.set(tnodeid);
10038  }
10039 
10040  switch (ttransStatus) {
10041  case LqhTransConf::Committed:
10042  jam();
10043  switch (apiConnectptr.p->apiConnectstate) {
10044  case CS_FAIL_COMMITTING:
10045  case CS_FAIL_COMMITTED:
10046  jam();
10047  ndbrequire(tgci == apiConnectptr.p->globalcheckpointid);
10048  break;
10049  case CS_FAIL_PREPARED:
10050  jam();
10051  apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTING;
10052  apiConnectptr.p->globalcheckpointid = tgci;
10053  break;
10054  case CS_FAIL_COMPLETED:
10055  jam();
10056  apiConnectptr.p->globalcheckpointid = tgci;
10057  apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTED;
10058  break;
10059  default:
10060  jam();
10061  systemErrorLab(signal, __LINE__);
10062  break;
10063  }//switch
10064  break;
10065  case LqhTransConf::Prepared:
10066  jam();
10067  switch (apiConnectptr.p->apiConnectstate) {
10068  case CS_FAIL_COMMITTED:
10069  jam();
10070  apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTING;
10071  break;
10072  case CS_FAIL_ABORTED:
10073  jam();
10074  apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTING;
10075  break;
10076  case CS_FAIL_COMMITTING:
10077  case CS_FAIL_PREPARED:
10078  case CS_FAIL_ABORTING:
10079  jam();
10080  /*empty*/;
10081  break;
10082  default:
10083  jam();
10084  systemErrorLab(signal, __LINE__);
10085  break;
10086  }//switch
10087  break;
10088  case LqhTransConf::Aborted:
10089  jam();
10090  switch (apiConnectptr.p->apiConnectstate) {
10091  case CS_FAIL_COMMITTING:
10092  case CS_FAIL_COMMITTED:
10093  jam();
10094  systemErrorLab(signal, __LINE__);
10095  break;
10096  case CS_FAIL_PREPARED:
10097  jam();
10098  apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTING;
10099  break;
10100  case CS_FAIL_ABORTING:
10101  case CS_FAIL_ABORTED:
10102  jam();
10103  /*empty*/;
10104  break;
10105  default:
10106  jam();
10107  systemErrorLab(signal, __LINE__);
10108  break;
10109  }//switch
10110  break;
10111  case LqhTransConf::Marker:
10112  jam();
10113  break;
10114  default:
10115  jam();
10116  systemErrorLab(signal, __LINE__);
10117  break;
10118  }//switch
10119 }//Dbtc::updateApiStateFail()
10120 
10121 /*------------------------------------------------------------*/
10122 /* UPDATE_TC_STATE_FAIL */
10123 /* */
10124 /* WE NEED TO UPDATE THE STATUS OF TC_CONNECT RECORD AND*/
10125 /* WE ALSO NEED TO CHECK THAT THERE IS CONSISTENCY */
10126 /* BETWEEN THE DIFFERENT REPLICAS. */
10127 /*------------------------------------------------------------*/
10128 void Dbtc::updateTcStateFail(Signal* signal, Uint32 instanceKey)
10129 {
10130  const Uint8 treplicaNo = LqhTransConf::getReplicaNo(treqinfo);
10131  const Uint8 tlastReplicaNo = LqhTransConf::getLastReplicaNo(treqinfo);
10132  const Uint8 tdirtyOp = LqhTransConf::getDirtyFlag(treqinfo);
10133 
10134  TcConnectRecord * regTcPtr = tcConnectptr.p;
10135 
10136  ndbrequire(regTcPtr->apiConnect == apiConnectptr.i);
10137  ndbrequire(regTcPtr->failData[treplicaNo] == LqhTransConf::InvalidStatus);
10138  ndbrequire(regTcPtr->lastReplicaNo == tlastReplicaNo);
10139  ndbrequire(regTcPtr->dirtyOp == tdirtyOp);
10140 
10141  regTcPtr->tcNodedata[treplicaNo] = tnodeid;
10142  regTcPtr->failData[treplicaNo] = ttransStatus;
10143  ndbrequire(regTcPtr->lqhInstanceKey == instanceKey)
10144 }//Dbtc::updateTcStateFail()
10145 
10146 void Dbtc::execTCGETOPSIZEREQ(Signal* signal)
10147 {
10148  jamEntry();
10149  CRASH_INSERTION(8000);
10150 
10151  UintR Tuserpointer = signal->theData[0]; /* DBDIH POINTER */
10152  BlockReference Tusersblkref = signal->theData[1];/* DBDIH BLOCK REFERENCE */
10153  signal->theData[0] = Tuserpointer;
10154  signal->theData[1] = coperationsize;
10155  sendSignal(Tusersblkref, GSN_TCGETOPSIZECONF, signal, 2, JBB);
10156 }//Dbtc::execTCGETOPSIZEREQ()
10157 
10158 void Dbtc::execTC_CLOPSIZEREQ(Signal* signal)
10159 {
10160  jamEntry();
10161  CRASH_INSERTION(8001);
10162 
10163  tuserpointer = signal->theData[0];
10164  tusersblkref = signal->theData[1];
10165  /* DBDIH BLOCK REFERENCE */
10166  coperationsize = 0;
10167  signal->theData[0] = tuserpointer;
10168  sendSignal(tusersblkref, GSN_TC_CLOPSIZECONF, signal, 1, JBB);
10169 }//Dbtc::execTC_CLOPSIZEREQ()
10170 
10171 /* ######################################################################### */
10172 /* ####### ERROR MODULE ####### */
10173 /* ######################################################################### */
10174 void Dbtc::tabStateErrorLab(Signal* signal)
10175 {
10176  terrorCode = ZSTATE_ERROR;
10177  releaseAtErrorLab(signal);
10178 }//Dbtc::tabStateErrorLab()
10179 
10180 void Dbtc::wrongSchemaVersionErrorLab(Signal* signal)
10181 {
10182  const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
10183 
10184  TableRecordPtr tabPtr;
10185  tabPtr.i = tcKeyReq->tableId;
10186  const Uint32 schemVer = tcKeyReq->tableSchemaVersion;
10187  ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
10188 
10189  terrorCode = tabPtr.p->getErrorCode(schemVer);
10190 
10191  abortErrorLab(signal);
10192 }//Dbtc::wrongSchemaVersionErrorLab()
10193 
10194 void Dbtc::noFreeConnectionErrorLab(Signal* signal)
10195 {
10196  terrorCode = ZNO_FREE_TC_CONNECTION;
10197  abortErrorLab(signal); /* RECORD. OTHERWISE GOTO ERRORHANDLING */
10198 }//Dbtc::noFreeConnectionErrorLab()
10199 
10200 void Dbtc::aiErrorLab(Signal* signal)
10201 {
10202  terrorCode = ZLENGTH_ERROR;
10203  abortErrorLab(signal);
10204 }//Dbtc::aiErrorLab()
10205 
10206 void Dbtc::seizeDatabuferrorLab(Signal* signal)
10207 {
10208  terrorCode = ZGET_DATAREC_ERROR;
10209  releaseAtErrorLab(signal);
10210 }//Dbtc::seizeDatabuferrorLab()
10211 
10212 void Dbtc::appendToSectionErrorLab(Signal* signal)
10213 {
10214  terrorCode = ZGET_DATAREC_ERROR;
10215  releaseAtErrorLab(signal);
10216 }//Dbtc::appendToSectionErrorLab
10217 
10218 void Dbtc::releaseAtErrorLab(Signal* signal)
10219 {
10220  ptrGuard(tcConnectptr);
10221  tcConnectptr.p->tcConnectstate = OS_ABORTING;
10222  /*-------------------------------------------------------------------------*
10223  * A FAILURE OF THIS OPERATION HAS OCCURRED. THIS FAILURE WAS EITHER A
10224  * FAULTY PARAMETER OR A RESOURCE THAT WAS NOT AVAILABLE.
10225  * WE WILL ABORT THE ENTIRE TRANSACTION SINCE THIS IS THE SAFEST PATH
10226  * TO HANDLE THIS PROBLEM.
10227  * SINCE WE HAVE NOT YET CONTACTED ANY LQH WE SET NUMBER OF NODES TO ZERO
10228  * WE ALSO SET THE STATE TO ABORTING TO INDICATE THAT WE ARE NOT EXPECTING
10229  * ANY SIGNALS.
10230  *-------------------------------------------------------------------------*/
10231  tcConnectptr.p->noOfNodes = 0;
10232  abortErrorLab(signal);
10233 }//Dbtc::releaseAtErrorLab()
10234 
10235 void Dbtc::warningHandlerLab(Signal* signal, int line)
10236 {
10237  ndbassert(false);
10238 }//Dbtc::warningHandlerLab()
10239 
10240 void Dbtc::systemErrorLab(Signal* signal, int line)
10241 {
10242  progError(line, NDBD_EXIT_NDBREQUIRE);
10243 }//Dbtc::systemErrorLab()
10244 
10245 
10246 #ifdef ERROR_INSERT
10247 bool Dbtc::testFragmentDrop(Signal* signal)
10248 {
10249  Uint32 fragIdToDrop= ~0;
10250  /* Drop some fragments to test the dropped fragment handling code */
10251  if (ERROR_INSERTED(8074))
10252  fragIdToDrop= 1;
10253  else if (ERROR_INSERTED(8075))
10254  fragIdToDrop= 2;
10255  else if (ERROR_INSERTED(8076))
10256  fragIdToDrop= 3;
10257 
10258  if ((signal->header.m_fragmentInfo == fragIdToDrop) ||
10259  ERROR_INSERTED(8077)) // Drop all fragments
10260  {
10261  /* This signal fragment should be dropped
10262  * Let's throw away the sections, and call the
10263  * signal dropped report handler
10264  * This code is replicating the effect of the code in
10265  * TransporterCallback::deliver_signal()
10266  */
10267  SectionHandle handle(this, signal);
10268  Uint32 secCount= handle.m_cnt;
10269  releaseSections(handle);
10270  SignalDroppedRep* rep = (SignalDroppedRep*)signal->theData;
10271  Uint32 gsn = signal->header.theVerId_signalNumber;
10272  Uint32 len = signal->header.theLength;
10273  Uint32 newLen= (len > 22 ? 22 : len);
10274  memmove(rep->originalData, signal->theData, (4 * newLen));
10275  rep->originalGsn = gsn;
10276  rep->originalLength = len;
10277  rep->originalSectionCount = secCount;
10278  signal->header.theVerId_signalNumber = GSN_SIGNAL_DROPPED_REP;
10279  signal->header.theLength = newLen + 3;
10280  signal->header.m_noOfSections = 0;
10281 
10282  executeFunction(GSN_SIGNAL_DROPPED_REP, signal);
10283  return true;
10284  }
10285  return false;
10286 }
10287 #endif
10288 
10289 /* ######################################################################### *
10290  * ####### SCAN MODULE ####### *
10291  * ######################################################################### *
10292 
10293  The application orders a scan of a table. We divide the scan into a scan on
10294  each fragment. The scan uses the primary replicas since the scan might be
10295  used for an update in a separate transaction.
10296 
10297  Scans are always done as a separate transaction. Locks from the scan
10298  can be overtaken by another transaction. Scans can never lock the entire
10299  table. Locks are released immediately after the read has been verified
10300  by the application. There is not even an option to leave the locks.
10301  The reason is that this would hurt real-time behaviour too much.
10302 
10303  -# The first step in handling a scan of a table is to receive all signals
10304  defining the scan. If failures occur during this step we release all
10305  resource and reply with SCAN_TABREF providing the error code.
10306  If system load is too high, the request will not be allowed.
10307 
10308  -# The second step retrieves the number of fragments that exist in the
10309  table. It also ensures that the table actually exist. After this,
10310  the scan is ready to be parallelised. The idea is that the receiving
10311  process (hereafter called delivery process) will start up a number
10312  of scan processes. Each of these scan processes will
10313  independently scan one fragment at a time. The delivery
10314  process object is the scan record and the scan process object is
10315  the scan fragment record plus the scan operation record.
10316 
10317  -# The third step is thus performed in parallel. In the third step each
10318  scan process retrieves the primary replica of the fragment it will
10319  scan. Then it starts the scan as soon as the load on that node permits.
10320 
10321  The LQH returns either when it retrieved the maximum number of tuples or
10322  when it has retrived at least one tuple and is hindered by a lock to
10323  retrieve the next tuple. This is to ensure that a scan process never
10324  can be involved in a deadlock situation.
10325 
10326  Tuples from each fragment scan are sent directly to API from TUP, and tuples
10327  from different fragments are delivered in parallel (so will be interleaved
10328  when received).
10329 
10330  When a batch of tuples from one fragment has been fully fetched, the scan of
10331  that fragment will not continue until the previous batch has been
10332  acknowledged by API with a SCAN_NEXTREQ signal.
10333 
10334 
10335  ERROR HANDLING
10336 
10337  As already mentioned it is rather easy to handle errors before the scan
10338  processes have started. In this case it is enough to release the resources
10339  and send SCAN_TAB_REF.
10340 
10341  If an error occurs in any of the scan processes then we have to stop all
10342  scan processes. We do however only stop the delivery process and ask
10343  the api to order us to close the scan. The reason is that we can easily
10344  enter into difficult timing problems since the application and this
10345  block is out of synch we will thus always start by report the error to
10346  the application and wait for a close request. This error report uses the
10347  SCAN_TABREF signal with a special error code that the api must check for.
10348 
10349 
10350  CLOSING AN ACTIVE SCAN
10351 
10352  The application can close a scan for several reasons before it is completed.
10353  One reason was mentioned above where an error in a scan process led to a
10354  request to close the scan. Another reason could simply be that the
10355  application found what it looked for and is thus not interested in the
10356  rest of the scan.
10357 
10358  IT COULD ALSO BE DEPENDENT ON INTERNAL ERRORS IN THE API.
10359 
10360  When a close scan request is received, all scan processes are stopped and all
10361  resources belonging to those scan processes are released. Stopping the scan
10362  processes most often includes communication with an LQH where the local scan
10363  is controlled. Finally all resources belonging to the scan is released and
10364  the SCAN_TABCONF is sent with an indication of that the scan is closed.
10365 
10366 
10367  CLOSING A COMPLETED SCAN
10368 
10369  When all scan processes are completed then a report is sent to the
10370  application which indicates that no more tuples can be fetched.
10371  The application will send a close scan and the same action as when
10372  closing an active scan is performed.
10373  In this case it will of course not find any active scan processes.
10374  It will even find all scan processes already released.
10375 
10376  The reason for requiring the api to close the scan is the same as above.
10377  It is to avoid any timing problems due to that the api and this block
10378  is out of synch.
10379 
10380  * ######################################################################## */
10381 void Dbtc::execSCAN_TABREQ(Signal* signal)
10382 {
10383  jamEntry();
10384 
10385 #ifdef ERROR_INSERT
10386  /* Test fragmented + dropped signal handling */
10387  if (ERROR_INSERTED(8074) ||
10388  ERROR_INSERTED(8075) ||
10389  ERROR_INSERTED(8076) ||
10390  ERROR_INSERTED(8077))
10391  {
10392  jam();
10393  if (testFragmentDrop(signal)) {
10394  jam();
10395  return;
10396  }
10397  } /* End of test fragmented + dropped signal handling */
10398 #endif
10399 
10400  /* Reassemble if the request was fragmented */
10401  if (!assembleFragments(signal)){
10402  jam();
10403  return;
10404  }
10405 
10406  const ScanTabReq * const scanTabReq = (ScanTabReq *)&signal->theData[0];
10407  const Uint32 ri = scanTabReq->requestInfo;
10408  const Uint32 schemaVersion = scanTabReq->tableSchemaVersion;
10409  const Uint32 transid1 = scanTabReq->transId1;
10410  const Uint32 transid2 = scanTabReq->transId2;
10411  const Uint32 tmpXX = scanTabReq->buddyConPtr;
10412  const Uint32 buddyPtr = (tmpXX == 0xFFFFFFFF ? RNIL : tmpXX);
10413  Uint32 currSavePointId = 0;
10414 
10415  Uint32 scanConcurrency = scanTabReq->getParallelism(ri);
10416  Uint32 noOprecPerFrag = ScanTabReq::getScanBatch(ri);
10417  Uint32 scanParallel = scanConcurrency;
10418  Uint32 errCode;
10419  ScanRecordPtr scanptr;
10420 
10421  /* Short SCANTABREQ has 1 section, Long has 2 or 3.
10422  * Section 0 : NDBAPI receiver ids (Mandatory)
10423  * Section 1 : ATTRINFO section (Mandatory for long SCAN_TABREQ
10424  * Section 2 : KEYINFO section (Optional for long SCAN_TABREQ
10425  */
10426  Uint32 numSections= signal->getNoOfSections();
10427  ndbassert( numSections >= 1 );
10428  bool isLongReq= numSections >= 2;
10429 
10430  SectionHandle handle(this, signal);
10431  SegmentedSectionPtr api_op_ptr;
10432  handle.getSection(api_op_ptr, 0);
10433  copy(&cdata[0], api_op_ptr);
10434 
10435  Uint32 aiLength= 0;
10436  Uint32 keyLen= 0;
10437 
10438  if (likely(isLongReq))
10439  {
10440  SegmentedSectionPtr attrInfoPtr, keyInfoPtr;
10441  /* Long SCANTABREQ, determine Ai and Key length from sections */
10442  handle.getSection(attrInfoPtr, ScanTabReq::AttrInfoSectionNum);
10443  aiLength= attrInfoPtr.sz;
10444  if (numSections == 3)
10445  {
10446  handle.getSection(keyInfoPtr, ScanTabReq::KeyInfoSectionNum);
10447  keyLen= keyInfoPtr.sz;
10448  }
10449  }
10450  else
10451  {
10452  /* Short SCANTABREQ, get Ai and Key length from signal */
10453  aiLength = (scanTabReq->attrLenKeyLen & 0xFFFF);
10454  keyLen = scanTabReq->attrLenKeyLen >> 16;
10455  }
10456 
10457 
10458  apiConnectptr.i = scanTabReq->apiConnectPtr;
10459  tabptr.i = scanTabReq->tableId;
10460 
10461  if (apiConnectptr.i >= capiConnectFilesize)
10462  {
10463  jam();
10464  releaseSections(handle);
10465  warningHandlerLab(signal, __LINE__);
10466  return;
10467  }//if
10468 
10469  ptrAss(apiConnectptr, apiConnectRecord);
10470  ApiConnectRecord * transP = apiConnectptr.p;
10471 
10472  if (transP->apiConnectstate != CS_CONNECTED) {
10473  jam();
10474  // could be left over from TCKEYREQ rollback
10475  if (transP->apiConnectstate == CS_ABORTING &&
10476  transP->abortState == AS_IDLE) {
10477  jam();
10478  } else if(transP->apiConnectstate == CS_STARTED &&
10479  transP->firstTcConnect == RNIL){
10480  jam();
10481  // left over from simple/dirty read
10482  } else {
10483  jam();
10484  jamLine(transP->apiConnectstate);
10485  errCode = ZSTATE_ERROR;
10486  goto SCAN_TAB_error_no_state_change;
10487  }
10488  }
10489 
10490  if(tabptr.i >= ctabrecFilesize)
10491  {
10492  errCode = ZUNKNOWN_TABLE_ERROR;
10493  goto SCAN_TAB_error;
10494  }
10495 
10496  ptrAss(tabptr, tableRecord);
10497  if ((aiLength == 0) ||
10498  (!tabptr.p->checkTable(schemaVersion)) ||
10499  (scanConcurrency == 0) ||
10500  (cfirstfreeTcConnect == RNIL) ||
10501  (cfirstfreeScanrec == RNIL)) {
10502  goto SCAN_error_check;
10503  }
10504  if (buddyPtr != RNIL) {
10505  jam();
10506  ApiConnectRecordPtr buddyApiPtr;
10507  buddyApiPtr.i = buddyPtr;
10508  ptrCheckGuard(buddyApiPtr, capiConnectFilesize, apiConnectRecord);
10509  if ((transid1 == buddyApiPtr.p->transid[0]) &&
10510  (transid2 == buddyApiPtr.p->transid[1])) {
10511  jam();
10512 
10513  if (buddyApiPtr.p->apiConnectstate == CS_ABORTING) {
10514  // transaction has been aborted
10515  jam();
10516  errCode = buddyApiPtr.p->returncode;
10517  goto SCAN_TAB_error;
10518  }//if
10519  currSavePointId = buddyApiPtr.p->currSavePointId;
10520  buddyApiPtr.p->currSavePointId++;
10521  }
10522  }
10523 
10524  if (getNodeState().startLevel == NodeState::SL_SINGLEUSER &&
10525  getNodeState().getSingleUserApi() !=
10526  refToNode(apiConnectptr.p->ndbapiBlockref))
10527  {
10528  errCode = ZCLUSTER_IN_SINGLEUSER_MODE;
10529  goto SCAN_TAB_error;
10530  }
10531 
10532  seizeTcConnect(signal);
10533  tcConnectptr.p->apiConnect = apiConnectptr.i;
10534  tcConnectptr.p->tcConnectstate = OS_WAIT_SCAN;
10535  apiConnectptr.p->lastTcConnect = tcConnectptr.i;
10536 
10537  seizeCacheRecord(signal);
10538 
10539  if (likely(isLongReq))
10540  {
10541  /* We keep the AttrInfo and KeyInfo sections */
10542  cachePtr.p->attrInfoSectionI= handle.m_ptr[ScanTabReq::AttrInfoSectionNum].i;
10543  if (keyLen)
10544  cachePtr.p->keyInfoSectionI= handle.m_ptr[ScanTabReq::KeyInfoSectionNum].i;
10545  }
10546 
10547  releaseSection(handle.m_ptr[ScanTabReq::ReceiverIdSectionNum].i);
10548  handle.clear();
10549 
10550  cachePtr.p->keylen = keyLen;
10551  cachePtr.p->save1 = 0;
10552  cachePtr.p->distributionKey = scanTabReq->distributionKey;
10553  cachePtr.p->distributionKeyIndicator= ScanTabReq::getDistributionKeyFlag(ri);
10554  scanptr = seizeScanrec(signal);
10555 
10556  ndbrequire(transP->apiScanRec == RNIL);
10557  ndbrequire(scanptr.p->scanApiRec == RNIL);
10558 
10559  errCode = initScanrec(scanptr, scanTabReq, scanParallel, noOprecPerFrag, aiLength, keyLen);
10560  if (unlikely(errCode))
10561  {
10562  jam();
10563  goto SCAN_TAB_error;
10564  }
10565 
10566  transP->apiScanRec = scanptr.i;
10567  transP->returncode = 0;
10568  transP->transid[0] = transid1;
10569  transP->transid[1] = transid2;
10570  transP->buddyPtr = buddyPtr;
10571 
10572  // The scan is started
10573  transP->apiConnectstate = CS_START_SCAN;
10574  transP->currSavePointId = currSavePointId;
10575 
10576  /**********************************************************
10577  * We start the timer on scanRec to be able to discover a
10578  * timeout in the API the API now is in charge!
10579  ***********************************************************/
10580  setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
10581  updateBuddyTimer(apiConnectptr);
10582 
10583  /***********************************************************
10584  * WE HAVE NOW RECEIVED ALL REFERENCES TO SCAN OBJECTS IN
10585  * THE API. WE ARE NOW READY TO RECEIVE THE ATTRIBUTE INFO
10586  * IF ANY TO RECEIVE.
10587  **********************************************************/
10588  scanptr.p->scanState = ScanRecord::WAIT_AI;
10589 
10590  if (ERROR_INSERTED(8038))
10591  {
10595  DisconnectRep * const rep = (DisconnectRep *)signal->getDataPtrSend();
10596  rep->nodeId = refToNode(apiConnectptr.p->ndbapiBlockref);
10597  rep->err = 8038;
10598 
10599  sendSignal(CMVMI_REF, GSN_DISCONNECT_REP, signal, 2, JBA);
10600  CLEAR_ERROR_INSERT_VALUE;
10601  }
10602 
10603  if (isLongReq)
10604  {
10605  /* All AttrInfo (and KeyInfo) has been received, continue
10606  * processing
10607  */
10608  diFcountReqLab(signal, scanptr);
10609  }
10610 
10611  return;
10612 
10613  SCAN_error_check:
10614  if (aiLength == 0) {
10615  jam();
10616  errCode = ZSCAN_AI_LEN_ERROR;
10617  goto SCAN_TAB_error;
10618  }//if
10619  if (!tabptr.p->checkTable(schemaVersion)){
10620  jam();
10621  errCode = tabptr.p->getErrorCode(schemaVersion);
10622  goto SCAN_TAB_error;
10623  }//if
10624  if (scanConcurrency == 0) {
10625  jam();
10626  errCode = ZNO_CONCURRENCY_ERROR;
10627  goto SCAN_TAB_error;
10628  }//if
10629  if (cfirstfreeTcConnect == RNIL) {
10630  jam();
10631  errCode = ZNO_FREE_TC_CONNECTION;
10632  goto SCAN_TAB_error;
10633  }//if
10634  ndbrequire(cfirstfreeScanrec == RNIL);
10635  jam();
10636  errCode = ZNO_SCANREC_ERROR;
10637  goto SCAN_TAB_error;
10638 
10639 SCAN_TAB_error:
10640  jam();
10644  transP->apiConnectstate = CS_ABORTING;
10645  transP->abortState = AS_IDLE;
10646  transP->transid[0] = transid1;
10647  transP->transid[1] = transid2;
10648 
10649 SCAN_TAB_error_no_state_change:
10650 
10651  releaseSections(handle);
10652 
10653  ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
10654  ref->apiConnectPtr = transP->ndbapiConnect;
10655  ref->transId1 = transid1;
10656  ref->transId2 = transid2;
10657  ref->errorCode = errCode;
10658  ref->closeNeeded = 0;
10659  sendSignal(transP->ndbapiBlockref, GSN_SCAN_TABREF,
10660  signal, ScanTabRef::SignalLength, JBB);
10661  return;
10662 }//Dbtc::execSCAN_TABREQ()
10663 
10664 Uint32
10665 Dbtc::initScanrec(ScanRecordPtr scanptr,
10666  const ScanTabReq * scanTabReq,
10667  UintR scanParallel,
10668  UintR noOprecPerFrag,
10669  Uint32 aiLength,
10670  Uint32 keyLength)
10671 {
10672  const UintR ri = scanTabReq->requestInfo;
10673  scanptr.p->scanTcrec = tcConnectptr.i;
10674  scanptr.p->scanApiRec = apiConnectptr.i;
10675  scanptr.p->scanAiLength = aiLength;
10676  scanptr.p->scanKeyLen = keyLength;
10677  scanptr.p->scanTableref = tabptr.i;
10678  scanptr.p->scanSchemaVersion = scanTabReq->tableSchemaVersion;
10679  scanptr.p->scanParallel = scanParallel;
10680  scanptr.p->first_batch_size_rows = scanTabReq->first_batch_size;
10681  scanptr.p->batch_byte_size = scanTabReq->batch_byte_size;
10682  scanptr.p->batch_size_rows = noOprecPerFrag;
10683  scanptr.p->m_scan_block_no = DBLQH;
10684 
10685  Uint32 tmp = 0;
10686  ScanFragReq::setLockMode(tmp, ScanTabReq::getLockMode(ri));
10687  ScanFragReq::setHoldLockFlag(tmp, ScanTabReq::getHoldLockFlag(ri));
10688  ScanFragReq::setKeyinfoFlag(tmp, ScanTabReq::getKeyinfoFlag(ri));
10689  ScanFragReq::setReadCommittedFlag(tmp,ScanTabReq::getReadCommittedFlag(ri));
10690  ScanFragReq::setRangeScanFlag(tmp, ScanTabReq::getRangeScanFlag(ri));
10691  ScanFragReq::setDescendingFlag(tmp, ScanTabReq::getDescendingFlag(ri));
10692  ScanFragReq::setTupScanFlag(tmp, ScanTabReq::getTupScanFlag(ri));
10693  ScanFragReq::setNoDiskFlag(tmp, ScanTabReq::getNoDiskFlag(ri));
10694  if (ScanTabReq::getViaSPJFlag(ri))
10695  {
10696  jam();
10697  scanptr.p->m_scan_block_no = DBSPJ;
10698  }
10699 
10700  scanptr.p->scanRequestInfo = tmp;
10701  scanptr.p->scanStoredProcId = scanTabReq->storedProcId;
10702  scanptr.p->scanState = ScanRecord::RUNNING;
10703  scanptr.p->m_queued_count = 0;
10704  scanptr.p->m_scan_cookie = RNIL;
10705  scanptr.p->m_close_scan_req = false;
10706  scanptr.p->m_pass_all_confs = ScanTabReq::getPassAllConfsFlag(ri);
10707  scanptr.p->m_4word_conf = ScanTabReq::get4WordConf(ri);
10708 
10709  ScanFragList list(c_scan_frag_pool,
10710  scanptr.p->m_running_scan_frags);
10711  for (Uint32 i = 0; i < scanParallel; i++) {
10712  jam();
10713  ScanFragRecPtr ptr;
10714  if (unlikely(list.seize(ptr) == false))
10715  {
10716  jam();
10717  goto errout;
10718  }
10719  ptr.p->scanFragState = ScanFragRec::IDLE;
10720  ptr.p->scanRec = scanptr.i;
10721  ptr.p->scanFragId = 0;
10722  ptr.p->m_apiPtr = cdata[i];
10723  }//for
10724 
10725  (* (ScanTabReq::getRangeScanFlag(ri) ?
10726  &c_counters.c_range_scan_count :
10727  &c_counters.c_scan_count))++;
10728  return 0;
10729 errout:
10730  list.release();
10731  return ZSCAN_FRAGREC_ERROR;
10732 }//Dbtc::initScanrec()
10733 
10734 void Dbtc::scanTabRefLab(Signal* signal, Uint32 errCode)
10735 {
10736  ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
10737  ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
10738  ref->transId1 = apiConnectptr.p->transid[0];
10739  ref->transId2 = apiConnectptr.p->transid[1];
10740  ref->errorCode = errCode;
10741  ref->closeNeeded = 0;
10742  sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF,
10743  signal, ScanTabRef::SignalLength, JBB);
10744 }//Dbtc::scanTabRefLab()
10745 
10750 void Dbtc::scanKeyinfoLab(Signal* signal)
10751 {
10752  /* Receive KEYINFO for a SCAN operation
10753  * Note that old NDBAPI nodes sometimes send header-only KEYINFO signals
10754  */
10755  CacheRecord * const regCachePtr = cachePtr.p;
10756  UintR TkeyLen = regCachePtr->keylen;
10757  UintR Tlen = regCachePtr->save1;
10758 
10759  Uint32 wordsInSignal= MIN(KeyInfo::DataLength,
10760  (TkeyLen - Tlen));
10761 
10762  ndbassert( signal->getLength() ==
10763  (KeyInfo::HeaderLength + wordsInSignal) );
10764 
10765  if (unlikely (! appendToSection(regCachePtr->keyInfoSectionI,
10766  &signal->theData[KeyInfo::HeaderLength],
10767  wordsInSignal)))
10768  {
10769  jam();
10770  seizeDatabuferrorLab(signal);
10771  return;
10772  }
10773 
10774  Tlen+= wordsInSignal;
10775  regCachePtr->save1 = Tlen;
10776 
10777  if (Tlen < TkeyLen)
10778  {
10779  jam();
10780  /* More KeyInfo still to come - continue waiting */
10781  setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
10782  return;
10783  }
10784 
10785  /* All KeyInfo has been received, we will now start receiving
10786  * ATTRINFO
10787  */
10788  jam();
10789  ndbassert(Tlen == TkeyLen);
10790  return;
10791 } // scanKeyinfoLab
10792 
10793 /*---------------------------------------------------------------------------*/
10794 /* */
10795 /* RECEPTION OF ATTRINFO FOR SCAN TABLE REQUEST. */
10796 /*---------------------------------------------------------------------------*/
10797 void Dbtc::scanAttrinfoLab(Signal* signal, UintR Tlen)
10798 {
10799  ScanRecordPtr scanptr;
10800  scanptr.i = apiConnectptr.p->apiScanRec;
10801  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
10802  tcConnectptr.i = scanptr.p->scanTcrec;
10803  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
10804  cachePtr.i = apiConnectptr.p->cachePtr;
10805  ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
10806  CacheRecord * const regCachePtr = cachePtr.p;
10807  ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_AI);
10808 
10809  regCachePtr->currReclenAi = regCachePtr->currReclenAi + Tlen;
10810 
10811  if (unlikely(! appendToSection(regCachePtr->attrInfoSectionI,
10812  &signal->theData[AttrInfo::HeaderLength],
10813  Tlen)))
10814  {
10815  jam();
10816  abortScanLab(signal, scanptr, ZGET_ATTRBUF_ERROR, true);
10817  return;
10818  }
10819 
10820  if (regCachePtr->currReclenAi == scanptr.p->scanAiLength)
10821  {
10822  /* We have now received all the signals defining this
10823  * scan. We are ready to start executing the scan
10824  */
10825  diFcountReqLab(signal, scanptr);
10826  return;
10827  }
10828  else if (unlikely (regCachePtr->currReclenAi > scanptr.p->scanAiLength))
10829  {
10830  jam();
10831  abortScanLab(signal, scanptr, ZLENGTH_ERROR, true);
10832  return;
10833  }
10834 
10835  /* Still some ATTRINFO to arrive...*/
10836  return;
10837 }//Dbtc::scanAttrinfoLab()
10838 
10839 void Dbtc::diFcountReqLab(Signal* signal, ScanRecordPtr scanptr)
10840 {
10844  TableRecordPtr tabPtr;
10845  tabPtr.i = scanptr.p->scanTableref;
10846  tabPtr.p = &tableRecord[tabPtr.i];
10847  if (tabPtr.p->checkTable(scanptr.p->scanSchemaVersion)){
10848  ;
10849  } else {
10850  abortScanLab(signal, scanptr,
10851  tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion),
10852  true);
10853  return;
10854  }
10855 
10856  scanptr.p->scanNextFragId = 0;
10857  scanptr.p->m_booked_fragments_count= 0;
10858  scanptr.p->scanState = ScanRecord::WAIT_FRAGMENT_COUNT;
10859 
10860  /*************************************************
10861  * THE FIRST STEP TO RECEIVE IS SUCCESSFULLY COMPLETED.
10862  ***************************************************/
10863  DihScanTabReq * req = (DihScanTabReq*)signal->getDataPtrSend();
10864  req->senderRef = reference();
10865  req->senderData = tcConnectptr.i;
10866  req->tableId = scanptr.p->scanTableref;
10867  req->schemaTransId = 0;
10868  sendSignal(cdihblockref, GSN_DIH_SCAN_TAB_REQ, signal,
10869  DihScanTabReq::SignalLength, JBB);
10870  return;
10871 }//Dbtc::diFcountReqLab()
10872 
10873 /********************************************************************
10874  * execDI_FCOUNTCONF
10875  *
10876  * WE HAVE ASKED DIH ABOUT THE NUMBER OF FRAGMENTS IN THIS TABLE.
10877  * WE WILL NOW START A NUMBER OF PARALLEL SCAN PROCESSES. EACH OF
10878  * THESE WILL SCAN ONE FRAGMENT AT A TIME. THEY WILL CONTINUE THIS
10879  * UNTIL THERE ARE NO MORE FRAGMENTS TO SCAN OR UNTIL THE APPLICATION
10880  * CLOSES THE SCAN.
10881  ********************************************************************/
10882 void Dbtc::execDIH_SCAN_TAB_CONF(Signal* signal)
10883 {
10884  jamEntry();
10885  DihScanTabConf * conf = (DihScanTabConf*)signal->getDataPtr();
10886  tcConnectptr.i = conf->senderData;
10887  Uint32 tfragCount = conf->fragmentCount;
10888  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
10889  apiConnectptr.i = tcConnectptr.p->apiConnect;
10890  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10891  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
10892  ScanRecordPtr scanptr;
10893  scanptr.i = regApiPtr->apiScanRec;
10894  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
10895  ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT);
10896  scanptr.p->m_scan_cookie = conf->scanCookie;
10897 
10898  if (conf->reorgFlag)
10899  {
10900  jam();
10901  ScanFragReq::setReorgFlag(scanptr.p->scanRequestInfo, 1);
10902  }
10903  if (regApiPtr->apiFailState == ZTRUE) {
10904  jam();
10905  releaseScanResources(signal, scanptr, true);
10906  handleApiFailState(signal, apiConnectptr.i);
10907  return;
10908  }//if
10909  if (tfragCount == 0) {
10910  jam();
10911  abortScanLab(signal, scanptr, ZNO_FRAGMENT_ERROR, true);
10912  return;
10913  }//if
10914 
10918  TableRecordPtr tabPtr;
10919  tabPtr.i = scanptr.p->scanTableref;
10920  tabPtr.p = &tableRecord[tabPtr.i];
10921  if (tabPtr.p->checkTable(scanptr.p->scanSchemaVersion)){
10922  ;
10923  } else {
10924  abortScanLab(signal, scanptr,
10925  tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion),
10926  true);
10927  return;
10928  }
10929 
10930  cachePtr.i = regApiPtr->cachePtr;
10931  ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
10932  CacheRecord * regCachePtrP = cachePtr.p;
10933 
10934  Uint32 version = getNodeInfo(refToNode(regApiPtr->ndbapiBlockref)).m_version;
10935  if (unlikely(!ndb_scan_distributionkey(version)))
10936  {
10937  jam();
10938  regCachePtrP->distributionKeyIndicator = 0;
10939  }
10940  if (regCachePtrP->distributionKeyIndicator)
10941  {
10942  jam();
10943  ndbrequire(DictTabInfo::isOrderedIndex(tabPtr.p->tableType) ||
10944  tabPtr.p->get_user_defined_partitioning());
10945 
10946  DiGetNodesReq * req = (DiGetNodesReq *)&signal->theData[0];
10947  const DiGetNodesConf * get_conf = (DiGetNodesConf *)&signal->theData[0];
10948  req->tableId = tabPtr.i;
10949  req->hashValue = cachePtr.p->distributionKey;
10950  req->distr_key_indicator = tabPtr.p->get_user_defined_partitioning();
10951  * (EmulatedJamBuffer**)req->jamBuffer = jamBuffer();
10952  EXECUTE_DIRECT(DBDIH, GSN_DIGETNODESREQ, signal,
10953  DiGetNodesReq::SignalLength, 0);
10954  UintR TerrorIndicator = signal->theData[0];
10955  jamEntry();
10956  if (TerrorIndicator != 0)
10957  {
10958  jam();
10959  abortScanLab(signal, scanptr,
10960  signal->theData[1],
10961  true);
10962  return;
10963  }
10964 
10965  scanptr.p->scanNextFragId = get_conf->fragId;
10966  tfragCount = 1;
10967  }
10968 
10969  scanptr.p->scanParallel = tfragCount;
10970  scanptr.p->scanNoFrag = tfragCount;
10971  scanptr.p->scanState = ScanRecord::RUNNING;
10972 
10973  setApiConTimer(apiConnectptr.i, 0, __LINE__);
10974  updateBuddyTimer(apiConnectptr);
10975 
10976  ScanFragRecPtr ptr;
10977  ScanFragList list(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
10978  for (list.first(ptr); !ptr.isNull() && tfragCount;
10979  list.next(ptr), tfragCount--){
10980  jam();
10981 
10982  ptr.p->lqhBlockref = 0;
10983  ptr.p->startFragTimer(ctcTimer);
10984  ptr.p->scanFragId = scanptr.p->scanNextFragId++;
10985  ptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
10986  ptr.p->startFragTimer(ctcTimer);
10987 
10988 
10989  DihScanGetNodesReq* req = (DihScanGetNodesReq*)signal->getDataPtrSend();
10990  req->senderRef = reference();
10991  req->senderData = ptr.i;
10992  req->tableId = scanptr.p->scanTableref;
10993  req->fragId = ptr.p->scanFragId;
10994  req->scanCookie = scanptr.p->m_scan_cookie;
10995  sendSignal(cdihblockref, GSN_DIH_SCAN_GET_NODES_REQ, signal,
10996  DihScanGetNodesReq::SignalLength, JBB);
10997  }//for
10998 
10999  ScanFragList queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags);
11000  for (; !ptr.isNull();)
11001  {
11002  ptr.p->m_ops = 0;
11003  ptr.p->m_totalLen = 0;
11004  ptr.p->m_scan_frag_conf_status = 1;
11005  ptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
11006  ptr.p->stopFragTimer();
11007 
11008  ScanFragRecPtr tmp;
11009  tmp.i = ptr.i;
11010  tmp.p = ptr.p;
11011  list.next(ptr);
11012  list.remove(tmp);
11013  queued.add(tmp);
11014  scanptr.p->m_queued_count++;
11015  }
11016 }//Dbtc::execDI_FCOUNTCONF()
11017 
11018 /******************************************************
11019  * execDI_FCOUNTREF
11020  ******************************************************/
11021 void Dbtc::execDIH_SCAN_TAB_REF(Signal* signal)
11022 {
11023  jamEntry();
11024  DihScanTabRef * ref = (DihScanTabRef*)signal->getDataPtr();
11025  tcConnectptr.i = ref->senderData;
11026  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
11027  const Uint32 errCode = ref->error;
11028  apiConnectptr.i = tcConnectptr.p->apiConnect;
11029  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11030  ScanRecordPtr scanptr;
11031  scanptr.i = apiConnectptr.p->apiScanRec;
11032  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
11033  ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT);
11034  if (apiConnectptr.p->apiFailState == ZTRUE) {
11035  jam();
11036  releaseScanResources(signal, scanptr, true);
11037  handleApiFailState(signal, apiConnectptr.i);
11038  return;
11039  }//if
11040  abortScanLab(signal, scanptr, errCode, true);
11041 }//Dbtc::execDI_FCOUNTREF()
11042 
11043 void Dbtc::abortScanLab(Signal* signal, ScanRecordPtr scanptr, Uint32 errCode,
11044  bool not_started)
11045 {
11046  scanTabRefLab(signal, errCode);
11047  releaseScanResources(signal, scanptr, not_started);
11048 }//Dbtc::abortScanLab()
11049 
11050 void Dbtc::releaseScanResources(Signal* signal,
11051  ScanRecordPtr scanPtr,
11052  bool not_started)
11053 {
11054  if (apiConnectptr.p->cachePtr != RNIL) {
11055  cachePtr.i = apiConnectptr.p->cachePtr;
11056  ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
11057  releaseKeys();
11058  releaseAttrinfo();
11059  }//if
11060  tcConnectptr.i = scanPtr.p->scanTcrec;
11061  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
11062  releaseTcCon();
11063 
11064  if (not_started)
11065  {
11066  jam();
11067  ScanFragList run(c_scan_frag_pool, scanPtr.p->m_running_scan_frags);
11068  ScanFragList queue(c_scan_frag_pool, scanPtr.p->m_queued_scan_frags);
11069  run.release();
11070  queue.release();
11071  }
11072 
11073  ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty());
11074  ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty());
11075  ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty());
11076 
11077  ndbassert(scanPtr.p->scanApiRec == apiConnectptr.i);
11078  ndbassert(apiConnectptr.p->apiScanRec == scanPtr.i);
11079 
11080  DihScanTabCompleteRep* rep = (DihScanTabCompleteRep*)signal->getDataPtrSend();
11081  rep->tableId = scanPtr.p->scanTableref;
11082  rep->scanCookie = scanPtr.p->m_scan_cookie;
11083  sendSignal(cdihblockref, GSN_DIH_SCAN_TAB_COMPLETE_REP,
11084  signal, DihScanTabCompleteRep::SignalLength, JBB);
11085 
11086  // link into free list
11087  scanPtr.p->nextScan = cfirstfreeScanrec;
11088  scanPtr.p->scanState = ScanRecord::IDLE;
11089  scanPtr.p->scanTcrec = RNIL;
11090  scanPtr.p->scanApiRec = RNIL;
11091  cfirstfreeScanrec = scanPtr.i;
11092 
11093  apiConnectptr.p->apiScanRec = RNIL;
11094  apiConnectptr.p->apiConnectstate = CS_CONNECTED;
11095  setApiConTimer(apiConnectptr.i, 0, __LINE__);
11096 }//Dbtc::releaseScanResources()
11097 
11098 
11099 /****************************************************************
11100  * execDIGETPRIMCONF
11101  *
11102  * WE HAVE RECEIVED THE PRIMARY NODE OF THIS FRAGMENT.
11103  * WE ARE NOW READY TO ASK FOR PERMISSION TO LOAD THIS
11104  * SPECIFIC NODE WITH A SCAN OPERATION.
11105  ****************************************************************/
11106 void Dbtc::execDIH_SCAN_GET_NODES_CONF(Signal* signal)
11107 {
11108  jamEntry();
11109  DihScanGetNodesConf * conf = (DihScanGetNodesConf*)signal->getDataPtr();
11110  scanFragptr.i = conf->senderData;
11111  c_scan_frag_pool.getPtr(scanFragptr);
11112 
11113  tnodeid = conf->nodes[0];
11114  arrGuard(tnodeid, MAX_NDB_NODES);
11115 
11116  if(ERROR_INSERTED(8050) && tnodeid != getOwnNodeId())
11117  {
11118  /* Asked to scan a fragment which is not on the same node as the
11119  * TC - transaction hinting / scan partition pruning has failed
11120  * Used by testPartitioning.cpp
11121  */
11122  CRASH_INSERTION(8050);
11123  }
11124 
11125  ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF);
11126  scanFragptr.p->stopFragTimer();
11127 
11128  ScanRecordPtr scanptr;
11129  scanptr.i = scanFragptr.p->scanRec;
11130  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
11131 
11137  if(false && ScanFragReq::getReadCommittedFlag(scanptr.p->scanRequestInfo))
11138  {
11139  jam();
11140  Uint32 nodeid = getOwnNodeId();
11141  for(Uint32 i = 1; i<conf->count; i++)
11142  {
11143  if(conf->nodes[i] == nodeid)
11144  {
11145  jam();
11146  tnodeid = nodeid;
11147  break;
11148  }
11149  }
11150  }
11151 
11152  {
11156  TableRecordPtr tabPtr;
11157  tabPtr.i = scanptr.p->scanTableref;
11158  ptrAss(tabPtr, tableRecord);
11159  Uint32 schemaVersion = scanptr.p->scanSchemaVersion;
11160  if (ERROR_INSERTED(8081) || tabPtr.p->checkTable(schemaVersion) == false)
11161  {
11162  jam();
11163  Uint32 err;
11164  if (ERROR_INSERTED(8081))
11165  {
11166  err = ZTIME_OUT_ERROR;
11167  CLEAR_ERROR_INSERT_VALUE;
11168  }
11169  else
11170  {
11171  err = tabPtr.p->getErrorCode(schemaVersion);
11172  }
11173  {
11174  ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
11175  run.release(scanFragptr);
11176  }
11177  scanError(signal, scanptr, err);
11178  return;
11179  }
11180  }
11181 
11182  tcConnectptr.i = scanptr.p->scanTcrec;
11183  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
11184  apiConnectptr.i = scanptr.p->scanApiRec;
11185  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11186  cachePtr.i = apiConnectptr.p->cachePtr;
11187  ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
11188  switch (scanptr.p->scanState) {
11189  case ScanRecord::CLOSING_SCAN:
11190  jam();
11191  updateBuddyTimer(apiConnectptr);
11192  {
11193  ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
11194  run.release(scanFragptr);
11195  }
11196  close_scan_req_send_conf(signal, scanptr);
11197  return;
11198  default:
11199  jam();
11200  /*empty*/;
11201  break;
11202  }//switch
11203 
11204  /* Send SCANFRAGREQ to LQH block
11205  * SCANFRAGREQ with optional KEYINFO and mandatory ATTRINFO are
11206  * now sent to LQH
11207  * This starts the scan on the given fragment.
11208  * If this is the last SCANFRAGREQ, sendScanFragReq will release
11209  * the KeyInfo and AttrInfo sections when sending.
11210  */
11211  Uint32 instanceKey = conf->instanceKey;
11212  scanFragptr.p->lqhBlockref = numberToRef(scanptr.p->m_scan_block_no,
11213  instanceKey, tnodeid);
11214  if (scanptr.p->m_scan_block_no == DBSPJ)
11215  {
11216  // only 1 instance
11217  scanFragptr.p->lqhBlockref = numberToRef(scanptr.p->m_scan_block_no,
11218  tnodeid);
11219  }
11220  scanFragptr.p->m_connectCount = getNodeInfo(tnodeid).m_connectCount;
11221 
11222  /* Determine whether this is the last scanFragReq
11223  * Handle normal scan-all-fragments and partition pruned
11224  * scan-one-fragment cases.
11225  *
11226  * (Note that this assumes that fragments are processed in order,
11227  * and that DIH_SCAN_GET_NODES_CONF signals are received in the
11228  * order that the DIH_SCAN_GET_NODES_REQs were sent)
11229  */
11230  bool isLastScanFragReq= ((scanptr.p->scanNextFragId >=
11231  scanptr.p->scanNoFrag) &&
11232  (scanFragptr.p->scanFragId ==
11233  (scanptr.p->scanNextFragId - 1)));
11234 
11235  sendScanFragReq(signal, scanptr.p, scanFragptr.p, isLastScanFragReq);
11236 
11237  scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
11238  scanFragptr.p->startFragTimer(ctcTimer);
11239  updateBuddyTimer(apiConnectptr);
11240  /*********************************************
11241  * WE HAVE NOW STARTED A FRAGMENT SCAN. NOW
11242  * WAIT FOR THE FIRST SCANNED RECORDS
11243  *********************************************/
11244 }//Dbtc::execDIGETPRIMCONF
11245 
11246 /***************************************************
11247  * execDIGETPRIMREF
11248  *
11249  * WE ARE NOW FORCED TO STOP THE SCAN. THIS ERROR
11250  * IS NOT RECOVERABLE SINCE THERE IS A PROBLEM WITH
11251  * FINDING A PRIMARY REPLICA OF A CERTAIN FRAGMENT.
11252  ***************************************************/
11253 void Dbtc::execDIH_SCAN_GET_NODES_REF(Signal* signal)
11254 {
11255  jamEntry();
11256  // tcConnectptr.i in theData[0] is not used.
11257  scanFragptr.i = signal->theData[1];
11258  const Uint32 errCode = signal->theData[2];
11259  c_scan_frag_pool.getPtr(scanFragptr);
11260  ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF);
11261 
11262  ScanRecordPtr scanptr;
11263  scanptr.i = scanFragptr.p->scanRec;
11264  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
11265 
11266  {
11267  ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
11268  run.release(scanFragptr);
11269  }
11270 
11271  scanError(signal, scanptr, errCode);
11272 }//Dbtc::execDIGETPRIMREF()
11273 
11280 void Dbtc::execSCAN_FRAGREF(Signal* signal)
11281 {
11282  const ScanFragRef * const ref = (ScanFragRef *)&signal->theData[0];
11283 
11284  jamEntry();
11285  const Uint32 errCode = ref->errorCode;
11286 
11287  scanFragptr.i = ref->senderData;
11288  c_scan_frag_pool.getPtr(scanFragptr);
11289 
11290  ScanRecordPtr scanptr;
11291  scanptr.i = scanFragptr.p->scanRec;
11292  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
11293 
11294  apiConnectptr.i = scanptr.p->scanApiRec;
11295  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11296 
11297  Uint32 transid1 = apiConnectptr.p->transid[0] ^ ref->transId1;
11298  Uint32 transid2 = apiConnectptr.p->transid[1] ^ ref->transId2;
11299  transid1 = transid1 | transid2;
11300  if (transid1 != 0) {
11301  jam();
11302  systemErrorLab(signal, __LINE__);
11303  }//if
11304 
11310  ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
11311  scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
11312  scanFragptr.p->stopFragTimer();
11313  {
11314  ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
11315  run.release(scanFragptr);
11316  }
11317  scanError(signal, scanptr, errCode);
11318 }//Dbtc::execSCAN_FRAGREF()
11319 
11325 void Dbtc::scanError(Signal* signal, ScanRecordPtr scanptr, Uint32 errorCode)
11326 {
11327  jam();
11328  ScanRecord* scanP = scanptr.p;
11329 
11330  DEBUG("scanError, errorCode = "<< errorCode <<
11331  ", scanState = " << scanptr.p->scanState);
11332 
11333  apiConnectptr.i = scanP->scanApiRec;
11334  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11335  ndbrequire(apiConnectptr.p->apiScanRec == scanptr.i);
11336 
11337  if(scanP->scanState == ScanRecord::CLOSING_SCAN){
11338  jam();
11339  close_scan_req_send_conf(signal, scanptr);
11340  return;
11341  }
11342 
11343  ndbrequire(scanP->scanState == ScanRecord::RUNNING);
11344 
11348  close_scan_req(signal, scanptr, false);
11349 
11350  const bool apiFail = (apiConnectptr.p->apiFailState == ZTRUE);
11351  if(apiFail){
11352  jam();
11353  return;
11354  }
11355 
11356  ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
11357  ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
11358  ref->transId1 = apiConnectptr.p->transid[0];
11359  ref->transId2 = apiConnectptr.p->transid[1];
11360  ref->errorCode = errorCode;
11361  ref->closeNeeded = 1;
11362  sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF,
11363  signal, ScanTabRef::SignalLength, JBB);
11364 }//Dbtc::scanError()
11365 
11366 /************************************************************
11367  * execSCAN_FRAGCONF
11368  *
11369  * A NUMBER OF OPERATIONS HAVE BEEN COMPLETED IN THIS
11370  * FRAGMENT. TAKE CARE OF AND ISSUE FURTHER ACTIONS.
11371  ************************************************************/
11372 void Dbtc::execSCAN_FRAGCONF(Signal* signal)
11373 {
11374  Uint32 transid1, transid2, total_len;
11375  jamEntry();
11376 
11377  const ScanFragConf * const conf = (ScanFragConf*)&signal->theData[0];
11378  const Uint32 noCompletedOps = conf->completedOps;
11379  const Uint32 status = conf->fragmentCompleted;
11380 
11381  scanFragptr.i = conf->senderData;
11382  c_scan_frag_pool.getPtr(scanFragptr);
11383 
11384  ScanRecordPtr scanptr;
11385  scanptr.i = scanFragptr.p->scanRec;
11386  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
11387 
11388  apiConnectptr.i = scanptr.p->scanApiRec;
11389  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11390 
11391  transid1 = apiConnectptr.p->transid[0] ^ conf->transId1;
11392  transid2 = apiConnectptr.p->transid[1] ^ conf->transId2;
11393  total_len= conf->total_len;
11394  transid1 = transid1 | transid2;
11395  if (transid1 != 0) {
11396  jam();
11397  systemErrorLab(signal, __LINE__);
11398  }//if
11399 
11400  ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
11401 
11402  if(scanptr.p->scanState == ScanRecord::CLOSING_SCAN){
11403  jam();
11404  if(status == 0){
11408  return;
11409  } else {
11410  jam();
11411  scanFragptr.p->stopFragTimer();
11412  scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
11413  {
11414  ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
11415  run.release(scanFragptr);
11416  }
11417  }
11418  close_scan_req_send_conf(signal, scanptr);
11419  return;
11420  }
11421 
11422  if(noCompletedOps == 0 && status != 0 &&
11423  !scanptr.p->m_pass_all_confs &&
11424  scanptr.p->scanNextFragId+scanptr.p->m_booked_fragments_count < scanptr.p->scanNoFrag){
11433  scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
11434  scanFragptr.p->startFragTimer(ctcTimer);
11435 
11436  tcConnectptr.i = scanptr.p->scanTcrec;
11437  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
11438  scanFragptr.p->scanFragId = scanptr.p->scanNextFragId++;
11439  DihScanGetNodesReq* req = (DihScanGetNodesReq*)signal->getDataPtrSend();
11440  req->senderRef = reference();
11441  req->senderData = scanFragptr.i;
11442  req->tableId = scanptr.p->scanTableref;
11443  req->fragId = scanFragptr.p->scanFragId;
11444  req->scanCookie = scanptr.p->m_scan_cookie;
11445  sendSignal(cdihblockref, GSN_DIH_SCAN_GET_NODES_REQ, signal,
11446  DihScanGetNodesReq::SignalLength, JBB);
11447  return;
11448  }
11449  /*
11450  Uint32 totalLen = 0;
11451  for(Uint32 i = 0; i<noCompletedOps; i++){
11452  Uint32 tmp = conf->opReturnDataLen[i];
11453  totalLen += tmp;
11454  }
11455  */
11456  {
11457  ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
11458  ScanFragList queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags);
11459 
11460  run.remove(scanFragptr);
11461  queued.add(scanFragptr);
11462  scanptr.p->m_queued_count++;
11463  }
11464 
11465  if (status != 0 &&
11466  scanptr.p->m_pass_all_confs &&
11467  scanptr.p->scanNextFragId+scanptr.p->m_booked_fragments_count
11468  < scanptr.p->scanNoFrag){
11473  ndbrequire(total_len==0);
11478  total_len = 1;
11479  }
11480 
11481  scanFragptr.p->m_scan_frag_conf_status = status;
11482  scanFragptr.p->m_ops = noCompletedOps;
11483  scanFragptr.p->m_totalLen = total_len;
11484  scanFragptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
11485  scanFragptr.p->stopFragTimer();
11486 
11487  if(scanptr.p->m_queued_count > 0){
11488  jam();
11489  sendScanTabConf(signal, scanptr);
11490  }
11491 }//Dbtc::execSCAN_FRAGCONF()
11492 
11493 /****************************************************************************
11494  * execSCAN_NEXTREQ
11495  *
11496  * THE APPLICATION HAS PROCESSED THE TUPLES TRANSFERRED AND IS NOW READY FOR
11497  * MORE. THIS SIGNAL IS ALSO USED TO CLOSE THE SCAN.
11498  ****************************************************************************/
11499 void Dbtc::execSCAN_NEXTREQ(Signal* signal)
11500 {
11501  const ScanNextReq * const req = (ScanNextReq *)&signal->theData[0];
11502  const UintR transid1 = req->transId1;
11503  const UintR transid2 = req->transId2;
11504  const UintR stopScan = req->stopScan;
11505 
11506  jamEntry();
11507 
11508  SectionHandle handle(this, signal);
11509  apiConnectptr.i = req->apiConnectPtr;
11510  if (apiConnectptr.i >= capiConnectFilesize) {
11511  jam();
11512  releaseSections(handle);
11513  warningHandlerLab(signal, __LINE__);
11514  return;
11515  }//if
11516  ptrAss(apiConnectptr, apiConnectRecord);
11517 
11521  const UintR ctransid1 = apiConnectptr.p->transid[0] ^ transid1;
11522  const UintR ctransid2 = apiConnectptr.p->transid[1] ^ transid2;
11523  if ((ctransid1 | ctransid2) != 0){
11524  releaseSections(handle);
11525  ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
11526  ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
11527  ref->transId1 = transid1;
11528  ref->transId2 = transid2;
11529  ref->errorCode = ZSTATE_ERROR;
11530  ref->closeNeeded = 0;
11531  sendSignal(signal->senderBlockRef(), GSN_SCAN_TABREF,
11532  signal, ScanTabRef::SignalLength, JBB);
11533  DEBUG("Wrong transid");
11534  return;
11535  }
11536 
11540  if (apiConnectptr.p->apiConnectstate != CS_START_SCAN) {
11541  jam();
11542  releaseSections(handle);
11543  if (apiConnectptr.p->apiConnectstate == CS_CONNECTED) {
11544  jam();
11545  /*********************************************************************
11546  * The application sends a SCAN_NEXTREQ after experiencing a time-out.
11547  * We will send a SCAN_TABREF to indicate a time-out occurred.
11548  *********************************************************************/
11549  DEBUG("scanTabRefLab: ZSCANTIME_OUT_ERROR2");
11550  ndbout_c("apiConnectptr(%d) -> abort", apiConnectptr.i);
11551  ndbrequire(false); //B2 indication of strange things going on
11552  scanTabRefLab(signal, ZSCANTIME_OUT_ERROR2);
11553  return;
11554  }
11555  DEBUG("scanTabRefLab: ZSTATE_ERROR");
11556  DEBUG(" apiConnectstate="<<apiConnectptr.p->apiConnectstate);
11557  ndbrequire(false); //B2 indication of strange things going on
11558  scanTabRefLab(signal, ZSTATE_ERROR);
11559  return;
11560  }//if
11561 
11562  /*******************************************************
11563  * START THE ACTUAL LOGIC OF SCAN_NEXTREQ.
11564  ********************************************************/
11565  // Stop the timer that is used to check for timeout in the API
11566  setApiConTimer(apiConnectptr.i, 0, __LINE__);
11567  ScanRecordPtr scanptr;
11568  scanptr.i = apiConnectptr.p->apiScanRec;
11569  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
11570  ScanRecord* scanP = scanptr.p;
11571 
11572  /* Copy ReceiverIds to working space past end of signal
11573  * so that we don't overwrite them when sending signals
11574  */
11575  Uint32 len = 0;
11576  if (handle.m_cnt > 0)
11577  {
11578  jam();
11579  /* TODO : Add Dropped signal handling for SCAN_NEXTREQ */
11580  /* Receiver ids are in a long section */
11581  ndbrequire(signal->getLength() == ScanNextReq::SignalLength);
11582  ndbrequire(handle.m_cnt == 1);
11583  SegmentedSectionPtr receiverIdsSection;
11584  ndbrequire(handle.getSection(receiverIdsSection,
11585  ScanNextReq::ReceiverIdsSectionNum));
11586  len= receiverIdsSection.p->m_sz;
11587  ndbassert(len < (8192 - 25));
11588 
11589  copy(signal->getDataPtrSend()+25, receiverIdsSection);
11590  releaseSections(handle);
11591  }
11592  else
11593  {
11594  jam();
11595  len= signal->getLength() - ScanNextReq::SignalLength;
11596  memcpy(signal->getDataPtrSend()+25,
11597  signal->getDataPtr()+ ScanNextReq::SignalLength,
11598  4 * len);
11599  }
11600 
11601  if (stopScan == ZTRUE) {
11602  jam();
11603  /*********************************************************************
11604  * APPLICATION IS CLOSING THE SCAN.
11605  **********************************************************************/
11606  close_scan_req(signal, scanptr, true);
11607  return;
11608  }//if
11609 
11610  if (scanptr.p->scanState == ScanRecord::CLOSING_SCAN){
11611  jam();
11618  return;
11619  }
11620 
11621  ScanFragNextReq tmp;
11622  tmp.requestInfo = 0;
11623  tmp.transId1 = apiConnectptr.p->transid[0];
11624  tmp.transId2 = apiConnectptr.p->transid[1];
11625  tmp.batch_size_rows = scanP->batch_size_rows;
11626  tmp.batch_size_bytes = scanP->batch_byte_size;
11627 
11628  ScanFragList running(c_scan_frag_pool, scanP->m_running_scan_frags);
11629  ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags);
11630  for(Uint32 i = 0 ; i<len; i++){
11631  jam();
11632  scanFragptr.i = signal->theData[i+25];
11633  c_scan_frag_pool.getPtr(scanFragptr);
11634  ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::DELIVERED);
11635 
11636  scanFragptr.p->startFragTimer(ctcTimer);
11637  scanFragptr.p->m_ops = 0;
11638 
11639  if(scanFragptr.p->m_scan_frag_conf_status)
11640  {
11644  jam();
11645  ndbrequire(scanptr.p->scanNextFragId < scanptr.p->scanNoFrag);
11646  jam();
11647  ndbassert(scanptr.p->m_booked_fragments_count);
11648  scanptr.p->m_booked_fragments_count--;
11649  scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
11650 
11651  tcConnectptr.i = scanptr.p->scanTcrec;
11652  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
11653  scanFragptr.p->scanFragId = scanptr.p->scanNextFragId++;
11654 
11655  DihScanGetNodesReq* req = (DihScanGetNodesReq*)signal->getDataPtrSend();
11656  req->senderRef = reference();
11657  req->senderData = scanFragptr.i;
11658  req->tableId = scanptr.p->scanTableref;
11659  req->fragId = scanFragptr.p->scanFragId;
11660  req->scanCookie = scanptr.p->m_scan_cookie;
11661  sendSignal(cdihblockref, GSN_DIH_SCAN_GET_NODES_REQ, signal,
11662  DihScanGetNodesReq::SignalLength, JBB);
11663  }
11664  else
11665  {
11666  jam();
11667  scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
11668  ScanFragNextReq * req = (ScanFragNextReq*)signal->getDataPtrSend();
11669  * req = tmp;
11670  req->senderData = scanFragptr.i;
11671  sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
11672  ScanFragNextReq::SignalLength, JBB);
11673  }
11674  delivered.remove(scanFragptr);
11675  running.add(scanFragptr);
11676  }//for
11677 
11678 }//Dbtc::execSCAN_NEXTREQ()
11679 
11680 void
11681 Dbtc::close_scan_req(Signal* signal, ScanRecordPtr scanPtr, bool req_received){
11682 
11683  ScanRecord* scanP = scanPtr.p;
11684  ndbrequire(scanPtr.p->scanState != ScanRecord::IDLE);
11685  ScanRecord::ScanState old = scanPtr.p->scanState;
11686  scanPtr.p->scanState = ScanRecord::CLOSING_SCAN;
11687  scanPtr.p->m_close_scan_req = req_received;
11688 
11689  if (old == ScanRecord::WAIT_FRAGMENT_COUNT)
11690  {
11691  jam();
11692  scanPtr.p->scanState = old;
11693  return; // Will continue on execDI_FCOUNTCONF
11694  }
11695 
11707  ScanFragNextReq * nextReq = (ScanFragNextReq*)&signal->theData[0];
11708  nextReq->requestInfo = ScanFragNextReq::ZCLOSE;
11709  nextReq->transId1 = apiConnectptr.p->transid[0];
11710  nextReq->transId2 = apiConnectptr.p->transid[1];
11711 
11712  {
11713  ScanFragRecPtr ptr;
11714  ScanFragList running(c_scan_frag_pool, scanP->m_running_scan_frags);
11715  ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags);
11716  ScanFragList queued(c_scan_frag_pool, scanP->m_queued_scan_frags);
11717 
11718  // Close running
11719  for(running.first(ptr); !ptr.isNull(); ){
11720  ScanFragRecPtr curr = ptr; // Remove while iterating...
11721  running.next(ptr);
11722 
11723  switch(curr.p->scanFragState){
11724  case ScanFragRec::IDLE:
11725  jam(); // real early abort
11726  ndbrequire(old == ScanRecord::WAIT_AI);
11727  running.release(curr);
11728  continue;
11729  case ScanFragRec::WAIT_GET_PRIMCONF:
11730  jam();
11731  continue;
11732  case ScanFragRec::LQH_ACTIVE:
11733  jam();
11734  break;
11735  default:
11736  jamLine(curr.p->scanFragState);
11737  ndbrequire(false);
11738  }
11739 
11740  curr.p->startFragTimer(ctcTimer);
11741  curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
11742  nextReq->senderData = curr.i;
11743  sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
11744  ScanFragNextReq::SignalLength, JBB);
11745  }
11746 
11747  // Close delivered
11748  for(delivered.first(ptr); !ptr.isNull(); ){
11749  jam();
11750  ScanFragRecPtr curr = ptr; // Remove while iterating...
11751  delivered.next(ptr);
11752 
11753  ndbrequire(curr.p->scanFragState == ScanFragRec::DELIVERED);
11754  delivered.remove(curr);
11755 
11756  if (curr.p->m_scan_frag_conf_status == 0)
11757  {
11758  jam();
11759  running.add(curr);
11760  curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
11761  curr.p->startFragTimer(ctcTimer);
11762  nextReq->senderData = curr.i;
11763  sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
11764  ScanFragNextReq::SignalLength, JBB);
11765 
11766  }
11767  else
11768  {
11769  jam();
11770  c_scan_frag_pool.release(curr);
11771  curr.p->scanFragState = ScanFragRec::COMPLETED;
11772  curr.p->stopFragTimer();
11773  }
11774  }//for
11775 
11779  for(queued.first(ptr); !ptr.isNull(); ){
11780  jam();
11781  ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY);
11782  ScanFragRecPtr curr = ptr; // Remove while iterating...
11783  queued.next(ptr);
11784 
11785  queued.remove(curr);
11786  scanP->m_queued_count--;
11787 
11788  if (curr.p->m_scan_frag_conf_status == 0)
11789  {
11790  jam();
11791  running.add(curr);
11792  curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
11793  curr.p->startFragTimer(ctcTimer);
11794  nextReq->senderData = curr.i;
11795  sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
11796  ScanFragNextReq::SignalLength, JBB);
11797  }
11798  else
11799  {
11800  jam();
11801  c_scan_frag_pool.release(curr);
11802  curr.p->scanFragState = ScanFragRec::COMPLETED;
11803  curr.p->stopFragTimer();
11804  }
11805  }
11806  }
11807  close_scan_req_send_conf(signal, scanPtr);
11808 }
11809 
11810 void
11811 Dbtc::close_scan_req_send_conf(Signal* signal, ScanRecordPtr scanPtr){
11812 
11813  jam();
11814 
11815  ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty());
11816  ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty());
11817  //ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty());
11818 
11819 #if 0
11820  {
11821  ScanFragList comp(c_scan_frag_pool, scanPtr.p->m_completed_scan_frags);
11822  ScanFragRecPtr ptr;
11823  for(comp.first(ptr); !ptr.isNull(); comp.next(ptr)){
11824  ndbrequire(ptr.p->scanFragTimer == 0);
11825  ndbrequire(ptr.p->scanFragState == ScanFragRec::COMPLETED);
11826  }
11827  }
11828 #endif
11829 
11830  if(!scanPtr.p->m_running_scan_frags.isEmpty()){
11831  jam();
11832  return;
11833  }
11834 
11835  const bool apiFail = (apiConnectptr.p->apiFailState == ZTRUE);
11836 
11837  if(!scanPtr.p->m_close_scan_req){
11838  jam();
11842  return;
11843  }
11844 
11845  Uint32 ref = apiConnectptr.p->ndbapiBlockref;
11846  if(!apiFail && ref){
11847  jam();
11848  ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
11849  conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
11850  conf->requestInfo = ScanTabConf::EndOfData;
11851  conf->transId1 = apiConnectptr.p->transid[0];
11852  conf->transId2 = apiConnectptr.p->transid[1];
11853  sendSignal(ref, GSN_SCAN_TABCONF, signal, ScanTabConf::SignalLength, JBB);
11854  }
11855 
11856  releaseScanResources(signal, scanPtr);
11857 
11858  if(apiFail){
11859  jam();
11863  handleApiFailState(signal, apiConnectptr.i);
11864  }
11865 }
11866 
11868 Dbtc::seizeScanrec(Signal* signal) {
11869  ScanRecordPtr scanptr;
11870  scanptr.i = cfirstfreeScanrec;
11871  ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
11872  cfirstfreeScanrec = scanptr.p->nextScan;
11873  scanptr.p->nextScan = RNIL;
11874  ndbrequire(scanptr.p->scanState == ScanRecord::IDLE);
11875  return scanptr;
11876 }//Dbtc::seizeScanrec()
11877 
11878 void Dbtc::sendScanFragReq(Signal* signal,
11879  ScanRecord* scanP,
11880  ScanFragRec* scanFragP,
11881  bool isLastReq)
11882 {
11883  Uint32 version= getNodeInfo(refToNode(scanFragP->lqhBlockref)).m_version;
11884  bool longFragReq= ((version >= NDBD_LONG_SCANFRAGREQ) &&
11885  (! ERROR_INSERTED(8070) &&
11886  ! ERROR_INSERTED(8088)));
11887  cachePtr.i = apiConnectptr.p->cachePtr;
11888  ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
11889 
11890  Uint32 reqKeyLen = scanP->scanKeyLen;
11891 
11892  SectionHandle sections(this);
11893  sections.m_ptr[0].i = cachePtr.p->attrInfoSectionI;
11894  sections.m_cnt = 1;
11895 
11896  if (reqKeyLen > 0)
11897  {
11898  jam();
11899  ndbassert(cachePtr.p->keyInfoSectionI != RNIL);
11900  sections.m_ptr[1].i = cachePtr.p->keyInfoSectionI;
11901  sections.m_cnt = 2;
11902  }
11903 
11904  if (isLastReq)
11905  {
11906  /* This send will release these sections, remove our
11907  * references to them
11908  */
11909  cachePtr.p->attrInfoSectionI = RNIL;
11910  cachePtr.p->keyInfoSectionI = RNIL;
11911  }
11912 
11913  getSections(sections.m_cnt, sections.m_ptr);
11914 
11915  ScanFragReq * const req = (ScanFragReq *)&signal->theData[0];
11916  Uint32 requestInfo = scanP->scanRequestInfo;
11917  ScanFragReq::setScanPrio(requestInfo, 1);
11918  apiConnectptr.i = scanP->scanApiRec;
11919  req->tableId = scanP->scanTableref;
11920  req->schemaVersion = scanP->scanSchemaVersion;
11921  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11922  req->senderData = scanFragptr.i;
11923  req->requestInfo = requestInfo;
11924  req->fragmentNoKeyLen = scanFragP->scanFragId;
11925  req->resultRef = apiConnectptr.p->ndbapiBlockref;
11926  req->savePointId = apiConnectptr.p->currSavePointId;
11927  req->transId1 = apiConnectptr.p->transid[0];
11928  req->transId2 = apiConnectptr.p->transid[1];
11929  req->clientOpPtr = scanFragP->m_apiPtr;
11930  req->batch_size_rows= scanP->batch_size_rows;
11931  req->batch_size_bytes= scanP->batch_byte_size;
11932 
11933  if (likely(longFragReq))
11934  {
11935  jam();
11936  /* Send long, possibly fragmented SCAN_FRAGREQ */
11937 
11938  // TODO :
11939  // 1) Consider whether to adjust fragmentation threshold
11940  // a) When to fragment signal vs fragment size
11941  // b) Fragment size
11942  /* To reduce the copy burden we want to keep hold of the
11943  * AttrInfo and KeyInfo sections after sending them to
11944  * LQH. To do this we perform the fragmented send inline,
11945  * so that all fragments are sent *now*. This avoids any
11946  * problems with the fragmented send CONTINUE 'thread' using
11947  * the section while we hold or even release it. The
11948  * signal receiver can still take realtime breaks when
11949  * receiving.
11950  *
11951  * Indicate to sendFirstFragment that we want to keep the
11952  * fragments, so it must not free them, unless this is the
11953  * last request in which case they can be freed. If the
11954  * last request is a local send then a copy is avoided.
11955  */
11956  FragmentSendInfo fragSendInfo;
11957 
11958  sendFirstFragment(fragSendInfo,
11959  NodeReceiverGroup(scanFragP->lqhBlockref),
11960  GSN_SCAN_FRAGREQ,
11961  signal,
11962  ScanFragReq::SignalLength,
11963  JBB,
11964  &sections,
11965  !isLastReq); // Keep sent sections unless
11966  // last send
11967 
11968  while (fragSendInfo.m_status != FragmentSendInfo::SendComplete)
11969  {
11970  jam();
11971  /* Send remaining fragments */
11972  sendNextSegmentedFragment(signal, fragSendInfo);
11973  }
11974 
11975  /* Clear handle, section deallocation handled elsewhere. */
11976  sections.clear();
11977  }
11978  else
11979  {
11980  jam();
11981  /* Short SCANFRAGREQ with separate KeyInfo and AttrInfo trains
11982  * Sent to older NDBD nodes during upgrade
11983  */
11984  Uint32 reqAttrLen = sections.m_ptr[0].sz;
11985  ScanFragReq::setAttrLen(req->requestInfo, reqAttrLen);
11986  req->fragmentNoKeyLen |= reqKeyLen;
11987  sendSignal(scanFragP->lqhBlockref, GSN_SCAN_FRAGREQ, signal,
11988  ScanFragReq::SignalLength, JBB);
11989  if(reqKeyLen > 0)
11990  {
11991  jam();
11992  tcConnectptr.i = scanFragptr.i;
11993  /* Build KeyInfo train from KeyInfo long signal section */
11994  sendKeyInfoTrain(signal,
11995  scanFragP->lqhBlockref,
11996  scanFragptr.i,
11997  0, // Offset 0
11998  sections.m_ptr[1].i);
11999  }
12000 
12001  if(ERROR_INSERTED(8035))
12002  globalTransporterRegistry.performSend();
12003 
12004  if (!ERROR_INSERTED(8088))
12005  {
12006  ndbrequire(sendAttrInfoTrain(signal,
12007  scanFragP->lqhBlockref,
12008  scanFragptr.i,
12009  0, // Offset 0
12010  sections.m_ptr[0].i));
12011  }
12012 
12013  if(ERROR_INSERTED(8035))
12014  globalTransporterRegistry.performSend();
12015 
12016  if (isLastReq)
12017  {
12018  /* Free the sections here */
12019  releaseSections(sections);
12020  }
12021  else
12022  {
12023  sections.clear();
12024  }
12025  }
12026 
12027  if (ERROR_INSERTED(8088))
12028  {
12029  signal->theData[0] = 9999;
12030  sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 100, 1);
12031  }
12032 }//Dbtc::sendScanFragReq()
12033 
12034 
12035 void Dbtc::sendScanTabConf(Signal* signal, ScanRecordPtr scanPtr) {
12036  jam();
12037  Uint32* ops = signal->getDataPtrSend()+4;
12038  Uint32 op_count = scanPtr.p->m_queued_count;
12039 
12040  Uint32 words_per_op = 4;
12041  const Uint32 ref = apiConnectptr.p->ndbapiBlockref;
12042  if (!scanPtr.p->m_4word_conf)
12043  {
12044  jam();
12045  words_per_op = 3;
12046  }
12047 
12048  if (4 + words_per_op * op_count > 25)
12049  {
12050  jam();
12051  ops += 21;
12052  }
12053 
12054  int left = scanPtr.p->scanNoFrag - scanPtr.p->scanNextFragId;
12055  Uint32 booked = scanPtr.p->m_booked_fragments_count;
12056 
12057  ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
12058  conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
12059  conf->requestInfo = op_count;
12060  conf->transId1 = apiConnectptr.p->transid[0];
12061  conf->transId2 = apiConnectptr.p->transid[1];
12062  ScanFragRecPtr ptr;
12063  {
12064  ScanFragList queued(c_scan_frag_pool, scanPtr.p->m_queued_scan_frags);
12065  ScanFragList delivered(c_scan_frag_pool,scanPtr.p->m_delivered_scan_frags);
12066  for(queued.first(ptr); !ptr.isNull(); ){
12067  ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY);
12068  ScanFragRecPtr curr = ptr; // Remove while iterating...
12069  queued.next(ptr);
12070 
12071  bool done = curr.p->m_scan_frag_conf_status && (left <= (int)booked);
12072  if(curr.p->m_scan_frag_conf_status)
12073  booked++;
12074 
12075  * ops++ = curr.p->m_apiPtr;
12076  * ops++ = done ? RNIL : curr.i;
12077  if (words_per_op == 4)
12078  {
12079  * ops++ = curr.p->m_ops;
12080  * ops++ = curr.p->m_totalLen;
12081  }
12082  else
12083  {
12084  * ops++ = (curr.p->m_totalLen << 10) + curr.p->m_ops;
12085  }
12086 
12087  queued.remove(curr);
12088  if(!done){
12089  delivered.add(curr);
12090  curr.p->scanFragState = ScanFragRec::DELIVERED;
12091  curr.p->stopFragTimer();
12092  } else {
12093  c_scan_frag_pool.release(curr);
12094  curr.p->scanFragState = ScanFragRec::COMPLETED;
12095  curr.p->stopFragTimer();
12096  }
12097  }
12098  }
12099 
12100  bool release = false;
12101  scanPtr.p->m_booked_fragments_count = booked;
12102  if(scanPtr.p->m_delivered_scan_frags.isEmpty() &&
12103  scanPtr.p->m_running_scan_frags.isEmpty())
12104  {
12105  jam();
12106  release = true;
12107  conf->requestInfo = op_count | ScanTabConf::EndOfData;
12108  }
12109  else
12110  {
12111  if (scanPtr.p->m_running_scan_frags.isEmpty())
12112  {
12113  jam();
12117  setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
12118  }
12119  }
12120 
12121  if (4 + words_per_op * op_count > 25)
12122  {
12123  jam();
12124  LinearSectionPtr ptr[3];
12125  ptr[0].p = signal->getDataPtrSend()+25;
12126  ptr[0].sz = words_per_op * op_count;
12127  sendSignal(ref, GSN_SCAN_TABCONF, signal,
12128  ScanTabConf::SignalLength, JBB, ptr, 1);
12129  }
12130  else
12131  {
12132  jam();
12133  sendSignal(ref, GSN_SCAN_TABCONF, signal,
12134  ScanTabConf::SignalLength + words_per_op * op_count, JBB);
12135  }
12136  scanPtr.p->m_queued_count = 0;
12137 
12138  if (release)
12139  {
12140  jam();
12141  releaseScanResources(signal, scanPtr);
12142  }
12143 
12144 }//Dbtc::sendScanTabConf()
12145 
12146 
12147 void Dbtc::gcpTcfinished(Signal* signal, Uint64 gci)
12148 {
12149  GCPTCFinished* conf = (GCPTCFinished*)signal->getDataPtrSend();
12150  conf->senderData = c_gcp_data;
12151  conf->gci_hi = Uint32(gci >> 32);
12152  conf->gci_lo = Uint32(gci);
12153  sendSignal(c_gcp_ref, GSN_GCP_TCFINISHED, signal,
12154  GCPTCFinished::SignalLength, JBB);
12155 }//Dbtc::gcpTcfinished()
12156 
12157 void Dbtc::initApiConnect(Signal* signal)
12158 {
12159  Uint32 tiacTmp;
12160  Uint32 guard4;
12161 
12162  tiacTmp = capiConnectFilesize / 3;
12163  ndbrequire(tiacTmp > 0);
12164  guard4 = tiacTmp + 1;
12165  for (cachePtr.i = 0; cachePtr.i < guard4; cachePtr.i++) {
12167  ptrAss(cachePtr, cacheRecord);
12168  cachePtr.p->nextCacheRec = cachePtr.i + 1;
12169  }//for
12170  cachePtr.i = tiacTmp;
12171  ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
12172  cachePtr.p->nextCacheRec = RNIL;
12173  cfirstfreeCacheRec = 0;
12174 
12175  guard4 = tiacTmp - 1;
12176  for (apiConnectptr.i = 0; apiConnectptr.i <= guard4; apiConnectptr.i++) {
12178  jam();
12179  ptrAss(apiConnectptr, apiConnectRecord);
12180  apiConnectptr.p->apiConnectstate = CS_DISCONNECTED;
12181  apiConnectptr.p->apiFailState = ZFALSE;
12182  setApiConTimer(apiConnectptr.i, 0, __LINE__);
12183  apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
12184  apiConnectptr.p->cachePtr = RNIL;
12185  apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
12186  apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
12187  apiConnectptr.p->commitAckMarker = RNIL;
12188  apiConnectptr.p->firstTcConnect = RNIL;
12189  apiConnectptr.p->lastTcConnect = RNIL;
12190  apiConnectptr.p->m_flags = 0;
12191  apiConnectptr.p->m_special_op_flags = 0;
12192  apiConnectptr.p->accumulatingIndexOp = RNIL;
12193  apiConnectptr.p->executingIndexOp = RNIL;
12194  apiConnectptr.p->buddyPtr = RNIL;
12195  apiConnectptr.p->currSavePointId = 0;
12196  apiConnectptr.p->m_transaction_nodes.clear();
12197  apiConnectptr.p->singleUserMode = 0;
12198  }//for
12199  apiConnectptr.i = tiacTmp - 1;
12200  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12201  apiConnectptr.p->nextApiConnect = RNIL;
12202  cfirstfreeApiConnect = 0;
12203  guard4 = (2 * tiacTmp) - 1;
12204  for (apiConnectptr.i = tiacTmp; apiConnectptr.i <= guard4; apiConnectptr.i++)
12205  {
12207  jam();
12208  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12209  apiConnectptr.p->apiConnectstate = CS_RESTART;
12210  apiConnectptr.p->apiFailState = ZFALSE;
12211  setApiConTimer(apiConnectptr.i, 0, __LINE__);
12212  apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
12213  apiConnectptr.p->cachePtr = RNIL;
12214  apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
12215  apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
12216  apiConnectptr.p->commitAckMarker = RNIL;
12217  apiConnectptr.p->firstTcConnect = RNIL;
12218  apiConnectptr.p->lastTcConnect = RNIL;
12219  apiConnectptr.p->m_flags = 0;
12220  apiConnectptr.p->m_special_op_flags = 0;
12221  apiConnectptr.p->accumulatingIndexOp = RNIL;
12222  apiConnectptr.p->executingIndexOp = RNIL;
12223  apiConnectptr.p->buddyPtr = RNIL;
12224  apiConnectptr.p->currSavePointId = 0;
12225  apiConnectptr.p->m_transaction_nodes.clear();
12226  apiConnectptr.p->singleUserMode = 0;
12227  }//for
12228  apiConnectptr.i = (2 * tiacTmp) - 1;
12229  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12230  apiConnectptr.p->nextApiConnect = RNIL;
12231  cfirstfreeApiConnectCopy = tiacTmp;
12232  guard4 = (3 * tiacTmp) - 1;
12233  for (apiConnectptr.i = 2 * tiacTmp; apiConnectptr.i <= guard4;
12234  apiConnectptr.i++) {
12236  jam();
12237  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12238  setApiConTimer(apiConnectptr.i, 0, __LINE__);
12239  apiConnectptr.p->apiFailState = ZFALSE;
12240  apiConnectptr.p->apiConnectstate = CS_RESTART;
12241  apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
12242  apiConnectptr.p->cachePtr = RNIL;
12243  apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
12244  apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
12245  apiConnectptr.p->commitAckMarker = RNIL;
12246  apiConnectptr.p->firstTcConnect = RNIL;
12247  apiConnectptr.p->lastTcConnect = RNIL;
12248  apiConnectptr.p->m_flags = 0;
12249  apiConnectptr.p->m_special_op_flags = 0;
12250  apiConnectptr.p->accumulatingIndexOp = RNIL;
12251  apiConnectptr.p->executingIndexOp = RNIL;
12252  apiConnectptr.p->buddyPtr = RNIL;
12253  apiConnectptr.p->currSavePointId = 0;
12254  apiConnectptr.p->m_transaction_nodes.clear();
12255  apiConnectptr.p->singleUserMode = 0;
12256  }//for
12257  apiConnectptr.i = (3 * tiacTmp) - 1;
12258  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12259  apiConnectptr.p->nextApiConnect = RNIL;
12260  cfirstfreeApiConnectFail = 2 * tiacTmp;
12261 }//Dbtc::initApiConnect()
12262 
12263 void Dbtc::initgcp(Signal* signal)
12264 {
12265  Ptr<GcpRecord> gcpPtr;
12266  ndbrequire(cgcpFilesize > 0);
12267  for (gcpPtr.i = 0; gcpPtr.i < cgcpFilesize; gcpPtr.i++) {
12268  ptrAss(gcpPtr, gcpRecord);
12269  gcpPtr.p->nextGcp = gcpPtr.i + 1;
12270  }//for
12271  gcpPtr.i = cgcpFilesize - 1;
12272  ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord);
12273  gcpPtr.p->nextGcp = RNIL;
12274  cfirstfreeGcp = 0;
12275  cfirstgcp = RNIL;
12276  clastgcp = RNIL;
12277 }//Dbtc::initgcp()
12278 
12279 void Dbtc::inithost(Signal* signal)
12280 {
12281  cpackedListIndex = 0;
12282  ndbrequire(chostFilesize > 0);
12283  for (hostptr.i = 0; hostptr.i < chostFilesize; hostptr.i++) {
12284  jam();
12285  ptrAss(hostptr, hostRecord);
12286  hostptr.p->hostStatus = HS_DEAD;
12287  hostptr.p->inPackedList = false;
12288  hostptr.p->lqhTransStatus = LTS_IDLE;
12289  hostptr.p->noOfWordsTCKEYCONF = 0;
12290  hostptr.p->noOfPackedWordsLqh = 0;
12291  hostptr.p->hostLqhBlockRef = calcLqhBlockRef(hostptr.i);
12292  hostptr.p->m_nf_bits = 0;
12293  }//for
12294  c_alive_nodes.clear();
12295 }//Dbtc::inithost()
12296 
12297 void Dbtc::initialiseRecordsLab(Signal* signal, UintR Tdata0,
12298  Uint32 retRef, Uint32 retData)
12299 {
12300  switch (Tdata0) {
12301  case 0:
12302  jam();
12303  initApiConnect(signal);
12304  break;
12305  case 1:
12306  jam();
12307  // UNUSED Free to initialise something
12308  break;
12309  case 2:
12310  jam();
12311  // UNUSED Free to initialise something
12312  break;
12313  case 3:
12314  jam();
12315  initgcp(signal);
12316  break;
12317  case 4:
12318  jam();
12319  inithost(signal);
12320  break;
12321  case 5:
12322  jam();
12323  // UNUSED Free to initialise something
12324  break;
12325  case 6:
12326  jam();
12327  initTable(signal);
12328  break;
12329  case 7:
12330  jam();
12331  initialiseScanrec(signal);
12332  break;
12333  case 8:
12334  jam();
12335  initialiseScanOprec(signal);
12336  break;
12337  case 9:
12338  jam();
12339  initialiseScanFragrec(signal);
12340  break;
12341  case 10:
12342  jam();
12343  initialiseTcConnect(signal);
12344  break;
12345  case 11:
12346  jam();
12347  initTcFail(signal);
12348 
12349  {
12350  ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
12351  conf->senderRef = reference();
12352  conf->senderData = retData;
12353  sendSignal(retRef, GSN_READ_CONFIG_CONF, signal,
12354  ReadConfigConf::SignalLength, JBB);
12355  }
12356  return;
12357  break;
12358  default:
12359  jam();
12360  systemErrorLab(signal, __LINE__);
12361  return;
12362  break;
12363  }//switch
12364 
12365  signal->theData[0] = TcContinueB::ZINITIALISE_RECORDS;
12366  signal->theData[1] = Tdata0 + 1;
12367  signal->theData[2] = 0;
12368  signal->theData[3] = retRef;
12369  signal->theData[4] = retData;
12370  sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);
12371 }
12372 
12373 /* ========================================================================= */
12374 /* ======= INITIALISE_SCANREC ======= */
12375 /* */
12376 /* ========================================================================= */
12377 void Dbtc::initialiseScanrec(Signal* signal)
12378 {
12379  ScanRecordPtr scanptr;
12380  ndbrequire(cscanrecFileSize > 0);
12381  for (scanptr.i = 0; scanptr.i < cscanrecFileSize; scanptr.i++) {
12383  jam();
12384  ptrAss(scanptr, scanRecord);
12385  new (scanptr.p) ScanRecord();
12386  scanptr.p->scanState = ScanRecord::IDLE;
12387  scanptr.p->scanApiRec = RNIL;
12388  scanptr.p->nextScan = scanptr.i + 1;
12389  }//for
12390  scanptr.i = cscanrecFileSize - 1;
12391  ptrAss(scanptr, scanRecord);
12392  scanptr.p->nextScan = RNIL;
12393  cfirstfreeScanrec = 0;
12394 }//Dbtc::initialiseScanrec()
12395 
12396 void Dbtc::initialiseScanFragrec(Signal* signal)
12397 {
12398 }//Dbtc::initialiseScanFragrec()
12399 
12400 void Dbtc::initialiseScanOprec(Signal* signal)
12401 {
12402 }//Dbtc::initialiseScanOprec()
12403 
12404 void Dbtc::initTable(Signal* signal)
12405 {
12406 
12407  ndbrequire(ctabrecFilesize > 0);
12408  for (tabptr.i = 0; tabptr.i < ctabrecFilesize; tabptr.i++) {
12410  ptrAss(tabptr, tableRecord);
12411  tabptr.p->currentSchemaVersion = 0;
12412  tabptr.p->m_flags = 0;
12413  tabptr.p->set_storedTable(true);
12414  tabptr.p->tableType = 0;
12415  tabptr.p->set_enabled(false);
12416  tabptr.p->set_dropping(false);
12417  tabptr.p->noOfKeyAttr = 0;
12418  tabptr.p->hasCharAttr = 0;
12419  tabptr.p->noOfDistrKeys = 0;
12420  tabptr.p->hasVarKeys = 0;
12421  }//for
12422 }//Dbtc::initTable()
12423 
12424 void Dbtc::initialiseTcConnect(Signal* signal)
12425 {
12426  ndbrequire(ctcConnectFilesize >= 2);
12427 
12428  // Place half of tcConnectptr's in cfirstfreeTcConnectFail list
12429  Uint32 titcTmp = ctcConnectFilesize / 2;
12430  for (tcConnectptr.i = 0; tcConnectptr.i < titcTmp; tcConnectptr.i++) {
12432  jam();
12433  ptrAss(tcConnectptr, tcConnectRecord);
12434  tcConnectptr.p->tcConnectstate = OS_RESTART;
12435  tcConnectptr.p->apiConnect = RNIL;
12436  tcConnectptr.p->noOfNodes = 0;
12437  tcConnectptr.p->nextTcConnect = tcConnectptr.i + 1;
12438  tcConnectptr.p->commitAckMarker = RNIL;
12439  }//for
12440  tcConnectptr.i = titcTmp - 1;
12441  ptrAss(tcConnectptr, tcConnectRecord);
12442  tcConnectptr.p->nextTcConnect = RNIL;
12443  cfirstfreeTcConnectFail = 0;
12444 
12445  // Place other half in cfirstfreeTcConnect list
12446  for (tcConnectptr.i = titcTmp; tcConnectptr.i < ctcConnectFilesize;
12447  tcConnectptr.i++) {
12449  jam();
12450  ptrAss(tcConnectptr, tcConnectRecord);
12451  tcConnectptr.p->tcConnectstate = OS_RESTART;
12452  tcConnectptr.p->apiConnect = RNIL;
12453  tcConnectptr.p->noOfNodes = 0;
12454  tcConnectptr.p->nextTcConnect = tcConnectptr.i + 1;
12455  tcConnectptr.p->commitAckMarker = RNIL;
12456  }//for
12457  tcConnectptr.i = ctcConnectFilesize - 1;
12458  ptrAss(tcConnectptr, tcConnectRecord);
12459  tcConnectptr.p->nextTcConnect = RNIL;
12460  cfirstfreeTcConnect = titcTmp;
12461  c_counters.cconcurrentOp = 0;
12462 }//Dbtc::initialiseTcConnect()
12463 
12464 /* ------------------------------------------------------------------------- */
12465 /* ---- LINK A GLOBAL CHECKPOINT RECORD INTO THE LIST WITH TRANSACTIONS */
12466 /* WAITING FOR COMPLETION. */
12467 /* ------------------------------------------------------------------------- */
12468 void Dbtc::linkGciInGcilist(Ptr<GcpRecord> gcpPtr)
12469 {
12470  GcpRecordPtr tmpGcpPointer;
12471  if (cfirstgcp == RNIL) {
12472  jam();
12473  cfirstgcp = gcpPtr.i;
12474  } else {
12475  jam();
12476  tmpGcpPointer.i = clastgcp;
12477  ptrCheckGuard(tmpGcpPointer, cgcpFilesize, gcpRecord);
12478  tmpGcpPointer.p->nextGcp = gcpPtr.i;
12479  }//if
12480  clastgcp = gcpPtr.i;
12481 }//Dbtc::linkGciInGcilist()
12482 
12483 /* ------------------------------------------------------------------------- */
12484 /* ------- LINK A TC CONNECT RECORD INTO THE API LIST OF TC CONNECTIONS --- */
12485 /* ------------------------------------------------------------------------- */
12486 void Dbtc::linkTcInConnectionlist(Signal* signal)
12487 {
12488  /* POINTER FOR THE CONNECT_RECORD */
12489  TcConnectRecordPtr ltcTcConnectptr;
12490 
12491  tcConnectptr.p->nextTcConnect = RNIL;
12492  ltcTcConnectptr.i = apiConnectptr.p->lastTcConnect;
12493  ptrCheck(ltcTcConnectptr, ctcConnectFilesize, tcConnectRecord);
12494  apiConnectptr.p->lastTcConnect = tcConnectptr.i;
12495  if (ltcTcConnectptr.i == RNIL) {
12496  jam();
12497  apiConnectptr.p->firstTcConnect = tcConnectptr.i;
12498  } else {
12499  jam();
12500  ptrGuard(ltcTcConnectptr);
12501  ltcTcConnectptr.p->nextTcConnect = tcConnectptr.i;
12502  }//if
12503 }//Dbtc::linkTcInConnectionlist()
12504 
12505 /*---------------------------------------------------------------------------*/
12506 /* RELEASE_ABORT_RESOURCES */
12507 /* THIS CODE RELEASES ALL RESOURCES AFTER AN ABORT OF A TRANSACTION AND ALSO */
12508 /* SENDS THE ABORT DECISION TO THE APPLICATION. */
12509 /*---------------------------------------------------------------------------*/
12510 void Dbtc::releaseAbortResources(Signal* signal)
12511 {
12512  TcConnectRecordPtr rarTcConnectptr;
12513 
12514  c_counters.cabortCount++;
12515  if (apiConnectptr.p->cachePtr != RNIL) {
12516  cachePtr.i = apiConnectptr.p->cachePtr;
12517  ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
12518  releaseAttrinfo();
12519  releaseKeys();
12520  }//if
12521  tcConnectptr.i = apiConnectptr.p->firstTcConnect;
12522  while (tcConnectptr.i != RNIL) {
12523  jam();
12524  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
12525  // Clear any markers that were set in CS_RECEIVING state
12526  clearCommitAckMarker(apiConnectptr.p, tcConnectptr.p);
12527  rarTcConnectptr.i = tcConnectptr.p->nextTcConnect;
12528  releaseTcCon();
12529  tcConnectptr.i = rarTcConnectptr.i;
12530  }//while
12531 
12532  Uint32 marker = apiConnectptr.p->commitAckMarker;
12533  if (marker != RNIL)
12534  {
12535  jam();
12536  m_commitAckMarkerHash.release(marker);
12537  apiConnectptr.p->commitAckMarker = RNIL;
12538  }
12539 
12540  apiConnectptr.p->firstTcConnect = RNIL;
12541  apiConnectptr.p->lastTcConnect = RNIL;
12542  apiConnectptr.p->m_transaction_nodes.clear();
12543  apiConnectptr.p->singleUserMode = 0;
12544 
12545  // MASV let state be CS_ABORTING until all
12546  // signals in the "air" have been received. Reset to CS_CONNECTED
12547  // will be done when a TCKEYREQ with start flag is recieved
12548  // or releaseApiCon is called
12549  // apiConnectptr.p->apiConnectstate = CS_CONNECTED;
12550  apiConnectptr.p->apiConnectstate = CS_ABORTING;
12551  apiConnectptr.p->abortState = AS_IDLE;
12552  releaseAllSeizedIndexOperations(apiConnectptr.p);
12553 
12554  if (tc_testbit(apiConnectptr.p->m_flags, ApiConnectRecord::TF_EXEC_FLAG) ||
12555  apiConnectptr.p->apiFailState == ZTRUE)
12556  {
12557  jam();
12558  bool ok = false;
12559  Uint32 blockRef = apiConnectptr.p->ndbapiBlockref;
12560  ReturnSignal ret = apiConnectptr.p->returnsignal;
12561  apiConnectptr.p->returnsignal = RS_NO_RETURN;
12562  tc_clearbit(apiConnectptr.p->m_flags, ApiConnectRecord::TF_EXEC_FLAG);
12563  switch(ret){
12564  case RS_TCROLLBACKCONF:
12565  jam();
12566  ok = true;
12567  signal->theData[0] = apiConnectptr.p->ndbapiConnect;
12568  signal->theData[1] = apiConnectptr.p->transid[0];
12569  signal->theData[2] = apiConnectptr.p->transid[1];
12570  sendSignal(blockRef, GSN_TCROLLBACKCONF, signal, 3, JBB);
12571  break;
12572  case RS_TCROLLBACKREP:{
12573  jam();
12574  ok = true;
12575  TcRollbackRep * const tcRollbackRep =
12576  (TcRollbackRep *) signal->getDataPtr();
12577 
12578  tcRollbackRep->connectPtr = apiConnectptr.p->ndbapiConnect;
12579  tcRollbackRep->transId[0] = apiConnectptr.p->transid[0];
12580  tcRollbackRep->transId[1] = apiConnectptr.p->transid[1];
12581  tcRollbackRep->returnCode = apiConnectptr.p->returncode;
12582  tcRollbackRep->errorData = apiConnectptr.p->errorData;
12583  sendSignal(blockRef, GSN_TCROLLBACKREP, signal,
12584  TcRollbackRep::SignalLength, JBB);
12585  }
12586  break;
12587  case RS_NO_RETURN:
12588  jam();
12589  ok = true;
12590  break;
12591  case RS_TCKEYCONF:
12592  case RS_TC_COMMITCONF:
12593  break;
12594  }
12595  if(!ok){
12596  jam();
12597  ndbout_c("returnsignal = %d", apiConnectptr.p->returnsignal);
12598  sendSystemError(signal, __LINE__);
12599  }//if
12600 
12601  }
12602  setApiConTimer(apiConnectptr.i, 0,
12603  100000+c_apiConTimer_line[apiConnectptr.i]);
12604  if (apiConnectptr.p->apiFailState == ZTRUE) {
12605  jam();
12606  handleApiFailState(signal, apiConnectptr.i);
12607  return;
12608  }//if
12609 }//Dbtc::releaseAbortResources()
12610 
12611 void Dbtc::releaseApiCon(Signal* signal, UintR TapiConnectPtr)
12612 {
12613  ApiConnectRecordPtr TlocalApiConnectptr;
12614 
12615  TlocalApiConnectptr.i = TapiConnectPtr;
12616  ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
12617  TlocalApiConnectptr.p->nextApiConnect = cfirstfreeApiConnect;
12618  cfirstfreeApiConnect = TlocalApiConnectptr.i;
12619  setApiConTimer(TlocalApiConnectptr.i, 0, __LINE__);
12620  TlocalApiConnectptr.p->apiConnectstate = CS_DISCONNECTED;
12621  ndbassert(TlocalApiConnectptr.p->m_transaction_nodes.isclear());
12622  ndbassert(TlocalApiConnectptr.p->apiScanRec == RNIL);
12623  TlocalApiConnectptr.p->ndbapiBlockref = 0;
12624 }//Dbtc::releaseApiCon()
12625 
12626 void Dbtc::releaseApiConnectFail(Signal* signal)
12627 {
12628  apiConnectptr.p->apiConnectstate = CS_RESTART;
12629  apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
12630  setApiConTimer(apiConnectptr.i, 0, __LINE__);
12631  apiConnectptr.p->nextApiConnect = cfirstfreeApiConnectFail;
12632  cfirstfreeApiConnectFail = apiConnectptr.i;
12633  ndbrequire(apiConnectptr.p->commitAckMarker == RNIL);
12634 }//Dbtc::releaseApiConnectFail()
12635 
12636 void Dbtc::releaseKeys()
12637 {
12638  Uint32 keyInfoSectionI= cachePtr.p->keyInfoSectionI;
12639 
12640  /* Release KeyInfo section if there is one */
12641  releaseSection(keyInfoSectionI);
12642  cachePtr.p->keyInfoSectionI= RNIL;
12643 
12644 }//Dbtc::releaseKeys()
12645 
12646 void Dbtc::releaseTcConnectFail(Signal* signal)
12647 {
12648  ptrGuard(tcConnectptr);
12649  tcConnectptr.p->nextTcConnect = cfirstfreeTcConnectFail;
12650  cfirstfreeTcConnectFail = tcConnectptr.i;
12651 }//Dbtc::releaseTcConnectFail()
12652 
12653 void Dbtc::seizeApiConnect(Signal* signal)
12654 {
12655  if (cfirstfreeApiConnect != RNIL) {
12656  jam();
12657  terrorCode = ZOK;
12658  apiConnectptr.i = cfirstfreeApiConnect; /* ASSIGN A FREE RECORD FROM */
12659  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12660  cfirstfreeApiConnect = apiConnectptr.p->nextApiConnect;
12661  apiConnectptr.p->nextApiConnect = RNIL;
12662  setApiConTimer(apiConnectptr.i, 0, __LINE__);
12663  apiConnectptr.p->apiConnectstate = CS_CONNECTED; /* STATE OF CONNECTION */
12664  tc_clearbit(apiConnectptr.p->m_flags,
12665  ApiConnectRecord::TF_TRIGGER_PENDING);
12666  apiConnectptr.p->m_special_op_flags = 0;
12667  } else {
12668  jam();
12669  terrorCode = ZNO_FREE_API_CONNECTION;
12670  }//if
12671 }//Dbtc::seizeApiConnect()
12672 
12673 void Dbtc::seizeApiConnectFail(Signal* signal)
12674 {
12675  apiConnectptr.i = cfirstfreeApiConnectFail;
12676  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12677  cfirstfreeApiConnectFail = apiConnectptr.p->nextApiConnect;
12678 }//Dbtc::seizeApiConnectFail()
12679 
12680 void Dbtc::seizeTcConnect(Signal* signal)
12681 {
12682  tcConnectptr.i = cfirstfreeTcConnect;
12683  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
12684  cfirstfreeTcConnect = tcConnectptr.p->nextTcConnect;
12685  c_counters.cconcurrentOp++;
12686  tcConnectptr.p->m_special_op_flags = 0;
12687  tcConnectptr.p->tcConnectstate = OS_ABORTING;
12688  tcConnectptr.p->noOfNodes = 0;
12689 }//Dbtc::seizeTcConnect()
12690 
12691 void Dbtc::seizeTcConnectFail(Signal* signal)
12692 {
12693  tcConnectptr.i = cfirstfreeTcConnectFail;
12694  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
12695  cfirstfreeTcConnectFail = tcConnectptr.p->nextTcConnect;
12696 }//Dbtc::seizeTcConnectFail()
12697 
12703 bool Dbtc::sendAttrInfoTrain(Signal* signal,
12704  UintR TBRef,
12705  Uint32 connectPtr,
12706  Uint32 offset,
12707  Uint32 attrInfoIVal)
12708 {
12709  ApiConnectRecord * const regApiPtr = apiConnectptr.p;
12710 
12711  ndbassert( attrInfoIVal != RNIL );
12712  SectionReader attrInfoReader(attrInfoIVal, getSectionSegmentPool());
12713  Uint32 attrInfoLength= attrInfoReader.getSize();
12714 
12715  ndbassert( offset < attrInfoLength );
12716  if (unlikely(! attrInfoReader.step( offset )))
12717  return false;
12718  attrInfoLength-= offset;
12719 
12720  signal->theData[0] = connectPtr;
12721  signal->theData[1] = regApiPtr->transid[0];
12722  signal->theData[2] = regApiPtr->transid[1];
12723 
12724  while (attrInfoLength != 0)
12725  {
12726  Uint32 dataInSignal= MIN(AttrInfo::DataLength, attrInfoLength);
12727 
12728  if (unlikely(! attrInfoReader.getWords(&signal->theData[3],
12729  dataInSignal)))
12730  return false;
12731 
12732  sendSignal(TBRef, GSN_ATTRINFO, signal,
12733  AttrInfo::HeaderLength + dataInSignal, JBB);
12734 
12735  attrInfoLength-= dataInSignal;
12736  }
12737  return true;
12738 } //Dbtc::sendAttrInfoTrain()
12739 
12740 void Dbtc::sendContinueTimeOutControl(Signal* signal, Uint32 TapiConPtr)
12741 {
12742  signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_CONTROL;
12743  signal->theData[1] = TapiConPtr;
12744  sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
12745 }//Dbtc::sendContinueTimeOutControl()
12746 
12747 void Dbtc::sendSystemError(Signal* signal, int line)
12748 {
12749  progError(line, NDBD_EXIT_NDBREQUIRE);
12750 }//Dbtc::sendSystemError()
12751 
12752 /* ========================================================================= */
12753 /* ------- LINK ACTUAL GCP OUT OF LIST ------- */
12754 /* ------------------------------------------------------------------------- */
12755 void Dbtc::unlinkGcp(Ptr<GcpRecord> tmpGcpPtr)
12756 {
12757  ndbrequire(cfirstgcp == tmpGcpPtr.i);
12758 
12759  cfirstgcp = tmpGcpPtr.p->nextGcp;
12760  if (tmpGcpPtr.i == clastgcp) {
12761  jam();
12762  clastgcp = RNIL;
12763  }//if
12764 
12765  tmpGcpPtr.p->nextGcp = cfirstfreeGcp;
12766  cfirstfreeGcp = tmpGcpPtr.i;
12767 }//Dbtc::unlinkGcp()
12768 
12769 void
12770 Dbtc::execDUMP_STATE_ORD(Signal* signal)
12771 {
12772  jamEntry();
12773  DumpStateOrd * const dumpState = (DumpStateOrd *)&signal->theData[0];
12774  Uint32 arg = signal->theData[0];
12775  if (signal->theData[0] == DumpStateOrd::CommitAckMarkersSize)
12776  {
12777  infoEvent("TC: m_commitAckMarkerPool: %d free size: %d",
12778  m_commitAckMarkerPool.getNoOfFree(),
12779  m_commitAckMarkerPool.getSize());
12780  return;
12781  }
12782  if (signal->theData[0] == DumpStateOrd::CommitAckMarkersDump)
12783  {
12784  infoEvent("TC: m_commitAckMarkerPool: %d free size: %d",
12785  m_commitAckMarkerPool.getNoOfFree(),
12786  m_commitAckMarkerPool.getSize());
12787  CommitAckMarkerIterator iter;
12788  for(m_commitAckMarkerHash.first(iter); iter.curr.i != RNIL;
12789  m_commitAckMarkerHash.next(iter)){
12790  infoEvent("CommitAckMarker: i = %d (0x%x, 0x%x)"
12791  " Api: %d %x %x %x %x bucket = %d",
12792  iter.curr.i,
12793  iter.curr.p->transid1,
12794  iter.curr.p->transid2,
12795  iter.curr.p->apiNodeId,
12796  iter.curr.p->m_commit_ack_marker_nodes.getWord(0),
12797  iter.curr.p->m_commit_ack_marker_nodes.getWord(1),
12798  iter.curr.p->m_commit_ack_marker_nodes.getWord(2),
12799  iter.curr.p->m_commit_ack_marker_nodes.getWord(3),
12800  iter.bucket);
12801  }
12802  return;
12803  }
12804  // Dump all ScanFragRecs
12805  if (dumpState->args[0] == DumpStateOrd::TcDumpAllScanFragRec){
12806  Uint32 recordNo = 0;
12807  if (signal->getLength() == 1)
12808  infoEvent("TC: Dump all ScanFragRec - size: %d",
12809  cscanFragrecFileSize);
12810  else if (signal->getLength() == 2)
12811  recordNo = dumpState->args[1];
12812  else
12813  return;
12814 
12815  dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec;
12816  dumpState->args[1] = recordNo;
12817  execDUMP_STATE_ORD(signal);
12818 
12819  if (recordNo < cscanFragrecFileSize-1){
12820  dumpState->args[0] = DumpStateOrd::TcDumpAllScanFragRec;
12821  dumpState->args[1] = recordNo+1;
12822  sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
12823  }
12824  }
12825 
12826  // Dump one ScanFragRec
12827  if (dumpState->args[0] == DumpStateOrd::TcDumpOneScanFragRec){
12828  Uint32 recordNo = RNIL;
12829  if (signal->getLength() == 2)
12830  recordNo = dumpState->args[1];
12831  else
12832  return;
12833 
12834  if (recordNo >= cscanFragrecFileSize)
12835  return;
12836 
12837  ScanFragRecPtr sfp;
12838  sfp.i = recordNo;
12839  c_scan_frag_pool.getPtr(sfp);
12840  infoEvent("Dbtc::ScanFragRec[%d]: state=%d fragid=%d",
12841  sfp.i,
12842  sfp.p->scanFragState,
12843  sfp.p->scanFragId);
12844  infoEvent(" nodeid=%d, timer=%d",
12845  refToNode(sfp.p->lqhBlockref),
12846  sfp.p->scanFragTimer);
12847  }
12848 
12849  // Dump all ScanRecords
12850  if (dumpState->args[0] == DumpStateOrd::TcDumpAllScanRec){
12851  Uint32 recordNo = 0;
12852  if (signal->getLength() == 1)
12853  infoEvent("TC: Dump all ScanRecord - size: %d",
12854  cscanrecFileSize);
12855  else if (signal->getLength() == 2)
12856  recordNo = dumpState->args[1];
12857  else
12858  return;
12859 
12860  dumpState->args[0] = DumpStateOrd::TcDumpOneScanRec;
12861  dumpState->args[1] = recordNo;
12862  execDUMP_STATE_ORD(signal);
12863 
12864  if (recordNo < cscanrecFileSize-1){
12865  dumpState->args[0] = DumpStateOrd::TcDumpAllScanRec;
12866  dumpState->args[1] = recordNo+1;
12867  sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
12868  }
12869  }
12870 
12871  // Dump all active ScanRecords
12872  if (dumpState->args[0] == DumpStateOrd::TcDumpAllActiveScanRec){
12873  Uint32 recordNo = 0;
12874  if (signal->getLength() == 1)
12875  infoEvent("TC: Dump active ScanRecord - size: %d",
12876  cscanrecFileSize);
12877  else if (signal->getLength() == 2)
12878  recordNo = dumpState->args[1];
12879  else
12880  return;
12881 
12882  ScanRecordPtr sp;
12883  sp.i = recordNo;
12884  ptrAss(sp, scanRecord);
12885  if (sp.p->scanState != ScanRecord::IDLE){
12886  dumpState->args[0] = DumpStateOrd::TcDumpOneScanRec;
12887  dumpState->args[1] = recordNo;
12888  execDUMP_STATE_ORD(signal);
12889  }
12890 
12891  if (recordNo < cscanrecFileSize-1){
12892  dumpState->args[0] = DumpStateOrd::TcDumpAllActiveScanRec;
12893  dumpState->args[1] = recordNo+1;
12894  sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
12895  }
12896  }
12897 
12898  // Dump one ScanRecord
12899  // and associated ScanFragRec and ApiConnectRecord
12900  if (dumpState->args[0] == DumpStateOrd::TcDumpOneScanRec){
12901  Uint32 recordNo = RNIL;
12902  if (signal->getLength() == 2)
12903  recordNo = dumpState->args[1];
12904  else
12905  return;
12906 
12907  if (recordNo >= cscanrecFileSize)
12908  return;
12909 
12910  ScanRecordPtr sp;
12911  sp.i = recordNo;
12912  ptrAss(sp, scanRecord);
12913  infoEvent("Dbtc::ScanRecord[%d]: state=%d"
12914  "nextfrag=%d, nofrag=%d",
12915  sp.i,
12916  sp.p->scanState,
12917  sp.p->scanNextFragId,
12918  sp.p->scanNoFrag);
12919  infoEvent(" ailen=%d, para=%d, receivedop=%d, noOprePperFrag=%d",
12920  sp.p->scanAiLength,
12921  sp.p->scanParallel,
12922  sp.p->scanReceivedOperations,
12923  sp.p->batch_size_rows);
12924  infoEvent(" schv=%d, tab=%d, sproc=%d",
12925  sp.p->scanSchemaVersion,
12926  sp.p->scanTableref,
12927  sp.p->scanStoredProcId);
12928  infoEvent(" apiRec=%d, next=%d",
12929  sp.p->scanApiRec, sp.p->nextScan);
12930 
12931  if (sp.p->scanState != ScanRecord::IDLE){
12932  // Request dump of ScanFragRec
12933  ScanFragRecPtr sfptr;
12934 #define DUMP_SFR(x){\
12935  ScanFragList list(c_scan_frag_pool, x);\
12936  for(list.first(sfptr); !sfptr.isNull(); list.next(sfptr)){\
12937  dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec; \
12938  dumpState->args[1] = sfptr.i;\
12939  execDUMP_STATE_ORD(signal);\
12940  }}
12941 
12942  DUMP_SFR(sp.p->m_running_scan_frags);
12943  DUMP_SFR(sp.p->m_queued_scan_frags);
12944  DUMP_SFR(sp.p->m_delivered_scan_frags);
12945 
12946  // Request dump of ApiConnectRecord
12947  dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
12948  dumpState->args[1] = sp.p->scanApiRec;
12949  execDUMP_STATE_ORD(signal);
12950  }
12951 
12952  }
12953 
12954  // Dump all ApiConnectRecord(s)
12955  if (dumpState->args[0] == DumpStateOrd::TcDumpAllApiConnectRec){
12956  Uint32 recordNo = 0;
12957  if (signal->getLength() == 1)
12958  infoEvent("TC: Dump all ApiConnectRecord - size: %d",
12959  capiConnectFilesize);
12960  else if (signal->getLength() == 2)
12961  recordNo = dumpState->args[1];
12962  else
12963  return;
12964 
12965  dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
12966  dumpState->args[1] = recordNo;
12967  execDUMP_STATE_ORD(signal);
12968 
12969  if (recordNo < capiConnectFilesize-1){
12970  dumpState->args[0] = DumpStateOrd::TcDumpAllApiConnectRec;
12971  dumpState->args[1] = recordNo+1;
12972  sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
12973  }
12974  }
12975 
12976  // Dump one ApiConnectRecord
12977  if (dumpState->args[0] == DumpStateOrd::TcDumpOneApiConnectRec){
12978  Uint32 recordNo = RNIL;
12979  if (signal->getLength() == 2)
12980  recordNo = dumpState->args[1];
12981  else
12982  return;
12983 
12984  if (recordNo >= capiConnectFilesize)
12985  return;
12986 
12987  ApiConnectRecordPtr ap;
12988  ap.i = recordNo;
12989  ptrAss(ap, apiConnectRecord);
12990  infoEvent("Dbtc::ApiConnectRecord[%d]: state=%d, abortState=%d, "
12991  "apiFailState=%d",
12992  ap.i,
12993  ap.p->apiConnectstate,
12994  ap.p->abortState,
12995  ap.p->apiFailState);
12996  infoEvent(" transid(0x%x, 0x%x), apiBref=0x%x, scanRec=%d",
12997  ap.p->transid[0],
12998  ap.p->transid[1],
12999  ap.p->ndbapiBlockref,
13000  ap.p->apiScanRec);
13001  infoEvent(" ctcTimer=%d, apiTimer=%d, counter=%d, retcode=%d, "
13002  "retsig=%d",
13003  ctcTimer, getApiConTimer(ap.i),
13004  ap.p->counter,
13005  ap.p->returncode,
13006  ap.p->returnsignal);
13007  infoEvent(" lqhkeyconfrec=%d, lqhkeyreqrec=%d, "
13008  "tckeyrec=%d",
13009  ap.p->lqhkeyconfrec,
13010  ap.p->lqhkeyreqrec,
13011  ap.p->tckeyrec);
13012  infoEvent(" next=%d ",
13013  ap.p->nextApiConnect);
13014  }
13015 
13016  if (dumpState->args[0] == DumpStateOrd::TcSetTransactionTimeout){
13017  jam();
13018  if(signal->getLength() > 1){
13019  set_timeout_value(signal->theData[1]);
13020  }
13021  }
13022 
13023  if (dumpState->args[0] == DumpStateOrd::TcSetApplTransactionTimeout){
13024  jam();
13025  if(signal->getLength() > 1){
13026  set_appl_timeout_value(signal->theData[1]);
13027  }
13028  }
13029 
13030  if (dumpState->args[0] == DumpStateOrd::TcStartDumpIndexOpCount)
13031  {
13032  static int frequency = 1;
13033  if (signal->getLength() > 1)
13034  frequency = signal->theData[1];
13035  else
13036  if (refToBlock(signal->getSendersBlockRef()) != DBTC)
13037  frequency = 1;
13038 
13039  if (frequency)
13040  {
13041  dumpState->args[0] = DumpStateOrd::TcDumpIndexOpCount;
13042  execDUMP_STATE_ORD(signal);
13043  dumpState->args[0] = DumpStateOrd::TcStartDumpIndexOpCount;
13044 
13045  Uint32 delay = 1000 * (frequency > 25 ? 25 : frequency);
13046  sendSignalWithDelay(cownref, GSN_DUMP_STATE_ORD, signal, delay, 1);
13047  }
13048  }
13049 
13050  if (dumpState->args[0] == DumpStateOrd::TcDumpIndexOpCount)
13051  {
13052  infoEvent("IndexOpCount: pool: %d free: %d",
13053  c_theIndexOperationPool.getSize(),
13054  c_theIndexOperationPool.getNoOfFree());
13055  }
13056 
13057  if (dumpState->args[0] == 2514)
13058  {
13059  if (signal->getLength() == 2)
13060  {
13061  dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
13062  execDUMP_STATE_ORD(signal);
13063  }
13064 
13065  NodeReceiverGroup rg(CMVMI, c_alive_nodes);
13066  dumpState->args[0] = 15;
13067  sendSignal(rg, GSN_DUMP_STATE_ORD, signal, 1, JBB);
13068 
13069  signal->theData[0] = 2515;
13070  sendSignalWithDelay(cownref, GSN_DUMP_STATE_ORD, signal, 1000, 1);
13071  return;
13072  }
13073 
13074  if (dumpState->args[0] == 2515)
13075  {
13076  NdbNodeBitmask mask = c_alive_nodes;
13077  mask.clear(getOwnNodeId());
13078  NodeReceiverGroup rg(NDBCNTR, mask);
13079 
13080  sendSignal(rg, GSN_SYSTEM_ERROR, signal, 1, JBB);
13081  sendSignalWithDelay(cownref, GSN_SYSTEM_ERROR, signal, 300, 1);
13082  return;
13083  }
13084 
13085  if (arg == 2550)
13086  {
13087  jam();
13088  Uint32 len = signal->getLength() - 1;
13089  if (len + 2 > 25)
13090  {
13091  jam();
13092  infoEvent("Too long filter");
13093  return;
13094  }
13095  if (validate_filter(signal))
13096  {
13097  jam();
13098  memmove(signal->theData + 2, signal->theData + 1, 4 * len);
13099  signal->theData[0] = 2551;
13100  signal->theData[1] = 0; // record
13101  sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, len + 2, JBB);
13102 
13103  infoEvent("Starting dump of transactions");
13104  }
13105  return;
13106  }
13107 
13108  if (arg == 2551)
13109  {
13110  jam();
13111  Uint32 record = signal->theData[1];
13112  Uint32 len = signal->getLength();
13113  ndbassert(len > 1);
13114 
13115  ApiConnectRecordPtr ap;
13116  ap.i = record;
13117  ptrAss(ap, apiConnectRecord);
13118 
13119  bool print = false;
13120  for (Uint32 i = 0; i<32; i++)
13121  {
13122  jam();
13123  print = match_and_print(signal, ap);
13124 
13125  ap.i++;
13126  if (ap.i == capiConnectFilesize || print)
13127  {
13128  jam();
13129  break;
13130  }
13131 
13132  ptrAss(ap, apiConnectRecord);
13133  }
13134 
13135  if (ap.i == capiConnectFilesize)
13136  {
13137  jam();
13138  infoEvent("End of transaction dump");
13139  return;
13140  }
13141 
13142  signal->theData[1] = ap.i;
13143  if (print)
13144  {
13145  jam();
13146  sendSignalWithDelay(reference(), GSN_DUMP_STATE_ORD, signal, 200, len);
13147  }
13148  else
13149  {
13150  jam();
13151  sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, len, JBB);
13152  }
13153  return;
13154  }
13155 #ifdef ERROR_INSERT
13156  if (arg == 2552 || arg == 4002)
13157  {
13158  ndbrequire(m_commitAckMarkerPool.getNoOfFree() == m_commitAckMarkerPool.getSize());
13159  return;
13160  }
13161 #endif
13162 
13163  if (arg == 7019 && signal->getLength() == 2)
13164  {
13165  jam();
13166  Uint32 nodeId = signal->theData[1];
13167  if (nodeId < MAX_NODES && nodeId < NDB_ARRAY_SIZE(capiConnectClosing))
13168  {
13169  warningEvent(" DBTC: capiConnectClosing[%u]: %u",
13170  nodeId, capiConnectClosing[nodeId]);
13171  }
13172  else
13173  {
13174  warningEvent(" DBTC: dump-7019 to unknown node: %u", nodeId);
13175  }
13176  }
13177 }//Dbtc::execDUMP_STATE_ORD()
13178 
13179 void Dbtc::execDBINFO_SCANREQ(Signal *signal)
13180 {
13181  DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
13182  const Ndbinfo::ScanCursor* cursor =
13183  CAST_CONSTPTR(Ndbinfo::ScanCursor, DbinfoScan::getCursorPtr(&req));
13184  Ndbinfo::Ratelimit rl;
13185 
13186  jamEntry();
13187 
13188  switch(req.tableId){
13189  case Ndbinfo::POOLS_TABLEID:
13190  {
13191  Ndbinfo::pool_entry pools[] =
13192  {
13193  { "Defined Trigger",
13194  c_theDefinedTriggerPool.getUsed(),
13195  c_theDefinedTriggerPool.getSize(),
13196  c_theDefinedTriggerPool.getEntrySize(),
13197  c_theDefinedTriggerPool.getUsedHi(),
13198  { CFG_DB_NO_TRIGGERS,0,0,0 }},
13199  { "Fired Trigger",
13200  c_theFiredTriggerPool.getUsed(),
13201  c_theFiredTriggerPool.getSize(),
13202  c_theFiredTriggerPool.getEntrySize(),
13203  c_theFiredTriggerPool.getUsedHi(),
13204  { CFG_DB_NO_TRIGGER_OPS,0,0,0 }},
13205  { "Index",
13206  c_theIndexPool.getUsed(),
13207  c_theIndexPool.getSize(),
13208  c_theIndexPool.getEntrySize(),
13209  c_theIndexPool.getUsedHi(),
13210  { CFG_DB_NO_TABLES,
13211  CFG_DB_NO_ORDERED_INDEXES,
13212  CFG_DB_NO_UNIQUE_HASH_INDEXES,0 }},
13213  { "Scan Fragment",
13214  c_scan_frag_pool.getUsed(),
13215  c_scan_frag_pool.getSize(),
13216  c_scan_frag_pool.getEntrySize(),
13217  c_scan_frag_pool.getUsedHi(),
13218  { CFG_DB_NO_LOCAL_SCANS,0,0,0 }},
13219  { "Commit ACK Marker",
13220  m_commitAckMarkerPool.getUsed(),
13221  m_commitAckMarkerPool.getSize(),
13222  m_commitAckMarkerPool.getEntrySize(),
13223  m_commitAckMarkerPool.getUsedHi(),
13224  { CFG_DB_NO_TRANSACTIONS,0,0,0 }},
13225  { "Index Op",
13226  c_theIndexOperationPool.getUsed(),
13227  c_theIndexOperationPool.getSize(),
13228  c_theIndexOperationPool.getEntrySize(),
13229  c_theIndexOperationPool.getUsedHi(),
13230  { CFG_DB_NO_INDEX_OPS,0,0,0 }},
13231  { "Operations",
13232  c_counters.cconcurrentOp,
13233  ctcConnectFilesize,
13234  sizeof(TcConnectRecord),
13235  0,
13236  { CFG_DB_NO_TRANSACTIONS,
13237  CFG_DB_NO_OPS,0,0 }},
13238  { NULL, 0,0,0,0,{0,0,0,0} }
13239  };
13240 
13241  const size_t num_config_params =
13242  sizeof(pools[0].config_params) / sizeof(pools[0].config_params[0]);
13243  Uint32 pool = cursor->data[0];
13244  BlockNumber bn = blockToMain(number());
13245  while(pools[pool].poolname)
13246  {
13247  jam();
13248  Ndbinfo::Row row(signal, req);
13249  row.write_uint32(getOwnNodeId());
13250  row.write_uint32(bn); // block number
13251  row.write_uint32(instance()); // block instance
13252  row.write_string(pools[pool].poolname);
13253 
13254  row.write_uint64(pools[pool].used);
13255  row.write_uint64(pools[pool].total);
13256  row.write_uint64(pools[pool].used_hi);
13257  row.write_uint64(pools[pool].entry_size);
13258  for (size_t i = 0; i < num_config_params; i++)
13259  row.write_uint32(pools[pool].config_params[i]);
13260  ndbinfo_send_row(signal, req, row, rl);
13261  pool++;
13262  if (rl.need_break(req))
13263  {
13264  jam();
13265  ndbinfo_send_scan_break(signal, req, rl, pool);
13266  return;
13267  }
13268  }
13269  break;
13270  }
13271 
13272  case Ndbinfo::COUNTERS_TABLEID:
13273  {
13274  Ndbinfo::counter_entry counters[] = {
13275  { Ndbinfo::ATTRINFO_COUNTER, c_counters.cattrinfoCount },
13276  { Ndbinfo::TRANSACTIONS_COUNTER, c_counters.ctransCount },
13277  { Ndbinfo::COMMITS_COUNTER, c_counters.ccommitCount },
13278  { Ndbinfo::READS_COUNTER, c_counters.creadCount },
13279  { Ndbinfo::SIMPLE_READS_COUNTER, c_counters.csimpleReadCount },
13280  { Ndbinfo::WRITES_COUNTER, c_counters.cwriteCount },
13281  { Ndbinfo::ABORTS_COUNTER, c_counters.cabortCount },
13282  { Ndbinfo::TABLE_SCANS_COUNTER, c_counters.c_scan_count },
13283  { Ndbinfo::RANGE_SCANS_COUNTER, c_counters.c_range_scan_count }
13284  };
13285  const size_t num_counters = sizeof(counters) / sizeof(counters[0]);
13286 
13287  Uint32 i = cursor->data[0];
13288  BlockNumber bn = blockToMain(number());
13289  while(i < num_counters)
13290  {
13291  jam();
13292  Ndbinfo::Row row(signal, req);
13293  row.write_uint32(getOwnNodeId());
13294  row.write_uint32(bn); // block number
13295  row.write_uint32(instance()); // block instance
13296  row.write_uint32(counters[i].id);
13297 
13298  row.write_uint64(counters[i].val);
13299  ndbinfo_send_row(signal, req, row, rl);
13300  i++;
13301  if (rl.need_break(req))
13302  {
13303  jam();
13304  ndbinfo_send_scan_break(signal, req, rl, i);
13305  return;
13306  }
13307  }
13308 
13309  break;
13310  }
13311 
13312  default:
13313  break;
13314  }
13315 
13316  ndbinfo_send_scan_conf(signal, req, rl);
13317 }
13318 
13319 bool
13320 Dbtc::validate_filter(Signal* signal)
13321 {
13322  Uint32 * start = signal->theData + 1;
13323  Uint32 * end = signal->theData + signal->getLength();
13324  if (start == end)
13325  {
13326  infoEvent("No filter specified, not listing...");
13327  return false;
13328  }
13329 
13330  while(start < end)
13331  {
13332  switch(* start){
13333  case 1: // API Node
13334  case 4: // Inactive time
13335  start += 2;
13336  break;
13337  case 2: // Transid
13338  start += 3;
13339  break;
13340  default:
13341  infoEvent("Invalid filter op: 0x%x pos: %ld",
13342  * start,
13343  (long int)(start - (signal->theData + 1)));
13344  return false;
13345  }
13346  }
13347 
13348  if (start != end)
13349  {
13350  infoEvent("Invalid filter, unexpected end");
13351  return false;
13352  }
13353 
13354  return true;
13355 }
13356 
13357 bool
13358 Dbtc::match_and_print(Signal* signal, ApiConnectRecordPtr apiPtr)
13359 {
13360  Uint32 conState = apiPtr.p->apiConnectstate;
13361  if (conState == CS_CONNECTED ||
13362  conState == CS_DISCONNECTED ||
13363  conState == CS_RESTART)
13364  return false;
13365 
13366  Uint32 len = signal->getLength();
13367  Uint32* start = signal->theData + 2;
13368  Uint32* end = signal->theData + len;
13369  Uint32 apiTimer = getApiConTimer(apiPtr.i);
13370  while (start < end)
13371  {
13372  jam();
13373  switch(* start){
13374  case 1:
13375  jam();
13376  if (refToNode(apiPtr.p->ndbapiBlockref) != * (start + 1))
13377  return false;
13378  start += 2;
13379  break;
13380  case 2:
13381  jam();
13382  if (apiPtr.p->transid[0] != * (start + 1) ||
13383  apiPtr.p->transid[1] != * (start + 2))
13384  return false;
13385  start += 3;
13386  break;
13387  case 4:{
13388  jam();
13389  if (apiTimer == 0 || ((ctcTimer - apiTimer) / 100) < * (start + 1))
13390  return false;
13391  start += 2;
13392  break;
13393  }
13394  default:
13395  ndbassert(false);
13396  return false;
13397  }
13398  }
13399 
13400  if (start != end)
13401  {
13402  ndbassert(false);
13403  return false;
13404  }
13405 
13409  Uint32 *temp = signal->theData + 25;
13410  memcpy(temp, signal->theData, 4 * len);
13411 
13412  char state[10];
13413  const char *stateptr = "";
13414 
13415  switch(apiPtr.p->apiConnectstate){
13416  case CS_STARTED:
13417  stateptr = "Prepared";
13418  break;
13419  case CS_RECEIVING:
13420  case CS_REC_COMMITTING:
13421  case CS_START_COMMITTING:
13422  stateptr = "Running";
13423  break;
13424  case CS_COMMITTING:
13425  stateptr = "Committing";
13426  break;
13427  case CS_COMPLETING:
13428  stateptr = "Completing";
13429  break;
13430  case CS_PREPARE_TO_COMMIT:
13431  stateptr = "Prepare to commit";
13432  break;
13433  case CS_COMMIT_SENT:
13434  stateptr = "Commit sent";
13435  break;
13436  case CS_COMPLETE_SENT:
13437  stateptr = "Complete sent";
13438  break;
13439  case CS_ABORTING:
13440  stateptr = "Aborting";
13441  break;
13442  case CS_START_SCAN:
13443  stateptr = "Scanning";
13444  break;
13445  case CS_WAIT_ABORT_CONF:
13446  case CS_WAIT_COMMIT_CONF:
13447  case CS_WAIT_COMPLETE_CONF:
13448  case CS_FAIL_PREPARED:
13449  case CS_FAIL_COMMITTING:
13450  case CS_FAIL_COMMITTED:
13451  case CS_REC_PREPARING:
13452  case CS_START_PREPARING:
13453  case CS_PREPARED:
13454  case CS_RESTART:
13455  case CS_FAIL_ABORTED:
13456  case CS_DISCONNECTED:
13457  default:
13458  BaseString::snprintf(state, sizeof(state),
13459  "%u", apiPtr.p->apiConnectstate);
13460  stateptr = state;
13461  break;
13462  }
13463 
13464  char buf[100];
13465  BaseString::snprintf(buf, sizeof(buf),
13466  "TRX[%u]: API: %d(0x%x)"
13467  "transid: 0x%x 0x%x inactive: %u(%d) state: %s",
13468  apiPtr.i,
13469  refToNode(apiPtr.p->ndbapiBlockref),
13470  refToBlock(apiPtr.p->ndbapiBlockref),
13471  apiPtr.p->transid[0],
13472  apiPtr.p->transid[1],
13473  apiTimer ? (ctcTimer - apiTimer) / 100 : 0,
13474  c_apiConTimer_line[apiPtr.i],
13475  stateptr);
13476  infoEvent("%s", buf);
13477 
13478  memcpy(signal->theData, temp, 4*len);
13479  return true;
13480 }
13481 
13482 void Dbtc::execABORT_ALL_REQ(Signal* signal)
13483 {
13484  jamEntry();
13485  AbortAllReq * req = (AbortAllReq*)&signal->theData[0];
13486  AbortAllRef * ref = (AbortAllRef*)&signal->theData[0];
13487 
13488  const Uint32 senderData = req->senderData;
13489  const BlockReference senderRef = req->senderRef;
13490 
13491  if(getAllowStartTransaction(refToNode(senderRef), 0) == true && !getNodeState().getSingleUserMode()){
13492  jam();
13493 
13494  ref->senderData = senderData;
13495  ref->errorCode = AbortAllRef::InvalidState;
13496  sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
13497  AbortAllRef::SignalLength, JBB);
13498  return;
13499  }
13500 
13501  if(c_abortRec.clientRef != 0){
13502  jam();
13503 
13504  ref->senderData = senderData;
13505  ref->errorCode = AbortAllRef::AbortAlreadyInProgress;
13506  sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
13507  AbortAllRef::SignalLength, JBB);
13508  return;
13509  }
13510 
13511  if(refToNode(senderRef) != getOwnNodeId()){
13512  jam();
13513 
13514  ref->senderData = senderData;
13515  ref->errorCode = AbortAllRef::FunctionNotImplemented;
13516  sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
13517  AbortAllRef::SignalLength, JBB);
13518  return;
13519  }
13520 
13521  c_abortRec.clientRef = senderRef;
13522  c_abortRec.clientData = senderData;
13523  c_abortRec.oldTimeOutValue = ctimeOutValue;
13524 
13525  ctimeOutValue = 0;
13526  const Uint32 sleepTime = (2 * 10 * ctimeOutCheckDelay + 199) / 200;
13527 
13528  checkAbortAllTimeout(signal, (sleepTime == 0 ? 1 : sleepTime));
13529 }
13530 
13531 void Dbtc::checkAbortAllTimeout(Signal* signal, Uint32 sleepTime)
13532 {
13533 
13534  ndbrequire(c_abortRec.clientRef != 0);
13535 
13536  if(sleepTime > 0){
13537  jam();
13538 
13539  sleepTime -= 1;
13540  signal->theData[0] = TcContinueB::ZWAIT_ABORT_ALL;
13541  signal->theData[1] = sleepTime;
13542  sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 200, 2);
13543  return;
13544  }
13545 
13546  AbortAllConf * conf = (AbortAllConf*)&signal->theData[0];
13547  conf->senderData = c_abortRec.clientData;
13548  sendSignal(c_abortRec.clientRef, GSN_ABORT_ALL_CONF, signal,
13549  AbortAllConf::SignalLength, JBB);
13550 
13551  ctimeOutValue = c_abortRec.oldTimeOutValue;
13552  c_abortRec.clientRef = 0;
13553 }
13554 
13555 /* **************************************************************** */
13556 /* ---------------------------------------------------------------- */
13557 /* ------------------ TRIGGER AND INDEX HANDLING ------------------ */
13558 /* ---------------------------------------------------------------- */
13559 /* **************************************************************** */
13560 
13561 void Dbtc::execCREATE_TRIG_IMPL_REQ(Signal* signal)
13562 {
13563  jamEntry();
13564  if (!assembleFragments(signal))
13565  {
13566  jam();
13567  return;
13568  }
13569 
13570  const CreateTrigImplReq* req = (const CreateTrigImplReq*)signal->getDataPtr();
13571  const Uint32 senderRef = req->senderRef;
13572  const Uint32 senderData = req->senderData;
13573 
13574  SectionHandle handle(this, signal);
13575  releaseSections(handle); // Not using mask
13576 
13577  TcDefinedTriggerData* triggerData;
13578  DefinedTriggerPtr triggerPtr;
13579 
13580  triggerPtr.i = req->triggerId;
13581  if (ERROR_INSERTED(8033) ||
13582  !c_theDefinedTriggers.seizeId(triggerPtr, req->triggerId)) {
13583  jam();
13584  CLEAR_ERROR_INSERT_VALUE;
13585  // Failed to allocate trigger record
13586 ref:
13587  CreateTrigImplRef* ref = (CreateTrigImplRef*)signal->getDataPtrSend();
13588 
13589  ref->senderRef = reference();
13590  ref->senderData = senderData;
13591  ref->errorCode = CreateTrigImplRef::InconsistentTC;
13592  ref->errorLine = __LINE__;
13593  sendSignal(senderRef, GSN_CREATE_TRIG_IMPL_REF,
13594  signal, CreateTrigImplRef::SignalLength, JBB);
13595  return;
13596  }
13597 
13598  triggerData = triggerPtr.p;
13599  triggerData->triggerId = req->triggerId;
13600  triggerData->triggerType = TriggerInfo::getTriggerType(req->triggerInfo);
13601  triggerData->triggerEvent = TriggerInfo::getTriggerEvent(req->triggerInfo);
13602  triggerData->oldTriggerIds[0] = RNIL;
13603  triggerData->oldTriggerIds[1] = RNIL;
13604 
13605  switch(triggerData->triggerType){
13606  case TriggerType::SECONDARY_INDEX:
13607  jam();
13608  triggerData->indexId = req->indexId;
13609  break;
13610  case TriggerType::REORG_TRIGGER:
13611  jam();
13612  triggerData->tableId = req->tableId;
13613  break;
13614  default:
13615  c_theDefinedTriggers.release(triggerPtr);
13616  goto ref;
13617  }
13618 
13619  if (unlikely(req->triggerId != req->upgradeExtra[1]))
13620  {
13624  jam();
13625  ndbrequire(req->triggerId == req->upgradeExtra[0]);
13626  ndbrequire(triggerData->triggerType == TriggerType::SECONDARY_INDEX);
13627 
13628  DefinedTriggerPtr insertPtr = triggerPtr;
13629  DefinedTriggerPtr updatePtr;
13630  DefinedTriggerPtr deletePtr;
13631  if (c_theDefinedTriggers.seizeId(updatePtr, req->upgradeExtra[1]) == false)
13632  {
13633  jam();
13634  c_theDefinedTriggers.release(insertPtr);
13635  goto ref;
13636  }
13637 
13638  if (c_theDefinedTriggers.seizeId(deletePtr, req->upgradeExtra[2]) == false)
13639  {
13640  jam();
13641  c_theDefinedTriggers.release(insertPtr);
13642  c_theDefinedTriggers.release(updatePtr);
13643  goto ref;
13644  }
13645 
13646  insertPtr.p->triggerEvent = TriggerEvent::TE_INSERT;
13647 
13648  updatePtr.p->triggerId = req->upgradeExtra[1];
13649  updatePtr.p->triggerType = TriggerType::SECONDARY_INDEX;
13650  updatePtr.p->triggerEvent = TriggerEvent::TE_UPDATE;
13651  updatePtr.p->oldTriggerIds[0] = RNIL;
13652  updatePtr.p->oldTriggerIds[1] = RNIL;
13653  updatePtr.p->indexId = req->indexId;
13654 
13655  deletePtr.p->triggerId = req->upgradeExtra[2];
13656  deletePtr.p->triggerType = TriggerType::SECONDARY_INDEX;
13657  deletePtr.p->triggerEvent = TriggerEvent::TE_DELETE;
13658  deletePtr.p->oldTriggerIds[0] = RNIL;
13659  deletePtr.p->oldTriggerIds[1] = RNIL;
13660  deletePtr.p->indexId = req->indexId;
13661  }
13662 
13663  CreateTrigImplConf* conf = (CreateTrigImplConf*)signal->getDataPtrSend();
13664  conf->senderRef = reference();
13665  conf->senderData = senderData;
13666  sendSignal(senderRef, GSN_CREATE_TRIG_IMPL_CONF,
13667  signal, CreateTrigImplConf::SignalLength, JBB);
13668 }
13669 
13670 void Dbtc::execDROP_TRIG_IMPL_REQ(Signal* signal)
13671 {
13672  jamEntry();
13673  const DropTrigImplReq* req = (const DropTrigImplReq*)signal->getDataPtr();
13674  const Uint32 senderRef = req->senderRef;
13675  const Uint32 senderData = req->senderData;
13676 
13677  DefinedTriggerPtr triggerPtr;
13678  triggerPtr.i = req->triggerId;
13679 
13680  if (ERROR_INSERTED(8035) ||
13681  ((triggerPtr.p = c_theDefinedTriggers.getPtr(req->triggerId)) == NULL))
13682  {
13683  jam();
13684  CLEAR_ERROR_INSERT_VALUE;
13685  // Failed to find find trigger record
13686  DropTrigImplRef* ref = (DropTrigImplRef*)signal->getDataPtrSend();
13687 
13688  ref->senderRef = reference();
13689  ref->senderData = senderData;
13690  ref->errorCode = DropTrigImplRef::InconsistentTC;
13691  ref->errorLine = __LINE__;
13692  sendSignal(senderRef, GSN_DROP_TRIG_IMPL_REF,
13693  signal, DropTrigImplRef::SignalLength, JBB);
13694  return;
13695  }
13696 
13697  if (unlikely(triggerPtr.p->oldTriggerIds[0] != RNIL))
13698  {
13699  jam();
13700  c_theDefinedTriggers.release(triggerPtr.p->oldTriggerIds[0]);
13701  c_theDefinedTriggers.release(triggerPtr.p->oldTriggerIds[1]);
13702  }
13703 
13704  // Release trigger record
13705  c_theDefinedTriggers.release(triggerPtr);
13706 
13707  DropTrigImplConf* conf = (DropTrigImplConf*)signal->getDataPtrSend();
13708 
13709  conf->senderRef = reference();
13710  conf->senderData = senderData;
13711 
13712  sendSignal(senderRef, GSN_DROP_TRIG_IMPL_CONF,
13713  signal, DropTrigImplConf::SignalLength, JBB);
13714 }
13715 
13716 void Dbtc::execCREATE_INDX_IMPL_REQ(Signal* signal)
13717 {
13718  jamEntry();
13719  const CreateIndxImplReq * const req =
13720  (const CreateIndxImplReq *)signal->getDataPtr();
13721  const Uint32 senderRef = req->senderRef;
13722  const Uint32 senderData = req->senderData;
13723  TcIndexData* indexData;
13724  TcIndexDataPtr indexPtr;
13725 
13726  SectionHandle handle(this, signal);
13727  if (ERROR_INSERTED(8034) ||
13728  !c_theIndexes.seizeId(indexPtr, req->indexId)) {
13729  jam();
13730  CLEAR_ERROR_INSERT_VALUE;
13731  // Failed to allocate index record
13732  CreateIndxImplRef * const ref =
13733  (CreateIndxImplRef *)signal->getDataPtrSend();
13734 
13735  ref->senderRef = reference();
13736  ref->senderData = senderData;
13737  ref->errorCode = CreateIndxImplRef::InconsistentTC;
13738  ref->errorLine = __LINE__;
13739  releaseSections(handle);
13740  sendSignal(senderRef, GSN_CREATE_INDX_IMPL_REF,
13741  signal, CreateIndxImplRef::SignalLength, JBB);
13742  return;
13743  }
13744  indexData = indexPtr.p;
13745  // Indexes always start in state IS_BUILDING
13746  // Will become IS_ONLINE in execALTER_INDX_IMPL_REQ
13747  indexData->indexState = IS_BUILDING;
13748  indexData->indexId = indexPtr.i;
13749  indexData->primaryTableId = req->tableId;
13750 
13751  // So far need only attribute count
13752  SegmentedSectionPtr ssPtr;
13753  handle.getSection(ssPtr, CreateIndxReq::ATTRIBUTE_LIST_SECTION);
13754  SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
13755  r0.reset(); // undo implicit first()
13756  if (!r0.getWord(&indexData->attributeList.sz) ||
13757  !r0.getWords(indexData->attributeList.id, indexData->attributeList.sz)) {
13758  ndbrequire(false);
13759  }
13760  indexData->primaryKeyPos = indexData->attributeList.sz;
13761 
13762  releaseSections(handle);
13763 
13764  CreateIndxImplConf * const conf =
13765  (CreateIndxImplConf *)signal->getDataPtrSend();
13766 
13767  conf->senderRef = reference();
13768  conf->senderData = senderData;
13769  sendSignal(senderRef, GSN_CREATE_INDX_IMPL_CONF,
13770  signal, CreateIndxImplConf::SignalLength, JBB);
13771 }
13772 
13773 void Dbtc::execALTER_INDX_IMPL_REQ(Signal* signal)
13774 {
13775  jamEntry();
13776  const AlterIndxImplReq * const req =
13777  (const AlterIndxImplReq *)signal->getDataPtr();
13778  const Uint32 senderRef = req->senderRef;
13779  const Uint32 senderData = req->senderData;
13780  TcIndexData* indexData;
13781  const Uint32 requestType = req->requestType;
13782  const Uint32 indexId = req->indexId;
13783 
13784  if ((indexData = c_theIndexes.getPtr(indexId)) == NULL) {
13785  jam();
13786  // Failed to find index record
13787  AlterIndxImplRef * const ref =
13788  (AlterIndxImplRef *)signal->getDataPtrSend();
13789 
13790  ref->senderRef = reference();
13791  ref->senderData = senderData;
13792  ref->errorCode = AlterIndxImplRef::InconsistentTC;
13793  ref->errorLine = __LINE__;
13794 
13795  sendSignal(senderRef, GSN_ALTER_INDX_IMPL_REF,
13796  signal, AlterIndxImplRef::SignalLength, JBB);
13797  return;
13798  }
13799  // Found index record, alter it's state
13800  switch (requestType) {
13801  case AlterIndxImplReq::AlterIndexOnline:
13802  jam();
13803  indexData->indexState = IS_ONLINE;
13804  break;
13805  case AlterIndxImplReq::AlterIndexOffline:
13806  jam();
13807  indexData->indexState = IS_BUILDING; // wl3600_todo ??
13808  break;
13809  default:
13810  ndbrequire(false);
13811  break;
13812  }
13813  AlterIndxImplConf * const conf =
13814  (AlterIndxImplConf *)signal->getDataPtrSend();
13815 
13816  conf->senderRef = reference();
13817  conf->senderData = senderData;
13818  sendSignal(senderRef, GSN_ALTER_INDX_IMPL_CONF,
13819  signal, AlterIndxImplConf::SignalLength, JBB);
13820 }
13821 
13822 void Dbtc::execFIRE_TRIG_ORD(Signal* signal)
13823 {
13824  jamEntry();
13825  FireTrigOrd * const fireOrd = (FireTrigOrd *)signal->getDataPtr();
13826  ApiConnectRecordPtr transPtr;
13827  TcConnectRecordPtr opPtr;
13828  bool transIdOk = true;
13829  /* Check the received transaction id
13830  * Older nodes do not send transid info in FIRE_TRIG_ORD
13831  */
13832  const Uint32 sourceNode = refToNode(signal->getSendersBlockRef());
13833  const Uint32 sourceNodeVersion = getNodeInfo(sourceNode).m_version;
13834  bool sigContainsTransId = ndb_fire_trig_ord_transid(sourceNodeVersion);
13835 
13836  /* Get triggering operation record */
13837  opPtr.i = fireOrd->getConnectionPtr();
13838  ptrCheckGuard(opPtr, ctcConnectFilesize, tcConnectRecord);
13839 
13840  /* Get transaction record */
13841  transPtr.i = opPtr.p->apiConnect;
13842  if (unlikely(transPtr.i == RNIL))
13843  {
13844  /* Looks like the connect record was released
13845  * Treat as a bad transid
13846  */
13847  transIdOk = false;
13848  }
13849  else
13850  {
13851  ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
13852 
13853  /* Check if signal's trans id and operation's transid are aligned */
13854  transIdOk = (! sigContainsTransId) |
13855  (! ((fireOrd->m_transId1 ^ transPtr.p->transid[0]) |
13856  (fireOrd->m_transId2 ^ transPtr.p->transid[1])));
13857  }
13858 
13859  TcFiredTriggerData key;
13860  key.fireingOperation = opPtr.i;
13861  key.nodeId = refToNode(signal->getSendersBlockRef());
13862  FiredTriggerPtr trigPtr;
13863  if(likely(c_firedTriggerHash.find(trigPtr, key)))
13864  {
13865  jam();
13866  c_firedTriggerHash.remove(trigPtr);
13867 
13868  trigPtr.p->triggerType = (TriggerType::Value)fireOrd->m_triggerType;
13869  trigPtr.p->triggerEvent = (TriggerEvent::Value)fireOrd->m_triggerEvent;
13870 
13871  if (unlikely(signal->getLength() < FireTrigOrd::SignalLength))
13872  {
13873  jam();
13874  ndbrequire(! sigContainsTransId );
13876  c_theDefinedTriggers.getPtr(ptr, trigPtr.p->triggerId);
13877  trigPtr.p->triggerType = ptr.p->triggerType;
13878  trigPtr.p->triggerEvent = ptr.p->triggerEvent;
13879  }
13880  trigPtr.p->fragId= fireOrd->fragId;
13881  bool ok = transIdOk;
13882  ok &= trigPtr.p->keyValues.getSize() == fireOrd->m_noPrimKeyWords;
13883  ok &= trigPtr.p->afterValues.getSize() == fireOrd->m_noAfterValueWords;
13884  ok &= trigPtr.p->beforeValues.getSize() == fireOrd->m_noBeforeValueWords;
13885 
13886  if (ERROR_INSERTED(8085))
13887  {
13888  ok = false;
13889  }
13890 
13891  if(likely( ok ))
13892  {
13893  jam();
13894  setApiConTimer(transPtr.i, ctcTimer, __LINE__);
13895  opPtr.p->noReceivedTriggers++;
13896  opPtr.p->triggerExecutionCount++; // Default 1 LQHKEYREQ per trigger
13897 
13898  // Insert fired trigger in execution queue
13899  transPtr.p->theFiredTriggers.add(trigPtr);
13900  if (opPtr.p->noReceivedTriggers == opPtr.p->noFiredTriggers ||
13901  transPtr.p->isExecutingDeferredTriggers()) {
13902  executeTriggers(signal, &transPtr);
13903  }
13904  return;
13905  }
13906 
13907  /* Trigger entry found but either :
13908  * - Overload resulted in loss of Trig_Attrinfo
13909  * : Release resources + Abort transaction
13910  * - Bad transaction id due to concurrent abort?
13911  * : Release resources
13912  */
13913  jam();
13914  // Release trigger records
13915  AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
13916  LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
13917  tmp1.release();
13918  LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
13919  tmp2.release();
13920  LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
13921  tmp3.release();
13922  c_theFiredTriggerPool.release(trigPtr);
13923  }
13924 
13925  /* Either no trigger entry found, or overload, or
13926  * bad transid
13927  * If transid is ok, abort the transaction.
13928  * else, return.
13929  * (Note small risk of 'abort of innocent' in upgrade
13930  * scenario with no transid in FIRE_TRIG_ORD)
13931  */
13932  jam();
13933  if (transIdOk)
13934  {
13935  jam();
13936  abortTransFromTrigger(signal, transPtr, ZGET_DATAREC_ERROR);
13937  }
13938 
13939  return;
13940 }
13941 
13942 void Dbtc::execTRIG_ATTRINFO(Signal* signal)
13943 {
13944  jamEntry();
13945  TrigAttrInfo * const trigAttrInfo = (TrigAttrInfo *)signal->getDataPtr();
13946  Uint32 attrInfoLength = signal->getLength() - TrigAttrInfo::StaticLength;
13947  const Uint32 *src = trigAttrInfo->getData();
13948  FiredTriggerPtr firedTrigPtr;
13949 
13950  TcFiredTriggerData key;
13951  key.fireingOperation = trigAttrInfo->getConnectionPtr();
13952  key.nodeId = refToNode(signal->getSendersBlockRef());
13953  if(!c_firedTriggerHash.find(firedTrigPtr, key)){
13954  jam();
13955  /* TODO : Node failure handling (use sig-train assembly) */
13956  if(!c_firedTriggerHash.seize(firedTrigPtr)){
13957  jam();
13961  ndbout_c("op: %d node: %d failed to seize",
13962  key.fireingOperation, key.nodeId);
13963  return;
13964  }
13965  ndbrequire(firedTrigPtr.p->keyValues.getSize() == 0 &&
13966  firedTrigPtr.p->beforeValues.getSize() == 0 &&
13967  firedTrigPtr.p->afterValues.getSize() == 0);
13968 
13969  firedTrigPtr.p->nodeId = refToNode(signal->getSendersBlockRef());
13970  firedTrigPtr.p->fireingOperation = key.fireingOperation;
13971  firedTrigPtr.p->triggerId = trigAttrInfo->getTriggerId();
13972  c_firedTriggerHash.add(firedTrigPtr);
13973  }
13974 
13975  AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
13976  switch (trigAttrInfo->getAttrInfoType()) {
13977  case(TrigAttrInfo::PRIMARY_KEY):
13978  jam();
13979  {
13980  LocalDataBuffer<11> buf(pool, firedTrigPtr.p->keyValues);
13981  buf.append(src, attrInfoLength);
13982  }
13983  break;
13984  case(TrigAttrInfo::BEFORE_VALUES):
13985  jam();
13986  {
13987  LocalDataBuffer<11> buf(pool, firedTrigPtr.p->beforeValues);
13988  buf.append(src, attrInfoLength);
13989  }
13990  break;
13991  case(TrigAttrInfo::AFTER_VALUES):
13992  jam();
13993  {
13994  LocalDataBuffer<11> buf(pool, firedTrigPtr.p->afterValues);
13995  buf.append(src, attrInfoLength);
13996  }
13997  break;
13998  default:
13999  ndbrequire(false);
14000  }
14001 }
14002 
14003 void Dbtc::execDROP_INDX_IMPL_REQ(Signal* signal)
14004 {
14005  jamEntry();
14006  const DropIndxImplReq * const req =
14007  (const DropIndxImplReq *)signal->getDataPtr();
14008  const Uint32 senderRef = req->senderRef;
14009  const Uint32 senderData = req->senderData;
14010  TcIndexData* indexData;
14011 
14012  if (ERROR_INSERTED(8036) ||
14013  (indexData = c_theIndexes.getPtr(req->indexId)) == NULL) {
14014  jam();
14015  CLEAR_ERROR_INSERT_VALUE;
14016  // Failed to find index record
14017  DropIndxImplRef * const ref =
14018  (DropIndxImplRef *)signal->getDataPtrSend();
14019 
14020  ref->senderRef = reference();
14021  ref->senderData = senderData;
14022  ref->errorCode = DropIndxImplRef::InconsistentTC;
14023  ref->errorLine = __LINE__;
14024  sendSignal(senderRef, GSN_DROP_INDX_IMPL_REF,
14025  signal, DropIndxImplRef::SignalLength, JBB);
14026  return;
14027  }
14028  // Release index record
14029  c_theIndexes.release(req->indexId);
14030 
14031  DropIndxImplConf * const conf =
14032  (DropIndxImplConf *)signal->getDataPtrSend();
14033 
14034  conf->senderRef = reference();
14035  conf->senderData = senderData;
14036  sendSignal(senderRef, GSN_DROP_INDX_IMPL_CONF,
14037  signal, DropIndxImplConf::SignalLength, JBB);
14038 }
14039 
14040 void Dbtc::execTCINDXREQ(Signal* signal)
14041 {
14042  jamEntry();
14043 
14044  TcKeyReq * const tcIndxReq = (TcKeyReq *)signal->getDataPtr();
14045  const UintR TapiIndex = tcIndxReq->apiConnectPtr;
14046  Uint32 tcIndxRequestInfo = tcIndxReq->requestInfo;
14047  Uint32 startFlag = tcIndxReq->getStartFlag(tcIndxRequestInfo);
14048  ApiConnectRecordPtr transPtr;
14049  bool isLongTcIndxReq= (signal->getNoOfSections() != 0);
14050  SectionHandle handle(this, signal);
14051 
14052  transPtr.i = TapiIndex;
14053  if (transPtr.i >= capiConnectFilesize) {
14054  jam();
14055  warningHandlerLab(signal, __LINE__);
14056  releaseSections(handle);
14057  return;
14058  }//if
14059  ptrAss(transPtr, apiConnectRecord);
14060  ApiConnectRecord * const regApiPtr = transPtr.p;
14061  // Seize index operation
14062  TcIndexOperationPtr indexOpPtr;
14076  if (((startFlag == 1) &&
14077  (regApiPtr->apiConnectstate == CS_CONNECTED ||
14078  (regApiPtr->apiConnectstate == CS_STARTED &&
14079  regApiPtr->firstTcConnect == RNIL))) ||
14080  (regApiPtr->apiConnectstate == CS_ABORTING &&
14081  regApiPtr->abortState == AS_IDLE))
14082  {
14083  jam();
14084  // This is a newly started transaction, clean-up from any
14085  // previous transaction.
14086  releaseAllSeizedIndexOperations(regApiPtr);
14087 
14088  regApiPtr->apiConnectstate = CS_STARTED;
14089  regApiPtr->transid[0] = tcIndxReq->transId1;
14090  regApiPtr->transid[1] = tcIndxReq->transId2;
14091  }//if
14092 
14093  if (getNodeState().startLevel == NodeState::SL_SINGLEUSER &&
14094  getNodeState().getSingleUserApi() !=
14095  refToNode(regApiPtr->ndbapiBlockref))
14096  {
14097  jam();
14098  releaseSections(handle);
14099  terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
14100  regApiPtr->m_flags |=
14101  TcKeyReq::getExecuteFlag(tcIndxRequestInfo) ?
14102  ApiConnectRecord::TF_EXEC_FLAG : 0;
14103  apiConnectptr = transPtr;
14104  abortErrorLab(signal);
14105  return;
14106  }
14107 
14108  if (ERROR_INSERTED(8036) || !seizeIndexOperation(regApiPtr, indexOpPtr)) {
14109  jam();
14110  releaseSections(handle);
14111  // Failed to allocate index operation
14112  terrorCode = 288;
14113  regApiPtr->m_flags |=
14114  TcKeyReq::getExecuteFlag(tcIndxRequestInfo) ?
14115  ApiConnectRecord::TF_EXEC_FLAG : 0;
14116  apiConnectptr = transPtr;
14117  abortErrorLab(signal);
14118  return;
14119  }
14120  TcIndexOperation* indexOp = indexOpPtr.p;
14121  indexOp->indexOpId = indexOpPtr.i;
14122 
14123  // Save original signal
14124  indexOp->tcIndxReq = *tcIndxReq;
14125  indexOp->connectionIndex = TapiIndex;
14126  regApiPtr->accumulatingIndexOp = indexOp->indexOpId;
14127 
14128  if (isLongTcIndxReq)
14129  {
14130  jam();
14131  /* KeyInfo and AttrInfo already received into sections */
14132  SegmentedSectionPtr keyInfoSection, attrInfoSection;
14133 
14134  /* Store i value for first long section of KeyInfo
14135  * and AttrInfo in Index operation
14136  */
14137  handle.getSection(keyInfoSection,
14138  TcKeyReq::KeyInfoSectionNum);
14139 
14140  indexOp->keyInfoSectionIVal= keyInfoSection.i;
14141 
14142  if (handle.m_cnt == 2)
14143  {
14144  handle.getSection(attrInfoSection,
14145  TcKeyReq::AttrInfoSectionNum);
14146  indexOp->attrInfoSectionIVal= attrInfoSection.i;
14147  }
14148 
14149  /* Detach sections from the handle
14150  * Success path code, or index operation cleanup is
14151  * now responsible for freeing the sections
14152  */
14153  handle.clear();
14154 
14155  /* All data received, process */
14156  readIndexTable(signal, regApiPtr, indexOp);
14157  return;
14158  }
14159  else
14160  {
14161  jam();
14162  /* Short TcIndxReq, build up KeyInfo and AttrInfo
14163  * sections from separate signals
14164  */
14165  Uint32 * dataPtr = &tcIndxReq->scanInfo;
14166  Uint32 indexLength = TcKeyReq::getKeyLength(tcIndxRequestInfo);
14167  Uint32 attrLength = TcKeyReq::getAttrinfoLen(tcIndxReq->attrLen);
14168 
14169  indexOp->pendingKeyInfo = indexLength;
14170  indexOp->pendingAttrInfo = attrLength;
14171 
14172  const Uint32 includedIndexLength = MIN(indexLength, TcKeyReq::MaxKeyInfo);
14173  const Uint32 includedAttrLength = MIN(attrLength, TcKeyReq::MaxAttrInfo);
14174  int ret;
14175 
14176  if ((ret = saveINDXKEYINFO(signal,
14177  indexOp,
14178  dataPtr,
14179  includedIndexLength)) == 0)
14180  {
14181  jam();
14182  /* All KI + no AI received, process */
14183  readIndexTable(signal, regApiPtr, indexOp);
14184  return;
14185  }
14186  else if (ret == -1)
14187  {
14188  jam();
14189  return;
14190  }
14191 
14192  dataPtr += includedIndexLength;
14193 
14194  if (saveINDXATTRINFO(signal,
14195  indexOp,
14196  dataPtr,
14197  includedAttrLength) == 0) {
14198  jam();
14199  /* All KI and AI received, process */
14200  readIndexTable(signal, regApiPtr, indexOp);
14201  return;
14202  }
14203  }
14204 }
14205 
14206 void Dbtc::execINDXKEYINFO(Signal* signal)
14207 {
14208  jamEntry();
14209  Uint32 keyInfoLength = signal->getLength() - IndxKeyInfo::HeaderLength;
14210  IndxKeyInfo * const indxKeyInfo = (IndxKeyInfo *)signal->getDataPtr();
14211  const Uint32 *src = indxKeyInfo->getData();
14212  const UintR TconnectIndex = indxKeyInfo->connectPtr;
14213  ApiConnectRecordPtr transPtr;
14214  transPtr.i = TconnectIndex;
14215  if (transPtr.i >= capiConnectFilesize) {
14216  jam();
14217  warningHandlerLab(signal, __LINE__);
14218  return;
14219  }//if
14220  ptrAss(transPtr, apiConnectRecord);
14221  ApiConnectRecord * const regApiPtr = transPtr.p;
14222  TcIndexOperationPtr indexOpPtr;
14223  TcIndexOperation* indexOp;
14224 
14225  if (compare_transid(regApiPtr->transid, indxKeyInfo->transId) == false)
14226  {
14227  TCKEY_abort(signal, 19);
14228  return;
14229  }
14230 
14231  if (regApiPtr->apiConnectstate == CS_ABORTING)
14232  {
14233  jam();
14234  return;
14235  }
14236 
14237  if((indexOpPtr.i = regApiPtr->accumulatingIndexOp) != RNIL)
14238  {
14239  indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
14240 
14241  ndbassert( indexOp->pendingKeyInfo > 0 );
14242 
14243  if (saveINDXKEYINFO(signal,
14244  indexOp,
14245  src,
14246  keyInfoLength) == 0) {
14247  jam();
14248  /* All KI + AI received, process */
14249  readIndexTable(signal, regApiPtr, indexOp);
14250  }
14251  }
14252 }
14253 
14254 void Dbtc::execINDXATTRINFO(Signal* signal)
14255 {
14256  jamEntry();
14257  Uint32 attrInfoLength = signal->getLength() - IndxAttrInfo::HeaderLength;
14258  IndxAttrInfo * const indxAttrInfo = (IndxAttrInfo *)signal->getDataPtr();
14259  const Uint32 *src = indxAttrInfo->getData();
14260  const UintR TconnectIndex = indxAttrInfo->connectPtr;
14261  ApiConnectRecordPtr transPtr;
14262  transPtr.i = TconnectIndex;
14263  if (transPtr.i >= capiConnectFilesize) {
14264  jam();
14265  warningHandlerLab(signal, __LINE__);
14266  return;
14267  }//if
14268  ptrAss(transPtr, apiConnectRecord);
14269  ApiConnectRecord * const regApiPtr = transPtr.p;
14270  TcIndexOperationPtr indexOpPtr;
14271  TcIndexOperation* indexOp;
14272 
14273  if (compare_transid(regApiPtr->transid, indxAttrInfo->transId) == false)
14274  {
14275  TCKEY_abort(signal, 19);
14276  return;
14277  }
14278 
14279  if (regApiPtr->apiConnectstate == CS_ABORTING)
14280  {
14281  jam();
14282  return;
14283  }
14284 
14285  if((indexOpPtr.i = regApiPtr->accumulatingIndexOp) != RNIL)
14286  {
14287  indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
14288 
14289  ndbassert( indexOp->pendingAttrInfo > 0 );
14290 
14291  if (saveINDXATTRINFO(signal,
14292  indexOp,
14293  src,
14294  attrInfoLength) == 0) {
14295  jam();
14296  /* All KI + AI received, process */
14297  readIndexTable(signal, regApiPtr, indexOp);
14298  return;
14299  }
14300  return;
14301  }
14302 }
14303 
14308 int
14309 Dbtc::saveINDXKEYINFO(Signal* signal,
14310  TcIndexOperation* indexOp,
14311  const Uint32 *src,
14312  Uint32 len)
14313 {
14314  if (ERROR_INSERTED(8052) ||
14315  ! appendToSection(indexOp->keyInfoSectionIVal,
14316  src,
14317  len))
14318  {
14319  jam();
14320  // Failed to seize keyInfo, abort transaction
14321 #ifdef VM_TRACE
14322  ndbout_c("Dbtc::saveINDXKEYINFO: Failed to seize buffer for KeyInfo\n");
14323 #endif
14324  // Abort transaction
14325  apiConnectptr.i = indexOp->connectionIndex;
14326  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
14327  releaseIndexOperation(apiConnectptr.p, indexOp);
14328  terrorCode = 289;
14329  if(TcKeyReq::getExecuteFlag(indexOp->tcIndxReq.requestInfo))
14330  apiConnectptr.p->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
14331  abortErrorLab(signal);
14332  return -1;
14333  }
14334  indexOp->pendingKeyInfo-= len;
14335 
14336  if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp)) {
14337  jam();
14338  return 0;
14339  }
14340  return 1;
14341 }
14342 
14343 bool Dbtc::receivedAllINDXKEYINFO(TcIndexOperation* indexOp)
14344 {
14345  return (indexOp->pendingKeyInfo == 0);
14346 }
14347 
14352 int
14353 Dbtc::saveINDXATTRINFO(Signal* signal,
14354  TcIndexOperation* indexOp,
14355  const Uint32 *src,
14356  Uint32 len)
14357 {
14358  if (ERROR_INSERTED(8051) ||
14359  ! appendToSection(indexOp->attrInfoSectionIVal,
14360  src,
14361  len))
14362  {
14363  jam();
14364 #ifdef VM_TRACE
14365  ndbout_c("Dbtc::saveINDXATTRINFO: Failed to seize buffer for attrInfo\n");
14366 #endif
14367  apiConnectptr.i = indexOp->connectionIndex;
14368  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
14369  releaseIndexOperation(apiConnectptr.p, indexOp);
14370  terrorCode = 289;
14371  if(TcKeyReq::getExecuteFlag(indexOp->tcIndxReq.requestInfo))
14372  apiConnectptr.p->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
14373  abortErrorLab(signal);
14374  return -1;
14375  }
14376 
14377  indexOp->pendingAttrInfo-= len;
14378 
14379  if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp)) {
14380  jam();
14381  return 0;
14382  }
14383  return 1;
14384 }
14385 
14386 bool Dbtc::receivedAllINDXATTRINFO(TcIndexOperation* indexOp)
14387 {
14388  return (indexOp->pendingAttrInfo == 0);
14389 }
14390 
14391 #ifdef ERROR_INSERT
14392 extern bool ErrorImportActive;
14393 #endif
14394 
14395 bool Dbtc::saveTRANSID_AI(Signal* signal,
14396  TcIndexOperation* indexOp,
14397  const Uint32 *src,
14398  Uint32 len)
14399 {
14400  /* TransID_AI is received as a result of looking up a
14401  * unique index table
14402  * The unique index table is looked up using the index
14403  * key to receive a single attribute containing the
14404  * fragment holding the base table row and the base
14405  * table primary key.
14406  * This is later used to build a TCKEYREQ against the
14407  * base table.
14408  * In this method, we prepare a KEYINFO section for the
14409  * TCKEYREQ as we receive TRANSID_AI words.
14410  *
14411  * Expected TRANSID_AI words :
14412  *
14413  * Word(s) Description States
14414  *
14415  * 0 Attribute header ITAS_WAIT_HEADER
14416  * containing length -> ITAS_WAIT_FRAGID
14417  *
14418  * 1 Fragment Id ITAS_WAIT_FRAGID
14419  * -> ITAS_WAIT_KEY
14420  *
14421  * [2..N] Base table primary ITAS_WAIT_KEY
14422  * key info -> [ ITAS_WAIT_KEY |
14423  * ITAS_WAIT_KEY_FAIL ]
14424  * -> ITAS_ALL_RECEIVED
14425  *
14426  * The outgoing KeyInfo section contains the base
14427  * table primary key info, with the fragment id passed
14428  * as the distribution key.
14429  * ITAS_WAIT_KEY_FAIL state is entered when there is no
14430  * space to store received TRANSID_AI information and
14431  * key collection must fail. Transaction abort is performed
14432  * once all TRANSID_AI is received, and the system waits in
14433  * ITAS_WAIT_KEY_FAIL state until then.
14434  *
14435  */
14436  Uint32 remain= len;
14437 
14438  while (remain != 0)
14439  {
14440  switch(indexOp->transIdAIState) {
14441  case ITAS_WAIT_HEADER:
14442  {
14443  jam();
14444  ndbassert(indexOp->transIdAISectionIVal == RNIL);
14445  /* Look at the first AttributeHeader to get the
14446  * expected size of the primary key attribute
14447  */
14448  AttributeHeader* head = (AttributeHeader *) src;
14449  ndbassert(head->getHeaderSize() == 1);
14450  indexOp->pendingTransIdAI = 1 + head->getDataSize();
14451 
14452  src++;
14453  remain--;
14454  indexOp->transIdAIState = ITAS_WAIT_FRAGID;
14455  break;
14456  }
14457  case ITAS_WAIT_FRAGID:
14458  {
14459  jam();
14460  ndbassert(indexOp->transIdAISectionIVal == RNIL);
14461  /* Grab the fragment Id word */
14462  indexOp->fragmentId= *src;
14463 
14464  src++;
14465  remain--;
14466  indexOp->transIdAIState = ITAS_WAIT_KEY;
14467  break;
14468  }
14469  case ITAS_WAIT_KEY:
14470  {
14471  jam();
14472  /* Add key information to long section */
14473 #ifdef ERROR_INSERT
14474  if (ERROR_INSERTED(8066))
14475  {
14476  ErrorImportActive = true;
14477  }
14478 #endif
14479 
14480  bool res = appendToSection(indexOp->transIdAISectionIVal, src, remain);
14481 #ifdef ERROR_INSERT
14482  if (ERROR_INSERTED(8066))
14483  {
14484  ErrorImportActive = false;
14485  }
14486 #endif
14487 
14488  if (res)
14489  {
14490  jam();
14491  remain= 0;
14492  break;
14493  }
14494  else
14495  {
14496  jam();
14497 #ifdef VM_TRACE
14498  ndbout_c("Dbtc::saveTRANSID_AI: Failed to seize buffer for TRANSID_AI\n");
14499 #endif
14500  indexOp->transIdAIState= ITAS_WAIT_KEY_FAIL;
14501  /* Fall through to ITAS_WAIT_KEY_FAIL state handling */
14502  }
14503  }
14504 
14505  case ITAS_WAIT_KEY_FAIL:
14506  {
14507  /* Failed when collecting key previously - if we have all the
14508  * TRANSID_AI now then we abort
14509  */
14510  if (indexOp->pendingTransIdAI > len)
14511  {
14512  /* Still some TransIdAI to arrive, keep waiting as if we had
14513  * stored it
14514  */
14515  remain= 0;
14516  break;
14517  }
14518 
14519  /* All TransIdAI has arrived, abort */
14520  apiConnectptr.i = indexOp->connectionIndex;
14521  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
14522  releaseIndexOperation(apiConnectptr.p, indexOp);
14523  terrorCode = ZGET_DATAREC_ERROR;
14524  abortErrorLab(signal);
14525  return false;
14526  }
14527 
14528  case ITAS_ALL_RECEIVED:
14529  jam();
14530  // Fall through
14531  default:
14532  jam();
14533  /* Bad state, or bad state to receive TransId_Ai in */
14534  // Todo : Check error handling here.
14535 #ifdef VM_TRACE
14536  ndbout_c("Dbtc::saveTRANSID_AI: Bad state when receiving\n");
14537 #endif
14538  apiConnectptr.i = indexOp->connectionIndex;
14539  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
14540  releaseIndexOperation(apiConnectptr.p, indexOp);
14541  terrorCode = 4349;
14542  abortErrorLab(signal);
14543  return false;
14544  } // switch
14545  } // while
14546 
14547  if ((indexOp->pendingTransIdAI-= len) == 0)
14548  indexOp->transIdAIState = ITAS_ALL_RECEIVED;
14549 
14550  return true;
14551 }
14552 
14553 bool Dbtc::receivedAllTRANSID_AI(TcIndexOperation* indexOp)
14554 {
14555  return (indexOp->transIdAIState == ITAS_ALL_RECEIVED);
14556 }
14557 
14563 void Dbtc::execTCKEYCONF(Signal* signal)
14564 {
14565  TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtr();
14566  TcIndexOperationPtr indexOpPtr;
14567 
14568  jamEntry();
14569  indexOpPtr.i = tcKeyConf->apiConnectPtr;
14570  TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
14571  Uint32 confInfo = tcKeyConf->confInfo;
14572 
14576  ndbassert(TcKeyConf::getCommitFlag(confInfo) == false);
14577 
14578  indexOpPtr.p = indexOp;
14579  if (!indexOp) {
14580  jam();
14581  // Missing index operation
14582  return;
14583  }
14584  const UintR TconnectIndex = indexOp->connectionIndex;
14585  ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex];
14586  apiConnectptr.p = regApiPtr;
14587  apiConnectptr.i = TconnectIndex;
14588  switch(indexOp->indexOpState) {
14589  case(IOS_NOOP): {
14590  jam();
14591  // Should never happen, abort
14592  TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
14593 
14594  tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
14595  tcIndxRef->transId[0] = regApiPtr->transid[0];
14596  tcIndxRef->transId[1] = regApiPtr->transid[1];
14597  tcIndxRef->errorCode = 4349;
14598  tcIndxRef->errorData = 0;
14599  sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
14600  TcKeyRef::SignalLength, JBB);
14601  return;
14602  }
14603  case(IOS_INDEX_ACCESS): {
14604  jam();
14605  // Just waiting for the TRANSID_AI now
14606  indexOp->indexOpState = IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI;
14607  break;
14608  }
14609  case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI): {
14610  jam();
14611  // Double TCKEYCONF, should never happen, abort
14612  TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
14613 
14614  tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
14615  tcIndxRef->transId[0] = regApiPtr->transid[0];
14616  tcIndxRef->transId[1] = regApiPtr->transid[1];
14617  tcIndxRef->errorCode = 4349;
14618  tcIndxRef->errorData = 0;
14619  sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
14620  TcKeyRef::SignalLength, JBB);
14621  return;
14622  }
14623  case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
14624  jam();
14625  // Continue with index operation
14626  executeIndexOperation(signal, regApiPtr, indexOp);
14627  break;
14628  }
14629  }
14630 }
14631 
14632 void Dbtc::execTCKEYREF(Signal* signal)
14633 {
14634  TcKeyRef * const tcKeyRef = (TcKeyRef *)signal->getDataPtr();
14635  TcIndexOperationPtr indexOpPtr;
14636 
14637  jamEntry();
14638  indexOpPtr.i = tcKeyRef->connectPtr;
14639  TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
14640  indexOpPtr.p = indexOp;
14641  if (!indexOp) {
14642  jam();
14643  // Missing index operation
14644  return;
14645  }
14646  const UintR TconnectIndex = indexOp->connectionIndex;
14647  ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex];
14648 
14649  switch(indexOp->indexOpState) {
14650  case(IOS_NOOP): {
14651  jam();
14652  // Should never happen, abort
14653  break;
14654  }
14655  case(IOS_INDEX_ACCESS):
14656  case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI):
14657  case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
14658  jam();
14659  // Send TCINDXREF
14660 
14661  TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
14662  TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
14663 
14664  tcIndxRef->connectPtr = tcIndxReq->senderData;
14665  tcIndxRef->transId[0] = tcKeyRef->transId[0];
14666  tcIndxRef->transId[1] = tcKeyRef->transId[1];
14667  tcIndxRef->errorCode = tcKeyRef->errorCode;
14668  tcIndxRef->errorData = 0;
14669 
14670  releaseIndexOperation(regApiPtr, indexOp);
14671 
14672  sendSignal(regApiPtr->ndbapiBlockref,
14673  GSN_TCINDXREF, signal, TcKeyRef::SignalLength, JBB);
14674  return;
14675  }
14676  }
14677 }
14678 
14679 void Dbtc::execTRANSID_AI_R(Signal* signal){
14680  TransIdAI * const transIdAI = (TransIdAI *)signal->getDataPtr();
14681  Uint32 sigLen = signal->length();
14682  Uint32 dataLen = sigLen - TransIdAI::HeaderLength - 1;
14683  Uint32 recBlockref = transIdAI->attrData[dataLen];
14684 
14685  jamEntry();
14686 
14687  SectionHandle handle(this, signal);
14688 
14693  sendSignal(recBlockref, GSN_TRANSID_AI,
14694  signal, sigLen - 1, JBB,
14695  &handle);
14696 }
14697 
14698 void Dbtc::execKEYINFO20_R(Signal* signal){
14699  KeyInfo20 * const keyInfo = (KeyInfo20 *)signal->getDataPtr();
14700  Uint32 sigLen = signal->length();
14701  Uint32 dataLen = sigLen - KeyInfo20::HeaderLength - 1;
14702  Uint32 recBlockref = keyInfo->keyData[dataLen];
14703 
14704  jamEntry();
14705 
14706  SectionHandle handle(this, signal);
14707 
14712  sendSignal(recBlockref, GSN_KEYINFO20,
14713  signal, sigLen - 1, JBB,
14714  &handle);
14715 }
14716 
14717 
14727 void Dbtc::execTRANSID_AI(Signal* signal)
14728 {
14729  TransIdAI * const transIdAI = (TransIdAI *)signal->getDataPtr();
14730 
14731  jamEntry();
14732  TcIndexOperationPtr indexOpPtr;
14733  indexOpPtr.i = transIdAI->connectPtr;
14734  TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
14735  indexOpPtr.p = indexOp;
14736  if (!indexOp) {
14737  jam();
14738  // Missing index operation
14739  }
14740  const UintR TconnectIndex = indexOp->connectionIndex;
14741  ApiConnectRecordPtr transPtr;
14742 
14743  transPtr.i = TconnectIndex;
14744  ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
14745  ApiConnectRecord * const regApiPtr = transPtr.p;
14746 
14747  // Acccumulate attribute data
14748  SectionHandle handle(this, signal);
14749  bool longSignal = (handle.m_cnt == 1);
14750  if (longSignal)
14751  {
14752  SegmentedSectionPtr dataPtr;
14753  Uint32 dataLen;
14754  ndbrequire(handle.getSection(dataPtr, 0));
14755  dataLen = dataPtr.sz;
14756 
14757  SectionSegment * ptrP = dataPtr.p;
14758  while (dataLen > NDB_SECTION_SEGMENT_SZ)
14759  {
14760  if (!saveTRANSID_AI(signal, indexOp, &ptrP->theData[0],
14761  NDB_SECTION_SEGMENT_SZ))
14762  {
14763  releaseSections(handle);
14764  goto save_error;
14765  }
14766  dataLen -= NDB_SECTION_SEGMENT_SZ;
14767  ptrP = g_sectionSegmentPool.getPtr(ptrP->m_nextSegment);
14768  }
14769  if (!saveTRANSID_AI(signal, indexOp, &ptrP->theData[0], dataLen))
14770  {
14771  releaseSections(handle);
14772  goto save_error;
14773  }
14774 
14775  releaseSections(handle);
14776  }
14777  else
14778  {
14779  /* Short TransId_AI signal */
14780  if (!saveTRANSID_AI(signal,
14781  indexOp,
14782  transIdAI->getData(),
14783  signal->getLength() - TransIdAI::HeaderLength)) {
14784  save_error:
14785  jam();
14786  // Failed to allocate space for TransIdAI
14787  // Todo : How will this behave when transaction already aborted
14788  // in saveTRANSID_AI call?
14789  TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
14790 
14791  tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
14792  tcIndxRef->transId[0] = regApiPtr->transid[0];
14793  tcIndxRef->transId[1] = regApiPtr->transid[1];
14794  tcIndxRef->errorCode = ZGET_DATAREC_ERROR;
14795  tcIndxRef->errorData = 0;
14796  sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
14797  TcKeyRef::SignalLength, JBB);
14798  return;
14799  }
14800  }
14801 
14802  switch(indexOp->indexOpState) {
14803  case(IOS_NOOP): {
14804  jam();
14805  // Should never happen, abort
14806  TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
14807 
14808  tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
14809  tcIndxRef->transId[0] = regApiPtr->transid[0];
14810  tcIndxRef->transId[1] = regApiPtr->transid[1];
14811  tcIndxRef->errorCode = 4349;
14812  tcIndxRef->errorData = 0;
14813  sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
14814  TcKeyRef::SignalLength, JBB);
14815  return;
14816  break;
14817  }
14818  case(IOS_INDEX_ACCESS): {
14819  jam();
14820  // Check if all TRANSID_AI have been received
14821  if (receivedAllTRANSID_AI(indexOp)) {
14822  jam();
14823  // Just waiting for a TCKEYCONF now
14824  indexOp->indexOpState = IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF;
14825  }
14826  // else waiting for either TRANSID_AI or TCKEYCONF
14827  break;
14828  }
14829  case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
14830  jam();
14831 #ifdef VM_TRACE
14832  ndbout_c("Dbtc::execTRANSID_AI: Too many TRANSID_AI, ignore for now\n");
14833 #endif
14834  /*
14835  // Too many TRANSID_AI
14836  TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
14837 
14838  tcIndexRef->connectPtr = indexOp->tcIndxReq.senderData;
14839  tcIndxRef->transId[0] = regApiPtr->transid[0];
14840  tcIndxRef->transId[1] = regApiPtr->transid[1];
14841  tcIndxRef->errorCode = 4349;
14842  tcIndxRef->errorData = 0;
14843  sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
14844  TcKeyRef::SignalLength, JBB);
14845  */
14846  break;
14847  }
14848  case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI): {
14849  jam();
14850  // Check if all TRANSID_AI have been received
14851  if (receivedAllTRANSID_AI(indexOp)) {
14852  jam();
14853  // Continue with index operation
14854  executeIndexOperation(signal, regApiPtr, indexOp);
14855  }
14856  // else continue waiting for more TRANSID_AI
14857  break;
14858  }
14859  }
14860 }
14861 
14862 void Dbtc::execTCROLLBACKREP(Signal* signal)
14863 {
14864  TcRollbackRep* tcRollbackRep = (TcRollbackRep *)signal->getDataPtr();
14865  jamEntry();
14866  TcIndexOperationPtr indexOpPtr;
14867  indexOpPtr.i = tcRollbackRep->connectPtr;
14868  TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
14869  indexOpPtr.p = indexOp;
14870  tcRollbackRep = (TcRollbackRep *)signal->getDataPtrSend();
14871  tcRollbackRep->connectPtr = indexOp->tcIndxReq.senderData;
14872  sendSignal(apiConnectptr.p->ndbapiBlockref,
14873  GSN_TCROLLBACKREP, signal, TcRollbackRep::SignalLength, JBB);
14874 }
14875 
14879 void Dbtc::readIndexTable(Signal* signal,
14880  ApiConnectRecord* regApiPtr,
14881  TcIndexOperation* indexOp)
14882 {
14883  TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
14884  Uint32 tcKeyRequestInfo = indexOp->tcIndxReq.requestInfo;
14885  TcIndexData* indexData;
14886  Uint32 transId1 = indexOp->tcIndxReq.transId1;
14887  Uint32 transId2 = indexOp->tcIndxReq.transId2;
14888 
14889  const Operation_t opType =
14890  (Operation_t)TcKeyReq::getOperationType(tcKeyRequestInfo);
14891 
14892  // Find index table
14893  if ((indexData = c_theIndexes.getPtr(indexOp->tcIndxReq.tableId)) == NULL) {
14894  // TODO : Free KeyInfo and AttrInfo sections here if necessary
14895  // How is this operation cleaned up?
14896  jam();
14897  // Failed to find index record
14898  TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
14899 
14900  tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
14901  tcIndxRef->transId[0] = regApiPtr->transid[0];
14902  tcIndxRef->transId[1] = regApiPtr->transid[1];
14903  tcIndxRef->errorCode = 4000;
14904  // tcIndxRef->errorData = ??; Where to find indexId
14905  sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
14906  TcKeyRef::SignalLength, JBB);
14907  return;
14908  }
14909  tcKeyReq->transId1 = transId1;
14910  tcKeyReq->transId2 = transId2;
14911  tcKeyReq->tableId = indexData->indexId;
14912  tcKeyReq->tableSchemaVersion = indexOp->tcIndxReq.tableSchemaVersion;
14913  TcKeyReq::setOperationType(tcKeyRequestInfo,
14914  opType == ZREAD ? ZREAD : ZREAD_EX);
14915  TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0); // No AI in long TCKEYREQ
14916  TcKeyReq::setInterpretedFlag(tcKeyRequestInfo, 0);
14917  tcKeyReq->senderData = indexOp->indexOpId;
14918  indexOp->indexOpState = IOS_INDEX_ACCESS;
14919  regApiPtr->executingIndexOp = regApiPtr->accumulatingIndexOp;
14920  regApiPtr->accumulatingIndexOp = RNIL;
14921  regApiPtr->m_special_op_flags = TcConnectRecord::SOF_INDEX_TABLE_READ;
14922 
14923  if (ERROR_INSERTED(8037))
14924  {
14925  ndbout_c("shifting index version");
14926  tcKeyReq->tableSchemaVersion = ~(Uint32)indexOp->tcIndxReq.tableSchemaVersion;
14927  }
14928  tcKeyReq->attrLen = 1; // Primary key is stored as one attribute
14929  tcKeyReq->requestInfo = tcKeyRequestInfo;
14930 
14931  ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0);
14932  ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0);
14933 
14934  /* Long TCKEYREQ Signal sections
14935  * We attach the KeyInfo section received from the user, and
14936  * create a new AttrInfo section with just one AttributeHeader
14937  * to retrieve the base table primary key
14938  */
14939  Ptr<SectionSegment> indexLookupAttrInfoSection;
14940  Uint32 singleAIWord;
14941 
14942  AttributeHeader::init(&singleAIWord, indexData->primaryKeyPos, 0);
14943  if (! import(indexLookupAttrInfoSection,
14944  &singleAIWord,
14945  1))
14946  {
14947  jam();
14948  /* Error creating AttrInfo section to request primary
14949  * key from index table.
14950  */
14951  // TODO - verify error handling
14952 #ifdef VM_TRACE
14953  ndbout_c("Dbtc::readIndexTable: Failed to create AttrInfo section");
14954 #endif
14955  apiConnectptr.i = indexOp->connectionIndex;
14956  ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
14957  releaseIndexOperation(apiConnectptr.p, indexOp);
14958  terrorCode = 4000;
14959  abortErrorLab(signal);
14960  return;
14961  }
14962 
14963  ndbassert(signal->header.m_noOfSections == 0);
14964 
14965  signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ]
14966  = indexOp->keyInfoSectionIVal;
14967 
14968  /* We pass this section to TCKEYREQ next */
14969  indexOp->keyInfoSectionIVal= RNIL;
14970 
14971  signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ]
14972  = indexLookupAttrInfoSection.i;
14973  signal->header.m_noOfSections= 2;
14974 
14975  /* Direct execute of long TCKEYREQ
14976  * TCKEYREQ is responsible for freeing the KeyInfo and
14977  * AttrInfo sections passed to it
14978  */
14979  EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
14980  jamEntry();
14981 
14982  if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
14983  {
14984  jam();
14985  }
14986  else
14987  {
14988  jam();
14994  regApiPtr->lqhkeyreqrec++;
14995 
15000  indexOp->indexReadTcConnect = regApiPtr->lastTcConnect;
15001  }
15002 
15003  return;
15004 }
15005 
15010 void Dbtc::executeIndexOperation(Signal* signal,
15011  ApiConnectRecord* regApiPtr,
15012  TcIndexOperation* indexOp) {
15013 
15014  TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
15015  TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
15016  Uint32 tcKeyRequestInfo = tcIndxReq->requestInfo;
15017  TcIndexData* indexData;
15018 
15019  // Find index table
15020  if ((indexData = c_theIndexes.getPtr(tcIndxReq->tableId)) == NULL) {
15021  jam();
15022  // Failed to find index record
15023  // TODO : How is this operation cleaned up?
15024  TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
15025 
15026  tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
15027  tcIndxRef->transId[0] = regApiPtr->transid[0];
15028  tcIndxRef->transId[1] = regApiPtr->transid[1];
15029  tcIndxRef->errorCode = 4349;
15030  tcIndxRef->errorData = 0;
15031  sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
15032  TcKeyRef::SignalLength, JBB);
15033  return;
15034  }
15035 
15036  // Find schema version of primary table
15037  TableRecordPtr tabPtr;
15038  tabPtr.i = indexData->primaryTableId;
15039  ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
15040 
15041  tcKeyReq->apiConnectPtr = tcIndxReq->apiConnectPtr;
15042  tcKeyReq->attrLen = tcIndxReq->attrLen;
15043  tcKeyReq->tableId = indexData->primaryTableId;
15044  tcKeyReq->tableSchemaVersion = tabPtr.p->currentSchemaVersion;
15045  tcKeyReq->transId1 = regApiPtr->transid[0];
15046  tcKeyReq->transId2 = regApiPtr->transid[1];
15047  tcKeyReq->senderData = tcIndxReq->senderData; // Needed for TRANSID_AI to API
15048 
15049  if (tabPtr.p->get_user_defined_partitioning())
15050  {
15051  jam();
15052  tcKeyReq->scanInfo = indexOp->fragmentId; // As read from Index table
15053  TcKeyReq::setDistributionKeyFlag(tcKeyRequestInfo, 1U);
15054  }
15055  regApiPtr->m_special_op_flags = 0;
15056  regApiPtr->executingIndexOp = 0;
15057 
15058  /* KeyInfo section
15059  * Get the KeyInfo we received from the index table lookup
15060  */
15061  SegmentedSectionPtr keyInfoFromTransIdAI;
15062 
15063  ndbassert( indexOp->transIdAISectionIVal != RNIL );
15064  getSection(keyInfoFromTransIdAI, indexOp->transIdAISectionIVal);
15065 
15066  ndbassert( signal->header.m_noOfSections == 0 );
15067  signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ]
15068  = indexOp->transIdAISectionIVal;
15069  signal->header.m_noOfSections = 1;
15070 
15071  indexOp->transIdAISectionIVal = RNIL;
15072 
15073  /* AttrInfo section
15074  * Attach any AttrInfo section from original TCINDXREQ
15075  */
15076  if ( indexOp->attrInfoSectionIVal != RNIL )
15077  {
15078  jam();
15079  SegmentedSectionPtr attrInfoFromInitialReq;
15080 
15081  getSection(attrInfoFromInitialReq, indexOp->attrInfoSectionIVal);
15082  signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ]
15083  = indexOp->attrInfoSectionIVal;
15084  signal->header.m_noOfSections = 2;
15085  indexOp->attrInfoSectionIVal = RNIL;
15086  }
15087 
15088  releaseIndexOperation(regApiPtr, indexOp);
15089 
15090  TcKeyReq::setKeyLength(tcKeyRequestInfo, keyInfoFromTransIdAI.sz);
15091  TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
15092  TcKeyReq::setCommitFlag(tcKeyRequestInfo, 0);
15093  TcKeyReq::setExecuteFlag(tcKeyRequestInfo, 0);
15094  tcKeyReq->requestInfo = tcKeyRequestInfo;
15095 
15096  ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0);
15097  ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0);
15098 
15104  regApiPtr->lqhkeyreqrec--;
15105 
15111  TcConnectRecordPtr tmp;
15112  tmp.i = indexOp->indexReadTcConnect;
15113  ptrCheckGuard(tmp, ctcConnectFilesize, tcConnectRecord);
15114  const Uint32 currSavePointId = regApiPtr->currSavePointId;
15115  regApiPtr->currSavePointId = tmp.p->savePointId;
15116 
15117 #ifdef ERROR_INSERT
15118  bool err8072 = ERROR_INSERTED(8072);
15119  if (err8072)
15120  {
15121  CLEAR_ERROR_INSERT_VALUE;
15122  }
15123 #endif
15124 
15125  /* Execute TCKEYREQ now - it is now responsible for freeing
15126  * the KeyInfo and AttrInfo sections
15127  */
15128  EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
15129  jamEntry();
15130 
15131 #ifdef ERROR_INSERT
15132  if (err8072)
15133  {
15134  SET_ERROR_INSERT_VALUE(8072);
15135  }
15136 #endif
15137 
15138  if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
15139  {
15140  // TODO : Presumably the abort cleans up the operation
15141  jam();
15142  return;
15143  }
15144 
15145  regApiPtr->currSavePointId = currSavePointId;
15146 
15147 }
15148 
15149 bool Dbtc::seizeIndexOperation(ApiConnectRecord* regApiPtr,
15150  TcIndexOperationPtr& indexOpPtr)
15151 {
15152  if (regApiPtr->theSeizedIndexOperations.seize(indexOpPtr))
15153  {
15154  ndbassert(indexOpPtr.p->pendingKeyInfo == 0);
15155  ndbassert(indexOpPtr.p->keyInfoSectionIVal == RNIL);
15156  ndbassert(indexOpPtr.p->pendingAttrInfo == 0);
15157  ndbassert(indexOpPtr.p->attrInfoSectionIVal == RNIL);
15158  ndbassert(indexOpPtr.p->transIdAIState == ITAS_WAIT_HEADER);
15159  ndbassert(indexOpPtr.p->pendingTransIdAI == 0);
15160  ndbassert(indexOpPtr.p->transIdAISectionIVal == RNIL);
15161  return true;
15162  }
15163 
15164  return false;
15165 }
15166 
15167 void Dbtc::releaseIndexOperation(ApiConnectRecord* regApiPtr,
15168  TcIndexOperation* indexOp)
15169 {
15170  indexOp->indexOpState = IOS_NOOP;
15171  indexOp->pendingKeyInfo = 0;
15172  releaseSection(indexOp->keyInfoSectionIVal);
15173  indexOp->keyInfoSectionIVal= RNIL;
15174  indexOp->pendingAttrInfo = 0;
15175  releaseSection(indexOp->attrInfoSectionIVal);
15176  indexOp->attrInfoSectionIVal= RNIL;
15177  indexOp->transIdAIState = ITAS_WAIT_HEADER;
15178  indexOp->pendingTransIdAI = 0;
15179  releaseSection(indexOp->transIdAISectionIVal);
15180  indexOp->transIdAISectionIVal= RNIL;
15181  regApiPtr->theSeizedIndexOperations.release(indexOp->indexOpId);
15182 }
15183 
15184 void Dbtc::releaseAllSeizedIndexOperations(ApiConnectRecord* regApiPtr)
15185 {
15186  TcIndexOperationPtr seizedIndexOpPtr;
15187 
15188  regApiPtr->theSeizedIndexOperations.first(seizedIndexOpPtr);
15189  while(seizedIndexOpPtr.i != RNIL) {
15190  jam();
15191  TcIndexOperation* indexOp = seizedIndexOpPtr.p;
15192 
15193  indexOp->indexOpState = IOS_NOOP;
15194  indexOp->pendingKeyInfo = 0;
15195  releaseSection(indexOp->keyInfoSectionIVal);
15196  indexOp->keyInfoSectionIVal = RNIL;
15197  indexOp->pendingAttrInfo = 0;
15198  releaseSection(indexOp->attrInfoSectionIVal);
15199  indexOp->attrInfoSectionIVal = RNIL;
15200  indexOp->transIdAIState = ITAS_WAIT_HEADER;
15201  indexOp->pendingTransIdAI = 0;
15202  releaseSection(indexOp->transIdAISectionIVal);
15203  indexOp->transIdAISectionIVal = RNIL;
15204  regApiPtr->theSeizedIndexOperations.next(seizedIndexOpPtr);
15205  }
15206  regApiPtr->theSeizedIndexOperations.release();
15207 }
15208 
15209 void Dbtc::saveTriggeringOpState(Signal* signal, TcConnectRecord* trigOp)
15210 {
15211  LqhKeyConf * lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
15212  copyFromToLen((UintR*)lqhKeyConf,
15213  &trigOp->savedState[0],
15214  LqhKeyConf::SignalLength);
15215 }
15216 
15217 void
15218 Dbtc::trigger_op_finished(Signal* signal, ApiConnectRecordPtr regApiPtr,
15219  TcConnectRecord* triggeringOp)
15220 {
15221  if (!regApiPtr.p->isExecutingDeferredTriggers())
15222  {
15223  ndbassert(triggeringOp->triggerExecutionCount > 0);
15224  triggeringOp->triggerExecutionCount--;
15225  if (triggeringOp->triggerExecutionCount == 0)
15226  {
15231  jam();
15232  continueTriggeringOp(signal, triggeringOp);
15233  }
15234  }
15235  else
15236  {
15237  jam();
15238  lqhKeyConf_checkTransactionState(signal, regApiPtr);
15239  }
15240 }
15241 
15242 void Dbtc::continueTriggeringOp(Signal* signal, TcConnectRecord* trigOp)
15243 {
15244  LqhKeyConf * lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
15245  copyFromToLen(&trigOp->savedState[0],
15246  (UintR*)lqhKeyConf,
15247  LqhKeyConf::SignalLength);
15248 
15249  ndbassert(trigOp->savedState[LqhKeyConf::SignalLength-1] != ~Uint32(0));
15250  trigOp->savedState[LqhKeyConf::SignalLength-1] = ~Uint32(0);
15251 
15252  lqhKeyConf->noFiredTriggers = 0;
15253  trigOp->noReceivedTriggers = 0;
15254 
15255  // All triggers executed successfully, continue operation
15256  execLQHKEYCONF(signal);
15257 }
15258 
15259 void Dbtc::executeTriggers(Signal* signal, ApiConnectRecordPtr* transPtr)
15260 {
15261  ApiConnectRecord* regApiPtr = transPtr->p;
15262  TcConnectRecord *localTcConnectRecord = tcConnectRecord;
15263  TcConnectRecordPtr opPtr;
15264  FiredTriggerPtr trigPtr;
15265 
15266  if (!regApiPtr->theFiredTriggers.isEmpty()) {
15267  jam();
15268  if ((regApiPtr->apiConnectstate == CS_STARTED) ||
15269  (regApiPtr->apiConnectstate == CS_START_COMMITTING) ||
15270  (regApiPtr->apiConnectstate == CS_SEND_FIRE_TRIG_REQ) ||
15271  (regApiPtr->apiConnectstate == CS_WAIT_FIRE_TRIG_REQ))
15272  {
15273  jam();
15274  regApiPtr->theFiredTriggers.first(trigPtr);
15275  while (trigPtr.i != RNIL) {
15276  jam();
15277  // Execute all ready triggers in parallel
15278  opPtr.i = trigPtr.p->fireingOperation;
15279  ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
15280  FiredTriggerPtr nextTrigPtr = trigPtr;
15281  regApiPtr->theFiredTriggers.next(nextTrigPtr);
15282  if (opPtr.p->noReceivedTriggers == opPtr.p->noFiredTriggers ||
15283  regApiPtr->isExecutingDeferredTriggers()) {
15284  jam();
15285  // Fireing operation is ready to have a trigger executing
15286  executeTrigger(signal, trigPtr.p, transPtr, &opPtr);
15287  // Should allow for interleaving here by sending a CONTINUEB and
15288  // return
15289  // Release trigger records
15290  AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
15291  LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
15292  tmp1.release();
15293  LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
15294  tmp2.release();
15295  LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
15296  tmp3.release();
15297  regApiPtr->theFiredTriggers.release(trigPtr);
15298  }
15299  trigPtr = nextTrigPtr;
15300  }
15301  return;
15302  // No more triggers, continue transaction after last executed trigger has
15303  // reurned (in execLQHKEYCONF or execLQHKEYREF)
15304  } else {
15305 
15306  jam();
15307  /* Not in correct state to fire triggers yet, need to wait
15308  * (or keep waiting)
15309  */
15310 
15311  if ((regApiPtr->apiConnectstate == CS_RECEIVING) ||
15312  (regApiPtr->apiConnectstate == CS_REC_COMMITTING))
15313  {
15314  // Wait until transaction is ready to execute a trigger
15315  jam();
15316  if (!tc_testbit(regApiPtr->m_flags,
15317  ApiConnectRecord::TF_TRIGGER_PENDING))
15318  {
15319  jam();
15320  regApiPtr->m_flags |= ApiConnectRecord::TF_TRIGGER_PENDING;
15321  signal->theData[0] = TcContinueB::TRIGGER_PENDING;
15322  signal->theData[1] = transPtr->i;
15323  signal->theData[2] = regApiPtr->transid[0];
15324  signal->theData[3] = regApiPtr->transid[1];
15325  sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
15326  }
15327  // else
15328  // We are already waiting for a pending trigger (CONTINUEB)
15329  }
15330  else
15331  {
15332  /* Transaction has started aborting.
15333  * Forget about unprocessed triggers
15334  */
15335  ndbrequire(regApiPtr->apiConnectstate == CS_ABORTING);
15336  }
15337  }
15338  }
15339 }
15340 
15341 void Dbtc::executeTrigger(Signal* signal,
15342  TcFiredTriggerData* firedTriggerData,
15343  ApiConnectRecordPtr* transPtr,
15344  TcConnectRecordPtr* opPtr)
15345 {
15346  TcDefinedTriggerData* definedTriggerData;
15347 
15348  if ((definedTriggerData =
15349  c_theDefinedTriggers.getPtr(firedTriggerData->triggerId))
15350  != NULL)
15351  {
15352  transPtr->p->pendingTriggers--;
15353  switch(firedTriggerData->triggerType) {
15354  case(TriggerType::SECONDARY_INDEX):
15355  jam();
15356  executeIndexTrigger(signal, definedTriggerData, firedTriggerData,
15357  transPtr, opPtr);
15358  break;
15359  case TriggerType::REORG_TRIGGER:
15360  jam();
15361  executeReorgTrigger(signal, definedTriggerData, firedTriggerData,
15362  transPtr, opPtr);
15363  break;
15364  default:
15365  ndbrequire(false);
15366  }
15367  }
15368 }
15369 
15370 void Dbtc::executeIndexTrigger(Signal* signal,
15371  TcDefinedTriggerData* definedTriggerData,
15372  TcFiredTriggerData* firedTriggerData,
15373  ApiConnectRecordPtr* transPtr,
15374  TcConnectRecordPtr* opPtr)
15375 {
15376  TcIndexData* indexData = c_theIndexes.getPtr(definedTriggerData->indexId);
15377  ndbassert(indexData != NULL);
15378 
15379  switch (firedTriggerData->triggerEvent) {
15380  case(TriggerEvent::TE_INSERT): {
15381  jam();
15382  insertIntoIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
15383  break;
15384  }
15385  case(TriggerEvent::TE_DELETE): {
15386  jam();
15387  deleteFromIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
15388  break;
15389  }
15390  case(TriggerEvent::TE_UPDATE): {
15391  jam();
15392  opPtr->p->triggerExecutionCount++; // One is already added...and this is 2
15393  deleteFromIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
15394  insertIntoIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
15395  break;
15396  }
15397  default:
15398  ndbrequire(false);
15399  }
15400 }
15401 
15402 void Dbtc::releaseFiredTriggerData(DLFifoList<TcFiredTriggerData>* triggers)
15403 {
15404  FiredTriggerPtr trigPtr;
15405 
15406  triggers->first(trigPtr);
15407  while (trigPtr.i != RNIL) {
15408  jam();
15409  // Release trigger records
15410 
15411  AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
15412  LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
15413  tmp1.release();
15414  LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
15415  tmp2.release();
15416  LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
15417  tmp3.release();
15418 
15419  triggers->next(trigPtr);
15420  }
15421  triggers->release();
15422 }
15423 
15431 void Dbtc::abortTransFromTrigger(Signal* signal,
15432  const ApiConnectRecordPtr& transPtr,
15433  Uint32 error)
15434 {
15435  jam();
15436  terrorCode = error;
15437 
15438  apiConnectptr = transPtr;
15439 
15440  abortErrorLab(signal);
15441 }
15442 
15454 bool Dbtc::appendAttrDataToSection(Uint32& sectionIVal,
15455  DataBuffer<11>& values,
15456  bool withHeaders,
15457  Uint32& attrId,
15458  bool& hasNull)
15459 {
15460  AttributeBuffer::DataBufferIterator iter;
15461  bool moreData= values.first(iter);
15462  hasNull= false;
15463  const Uint32 segSize= values.getSegmentSize(); // 11
15464 
15465  while (moreData)
15466  {
15467  AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
15468  Uint32 dataSize= attrHeader->getDataSize();
15469  hasNull |= (dataSize == 0);
15470 
15471  if (withHeaders)
15472  {
15473  AttributeHeader ah(*iter.data);
15474  ah.setAttributeId(attrId); // Renumber AttrIds
15475  if (unlikely(!appendToSection(sectionIVal,
15476  &ah.m_value,
15477  1)))
15478  {
15479  releaseSection(sectionIVal);
15480  sectionIVal= RNIL;
15481  return false;
15482  }
15483  }
15484 
15485  moreData= values.next(iter, 1);
15486 
15487  while (dataSize)
15488  {
15489  ndbrequire(moreData);
15490  /* Copy as many contiguous words as possible */
15491  Uint32 contigLeft= segSize - iter.ind;
15492  ndbassert(contigLeft);
15493  Uint32 contigValid= MIN(dataSize, contigLeft);
15494 
15495  if (unlikely(!appendToSection(sectionIVal,
15496  iter.data,
15497  contigValid)))
15498  {
15499  releaseSection(sectionIVal);
15500  sectionIVal= RNIL;
15501  return false;
15502  }
15503  moreData= values.next(iter, contigValid);
15504  dataSize-= contigValid;
15505  }
15506  attrId++;
15507  }
15508 
15509  return true;
15510 }
15511 
15512 void Dbtc::insertIntoIndexTable(Signal* signal,
15513  TcFiredTriggerData* firedTriggerData,
15514  ApiConnectRecordPtr* transPtr,
15515  TcConnectRecordPtr* opPtr,
15516  TcIndexData* indexData)
15517 {
15518  ApiConnectRecord* regApiPtr = transPtr->p;
15519  TcConnectRecord* opRecord = opPtr->p;
15520  TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
15521  Uint32 tcKeyRequestInfo = 0;
15522  TableRecordPtr indexTabPtr;
15523 
15524  jam();
15525 
15526  indexTabPtr.i = indexData->indexId;
15527  ptrCheckGuard(indexTabPtr, ctabrecFilesize, tableRecord);
15528  tcKeyReq->apiConnectPtr = transPtr->i;
15529  tcKeyReq->senderData = opPtr->i;
15530 
15531  /* Key for insert to unique index table is the afterValues from the
15532  * base table operation (from update or insert on base).
15533  * Data for insert to unique index table is the afterValues from the
15534  * base table operation plus the fragment id and packed keyValues from
15535  * the base table operation
15536  */
15537  // Calculate key length and renumber attribute id:s
15538  AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
15539  LocalDataBuffer<11> afterValues(pool, firedTriggerData->afterValues);
15540  LocalDataBuffer<11> keyValues(pool, firedTriggerData->keyValues);
15541 
15542  if (afterValues.getSize() == 0)
15543  {
15544  jam();
15545  ndbrequire(tc_testbit(regApiPtr->m_flags,
15546  ApiConnectRecord::TF_DEFERRED_CONSTRAINTS));
15547  trigger_op_finished(signal, *transPtr, opRecord);
15548  return;
15549  }
15550 
15551  Uint32 keyIVal= RNIL;
15552  Uint32 attrIVal= RNIL;
15553  bool appendOk= false;
15554  do
15555  {
15556  Uint32 attrId= 0;
15557  bool hasNull= false;
15558 
15559  /* Build Insert KeyInfo section from aftervalues */
15560  if (unlikely(! appendAttrDataToSection(keyIVal,
15561  afterValues,
15562  false, // No AttributeHeaders
15563  attrId,
15564  hasNull)))
15565  {
15566  jam();
15567  break;
15568  }
15569 
15570  if(ERROR_INSERTED(8086))
15571  {
15572  /* Simulate SS exhaustion */
15573  break;
15574  }
15575 
15576  /* If there's Nulls in the values that become the index table's
15577  * PK then we skip this insert
15578  */
15579  if (hasNull)
15580  {
15581  jam();
15582  releaseSection(keyIVal);
15583  trigger_op_finished(signal, *transPtr, opRecord);
15584  return;
15585  }
15586 
15587  /* Build Insert AttrInfo section from aftervalues,
15588  * fragment id + keyvalues
15589  */
15590  AttributeHeader ah(attrId, 0); // Length tbd.
15591  attrId= 0;
15592  if (unlikely((! appendAttrDataToSection(attrIVal,
15593  afterValues,
15594  true, // Include AttributeHeaders,
15595  attrId,
15596  hasNull)) ||
15597  (! appendToSection(attrIVal,
15598  &ah.m_value,
15599  1))))
15600  {
15601  jam();
15602  break;
15603  }
15604 
15605  AttributeHeader* pkHeader= (AttributeHeader*) getLastWordPtr(attrIVal);
15606  Uint32 startSz= getSectionSz(attrIVal);
15607  if (unlikely((! appendToSection(attrIVal,
15608  &firedTriggerData->fragId,
15609  1)) ||
15610  (! appendAttrDataToSection(attrIVal,
15611  keyValues,
15612  false, // No AttributeHeaders
15613  attrId,
15614  hasNull))))
15615  {
15616  jam();
15617  break;
15618  }
15619 
15620  appendOk= true;
15621 
15622  /* Now go back and set pk header length */
15623  pkHeader->setDataSize(getSectionSz(attrIVal) - startSz);
15624  } while(0);
15625 
15626  if (unlikely(!appendOk))
15627  {
15628  /* Some failure building up KeyInfo and AttrInfo */
15629  releaseSection(keyIVal);
15630  releaseSection(attrIVal);
15631  abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
15632  return;
15633  }
15634 
15635  /* Now build TcKeyReq for insert */
15636  TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
15637  tcKeyReq->attrLen = 0;
15638  TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
15639  tcKeyReq->tableId = indexData->indexId;
15640  TcKeyReq::setOperationType(tcKeyRequestInfo, ZINSERT);
15641  tcKeyReq->tableSchemaVersion = indexTabPtr.p->currentSchemaVersion;
15642  tcKeyReq->transId1 = regApiPtr->transid[0];
15643  tcKeyReq->transId2 = regApiPtr->transid[1];
15644  tcKeyReq->requestInfo = tcKeyRequestInfo;
15645 
15646  /* Attach Key and AttrInfo sections to signal */
15647  ndbrequire(signal->header.m_noOfSections == 0);
15648  signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyIVal;
15649  signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ] = attrIVal;
15650  signal->header.m_noOfSections= 2;
15651 
15652  /*
15653  * Fix savepoint id -
15654  * fix so that insert has same savepoint id as triggering operation
15655  */
15656  const Uint32 currSavePointId = regApiPtr->currSavePointId;
15657  regApiPtr->currSavePointId = opRecord->savePointId;
15658  regApiPtr->m_special_op_flags = TcConnectRecord::SOF_TRIGGER;
15659  /* Pass trigger Id via ApiConnectRecord (nasty) */
15660  ndbrequire(regApiPtr->immediateTriggerId == RNIL);
15661  regApiPtr->immediateTriggerId= firedTriggerData->triggerId;
15662 
15663  EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
15664  jamEntry();
15665 
15666  /*
15667  * Restore ApiConnectRecord state
15668  */
15669  regApiPtr->currSavePointId = currSavePointId;
15670  regApiPtr->immediateTriggerId = RNIL;
15671 }
15672 
15673 void Dbtc::deleteFromIndexTable(Signal* signal,
15674  TcFiredTriggerData* firedTriggerData,
15675  ApiConnectRecordPtr* transPtr,
15676  TcConnectRecordPtr* opPtr,
15677  TcIndexData* indexData)
15678 {
15679  ApiConnectRecord* regApiPtr = transPtr->p;
15680  TcConnectRecord* opRecord = opPtr->p;
15681  TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
15682  Uint32 tcKeyRequestInfo = 0;
15683  TableRecordPtr indexTabPtr;
15684 
15685  indexTabPtr.i = indexData->indexId;
15686  ptrCheckGuard(indexTabPtr, ctabrecFilesize, tableRecord);
15687  tcKeyReq->apiConnectPtr = transPtr->i;
15688  tcKeyReq->senderData = opPtr->i;
15689 
15690  // Calculate key length and renumber attribute id:s
15691  AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
15692  LocalDataBuffer<11> beforeValues(pool, firedTriggerData->beforeValues);
15693 
15694  Uint32 keyIVal= RNIL;
15695  Uint32 attrId= 0;
15696  bool hasNull= false;
15697 
15698  if (beforeValues.getSize() == 0)
15699  {
15700  jam();
15701  ndbrequire(tc_testbit(regApiPtr->m_flags,
15702  ApiConnectRecord::TF_DEFERRED_CONSTRAINTS));
15703  trigger_op_finished(signal, *transPtr, opRecord);
15704  return;
15705  }
15706 
15707  /* Build Delete KeyInfo section from beforevalues */
15708  if (unlikely((! appendAttrDataToSection(keyIVal,
15709  beforeValues,
15710  false, // No AttributeHeaders
15711  attrId,
15712  hasNull)) ||
15713  ERROR_INSERTED(8086)))
15714  {
15715  jam();
15716  releaseSection(keyIVal);
15717  abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
15718  return;
15719  }
15720 
15721  /* If there's Nulls in the values that become the index table's
15722  * PK then we skip this delete
15723  */
15724  if (hasNull)
15725  {
15726  jam();
15727  releaseSection(keyIVal);
15728  trigger_op_finished(signal, *transPtr, opRecord);
15729  return;
15730  }
15731 
15732  TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
15733  TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
15734  tcKeyReq->attrLen = 0;
15735  tcKeyReq->tableId = indexData->indexId;
15736  TcKeyReq::setOperationType(tcKeyRequestInfo, ZDELETE);
15737  tcKeyReq->tableSchemaVersion = indexTabPtr.p->currentSchemaVersion;
15738  tcKeyReq->transId1 = regApiPtr->transid[0];
15739  tcKeyReq->transId2 = regApiPtr->transid[1];
15740  tcKeyReq->requestInfo = tcKeyRequestInfo;
15741 
15742  /* Attach KeyInfo section to signal */
15743  ndbrequire(signal->header.m_noOfSections == 0);
15744  signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyIVal;
15745  signal->header.m_noOfSections= 1;
15746 
15751  const Uint32 currSavePointId = regApiPtr->currSavePointId;
15752  regApiPtr->currSavePointId = opRecord->savePointId;
15753  regApiPtr->m_special_op_flags = TcConnectRecord::SOF_TRIGGER;
15754  /* Pass trigger Id via ApiConnectRecord (nasty) */
15755  ndbrequire(regApiPtr->immediateTriggerId == RNIL);
15756  regApiPtr->immediateTriggerId= firedTriggerData->triggerId;
15757  EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
15758  jamEntry();
15759 
15760  /*
15761  * Restore ApiConnectRecord state
15762  */
15763  regApiPtr->currSavePointId = currSavePointId;
15764  regApiPtr->immediateTriggerId = RNIL;
15765 }
15766 
15767 Uint32
15768 Dbtc::TableRecord::getErrorCode(Uint32 schemaVersion) const {
15769  if(!get_enabled())
15770  return ZNO_SUCH_TABLE;
15771  if(get_dropping())
15772  return ZDROP_TABLE_IN_PROGRESS;
15773  if(table_version_major(schemaVersion) != table_version_major(currentSchemaVersion))
15774  return ZWRONG_SCHEMA_VERSION_ERROR;
15775  ErrorReporter::handleAssert("Dbtc::TableRecord::getErrorCode",
15776  __FILE__, __LINE__);
15777  return 0;
15778 }
15779 
15780 void Dbtc::executeReorgTrigger(Signal* signal,
15781  TcDefinedTriggerData* definedTriggerData,
15782  TcFiredTriggerData* firedTriggerData,
15783  ApiConnectRecordPtr* transPtr,
15784  TcConnectRecordPtr* opPtr)
15785 {
15786 
15787  ApiConnectRecord* regApiPtr = transPtr->p;
15788  TcConnectRecord* opRecord = opPtr->p;
15789  TcKeyReq * tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
15790 
15791  tcKeyReq->apiConnectPtr = transPtr->i;
15792  tcKeyReq->senderData = opPtr->i;
15793 
15794  AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
15795  LocalDataBuffer<11> keyValues(pool, firedTriggerData->keyValues);
15796  LocalDataBuffer<11> attrValues(pool, firedTriggerData->afterValues);
15797 
15798  Uint32 optype;
15799  bool sendAttrInfo= true;
15800 
15801  switch (firedTriggerData->triggerEvent) {
15802  case TriggerEvent::TE_INSERT:
15803  optype = ZINSERT;
15804  break;
15805  case TriggerEvent::TE_UPDATE:
15811  optype = ZWRITE;
15812  break;
15813  case TriggerEvent::TE_DELETE:
15814  optype = ZDELETE;
15815  sendAttrInfo= false;
15816  break;
15817  default:
15818  ndbrequire(false);
15819  }
15820 
15821  Ptr<TableRecord> tablePtr;
15822  tablePtr.i = definedTriggerData->tableId;
15823  ptrCheckGuard(tablePtr, ctabrecFilesize, tableRecord);
15824  Uint32 tableVersion = tablePtr.p->currentSchemaVersion;
15825 
15826  Uint32 tcKeyRequestInfo = 0;
15827  TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
15828  TcKeyReq::setOperationType(tcKeyRequestInfo, optype);
15829  TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
15830  tcKeyReq->attrLen = 0;
15831  tcKeyReq->tableId = tablePtr.i;
15832  tcKeyReq->requestInfo = tcKeyRequestInfo;
15833  tcKeyReq->tableSchemaVersion = tableVersion;
15834  tcKeyReq->transId1 = regApiPtr->transid[0];
15835  tcKeyReq->transId2 = regApiPtr->transid[1];
15836 
15837  Uint32 keyIVal= RNIL;
15838  Uint32 attrIVal= RNIL;
15839  Uint32 attrId= 0;
15840  bool hasNull= false;
15841 
15842  /* Prepare KeyInfo section */
15843  if (unlikely(!appendAttrDataToSection(keyIVal,
15844  keyValues,
15845  false, // No AttributeHeaders
15846  attrId,
15847  hasNull)))
15848  {
15849  releaseSection(keyIVal);
15850  abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
15851  return;
15852  }
15853 
15854  ndbrequire(!hasNull);
15855 
15856  if (sendAttrInfo)
15857  {
15858  /* Prepare AttrInfo section from Key values and
15859  * After values
15860  */
15862  LocalDataBuffer<11>* buffers[2];
15863  buffers[0]= &keyValues;
15864  buffers[1]= &attrValues;
15865  const Uint32 segSize= keyValues.getSegmentSize(); // 11
15866  for (int buf=0; buf < 2; buf++)
15867  {
15868  Uint32 dataSize= buffers[buf]->getSize();
15869  bool moreData= buffers[buf]->first(attrIter);
15870 
15871  while(dataSize)
15872  {
15873  ndbrequire(moreData);
15874  Uint32 contigLeft= segSize - attrIter.ind;
15875  Uint32 contigValid= MIN(dataSize, contigLeft);
15876 
15877  if (unlikely(!appendToSection(attrIVal,
15878  attrIter.data,
15879  contigValid)))
15880  {
15881  releaseSection(keyIVal);
15882  releaseSection(attrIVal);
15883  abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
15884  return;
15885  }
15886  moreData= buffers[buf]->next(attrIter, contigValid);
15887  dataSize-= contigValid;
15888  }
15889  ndbassert(!moreData);
15890  }
15891  }
15892 
15893  /* Attach Key and optional AttrInfo sections to signal */
15894  ndbrequire(signal->header.m_noOfSections == 0);
15895  signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyIVal;
15896  signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ] = attrIVal;
15897  signal->header.m_noOfSections= sendAttrInfo? 2 : 1;
15898 
15903  const Uint32 currSavePointId = regApiPtr->currSavePointId;
15904  regApiPtr->currSavePointId = opRecord->savePointId;
15905  regApiPtr->m_special_op_flags = TcConnectRecord::SOF_REORG_TRIGGER;
15906  /* Pass trigger Id via ApiConnectRecord (nasty) */
15907  ndbrequire(regApiPtr->immediateTriggerId == RNIL);
15908 
15909  regApiPtr->immediateTriggerId= firedTriggerData->triggerId;
15910  EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
15911  jamEntry();
15912 
15913  /*
15914  * Restore ApiConnectRecord state
15915  */
15916  regApiPtr->currSavePointId = currSavePointId;
15917  regApiPtr->immediateTriggerId = RNIL;
15918 }
15919 
15920 void
15921 Dbtc::execROUTE_ORD(Signal* signal)
15922 {
15923  jamEntry();
15924  if(!assembleFragments(signal)){
15925  jam();
15926  return;
15927  }
15928 
15929  SectionHandle handle(this, signal);
15930 
15931  RouteOrd* ord = (RouteOrd*)signal->getDataPtr();
15932  Uint32 dstRef = ord->dstRef;
15933  Uint32 srcRef = ord->srcRef;
15934  Uint32 gsn = ord->gsn;
15935 
15936  if (likely(getNodeInfo(refToNode(dstRef)).m_connected))
15937  {
15938  jam();
15939  Uint32 secCount = handle.m_cnt;
15940  ndbrequire(secCount >= 1 && secCount <= 3);
15941 
15942  jamLine(secCount);
15943 
15947  Uint32 sigLen = handle.m_ptr[0].sz;
15948  ndbrequire(sigLen <= 25);
15949  copy(signal->theData, handle.m_ptr[0]);
15950 
15951  SegmentedSectionPtr save = handle.m_ptr[0];
15952  for (Uint32 i = 0; i < secCount - 1; i++)
15953  handle.m_ptr[i] = handle.m_ptr[i+1];
15954  handle.m_cnt--;
15955 
15956  sendSignal(dstRef, gsn, signal, sigLen, JBB, &handle);
15957 
15958  handle.m_cnt = 1;
15959  handle.m_ptr[0] = save;
15960  releaseSections(handle);
15961  return ;
15962  }
15963 
15964  releaseSections(handle);
15965  warningEvent("Unable to route GSN: %d from %x to %x",
15966  gsn, srcRef, dstRef);
15967 
15968 }