summaryrefslogtreecommitdiff
path: root/src/mongo/db/catalog/coll_mod.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/catalog/coll_mod.cpp')
-rw-r--r--src/mongo/db/catalog/coll_mod.cpp250
1 files changed, 121 insertions, 129 deletions
diff --git a/src/mongo/db/catalog/coll_mod.cpp b/src/mongo/db/catalog/coll_mod.cpp
index 768ee713b0a..00a3a643a5b 100644
--- a/src/mongo/db/catalog/coll_mod.cpp
+++ b/src/mongo/db/catalog/coll_mod.cpp
@@ -40,148 +40,140 @@
#include "mongo/db/service_context.h"
namespace mongo {
- Status collMod(OperationContext* txn,
- const NamespaceString& ns,
- const BSONObj& cmdObj,
- BSONObjBuilder* result) {
- StringData dbName = ns.db();
- ScopedTransaction transaction(txn, MODE_IX);
- AutoGetDb autoDb(txn, dbName, MODE_X);
- Database* const db = autoDb.getDb();
- Collection* coll = db ? db->getCollection(ns) : NULL;
-
- // If db/collection does not exist, short circuit and return.
- if (!db || !coll) {
- return Status(ErrorCodes::NamespaceNotFound, "ns does not exist");
- }
+Status collMod(OperationContext* txn,
+ const NamespaceString& ns,
+ const BSONObj& cmdObj,
+ BSONObjBuilder* result) {
+ StringData dbName = ns.db();
+ ScopedTransaction transaction(txn, MODE_IX);
+ AutoGetDb autoDb(txn, dbName, MODE_X);
+ Database* const db = autoDb.getDb();
+ Collection* coll = db ? db->getCollection(ns) : NULL;
+
+ // If db/collection does not exist, short circuit and return.
+ if (!db || !coll) {
+ return Status(ErrorCodes::NamespaceNotFound, "ns does not exist");
+ }
- OldClientContext ctx(txn, ns);
+ OldClientContext ctx(txn, ns);
- bool userInitiatedWritesAndNotPrimary = txn->writesAreReplicated() &&
- !repl::getGlobalReplicationCoordinator()->canAcceptWritesFor(ns);
+ bool userInitiatedWritesAndNotPrimary = txn->writesAreReplicated() &&
+ !repl::getGlobalReplicationCoordinator()->canAcceptWritesFor(ns);
- if (userInitiatedWritesAndNotPrimary) {
- return Status(ErrorCodes::NotMaster,
- str::stream() << "Not primary while setting collection options on "
- << ns.toString());
- }
+ if (userInitiatedWritesAndNotPrimary) {
+ return Status(ErrorCodes::NotMaster,
+ str::stream() << "Not primary while setting collection options on "
+ << ns.toString());
+ }
+
+ WriteUnitOfWork wunit(txn);
- WriteUnitOfWork wunit(txn);
+ Status errorStatus = Status::OK();
- Status errorStatus = Status::OK();
+ BSONForEach(e, cmdObj) {
+ if (str::equals("collMod", e.fieldName())) {
+ // no-op
+ } else if (str::startsWith(e.fieldName(), "$")) {
+ // no-op ignore top-level fields prefixed with $. They are for the command processor
+ } else if (LiteParsedQuery::cmdOptionMaxTimeMS == e.fieldNameStringData()) {
+ // no-op
+ } else if (str::equals("index", e.fieldName())) {
+ BSONObj indexObj = e.Obj();
+ BSONObj keyPattern = indexObj.getObjectField("keyPattern");
- BSONForEach(e, cmdObj) {
- if (str::equals("collMod", e.fieldName())) {
- // no-op
+ if (keyPattern.isEmpty()) {
+ errorStatus = Status(ErrorCodes::InvalidOptions, "no keyPattern specified");
+ continue;
}
- else if (str::startsWith(e.fieldName(), "$")) {
- // no-op ignore top-level fields prefixed with $. They are for the command processor
+
+ BSONElement newExpireSecs = indexObj["expireAfterSeconds"];
+ if (newExpireSecs.eoo()) {
+ errorStatus = Status(ErrorCodes::InvalidOptions, "no expireAfterSeconds field");
+ continue;
}
- else if (LiteParsedQuery::cmdOptionMaxTimeMS == e.fieldNameStringData()) {
- // no-op
+ if (!newExpireSecs.isNumber()) {
+ errorStatus =
+ Status(ErrorCodes::InvalidOptions, "expireAfterSeconds field must be a number");
+ continue;
}
- else if (str::equals("index", e.fieldName())) {
- BSONObj indexObj = e.Obj();
- BSONObj keyPattern = indexObj.getObjectField("keyPattern");
-
- if (keyPattern.isEmpty()){
- errorStatus = Status(ErrorCodes::InvalidOptions, "no keyPattern specified");
- continue;
- }
-
- BSONElement newExpireSecs = indexObj["expireAfterSeconds"];
- if (newExpireSecs.eoo()) {
- errorStatus = Status(ErrorCodes::InvalidOptions, "no expireAfterSeconds field");
- continue;
- }
- if (! newExpireSecs.isNumber()) {
- errorStatus = Status(ErrorCodes::InvalidOptions,
- "expireAfterSeconds field must be a number");
- continue;
- }
-
- const IndexDescriptor* idx = coll->getIndexCatalog()
- ->findIndexByKeyPattern(txn, keyPattern);
- if (idx == NULL) {
- errorStatus = Status(ErrorCodes::InvalidOptions,
- str::stream() << "cannot find index " << keyPattern
- << " for ns " << ns.toString());
- continue;
- }
- BSONElement oldExpireSecs = idx->infoObj().getField("expireAfterSeconds");
- if (oldExpireSecs.eoo()){
- errorStatus = Status(ErrorCodes::InvalidOptions,
- "no expireAfterSeconds field to update");
- continue;
- }
- if (! oldExpireSecs.isNumber()) {
- errorStatus = Status(ErrorCodes::InvalidOptions,
- "existing expireAfterSeconds field is not a number");
- continue;
- }
-
- if (oldExpireSecs != newExpireSecs) {
- result->appendAs(oldExpireSecs, "expireAfterSeconds_old");
- // Change the value of "expireAfterSeconds" on disk.
- coll->getCatalogEntry()->updateTTLSetting(txn,
- idx->indexName(),
- newExpireSecs.numberLong());
- // Notify the index catalog that the definition of this index changed.
- idx = coll->getIndexCatalog()->refreshEntry(txn, idx);
- result->appendAs(newExpireSecs , "expireAfterSeconds_new");
- }
+
+ const IndexDescriptor* idx =
+ coll->getIndexCatalog()->findIndexByKeyPattern(txn, keyPattern);
+ if (idx == NULL) {
+ errorStatus = Status(ErrorCodes::InvalidOptions,
+ str::stream() << "cannot find index " << keyPattern
+ << " for ns " << ns.toString());
+ continue;
}
- else if (str::equals("validator", e.fieldName())) {
- auto status = coll->setValidator(txn, e.Obj());
- if (!status.isOK())
- errorStatus = std::move(status);
+ BSONElement oldExpireSecs = idx->infoObj().getField("expireAfterSeconds");
+ if (oldExpireSecs.eoo()) {
+ errorStatus =
+ Status(ErrorCodes::InvalidOptions, "no expireAfterSeconds field to update");
+ continue;
}
- else {
- // As of SERVER-17312 we only support these two options. When SERVER-17320 is
- // resolved this will need to be enhanced to handle other options.
- typedef CollectionOptions CO;
- const StringData name = e.fieldNameStringData();
- const int flag = (name == "usePowerOf2Sizes") ? CO::Flag_UsePowerOf2Sizes :
- (name == "noPadding") ? CO::Flag_NoPadding :
- 0;
- if (!flag) {
- errorStatus = Status(ErrorCodes::InvalidOptions,
- str::stream() << "unknown option to collMod: " << name);
- continue;
- }
-
- CollectionCatalogEntry* cce = coll->getCatalogEntry();
-
- const int oldFlags = cce->getCollectionOptions(txn).flags;
- const bool oldSetting = oldFlags & flag;
- const bool newSetting = e.trueValue();
-
- result->appendBool(name.toString() + "_old", oldSetting);
- result->appendBool(name.toString() + "_new", newSetting);
-
- const int newFlags = newSetting
- ? (oldFlags | flag) // set flag
- : (oldFlags & ~flag); // clear flag
-
- // NOTE we do this unconditionally to ensure that we note that the user has
- // explicitly set flags, even if they are just setting the default.
- cce->updateFlags(txn, newFlags);
-
- const CollectionOptions newOptions = cce->getCollectionOptions(txn);
- invariant(newOptions.flags == newFlags);
- invariant(newOptions.flagsSet);
+ if (!oldExpireSecs.isNumber()) {
+ errorStatus = Status(ErrorCodes::InvalidOptions,
+ "existing expireAfterSeconds field is not a number");
+ continue;
}
- }
- if (!errorStatus.isOK()) {
- return errorStatus;
- }
+ if (oldExpireSecs != newExpireSecs) {
+ result->appendAs(oldExpireSecs, "expireAfterSeconds_old");
+ // Change the value of "expireAfterSeconds" on disk.
+ coll->getCatalogEntry()->updateTTLSetting(
+ txn, idx->indexName(), newExpireSecs.numberLong());
+ // Notify the index catalog that the definition of this index changed.
+ idx = coll->getIndexCatalog()->refreshEntry(txn, idx);
+ result->appendAs(newExpireSecs, "expireAfterSeconds_new");
+ }
+ } else if (str::equals("validator", e.fieldName())) {
+ auto status = coll->setValidator(txn, e.Obj());
+ if (!status.isOK())
+ errorStatus = std::move(status);
+ } else {
+ // As of SERVER-17312 we only support these two options. When SERVER-17320 is
+ // resolved this will need to be enhanced to handle other options.
+ typedef CollectionOptions CO;
+ const StringData name = e.fieldNameStringData();
+ const int flag = (name == "usePowerOf2Sizes")
+ ? CO::Flag_UsePowerOf2Sizes
+ : (name == "noPadding") ? CO::Flag_NoPadding : 0;
+ if (!flag) {
+ errorStatus = Status(ErrorCodes::InvalidOptions,
+ str::stream() << "unknown option to collMod: " << name);
+ continue;
+ }
+
+ CollectionCatalogEntry* cce = coll->getCatalogEntry();
+
+ const int oldFlags = cce->getCollectionOptions(txn).flags;
+ const bool oldSetting = oldFlags & flag;
+ const bool newSetting = e.trueValue();
+
+ result->appendBool(name.toString() + "_old", oldSetting);
+ result->appendBool(name.toString() + "_new", newSetting);
+
+ const int newFlags = newSetting ? (oldFlags | flag) // set flag
+ : (oldFlags & ~flag); // clear flag
- getGlobalServiceContext()->getOpObserver()->onCollMod(txn,
- (dbName.toString() + ".$cmd").c_str(),
- cmdObj);
+ // NOTE we do this unconditionally to ensure that we note that the user has
+ // explicitly set flags, even if they are just setting the default.
+ cce->updateFlags(txn, newFlags);
- wunit.commit();
- return Status::OK();
+ const CollectionOptions newOptions = cce->getCollectionOptions(txn);
+ invariant(newOptions.flags == newFlags);
+ invariant(newOptions.flagsSet);
+ }
+ }
+
+ if (!errorStatus.isOK()) {
+ return errorStatus;
}
-} // namespace mongo
+
+ getGlobalServiceContext()->getOpObserver()->onCollMod(
+ txn, (dbName.toString() + ".$cmd").c_str(), cmdObj);
+
+ wunit.commit();
+ return Status::OK();
+}
+} // namespace mongo