1 /*************************************************************************
3 * Copyright 2016 Realm Inc.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 **************************************************************************/
19 #ifndef REALM_IMPL_SIMULATED_FAILURE_HPP
20 #define REALM_IMPL_SIMULATED_FAILURE_HPP
23 #include <system_error>
25 #include <realm/util/features.h>
28 #define REALM_ENABLE_SIMULATED_FAILURE
34 class SimulatedFailure : public std::system_error {
38 slab_alloc__reset_free_space_tracking,
40 shared_group__grow_reader_mapping,
41 sync_client__read_head,
42 sync_server__read_head,
46 class OneShotPrimeGuard;
47 class RandomPrimeGuard;
49 /// Prime the specified failure type on the calling thread for triggering
51 static void prime_one_shot(FailureType);
53 /// Prime the specified failure type on the calling thread for triggering
54 /// randomly \a n out of \a m times.
55 static void prime_random(FailureType, int n, int m, uint_fast64_t seed = 0);
57 /// Unprime the specified failure type on the calling thread.
58 static void unprime(FailureType) noexcept;
60 /// Returns true according to the mode of priming of the specified failure
61 /// type on the calling thread, but only if REALM_ENABLE_SIMULATED_FAILURE
62 /// was defined during compilation. If REALM_ENABLE_SIMULATED_FAILURE was
63 /// not defined, this function always return false.
64 static bool check_trigger(FailureType) noexcept;
66 /// The specified error code is set to `make_error_code(failure_type)` if
67 /// check_trigger() returns true. Otherwise it is set to
68 /// `std::error_code()`. Returns a copy of the updated error code.
69 static std::error_code trigger(FailureType failure_type, std::error_code&) noexcept;
71 /// Throws SimulatedFailure if check_trigger() returns true. The exception
72 /// will be constructed with an error code equal to
73 /// `make_error_code(failure_type)`.
74 static void trigger(FailureType failure_type);
76 /// Returns true when, and only when REALM_ENABLE_SIMULATED_FAILURE was
77 /// defined during compilation.
78 static constexpr bool is_enabled();
80 SimulatedFailure(std::error_code);
83 #ifdef REALM_ENABLE_SIMULATED_FAILURE
84 static void do_prime_one_shot(FailureType);
85 static void do_prime_random(FailureType, int n, int m, uint_fast64_t seed);
86 static void do_unprime(FailureType) noexcept;
87 static bool do_check_trigger(FailureType) noexcept;
91 std::error_code make_error_code(SimulatedFailure::FailureType) noexcept;
93 class SimulatedFailure::OneShotPrimeGuard {
95 OneShotPrimeGuard(FailureType);
96 ~OneShotPrimeGuard() noexcept;
99 const FailureType m_type;
103 class SimulatedFailure::RandomPrimeGuard {
105 RandomPrimeGuard(FailureType, int n, int m, uint_fast64_t seed = 0);
106 ~RandomPrimeGuard() noexcept;
109 const FailureType m_type;
112 std::error_code make_error_code(SimulatedFailure::FailureType) noexcept;
119 template<> struct is_error_code_enum<realm::_impl::SimulatedFailure::FailureType> {
120 static const bool value = true;
131 inline void SimulatedFailure::prime_one_shot(FailureType failure_type)
133 #ifdef REALM_ENABLE_SIMULATED_FAILURE
134 do_prime_one_shot(failure_type);
136 static_cast<void>(failure_type);
140 inline void SimulatedFailure::prime_random(FailureType failure_type, int n, int m, uint_fast64_t seed)
142 #ifdef REALM_ENABLE_SIMULATED_FAILURE
143 do_prime_random(failure_type, n, m, seed);
145 static_cast<void>(failure_type);
146 static_cast<void>(n);
147 static_cast<void>(m);
148 static_cast<void>(seed);
152 inline void SimulatedFailure::unprime(FailureType failure_type) noexcept
154 #ifdef REALM_ENABLE_SIMULATED_FAILURE
155 do_unprime(failure_type);
157 static_cast<void>(failure_type);
161 inline bool SimulatedFailure::check_trigger(FailureType failure_type) noexcept
163 #ifdef REALM_ENABLE_SIMULATED_FAILURE
164 return do_check_trigger(failure_type);
166 static_cast<void>(failure_type);
171 inline std::error_code SimulatedFailure::trigger(FailureType failure_type, std::error_code& ec) noexcept
173 if (check_trigger(failure_type)) {
174 ec = make_error_code(failure_type);
177 ec = std::error_code();
182 inline void SimulatedFailure::trigger(FailureType failure_type)
184 if (check_trigger(failure_type))
185 throw SimulatedFailure(make_error_code(failure_type));
188 inline constexpr bool SimulatedFailure::is_enabled()
190 #ifdef REALM_ENABLE_SIMULATED_FAILURE
197 inline SimulatedFailure::SimulatedFailure(std::error_code ec)
198 : std::system_error(ec)
202 inline SimulatedFailure::OneShotPrimeGuard::OneShotPrimeGuard(FailureType failure_type)
203 : m_type(failure_type)
205 prime_one_shot(m_type);
208 inline SimulatedFailure::OneShotPrimeGuard::~OneShotPrimeGuard() noexcept
213 inline SimulatedFailure::RandomPrimeGuard::RandomPrimeGuard(FailureType failure_type, int n, int m,
215 : m_type(failure_type)
217 prime_random(m_type, n, m, seed);
220 inline SimulatedFailure::RandomPrimeGuard::~RandomPrimeGuard() noexcept
228 #endif // REALM_IMPL_SIMULATED_FAILURE_HPP