You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

95 lines
1.7 KiB

package lease
import (
"errors"
"sync"
"github.com/tblyler/sheepmq/shepard"
)
var (
// ErrLeased denotes the item is already leased
ErrLeased = errors.New("Item is already leased")
// ErrNoLeaser denotes no leaser was provided to add a lease
ErrNoLeaser = errors.New("No leaser provided")
)
// Manager contains many leases and their validity
type Manager struct {
leases map[uint64]Leaser
locker sync.RWMutex
}
// NewManager creates a new Manager instance
func NewManager() *Manager {
return &Manager{
leases: make(map[uint64]Leaser),
}
}
// AddLease to the manager for the given item
func (m *Manager) AddLease(id uint64, info *shepard.GetInfo) error {
if m.CheckLease(id) {
return ErrLeased
}
var leaser Leaser
if info.TimeoutLease != nil {
leaser = NewTimeout(info.TimeoutLease.Ttl)
} else if info.PidLease != nil {
leaser = NewPID(int(info.PidLease.Pid))
} else if info.HeartLease != nil {
leaser = NewHeart(info.HeartLease.Ttl)
} else {
return ErrNoLeaser
}
m.locker.Lock()
m.leases[id] = leaser
m.locker.Unlock()
return nil
}
// CheckLease for validity
func (m *Manager) CheckLease(id uint64) bool {
m.locker.RLock()
lease, exists := m.leases[id]
if !exists {
m.locker.RUnlock()
return false
}
ret := lease.Valid()
m.locker.RUnlock()
if !ret {
// delete the lease since it is no longer valid
m.locker.Lock()
delete(m.leases, id)
m.locker.Unlock()
}
return ret
}
// PruneLeases that fail their checks
func (m *Manager) PruneLeases() {
deleteKeys := []uint64{}
m.locker.RLock()
for key, lease := range m.leases {
if !lease.Check() {
deleteKeys = append(deleteKeys, key)
}
}
m.locker.RUnlock()
m.locker.Lock()
for _, key := range deleteKeys {
delete(m.leases, key)
}
m.locker.Unlock()
}