1 /*
2    Copyright (c) 2004, 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 NDB_GLOBAL_H
26 #define NDB_GLOBAL_H
27 
28 #ifdef _WIN32
29 /* Workaround for Bug#32082: VOID refdefinition results in compile errors */
30 #ifndef DONT_DEFINE_VOID
31 #define DONT_DEFINE_VOID
32 #endif
33 #endif
34 
35 #include <my_global.h>
36 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39 #ifdef HAVE_SYS_TIME_H
40 #include <sys/time.h>
41 #endif
42 #ifdef _WIN32
43 #include <process.h>
44 #endif
45 
46 #if defined __GNUC__
47 # define ATTRIBUTE_FORMAT(style, m, n) __attribute__((format(style, m, n)))
48 #else
49 # define ATTRIBUTE_FORMAT(style, m, n)
50 #endif
51 
52 #ifdef HAVE_NDB_CONFIG_H
53 #include "ndb_config.h"
54 #endif
55 
56 #include <mysql_com.h>
57 #include <ndb_types.h>
58 
59 #ifndef NDB_PORT
60 /* Default port used by ndb_mgmd */
61 #define NDB_PORT 1186
62 #endif
63 
64 #if defined(_WIN32)
65 #define NDB_WIN32 1
66 #define NDB_WIN 1
67 #define PATH_MAX 256
68 #define DIR_SEPARATOR "\\"
69 
70 /* Disable a few compiler warnings on Windows */
71 /* 4355: 'this': used in base member initializer list */
72 #pragma warning(disable: 4355)
73 
74 #else
75 #undef NDB_WIN32
76 #undef NDB_WIN
77 #define DIR_SEPARATOR "/"
78 #endif
79 
80 #if ! (NDB_SIZEOF_CHAR == SIZEOF_CHAR)
81 #error "Invalid define for Uint8"
82 #endif
83 
84 #if ! (NDB_SIZEOF_INT == SIZEOF_INT)
85 #error "Invalid define for Uint32"
86 #endif
87 
88 #if ! (NDB_SIZEOF_LONG_LONG == SIZEOF_LONG_LONG)
89 #error "Invalid define for Uint64"
90 #endif
91 
92 #include <signal.h>
93 
94 #ifdef _AIX
95 #undef _H_STRINGS
96 #endif
97 #include <m_string.h>
98 
99 #ifndef NDB_REMOVE_BZERO
100 /*
101   Make it possible to use bzero in NDB although
102   MySQL headers redefines it to an invalid symbol
103 */
104 #ifdef bzero
105 #undef bzero
106 #endif
107 
108 #ifdef HAVE_STRINGS_H
109 #include <strings.h>
110 #endif
111 
112 #if !defined(bzero) && !defined(HAVE_BZERO)
113 #define bzero(A,B) memset((A),0,(B))
114 #endif
115 #endif
116 
117 #include <m_ctype.h>
118 #include <ctype.h>
119 
120 #ifdef HAVE_STDARG_H
121 #include <stdarg.h>
122 #endif
123 
124 #ifdef TIME_WITH_SYS_TIME
125 #include <time.h>
126 #endif
127 
128 #ifdef HAVE_FCNTL_H
129 #include <fcntl.h>
130 #endif
131 
132 #include <sys/stat.h>
133 
134 #ifdef HAVE_SYS_PARAM_H
135 #include <sys/param.h>
136 #endif
137 
138 #ifdef HAVE_SYS_RESOURCE_H
139 #include <sys/resource.h>
140 #endif
141 
142 #ifdef HAVE_SYS_WAIT_H
143 #include <sys/wait.h>
144 #endif
145 
146 #ifdef HAVE_SYS_MMAN_H
147 #include <sys/mman.h>
148 #endif
149 
150 #ifndef HAVE_STRDUP
151 extern char * strdup(const char *s);
152 #endif
153 
154 static const char table_name_separator =  '/';
155 
156 #if defined(_AIX) || defined(WIN32) || defined(NDB_VC98)
157 #define STATIC_CONST(x) enum { x }
158 #else
159 #define STATIC_CONST(x) static const Uint32 x
160 #endif
161 
162 #ifdef  __cplusplus
163 extern "C" {
164 #endif
165 
166 #include <assert.h>
167 
168 #ifdef  __cplusplus
169 }
170 #endif
171 
172 #include "ndb_init.h"
173 
174 #ifndef PATH_MAX
175 #define PATH_MAX 1024
176 #endif
177 
178 #ifndef MIN
179 #define MIN(x,y) (((x)<(y))?(x):(y))
180 #endif
181 
182 #ifndef MAX
183 #define MAX(x,y) (((x)>(y))?(x):(y))
184 #endif
185 
186 /*
187   Dont allow use of min() or max() macros
188    - in order to enforce forward compatibilty
189 */
190 
191 #ifdef min
192 #undef min
193 #endif
194 
195 #ifdef max
196 #undef max
197 #endif
198 
199 #define NDB_O_DIRECT_WRITE_ALIGNMENT 512
200 
201 #ifndef STATIC_ASSERT
202 #if defined VM_TRACE
203 /**
204  * Compile-time assert for use from procedure body
205  * Zero length array not allowed in C
206  * Add use of array to avoid compiler warning
207  */
208 #define STATIC_ASSERT(expr) { char a_static_assert[(expr)? 1 : 0] = {'\0'}; if (a_static_assert[0]) {}; }
209 #else
210 #define STATIC_ASSERT(expr)
211 #endif
212 #endif
213 
214 #define NDB_ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
215 
216 
217 /*
218   NDB_STATIC_ASSERT(expr)
219    - Check coding assumptions during compile time
220      by laying out code that will generate a compiler error
221      if the expression is false.
222 */
223 
224 #if (_MSC_VER > 1500) || (defined __GXX_EXPERIMENTAL_CXX0X__)
225 
226 /*
227   Prefer to use the 'static_assert' function from C++0x
228   to get best error message
229 */
230 #define NDB_STATIC_ASSERT(expr) static_assert(expr, #expr)
231 
232 #else
233 
234 /*
235   Fallback to use home grown solution
236   (i.e use mysys version)
237 */
238 
239 #define NDB_STATIC_ASSERT(expr) compile_time_assert(expr)
240 
241 #endif
242 
243 
244 #if (_MSC_VER > 1500)
245 #define HAVE___HAS_TRIVIAL_CONSTRUCTOR
246 #define HAVE___IS_POD
247 #endif
248 
249 #ifdef HAVE___HAS_TRIVIAL_CONSTRUCTOR
250 #define ASSERT_TYPE_HAS_CONSTRUCTOR(x)     \
251   NDB_STATIC_ASSERT(!__has_trivial_constructor(x))
252 #else
253 #define ASSERT_TYPE_HAS_CONSTRUCTOR(x)
254 #endif
255 
256 /**
257  * visual studio is stricter than gcc for __is_pod, settle for __has_trivial_constructor
258  *  until we really really made all signal data classes POD
259  *
260  * UPDATE: also gcc fails to compile our code with gcc4.4.3
261  */
262 #ifdef HAVE___HAS_TRIVIAL_CONSTRUCTOR
263 #define NDB_ASSERT_POD(x) \
264   NDB_STATIC_ASSERT(__has_trivial_constructor(x))
265 #else
266 #define NDB_ASSERT_POD(x)
267 #endif
268 
269 /**
270  *  __attribute__((noreturn)) was introduce in gcc 2.5
271  */
272 #if (GCC_VERSION >= 2005)
273 #define ATTRIBUTE_NORETURN __attribute__((noreturn))
274 #else
275 #define ATTRIBUTE_NORETURN
276 #endif
277 
278 /**
279  *  __attribute__((noinline)) was introduce in gcc 3.1
280  */
281 #if (GCC_VERSION >= 3001)
282 #define ATTRIBUTE_NOINLINE __attribute__((noinline))
283 #else
284 #define ATTRIBUTE_NOINLINE
285 #endif
286 
287 /**
288  * sizeof cacheline (in bytes)
289  *
290  * TODO: Add configure check...
291  */
292 #define NDB_CL 64
293 
294 /**
295  * Pad to NDB_CL size
296  */
297 #define NDB_CL_PADSZ(x) (NDB_CL - ((x) % NDB_CL))
298 
299 /*
300  * require is like a normal assert, only it's always on (eg. in release)
301  */
302 C_MODE_START
303 /** see below */
304 typedef int(*RequirePrinter)(const char *fmt, ...);
305 void require_failed(int exitcode, RequirePrinter p,
306                     const char* expr, const char* file, int line)
307                     ATTRIBUTE_NORETURN;
308 int ndbout_printer(const char * fmt, ...);
309 C_MODE_END
310 /*
311  *  this allows for an exit() call if exitcode is not zero
312  *  and takes a Printer to print the error
313  */
314 #define require_exit_or_core_with_printer(v, exitcode, printer) \
315   do { if (likely(!(!(v)))) break;                                    \
316        require_failed((exitcode), (printer), #v, __FILE__, __LINE__); \
317   } while (0)
318 
319 /*
320  *  this allows for an exit() call if exitcode is not zero
321 */
322 #define require_exit_or_core(v, exitcode) \
323        require_exit_or_core_with_printer((v), (exitcode), 0)
324 
325 /*
326  * this require is like a normal assert.  (only it's always on)
327 */
328 #define require(v) require_exit_or_core_with_printer((v), 0, 0)
329 
330 struct LinearSectionPtr
331 {
332   Uint32 sz;
333   Uint32 * p;
334 };
335 
336 struct SegmentedSectionPtrPOD
337 {
338   Uint32 sz;
339   Uint32 i;
340   struct SectionSegment * p;
341 
342 #ifdef __cplusplus
setNullSegmentedSectionPtrPOD343   void setNull() { p = 0;}
isNullSegmentedSectionPtrPOD344   bool isNull() const { return p == 0;}
345   inline SegmentedSectionPtrPOD& assign(struct SegmentedSectionPtr&);
346 #endif
347 };
348 
349 struct SegmentedSectionPtr
350 {
351   Uint32 sz;
352   Uint32 i;
353   struct SectionSegment * p;
354 
355 #ifdef __cplusplus
SegmentedSectionPtrSegmentedSectionPtr356   SegmentedSectionPtr() {}
SegmentedSectionPtrSegmentedSectionPtr357   SegmentedSectionPtr(Uint32 sz_arg, Uint32 i_arg,
358                       struct SectionSegment *p_arg)
359     :sz(sz_arg), i(i_arg), p(p_arg)
360   {}
SegmentedSectionPtrSegmentedSectionPtr361   SegmentedSectionPtr(const SegmentedSectionPtrPOD & src)
362     :sz(src.sz), i(src.i), p(src.p)
363   {}
364 
setNullSegmentedSectionPtr365   void setNull() { p = 0;}
isNullSegmentedSectionPtr366   bool isNull() const { return p == 0;}
367 #endif
368 };
369 
370 #ifdef __cplusplus
371 inline
372 SegmentedSectionPtrPOD&
assign(struct SegmentedSectionPtr & src)373 SegmentedSectionPtrPOD::assign(struct SegmentedSectionPtr& src)
374 {
375   this->i = src.i;
376   this->p = src.p;
377   this->sz = src.sz;
378   return *this;
379 }
380 #endif
381 
382 /* Abstract interface for iterating over
383  * words in a section
384  */
385 #ifdef __cplusplus
386 struct GenericSectionIterator
387 {
~GenericSectionIteratorGenericSectionIterator388   virtual ~GenericSectionIterator() {};
389   virtual void reset()=0;
390   virtual const Uint32* getNextWords(Uint32& sz)=0;
391 };
392 #else
393 struct GenericSectionIterator;
394 #endif
395 
396 struct GenericSectionPtr
397 {
398   Uint32 sz;
399   struct GenericSectionIterator* sectionIter;
400 };
401 
402 #endif
403