0.9.8.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
FailureInducer.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007-2015 Hypertable, Inc.
3  *
4  * This file is part of Hypertable.
5  *
6  * Hypertable is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 3
9  * of the License, or any later version.
10  *
11  * Hypertable is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  * 02110-1301, USA.
20  */
21 
29 #include <Common/Compat.h>
30 #include <Common/String.h>
31 #include <Common/FailureInducer.h>
32 #include <Common/Error.h>
33 #include <Common/Logger.h>
34 
35 #include <boost/algorithm/string.hpp>
36 #include <boost/algorithm/string/predicate.hpp>
37 
38 #include <chrono>
39 #include <thread>
40 #include <vector>
41 
42 using namespace Hypertable;
43 using namespace std;
44 
45 namespace {
46  enum {
47  FAILURE_TYPE_EXIT,
48  FAILURE_TYPE_THROW,
49  FAILURE_TYPE_SIGNAL,
50  FAILURE_TYPE_PAUSE
51  };
52 }
53 
55 
57  std::vector<String> args;
58  boost::algorithm::split(args, option, boost::algorithm::is_any_of(";"));
59  for (auto &a : args)
60  parse_option_single(a);
61 }
62 
63 void FailureInducer::maybe_fail(const String &label) {
64  lock_guard<mutex> lock(m_mutex);
65  StateMap::iterator iter = m_state_map.find(label);
66  if (iter != m_state_map.end()) {
67  if ((*iter).second->iteration == (*iter).second->trigger_iteration) {
68  if ((*iter).second->failure_type == FAILURE_TYPE_THROW) {
69  uint32_t iteration = (*iter).second->iteration;
70  int error_code = (*iter).second->error_code;
71  delete (*iter).second;
72  m_state_map.erase(iter);
73  HT_THROW(error_code,
74  format("induced failure code '%d' '%s' iteration=%u",
75  error_code, label.c_str(), iteration));
76  }
77  else if ((*iter).second->failure_type == FAILURE_TYPE_PAUSE) {
78  HT_INFOF("Induced pause at '%s' iteration=%u for %u milliseconds",
79  label.c_str(), (*iter).second->iteration,
80  (*iter).second->pause_millis);
81  this_thread::sleep_for(chrono::milliseconds((*iter).second->pause_millis));
82  }
83  else {
84  HT_ERRORF("induced failure code '%d' '%s' iteration=%u",
85  (*iter).second->error_code, (*iter).first.c_str(),
86  (*iter).second->iteration);
87  quick_exit(EXIT_FAILURE);
88  }
89  }
90  (*iter).second->iteration++;
91  }
92 }
93 
95  lock_guard<mutex> lock(m_mutex);
96  StateMap::iterator iter = m_state_map.find(label);
97  if (iter == m_state_map.end())
98  return false;
99  if ((*iter).second->failure_type == FAILURE_TYPE_SIGNAL
100  && (*iter).second->iteration == (*iter).second->trigger_iteration)
101  return true;
102  (*iter).second->iteration++;
103  return false;
104 }
105 
107  lock_guard<mutex> lock(m_mutex);
108  for (StateMap::iterator iter = m_state_map.begin();
109  iter != m_state_map.end(); ++iter)
110  delete iter->second;
111  m_state_map.clear();
112 }
113 
115  char *istr = (char*)strchr(option.c_str(), ':');
116  HT_ASSERT(istr != 0);
117  *istr++ = 0;
118 
119  const char *failure_type = istr;
120  istr = strchr(istr, ':');
121  HT_ASSERT(istr != 0);
122  *istr++ = 0;
123  size_t failure_type_len = strlen(failure_type);
125 
126  statep->error_code = 0;
127  statep->pause_millis = 0;
128 
129  if (!strcmp(failure_type, "exit"))
130  statep->failure_type = FAILURE_TYPE_EXIT;
131  else if (!strcmp(failure_type, "signal"))
132  statep->failure_type = FAILURE_TYPE_SIGNAL;
133  else if (boost::algorithm::starts_with(failure_type, "pause")) {
134  statep->failure_type = FAILURE_TYPE_PAUSE;
135  if (failure_type_len > 5 && failure_type[5] == '(') {
136  const char *ptr = failure_type + 6;
137  statep->pause_millis = (int)strtol(ptr, NULL, 0);
138  }
139  }
140  else if (boost::algorithm::starts_with(failure_type, "throw")) {
141  statep->failure_type = FAILURE_TYPE_THROW;
143  if (failure_type_len > 5 && failure_type[5] == '(') {
144  const char *error_code = failure_type + 6;
145  if (boost::algorithm::istarts_with(error_code, "0x"))
146  statep->error_code = (int)strtol(error_code, NULL, 16);
147  else
148  statep->error_code = (int)strtol(error_code, NULL, 0);
149  }
150  }
151  else
152  HT_ASSERT(!"Unknown failure type");
153 
154  statep->iteration = 0;
155  statep->trigger_iteration = atoi(istr);
156  m_state_map[option.c_str()] = statep;
157 }
158 
The FailureInducer simulates errors.
uint32_t iteration
Current iteration of the failure.
void clear()
Clears the failure inducer.
std::string String
A String is simply a typedef to std::string.
Definition: String.h:44
int failure_type
The failure type; an enum in FailureInducer.cc.
String format(const char *fmt,...)
Returns a String using printf like format facilities Vanilla snprintf is about 1.5x faster than this...
Definition: String.cc:37
uint32_t trigger_iteration
Number of iterations after which the failure is triggered.
STL namespace.
static FailureInducer * instance
This is a singleton class.
#define HT_ASSERT(_e_)
Definition: Logger.h:396
void maybe_fail(const String &label)
Tests and executes the induced failures.
Logging routines and macros.
Compatibility Macros for C/C++.
void parse_option(String spec)
Parses a spec string (as explained above) and stores it in an internal structure. ...
int pause_millis
Milliseconds to pause (if type is FAILURE_TYPE_PAUSE)
Hypertable definitions
#define HT_INFOF(msg,...)
Definition: Logger.h:272
bool split(int flags)
Tests the SPLIT bit of flags
A String class based on std::string.
bool failure_signalled(const String &label)
Returns true if a failure was signalled.
#define HT_ERRORF(msg,...)
Definition: Logger.h:300
void parse_option_single(String option)
Helper function to parse a single option.
Error codes, Exception handling, error logging.
#define HT_THROW(_code_, _msg_)
Definition: Error.h:478
Internal structure to store a single failure setting.
int error_code
The error code which is thrown (if type is FAILURE_TYPE_THROW)