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