2018-04-10 06:44:09 +00:00
|
|
|
package db
|
|
|
|
|
|
|
|
import (
|
2018-04-20 11:26:54 +00:00
|
|
|
"path/filepath"
|
|
|
|
|
2018-04-10 06:44:09 +00:00
|
|
|
"github.com/ethereum/go-ethereum/log"
|
|
|
|
"github.com/syndtr/goleveldb/leveldb"
|
|
|
|
"github.com/syndtr/goleveldb/leveldb/errors"
|
|
|
|
"github.com/syndtr/goleveldb/leveldb/opt"
|
2018-04-20 11:26:54 +00:00
|
|
|
"github.com/syndtr/goleveldb/leveldb/storage"
|
|
|
|
)
|
|
|
|
|
|
|
|
type storagePrefix byte
|
|
|
|
|
|
|
|
const (
|
|
|
|
// PeersCache is used for the db entries used for peers DB
|
|
|
|
PeersCache storagePrefix = iota
|
|
|
|
// DeduplicatorCache is used for the db entries used for messages
|
|
|
|
// deduplication cache
|
|
|
|
DeduplicatorCache
|
2018-12-12 09:39:00 +00:00
|
|
|
// MailserversCache is a list of mail servers provided by users.
|
|
|
|
MailserversCache
|
2018-04-10 06:44:09 +00:00
|
|
|
)
|
|
|
|
|
2018-04-20 11:26:54 +00:00
|
|
|
// Key creates a DB key for a specified service with specified data
|
|
|
|
func Key(prefix storagePrefix, data ...[]byte) []byte {
|
|
|
|
keyLength := 1
|
|
|
|
for _, d := range data {
|
|
|
|
keyLength += len(d)
|
|
|
|
}
|
|
|
|
key := make([]byte, keyLength)
|
|
|
|
key[0] = byte(prefix)
|
|
|
|
startPos := 1
|
|
|
|
for _, d := range data {
|
|
|
|
copy(key[startPos:], d[:])
|
|
|
|
startPos += len(d)
|
|
|
|
}
|
|
|
|
|
|
|
|
return key
|
|
|
|
}
|
|
|
|
|
2018-04-10 06:44:09 +00:00
|
|
|
// Create returns status pointer to leveldb.DB.
|
2018-04-20 11:26:54 +00:00
|
|
|
func Create(path, dbName string) (*leveldb.DB, error) {
|
|
|
|
// Create euphemeral storage if the node config path isn't provided
|
|
|
|
if path == "" {
|
|
|
|
return leveldb.Open(storage.NewMemStorage(), nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
path = filepath.Join(path, dbName)
|
2018-07-02 08:42:16 +00:00
|
|
|
return Open(path, &opt.Options{OpenFilesCacheCapacity: 5})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Open opens an existing leveldb database
|
|
|
|
func Open(path string, opts *opt.Options) (db *leveldb.DB, err error) {
|
|
|
|
db, err = leveldb.OpenFile(path, opts)
|
2018-04-10 06:44:09 +00:00
|
|
|
if _, iscorrupted := err.(*errors.ErrCorrupted); iscorrupted {
|
|
|
|
log.Info("database is corrupted trying to recover", "path", path)
|
|
|
|
db, err = leveldb.RecoverFile(path, nil)
|
|
|
|
}
|
2018-07-02 08:42:16 +00:00
|
|
|
return
|
2018-04-10 06:44:09 +00:00
|
|
|
}
|