From 292d8f2c006d66404c3270f724eda3c9dff8d93c Mon Sep 17 00:00:00 2001 From: liuchun Date: Sun, 6 Mar 2016 13:17:16 +0800 Subject: [PATCH 01/13] add ssdb cache adapter --- cache/ssdb/ssdb.go | 239 ++++++++++++++++++++++++++++++++++++++++ cache/ssdb/ssdb_test.go | 103 +++++++++++++++++ 2 files changed, 342 insertions(+) create mode 100644 cache/ssdb/ssdb.go create mode 100644 cache/ssdb/ssdb_test.go diff --git a/cache/ssdb/ssdb.go b/cache/ssdb/ssdb.go new file mode 100644 index 00000000..5a73aebb --- /dev/null +++ b/cache/ssdb/ssdb.go @@ -0,0 +1,239 @@ +package ssdb + +import ( + "encoding/json" + "errors" + "strconv" + "strings" + + "github.com/ssdb/gossdb/ssdb" + "time" + + "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 { + panic(err) + } + } + 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) + if err == nil { + for i := 1; i < size*2; 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 resp[1] == "1" { + return true + } else { + 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 + } + } + key_start, key_end, limit := "", "", 50 + resp, err := rc.Scan(key_start, key_end, 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 + } + key_start = resp[size-2] + resp, err = rc.Scan(key_start, key_end, limit) + } + return err +} + +// Scan key all cached in ssdb. +func (rc *Cache) Scan(key_start string, key_end string, limit int) ([]string, error) { + if rc.conn == nil { + if err := rc.connectInit(); err != nil { + return nil, err + } + } + resp, err := rc.conn.Do("scan", key_start, key_end, 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 { + conninfo_array := strings.Split(rc.conninfo[0], ":") + host := conninfo_array[0] + port, e := strconv.Atoi(conninfo_array[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) +} diff --git a/cache/ssdb/ssdb_test.go b/cache/ssdb/ssdb_test.go new file mode 100644 index 00000000..ed6d4db3 --- /dev/null +++ b/cache/ssdb/ssdb_test.go @@ -0,0 +1,103 @@ +package ssdb + +import ( + "github.com/astaxie/beego/cache" + "strconv" + "testing" + "time" +) + +func TestMemcacheCache(t *testing.T) { + ssdb, err := cache.NewCache("ssdb", `{"conn": "127.0.0.1:8888"}`) + if err != nil { + t.Error("init err") + } + + // test put and exist + if ssdb.IsExist("ssdb") { + t.Error("check err") + } + timeoutDuration := 10 * time.Second + //timeoutDuration := -10*time.Second if timeoutDuration is negtive,it means permanent + if err = ssdb.Put("ssdb", "ssdb", timeoutDuration); err != nil { + t.Error("set Error", err) + } + if !ssdb.IsExist("ssdb") { + t.Error("check err") + } + + // Get test done + if err = ssdb.Put("ssdb", "ssdb", timeoutDuration); err != nil { + t.Error("set Error", err) + } + + if v := ssdb.Get("ssdb"); v != "ssdb" { + t.Error("get Error") + } + + //inc/dec test done + if err = ssdb.Put("ssdb", "2", timeoutDuration); err != nil { + t.Error("set Error", err) + } + if err = ssdb.Incr("ssdb"); err != nil { + t.Error("incr Error", err) + } + + if v, err := strconv.Atoi(ssdb.Get("ssdb").(string)); err != nil || v != 3 { + t.Error("get err") + } + + if err = ssdb.Decr("ssdb"); err != nil { + t.Error("decr error") + } + + // test del + if err = ssdb.Put("ssdb", "3", timeoutDuration); err != nil { + t.Error("set Error", err) + } + if v, err := strconv.Atoi(ssdb.Get("ssdb").(string)); err != nil || v != 3 { + t.Error("get err") + } + if err := ssdb.Delete("ssdb"); err == nil { + if ssdb.IsExist("ssdb") { + t.Error("delete err") + } + } + + //test string + if err = ssdb.Put("ssdb", "ssdb", -10*time.Second); err != nil { + t.Error("set Error", err) + } + if !ssdb.IsExist("ssdb") { + t.Error("check err") + } + if v := ssdb.Get("ssdb").(string); v != "ssdb" { + t.Error("get err") + } + + //test GetMulti done + if err = ssdb.Put("ssdb1", "ssdb1", -10*time.Second); err != nil { + t.Error("set Error", err) + } + if !ssdb.IsExist("ssdb1") { + t.Error("check err") + } + vv := ssdb.GetMulti([]string{"ssdb", "ssdb1"}) + if len(vv) != 2 { + t.Error("getmulti error") + } + if vv[0].(string) != "ssdb" { + t.Error("getmulti error") + } + if vv[1].(string) != "ssdb1" { + t.Error("getmulti error") + } + + // test clear all done + if err = ssdb.ClearAll(); err != nil { + t.Error("clear all err") + } + if ssdb.IsExist("ssdb") || ssdb.IsExist("ssdb1") { + t.Error("check err") + } +} From 48ec7f736e974c35c03889b2f20547b5410d3105 Mon Sep 17 00:00:00 2001 From: liuchun Date: Sun, 6 Mar 2016 14:46:13 +0800 Subject: [PATCH 02/13] fix GetMulti bug --- cache/ssdb/ssdb.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cache/ssdb/ssdb.go b/cache/ssdb/ssdb.go index 5a73aebb..d329149c 100644 --- a/cache/ssdb/ssdb.go +++ b/cache/ssdb/ssdb.go @@ -50,8 +50,9 @@ func (rc *Cache) GetMulti(keys []string) []interface{} { } } res, err := rc.conn.Do("multi_get", keys) + res_size := len(res) if err == nil { - for i := 1; i < size*2; i += 2 { + for i := 1; i < res_size; i += 2 { values = append(values, string(res[i+1])) } return values From b39830dff3886b234595a0019769f8f1bfae958d Mon Sep 17 00:00:00 2001 From: liuchun Date: Mon, 7 Mar 2016 10:31:56 +0800 Subject: [PATCH 03/13] add .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 3a6c9f84..c732aac0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,6 +28,7 @@ install: - go get github.com/siddontang/ledisdb/ledis - go get golang.org/x/tools/cmd/vet - go get github.com/golang/lint/golint + - go get github.com/ssdb/gossdb/ssdb before_script: - sh -c "if [ '$ORM_DRIVER' = 'postgres' ]; then psql -c 'create database orm_test;' -U postgres; fi" - sh -c "if [ '$ORM_DRIVER' = 'mysql' ]; then mysql -u root -e 'create database orm_test;'; fi" From 22e3900403ae59821743bb398c861f9d0f52520a Mon Sep 17 00:00:00 2001 From: liuchun Date: Mon, 7 Mar 2016 14:34:40 +0800 Subject: [PATCH 04/13] add .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index c732aac0..8c6805fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ services: - mysql - postgresql - memcached + - ssdb env: - ORM_DRIVER=sqlite3 ORM_SOURCE=$TRAVIS_BUILD_DIR/orm_test.db - ORM_DRIVER=mysql ORM_SOURCE="root:@/orm_test?charset=utf8" From 0caadb9b665ccc0774cc60918eada939382456f8 Mon Sep 17 00:00:00 2001 From: liuchun Date: Mon, 7 Mar 2016 14:45:45 +0800 Subject: [PATCH 05/13] rename vars --- .travis.yml | 1 - cache/ssdb/ssdb.go | 26 +++++++++++++------------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8c6805fc..c732aac0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,6 @@ services: - mysql - postgresql - memcached - - ssdb env: - ORM_DRIVER=sqlite3 ORM_SOURCE=$TRAVIS_BUILD_DIR/orm_test.db - ORM_DRIVER=mysql ORM_SOURCE="root:@/orm_test?charset=utf8" diff --git a/cache/ssdb/ssdb.go b/cache/ssdb/ssdb.go index d329149c..128314a6 100644 --- a/cache/ssdb/ssdb.go +++ b/cache/ssdb/ssdb.go @@ -50,9 +50,9 @@ func (rc *Cache) GetMulti(keys []string) []interface{} { } } res, err := rc.conn.Do("multi_get", keys) - res_size := len(res) + resSize := len(res) if err == nil { - for i := 1; i < res_size; i += 2 { + for i := 1; i < resSize; i += 2 { values = append(values, string(res[i+1])) } return values @@ -154,9 +154,9 @@ func (rc *Cache) IsExist(key string) bool { } if resp[1] == "1" { return true - } else { - return false } + return false + } // ClearAll clear all cached in memcache. @@ -166,8 +166,8 @@ func (rc *Cache) ClearAll() error { return err } } - key_start, key_end, limit := "", "", 50 - resp, err := rc.Scan(key_start, key_end, limit) + keyStart, keyEnd, limit := "", "", 50 + resp, err := rc.Scan(keyStart, keyEnd, limit) for err == nil { size := len(resp) if size == 1 { @@ -181,20 +181,20 @@ func (rc *Cache) ClearAll() error { if e != nil { return e } - key_start = resp[size-2] - resp, err = rc.Scan(key_start, key_end, limit) + keyStart = resp[size-2] + resp, err = rc.Scan(keyStart, keyEnd, limit) } return err } // Scan key all cached in ssdb. -func (rc *Cache) Scan(key_start string, key_end string, limit int) ([]string, error) { +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", key_start, key_end, limit) + resp, err := rc.conn.Do("scan", keyStart, keyEnd, limit) if err != nil { return nil, err } @@ -221,9 +221,9 @@ func (rc *Cache) StartAndGC(config string) error { // connect to memcache and keep the connection. func (rc *Cache) connectInit() error { - conninfo_array := strings.Split(rc.conninfo[0], ":") - host := conninfo_array[0] - port, e := strconv.Atoi(conninfo_array[1]) + conninfoArray := strings.Split(rc.conninfo[0], ":") + host := conninfoArray[0] + port, e := strconv.Atoi(conninfoArray[1]) if e != nil { return e } From e29f4b57a3b9bc80b2ae1fd262ff7b28eefe4229 Mon Sep 17 00:00:00 2001 From: liuchun Date: Mon, 7 Mar 2016 14:53:36 +0800 Subject: [PATCH 06/13] fix travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index c732aac0..ffc78d1b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,6 +29,7 @@ install: - go get golang.org/x/tools/cmd/vet - go get github.com/golang/lint/golint - go get github.com/ssdb/gossdb/ssdb + - go get github.com/astaxie/beego/cache before_script: - sh -c "if [ '$ORM_DRIVER' = 'postgres' ]; then psql -c 'create database orm_test;' -U postgres; fi" - sh -c "if [ '$ORM_DRIVER' = 'mysql' ]; then mysql -u root -e 'create database orm_test;'; fi" From 9ddc2f5474379f56d1f1f58d57cc7f0d675b9770 Mon Sep 17 00:00:00 2001 From: liuchun Date: Mon, 7 Mar 2016 15:00:03 +0800 Subject: [PATCH 07/13] fix panic err --- cache/ssdb/ssdb.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cache/ssdb/ssdb.go b/cache/ssdb/ssdb.go index 128314a6..0f8fdf00 100644 --- a/cache/ssdb/ssdb.go +++ b/cache/ssdb/ssdb.go @@ -27,7 +27,7 @@ func NewSsdbCache() cache.Cache { func (rc *Cache) Get(key string) interface{} { if rc.conn == nil { if err := rc.connectInit(); err != nil { - panic(err) + return nil } } value, err := rc.conn.Get(key) From 1ddb1ce2fe0c4c722d78cc7d3c1d07f4133b6a55 Mon Sep 17 00:00:00 2001 From: liuchun Date: Mon, 7 Mar 2016 15:50:13 +0800 Subject: [PATCH 08/13] add ssdb travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index ffc78d1b..60ef36bc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ services: - mysql - postgresql - memcached + - ssdb env: - ORM_DRIVER=sqlite3 ORM_SOURCE=$TRAVIS_BUILD_DIR/orm_test.db - ORM_DRIVER=mysql ORM_SOURCE="root:@/orm_test?charset=utf8" From 662bea352f598e7c8e67a16cc033b9fc4b02e1aa Mon Sep 17 00:00:00 2001 From: liuchun Date: Tue, 8 Mar 2016 12:45:54 +0800 Subject: [PATCH 09/13] modify travis --- .travis.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.travis.yml b/.travis.yml index 60ef36bc..45358f36 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,11 @@ env: - ORM_DRIVER=sqlite3 ORM_SOURCE=$TRAVIS_BUILD_DIR/orm_test.db - ORM_DRIVER=mysql ORM_SOURCE="root:@/orm_test?charset=utf8" - ORM_DRIVER=postgres ORM_SOURCE="user=postgres dbname=orm_test sslmode=disable" +before_install: + - git clone git://github.com/ideawu/ssdb.git + - cd ssdb + - make + - cd .. install: - go get github.com/lib/pq - go get github.com/go-sql-driver/mysql @@ -35,6 +40,11 @@ before_script: - sh -c "if [ '$ORM_DRIVER' = 'postgres' ]; then psql -c 'create database orm_test;' -U postgres; fi" - sh -c "if [ '$ORM_DRIVER' = 'mysql' ]; then mysql -u root -e 'create database orm_test;'; fi" - sh -c "if [ '$ORM_DRIVER' = 'sqlite' ]; then touch $TRAVIS_BUILD_DIR/orm_test.db; fi" + - mkdir -p res/var + - ./ssdb/ssdb-server ./ssdb/ssdb.conf -d +after_script: + -killall -w ssdb-server + - rm -rf ./res/var/* script: - go vet -x ./... - $HOME/gopath/bin/golint ./... From 0a0fc351e7d1a747e37903ed8f7ae4195009a22e Mon Sep 17 00:00:00 2001 From: liuchun Date: Tue, 8 Mar 2016 12:59:19 +0800 Subject: [PATCH 10/13] fix ssdb_test --- cache/ssdb/ssdb_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cache/ssdb/ssdb_test.go b/cache/ssdb/ssdb_test.go index ed6d4db3..e03ba343 100644 --- a/cache/ssdb/ssdb_test.go +++ b/cache/ssdb/ssdb_test.go @@ -7,7 +7,7 @@ import ( "time" ) -func TestMemcacheCache(t *testing.T) { +func TestSsdbcacheCache(t *testing.T) { ssdb, err := cache.NewCache("ssdb", `{"conn": "127.0.0.1:8888"}`) if err != nil { t.Error("init err") From 14be252d2a81c7b17d48012a3ca0b9a4adc1a480 Mon Sep 17 00:00:00 2001 From: liuchun Date: Tue, 8 Mar 2016 14:01:33 +0800 Subject: [PATCH 11/13] fix travis.yml --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 45358f36..9001589e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,7 +35,6 @@ install: - go get golang.org/x/tools/cmd/vet - go get github.com/golang/lint/golint - go get github.com/ssdb/gossdb/ssdb - - go get github.com/astaxie/beego/cache before_script: - sh -c "if [ '$ORM_DRIVER' = 'postgres' ]; then psql -c 'create database orm_test;' -U postgres; fi" - sh -c "if [ '$ORM_DRIVER' = 'mysql' ]; then mysql -u root -e 'create database orm_test;'; fi" From ef59a0ed638da872643aa9a22783f3e5f5124347 Mon Sep 17 00:00:00 2001 From: liuchun Date: Tue, 8 Mar 2016 14:03:33 +0800 Subject: [PATCH 12/13] fix travis.yml --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9001589e..4452012e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,6 @@ services: - mysql - postgresql - memcached - - ssdb env: - ORM_DRIVER=sqlite3 ORM_SOURCE=$TRAVIS_BUILD_DIR/orm_test.db - ORM_DRIVER=mysql ORM_SOURCE="root:@/orm_test?charset=utf8" From bd04be447074094ada01a33e502d17d634166a62 Mon Sep 17 00:00:00 2001 From: liuchun Date: Tue, 8 Mar 2016 14:44:37 +0800 Subject: [PATCH 13/13] move time to the top --- cache/ssdb/ssdb.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cache/ssdb/ssdb.go b/cache/ssdb/ssdb.go index 0f8fdf00..bfee69ce 100644 --- a/cache/ssdb/ssdb.go +++ b/cache/ssdb/ssdb.go @@ -5,9 +5,9 @@ import ( "errors" "strconv" "strings" + "time" "github.com/ssdb/gossdb/ssdb" - "time" "github.com/astaxie/beego/cache" )