diff options
Diffstat (limited to 'src/mongo/util/fail_point.h')
-rw-r--r-- | src/mongo/util/fail_point.h | 357 |
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());) } |