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

« back to all changes in this revision

Viewing changes to storage/ndb/src/kernel/blocks/dbtux/Dbtux.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 DBTUX_H
 
17
#define DBTUX_H
 
18
 
 
19
#include <ndb_limits.h>
 
20
#include <SimulatedBlock.hpp>
 
21
#include <AttributeDescriptor.hpp>
 
22
#include <AttributeHeader.hpp>
 
23
#include <ArrayPool.hpp>
 
24
#include <DataBuffer.hpp>
 
25
#include <DLFifoList.hpp>
 
26
#include <md5_hash.hpp>
 
27
 
 
28
// big brother
 
29
#include <dbtup/Dbtup.hpp>
 
30
 
 
31
// signal classes
 
32
#include <signaldata/DictTabInfo.hpp>
 
33
#include <signaldata/TuxContinueB.hpp>
 
34
#include <signaldata/TupFrag.hpp>
 
35
#include <signaldata/AlterIndx.hpp>
 
36
#include <signaldata/DropTab.hpp>
 
37
#include <signaldata/TuxMaint.hpp>
 
38
#include <signaldata/AccScan.hpp>
 
39
#include <signaldata/TuxBound.hpp>
 
40
#include <signaldata/NextScan.hpp>
 
41
#include <signaldata/AccLock.hpp>
 
42
#include <signaldata/DumpStateOrd.hpp>
 
43
 
 
44
// debug
 
45
#ifdef VM_TRACE
 
46
#include <NdbOut.hpp>
 
47
#include <OutputStream.hpp>
 
48
#endif
 
49
 
 
50
// jams
 
51
#undef jam
 
52
#undef jamEntry
 
53
#ifdef DBTUX_GEN_CPP
 
54
#define jam()           jamLine(10000 + __LINE__)
 
55
#define jamEntry()      jamEntryLine(10000 + __LINE__)
 
56
#endif
 
57
#ifdef DBTUX_META_CPP
 
58
#define jam()           jamLine(20000 + __LINE__)
 
59
#define jamEntry()      jamEntryLine(20000 + __LINE__)
 
60
#endif
 
61
#ifdef DBTUX_MAINT_CPP
 
62
#define jam()           jamLine(30000 + __LINE__)
 
63
#define jamEntry()      jamEntryLine(30000 + __LINE__)
 
64
#endif
 
65
#ifdef DBTUX_NODE_CPP
 
66
#define jam()           jamLine(40000 + __LINE__)
 
67
#define jamEntry()      jamEntryLine(40000 + __LINE__)
 
68
#endif
 
69
#ifdef DBTUX_TREE_CPP
 
70
#define jam()           jamLine(50000 + __LINE__)
 
71
#define jamEntry()      jamEntryLine(50000 + __LINE__)
 
72
#endif
 
73
#ifdef DBTUX_SCAN_CPP
 
74
#define jam()           jamLine(60000 + __LINE__)
 
75
#define jamEntry()      jamEntryLine(60000 + __LINE__)
 
76
#endif
 
77
#ifdef DBTUX_SEARCH_CPP
 
78
#define jam()           jamLine(70000 + __LINE__)
 
79
#define jamEntry()      jamEntryLine(70000 + __LINE__)
 
80
#endif
 
81
#ifdef DBTUX_CMP_CPP
 
82
#define jam()           jamLine(80000 + __LINE__)
 
83
#define jamEntry()      jamEntryLine(80000 + __LINE__)
 
84
#endif
 
85
#ifdef DBTUX_STAT_CPP
 
86
#define jam()           jamLine(90000 + __LINE__)
 
87
#define jamEntry()      jamEntryLine(90000 + __LINE__)
 
88
#endif
 
89
#ifdef DBTUX_DEBUG_CPP
 
90
#define jam()           jamLine(100000 + __LINE__)
 
91
#define jamEntry()      jamEntryLine(100000 + __LINE__)
 
92
#endif
 
93
#ifndef jam
 
94
#define jam()           jamLine(__LINE__)
 
95
#define jamEntry()      jamEntryLine(__LINE__)
 
96
#endif
 
97
 
 
98
#undef max
 
99
#undef min
 
100
 
 
101
class Configuration;
 
102
 
 
103
class Dbtux : public SimulatedBlock {
 
104
public:
 
105
  Dbtux(Block_context& ctx);
 
106
  virtual ~Dbtux();
 
107
 
 
108
  // pointer to TUP instance in this thread
 
109
  Dbtup* c_tup;
 
110
 
 
111
private:
 
112
  // sizes are in words (Uint32)
 
113
  STATIC_CONST( MaxIndexFragments = MAX_FRAG_PER_NODE );
 
114
  STATIC_CONST( MaxIndexAttributes = MAX_ATTRIBUTES_IN_INDEX );
 
115
  STATIC_CONST( MaxAttrDataSize = 2048 );
 
116
public:
 
117
  STATIC_CONST( DescPageSize = 256 );
 
118
private:
 
119
  STATIC_CONST( MaxTreeNodeSize = MAX_TTREE_NODE_SIZE );
 
120
  STATIC_CONST( MaxPrefSize = MAX_TTREE_PREF_SIZE );
 
121
  STATIC_CONST( ScanBoundSegmentSize = 7 );
 
122
  STATIC_CONST( MaxAccLockOps = MAX_PARALLEL_OP_PER_SCAN );
 
123
  STATIC_CONST( MaxTreeDepth = 32 );    // strict
 
124
  BLOCK_DEFINES(Dbtux);
 
125
 
 
126
  // forward declarations
 
127
  struct DescEnt;
 
128
 
 
129
  // Pointer to array of Uint32 represents attribute data and bounds
 
130
 
 
131
  typedef Uint32 *Data;
 
132
  inline AttributeHeader& ah(Data data) {
 
133
    return *reinterpret_cast<AttributeHeader*>(data);
 
134
  }
 
135
 
 
136
  typedef const Uint32* ConstData;
 
137
  inline const AttributeHeader& ah(ConstData data) {
 
138
    return *reinterpret_cast<const AttributeHeader*>(data);
 
139
  }
 
140
 
 
141
  // AttributeHeader size is assumed to be 1 word
 
142
  STATIC_CONST( AttributeHeaderSize = 1 );
 
143
 
 
144
  /*
 
145
   * Logical tuple address, "local key".  Identifies table tuples.
 
146
   */
 
147
  typedef Uint32 TupAddr;
 
148
  STATIC_CONST( NullTupAddr = (Uint32)-1 );
 
149
 
 
150
  /*
 
151
   * Physical tuple address in TUP.  Provides fast access to table tuple
 
152
   * or index node.  Valid within the db node and across timeslices.
 
153
   * Not valid between db nodes or across restarts.
 
154
   *
 
155
   * To avoid wasting an Uint16 the pageid is split in two.
 
156
   */
 
157
  struct TupLoc {
 
158
  private:
 
159
    Uint16 m_pageId1;           // page i-value (big-endian)
 
160
    Uint16 m_pageId2;
 
161
    Uint16 m_pageOffset;        // page offset in words
 
162
  public:
 
163
    TupLoc();
 
164
    TupLoc(Uint32 pageId, Uint16 pageOffset);
 
165
    Uint32 getPageId() const;
 
166
    void setPageId(Uint32 pageId);
 
167
    Uint32 getPageOffset() const;
 
168
    void setPageOffset(Uint32 pageOffset);
 
169
    bool operator==(const TupLoc& loc) const;
 
170
    bool operator!=(const TupLoc& loc) const;
 
171
  };
 
172
 
 
173
  /*
 
174
   * There is no const member NullTupLoc since the compiler may not be
 
175
   * able to optimize it to TupLoc() constants.  Instead null values are
 
176
   * constructed on the stack with TupLoc().
 
177
   */
 
178
#define NullTupLoc TupLoc()
 
179
 
 
180
  // tree definitions
 
181
 
 
182
  /*
 
183
   * Tree entry.  Points to a tuple in primary table via physical
 
184
   * address of "original" tuple and tuple version.
 
185
   *
 
186
   * ZTUP_VERSION_BITS must be 15 (or less).
 
187
   */
 
188
  struct TreeEnt;
 
189
  friend struct TreeEnt;
 
190
  struct TreeEnt {
 
191
    TupLoc m_tupLoc;            // address of original tuple
 
192
    unsigned m_tupVersion : 15; // version
 
193
    TreeEnt();
 
194
    // methods
 
195
    bool eqtuple(const TreeEnt ent) const;
 
196
    bool eq(const TreeEnt ent) const;
 
197
    int cmp(const TreeEnt ent) const;
 
198
  };
 
199
  STATIC_CONST( TreeEntSize = sizeof(TreeEnt) >> 2 );
 
200
  static const TreeEnt NullTreeEnt;
 
201
 
 
202
  /*
 
203
   * Tree node has 1) fixed part 2) a prefix of index key data for min
 
204
   * entry 3) max and min entries 4) rest of entries 5) one extra entry
 
205
   * used as work space.
 
206
   *
 
207
   * struct TreeNode            part 1, size 6 words
 
208
   * min prefix                 part 2, size TreeHead::m_prefSize
 
209
   * max entry                  part 3
 
210
   * min entry                  part 3
 
211
   * rest of entries            part 4
 
212
   * work entry                 part 5
 
213
   *
 
214
   * There are 3 links to other nodes: left child, right child, parent.
 
215
   * Occupancy (number of entries) is at least 1 except temporarily when
 
216
   * a node is about to be removed.
 
217
   */
 
218
  struct TreeNode;
 
219
  friend struct TreeNode;
 
220
  struct TreeNode {
 
221
    TupLoc m_link[3];           // link to 0-left child 1-right child 2-parent
 
222
    unsigned m_side : 2;        // we are 0-left child 1-right child 2-root
 
223
    unsigned m_balance : 2;     // balance -1, 0, +1 plus 1 for Solaris CC
 
224
    unsigned pad1 : 4;
 
225
    Uint8 m_occup;              // current number of entries
 
226
    Uint32 m_nodeScan;          // list of scans at this node
 
227
    TreeNode();
 
228
  };
 
229
  STATIC_CONST( NodeHeadSize = sizeof(TreeNode) >> 2 );
 
230
 
 
231
  /*
 
232
   * Tree node "access size" was for an early version with signal
 
233
   * interface to TUP.  It is now used only to compute sizes.
 
234
   */
 
235
  enum AccSize {
 
236
    AccNone = 0,
 
237
    AccHead = 1,                // part 1
 
238
    AccPref = 2,                // parts 1-3
 
239
    AccFull = 3                 // parts 1-5
 
240
  };
 
241
 
 
242
  /*
 
243
   * Tree header.  There is one in each fragment.  Contains tree
 
244
   * parameters and address of root node.
 
245
   */
 
246
  struct TreeHead;
 
247
  friend struct TreeHead;
 
248
  struct TreeHead {
 
249
    Uint8 m_nodeSize;           // words in tree node
 
250
    Uint8 m_prefSize;           // words in min prefix
 
251
    Uint8 m_minOccup;           // min entries in internal node
 
252
    Uint8 m_maxOccup;           // max entries in node
 
253
    Uint32 m_entryCount;        // stat: current entries
 
254
    TupLoc m_root;              // root node
 
255
    TreeHead();
 
256
    // methods
 
257
    unsigned getSize(AccSize acc) const;
 
258
    Data getPref(TreeNode* node) const;
 
259
    TreeEnt* getEntList(TreeNode* node) const;
 
260
  };
 
261
 
 
262
  /*
 
263
   * Tree position.  Specifies node, position within node (from 0 to
 
264
   * m_occup), and whether the position is at an existing entry or
 
265
   * before one (if any).  Position m_occup points past the node and is
 
266
   * also represented by position 0 of next node.  Includes direction
 
267
   * used by scan.
 
268
   */
 
269
  struct TreePos;
 
270
  friend struct TreePos;
 
271
  struct TreePos {
 
272
    TupLoc m_loc;               // physical node address
 
273
    Uint16 m_pos;               // position 0 to m_occup
 
274
    Uint8 m_dir;                // see scanNext
 
275
    TreePos();
 
276
  };
 
277
 
 
278
  // packed metadata
 
279
 
 
280
  /*
 
281
   * Descriptor page.  The "hot" metadata for an index is stored as
 
282
   * a contiguous array of words on some page.
 
283
   */
 
284
  struct DescPage;
 
285
  friend struct DescPage;
 
286
  struct DescPage {
 
287
    Uint32 m_nextPage;
 
288
    Uint32 m_numFree;           // number of free words
 
289
    union {
 
290
    Uint32 m_data[DescPageSize];
 
291
    Uint32 nextPool;
 
292
    };
 
293
    DescPage();
 
294
  };
 
295
  typedef Ptr<DescPage> DescPagePtr;
 
296
  ArrayPool<DescPage> c_descPagePool;
 
297
  Uint32 c_descPageList;
 
298
 
 
299
  /*
 
300
   * Header for index metadata.  Size must be multiple of word size.
 
301
   */
 
302
  struct DescHead {
 
303
    unsigned m_indexId : 24;
 
304
    unsigned pad1 : 8;
 
305
  };
 
306
  STATIC_CONST( DescHeadSize = sizeof(DescHead) >> 2 );
 
307
 
 
308
  /*
 
309
   * Attribute metadata.  Size must be multiple of word size.
 
310
   *
 
311
   * Prefix comparison of char data must use strxfrm and binary
 
312
   * comparison.  The charset is currently unused.
 
313
   */
 
314
  struct DescAttr {
 
315
    Uint32 m_attrDesc;          // standard AttributeDescriptor
 
316
    Uint16 m_primaryAttrId;
 
317
    unsigned m_typeId : 6;
 
318
    unsigned m_charset : 10;
 
319
  };
 
320
  STATIC_CONST( DescAttrSize = sizeof(DescAttr) >> 2 );
 
321
 
 
322
  /*
 
323
   * Complete metadata for one index. The array of attributes has
 
324
   * variable size.
 
325
   */
 
326
  friend struct DescEnt;
 
327
  struct DescEnt {
 
328
    DescHead m_descHead;
 
329
    DescAttr m_descAttr[1];     // variable size data
 
330
  };
 
331
 
 
332
  // range scan
 
333
 
 
334
  /*
 
335
   * Scan bounds are stored in linked list of segments.
 
336
   */
 
337
  typedef DataBuffer<ScanBoundSegmentSize> ScanBound;
 
338
  typedef DataBuffer<ScanBoundSegmentSize>::ConstDataBufferIterator ScanBoundIterator;
 
339
  typedef DataBuffer<ScanBoundSegmentSize>::DataBufferPool ScanBoundPool;
 
340
  ScanBoundPool c_scanBoundPool;
 
341
 
 
342
  // ScanLock
 
343
  struct ScanLock {
 
344
    Uint32 m_accLockOp;
 
345
    union {
 
346
    Uint32 nextPool;
 
347
    Uint32 nextList;
 
348
    };
 
349
    Uint32 prevList;
 
350
  };
 
351
  typedef Ptr<ScanLock> ScanLockPtr;
 
352
  ArrayPool<ScanLock> c_scanLockPool;
 
353
 
 
354
  /*
 
355
   * Scan operation.
 
356
   *
 
357
   * Tuples are locked one at a time.  The current lock op is set to
 
358
   * RNIL as soon as the lock is obtained and passed to LQH.  We must
 
359
   * however remember all locks which LQH has not returned for unlocking
 
360
   * since they must be aborted by us when the scan is closed.
 
361
   *
 
362
   * Scan state describes the entry we are interested in.  There is
 
363
   * a separate lock wait flag.  It may be for current entry or it may
 
364
   * be for an entry we were moved away from.  In any case nothing
 
365
   * happens with current entry before lock wait flag is cleared.
 
366
   *
 
367
   * An unfinished scan is always linked to some tree node, and has
 
368
   * current position and direction (see comments at scanNext).  There
 
369
   * is also a copy of latest entry found.
 
370
   */
 
371
  struct ScanOp;
 
372
  friend struct ScanOp;
 
373
  struct ScanOp {
 
374
    enum {
 
375
      Undef = 0,
 
376
      First = 1,                // before first entry
 
377
      Current = 2,              // at some entry
 
378
      Found = 3,                // return current as next scan result
 
379
      Blocked = 4,              // found and waiting for ACC lock
 
380
      Locked = 5,               // found and locked or no lock needed
 
381
      Next = 6,                 // looking for next extry
 
382
      Last = 7,                 // after last entry
 
383
      Aborting = 8,             // lock wait at scan close
 
384
      Invalid = 9               // cannot return REF to LQH currently
 
385
    };
 
386
    Uint16 m_state;
 
387
    Uint16 m_lockwait;
 
388
    Uint32 m_userPtr;           // scanptr.i in LQH
 
389
    Uint32 m_userRef;
 
390
    Uint32 m_tableId;
 
391
    Uint32 m_indexId;
 
392
    Uint32 m_fragId;
 
393
    Uint32 m_fragPtrI;
 
394
    Uint32 m_transId1;
 
395
    Uint32 m_transId2;
 
396
    Uint32 m_savePointId;
 
397
    // lock waited for or obtained and not yet passed to LQH
 
398
    Uint32 m_accLockOp;
 
399
    // locks obtained and passed to LQH but not yet returned by LQH
 
400
    DLFifoList<ScanLock>::Head m_accLockOps;
 
401
    Uint8 m_readCommitted;      // no locking
 
402
    Uint8 m_lockMode;
 
403
    Uint8 m_descending;
 
404
    ScanBound m_boundMin;
 
405
    ScanBound m_boundMax;
 
406
    ScanBound* m_bound[2];      // pointers to above 2
 
407
    Uint16 m_boundCnt[2];       // number of bounds in each
 
408
    TreePos m_scanPos;          // position
 
409
    TreeEnt m_scanEnt;          // latest entry found
 
410
    Uint32 m_nodeScan;          // next scan at node (single-linked)
 
411
    union {
 
412
    Uint32 nextPool;
 
413
    Uint32 nextList;
 
414
    };
 
415
    Uint32 prevList;
 
416
    ScanOp(ScanBoundPool& scanBoundPool);
 
417
  };
 
418
  typedef Ptr<ScanOp> ScanOpPtr;
 
419
  ArrayPool<ScanOp> c_scanOpPool;
 
420
 
 
421
  // indexes and fragments
 
422
 
 
423
  /*
 
424
   * Ordered index.  Top level data structure.  The primary table (table
 
425
   * being indexed) lives in TUP.
 
426
   */
 
427
  struct Index;
 
428
  friend struct Index;
 
429
  struct Index {
 
430
    enum State {
 
431
      NotDefined = 0,
 
432
      Defining = 1,
 
433
      Online = 2,               // triggers activated and build done
 
434
      Dropping = 9
 
435
    };
 
436
    State m_state;
 
437
    DictTabInfo::TableType m_tableType;
 
438
    Uint32 m_tableId;
 
439
    Uint16 unused;
 
440
    Uint16 m_numFrags;
 
441
    Uint32 m_fragId[MaxIndexFragments];
 
442
    Uint32 m_fragPtrI[MaxIndexFragments];
 
443
    Uint32 m_descPage;          // descriptor page
 
444
    Uint16 m_descOff;           // offset within the page
 
445
    Uint16 m_numAttrs;
 
446
    bool m_storeNullKey;
 
447
    union {
 
448
    Uint32 nextPool;
 
449
    };
 
450
    Index();
 
451
  };
 
452
  typedef Ptr<Index> IndexPtr;
 
453
  ArrayPool<Index> c_indexPool;
 
454
 
 
455
  /*
 
456
   * Fragment of an index, as known to DIH/TC.  Represents the two
 
457
   * duplicate fragments known to LQH/ACC/TUP.  Includes tree header.
 
458
   * There are no maintenance operation records yet.
 
459
   */
 
460
  struct Frag;
 
461
  friend struct Frag;
 
462
  struct Frag {
 
463
    Uint32 m_tableId;           // copy from index level
 
464
    Uint32 m_indexId;
 
465
    Uint16 unused;
 
466
    Uint16 m_fragId;
 
467
    Uint32 m_descPage;          // copy from index level
 
468
    Uint16 m_descOff;
 
469
    Uint16 m_numAttrs;
 
470
    bool m_storeNullKey;
 
471
    TreeHead m_tree;
 
472
    TupLoc m_freeLoc;           // list of free index nodes
 
473
    DLList<ScanOp> m_scanList;  // current scans on this fragment
 
474
    Uint32 m_tupIndexFragPtrI;
 
475
    Uint32 m_tupTableFragPtrI;
 
476
    Uint32 m_accTableFragPtrI;
 
477
    union {
 
478
    Uint32 nextPool;
 
479
    };
 
480
    Frag(ArrayPool<ScanOp>& scanOpPool);
 
481
  };
 
482
  typedef Ptr<Frag> FragPtr;
 
483
  ArrayPool<Frag> c_fragPool;
 
484
 
 
485
  /*
 
486
   * Fragment metadata operation.
 
487
   */
 
488
  struct FragOp {
 
489
    Uint32 m_userPtr;
 
490
    Uint32 m_userRef;
 
491
    Uint32 m_indexId;
 
492
    Uint32 m_fragId;
 
493
    Uint32 m_fragPtrI;
 
494
    Uint32 m_fragNo;            // fragment number starting at zero
 
495
    Uint32 m_numAttrsRecvd;
 
496
    union {
 
497
    Uint32 nextPool;
 
498
    };
 
499
    FragOp();
 
500
  };
 
501
  typedef Ptr<FragOp> FragOpPtr;
 
502
  ArrayPool<FragOp> c_fragOpPool;
 
503
 
 
504
  // node handles
 
505
 
 
506
  /*
 
507
   * A node handle is a reference to a tree node in TUP.  It is used to
 
508
   * operate on the node.  Node handles are allocated on the stack.
 
509
   */
 
510
  struct NodeHandle;
 
511
  friend struct NodeHandle;
 
512
  struct NodeHandle {
 
513
    Frag& m_frag;               // fragment using the node
 
514
    TupLoc m_loc;               // physical node address
 
515
    TreeNode* m_node;           // pointer to node storage
 
516
    NodeHandle(Frag& frag);
 
517
    NodeHandle(const NodeHandle& node);
 
518
    NodeHandle& operator=(const NodeHandle& node);
 
519
    // check if unassigned
 
520
    bool isNull();
 
521
    // getters
 
522
    TupLoc getLink(unsigned i);
 
523
    unsigned getChilds();       // cannot spell
 
524
    unsigned getSide();
 
525
    unsigned getOccup();
 
526
    int getBalance();
 
527
    Uint32 getNodeScan();
 
528
    // setters
 
529
    void setLink(unsigned i, TupLoc loc);
 
530
    void setSide(unsigned i);
 
531
    void setOccup(unsigned n);
 
532
    void setBalance(int b);
 
533
    void setNodeScan(Uint32 scanPtrI);
 
534
    // access other parts of the node
 
535
    Data getPref();
 
536
    TreeEnt getEnt(unsigned pos);
 
537
    TreeEnt getMinMax(unsigned i);
 
538
    // for ndbrequire and ndbassert
 
539
    void progError(int line, int cause, const char* file);
 
540
  };
 
541
 
 
542
  // methods
 
543
 
 
544
  /*
 
545
   * DbtuxGen.cpp
 
546
   */
 
547
  void execCONTINUEB(Signal* signal);
 
548
  void execSTTOR(Signal* signal);
 
549
  void execREAD_CONFIG_REQ(Signal* signal);
 
550
  // utils
 
551
  void setKeyAttrs(const Frag& frag);
 
552
  void readKeyAttrs(const Frag& frag, TreeEnt ent, unsigned start, Data keyData);
 
553
  void readTablePk(const Frag& frag, TreeEnt ent, Data pkData, unsigned& pkSize);
 
554
  void copyAttrs(const Frag& frag, ConstData data1, Data data2, unsigned maxlen2 = MaxAttrDataSize);
 
555
  void unpackBound(const ScanBound& bound, Data data);
 
556
 
 
557
  /*
 
558
   * DbtuxMeta.cpp
 
559
   */
 
560
  void execTUXFRAGREQ(Signal* signal);
 
561
  void execTUX_ADD_ATTRREQ(Signal* signal);
 
562
  void execALTER_INDX_REQ(Signal* signal);
 
563
  void execDROP_TAB_REQ(Signal* signal);
 
564
  bool allocDescEnt(IndexPtr indexPtr);
 
565
  void freeDescEnt(IndexPtr indexPtr);
 
566
  void abortAddFragOp(Signal* signal);
 
567
  void dropIndex(Signal* signal, IndexPtr indexPtr, Uint32 senderRef, Uint32 senderData);
 
568
 
 
569
  /*
 
570
   * DbtuxMaint.cpp
 
571
   */
 
572
  void execTUX_MAINT_REQ(Signal* signal);
 
573
  
 
574
  /*
 
575
   * DbtuxNode.cpp
 
576
   */
 
577
  int allocNode(Signal* signal, NodeHandle& node);
 
578
  void selectNode(NodeHandle& node, TupLoc loc);
 
579
  void insertNode(NodeHandle& node);
 
580
  void deleteNode(NodeHandle& node);
 
581
  void setNodePref(NodeHandle& node);
 
582
  // node operations
 
583
  void nodePushUp(NodeHandle& node, unsigned pos, const TreeEnt& ent, Uint32 scanList);
 
584
  void nodePushUpScans(NodeHandle& node, unsigned pos);
 
585
  void nodePopDown(NodeHandle& node, unsigned pos, TreeEnt& en, Uint32* scanList);
 
586
  void nodePopDownScans(NodeHandle& node, unsigned pos);
 
587
  void nodePushDown(NodeHandle& node, unsigned pos, TreeEnt& ent, Uint32& scanList);
 
588
  void nodePushDownScans(NodeHandle& node, unsigned pos);
 
589
  void nodePopUp(NodeHandle& node, unsigned pos, TreeEnt& ent, Uint32 scanList);
 
590
  void nodePopUpScans(NodeHandle& node, unsigned pos);
 
591
  void nodeSlide(NodeHandle& dstNode, NodeHandle& srcNode, unsigned cnt, unsigned i);
 
592
  // scans linked to node
 
593
  void addScanList(NodeHandle& node, unsigned pos, Uint32 scanList);
 
594
  void removeScanList(NodeHandle& node, unsigned pos, Uint32& scanList);
 
595
  void moveScanList(NodeHandle& node, unsigned pos);
 
596
  void linkScan(NodeHandle& node, ScanOpPtr scanPtr);
 
597
  void unlinkScan(NodeHandle& node, ScanOpPtr scanPtr);
 
598
  bool islinkScan(NodeHandle& node, ScanOpPtr scanPtr);
 
599
 
 
600
  /*
 
601
   * DbtuxTree.cpp
 
602
   */
 
603
  // add entry
 
604
  void treeAdd(Frag& frag, TreePos treePos, TreeEnt ent);
 
605
  void treeAddFull(Frag& frag, NodeHandle lubNode, unsigned pos, TreeEnt ent);
 
606
  void treeAddNode(Frag& frag, NodeHandle lubNode, unsigned pos, TreeEnt ent, NodeHandle parentNode, unsigned i);
 
607
  void treeAddRebalance(Frag& frag, NodeHandle node, unsigned i);
 
608
  // remove entry
 
609
  void treeRemove(Frag& frag, TreePos treePos);
 
610
  void treeRemoveInner(Frag& frag, NodeHandle lubNode, unsigned pos);
 
611
  void treeRemoveSemi(Frag& frag, NodeHandle node, unsigned i);
 
612
  void treeRemoveLeaf(Frag& frag, NodeHandle node);
 
613
  void treeRemoveNode(Frag& frag, NodeHandle node);
 
614
  void treeRemoveRebalance(Frag& frag, NodeHandle node, unsigned i);
 
615
  // rotate
 
616
  void treeRotateSingle(Frag& frag, NodeHandle& node, unsigned i);
 
617
  void treeRotateDouble(Frag& frag, NodeHandle& node, unsigned i);
 
618
 
 
619
  /*
 
620
   * DbtuxScan.cpp
 
621
   */
 
622
  void execACC_SCANREQ(Signal* signal);
 
623
  void execTUX_BOUND_INFO(Signal* signal);
 
624
  void execNEXT_SCANREQ(Signal* signal);
 
625
  void execACC_CHECK_SCAN(Signal* signal);
 
626
  void execACCKEYCONF(Signal* signal);
 
627
  void execACCKEYREF(Signal* signal);
 
628
  void execACC_ABORTCONF(Signal* signal);
 
629
  void scanFirst(ScanOpPtr scanPtr);
 
630
  void scanFind(ScanOpPtr scanPtr);
 
631
  void scanNext(ScanOpPtr scanPtr, bool fromMaintReq);
 
632
  bool scanCheck(ScanOpPtr scanPtr, TreeEnt ent);
 
633
  bool scanVisible(ScanOpPtr scanPtr, TreeEnt ent);
 
634
  void scanClose(Signal* signal, ScanOpPtr scanPtr);
 
635
  void abortAccLockOps(Signal* signal, ScanOpPtr scanPtr);
 
636
  void addAccLockOp(ScanOpPtr scanPtr, Uint32 accLockOp);
 
637
  void removeAccLockOp(ScanOpPtr scanPtr, Uint32 accLockOp);
 
638
  void releaseScanOp(ScanOpPtr& scanPtr);
 
639
 
 
640
  /*
 
641
   * DbtuxSearch.cpp
 
642
   */
 
643
  bool searchToAdd(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos);
 
644
  bool searchToRemove(Frag& frag, ConstData searchKey, TreeEnt searchEnt, TreePos& treePos);
 
645
  void searchToScan(Frag& frag, ConstData boundInfo, unsigned boundCount, bool descending, TreePos& treePos);
 
646
  void searchToScanAscending(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos);
 
647
  void searchToScanDescending(Frag& frag, ConstData boundInfo, unsigned boundCount, TreePos& treePos);
 
648
 
 
649
  /*
 
650
   * DbtuxCmp.cpp
 
651
   */
 
652
  int cmpSearchKey(const Frag& frag, unsigned& start, ConstData searchKey, ConstData entryData, unsigned maxlen = MaxAttrDataSize);
 
653
  int cmpScanBound(const Frag& frag, unsigned dir, ConstData boundInfo, unsigned boundCount, ConstData entryData, unsigned maxlen = MaxAttrDataSize);
 
654
 
 
655
  /*
 
656
   * DbtuxStat.cpp
 
657
   */
 
658
  void execREAD_PSEUDO_REQ(Signal* signal);
 
659
  void statRecordsInRange(ScanOpPtr scanPtr, Uint32* out);
 
660
  Uint32 getEntriesBeforeOrAfter(Frag& frag, TreePos pos, unsigned idir);
 
661
  unsigned getPathToNode(NodeHandle node, Uint16* path);
 
662
 
 
663
  /*
 
664
   * DbtuxDebug.cpp
 
665
   */
 
666
  void execDUMP_STATE_ORD(Signal* signal);
 
667
#ifdef VM_TRACE
 
668
  struct PrintPar {
 
669
    char m_path[100];           // LR prefix
 
670
    unsigned m_side;            // expected side
 
671
    TupLoc m_parent;            // expected parent address
 
672
    int m_depth;                // returned depth
 
673
    unsigned m_occup;           // returned occupancy
 
674
    TreeEnt m_minmax[2];        // returned subtree min and max
 
675
    bool m_ok;                  // returned status
 
676
    PrintPar();
 
677
  };
 
678
  void printTree(Signal* signal, Frag& frag, NdbOut& out);
 
679
  void printNode(Frag& frag, NdbOut& out, TupLoc loc, PrintPar& par);
 
680
  friend class NdbOut& operator<<(NdbOut&, const TupLoc&);
 
681
  friend class NdbOut& operator<<(NdbOut&, const TreeEnt&);
 
682
  friend class NdbOut& operator<<(NdbOut&, const TreeNode&);
 
683
  friend class NdbOut& operator<<(NdbOut&, const TreeHead&);
 
684
  friend class NdbOut& operator<<(NdbOut&, const TreePos&);
 
685
  friend class NdbOut& operator<<(NdbOut&, const DescAttr&);
 
686
  friend class NdbOut& operator<<(NdbOut&, const ScanOp&);
 
687
  friend class NdbOut& operator<<(NdbOut&, const Index&);
 
688
  friend class NdbOut& operator<<(NdbOut&, const Frag&);
 
689
  friend class NdbOut& operator<<(NdbOut&, const FragOp&);
 
690
  friend class NdbOut& operator<<(NdbOut&, const NodeHandle&);
 
691
  FILE* debugFile;
 
692
  NdbOut debugOut;
 
693
  unsigned debugFlags;
 
694
  enum {
 
695
    DebugMeta = 1,              // log create and drop index
 
696
    DebugMaint = 2,             // log maintenance ops
 
697
    DebugTree = 4,              // log and check tree after each op
 
698
    DebugScan = 8,              // log scans
 
699
    DebugLock = 16              // log ACC locks
 
700
  };
 
701
  STATIC_CONST( DataFillByte = 0xa2 );
 
702
  STATIC_CONST( NodeFillByte = 0xa4 );
 
703
#endif
 
704
 
 
705
  // start up info
 
706
  Uint32 c_internalStartPhase;
 
707
  Uint32 c_typeOfStart;
 
708
 
 
709
  /*
 
710
   * Global data set at operation start.  Unpacked from index metadata.
 
711
   * Not passed as parameter to methods.  Invalid across timeslices.
 
712
   *
 
713
   * TODO inline all into index metadata
 
714
   */
 
715
 
 
716
  // index key attr ids with sizes in AttributeHeader format
 
717
  Data c_keyAttrs;
 
718
 
 
719
  // pointers to index key comparison functions
 
720
  NdbSqlUtil::Cmp** c_sqlCmp;
 
721
 
 
722
  /*
 
723
   * Other buffers used during the operation.
 
724
   */
 
725
 
 
726
  // buffer for search key data with headers
 
727
  Data c_searchKey;
 
728
 
 
729
  // buffer for current entry key data with headers
 
730
  Data c_entryKey;
 
731
 
 
732
  // buffer for scan bounds and keyinfo (primary key)
 
733
  Data c_dataBuffer;
 
734
 
 
735
  // inlined utils
 
736
  DescEnt& getDescEnt(Uint32 descPage, Uint32 descOff);
 
737
  Uint32 getTupAddr(const Frag& frag, TreeEnt ent);
 
738
  static unsigned min(unsigned x, unsigned y);
 
739
  static unsigned max(unsigned x, unsigned y);
 
740
};
 
741
 
 
742
// Dbtux::TupLoc
 
743
 
 
744
inline
 
745
Dbtux::TupLoc::TupLoc() :
 
746
  m_pageId1(RNIL >> 16),
 
747
  m_pageId2(RNIL & 0xFFFF),
 
748
  m_pageOffset(0)
 
749
{
 
750
}
 
751
 
 
752
inline
 
753
Dbtux::TupLoc::TupLoc(Uint32 pageId, Uint16 pageOffset) :
 
754
  m_pageId1(pageId >> 16),
 
755
  m_pageId2(pageId & 0xFFFF),
 
756
  m_pageOffset(pageOffset)
 
757
{
 
758
}
 
759
 
 
760
inline Uint32
 
761
Dbtux::TupLoc::getPageId() const
 
762
{
 
763
  return (m_pageId1 << 16) | m_pageId2;
 
764
}
 
765
 
 
766
inline void
 
767
Dbtux::TupLoc::setPageId(Uint32 pageId)
 
768
{
 
769
  m_pageId1 = (pageId >> 16);
 
770
  m_pageId2 = (pageId & 0xFFFF);
 
771
}
 
772
 
 
773
inline Uint32
 
774
Dbtux::TupLoc::getPageOffset() const
 
775
{
 
776
  return (Uint32)m_pageOffset;
 
777
}
 
778
 
 
779
inline void
 
780
Dbtux::TupLoc::setPageOffset(Uint32 pageOffset)
 
781
{
 
782
  m_pageOffset = (Uint16)pageOffset;
 
783
}
 
784
 
 
785
inline bool
 
786
Dbtux::TupLoc::operator==(const TupLoc& loc) const
 
787
{
 
788
  return
 
789
    m_pageId1 == loc.m_pageId1 &&
 
790
    m_pageId2 == loc.m_pageId2 &&
 
791
    m_pageOffset == loc.m_pageOffset;
 
792
}
 
793
 
 
794
inline bool
 
795
Dbtux::TupLoc::operator!=(const TupLoc& loc) const
 
796
{
 
797
  return ! (*this == loc);
 
798
}
 
799
 
 
800
// Dbtux::TreeEnt
 
801
 
 
802
inline
 
803
Dbtux::TreeEnt::TreeEnt() :
 
804
  m_tupLoc(),
 
805
  m_tupVersion(0)
 
806
{
 
807
}
 
808
 
 
809
inline bool
 
810
Dbtux::TreeEnt::eqtuple(const TreeEnt ent) const
 
811
{
 
812
  return
 
813
    m_tupLoc == ent.m_tupLoc;
 
814
}
 
815
 
 
816
inline bool
 
817
Dbtux::TreeEnt::eq(const TreeEnt ent) const
 
818
{
 
819
  return
 
820
    m_tupLoc == ent.m_tupLoc &&
 
821
    m_tupVersion == ent.m_tupVersion;
 
822
}
 
823
 
 
824
inline int
 
825
Dbtux::TreeEnt::cmp(const TreeEnt ent) const
 
826
{
 
827
  if (m_tupLoc.getPageId() < ent.m_tupLoc.getPageId())
 
828
    return -1;
 
829
  if (m_tupLoc.getPageId() > ent.m_tupLoc.getPageId())
 
830
    return +1;
 
831
  if (m_tupLoc.getPageOffset() < ent.m_tupLoc.getPageOffset())
 
832
    return -1;
 
833
  if (m_tupLoc.getPageOffset() > ent.m_tupLoc.getPageOffset())
 
834
    return +1;
 
835
  /*
 
836
   * Guess if one tuple version has wrapped around.  This is well
 
837
   * defined ordering on existing versions since versions are assigned
 
838
   * consecutively and different versions exists only on uncommitted
 
839
   * tuple.  Assuming max 2**14 uncommitted ops on same tuple.
 
840
   */
 
841
  const unsigned version_wrap_limit = (1 << (ZTUP_VERSION_BITS - 1));
 
842
  if (m_tupVersion < ent.m_tupVersion) {
 
843
    if (ent.m_tupVersion - m_tupVersion < version_wrap_limit)
 
844
      return -1;
 
845
    else
 
846
      return +1;
 
847
  }
 
848
  if (m_tupVersion > ent.m_tupVersion) {
 
849
    if (m_tupVersion - ent.m_tupVersion < version_wrap_limit)
 
850
      return +1;
 
851
    else
 
852
      return -1;
 
853
  }
 
854
  return 0;
 
855
}
 
856
 
 
857
// Dbtux::TreeNode
 
858
 
 
859
inline
 
860
Dbtux::TreeNode::TreeNode() :
 
861
  m_side(2),
 
862
  m_balance(0 + 1),
 
863
  pad1(0),
 
864
  m_occup(0),
 
865
  m_nodeScan(RNIL)
 
866
{
 
867
  m_link[0] = NullTupLoc;
 
868
  m_link[1] = NullTupLoc;
 
869
  m_link[2] = NullTupLoc;
 
870
}
 
871
 
 
872
// Dbtux::TreeHead
 
873
 
 
874
inline
 
875
Dbtux::TreeHead::TreeHead() :
 
876
  m_nodeSize(0),
 
877
  m_prefSize(0),
 
878
  m_minOccup(0),
 
879
  m_maxOccup(0),
 
880
  m_entryCount(0),
 
881
  m_root()
 
882
{
 
883
}
 
884
 
 
885
inline unsigned
 
886
Dbtux::TreeHead::getSize(AccSize acc) const
 
887
{
 
888
  switch (acc) {
 
889
  case AccNone:
 
890
    return 0;
 
891
  case AccHead:
 
892
    return NodeHeadSize;
 
893
  case AccPref:
 
894
    return NodeHeadSize + m_prefSize + 2 * TreeEntSize;
 
895
  case AccFull:
 
896
    return m_nodeSize;
 
897
  }
 
898
  return 0;
 
899
}
 
900
 
 
901
inline Dbtux::Data
 
902
Dbtux::TreeHead::getPref(TreeNode* node) const
 
903
{
 
904
  Uint32* ptr = (Uint32*)node + NodeHeadSize;
 
905
  return ptr;
 
906
}
 
907
 
 
908
inline Dbtux::TreeEnt*
 
909
Dbtux::TreeHead::getEntList(TreeNode* node) const
 
910
{
 
911
  Uint32* ptr = (Uint32*)node + NodeHeadSize + m_prefSize;
 
912
  return (TreeEnt*)ptr;
 
913
}
 
914
 
 
915
// Dbtux::TreePos
 
916
 
 
917
inline
 
918
Dbtux::TreePos::TreePos() :
 
919
  m_loc(),
 
920
  m_pos(ZNIL),
 
921
  m_dir(255)
 
922
{
 
923
}
 
924
 
 
925
// Dbtux::DescPage
 
926
 
 
927
inline
 
928
Dbtux::DescPage::DescPage() :
 
929
  m_nextPage(RNIL),
 
930
  m_numFree(ZNIL)
 
931
{
 
932
  for (unsigned i = 0; i < DescPageSize; i++) {
 
933
#ifdef VM_TRACE
 
934
    m_data[i] = 0x13571357;
 
935
#else
 
936
    m_data[i] = 0;
 
937
#endif
 
938
  }
 
939
}
 
940
 
 
941
// Dbtux::ScanOp
 
942
 
 
943
inline
 
944
Dbtux::ScanOp::ScanOp(ScanBoundPool& scanBoundPool) :
 
945
  m_state(Undef),
 
946
  m_lockwait(false),
 
947
  m_userPtr(RNIL),
 
948
  m_userRef(RNIL),
 
949
  m_tableId(RNIL),
 
950
  m_indexId(RNIL),
 
951
  m_fragPtrI(RNIL),
 
952
  m_transId1(0),
 
953
  m_transId2(0),
 
954
  m_savePointId(0),
 
955
  m_accLockOp(RNIL),
 
956
  m_accLockOps(),
 
957
  m_readCommitted(0),
 
958
  m_lockMode(0),
 
959
  m_descending(0),
 
960
  m_boundMin(scanBoundPool),
 
961
  m_boundMax(scanBoundPool),
 
962
  m_scanPos(),
 
963
  m_scanEnt(),
 
964
  m_nodeScan(RNIL)
 
965
{
 
966
  m_bound[0] = &m_boundMin;
 
967
  m_bound[1] = &m_boundMax;
 
968
  m_boundCnt[0] = 0;
 
969
  m_boundCnt[1] = 0;
 
970
}
 
971
 
 
972
// Dbtux::Index
 
973
 
 
974
inline
 
975
Dbtux::Index::Index() :
 
976
  m_state(NotDefined),
 
977
  m_tableType(DictTabInfo::UndefTableType),
 
978
  m_tableId(RNIL),
 
979
  m_numFrags(0),
 
980
  m_descPage(RNIL),
 
981
  m_descOff(0),
 
982
  m_numAttrs(0),
 
983
  m_storeNullKey(false)
 
984
{
 
985
  for (unsigned i = 0; i < MaxIndexFragments; i++) {
 
986
    m_fragId[i] = ZNIL;
 
987
    m_fragPtrI[i] = RNIL;
 
988
  };
 
989
}
 
990
 
 
991
// Dbtux::Frag
 
992
 
 
993
inline
 
994
Dbtux::Frag::Frag(ArrayPool<ScanOp>& scanOpPool) :
 
995
  m_tableId(RNIL),
 
996
  m_indexId(RNIL),
 
997
  m_fragId(ZNIL),
 
998
  m_descPage(RNIL),
 
999
  m_descOff(0),
 
1000
  m_numAttrs(ZNIL),
 
1001
  m_storeNullKey(false),
 
1002
  m_tree(),
 
1003
  m_freeLoc(),
 
1004
  m_scanList(scanOpPool),
 
1005
  m_tupIndexFragPtrI(RNIL)
 
1006
{
 
1007
  m_tupTableFragPtrI = RNIL;
 
1008
  m_accTableFragPtrI = RNIL;
 
1009
}
 
1010
 
 
1011
// Dbtux::FragOp
 
1012
 
 
1013
inline
 
1014
Dbtux::FragOp::FragOp() :
 
1015
  m_userPtr(RNIL),
 
1016
  m_userRef(RNIL),
 
1017
  m_indexId(RNIL),
 
1018
  m_fragId(ZNIL),
 
1019
  m_fragPtrI(RNIL),
 
1020
  m_fragNo(ZNIL),
 
1021
  m_numAttrsRecvd(ZNIL)
 
1022
{
 
1023
}
 
1024
 
 
1025
// Dbtux::NodeHandle
 
1026
 
 
1027
inline
 
1028
Dbtux::NodeHandle::NodeHandle(Frag& frag) :
 
1029
  m_frag(frag),
 
1030
  m_loc(),
 
1031
  m_node(0)
 
1032
{
 
1033
}
 
1034
 
 
1035
inline
 
1036
Dbtux::NodeHandle::NodeHandle(const NodeHandle& node) :
 
1037
  m_frag(node.m_frag),
 
1038
  m_loc(node.m_loc),
 
1039
  m_node(node.m_node)
 
1040
{
 
1041
}
 
1042
 
 
1043
inline Dbtux::NodeHandle&
 
1044
Dbtux::NodeHandle::operator=(const NodeHandle& node)
 
1045
{
 
1046
  ndbassert(&m_frag == &node.m_frag);
 
1047
  m_loc = node.m_loc;
 
1048
  m_node = node.m_node;
 
1049
  return *this;
 
1050
}
 
1051
 
 
1052
inline bool
 
1053
Dbtux::NodeHandle::isNull()
 
1054
{
 
1055
  return m_node == 0;
 
1056
}
 
1057
 
 
1058
inline Dbtux::TupLoc
 
1059
Dbtux::NodeHandle::getLink(unsigned i)
 
1060
{
 
1061
  ndbrequire(i <= 2);
 
1062
  return m_node->m_link[i];
 
1063
}
 
1064
 
 
1065
inline unsigned
 
1066
Dbtux::NodeHandle::getChilds()
 
1067
{
 
1068
  return (m_node->m_link[0] != NullTupLoc) + (m_node->m_link[1] != NullTupLoc);
 
1069
}
 
1070
 
 
1071
inline unsigned
 
1072
Dbtux::NodeHandle::getSide()
 
1073
{
 
1074
  return m_node->m_side;
 
1075
}
 
1076
 
 
1077
inline unsigned
 
1078
Dbtux::NodeHandle::getOccup()
 
1079
{
 
1080
  return m_node->m_occup;
 
1081
}
 
1082
 
 
1083
inline int
 
1084
Dbtux::NodeHandle::getBalance()
 
1085
{
 
1086
  return (int)m_node->m_balance - 1;
 
1087
}
 
1088
 
 
1089
inline Uint32
 
1090
Dbtux::NodeHandle::getNodeScan()
 
1091
{
 
1092
  return m_node->m_nodeScan;
 
1093
}
 
1094
 
 
1095
inline void
 
1096
Dbtux::NodeHandle::setLink(unsigned i, TupLoc loc)
 
1097
{
 
1098
  ndbrequire(i <= 2);
 
1099
  m_node->m_link[i] = loc;
 
1100
}
 
1101
 
 
1102
inline void
 
1103
Dbtux::NodeHandle::setSide(unsigned i)
 
1104
{
 
1105
  ndbrequire(i <= 2);
 
1106
  m_node->m_side = i;
 
1107
}
 
1108
 
 
1109
inline void
 
1110
Dbtux::NodeHandle::setOccup(unsigned n)
 
1111
{
 
1112
  TreeHead& tree = m_frag.m_tree;
 
1113
  ndbrequire(n <= tree.m_maxOccup);
 
1114
  m_node->m_occup = n;
 
1115
}
 
1116
 
 
1117
inline void
 
1118
Dbtux::NodeHandle::setBalance(int b)
 
1119
{
 
1120
  ndbrequire(abs(b) <= 1);
 
1121
  m_node->m_balance = (unsigned)(b + 1);
 
1122
}
 
1123
 
 
1124
inline void
 
1125
Dbtux::NodeHandle::setNodeScan(Uint32 scanPtrI)
 
1126
{
 
1127
  m_node->m_nodeScan = scanPtrI;
 
1128
}
 
1129
 
 
1130
inline Dbtux::Data
 
1131
Dbtux::NodeHandle::getPref()
 
1132
{
 
1133
  TreeHead& tree = m_frag.m_tree;
 
1134
  return tree.getPref(m_node);
 
1135
}
 
1136
 
 
1137
inline Dbtux::TreeEnt
 
1138
Dbtux::NodeHandle::getEnt(unsigned pos)
 
1139
{
 
1140
  TreeHead& tree = m_frag.m_tree;
 
1141
  TreeEnt* entList = tree.getEntList(m_node);
 
1142
  const unsigned occup = m_node->m_occup;
 
1143
  ndbrequire(pos < occup);
 
1144
  return entList[(1 + pos) % occup];
 
1145
}
 
1146
 
 
1147
inline Dbtux::TreeEnt
 
1148
Dbtux::NodeHandle::getMinMax(unsigned i)
 
1149
{
 
1150
  const unsigned occup = m_node->m_occup;
 
1151
  ndbrequire(i <= 1 && occup != 0);
 
1152
  return getEnt(i == 0 ? 0 : occup - 1);
 
1153
}
 
1154
 
 
1155
// parameters for methods
 
1156
 
 
1157
#ifdef VM_TRACE
 
1158
inline
 
1159
Dbtux::PrintPar::PrintPar() :
 
1160
  // caller fills in
 
1161
  m_path(),
 
1162
  m_side(255),
 
1163
  m_parent(),
 
1164
  // default return values
 
1165
  m_depth(0),
 
1166
  m_occup(0),
 
1167
  m_ok(true)
 
1168
{
 
1169
}
 
1170
#endif
 
1171
 
 
1172
// utils
 
1173
 
 
1174
inline Dbtux::DescEnt&
 
1175
Dbtux::getDescEnt(Uint32 descPage, Uint32 descOff)
 
1176
{
 
1177
  DescPagePtr pagePtr;
 
1178
  pagePtr.i = descPage;
 
1179
  c_descPagePool.getPtr(pagePtr);
 
1180
  ndbrequire(descOff < DescPageSize);
 
1181
  DescEnt* descEnt = (DescEnt*)&pagePtr.p->m_data[descOff];
 
1182
  return *descEnt;
 
1183
}
 
1184
 
 
1185
inline Uint32
 
1186
Dbtux::getTupAddr(const Frag& frag, TreeEnt ent)
 
1187
{
 
1188
  const Uint32 tableFragPtrI = frag.m_tupTableFragPtrI;
 
1189
  const TupLoc tupLoc = ent.m_tupLoc;
 
1190
  Uint32 tupAddr = NullTupAddr;
 
1191
  c_tup->tuxGetTupAddr(tableFragPtrI, tupLoc.getPageId(), tupLoc.getPageOffset(), tupAddr);
 
1192
  jamEntry();
 
1193
  return tupAddr;
 
1194
}
 
1195
 
 
1196
inline unsigned
 
1197
Dbtux::min(unsigned x, unsigned y)
 
1198
{
 
1199
  return x < y ? x : y;
 
1200
}
 
1201
 
 
1202
inline unsigned
 
1203
Dbtux::max(unsigned x, unsigned y)
 
1204
{
 
1205
  return x > y ? x : y;
 
1206
}
 
1207
 
 
1208
#endif