refactor store, reduce code

This commit is contained in:
siddontang 2014-08-16 00:08:01 +08:00
parent 22161f91ba
commit 09e49ca346
30 changed files with 158 additions and 329 deletions

View File

@ -1,12 +1,12 @@
# LedisDB
Ledisdb is a high performance NoSQL like Redis written by go. It supports some advanced data structure like kv, list, hash, zset, bitmap,set, and may be alternative for Redis.
Ledisdb is a high performance NoSQL like Redis written by go. It supports some data structure like kv, list, hash, zset, bitmap,set, and may be alternative for Redis.
LedisDB now supports multiple databases as backend to store data, you can test and choose the proper one for you.
## Features
+ Rich advanced data structure: KV, List, Hash, ZSet, Bitmap, Set.
+ Rich data structure: KV, List, Hash, ZSet, Bitmap, Set.
+ Stores lots of data, over the memory limit.
+ Various backend database to use: LevelDB, goleveldb, LMDB, RocksDB, BoltDB, HyperLevelDB.
+ Supports expiration and ttl.

View File

@ -1,11 +0,0 @@
// +build !windows
package store
import (
"github.com/siddontang/ledisdb/store/boltdb"
)
func init() {
Register(boltdb.Store{})
}

3
store/boltdb/const.go Normal file
View File

@ -0,0 +1,3 @@
package boltdb
const DBName = "boltdb"

View File

@ -14,7 +14,7 @@ type Store struct {
}
func (s Store) String() string {
return "boltdb"
return DBName
}
func (s Store) Open(dbPath string, cfg *config.Config) (driver.IDB, error) {
@ -150,3 +150,7 @@ func (db *DB) BatchPut(writes []driver.Write) error {
})
return err
}
func init() {
driver.Register(Store{})
}

View File

@ -1,39 +0,0 @@
package store
import (
"github.com/siddontang/ledisdb/config"
"os"
"testing"
)
func newTestBoltDB() *DB {
cfg := new(config.Config)
cfg.DBName = "boltdb"
cfg.DataDir = "/tmp/testdb"
os.RemoveAll(getStorePath(cfg))
db, err := Open(cfg)
if err != nil {
println(err.Error())
panic(err)
}
return db
}
func TestBoltDB(t *testing.T) {
db := newTestBoltDB()
testStore(db, t)
db.Close()
}
func TestBoltDBTx(t *testing.T) {
db := newTestBoltDB()
testTx(db, t)
db.Close()
}

45
store/driver/store.go Normal file
View File

@ -0,0 +1,45 @@
package driver
import (
"fmt"
"github.com/siddontang/ledisdb/config"
)
type Store interface {
String() string
Open(path string, cfg *config.Config) (IDB, error)
Repair(paht string, cfg *config.Config) error
}
var dbs = map[string]Store{}
func Register(s Store) {
name := s.String()
if _, ok := dbs[name]; ok {
panic(fmt.Errorf("store %s is registered", s))
}
dbs[name] = s
}
func ListStores() []string {
s := []string{}
for k, _ := range dbs {
s = append(s, k)
}
return s
}
func GetStore(cfg *config.Config) (Store, error) {
if len(cfg.DBName) == 0 {
cfg.DBName = config.DefaultDBName
}
s, ok := dbs[cfg.DBName]
if !ok {
return nil, fmt.Errorf("store %s is not registered", cfg.DBName)
}
return s, nil
}

View File

@ -1,9 +0,0 @@
package store
import (
"github.com/siddontang/ledisdb/store/goleveldb"
)
func init() {
Register(goleveldb.Store{})
}

3
store/goleveldb/const.go Normal file
View File

@ -0,0 +1,3 @@
package goleveldb
const DBName = "goleveldb"

View File

@ -17,7 +17,7 @@ type Store struct {
}
func (s Store) String() string {
return "goleveldb"
return DBName
}
type DB struct {
@ -136,3 +136,7 @@ func (db *DB) NewIterator() driver.IIterator {
func (db *DB) Begin() (driver.Tx, error) {
return nil, driver.ErrTxSupport
}
func init() {
driver.Register(Store{})
}

View File

@ -1,32 +0,0 @@
package store
import (
"github.com/siddontang/ledisdb/config"
"os"
"testing"
)
func newTestGoLevelDB() *DB {
cfg := new(config.Config)
cfg.DBName = "goleveldb"
cfg.DataDir = "/tmp/testdb"
os.RemoveAll(getStorePath(cfg))
db, err := Open(cfg)
if err != nil {
println(err.Error())
panic(err)
}
return db
}
func TestGoLevelDB(t *testing.T) {
db := newTestGoLevelDB()
testStore(db, t)
db.Close()
}

View File

@ -1,11 +0,0 @@
// +build hyperleveldb
package store
import (
"github.com/siddontang/ledisdb/store/hyperleveldb"
)
func init() {
Register(hyperleveldb.Store{})
}

View File

@ -0,0 +1,3 @@
package hyperleveldb
const DBName = "hyperleveldb"

View File

@ -24,7 +24,7 @@ type Store struct {
}
func (s Store) String() string {
return "hyperleveldb"
return Name
}
func (s Store) Open(path string, cfg *config.Config) (driver.IDB, error) {
@ -257,3 +257,7 @@ func (db *DB) delete(wo *WriteOptions, key []byte) error {
func (db *DB) Begin() (driver.Tx, error) {
return nil, driver.ErrTxSupport
}
func init() {
driver.Register(Store{})
}

View File

@ -1,33 +0,0 @@
// +build hyperleveldb
package store
import (
"github.com/siddontang/ledisdb/config"
"os"
"testing"
)
func newTestHyperLevelDB() *DB {
cfg := new(config.Config)
cfg.DBName = "hyperleveldb"
cfg.DataDir = "/tmp/testdb"
os.RemoveAll(getStorePath(cfg))
db, err := Open(cfg)
if err != nil {
println(err.Error())
panic(err)
}
return db
}
func TestHyperLevelDB(t *testing.T) {
db := newTestHyperLevelDB()
testStore(db, t)
db.Close()
}

View File

@ -1,11 +0,0 @@
// +build leveldb
package store
import (
"github.com/siddontang/ledisdb/store/leveldb"
)
func init() {
Register(leveldb.Store{})
}

3
store/leveldb/const.go Normal file
View File

@ -0,0 +1,3 @@
package leveldb
const DBName = "leveldb"

View File

@ -24,7 +24,7 @@ type Store struct {
}
func (s Store) String() string {
return "leveldb"
return DBName
}
func (s Store) Open(path string, cfg *config.Config) (driver.IDB, error) {
@ -257,3 +257,7 @@ func (db *DB) delete(wo *WriteOptions, key []byte) error {
func (db *DB) Begin() (driver.Tx, error) {
return nil, driver.ErrTxSupport
}
func init() {
driver.Register(Store{})
}

View File

@ -1,34 +0,0 @@
// +build leveldb
package store
import (
"github.com/siddontang/ledisdb/config"
"os"
"testing"
)
func newTestLevelDB() *DB {
cfg := new(config.Config)
cfg.DBName = "leveldb"
cfg.DataDir = "/tmp/testdb"
os.RemoveAll(getStorePath(cfg))
db, err := Open(cfg)
if err != nil {
println(err.Error())
panic(err)
}
return db
}
func TestLevelDB(t *testing.T) {
db := newTestLevelDB()
testStore(db, t)
db.Close()
}

View File

@ -1,10 +0,0 @@
// +build !windows
package store
import (
"github.com/siddontang/ledisdb/store/mdb"
)
func init() {
Register(mdb.Store{})
}

3
store/mdb/const.go Normal file
View File

@ -0,0 +1,3 @@
package mdb
const DBName = "lmdb"

View File

@ -1,3 +1,5 @@
// +build !windows
package mdb
import (
@ -11,7 +13,7 @@ type Store struct {
}
func (s Store) String() string {
return "lmdb"
return DBName
}
type MDB struct {
@ -275,3 +277,7 @@ func (db MDB) NewWriteBatch() driver.IWriteBatch {
func (db MDB) Begin() (driver.Tx, error) {
return newTx(db)
}
func init() {
driver.Register(Store{})
}

View File

@ -1,3 +1,5 @@
// +build !windows
package mdb
import (

View File

@ -1,43 +0,0 @@
// +build !windows
package store
import (
"github.com/siddontang/ledisdb/config"
"os"
"testing"
)
func newTestLMDB() *DB {
cfg := new(config.Config)
cfg.DBName = "lmdb"
cfg.DataDir = "/tmp/testdb"
cfg.LMDB.MapSize = 10 * 1024 * 1024
os.RemoveAll(getStorePath(cfg))
db, err := Open(cfg)
if err != nil {
println(err.Error())
panic(err)
}
return db
}
func TestLMDB(t *testing.T) {
db := newTestLMDB()
testStore(db, t)
db.Close()
}
func TestLMDBTx(t *testing.T) {
db := newTestLMDB()
testTx(db, t)
db.Close()
}

View File

@ -1,11 +0,0 @@
// +build rocksdb
package store
import (
"github.com/siddontang/ledisdb/store/rocksdb"
)
func init() {
Register(rocksdb.Store{})
}

3
store/rocksdb/const.go Normal file
View File

@ -0,0 +1,3 @@
package rocksdb
const DBName = "rocksdb"

View File

@ -25,7 +25,7 @@ type Store struct {
}
func (s Store) String() string {
return "rocksdb"
return DBName
}
func (s Store) Open(path string, cfg *config.Config) (driver.IDB, error) {
@ -274,3 +274,7 @@ func (db *DB) delete(wo *WriteOptions, key []byte) error {
func (db *DB) Begin() (driver.Tx, error) {
return nil, driver.ErrTxSupport
}
func init() {
driver.Register(Store{})
}

View File

@ -1,34 +0,0 @@
// +build rocksdb
package store
import (
"github.com/siddontang/ledisdb/config"
"os"
"testing"
)
func newTestRocksDB() *DB {
cfg := new(config.Config)
cfg.DBName = "rocksdb"
cfg.DataDir = "/tmp/testdb"
os.RemoveAll(getStorePath(cfg))
db, err := Open(cfg)
if err != nil {
println(err.Error())
panic(err)
}
return db
}
func TestRocksDB(t *testing.T) {
db := newTestRocksDB()
testStore(db, t)
db.Close()
}

View File

@ -6,55 +6,21 @@ import (
"github.com/siddontang/ledisdb/store/driver"
"os"
"path"
"github.com/siddontang/ledisdb/store/boltdb"
"github.com/siddontang/ledisdb/store/goleveldb"
"github.com/siddontang/ledisdb/store/hyperleveldb"
"github.com/siddontang/ledisdb/store/leveldb"
"github.com/siddontang/ledisdb/store/mdb"
"github.com/siddontang/ledisdb/store/rocksdb"
)
type Config config.Config
type Store interface {
String() string
Open(path string, cfg *config.Config) (driver.IDB, error)
Repair(paht string, cfg *config.Config) error
}
var dbs = map[string]Store{}
func Register(s Store) {
name := s.String()
if _, ok := dbs[name]; ok {
panic(fmt.Errorf("store %s is registered", s))
}
dbs[name] = s
}
func ListStores() []string {
s := []string{}
for k, _ := range dbs {
s = append(s, k)
}
return s
}
func getStore(cfg *config.Config) (Store, error) {
if len(cfg.DBName) == 0 {
cfg.DBName = config.DefaultDBName
}
s, ok := dbs[cfg.DBName]
if !ok {
return nil, fmt.Errorf("store %s is not registered", cfg.DBName)
}
return s, nil
}
func getStorePath(cfg *config.Config) string {
return path.Join(cfg.DataDir, fmt.Sprintf("%s_data", cfg.DBName))
}
func Open(cfg *config.Config) (*DB, error) {
s, err := getStore(cfg)
s, err := driver.GetStore(cfg)
if err != nil {
return nil, err
}
@ -76,7 +42,7 @@ func Open(cfg *config.Config) (*DB, error) {
}
func Repair(cfg *config.Config) error {
s, err := getStore(cfg)
s, err := driver.GetStore(cfg)
if err != nil {
return err
}
@ -85,3 +51,12 @@ func Repair(cfg *config.Config) error {
return s.Repair(path, cfg)
}
func init() {
_ = boltdb.DBName
_ = goleveldb.DBName
_ = hyperleveldb.DBName
_ = leveldb.DBName
_ = mdb.DBName
_ = rocksdb.DBName
}

View File

@ -3,11 +3,34 @@ package store
import (
"bytes"
"fmt"
"github.com/siddontang/ledisdb/config"
"github.com/siddontang/ledisdb/store/driver"
"os"
"testing"
)
func TestStore(t *testing.T) {
cfg := new(config.Config)
cfg.DataDir = "/tmp/testdb"
cfg.LMDB.MapSize = 10 * 1024 * 1024
ns := driver.ListStores()
for _, s := range ns {
cfg.DBName = s
os.RemoveAll(getStorePath(cfg))
db, err := Open(cfg)
if err != nil {
t.Fatal(err)
}
testStore(db, t)
testClear(db, t)
testTx(db, t)
db.Close()
}
}
func testStore(db *DB, t *testing.T) {
@ -16,6 +39,13 @@ func testStore(db *DB, t *testing.T) {
testIterator(db, t)
}
func testClear(db *DB, t *testing.T) {
it := db.RangeIterator(nil, nil, RangeClose)
for ; it.Valid(); it.Next() {
db.Delete(it.RawKey())
}
}
func testSimple(db *DB, t *testing.T) {
key := []byte("key")
value := []byte("hello world")

View File

@ -1,6 +1,7 @@
package store
import (
"github.com/siddontang/ledisdb/store/driver"
"testing"
)
@ -9,6 +10,16 @@ func TestTx(t *testing.T) {
}
func testTx(db *DB, t *testing.T) {
if tx, err := db.Begin(); err != nil {
if err == driver.ErrTxSupport {
return
} else {
t.Fatal(err)
}
} else {
tx.Rollback()
}
key1 := []byte("1")
key2 := []byte("2")
key3 := []byte("3")