summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias Stearn <redbeard0531@gmail.com>2016-01-15 16:30:52 -0500
committerMathias Stearn <redbeard0531@gmail.com>2016-01-18 13:33:40 -0500
commitc44a3ecdffd5c98fdd2daa6e46f52c50ff594576 (patch)
tree4a04d9df845d94beba13abcde6b13a8ab6e0ba6d
parent930e47f1864d0319b7d9033ad2c2bf99f02014c1 (diff)
downloadmongo-r3.0.9-rc0.tar.gz
SERVER-19128 Clean up interaction of background index builds and cursor killingr3.0.9-rc0
This reverts commit 90a684ad25a86deff16f80e11e257c6ac6611683, restoring 1d26b77d115eb39f03dffbdbaccf10e696cd4fe3.
-rw-r--r--src/mongo/db/background.h10
-rw-r--r--src/mongo/db/catalog/collection.cpp6
-rw-r--r--src/mongo/db/catalog/cursor_manager.cpp2
-rw-r--r--src/mongo/db/catalog/database.cpp2
-rw-r--r--src/mongo/db/catalog/index_catalog.cpp17
-rw-r--r--src/mongo/db/catalog/index_create.cpp14
-rw-r--r--src/mongo/db/dbcommands.cpp4
7 files changed, 40 insertions, 15 deletions
diff --git a/src/mongo/db/background.h b/src/mongo/db/background.h
index b5ec4caea70..3a40a286bda 100644
--- a/src/mongo/db/background.h
+++ b/src/mongo/db/background.h
@@ -64,6 +64,16 @@ public:
static void awaitNoBgOpInProgForNs(const StringData& ns);
static void dump(std::ostream&);
+ static bool inProgForNs(const NamespaceString& ns) {
+ return inProgForNs(ns.ns());
+ }
+ static void assertNoBgOpInProgForNs(const NamespaceString& ns) {
+ assertNoBgOpInProgForNs(ns.ns());
+ }
+ static void awaitNoBgOpInProgForNs(const NamespaceString& ns) {
+ awaitNoBgOpInProgForNs(ns.ns());
+ }
+
/* check for in progress before instantiating */
BackgroundOperation(const StringData& ns);
diff --git a/src/mongo/db/catalog/collection.cpp b/src/mongo/db/catalog/collection.cpp
index 936909a4456..89e58c10021 100644
--- a/src/mongo/db/catalog/collection.cpp
+++ b/src/mongo/db/catalog/collection.cpp
@@ -38,6 +38,7 @@
#include "mongo/base/counter.h"
#include "mongo/base/owned_pointer_map.h"
+#include "mongo/db/background.h"
#include "mongo/db/clientcursor.h"
#include "mongo/db/commands/server_status_metric.h"
#include "mongo/db/curop.h"
@@ -480,7 +481,8 @@ uint64_t Collection::getIndexSize(OperationContext* opCtx, BSONObjBuilder* detai
*/
Status Collection::truncate(OperationContext* txn) {
dassert(txn->lockState()->isCollectionLockedForMode(ns().toString(), MODE_X));
- massert(17445, "index build in progress", _indexCatalog.numIndexesInProgress(txn) == 0);
+ BackgroundOperation::assertNoBgOpInProgForNs(ns());
+ invariant(_indexCatalog.numIndexesInProgress(txn) == 0);
// 1) store index specs
vector<BSONObj> indexSpecs;
@@ -517,6 +519,8 @@ Status Collection::truncate(OperationContext* txn) {
void Collection::temp_cappedTruncateAfter(OperationContext* txn, RecordId end, bool inclusive) {
dassert(txn->lockState()->isCollectionLockedForMode(ns().toString(), MODE_IX));
invariant(isCapped());
+ BackgroundOperation::assertNoBgOpInProgForNs(ns());
+ invariant(_indexCatalog.numIndexesInProgress(txn) == 0);
_cursorManager.invalidateAll(false);
_recordStore->temp_cappedTruncateAfter(txn, end, inclusive);
diff --git a/src/mongo/db/catalog/cursor_manager.cpp b/src/mongo/db/catalog/cursor_manager.cpp
index 6507b8fd1a5..d192d52ba25 100644
--- a/src/mongo/db/catalog/cursor_manager.cpp
+++ b/src/mongo/db/catalog/cursor_manager.cpp
@@ -34,6 +34,7 @@
#include "mongo/base/init.h"
#include "mongo/db/audit.h"
#include "mongo/db/auth/authorization_session.h"
+#include "mongo/db/background.h"
#include "mongo/db/catalog/collection.h"
#include "mongo/db/catalog/database.h"
#include "mongo/db/catalog/database_holder.h"
@@ -313,6 +314,7 @@ CursorManager::~CursorManager() {
void CursorManager::invalidateAll(bool collectionGoingAway) {
SimpleMutex::scoped_lock lk(_mutex);
+ fassert(28819, !BackgroundOperation::inProgForNs(_nss));
for (ExecSet::iterator it = _nonCachedExecutors.begin(); it != _nonCachedExecutors.end();
++it) {
diff --git a/src/mongo/db/catalog/database.cpp b/src/mongo/db/catalog/database.cpp
index 0d6f0e9aef2..652717dddce 100644
--- a/src/mongo/db/catalog/database.cpp
+++ b/src/mongo/db/catalog/database.cpp
@@ -432,6 +432,8 @@ Status Database::renameCollection(OperationContext* txn,
bool stayTemp) {
audit::logRenameCollection(currentClient.get(), fromNS, toNS);
invariant(txn->lockState()->isDbLockedForMode(name(), MODE_X));
+ BackgroundOperation::assertNoBgOpInProgForNs(fromNS);
+ BackgroundOperation::assertNoBgOpInProgForNs(toNS);
{ // remove anything cached
Collection* coll = getCollection(fromNS);
diff --git a/src/mongo/db/catalog/index_catalog.cpp b/src/mongo/db/catalog/index_catalog.cpp
index ceef866f8de..c7752655ee5 100644
--- a/src/mongo/db/catalog/index_catalog.cpp
+++ b/src/mongo/db/catalog/index_catalog.cpp
@@ -744,15 +744,21 @@ Status IndexCatalog::_dropIndex(OperationContext* txn, IndexCatalogEntry* entry)
if (!status.isOK())
return status;
- // there may be pointers pointing at keys in the btree(s). kill them.
- // TODO: can this can only clear cursors on this index?
- _collection->getCursorManager()->invalidateAll(false);
-
// wipe out stats
_collection->infoCache()->reset(txn);
- string indexNamespace = entry->descriptor()->indexNamespace();
+ // Pulling indexName/indexNamespace out as they are needed post descriptor release.
string indexName = entry->descriptor()->indexName();
+ string indexNamespace = entry->descriptor()->indexNamespace();
+
+ // If any cursors could be using this index, invalidate them. Note that we do not use indexes
+ // until they are ready, so we do not need to invalidate anything if the index fails while it is
+ // being built.
+ // TODO only kill cursors that are actually using the index rather than everything on this
+ // collection.
+ if (entry->isReady(txn)) {
+ _collection->getCursorManager()->invalidateAll(false);
+ }
// --------- START REAL WORK ----------
@@ -966,6 +972,7 @@ const IndexCatalogEntry* IndexCatalog::getEntry(const IndexDescriptor* desc) con
const IndexDescriptor* IndexCatalog::refreshEntry(OperationContext* txn,
const IndexDescriptor* oldDesc) {
invariant(txn->lockState()->isCollectionLockedForMode(_collection->ns().ns(), MODE_X));
+ invariant(!BackgroundOperation::inProgForNs(_collection->ns()));
const std::string indexName = oldDesc->indexName();
invariant(_collection->getCatalogEntry()->isIndexReady(txn, indexName));
diff --git a/src/mongo/db/catalog/index_create.cpp b/src/mongo/db/catalog/index_create.cpp
index dcf70e5c3a0..3209b6cfbf5 100644
--- a/src/mongo/db/catalog/index_create.cpp
+++ b/src/mongo/db/catalog/index_create.cpp
@@ -45,6 +45,7 @@
#include "mongo/db/clientcursor.h"
#include "mongo/db/concurrency/write_conflict_exception.h"
#include "mongo/db/curop.h"
+#include "mongo/db/exec/working_set_common.h"
#include "mongo/db/query/internal_plans.h"
#include "mongo/db/repl/oplog.h"
#include "mongo/db/repl/replication_coordinator_global.h"
@@ -285,15 +286,10 @@ Status MultiIndexBlock::insertAllDocumentsInCollection(std::set<RecordId>* dupsO
}
}
- if (state != PlanExecutor::IS_EOF) {
- // If the plan executor was killed, this means the DB/collection was dropped and so it
- // is not safe to cleanup the in-progress indexes.
- if (state == PlanExecutor::DEAD) {
- abortWithoutCleanup();
- }
-
- uasserted(28550, "Unable to complete index build as the collection is no longer readable");
- }
+ uassert(28550,
+ "Unable to complete index build due to collection scan failure: " +
+ WorkingSetCommon::toStatusString(objToIndex.value()),
+ state == PlanExecutor::IS_EOF);
progress->finished();
diff --git a/src/mongo/db/dbcommands.cpp b/src/mongo/db/dbcommands.cpp
index d59ddbfc132..e83a287631b 100644
--- a/src/mongo/db/dbcommands.cpp
+++ b/src/mongo/db/dbcommands.cpp
@@ -1079,6 +1079,10 @@ public:
Database* const db = autoDb.getDb();
Collection* coll = db ? db->getCollection(ns) : NULL;
+ // This can kill all cursors so don't allow running it while a background operation is in
+ // progress.
+ BackgroundOperation::assertNoBgOpInProgForNs(ns);
+
// If db/collection does not exist, short circuit and return.
if (!db || !coll) {
errmsg = "ns does not exist";