volcano.sh/volcano@v1.9.0/pkg/scheduler/framework/session_plugins.go (about) 1 /* 2 Copyright 2018 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package framework 18 19 import ( 20 k8sframework "k8s.io/kubernetes/pkg/scheduler/framework" 21 22 "volcano.sh/apis/pkg/apis/scheduling" 23 "volcano.sh/volcano/pkg/controllers/job/helpers" 24 "volcano.sh/volcano/pkg/scheduler/api" 25 "volcano.sh/volcano/pkg/scheduler/util" 26 ) 27 28 // AddJobOrderFn add job order function 29 func (ssn *Session) AddJobOrderFn(name string, cf api.CompareFn) { 30 ssn.jobOrderFns[name] = cf 31 } 32 33 // AddQueueOrderFn add queue order function 34 func (ssn *Session) AddQueueOrderFn(name string, qf api.CompareFn) { 35 ssn.queueOrderFns[name] = qf 36 } 37 38 // AddClusterOrderFn add queue order function 39 func (ssn *Session) AddClusterOrderFn(name string, qf api.CompareFn) { 40 ssn.clusterOrderFns[name] = qf 41 } 42 43 // AddTaskOrderFn add task order function 44 func (ssn *Session) AddTaskOrderFn(name string, cf api.CompareFn) { 45 ssn.taskOrderFns[name] = cf 46 } 47 48 // AddPreemptableFn add preemptable function 49 func (ssn *Session) AddPreemptableFn(name string, cf api.EvictableFn) { 50 ssn.preemptableFns[name] = cf 51 } 52 53 // AddReclaimableFn add Reclaimable function 54 func (ssn *Session) AddReclaimableFn(name string, rf api.EvictableFn) { 55 ssn.reclaimableFns[name] = rf 56 } 57 58 // AddJobReadyFn add JobReady function 59 func (ssn *Session) AddJobReadyFn(name string, vf api.ValidateFn) { 60 ssn.jobReadyFns[name] = vf 61 } 62 63 // AddJobPipelinedFn add pipelined function 64 func (ssn *Session) AddJobPipelinedFn(name string, vf api.VoteFn) { 65 ssn.jobPipelinedFns[name] = vf 66 } 67 68 // AddPredicateFn add Predicate function 69 func (ssn *Session) AddPredicateFn(name string, pf api.PredicateFn) { 70 ssn.predicateFns[name] = pf 71 } 72 73 // AddPrePredicateFn add PrePredicate function 74 func (ssn *Session) AddPrePredicateFn(name string, pf api.PrePredicateFn) { 75 ssn.prePredicateFns[name] = pf 76 } 77 78 // AddBestNodeFn add BestNode function 79 func (ssn *Session) AddBestNodeFn(name string, pf api.BestNodeFn) { 80 ssn.bestNodeFns[name] = pf 81 } 82 83 // AddNodeOrderFn add Node order function 84 func (ssn *Session) AddNodeOrderFn(name string, pf api.NodeOrderFn) { 85 ssn.nodeOrderFns[name] = pf 86 } 87 88 // AddBatchNodeOrderFn add Batch Node order function 89 func (ssn *Session) AddBatchNodeOrderFn(name string, pf api.BatchNodeOrderFn) { 90 ssn.batchNodeOrderFns[name] = pf 91 } 92 93 // AddNodeMapFn add Node map function 94 func (ssn *Session) AddNodeMapFn(name string, pf api.NodeMapFn) { 95 ssn.nodeMapFns[name] = pf 96 } 97 98 // AddNodeReduceFn add Node reduce function 99 func (ssn *Session) AddNodeReduceFn(name string, pf api.NodeReduceFn) { 100 ssn.nodeReduceFns[name] = pf 101 } 102 103 // AddOverusedFn add overused function 104 func (ssn *Session) AddOverusedFn(name string, fn api.ValidateFn) { 105 ssn.overusedFns[name] = fn 106 } 107 108 // AddPreemptiveFn add preemptive function 109 func (ssn *Session) AddPreemptiveFn(name string, fn api.ValidateFn) { 110 ssn.preemptiveFns[name] = fn 111 } 112 113 // AddAllocatableFn add allocatable function 114 func (ssn *Session) AddAllocatableFn(name string, fn api.AllocatableFn) { 115 ssn.allocatableFns[name] = fn 116 } 117 118 // AddJobValidFn add jobvalid function 119 func (ssn *Session) AddJobValidFn(name string, fn api.ValidateExFn) { 120 ssn.jobValidFns[name] = fn 121 } 122 123 // AddJobEnqueueableFn add jobenqueueable function 124 func (ssn *Session) AddJobEnqueueableFn(name string, fn api.VoteFn) { 125 ssn.jobEnqueueableFns[name] = fn 126 } 127 128 // AddJobEnqueuedFn add jobEnqueued function 129 func (ssn *Session) AddJobEnqueuedFn(name string, fn api.JobEnqueuedFn) { 130 ssn.jobEnqueuedFns[name] = fn 131 } 132 133 // AddTargetJobFn add targetjob function 134 func (ssn *Session) AddTargetJobFn(name string, fn api.TargetJobFn) { 135 ssn.targetJobFns[name] = fn 136 } 137 138 // AddReservedNodesFn add reservedNodesFn function 139 func (ssn *Session) AddReservedNodesFn(name string, fn api.ReservedNodesFn) { 140 ssn.reservedNodesFns[name] = fn 141 } 142 143 // AddVictimTasksFns add victimTasksFns function 144 func (ssn *Session) AddVictimTasksFns(name string, fns []api.VictimTasksFn) { 145 ssn.victimTasksFns[name] = fns 146 } 147 148 // AddJobStarvingFns add jobStarvingFns function 149 func (ssn *Session) AddJobStarvingFns(name string, fn api.ValidateFn) { 150 ssn.jobStarvingFns[name] = fn 151 } 152 153 // Reclaimable invoke reclaimable function of the plugins 154 func (ssn *Session) Reclaimable(reclaimer *api.TaskInfo, reclaimees []*api.TaskInfo) []*api.TaskInfo { 155 var victims []*api.TaskInfo 156 var init bool 157 158 for _, tier := range ssn.Tiers { 159 for _, plugin := range tier.Plugins { 160 if !isEnabled(plugin.EnabledReclaimable) { 161 continue 162 } 163 rf, found := ssn.reclaimableFns[plugin.Name] 164 if !found { 165 continue 166 } 167 168 candidates, abstain := rf(reclaimer, reclaimees) 169 if abstain == 0 { 170 continue 171 } 172 if len(candidates) == 0 { 173 victims = nil 174 break 175 } 176 if !init { 177 victims = candidates 178 init = true 179 } else { 180 var intersection []*api.TaskInfo 181 // Get intersection of victims and candidates. 182 for _, v := range victims { 183 for _, c := range candidates { 184 if v.UID == c.UID { 185 intersection = append(intersection, v) 186 } 187 } 188 } 189 190 // Update victims to intersection 191 victims = intersection 192 } 193 } 194 // Plugins in this tier made decision if victims is not nil 195 if victims != nil { 196 return victims 197 } 198 } 199 200 return victims 201 } 202 203 // Preemptable invoke preemptable function of the plugins 204 func (ssn *Session) Preemptable(preemptor *api.TaskInfo, preemptees []*api.TaskInfo) []*api.TaskInfo { 205 var victims []*api.TaskInfo 206 var init bool 207 208 for _, tier := range ssn.Tiers { 209 for _, plugin := range tier.Plugins { 210 if !isEnabled(plugin.EnabledPreemptable) { 211 continue 212 } 213 214 pf, found := ssn.preemptableFns[plugin.Name] 215 if !found { 216 continue 217 } 218 candidates, abstain := pf(preemptor, preemptees) 219 if abstain == 0 { 220 continue 221 } 222 // intersection will be nil if length is 0, don't need to do any more check 223 if len(candidates) == 0 { 224 victims = nil 225 break 226 } 227 228 if !init { 229 victims = candidates 230 init = true 231 } else { 232 var intersection []*api.TaskInfo 233 // Get intersection of victims and candidates. 234 for _, v := range victims { 235 for _, c := range candidates { 236 if v.UID == c.UID { 237 intersection = append(intersection, v) 238 } 239 } 240 } 241 242 // Update victims to intersection 243 victims = intersection 244 } 245 } 246 // Plugins in this tier made decision if victims is not nil 247 if victims != nil { 248 return victims 249 } 250 } 251 252 return victims 253 } 254 255 // Overused invoke overused function of the plugins 256 func (ssn *Session) Overused(queue *api.QueueInfo) bool { 257 for _, tier := range ssn.Tiers { 258 for _, plugin := range tier.Plugins { 259 if !isEnabled(plugin.EnabledOverused) { 260 continue 261 } 262 of, found := ssn.overusedFns[plugin.Name] 263 if !found { 264 continue 265 } 266 if of(queue) { 267 return true 268 } 269 } 270 } 271 272 return false 273 } 274 275 // Preemptive invoke can preemptive function of the plugins 276 func (ssn *Session) Preemptive(queue *api.QueueInfo) bool { 277 for _, tier := range ssn.Tiers { 278 for _, plugin := range tier.Plugins { 279 of, found := ssn.preemptiveFns[plugin.Name] 280 if !isEnabled(plugin.EnablePreemptive) { 281 continue 282 } 283 if !found { 284 continue 285 } 286 if !of(queue) { 287 return false 288 } 289 } 290 } 291 292 return true 293 } 294 295 // Allocatable invoke allocatable function of the plugins 296 func (ssn *Session) Allocatable(queue *api.QueueInfo, candidate *api.TaskInfo) bool { 297 for _, tier := range ssn.Tiers { 298 for _, plugin := range tier.Plugins { 299 if !isEnabled(plugin.EnabledAllocatable) { 300 continue 301 } 302 af, found := ssn.allocatableFns[plugin.Name] 303 if !found { 304 continue 305 } 306 if !af(queue, candidate) { 307 return false 308 } 309 } 310 } 311 312 return true 313 } 314 315 // JobReady invoke jobready function of the plugins 316 func (ssn *Session) JobReady(obj interface{}) bool { 317 for _, tier := range ssn.Tiers { 318 for _, plugin := range tier.Plugins { 319 if !isEnabled(plugin.EnabledJobReady) { 320 continue 321 } 322 jrf, found := ssn.jobReadyFns[plugin.Name] 323 if !found { 324 continue 325 } 326 327 if !jrf(obj) { 328 return false 329 } 330 } 331 } 332 333 return true 334 } 335 336 // JobPipelined invoke pipelined function of the plugins 337 // Check if job has get enough resource to run 338 func (ssn *Session) JobPipelined(obj interface{}) bool { 339 var hasFound bool 340 for _, tier := range ssn.Tiers { 341 for _, plugin := range tier.Plugins { 342 if !isEnabled(plugin.EnabledJobPipelined) { 343 continue 344 } 345 jrf, found := ssn.jobPipelinedFns[plugin.Name] 346 if !found { 347 continue 348 } 349 350 res := jrf(obj) 351 if res < 0 { 352 return false 353 } 354 if res > 0 { 355 hasFound = true 356 } 357 } 358 // if plugin exists that votes permit, meanwhile other plugin votes abstention, 359 // permit job to be pipelined, do not check next tier 360 if hasFound { 361 return true 362 } 363 } 364 365 return true 366 } 367 368 // JobStarving invoke jobStarving function of the plugins 369 // Check if job still need more resource 370 func (ssn *Session) JobStarving(obj interface{}) bool { 371 var hasFound bool 372 for _, tier := range ssn.Tiers { 373 for _, plugin := range tier.Plugins { 374 if !isEnabled(plugin.EnabledJobStarving) { 375 continue 376 } 377 jrf, found := ssn.jobStarvingFns[plugin.Name] 378 if !found { 379 continue 380 } 381 hasFound = true 382 383 if !jrf(obj) { 384 return false 385 } 386 } 387 // this tier registered function 388 if hasFound { 389 return true 390 } 391 } 392 393 return false 394 } 395 396 // JobValid invoke jobvalid function of the plugins 397 func (ssn *Session) JobValid(obj interface{}) *api.ValidateResult { 398 for _, tier := range ssn.Tiers { 399 for _, plugin := range tier.Plugins { 400 jrf, found := ssn.jobValidFns[plugin.Name] 401 if !found { 402 continue 403 } 404 405 if vr := jrf(obj); vr != nil && !vr.Pass { 406 return vr 407 } 408 } 409 } 410 411 return nil 412 } 413 414 // JobEnqueueable invoke jobEnqueueableFns function of the plugins 415 func (ssn *Session) JobEnqueueable(obj interface{}) bool { 416 var hasFound bool 417 for _, tier := range ssn.Tiers { 418 for _, plugin := range tier.Plugins { 419 if !isEnabled(plugin.EnabledJobEnqueued) { 420 continue 421 } 422 fn, found := ssn.jobEnqueueableFns[plugin.Name] 423 if !found { 424 continue 425 } 426 427 res := fn(obj) 428 if res < 0 { 429 return false 430 } 431 if res > 0 { 432 hasFound = true 433 } 434 } 435 // if plugin exists that votes permit, meanwhile other plugin votes abstention, 436 // permit job to be enqueueable, do not check next tier 437 if hasFound { 438 return true 439 } 440 } 441 442 return true 443 } 444 445 // JobEnqueued invoke jobEnqueuedFns function of the plugins 446 func (ssn *Session) JobEnqueued(obj interface{}) { 447 for _, tier := range ssn.Tiers { 448 for _, plugin := range tier.Plugins { 449 if !isEnabled(plugin.EnabledJobEnqueued) { 450 continue 451 } 452 fn, found := ssn.jobEnqueuedFns[plugin.Name] 453 if !found { 454 continue 455 } 456 457 fn(obj) 458 } 459 } 460 } 461 462 // TargetJob invoke targetJobFns function of the plugins 463 func (ssn *Session) TargetJob(jobs []*api.JobInfo) *api.JobInfo { 464 for _, tier := range ssn.Tiers { 465 for _, plugin := range tier.Plugins { 466 if !isEnabled(plugin.EnabledTargetJob) { 467 continue 468 } 469 fn, found := ssn.targetJobFns[plugin.Name] 470 if !found { 471 continue 472 } 473 return fn(jobs) 474 } 475 } 476 return nil 477 } 478 479 // VictimTasks returns the victims selected 480 func (ssn *Session) VictimTasks(tasks []*api.TaskInfo) map[*api.TaskInfo]bool { 481 // different filters may add the same task to victims, so use a map to remove duplicate tasks. 482 victimSet := make(map[*api.TaskInfo]bool) 483 for _, tier := range ssn.Tiers { 484 for _, plugin := range tier.Plugins { 485 if !isEnabled(plugin.EnabledVictim) { 486 continue 487 } 488 fns, found := ssn.victimTasksFns[plugin.Name] 489 if !found { 490 continue 491 } 492 for _, fn := range fns { 493 victimTasks := fn(tasks) 494 for _, victim := range victimTasks { 495 victimSet[victim] = true 496 } 497 } 498 } 499 if len(victimSet) > 0 { 500 return victimSet 501 } 502 } 503 return victimSet 504 } 505 506 // ReservedNodes invoke ReservedNodes function of the plugins 507 func (ssn *Session) ReservedNodes() { 508 for _, tier := range ssn.Tiers { 509 for _, plugin := range tier.Plugins { 510 if !isEnabled(plugin.EnabledReservedNodes) { 511 continue 512 } 513 fn, found := ssn.reservedNodesFns[plugin.Name] 514 if !found { 515 continue 516 } 517 fn() 518 } 519 } 520 } 521 522 // JobOrderFn invoke joborder function of the plugins 523 func (ssn *Session) JobOrderFn(l, r interface{}) bool { 524 for _, tier := range ssn.Tiers { 525 for _, plugin := range tier.Plugins { 526 if !isEnabled(plugin.EnabledJobOrder) { 527 continue 528 } 529 jof, found := ssn.jobOrderFns[plugin.Name] 530 if !found { 531 continue 532 } 533 if j := jof(l, r); j != 0 { 534 return j < 0 535 } 536 } 537 } 538 539 // If no job order funcs, order job by CreationTimestamp first, then by UID. 540 lv := l.(*api.JobInfo) 541 rv := r.(*api.JobInfo) 542 if lv.CreationTimestamp.Equal(&rv.CreationTimestamp) { 543 return lv.UID < rv.UID 544 } 545 return lv.CreationTimestamp.Before(&rv.CreationTimestamp) 546 } 547 548 // ClusterOrderFn invoke ClusterOrderFn function of the plugins 549 func (ssn *Session) ClusterOrderFn(l, r interface{}) bool { 550 for _, tier := range ssn.Tiers { 551 for _, plugin := range tier.Plugins { 552 if !isEnabled(plugin.EnabledClusterOrder) { 553 continue 554 } 555 cof, found := ssn.clusterOrderFns[plugin.Name] 556 if !found { 557 continue 558 } 559 if j := cof(l, r); j != 0 { 560 return j < 0 561 } 562 } 563 } 564 565 // If no cluster order funcs, order cluster by ClusterID 566 lv := l.(*scheduling.Cluster) 567 rv := r.(*scheduling.Cluster) 568 return lv.Name < rv.Name 569 } 570 571 // QueueOrderFn invoke queueorder function of the plugins 572 func (ssn *Session) QueueOrderFn(l, r interface{}) bool { 573 for _, tier := range ssn.Tiers { 574 for _, plugin := range tier.Plugins { 575 if !isEnabled(plugin.EnabledQueueOrder) { 576 continue 577 } 578 qof, found := ssn.queueOrderFns[plugin.Name] 579 if !found { 580 continue 581 } 582 if j := qof(l, r); j != 0 { 583 return j < 0 584 } 585 } 586 } 587 588 // If no queue order funcs, order queue by CreationTimestamp first, then by UID. 589 lv := l.(*api.QueueInfo) 590 rv := r.(*api.QueueInfo) 591 if lv.Queue.CreationTimestamp.Equal(&rv.Queue.CreationTimestamp) { 592 return lv.UID < rv.UID 593 } 594 return lv.Queue.CreationTimestamp.Before(&rv.Queue.CreationTimestamp) 595 } 596 597 // TaskCompareFns invoke taskorder function of the plugins 598 func (ssn *Session) TaskCompareFns(l, r interface{}) int { 599 for _, tier := range ssn.Tiers { 600 for _, plugin := range tier.Plugins { 601 if !isEnabled(plugin.EnabledTaskOrder) { 602 continue 603 } 604 tof, found := ssn.taskOrderFns[plugin.Name] 605 if !found { 606 continue 607 } 608 if j := tof(l, r); j != 0 { 609 return j 610 } 611 } 612 } 613 614 return 0 615 } 616 617 // TaskOrderFn invoke taskorder function of the plugins 618 func (ssn *Session) TaskOrderFn(l, r interface{}) bool { 619 if res := ssn.TaskCompareFns(l, r); res != 0 { 620 return res < 0 621 } 622 623 // If no task order funcs, order task by default func. 624 lv := l.(*api.TaskInfo) 625 rv := r.(*api.TaskInfo) 626 return helpers.CompareTask(lv, rv) 627 } 628 629 // PredicateFn invoke predicate function of the plugins 630 func (ssn *Session) PredicateFn(task *api.TaskInfo, node *api.NodeInfo) ([]*api.Status, error) { 631 predicateStatus := make([]*api.Status, 0) 632 for _, tier := range ssn.Tiers { 633 for _, plugin := range tier.Plugins { 634 if !isEnabled(plugin.EnabledPredicate) { 635 continue 636 } 637 pfn, found := ssn.predicateFns[plugin.Name] 638 if !found { 639 continue 640 } 641 status, err := pfn(task, node) 642 predicateStatus = append(predicateStatus, status...) 643 if err != nil { 644 return predicateStatus, err 645 } 646 } 647 } 648 return predicateStatus, nil 649 } 650 651 // PrePredicateFn invoke predicate function of the plugins 652 func (ssn *Session) PrePredicateFn(task *api.TaskInfo) error { 653 for _, tier := range ssn.Tiers { 654 for _, plugin := range tier.Plugins { 655 // we use same option as predicates for they are 656 if !isEnabled(plugin.EnabledPredicate) { 657 continue 658 } 659 pfn, found := ssn.prePredicateFns[plugin.Name] 660 if !found { 661 continue 662 } 663 err := pfn(task) 664 if err != nil { 665 return err 666 } 667 } 668 } 669 return nil 670 } 671 672 // BestNodeFn invoke bestNode function of the plugins 673 func (ssn *Session) BestNodeFn(task *api.TaskInfo, nodeScores map[float64][]*api.NodeInfo) *api.NodeInfo { 674 for _, tier := range ssn.Tiers { 675 for _, plugin := range tier.Plugins { 676 if !isEnabled(plugin.EnabledBestNode) { 677 continue 678 } 679 pfn, found := ssn.bestNodeFns[plugin.Name] 680 if !found { 681 continue 682 } 683 // Only the first plugin that enables and realizes bestNodeFn is allowed to choose best node for task 684 if bestNode := pfn(task, nodeScores); bestNode != nil { 685 return bestNode 686 } 687 } 688 } 689 return nil 690 } 691 692 // NodeOrderFn invoke node order function of the plugins 693 func (ssn *Session) NodeOrderFn(task *api.TaskInfo, node *api.NodeInfo) (float64, error) { 694 priorityScore := 0.0 695 for _, tier := range ssn.Tiers { 696 for _, plugin := range tier.Plugins { 697 if !isEnabled(plugin.EnabledNodeOrder) { 698 continue 699 } 700 pfn, found := ssn.nodeOrderFns[plugin.Name] 701 if !found { 702 continue 703 } 704 score, err := pfn(task, node) 705 if err != nil { 706 return 0, err 707 } 708 priorityScore += score 709 } 710 } 711 return priorityScore, nil 712 } 713 714 // BatchNodeOrderFn invoke node order function of the plugins 715 func (ssn *Session) BatchNodeOrderFn(task *api.TaskInfo, nodes []*api.NodeInfo) (map[string]float64, error) { 716 priorityScore := make(map[string]float64, len(nodes)) 717 for _, tier := range ssn.Tiers { 718 for _, plugin := range tier.Plugins { 719 if !isEnabled(plugin.EnabledNodeOrder) { 720 continue 721 } 722 pfn, found := ssn.batchNodeOrderFns[plugin.Name] 723 if !found { 724 continue 725 } 726 score, err := pfn(task, nodes) 727 if err != nil { 728 return nil, err 729 } 730 for nodeName, score := range score { 731 priorityScore[nodeName] += score 732 } 733 } 734 } 735 return priorityScore, nil 736 } 737 738 func isEnabled(enabled *bool) bool { 739 return enabled != nil && *enabled 740 } 741 742 // NodeOrderMapFn invoke node order function of the plugins 743 func (ssn *Session) NodeOrderMapFn(task *api.TaskInfo, node *api.NodeInfo) (map[string]float64, float64, error) { 744 nodeScoreMap := map[string]float64{} 745 var priorityScore float64 746 for _, tier := range ssn.Tiers { 747 for _, plugin := range tier.Plugins { 748 if !isEnabled(plugin.EnabledNodeOrder) { 749 continue 750 } 751 if pfn, found := ssn.nodeOrderFns[plugin.Name]; found { 752 score, err := pfn(task, node) 753 if err != nil { 754 return nodeScoreMap, priorityScore, err 755 } 756 priorityScore += score 757 } 758 if pfn, found := ssn.nodeMapFns[plugin.Name]; found { 759 score, err := pfn(task, node) 760 if err != nil { 761 return nodeScoreMap, priorityScore, err 762 } 763 nodeScoreMap[plugin.Name] = score 764 } 765 } 766 } 767 return nodeScoreMap, priorityScore, nil 768 } 769 770 // NodeOrderReduceFn invoke node order function of the plugins 771 func (ssn *Session) NodeOrderReduceFn(task *api.TaskInfo, pluginNodeScoreMap map[string]k8sframework.NodeScoreList) (map[string]float64, error) { 772 nodeScoreMap := map[string]float64{} 773 for _, tier := range ssn.Tiers { 774 for _, plugin := range tier.Plugins { 775 if !isEnabled(plugin.EnabledNodeOrder) { 776 continue 777 } 778 pfn, found := ssn.nodeReduceFns[plugin.Name] 779 if !found { 780 continue 781 } 782 if err := pfn(task, pluginNodeScoreMap[plugin.Name]); err != nil { 783 return nodeScoreMap, err 784 } 785 for _, hp := range pluginNodeScoreMap[plugin.Name] { 786 nodeScoreMap[hp.Name] += float64(hp.Score) 787 } 788 } 789 } 790 return nodeScoreMap, nil 791 } 792 793 // BuildVictimsPriorityQueue returns a priority queue with victims sorted by: 794 // if victims has same job id, sorted by !ssn.TaskOrderFn 795 // if victims has different job id, sorted by !ssn.JobOrderFn 796 func (ssn *Session) BuildVictimsPriorityQueue(victims []*api.TaskInfo) *util.PriorityQueue { 797 victimsQueue := util.NewPriorityQueue(func(l, r interface{}) bool { 798 lv := l.(*api.TaskInfo) 799 rv := r.(*api.TaskInfo) 800 if lv.Job == rv.Job { 801 return !ssn.TaskOrderFn(l, r) 802 } 803 return !ssn.JobOrderFn(ssn.Jobs[lv.Job], ssn.Jobs[rv.Job]) 804 }) 805 for _, victim := range victims { 806 victimsQueue.Push(victim) 807 } 808 return victimsQueue 809 }