5
5
#include < ydb/core/tx/datashard/range_ops.h>
6
6
#include < ydb/core/tx/tx_proxy/proxy.h>
7
7
8
+ #include < library/cpp/protobuf/json/proto2json.h>
9
+
8
10
#include < library/cpp/html/pcdata/pcdata.h>
9
11
#include < util/string/cast.h>
10
12
11
13
static ui64 TryParseTabletId (TStringBuf tabletIdParam) {
12
- if (tabletIdParam.StartsWith (" 0x" ))
13
- return IntFromString<ui64, 16 >(tabletIdParam.substr (2 ));
14
- else
15
- return FromStringWithDefault<ui64>(tabletIdParam, ui64 (NKikimr::NSchemeShard::InvalidTabletId));
14
+ ui64 tabletId = ui64 (NKikimr::NSchemeShard::InvalidTabletId);
15
+ if (tabletIdParam.StartsWith (" 0x" )) {
16
+ TryIntFromString<16 >(tabletIdParam.substr (2 ), tabletId);
17
+ } else {
18
+ TryFromString (tabletIdParam, tabletId);
19
+ }
20
+ return tabletId;
16
21
}
17
22
18
23
namespace NKikimr {
@@ -79,6 +84,7 @@ struct TCgi {
79
84
static const TParam BuildIndexId;
80
85
static const TParam UpdateCoordinatorsConfig;
81
86
static const TParam UpdateCoordinatorsConfigDryRun;
87
+ static const TParam Action;
82
88
83
89
struct TPages {
84
90
static constexpr TStringBuf MainPage = " Main" ;
@@ -91,6 +97,10 @@ struct TCgi {
91
97
static constexpr TStringBuf ShardInfoByShardIdx = " ShardInfoByShardIdx" ;
92
98
static constexpr TStringBuf BuildIndexInfo = " BuildIndexInfo" ;
93
99
};
100
+
101
+ struct TActions {
102
+ static constexpr TStringBuf SplitOneToOne = " SplitOneToOne" ;
103
+ };
94
104
};
95
105
96
106
const TCgi::TParam TCgi::TabletID = TStringBuf(" TabletID" );
@@ -111,6 +121,7 @@ const TCgi::TParam TCgi::Page = TStringBuf("Page");
111
121
const TCgi::TParam TCgi::BuildIndexId = TStringBuf(" BuildIndexId" );
112
122
const TCgi::TParam TCgi::UpdateCoordinatorsConfig = TStringBuf(" UpdateCoordinatorsConfig" );
113
123
const TCgi::TParam TCgi::UpdateCoordinatorsConfigDryRun = TStringBuf(" UpdateCoordinatorsConfigDryRun" );
124
+ const TCgi::TParam TCgi::Action = TStringBuf(" Action" );
114
125
115
126
116
127
class TUpdateCoordinatorsConfigActor : public TActorBootstrapped <TUpdateCoordinatorsConfigActor> {
@@ -231,6 +242,93 @@ class TUpdateCoordinatorsConfigActor : public TActorBootstrapped<TUpdateCoordina
231
242
THashMap<ui64, const TItem*> InFlight;
232
243
};
233
244
245
+ class TMonitoringShardSplitOneToOne : public TActorBootstrapped <TMonitoringShardSplitOneToOne> {
246
+ public:
247
+ TMonitoringShardSplitOneToOne (NMon::TEvRemoteHttpInfo::TPtr&& ev, ui64 schemeShardId, const TPathId& pathId, TTabletId shardId)
248
+ : Ev(std::move(ev))
249
+ , SchemeShardId(schemeShardId)
250
+ , PathId(pathId)
251
+ , ShardId(shardId)
252
+ {}
253
+
254
+ void Bootstrap () {
255
+ Send (MakeTxProxyID (), new TEvTxUserProxy::TEvAllocateTxId);
256
+ Become (&TThis::StateWaitTxId);
257
+ }
258
+
259
+ STFUNC (StateWaitTxId) {
260
+ switch (ev->GetTypeRewrite ()) {
261
+ hFunc (TEvTxUserProxy::TEvAllocateTxIdResult, Handle);
262
+ }
263
+ }
264
+
265
+ void Handle (TEvTxUserProxy::TEvAllocateTxIdResult::TPtr& ev) {
266
+ TxId = ev->Get ()->TxId ;
267
+
268
+ auto propose = MakeHolder<TEvSchemeShard::TEvModifySchemeTransaction>(TxId, SchemeShardId);
269
+
270
+ auto & modifyScheme = *propose->Record .AddTransaction ();
271
+ modifyScheme.SetOperationType (NKikimrSchemeOp::ESchemeOpSplitMergeTablePartitions);
272
+ modifyScheme.SetInternal (true );
273
+
274
+ auto & info = *modifyScheme.MutableSplitMergeTablePartitions ();
275
+ info.SetTableOwnerId (PathId.OwnerId );
276
+ info.SetTableLocalId (PathId.LocalPathId );
277
+ info.AddSourceTabletId (ui64 (ShardId));
278
+ info.SetAllowOneToOneSplitMerge (true );
279
+
280
+ PipeCache = MakePipePerNodeCacheID (EPipePerNodeCache::Leader);
281
+ Send (PipeCache, new TEvPipeCache::TEvForward (propose.Release (), SchemeShardId, /* subscribe */ true ));
282
+ Become (&TThis::StateWaitProposed);
283
+ }
284
+
285
+ STFUNC (StateWaitProposed) {
286
+ switch (ev->GetTypeRewrite ()) {
287
+ hFunc (TEvSchemeShard::TEvModifySchemeTransactionResult, Handle);
288
+ hFunc (TEvPipeCache::TEvDeliveryProblem, Handle);
289
+ }
290
+ }
291
+
292
+ void Handle (TEvSchemeShard::TEvModifySchemeTransactionResult::TPtr& ev) {
293
+ TString text;
294
+ try {
295
+ NProtobufJson::Proto2Json (ev->Get ()->Record , text, {
296
+ .EnumMode = NProtobufJson::TProto2JsonConfig::EnumName,
297
+ .FieldNameMode = NProtobufJson::TProto2JsonConfig::FieldNameSnakeCaseDense,
298
+ .MapAsObject = true ,
299
+ });
300
+ } catch (const std::exception& e) {
301
+ Send (Ev->Sender , new NMon::TEvRemoteBinaryInfoRes (
302
+ " HTTP/1.1 500 Internal Error\r\n Connection: Close\r\n\r\n Unexpected failure to serialize the response\r\n " ));
303
+ PassAway ();
304
+ }
305
+
306
+ Send (Ev->Sender , new NMon::TEvRemoteJsonInfoRes (text));
307
+ PassAway ();
308
+ }
309
+
310
+ void Handle (TEvPipeCache::TEvDeliveryProblem::TPtr&) {
311
+ Send (Ev->Sender , new NMon::TEvRemoteBinaryInfoRes (
312
+ TStringBuilder () << " HTTP/1.1 502 Bad Gateway\r\n Connection: Close\r\n\r\n SchemeShard tablet disconnected\r\n " ));
313
+ PassAway ();
314
+ }
315
+
316
+ void PassAway () override {
317
+ if (PipeCache) {
318
+ Send (PipeCache, new TEvPipeCache::TEvUnlink (0 ));
319
+ }
320
+ TActorBootstrapped::PassAway ();
321
+ }
322
+
323
+ private:
324
+ NMon::TEvRemoteHttpInfo::TPtr Ev;
325
+ ui64 SchemeShardId;
326
+ TPathId PathId;
327
+ TTabletId ShardId;
328
+ ui64 TxId = 0 ;
329
+ TActorId PipeCache;
330
+ };
331
+
234
332
struct TSchemeShard ::TTxMonitoring : public NTabletFlatExecutor::TTransactionBase<TSchemeShard> {
235
333
NMon::TEvRemoteHttpInfo::TPtr Ev;
236
334
TStringStream Answer;
@@ -242,11 +340,18 @@ struct TSchemeShard::TTxMonitoring : public NTabletFlatExecutor::TTransactionBas
242
340
{
243
341
}
244
342
343
+ TTxType GetTxType () const override { return TXTYPE_MONITORING; }
344
+
245
345
bool Execute (NTabletFlatExecutor::TTransactionContext &txc, const TActorContext &ctx) override {
246
346
Y_UNUSED (txc);
247
347
248
348
const TCgiParameters& cgi = Ev->Get ()->Cgi ();
249
349
350
+ if (cgi.Has (TCgi::Action)) {
351
+ HandleAction (cgi.Get (TCgi::Action), cgi, ctx);
352
+ return true ;
353
+ }
354
+
250
355
const TString page = cgi.Has (TCgi::Page) ? cgi.Get (TCgi::Page) : ToString (TCgi::TPages::MainPage);
251
356
252
357
if (page == TCgi::TPages::AdminRequest) {
@@ -311,7 +416,7 @@ struct TSchemeShard::TTxMonitoring : public NTabletFlatExecutor::TTransactionBas
311
416
}
312
417
313
418
void Complete (const TActorContext &ctx) override {
314
- if (Answer) {
419
+ if (Ev && Answer) {
315
420
ctx.Send (Ev->Sender , new NMon::TEvRemoteHttpInfoRes (Answer.Str ()));
316
421
}
317
422
}
@@ -1360,7 +1465,44 @@ struct TSchemeShard::TTxMonitoring : public NTabletFlatExecutor::TTransactionBas
1360
1465
}
1361
1466
}
1362
1467
1363
- TTxType GetTxType () const override { return TXTYPE_MONITORING; }
1468
+ private:
1469
+ void SendBadRequest (const TString& details, const TActorContext& ctx) {
1470
+ ctx.Send (Ev->Sender , new NMon::TEvRemoteBinaryInfoRes (
1471
+ TStringBuilder () << " HTTP/1.1 400 Bad Request\r\n Connection: Close\r\n\r\n " << details << " \r\n " ));
1472
+ }
1473
+
1474
+ private:
1475
+ void HandleAction (const TString& action, const TCgiParameters& cgi, const TActorContext& ctx) {
1476
+ if (Ev->Get ()->Method != HTTP_METHOD_POST) {
1477
+ SendBadRequest (" Action requires a POST method" , ctx);
1478
+ return ;
1479
+ }
1480
+
1481
+ if (action == TCgi::TActions::SplitOneToOne) {
1482
+ TTabletId tabletId = TTabletId (TryParseTabletId (cgi.Get (TCgi::ShardID)));
1483
+ TShardIdx shardIdx = Self->GetShardIdx (tabletId);
1484
+ if (!shardIdx) {
1485
+ SendBadRequest (" Cannot find the specified shard" , ctx);
1486
+ return ;
1487
+ }
1488
+ auto * info = Self->ShardInfos .FindPtr (shardIdx);
1489
+ if (!info) {
1490
+ SendBadRequest (" Cannot find the specified shard info" , ctx);
1491
+ return ;
1492
+ }
1493
+ TPathId pathId = info->PathId ;
1494
+ auto * table = Self->Tables .FindPtr (pathId);
1495
+ if (!table) {
1496
+ SendBadRequest (" Cannot find the specified shard's table" , ctx);
1497
+ return ;
1498
+ }
1499
+
1500
+ ctx.Register (new TMonitoringShardSplitOneToOne (std::move (Ev), Self->TabletID (), pathId, tabletId));
1501
+ return ;
1502
+ }
1503
+
1504
+ SendBadRequest (" Action not supported" , ctx);
1505
+ }
1364
1506
};
1365
1507
1366
1508
bool TSchemeShard::OnRenderAppHtmlPage (NMon::TEvRemoteHttpInfo::TPtr ev, const TActorContext &ctx) {
0 commit comments