0
0
bleve/index/store/gouchstore/iterator.go

110 lines
2.6 KiB
Go
Raw Normal View History

// Copyright (c) 2014 Couchbase, Inc.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
package gouchstore
import (
"fmt"
"github.com/mschoch/gouchstore"
)
type GouchstoreIterator struct {
store *GouchstoreStore
valid bool
curr *gouchstore.DocumentInfo
diChan chan *gouchstore.DocumentInfo
closeChan chan bool
}
func newGouchstoreIterator(store *GouchstoreStore) *GouchstoreIterator {
rv := GouchstoreIterator{
store: store,
}
return &rv
}
func (gi *GouchstoreIterator) cleanupExistingIterator() {
if gi.closeChan != nil {
close(gi.closeChan)
alive := true
for alive {
_, alive = <-gi.diChan
}
gi.closeChan = nil
}
}
func (gi *GouchstoreIterator) SeekFirst() {
gi.Seek([]byte{})
}
func (gi *GouchstoreIterator) Seek(key []byte) {
gi.cleanupExistingIterator()
gi.curr = nil
gi.diChan = make(chan *gouchstore.DocumentInfo)
gi.closeChan = make(chan bool)
wtCallback := func(gouchstore *gouchstore.Gouchstore, depth int, documentInfo *gouchstore.DocumentInfo, key []byte, subTreeSize uint64, reducedValue []byte, userContext interface{}) error {
if documentInfo != nil && documentInfo.Deleted == false {
select {
case gi.diChan <- documentInfo:
gi.valid = true
case <-gi.closeChan:
return fmt.Errorf("seek aborted")
}
}
return nil
}
go func() {
gi.store.db.WalkIdTree(string(key), "", wtCallback, nil)
close(gi.diChan)
}()
gi.curr = <-gi.diChan
}
func (gi *GouchstoreIterator) Current() ([]byte, []byte, bool) {
if gi.Valid() {
return gi.Key(), gi.Value(), true
}
return nil, nil, false
}
func (gi *GouchstoreIterator) Next() {
gi.curr = <-gi.diChan
if gi.curr == nil {
gi.valid = false
}
}
func (gi *GouchstoreIterator) Key() []byte {
if gi.curr != nil {
return []byte(gi.curr.ID)
}
return nil
}
func (gi *GouchstoreIterator) Value() []byte {
if gi.curr != nil {
doc, err := gi.store.db.DocumentByDocumentInfo(gi.curr)
if err == nil {
return doc.Body
}
}
return nil
}
func (gi *GouchstoreIterator) Valid() bool {
return gi.valid
}
func (gi *GouchstoreIterator) Close() {
gi.cleanupExistingIterator()
}