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
1.4.3