diff options
author | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2017-09-11 11:13:08 -0400 |
---|---|---|
committer | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2017-09-14 07:46:46 -0400 |
commit | b0abd3f0b318e61837c2853a21b0ffde0bf8639f (patch) | |
tree | cc6ae8ca405766d44799c93667990bf7a8da25ed /src/mongo | |
parent | b15fb2303c5c9ef72b64061c4b931bf7d39cdfab (diff) | |
download | mongo-b0abd3f0b318e61837c2853a21b0ffde0bf8639f.tar.gz |
SERVER-29606 Add a 'skip' failpoint option
This option allows the failpoint's effect to be skipped for up to a
certain amount of checks.
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/util/fail_point.cpp | 37 | ||||
-rw-r--r-- | src/mongo/util/fail_point.h | 11 |
2 files changed, 36 insertions, 12 deletions
diff --git a/src/mongo/util/fail_point.cpp b/src/mongo/util/fail_point.cpp index 8f85ba18f17..75be5f48231 100644 --- a/src/mongo/util/fail_point.cpp +++ b/src/mongo/util/fail_point.cpp @@ -76,7 +76,7 @@ void FailPoint::setThreadPRNGSeed(int32_t seed) { FailPointPRNG::current()->resetSeed(seed); } -FailPoint::FailPoint() : _fpInfo(0), _mode(off), _timesOrPeriod(0) {} +FailPoint::FailPoint() = default; void FailPoint::shouldFailCloseBlock() { _fpInfo.subtractAndFetch(1); @@ -151,24 +151,28 @@ FailPoint::RetCode FailPoint::slowShouldFailOpenBlock() { switch (_mode) { case alwaysOn: return slowOn; - case random: { const AtomicInt32::WordType maxActivationValue = _timesOrPeriod.load(); - if (FailPointPRNG::current()->nextPositiveInt32() < maxActivationValue) { + if (FailPointPRNG::current()->nextPositiveInt32() < maxActivationValue) return slowOn; - } + return slowOff; } case nTimes: { - AtomicInt32::WordType newVal = _timesOrPeriod.subtractAndFetch(1); - - if (newVal <= 0) { + if (_timesOrPeriod.subtractAndFetch(1) <= 0) disableFailPoint(); - } return slowOn; } + case skip: { + // Ensure that once the skip counter reaches within some delta from 0 we don't continue + // decrementing it unboundedly because at some point it will roll over and become + // positive again + if (_timesOrPeriod.load() <= 0 || _timesOrPeriod.subtractAndFetch(1) < 0) + return slowOn; + return slowOff; + } default: error() << "FailPoint Mode not supported: " << static_cast<int>(_mode); fassertFailed(16444); @@ -212,6 +216,23 @@ StatusWith<std::tuple<FailPoint::Mode, FailPoint::ValType, BSONObj>> FailPoint:: return {ErrorCodes::BadValue, "'times' option to 'mode' is too large"}; } val = static_cast<int>(longVal); + } else if (modeObj.hasField("skip")) { + mode = FailPoint::skip; + + long long longVal; + auto status = bsonExtractIntegerField(modeObj, "skip", &longVal); + if (!status.isOK()) { + return status; + } + + if (longVal < 0) { + return {ErrorCodes::BadValue, "'skip' option to 'mode' must be positive"}; + } + + if (longVal > std::numeric_limits<int>::max()) { + return {ErrorCodes::BadValue, "'skip' option to 'mode' is too large"}; + } + val = static_cast<int>(longVal); } else if (modeObj.hasField("activationProbability")) { mode = FailPoint::random; diff --git a/src/mongo/util/fail_point.h b/src/mongo/util/fail_point.h index 77bb9ab882a..a5fc58d21d5 100644 --- a/src/mongo/util/fail_point.h +++ b/src/mongo/util/fail_point.h @@ -69,7 +69,7 @@ class FailPoint { public: typedef AtomicUInt32::WordType ValType; - enum Mode { off, alwaysOn, random, nTimes }; + enum Mode { off, alwaysOn, random, nTimes, skip }; enum RetCode { fastOff = 0, slowOff, slowOn }; /** @@ -136,6 +136,9 @@ public: * activate. * - nTimes: the number of times this fail point will be active when * #shouldFail or #shouldFailOpenBlock is called. + * - skip: the number of times this failpoint will be inactive when + * #shouldFail or #shouldFailOpenBlock is called. After this number is reached, the + * failpoint will always be 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 @@ -155,11 +158,11 @@ private: // Bit layout: // 31: tells whether this fail point is active. // 0~30: unsigned ref counter for active dynamic instances. - AtomicUInt32 _fpInfo; + AtomicUInt32 _fpInfo{0}; // Invariant: These should be read only if ACTIVE_BIT of _fpInfo is set. - Mode _mode; - AtomicInt32 _timesOrPeriod; + Mode _mode{off}; + AtomicInt32 _timesOrPeriod{0}; BSONObj _data; // protects _mode, _timesOrPeriod, _data |