File: _kievents.h

package info (click to toggle)
python-kinterbasdb 3.3.0-2
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 2,432 kB
  • ctags: 1,830
  • sloc: ansic: 16,803; python: 3,514; makefile: 63; sh: 22
file content (256 lines) | stat: -rw-r--r-- 9,005 bytes parent folder | download | duplicates (2)
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
/* KInterbasDB Python Package - Header File for Events Support
 *
 * Version 3.3
 *
 * The following contributors hold Copyright (C) over their respective
 * portions of code (see license.txt for details):
 *
 * [Original Author (maintained through version 2.0-0.3.1):]
 *   1998-2001 [alex]  Alexander Kuznetsov   <alexan@users.sourceforge.net>
 * [Maintainers (after version 2.0-0.3.1):]
 *   2001-2002 [maz]   Marek Isalski         <kinterbasdb@maz.nu>
 *   2002-2007 [dsr]   David Rushby          <woodsplitter@rocketmail.com>
 * [Contributors:]
 *   2001      [eac]   Evgeny A. Cherkashin  <eugeneai@icc.ru>
 *   2001-2002 [janez] Janez Jere            <janez.jere@void.si>            */

/* Throughout these declarations, note the use of the 'volatile' modifier to
 * ensure that an altered variable's value is written back to main memory
 * instead of mistakenly written only to one CPU's cache on a
 * multiprocessor. */

#ifndef _KIEVENTS_H
#define _KIEVENTS_H

#include "_kinterbasdb.h"

#ifdef ENABLE_DB_EVENT_SUPPORT

#include "_kinterbasdb_exception_functions_without_python.h"
#include "_kisupport.h"
#include "_kisupport_threadsafe_fifo_queue.h"

#ifdef FIREBIRD_2_0_OR_LATER
  #define EVENT_CALLBACK_FUNCTION ISC_EVENT_CALLBACK
#else
  #define EVENT_CALLBACK_FUNCTION isc_callback
#endif

#define DV_VOID(void_ptr) DEVOLATILE(void *, void_ptr)
#define DV_STR(char_ptr) DEVOLATILE(char *, char_ptr)
#define DV_STR_PTR(char_ptr_ptr) DEVOLATILE(char **, char_ptr_ptr)
#define DV_Q(q) DEVOLATILE(ThreadSafeFIFOQueue *, q)
#define DV_EOTC(eotc) DEVOLATILE(EventOpThreadContext *, eotc)
#define DV_ERB(erb) DEVOLATILE(EventRequestBlock *, erb)
#define DV_CALCTX(callctx) DEVOLATILE(EventCallbackThreadContext *, callctx)
#define DV_ISC_STATUS(ISC_STATUS_) DEVOLATILE(ISC_STATUS, ISC_STATUS_)
#define DV_STATVEC(ISC_STATUS_ptr) DEVOLATILE(ISC_STATUS *, ISC_STATUS_ptr)
#define DV_DB_HANDLE_PTR(isc_db_handle_ptr) DEVOLATILE(isc_db_handle *, isc_db_handle_ptr)
#define DV_LONG_PTR(long_ptr) DEVOLATILE(long *, long_ptr)
#define DV_ISC_LONG_PTR(ISC_LONG_ptr) DEVOLATILE(ISC_LONG *, ISC_LONG_ptr)
#define DV_THREADID_PTR(thread_id_ptr) \
  DEVOLATILE(PlatformThreadIdType *, thread_id_ptr)

/******************** HARD-CODED LIMITS:BEGIN ********************/

/* EVENT_BLOCK_SIZE is a limitation imposed by the DB client library, but
 * kinterbasdb transparently eliminates it from the Python programmer's
 * perspective. */
#define EVENT_BLOCK_SIZE 15

/******************** HARD-CODED LIMITS:END ********************/

/******************** MODULE TYPE DEFINITIONS:BEGIN ********************/

typedef enum {
  ECALL_UNINITIALIZED = 1,
  ECALL_DUMMY         = 2,
  ECALL_NORMAL        = 3,
  ECALL_DEAD          = 4
} EventCallbackThreadState;

typedef struct {
  PlatformMutexType lock;
  volatile EventCallbackThreadState state;

  volatile int block_number;

  volatile PlatformThreadIdType op_thread_id;

  /* op_q is a pointer to the operation request queue in the
   * EventOpThreadContext.  The queue's memory and member cleanup is managed
   * by the EventOpThreadContext, not by EventCallbackThreadContext. */
  volatile ThreadSafeFIFOQueue *op_q;
} EventCallbackThreadContext;


typedef struct {
  #define NULL_EVENT_ID -1
  volatile ISC_LONG event_id;

  volatile char *req_buf;
  volatile short req_buf_len;

  /* The EventOpThread never accesses the members of this structure.  The only
   * threads that do so are the thread that creates/destroys the
   * EventConduit, as well as (obviously) the respective EventCallbackThreads
   * themselves. */
  volatile EventCallbackThreadContext callback_ctx;
} EventRequestBlock;

typedef enum {
  /* Requested by the thread that creates the event conduit: */
  OP_CONNECT,
  OP_REGISTER,
  OP_DIE,

  /* Requested by the event callback (which runs for all except its final
   * iteration in a thread started by the database client library).
   * During this operation, the EventOpThread:
   *   1) Calculates and posts to the EventFiredQueue an EventFiredNode that
   *      contains the counts of the events that the EventOpNode indicates
   *      occurred.  The EventConduit.wait method is where EventFiredNodes are
   *      consumed from the EventFiredQueue.
   *   2) Re-registers the event callback to be called by the database client
   *      library the next time the server detects the occurence of any of the
   *      events that were specified by the client programmer in the
   *      event_names parameter to the EventConduit constructor. */
  OP_RECORD_AND_REREGISTER,

  /* Sent by the event callback thread in case of error: */
  OP_CALLBACK_ERROR
} EventOpThreadOpCode;

typedef enum {
  OPTHREADSTATE_NONE                           = 1,
  OPTHREADSTATE_WAITING_FOR_CONNECTION_REQUEST = 2,
  OPTHREADSTATE_WAITING_FOR_REGISTER_REQUEST   = 3,
  OPTHREADSTATE_READY                          = 4,
  OPTHREADSTATE_FATALLY_WOUNDED                = 5,
  OPTHREADSTATE_DEAD                           = 6
} EventOpThreadState;

typedef struct {
  PlatformMutexType lock;
  volatile EventOpThreadState state;
  volatile PlatformThreadIdType event_op_thread_id;

  volatile int n_event_blocks;

  /* error_info is used to transfer error information from one piece of code
   * that uses the EventOpThreadContext to another.  This member is always
   * manipulated by the EventOpThread, except during its initialization and
   * (potentially) its destruction. */
  NonPythonSQLErrorInfo *error_info;

  /* Members to support the database API calls: */
  volatile EventRequestBlock *er_blocks;

  volatile isc_db_handle db_handle;

  volatile ISC_STATUS sv[STATUS_VECTOR_SIZE];

  /* Members used to communicate with other threads: */
  /* Threads that want the EventOpThread to do something post EventOpNodes
   * bearing an EventOpThreadOpCode to this queue: */
  ThreadSafeFIFOQueue op_q;

  /* The thread(s) that make "administrative requests" of the EventOpThread
   * wait for acknowledgement on this queue; the EventOpThread provides those
   * acknowledgements in the form of AdminResponseNodes.  Although it's
   * possible for different threads to wait on this queue, they won't do it
   * simultaneously, so there's no risk of a waiting thread receiving
   * acknowledgement of an operation that another thread requested. */
  ThreadSafeFIFOQueue admin_response_q;

  /* event_q is a pointer to the EventConduit's event queue.  The EventOpThread
   * posts EventFiredNodes to this queue in reaction to EventOpNodes that it
   * receives via op_q from the EventCallbackThread.  The EventConduit.wait
   * method is where EventFiredNodes are consumed from event_q.*/
  volatile ThreadSafeFIFOQueue *event_q;
} EventOpThreadContext;


typedef enum {
  CONDUIT_STATE_CREATED,
  CONDUIT_STATE_OPEN,
  CONDUIT_STATE_CLOSED
} EventConduitState;

typedef struct {
  PyObject_HEAD /* Python API - infrastructural macro. */

  /* Since EventConduits are Python objects, access to them is implicitly
   * serialized by the GIL.  Destructive operations on those members of an
   * EventConduit that might be in use in multiple threads are not performed
   * until the destructor.  Therefore, no explicit lock is necessary. */

  EventConduitState state;

  PyObject *py_event_names;
  int n_event_names;
  int n_event_blocks;
  PyObject *py_event_counts_dict_template;

  ThreadSafeFIFOQueue event_q;

  /* The only time a thread other than the EventOpThread accesses the members
   * of op_thread_context is during the creation or destruction of the
   * EventConduit. */
  EventOpThreadContext op_thread_context;

  /* This thread reference is used during EventConduit destruction to ensure
   * that the EventOpThread has actually exited before the thread that's
   * destroying the EventOpThread's context pulls the rug out from under it. */
  PlatformThreadRefType op_thread_ref;
} EventConduit;


/* Node types used as elements of the various ThreadSafeFIFOQueues: */

typedef struct {
  volatile EventOpThreadOpCode op_code;

  #define NO_TAG -1
  volatile int tag;

  volatile void *payload; /* Might be NULL. */
} EventOpNode;

typedef struct {
  volatile EventOpThreadOpCode op_code;
  volatile long status;
  volatile ISC_STATUS sql_error_code;
  volatile char *message; /* Might be NULL. */
} AdminResponseNode;

#ifdef FIREBIRD_2_0_OR_LATER
  #define UPDATED_BUF_SIGNEDNESS unsigned
#else
  #define UPDATED_BUF_SIGNEDNESS
#endif

typedef struct {
  volatile int block_number;
  UPDATED_BUF_SIGNEDNESS char *updated_buf;
} EventCallbackOutputNode;

typedef struct {
  volatile int block_number;
  volatile long counts[EVENT_BLOCK_SIZE];
  #define COUNTS_BUF_SIZE (sizeof(long) * EVENT_BLOCK_SIZE)
} EventFiredNode;

typedef struct {
  volatile char *dsn;
  volatile short dsn_len;
  volatile char *dpb;
  volatile short dpb_len;
  volatile short dialect;
} ConnParamsNode;

/******************** MODULE TYPE DEFINITIONS:END ********************/

#endif /* ENABLE_DB_EVENT_SUPPORT */

#endif /* if not def _KIEVENTS_H */