From ab0eb4eaa86f8aa8a86fb1cc7557d8cbe0099078 Mon Sep 17 00:00:00 2001
From: Carsten Haubold
+ * This is {@code true} by default.
+ *
+ * Because processing of removed entries is done whenever the cache is accessed,
+ * this may also block accesses to the cache. (This is a good thing, because it
+ * avoids running out of memory because entries cannot be cleared fast
+ * enough...)
+ *
+ * This is {@code false} by default.
+ *
+ * This option only has an effect for {@link DiskCachedCellImg} that are created
+ * with a {@link CellLoader}
+ * ({@link DiskCachedCellImgFactory#create(long[], net.imglib2.type.NativeType, CellLoader)}).
+ *
From 294ebf2376a5e2a2843f6864383ebd718c307245 Mon Sep 17 00:00:00 2001
From: Carsten Haubold
+ *
+ *
+ * @param cacheType which cache type to use (default is {@code SOFTREF}).
+ */
+ public abstract AbstractReadWriteCachedCellImgOptions cacheType(final CacheType cacheType);
+
+ /**
+ * Set the maximum number of values (cells) to keep in the cache. This is only
+ * used if {@link #cacheType(CacheType)} is {@link CacheType#BOUNDED}.
+ *
+ * @param maxCacheSize maximum number of values in the cache (default is 1000).
+ */
+ public abstract AbstractReadWriteCachedCellImgOptions maxCacheSize(final long maxCacheSize);
+
+ /**
+ * Set the dimensions of a cell. This is extended or truncated as necessary. For
+ * example if {@code cellDimensions=[64,32]} then for creating a 3D image it
+ * will be augmented to {@code [64,32,32]}. For creating a 1D image it will be
+ * truncated to {@code [64]}.
+ *
+ * @param cellDimensions dimensions of a cell (default is 10).
+ */
+ public abstract AbstractReadWriteCachedCellImgOptions cellDimensions(final int... cellDimensions);
+
+ /**
+ * Specify whether cells initialized by a {@link CellLoader} should be marked as
+ * dirty. It is useful to set this to {@code true} if initialization is a costly
+ * operation. By this, it is made sure that cells are initialized only once, and
+ * then written and retrieve from the disk cache when they are next required.
+ * ImgFactory imgFactory(final S type) throws IncompatibleTypeException {
+ if (NativeType.class.isInstance(type))
+ return new DiskCachedCellImgFactory(factoryOptions);
+ throw new IncompatibleTypeException(this,
+ type.getClass().getCanonicalName() + " does not implement NativeType.");
}
private Path createBlockCachePath( final DiskCachedCellImgOptions.Values options )
@@ -308,6 +215,37 @@ else if ( dir != null )
}
}
+ @Override
+ AbstractReadWriteCachedCellImgOptions mergeWithFactoryOptions(
+ AbstractReadWriteCachedCellImgOptions userProvidedOptions) {
+ return ( userProvidedOptions == null ) ? factoryOptions : factoryOptions.merge(userProvidedOptions);
+ }
+
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ @Override
+ protected > CellCache createCellCache(AbstractReadWriteCachedCellImgOptions options,
+ CellGrid grid, CacheLoader
* For safety reasons, only cell cache directories that are created by the - * {@link DiskCachedCellImgFactory} are actually marked for deletion. This + * {@link AbstractReadWriteCachedCellImgFactory} are actually marked for deletion. This * means that either no {@link #cacheDirectory(Path)} is specified (a * temporary directory is created), or the specified * {@link #cacheDirectory(Path)} does not exist yet. @@ -252,7 +261,7 @@ public DiskCachedCellImgOptions tempDirectoryPrefix( final String prefix ) */ public DiskCachedCellImgOptions deleteCacheDirectoryOnExit( final boolean deleteOnExit ) { - return new DiskCachedCellImgOptions( values.copy().setDeleteCacheDirectoryOnExit( deleteOnExit ) ); + return new DiskCachedCellImgOptions(values.copy().setDeleteCacheDirectoryOnExit( deleteOnExit )); } /** @@ -267,7 +276,7 @@ public DiskCachedCellImgOptions deleteCacheDirectoryOnExit( final boolean delete *
* This option only has an effect for {@link DiskCachedCellImg} that are * created with a {@link CellLoader} - * ({@link DiskCachedCellImgFactory#create(long[], net.imglib2.type.NativeType, CellLoader)}). + * ({@link AbstractReadWriteCachedCellImgFactory#create(long[], net.imglib2.type.NativeType, CellLoader)}). *
* * @param initializeAsDirty @@ -276,33 +285,20 @@ public DiskCachedCellImgOptions deleteCacheDirectoryOnExit( final boolean delete */ public DiskCachedCellImgOptions initializeCellsAsDirty( final boolean initializeAsDirty ) { - return new DiskCachedCellImgOptions( values.copy().setInitializeCellsAsDirty( initializeAsDirty ) ); + return new DiskCachedCellImgOptions(values.copy().setInitializeCellsAsDirty( initializeAsDirty )); } /** * Read-only {@link DiskCachedCellImgOptions} values. */ - public static class Values + protected static class Values extends AbstractReadWriteCachedCellImgOptions.Values { /** * Copy constructor. */ Values( final Values that ) { - this.dirtyAccesses = that.dirtyAccesses; - this.dirtyAccessesModified = that.dirtyAccessesModified; - this.volatileAccesses = that.volatileAccesses; - this.volatileAccessesModified = that.volatileAccessesModified; - this.numIoThreads = that.numIoThreads; - this.numIoThreadsModified = that.numIoThreadsModified; - this.maxIoQueueSize = that.maxIoQueueSize; - this.maxIoQueueSizeModified = that.maxIoQueueSizeModified; - this.cacheType = that.cacheType; - this.cacheTypeModified = that.cacheTypeModified; - this.maxCacheSize = that.maxCacheSize; - this.maxCacheSizeModified = that.maxCacheSizeModified; - this.cellDimensions = that.cellDimensions; - this.cellDimensionsModified = that.cellDimensionsModified; + super(that); this.cacheDirectory = that.cacheDirectory; this.cacheDirectoryModified = that.cacheDirectoryModified; this.tempDirectory = that.tempDirectory; @@ -311,8 +307,6 @@ public static class Values this.tempDirectoryPrefixModified = that.tempDirectoryPrefixModified; this.deleteCacheDirectoryOnExit = that.deleteCacheDirectoryOnExit; this.deleteCacheDirectoryOnExitModified = that.deleteCacheDirectoryOnExitModified; - this.initializeCellsAsDirty = that.initializeCellsAsDirty; - this.initializeCellsAsDirtyModified = that.initializeCellsAsDirtyModified; } Values() @@ -320,27 +314,7 @@ public static class Values Values( final Values base, final Values aug ) { - dirtyAccesses = aug.dirtyAccessesModified - ? aug.dirtyAccesses - : base.dirtyAccesses; - volatileAccesses = aug.volatileAccessesModified - ? aug.volatileAccesses - : base.volatileAccesses; - numIoThreads = aug.numIoThreadsModified - ? aug.numIoThreads - : base.numIoThreads; - maxIoQueueSize = aug.maxIoQueueSizeModified - ? aug.maxIoQueueSize - : base.maxIoQueueSize; - cacheType = aug.cacheTypeModified - ? aug.cacheType - : base.cacheType; - maxCacheSize = aug.maxCacheSizeModified - ? aug.maxCacheSize - : base.maxCacheSize; - cellDimensions = aug.cellDimensionsModified - ? aug.cellDimensions - : base.cellDimensions; + super(base, aug); cacheDirectory = aug.cacheDirectoryModified ? aug.cacheDirectory : base.cacheDirectory; @@ -353,30 +327,17 @@ public static class Values deleteCacheDirectoryOnExit = aug.deleteCacheDirectoryOnExitModified ? aug.deleteCacheDirectoryOnExit : base.deleteCacheDirectoryOnExit; - initializeCellsAsDirty = aug.initializeCellsAsDirtyModified - ? aug.initializeCellsAsDirty - : base.initializeCellsAsDirty; } - public DiskCachedCellImgOptions optionsFromValues() + Values( final Values base, final AbstractReadWriteCachedCellImgOptions.Values aug ) { - return new DiskCachedCellImgOptions( new Values( this ) ); + super(base, aug); + cacheDirectory = base.cacheDirectory; + tempDirectory = base.tempDirectory; + tempDirectoryPrefix = base.tempDirectoryPrefix; + deleteCacheDirectoryOnExit = base.deleteCacheDirectoryOnExit; } - private boolean dirtyAccesses = true; - - private boolean volatileAccesses = true; - - private int numIoThreads = 1; - - private int maxIoQueueSize = 10; - - private CacheType cacheType = CacheType.SOFTREF; - - private long maxCacheSize = 1000; - - private int[] cellDimensions = new int[] { 10 }; - private Path cacheDirectory = null; private Path tempDirectory = null; @@ -385,48 +346,6 @@ public DiskCachedCellImgOptions optionsFromValues() private boolean deleteCacheDirectoryOnExit = true; - private boolean initializeCellsAsDirty = false; - - public boolean dirtyAccesses() - { - return dirtyAccesses; - } - - public boolean volatileAccesses() - { - return volatileAccesses; - } - - public Set< AccessFlags > accessFlags() - { - return AccessFlags.fromBooleansDirtyVolatile( dirtyAccesses, volatileAccesses ); - } - - public int numIoThreads() - { - return numIoThreads; - } - - public int maxIoQueueSize() - { - return maxIoQueueSize; - } - - public CacheType cacheType() - { - return cacheType; - } - - public long maxCacheSize() - { - return maxCacheSize; - } - - public int[] cellDimensions() - { - return cellDimensions; - } - public Path cacheDirectory() { return cacheDirectory; @@ -447,25 +366,6 @@ public boolean deleteCacheDirectoryOnExit() return deleteCacheDirectoryOnExit; } - public boolean initializeCellsAsDirty() - { - return initializeCellsAsDirty; - } - - private boolean dirtyAccessesModified = false; - - private boolean volatileAccessesModified = false; - - private boolean numIoThreadsModified = false; - - private boolean maxIoQueueSizeModified = false; - - private boolean cacheTypeModified = false; - - private boolean maxCacheSizeModified = false; - - private boolean cellDimensionsModified = false; - private boolean cacheDirectoryModified = false; private boolean tempDirectoryModified = false; @@ -474,145 +374,93 @@ public boolean initializeCellsAsDirty() private boolean deleteCacheDirectoryOnExitModified = false; - private boolean initializeCellsAsDirtyModified = false; - - Values setDirtyAccesses( final boolean b ) + Values setCacheDirectory( final Path dir ) { - dirtyAccesses = b; - dirtyAccessesModified = true; + cacheDirectory = dir; + cacheDirectoryModified = true; return this; } - Values setVolatileAccesses( final boolean b ) + Values setTempDirectory( final Path dir ) { - volatileAccesses = b; - volatileAccessesModified = true; + tempDirectory = dir; + tempDirectoryModified = true; return this; } - Values setNumIoThreads( final int n ) + Values setTempDirectoryPrefix( final String prefix ) { - numIoThreads = n; - numIoThreadsModified = true; + tempDirectoryPrefix = prefix; + tempDirectoryPrefixModified = true; return this; } - Values setMaxIoQueueSize( final int n ) + Values setDeleteCacheDirectoryOnExit( final boolean b ) { - maxIoQueueSize = n; - maxIoQueueSizeModified = true; + deleteCacheDirectoryOnExit = b; + deleteCacheDirectoryOnExitModified = true; return this; } - Values setCacheType( final CacheType t ) + @Override + Values setDirtyAccesses( final boolean b ) { - cacheType = t; - cacheTypeModified = true; + super.setDirtyAccesses(b); return this; } - Values setMaxCacheSize( final long n ) + @Override + Values setVolatileAccesses( final boolean b ) { - maxCacheSize = n; - maxCacheSizeModified = true; + super.setVolatileAccesses(b); return this; } - Values setCellDimensions( final int[] dims ) + @Override + Values setCacheType( final CacheType t ) { - cellDimensions = dims; - cellDimensionsModified = true; + super.setCacheType(t); return this; } - Values setCacheDirectory( final Path dir ) + @Override + Values setMaxCacheSize( final long n ) { - cacheDirectory = dir; - cacheDirectoryModified = true; + super.setMaxCacheSize(n); return this; } - Values setTempDirectory( final Path dir ) + @Override + Values setCellDimensions( final int[] dims ) { - tempDirectory = dir; - tempDirectoryModified = true; + super.setCellDimensions(dims); return this; } - Values setTempDirectoryPrefix( final String prefix ) - { - tempDirectoryPrefix = prefix; - tempDirectoryPrefixModified = true; + @Override + Values setNumIoThreads(final int n) { + super.setNumIoThreads(n); return this; } - Values setDeleteCacheDirectoryOnExit( final boolean b ) - { - deleteCacheDirectoryOnExit = b; - deleteCacheDirectoryOnExitModified = true; + @Override + Values setMaxIoQueueSize(final int n) { + super.setMaxIoQueueSize(n); return this; } - Values setInitializeCellsAsDirty( final boolean b ) - { - initializeCellsAsDirty = b; - initializeCellsAsDirtyModified = true; + @Override + Values setInitializeCellsAsDirty(final boolean b) { + super.setInitializeCellsAsDirty(b); return this; } - Values copy() - { - return new Values( this ); - } - @Override public String toString() { final StringBuilder sb = new StringBuilder(); - - sb.append( "{" ); - - sb.append( "dirtyAccesses = " ); - sb.append( Boolean.toString( dirtyAccesses ) ); - if ( dirtyAccessesModified ) - sb.append( " [m]" ); - sb.append( ", " ); - - sb.append( "volatileAccesses = " ); - sb.append( Boolean.toString( volatileAccesses ) ); - if ( volatileAccessesModified ) - sb.append( " [m]" ); - sb.append( ", " ); - - sb.append( "numIoThreads = " ); - sb.append( numIoThreads ); - if ( numIoThreadsModified ) - sb.append( " [m]" ); - sb.append( ", " ); - - sb.append( "maxIoQueueSize = " ); - sb.append( maxIoQueueSize ); - if ( maxIoQueueSizeModified ) - sb.append( " [m]" ); - sb.append( ", " ); - - sb.append( "cacheType = " ); - sb.append( cacheType ); - if ( cacheTypeModified ) - sb.append( " [m]" ); - sb.append( ", " ); - - sb.append( "maxCacheSize = " ); - sb.append( maxCacheSize ); - if ( maxCacheSizeModified ) - sb.append( " [m]" ); - sb.append( ", " ); - - sb.append( "cellDimensions = " ); - sb.append( Util.printCoordinates( cellDimensions ) ); - if ( cellDimensionsModified ) - sb.append( " [m]" ); - sb.append( ", " ); + sb.append(super.toString()); + sb.append( "DiskCachedCellImgOptions = {" ); sb.append( "cacheDirectory = " ); sb.append( cacheDirectory ); @@ -637,14 +485,14 @@ public String toString() if ( deleteCacheDirectoryOnExitModified ) sb.append( " [m]" ); - sb.append( "initializeCellsAsDirty = " ); - sb.append( Boolean.toString( initializeCellsAsDirty ) ); - if ( initializeCellsAsDirtyModified ) - sb.append( " [m]" ); - sb.append( "}" ); return sb.toString(); } + + @Override + Values copy() { + return new Values(this); + } } } diff --git a/src/main/java/net/imglib2/cache/img/ReadOnlyCachedCellImgFactory.java b/src/main/java/net/imglib2/cache/img/ReadOnlyCachedCellImgFactory.java index cd7e9d3..21a322c 100644 --- a/src/main/java/net/imglib2/cache/img/ReadOnlyCachedCellImgFactory.java +++ b/src/main/java/net/imglib2/cache/img/ReadOnlyCachedCellImgFactory.java @@ -123,8 +123,8 @@ public < T extends NativeType< T >, A > CachedCellImg< T, A > createWithCacheLoa final ReadOnlyCachedCellImgOptions additionalOptions ) { final ReadOnlyCachedCellImgOptions.Values options = ( additionalOptions == null ) - ? factoryOptions.values - : new ReadOnlyCachedCellImgOptions.Values( factoryOptions.values, additionalOptions.values ); + ? factoryOptions.values() + : factoryOptions.merge(additionalOptions).values(); final PrimitiveType primitiveType = type.getNativeTypeFactory().getPrimitiveType(); final Fraction entitiesPerPixel = type.getEntitiesPerPixel(); diff --git a/src/main/java/net/imglib2/cache/img/ReadOnlyCachedCellImgOptions.java b/src/main/java/net/imglib2/cache/img/ReadOnlyCachedCellImgOptions.java index 5d82b05..46e219e 100644 --- a/src/main/java/net/imglib2/cache/img/ReadOnlyCachedCellImgOptions.java +++ b/src/main/java/net/imglib2/cache/img/ReadOnlyCachedCellImgOptions.java @@ -43,7 +43,7 @@ */ public class ReadOnlyCachedCellImgOptions { - public final Values values; + private final Values values; ReadOnlyCachedCellImgOptions( final Values values ) { @@ -65,6 +65,22 @@ public static ReadOnlyCachedCellImgOptions options() return new ReadOnlyCachedCellImgOptions(); } + /** + * @return The values of this options object + */ + public Values values() { + return values; + } + + /** + * @param other Options that should be merged with this option object + * @return New {@link ReadOnlyCachedCellImgOptions} containing the options of this object, + * overwritten by the non-default settings in the provided other options object + */ + public ReadOnlyCachedCellImgOptions merge(final ReadOnlyCachedCellImgOptions other) { + return new ReadOnlyCachedCellImgOptions(new Values(values, other.values)); + } + /** * Specify whether the image should use {@link Dirty} accesses. Dirty * accesses track whether cells were written to. @@ -176,10 +192,22 @@ public ReadOnlyCachedCellImgOptions cellDimensions( final int... cellDimensions } /** - * Read-only {@link ReadOnlyCachedCellImgOptions} values. + * Abstract base class for read-only {@link ReadOnlyCachedCellImgOptions} values, that can be extended + * in specialized classes to e.g. add options for writeable caches. + * + * We use the curious recuring template pattern here to facilitate chaining the builder methods while + * maintaining the concrete type of the values object. Hence non-abstract derived classes must implement + * a self() method which is used to return an instance to the updated value object. */ - public static class Values + protected static class Values { + /** + * @return a copy of this value object + */ + Values copy() { + return new Values(this); + } + /** * Copy constructor. */ @@ -219,20 +247,15 @@ public static class Values : base.cellDimensions; } - public ReadOnlyCachedCellImgOptions optionsFromValues() - { - return new ReadOnlyCachedCellImgOptions( new Values( this ) ); - } + protected boolean dirtyAccesses = false; - private boolean dirtyAccesses = false; + protected boolean volatileAccesses = true; - private boolean volatileAccesses = true; + protected CacheType cacheType = CacheType.SOFTREF; - private CacheType cacheType = CacheType.SOFTREF; + protected long maxCacheSize = 1000; - private long maxCacheSize = 1000; - - private int[] cellDimensions = new int[] { 10 }; + protected int[] cellDimensions = new int[] { 10 }; public boolean dirtyAccesses() { @@ -264,15 +287,15 @@ public int[] cellDimensions() return cellDimensions; } - private boolean dirtyAccessesModified = false; + protected boolean dirtyAccessesModified = false; - private boolean volatileAccessesModified = false; + protected boolean volatileAccessesModified = false; - private boolean cacheTypeModified = false; + protected boolean cacheTypeModified = false; - private boolean maxCacheSizeModified = false; + protected boolean maxCacheSizeModified = false; - private boolean cellDimensionsModified = false; + protected boolean cellDimensionsModified = false; Values setDirtyAccesses( final boolean b ) { @@ -309,17 +332,12 @@ Values setCellDimensions( final int[] dims ) return this; } - Values copy() - { - return new Values( this ); - } - @Override public String toString() { final StringBuilder sb = new StringBuilder(); - sb.append( "{" ); + sb.append( "ReadOnlyCachedCellImgOptions = {" ); sb.append( "dirtyAccesses = " ); sb.append( Boolean.toString( dirtyAccesses ) ); From 054076b01735a1e326ca4704fd045521495114a9 Mon Sep 17 00:00:00 2001 From: Carsten Haubold* For safety reasons, only cell cache directories that are created by the - * {@link AbstractReadWriteCachedCellImgFactory} are actually marked for deletion. This + * {@link DiskCachedCellImgFactory} are actually marked for deletion. This * means that either no {@link #cacheDirectory(Path)} is specified (a * temporary directory is created), or the specified * {@link #cacheDirectory(Path)} does not exist yet. @@ -275,8 +275,7 @@ public DiskCachedCellImgOptions deleteCacheDirectoryOnExit( final boolean delete *
** This option only has an effect for {@link DiskCachedCellImg} that are - * created with a {@link CellLoader} - * ({@link AbstractReadWriteCachedCellImgFactory#create(long[], net.imglib2.type.NativeType, CellLoader)}). + * created with a {@link CellLoader} ({@link DiskCachedCellImgFactory#create(net.imglib2.Dimensions, CellLoader)}}) *
* * @param initializeAsDirty