-
Notifications
You must be signed in to change notification settings - Fork 107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add support for gzip archive files #157
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
1082b29
feat: add support for tgz archive files
513e5fb
feat: add support for tgz archive files - test on linux as well as wi…
c67b586
feat: add support for tgz archive files - apply PR review comments
6e04d6f
feat: add support for tgz archive files - fix issue in endsWith
d567d8f
Merge branch 'sevdokimov:master' into master
mhewedy 1dfcfd3
feat: add support for gzip archive files - polish
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,8 @@ | |
import org.springframework.lang.Nullable; | ||
|
||
import java.io.EOFException; | ||
import java.io.File; | ||
import java.io.FileOutputStream; | ||
import java.io.IOException; | ||
import java.nio.ByteBuffer; | ||
import java.nio.channels.SeekableByteChannel; | ||
|
@@ -30,6 +32,9 @@ | |
import java.util.function.Function; | ||
import java.util.function.Predicate; | ||
import java.util.zip.CRC32; | ||
import java.util.zip.GZIPInputStream; | ||
|
||
import static com.logviewer.files.FileTypes.GZ; | ||
|
||
public class Log implements LogView { | ||
|
||
|
@@ -56,7 +61,7 @@ public class Log implements LogView { | |
|
||
private final Object logChangedTaskKey = new Object(); | ||
|
||
private final Path file; | ||
private Path file; | ||
|
||
private final String id; | ||
|
||
|
@@ -77,6 +82,8 @@ public class Log implements LogView { | |
private LvFileAccessManager accessManager; | ||
@Value("${log-viewer.parser.max-unparsable-block-size:2097152}") // 2Mb | ||
private long unparsableBlockMaxSize; | ||
@Value("${log-viewer.unpack-archive:false}") | ||
private boolean unpackArchive; | ||
|
||
private final MultiListener<Consumer<FileAttributes>> changeListener = new MultiListener<>(this::createFileListener); | ||
|
||
|
@@ -141,6 +148,25 @@ public Snapshot createSnapshot() { | |
} | ||
} | ||
|
||
private void decompressAndCopyGZipFile() throws IOException { | ||
|
||
File tempFile = File.createTempFile("log-viewer-", "-" + file.getName(file.getNameCount() - 1) + ".tmp"); | ||
tempFile.deleteOnExit(); | ||
|
||
try (GZIPInputStream gis = new GZIPInputStream( | ||
Files.newInputStream(file.toFile().toPath())); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it really necessary to convert it to File, and then back to Path? Or is it just mistake? |
||
FileOutputStream fos = new FileOutputStream(tempFile)) { | ||
|
||
byte[] buffer = new byte[1024 * 10]; | ||
int len; | ||
while ((len = gis.read(buffer)) > 0) { | ||
fos.write(buffer, 0, len); | ||
} | ||
} | ||
|
||
this.file = tempFile.toPath(); | ||
} | ||
|
||
public class LogSnapshot implements Snapshot { | ||
|
||
private final long size; | ||
|
@@ -183,8 +209,7 @@ public class LogSnapshot implements Snapshot { | |
|
||
if (cachedHashTimestamp == lastModification) { | ||
hash = cachedHash; | ||
} | ||
else { | ||
} else { | ||
hash = calculateHash(size); | ||
|
||
if (!hash.equals(cachedHash)) { | ||
|
@@ -200,8 +225,7 @@ public class LogSnapshot implements Snapshot { | |
success = true; | ||
} catch (IOException e) { | ||
error = e; | ||
} | ||
finally { | ||
} finally { | ||
if (!success) | ||
Utils.closeQuietly(this); | ||
} | ||
|
@@ -228,6 +252,9 @@ private SeekableByteChannel getChannel() throws IOException { | |
if (error != null) | ||
throw new IOException(error); | ||
|
||
if (unpackArchive && GZ.getPattern().matcher(file.toString()).matches()) | ||
decompressAndCopyGZipFile(); | ||
|
||
channel = Files.newByteChannel(file, StandardOpenOption.READ); | ||
} | ||
|
||
|
@@ -317,8 +344,7 @@ public boolean processRecordsBack(long position, boolean fromPrevLine, Predicate | |
if (fromPrevLine) { | ||
if (!buf.loadPrevLine(firstLine, position)) | ||
return true; | ||
} | ||
else { | ||
} else { | ||
buf.loadLine(firstLine, position); | ||
} | ||
|
||
|
@@ -341,8 +367,7 @@ public boolean processRecordsBack(long position, boolean fromPrevLine, Predicate | |
|
||
if (reader.canAppendTail()) { | ||
appendTail(buf, reader, line.getEnd(), unparsedEnd); | ||
} | ||
else { | ||
} else { | ||
if (!consumer.test(createUnparsedRecord(buf, unparsedStart, unparsedEnd))) | ||
return false; | ||
} | ||
|
@@ -378,8 +403,7 @@ public boolean processRecordsBack(long position, boolean fromPrevLine, Predicate | |
|
||
if (reader.canAppendTail()) { | ||
appendTail(buf, reader, line.getEnd(), unparsedEnd); | ||
} | ||
else { | ||
} else { | ||
if (!consumer.test(createUnparsedRecord(buf, unparsedStart, unparsedEnd))) | ||
return false; | ||
} | ||
|
@@ -414,8 +438,7 @@ public boolean processRecords(long position, boolean fromNextLine, Predicate<Log | |
if (fromNextLine) { | ||
if (!buf.loadNextLine(line, position)) | ||
return true; | ||
} | ||
else { | ||
} else { | ||
buf.loadLine(line, position); | ||
} | ||
|
||
|
@@ -529,8 +552,7 @@ public boolean processRecords(long position, boolean fromNextLine, Predicate<Log | |
if (!consumer.test(createUnparsedRecord(buf, unparsedStart, prevEnd))) | ||
return false; | ||
} | ||
} | ||
else { | ||
} else { | ||
if (!consumer.test(reader.buildRecord().setLogId(id))) | ||
return false; | ||
} | ||
|
@@ -603,7 +625,7 @@ private String calculateHash(long fileSize) throws LogCrashedException, IOExcept | |
crc.update(buf.array()); | ||
|
||
int hash = (int) crc.getValue(); | ||
long hashWithLength = (hash & 0xffff_ffffL) | ((long)hashSize << 32); | ||
long hashWithLength = (hash & 0xffff_ffffL) | ((long) hashSize << 32); | ||
|
||
return Long.toHexString(hashWithLength); | ||
} catch (EOFException e) { | ||
|
@@ -621,7 +643,7 @@ public boolean isValidHash(@NonNull String hash) { | |
|
||
int hashSize = (int) ((tLong >>> 32) & 0xff); | ||
|
||
if (hashSize == hashSize(size) ) { // Compare size of block used to has calculation. | ||
if (hashSize == hashSize(size)) { // Compare size of block used to has calculation. | ||
return hash.equals(this.hash); | ||
} | ||
|
||
|
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 was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest to change it to NIO2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did some searches, and find out there's no direct way in java nio API to get from gz to SeekableByteChannel.
I have to introduce some external dependencies and/or write custom code to accomplish this.
I appreciate your help on this.