diff options
-rw-r--r-- | jstests/replsets/initial_sync_replSetGetStatus.js | 2 | ||||
-rw-r--r-- | src/mongo/SConscript | 7 | ||||
-rw-r--r-- | src/mongo/db/SConscript | 8 | ||||
-rw-r--r-- | src/mongo/db/db.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/namespace_string.cpp | 61 | ||||
-rw-r--r-- | src/mongo/db/namespace_string.h | 59 | ||||
-rw-r--r-- | src/mongo/db/repl/SConscript | 41 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_coordinator_external_state_impl.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/session_transaction_table.cpp | 68 | ||||
-rw-r--r-- | src/mongo/db/session_transaction_table.h | 24 |
10 files changed, 171 insertions, 105 deletions
diff --git a/jstests/replsets/initial_sync_replSetGetStatus.js b/jstests/replsets/initial_sync_replSetGetStatus.js index 265a393374f..5d8398b5802 100644 --- a/jstests/replsets/initial_sync_replSetGetStatus.js +++ b/jstests/replsets/initial_sync_replSetGetStatus.js @@ -64,7 +64,7 @@ assert.eq(res.initialSyncStatus.appliedOps, 2); assert.eq(res.initialSyncStatus.failedInitialSyncAttempts, 0); assert.eq(res.initialSyncStatus.maxFailedInitialSyncAttempts, 1); - assert.eq(res.initialSyncStatus.databases.databasesCloned, 2); + assert.eq(res.initialSyncStatus.databases.databasesCloned, 3); assert.eq(res.initialSyncStatus.databases.test.collections, 1); assert.eq(res.initialSyncStatus.databases.test.clonedCollections, 1); assert.eq(res.initialSyncStatus.databases.test["test.foo"].documentsToCopy, 4); diff --git a/src/mongo/SConscript b/src/mongo/SConscript index 2ded0280bd4..0e211aaa4b2 100644 --- a/src/mongo/SConscript +++ b/src/mongo/SConscript @@ -283,10 +283,10 @@ env.Library( "db/mongod_options_init.cpp", ], LIBDEPS=[ - 'db/commands/core', - 'db/conn_pool_options', 'db/catalog/catalog', 'db/clientcursor', + 'db/commands/core', + 'db/conn_pool_options', 'db/dbdirectclient', 'db/ftdc/ftdc_mongod', 'db/index_d', @@ -295,13 +295,14 @@ env.Library( 'db/mongod_options', 'db/mongodandmongos', 'db/op_observer_d', - 'db/repl/repl_set_commands', 'db/repair_database', + 'db/repl/repl_set_commands', 'db/repl/storage_interface_impl', 'db/repl/topology_coordinator_impl', 'db/s/balancer', 'db/serveronly', 'db/service_context_d', + 'db/session_transactions', 'db/startup_warnings_mongod', 'db/system_index', 'db/ttl_d', diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index 2ce2c26873a..cbb721fe868 100644 --- a/src/mongo/db/SConscript +++ b/src/mongo/db/SConscript @@ -1308,7 +1308,7 @@ asioEnv.CppIntegrationTest( ) env.Library( - target='session_transaction', + target='session_transactions', source=[ 'session_transaction_table.cpp', 'session_txn_state.cpp', @@ -1316,6 +1316,7 @@ env.Library( env.Idlc('session_txn_record.idl')[0], ], LIBDEPS=[ + '$BUILD_DIR/mongo/db/dbdirectclient', '$BUILD_DIR/mongo/db/logical_session_id', '$BUILD_DIR/mongo/db/ops/write_ops', '$BUILD_DIR/mongo/idl/idl_parser', @@ -1323,13 +1324,12 @@ env.Library( ) env.CppUnitTest( - target='session_transaction_state_test', + target='session_transactions_test', source=[ 'session_transaction_state_test.cpp', ], LIBDEPS=[ 'service_context_d_test_fixture', - 'session_transaction', + 'session_transactions', ], ) - diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp index 57182133a5a..d53c4c0b50b 100644 --- a/src/mongo/db/db.cpp +++ b/src/mongo/db/db.cpp @@ -105,6 +105,7 @@ #include "mongo/db/service_context.h" #include "mongo/db/service_context_d.h" #include "mongo/db/service_entry_point_mongod.h" +#include "mongo/db/session_transaction_table.h" #include "mongo/db/startup_warnings_mongod.h" #include "mongo/db/stats/counters.h" #include "mongo/db/storage/encryption_hooks.h" @@ -642,6 +643,8 @@ ExitCode _initAndListen(int listenPort) { << startupWarningsLog; } + SessionTransactionTable::create(globalServiceContext); + // This function may take the global lock. auto shardingInitialized = uassertStatusOK(ShardingState::get(startupOpCtx.get()) diff --git a/src/mongo/db/namespace_string.cpp b/src/mongo/db/namespace_string.cpp index c41e4b91bb6..b9cedd47a95 100644 --- a/src/mongo/db/namespace_string.cpp +++ b/src/mongo/db/namespace_string.cpp @@ -1,40 +1,37 @@ -// namespace_string.cpp - /** -* Copyright (C) 2014 MongoDB Inc. -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU Affero General Public License, version 3, -* as published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Affero General Public License for more details. -* -* You should have received a copy of the GNU Affero General Public License -* along with this program. If not, see <http://www.gnu.org/licenses/>. -* -* As a special exception, the copyright holders give permission to link the -* code of portions of this program with the OpenSSL library under certain -* conditions as described in each individual source file and distribute -* linked combinations including the program with the OpenSSL library. You -* must comply with the GNU Affero General Public License in all respects for -* all of the code used other than as permitted herein. If you modify file(s) -* with this exception, you may extend this exception to your version of the -* file(s), but you are not obligated to do so. If you do not wish to do so, -* delete this exception statement from your version. If you delete this -* exception statement from all source files in the program, then also delete -* it in the license file. -*/ + * Copyright (C) 2017 MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ #include "mongo/platform/basic.h" -#include <algorithm> -#include <ostream> - #include "mongo/db/namespace_string.h" +#include <ostream> + #include "mongo/base/parse_number.h" #include "mongo/util/mongoutils/str.h" @@ -116,6 +113,8 @@ constexpr StringData NamespaceString::kSystemDotViewsCollectionName; constexpr StringData NamespaceString::kShardConfigCollectionsCollectionName; const NamespaceString NamespaceString::kServerConfigurationNamespace(kServerConfiguration); +const NamespaceString NamespaceString::kSessionTransactionsTableNamespace( + NamespaceString::kConfigDb, "transactions"); bool NamespaceString::isListCollectionsCursorNS() const { return coll() == listCollectionsCursorCol; diff --git a/src/mongo/db/namespace_string.h b/src/mongo/db/namespace_string.h index dc1714c2e10..24abea86771 100644 --- a/src/mongo/db/namespace_string.h +++ b/src/mongo/db/namespace_string.h @@ -1,32 +1,30 @@ -// @file namespacestring.h - /** -* Copyright (C) 2008 10gen Inc. -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU Affero General Public License, version 3, -* as published by the Free Software Foundation. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Affero General Public License for more details. -* -* You should have received a copy of the GNU Affero General Public License -* along with this program. If not, see <http://www.gnu.org/licenses/>. -* -* As a special exception, the copyright holders give permission to link the -* code of portions of this program with the OpenSSL library under certain -* conditions as described in each individual source file and distribute -* linked combinations including the program with the OpenSSL library. You -* must comply with the GNU Affero General Public License in all respects for -* all of the code used other than as permitted herein. If you modify file(s) -* with this exception, you may extend this exception to your version of the -* file(s), but you are not obligated to do so. If you do not wish to do so, -* delete this exception statement from your version. If you delete this -* exception statement from all source files in the program, then also delete -* it in the license file. -*/ + * Copyright (C) 2017 MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ #pragma once @@ -43,8 +41,6 @@ namespace mongo { -/* in the mongo source code, "client" means "database". */ - const size_t MaxDatabaseNameLen = 128; // max str len for the db name, including null char /** @return true if a client can modify this namespace even though it is under ".system." @@ -83,6 +79,9 @@ public: // represents. static const NamespaceString kServerConfigurationNamespace; + // Namespace for storing the transaction information for each session + static const NamespaceString kSessionTransactionsTableNamespace; + /** * Constructs an empty NamespaceString. */ diff --git a/src/mongo/db/repl/SConscript b/src/mongo/db/repl/SConscript index 4745ed48426..f44ca19e037 100644 --- a/src/mongo/db/repl/SConscript +++ b/src/mongo/db/repl/SConscript @@ -1450,37 +1450,38 @@ env.Library( "sync_source_feedback.cpp", ], LIBDEPS=[ - 'bgsync', - 'drop_pending_collection_reaper', - 'rollback_source_impl', - 'oplog_buffer_collection', - 'oplog_interface_remote', - 'optime', - 'repl_coordinator_interface', - 'repl_coordinator_impl', - 'repl_settings', - 'replication_consistency_markers_impl', - 'replication_process', - 'sync_tail', '$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/client/clientdriver', '$BUILD_DIR/mongo/db/auth/authcore', + '$BUILD_DIR/mongo/db/cloner', '$BUILD_DIR/mongo/db/commands/dcommands_fcv', - '$BUILD_DIR/mongo/db/commands/server_status', - '$BUILD_DIR/mongo/db/logical_clock', - '$BUILD_DIR/mongo/db/logical_time', '$BUILD_DIR/mongo/db/commands/list_collections_filter', - '$BUILD_DIR/mongo/rpc/client_metadata', + '$BUILD_DIR/mongo/db/commands/server_status', '$BUILD_DIR/mongo/db/concurrency/lock_manager', '$BUILD_DIR/mongo/db/curop', + '$BUILD_DIR/mongo/db/index_d', '$BUILD_DIR/mongo/db/lasterror', + '$BUILD_DIR/mongo/db/logical_clock', + '$BUILD_DIR/mongo/db/logical_time', '$BUILD_DIR/mongo/db/query/query', + '$BUILD_DIR/mongo/db/repair_database', + '$BUILD_DIR/mongo/db/repl/oplog_buffer_proxy', '$BUILD_DIR/mongo/db/s/balancer', '$BUILD_DIR/mongo/db/service_context', + '$BUILD_DIR/mongo/db/session_transactions', '$BUILD_DIR/mongo/db/stats/counters', - '$BUILD_DIR/mongo/db/repl/oplog_buffer_proxy', - '$BUILD_DIR/mongo/db/cloner', - '$BUILD_DIR/mongo/db/index_d', - '$BUILD_DIR/mongo/db/repair_database', + '$BUILD_DIR/mongo/rpc/client_metadata', + 'bgsync', + 'drop_pending_collection_reaper', + 'oplog_buffer_collection', + 'oplog_interface_remote', + 'optime', + 'repl_coordinator_impl', + 'repl_coordinator_interface', + 'repl_settings', + 'replication_consistency_markers_impl', + 'replication_process', + 'rollback_source_impl', + 'sync_tail', ], ) diff --git a/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp b/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp index e92921ab55a..4d328f5f1de 100644 --- a/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp @@ -74,6 +74,7 @@ #include "mongo/db/server_options.h" #include "mongo/db/server_parameters.h" #include "mongo/db/service_context.h" +#include "mongo/db/session_transaction_table.h" #include "mongo/db/storage/storage_engine.h" #include "mongo/executor/network_connection_hook.h" #include "mongo/executor/network_interface.h" @@ -798,6 +799,8 @@ void ReplicationCoordinatorExternalStateImpl::_shardingOnTransitionToPrimaryHook Grid::get(_service)->catalogCache()->onStepUp(); } + SessionTransactionTable::get(_service)->onStepUp(opCtx); + // There is a slight chance that some stale metadata might have been loaded before the latest // optime has been recovered, so throw out everything that we have up to now ShardingState::get(opCtx)->markCollectionsNotShardedAtStepdown(); diff --git a/src/mongo/db/session_transaction_table.cpp b/src/mongo/db/session_transaction_table.cpp index 2d9c3e65c0c..9cde9802287 100644 --- a/src/mongo/db/session_transaction_table.cpp +++ b/src/mongo/db/session_transaction_table.cpp @@ -26,32 +26,80 @@ * it in the license file. */ +#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kWrite + #include "mongo/platform/basic.h" #include "mongo/db/session_transaction_table.h" +#include <boost/optional.hpp> + +#include "mongo/db/dbdirectclient.h" +#include "mongo/db/namespace_string.h" #include "mongo/db/operation_context.h" #include "mongo/db/service_context.h" +#include "mongo/rpc/get_status_from_command_result.h" #include "mongo/stdx/memory.h" -#include "session_txn_state_holder.h" +#include "mongo/util/log.h" namespace mongo { +namespace { const auto sessionTransactionTableDecoration = - ServiceContext::declareDecoration<std::unique_ptr<SessionTransactionTable>>(); + ServiceContext::declareDecoration<boost::optional<SessionTransactionTable>>(); -SessionTransactionTable* SessionTransactionTable::get(ServiceContext* service) { - return sessionTransactionTableDecoration(service).get(); +} // namespace + +SessionTransactionTable::SessionTransactionTable(ServiceContext* serviceContext) + : _serviceContext(serviceContext) {} + +void SessionTransactionTable::create(ServiceContext* service) { + auto& sessionTransactionTable = sessionTransactionTableDecoration(service); + invariant(!sessionTransactionTable); + + sessionTransactionTable.emplace(service); +} + +SessionTransactionTable* SessionTransactionTable::get(OperationContext* opCtx) { + return get(opCtx->getServiceContext()); } -void SessionTransactionTable::set(ServiceContext* service, - std::unique_ptr<SessionTransactionTable> txnTable) { - auto& serviceTxnTable = sessionTransactionTableDecoration(service); - serviceTxnTable = std::move(txnTable); +SessionTransactionTable* SessionTransactionTable::get(ServiceContext* service) { + auto& sessionTransactionTable = sessionTransactionTableDecoration(service); + invariant(sessionTransactionTable); + + return sessionTransactionTable.get_ptr(); } -SessionTransactionTable::SessionTransactionTable(LogicalSessionCache* sessionsCache) - : _sessionsCache(sessionsCache) {} +void SessionTransactionTable::onStepUp(OperationContext* opCtx) { + DBDirectClient client(opCtx); + + const size_t initialExtentSize = 0; + const bool capped = false; + const bool maxSize = 0; + + BSONObj result; + + if (client.createCollection(NamespaceString::kSessionTransactionsTableNamespace.ns(), + initialExtentSize, + capped, + maxSize, + &result)) { + return; + } + + const auto status = getStatusFromCommandResult(result); + + if (status == ErrorCodes::NamespaceExists) { + return; + } + + uasserted(status.code(), + str::stream() << "Failed to create the " + << NamespaceString::kSessionTransactionsTableNamespace.ns() + << " collection due to " + << status.reason()); +} std::shared_ptr<SessionTxnStateHolder> SessionTransactionTable::getSessionTxnState( const LogicalSessionId& sessionId) { diff --git a/src/mongo/db/session_transaction_table.h b/src/mongo/db/session_transaction_table.h index 13f39e3b520..8586f5bd889 100644 --- a/src/mongo/db/session_transaction_table.h +++ b/src/mongo/db/session_transaction_table.h @@ -28,8 +28,6 @@ #pragma once -#include <map> - #include "mongo/db/logical_session_id.h" #include "mongo/db/session_txn_state_holder.h" #include "mongo/stdx/mutex.h" @@ -46,13 +44,27 @@ class ServiceContext; */ class SessionTransactionTable { public: + explicit SessionTransactionTable(ServiceContext* serviceContext); + /** - * Note: sessionsCache should outlive this object. + * Instantiates a transaction table on the specified service context. Must be called only once + * and is not thread-safe. */ - explicit SessionTransactionTable(LogicalSessionCache* sessionsCache); + static void create(ServiceContext* service); + /** + * Retrieves the session transaction table associated with the service or operation context. + * Must only be called after 'create' has been called. + */ + static SessionTransactionTable* get(OperationContext* opCtx); static SessionTransactionTable* get(ServiceContext* service); - static void set(ServiceContext* service, std::unique_ptr<SessionTransactionTable> txnTable); + + /** + * Invoked when the node enters the primary state. Ensures that the transactions collection is + * created. Throws on severe exceptions due to which it is not safe to continue the step-up + * process. + */ + void onStepUp(OperationContext* opCtx); /** * Returns transaction state with the given sessionId and txnNum. @@ -68,7 +80,7 @@ public: void cleanupInactiveSessions(OperationContext* opCtx); private: - LogicalSessionCache* const _sessionsCache; + ServiceContext* const _serviceContext; stdx::mutex _mutex; stdx::unordered_map<LogicalSessionId, |