| 149 | } |
| 150 | |
| 151 | func (item *Item) yieldItemValue() ([]byte, func(), error) { |
| 152 | key := item.Key() // No need to copy. |
| 153 | for { |
| 154 | if !item.hasValue() { |
| 155 | return nil, nil, nil |
| 156 | } |
| 157 | |
| 158 | if item.slice == nil { |
| 159 | item.slice = new(y.Slice) |
| 160 | } |
| 161 | |
| 162 | if (item.meta & bitValuePointer) == 0 { |
| 163 | val := item.slice.Resize(len(item.vptr)) |
| 164 | copy(val, item.vptr) |
| 165 | return val, nil, nil |
| 166 | } |
| 167 | |
| 168 | var vp valuePointer |
| 169 | vp.Decode(item.vptr) |
| 170 | result, cb, err := item.db.vlog.Read(vp, item.slice) |
| 171 | if err != ErrRetry { |
| 172 | if err != nil { |
| 173 | item.db.opt.Logger.Errorf(`Unable to read: Key: %v, Version : %v, |
| 174 | meta: %v, userMeta: %v`, key, item.version, item.meta, item.userMeta) |
| 175 | } |
| 176 | return result, cb, err |
| 177 | } |
| 178 | if bytes.HasPrefix(key, badgerMove) { |
| 179 | // err == ErrRetry |
| 180 | // Error is retry even after checking the move keyspace. So, let's |
| 181 | // just assume that value is not present. |
| 182 | return nil, cb, nil |
| 183 | } |
| 184 | |
| 185 | // The value pointer is pointing to a deleted value log. Look for the |
| 186 | // move key and read that instead. |
| 187 | runCallback(cb) |
| 188 | // Do not put badgerMove on the left in append. It seems to cause some sort of manipulation. |
| 189 | keyTs := y.KeyWithTs(item.Key(), item.Version()) |
| 190 | key = make([]byte, len(badgerMove)+len(keyTs)) |
| 191 | n := copy(key, badgerMove) |
| 192 | copy(key[n:], keyTs) |
| 193 | // Note that we can't set item.key to move key, because that would |
| 194 | // change the key user sees before and after this call. Also, this move |
| 195 | // logic is internal logic and should not impact the external behavior |
| 196 | // of the retrieval. |
| 197 | vs, err := item.db.get(key) |
| 198 | if err != nil { |
| 199 | return nil, nil, err |
| 200 | } |
| 201 | if vs.Version != item.Version() { |
| 202 | return nil, nil, nil |
| 203 | } |
| 204 | // Bug fix: Always copy the vs.Value into vptr here. Otherwise, when item is reused this |
| 205 | // slice gets overwritten. |
| 206 | item.vptr = y.SafeCopy(item.vptr, vs.Value) |
| 207 | item.meta &^= bitValuePointer // Clear the value pointer bit. |
| 208 | if vs.Meta&bitValuePointer > 0 { |