0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 09:32:32 +01:00

SERVER-44391 Preserve internal tables and temporary files when starting up after a clean shutdown

This commit is contained in:
Gregory Noma 2020-06-25 16:41:45 -04:00 committed by Evergreen Agent
parent 21075112a9
commit 08b190379b
3 changed files with 41 additions and 8 deletions

View File

@ -155,6 +155,7 @@
#include "mongo/db/system_index.h"
#include "mongo/db/transaction_participant.h"
#include "mongo/db/ttl.h"
#include "mongo/db/unclean_shutdown.h"
#include "mongo/db/wire_version.h"
#include "mongo/executor/network_connection_hook.h"
#include "mongo/executor/network_interface_factory.h"
@ -432,7 +433,9 @@ ExitCode _initAndListen(ServiceContext* serviceContext, int listenPort) {
startWatchdog(serviceContext);
if (!storageGlobalParams.readOnly) {
// When starting up after an unclean shutdown, we do not attempt to use any of the temporary
// files left from the previous run. Thus, we remove them in this case.
if (!storageGlobalParams.readOnly && startingAfterUncleanShutdown(serviceContext)) {
boost::filesystem::remove_all(storageGlobalParams.dbpath + "/_tmp/");
}
@ -463,6 +466,14 @@ ExitCode _initAndListen(ServiceContext* serviceContext, int listenPort) {
exitCleanly(EXIT_NEED_DOWNGRADE);
}
// This flag is used during storage engine initialization to perform behavior that is specific
// to recovering from an unclean shutdown. It is also used to determine whether temporary files
// should be removed. The last of these uses is done by repairDatabasesAndCheckVersion() above,
// so we reset the flag to false here. We reset the flag so that other users of these functions
// outside of startup do not perform behavior that is specific to starting up after an unclean
// shutdown.
startingAfterUncleanShutdown(serviceContext) = false;
auto replProcess = repl::ReplicationProcess::get(serviceContext);
invariant(replProcess);
const bool initialSyncFlag =

View File

@ -136,6 +136,9 @@ TEST_F(StorageEngineTest, ReconcileDropsTemporary) {
ASSERT(identExists(opCtx.get(), ident));
// Reconcile will only drop temporary idents when starting up after an unclean shutdown.
startingAfterUncleanShutdown(opCtx->getServiceContext()) = true;
auto reconcileResult = unittest::assertGet(reconcile(opCtx.get()));
ASSERT_EQUALS(0UL, reconcileResult.indexesToRebuild.size());
ASSERT_EQUALS(0UL, reconcileResult.indexBuildsToRestart.size());
@ -146,6 +149,28 @@ TEST_F(StorageEngineTest, ReconcileDropsTemporary) {
rs->finalizeTemporaryTable(opCtx.get(), TemporaryRecordStore::FinalizationAction::kDelete);
}
TEST_F(StorageEngineTest, ReconcileKeepsTemporary) {
auto opCtx = cc().makeOperationContext();
Lock::GlobalLock lk(&*opCtx, MODE_IS);
auto rs = makeTemporary(opCtx.get());
ASSERT(rs.get());
const std::string ident = rs->rs()->getIdent();
ASSERT(identExists(opCtx.get(), ident));
auto reconcileResult = unittest::assertGet(reconcile(opCtx.get()));
ASSERT_EQUALS(0UL, reconcileResult.indexesToRebuild.size());
ASSERT_EQUALS(0UL, reconcileResult.indexBuildsToRestart.size());
// The storage engine does not drop its temporary idents outside of starting up after an
// unclean shutdown.
ASSERT(identExists(opCtx.get(), ident));
rs->finalizeTemporaryTable(opCtx.get(), TemporaryRecordStore::FinalizationAction::kDelete);
}
TEST_F(StorageEngineTest, TemporaryDropsItself) {
auto opCtx = cc().makeOperationContext();

View File

@ -243,10 +243,6 @@ void StorageEngineImpl::loadCatalog(OperationContext* opCtx) {
KVPrefix::setLargestPrefix(maxSeenPrefix);
opCtx->recoveryUnit()->abandonSnapshot();
// Unset the unclean shutdown flag to avoid executing special behavior if this method is called
// after startup.
startingAfterUncleanShutdown(getGlobalServiceContext()) = false;
}
void StorageEngineImpl::_initCollection(OperationContext* opCtx,
@ -375,9 +371,10 @@ StatusWith<StorageEngine::ReconcileResult> StorageEngineImpl::reconcileCatalogAn
continue;
}
// Internal idents are dropped at the end after those left over from index builds are
// identified.
if (_catalog->isInternalIdent(it)) {
// When starting up after an unclean shutdown, we do not attempt to recover any state from
// the internal idents. Thus, we drop them in this case.
if (startingAfterUncleanShutdown(opCtx->getServiceContext()) &&
_catalog->isInternalIdent(it)) {
internalIdentsToDrop.insert(it);
continue;
}