1 /* Copyright (c) 2003-2006 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 #ifndef DBUTIL_H 18 #define DBUTIL_H 19 20 #include <ndb_limits.h> 21 #include <SimulatedBlock.hpp> 22 #include <NodeBitmask.hpp> 23 24 #include <ArrayPool.hpp> 25 #include <SLList.hpp> 26 #include <DLList.hpp> 27 #include <DLFifoList.hpp> 28 #include <DataBuffer.hpp> 29 #include <KeyTable.hpp> 30 31 #include <signaldata/KeyInfo.hpp> 32 #include <signaldata/AttrInfo.hpp> 33 #include <signaldata/TcKeyReq.hpp> 34 #include <signaldata/UtilPrepare.hpp> 35 #include <signaldata/UtilExecute.hpp> 36 #include <signaldata/UtilLock.hpp> 37 #include <SimpleProperties.hpp> 38 #include <Array.hpp> 39 40 #define UTIL_WORDS_PER_PAGE 1023 41 42 /** 43 * @class DbUtil 44 * @brief Database utilities 45 * 46 * This block implements transactional services which can be used by other 47 * blocks. 48 * 49 * @section secSequence Module: The Sequence Service 50 * 51 * A sequence is a varaible stored in the database. Each time it is 52 * requested with "NextVal" it returns a unique number. If requested 53 * with "CurrVal" it returns the current number. 54 * 55 * - Request: SEQUENCE_REQ 56 * Requests the 'NextVal' or 'CurrVal' for sequence variable 'sequenceId'. 57 * 58 * - Response: SEQUENCE_CONF / REF (if failure) 59 * Returns value requested. 60 */ 61 class DbUtil : public SimulatedBlock 62 { 63 public: 64 DbUtil(Block_context& ctx); 65 virtual ~DbUtil(); 66 BLOCK_DEFINES(DbUtil); 67 68 protected: 69 /** 70 * Startup & Misc 71 */ 72 void execREAD_CONFIG_REQ(Signal* signal); 73 void execSTTOR(Signal* signal); 74 void execNDB_STTOR(Signal* signal); 75 void execDUMP_STATE_ORD(Signal* signal); 76 void execCONTINUEB(Signal* signal); 77 78 /** 79 * Sequence Service : Public interface 80 */ 81 void execUTIL_SEQUENCE_REQ(Signal* signal); 82 void execUTIL_SEQUENCE_REF(Signal* signal); 83 void execUTIL_SEQUENCE_CONF(Signal* signal); 84 85 /** 86 * Prepare Service : Public interface 87 */ 88 void execUTIL_PREPARE_REQ(Signal* signal); 89 void execUTIL_PREPARE_CONF(Signal* signal); 90 void execUTIL_PREPARE_REF(Signal* signal); 91 92 /** 93 * Delete Service : Public interface 94 */ 95 void execUTIL_DELETE_REQ(Signal* signal); 96 void execUTIL_DELETE_REF(Signal* signal); 97 void execUTIL_DELETE_CONF(Signal* signal); 98 99 /** 100 * Execute Service : Public interface 101 */ 102 void execUTIL_EXECUTE_REQ(Signal* signal); 103 void execUTIL_EXECUTE_REF(Signal* signal); 104 void execUTIL_EXECUTE_CONF(Signal* signal); 105 106 /** 107 * Prepare Release Service : Public interface 108 */ 109 void execUTIL_RELEASE_REQ(Signal* signal); 110 void execUTIL_RELEASE_CONF(Signal* signal); 111 void execUTIL_RELEASE_REF(Signal* signal); 112 113 /** 114 * Backend interface to a used TC service 115 */ 116 void execTCSEIZECONF(Signal* signal); 117 void execTCKEYCONF(Signal* signal); 118 void execTCKEYREF(Signal* signal); 119 void execTCROLLBACKREP(Signal* signal); 120 void execTCKEY_FAILCONF(Signal* signal); 121 void execTCKEY_FAILREF(Signal* signal); 122 void execTRANSID_AI(Signal* signal); 123 124 /** 125 * Backend interface to a used DICT service 126 */ 127 void execGET_TABINFOREF(Signal*); 128 void execGET_TABINFO_CONF(Signal* signal); 129 130 private: 131 132 public: 133 struct PreparedOperation; 134 135 typedef DataBuffer<11> KeyInfoBuffer; 136 typedef KeyInfoBuffer::ConstDataBufferIterator KeyInfoIterator; 137 typedef DataBuffer<11> AttrInfoBuffer; 138 typedef AttrInfoBuffer::ConstDataBufferIterator AttrInfoIterator; 139 typedef DataBuffer<11> ResultSetBuffer; 140 typedef DataBuffer<11> ResultSetInfoBuffer; 141 typedef DataBuffer<1> AttrMappingBuffer; 142 143 /** 144 * @struct Page32 145 * @brief For storing SimpleProperties objects and similar temporary data 146 */ 147 struct Page32 { 148 Uint32 data[UTIL_WORDS_PER_PAGE]; 149 Uint32 nextPool; // Note: This used as data when seized 150 }; 151 152 /** 153 * @struct Prepare 154 * @brief Info regarding prepare request (contains a prepared operation) 155 * 156 * The prepare phase interprets the table and attribute names sent 157 * in the prepare request from the client and asks DICT for meta 158 * information. 159 */ 160 struct Prepare { PrepareDbUtil::Prepare161 Prepare(ArrayPool<Page32> & ap) : preparePages(ap) {} 162 163 /*** Client info ***/ 164 Uint32 clientRef; 165 Uint32 clientData; 166 167 /** 168 * SimpleProp sent in UTIL_PREPARE_REQ 169 * 170 * Example format: 171 * - UtilPrepareReq::NoOfOperations=1 172 * - UtilPrepareReq::OperationType=UtilPrepareReq::Delete 173 * - UtilPrepareReq::TableName="SYSTAB_0" 174 * - UtilPrepareReq::AttributeName="SYSKEY_0" 175 */ 176 Uint32 prepDataLen; 177 Array<Page32> preparePages; 178 179 /*** PreparedOperation constructed in Prepare phase ***/ 180 Ptr<PreparedOperation> prepOpPtr; 181 182 union { 183 Uint32 nextPool; 184 Uint32 nextList; 185 }; 186 Uint32 prevList; 187 printDbUtil::Prepare188 void print() const { 189 ndbout << "[-Prepare-" << endl 190 << " clientRef: " << clientRef 191 << ", clientData: " << clientData 192 << "]" << endl; 193 } 194 }; 195 196 /** 197 * @struct PreparedOperation 198 * @brief Contains instantiated TcKeyReq signaldata for operation 199 * 200 * The prepare phase is finished by storing the request in a 201 * PreparedOperation record. 202 */ 203 struct PreparedOperation { PreparedOperationDbUtil::PreparedOperation204 PreparedOperation(AttrMappingBuffer::DataBufferPool & am, 205 AttrInfoBuffer::DataBufferPool & ai, 206 ResultSetInfoBuffer::DataBufferPool & rs) : 207 releaseFlag(false), attrMapping(am), attrInfo(ai), rsInfo(rs) 208 { 209 pkBitmask.clear(); 210 } 211 212 /*** Various Operation Info ***/ 213 Uint32 keyLen; // Length of primary key (fixed size is assumed) 214 Uint32 rsLen; // Size of result set 215 Uint32 noOfKeyAttr; // Number of key attributes 216 Uint32 noOfAttr; // Number of attributes 217 bool releaseFlag; // flag if operation release after completion 218 219 /** 220 * Attribute Mapping 221 * 222 * This datastructure (buffer of AttributeHeader:s) are used to map 223 * each execute request to a TCKEYREQ train of signals. 224 * 225 * The datastructure contains (AttributeId, Position) pairs, where 226 * - AttributeId is id used in database, and 227 * - Position is position of attribute value in TCKEYREQ keyinfo 228 * part of the train of signals which will be send to TC. 229 * Position == 0x3fff means it should *not* be sent 230 * in keyinfo part. 231 */ 232 AttrMappingBuffer attrMapping; 233 234 /*** First signal in tckeyreq train ***/ 235 Uint32 tckeyLenInBytes; // TcKeyReq total signal length (in bytes) 236 Uint32 keyDataPos; // Where to store keydata[] in tckey signal 237 // (in #words from base in tckey signal) 238 TcKeyReq tckey; // Signaldata for first signal in train 239 240 /*** Attrinfo signals sent to TC (part of tckeyreq train) ***/ 241 AttrInfoBuffer attrInfo; 242 243 /*** Result of executed operation ***/ 244 ResultSetInfoBuffer rsInfo; 245 246 Bitmask<MAX_ATTRIBUTES_IN_TABLE> pkBitmask; 247 248 union { 249 Uint32 nextPool; 250 Uint32 nextList; 251 }; 252 Uint32 prevList; 253 printDbUtil::PreparedOperation254 void print() const { 255 ndbout << "[-PreparedOperation-" << endl 256 << " keyLen: " << keyLen 257 << ", rsLen: " << rsLen 258 << ", noOfKeyAttr: " << noOfKeyAttr 259 << ", noOfAttr: " << noOfAttr 260 << ", tckeyLenInBytes: " << tckeyLenInBytes 261 << ", keyDataPos: " << keyDataPos << endl 262 << "-AttrMapping- (AttrId, KeyPos)-pairs " 263 << "(Pos=3fff if non-key attr):" << endl; 264 attrMapping.print(stdout); 265 ndbout << "[-tckey- "; 266 printTCKEYREQ(stdout, (Uint32*)&tckey, 8, 0); 267 ndbout << "[-attrInfo- "; 268 attrInfo.print(stdout); 269 ndbout << "[-rsInfo- "; 270 rsInfo.print(stdout); 271 ndbout << "]]]]" << endl; 272 } 273 }; 274 275 /** 276 * @struct Operation 277 * @brief Used in execution (contains resultset and buffers for result) 278 */ 279 struct Operation { OperationDbUtil::Operation280 Operation(KeyInfoBuffer::DataBufferPool & ki, 281 AttrInfoBuffer::DataBufferPool & ai, 282 ResultSetBuffer::DataBufferPool & _rs) : 283 prepOp_i(RNIL), keyInfo(ki), attrInfo(ai), rs(_rs) {} 284 285 PreparedOperation * prepOp; 286 Uint32 prepOp_i; 287 KeyInfoBuffer keyInfo; 288 AttrInfoBuffer attrInfo; 289 ResultSetBuffer rs; 290 ResultSetBuffer::DataBufferIterator rsIterator; 291 292 Uint32 transPtrI; 293 294 Uint32 rsRecv; 295 Uint32 rsExpect; completeDbUtil::Operation296 inline bool complete() const { return rsRecv == rsExpect; } 297 298 union { 299 Uint32 nextPool; 300 Uint32 nextList; 301 }; 302 printDbUtil::Operation303 void print() const { 304 ndbout << "[-Operation-" << endl 305 << " transPtrI: " << transPtrI 306 << ", rsRecv: " << rsRecv; 307 ndbout << "[-PreparedOperation-" << endl; 308 prepOp->print(); 309 ndbout << "[-keyInfo-" << endl; 310 keyInfo.print(stdout); 311 ndbout << "[-attrInfo-" << endl; 312 attrInfo.print(stdout); 313 ndbout << "]]" << endl; 314 } 315 }; 316 317 /** 318 * @struct Transaction 319 * @brief Used in execution (contains list of operations) 320 */ 321 struct Transaction { TransactionDbUtil::Transaction322 Transaction(ArrayPool<Page32> & ap, ArrayPool<Operation> & op) : 323 executePages(ap), operations(op) {} 324 325 Uint32 clientRef; 326 Uint32 clientData; 327 Array<Page32> executePages; 328 329 Uint32 gsn; // Request type (SEQUENCE, DELETE, etc) 330 union { 331 /** 332 * Sequence transaction 333 */ 334 struct { 335 Uint32 sequenceId; 336 Uint32 requestType; 337 } sequence; 338 }; 339 340 Uint32 connectPtr; 341 Uint32 transId[2]; 342 SLList<Operation> operations; 343 344 Uint32 errorCode; 345 Uint32 noOfRetries; 346 Uint32 sent; // No of operations sent 347 Uint32 recv; // No of completed operations received completeDbUtil::Transaction348 inline bool complete() const { return sent == recv; }; 349 350 union { 351 Uint32 nextPool; 352 Uint32 nextList; 353 }; 354 Uint32 prevList; 355 printDbUtil::Transaction356 void print() const { 357 ndbout << "[-Transaction-" << endl 358 << " clientRef: " << clientRef 359 << ", clientData: " << clientData 360 << ", gsn: " << gsn 361 << ", errorCode: " << errorCode 362 << endl 363 << " sent: " << sent << " operations" 364 << ", recv: " << recv << " completed operations"; 365 OperationPtr opPtr; 366 this->operations.first(opPtr); 367 while(opPtr.i != RNIL){ 368 ndbout << "[-Operation-" << endl; 369 opPtr.p->print(); 370 this->operations.next(opPtr); 371 } 372 ndbout << "]" << endl; 373 } 374 }; 375 376 typedef Ptr<Page32> Page32Ptr; 377 typedef Ptr<Prepare> PreparePtr; 378 typedef Ptr<Transaction> TransactionPtr; 379 typedef Ptr<Operation> OperationPtr; 380 typedef Ptr<PreparedOperation> PreparedOperationPtr; 381 382 Uint32 c_transId[2]; 383 ArrayPool<Page32> c_pagePool; 384 ArrayPool<Prepare> c_preparePool; 385 ArrayPool<Operation> c_operationPool; 386 ArrayPool<PreparedOperation> c_preparedOperationPool; 387 ArrayPool<Transaction> c_transactionPool; 388 389 DataBuffer<1>::DataBufferPool c_attrMappingPool; 390 DataBuffer<11>::DataBufferPool c_dataBufPool; 391 DLList<Prepare> c_runningPrepares; 392 DLList<Transaction> c_seizingTransactions; // Being seized at TC 393 DLList<Transaction> c_runningTransactions; // Seized and now exec. 394 395 void getTransId(Transaction *); 396 void initResultSet(ResultSetBuffer &, const ResultSetInfoBuffer &); 397 void runTransaction(Signal* signal, TransactionPtr); 398 void runOperation(Signal* signal, TransactionPtr &, OperationPtr &, Uint32); 399 void sendKeyInfo(Signal* signal, 400 KeyInfo* keyInfo, 401 const KeyInfoBuffer & keyBuf, 402 KeyInfoIterator & kit); 403 void sendAttrInfo(Signal*, 404 AttrInfo* attrInfo, 405 const AttrInfoBuffer &, 406 AttrInfoIterator & ait); 407 int getResultSet(Signal* signal, const Transaction * transP, 408 struct LinearSectionPtr sectionsPtr[]); 409 void finishTransaction(Signal*, TransactionPtr); 410 void releaseTransaction(TransactionPtr transPtr); 411 void hardcodedPrepare(); 412 void connectTc(Signal* signal); 413 void reportSequence(Signal*, const Transaction *); 414 void readPrepareProps(Signal* signal, 415 SimpleProperties::Reader* reader, 416 Uint32 senderData); 417 void prepareOperation(Signal*, PreparePtr); 418 void sendUtilPrepareRef(Signal*, UtilPrepareRef::ErrorCode, Uint32, Uint32); 419 void sendUtilExecuteRef(Signal*, UtilExecuteRef::ErrorCode, 420 Uint32, Uint32, Uint32); 421 void releasePrepare(PreparePtr); 422 void releasePreparedOperation(PreparedOperationPtr); 423 424 /*************************************************************************** 425 * Lock manager 426 */ 427 struct LockQueueElement { 428 Uint32 m_senderData; 429 Uint32 m_senderRef; 430 union { 431 Uint32 nextPool; 432 Uint32 nextList; 433 }; 434 Uint32 prevList; 435 }; 436 typedef Ptr<LockQueueElement> LockQueueElementPtr; 437 438 struct LockQueue { LockQueueDbUtil::LockQueue439 LockQueue(){} LockQueueDbUtil::LockQueue440 LockQueue(Uint32 id) : m_queue() { m_lockId = id; m_lockKey = 0;} 441 union { 442 Uint32 m_lockId; 443 Uint32 key; 444 }; 445 Uint32 m_lockKey; 446 DLFifoList<LockQueueElement>::Head m_queue; 447 union { 448 Uint32 nextHash; 449 Uint32 nextPool; 450 }; 451 Uint32 prevHash; 452 hashValueDbUtil::LockQueue453 Uint32 hashValue() const { 454 return m_lockId; 455 } equalDbUtil::LockQueue456 bool equal(const LockQueue & rec) const { 457 return m_lockId == rec.m_lockId; 458 } 459 }; 460 typedef Ptr<LockQueue> LockQueuePtr; 461 462 463 ArrayPool<LockQueue> c_lockQueuePool; 464 ArrayPool<LockQueueElement> c_lockElementPool; 465 KeyTable<LockQueue> c_lockQueues; 466 467 void execUTIL_CREATE_LOCK_REQ(Signal* signal); 468 void execUTIL_DESTORY_LOCK_REQ(Signal* signal); 469 void execUTIL_LOCK_REQ(Signal* signal); 470 void execUTIL_UNLOCK_REQ(Signal* signal); 471 472 void sendLOCK_REF(Signal*, const UtilLockReq * req, UtilLockRef::ErrorCode); 473 void sendLOCK_CONF(Signal*, LockQueue *, LockQueueElement *); 474 475 void sendUNLOCK_REF(Signal*, const UtilUnlockReq*, UtilUnlockRef::ErrorCode); 476 void sendUNLOCK_CONF(Signal*, LockQueue *, LockQueueElement *); 477 478 // For testing of mutex:es 479 void mutex_created(Signal* signal, Uint32 mutexId, Uint32 retVal); 480 void mutex_destroyed(Signal* signal, Uint32 mutexId, Uint32 retVal); 481 void mutex_locked(Signal* signal, Uint32 mutexId, Uint32 retVal); 482 void mutex_unlocked(Signal* signal, Uint32 mutexId, Uint32 retVal); 483 }; 484 485 #endif 486