summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/s/chunk_split_state_driver.cpp32
-rw-r--r--src/mongo/db/s/chunk_split_state_driver.h14
-rw-r--r--src/mongo/db/s/chunk_split_state_driver_test.cpp50
3 files changed, 45 insertions, 51 deletions
diff --git a/src/mongo/db/s/chunk_split_state_driver.cpp b/src/mongo/db/s/chunk_split_state_driver.cpp
index 24009a312b3..dd80060e642 100644
--- a/src/mongo/db/s/chunk_split_state_driver.cpp
+++ b/src/mongo/db/s/chunk_split_state_driver.cpp
@@ -47,14 +47,21 @@ boost::optional<ChunkSplitStateDriver> ChunkSplitStateDriver::tryInitiateSplit(
ChunkSplitStateDriver::ChunkSplitStateDriver(ChunkSplitStateDriver&& source) {
_writesTracker = source._writesTracker;
source._writesTracker.reset();
+
+ _stashedBytesWritten = source._stashedBytesWritten;
+ source._stashedBytesWritten = 0;
+
_splitState = source._splitState;
- // Ensure that the source driver does not cancel the ongoing split
source._splitState = SplitState::kNotSplitting;
}
ChunkSplitStateDriver::~ChunkSplitStateDriver() {
- if (_splitState == SplitState::kSplitInProgress || _splitState == SplitState::kSplitPrepared) {
- cancelSplit();
+ if (_splitState != SplitState::kSplitCommitted) {
+ auto wt = _writesTracker.lock();
+ if (wt) {
+ wt->releaseSplitLock();
+ wt->addBytesWritten(_stashedBytesWritten);
+ }
}
}
@@ -62,8 +69,10 @@ void ChunkSplitStateDriver::prepareSplit() {
invariant(_splitState == SplitState::kSplitInProgress);
_splitState = SplitState::kSplitPrepared;
+ auto wt = _writesTracker.lock();
+ uassert(50873, "Split interrupted due to chunk metadata change.", wt);
// Clear bytes written and get the previous bytes written.
- _stashedBytesWritten = _getWritesTracker()->clearBytesWritten();
+ _stashedBytesWritten = wt->clearBytesWritten();
}
void ChunkSplitStateDriver::commitSplit() {
@@ -71,19 +80,4 @@ void ChunkSplitStateDriver::commitSplit() {
_splitState = SplitState::kSplitCommitted;
}
-void ChunkSplitStateDriver::cancelSplit() {
- invariant(_splitState == SplitState::kSplitInProgress ||
- _splitState == SplitState::kSplitPrepared);
- _splitState = SplitState::kNotSplitting;
-
- _getWritesTracker()->releaseSplitLock();
- _getWritesTracker()->addBytesWritten(_stashedBytesWritten);
-}
-
-std::shared_ptr<ChunkWritesTracker> ChunkSplitStateDriver::_getWritesTracker() {
- auto wt = _writesTracker.lock();
- invariant(wt, "ChunkWritesTracker was destructed before ChunkSplitStateDriver");
- return wt;
-}
-
} // namespace mongo
diff --git a/src/mongo/db/s/chunk_split_state_driver.h b/src/mongo/db/s/chunk_split_state_driver.h
index 427f3cda056..b1954a7f9c9 100644
--- a/src/mongo/db/s/chunk_split_state_driver.h
+++ b/src/mongo/db/s/chunk_split_state_driver.h
@@ -86,13 +86,6 @@ public:
*/
void commitSplit();
- /**
- * Marks the split state of an in-progress split back to kNotSplitting.
- * If a split has already been prepared, resets the byte counter to what it
- * was prior to prepare plus any new bytes that have been written.
- */
- void cancelSplit();
-
private:
/**
* Should only be used by tryInitiateSplit
@@ -119,13 +112,6 @@ private:
kSplitPrepared,
kSplitCommitted,
} _splitState{SplitState::kNotSplitting};
-
-
- /**
- * Returns the ChunkWritesTracker whose state this driver is controlling,
- * checking to make sure it has not yet been destroyed.
- */
- std::shared_ptr<ChunkWritesTracker> _getWritesTracker();
};
} // namespace mongo
diff --git a/src/mongo/db/s/chunk_split_state_driver_test.cpp b/src/mongo/db/s/chunk_split_state_driver_test.cpp
index 1619d035f81..6de8ae1ecaa 100644
--- a/src/mongo/db/s/chunk_split_state_driver_test.cpp
+++ b/src/mongo/db/s/chunk_split_state_driver_test.cpp
@@ -36,7 +36,7 @@
namespace mongo {
-class ChunkSplitStateDriverTest : public unittest::Test {
+class ChunkSplitStateDriverTestNoTeardown : public unittest::Test {
public:
// Add bytes to write tracker and create the ChunkSplitStateDriver object
// to test, which starts the split on the writes tracker
@@ -48,24 +48,29 @@ public:
ChunkSplitStateDriver::tryInitiateSplit(_writesTracker));
}
- void tearDown() override {
- _splitDriver.reset();
- _writesTracker.reset();
- }
+ void tearDown() override {}
- ChunkWritesTracker& writesTracker() {
+ virtual ChunkWritesTracker& writesTracker() {
return *_writesTracker;
}
- boost::optional<ChunkSplitStateDriver>& splitDriver() {
+ virtual boost::optional<ChunkSplitStateDriver>& splitDriver() {
return *_splitDriver;
}
-private:
+protected:
std::shared_ptr<ChunkWritesTracker> _writesTracker;
std::unique_ptr<boost::optional<ChunkSplitStateDriver>> _splitDriver;
};
+class ChunkSplitStateDriverTest : public ChunkSplitStateDriverTestNoTeardown {
+public:
+ void tearDown() override {
+ _splitDriver.reset();
+ _writesTracker.reset();
+ }
+};
+
TEST(ChunkSplitStateDriverTest, InitiateSplitLeavesBytesWrittenUnchanged) {
auto writesTracker = std::make_shared<ChunkWritesTracker>();
uint64_t bytesInTrackerBeforeSplit{4};
@@ -82,20 +87,21 @@ TEST_F(ChunkSplitStateDriverTest, PrepareSplitClearsBytesWritten) {
ASSERT_EQ(writesTracker().getBytesWritten(), 0ull);
}
-TEST_F(ChunkSplitStateDriverTest, PrepareSplitFollowedByCancelSplitRestoresBytesWritten) {
+TEST_F(ChunkSplitStateDriverTestNoTeardown,
+ PrepareSplitFollowedByDestructorWithoutCommitRestoresBytesWritten) {
auto bytesInTracker = writesTracker().getBytesWritten();
splitDriver()->prepareSplit();
- splitDriver()->cancelSplit();
+ splitDriver().reset();
ASSERT_EQ(writesTracker().getBytesWritten(), bytesInTracker);
}
-TEST_F(ChunkSplitStateDriverTest,
- PrepareSplitThenAddBytesThenCancelSplitRestoresOldBytesWrittenPlusNewBytesWritten) {
+TEST_F(ChunkSplitStateDriverTestNoTeardown,
+ PrepareSplitFollowedByDestructorWithoutCommitRestoresOldBytesWrittenPlusNewBytesWritten) {
auto bytesInTracker = writesTracker().getBytesWritten();
splitDriver()->prepareSplit();
uint64_t extraBytesToAdd{4};
writesTracker().addBytesWritten(extraBytesToAdd);
- splitDriver()->cancelSplit();
+ splitDriver().reset();
ASSERT_EQ(writesTracker().getBytesWritten(), bytesInTracker + extraBytesToAdd);
}
@@ -125,9 +131,10 @@ TEST_F(ChunkSplitStateDriverTest, ShouldSplitReturnsFalseEvenAfterCommit) {
ASSERT_FALSE(writesTracker().shouldSplit(maxChunkSize));
}
-TEST_F(ChunkSplitStateDriverTest, ShouldSplitReturnsTrueAgainAfterCancel) {
+TEST_F(ChunkSplitStateDriverTestNoTeardown,
+ ShouldSplitReturnsTrueAfterPrepareSplitThenDestruction) {
splitDriver()->prepareSplit();
- splitDriver()->cancelSplit();
+ splitDriver().reset();
uint64_t maxChunkSize{0};
ASSERT_TRUE(writesTracker().shouldSplit(maxChunkSize));
@@ -139,9 +146,16 @@ DEATH_TEST_F(ChunkSplitStateDriverTest,
splitDriver()->commitSplit();
}
-DEATH_TEST_F(ChunkSplitStateDriverTest, CancelSplitAfterCommitErrors, "Invariant failure") {
- splitDriver()->commitSplit();
- splitDriver()->cancelSplit();
+TEST(ChunkSplitStateDriverTest, PrepareErrorsWhenChunkWritesTrackerNoLongerExists) {
+ std::unique_ptr<boost::optional<ChunkSplitStateDriver>> splitDriver;
+ {
+ auto writesTracker = std::make_shared<ChunkWritesTracker>();
+ uint64_t bytesToAdd{4};
+ writesTracker->addBytesWritten(bytesToAdd);
+ splitDriver = std::make_unique<boost::optional<ChunkSplitStateDriver>>(
+ ChunkSplitStateDriver::tryInitiateSplit(writesTracker));
+ }
+ ASSERT_THROWS(splitDriver->get().prepareSplit(), AssertionException);
}
} // namespace mongo