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