1 /*
2    Copyright (c) 2003, 2021, Oracle and/or its affiliates.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #include <ndb_global.h>
26 
27 #include "DbUtil.hpp"
28 
29 #include <ndb_version.h>
30 
31 #include <signaldata/WaitGCP.hpp>
32 #include <signaldata/KeyInfo.hpp>
33 #include <signaldata/AttrInfo.hpp>
34 #include <signaldata/TcKeyConf.hpp>
35 #include <signaldata/TcKeyFailConf.hpp>
36 #include <signaldata/GetTabInfo.hpp>
37 #include <signaldata/DictTabInfo.hpp>
38 #include <signaldata/NodeFailRep.hpp>
39 
40 #include <signaldata/UtilSequence.hpp>
41 #include <signaldata/UtilPrepare.hpp>
42 #include <signaldata/UtilRelease.hpp>
43 #include <signaldata/UtilExecute.hpp>
44 #include <signaldata/UtilLock.hpp>
45 
46 #include <SectionReader.hpp>
47 #include <Interpreter.hpp>
48 #include <AttributeHeader.hpp>
49 
50 #include <NdbTick.h>
51 
52 #include <signaldata/DbinfoScan.hpp>
53 #include <signaldata/TransIdAI.hpp>
54 
55 #define JAM_FILE_ID 400
56 
57 
58 /**************************************************************************
59  * ------------------------------------------------------------------------
60  *  MODULE:       Startup
61  * ------------------------------------------------------------------------
62  *
63  *  Constructors, startup, initializations
64  **************************************************************************/
65 
DbUtil(Block_context & ctx)66 DbUtil::DbUtil(Block_context& ctx) :
67   SimulatedBlock(DBUTIL, ctx),
68   c_runningPrepares(c_preparePool),
69   c_seizingTransactions(c_transactionPool),
70   c_runningTransactions(c_transactionPool),
71   c_lockQueues(c_lockQueuePool)
72 {
73   BLOCK_CONSTRUCTOR(DbUtil);
74 
75   // Add received signals
76   addRecSignal(GSN_READ_CONFIG_REQ, &DbUtil::execREAD_CONFIG_REQ);
77   addRecSignal(GSN_STTOR, &DbUtil::execSTTOR);
78   addRecSignal(GSN_NDB_STTOR, &DbUtil::execNDB_STTOR);
79   addRecSignal(GSN_DUMP_STATE_ORD, &DbUtil::execDUMP_STATE_ORD);
80   addRecSignal(GSN_DBINFO_SCANREQ, &DbUtil::execDBINFO_SCANREQ);
81   addRecSignal(GSN_CONTINUEB, &DbUtil::execCONTINUEB);
82   addRecSignal(GSN_NODE_FAILREP, &DbUtil::execNODE_FAILREP);
83 
84   //addRecSignal(GSN_TCSEIZEREF, &DbUtil::execTCSEIZEREF);
85   addRecSignal(GSN_TCSEIZECONF, &DbUtil::execTCSEIZECONF);
86   addRecSignal(GSN_TCKEYCONF, &DbUtil::execTCKEYCONF);
87   addRecSignal(GSN_TCKEYREF, &DbUtil::execTCKEYREF);
88   addRecSignal(GSN_TCROLLBACKREP, &DbUtil::execTCROLLBACKREP);
89 
90   //addRecSignal(GSN_TCKEY_FAILCONF, &DbUtil::execTCKEY_FAILCONF);
91   //addRecSignal(GSN_TCKEY_FAILREF, &DbUtil::execTCKEY_FAILREF);
92   addRecSignal(GSN_TRANSID_AI, &DbUtil::execTRANSID_AI);
93 
94   /**
95    *  Sequence Service
96    */
97   addRecSignal(GSN_UTIL_SEQUENCE_REQ, &DbUtil::execUTIL_SEQUENCE_REQ);
98   // Debug
99   addRecSignal(GSN_UTIL_SEQUENCE_REF, &DbUtil::execUTIL_SEQUENCE_REF);
100   addRecSignal(GSN_UTIL_SEQUENCE_CONF, &DbUtil::execUTIL_SEQUENCE_CONF);
101 
102   /**
103    * Locking
104    */
105   addRecSignal(GSN_UTIL_CREATE_LOCK_REQ,  &DbUtil::execUTIL_CREATE_LOCK_REQ);
106   addRecSignal(GSN_UTIL_DESTROY_LOCK_REQ, &DbUtil::execUTIL_DESTORY_LOCK_REQ);
107   addRecSignal(GSN_UTIL_LOCK_REQ,  &DbUtil::execUTIL_LOCK_REQ);
108   addRecSignal(GSN_UTIL_UNLOCK_REQ, &DbUtil::execUTIL_UNLOCK_REQ);
109 
110   /**
111    *  Backend towards Dict
112    */
113   addRecSignal(GSN_GET_TABINFOREF, &DbUtil::execGET_TABINFOREF);
114   addRecSignal(GSN_GET_TABINFO_CONF, &DbUtil::execGET_TABINFO_CONF);
115 
116   /**
117    *  Prepare / Execute / Release Services
118    */
119   addRecSignal(GSN_UTIL_PREPARE_REQ,  &DbUtil::execUTIL_PREPARE_REQ);
120   addRecSignal(GSN_UTIL_PREPARE_CONF, &DbUtil::execUTIL_PREPARE_CONF);
121   addRecSignal(GSN_UTIL_PREPARE_REF,  &DbUtil::execUTIL_PREPARE_REF);
122 
123   addRecSignal(GSN_UTIL_EXECUTE_REQ,  &DbUtil::execUTIL_EXECUTE_REQ);
124   addRecSignal(GSN_UTIL_EXECUTE_CONF, &DbUtil::execUTIL_EXECUTE_CONF);
125   addRecSignal(GSN_UTIL_EXECUTE_REF,  &DbUtil::execUTIL_EXECUTE_REF);
126 
127   addRecSignal(GSN_UTIL_RELEASE_REQ,  &DbUtil::execUTIL_RELEASE_REQ);
128   addRecSignal(GSN_UTIL_RELEASE_CONF, &DbUtil::execUTIL_RELEASE_CONF);
129   addRecSignal(GSN_UTIL_RELEASE_REF,  &DbUtil::execUTIL_RELEASE_REF);
130 }
131 
~DbUtil()132 DbUtil::~DbUtil()
133 {
134 }
135 
BLOCK_FUNCTIONS(DbUtil)136 BLOCK_FUNCTIONS(DbUtil)
137 
138 void
139 DbUtil::releasePrepare(PreparePtr prepPtr) {
140   prepPtr.p->preparePages.release();
141   c_runningPrepares.release(prepPtr);  // Automatic release in pool
142 }
143 
144 void
releasePreparedOperation(PreparedOperationPtr prepOpPtr)145 DbUtil::releasePreparedOperation(PreparedOperationPtr prepOpPtr) {
146   prepOpPtr.p->attrMapping.release();
147   prepOpPtr.p->attrInfo.release();
148   prepOpPtr.p->rsInfo.release();
149   prepOpPtr.p->pkBitmask.clear();
150   c_preparedOperationPool.release(prepOpPtr);  // No list holding these structs
151 }
152 
153 void
releaseTransaction(TransactionPtr transPtr)154 DbUtil::releaseTransaction(TransactionPtr transPtr){
155   transPtr.p->executePages.release();
156   OperationPtr opPtr;
157   for(transPtr.p->operations.first(opPtr); opPtr.i != RNIL;
158       transPtr.p->operations.next(opPtr)){
159     opPtr.p->attrInfo.release();
160     opPtr.p->keyInfo.release();
161     opPtr.p->rs.release();
162     opPtr.p->transPtrI = RNIL;
163     if (opPtr.p->prepOp != 0 && opPtr.p->prepOp_i != RNIL) {
164       if (opPtr.p->prepOp->releaseFlag) {
165 	PreparedOperationPtr prepOpPtr;
166 	prepOpPtr.i = opPtr.p->prepOp_i;
167 	prepOpPtr.p = opPtr.p->prepOp;
168 	releasePreparedOperation(prepOpPtr);
169       }
170     }
171   }
172   while (transPtr.p->operations.releaseFirst());
173   c_runningTransactions.release(transPtr);
174 }
175 
176 void
execREAD_CONFIG_REQ(Signal * signal)177 DbUtil::execREAD_CONFIG_REQ(Signal* signal)
178 {
179   jamEntry();
180 
181   const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
182 
183   Uint32 ref = req->senderRef;
184   Uint32 senderData = req->senderData;
185 
186   const ndb_mgm_configuration_iterator * p =
187     m_ctx.m_config.getOwnConfigIterator();
188   ndbrequire(p != 0);
189 
190   c_pagePool.setSize(10);
191   c_preparePool.setSize(1);            // one parallel prepare at a time
192   c_preparedOperationPool.setSize(6);  // three hardcoded, one for setval, two for test
193   c_operationPool.setSize(64);         // 64 parallel operations
194   c_transactionPool.setSize(32);       // 16 parallel transactions
195   c_attrMappingPool.setSize(100);
196   c_dataBufPool.setSize(6000);	       // 6000*11*4 = 264K > 8k+8k*16 = 256k
197   {
198     SLList<Prepare> tmp(c_preparePool);
199     PreparePtr ptr;
200     while (tmp.seizeFirst(ptr))
201       new (ptr.p) Prepare(c_pagePool);
202     while (tmp.releaseFirst());
203   }
204   {
205     SLList<Operation> tmp(c_operationPool);
206     OperationPtr ptr;
207     while (tmp.seizeFirst(ptr))
208       new (ptr.p) Operation(c_dataBufPool, c_dataBufPool, c_dataBufPool);
209     while (tmp.releaseFirst());
210   }
211   {
212     SLList<PreparedOperation> tmp(c_preparedOperationPool);
213     PreparedOperationPtr ptr;
214     while (tmp.seizeFirst(ptr))
215       new (ptr.p) PreparedOperation(c_attrMappingPool,
216 				    c_dataBufPool, c_dataBufPool);
217     while (tmp.releaseFirst());
218   }
219   {
220     SLList<Transaction> tmp(c_transactionPool);
221     TransactionPtr ptr;
222     while (tmp.seizeFirst(ptr))
223       new (ptr.p) Transaction(c_pagePool, c_operationPool);
224     while (tmp.releaseFirst());
225   }
226 
227   c_lockQueuePool.setSize(5);
228   c_lockElementPool.setSize(4*MAX_NDB_NODES);
229   c_lockQueues.setSize(8);
230 
231   ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
232   conf->senderRef = reference();
233   conf->senderData = senderData;
234   sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
235 	     ReadConfigConf::SignalLength, JBB);
236 }
237 
238 void
execSTTOR(Signal * signal)239 DbUtil::execSTTOR(Signal* signal)
240 {
241   jamEntry();
242 
243   const Uint32 startphase = signal->theData[1];
244 
245   if(startphase == 1){
246     c_transId[0] = (number() << 20) + (getOwnNodeId() << 8);
247     c_transId[1] = 0;
248   }
249 
250   if(startphase == 6)
251   {
252     jam();
253 
254     /**
255      * 1) get systab_0 table-id
256      * 2) run hardcodedPrepare (for sequences)
257      * 3) connectTc()
258      * 4) STTORRY
259      */
260 
261     /**
262      * We need to find table-id of SYSTAB_0, as it can be after upgrade
263      *   we don't know what it will be...
264      */
265     get_systab_tableid(signal);
266 
267     return;
268   }
269 
270   signal->theData[0] = 0;
271   signal->theData[3] = 1;
272   signal->theData[4] = 6;
273   signal->theData[5] = 255;
274   sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 6, JBB);
275 
276   return;
277 }
278 
279 void
get_systab_tableid(Signal * signal)280 DbUtil::get_systab_tableid(Signal* signal)
281 {
282   static char NAME[] = "sys/def/SYSTAB_0";
283 
284   GetTabInfoReq * req = (GetTabInfoReq *)signal->getDataPtrSend();
285   req->senderRef = reference();
286   req->senderData = RNIL;
287   req->schemaTransId = 0;
288   req->requestType = GetTabInfoReq::RequestByName |
289     GetTabInfoReq::LongSignalConf;
290 
291   req->tableNameLen = sizeof(NAME);
292 
293   /********************************************
294    * Code signal data and send signals to DICT
295    ********************************************/
296 
297   Uint32 buf[(sizeof(NAME)+3)/4];
298   ndbrequire(sizeof(buf) >= sizeof(NAME));
299   memcpy(buf, NAME, sizeof(NAME));
300 
301   LinearSectionPtr ptr[1];
302   ptr[0].p = buf;
303   ptr[0].sz = sizeof(buf) / sizeof(Uint32);
304   sendSignal(DBDICT_REF, GSN_GET_TABINFOREQ, signal,
305              GetTabInfoReq::SignalLength, JBB, ptr,1);
306 }
307 
308 void
execNDB_STTOR(Signal * signal)309 DbUtil::execNDB_STTOR(Signal* signal)
310 {
311   (void)signal;  // Don't want compiler warning
312 
313   jamEntry();
314 }
315 
316 
317 /***************************
318  *  Seize a number of TC records
319  *  to use for Util transactions
320  */
321 
322 void
connectTc(Signal * signal)323 DbUtil::connectTc(Signal* signal){
324 
325   TransactionPtr ptr;
326   while (c_seizingTransactions.seizeFirst(ptr)){
327     signal->theData[0] = ptr.i << 1; // See TcCommitConf
328     signal->theData[1] = reference();
329     sendSignal(DBTC_REF, GSN_TCSEIZEREQ, signal, 2, JBB);
330   }
331 }
332 
333 void
execTCSEIZECONF(Signal * signal)334 DbUtil::execTCSEIZECONF(Signal* signal){
335   jamEntry();
336 
337   TransactionPtr ptr;
338   ptr.i = signal->theData[0] >> 1;
339   c_seizingTransactions.getPtr(ptr, signal->theData[0] >> 1);
340   ptr.p->connectPtr = signal->theData[1];
341   ptr.p->connectRef = signal->theData[2];
342 
343   c_seizingTransactions.release(ptr);
344 
345   if (c_seizingTransactions.isEmpty())
346   {
347     jam();
348     signal->theData[0] = 0;
349     signal->theData[3] = 1;
350     signal->theData[4] = 6;
351     signal->theData[5] = 255;
352     sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 6, JBB);
353   }
354 }
355 
356 
357 /**************************************************************************
358  * ------------------------------------------------------------------------
359  *  MODULE:       Misc
360  * ------------------------------------------------------------------------
361  *
362  *  ContinueB, Dump
363  **************************************************************************/
364 
365 void
execCONTINUEB(Signal * signal)366 DbUtil::execCONTINUEB(Signal* signal){
367   jamEntry();
368   //const Uint32 Tdata0 = signal->theData[0];
369 
370   ndbrequire(0);
371 }
372 
373 void
execNODE_FAILREP(Signal * signal)374 DbUtil::execNODE_FAILREP(Signal* signal){
375   jamEntry();
376   const NodeFailRep * rep = (NodeFailRep*)signal->getDataPtr();
377   NdbNodeBitmask failed;
378   failed.assign(NdbNodeBitmask::Size, rep->theNodes);
379 
380   /* Block level cleanup */
381   for(unsigned i = 1; i < MAX_NDB_NODES; i++) {
382     jam();
383     if(failed.get(i)) {
384       jam();
385       Uint32 elementsCleaned = simBlockNodeFailure(signal, i); // No callback
386       ndbassert(elementsCleaned == 0); // No distributed fragmented signals
387       (void) elementsCleaned; // Remove compiler warning
388     }//if
389   }//for
390 }
391 
392 void
execDUMP_STATE_ORD(Signal * signal)393 DbUtil::execDUMP_STATE_ORD(Signal* signal){
394   jamEntry();
395 
396   /****************************************************************************
397    *  SEQUENCE SERVICE
398    *
399    *  200 : Simple test of Public Sequence Interface
400    *  ----------------------------------------------
401    *  - Sends a SEQUENCE_REQ signal to Util (itself)
402    */
403   const Uint32 tCase = signal->theData[0];
404   if(tCase == 200){
405     jam();
406     ndbout << "--------------------------------------------------" << endl;
407     UtilSequenceReq * req = (UtilSequenceReq*)signal->getDataPtrSend();
408     Uint32 seqId = 1;
409     Uint32 reqTy = UtilSequenceReq::CurrVal;
410 
411     if(signal->length() > 1) seqId = signal->theData[1];
412     if(signal->length() > 2) reqTy = signal->theData[2];
413 
414     req->senderData = 12;
415     req->sequenceId = seqId;
416     req->requestType = reqTy;
417 
418     sendSignal(DBUTIL_REF, GSN_UTIL_SEQUENCE_REQ,
419 	       signal, UtilSequenceReq::SignalLength, JBB);
420   }
421 
422   /****************************************************************************/
423   /* // Obsolete tests, should be rewritten for long signals!!
424   if(tCase == 210){
425     jam();
426     ndbout << "--------------------------------------------------" << endl;
427     const Uint32 pageSizeInWords = 128;
428     Uint32 propPage[pageSizeInWords];
429     LinearWriter w(&propPage[0], 128);
430     w.first();
431     w.add(UtilPrepareReq::NoOfOperations, 1);
432     w.add(UtilPrepareReq::OperationType, UtilPrepareReq::Delete);
433     w.add(UtilPrepareReq::TableName,      "sys/def/SYSTAB_0");
434     w.add(UtilPrepareReq::AttributeName,  "SYSKEY_0"); // AttrNo = 0
435     Uint32 length = w.getWordsUsed();
436     ndbassert(length <= pageSizeInWords);
437 
438     sendUtilPrepareReqSignals(signal, propPage, length);
439   }
440   if(tCase == 211){
441     jam();
442     ndbout << "--------------------------------------------------" << endl;
443     const Uint32 pageSizeInWords = 128;
444     Uint32 propPage[pageSizeInWords];
445     LinearWriter w(&propPage[0],128);
446     w.first();
447     w.add(UtilPrepareReq::NoOfOperations, 1);
448     w.add(UtilPrepareReq::OperationType,  UtilPrepareReq::Insert);
449     w.add(UtilPrepareReq::TableName,      "sys/def/SYSTAB_0");
450     w.add(UtilPrepareReq::AttributeName,  "SYSKEY_0");  // AttrNo = 0
451     w.add(UtilPrepareReq::AttributeName,  "NEXTID");    // AttrNo = 1
452     Uint32 length = w.getWordsUsed();
453     ndbassert(length <= pageSizeInWords);
454 
455     sendUtilPrepareReqSignals(signal, propPage, length);
456   }
457   if(tCase == 212){
458     jam();
459     ndbout << "--------------------------------------------------" << endl;
460     const Uint32 pageSizeInWords = 128;
461     Uint32 propPage[pageSizeInWords];
462     LinearWriter w(&propPage[0],128);
463     w.first();
464     w.add(UtilPrepareReq::NoOfOperations, 1);
465     w.add(UtilPrepareReq::OperationType,  UtilPrepareReq::Update);
466     w.add(UtilPrepareReq::TableName,      "sys/def/SYSTAB_0");
467     w.add(UtilPrepareReq::AttributeName,  "SYSKEY_0");  // AttrNo = 0
468     w.add(UtilPrepareReq::AttributeName,  "NEXTID");    // AttrNo = 1
469     Uint32 length = w.getWordsUsed();
470     ndbassert(length <= pageSizeInWords);
471 
472     sendUtilPrepareReqSignals(signal, propPage, length);
473   }
474   if(tCase == 213){
475     jam();
476     ndbout << "--------------------------------------------------" << endl;
477     const Uint32 pageSizeInWords = 128;
478     Uint32 propPage[pageSizeInWords];
479     LinearWriter w(&propPage[0],128);
480     w.first();
481     w.add(UtilPrepareReq::NoOfOperations, 1);
482     w.add(UtilPrepareReq::OperationType, UtilPrepareReq::Read);
483     w.add(UtilPrepareReq::TableName,      "sys/def/SYSTAB_0");
484     w.add(UtilPrepareReq::AttributeName,  "SYSKEY_0"); // AttrNo = 0
485     Uint32 length = w.getWordsUsed();
486     ndbassert(length <= pageSizeInWords);
487 
488     sendUtilPrepareReqSignals(signal, propPage, length);
489   }
490   if(tCase == 214){
491     jam();
492     ndbout << "--------------------------------------------------" << endl;
493     const Uint32 pageSizeInWords = 128;
494     Uint32 propPage[pageSizeInWords];
495     LinearWriter w(&propPage[0], 128);
496     w.first();
497     w.add(UtilPrepareReq::NoOfOperations, 1);
498     w.add(UtilPrepareReq::OperationType, UtilPrepareReq::Delete);
499     w.add(UtilPrepareReq::TableId, (unsigned int)0);	// SYSTAB_0
500     w.add(UtilPrepareReq::AttributeId, (unsigned int)0);// SYSKEY_0
501     Uint32 length = w.getWordsUsed();
502     ndbassert(length <= pageSizeInWords);
503 
504     sendUtilPrepareReqSignals(signal, propPage, length);
505   }
506   if(tCase == 215){
507     jam();
508     ndbout << "--------------------------------------------------" << endl;
509     const Uint32 pageSizeInWords = 128;
510     Uint32 propPage[pageSizeInWords];
511     LinearWriter w(&propPage[0],128);
512     w.first();
513     w.add(UtilPrepareReq::NoOfOperations, 1);
514     w.add(UtilPrepareReq::OperationType,  UtilPrepareReq::Insert);
515     w.add(UtilPrepareReq::TableId, (unsigned int)0);	 // SYSTAB_0
516     w.add(UtilPrepareReq::AttributeId, (unsigned int)0); // SYSKEY_0
517     w.add(UtilPrepareReq::AttributeId, 1);		 // NEXTID
518     Uint32 length = w.getWordsUsed();
519     ndbassert(length <= pageSizeInWords);
520 
521     sendUtilPrepareReqSignals(signal, propPage, length);
522   }
523   if(tCase == 216){
524     jam();
525     ndbout << "--------------------------------------------------" << endl;
526     const Uint32 pageSizeInWords = 128;
527     Uint32 propPage[pageSizeInWords];
528     LinearWriter w(&propPage[0],128);
529     w.first();
530     w.add(UtilPrepareReq::NoOfOperations, 1);
531     w.add(UtilPrepareReq::OperationType,  UtilPrepareReq::Update);
532     w.add(UtilPrepareReq::TableId, (unsigned int)0);	// SYSTAB_0
533     w.add(UtilPrepareReq::AttributeId, (unsigned int)0);// SYSKEY_0
534     w.add(UtilPrepareReq::AttributeId, 1);		// NEXTID
535     Uint32 length = w.getWordsUsed();
536     ndbassert(length <= pageSizeInWords);
537 
538     sendUtilPrepareReqSignals(signal, propPage, length);
539   }
540   if(tCase == 217){
541     jam();
542     ndbout << "--------------------------------------------------" << endl;
543     const Uint32 pageSizeInWords = 128;
544     Uint32 propPage[pageSizeInWords];
545     LinearWriter w(&propPage[0],128);
546     w.first();
547     w.add(UtilPrepareReq::NoOfOperations, 1);
548     w.add(UtilPrepareReq::OperationType, UtilPrepareReq::Read);
549     w.add(UtilPrepareReq::TableId, (unsigned int)0);	// SYSTAB_0
550     w.add(UtilPrepareReq::AttributeId, (unsigned int)0);// SYSKEY_0
551     Uint32 length = w.getWordsUsed();
552     ndbassert(length <= pageSizeInWords);
553 
554     sendUtilPrepareReqSignals(signal, propPage, length);
555   }
556   */
557   /****************************************************************************/
558   /* // Obsolete tests, should be rewritten for long signals!!
559   if(tCase == 220){
560     jam();
561     ndbout << "--------------------------------------------------" << endl;
562     Uint32 prepI = signal->theData[1];
563     Uint32 length = signal->theData[2];
564     Uint32 attributeValue0 = signal->theData[3];
565     Uint32 attributeValue1a = signal->theData[4];
566     Uint32 attributeValue1b = signal->theData[5];
567     ndbrequire(prepI != 0);
568 
569     UtilExecuteReq * req = (UtilExecuteReq *)signal->getDataPtrSend();
570 
571     req->senderData   = 221;
572     req->prepareId    = prepI;
573     req->totalDataLen = length;  // Including headers
574     req->offset       = 0;
575 
576     AttributeHeader::init(&req->attrData[0], 0, 1);  // AttrNo 0, DataSize
577     req->attrData[1] = attributeValue0;              // AttrValue
578     AttributeHeader::init(&req->attrData[2], 1, 2);  // AttrNo 1, DataSize
579     req->attrData[3] = attributeValue1a;             // AttrValue
580     req->attrData[4] = attributeValue1b;             // AttrValue
581 
582     printUTIL_EXECUTE_REQ(stdout, signal->getDataPtrSend(), 3 + 5,0);
583     sendSignal(DBUTIL_REF, GSN_UTIL_EXECUTE_REQ, signal, 3 + 5, JBB);
584   }
585 */
586   /****************************************************************************
587    *  230 : PRINT STATE
588    */
589 #ifdef ARRAY_GUARD
590   if(tCase == 230){
591     jam();
592 
593     ndbout << "--------------------------------------------------" << endl;
594     if (signal->length() <= 1) {
595       ndbout << "Usage: DUMP 230 <recordType> <recordNo>" << endl
596 	     << "[1] Print Prepare (running) records" << endl
597 	     << "[2] Print PreparedOperation records" << endl
598 	     << "[3] Print Transaction records" << endl
599 	     << "[4] Print Operation records" << endl
600 	     << "Ex. \"dump 230 1 2\" prints Prepare record no 2." << endl
601 	     << endl
602 	     << "210 : PREPARE_REQ DELETE SYSTAB_0 SYSKEY_0" << endl
603 	     << "211 : PREPARE_REQ INSERT SYSTAB_0 SYSKEY_0 NEXTID" << endl
604 	     << "212 : PREPARE_REQ UPDATE SYSTAB_0 SYSKEY_0 NEXTID" << endl
605 	     << "213 : PREPARE_REQ READ   SYSTAB_0 SYSKEY_0" << endl
606 	     << "214 : PREPARE_REQ DELETE SYSTAB_0 SYSKEY_0 using id" << endl
607 	     << "215 : PREPARE_REQ INSERT SYSTAB_0 SYSKEY_0 NEXTID using id" << endl
608 	     << "216 : PREPARE_REQ UPDATE SYSTAB_0 SYSKEY_0 NEXTID using id" << endl
609 	     << "217 : PREPARE_REQ READ   SYSTAB_0 SYSKEY_0 using id" << endl
610 	     << "220 : EXECUTE_REQ <PrepId> <Len> <Val1> <Val2a> <Val2b>" <<endl
611 	     << "299 : Crash system (using ndbrequire(0))"
612 	     << endl
613 	     << "Ex. \"dump 220 3 5 1 0 17 \" prints Prepare record no 2."
614 	     << endl;
615       return;
616     }
617 
618     switch (signal->theData[1]) {
619     case 1:
620     {
621       // ** Print a specific record **
622       if (signal->length() >= 3) {
623 	PreparePtr prepPtr;
624 	if (!c_preparePool.isSeized(signal->theData[2])) {
625 	  ndbout << "Prepare Id: " << signal->theData[2]
626 		 << " (Not seized!)" << endl;
627 	} else {
628 	  c_preparePool.getPtr(prepPtr, signal->theData[2]);
629 	  prepPtr.p->print();
630 	}
631 	return;
632       }
633 
634       // ** Print all records **
635       PreparePtr prepPtr;
636       if (!c_runningPrepares.first(prepPtr)) {
637 	ndbout << "No Prepare records exist" << endl;
638 	return;
639       }
640 
641       while (!prepPtr.isNull()) {
642 	prepPtr.p->print();
643 	c_runningPrepares.next(prepPtr);
644       }
645       return;
646     }
647     case 2:
648       // ** Print a specific record **
649       if (signal->length() >= 3) {
650 	if (!c_preparedOperationPool.isSeized(signal->theData[2])) {
651 	  ndbout << "PreparedOperation Id: " << signal->theData[2]
652 		 << " (Not seized!)" << endl;
653 	  return;
654 	}
655 	ndbout << "PreparedOperation Id: " << signal->theData[2] << endl;
656 	PreparedOperationPtr prepOpPtr;
657 	c_preparedOperationPool.getPtr(prepOpPtr, signal->theData[2]);
658 	prepOpPtr.p->print();
659 	return;
660       }
661 
662       // ** Print all records **
663 #if 0 // not implemented
664       PreparedOperationPtr prepOpPtr;
665       if (!c_runningPreparedOperations.first(prepOpPtr)) {
666 	ndbout << "No PreparedOperations exist" << endl;
667 	return;
668       }
669       while (!prepOpPtr.isNull()) {
670 	ndbout << "[-PreparedOperation no " << prepOpPtr.i << ":";
671 	prepOpPtr.p->print();
672 	ndbout << "]";
673 	c_runningPreparedOperations.next(prepOpPtr);
674       }
675 #endif
676       return;
677 
678     case 3:
679       // ** Print a specific record **
680       if (signal->length() >= 3) {
681 	ndbout << "Print specific record not implemented." << endl;
682 	return;
683       }
684 
685       // ** Print all records **
686       ndbout << "Print all records not implemented, specify an Id." << endl;
687       return;
688 
689     case 4:
690       ndbout << "Not implemented" << endl;
691       return;
692 
693     default:
694       ndbout << "Unknown input (try without any data)" << endl;
695       return;
696     }
697   }
698 #endif
699   if(tCase == 240 && signal->getLength() == 2){
700     MutexManager::ActiveMutexPtr ptr;
701     ndbrequire(c_mutexMgr.seize(ptr));
702     ptr.p->m_mutexId = signal->theData[1];
703     Callback c = { safe_cast(&DbUtil::mutex_created), ptr.i };
704     ptr.p->m_callback = c;
705     c_mutexMgr.create(signal, ptr);
706     ndbout_c("c_mutexMgr.create ptrI=%d mutexId=%d", ptr.i, ptr.p->m_mutexId);
707   }
708 
709   if(tCase == 241 && signal->getLength() == 2){
710     MutexManager::ActiveMutexPtr ptr;
711     ndbrequire(c_mutexMgr.seize(ptr));
712     ptr.p->m_mutexId = signal->theData[1];
713     Callback c = { safe_cast(&DbUtil::mutex_locked), ptr.i };
714     ptr.p->m_callback = c;
715     c_mutexMgr.lock(signal, ptr, true);
716     ndbout_c("c_mutexMgr.lock ptrI=%d mutexId=%d", ptr.i, ptr.p->m_mutexId);
717   }
718 
719   if(tCase == 242 && signal->getLength() == 2){
720     MutexManager::ActiveMutexPtr ptr;
721     ptr.i = signal->theData[1];
722     c_mutexMgr.getPtr(ptr);
723     Callback c = { safe_cast(&DbUtil::mutex_unlocked), ptr.i };
724     ptr.p->m_callback = c;
725     c_mutexMgr.unlock(signal, ptr);
726     ndbout_c("c_mutexMgr.unlock ptrI=%d mutexId=%d", ptr.i, ptr.p->m_mutexId);
727   }
728 
729   if(tCase == 243 && signal->getLength() == 3){
730     MutexManager::ActiveMutexPtr ptr;
731     ndbrequire(c_mutexMgr.seize(ptr));
732     ptr.p->m_mutexId = signal->theData[1];
733     Callback c = { safe_cast(&DbUtil::mutex_destroyed), ptr.i };
734     ptr.p->m_callback = c;
735     c_mutexMgr.destroy(signal, ptr);
736     ndbout_c("c_mutexMgr.destroy ptrI=%d mutexId=%d",
737 	     ptr.i, ptr.p->m_mutexId);
738   }
739 
740   if (tCase == 244)
741   {
742     jam();
743     DLHashTable<LockQueueInstance>::Iterator iter;
744     Uint32 bucket = signal->theData[1];
745     if (signal->getLength() == 1)
746     {
747       bucket = 0;
748       infoEvent("Starting dumping of DbUtil::Locks");
749     }
750     c_lockQueues.next(bucket, iter);
751 
752     for (Uint32 i = 0; i<32 || iter.bucket == bucket; i++)
753     {
754       if (iter.curr.isNull())
755       {
756         infoEvent("Dumping of DbUtil::Locks - done");
757         return;
758       }
759 
760       infoEvent("LockQueue %u", iter.curr.p->m_lockId);
761       iter.curr.p->m_queue.dump_queue(c_lockElementPool, this);
762       c_lockQueues.next(iter);
763     }
764     signal->theData[0] = 244;
765     signal->theData[1] = iter.bucket;
766     sendSignal(reference(),  GSN_DUMP_STATE_ORD, signal, 2, JBB);
767     return;
768   }
769 }
770 
execDBINFO_SCANREQ(Signal * signal)771 void DbUtil::execDBINFO_SCANREQ(Signal *signal)
772 {
773   DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
774   const Ndbinfo::ScanCursor* cursor =
775     CAST_CONSTPTR(Ndbinfo::ScanCursor, DbinfoScan::getCursorPtr(&req));
776   Ndbinfo::Ratelimit rl;
777 
778   jamEntry();
779 
780   switch(req.tableId){
781   case Ndbinfo::POOLS_TABLEID:
782   {
783     Ndbinfo::pool_entry pools[] =
784     {
785       { "Page",
786         c_pagePool.getUsed(),
787         c_pagePool.getSize(),
788         c_pagePool.getEntrySize(),
789         c_pagePool.getUsedHi(),
790         { 0,0,0,0 }},
791       { "Prepare",
792         c_preparePool.getUsed(),
793         c_preparePool.getSize(),
794         c_preparePool.getEntrySize(),
795         c_preparePool.getUsedHi(),
796         { 0,0,0,0 }},
797       { "Prepared Operation",
798         c_preparedOperationPool.getUsed(),
799         c_preparedOperationPool.getSize(),
800         c_preparedOperationPool.getEntrySize(),
801         c_preparedOperationPool.getUsedHi(),
802         { 0,0,0,0 }},
803       { "Operation",
804         c_operationPool.getUsed(),
805         c_operationPool.getSize(),
806         c_operationPool.getEntrySize(),
807         c_operationPool.getUsedHi(),
808         { 0,0,0,0 }},
809       { "Transaction",
810         c_transactionPool.getUsed(),
811         c_transactionPool.getSize(),
812         c_transactionPool.getEntrySize(),
813         c_transactionPool.getUsedHi(),
814         { 0,0,0,0 }},
815       { "Attribute Mapping",
816         c_attrMappingPool.getUsed(),
817         c_attrMappingPool.getSize(),
818         c_attrMappingPool.getEntrySize(),
819         c_attrMappingPool.getUsedHi(),
820         { 0,0,0,0 }},
821       { "Data Buffer",
822         c_dataBufPool.getUsed(),
823         c_dataBufPool.getSize(),
824         c_dataBufPool.getEntrySize(),
825         c_dataBufPool.getUsedHi(),
826         { 0,0,0,0 }},
827       { NULL, 0,0,0,0, { 0,0,0,0 }}
828     };
829 
830     const size_t num_config_params =
831       sizeof(pools[0].config_params) / sizeof(pools[0].config_params[0]);
832     Uint32 pool = cursor->data[0];
833     BlockNumber bn = blockToMain(number());
834     while(pools[pool].poolname)
835     {
836       jam();
837       Ndbinfo::Row row(signal, req);
838       row.write_uint32(getOwnNodeId());
839       row.write_uint32(bn);           // block number
840       row.write_uint32(instance());   // block instance
841       row.write_string(pools[pool].poolname);
842       row.write_uint64(pools[pool].used);
843       row.write_uint64(pools[pool].total);
844       row.write_uint64(pools[pool].used_hi);
845       row.write_uint64(pools[pool].entry_size);
846       for (size_t i = 0; i < num_config_params; i++)
847         row.write_uint32(pools[pool].config_params[i]);
848       ndbinfo_send_row(signal, req, row, rl);
849       pool++;
850       if (rl.need_break(req))
851       {
852         jam();
853         ndbinfo_send_scan_break(signal, req, rl, pool);
854         return;
855       }
856     }
857     break;
858   }
859   default:
860     break;
861   }
862 
863   ndbinfo_send_scan_conf(signal, req, rl);
864 }
865 
866 void
mutex_created(Signal * signal,Uint32 ptrI,Uint32 retVal)867 DbUtil::mutex_created(Signal* signal, Uint32 ptrI, Uint32 retVal){
868   MutexManager::ActiveMutexPtr ptr; ptr.i = ptrI;
869   c_mutexMgr.getPtr(ptr);
870   ndbout_c("mutex_created - mutexId=%d, retVal=%d",
871 	   ptr.p->m_mutexId, retVal);
872   c_mutexMgr.release(ptrI);
873 }
874 
875 void
mutex_destroyed(Signal * signal,Uint32 ptrI,Uint32 retVal)876 DbUtil::mutex_destroyed(Signal* signal, Uint32 ptrI, Uint32 retVal){
877   MutexManager::ActiveMutexPtr ptr; ptr.i = ptrI;
878   c_mutexMgr.getPtr(ptr);
879   ndbout_c("mutex_destroyed - mutexId=%d, retVal=%d",
880 	   ptr.p->m_mutexId, retVal);
881   c_mutexMgr.release(ptrI);
882 }
883 
884 void
mutex_locked(Signal * signal,Uint32 ptrI,Uint32 retVal)885 DbUtil::mutex_locked(Signal* signal, Uint32 ptrI, Uint32 retVal){
886   MutexManager::ActiveMutexPtr ptr; ptr.i = ptrI;
887   c_mutexMgr.getPtr(ptr);
888   ndbout_c("mutex_locked - mutexId=%d, retVal=%d ptrI=%d",
889 	   ptr.p->m_mutexId, retVal, ptrI);
890   if(retVal)
891     c_mutexMgr.release(ptrI);
892 }
893 
894 void
mutex_unlocked(Signal * signal,Uint32 ptrI,Uint32 retVal)895 DbUtil::mutex_unlocked(Signal* signal, Uint32 ptrI, Uint32 retVal){
896   MutexManager::ActiveMutexPtr ptr; ptr.i = ptrI;
897   c_mutexMgr.getPtr(ptr);
898   ndbout_c("mutex_unlocked - mutexId=%d, retVal=%d",
899 	   ptr.p->m_mutexId, retVal);
900   if(!retVal)
901     c_mutexMgr.release(ptrI);
902 }
903 
904 void
execUTIL_SEQUENCE_REF(Signal * signal)905 DbUtil::execUTIL_SEQUENCE_REF(Signal* signal){
906   jamEntry();
907   ndbout << "UTIL_SEQUENCE_REF" << endl;
908   printUTIL_SEQUENCE_REF(stdout, signal->getDataPtrSend(), signal->length(), 0);
909 }
910 
911 void
execUTIL_SEQUENCE_CONF(Signal * signal)912 DbUtil::execUTIL_SEQUENCE_CONF(Signal* signal){
913   jamEntry();
914   ndbout << "UTIL_SEQUENCE_CONF" << endl;
915   printUTIL_SEQUENCE_CONF(stdout, signal->getDataPtrSend(), signal->length(),0);
916 }
917 
918 void
execUTIL_PREPARE_CONF(Signal * signal)919 DbUtil::execUTIL_PREPARE_CONF(Signal* signal){
920   jamEntry();
921   ndbout << "UTIL_PREPARE_CONF" << endl;
922   printUTIL_PREPARE_CONF(stdout, signal->getDataPtrSend(), signal->length(), 0);
923 }
924 
925 void
execUTIL_PREPARE_REF(Signal * signal)926 DbUtil::execUTIL_PREPARE_REF(Signal* signal){
927   jamEntry();
928   ndbout << "UTIL_PREPARE_REF" << endl;
929   printUTIL_PREPARE_REF(stdout, signal->getDataPtrSend(), signal->length(), 0);
930 }
931 
932 void
execUTIL_EXECUTE_CONF(Signal * signal)933 DbUtil::execUTIL_EXECUTE_CONF(Signal* signal) {
934   jamEntry();
935   ndbout << "UTIL_EXECUTE_CONF" << endl;
936   printUTIL_EXECUTE_CONF(stdout, signal->getDataPtrSend(), signal->length(), 0);
937 }
938 
939 void
execUTIL_EXECUTE_REF(Signal * signal)940 DbUtil::execUTIL_EXECUTE_REF(Signal* signal) {
941   jamEntry();
942 
943   ndbout << "UTIL_EXECUTE_REF" << endl;
944   printUTIL_EXECUTE_REF(stdout, signal->getDataPtrSend(), signal->length(), 0);
945 }
946 
947 void
execUTIL_RELEASE_CONF(Signal * signal)948 DbUtil::execUTIL_RELEASE_CONF(Signal* signal) {
949   jamEntry();
950   ndbout << "UTIL_RELEASE_CONF" << endl;
951 }
952 
953 void
execUTIL_RELEASE_REF(Signal * signal)954 DbUtil::execUTIL_RELEASE_REF(Signal* signal) {
955   jamEntry();
956 
957   ndbout << "UTIL_RELEASE_REF" << endl;
958 }
959 
960 void
sendUtilPrepareRef(Signal * signal,UtilPrepareRef::ErrorCode error,Uint32 recipient,Uint32 senderData,Uint32 errCode2)961 DbUtil::sendUtilPrepareRef(Signal* signal, UtilPrepareRef::ErrorCode error,
962 			   Uint32 recipient, Uint32 senderData,
963                            Uint32 errCode2){
964   UtilPrepareRef * ref = (UtilPrepareRef *)signal->getDataPtrSend();
965   ref->errorCode = error;
966   ref->senderData = senderData;
967   ref->dictErrCode = errCode2;
968 
969   sendSignal(recipient, GSN_UTIL_PREPARE_REF, signal,
970 	     UtilPrepareRef::SignalLength, JBB);
971 }
972 
973 void
sendUtilExecuteRef(Signal * signal,UtilExecuteRef::ErrorCode error,Uint32 TCerror,Uint32 recipient,Uint32 senderData)974 DbUtil::sendUtilExecuteRef(Signal* signal, UtilExecuteRef::ErrorCode error,
975 			   Uint32 TCerror, Uint32 recipient, Uint32 senderData){
976 
977   UtilExecuteRef * ref = (UtilExecuteRef *)signal->getDataPtrSend();
978   ref->senderData  = senderData;
979   ref->errorCode   = error;
980   ref->TCErrorCode = TCerror;
981 
982   sendSignal(recipient, GSN_UTIL_EXECUTE_REF, signal,
983 	     UtilPrepareRef::SignalLength, JBB);
984 }
985 
986 
987 /**************************************************************************
988  * ------------------------------------------------------------------------
989  *  MODULE:       Prepare service
990  * ------------------------------------------------------------------------
991  *
992  *  Prepares a transaction by storing info in some structs
993  **************************************************************************/
994 
995 void
execUTIL_PREPARE_REQ(Signal * signal)996 DbUtil::execUTIL_PREPARE_REQ(Signal* signal)
997 {
998   jamEntry();
999 
1000   /****************
1001    * Decode Signal
1002    ****************/
1003   UtilPrepareReq * req = (UtilPrepareReq *)signal->getDataPtr();
1004   const Uint32 senderRef    = req->senderRef;
1005   const Uint32 senderData   = req->senderData;
1006   const Uint32 schemaTransId= req->schemaTransId;
1007 
1008   if(signal->getNoOfSections() == 0) {
1009     // Missing prepare data
1010     jam();
1011     sendUtilPrepareRef(signal, UtilPrepareRef::MISSING_PROPERTIES_SECTION,
1012 		       senderRef, senderData);
1013     return;
1014   }
1015 
1016   PreparePtr prepPtr;
1017   SegmentedSectionPtr ptr;
1018   SectionHandle handle(this, signal);
1019 
1020   jam();
1021   if (!c_runningPrepares.seizeFirst(prepPtr)) {
1022     jam();
1023     releaseSections(handle);
1024     sendUtilPrepareRef(signal, UtilPrepareRef::PREPARE_SEIZE_ERROR,
1025 		       senderRef, senderData);
1026     return;
1027   };
1028   handle.getSection(ptr, UtilPrepareReq::PROPERTIES_SECTION);
1029   const Uint32 noPages  = (ptr.sz + sizeof(Page32)) / sizeof(Page32);
1030   ndbassert(noPages > 0);
1031   if (!prepPtr.p->preparePages.seize(noPages)) {
1032     jam();
1033     releaseSections(handle);
1034     sendUtilPrepareRef(signal, UtilPrepareRef::PREPARE_PAGES_SEIZE_ERROR,
1035 		       senderRef, senderData);
1036     c_preparePool.release(prepPtr);
1037     return;
1038   }
1039   // Save SimpleProperties
1040   Uint32* target = &prepPtr.p->preparePages.getPtr(0)->data[0];
1041   copy(target, ptr);
1042   prepPtr.p->prepDataLen = ptr.sz;
1043   // Release long signal sections
1044   releaseSections(handle);
1045   // Check table properties with DICT
1046   SimplePropertiesSectionReader reader(ptr, getSectionSegmentPool());
1047   prepPtr.p->clientRef = senderRef;
1048   prepPtr.p->clientData = senderData;
1049   prepPtr.p->schemaTransId = schemaTransId;
1050   // Release long signal sections
1051   readPrepareProps(signal, &reader, prepPtr);
1052 }
1053 
readPrepareProps(Signal * signal,SimpleProperties::Reader * reader,PreparePtr prepPtr)1054 void DbUtil::readPrepareProps(Signal* signal,
1055 			      SimpleProperties::Reader* reader,
1056 			      PreparePtr prepPtr)
1057 {
1058   jam();
1059 #if 0
1060   printf("DbUtil::readPrepareProps: Received SimpleProperties:\n");
1061   reader->printAll(ndbout);
1062 #endif
1063   ndbrequire(reader->first());
1064   ndbrequire(reader->getKey() == UtilPrepareReq::NoOfOperations);
1065   ndbrequire(reader->getUint32() == 1);      // Only one op/trans implemented
1066 
1067   ndbrequire(reader->next());
1068   ndbrequire(reader->getKey() == UtilPrepareReq::OperationType);
1069 
1070   ndbrequire(reader->next());
1071   UtilPrepareReq::KeyValue tableKey =
1072     (UtilPrepareReq::KeyValue) reader->getKey();
1073   if (tableKey == UtilPrepareReq::ScanTakeOverInd)
1074   {
1075     reader->next();
1076     tableKey = (UtilPrepareReq::KeyValue) reader->getKey();
1077   }
1078   if (tableKey == UtilPrepareReq::ReorgInd)
1079   {
1080     reader->next();
1081     tableKey = (UtilPrepareReq::KeyValue) reader->getKey();
1082   }
1083 
1084   ndbrequire((tableKey == UtilPrepareReq::TableName) ||
1085 	     (tableKey == UtilPrepareReq::TableId));
1086 
1087   /************************
1088    * Ask Dict for metadata
1089    ************************/
1090   {
1091     GetTabInfoReq * req = (GetTabInfoReq *)signal->getDataPtrSend();
1092     req->senderRef = reference();
1093     req->senderData = prepPtr.i;
1094     req->schemaTransId = prepPtr.p->schemaTransId;
1095     if (tableKey == UtilPrepareReq::TableName) {
1096       jam();
1097       char tableName[MAX_TAB_NAME_SIZE];
1098       req->requestType = GetTabInfoReq::RequestByName |
1099 	GetTabInfoReq::LongSignalConf;
1100 
1101       req->tableNameLen = reader->getValueLen();    // Including trailing \0
1102 
1103       /********************************************
1104        * Code signal data and send signals to DICT
1105        ********************************************/
1106 
1107       ndbrequire(req->tableNameLen < MAX_TAB_NAME_SIZE);
1108       reader->getString((char*)tableName);
1109       LinearSectionPtr ptr[1];
1110       ptr[0].p = (Uint32*)tableName;
1111       ptr[0].sz = req->tableNameLen;
1112       sendSignal(DBDICT_REF, GSN_GET_TABINFOREQ, signal,
1113 		 GetTabInfoReq::SignalLength, JBB, ptr,1);
1114 
1115     }
1116     else { // (tableKey == UtilPrepareReq::TableId)
1117       jam();
1118       req->requestType = GetTabInfoReq::RequestById |
1119 	GetTabInfoReq::LongSignalConf;
1120       req->tableId = reader->getUint32();
1121       sendSignal(DBDICT_REF, GSN_GET_TABINFOREQ, signal,
1122 		 GetTabInfoReq::SignalLength, JBB);
1123     }
1124 
1125   }
1126 }
1127 
1128 /**
1129  *  @note  We assume that this signal comes due to a request related
1130  *         to a Prepare struct.  DictTabInfo:s 'senderData' denotes
1131  *         the Prepare struct related to the request.
1132  */
1133 void
execGET_TABINFO_CONF(Signal * signal)1134 DbUtil::execGET_TABINFO_CONF(Signal* signal){
1135   jamEntry();
1136 
1137   if(!assembleFragments(signal)){
1138     jam();
1139     return;
1140   }
1141 
1142   /****************
1143    * Decode signal
1144    ****************/
1145   GetTabInfoConf * const conf = (GetTabInfoConf*)signal->getDataPtr();
1146   const Uint32  prepI    = conf->senderData;
1147   const Uint32  totalLen = conf->totalLen;
1148 
1149   SectionHandle handle(this, signal);
1150   SegmentedSectionPtr dictTabInfoPtr;
1151   handle.getSection(dictTabInfoPtr, GetTabInfoConf::DICT_TAB_INFO);
1152   ndbrequire(dictTabInfoPtr.sz == totalLen);
1153 
1154   if (prepI != RNIL)
1155   {
1156     jam();
1157     PreparePtr prepPtr;
1158     c_runningPrepares.getPtr(prepPtr, prepI);
1159     prepareOperation(signal, prepPtr, dictTabInfoPtr);
1160     releaseSections(handle);
1161     return;
1162   }
1163   else
1164   {
1165     jam();
1166     // get_systab_tableid
1167     releaseSections(handle);
1168     hardcodedPrepare(signal, conf->tableId);
1169     return;
1170   }
1171 }
1172 
1173 void
execGET_TABINFOREF(Signal * signal)1174 DbUtil::execGET_TABINFOREF(Signal* signal){
1175   jamEntry();
1176 
1177   GetTabInfoRef * ref = (GetTabInfoRef *)signal->getDataPtr();
1178   Uint32 prepI = ref->senderData;
1179 #define EVENT_DEBUG
1180 #if 0 //def EVENT_DEBUG
1181   ndbout << "Signal GET_TABINFOREF received." << endl;
1182   ndbout << "Error Code: " << ref->errorCode << endl;
1183 
1184   switch (ref->errorCode) {
1185   case GetTabInfoRef::InvalidTableId:
1186     ndbout << "      Msg:  Invalid table id" << endl;
1187     break;
1188   case GetTabInfoRef::TableNotDefined:
1189     ndbout << "      Msg:  Table not defined" << endl;
1190     break;
1191   case GetTabInfoRef::TableNameToLong:
1192     ndbout << "      Msg:  Table node too long" << endl;
1193     break;
1194   default:
1195     ndbout << "      Msg:  Unknown error returned from Dict" << endl;
1196     break;
1197   }
1198 #endif
1199 
1200   PreparePtr prepPtr;
1201   c_runningPrepares.getPtr(prepPtr, prepI);
1202 
1203   sendUtilPrepareRef(signal, UtilPrepareRef::DICT_TAB_INFO_ERROR,
1204 		     prepPtr.p->clientRef, prepPtr.p->clientData,
1205                      ref->errorCode);
1206 
1207   releasePrepare(prepPtr);
1208 }
1209 
1210 
1211 /******************************************************************************
1212  * Prepare Operation
1213  *
1214  * Using a prepare record, prepare an operation (i.e. create PreparedOperation).
1215  * Info from both Pepare request (PreparePages) and DictTabInfo is used.
1216  *
1217  * Algorithm:
1218  * -# Seize AttrbuteMapping
1219  *    - Lookup in preparePages how many attributes should be prepared
1220  *    - Seize AttributeMapping
1221  * -# For each attributes in preparePages
1222  *    - Lookup id and isPK in dictInfoPages
1223  *    - Store "no -> (AttributeId, Position)" in AttributeMapping
1224  * -# For each map in AttributeMapping
1225  *    - if (isPK) then assign offset
1226  ******************************************************************************/
1227 void
prepareOperation(Signal * signal,PreparePtr prepPtr,SegmentedSectionPtr ptr)1228 DbUtil::prepareOperation(Signal* signal,
1229 			 PreparePtr prepPtr,
1230 			 SegmentedSectionPtr ptr)
1231 {
1232   jam();
1233 
1234   /*******************************************
1235    * Seize and store PreparedOperation struct
1236    *******************************************/
1237   PreparedOperationPtr prepOpPtr;
1238   if(!c_preparedOperationPool.seize(prepOpPtr)) {
1239     jam();
1240     sendUtilPrepareRef(signal, UtilPrepareRef::PREPARED_OPERATION_SEIZE_ERROR,
1241 		       prepPtr.p->clientRef, prepPtr.p->clientData);
1242     releasePrepare(prepPtr);
1243     return;
1244   }
1245   prepPtr.p->prepOpPtr = prepOpPtr;
1246 
1247   /********************
1248    * Read request info
1249    ********************/
1250   SimplePropertiesLinearReader prepPagesReader(&prepPtr.p->preparePages.getPtr(0)->data[0],
1251 					       prepPtr.p->prepDataLen);
1252 
1253   ndbrequire(prepPagesReader.first());
1254   ndbrequire(prepPagesReader.getKey() == UtilPrepareReq::NoOfOperations);
1255   const Uint32 noOfOperations = prepPagesReader.getUint32();
1256   ndbrequire(noOfOperations == 1);
1257 
1258   ndbrequire(prepPagesReader.next());
1259   ndbrequire(prepPagesReader.getKey() == UtilPrepareReq::OperationType);
1260   const Uint32 operationType = prepPagesReader.getUint32();
1261   prepOpPtr.p->operationType =(UtilPrepareReq::OperationTypeValue)operationType;
1262 
1263   ndbrequire(prepPagesReader.next());
1264 
1265   char tableName[MAX_TAB_NAME_SIZE];
1266   Uint32 tableId;
1267   UtilPrepareReq::KeyValue tableKey =
1268     (UtilPrepareReq::KeyValue) prepPagesReader.getKey();
1269 
1270   bool scanTakeOver = false;
1271   bool reorg = false;
1272   if (tableKey == UtilPrepareReq::ScanTakeOverInd)
1273   {
1274     scanTakeOver = true;
1275     prepPagesReader.next();
1276     tableKey = (UtilPrepareReq::KeyValue) prepPagesReader.getKey();
1277   }
1278 
1279   if (tableKey == UtilPrepareReq::ReorgInd)
1280   {
1281     reorg = true;
1282     prepPagesReader.next();
1283     tableKey = (UtilPrepareReq::KeyValue) prepPagesReader.getKey();
1284   }
1285 
1286   if (tableKey == UtilPrepareReq::TableId) {
1287     jam();
1288     tableId = prepPagesReader.getUint32();
1289   }
1290   else {
1291     jam();
1292     ndbrequire(prepPagesReader.getKey() == UtilPrepareReq::TableName);
1293     ndbrequire(prepPagesReader.getValueLen() <= MAX_TAB_NAME_SIZE);
1294     prepPagesReader.getString(tableName);
1295   }
1296   /******************************************************************
1297    * Seize AttributeMapping (by counting no of attribs in prepPages)
1298    ******************************************************************/
1299   Uint32 noOfAttributes = 0;   // No of attributes in PreparePages (used later)
1300   while(prepPagesReader.next()) {
1301     if (tableKey == UtilPrepareReq::TableName) {
1302       jam();
1303       ndbrequire(prepPagesReader.getKey() == UtilPrepareReq::AttributeName);
1304     } else {
1305       jam();
1306       ndbrequire(prepPagesReader.getKey() == UtilPrepareReq::AttributeId);
1307     }
1308     noOfAttributes++;
1309   }
1310   ndbrequire(prepPtr.p->prepOpPtr.p->attrMapping.seize(noOfAttributes));
1311   if (operationType == UtilPrepareReq::Read) {
1312     ndbrequire(prepPtr.p->prepOpPtr.p->rsInfo.seize(noOfAttributes));
1313   }
1314   /***************************************
1315    * For each attribute name, lookup info
1316    ***************************************/
1317   // Goto start of attribute names
1318   ndbrequire(prepPagesReader.first() && prepPagesReader.next() &&
1319 	     prepPagesReader.next());
1320 
1321   if (scanTakeOver)
1322     prepPagesReader.next();
1323 
1324   if (reorg)
1325     prepPagesReader.next();
1326 
1327   DictTabInfo::Table tableDesc; tableDesc.init();
1328   AttrMappingBuffer::DataBufferIterator attrMappingIt;
1329   ndbrequire(prepPtr.p->prepOpPtr.p->attrMapping.first(attrMappingIt));
1330 
1331   ResultSetBuffer::DataBufferIterator rsInfoIt;
1332   if (operationType == UtilPrepareReq::Read) {
1333     ndbrequire(prepPtr.p->prepOpPtr.p->rsInfo.first(rsInfoIt));
1334   }
1335 
1336   Uint32 noOfPKAttribsStored = 0;
1337   Uint32 noOfNonPKAttribsStored = 0;
1338   Uint32 attrLength = 0;
1339   char attrNameRequested[MAX_ATTR_NAME_SIZE];
1340   Uint32 attrIdRequested;
1341 
1342   while(prepPagesReader.next()) {
1343     UtilPrepareReq::KeyValue attributeKey =
1344       (UtilPrepareReq::KeyValue) prepPagesReader.getKey();
1345 
1346     ndbrequire((attributeKey == UtilPrepareReq::AttributeName) ||
1347 	       (attributeKey == UtilPrepareReq::AttributeId));
1348     if (attributeKey == UtilPrepareReq::AttributeName) {
1349       jam();
1350       ndbrequire(prepPagesReader.getValueLen() <= MAX_ATTR_NAME_SIZE);
1351 
1352       prepPagesReader.getString(attrNameRequested);
1353       attrIdRequested= ~0u;
1354     } else {
1355       jam();
1356       attrIdRequested = prepPagesReader.getUint32();
1357     }
1358     /*****************************************
1359      * Copy DictTabInfo into tableDesc struct
1360      *****************************************/
1361 
1362     SimplePropertiesSectionReader dictInfoReader(ptr, getSectionSegmentPool());
1363     SimpleProperties::UnpackStatus unpackStatus;
1364     unpackStatus = SimpleProperties::unpack(dictInfoReader, &tableDesc,
1365 					    DictTabInfo::TableMapping,
1366 					    DictTabInfo::TableMappingSize,
1367 					    true, true);
1368     ndbrequire(unpackStatus == SimpleProperties::Break);
1369 
1370     /************************
1371      * Lookup in DictTabInfo
1372      ************************/
1373     DictTabInfo::Attribute attrDesc; attrDesc.init();
1374     char attrName[MAX_ATTR_NAME_SIZE];
1375     Uint32 attrId= ~(Uint32)0;
1376     bool attributeFound = false;
1377     Uint32 noOfKeysFound = 0;     // # PK attrs found before attr in DICTdata
1378     Uint32 noOfNonKeysFound = 0;  // # nonPK attrs found before attr in DICTdata
1379     for (Uint32 i=0; i<tableDesc.NoOfAttributes; i++) {
1380       if (tableKey == UtilPrepareReq::TableName) {
1381 	jam();
1382 	ndbrequire(dictInfoReader.getKey() == DictTabInfo::AttributeName);
1383 	ndbrequire(dictInfoReader.getValueLen() <= MAX_ATTR_NAME_SIZE);
1384 	dictInfoReader.getString(attrName);
1385 	attrId= ~(Uint32)0; // attrId not used
1386       } else { // (tableKey == UtilPrepareReq::TableId)
1387 	jam();
1388 	dictInfoReader.next(); // Skip name
1389 	ndbrequire(dictInfoReader.getKey() == DictTabInfo::AttributeId);
1390 	attrId = dictInfoReader.getUint32();
1391 	attrName[0]= '\0'; // attrName not used
1392       }
1393       unpackStatus = SimpleProperties::unpack(dictInfoReader, &attrDesc,
1394 					      DictTabInfo::AttributeMapping,
1395 					      DictTabInfo::AttributeMappingSize,
1396 					      true, true);
1397       ndbrequire(unpackStatus == SimpleProperties::Break);
1398       //attrDesc.print(stdout);
1399 
1400       if (attrDesc.AttributeKeyFlag) { jam(); noOfKeysFound++; }
1401       else                           { jam(); noOfNonKeysFound++; }
1402       if (attributeKey == UtilPrepareReq::AttributeName) {
1403 	if (strcmp(attrName, attrNameRequested) == 0) {
1404 	  attributeFound = true;
1405 	  break;
1406 	}
1407       }
1408       else // (attributeKey == UtilPrepareReq::AttributeId)
1409 	if (attrId == attrIdRequested) {
1410 	  attributeFound = true;
1411 	  break;
1412 	}
1413 
1414       // Move to next attribute
1415       ndbassert(dictInfoReader.getKey() == DictTabInfo::AttributeEnd);
1416       dictInfoReader.next();
1417     }
1418 
1419     /**********************
1420      * Attribute not found
1421      **********************/
1422     if (!attributeFound) {
1423       jam();
1424       sendUtilPrepareRef(signal,
1425 			 UtilPrepareRef::DICT_TAB_INFO_ERROR,
1426 			 prepPtr.p->clientRef, prepPtr.p->clientData);
1427       infoEvent("UTIL: Unknown attribute requested: %s in table: %s",
1428 		attrNameRequested, tableName);
1429       releasePreparedOperation(prepOpPtr);
1430       releasePrepare(prepPtr);
1431       return;
1432     }
1433 
1434     /**************************************************************
1435      * Attribute found - store in mapping  (AttributeId, Position)
1436      **************************************************************/
1437     AttributeHeader attrMap(attrDesc.AttributeId,    // 1. Store AttrId
1438 			    0);
1439 
1440     if (attrDesc.AttributeKeyFlag) {
1441       // ** Attribute belongs to PK **
1442       prepOpPtr.p->pkBitmask.set(attrDesc.AttributeId);
1443       attrMap.setDataSize(noOfKeysFound - 1);        // 2. Store Position
1444       noOfPKAttribsStored++;
1445     } else {
1446       attrMap.setDataSize(0x3fff);                   // 2. Store Position (fake)
1447       noOfNonPKAttribsStored++;
1448 
1449       /***********************************************************
1450        * Error: Read nonPK Attr before all PK attr have been read
1451        ***********************************************************/
1452       if (noOfPKAttribsStored != tableDesc.NoOfKeyAttr) {
1453 	jam();
1454 	sendUtilPrepareRef(signal,
1455 			   UtilPrepareRef::DICT_TAB_INFO_ERROR,
1456 			   prepPtr.p->clientRef, prepPtr.p->clientData);
1457 	infoEvent("UTIL: Non-PK attr not allowed before "
1458 		  "all PK attrs have been defined, table: %s",
1459 		  tableName);
1460 	releasePreparedOperation(prepOpPtr);
1461 	releasePrepare(prepPtr);
1462 	return;
1463       }
1464     }
1465     *(attrMappingIt.data) = attrMap.m_value;
1466 #if 0
1467     ndbout << "BEFORE: attrLength: " << attrLength << endl;
1468 #endif
1469     {
1470       int len = 0;
1471       switch (attrDesc.AttributeSize) {
1472       case DictTabInfo::an8Bit:
1473 	len = (attrDesc.AttributeArraySize + 3)/ 4;
1474 	break;
1475       case DictTabInfo::a16Bit:
1476 	len = (attrDesc.AttributeArraySize + 1) / 2;
1477 	break;
1478       case DictTabInfo::a32Bit:
1479 	len = attrDesc.AttributeArraySize;
1480 	break;
1481       case DictTabInfo::a64Bit:
1482 	len = attrDesc.AttributeArraySize * 2;
1483       break;
1484       case DictTabInfo::a128Bit:
1485 	len = attrDesc.AttributeArraySize * 4;
1486 	break;
1487       }
1488       attrLength += len;
1489 
1490       if (operationType == UtilPrepareReq::Read) {
1491 	AttributeHeader::init(rsInfoIt.data,
1492 			      attrDesc.AttributeId,    // 1. Store AttrId
1493 			      len << 2);
1494 	prepOpPtr.p->rsInfo.next(rsInfoIt, 1);
1495       }
1496     }
1497 #if 0
1498     ndbout << ": AttributeSize: " << attrDesc.AttributeSize << endl;
1499     ndbout << ": AttributeArraySize: " << attrDesc.AttributeArraySize << endl;
1500     ndbout << "AFTER: attrLength: " << attrLength << endl;
1501 #endif
1502     //attrMappingIt.print(stdout);
1503     //prepPtr.p->prepOpPtr.p->attrMapping.print(stdout);
1504     prepPtr.p->prepOpPtr.p->attrMapping.next(attrMappingIt, 1);
1505   }
1506 
1507   /***************************
1508    * Error: Not all PKs found
1509    ***************************/
1510   if (noOfPKAttribsStored != tableDesc.NoOfKeyAttr) {
1511     jam();
1512     sendUtilPrepareRef(signal,
1513 		       UtilPrepareRef::DICT_TAB_INFO_ERROR,
1514 		       prepPtr.p->clientRef, prepPtr.p->clientData);
1515     infoEvent("UTIL: Not all primary key attributes requested for table: %s",
1516 	      tableName);
1517     releasePreparedOperation(prepOpPtr);
1518     releasePrepare(prepPtr);
1519     return;
1520   }
1521 
1522 #if 0
1523   AttrMappingBuffer::ConstDataBufferIterator tmpIt;
1524   for (prepPtr.p->prepOpPtr.p->attrMapping.first(tmpIt); tmpIt.curr.i != RNIL;
1525        prepPtr.p->prepOpPtr.p->attrMapping.next(tmpIt)) {
1526     AttributeHeader* ah = (AttributeHeader *) tmpIt.data;
1527     ah->print(stdout);
1528   }
1529 #endif
1530 
1531   /**********************************************
1532    * Preparing of PreparedOperation signal train
1533    **********************************************/
1534   Uint32 static_len = TcKeyReq::StaticLength;
1535   Uint32 requestInfo = 0;
1536   if (scanTakeOver)
1537   {
1538     static_len ++;
1539     TcKeyReq::setScanIndFlag(requestInfo, 1);
1540   }
1541   if (reorg)
1542   {
1543     TcKeyReq::setReorgFlag(requestInfo, 1);
1544   }
1545   prepOpPtr.p->tckey.tableId = tableDesc.TableId;
1546   prepOpPtr.p->tckey.tableSchemaVersion = tableDesc.TableVersion;
1547   prepOpPtr.p->noOfKeyAttr = tableDesc.NoOfKeyAttr;
1548   prepOpPtr.p->tckeyLen = static_len;
1549   prepOpPtr.p->keyDataPos = static_len;  // Start of keyInfo[] in tckeyreq
1550 
1551   TcKeyReq::setAbortOption(requestInfo, TcKeyReq::AbortOnError);
1552   TcKeyReq::setKeyLength(requestInfo, tableDesc.KeyLength);
1553   switch((UtilPrepareReq::OperationTypeValue)operationType) {
1554   case(UtilPrepareReq::Read):
1555     prepOpPtr.p->rsLen =
1556       attrLength +
1557       tableDesc.NoOfKeyAttr +
1558       noOfNonPKAttribsStored;          // Read needs a resultset
1559     prepOpPtr.p->noOfAttr = tableDesc.NoOfKeyAttr + noOfNonPKAttribsStored;
1560     prepOpPtr.p->tckey.attrLen = prepOpPtr.p->noOfAttr;
1561     TcKeyReq::setOperationType(requestInfo, ZREAD);
1562     break;
1563   case(UtilPrepareReq::Update):
1564     prepOpPtr.p->rsLen = 0;
1565     prepOpPtr.p->noOfAttr = tableDesc.NoOfKeyAttr + noOfNonPKAttribsStored;
1566     prepOpPtr.p->tckey.attrLen = attrLength + prepOpPtr.p->noOfAttr;
1567     TcKeyReq::setOperationType(requestInfo, ZUPDATE);
1568     break;
1569   case(UtilPrepareReq::Insert):
1570     prepOpPtr.p->rsLen = 0;
1571     prepOpPtr.p->noOfAttr = tableDesc.NoOfKeyAttr + noOfNonPKAttribsStored;
1572     prepOpPtr.p->tckey.attrLen = attrLength + prepOpPtr.p->noOfAttr;
1573     TcKeyReq::setOperationType(requestInfo, ZINSERT);
1574     break;
1575   case(UtilPrepareReq::Delete):
1576     // The number of attributes should equal the size of the primary key
1577     ndbrequire(tableDesc.KeyLength == attrLength);
1578     prepOpPtr.p->rsLen = 0;
1579     prepOpPtr.p->noOfAttr = tableDesc.NoOfKeyAttr;
1580     prepOpPtr.p->tckey.attrLen = 0;
1581     TcKeyReq::setOperationType(requestInfo, ZDELETE);
1582     break;
1583   case(UtilPrepareReq::Probe):
1584     // The number of attributes should equal the size of the primary key
1585     ndbrequire(tableDesc.KeyLength == attrLength);
1586     prepOpPtr.p->rsLen = 0;
1587     prepOpPtr.p->noOfAttr = tableDesc.NoOfKeyAttr;
1588     prepOpPtr.p->tckey.attrLen = 0;
1589     TcKeyReq::setOperationType(requestInfo, ZREAD);
1590     break;
1591   case(UtilPrepareReq::Write):
1592     prepOpPtr.p->rsLen = 0;
1593     prepOpPtr.p->noOfAttr = tableDesc.NoOfKeyAttr + noOfNonPKAttribsStored;
1594     prepOpPtr.p->tckey.attrLen = attrLength + prepOpPtr.p->noOfAttr;
1595     TcKeyReq::setOperationType(requestInfo, ZWRITE);
1596     break;
1597   }
1598   TcKeyReq::setAIInTcKeyReq(requestInfo, 0);  // Attrinfo sent separately
1599   prepOpPtr.p->tckey.requestInfo = requestInfo;
1600 
1601   /****************************
1602    * Confirm completed prepare
1603    ****************************/
1604   UtilPrepareConf * conf = (UtilPrepareConf *)signal->getDataPtr();
1605   conf->senderData = prepPtr.p->clientData;
1606   conf->prepareId = prepPtr.p->prepOpPtr.i;
1607 
1608   sendSignal(prepPtr.p->clientRef, GSN_UTIL_PREPARE_CONF, signal,
1609 	     UtilPrepareConf::SignalLength, JBB);
1610 
1611 #if 0
1612   prepPtr.p->prepOpPtr.p->print();
1613 #endif
1614   releasePrepare(prepPtr);
1615 }
1616 
1617 
1618 void
execUTIL_RELEASE_REQ(Signal * signal)1619 DbUtil::execUTIL_RELEASE_REQ(Signal* signal){
1620   jamEntry();
1621 
1622   UtilReleaseReq * req = (UtilReleaseReq *)signal->getDataPtr();
1623   const Uint32 clientRef      = signal->senderBlockRef();
1624   const Uint32 prepareId      = req->prepareId;
1625   const Uint32 senderData     = req->senderData;
1626 
1627 #if 0
1628   /**
1629    * This only works in when ARRAY_GUARD is defined (debug-mode)
1630    */
1631   if (!c_preparedOperationPool.isSeized(prepareId)) {
1632     UtilReleaseRef * ref = (UtilReleaseRef *)signal->getDataPtr();
1633     ref->prepareId = prepareId;
1634     ref->errorCode = UtilReleaseRef::NO_SUCH_PREPARE_SEIZED;
1635     sendSignal(clientRef, GSN_UTIL_RELEASE_REF, signal,
1636 	       UtilReleaseRef::SignalLength, JBB);
1637   }
1638 #endif
1639   PreparedOperationPtr prepOpPtr;
1640   c_preparedOperationPool.getPtr(prepOpPtr, prepareId);
1641 
1642   releasePreparedOperation(prepOpPtr);
1643 
1644   UtilReleaseConf * const conf = (UtilReleaseConf*)signal->getDataPtrSend();
1645   conf->senderData = senderData;
1646   sendSignal(clientRef, GSN_UTIL_RELEASE_CONF, signal,
1647 	     UtilReleaseConf::SignalLength, JBB);
1648 }
1649 
1650 
1651 /**************************************************************************
1652  * ------------------------------------------------------------------------
1653  *  MODULE:       Sequence Service
1654  * ------------------------------------------------------------------------
1655  *
1656  *  A service with a stored incrementable number
1657  **************************************************************************/
1658 void
hardcodedPrepare(Signal * signal,Uint32 SYSTAB_0)1659 DbUtil::hardcodedPrepare(Signal* signal, Uint32 SYSTAB_0)
1660 {
1661   /**
1662    * Prepare SequenceCurrVal (READ)
1663    */
1664   Uint32 keyLen = 1;
1665   {
1666     PreparedOperationPtr ptr;
1667     ndbrequire(c_preparedOperationPool.seizeId(ptr, 0));
1668     ptr.p->tckey.attrLen = 1;
1669     ptr.p->rsLen = 3;
1670     ptr.p->tckeyLen = TcKeyReq::StaticLength + keyLen + ptr.p->tckey.attrLen;
1671     ptr.p->keyDataPos = TcKeyReq::StaticLength;
1672     ptr.p->tckey.tableId = SYSTAB_0;
1673     Uint32 requestInfo = 0;
1674     TcKeyReq::setAbortOption(requestInfo, TcKeyReq::CommitIfFailFree);
1675     TcKeyReq::setOperationType(requestInfo, ZREAD);
1676     TcKeyReq::setKeyLength(requestInfo, 1);
1677     TcKeyReq::setAIInTcKeyReq(requestInfo, 1);
1678     ptr.p->tckey.requestInfo = requestInfo;
1679     ptr.p->tckey.tableSchemaVersion = 1;
1680 
1681     // This is actually attr data
1682     AttributeHeader::init(&ptr.p->tckey.distrGroupHashValue, 1, 0);
1683 
1684     ndbrequire(ptr.p->rsInfo.seize(1));
1685     ResultSetInfoBuffer::DataBufferIterator it;
1686     ptr.p->rsInfo.first(it);
1687     AttributeHeader::init(it.data, 1, 2 << 2); // Attribute 1 - 2 data words
1688   }
1689 
1690   /**
1691    * Prepare SequenceNextVal (UPDATE)
1692    */
1693   {
1694     PreparedOperationPtr ptr;
1695     ndbrequire(c_preparedOperationPool.seizeId(ptr, 1));
1696     ptr.p->rsLen = 3;
1697     ptr.p->tckeyLen = TcKeyReq::StaticLength + keyLen + 5;
1698     ptr.p->keyDataPos = TcKeyReq::StaticLength;
1699     ptr.p->tckey.attrLen = 11;
1700     ptr.p->tckey.tableId = SYSTAB_0;
1701     Uint32 requestInfo = 0;
1702     TcKeyReq::setAbortOption(requestInfo, TcKeyReq::CommitIfFailFree);
1703     TcKeyReq::setOperationType(requestInfo, ZUPDATE);
1704     TcKeyReq::setKeyLength(requestInfo, 1);
1705     TcKeyReq::setAIInTcKeyReq(requestInfo, 5);
1706     TcKeyReq::setInterpretedFlag(requestInfo, 1);
1707     ptr.p->tckey.requestInfo = requestInfo;
1708     ptr.p->tckey.tableSchemaVersion = 1;
1709 
1710     // Signal is packed, which is why attrInfo is at distrGroupHashValue
1711     // position
1712     Uint32 * attrInfo = &ptr.p->tckey.distrGroupHashValue;
1713     attrInfo[0] = 0; // IntialReadSize
1714     attrInfo[1] = 5; // InterpretedSize
1715     attrInfo[2] = 0; // FinalUpdateSize
1716     attrInfo[3] = 1; // FinalReadSize
1717     attrInfo[4] = 0; // SubroutineSize
1718 
1719     { // AttrInfo
1720       ndbrequire(ptr.p->attrInfo.seize(6));
1721       AttrInfoBuffer::DataBufferIterator it;
1722       ptr.p->attrInfo.first(it);
1723       * it.data = Interpreter::Read(1, 6);
1724       ndbrequire(ptr.p->attrInfo.next(it));
1725       * it.data = Interpreter::LoadConst16(7, 1);
1726       ndbrequire(ptr.p->attrInfo.next(it));
1727       * it.data = Interpreter::Add(7, 6, 7);
1728       ndbrequire(ptr.p->attrInfo.next(it));
1729       * it.data = Interpreter::Write(1, 7);
1730       ndbrequire(ptr.p->attrInfo.next(it));
1731       * it.data = Interpreter::ExitOK();
1732 
1733       ndbrequire(ptr.p->attrInfo.next(it));
1734       AttributeHeader::init(it.data, 1, 0);
1735     }
1736 
1737     { // ResultSet
1738       ndbrequire(ptr.p->rsInfo.seize(1));
1739       ResultSetInfoBuffer::DataBufferIterator it;
1740       ptr.p->rsInfo.first(it);
1741       AttributeHeader::init(it.data, 1, 2 << 2); // Attribute 1 - 2 data words
1742     }
1743   }
1744 
1745   /**
1746    * Prepare CreateSequence (INSERT)
1747    */
1748   {
1749     PreparedOperationPtr ptr;
1750     ndbrequire(c_preparedOperationPool.seizeId(ptr, 2));
1751     ptr.p->tckey.attrLen = 5;
1752     ptr.p->rsLen = 0;
1753     ptr.p->tckeyLen = TcKeyReq::StaticLength + keyLen + ptr.p->tckey.attrLen;
1754     ptr.p->keyDataPos = TcKeyReq::StaticLength;
1755     ptr.p->tckey.tableId = SYSTAB_0;
1756     Uint32 requestInfo = 0;
1757     TcKeyReq::setAbortOption(requestInfo, TcKeyReq::CommitIfFailFree);
1758     TcKeyReq::setOperationType(requestInfo, ZINSERT);
1759     TcKeyReq::setKeyLength(requestInfo, 1);
1760     TcKeyReq::setAIInTcKeyReq(requestInfo, 0);
1761     ptr.p->tckey.requestInfo = requestInfo;
1762     ptr.p->tckey.tableSchemaVersion = 1;
1763   }
1764 
1765   /**
1766    * Prepare SetSequence (UPDATE)
1767    */
1768   {
1769     PreparedOperationPtr ptr;
1770     ndbrequire(c_preparedOperationPool.seizeId(ptr, 3));
1771     ptr.p->rsLen = 0;
1772     ptr.p->tckeyLen = TcKeyReq::StaticLength + keyLen + 5;
1773     ptr.p->keyDataPos = TcKeyReq::StaticLength;
1774     ptr.p->tckey.attrLen = 9;
1775     ptr.p->tckey.tableId = SYSTAB_0;
1776     Uint32 requestInfo = 0;
1777     TcKeyReq::setAbortOption(requestInfo, TcKeyReq::CommitIfFailFree);
1778     TcKeyReq::setOperationType(requestInfo, ZUPDATE);
1779     TcKeyReq::setKeyLength(requestInfo, 1);
1780     TcKeyReq::setAIInTcKeyReq(requestInfo, 5);
1781     TcKeyReq::setInterpretedFlag(requestInfo, 1);
1782     ptr.p->tckey.requestInfo = requestInfo;
1783     ptr.p->tckey.tableSchemaVersion = 1;
1784 
1785     Uint32 * attrInfo = &ptr.p->tckey.distrGroupHashValue;
1786     attrInfo[0] = 0; // IntialReadSize
1787     attrInfo[1] = 4; // InterpretedSize
1788     attrInfo[2] = 0; // FinalUpdateSize
1789     attrInfo[3] = 0; // FinalReadSize
1790     attrInfo[4] = 0; // SubroutineSize
1791   }
1792 
1793   connectTc(signal);
1794 }
1795 
1796 void
execUTIL_SEQUENCE_REQ(Signal * signal)1797 DbUtil::execUTIL_SEQUENCE_REQ(Signal* signal){
1798   jamEntry();
1799 
1800   UtilSequenceReq * req = (UtilSequenceReq*)signal->getDataPtr();
1801 
1802   PreparedOperation * prepOp;
1803 
1804   switch(req->requestType){
1805   case UtilSequenceReq::CurrVal:
1806     prepOp = c_preparedOperationPool.getPtr(0); //c_SequenceCurrVal
1807     break;
1808   case UtilSequenceReq::NextVal:
1809     prepOp = c_preparedOperationPool.getPtr(1); //c_SequenceNextVal
1810     break;
1811   case UtilSequenceReq::Create:
1812     prepOp = c_preparedOperationPool.getPtr(2); //c_CreateSequence
1813     break;
1814   case UtilSequenceReq::SetVal:{
1815     prepOp = c_preparedOperationPool.getPtr(3);
1816     break;
1817   }
1818   default:
1819     ndbrequire(false);
1820     prepOp = 0; // remove warning
1821   }
1822 
1823   /**
1824    * 1 Transaction with 1 operation
1825    */
1826   TransactionPtr transPtr;
1827   ndbrequire(c_runningTransactions.seizeFirst(transPtr));
1828 
1829   OperationPtr opPtr;
1830   ndbrequire(transPtr.p->operations.seizeFirst(opPtr));
1831   ndbrequire(opPtr.p->transPtrI == RNIL);
1832   ndbrequire(opPtr.p->keyInfo.seize(1));
1833 
1834   transPtr.p->gci_hi = 0;
1835   transPtr.p->gci_lo = 0;
1836   transPtr.p->gsn = GSN_UTIL_SEQUENCE_REQ;
1837   transPtr.p->clientRef = signal->senderBlockRef();
1838   transPtr.p->clientData = req->senderData;
1839   transPtr.p->sequence.sequenceId = req->sequenceId;
1840   transPtr.p->sequence.requestType = req->requestType;
1841 
1842   opPtr.p->prepOp   = prepOp;
1843   opPtr.p->prepOp_i = RNIL;
1844 
1845   KeyInfoBuffer::DataBufferIterator it;
1846   opPtr.p->keyInfo.first(it);
1847   it.data[0] = transPtr.p->sequence.sequenceId;
1848 
1849   if(req->requestType == UtilSequenceReq::Create){
1850     ndbrequire(opPtr.p->attrInfo.seize(5));
1851     AttrInfoBuffer::DataBufferIterator it;
1852 
1853     opPtr.p->attrInfo.first(it);
1854     AttributeHeader::init(it.data, 0, 1 << 2);
1855 
1856     ndbrequire(opPtr.p->attrInfo.next(it));
1857     * it.data = transPtr.p->sequence.sequenceId;
1858 
1859     ndbrequire(opPtr.p->attrInfo.next(it));
1860     AttributeHeader::init(it.data, 1, 2 << 2);
1861 
1862     ndbrequire(opPtr.p->attrInfo.next(it));
1863     * it.data = 0;
1864 
1865     ndbrequire(opPtr.p->attrInfo.next(it));
1866     * it.data = 0;
1867   }
1868 
1869   if(req->requestType == UtilSequenceReq::SetVal)
1870   { // AttrInfo
1871     ndbrequire(opPtr.p->attrInfo.seize(4));
1872     AttrInfoBuffer::DataBufferIterator it;
1873     opPtr.p->attrInfo.first(it);
1874     * it.data = Interpreter::LoadConst32(7);
1875     ndbrequire(opPtr.p->attrInfo.next(it));
1876     * it.data = req->value;
1877     ndbrequire(opPtr.p->attrInfo.next(it));
1878     * it.data = Interpreter::Write(1, 7);
1879     ndbrequire(opPtr.p->attrInfo.next(it))
1880     * it.data = Interpreter::ExitOK();
1881   }
1882 
1883   transPtr.p->noOfRetries = 3;
1884   runTransaction(signal, transPtr);
1885 }
1886 
1887 int
getResultSet(Signal * signal,const Transaction * transP,struct LinearSectionPtr sectionsPtr[])1888 DbUtil::getResultSet(Signal* signal, const Transaction * transP,
1889 		     struct LinearSectionPtr sectionsPtr[]) {
1890   OperationPtr opPtr;
1891   ndbrequire(transP->operations.first(opPtr));
1892   ndbrequire(transP->operations.hasNext(opPtr) == false);
1893 
1894   int noAttr = 0;
1895   int dataSz = 0;
1896   Uint32* tmpBuf = signal->theData + 25;
1897   const Uint32* headerBuffer = tmpBuf;
1898 
1899   const ResultSetBuffer & rs = opPtr.p->rs;
1900   ResultSetInfoBuffer::ConstDataBufferIterator it;
1901 
1902   // extract headers
1903   for(rs.first(it); it.curr.i != RNIL; ) {
1904     *tmpBuf++ = it.data[0];
1905     rs.next(it, AttributeHeader::getDataSize(it.data[0]) + 1);
1906     noAttr++;
1907   }
1908 
1909   if (noAttr == 0)
1910     return 0;
1911 
1912   const Uint32* dataBuffer = tmpBuf;
1913 
1914   // extract data
1915   for(rs.first(it); it.curr.i != RNIL; )
1916   {
1917     jam();
1918     int sz = AttributeHeader::getDataSize(it.data[0]);
1919     rs.next(it,1);
1920     for (int i = 0; i < sz; i++)
1921     {
1922       *tmpBuf++ = *it.data;
1923       rs.next(it,1);
1924       dataSz++;
1925     }
1926   }
1927 
1928   sectionsPtr[UtilExecuteReq::HEADER_SECTION].p = (Uint32 *)headerBuffer;
1929   sectionsPtr[UtilExecuteReq::HEADER_SECTION].sz = noAttr;
1930   sectionsPtr[UtilExecuteReq::DATA_SECTION].p = (Uint32 *)dataBuffer;
1931   sectionsPtr[UtilExecuteReq::DATA_SECTION].sz = dataSz;
1932 
1933   return 1;
1934 }
1935 
1936 void
reportSequence(Signal * signal,const Transaction * transP)1937 DbUtil::reportSequence(Signal* signal, const Transaction * transP){
1938   OperationPtr opPtr;
1939   ndbrequire(transP->operations.first(opPtr));
1940   ndbrequire(transP->operations.hasNext(opPtr) == false);
1941 
1942   if(transP->errorCode == 0){
1943     jam(); // OK
1944 
1945     UtilSequenceConf * ret = (UtilSequenceConf *)signal->getDataPtrSend();
1946     ret->senderData = transP->clientData;
1947     ret->sequenceId = transP->sequence.sequenceId;
1948     ret->requestType = transP->sequence.requestType;
1949 
1950     bool ok = false;
1951     switch(transP->sequence.requestType){
1952     case UtilSequenceReq::CurrVal:
1953     case UtilSequenceReq::NextVal:{
1954       ok = true;
1955       ndbrequire(opPtr.p->rsRecv == 3);
1956 
1957       ResultSetBuffer::DataBufferIterator rsit;
1958       ndbrequire(opPtr.p->rs.first(rsit));
1959 
1960       ret->sequenceValue[0] = rsit.data[1];
1961       ret->sequenceValue[1] = rsit.data[2];
1962       break;
1963     }
1964     case UtilSequenceReq::SetVal:
1965       ok = true;
1966     case UtilSequenceReq::Create:
1967       ok = true;
1968       ret->sequenceValue[0] = 0;
1969       ret->sequenceValue[1] = 0;
1970       break;
1971     }
1972     ndbrequire(ok);
1973     sendSignal(transP->clientRef, GSN_UTIL_SEQUENCE_CONF, signal,
1974 	       UtilSequenceConf::SignalLength, JBB);
1975     return;
1976   }
1977 
1978   UtilSequenceRef::ErrorCode errCode = UtilSequenceRef::TCError;
1979 
1980   switch(transP->sequence.requestType)
1981     {
1982     case UtilSequenceReq::SetVal:
1983     case UtilSequenceReq::CurrVal:
1984     case UtilSequenceReq::NextVal:{
1985       if (transP->errorCode == 626)
1986 	errCode = UtilSequenceRef::NoSuchSequence;
1987       break;
1988     }
1989     case UtilSequenceReq::Create:
1990       break;
1991     }
1992 
1993   UtilSequenceRef * ret = (UtilSequenceRef *)signal->getDataPtrSend();
1994   ret->senderData = transP->clientData;
1995   ret->sequenceId = transP->sequence.sequenceId;
1996   ret->requestType = transP->sequence.requestType;
1997   ret->errorCode = (Uint32)errCode;
1998   ret->TCErrorCode = transP->errorCode;
1999   sendSignal(transP->clientRef, GSN_UTIL_SEQUENCE_REF, signal,
2000 	     UtilSequenceRef::SignalLength, JBB);
2001 }
2002 #if 0
2003   Ndb ndb("ndb","def");
2004   NdbConnection* tConnection = ndb.startTransaction();
2005   NdbOperation* tOperation = tConnection->getNdbOperation("SYSTAB_0");
2006 
2007   //#if 0 && API_CODE
2008   if( tOperation != NULL ) {
2009     tOperation->interpretedUpdateTuple();
2010     tOperation->equal((U_Int32)0, keyValue );
2011     tNextId_Result = tOperation->getValue((U_Int32)1);
2012     tOperation->incValue((U_Int32)1, (U_Int32)8192);
2013 
2014     if (tConnection->execute( Commit ) != -1 ) {
2015       U_Int64 tValue = tNextId_Result->u_64_value();   // Read result value
2016       theFirstTransId = tValue;
2017       theLastTransId  = tValue + 8191;
2018       closeTransaction(tConnection);
2019       return startTransactionLocal(aPriority, nodeId);
2020     }
2021   }
2022   /**
2023    * IntialReadSize = 0;
2024    * InterpretedSize = incValue(1);
2025    * FinalUpdateSize = 0;
2026    * FinalReadSize = 1; // Read value
2027    * SubroutineSize = 0;
2028    */
2029 #endif
2030 
2031 
2032 /**************************************************************************
2033  * ------------------------------------------------------------------------
2034  *  MODULE:       Transaction execution request
2035  * ------------------------------------------------------------------------
2036  *
2037  *  Handle requests to execute a prepared transaction
2038  **************************************************************************/
2039 
2040 void
execUTIL_EXECUTE_REQ(Signal * signal)2041 DbUtil::execUTIL_EXECUTE_REQ(Signal* signal)
2042 {
2043   jamEntry();
2044 
2045   UtilExecuteReq * req = (UtilExecuteReq *)signal->getDataPtr();
2046   const Uint32  clientRef      = req->senderRef;
2047   const Uint32  clientData     = req->senderData;
2048   const Uint32  prepareId      = req->getPrepareId();
2049   const bool    releaseFlag    = req->getReleaseFlag();
2050   const Uint32  scanTakeOver   = req->scanTakeOver;
2051 
2052   if(signal->getNoOfSections() == 0) {
2053     // Missing prepare data
2054     jam();
2055     sendUtilExecuteRef(signal, UtilExecuteRef::MissingDataSection,
2056 		       0, clientRef, clientData);
2057     return;
2058   }
2059   /*******************************
2060    * Get PreparedOperation struct
2061    *******************************/
2062   PreparedOperationPtr prepOpPtr;
2063   c_preparedOperationPool.getPtr(prepOpPtr, prepareId);
2064 
2065   prepOpPtr.p->releaseFlag = releaseFlag;
2066 
2067   TransactionPtr  transPtr;
2068   OperationPtr    opPtr;
2069   SectionHandle handle(this, signal);
2070   SegmentedSectionPtr headerPtr, dataPtr;
2071 
2072   handle.getSection(headerPtr, UtilExecuteReq::HEADER_SECTION);
2073   SectionReader headerReader(headerPtr, getSectionSegmentPool());
2074   handle.getSection(dataPtr, UtilExecuteReq::DATA_SECTION);
2075   SectionReader dataReader(dataPtr, getSectionSegmentPool());
2076 
2077 #if 0 //def EVENT_DEBUG
2078   // Debugging
2079   printf("DbUtil::execUTIL_EXECUTEL_REQ: Headers (%u): ", headerPtr.sz);
2080   Uint32 word;
2081   while(headerReader.getWord(&word))
2082     printf("H'%.8x ", word);
2083   printf("\n");
2084   printf("DbUtil::execUTIL_EXECUTEL_REQ: Data (%u): ", dataPtr.sz);
2085   headerReader.reset();
2086   while(dataReader.getWord(&word))
2087     printf("H'%.8x ", word);
2088   printf("\n");
2089   dataReader.reset();
2090 #endif
2091 
2092 //  Uint32 totalDataLen = headerPtr.sz + dataPtr.sz;
2093 
2094   /************************************************************
2095    * Seize Transaction record
2096    ************************************************************/
2097   ndbrequire(c_runningTransactions.seizeFirst(transPtr));
2098   transPtr.p->gci_hi = 0;
2099   transPtr.p->gci_lo = 0;
2100   transPtr.p->gsn        = GSN_UTIL_EXECUTE_REQ;
2101   transPtr.p->clientRef  = clientRef;
2102   transPtr.p->clientData = clientData;
2103   ndbrequire(transPtr.p->operations.seizeFirst(opPtr));
2104   ndbrequire(opPtr.p->transPtrI == RNIL);
2105   opPtr.p->prepOp   = prepOpPtr.p;
2106   opPtr.p->prepOp_i = prepOpPtr.i;
2107   opPtr.p->m_scanTakeOver = scanTakeOver;
2108 
2109  /***********************************************************
2110    * Store signal data on linear memory in Transaction record
2111    ***********************************************************/
2112   KeyInfoBuffer* keyInfo = &opPtr.p->keyInfo;
2113   AttrInfoBuffer* attrInfo = &opPtr.p->attrInfo;
2114   AttributeHeader header;
2115   Uint32* tempBuf = signal->theData + 25;
2116   bool dataComplete = true;
2117 
2118   while(headerReader.getWord((Uint32 *)&header)) {
2119     Uint32* bufStart = tempBuf;
2120     header.insertHeader(tempBuf++);
2121     for(unsigned int i = 0; i < header.getDataSize(); i++) {
2122       if (!dataReader.getWord(tempBuf++)) {
2123 	dataComplete = false;
2124 	break;
2125       }
2126     }
2127     bool res = true;
2128 
2129 #if 0 //def EVENT_DEBUG
2130     if (TcKeyReq::getOperationType(prepOpPtr.p->tckey.requestInfo) ==
2131 	TcKeyReq::Read) {
2132       if(prepOpPtr.p->pkBitmask.get(header.getAttributeId()))
2133 	printf("PrimaryKey\n");
2134     }
2135     printf("AttrId %u Hdrsz %d Datasz %u \n",
2136 	   header.getAttributeId(),
2137 	   header.getHeaderSize(),
2138 	   header.getDataSize());
2139 #endif
2140 
2141     if(prepOpPtr.p->pkBitmask.get(header.getAttributeId()))
2142       // A primary key attribute
2143       res = keyInfo->append(bufStart + header.getHeaderSize(),
2144 			    header.getDataSize());
2145 
2146     switch (prepOpPtr.p->operationType) {
2147     case UtilPrepareReq::Read:
2148       res &= attrInfo->append(bufStart, header.getHeaderSize());
2149       break;
2150     case UtilPrepareReq::Delete:
2151     case UtilPrepareReq::Probe:
2152       // no attrinfo for Delete
2153       break;
2154     case UtilPrepareReq::Insert:
2155     case UtilPrepareReq::Update:
2156     case UtilPrepareReq::Write:
2157       res &= attrInfo->append(bufStart,
2158 			      header.getHeaderSize() + header.getDataSize());
2159     }
2160 
2161     if (!res) {
2162       // Failed to allocate buffer data
2163       jam();
2164       releaseSections(handle);
2165       sendUtilExecuteRef(signal, UtilExecuteRef::AllocationError,
2166 			 0, clientRef, clientData);
2167       releaseTransaction(transPtr);
2168       return;
2169     }
2170   }
2171   if (!dataComplete) {
2172     // Missing data in data section
2173     jam();
2174     releaseSections(handle);
2175     sendUtilExecuteRef(signal, UtilExecuteRef::MissingData,
2176 		       0, clientRef, clientData);
2177     releaseTransaction(transPtr);
2178     return;
2179   }
2180 
2181 #if 0
2182   const Uint32 l1 = prepOpPtr.p->tckey.attrLen;
2183   const Uint32 l2 =
2184     prepOpPtr.p->attrInfo.getSize() + opPtr.p->attrInfo.getSize();
2185 
2186   if (TcKeyReq::getOperationType(prepOpPtr.p->tckey.requestInfo) != ZREAD){
2187     ndbrequire(l1 == l2);
2188   } else {
2189     ndbout_c("TcKeyReq::Read");
2190   }
2191 #endif
2192 
2193   releaseSections(handle);
2194   transPtr.p->noOfRetries = 3;
2195   runTransaction(signal, transPtr);
2196 }
2197 
2198 /**************************************************************************
2199  * ------------------------------------------------------------------------
2200  *  MODULE:       General transaction machinery
2201  * ------------------------------------------------------------------------
2202  *   Executes a prepared transaction
2203  **************************************************************************/
2204 void
runTransaction(Signal * signal,TransactionPtr transPtr)2205 DbUtil::runTransaction(Signal* signal, TransactionPtr transPtr){
2206 
2207   /* Init transaction */
2208   transPtr.p->sent = 0;
2209   transPtr.p->recv = 0;
2210   transPtr.p->errorCode = 0;
2211   getTransId(transPtr.p);
2212 
2213   OperationPtr opPtr;
2214   ndbrequire(transPtr.p->operations.first(opPtr));
2215 
2216   /* First operation */
2217   Uint32 start = 0;
2218   TcKeyReq::setStartFlag(start, 1);
2219   runOperation(signal, transPtr, opPtr, start);
2220   transPtr.p->sent ++;
2221 
2222   /* Rest of operations */
2223   start = 0;
2224   while(opPtr.i != RNIL){
2225     runOperation(signal, transPtr, opPtr, start);
2226     transPtr.p->sent ++;
2227   }
2228   //transPtr.p->print();
2229 }
2230 
2231 void
runOperation(Signal * signal,TransactionPtr & transPtr,OperationPtr & opPtr,Uint32 start)2232 DbUtil::runOperation(Signal* signal, TransactionPtr & transPtr,
2233 		     OperationPtr & opPtr, Uint32 start) {
2234   Uint32 opI = opPtr.i;
2235   Operation * op = opPtr.p;
2236   const PreparedOperation * pop = op->prepOp;
2237 
2238   if(!transPtr.p->operations.next(opPtr)){
2239     TcKeyReq::setCommitFlag(start, 1);   // Last operation
2240     TcKeyReq::setExecuteFlag(start, 1);
2241   }
2242 
2243 #if 0 //def EVENT_DEBUG
2244   if (TcKeyReq::getOperationType(pop->tckey.requestInfo) ==
2245       TcKeyReq::Read) {
2246     printf("TcKeyReq::Read runOperation\n");
2247   }
2248 #endif
2249 
2250   /**
2251    * Init operation w.r.t result set
2252    */
2253   op->rsRecv = 0;
2254 #if 0 //def EVENT_DEBUG
2255   printf("pop->rsLen %u\n", pop->rsLen);
2256 #endif
2257   op->rsExpect = 0;
2258   op->transPtrI = transPtr.i;
2259 
2260   TcKeyReq * tcKey = (TcKeyReq*)signal->getDataPtrSend();
2261   //ndbout << "*** 6 ***"<< endl; pop->print();
2262   memcpy(tcKey, &pop->tckey, 4*pop->tckeyLen);
2263   //ndbout << "*** 6b ***"<< endl;
2264   //printTCKEYREQ(stdout, signal->getDataPtrSend(),
2265   //              pop->tckeyLenInBytes >> 2, 0);
2266   tcKey->apiConnectPtr = transPtr.p->connectPtr;
2267   tcKey->senderData = opI;
2268   tcKey->transId1 = transPtr.p->transId[0];
2269   tcKey->transId2 = transPtr.p->transId[1];
2270   tcKey->requestInfo |= start;
2271 
2272   if (TcKeyReq::getScanIndFlag(tcKey->requestInfo))
2273   {
2274     tcKey->scanInfo = op->m_scanTakeOver;
2275   }
2276 
2277 #if 0 //def EVENT_DEBUG
2278   // Debugging
2279   printf("DbUtil::runOperation: KEYINFO\n");
2280   op->keyInfo.print(stdout);
2281   printf("DbUtil::runOperation: ATTRINFO\n");
2282   op->attrInfo.print(stdout);
2283 #endif
2284 
2285   Uint32 attrLen = pop->attrInfo.getSize() + op->attrInfo.getSize();
2286   Uint32 keyLen = op->keyInfo.getSize();
2287   tcKey->attrLen = attrLen + TcKeyReq::getAIInTcKeyReq(tcKey->requestInfo);
2288   TcKeyReq::setKeyLength(tcKey->requestInfo, keyLen);
2289 
2290   /**
2291    * Key Info
2292    */
2293   //KeyInfoBuffer::DataBufferIterator kit;
2294   KeyInfoIterator kit;
2295   op->keyInfo.first(kit);
2296   Uint32 *keyDst = ((Uint32*)tcKey) + pop->keyDataPos;
2297   for(Uint32 i = 0; i<8 && kit.curr.i != RNIL; i++, op->keyInfo.next(kit)){
2298     keyDst[i] = * kit.data;
2299   }
2300   //ndbout << "*** 7 ***" << endl;
2301   //printTCKEYREQ(stdout, signal->getDataPtrSend(),
2302   //		pop->tckeyLenInBytes >> 2, 0);
2303 
2304 #if 0 //def EVENT_DEBUG
2305   printf("DbUtil::runOperation: sendSignal(DBTC_REF, GSN_TCKEYREQ, signal, %d , JBB)\n",  pop->tckeyLenInBytes >> 2);
2306   printTCKEYREQ(stdout, signal->getDataPtr(), pop->tckeyLenInBytes >> 2,0);
2307 #endif
2308   Uint32 sigLen = pop->tckeyLen + (keyLen > 8 ? 8 : keyLen);
2309   sendSignal(transPtr.p->connectRef, GSN_TCKEYREQ, signal, sigLen, JBB);
2310 
2311   /**
2312    * More the 8 words of key info not implemented
2313    */
2314   // ndbrequire(kit.curr.i == RNIL); // Yes it is
2315 
2316   /**
2317    * KeyInfo
2318    */
2319   KeyInfo* keyInfo = (KeyInfo *)signal->getDataPtrSend();
2320   keyInfo->connectPtr = transPtr.p->connectPtr;
2321   keyInfo->transId[0] = transPtr.p->transId[0];
2322   keyInfo->transId[1] = transPtr.p->transId[1];
2323   sendKeyInfo(signal, transPtr.p->connectRef,
2324               keyInfo, op->keyInfo, kit);
2325 
2326   /**
2327    * AttrInfo
2328    */
2329   AttrInfo* attrInfo = (AttrInfo *)signal->getDataPtrSend();
2330   attrInfo->connectPtr = transPtr.p->connectPtr;
2331   attrInfo->transId[0] = transPtr.p->transId[0];
2332   attrInfo->transId[1] = transPtr.p->transId[1];
2333 
2334   AttrInfoIterator ait;
2335   pop->attrInfo.first(ait);
2336   sendAttrInfo(signal, transPtr.p->connectRef,
2337                attrInfo, pop->attrInfo, ait);
2338 
2339   op->attrInfo.first(ait);
2340   sendAttrInfo(signal, transPtr.p->connectRef,
2341                attrInfo, op->attrInfo, ait);
2342 }
2343 
2344 void
sendKeyInfo(Signal * signal,Uint32 tcRef,KeyInfo * keyInfo,const KeyInfoBuffer & keyBuf,KeyInfoIterator & kit)2345 DbUtil::sendKeyInfo(Signal* signal,
2346                     Uint32 tcRef,
2347 		    KeyInfo* keyInfo,
2348 		    const KeyInfoBuffer & keyBuf,
2349 		    KeyInfoIterator & kit)
2350 {
2351   while(kit.curr.i != RNIL) {
2352     Uint32 *keyDst = keyInfo->keyData;
2353     Uint32 keyDataLen = 0;
2354     for(Uint32 i = 0; i<KeyInfo::DataLength && kit.curr.i != RNIL;
2355 	i++, keyBuf.next(kit)){
2356       keyDst[i] = * kit.data;
2357       keyDataLen++;
2358     }
2359 #if 0 //def EVENT_DEBUG
2360     printf("DbUtil::sendKeyInfo: sendSignal(DBTC_REF, GSN_KEYINFO, signal, %d , JBB)\n", KeyInfo::HeaderLength + keyDataLen);
2361 #endif
2362     sendSignal(tcRef, GSN_KEYINFO, signal,
2363 	       KeyInfo::HeaderLength + keyDataLen, JBB);
2364   }
2365 }
2366 
2367 void
sendAttrInfo(Signal * signal,Uint32 tcRef,AttrInfo * attrInfo,const AttrInfoBuffer & attrBuf,AttrInfoIterator & ait)2368 DbUtil::sendAttrInfo(Signal* signal,
2369                      Uint32 tcRef,
2370 		     AttrInfo* attrInfo,
2371 		     const AttrInfoBuffer & attrBuf,
2372 		     AttrInfoIterator & ait)
2373 {
2374   while(ait.curr.i != RNIL) {
2375     Uint32 *attrDst = attrInfo->attrData;
2376     Uint32 i = 0;
2377     for(i = 0; i<AttrInfo::DataLength && ait.curr.i != RNIL;
2378 	i++, attrBuf.next(ait)){
2379       attrDst[i] = * ait.data;
2380     }
2381 #if 0 //def EVENT_DEBUG
2382     printf("DbUtil::sendAttrInfo: sendSignal(DBTC_REF, GSN_ATTRINFO, signal, %d , JBB)\n", AttrInfo::HeaderLength + i);
2383 #endif
2384     sendSignal(tcRef, GSN_ATTRINFO, signal,
2385 	       AttrInfo::HeaderLength + i, JBB);
2386   }
2387 }
2388 
2389 void
getTransId(Transaction * transP)2390 DbUtil::getTransId(Transaction * transP){
2391 
2392   Uint32 tmp[2];
2393   tmp[0] = c_transId[0];
2394   tmp[1] = c_transId[1];
2395 
2396   transP->transId[0] = tmp[0];
2397   transP->transId[1] = tmp[1];
2398 
2399   c_transId[1] = tmp[1] + 1;
2400 }
2401 
2402 
2403 
2404 /**************************************************************************
2405  * ------------------------------------------------------------------------
2406  *  MODULE:       Post Execute
2407  * ------------------------------------------------------------------------
2408  *
2409  *  Handles result from a sent transaction
2410  **************************************************************************/
2411 
2412 /**
2413  * execTRANSID_AI
2414  *
2415  * Receive result from transaction
2416  *
2417  * NOTE: This codes assumes that
2418  *       TransidAI::DataLength = ResultSetBuffer::getSegmentSize() * n
2419  */
2420 void
execTRANSID_AI(Signal * signal)2421 DbUtil::execTRANSID_AI(Signal* signal){
2422   jamEntry();
2423 #if 0 //def EVENT_DEBUG
2424   ndbout_c("File: %s line: %u",__FILE__,__LINE__);
2425 #endif
2426 
2427   const Uint32 opI      = signal->theData[0];
2428   const Uint32 transId1 = signal->theData[1];
2429   const Uint32 transId2 = signal->theData[2];
2430   SectionHandle handle(this, signal);
2431   SegmentedSectionPtr dataPtr;
2432   bool longSignal = (handle.m_cnt == 1);
2433   Uint32 dataLen;
2434 
2435   if (longSignal)
2436   {
2437     ndbrequire(handle.getSection(dataPtr, 0));
2438     dataLen = dataPtr.sz;
2439   }
2440   else
2441   {
2442     dataLen = signal->length() - 3;
2443   }
2444 
2445   bool validSignal = false;
2446   Operation * opP;
2447   TransactionPtr transPtr;
2448   do
2449   {
2450     /* Lookup op record carefully, it may have been released if the
2451      * transaction was aborted and the TRANSID_AI was delayed
2452      */
2453     OperationPtr opPtr;
2454     opPtr.i = opI;
2455     c_operationPool.getPtrIgnoreAlloc(opPtr);
2456     opP = opPtr.p;
2457 
2458     /* Use transPtrI == RNIL as test of op record validity */
2459     if (opP->transPtrI == RNIL)
2460     {
2461       jam();
2462       break;
2463     }
2464 
2465 #ifdef ARRAY_GUARD
2466     /* Op was valid, do normal debug-only allocation double-check */
2467     ndbrequire(c_operationPool.isSeized(opI));
2468 #endif
2469 
2470     /* Valid op record must always point to allocated transaction record */
2471     c_runningTransactions.getPtr(transPtr, opP->transPtrI);
2472 
2473     /* Transaction may have different transid since this op was
2474      * executed - e.g. if it is retried due to a temp error.
2475      */
2476     validSignal = (transId1 == transPtr.p->transId[0] &&
2477                    transId2 == transPtr.p->transId[1]);
2478   } while(0);
2479 
2480   if (unlikely(!validSignal))
2481   {
2482     /* Can get strays as TRANSID_AI takes a different path
2483      * to LQHKEYCONF/TCKEYCONF/LQHKEYREF/TCKEYREF/TCROLLBACKREP
2484      * and we may have retried (with different transid), or
2485      * given up since then
2486      */
2487     jam();
2488     releaseSections(handle);
2489     return;
2490   }
2491 
2492   jam();
2493 
2494   opP->rsRecv += dataLen;
2495 
2496   /**
2497    * Save result
2498    */
2499   if (longSignal)
2500   {
2501     SectionSegment * ptrP = dataPtr.p;
2502     while (dataLen > NDB_SECTION_SEGMENT_SZ)
2503     {
2504       ndbrequire(opP->rs.append(ptrP->theData, NDB_SECTION_SEGMENT_SZ));
2505       dataLen -= NDB_SECTION_SEGMENT_SZ;
2506       ptrP = g_sectionSegmentPool.getPtr(ptrP->m_nextSegment);
2507     }
2508     ndbrequire(opP->rs.append(ptrP->theData, dataLen));
2509 
2510     releaseSections(handle);
2511   }
2512   else
2513   {
2514     const Uint32 *src = &signal->theData[3];
2515     ndbrequire(opP->rs.append(src, dataLen));
2516   }
2517 
2518   if(!opP->complete()){
2519    jam();
2520    return;
2521   }
2522 
2523   transPtr.p->recv++;
2524   if(!transPtr.p->complete()){
2525     jam();
2526     return;
2527   }
2528 
2529   finishTransaction(signal, transPtr);
2530 }
2531 
2532 void
execTCKEYCONF(Signal * signal)2533 DbUtil::execTCKEYCONF(Signal* signal){
2534   jamEntry();
2535 #if 0 //def EVENT_DEBUG
2536   ndbout_c("File: %s line: %u",__FILE__,__LINE__);
2537 #endif
2538 
2539   TcKeyConf * keyConf = (TcKeyConf*)signal->getDataPtr();
2540 
2541   Uint32 gci_lo = 0;
2542   const Uint32 gci_hi   = keyConf->gci_hi;
2543   const Uint32 transI   = keyConf->apiConnectPtr >> 1;
2544   const Uint32 confInfo = keyConf->confInfo;
2545   const Uint32 transId1 = keyConf->transId1;
2546   const Uint32 transId2 = keyConf->transId2;
2547 
2548   Uint32 recv = 0;
2549   const Uint32 ops = TcKeyConf::getNoOfOperations(confInfo);
2550   for(Uint32 i = 0; i<ops; i++){
2551     OperationPtr opPtr;
2552     c_operationPool.getPtr(opPtr, keyConf->operations[i].apiOperationPtr);
2553 
2554     ndbrequire(opPtr.p->transPtrI == transI);
2555     opPtr.p->rsExpect += keyConf->operations[i].attrInfoLen;
2556     if(opPtr.p->complete()){
2557       recv++;
2558     }
2559   }
2560 
2561   if (TcKeyConf::getCommitFlag(confInfo))
2562   {
2563     jam();
2564     gci_lo = keyConf->operations[ops].apiOperationPtr;
2565   }
2566 
2567   TransactionPtr transPtr;
2568   c_runningTransactions.getPtr(transPtr, transI);
2569 
2570   /**
2571    * Check commit ack marker flag
2572    */
2573   if (TcKeyConf::getMarkerFlag(confInfo))
2574   {
2575     jam();
2576     signal->theData[0] = transId1;
2577     signal->theData[1] = transId2;
2578     sendSignal(transPtr.p->connectRef, GSN_TC_COMMIT_ACK, signal, 2, JBB);
2579   }//if
2580 
2581   ndbrequire(transId1 == transPtr.p->transId[0] &&
2582 	     transId2 == transPtr.p->transId[1]);
2583 
2584   if (TcKeyConf::getCommitFlag(confInfo))
2585   {
2586     jam();
2587     transPtr.p->gci_hi = gci_hi;
2588     transPtr.p->gci_lo = gci_lo;
2589   }
2590 
2591   transPtr.p->recv += recv;
2592   if(!transPtr.p->complete()){
2593     jam();
2594     return;
2595   }
2596   finishTransaction(signal, transPtr);
2597 }
2598 
2599 void
execTCKEYREF(Signal * signal)2600 DbUtil::execTCKEYREF(Signal* signal){
2601   jamEntry();
2602 #if 0 //def EVENT_DEBUG
2603   ndbout_c("File: %s line: %u",__FILE__,__LINE__);
2604 #endif
2605 
2606   const Uint32 transI   = signal->theData[0] >> 1;
2607   const Uint32 transId1 = signal->theData[1];
2608   const Uint32 transId2 = signal->theData[2];
2609   const Uint32 errCode  = signal->theData[3];
2610 
2611   TransactionPtr transPtr;
2612   c_runningTransactions.getPtr(transPtr, transI);
2613   ndbrequire(transId1 == transPtr.p->transId[0] &&
2614 	     transId2 == transPtr.p->transId[1]);
2615 
2616   //if(getClassification(errCode) == PermanentError){
2617   //}
2618 
2619   //ndbout << "Transaction error (code: " << errCode << ")" << endl;
2620 
2621   transPtr.p->errorCode = errCode;
2622   finishTransaction(signal, transPtr);
2623 }
2624 
2625 void
execTCROLLBACKREP(Signal * signal)2626 DbUtil::execTCROLLBACKREP(Signal* signal){
2627   jamEntry();
2628 #if 0 //def EVENT_DEBUG
2629   ndbout_c("File: %s line: %u",__FILE__,__LINE__);
2630 #endif
2631 
2632   const Uint32 transI   = signal->theData[0] >> 1;
2633   const Uint32 transId1 = signal->theData[1];
2634   const Uint32 transId2 = signal->theData[2];
2635   const Uint32 errCode  = signal->theData[3];
2636 
2637   TransactionPtr transPtr;
2638   c_runningTransactions.getPtr(transPtr, transI);
2639   ndbrequire(transId1 == transPtr.p->transId[0] &&
2640 	     transId2 == transPtr.p->transId[1]);
2641 
2642   //if(getClassification(errCode) == PermanentError){
2643   //}
2644 
2645 #if 0 //def EVENT_DEBUG
2646   ndbout << "Transaction error (code: " << errCode << ")" << endl;
2647 #endif
2648 
2649   if(transPtr.p->noOfRetries > 0){
2650     transPtr.p->noOfRetries--;
2651     switch(errCode){
2652     case 266:
2653     case 410:
2654     case 1204:
2655 #if 0
2656       ndbout_c("errCode: %d noOfRetries: %d -> retry",
2657 	       errCode, transPtr.p->noOfRetries);
2658 #endif
2659       runTransaction(signal, transPtr);
2660       return;
2661     }
2662   }
2663 
2664   transPtr.p->errorCode = errCode;
2665   finishTransaction(signal, transPtr);
2666 }
2667 
2668 void
finishTransaction(Signal * signal,TransactionPtr transPtr)2669 DbUtil::finishTransaction(Signal* signal, TransactionPtr transPtr){
2670 #if 0 //def EVENT_DEBUG
2671   ndbout_c("Transaction %x %x completed %s",
2672 	   transPtr.p->transId[0],
2673 	   transPtr.p->transId[1],
2674 	   transPtr.p->errorCode == 0 ? "OK" : "FAILED");
2675 #endif
2676 
2677   /*
2678      How to find the correct RS?  Could we have multi-RS/transaction?
2679 
2680   Operation * opP = c_operationPool.getPtr(opI);
2681 
2682   ResultSetBuffer::DataBufferIterator rsit;
2683   ndbrequire(opP->rs.first(rsit));
2684   ndbout << "F Result: " << rsit.data << endl;
2685 
2686   while (opP->rs.next(rsit)) {
2687     ndbout << "R Result: " << rsit.data << endl;
2688   }
2689   */
2690 
2691   switch(transPtr.p->gsn){
2692   case GSN_UTIL_SEQUENCE_REQ:
2693     jam();
2694     reportSequence(signal, transPtr.p);
2695     break;
2696   case GSN_UTIL_EXECUTE_REQ:
2697     if (transPtr.p->errorCode) {
2698       UtilExecuteRef * ret = (UtilExecuteRef *)signal->getDataPtrSend();
2699       ret->senderData = transPtr.p->clientData;
2700       ret->errorCode = UtilExecuteRef::TCError;
2701       ret->TCErrorCode = transPtr.p->errorCode;
2702       sendSignal(transPtr.p->clientRef, GSN_UTIL_EXECUTE_REF, signal,
2703 		 UtilExecuteRef::SignalLength, JBB);
2704     } else {
2705       struct LinearSectionPtr sectionsPtr[UtilExecuteReq::NoOfSections];
2706       UtilExecuteConf * ret = (UtilExecuteConf *)signal->getDataPtrSend();
2707       ret->senderData = transPtr.p->clientData;
2708       ret->gci_hi = transPtr.p->gci_hi;
2709       ret->gci_lo = transPtr.p->gci_lo;
2710       if (getResultSet(signal, transPtr.p, sectionsPtr)) {
2711 #if 0 //def EVENT_DEBUG
2712 	for (int j = 0; j < 2; j++) {
2713 	  printf("Result set %u %u\n", j,sectionsPtr[j].sz);
2714 	  for (int i=0; i < sectionsPtr[j].sz; i++)
2715 	    printf("H'%.8x ", sectionsPtr[j].p[i]);
2716 	  printf("\n");
2717 	}
2718 #endif
2719 	sendSignal(transPtr.p->clientRef, GSN_UTIL_EXECUTE_CONF, signal,
2720 		   UtilExecuteConf::SignalLength, JBB,
2721 		   sectionsPtr, UtilExecuteReq::NoOfSections);
2722       } else
2723 	sendSignal(transPtr.p->clientRef, GSN_UTIL_EXECUTE_CONF, signal,
2724 		   UtilExecuteConf::SignalLength, JBB);
2725     }
2726     break;
2727   default:
2728     ndbrequire(0);
2729     break;
2730   }
2731   releaseTransaction(transPtr);
2732 }
2733 
2734 void
execUTIL_LOCK_REQ(Signal * signal)2735 DbUtil::execUTIL_LOCK_REQ(Signal * signal){
2736   jamEntry();
2737 
2738   UtilLockReq req = *(UtilLockReq*)signal->getDataPtr();
2739 
2740   LockQueuePtr lockQPtr;
2741   if(!c_lockQueues.find(lockQPtr, req.lockId))
2742   {
2743     jam();
2744     sendLOCK_REF(signal, &req, UtilLockRef::NoSuchLock);
2745     return;
2746   }
2747 
2748   const Uint32 senderNode = refToNode(req.senderRef);
2749   if(senderNode != getOwnNodeId() && senderNode != 0)
2750   {
2751     jam();
2752     sendLOCK_REF(signal, &req, UtilLockRef::DistributedLockNotSupported);
2753     return;
2754   }
2755 
2756   Uint32 res = lockQPtr.p->m_queue.lock(this, c_lockElementPool, &req);
2757   switch(res){
2758   case UtilLockRef::OK:
2759     jam();
2760     sendLOCK_CONF(signal, &req);
2761     return;
2762   case UtilLockRef::OutOfLockRecords:
2763     jam();
2764     sendLOCK_REF(signal, &req, UtilLockRef::OutOfLockRecords);
2765     return;
2766   case UtilLockRef::InLockQueue:
2767     jam();
2768     if (req.requestInfo & UtilLockReq::Notify)
2769     {
2770       jam();
2771       sendLOCK_REF(signal, &req, UtilLockRef::InLockQueue);
2772     }
2773     return;
2774   case UtilLockRef::LockAlreadyHeld:
2775     jam();
2776     ndbassert(req.requestInfo & UtilLockReq::TryLock);
2777     sendLOCK_REF(signal, &req, UtilLockRef::LockAlreadyHeld);
2778     return;
2779   default:
2780     jam();
2781     ndbassert(false);
2782     sendLOCK_REF(signal, &req, (UtilLockRef::ErrorCode)res);
2783     return;
2784   }
2785 }
2786 
2787 void
execUTIL_UNLOCK_REQ(Signal * signal)2788 DbUtil::execUTIL_UNLOCK_REQ(Signal* signal)
2789 {
2790   jamEntry();
2791 
2792   UtilUnlockReq req = *(UtilUnlockReq*)signal->getDataPtr();
2793 
2794   LockQueuePtr lockQPtr;
2795   if(!c_lockQueues.find(lockQPtr, req.lockId))
2796   {
2797     jam();
2798     sendUNLOCK_REF(signal, &req, UtilUnlockRef::NoSuchLock);
2799     return;
2800   }
2801 
2802   Uint32 res = lockQPtr.p->m_queue.unlock(this, c_lockElementPool, &req);
2803   switch(res){
2804   case UtilUnlockRef::OK:
2805     jam();
2806   case UtilUnlockRef::NotLockOwner: {
2807     jam();
2808     UtilUnlockConf * conf = (UtilUnlockConf*)signal->getDataPtrSend();
2809     conf->senderData = req.senderData;
2810     conf->senderRef = reference();
2811     conf->lockId = req.lockId;
2812     sendSignal(req.senderRef, GSN_UTIL_UNLOCK_CONF, signal,
2813                UtilUnlockConf::SignalLength, JBB);
2814     break;
2815   }
2816   case UtilUnlockRef::NotInLockQueue:
2817     jam();
2818   default:
2819     jam();
2820     ndbassert(false);
2821     sendUNLOCK_REF(signal, &req, (UtilUnlockRef::ErrorCode)res);
2822     break;
2823   }
2824 
2825   /**
2826    * Unlock can make other(s) acquie lock
2827    */
2828   UtilLockReq lockReq;
2829   LockQueue::Iterator iter;
2830   if (lockQPtr.p->m_queue.first(this, c_lockElementPool, iter))
2831   {
2832     int res;
2833     while ((res = lockQPtr.p->m_queue.checkLockGrant(iter, &lockReq)) > 0)
2834     {
2835       jam();
2836       /**
2837        *
2838        */
2839       if (res == 2)
2840       {
2841         jam();
2842         sendLOCK_CONF(signal, &lockReq);
2843       }
2844 
2845       if (!lockQPtr.p->m_queue.next(iter))
2846         break;
2847     }
2848   }
2849 }
2850 
2851 void
sendLOCK_REF(Signal * signal,const UtilLockReq * req,UtilLockRef::ErrorCode err)2852 DbUtil::sendLOCK_REF(Signal* signal,
2853                      const UtilLockReq * req, UtilLockRef::ErrorCode err)
2854 {
2855   const Uint32 senderData = req->senderData;
2856   const Uint32 senderRef = req->senderRef;
2857   const Uint32 lockId = req->lockId;
2858   const Uint32 extra = req->extra;
2859 
2860   UtilLockRef * ref = (UtilLockRef*)signal->getDataPtrSend();
2861   ref->senderData = senderData;
2862   ref->senderRef = reference();
2863   ref->lockId = lockId;
2864   ref->errorCode = err;
2865   ref->extra = extra;
2866   sendSignal(senderRef, GSN_UTIL_LOCK_REF, signal,
2867 	     UtilLockRef::SignalLength, JBB);
2868 }
2869 
2870 void
sendLOCK_CONF(Signal * signal,const UtilLockReq * req)2871 DbUtil::sendLOCK_CONF(Signal* signal, const UtilLockReq * req)
2872 {
2873   const Uint32 senderData = req->senderData;
2874   const Uint32 senderRef = req->senderRef;
2875   const Uint32 lockId = req->lockId;
2876   const Uint32 extra = req->extra;
2877 
2878   UtilLockConf * conf = (UtilLockConf*)signal->getDataPtrSend();
2879   conf->senderData = senderData;
2880   conf->senderRef = reference();
2881   conf->lockId = lockId;
2882   conf->extra = extra;
2883   sendSignal(senderRef, GSN_UTIL_LOCK_CONF, signal,
2884 	     UtilLockConf::SignalLength, JBB);
2885 }
2886 
2887 void
sendUNLOCK_REF(Signal * signal,const UtilUnlockReq * req,UtilUnlockRef::ErrorCode err)2888 DbUtil::sendUNLOCK_REF(Signal* signal,
2889 		       const UtilUnlockReq* req, UtilUnlockRef::ErrorCode err){
2890 
2891   const Uint32 senderData = req->senderData;
2892   const Uint32 senderRef = req->senderRef;
2893   const Uint32 lockId = req->lockId;
2894 
2895   UtilUnlockRef * ref = (UtilUnlockRef*)signal->getDataPtrSend();
2896   ref->senderData = senderData;
2897   ref->senderRef = reference();
2898   ref->lockId = lockId;
2899   ref->errorCode = err;
2900   sendSignal(senderRef, GSN_UTIL_UNLOCK_REF, signal,
2901 	     UtilUnlockRef::SignalLength, JBB);
2902 }
2903 
2904 void
execUTIL_CREATE_LOCK_REQ(Signal * signal)2905 DbUtil::execUTIL_CREATE_LOCK_REQ(Signal* signal){
2906   jamEntry();
2907   UtilCreateLockReq req = * (UtilCreateLockReq*)signal->getDataPtr();
2908 
2909   UtilCreateLockRef::ErrorCode err = UtilCreateLockRef::OK;
2910 
2911   do {
2912     LockQueuePtr lockQPtr;
2913     if(c_lockQueues.find(lockQPtr, req.lockId)){
2914       jam();
2915       err = UtilCreateLockRef::LockIdAlreadyUsed;
2916       break;
2917     }
2918 
2919     if(req.lockType != UtilCreateLockReq::Mutex){
2920       jam();
2921       err = UtilCreateLockRef::UnsupportedLockType;
2922       break;
2923     }
2924 
2925     if(!c_lockQueues.seize(lockQPtr)){
2926       jam();
2927       err = UtilCreateLockRef::OutOfLockQueueRecords;
2928       break;
2929     }
2930 
2931     new (lockQPtr.p) LockQueueInstance(req.lockId);
2932     c_lockQueues.add(lockQPtr);
2933 
2934     UtilCreateLockConf * conf = (UtilCreateLockConf*)signal->getDataPtrSend();
2935     conf->senderData = req.senderData;
2936     conf->senderRef = reference();
2937     conf->lockId = req.lockId;
2938 
2939     sendSignal(req.senderRef, GSN_UTIL_CREATE_LOCK_CONF, signal,
2940 	       UtilCreateLockConf::SignalLength, JBB);
2941     return;
2942   } while(false);
2943 
2944   UtilCreateLockRef * ref = (UtilCreateLockRef*)signal->getDataPtrSend();
2945   ref->senderData = req.senderData;
2946   ref->senderRef = reference();
2947   ref->lockId = req.lockId;
2948   ref->errorCode = err;
2949 
2950   sendSignal(req.senderRef, GSN_UTIL_CREATE_LOCK_REF, signal,
2951 	     UtilCreateLockRef::SignalLength, JBB);
2952 }
2953 
2954 void
execUTIL_DESTORY_LOCK_REQ(Signal * signal)2955 DbUtil::execUTIL_DESTORY_LOCK_REQ(Signal* signal){
2956   jamEntry();
2957 
2958   UtilDestroyLockReq req = * (UtilDestroyLockReq*)signal->getDataPtr();
2959   UtilDestroyLockRef::ErrorCode err = UtilDestroyLockRef::OK;
2960   do {
2961     LockQueuePtr lockQPtr;
2962     if(!c_lockQueues.find(lockQPtr, req.lockId))
2963     {
2964       jam();
2965       err = UtilDestroyLockRef::NoSuchLock;
2966       break;
2967     }
2968 
2969     LockQueue::Iterator iter;
2970     if (lockQPtr.p->m_queue.first(this, c_lockElementPool, iter) == false)
2971     {
2972       jam();
2973       err = UtilDestroyLockRef::NotLockOwner;
2974       break;
2975     }
2976 
2977     if (! (iter.m_curr.p->m_req.senderData == req.senderData &&
2978            iter.m_curr.p->m_req.senderRef == req.senderRef &&
2979            (! (iter.m_curr.p->m_req.requestInfo & UtilLockReq::SharedLock)) &&
2980            iter.m_curr.p->m_req.requestInfo & UtilLockReq::Granted))
2981     {
2982       jam();
2983       err = UtilDestroyLockRef::NotLockOwner;
2984       break;
2985     }
2986 
2987     /**
2988      * OK
2989      */
2990 
2991     while (lockQPtr.p->m_queue.next(iter))
2992     {
2993       jam();
2994       sendLOCK_REF(signal, &iter.m_curr.p->m_req, UtilLockRef::NoSuchLock);
2995     }
2996 
2997     lockQPtr.p->m_queue.clear(c_lockElementPool);
2998     c_lockQueues.release(lockQPtr);
2999 
3000     // Send Destroy conf
3001     UtilDestroyLockConf* conf=(UtilDestroyLockConf*)signal->getDataPtrSend();
3002     conf->senderData = req.senderData;
3003     conf->senderRef = reference();
3004     conf->lockId = req.lockId;
3005     sendSignal(req.senderRef, GSN_UTIL_DESTROY_LOCK_CONF, signal,
3006 	       UtilDestroyLockConf::SignalLength, JBB);
3007     return;
3008   } while(false);
3009 
3010   UtilDestroyLockRef * ref = (UtilDestroyLockRef*)signal->getDataPtrSend();
3011   ref->senderData = req.senderData;
3012   ref->senderRef = reference();
3013   ref->lockId = req.lockId;
3014   ref->errorCode = err;
3015   sendSignal(req.senderRef, GSN_UTIL_DESTROY_LOCK_REF, signal,
3016 	     UtilDestroyLockRef::SignalLength, JBB);
3017 }
3018 
3019 template class ArrayPool<DbUtil::Page32>;
3020