@@ -267,6 +267,7 @@ class TStorageGroups : public TViewerPipeClient {
267267 TString Erasure;
268268 TErasureType::EErasureSpecies ErasureSpecies = TErasureType::ErasureNone;
269269 TString State;
270+ ui32 StateSortKey = 0 ;
270271 ui32 EncryptionMode = 0 ;
271272 ui64 AllocationUnits = 0 ;
272273 float Usage = 0 ;
@@ -290,11 +291,13 @@ class TStorageGroups : public TViewerPipeClient {
290291 TString result;
291292 result += ::ToString (failedDomains.size ());
292293 result += ' (' ;
294+ bool was_domains = false ;
293295 for (ui8 domains : failedDomains) {
294- if (!result. empty () ) {
296+ if (was_domains ) {
295297 result += ' ,' ;
296298 }
297299 result += ::ToString (domains);
300+ was_domains = true ;
298301 }
299302 result += ' )' ;
300303 return result;
@@ -377,35 +380,43 @@ class TStorageGroups : public TViewerPipeClient {
377380 if (MissingDisks == 0 ) {
378381 Overall = NKikimrViewer::EFlag::Green;
379382 State = " ok" ;
383+ StateSortKey = 0 ;
380384 } else {
381385 if (ErasureSpecies == TErasureType::ErasureNone) {
382386 TString state;
383387 Overall = NKikimrViewer::EFlag::Red;
384388 if (MissingDisks == startingDisks) {
385389 state = " starting" ;
390+ StateSortKey = 10 ;
386391 } else {
387392 state = " dead" ;
393+ StateSortKey = 100 ;
388394 }
389395 State = TStringBuilder () << state << ' :' << MissingDisks;
390396 } else if (ErasureSpecies == TErasureType::Erasure4Plus2Block) {
391397 TString state;
392398 if (MissingDisks > 2 ) {
393399 Overall = NKikimrViewer::EFlag::Red;
394400 state = " dead" ;
401+ StateSortKey = 100 ;
395402 } else if (MissingDisks == 2 ) {
396403 Overall = NKikimrViewer::EFlag::Orange;
397404 state = " degraded" ;
405+ StateSortKey = 50 + MissingDisks;
398406 } else if (MissingDisks == 1 ) {
399407 if (MissingDisks == replicatingDisks + startingDisks) {
400408 Overall = NKikimrViewer::EFlag::Blue;
401409 if (replicatingDisks) {
402410 state = " replicating" ;
411+ StateSortKey = 20 ;
403412 } else {
404413 state = " starting" ;
414+ StateSortKey = 10 ;
405415 }
406416 } else {
407417 Overall = NKikimrViewer::EFlag::Yellow;
408418 state = " degraded" ;
419+ StateSortKey = 50 + MissingDisks;
409420 }
410421 }
411422 State = TStringBuilder () << state << ' :' << MissingDisks;
@@ -418,20 +429,25 @@ class TStorageGroups : public TViewerPipeClient {
418429 if (failedDomainsPerRealm.size () > 2 || (failedDomainsPerRealm.size () == 2 && failedDomainsPerRealm[1 ] > 1 )) {
419430 Overall = NKikimrViewer::EFlag::Red;
420431 state = " dead" ;
432+ StateSortKey = 100 ;
421433 } else if (failedDomainsPerRealm.size () == 2 ) {
422434 Overall = NKikimrViewer::EFlag::Orange;
423435 state = " degraded" ;
436+ StateSortKey = 50 + failedDomainsPerRealm.size () * 10 + MissingDisks;
424437 } else if (failedDomainsPerRealm.size ()) {
425438 if (MissingDisks == replicatingDisks + startingDisks) {
426439 Overall = NKikimrViewer::EFlag::Blue;
427440 if (replicatingDisks > startingDisks) {
428441 state = " replicating" ;
442+ StateSortKey = 20 ;
429443 } else {
430444 state = " starting" ;
445+ StateSortKey = 10 ;
431446 }
432447 } else {
433448 Overall = NKikimrViewer::EFlag::Yellow;
434449 state = " degraded" ;
450+ StateSortKey = 50 + failedDomainsPerRealm.size () * 10 + MissingDisks;
435451 }
436452 }
437453 State = TStringBuilder () << state << ' :' << PrintDomains (failedDomainsPerRealm);
@@ -533,8 +549,9 @@ class TStorageGroups : public TViewerPipeClient {
533549 case EGroupFields::PoolName:
534550 case EGroupFields::Kind:
535551 case EGroupFields::MediaType:
536- case EGroupFields::State:
537552 return GetGroupName (groupBy);
553+ case EGroupFields::State:
554+ return StateSortKey;
538555 case EGroupFields::Usage:
539556 return Usage;
540557 case EGroupFields::DiskSpaceUsage:
@@ -1029,19 +1046,12 @@ class TStorageGroups : public TViewerPipeClient {
10291046 TVector<TString> filterWords = SplitString (Filter, " " );
10301047 TGroupView groupView;
10311048 for (TGroup* group : GroupView) {
1032- bool match = false ;
10331049 for (const TString& word : filterWords) {
1034- if (group->PoolName .Contains (word)) {
1035- match = true ;
1036- break ;
1037- } else if (::ToString (group->GroupId ).Contains (word)) {
1038- match = true ;
1050+ if (group->PoolName .Contains (word) || ::ToString (group->GroupId ).Contains (word)) {
1051+ groupView.push_back (group);
10391052 break ;
10401053 }
10411054 }
1042- if (match) {
1043- groupView.push_back (group);
1044- }
10451055 }
10461056 GroupView.swap (groupView);
10471057 Filter.clear ();
@@ -1091,11 +1101,11 @@ class TStorageGroups : public TViewerPipeClient {
10911101 case EGroupFields::Kind:
10921102 case EGroupFields::Encryption:
10931103 case EGroupFields::MediaType:
1094- case EGroupFields::State:
10951104 GroupCollection ();
10961105 SortCollection (GroupGroups, [](const TGroupGroup& groupGroup) { return groupGroup.SortKey ; });
10971106 NeedGroup = false ;
10981107 break ;
1108+ case EGroupFields::State:
10991109 case EGroupFields::Usage:
11001110 case EGroupFields::DiskSpaceUsage:
11011111 case EGroupFields::MissingDisks:
@@ -1169,7 +1179,7 @@ class TStorageGroups : public TViewerPipeClient {
11691179 SortCollection (GroupView, [](const TGroup* group) { return group->Write ; }, ReverseSort);
11701180 break ;
11711181 case EGroupFields::State:
1172- SortCollection (GroupView, [](const TGroup* group) { return group->State ; }, ReverseSort);
1182+ SortCollection (GroupView, [](const TGroup* group) { return group->StateSortKey ; }, ReverseSort);
11731183 break ;
11741184 case EGroupFields::Latency:
11751185 SortCollection (GroupView, [](const TGroup* group) { return group->GetLatencyForSort (); }, ReverseSort);
@@ -1207,8 +1217,10 @@ class TStorageGroups : public TViewerPipeClient {
12071217 ApplyLimit ();
12081218 }
12091219
1220+ bool CollectedHiveData = false ;
1221+
12101222 void CollectHiveData () {
1211- if (FieldsNeeded (FieldsHive) ) {
1223+ if (!CollectedHiveData ) {
12121224 if (!GroupView.empty ()) {
12131225 ui64 hiveId = AppData ()->DomainsInfo ->GetHive ();
12141226 if (hiveId != TDomainsInfo::BadTabletId) {
@@ -1226,6 +1238,7 @@ class TStorageGroups : public TViewerPipeClient {
12261238 ++NavigateKeySetInFlight;
12271239 }
12281240 }
1241+ CollectedHiveData = true ;
12291242 }
12301243 }
12311244
@@ -1341,7 +1354,6 @@ class TStorageGroups : public TViewerPipeClient {
13411354 }
13421355 FieldsAvailable |= FieldsBsPools;
13431356 ApplyEverything ();
1344- CollectHiveData ();
13451357 } else {
13461358 AddProblem (" bsc-storage-pools-no-data" );
13471359 }
@@ -1427,6 +1439,9 @@ class TStorageGroups : public TViewerPipeClient {
14271439 }
14281440 }
14291441 if (AreBSControllerRequestsDone ()) {
1442+ if (FieldsNeeded (FieldsHive) && !CollectedHiveData) {
1443+ CollectHiveData ();
1444+ }
14301445 if (FieldsAvailable.test (+EGroupFields::GroupId) && FieldsNeeded (FieldsHive) && NavigateKeySetInFlight == 0 && HiveStorageStatsInFlight == 0 ) {
14311446 if (GroupsByGroupId.empty ()) {
14321447 RebuildGroupsByGroupId ();
@@ -2076,8 +2091,16 @@ class TStorageGroups : public TViewerPipeClient {
20762091 if (FieldsAvailable.test (+EGroupFields::PoolName)) {
20772092 jsonGroup.SetPoolName (group->PoolName );
20782093 }
2079- for (const TVDisk& vdisk : group->VDisks ) {
2080- RenderVDisk (*jsonGroup.AddVDisks (), vdisk);
2094+ std::vector<const TVDisk*> vdisks;
2095+ vdisks.resize (group->VDisks .size ());
2096+ for (size_t idx = 0 ; idx < group->VDisks .size (); ++idx) {
2097+ vdisks[idx] = &group->VDisks [idx];
2098+ }
2099+ std::sort (vdisks.begin (), vdisks.end (), [](const TVDisk* a, const TVDisk* b) {
2100+ return a->VDiskId < b->VDiskId ;
2101+ });
2102+ for (const TVDisk* vdisk : vdisks) {
2103+ RenderVDisk (*jsonGroup.AddVDisks (), *vdisk);
20812104 }
20822105 if (FieldsAvailable.test (+EGroupFields::Encryption)) {
20832106 jsonGroup.SetEncryption (group->EncryptionMode );
0 commit comments