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