package storage import ( "path" "strings" "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) namespace = path.Join(namespace) 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 } k = strings.TrimPrefix(k, namespace+"/") 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() }