summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTess Avitabile <tess.avitabile@mongodb.com>2016-10-24 12:04:42 -0400
committerTess Avitabile <tess.avitabile@mongodb.com>2016-10-28 19:07:00 -0400
commite923952dd2c492ab19c34bfe094da6b855d0f99d (patch)
treeac1fdf64ee83055c63de3f62f3720a4dffcfea92 /src
parent8ac6f69b0879df0e69b8d9929badb472772a3bca (diff)
downloadmongo-e923952dd2c492ab19c34bfe094da6b855d0f99d.tar.gz
SERVER-26515 Create collection with v=2 index should include full index spec in oplog
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/catalog/collection.cpp2
-rw-r--r--src/mongo/db/catalog/database.cpp14
-rw-r--r--src/mongo/db/catalog/index_catalog.cpp5
-rw-r--r--src/mongo/db/catalog/index_catalog.h5
-rw-r--r--src/mongo/db/commands/mr.cpp8
-rw-r--r--src/mongo/db/op_observer.cpp15
-rw-r--r--src/mongo/db/op_observer.h3
-rw-r--r--src/mongo/db/repl/oplog.cpp17
8 files changed, 48 insertions, 21 deletions
diff --git a/src/mongo/db/catalog/collection.cpp b/src/mongo/db/catalog/collection.cpp
index 0df69a9d2e6..cccaa6b257b 100644
--- a/src/mongo/db/catalog/collection.cpp
+++ b/src/mongo/db/catalog/collection.cpp
@@ -918,7 +918,7 @@ Status Collection::truncate(OperationContext* txn) {
// 4) re-create indexes
for (size_t i = 0; i < indexSpecs.size(); i++) {
- status = _indexCatalog.createIndexOnEmptyCollection(txn, indexSpecs[i]);
+ status = _indexCatalog.createIndexOnEmptyCollection(txn, indexSpecs[i]).getStatus();
if (!status.isOK())
return status;
}
diff --git a/src/mongo/db/catalog/database.cpp b/src/mongo/db/catalog/database.cpp
index b667e5022a3..438c8ed91fe 100644
--- a/src/mongo/db/catalog/database.cpp
+++ b/src/mongo/db/catalog/database.cpp
@@ -579,22 +579,16 @@ Collection* Database::createCollection(OperationContext* txn,
invariant(collection);
_collections[ns] = collection;
+ BSONObj fullIdIndexSpec;
+
if (createIdIndex) {
if (collection->requiresIdIndex()) {
if (options.autoIndexId == CollectionOptions::YES ||
options.autoIndexId == CollectionOptions::DEFAULT) {
- // The creation of the _id index isn't replicated and is instead implicit in the
- // creation of the collection. This means that the version of the _id index to build
- // is technically unspecified. However, we're able to use the
- // featureCompatibilityVersion of this server to determine the default index version
- // to use because we apply commands (opType == 'c') in their own batch. This
- // guarantees the write to the admin.system.version collection from the
- // "setFeatureCompatibilityVersion" command either happens entirely before the
- // collection creation or it happens entirely after.
const auto featureCompatibilityVersion =
serverGlobalParams.featureCompatibility.version.load();
IndexCatalog* ic = collection->getIndexCatalog();
- uassertStatusOK(ic->createIndexOnEmptyCollection(
+ fullIdIndexSpec = uassertStatusOK(ic->createIndexOnEmptyCollection(
txn,
!idIndex.isEmpty() ? idIndex
: ic->getDefaultIdIndexSpec(featureCompatibilityVersion)));
@@ -608,7 +602,7 @@ Collection* Database::createCollection(OperationContext* txn,
auto opObserver = getGlobalServiceContext()->getOpObserver();
if (opObserver)
- opObserver->onCreateCollection(txn, nss, options);
+ opObserver->onCreateCollection(txn, nss, options, fullIdIndexSpec);
return collection;
}
diff --git a/src/mongo/db/catalog/index_catalog.cpp b/src/mongo/db/catalog/index_catalog.cpp
index e680a852360..f8d3a04f4c1 100644
--- a/src/mongo/db/catalog/index_catalog.cpp
+++ b/src/mongo/db/catalog/index_catalog.cpp
@@ -299,7 +299,8 @@ StatusWith<BSONObj> IndexCatalog::prepareSpecForCreate(OperationContext* txn,
return fixed;
}
-Status IndexCatalog::createIndexOnEmptyCollection(OperationContext* txn, BSONObj spec) {
+StatusWith<BSONObj> IndexCatalog::createIndexOnEmptyCollection(OperationContext* txn,
+ BSONObj spec) {
invariant(txn->lockState()->isCollectionLockedForMode(_collection->ns().toString(), MODE_X));
invariant(_collection->numRecords(txn) == 0);
@@ -342,7 +343,7 @@ Status IndexCatalog::createIndexOnEmptyCollection(OperationContext* txn, BSONObj
// sanity check
invariant(_collection->getCatalogEntry()->isIndexReady(txn, descriptor->indexName()));
- return Status::OK();
+ return spec;
}
IndexCatalog::IndexBuildBlock::IndexBuildBlock(OperationContext* txn,
diff --git a/src/mongo/db/catalog/index_catalog.h b/src/mongo/db/catalog/index_catalog.h
index 446a949ff2f..bd0c919076a 100644
--- a/src/mongo/db/catalog/index_catalog.h
+++ b/src/mongo/db/catalog/index_catalog.h
@@ -211,9 +211,10 @@ public:
/**
* Call this only on an empty collection from inside a WriteUnitOfWork. Index creation on an
- * empty collection can be rolled back as part of a larger WUOW.
+ * empty collection can be rolled back as part of a larger WUOW. Returns the full specification
+ * of the created index, as it is stored in this index catalog.
*/
- Status createIndexOnEmptyCollection(OperationContext* txn, BSONObj spec);
+ StatusWith<BSONObj> createIndexOnEmptyCollection(OperationContext* txn, BSONObj spec);
StatusWith<BSONObj> prepareSpecForCreate(OperationContext* txn, const BSONObj& original) const;
diff --git a/src/mongo/db/commands/mr.cpp b/src/mongo/db/commands/mr.cpp
index 920eb9aa980..3f2f13d2db0 100644
--- a/src/mongo/db/commands/mr.cpp
+++ b/src/mongo/db/commands/mr.cpp
@@ -424,8 +424,9 @@ void State::prepTempCollection() {
<< "_temp_0"
<< "v"
<< static_cast<int>(IndexVersion::kV2));
- Status status =
- incColl->getIndexCatalog()->createIndexOnEmptyCollection(_txn, indexSpec);
+ Status status = incColl->getIndexCatalog()
+ ->createIndexOnEmptyCollection(_txn, indexSpec)
+ .getStatus();
if (!status.isOK()) {
uasserted(17305,
str::stream() << "createIndex failed for mr incLong ns: "
@@ -486,7 +487,8 @@ void State::prepTempCollection() {
for (vector<BSONObj>::iterator it = indexesToInsert.begin(); it != indexesToInsert.end();
++it) {
- Status status = tempColl->getIndexCatalog()->createIndexOnEmptyCollection(_txn, *it);
+ Status status =
+ tempColl->getIndexCatalog()->createIndexOnEmptyCollection(_txn, *it).getStatus();
if (!status.isOK()) {
if (status.code() == ErrorCodes::IndexAlreadyExists) {
continue;
diff --git a/src/mongo/db/op_observer.cpp b/src/mongo/db/op_observer.cpp
index 8defc1c71fe..99e1fe2f649 100644
--- a/src/mongo/db/op_observer.cpp
+++ b/src/mongo/db/op_observer.cpp
@@ -34,6 +34,7 @@
#include "mongo/db/catalog/collection_options.h"
#include "mongo/db/commands/dbhash.h"
#include "mongo/db/commands/feature_compatibility_version.h"
+#include "mongo/db/index/index_descriptor.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/repl/oplog.h"
@@ -173,11 +174,23 @@ void OpObserver::onOpMessage(OperationContext* txn, const BSONObj& msgObj) {
void OpObserver::onCreateCollection(OperationContext* txn,
const NamespaceString& collectionName,
- const CollectionOptions& options) {
+ const CollectionOptions& options,
+ const BSONObj& idIndex) {
std::string dbName = collectionName.db().toString() + ".$cmd";
BSONObjBuilder b;
b.append("create", collectionName.coll().toString());
b.appendElements(options.toBSON());
+
+ // Include the full _id index spec in the oplog for index versions >= 2.
+ if (!idIndex.isEmpty()) {
+ auto versionElem = idIndex[IndexDescriptor::kIndexVersionFieldName];
+ invariant(versionElem.isNumber());
+ if (IndexDescriptor::IndexVersion::kV2 <=
+ static_cast<IndexDescriptor::IndexVersion>(versionElem.numberInt())) {
+ b.append("idIndex", idIndex);
+ }
+ }
+
BSONObj cmdObj = b.obj();
if (!collectionName.isSystemDotProfile()) {
diff --git a/src/mongo/db/op_observer.h b/src/mongo/db/op_observer.h
index b5a2d926489..e9c6f7d7425 100644
--- a/src/mongo/db/op_observer.h
+++ b/src/mongo/db/op_observer.h
@@ -95,7 +95,8 @@ public:
void onOpMessage(OperationContext* txn, const BSONObj& msgObj);
void onCreateCollection(OperationContext* txn,
const NamespaceString& collectionName,
- const CollectionOptions& options);
+ const CollectionOptions& options,
+ const BSONObj& idIndex);
void onCollMod(OperationContext* txn, const std::string& dbName, const BSONObj& collModCmd);
void onDropDatabase(OperationContext* txn, const std::string& dbName);
void onDropCollection(OperationContext* txn, const NamespaceString& collectionName);
diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp
index cfd4b5792cc..a2fd477ab9d 100644
--- a/src/mongo/db/repl/oplog.cpp
+++ b/src/mongo/db/repl/oplog.cpp
@@ -575,7 +575,22 @@ struct ApplyOpMetadata {
std::map<std::string, ApplyOpMetadata> opsMap = {
{"create",
{[](OperationContext* txn, const char* ns, BSONObj& cmd) -> Status {
- return createCollection(txn, NamespaceString(ns).db().toString(), cmd);
+ const NamespaceString nss(parseNs(ns, cmd));
+ if (auto idIndexElem = cmd["idIndex"]) {
+ // Remove "idIndex" field from command.
+ auto cmdWithoutIdIndex = cmd.removeField("idIndex");
+ return createCollection(
+ txn, nss.db().toString(), cmdWithoutIdIndex, idIndexElem.Obj());
+ }
+
+ // No _id index spec was provided, so we should build a v:1 _id index.
+ BSONObjBuilder idIndexSpecBuilder;
+ idIndexSpecBuilder.append(IndexDescriptor::kIndexVersionFieldName,
+ static_cast<int>(IndexVersion::kV1));
+ idIndexSpecBuilder.append(IndexDescriptor::kIndexNameFieldName, "_id_");
+ idIndexSpecBuilder.append(IndexDescriptor::kNamespaceFieldName, nss.ns());
+ idIndexSpecBuilder.append(IndexDescriptor::kKeyPatternFieldName, BSON("_id" << 1));
+ return createCollection(txn, nss.db().toString(), cmd, idIndexSpecBuilder.done());
},
{ErrorCodes::NamespaceExists}}},
{"collMod", {[](OperationContext* txn, const char* ns, BSONObj& cmd) -> Status {