123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- package datautil
- import (
- "bytes"
- "fmt"
- "math"
- "sort"
- "sync"
- "time"
- )
- type MapCache struct {
- data map[string]interface{}
- ts map[string]int64
- size uint64
- maxsize uint64
- maxage int64
- mutex *sync.RWMutex
- }
- func NewMapCache(maxsize uint64, maxage int64) *MapCache {
- return &MapCache{make(map[string]interface{}), make(map[string]int64),
- 0, maxsize, maxage, &sync.RWMutex{}}
- }
- func (mc *MapCache) Clear() {
-
- mc.mutex.Lock()
- defer mc.mutex.Unlock()
- mc.data = make(map[string]interface{})
- mc.ts = make(map[string]int64)
- mc.size = 0
- }
- func (mc *MapCache) Size() uint64 {
- return mc.size
- }
- func (mc *MapCache) Put(k string, v interface{}) {
-
- oldest := mc.maintainCache()
-
- mc.mutex.Lock()
- defer mc.mutex.Unlock()
-
- if _, exists := mc.data[k]; !exists {
-
- if mc.maxsize != 0 && mc.size == mc.maxsize {
- delete(mc.data, oldest)
- delete(mc.ts, oldest)
- } else {
- mc.size++
- }
- }
-
- mc.data[k] = v
- mc.ts[k] = time.Now().Unix()
- }
- func (mc *MapCache) Remove(k string) bool {
-
- mc.maintainCache()
-
- mc.mutex.Lock()
- defer mc.mutex.Unlock()
-
- _, exists := mc.data[k]
- if exists {
-
- delete(mc.data, k)
- delete(mc.ts, k)
- mc.size--
- }
- return exists
- }
- func (mc *MapCache) Get(k string) (interface{}, bool) {
-
- mc.maintainCache()
-
- mc.mutex.RLock()
- defer mc.mutex.RUnlock()
-
- v, ok := mc.data[k]
- return v, ok
- }
- func (mc *MapCache) GetAll() map[string]interface{} {
-
- mc.maintainCache()
-
- mc.mutex.RLock()
- defer mc.mutex.RUnlock()
-
- cp := make(map[string]interface{})
- for k, v := range mc.data {
- cp[k] = v
- }
- return cp
- }
- func (mc *MapCache) String() string {
- mc.mutex.RLock()
- defer mc.mutex.RUnlock()
-
- var keys []string
- for k := range mc.data {
- keys = append(keys, k)
- }
- sort.Sort(sort.StringSlice(keys))
- buf := &bytes.Buffer{}
- for _, k := range keys {
- buf.WriteString(fmt.Sprint(k, ":", mc.data[k], "\n"))
- }
- return buf.String()
- }
- func (mc *MapCache) maintainCache() string {
- mc.mutex.RLock()
- oldestTS := int64(math.MaxInt64)
- oldestK := ""
- now := time.Now().Unix()
- for k, v := range mc.ts {
-
- if mc.maxage != 0 && now-v > mc.maxage {
-
- mc.mutex.RUnlock()
- mc.mutex.Lock()
- delete(mc.data, k)
- delete(mc.ts, k)
- mc.size--
- mc.mutex.Unlock()
- mc.mutex.RLock()
- }
-
- if v < oldestTS {
- oldestTS = v
- oldestK = k
- }
- }
- mc.mutex.RUnlock()
- return oldestK
- }
|