mariadb/ndb/include/ndbapi/NdbBlob.hpp

335 lines
10 KiB
C++
Raw Normal View History

2004-06-10 12:04:30 +02:00
/* 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 NdbBlob_H
#define NdbBlob_H
#include <ndb_types.h>
#include <NdbDictionary.hpp>
#include <NdbTransaction.hpp>
2004-06-10 12:04:30 +02:00
#include <NdbError.hpp>
class Ndb;
class NdbTransaction;
2004-06-10 12:04:30 +02:00
class NdbOperation;
class NdbRecAttr;
class NdbTableImpl;
class NdbColumnImpl;
/**
* @class NdbBlob
* @brief Blob handle
*
* Blob data is stored in 2 places:
*
* - "header" and "inline bytes" stored in the blob attribute
* - "blob parts" stored in a separate table NDB$BLOB_<tid>_<cid>
2004-06-10 12:04:30 +02:00
*
* Inline and part sizes can be set via NdbDictionary::Column methods
* when the table is created.
*
* NdbBlob is a blob handle. To access blob data, the handle must be
* created using NdbOperation::getBlobHandle in operation prepare phase.
* The handle has following states:
*
* - prepared: before the operation is executed
* - active: after execute or next result but before transaction commit
* - closed: after transaction commit
* - invalid: after rollback or transaction close
*
2004-07-22 12:33:14 +02:00
* NdbBlob supports 3 styles of data access:
2004-06-10 12:04:30 +02:00
*
* - in prepare phase, NdbBlob methods getValue and setValue are used to
2004-07-22 12:33:14 +02:00
* prepare a read or write of a blob value of known size
2004-06-10 12:04:30 +02:00
*
2004-07-22 12:33:14 +02:00
* - in prepare phase, setActiveHook is used to define a routine which
* is invoked as soon as the handle becomes active
*
* - in active phase, readData and writeData are used to read or write
* blob data of arbitrary size
*
* The styles can be applied in combination (in above order).
*
* Blob operations take effect at next transaction execute. In some
* cases NdbBlob is forced to do implicit executes. To avoid this,
* operate on complete blob parts.
*
* Use NdbTransaction::executePendingBlobOps to flush your reads and
2004-07-22 12:33:14 +02:00
* writes. It avoids execute penalty if nothing is pending. It is not
* needed after execute (obviously) or after next scan result.
2004-06-10 12:04:30 +02:00
*
* NdbBlob methods return -1 on error and 0 on success, and use output
* parameters when necessary.
*
* Operation types:
* - insertTuple must use setValue if blob column is non-nullable
* - readTuple with exclusive lock can also update existing value
* - updateTuple can overwrite with setValue or update existing value
* - writeTuple always overwrites and must use setValue if non-nullable
* - deleteTuple creates implicit non-accessible blob handles
* - scan with exclusive lock can also update existing value
* - scan "lock takeover" update op must do its own getBlobHandle
2004-06-10 12:04:30 +02:00
*
* Bugs / limitations:
* - lock mode upgrade should be handled automatically
* - lock mode vs allowed operation is not checked
* - too many pending blob ops can blow up i/o buffers
* - table and its blob part tables are not created atomically
2004-12-23 13:43:54 +01:00
*/
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
2004-12-23 13:43:54 +01:00
/**
* - there is no support for an asynchronous interface
2004-06-10 12:04:30 +02:00
*/
2004-12-23 13:43:54 +01:00
#endif
2004-06-10 12:04:30 +02:00
class NdbBlob {
public:
2004-07-22 12:33:14 +02:00
/**
* State.
*/
2004-06-10 12:04:30 +02:00
enum State {
Idle = 0,
Prepared = 1,
Active = 2,
Closed = 3,
Invalid = 9
};
2005-01-10 01:25:20 +01:00
/**
* Get the state of a NdbBlob object.
*/
2004-06-10 12:04:30 +02:00
State getState();
2004-07-22 12:33:14 +02:00
/**
* Inline blob header.
*/
struct Head {
Uint64 length;
};
2004-06-10 12:04:30 +02:00
/**
* Prepare to read blob value. The value is available after execute.
2005-01-10 01:25:20 +01:00
* Use getNull() to check for NULL and getLength() to get the real length
2004-06-10 12:04:30 +02:00
* and to check for truncation. Sets current read/write position to
* after the data read.
*/
int getValue(void* data, Uint32 bytes);
/**
* Prepare to insert or update blob value. An existing longer blob
* value will be truncated. The data buffer must remain valid until
* execute. Sets current read/write position to after the data. Set
* data to null pointer (0) to create a NULL value.
*/
int setValue(const void* data, Uint32 bytes);
2004-07-22 12:33:14 +02:00
/**
2005-01-10 01:25:20 +01:00
* Callback for setActiveHook(). Invoked immediately when the prepared
* operation has been executed (but not committed). Any getValue() or
* setValue() is done first. The blob handle is active so readData or
* writeData() etc can be used to manipulate blob value. A user-defined
2004-07-22 12:33:14 +02:00
* argument is passed along. Returns non-zero on error.
*/
typedef int ActiveHook(NdbBlob* me, void* arg);
/**
* Define callback for blob handle activation. The queue of prepared
* operations will be executed in no commit mode up to this point and
* then the callback is invoked.
*/
int setActiveHook(ActiveHook* activeHook, void* arg);
2004-06-10 12:04:30 +02:00
/**
* Check if blob is null.
*/
int getNull(bool& isNull);
/**
* Set blob to NULL.
*/
int setNull();
/**
2004-07-22 12:33:14 +02:00
* Get current length in bytes. Use getNull to distinguish between
2004-06-10 12:04:30 +02:00
* length 0 blob and NULL blob.
*/
int getLength(Uint64& length);
/**
* Truncate blob to given length. Has no effect if the length is
* larger than current length.
*/
int truncate(Uint64 length = 0);
/**
* Get current read/write position.
*/
int getPos(Uint64& pos);
/**
* Set read/write position. Must be between 0 and current length.
* "Sparse blobs" are not supported.
*/
int setPos(Uint64 pos);
/**
* Read at current position and set new position to first byte after
* the data read. A read past blob end returns actual number of bytes
* read in the in/out bytes parameter.
*/
int readData(void* data, Uint32& bytes);
/**
* Write at current position and set new position to first byte after
* the data written. A write past blob end extends the blob value.
*/
int writeData(const void* data, Uint32 bytes);
/**
* Return the blob column.
*/
const NdbDictionary::Column* getColumn();
/**
* Get blob parts table name. Useful only to test programs.
*/
static int getBlobTableName(char* btname, Ndb* anNdb, const char* tableName, const char* columnName);
/**
* Return error object. The error may be blob specific (below) or may
* be copied from a failed implicit operation.
*/
const NdbError& getNdbError() const;
2004-07-22 12:33:14 +02:00
/**
* Return info about all blobs in this operation.
2005-01-10 01:25:20 +01:00
*
* Get first blob in list.
2004-07-22 12:33:14 +02:00
*/
NdbBlob* blobsFirstBlob();
2005-01-10 01:25:20 +01:00
/**
* Return info about all blobs in this operation.
*
* Get next blob in list. Initialize with blobsFirstBlob().
*/
2004-07-22 12:33:14 +02:00
NdbBlob* blobsNextBlob();
2004-06-10 12:04:30 +02:00
private:
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
2004-06-10 12:04:30 +02:00
friend class Ndb;
friend class NdbTransaction;
2004-06-10 12:04:30 +02:00
friend class NdbOperation;
friend class NdbScanOperation;
friend class NdbDictionaryImpl;
2004-06-17 23:42:17 +02:00
friend class NdbResultSet; // atNextResult
#endif
2004-06-10 12:04:30 +02:00
// state
State theState;
void setState(State newState);
// define blob table
static void getBlobTableName(char* btname, const NdbTableImpl* t, const NdbColumnImpl* c);
static void getBlobTable(NdbTableImpl& bt, const NdbTableImpl* t, const NdbColumnImpl* c);
// ndb api stuff
Ndb* theNdb;
NdbTransaction* theNdbCon;
2004-06-10 12:04:30 +02:00
NdbOperation* theNdbOp;
2004-09-07 21:53:59 +02:00
const NdbTableImpl* theTable;
const NdbTableImpl* theAccessTable;
const NdbTableImpl* theBlobTable;
2004-06-10 12:04:30 +02:00
const NdbColumnImpl* theColumn;
char theFillChar;
// sizes
Uint32 theInlineSize;
Uint32 thePartSize;
Uint32 theStripeSize;
// getValue/setValue
bool theGetFlag;
char* theGetBuf;
bool theSetFlag;
const char* theSetBuf;
Uint32 theGetSetBytes;
2004-07-22 12:33:14 +02:00
// pending ops
Uint8 thePendingBlobOps;
// activation callback
ActiveHook* theActiveHook;
void* theActiveHookArg;
2004-06-10 12:04:30 +02:00
// buffers
struct Buf {
char* data;
unsigned size;
unsigned maxsize;
Buf();
~Buf();
void alloc(unsigned n);
void copyfrom(const Buf& src);
2004-06-10 12:04:30 +02:00
};
Buf theKeyBuf;
Buf theAccessKeyBuf;
Buf theHeadInlineBuf;
Buf theHeadInlineCopyBuf; // for writeTuple
2004-06-10 12:04:30 +02:00
Buf thePartBuf;
Head* theHead;
char* theInlineData;
NdbRecAttr* theHeadInlineRecAttr;
NdbOperation* theHeadInlineReadOp;
2004-06-10 12:04:30 +02:00
bool theHeadInlineUpdateFlag;
// length and read/write position
int theNullFlag;
Uint64 theLength;
Uint64 thePos;
// errors
NdbError theError;
// for keeping in lists
NdbBlob* theNext;
// initialization
NdbBlob();
void init();
void release();
// classify operations
bool isTableOp();
bool isIndexOp();
bool isKeyOp();
bool isReadOp();
bool isInsertOp();
bool isUpdateOp();
bool isWriteOp();
2004-06-10 12:04:30 +02:00
bool isDeleteOp();
bool isScanOp();
// computations
Uint32 getPartNumber(Uint64 pos);
Uint32 getPartCount();
Uint32 getDistKey(Uint32 part);
// getters and setters
int getTableKeyValue(NdbOperation* anOp);
int setTableKeyValue(NdbOperation* anOp);
int setAccessKeyValue(NdbOperation* anOp);
int setPartKeyValue(NdbOperation* anOp, Uint32 part);
int getHeadInlineValue(NdbOperation* anOp);
void getHeadFromRecAttr();
int setHeadInlineValue(NdbOperation* anOp);
// data operations
int readDataPrivate(char* buf, Uint32& bytes);
int writeDataPrivate(const char* buf, Uint32 bytes);
2004-06-10 12:04:30 +02:00
int readParts(char* buf, Uint32 part, Uint32 count);
int insertParts(const char* buf, Uint32 part, Uint32 count);
int updateParts(const char* buf, Uint32 part, Uint32 count);
int deleteParts(Uint32 part, Uint32 count);
int deletePartsUnknown(Uint32 part);
2004-07-22 12:33:14 +02:00
// pending ops
int executePendingBlobReads();
int executePendingBlobWrites();
// callbacks
int invokeActiveHook();
2004-06-10 12:04:30 +02:00
// blob handle maintenance
int atPrepare(NdbTransaction* aCon, NdbOperation* anOp, const NdbColumnImpl* aColumn);
int preExecute(NdbTransaction::ExecType anExecType, bool& batch);
int postExecute(NdbTransaction::ExecType anExecType);
2004-06-10 12:04:30 +02:00
int preCommit();
int atNextResult();
// errors
void setErrorCode(int anErrorCode, bool invalidFlag = true);
void setErrorCode(NdbOperation* anOp, bool invalidFlag = true);
void setErrorCode(NdbTransaction* aCon, bool invalidFlag = true);
2004-06-10 12:04:30 +02:00
#ifdef VM_TRACE
2004-07-22 12:33:14 +02:00
int getOperationType() const;
2004-06-10 12:04:30 +02:00
friend class NdbOut& operator<<(NdbOut&, const NdbBlob&);
#endif
};
#endif