2013-10-19 02:56:28 +02:00
|
|
|
package ccache
|
|
|
|
|
|
|
|
import (
|
2014-02-28 13:10:42 +01:00
|
|
|
"container/list"
|
|
|
|
"sync/atomic"
|
2014-10-25 12:15:47 +02:00
|
|
|
"time"
|
2013-10-19 02:56:28 +02:00
|
|
|
)
|
|
|
|
|
2014-11-21 08:39:25 +01:00
|
|
|
type Sized interface {
|
|
|
|
Size() int64
|
|
|
|
}
|
|
|
|
|
2014-02-28 13:10:42 +01:00
|
|
|
type TrackedItem interface {
|
|
|
|
Value() interface{}
|
|
|
|
Release()
|
2014-10-25 12:15:47 +02:00
|
|
|
Expired() bool
|
|
|
|
TTL() time.Duration
|
|
|
|
Expires() time.Time
|
2014-10-27 02:27:26 +01:00
|
|
|
Extend(duration time.Duration)
|
2014-02-28 13:10:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
type nilItem struct{}
|
|
|
|
|
|
|
|
func (n *nilItem) Value() interface{} { return nil }
|
|
|
|
func (n *nilItem) Release() {}
|
|
|
|
|
2014-10-25 12:15:47 +02:00
|
|
|
func (i *nilItem) Expired() bool {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *nilItem) TTL() time.Duration {
|
|
|
|
return time.Minute
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *nilItem) Expires() time.Time {
|
|
|
|
return time.Time{}
|
|
|
|
}
|
|
|
|
|
2014-10-27 02:27:26 +01:00
|
|
|
func (i *nilItem) Extend(duration time.Duration) {
|
|
|
|
}
|
|
|
|
|
2014-02-28 13:10:42 +01:00
|
|
|
var NilTracked = new(nilItem)
|
|
|
|
|
2013-10-19 02:56:28 +02:00
|
|
|
type Item struct {
|
2014-10-25 07:21:10 +02:00
|
|
|
key string
|
|
|
|
group string
|
2014-02-28 13:10:42 +01:00
|
|
|
promotions int32
|
|
|
|
refCount int32
|
2014-10-25 03:35:52 +02:00
|
|
|
expires int64
|
2014-11-21 08:39:25 +01:00
|
|
|
size int64
|
2014-02-28 13:10:42 +01:00
|
|
|
value interface{}
|
|
|
|
element *list.Element
|
2013-10-19 02:56:28 +02:00
|
|
|
}
|
|
|
|
|
2020-08-13 19:43:38 +02:00
|
|
|
func newItem(key string, value interface{}, expires int64, track bool) *Item {
|
2014-11-21 08:39:25 +01:00
|
|
|
size := int64(1)
|
|
|
|
if sized, ok := value.(Sized); ok {
|
|
|
|
size = sized.Size()
|
|
|
|
}
|
2020-08-13 19:43:38 +02:00
|
|
|
item := &Item{
|
2014-02-28 13:10:42 +01:00
|
|
|
key: key,
|
|
|
|
value: value,
|
2014-12-28 05:11:32 +01:00
|
|
|
promotions: 0,
|
2014-11-21 08:39:25 +01:00
|
|
|
size: size,
|
2014-10-25 04:44:22 +02:00
|
|
|
expires: expires,
|
2014-02-28 13:10:42 +01:00
|
|
|
}
|
2020-08-13 19:43:38 +02:00
|
|
|
if track {
|
|
|
|
item.refCount = 1
|
|
|
|
}
|
|
|
|
return item
|
2013-10-21 13:37:35 +02:00
|
|
|
}
|
|
|
|
|
2013-10-30 13:18:51 +01:00
|
|
|
func (i *Item) shouldPromote(getsPerPromote int32) bool {
|
2014-12-28 05:11:32 +01:00
|
|
|
i.promotions += 1
|
|
|
|
return i.promotions == getsPerPromote
|
2014-02-28 13:10:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (i *Item) Value() interface{} {
|
|
|
|
return i.value
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *Item) track() {
|
|
|
|
atomic.AddInt32(&i.refCount, 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (i *Item) Release() {
|
|
|
|
atomic.AddInt32(&i.refCount, -1)
|
2013-10-19 02:56:28 +02:00
|
|
|
}
|
2014-10-25 12:15:47 +02:00
|
|
|
|
|
|
|
func (i *Item) Expired() bool {
|
2014-10-27 02:27:26 +01:00
|
|
|
expires := atomic.LoadInt64(&i.expires)
|
2016-07-08 00:32:49 +02:00
|
|
|
return expires < time.Now().UnixNano()
|
2014-10-25 12:15:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (i *Item) TTL() time.Duration {
|
2014-10-27 02:27:26 +01:00
|
|
|
expires := atomic.LoadInt64(&i.expires)
|
2016-07-08 00:32:49 +02:00
|
|
|
return time.Nanosecond * time.Duration(expires-time.Now().UnixNano())
|
2014-10-25 12:15:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (i *Item) Expires() time.Time {
|
2014-10-27 02:27:26 +01:00
|
|
|
expires := atomic.LoadInt64(&i.expires)
|
2016-07-08 00:32:49 +02:00
|
|
|
return time.Unix(0, expires)
|
2014-10-27 02:27:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (i *Item) Extend(duration time.Duration) {
|
2016-07-08 00:32:49 +02:00
|
|
|
atomic.StoreInt64(&i.expires, time.Now().Add(duration).UnixNano())
|
2014-10-25 12:15:47 +02:00
|
|
|
}
|