CUBRID Engine  latest
fault_injection.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * fault_injection.c :
21  *
22  */
23 
24 #ident "$Id$"
25 
26 #include "fault_injection.h"
27 
28 #if defined (SERVER_MODE) || defined (SA_MODE)
29 #include "log_impl.h"
30 #endif /* defined (SERVER_MODE) || defined (SA_MODE) */
31 #include "porting.h"
32 #include "system_parameter.h"
33 #if defined (SERVER_MODE) || defined (SA_MODE)
34 #include "thread_manager.hpp" // for thread_get_thread_entry_info
35 #endif /* defined (SERVER_MODE) || defined (SA_MODE) */
36 
37 #include <assert.h>
38 
39 #if !defined(NDEBUG)
40 
41 static int fi_handler_exit (THREAD_ENTRY * thread_p, void *arg, const char *caller_file, const int caller_line);
42 static int fi_handler_random_exit (THREAD_ENTRY * thread_p, void *arg, const char *caller_file, const int caller_line);
43 static int fi_handler_random_fail (THREAD_ENTRY * thread_p, void *arg, const char *caller_file, const int caller_line);
44 static int fi_handler_hang (THREAD_ENTRY * thread_p, void *arg, const char *caller_file, const int caller_line);
45 
46 static FI_TEST_ITEM *fi_code_item (THREAD_ENTRY * thread_p, FI_TEST_CODE code);
47 
48 /******************************************************************************
49  *
50  * FI test scenario array
51  *
52  * Register new scenario in here with new FI_TEST_CODE & handler function
53  *
54  *******************************************************************************/
67 };
68 
71 };
72 
79 };
80 
84 };
85 
86 /*
87  * fi_thread_init -
88  *
89  * return: NO_ERROR or ER_FAILED
90  *
91  * thread_p(in):
92  */
93 int
95 {
96  FI_TEST_ITEM *fi_test_array = NULL;
97  unsigned int i;
98 
99 
100 #if defined (SERVER_MODE)
101  if (thread_p == NULL)
102  {
103  thread_p = thread_get_thread_entry_info ();
104  }
105  if (thread_p == NULL)
106  {
107  assert (thread_p != NULL);
108 
109  return ER_FAILED;
110  }
111 
112  if (thread_p->fi_test_array == NULL)
113  {
114  thread_p->fi_test_array = (FI_TEST_ITEM *) malloc (sizeof (fi_Test_array));
115  if (thread_p->fi_test_array == NULL)
116  {
117  er_set (ER_ERROR_SEVERITY, ARG_FILE_LINE, ER_OUT_OF_VIRTUAL_MEMORY, 1, sizeof (fi_Test_array));
119  }
120  }
121 
122  fi_test_array = thread_p->fi_test_array;
123 
124  memcpy (fi_test_array, fi_Test_array, sizeof (fi_Test_array));
125 
126 #else
127  fi_test_array = fi_Test_array;
128 #endif
129 
130  for (i = 0; i < DIM (fi_Test_array); i++)
131  {
132  fi_test_array[i].state = FI_INIT_STATE;
133  }
134 
135  return NO_ERROR;
136 }
137 
138 /*
139  * fi_thread_final -
140  *
141  * return: NO_ERROR or ER_FAILED
142  *
143  * thread_p(in):
144  */
145 int
147 {
148 #if defined (SERVER_MODE)
149  if (thread_p == NULL)
150  {
151  thread_p = thread_get_thread_entry_info ();
152  }
153  if (thread_p == NULL)
154  {
155  assert (thread_p != NULL);
156 
157  return ER_FAILED;
158  }
159 
160  if (thread_p->fi_test_array != NULL)
161  {
162  free_and_init (thread_p->fi_test_array);
163  }
164 #endif
165 
166  return NO_ERROR;
167 }
168 
169 /*
170  * fi_code_item -
171  *
172  * return: NO_ERROR or ER_FAILED
173  *
174  * code(in):
175  * state(in):
176  */
177 static FI_TEST_ITEM *
179 {
180  FI_TEST_ITEM *fi_test_array;
181  FI_TEST_ITEM *item;
182  unsigned int i;
183 
184 #if defined(SERVER_MODE)
185  if (thread_p == NULL)
186  {
187  thread_p = thread_get_thread_entry_info ();
188  }
189  if (thread_p == NULL)
190  {
191  assert (thread_p != NULL);
192 
193  return NULL;
194  }
195 
196  fi_test_array = thread_p->fi_test_array;
197 #else
198  fi_test_array = fi_Test_array;
199 #endif
200 
201  item = NULL;
202  for (i = 0; i < DIM (fi_Test_array); i++)
203  {
204  if (fi_test_array[i].code == code)
205  {
206  item = &fi_test_array[i];
207  break;
208  }
209  }
210 
211  assert (item != NULL);
212  return item;
213 }
214 
215 /*
216  * fi_set -
217  *
218  * return: NO_ERROR or ER_FAILED
219  *
220  * code(in):
221  * state(in):
222  */
223 int
224 fi_set (THREAD_ENTRY * thread_p, FI_TEST_CODE code, int state)
225 {
226  FI_TEST_ITEM *item = NULL;
227 
228 
230  {
231  return NO_ERROR;
232  }
233 
234  item = fi_code_item (thread_p, code);
235  if (item == NULL)
236  {
237  assert (item != NULL);
238  return ER_FAILED;
239  }
240 
241  if (item->state == state - 1)
242  {
243  item->state = state;
244  }
245 
246  return NO_ERROR;
247 }
248 
249 /*
250  * fi_set_force -
251  *
252  * return: NO_ERROR or error code
253  *
254  * code(in):
255  * state(in):
256  */
257 int
258 fi_set_force (THREAD_ENTRY * thread_p, FI_TEST_CODE code, int state)
259 {
260  FI_TEST_ITEM *item = NULL;
261 
263  {
264  return NO_ERROR;
265  }
266 
267  item = fi_code_item (thread_p, code);
268  if (item == NULL)
269  {
270  assert (item != NULL);
271  return ER_FAILED;
272  }
273 
274  item->state = state;
275 
276  return NO_ERROR;
277 }
278 
279 /*
280  * fi_reset -
281  *
282  * return:
283  *
284  * code(in):
285  */
286 void
288 {
289  FI_TEST_ITEM *item = NULL;
290 
291  item = fi_code_item (thread_p, code);
292  item->state = FI_INIT_STATE;
293 }
294 
295 /*
296  * fi_test -
297  *
298  * return: NO_ERROR or error code
299  *
300  * code(in):
301  * arg(in):
302  * state(in):
303  */
304 int
305 fi_test (THREAD_ENTRY * thread_p, FI_TEST_CODE code, void *arg, int state, const char *caller_file,
306  const int caller_line)
307 {
308  FI_TEST_ITEM *item = NULL;
309 
311  {
312  return NO_ERROR;
313  }
314 
315  item = fi_code_item (thread_p, code);
316  if (item == NULL)
317  {
318  assert (item != NULL);
319  return ER_FAILED;
320  }
321 
322  if (item->state == state)
323  {
324  return (*item->func) (thread_p, arg, caller_file, caller_line);
325  }
326 
327  return NO_ERROR;
328 }
329 
330 /*
331  * fi_state -
332  *
333  * return:
334  *
335  * code(in):
336  */
337 int
339 {
340  FI_TEST_ITEM *item = NULL;
341 
343  {
344  return FI_INIT_STATE;
345  }
346 
347  item = fi_code_item (thread_p, code);
348  assert (item != NULL);
349 
350  return item->state;
351 }
352 
353 /*
354  * fi_test_on -
355  *
356  * return: true or false
357  *
358  * code(in):
359  */
360 bool
362 {
364 }
365 
366 
367 /*
368  * fi_handler_exit -
369  *
370  * return: NO_ERROR
371  *
372  * arg(in):
373  */
374 static int
375 fi_handler_exit (THREAD_ENTRY * thread_p, void *arg, const char *caller_file, const int caller_line)
376 {
377  exit (0);
378 
379  return NO_ERROR;
380 }
381 
382 /*
383  * fi_handler_hang -
384  *
385  * return: NO_ERROR
386  *
387  * arg(in):
388  */
389 static int
390 fi_handler_hang (THREAD_ENTRY * thread_p, void *arg, const char *caller_file, const int caller_line)
391 {
392  while (true)
393  {
394  sleep (1);
395  }
396 
397  return NO_ERROR;
398 }
399 
400 static int
401 fi_handler_random_exit (THREAD_ENTRY * thread_p, void *arg, const char *caller_file, const int caller_line)
402 {
403  static bool init = false;
404  int r;
405  int mod_factor;
406 
407  if (arg == NULL)
408  {
409  mod_factor = 20000;
410  }
411  else
412  {
413  mod_factor = *((int *) arg);
414  }
415 
416  if (init == false)
417  {
418  srand ((unsigned int) time (NULL));
419  init = true;
420  }
421  r = rand ();
422 
423 #if 0
424  if ((r % 10) == 0)
425  {
426  /* todo: what is the purpose of this? */
427  LOG_CS_ENTER (thread_p);
428  logpb_flush_pages_direct (thread_p);
429  LOG_CS_EXIT (thread_p);
430  }
431 #endif
432  if ((r % mod_factor) == 0)
433  {
434  er_print_callstack (ARG_FILE_LINE, "FAULT INJECTION: RANDOM EXIT\n");
435  er_set (ER_NOTIFICATION_SEVERITY, caller_file, caller_line, ER_FAILED_ASSERTION, 1,
436  "fault injection: random exit");
437 
439  {
440  abort ();
441  }
442  else
443  {
444  _exit (0);
445  }
446  }
447 
448  return NO_ERROR;
449 }
450 
451 static int
452 fi_handler_random_fail (THREAD_ENTRY * thread_p, void *arg, const char *caller_file, const int caller_line)
453 {
454  static bool init = false;
455  int r;
456  int mod_factor;
457 
458  if (arg == NULL)
459  {
460  mod_factor = 20000;
461  }
462  else
463  {
464  mod_factor = *((int *) arg);
465  }
466 
467  if (init == false)
468  {
469  srand ((unsigned int) time (NULL));
470  init = true;
471  }
472  r = rand ();
473 
474  if ((r % mod_factor) == 0)
475  {
476  er_set (ER_NOTIFICATION_SEVERITY, caller_file, caller_line, ER_FAILED_ASSERTION, 1,
477  "fault injection: random fail");
478 
479  return ER_FAILED;
480  }
481 
482  return NO_ERROR;
483 }
484 #endif
#define ER_FAILED_ASSERTION
Definition: error_code.h:695
static int fi_handler_random_exit(THREAD_ENTRY *thread_p, void *arg, const char *caller_file, const int caller_line)
cubthread::entry * thread_get_thread_entry_info(void)
#define NO_ERROR
Definition: error_code.h:46
int fi_set_force(THREAD_ENTRY *thread_p, FI_TEST_CODE code, int state)
#define ER_FAILED
Definition: error_code.h:47
FI_TEST_ITEM fi_Test_array[]
void LOG_CS_ENTER(THREAD_ENTRY *thread_p)
FI_TEST_CODE fi_Group_recovery[]
int fi_thread_final(THREAD_ENTRY *thread_p)
static int fi_handler_exit(THREAD_ENTRY *thread_p, void *arg, const char *caller_file, const int caller_line)
void THREAD_ENTRY
void er_set(int severity, const char *file_name, const int line_no, int err_id, int num_args,...)
void logpb_flush_pages_direct(THREAD_ENTRY *thread_p)
#define assert(x)
FI_TEST_CODE * fi_Groups[FI_GROUP_MAX+1]
bool fi_test_on(FI_TEST_CODE code)
#define ER_OUT_OF_VIRTUAL_MEMORY
Definition: error_code.h:50
void LOG_CS_EXIT(THREAD_ENTRY *thread_p)
FI_HANDLER_FUNC func
static int fi_handler_hang(THREAD_ENTRY *thread_p, void *arg, const char *caller_file, const int caller_line)
#define NULL
Definition: freelistheap.h:34
void fi_reset(THREAD_ENTRY *thread_p, FI_TEST_CODE code)
#define FI_INIT_STATE
#define ARG_FILE_LINE
Definition: error_manager.h:44
void er_print_callstack(const char *file_name, const int line_no, const char *fmt,...)
#define free_and_init(ptr)
Definition: memory_alloc.h:147
static int fi_handler_random_fail(THREAD_ENTRY *thread_p, void *arg, const char *caller_file, const int caller_line)
bool prm_get_bool_value(PARAM_ID prm_id)
int i
Definition: dynamic_load.c:954
_exit(1)
int fi_test(THREAD_ENTRY *thread_p, FI_TEST_CODE code, void *arg, int state, const char *caller_file, const int caller_line)
FI_TEST_CODE
int fi_set(THREAD_ENTRY *thread_p, FI_TEST_CODE code, int state)
int fi_thread_init(THREAD_ENTRY *thread_p)
int fi_state(THREAD_ENTRY *thread_p, FI_TEST_CODE code)
static FI_TEST_ITEM * fi_code_item(THREAD_ENTRY *thread_p, FI_TEST_CODE code)
FI_TEST_CODE fi_Group_none[]
bool sysprm_find_fi_code_in_integer_list(PARAM_ID prm_id, int fi_code)