From 8bb3e56cbb54f0efddb615b9f5883da50c8f42d8 Mon Sep 17 00:00:00 2001 From: JP Martin Date: Wed, 14 Dec 2016 17:04:35 -0800 Subject: [PATCH 1/4] Add optional wrapper for the underlying SeekableByteChannel This allows users to provide their own buffering or prefetching, without them having to change htsjdk. --- .../htsjdk/samtools/seekablestream/SeekablePathStream.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/htsjdk/samtools/seekablestream/SeekablePathStream.java b/src/main/java/htsjdk/samtools/seekablestream/SeekablePathStream.java index cb88512df..b7a33e601 100644 --- a/src/main/java/htsjdk/samtools/seekablestream/SeekablePathStream.java +++ b/src/main/java/htsjdk/samtools/seekablestream/SeekablePathStream.java @@ -43,6 +43,16 @@ public SeekablePathStream(final Path path, Function wrapper) throws IOException { + this.path = path; + if (null==wrapper) { + this.sbc = Files.newByteChannel(path); + } else { + this.sbc = wrapper.apply(Files.newByteChannel(path)); + } + ALL_INSTANCES.add(this); + } + @Override public long length() { try { From 6693de6d6aaaa13a8491491fbbfb6a9864b101b3 Mon Sep 17 00:00:00 2001 From: JP Martin Date: Wed, 11 Jan 2017 14:14:52 -0800 Subject: [PATCH 2/4] Index wrapper code --- src/main/java/htsjdk/samtools/SamInputResource.java | 8 +++++++- src/main/java/htsjdk/samtools/SamReaderFactory.java | 10 ++++++++-- .../htsjdk/samtools/seekablestream/SeekablePathStream.java | 10 ---------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/main/java/htsjdk/samtools/SamInputResource.java b/src/main/java/htsjdk/samtools/SamInputResource.java index d76694eeb..277c6e5fd 100644 --- a/src/main/java/htsjdk/samtools/SamInputResource.java +++ b/src/main/java/htsjdk/samtools/SamInputResource.java @@ -132,7 +132,13 @@ public SamInputResource index(final File file) { /** Updates the index to point at the provided resource, then returns itself. */ public SamInputResource index(final Path path) { - this.index = new PathInputResource(path, Function.identity()); + this.index = new PathInputResource(path); + return this; + } + + /** Updates the index to point at the provided resource, with the provided wrapper, then returns itself. */ + public SamInputResource index(final Path path, Function wrapper) { + this.index = new PathInputResource(path, wrapper); return this; } diff --git a/src/main/java/htsjdk/samtools/SamReaderFactory.java b/src/main/java/htsjdk/samtools/SamReaderFactory.java index a5eef5038..bb90ce094 100644 --- a/src/main/java/htsjdk/samtools/SamReaderFactory.java +++ b/src/main/java/htsjdk/samtools/SamReaderFactory.java @@ -82,9 +82,15 @@ abstract public SamReader open(final File file); public SamReader open(final Path path) { - final SamInputResource r = SamInputResource.of(path, getPathWrapper()); + return open(path, getPathWrapper(), Function.identity()); + } + + public SamReader open(final Path path, + Function pathWrapper, + Function indexWrapper) { + final SamInputResource r = SamInputResource.of(path, pathWrapper); final Path indexMaybe = SamFiles.findIndex(path); - if (indexMaybe != null) r.index(indexMaybe); + if (indexMaybe != null) r.index(indexMaybe, indexWrapper); return open(r); } diff --git a/src/main/java/htsjdk/samtools/seekablestream/SeekablePathStream.java b/src/main/java/htsjdk/samtools/seekablestream/SeekablePathStream.java index b7a33e601..cb88512df 100644 --- a/src/main/java/htsjdk/samtools/seekablestream/SeekablePathStream.java +++ b/src/main/java/htsjdk/samtools/seekablestream/SeekablePathStream.java @@ -43,16 +43,6 @@ public SeekablePathStream(final Path path, Function wrapper) throws IOException { - this.path = path; - if (null==wrapper) { - this.sbc = Files.newByteChannel(path); - } else { - this.sbc = wrapper.apply(Files.newByteChannel(path)); - } - ALL_INSTANCES.add(this); - } - @Override public long length() { try { From 496dcbfcc6e22849ebb20cf342e76479e73bd076 Mon Sep 17 00:00:00 2001 From: JP Martin Date: Thu, 19 Jan 2017 14:05:10 -0800 Subject: [PATCH 3/4] Add tests and javadoc Tested this version with GATK's ReadsDataSourceUnitTest, and it passes. --- .../java/htsjdk/samtools/SamReaderFactory.java | 44 ++++++++------------- .../htsjdk/samtools/PathInputResourceTest.java | 46 ++++++++++++++++++++++ .../java/htsjdk/samtools/SamReaderFactoryTest.java | 5 +-- src/test/java/htsjdk/samtools/SamReaderTest.java | 1 - 4 files changed, 64 insertions(+), 32 deletions(-) create mode 100644 src/test/java/htsjdk/samtools/PathInputResourceTest.java diff --git a/src/main/java/htsjdk/samtools/SamReaderFactory.java b/src/main/java/htsjdk/samtools/SamReaderFactory.java index bb90ce094..8f203d5c0 100644 --- a/src/main/java/htsjdk/samtools/SamReaderFactory.java +++ b/src/main/java/htsjdk/samtools/SamReaderFactory.java @@ -81,14 +81,26 @@ abstract public SamReader open(final File file); + /** + * Open the specified path (without using any wrappers). + * + * @param path the SAM or BAM file to open. + */ public SamReader open(final Path path) { - return open(path, getPathWrapper(), Function.identity()); + return open(path, null, null); } + /** + * Open the specified path, using the specified wrappers for prefetching/caching. + * + * @param path the SAM or BAM file to open + * @param dataWrapper the wrapper for the data (or null for none) + * @param indexWrapper the wrapper for the index (or null for none) + */ public SamReader open(final Path path, - Function pathWrapper, + Function dataWrapper, Function indexWrapper) { - final SamInputResource r = SamInputResource.of(path, pathWrapper); + final SamInputResource r = SamInputResource.of(path, dataWrapper); final Path indexMaybe = SamFiles.findIndex(path); if (indexMaybe != null) r.index(indexMaybe, indexWrapper); return open(r); @@ -112,25 +124,6 @@ public SamReader open(final Path path, /** Sets a specific Option to a boolean value. * */ abstract public SamReaderFactory setOption(final Option option, boolean value); - /** Sets a wrapper to modify the SeekableByteChannel from an opened Path, e.g. to add - * buffering or prefetching. This only works on Path inputs since we need a SeekableByteChannel. - * - * @param wrapper how to modify the SeekableByteChannel (Function.identity to unset) - * @return this - */ - public SamReaderFactory setPathWrapper(Function wrapper) { - this.pathWrapper = wrapper; - return this; - } - - /** Gets the wrapper previously set via setPathWrapper. - * - * @return the wrapper. - */ - public Function getPathWrapper() { - return pathWrapper; - } - /** Sets the specified reference sequence * */ abstract public SamReaderFactory referenceSequence(File referenceSequence); @@ -184,15 +177,10 @@ public static SamReaderFactory make() { private CRAMReferenceSource referenceSource; private SamReaderFactoryImpl(final EnumSet