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  }