Version the leveldb (and keep compatibility with pre-versioned uncompressed databases.

This commit is contained in:
Dale Rahn 2013-09-25 16:18:35 -04:00
parent 0e98349c98
commit 3640f6d37c
5 changed files with 72 additions and 2 deletions

View file

@ -16,13 +16,16 @@ import (
func TestEmptyDB(t *testing.T) {
dbname := "tstdbempty"
dbnamever := dbname + ".ver"
_ = os.RemoveAll(dbname)
_ = os.RemoveAll(dbnamever)
db, err := btcdb.CreateDB("leveldb", dbname)
if err != nil {
t.Errorf("Failed to open test database %v", err)
return
}
defer os.RemoveAll(dbname)
defer os.RemoveAll(dbnamever)
sha, height, err := db.NewestSha()
if !sha.IsEqual(&btcwire.ShaHash{}) {

View file

@ -11,5 +11,12 @@ The performance is generally high although it goes down with database
size.
Many of the block or tx specific functions for btcdb are in this subpackage.
Database version number is stored in a flat file <dbname>.ver
Currently a single (littlendian) integer in the file. If there is
additional data to save in the future, the presense of additional
data can be indicated by changing the version number, then parsing the
file differently.
*/
package ldb

View file

@ -46,13 +46,16 @@ func TestUnspentInsert(t *testing.T) {
func testUnspentInsert(t *testing.T, mode int) {
// Ignore db remove errors since it means we didn't have an old one.
dbname := fmt.Sprintf("tstdbuspnt1.%d", mode)
dbnamever := dbname + ".ver"
_ = os.RemoveAll(dbname)
_ = os.RemoveAll(dbnamever)
db, err := btcdb.CreateDB("leveldb", dbname)
if err != nil {
t.Errorf("Failed to open test database %v", err)
return
}
defer os.RemoveAll(dbname)
defer os.RemoveAll(dbnamever)
defer db.Close()
switch mode {

View file

@ -5,6 +5,7 @@
package ldb
import (
"encoding/binary"
"fmt"
"github.com/conformal/btcdb"
"github.com/conformal/btcutil"
@ -129,9 +130,13 @@ blocknarrow:
return db, nil
}
var CurrentDBVersion int32 = 1
func openDB(dbpath string, flag opt.OptionsFlag) (pbdb btcdb.Db, err error) {
var db LevelDb
var tlDb *leveldb.DB
var dbversion int32
defer func() {
if err == nil {
db.lDb = tlDb
@ -156,14 +161,60 @@ func openDB(dbpath string, flag opt.OptionsFlag) (pbdb btcdb.Db, err error) {
}
}
tlDb, err = leveldb.OpenFile(dbpath, &opt.Options{Flag: flag,
needVersionFile := false
verfile := dbpath + ".ver"
fi, ferr := os.Open(verfile)
if ferr == nil {
defer fi.Close()
ferr = binary.Read(fi, binary.LittleEndian, &dbversion)
if ferr != nil {
dbversion = ^0
}
} else {
if flag&opt.OFCreateIfMissing != 0 {
needVersionFile = true
}
}
opts := &opt.Options{Flag: flag,
BlockCache: cache.EmptyCache{},
MaxOpenFiles: 256,
CompressionType: opt.NoCompression})
CompressionType: opt.NoCompression,
}
switch dbversion {
case 0:
opts = &opt.Options{Flag: flag}
case 1:
// uses defaults from above
default:
err = fmt.Errorf("unsupported db version %v", dbversion)
return
}
tlDb, err = leveldb.OpenFile(dbpath, opts)
if err != nil {
return
}
// If we opened the database successfully on 'create'
// update the
if needVersionFile {
fo, ferr := os.Create(verfile)
if ferr != nil {
// TODO(design) close and delete database?
err = ferr
return
}
defer fo.Close()
dbversion = CurrentDBVersion
err = binary.Write(fo, binary.LittleEndian, dbversion)
if err != nil {
return
}
}
return
}

View file

@ -42,13 +42,16 @@ func testOperationalMode(t *testing.T, mode int) {
// Ignore db remove errors since it means we didn't have an old one.
dbname := fmt.Sprintf("tstdbop1.%d", mode)
dbnamever := dbname + ".ver"
_ = os.RemoveAll(dbname)
_ = os.RemoveAll(dbnamever)
db, err := btcdb.CreateDB("leveldb", dbname)
if err != nil {
t.Errorf("Failed to open test database %v", err)
return
}
defer os.RemoveAll(dbname)
defer os.RemoveAll(dbnamever)
defer db.Close()
switch mode {
@ -177,13 +180,16 @@ func testBackout(t *testing.T, mode int) {
t.Logf("mode %v", mode)
// Ignore db remove errors since it means we didn't have an old one.
dbname := fmt.Sprintf("tstdbop2.%d", mode)
dbnamever := dbname + ".ver"
_ = os.RemoveAll(dbname)
_ = os.RemoveAll(dbnamever)
db, err := btcdb.CreateDB("leveldb", dbname)
if err != nil {
t.Errorf("Failed to open test database %v", err)
return
}
defer os.RemoveAll(dbname)
defer os.RemoveAll(dbnamever)
defer db.Close()
switch mode {