github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/worker/lease/check.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package lease
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  
     9  	"github.com/juju/juju/core/lease"
    10  )
    11  
    12  // token implements lease.Token.
    13  type token struct {
    14  	leaseKey   lease.Key
    15  	holderName string
    16  	secretary  Secretary
    17  	checks     chan<- check
    18  	stop       <-chan struct{}
    19  }
    20  
    21  // Check is part of the lease.Token interface.
    22  func (t token) Check(attempt int, trapdoorKey interface{}) error {
    23  
    24  	// This validation, which could be done at Token creation time, is deferred
    25  	// until this point for historical reasons. In particular, this code was
    26  	// extracted from a *leadership* implementation which has a LeadershipCheck
    27  	// method returning a token; if it returned an error as well it would seem
    28  	// to imply that the method implemented a check itself, rather than a check
    29  	// factory.
    30  	//
    31  	// Fixing that would be great but seems out of scope.
    32  	if err := t.secretary.CheckLease(t.leaseKey); err != nil {
    33  		return errors.Annotatef(err, "cannot check lease %q", t.leaseKey.Lease)
    34  	}
    35  	if err := t.secretary.CheckHolder(t.holderName); err != nil {
    36  		return errors.Annotatef(err, "cannot check holder %q", t.holderName)
    37  	}
    38  	return check{
    39  		leaseKey:    t.leaseKey,
    40  		holderName:  t.holderName,
    41  		attempt:     attempt,
    42  		trapdoorKey: trapdoorKey,
    43  		response:    make(chan error),
    44  		stop:        t.stop,
    45  	}.invoke(t.checks)
    46  }
    47  
    48  // check is used to deliver lease-check requests to a manager's loop
    49  // goroutine on behalf of a token (as returned by LeadershipCheck).
    50  type check struct {
    51  	leaseKey    lease.Key
    52  	holderName  string
    53  	attempt     int
    54  	trapdoorKey interface{}
    55  	response    chan error
    56  	stop        <-chan struct{}
    57  }
    58  
    59  // invoke sends the check on the supplied channel and waits for an error
    60  // response.
    61  func (c check) invoke(ch chan<- check) error {
    62  	for {
    63  		select {
    64  		case <-c.stop:
    65  			return errStopped
    66  		case ch <- c:
    67  			ch = nil
    68  		case err := <-c.response:
    69  			return errors.Trace(err)
    70  		}
    71  	}
    72  }
    73  
    74  // respond notifies the originating invoke of completion status.
    75  func (c check) respond(err error) {
    76  	select {
    77  	case <-c.stop:
    78  	case c.response <- err:
    79  	}
    80  }