123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- package ssdb
- import (
- "encoding/json"
- "errors"
- "strconv"
- "strings"
- "time"
- "github.com/ssdb/gossdb/ssdb"
- "github.com/astaxie/beego/cache"
- )
- // Cache SSDB adapter
- type Cache struct {
- conn *ssdb.Client
- conninfo []string
- }
- //NewSsdbCache create new ssdb adapter.
- func NewSsdbCache() cache.Cache {
- return &Cache{}
- }
- // Get get value from memcache.
- func (rc *Cache) Get(key string) interface{} {
- if rc.conn == nil {
- if err := rc.connectInit(); err != nil {
- return nil
- }
- }
- value, err := rc.conn.Get(key)
- if err == nil {
- return value
- }
- return nil
- }
- // GetMulti get value from memcache.
- func (rc *Cache) GetMulti(keys []string) []interface{} {
- size := len(keys)
- var values []interface{}
- if rc.conn == nil {
- if err := rc.connectInit(); err != nil {
- for i := 0; i < size; i++ {
- values = append(values, err)
- }
- return values
- }
- }
- res, err := rc.conn.Do("multi_get", keys)
- resSize := len(res)
- if err == nil {
- for i := 1; i < resSize; i += 2 {
- values = append(values, string(res[i+1]))
- }
- return values
- }
- for i := 0; i < size; i++ {
- values = append(values, err)
- }
- return values
- }
- // DelMulti get value from memcache.
- func (rc *Cache) DelMulti(keys []string) error {
- if rc.conn == nil {
- if err := rc.connectInit(); err != nil {
- return err
- }
- }
- _, err := rc.conn.Do("multi_del", keys)
- if err != nil {
- return err
- }
- return nil
- }
- // Put put value to memcache. only support string.
- func (rc *Cache) Put(key string, value interface{}, timeout time.Duration) error {
- if rc.conn == nil {
- if err := rc.connectInit(); err != nil {
- return err
- }
- }
- v, ok := value.(string)
- if !ok {
- return errors.New("value must string")
- }
- var resp []string
- var err error
- ttl := int(timeout / time.Second)
- if ttl < 0 {
- resp, err = rc.conn.Do("set", key, v)
- } else {
- resp, err = rc.conn.Do("setx", key, v, ttl)
- }
- if err != nil {
- return err
- }
- if len(resp) == 2 && resp[0] == "ok" {
- return nil
- }
- return errors.New("bad response")
- }
- // Delete delete value in memcache.
- func (rc *Cache) Delete(key string) error {
- if rc.conn == nil {
- if err := rc.connectInit(); err != nil {
- return err
- }
- }
- _, err := rc.conn.Del(key)
- if err != nil {
- return err
- }
- return nil
- }
- // Incr increase counter.
- func (rc *Cache) Incr(key string) error {
- if rc.conn == nil {
- if err := rc.connectInit(); err != nil {
- return err
- }
- }
- _, err := rc.conn.Do("incr", key, 1)
- return err
- }
- // Decr decrease counter.
- func (rc *Cache) Decr(key string) error {
- if rc.conn == nil {
- if err := rc.connectInit(); err != nil {
- return err
- }
- }
- _, err := rc.conn.Do("incr", key, -1)
- return err
- }
- // IsExist check value exists in memcache.
- func (rc *Cache) IsExist(key string) bool {
- if rc.conn == nil {
- if err := rc.connectInit(); err != nil {
- return false
- }
- }
- resp, err := rc.conn.Do("exists", key)
- if err != nil {
- return false
- }
- if len(resp) == 2 && resp[1] == "1" {
- return true
- }
- return false
- }
- // ClearAll clear all cached in memcache.
- func (rc *Cache) ClearAll() error {
- if rc.conn == nil {
- if err := rc.connectInit(); err != nil {
- return err
- }
- }
- keyStart, keyEnd, limit := "", "", 50
- resp, err := rc.Scan(keyStart, keyEnd, limit)
- for err == nil {
- size := len(resp)
- if size == 1 {
- return nil
- }
- keys := []string{}
- for i := 1; i < size; i += 2 {
- keys = append(keys, string(resp[i]))
- }
- _, e := rc.conn.Do("multi_del", keys)
- if e != nil {
- return e
- }
- keyStart = resp[size-2]
- resp, err = rc.Scan(keyStart, keyEnd, limit)
- }
- return err
- }
- // Scan key all cached in ssdb.
- func (rc *Cache) Scan(keyStart string, keyEnd string, limit int) ([]string, error) {
- if rc.conn == nil {
- if err := rc.connectInit(); err != nil {
- return nil, err
- }
- }
- resp, err := rc.conn.Do("scan", keyStart, keyEnd, limit)
- if err != nil {
- return nil, err
- }
- return resp, nil
- }
- // StartAndGC start memcache adapter.
- // config string is like {"conn":"connection info"}.
- // if connecting error, return.
- func (rc *Cache) StartAndGC(config string) error {
- var cf map[string]string
- json.Unmarshal([]byte(config), &cf)
- if _, ok := cf["conn"]; !ok {
- return errors.New("config has no conn key")
- }
- rc.conninfo = strings.Split(cf["conn"], ";")
- if rc.conn == nil {
- if err := rc.connectInit(); err != nil {
- return err
- }
- }
- return nil
- }
- // connect to memcache and keep the connection.
- func (rc *Cache) connectInit() error {
- conninfoArray := strings.Split(rc.conninfo[0], ":")
- host := conninfoArray[0]
- port, e := strconv.Atoi(conninfoArray[1])
- if e != nil {
- return e
- }
- var err error
- rc.conn, err = ssdb.Connect(host, port)
- if err != nil {
- return err
- }
- return nil
- }
- func init() {
- cache.Register("ssdb", NewSsdbCache)
- }
|