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