@@ -275,14 +275,11 @@ NProto::TDeviceConfig TDeviceList::AllocateDevice(
275275 const TDiskId& diskId,
276276 const TAllocationQuery& query)
277277{
278- for (auto & kv : NodeDevices) {
279- if (!query.NodeIds .empty () && !query.NodeIds .contains (kv. first )) {
278+ for (auto & [nodeId, nodeDevices] : NodeDevices) {
279+ if (!query.NodeIds .empty () && !query.NodeIds .contains (nodeId )) {
280280 continue ;
281281 }
282282
283- const ui32 nodeId = kv.first ;
284- auto & nodeDevices = kv.second ;
285-
286283 const auto & currentRack = nodeDevices.Rack ;
287284 auto & devices = nodeDevices.FreeDevices ;
288285
@@ -428,10 +425,6 @@ void TDeviceList::MarkDeviceAllocated(const TDiskId& diskId, const TDeviceId& id
428425 AllocatedDevices.emplace (id, diskId);
429426}
430427
431- // returns a list of racks sorted by preference and then by occupied space ASC
432- // then by free space DESC
433- // the nodes in each rack are sorted by occupied space ASC then by free space
434- // DESC
435428auto TDeviceList::SelectRacks (
436429 const TAllocationQuery& query,
437430 const TString& poolName) const -> TVector<TRack>
@@ -446,7 +439,6 @@ auto TDeviceList::SelectRacks(
446439 auto & rack = racks[currentRack];
447440 rack.Id = currentRack;
448441 rack.Nodes .push_back ({nodeId, 0 , 0 });
449- rack.Preferred = query.PreferredRacks .contains (currentRack);
450442 };
451443
452444 if (!query.NodeIds .empty ()) {
@@ -486,59 +478,64 @@ auto TDeviceList::SelectRacks(
486478
487479 TVector<TRack> result;
488480 result.reserve (racks.size ());
489- for (auto & r: racks) {
490- result.push_back (std::move (r.second ));
481+ for (auto & [_, r]: racks) {
482+ if (r.FreeSpace ) {
483+ r.Preferred = query.PreferredRacks .contains (r.Id );
484+ result.push_back (std::move (r));
485+ }
491486 }
492487
493488 return result;
494489}
495490
491+ // Returns a ranked list of nodes. Sorting is performed in stages:
492+ // - Sort racks by preference, occupied space, free space
493+ // - Sort nodes within each rack by occupied space, free space
494+ // - Optionally apply custom NodeRankingFunc to all nodes (if set in query)
496495auto TDeviceList::RankNodes (
497496 const TAllocationQuery& query,
498- TVector<TRack> racks) const -> TVector<TNodeInfo >
497+ TVector<TRack> racks) const -> TVector<TNodeId >
499498{
499+ // Sort racks by preference then by occupied space ASC then by free space
500+ // DESC
500501 Sort (
501502 racks,
502- [](const TRack& l, const TRack& r)
503+ [& ](const TRack& l, const TRack& r)
503504 {
504505 return std::tie (r.Preferred , l.OccupiedSpace , r.FreeSpace , l.Id ) <
505506 std::tie (l.Preferred , r.OccupiedSpace , l.FreeSpace , r.Id );
506507 });
507508
508- TVector<TNodeInfo> nodes ;
509+ TVector<TNodeId> nodeIds ;
509510 {
510511 size_t size = 0 ;
511512 for (const auto & rack: racks) {
512513 size += rack.Nodes .size ();
513514 }
514- nodes .reserve (size);
515+ nodeIds .reserve (size);
515516 }
516517
517- for (auto & rack: racks) {
518+ for (TRack& rack: racks) {
519+ // Sort rack's nodes by occupied space ASC then by free space DESC
518520 Sort (
519521 rack.Nodes ,
520- [](const TNodeInfo& l , const TNodeInfo& r )
522+ [](const TNodeInfo& lhs , const TNodeInfo& rhs )
521523 {
522- return std::tie (l .OccupiedSpace , r .FreeSpace ) <
523- std::tie (r .OccupiedSpace , l .FreeSpace );
524+ return std::tie (lhs .OccupiedSpace , rhs .FreeSpace ) <
525+ std::tie (rhs .OccupiedSpace , lhs .FreeSpace );
524526 });
525527
526- nodes.insert (
527- nodes.end (),
528- std::make_move_iterator (rack.Nodes .begin ()),
529- std::make_move_iterator (rack.Nodes .end ()));
528+ for (const TNodeInfo& node: rack.Nodes ) {
529+ nodeIds.push_back (node.NodeId );
530+ }
530531 }
531532
532- if (query.DownrankedNodeIds ) {
533- // move downranked nodes to the end of the list
534- std::stable_partition (
535- nodes.begin (),
536- nodes.end (),
537- [&](const TNodeInfo& node)
538- { return !query.DownrankedNodeIds .contains (node.NodeId ); });
533+ // Get the final order of nodes
534+ if (query.NodeRankingFunc ) {
535+ query.NodeRankingFunc (nodeIds);
539536 }
540537
541- return nodes ;
538+ return nodeIds ;
542539}
543540
544541TVector<TDeviceList::TDeviceRange> TDeviceList::CollectDevices (
@@ -552,8 +549,8 @@ TVector<TDeviceList::TDeviceRange> TDeviceList::CollectDevices(
552549 TVector<TDeviceRange> ranges;
553550 ui64 totalSize = query.GetTotalByteCount ();
554551
555- for (const auto & node : RankNodes (query, SelectRacks (query, poolName))) {
556- const auto * nodeDevices = NodeDevices.FindPtr (node. NodeId );
552+ for (ui32 nodeId : RankNodes (query, SelectRacks (query, poolName))) {
553+ const auto * nodeDevices = NodeDevices.FindPtr (nodeId );
557554 Y_ABORT_UNLESS (nodeDevices);
558555
559556 // finding free devices belonging to this node that match our
@@ -615,7 +612,7 @@ TVector<TDeviceList::TDeviceRange> TDeviceList::CollectDevices(
615612 }
616613
617614 if (deviceInfo.Range .first != it) {
618- ranges.emplace_back (node. NodeId , deviceInfo.Range .first , it);
615+ ranges.emplace_back (nodeId , deviceInfo.Range .first , it);
619616 }
620617
621618 if (totalSize == 0 ) {
0 commit comments