func TestMathMaxInt(t *testing.T) { tests := [][3]int{{1, 2, 2}, {-1, 1, 1}, {2, 0, 2}} for _, test := range tests { expected := test[2] actual := lib.MaxInt(test[0], test[1]) if expected != actual { t.Fatalf("expected %d, got %d", expected, actual) } } }
// unblock unblocks all blocked evals that could run on the passed computed node // class. func (b *BlockedEvals) unblock(computedClass string, index uint64) { b.l.Lock() defer b.l.Unlock() // Protect against the case of a flush. if !b.enabled { return } // Every eval that has escaped computed node class has to be unblocked // because any node could potentially be feasible. numEscaped := len(b.escaped) unblocked := make(map[*structs.Evaluation]string, lib.MaxInt(numEscaped, 4)) if numEscaped != 0 { for id, wrapped := range b.escaped { unblocked[wrapped.eval] = wrapped.token delete(b.escaped, id) delete(b.jobs, wrapped.eval.JobID) } } // We unblock any eval that is explicitly eligible for the computed class // and also any eval that is not eligible or uneligible. This signifies that // when the evaluation was originally run through the scheduler, that it // never saw a node with the given computed class and thus needs to be // unblocked for correctness. for id, wrapped := range b.captured { if elig, ok := wrapped.eval.ClassEligibility[computedClass]; ok && !elig { // Can skip because the eval has explicitly marked the node class // as ineligible. continue } // The computed node class has never been seen by the eval so we unblock // it. unblocked[wrapped.eval] = wrapped.token delete(b.jobs, wrapped.eval.JobID) delete(b.captured, id) } if l := len(unblocked); l != 0 { // Update the counters b.stats.TotalEscaped = 0 b.stats.TotalBlocked -= l // Enqueue all the unblocked evals into the broker. b.evalBroker.EnqueueAll(unblocked) } }