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

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. #ifndef __SAFE_COUNTER_HPP
  14. #define __SAFE_COUNTER_HPP
  15. /*************************************************************
  16.  *
  17.  * SafeCounter "automates" three way to node-fais safe protocols
  18.  * for "slave" failures.  This is done by registing "fake" signals
  19.  * to be sent in case of nodefailure.
  20.  *
  21.  * init<SignalClass>(..., GSN, senderData);
  22.  *
  23.  * It is implemented so that one can replace SignalCounter with
  24.  * SafeCounter (SignalCounter should probably go away with time)
  25.  * methods:
  26.  * clearWaitingFor(nodeId);
  27.  * done();
  28.  * etc.
  29.  *
  30.  * If included in a new block method
  31.  * SafeCounterManager::execNODE_FAILREP must included in
  32.  * <block>::execNODE_FAILREP
  33.  *
  34.  * the SignalClass must have senderRef, senderData and errorCode
  35.  * and also ErrorCode::NF_FakeErrorREF, implemented
  36.  *
  37.  * SafeCounter consists of 3 parts:
  38.  * SafeCounterManager which keeps track of active "counters"
  39.  * SafeCounterHandle to store "i-value" in your "op record"
  40.  * SafeCounter as a temporary variable only to use on the stack
  41.  * for operation
  42.  *
  43.  */
  44. #include <NodeBitmask.hpp>
  45. #include "DLList.hpp"
  46. #include "VMSignal.hpp"
  47. class SimulatedBlock;
  48. /**
  49.  *
  50.  */
  51. class SafeCounterManager {
  52.   friend class SafeCounter;
  53.   friend class SafeCounterHandle;
  54.   friend class SimulatedBlock;
  55. public:
  56.   SafeCounterManager(class SimulatedBlock &);
  57.   
  58.   bool setSize(Uint32 maxNoOfActiveMutexes);
  59.   Uint32 getSize() const ;
  60.   void execNODE_FAILREP(Signal*); 
  61.   void printNODE_FAILREP(); 
  62. private:
  63.   struct ActiveCounter { /** sizeof = 7words = 28bytes */ 
  64.   public:
  65.     Uint32 m_senderData;
  66.     NodeBitmask m_nodes;
  67.     struct SignalDesc {
  68.     public:
  69.       Uint16 m_gsn; 
  70.       Uint16 m_block;
  71.       Uint8 m_senderRefOffset;
  72.       Uint8 m_senderDataOffset;
  73.       Uint8 m_errorCodeOffset;
  74.       Uint8 m_nodeFailErrorCode;
  75.     } m_signalDesc;
  76.     union {
  77.       Uint32 nextPool;
  78.       Uint32 nextList;
  79.     };
  80.     Uint32 prevList;
  81.   };
  82.   typedef Ptr<ActiveCounter> ActiveCounterPtr;
  83.   
  84.   bool seize(ActiveCounterPtr& ptr);
  85.   void release(ActiveCounterPtr& ptr);
  86.   void getPtr(ActiveCounterPtr& ptr, Uint32 ptrI);
  87.   SimulatedBlock & m_block;
  88.   ArrayPool<ActiveCounter> m_counterPool;
  89.   DLList<ActiveCounter> m_activeCounters;
  90.   BlockReference reference() const;
  91.   void progError(int line, int err_code, const char* extra = 0);
  92. };
  93. class SafeCounterHandle {
  94.   friend class SafeCounter;
  95. public:
  96.   SafeCounterHandle();
  97.   /**
  98.    * Return if done (no nodes set in bitmask)
  99.    */
  100.   bool clearWaitingFor(SafeCounterManager& mgr, Uint32 nodeId);
  101.   
  102.   bool done() const;
  103.   
  104. private:
  105.   Uint32 m_activeCounterPtrI;
  106. };
  107. class SafeCounter {
  108.   friend class SafeCounterManager;
  109. public:
  110.   SafeCounter(SafeCounterManager&, SafeCounterHandle&);
  111.   
  112.   template<typename SignalClass>
  113.     bool init(Uint16 block, Uint16 GSN, Uint32 senderData);
  114.   
  115.   template<typename SignalClass>
  116.     bool init(NodeReceiverGroup rg, Uint16 GSN, Uint32 senderData);
  117.   template<typename SignalClass>
  118.     bool init(NodeReceiverGroup rg, Uint32 senderData);
  119.   
  120.   ~SafeCounter();
  121.   
  122.   void clearWaitingFor();
  123.   
  124.   /**
  125.    * When sending to different node
  126.    */
  127.   void setWaitingFor(Uint32 nodeId);
  128.   bool clearWaitingFor(Uint32 nodeId);
  129.   bool forceClearWaitingFor(Uint32 nodeId);
  130.   
  131.   bool isWaitingFor(Uint32 nodeId) const;
  132.   bool done() const;
  133.   const char * getText() const; /* ? needed for, some portability issues */
  134.   SafeCounter& operator=(const NdbNodeBitmask&);
  135.   SafeCounter& operator=(const NodeReceiverGroup&);
  136. private:
  137.   Uint32 m_count;
  138.   NodeBitmask m_nodes;
  139.   
  140.   SafeCounterManager & m_mgr;
  141.   SafeCounterManager::ActiveCounterPtr m_ptr;
  142.   
  143.   Uint32 & m_activeCounterPtrI;
  144. };
  145. inline
  146. SafeCounterHandle::SafeCounterHandle(){
  147.   m_activeCounterPtrI = RNIL;
  148. }
  149. inline
  150. bool
  151. SafeCounterHandle::done() const {
  152.   return m_activeCounterPtrI == RNIL;
  153. }
  154. inline
  155. SafeCounter::SafeCounter(SafeCounterManager& mgr, SafeCounterHandle& handle)
  156.   : m_mgr(mgr),
  157.     m_activeCounterPtrI(handle.m_activeCounterPtrI)
  158. {
  159.   m_ptr.i = handle.m_activeCounterPtrI;
  160.   if (m_ptr.i == RNIL) {
  161.     m_nodes.clear();
  162.     m_count = 0;
  163.   } else {
  164.     m_mgr.getPtr(m_ptr, m_ptr.i);
  165.     m_nodes = m_ptr.p->m_nodes;
  166.     m_count = m_nodes.count();
  167.   }
  168. }
  169. template<typename Ref>
  170. inline
  171. bool
  172. SafeCounter::init(Uint16 block, Uint16 GSN, Uint32 senderData){
  173.   
  174.   SafeCounterManager::ActiveCounter::SignalDesc signalDesc;
  175.   signalDesc.m_gsn = GSN;
  176.   signalDesc.m_block = block;
  177.   signalDesc.m_errorCodeOffset = offsetof(Ref, errorCode) >> 2;
  178.   signalDesc.m_senderRefOffset = offsetof(Ref, senderRef) >> 2;
  179.   signalDesc.m_senderDataOffset = offsetof(Ref, senderData) >> 2;
  180.   signalDesc.m_nodeFailErrorCode = Ref::NF_FakeErrorREF;
  181.   assert(((Uint32)Ref::NF_FakeErrorREF) < 256);
  182.   
  183.   if(m_ptr.i == RNIL){
  184.     SafeCounterManager::ActiveCounterPtr ptr;
  185.     if(m_mgr.seize(ptr)){
  186.       ptr.p->m_senderData = senderData;
  187.       ptr.p->m_signalDesc = signalDesc;
  188.       m_ptr = ptr;
  189.       return true;
  190.     }
  191.     return false;
  192.   }
  193.   if(m_count == 0){
  194.     m_ptr.p->m_senderData = senderData;
  195.     m_ptr.p->m_signalDesc = signalDesc;
  196.     return true;
  197.   } 
  198.   ErrorReporter::handleAssert("SafeCounter::init twice", __FILE__, __LINE__);  
  199.   return false;
  200. }
  201. template<typename Ref>
  202. inline
  203. bool
  204. SafeCounter::init(NodeReceiverGroup rg, Uint16 GSN, Uint32 senderData){
  205.   
  206.   bool b = init<Ref>(rg.m_block, GSN, senderData);
  207.   m_nodes = rg.m_nodes;
  208.   m_count = m_nodes.count();
  209.   return b;
  210. }
  211. template<typename Ref>
  212. inline
  213. bool
  214. SafeCounter::init(NodeReceiverGroup rg, Uint32 senderData){
  215.   
  216.   bool b = init<Ref>(rg.m_block, Ref::GSN, senderData);
  217.   m_nodes = rg.m_nodes;
  218.   m_count = m_nodes.count();
  219.   return b;
  220. }
  221. inline
  222. void 
  223. SafeCounter::setWaitingFor(Uint32 nodeId) {
  224.   if(!m_nodes.get(nodeId)){
  225.     m_nodes.set(nodeId);
  226.     m_count++;
  227.     return;
  228.   }
  229.   ErrorReporter::handleAssert("SafeCounter::set", __FILE__, __LINE__);
  230. }
  231. inline
  232. bool
  233. SafeCounter::isWaitingFor(Uint32 nodeId) const {
  234.   return m_nodes.get(nodeId);
  235. }
  236. inline
  237. bool
  238. SafeCounter::done() const {
  239.   return m_count == 0;
  240. }
  241. inline
  242. bool
  243. SafeCounter::clearWaitingFor(Uint32 nodeId) {
  244.   if(m_count > 0 && m_nodes.get(nodeId)){
  245.     m_count--;
  246.     m_nodes.clear(nodeId);
  247.     return (m_count == 0);
  248.   }
  249.   ErrorReporter::handleAssert("SafeCounter::clear", __FILE__, __LINE__);
  250.   return false;
  251. }
  252. inline
  253. void
  254. SafeCounter::clearWaitingFor(){
  255.   m_count = 0;
  256.   m_nodes.clear();
  257. }
  258. inline
  259. bool
  260. SafeCounter::forceClearWaitingFor(Uint32 nodeId){
  261.   if(isWaitingFor(nodeId)){
  262.     return clearWaitingFor(nodeId);
  263.   }
  264.   return (m_count == 0);
  265. }
  266. #endif