MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SafeCounter.hpp
1 /*
2  Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #ifndef __SAFE_COUNTER_HPP
19 #define __SAFE_COUNTER_HPP
20 
21 /*************************************************************
22  *
23  * SafeCounter "automates" three way to node-fais safe protocols
24  * for "slave" failures. This is done by registing "fake" signals
25  * to be sent in case of nodefailure.
26  *
27  * init<SignalClass>(..., GSN, senderData);
28  *
29  * It is implemented so that one can replace SignalCounter with
30  * SafeCounter (SignalCounter should probably go away with time)
31  * methods:
32  * clearWaitingFor(nodeId);
33  * done();
34  * etc.
35  *
36  * If included in a new block method
37  * SafeCounterManager::execNODE_FAILREP must included in
38  * <block>::execNODE_FAILREP
39  *
40  * the SignalClass must have senderRef, senderData and errorCode
41  * and also ErrorCode::NF_FakeErrorREF, implemented
42  *
43  * SafeCounter consists of 3 parts:
44  * SafeCounterManager which keeps track of active "counters"
45  * SafeCounterHandle to store "i-value" in your "op record"
46  * SafeCounter as a temporary variable only to use on the stack
47  * for operation
48  *
49  */
50 
51 #include <NodeBitmask.hpp>
52 #include "DLList.hpp"
53 #include "VMSignal.hpp"
54 
55 class SimulatedBlock;
56 
61  friend class SafeCounter;
62  friend class SafeCounterHandle;
63  friend class SimulatedBlock;
64 public:
66 
67  bool setSize(Uint32 maxNoOfActiveMutexes, bool exit_on_error = true);
68  Uint32 getSize() const ;
69  Uint32 getNoOfFree() const;
70 
71  void execNODE_FAILREP(Signal*);
72  void printNODE_FAILREP();
73 
74 private:
75  struct ActiveCounter {
76  public:
77  Uint32 m_senderData;
78  NdbNodeBitmask m_nodes;
79  struct SignalDesc {
80  public:
81  Uint16 m_gsn;
82  Uint16 m_block;
83  Uint8 m_senderRefOffset;
84  Uint8 m_senderDataOffset;
85  Uint8 m_errorCodeOffset;
86  Uint8 m_nodeFailErrorCode;
87  } m_signalDesc;
88  union {
89  Uint32 nextPool;
90  Uint32 nextList;
91  };
92  Uint32 prevList;
93  };
94 
95  typedef Ptr<ActiveCounter> ActiveCounterPtr;
96 
97  bool seize(ActiveCounterPtr& ptr);
98  void release(ActiveCounterPtr& ptr);
99  void getPtr(ActiveCounterPtr& ptr, Uint32 ptrI);
100 
101  SimulatedBlock & m_block;
102  ArrayPool<ActiveCounter> m_counterPool;
103  DLList<ActiveCounter> m_activeCounters;
104 
105  BlockReference reference() const;
106  void progError(int line, int err_code, const char* extra = 0);
107 };
108 
109 
111  friend class SafeCounter;
112 public:
114 
118  bool clearWaitingFor(SafeCounterManager& mgr, Uint32 nodeId);
119 
120  bool done() const;
121 
122 private:
123  Uint32 m_activeCounterPtrI;
124 };
125 
126 class SafeCounter {
127  friend class SafeCounterManager;
128 public:
130 
131  template<typename SignalClass>
132  bool init(Uint16 block, Uint16 GSN, Uint32 senderData);
133 
134  template<typename SignalClass>
135  bool init(NodeReceiverGroup rg, Uint16 GSN, Uint32 senderData);
136 
137  template<typename SignalClass>
138  bool init(NodeReceiverGroup rg, Uint32 senderData);
139 
140  ~SafeCounter();
141 
142  void clearWaitingFor();
143 
147  void setWaitingFor(Uint32 nodeId);
148  bool clearWaitingFor(Uint32 nodeId);
149  bool forceClearWaitingFor(Uint32 nodeId);
150 
151  bool isWaitingFor(Uint32 nodeId) const;
152  bool done() const;
153 
154  const char * getText() const; /* ? needed for, some portability issues */
155 
156  SafeCounter& operator=(const NdbNodeBitmask&);
157  SafeCounter& operator=(const NodeReceiverGroup&);
158 private:
159  Uint32 m_count;
160  NdbNodeBitmask m_nodes;
161 
162  SafeCounterManager & m_mgr;
164 
165  Uint32 & m_activeCounterPtrI;
166 };
167 
168 inline
169 SafeCounterHandle::SafeCounterHandle(){
170  m_activeCounterPtrI = RNIL;
171 }
172 
173 inline
174 bool
175 SafeCounterHandle::done() const {
176  return m_activeCounterPtrI == RNIL;
177 }
178 
179 inline
180 SafeCounter::SafeCounter(SafeCounterManager& mgr, SafeCounterHandle& handle)
181  : m_mgr(mgr),
182  m_activeCounterPtrI(handle.m_activeCounterPtrI)
183 {
184  m_ptr.i = handle.m_activeCounterPtrI;
185  if (m_ptr.i == RNIL) {
186  m_nodes.clear();
187  m_count = 0;
188  } else {
189  m_mgr.getPtr(m_ptr, m_ptr.i);
190  m_nodes = m_ptr.p->m_nodes;
191  m_count = m_nodes.count();
192  }
193 }
194 
195 template<typename Ref>
196 inline
197 bool
198 SafeCounter::init(Uint16 block, Uint16 GSN, Uint32 senderData){
199 
201  signalDesc.m_gsn = GSN;
202  signalDesc.m_block = block;
203  signalDesc.m_errorCodeOffset = offsetof(Ref, errorCode) >> 2;
204  signalDesc.m_senderRefOffset = offsetof(Ref, senderRef) >> 2;
205  signalDesc.m_senderDataOffset = offsetof(Ref, senderData) >> 2;
206  signalDesc.m_nodeFailErrorCode = Ref::NF_FakeErrorREF;
207  assert(((Uint32)Ref::NF_FakeErrorREF) < 256);
208 
209  if(m_ptr.i == RNIL){
211  if(m_mgr.seize(ptr)){
212  ptr.p->m_senderData = senderData;
213  ptr.p->m_signalDesc = signalDesc;
214  m_ptr = ptr;
215  return true;
216  }
217  return false;
218  }
219 
220  if(m_count == 0){
221  m_ptr.p->m_senderData = senderData;
222  m_ptr.p->m_signalDesc = signalDesc;
223  return true;
224  }
225 
226  ErrorReporter::handleAssert("SafeCounter::init twice", __FILE__, __LINE__);
227  return false;
228 }
229 
230 template<typename Ref>
231 inline
232 bool
233 SafeCounter::init(NodeReceiverGroup rg, Uint16 GSN, Uint32 senderData){
234 
235  if (init<Ref>(rg.m_block, GSN, senderData))
236  {
237  m_nodes = rg.m_nodes;
238  m_count = m_nodes.count();
239 
240  if (unlikely(m_count == 0))
241  {
242  ErrorReporter::handleAssert("SafeCounter::empty node list",
243  __FILE__, __LINE__);
244  }
245  return true;
246  }
247  return false;
248 }
249 
250 template<typename Ref>
251 inline
252 bool
253 SafeCounter::init(NodeReceiverGroup rg, Uint32 senderData)
254 {
255  if (init<Ref>(rg.m_block, Ref::GSN, senderData))
256  {
257  m_nodes = rg.m_nodes;
258  m_count = m_nodes.count();
259 
260  if (unlikely(m_count == 0))
261  {
262  ErrorReporter::handleAssert("SafeCounter::empty node list",
263  __FILE__, __LINE__);
264  }
265  return true;
266  }
267  return false;
268 }
269 
270 inline
271 void
273  if(!m_nodes.get(nodeId)){
274  m_nodes.set(nodeId);
275  m_count++;
276  return;
277  }
278  ErrorReporter::handleAssert("SafeCounter::set", __FILE__, __LINE__);
279 }
280 
281 inline
282 bool
283 SafeCounter::isWaitingFor(Uint32 nodeId) const {
284  return m_nodes.get(nodeId);
285 }
286 
287 inline
288 bool
289 SafeCounter::done() const {
290  return m_count == 0;
291 }
292 
293 inline
294 bool
295 SafeCounter::clearWaitingFor(Uint32 nodeId) {
296  if(m_count > 0 && m_nodes.get(nodeId)){
297  m_count--;
298  m_nodes.clear(nodeId);
299  return (m_count == 0);
300  }
301  ErrorReporter::handleAssert("SafeCounter::clear", __FILE__, __LINE__);
302  return false;
303 }
304 
305 inline
306 void
307 SafeCounter::clearWaitingFor(){
308  m_count = 0;
309  m_nodes.clear();
310 }
311 
312 inline
313 bool
314 SafeCounter::forceClearWaitingFor(Uint32 nodeId){
315  if(isWaitingFor(nodeId)){
316  return clearWaitingFor(nodeId);
317  }
318  return (m_count == 0);
319 }
320 
321 #endif