/* Copyright (C) 2003 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef ClusterMgr_H #define ClusterMgr_H #include "API.hpp" #include #include #include #include #include #include #include #include extern "C" void* runClusterMgr_C(void * me); /** * @class ClusterMgr */ class ClusterMgr { friend void* runClusterMgr_C(void * me); friend void execute(void *, struct SignalHeader * const, Uint8, Uint32 * const, LinearSectionPtr ptr[3]); public: ClusterMgr(class TransporterFacade &); ~ClusterMgr(); void init(struct ndb_mgm_configuration_iterator & config); void reportConnected(NodeId nodeId); void reportDisconnected(NodeId nodeId); bool checkUpgradeCompatability(Uint32 nodeVersion); void doStop(); void startThread(); private: void threadMain(); int theStop; class TransporterFacade & theFacade; public: struct Node { Node(); bool defined; bool connected; // Transporter connected bool compatible; // Version is compatible bool nfCompleteRep; // NF Complete Rep has arrived bool m_alive; // Node is alive NodeInfo m_info; NodeState m_state; /** * Heartbeat stuff */ Uint32 hbFrequency; // Heartbeat frequence Uint32 hbCounter; // # milliseconds passed since last hb sent Uint32 hbSent; // # heartbeats sent (without answer) }; const Node & getNodeInfo(NodeId) const; Uint32 getNoOfConnectedNodes() const; private: Uint32 noOfConnectedNodes; Node theNodes[MAX_NODES]; NdbThread* theClusterMgrThread; /** * Used for controlling start/stop of the thread */ NdbMutex* clusterMgrThreadMutex; void showState(NodeId nodeId); void reportNodeFailed(NodeId nodeId); /** * Signals received */ void execAPI_REGREQ (const Uint32 * theData); void execAPI_REGCONF (const Uint32 * theData); void execAPI_REGREF (const Uint32 * theData); void execNODE_FAILREP (const Uint32 * theData); void execNF_COMPLETEREP(const Uint32 * theData); }; inline const ClusterMgr::Node & ClusterMgr::getNodeInfo(NodeId nodeId) const { return theNodes[nodeId]; } inline Uint32 ClusterMgr::getNoOfConnectedNodes() const { return noOfConnectedNodes; } /*****************************************************************************/ /** * @class ArbitMgr * Arbitration manager. Runs in separate thread. * Started only by a request from the kernel. */ extern "C" void* runArbitMgr_C(void* me); class ArbitMgr { public: ArbitMgr(class TransporterFacade &); ~ArbitMgr(); inline void setRank(unsigned n) { theRank = n; } inline void setDelay(unsigned n) { theDelay = n; } void doStart(const Uint32* theData); void doChoose(const Uint32* theData); void doStop(const Uint32* theData); friend void* runArbitMgr_C(void* me); private: class TransporterFacade & theFacade; unsigned theRank; unsigned theDelay; void threadMain(); NdbThread* theThread; NdbMutex* theThreadMutex; // not really needed struct ArbitSignal { GlobalSignalNumber gsn; ArbitSignalData data; NDB_TICKS timestamp; inline void init(GlobalSignalNumber aGsn, const Uint32* aData) { gsn = aGsn; if (aData != NULL) memcpy(&data, aData, sizeof(data)); else memset(&data, 0, sizeof(data)); } inline void setTimestamp() { timestamp = NdbTick_CurrentMillisecond(); } inline NDB_TICKS getTimediff() { NDB_TICKS now = NdbTick_CurrentMillisecond(); return now < timestamp ? 0 : now - timestamp; } }; NdbMutex* theInputMutex; NdbCondition* theInputCond; int theInputTimeout; bool theInputFull; // the predicate ArbitSignal theInputBuffer; // shared buffer void sendSignalToThread(ArbitSignal& aSignal); enum State { // thread states StateInit, StateStarted, // thread started StateChoose1, // received one valid REQ StateChoose2, // received two valid REQs StateFinished // finished one way or other }; State theState; enum Stop { // stop code in ArbitSignal.data.code StopExit = 1, // at API exit StopRequest = 2, // request from kernel StopRestart = 3 // stop before restart }; void threadStart(ArbitSignal& aSignal); // handle thread events void threadChoose(ArbitSignal& aSignal); void threadTimeout(); void threadStop(ArbitSignal& aSignal); ArbitSignal theStartReq; ArbitSignal theChooseReq1; ArbitSignal theChooseReq2; ArbitSignal theStopOrd; void sendStartConf(ArbitSignal& aSignal, Uint32); void sendChooseRef(ArbitSignal& aSignal, Uint32); void sendChooseConf(ArbitSignal& aSignal, Uint32); void sendStopRep(ArbitSignal& aSignal, Uint32); void sendSignalToQmgr(ArbitSignal& aSignal); }; #endif