vinyl: fix read iterator skips source after reading cache
If a source is used on a read iteration (i.e. the key at which it is positioned is the next best match or, in terms of the read iterator implementation, its front_id matches the read iterator front_id), its history is cleaned up, see vy_read_iterator_apply_history(). This breaks the logic behind vy_read_src_is_behind(), which assumes that the history always points to the last used key. As a result, a source may be mistakenly skipped, as illustrated below: Fiber 1 Fiber 2 ------- ------- 1. Opens read iterator. 2. Advances it to the next key. The returned key was read from a mem or run (not from cache). The source's history is emptied. Adds a chain containing the key read by fiber 1 to the cache. 3. Continues iteration, reads next few keys from the cache until the chain ends. The source used at step 2 is skipped. 4. Calls vy_read_src_is_behind() on the source used at step 2 and skipped at step 3. It returns false, because its history is empty, thus skipping keys stored in it. Fix this bug by moving the code that checks whether a source iterator needs to be advanced from vy_read_src_is_behind() to source iterator 'skip' method, because there we always know the last key returned by the iterator. Basically, this returns the code we had before commit b4d57284 ("vinyl: consolidate skip optimization checks in read iterator"). Closes #3477
Showing
- src/box/vy_cache.c 13 additions, 2 deletionssrc/box/vy_cache.c
- src/box/vy_mem.c 11 additions, 0 deletionssrc/box/vy_mem.c
- src/box/vy_read_iterator.c 3 additions, 21 deletionssrc/box/vy_read_iterator.c
- src/box/vy_run.c 13 additions, 1 deletionsrc/box/vy_run.c
- src/box/vy_tx.c 11 additions, 0 deletionssrc/box/vy_tx.c
- test/vinyl/iterator.result 47 additions, 0 deletionstest/vinyl/iterator.result
- test/vinyl/iterator.test.lua 22 additions, 0 deletionstest/vinyl/iterator.test.lua
Loading
Please register or sign in to comment