diff --git a/etcdserver/server.go b/etcdserver/server.go index 16c6b6ed0..4da708f6d 100644 --- a/etcdserver/server.go +++ b/etcdserver/server.go @@ -18,6 +18,7 @@ import ( "encoding/json" "expvar" "fmt" + "math" "math/rand" "net/http" "os" @@ -393,7 +394,8 @@ func NewServer(cfg *ServerConfig) (srv *EtcdServer, err error) { srv.applyV2 = &applierV2store{store: srv.store, cluster: srv.cluster} srv.be = be - srv.lessor = lease.NewLessor(srv.be) + minTTL := time.Duration((3*cfg.ElectionTicks)/2) * time.Duration(cfg.TickMs) * time.Millisecond + srv.lessor = lease.NewLessor(srv.be, int64(math.Ceil(minTTL.Seconds()))) srv.kv = mvcc.New(srv.be, srv.lessor, &srv.consistIndex) if beExist { kvindex := srv.kv.ConsistentIndex() diff --git a/lease/lessor.go b/lease/lessor.go index 13c3f1b12..45c8c2520 100644 --- a/lease/lessor.go +++ b/lease/lessor.go @@ -31,8 +31,6 @@ const ( ) var ( - minLeaseTTL = int64(5) - leaseBucketName = []byte("lease") // do not use maxInt64 since it can overflow time which will add // the offset of unix time (1970yr to seconds). @@ -138,6 +136,10 @@ type lessor struct { // The leased items can be recovered by iterating all the keys in kv. b backend.Backend + // minLeaseTTL is the minimum lease TTL that can be granted for a lease. Any + // requests for shorter TTLs are extended to the minimum TTL. + minLeaseTTL int64 + expiredC chan []*Lease // stopC is a channel whose closure indicates that the lessor should be stopped. stopC chan struct{} @@ -145,14 +147,15 @@ type lessor struct { doneC chan struct{} } -func NewLessor(b backend.Backend) Lessor { - return newLessor(b) +func NewLessor(b backend.Backend, minLeaseTTL int64) Lessor { + return newLessor(b, minLeaseTTL) } -func newLessor(b backend.Backend) *lessor { +func newLessor(b backend.Backend, minLeaseTTL int64) *lessor { l := &lessor{ - leaseMap: make(map[LeaseID]*Lease), - b: b, + leaseMap: make(map[LeaseID]*Lease), + b: b, + minLeaseTTL: minLeaseTTL, // expiredC is a small buffered chan to avoid unnecessary blocking. expiredC: make(chan []*Lease, 16), stopC: make(chan struct{}), @@ -188,6 +191,10 @@ func (le *lessor) Grant(id LeaseID, ttl int64) (*Lease, error) { return nil, ErrLeaseExists } + if l.TTL < le.minLeaseTTL { + l.TTL = le.minLeaseTTL + } + if le.primary { l.refresh(0) } else { @@ -406,6 +413,9 @@ func (le *lessor) initAndRecover() { panic("failed to unmarshal lease proto item") } ID := LeaseID(lpb.ID) + if lpb.TTL < le.minLeaseTTL { + lpb.TTL = le.minLeaseTTL + } le.leaseMap[ID] = &Lease{ ID: ID, TTL: lpb.TTL, @@ -451,22 +461,13 @@ func (l Lease) removeFrom(b backend.Backend) { b.BatchTx().Unlock() } -// refresh refreshes the expiry of the lease. It extends the expiry at least -// minLeaseTTL second. +// refresh refreshes the expiry of the lease. func (l *Lease) refresh(extend time.Duration) { - if l.TTL < minLeaseTTL { - l.TTL = minLeaseTTL - } l.expiry = time.Now().Add(extend + time.Second*time.Duration(l.TTL)) } // forever sets the expiry of lease to be forever. -func (l *Lease) forever() { - if l.TTL < minLeaseTTL { - l.TTL = minLeaseTTL - } - l.expiry = forever -} +func (l *Lease) forever() { l.expiry = forever } type LeaseItem struct { Key string diff --git a/lease/lessor_test.go b/lease/lessor_test.go index a9b7add61..946e8c03b 100644 --- a/lease/lessor_test.go +++ b/lease/lessor_test.go @@ -26,6 +26,8 @@ import ( "github.com/coreos/etcd/mvcc/backend" ) +const minLeaseTTL = int64(5) + // TestLessorGrant ensures Lessor can grant wanted lease. // The granted lease should have a unique ID with a term // that is greater than minLeaseTTL. @@ -34,7 +36,7 @@ func TestLessorGrant(t *testing.T) { defer os.RemoveAll(dir) defer be.Close() - le := newLessor(be) + le := newLessor(be, minLeaseTTL) le.Promote(0) l, err := le.Grant(1, 1) @@ -82,7 +84,7 @@ func TestLessorRevoke(t *testing.T) { fd := &fakeDeleter{} - le := newLessor(be) + le := newLessor(be, minLeaseTTL) le.SetRangeDeleter(fd) // grant a lease with long term (100 seconds) to @@ -129,10 +131,10 @@ func TestLessorRenew(t *testing.T) { defer be.Close() defer os.RemoveAll(dir) - le := newLessor(be) + le := newLessor(be, minLeaseTTL) le.Promote(0) - l, err := le.Grant(1, 5) + l, err := le.Grant(1, minLeaseTTL) if err != nil { t.Fatalf("failed to grant lease (%v)", err) } @@ -160,7 +162,7 @@ func TestLessorDetach(t *testing.T) { fd := &fakeDeleter{} - le := newLessor(be) + le := newLessor(be, minLeaseTTL) le.SetRangeDeleter(fd) // grant a lease with long term (100 seconds) to @@ -199,7 +201,7 @@ func TestLessorRecover(t *testing.T) { defer os.RemoveAll(dir) defer be.Close() - le := newLessor(be) + le := newLessor(be, minLeaseTTL) l1, err1 := le.Grant(1, 10) l2, err2 := le.Grant(2, 20) if err1 != nil || err2 != nil { @@ -207,7 +209,7 @@ func TestLessorRecover(t *testing.T) { } // Create a new lessor with the same backend - nle := newLessor(be) + nle := newLessor(be, minLeaseTTL) nl1 := nle.get(l1.ID) if nl1 == nil || nl1.TTL != l1.TTL { t.Errorf("nl1 = %v, want nl1.TTL= %d", nl1.TTL, l1.TTL)