Ticket #23258: 23258.patch

File 23258.patch, 5.2 KB (added by marcello@…, 2 years ago)

patch

  • src/org/openstreetmap/josm/data/cache/JCSCacheManager.java

    diff --git a/src/org/openstreetmap/josm/data/cache/JCSCacheManager.java b/src/org/openstreetmap/josm/data/cache/JCSCacheManager.java
    index ad6c50ae9..6c246a853 100644
    a b import java.nio.channels.FileLock;  
    88import java.nio.file.StandardOpenOption;
    99import java.util.Arrays;
    1010import java.util.Collections;
     11import java.util.HashMap;
     12import java.util.Map;
    1113import java.util.Properties;
    1214import java.util.logging.Handler;
    1315import java.util.logging.Level;
    public final class JCSCacheManager {  
    5052    public static final BooleanProperty USE_BLOCK_CACHE = new BooleanProperty(PREFERENCE_PREFIX + ".use_block_cache", true);
    5153
    5254    private static final AuxiliaryCacheFactory DISK_CACHE_FACTORY = getDiskCacheFactory();
    53     private static FileLock cacheDirLock;
     55    /**
     56     * These locks prevents multiple running JOSM instances from thrashing each other's
     57     * caches. A single lock is not appropriate because it prevents Gradle from running
     58     * JUnit tests in parallel on multiple VMs.
     59     */
     60    private static Map<String, FileLock> cacheDirLock = new HashMap<>();
    5461
    5562    /**
    5663     * default objects to be held in memory by JCS caches (per region)
    public final class JCSCacheManager {  
    106113    }
    107114
    108115    static {
    109         File cacheDir = new File(Config.getDirs().getCacheDirectory(true), "jcs");
    110 
    111         try {
    112             if (!cacheDir.exists() && !cacheDir.mkdirs()) {
    113                 Logging.warn("Cache directory " + cacheDir.toString() + " does not exists and could not create it");
    114             } else {
    115                 File cacheDirLockPath = new File(cacheDir, ".lock");
    116                 try {
    117                     if (!cacheDirLockPath.exists() && !cacheDirLockPath.createNewFile()) {
    118                         Logging.warn("Cannot create cache dir lock file");
    119                     }
    120                     cacheDirLock = FileChannel.open(cacheDirLockPath.toPath(), StandardOpenOption.WRITE).tryLock();
    121 
    122                     if (cacheDirLock == null)
    123                         Logging.warn("Cannot lock cache directory. Will not use disk cache");
    124                 } catch (IOException e) {
    125                     Logging.log(Logging.LEVEL_WARN, "Cannot create cache dir \"" + cacheDirLockPath + "\" lock file:", e);
    126                     Logging.warn("Will not use disk cache");
    127                 }
    128             }
    129         } catch (Exception e) {
    130             Logging.log(Logging.LEVEL_WARN, "Unable to configure disk cache. Will not use it", e);
    131         }
    132 
    133116        // this could be moved to external file
    134117        Properties props = new Properties();
    135118        // these are default common to all cache regions
    public final class JCSCacheManager {  
    152135        }
    153136    }
    154137
     138    /**
     139     * Try to acquire a lock for a cache directory.
     140     */
     141    static FileLock tryLock(String cachePath) {
     142        if (cacheDirLock.get(cachePath) != null)
     143            return cacheDirLock.get(cachePath);
     144
     145        File cacheDir = new File(Config.getDirs().getCacheDirectory(true), cachePath);
     146        try {
     147            if (!cacheDir.exists() && !cacheDir.mkdirs()) {
     148                Logging.warn("Cache directory " + cacheDir.toString() + " does not exists and could not create it");
     149            } else {
     150                File cacheDirLockPath = new File(cacheDir, ".lock");
     151                try {
     152                    if (!cacheDirLockPath.exists() && !cacheDirLockPath.createNewFile()) {
     153                        Logging.warn("Cannot create cache dir lock file");
     154                    }
     155                    FileLock lock = FileChannel.open(cacheDirLockPath.toPath(), StandardOpenOption.WRITE).tryLock();
     156
     157                    if (lock == null)
     158                        Logging.warn("Cannot lock cache directory. Will not use disk cache");
     159                    cacheDirLock.put(cachePath, lock);
     160                } catch (IOException e) {
     161                    Logging.log(Logging.LEVEL_WARN, "Cannot create cache dir \"" + cacheDirLockPath + "\" lock file:", e);
     162                    Logging.warn("Will not use disk cache");
     163                }
     164            }
     165        } catch (Exception e) {
     166            Logging.log(Logging.LEVEL_WARN, "Unable to configure disk cache. Will not use it", e);
     167        }
     168        return cacheDirLock.get(cachePath);
     169    }
     170
    155171    private static AuxiliaryCacheFactory getDiskCacheFactory() {
    156172        try {
    157173            return useBlockCache() ? new BlockDiskCacheFactory() : new IndexedDiskCacheFactory();
    public final class JCSCacheManager {  
    189205    public static <K, V> CacheAccess<K, V> getCache(String cacheName, int maxMemoryObjects, int maxDiskObjects, String cachePath) {
    190206        CacheAccess<K, V> cacheAccess = getCacheAccess(cacheName, getCacheAttributes(maxMemoryObjects));
    191207
    192         if (cachePath != null && cacheDirLock != null && cacheAccess != null && DISK_CACHE_FACTORY != null) {
     208        if (cachePath != null && tryLock(cachePath) != null && cacheAccess != null && DISK_CACHE_FACTORY != null) {
    193209            CompositeCache<K, V> cc = cacheAccess.getCacheControl();
    194210            try {
    195211                IDiskCacheAttributes diskAttributes = getDiskCacheAttributes(maxDiskObjects, cachePath, cacheName);