summaryrefslogtreecommitdiff
path: root/src/mongo/db/commands/compact.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/commands/compact.cpp')
-rw-r--r--src/mongo/db/commands/compact.cpp73
1 files changed, 54 insertions, 19 deletions
diff --git a/src/mongo/db/commands/compact.cpp b/src/mongo/db/commands/compact.cpp
index 26ee8ab5d4b..48d899efcd1 100644
--- a/src/mongo/db/commands/compact.cpp
+++ b/src/mongo/db/commands/compact.cpp
@@ -27,23 +27,34 @@
* it in the license file.
*/
+#include <absl/container/btree_set.h>
#include <string>
#include <vector>
#include "mongo/db/auth/action_set.h"
#include "mongo/db/auth/action_type.h"
+#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/auth/privilege.h"
#include "mongo/db/catalog/collection.h"
+#include "mongo/db/catalog/collection_catalog.h"
#include "mongo/db/catalog/collection_compact.h"
#include "mongo/db/catalog/database.h"
#include "mongo/db/commands.h"
#include "mongo/db/concurrency/d_concurrency.h"
#include "mongo/db/curop.h"
+#include "mongo/db/db_raii.h"
#include "mongo/db/jsobj.h"
+#include "mongo/db/namespace_string.h"
+#include "mongo/db/operation_context.h"
+#include "mongo/db/repl/member_state.h"
#include "mongo/db/repl/replication_coordinator.h"
namespace mongo {
+namespace {
+static absl::btree_set<UUID> compactsRunning;
+} // namespace
+
using std::string;
using std::stringstream;
@@ -65,6 +76,7 @@ public:
actions.addAction(ActionType::compact);
out->push_back(Privilege(parseResourcePattern(dbname, cmdObj), actions));
}
+
std::string help() const override {
return "compact collection\n"
"warning: this operation locks the database and is slow. you can cancel with "
@@ -75,36 +87,59 @@ public:
CompactCmd() : ErrmsgCommandDeprecated("compact") {}
virtual bool errmsgRun(OperationContext* opCtx,
- const string& db,
+ const std::string& dbName,
const BSONObj& cmdObj,
string& errmsg,
BSONObjBuilder& result) {
- NamespaceString nss = CommandHelpers::parseNsCollectionRequired(db, cmdObj);
-
- repl::ReplicationCoordinator* replCoord = repl::ReplicationCoordinator::get(opCtx);
- if (replCoord->getMemberState().primary() && !cmdObj["force"].trueValue()) {
- errmsg =
- "will not run compact on an active replica set primary as this is a slow blocking "
- "operation. use force:true to force";
- return false;
- }
+ NamespaceString collectionNss = CommandHelpers::parseNsCollectionRequired(dbName, cmdObj);
+
+ Lock::GlobalLock lk(opCtx,
+ MODE_IX,
+ Date_t::max(),
+ Lock::InterruptBehavior::kThrow,
+ /*skipRSTLLock=*/true);
+
+ // Hold reference to the catalog for collection lookup without locks to be safe.
+ auto collectionCatalog = CollectionCatalog::get(opCtx);
- if (nss.isSystem()) {
- // Items in system.* cannot be moved as there might be pointers to them.
- errmsg = "can't compact a system namespace";
- return false;
+ CollectionPtr collection = [&]() {
+ if (CollectionPtr collection = CollectionPtr(
+ collectionCatalog->lookupCollectionByNamespace(opCtx, collectionNss))) {
+ return collection;
+ }
+
+ // Check if this is a time-series collection.
+ auto bucketsNs = collectionNss.makeTimeseriesBucketsNamespace();
+ if (CollectionPtr collection = CollectionPtr(
+ collectionCatalog->lookupCollectionByNamespace(opCtx, bucketsNs))) {
+ return collection;
+ }
+
+ return CollectionPtr();
+ }();
+
+ if (!collection) {
+ std::shared_ptr<const ViewDefinition> view =
+ collectionCatalog->lookupView(opCtx, collectionNss);
+ uassert(ErrorCodes::CommandNotSupportedOnView, "can't compact a view", !view);
+ uasserted(ErrorCodes::NamespaceNotFound, "collection does not exist");
}
- // This command is internal to the storage engine and should not block oplog application.
- ShouldNotConflictWithSecondaryBatchApplicationBlock noPBWMBlock(opCtx->lockState());
+ AutoStatsTracker statsTracker(opCtx,
+ collectionNss,
+ Top::LockType::NotLocked,
+ AutoStatsTracker::LogMode::kUpdateTopAndCurOp,
+ collectionCatalog->getDatabaseProfileLevel(dbName));
+
+ StatusWith<int64_t> status = compactCollection(opCtx, collection);
- StatusWith<int64_t> status = compactCollection(opCtx, nss);
uassertStatusOK(status.getStatus());
int64_t bytesFreed = status.getValue();
if (bytesFreed < 0) {
- // When compacting a collection that is actively being written to, it is possible that
- // the collection is larger at the completion of compaction than when it started.
+ // When compacting a collection that is actively being written to, it is possible
+ // that the collection is larger at the completion of compaction than when it
+ // started.
bytesFreed = 0;
}