From 1537fb95a9977a162dc29e2487c4020e96b43074 Mon Sep 17 00:00:00 2001
From: Kai Reinhard <K.Reinhard@micromata.de>
Date: Mon, 10 Dec 2018 04:19:02 +0000
Subject: [PATCH] Last modifications (untested) before migrating to Apache jcs.

---
 borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractCache.java |  127 +++++++++++++++++++++++-------------------
 1 files changed, 70 insertions(+), 57 deletions(-)

diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractCache.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractCache.java
index d89de91..4072ebd 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractCache.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractCache.java
@@ -21,11 +21,6 @@
     private static final String CACHE_FILE_EXTENSION = "json";
     private static final String CACHE_FILE_ZIP_EXTENSION = ".gz";
 
-    /**
-     * INITIAL - on startup (not yet read), DIRTY - modifications not written, SAVED - content written to file.
-     */
-    protected enum STATE {INITIAL, DIRTY, SAVED}
-
     @JsonIgnore
     protected File cacheFile;
     @JsonIgnore
@@ -33,7 +28,7 @@
     private boolean compress;
     @Getter
     @JsonIgnore
-    private STATE state = STATE.INITIAL;
+    private CacheState state = CacheState.INITIAL;
     @Getter
     private Date lastModified;
     @Getter
@@ -43,7 +38,7 @@
      * Removes all entries (doesn't effect the cache files!).
      */
     public void clear() {
-        state = STATE.DIRTY;
+        state = CacheState.INITIAL;
     }
 
     /**
@@ -56,76 +51,94 @@
                 cacheFile.delete();
             }
             clear();
-            state = STATE.SAVED;
         }
     }
 
     protected void setDirty() {
-        state = STATE.DIRTY;
+        state = CacheState.DIRTY;
     }
 
     public void read() {
-        try {
-            if (!cacheFile.exists()) {
-                // Cache file doesn't exist. Nothing to read.
-                state = STATE.DIRTY; // Needed to save cache to file.
+        if (state == CacheState.LOADING_FROM_CACHE_FILE) {
+            // Already in progress, nothing to do.
+            synchronized (this) {
+                // Wait and do nothing.
                 return;
             }
-            log.info("Parsing cache file '" + cacheFile.getAbsolutePath() + "'.");
-            String json;
-            if (compress) {
-                try (GzipCompressorInputStream in = new GzipCompressorInputStream(new FileInputStream(cacheFile))) {
-                    StringWriter writer = new StringWriter();
-                    IOUtils.copy(in, writer, Definitions.STD_CHARSET);
-                    json = writer.toString();
+        }
+        synchronized (this) {
+            try {
+                state = CacheState.LOADING_FROM_CACHE_FILE;
+                if (!cacheFile.exists()) {
+                    // Cache file doesn't exist. Nothing to read.
+                    state = CacheState.DIRTY; // Needed to save cache to file.
+                    return;
                 }
-            } else {
-                json = FileUtils.readFileToString(cacheFile, Definitions.STD_CHARSET);
+                log.info("Parsing cache file '" + cacheFile.getAbsolutePath() + "'.");
+                String json;
+                if (compress) {
+                    try (GzipCompressorInputStream in = new GzipCompressorInputStream(new FileInputStream(cacheFile))) {
+                        StringWriter writer = new StringWriter();
+                        IOUtils.copy(in, writer, Definitions.STD_CHARSET);
+                        json = writer.toString();
+                    }
+                } else {
+                    json = FileUtils.readFileToString(cacheFile, Definitions.STD_CHARSET);
+                }
+                AbstractCache readCache = JsonUtils.fromJson(this.getClass(), json);
+                if (readCache != null) {
+                    this.lastModified = readCache.lastModified;
+                    this.created = readCache.created;
+                    update(readCache);
+                    this.state = CacheState.SAVED; // State of cache is updated from cache file.
+                } else {
+                    log.error("Error while parsing cache: " + cacheFile.getAbsolutePath());
+                    this.state = CacheState.DIRTY; // Needed to save cache to file.
+                }
+            } catch (IOException ex) {
+                log.error("Error while trying to read cache file '" + cacheFile.getAbsolutePath() + "': "
+                        + ex.getMessage(), ex);
+                this.state = CacheState.DIRTY; // Needed to save cache to file.
             }
-            AbstractCache readCache = JsonUtils.fromJson(this.getClass(), json);
-            if (readCache != null) {
-                this.lastModified = readCache.lastModified;
-                this.created = readCache.created;
-                this.state = STATE.SAVED; // State of cache is updated from cache file.
-                update(readCache);
-            } else {
-                log.error("Error while parsing cache: " + cacheFile.getAbsolutePath());
-                this.state = STATE.DIRTY; // Needed to save cache to file.
-            }
-        } catch (IOException ex) {
-            log.error("Error while trying to read cache file '" + cacheFile.getAbsolutePath() + "': "
-                    + ex.getMessage(), ex);
-            this.state = STATE.DIRTY; // Needed to save cache to file.
         }
     }
 
     protected abstract void update(AbstractCache readCache);
 
     public void save() {
-        if (this.state == STATE.SAVED || this.state == STATE.INITIAL) {
+        if (this.state == CacheState.SAVED || this.state == CacheState.INITIAL) {
             log.info("Cache file is up to date (nothing to save): " + cacheFile);
             return;
         }
-        log.info("Saving to cache file: " + cacheFile);
-        if (created == null) {
-            created = lastModified = new Date();
-        } else {
-            lastModified = new Date();
-        }
-        String json = JsonUtils.toJson(this);
-        try {
-            if (this.compress) {
-                try (GzipCompressorOutputStream out = new GzipCompressorOutputStream(new FileOutputStream(cacheFile))) {
-                    IOUtils.copy(new StringReader(json), out, Definitions.STD_CHARSET);
-                }
-            } else {
-                FileUtils.write(cacheFile, json, Definitions.STD_CHARSET);
+        if (state == CacheState.SAVING) {
+            // Already in progress, nothing to do.
+            synchronized (this) {
+                // Wait and do nothing.
+                return;
             }
-            this.state = STATE.SAVED;
-        } catch (IOException ex) {
-            log.error("Error while trying to write cache file '" + cacheFile.getAbsolutePath() + "': "
-                    + ex.getMessage(), ex);
-            this.state = STATE.DIRTY;
+        }
+        synchronized (this) {
+            log.info("Saving to cache file: " + cacheFile);
+            if (created == null) {
+                created = lastModified = new Date();
+            } else {
+                lastModified = new Date();
+            }
+            String json = JsonUtils.toJson(this);
+            try {
+                if (this.compress) {
+                    try (GzipCompressorOutputStream out = new GzipCompressorOutputStream(new FileOutputStream(cacheFile))) {
+                        IOUtils.copy(new StringReader(json), out, Definitions.STD_CHARSET);
+                    }
+                } else {
+                    FileUtils.write(cacheFile, json, Definitions.STD_CHARSET);
+                }
+                this.state = CacheState.SAVED;
+            } catch (IOException ex) {
+                log.error("Error while trying to write cache file '" + cacheFile.getAbsolutePath() + "': "
+                        + ex.getMessage(), ex);
+                this.state = CacheState.DIRTY;
+            }
         }
     }
 
@@ -145,7 +158,7 @@
         if (this.compress)
             filename = filename + CACHE_FILE_ZIP_EXTENSION;
         cacheFile = new File(cacheDir, filename);
-        this.state = STATE.INITIAL;
+        this.state = CacheState.INITIAL;
     }
 
     public static boolean isCacheFile(File file) {

--
Gitblit v1.10.0