1 /*
2    Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #ifndef DBTUX_H
26 #define DBTUX_H
27 
28 #include <ndb_limits.h>
29 #include <SimulatedBlock.hpp>
30 #include <AttributeDescriptor.hpp>
31 #include <AttributeHeader.hpp>
32 #include <ArrayPool.hpp>
33 #include <DataBuffer.hpp>
34 #include <IntrusiveList.hpp>
35 #include <md5_hash.hpp>
36 
37 // big brother
38 #include <dbtup/Dbtup.hpp>
39 #include <dblqh/Dblqh.hpp>
40 
41 // packed index keys and bounds
42 #include <NdbPack.hpp>
43 
44 // signal classes
45 #include <signaldata/DictTabInfo.hpp>
46 #include <signaldata/TuxContinueB.hpp>
47 #include <signaldata/TupFrag.hpp>
48 #include <signaldata/AlterIndxImpl.hpp>
49 #include <signaldata/DropTab.hpp>
50 #include <signaldata/TuxMaint.hpp>
51 #include <signaldata/AccScan.hpp>
52 #include <signaldata/TuxBound.hpp>
53 #include <signaldata/NextScan.hpp>
54 #include <signaldata/AccLock.hpp>
55 #include <signaldata/DumpStateOrd.hpp>
56 #include <signaldata/IndexStatSignal.hpp>
57 
58 // debug
59 #ifdef VM_TRACE
60 #include <NdbOut.hpp>
61 #include <OutputStream.hpp>
62 #endif
63 
64 
65 #define JAM_FILE_ID 374
66 
67 
68 #undef max
69 #undef min
70 
71 class Configuration;
72 struct mt_BuildIndxCtx;
73 
74 class Dbtux : public SimulatedBlock {
75   friend class DbtuxProxy;
76   friend struct mt_BuildIndxCtx;
77   friend Uint32 Dbtux_mt_buildIndexFragment_wrapper_C(void*);
78 public:
79   Dbtux(Block_context& ctx, Uint32 instanceNumber = 0);
80   virtual ~Dbtux();
81 
82   void prepare_scan_ctx(Uint32 scanPtrI);
83   // pointer to TUP and LQH instance in this thread
84   Dbtup* c_tup;
85   Dblqh* c_lqh;
86   void execTUX_BOUND_INFO(Signal* signal);
87   void execREAD_PSEUDO_REQ(Signal* signal);
88 
89 private:
90   // sizes are in words (Uint32)
91   STATIC_CONST( MaxIndexFragments = MAX_FRAG_PER_LQH );
92   STATIC_CONST( MaxIndexAttributes = MAX_ATTRIBUTES_IN_INDEX );
93   STATIC_CONST( MaxAttrDataSize = 2 * MAX_ATTRIBUTES_IN_INDEX + MAX_KEY_SIZE_IN_WORDS );
94   STATIC_CONST( MaxXfrmDataSize = MaxAttrDataSize * MAX_XFRM_MULTIPLY);
95 public:
96   STATIC_CONST( DescPageSize = 512 );
97 private:
98   STATIC_CONST( MaxTreeNodeSize = MAX_TTREE_NODE_SIZE );
99   STATIC_CONST( MaxPrefSize = MAX_TTREE_PREF_SIZE );
100   STATIC_CONST( ScanBoundSegmentSize = 7 );
101   STATIC_CONST( MaxAccLockOps = MAX_PARALLEL_OP_PER_SCAN );
102   STATIC_CONST( MaxTreeDepth = 32 );    // strict
103 #ifdef VM_TRACE
104   // for TuxCtx::c_debugBuffer
105   STATIC_CONST( DebugBufferBytes = (MaxAttrDataSize << 2) );
106 #endif
107   BLOCK_DEFINES(Dbtux);
108 
109   // forward declarations
110   struct TuxCtx;
111 
112   // AttributeHeader size is assumed to be 1 word
113   STATIC_CONST( AttributeHeaderSize = 1 );
114 
115   /*
116    * Logical tuple address, "local key".  Identifies table tuples.
117    */
118   typedef Uint32 TupAddr;
119   STATIC_CONST( NullTupAddr = (Uint32)-1 );
120 
121   /*
122    * Physical tuple address in TUP.  Provides fast access to table tuple
123    * or index node.  Valid within the db node and across timeslices.
124    * Not valid between db nodes or across restarts.
125    *
126    * To avoid wasting an Uint16 the pageid is split in two.
127    */
128   struct TupLoc {
129   private:
130     Uint16 m_pageId1;           // page i-value (big-endian)
131     Uint16 m_pageId2;
132     Uint16 m_pageOffset;        // page offset in words
133   public:
134     TupLoc();
135     TupLoc(Uint32 pageId, Uint16 pageOffset);
136     Uint32 getPageId() const;
137     void setPageId(Uint32 pageId);
138     Uint32 getPageOffset() const;
139     void setPageOffset(Uint32 pageOffset);
140     bool operator==(const TupLoc& loc) const;
141     bool operator!=(const TupLoc& loc) const;
142   };
143 
144   /*
145    * There is no const member NullTupLoc since the compiler may not be
146    * able to optimize it to TupLoc() constants.  Instead null values are
147    * constructed on the stack with TupLoc().
148    */
149 #define NullTupLoc TupLoc()
150 
151   // tree definitions
152 
153   /*
154    * Tree entry.  Points to a tuple in primary table via physical
155    * address of "original" tuple and tuple version.
156    *
157    * ZTUP_VERSION_BITS must be 15 (or less).
158    */
159   struct TreeEnt;
160   friend struct TreeEnt;
161   struct TreeEnt {
162     TupLoc m_tupLoc;            // address of original tuple
163     unsigned m_tupVersion : 15; // version
164     TreeEnt();
165     // methods
166     bool eqtuple(const TreeEnt ent) const;
167     bool eq(const TreeEnt ent) const;
168     int cmp(const TreeEnt ent) const;
169   };
170   STATIC_CONST( TreeEntSize = sizeof(TreeEnt) >> 2 );
171   static const TreeEnt NullTreeEnt;
172 
173   /*
174    * Tree node has 3 parts:
175    *
176    * 1) struct TreeNode - the header (6 words)
177    * 2) some key values for min entry - the min prefix
178    * 3) list of TreeEnt (each 2 words)
179    *
180    * There are 3 links to other nodes: left child, right child, parent.
181    * Occupancy (number of entries) is at least 1 except temporarily when
182    * a node is about to be removed.
183    */
184   struct TreeNode;
185   friend struct TreeNode;
186   struct TreeNode {
187     TupLoc m_link[3];           // link to 0-left child 1-right child 2-parent
188     unsigned m_side : 2;        // we are 0-left child 1-right child 2-root
189     unsigned m_balance : 2;     // balance -1, 0, +1 plus 1 for Solaris CC
190     unsigned pad1 : 4;
191     Uint8 m_occup;              // current number of entries
192     Uint32 m_nodeScan;          // list of scans at this node
193     TreeNode();
194   };
195   STATIC_CONST( NodeHeadSize = sizeof(TreeNode) >> 2 );
196 
197   /*
198    * Tree header.  There is one in each fragment.  Contains tree
199    * parameters and address of root node.
200    */
201   struct TreeHead;
202   friend struct TreeHead;
203   struct TreeHead {
204     Uint8 m_nodeSize;           // words in tree node
205     Uint8 m_prefSize;           // words in min prefix
206     Uint8 m_minOccup;           // min entries in internal node
207     Uint8 m_maxOccup;           // max entries in node
208     TupLoc m_root;              // root node
209     TreeHead();
210     // methods
211     Uint32* getPref(TreeNode* node) const;
212     TreeEnt* getEntList(TreeNode* node) const;
213   };
214 
215   /*
216    * Tree position.  Specifies node, position within node (from 0 to
217    * m_occup), and whether the position is at an existing entry or
218    * before one (if any).  Position m_occup points past the node and is
219    * also represented by position 0 of next node.  Includes direction
220    * used by scan.
221    */
222   struct TreePos;
223   friend struct TreePos;
224   struct TreePos {
225     TupLoc m_loc;               // physical node address
226     Uint32 m_pos;               // position 0 to m_occup
227     Uint32 m_dir;                // see scanNext
228     TreePos();
229   };
230 
231   // packed metadata
232 
233   /*
234    * Descriptor page.  The "hot" metadata for an index is stored as
235    * contiguous array of words on some page.  It has 3 parts:
236    * 1) DescHead
237    * 2) array of NdbPack::Type used by NdbPack::Spec of index key
238    * 3) array of attr headers for reading index key values from TUP
239    */
240   struct DescPage;
241   friend struct DescPage;
242   struct DescPage {
243     Uint32 m_nextPage;
244     Uint32 m_numFree;           // number of free words
245     union {
246     Uint32 m_data[DescPageSize];
247     Uint32 nextPool;
248     };
249     DescPage();
250   };
251   typedef Ptr<DescPage> DescPagePtr;
252   typedef ArrayPool<DescPage> DescPage_pool;
253 
254   DescPage_pool c_descPagePool;
255   Uint32 c_descPageList;
256 
257   struct DescHead {
258     Uint32 m_indexId;
259     Uint16 m_numAttrs;
260     Uint16 m_magic;
261     enum { Magic = 0xDE5C };
262   };
263   STATIC_CONST( DescHeadSize = sizeof(DescHead) >> 2 );
264 
265   typedef NdbPack::Type KeyType;
266   typedef NdbPack::Spec KeySpec;
267   STATIC_CONST( KeyTypeSize = sizeof(KeyType) >> 2 );
268 
269   typedef NdbPack::DataC KeyDataC;
270   typedef NdbPack::Data KeyData;
271   typedef NdbPack::BoundC KeyBoundC;
272   typedef NdbPack::Bound KeyBound;
273   typedef NdbPack::DataArray KeyDataArray;
274   typedef NdbPack::BoundArray KeyBoundArray;
275 
276   // range scan
277 
278   /*
279    * ScanBound instances are members of ScanOp.  Bound data is stored in
280    * a separate segmented buffer pool.
281    */
282   typedef DataBufferSegment<ScanBoundSegmentSize, RT_DBTUX_SCAN_BOUND>
283             ScanBoundSegment;
284   typedef TransientPool<ScanBoundSegment> ScanBoundBuffer_pool;
285   STATIC_CONST(DBTUX_SCAN_BOUND_TRANSIENT_POOL_INDEX = 2);
286   typedef DataBuffer<ScanBoundSegmentSize,
287                      ScanBoundBuffer_pool,
288                      RT_DBTUX_SCAN_BOUND> ScanBoundBuffer;
289   typedef LocalDataBuffer<ScanBoundSegmentSize,
290                           ScanBoundBuffer_pool,
291                           RT_DBTUX_SCAN_BOUND> LocalScanBoundBuffer;
292   struct ScanBound {
293     ScanBoundBuffer::Head m_head;
294     Uint16 m_cnt;       // number of attributes
295     Int16 m_side;
296     ScanBound();
297   };
298   ScanBoundBuffer_pool c_scanBoundPool;
299 
300   // ScanLock
301   struct ScanLock {
302     STATIC_CONST( TYPE_ID = RT_DBTUX_SCAN_LOCK);
303     Uint32 m_magic;
304 
ScanLockDbtux::ScanLock305     ScanLock() :
306       m_magic(Magic::make(TYPE_ID))
307     {
308     }
~ScanLockDbtux::ScanLock309     ~ScanLock()
310     {
311     }
312     Uint32 m_accLockOp;
313     union {
314     Uint32 nextPool;
315     Uint32 nextList;
316     };
317     Uint32 prevList;
318   };
319   STATIC_CONST(DBTUX_SCAN_LOCK_TRANSIENT_POOL_INDEX = 1);
320   typedef Ptr<ScanLock> ScanLockPtr;
321   typedef TransientPool<ScanLock> ScanLock_pool;
322   typedef DLFifoList<ScanLock_pool> ScanLock_fifo;
323   typedef LocalDLFifoList<ScanLock_pool> Local_ScanLock_fifo;
324   typedef ConstLocalDLFifoList<ScanLock_pool> ConstLocal_ScanLock_fifo;
325   Uint32 c_freeScanLock;
326   ScanLock_pool c_scanLockPool;
327 
328   /*
329    * Scan operation.
330    *
331    * Tuples are locked one at a time.  The current lock op is set to
332    * RNIL as soon as the lock is obtained and passed to LQH.  We must
333    * however remember all locks which LQH has not returned for unlocking
334    * since they must be aborted by us when the scan is closed.
335    *
336    * Scan state describes the entry we are interested in.  There is
337    * a separate lock wait flag.  It may be for current entry or it may
338    * be for an entry we were moved away from.  In any case nothing
339    * happens with current entry before lock wait flag is cleared.
340    *
341    * An unfinished scan is always linked to some tree node, and has
342    * current position and direction (see comments at scanNext).  There
343    * is also a copy of latest entry found.
344    *
345    * Error handling:  An error code (independent of scan state) is set
346    * and returned to LQH.  No more result rows are returned but normal
347    * protocol is still followed until scan close.
348    */
349   struct ScanOp {
350     STATIC_CONST( TYPE_ID = RT_DBTUX_SCAN_OPERATION);
351     Uint32 m_magic;
352 
~ScanOpDbtux::ScanOp353     ~ScanOp()
354     {
355     }
356 
357     enum {
358       Undef = 0,
359       First = 1,                // before first entry
360       Current = 2,              // at some entry
361       Found = 3,                // return current as next scan result
362       Blocked = 4,              // found and waiting for ACC lock
363       Locked = 5,               // found and locked or no lock needed
364       Next = 6,                 // looking for next extry
365       Last = 7,                 // after last entry
366       Aborting = 8
367     };
368     Uint32 m_errorCode;
369     Uint32 m_lockwait;
370     Uint32 m_state;
371     Uint32 m_userPtr;           // scanptr.i in LQH
372     Uint32 m_userRef;
373     Uint32 m_tableId;
374     Uint32 m_indexId;
375     Uint32 m_fragId;
376     Uint32 m_fragPtrI;
377     Uint32 m_transId1;
378     Uint32 m_transId2;
379     Uint32 m_savePointId;
380     // lock waited for or obtained and not yet passed to LQH
381     Uint32 m_accLockOp;
382     // locks obtained and passed to LQH but not yet returned by LQH
383     ScanLock_fifo::Head m_accLockOps;
384     Uint8 m_readCommitted;      // no locking
385     Uint8 m_lockMode;
386     Uint8 m_descending;
387     ScanBound m_scanBound[2];
388     TreePos m_scanPos;          // position
389     TreeEnt m_scanEnt;          // latest entry found
390     Uint32 m_nodeScan;          // next scan at node (single-linked)
391     Uint32 m_statOpPtrI;        // RNIL unless this is a statistics scan
392     union {
393     Uint32 nextPool;
394     Uint32 nextList;
395     };
396     Uint32 prevList;
397     ScanOp();
398   };
399   STATIC_CONST(DBTUX_SCAN_OPERATION_TRANSIENT_POOL_INDEX = 0);
400   typedef Ptr<ScanOp> ScanOpPtr;
401   typedef TransientPool<ScanOp> ScanOp_pool;
402   typedef DLList<ScanOp_pool> ScanOp_list;
403   ScanOp_pool c_scanOpPool;
404 
405   // indexes and fragments
406 
407   /*
408    * Ordered index.  Top level data structure.  The primary table (table
409    * being indexed) lives in TUP.
410    */
411   struct Index;
412   friend struct Index;
413   struct Index {
414     enum State {
415       NotDefined = 0,
416       Defining = 1,
417       Building = 3,             // triggers activated, building
418       Online = 2,               // triggers activated and build done
419       Dropping = 9
420     };
421     State m_state;
422     DictTabInfo::TableType m_tableType;
423     Uint32 m_tableId;
424     Uint16 unused;
425     Uint16 m_numFrags;
426     Uint32 m_fragId[MaxIndexFragments];
427     Uint32 m_fragPtrI[MaxIndexFragments];
428     Uint32 m_descPage;          // descriptor page
429     Uint16 m_descOff;           // offset within the page
430     Uint16 m_numAttrs;
431     Uint16 m_prefAttrs;         // attributes in min prefix
432     Uint16 m_prefBytes;         // max bytes in min prefix
433     KeySpec m_keySpec;
434     Uint32 m_statFragPtrI;      // fragment to monitor if not RNIL
435     Uint32 m_statLoadTime;      // load time of index stats
436     union {
437     bool m_storeNullKey;
438     Uint32 nextPool;
439     };
440     Index();
441   };
442   typedef Ptr<Index> IndexPtr;
443   typedef ArrayPool<Index> Index_pool;
444 
445   Index_pool c_indexPool;
446   RSS_AP_SNAPSHOT(c_indexPool);
447 
448   /*
449    * Fragment of an index, as known to DIH/TC.  Represents the two
450    * duplicate fragments known to LQH/ACC/TUP.  Includes tree header.
451    * There are no maintenance operation records yet.
452    */
453   struct Frag;
454   friend struct Frag;
455   struct Frag {
456     Uint32 m_tableId;           // copy from index level
457     Uint32 m_indexId;
458     Uint16 unused;
459     Uint16 m_fragId;
460     TreeHead m_tree;
461     TupLoc m_freeLoc;           // one free node for next op
462     ScanOp_list m_scanList;  // current scans on this fragment
463     Uint32 m_tupIndexFragPtrI;
464     Uint32 m_tupTableFragPtrI;
465     Uint32 m_accTableFragPtrI;
466     Uint64 m_entryCount;        // current entries
467     Uint64 m_entryBytes;        // sum of index key sizes
468     Uint64 m_entryOps;          // ops since last index stats update
469     union {
470     Uint32 nextPool;
471     };
472     Frag(ScanOp_pool& scanOpPool);
473   };
474   typedef Ptr<Frag> FragPtr;
475   typedef ArrayPool<Frag> Frag_pool;
476 
477   Frag_pool c_fragPool;
478   RSS_AP_SNAPSHOT(c_fragPool);
479 
480   /*
481    * Fragment metadata operation.
482    */
483   struct FragOp {
484     Uint32 m_userPtr;
485     Uint32 m_userRef;
486     Uint32 m_indexId;
487     Uint32 m_fragId;
488     Uint32 m_fragPtrI;
489     Uint32 m_fragNo;            // fragment number starting at zero
490     Uint32 m_numAttrsRecvd;
491     union {
492     Uint32 nextPool;
493     };
494     FragOp();
495   };
496   typedef Ptr<FragOp> FragOpPtr;
497   typedef ArrayPool<FragOp> FragOp_pool;
498 
499   FragOp_pool c_fragOpPool;
500   RSS_AP_SNAPSHOT(c_fragOpPool);
501 
502   // node handles
503 
504   /*
505    * A node handle is a reference to a tree node in TUP.  It is used to
506    * operate on the node.  Node handles are allocated on the stack.
507    */
508   struct NodeHandle;
509   friend struct NodeHandle;
510   struct NodeHandle {
511     Frag& m_frag;               // fragment using the node
512     TupLoc m_loc;               // physical node address
513     TreeNode* m_node;           // pointer to node storage
514     NodeHandle(Frag& frag);
515     NodeHandle(const NodeHandle& node);
516     NodeHandle& operator=(const NodeHandle& node);
517     // check if unassigned
518     bool isNull();
519     // getters
520     TupLoc getLink(unsigned i);
521     unsigned getChilds();       // cannot spell
522     unsigned getSide();
523     unsigned getOccup();
524     int getBalance();
525     Uint32 getNodeScan();
526     // setters
527     void setLink(unsigned i, TupLoc loc);
528     void setSide(unsigned i);
529     void setOccup(unsigned n);
530     void setBalance(int b);
531     void setNodeScan(Uint32 scanPtrI);
532     // access other parts of the node
533     Uint32* getPref();
534     TreeEnt getEnt(unsigned pos);
535     // for ndbrequire and ndbassert
536     [[noreturn]] void progError(int line,
537                                 int cause,
538                                 const char* file,
539                                 const char* check);
540   };
541 
542   // stats scan
543   struct StatOp;
544   friend struct StatOp;
545   struct StatOp {
546     // the scan
547     Uint32 m_scanOpPtrI;
548     // parameters
549     Uint32 m_saveSize;
550     Uint32 m_saveScale;
551     Uint32 m_batchSize;
552     Uint32 m_estBytes;
553    // counters
554    Uint32 m_rowCount;
555    Uint32 m_batchCurr;
556    bool m_haveSample;
557    Uint32 m_sampleCount;
558    Uint32 m_keyBytes;
559    bool m_keyChange;
560    bool m_usePrev;
561    // metadata
562    enum { MaxKeyCount = MAX_INDEX_STAT_KEY_COUNT };
563    enum { MaxKeySize = MAX_INDEX_STAT_KEY_SIZE };
564    enum { MaxValueCount = MAX_INDEX_STAT_VALUE_COUNT };
565    enum { MaxValueSize = MAX_INDEX_STAT_VALUE_SIZE };
566    Uint32 m_keyCount;
567    Uint32 m_valueCount;
568    // pack
569    const KeySpec& m_keySpec;
570    NdbPack::Spec m_valueSpec;
571    NdbPack::Type m_valueSpecBuf[MaxValueCount];
572    // data previous current result
573    KeyData m_keyData1;
574    KeyData m_keyData2;
575    KeyData m_keyData;
576    NdbPack::Data m_valueData;
577    // buffers with one word for length bytes
578    Uint32 m_keyDataBuf1[1 + MaxKeySize];
579    Uint32 m_keyDataBuf2[1 + MaxKeySize];
580    Uint32 m_keyDataBuf[1 + MaxKeySize];
581    Uint32 m_valueDataBuf[1 + MaxValueCount];
582    // value collection
583    struct Value {
584      Uint32 m_rir;
585      Uint32 m_unq[MaxKeyCount];
586      Value();
587    };
588    Value m_value1;
589    Value m_value2;
590    union {
591    Uint32 nextPool;
592    };
593    StatOp(const Index&);
594   };
595   typedef Ptr<StatOp> StatOpPtr;
596   typedef ArrayPool<StatOp> StatOp_pool;
597 
598   StatOp_pool c_statOpPool;
599   RSS_AP_SNAPSHOT(c_statOpPool);
600 
601   // stats monitor (shared by req data and continueB loop)
602   struct StatMon;
603   friend struct StatMon;
604   struct StatMon {
605     IndexStatImplReq m_req;
606     Uint32 m_requestType;
607     // continueB loop
608     Uint32 m_loopIndexId;
609     Uint32 m_loopDelay;
610     StatMon();
611   };
612   StatMon c_statMon;
613 
614   // methods
615 
616   /*
617    * DbtuxGen.cpp
618    */
619   void execCONTINUEB(Signal* signal);
620   void execSTTOR(Signal* signal);
621   void execREAD_CONFIG_REQ(Signal* signal);
622   void execNODE_STATE_REP(Signal* signal);
623 
624   // utils
625   void readKeyAttrs(TuxCtx&,
626                     const Frag& frag,
627                     TreeEnt ent,
628                     KeyData& keyData,
629                     Uint32 count);
630   void readKeyAttrs(TuxCtx&,
631                     const Frag& frag,
632                     TreeEnt ent,
633                     Uint32 count,
634                     Uint32 *outputBuffer);
635   void readTablePk(TreeEnt ent, Uint32* pkData, unsigned& pkSize);
636   void unpackBound(Uint32* const outputBuffer,
637                    const ScanBound& bound,
638                    KeyBoundC& searchBound);
639   void findFrag(EmulatedJamBuffer* jamBuf, const Index& index,
640                 Uint32 fragId, FragPtr& fragPtr);
641 
642   /*
643    * DbtuxMeta.cpp
644    */
645   void execCREATE_TAB_REQ(Signal*);
646   void execTUXFRAGREQ(Signal* signal);
647   void execTUX_ADD_ATTRREQ(Signal* signal);
648   void execALTER_INDX_IMPL_REQ(Signal* signal);
649   void execDROP_TAB_REQ(Signal* signal);
650   void execDROP_FRAG_REQ(Signal* signal);
651   bool allocDescEnt(IndexPtr indexPtr);
652   void freeDescEnt(IndexPtr indexPtr);
653   void abortAddFragOp(Signal* signal);
654   void dropIndex(Signal* signal, IndexPtr indexPtr, Uint32 senderRef, Uint32 senderData);
655 
656   /*
657    * DbtuxMaint.cpp
658    */
659   void execTUX_MAINT_REQ(Signal* signal);
660 
661   /*
662    * DbtuxNode.cpp
663    */
664   int allocNode(TuxCtx&, NodeHandle& node);
665   void freeNode(NodeHandle& node);
666   void selectNode(TuxCtx&, NodeHandle& node, TupLoc loc);
667   void insertNode(TuxCtx&, NodeHandle& node);
668   void deleteNode(NodeHandle& node);
669   void freePreallocatedNode(Frag& frag);
670   void setNodePref(struct TuxCtx &, NodeHandle& node);
671   // node operations
672   void nodePushUp(TuxCtx&, NodeHandle& node, unsigned pos, const TreeEnt& ent, Uint32 scanList);
673   void nodePushUpScans(NodeHandle& node, unsigned pos);
674   void nodePopDown(TuxCtx&, NodeHandle& node, unsigned pos, TreeEnt& en, Uint32* scanList);
675   void nodePopDownScans(NodeHandle& node, unsigned pos);
676   void nodePushDown(TuxCtx&, NodeHandle& node, unsigned pos, TreeEnt& ent, Uint32& scanList);
677   void nodePushDownScans(NodeHandle& node, unsigned pos);
678   void nodePopUp(TuxCtx&, NodeHandle& node, unsigned pos, TreeEnt& ent, Uint32 scanList);
679   void nodePopUpScans(NodeHandle& node, unsigned pos);
680   void nodeSlide(TuxCtx&, NodeHandle& dstNode, NodeHandle& srcNode, unsigned cnt, unsigned i);
681   // scans linked to node
682   void addScanList(NodeHandle& node, unsigned pos, Uint32 scanList);
683   void removeScanList(NodeHandle& node, unsigned pos, Uint32& scanList);
684   void moveScanList(NodeHandle& node, unsigned pos);
685   void linkScan(NodeHandle& node, ScanOpPtr scanPtr);
686   void unlinkScan(NodeHandle& node, ScanOpPtr scanPtr);
687   bool islinkScan(NodeHandle& node, ScanOpPtr scanPtr);
688 
689   /*
690    * DbtuxTree.cpp
691    */
692   // add entry
693   void treeAdd(TuxCtx&, Frag& frag, TreePos treePos, TreeEnt ent);
694   void treeAddFull(TuxCtx&, Frag& frag, NodeHandle lubNode, unsigned pos, TreeEnt ent);
695   void treeAddNode(TuxCtx&, Frag& frag, NodeHandle lubNode, unsigned pos, TreeEnt ent, NodeHandle parentNode, unsigned i);
696   void treeAddRebalance(TuxCtx&, Frag& frag, NodeHandle node, unsigned i);
697   // remove entry
698   void treeRemove(Frag& frag, TreePos treePos);
699   void treeRemoveInner(Frag& frag, NodeHandle lubNode, unsigned pos);
700   void treeRemoveSemi(Frag& frag, NodeHandle node, unsigned i);
701   void treeRemoveLeaf(Frag& frag, NodeHandle node);
702   void treeRemoveNode(Frag& frag, NodeHandle node);
703   void treeRemoveRebalance(Frag& frag, NodeHandle node, unsigned i);
704   // rotate
705   void treeRotateSingle(TuxCtx&, Frag& frag, NodeHandle& node, unsigned i);
706   void treeRotateDouble(TuxCtx&, Frag& frag, NodeHandle& node, unsigned i);
707 
708   /*
709    * DbtuxScan.cpp
710    */
711   void execACC_SCANREQ(Signal* signal);
712   void execNEXT_SCANREQ(Signal* signal);
713   void execACC_CHECK_SCAN(Signal* signal);
714   void execACCKEYCONF(Signal* signal);
715   void execACCKEYREF(Signal* signal);
716   void execACC_ABORTCONF(Signal* signal);
717   void scanFirst(ScanOpPtr scanPtr, Frag& frag, const Index& index);
718   void continue_scan(Signal *signal, ScanOpPtr scanPtr, Frag& frag, bool);
719   void scanFind(ScanOpPtr scanPtr, Frag& frag);
720   Uint32 scanNext(ScanOpPtr scanPtr, bool fromMaintReq, Frag& frag);
721   bool scanCheck(ScanOp& scan, TreeEnt ent);
722   bool scanVisible(ScanOp& scan, TreeEnt ent);
723   void scanClose(Signal* signal, ScanOpPtr scanPtr);
724   void abortAccLockOps(Signal* signal, ScanOpPtr scanPtr);
725   void addAccLockOp(ScanOpPtr scanPtr, Uint32 accLockOp);
726   void removeAccLockOp(ScanOpPtr scanPtr, Uint32 accLockOp);
727   void releaseScanOp(ScanOpPtr& scanPtr);
728 
729   /*
730    * DbtuxSearch.cpp
731    */
732   void findNodeToUpdate(TuxCtx&,
733                         Frag& frag,
734                         const KeyBoundArray& searchBound,
735                         TreeEnt searchEnt,
736                         NodeHandle& currNode);
737   bool findPosToAdd(TuxCtx&,
738                     Frag& frag,
739                     const KeyBoundArray& searchBound,
740                     TreeEnt searchEnt,
741                     NodeHandle& currNode,
742                     TreePos& treePos);
743   bool findPosToRemove(TuxCtx&,
744                        TreeEnt searchEnt,
745                        NodeHandle& currNode,
746                        TreePos& treePos);
747   bool searchToAdd(TuxCtx&,
748                    Frag& frag,
749                    const KeyBoundArray& searchBound,
750                    TreeEnt searchEnt,
751                    TreePos& treePos);
752   bool searchToRemove(TuxCtx&,
753                       Frag& frag,
754                       const KeyBoundArray& searchBound,
755                       TreeEnt searchEnt,
756                       TreePos& treePos);
757   void findNodeToScan(Frag& frag,
758                       unsigned dir,
759                       const KeyBoundArray& searchBound,
760                       NodeHandle& currNode);
761   void findPosToScan(Frag& frag,
762                      unsigned idir,
763                      const KeyBoundArray& searchBound,
764                      NodeHandle& currNode,
765                      Uint32* pos);
766   void searchToScan(Frag& frag,
767                     unsigned idir,
768                     const KeyBoundArray& searchBound,
769                     TreePos& treePos);
770 
771   /**
772    * Prepare methods
773    * These methods are setting up variables that are precomputed to avoid having
774    * to compute those every time we need them.
775    */
776   void prepare_scan_bounds(const ScanOp *scanPtrP, const Index *indexPtrP);
777   void prepare_move_scan_ctx(ScanOpPtr scanPtr);
778 
779   /*
780    * DbtuxCmp.cpp
781    */
782   int cmpSearchKey(TuxCtx&, const KeyDataC& searchKey, const KeyDataC& entryKey, Uint32 cnt);
783   int cmpSearchBound(TuxCtx&, const KeyBoundC& searchBound, const KeyDataC& entryKey, Uint32 cnt);
784 
785   /*
786    * DbtuxStat.cpp
787    */
788   // one-round-trip tree-dive records in range
789   void statRecordsInRange(ScanOpPtr scanPtr, Uint32* out);
790   Uint32 getEntriesBeforeOrAfter(Frag& frag, TreePos pos, unsigned idir);
791   unsigned getPathToNode(NodeHandle node, Uint16* path);
792   // stats scan
793   int statScanInit(StatOpPtr, const Uint32* data, Uint32 len, Uint32* usedLen);
794   int statScanAddRow(StatOpPtr, TreeEnt ent);
795   void statScanReadKey(StatOpPtr, Uint32* out);
796   void statScanReadValue(StatOpPtr, Uint32* out);
797   void execINDEX_STAT_REP(Signal*); // from TRIX
798   // stats monitor request
799   void execINDEX_STAT_IMPL_REQ(Signal*);
800   void statMonStart(Signal*, StatMon&);
801   void statMonStop(Signal*, StatMon&);
802   void statMonConf(Signal*, StatMon&);
803   // stats monitor continueB loop
804   void statMonSendContinueB(Signal*);
805   void statMonExecContinueB(Signal*);
806   void statMonCheck(Signal*, StatMon&);
807   void statMonRep(Signal*, StatMon&);
808 
809   /*
810    * DbtuxDebug.cpp
811    */
812   void execDUMP_STATE_ORD(Signal* signal);
813 #ifdef VM_TRACE
814   struct PrintPar {
815     char m_path[100];           // LR prefix
816     unsigned m_side;            // expected side
817     TupLoc m_parent;            // expected parent address
818     int m_depth;                // returned depth
819     unsigned m_occup;           // returned occupancy
820     TreeEnt m_minmax[2];        // returned subtree min and max
821     bool m_ok;                  // returned status
822     PrintPar();
823   };
824   void printTree(Signal* signal, Frag& frag, NdbOut& out);
825   void printNode(struct TuxCtx&, Frag&, NdbOut& out, TupLoc loc, PrintPar& par);
826   friend class NdbOut& operator<<(NdbOut&, const TupLoc&);
827   friend class NdbOut& operator<<(NdbOut&, const TreeEnt&);
828   friend class NdbOut& operator<<(NdbOut&, const TreeNode&);
829   friend class NdbOut& operator<<(NdbOut&, const TreeHead&);
830   friend class NdbOut& operator<<(NdbOut&, const TreePos&);
831   friend class NdbOut& operator<<(NdbOut&, const KeyType&);
832   friend class NdbOut& operator<<(NdbOut&, const ScanOp&);
833   friend class NdbOut& operator<<(NdbOut&, const Index&);
834   friend class NdbOut& operator<<(NdbOut&, const Frag&);
835   friend class NdbOut& operator<<(NdbOut&, const FragOp&);
836   friend class NdbOut& operator<<(NdbOut&, const NodeHandle&);
837   friend class NdbOut& operator<<(NdbOut&, const StatOp&);
838   friend class NdbOut& operator<<(NdbOut&, const StatMon&);
839   FILE* debugFile;
840   NdbOut tuxDebugOut;
841   unsigned debugFlags;
842   enum {
843     DebugMeta = 1,              // log create and drop index
844     DebugMaint = 2,             // log maintenance ops
845     DebugTree = 4,              // log and check tree after each op
846     DebugScan = 8,              // log scans
847     DebugLock = 16,             // log ACC locks
848     DebugStat = 32              // log stats collection
849   };
850   STATIC_CONST( DataFillByte = 0xa2 );
851   STATIC_CONST( NodeFillByte = 0xa4 );
852 #endif
853 
854   void execDBINFO_SCANREQ(Signal* signal);
855 
856   // start up info
857   Uint32 c_internalStartPhase;
858   Uint32 c_typeOfStart;
859 
860   /*
861    * Global data set at operation start.  Unpacked from index metadata.
862    * Not passed as parameter to methods.  Invalid across timeslices.
863    *
864    * TODO inline all into index metadata
865    */
866   struct TuxCtx
867   {
868     EmulatedJamBuffer * jamBuffer;
869 
870 
871     ScanOpPtr scanPtr;
872     FragPtr fragPtr;
873     IndexPtr indexPtr;
874     Uint32 *tupIndexFragPtr;
875     Uint32 *tupIndexTablePtr;
876     Uint32 *tupRealFragPtr;
877     Uint32 *tupRealTablePtr;
878     Uint32 attrDataOffset;
879     Uint32 tuxFixHeaderSize;
880 
881     KeyDataArray searchScanDataArray;
882     KeyBoundArray searchScanBoundArray;
883     Uint32 *keyAttrs;
884 
885     KeyDataArray searchKeyDataArray;
886     KeyBoundArray searchKeyBoundArray;
887 
888     Uint32 scanBoundCnt;
889     Uint32 descending;
890 
891     TreeEnt m_current_ent;
892 
893     // buffer for scan bound and search key data
894     Uint32* c_searchKey;
895 
896     // buffer for scan bound and search key data for next key
897     Uint32* c_nextKey;
898 
899     // buffer for current entry key data
900     Uint32* c_entryKey;
901 
902     // buffer for xfrm-ed PK and for temporary use
903     Uint32* c_dataBuffer;
904 
905     // buffer for xfrm-ed PK and for temporary use
906     Uint32* c_boundBuffer;
907 
908 #ifdef VM_TRACE
909     char* c_debugBuffer;
910 #endif
911   };
912 
913   struct TuxCtx c_ctx; // Global Tux context, for everything build MT-index build
914 
915   // index stats
916   bool c_indexStatAutoUpdate;
917   Uint32 c_indexStatSaveSize;
918   Uint32 c_indexStatSaveScale;
919   Uint32 c_indexStatTriggerPct;
920   Uint32 c_indexStatTriggerScale;
921   Uint32 c_indexStatUpdateDelay;
922 
923   // inlined utils
924   Uint32 getDescSize(const Index& index);
925   DescHead& getDescHead(const Index& index);
926   KeyType* getKeyTypes(DescHead& descHead);
927   const KeyType* getKeyTypes(const DescHead& descHead);
928   AttributeHeader* getKeyAttrs(DescHead& descHead);
929   const AttributeHeader* getKeyAttrs(const DescHead& descHead);
930   //
931   void getTupAddr(const Frag& frag, TreeEnt ent, Uint32& lkey1, Uint32& lkey2);
932   static unsigned min(unsigned x, unsigned y);
933   static unsigned max(unsigned x, unsigned y);
934 
935 public:
936   static Uint32 mt_buildIndexFragment_wrapper(void*);
937   void prepare_build_ctx(TuxCtx& ctx, FragPtr fragPtr);
938   void prepare_tup_ptrs(TuxCtx& ctx);
939   void prepare_all_tup_ptrs(TuxCtx& ctx);
940 private:
941   Uint32 mt_buildIndexFragment(struct mt_BuildIndxCtx*);
942 
943   Signal* c_signal_bug32040;
944 
945 private:
946   bool check_freeScanLock(ScanOp& scan);
947   void release_c_free_scan_lock();
948   void checkPoolShrinkNeed(Uint32 pool_index,
949                            const TransientFastSlotPool& pool);
950   void sendPoolShrink(Uint32 pool_index);
951   void shrinkTransientPools(Uint32 pool_index);
952 
953   static const Uint32 c_transient_pool_count = 3;
954   TransientFastSlotPool* c_transient_pools[c_transient_pool_count];
955   Bitmask<1> c_transient_pools_shrinking;
956 
957 public:
958   static Uint64 getTransactionMemoryNeed(
959     const Uint32 ldm_instance_count,
960     const ndb_mgm_configuration_iterator *mgm_cfg,
961     const bool use_reserved);
962 };
963 
check_freeScanLock(ScanOp & scan)964 inline bool Dbtux::check_freeScanLock(ScanOp& scan)
965 {
966   if (unlikely((! scan.m_readCommitted) &&
967                 c_freeScanLock == RNIL))
968   {
969     ScanLockPtr allocPtr;
970     if (c_scanLockPool.seize(allocPtr))
971     {
972       jam();
973       c_freeScanLock = allocPtr.i;
974     }
975     else
976     {
977       return true;
978     }
979   }
980   return false;
981 }
982 
983 inline void
release_c_free_scan_lock()984 Dbtux::release_c_free_scan_lock()
985 {
986   if (c_freeScanLock != RNIL)
987   {
988     jam();
989     ScanLockPtr releasePtr;
990     releasePtr.i = c_freeScanLock;
991     ndbrequire(c_scanLockPool.getValidPtr(releasePtr));
992     c_scanLockPool.release(releasePtr);
993     c_freeScanLock = RNIL;
994     checkPoolShrinkNeed(DBTUX_SCAN_LOCK_TRANSIENT_POOL_INDEX,
995                         c_scanLockPool);
996   }
997 }
998 
checkPoolShrinkNeed(const Uint32 pool_index,const TransientFastSlotPool & pool)999 inline void Dbtux::checkPoolShrinkNeed(const Uint32 pool_index,
1000                                        const TransientFastSlotPool& pool)
1001 {
1002 #if defined(VM_TRACE) || defined(ERROR_INSERT)
1003   ndbrequire(pool_index < c_transient_pool_count);
1004   ndbrequire(c_transient_pools[pool_index] == &pool);
1005 #endif
1006   if (pool.may_shrink())
1007   {
1008     sendPoolShrink(pool_index);
1009   }
1010 }
1011 
1012 // Dbtux::TupLoc
1013 
1014 inline
TupLoc()1015 Dbtux::TupLoc::TupLoc() :
1016   m_pageId1(RNIL >> 16),
1017   m_pageId2(RNIL & 0xFFFF),
1018   m_pageOffset(0)
1019 {
1020 }
1021 
1022 inline
TupLoc(Uint32 pageId,Uint16 pageOffset)1023 Dbtux::TupLoc::TupLoc(Uint32 pageId, Uint16 pageOffset) :
1024   m_pageId1(pageId >> 16),
1025   m_pageId2(pageId & 0xFFFF),
1026   m_pageOffset(pageOffset)
1027 {
1028 }
1029 
1030 inline Uint32
getPageId() const1031 Dbtux::TupLoc::getPageId() const
1032 {
1033   return (m_pageId1 << 16) | m_pageId2;
1034 }
1035 
1036 inline void
setPageId(Uint32 pageId)1037 Dbtux::TupLoc::setPageId(Uint32 pageId)
1038 {
1039   m_pageId1 = (pageId >> 16);
1040   m_pageId2 = (pageId & 0xFFFF);
1041 }
1042 
1043 inline Uint32
getPageOffset() const1044 Dbtux::TupLoc::getPageOffset() const
1045 {
1046   return (Uint32)m_pageOffset;
1047 }
1048 
1049 inline void
setPageOffset(Uint32 pageOffset)1050 Dbtux::TupLoc::setPageOffset(Uint32 pageOffset)
1051 {
1052   m_pageOffset = (Uint16)pageOffset;
1053 }
1054 
1055 inline bool
operator ==(const TupLoc & loc) const1056 Dbtux::TupLoc::operator==(const TupLoc& loc) const
1057 {
1058   return
1059     m_pageId1 == loc.m_pageId1 &&
1060     m_pageId2 == loc.m_pageId2 &&
1061     m_pageOffset == loc.m_pageOffset;
1062 }
1063 
1064 inline bool
operator !=(const TupLoc & loc) const1065 Dbtux::TupLoc::operator!=(const TupLoc& loc) const
1066 {
1067   return ! (*this == loc);
1068 }
1069 
1070 // Dbtux::TreeEnt
1071 
1072 inline
TreeEnt()1073 Dbtux::TreeEnt::TreeEnt() :
1074   m_tupLoc(),
1075   m_tupVersion(0)
1076 {
1077 }
1078 
1079 inline bool
eqtuple(const TreeEnt ent) const1080 Dbtux::TreeEnt::eqtuple(const TreeEnt ent) const
1081 {
1082   return
1083     m_tupLoc == ent.m_tupLoc;
1084 }
1085 
1086 inline bool
eq(const TreeEnt ent) const1087 Dbtux::TreeEnt::eq(const TreeEnt ent) const
1088 {
1089   return
1090     m_tupLoc == ent.m_tupLoc &&
1091     m_tupVersion == ent.m_tupVersion;
1092 }
1093 
1094 inline int
cmp(const TreeEnt ent) const1095 Dbtux::TreeEnt::cmp(const TreeEnt ent) const
1096 {
1097   if (m_tupLoc.getPageId() < ent.m_tupLoc.getPageId())
1098     return -1;
1099   if (m_tupLoc.getPageId() > ent.m_tupLoc.getPageId())
1100     return +1;
1101   if (m_tupLoc.getPageOffset() < ent.m_tupLoc.getPageOffset())
1102     return -1;
1103   if (m_tupLoc.getPageOffset() > ent.m_tupLoc.getPageOffset())
1104     return +1;
1105   /*
1106    * Guess if one tuple version has wrapped around.  This is well
1107    * defined ordering on existing versions since versions are assigned
1108    * consecutively and different versions exists only on uncommitted
1109    * tuple.  Assuming max 2**14 uncommitted ops on same tuple.
1110    */
1111   const unsigned version_wrap_limit = (1 << (ZTUP_VERSION_BITS - 1));
1112   if (m_tupVersion < ent.m_tupVersion) {
1113     if (unsigned(ent.m_tupVersion - m_tupVersion) < version_wrap_limit)
1114       return -1;
1115     else
1116       return +1;
1117   }
1118   if (m_tupVersion > ent.m_tupVersion) {
1119     if (unsigned(m_tupVersion - ent.m_tupVersion) < version_wrap_limit)
1120       return +1;
1121     else
1122       return -1;
1123   }
1124   return 0;
1125 }
1126 
1127 // Dbtux::TreeNode
1128 
1129 inline
TreeNode()1130 Dbtux::TreeNode::TreeNode() :
1131   m_side(2),
1132   m_balance(0 + 1),
1133   pad1(0),
1134   m_occup(0),
1135   m_nodeScan(RNIL)
1136 {
1137   m_link[0] = NullTupLoc;
1138   m_link[1] = NullTupLoc;
1139   m_link[2] = NullTupLoc;
1140 }
1141 
1142 // Dbtux::TreeHead
1143 
1144 inline
TreeHead()1145 Dbtux::TreeHead::TreeHead() :
1146   m_nodeSize(0),
1147   m_prefSize(0),
1148   m_minOccup(0),
1149   m_maxOccup(0),
1150   m_root()
1151 {
1152 }
1153 
1154 inline Uint32*
getPref(TreeNode * node) const1155 Dbtux::TreeHead::getPref(TreeNode* node) const
1156 {
1157   Uint32* ptr = (Uint32*)node + NodeHeadSize;
1158   return ptr;
1159 }
1160 
1161 inline Dbtux::TreeEnt*
getEntList(TreeNode * node) const1162 Dbtux::TreeHead::getEntList(TreeNode* node) const
1163 {
1164   Uint32* ptr = (Uint32*)node + NodeHeadSize + m_prefSize;
1165   return (TreeEnt*)ptr;
1166 }
1167 
1168 // Dbtux::TreePos
1169 
1170 inline
TreePos()1171 Dbtux::TreePos::TreePos() :
1172   m_loc(),
1173   m_pos(Uint32(~0)),
1174   m_dir(Uint32(~0))
1175 {
1176 }
1177 
1178 // Dbtux::DescPage
1179 
1180 inline
DescPage()1181 Dbtux::DescPage::DescPage() :
1182   m_nextPage(RNIL),
1183   m_numFree(ZNIL)
1184 {
1185   for (unsigned i = 0; i < DescPageSize; i++) {
1186 #ifdef VM_TRACE
1187     m_data[i] = 0x13571357;
1188 #else
1189     m_data[i] = 0;
1190 #endif
1191   }
1192 }
1193 
1194 // Dbtux::ScanBound
1195 
1196 inline
ScanBound()1197 Dbtux::ScanBound::ScanBound() :
1198   m_head(),
1199   m_cnt(0),
1200   m_side(0)
1201 {
1202 }
1203 
1204 inline
ScanOp()1205 Dbtux::ScanOp::ScanOp() :
1206   m_magic(Magic::make(ScanOp::TYPE_ID)),
1207   m_errorCode(0),
1208   m_lockwait(false),
1209   m_fragPtrI(RNIL),
1210   m_accLockOp(RNIL),
1211   m_accLockOps(),
1212   m_scanBound(),
1213   m_scanPos(),
1214   m_scanEnt(),
1215   m_nodeScan(RNIL),
1216   m_statOpPtrI(RNIL)
1217 {
1218 }
1219 
1220 // Dbtux::Index
1221 
1222 inline
Index()1223 Dbtux::Index::Index() :
1224   m_state(NotDefined),
1225   m_tableType(DictTabInfo::UndefTableType),
1226   m_tableId(RNIL),
1227   m_numFrags(0),
1228   m_descPage(RNIL),
1229   m_descOff(0),
1230   m_numAttrs(0),
1231   m_prefAttrs(0),
1232   m_prefBytes(0),
1233   m_keySpec(),
1234   m_statFragPtrI(RNIL),
1235   m_statLoadTime(0),
1236   m_storeNullKey(false)
1237 {
1238   for (unsigned i = 0; i < MaxIndexFragments; i++) {
1239     m_fragId[i] = ZNIL;
1240     m_fragPtrI[i] = RNIL;
1241   };
1242 }
1243 
1244 // Dbtux::Frag
1245 
1246 inline
Frag(ScanOp_pool & scanOpPool)1247 Dbtux::Frag::Frag(ScanOp_pool& scanOpPool) :
1248   m_tableId(RNIL),
1249   m_indexId(RNIL),
1250   m_fragId(ZNIL),
1251   m_tree(),
1252   m_freeLoc(),
1253   m_scanList(scanOpPool),
1254   m_tupIndexFragPtrI(RNIL),
1255   m_tupTableFragPtrI(RNIL),
1256   m_accTableFragPtrI(RNIL),
1257   m_entryCount(0),
1258   m_entryBytes(0),
1259   m_entryOps(0)
1260 {
1261 }
1262 
1263 // Dbtux::FragOp
1264 
1265 inline
FragOp()1266 Dbtux::FragOp::FragOp() :
1267   m_userPtr(RNIL),
1268   m_userRef(RNIL),
1269   m_indexId(RNIL),
1270   m_fragId(ZNIL),
1271   m_fragPtrI(RNIL),
1272   m_fragNo(ZNIL),
1273   m_numAttrsRecvd(ZNIL)
1274 {
1275 }
1276 
1277 // Dbtux::NodeHandle
1278 
1279 inline
NodeHandle(Frag & frag)1280 Dbtux::NodeHandle::NodeHandle(Frag& frag) :
1281   m_frag(frag),
1282   m_loc(),
1283   m_node(0)
1284 {
1285 }
1286 
1287 inline
NodeHandle(const NodeHandle & node)1288 Dbtux::NodeHandle::NodeHandle(const NodeHandle& node) :
1289   m_frag(node.m_frag),
1290   m_loc(node.m_loc),
1291   m_node(node.m_node)
1292 {
1293 }
1294 
1295 inline Dbtux::NodeHandle&
operator =(const NodeHandle & node)1296 Dbtux::NodeHandle::operator=(const NodeHandle& node)
1297 {
1298   ndbassert(&m_frag == &node.m_frag);
1299   m_loc = node.m_loc;
1300   m_node = node.m_node;
1301   return *this;
1302 }
1303 
1304 inline bool
isNull()1305 Dbtux::NodeHandle::isNull()
1306 {
1307   return m_node == 0;
1308 }
1309 
1310 inline Dbtux::TupLoc
getLink(unsigned i)1311 Dbtux::NodeHandle::getLink(unsigned i)
1312 {
1313   ndbrequire(i <= 2);
1314   return m_node->m_link[i];
1315 }
1316 
1317 inline unsigned
getChilds()1318 Dbtux::NodeHandle::getChilds()
1319 {
1320   return (m_node->m_link[0] != NullTupLoc) + (m_node->m_link[1] != NullTupLoc);
1321 }
1322 
1323 inline unsigned
getSide()1324 Dbtux::NodeHandle::getSide()
1325 {
1326   return m_node->m_side;
1327 }
1328 
1329 inline unsigned
getOccup()1330 Dbtux::NodeHandle::getOccup()
1331 {
1332   return m_node->m_occup;
1333 }
1334 
1335 inline int
getBalance()1336 Dbtux::NodeHandle::getBalance()
1337 {
1338   return (int)m_node->m_balance - 1;
1339 }
1340 
1341 inline Uint32
getNodeScan()1342 Dbtux::NodeHandle::getNodeScan()
1343 {
1344   return m_node->m_nodeScan;
1345 }
1346 
1347 inline void
setLink(unsigned i,TupLoc loc)1348 Dbtux::NodeHandle::setLink(unsigned i, TupLoc loc)
1349 {
1350   if (likely(i <= 2))
1351   {
1352     m_node->m_link[i] = loc;
1353   }
1354   else
1355   {
1356     ndbabort();
1357   }
1358 }
1359 
1360 inline void
setSide(unsigned i)1361 Dbtux::NodeHandle::setSide(unsigned i)
1362 {
1363   if (likely(i <= 2))
1364   {
1365     m_node->m_side = i;
1366   }
1367   else
1368   {
1369     ndbabort();
1370   }
1371 }
1372 
1373 inline void
setOccup(unsigned n)1374 Dbtux::NodeHandle::setOccup(unsigned n)
1375 {
1376   TreeHead& tree = m_frag.m_tree;
1377   ndbrequire(n <= tree.m_maxOccup);
1378   m_node->m_occup = n;
1379 }
1380 
1381 inline void
setBalance(int b)1382 Dbtux::NodeHandle::setBalance(int b)
1383 {
1384   ndbrequire(abs(b) <= 1);
1385   m_node->m_balance = (unsigned)(b + 1);
1386 }
1387 
1388 inline void
setNodeScan(Uint32 scanPtrI)1389 Dbtux::NodeHandle::setNodeScan(Uint32 scanPtrI)
1390 {
1391   m_node->m_nodeScan = scanPtrI;
1392 }
1393 
1394 inline Uint32*
getPref()1395 Dbtux::NodeHandle::getPref()
1396 {
1397   TreeHead& tree = m_frag.m_tree;
1398   return tree.getPref(m_node);
1399 }
1400 
1401 inline Dbtux::TreeEnt
getEnt(unsigned pos)1402 Dbtux::NodeHandle::getEnt(unsigned pos)
1403 {
1404   TreeHead& tree = m_frag.m_tree;
1405   TreeEnt* entList = tree.getEntList(m_node);
1406   const unsigned occup = m_node->m_occup;
1407   ndbrequire(pos < occup);
1408   return entList[pos];
1409 }
1410 
1411 // stats
1412 
1413 inline
Value()1414 Dbtux::StatOp::Value::Value()
1415 {
1416   m_rir = 0;
1417   Uint32 i;
1418   for (i = 0; i < MaxKeyCount; i++)
1419     m_unq[i] = 0;
1420 }
1421 
1422 inline
StatOp(const Index & index)1423 Dbtux::StatOp::StatOp(const Index& index) :
1424   m_scanOpPtrI(RNIL),
1425   m_saveSize(0),
1426   m_saveScale(0),
1427   m_batchSize(0),
1428   m_estBytes(0),
1429   m_rowCount(0),
1430   m_batchCurr(0),
1431   m_haveSample(false),
1432   m_sampleCount(0),
1433   m_keyBytes(0),
1434   m_keyChange(false),
1435   m_usePrev(false),
1436   m_keyCount(0),
1437   m_valueCount(0),
1438   m_keySpec(index.m_keySpec),
1439   m_keyData1(m_keySpec, false, 2),
1440   m_keyData2(m_keySpec, false, 2),
1441   m_keyData(m_keySpec, false, 2),
1442   m_valueData(m_valueSpec, false, 2),
1443   m_value1(),
1444   m_value2()
1445 {
1446   m_valueSpec.set_buf(m_valueSpecBuf, MaxValueCount);
1447   m_keyData1.set_buf(m_keyDataBuf1, sizeof(m_keyDataBuf1));
1448   m_keyData2.set_buf(m_keyDataBuf2, sizeof(m_keyDataBuf2));
1449   m_keyData.set_buf(m_keyDataBuf, sizeof(m_keyDataBuf));
1450   m_valueData.set_buf(m_valueDataBuf, sizeof(m_valueDataBuf));
1451 }
1452 
1453 // Dbtux::StatMon
1454 
1455 inline
StatMon()1456 Dbtux::StatMon::StatMon() :
1457   m_requestType(0),
1458   m_loopIndexId(0),
1459   m_loopDelay(1000)
1460 {
1461   memset(&m_req, 0, sizeof(m_req));
1462 }
1463 
1464 // parameters for methods
1465 
1466 #ifdef VM_TRACE
1467 inline
PrintPar()1468 Dbtux::PrintPar::PrintPar() :
1469   // caller fills in
1470   m_path(),
1471   m_side(255),
1472   m_parent(),
1473   // default return values
1474   m_depth(0),
1475   m_occup(0),
1476   m_ok(true)
1477 {
1478 }
1479 #endif
1480 
1481 // utils
1482 
1483 inline Uint32
getDescSize(const Index & index)1484 Dbtux::getDescSize(const Index& index)
1485 {
1486   return
1487     DescHeadSize +
1488     index.m_numAttrs * KeyTypeSize +
1489     index.m_numAttrs * AttributeHeaderSize;
1490 }
1491 
1492 inline Dbtux::DescHead&
getDescHead(const Index & index)1493 Dbtux::getDescHead(const Index& index)
1494 {
1495   DescPagePtr pagePtr;
1496   pagePtr.i = index.m_descPage;
1497   c_descPagePool.getPtr(pagePtr);
1498   ndbrequire(index.m_descOff < DescPageSize);
1499   Uint32* ptr = &pagePtr.p->m_data[index.m_descOff];
1500   DescHead* descHead = reinterpret_cast<DescHead*>(ptr);
1501   ndbrequire(descHead->m_magic == DescHead::Magic);
1502   return *descHead;
1503 }
1504 
1505 inline Dbtux::KeyType*
getKeyTypes(DescHead & descHead)1506 Dbtux::getKeyTypes(DescHead& descHead)
1507 {
1508   Uint32* ptr = reinterpret_cast<Uint32*>(&descHead);
1509   ptr += DescHeadSize;
1510   return reinterpret_cast<KeyType*>(ptr);
1511 }
1512 
1513 inline const Dbtux::KeyType*
getKeyTypes(const DescHead & descHead)1514 Dbtux::getKeyTypes(const DescHead& descHead)
1515 {
1516   const Uint32* ptr = reinterpret_cast<const Uint32*>(&descHead);
1517   ptr += DescHeadSize;
1518   return reinterpret_cast<const KeyType*>(ptr);
1519 }
1520 
1521 inline AttributeHeader*
getKeyAttrs(DescHead & descHead)1522 Dbtux::getKeyAttrs(DescHead& descHead)
1523 {
1524   Uint32* ptr = reinterpret_cast<Uint32*>(&descHead);
1525   ptr += DescHeadSize;
1526   ptr += descHead.m_numAttrs * KeyTypeSize;
1527   return reinterpret_cast<AttributeHeader*>(ptr);
1528 }
1529 
1530 inline const AttributeHeader*
getKeyAttrs(const DescHead & descHead)1531 Dbtux::getKeyAttrs(const DescHead& descHead)
1532 {
1533   const Uint32* ptr = reinterpret_cast<const Uint32*>(&descHead);
1534   ptr += DescHeadSize;
1535   ptr += descHead.m_numAttrs * KeyTypeSize;
1536   return reinterpret_cast<const AttributeHeader*>(ptr);
1537 }
1538 
1539 inline
1540 void
getTupAddr(const Frag & frag,TreeEnt ent,Uint32 & lkey1,Uint32 & lkey2)1541 Dbtux::getTupAddr(const Frag& frag, TreeEnt ent, Uint32& lkey1, Uint32& lkey2)
1542 {
1543   const Uint32 tableFragPtrI = frag.m_tupTableFragPtrI;
1544   const TupLoc tupLoc = ent.m_tupLoc;
1545   c_tup->tuxGetTupAddr(tableFragPtrI, tupLoc.getPageId(),tupLoc.getPageOffset(),
1546                        lkey1, lkey2);
1547   jamEntryDebug();
1548 }
1549 
1550 inline unsigned
min(unsigned x,unsigned y)1551 Dbtux::min(unsigned x, unsigned y)
1552 {
1553   return x < y ? x : y;
1554 }
1555 
1556 inline unsigned
max(unsigned x,unsigned y)1557 Dbtux::max(unsigned x, unsigned y)
1558 {
1559   return x > y ? x : y;
1560 }
1561 
1562 // DbtuxCmp.cpp
1563 
1564 /**
1565  * Can be called from MT-build of ordered indexes,
1566  * but it doesn't make use of the MT-context other
1567  * than for debug printouts.
1568  */
1569 inline int
cmpSearchKey(TuxCtx & ctx,const KeyDataC & searchKey,const KeyDataC & entryKey,Uint32 cnt)1570 Dbtux::cmpSearchKey(TuxCtx& ctx,
1571                     const KeyDataC& searchKey,
1572                     const KeyDataC& entryKey,
1573                     Uint32 cnt)
1574 {
1575   // compare cnt attributes from each
1576   Uint32 num_eq;
1577   int ret = searchKey.cmp(entryKey, cnt, num_eq);
1578 #ifdef VM_TRACE
1579   if (debugFlags & DebugMaint) {
1580     tuxDebugOut << "cmpSearchKey: ret:" << ret;
1581     tuxDebugOut << " search:" << searchKey.print(ctx.c_debugBuffer, DebugBufferBytes);
1582     tuxDebugOut << " entry:" << entryKey.print(ctx.c_debugBuffer, DebugBufferBytes);
1583     tuxDebugOut << endl;
1584   }
1585 #endif
1586   return ret;
1587 }
1588 
1589 inline int
cmpSearchBound(TuxCtx & ctx,const KeyBoundC & searchBound,const KeyDataC & entryKey,Uint32 cnt)1590 Dbtux::cmpSearchBound(TuxCtx& ctx, const KeyBoundC& searchBound, const KeyDataC& entryKey, Uint32 cnt)
1591 {
1592   // compare cnt attributes from each
1593   Uint32 num_eq;
1594   int ret = searchBound.cmp(entryKey, cnt, num_eq);
1595 #ifdef VM_TRACE
1596   if (debugFlags & DebugScan) {
1597     tuxDebugOut << "cmpSearchBound: res:" << ret;
1598     tuxDebugOut << " search:" << searchBound.print(ctx.c_debugBuffer, DebugBufferBytes);
1599     tuxDebugOut << " entry:" << entryKey.print(ctx.c_debugBuffer, DebugBufferBytes);
1600     tuxDebugOut << endl;
1601   }
1602 #endif
1603   return ret;
1604 }
1605 
1606 inline
1607 void
prepare_all_tup_ptrs(TuxCtx & ctx)1608 Dbtux::prepare_all_tup_ptrs(TuxCtx& ctx)
1609 {
1610   c_tup->get_all_tup_ptrs(ctx.fragPtr.p->m_tupIndexFragPtrI,
1611                           ctx.fragPtr.p->m_tupTableFragPtrI,
1612                           &ctx.tupIndexFragPtr,
1613                           &ctx.tupIndexTablePtr,
1614                           &ctx.tupRealFragPtr,
1615                           &ctx.tupRealTablePtr,
1616                           ctx.attrDataOffset,
1617                           ctx.tuxFixHeaderSize);
1618 }
1619 #undef JAM_FILE_ID
1620 
1621 #endif
1622