@@ -2780,6 +2780,96 @@ Y_UNIT_TEST_SUITE(THiveTest) {
2780
2780
UNIT_ASSERT_VALUES_EQUAL (getGroup (tabletId), goodGroup);
2781
2781
}
2782
2782
2783
+ Y_UNIT_TEST (TestStorageBalancer) {
2784
+ static constexpr ui64 NUM_TABLETS = 4 ;
2785
+ TTestBasicRuntime runtime (1 , false );
2786
+ Setup (runtime, true , 2 , [](TAppPrepare& app) {
2787
+ app.HiveConfig .SetMinPeriodBetweenReassign (0 );
2788
+ });
2789
+ const ui64 hiveTablet = MakeDefaultHiveID (0 );
2790
+ const ui64 testerTablet = MakeDefaultHiveID (1 );
2791
+ CreateTestBootstrapper (runtime, CreateTestTabletInfo (hiveTablet, TTabletTypes::Hive), &CreateDefaultHive);
2792
+
2793
+ TTabletTypes::EType tabletType = TTabletTypes::Dummy;
2794
+ TVector<ui64> tablets;
2795
+ for (ui64 i = 0 ; i < NUM_TABLETS; ++i) {
2796
+ THolder<TEvHive::TEvCreateTablet> ev (new TEvHive::TEvCreateTablet (testerTablet, 100500 + i, tabletType, BINDED_CHANNELS));
2797
+ ev->Record .SetObjectId (i);
2798
+ ui64 tabletId = SendCreateTestTablet (runtime, hiveTablet, testerTablet, std::move (ev), 0 , true );
2799
+ tablets.emplace_back (tabletId);
2800
+ MakeSureTabletIsUp (runtime, tabletId, 0 );
2801
+ }
2802
+ ui64 tabletBase = tablets.front ();
2803
+
2804
+ TActorId sender = runtime.AllocateEdgeActor ();
2805
+ auto getGroup = [&runtime, sender, hiveTablet](ui64 tabletId) {
2806
+ runtime.SendToPipe (hiveTablet, sender, new TEvHive::TEvRequestHiveInfo ({
2807
+ .TabletId = tabletId,
2808
+ .ReturnChannelHistory = true ,
2809
+ }));
2810
+ TAutoPtr<IEventHandle> handle;
2811
+ TEvHive::TEvResponseHiveInfo* response = runtime.GrabEdgeEventRethrow <TEvHive::TEvResponseHiveInfo>(handle);
2812
+
2813
+ const auto & tablet = response->Record .GetTablets ().Get (0 );
2814
+ const auto & channel = tablet.GetTabletChannels ().Get (0 );
2815
+ const auto & history = channel.GetHistory ();
2816
+ return history.Get (history.size () - 1 ).GetGroup ();
2817
+ };
2818
+
2819
+ std::unordered_map<ui64, std::vector<ui64>> groupToTablets;
2820
+ for (auto tablet : tablets) {
2821
+ groupToTablets[getGroup (tablet)].push_back (tablet);
2822
+ }
2823
+ ui64 tabletA;
2824
+ ui64 tabletB;
2825
+ for (const auto & [group, tablets] : groupToTablets) {
2826
+ if (tablets.size () >= 2 ) {
2827
+ tabletA = tablets[0 ];
2828
+ tabletB = tablets[1 ];
2829
+ }
2830
+ }
2831
+
2832
+ // If assured space is not set, usage is always set to 1
2833
+ auto groupMetricsExchange = MakeHolder<TEvBlobStorage::TEvControllerGroupMetricsExchange>();
2834
+ for (const auto & [group, tablets] : groupToTablets) {
2835
+ NKikimrBlobStorage::TGroupMetrics* metrics = groupMetricsExchange->Record .AddGroupMetrics ();
2836
+
2837
+ metrics->SetGroupId (group);
2838
+ metrics->MutableGroupParameters ()->SetGroupID (group);
2839
+ metrics->MutableGroupParameters ()->SetStoragePoolName (" def1" );
2840
+ metrics->MutableGroupParameters ()->MutableAssuredResources ()->SetSpace (300'000'000 );
2841
+ }
2842
+
2843
+ runtime.SendToPipe (MakeBSControllerID (0 ), sender, groupMetricsExchange.Release (), 0 , GetPipeConfigWithRetries ());
2844
+ {
2845
+ TDispatchOptions options;
2846
+ options.FinalEvents .push_back (TDispatchOptions::TFinalEventCondition (TEvBlobStorage::EvControllerGroupMetricsExchange));
2847
+ runtime.DispatchEvents (options);
2848
+ }
2849
+
2850
+ TChannelsBindings channels = BINDED_CHANNELS;
2851
+ for (auto & bind : channels) {
2852
+ bind.SetSize (200'000'000 );
2853
+ }
2854
+ for (auto tablet : {tabletA, tabletB}) {
2855
+ TAutoPtr<TEvHive::TEvCreateTablet> updateTablet (new TEvHive::TEvCreateTablet (testerTablet, 100500 + (tablet - tabletBase), tabletType, channels));
2856
+ SendCreateTestTablet (runtime, hiveTablet, testerTablet, updateTablet, 0 , true );
2857
+ }
2858
+ runtime.SendToPipe (hiveTablet, sender, new NHive::TEvPrivate::TEvStartStorageBalancer ({
2859
+ .NumReassigns = 100 ,
2860
+ .MaxInFlight = 1 ,
2861
+ .StoragePool = " def1" ,
2862
+ }));
2863
+
2864
+ {
2865
+ TDispatchOptions options;
2866
+ options.FinalEvents .emplace_back (NHive::TEvPrivate::EvRestartComplete, 4 ); // should actually be less than 4
2867
+ runtime.DispatchEvents (options, TDuration::Seconds (10 ));
2868
+ }
2869
+
2870
+ UNIT_ASSERT_VALUES_UNEQUAL (getGroup (tabletA), getGroup (tabletB));
2871
+ }
2872
+
2783
2873
// Y_UNIT_TEST(TestCreateTabletAndChangeProfiles) {
2784
2874
// TTestBasicRuntime runtime(1, false);
2785
2875
// Setup(runtime, true);
0 commit comments