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
|
/* 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 */
/*****************************************************************************
* Name: NdbEventOperation.hpp
* Include:
* Link:
* Author: Tomas Ulin MySQL AB
* Date: 2003-11-21
* Version: 0.1
* Description: Event support
* Documentation:
* Adjust: 2003-11-21 Tomas Ulin First version.
* Adjust: 2003-12-11 Tomas Ulin Alpha Release.
****************************************************************************/
#ifndef NdbEventOperation_H
#define NdbEventOperation_H
class NdbGlobalEventBuffer;
class NdbEventOperationImpl;
/**
* @class NdbEventOperation
* @brief Class of operations for getting change events from database.
*
* An NdbEventOperation object is instantiated by
* NdbEventOperation *Ndb::createEventOperation(const char *eventName,
* int bufferLength)
*
* Prior to that an event must have been created in the Database through
* int NdbDictionary::createEvent(NdbDictionary::Event)
*
* bufferLength indicates size of circular buffer to store event info as
* they occur.
*
* The instance is removed by Ndb::dropEventOperation(NdbEventOperation*)
*
* For more info see:
* ndbapi_example5.cpp
* Ndb.hpp
* NdbDictionary.hpp
*
* 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 next(). However false exits from pollEvents() may occur and thus
* the subsequent next() will return zero, since there was no available
* data. Just do pollEvents() again. Will be fixed in later versions.
*
* Event code does not check table schema version. Make sure to drop events
* after table is dropped. Will be fixed in later
* versions.
*
* On a replicated system one will receive each event 2 times, one for each
* replica. If a node fails events will not be received twice anymore
* for data in corresponding fragment. Will be optimized in later versions.
*
* If a nodefailiure 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
*
* Known bugs:
*
* None, except if we can call some of the "isses" above bugs
*
* Useful API programs:
*
* select_all -d sys 'NDB$EVENTS_0'
* Will show contents in the system table containing created events.
*
*/
class NdbEventOperation {
public:
enum State {CREATED,EXECUTING,ERROR};
State getState();
/**
* Activates the NdbEventOperation to start receiving events. The
* changed attribute values may be retrieved after next() has returned
* a value greater than zero. The getValue() methods below must be called
* prior to execute().
*
* @return 0 if successful otherwise -1.
*/
int execute();
// about the event operation
// getting data
// NdbResultSet* getResultSet();
/**
* 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, NdbOperation::getValue and
* NdbOperation::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
* NdbEventConnection::execute has been made and
* NdbEventConnection::next has returned a value greater than
* zero. 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 = NULL);
NdbRecAttr *getPreValue(const char *anAttrName, char *aValue = NULL);
/**
* Retrieves event resultset if available, inserted into the NdbRecAttrs
* specified in getValue() and getPreValue(). To avoid polling for
* a resultset, one can use Ndb::pollEvents(int millisecond_timeout)
* which will wait on a mutex until an event occurs or the specified
* timeout occurs.
*
* @return >=0 if successful otherwise -1. Return value inicates number
* of available events. By sending pOverRun one may query for buffer
* overflow and *pOverRun will indicate the number of events that have
* overwritten.
*/
int next(int *pOverRun=NULL);
/**
* In the current implementation a nodefailiure may cause loss of events,
* in which case isConsistent() will return false
*/
bool isConsistent();
/**
* Query for occured event type.
* NdbDictionary::Event::{TE_INSERT,TE_UPDATE,TE_DELETE}
* Only valid after next() has returned value >= 0
*/
NdbDictionary::Event::TableEvent getEventType();
Uint32 getGCI();
Uint32 getLatestGCI();
void print();
private:
friend class NdbEventOperationImpl;
friend class Ndb;
NdbEventOperation(Ndb *theNdb, const char* eventName,int bufferLength);
~NdbEventOperation();
static int wait(void *p, int aMillisecondNumber);
class NdbEventOperationImpl &m_impl;
NdbEventOperation(NdbEventOperationImpl& impl);
};
typedef void (* NdbEventCallback)(NdbEventOperation*, Ndb*, void*);
#endif
|