1 /*
2 Copyright (c) 2003, 2011, 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 SIMULATEDBLOCK_H
26 #define SIMULATEDBLOCK_H
27
28 #include <NdbTick.h>
29 #include <kernel_types.h>
30 #include <util/version.h>
31 #include <ndb_limits.h>
32
33 #include "VMSignal.hpp"
34 #include <RefConvert.hpp>
35 #include <BlockNumbers.h>
36 #include <GlobalSignalNumbers.h>
37
38 #include "pc.hpp"
39 #include "Pool.hpp"
40 #include <NodeInfo.hpp>
41 #include <NodeState.hpp>
42 #include "GlobalData.hpp"
43 #include "LongSignal.hpp"
44 #include <SignalLoggerManager.hpp>
45
46 #include <ErrorReporter.hpp>
47 #include <ErrorHandlingMacros.hpp>
48
49 #include "DLList.hpp"
50 #include "ArrayPool.hpp"
51 #include "DLHashTable.hpp"
52 #include "WOPool.hpp"
53 #include "RWPool.hpp"
54 #include "Callback.hpp"
55 #include "SafeCounter.hpp"
56
57 #include <mgmapi.h>
58 #include <mgmapi_config_parameters.h>
59 #include <mgmapi_config_parameters_debug.h>
60 #include <kernel_config_parameters.h>
61 #include <Configuration.hpp>
62
63 #include <signaldata/ReadConfig.hpp>
64 #include "ndbd_malloc_impl.hpp"
65 #include <blocks/record_types.hpp>
66
67 #include "Ndbinfo.hpp"
68
69 #ifdef VM_TRACE
70 #define D(x) \
71 do { \
72 char buf[200]; \
73 if (!debugOutOn()) break; \
74 debugOutLock(); \
75 debugOutStream() << debugOutTag(buf, __LINE__) << x << dec << "\n"; \
76 debugOutUnlock(); \
77 } while (0)
78 #define V(x) " " << #x << ":" << (x)
79 #else
80 #define D(x) do { } while(0)
81 #undef V
82 #endif
83
84 /**
85 * Something for filesystem access
86 */
87 struct NewBaseAddrBits /* 32 bits */
88 {
89 unsigned int q : 4; /* Highest index - 2log */
90 /* Strings are treated as 16 bit indexed */
91 /* variables with the number of characters in */
92 /* index 0, byte 0 */
93 unsigned int v : 3; /* Size in bits - 2log */
94 unsigned int unused : 25 ;
95 };
96
97 typedef struct NewVar
98 {
99 Uint32 * WA;
100 Uint32 nrr;
101 Uint32 ClusterSize; /* Real Cluster size */
102 NewBaseAddrBits bits;
103 } NewVARIABLE; /* 128 bits */
104
105 struct Block_context
106 {
Block_contextBlock_context107 Block_context(class Configuration& cfg, class Ndbd_mem_manager& mm)
108 : m_config(cfg), m_mm(mm) {}
109 class Configuration& m_config;
110 class Ndbd_mem_manager& m_mm;
111 };
112
113 class SimulatedBlock {
114 friend class TraceLCP;
115 friend class SafeCounter;
116 friend class SafeCounterManager;
117 friend class AsyncFile;
118 friend class PosixAsyncFile; // FIXME
119 friend class Win32AsyncFile;
120 friend class Pgman;
121 friend class Page_cache_client;
122 friend class Lgman;
123 friend class Logfile_client;
124 friend class Tablespace_client;
125 friend class Dbtup_client;
126 friend struct Pool_context;
127 friend struct SectionHandle;
128 friend class LockQueue;
129 friend class SimplePropertiesSectionWriter;
130 public:
131 friend class BlockComponent;
132 virtual ~SimulatedBlock();
133
134 protected:
135 /**
136 * Constructor
137 */
138 SimulatedBlock(BlockNumber blockNumber,
139 struct Block_context & ctx,
140 Uint32 instanceNumber = 0);
141
142 /**********************************************************
143 * Handling of execFunctions
144 */
145 typedef void (SimulatedBlock::* ExecFunction)(Signal* signal);
146 void addRecSignalImpl(GlobalSignalNumber g, ExecFunction fun, bool f =false);
147 void installSimulatedBlockFunctions();
148 ExecFunction theExecArray[MAX_GSN+1];
149
150 void initCommon();
151 public:
152 typedef void (SimulatedBlock::* CallbackFunction)(class Signal*,
153 Uint32 callbackData,
154 Uint32 returnCode);
155 struct Callback {
156 CallbackFunction m_callbackFunction;
157 Uint32 m_callbackData;
158 };
159
160 /**
161 *
162 */
163 inline void executeFunction(GlobalSignalNumber gsn, Signal* signal);
164
165 /* Multiple block instances */
instance() const166 Uint32 instance() const {
167 return theInstance;
168 }
getInstance(Uint32 instanceNumber)169 SimulatedBlock* getInstance(Uint32 instanceNumber) {
170 ndbrequire(theInstance == 0); // valid only on main instance
171 if (instanceNumber == 0)
172 return this;
173 ndbrequire(instanceNumber < MaxInstances);
174 if (theInstanceList != 0)
175 return theInstanceList[instanceNumber];
176 return 0;
177 }
178 void addInstance(SimulatedBlock* b, Uint32 theInstanceNo);
loadWorkers()179 virtual void loadWorkers() {}
180
181 struct ThreadContext
182 {
183 Uint32 threadId;
184 EmulatedJamBuffer* jamBuffer;
185 Uint32 * watchDogCounter;
186 SectionSegmentPool::Cache * sectionPoolCache;
187 };
188 /* Setup state of a block object for executing in a particular thread. */
189 void assignToThread(ThreadContext ctx);
190 /* For multithreaded ndbd, get the id of owning thread. */
getThreadId() const191 uint32 getThreadId() const { return m_threadId; }
192 static bool isMultiThreaded();
193
194 /* Configuration based alternative. Applies only to this node */
isNdbMt()195 static bool isNdbMt() { return globalData.isNdbMt; }
isNdbMtLqh()196 static bool isNdbMtLqh() { return globalData.isNdbMtLqh; }
getLqhWorkers()197 static Uint32 getLqhWorkers() { return globalData.ndbMtLqhWorkers; }
198
199 /**
200 * Assert that thread calling this function is "owner" of block instance
201 */
202 #ifdef VM_TRACE
203 void assertOwnThread();
204 #else
assertOwnThread()205 void assertOwnThread(){ }
206 #endif
207
208 /*
209 * Instance key (1-4) is used only when sending a signal. Receiver
210 * maps it to actual instance (0, if receiver is not MT LQH).
211 *
212 * For performance reason, DBTC gets instance key directly from DBDIH
213 * via DI*GET*NODES*REQ signals.
214 */
215 static Uint32 getInstanceKey(Uint32 tabId, Uint32 fragId);
216 static Uint32 getInstanceFromKey(Uint32 instanceKey); // local use only
217
218 /**
219 * This method will make sure that when callback in called each
220 * thread running an instance any of the threads in blocks[]
221 * will have executed a signal
222 */
223 void synchronize_threads_for_blocks(Signal*, const Uint32 blocks[],
224 const Callback&, JobBufferLevel = JBB);
225
226 /**
227 * This method make sure that the path specified in blocks[]
228 * will be traversed before returning
229 */
230 void synchronize_path(Signal*, const Uint32 blocks[],
231 const Callback&, JobBufferLevel = JBB);
232
233 private:
234 struct SyncThreadRecord
235 {
236 Callback m_callback;
237 Uint32 m_cnt;
238 Uint32 nextPool;
239 };
240 ArrayPool<SyncThreadRecord> c_syncThreadPool;
241 void execSYNC_THREAD_REQ(Signal*);
242 void execSYNC_THREAD_CONF(Signal*);
243
244 void execSYNC_REQ(Signal*);
245
246 void execSYNC_PATH_REQ(Signal*);
247 void execSYNC_PATH_CONF(Signal*);
248 public:
get_filename(Uint32 fd) const249 virtual const char* get_filename(Uint32 fd) const { return "";}
250 protected:
251 static Callback TheEmptyCallback;
252 void TheNULLCallbackFunction(class Signal*, Uint32, Uint32);
253 static Callback TheNULLCallback;
254 void execute(Signal* signal, Callback & c, Uint32 returnCode);
255
256
257 /**********************************************************
258 * Send signal - dialects
259 */
260
261 void sendSignal(BlockReference ref,
262 GlobalSignalNumber gsn,
263 Signal* signal,
264 Uint32 length,
265 JobBufferLevel jbuf ) const ;
266
267 void sendSignal(NodeReceiverGroup rg,
268 GlobalSignalNumber gsn,
269 Signal* signal,
270 Uint32 length,
271 JobBufferLevel jbuf ) const ;
272
273 void sendSignal(BlockReference ref,
274 GlobalSignalNumber gsn,
275 Signal* signal,
276 Uint32 length,
277 JobBufferLevel jbuf,
278 SectionHandle* sections) const;
279
280 void sendSignal(NodeReceiverGroup rg,
281 GlobalSignalNumber gsn,
282 Signal* signal,
283 Uint32 length,
284 JobBufferLevel jbuf,
285 SectionHandle* sections) const;
286
287 void sendSignal(BlockReference ref,
288 GlobalSignalNumber gsn,
289 Signal* signal,
290 Uint32 length,
291 JobBufferLevel jbuf,
292 LinearSectionPtr ptr[3],
293 Uint32 noOfSections) const ;
294
295 void sendSignal(NodeReceiverGroup rg,
296 GlobalSignalNumber gsn,
297 Signal* signal,
298 Uint32 length,
299 JobBufferLevel jbuf,
300 LinearSectionPtr ptr[3],
301 Uint32 noOfSections) const ;
302
303 /* NoRelease sendSignal variants do not release sections as
304 * a side-effect of sending. This requires extra
305 * copying for local sends
306 */
307 void sendSignalNoRelease(BlockReference ref,
308 GlobalSignalNumber gsn,
309 Signal* signal,
310 Uint32 length,
311 JobBufferLevel jbuf,
312 SectionHandle* sections) const;
313
314 void sendSignalNoRelease(NodeReceiverGroup rg,
315 GlobalSignalNumber gsn,
316 Signal* signal,
317 Uint32 length,
318 JobBufferLevel jbuf,
319 SectionHandle* sections) const;
320
321 // Send multiple signal with delay. In this VM the jobbufffer level has
322 // no effect on on delayed signals
323 //
324 void sendSignalWithDelay(BlockReference ref,
325 GlobalSignalNumber gsn,
326 Signal* signal,
327 Uint32 delayInMilliSeconds,
328 Uint32 length) const ;
329
330 void sendSignalWithDelay(BlockReference ref,
331 GlobalSignalNumber gsn,
332 Signal* signal,
333 Uint32 delayInMilliSeconds,
334 Uint32 length,
335 SectionHandle* sections) const;
336
337 /*
338 * Instance defaults to instance of sender. Using explicit
339 * instance argument asserts that the call is thread-safe.
340 */
341 void EXECUTE_DIRECT(Uint32 block,
342 Uint32 gsn,
343 Signal* signal,
344 Uint32 len,
345 Uint32 givenInstanceNo = ZNIL);
346
347 class SectionSegmentPool& getSectionSegmentPool();
348 void release(SegmentedSectionPtr & ptr);
release(SegmentedSectionPtrPOD & ptr)349 void release(SegmentedSectionPtrPOD & ptr) {
350 SegmentedSectionPtr tmp(ptr);
351 release(tmp);
352 ptr.setNull();
353 }
354 void releaseSection(Uint32 firstSegmentIVal);
355 void releaseSections(struct SectionHandle&);
356
357 bool import(Ptr<SectionSegment> & first, const Uint32 * src, Uint32 len);
358 bool import(SegmentedSectionPtr& ptr, const Uint32* src, Uint32 len);
359 bool appendToSection(Uint32& firstSegmentIVal, const Uint32* src, Uint32 len);
360 bool dupSection(Uint32& copyFirstIVal, Uint32 srcFirstIVal);
361 bool writeToSection(Uint32 firstSegmentIVal, Uint32 offset, const Uint32* src, Uint32 len);
362
363 void handle_invalid_sections_in_send_signal(Signal*) const;
364 void handle_lingering_sections_after_execute(Signal*) const;
365 void handle_lingering_sections_after_execute(SectionHandle*) const;
366 void handle_invalid_fragmentInfo(Signal*) const;
367 void handle_send_failed(SendStatus, Signal*) const;
368 void handle_out_of_longsignal_memory(Signal*) const;
369
370 /**
371 * Send routed signals (ONLY LOCALLY)
372 *
373 * NOTE: Only localhost is allowed!
374 */
375 struct RoutePath
376 {
377 Uint32 ref;
378 JobBufferLevel prio;
379 };
380 void sendRoutedSignal(RoutePath path[],
381 Uint32 pathcnt, // #hops
382 Uint32 dst[], // Final destination(s)
383 Uint32 dstcnt, // #final destination(s)
384 Uint32 gsn, // Final GSN
385 Signal*,
386 Uint32 len,
387 JobBufferLevel prio, // Final prio
388 SectionHandle * handle = 0);
389
390
391 /**
392 * Check that signal sent from remote node
393 * is guaranteed to be correctly serialized wrt to NODE_FAILREP
394 */
395 bool checkNodeFailSequence(Signal*);
396
397 /**********************************************************
398 * Fragmented signals
399 */
400
401 /**
402 * Assemble fragments
403 *
404 * @return true if all fragments has arrived
405 * false otherwise
406 */
407 bool assembleFragments(Signal * signal);
408
409 /**
410 * Assemble dropped fragments
411 *
412 * Should be called at the start of a Dropped Signal Report
413 * (GSN_DROPPED_SIGNAL_REP) handler when it is expected that
414 * the block could receive fragmented signals.
415 * No dropped signal handling should be done until this method
416 * returns true.
417 *
418 * @return true if all fragments has arrived and dropped signal
419 * handling can proceed.
420 * false otherwise
421 */
422 bool assembleDroppedFragments(Signal * signal);
423
424 /* If send size is > FRAGMENT_WORD_SIZE, fragments of this size
425 * will be sent by the sendFragmentedSignal variants
426 */
427 STATIC_CONST( FRAGMENT_WORD_SIZE = 240 );
428
429 void sendFragmentedSignal(BlockReference ref,
430 GlobalSignalNumber gsn,
431 Signal* signal,
432 Uint32 length,
433 JobBufferLevel jbuf,
434 SectionHandle * sections,
435 Callback & = TheEmptyCallback,
436 Uint32 messageSize = FRAGMENT_WORD_SIZE);
437
438 void sendFragmentedSignal(NodeReceiverGroup rg,
439 GlobalSignalNumber gsn,
440 Signal* signal,
441 Uint32 length,
442 JobBufferLevel jbuf,
443 SectionHandle * sections,
444 Callback & = TheEmptyCallback,
445 Uint32 messageSize = FRAGMENT_WORD_SIZE);
446
447 void sendFragmentedSignal(BlockReference ref,
448 GlobalSignalNumber gsn,
449 Signal* signal,
450 Uint32 length,
451 JobBufferLevel jbuf,
452 LinearSectionPtr ptr[3],
453 Uint32 noOfSections,
454 Callback & = TheEmptyCallback,
455 Uint32 messageSize = FRAGMENT_WORD_SIZE);
456
457 void sendFragmentedSignal(NodeReceiverGroup rg,
458 GlobalSignalNumber gsn,
459 Signal* signal,
460 Uint32 length,
461 JobBufferLevel jbuf,
462 LinearSectionPtr ptr[3],
463 Uint32 noOfSections,
464 Callback & = TheEmptyCallback,
465 Uint32 messageSize = FRAGMENT_WORD_SIZE);
466
467 /**
468 * simBlockNodeFailure
469 *
470 * Method must be called by blocks that send or receive
471 * remote Fragmented Signals when they detect a node
472 * (NDBD or API) failure.
473 * If the block needs to acknowledge or perform further
474 * processing after completing block-level node failure
475 * handling, it can supply a Callback which will be invoked
476 * when block-level node failure handling has completed.
477 * Otherwise TheEmptyCallback is used.
478 * If TheEmptyCallback is used, all failure handling is
479 * performed in the current timeslice, to avoid any
480 * races.
481 *
482 * Parameters
483 * signal : Current signal*
484 * failedNodeId : Node id of failed node
485 * cb : Callback to be executed when block-level
486 * node failure handling completed.
487 * TheEmptyCallback is passed if no further
488 * processing is required.
489 * Returns
490 * Number of 'resources' cleaned up in call.
491 * Callback return code is total resources cleaned up.
492 *
493 */
494 Uint32 simBlockNodeFailure(Signal* signal,
495 Uint32 failedNodeId,
496 Callback& cb = TheEmptyCallback);
497
498 /**********************************************************
499 * Fragmented signals structures
500 */
501
502 /**
503 * Struct used when assembling fragmented long signals at receiver side
504 */
505 struct FragmentInfo {
506 FragmentInfo(Uint32 fragId, Uint32 sender);
507
508 Uint32 m_senderRef;
509 Uint32 m_fragmentId;
510 Uint32 m_sectionPtrI[3];
511 union {
512 Uint32 nextPool;
513 Uint32 nextHash;
514 };
515 Uint32 prevHash;
516
equalSimulatedBlock::FragmentInfo517 inline bool equal(FragmentInfo & p) const {
518 return m_senderRef == p.m_senderRef && m_fragmentId == p.m_fragmentId;
519 }
520
hashValueSimulatedBlock::FragmentInfo521 inline Uint32 hashValue() const {
522 return m_senderRef + m_fragmentId ;
523 }
524
isDroppedSimulatedBlock::FragmentInfo525 inline bool isDropped() const {
526 /* IsDropped when entry in hash, but no segments stored */
527 return (( m_sectionPtrI[0] == RNIL ) &&
528 ( m_sectionPtrI[1] == RNIL ) &&
529 ( m_sectionPtrI[2] == RNIL ) );
530 }
531 }; // sizeof() = 32 bytes
532
533 /**
534 * Struct used when sending fragmented signals
535 */
536 struct FragmentSendInfo {
537 FragmentSendInfo();
538
539 enum Status {
540 SendNotComplete = 0,
541 SendComplete = 1,
542 SendCancelled = 2
543 };
544 Uint8 m_status;
545 Uint8 m_prio;
546 Uint8 m_fragInfo;
547 enum Flags {
548 SendNoReleaseSeg = 0x1
549 };
550 Uint8 m_flags;
551 Uint16 m_gsn;
552 Uint16 m_messageSize; // Size of each fragment
553 Uint32 m_fragmentId;
554 union {
555 Ptr<struct SectionSegment> m_segmented;
556 LinearSectionPtr m_linear;
557 } m_sectionPtr[3];
558 LinearSectionPtr m_theDataSection;
559 NodeReceiverGroup m_nodeReceiverGroup; // 3
560 Callback m_callback;
561 union {
562 Uint32 nextPool;
563 Uint32 nextList;
564 };
565 Uint32 prevList;
566 };
567
568 /**
569 * sendFirstFragment
570 * Used by sendFragmentedSignal
571 * noRelease can only be used if the caller can guarantee
572 * not to free the supplied sections until all fragments
573 * have been sent.
574 */
575 bool sendFirstFragment(FragmentSendInfo & info,
576 NodeReceiverGroup rg,
577 GlobalSignalNumber gsn,
578 Signal* signal,
579 Uint32 length,
580 JobBufferLevel jbuf,
581 SectionHandle * sections,
582 bool noRelease,
583 Uint32 messageSize = FRAGMENT_WORD_SIZE);
584
585 bool sendFirstFragment(FragmentSendInfo & info,
586 NodeReceiverGroup rg,
587 GlobalSignalNumber gsn,
588 Signal* signal,
589 Uint32 length,
590 JobBufferLevel jbuf,
591 LinearSectionPtr ptr[3],
592 Uint32 noOfSections,
593 Uint32 messageSize = FRAGMENT_WORD_SIZE);
594
595 /**
596 * Send signal fragment
597 *
598 * @see sendFragmentedSignal
599 */
600 void sendNextSegmentedFragment(Signal* signal, FragmentSendInfo & info);
601
602 /**
603 * Send signal fragment
604 *
605 * @see sendFragmentedSignal
606 */
607 void sendNextLinearFragment(Signal* signal, FragmentSendInfo & info);
608
609 BlockNumber number() const;
610 public:
611 /* Must be public so that we can jam() outside of block scope. */
612 EmulatedJamBuffer *jamBuffer() const;
613 protected:
614 BlockReference reference() const;
615 NodeId getOwnNodeId() const;
616
617 /**
618 * Refresh Watch Dog in initialising code
619 *
620 */
621 void refresh_watch_dog(Uint32 place = 1);
622 void update_watch_dog_timer(Uint32 interval);
623
624 /**
625 * Prog error
626 * This function should be called when this node should be shutdown
627 * If the cause of the shutdown is known use extradata to add an
628 * errormessage describing the problem
629 */
630 void progError(int line, int err_code, const char* extradata=NULL) const
631 ATTRIBUTE_NORETURN;
632 private:
633 void signal_error(Uint32, Uint32, Uint32, const char*, int) const
634 ATTRIBUTE_NORETURN;
635 const NodeId theNodeId;
636 const BlockNumber theNumber;
637 const Uint32 theInstance;
638 const BlockReference theReference;
639 /*
640 * Instance 0 is the main instance. It creates/owns other instances.
641 * In MT LQH main instance is the LQH proxy and the others ("workers")
642 * are real LQHs run by multiple threads.
643 */
644 enum { MaxInstances = 1 + MAX_NDBMT_LQH_WORKERS + 1 }; // main+lqh+extra
645 SimulatedBlock** theInstanceList; // set in main, indexed by instance
646 SimulatedBlock* theMainInstance; // set in all
647 /*
648 Thread id currently executing this block.
649 Not used in singlethreaded ndbd.
650 */
651 Uint32 m_threadId;
652 /*
653 Jam buffer reference.
654 In multithreaded ndbd, this is different in each thread, and must be
655 updated if migrating the block to another thread.
656 */
657 EmulatedJamBuffer *m_jamBuffer;
658 /* For multithreaded ndb, the thread-specific watchdog counter. */
659 Uint32 *m_watchDogCounter;
660
661 SectionSegmentPool::Cache * m_sectionPoolCache;
662
663
664 Uint32 doNodeFailureCleanup(Signal* signal,
665 Uint32 failedNodeId,
666 Uint32 resource,
667 Uint32 cursor,
668 Uint32 elementsCleaned,
669 Callback& cb);
670
671 bool doCleanupFragInfo(Uint32 failedNodeId,
672 Uint32& cursor,
673 Uint32& rtUnitsUsed,
674 Uint32& elementsCleaned);
675
676 bool doCleanupFragSend(Uint32 failedNodeId,
677 Uint32& cursor,
678 Uint32& rtUnitsUsed,
679 Uint32& elementsCleaned);
680
681 protected:
682 Block_context m_ctx;
683 NewVARIABLE* allocateBat(int batSize);
684 void freeBat();
685 static const NewVARIABLE* getBat (BlockNumber blockNo,
686 Uint32 instanceNo);
687 static Uint16 getBatSize(BlockNumber blockNo,
688 Uint32 instanceNo);
689
690 static BlockReference calcTcBlockRef (NodeId aNode);
691 static BlockReference calcLqhBlockRef (NodeId aNode);
692 static BlockReference calcAccBlockRef (NodeId aNode);
693 static BlockReference calcTupBlockRef (NodeId aNode);
694 static BlockReference calcTuxBlockRef (NodeId aNode);
695 static BlockReference calcDihBlockRef (NodeId aNode);
696 static BlockReference calcQmgrBlockRef (NodeId aNode);
697 static BlockReference calcDictBlockRef (NodeId aNode);
698 static BlockReference calcNdbCntrBlockRef (NodeId aNode);
699 static BlockReference calcTrixBlockRef (NodeId aNode);
700 static BlockReference calcBackupBlockRef (NodeId aNode);
701 static BlockReference calcSumaBlockRef (NodeId aNode);
702
703 static BlockReference calcApiClusterMgrBlockRef (NodeId aNode);
704
705 // matching instance on same node e.g. LQH-ACC-TUP
706 BlockReference calcInstanceBlockRef(BlockNumber aBlock);
707
708 // matching instance on another node e.g. LQH-LQH
709 // valid only if receiver has same number of workers
710 BlockReference calcInstanceBlockRef(BlockNumber aBlock, NodeId aNode);
711
712 /**
713 * allocRecord
714 * Allocates memory for the datastructures where ndb keeps the data
715 *
716 */
717 void* allocRecord(const char * type, size_t s, size_t n, bool clear = true, Uint32 paramId = 0);
718 void* allocRecordAligned(const char * type, size_t s, size_t n, void **unaligned_buffer, Uint32 align = NDB_O_DIRECT_WRITE_ALIGNMENT, bool clear = true, Uint32 paramId = 0);
719
720 /**
721 * Deallocate record
722 *
723 * NOTE: Also resets pointer
724 */
725 void deallocRecord(void **, const char * type, size_t s, size_t n);
726
727 /**
728 * Allocate memory from global pool,
729 * returns #chunks used
730 *
731 * Typically used by part of code, not converted to use global pool
732 * directly, but allocates everything during startup
733 */
734 struct AllocChunk
735 {
736 Uint32 ptrI;
737 Uint32 cnt;
738 };
739 Uint32 allocChunks(AllocChunk dst[], Uint32 /* size of dst */ arraysize,
740 Uint32 /* resource group */ rg,
741 Uint32 /* no of pages to allocate */ pages,
742 Uint32 paramId /* for error message if failing */);
743
744 static int sortchunks(const void*, const void*);
745
746 /**
747 * General info event (sent to cluster log)
748 */
749 void infoEvent(const char * msg, ...) const
750 ATTRIBUTE_FORMAT(printf, 2, 3);
751 void warningEvent(const char * msg, ...) const
752 ATTRIBUTE_FORMAT(printf, 2, 3);
753
754 /**
755 * Get node state
756 */
757 const NodeState & getNodeState() const;
758
759 /**
760 * Get node info
761 */
762 const NodeInfo & getNodeInfo(NodeId nodeId) const;
763 NodeInfo & setNodeInfo(NodeId);
764
765 const NodeVersionInfo& getNodeVersionInfo() const;
766 NodeVersionInfo& setNodeVersionInfo();
767
768 /**********************
769 * Xfrm stuff
770 */
771
772 /**
773 * @return length
774 */
775 Uint32 xfrm_key(Uint32 tab, const Uint32* src,
776 Uint32 *dst, Uint32 dstSize,
777 Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX]) const;
778
779 Uint32 xfrm_attr(Uint32 attrDesc, CHARSET_INFO* cs,
780 const Uint32* src, Uint32 & srcPos,
781 Uint32* dst, Uint32 & dstPos, Uint32 dstSize) const;
782
783 /**
784 *
785 */
786 Uint32 create_distr_key(Uint32 tableId,
787 const Uint32* src,
788 Uint32 *dst,
789 const Uint32 keyPaLen[MAX_ATTRIBUTES_IN_INDEX])const;
790
791 /**
792 * if ndbd,
793 * wakeup main-loop if sleeping on IO
794 * if ndbmtd
795 * wakeup thread running block-instance
796 */
797 void wakeup();
798
799 /**
800 * setup struct for wakeup
801 */
802 void setup_wakeup();
803
804 private:
805 NewVARIABLE* NewVarRef; /* New Base Address Table for block */
806 Uint16 theBATSize; /* # entries in BAT */
807
808 protected:
809 SafeArrayPool<GlobalPage>& m_global_page_pool;
810 ArrayPool<GlobalPage>& m_shared_page_pool;
811
812 void execNDB_TAMPER(Signal * signal);
813 void execNODE_STATE_REP(Signal* signal);
814 void execCHANGE_NODE_STATE_REQ(Signal* signal);
815
816 void execSIGNAL_DROPPED_REP(Signal* signal);
817 void execCONTINUE_FRAGMENTED(Signal* signal);
818 void execSTOP_FOR_CRASH(Signal* signal);
819 void execAPI_START_REP(Signal* signal);
820 void execNODE_START_REP(Signal* signal);
821 void execSEND_PACKED(Signal* signal);
822 void execLOCAL_ROUTE_ORD(Signal*);
823 private:
824 /**
825 * Node state
826 */
827 NodeState theNodeState;
828
829 Uint32 c_fragmentIdCounter;
830 ArrayPool<FragmentInfo> c_fragmentInfoPool;
831 DLHashTable<FragmentInfo> c_fragmentInfoHash;
832
833 bool c_fragSenderRunning;
834 ArrayPool<FragmentSendInfo> c_fragmentSendPool;
835 DLList<FragmentSendInfo> c_linearFragmentSendList;
836 DLList<FragmentSendInfo> c_segmentedFragmentSendList;
837
838 protected:
839 Uint32 debugPrintFragmentCounts();
840
841 public:
842 class MutexManager {
843 friend class Mutex;
844 friend class SimulatedBlock;
845 friend class DbUtil;
846 public:
847 MutexManager(class SimulatedBlock &);
848
849 bool setSize(Uint32 maxNoOfActiveMutexes);
850 Uint32 getSize() const ; // Get maxNoOfActiveMutexes
851
852 private:
853 /**
854 * core interface
855 */
856 struct ActiveMutex {
ActiveMutexSimulatedBlock::MutexManager::ActiveMutex857 ActiveMutex() {}
858 Uint32 m_gsn; // state
859 Uint32 m_mutexId;
860 Callback m_callback;
861 union {
862 Uint32 nextPool;
863 Uint32 nextList;
864 };
865 Uint32 prevList;
866 };
867 typedef Ptr<ActiveMutex> ActiveMutexPtr;
868
869 bool seize(ActiveMutexPtr& ptr);
870 void release(Uint32 activeMutexPtrI);
871
872 void getPtr(ActiveMutexPtr& ptr);
873
874 void create(Signal*, ActiveMutexPtr&);
875 void destroy(Signal*, ActiveMutexPtr&);
876 void lock(Signal*, ActiveMutexPtr&, Uint32 flags);
877 void unlock(Signal*, ActiveMutexPtr&);
878
879 private:
880 void execUTIL_CREATE_LOCK_REF(Signal* signal);
881 void execUTIL_CREATE_LOCK_CONF(Signal* signal);
882 void execUTIL_DESTORY_LOCK_REF(Signal* signal);
883 void execUTIL_DESTORY_LOCK_CONF(Signal* signal);
884 void execUTIL_LOCK_REF(Signal* signal);
885 void execUTIL_LOCK_CONF(Signal* signal);
886 void execUTIL_UNLOCK_REF(Signal* signal);
887 void execUTIL_UNLOCK_CONF(Signal* signal);
888
889 SimulatedBlock & m_block;
890 ArrayPool<ActiveMutex> m_mutexPool;
891 DLList<ActiveMutex> m_activeMutexes;
892
893 BlockReference reference() const;
894 void progError(int line, int err_code, const char* extra = 0);
895 };
896
897 friend class MutexManager;
898 MutexManager c_mutexMgr;
899
900 void ignoreMutexUnlockCallback(Signal* signal, Uint32 ptrI, Uint32 retVal);
getParam(const char * param,Uint32 * retVal)901 virtual bool getParam(const char * param, Uint32 * retVal) { return false;}
902
903 SafeCounterManager c_counterMgr;
904 private:
905 void execUTIL_CREATE_LOCK_REF(Signal* signal);
906 void execUTIL_CREATE_LOCK_CONF(Signal* signal);
907 void execUTIL_DESTORY_LOCK_REF(Signal* signal);
908 void execUTIL_DESTORY_LOCK_CONF(Signal* signal);
909 void execUTIL_LOCK_REF(Signal* signal);
910 void execUTIL_LOCK_CONF(Signal* signal);
911 void execUTIL_UNLOCK_REF(Signal* signal);
912 void execUTIL_UNLOCK_CONF(Signal* signal);
913
914 protected:
915
916 void fsRefError(Signal* signal, Uint32 line, const char *msg);
917 void execFSWRITEREF(Signal* signal);
918 void execFSREADREF(Signal* signal);
919 void execFSOPENREF(Signal* signal);
920 void execFSCLOSEREF(Signal* signal);
921 void execFSREMOVEREF(Signal* signal);
922 void execFSSYNCREF(Signal* signal);
923 void execFSAPPENDREF(Signal* signal);
924
925 // MT LQH callback CONF via signal
926 public:
927 struct CallbackPtr {
928 Uint32 m_callbackIndex;
929 Uint32 m_callbackData;
930 };
931 protected:
932 enum CallbackFlags {
933 CALLBACK_DIRECT = 0x0001, // use EXECUTE_DIRECT (assumed thread safe)
934 CALLBACK_ACK = 0x0002 // send ack at the end of callback timeslice
935 };
936
937 struct CallbackEntry {
938 CallbackFunction m_function;
939 Uint32 m_flags;
940 };
941
942 struct CallbackTable {
943 Uint32 m_count;
944 CallbackEntry* m_entry; // array
945 };
946
947 CallbackTable* m_callbackTableAddr; // set by block if used
948
949 enum {
950 THE_NULL_CALLBACK = 0 // must assign TheNULLCallbackFunction
951 };
952
953 void execute(Signal* signal, CallbackPtr & cptr, Uint32 returnCode);
954 const CallbackEntry& getCallbackEntry(Uint32 ci);
955 void sendCallbackConf(Signal* signal, Uint32 fullBlockNo,
956 CallbackPtr& cptr, Uint32 returnCode);
957 void execCALLBACK_CONF(Signal* signal);
958
959 // Variable for storing inserted errors, see pc.H
960 ERROR_INSERT_VARIABLE;
961
962 #ifdef VM_TRACE_TIME
963 public:
964 void clearTimes();
965 void printTimes(FILE * output);
966 void addTime(Uint32 gsn, Uint64 time);
967 void subTime(Uint32 gsn, Uint64 time);
968 struct TimeTrace {
969 Uint32 cnt;
970 Uint64 sum, sub;
971 } m_timeTrace[MAX_GSN+1];
972 Uint32 m_currentGsn;
973 #endif
974
975 #ifdef VM_TRACE
976 Ptr<void> **m_global_variables, **m_global_variables_save;
977 void clear_global_variables();
978 void init_globals_list(void ** tmp, size_t cnt);
979 void disable_global_variables();
980 void enable_global_variables();
981 #endif
982
983 #ifdef VM_TRACE
984 public:
985 NdbOut debugOut;
debugOutStream()986 NdbOut& debugOutStream() { return debugOut; };
987 bool debugOutOn();
debugOutLock()988 void debugOutLock() { globalSignalLoggers.lock(); }
debugOutUnlock()989 void debugOutUnlock() { globalSignalLoggers.unlock(); }
990 const char* debugOutTag(char* buf, int line);
991 #endif
992
993 void ndbinfo_send_row(Signal* signal,
994 const DbinfoScanReq& req,
995 const Ndbinfo::Row& row,
996 Ndbinfo::Ratelimit& rl) const;
997
998 void ndbinfo_send_scan_break(Signal* signal,
999 DbinfoScanReq& req,
1000 const Ndbinfo::Ratelimit& rl,
1001 Uint32 data1, Uint32 data2 = 0,
1002 Uint32 data3 = 0, Uint32 data4 = 0) const;
1003
1004 void ndbinfo_send_scan_conf(Signal* signal,
1005 DbinfoScanReq& req,
1006 const Ndbinfo::Ratelimit& rl) const;
1007
1008 };
1009
1010 // outside blocks e.g. within a struct
1011 #ifdef VM_TRACE
1012 #define DEBUG_OUT_DEFINES(blockNo) \
1013 static SimulatedBlock* debugOutBlock() \
1014 { return globalData.getBlock(blockNo); } \
1015 static NdbOut& debugOutStream() \
1016 { return debugOutBlock()->debugOutStream(); } \
1017 static bool debugOutOn() \
1018 { return debugOutBlock()->debugOutOn(); } \
1019 static void debugOutLock() \
1020 { debugOutBlock()->debugOutLock(); } \
1021 static void debugOutUnlock() \
1022 { debugOutBlock()->debugOutUnlock(); } \
1023 static const char* debugOutTag(char* buf, int line) \
1024 { return debugOutBlock()->debugOutTag(buf, line); } \
1025 static void debugOutDefines()
1026 #else
1027 #define DEBUG_OUT_DEFINES(blockNo) \
1028 static void debugOutDefines()
1029 #endif
1030
1031 inline
1032 void
executeFunction(GlobalSignalNumber gsn,Signal * signal)1033 SimulatedBlock::executeFunction(GlobalSignalNumber gsn, Signal* signal){
1034 ExecFunction f = theExecArray[gsn];
1035 if(gsn <= MAX_GSN && f != 0){
1036 #ifdef VM_TRACE
1037 clear_global_variables();
1038 #endif
1039 (this->*f)(signal);
1040
1041 if (unlikely(signal->header.m_noOfSections))
1042 {
1043 handle_lingering_sections_after_execute(signal);
1044 }
1045 return;
1046 }
1047
1048 /**
1049 * This point only passed if an error has occurred
1050 */
1051 char errorMsg[255];
1052 if (!(gsn <= MAX_GSN)) {
1053 BaseString::snprintf(errorMsg, 255, "Illegal signal received (GSN %d too high)", gsn);
1054 ERROR_SET(fatal, NDBD_EXIT_PRGERR, errorMsg, errorMsg);
1055 }
1056 if (!(theExecArray[gsn] != 0)) {
1057 BaseString::snprintf(errorMsg, 255, "Illegal signal received (GSN %d not added)", gsn);
1058 ERROR_SET(fatal, NDBD_EXIT_PRGERR, errorMsg, errorMsg);
1059 }
1060 ndbrequire(false);
1061 }
1062
1063 inline
1064 void
execute(Signal * signal,Callback & c,Uint32 returnCode)1065 SimulatedBlock::execute(Signal* signal, Callback & c, Uint32 returnCode){
1066 CallbackFunction fun = c.m_callbackFunction;
1067 if (fun == TheNULLCallback.m_callbackFunction)
1068 return;
1069 ndbrequire(fun != 0);
1070 c.m_callbackFunction = NULL;
1071 (this->*fun)(signal, c.m_callbackData, returnCode);
1072 }
1073
1074 inline
1075 void
execute(Signal * signal,CallbackPtr & cptr,Uint32 returnCode)1076 SimulatedBlock::execute(Signal* signal, CallbackPtr & cptr, Uint32 returnCode){
1077 const CallbackEntry& ce = getCallbackEntry(cptr.m_callbackIndex);
1078 cptr.m_callbackIndex = ZNIL;
1079 Callback c;
1080 c.m_callbackFunction = ce.m_function;
1081 c.m_callbackData = cptr.m_callbackData;
1082 execute(signal, c, returnCode);
1083 }
1084
1085 inline
1086 BlockNumber
number() const1087 SimulatedBlock::number() const {
1088 return theNumber;
1089 }
1090
1091 inline
1092 EmulatedJamBuffer *
jamBuffer() const1093 SimulatedBlock::jamBuffer() const {
1094 return m_jamBuffer;
1095 }
1096
1097 inline
1098 BlockReference
reference() const1099 SimulatedBlock::reference() const {
1100 return theReference;
1101 }
1102
1103 inline
1104 NodeId
getOwnNodeId() const1105 SimulatedBlock::getOwnNodeId() const {
1106 return theNodeId;
1107 }
1108
1109 inline
1110 BlockReference
calcTcBlockRef(NodeId aNodeId)1111 SimulatedBlock::calcTcBlockRef (NodeId aNodeId){
1112 return numberToRef(DBTC, aNodeId);
1113 }
1114
1115 inline
1116 BlockReference
calcLqhBlockRef(NodeId aNodeId)1117 SimulatedBlock::calcLqhBlockRef (NodeId aNodeId){
1118 return numberToRef(DBLQH, aNodeId);
1119 }
1120
1121 inline
1122 BlockReference
calcAccBlockRef(NodeId aNodeId)1123 SimulatedBlock::calcAccBlockRef (NodeId aNodeId){
1124 return numberToRef(DBACC, aNodeId);
1125 }
1126
1127 inline
1128 BlockReference
calcTupBlockRef(NodeId aNodeId)1129 SimulatedBlock::calcTupBlockRef (NodeId aNodeId){
1130 return numberToRef(DBTUP, aNodeId);
1131 }
1132
1133 inline
1134 BlockReference
calcTuxBlockRef(NodeId aNodeId)1135 SimulatedBlock::calcTuxBlockRef (NodeId aNodeId){
1136 return numberToRef(DBTUX, aNodeId);
1137 }
1138
1139 inline
1140 BlockReference
calcDihBlockRef(NodeId aNodeId)1141 SimulatedBlock::calcDihBlockRef (NodeId aNodeId){
1142 return numberToRef(DBDIH, aNodeId);
1143 }
1144
1145 inline
1146 BlockReference
calcDictBlockRef(NodeId aNodeId)1147 SimulatedBlock::calcDictBlockRef (NodeId aNodeId){
1148 return numberToRef(DBDICT, aNodeId);
1149 }
1150
1151 inline
1152 BlockReference
calcQmgrBlockRef(NodeId aNodeId)1153 SimulatedBlock::calcQmgrBlockRef (NodeId aNodeId){
1154 return numberToRef(QMGR, aNodeId);
1155 }
1156
1157 inline
1158 BlockReference
calcNdbCntrBlockRef(NodeId aNodeId)1159 SimulatedBlock::calcNdbCntrBlockRef (NodeId aNodeId){
1160 return numberToRef(NDBCNTR, aNodeId);
1161 }
1162
1163 inline
1164 BlockReference
calcTrixBlockRef(NodeId aNodeId)1165 SimulatedBlock::calcTrixBlockRef (NodeId aNodeId){
1166 return numberToRef(TRIX, aNodeId);
1167 }
1168
1169 inline
1170 BlockReference
calcBackupBlockRef(NodeId aNodeId)1171 SimulatedBlock::calcBackupBlockRef (NodeId aNodeId){
1172 return numberToRef(BACKUP, aNodeId);
1173 }
1174
1175 inline
1176 BlockReference
calcSumaBlockRef(NodeId aNodeId)1177 SimulatedBlock::calcSumaBlockRef (NodeId aNodeId){
1178 return numberToRef(SUMA, aNodeId);
1179 }
1180
1181 inline
1182 BlockReference
calcApiClusterMgrBlockRef(NodeId aNodeId)1183 SimulatedBlock::calcApiClusterMgrBlockRef (NodeId aNodeId){
1184 return numberToRef(API_CLUSTERMGR, aNodeId);
1185 }
1186
1187 inline
1188 BlockReference
calcInstanceBlockRef(BlockNumber aBlock)1189 SimulatedBlock::calcInstanceBlockRef(BlockNumber aBlock){
1190 return numberToRef(aBlock, instance(), getOwnNodeId());
1191 }
1192
1193 inline
1194 BlockReference
calcInstanceBlockRef(BlockNumber aBlock,NodeId aNodeId)1195 SimulatedBlock::calcInstanceBlockRef(BlockNumber aBlock, NodeId aNodeId){
1196 return numberToRef(aBlock, instance(), aNodeId);
1197 }
1198
1199 inline
1200 const NodeState &
getNodeState() const1201 SimulatedBlock::getNodeState() const {
1202 return theNodeState;
1203 }
1204
1205 inline
1206 const NodeInfo &
getNodeInfo(NodeId nodeId) const1207 SimulatedBlock::getNodeInfo(NodeId nodeId) const {
1208 ndbrequire(nodeId > 0 && nodeId < MAX_NODES);
1209 return globalData.m_nodeInfo[nodeId];
1210 }
1211
1212 inline
1213 const NodeVersionInfo &
getNodeVersionInfo() const1214 SimulatedBlock::getNodeVersionInfo() const {
1215 return globalData.m_versionInfo;
1216 }
1217
1218 inline
1219 NodeVersionInfo &
setNodeVersionInfo()1220 SimulatedBlock::setNodeVersionInfo() {
1221 return globalData.m_versionInfo;
1222 }
1223
1224 #ifdef VM_TRACE_TIME
1225 inline
1226 void
addTime(Uint32 gsn,Uint64 time)1227 SimulatedBlock::addTime(Uint32 gsn, Uint64 time){
1228 m_timeTrace[gsn].cnt ++;
1229 m_timeTrace[gsn].sum += time;
1230 }
1231
1232 inline
1233 void
subTime(Uint32 gsn,Uint64 time)1234 SimulatedBlock::subTime(Uint32 gsn, Uint64 time){
1235 m_timeTrace[gsn].sub += time;
1236 }
1237 #endif
1238
1239 inline
1240 void
EXECUTE_DIRECT(Uint32 block,Uint32 gsn,Signal * signal,Uint32 len,Uint32 givenInstanceNo)1241 SimulatedBlock::EXECUTE_DIRECT(Uint32 block,
1242 Uint32 gsn,
1243 Signal* signal,
1244 Uint32 len,
1245 Uint32 givenInstanceNo)
1246 {
1247 signal->setLength(len);
1248 SimulatedBlock* b = globalData.getBlock(block);
1249 ndbassert(b != 0);
1250 /**
1251 * In multithreaded NDB, blocks run in different threads, and EXECUTE_DIRECT
1252 * (unlike sendSignal) is generally not thread-safe.
1253 * So only allow EXECUTE_DIRECT between blocks that run in the same thread,
1254 * unless caller explicitly marks it as being thread safe (eg NDBFS),
1255 * by using an explicit instance argument.
1256 * By default instance of sender is used. This is automatically thread-safe
1257 * for worker instances (instance != 0).
1258 */
1259 Uint32 instanceNo = givenInstanceNo;
1260 if (instanceNo == ZNIL)
1261 instanceNo = instance();
1262 if (instanceNo != 0)
1263 b = b->getInstance(instanceNo);
1264 ndbassert(b != 0);
1265 ndbassert(givenInstanceNo != ZNIL || b->getThreadId() == getThreadId());
1266 signal->header.theSendersBlockRef = reference();
1267 #ifdef VM_TRACE
1268 if(globalData.testOn){
1269 signal->header.theVerId_signalNumber = gsn;
1270 signal->header.theReceiversBlockNumber = numberToBlock(block, instanceNo);
1271 globalSignalLoggers.executeDirect(signal->header,
1272 0, // in
1273 &signal->theData[0],
1274 globalData.ownId);
1275 }
1276 #endif
1277 #ifdef VM_TRACE_TIME
1278 Uint32 us1, us2;
1279 Uint64 ms1, ms2;
1280 NdbTick_CurrentMicrosecond(&ms1, &us1);
1281 Uint32 tGsn = m_currentGsn;
1282 b->m_currentGsn = gsn;
1283 #endif
1284 b->executeFunction(gsn, signal);
1285 #ifdef VM_TRACE_TIME
1286 NdbTick_CurrentMicrosecond(&ms2, &us2);
1287 Uint64 diff = ms2;
1288 diff -= ms1;
1289 diff *= 1000000;
1290 diff += us2;
1291 diff -= us1;
1292 b->addTime(gsn, diff);
1293 m_currentGsn = tGsn;
1294 subTime(tGsn, diff);
1295 #endif
1296 }
1297
1298 /**
1299 * Defines for backward compatiblility
1300 */
1301
1302 #define BLOCK_DEFINES(BLOCK) \
1303 typedef void (BLOCK::* ExecSignalLocal) (Signal* signal); \
1304 typedef void (BLOCK::* BlockCallback)(Signal*, Uint32 callb, Uint32 retCode); \
1305 inline CallbackFunction safe_cast(BlockCallback f){ \
1306 return static_cast<CallbackFunction>(f); \
1307 } \
1308 public:\
1309 private: \
1310 void addRecSignal(GlobalSignalNumber gsn, ExecSignalLocal f, bool force = false)
1311
1312 #define BLOCK_CONSTRUCTOR(BLOCK) do { SimulatedBlock::initCommon(); } while(0)
1313
1314 #define BLOCK_FUNCTIONS(BLOCK) \
1315 void \
1316 BLOCK::addRecSignal(GlobalSignalNumber gsn, ExecSignalLocal f, bool force){ \
1317 addRecSignalImpl(gsn, (ExecFunction)f, force);\
1318 }
1319
1320 #include "Mutex.hpp"
1321
1322 inline
~SectionHandle()1323 SectionHandle::~SectionHandle()
1324 {
1325 if (unlikely(m_cnt))
1326 {
1327 m_block->handle_lingering_sections_after_execute(this);
1328 }
1329 }
1330
1331 #ifdef ERROR_INSERT
1332 #define RSS_AP_SNAPSHOT(x) Uint32 rss_##x
1333 #define RSS_AP_SNAPSHOT_SAVE(x) rss_##x = x.getNoOfFree()
1334 #define RSS_AP_SNAPSHOT_CHECK(x) ndbrequire(rss_##x == x.getNoOfFree())
1335 #define RSS_AP_SNAPSHOT_SAVE2(x,y) rss_##x = x.getNoOfFree()+(y)
1336 #define RSS_AP_SNAPSHOT_CHECK2(x,y) ndbrequire(rss_##x == x.getNoOfFree()+(y))
1337
1338 #define RSS_OP_COUNTER(x) Uint32 x
1339 #define RSS_OP_COUNTER_INIT(x) x = 0
1340 #define RSS_OP_ALLOC(x) x ++
1341 #define RSS_OP_FREE(x) x --
1342 #define RSS_OP_ALLOC_X(x,n) x += n
1343 #define RSS_OP_FREE_X(x,n) x -= n
1344
1345 #define RSS_OP_SNAPSHOT(x) Uint32 rss_##x
1346 #define RSS_OP_SNAPSHOT_SAVE(x) rss_##x = x
1347 #define RSS_OP_SNAPSHOT_CHECK(x) ndbrequire(rss_##x == x)
1348 #else
1349 #define RSS_AP_SNAPSHOT(x) struct rss_dummy0_##x { int dummy; }
1350 #define RSS_AP_SNAPSHOT_SAVE(x)
1351 #define RSS_AP_SNAPSHOT_CHECK(x)
1352 #define RSS_AP_SNAPSHOT_SAVE2(x,y)
1353 #define RSS_AP_SNAPSHOT_CHECK2(x,y)
1354
1355 #define RSS_OP_COUNTER(x) struct rss_dummy1_##x { int dummy; }
1356 #define RSS_OP_COUNTER_INIT(x)
1357 #define RSS_OP_ALLOC(x)
1358 #define RSS_OP_FREE(x)
1359 #define RSS_OP_ALLOC_X(x,n)
1360 #define RSS_OP_FREE_X(x,n)
1361
1362 #define RSS_OP_SNAPSHOT(x) struct rss_dummy2_##x { int dummy; }
1363 #define RSS_OP_SNAPSHOT_SAVE(x)
1364 #define RSS_OP_SNAPSHOT_CHECK(x)
1365
1366 #endif
1367
1368 struct Hash2FragmentMap
1369 {
1370 STATIC_CONST( MAX_MAP = 240 );
1371 Uint32 m_cnt;
1372 Uint32 m_fragments;
1373 Uint8 m_map[MAX_MAP];
1374 Uint32 nextPool;
1375 Uint32 m_object_id;
1376 };
1377
1378 extern ArrayPool<Hash2FragmentMap> g_hash_map;
1379
1380 #endif
1381
1382