Browse Source

lease: delete items when the lease is revoked.

Add minimum KV interface and implmement the deleting mechanism for
revoking lease.
Xiang Li 10 years ago
parent
commit
bf3bc0ed6b
2 changed files with 52 additions and 7 deletions
  1. 21 3
      lease/lessor.go
  2. 31 4
      lease/lessor_test.go

+ 21 - 3
lease/lessor.go

@@ -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
 }
 

+ 31 - 4
lease/lessor_test.go

@@ -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
+}