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