X-Git-Url: https://gerrit.akraino.org/r/gitweb?a=blobdiff_plain;f=src%2Ffoundation%2Fapi%2Frevel%2Fcache%2Fmemcached.go;fp=src%2Ffoundation%2Fapi%2Frevel%2Fcache%2Fmemcached.go;h=fbc7ece35cf1eafb74312983de2c1964e0f45980;hb=1d1ee6961c93781e1187d8c7faa868da6b2f01f4;hp=0000000000000000000000000000000000000000;hpb=56dd5e0f2164b37b40ac1daa188ccc618b4cbd19;p=iec.git diff --git a/src/foundation/api/revel/cache/memcached.go b/src/foundation/api/revel/cache/memcached.go new file mode 100644 index 0000000..fbc7ece --- /dev/null +++ b/src/foundation/api/revel/cache/memcached.go @@ -0,0 +1,118 @@ +// Copyright (c) 2012-2016 The Revel Framework Authors, All rights reserved. +// Revel Framework source code and usage is governed by a MIT style +// license that can be found in the LICENSE file. + +package cache + +import ( + "errors" + "time" + + "github.com/bradfitz/gomemcache/memcache" + "github.com/revel/revel/logger" +) + +// MemcachedCache wraps the Memcached client to meet the Cache interface. +type MemcachedCache struct { + *memcache.Client + defaultExpiration time.Duration +} + +func NewMemcachedCache(hostList []string, defaultExpiration time.Duration) MemcachedCache { + return MemcachedCache{memcache.New(hostList...), defaultExpiration} +} + +func (c MemcachedCache) Set(key string, value interface{}, expires time.Duration) error { + return c.invoke((*memcache.Client).Set, key, value, expires) +} + +func (c MemcachedCache) Add(key string, value interface{}, expires time.Duration) error { + return c.invoke((*memcache.Client).Add, key, value, expires) +} + +func (c MemcachedCache) Replace(key string, value interface{}, expires time.Duration) error { + return c.invoke((*memcache.Client).Replace, key, value, expires) +} + +func (c MemcachedCache) Get(key string, ptrValue interface{}) error { + item, err := c.Client.Get(key) + if err != nil { + return convertMemcacheError(err) + } + return Deserialize(item.Value, ptrValue) +} + +func (c MemcachedCache) GetMulti(keys ...string) (Getter, error) { + items, err := c.Client.GetMulti(keys) + if err != nil { + return nil, convertMemcacheError(err) + } + return ItemMapGetter(items), nil +} + +func (c MemcachedCache) Delete(key string) error { + return convertMemcacheError(c.Client.Delete(key)) +} + +func (c MemcachedCache) Increment(key string, delta uint64) (newValue uint64, err error) { + newValue, err = c.Client.Increment(key, delta) + return newValue, convertMemcacheError(err) +} + +func (c MemcachedCache) Decrement(key string, delta uint64) (newValue uint64, err error) { + newValue, err = c.Client.Decrement(key, delta) + return newValue, convertMemcacheError(err) +} + +func (c MemcachedCache) Flush() error { + err := errors.New("Flush: can not flush memcached") + cacheLog.Error(err.Error()) + return err +} + +func (c MemcachedCache) invoke(f func(*memcache.Client, *memcache.Item) error, + key string, value interface{}, expires time.Duration) error { + + switch expires { + case DefaultExpiryTime: + expires = c.defaultExpiration + case ForEverNeverExpiry: + expires = time.Duration(0) + } + + b, err := Serialize(value) + if err != nil { + return err + } + return convertMemcacheError(f(c.Client, &memcache.Item{ + Key: key, + Value: b, + Expiration: int32(expires / time.Second), + })) +} + +// ItemMapGetter implements a Getter on top of the returned item map. +type ItemMapGetter map[string]*memcache.Item + +func (g ItemMapGetter) Get(key string, ptrValue interface{}) error { + item, ok := g[key] + if !ok { + return ErrCacheMiss + } + + return Deserialize(item.Value, ptrValue) +} + +func convertMemcacheError(err error) error { + switch err { + case nil: + return nil + case memcache.ErrCacheMiss: + return ErrCacheMiss + case memcache.ErrNotStored: + return ErrNotStored + } + + cacheLog.Error("convertMemcacheError:", "error", err, "trace", logger.NewCallStack()) + return err +}