forked from mirror/ledisdb
248 lines
4.3 KiB
Go
248 lines
4.3 KiB
Go
package server
|
|
|
|
import (
|
|
"fmt"
|
|
goledis "github.com/siddontang/ledisdb/client/go/ledis"
|
|
"github.com/siddontang/ledisdb/ledis"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func dumpCommand(c *client) error {
|
|
if len(c.args) != 1 {
|
|
return ErrCmdParams
|
|
}
|
|
|
|
key := c.args[0]
|
|
if data, err := c.db.Dump(key); err != nil {
|
|
return err
|
|
} else {
|
|
c.resp.writeBulk(data)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func ldumpCommand(c *client) error {
|
|
if len(c.args) != 1 {
|
|
return ErrCmdParams
|
|
}
|
|
|
|
key := c.args[0]
|
|
if data, err := c.db.LDump(key); err != nil {
|
|
return err
|
|
} else {
|
|
c.resp.writeBulk(data)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func hdumpCommand(c *client) error {
|
|
if len(c.args) != 1 {
|
|
return ErrCmdParams
|
|
}
|
|
|
|
key := c.args[0]
|
|
if data, err := c.db.HDump(key); err != nil {
|
|
return err
|
|
} else {
|
|
c.resp.writeBulk(data)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func sdumpCommand(c *client) error {
|
|
if len(c.args) != 1 {
|
|
return ErrCmdParams
|
|
}
|
|
|
|
key := c.args[0]
|
|
if data, err := c.db.SDump(key); err != nil {
|
|
return err
|
|
} else {
|
|
c.resp.writeBulk(data)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func zdumpCommand(c *client) error {
|
|
if len(c.args) != 1 {
|
|
return ErrCmdParams
|
|
}
|
|
|
|
key := c.args[0]
|
|
if data, err := c.db.ZDump(key); err != nil {
|
|
return err
|
|
} else {
|
|
c.resp.writeBulk(data)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// unlike redis, restore will try to delete old key first
|
|
func restoreCommand(c *client) error {
|
|
args := c.args
|
|
if len(args) != 3 {
|
|
return ErrCmdParams
|
|
}
|
|
|
|
key := args[0]
|
|
ttl, err := ledis.StrInt64(args[1], nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
data := args[2]
|
|
|
|
if err = c.db.Restore(key, ttl, data); err != nil {
|
|
return err
|
|
} else {
|
|
c.resp.writeStatus(OK)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func xdump(db *ledis.DB, tp string, key []byte) ([]byte, error) {
|
|
var err error
|
|
var data []byte
|
|
switch tp {
|
|
case "kv":
|
|
data, err = db.Dump(key)
|
|
case "hash":
|
|
data, err = db.HDump(key)
|
|
case "list":
|
|
data, err = db.LDump(key)
|
|
case "set":
|
|
data, err = db.SDump(key)
|
|
case "zset":
|
|
data, err = db.ZDump(key)
|
|
default:
|
|
err = fmt.Errorf("invalid key type %s", tp)
|
|
}
|
|
return data, err
|
|
}
|
|
|
|
func xdel(db *ledis.DB, tp string, key []byte) error {
|
|
var err error
|
|
switch tp {
|
|
case "kv":
|
|
_, err = db.Del(key)
|
|
case "hash":
|
|
_, err = db.HClear(key)
|
|
case "list":
|
|
_, err = db.LClear(key)
|
|
case "set":
|
|
_, err = db.SClear(key)
|
|
case "zset":
|
|
_, err = db.ZClear(key)
|
|
default:
|
|
err = fmt.Errorf("invalid key type %s", tp)
|
|
}
|
|
return err
|
|
}
|
|
|
|
func xdumpCommand(c *client) error {
|
|
args := c.args
|
|
if len(args) != 2 {
|
|
return ErrCmdParams
|
|
}
|
|
|
|
tp := string(args[0])
|
|
key := args[1]
|
|
|
|
if data, err := xdump(c.db, tp, key); err != nil {
|
|
return err
|
|
} else {
|
|
c.resp.writeBulk(data)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
//XMIGRATE host port type key destination-db timeout [COPY]
|
|
func xmigrateCommand(c *client) error {
|
|
args := c.args
|
|
|
|
if len(args) != 6 && len(args) != 7 {
|
|
return ErrCmdParams
|
|
}
|
|
|
|
addr := fmt.Sprintf("%s:%d", string(args[0]), string(args[1]))
|
|
tp := string(args[2])
|
|
key := args[3]
|
|
db, err := ledis.StrUint64(args[4], nil)
|
|
if err != nil {
|
|
return err
|
|
} else if db >= uint64(ledis.MaxDBNumber) {
|
|
return fmt.Errorf("invalid db index %d, must < %d", db, ledis.MaxDBNumber)
|
|
}
|
|
var timeout int64
|
|
timeout, err = ledis.StrInt64(args[5], nil)
|
|
if err != nil {
|
|
return err
|
|
} else if timeout < 0 {
|
|
return fmt.Errorf("invalid timeout %d", timeout)
|
|
}
|
|
|
|
onlyCopy := false
|
|
if len(args) == 7 {
|
|
if strings.ToUpper(string(args[6])) == "COPY" {
|
|
onlyCopy = true
|
|
}
|
|
}
|
|
|
|
var m *ledis.Multi
|
|
if m, err = c.db.Multi(); err != nil {
|
|
return err
|
|
}
|
|
defer m.Close()
|
|
|
|
var data []byte
|
|
data, err = xdump(m.DB, tp, key)
|
|
if err != nil {
|
|
return err
|
|
} else if data == nil {
|
|
c.resp.writeStatus(NOKEY)
|
|
return nil
|
|
}
|
|
|
|
c.app.migrateConnM.Lock()
|
|
defer c.app.migrateConnM.Unlock()
|
|
|
|
conn, ok := c.app.migrateConns[addr]
|
|
if !ok {
|
|
conn = goledis.NewConn(addr)
|
|
c.app.migrateConns[addr] = conn
|
|
}
|
|
|
|
//timeout is milliseconds
|
|
conn.SetConnectTimeout(time.Duration(timeout) * time.Millisecond)
|
|
|
|
if _, err = conn.Do("restore", key, data); err != nil {
|
|
return err
|
|
}
|
|
|
|
if !onlyCopy {
|
|
if err = xdel(m.DB, tp, key); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
c.resp.writeStatus(OK)
|
|
return nil
|
|
}
|
|
|
|
func init() {
|
|
register("dump", dumpCommand)
|
|
register("ldump", ldumpCommand)
|
|
register("hdump", hdumpCommand)
|
|
register("sdump", sdumpCommand)
|
|
register("zdump", zdumpCommand)
|
|
register("restore", restoreCommand)
|
|
register("xdump", xdumpCommand)
|
|
register("xmigrate", xmigrateCommand)
|
|
}
|