1 /*
2    Copyright (c) 2003, 2021, Oracle and/or its affiliates.
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 ARBIT_SIGNAL_DATA_H
26 #define ARBIT_SIGNAL_DATA_H
27 
28 #include <string.h>
29 #include <NodeBitmask.hpp>
30 #include <NdbTick.h>
31 #include <NdbHost.h>
32 #include "SignalData.hpp"
33 #include "SignalDataPrint.hpp"
34 
35 #define JAM_FILE_ID 23
36 
37 
38 /**
39  * The ticket.
40  */
41 class ArbitTicket {
42 private:
43   Uint32 data[2];
44 
45 public:
46   STATIC_CONST( DataLength = 2 );
47   STATIC_CONST( TextLength = DataLength * 8 );  // hex digits
48 
clear()49   inline void clear() {
50     data[0] = 0;
51     data[1] = 0;
52   }
53 
update()54   inline void update() {
55     Uint16 cnt = data[0] & 0xFFFF;              // previous count
56     Uint16 pid = NdbHost_GetProcessId();
57     data[0] = (pid << 16) | (cnt + 1);
58     data[1] = (Uint32)NdbTick_CurrentMillisecond();
59   }
60 
match(ArbitTicket & aTicket) const61   inline bool match(ArbitTicket& aTicket) const {
62     return
63       data[0] == aTicket.data[0] &&
64       data[1] == aTicket.data[1];
65   }
66 
getText(char * buf,size_t buf_len) const67   inline void getText(char *buf, size_t buf_len) const {
68     BaseString::snprintf(buf, buf_len, "%08x%08x", data[0], data[1]);
69   }
70 
71 /*  inline char* getText() const {
72     static char buf[TextLength + 1];
73     getText(buf, sizeof(buf));
74     return buf;
75   } */
76 };
77 
78 /**
79  * Result codes.  Part of signal data.  Each signal uses only
80  * a subset but a common namespace is convenient.
81  */
82 class ArbitCode {
83 public:
84   STATIC_CONST( ErrTextLength = 80 );
85 
86   enum {
87     NoInfo = 0,
88 
89     // CFG signals
90     CfgRank1 = 1,               // these have to be 1 and 2
91     CfgRank2 = 2,
92 
93     // QMGR continueB thread state
94     ThreadStart = 11,           // continueB thread started
95 
96     // PREP signals
97     PrepPart1 = 21,             // zero old ticket
98     PrepPart2 = 22,             // get new ticket
99     PrepAtrun = 23,             // late joiner gets ticket at RUN time
100 
101     // arbitrator state
102     ApiStart = 31,              // arbitrator thread started
103     ApiFail = 32,               // arbitrator died
104     ApiExit = 33,               // arbitrator reported it will exit
105 
106     // arbitration result
107     LoseNodes = 41,             // lose on ndb node count
108     WinNodes = 42,              // win on ndb node count
109     WinGroups = 43,             // we win, no need for arbitration
110     LoseGroups = 44,            // we lose, missing node group
111     Partitioning = 45,          // possible network partitioning
112     WinChoose = 46,             // positive reply
113     LoseChoose = 47,            // negative reply
114     LoseNorun = 48,             // arbitrator required but not running
115     LoseNocfg = 49,             // arbitrator required but none configured
116     WinWaitExternal = 50,       // continue after external arbitration wait
117 
118     // general error codes
119     ErrTicket = 91,             // invalid arbitrator-ticket
120     ErrToomany = 92,            // too many requests
121     ErrState = 93,              // invalid state
122     ErrTimeout = 94,            // timeout waiting for signals
123     ErrUnknown = 95             // unknown error
124   };
125 
getErrText(Uint32 code,char * buf,size_t buf_len)126   static inline void getErrText(Uint32 code, char* buf, size_t buf_len) {
127     switch (code) {
128     case ErrTicket:
129       BaseString::snprintf(buf, buf_len, "invalid arbitrator-ticket");
130       break;
131     case ErrToomany:
132       BaseString::snprintf(buf, buf_len, "too many requests");
133       break;
134     case ErrState:
135       BaseString::snprintf(buf, buf_len, "invalid state");
136       break;
137     case ErrTimeout:
138       BaseString::snprintf(buf, buf_len, "timeout");
139       break;
140     default:
141       BaseString::snprintf(buf, buf_len, "unknown error [code=%u]", code);
142       break;
143     }
144   }
145 };
146 
147 /**
148  * Common class for arbitration signal data.
149  */
150 class ArbitSignalData {
151 public:
152   Uint32 sender;                // sender's node id (must be word 0)
153   Uint32 code;                  // result code or other info
154   Uint32 node;                  // arbitrator node id
155   ArbitTicket ticket;           // ticket
156   NodeBitmaskPOD mask;          // set of nodes
157 
158   STATIC_CONST( SignalLength = 3 + ArbitTicket::DataLength + NodeBitmask::Size );
159 
match(ArbitSignalData & aData) const160   inline bool match(ArbitSignalData& aData) const {
161     return
162       node == aData.node &&
163       ticket.match(aData.ticket);
164   }
165 };
166 
167 
168 #undef JAM_FILE_ID
169 
170 #endif
171