39
39
#include " mongo/db/auth/action_type.h"
40
40
#include " mongo/db/auth/authorization_session.h"
41
41
#include " mongo/db/auth/resource_pattern.h"
42
+ #include " mongo/db/cancelable_operation_context.h"
42
43
#include " mongo/db/catalog/document_validation.h"
43
44
#include " mongo/db/cloner.h"
44
45
#include " mongo/db/cluster_role.h"
45
46
#include " mongo/db/commands.h"
46
47
#include " mongo/db/commands/feature_compatibility_version.h"
47
48
#include " mongo/db/database_name.h"
49
+ #include " mongo/db/dbdirectclient.h"
48
50
#include " mongo/db/namespace_string.h"
49
51
#include " mongo/db/operation_context.h"
50
52
#include " mongo/db/repl/read_concern_level.h"
51
53
#include " mongo/db/s/sharding_state.h"
52
54
#include " mongo/db/server_options.h"
53
55
#include " mongo/db/service_context.h"
56
+ #include " mongo/db/transaction/transaction_participant.h"
57
+ #include " mongo/db/write_block_bypass.h"
54
58
#include " mongo/idl/idl_parser.h"
55
59
#include " mongo/s/catalog/sharding_catalog_client.h"
56
60
#include " mongo/s/grid.h"
66
70
namespace mongo {
67
71
namespace {
68
72
73
+ void cloneDatabase (OperationContext* opCtx,
74
+ const DatabaseName& dbName,
75
+ StringData from,
76
+ BSONObjBuilder& result) {
77
+ auto const catalogClient = Grid::get (opCtx)->catalogClient ();
78
+ auto shardedOrUntrackedColls = catalogClient->getShardedCollectionNamespacesForDb (
79
+ opCtx, dbName, repl::ReadConcernLevel::kMajorityReadConcern , {});
80
+ const auto databasePrimary =
81
+ catalogClient->getDatabase (opCtx, dbName, repl::ReadConcernLevel::kMajorityReadConcern )
82
+ .getPrimary ()
83
+ .toString ();
84
+ auto unsplittableCollsOutsideDbPrimary =
85
+ catalogClient->getUnsplittableCollectionNamespacesForDbOutsideOfShards (
86
+ opCtx, dbName, {databasePrimary}, repl::ReadConcernLevel::kMajorityReadConcern );
87
+
88
+ std::move (unsplittableCollsOutsideDbPrimary.begin (),
89
+ unsplittableCollsOutsideDbPrimary.end (),
90
+ std::back_inserter (shardedOrUntrackedColls));
91
+
92
+ DisableDocumentValidation disableValidation (opCtx);
93
+
94
+ // Clone the non-ignored collections.
95
+ std::set<std::string> clonedColls;
96
+ bool forceSameUUIDAsSource = false ;
97
+ {
98
+ FixedFCVRegion fcvRegion{opCtx};
99
+ forceSameUUIDAsSource =
100
+ feature_flags::gTrackUnshardedCollectionsOnShardingCatalog .isEnabled (
101
+ (*fcvRegion).acquireFCVSnapshot ());
102
+ }
103
+
104
+ Cloner cloner;
105
+ uassertStatusOK (cloner.copyDb (opCtx,
106
+ dbName,
107
+ from.toString (),
108
+ shardedOrUntrackedColls,
109
+ forceSameUUIDAsSource,
110
+ &clonedColls));
111
+ {
112
+ BSONArrayBuilder cloneBarr = result.subarrayStart (" clonedColls" );
113
+ cloneBarr.append (clonedColls);
114
+ }
115
+ }
116
+
69
117
/* *
70
118
* Currently, _shardsvrCloneCatalogData will clone all data (including metadata). In the second part
71
119
* of
@@ -93,6 +141,10 @@ class CloneCatalogDataCommand : public BasicCommand {
93
141
return true ;
94
142
}
95
143
144
+ virtual bool supportsRetryableWrite () const override {
145
+ return true ;
146
+ }
147
+
96
148
Status checkAuthForOperation (OperationContext* opCtx,
97
149
const DatabaseName& dbName,
98
150
const BSONObj&) const override {
@@ -110,7 +162,6 @@ class CloneCatalogDataCommand : public BasicCommand {
110
162
const DatabaseName&,
111
163
const BSONObj& cmdObj,
112
164
BSONObjBuilder& result) override {
113
-
114
165
auto shardingState = ShardingState::get (opCtx);
115
166
uassertStatusOK (shardingState->canAcceptShardedCommands ());
116
167
@@ -139,45 +190,39 @@ class CloneCatalogDataCommand : public BasicCommand {
139
190
str::stream () << " Can't run _shardsvrCloneCatalogData without a source" ,
140
191
!from.empty ());
141
192
142
- auto const catalogClient = Grid::get (opCtx)->catalogClient ();
143
- auto shardedOrUntrackedColls = catalogClient->getShardedCollectionNamespacesForDb (
144
- opCtx, dbName, repl::ReadConcernLevel::kMajorityReadConcern , {});
145
- const auto databasePrimary =
146
- catalogClient->getDatabase (opCtx, dbName, repl::ReadConcernLevel::kMajorityReadConcern )
147
- .getPrimary ()
148
- .toString ();
149
- auto unsplittableCollsOutsideDbPrimary =
150
- catalogClient->getUnsplittableCollectionNamespacesForDbOutsideOfShards (
151
- opCtx, dbName, {databasePrimary}, repl::ReadConcernLevel::kMajorityReadConcern );
152
-
153
- std::move (unsplittableCollsOutsideDbPrimary.begin (),
154
- unsplittableCollsOutsideDbPrimary.end (),
155
- std::back_inserter (shardedOrUntrackedColls));
156
-
157
- DisableDocumentValidation disableValidation (opCtx);
158
-
159
- // Clone the non-ignored collections.
160
- std::set<std::string> clonedColls;
161
- bool forceSameUUIDAsSource = false ;
162
- {
163
- FixedFCVRegion fcvRegion{opCtx};
164
- forceSameUUIDAsSource =
165
- feature_flags::gTrackUnshardedCollectionsOnShardingCatalog .isEnabled (
166
- (*fcvRegion).acquireFCVSnapshot ());
193
+ // For newer versions, execute the operation in another operation context with local write
194
+ // concern to prevent doing waits while we're holding resources (we have a session checked
195
+ // out).
196
+ if (TransactionParticipant::get (opCtx)) {
197
+ {
198
+ // Use ACR to have a thread holding the session while we do the cloning.
199
+ auto newClient = opCtx->getServiceContext ()
200
+ ->getService (ClusterRole::ShardServer)
201
+ ->makeClient (" SetAllowMigrations" );
202
+ AlternativeClientRegion acr (newClient);
203
+ auto executor =
204
+ Grid::get (opCtx->getServiceContext ())->getExecutorPool ()->getFixedExecutor ();
205
+ auto newOpCtxPtr = CancelableOperationContext (
206
+ cc ().makeOperationContext (), opCtx->getCancellationToken (), executor);
207
+
208
+ AuthorizationSession::get (newOpCtxPtr.get ()->getClient ())
209
+ ->grantInternalAuthorization (newOpCtxPtr.get ()->getClient ());
210
+ newOpCtxPtr->setWriteConcern (ShardingCatalogClient::kLocalWriteConcern );
211
+ WriteBlockBypass::get (newOpCtxPtr.get ()).set (true );
212
+ cloneDatabase (newOpCtxPtr.get (), dbName, from, result);
213
+ }
214
+ // Since no write happened on this txnNumber, we need to make a dummy write to protect
215
+ // against older requests with old txnNumbers.
216
+ DBDirectClient client (opCtx);
217
+ client.update (NamespaceString::kServerConfigurationNamespace ,
218
+ BSON (" _id"
219
+ << " CloneCatalogDataStats" ),
220
+ BSON (" $inc" << BSON (" count" << 1 )),
221
+ true /* upsert */ ,
222
+ false /* multi */ );
223
+ } else {
224
+ cloneDatabase (opCtx, dbName, from, result);
167
225
}
168
-
169
- Cloner cloner;
170
- uassertStatusOK (cloner.copyDb (opCtx,
171
- dbName,
172
- from.toString (),
173
- shardedOrUntrackedColls,
174
- forceSameUUIDAsSource,
175
- &clonedColls));
176
- {
177
- BSONArrayBuilder cloneBarr = result.subarrayStart (" clonedColls" );
178
- cloneBarr.append (clonedColls);
179
- }
180
-
181
226
return true ;
182
227
}
183
228
};
0 commit comments