COMPRESS-505 : bug fix for random access of 7z #95
+255
−49
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There are some problems in my PR about random access of 7z [#83](COMPRESS-342 random access of 7z files) :
I was thinking that the
currentFolderInputStream
can be repositioned by changing the position of thechannel
, which turns out to be impossible. This PR fixesit by reopening thecurrentFolderInputStream
.There are 2 ways to access the content of a 7z archive now : by sequential access(getNextEntry) and by random access(getInputStream). They may be used one after another. So there're some conditions we need to deal with :
2.1 In a random access, if
currentEntryIndex
==entryIndex
&& the entry has not been read yet :This means the input stream of the entry we want has already been put in the
deferredBlockStreams
as the last array member. We SHOULD NOT build a new input stream for the entry again, because this will make same the existed stream indeferredBlockStreams
be skipped. We should just do nothing cause the input stream is already in thedeferredBlockStreams
.2.2 In a random access, if
currentEntryIndex
==entryIndex
&& the entry has already been read :This means the entry we want has been read(maybe some of entry or all of the entry has been read, it does not matter). Then we should reopen the
currentFolderInputStream
and skip all the entries before the entry we want.BTW : we could determine if the file has been read or not by comparing the
bytesRemaining
of the input stream(as aCRC32VerifyingInputStream
) and the actual size of the file.2.3 In a random access, if
currentEntryIndex
<entryIndex
:The input streams whose index equals or less than
currentEntryIndex
has already been put into thedeferredBlockStreams
. We could just add the remaining entries to thedeferredBlockStreams
.2.4 In a random access, if
currentEntryIndex
>entryIndex
:This means the entry we want has already been read or skipped beforehand. We could only reopen the
currentFolderInputStream
and skip all the entries again.In short, we should do nothing in 2.1, skip the remaining entries in 2.3, and reopen the
currentFolderInputStream
in 2.2/2.4. I have to admit this is a bit complicated, but I didn't find any other better ideas building the logic. :(I made some refactoring and added some new comments to make the code more clear. The corresponding testcases are also included in this PR.