diff --git a/geowebcache/core/src/main/java/org/geowebcache/locks/MemoryLockProvider.java b/geowebcache/core/src/main/java/org/geowebcache/locks/MemoryLockProvider.java index 55a814c2a..d3d15e248 100644 --- a/geowebcache/core/src/main/java/org/geowebcache/locks/MemoryLockProvider.java +++ b/geowebcache/core/src/main/java/org/geowebcache/locks/MemoryLockProvider.java @@ -14,26 +14,26 @@ */ package org.geowebcache.locks; -import org.geotools.util.logging.Logging; - import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Level; import java.util.logging.Logger; +import org.geotools.util.logging.Logging; /** * An in memory lock provider. - *

- * This provider does not constrain the number of locks that can be held at any given time. - * Because any one thread can hold multiple locks at a time, a more appropriate approach - * to constraining resource usage would be to limit the number of concurrent threads instead. - *

- * One objective of this class is to support - * nested locking scenarios. This class used to use a striped lock algorithm which - * would cause deadlocks for nested locking because of the non-predictable manner in - * which any lock can be arbitrarily locked by another unrelated lock. An example use case of - * nested locks, in pseudocode, would be: + * + *

This provider does not constrain the number of locks that can be held at any given time. + * Because any one thread can hold multiple locks at a time, a more appropriate approach to + * constraining resource usage would be to limit the number of concurrent threads instead. + * + *

One objective of this class is to support nested locking + * scenarios. This class used to use a striped lock algorithm which would cause deadlocks for + * nested locking because of the non-predictable manner in which any lock can be arbitrarily locked + * by another unrelated lock. An example use case of nested locks, in pseudocode, would be: + * *

  *  lock(metatile);
  *  try {
@@ -54,7 +54,7 @@
  */
 public class MemoryLockProvider implements LockProvider {
 
-    private final static Logger LOGGER = Logging.getLogger(MemoryLockProvider.class.getName());
+    private static final Logger LOGGER = Logging.getLogger(MemoryLockProvider.class.getName());
 
     ConcurrentHashMap lockAndCounters = new ConcurrentHashMap<>();
 
@@ -93,8 +93,10 @@ public void release() {
                     // Attempt to remove lock if no other thread is waiting for it
                     if (lockAndCounter.counter.decrementAndGet() == 0) {
 
-                        // Try to remove the lock, but we have to check the count AGAIN inside of "compute"
-                        // so that we know it hasn't been incremented since the if-statement above was evaluated
+                        // Try to remove the lock, but we have to check the count AGAIN inside of
+                        // "compute"
+                        // so that we know it hasn't been incremented since the if-statement above
+                        // was evaluated
                         lockAndCounters.compute(
                                 lockKey,
                                 (key, existingLockAndCounter) -> {
@@ -113,8 +115,8 @@ public void release() {
     }
 
     /**
-     * A ReentrantLock with a counter to track how many threads are waiting on this lock
-     * so we know if it's safe to remove it during a release.
+     * A ReentrantLock with a counter to track how many threads are waiting on this lock so we know
+     * if it's safe to remove it during a release.
      */
     private static class LockAndCounter {
         private final java.util.concurrent.locks.Lock lock = new ReentrantLock();
diff --git a/geowebcache/core/src/main/java/org/geowebcache/storage/blobstore/file/FileBlobStore.java b/geowebcache/core/src/main/java/org/geowebcache/storage/blobstore/file/FileBlobStore.java
index 39f3b18d5..0d57555d5 100644
--- a/geowebcache/core/src/main/java/org/geowebcache/storage/blobstore/file/FileBlobStore.java
+++ b/geowebcache/core/src/main/java/org/geowebcache/storage/blobstore/file/FileBlobStore.java
@@ -14,7 +14,6 @@
  */
 package org.geowebcache.storage.blobstore.file;
 
-import static java.util.Objects.isNull;
 import static org.geowebcache.storage.blobstore.file.FilePathUtils.filteredGridSetId;
 import static org.geowebcache.storage.blobstore.file.FilePathUtils.filteredLayerName;
 import static org.geowebcache.util.FileUtils.listFilesNullSafe;
@@ -71,7 +70,12 @@
 /** See BlobStore interface description for details */
 public class FileBlobStore implements BlobStore {
 
-    interface Writer {
+    /**
+     * Interface for writing files. This is used to abstract the writing of files to allow different
+     * types of file writes, while keeping the same general machinery (write on temp file, rename to
+     * final file).
+     */
+    interface FileWriter {
         void write(File file) throws IOException;
     }
 
@@ -526,10 +530,9 @@ public void put(TileObject stObj) throws StorageException {
     private void putParametersMetadata(
             String layerName, String parametersId, Map parameters)
             throws StorageException {
-        assert (isNull(parametersId) == isNull(parameters));
-        if (isNull(parametersId)) {
-            return;
-        }
+        // check if we even need to use any IO
+        if (parametersId == null || parameters == null || parameters.isEmpty()) return;
+
         File parametersFile = parametersFile(layerName, parametersId);
         if (parametersFile.exists()) return;
 
@@ -606,7 +609,8 @@ private void writeTile(File target, TileObject stObj, boolean existed) throws St
      *
      * @throws StorageException
      */
-    private void writeFile(File target, boolean existed, Writer writer) throws StorageException {
+    private void writeFile(File target, boolean existed, FileWriter writer)
+            throws StorageException {
         // first write to temp file
         tmp.mkdirs();
         File temp = new File(tmp, tmpGenerator.newName());
@@ -769,6 +773,18 @@ public boolean deleteByParametersId(String layerName, String parametersId)
         // delete the parameter file
         parametersFile(layerName, parametersId).delete();
 
+        // clean up from the legacy metadata storage as well, if necessary
+        try {
+            layerMetadata.putEntry(layerName, "parameters." + parametersId, null);
+        } catch (IOException e) {
+            log.log(
+                    Level.WARNING,
+                    String.format(
+                            "Failed to clean up metadata for parameters %s in layer %s",
+                            parametersId, layerName),
+                    e);
+        }
+
         // delete the caches
         File[] parameterCaches =
                 listFilesNullSafe(