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