github.com/iqoqo/nomad@v0.11.3-0.20200911112621-d7021c74d101/nomad/drainer/drainer_util.go (about) 1 package drainer 2 3 import ( 4 "github.com/hashicorp/nomad/nomad/structs" 5 ) 6 7 const ( 8 // defaultMaxIdsPerTxn is the maximum number of IDs that can be included in a 9 // single Raft transaction. This is to ensure that the Raft message 10 // does not become too large. 11 defaultMaxIdsPerTxn = (1024 * 256) / 36 // 0.25 MB of ids. 12 ) 13 14 // partitionIds takes a set of IDs and returns a partitioned view of them such 15 // that no batch would result in an overly large raft transaction. 16 func partitionIds(maxIds int, ids []string) [][]string { 17 index := 0 18 total := len(ids) 19 var partitions [][]string 20 for remaining := total - index; remaining > 0; remaining = total - index { 21 if remaining < maxIds { 22 partitions = append(partitions, ids[index:]) 23 break 24 } else { 25 partitions = append(partitions, ids[index:index+maxIds]) 26 index += maxIds 27 } 28 } 29 30 return partitions 31 } 32 33 // transitionTuple is used to group desired transitions and evals 34 type transitionTuple struct { 35 Transitions map[string]*structs.DesiredTransition 36 Evals []*structs.Evaluation 37 } 38 39 // partitionAllocDrain returns a list of alloc transitions and evals to apply 40 // in a single raft transaction.This is necessary to ensure that the Raft 41 // transaction does not become too large. 42 func partitionAllocDrain(maxIds int, transitions map[string]*structs.DesiredTransition, 43 evals []*structs.Evaluation) []*transitionTuple { 44 45 // Determine a stable ordering of the transitioning allocs 46 allocs := make([]string, 0, len(transitions)) 47 for id := range transitions { 48 allocs = append(allocs, id) 49 } 50 51 var requests []*transitionTuple 52 submittedEvals, submittedTrans := 0, 0 53 for submittedEvals != len(evals) || submittedTrans != len(transitions) { 54 req := &transitionTuple{ 55 Transitions: make(map[string]*structs.DesiredTransition), 56 } 57 requests = append(requests, req) 58 available := maxIds 59 60 // Add the allocs first 61 if remaining := len(allocs) - submittedTrans; remaining > 0 { 62 if remaining <= available { 63 for _, id := range allocs[submittedTrans:] { 64 req.Transitions[id] = transitions[id] 65 } 66 available -= remaining 67 submittedTrans += remaining 68 } else { 69 for _, id := range allocs[submittedTrans : submittedTrans+available] { 70 req.Transitions[id] = transitions[id] 71 } 72 submittedTrans += available 73 74 // Exhausted space so skip adding evals 75 continue 76 } 77 78 } 79 80 // Add the evals 81 if remaining := len(evals) - submittedEvals; remaining > 0 { 82 if remaining <= available { 83 req.Evals = evals[submittedEvals:] 84 submittedEvals += remaining 85 } else { 86 req.Evals = evals[submittedEvals : submittedEvals+available] 87 submittedEvals += available 88 } 89 } 90 } 91 92 return requests 93 }