SimulatedBlock.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:48k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2003 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #include <ndb_global.h>
  14. #include "SimulatedBlock.hpp"
  15. #include <NdbOut.hpp>
  16. #include <GlobalData.hpp>
  17. #include <Emulator.hpp>
  18. #include <ErrorHandlingMacros.hpp>
  19. #include <TimeQueue.hpp>
  20. #include <TransporterRegistry.hpp>
  21. #include <SignalLoggerManager.hpp>
  22. #include <FastScheduler.hpp>
  23. #include <NdbMem.h>
  24. #include <signaldata/EventReport.hpp>
  25. #include <signaldata/ContinueFragmented.hpp>
  26. #include <signaldata/NodeStateSignalData.hpp>
  27. #include <signaldata/FsRef.hpp>
  28. #include <DebuggerNames.hpp>
  29. #include "LongSignal.hpp"
  30. #include <Properties.hpp>
  31. #include "Configuration.hpp"
  32. #define ljamEntry() jamEntryLine(30000 + __LINE__)
  33. #define ljam() jamLine(30000 + __LINE__)
  34. //
  35. // Constructor, Destructor
  36. //
  37. SimulatedBlock::SimulatedBlock(BlockNumber blockNumber,
  38.        const class Configuration & conf) 
  39.   : theNodeId(globalData.ownId),
  40.     theNumber(blockNumber),
  41.     theReference(numberToRef(blockNumber, globalData.ownId)),
  42.     theConfiguration(conf),
  43.     c_fragmentInfoHash(c_fragmentInfoPool),
  44.     c_linearFragmentSendList(c_fragmentSendPool),
  45.     c_segmentedFragmentSendList(c_fragmentSendPool),
  46.     c_mutexMgr(* this),
  47.     c_counterMgr(* this),
  48.     c_ptrMetaDataCommon(0)
  49. {
  50.   NewVarRef = 0;
  51.   
  52.   globalData.setBlock(blockNumber, this);
  53.   c_fragmentIdCounter = 1;
  54.   c_fragSenderRunning = false;
  55.   
  56.   Properties tmp;
  57.   const Properties * p = &tmp;
  58.   ndbrequire(p != 0);
  59.   Uint32 count = 10;
  60.   char buf[255];
  61.   count = 10;
  62.   BaseString::snprintf(buf, 255, "%s.FragmentSendPool", getBlockName(blockNumber));
  63.   if(!p->get(buf, &count))
  64.     p->get("FragmentSendPool", &count);
  65.   c_fragmentSendPool.setSize(count);
  66.   count = 10;
  67.   BaseString::snprintf(buf, 255, "%s.FragmentInfoPool", getBlockName(blockNumber));
  68.   if(!p->get(buf, &count))
  69.     p->get("FragmentInfoPool", &count);
  70.   c_fragmentInfoPool.setSize(count);
  71.   count = 10;
  72.   BaseString::snprintf(buf, 255, "%s.FragmentInfoHash", getBlockName(blockNumber));
  73.   if(!p->get(buf, &count))
  74.     p->get("FragmentInfoHash", &count);
  75.   c_fragmentInfoHash.setSize(count);
  76.   count = 5;
  77.   BaseString::snprintf(buf, 255, "%s.ActiveMutexes", getBlockName(blockNumber));
  78.   if(!p->get(buf, &count))
  79.     p->get("ActiveMutexes", &count);
  80.   c_mutexMgr.setSize(count);
  81.   
  82.   c_counterMgr.setSize(5);
  83.   
  84. #ifdef VM_TRACE_TIME
  85.   clearTimes();
  86. #endif
  87.   for(GlobalSignalNumber i = 0; i<=MAX_GSN; i++)
  88.     theExecArray[i] = 0;
  89.   installSimulatedBlockFunctions();
  90.   UpgradeStartup::installEXEC(this);
  91.   CLEAR_ERROR_INSERT_VALUE;
  92. #ifdef VM_TRACE
  93.   m_global_variables = new Ptr<void> * [1];
  94.   m_global_variables[0] = 0;
  95. #endif
  96. }
  97. SimulatedBlock::~SimulatedBlock()
  98. {
  99.   freeBat();
  100. #ifdef VM_TRACE_TIME
  101.   printTimes(stdout);
  102. #endif
  103. #ifdef VM_TRACE
  104.   delete [] m_global_variables;
  105. #endif
  106. }
  107. void 
  108. SimulatedBlock::installSimulatedBlockFunctions(){
  109.   ExecFunction * a = theExecArray;
  110.   a[GSN_NODE_STATE_REP] = &SimulatedBlock::execNODE_STATE_REP;
  111.   a[GSN_CHANGE_NODE_STATE_REQ] = &SimulatedBlock::execCHANGE_NODE_STATE_REQ;
  112.   a[GSN_NDB_TAMPER] = &SimulatedBlock::execNDB_TAMPER;
  113.   a[GSN_SIGNAL_DROPPED_REP] = &SimulatedBlock::execSIGNAL_DROPPED_REP;
  114.   a[GSN_CONTINUE_FRAGMENTED]= &SimulatedBlock::execCONTINUE_FRAGMENTED;
  115.   a[GSN_UTIL_CREATE_LOCK_REF]   = &SimulatedBlock::execUTIL_CREATE_LOCK_REF;
  116.   a[GSN_UTIL_CREATE_LOCK_CONF]  = &SimulatedBlock::execUTIL_CREATE_LOCK_CONF;
  117.   a[GSN_UTIL_DESTROY_LOCK_REF]  = &SimulatedBlock::execUTIL_DESTORY_LOCK_REF;
  118.   a[GSN_UTIL_DESTROY_LOCK_CONF] = &SimulatedBlock::execUTIL_DESTORY_LOCK_CONF;
  119.   a[GSN_UTIL_LOCK_REF]    = &SimulatedBlock::execUTIL_LOCK_REF;
  120.   a[GSN_UTIL_LOCK_CONF]   = &SimulatedBlock::execUTIL_LOCK_CONF;
  121.   a[GSN_UTIL_UNLOCK_REF]  = &SimulatedBlock::execUTIL_UNLOCK_REF;
  122.   a[GSN_UTIL_UNLOCK_CONF] = &SimulatedBlock::execUTIL_UNLOCK_CONF;
  123.   a[GSN_READ_CONFIG_REQ] = &SimulatedBlock::execREAD_CONFIG_REQ;
  124.   a[GSN_FSOPENREF]    = &SimulatedBlock::execFSOPENREF;
  125.   a[GSN_FSCLOSEREF]   = &SimulatedBlock::execFSCLOSEREF;
  126.   a[GSN_FSWRITEREF]   = &SimulatedBlock::execFSWRITEREF;
  127.   a[GSN_FSREADREF]    = &SimulatedBlock::execFSREADREF;
  128.   a[GSN_FSREMOVEREF]  = &SimulatedBlock::execFSREMOVEREF;
  129.   a[GSN_FSSYNCREF]    = &SimulatedBlock::execFSSYNCREF;
  130.   a[GSN_FSAPPENDREF]  = &SimulatedBlock::execFSAPPENDREF;
  131. }
  132. void
  133. SimulatedBlock::addRecSignalImpl(GlobalSignalNumber gsn, 
  134.  ExecFunction f, bool force){
  135.   if(gsn > MAX_GSN || (!force &&  theExecArray[gsn] != 0)){
  136.     char errorMsg[255];
  137.     BaseString::snprintf(errorMsg, 255, 
  138.        "Illeagal signal (%d %d)", gsn, MAX_GSN); 
  139.     ERROR_SET(fatal, ERR_ERROR_PRGERR, errorMsg, errorMsg);
  140.   }
  141.   theExecArray[gsn] = f;
  142. }
  143. void
  144. SimulatedBlock::signal_error(Uint32 gsn, Uint32 len, Uint32 recBlockNo, 
  145.      const char* filename, int lineno) const 
  146. {
  147.   char objRef[255];
  148.   BaseString::snprintf(objRef, 255, "%s:%d", filename, lineno);
  149.   char probData[255];
  150.   BaseString::snprintf(probData, 255, 
  151.    "Signal (GSN: %d, Length: %d, Rec Block No: %d)", 
  152.    gsn, len, recBlockNo);
  153.   
  154.   ErrorReporter::handleError(ecError, 
  155.      BLOCK_ERROR_BNR_ZERO,
  156.      probData, 
  157.      objRef);
  158. }
  159. extern class SectionSegmentPool g_sectionSegmentPool;
  160. void 
  161. SimulatedBlock::sendSignal(BlockReference ref, 
  162.    GlobalSignalNumber gsn, 
  163.    Signal* signal, 
  164.    Uint32 length, 
  165.    JobBufferLevel jobBuffer) const {
  166.   BlockNumber sendBnr = number();
  167.   BlockReference sendBRef = reference();
  168.   
  169.   Uint32 noOfSections = signal->header.m_noOfSections;
  170.   Uint32 recBlock = refToBlock(ref);
  171.   Uint32 recNode   = refToNode(ref);
  172.   Uint32 ourProcessor         = globalData.ownId;
  173.   
  174.   signal->header.theLength = length;
  175.   signal->header.theVerId_signalNumber = gsn;
  176.   signal->header.theReceiversBlockNumber = recBlock;
  177.   
  178.   Uint32 tSignalId = signal->header.theSignalId;
  179.   
  180.   if ((length == 0) || (length + noOfSections > 25) || (recBlock == 0)) {
  181.     signal_error(gsn, length, recBlock, __FILE__, __LINE__);
  182.     return;
  183.   }//if
  184. #ifdef VM_TRACE
  185.   if(globalData.testOn){
  186.     Uint16 proc = 
  187.       (recNode == 0 ? globalData.ownId : recNode);
  188.     signal->header.theSendersBlockRef = sendBRef;
  189.     globalSignalLoggers.sendSignal(signal->header, 
  190.    jobBuffer, 
  191.    &signal->theData[0],
  192.    proc,
  193.                                    signal->m_sectionPtr,
  194.                                    signal->header.m_noOfSections);
  195.   }
  196. #endif
  197.   
  198.   if(recNode == ourProcessor || recNode == 0) {
  199.     signal->header.theSendersSignalId = tSignalId;
  200.     signal->header.theSendersBlockRef = sendBRef;
  201.     signal->header.theLength = length;
  202.     globalScheduler.execute(signal, jobBuffer, recBlock,
  203.     gsn);
  204.     signal->header.m_noOfSections = 0;
  205.     signal->header.m_fragmentInfo = 0;
  206.     return;
  207.   } else { 
  208.     // send distributed Signal
  209.     SignalHeader sh;
  210.     Uint32 tTrace = signal->getTrace();
  211.     
  212.     sh.theVerId_signalNumber   = gsn;
  213.     sh.theReceiversBlockNumber = recBlock;
  214.     sh.theSendersBlockRef      = sendBnr;
  215.     sh.theLength               = length;
  216.     sh.theTrace                = tTrace;
  217.     sh.theSignalId             = tSignalId;
  218.     sh.m_noOfSections          = noOfSections;
  219.     sh.m_fragmentInfo          = 0;
  220.     
  221. #ifdef TRACE_DISTRIBUTED
  222.     ndbout_c("send: %s(%d) to (%s, %d)",
  223.      getSignalName(gsn), gsn, getBlockName(recBlock),
  224.      recNode);
  225. #endif
  226.     SendStatus ss = globalTransporterRegistry.prepareSend(&sh, jobBuffer, 
  227.   &signal->theData[0],
  228.   recNode, 
  229.   g_sectionSegmentPool,
  230.   signal->m_sectionPtr);
  231.     
  232.     ndbrequire(ss == SEND_OK || ss == SEND_BLOCKED || ss == SEND_DISCONNECTED);
  233.     ::releaseSections(noOfSections, signal->m_sectionPtr);
  234.     signal->header.m_noOfSections = 0;   
  235.   }
  236.   return;
  237. }
  238. void 
  239. SimulatedBlock::sendSignal(NodeReceiverGroup rg, 
  240.    GlobalSignalNumber gsn, 
  241.    Signal* signal, 
  242.    Uint32 length, 
  243.    JobBufferLevel jobBuffer) const {
  244.   Uint32 noOfSections = signal->header.m_noOfSections;
  245.   Uint32 tSignalId = signal->header.theSignalId;
  246.   Uint32 tTrace = signal->getTrace();
  247.   Uint32 tFragInf = signal->header.m_fragmentInfo;
  248.   
  249.   Uint32 ourProcessor = globalData.ownId;
  250.   Uint32 recBlock = rg.m_block;
  251.   
  252.   signal->header.theLength = length;
  253.   signal->header.theVerId_signalNumber = gsn;
  254.   signal->header.theReceiversBlockNumber = recBlock;
  255.   signal->header.theSendersSignalId = tSignalId;
  256.   signal->header.theSendersBlockRef = reference();
  257.   
  258.   if ((length == 0) || (length + noOfSections > 25) || (recBlock == 0)) {
  259.     signal_error(gsn, length, recBlock, __FILE__, __LINE__);
  260.     return;
  261.   }//if
  262.   SignalHeader sh;
  263.   
  264.   sh.theVerId_signalNumber   = gsn;
  265.   sh.theReceiversBlockNumber = recBlock;
  266.   sh.theSendersBlockRef      = number();
  267.   sh.theLength               = length;
  268.   sh.theTrace                = tTrace;
  269.   sh.theSignalId             = tSignalId;
  270.   sh.m_noOfSections          = noOfSections;
  271.   sh.m_fragmentInfo          = tFragInf;
  272.   /**
  273.    * Check own node
  274.    */
  275.   bool release = true;
  276.   if(rg.m_nodes.get(0) || rg.m_nodes.get(ourProcessor)){
  277. #ifdef VM_TRACE
  278.     if(globalData.testOn){
  279.       globalSignalLoggers.sendSignal(signal->header, 
  280.      jobBuffer, 
  281.      &signal->theData[0],
  282.      ourProcessor,
  283.                                      signal->m_sectionPtr,
  284.                                      signal->header.m_noOfSections);
  285.     }
  286. #endif
  287.     globalScheduler.execute(signal, jobBuffer, recBlock, gsn);
  288.     
  289.     rg.m_nodes.clear((Uint32)0);
  290.     rg.m_nodes.clear(ourProcessor);
  291.     release = false;
  292.   }
  293.   /**
  294.    * Do the big loop
  295.    */
  296.   Uint32 recNode = 0;
  297.   while(!rg.m_nodes.isclear()){
  298.     recNode = rg.m_nodes.find(recNode + 1);
  299.     rg.m_nodes.clear(recNode);
  300. #ifdef VM_TRACE
  301.     if(globalData.testOn){
  302.       globalSignalLoggers.sendSignal(signal->header, 
  303.      jobBuffer, 
  304.      &signal->theData[0],
  305.      recNode,
  306.                                      signal->m_sectionPtr,
  307.                                      signal->header.m_noOfSections);
  308.     }
  309. #endif
  310. #ifdef TRACE_DISTRIBUTED
  311.     ndbout_c("send: %s(%d) to (%s, %d)",
  312.      getSignalName(gsn), gsn, getBlockName(recBlock),
  313.      recNode);
  314. #endif
  315.     SendStatus ss = globalTransporterRegistry.prepareSend(&sh, jobBuffer, 
  316.   &signal->theData[0],
  317.   recNode,
  318.   g_sectionSegmentPool,
  319.   signal->m_sectionPtr);
  320.     ndbrequire(ss == SEND_OK || ss == SEND_BLOCKED || ss == SEND_DISCONNECTED);
  321.   }
  322.   
  323.   if(release){
  324.     ::releaseSections(noOfSections, signal->m_sectionPtr);
  325.   }
  326.   
  327.   signal->header.m_noOfSections = 0;
  328.   signal->header.m_fragmentInfo = 0;
  329.   
  330.   return;
  331. }
  332. bool import(Ptr<SectionSegment> & first, const Uint32 * src, Uint32 len);
  333. void 
  334. SimulatedBlock::sendSignal(BlockReference ref, 
  335.    GlobalSignalNumber gsn, 
  336.    Signal* signal, 
  337.    Uint32 length, 
  338.    JobBufferLevel jobBuffer,
  339.    LinearSectionPtr ptr[3],
  340.    Uint32 noOfSections) const {
  341.   
  342.   BlockNumber sendBnr = number();
  343.   BlockReference sendBRef = reference();
  344.   
  345.   Uint32 recBlock = refToBlock(ref);
  346.   Uint32 recNode   = refToNode(ref);
  347.   Uint32 ourProcessor         = globalData.ownId;
  348.   
  349.   ::releaseSections(signal->header.m_noOfSections, signal->m_sectionPtr);
  350.   
  351.   signal->header.theLength = length;
  352.   signal->header.theVerId_signalNumber = gsn;
  353.   signal->header.theReceiversBlockNumber = recBlock;
  354.   signal->header.m_noOfSections = noOfSections;
  355.   Uint32 tSignalId = signal->header.theSignalId;
  356.   Uint32 tFragInfo = signal->header.m_fragmentInfo;
  357.   
  358.   if ((length == 0) || (length + noOfSections > 25) || (recBlock == 0)) {
  359.     signal_error(gsn, length, recBlock, __FILE__, __LINE__);
  360.     return;
  361.   }//if
  362. #ifdef VM_TRACE
  363.   if(globalData.testOn){
  364.     Uint16 proc = 
  365.       (recNode == 0 ? globalData.ownId : recNode);
  366.     signal->header.theSendersBlockRef = sendBRef;
  367.     globalSignalLoggers.sendSignal(signal->header, 
  368.    jobBuffer, 
  369.    &signal->theData[0],
  370.    proc,
  371.                                    ptr, noOfSections);
  372.   }
  373. #endif
  374.   
  375.   if(recNode == ourProcessor || recNode == 0) {
  376.     signal->header.theSendersSignalId = tSignalId;
  377.     signal->header.theSendersBlockRef = sendBRef;
  378.     /**
  379.      * We have to copy the data
  380.      */
  381.     Ptr<SectionSegment> segptr[3];
  382.     for(Uint32 i = 0; i<noOfSections; i++){
  383.       ndbrequire(import(segptr[i], ptr[i].p, ptr[i].sz));
  384.       signal->m_sectionPtr[i].i = segptr[i].i;
  385.     }
  386.     
  387.     globalScheduler.execute(signal, jobBuffer, recBlock,
  388.     gsn);
  389.     signal->header.m_noOfSections = 0;
  390.     return;
  391.   } else { 
  392.     // send distributed Signal
  393.     SignalHeader sh;
  394.     Uint32 tTrace = signal->getTrace();
  395.     Uint32 noOfSections = signal->header.m_noOfSections;
  396.     
  397.     sh.theVerId_signalNumber   = gsn;
  398.     sh.theReceiversBlockNumber = recBlock;
  399.     sh.theSendersBlockRef      = sendBnr;
  400.     sh.theLength               = length;
  401.     sh.theTrace                = tTrace;
  402.     sh.theSignalId             = tSignalId;
  403.     sh.m_noOfSections          = noOfSections;
  404.     sh.m_fragmentInfo          = tFragInfo;
  405.     
  406. #ifdef TRACE_DISTRIBUTED
  407.     ndbout_c("send: %s(%d) to (%s, %d)",
  408.      getSignalName(gsn), gsn, getBlockName(recBlock),
  409.      recNode);
  410. #endif
  411.     SendStatus ss = globalTransporterRegistry.prepareSend(&sh, jobBuffer, 
  412.   &signal->theData[0],
  413.   recNode, 
  414.   ptr);
  415.     ndbrequire(ss == SEND_OK || ss == SEND_BLOCKED || ss == SEND_DISCONNECTED);
  416.   }
  417.   signal->header.m_noOfSections = 0;
  418.   signal->header.m_fragmentInfo = 0;
  419.   return;
  420. }
  421. void 
  422. SimulatedBlock::sendSignal(NodeReceiverGroup rg, 
  423.    GlobalSignalNumber gsn, 
  424.    Signal* signal, 
  425.    Uint32 length, 
  426.    JobBufferLevel jobBuffer,
  427.    LinearSectionPtr ptr[3],
  428.    Uint32 noOfSections) const {
  429.   
  430.   Uint32 tSignalId = signal->header.theSignalId;
  431.   Uint32 tTrace    = signal->getTrace();
  432.   Uint32 tFragInfo = signal->header.m_fragmentInfo;
  433.   
  434.   Uint32 ourProcessor = globalData.ownId;
  435.   Uint32 recBlock = rg.m_block;
  436.   
  437.   ::releaseSections(signal->header.m_noOfSections, signal->m_sectionPtr);
  438.   
  439.   signal->header.theLength = length;
  440.   signal->header.theVerId_signalNumber = gsn;
  441.   signal->header.theReceiversBlockNumber = recBlock;
  442.   signal->header.theSendersSignalId = tSignalId;
  443.   signal->header.theSendersBlockRef = reference();
  444.   signal->header.m_noOfSections = noOfSections;
  445.   
  446.   if ((length == 0) || (length + noOfSections > 25) || (recBlock == 0)) {
  447.     signal_error(gsn, length, recBlock, __FILE__, __LINE__);
  448.     return;
  449.   }//if
  450.   SignalHeader sh;
  451.   sh.theVerId_signalNumber   = gsn;
  452.   sh.theReceiversBlockNumber = recBlock;
  453.   sh.theSendersBlockRef      = number();
  454.   sh.theLength               = length;
  455.   sh.theTrace                = tTrace;
  456.   sh.theSignalId             = tSignalId;
  457.   sh.m_noOfSections          = noOfSections;
  458.   sh.m_fragmentInfo          = tFragInfo;
  459.   /**
  460.    * Check own node
  461.    */
  462.   if(rg.m_nodes.get(0) || rg.m_nodes.get(ourProcessor)){
  463. #ifdef VM_TRACE
  464.     if(globalData.testOn){
  465.       globalSignalLoggers.sendSignal(signal->header, 
  466.      jobBuffer, 
  467.      &signal->theData[0],
  468.      ourProcessor,
  469.                                      ptr, noOfSections);
  470.     }
  471. #endif
  472.     /**
  473.      * We have to copy the data
  474.      */
  475.     Ptr<SectionSegment> segptr[3];
  476.     for(Uint32 i = 0; i<noOfSections; i++){
  477.       ndbrequire(import(segptr[i], ptr[i].p, ptr[i].sz));
  478.       signal->m_sectionPtr[i].i = segptr[i].i;
  479.     }
  480.     globalScheduler.execute(signal, jobBuffer, recBlock, gsn);
  481.     
  482.     rg.m_nodes.clear((Uint32)0);
  483.     rg.m_nodes.clear(ourProcessor);
  484.   }
  485.   
  486.   /**
  487.    * Do the big loop
  488.    */
  489.   Uint32 recNode = 0;
  490.   while(!rg.m_nodes.isclear()){
  491.     recNode = rg.m_nodes.find(recNode + 1);
  492.     rg.m_nodes.clear(recNode);
  493.     
  494. #ifdef VM_TRACE
  495.     if(globalData.testOn){
  496.       globalSignalLoggers.sendSignal(signal->header, 
  497.      jobBuffer, 
  498.      &signal->theData[0],
  499.      recNode,
  500.                                      ptr, noOfSections);
  501.     }
  502. #endif
  503.     
  504. #ifdef TRACE_DISTRIBUTED
  505.     ndbout_c("send: %s(%d) to (%s, %d)",
  506.      getSignalName(gsn), gsn, getBlockName(recBlock),
  507.      recNode);
  508. #endif
  509.     SendStatus ss = globalTransporterRegistry.prepareSend(&sh, jobBuffer, 
  510.   &signal->theData[0],
  511.   recNode,
  512.   ptr);
  513.     ndbrequire(ss == SEND_OK || ss == SEND_BLOCKED || ss == SEND_DISCONNECTED);
  514.   }
  515.   
  516.   signal->header.m_noOfSections = 0;
  517.   signal->header.m_fragmentInfo = 0;
  518.   
  519.   return;
  520. }
  521. void
  522. SimulatedBlock::sendSignalWithDelay(BlockReference ref, 
  523.     GlobalSignalNumber gsn,
  524.     Signal* signal,
  525.     Uint32 delayInMilliSeconds, 
  526.     Uint32 length) const {
  527.   
  528.   BlockNumber bnr = refToBlock(ref);
  529.   
  530.   //BlockNumber sendBnr = number();
  531.   BlockReference sendBRef = reference();
  532.   
  533.   if (bnr == 0) {
  534.     bnr_error();
  535.   }//if
  536.   
  537.   signal->header.theLength = length;
  538.   signal->header.theSendersSignalId = signal->header.theSignalId;
  539.   signal->header.theSendersBlockRef = sendBRef;
  540.   signal->header.theVerId_signalNumber = gsn;
  541.   signal->header.theReceiversBlockNumber = bnr;
  542. #ifdef VM_TRACE
  543.   {
  544.     if(globalData.testOn){
  545.       globalSignalLoggers.sendSignalWithDelay(delayInMilliSeconds,
  546.       signal->header,
  547.       0,
  548.       &signal->theData[0], 
  549.       globalData.ownId,
  550.                                               signal->m_sectionPtr,
  551.                                               signal->header.m_noOfSections);
  552.     }
  553.   }
  554. #endif
  555.   globalTimeQueue.insert(signal, bnr, gsn, delayInMilliSeconds);
  556.   signal->header.m_noOfSections = 0;
  557.   signal->header.m_fragmentInfo = 0;
  558.   
  559.   // befor 2nd parameter to globalTimeQueue.insert
  560.   // (Priority)theSendSig[sigIndex].jobBuffer
  561. }
  562. void
  563. SimulatedBlock::releaseSections(Signal* signal){
  564.   ::releaseSections(signal->header.m_noOfSections, signal->m_sectionPtr);
  565.   signal->header.m_noOfSections = 0;
  566. }
  567. class SectionSegmentPool& 
  568. SimulatedBlock::getSectionSegmentPool(){
  569.   return g_sectionSegmentPool;
  570. }
  571. NewVARIABLE *
  572. SimulatedBlock::allocateBat(int batSize){
  573.   NewVARIABLE* bat = NewVarRef;
  574.   bat = (NewVARIABLE*)realloc(bat, batSize * sizeof(NewVARIABLE));
  575.   NewVarRef = bat;
  576.   theBATSize = batSize;
  577.   return bat;
  578. }
  579. void
  580. SimulatedBlock::freeBat(){
  581.   if(NewVarRef != 0){
  582.     free(NewVarRef);
  583.     NewVarRef = 0;
  584.   }
  585. }
  586. const NewVARIABLE *
  587. SimulatedBlock::getBat(Uint16 blockNo){
  588.   SimulatedBlock * sb = globalData.getBlock(blockNo);
  589.   if(sb == 0)
  590.     return 0;
  591.   return sb->NewVarRef;
  592. }
  593. Uint16
  594. SimulatedBlock::getBatSize(Uint16 blockNo){
  595.   SimulatedBlock * sb = globalData.getBlock(blockNo);
  596.   if(sb == 0)
  597.     return 0;
  598.   return sb->theBATSize;
  599. }
  600. void* 
  601. SimulatedBlock::allocRecord(const char * type, size_t s, size_t n, bool clear) 
  602. {
  603.   void * p = NULL;
  604.   size_t size = n*s;
  605.   refresh_watch_dog(); 
  606.   if (size > 0){
  607. #ifdef VM_TRACE_MEM
  608.     ndbout_c("%s::allocRecord(%s, %u, %u) = %u bytes", 
  609.      getBlockName(number()), 
  610.      type,
  611.      s,
  612.      n,
  613.      size);
  614. #endif
  615.     p = NdbMem_Allocate(size);
  616.     if (p == NULL){
  617.       char buf1[255];
  618.       char buf2[255];
  619.       BaseString::snprintf(buf1, sizeof(buf1), "%s could not allocate memory for %s", 
  620.        getBlockName(number()), type);
  621.       BaseString::snprintf(buf2, sizeof(buf2), "Requested: %ux%u = %u bytes", 
  622.        (Uint32)s, (Uint32)n, (Uint32)size);
  623.       ERROR_SET(fatal, ERR_MEMALLOC, buf1, buf2);
  624.     }
  625.     if(clear){
  626.       char * ptr = (char*)p;
  627.       const Uint32 chunk = 128 * 1024;
  628.       while(size > chunk){
  629. refresh_watch_dog(); 
  630. memset(ptr, 0, chunk);
  631. ptr += chunk;
  632. size -= chunk;
  633.       }
  634.       refresh_watch_dog(); 
  635.       memset(ptr, 0, size);
  636.     }
  637.   }
  638.   return p;
  639. }
  640. void 
  641. SimulatedBlock::deallocRecord(void ** ptr, 
  642.       const char * type, size_t s, size_t n){
  643.   (void)type;
  644.   (void)s;
  645.   (void)n;
  646.   if(* ptr != 0){
  647.     NdbMem_Free(* ptr);
  648.     * ptr = 0;
  649.   }
  650. }
  651. void
  652. SimulatedBlock::refresh_watch_dog()
  653. {
  654.   globalData.incrementWatchDogCounter(1);
  655. }
  656. void
  657. SimulatedBlock::progError(int line, int err_code, const char* extra) const {
  658.   jamLine(line);
  659.   const char *aBlockName = getBlockName(number(), "VM Kernel");
  660.   // Pack status of interesting config variables 
  661.   // so that we can print them in error.log
  662.   int magicStatus = 
  663.     (theConfiguration.stopOnError()<<1) + 
  664.     (theConfiguration.getInitialStart()<<2) + 
  665.     (theConfiguration.getDaemonMode()<<3);
  666.   
  667.   /* Add line number to block name */
  668.   char buf[100];
  669.   BaseString::snprintf(&buf[0], 100, "%s (Line: %d) 0x%.8x", 
  670.    aBlockName, line, magicStatus);
  671.   ErrorReporter::handleError(ecError, err_code, extra, buf);
  672. }
  673. void 
  674. SimulatedBlock::infoEvent(const char * msg, ...) const {
  675.   if(msg == 0)
  676.     return;
  677.   
  678.   Uint32 theData[25];
  679.   theData[0] = EventReport::InfoEvent;
  680.   char * buf = (char *)&(theData[1]);
  681.   
  682.   va_list ap;
  683.   va_start(ap, msg);
  684.   BaseString::vsnprintf(buf, 96, msg, ap); // 96 = 100 - 4
  685.   va_end(ap);
  686.   
  687.   int len = strlen(buf) + 1;
  688.   if(len > 96){
  689.     len = 96;
  690.     buf[95] = 0;
  691.   }
  692.   /**
  693.    * Init and put it into the job buffer
  694.    */
  695.   SignalHeader sh;
  696.   memset(&sh, 0, sizeof(SignalHeader));
  697.   
  698.   const Signal * signal = globalScheduler.getVMSignals();
  699.   Uint32 tTrace = signal->header.theTrace;
  700.   Uint32 tSignalId = signal->header.theSignalId;
  701.   
  702.   sh.theVerId_signalNumber   = GSN_EVENT_REP;
  703.   sh.theReceiversBlockNumber = CMVMI;
  704.   sh.theSendersBlockRef      = reference();
  705.   sh.theTrace                = tTrace;
  706.   sh.theSignalId             = tSignalId;
  707.   sh.theLength               = ((len+3)/4)+1;
  708.   
  709.   Uint32 secPtrI[3]; // Dummy
  710.   globalScheduler.execute(&sh, JBB, theData, secPtrI);
  711. }
  712. void 
  713. SimulatedBlock::warningEvent(const char * msg, ...) const {
  714.   if(msg == 0)
  715.     return;
  716.   
  717.   Uint32 theData[25];
  718.   theData[0] = EventReport::WarningEvent;
  719.   char * buf = (char *)&(theData[1]);
  720.   
  721.   va_list ap;
  722.   va_start(ap, msg);
  723.   BaseString::vsnprintf(buf, 96, msg, ap); // 96 = 100 - 4
  724.   va_end(ap);
  725.   
  726.   int len = strlen(buf) + 1;
  727.   if(len > 96){
  728.     len = 96;
  729.     buf[95] = 0;
  730.   }
  731.   /**
  732.    * Init and put it into the job buffer
  733.    */
  734.   SignalHeader sh;
  735.   memset(&sh, 0, sizeof(SignalHeader));
  736.   
  737.   const Signal * signal = globalScheduler.getVMSignals();
  738.   Uint32 tTrace = signal->header.theTrace;
  739.   Uint32 tSignalId = signal->header.theSignalId;
  740.   
  741.   sh.theVerId_signalNumber   = GSN_EVENT_REP;
  742.   sh.theReceiversBlockNumber = CMVMI;
  743.   sh.theSendersBlockRef      = reference();
  744.   sh.theTrace                = tTrace;
  745.   sh.theSignalId             = tSignalId;
  746.   sh.theLength               = ((len+3)/4)+1;
  747.   Uint32 secPtrI[3]; // Dummy
  748.   globalScheduler.execute(&sh, JBB, theData, secPtrI);
  749. }
  750. void
  751. SimulatedBlock::execNODE_STATE_REP(Signal* signal){
  752.   const NodeStateRep * const  rep = (NodeStateRep *)&signal->theData[0];
  753.   
  754.   this->theNodeState = rep->nodeState;
  755. }
  756. void
  757. SimulatedBlock::execCHANGE_NODE_STATE_REQ(Signal* signal){
  758.   const ChangeNodeStateReq * const  req = 
  759.     (ChangeNodeStateReq *)&signal->theData[0];
  760.   
  761.   this->theNodeState = req->nodeState;
  762.   const Uint32 senderData = req->senderData;
  763.   const BlockReference senderRef = req->senderRef;
  764.   /**
  765.    * Pack return signal
  766.    */
  767.   ChangeNodeStateConf * const  conf = 
  768.     (ChangeNodeStateConf *)&signal->theData[0];
  769.   
  770.   conf->senderData = senderData;
  771.   sendSignal(senderRef, GSN_CHANGE_NODE_STATE_CONF, signal, 
  772.      ChangeNodeStateConf::SignalLength, JBB);
  773. }
  774. void
  775. SimulatedBlock::execNDB_TAMPER(Signal * signal){
  776.   SET_ERROR_INSERT_VALUE(signal->theData[0]);
  777. }
  778. void
  779. SimulatedBlock::execSIGNAL_DROPPED_REP(Signal * signal){
  780.   ErrorReporter::handleError(ecError,
  781.      ERR_OUT_OF_LONG_SIGNAL_MEMORY,
  782.      "Signal lost, out of long signal memory",
  783.      __FILE__,
  784.      NST_ErrorHandler);
  785. }
  786. void
  787. SimulatedBlock::execCONTINUE_FRAGMENTED(Signal * signal){
  788.   ljamEntry();
  789.   
  790.   Ptr<FragmentSendInfo> fragPtr;
  791.   
  792.   c_segmentedFragmentSendList.first(fragPtr);  
  793.   for(; !fragPtr.isNull();){
  794.     ljam();
  795.     Ptr<FragmentSendInfo> copyPtr = fragPtr;
  796.     c_segmentedFragmentSendList.next(fragPtr);
  797.     
  798.     sendNextSegmentedFragment(signal, * copyPtr.p);
  799.     if(copyPtr.p->m_status == FragmentSendInfo::SendComplete){
  800.       ljam();
  801.       if(copyPtr.p->m_callback.m_callbackFunction != 0) {
  802.         ljam();
  803. execute(signal, copyPtr.p->m_callback, 0);
  804.       }//if
  805.       c_segmentedFragmentSendList.release(copyPtr);
  806.     }
  807.   }
  808.   
  809.   c_linearFragmentSendList.first(fragPtr);  
  810.   for(; !fragPtr.isNull();){
  811.     ljam(); 
  812.     Ptr<FragmentSendInfo> copyPtr = fragPtr;
  813.     c_linearFragmentSendList.next(fragPtr);
  814.     
  815.     sendNextLinearFragment(signal, * copyPtr.p);
  816.     if(copyPtr.p->m_status == FragmentSendInfo::SendComplete){
  817.       ljam();
  818.       if(copyPtr.p->m_callback.m_callbackFunction != 0) {
  819.         ljam();
  820. execute(signal, copyPtr.p->m_callback, 0);
  821.       }//if
  822.       c_linearFragmentSendList.release(copyPtr);
  823.     }
  824.   }
  825.   
  826.   if(c_segmentedFragmentSendList.isEmpty() && 
  827.      c_linearFragmentSendList.isEmpty()){
  828.     ljam();
  829.     c_fragSenderRunning = false;
  830.     return;
  831.   }
  832.   
  833.   ContinueFragmented * sig = (ContinueFragmented*)signal->getDataPtrSend();
  834.   sig->line = __LINE__;
  835.   sendSignal(reference(), GSN_CONTINUE_FRAGMENTED, signal, 1, JBB);
  836. }
  837. #ifdef VM_TRACE_TIME
  838. void
  839. SimulatedBlock::clearTimes() {
  840.   for(Uint32 i = 0; i <= MAX_GSN; i++){
  841.     m_timeTrace[i].cnt = 0;
  842.     m_timeTrace[i].sum = 0;
  843.     m_timeTrace[i].sub = 0;
  844.   }
  845. }
  846. void
  847. SimulatedBlock::printTimes(FILE * output){
  848.   fprintf(output, "-- %s --n", getBlockName(number()));
  849.   Uint64 sum = 0;
  850.   for(Uint32 i = 0; i <= MAX_GSN; i++){
  851.     Uint32 n = m_timeTrace[i].cnt;
  852.     if(n != 0){
  853.       double dn = n;
  854.       
  855.       double avg = m_timeTrace[i].sum;
  856.       double avg2 = avg - m_timeTrace[i].sub;
  857.       
  858.       avg /= dn;
  859.       avg2 /= dn;
  860.       
  861.       fprintf(output, 
  862.       //name ; cnt ; loc ; acc
  863.       "%s ; #%d ; %dus ; %dus ; %dmsn",
  864.       getSignalName(i), n, (Uint32)avg, (Uint32)avg2, 
  865.       (Uint32)((m_timeTrace[i].sum - m_timeTrace[i].sub + 500)/ 1000));
  866.       
  867.       sum += (m_timeTrace[i].sum - m_timeTrace[i].sub);
  868.     }
  869.   }
  870.   sum = (sum + 500)/ 1000;
  871.   fprintf(output, "-- %s : %d --n", getBlockName(number()), sum);
  872.   fprintf(output, "n");
  873.   fflush(output);
  874. }
  875. #endif
  876. void release(SegmentedSectionPtr & ptr);
  877. SimulatedBlock::FragmentInfo::FragmentInfo(Uint32 fragId, Uint32 sender){
  878.   m_fragmentId = fragId;
  879.   m_senderRef = sender;
  880.   m_sectionPtrI[0] = RNIL; 
  881.   m_sectionPtrI[1] = RNIL;
  882.   m_sectionPtrI[2] = RNIL;
  883. }
  884. SimulatedBlock::FragmentSendInfo::FragmentSendInfo()
  885. {
  886. }
  887. bool
  888. SimulatedBlock::assembleFragments(Signal * signal){
  889.   Uint32 sigLen = signal->length() - 1;
  890.   Uint32 fragId = signal->theData[sigLen];
  891.   Uint32 fragInfo = signal->header.m_fragmentInfo;
  892.   Uint32 senderRef = signal->getSendersBlockRef();
  893.   
  894.   if(fragInfo == 0){
  895.     return true;
  896.   }
  897.   
  898.   const Uint32 secs = signal->header.m_noOfSections;
  899.   const Uint32 * const secNos = &signal->theData[sigLen - secs];
  900.   
  901.   if(fragInfo == 1){
  902.     /**
  903.      * First in train
  904.      */
  905.     Ptr<FragmentInfo> fragPtr;
  906.     if(!c_fragmentInfoHash.seize(fragPtr)){
  907.       ndbrequire(false);
  908.       return false;
  909.     }
  910.     
  911.     new (fragPtr.p)FragmentInfo(fragId, senderRef);
  912.     c_fragmentInfoHash.add(fragPtr);
  913.     
  914.     for(Uint32 i = 0; i<secs; i++){
  915.       Uint32 sectionNo = secNos[i];
  916.       ndbassert(sectionNo < 3);
  917.       fragPtr.p->m_sectionPtrI[sectionNo] = signal->m_sectionPtr[i].i;
  918.     }
  919.     
  920.     /**
  921.      * Don't release allocated segments
  922.      */
  923.     signal->header.m_noOfSections = 0;
  924.     return false;
  925.   }
  926.   
  927.   FragmentInfo key(fragId, senderRef);
  928.   Ptr<FragmentInfo> fragPtr;
  929.   if(c_fragmentInfoHash.find(fragPtr, key)){
  930.     
  931.     /**
  932.      * FragInfo == 2 or 3
  933.      */
  934.     Uint32 i;
  935.     for(i = 0; i<secs; i++){
  936.       Uint32 sectionNo = secNos[i];
  937.       ndbassert(sectionNo < 3);
  938.       Uint32 sectionPtrI = signal->m_sectionPtr[i].i;
  939.       if(fragPtr.p->m_sectionPtrI[sectionNo] != RNIL){
  940. linkSegments(fragPtr.p->m_sectionPtrI[sectionNo], sectionPtrI);
  941.       } else {
  942. fragPtr.p->m_sectionPtrI[sectionNo] = sectionPtrI;
  943.       }
  944.     }
  945.     
  946.     /**
  947.      * fragInfo = 2
  948.      */
  949.     if(fragInfo == 2){
  950.       signal->header.m_noOfSections = 0;
  951.       return false;
  952.     }
  953.     
  954.     /**
  955.      * fragInfo = 3
  956.      */
  957.     for(i = 0; i<3; i++){
  958.       Uint32 ptrI = fragPtr.p->m_sectionPtrI[i];
  959.       if(ptrI != RNIL){
  960. signal->m_sectionPtr[i].i = ptrI;
  961.       } else {
  962. break;
  963.       }
  964.     }
  965.     signal->setLength(sigLen - i);
  966.     signal->header.m_noOfSections = i;
  967.     signal->header.m_fragmentInfo = 0;
  968.     getSections(i, signal->m_sectionPtr);
  969.     
  970.     c_fragmentInfoHash.release(fragPtr);
  971.     return true;
  972.   }
  973.   
  974.   /**
  975.    * Unable to find fragment
  976.    */
  977.   ndbrequire(false);
  978.   return false;
  979. }
  980. bool
  981. SimulatedBlock::sendFirstFragment(FragmentSendInfo & info,
  982.   NodeReceiverGroup rg, 
  983.   GlobalSignalNumber gsn, 
  984.   Signal* signal, 
  985.   Uint32 length, 
  986.   JobBufferLevel jbuf,
  987.   Uint32 messageSize){
  988.   
  989.   info.m_sectionPtr[0].m_segmented.i = RNIL;
  990.   info.m_sectionPtr[1].m_segmented.i = RNIL;
  991.   info.m_sectionPtr[2].m_segmented.i = RNIL;
  992.   
  993.   Uint32 totalSize = 0;
  994.   SectionSegment * p;
  995.   switch(signal->header.m_noOfSections){
  996.   case 3:
  997.     p = signal->m_sectionPtr[2].p;  
  998.     info.m_sectionPtr[2].m_segmented.p = p;
  999.     info.m_sectionPtr[2].m_segmented.i = signal->m_sectionPtr[2].i;
  1000.     totalSize += p->m_sz;
  1001.   case 2:
  1002.     p = signal->m_sectionPtr[1].p;  
  1003.     info.m_sectionPtr[1].m_segmented.p = p;
  1004.     info.m_sectionPtr[1].m_segmented.i = signal->m_sectionPtr[1].i;
  1005.     totalSize += p->m_sz;
  1006.   case 1:
  1007.     p = signal->m_sectionPtr[0].p;  
  1008.     info.m_sectionPtr[0].m_segmented.p = p;
  1009.     info.m_sectionPtr[0].m_segmented.i = signal->m_sectionPtr[0].i;
  1010.     totalSize += p->m_sz;
  1011.   }
  1012.   if(totalSize <= messageSize + SectionSegment::DataLength){
  1013.     /**
  1014.      * Send signal directly
  1015.      */
  1016.     sendSignal(rg, gsn, signal, length, jbuf);
  1017.     info.m_status = FragmentSendInfo::SendComplete;
  1018.     return true;
  1019.   }
  1020.   /**
  1021.    * Consume sections
  1022.    */
  1023.   signal->header.m_noOfSections = 0;
  1024.     
  1025.   /**
  1026.    * Setup info object
  1027.    */
  1028.   info.m_status = FragmentSendInfo::SendNotComplete;
  1029.   info.m_prio = (Uint8)jbuf;
  1030.   info.m_gsn = gsn;
  1031.   info.m_fragInfo = 1;
  1032.   info.m_messageSize = messageSize;
  1033.   info.m_fragmentId = c_fragmentIdCounter++;
  1034.   info.m_nodeReceiverGroup = rg;
  1035.   info.m_callback.m_callbackFunction = 0;
  1036.   
  1037.   Ptr<SectionSegment> tmp;
  1038.   if(!import(tmp, &signal->theData[0], length)){
  1039.     ndbrequire(false);
  1040.     return false;
  1041.   }
  1042.   info.m_theDataSection.p = &tmp.p->theData[0];
  1043.   info.m_theDataSection.sz = length;
  1044.   tmp.p->theData[length] = tmp.i;
  1045.   
  1046.   sendNextSegmentedFragment(signal, info);
  1047.   
  1048.   if(c_fragmentIdCounter == 0){
  1049.     /**
  1050.      * Fragment id 0 is invalid
  1051.      */
  1052.     c_fragmentIdCounter = 1;
  1053.   }
  1054.   return true;
  1055. }
  1056. #if 0
  1057. #define lsout(x) x
  1058. #else
  1059. #define lsout(x)
  1060. #endif
  1061. void
  1062. SimulatedBlock::sendNextSegmentedFragment(Signal* signal,
  1063.   FragmentSendInfo & info){
  1064.   
  1065.   /**
  1066.    * Store "theData"
  1067.    */
  1068.   const Uint32 sigLen = info.m_theDataSection.sz;
  1069.   memcpy(&signal->theData[0], info.m_theDataSection.p, 4 * sigLen);
  1070.   
  1071.   Uint32 sz = 0; 
  1072.   Uint32 maxSz = info.m_messageSize;
  1073.   
  1074.   Int32 secNo = 2;
  1075.   Uint32 secCount = 0;
  1076.   Uint32 * secNos = &signal->theData[sigLen];
  1077.   
  1078.   enum { Unknown = 0, Full = 1 } loop = Unknown;
  1079.   for(; secNo >= 0 && secCount < 3; secNo--){
  1080.     Uint32 ptrI = info.m_sectionPtr[secNo].m_segmented.i;
  1081.     if(ptrI == RNIL)
  1082.       continue;
  1083.     
  1084.     info.m_sectionPtr[secNo].m_segmented.i = RNIL;
  1085.     
  1086.     SectionSegment * ptrP = info.m_sectionPtr[secNo].m_segmented.p;
  1087.     const Uint32 size = ptrP->m_sz;
  1088.     
  1089.     signal->m_sectionPtr[secCount].i = ptrI;
  1090.     signal->m_sectionPtr[secCount].p = ptrP;
  1091.     signal->m_sectionPtr[secCount].sz = size;
  1092.     secNos[secCount] = secNo;
  1093.     secCount++;
  1094.     
  1095.     const Uint32 sizeLeft = maxSz - sz;
  1096.     if(size <= sizeLeft){
  1097.       /**
  1098.        * The section fits
  1099.        */
  1100.       sz += size;
  1101.       lsout(ndbout_c("section %d saved as %d", secNo, secCount-1));
  1102.       continue;
  1103.     }
  1104.     
  1105.     const Uint32 overflow = size - sizeLeft; // > 0
  1106.     if(overflow <= SectionSegment::DataLength){
  1107.       /**
  1108.        * Only one segment left to send
  1109.        *   send even if sizeLeft <= size
  1110.        */
  1111.       lsout(ndbout_c("section %d saved as %d but full over: %d", 
  1112.      secNo, secCount-1, overflow));
  1113.       secNo--;
  1114.       break;
  1115.     }
  1116.     // size >= 61
  1117.     if(sizeLeft < SectionSegment::DataLength){
  1118.       /**
  1119.        * Less than one segment left (space)
  1120.        *   dont bother sending
  1121.        */
  1122.       secCount--;
  1123.       info.m_sectionPtr[secNo].m_segmented.i = ptrI;
  1124.       loop = Full;
  1125.       lsout(ndbout_c("section %d not saved", secNo));
  1126.       break;
  1127.     }
  1128.     
  1129.     /**
  1130.      * Split list
  1131.      * 1) Find place to split
  1132.      * 2) Rewrite header (the part that will be sent)
  1133.      * 3) Write new header (for remaining part)
  1134.      * 4) Store new header on FragmentSendInfo - record
  1135.      */
  1136.     // size >= 61 && sizeLeft >= 60
  1137.     Uint32 sum = SectionSegment::DataLength;
  1138.     Uint32 prevPtrI = ptrI;
  1139.     ptrI = ptrP->m_nextSegment;
  1140.     const Uint32 fill = sizeLeft - SectionSegment::DataLength;
  1141.     while(sum < fill){
  1142.       prevPtrI = ptrI;
  1143.       ptrP = g_sectionSegmentPool.getPtr(ptrI);
  1144.       ptrI = ptrP->m_nextSegment;
  1145.       sum += SectionSegment::DataLength;
  1146.     }
  1147.     
  1148.     /**
  1149.      * Rewrite header w.r.t size and last
  1150.      */
  1151.     Uint32 prev = secCount - 1;
  1152.     const Uint32 last = signal->m_sectionPtr[prev].p->m_lastSegment;
  1153.     signal->m_sectionPtr[prev].p->m_lastSegment = prevPtrI;
  1154.     signal->m_sectionPtr[prev].p->m_sz = sum;
  1155.     signal->m_sectionPtr[prev].sz = sum;
  1156.       
  1157.     /**
  1158.      * Write "new" list header
  1159.      */
  1160.     ptrP = g_sectionSegmentPool.getPtr(ptrI);
  1161.     ptrP->m_lastSegment = last;
  1162.     ptrP->m_sz = size - sum;
  1163.     
  1164.     /**
  1165.      * And store it on info-record
  1166.      */
  1167.     info.m_sectionPtr[secNo].m_segmented.i = ptrI;
  1168.     info.m_sectionPtr[secNo].m_segmented.p = ptrP;
  1169.     
  1170.     loop = Full;
  1171.     lsout(ndbout_c("section %d split into %d", secNo, prev));
  1172.     break;
  1173.   }
  1174.   
  1175.   lsout(ndbout_c("loop: %d secNo: %d secCount: %d sz: %d", 
  1176.  loop, secNo, secCount, sz));
  1177.   
  1178.   /**
  1179.    * Store fragment id
  1180.    */
  1181.   secNos[secCount] = info.m_fragmentId;
  1182.   
  1183.   Uint32 fragInfo = info.m_fragInfo;
  1184.   info.m_fragInfo = 2;
  1185.   switch(loop){
  1186.   case Unknown:
  1187.     if(secNo >= 0){
  1188.       lsout(ndbout_c("Unknown - Full"));
  1189.       /**
  1190.        * Not finished
  1191.        */
  1192.       break;
  1193.     }
  1194.     // Fall through
  1195.     lsout(ndbout_c("Unknown - Done"));
  1196.     info.m_status = FragmentSendInfo::SendComplete;
  1197.     ndbassert(fragInfo == 2);
  1198.     fragInfo = 3;
  1199.   case Full:
  1200.     break;
  1201.   }
  1202.   
  1203.   signal->header.m_fragmentInfo = fragInfo;
  1204.   signal->header.m_noOfSections = secCount;
  1205.   
  1206.   sendSignal(info.m_nodeReceiverGroup,
  1207.      info.m_gsn,
  1208.      signal, 
  1209.      sigLen + secCount + 1,
  1210.      (JobBufferLevel)info.m_prio);
  1211.   
  1212.   if(fragInfo == 3){
  1213.     /**
  1214.      * This is the last signal
  1215.      */
  1216.     g_sectionSegmentPool.release(info.m_theDataSection.p[sigLen]);
  1217.   }
  1218. }
  1219. bool
  1220. SimulatedBlock::sendFirstFragment(FragmentSendInfo & info,
  1221.   NodeReceiverGroup rg, 
  1222.   GlobalSignalNumber gsn, 
  1223.   Signal* signal, 
  1224.   Uint32 length, 
  1225.   JobBufferLevel jbuf,
  1226.   LinearSectionPtr ptr[3],
  1227.   Uint32 noOfSections,
  1228.   Uint32 messageSize){
  1229.   
  1230.   ::releaseSections(signal->header.m_noOfSections, signal->m_sectionPtr);
  1231.   signal->header.m_noOfSections = 0;
  1232.   
  1233.   info.m_sectionPtr[0].m_linear.p = NULL;
  1234.   info.m_sectionPtr[1].m_linear.p = NULL;
  1235.   info.m_sectionPtr[2].m_linear.p = NULL;
  1236.   
  1237.   Uint32 totalSize = 0;
  1238.   switch(noOfSections){
  1239.   case 3:
  1240.     info.m_sectionPtr[2].m_linear = ptr[2];
  1241.     totalSize += ptr[2].sz;
  1242.   case 2:
  1243.     info.m_sectionPtr[1].m_linear = ptr[1];
  1244.     totalSize += ptr[1].sz;
  1245.   case 1:
  1246.     info.m_sectionPtr[0].m_linear = ptr[0];
  1247.     totalSize += ptr[0].sz;
  1248.   }
  1249.   if(totalSize <= messageSize + SectionSegment::DataLength){
  1250.     /**
  1251.      * Send signal directly
  1252.      */
  1253.     sendSignal(rg, gsn, signal, length, jbuf, ptr, noOfSections);
  1254.     info.m_status = FragmentSendInfo::SendComplete;
  1255.     
  1256.     /**
  1257.      * Indicate to sendLinearSignalFragment
  1258.      *   that we'r already done
  1259.      */
  1260.     return true;
  1261.   }
  1262.   /**
  1263.    * Setup info object
  1264.    */
  1265.   info.m_status = FragmentSendInfo::SendNotComplete;
  1266.   info.m_prio = (Uint8)jbuf;
  1267.   info.m_gsn = gsn;
  1268.   info.m_messageSize = messageSize;
  1269.   info.m_fragInfo = 1;
  1270.   info.m_fragmentId = c_fragmentIdCounter++;
  1271.   info.m_nodeReceiverGroup = rg;
  1272.   info.m_callback.m_callbackFunction = 0;
  1273.   Ptr<SectionSegment> tmp;
  1274.   if(!import(tmp, &signal->theData[0], length)){
  1275.     ndbrequire(false);
  1276.     return false;
  1277.   }
  1278.   info.m_theDataSection.p = &tmp.p->theData[0];
  1279.   info.m_theDataSection.sz = length;
  1280.   tmp.p->theData[length] = tmp.i;
  1281.   
  1282.   sendNextLinearFragment(signal, info);
  1283.   if(c_fragmentIdCounter == 0){
  1284.     /**
  1285.      * Fragment id 0 is invalid
  1286.      */
  1287.     c_fragmentIdCounter = 1;
  1288.   }
  1289.   
  1290.   return true;
  1291. }
  1292. void
  1293. SimulatedBlock::sendNextLinearFragment(Signal* signal,
  1294.        FragmentSendInfo & info){
  1295.   
  1296.   /**
  1297.    * Store "theData"
  1298.    */
  1299.   const Uint32 sigLen = info.m_theDataSection.sz;
  1300.   memcpy(&signal->theData[0], info.m_theDataSection.p, 4 * sigLen);
  1301.   
  1302.   Uint32 sz = 0; 
  1303.   Uint32 maxSz = info.m_messageSize;
  1304.   
  1305.   Int32 secNo = 2;
  1306.   Uint32 secCount = 0;
  1307.   Uint32 * secNos = &signal->theData[sigLen];
  1308.   LinearSectionPtr signalPtr[3];
  1309.   
  1310.   enum { Unknown = 0, Full = 2 } loop = Unknown;
  1311.   for(; secNo >= 0 && secCount < 3; secNo--){
  1312.     Uint32 * ptrP = info.m_sectionPtr[secNo].m_linear.p;
  1313.     if(ptrP == NULL)
  1314.       continue;
  1315.     
  1316.     info.m_sectionPtr[secNo].m_linear.p = NULL;
  1317.     const Uint32 size = info.m_sectionPtr[secNo].m_linear.sz;
  1318.     
  1319.     signalPtr[secCount].p = ptrP;
  1320.     signalPtr[secCount].sz = size;
  1321.     secNos[secCount] = secNo;
  1322.     secCount++;
  1323.     
  1324.     const Uint32 sizeLeft = maxSz - sz;
  1325.     if(size <= sizeLeft){
  1326.       /**
  1327.        * The section fits
  1328.        */
  1329.       sz += size;
  1330.       lsout(ndbout_c("section %d saved as %d", secNo, secCount-1));
  1331.       continue;
  1332.     }
  1333.     
  1334.     const Uint32 overflow = size - sizeLeft; // > 0
  1335.     if(overflow <= SectionSegment::DataLength){
  1336.       /**
  1337.        * Only one segment left to send
  1338.        *   send even if sizeLeft <= size
  1339.        */
  1340.       lsout(ndbout_c("section %d saved as %d but full over: %d", 
  1341.      secNo, secCount-1, overflow));
  1342.       secNo--;
  1343.       break;
  1344.     }
  1345.     // size >= 61
  1346.     if(sizeLeft < SectionSegment::DataLength){
  1347.       /**
  1348.        * Less than one segment left (space)
  1349.        *   dont bother sending
  1350.        */
  1351.       secCount--;
  1352.       info.m_sectionPtr[secNo].m_linear.p = ptrP;
  1353.       loop = Full;
  1354.       lsout(ndbout_c("section %d not saved", secNo));
  1355.       break;
  1356.     }
  1357.     
  1358.     /**
  1359.      * Split list
  1360.      * 1) Find place to split
  1361.      * 2) Rewrite header (the part that will be sent)
  1362.      * 3) Write new header (for remaining part)
  1363.      * 4) Store new header on FragmentSendInfo - record
  1364.      */
  1365.     Uint32 sum = sizeLeft;
  1366.     sum /= SectionSegment::DataLength;
  1367.     sum *= SectionSegment::DataLength;
  1368.     
  1369.     /**
  1370.      * Rewrite header w.r.t size
  1371.      */
  1372.     Uint32 prev = secCount - 1;
  1373.     signalPtr[prev].sz = sum;
  1374.     
  1375.     /**
  1376.      * Write/store "new" header
  1377.      */
  1378.     info.m_sectionPtr[secNo].m_linear.p = ptrP + sum;
  1379.     info.m_sectionPtr[secNo].m_linear.sz = size - sum;
  1380.     
  1381.     loop = Full;
  1382.     lsout(ndbout_c("section %d split into %d", secNo, prev));
  1383.     break;
  1384.   }
  1385.   
  1386.   lsout(ndbout_c("loop: %d secNo: %d secCount: %d sz: %d", 
  1387.  loop, secNo, secCount, sz));
  1388.   
  1389.   /**
  1390.    * Store fragment id
  1391.    */
  1392.   secNos[secCount] = info.m_fragmentId;
  1393.   
  1394.   Uint32 fragInfo = info.m_fragInfo;
  1395.   info.m_fragInfo = 2;
  1396.   switch(loop){
  1397.   case Unknown:
  1398.     if(secNo >= 0){
  1399.       lsout(ndbout_c("Unknown - Full"));
  1400.       /**
  1401.        * Not finished
  1402.        */
  1403.       break;
  1404.     }
  1405.     // Fall through
  1406.     lsout(ndbout_c("Unknown - Done"));
  1407.     info.m_status = FragmentSendInfo::SendComplete;
  1408.     ndbassert(fragInfo == 2);
  1409.     fragInfo = 3;
  1410.   case Full:
  1411.     break;
  1412.   }
  1413.   
  1414.   signal->header.m_noOfSections = 0;
  1415.   signal->header.m_fragmentInfo = fragInfo;
  1416.   
  1417.   sendSignal(info.m_nodeReceiverGroup,
  1418.      info.m_gsn,
  1419.      signal, 
  1420.      sigLen + secCount + 1,
  1421.      (JobBufferLevel)info.m_prio,
  1422.      signalPtr,
  1423.      secCount);
  1424.   
  1425.   if(fragInfo == 3){
  1426.     /**
  1427.      * This is the last signal
  1428.      */
  1429.     g_sectionSegmentPool.release(info.m_theDataSection.p[sigLen]);
  1430.   }
  1431. }
  1432. void
  1433. SimulatedBlock::sendFragmentedSignal(BlockReference ref, 
  1434.      GlobalSignalNumber gsn, 
  1435.      Signal* signal, 
  1436.      Uint32 length, 
  1437.      JobBufferLevel jbuf,
  1438.      Callback & c,
  1439.      Uint32 messageSize){
  1440.   bool res = true;
  1441.   Ptr<FragmentSendInfo> ptr;
  1442.   res = c_segmentedFragmentSendList.seize(ptr);
  1443.   ndbrequire(res);
  1444.   
  1445.   res = sendFirstFragment(* ptr.p, 
  1446.   NodeReceiverGroup(ref),
  1447.   gsn,
  1448.   signal,
  1449.   length,
  1450.   jbuf,
  1451.   messageSize);
  1452.   ndbrequire(res);
  1453.   
  1454.   if(ptr.p->m_status == FragmentSendInfo::SendComplete){
  1455.     c_segmentedFragmentSendList.release(ptr);
  1456.     if(c.m_callbackFunction != 0)
  1457.       execute(signal, c, 0);
  1458.     return;
  1459.   }
  1460.   ptr.p->m_callback = c;
  1461.   if(!c_fragSenderRunning){
  1462.     c_fragSenderRunning = true;
  1463.     ContinueFragmented * sig = (ContinueFragmented*)signal->getDataPtrSend();
  1464.     sig->line = __LINE__;
  1465.     sendSignal(reference(), GSN_CONTINUE_FRAGMENTED, signal, 1, JBB);
  1466.   }
  1467. }
  1468. void
  1469. SimulatedBlock::sendFragmentedSignal(NodeReceiverGroup rg, 
  1470.      GlobalSignalNumber gsn, 
  1471.      Signal* signal, 
  1472.      Uint32 length, 
  1473.      JobBufferLevel jbuf,
  1474.      Callback & c,
  1475.      Uint32 messageSize){
  1476.   bool res = true;
  1477.   Ptr<FragmentSendInfo> ptr;
  1478.   res = c_segmentedFragmentSendList.seize(ptr);
  1479.   ndbrequire(res);
  1480.   
  1481.   res = sendFirstFragment(* ptr.p, 
  1482.   rg,
  1483.   gsn,
  1484.   signal,
  1485.   length,
  1486.   jbuf,
  1487.   messageSize);
  1488.   ndbrequire(res);
  1489.   
  1490.   if(ptr.p->m_status == FragmentSendInfo::SendComplete){
  1491.     c_segmentedFragmentSendList.release(ptr);
  1492.     if(c.m_callbackFunction != 0)
  1493.       execute(signal, c, 0);
  1494.     return;
  1495.   }
  1496.   ptr.p->m_callback = c;
  1497.   if(!c_fragSenderRunning){
  1498.     c_fragSenderRunning = true;
  1499.     ContinueFragmented * sig = (ContinueFragmented*)signal->getDataPtrSend();
  1500.     sig->line = __LINE__;
  1501.     sendSignal(reference(), GSN_CONTINUE_FRAGMENTED, signal, 1, JBB);
  1502.   }
  1503. }
  1504. SimulatedBlock::Callback SimulatedBlock::TheEmptyCallback = {0, 0};
  1505. void
  1506. SimulatedBlock::sendFragmentedSignal(BlockReference ref, 
  1507.      GlobalSignalNumber gsn, 
  1508.      Signal* signal, 
  1509.      Uint32 length, 
  1510.      JobBufferLevel jbuf,
  1511.      LinearSectionPtr ptr[3],
  1512.      Uint32 noOfSections,
  1513.      Callback & c,
  1514.      Uint32 messageSize){
  1515.   bool res = true;
  1516.   Ptr<FragmentSendInfo> tmp;
  1517.   res = c_linearFragmentSendList.seize(tmp);
  1518.   ndbrequire(res);
  1519.   res = sendFirstFragment(* tmp.p, 
  1520.   NodeReceiverGroup(ref),
  1521.   gsn,
  1522.   signal,
  1523.   length,
  1524.   jbuf,
  1525.   ptr,
  1526.   noOfSections,
  1527.   messageSize);
  1528.   ndbrequire(res);
  1529.   
  1530.   if(tmp.p->m_status == FragmentSendInfo::SendComplete){
  1531.     c_linearFragmentSendList.release(tmp);
  1532.     if(c.m_callbackFunction != 0)
  1533.       execute(signal, c, 0);
  1534.     return;
  1535.   }
  1536.   tmp.p->m_callback = c;
  1537.   
  1538.   if(!c_fragSenderRunning){
  1539.     c_fragSenderRunning = true;
  1540.     ContinueFragmented * sig = (ContinueFragmented*)signal->getDataPtrSend();
  1541.     sig->line = __LINE__;
  1542.     sendSignal(reference(), GSN_CONTINUE_FRAGMENTED, signal, 1, JBB);
  1543.   }
  1544. }
  1545. void
  1546. SimulatedBlock::sendFragmentedSignal(NodeReceiverGroup rg, 
  1547.      GlobalSignalNumber gsn, 
  1548.      Signal* signal, 
  1549.      Uint32 length, 
  1550.      JobBufferLevel jbuf,
  1551.      LinearSectionPtr ptr[3],
  1552.      Uint32 noOfSections,
  1553.      Callback & c,
  1554.      Uint32 messageSize){
  1555.   bool res = true;
  1556.   Ptr<FragmentSendInfo> tmp;
  1557.   res = c_linearFragmentSendList.seize(tmp);
  1558.   ndbrequire(res);
  1559.   res = sendFirstFragment(* tmp.p, 
  1560.   rg,
  1561.   gsn,
  1562.   signal,
  1563.   length,
  1564.   jbuf,
  1565.   ptr,
  1566.   noOfSections,
  1567.   messageSize);
  1568.   ndbrequire(res);
  1569.   
  1570.   if(tmp.p->m_status == FragmentSendInfo::SendComplete){
  1571.     c_linearFragmentSendList.release(tmp);
  1572.     if(c.m_callbackFunction != 0)
  1573.       execute(signal, c, 0);
  1574.     return;
  1575.   }
  1576.   tmp.p->m_callback = c;
  1577.   
  1578.   if(!c_fragSenderRunning){
  1579.     c_fragSenderRunning = true;
  1580.     ContinueFragmented * sig = (ContinueFragmented*)signal->getDataPtrSend();
  1581.     sig->line = __LINE__;
  1582.     sendSignal(reference(), GSN_CONTINUE_FRAGMENTED, signal, 1, JBB);
  1583.   }
  1584. }
  1585. NodeInfo &
  1586. SimulatedBlock::setNodeInfo(NodeId nodeId) {
  1587.   ndbrequire(nodeId > 0 && nodeId < MAX_NODES);
  1588.   return globalData.m_nodeInfo[nodeId];
  1589. }
  1590. void 
  1591. SimulatedBlock::execUTIL_CREATE_LOCK_REF(Signal* signal){
  1592.   ljamEntry();
  1593.   c_mutexMgr.execUTIL_CREATE_LOCK_REF(signal);
  1594. }
  1595. void SimulatedBlock::execUTIL_CREATE_LOCK_CONF(Signal* signal){
  1596.   ljamEntry();
  1597.   c_mutexMgr.execUTIL_CREATE_LOCK_CONF(signal);
  1598. }
  1599. void SimulatedBlock::execUTIL_DESTORY_LOCK_REF(Signal* signal){
  1600.   ljamEntry();
  1601.   c_mutexMgr.execUTIL_DESTORY_LOCK_REF(signal);
  1602. }
  1603. void SimulatedBlock::execUTIL_DESTORY_LOCK_CONF(Signal* signal){
  1604.   ljamEntry();
  1605.   c_mutexMgr.execUTIL_DESTORY_LOCK_CONF(signal);
  1606. }
  1607. void SimulatedBlock::execUTIL_LOCK_REF(Signal* signal){
  1608.   ljamEntry();
  1609.   c_mutexMgr.execUTIL_LOCK_REF(signal);
  1610. }
  1611. void SimulatedBlock::execUTIL_LOCK_CONF(Signal* signal){
  1612.   ljamEntry();
  1613.   c_mutexMgr.execUTIL_LOCK_CONF(signal);
  1614. }
  1615. void SimulatedBlock::execUTIL_UNLOCK_REF(Signal* signal){
  1616.   ljamEntry();
  1617.   c_mutexMgr.execUTIL_UNLOCK_REF(signal);
  1618. }
  1619. void SimulatedBlock::execUTIL_UNLOCK_CONF(Signal* signal){
  1620.   ljamEntry();
  1621.   c_mutexMgr.execUTIL_UNLOCK_CONF(signal);
  1622. }
  1623. void 
  1624. SimulatedBlock::execREAD_CONFIG_REQ(Signal* signal){
  1625.   const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
  1626.   Uint32 ref = req->senderRef;
  1627.   Uint32 senderData = req->senderData;
  1628.   ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
  1629.   conf->senderRef = reference();
  1630.   conf->senderData = senderData;
  1631.   sendSignal(ref, GSN_READ_CONFIG_CONF, signal, 
  1632.      ReadConfigConf::SignalLength, JBB);
  1633. }
  1634. void
  1635. SimulatedBlock::ignoreMutexUnlockCallback(Signal* signal, 
  1636.   Uint32 ptrI, Uint32 retVal){
  1637.   c_mutexMgr.release(ptrI);
  1638. }
  1639. void 
  1640. UpgradeStartup::installEXEC(SimulatedBlock* block){
  1641.   SimulatedBlock::ExecFunction * a = block->theExecArray;
  1642.   switch(block->number()){
  1643.   case QMGR:
  1644.     a[UpgradeStartup::GSN_CM_APPCHG] = &SimulatedBlock::execUPGRADE;
  1645.     break;
  1646.   case CNTR:
  1647.     a[UpgradeStartup::GSN_CNTR_MASTERREF] = &SimulatedBlock::execUPGRADE;
  1648.     a[UpgradeStartup::GSN_CNTR_MASTERCONF] = &SimulatedBlock::execUPGRADE;
  1649.     break;
  1650.   }
  1651. }
  1652. void
  1653. SimulatedBlock::execUPGRADE(Signal* signal){
  1654.   Uint32 gsn = signal->header.theVerId_signalNumber;
  1655.   switch(gsn){
  1656.   case UpgradeStartup::GSN_CM_APPCHG:
  1657.     UpgradeStartup::execCM_APPCHG(* this, signal);
  1658.     break;
  1659.   case UpgradeStartup::GSN_CNTR_MASTERREF:
  1660.     UpgradeStartup::execCNTR_MASTER_REPLY(* this, signal);
  1661.     break;
  1662.   case UpgradeStartup::GSN_CNTR_MASTERCONF:
  1663.     UpgradeStartup::execCNTR_MASTER_REPLY(* this, signal);
  1664.     break;
  1665.   }
  1666. }
  1667. void
  1668. SimulatedBlock::fsRefError(Signal* signal, Uint32 line, const char *msg) 
  1669. {
  1670.   const FsRef *fsRef = (FsRef*)signal->getDataPtr();
  1671.   Uint32 errorCode = fsRef->errorCode;
  1672.   Uint32 osErrorCode = fsRef->osErrorCode;
  1673.   char msg2[100];
  1674.   sprintf(msg2, "%s: %s. OS errno: %u", getBlockName(number()), msg, osErrorCode);
  1675.   progError(line, errorCode, msg2);
  1676. }
  1677. void
  1678. SimulatedBlock::execFSWRITEREF(Signal* signal) 
  1679. {
  1680.   fsRefError(signal, __LINE__, "File system write failed");
  1681. }
  1682. void
  1683. SimulatedBlock::execFSREADREF(Signal* signal) 
  1684. {
  1685.   fsRefError(signal, __LINE__, "File system read failed");
  1686. }
  1687. void
  1688. SimulatedBlock::execFSCLOSEREF(Signal* signal) 
  1689. {
  1690.   fsRefError(signal, __LINE__, "File system close failed");
  1691. }
  1692. void
  1693. SimulatedBlock::execFSOPENREF(Signal* signal) 
  1694. {
  1695.   fsRefError(signal, __LINE__, "File system open failed");
  1696. }
  1697. void
  1698. SimulatedBlock::execFSREMOVEREF(Signal* signal) 
  1699. {
  1700.   fsRefError(signal, __LINE__, "File system remove failed");
  1701. }
  1702. void
  1703. SimulatedBlock::execFSSYNCREF(Signal* signal) 
  1704. {
  1705.   fsRefError(signal, __LINE__, "File system sync failed");
  1706. }
  1707. void
  1708. SimulatedBlock::execFSAPPENDREF(Signal* signal) 
  1709. {
  1710.   fsRefError(signal, __LINE__, "File system append failed");
  1711. }
  1712. #ifdef VM_TRACE
  1713. void
  1714. SimulatedBlock::clear_global_variables(){
  1715.   Ptr<void> ** tmp = m_global_variables;
  1716.   while(* tmp != 0){
  1717.     (* tmp)->i = RNIL;
  1718.     (* tmp)->p = 0;
  1719.     tmp++;
  1720.   }
  1721. }
  1722. void
  1723. SimulatedBlock::init_globals_list(void ** tmp, size_t cnt){
  1724.   m_global_variables = new Ptr<void> * [cnt+1];
  1725.   for(size_t i = 0; i<cnt; i++){
  1726.     m_global_variables[i] = (Ptr<void>*)tmp[i];
  1727.   }
  1728.   m_global_variables[cnt] = 0;
  1729. }
  1730. #endif