summaryrefslogtreecommitdiff
path: root/src/mongo/db/session_catalog_mongod.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/session_catalog_mongod.cpp')
-rw-r--r--src/mongo/db/session_catalog_mongod.cpp141
1 files changed, 80 insertions, 61 deletions
diff --git a/src/mongo/db/session_catalog_mongod.cpp b/src/mongo/db/session_catalog_mongod.cpp
index eeb1ffb175a..fcefa1ed69b 100644
--- a/src/mongo/db/session_catalog_mongod.cpp
+++ b/src/mongo/db/session_catalog_mongod.cpp
@@ -208,12 +208,70 @@ const auto kIdProjection = BSON(SessionTxnRecord::kSessionIdFieldName << 1);
const auto kSortById = BSON(SessionTxnRecord::kSessionIdFieldName << 1);
const auto kLastWriteDateFieldName = SessionTxnRecord::kLastWriteDateFieldName;
+template <typename SessionContainer>
+int removeSessionsTransactionRecordsFromDisk(OperationContext* opCtx,
+ const SessionContainer& transactionSessionIdsToReap) {
+ if (transactionSessionIdsToReap.empty()) {
+ return 0;
+ }
+
+ // Remove the config.image_collection entries for the expired transaction session ids. We first
+ // delete any images belonging to sessions about to be reaped, followed by the sessions. This
+ // way if there's a failure, we'll only be left with sessions that have a dangling reference
+ // to an image. Session reaping will rediscover the sessions to delete and try again.
+ //
+ // We opt for this rather than performing the two sets of deletes in a single transaction simply
+ // to reduce code complexity.
+ DBDirectClient client(opCtx);
+ write_ops::checkWriteErrors(client.remove([&] {
+ write_ops::DeleteCommandRequest imageDeleteOp(NamespaceString::kConfigImagesNamespace);
+ imageDeleteOp.setWriteCommandRequestBase([] {
+ write_ops::WriteCommandRequestBase base;
+ base.setOrdered(false);
+ return base;
+ }());
+ imageDeleteOp.setDeletes([&] {
+ std::vector<write_ops::DeleteOpEntry> entries;
+ for (const auto& transactionSessionId : transactionSessionIdsToReap) {
+ entries.emplace_back(
+ BSON(LogicalSessionRecord::kIdFieldName << transactionSessionId.toBSON()),
+ false /* multi = false */);
+ }
+ return entries;
+ }());
+ return imageDeleteOp;
+ }()));
+
+ // Remove the config.transaction entries for the expired transaction session ids.
+ auto sessionDeleteReply = write_ops::checkWriteErrors(client.remove([&] {
+ write_ops::DeleteCommandRequest sessionDeleteOp(
+ NamespaceString::kSessionTransactionsTableNamespace);
+ sessionDeleteOp.setWriteCommandRequestBase([] {
+ write_ops::WriteCommandRequestBase base;
+ base.setOrdered(false);
+ return base;
+ }());
+ sessionDeleteOp.setDeletes([&] {
+ std::vector<write_ops::DeleteOpEntry> entries;
+ for (const auto& transactionSessionId : transactionSessionIdsToReap) {
+ entries.emplace_back(
+ BSON(LogicalSessionRecord::kIdFieldName << transactionSessionId.toBSON()),
+ false /* multi = false */);
+ }
+ return entries;
+ }());
+ return sessionDeleteOp;
+ }()));
+
+ return sessionDeleteReply.getN();
+}
+
/**
* Removes the the config.transactions and the config.image_collection entries for the transaction
* sessions in 'expiredTransactionSessionIdsNotInUse' that are safe to reap. Returns the number
* of transaction sessions whose entries were removed.
*/
-int removeSessionsTransactionRecords(
+int removeSessionsTransactionRecordsIfExpired(
OperationContext* opCtx,
SessionsCollection& sessionsCollection,
const LogicalSessionIdSet& expiredTransactionSessionIdsNotInUse) {
@@ -267,59 +325,7 @@ int removeSessionsTransactionRecords(
}
}
- if (transactionSessionIdsToReap.empty()) {
- return 0;
- }
-
- // Remove the config.image_collection entries for the expired transaction session ids. We first
- // delete any images belonging to sessions about to be reaped, followed by the sessions. This
- // way if there's a failure, we'll only be left with sessions that have a dangling reference
- // to an image. Session reaping will rediscover the sessions to delete and try again.
- //
- // We opt for this rather than performing the two sets of deletes in a single transaction simply
- // to reduce code complexity.
- DBDirectClient client(opCtx);
- write_ops::checkWriteErrors(client.remove([&] {
- write_ops::DeleteCommandRequest imageDeleteOp(NamespaceString::kConfigImagesNamespace);
- imageDeleteOp.setWriteCommandRequestBase([] {
- write_ops::WriteCommandRequestBase base;
- base.setOrdered(false);
- return base;
- }());
- imageDeleteOp.setDeletes([&] {
- std::vector<write_ops::DeleteOpEntry> entries;
- for (const auto& transactionSessionId : transactionSessionIdsToReap) {
- entries.emplace_back(
- BSON(LogicalSessionRecord::kIdFieldName << transactionSessionId.toBSON()),
- false /* multi = false */);
- }
- return entries;
- }());
- return imageDeleteOp;
- }()));
-
- // Remove the config.transaction entries for the expired transaction session ids.
- auto sessionDeleteReply = write_ops::checkWriteErrors(client.remove([&] {
- write_ops::DeleteCommandRequest sessionDeleteOp(
- NamespaceString::kSessionTransactionsTableNamespace);
- sessionDeleteOp.setWriteCommandRequestBase([] {
- write_ops::WriteCommandRequestBase base;
- base.setOrdered(false);
- return base;
- }());
- sessionDeleteOp.setDeletes([&] {
- std::vector<write_ops::DeleteOpEntry> entries;
- for (const auto& transactionSessionId : transactionSessionIdsToReap) {
- entries.emplace_back(
- BSON(LogicalSessionRecord::kIdFieldName << transactionSessionId.toBSON()),
- false /* multi = false */);
- }
- return entries;
- }());
- return sessionDeleteOp;
- }()));
-
- return sessionDeleteReply.getN();
+ return removeSessionsTransactionRecordsFromDisk(opCtx, transactionSessionIdsToReap);
}
/**
@@ -340,10 +346,6 @@ int removeExpiredTransactionSessionsFromDisk(
findRequest.setProjection(kIdProjection);
auto cursor = client.find(std::move(findRequest));
- // The max batch size is chosen so that a single batch won't exceed the 16MB BSON object size
- // limit.
- const int kMaxBatchSize = 10'000;
-
LogicalSessionIdSet expiredTransactionSessionIdsNotInUse;
int numReaped = 0;
while (cursor->more()) {
@@ -357,13 +359,14 @@ int removeExpiredTransactionSessionsFromDisk(
}
expiredTransactionSessionIdsNotInUse.insert(transactionSessionId);
- if (expiredTransactionSessionIdsNotInUse.size() > kMaxBatchSize) {
- numReaped += removeSessionsTransactionRecords(
+ if (expiredTransactionSessionIdsNotInUse.size() >
+ MongoDSessionCatalog::kMaxSessionDeletionBatchSize) {
+ numReaped += removeSessionsTransactionRecordsIfExpired(
opCtx, sessionsCollection, expiredTransactionSessionIdsNotInUse);
expiredTransactionSessionIdsNotInUse.clear();
}
}
- numReaped += removeSessionsTransactionRecords(
+ numReaped += removeSessionsTransactionRecordsIfExpired(
opCtx, sessionsCollection, expiredTransactionSessionIdsNotInUse);
return numReaped;
@@ -621,6 +624,22 @@ int MongoDSessionCatalog::reapSessionsOlderThan(OperationContext* opCtx,
opCtx, sessionsCollection, possiblyExpired, expiredTransactionSessionIdsStillInUse);
}
+int MongoDSessionCatalog::removeSessionsTransactionRecords(
+ OperationContext* opCtx, const std::vector<LogicalSessionId>& transactionSessionIdsToRemove) {
+ std::vector<LogicalSessionId> nextLsidBatch;
+ int numReaped = 0;
+ for (const auto& transactionSessionIdToRemove : transactionSessionIdsToRemove) {
+ nextLsidBatch.push_back(transactionSessionIdToRemove);
+ if (nextLsidBatch.size() > MongoDSessionCatalog::kMaxSessionDeletionBatchSize) {
+ numReaped += removeSessionsTransactionRecordsFromDisk(opCtx, nextLsidBatch);
+ nextLsidBatch.clear();
+ }
+ }
+ numReaped += removeSessionsTransactionRecordsFromDisk(opCtx, nextLsidBatch);
+
+ return numReaped;
+}
+
MongoDOperationContextSession::MongoDOperationContextSession(OperationContext* opCtx)
: _operationContextSession(opCtx) {
invariant(!opCtx->getClient()->isInDirectClient());