github.com/astaxie/beego@v1.12.3/cache/ssdb/ssdb.go (about)

     1  package ssdb
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"strconv"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/ssdb/gossdb/ssdb"
    11  
    12  	"github.com/astaxie/beego/cache"
    13  )
    14  
    15  // Cache SSDB adapter
    16  type Cache struct {
    17  	conn     *ssdb.Client
    18  	conninfo []string
    19  }
    20  
    21  //NewSsdbCache create new ssdb adapter.
    22  func NewSsdbCache() cache.Cache {
    23  	return &Cache{}
    24  }
    25  
    26  // Get get value from memcache.
    27  func (rc *Cache) Get(key string) interface{} {
    28  	if rc.conn == nil {
    29  		if err := rc.connectInit(); err != nil {
    30  			return nil
    31  		}
    32  	}
    33  	value, err := rc.conn.Get(key)
    34  	if err == nil {
    35  		return value
    36  	}
    37  	return nil
    38  }
    39  
    40  // GetMulti get value from memcache.
    41  func (rc *Cache) GetMulti(keys []string) []interface{} {
    42  	size := len(keys)
    43  	var values []interface{}
    44  	if rc.conn == nil {
    45  		if err := rc.connectInit(); err != nil {
    46  			for i := 0; i < size; i++ {
    47  				values = append(values, err)
    48  			}
    49  			return values
    50  		}
    51  	}
    52  	res, err := rc.conn.Do("multi_get", keys)
    53  	resSize := len(res)
    54  	if err == nil {
    55  		for i := 1; i < resSize; i += 2 {
    56  			values = append(values, res[i+1])
    57  		}
    58  		return values
    59  	}
    60  	for i := 0; i < size; i++ {
    61  		values = append(values, err)
    62  	}
    63  	return values
    64  }
    65  
    66  // DelMulti get value from memcache.
    67  func (rc *Cache) DelMulti(keys []string) error {
    68  	if rc.conn == nil {
    69  		if err := rc.connectInit(); err != nil {
    70  			return err
    71  		}
    72  	}
    73  	_, err := rc.conn.Do("multi_del", keys)
    74  	return err
    75  }
    76  
    77  // Put put value to memcache. only support string.
    78  func (rc *Cache) Put(key string, value interface{}, timeout time.Duration) error {
    79  	if rc.conn == nil {
    80  		if err := rc.connectInit(); err != nil {
    81  			return err
    82  		}
    83  	}
    84  	v, ok := value.(string)
    85  	if !ok {
    86  		return errors.New("value must string")
    87  	}
    88  	var resp []string
    89  	var err error
    90  	ttl := int(timeout / time.Second)
    91  	if ttl < 0 {
    92  		resp, err = rc.conn.Do("set", key, v)
    93  	} else {
    94  		resp, err = rc.conn.Do("setx", key, v, ttl)
    95  	}
    96  	if err != nil {
    97  		return err
    98  	}
    99  	if len(resp) == 2 && resp[0] == "ok" {
   100  		return nil
   101  	}
   102  	return errors.New("bad response")
   103  }
   104  
   105  // Delete delete value in memcache.
   106  func (rc *Cache) Delete(key string) error {
   107  	if rc.conn == nil {
   108  		if err := rc.connectInit(); err != nil {
   109  			return err
   110  		}
   111  	}
   112  	_, err := rc.conn.Del(key)
   113  	return err
   114  }
   115  
   116  // Incr increase counter.
   117  func (rc *Cache) Incr(key string) error {
   118  	if rc.conn == nil {
   119  		if err := rc.connectInit(); err != nil {
   120  			return err
   121  		}
   122  	}
   123  	_, err := rc.conn.Do("incr", key, 1)
   124  	return err
   125  }
   126  
   127  // Decr decrease counter.
   128  func (rc *Cache) Decr(key string) error {
   129  	if rc.conn == nil {
   130  		if err := rc.connectInit(); err != nil {
   131  			return err
   132  		}
   133  	}
   134  	_, err := rc.conn.Do("incr", key, -1)
   135  	return err
   136  }
   137  
   138  // IsExist check value exists in memcache.
   139  func (rc *Cache) IsExist(key string) bool {
   140  	if rc.conn == nil {
   141  		if err := rc.connectInit(); err != nil {
   142  			return false
   143  		}
   144  	}
   145  	resp, err := rc.conn.Do("exists", key)
   146  	if err != nil {
   147  		return false
   148  	}
   149  	if len(resp) == 2 && resp[1] == "1" {
   150  		return true
   151  	}
   152  	return false
   153  
   154  }
   155  
   156  // ClearAll clear all cached in memcache.
   157  func (rc *Cache) ClearAll() error {
   158  	if rc.conn == nil {
   159  		if err := rc.connectInit(); err != nil {
   160  			return err
   161  		}
   162  	}
   163  	keyStart, keyEnd, limit := "", "", 50
   164  	resp, err := rc.Scan(keyStart, keyEnd, limit)
   165  	for err == nil {
   166  		size := len(resp)
   167  		if size == 1 {
   168  			return nil
   169  		}
   170  		keys := []string{}
   171  		for i := 1; i < size; i += 2 {
   172  			keys = append(keys, resp[i])
   173  		}
   174  		_, e := rc.conn.Do("multi_del", keys)
   175  		if e != nil {
   176  			return e
   177  		}
   178  		keyStart = resp[size-2]
   179  		resp, err = rc.Scan(keyStart, keyEnd, limit)
   180  	}
   181  	return err
   182  }
   183  
   184  // Scan key all cached in ssdb.
   185  func (rc *Cache) Scan(keyStart string, keyEnd string, limit int) ([]string, error) {
   186  	if rc.conn == nil {
   187  		if err := rc.connectInit(); err != nil {
   188  			return nil, err
   189  		}
   190  	}
   191  	resp, err := rc.conn.Do("scan", keyStart, keyEnd, limit)
   192  	if err != nil {
   193  		return nil, err
   194  	}
   195  	return resp, nil
   196  }
   197  
   198  // StartAndGC start memcache adapter.
   199  // config string is like {"conn":"connection info"}.
   200  // if connecting error, return.
   201  func (rc *Cache) StartAndGC(config string) error {
   202  	var cf map[string]string
   203  	json.Unmarshal([]byte(config), &cf)
   204  	if _, ok := cf["conn"]; !ok {
   205  		return errors.New("config has no conn key")
   206  	}
   207  	rc.conninfo = strings.Split(cf["conn"], ";")
   208  	if rc.conn == nil {
   209  		if err := rc.connectInit(); err != nil {
   210  			return err
   211  		}
   212  	}
   213  	return nil
   214  }
   215  
   216  // connect to memcache and keep the connection.
   217  func (rc *Cache) connectInit() error {
   218  	conninfoArray := strings.Split(rc.conninfo[0], ":")
   219  	host := conninfoArray[0]
   220  	port, e := strconv.Atoi(conninfoArray[1])
   221  	if e != nil {
   222  		return e
   223  	}
   224  	var err error
   225  	rc.conn, err = ssdb.Connect(host, port)
   226  	return err
   227  }
   228  
   229  func init() {
   230  	cache.Register("ssdb", NewSsdbCache)
   231  }