github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/provider/dummy/leasestore.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package dummy 5 6 import ( 7 "sync" 8 "time" 9 10 "github.com/juju/clock" 11 "github.com/juju/errors" 12 13 "github.com/juju/juju/core/lease" 14 "github.com/juju/juju/core/raftlease" 15 ) 16 17 // leaseStore implements lease.Store as simply as possible for use in 18 // the dummy provider. Heavily cribbed from raftlease.FSM. 19 type leaseStore struct { 20 mu sync.Mutex 21 clock clock.Clock 22 entries map[lease.Key]*entry 23 trapdoor raftlease.TrapdoorFunc 24 target raftlease.NotifyTarget 25 } 26 27 // entry holds the details of a lease. 28 type entry struct { 29 // holder identifies the current holder of the lease. 30 holder string 31 32 // start is the global time at which the lease started. 33 start time.Time 34 35 // duration is the duration for which the lease is valid, 36 // from the start time. 37 duration time.Duration 38 } 39 40 func newLeaseStore(clock clock.Clock, target raftlease.NotifyTarget, trapdoor raftlease.TrapdoorFunc) *leaseStore { 41 return &leaseStore{ 42 clock: clock, 43 entries: make(map[lease.Key]*entry), 44 target: target, 45 trapdoor: trapdoor, 46 } 47 } 48 49 // Autoexpire is part of lease.Store. 50 func (*leaseStore) Autoexpire() bool { return false } 51 52 // ClaimLease is part of lease.Store. 53 func (s *leaseStore) ClaimLease(key lease.Key, req lease.Request) error { 54 s.mu.Lock() 55 defer s.mu.Unlock() 56 if _, found := s.entries[key]; found { 57 return lease.ErrInvalid 58 } 59 s.entries[key] = &entry{ 60 holder: req.Holder, 61 start: s.clock.Now(), 62 duration: req.Duration, 63 } 64 s.target.Claimed(key, req.Holder) 65 return nil 66 } 67 68 // ExtendLease is part of lease.Store. 69 func (s *leaseStore) ExtendLease(key lease.Key, req lease.Request) error { 70 s.mu.Lock() 71 defer s.mu.Unlock() 72 entry, found := s.entries[key] 73 if !found { 74 return lease.ErrInvalid 75 } 76 if entry.holder != req.Holder { 77 return lease.ErrInvalid 78 } 79 now := s.clock.Now() 80 expiry := now.Add(req.Duration) 81 if !expiry.After(entry.start.Add(entry.duration)) { 82 // No extension needed - the lease already expires after the 83 // new time. 84 return nil 85 } 86 // entry is a pointer back into the f.entries map, so this update 87 // isn't lost. 88 entry.start = now 89 entry.duration = req.Duration 90 return nil 91 } 92 93 // Expire is part of lease.Store. 94 func (s *leaseStore) ExpireLease(key lease.Key) error { 95 s.mu.Lock() 96 defer s.mu.Unlock() 97 entry, found := s.entries[key] 98 if !found { 99 return lease.ErrInvalid 100 } 101 expiry := entry.start.Add(entry.duration) 102 if !s.clock.Now().After(expiry) { 103 return lease.ErrInvalid 104 } 105 delete(s.entries, key) 106 s.target.Expired(key) 107 return nil 108 } 109 110 // Leases is part of lease.Store. 111 func (s *leaseStore) Leases(keys ...lease.Key) map[lease.Key]lease.Info { 112 s.mu.Lock() 113 defer s.mu.Unlock() 114 115 filter := make(map[lease.Key]bool) 116 filtering := len(keys) > 0 117 if filtering { 118 for _, key := range keys { 119 filter[key] = true 120 } 121 } 122 123 results := make(map[lease.Key]lease.Info) 124 for key, entry := range s.entries { 125 if filtering && !filter[key] { 126 continue 127 } 128 129 results[key] = lease.Info{ 130 Holder: entry.holder, 131 Expiry: entry.start.Add(entry.duration), 132 Trapdoor: s.trapdoor(key, entry.holder), 133 } 134 } 135 return results 136 } 137 138 // Refresh is part of lease.Store. 139 func (s *leaseStore) Refresh() error { 140 return nil 141 } 142 143 // PinLease is part of lease.Store. 144 func (s *leaseStore) PinLease(key lease.Key, entity string) error { 145 return errors.NotImplementedf("lease pinning") 146 } 147 148 // UnpinLease is part of lease.Store. 149 func (s *leaseStore) UnpinLease(key lease.Key, entity string) error { 150 return errors.NotImplementedf("lease unpinning") 151 } 152 153 // Pinned is part of the Store interface. 154 func (s *leaseStore) Pinned() map[lease.Key][]string { 155 return nil 156 }