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