summaryrefslogtreecommitdiff
path: root/src/mongo/util/fail_point.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/util/fail_point.h')
-rw-r--r--src/mongo/util/fail_point.h357
1 files changed, 178 insertions, 179 deletions
diff --git a/src/mongo/util/fail_point.h b/src/mongo/util/fail_point.h
index a23ee1daced..f0bcffcb06e 100644
--- a/src/mongo/util/fail_point.h
+++ b/src/mongo/util/fail_point.h
@@ -34,201 +34,200 @@
#include "mongo/stdx/mutex.h"
namespace mongo {
+/**
+ * A simple thread-safe fail point implementation that can be activated and
+ * deactivated, as well as embed temporary data into it.
+ *
+ * The fail point has a static instance, which is represented by a FailPoint
+ * object, and dynamic instance, which are all the threads in between
+ * shouldFailOpenBlock and shouldFailCloseBlock.
+ *
+ * Sample use:
+ * // Declared somewhere:
+ * FailPoint makeBadThingsHappen;
+ *
+ * // Somewhere in the code
+ * return false || MONGO_FAIL_POINT(makeBadThingsHappen);
+ *
+ * or
+ *
+ * // Somewhere in the code
+ * MONGO_FAIL_POINT_BLOCK(makeBadThingsHappen, blockMakeBadThingsHappen) {
+ * const BSONObj& data = blockMakeBadThingsHappen.getData();
+ * // Do something
+ * }
+ *
+ * Invariants:
+ *
+ * 1. Always refer to _fpInfo first to check if failPoint is active or not before
+ * entering fail point or modifying fail point.
+ * 2. Client visible fail point states are read-only when active.
+ */
+class FailPoint {
+ MONGO_DISALLOW_COPYING(FailPoint);
+
+public:
+ typedef AtomicUInt32::WordType ValType;
+ enum Mode { off, alwaysOn, random, nTimes, numModes };
+ enum RetCode { fastOff = 0, slowOff, slowOn };
+
/**
- * A simple thread-safe fail point implementation that can be activated and
- * deactivated, as well as embed temporary data into it.
- *
- * The fail point has a static instance, which is represented by a FailPoint
- * object, and dynamic instance, which are all the threads in between
- * shouldFailOpenBlock and shouldFailCloseBlock.
- *
- * Sample use:
- * // Declared somewhere:
- * FailPoint makeBadThingsHappen;
+ * Explicitly resets the seed used for the PRNG in this thread. If not called on a thread,
+ * an instance of SecureRandom is used to seed the PRNG.
+ */
+ static void setThreadPRNGSeed(int32_t seed);
+
+ FailPoint();
+
+ /**
+ * Note: This is not side-effect free - it can change the state to OFF after calling.
*
- * // Somewhere in the code
- * return false || MONGO_FAIL_POINT(makeBadThingsHappen);
+ * @return true if fail point is active.
+ */
+ inline bool shouldFail() {
+ RetCode ret = shouldFailOpenBlock();
+
+ if (MONGO_likely(ret == fastOff)) {
+ return false;
+ }
+
+ shouldFailCloseBlock();
+ return ret == slowOn;
+ }
+
+ /**
+ * Checks whether fail point is active and increments the reference counter without
+ * decrementing it. Must call shouldFailCloseBlock afterwards when the return value
+ * is not fastOff. Otherwise, this will remain read-only forever.
*
- * or
+ * @return slowOn if fail point is active.
+ */
+ inline RetCode shouldFailOpenBlock() {
+ if (MONGO_likely((_fpInfo.loadRelaxed() & ACTIVE_BIT) == 0)) {
+ return fastOff;
+ }
+
+ return slowShouldFailOpenBlock();
+ }
+
+ /**
+ * Decrements the reference counter.
+ * @see #shouldFailOpenBlock
+ */
+ void shouldFailCloseBlock();
+
+ /**
+ * Changes the settings of this fail point. This will turn off the fail point
+ * and waits for all dynamic instances referencing this fail point to go away before
+ * actually modifying the settings.
*
- * // Somewhere in the code
- * MONGO_FAIL_POINT_BLOCK(makeBadThingsHappen, blockMakeBadThingsHappen) {
- * const BSONObj& data = blockMakeBadThingsHappen.getData();
- * // Do something
- * }
+ * @param mode the new mode for this fail point.
+ * @param val the value that can have different usage depending on the mode:
*
- * Invariants:
+ * - off, alwaysOn: ignored
+ * - random: static_cast<int32_t>(std::numeric_limits<int32_t>::max() * p), where
+ * where p is the probability that any given evaluation of the failpoint should
+ * activate.
+ * - nTimes: the number of times this fail point will be active when
+ * #shouldFail or #shouldFailOpenBlock is called.
*
- * 1. Always refer to _fpInfo first to check if failPoint is active or not before
- * entering fail point or modifying fail point.
- * 2. Client visible fail point states are read-only when active.
+ * @param extra arbitrary BSON object that can be stored to this fail point
+ * that can be referenced afterwards with #getData. Defaults to an empty
+ * document.
*/
- class FailPoint {
- MONGO_DISALLOW_COPYING(FailPoint);
-
- public:
- typedef AtomicUInt32::WordType ValType;
- enum Mode { off, alwaysOn, random, nTimes, numModes };
- enum RetCode { fastOff = 0, slowOff, slowOn };
-
- /**
- * Explicitly resets the seed used for the PRNG in this thread. If not called on a thread,
- * an instance of SecureRandom is used to seed the PRNG.
- */
- static void setThreadPRNGSeed(int32_t seed);
-
- FailPoint();
-
- /**
- * Note: This is not side-effect free - it can change the state to OFF after calling.
- *
- * @return true if fail point is active.
- */
- inline bool shouldFail() {
- RetCode ret = shouldFailOpenBlock();
-
- if (MONGO_likely(ret == fastOff)) {
- return false;
- }
-
- shouldFailCloseBlock();
- return ret == slowOn;
- }
+ void setMode(Mode mode, ValType val = 0, const BSONObj& extra = BSONObj());
- /**
- * Checks whether fail point is active and increments the reference counter without
- * decrementing it. Must call shouldFailCloseBlock afterwards when the return value
- * is not fastOff. Otherwise, this will remain read-only forever.
- *
- * @return slowOn if fail point is active.
- */
- inline RetCode shouldFailOpenBlock() {
- if (MONGO_likely((_fpInfo.loadRelaxed() & ACTIVE_BIT) == 0)) {
- return fastOff;
- }
-
- return slowShouldFailOpenBlock();
- }
+ /**
+ * @returns a BSON object showing the current mode and data stored.
+ */
+ BSONObj toBSON() const;
+
+private:
+ static const ValType ACTIVE_BIT = 1 << 31;
+ static const ValType REF_COUNTER_MASK = ~ACTIVE_BIT;
+
+ // Bit layout:
+ // 31: tells whether this fail point is active.
+ // 0~30: unsigned ref counter for active dynamic instances.
+ AtomicUInt32 _fpInfo;
+
+ // Invariant: These should be read only if ACTIVE_BIT of _fpInfo is set.
+ Mode _mode;
+ AtomicInt32 _timesOrPeriod;
+ BSONObj _data;
- /**
- * Decrements the reference counter.
- * @see #shouldFailOpenBlock
- */
- void shouldFailCloseBlock();
-
- /**
- * Changes the settings of this fail point. This will turn off the fail point
- * and waits for all dynamic instances referencing this fail point to go away before
- * actually modifying the settings.
- *
- * @param mode the new mode for this fail point.
- * @param val the value that can have different usage depending on the mode:
- *
- * - off, alwaysOn: ignored
- * - random: static_cast<int32_t>(std::numeric_limits<int32_t>::max() * p), where
- * where p is the probability that any given evaluation of the failpoint should
- * activate.
- * - nTimes: the number of times this fail point will be active when
- * #shouldFail or #shouldFailOpenBlock is called.
- *
- * @param extra arbitrary BSON object that can be stored to this fail point
- * that can be referenced afterwards with #getData. Defaults to an empty
- * document.
- */
- void setMode(Mode mode, ValType val = 0, const BSONObj& extra = BSONObj());
-
- /**
- * @returns a BSON object showing the current mode and data stored.
- */
- BSONObj toBSON() const;
-
- private:
- static const ValType ACTIVE_BIT = 1 << 31;
- static const ValType REF_COUNTER_MASK = ~ACTIVE_BIT;
-
- // Bit layout:
- // 31: tells whether this fail point is active.
- // 0~30: unsigned ref counter for active dynamic instances.
- AtomicUInt32 _fpInfo;
-
- // Invariant: These should be read only if ACTIVE_BIT of _fpInfo is set.
- Mode _mode;
- AtomicInt32 _timesOrPeriod;
- BSONObj _data;
-
- // protects _mode, _timesOrPeriod, _data
- mutable stdx::mutex _modMutex;
-
- /**
- * Enables this fail point.
- */
- void enableFailPoint();
-
- /**
- * Disables this fail point.
- */
- void disableFailPoint();
-
- /**
- * slow path for #shouldFailOpenBlock
- */
- RetCode slowShouldFailOpenBlock();
-
- /**
- * @return the stored BSONObj in this fail point. Note that this cannot be safely
- * read if this fail point is off.
- */
- const BSONObj& getData() const;
-
- friend class ScopedFailPoint;
- };
+ // protects _mode, _timesOrPeriod, _data
+ mutable stdx::mutex _modMutex;
/**
- * Helper class for making sure that FailPoint#shouldFailCloseBlock is called when
- * FailPoint#shouldFailOpenBlock was called. This should only be used within the
- * MONGO_FAIL_POINT_BLOCK macro.
+ * Enables this fail point.
*/
- class ScopedFailPoint {
- MONGO_DISALLOW_COPYING(ScopedFailPoint);
-
- public:
- ScopedFailPoint(FailPoint* failPoint);
- ~ScopedFailPoint();
-
- /**
- * @return true if fail point is on. This will be true at most once.
- */
- inline bool isActive() {
- if (_once) {
- return false;
- }
-
- _once = true;
-
- FailPoint::RetCode ret = _failPoint->shouldFailOpenBlock();
- _shouldClose = ret != FailPoint::fastOff;
- return ret == FailPoint::slowOn;
- }
+ void enableFailPoint();
- /**
- * @return the data stored in the fail point. #isActive must be true
- * before you can call this.
- */
- const BSONObj& getData() const;
+ /**
+ * Disables this fail point.
+ */
+ void disableFailPoint();
- private:
- FailPoint* _failPoint;
- bool _once;
- bool _shouldClose;
- };
+ /**
+ * slow path for #shouldFailOpenBlock
+ */
+ RetCode slowShouldFailOpenBlock();
- #define MONGO_FAIL_POINT(symbol) MONGO_unlikely(symbol.shouldFail())
+ /**
+ * @return the stored BSONObj in this fail point. Note that this cannot be safely
+ * read if this fail point is off.
+ */
+ const BSONObj& getData() const;
+
+ friend class ScopedFailPoint;
+};
+
+/**
+ * Helper class for making sure that FailPoint#shouldFailCloseBlock is called when
+ * FailPoint#shouldFailOpenBlock was called. This should only be used within the
+ * MONGO_FAIL_POINT_BLOCK macro.
+ */
+class ScopedFailPoint {
+ MONGO_DISALLOW_COPYING(ScopedFailPoint);
+
+public:
+ ScopedFailPoint(FailPoint* failPoint);
+ ~ScopedFailPoint();
+
+ /**
+ * @return true if fail point is on. This will be true at most once.
+ */
+ inline bool isActive() {
+ if (_once) {
+ return false;
+ }
+
+ _once = true;
+
+ FailPoint::RetCode ret = _failPoint->shouldFailOpenBlock();
+ _shouldClose = ret != FailPoint::fastOff;
+ return ret == FailPoint::slowOn;
+ }
/**
- * Macro for creating a fail point with block context. Also use this when
- * you want to access the data stored in the fail point.
+ * @return the data stored in the fail point. #isActive must be true
+ * before you can call this.
*/
- #define MONGO_FAIL_POINT_BLOCK(symbol, blockSymbol) \
- for (mongo::ScopedFailPoint blockSymbol(&symbol); \
- MONGO_unlikely(blockSymbol.isActive()); )
+ const BSONObj& getData() const;
+
+private:
+ FailPoint* _failPoint;
+ bool _once;
+ bool _shouldClose;
+};
+
+#define MONGO_FAIL_POINT(symbol) MONGO_unlikely(symbol.shouldFail())
+
+/**
+ * Macro for creating a fail point with block context. Also use this when
+ * you want to access the data stored in the fail point.
+ */
+#define MONGO_FAIL_POINT_BLOCK(symbol, blockSymbol) \
+ for (mongo::ScopedFailPoint blockSymbol(&symbol); MONGO_unlikely(blockSymbol.isActive());)
}