storage/leveldb.go

76 lines
1.6 KiB
Go

package storage
import (
"path"
"github.com/syndtr/goleveldb/leveldb"
"github.com/syndtr/goleveldb/leveldb/filter"
"github.com/syndtr/goleveldb/leveldb/opt"
"github.com/syndtr/goleveldb/leveldb/util"
)
type LevelDB struct {
db *leveldb.DB
}
func NewLevelDB(path string) (*LevelDB, error) {
db, err := leveldb.OpenFile(path, &opt.Options{
Filter: filter.NewBloomFilter(32),
})
return &LevelDB{
db: db,
}, err
}
func (ldb *LevelDB) List(ns []string, limits ...string) ([]string, error) {
namespace := resolveNamespace(ns)
limits = resolveLimits(limits)
limits[0] = path.Join(namespace, limits[0])
limits[1] = path.Join(namespace, limits[1])
keys := []string{}
r := util.BytesPrefix([]byte(namespace))
it := ldb.db.NewIterator(r, nil)
defer it.Release()
for it.Next() {
k := string(it.Key())
if k < limits[0] {
continue
} else if k > limits[1] {
break
}
keys = append(keys, k)
}
err := it.Error()
return keys, err
}
func (ldb *LevelDB) Get(key string, ns ...string) ([]byte, error) {
namespace := resolveNamespace(ns)
snapshot, err := ldb.db.GetSnapshot()
if err != nil {
return nil, err
}
defer snapshot.Release()
v, err := snapshot.Get([]byte(path.Join(namespace, key)), nil)
if err == leveldb.ErrNotFound {
err = ErrNotFound
} else if err != nil {
return nil, err
}
return v, err
}
func (ldb *LevelDB) Set(key string, value []byte, ns ...string) error {
namespace := resolveNamespace(ns)
batch := &leveldb.Batch{}
batch.Put([]byte(path.Join(namespace, key)), value)
return ldb.db.Write(batch, nil)
}
func (ldb *LevelDB) Close() error {
return ldb.db.Close()
}