github.com/zoomfoo/nomad@v0.8.5-0.20180907175415-f28fd3a1a056/nomad/plan_apply_pool.go (about) 1 package nomad 2 3 import ( 4 "github.com/hashicorp/nomad/nomad/state" 5 "github.com/hashicorp/nomad/nomad/structs" 6 ) 7 8 const ( 9 // workerPoolBufferSize is the size of the buffers used to push 10 // request to the workers and to collect the responses. It should 11 // be large enough just to keep things busy 12 workerPoolBufferSize = 64 13 ) 14 15 // EvaluatePool is used to have a pool of workers that are evaluating 16 // if a plan is valid. It can be used to parallelize the evaluation 17 // of a plan. 18 type EvaluatePool struct { 19 workers int 20 workerStop []chan struct{} 21 req chan evaluateRequest 22 res chan evaluateResult 23 } 24 25 type evaluateRequest struct { 26 snap *state.StateSnapshot 27 plan *structs.Plan 28 nodeID string 29 } 30 31 type evaluateResult struct { 32 nodeID string 33 fit bool 34 reason string 35 err error 36 } 37 38 // NewEvaluatePool returns a pool of the given size. 39 func NewEvaluatePool(workers, bufSize int) *EvaluatePool { 40 p := &EvaluatePool{ 41 workers: workers, 42 workerStop: make([]chan struct{}, workers), 43 req: make(chan evaluateRequest, bufSize), 44 res: make(chan evaluateResult, bufSize), 45 } 46 for i := 0; i < workers; i++ { 47 stopCh := make(chan struct{}) 48 p.workerStop[i] = stopCh 49 go p.run(stopCh) 50 } 51 return p 52 } 53 54 // Size returns the current size 55 func (p *EvaluatePool) Size() int { 56 return p.workers 57 } 58 59 // SetSize is used to resize the worker pool 60 func (p *EvaluatePool) SetSize(size int) { 61 // Protect against a negative size 62 if size < 0 { 63 size = 0 64 } 65 66 // Handle an upwards resize 67 if size >= p.workers { 68 for i := p.workers; i < size; i++ { 69 stopCh := make(chan struct{}) 70 p.workerStop = append(p.workerStop, stopCh) 71 go p.run(stopCh) 72 } 73 p.workers = size 74 return 75 } 76 77 // Handle a downwards resize 78 for i := p.workers; i > size; i-- { 79 close(p.workerStop[i-1]) 80 p.workerStop[i-1] = nil 81 } 82 p.workerStop = p.workerStop[:size] 83 p.workers = size 84 } 85 86 // RequestCh is used to push requests 87 func (p *EvaluatePool) RequestCh() chan<- evaluateRequest { 88 return p.req 89 } 90 91 // ResultCh is used to read the results as they are ready 92 func (p *EvaluatePool) ResultCh() <-chan evaluateResult { 93 return p.res 94 } 95 96 // Shutdown is used to shutdown the pool 97 func (p *EvaluatePool) Shutdown() { 98 p.SetSize(0) 99 } 100 101 // run is a long running go routine per worker 102 func (p *EvaluatePool) run(stopCh chan struct{}) { 103 for { 104 select { 105 case req := <-p.req: 106 fit, reason, err := evaluateNodePlan(req.snap, req.plan, req.nodeID) 107 p.res <- evaluateResult{req.nodeID, fit, reason, err} 108 109 case <-stopCh: 110 return 111 } 112 } 113 }