~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to storage/ndb/src/kernel/vm/SafeCounter.hpp

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

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