github.com/taylorchu/nomad@v0.5.3-rc1.0.20170407200202-db11e7dd7b55/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 err error 35 } 36 37 // NewEvaluatePool returns a pool of the given size. 38 func NewEvaluatePool(workers, bufSize int) *EvaluatePool { 39 p := &EvaluatePool{ 40 workers: workers, 41 workerStop: make([]chan struct{}, workers), 42 req: make(chan evaluateRequest, bufSize), 43 res: make(chan evaluateResult, bufSize), 44 } 45 for i := 0; i < workers; i++ { 46 stopCh := make(chan struct{}) 47 p.workerStop[i] = stopCh 48 go p.run(stopCh) 49 } 50 return p 51 } 52 53 // Size returns the current size 54 func (p *EvaluatePool) Size() int { 55 return p.workers 56 } 57 58 // SetSize is used to resize the worker pool 59 func (p *EvaluatePool) SetSize(size int) { 60 // Protect against a negative size 61 if size < 0 { 62 size = 0 63 } 64 65 // Handle an upwards resize 66 if size >= p.workers { 67 for i := p.workers; i < size; i++ { 68 stopCh := make(chan struct{}) 69 p.workerStop = append(p.workerStop, stopCh) 70 go p.run(stopCh) 71 } 72 p.workers = size 73 return 74 } 75 76 // Handle a downwards resize 77 for i := p.workers; i > size; i-- { 78 close(p.workerStop[i-1]) 79 p.workerStop[i-1] = nil 80 } 81 p.workerStop = p.workerStop[:size] 82 p.workers = size 83 } 84 85 // RequestCh is used to push requests 86 func (p *EvaluatePool) RequestCh() chan<- evaluateRequest { 87 return p.req 88 } 89 90 // ResultCh is used to read the results as they are ready 91 func (p *EvaluatePool) ResultCh() <-chan evaluateResult { 92 return p.res 93 } 94 95 // Shutdown is used to shutdown the pool 96 func (p *EvaluatePool) Shutdown() { 97 p.SetSize(0) 98 } 99 100 // run is a long running go routine per worker 101 func (p *EvaluatePool) run(stopCh chan struct{}) { 102 for { 103 select { 104 case req := <-p.req: 105 fit, err := evaluateNodePlan(req.snap, req.plan, req.nodeID) 106 p.res <- evaluateResult{req.nodeID, fit, err} 107 108 case <-stopCh: 109 return 110 } 111 } 112 }