@@ -140,42 +140,49 @@ func (item *Item) DiscardEarlierVersions() bool {
140140}
141141
142142func (item * Item ) yieldItemValue () ([]byte , func (), error ) {
143- if ! item .hasValue () {
144- return nil , nil , nil
145- }
143+ key := item .Key () // No need to copy.
144+ for {
145+ if ! item .hasValue () {
146+ return nil , nil , nil
147+ }
146148
147- if item .slice == nil {
148- item .slice = new (y.Slice )
149- }
149+ if item .slice == nil {
150+ item .slice = new (y.Slice )
151+ }
150152
151- if (item .meta & bitValuePointer ) == 0 {
152- val := item .slice .Resize (len (item .vptr ))
153- copy (val , item .vptr )
154- return val , nil , nil
155- }
153+ if (item .meta & bitValuePointer ) == 0 {
154+ val := item .slice .Resize (len (item .vptr ))
155+ copy (val , item .vptr )
156+ return val , nil , nil
157+ }
156158
157- var vp valuePointer
158- vp .Decode (item .vptr )
159- result , cb , err := item .db .vlog .Read (vp , item .slice )
160- if err != ErrRetry {
161- return result , cb , err
162- }
163-
164- // The value pointer is pointing to a deleted value log. Look for the move key and read that
165- // instead.
166- runCallback (cb )
167- key := y .KeyWithTs (item .Key (), item .Version ())
168- moveKey := append (badgerMove , key ... )
169- vs , err := item .db .get (moveKey )
170- if err != nil {
171- return nil , nil , err
172- }
173- if vs .Version != item .Version () {
174- return nil , nil , nil
175- }
176- item .vptr = vs .Value
177- item .meta |= vs .Meta // This meta would only be about value pointer.
178- return item .yieldItemValue ()
159+ var vp valuePointer
160+ vp .Decode (item .vptr )
161+ result , cb , err := item .db .vlog .Read (vp , item .slice )
162+ if err != ErrRetry || bytes .HasPrefix (key , badgerMove ) {
163+ // The error is not retry, or we have already searched the move keyspace.
164+ return result , cb , err
165+ }
166+
167+ // The value pointer is pointing to a deleted value log. Look for the
168+ // move key and read that instead.
169+ runCallback (cb )
170+ key = append (badgerMove , y .KeyWithTs (item .Key (), item .Version ())... )
171+ // Note that we can't set item.key to move key, because that would
172+ // change the key user sees before and after this call. Also, this move
173+ // logic is internal logic and should not impact the external behavior
174+ // of the retrieval.
175+ vs , err := item .db .get (key )
176+ if err != nil {
177+ return nil , nil , err
178+ }
179+ if vs .Version != item .Version () {
180+ return nil , nil , nil
181+ }
182+ item .vptr = vs .Value
183+ item .meta &^= bitValuePointer // Clear the value pointer bit.
184+ item .meta |= vs .Meta // This meta would only be about value pointer.
185+ }
179186}
180187
181188func runCallback (cb func ()) {
0 commit comments