1
/* Copyright (C) 2003 MySQL AB
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.
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.
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 */
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>
29
#include <dbtup/Dbtup.hpp>
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>
47
#include <OutputStream.hpp>
54
#define jam() jamLine(10000 + __LINE__)
55
#define jamEntry() jamEntryLine(10000 + __LINE__)
58
#define jam() jamLine(20000 + __LINE__)
59
#define jamEntry() jamEntryLine(20000 + __LINE__)
61
#ifdef DBTUX_MAINT_CPP
62
#define jam() jamLine(30000 + __LINE__)
63
#define jamEntry() jamEntryLine(30000 + __LINE__)
66
#define jam() jamLine(40000 + __LINE__)
67
#define jamEntry() jamEntryLine(40000 + __LINE__)
70
#define jam() jamLine(50000 + __LINE__)
71
#define jamEntry() jamEntryLine(50000 + __LINE__)
74
#define jam() jamLine(60000 + __LINE__)
75
#define jamEntry() jamEntryLine(60000 + __LINE__)
77
#ifdef DBTUX_SEARCH_CPP
78
#define jam() jamLine(70000 + __LINE__)
79
#define jamEntry() jamEntryLine(70000 + __LINE__)
82
#define jam() jamLine(80000 + __LINE__)
83
#define jamEntry() jamEntryLine(80000 + __LINE__)
86
#define jam() jamLine(90000 + __LINE__)
87
#define jamEntry() jamEntryLine(90000 + __LINE__)
89
#ifdef DBTUX_DEBUG_CPP
90
#define jam() jamLine(100000 + __LINE__)
91
#define jamEntry() jamEntryLine(100000 + __LINE__)
94
#define jam() jamLine(__LINE__)
95
#define jamEntry() jamEntryLine(__LINE__)
103
class Dbtux : public SimulatedBlock {
105
Dbtux(Block_context& ctx);
108
// pointer to TUP instance in this thread
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 );
117
STATIC_CONST( DescPageSize = 256 );
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);
126
// forward declarations
129
// Pointer to array of Uint32 represents attribute data and bounds
131
typedef Uint32 *Data;
132
inline AttributeHeader& ah(Data data) {
133
return *reinterpret_cast<AttributeHeader*>(data);
136
typedef const Uint32* ConstData;
137
inline const AttributeHeader& ah(ConstData data) {
138
return *reinterpret_cast<const AttributeHeader*>(data);
141
// AttributeHeader size is assumed to be 1 word
142
STATIC_CONST( AttributeHeaderSize = 1 );
145
* Logical tuple address, "local key". Identifies table tuples.
147
typedef Uint32 TupAddr;
148
STATIC_CONST( NullTupAddr = (Uint32)-1 );
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.
155
* To avoid wasting an Uint16 the pageid is split in two.
159
Uint16 m_pageId1; // page i-value (big-endian)
161
Uint16 m_pageOffset; // page offset in words
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;
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().
178
#define NullTupLoc TupLoc()
183
* Tree entry. Points to a tuple in primary table via physical
184
* address of "original" tuple and tuple version.
186
* ZTUP_VERSION_BITS must be 15 (or less).
189
friend struct TreeEnt;
191
TupLoc m_tupLoc; // address of original tuple
192
unsigned m_tupVersion : 15; // version
195
bool eqtuple(const TreeEnt ent) const;
196
bool eq(const TreeEnt ent) const;
197
int cmp(const TreeEnt ent) const;
199
STATIC_CONST( TreeEntSize = sizeof(TreeEnt) >> 2 );
200
static const TreeEnt NullTreeEnt;
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.
207
* struct TreeNode part 1, size 6 words
208
* min prefix part 2, size TreeHead::m_prefSize
211
* rest of entries part 4
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.
219
friend 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
225
Uint8 m_occup; // current number of entries
226
Uint32 m_nodeScan; // list of scans at this node
229
STATIC_CONST( NodeHeadSize = sizeof(TreeNode) >> 2 );
232
* Tree node "access size" was for an early version with signal
233
* interface to TUP. It is now used only to compute sizes.
237
AccHead = 1, // part 1
238
AccPref = 2, // parts 1-3
239
AccFull = 3 // parts 1-5
243
* Tree header. There is one in each fragment. Contains tree
244
* parameters and address of root node.
247
friend 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
257
unsigned getSize(AccSize acc) const;
258
Data getPref(TreeNode* node) const;
259
TreeEnt* getEntList(TreeNode* node) const;
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
270
friend struct TreePos;
272
TupLoc m_loc; // physical node address
273
Uint16 m_pos; // position 0 to m_occup
274
Uint8 m_dir; // see scanNext
281
* Descriptor page. The "hot" metadata for an index is stored as
282
* a contiguous array of words on some page.
285
friend struct DescPage;
288
Uint32 m_numFree; // number of free words
290
Uint32 m_data[DescPageSize];
295
typedef Ptr<DescPage> DescPagePtr;
296
ArrayPool<DescPage> c_descPagePool;
297
Uint32 c_descPageList;
300
* Header for index metadata. Size must be multiple of word size.
303
unsigned m_indexId : 24;
306
STATIC_CONST( DescHeadSize = sizeof(DescHead) >> 2 );
309
* Attribute metadata. Size must be multiple of word size.
311
* Prefix comparison of char data must use strxfrm and binary
312
* comparison. The charset is currently unused.
315
Uint32 m_attrDesc; // standard AttributeDescriptor
316
Uint16 m_primaryAttrId;
317
unsigned m_typeId : 6;
318
unsigned m_charset : 10;
320
STATIC_CONST( DescAttrSize = sizeof(DescAttr) >> 2 );
323
* Complete metadata for one index. The array of attributes has
326
friend struct DescEnt;
329
DescAttr m_descAttr[1]; // variable size data
335
* Scan bounds are stored in linked list of segments.
337
typedef DataBuffer<ScanBoundSegmentSize> ScanBound;
338
typedef DataBuffer<ScanBoundSegmentSize>::ConstDataBufferIterator ScanBoundIterator;
339
typedef DataBuffer<ScanBoundSegmentSize>::DataBufferPool ScanBoundPool;
340
ScanBoundPool c_scanBoundPool;
351
typedef Ptr<ScanLock> ScanLockPtr;
352
ArrayPool<ScanLock> c_scanLockPool;
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.
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.
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.
372
friend struct ScanOp;
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
388
Uint32 m_userPtr; // scanptr.i in LQH
396
Uint32 m_savePointId;
397
// lock waited for or obtained and not yet passed to LQH
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
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)
416
ScanOp(ScanBoundPool& scanBoundPool);
418
typedef Ptr<ScanOp> ScanOpPtr;
419
ArrayPool<ScanOp> c_scanOpPool;
421
// indexes and fragments
424
* Ordered index. Top level data structure. The primary table (table
425
* being indexed) lives in TUP.
433
Online = 2, // triggers activated and build done
437
DictTabInfo::TableType m_tableType;
441
Uint32 m_fragId[MaxIndexFragments];
442
Uint32 m_fragPtrI[MaxIndexFragments];
443
Uint32 m_descPage; // descriptor page
444
Uint16 m_descOff; // offset within the page
452
typedef Ptr<Index> IndexPtr;
453
ArrayPool<Index> c_indexPool;
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.
463
Uint32 m_tableId; // copy from index level
467
Uint32 m_descPage; // copy from index level
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;
480
Frag(ArrayPool<ScanOp>& scanOpPool);
482
typedef Ptr<Frag> FragPtr;
483
ArrayPool<Frag> c_fragPool;
486
* Fragment metadata operation.
494
Uint32 m_fragNo; // fragment number starting at zero
495
Uint32 m_numAttrsRecvd;
501
typedef Ptr<FragOp> FragOpPtr;
502
ArrayPool<FragOp> c_fragOpPool;
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.
511
friend 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
522
TupLoc getLink(unsigned i);
523
unsigned getChilds(); // cannot spell
527
Uint32 getNodeScan();
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
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);
547
void execCONTINUEB(Signal* signal);
548
void execSTTOR(Signal* signal);
549
void execREAD_CONFIG_REQ(Signal* signal);
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);
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);
572
void execTUX_MAINT_REQ(Signal* signal);
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);
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);
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);
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);
616
void treeRotateSingle(Frag& frag, NodeHandle& node, unsigned i);
617
void treeRotateDouble(Frag& frag, NodeHandle& node, unsigned i);
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);
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);
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);
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);
666
void execDUMP_STATE_ORD(Signal* signal);
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
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&);
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
701
STATIC_CONST( DataFillByte = 0xa2 );
702
STATIC_CONST( NodeFillByte = 0xa4 );
706
Uint32 c_internalStartPhase;
707
Uint32 c_typeOfStart;
710
* Global data set at operation start. Unpacked from index metadata.
711
* Not passed as parameter to methods. Invalid across timeslices.
713
* TODO inline all into index metadata
716
// index key attr ids with sizes in AttributeHeader format
719
// pointers to index key comparison functions
720
NdbSqlUtil::Cmp** c_sqlCmp;
723
* Other buffers used during the operation.
726
// buffer for search key data with headers
729
// buffer for current entry key data with headers
732
// buffer for scan bounds and keyinfo (primary key)
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);
745
Dbtux::TupLoc::TupLoc() :
746
m_pageId1(RNIL >> 16),
747
m_pageId2(RNIL & 0xFFFF),
753
Dbtux::TupLoc::TupLoc(Uint32 pageId, Uint16 pageOffset) :
754
m_pageId1(pageId >> 16),
755
m_pageId2(pageId & 0xFFFF),
756
m_pageOffset(pageOffset)
761
Dbtux::TupLoc::getPageId() const
763
return (m_pageId1 << 16) | m_pageId2;
767
Dbtux::TupLoc::setPageId(Uint32 pageId)
769
m_pageId1 = (pageId >> 16);
770
m_pageId2 = (pageId & 0xFFFF);
774
Dbtux::TupLoc::getPageOffset() const
776
return (Uint32)m_pageOffset;
780
Dbtux::TupLoc::setPageOffset(Uint32 pageOffset)
782
m_pageOffset = (Uint16)pageOffset;
786
Dbtux::TupLoc::operator==(const TupLoc& loc) const
789
m_pageId1 == loc.m_pageId1 &&
790
m_pageId2 == loc.m_pageId2 &&
791
m_pageOffset == loc.m_pageOffset;
795
Dbtux::TupLoc::operator!=(const TupLoc& loc) const
797
return ! (*this == loc);
803
Dbtux::TreeEnt::TreeEnt() :
810
Dbtux::TreeEnt::eqtuple(const TreeEnt ent) const
813
m_tupLoc == ent.m_tupLoc;
817
Dbtux::TreeEnt::eq(const TreeEnt ent) const
820
m_tupLoc == ent.m_tupLoc &&
821
m_tupVersion == ent.m_tupVersion;
825
Dbtux::TreeEnt::cmp(const TreeEnt ent) const
827
if (m_tupLoc.getPageId() < ent.m_tupLoc.getPageId())
829
if (m_tupLoc.getPageId() > ent.m_tupLoc.getPageId())
831
if (m_tupLoc.getPageOffset() < ent.m_tupLoc.getPageOffset())
833
if (m_tupLoc.getPageOffset() > ent.m_tupLoc.getPageOffset())
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.
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)
848
if (m_tupVersion > ent.m_tupVersion) {
849
if (m_tupVersion - ent.m_tupVersion < version_wrap_limit)
860
Dbtux::TreeNode::TreeNode() :
867
m_link[0] = NullTupLoc;
868
m_link[1] = NullTupLoc;
869
m_link[2] = NullTupLoc;
875
Dbtux::TreeHead::TreeHead() :
886
Dbtux::TreeHead::getSize(AccSize acc) const
894
return NodeHeadSize + m_prefSize + 2 * TreeEntSize;
902
Dbtux::TreeHead::getPref(TreeNode* node) const
904
Uint32* ptr = (Uint32*)node + NodeHeadSize;
908
inline Dbtux::TreeEnt*
909
Dbtux::TreeHead::getEntList(TreeNode* node) const
911
Uint32* ptr = (Uint32*)node + NodeHeadSize + m_prefSize;
912
return (TreeEnt*)ptr;
918
Dbtux::TreePos::TreePos() :
928
Dbtux::DescPage::DescPage() :
932
for (unsigned i = 0; i < DescPageSize; i++) {
934
m_data[i] = 0x13571357;
944
Dbtux::ScanOp::ScanOp(ScanBoundPool& scanBoundPool) :
960
m_boundMin(scanBoundPool),
961
m_boundMax(scanBoundPool),
966
m_bound[0] = &m_boundMin;
967
m_bound[1] = &m_boundMax;
975
Dbtux::Index::Index() :
977
m_tableType(DictTabInfo::UndefTableType),
983
m_storeNullKey(false)
985
for (unsigned i = 0; i < MaxIndexFragments; i++) {
987
m_fragPtrI[i] = RNIL;
994
Dbtux::Frag::Frag(ArrayPool<ScanOp>& scanOpPool) :
1001
m_storeNullKey(false),
1004
m_scanList(scanOpPool),
1005
m_tupIndexFragPtrI(RNIL)
1007
m_tupTableFragPtrI = RNIL;
1008
m_accTableFragPtrI = RNIL;
1014
Dbtux::FragOp::FragOp() :
1021
m_numAttrsRecvd(ZNIL)
1025
// Dbtux::NodeHandle
1028
Dbtux::NodeHandle::NodeHandle(Frag& frag) :
1036
Dbtux::NodeHandle::NodeHandle(const NodeHandle& node) :
1037
m_frag(node.m_frag),
1043
inline Dbtux::NodeHandle&
1044
Dbtux::NodeHandle::operator=(const NodeHandle& node)
1046
ndbassert(&m_frag == &node.m_frag);
1048
m_node = node.m_node;
1053
Dbtux::NodeHandle::isNull()
1058
inline Dbtux::TupLoc
1059
Dbtux::NodeHandle::getLink(unsigned i)
1062
return m_node->m_link[i];
1066
Dbtux::NodeHandle::getChilds()
1068
return (m_node->m_link[0] != NullTupLoc) + (m_node->m_link[1] != NullTupLoc);
1072
Dbtux::NodeHandle::getSide()
1074
return m_node->m_side;
1078
Dbtux::NodeHandle::getOccup()
1080
return m_node->m_occup;
1084
Dbtux::NodeHandle::getBalance()
1086
return (int)m_node->m_balance - 1;
1090
Dbtux::NodeHandle::getNodeScan()
1092
return m_node->m_nodeScan;
1096
Dbtux::NodeHandle::setLink(unsigned i, TupLoc loc)
1099
m_node->m_link[i] = loc;
1103
Dbtux::NodeHandle::setSide(unsigned i)
1110
Dbtux::NodeHandle::setOccup(unsigned n)
1112
TreeHead& tree = m_frag.m_tree;
1113
ndbrequire(n <= tree.m_maxOccup);
1114
m_node->m_occup = n;
1118
Dbtux::NodeHandle::setBalance(int b)
1120
ndbrequire(abs(b) <= 1);
1121
m_node->m_balance = (unsigned)(b + 1);
1125
Dbtux::NodeHandle::setNodeScan(Uint32 scanPtrI)
1127
m_node->m_nodeScan = scanPtrI;
1131
Dbtux::NodeHandle::getPref()
1133
TreeHead& tree = m_frag.m_tree;
1134
return tree.getPref(m_node);
1137
inline Dbtux::TreeEnt
1138
Dbtux::NodeHandle::getEnt(unsigned pos)
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];
1147
inline Dbtux::TreeEnt
1148
Dbtux::NodeHandle::getMinMax(unsigned i)
1150
const unsigned occup = m_node->m_occup;
1151
ndbrequire(i <= 1 && occup != 0);
1152
return getEnt(i == 0 ? 0 : occup - 1);
1155
// parameters for methods
1159
Dbtux::PrintPar::PrintPar() :
1164
// default return values
1174
inline Dbtux::DescEnt&
1175
Dbtux::getDescEnt(Uint32 descPage, Uint32 descOff)
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];
1186
Dbtux::getTupAddr(const Frag& frag, TreeEnt ent)
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);
1197
Dbtux::min(unsigned x, unsigned y)
1199
return x < y ? x : y;
1203
Dbtux::max(unsigned x, unsigned y)
1205
return x > y ? x : y;