summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2017-09-11 11:13:08 -0400
committerKaloian Manassiev <kaloian.manassiev@mongodb.com>2017-09-14 07:46:46 -0400
commitb0abd3f0b318e61837c2853a21b0ffde0bf8639f (patch)
treecc6ae8ca405766d44799c93667990bf7a8da25ed /src/mongo
parentb15fb2303c5c9ef72b64061c4b931bf7d39cdfab (diff)
downloadmongo-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.cpp37
-rw-r--r--src/mongo/util/fail_point.h11
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