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

     1  // Copyright 2018 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package lease
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/errors"
    10  
    11  	"github.com/juju/juju/core/lease"
    12  )
    13  
    14  // broker describes methods for manipulating and checking leases.
    15  type broker interface {
    16  	lease.Checker
    17  	lease.Claimer
    18  	lease.Pinner
    19  }
    20  
    21  // boundManager implements the broker interface.
    22  // It represents a lease manager for a specific namespace and model.
    23  type boundManager struct {
    24  	manager   *Manager
    25  	secretary Secretary
    26  	namespace string
    27  	modelUUID string
    28  }
    29  
    30  // Claim is part of the lease.Claimer interface.
    31  func (b *boundManager) Claim(leaseName, holderName string, duration time.Duration) error {
    32  	key := b.leaseKey(leaseName)
    33  	if err := b.secretary.CheckLease(key); err != nil {
    34  		return errors.Annotatef(err, "cannot claim lease %q", leaseName)
    35  	}
    36  	if err := b.secretary.CheckHolder(holderName); err != nil {
    37  		return errors.Annotatef(err, "cannot claim lease for holder %q", holderName)
    38  	}
    39  	if err := b.secretary.CheckDuration(duration); err != nil {
    40  		return errors.Annotatef(err, "cannot claim lease for %s", duration)
    41  	}
    42  
    43  	return claim{
    44  		leaseKey:   key,
    45  		holderName: holderName,
    46  		duration:   duration,
    47  		response:   make(chan error),
    48  		stop:       b.manager.catacomb.Dying(),
    49  	}.invoke(b.manager.claims)
    50  }
    51  
    52  // WaitUntilExpired is part of the lease.Claimer interface.
    53  func (b *boundManager) WaitUntilExpired(leaseName string, cancel <-chan struct{}) error {
    54  	key := b.leaseKey(leaseName)
    55  	if err := b.secretary.CheckLease(key); err != nil {
    56  		return errors.Annotatef(err, "cannot wait for lease %q expiry", leaseName)
    57  	}
    58  
    59  	return block{
    60  		leaseKey: key,
    61  		unblock:  make(chan struct{}),
    62  		stop:     b.manager.catacomb.Dying(),
    63  		cancel:   cancel,
    64  	}.invoke(b.manager.blocks)
    65  }
    66  
    67  // Token is part of the lease.Checker interface.
    68  func (b *boundManager) Token(leaseName, holderName string) lease.Token {
    69  	return token{
    70  		leaseKey:   b.leaseKey(leaseName),
    71  		holderName: holderName,
    72  		secretary:  b.secretary,
    73  		checks:     b.manager.checks,
    74  		stop:       b.manager.catacomb.Dying(),
    75  	}
    76  }
    77  
    78  // Pinned (lease.Pinner) returns applications and the entities requiring their
    79  // pinned behaviour, for pinned leases in the bound namespace/model.
    80  func (b *boundManager) Pinned() map[string][]string {
    81  	return b.manager.pinned(b.namespace, b.modelUUID)
    82  }
    83  
    84  // Pin (lease.Pinner) sends a pin message to the worker loop.
    85  func (b *boundManager) Pin(leaseName string, entity string) error {
    86  	return errors.Trace(b.pinOp(leaseName, entity, b.manager.pins))
    87  }
    88  
    89  // Unpin (lease.Pinner) sends an unpin message to the worker loop.
    90  func (b *boundManager) Unpin(leaseName string, entity string) error {
    91  	return errors.Trace(b.pinOp(leaseName, entity, b.manager.unpins))
    92  }
    93  
    94  // pinOp creates a pin instance from the input lease name,
    95  // then sends it on the input channel.
    96  func (b *boundManager) pinOp(leaseName string, entity string, ch chan pin) error {
    97  	return errors.Trace(pin{
    98  		leaseKey: b.leaseKey(leaseName),
    99  		entity:   entity,
   100  		response: make(chan error),
   101  		stop:     b.manager.catacomb.Dying(),
   102  	}.invoke(ch))
   103  }
   104  
   105  // leaseKey returns a key for the manager's binding and the input lease name.
   106  func (b *boundManager) leaseKey(leaseName string) lease.Key {
   107  	return lease.Key{
   108  		Namespace: b.namespace,
   109  		ModelUUID: b.modelUUID,
   110  		Lease:     leaseName,
   111  	}
   112  }