1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
|
/* Copyright (c) 2003-2007 MySQL AB, 2010 Sun Microsystems, Inc.
Use is subject to license terms.
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; version 2 of the License.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#ifndef NdbEventOperation_H
#define NdbEventOperation_H
class NdbGlobalEventBuffer;
class NdbEventOperationImpl;
/**
* @class NdbEventOperation
* @brief Class of operations for getting change events from database.
*
* Brief description on how to work with events:
*
* - An event, represented by an NdbDictionary::Event, i created in the
* Database through
* NdbDictionary::Dictionary::createEvent() (note that this can be done
* by any application or thread and not necessarily by the "listener")
* - To listen to events, an NdbEventOperation object is instantiated by
* Ndb::createEventOperation()
* - execute() starts the event flow. Use Ndb::pollEvents() to wait
* for an event to occur. Use Ndb::nextEvent() to iterate
* through the events that have occured.
* - The instance is removed by Ndb::dropEventOperation()
*
* For more info see:
* @ref ndbapi_event.cpp
*
* Known limitations:
*
* - Maximum number of active NdbEventOperations are now set at compile time.
* Today 100. This will become a configuration parameter later.
* - Maximum number of NdbEventOperations tied to same event are maximum 16
* per process.
*
* Known issues:
*
* - When several NdbEventOperation's are tied to the same event in the same
* process they will share the circular buffer. The BufferLength will then
* be the same for all and decided by the first NdbEventOperation
* instantiation. Just make sure to instantiate the "largest" one first.
* - Today all events INSERT/DELETE/UPDATE and all changed attributes are
* sent to the API, even if only specific attributes have been specified.
* These are however hidden from the user and only relevant data is shown
* after Ndb::nextEvent().
* - "False" exits from Ndb::pollEvents() may occur and thus
* the subsequent Ndb::nextEvent() will return NULL,
* since there was no available data. Just do Ndb::pollEvents() again.
* - Event code does not check table schema version. Make sure to drop events
* after table is dropped. Will be fixed in later
* versions.
* - If a node failure has occured not all events will be recieved
* anymore. Drop NdbEventOperation and Create again after nodes are up
* again. Will be fixed in later versions.
*
* Test status:
*
* - Tests have been run on 1-node and 2-node systems
*
* Useful API programs:
*
* - ndb_select_all -d sys 'NDB$EVENTS_0'
* shows contents in the system table containing created events.
*
* @note this is an inteface to viewing events that is subject to change
*/
class NdbEventOperation {
public:
/**
* State of the NdbEventOperation object
*/
enum State {
EO_CREATED, ///< Created but execute() not called
EO_EXECUTING, ///< execute() called
EO_DROPPED, ///< Waiting to be deleted, Object unusable.
EO_ERROR ///< An error has occurred. Object unusable.
};
/**
* Retrieve current state of the NdbEventOperation object
*/
State getState();
/**
* See NdbDictionary::Event. Default is false.
*/
void mergeEvents(bool flag);
/**
* Activates the NdbEventOperation to start receiving events. The
* changed attribute values may be retrieved after Ndb::nextEvent()
* has returned not NULL. The getValue() methods must be called
* prior to execute().
*
* @return 0 if successful otherwise -1.
*/
int execute();
/**
* Defines a retrieval operation of an attribute value.
* The NDB API allocate memory for the NdbRecAttr object that
* will hold the returned attribute value.
*
* @note Note that it is the applications responsibility
* to allocate enough memory for aValue (if non-NULL).
* The buffer aValue supplied by the application must be
* aligned appropriately. The buffer is used directly
* (avoiding a copy penalty) only if it is aligned on a
* 4-byte boundary and the attribute size in bytes
* (i.e. NdbRecAttr::attrSize() times NdbRecAttr::arraySize() is
* a multiple of 4).
*
* @note There are two versions, getValue() and
* getPreValue() for retrieving the current and
* previous value repectively.
*
* @note This method does not fetch the attribute value from
* the database! The NdbRecAttr object returned by this method
* is <em>not</em> readable/printable before the
* execute() has been made and
* Ndb::nextEvent() has returned not NULL.
* If a specific attribute has not changed the corresponding
* NdbRecAttr will be in state UNDEFINED. This is checked by
* NdbRecAttr::isNULL() which then returns -1.
*
* @param anAttrName Attribute name
* @param aValue If this is non-NULL, then the attribute value
* will be returned in this parameter.<br>
* If NULL, then the attribute value will only
* be stored in the returned NdbRecAttr object.
* @return An NdbRecAttr object to hold the value of
* the attribute, or a NULL pointer
* (indicating error).
*/
NdbRecAttr *getValue(const char *anAttrName, char *aValue = 0);
/**
* See getValue().
*/
NdbRecAttr *getPreValue(const char *anAttrName, char *aValue = 0);
/**
* These methods replace getValue/getPreValue for blobs. Each
* method creates a blob handle NdbBlob. The handle supports only
* read operations. See NdbBlob.
*/
NdbBlob* getBlobHandle(const char *anAttrName);
NdbBlob* getPreBlobHandle(const char *anAttrName);
int isOverrun() const;
/**
* In the current implementation a nodefailiure may cause loss of events,
* in which case isConsistent() will return false
*/
bool isConsistent() const;
/**
* Query for occured event type.
*
* @note Only valid after Ndb::nextEvent() has been called and
* returned a not NULL value
*
* @return type of event
*/
NdbDictionary::Event::TableEvent getEventType() const;
/**
* Check if table name has changed, for event TE_ALTER
*/
bool tableNameChanged() const;
/**
* Check if table frm has changed, for event TE_ALTER
*/
bool tableFrmChanged() const;
/**
* Check if table fragmentation has changed, for event TE_ALTER
*/
bool tableFragmentationChanged() const;
/**
* Check if table range partition list name has changed, for event TE_ALTER
*/
bool tableRangeListChanged() const;
/**
* Retrieve the GCI of the latest retrieved event
*
* @return GCI number
*/
Uint64 getGCI() const;
/**
* Retrieve the AnyValue of the latest retrieved event
*
* @return AnyValue
*/
Uint32 getAnyValue() const;
/**
* Retrieve the complete GCI in the cluster (not necessarily
* associated with an event)
*
* @return GCI number
*/
Uint64 getLatestGCI() const;
/**
* Get the latest error
*
* @return Error object.
*/
const struct NdbError & getNdbError() const;
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/** these are subject to change at any time */
const NdbDictionary::Table* getTable() const;
const NdbDictionary::Event *getEvent() const;
const NdbRecAttr *getFirstPkAttr() const;
const NdbRecAttr *getFirstPkPreAttr() const;
const NdbRecAttr *getFirstDataAttr() const;
const NdbRecAttr *getFirstDataPreAttr() const;
// bool validateTable(NdbDictionary::Table &table) const;
void setCustomData(void * data);
void * getCustomData() const;
void clearError();
int hasError() const;
int getReqNodeId() const;
int getNdbdNodeId() const;
#endif
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
/*
*
*/
void print();
#endif
private:
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
friend class NdbEventOperationImpl;
friend class NdbEventBuffer;
#endif
NdbEventOperation(Ndb *theNdb, const char* eventName);
~NdbEventOperation();
class NdbEventOperationImpl &m_impl;
NdbEventOperation(NdbEventOperationImpl& impl);
};
typedef void (* NdbEventCallback)(NdbEventOperation*, Ndb*, void*);
#endif
|