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