refactor, use go-leveldb,

you must re execute bootstrap.sh to go get go-leveldb
you must remove your old leveldb path because hash size format changed
This commit is contained in:
siddontang 2014-05-14 16:35:49 +08:00
parent d8eab1572c
commit 990b2ee69d
14 changed files with 119 additions and 102 deletions

View File

@ -3,7 +3,6 @@
. ./dev.sh
go get -u github.com/jmhodges/levigo
go get -u github.com/siddontang/golib/leveldb
go get -u github.com/siddontang/go-leveldb/leveldb
go get -u github.com/siddontang/golib/log
go get -u github.com/siddontang/golib/hack
go get -u github.com/garyburd/redigo/redis

View File

@ -1,7 +1,7 @@
package ledis
import (
"github.com/siddontang/golib/leveldb"
"github.com/siddontang/go-leveldb/leveldb"
"net"
"strings"
)

View File

@ -3,7 +3,6 @@ package ledis
import (
"bufio"
"errors"
"github.com/siddontang/golib/hack"
"github.com/siddontang/golib/log"
"io"
"net"
@ -92,7 +91,7 @@ func (c *client) readRequest() ([][]byte, error) {
}
var nparams int
if nparams, err = strconv.Atoi(hack.String(l[1:])); err != nil {
if nparams, err = strconv.Atoi(String(l[1:])); err != nil {
return nil, err
} else if nparams <= 0 {
return nil, errReadRequest
@ -109,7 +108,7 @@ func (c *client) readRequest() ([][]byte, error) {
return nil, errReadRequest
} else if l[0] == '$' {
//handle resp string
if n, err = strconv.Atoi(hack.String(l[1:])); err != nil {
if n, err = strconv.Atoi(String(l[1:])); err != nil {
return nil, err
} else if n == -1 {
req = append(req, nil)
@ -139,7 +138,7 @@ func (c *client) handleRequest(req [][]byte) {
if len(req) == 0 {
err = ErrEmptyCommand
} else {
c.cmd = strings.ToLower(hack.String(req[0]))
c.cmd = strings.ToLower(String(req[0]))
c.args = req[1:]
f, ok := regCmds[c.cmd]
@ -161,23 +160,23 @@ func (c *client) handleRequest(req [][]byte) {
}
func (c *client) writeError(err error) {
c.wb.Write(hack.Slice("-ERR"))
c.wb.Write(Slice("-ERR"))
if err != nil {
c.wb.WriteByte(' ')
c.wb.Write(hack.Slice(err.Error()))
c.wb.Write(Slice(err.Error()))
}
c.wb.Write(Delims)
}
func (c *client) writeStatus(status string) {
c.wb.WriteByte('+')
c.wb.Write(hack.Slice(status))
c.wb.Write(Slice(status))
c.wb.Write(Delims)
}
func (c *client) writeInteger(n int64) {
c.wb.WriteByte(':')
c.wb.Write(hack.Slice(strconv.FormatInt(n, 10)))
c.wb.Write(Slice(strconv.FormatInt(n, 10)))
c.wb.Write(Delims)
}
@ -186,7 +185,7 @@ func (c *client) writeBulk(b []byte) {
if b == nil {
c.wb.Write(NullBulk)
} else {
c.wb.Write(hack.Slice(strconv.Itoa(len(b))))
c.wb.Write(Slice(strconv.Itoa(len(b))))
c.wb.Write(Delims)
c.wb.Write(b)
}
@ -200,7 +199,7 @@ func (c *client) writeArray(ay []interface{}) {
c.wb.Write(NullArray)
c.wb.Write(Delims)
} else {
c.wb.Write(hack.Slice(strconv.Itoa(len(ay))))
c.wb.Write(Slice(strconv.Itoa(len(ay))))
c.wb.Write(Delims)
for i := 0; i < len(ay); i++ {

View File

@ -1,9 +1,6 @@
package ledis
import (
"github.com/siddontang/golib/hack"
"strconv"
)
import ()
func hsetCommand(c *client) error {
args := c.args
@ -90,7 +87,7 @@ func hincrbyCommand(c *client) error {
return ErrCmdParams
}
delta, err := strconv.ParseInt(hack.String(args[2]), 10, 64)
delta, err := StrInt64(args[2], nil)
if err != nil {
return err
}

View File

@ -1,9 +1,6 @@
package ledis
import (
"github.com/siddontang/golib/hack"
"strconv"
)
import ()
func getCommand(c *client) error {
args := c.args
@ -115,7 +112,7 @@ func incrbyCommand(c *client) error {
return ErrCmdParams
}
delta, err := strconv.ParseInt(hack.String(args[1]), 10, 64)
delta, err := StrInt64(args[1], nil)
if err != nil {
return err
}
@ -135,7 +132,7 @@ func decrbyCommand(c *client) error {
return ErrCmdParams
}
delta, err := strconv.ParseInt(hack.String(args[1]), 10, 64)
delta, err := StrInt64(args[1], nil)
if err != nil {
return err
}

View File

@ -1,9 +1,6 @@
package ledis
import (
"github.com/siddontang/golib/hack"
"strconv"
)
import ()
func lpushCommand(c *client) error {
args := c.args
@ -86,7 +83,7 @@ func lindexCommand(c *client) error {
return ErrCmdParams
}
index, err := strconv.ParseInt(hack.String(args[1]), 10, 64)
index, err := StrInt64(args[1], nil)
if err != nil {
return err
}
@ -110,12 +107,12 @@ func lrangeCommand(c *client) error {
var stop int64
var err error
start, err = strconv.ParseInt(hack.String(args[1]), 10, 64)
start, err = StrInt64(args[1], nil)
if err != nil {
return err
}
stop, err = strconv.ParseInt(hack.String(args[2]), 10, 64)
stop, err = StrInt64(args[2], nil)
if err != nil {
return err
}

View File

@ -2,7 +2,6 @@ package ledis
import (
"errors"
"github.com/siddontang/golib/hack"
"math"
"strconv"
"strings"
@ -31,7 +30,7 @@ func zaddCommand(c *client) error {
args = args[1:]
params := make([]interface{}, len(args))
for i := 0; i < len(params); i += 2 {
score, err := strconv.ParseInt(hack.String(args[i]), 10, 64)
score, err := StrInt64(args[i], nil)
if err != nil {
return err
}
@ -102,7 +101,7 @@ func zincrbyCommand(c *client) error {
key := args[0]
delta, err := strconv.ParseInt(hack.String(args[1]), 10, 64)
delta, err := StrInt64(args[1], nil)
if err != nil {
return err
}
@ -117,7 +116,7 @@ func zincrbyCommand(c *client) error {
}
func zparseScoreRange(minBuf []byte, maxBuf []byte) (min int64, max int64, err error) {
if strings.ToLower(hack.String(minBuf)) == "-inf" {
if strings.ToLower(String(minBuf)) == "-inf" {
min = math.MinInt64
} else {
var lopen bool = false
@ -131,7 +130,7 @@ func zparseScoreRange(minBuf []byte, maxBuf []byte) (min int64, max int64, err e
return
}
min, err = strconv.ParseInt(hack.String(minBuf), 10, 64)
min, err = StrInt64(minBuf, nil)
if err != nil {
return
}
@ -146,7 +145,7 @@ func zparseScoreRange(minBuf []byte, maxBuf []byte) (min int64, max int64, err e
}
}
if strings.ToLower(hack.String(maxBuf)) == "+inf" {
if strings.ToLower(String(maxBuf)) == "+inf" {
max = math.MaxInt64
} else {
var ropen = false
@ -160,7 +159,7 @@ func zparseScoreRange(minBuf []byte, maxBuf []byte) (min int64, max int64, err e
return
}
max, err = strconv.ParseInt(hack.String(maxBuf), 10, 64)
max, err = StrInt64(maxBuf, nil)
if err != nil {
return
}
@ -288,11 +287,11 @@ func zremrangebyscoreCommand(c *client) error {
func zparseRange(c *client, key []byte, startBuf []byte, stopBuf []byte) (offset int, limit int, err error) {
var start int
var stop int
if start, err = strconv.Atoi(hack.String(startBuf)); err != nil {
if start, err = strconv.Atoi(String(startBuf)); err != nil {
return
}
if stop, err = strconv.Atoi(hack.String(stopBuf)); err != nil {
if stop, err = strconv.Atoi(String(stopBuf)); err != nil {
return
}
@ -354,7 +353,7 @@ func zrangeGeneric(c *client, reverse bool) error {
args = args[3:]
var withScores bool = false
if len(args) > 0 && strings.ToLower(hack.String(args[0])) == "withscores" {
if len(args) > 0 && strings.ToLower(String(args[0])) == "withscores" {
withScores = true
}
@ -390,7 +389,7 @@ func zrangebyscoreGeneric(c *client, reverse bool) error {
var withScores bool = false
if len(args) > 0 && strings.ToLower(hack.String(args[0])) == "withscores" {
if len(args) > 0 && strings.ToLower(String(args[0])) == "withscores" {
withScores = true
args = args[1:]
}
@ -403,15 +402,15 @@ func zrangebyscoreGeneric(c *client, reverse bool) error {
return ErrCmdParams
}
if strings.ToLower(hack.String(args[0])) != "limit" {
if strings.ToLower(String(args[0])) != "limit" {
return ErrCmdParams
}
if offset, err = strconv.Atoi(hack.String(args[1])); err != nil {
if offset, err = strconv.Atoi(String(args[1])); err != nil {
return ErrCmdParams
}
if limit, err = strconv.Atoi(hack.String(args[2])); err != nil {
if limit, err = strconv.Atoi(String(args[2])); err != nil {
return ErrCmdParams
}
}

View File

@ -2,7 +2,7 @@ package ledis
import (
"encoding/json"
"github.com/siddontang/golib/leveldb"
"github.com/siddontang/go-leveldb/leveldb"
"io/ioutil"
)

View File

@ -3,9 +3,7 @@ package ledis
import (
"encoding/binary"
"errors"
"github.com/siddontang/golib/hack"
"github.com/siddontang/golib/leveldb"
"strconv"
"github.com/siddontang/go-leveldb/leveldb"
)
var errHashKey = errors.New("invalid hash key")
@ -90,26 +88,21 @@ func decode_hash_key(ek []byte) ([]byte, []byte, error) {
}
func (a *App) hash_len(key []byte) (int64, error) {
return a.db.GetInt(encode_hsize_key(key))
return Int64(a.db.Get(encode_hsize_key(key)))
}
func (a *App) hash_setItem(key []byte, field []byte, value []byte) (int64, error) {
t := a.hashTx
ek := encode_hash_key(key, field)
sk := encode_hsize_key(key)
size, err := a.db.GetInt(sk)
if err != nil {
return 0, err
}
var n int64 = 1
if v, _ := a.db.Get(ek); v != nil {
n = 0
} else {
size++
t.Put(sk, hack.Slice(strconv.FormatInt(size, 10)))
if _, err := a.hash_incrSize(key, 1); err != nil {
return 0, err
}
}
t.Put(ek, value)
@ -137,30 +130,26 @@ func (a *App) hash_get(key []byte, field []byte) ([]byte, error) {
}
func (a *App) hash_mset(key []byte, args [][]byte) error {
sk := encode_hsize_key(key)
t := a.hashTx
t.Lock()
defer t.Unlock()
size, err := a.db.GetInt(sk)
if err != nil {
return err
}
var num int64 = 0
for i := 0; i < len(args); i += 2 {
ek := encode_hash_key(key, args[i])
if v, _ := a.db.Get(ek); v == nil {
size++
num++
}
t.Put(ek, args[i+1])
}
t.Put(sk, hack.Slice(strconv.FormatInt(size, 10)))
if _, err := a.hash_incrSize(key, num); err != nil {
return err
}
//todo add binglog
err = t.Commit()
err := t.Commit()
return err
}
@ -179,17 +168,10 @@ func (a *App) hash_mget(key []byte, args [][]byte) ([]interface{}, error) {
}
func (a *App) hash_del(key []byte, args [][]byte) (int64, error) {
sk := encode_hsize_key(key)
t := a.hashTx
t.Lock()
defer t.Unlock()
size, err := a.db.GetInt(sk)
if err != nil {
return 0, err
}
var num int64 = 0
for i := 0; i < len(args); i++ {
ek := encode_hash_key(key, args[i])
@ -199,22 +181,38 @@ func (a *App) hash_del(key []byte, args [][]byte) (int64, error) {
continue
} else {
num++
size--
t.Delete(ek)
}
}
if size <= 0 {
t.Delete(sk)
} else {
t.Put(sk, hack.Slice(strconv.FormatInt(size, 10)))
if _, err := a.hash_incrSize(key, -num); err != nil {
return 0, err
}
err = t.Commit()
err := t.Commit()
return num, err
}
func (a *App) hash_incrSize(key []byte, delta int64) (int64, error) {
t := a.hashTx
sk := encode_hsize_key(key)
size, err := Int64(a.db.Get(sk))
if err != nil {
return 0, err
} else {
size += delta
if size <= 0 {
size = 0
t.Delete(sk)
} else {
t.Put(sk, PutInt64(size))
}
}
return size, nil
}
func (a *App) hash_incrby(key []byte, field []byte, delta int64) (int64, error) {
t := a.hashTx
t.Lock()
@ -223,18 +221,14 @@ func (a *App) hash_incrby(key []byte, field []byte, delta int64) (int64, error)
ek := encode_hash_key(key, field)
var n int64 = 0
v, err := a.db.Get(ek)
n, err := StrInt64(a.db.Get(ek))
if err != nil {
return 0, err
} else if v != nil {
if n, err = strconv.ParseInt(hack.String(v), 10, 64); err != nil {
return 0, err
}
}
n += delta
_, err = a.hash_setItem(key, field, hack.Slice(strconv.FormatInt(n, 10)))
_, err = a.hash_setItem(key, field, StrPutInt64(n))
if err != nil {
return 0, err
}

View File

@ -2,8 +2,6 @@ package ledis
import (
"errors"
"github.com/siddontang/golib/hack"
"strconv"
)
var errKVKey = errors.New("invalid encode kv key")
@ -117,14 +115,14 @@ func (a *App) kv_incr(key []byte, delta int64) (int64, error) {
defer t.Unlock()
var n int64
n, err = a.db.GetInt(key)
n, err = StrInt64(a.db.Get(key))
if err != nil {
return 0, err
}
n += delta
t.Put(key, hack.Slice(strconv.FormatInt(n, 10)))
t.Put(key, StrPutInt64(n))
//todo binlog

View File

@ -3,7 +3,7 @@ package ledis
import (
"encoding/binary"
"errors"
"github.com/siddontang/golib/leveldb"
"github.com/siddontang/go-leveldb/leveldb"
)
const (

View File

@ -4,8 +4,7 @@ import (
"bytes"
"encoding/binary"
"errors"
"github.com/siddontang/golib/hack"
"github.com/siddontang/golib/leveldb"
"github.com/siddontang/go-leveldb/leveldb"
"strconv"
)
@ -262,7 +261,7 @@ func (a *App) zset_score(key []byte, member []byte) ([]byte, error) {
return nil, err
}
return hack.Slice(strconv.FormatInt(score, 10)), nil
return Slice(strconv.FormatInt(score, 10)), nil
}
func (a *App) zset_rem(key []byte, args [][]byte) (int64, error) {
@ -319,7 +318,7 @@ func (a *App) zset_incrby(key []byte, delta int64, member []byte) ([]byte, error
t.Put(encode_zscore_key(key, member, score), []byte{})
err = t.Commit()
return hack.Slice(strconv.FormatInt(score, 10)), err
return Slice(strconv.FormatInt(score, 10)), err
}
func (a *App) zset_count(key []byte, min int64, max int64) (int64, error) {
@ -471,7 +470,7 @@ func (a *App) zset_range(key []byte, min int64, max int64, withScores bool, offs
v = append(v, m)
if withScores {
v = append(v, hack.Slice(strconv.FormatInt(s, 10)))
v = append(v, Slice(strconv.FormatInt(s, 10)))
}
}

View File

@ -1,7 +1,7 @@
package ledis
import (
"github.com/siddontang/golib/leveldb"
"github.com/siddontang/go-leveldb/leveldb"
"sync"
)

View File

@ -3,11 +3,34 @@ package ledis
import (
"encoding/binary"
"errors"
"github.com/siddontang/golib/hack"
"reflect"
"strconv"
"unsafe"
)
var errIntNumber = errors.New("invalid integer")
// no copy to change slice to string
// use your own risk
func String(b []byte) (s string) {
pbytes := (*reflect.SliceHeader)(unsafe.Pointer(&b))
pstring := (*reflect.StringHeader)(unsafe.Pointer(&s))
pstring.Data = pbytes.Data
pstring.Len = pbytes.Len
return
}
// no copy to change string to slice
// use your own risk
func Slice(s string) (b []byte) {
pbytes := (*reflect.SliceHeader)(unsafe.Pointer(&b))
pstring := (*reflect.StringHeader)(unsafe.Pointer(&s))
pbytes.Data = pstring.Data
pbytes.Len = pstring.Len
pbytes.Cap = pstring.Len
return
}
func Int64(v []byte, err error) (int64, error) {
if err != nil {
return 0, err
@ -21,9 +44,24 @@ func Int64(v []byte, err error) (int64, error) {
}
func PutInt64(v int64) []byte {
return hack.Int64Slice(v)
var b []byte
pbytes := (*reflect.SliceHeader)(unsafe.Pointer(&b))
pbytes.Data = uintptr(unsafe.Pointer(&v))
pbytes.Len = 8
pbytes.Cap = 8
return b
}
func PutInt32(v int32) []byte {
return hack.Int32Slice(v)
func StrInt64(v []byte, err error) (int64, error) {
if err != nil {
return 0, err
} else if v == nil {
return 0, nil
} else {
return strconv.ParseInt(String(v), 10, 64)
}
}
func StrPutInt64(v int64) []byte {
return Slice(strconv.FormatInt(v, 10))
}