ThreadConfig.cpp

Go to the documentation of this file.
00001 /* Copyright (C) 2003 MySQL AB
00002 
00003    This program is free software; you can redistribute it and/or modify
00004    it under the terms of the GNU General Public License as published by
00005    the Free Software Foundation; either version 2 of the License, or
00006    (at your option) any later version.
00007 
00008    This program is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011    GNU General Public License for more details.
00012 
00013    You should have received a copy of the GNU General Public License
00014    along with this program; if not, write to the Free Software
00015    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
00016 
00017 #include "ThreadConfig.hpp"
00018 #include "Emulator.hpp"
00019 #include "GlobalData.hpp"
00020 #include "TimeQueue.hpp"
00021 #include "TransporterRegistry.hpp"
00022 #include "FastScheduler.hpp"
00023 #include "pc.hpp"
00024 
00025 #include <GlobalSignalNumbers.h>
00026 #include <BlockNumbers.h>
00027 
00028 #include <NdbSleep.h>
00029 #include <NdbTick.h>
00030 #include <NdbOut.hpp>
00031 
00032 #include <signaldata/StartOrd.hpp>
00033 
00034 ThreadConfig::ThreadConfig()
00035 {
00036 }
00037 
00038 ThreadConfig::~ThreadConfig()
00039 {
00040 }
00041 
00047 inline
00048 void 
00049 ThreadConfig::scanTimeQueue()
00050 {
00051   unsigned int maxCounter;
00052   Uint64 currMilliSecond;
00053   maxCounter = 0;
00054   currMilliSecond = NdbTick_CurrentMillisecond();
00055   if (currMilliSecond < globalData.internalMillisecCounter) {
00056 //--------------------------------------------------------------------
00057 // This could occur around 2036 or if the operator decides to change
00058 // time backwards. We cannot know how long time has past since last
00059 // time and we make a best try with 0 milliseconds.
00060 //--------------------------------------------------------------------
00061 #ifdef VM_TRACE
00062     ndbout << "Time moved backwards with ";
00063     ndbout << (globalData.internalMillisecCounter - currMilliSecond);
00064     ndbout << " milliseconds" << endl;
00065 #endif
00066     globalData.internalMillisecCounter = currMilliSecond;
00067   }//if
00068   if (currMilliSecond > (globalData.internalMillisecCounter + 1500)) {
00069 //--------------------------------------------------------------------
00070 // Time has moved forward more than a second. Either it could happen
00071 // if operator changed the time or if the OS has misbehaved badly.
00072 // We set the new time to one second from the past.
00073 //--------------------------------------------------------------------
00074 #ifdef VM_TRACE
00075     ndbout << "Time moved forward with ";
00076     ndbout << (currMilliSecond - globalData.internalMillisecCounter);
00077     ndbout << " milliseconds" << endl;
00078 #endif
00079     globalData.internalMillisecCounter = currMilliSecond - 1000;
00080   }//if
00081   while (((currMilliSecond - globalData.internalMillisecCounter) > 0) &&
00082          (maxCounter < 20)){
00083     globalData.internalMillisecCounter++;
00084     maxCounter++;
00085     globalTimeQueue.scanTable();
00086   }//while
00087 }//ThreadConfig::scanTimeQueue()
00088 
00089 
00090 //--------------------------------------------------------------------
00091 // ipControlLoop -- The main loop of ndb.
00092 // Handles the scheduling of signal execution and input/output
00093 // One lap in the loop should take approximately 10 milli seconds
00094 // If the jobbuffer is empty and the laptime is less than 10 milliseconds
00095 // at the end of the loop
00096 // the TransporterRegistry is called in order to sleep on the IO ports
00097 // waiting for another incoming signal to wake us up.
00098 // The timeout value in this call is calculated as (10 ms - laptime)
00099 // This would make ndb use less cpu while improving response time.
00100 //--------------------------------------------------------------------
00101 void ThreadConfig::ipControlLoop()
00102 {
00103 
00104 #if defined NDB_OSE || defined NDB_SOFTOSE
00105 //--------------------------------------------------------------------
00106 // To let the Cello Watchdog do it's work NDB must sleep a short 
00107 // period every 10 minutes. If this is not done, the watchdog will 
00108 // reboot the board NDB is running on when the load is high. 
00109 //--------------------------------------------------------------------
00110   int loopCounter = 0;
00111 #endif
00112 
00113 //--------------------------------------------------------------------
00114 // initialise the counter that keeps track of the current millisecond
00115 //--------------------------------------------------------------------
00116   globalData.internalMillisecCounter = NdbTick_CurrentMillisecond();
00117   Uint32 i = 0;
00118   while (globalData.theRestartFlag != perform_stop)  { 
00119 
00120 #if defined NDB_OSE || defined NDB_SOFTOSE
00121     loopCounter++;
00122     if(loopCounter > 1000){
00123 //--------------------------------------------------------------------
00124 // This is done to allow OSE do a context switch to let the watchdog 
00125 // do it's stuff.
00126 //--------------------------------------------------------------------
00127       NdbSleep_MilliSleep(1);
00128       loopCounter = 0;
00129     }
00130 #endif
00131 
00132     Uint32 timeOutMillis = 0;
00133     if (LEVEL_IDLE == globalData.highestAvailablePrio) {
00134 //--------------------------------------------------------------------
00135 // The buffers are empty, we need to wait for a while until we continue.
00136 // We cannot wait forever since we can also have timed events.
00137 //--------------------------------------------------------------------
00138 //--------------------------------------------------------------------
00139 // Set the time we will sleep on the sockets before waking up
00140 // unconditionally to 10 ms. Will never sleep more than 10 milliseconds
00141 // on a socket.
00142 //--------------------------------------------------------------------
00143       timeOutMillis = 10;
00144     }//if
00145 //--------------------------------------------------------------------
00146 // Now it is time to check all interfaces. We will send all buffers
00147 // plus checking for any received messages.
00148 //--------------------------------------------------------------------
00149     if (i++ >= 20) {
00150       globalTransporterRegistry.update_connections();
00151       globalData.incrementWatchDogCounter(5);
00152       i = 0;
00153     }//if
00154 
00155     globalData.incrementWatchDogCounter(6);
00156     globalTransporterRegistry.performSend();
00157     
00158     globalData.incrementWatchDogCounter(7);
00159     if (globalTransporterRegistry.pollReceive(timeOutMillis)) {
00160       globalData.incrementWatchDogCounter(8);
00161       globalTransporterRegistry.performReceive();
00162     }
00163 
00164 //--------------------------------------------------------------------
00165 // We scan the time queue to see if there are any timed signals that
00166 // is now ready to be executed.
00167 //--------------------------------------------------------------------
00168     globalData.incrementWatchDogCounter(2);
00169     scanTimeQueue(); 
00170 
00171 //--------------------------------------------------------------------
00172 // This is where the actual execution of signals occur. We execute
00173 // until all buffers are empty or until we have executed 2048 signals.
00174 //--------------------------------------------------------------------
00175     globalScheduler.doJob();
00176   }//while
00177 
00178   globalData.incrementWatchDogCounter(6);
00179   globalTransporterRegistry.performSend();
00180 
00181 }//ThreadConfig::ipControlLoop()
00182 
00183 int
00184 ThreadConfig::doStart(NodeState::StartLevel startLevel){
00185   
00186   SignalHeader sh;
00187   memset(&sh, 0, sizeof(SignalHeader));
00188   
00189   sh.theVerId_signalNumber   = GSN_START_ORD;
00190   sh.theReceiversBlockNumber = CMVMI;
00191   sh.theSendersBlockRef      = 0;
00192   sh.theTrace                = 0;
00193   sh.theSignalId             = 0;
00194   sh.theLength               = StartOrd::SignalLength;
00195   
00196   Uint32 theData[25];
00197   StartOrd * const  startOrd = (StartOrd *)&theData[0];
00198   startOrd->restartInfo = 0;
00199   
00200   Uint32 secPtrI[3];
00201   globalScheduler.execute(&sh, JBA, theData, secPtrI);
00202   return 0;
00203 }
00204 

Generated on Wed Jul 20 21:05:40 2005 for MySQL 5.0.9 Beta by  doxygen 1.4.3