Merge pull request #3853 from xiang90/lease_new

lease: delete items when the lease is revoked.
This commit is contained in:
Xiang Li 2015-11-11 22:13:37 -08:00
commit de02254659
2 changed files with 52 additions and 7 deletions

View File

@ -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.
@ -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()),
}
}
@ -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!")
}
@ -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
}

View File

@ -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)
@ -43,15 +43,28 @@ 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)
}
@ -59,11 +72,16 @@ func TestLessorRevoke(t *testing.T) {
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))
@ -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
}