summaryrefslogtreecommitdiff
path: root/storage/ndb/src/kernel/blocks/dbutil/DbUtil.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'storage/ndb/src/kernel/blocks/dbutil/DbUtil.hpp')
-rw-r--r--storage/ndb/src/kernel/blocks/dbutil/DbUtil.hpp485
1 files changed, 485 insertions, 0 deletions
diff --git a/storage/ndb/src/kernel/blocks/dbutil/DbUtil.hpp b/storage/ndb/src/kernel/blocks/dbutil/DbUtil.hpp
new file mode 100644
index 00000000000..5499970fde3
--- /dev/null
+++ b/storage/ndb/src/kernel/blocks/dbutil/DbUtil.hpp
@@ -0,0 +1,485 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef DBUTIL_H
+#define DBUTIL_H
+
+#include <ndb_limits.h>
+#include <SimulatedBlock.hpp>
+#include <NodeBitmask.hpp>
+
+#include <ArrayList.hpp>
+#include <ArrayPool.hpp>
+#include <SLList.hpp>
+#include <DLList.hpp>
+#include <DLFifoList.hpp>
+#include <DataBuffer.hpp>
+#include <KeyTable.hpp>
+
+#include <signaldata/KeyInfo.hpp>
+#include <signaldata/AttrInfo.hpp>
+#include <signaldata/TcKeyReq.hpp>
+#include <signaldata/UtilPrepare.hpp>
+#include <signaldata/UtilExecute.hpp>
+#include <signaldata/UtilLock.hpp>
+#include <SimpleProperties.hpp>
+
+#define UTIL_WORDS_PER_PAGE 1023
+
+/**
+ * @class DbUtil
+ * @brief Database utilities
+ *
+ * This block implements transactional services which can be used by other
+ * blocks.
+ *
+ * @section secSequence Module: The Sequence Service
+ *
+ * A sequence is a varaible stored in the database. Each time it is
+ * requested with "NextVal" it returns a unique number. If requested
+ * with "CurrVal" it returns the current number.
+ *
+ * - Request: SEQUENCE_REQ
+ * Requests the 'NextVal' or 'CurrVal' for sequence variable 'sequenceId'.
+ *
+ * - Response: SEQUENCE_CONF / REF (if failure)
+ * Returns value requested.
+ */
+class DbUtil : public SimulatedBlock
+{
+public:
+ DbUtil(const class Configuration & conf);
+ virtual ~DbUtil();
+ BLOCK_DEFINES(DbUtil);
+
+protected:
+ /**
+ * Startup & Misc
+ */
+ void execSTTOR(Signal* signal);
+ void execNDB_STTOR(Signal* signal);
+ void execDUMP_STATE_ORD(Signal* signal);
+ void execCONTINUEB(Signal* signal);
+
+ /**
+ * Sequence Service : Public interface
+ */
+ void execUTIL_SEQUENCE_REQ(Signal* signal);
+ void execUTIL_SEQUENCE_REF(Signal* signal);
+ void execUTIL_SEQUENCE_CONF(Signal* signal);
+
+ /**
+ * Prepare Service : Public interface
+ */
+ void execUTIL_PREPARE_REQ(Signal* signal);
+ void execUTIL_PREPARE_CONF(Signal* signal);
+ void execUTIL_PREPARE_REF(Signal* signal);
+
+ /**
+ * Delete Service : Public interface
+ */
+ void execUTIL_DELETE_REQ(Signal* signal);
+ void execUTIL_DELETE_REF(Signal* signal);
+ void execUTIL_DELETE_CONF(Signal* signal);
+
+ /**
+ * Execute Service : Public interface
+ */
+ void execUTIL_EXECUTE_REQ(Signal* signal);
+ void execUTIL_EXECUTE_REF(Signal* signal);
+ void execUTIL_EXECUTE_CONF(Signal* signal);
+
+ /**
+ * Prepare Release Service : Public interface
+ */
+ void execUTIL_RELEASE_REQ(Signal* signal);
+ void execUTIL_RELEASE_CONF(Signal* signal);
+ void execUTIL_RELEASE_REF(Signal* signal);
+
+ /**
+ * Backend interface to a used TC service
+ */
+ void execTCSEIZECONF(Signal* signal);
+ void execTCKEYCONF(Signal* signal);
+ void execTCKEYREF(Signal* signal);
+ void execTCROLLBACKREP(Signal* signal);
+ void execTCKEY_FAILCONF(Signal* signal);
+ void execTCKEY_FAILREF(Signal* signal);
+ void execTRANSID_AI(Signal* signal);
+
+ /**
+ * Backend interface to a used DICT service
+ */
+ void execGET_TABINFOREF(Signal*);
+ void execGET_TABINFO_CONF(Signal* signal);
+
+private:
+
+public:
+ struct PreparedOperation;
+
+ typedef DataBuffer<11> KeyInfoBuffer;
+ typedef KeyInfoBuffer::ConstDataBufferIterator KeyInfoIterator;
+ typedef DataBuffer<11> AttrInfoBuffer;
+ typedef AttrInfoBuffer::ConstDataBufferIterator AttrInfoIterator;
+ typedef DataBuffer<11> ResultSetBuffer;
+ typedef DataBuffer<11> ResultSetInfoBuffer;
+ typedef DataBuffer<1> AttrMappingBuffer;
+
+ /**
+ * @struct Page32
+ * @brief For storing SimpleProperties objects and similar temporary data
+ */
+ struct Page32 {
+ Uint32 data[UTIL_WORDS_PER_PAGE];
+ Uint32 nextPool; // Note: This used as data when seized
+ };
+
+ /**
+ * @struct Prepare
+ * @brief Info regarding prepare request (contains a prepared operation)
+ *
+ * The prepare phase interprets the table and attribute names sent
+ * in the prepare request from the client and asks DICT for meta
+ * information.
+ */
+ struct Prepare {
+ Prepare(ArrayPool<Page32> & ap) : preparePages(ap) {}
+
+ /*** Client info ***/
+ Uint32 clientRef;
+ Uint32 clientData;
+
+ /**
+ * SimpleProp sent in UTIL_PREPARE_REQ
+ *
+ * Example format:
+ * - UtilPrepareReq::NoOfOperations=1
+ * - UtilPrepareReq::OperationType=UtilPrepareReq::Delete
+ * - UtilPrepareReq::TableName="SYSTAB_0"
+ * - UtilPrepareReq::AttributeName="SYSKEY_0"
+ */
+ Uint32 prepDataLen;
+ Array<Page32> preparePages;
+
+ /*** PreparedOperation constructed in Prepare phase ***/
+ Ptr<PreparedOperation> prepOpPtr;
+
+ union {
+ Uint32 nextPool;
+ Uint32 nextList;
+ };
+ Uint32 prevList;
+
+ void print() const {
+ ndbout << "[-Prepare-" << endl
+ << " clientRef: " << clientRef
+ << ", clientData: " << clientData
+ << "]" << endl;
+ }
+ };
+
+ /**
+ * @struct PreparedOperation
+ * @brief Contains instantiated TcKeyReq signaldata for operation
+ *
+ * The prepare phase is finished by storing the request in a
+ * PreparedOperation record.
+ */
+ struct PreparedOperation {
+ PreparedOperation(AttrMappingBuffer::DataBufferPool & am,
+ AttrInfoBuffer::DataBufferPool & ai,
+ ResultSetInfoBuffer::DataBufferPool & rs) :
+ releaseFlag(false), attrMapping(am), attrInfo(ai), rsInfo(rs)
+ {
+ pkBitmask.clear();
+ }
+
+ /*** Various Operation Info ***/
+ Uint32 keyLen; // Length of primary key (fixed size is assumed)
+ Uint32 rsLen; // Size of result set
+ Uint32 noOfKeyAttr; // Number of key attributes
+ Uint32 noOfAttr; // Number of attributes
+ bool releaseFlag; // flag if operation release after completion
+
+ /**
+ * Attribute Mapping
+ *
+ * This datastructure (buffer of AttributeHeader:s) are used to map
+ * each execute request to a TCKEYREQ train of signals.
+ *
+ * The datastructure contains (AttributeId, Position) pairs, where
+ * - AttributeId is id used in database, and
+ * - Position is position of attribute value in TCKEYREQ keyinfo
+ * part of the train of signals which will be send to TC.
+ * Position == 0x3fff means it should *not* be sent
+ * in keyinfo part.
+ */
+ AttrMappingBuffer attrMapping;
+
+ /*** First signal in tckeyreq train ***/
+ Uint32 tckeyLenInBytes; // TcKeyReq total signal length (in bytes)
+ Uint32 keyDataPos; // Where to store keydata[] in tckey signal
+ // (in #words from base in tckey signal)
+ TcKeyReq tckey; // Signaldata for first signal in train
+
+ /*** Attrinfo signals sent to TC (part of tckeyreq train) ***/
+ AttrInfoBuffer attrInfo;
+
+ /*** Result of executed operation ***/
+ ResultSetInfoBuffer rsInfo;
+
+ Bitmask<MAX_ATTRIBUTES_IN_TABLE> pkBitmask;
+
+ union {
+ Uint32 nextPool;
+ Uint32 nextList;
+ };
+ Uint32 prevList;
+
+ void print() const {
+ ndbout << "[-PreparedOperation-" << endl
+ << " keyLen: " << keyLen
+ << ", rsLen: " << rsLen
+ << ", noOfKeyAttr: " << noOfKeyAttr
+ << ", noOfAttr: " << noOfAttr
+ << ", tckeyLenInBytes: " << tckeyLenInBytes
+ << ", keyDataPos: " << keyDataPos << endl
+ << "-AttrMapping- (AttrId, KeyPos)-pairs "
+ << "(Pos=3fff if non-key attr):" << endl;
+ attrMapping.print(stdout);
+ ndbout << "[-tckey- ";
+ printTCKEYREQ(stdout, (Uint32*)&tckey, 8, 0);
+ ndbout << "[-attrInfo- ";
+ attrInfo.print(stdout);
+ ndbout << "[-rsInfo- ";
+ rsInfo.print(stdout);
+ ndbout << "]]]]" << endl;
+ }
+ };
+
+ /**
+ * @struct Operation
+ * @brief Used in execution (contains resultset and buffers for result)
+ */
+ struct Operation {
+ Operation(KeyInfoBuffer::DataBufferPool & ki,
+ AttrInfoBuffer::DataBufferPool & ai,
+ ResultSetBuffer::DataBufferPool & _rs) :
+ prepOp_i(RNIL), keyInfo(ki), attrInfo(ai), rs(_rs) {}
+
+ PreparedOperation * prepOp;
+ Uint32 prepOp_i;
+ KeyInfoBuffer keyInfo;
+ AttrInfoBuffer attrInfo;
+ ResultSetBuffer rs;
+ ResultSetBuffer::DataBufferIterator rsIterator;
+
+ Uint32 transPtrI;
+
+ Uint32 rsRecv;
+ Uint32 rsExpect;
+ inline bool complete() const { return rsRecv == rsExpect; }
+
+ union {
+ Uint32 nextPool;
+ Uint32 nextList;
+ };
+
+ void print() const {
+ ndbout << "[-Operation-" << endl
+ << " transPtrI: " << transPtrI
+ << ", rsRecv: " << rsRecv;
+ ndbout << "[-PreparedOperation-" << endl;
+ prepOp->print();
+ ndbout << "[-keyInfo-" << endl;
+ keyInfo.print(stdout);
+ ndbout << "[-attrInfo-" << endl;
+ attrInfo.print(stdout);
+ ndbout << "]]" << endl;
+ }
+ };
+
+ /**
+ * @struct Transaction
+ * @brief Used in execution (contains list of operations)
+ */
+ struct Transaction {
+ Transaction(ArrayPool<Page32> & ap, ArrayPool<Operation> & op) :
+ executePages(ap), operations(op) {}
+
+ Uint32 clientRef;
+ Uint32 clientData;
+ Array<Page32> executePages;
+
+ Uint32 gsn; // Request type (SEQUENCE, DELETE, etc)
+ union {
+ /**
+ * Sequence transaction
+ */
+ struct {
+ Uint32 sequenceId;
+ Uint32 requestType;
+ } sequence;
+ };
+
+ Uint32 connectPtr;
+ Uint32 transId[2];
+ SLList<Operation> operations;
+
+ Uint32 errorCode;
+ Uint32 noOfRetries;
+ Uint32 sent; // No of operations sent
+ Uint32 recv; // No of completed operations received
+ inline bool complete() const { return sent == recv; };
+
+ union {
+ Uint32 nextPool;
+ Uint32 nextList;
+ };
+ Uint32 prevList;
+
+ void print() const {
+ ndbout << "[-Transaction-" << endl
+ << " clientRef: " << clientRef
+ << ", clientData: " << clientData
+ << ", gsn: " << gsn
+ << ", errorCode: " << errorCode
+ << endl
+ << " sent: " << sent << " operations"
+ << ", recv: " << recv << " completed operations";
+ OperationPtr opPtr;
+ this->operations.first(opPtr);
+ while(opPtr.i != RNIL){
+ ndbout << "[-Operation-" << endl;
+ opPtr.p->print();
+ this->operations.next(opPtr);
+ }
+ ndbout << "]" << endl;
+ }
+ };
+
+ typedef Ptr<Page32> Page32Ptr;
+ typedef Ptr<Prepare> PreparePtr;
+ typedef Ptr<Transaction> TransactionPtr;
+ typedef Ptr<Operation> OperationPtr;
+ typedef Ptr<PreparedOperation> PreparedOperationPtr;
+
+ Uint32 c_transId[2];
+ ArrayPool<Page32> c_pagePool;
+ ArrayPool<Prepare> c_preparePool;
+ ArrayPool<Operation> c_operationPool;
+ ArrayPool<PreparedOperation> c_preparedOperationPool;
+ ArrayPool<Transaction> c_transactionPool;
+
+ DataBuffer<1>::DataBufferPool c_attrMappingPool;
+ DataBuffer<11>::DataBufferPool c_dataBufPool;
+ DLList<Prepare> c_runningPrepares;
+ DLList<PreparedOperation> c_runningPreparedOperations;
+ DLList<Transaction> c_seizingTransactions; // Being seized at TC
+ DLList<Transaction> c_runningTransactions; // Seized and now exec.
+
+ void getTransId(Transaction *);
+ void initResultSet(ResultSetBuffer &, const ResultSetInfoBuffer &);
+ void runTransaction(Signal* signal, TransactionPtr);
+ void runOperation(Signal* signal, TransactionPtr &, OperationPtr &, Uint32);
+ void sendKeyInfo(Signal* signal,
+ KeyInfo* keyInfo,
+ const KeyInfoBuffer & keyBuf,
+ KeyInfoIterator & kit);
+ void sendAttrInfo(Signal*,
+ AttrInfo* attrInfo,
+ const AttrInfoBuffer &,
+ AttrInfoIterator & ait);
+ int getResultSet(Signal* signal, const Transaction * transP,
+ struct LinearSectionPtr sectionsPtr[]);
+ void finishTransaction(Signal*, TransactionPtr);
+ void releaseTransaction(TransactionPtr transPtr);
+ void hardcodedPrepare();
+ void connectTc(Signal* signal);
+ void reportSequence(Signal*, const Transaction *);
+ void readPrepareProps(Signal* signal,
+ SimpleProperties::Reader* reader,
+ Uint32 senderData);
+ void prepareOperation(Signal*, PreparePtr);
+ void sendUtilPrepareRef(Signal*, UtilPrepareRef::ErrorCode, Uint32, Uint32);
+ void sendUtilExecuteRef(Signal*, UtilExecuteRef::ErrorCode,
+ Uint32, Uint32, Uint32);
+ void releasePrepare(PreparePtr);
+ void releasePreparedOperation(PreparedOperationPtr);
+
+ /***************************************************************************
+ * Lock manager
+ */
+ struct LockQueueElement {
+ Uint32 m_senderData;
+ Uint32 m_senderRef;
+ union {
+ Uint32 nextPool;
+ Uint32 nextList;
+ };
+ Uint32 prevList;
+ };
+ typedef Ptr<LockQueueElement> LockQueueElementPtr;
+
+ struct LockQueue {
+ LockQueue(){}
+ LockQueue(Uint32 id) : m_queue() { m_lockId = id; m_lockKey = 0;}
+ union {
+ Uint32 m_lockId;
+ Uint32 key;
+ };
+ Uint32 m_lockKey;
+ DLFifoList<LockQueueElement>::Head m_queue;
+ union {
+ Uint32 nextHash;
+ Uint32 nextPool;
+ };
+ Uint32 prevHash;
+
+ Uint32 hashValue() const {
+ return m_lockId;
+ }
+ bool equal(const LockQueue & rec) const {
+ return m_lockId == rec.m_lockId;
+ }
+ };
+ typedef Ptr<LockQueue> LockQueuePtr;
+
+
+ ArrayPool<LockQueue> c_lockQueuePool;
+ ArrayPool<LockQueueElement> c_lockElementPool;
+ KeyTable<LockQueue> c_lockQueues;
+
+ void execUTIL_CREATE_LOCK_REQ(Signal* signal);
+ void execUTIL_DESTORY_LOCK_REQ(Signal* signal);
+ void execUTIL_LOCK_REQ(Signal* signal);
+ void execUTIL_UNLOCK_REQ(Signal* signal);
+
+ void sendLOCK_REF(Signal*, const UtilLockReq * req, UtilLockRef::ErrorCode);
+ void sendLOCK_CONF(Signal*, LockQueue *, LockQueueElement *);
+
+ void sendUNLOCK_REF(Signal*, const UtilUnlockReq*, UtilUnlockRef::ErrorCode);
+ void sendUNLOCK_CONF(Signal*, LockQueue *, LockQueueElement *);
+
+ // For testing of mutex:es
+ void mutex_created(Signal* signal, Uint32 mutexId, Uint32 retVal);
+ void mutex_destroyed(Signal* signal, Uint32 mutexId, Uint32 retVal);
+ void mutex_locked(Signal* signal, Uint32 mutexId, Uint32 retVal);
+ void mutex_unlocked(Signal* signal, Uint32 mutexId, Uint32 retVal);
+};
+
+#endif