aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/lunny/nodb/store
diff options
context:
space:
mode:
authortechknowlogick <matti@mdranta.net>2019-02-05 11:52:51 -0500
committerGitHub <noreply@github.com>2019-02-05 11:52:51 -0500
commit9de871a0f8911030f8e06a881803cf722b8798ea (patch)
tree206400f0a5873d7d078fcdd004956036f07a1db5 /vendor/github.com/lunny/nodb/store
parentbf4badad1d68c18d7ffb92c69e09e4e8aa252935 (diff)
downloadgitea-9de871a0f8911030f8e06a881803cf722b8798ea.tar.gz
gitea-9de871a0f8911030f8e06a881803cf722b8798ea.zip
add other session providers (#5963)
Diffstat (limited to 'vendor/github.com/lunny/nodb/store')
-rw-r--r--vendor/github.com/lunny/nodb/store/db.go61
-rw-r--r--vendor/github.com/lunny/nodb/store/driver/batch.go39
-rw-r--r--vendor/github.com/lunny/nodb/store/driver/driver.go67
-rw-r--r--vendor/github.com/lunny/nodb/store/driver/store.go46
-rw-r--r--vendor/github.com/lunny/nodb/store/goleveldb/batch.go27
-rw-r--r--vendor/github.com/lunny/nodb/store/goleveldb/const.go4
-rw-r--r--vendor/github.com/lunny/nodb/store/goleveldb/db.go187
-rw-r--r--vendor/github.com/lunny/nodb/store/goleveldb/iterator.go49
-rw-r--r--vendor/github.com/lunny/nodb/store/goleveldb/snapshot.go26
-rw-r--r--vendor/github.com/lunny/nodb/store/iterator.go327
-rw-r--r--vendor/github.com/lunny/nodb/store/snapshot.go16
-rw-r--r--vendor/github.com/lunny/nodb/store/store.go51
-rw-r--r--vendor/github.com/lunny/nodb/store/tx.go42
-rw-r--r--vendor/github.com/lunny/nodb/store/writebatch.go9
14 files changed, 951 insertions, 0 deletions
diff --git a/vendor/github.com/lunny/nodb/store/db.go b/vendor/github.com/lunny/nodb/store/db.go
new file mode 100644
index 0000000000..00a8831a67
--- /dev/null
+++ b/vendor/github.com/lunny/nodb/store/db.go
@@ -0,0 +1,61 @@
+package store
+
+import (
+ "github.com/lunny/nodb/store/driver"
+)
+
+type DB struct {
+ driver.IDB
+}
+
+func (db *DB) NewIterator() *Iterator {
+ it := new(Iterator)
+ it.it = db.IDB.NewIterator()
+
+ return it
+}
+
+func (db *DB) NewWriteBatch() WriteBatch {
+ return db.IDB.NewWriteBatch()
+}
+
+func (db *DB) NewSnapshot() (*Snapshot, error) {
+ var err error
+ s := &Snapshot{}
+ if s.ISnapshot, err = db.IDB.NewSnapshot(); err != nil {
+ return nil, err
+ }
+
+ return s, nil
+}
+
+func (db *DB) RangeIterator(min []byte, max []byte, rangeType uint8) *RangeLimitIterator {
+ return NewRangeLimitIterator(db.NewIterator(), &Range{min, max, rangeType}, &Limit{0, -1})
+}
+
+func (db *DB) RevRangeIterator(min []byte, max []byte, rangeType uint8) *RangeLimitIterator {
+ return NewRevRangeLimitIterator(db.NewIterator(), &Range{min, max, rangeType}, &Limit{0, -1})
+}
+
+//count < 0, unlimit.
+//
+//offset must >= 0, if < 0, will get nothing.
+func (db *DB) RangeLimitIterator(min []byte, max []byte, rangeType uint8, offset int, count int) *RangeLimitIterator {
+ return NewRangeLimitIterator(db.NewIterator(), &Range{min, max, rangeType}, &Limit{offset, count})
+}
+
+//count < 0, unlimit.
+//
+//offset must >= 0, if < 0, will get nothing.
+func (db *DB) RevRangeLimitIterator(min []byte, max []byte, rangeType uint8, offset int, count int) *RangeLimitIterator {
+ return NewRevRangeLimitIterator(db.NewIterator(), &Range{min, max, rangeType}, &Limit{offset, count})
+}
+
+func (db *DB) Begin() (*Tx, error) {
+ tx, err := db.IDB.Begin()
+ if err != nil {
+ return nil, err
+ }
+
+ return &Tx{tx}, nil
+}
diff --git a/vendor/github.com/lunny/nodb/store/driver/batch.go b/vendor/github.com/lunny/nodb/store/driver/batch.go
new file mode 100644
index 0000000000..6b79c21c48
--- /dev/null
+++ b/vendor/github.com/lunny/nodb/store/driver/batch.go
@@ -0,0 +1,39 @@
+package driver
+
+type BatchPuter interface {
+ BatchPut([]Write) error
+}
+
+type Write struct {
+ Key []byte
+ Value []byte
+}
+
+type WriteBatch struct {
+ batch BatchPuter
+ wb []Write
+}
+
+func (w *WriteBatch) Put(key, value []byte) {
+ if value == nil {
+ value = []byte{}
+ }
+ w.wb = append(w.wb, Write{key, value})
+}
+
+func (w *WriteBatch) Delete(key []byte) {
+ w.wb = append(w.wb, Write{key, nil})
+}
+
+func (w *WriteBatch) Commit() error {
+ return w.batch.BatchPut(w.wb)
+}
+
+func (w *WriteBatch) Rollback() error {
+ w.wb = w.wb[0:0]
+ return nil
+}
+
+func NewWriteBatch(puter BatchPuter) IWriteBatch {
+ return &WriteBatch{puter, []Write{}}
+}
diff --git a/vendor/github.com/lunny/nodb/store/driver/driver.go b/vendor/github.com/lunny/nodb/store/driver/driver.go
new file mode 100644
index 0000000000..6da67df083
--- /dev/null
+++ b/vendor/github.com/lunny/nodb/store/driver/driver.go
@@ -0,0 +1,67 @@
+package driver
+
+import (
+ "errors"
+)
+
+var (
+ ErrTxSupport = errors.New("transaction is not supported")
+)
+
+type IDB interface {
+ Close() error
+
+ Get(key []byte) ([]byte, error)
+
+ Put(key []byte, value []byte) error
+ Delete(key []byte) error
+
+ NewIterator() IIterator
+
+ NewWriteBatch() IWriteBatch
+
+ NewSnapshot() (ISnapshot, error)
+
+ Begin() (Tx, error)
+}
+
+type ISnapshot interface {
+ Get(key []byte) ([]byte, error)
+ NewIterator() IIterator
+ Close()
+}
+
+type IIterator interface {
+ Close() error
+
+ First()
+ Last()
+ Seek(key []byte)
+
+ Next()
+ Prev()
+
+ Valid() bool
+
+ Key() []byte
+ Value() []byte
+}
+
+type IWriteBatch interface {
+ Put(key []byte, value []byte)
+ Delete(key []byte)
+ Commit() error
+ Rollback() error
+}
+
+type Tx interface {
+ Get(key []byte) ([]byte, error)
+ Put(key []byte, value []byte) error
+ Delete(key []byte) error
+
+ NewIterator() IIterator
+ NewWriteBatch() IWriteBatch
+
+ Commit() error
+ Rollback() error
+}
diff --git a/vendor/github.com/lunny/nodb/store/driver/store.go b/vendor/github.com/lunny/nodb/store/driver/store.go
new file mode 100644
index 0000000000..173431d4c1
--- /dev/null
+++ b/vendor/github.com/lunny/nodb/store/driver/store.go
@@ -0,0 +1,46 @@
+package driver
+
+import (
+ "fmt"
+
+ "github.com/lunny/nodb/config"
+)
+
+type Store interface {
+ String() string
+ Open(path string, cfg *config.Config) (IDB, error)
+ Repair(path string, cfg *config.Config) error
+}
+
+var dbs = map[string]Store{}
+
+func Register(s Store) {
+ name := s.String()
+ if _, ok := dbs[name]; ok {
+ panic(fmt.Errorf("store %s is registered", s))
+ }
+
+ dbs[name] = s
+}
+
+func ListStores() []string {
+ s := []string{}
+ for k, _ := range dbs {
+ s = append(s, k)
+ }
+
+ return s
+}
+
+func GetStore(cfg *config.Config) (Store, error) {
+ if len(cfg.DBName) == 0 {
+ cfg.DBName = config.DefaultDBName
+ }
+
+ s, ok := dbs[cfg.DBName]
+ if !ok {
+ return nil, fmt.Errorf("store %s is not registered", cfg.DBName)
+ }
+
+ return s, nil
+}
diff --git a/vendor/github.com/lunny/nodb/store/goleveldb/batch.go b/vendor/github.com/lunny/nodb/store/goleveldb/batch.go
new file mode 100644
index 0000000000..b17e85e750
--- /dev/null
+++ b/vendor/github.com/lunny/nodb/store/goleveldb/batch.go
@@ -0,0 +1,27 @@
+package goleveldb
+
+import (
+ "github.com/syndtr/goleveldb/leveldb"
+)
+
+type WriteBatch struct {
+ db *DB
+ wbatch *leveldb.Batch
+}
+
+func (w *WriteBatch) Put(key, value []byte) {
+ w.wbatch.Put(key, value)
+}
+
+func (w *WriteBatch) Delete(key []byte) {
+ w.wbatch.Delete(key)
+}
+
+func (w *WriteBatch) Commit() error {
+ return w.db.db.Write(w.wbatch, nil)
+}
+
+func (w *WriteBatch) Rollback() error {
+ w.wbatch.Reset()
+ return nil
+}
diff --git a/vendor/github.com/lunny/nodb/store/goleveldb/const.go b/vendor/github.com/lunny/nodb/store/goleveldb/const.go
new file mode 100644
index 0000000000..2fffa7c82b
--- /dev/null
+++ b/vendor/github.com/lunny/nodb/store/goleveldb/const.go
@@ -0,0 +1,4 @@
+package goleveldb
+
+const DBName = "goleveldb"
+const MemDBName = "memory"
diff --git a/vendor/github.com/lunny/nodb/store/goleveldb/db.go b/vendor/github.com/lunny/nodb/store/goleveldb/db.go
new file mode 100644
index 0000000000..a36e87f628
--- /dev/null
+++ b/vendor/github.com/lunny/nodb/store/goleveldb/db.go
@@ -0,0 +1,187 @@
+package goleveldb
+
+import (
+ "github.com/syndtr/goleveldb/leveldb"
+ "github.com/syndtr/goleveldb/leveldb/cache"
+ "github.com/syndtr/goleveldb/leveldb/filter"
+ "github.com/syndtr/goleveldb/leveldb/opt"
+ "github.com/syndtr/goleveldb/leveldb/storage"
+
+ "github.com/lunny/nodb/config"
+ "github.com/lunny/nodb/store/driver"
+
+ "os"
+)
+
+const defaultFilterBits int = 10
+
+type Store struct {
+}
+
+func (s Store) String() string {
+ return DBName
+}
+
+type MemStore struct {
+}
+
+func (s MemStore) String() string {
+ return MemDBName
+}
+
+type DB struct {
+ path string
+
+ cfg *config.LevelDBConfig
+
+ db *leveldb.DB
+
+ opts *opt.Options
+
+ iteratorOpts *opt.ReadOptions
+
+ cache cache.Cache
+
+ filter filter.Filter
+}
+
+func (s Store) Open(path string, cfg *config.Config) (driver.IDB, error) {
+ if err := os.MkdirAll(path, os.ModePerm); err != nil {
+ return nil, err
+ }
+
+ db := new(DB)
+ db.path = path
+ db.cfg = &cfg.LevelDB
+
+ db.initOpts()
+
+ var err error
+ db.db, err = leveldb.OpenFile(db.path, db.opts)
+
+ if err != nil {
+ return nil, err
+ }
+
+ return db, nil
+}
+
+func (s Store) Repair(path string, cfg *config.Config) error {
+ db, err := leveldb.RecoverFile(path, newOptions(&cfg.LevelDB))
+ if err != nil {
+ return err
+ }
+
+ db.Close()
+ return nil
+}
+
+func (s MemStore) Open(path string, cfg *config.Config) (driver.IDB, error) {
+ db := new(DB)
+ db.path = path
+ db.cfg = &cfg.LevelDB
+
+ db.initOpts()
+
+ var err error
+ db.db, err = leveldb.Open(storage.NewMemStorage(), db.opts)
+ if err != nil {
+ return nil, err
+ }
+
+ return db, nil
+}
+
+func (s MemStore) Repair(path string, cfg *config.Config) error {
+ return nil
+}
+
+func (db *DB) initOpts() {
+ db.opts = newOptions(db.cfg)
+
+ db.iteratorOpts = &opt.ReadOptions{}
+ db.iteratorOpts.DontFillCache = true
+}
+
+func newOptions(cfg *config.LevelDBConfig) *opt.Options {
+ opts := &opt.Options{}
+ opts.ErrorIfMissing = false
+
+ cfg.Adjust()
+
+ //opts.BlockCacher = cache.NewLRU(cfg.CacheSize)
+ opts.BlockCacheCapacity = cfg.CacheSize
+
+ //we must use bloomfilter
+ opts.Filter = filter.NewBloomFilter(defaultFilterBits)
+
+ if !cfg.Compression {
+ opts.Compression = opt.NoCompression
+ } else {
+ opts.Compression = opt.SnappyCompression
+ }
+
+ opts.BlockSize = cfg.BlockSize
+ opts.WriteBuffer = cfg.WriteBufferSize
+
+ return opts
+}
+
+func (db *DB) Close() error {
+ return db.db.Close()
+}
+
+func (db *DB) Put(key, value []byte) error {
+ return db.db.Put(key, value, nil)
+}
+
+func (db *DB) Get(key []byte) ([]byte, error) {
+ v, err := db.db.Get(key, nil)
+ if err == leveldb.ErrNotFound {
+ return nil, nil
+ }
+ return v, nil
+}
+
+func (db *DB) Delete(key []byte) error {
+ return db.db.Delete(key, nil)
+}
+
+func (db *DB) NewWriteBatch() driver.IWriteBatch {
+ wb := &WriteBatch{
+ db: db,
+ wbatch: new(leveldb.Batch),
+ }
+ return wb
+}
+
+func (db *DB) NewIterator() driver.IIterator {
+ it := &Iterator{
+ db.db.NewIterator(nil, db.iteratorOpts),
+ }
+
+ return it
+}
+
+func (db *DB) Begin() (driver.Tx, error) {
+ return nil, driver.ErrTxSupport
+}
+
+func (db *DB) NewSnapshot() (driver.ISnapshot, error) {
+ snapshot, err := db.db.GetSnapshot()
+ if err != nil {
+ return nil, err
+ }
+
+ s := &Snapshot{
+ db: db,
+ snp: snapshot,
+ }
+
+ return s, nil
+}
+
+func init() {
+ driver.Register(Store{})
+ driver.Register(MemStore{})
+}
diff --git a/vendor/github.com/lunny/nodb/store/goleveldb/iterator.go b/vendor/github.com/lunny/nodb/store/goleveldb/iterator.go
new file mode 100644
index 0000000000..c1fd8b5573
--- /dev/null
+++ b/vendor/github.com/lunny/nodb/store/goleveldb/iterator.go
@@ -0,0 +1,49 @@
+package goleveldb
+
+import (
+ "github.com/syndtr/goleveldb/leveldb/iterator"
+)
+
+type Iterator struct {
+ it iterator.Iterator
+}
+
+func (it *Iterator) Key() []byte {
+ return it.it.Key()
+}
+
+func (it *Iterator) Value() []byte {
+ return it.it.Value()
+}
+
+func (it *Iterator) Close() error {
+ if it.it != nil {
+ it.it.Release()
+ it.it = nil
+ }
+ return nil
+}
+
+func (it *Iterator) Valid() bool {
+ return it.it.Valid()
+}
+
+func (it *Iterator) Next() {
+ it.it.Next()
+}
+
+func (it *Iterator) Prev() {
+ it.it.Prev()
+}
+
+func (it *Iterator) First() {
+ it.it.First()
+}
+
+func (it *Iterator) Last() {
+ it.it.Last()
+}
+
+func (it *Iterator) Seek(key []byte) {
+ it.it.Seek(key)
+}
diff --git a/vendor/github.com/lunny/nodb/store/goleveldb/snapshot.go b/vendor/github.com/lunny/nodb/store/goleveldb/snapshot.go
new file mode 100644
index 0000000000..fe2b409c3f
--- /dev/null
+++ b/vendor/github.com/lunny/nodb/store/goleveldb/snapshot.go
@@ -0,0 +1,26 @@
+package goleveldb
+
+import (
+ "github.com/lunny/nodb/store/driver"
+ "github.com/syndtr/goleveldb/leveldb"
+)
+
+type Snapshot struct {
+ db *DB
+ snp *leveldb.Snapshot
+}
+
+func (s *Snapshot) Get(key []byte) ([]byte, error) {
+ return s.snp.Get(key, s.db.iteratorOpts)
+}
+
+func (s *Snapshot) NewIterator() driver.IIterator {
+ it := &Iterator{
+ s.snp.NewIterator(nil, s.db.iteratorOpts),
+ }
+ return it
+}
+
+func (s *Snapshot) Close() {
+ s.snp.Release()
+}
diff --git a/vendor/github.com/lunny/nodb/store/iterator.go b/vendor/github.com/lunny/nodb/store/iterator.go
new file mode 100644
index 0000000000..27bf689da2
--- /dev/null
+++ b/vendor/github.com/lunny/nodb/store/iterator.go
@@ -0,0 +1,327 @@
+package store
+
+import (
+ "bytes"
+
+ "github.com/lunny/nodb/store/driver"
+)
+
+const (
+ IteratorForward uint8 = 0
+ IteratorBackward uint8 = 1
+)
+
+const (
+ RangeClose uint8 = 0x00
+ RangeLOpen uint8 = 0x01
+ RangeROpen uint8 = 0x10
+ RangeOpen uint8 = 0x11
+)
+
+// min must less or equal than max
+//
+// range type:
+//
+// close: [min, max]
+// open: (min, max)
+// lopen: (min, max]
+// ropen: [min, max)
+//
+type Range struct {
+ Min []byte
+ Max []byte
+
+ Type uint8
+}
+
+type Limit struct {
+ Offset int
+ Count int
+}
+
+type Iterator struct {
+ it driver.IIterator
+}
+
+// Returns a copy of key.
+func (it *Iterator) Key() []byte {
+ k := it.it.Key()
+ if k == nil {
+ return nil
+ }
+
+ return append([]byte{}, k...)
+}
+
+// Returns a copy of value.
+func (it *Iterator) Value() []byte {
+ v := it.it.Value()
+ if v == nil {
+ return nil
+ }
+
+ return append([]byte{}, v...)
+}
+
+// Returns a reference of key.
+// you must be careful that it will be changed after next iterate.
+func (it *Iterator) RawKey() []byte {
+ return it.it.Key()
+}
+
+// Returns a reference of value.
+// you must be careful that it will be changed after next iterate.
+func (it *Iterator) RawValue() []byte {
+ return it.it.Value()
+}
+
+// Copy key to b, if b len is small or nil, returns a new one.
+func (it *Iterator) BufKey(b []byte) []byte {
+ k := it.RawKey()
+ if k == nil {
+ return nil
+ }
+ if b == nil {
+ b = []byte{}
+ }
+
+ b = b[0:0]
+ return append(b, k...)
+}
+
+// Copy value to b, if b len is small or nil, returns a new one.
+func (it *Iterator) BufValue(b []byte) []byte {
+ v := it.RawValue()
+ if v == nil {
+ return nil
+ }
+
+ if b == nil {
+ b = []byte{}
+ }
+
+ b = b[0:0]
+ return append(b, v...)
+}
+
+func (it *Iterator) Close() {
+ if it.it != nil {
+ it.it.Close()
+ it.it = nil
+ }
+}
+
+func (it *Iterator) Valid() bool {
+ return it.it.Valid()
+}
+
+func (it *Iterator) Next() {
+ it.it.Next()
+}
+
+func (it *Iterator) Prev() {
+ it.it.Prev()
+}
+
+func (it *Iterator) SeekToFirst() {
+ it.it.First()
+}
+
+func (it *Iterator) SeekToLast() {
+ it.it.Last()
+}
+
+func (it *Iterator) Seek(key []byte) {
+ it.it.Seek(key)
+}
+
+// Finds by key, if not found, nil returns.
+func (it *Iterator) Find(key []byte) []byte {
+ it.Seek(key)
+ if it.Valid() {
+ k := it.RawKey()
+ if k == nil {
+ return nil
+ } else if bytes.Equal(k, key) {
+ return it.Value()
+ }
+ }
+
+ return nil
+}
+
+// Finds by key, if not found, nil returns, else a reference of value returns.
+// you must be careful that it will be changed after next iterate.
+func (it *Iterator) RawFind(key []byte) []byte {
+ it.Seek(key)
+ if it.Valid() {
+ k := it.RawKey()
+ if k == nil {
+ return nil
+ } else if bytes.Equal(k, key) {
+ return it.RawValue()
+ }
+ }
+
+ return nil
+}
+
+type RangeLimitIterator struct {
+ it *Iterator
+
+ r *Range
+ l *Limit
+
+ step int
+
+ //0 for IteratorForward, 1 for IteratorBackward
+ direction uint8
+}
+
+func (it *RangeLimitIterator) Key() []byte {
+ return it.it.Key()
+}
+
+func (it *RangeLimitIterator) Value() []byte {
+ return it.it.Value()
+}
+
+func (it *RangeLimitIterator) RawKey() []byte {
+ return it.it.RawKey()
+}
+
+func (it *RangeLimitIterator) RawValue() []byte {
+ return it.it.RawValue()
+}
+
+func (it *RangeLimitIterator) BufKey(b []byte) []byte {
+ return it.it.BufKey(b)
+}
+
+func (it *RangeLimitIterator) BufValue(b []byte) []byte {
+ return it.it.BufValue(b)
+}
+
+func (it *RangeLimitIterator) Valid() bool {
+ if it.l.Offset < 0 {
+ return false
+ } else if !it.it.Valid() {
+ return false
+ } else if it.l.Count >= 0 && it.step >= it.l.Count {
+ return false
+ }
+
+ if it.direction == IteratorForward {
+ if it.r.Max != nil {
+ r := bytes.Compare(it.it.RawKey(), it.r.Max)
+ if it.r.Type&RangeROpen > 0 {
+ return !(r >= 0)
+ } else {
+ return !(r > 0)
+ }
+ }
+ } else {
+ if it.r.Min != nil {
+ r := bytes.Compare(it.it.RawKey(), it.r.Min)
+ if it.r.Type&RangeLOpen > 0 {
+ return !(r <= 0)
+ } else {
+ return !(r < 0)
+ }
+ }
+ }
+
+ return true
+}
+
+func (it *RangeLimitIterator) Next() {
+ it.step++
+
+ if it.direction == IteratorForward {
+ it.it.Next()
+ } else {
+ it.it.Prev()
+ }
+}
+
+func (it *RangeLimitIterator) Close() {
+ it.it.Close()
+}
+
+func NewRangeLimitIterator(i *Iterator, r *Range, l *Limit) *RangeLimitIterator {
+ return rangeLimitIterator(i, r, l, IteratorForward)
+}
+
+func NewRevRangeLimitIterator(i *Iterator, r *Range, l *Limit) *RangeLimitIterator {
+ return rangeLimitIterator(i, r, l, IteratorBackward)
+}
+
+func NewRangeIterator(i *Iterator, r *Range) *RangeLimitIterator {
+ return rangeLimitIterator(i, r, &Limit{0, -1}, IteratorForward)
+}
+
+func NewRevRangeIterator(i *Iterator, r *Range) *RangeLimitIterator {
+ return rangeLimitIterator(i, r, &Limit{0, -1}, IteratorBackward)
+}
+
+func rangeLimitIterator(i *Iterator, r *Range, l *Limit, direction uint8) *RangeLimitIterator {
+ it := new(RangeLimitIterator)
+
+ it.it = i
+
+ it.r = r
+ it.l = l
+ it.direction = direction
+
+ it.step = 0
+
+ if l.Offset < 0 {
+ return it
+ }
+
+ if direction == IteratorForward {
+ if r.Min == nil {
+ it.it.SeekToFirst()
+ } else {
+ it.it.Seek(r.Min)
+
+ if r.Type&RangeLOpen > 0 {
+ if it.it.Valid() && bytes.Equal(it.it.RawKey(), r.Min) {
+ it.it.Next()
+ }
+ }
+ }
+ } else {
+ if r.Max == nil {
+ it.it.SeekToLast()
+ } else {
+ it.it.Seek(r.Max)
+
+ if !it.it.Valid() {
+ it.it.SeekToLast()
+ } else {
+ if !bytes.Equal(it.it.RawKey(), r.Max) {
+ it.it.Prev()
+ }
+ }
+
+ if r.Type&RangeROpen > 0 {
+ if it.it.Valid() && bytes.Equal(it.it.RawKey(), r.Max) {
+ it.it.Prev()
+ }
+ }
+ }
+ }
+
+ for i := 0; i < l.Offset; i++ {
+ if it.it.Valid() {
+ if it.direction == IteratorForward {
+ it.it.Next()
+ } else {
+ it.it.Prev()
+ }
+ }
+ }
+
+ return it
+}
diff --git a/vendor/github.com/lunny/nodb/store/snapshot.go b/vendor/github.com/lunny/nodb/store/snapshot.go
new file mode 100644
index 0000000000..75ba0497db
--- /dev/null
+++ b/vendor/github.com/lunny/nodb/store/snapshot.go
@@ -0,0 +1,16 @@
+package store
+
+import (
+ "github.com/lunny/nodb/store/driver"
+)
+
+type Snapshot struct {
+ driver.ISnapshot
+}
+
+func (s *Snapshot) NewIterator() *Iterator {
+ it := new(Iterator)
+ it.it = s.ISnapshot.NewIterator()
+
+ return it
+}
diff --git a/vendor/github.com/lunny/nodb/store/store.go b/vendor/github.com/lunny/nodb/store/store.go
new file mode 100644
index 0000000000..5d0ade1bf0
--- /dev/null
+++ b/vendor/github.com/lunny/nodb/store/store.go
@@ -0,0 +1,51 @@
+package store
+
+import (
+ "fmt"
+ "os"
+ "path"
+ "github.com/lunny/nodb/config"
+ "github.com/lunny/nodb/store/driver"
+
+ _ "github.com/lunny/nodb/store/goleveldb"
+)
+
+func getStorePath(cfg *config.Config) string {
+ return path.Join(cfg.DataDir, fmt.Sprintf("%s_data", cfg.DBName))
+}
+
+func Open(cfg *config.Config) (*DB, error) {
+ s, err := driver.GetStore(cfg)
+ if err != nil {
+ return nil, err
+ }
+
+ path := getStorePath(cfg)
+
+ if err := os.MkdirAll(path, os.ModePerm); err != nil {
+ return nil, err
+ }
+
+ idb, err := s.Open(path, cfg)
+ if err != nil {
+ return nil, err
+ }
+
+ db := &DB{idb}
+
+ return db, nil
+}
+
+func Repair(cfg *config.Config) error {
+ s, err := driver.GetStore(cfg)
+ if err != nil {
+ return err
+ }
+
+ path := getStorePath(cfg)
+
+ return s.Repair(path, cfg)
+}
+
+func init() {
+}
diff --git a/vendor/github.com/lunny/nodb/store/tx.go b/vendor/github.com/lunny/nodb/store/tx.go
new file mode 100644
index 0000000000..32bcbcda4b
--- /dev/null
+++ b/vendor/github.com/lunny/nodb/store/tx.go
@@ -0,0 +1,42 @@
+package store
+
+import (
+ "github.com/lunny/nodb/store/driver"
+)
+
+type Tx struct {
+ driver.Tx
+}
+
+func (tx *Tx) NewIterator() *Iterator {
+ it := new(Iterator)
+ it.it = tx.Tx.NewIterator()
+
+ return it
+}
+
+func (tx *Tx) NewWriteBatch() WriteBatch {
+ return tx.Tx.NewWriteBatch()
+}
+
+func (tx *Tx) RangeIterator(min []byte, max []byte, rangeType uint8) *RangeLimitIterator {
+ return NewRangeLimitIterator(tx.NewIterator(), &Range{min, max, rangeType}, &Limit{0, -1})
+}
+
+func (tx *Tx) RevRangeIterator(min []byte, max []byte, rangeType uint8) *RangeLimitIterator {
+ return NewRevRangeLimitIterator(tx.NewIterator(), &Range{min, max, rangeType}, &Limit{0, -1})
+}
+
+//count < 0, unlimit.
+//
+//offset must >= 0, if < 0, will get nothing.
+func (tx *Tx) RangeLimitIterator(min []byte, max []byte, rangeType uint8, offset int, count int) *RangeLimitIterator {
+ return NewRangeLimitIterator(tx.NewIterator(), &Range{min, max, rangeType}, &Limit{offset, count})
+}
+
+//count < 0, unlimit.
+//
+//offset must >= 0, if < 0, will get nothing.
+func (tx *Tx) RevRangeLimitIterator(min []byte, max []byte, rangeType uint8, offset int, count int) *RangeLimitIterator {
+ return NewRevRangeLimitIterator(tx.NewIterator(), &Range{min, max, rangeType}, &Limit{offset, count})
+}
diff --git a/vendor/github.com/lunny/nodb/store/writebatch.go b/vendor/github.com/lunny/nodb/store/writebatch.go
new file mode 100644
index 0000000000..23e079eba6
--- /dev/null
+++ b/vendor/github.com/lunny/nodb/store/writebatch.go
@@ -0,0 +1,9 @@
+package store
+
+import (
+ "github.com/lunny/nodb/store/driver"
+)
+
+type WriteBatch interface {
+ driver.IWriteBatch
+}