From c5107c71372cc9e403d899fd76fce4b2401979a6 Mon Sep 17 00:00:00 2001 From: siddontang Date: Tue, 28 Oct 2014 23:30:00 +0800 Subject: [PATCH] add slice for store, optimize leveldb/rocksdb get --- store/boltdb/db.go | 9 +++++++ store/driver/driver.go | 1 + store/driver/slice.go | 60 ++++++++++++++++++++++++++++++++++++++++++ store/goleveldb/db.go | 8 ++++++ store/leveldb/db.go | 26 ++++++++++++++++++ store/mdb/mdb.go | 9 +++++++ store/rocksdb/db.go | 26 ++++++++++++++++++ 7 files changed, 139 insertions(+) create mode 100644 store/driver/slice.go diff --git a/store/boltdb/db.go b/store/boltdb/db.go index ac8cc03..377cac5 100644 --- a/store/boltdb/db.go +++ b/store/boltdb/db.go @@ -167,6 +167,15 @@ func (db *DB) Compact() error { return nil } +func (db *DB) GetSlice(key []byte) (driver.ISlice, error) { + v, err := db.Get(key) + if err != nil { + return nil, err + } else { + return driver.GoSlice(v), nil + } +} + func init() { driver.Register(Store{}) } diff --git a/store/driver/driver.go b/store/driver/driver.go index e4312ce..32e5a68 100644 --- a/store/driver/driver.go +++ b/store/driver/driver.go @@ -12,6 +12,7 @@ type IDB interface { Close() error Get(key []byte) ([]byte, error) + GetSlice(key []byte) (ISlice, error) Put(key []byte, value []byte) error Delete(key []byte) error diff --git a/store/driver/slice.go b/store/driver/slice.go new file mode 100644 index 0000000..76e4ea7 --- /dev/null +++ b/store/driver/slice.go @@ -0,0 +1,60 @@ +package driver + +// #include +import "C" + +import ( + "reflect" + "unsafe" +) + +type ISlice interface { + Data() []byte + Size() int + Free() +} + +type CSlice struct { + data unsafe.Pointer + size int +} + +func NewCSlice(p unsafe.Pointer, n int) *CSlice { + return &CSlice{p, n} +} + +func (s *CSlice) Data() []byte { + var value []byte + + sH := (*reflect.SliceHeader)(unsafe.Pointer(&value)) + sH.Cap = int(s.size) + sH.Len = int(s.size) + sH.Data = uintptr(s.data) + + return value +} + +func (s *CSlice) Size() int { + return int(s.size) +} + +func (s *CSlice) Free() { + if s.data != nil { + C.free(s.data) + s.data = nil + } +} + +type GoSlice []byte + +func (s GoSlice) Data() []byte { + return []byte(s) +} + +func (s GoSlice) Size() int { + return len(s) +} + +func (s GoSlice) Free() { + +} diff --git a/store/goleveldb/db.go b/store/goleveldb/db.go index 9924067..6b3fb1b 100644 --- a/store/goleveldb/db.go +++ b/store/goleveldb/db.go @@ -196,6 +196,14 @@ func (db *DB) Compact() error { return db.db.CompactRange(util.Range{nil, nil}) } +func (db *DB) GetSlice(key []byte) (driver.ISlice, error) { + v, err := db.Get(key) + if err != nil { + return nil, err + } else { + return driver.GoSlice(v), nil + } +} func init() { driver.Register(Store{}) driver.Register(MemStore{}) diff --git a/store/leveldb/db.go b/store/leveldb/db.go index 449c32b..2de24b6 100644 --- a/store/leveldb/db.go +++ b/store/leveldb/db.go @@ -257,6 +257,28 @@ func (db *DB) get(ro *ReadOptions, key []byte) ([]byte, error) { return C.GoBytes(unsafe.Pointer(value), C.int(vallen)), nil } +func (db *DB) getSlice(ro *ReadOptions, key []byte) (driver.ISlice, error) { + var errStr *C.char + var vallen C.size_t + var k *C.char + if len(key) != 0 { + k = (*C.char)(unsafe.Pointer(&key[0])) + } + + value := C.leveldb_get( + db.db, ro.Opt, k, C.size_t(len(key)), &vallen, &errStr) + + if errStr != nil { + return nil, saveError(errStr) + } + + if value == nil { + return nil, nil + } + + return driver.NewCSlice(unsafe.Pointer(value), int(vallen)), nil +} + func (db *DB) delete(wo *WriteOptions, key []byte) error { var errStr *C.char var k *C.char @@ -282,6 +304,10 @@ func (db *DB) Compact() error { return nil } +func (db *DB) GetSlice(key []byte) (driver.ISlice, error) { + return db.getSlice(db.readOpts, key) +} + func init() { driver.Register(Store{}) } diff --git a/store/mdb/mdb.go b/store/mdb/mdb.go index 6bf26f6..ed8f2d1 100644 --- a/store/mdb/mdb.go +++ b/store/mdb/mdb.go @@ -311,6 +311,15 @@ func (db MDB) Compact() error { return nil } +func (db MDB) GetSlice(key []byte) (driver.ISlice, error) { + v, err := db.Get(key) + if err != nil { + return nil, err + } else { + return driver.GoSlice(v), nil + } +} + func init() { driver.Register(Store{}) } diff --git a/store/rocksdb/db.go b/store/rocksdb/db.go index e1f10a4..7ed572a 100644 --- a/store/rocksdb/db.go +++ b/store/rocksdb/db.go @@ -284,6 +284,28 @@ func (db *DB) get(ro *ReadOptions, key []byte) ([]byte, error) { return C.GoBytes(unsafe.Pointer(value), C.int(vallen)), nil } +func (db *DB) getSlice(ro *ReadOptions, key []byte) (driver.ISlice, error) { + var errStr *C.char + var vallen C.size_t + var k *C.char + if len(key) != 0 { + k = (*C.char)(unsafe.Pointer(&key[0])) + } + + value := C.rocksdb_get( + db.db, ro.Opt, k, C.size_t(len(key)), &vallen, &errStr) + + if errStr != nil { + return nil, saveError(errStr) + } + + if value == nil { + return nil, nil + } + + return driver.NewCSlice(unsafe.Pointer(value), int(vallen)), nil +} + func (db *DB) delete(wo *WriteOptions, key []byte) error { var errStr *C.char var k *C.char @@ -309,6 +331,10 @@ func (db *DB) Compact() error { return nil } +func (db *DB) GetSlice(key []byte) (driver.ISlice, error) { + return db.getSlice(db.readOpts, key) +} + func init() { driver.Register(Store{}) }