mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-25 13:56:35 +00:00
ddd1d92ff1
The idea here is to preserve the history of `dev` branch development and its code when merging with the `master`. Later this code could be moved into the masters code where appropriate.
114 lines
2.6 KiB
Go
114 lines
2.6 KiB
Go
package database
|
|
|
|
import (
|
|
"github.com/syndtr/goleveldb/leveldb"
|
|
"github.com/syndtr/goleveldb/leveldb/errors"
|
|
ldbutil "github.com/syndtr/goleveldb/leveldb/util"
|
|
)
|
|
|
|
//DbDir is the folder which all database files will be put under
|
|
// Structure /DbDir/net
|
|
const DbDir = "db/"
|
|
|
|
// LDB represents a leveldb object
|
|
type LDB struct {
|
|
db *leveldb.DB
|
|
Path string
|
|
}
|
|
|
|
// ErrNotFound means that the value was not found in the db
|
|
var ErrNotFound = errors.New("value not found for that key")
|
|
|
|
// Database contains all methods needed for an object to be a database
|
|
type Database interface {
|
|
// Has checks whether the key is in the database
|
|
Has(key []byte) (bool, error)
|
|
// Put adds the key value pair into the pair
|
|
Put(key []byte, value []byte) error
|
|
// Get returns the value for the given key
|
|
Get(key []byte) ([]byte, error)
|
|
// Delete deletes the given value for the key from the database
|
|
Delete(key []byte) error
|
|
//Prefix returns all values that start with key
|
|
Prefix(key []byte) ([][]byte, error)
|
|
// Close closes the underlying db object
|
|
Close() error
|
|
}
|
|
|
|
// New will return a new leveldb instance
|
|
func New(path string) (*LDB, error) {
|
|
dbPath := DbDir + path
|
|
db, err := leveldb.OpenFile(dbPath, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if _, corrupted := err.(*errors.ErrCorrupted); corrupted {
|
|
db, err = leveldb.RecoverFile(path, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return &LDB{
|
|
db,
|
|
dbPath,
|
|
}, nil
|
|
}
|
|
|
|
// Has implements the database interface
|
|
func (l *LDB) Has(key []byte) (bool, error) {
|
|
return l.db.Has(key, nil)
|
|
}
|
|
|
|
// Put implements the database interface
|
|
func (l *LDB) Put(key []byte, value []byte) error {
|
|
return l.db.Put(key, value, nil)
|
|
}
|
|
|
|
// Get implements the database interface
|
|
func (l *LDB) Get(key []byte) ([]byte, error) {
|
|
val, err := l.db.Get(key, nil)
|
|
if err == nil {
|
|
return val, nil
|
|
}
|
|
if err == leveldb.ErrNotFound {
|
|
return val, ErrNotFound
|
|
}
|
|
return val, err
|
|
|
|
}
|
|
|
|
// Delete implements the database interface
|
|
func (l *LDB) Delete(key []byte) error {
|
|
return l.db.Delete(key, nil)
|
|
}
|
|
|
|
// Close implements the database interface
|
|
func (l *LDB) Close() error {
|
|
return l.db.Close()
|
|
}
|
|
|
|
// Prefix implements the database interface
|
|
func (l *LDB) Prefix(key []byte) ([][]byte, error) {
|
|
|
|
var results [][]byte
|
|
|
|
iter := l.db.NewIterator(ldbutil.BytesPrefix(key), nil)
|
|
for iter.Next() {
|
|
|
|
value := iter.Value()
|
|
|
|
// Copy the data, as we cannot modify it
|
|
// Once the iter has been released
|
|
deref := make([]byte, len(value))
|
|
|
|
copy(deref, value)
|
|
|
|
// Append result
|
|
results = append(results, deref)
|
|
|
|
}
|
|
iter.Release()
|
|
err := iter.Error()
|
|
return results, err
|
|
}
|