1 /*
2    Copyright (c) 2003, 2021, Oracle and/or its affiliates.
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 "IntrusiveList.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 #define JAM_FILE_ID 248
70 
71 
72 #ifdef VM_TRACE
73 #define D(x) \
74   do { \
75     char buf[200]; \
76     if (!debugOutOn()) break; \
77     debugOutLock(); \
78     debugOutStream() << debugOutTag(buf, __LINE__) << x << dec << "\n"; \
79     debugOutUnlock(); \
80   } while (0)
81 #define V(x) " " << #x << ":" << (x)
82 #else
83 #define D(x) do { } while(0)
84 #undef V
85 #endif
86 
87 /**
88  * LCP scans and Backup scans always use batch size 16, there are even
89  * optimisations in allocation and handling LCP scans and Backup scans
90  * keeping proper rates using this particular batch size. This is also
91  * true for Node recovery scans as started by COPY_FRAGREQ.
92  */
93 #define ZRESERVED_SCAN_BATCH_SIZE 16
94 /**
95  * Something for filesystem access
96  */
97 struct  NewBaseAddrBits              /* 32 bits */
98 {
99   unsigned int     q               : 4;    /* Highest index - 2log */
100   /* Strings are treated as 16 bit indexed        */
101   /* variables with the number of characters in   */
102   /* index 0, byte 0                              */
103   unsigned int     v               : 3;    /* Size in bits - 2log */
104   unsigned int     unused : 25 ;
105 };
106 
107 typedef struct NewVar
108 {
109   Uint32 *              WA;
110   Uint32                nrr;
111   Uint32                ClusterSize;    /* Real Cluster size    */
112   NewBaseAddrBits       bits;
113 } NewVARIABLE;  /* 128 bits */
114 
115 struct Block_context
116 {
Block_contextBlock_context117   Block_context(class Configuration& cfg, class Ndbd_mem_manager& mm)
118     : m_config(cfg), m_mm(mm) {}
119   class Configuration& m_config;
120   class Ndbd_mem_manager& m_mm;
121 };
122 
123 struct PackedWordsContainer
124 {
125   BlockReference hostBlockRef;
126   Uint32 noOfPackedWords;
127   Uint32 packedWords[30];
128 }; // 128 bytes
129 
130 /**
131   Description of NDB Software Architecture
132   ----------------------------------------
133 
134   The NDB software architecture has two foundations, blocks and signals.
135   The base object for the blocks is the below SimulatedBlock class and
136   the signal object is the base class Signal defined in VMSignal.hpp.
137 
138   Blocks are intended as software units that owns its own data and it
139   communicates with other blocks only through signals. Each block owns
140   its own set of data which it entirely controls. There has been some
141   optimisations where blocks always executing in the same thread can do
142   some shortcuts by calling functions in a different block directly.
143   There is even some code to call functions in a block in a different
144   thread, in this case however some mutex is required to protect the
145   data.
146 
147   Blocks are gathered together in threads. Threads are gathered into nodes.
148   So when sending a signal you need to send it to an address. The address is
149   a 32-bit word. It is a bit similar to IPv4 addresses. The address is
150   setup in the following manner:
151 
152   -- Bit 0-8 ------- Bit 9-15 ------ Bit 16-31 ------
153   | Block number  | Thread id   |       NodeId      |
154   ---------------------------------------------------
155 
156   So when delivering a signal we start by checking the node id. If the node
157   id is our own node id, then we will continue checking thread id. If it
158   is destined to another node, then we move the signal sending to the module
159   that takes care of transporting the signal to another node in the cluster.
160 
161   Each other node is found using a socket over TCP/IP. The architecture
162   supports also other ways to transport signals such as using some form
163   of shared memory between processes on the same or different machines.
164   It would also be possible to extend the architecture such that we
165   might use different sockets for different threads in the node.
166 
167   If the signal is destined for a different thread then we transport the
168   signal to that thread, we use a separate memory buffer for each two
169   threads that communicate such that the communication between threads is
170   completely lock-free.
171 
172   One block number can be used in several threads. So e.g. the LDM threads
173   all contain its own instance of the DBLQH block. The method instance()
174   gets the instance number of the currently executing block. The method
175   reference() gets the block reference of the currently executing block.
176 
177   If we send to ourselves we put the signal in the memory buffer for
178   communication with our own thread.
179 
180   The current limits of the architecture is a maximum of 512 block numbers.
181   We currently use less than 25 of those numbers. The maximum number of
182   threads are 128 threads. We currently can use at most 72 threads.
183   The current node limit is 255 nodes and node id 0 is a special case.
184 
185   So there is still a lot of space in the addressing mechanism for growth
186   in terms of number of threads, blocks and nodes and even for introduction
187   of new addressable units like subthreads or similar things.
188 
189   The software architecture also contains a structure for how signals are
190   structured. Each signal is sent at a certain priority level. Finally also
191   there is a concept of sending delayed signals to blocks within the same
192   thread.
193 
194   Priority level on signals
195   -------------------------
196   So starting with priority level a signal can be sent on high priority
197   (JBA) and normal priority (JBB). The priority level can be used also when
198   sending to other nodes. The priority will however not be used to prioritise
199   the signal in sending it over the socket to the receiving node.
200 
201   Each thread has its own buffer for A-priority signals. In the scheduler
202   we will always execute all signals in the A-priority buffer first. If
203   new A-priority signals are sent during these signals, then they will also
204   be executed until no more signals exist on A-priority level. So it's not
205   allowed to have a flow of signals all executing at A-level. We always have
206   to insert a signal in the flow that either goes down to B-level or use some
207   form of delayed signal.
208 
209   If an A-level signal is sent from a B-level signal it will be handled
210   differently in the single threaded ndbd and the multi-threaded ndbmtd. In
211   ndbmtd it will be executed after executing up to 128 B-level signals. In
212   ndbd it will be executed as the next signal. So one cannot assume that an
213   A-level signal will be executed before a specific B-level signal. A B-level
214   signal can even be executed before an A-level signal although it was sent
215   after the A-level signal.
216 
217   Delayed signals
218   ---------------
219   Delayed signals are used to create threads of activities that execute without
220   consuming too much CPU activity. Delayed signals can only be sent internally
221   within the same thread. When the signal has been delayed and is taken out of
222   its timer queue its inserted into the priority A buffer.
223 
224   Bounded delay signals
225   ---------------------
226   A special form of delayed signal also exists, this is sent with delay equal to
227   the constant BOUNDED_DELAY. This means that the signal will be executed as a
228   priority A task as soon as the current set of B-level tasks are done. This is
229   similar to sending an A-level signal from a B-level job in ndbmtd. However for
230   ndbd it's not the same thing and also when sending an A-level signal from an
231   A-level signal it is also not the same thing.
232 
233   So a delayed signal with delay BOUNDED_DELAY is a special type of signal
234   with a bounded delay. The bound is that no more than 100 B-level signals will
235   be executed before this signal is executed. Given our design requirements
236   a B-level signal should mostly be executed within at most 5-10 microseconds
237   or so, mostly much shorter than this even, so a normal execution time of
238   a signal would be below 1 microsecond. So 100 signals should almost never
239   execute for more than 1000 microseconds and rarely go beyond even 100
240   microseconds.
241 
242   So these bounded delay signals are a good tool to ensure that activitites
243   such as backups, checkpoints, node recovery activities, altering of tables
244   and similar things gets executed at a certain rate. Without any possibility
245   of bounded delay signals it is very hard to implement an activity that gets
246   executed at a certain rate.
247 
248   So in a sense we're using the bounded delay signals to implement a form of
249   time-sharing priority, certain activities are allowed to use a proportion
250   of the available CPU resources, not too much, but also not too little. If
251   an LCP gets bogged down by user transactions then the system will eventually
252   run out of REDO log space. If a node recovery activity gets bogged down by
253   user transactions then we will run for too long with only one replica in the
254   node group which is bad for system availability.
255 
256   Execute direct signals
257   ----------------------
258   If the receiving block is within the same thread, then it is possible to
259   send the signal using the method EXECUTE_DIRECT. This execution will
260   happen immediately and won't be scheduled for later, it will be done in
261   the same fashion as a function call.
262 
263   Signals
264   -------
265   Signals are carried with a certain structure:
266   1) Each signal has a signal number. This number also is mapped to a name.
267      When executing a signal with a certain number which e.g. has the name
268      TCKEYREQ, then this signal is implemented by a method called
269      execTCKEYREQ in the receiving block. More than one block could have
270      such a method since a signal is not tied to a certain block.
271 
272   2) Each signal has 4 areas that can be sent in the signal. The first is
273      always sent in the signal, this is the fixed part. The fixed part
274      consists of at least 1 and at most 25 32-bit words. Many signals have
275      a class that defines this part of the signal. This is however not
276      absolutely necessary. Then there are up to 3 sections that can carry
277      longer information bits. So e.g. a TCKEYREQ has one section that contains
278      the primary key and another part that contains the attribute information.
279      The attribute information could be seen as a program sent to MySQL
280      Cluster data nodes to read, update the row specified in the key
281      section. The attribute information could also contain interpreted
282      programs that can do things like increment, decrement, conditional
283      update and so forth.
284 
285    3) As mentioned above each signal carries a certain priority level to
286       execute it on. It is currently not possible to check the prio
287       level you're currently executing on, but it would be real simple
288       to add this capability if necessary.
289 
290    4) When executing a certain signal it gets a signal id, this id is
291       local to the thread and is incremented by one each new signal that
292       is executed. This signal id is available in the Signal class and
293       can e.g. be used to deduce if the thread is currently at high load.
294 
295    A signal is sent over the socket using a special protocol that is called
296    Protocol6. This is not discussed more here, it is a feature of the
297    transport mechanisms of the NDB Software Architecture.
298 
299    CONTINUEB
300    ---------
301    CONTINUEB is a special signal used by almost all blocks. This signal is
302    used to handle background thread activities. Often the CONTINUEB signals
303    are used as part of implementing a more complex action. One example is
304    when DBDIH starts up a new LCP. It sends various forms of CONTINUEB
305    signals to itself to move ahead through the LCP actions it needs to do
306    as part of starting up a new LCP. The first word contains the type of
307    CONTINUEB signal, so this is in a sense a bit like a second level of
308    signal number. Based on this number the CONTINUEB data is treated
309    differently.
310 
311    Common patterns of signals
312    --------------------------
313    There is no absolute patterns for how signal data looks like. But it is
314    very common that a signal at least contains the destination object id,
315    the senders object id and the senders block reference. The senders block
316    reference is actually also available in the Signal class when executing
317    a signal. But we can use various forms of software routing of the
318    signal, so the senders block reference is the originator of the signal,
319    not necessarily the same as the sender of the signal since it could be
320    routed through several blocks on the way.
321 
322    The basic data type in the NDB signals are unsigned 32-bit integers. So
323    all addressing is using a special form of pointers. The pointers always
324    refers to a special class of objects and the pointer is the index in an
325    array of objects of this kind. So we can have up to 4 billion objects of
326    most kinds. If one needs to send strings and 64-bit integers one follows
327    various techniques to do this. Signals are sent in the endian order of
328    the machine they were generated, so machines in a cluster has to be
329    of the same type of endian.
330 
331    ROUTE_SIGNAL
332    ------------
333    ROUTE_SIGNAL is a special signal that can be used to carry a signal
334    in a special path to ensure that it arrives in the correct order to
335    the receiving block.
336 
337    Signal order guarantees
338    -----------------------
339    The following signal order guarantees are maintained.
340 
341    1) Sending signals at the same priority level to the same block reference
342       from one block will arrive in the order they were sent.
343 
344       It is not guaranteed if the priority level is different for the signals,
345       it is also not guaranteed if they are sent through different paths.
346       Not even sending in the following pattern has a guarantee on the
347       delivery order. Signal 1: Block A -> Block B, Signal 2: Block A ->
348       Block C -> Block B. Although the signal 2 uses a longer path and is
349       destined to the same block it can still arrive before signal 1 at
350       Block B. The reason is that we execute signals from one sender at a
351       time, so we might be executing in Block C very quickly whereas the
352       thread executing Block B might be stalled and then when Block C has
353       sent its signal the thread executing Block B wakes up and decides
354       to execute signals from Block C before signals from Block A.
355 
356    So as can be seen there is very little support for signal orders in the
357    NDB software architecture and so most protocols have to take into
358    account that signals can arrive in many different orders.
359 
360    Fragmented signals
361    ------------------
362    It is possible to send really long signals. These signals cannot be
363    sent as one signal though. They are sent as one signal, then they will
364    be split up into multiple signals. The fixed part is the same in all
365    signals. What mainly differs is that they each contain a part of each
366    segment.
367 
368    When receiving such a signal one should always call assembleFragments()
369    at first to see if the entire signal has arrived first. The signal
370    executor method is executed once for each signal fragment that is sent.
371    When all fragments have arrived then they will contain the full signal
372    with up to 3 sections that can much longer than the normal sized signals
373    that have limitations on the size of the signals.
374 
375    Tracing infrastructure
376    ----------------------
377    All signals are sent through memory buffers. At crashes these memory
378    buffers can be used to print the last executed signals in each thread.
379    This will aid in looking for reasons for the crash. There will be one
380    file generated for each thread in the ndbmtd, in the case of ndbd there
381    will be only one file since there is only one file.
382 
383    Jams
384    ----
385    jam() and its cousins is a set of macros used for tracing what happened
386    at the point of a crash. Each jam call executes a set of instructions
387    that inserts the line number of the jam macro into an array kept per
388    thread. There is some overhead in the jams, but it helps quite a lot in
389    debugging crashes of the NDB data nodes. At crash time we can see a few
390    thousand of the last decisions made just before the crash. This together
391    with the signal logs makes for a powerful tool to root out bugs in NDB
392    data nodes.
393 
394    Trace Id
395    --------
396    Each signal also carries a signal id, this id can be used to trace certain
397    activities that go on for a longer time. This tracing can happen even in a
398    live system.
399 */
400 
401 class SimulatedBlock :
402   public SegmentUtils  /* SimulatedBlock implements the Interface */
403 {
404   friend class TraceLCP;
405   friend class SafeCounter;
406   friend class SafeCounterManager;
407   friend class AsyncFile;
408   friend class PosixAsyncFile; // FIXME
409   friend class Win32AsyncFile;
410   friend class Pgman;
411   friend class Page_cache_client;
412   friend class Lgman;
413   friend class Logfile_client;
414   friend class Tablespace_client;
415   friend class Dbtup_client;
416   friend struct Pool_context;
417   friend struct SectionHandle;
418   friend class LockQueue;
419   friend class SimplePropertiesSectionWriter;
420   friend class SegmentedSectionGuard;
421 public:
422   friend class BlockComponent;
423   virtual ~SimulatedBlock();
424 
425   static const Uint32 BOUNDED_DELAY = 0xFFFFFF00;
426 protected:
427   /**
428    * Constructor
429    */
430   SimulatedBlock(BlockNumber blockNumber,
431 		 struct Block_context & ctx,
432                  Uint32 instanceNumber = 0);
433 
434   /**********************************************************
435    * Handling of execFunctions
436    */
437   typedef void (SimulatedBlock::* ExecFunction)(Signal* signal);
438   void addRecSignalImpl(GlobalSignalNumber g, ExecFunction fun, bool f =false);
439   void installSimulatedBlockFunctions();
440   ExecFunction theExecArray[MAX_GSN+1];
441   void handle_execute_error(GlobalSignalNumber gsn);
442 
443   void initCommon();
444 
445   inline void executeFunction(GlobalSignalNumber gsn,
446                               Signal* signal,
447                               ExecFunction f);
448 
449   inline void executeFunction(GlobalSignalNumber gsn,
450                               Signal* signal,
451                               ExecFunction f,
452                               BlockReference ref,
453                               Uint32 len);
454 
455 public:
456   typedef void (SimulatedBlock::* CallbackFunction)(class Signal*,
457 						    Uint32 callbackData,
458 						    Uint32 returnCode);
459   struct Callback {
460     CallbackFunction m_callbackFunction;
461     Uint32 m_callbackData;
462   };
463 
464   inline void executeFunction(GlobalSignalNumber gsn, Signal* signal);
465   inline void executeFunction_async(GlobalSignalNumber gsn, Signal* signal);
466 
467   /* Multiple block instances */
instance() const468   Uint32 instance() const {
469     return theInstance;
470   }
471 
getExecuteFunction(GlobalSignalNumber gsn)472   ExecFunction getExecuteFunction(GlobalSignalNumber gsn)
473   {
474     return theExecArray[gsn];
475   }
476 
getInstance(Uint32 instanceNumber)477   SimulatedBlock* getInstance(Uint32 instanceNumber) {
478     ndbrequire(theInstance == 0); // valid only on main instance
479     if (instanceNumber == 0)
480       return this;
481     ndbrequire(instanceNumber < MaxInstances);
482     if (theInstanceList != 0)
483       return theInstanceList[instanceNumber];
484     return 0;
485   }
486   void addInstance(SimulatedBlock* b, Uint32 theInstanceNo);
loadWorkers()487   virtual void loadWorkers() {}
488 
489   struct ThreadContext
490   {
491     Uint32 threadId;
492     EmulatedJamBuffer* jamBuffer;
493     Uint32 * watchDogCounter;
494     SectionSegmentPool::Cache * sectionPoolCache;
495   };
496   /* Setup state of a block object for executing in a particular thread. */
497   void assignToThread(ThreadContext ctx);
498   /* For multithreaded ndbd, get the id of owning thread. */
getThreadId() const499   uint32 getThreadId() const { return m_threadId; }
500   /**
501    * To call EXECUTE_DIRECT on THRMAN we need to get its instance number.
502    * Its instance number is always 1 higher than the thread id since 0
503    * is used for the proxy instance and then there is one instance per
504    * thread.
505    */
getThrmanInstance() const506   Uint32 getThrmanInstance() const
507   {
508     if (isNdbMt())
509     {
510       return m_threadId + 1;
511     }
512     else
513     {
514       return 0;
515     }
516   }
517   static bool isMultiThreaded();
518 
519   /* Configuration based alternative.  Applies only to this node */
isNdbMt()520   static bool isNdbMt() { return globalData.isNdbMt; }
isNdbMtLqh()521   static bool isNdbMtLqh() { return globalData.isNdbMtLqh; }
getLqhWorkers()522   static Uint32 getLqhWorkers() { return globalData.ndbMtLqhWorkers; }
523 
524   /**
525    * Assert that thread calling this function is "owner" of block instance
526    */
527 #ifdef VM_TRACE
528   void assertOwnThread();
529 #else
assertOwnThread()530   void assertOwnThread(){ }
531 #endif
532 
533   /*
534    * Instance key (1-4) is used only when sending a signal.  Receiver
535    * maps it to actual instance (0, if receiver is not MT LQH).
536    *
537    * For performance reason, DBTC gets instance key directly from DBDIH
538    * via DI*GET*NODES*REQ signals.
539    */
540   static Uint32 getInstanceKey(Uint32 tabId, Uint32 fragId);
541   static Uint32 getInstanceFromKey(Uint32 instanceKey); // local use only
542 
543   /**
544    * This method will make sure that when callback in called each
545    *   thread running an instance any of the threads in blocks[]
546    *   will have executed a signal
547    */
548   void synchronize_threads_for_blocks(Signal*, const Uint32 blocks[],
549                                       const Callback&, JobBufferLevel = JBB);
550 
551   /**
552    * This method make sure that the path specified in blocks[]
553    *   will be traversed before returning
554    */
555   void synchronize_path(Signal*, const Uint32 blocks[],
556                         const Callback&, JobBufferLevel = JBB);
557 
558   /**
559    * These methods are used to assist blocks to use the TIME_SIGNAL to
560    * generate drum beats with a regular delay. elapsed_time will report
561    * back the elapsed time since last call but will never report more
562    * than max delay. max_delay = 2 * delay here.
563    */
564   void init_elapsed_time(Signal *signal,
565                          NDB_TICKS &latestTIME_SIGNAL);
566   void sendTIME_SIGNAL(Signal *signal,
567                        const NDB_TICKS currentTime,
568                        Uint32 delay);
569   Uint64 elapsed_time(Signal *signal,
570                       const NDB_TICKS currentTime,
571                       NDB_TICKS &latestTIME_SIGNAL,
572                       Uint32 max_delay);
573 
574 private:
575   struct SyncThreadRecord
576   {
577     Callback m_callback;
578     Uint32 m_cnt;
579     Uint32 nextPool;
580   };
581   ArrayPool<SyncThreadRecord> c_syncThreadPool;
582   void execSYNC_THREAD_REQ(Signal*);
583   void execSYNC_THREAD_CONF(Signal*);
584 
585   void execSYNC_REQ(Signal*);
586 
587   void execSYNC_PATH_REQ(Signal*);
588   void execSYNC_PATH_CONF(Signal*);
589 public:
get_filename(Uint32 fd) const590   virtual const char* get_filename(Uint32 fd) const { return "";}
591 
592   void EXECUTE_DIRECT(ExecFunction f,
593                       Signal *signal);
594 protected:
595   static Callback TheEmptyCallback;
596   void TheNULLCallbackFunction(class Signal*, Uint32, Uint32);
597   static Callback TheNULLCallback;
598   void execute(Signal* signal, Callback & c, Uint32 returnCode);
599 
600 
601   void getSendBufferLevel(NodeId node, SB_LevelType &level);
602   Uint32 getSignalsInJBB();
603 
604   /**********************************************************
605    * Send signal - dialects
606    */
607 
608   void sendSignal(BlockReference ref,
609 		  GlobalSignalNumber gsn,
610                   Signal* signal,
611 		  Uint32 length,
612 		  JobBufferLevel jbuf ) const ;
613 
614   void sendSignal(NodeReceiverGroup rg,
615 		  GlobalSignalNumber gsn,
616                   Signal* signal,
617 		  Uint32 length,
618 		  JobBufferLevel jbuf ) const ;
619 
620   void sendSignal(BlockReference ref,
621 		  GlobalSignalNumber gsn,
622                   Signal* signal,
623 		  Uint32 length,
624 		  JobBufferLevel jbuf,
625 		  SectionHandle* sections) const;
626 
627   void sendSignal(NodeReceiverGroup rg,
628 		  GlobalSignalNumber gsn,
629                   Signal* signal,
630 		  Uint32 length,
631 		  JobBufferLevel jbuf,
632 		  SectionHandle* sections) const;
633 
634   void sendSignal(BlockReference ref,
635 		  GlobalSignalNumber gsn,
636                   Signal* signal,
637 		  Uint32 length,
638 		  JobBufferLevel jbuf,
639 		  LinearSectionPtr ptr[3],
640 		  Uint32 noOfSections) const ;
641 
642   void sendSignal(NodeReceiverGroup rg,
643 		  GlobalSignalNumber gsn,
644                   Signal* signal,
645 		  Uint32 length,
646 		  JobBufferLevel jbuf,
647 		  LinearSectionPtr ptr[3],
648 		  Uint32 noOfSections) const ;
649 
650   /* NoRelease sendSignal variants do not release sections as
651    * a side-effect of sending.  This requires extra
652    * copying for local sends
653    */
654   void sendSignalNoRelease(BlockReference ref,
655                            GlobalSignalNumber gsn,
656                            Signal* signal,
657                            Uint32 length,
658                            JobBufferLevel jbuf,
659                            SectionHandle* sections) const;
660 
661   void sendSignalNoRelease(NodeReceiverGroup rg,
662                            GlobalSignalNumber gsn,
663                            Signal* signal,
664                            Uint32 length,
665                            JobBufferLevel jbuf,
666                            SectionHandle* sections) const;
667 
668   // Send multiple signal with delay. In this VM the jobbufffer level has
669   // no effect on on delayed signals
670   //
671 
672   void sendSignalWithDelay(BlockReference ref,
673 			   GlobalSignalNumber gsn,
674                            Signal* signal,
675                            Uint32 delayInMilliSeconds,
676 			   Uint32 length) const ;
677 
678   void sendSignalWithDelay(BlockReference ref,
679 			   GlobalSignalNumber gsn,
680                            Signal* signal,
681                            Uint32 delayInMilliSeconds,
682 			   Uint32 length,
683 			   SectionHandle* sections) const;
684 
685   /*
686    * Instance defaults to instance of sender.  Using explicit
687    * instance argument asserts that the call is thread-safe.
688    */
689   void EXECUTE_DIRECT(Uint32 block,
690 		      Uint32 gsn,
691 		      Signal* signal,
692 		      Uint32 len,
693                       Uint32 givenInstanceNo);
694   void EXECUTE_DIRECT(Uint32 block,
695 		      Uint32 gsn,
696 		      Signal* signal,
697 		      Uint32 len);
698 
699   class SectionSegmentPool& getSectionSegmentPool();
700   void release(SegmentedSectionPtr & ptr);
release(SegmentedSectionPtrPOD & ptr)701   void release(SegmentedSectionPtrPOD & ptr) {
702     SegmentedSectionPtr tmp(ptr);
703     release(tmp);
704     ptr.setNull();
705   }
706   void releaseSection(Uint32 firstSegmentIVal);
707   void releaseSections(struct SectionHandle&);
708 
709   bool import(Ptr<SectionSegment> & first, const Uint32 * src, Uint32 len);
710   bool import(SegmentedSectionPtr& ptr, const Uint32* src, Uint32 len);
711   bool import(SectionHandle * dst, LinearSectionPtr src[3],Uint32 cnt);
712 
713   bool appendToSection(Uint32& firstSegmentIVal, const Uint32* src, Uint32 len);
714   bool dupSection(Uint32& copyFirstIVal, Uint32 srcFirstIVal);
715   bool writeToSection(Uint32 firstSegmentIVal, Uint32 offset, const Uint32* src, Uint32 len);
716 
717   void handle_invalid_sections_in_send_signal(const Signal*) const;
718   void handle_lingering_sections_after_execute(const Signal*) const;
719   void handle_invalid_fragmentInfo(Signal*) const;
720   void handle_send_failed(SendStatus, Signal*) const;
721   void handle_out_of_longsignal_memory(Signal*) const;
722 
723   /**
724    * Send routed signals (ONLY LOCALLY)
725    *
726    * NOTE: Only localhost is allowed!
727    */
728   struct RoutePath
729   {
730     Uint32 ref;
731     JobBufferLevel prio;
732   };
733   void sendRoutedSignal(RoutePath path[],
734                         Uint32 pathcnt,      // #hops
735                         Uint32 dst[],        // Final destination(s)
736                         Uint32 dstcnt,       // #final destination(s)
737                         Uint32 gsn,          // Final GSN
738                         Signal*,
739                         Uint32 len,
740                         JobBufferLevel prio, // Final prio
741                         SectionHandle * handle = 0);
742 
743 
744   /**
745    * Check that signal sent from remote node
746    *   is guaranteed to be correctly serialized wrt to NODE_FAILREP
747    */
748   bool checkNodeFailSequence(Signal*);
749 
750   /**********************************************************
751    * Fragmented signals
752    */
753 
754   /**
755    * Assemble fragments
756    *
757    * @return true if all fragments has arrived
758    *         false otherwise
759    */
760   bool assembleFragments(Signal * signal);
761 
762   /**
763    * Assemble dropped fragments
764    *
765    * Should be called at the start of a Dropped Signal Report
766    * (GSN_DROPPED_SIGNAL_REP) handler when it is expected that
767    * the block could receive fragmented signals.
768    * No dropped signal handling should be done until this method
769    * returns true.
770    *
771    * @return true if all fragments has arrived and dropped signal
772    *              handling can proceed.
773    *         false otherwise
774    */
775   bool assembleDroppedFragments(Signal * signal);
776 
777   /* If send size is > FRAGMENT_WORD_SIZE, fragments of this size
778    * will be sent by the sendFragmentedSignal variants
779    */
780   STATIC_CONST( FRAGMENT_WORD_SIZE = 240 );
781 
782   void sendFragmentedSignal(BlockReference ref,
783 			    GlobalSignalNumber gsn,
784 			    Signal* signal,
785 			    Uint32 length,
786 			    JobBufferLevel jbuf,
787 			    SectionHandle * sections,
788 			    Callback & = TheEmptyCallback,
789 			    Uint32 messageSize = FRAGMENT_WORD_SIZE);
790 
791   void sendFragmentedSignal(NodeReceiverGroup rg,
792 			    GlobalSignalNumber gsn,
793 			    Signal* signal,
794 			    Uint32 length,
795 			    JobBufferLevel jbuf,
796 			    SectionHandle * sections,
797 			    Callback & = TheEmptyCallback,
798 			    Uint32 messageSize = FRAGMENT_WORD_SIZE);
799 
800   void sendFragmentedSignal(BlockReference ref,
801 			    GlobalSignalNumber gsn,
802 			    Signal* signal,
803 			    Uint32 length,
804 			    JobBufferLevel jbuf,
805 			    LinearSectionPtr ptr[3],
806 			    Uint32 noOfSections,
807 			    Callback & = TheEmptyCallback,
808 			    Uint32 messageSize = FRAGMENT_WORD_SIZE);
809 
810   void sendFragmentedSignal(NodeReceiverGroup rg,
811 			    GlobalSignalNumber gsn,
812 			    Signal* signal,
813 			    Uint32 length,
814 			    JobBufferLevel jbuf,
815 			    LinearSectionPtr ptr[3],
816 			    Uint32 noOfSections,
817 			    Callback & = TheEmptyCallback,
818 			    Uint32 messageSize = FRAGMENT_WORD_SIZE);
819 
820   /**
821    * simBlockNodeFailure
822    *
823    * Method must be called by blocks that send or receive
824    * remote Fragmented Signals when they detect a node
825    * (NDBD or API) failure.
826    * If the block needs to acknowledge or perform further
827    * processing after completing block-level node failure
828    * handling, it can supply a Callback which will be invoked
829    * when block-level node failure handling has completed.
830    * Otherwise TheEmptyCallback is used.
831    * If TheEmptyCallback is used, all failure handling is
832    * performed in the current timeslice, to avoid any
833    * races.
834    *
835    * Parameters
836    *   signal       : Current signal*
837    *   failedNodeId : Node id of failed node
838    *   cb           : Callback to be executed when block-level
839    *                  node failure handling completed.
840    *                  TheEmptyCallback is passed if no further
841    *                  processing is required.
842    * Returns
843    *   Number of 'resources' cleaned up in call.
844    *   Callback return code is total resources cleaned up.
845    *
846    */
847   Uint32 simBlockNodeFailure(Signal* signal,
848                              Uint32 failedNodeId,
849                              Callback& cb = TheEmptyCallback);
850 
851   /**********************************************************
852    * Fragmented signals structures
853    */
854 
855   /**
856    * Struct used when assembling fragmented long signals at receiver side
857    */
858   struct FragmentInfo {
859     FragmentInfo(Uint32 fragId, Uint32 sender);
860 
861     Uint32 m_senderRef;
862     Uint32 m_fragmentId;
863     Uint32 m_sectionPtrI[3];
864     union {
865       Uint32 nextPool;
866       Uint32 nextHash;
867     };
868     Uint32 prevHash;
869 
equalSimulatedBlock::FragmentInfo870     inline bool equal(FragmentInfo const & p) const {
871       return m_senderRef == p.m_senderRef && m_fragmentId == p.m_fragmentId;
872     }
873 
hashValueSimulatedBlock::FragmentInfo874     inline Uint32 hashValue() const {
875       return m_senderRef + m_fragmentId ;
876     }
877 
isDroppedSimulatedBlock::FragmentInfo878     inline bool isDropped() const {
879       /* IsDropped when entry in hash, but no segments stored */
880       return (( m_sectionPtrI[0] == RNIL ) &&
881               ( m_sectionPtrI[1] == RNIL ) &&
882               ( m_sectionPtrI[2] == RNIL ) );
883     }
884   }; // sizeof() = 32 bytes
885 
886   /**
887    * Struct used when sending fragmented signals
888    */
889   struct FragmentSendInfo {
890     FragmentSendInfo();
891 
892     enum Status {
893       SendNotComplete = 0,
894       SendComplete    = 1,
895       SendCancelled   = 2
896     };
897     Uint8  m_status;
898     Uint8  m_prio;
899     Uint8  m_fragInfo;
900     enum Flags {
901       SendNoReleaseSeg = 0x1
902     };
903     Uint8  m_flags;
904     Uint16 m_gsn;
905     Uint16 m_messageSize; // Size of each fragment
906     Uint32 m_fragmentId;
907     union {
908       // Similar to Ptr<SectionSegment> but a POD, as needed in a union.
909       struct {
910         SectionSegment* p;
911         Uint32 i;
912       } m_segmented;
913       LinearSectionPtr m_linear;
914     } m_sectionPtr[3];
915     LinearSectionPtr m_theDataSection;
916     NodeReceiverGroup m_nodeReceiverGroup; // 3
917     Callback m_callback;
918     union  {
919       Uint32 nextPool;
920       Uint32 nextList;
921     };
922     Uint32 prevList;
923   };
924 
925   /**
926    * sendFirstFragment
927    *   Used by sendFragmentedSignal
928    *   noRelease can only be used if the caller can guarantee
929    *   not to free the supplied sections until all fragments
930    *   have been sent.
931    */
932   bool sendFirstFragment(FragmentSendInfo & info,
933 			 NodeReceiverGroup rg,
934 			 GlobalSignalNumber gsn,
935 			 Signal* signal,
936 			 Uint32 length,
937 			 JobBufferLevel jbuf,
938 			 SectionHandle * sections,
939                          bool noRelease,
940 			 Uint32 messageSize = FRAGMENT_WORD_SIZE);
941 
942   bool sendFirstFragment(FragmentSendInfo & info,
943 			 NodeReceiverGroup rg,
944 			 GlobalSignalNumber gsn,
945 			 Signal* signal,
946 			 Uint32 length,
947 			 JobBufferLevel jbuf,
948 			 LinearSectionPtr ptr[3],
949 			 Uint32 noOfSections,
950 			 Uint32 messageSize = FRAGMENT_WORD_SIZE);
951 
952   /**
953    * Send signal fragment
954    *
955    * @see sendFragmentedSignal
956    */
957   void sendNextSegmentedFragment(Signal* signal, FragmentSendInfo & info);
958 
959   /**
960    * Send signal fragment
961    *
962    * @see sendFragmentedSignal
963    */
964   void sendNextLinearFragment(Signal* signal, FragmentSendInfo & info);
965 
966   BlockNumber    number() const;
967 public:
968   /* Must be public so that we can jam() outside of block scope. */
969   EmulatedJamBuffer *jamBuffer() const;
970 protected:
971   BlockReference reference() const;
972   NodeId         getOwnNodeId() const;
973 
974   /**
975    * Refresh Watch Dog in initialising code
976    *
977    */
978   void refresh_watch_dog(Uint32 place = 1);
979   void update_watch_dog_timer(Uint32 interval);
980 
981   /**
982    * Prog error
983    * This function should be called when this node should be shutdown
984    * If the cause of the shutdown is known use extradata to add an
985    * errormessage describing the problem
986    */
987   void progError(int line, int err_code, const char* extradata=NULL) const
988     ATTRIBUTE_NORETURN;
989 private:
990   void  signal_error(Uint32, Uint32, Uint32, const char*, int) const
991     ATTRIBUTE_NORETURN;
992   const NodeId         theNodeId;
993   const BlockNumber    theNumber;
994   const Uint32 theInstance;
995   const BlockReference theReference;
996   /*
997    * Instance 0 is the main instance.  It creates/owns other instances.
998    * In MT LQH main instance is the LQH proxy and the others ("workers")
999    * are real LQHs run by multiple threads.
1000    */
1001 protected:
1002   enum { MaxInstances = NDBMT_MAX_BLOCK_INSTANCES };
1003 private:
1004   SimulatedBlock** theInstanceList; // set in main, indexed by instance
1005   SimulatedBlock* theMainInstance;  // set in all
1006   /*
1007     Thread id currently executing this block.
1008     Not used in singlethreaded ndbd.
1009   */
1010   Uint32 m_threadId;
1011   /*
1012     Jam buffer reference.
1013     In multithreaded ndbd, this is different in each thread, and must be
1014     updated if migrating the block to another thread.
1015   */
1016   EmulatedJamBuffer *m_jamBuffer;
1017   /* For multithreaded ndb, the thread-specific watchdog counter. */
1018   Uint32 *m_watchDogCounter;
1019 
1020   SectionSegmentPool::Cache * m_sectionPoolCache;
1021 
1022 
1023   Uint32 doNodeFailureCleanup(Signal* signal,
1024                               Uint32 failedNodeId,
1025                               Uint32 resource,
1026                               Uint32 cursor,
1027                               Uint32 elementsCleaned,
1028                               Callback& cb);
1029 
1030   bool doCleanupFragInfo(Uint32 failedNodeId,
1031                          Uint32& cursor,
1032                          Uint32& rtUnitsUsed,
1033                          Uint32& elementsCleaned);
1034 
1035   bool doCleanupFragSend(Uint32 failedNodeId,
1036                          Uint32& cursor,
1037                          Uint32& rtUnitsUsed,
1038                          Uint32& elementsCleaned);
1039 
1040 protected:
1041   Block_context m_ctx;
1042   NewVARIABLE* allocateBat(int batSize);
1043   void freeBat();
1044   static const NewVARIABLE* getBat    (BlockNumber blockNo,
1045                                        Uint32 instanceNo);
1046   static Uint16             getBatSize(BlockNumber blockNo,
1047                                        Uint32 instanceNo);
1048 
1049   static BlockReference calcTcBlockRef   (NodeId aNode);
1050   static BlockReference calcLqhBlockRef  (NodeId aNode);
1051   static BlockReference calcAccBlockRef  (NodeId aNode);
1052   static BlockReference calcTupBlockRef  (NodeId aNode);
1053   static BlockReference calcTuxBlockRef  (NodeId aNode);
1054   static BlockReference calcDihBlockRef  (NodeId aNode);
1055   static BlockReference calcQmgrBlockRef (NodeId aNode);
1056   static BlockReference calcDictBlockRef (NodeId aNode);
1057   static BlockReference calcNdbCntrBlockRef (NodeId aNode);
1058   static BlockReference calcTrixBlockRef (NodeId aNode);
1059   static BlockReference calcBackupBlockRef (NodeId aNode);
1060   static BlockReference calcSumaBlockRef (NodeId aNode);
1061 
1062   static BlockReference calcApiClusterMgrBlockRef (NodeId aNode);
1063 
1064   // matching instance on same node e.g. LQH-ACC-TUP
1065   BlockReference calcInstanceBlockRef(BlockNumber aBlock);
1066 
1067   // matching instance on another node e.g. LQH-LQH
1068   // valid only if receiver has same number of workers
1069   BlockReference calcInstanceBlockRef(BlockNumber aBlock, NodeId aNode);
1070 
1071   /**
1072    * allocRecord
1073    * Allocates memory for the datastructures where ndb keeps the data
1074    *
1075    */
1076   void* allocRecord(const char * type, size_t s, size_t n, bool clear = true, Uint32 paramId = 0);
1077   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);
1078 
1079   /**
1080    * Deallocate record
1081    *
1082    * NOTE: Also resets pointer
1083    */
1084   void deallocRecord(void **, const char * type, size_t s, size_t n);
1085 
1086   /**
1087    * Allocate memory from global pool,
1088    *   returns #chunks used
1089    *
1090    * Typically used by part of code, not converted to use global pool
1091    *   directly, but allocates everything during startup
1092    */
1093   struct AllocChunk
1094   {
1095     Uint32 ptrI;
1096     Uint32 cnt;
1097   };
1098   Uint32 allocChunks(AllocChunk dst[], Uint32 /* size of dst */ arraysize,
1099                      Uint32 /* resource group */ rg,
1100                      Uint32 /* no of pages to allocate */ pages,
1101                      Uint32 paramId /* for error message if failing */);
1102 
1103   static int sortchunks(const void*, const void*);
1104 
1105   /**
1106    * General info event (sent to cluster log)
1107    */
1108   void infoEvent(const char * msg, ...) const
1109     ATTRIBUTE_FORMAT(printf, 2, 3);
1110   void warningEvent(const char * msg, ...) const
1111     ATTRIBUTE_FORMAT(printf, 2, 3);
1112 
1113   /**
1114    * Get node state
1115    */
1116   const NodeState & getNodeState() const;
1117 
1118   /**
1119    * Get node info
1120    */
1121   const NodeInfo & getNodeInfo(NodeId nodeId) const;
1122   NodeInfo & setNodeInfo(NodeId);
1123 
1124   const NodeVersionInfo& getNodeVersionInfo() const;
1125   NodeVersionInfo& setNodeVersionInfo();
1126 
1127   /**********************
1128    * Xfrm stuff
1129    */
1130 
1131   /**
1132    * @return length
1133    */
1134   Uint32 xfrm_key(Uint32 tab, const Uint32* src,
1135 		  Uint32 *dst, Uint32 dstSize,
1136 		  Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX]) const;
1137 
1138   Uint32 xfrm_attr(Uint32 attrDesc, CHARSET_INFO* cs,
1139                    const Uint32* src, Uint32 & srcPos,
1140                    Uint32* dst, Uint32 & dstPos, Uint32 dstSize) const;
1141 
1142   /**
1143    *
1144    */
1145   Uint32 create_distr_key(Uint32 tableId,
1146 			  const Uint32* src,
1147                           Uint32 *dst,
1148 			  const Uint32 keyPaLen[MAX_ATTRIBUTES_IN_INDEX])const;
1149 
1150   /**
1151    * if ndbd,
1152    *   wakeup main-loop if sleeping on IO
1153    * if ndbmtd
1154    *   wakeup thread running block-instance
1155    */
1156   void wakeup();
1157 
1158   /**
1159    * setup struct for wakeup
1160    */
1161   void setup_wakeup();
1162 
1163   /**
1164    * Get receiver thread index for node
1165    * MAX_NODES == no receiver thread
1166    */
1167   Uint32 get_recv_thread_idx(NodeId nodeId);
1168 
1169 private:
1170   NewVARIABLE* NewVarRef;      /* New Base Address Table for block  */
1171   Uint16       theBATSize;     /* # entries in BAT */
1172 
1173 protected:
1174   SafeArrayPool<GlobalPage>& m_global_page_pool;
1175   ArrayPool<GlobalPage>& m_shared_page_pool;
1176 
1177   void execNDB_TAMPER(Signal * signal);
1178   void execNODE_STATE_REP(Signal* signal);
1179   void execCHANGE_NODE_STATE_REQ(Signal* signal);
1180 
1181   void execSIGNAL_DROPPED_REP(Signal* signal);
1182   void execCONTINUE_FRAGMENTED(Signal* signal);
1183   void execSTOP_FOR_CRASH(Signal* signal);
1184   void execAPI_START_REP(Signal* signal);
1185   void execNODE_START_REP(Signal* signal);
1186   void execSEND_PACKED(Signal* signal);
1187   void execLOCAL_ROUTE_ORD(Signal*);
1188 private:
1189   /**
1190    * Node state
1191    */
1192   NodeState theNodeState;
1193 
1194   Uint32 c_fragmentIdCounter;
1195   ArrayPool<FragmentInfo> c_fragmentInfoPool;
1196   DLHashTable<FragmentInfo> c_fragmentInfoHash;
1197 
1198   bool c_fragSenderRunning;
1199   ArrayPool<FragmentSendInfo> c_fragmentSendPool;
1200   DLList<FragmentSendInfo> c_linearFragmentSendList;
1201   DLList<FragmentSendInfo> c_segmentedFragmentSendList;
1202 
1203 protected:
1204   Uint32 debugPrintFragmentCounts();
1205 
1206 public:
1207   class MutexManager {
1208     friend class Mutex;
1209     friend class SimulatedBlock;
1210     friend class DbUtil;
1211   public:
1212     MutexManager(class SimulatedBlock &);
1213 
1214     bool setSize(Uint32 maxNoOfActiveMutexes);
1215     Uint32 getSize() const ; // Get maxNoOfActiveMutexes
1216 
1217   private:
1218     /**
1219      * core interface
1220      */
1221     struct ActiveMutex {
ActiveMutexSimulatedBlock::MutexManager::ActiveMutex1222       ActiveMutex() {}
1223       Uint32 m_gsn; // state
1224       Uint32 m_mutexId;
1225       Callback m_callback;
1226       union {
1227 	Uint32 nextPool;
1228 	Uint32 nextList;
1229       };
1230       Uint32 prevList;
1231     };
1232     typedef Ptr<ActiveMutex> ActiveMutexPtr;
1233 
1234     bool seize(ActiveMutexPtr& ptr);
1235     void release(Uint32 activeMutexPtrI);
1236 
1237     void getPtr(ActiveMutexPtr& ptr);
1238 
1239     void create(Signal*, ActiveMutexPtr&);
1240     void destroy(Signal*, ActiveMutexPtr&);
1241     void lock(Signal*, ActiveMutexPtr&, Uint32 flags);
1242     void unlock(Signal*, ActiveMutexPtr&);
1243 
1244   private:
1245     void execUTIL_CREATE_LOCK_REF(Signal* signal);
1246     void execUTIL_CREATE_LOCK_CONF(Signal* signal);
1247     void execUTIL_DESTORY_LOCK_REF(Signal* signal);
1248     void execUTIL_DESTORY_LOCK_CONF(Signal* signal);
1249     void execUTIL_LOCK_REF(Signal* signal);
1250     void execUTIL_LOCK_CONF(Signal* signal);
1251     void execUTIL_UNLOCK_REF(Signal* signal);
1252     void execUTIL_UNLOCK_CONF(Signal* signal);
1253 
1254     SimulatedBlock & m_block;
1255     ArrayPool<ActiveMutex> m_mutexPool;
1256     DLList<ActiveMutex> m_activeMutexes;
1257 
1258     BlockReference reference() const;
1259     void progError(int line,
1260                    int err_code,
1261                    const char* extra = 0) ATTRIBUTE_NORETURN;
1262   };
1263 
1264   friend class MutexManager;
1265   MutexManager c_mutexMgr;
1266 
1267   void ignoreMutexUnlockCallback(Signal* signal, Uint32 ptrI, Uint32 retVal);
getParam(const char * param,Uint32 * retVal)1268   virtual bool getParam(const char * param, Uint32 * retVal) { return false;}
1269 
1270   SafeCounterManager c_counterMgr;
1271 private:
1272   void execUTIL_CREATE_LOCK_REF(Signal* signal);
1273   void execUTIL_CREATE_LOCK_CONF(Signal* signal);
1274   void execUTIL_DESTORY_LOCK_REF(Signal* signal);
1275   void execUTIL_DESTORY_LOCK_CONF(Signal* signal);
1276   void execUTIL_LOCK_REF(Signal* signal);
1277   void execUTIL_LOCK_CONF(Signal* signal);
1278   void execUTIL_UNLOCK_REF(Signal* signal);
1279   void execUTIL_UNLOCK_CONF(Signal* signal);
1280 
1281   void check_sections(Signal* signal,
1282                       Uint32 oldSecCount,
1283                       Uint32 newSecCount) const;
1284 protected:
1285 
1286   void fsRefError(Signal* signal, Uint32 line, const char *msg);
1287   void execFSWRITEREF(Signal* signal);
1288   void execFSREADREF(Signal* signal);
1289   void execFSOPENREF(Signal* signal);
1290   void execFSCLOSEREF(Signal* signal);
1291   void execFSREMOVEREF(Signal* signal);
1292   void execFSSYNCREF(Signal* signal);
1293   void execFSAPPENDREF(Signal* signal);
1294 
1295   // MT LQH callback CONF via signal
1296 public:
1297   struct CallbackPtr {
1298     Uint32 m_callbackIndex;
1299     Uint32 m_callbackData;
1300   };
1301 protected:
1302   enum CallbackFlags {
1303     CALLBACK_DIRECT = 0x0001, // use EXECUTE_DIRECT (assumed thread safe)
1304     CALLBACK_ACK    = 0x0002  // send ack at the end of callback timeslice
1305   };
1306 
1307   struct CallbackEntry {
1308     CallbackFunction m_function;
1309     Uint32 m_flags;
1310   };
1311 
1312   struct CallbackTable {
1313     Uint32 m_count;
1314     CallbackEntry* m_entry; // array
1315   };
1316 
1317   CallbackTable* m_callbackTableAddr; // set by block if used
1318 
1319   enum {
1320     THE_NULL_CALLBACK = 0 // must assign TheNULLCallbackFunction
1321   };
1322 
1323   void execute(Signal* signal, CallbackPtr & cptr, Uint32 returnCode);
1324   const CallbackEntry& getCallbackEntry(Uint32 ci);
1325   void sendCallbackConf(Signal* signal, Uint32 fullBlockNo,
1326                         CallbackPtr& cptr,
1327                         Uint32 senderData, Uint32 callbackInfo,
1328                         Uint32 returnCode);
1329   void execCALLBACK_CONF(Signal* signal);
1330 
1331   // Variable for storing inserted errors, see pc.H
1332   ERROR_INSERT_VARIABLE;
1333 
1334 #ifdef VM_TRACE_TIME
1335 public:
1336   void clearTimes();
1337   void printTimes(FILE * output);
1338   void addTime(Uint32 gsn, Uint64 time);
1339   void subTime(Uint32 gsn, Uint64 time);
1340   struct TimeTrace {
1341     Uint32 cnt;
1342     Uint64 sum, sub;
1343   } m_timeTrace[MAX_GSN+1];
1344   Uint32 m_currentGsn;
1345 #endif
1346 
1347 #ifdef VM_TRACE
1348   Ptr<void> **m_global_variables, **m_global_variables_save;
1349   void clear_global_variables();
1350   void init_globals_list(void ** tmp, size_t cnt);
1351   void disable_global_variables();
1352   void enable_global_variables();
1353 #endif
1354 
1355 #ifdef VM_TRACE
1356 public:
1357   NdbOut debugOut;
debugOutStream()1358   NdbOut& debugOutStream() { return debugOut; };
1359   bool debugOutOn();
debugOutLock()1360   void debugOutLock() { globalSignalLoggers.lock(); }
debugOutUnlock()1361   void debugOutUnlock() { globalSignalLoggers.unlock(); }
1362   const char* debugOutTag(char* buf, int line);
1363 #endif
1364 
1365   void ndbinfo_send_row(Signal* signal,
1366                         const DbinfoScanReq& req,
1367                         const Ndbinfo::Row& row,
1368                         Ndbinfo::Ratelimit& rl) const;
1369 
1370   void ndbinfo_send_scan_break(Signal* signal,
1371                                DbinfoScanReq& req,
1372                                const Ndbinfo::Ratelimit& rl,
1373                                Uint32 data1, Uint32 data2 = 0,
1374                                Uint32 data3 = 0, Uint32 data4 = 0) const;
1375 
1376   void ndbinfo_send_scan_conf(Signal* signal,
1377                               DbinfoScanReq& req,
1378                               const Ndbinfo::Ratelimit& rl) const;
1379 
1380 
1381 protected:
1382   /**
1383    * SegmentUtils methods
1384    */
1385   virtual SectionSegment* getSegmentPtr(Uint32 iVal);
1386   virtual bool seizeSegment(Ptr<SectionSegment>& p);
1387   virtual void releaseSegment(Uint32 iVal);
1388 
1389   virtual void releaseSegmentList(Uint32 firstSegmentIVal);
1390 
1391   /** End of SegmentUtils methods */
1392 };
1393 
1394 // outside blocks e.g. within a struct
1395 #ifdef VM_TRACE
1396 #define DEBUG_OUT_DEFINES(blockNo) \
1397 static SimulatedBlock* debugOutBlock() \
1398   { return globalData.getBlock(blockNo); } \
1399 static NdbOut& debugOutStream() \
1400   { return debugOutBlock()->debugOutStream(); } \
1401 static bool debugOutOn() \
1402   { return debugOutBlock()->debugOutOn(); } \
1403 static void debugOutLock() \
1404   { debugOutBlock()->debugOutLock(); } \
1405 static void debugOutUnlock() \
1406   { debugOutBlock()->debugOutUnlock(); } \
1407 static const char* debugOutTag(char* buf, int line) \
1408   { return debugOutBlock()->debugOutTag(buf, line); } \
1409 static void debugOutDefines()
1410 #else
1411 #define DEBUG_OUT_DEFINES(blockNo) \
1412 static void debugOutDefines()
1413 #endif
1414 
1415 inline
1416 void
executeFunction(GlobalSignalNumber gsn,Signal * signal)1417 SimulatedBlock::executeFunction(GlobalSignalNumber gsn,
1418                                 Signal *signal)
1419 {
1420   ExecFunction f = theExecArray[gsn];
1421   if (unlikely(gsn > MAX_GSN))
1422   {
1423     handle_execute_error(gsn);
1424     return;
1425   }
1426   executeFunction(gsn, signal, f);
1427 }
1428 
1429 inline
1430 void
executeFunction_async(GlobalSignalNumber gsn,Signal * signal)1431 SimulatedBlock::executeFunction_async(GlobalSignalNumber gsn,
1432                                       Signal *signal)
1433 {
1434   ExecFunction f = theExecArray[gsn];
1435 #ifdef VM_TRACE
1436   clear_global_variables();
1437 #endif
1438   if (unlikely(gsn > MAX_GSN))
1439   {
1440     handle_execute_error(gsn);
1441     return;
1442   }
1443   executeFunction(gsn, signal, f);
1444 }
1445 
1446 inline
1447 void
executeFunction(GlobalSignalNumber gsn,Signal * signal,ExecFunction f,BlockReference ref,Uint32 len)1448 SimulatedBlock::executeFunction(GlobalSignalNumber gsn,
1449                                 Signal* signal,
1450                                 ExecFunction f,
1451                                 BlockReference ref,
1452                                 Uint32 len)
1453 {
1454   if (unlikely(gsn > MAX_GSN))
1455   {
1456     handle_execute_error(gsn);
1457     return;
1458   }
1459   signal->setLength(len);
1460   signal->header.theSendersBlockRef = ref;
1461   executeFunction(gsn, signal, f);
1462 }
1463 
1464 inline
1465 void
executeFunction(GlobalSignalNumber gsn,Signal * signal,ExecFunction f)1466 SimulatedBlock::executeFunction(GlobalSignalNumber gsn,
1467                                 Signal* signal,
1468                                 ExecFunction f)
1469 {
1470   if (likely(f != 0))
1471   {
1472     (this->*f)(signal);
1473 
1474     if (unlikely(signal->header.m_noOfSections))
1475     {
1476       handle_lingering_sections_after_execute(signal);
1477     }
1478     return;
1479   }
1480   /**
1481    * This point only passed if an error has occurred
1482    */
1483   handle_execute_error(gsn);
1484 }
1485 
1486 inline
1487 void
execute(Signal * signal,Callback & c,Uint32 returnCode)1488 SimulatedBlock::execute(Signal* signal, Callback & c, Uint32 returnCode){
1489   CallbackFunction fun = c.m_callbackFunction;
1490   if (fun == TheNULLCallback.m_callbackFunction)
1491     return;
1492   ndbrequire(fun != 0);
1493   c.m_callbackFunction = NULL;
1494   (this->*fun)(signal, c.m_callbackData, returnCode);
1495 }
1496 
1497 inline
1498 void
execute(Signal * signal,CallbackPtr & cptr,Uint32 returnCode)1499 SimulatedBlock::execute(Signal* signal, CallbackPtr & cptr, Uint32 returnCode){
1500   const CallbackEntry& ce = getCallbackEntry(cptr.m_callbackIndex);
1501   cptr.m_callbackIndex = ZNIL;
1502   Callback c;
1503   c.m_callbackFunction = ce.m_function;
1504   c.m_callbackData = cptr.m_callbackData;
1505   execute(signal, c, returnCode);
1506 }
1507 
1508 inline
1509 BlockNumber
number() const1510 SimulatedBlock::number() const {
1511    return theNumber;
1512 }
1513 
1514 inline
1515 EmulatedJamBuffer *
jamBuffer() const1516 SimulatedBlock::jamBuffer() const {
1517    return m_jamBuffer;
1518 }
1519 
1520 inline
1521 BlockReference
reference() const1522 SimulatedBlock::reference() const {
1523    return theReference;
1524 }
1525 
1526 inline
1527 NodeId
getOwnNodeId() const1528 SimulatedBlock::getOwnNodeId() const {
1529   return theNodeId;
1530 }
1531 
1532 inline
1533 BlockReference
calcTcBlockRef(NodeId aNodeId)1534 SimulatedBlock::calcTcBlockRef   (NodeId aNodeId){
1535   return numberToRef(DBTC, aNodeId);
1536 }
1537 
1538 inline
1539 BlockReference
calcLqhBlockRef(NodeId aNodeId)1540 SimulatedBlock::calcLqhBlockRef  (NodeId aNodeId){
1541 return numberToRef(DBLQH, aNodeId);
1542 }
1543 
1544 inline
1545 BlockReference
calcAccBlockRef(NodeId aNodeId)1546 SimulatedBlock::calcAccBlockRef  (NodeId aNodeId){
1547   return numberToRef(DBACC, aNodeId);
1548 }
1549 
1550 inline
1551 BlockReference
calcTupBlockRef(NodeId aNodeId)1552 SimulatedBlock::calcTupBlockRef  (NodeId aNodeId){
1553   return numberToRef(DBTUP, aNodeId);
1554 }
1555 
1556 inline
1557 BlockReference
calcTuxBlockRef(NodeId aNodeId)1558 SimulatedBlock::calcTuxBlockRef  (NodeId aNodeId){
1559   return numberToRef(DBTUX, aNodeId);
1560 }
1561 
1562 inline
1563 BlockReference
calcDihBlockRef(NodeId aNodeId)1564 SimulatedBlock::calcDihBlockRef  (NodeId aNodeId){
1565   return numberToRef(DBDIH, aNodeId);
1566 }
1567 
1568 inline
1569 BlockReference
calcDictBlockRef(NodeId aNodeId)1570 SimulatedBlock::calcDictBlockRef (NodeId aNodeId){
1571   return numberToRef(DBDICT, aNodeId);
1572 }
1573 
1574 inline
1575 BlockReference
calcQmgrBlockRef(NodeId aNodeId)1576 SimulatedBlock::calcQmgrBlockRef (NodeId aNodeId){
1577   return numberToRef(QMGR, aNodeId);
1578 }
1579 
1580 inline
1581 BlockReference
calcNdbCntrBlockRef(NodeId aNodeId)1582 SimulatedBlock::calcNdbCntrBlockRef (NodeId aNodeId){
1583   return numberToRef(NDBCNTR, aNodeId);
1584 }
1585 
1586 inline
1587 BlockReference
calcTrixBlockRef(NodeId aNodeId)1588 SimulatedBlock::calcTrixBlockRef (NodeId aNodeId){
1589   return numberToRef(TRIX, aNodeId);
1590 }
1591 
1592 inline
1593 BlockReference
calcBackupBlockRef(NodeId aNodeId)1594 SimulatedBlock::calcBackupBlockRef (NodeId aNodeId){
1595   return numberToRef(BACKUP, aNodeId);
1596 }
1597 
1598 inline
1599 BlockReference
calcSumaBlockRef(NodeId aNodeId)1600 SimulatedBlock::calcSumaBlockRef (NodeId aNodeId){
1601   return numberToRef(SUMA, aNodeId);
1602 }
1603 
1604 inline
1605 BlockReference
calcApiClusterMgrBlockRef(NodeId aNodeId)1606 SimulatedBlock::calcApiClusterMgrBlockRef (NodeId aNodeId){
1607   return numberToRef(API_CLUSTERMGR, aNodeId);
1608 }
1609 
1610 inline
1611 BlockReference
calcInstanceBlockRef(BlockNumber aBlock)1612 SimulatedBlock::calcInstanceBlockRef(BlockNumber aBlock){
1613   return numberToRef(aBlock, instance(), getOwnNodeId());
1614 }
1615 
1616 inline
1617 BlockReference
calcInstanceBlockRef(BlockNumber aBlock,NodeId aNodeId)1618 SimulatedBlock::calcInstanceBlockRef(BlockNumber aBlock, NodeId aNodeId){
1619   return numberToRef(aBlock, instance(), aNodeId);
1620 }
1621 
1622 inline
1623 const NodeState &
getNodeState() const1624 SimulatedBlock::getNodeState() const {
1625   return theNodeState;
1626 }
1627 
1628 inline
1629 const NodeInfo &
getNodeInfo(NodeId nodeId) const1630 SimulatedBlock::getNodeInfo(NodeId nodeId) const {
1631   ndbrequire(nodeId > 0 && nodeId < MAX_NODES);
1632   return globalData.m_nodeInfo[nodeId];
1633 }
1634 
1635 inline
1636 const NodeVersionInfo &
getNodeVersionInfo() const1637 SimulatedBlock::getNodeVersionInfo() const {
1638   return globalData.m_versionInfo;
1639 }
1640 
1641 inline
1642 NodeVersionInfo &
setNodeVersionInfo()1643 SimulatedBlock::setNodeVersionInfo() {
1644   return globalData.m_versionInfo;
1645 }
1646 
1647 #ifdef VM_TRACE_TIME
1648 inline
1649 void
addTime(Uint32 gsn,Uint64 time)1650 SimulatedBlock::addTime(Uint32 gsn, Uint64 time){
1651   m_timeTrace[gsn].cnt ++;
1652   m_timeTrace[gsn].sum += time;
1653 }
1654 
1655 inline
1656 void
subTime(Uint32 gsn,Uint64 time)1657 SimulatedBlock::subTime(Uint32 gsn, Uint64 time){
1658   m_timeTrace[gsn].sub += time;
1659 }
1660 #endif
1661 
1662 inline
1663 void
EXECUTE_DIRECT(ExecFunction f,Signal * signal)1664 SimulatedBlock::EXECUTE_DIRECT(ExecFunction f,
1665                                Signal *signal)
1666 {
1667   (this->*f)(signal);
1668 }
1669 
1670 inline
1671 void
EXECUTE_DIRECT(Uint32 block,Uint32 gsn,Signal * signal,Uint32 len,Uint32 instanceNo)1672 SimulatedBlock::EXECUTE_DIRECT(Uint32 block,
1673 			       Uint32 gsn,
1674 			       Signal* signal,
1675 			       Uint32 len,
1676                                Uint32 instanceNo)
1677 {
1678   SimulatedBlock* rec_block;
1679   SimulatedBlock* main_block = globalData.getBlock(block);
1680   ndbassert(main_block != 0);
1681   /**
1682    * In multithreaded NDB, blocks run in different threads, and EXECUTE_DIRECT
1683    * (unlike sendSignal) is generally not thread-safe.
1684    * So only allow EXECUTE_DIRECT between blocks that run in the same thread,
1685    * unless caller explicitly marks it as being thread safe (eg NDBFS),
1686    * by using an explicit instance argument.
1687    * By default instance of sender is used.  This is automatically thread-safe
1688    * for worker instances (instance != 0).
1689    *
1690    * We also need to use this function when calling blocks that don't belong
1691    * to the same module, so e.g. LDM blocks can all call each other without
1692    * using this method. But e.g. no block can call THRMAN using implicit
1693    * instance id since the instance numbers of the LDM blocks and the THRMAN
1694    * blocks are not the same. There is one THRMAN instance for each thread,
1695    * not only for the LDM threads.
1696    */
1697   signal->header.theSendersBlockRef = reference();
1698   signal->setLength(len);
1699   ndbassert(instanceNo < MaxInstances);
1700   rec_block = main_block->getInstance(instanceNo);
1701   ndbassert(rec_block != 0);
1702 #ifdef VM_TRACE
1703   if(globalData.testOn){
1704     signal->header.theVerId_signalNumber = gsn;
1705     signal->header.theReceiversBlockNumber = numberToBlock(block, instanceNo);
1706     globalSignalLoggers.executeDirect(signal->header,
1707 				      0,        // in
1708 				      &signal->theData[0],
1709                                       globalData.ownId);
1710   }
1711 #endif
1712 #ifdef VM_TRACE_TIME
1713   const NDB_TICKS t1 = NdbTick_getCurrentTicks();
1714   Uint32 tGsn = m_currentGsn;
1715   rec_block->m_currentGsn = gsn;
1716 #endif
1717   rec_block->executeFunction(gsn, signal);
1718 #ifdef VM_TRACE_TIME
1719   const NDB_TICKS t2 = NdbTick_getCurrentTicks();
1720   const Uint64 diff = NdbTick_Elapsed(t1, t2).microSec();
1721   rec_block->addTime(gsn, diff);
1722   m_currentGsn = tGsn;
1723   subTime(tGsn, diff);
1724 #endif
1725 }
1726 
1727 /**
1728   We implement the normal EXECUTE_DIRECT in a special function
1729   since this is performance-critical although it introduces a
1730   little bit of code duplication.
1731 */
1732 inline
1733 void
EXECUTE_DIRECT(Uint32 block,Uint32 gsn,Signal * signal,Uint32 len)1734 SimulatedBlock::EXECUTE_DIRECT(Uint32 block,
1735 			       Uint32 gsn,
1736 			       Signal* signal,
1737 			       Uint32 len)
1738 {
1739   /**
1740     globalData.getBlock(block) gives us the pointer to the block of
1741     the receiving class, it gives the pointer to instance 0. This
1742     instance has all the function pointers that all other instances
1743     also have, so we can reuse this block object to get the execute
1744     function. This means that we will use less cache lines over the
1745     system.
1746   */
1747   SimulatedBlock* main_block = globalData.getBlock(block);
1748   Uint32 instanceNo = instance();
1749   BlockReference ref = reference();
1750   SimulatedBlock* rec_block;
1751   signal->setLength(len);
1752   ndbassert(main_block != 0);
1753   ndbassert(main_block->theInstance == 0);
1754   ndbassert(instanceNo < MaxInstances);
1755   rec_block = main_block->theInstanceList[instanceNo];
1756   if (unlikely(gsn > MAX_GSN))
1757   {
1758     handle_execute_error(gsn);
1759     return;
1760   }
1761   ExecFunction f = rec_block->theExecArray[gsn];
1762   signal->header.theSendersBlockRef = ref;
1763   /**
1764    * In this function we only allow function calls within the same thread.
1765    *
1766    * No InstanceList leads to immediate Segmentation Fault,
1767    * so not necessary to check with ndbrequire for this.
1768    */
1769   ndbassert(rec_block != 0);
1770   ndbassert(rec_block->getThreadId() == getThreadId());
1771 #ifdef VM_TRACE
1772   if(globalData.testOn){
1773     signal->header.theVerId_signalNumber = gsn;
1774     signal->header.theReceiversBlockNumber = numberToBlock(block, instanceNo);
1775     globalSignalLoggers.executeDirect(signal->header,
1776 				      0,        // in
1777 				      &signal->theData[0],
1778                                       globalData.ownId);
1779   }
1780 #endif
1781 #ifdef VM_TRACE_TIME
1782   const NDB_TICKS t1 = NdbTick_getCurrentTicks();
1783   Uint32 tGsn = m_currentGsn;
1784   rec_block->m_currentGsn = gsn;
1785 #endif
1786   rec_block->executeFunction(gsn, signal, f);
1787 #ifdef VM_TRACE_TIME
1788   const NDB_TICKS t2 = NdbTick_getCurrentTicks();
1789   const Uint64 diff = NdbTick_Elapsed(t1,t2).microSec();
1790   rec_block->addTime(gsn, diff);
1791   m_currentGsn = tGsn;
1792   subTime(tGsn, diff);
1793 #endif
1794 }
1795 
1796 // Do a consictency check before reusing a signal.
1797 inline void
check_sections(Signal * signal,Uint32 oldSecCount,Uint32 newSecCount) const1798 SimulatedBlock::check_sections(Signal* signal,
1799                                Uint32 oldSecCount,
1800                                Uint32 newSecCount) const
1801 {
1802   // Sections from previous use should have been consumed by now.
1803   if (unlikely(oldSecCount != 0))
1804   {
1805     handle_invalid_sections_in_send_signal(signal);
1806   }
1807   else if (unlikely(newSecCount == 0 &&
1808                     signal->header.m_fragmentInfo != 0 &&
1809                     signal->header.m_fragmentInfo != 3))
1810   {
1811     handle_invalid_fragmentInfo(signal);
1812   }
1813 }
1814 
1815 /**
1816  * Defines for backward compatiblility
1817  */
1818 
1819 #define BLOCK_DEFINES(BLOCK) \
1820   typedef void (BLOCK::* ExecSignalLocal) (Signal* signal); \
1821   typedef void (BLOCK::* BlockCallback)(Signal*, Uint32 callb, Uint32 retCode); \
1822   inline CallbackFunction safe_cast(BlockCallback f){ \
1823     return static_cast<CallbackFunction>(f); \
1824   } \
1825 public:\
1826 private: \
1827   void addRecSignal(GlobalSignalNumber gsn, ExecSignalLocal f, bool force = false)
1828 
1829 #define BLOCK_CONSTRUCTOR(BLOCK) do { SimulatedBlock::initCommon(); } while(0)
1830 
1831 #define BLOCK_FUNCTIONS(BLOCK) \
1832 void \
1833 BLOCK::addRecSignal(GlobalSignalNumber gsn, ExecSignalLocal f, bool force){ \
1834   addRecSignalImpl(gsn, (ExecFunction)f, force);\
1835 }
1836 
1837 #ifdef ERROR_INSERT
1838 #define RSS_AP_SNAPSHOT(x) Uint32 rss_##x
1839 #define RSS_AP_SNAPSHOT_SAVE(x) rss_##x = x.getNoOfFree()
1840 #define RSS_AP_SNAPSHOT_CHECK(x) ndbrequire(rss_##x == x.getNoOfFree())
1841 #define RSS_AP_SNAPSHOT_SAVE2(x,y) rss_##x = x.getNoOfFree()+(y)
1842 #define RSS_AP_SNAPSHOT_CHECK2(x,y) ndbrequire(rss_##x == x.getNoOfFree()+(y))
1843 
1844 #define RSS_OP_COUNTER(x) Uint32 x
1845 #define RSS_OP_COUNTER_INIT(x) x = 0
1846 #define RSS_OP_ALLOC(x) x ++
1847 #define RSS_OP_FREE(x) x --
1848 #define RSS_OP_ALLOC_X(x,n) x += n
1849 #define RSS_OP_FREE_X(x,n) x -= n
1850 
1851 #define RSS_OP_SNAPSHOT(x) Uint32 rss_##x
1852 #define RSS_OP_SNAPSHOT_SAVE(x) rss_##x = x
1853 #define RSS_OP_SNAPSHOT_CHECK(x) ndbrequire(rss_##x == x)
1854 
1855 #define RSS_DA256_SNAPSHOT(x) Uint32 rss_##x
1856 #define RSS_DA256_SNAPSHOT_SAVE(x) rss_##x = x.m_high_pos
1857 #define RSS_DA256_SNAPSHOT_CHECK(x) ndbrequire(x.m_high_pos <= rss_##x)
1858 #else
1859 #define RSS_AP_SNAPSHOT(x) struct rss_dummy0_##x { int dummy; }
1860 #define RSS_AP_SNAPSHOT_SAVE(x)
1861 #define RSS_AP_SNAPSHOT_CHECK(x)
1862 #define RSS_AP_SNAPSHOT_SAVE2(x,y)
1863 #define RSS_AP_SNAPSHOT_CHECK2(x,y)
1864 
1865 #define RSS_OP_COUNTER(x) struct rss_dummy1_##x { int dummy; }
1866 #define RSS_OP_COUNTER_INIT(x)
1867 #define RSS_OP_ALLOC(x)
1868 #define RSS_OP_FREE(x)
1869 #define RSS_OP_ALLOC_X(x,n)
1870 #define RSS_OP_FREE_X(x,n)
1871 
1872 #define RSS_OP_SNAPSHOT(x) struct rss_dummy2_##x { int dummy; }
1873 #define RSS_OP_SNAPSHOT_SAVE(x)
1874 #define RSS_OP_SNAPSHOT_CHECK(x)
1875 
1876 #define RSS_DA256_SNAPSHOT(x)
1877 #define RSS_DA256_SNAPSHOT_SAVE(x)
1878 #define RSS_DA256_SNAPSHOT_CHECK(x)
1879 #endif
1880 
1881 struct Hash2FragmentMap
1882 {
1883   STATIC_CONST( MAX_MAP = NDB_MAX_HASHMAP_BUCKETS );
1884   Uint32 m_cnt;
1885   Uint32 m_fragments;
1886   Uint16 m_map[MAX_MAP];
1887   Uint32 nextPool;
1888   Uint32 m_object_id;
1889 };
1890 
1891 extern ArrayPool<Hash2FragmentMap> g_hash_map;
1892 
1893 /**
1894  * Guard class for auto release of segmentedsectionptr's
1895  */
1896 class SegmentedSectionGuard
1897 {
1898   Uint32 cnt;
1899   Uint32 ptr[3];
1900   SimulatedBlock * block;
1901 
1902 public:
SegmentedSectionGuard(SimulatedBlock * b)1903   SegmentedSectionGuard(SimulatedBlock* b) : cnt(0), block(b) { }
SegmentedSectionGuard(SimulatedBlock * b,Uint32 ptrI)1904   SegmentedSectionGuard(SimulatedBlock* b, Uint32 ptrI) : cnt(1), block(b) {
1905     ptr[0] = ptrI;
1906   }
1907 
add(Uint32 ptrI)1908   void add(Uint32 ptrI) {
1909     if (ptrI != RNIL)
1910     {
1911       assert(cnt < NDB_ARRAY_SIZE(ptr));
1912       ptr[cnt] = ptrI;
1913       cnt++;
1914     }
1915   }
1916 
release()1917   void release() {
1918     for (Uint32 i = 0; i < cnt; i++) {
1919       if (ptr[i] != RNIL)
1920         block->releaseSection(ptr[i]);
1921     }
1922     cnt = 0;
1923   }
1924 
clear()1925   void clear() {
1926     cnt = 0;
1927   }
1928 
~SegmentedSectionGuard()1929   ~SegmentedSectionGuard() {
1930     release();
1931   }
1932 };
1933 
1934 #undef JAM_FILE_ID
1935 
1936 #endif
1937 
1938