Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iterator issue #84

Closed
artvel opened this issue Jun 30, 2017 · 5 comments
Closed

iterator issue #84

artvel opened this issue Jun 30, 2017 · 5 comments

Comments

@artvel
Copy link

artvel commented Jun 30, 2017

Hi there

I just started trying out badger and it seems very nice so far!
I'm not sure about the behavior of the iterator at one point.

package badger

import (
	"testing"
	"fmt"
	"github.com/dgraph-io/badger/badger"
	"strconv"
)

func TestWrite(t *testing.T) {
	opts := badger.DefaultOptions
	opts.Dir = "data"
	opts.ValueDir = "data"
	kv, err := badger.NewKV(&opts)
	if err != nil{
		panic(err)
	}
	defer kv.Close()
	for i := 0; i < 15000; i++{
		err = kv.Set([]byte("test_"+strconv.Itoa(i)), []byte("value_"+strconv.Itoa(i)))
		if err != nil{
			panic(err)
		}
	}
}

func TestIterator(t *testing.T) {
	opts := badger.DefaultOptions
	opts.Dir = "data"
	opts.ValueDir = "data"
	kv, err := badger.NewKV(&opts)
	if err != nil{
		panic(err)
	}
	defer kv.Close()
	optsi := badger.DefaultIteratorOptions
	it := kv.NewIterator(optsi)
	var kvItem *badger.KVItem
	it.Rewind() // it.Next() produces error without it.Rewind()
	for it.Next();it.Valid();it.Next(){
		kvItem = it.Item()
		fmt.Println("k", string(kvItem.Key()), "v", string(kvItem.Value()), "c", kvItem.Counter())
	}
}

I called TestWrite and then TestIterator. Without it.Rewind() before the loop you should encounter an error.
My question is pretty simple. Do I need to call rewind at this point or is it a bug?

@fraenky8
Copy link

fraenky8 commented Jul 1, 2017

Hi!

i think you used the for-loop in a "wrong" way. You put a Next()-call at the initializing position. Looking at the godoc for the NewIterator-function, it says

for it.Rewind(); it.Valid(); it.Next() {
...
}

So you can just put the Rewind()-call inside the head of the for-loop.

Still wondering, why a new created iterator must be rewinded, following does not work too, if the Rewind()-call is missing:

it.Rewind()
for it.Valid() {
	kvItem = it.Item()
	fmt.Println("k", string(kvItem.Key()), "v", string(kvItem.Value()), "c", kvItem.Counter())
	it.Next()
}

I would expect a new iterator is just usable after creating it.

@manishrjain
Copy link
Contributor

manishrjain commented Jul 3, 2017

The reason Rewind must be called, is because we need to know where to start prefetching from. One could use Seek instead of Rewind. In that case, if we automatically start prefetching from the beginning, all that work would need to be abandoned and would cause delays in doing the Seek call.

In short, the reason to specify the initial point is that we do extra work in the background; and we need to know where to begin.

Hope that answers your query.

@artvel
Copy link
Author

artvel commented Jul 25, 2017

Well, the idea was to implement a custom Seek but as far as I understood it's not possible without calling Rewind.

@manishrjain
Copy link
Contributor

You can call Seek directly, then you don't need to call Rewind.

@artvel
Copy link
Author

artvel commented Jul 27, 2017

Yes, but you can't build a Seek like Seek([]byte("contains")). You can only seek the whole key and that's my issue. I thought it would be possible to build a custom seek without Rewind.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants