diff --git a/level_db2.go b/c_level_db.go similarity index 63% rename from level_db2.go rename to c_level_db.go index e3049aae3..638be41b1 100644 --- a/level_db2.go +++ b/c_level_db.go @@ -1,3 +1,5 @@ +// +build gcc + package db import ( @@ -9,15 +11,21 @@ import ( . "github.com/tendermint/go-common" ) -type LevelDB2 struct { +func init() { + registerDBCreator(CLevelDBBackendStr, func(name string, dir string) (DB, error) { + return NewCLevelDB(name, dir) + }, false) +} + +type CLevelDB struct { db *levigo.DB ro *levigo.ReadOptions wo *levigo.WriteOptions woSync *levigo.WriteOptions } -func NewLevelDB2(name string) (*LevelDB2, error) { - dbPath := path.Join(name) +func NewCLevelDB(name string, dir string) (*CLevelDB, error) { + dbPath := path.Join(dir, name+".db") opts := levigo.NewOptions() opts.SetCache(levigo.NewLRUCache(1 << 30)) @@ -30,7 +38,7 @@ func NewLevelDB2(name string) (*LevelDB2, error) { wo := levigo.NewWriteOptions() woSync := levigo.NewWriteOptions() woSync.SetSync(true) - database := &LevelDB2{ + database := &CLevelDB{ db: db, ro: ro, wo: wo, @@ -39,7 +47,7 @@ func NewLevelDB2(name string) (*LevelDB2, error) { return database, nil } -func (db *LevelDB2) Get(key []byte) []byte { +func (db *CLevelDB) Get(key []byte) []byte { res, err := db.db.Get(db.ro, key) if err != nil { PanicCrisis(err) @@ -47,46 +55,46 @@ func (db *LevelDB2) Get(key []byte) []byte { return res } -func (db *LevelDB2) Set(key []byte, value []byte) { +func (db *CLevelDB) Set(key []byte, value []byte) { err := db.db.Put(db.wo, key, value) if err != nil { PanicCrisis(err) } } -func (db *LevelDB2) SetSync(key []byte, value []byte) { +func (db *CLevelDB) SetSync(key []byte, value []byte) { err := db.db.Put(db.woSync, key, value) if err != nil { PanicCrisis(err) } } -func (db *LevelDB2) Delete(key []byte) { +func (db *CLevelDB) Delete(key []byte) { err := db.db.Delete(db.wo, key) if err != nil { PanicCrisis(err) } } -func (db *LevelDB2) DeleteSync(key []byte) { +func (db *CLevelDB) DeleteSync(key []byte) { err := db.db.Delete(db.woSync, key) if err != nil { PanicCrisis(err) } } -func (db *LevelDB2) DB() *levigo.DB { +func (db *CLevelDB) DB() *levigo.DB { return db.db } -func (db *LevelDB2) Close() { +func (db *CLevelDB) Close() { db.db.Close() db.ro.Close() db.wo.Close() db.woSync.Close() } -func (db *LevelDB2) Print() { +func (db *CLevelDB) Print() { iter := db.db.NewIterator(db.ro) defer iter.Close() for iter.Seek(nil); iter.Valid(); iter.Next() { @@ -96,27 +104,27 @@ func (db *LevelDB2) Print() { } } -func (db *LevelDB2) NewBatch() Batch { +func (db *CLevelDB) NewBatch() Batch { batch := levigo.NewWriteBatch() - return &levelDB2Batch{db, batch} + return &cLevelDBBatch{db, batch} } //-------------------------------------------------------------------------------- -type levelDB2Batch struct { - db *LevelDB2 +type cLevelDBBatch struct { + db *CLevelDB batch *levigo.WriteBatch } -func (mBatch *levelDB2Batch) Set(key, value []byte) { +func (mBatch *cLevelDBBatch) Set(key, value []byte) { mBatch.batch.Put(key, value) } -func (mBatch *levelDB2Batch) Delete(key []byte) { +func (mBatch *cLevelDBBatch) Delete(key []byte) { mBatch.batch.Delete(key) } -func (mBatch *levelDB2Batch) Write() { +func (mBatch *cLevelDBBatch) Write() { err := mBatch.db.db.Write(mBatch.db.wo, mBatch.batch) if err != nil { PanicCrisis(err) diff --git a/level_db2_test.go b/c_level_db_test.go similarity index 95% rename from level_db2_test.go rename to c_level_db_test.go index 27a558407..dbebcd902 100644 --- a/level_db2_test.go +++ b/c_level_db_test.go @@ -1,3 +1,5 @@ +// +build gcc + package db import ( @@ -16,7 +18,7 @@ func BenchmarkRandomReadsWrites2(b *testing.B) { for i := 0; i < int(numItems); i++ { internal[int64(i)] = int64(0) } - db, err := NewLevelDB2(Fmt("test_%x", RandStr(12))) + db, err := NewGoLevelDB(Fmt("test_%x", RandStr(12))) if err != nil { b.Fatal(err.Error()) return diff --git a/db.go b/db.go index ab38501e2..dac6df0cc 100644 --- a/db.go +++ b/db.go @@ -1,10 +1,6 @@ package db -import ( - "path" - - . "github.com/tendermint/go-common" -) +import . "github.com/tendermint/go-common" type DB interface { Get([]byte) []byte @@ -27,30 +23,28 @@ type Batch interface { //----------------------------------------------------------------------------- -// Database types -const DBBackendMemDB = "memdb" -const DBBackendLevelDB = "leveldb" -const DBBackendLevelDB2 = "leveldb2" +const ( + CLevelDBBackendStr = "goleveldb" + GoLevelDBBackendStr = "cleveldb" + MemDBBackendStr = "memdb" +) + +type dbCreator func(name string, dir string) (DB, error) + +var backends map[string]dbCreator + +func registerDBCreator(backend string, creator dbCreator, force bool) { + _, ok := backends[backend] + if !force && ok { + return + } + backends[backend] = creator +} func NewDB(name string, backend string, dir string) DB { - switch backend { - case DBBackendMemDB: - db := NewMemDB() - return db - case DBBackendLevelDB: - db, err := NewLevelDB(path.Join(dir, name+".db")) - if err != nil { - PanicCrisis(err) - } - return db - case DBBackendLevelDB2: - db, err := NewLevelDB2(path.Join(dir, name+".db")) - if err != nil { - PanicCrisis(err) - } - return db - default: - PanicSanity(Fmt("Unknown DB backend: %v", backend)) + db, err := backends[backend](name, dir) + if err != nil { + PanicSanity(Fmt("Error initializing DB: %v", err)) } - return nil + return db } diff --git a/level_db.go b/go_level_db.go similarity index 58% rename from level_db.go rename to go_level_db.go index 360362285..73c307b24 100644 --- a/level_db.go +++ b/go_level_db.go @@ -11,21 +11,27 @@ import ( . "github.com/tendermint/go-common" ) -type LevelDB struct { +func init() { + registerDBCreator(GoLevelDBBackendStr, func(name string, dir string) (DB, error) { + return NewGoLevelDB(name, dir) + }, false) +} + +type GoLevelDB struct { db *leveldb.DB } -func NewLevelDB(name string) (*LevelDB, error) { - dbPath := path.Join(name) +func NewGoLevelDB(name string, dir string) (*GoLevelDB, error) { + dbPath := path.Join(dir, name+".db") db, err := leveldb.OpenFile(dbPath, nil) if err != nil { return nil, err } - database := &LevelDB{db: db} + database := &GoLevelDB{db: db} return database, nil } -func (db *LevelDB) Get(key []byte) []byte { +func (db *GoLevelDB) Get(key []byte) []byte { res, err := db.db.Get(key, nil) if err != nil { if err == errors.ErrNotFound { @@ -37,43 +43,43 @@ func (db *LevelDB) Get(key []byte) []byte { return res } -func (db *LevelDB) Set(key []byte, value []byte) { +func (db *GoLevelDB) Set(key []byte, value []byte) { err := db.db.Put(key, value, nil) if err != nil { PanicCrisis(err) } } -func (db *LevelDB) SetSync(key []byte, value []byte) { +func (db *GoLevelDB) SetSync(key []byte, value []byte) { err := db.db.Put(key, value, &opt.WriteOptions{Sync: true}) if err != nil { PanicCrisis(err) } } -func (db *LevelDB) Delete(key []byte) { +func (db *GoLevelDB) Delete(key []byte) { err := db.db.Delete(key, nil) if err != nil { PanicCrisis(err) } } -func (db *LevelDB) DeleteSync(key []byte) { +func (db *GoLevelDB) DeleteSync(key []byte) { err := db.db.Delete(key, &opt.WriteOptions{Sync: true}) if err != nil { PanicCrisis(err) } } -func (db *LevelDB) DB() *leveldb.DB { +func (db *GoLevelDB) DB() *leveldb.DB { return db.db } -func (db *LevelDB) Close() { +func (db *GoLevelDB) Close() { db.db.Close() } -func (db *LevelDB) Print() { +func (db *GoLevelDB) Print() { iter := db.db.NewIterator(nil, nil) for iter.Next() { key := iter.Key() @@ -82,27 +88,27 @@ func (db *LevelDB) Print() { } } -func (db *LevelDB) NewBatch() Batch { +func (db *GoLevelDB) NewBatch() Batch { batch := new(leveldb.Batch) - return &levelDBBatch{db, batch} + return &goLevelDBBatch{db, batch} } //-------------------------------------------------------------------------------- -type levelDBBatch struct { - db *LevelDB +type goLevelDBBatch struct { + db *GoLevelDB batch *leveldb.Batch } -func (mBatch *levelDBBatch) Set(key, value []byte) { +func (mBatch *goLevelDBBatch) Set(key, value []byte) { mBatch.batch.Put(key, value) } -func (mBatch *levelDBBatch) Delete(key []byte) { +func (mBatch *goLevelDBBatch) Delete(key []byte) { mBatch.batch.Delete(key) } -func (mBatch *levelDBBatch) Write() { +func (mBatch *goLevelDBBatch) Write() { err := mBatch.db.db.Write(mBatch.batch, nil) if err != nil { PanicCrisis(err) diff --git a/level_db_test.go b/go_level_db_test.go similarity index 96% rename from level_db_test.go rename to go_level_db_test.go index 2a8e9ac1e..b7fe07bd7 100644 --- a/level_db_test.go +++ b/go_level_db_test.go @@ -17,7 +17,7 @@ func BenchmarkRandomReadsWrites(b *testing.B) { for i := 0; i < int(numItems); i++ { internal[int64(i)] = int64(0) } - db, err := NewLevelDB(Fmt("test_%x", RandStr(12))) + db, err := NewCLevelDB(Fmt("test_%x", RandStr(12))) if err != nil { b.Fatal(err.Error()) return diff --git a/mem_db.go b/mem_db.go index d27159dab..eb1e54b56 100644 --- a/mem_db.go +++ b/mem_db.go @@ -5,6 +5,12 @@ import ( "sync" ) +func init() { + registerDBCreator(MemDBBackendStr, func(name string, dir string) (DB, error) { + return NewMemDB(), nil + }, false) +} + type MemDB struct { mtx sync.Mutex db map[string][]byte