// Copyright 2018 The etcd Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package lease import "container/heap" // LeaseWithTime contains lease object with a time. // For the lessor's lease heap, time identifies the lease expiration time. // For the lessor's lease checkpoint heap, the time identifies the next lease checkpoint time. type LeaseWithTime struct { id LeaseID // Unix nanos timestamp. time int64 index int } type LeaseQueue []*LeaseWithTime func (pq LeaseQueue) Len() int { return len(pq) } func (pq LeaseQueue) Less(i, j int) bool { return pq[i].time < pq[j].time } func (pq LeaseQueue) Swap(i, j int) { pq[i], pq[j] = pq[j], pq[i] pq[i].index = i pq[j].index = j } func (pq *LeaseQueue) Push(x interface{}) { n := len(*pq) item := x.(*LeaseWithTime) item.index = n *pq = append(*pq, item) } func (pq *LeaseQueue) Pop() interface{} { old := *pq n := len(old) item := old[n-1] item.index = -1 // for safety *pq = old[0 : n-1] return item } // LeaseExpiredNotifier is a queue used to notify lessor to revoke expired lease. // Only save one item for a lease, `Register` will update time of the corresponding lease. type LeaseExpiredNotifier struct { m map[LeaseID]*LeaseWithTime queue LeaseQueue } func newLeaseExpiredNotifier() *LeaseExpiredNotifier { return &LeaseExpiredNotifier{ m: make(map[LeaseID]*LeaseWithTime), queue: make(LeaseQueue, 0), } } func (mq *LeaseExpiredNotifier) Init() { heap.Init(&mq.queue) mq.m = make(map[LeaseID]*LeaseWithTime) for _, item := range mq.queue { mq.m[item.id] = item } } func (mq *LeaseExpiredNotifier) RegisterOrUpdate(item *LeaseWithTime) { if old, ok := mq.m[item.id]; ok { old.time = item.time heap.Fix(&mq.queue, old.index) } else { heap.Push(&mq.queue, item) mq.m[item.id] = item } } func (mq *LeaseExpiredNotifier) Unregister() *LeaseWithTime { item := heap.Pop(&mq.queue).(*LeaseWithTime) delete(mq.m, item.id) return item } func (mq *LeaseExpiredNotifier) Poll() *LeaseWithTime { if mq.Len() == 0 { return nil } return mq.queue[0] } func (mq *LeaseExpiredNotifier) Len() int { return len(mq.m) }