~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to storage/ndb/src/ndbapi/NdbEventOperationImpl.hpp

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2003 MySQL AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
#ifndef NdbEventOperationImpl_H
 
17
#define NdbEventOperationImpl_H
 
18
 
 
19
#include <NdbEventOperation.hpp>
 
20
#include <signaldata/SumaImpl.hpp>
 
21
#include <transporter/TransporterDefinitions.hpp>
 
22
#include <NdbRecAttr.hpp>
 
23
#include <AttributeHeader.hpp>
 
24
#include <UtilBuffer.hpp>
 
25
 
 
26
#define NDB_EVENT_OP_MAGIC_NUMBER 0xA9F301B4
 
27
//#define EVENT_DEBUG
 
28
#ifdef EVENT_DEBUG
 
29
#define DBUG_ENTER_EVENT(A) DBUG_ENTER(A)
 
30
#define DBUG_RETURN_EVENT(A) DBUG_RETURN(A)
 
31
#define DBUG_VOID_RETURN_EVENT DBUG_VOID_RETURN
 
32
#define DBUG_PRINT_EVENT(A,B) DBUG_PRINT(A,B)
 
33
#define DBUG_DUMP_EVENT(A,B,C) DBUG_DUMP(A,B,C)
 
34
#else
 
35
#define DBUG_ENTER_EVENT(A)
 
36
#define DBUG_RETURN_EVENT(A) return(A)
 
37
#define DBUG_VOID_RETURN_EVENT return
 
38
#define DBUG_PRINT_EVENT(A,B)
 
39
#define DBUG_DUMP_EVENT(A,B,C)
 
40
#endif
 
41
 
 
42
#undef NDB_EVENT_VERIFY_SIZE
 
43
#ifdef VM_TRACE
 
44
// not much effect on performance, leave on
 
45
#define NDB_EVENT_VERIFY_SIZE
 
46
#endif
 
47
 
 
48
class NdbEventOperationImpl;
 
49
 
 
50
struct EventBufData
 
51
{
 
52
  union {
 
53
    SubTableData *sdata;
 
54
    Uint32 *memory;
 
55
  };
 
56
  LinearSectionPtr ptr[3];
 
57
  unsigned sz;
 
58
  NdbEventOperationImpl *m_event_op;
 
59
 
 
60
  /*
 
61
   * Blobs are stored in blob list (m_next_blob) where each entry
 
62
   * is list of parts (m_next).  TODO order by part number
 
63
   *
 
64
   * Processed data (m_used_data, m_free_data) keeps the old blob
 
65
   * list intact.  It is reconsumed when new data items are needed.
 
66
   *
 
67
   * Data item lists keep track of item count and sum(sz) and
 
68
   * these include both main items and blob parts.
 
69
   */
 
70
 
 
71
  EventBufData *m_next; // Next wrt to global order or Next blob part
 
72
  EventBufData *m_next_blob; // First part in next blob
 
73
 
 
74
  EventBufData *m_next_hash; // Next in per-GCI hash
 
75
  Uint32 m_pkhash; // PK hash (without op) for fast compare
 
76
 
 
77
  EventBufData() {}
 
78
 
 
79
  // Get blob part number from blob data
 
80
  Uint32 get_blob_part_no() const;
 
81
 
 
82
  /*
 
83
   * Main item does not include summary of parts (space / performance
 
84
   * tradeoff).  The summary is needed when moving single data item.
 
85
   * It is not needed when moving entire list.
 
86
   */
 
87
  void get_full_size(Uint32 & full_count, Uint32 & full_sz) const {
 
88
    full_count = 1;
 
89
    full_sz = sz;
 
90
    if (m_next_blob != 0)
 
91
      add_part_size(full_count, full_sz);
 
92
  }
 
93
  void add_part_size(Uint32 & full_count, Uint32 & full_sz) const;
 
94
};
 
95
 
 
96
class EventBufData_list
 
97
{
 
98
public:
 
99
  EventBufData_list();
 
100
  ~EventBufData_list();
 
101
 
 
102
  // remove first and return its size
 
103
  void remove_first(Uint32 & full_count, Uint32 & full_sz);
 
104
  // for remove+append avoid double call to get_full_size()
 
105
  void append_used_data(EventBufData *data, Uint32 full_count, Uint32 full_sz);
 
106
  // append data and insert data but ignore Gci_op list
 
107
  void append_used_data(EventBufData *data);
 
108
  // append data and insert data into Gci_op list with add_gci_op
 
109
  void append_data(EventBufData *data);
 
110
  // append list to another, will call move_gci_ops
 
111
  void append_list(EventBufData_list *list, Uint64 gci);
 
112
 
 
113
  int is_empty();
 
114
 
 
115
  EventBufData *m_head, *m_tail;
 
116
  Uint32 m_count;
 
117
  Uint32 m_sz;
 
118
 
 
119
  /*
 
120
    distinct ops per gci (assume no hash needed)
 
121
 
 
122
    list may be in 2 versions
 
123
 
 
124
    1. single list with on gci only
 
125
    - one linear array
 
126
    Gci_op  *m_gci_op_list;
 
127
    Uint32 m_gci_op_count;
 
128
    Uint32 m_gci_op_alloc != 0;
 
129
 
 
130
    2. multi list with several gcis
 
131
    - linked list of gci's
 
132
    - one linear array per gci
 
133
    Gci_ops *m_gci_ops_list;
 
134
    Gci_ops *m_gci_ops_list_tail;
 
135
    Uint32 m_is_not_multi_list == 0;
 
136
 
 
137
  */
 
138
  struct Gci_op                 // 1 + 2
 
139
  {
 
140
    NdbEventOperationImpl* op;
 
141
    Uint32 event_types;
 
142
  };
 
143
  struct Gci_ops                // 2
 
144
  {
 
145
    Uint64 m_gci;
 
146
    Gci_op *m_gci_op_list;
 
147
    Gci_ops *m_next;
 
148
    Uint32 m_gci_op_count;
 
149
  };
 
150
  union
 
151
  {
 
152
    Gci_op  *m_gci_op_list;      // 1
 
153
    Gci_ops *m_gci_ops_list;     // 2
 
154
  };
 
155
  union
 
156
  {
 
157
    Uint32 m_gci_op_count;       // 1
 
158
    Gci_ops *m_gci_ops_list_tail;// 2
 
159
  };
 
160
  union
 
161
  {
 
162
    Uint32 m_gci_op_alloc;       // 1
 
163
    Uint32 m_is_not_multi_list;  // 2
 
164
  };
 
165
  Gci_ops *first_gci_ops();
 
166
  Gci_ops *next_gci_ops();
 
167
  // case 1 above; add Gci_op to single list
 
168
  void add_gci_op(Gci_op g);
 
169
private:
 
170
  // case 2 above; move single list or multi list from
 
171
  // one list to another
 
172
  void move_gci_ops(EventBufData_list *list, Uint64 gci);
 
173
};
 
174
 
 
175
inline
 
176
EventBufData_list::EventBufData_list()
 
177
  : m_head(0), m_tail(0),
 
178
    m_count(0),
 
179
    m_sz(0),
 
180
    m_gci_op_list(NULL),
 
181
    m_gci_ops_list_tail(0),
 
182
    m_gci_op_alloc(0)
 
183
{
 
184
  DBUG_ENTER_EVENT("EventBufData_list::EventBufData_list");
 
185
  DBUG_PRINT_EVENT("info", ("this: %p", this));
 
186
  DBUG_VOID_RETURN_EVENT;
 
187
}
 
188
 
 
189
inline
 
190
EventBufData_list::~EventBufData_list()
 
191
{
 
192
  DBUG_ENTER_EVENT("EventBufData_list::~EventBufData_list");
 
193
  DBUG_PRINT_EVENT("info", ("this: %p  m_is_not_multi_list: %u",
 
194
                            this, m_is_not_multi_list));
 
195
  if (m_is_not_multi_list)
 
196
  {
 
197
    DBUG_PRINT_EVENT("info", ("delete m_gci_op_list: %p", m_gci_op_list));
 
198
    delete [] m_gci_op_list;
 
199
  }
 
200
  else
 
201
  {
 
202
    Gci_ops *op = first_gci_ops();
 
203
    while (op)
 
204
      op = next_gci_ops();
 
205
  }
 
206
  DBUG_VOID_RETURN_EVENT;
 
207
}
 
208
 
 
209
inline
 
210
int EventBufData_list::is_empty()
 
211
{
 
212
  return m_head == 0;
 
213
}
 
214
 
 
215
inline
 
216
void EventBufData_list::remove_first(Uint32 & full_count, Uint32 & full_sz)
 
217
{
 
218
  m_head->get_full_size(full_count, full_sz);
 
219
#ifdef VM_TRACE
 
220
  assert(m_count >= full_count);
 
221
  assert(m_sz >= full_sz);
 
222
#endif
 
223
  m_count -= full_count;
 
224
  m_sz -= full_sz;
 
225
  m_head = m_head->m_next;
 
226
  if (m_head == 0)
 
227
    m_tail = 0;
 
228
}
 
229
 
 
230
inline
 
231
void EventBufData_list::append_used_data(EventBufData *data, Uint32 full_count, Uint32 full_sz)
 
232
{
 
233
  data->m_next = 0;
 
234
  if (m_tail)
 
235
    m_tail->m_next = data;
 
236
  else
 
237
  {
 
238
#ifdef VM_TRACE
 
239
    assert(m_head == 0);
 
240
    assert(m_count == 0);
 
241
    assert(m_sz == 0);
 
242
#endif
 
243
    m_head = data;
 
244
  }
 
245
  m_tail = data;
 
246
 
 
247
  m_count += full_count;
 
248
  m_sz += full_sz;
 
249
}
 
250
 
 
251
inline
 
252
void EventBufData_list::append_used_data(EventBufData *data)
 
253
{
 
254
  Uint32 full_count, full_sz;
 
255
  data->get_full_size(full_count, full_sz);
 
256
  append_used_data(data, full_count, full_sz);
 
257
}
 
258
 
 
259
inline
 
260
void EventBufData_list::append_data(EventBufData *data)
 
261
{
 
262
  Gci_op g = { data->m_event_op, 
 
263
               1 << SubTableData::getOperation(data->sdata->requestInfo) };
 
264
  add_gci_op(g);
 
265
 
 
266
  append_used_data(data);
 
267
}
 
268
 
 
269
inline EventBufData_list::Gci_ops *
 
270
EventBufData_list::first_gci_ops()
 
271
{
 
272
  assert(!m_is_not_multi_list);
 
273
  return m_gci_ops_list;
 
274
}
 
275
 
 
276
inline EventBufData_list::Gci_ops *
 
277
EventBufData_list::next_gci_ops()
 
278
{
 
279
  assert(!m_is_not_multi_list);
 
280
  Gci_ops *first = m_gci_ops_list;
 
281
  m_gci_ops_list = first->m_next;
 
282
  if (first->m_gci_op_list)
 
283
  {
 
284
    DBUG_PRINT_EVENT("info", ("this: %p  delete m_gci_op_list: %p",
 
285
                              this, first->m_gci_op_list));
 
286
    delete [] first->m_gci_op_list;
 
287
  }
 
288
  delete first;
 
289
  if (m_gci_ops_list == 0)
 
290
    m_gci_ops_list_tail = 0;
 
291
  return m_gci_ops_list;
 
292
}
 
293
 
 
294
// GCI bucket has also a hash over data, with key event op, table PK.
 
295
// It can only be appended to and is invalid after remove_first().
 
296
class EventBufData_hash
 
297
{
 
298
public:
 
299
  struct Pos { // search result
 
300
    Uint32 index;       // index into hash array
 
301
    EventBufData* data; // non-zero if found
 
302
    Uint32 pkhash;      // PK hash
 
303
  };
 
304
 
 
305
  static Uint32 getpkhash(NdbEventOperationImpl* op, LinearSectionPtr ptr[3]);
 
306
  static bool getpkequal(NdbEventOperationImpl* op, LinearSectionPtr ptr1[3], LinearSectionPtr ptr2[3]);
 
307
 
 
308
  void search(Pos& hpos, NdbEventOperationImpl* op, LinearSectionPtr ptr[3]);
 
309
  void append(Pos& hpos, EventBufData* data);
 
310
 
 
311
  enum { GCI_EVENT_HASH_SIZE = 101 };
 
312
  EventBufData* m_hash[GCI_EVENT_HASH_SIZE];
 
313
};
 
314
 
 
315
inline
 
316
void EventBufData_hash::append(Pos& hpos, EventBufData* data)
 
317
{
 
318
  data->m_next_hash = m_hash[hpos.index];
 
319
  m_hash[hpos.index] = data;
 
320
}
 
321
 
 
322
struct Gci_container
 
323
{
 
324
  enum State 
 
325
  {
 
326
    GC_COMPLETE = 0x1 // GCI is complete, but waiting for out of order
 
327
  };
 
328
  
 
329
  Uint32 m_state;
 
330
  Uint32 m_gcp_complete_rep_count; // Remaining SUB_GCP_COMPLETE_REP until done
 
331
  Uint64 m_gci;                    // GCI
 
332
  EventBufData_list m_data;
 
333
  EventBufData_hash m_data_hash;
 
334
};
 
335
 
 
336
struct Gci_container_pod
 
337
{
 
338
  char data[sizeof(Gci_container)];
 
339
};
 
340
 
 
341
class NdbEventOperationImpl : public NdbEventOperation {
 
342
public:
 
343
  NdbEventOperationImpl(NdbEventOperation &f,
 
344
                        Ndb *theNdb, 
 
345
                        const char* eventName);
 
346
  NdbEventOperationImpl(Ndb *theNdb, 
 
347
                        NdbEventImpl& evnt);
 
348
  void init(NdbEventImpl& evnt);
 
349
  NdbEventOperationImpl(NdbEventOperationImpl&); //unimplemented
 
350
  NdbEventOperationImpl& operator=(const NdbEventOperationImpl&); //unimplemented
 
351
  ~NdbEventOperationImpl();
 
352
 
 
353
  NdbEventOperation::State getState();
 
354
 
 
355
  int execute();
 
356
  int execute_nolock();
 
357
  int stop();
 
358
  NdbRecAttr *getValue(const char *colName, char *aValue, int n);
 
359
  NdbRecAttr *getValue(const NdbColumnImpl *, char *aValue, int n);
 
360
  NdbBlob *getBlobHandle(const char *colName, int n);
 
361
  NdbBlob *getBlobHandle(const NdbColumnImpl *, int n);
 
362
  int readBlobParts(char* buf, NdbBlob* blob, Uint32 part, Uint32 count);
 
363
  int receive_event();
 
364
  bool tableNameChanged() const;
 
365
  bool tableFrmChanged() const;
 
366
  bool tableFragmentationChanged() const;
 
367
  bool tableRangeListChanged() const;
 
368
  Uint64 getGCI();
 
369
  Uint32 getAnyValue() const;
 
370
  Uint64 getLatestGCI();
 
371
  bool execSUB_TABLE_DATA(NdbApiSignal * signal, 
 
372
                          LinearSectionPtr ptr[3]);
 
373
 
 
374
  NdbDictionary::Event::TableEvent getEventType();
 
375
 
 
376
  void print();
 
377
  void printAll();
 
378
 
 
379
  NdbEventOperation *m_facade;
 
380
  Uint32 m_magic_number;
 
381
 
 
382
  const NdbError & getNdbError() const;
 
383
  NdbError m_error;
 
384
 
 
385
  Ndb *m_ndb;
 
386
  NdbEventImpl *m_eventImpl;
 
387
 
 
388
  NdbRecAttr *theFirstPkAttrs[2];
 
389
  NdbRecAttr *theCurrentPkAttrs[2];
 
390
  NdbRecAttr *theFirstDataAttrs[2];
 
391
  NdbRecAttr *theCurrentDataAttrs[2];
 
392
 
 
393
  NdbBlob* theBlobList;
 
394
  NdbEventOperationImpl* theBlobOpList; // in main op, list of blob ops
 
395
  NdbEventOperationImpl* theMainOp; // in blob op, the main op
 
396
 
 
397
  NdbEventOperation::State m_state; /* note connection to mi_type */
 
398
  Uint32 mi_type; /* should be == 0 if m_state != EO_EXECUTING
 
399
                   * else same as in EventImpl
 
400
                   */
 
401
  Uint32 m_eventId;
 
402
  Uint32 m_oid;
 
403
 
 
404
  /*
 
405
    m_node_bit_mask keeps track of which ndb nodes have reference to
 
406
    an event op
 
407
 
 
408
    - add    - TE_ACTIVE
 
409
    - remove - TE_STOP, TE_NODE_FAILURE, TE_CLUSTER_FAILURE
 
410
 
 
411
    TE_NODE_FAILURE and TE_CLUSTER_FAILURE are created as events
 
412
    and added to all event ops listed as active or pending delete
 
413
    in m_dropped_ev_op using insertDataL, includeing the blob
 
414
    event ops referenced by a regular event op.
 
415
    - NdbEventBuffer::report_node_failure
 
416
    - NdbEventBuffer::completeClusterFailed
 
417
 
 
418
    TE_ACTIVE is sent from the kernel on initial execute/start of the
 
419
    event op, but is also internally generetad on node connect like
 
420
    TE_NODE_FAILURE and TE_CLUSTER_FAILURE
 
421
    - NdbEventBuffer::report_node_connected
 
422
 
 
423
    when m_node_bit_mask becomes clear, the kernel reference is
 
424
    removed from m_ref_count
 
425
 
 
426
    node id 0 is used to denote that cluster has a reference
 
427
   */
 
428
 
 
429
  Bitmask<(unsigned int)_NDB_NODE_BITMASK_SIZE> m_node_bit_mask;
 
430
 
 
431
  /*
 
432
    m_ref_count keeps track of outstanding references to an event
 
433
    operation impl object.  To make sure that the object is not
 
434
    deleted too early.
 
435
 
 
436
    If on dropEventOperation there are still references to an
 
437
    object it is queued for delete in NdbEventBuffer::m_dropped_ev_op
 
438
  
 
439
    the following references exists for a _non_ blob event op:
 
440
    * user reference
 
441
    - add    - NdbEventBuffer::createEventOperation
 
442
    - remove - NdbEventBuffer::dropEventOperation
 
443
    * kernel reference
 
444
    - add    - execute_nolock
 
445
    - remove - TE_STOP, TE_CLUSTER_FAILURE
 
446
    * blob reference
 
447
    - add    - execute_nolock on blob event
 
448
    - remove - TE_STOP, TE_CLUSTER_FAILURE on blob event
 
449
    * gci reference
 
450
    - add    - insertDataL/add_gci_op
 
451
    - remove - NdbEventBuffer::deleteUsedEventOperations
 
452
 
 
453
    the following references exists for a blob event op:
 
454
    * kernel reference
 
455
    - add    - execute_nolock
 
456
    - remove - TE_STOP, TE_CLUSTER_FAILURE    
 
457
   */
 
458
 
 
459
  int m_ref_count;
 
460
  bool m_mergeEvents;
 
461
  
 
462
  EventBufData *m_data_item;
 
463
 
 
464
  void *m_custom_data;
 
465
  int m_has_error;
 
466
 
 
467
  Uint32 m_fragmentId;
 
468
  UtilBuffer m_buffer;
 
469
 
 
470
  // Bit mask for what has changed in a table (for TE_ALTER event)
 
471
  Uint32 m_change_mask;
 
472
 
 
473
#ifdef VM_TRACE
 
474
  Uint32 m_data_done_count;
 
475
  Uint32 m_data_count;
 
476
#endif
 
477
 
 
478
  // managed by the ndb object
 
479
  NdbEventOperationImpl *m_next;
 
480
  NdbEventOperationImpl *m_prev;
 
481
private:
 
482
  void receive_data(NdbRecAttr *r, const Uint32 *data, Uint32 sz);
 
483
};
 
484
 
 
485
class NdbEventBuffer {
 
486
public:
 
487
  NdbEventBuffer(Ndb*);
 
488
  ~NdbEventBuffer();
 
489
 
 
490
  const Uint32 &m_system_nodes;
 
491
  Vector<Gci_container_pod> m_active_gci;
 
492
  NdbEventOperation *createEventOperation(const char* eventName,
 
493
                                          NdbError &);
 
494
  NdbEventOperationImpl *createEventOperationImpl(NdbEventImpl& evnt,
 
495
                                                  NdbError &);
 
496
  void dropEventOperation(NdbEventOperation *);
 
497
  static NdbEventOperationImpl* getEventOperationImpl(NdbEventOperation* tOp);
 
498
 
 
499
  void add_drop_lock() { NdbMutex_Lock(m_add_drop_mutex); }
 
500
  void add_drop_unlock() { NdbMutex_Unlock(m_add_drop_mutex); }
 
501
  void lock() { NdbMutex_Lock(m_mutex); }
 
502
  void unlock() { NdbMutex_Unlock(m_mutex); }
 
503
 
 
504
  void add_op();
 
505
  void remove_op();
 
506
  void init_gci_containers();
 
507
 
 
508
  // accessed from the "receive thread"
 
509
  int insertDataL(NdbEventOperationImpl *op,
 
510
                  const SubTableData * const sdata,
 
511
                  LinearSectionPtr ptr[3]);
 
512
  void execSUB_GCP_COMPLETE_REP(const SubGcpCompleteRep * const rep);
 
513
  void complete_outof_order_gcis();
 
514
  
 
515
  void report_node_connected(Uint32 node_id);
 
516
  void report_node_failure(Uint32 node_id);
 
517
  void completeClusterFailed();
 
518
 
 
519
  // used by user thread 
 
520
  Uint64 getLatestGCI();
 
521
  Uint32 getEventId(int bufferId);
 
522
 
 
523
  int pollEvents(int aMillisecondNumber, Uint64 *latestGCI= 0);
 
524
  int flushIncompleteEvents(Uint64 gci);
 
525
  NdbEventOperation *nextEvent();
 
526
  NdbEventOperationImpl* getGCIEventOperations(Uint32* iter,
 
527
                                               Uint32* event_types);
 
528
  void deleteUsedEventOperations();
 
529
 
 
530
  NdbEventOperationImpl *move_data();
 
531
 
 
532
  // routines to copy/merge events
 
533
  EventBufData* alloc_data();
 
534
  int alloc_mem(EventBufData* data,
 
535
                LinearSectionPtr ptr[3],
 
536
                Uint32 * change_sz);
 
537
  void dealloc_mem(EventBufData* data,
 
538
                   Uint32 * change_sz);
 
539
  int copy_data(const SubTableData * const sdata,
 
540
                LinearSectionPtr ptr[3],
 
541
                EventBufData* data,
 
542
                Uint32 * change_sz);
 
543
  int merge_data(const SubTableData * const sdata,
 
544
                 LinearSectionPtr ptr[3],
 
545
                 EventBufData* data,
 
546
                 Uint32 * change_sz);
 
547
  int get_main_data(Gci_container* bucket,
 
548
                    EventBufData_hash::Pos& hpos,
 
549
                    EventBufData* blob_data);
 
550
  void add_blob_data(Gci_container* bucket,
 
551
                     EventBufData* main_data,
 
552
                     EventBufData* blob_data);
 
553
 
 
554
  void free_list(EventBufData_list &list);
 
555
 
 
556
  void reportStatus();
 
557
 
 
558
  // Global Mutex used for some things
 
559
  static NdbMutex *p_add_drop_mutex;
 
560
 
 
561
#ifdef VM_TRACE
 
562
  const char *m_latest_command;
 
563
  Uint64 m_flush_gci;
 
564
#endif
 
565
 
 
566
  Ndb *m_ndb;
 
567
  Uint64 m_latestGCI;           // latest "handover" GCI
 
568
  Uint64 m_latest_complete_GCI; // latest complete GCI (in case of outof order)
 
569
 
 
570
  NdbMutex *m_mutex;
 
571
  struct NdbCondition *p_cond;
 
572
 
 
573
  // receive thread
 
574
  Gci_container m_complete_data;
 
575
  EventBufData *m_free_data;
 
576
#ifdef VM_TRACE
 
577
  Uint32 m_free_data_count;
 
578
#endif
 
579
  Uint32 m_free_data_sz;
 
580
 
 
581
  // user thread
 
582
  EventBufData_list m_available_data;
 
583
  EventBufData_list m_used_data;
 
584
 
 
585
  unsigned m_total_alloc; // total allocated memory
 
586
 
 
587
  // threshholds to report status
 
588
  unsigned m_free_thresh, m_min_free_thresh, m_max_free_thresh;
 
589
  unsigned m_gci_slip_thresh;
 
590
 
 
591
  NdbError m_error;
 
592
 
 
593
#ifdef VM_TRACE
 
594
  static void verify_size(const EventBufData* data, Uint32 count, Uint32 sz);
 
595
  static void verify_size(const EventBufData_list & list);
 
596
#endif
 
597
 
 
598
private:
 
599
  void insert_event(NdbEventOperationImpl* impl,
 
600
                    SubTableData &data,
 
601
                    LinearSectionPtr *ptr,
 
602
                    Uint32 &oid_ref);
 
603
  
 
604
  int expand(unsigned sz);
 
605
 
 
606
  // all allocated data
 
607
  struct EventBufData_chunk
 
608
  {
 
609
    unsigned sz;
 
610
    EventBufData data[1];
 
611
  };
 
612
  Vector<EventBufData_chunk *> m_allocated_data;
 
613
  unsigned m_sz;
 
614
 
 
615
  /*
 
616
    dropped event operations (dropEventOperation) that have not yet
 
617
    been deleted because of outstanding m_ref_count
 
618
 
 
619
    check for delete is done on occations when the ref_count may have
 
620
    changed by calling deleteUsedEventOperations:
 
621
    - nextEvent - each time the user has completed processing a gci
 
622
  */
 
623
  NdbEventOperationImpl *m_dropped_ev_op;
 
624
 
 
625
  Uint32 m_active_op_count;
 
626
  NdbMutex *m_add_drop_mutex;
 
627
};
 
628
 
 
629
inline
 
630
NdbEventOperationImpl*
 
631
NdbEventBuffer::getEventOperationImpl(NdbEventOperation* tOp)
 
632
{
 
633
  return &tOp->m_impl;
 
634
}
 
635
 
 
636
inline void
 
637
NdbEventOperationImpl::receive_data(NdbRecAttr *r,
 
638
                                    const Uint32 *data,
 
639
                                    Uint32 sz)
 
640
{
 
641
  r->receive_data(data,sz);
 
642
#if 0
 
643
  if (sz)
 
644
  {
 
645
    assert((r->attrSize() * r->arraySize() + 3) >> 2 == sz);
 
646
    r->theNULLind= 0;
 
647
    memcpy(r->aRef(), data, 4 * sz);
 
648
    return;
 
649
  }
 
650
  r->theNULLind= 1;
 
651
#endif
 
652
}
 
653
 
 
654
#endif