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, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #ifndef NODE_STATE_HPP
26 #define NODE_STATE_HPP
27 
28 #include <NdbOut.hpp>
29 #include <NodeBitmask.hpp>
30 
31 struct NodeStatePOD
32 {
33   enum StartLevel {
34     /**
35      * SL_NOTHING
36      *   Nothing is started
37      */
38     SL_NOTHING    = 0,
39 
40     /**
41      * SL_CMVMI
42      *   CMVMI is started
43      *   Listening to management server
44      *   Qmgr knows nothing...
45      */
46     SL_CMVMI = 1,
47 
48     /**
49      * SL_STARTING
50      *   All blocks are starting
51      *   Initial or restart
52      *   During this phase is <b>startPhase</b> valid
53      */
54     SL_STARTING = 2,
55 
56     /**
57      * The database is started open for connections
58      */
59     SL_STARTED = 3,
60 
61     SL_SINGLEUSER = 4,
62 
63     /**
64      * SL_STOPPING_1 - Inform API
65      *   API is informed not to start transactions on node
66      *	 The database is about to close
67      *
68      *   New TcSeize(s) are refused (TcSeizeRef)
69      */
70     SL_STOPPING_1 = 5,
71 
72     /**
73      * SL_STOPPING_2 - Close TC
74      *   New transactions(TC) are refused
75      */
76     SL_STOPPING_2 = 6,
77 
78 
79 
80 
81     /**
82      * SL_STOPPING_3 - Wait for reads in LQH
83      *   No transactions are running in TC
84      *   New scans(s) and read(s) are refused in LQH
85      *   NS: The node is not Primary for any fragment
86      *   NS: No node is allow to start
87      */
88     SL_STOPPING_3 = 7,
89 
90     /**
91      * SL_STOPPING_4 - Close LQH
92      *   Node is out of DIGETNODES
93      *   Insert/Update/Delete can still be running in LQH
94      *   GCP is refused
95      *   Node is not startable w.o Node Recovery
96      */
97     SL_STOPPING_4 = 8
98   };
99 
100   enum StartType {
101     ST_INITIAL_START = 0,
102     ST_SYSTEM_RESTART = 1,
103     ST_NODE_RESTART = 2,
104     ST_INITIAL_NODE_RESTART = 3,
105     ST_ILLEGAL_TYPE = 4
106   };
107 
108   /**
109    * Length in 32-bit words
110    */
111   STATIC_CONST( DataLength = 8 + NodeBitmask::Size );
112 
113   /**
114    * Constructor(s)
115    */
116   void init();
117 
118   /**
119    * Current start level
120    */
121   Uint32 startLevel;
122 
123   /**
124    * Node group
125    */
126   Uint32 nodeGroup;  // valid when startLevel == SL_STARTING
127 
128   /**
129    * Dynamic id
130    */
131   union {
132     Uint32 dynamicId;    // valid when startLevel == SL_STARTING to API
133     Uint32 masterNodeId; // When from cntr
134   };
135 
136   /**
137    *
138    */
139   union {
140     struct {
141       Uint32 startPhase;     // valid when startLevel == SL_STARTING
142       Uint32 restartType;    // valid when startLevel == SL_STARTING
143     } starting;
144     struct {
145       Uint32 systemShutdown; // valid when startLevel == SL_STOPPING_{X}
146       Uint32 timeout;
147       Uint32 alarmTime;
148     } stopping;
149 
150 
151   };
152   Uint32 singleUserMode;
153   Uint32 singleUserApi;          //the single user node
154 
155   BitmaskPOD<NodeBitmask::Size> m_connected_nodes;
156 
157   void setDynamicId(Uint32 dynamic);
158   void setNodeGroup(Uint32 group);
159   void setSingleUser(Uint32 s);
160   void setSingleUserApi(Uint32 n);
161 
162 
163   /**
164    * Is a node restart in progress (ordinary or initial)
165    */
166   bool getNodeRestartInProgress() const;
167 
168   /**
169    * Is a system restart ongoing
170    */
171   bool getSystemRestartInProgress() const;
172 
173   /**
174    * Are we started
175    */
getStartedNodeStatePOD176   bool getStarted() const {
177     return startLevel == SL_STARTED || startLevel == SL_SINGLEUSER;
178   }
179 
180   /**
181    * Is in single user mode?
182    */
183   bool getSingleUserMode() const;
184 
185   /**
186    * Is in single user mode
187    */
188   Uint32 getSingleUserApi() const;
189 };
190 
191 class NodeState : public NodeStatePOD
192 {
193 public:
194   NodeState();
195   NodeState(StartLevel);
196   NodeState(StartLevel, bool systemShutdown);
197   NodeState(StartLevel, Uint32 startPhase, StartType);
198 
199   NodeState& operator=(const NodeStatePOD&);
200 };
201 
202 inline
NodeState()203 NodeState::NodeState(){
204   init();
205 }
206 
207 inline
208 void
init()209 NodeStatePOD::init(){
210   startLevel = SL_CMVMI;
211   nodeGroup = 0xFFFFFFFF;
212   dynamicId = 0xFFFFFFFF;
213   singleUserMode = 0;
214   singleUserApi = 0xFFFFFFFF;
215   m_connected_nodes.clear();
216 }
217 
218 inline
NodeState(StartLevel sl)219 NodeState::NodeState(StartLevel sl){
220   init();
221   startLevel = sl;
222   singleUserMode = 0;
223   singleUserApi = 0xFFFFFFFF;
224 }
225 
226 inline
NodeState(StartLevel sl,Uint32 sp,StartType typeOfStart)227 NodeState::NodeState(StartLevel sl, Uint32 sp, StartType typeOfStart){
228   init();
229   startLevel = sl;
230   starting.startPhase = sp;
231   starting.restartType = typeOfStart;
232   singleUserMode = 0;
233   singleUserApi = 0xFFFFFFFF;
234 }
235 
236 inline
NodeState(StartLevel sl,bool sys)237 NodeState::NodeState(StartLevel sl, bool sys){
238   init();
239   startLevel = sl;
240   stopping.systemShutdown = sys;
241   singleUserMode = 0;
242   singleUserApi = 0xFFFFFFFF;
243 }
244 
245 inline
setDynamicId(Uint32 dynamic)246 void NodeStatePOD::setDynamicId(Uint32 dynamic){
247   dynamicId = dynamic;
248 }
249 
250 inline
setNodeGroup(Uint32 group)251 void NodeStatePOD::setNodeGroup(Uint32 group){
252   nodeGroup = group;
253 }
254 
255 inline
setSingleUser(Uint32 s)256 void NodeStatePOD::setSingleUser(Uint32 s) {
257   singleUserMode = s;
258 }
259 
260 inline
setSingleUserApi(Uint32 n)261 void NodeStatePOD::setSingleUserApi(Uint32 n) {
262   singleUserApi = n;
263 }
264 inline
getNodeRestartInProgress() const265 bool NodeStatePOD::getNodeRestartInProgress() const {
266   return startLevel == SL_STARTING &&
267     (starting.restartType == ST_NODE_RESTART ||
268      starting.restartType == ST_INITIAL_NODE_RESTART);
269 }
270 
271 inline
getSingleUserMode() const272 bool NodeStatePOD::getSingleUserMode() const {
273   return singleUserMode;
274 }
275 
276 inline
getSingleUserApi() const277 Uint32 NodeStatePOD::getSingleUserApi() const {
278   return singleUserApi;
279 }
280 
281 inline
getSystemRestartInProgress() const282 bool NodeStatePOD::getSystemRestartInProgress() const {
283   return startLevel == SL_STARTING && starting.restartType == ST_SYSTEM_RESTART;
284 }
285 
286 inline
287 NdbOut &
operator <<(NdbOut & ndbout,const NodeStatePOD & state)288 operator<<(NdbOut& ndbout, const NodeStatePOD & state){
289   ndbout << "[NodeState: startLevel: ";
290   switch(state.startLevel){
291   case NodeState::SL_NOTHING:
292     ndbout << "<NOTHING> ]";
293     break;
294   case NodeState::SL_CMVMI:
295     ndbout << "<CMVMI> ]";
296     break;
297   case NodeState::SL_STARTING:
298     ndbout << "<STARTING type: ";
299     switch(state.starting.restartType){
300     case NodeState::ST_INITIAL_START:
301       ndbout << " INITIAL START";
302       break;
303     case NodeState::ST_SYSTEM_RESTART:
304       ndbout << " SYSTEM RESTART ";
305       break;
306     case NodeState::ST_NODE_RESTART:
307       ndbout << " NODE RESTART ";
308       break;
309     case NodeState::ST_INITIAL_NODE_RESTART:
310       ndbout << " INITIAL NODE RESTART ";
311       break;
312     case NodeState::ST_ILLEGAL_TYPE:
313     default:
314       ndbout << " UNKNOWN " << state.starting.restartType;
315     }
316     ndbout << " phase: " << state.starting.startPhase << "> ]";
317     break;
318   case NodeState::SL_STARTED:
319     ndbout << "<STARTED> ]";
320     break;
321   case NodeState::SL_STOPPING_1:
322     ndbout << "<STOPPING 1 sys: " << state.stopping.systemShutdown << "> ]";
323     break;
324   case NodeState::SL_STOPPING_2:
325     ndbout << "<STOPPING 2 sys: " << state.stopping.systemShutdown << "> ]";
326     break;
327   case NodeState::SL_STOPPING_3:
328     ndbout << "<STOPPING 3 sys: " << state.stopping.systemShutdown << "> ]";
329     break;
330   case NodeState::SL_STOPPING_4:
331     ndbout << "<STOPPING 4 sys: " << state.stopping.systemShutdown << "> ]";
332     break;
333   default:
334     ndbout << "<UNKNOWN " << state.startLevel << "> ]";
335   }
336   return ndbout;
337 }
338 
339 inline
340 NodeState&
operator =(const NodeStatePOD & ns)341 NodeState::operator=(const NodeStatePOD& ns)
342 {
343   startLevel = ns.startLevel;
344   nodeGroup  = ns.nodeGroup;
345   dynamicId  = ns.dynamicId;
346   // masterNodeId is union with dynamicId
347   starting.startPhase = ns.starting.startPhase;
348   starting.restartType = ns.starting.restartType;
349   // stopping.systemShutdown is union with starting.startPhase
350   // stopping.timeout is union with starting.restartType
351   stopping.alarmTime = ns.stopping.alarmTime;
352   singleUserMode = ns.singleUserMode;
353   singleUserApi  = ns.singleUserApi;
354   m_connected_nodes.assign(ns.m_connected_nodes);
355   return * this;
356 }
357 #endif
358