but why do we need to do this?
I'm not completely sure I understood what you are asking. If you're asking why the params specify slices in reverse order when reading reversed, it was because I thought it would make sense to specify the ranges we want the first results to come from, first.
If you're asking about this particular piece of code:
if (reversed && readBackwards)
lets say we have the following two slices [a,c] [f,j] and, in reverse [j,f] [c,a]. In IndexedBlockFecther we always start with the first slice ([a,c] and [j,f], respectively) and continue from there as we want to make sure we don't fetch more than necessary. In SimpleBlockFecther however we always fetch the whole row so we might as well process [j,f] [c,a] as if it were [a,c] [f,j] and simply add the blocks to the queue in reverse order. that's why we read reverse & backwards.
I hope that clarified it.
Your question reminds me of one another one I had, though. Why don't we make the "count" information reach ISR so that we can stop at the precise point the user query specifies? It seems wasteful to be reading the whole row in SimpleBlockFetcher is the user only requested the first 5 cols. This wouldn't work in reverse reads, of course, but would speed up forward ones, which are probably the most frequent, no?
In IndexedSliceReader itself is a iterator and within which there is Simple and IndexedFetcher which is also kind of a iterator ... it might be better to make IndexedSliceReader as abstract class and add functionality into classes.
I'm not sure I understood what you are suggesting... is it that we move the code that decides whether we need a Simple- or IndexedBlockFetcher out of ISR and make ISR itself the parent abstract class to Simple- or IndexedBlockFetcher?