1
/* Copyright (C) 2003 MySQL AB
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.
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.
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 */
16
#ifndef __SAFE_COUNTER_HPP
17
#define __SAFE_COUNTER_HPP
19
/*************************************************************
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.
25
* init<SignalClass>(..., GSN, senderData);
27
* It is implemented so that one can replace SignalCounter with
28
* SafeCounter (SignalCounter should probably go away with time)
30
* clearWaitingFor(nodeId);
34
* If included in a new block method
35
* SafeCounterManager::execNODE_FAILREP must included in
36
* <block>::execNODE_FAILREP
38
* the SignalClass must have senderRef, senderData and errorCode
39
* and also ErrorCode::NF_FakeErrorREF, implemented
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
49
#include <NodeBitmask.hpp>
51
#include "VMSignal.hpp"
58
class SafeCounterManager {
59
friend class SafeCounter;
60
friend class SafeCounterHandle;
61
friend class SimulatedBlock;
63
SafeCounterManager(class SimulatedBlock &);
65
bool setSize(Uint32 maxNoOfActiveMutexes, bool exit_on_error = true);
66
Uint32 getSize() const ;
68
void execNODE_FAILREP(Signal*);
69
void printNODE_FAILREP();
72
struct ActiveCounter { /** sizeof = 7words = 28bytes */
80
Uint8 m_senderRefOffset;
81
Uint8 m_senderDataOffset;
82
Uint8 m_errorCodeOffset;
83
Uint8 m_nodeFailErrorCode;
92
typedef Ptr<ActiveCounter> ActiveCounterPtr;
94
bool seize(ActiveCounterPtr& ptr);
95
void release(ActiveCounterPtr& ptr);
96
void getPtr(ActiveCounterPtr& ptr, Uint32 ptrI);
98
SimulatedBlock & m_block;
99
ArrayPool<ActiveCounter> m_counterPool;
100
DLList<ActiveCounter> m_activeCounters;
102
BlockReference reference() const;
103
void progError(int line, int err_code, const char* extra = 0);
107
class SafeCounterHandle {
108
friend class SafeCounter;
113
* Return if done (no nodes set in bitmask)
115
bool clearWaitingFor(SafeCounterManager& mgr, Uint32 nodeId);
120
Uint32 m_activeCounterPtrI;
124
friend class SafeCounterManager;
126
SafeCounter(SafeCounterManager&, SafeCounterHandle&);
128
template<typename SignalClass>
129
bool init(Uint16 block, Uint16 GSN, Uint32 senderData);
131
template<typename SignalClass>
132
bool init(NodeReceiverGroup rg, Uint16 GSN, Uint32 senderData);
134
template<typename SignalClass>
135
bool init(NodeReceiverGroup rg, Uint32 senderData);
139
void clearWaitingFor();
142
* When sending to different node
144
void setWaitingFor(Uint32 nodeId);
145
bool clearWaitingFor(Uint32 nodeId);
146
bool forceClearWaitingFor(Uint32 nodeId);
148
bool isWaitingFor(Uint32 nodeId) const;
151
const char * getText() const; /* ? needed for, some portability issues */
153
SafeCounter& operator=(const NdbNodeBitmask&);
154
SafeCounter& operator=(const NodeReceiverGroup&);
159
SafeCounterManager & m_mgr;
160
SafeCounterManager::ActiveCounterPtr m_ptr;
162
Uint32 & m_activeCounterPtrI;
166
SafeCounterHandle::SafeCounterHandle(){
167
m_activeCounterPtrI = RNIL;
172
SafeCounterHandle::done() const {
173
return m_activeCounterPtrI == RNIL;
177
SafeCounter::SafeCounter(SafeCounterManager& mgr, SafeCounterHandle& handle)
179
m_activeCounterPtrI(handle.m_activeCounterPtrI)
181
m_ptr.i = handle.m_activeCounterPtrI;
182
if (m_ptr.i == RNIL) {
186
m_mgr.getPtr(m_ptr, m_ptr.i);
187
m_nodes = m_ptr.p->m_nodes;
188
m_count = m_nodes.count();
192
template<typename Ref>
195
SafeCounter::init(Uint16 block, Uint16 GSN, Uint32 senderData){
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);
207
SafeCounterManager::ActiveCounterPtr ptr;
208
if(m_mgr.seize(ptr)){
209
ptr.p->m_senderData = senderData;
210
ptr.p->m_signalDesc = signalDesc;
218
m_ptr.p->m_senderData = senderData;
219
m_ptr.p->m_signalDesc = signalDesc;
223
ErrorReporter::handleAssert("SafeCounter::init twice", __FILE__, __LINE__);
227
template<typename Ref>
230
SafeCounter::init(NodeReceiverGroup rg, Uint16 GSN, Uint32 senderData){
232
if (init<Ref>(rg.m_block, GSN, senderData))
234
m_nodes = rg.m_nodes;
235
m_count = m_nodes.count();
241
template<typename Ref>
244
SafeCounter::init(NodeReceiverGroup rg, Uint32 senderData){
246
if (init<Ref>(rg.m_block, Ref::GSN, senderData))
248
m_nodes = rg.m_nodes;
249
m_count = m_nodes.count();
257
SafeCounter::setWaitingFor(Uint32 nodeId) {
258
if(!m_nodes.get(nodeId)){
263
ErrorReporter::handleAssert("SafeCounter::set", __FILE__, __LINE__);
268
SafeCounter::isWaitingFor(Uint32 nodeId) const {
269
return m_nodes.get(nodeId);
274
SafeCounter::done() const {
280
SafeCounter::clearWaitingFor(Uint32 nodeId) {
281
if(m_count > 0 && m_nodes.get(nodeId)){
283
m_nodes.clear(nodeId);
284
return (m_count == 0);
286
ErrorReporter::handleAssert("SafeCounter::clear", __FILE__, __LINE__);
292
SafeCounter::clearWaitingFor(){
299
SafeCounter::forceClearWaitingFor(Uint32 nodeId){
300
if(isWaitingFor(nodeId)){
301
return clearWaitingFor(nodeId);
303
return (m_count == 0);