github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/state/leadership/check.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package leadership 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/names" 9 ) 10 11 // check is used to deliver leadership-check requests to a manager's loop 12 // goroutine on behalf of CheckLeadership. 13 type check struct { 14 serviceName string 15 unitName string 16 response chan Token 17 abort <-chan struct{} 18 } 19 20 // validate returns an error if any fields are invalid or missing. 21 func (c check) validate() error { 22 if !names.IsValidService(c.serviceName) { 23 return errors.Errorf("invalid service name %q", c.serviceName) 24 } 25 if !names.IsValidUnit(c.unitName) { 26 return errors.Errorf("invalid unit name %q", c.unitName) 27 } 28 if c.response == nil { 29 return errors.New("missing response channel") 30 } 31 if c.abort == nil { 32 return errors.New("missing abort channel") 33 } 34 return nil 35 } 36 37 // invoke sends the check on the supplied channel, waits for a response, and 38 // returns either a Token that can be used to assert continued leadership in 39 // the future, or an error. 40 func (c check) invoke(ch chan<- check) (Token, error) { 41 if err := c.validate(); err != nil { 42 return nil, errors.Annotatef(err, "cannot check leadership") 43 } 44 for { 45 select { 46 case <-c.abort: 47 return nil, errStopped 48 case ch <- c: 49 ch = nil 50 case token := <-c.response: 51 if token == nil { 52 return nil, errors.Errorf("%q is not leader of %q", c.unitName, c.serviceName) 53 } 54 return token, nil 55 } 56 } 57 } 58 59 // respond causes the supplied token to be sent back to invoke. 60 func (c check) respond(token Token) { 61 select { 62 case <-c.abort: 63 case c.response <- token: 64 } 65 }