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 PC_H
26 #define PC_H
27 
28 
29 #include "Emulator.hpp"
30 #include <NdbOut.hpp>
31 #include <ndb_limits.h>
32 #include <NdbThread.h>
33 
34 #define JAM_FILE_ID 282
35 
36 
37 #ifdef NO_EMULATED_JAM
38 
39 #define jam()
40 #define jamLine(line)
41 #define jamEntry()
42 #define jamEntryLine(line)
43 #define jamBlock(block)
44 #define jamBlockLine(block, line)
45 #define jamEntryBlock(block)
46 #define jamEntryBlockLine(block, line)
47 #define jamNoBlock()
48 #define jamNoBlockLine(line)
49 #define thrjamEntry(buf)
50 #define thrjamEntryLine(buf, line)
51 #define thrjam(buf)
52 #define thrjamLine(buf, line)
53 
54 #else
55 
56 #define thrjamEntryBlockLine(jamBufferArg, blockNo, line) \
57   thrjamLine(jamBufferArg, line)
58 
59 /**
60  * Make an entry in the jamBuffer to record that execution reached a given
61  * point in the source code. For a description of how to maintain and debug
62  * JAM_FILE_IDs, please refer to the comments for jamFileNames in Emulator.cpp.
63  */
64 #define thrjamLine(jamBufferArg, line) \
65   do { \
66     EmulatedJamBuffer* const jamBuffer = jamBufferArg; \
67     Uint32 jamIndex = jamBuffer->theEmulatedJamIndex; \
68     jamBuffer->theEmulatedJam[jamIndex++] = JamEvent((JAM_FILE_ID), (line)); \
69     jamBuffer->theEmulatedJamIndex = jamIndex & JAM_MASK; \
70     /* Occasionally check that the jam buffer belongs to this thread.*/ \
71     assert((jamIndex & 3) != 0 || \
72            jamBuffer == NdbThread_GetTlsKey(NDB_THREAD_TLS_JAM));       \
73     /* Occasionally check that jamFileNames[JAM_FILE_ID] matches __FILE__.*/ \
74     assert((jamIndex & 0xff) != 0 ||                     \
75            JamEvent::verifyId((JAM_FILE_ID), __FILE__)); \
76   } while(0)
77 
78 #define jamBlockLine(block, line) thrjamLine(block->jamBuffer(), line)
79 #define jamBlock(block) jamBlockLine((block), __LINE__)
80 #define jamLine(line) jamBlockLine(this, (line))
81 #define jam() jamLine(__LINE__)
82 #define jamBlockEntryLine(block, line) \
83   thrjamEntryBlockLine(block->jamBuffer(), block->number(), line)
84 #define jamEntryBlock(block) jamEntryBlockLine(block, __LINE__)
85 #define jamEntryLine(line) jamBlockEntryLine(this, (line))
86 #define jamEntry() jamEntryLine(__LINE__)
87 
88 #define jamNoBlockLine(line) \
89     thrjamLine((EmulatedJamBuffer *)NdbThread_GetTlsKey(NDB_THREAD_TLS_JAM), \
90                (line))
91 #define jamNoBlock() jamNoBlockLine(__LINE__)
92 
93 #define thrjamEntryLine(buf, line) thrjamEntryBlockLine(buf, number(), line)
94 
95 #define thrjam(buf) thrjamLine(buf, __LINE__)
96 #define thrjamEntry(buf) thrjamEntryLine(buf, __LINE__)
97 
98 #endif
99 
100 #ifndef NDB_OPT
101 #define ptrCheck(ptr, limit, rec) if (ptr.i < (limit)) ptr.p = &rec[ptr.i]; else ptr.p = NULL
102 
103 /**
104  * Sets the p-value of a ptr-struct to be a pointer to record no i
105  * (where i is the i-value of the ptr-struct)
106  *
107  * @param ptr    ptr-struct with a set i-value  (the p-value in this gets set)
108  * @param limit  max no of records in rec
109  * @param rec    pointer to first record in an array of records
110  */
111 #define ptrCheckGuardErr(ptr, limit, rec, error) {\
112   UintR TxxzLimit; \
113   TxxzLimit = (limit); \
114   UintR TxxxPtr; \
115   TxxxPtr = ptr.i; \
116   ptr.p = &rec[TxxxPtr]; \
117   if (TxxxPtr < (TxxzLimit)) { \
118     ; \
119   } else { \
120     progError(__LINE__, error, __FILE__); \
121   }}
122 #define ptrAss(ptr, rec) ptr.p = &rec[ptr.i]
123 #define ptrNull(ptr) ptr.p = NULL
124 #define ptrGuardErr(ptr, error) if (ptr.p == NULL) \
125     progError(__LINE__, error, __FILE__)
126 #define arrGuardErr(ind, size, error) if ((ind) >= (size)) \
127     progError(__LINE__, error, __FILE__)
128 #else
129 #define ptrCheck(ptr, limit, rec) ptr.p = &rec[ptr.i]
130 #define ptrCheckGuardErr(ptr, limit, rec, error) ptr.p = &rec[ptr.i]
131 #define ptrAss(ptr, rec) ptr.p = &rec[ptr.i]
132 #define ptrNull(ptr) ptr.p = NULL
133 #define ptrGuardErr(ptr, error)
134 #define arrGuardErr(ind, size, error)
135 #endif
136 
137 #define ptrCheckGuard(ptr, limit, rec) \
138   ptrCheckGuardErr(ptr, limit, rec, NDBD_EXIT_POINTER_NOTINRANGE)
139 #define ptrGuard(ptr) ptrGuardErr(ptr, NDBD_EXIT_POINTER_NOTINRANGE)
140 #define arrGuard(ind, size) arrGuardErr(ind, size, NDBD_EXIT_INDEX_NOTINRANGE)
141 
142 // -------- ERROR INSERT MACROS -------
143 #ifdef ERROR_INSERT
144 #define ERROR_INSERT_VARIABLE mutable UintR cerrorInsert, c_error_insert_extra
145 #define ERROR_INSERTED(x) (cerrorInsert == (x))
146 #define ERROR_INSERTED_CLEAR(x) (cerrorInsert == (x) ? (cerrorInsert = 0, true) : false)
147 #define ERROR_INSERT_VALUE cerrorInsert
148 #define ERROR_INSERT_EXTRA c_error_insert_extra
149 #define SET_ERROR_INSERT_VALUE(x) cerrorInsert = x
150 #define SET_ERROR_INSERT_VALUE2(x,y) cerrorInsert = x; c_error_insert_extra = y
151 #define CLEAR_ERROR_INSERT_VALUE cerrorInsert = 0
152 #else
153 #define ERROR_INSERT_VARIABLE typedef void * cerrorInsert // Will generate compiler error if used
154 #define ERROR_INSERTED(x) false
155 #define ERROR_INSERTED_CLEAR(x) false
156 #define ERROR_INSERT_VALUE 0
157 #define ERROR_INSERT_EXTRA Uint32(0)
158 #define SET_ERROR_INSERT_VALUE(x) do { } while(0)
159 #define SET_ERROR_INSERT_VALUE2(x,y) do { } while(0)
160 #define CLEAR_ERROR_INSERT_VALUE do { } while(0)
161 #endif
162 
163 #define DECLARE_DUMP0(BLOCK, CODE, DESC) if (arg == CODE)
164 
165 /* ------------------------------------------------------------------------- */
166 /*       COMMONLY USED CONSTANTS.                                            */
167 /* ------------------------------------------------------------------------- */
168 #define ZFALSE 0
169 #define ZTRUE 1
170 #define ZSET 1
171 #define ZOK 0
172 #define ZNOT_OK 1
173 #define ZCLOSE_FILE 2
174 #define ZNIL 0xffff
175 #define Z8NIL 255
176 
177 /* ------------------------------------------------------------------------- */
178 // Number of fragments stored per node. Should be settable on a table basis
179 // in future version since small tables want small value and large tables
180 // need large value.
181 /* ------------------------------------------------------------------------- */
182 #define NO_OF_FRAG_PER_NODE 1
183 #define MAX_FRAG_PER_LQH 8
184 
185 /**
186 * DIH allocates fragments in chunk for fast find of fragment record.
187 * These parameters define chunk size and log of chunk size.
188 */
189 #define NO_OF_FRAGS_PER_CHUNK 4
190 #define LOG_NO_OF_FRAGS_PER_CHUNK 2
191 
192 /* ---------------------------------------------------------------- */
193 // To avoid synching too big chunks at a time we synch after writing
194 // a certain number of data/UNDO pages. (e.g. 2 MBytes).
195 /* ---------------------------------------------------------------- */
196 #define MAX_REDO_PAGES_WITHOUT_SYNCH 32
197 
198 /* ------------------------------------------------------------------ */
199 // We have these constants to ensure that we can easily change the
200 // parallelism of node recovery and the amount of scan
201 // operations needed for node recoovery.
202 /* ------------------------------------------------------------------ */
203 #define MAX_NO_WORDS_OUTSTANDING_COPY_FRAGMENT 6000
204 #define MAGIC_CONSTANT 56
205 #define NODE_RECOVERY_SCAN_OP_RECORDS \
206          (4 + ((4*MAX_NO_WORDS_OUTSTANDING_COPY_FRAGMENT)/ \
207          ((MAGIC_CONSTANT + 2) * 5)))
208 
209 #ifdef NO_CHECKPOINT
210 #define NO_LCP
211 #define NO_GCP
212 #endif
213 
214 /**
215  * Ndb kernel blocks assertion handling
216  *
217  * Two type of assertions:
218  * - ndbassert  - Only used when compiling VM_TRACE
219  * - ndbrequire - Always checked
220  *
221  * If a ndbassert/ndbrequire fails, the system will
222  * shutdown and generate an error log
223  *
224  *
225  * NOTE these may only be used within blocks
226  */
227 #if defined VM_TRACE
228 #define ndbassert(check) \
229   if(likely(check)){ \
230   } else {     \
231     jamNoBlock(); \
232     progError(__LINE__, NDBD_EXIT_NDBASSERT, __FILE__); \
233   }
234 #else
235 #define ndbassert(check) do { } while(0)
236 #endif
237 
238 #define ndbrequireErr(check, error) \
239   if(likely(check)){ \
240   } else {     \
241     jamNoBlock(); \
242     progError(__LINE__, error, __FILE__); \
243   }
244 
245 #define ndbrequire(check) \
246   ndbrequireErr(check, NDBD_EXIT_NDBREQUIRE)
247 
248 #define CRASH_INSERTION(errorType) \
249   if (!ERROR_INSERTED((errorType))) { \
250   } else { \
251     jamNoBlock(); \
252     progError(__LINE__, NDBD_EXIT_ERROR_INSERT, __FILE__); \
253   }
254 
255 #define CRASH_INSERTION2(errorNum, condition) \
256   if (!(ERROR_INSERTED(errorNum) && condition)) { \
257   } else { \
258     jamNoBlock(); \
259     progError(__LINE__, NDBD_EXIT_ERROR_INSERT, __FILE__); \
260   }
261 
262 #define MEMCOPY_PAGE(to, from, page_size_in_bytes) \
263   memcpy((void*)(to), (void*)(from), (size_t)(page_size_in_bytes));
264 #define MEMCOPY_NO_WORDS(to, from, no_of_words) \
265   memcpy((to), (void*)(from), (size_t)((no_of_words) << 2));
266 
267 // Get the jam buffer for the current thread.
getThrJamBuf()268 inline EmulatedJamBuffer* getThrJamBuf()
269 {
270   return reinterpret_cast<EmulatedJamBuffer*>
271     (NdbThread_GetTlsKey(NDB_THREAD_TLS_JAM));
272 }
273 
274 #undef JAM_FILE_ID
275 
276 #endif
277