Move expiration code into its own and add ticker select case

master
Harshavardhana 10 years ago
parent 8a65b90783
commit 01b474fca3
  1. 8
      pkg/storage/drivers/memory/memory.go
  2. 59
      pkg/storage/drivers/memory/memory_intelligent.go

@ -66,7 +66,7 @@ func Start(maxSize uint64, expiration time.Duration) (chan<- string, <-chan erro
memory.objects = NewIntelligent(maxSize, expiration)
memory.lock = new(sync.RWMutex)
memory.objects.OnEvicted = memory.evictObject
memory.objects.OnExpired = memory.expiredObject
// set up memory expiration
memory.objects.ExpireObjects(time.Second * 5)
@ -495,10 +495,10 @@ func (memory *memoryDriver) GetObjectMetadata(bucket, key, prefix string) (drive
return drivers.ObjectMetadata{}, iodine.New(drivers.ObjectNotFound{Bucket: bucket, Object: key}, nil)
}
func (memory *memoryDriver) evictObject(a ...interface{}) {
func (memory *memoryDriver) expiredObject(a ...interface{}) {
cacheStats := memory.objects.Stats()
log.Printf("CurrentSize: %d, CurrentItems: %d, TotalEvictions: %d",
cacheStats.Bytes, cacheStats.Items, cacheStats.Evictions)
log.Printf("CurrentSize: %d, CurrentItems: %d, TotalExpirations: %d",
cacheStats.Bytes, cacheStats.Items, cacheStats.Expired)
key := a[0].(string)
// loop through all buckets
for bucket, storedBucket := range memory.storedBuckets {

@ -39,8 +39,8 @@ type Intelligent struct {
// expiration is a duration for a cache key to expire
expiration time.Duration
// gcInterval is a duration for garbage collection
gcInterval time.Duration
// stopExpireTimer channel to quit the timer thread
stopExpireTimer chan struct{}
// maxSize is a total size for overall cache
maxSize uint64
@ -48,18 +48,18 @@ type Intelligent struct {
// currentSize is a current size in memory
currentSize uint64
// OnEvicted - callback function for eviction
OnEvicted func(a ...interface{})
// OnExpired - callback function for eviction
OnExpired func(a ...interface{})
// totalEvicted counter to keep track of total evictions
totalEvicted uint64
// totalExpired counter to keep track of total expirations
totalExpired uint64
}
// Stats current cache statistics
type Stats struct {
Bytes uint64
Items uint64
Evictions uint64
Bytes uint64
Items uint64
Expired uint64
}
// NewIntelligent creates an inmemory cache
@ -78,24 +78,26 @@ func NewIntelligent(maxSize uint64, expiration time.Duration) *Intelligent {
// Stats get current cache statistics
func (r *Intelligent) Stats() Stats {
return Stats{
Bytes: r.currentSize,
Items: uint64(len(r.items)),
Evictions: r.totalEvicted,
Bytes: r.currentSize,
Items: uint64(len(r.items)),
Expired: r.totalExpired,
}
}
// ExpireObjects expire objects in go routine
func (r *Intelligent) ExpireObjects(gcInterval time.Duration) {
r.gcInterval = gcInterval
r.stopExpireTimer = make(chan struct{})
ticker := time.NewTicker(gcInterval)
go func() {
for range time.Tick(gcInterval) {
r.Lock()
for key := range r.items {
if !r.isValid(key) {
r.Delete(key)
}
for {
select {
case <-ticker.C:
r.Expire()
case <-r.stopExpireTimer:
ticker.Stop()
return
}
r.Unlock()
}
}()
}
@ -132,15 +134,26 @@ func (r *Intelligent) Set(key string, value interface{}) {
return
}
// Expire expires keys which have expired
func (r *Intelligent) Expire() {
r.Lock()
defer r.Unlock()
for key := range r.items {
if !r.isValid(key) {
r.Delete(key)
}
}
}
// Delete deletes a given key if exists
func (r *Intelligent) Delete(key string) {
if _, ok := r.items[key]; ok {
r.currentSize -= uint64(len(r.items[key].([]byte)))
delete(r.items, key)
delete(r.updatedAt, key)
r.totalEvicted++
if r.OnEvicted != nil {
r.OnEvicted(key)
r.totalExpired++
if r.OnExpired != nil {
r.OnExpired(key)
}
}
}

Loading…
Cancel
Save