mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-05-04 13:50:39 +00:00
add other session providers (#5963)
This commit is contained in:
parent
bf4badad1d
commit
9de871a0f8
160 changed files with 37644 additions and 66 deletions
184
vendor/github.com/syndtr/goleveldb/leveldb/iterator/array_iter.go
generated
vendored
Normal file
184
vendor/github.com/syndtr/goleveldb/leveldb/iterator/array_iter.go
generated
vendored
Normal file
|
@ -0,0 +1,184 @@
|
|||
// Copyright (c) 2014, Suryandaru Triandana <syndtr@gmail.com>
|
||||
// All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package iterator
|
||||
|
||||
import (
|
||||
"github.com/syndtr/goleveldb/leveldb/util"
|
||||
)
|
||||
|
||||
// BasicArray is the interface that wraps basic Len and Search method.
|
||||
type BasicArray interface {
|
||||
// Len returns length of the array.
|
||||
Len() int
|
||||
|
||||
// Search finds smallest index that point to a key that is greater
|
||||
// than or equal to the given key.
|
||||
Search(key []byte) int
|
||||
}
|
||||
|
||||
// Array is the interface that wraps BasicArray and basic Index method.
|
||||
type Array interface {
|
||||
BasicArray
|
||||
|
||||
// Index returns key/value pair with index of i.
|
||||
Index(i int) (key, value []byte)
|
||||
}
|
||||
|
||||
// Array is the interface that wraps BasicArray and basic Get method.
|
||||
type ArrayIndexer interface {
|
||||
BasicArray
|
||||
|
||||
// Get returns a new data iterator with index of i.
|
||||
Get(i int) Iterator
|
||||
}
|
||||
|
||||
type basicArrayIterator struct {
|
||||
util.BasicReleaser
|
||||
array BasicArray
|
||||
pos int
|
||||
err error
|
||||
}
|
||||
|
||||
func (i *basicArrayIterator) Valid() bool {
|
||||
return i.pos >= 0 && i.pos < i.array.Len() && !i.Released()
|
||||
}
|
||||
|
||||
func (i *basicArrayIterator) First() bool {
|
||||
if i.Released() {
|
||||
i.err = ErrIterReleased
|
||||
return false
|
||||
}
|
||||
|
||||
if i.array.Len() == 0 {
|
||||
i.pos = -1
|
||||
return false
|
||||
}
|
||||
i.pos = 0
|
||||
return true
|
||||
}
|
||||
|
||||
func (i *basicArrayIterator) Last() bool {
|
||||
if i.Released() {
|
||||
i.err = ErrIterReleased
|
||||
return false
|
||||
}
|
||||
|
||||
n := i.array.Len()
|
||||
if n == 0 {
|
||||
i.pos = 0
|
||||
return false
|
||||
}
|
||||
i.pos = n - 1
|
||||
return true
|
||||
}
|
||||
|
||||
func (i *basicArrayIterator) Seek(key []byte) bool {
|
||||
if i.Released() {
|
||||
i.err = ErrIterReleased
|
||||
return false
|
||||
}
|
||||
|
||||
n := i.array.Len()
|
||||
if n == 0 {
|
||||
i.pos = 0
|
||||
return false
|
||||
}
|
||||
i.pos = i.array.Search(key)
|
||||
if i.pos >= n {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (i *basicArrayIterator) Next() bool {
|
||||
if i.Released() {
|
||||
i.err = ErrIterReleased
|
||||
return false
|
||||
}
|
||||
|
||||
i.pos++
|
||||
if n := i.array.Len(); i.pos >= n {
|
||||
i.pos = n
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (i *basicArrayIterator) Prev() bool {
|
||||
if i.Released() {
|
||||
i.err = ErrIterReleased
|
||||
return false
|
||||
}
|
||||
|
||||
i.pos--
|
||||
if i.pos < 0 {
|
||||
i.pos = -1
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (i *basicArrayIterator) Error() error { return i.err }
|
||||
|
||||
type arrayIterator struct {
|
||||
basicArrayIterator
|
||||
array Array
|
||||
pos int
|
||||
key, value []byte
|
||||
}
|
||||
|
||||
func (i *arrayIterator) updateKV() {
|
||||
if i.pos == i.basicArrayIterator.pos {
|
||||
return
|
||||
}
|
||||
i.pos = i.basicArrayIterator.pos
|
||||
if i.Valid() {
|
||||
i.key, i.value = i.array.Index(i.pos)
|
||||
} else {
|
||||
i.key = nil
|
||||
i.value = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (i *arrayIterator) Key() []byte {
|
||||
i.updateKV()
|
||||
return i.key
|
||||
}
|
||||
|
||||
func (i *arrayIterator) Value() []byte {
|
||||
i.updateKV()
|
||||
return i.value
|
||||
}
|
||||
|
||||
type arrayIteratorIndexer struct {
|
||||
basicArrayIterator
|
||||
array ArrayIndexer
|
||||
}
|
||||
|
||||
func (i *arrayIteratorIndexer) Get() Iterator {
|
||||
if i.Valid() {
|
||||
return i.array.Get(i.basicArrayIterator.pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewArrayIterator returns an iterator from the given array.
|
||||
func NewArrayIterator(array Array) Iterator {
|
||||
return &arrayIterator{
|
||||
basicArrayIterator: basicArrayIterator{array: array, pos: -1},
|
||||
array: array,
|
||||
pos: -1,
|
||||
}
|
||||
}
|
||||
|
||||
// NewArrayIndexer returns an index iterator from the given array.
|
||||
func NewArrayIndexer(array ArrayIndexer) IteratorIndexer {
|
||||
return &arrayIteratorIndexer{
|
||||
basicArrayIterator: basicArrayIterator{array: array, pos: -1},
|
||||
array: array,
|
||||
}
|
||||
}
|
242
vendor/github.com/syndtr/goleveldb/leveldb/iterator/indexed_iter.go
generated
vendored
Normal file
242
vendor/github.com/syndtr/goleveldb/leveldb/iterator/indexed_iter.go
generated
vendored
Normal file
|
@ -0,0 +1,242 @@
|
|||
// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
|
||||
// All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package iterator
|
||||
|
||||
import (
|
||||
"github.com/syndtr/goleveldb/leveldb/errors"
|
||||
"github.com/syndtr/goleveldb/leveldb/util"
|
||||
)
|
||||
|
||||
// IteratorIndexer is the interface that wraps CommonIterator and basic Get
|
||||
// method. IteratorIndexer provides index for indexed iterator.
|
||||
type IteratorIndexer interface {
|
||||
CommonIterator
|
||||
|
||||
// Get returns a new data iterator for the current position, or nil if
|
||||
// done.
|
||||
Get() Iterator
|
||||
}
|
||||
|
||||
type indexedIterator struct {
|
||||
util.BasicReleaser
|
||||
index IteratorIndexer
|
||||
strict bool
|
||||
|
||||
data Iterator
|
||||
err error
|
||||
errf func(err error)
|
||||
closed bool
|
||||
}
|
||||
|
||||
func (i *indexedIterator) setData() {
|
||||
if i.data != nil {
|
||||
i.data.Release()
|
||||
}
|
||||
i.data = i.index.Get()
|
||||
}
|
||||
|
||||
func (i *indexedIterator) clearData() {
|
||||
if i.data != nil {
|
||||
i.data.Release()
|
||||
}
|
||||
i.data = nil
|
||||
}
|
||||
|
||||
func (i *indexedIterator) indexErr() {
|
||||
if err := i.index.Error(); err != nil {
|
||||
if i.errf != nil {
|
||||
i.errf(err)
|
||||
}
|
||||
i.err = err
|
||||
}
|
||||
}
|
||||
|
||||
func (i *indexedIterator) dataErr() bool {
|
||||
if err := i.data.Error(); err != nil {
|
||||
if i.errf != nil {
|
||||
i.errf(err)
|
||||
}
|
||||
if i.strict || !errors.IsCorrupted(err) {
|
||||
i.err = err
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (i *indexedIterator) Valid() bool {
|
||||
return i.data != nil && i.data.Valid()
|
||||
}
|
||||
|
||||
func (i *indexedIterator) First() bool {
|
||||
if i.err != nil {
|
||||
return false
|
||||
} else if i.Released() {
|
||||
i.err = ErrIterReleased
|
||||
return false
|
||||
}
|
||||
|
||||
if !i.index.First() {
|
||||
i.indexErr()
|
||||
i.clearData()
|
||||
return false
|
||||
}
|
||||
i.setData()
|
||||
return i.Next()
|
||||
}
|
||||
|
||||
func (i *indexedIterator) Last() bool {
|
||||
if i.err != nil {
|
||||
return false
|
||||
} else if i.Released() {
|
||||
i.err = ErrIterReleased
|
||||
return false
|
||||
}
|
||||
|
||||
if !i.index.Last() {
|
||||
i.indexErr()
|
||||
i.clearData()
|
||||
return false
|
||||
}
|
||||
i.setData()
|
||||
if !i.data.Last() {
|
||||
if i.dataErr() {
|
||||
return false
|
||||
}
|
||||
i.clearData()
|
||||
return i.Prev()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (i *indexedIterator) Seek(key []byte) bool {
|
||||
if i.err != nil {
|
||||
return false
|
||||
} else if i.Released() {
|
||||
i.err = ErrIterReleased
|
||||
return false
|
||||
}
|
||||
|
||||
if !i.index.Seek(key) {
|
||||
i.indexErr()
|
||||
i.clearData()
|
||||
return false
|
||||
}
|
||||
i.setData()
|
||||
if !i.data.Seek(key) {
|
||||
if i.dataErr() {
|
||||
return false
|
||||
}
|
||||
i.clearData()
|
||||
return i.Next()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (i *indexedIterator) Next() bool {
|
||||
if i.err != nil {
|
||||
return false
|
||||
} else if i.Released() {
|
||||
i.err = ErrIterReleased
|
||||
return false
|
||||
}
|
||||
|
||||
switch {
|
||||
case i.data != nil && !i.data.Next():
|
||||
if i.dataErr() {
|
||||
return false
|
||||
}
|
||||
i.clearData()
|
||||
fallthrough
|
||||
case i.data == nil:
|
||||
if !i.index.Next() {
|
||||
i.indexErr()
|
||||
return false
|
||||
}
|
||||
i.setData()
|
||||
return i.Next()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (i *indexedIterator) Prev() bool {
|
||||
if i.err != nil {
|
||||
return false
|
||||
} else if i.Released() {
|
||||
i.err = ErrIterReleased
|
||||
return false
|
||||
}
|
||||
|
||||
switch {
|
||||
case i.data != nil && !i.data.Prev():
|
||||
if i.dataErr() {
|
||||
return false
|
||||
}
|
||||
i.clearData()
|
||||
fallthrough
|
||||
case i.data == nil:
|
||||
if !i.index.Prev() {
|
||||
i.indexErr()
|
||||
return false
|
||||
}
|
||||
i.setData()
|
||||
if !i.data.Last() {
|
||||
if i.dataErr() {
|
||||
return false
|
||||
}
|
||||
i.clearData()
|
||||
return i.Prev()
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (i *indexedIterator) Key() []byte {
|
||||
if i.data == nil {
|
||||
return nil
|
||||
}
|
||||
return i.data.Key()
|
||||
}
|
||||
|
||||
func (i *indexedIterator) Value() []byte {
|
||||
if i.data == nil {
|
||||
return nil
|
||||
}
|
||||
return i.data.Value()
|
||||
}
|
||||
|
||||
func (i *indexedIterator) Release() {
|
||||
i.clearData()
|
||||
i.index.Release()
|
||||
i.BasicReleaser.Release()
|
||||
}
|
||||
|
||||
func (i *indexedIterator) Error() error {
|
||||
if i.err != nil {
|
||||
return i.err
|
||||
}
|
||||
if err := i.index.Error(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *indexedIterator) SetErrorCallback(f func(err error)) {
|
||||
i.errf = f
|
||||
}
|
||||
|
||||
// NewIndexedIterator returns an 'indexed iterator'. An index is iterator
|
||||
// that returns another iterator, a 'data iterator'. A 'data iterator' is the
|
||||
// iterator that contains actual key/value pairs.
|
||||
//
|
||||
// If strict is true the any 'corruption errors' (i.e errors.IsCorrupted(err) == true)
|
||||
// won't be ignored and will halt 'indexed iterator', otherwise the iterator will
|
||||
// continue to the next 'data iterator'. Corruption on 'index iterator' will not be
|
||||
// ignored and will halt the iterator.
|
||||
func NewIndexedIterator(index IteratorIndexer, strict bool) Iterator {
|
||||
return &indexedIterator{index: index, strict: strict}
|
||||
}
|
132
vendor/github.com/syndtr/goleveldb/leveldb/iterator/iter.go
generated
vendored
Normal file
132
vendor/github.com/syndtr/goleveldb/leveldb/iterator/iter.go
generated
vendored
Normal file
|
@ -0,0 +1,132 @@
|
|||
// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
|
||||
// All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Package iterator provides interface and implementation to traverse over
|
||||
// contents of a database.
|
||||
package iterator
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/syndtr/goleveldb/leveldb/util"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrIterReleased = errors.New("leveldb/iterator: iterator released")
|
||||
)
|
||||
|
||||
// IteratorSeeker is the interface that wraps the 'seeks method'.
|
||||
type IteratorSeeker interface {
|
||||
// First moves the iterator to the first key/value pair. If the iterator
|
||||
// only contains one key/value pair then First and Last would moves
|
||||
// to the same key/value pair.
|
||||
// It returns whether such pair exist.
|
||||
First() bool
|
||||
|
||||
// Last moves the iterator to the last key/value pair. If the iterator
|
||||
// only contains one key/value pair then First and Last would moves
|
||||
// to the same key/value pair.
|
||||
// It returns whether such pair exist.
|
||||
Last() bool
|
||||
|
||||
// Seek moves the iterator to the first key/value pair whose key is greater
|
||||
// than or equal to the given key.
|
||||
// It returns whether such pair exist.
|
||||
//
|
||||
// It is safe to modify the contents of the argument after Seek returns.
|
||||
Seek(key []byte) bool
|
||||
|
||||
// Next moves the iterator to the next key/value pair.
|
||||
// It returns false if the iterator is exhausted.
|
||||
Next() bool
|
||||
|
||||
// Prev moves the iterator to the previous key/value pair.
|
||||
// It returns false if the iterator is exhausted.
|
||||
Prev() bool
|
||||
}
|
||||
|
||||
// CommonIterator is the interface that wraps common iterator methods.
|
||||
type CommonIterator interface {
|
||||
IteratorSeeker
|
||||
|
||||
// util.Releaser is the interface that wraps basic Release method.
|
||||
// When called Release will releases any resources associated with the
|
||||
// iterator.
|
||||
util.Releaser
|
||||
|
||||
// util.ReleaseSetter is the interface that wraps the basic SetReleaser
|
||||
// method.
|
||||
util.ReleaseSetter
|
||||
|
||||
// TODO: Remove this when ready.
|
||||
Valid() bool
|
||||
|
||||
// Error returns any accumulated error. Exhausting all the key/value pairs
|
||||
// is not considered to be an error.
|
||||
Error() error
|
||||
}
|
||||
|
||||
// Iterator iterates over a DB's key/value pairs in key order.
|
||||
//
|
||||
// When encounter an error any 'seeks method' will return false and will
|
||||
// yield no key/value pairs. The error can be queried by calling the Error
|
||||
// method. Calling Release is still necessary.
|
||||
//
|
||||
// An iterator must be released after use, but it is not necessary to read
|
||||
// an iterator until exhaustion.
|
||||
// Also, an iterator is not necessarily safe for concurrent use, but it is
|
||||
// safe to use multiple iterators concurrently, with each in a dedicated
|
||||
// goroutine.
|
||||
type Iterator interface {
|
||||
CommonIterator
|
||||
|
||||
// Key returns the key of the current key/value pair, or nil if done.
|
||||
// The caller should not modify the contents of the returned slice, and
|
||||
// its contents may change on the next call to any 'seeks method'.
|
||||
Key() []byte
|
||||
|
||||
// Value returns the value of the current key/value pair, or nil if done.
|
||||
// The caller should not modify the contents of the returned slice, and
|
||||
// its contents may change on the next call to any 'seeks method'.
|
||||
Value() []byte
|
||||
}
|
||||
|
||||
// ErrorCallbackSetter is the interface that wraps basic SetErrorCallback
|
||||
// method.
|
||||
//
|
||||
// ErrorCallbackSetter implemented by indexed and merged iterator.
|
||||
type ErrorCallbackSetter interface {
|
||||
// SetErrorCallback allows set an error callback of the corresponding
|
||||
// iterator. Use nil to clear the callback.
|
||||
SetErrorCallback(f func(err error))
|
||||
}
|
||||
|
||||
type emptyIterator struct {
|
||||
util.BasicReleaser
|
||||
err error
|
||||
}
|
||||
|
||||
func (i *emptyIterator) rErr() {
|
||||
if i.err == nil && i.Released() {
|
||||
i.err = ErrIterReleased
|
||||
}
|
||||
}
|
||||
|
||||
func (*emptyIterator) Valid() bool { return false }
|
||||
func (i *emptyIterator) First() bool { i.rErr(); return false }
|
||||
func (i *emptyIterator) Last() bool { i.rErr(); return false }
|
||||
func (i *emptyIterator) Seek(key []byte) bool { i.rErr(); return false }
|
||||
func (i *emptyIterator) Next() bool { i.rErr(); return false }
|
||||
func (i *emptyIterator) Prev() bool { i.rErr(); return false }
|
||||
func (*emptyIterator) Key() []byte { return nil }
|
||||
func (*emptyIterator) Value() []byte { return nil }
|
||||
func (i *emptyIterator) Error() error { return i.err }
|
||||
|
||||
// NewEmptyIterator creates an empty iterator. The err parameter can be
|
||||
// nil, but if not nil the given err will be returned by Error method.
|
||||
func NewEmptyIterator(err error) Iterator {
|
||||
return &emptyIterator{err: err}
|
||||
}
|
304
vendor/github.com/syndtr/goleveldb/leveldb/iterator/merged_iter.go
generated
vendored
Normal file
304
vendor/github.com/syndtr/goleveldb/leveldb/iterator/merged_iter.go
generated
vendored
Normal file
|
@ -0,0 +1,304 @@
|
|||
// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
|
||||
// All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package iterator
|
||||
|
||||
import (
|
||||
"github.com/syndtr/goleveldb/leveldb/comparer"
|
||||
"github.com/syndtr/goleveldb/leveldb/errors"
|
||||
"github.com/syndtr/goleveldb/leveldb/util"
|
||||
)
|
||||
|
||||
type dir int
|
||||
|
||||
const (
|
||||
dirReleased dir = iota - 1
|
||||
dirSOI
|
||||
dirEOI
|
||||
dirBackward
|
||||
dirForward
|
||||
)
|
||||
|
||||
type mergedIterator struct {
|
||||
cmp comparer.Comparer
|
||||
iters []Iterator
|
||||
strict bool
|
||||
|
||||
keys [][]byte
|
||||
index int
|
||||
dir dir
|
||||
err error
|
||||
errf func(err error)
|
||||
releaser util.Releaser
|
||||
}
|
||||
|
||||
func assertKey(key []byte) []byte {
|
||||
if key == nil {
|
||||
panic("leveldb/iterator: nil key")
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
func (i *mergedIterator) iterErr(iter Iterator) bool {
|
||||
if err := iter.Error(); err != nil {
|
||||
if i.errf != nil {
|
||||
i.errf(err)
|
||||
}
|
||||
if i.strict || !errors.IsCorrupted(err) {
|
||||
i.err = err
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (i *mergedIterator) Valid() bool {
|
||||
return i.err == nil && i.dir > dirEOI
|
||||
}
|
||||
|
||||
func (i *mergedIterator) First() bool {
|
||||
if i.err != nil {
|
||||
return false
|
||||
} else if i.dir == dirReleased {
|
||||
i.err = ErrIterReleased
|
||||
return false
|
||||
}
|
||||
|
||||
for x, iter := range i.iters {
|
||||
switch {
|
||||
case iter.First():
|
||||
i.keys[x] = assertKey(iter.Key())
|
||||
case i.iterErr(iter):
|
||||
return false
|
||||
default:
|
||||
i.keys[x] = nil
|
||||
}
|
||||
}
|
||||
i.dir = dirSOI
|
||||
return i.next()
|
||||
}
|
||||
|
||||
func (i *mergedIterator) Last() bool {
|
||||
if i.err != nil {
|
||||
return false
|
||||
} else if i.dir == dirReleased {
|
||||
i.err = ErrIterReleased
|
||||
return false
|
||||
}
|
||||
|
||||
for x, iter := range i.iters {
|
||||
switch {
|
||||
case iter.Last():
|
||||
i.keys[x] = assertKey(iter.Key())
|
||||
case i.iterErr(iter):
|
||||
return false
|
||||
default:
|
||||
i.keys[x] = nil
|
||||
}
|
||||
}
|
||||
i.dir = dirEOI
|
||||
return i.prev()
|
||||
}
|
||||
|
||||
func (i *mergedIterator) Seek(key []byte) bool {
|
||||
if i.err != nil {
|
||||
return false
|
||||
} else if i.dir == dirReleased {
|
||||
i.err = ErrIterReleased
|
||||
return false
|
||||
}
|
||||
|
||||
for x, iter := range i.iters {
|
||||
switch {
|
||||
case iter.Seek(key):
|
||||
i.keys[x] = assertKey(iter.Key())
|
||||
case i.iterErr(iter):
|
||||
return false
|
||||
default:
|
||||
i.keys[x] = nil
|
||||
}
|
||||
}
|
||||
i.dir = dirSOI
|
||||
return i.next()
|
||||
}
|
||||
|
||||
func (i *mergedIterator) next() bool {
|
||||
var key []byte
|
||||
if i.dir == dirForward {
|
||||
key = i.keys[i.index]
|
||||
}
|
||||
for x, tkey := range i.keys {
|
||||
if tkey != nil && (key == nil || i.cmp.Compare(tkey, key) < 0) {
|
||||
key = tkey
|
||||
i.index = x
|
||||
}
|
||||
}
|
||||
if key == nil {
|
||||
i.dir = dirEOI
|
||||
return false
|
||||
}
|
||||
i.dir = dirForward
|
||||
return true
|
||||
}
|
||||
|
||||
func (i *mergedIterator) Next() bool {
|
||||
if i.dir == dirEOI || i.err != nil {
|
||||
return false
|
||||
} else if i.dir == dirReleased {
|
||||
i.err = ErrIterReleased
|
||||
return false
|
||||
}
|
||||
|
||||
switch i.dir {
|
||||
case dirSOI:
|
||||
return i.First()
|
||||
case dirBackward:
|
||||
key := append([]byte{}, i.keys[i.index]...)
|
||||
if !i.Seek(key) {
|
||||
return false
|
||||
}
|
||||
return i.Next()
|
||||
}
|
||||
|
||||
x := i.index
|
||||
iter := i.iters[x]
|
||||
switch {
|
||||
case iter.Next():
|
||||
i.keys[x] = assertKey(iter.Key())
|
||||
case i.iterErr(iter):
|
||||
return false
|
||||
default:
|
||||
i.keys[x] = nil
|
||||
}
|
||||
return i.next()
|
||||
}
|
||||
|
||||
func (i *mergedIterator) prev() bool {
|
||||
var key []byte
|
||||
if i.dir == dirBackward {
|
||||
key = i.keys[i.index]
|
||||
}
|
||||
for x, tkey := range i.keys {
|
||||
if tkey != nil && (key == nil || i.cmp.Compare(tkey, key) > 0) {
|
||||
key = tkey
|
||||
i.index = x
|
||||
}
|
||||
}
|
||||
if key == nil {
|
||||
i.dir = dirSOI
|
||||
return false
|
||||
}
|
||||
i.dir = dirBackward
|
||||
return true
|
||||
}
|
||||
|
||||
func (i *mergedIterator) Prev() bool {
|
||||
if i.dir == dirSOI || i.err != nil {
|
||||
return false
|
||||
} else if i.dir == dirReleased {
|
||||
i.err = ErrIterReleased
|
||||
return false
|
||||
}
|
||||
|
||||
switch i.dir {
|
||||
case dirEOI:
|
||||
return i.Last()
|
||||
case dirForward:
|
||||
key := append([]byte{}, i.keys[i.index]...)
|
||||
for x, iter := range i.iters {
|
||||
if x == i.index {
|
||||
continue
|
||||
}
|
||||
seek := iter.Seek(key)
|
||||
switch {
|
||||
case seek && iter.Prev(), !seek && iter.Last():
|
||||
i.keys[x] = assertKey(iter.Key())
|
||||
case i.iterErr(iter):
|
||||
return false
|
||||
default:
|
||||
i.keys[x] = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
x := i.index
|
||||
iter := i.iters[x]
|
||||
switch {
|
||||
case iter.Prev():
|
||||
i.keys[x] = assertKey(iter.Key())
|
||||
case i.iterErr(iter):
|
||||
return false
|
||||
default:
|
||||
i.keys[x] = nil
|
||||
}
|
||||
return i.prev()
|
||||
}
|
||||
|
||||
func (i *mergedIterator) Key() []byte {
|
||||
if i.err != nil || i.dir <= dirEOI {
|
||||
return nil
|
||||
}
|
||||
return i.keys[i.index]
|
||||
}
|
||||
|
||||
func (i *mergedIterator) Value() []byte {
|
||||
if i.err != nil || i.dir <= dirEOI {
|
||||
return nil
|
||||
}
|
||||
return i.iters[i.index].Value()
|
||||
}
|
||||
|
||||
func (i *mergedIterator) Release() {
|
||||
if i.dir != dirReleased {
|
||||
i.dir = dirReleased
|
||||
for _, iter := range i.iters {
|
||||
iter.Release()
|
||||
}
|
||||
i.iters = nil
|
||||
i.keys = nil
|
||||
if i.releaser != nil {
|
||||
i.releaser.Release()
|
||||
i.releaser = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (i *mergedIterator) SetReleaser(releaser util.Releaser) {
|
||||
if i.dir == dirReleased {
|
||||
panic(util.ErrReleased)
|
||||
}
|
||||
if i.releaser != nil && releaser != nil {
|
||||
panic(util.ErrHasReleaser)
|
||||
}
|
||||
i.releaser = releaser
|
||||
}
|
||||
|
||||
func (i *mergedIterator) Error() error {
|
||||
return i.err
|
||||
}
|
||||
|
||||
func (i *mergedIterator) SetErrorCallback(f func(err error)) {
|
||||
i.errf = f
|
||||
}
|
||||
|
||||
// NewMergedIterator returns an iterator that merges its input. Walking the
|
||||
// resultant iterator will return all key/value pairs of all input iterators
|
||||
// in strictly increasing key order, as defined by cmp.
|
||||
// The input's key ranges may overlap, but there are assumed to be no duplicate
|
||||
// keys: if iters[i] contains a key k then iters[j] will not contain that key k.
|
||||
// None of the iters may be nil.
|
||||
//
|
||||
// If strict is true the any 'corruption errors' (i.e errors.IsCorrupted(err) == true)
|
||||
// won't be ignored and will halt 'merged iterator', otherwise the iterator will
|
||||
// continue to the next 'input iterator'.
|
||||
func NewMergedIterator(iters []Iterator, cmp comparer.Comparer, strict bool) Iterator {
|
||||
return &mergedIterator{
|
||||
iters: iters,
|
||||
cmp: cmp,
|
||||
strict: strict,
|
||||
keys: make([][]byte, len(iters)),
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue