Merge pull request #99 from holys/develop

add SETEX command support for the KV data structure
This commit is contained in:
siddontang 2014-10-26 15:30:00 +08:00
commit c3ca5bba14
7 changed files with 118 additions and 1 deletions

View File

@ -1,4 +1,4 @@
//This file was generated by .tools/generate_commands.py on Mon Oct 20 2014 22:35:33 +0800 //This file was generated by .tools/generate_commands.py on Sun Oct 26 2014 15:14:39 +0800
package main package main
var helpCommands = [][]string{ var helpCommands = [][]string{
@ -86,6 +86,7 @@ var helpCommands = [][]string{
{"SDIFFSTORE", "destination key [key ...]", "Set"}, {"SDIFFSTORE", "destination key [key ...]", "Set"},
{"SELECT", "index", "Server"}, {"SELECT", "index", "Server"},
{"SET", "key value", "KV"}, {"SET", "key value", "KV"},
{"SETEX", "key seconds value", "KV"},
{"SETNX", "key value", "KV"}, {"SETNX", "key value", "KV"},
{"SEXPIRE", "key seconds", "Set"}, {"SEXPIRE", "key seconds", "Set"},
{"SEXPIREAT", "key timestamp", "Set"}, {"SEXPIREAT", "key timestamp", "Set"},

View File

@ -310,6 +310,11 @@
"group": "KV", "group": "KV",
"readonly": false "readonly": false
}, },
"SETEX": {
"arguments": "key seconds value",
"group": "KV",
"readonly": false
},
"SLAVEOF": { "SLAVEOF": {
"arguments": "host port [RESTART] [READONLY]", "arguments": "host port [RESTART] [READONLY]",
"group": "Replication", "group": "Replication",

View File

@ -22,6 +22,7 @@ Table of Contents
- [MSET key value [key value ...]](#mset-key-value-key-value-) - [MSET key value [key value ...]](#mset-key-value-key-value-)
- [SET key value](#set-key-value) - [SET key value](#set-key-value)
- [SETNX key value](#setnx-key-value) - [SETNX key value](#setnx-key-value)
- [SETEX key seconds value](#setex-key-seconds-value)
- [EXPIRE key seconds](#expire-key-seconds) - [EXPIRE key seconds](#expire-key-seconds)
- [EXPIREAT key timestamp](#expireat-key-timestamp) - [EXPIREAT key timestamp](#expireat-key-timestamp)
- [TTL key](#ttl-key) - [TTL key](#ttl-key)
@ -389,6 +390,30 @@ ledis> GET mykey
"hello" "hello"
``` ```
### SETEX key seconds value
Set key to hold the string value and set key to timeout after a given number of seconds. This command is equivalent to executing the following commands:
```
SET mykey value
EXPIRE mykey seconds
```
**Return value**
Simple string reply
**Examples**
```
ledis> SETEX mykey 10 "Hello"
OK
ledis> TTL mykey
(integer) 10
ledis> GET mykey
"Hello"
ledis>
```
### EXPIRE key seconds ### EXPIRE key seconds
Set a timeout on key. After the timeout has expired, the key will be deleted. Set a timeout on key. After the timeout has expired, the key will be deleted.

View File

@ -300,6 +300,32 @@ func (db *DB) SetNX(key []byte, value []byte) (int64, error) {
return n, err return n, err
} }
func (db *DB) SetEX(key []byte, duration int64, value []byte) error {
if err := checkKeySize(key); err != nil {
return err
} else if err := checkValueSize(value); err != nil {
return err
} else if duration <= 0 {
return errExpireValue
}
ek := db.encodeKVKey(key)
t := db.kvBatch
t.Lock()
defer t.Unlock()
t.Put(ek, value)
db.expireAt(t, KVType, key, time.Now().Unix()+duration)
if err := t.Commit(); err != nil {
return err
}
return nil
}
func (db *DB) flush() (drop int64, err error) { func (db *DB) flush() (drop int64, err error) {
t := db.kvBatch t := db.kvBatch
t.Lock() t.Lock()

View File

@ -116,3 +116,32 @@ func TestKVFlush(t *testing.T) {
} }
} }
} }
func TestKVSetEX(t *testing.T) {
db := getTestDB()
db.FlushAll()
key := []byte("testdb_kv_c")
if err := db.SetEX(key, 10, []byte("hello world")); err != nil {
t.Fatal(err)
}
v, err := db.Get(key)
if err != nil {
t.Fatal(err)
} else if string(v) == "" {
t.Fatal("v is nil")
}
if n, err := db.TTL(key); err != nil {
t.Fatal(err)
} else if n != 10 {
t.Fatal(n)
}
if v, _ := db.Get(key); string(v) != "hello world" {
t.Fatal(string(v))
}
}

View File

@ -66,6 +66,26 @@ func setnxCommand(c *client) error {
return nil return nil
} }
func setexCommand(c *client) error {
args := c.args
if len(args) != 3 {
return ErrCmdParams
}
sec, err := ledis.StrInt64(args[1], nil)
if err != nil {
return ErrValue
}
if err := c.db.SetEX(args[0], sec, args[2]); err != nil {
return err
} else {
c.resp.writeStatus(OK)
}
return nil
}
func existsCommand(c *client) error { func existsCommand(c *client) error {
args := c.args args := c.args
if len(args) != 1 { if len(args) != 1 {
@ -365,6 +385,7 @@ func init() {
register("mset", msetCommand) register("mset", msetCommand)
register("set", setCommand) register("set", setCommand)
register("setnx", setnxCommand) register("setnx", setnxCommand)
register("setex", setexCommand)
register("expire", expireCommand) register("expire", expireCommand)
register("expireat", expireAtCommand) register("expireat", expireAtCommand)
register("ttl", ttlCommand) register("ttl", ttlCommand)

View File

@ -27,6 +27,12 @@ func TestKV(t *testing.T) {
t.Fatal(n) t.Fatal(n)
} }
if ok, err := ledis.String(c.Do("setex", "xx", 10, "hello world")); err != nil {
t.Fatal(err)
} else if ok != OK {
t.Fatal(ok)
}
if v, err := ledis.String(c.Do("get", "a")); err != nil { if v, err := ledis.String(c.Do("get", "a")); err != nil {
t.Fatal(err) t.Fatal(err)
} else if v != "1234" { } else if v != "1234" {
@ -214,4 +220,8 @@ func TestKVErrorParams(t *testing.T) {
t.Fatal("invalid err of %v", err) t.Fatal("invalid err of %v", err)
} }
if _, err := c.Do("setex", "a", "blah", "hello world"); err == nil {
t.Fatalf("invalid err %v", err)
}
} }