Skip to content
/ etcd Public
forked from etcd-io/etcd

Commit

Permalink
Merge pull request etcd-io#3853 from xiang90/lease_new
Browse files Browse the repository at this point in the history
lease: delete items when the lease is revoked.
  • Loading branch information
xiang90 committed Nov 12, 2015
2 parents 2990249 + bf3bc0e commit de02254
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 7 deletions.
24 changes: 21 additions & 3 deletions lease/lessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ var (
minLeaseTerm = 5 * time.Second
)

// DeleteableRange defines an interface with DeleteRange method.
// We define this interface only for lessor to limit the number
// of methods of storage.KV to what lessor actually needs.
//
// Having a minimum interface makes testing easy.
type DeleteableRange interface {
DeleteRange(key, end []byte) (int64, int64)
}

// a lessor is the owner of leases. It can grant, revoke,
// renew and modify leases for lessee.
// TODO: persist lease on to stable backend for failure recovery.
Expand All @@ -40,12 +49,18 @@ type lessor struct {
// FindExpired and Renew should be the most frequent operations.
leaseMap map[uint64]*lease

// A DeleteableRange the lessor operates on.
// When a lease expires, the lessor will delete the
// leased range (or key) from the DeleteableRange.
dr DeleteableRange

idgen *idutil.Generator
}

func NewLessor(lessorID uint8) *lessor {
func NewLessor(lessorID uint8, dr DeleteableRange) *lessor {
return &lessor{
leaseMap: make(map[uint64]*lease),
dr: dr,
idgen: idutil.NewGenerator(lessorID, time.Now()),
}
}
Expand All @@ -62,7 +77,7 @@ func (le *lessor) Grant(expiry time.Time) *lease {
le.mu.Lock()
defer le.mu.Unlock()

l := &lease{id: id, expiry: expiry}
l := &lease{id: id, expiry: expiry, itemSet: make(map[leaseItem]struct{})}
if _, ok := le.leaseMap[id]; ok {
panic("lease: unexpected duplicate ID!")
}
Expand All @@ -85,7 +100,10 @@ func (le *lessor) Revoke(id uint64) error {

delete(le.leaseMap, l.id)

// TODO: remove attached items
for item := range l.itemSet {
le.dr.DeleteRange([]byte(item.key), []byte(item.endRange))
}

return nil
}

Expand Down
35 changes: 31 additions & 4 deletions lease/lessor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
// The granted lease should have a unique ID with a term
// that is greater than minLeaseTerm.
func TestLessorGrant(t *testing.T) {
le := NewLessor(1)
le := NewLessor(1, &fakeDeleteable{})

l := le.Grant(time.Now().Add(time.Second))
gl := le.get(l.id)
Expand All @@ -43,27 +43,45 @@ func TestLessorGrant(t *testing.T) {
}

// TestLessorRevoke ensures Lessor can revoke a lease.
// The items in the revoked lease should be removed from
// the DeleteableKV.
// The revoked lease cannot be got from Lessor again.
func TestLessorRevoke(t *testing.T) {
le := NewLessor(1)
fd := &fakeDeleteable{}
le := NewLessor(1, fd)

// grant a lease with long term (100 seconds) to
// avoid early termination during the test.
l := le.Grant(time.Now().Add(100 * time.Second))

err := le.Revoke(l.id)
items := []leaseItem{
{"foo", ""},
{"bar", "zar"},
}

err := le.Attach(l.id, items)
if err != nil {
t.Fatalf("failed to attach items to the lease: %v", err)
}

err = le.Revoke(l.id)
if err != nil {
t.Fatal("failed to revoke lease:", err)
}

if le.get(l.id) != nil {
t.Errorf("got revoked lease %x", l.id)
}

wdeleted := []string{"foo_", "bar_zar"}
if !reflect.DeepEqual(fd.deleted, wdeleted) {
t.Errorf("deleted= %v, want %v", fd.deleted, wdeleted)
}
}

// TestLessorRenew ensures Lessor can renew an existing lease.
func TestLessorRenew(t *testing.T) {
le := NewLessor(1)
le := NewLessor(1, &fakeDeleteable{})
l := le.Grant(time.Now().Add(5 * time.Second))

le.Renew(l.id, time.Now().Add(100*time.Second))
Expand All @@ -73,3 +91,12 @@ func TestLessorRenew(t *testing.T) {
t.Errorf("failed to renew the lease for 100 seconds")
}
}

type fakeDeleteable struct {
deleted []string
}

func (fd *fakeDeleteable) DeleteRange(key, end []byte) (int64, int64) {
fd.deleted = append(fd.deleted, string(key)+"_"+string(end))
return 0, 0
}

0 comments on commit de02254

Please sign in to comment.