diff --git a/concurrent-tile-cache/pom.xml b/concurrent-tile-cache/pom.xml
index c6f6061d..8e9ca15c 100644
--- a/concurrent-tile-cache/pom.xml
+++ b/concurrent-tile-cache/pom.xml
@@ -17,26 +17,10 @@
gt-coverage
${geotools.version}
-
- com.googlecode.concurrentlinkedhashmap
- concurrentlinkedhashmap-lru
- 1.3.2
-
-
- com.boundary
- high-scale-lib
- 1.0.3
-
com.google.guava
guava
${guava.version}
-
-
- boundary-site
- http://maven.boundary.com/artifactory/repo
-
-
diff --git a/concurrent-tile-cache/src/main/java/it/geosolutions/concurrent/ConcurrentTileCache.java b/concurrent-tile-cache/src/main/java/it/geosolutions/concurrent/ConcurrentTileCache.java
index dee91556..c00eead9 100644
--- a/concurrent-tile-cache/src/main/java/it/geosolutions/concurrent/ConcurrentTileCache.java
+++ b/concurrent-tile-cache/src/main/java/it/geosolutions/concurrent/ConcurrentTileCache.java
@@ -105,9 +105,6 @@ public int weigh(Object o, CachedTileImpl cti) {
return (int) cti.getTileSize();
}
});
- if (diagnosticEnabled) {
- builder.removalListener(listener).recordStats();
- }
return builder.build();
diff --git a/concurrent-tile-cache/src/main/java/it/geosolutions/concurrent/ConcurrentTileCacheMultiMap.java b/concurrent-tile-cache/src/main/java/it/geosolutions/concurrent/ConcurrentTileCacheMultiMap.java
index 559416ae..0f76eaa8 100644
--- a/concurrent-tile-cache/src/main/java/it/geosolutions/concurrent/ConcurrentTileCacheMultiMap.java
+++ b/concurrent-tile-cache/src/main/java/it/geosolutions/concurrent/ConcurrentTileCacheMultiMap.java
@@ -7,20 +7,36 @@
import java.awt.image.RenderedImage;
import java.util.Comparator;
import java.util.Iterator;
+import java.util.Map;
import java.util.Observable;
import java.util.Set;
import java.util.Vector;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import javax.media.jai.TileCache;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.RemovalCause;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;
import com.google.common.cache.Weigher;
import com.sun.media.jai.util.CacheDiagnostics;
+/**
+ * This implementation of the TileCache class uses a Guava Cache and a multimap in order to provide a better concurrency handling. The first object
+ * contains all the cached tiles while the second one contains the mapping of the tile keys for each image. This class implements
+ * {@link CacheDiagnostics} in order to get the statistics associated to the {@link TileCache}. The user can define the cache memory capacity, the
+ * concurrency level (which indicates in how many segments the cache must be divided), the threshold of the total memory to use and a boolean
+ * indicating if the diagnostic must be enabled.
+ *
+ * @author Nicola Lagomarsini GeoSolutions S.A.S.
+ *
+ */
public class ConcurrentTileCacheMultiMap extends Observable implements TileCache, CacheDiagnostics {
/** The default memory threshold of the cache. */
@@ -43,11 +59,14 @@ public class ConcurrentTileCacheMultiMap extends Observable implements TileCache
/**
* A concurrent multimap used for mapping the tile keys for each image
*/
- private Cache> multimap;
+ private Map> multimap;
/** The memory capacity of the cache. */
private long memoryCacheCapacity;
+ /** The current memory capacity of the cache. */
+ private AtomicLong currentCacheCapacity;
+
/** The concurrency level of the cache. */
private int concurrencyLevel;
@@ -58,9 +77,10 @@ public class ConcurrentTileCacheMultiMap extends Observable implements TileCache
private volatile boolean diagnosticEnabled = DEFAULT_DIAGNOSTIC;
/**
- * The listener is used for receiving notification about the removal of a tile
+ * Logger to use for reporting the informations about the TileCache operations.
*/
- private final RemovalListener listener;
+ private final static Logger LOGGER = Logger.getLogger(ConcurrentTileCacheMultiMap.class
+ .toString());
public ConcurrentTileCacheMultiMap() {
this(DEFAULT_MEMORY_CACHE, DEFAULT_DIAGNOSTIC, DEFAULT_MEMORY_THRESHOLD,
@@ -77,14 +97,11 @@ public ConcurrentTileCacheMultiMap(long memoryCacheCapacity, boolean diagnostic,
this.memoryCacheCapacity = memoryCacheCapacity;
this.concurrencyLevel = concurrencyLevel;
- // Listener creation
- listener = createListener(diagnostic);
-
// cache creation
cacheObject = buildCache();
// multimap creation
- multimap = CacheBuilder.newBuilder().concurrencyLevel(concurrencyLevel).build();
+ multimap = new ConcurrentHashMap>();
}
/** Add a new tile to the cache */
@@ -96,35 +113,42 @@ public void add(RenderedImage owner, int tileX, int tileY, Raster data) {
public void add(RenderedImage owner, int tileX, int tileY, Raster data, Object tileCacheMetric) {
// This tile is not in the cache; create a new CachedTileImpl.
// else just update.
- Object key = CachedTileImpl.hashKey(owner, tileX, tileY);
+
// Key associated to the image
Object imageKey = CachedTileImpl.hashKey(owner);
+
// old tile
CachedTileImpl cti;
// create a new tile
CachedTileImpl cti_new = new CachedTileImpl(owner, tileX, tileY, data, tileCacheMetric);
- // if the tile is already cached
if (diagnosticEnabled) {
- cti = (CachedTileImpl) cacheObject.asMap().put(key, cti_new);
- synchronized (this) {
+ // if the tile is already cached
+ cti = (CachedTileImpl) cacheObject.asMap().putIfAbsent(cti_new.key, cti_new);
+ synchronized (cacheObject) {
if (cti != null) {
cti.updateTileTimeStamp();
cti.setAction(Actions.SUBSTITUTION_FROM_ADD);
setChanged();
notifyObservers(cti);
}
+ // Update Cache Memory Size
+ currentCacheCapacity.addAndGet(cti_new.getTileSize());
+ // Update the tile action in order to notify it to the observers
cti_new.setAction(Actions.ADDITION);
setChanged();
notifyObservers(cti_new);
- updateMultiMap(key, imageKey);
+ updateMultiMap(cti_new.key, imageKey);
}
} else {
+ if (LOGGER.isLoggable(Level.FINE)) {
+ LOGGER.fine("Added new Tile Image key " + imageKey);
+ }
// new tile insertion
- cacheObject.put(key, cti_new);
+ cacheObject.asMap().putIfAbsent(cti_new.key, cti_new);
// Atomically adds a new Map if needed and then adds a new tile inside the MultiMap.
- updateMultiMap(key, imageKey);
+ updateMultiMap(cti_new.key, imageKey);
}
}
@@ -133,7 +157,7 @@ public void remove(RenderedImage owner, int tileX, int tileY) {
// Calculation of the tile key
Object key = CachedTileImpl.hashKey(owner, tileX, tileY);
// remove operation
- removeTileFromKey(key);
+ removeTileByKey(key);
}
/** Retrieves the selected tile from the cache */
@@ -155,14 +179,20 @@ public Raster[] getTiles(RenderedImage owner) {
// Calculation of the key associated to the image
Object imageKey = CachedTileImpl.hashKey(owner);
- Set keys = multimap.getIfPresent(imageKey);
+ if (LOGGER.isLoggable(Level.FINE)) {
+ LOGGER.fine("Getting image Tiles Image key " + imageKey);
+ }
+ // Selection of the tile keys for the image
+ Set keys = multimap.get(imageKey);
+ // If no key is found then a null object is returned
if (keys == null || keys.isEmpty()) {
return tilesData;
}
+ // Else it is created an iterator on the tile keys
Iterator it = keys.iterator();
-
+ // Another check on the iterator
if (it.hasNext()) {
// arbitrarily set a temporary vector size
Vector tempData = new Vector(10, 20);
@@ -170,6 +200,7 @@ public Raster[] getTiles(RenderedImage owner) {
// cache...
while (it.hasNext()) {
Object key = it.next();
+ // get the tile from the key
Raster rasterTile = getTileFromKey(key);
// ...then add to the vector if present
@@ -177,7 +208,7 @@ public Raster[] getTiles(RenderedImage owner) {
tempData.add(rasterTile);
}
}
-
+ // Vector size
int tmpsize = tempData.size();
if (tmpsize > 0) {
tilesData = (Raster[]) tempData.toArray(new Raster[tmpsize]);
@@ -195,23 +226,25 @@ public void removeTiles(RenderedImage owner) {
Object imageKey = CachedTileImpl.hashKey(owner);
if (diagnosticEnabled) {
- synchronized (this) {
- Set keys = multimap.getIfPresent(imageKey);
+ synchronized (cacheObject) {
+ // Selection of the keys associated to the image and removal of each of them
+ Set keys = multimap.get(imageKey);
if (keys != null) {
Iterator it = keys.iterator();
while (it.hasNext()) {
Object key = it.next();
- removeTileFromKey(key);
+ removeTileByKey(key);
}
}
}
} else {
// Get the keys associated to the image and remove them
- Set keys = multimap.getIfPresent(imageKey);
+ Set keys = multimap.get(imageKey);
if (keys != null) {
+ if (LOGGER.isLoggable(Level.FINE)) {
+ LOGGER.fine("Removing image Tiles Image key " + imageKey);
+ }
cacheObject.invalidateAll(keys);
- // Then remove the multimap
- multimap.invalidate(imageKey);
}
}
}
@@ -221,6 +254,9 @@ public void removeTiles(RenderedImage owner) {
*/
public void addTiles(RenderedImage owner, Point[] tileIndices, Raster[] tiles,
Object tileCacheMetric) {
+ if (LOGGER.isLoggable(Level.FINE)) {
+ LOGGER.fine("Addeding Tiles");
+ }
// cycle through the array for adding tiles
for (int i = 0; i < tileIndices.length; i++) {
int tileX = tileIndices[i].x;
@@ -237,6 +273,10 @@ public void addTiles(RenderedImage owner, Point[] tileIndices, Raster[] tiles,
public Raster[] getTiles(RenderedImage owner, Point[] tileIndices) {
// instantiation of the array
Raster[] tilesData = new Raster[tileIndices.length];
+
+ if (LOGGER.isLoggable(Level.FINE)) {
+ LOGGER.fine("Getting Tiles at the selected positions");
+ }
// cycle through the array for getting tiles
for (int i = 0; i < tilesData.length; i++) {
int tileX = tileIndices[i].x;
@@ -257,31 +297,38 @@ public Raster[] getTiles(RenderedImage owner, Point[] tileIndices) {
}
/** Removes all tiles present in the cache without checking for the image owner */
- public synchronized void flush() {
- // It is necessary to clear all the elements
- // from the old cache.
- if (diagnosticEnabled) {
- // Creation of an iterator for accessing to every tile in the cache
- Iterator keys = cacheObject.asMap().keySet().iterator();
- // cycle across the cache for removing and updating every tile
- while (keys.hasNext()) {
- Object key = keys.next();
- CachedTileImpl cti = (CachedTileImpl) cacheObject.asMap().remove(key);
+ public void flush() {
+ synchronized (cacheObject) {
+ // It is necessary to clear all the elements
+ // from the old cache.
+ if (diagnosticEnabled) {
+ // Creation of an iterator for accessing to every tile in the cache
+ Iterator keys = cacheObject.asMap().keySet().iterator();
+ // cycle across the cache for removing and updating every tile
+ while (keys.hasNext()) {
+ Object key = keys.next();
+ CachedTileImpl cti = (CachedTileImpl) cacheObject.asMap().remove(key);
- // diagnosticEnabled
+ // diagnosticEnabled
- cti.setAction(Actions.REMOVAL_FROM_FLUSH);
- setChanged();
- notifyObservers(cti);
+ cti.setAction(Actions.REMOVAL_FROM_FLUSH);
+ setChanged();
+ notifyObservers(cti);
+ }
+ } else {
+ // Invalidation of all the keys of the cache
+ cacheObject.invalidateAll();
}
- } else {
- cacheObject.invalidateAll();
- }
- // multimap creation
- multimap = CacheBuilder.newBuilder().concurrencyLevel(concurrencyLevel).build();
+ if (LOGGER.isLoggable(Level.FINE)) {
+ LOGGER.fine("Flushing cache");
+ }
- cacheObject = buildCache();
+ // Cache creation
+ cacheObject = buildCache();
+ // multimap creation
+ multimap = new ConcurrentHashMap>();
+ }
}
/**
@@ -291,7 +338,6 @@ public synchronized void flush() {
*/
public void memoryControl() {
throw new UnsupportedOperationException("Memory Control not supported");
-
}
/**
@@ -313,15 +359,16 @@ public int getTileCapacity() {
}
/** Sets the cache memory capacity and then flush and rebuild the cache */
- public synchronized void setMemoryCapacity(long memoryCacheCapacity) {
- if (memoryCacheCapacity < 0) {
- throw new IllegalArgumentException("Memory capacity too small");
- } else {
- this.memoryCacheCapacity = memoryCacheCapacity;
- flush();
-
+ public void setMemoryCapacity(long memoryCacheCapacity) {
+ synchronized (cacheObject) {
+ if (memoryCacheCapacity < 0) {
+ throw new IllegalArgumentException("Memory capacity too small");
+ } else {
+ this.memoryCacheCapacity = memoryCacheCapacity;
+ // The flush is done in order to rebuild the cache with the new settings
+ flush();
+ }
}
-
}
/** Retrieve the cache memory capacity */
@@ -330,15 +377,17 @@ public long getMemoryCapacity() {
}
/** Sets the cache memory threshold and then flush and rebuild the cache */
- public synchronized void setMemoryThreshold(float mt) {
- if (mt < 0.0F || mt > 1.0F) {
- throw new IllegalArgumentException("Memory threshold should be between 0 and 1");
- } else {
- memoryCacheThreshold = mt;
- flush();
+ public void setMemoryThreshold(float mt) {
+ synchronized (cacheObject) {
+ if (mt < 0.0F || mt > 1.0F) {
+ throw new IllegalArgumentException("Memory threshold should be between 0 and 1");
+ } else {
+ memoryCacheThreshold = mt;
+ // The flush is done in order to rebuild the cache with the new settings
+ flush();
+ }
}
-
}
/** Retrieve the cache memory threshold */
@@ -347,15 +396,17 @@ public float getMemoryThreshold() {
}
/** Sets the cache ConcurrencyLevel and then flush and rebuild the cache */
- public synchronized void setConcurrencyLevel(int concurrency) {
- if (concurrency < 1) {
- throw new IllegalArgumentException("ConcurrencyLevel must be at least 1");
- } else {
- concurrencyLevel = concurrency;
- flush();
+ public void setConcurrencyLevel(int concurrency) {
+ synchronized (cacheObject) {
+ if (concurrency < 1) {
+ throw new IllegalArgumentException("ConcurrencyLevel must be at least 1");
+ } else {
+ concurrencyLevel = concurrency;
+ // The flush is done in order to rebuild the cache with the new settings
+ flush();
+ }
}
-
}
/** Retrieve the cache concurrency level */
@@ -383,17 +434,21 @@ public Comparator getTileComparator() {
}
/** Disables diagnosticEnabled for the observers */
- public synchronized void disableDiagnostics() {
- diagnosticEnabled = false;
- flush();
-
+ public void disableDiagnostics() {
+ synchronized (cacheObject) {
+ diagnosticEnabled = false;
+ // The flush is done in order to rebuild the cache with the new settings
+ flush();
+ }
}
/** Enables diagnosticEnabled for the observers */
- public synchronized void enableDiagnostics() {
- diagnosticEnabled = true;
- flush();
-
+ public void enableDiagnostics() {
+ synchronized (cacheObject) {
+ diagnosticEnabled = true;
+ // The flush is done in order to rebuild the cache with the new settings
+ flush();
+ }
}
/** Retrieves the hit count from the cache statistics */
@@ -405,27 +460,8 @@ public long getCacheHitCount() {
}
/** Retrieves the current memory size of the cache */
- public synchronized long getCacheMemoryUsed() {
- Iterator keys = multimap.asMap().keySet().iterator();
- long memoryUsed = 0;
- while (keys.hasNext()) {
- Object keyImage = keys.next();
- Set tileKeys = multimap.getIfPresent(keyImage);
- if (tileKeys != null) {
- int numTiles = tileKeys.size();
- Iterator iterator = tileKeys.iterator();
- if (numTiles > 0) {
- CachedTileImpl cti = null;
- while (cti == null && iterator.hasNext()) {
- cti = cacheObject.getIfPresent(iterator.next());
- }
- if (cti != null) {
- memoryUsed += (cti.getTileSize() * numTiles);
- }
- }
- }
- }
- return memoryUsed;
+ public long getCacheMemoryUsed() {
+ return currentCacheCapacity.get();
}
/** Retrieves the miss count from the cache statistics */
@@ -450,6 +486,12 @@ public void resetCounts() {
throw new UnsupportedOperationException("Operation not supported");
}
+ /**
+ * Creation of a listener to use for handling the removed tiles
+ *
+ * @param diagnostic
+ * @return
+ */
private RemovalListener createListener(final boolean diagnostic) {
return new RemovalListener() {
public void onRemoval(RemovalNotification n) {
@@ -458,33 +500,64 @@ public void onRemoval(RemovalNotification n) {
// the remove() method
if (diagnostic) {
- synchronized (this) {
+ synchronized (cacheObject) {
+ CachedTileImpl cti = n.getValue();
+ // Update of the tile action
if (n.wasEvicted()) {
- CachedTileImpl cti = n.getValue();
cti.setAction(Actions.REMOVAL_FROM_EVICTION);
- removeFromMultiMap(cti);
- setChanged();
- notifyObservers(cti);
+ } else {
+ cti.setAction(Actions.MANUAL_REMOVAL);
}
+ // Update Cache Memory Size
+ currentCacheCapacity.addAndGet(-cti.getTileSize());
+ // Removal from the multimap
+ removeTileFromMultiMap(cti);
+ setChanged();
+ notifyObservers(cti);
}
} else {
- if (n.wasEvicted()) {
- CachedTileImpl cti = n.getValue();
- removeFromMultiMap(cti);
+ CachedTileImpl cti = n.getValue();
+ if (n.getCause() == RemovalCause.SIZE) {
+ // Logging if the tile is removed because the size is exceeded
+ if (LOGGER.isLoggable(Level.FINE)) {
+ LOGGER.fine("Removing from MultiMap for size");
+ }
}
+ removeTileFromMultiMap(cti);
}
}
};
}
- private void removeFromMultiMap(CachedTileImpl cti) {
+ /**
+ * Method for removing the tile keys from the multimap. If the KeySet associated to the image is empty, it is removed from the multimap.
+ *
+ * @param cti
+ */
+ private void removeTileFromMultiMap(CachedTileImpl cti) {
+ // Tile key
Object key = cti.getKey();
+ // Image key
Object imageKey = cti.getImageKey();
- Set tileKeys = multimap.getIfPresent(imageKey);
+ // KeySet associated to the image
+ Set tileKeys = multimap.get(imageKey);
+
+ if (LOGGER.isLoggable(Level.FINE)) {
+ LOGGER.fine("Removing tile from MultiMap Image key " + imageKey);
+ }
+
if (tileKeys != null) {
+ // Removal of the keys
tileKeys.remove(key);
+ if (LOGGER.isLoggable(Level.FINE)) {
+ LOGGER.fine("Removed Tile Image key " + imageKey);
+ }
+ // If the KeySet is empty then it is removed from the multimap
if (tileKeys.isEmpty()) {
- multimap.invalidate(imageKey);
+ multimap.remove(imageKey);
+ if (LOGGER.isLoggable(Level.FINE)) {
+ LOGGER.fine("Removed image SET Image key " + imageKey);
+ }
}
}
}
@@ -498,58 +571,99 @@ public int weigh(Object o, CachedTileImpl cti) {
return (int) cti.getTileSize();
}
});
- builder.removalListener(listener);
- if (diagnosticEnabled) {
- builder.recordStats();
+ // Setting of the listener
+ builder.removalListener(createListener(diagnosticEnabled));
+
+ if (LOGGER.isLoggable(Level.FINE)) {
+ LOGGER.fine("Building Cache");
}
+ // Update of the Memory cache size
+ currentCacheCapacity = new AtomicLong(0);
return builder.build();
}
+ /**
+ * Update of the multimap when a tile is added.
+ *
+ * @param key
+ * @param imageKey
+ */
private void updateMultiMap(Object key, Object imageKey) {
- Set tileKeys = multimap.getIfPresent(imageKey);
- synchronized (this) {
+ Set tileKeys = null;
+ synchronized (cacheObject) {
+ // Check if the multimap contains the keys for the image
+ tileKeys = multimap.get(imageKey);
if (tileKeys == null) {
+ // If no key is present then a new KeySet is created and then added to the multimap
tileKeys = new ConcurrentSkipListSet();
multimap.put(imageKey, tileKeys);
+ if (LOGGER.isLoggable(Level.FINE)) {
+ LOGGER.fine("Created new Set for the image Image key " + imageKey);
+ }
}
}
+ if (LOGGER.isLoggable(Level.FINE)) {
+ LOGGER.fine("Added Tile to the set Image key " + imageKey);
+ }
+ // Finally the tile key is added.
tileKeys.add(key);
}
- private void removeTileFromKey(Object key) {
+ /**
+ * Removes the tile associated to the key.
+ *
+ * @param key
+ */
+ private void removeTileByKey(Object key) {
// check if the tile is still in cache
CachedTileImpl cti = (CachedTileImpl) cacheObject.getIfPresent(key);
// if so the tile is deleted (even if another thread write on it)
if (cti != null) {
if (diagnosticEnabled) {
- synchronized (this) {
+ synchronized (cacheObject) {
+ // Upgrade the tile action
cti.setAction(Actions.ABOUT_TO_REMOVAL);
setChanged();
notifyObservers(cti);
-
+ // Removal of the tile
cti = (CachedTileImpl) cacheObject.asMap().remove(key);
if (cti != null) {
+ // Upgrade the tile action
cti.setAction(Actions.MANUAL_REMOVAL);
setChanged();
notifyObservers(cti);
}
}
} else {
+ if (LOGGER.isLoggable(Level.FINE)) {
+ LOGGER.fine("Removed Tile Image key " + cti.getImageKey());
+ }
+ // Discard the tile from the cache
cacheObject.invalidate(key);
}
}
}
+ /**
+ * Gets the tile associated to the key.
+ *
+ * @param key
+ * @return
+ */
private Raster getTileFromKey(Object key) {
Raster tileData = null;
// check if the tile is present
- CachedTileImpl cti = (CachedTileImpl) cacheObject.getIfPresent(key);
+ CachedTileImpl cti = (CachedTileImpl) cacheObject.asMap().get(key);
+ // If not tile is found, null is returned
if (cti == null) {
+ if (LOGGER.isLoggable(Level.FINE)) {
+ LOGGER.fine("Null Tile returned");
+ }
return null;
}
if (diagnosticEnabled) {
- synchronized (this) {
+ synchronized (cacheObject) {
// Update last-access time for diagnosticEnabled
cti.updateTileTimeStamp();
@@ -558,6 +672,9 @@ private Raster getTileFromKey(Object key) {
notifyObservers(cti);
}
}
+ if (LOGGER.isLoggable(Level.FINE)) {
+ LOGGER.fine("Get the selected tile Image key " + cti.getImageKey());
+ }
// return the selected tile
tileData = cti.getTile();
return tileData;
diff --git a/concurrent-tile-cache/src/main/java/it/geosolutions/concurrentlinked/ConcurrentCache.java b/concurrent-tile-cache/src/main/java/it/geosolutions/concurrentlinked/ConcurrentCache.java
deleted file mode 100644
index 30bfb171..00000000
--- a/concurrent-tile-cache/src/main/java/it/geosolutions/concurrentlinked/ConcurrentCache.java
+++ /dev/null
@@ -1,440 +0,0 @@
-package it.geosolutions.concurrentlinked;
-
-import it.geosolutions.concurrent.CachedTileImpl;
-import it.geosolutions.concurrent.ConcurrentTileCache.Actions;
-import java.awt.Point;
-import java.awt.image.Raster;
-import java.awt.image.RenderedImage;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.Observable;
-import java.util.concurrent.ConcurrentHashMap;
-import javax.media.jai.TileCache;
-import com.sun.media.jai.util.CacheDiagnostics;
-
-public class ConcurrentCache extends Observable implements TileCache,
- CacheDiagnostics {
-
-/** Default value for memory threshold */
-public static final float DEFAULT_MEMORY_THRESHOLD = 0.75F;
-
-/** Default value for cache memory */
-public static final long DEFAULT_MEMORY_CACHE = 16L * 1024L * 1024L;
-
-/** Default boolean for diagnostic mode */
-public static final boolean DEFAULT_DIAGNOSTIC = false;
-
-/** Default ConcurrentHashMap concurrency level */
-public static final int DEFAULT_CONCURRENCY_LEVEL = 16;
-
-/** Cache memory capacity */
-private long memoryCacheCapacity = DEFAULT_MEMORY_CACHE;
-
-/** concurrency level of the ConcurrentHashMap */
-private int concurrencyLevel = DEFAULT_CONCURRENCY_LEVEL;
-
-/** Cache memory threshold (typically 0.75F) */
-private float memoryCacheThreshold = DEFAULT_MEMORY_THRESHOLD;
-
-/** The real cache */
-private ConcurrentHashMap cacheObject = new ConcurrentHashMap(
- 1000);
-
-/**
- * Current diagnostic mode (enabled or not). This variable is set to volatile
- * for visibility
- */
-private volatile boolean diagnosticEnabled = DEFAULT_DIAGNOSTIC;
-
-/** Current number of cache miss */
-private int missNumber;
-
-/** Current number of cache hits */
-private int hitNumber;
-
-/* Simple constructor */
-public ConcurrentCache() {
- this(DEFAULT_MEMORY_CACHE, DEFAULT_CONCURRENCY_LEVEL,
- DEFAULT_MEMORY_THRESHOLD, DEFAULT_DIAGNOSTIC);
-}
-
-/* Parameterized constructor */
-public ConcurrentCache(long memoryCacheCapacity, int concurrencyLevel,
- float memoryCacheThreshold, boolean diagnosticEnabled) {
- this.concurrencyLevel = concurrencyLevel;
- this.memoryCacheCapacity = memoryCacheCapacity;
- this.diagnosticEnabled = diagnosticEnabled;
- this.memoryCacheThreshold = memoryCacheThreshold;
- /* the counters are set to 0 */
- hitNumber = 0;
- missNumber = 0;
- System.err.println("Using ConcurrentCache");
-}
-
-public void add(RenderedImage image, int xTile, int yTile, Raster dataTile) {
- this.add(image, xTile, yTile, dataTile, null);
-}
-
-/**
- * This method adds a new tile in cache and, if diagnostic is enabled, notify
- * observers
- */
-public void add(RenderedImage image, int xTile, int yTile, Raster dataTile,
- Object tileMetric) {
- /* Tile key calculation */
- Object key = CachedTileImpl.hashKey(image, xTile, yTile);
- /* New tile creation */
- CachedTileImpl newValue = new CachedTileImpl(image, xTile, yTile, dataTile,
- tileMetric);
- /* If diagnostic is enabled the tile status is changed */
- if (diagnosticEnabled) {
- synchronized (this) {
- /* Updates the new tile status and notifies the observers */
- newValue.setAction(Actions.ADDITION);
- setChanged();
- notifyObservers(newValue);
- /* Puts the new value in cache and takes the old one */
- CachedTileImpl oldValue = cacheObject.put(key, newValue);
- if (oldValue != null) {
- hitNumber++;
- /* Update the old tile status and notify the observers */
- oldValue.updateTileTimeStamp();
- oldValue.setAction(Actions.SUBSTITUTION_FROM_ADD);
- setChanged();
- notifyObservers(oldValue);
- return;
- }
- }
- } else {
- /* Simply put the value in cache */
- cacheObject.put(key, newValue);
- }
-}
-
-/** This method add an array of tiles at given positions */
-public void addTiles(RenderedImage image, Point[] positions,
- Raster[] dataTiles, Object tileMetric) {
- for (int i = 0; i < positions.length; i++) {
- int xIndex = positions[i].x;
- int yIndex = positions[i].y;
- add(image, xIndex, yIndex, dataTiles[i], tileMetric);
- }
-}
-
-/**
- * This method flushes the cache and, if diagnostic is enabled, reset the
- * counters and, for every tile, update tile status
- */
-public synchronized void flush() {
- if (diagnosticEnabled) {
- /*
- * An iterator of all the key in the cache is used for updating every
- * tile and the removing it
- */
- CachedTileImpl oldValue;
- Iterator iter = cacheObject.keySet().iterator();
- while (iter.hasNext()) {
- oldValue = cacheObject.remove(iter.next());
- oldValue.setAction(Actions.REMOVAL_FROM_FLUSH);
- oldValue.updateTileTimeStamp();
- setChanged();
- notifyObservers(oldValue);
- }
- /* Counter reset */
- hitNumber = 0;
- missNumber = 0;
- } else {
- /* Simple cache clearing */
- cacheObject.clear();
- }
-
-}
-
-/** This method gets the current cache memory capacity */
-public long getMemoryCapacity() {
- return memoryCacheCapacity;
-}
-
-/** This method gets the current cache memory threshold */
-public float getMemoryThreshold() {
- return memoryCacheThreshold;
-}
-
-/**
- * This method gets a tile raster from his (x,y) tile coordinates and the image
- * reference
- */
-public Raster getTile(RenderedImage image, int xTile, int yTile) {
- /* Key creation */
- Object key = CachedTileImpl.hashKey(image, xTile, yTile);
- if (diagnosticEnabled) {
- synchronized (this) {
- /*
- * In diagnostic mode the oldvalue, if present, is updated and
- * retrieved
- */
- CachedTileImpl oldValue = cacheObject.get(key);
- if (oldValue != null) {
- /* if the tile is present the hit number is increased */
- hitNumber++;
- oldValue.setAction(Actions.UPDATING_TILE_FROM_GETTILE);
- oldValue.updateTileTimeStamp();
- /* Observers notifications */
- setChanged();
- notifyObservers(oldValue);
- return oldValue.getTile();
- } else {
- /* if the tile is not present the miss number is increased */
- missNumber++;
- return null;
- }
- }
- } else {
- /* The tile is returned if present, else null returned */
- CachedTileImpl oldValue = cacheObject.get(key);
- if (oldValue != null) {
- return oldValue.getTile();
- } else {
- return null;
- }
- }
-}
-
-/** All the tile of the specific image are returned */
-public Raster[] getTiles(RenderedImage image) {
- // instantiation of the result array
- Raster[] tilesData = null;
- // total number of tiles present in the cache
- int tileCount = (int) cacheObject.size();
-
- int size = Math.min(image.getNumXTiles() * image.getNumYTiles(), tileCount);
-
- if (size > 0) {
- int minTx = image.getMinTileX();
- int minTy = image.getMinTileY();
- int maxTx = minTx + image.getNumXTiles();
- int maxTy = minTy + image.getNumYTiles();
-
- // creates a temporary data arrayList
- ArrayList tempData = new ArrayList();
- // every not-null raster is added to the array
- for (int y = minTy; y < maxTy; y++) {
- for (int x = minTx; x < maxTx; x++) {
-
- Raster rasterTile = getTile(image, x, y);
-
- if (rasterTile != null) {
- tempData.add(rasterTile);
- }
- }
- }
- // the arrayList is then changed in an array
- int tmpsize = tempData.size();
- if (tmpsize > 0) {
- tilesData = (Raster[]) tempData.toArray(new Raster[tmpsize]);
- }
- }
-
- return tilesData;
-}
-
-/** This method returns an array of tiles at the given positions */
-public Raster[] getTiles(RenderedImage image, Point[] positions) {
- /* Initialization of an array of rasters */
- Raster[] tileData = new Raster[positions.length];
- if (diagnosticEnabled) {
- synchronized (this) {
- /*
- * If the diagnostic mode is enabled, the tiles are returned from
- * the method getTile which updates the tile status
- */
- for (int j = 0; j < positions.length; j++) {
- int xTile = positions[j].x;
- int yTile = positions[j].y;
- tileData[j] = getTile(image, xTile, yTile);
- }
- }
- } else {
- /*
- * Else, they are simply returned by the ConcurrentHashMap.get()
- * method
- */
- for (int j = 0; j < positions.length; j++) {
- int xTile = positions[j].x;
- int yTile = positions[j].y;
- Object key = CachedTileImpl.hashKey(image, xTile, yTile);
- tileData[j] = cacheObject.get(key).getTile();
- }
- }
- return tileData;
-}
-
-/** This method removes the specified tile and notify it to the observers */
-public void remove(RenderedImage image, int xTile, int yTile) {
- /* Tile key calculation */
- Object key = CachedTileImpl.hashKey(image, xTile, yTile);
- if (diagnosticEnabled) {
- synchronized (this) {
- /*
- * In diagnostic mode this method check if the old tile was present
- * and if so update its status and notify it to the observers, and
- * removes it
- */
- CachedTileImpl oldValue = cacheObject.get(key);
- if (oldValue != null) {
- oldValue.updateTileTimeStamp();
- oldValue.setAction(Actions.ABOUT_TO_REMOVAL);
- setChanged();
- notifyObservers(oldValue);
- cacheObject.remove(key);
- oldValue.updateTileTimeStamp();
- oldValue.setAction(Actions.MANUAL_REMOVAL);
- setChanged();
- notifyObservers(oldValue);
- }
- }
- } else {
- /* The tile is removed without checking if it is present or not */
- cacheObject.remove(key);
- }
-}
-
-/** This method removes all the tiles that belong to the specified image */
-public void removeTiles(RenderedImage image) {
- /* Image tile coordinates */
- int minTx = image.getMinTileX();
- int minTy = image.getMinTileY();
- int maxTx = minTx + image.getNumXTiles();
- int maxTy = minTy + image.getNumYTiles();
- if (diagnosticEnabled) {
- synchronized (this) {
- /*
- * This method is the same for both the diagnostic or non-diagnostic
- * mode the difference is the sincronized block
- */
- removeAllImageTiles(image, minTx, maxTx, minTy, maxTy);
- }
- } else {
- removeAllImageTiles(image, minTx, maxTx, minTy, maxTy);
- }
-}
-
-/** This method cycles through the image eliminating all of its tiles */
-private void removeAllImageTiles(RenderedImage image, int minX, int maxX,
- int minY, int maxY) {
- for (int y = minY; y < maxY; y++) {
- for (int x = minX; x < maxX; x++) {
- remove(image, x, y);
- }
- }
-}
-
-/** This method sets the memory capacity, then flush and rebuild the cache */
-public synchronized void setMemoryCapacity(long memoryCacheCapacity) {
- if (memoryCacheCapacity < 0) {
- throw new IllegalArgumentException("Memory capacity too small");
- } else {
- this.memoryCacheCapacity = memoryCacheCapacity;
- flush();
- }
-
-}
-
-/** This method sets the memory threshold, then flush and rebuild the cache */
-public synchronized void setMemoryThreshold(float memoryCacheThreshold) {
- if (memoryCacheThreshold < 0 || memoryCacheThreshold > 1) {
- throw new IllegalArgumentException(
- "Memory threshold must be between 0 and 1");
- } else {
- this.memoryCacheThreshold = memoryCacheThreshold;
- flush();
- }
-
-}
-
-/**
- * This method sets the cache ConcurrencyLevel and then flush and rebuild the
- * cache
- */
-public synchronized void setConcurrencyLevel(int concurrency) {
- if (concurrency < 1) {
- throw new IllegalArgumentException(
- "ConcurrencyLevel must be at least 1");
- } else {
- concurrencyLevel = concurrency;
- flush();
-
- }
-
-}
-
-/** Diagnostic is disabled, then the cache is flushed and rebuilt */
-public synchronized void disableDiagnostics() {
- this.diagnosticEnabled = false;
- flush();
-}
-
-/** Diagnostic is enabled, then the cache is flushed and rebuilt */
-public synchronized void enableDiagnostics() {
- this.diagnosticEnabled = true;
- flush();
-}
-
-/** The counters are set to 0 when the cache is flushed */
-public synchronized void resetCounts() {
- flush();
-}
-
-/** This method returns the number of cache hits */
-public long getCacheHitCount() {
- return hitNumber;
-}
-
-/** This method returns the cache weighed size */
-public long getCacheMemoryUsed() {
- return -1;
-}
-
-/** This method returns the number of cache miss */
-public long getCacheMissCount() {
- return missNumber;
-}
-
-/** This method returns the number of tile present in the cache */
-public long getCacheTileCount() {
- return cacheObject.size();
-}
-
-/** This method returns the cache concurrency level */
-public int getConcurrencyLevel() {
- return concurrencyLevel;
-}
-
-/** Not supported */
-public void setTileCapacity(int arg0) {
- throw new UnsupportedOperationException("Deprecated Operation");
-
-}
-
-/** Not supported */
-public int getTileCapacity() {
- throw new UnsupportedOperationException("Deprecated Operation");
-}
-
-/** Not supported */
-public Comparator getTileComparator() {
- throw new UnsupportedOperationException("Comparator not supported");
-}
-
-/** Not supported */
-public void setTileComparator(Comparator arg0) {
- throw new UnsupportedOperationException("Comparator not supported");
-}
-
-/** Not supported */
-public void memoryControl() {
- throw new UnsupportedOperationException("Memory Control not supported");
-}
-
-}
diff --git a/concurrent-tile-cache/src/main/java/it/geosolutions/concurrentlinked/ConcurrentLinkedCache.java b/concurrent-tile-cache/src/main/java/it/geosolutions/concurrentlinked/ConcurrentLinkedCache.java
deleted file mode 100644
index ea45cdb3..00000000
--- a/concurrent-tile-cache/src/main/java/it/geosolutions/concurrentlinked/ConcurrentLinkedCache.java
+++ /dev/null
@@ -1,486 +0,0 @@
-package it.geosolutions.concurrentlinked;
-
-import it.geosolutions.concurrent.CachedTileImpl;
-import it.geosolutions.concurrent.ConcurrentTileCache.Actions;
-import java.awt.Point;
-import java.awt.image.Raster;
-import java.awt.image.RenderedImage;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.Observable;
-import javax.media.jai.TileCache;
-import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
-import com.googlecode.concurrentlinkedhashmap.EvictionListener;
-import com.googlecode.concurrentlinkedhashmap.Weigher;
-import com.sun.media.jai.util.CacheDiagnostics;
-
-public class ConcurrentLinkedCache extends Observable implements TileCache,
- CacheDiagnostics {
-
-/** Default value for memory threshold */
-public static final float DEFAULT_MEMORY_THRESHOLD = 0.75F;
-
-/** Default value for cache memory */
-public static final long DEFAULT_MEMORY_CACHE = 16L * 1024L * 1024L;
-
-/** Default boolean for diagnostic mode */
-public static final boolean DEFAULT_DIAGNOSTIC = false;
-
-/** Default ConcurrentLinkedHashMap concurrency level */
-public static final int DEFAULT_CONCURRENCY_LEVEL = 16;
-
-/** The real cache */
-private ConcurrentLinkedHashMap cacheObject;
-
-/** Cache memory capacity */
-private long memoryCacheCapacity = DEFAULT_MEMORY_CACHE;
-
-/** concurrency level of the ConcurrentLinkedHashMap */
-private int concurrencyLevel = DEFAULT_CONCURRENCY_LEVEL;
-
-/** Cache memory threshold (typically 0.75F) */
-private float memoryCacheThreshold = DEFAULT_MEMORY_THRESHOLD;
-
-/**
- * Current diagnostic mode (enabled or not). This variable is set to volatile
- * for visibility
- */
-private volatile boolean diagnosticEnabled = DEFAULT_DIAGNOSTIC;
-
-/** Current number of cache miss */
-private int missNumber;
-
-/** Current number of cache hits */
-private int hitNumber;
-
-/**
- * Eviction listener for catching the tile evicted by the
- * ConcurrentLinkedHashMap and, if diagnostic is enabled, the eviction is
- * notified to the observer
- */
-private EvictionListener listener = new EvictionListener() {
-
- public void onEviction(Object key, CachedTileImpl oldValue) {
- if (diagnosticEnabled) {
- synchronized (this) {
- oldValue.updateTileTimeStamp();
- oldValue.setAction(Actions.REMOVAL_FROM_EVICTION);
- setChanged();
- notifyObservers(oldValue);
- }
-
- }
- }
-
-};
-
-/* Simple constructor */
-public ConcurrentLinkedCache() {
- this(DEFAULT_MEMORY_CACHE, DEFAULT_CONCURRENCY_LEVEL,
- DEFAULT_MEMORY_THRESHOLD, DEFAULT_DIAGNOSTIC);
-}
-
-/* Parameterized constructor */
-public ConcurrentLinkedCache(long memoryCacheCapacity, int concurrencyLevel,
- float memoryCacheThreshold, boolean diagnosticEnabled) {
- this.concurrencyLevel = concurrencyLevel;
- this.memoryCacheCapacity = memoryCacheCapacity;
- this.diagnosticEnabled = diagnosticEnabled;
- this.memoryCacheThreshold = memoryCacheThreshold;
- /* the cache instantiation is done in the buildLinkedCache() method */
- cacheObject = buildLinkedCache();
- /* the counters are set to 0 */
- hitNumber = 0;
- missNumber = 0;
- System.err.println("Using ConcurrentLinkedCache");
-}
-
-/** Private method for building the cache */
-private ConcurrentLinkedHashMap buildLinkedCache() {
- /* Builder instantiation */
- ConcurrentLinkedHashMap.Builder builder = new ConcurrentLinkedHashMap.Builder();
- builder.concurrencyLevel(concurrencyLevel)
- .maximumWeightedCapacity(
- (long) (memoryCacheCapacity * memoryCacheThreshold))
- /* The weigher is used for weighing every entry */
- .weigher(new Weigher() {
- public int weightOf(CachedTileImpl tile) {
- return (int) ((CachedTileImpl) tile).getTileSize();
- }
- });
- /* Listener is used only with diagnostic */
- if (diagnosticEnabled) {
- builder.listener(listener);
- }
- /* Cache creation */
- return builder.build();
-}
-
-public void add(RenderedImage image, int xTile, int yTile, Raster dataTile) {
- this.add(image, xTile, yTile, dataTile, null);
-}
-
-/**
- * This method adds a new tile in cache and, if diagnostic is enabled, notify
- * observers
- */
-public void add(RenderedImage image, int xTile, int yTile, Raster dataTile,
- Object tileMetric) {
- /* Tile key calculation */
- Object key = CachedTileImpl.hashKey(image, xTile, yTile);
- /* New tile creation */
- CachedTileImpl newValue = new CachedTileImpl(image, xTile, yTile, dataTile,
- tileMetric);
- /* If diagnostic is enabled the tile status is changed */
- if (diagnosticEnabled) {
- synchronized (this) {
- /* Updates the new tile status and notifies the observers */
- newValue.setAction(Actions.ADDITION);
- setChanged();
- notifyObservers(newValue);
- /* Puts the new value in cache and takes the old one */
- CachedTileImpl oldValue = cacheObject.put(key, newValue);
- if (oldValue != null) {
- hitNumber++;
- /* Update the old tile status and notify the observers */
- oldValue.updateTileTimeStamp();
- oldValue.setAction(Actions.SUBSTITUTION_FROM_ADD);
- setChanged();
- notifyObservers(oldValue);
- return;
- }
- }
- } else {
- /* Simply put the value in cache */
- cacheObject.put(key, newValue);
- }
-}
-
-/** This method add an array of tiles at given positions */
-public void addTiles(RenderedImage image, Point[] positions,
- Raster[] dataTiles, Object tileMetric) {
- for (int i = 0; i < positions.length; i++) {
- int xIndex = positions[i].x;
- int yIndex = positions[i].y;
- add(image, xIndex, yIndex, dataTiles[i], tileMetric);
- }
-}
-
-/**
- * This method flushes the cache and, if diagnostic is enabled, reset the
- * counters and, for every tile, update tile status
- */
-public synchronized void flush() {
- if (diagnosticEnabled) {
- /*
- * An iterator of all the key in the cache is used for updating every
- * tile and the removing it
- */
- CachedTileImpl oldValue;
- Iterator iter = cacheObject.keySet().iterator();
- while (iter.hasNext()) {
- oldValue = cacheObject.remove(iter.next());
- oldValue.setAction(Actions.REMOVAL_FROM_FLUSH);
- oldValue.updateTileTimeStamp();
- setChanged();
- notifyObservers(oldValue);
- }
- /* Counter reset */
- hitNumber = 0;
- missNumber = 0;
- } else {
- /* Simple cache clearing */
- cacheObject.clear();
- }
- /* The cache is rebuilt */
- cacheObject = buildLinkedCache();
-}
-
-/** This method gets the current cache memory capacity */
-public long getMemoryCapacity() {
- return memoryCacheCapacity;
-}
-
-/** This method gets the current cache memory threshold */
-public float getMemoryThreshold() {
- return memoryCacheThreshold;
-}
-
-/**
- * This method gets a tile raster from his (x,y) tile coordinates and the image
- * reference
- */
-public Raster getTile(RenderedImage image, int xTile, int yTile) {
- /* Key creation */
- Object key = CachedTileImpl.hashKey(image, xTile, yTile);
- if (diagnosticEnabled) {
- synchronized (this) {
- /*
- * In diagnostic mode the oldvalue, if present, is updated and
- * retrieved
- */
- CachedTileImpl oldValue = cacheObject.get(key);
- if (oldValue != null) {
- /* if the tile is present the hit number is increased */
- hitNumber++;
- oldValue.setAction(Actions.UPDATING_TILE_FROM_GETTILE);
- oldValue.updateTileTimeStamp();
- /* Observers notifications */
- setChanged();
- notifyObservers(oldValue);
- return oldValue.getTile();
- } else {
- /* if the tile is not present the miss number is increased */
- missNumber++;
- return null;
- }
- }
- } else {
- /* The tile is returned if present, else null returned */
- CachedTileImpl oldValue = cacheObject.get(key);
- if (oldValue != null) {
- return oldValue.getTile();
- } else {
- return null;
- }
- }
-}
-
-/** All the tile of the specific image are returned */
-public Raster[] getTiles(RenderedImage image) {
- // instantiation of the result array
- Raster[] tilesData = null;
- // total number of tiles present in the cache
- int tileCount = (int) cacheObject.size();
-
- int size = Math.min(image.getNumXTiles() * image.getNumYTiles(), tileCount);
-
- if (size > 0) {
- int minTx = image.getMinTileX();
- int minTy = image.getMinTileY();
- int maxTx = minTx + image.getNumXTiles();
- int maxTy = minTy + image.getNumYTiles();
-
- // creates a temporary data arrayList
- ArrayList tempData = new ArrayList();
- // every not-null raster is added to the array
- for (int y = minTy; y < maxTy; y++) {
- for (int x = minTx; x < maxTx; x++) {
-
- Raster rasterTile = getTile(image, x, y);
-
- if (rasterTile != null) {
- tempData.add(rasterTile);
- }
- }
- }
- // the arrayList is then changed in an array
- int tmpsize = tempData.size();
- if (tmpsize > 0) {
- tilesData = (Raster[]) tempData.toArray(new Raster[tmpsize]);
- }
- }
-
- return tilesData;
-}
-
-/** This method returns an array of tiles at the given positions */
-public Raster[] getTiles(RenderedImage image, Point[] positions) {
- /* Initialization of an array of rasters */
- Raster[] tileData = new Raster[positions.length];
- if (diagnosticEnabled) {
- synchronized (this) {
- /*
- * If the diagnostic mode is enabled, the tiles are returned from
- * the method getTile which updates the tile status
- */
- for (int j = 0; j < positions.length; j++) {
- int xTile = positions[j].x;
- int yTile = positions[j].y;
- tileData[j] = getTile(image, xTile, yTile);
- }
- }
- } else {
- /*
- * Else, they are simply returned by the ConcurrentLinkedHashMap.get()
- * method
- */
- for (int j = 0; j < positions.length; j++) {
- int xTile = positions[j].x;
- int yTile = positions[j].y;
- Object key = CachedTileImpl.hashKey(image, xTile, yTile);
- tileData[j] = cacheObject.get(key).getTile();
- }
- }
- return tileData;
-}
-
-/** This method removes the specified tile and notify it to the observers */
-public void remove(RenderedImage image, int xTile, int yTile) {
- /* Tile key calculation */
- Object key = CachedTileImpl.hashKey(image, xTile, yTile);
- if (diagnosticEnabled) {
- synchronized (this) {
- /*
- * In diagnostic mode this method check if the old tile was present
- * and if so update its status and notify it to the observers, and
- * removes it
- */
- CachedTileImpl oldValue = cacheObject.get(key);
- if (oldValue != null) {
- oldValue.updateTileTimeStamp();
- oldValue.setAction(Actions.ABOUT_TO_REMOVAL);
- setChanged();
- notifyObservers(oldValue);
- cacheObject.remove(key);
- oldValue.updateTileTimeStamp();
- oldValue.setAction(Actions.MANUAL_REMOVAL);
- setChanged();
- notifyObservers(oldValue);
- }
- }
- } else {
- /* The tile is removed without checking if it is present or not */
- cacheObject.remove(key);
- }
-}
-
-/** This method removes all the tiles that belong to the specified image */
-public void removeTiles(RenderedImage image) {
- /* Image tile coordinates */
- int minTx = image.getMinTileX();
- int minTy = image.getMinTileY();
- int maxTx = minTx + image.getNumXTiles();
- int maxTy = minTy + image.getNumYTiles();
- if (diagnosticEnabled) {
- synchronized (this) {
- /*
- * This method is the same for both the diagnostic or non-diagnostic
- * mode the difference is the sincronized block
- */
- removeAllImageTiles(image, minTx, maxTx, minTy, maxTy);
- }
- } else {
- removeAllImageTiles(image, minTx, maxTx, minTy, maxTy);
- }
-}
-
-/** This method cycles through the image eliminating all of its tiles */
-private void removeAllImageTiles(RenderedImage image, int minX, int maxX,
- int minY, int maxY) {
- for (int y = minY; y < maxY; y++) {
- for (int x = minX; x < maxX; x++) {
- remove(image, x, y);
- }
- }
-}
-
-/** This method sets the memory capacity, then flush and rebuild the cache */
-public synchronized void setMemoryCapacity(long memoryCacheCapacity) {
- if (memoryCacheCapacity < 0) {
- throw new IllegalArgumentException("Memory capacity too small");
- } else {
- this.memoryCacheCapacity = memoryCacheCapacity;
- flush();
- }
-
-}
-
-/** This method sets the memory threshold, then flush and rebuild the cache */
-public synchronized void setMemoryThreshold(float memoryCacheThreshold) {
- if (memoryCacheThreshold < 0 || memoryCacheThreshold > 1) {
- throw new IllegalArgumentException(
- "Memory threshold must be between 0 and 1");
- } else {
- this.memoryCacheThreshold = memoryCacheThreshold;
- flush();
- }
-
-}
-
-/**
- * This method sets the cache ConcurrencyLevel and then flush and rebuild the
- * cache
- */
-public synchronized void setConcurrencyLevel(int concurrency) {
- if (concurrency < 1) {
- throw new IllegalArgumentException(
- "ConcurrencyLevel must be at least 1");
- } else {
- concurrencyLevel = concurrency;
- flush();
-
- }
-
-}
-
-/** Diagnostic is disabled, then the cache is flushed and rebuilt */
-public synchronized void disableDiagnostics() {
- this.diagnosticEnabled = false;
- flush();
-}
-
-/** Diagnostic is enabled, then the cache is flushed and rebuilt */
-public synchronized void enableDiagnostics() {
- this.diagnosticEnabled = true;
- flush();
-}
-
-/** The counters are set to 0 when the cache is flushed */
-public synchronized void resetCounts() {
- flush();
-}
-
-/** This method returns the number of cache hits */
-public long getCacheHitCount() {
- return hitNumber;
-}
-
-/** This method returns the cache weighed size */
-public long getCacheMemoryUsed() {
- return cacheObject.weightedSize();
-}
-
-/** This method returns the number of cache miss */
-public long getCacheMissCount() {
- return missNumber;
-}
-
-/** This method returns the number of tile present in the cache */
-public long getCacheTileCount() {
- return cacheObject.size();
-}
-
-/** This method returns the cache concurrency level */
-public int getConcurrencyLevel() {
- return concurrencyLevel;
-}
-
-/** Not supported */
-public void setTileCapacity(int arg0) {
- throw new UnsupportedOperationException("Deprecated Operation");
-
-}
-
-/** Not supported */
-public int getTileCapacity() {
- throw new UnsupportedOperationException("Deprecated Operation");
-}
-
-/** Not supported */
-public Comparator getTileComparator() {
- throw new UnsupportedOperationException("Comparator not supported");
-}
-
-/** Not supported */
-public void setTileComparator(Comparator arg0) {
- throw new UnsupportedOperationException("Comparator not supported");
-}
-
-/** Not supported */
-public void memoryControl() {
- throw new UnsupportedOperationException("Memory Control not supported");
-}
-
-}
diff --git a/concurrent-tile-cache/src/main/java/it/geosolutions/concurrentlinked/ConcurrentNonBlockingCache.java b/concurrent-tile-cache/src/main/java/it/geosolutions/concurrentlinked/ConcurrentNonBlockingCache.java
deleted file mode 100644
index 97a3d705..00000000
--- a/concurrent-tile-cache/src/main/java/it/geosolutions/concurrentlinked/ConcurrentNonBlockingCache.java
+++ /dev/null
@@ -1,411 +0,0 @@
-package it.geosolutions.concurrentlinked;
-
-import it.geosolutions.concurrent.CachedTileImpl;
-import it.geosolutions.concurrent.ConcurrentTileCache.Actions;
-
-import java.awt.Point;
-import java.awt.image.Raster;
-import java.awt.image.RenderedImage;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.Observable;
-import javax.media.jai.TileCache;
-import org.cliffc.high_scale_lib.NonBlockingHashMap;
-import com.sun.media.jai.util.CacheDiagnostics;
-
-public class ConcurrentNonBlockingCache extends Observable implements
- TileCache, CacheDiagnostics {
-
-/** Default value for memory threshold */
-public static final float DEFAULT_MEMORY_THRESHOLD = 0.75F;
-
-/** Default value for cache memory */
-public static final long DEFAULT_MEMORY_CACHE = 16L * 1024L * 1024L;
-
-/** Default boolean for diagnostic mode */
-public static final boolean DEFAULT_DIAGNOSTIC = false;
-
-/** Cache memory capacity */
-private long memoryCacheCapacity = DEFAULT_MEMORY_CACHE;
-
-/** Cache memory threshold (typically 0.75F) */
-private float memoryCacheThreshold = DEFAULT_MEMORY_THRESHOLD;
-
-/** The real cache */
-private NonBlockingHashMap cacheObject = new NonBlockingHashMap(1000);
-
-/**
- * Current diagnostic mode (enabled or not). This variable is set to volatile
- * for visibility
- */
-private volatile boolean diagnosticEnabled = DEFAULT_DIAGNOSTIC;
-
-/** Current number of cache miss */
-private int missNumber;
-
-/** Current number of cache hits */
-private int hitNumber;
-
-/* Simple constructor */
-public ConcurrentNonBlockingCache() {
- this(DEFAULT_MEMORY_CACHE, DEFAULT_MEMORY_THRESHOLD, DEFAULT_DIAGNOSTIC);
-}
-
-/* Parameterized constructor */
-public ConcurrentNonBlockingCache(long memoryCacheCapacity,
- float memoryCacheThreshold, boolean diagnosticEnabled) {
- this.memoryCacheCapacity = memoryCacheCapacity;
- this.diagnosticEnabled = diagnosticEnabled;
- this.memoryCacheThreshold = memoryCacheThreshold;
- /* the counters are set to 0 */
- hitNumber = 0;
- missNumber = 0;
- System.err.println("Using ConcurrentNonBlockingCache");
-}
-
-public void add(RenderedImage image, int xTile, int yTile, Raster dataTile) {
- this.add(image, xTile, yTile, dataTile, null);
-}
-
-/**
- * This method adds a new tile in cache and, if diagnostic is enabled, notify
- * observers
- */
-public void add(RenderedImage image, int xTile, int yTile, Raster dataTile,
- Object tileMetric) {
- /* Tile key calculation */
- Object key = CachedTileImpl.hashKey(image, xTile, yTile);
- /* New tile creation */
- CachedTileImpl newValue = new CachedTileImpl(image, xTile, yTile, dataTile,
- tileMetric);
- /* If diagnostic is enabled the tile status is changed */
- if (diagnosticEnabled) {
- synchronized (this) {
- /* Updates the new tile status and notifies the observers */
- newValue.setAction(Actions.ADDITION);
- setChanged();
- notifyObservers(newValue);
- /* Puts the new value in cache and takes the old one */
- CachedTileImpl oldValue = cacheObject.put(key, newValue);
- if (oldValue != null) {
- hitNumber++;
- /* Update the old tile status and notify the observers */
- oldValue.updateTileTimeStamp();
- oldValue.setAction(Actions.SUBSTITUTION_FROM_ADD);
- setChanged();
- notifyObservers(oldValue);
- return;
- }
- }
- } else {
- /* Simply put the value in cache */
- cacheObject.put(key, newValue);
- }
-}
-
-/** This method add an array of tiles at given positions */
-public void addTiles(RenderedImage image, Point[] positions,
- Raster[] dataTiles, Object tileMetric) {
- for (int i = 0; i < positions.length; i++) {
- int xIndex = positions[i].x;
- int yIndex = positions[i].y;
- add(image, xIndex, yIndex, dataTiles[i], tileMetric);
- }
-}
-
-/**
- * This method flushes the cache and, if diagnostic is enabled, reset the
- * counters and, for every tile, update tile status
- */
-public synchronized void flush() {
- if (diagnosticEnabled) {
- /*
- * An iterator of all the key in the cache is used for updating every
- * tile and the removing it
- */
- CachedTileImpl oldValue;
- Iterator iter = cacheObject.keySet().iterator();
- while (iter.hasNext()) {
- oldValue = cacheObject.remove(iter.next());
- oldValue.setAction(Actions.REMOVAL_FROM_FLUSH);
- oldValue.updateTileTimeStamp();
- setChanged();
- notifyObservers(oldValue);
- }
- /* Counter reset */
- hitNumber = 0;
- missNumber = 0;
- } else {
- /* Simple cache clearing */
- cacheObject.clear();
- }
-}
-
-/** This method gets the current cache memory capacity */
-public long getMemoryCapacity() {
- return memoryCacheCapacity;
-}
-
-/** This method gets the current cache memory threshold */
-public float getMemoryThreshold() {
- return memoryCacheThreshold;
-}
-
-/**
- * This method gets a tile raster from his (x,y) tile coordinates and the image
- * reference
- */
-public Raster getTile(RenderedImage image, int xTile, int yTile) {
- /* Key creation */
- Object key = CachedTileImpl.hashKey(image, xTile, yTile);
- if (diagnosticEnabled) {
- synchronized (this) {
- /*
- * In diagnostic mode the oldvalue, if present, is updated and
- * retrieved
- */
- CachedTileImpl oldValue = cacheObject.get(key);
- if (oldValue != null) {
- /* if the tile is present the hit number is increased */
- hitNumber++;
- oldValue.setAction(Actions.UPDATING_TILE_FROM_GETTILE);
- oldValue.updateTileTimeStamp();
- /* Observers notifications */
- setChanged();
- notifyObservers(oldValue);
- return oldValue.getTile();
- } else {
- /* if the tile is not present the miss number is increased */
- missNumber++;
- return null;
- }
- }
- } else {
- /* The tile is returned if present, else null returned */
- CachedTileImpl oldValue = cacheObject.get(key);
- if (oldValue != null) {
- return oldValue.getTile();
- } else {
- return null;
- }
- }
-}
-
-/** All the tile of the specific image are returned */
-public Raster[] getTiles(RenderedImage image) {
- // instantiation of the result array
- Raster[] tilesData = null;
- // total number of tiles present in the cache
- int tileCount = (int) cacheObject.size();
-
- int size = Math.min(image.getNumXTiles() * image.getNumYTiles(), tileCount);
-
- if (size > 0) {
- int minTx = image.getMinTileX();
- int minTy = image.getMinTileY();
- int maxTx = minTx + image.getNumXTiles();
- int maxTy = minTy + image.getNumYTiles();
-
- // creates a temporary data arrayList
- ArrayList tempData = new ArrayList();
- // every not-null raster is added to the array
- for (int y = minTy; y < maxTy; y++) {
- for (int x = minTx; x < maxTx; x++) {
-
- Raster rasterTile = getTile(image, x, y);
-
- // the arrayList is then changed in an array
- if (rasterTile != null) {
- tempData.add(rasterTile);
- }
- }
- }
-
- int tmpsize = tempData.size();
- if (tmpsize > 0) {
- tilesData = (Raster[]) tempData.toArray(new Raster[tmpsize]);
- }
- }
-
- return tilesData;
-}
-
-/** This method returns an array of tiles at the given positions */
-public Raster[] getTiles(RenderedImage image, Point[] positions) {
- /* Initialization of an array of rasters */
- Raster[] tileData = new Raster[positions.length];
- if (diagnosticEnabled) {
- synchronized (this) {
- /*
- * If the diagnostic mode is enabled, the tiles are returned from
- * the method getTile which updates the tile status
- */
- for (int j = 0; j < positions.length; j++) {
- int xTile = positions[j].x;
- int yTile = positions[j].y;
- tileData[j] = getTile(image, xTile, yTile);
- }
- }
- } else {
- /*
- * Else, they are simply returned by the NonBlockingHashMap.get()
- * method
- */
- for (int j = 0; j < positions.length; j++) {
- int xTile = positions[j].x;
- int yTile = positions[j].y;
- Object key = CachedTileImpl.hashKey(image, xTile, yTile);
- tileData[j] = cacheObject.get(key).getTile();
- }
- }
- return tileData;
-}
-
-/** This method removes the specified tile and notify it to the observers */
-public void remove(RenderedImage image, int xTile, int yTile) {
- /* Tile key calculation */
- Object key = CachedTileImpl.hashKey(image, xTile, yTile);
- if (diagnosticEnabled) {
- synchronized (this) {
- /*
- * In diagnostic mode this method check if the old tile was present
- * and if so update its status and notify it to the observers, and
- * removes it
- */
- CachedTileImpl oldValue = cacheObject.get(key);
- if (oldValue != null) {
- oldValue.updateTileTimeStamp();
- oldValue.setAction(Actions.ABOUT_TO_REMOVAL);
- setChanged();
- notifyObservers(oldValue);
- cacheObject.remove(key);
- oldValue.updateTileTimeStamp();
- oldValue.setAction(Actions.MANUAL_REMOVAL);
- setChanged();
- notifyObservers(oldValue);
- }
- }
- } else {
- /* The tile is removed without checking if it is present or not */
- cacheObject.remove(key);
- }
-}
-
-/** This method removes all the tiles that belong to the specified image */
-public void removeTiles(RenderedImage image) {
- /* Image tile coordinates */
- int minTx = image.getMinTileX();
- int minTy = image.getMinTileY();
- int maxTx = minTx + image.getNumXTiles();
- int maxTy = minTy + image.getNumYTiles();
- if (diagnosticEnabled) {
- synchronized (this) {
- /*
- * This method is the same for both the diagnostic or non-diagnostic
- * mode the difference is the sincronized block
- */
- removeAllImageTiles(image, minTx, maxTx, minTy, maxTy);
- }
- } else {
- removeAllImageTiles(image, minTx, maxTx, minTy, maxTy);
- }
-}
-
-/** This method cycles through the image eliminating all of its tiles */
-private void removeAllImageTiles(RenderedImage image, int minX, int maxX,
- int minY, int maxY) {
- for (int y = minY; y < maxY; y++) {
- for (int x = minX; x < maxX; x++) {
- remove(image, x, y);
- }
- }
-}
-
-/** This method sets the memory capacity, then flush and rebuild the cache */
-public synchronized void setMemoryCapacity(long memoryCacheCapacity) {
- if (memoryCacheCapacity < 0) {
- throw new IllegalArgumentException("Memory capacity too small");
- } else {
- this.memoryCacheCapacity = memoryCacheCapacity;
- flush();
- }
-
-}
-
-/** This method sets the memory threshold, then flush and rebuild the cache */
-public synchronized void setMemoryThreshold(float memoryCacheThreshold) {
- if (memoryCacheThreshold < 0 || memoryCacheThreshold > 1) {
- throw new IllegalArgumentException(
- "Memory threshold must be between 0 and 1");
- } else {
- this.memoryCacheThreshold = memoryCacheThreshold;
- flush();
- }
-
-}
-
-/** Diagnostic is disabled, then the cache is flushed and rebuilt */
-public synchronized void disableDiagnostics() {
- this.diagnosticEnabled = false;
- flush();
-}
-
-/** Diagnostic is enabled, then the cache is flushed and rebuilt */
-public synchronized void enableDiagnostics() {
- this.diagnosticEnabled = true;
- flush();
-}
-
-/** The counters are set to 0 when the cache is flushed */
-public synchronized void resetCounts() {
- flush();
-}
-
-/** This method returns the number of cache hits */
-public long getCacheHitCount() {
- return hitNumber;
-}
-
-/** This method returns the cache weighed size */
-public long getCacheMemoryUsed() {
- return -1;
-}
-
-/** This method returns the number of cache miss */
-public long getCacheMissCount() {
- return missNumber;
-}
-
-/** This method returns the number of tile present in the cache */
-public long getCacheTileCount() {
- return cacheObject.size();
-}
-
-/** Not supported */
-public void setTileCapacity(int arg0) {
- throw new UnsupportedOperationException("Deprecated Operation");
-
-}
-
-/** Not supported */
-public int getTileCapacity() {
- throw new UnsupportedOperationException("Deprecated Operation");
-}
-
-/** Not supported */
-public Comparator getTileComparator() {
- throw new UnsupportedOperationException("Comparator not supported");
-}
-
-/** Not supported */
-public void setTileComparator(Comparator arg0) {
- throw new UnsupportedOperationException("Comparator not supported");
-}
-
-/** Not supported */
-public void memoryControl() {
- throw new UnsupportedOperationException("Memory Control not supported");
-}
-
-}
diff --git a/concurrent-tile-cache/src/test/java/it/geosolutions/concurrencytest/CacheCoberturaTest.java b/concurrent-tile-cache/src/test/java/it/geosolutions/concurrencytest/CacheCoberturaTest.java
index e4ef232a..b2e232f2 100644
--- a/concurrent-tile-cache/src/test/java/it/geosolutions/concurrencytest/CacheCoberturaTest.java
+++ b/concurrent-tile-cache/src/test/java/it/geosolutions/concurrencytest/CacheCoberturaTest.java
@@ -15,7 +15,7 @@ public class CacheCoberturaTest {
@Test
public void testConcurrency() throws Exception {
// setting the parameters
- int cacheUsed=4;
+ int cacheUsed=1;
int concurrencyLevel = 16;
long memoryCacheCapacity = 128 * 1024 * 1024;
RenderedImage imageSynth = ConcurrentCacheTest.getSynthetic(1);
diff --git a/concurrent-tile-cache/src/test/java/it/geosolutions/concurrencytest/ConcurrentCacheTest.java b/concurrent-tile-cache/src/test/java/it/geosolutions/concurrencytest/ConcurrentCacheTest.java
index 161e1445..54dbc662 100644
--- a/concurrent-tile-cache/src/test/java/it/geosolutions/concurrencytest/ConcurrentCacheTest.java
+++ b/concurrent-tile-cache/src/test/java/it/geosolutions/concurrencytest/ConcurrentCacheTest.java
@@ -1,9 +1,7 @@
package it.geosolutions.concurrencytest;
import it.geosolutions.concurrent.ConcurrentTileCache;
-import it.geosolutions.concurrentlinked.ConcurrentCache;
-import it.geosolutions.concurrentlinked.ConcurrentLinkedCache;
-import it.geosolutions.concurrentlinked.ConcurrentNonBlockingCache;
+
import java.awt.image.RenderedImage;
import java.awt.image.renderable.ParameterBlock;
import java.io.File;
@@ -16,6 +14,7 @@
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
+
import javax.imageio.stream.FileImageInputStream;
import javax.media.jai.InterpolationNearest;
import javax.media.jai.JAI;
@@ -133,29 +132,6 @@ public double[] testwriteImageAndWatchFlag(int cacheUsed, int concurrencyLevel,
}
JAI.getDefaultInstance().setTileCache(cTileCache);
break;
- case 2:
- ConcurrentLinkedCache cLinkedCache = new ConcurrentLinkedCache();
- cLinkedCache.setConcurrencyLevel(concurrencyLevel);
- if (diagnostics) {
- cLinkedCache.enableDiagnostics();
- }
- JAI.getDefaultInstance().setTileCache(cLinkedCache);
- break;
- case 3:
- ConcurrentCache cCache = new ConcurrentCache();
- cCache.setConcurrencyLevel(concurrencyLevel);
- if (diagnostics) {
- cCache.enableDiagnostics();
- }
- JAI.getDefaultInstance().setTileCache(cCache);
- break;
- case 4:
- ConcurrentNonBlockingCache cNonBlockingCache = new ConcurrentNonBlockingCache();
- if (diagnostics) {
- cNonBlockingCache.enableDiagnostics();
- }
- JAI.getDefaultInstance().setTileCache(cNonBlockingCache);
- break;
}
JAI.getDefaultInstance().getTileCache().setMemoryCapacity(memoryCacheCapacity);
JAI.getDefaultInstance().getTileScheduler().setParallelism(10);
@@ -436,18 +412,6 @@ public void run() {
ConcurrentTileCache cTileCache = (ConcurrentTileCache) cache;
memory = cTileCache.getCacheMemoryUsed();
break;
- case 2:
- ConcurrentLinkedCache cLinkedCache = (ConcurrentLinkedCache) cache;
- memory = cLinkedCache.getCacheMemoryUsed();
- break;
- case 3:
- ConcurrentCache cCache = (ConcurrentCache) cache;
- memory = cCache.getCacheMemoryUsed();
- break;
- case 4:
- ConcurrentNonBlockingCache cNonBlockingCache = (ConcurrentNonBlockingCache) cache;
- memory = cNonBlockingCache.getCacheMemoryUsed();
- break;
}
LOGGER.log(Level.INFO, "Current Memory Used: " + memory / (1024) + " Kb");
diff --git a/concurrent-tile-cache/src/test/java/it/geosolutions/concurrencytest/ConcurrentMultiMapTest.java b/concurrent-tile-cache/src/test/java/it/geosolutions/concurrencytest/ConcurrentMultiMapTest.java
new file mode 100644
index 00000000..cd39b3af
--- /dev/null
+++ b/concurrent-tile-cache/src/test/java/it/geosolutions/concurrencytest/ConcurrentMultiMapTest.java
@@ -0,0 +1,155 @@
+package it.geosolutions.concurrencytest;
+
+import it.geosolutions.concurrent.ConcurrentTileCacheMultiMap;
+
+import java.awt.image.Raster;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import javax.imageio.stream.FileImageInputStream;
+import javax.imageio.stream.ImageInputStream;
+import javax.media.jai.RenderedOp;
+
+import junit.framework.Assert;
+
+import org.geotools.TestData;
+import org.junit.Test;
+
+import com.sun.media.jai.operator.ImageReadDescriptor;
+
+/**
+ * This test class is used for checking if the {@link ConcurrentTileCacheMultiMap} behaves correctly.
+ *
+ * @author Nicola Lagomarsini GeoSolutions S.A.S.
+ *
+ */
+public class ConcurrentMultiMapTest {
+
+ /** Total number of requests to execute */
+ private final static int TOTAL = 100;
+
+ @Test
+ public void testAddAndGetTile() throws InterruptedException, FileNotFoundException, IOException {
+ // Input stream to use
+ ImageInputStream stream_in = null;
+ try {
+ stream_in = new FileImageInputStream(TestData.file(this, "world.tiff"));
+ // Input RenderedImage to use
+ final RenderedOp input = ImageReadDescriptor.create(stream_in, 0, false, false, false,
+ null, null, null, null, null);
+
+ // Boolean used for checking if the conditions are passed
+ final AtomicBoolean passed = new AtomicBoolean(true);
+ // Cache creation
+ final ConcurrentTileCacheMultiMap cache = new ConcurrentTileCacheMultiMap(1000 * 1000,
+ false, 1f, 4);
+ // Selection of one tile from the image
+ Raster data = input.getTile(input.getMinTileX(), input.getMinTileY());
+ // Setting the tile inside the cache
+ cache.add(input, input.getMinTileX(), input.getMinTileY(), data);
+ // Thread pool to use for doing concurrent access on the cache
+ ThreadPoolExecutor executor = new ThreadPoolExecutor(TOTAL, TOTAL, 60, TimeUnit.SECONDS,
+ new ArrayBlockingQueue(1000000));
+ // Latch used for waiting all the threads to end their work
+ final CountDownLatch latch = new CountDownLatch(TOTAL);
+ // Cycle for launching various requests
+ int counter = TOTAL;
+ while (counter > 0) {
+
+ executor.execute(new Runnable() {
+
+ public void run() {
+ // Get the tile to use
+ Raster data = cache.getTile(input, input.getMinTileX(), input.getMinTileY());
+ if (data == null) {
+ passed.getAndSet(false);
+ }
+ latch.countDown();
+
+ }
+ });
+ // Counter update
+ counter--;
+ }
+ // Waiting all threads to finish
+ latch.await();
+ // Ensure that all the threads have found the tile
+ Assert.assertTrue(passed.get());
+ } finally {
+ try {
+ if (stream_in != null) {
+ stream_in.flush();
+ stream_in.close();
+ }
+ } catch (Throwable t) {
+ //
+ }
+ }
+ }
+
+ @Test
+ public void testRemoveTile() throws InterruptedException, FileNotFoundException, IOException {
+ // Input stream to use
+ ImageInputStream stream_in = null;
+ try {
+ stream_in = new FileImageInputStream(TestData.file(this, "world.tiff"));
+ // Input RenderedImage to use
+ final RenderedOp input = ImageReadDescriptor.create(stream_in, 0, false, false, false,
+ null, null, null, null, null);
+
+ // Boolean used for checking if the conditions are passed
+ final AtomicBoolean passed = new AtomicBoolean(true);
+ // Cache creation
+ final ConcurrentTileCacheMultiMap cache = new ConcurrentTileCacheMultiMap(1000 * 1000,
+ false, 1f, 4);
+ // Selection of one tile from the image
+ Raster data = input.getTile(input.getMinTileX(), input.getMinTileY());
+ // Setting the tile inside the cache
+ cache.add(input, input.getMinTileX(), input.getMinTileY(), data);
+ // Removing tile
+ cache.remove(input, input.getMinTileX(), input.getMinTileY());
+ // Thread pool to use for doing concurrent access on the cache
+ ThreadPoolExecutor executor = new ThreadPoolExecutor(TOTAL, TOTAL, 60, TimeUnit.SECONDS,
+ new ArrayBlockingQueue(1000000));
+ // Latch used for waiting all the threads to end their work
+ final CountDownLatch latch = new CountDownLatch(TOTAL);
+ // Cycle for launching various requests
+ int counter = TOTAL;
+ while (counter > 0) {
+
+ executor.execute(new Runnable() {
+
+ public void run() {
+ // Get the tile to use
+ Raster data = cache.getTile(input, input.getMinTileX(), input.getMinTileY());
+ if (data != null) {
+ passed.getAndSet(false);
+ }
+ latch.countDown();
+
+ }
+ });
+ // Counter update
+ counter--;
+ }
+ // Waiting all threads to finish
+ latch.await();
+ // Ensure that all the threads have found the tile
+ Assert.assertTrue(passed.get());
+ } finally {
+ try {
+ if (stream_in != null) {
+ stream_in.flush();
+ stream_in.close();
+ }
+ } catch (Throwable t) {
+ //
+ }
+ }
+ }
+}
diff --git a/concurrent-tile-cache/src/test/resources/it/geosolutions/concurrencytest/test-data/world.tiff b/concurrent-tile-cache/src/test/resources/it/geosolutions/concurrencytest/test-data/world.tiff
new file mode 100644
index 00000000..7ea9c6f7
Binary files /dev/null and b/concurrent-tile-cache/src/test/resources/it/geosolutions/concurrencytest/test-data/world.tiff differ
diff --git a/jt-utilities/src/test/java/it/geosolutions/jaiext/range/RangeTest.java b/jt-utilities/src/test/java/it/geosolutions/jaiext/range/RangeTest.java
index bb18a72c..e68e3c71 100644
--- a/jt-utilities/src/test/java/it/geosolutions/jaiext/range/RangeTest.java
+++ b/jt-utilities/src/test/java/it/geosolutions/jaiext/range/RangeTest.java
@@ -14,6 +14,8 @@
/**
* This test-class is used for evaluating the functionalities of the {@link Range} class and its subclasses. Also this class is compared to other
* Range classes for seeing if its contain()
method could have a better performance than that of the other Range classes.
+ *
+ * Guava Ranges are commented in order to wait to upgrade the Guava version to 14.0.1
*/
public class RangeTest {
@@ -187,25 +189,25 @@ public class RangeTest {
private static NumberRange rangeGeoToolsDpoint;
- private static com.google.common.collect.Range rangeGuavaB;
-
- private static com.google.common.collect.Range rangeGuavaS;
-
- private static com.google.common.collect.Range rangeGuavaI;
-
- private static com.google.common.collect.Range rangeGuavaF;
-
- private static com.google.common.collect.Range rangeGuavaD;
-
- private static com.google.common.collect.Range rangeGuavaBpoint;
-
- private static com.google.common.collect.Range rangeGuavaSpoint;
-
- private static com.google.common.collect.Range rangeGuavaIpoint;
-
- private static com.google.common.collect.Range rangeGuavaFpoint;
-
- private static com.google.common.collect.Range rangeGuavaDpoint;
+// private static com.google.common.collect.Range rangeGuavaB;
+//
+// private static com.google.common.collect.Range rangeGuavaS;
+//
+// private static com.google.common.collect.Range rangeGuavaI;
+//
+// private static com.google.common.collect.Range rangeGuavaF;
+//
+// private static com.google.common.collect.Range rangeGuavaD;
+//
+// private static com.google.common.collect.Range rangeGuavaBpoint;
+//
+// private static com.google.common.collect.Range rangeGuavaSpoint;
+//
+// private static com.google.common.collect.Range rangeGuavaIpoint;
+//
+// private static com.google.common.collect.Range rangeGuavaFpoint;
+//
+// private static com.google.common.collect.Range rangeGuavaDpoint;
@BeforeClass
public static void initialSetup() {
@@ -305,18 +307,18 @@ public static void initialSetup() {
rangeGeoToolsFpoint = new org.geotools.util.NumberRange(Float.class, 5f, 5f);
rangeGeoToolsDpoint = new org.geotools.util.NumberRange(Double.class, 5d, 5d);
- // Guava Ranges
- rangeGuavaB = com.google.common.collect.Range.closed((byte) 1, (byte) 60);
- rangeGuavaS = com.google.common.collect.Range.closed((short) 1, (short) 60);
- rangeGuavaI = com.google.common.collect.Range.closed(1, 60);
- rangeGuavaF = com.google.common.collect.Range.closed(0.5f, 60.5f);
- rangeGuavaD = com.google.common.collect.Range.closed(1.5d, 60.5d);
- // 1 point Ranges
- rangeGuavaBpoint = com.google.common.collect.Range.singleton((byte) 5);
- rangeGuavaSpoint = com.google.common.collect.Range.singleton((short) 5);
- rangeGuavaIpoint = com.google.common.collect.Range.singleton(5);
- rangeGuavaFpoint = com.google.common.collect.Range.singleton(5f);
- rangeGuavaDpoint = com.google.common.collect.Range.singleton(5d);
+// // Guava Ranges
+// rangeGuavaB = com.google.common.collect.Range.closed((byte) 1, (byte) 60);
+// rangeGuavaS = com.google.common.collect.Range.closed((short) 1, (short) 60);
+// rangeGuavaI = com.google.common.collect.Range.closed(1, 60);
+// rangeGuavaF = com.google.common.collect.Range.closed(0.5f, 60.5f);
+// rangeGuavaD = com.google.common.collect.Range.closed(1.5d, 60.5d);
+// // 1 point Ranges
+// rangeGuavaBpoint = com.google.common.collect.Range.singleton((byte) 5);
+// rangeGuavaSpoint = com.google.common.collect.Range.singleton((short) 5);
+// rangeGuavaIpoint = com.google.common.collect.Range.singleton(5);
+// rangeGuavaFpoint = com.google.common.collect.Range.singleton(5f);
+// rangeGuavaDpoint = com.google.common.collect.Range.singleton(5d);
}
@Test
@@ -612,51 +614,51 @@ public void testGeoToolsRangeTimeByte1or2Points() {
}
}
- @Test
- public void testGuavaRangeTimeByte1or2Points() {
-
- if (!SINGLE_POINT) {
- switch(TEST_SELECTOR){
- case DataBuffer.TYPE_BYTE:
- testGuavaRangeTime(rangeGuavaB, SINGLE_POINT,arrayBtest);
- break;
- case DataBuffer.TYPE_SHORT:
- testGuavaRangeTime(rangeGuavaS, SINGLE_POINT,arrayStest);
- break;
- case DataBuffer.TYPE_INT:
- testGuavaRangeTime(rangeGuavaI, SINGLE_POINT,arrayItest);
- break;
- case DataBuffer.TYPE_FLOAT:
- testGuavaRangeTime(rangeGuavaF, SINGLE_POINT,arrayFtest);
- break;
- case DataBuffer.TYPE_DOUBLE:
- testGuavaRangeTime(rangeGuavaD, SINGLE_POINT,arrayDtest);
- break;
- default:
- throw new IllegalArgumentException("Wrong data type");
- }
- } else {
- switch(TEST_SELECTOR){
- case DataBuffer.TYPE_BYTE:
- testGuavaRangeTime(rangeGuavaBpoint, SINGLE_POINT,arrayBtest);
- break;
- case DataBuffer.TYPE_SHORT:
- testGuavaRangeTime(rangeGuavaSpoint, SINGLE_POINT,arrayStest);
- break;
- case DataBuffer.TYPE_INT:
- testGuavaRangeTime(rangeGuavaIpoint, SINGLE_POINT,arrayItest);
- break;
- case DataBuffer.TYPE_FLOAT:
- testGuavaRangeTime(rangeGuavaFpoint, SINGLE_POINT,arrayFtest);
- break;
- case DataBuffer.TYPE_DOUBLE:
- testGuavaRangeTime(rangeGuavaDpoint, SINGLE_POINT,arrayDtest);
- break;
- default:
- throw new IllegalArgumentException("Wrong data type");
- }
- }
- }
+// @Test
+// public void testGuavaRangeTimeByte1or2Points() {
+//
+// if (!SINGLE_POINT) {
+// switch(TEST_SELECTOR){
+// case DataBuffer.TYPE_BYTE:
+// testGuavaRangeTime(rangeGuavaB, SINGLE_POINT,arrayBtest);
+// break;
+// case DataBuffer.TYPE_SHORT:
+// testGuavaRangeTime(rangeGuavaS, SINGLE_POINT,arrayStest);
+// break;
+// case DataBuffer.TYPE_INT:
+// testGuavaRangeTime(rangeGuavaI, SINGLE_POINT,arrayItest);
+// break;
+// case DataBuffer.TYPE_FLOAT:
+// testGuavaRangeTime(rangeGuavaF, SINGLE_POINT,arrayFtest);
+// break;
+// case DataBuffer.TYPE_DOUBLE:
+// testGuavaRangeTime(rangeGuavaD, SINGLE_POINT,arrayDtest);
+// break;
+// default:
+// throw new IllegalArgumentException("Wrong data type");
+// }
+// } else {
+// switch(TEST_SELECTOR){
+// case DataBuffer.TYPE_BYTE:
+// testGuavaRangeTime(rangeGuavaBpoint, SINGLE_POINT,arrayBtest);
+// break;
+// case DataBuffer.TYPE_SHORT:
+// testGuavaRangeTime(rangeGuavaSpoint, SINGLE_POINT,arrayStest);
+// break;
+// case DataBuffer.TYPE_INT:
+// testGuavaRangeTime(rangeGuavaIpoint, SINGLE_POINT,arrayItest);
+// break;
+// case DataBuffer.TYPE_FLOAT:
+// testGuavaRangeTime(rangeGuavaFpoint, SINGLE_POINT,arrayFtest);
+// break;
+// case DataBuffer.TYPE_DOUBLE:
+// testGuavaRangeTime(rangeGuavaDpoint, SINGLE_POINT,arrayDtest);
+// break;
+// default:
+// throw new IllegalArgumentException("Wrong data type");
+// }
+// }
+// }
@@ -964,38 +966,38 @@ public >void testGeoToolsRangeTime(org.geotools
+ " nsec.");
}
- public >void testGuavaRangeTime(com.google.common.collect.Range testRange,
- boolean isPoint, T[] array) {
- int totalCycles = NOT_BENCHMARK_ITERATION + BENCHMARK_ITERATION;
- // Initialization of the statistics
- long mean = 0;
- for (int i = 0; i < totalCycles; i++) {
- // Total calculation time
- long start = System.nanoTime();
-
- for (int j = 0; j < array.length; j++) {
- testRange.contains(array[j]);
- }
- long end = System.nanoTime() - start;
-
- // If the the first NOT_BENCHMARK_ITERATION cycles has been done, then the mean, maximum and minimum values are stored
- if (i > NOT_BENCHMARK_ITERATION - 1) {
- if (i == NOT_BENCHMARK_ITERATION) {
- mean = end;
- } else {
- mean = mean + end;
- }
- }
- }
- String description = "";
- if (isPoint) {
- description += " a single point";
- }
- // Mean values
- double meanValue = mean / BENCHMARK_ITERATION;
- // Output print
- System.out.println("\nMean value for" + description + " Guava Range : " + meanValue
- + " nsec.");
- }
+// public >void testGuavaRangeTime(com.google.common.collect.Range testRange,
+// boolean isPoint, T[] array) {
+// int totalCycles = NOT_BENCHMARK_ITERATION + BENCHMARK_ITERATION;
+// // Initialization of the statistics
+// long mean = 0;
+// for (int i = 0; i < totalCycles; i++) {
+// // Total calculation time
+// long start = System.nanoTime();
+//
+// for (int j = 0; j < array.length; j++) {
+// testRange.contains(array[j]);
+// }
+// long end = System.nanoTime() - start;
+//
+// // If the the first NOT_BENCHMARK_ITERATION cycles has been done, then the mean, maximum and minimum values are stored
+// if (i > NOT_BENCHMARK_ITERATION - 1) {
+// if (i == NOT_BENCHMARK_ITERATION) {
+// mean = end;
+// } else {
+// mean = mean + end;
+// }
+// }
+// }
+// String description = "";
+// if (isPoint) {
+// description += " a single point";
+// }
+// // Mean values
+// double meanValue = mean / BENCHMARK_ITERATION;
+// // Output print
+// System.out.println("\nMean value for" + description + " Guava Range : " + meanValue
+// + " nsec.");
+// }
}
diff --git a/pom.xml b/pom.xml
index 7d36bdc2..c75da939 100644
--- a/pom.xml
+++ b/pom.xml
@@ -16,7 +16,7 @@
10-SNAPSHOT
true
256M
- 14.0.1
+ 11.0.1