mirror of https://github.com/micromata/borgbackup-butler.git

Kai Reinhard
10.19.2018 1537fb95a9977a162dc29e2487c4020e96b43074
Last modifications (untested) before migrating to Apache jcs.
1 files added
3 files modified
164 ■■■■■ changed files
borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractCache.java 127 ●●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractElementsCache.java 2 ●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/cache/CacheState.java 33 ●●●●● patch | view | raw | blame | history
borgbutler-server/src/main/java/de/micromata/borgbutler/server/Main.java 2 ●●●●● patch | view | raw | blame | history
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) {
borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractElementsCache.java
@@ -19,7 +19,7 @@
        if (identifier == null) {
            return null;
        }
        if (getState() == STATE.INITIAL) {
        if (getState() == CacheState.INITIAL) {
            read();
        }
        for (T element : elements.values()) {
borgbutler-core/src/main/java/de/micromata/borgbutler/cache/CacheState.java
New file
@@ -0,0 +1,33 @@
package de.micromata.borgbutler.cache;
/**
 * ,
 * PARSING - , DIRTY - , SAVED -
 */
public enum CacheState {
    /**
     * On startup or directly after {@link AbstractCache#clear()} is called. (not yet read).
     */
    INITIAL,
    /**
     * Cache is been loaded (with borg command).
     */
    LOADING_FROM_BORG,
    /**
     * Cache is beeing loaded from filesystem.
     */
    LOADING_FROM_CACHE_FILE,
    /**
     * Modifications done but not yet written.
     */
    DIRTY,
    /**
     * Save to cache file is in progress.
     */
    SAVING,
    /**
     * Content has been written to file, no modifications done after. Cache file is up-to-date.
     */
    SAVED
}
borgbutler-server/src/main/java/de/micromata/borgbutler/server/Main.java
@@ -1,5 +1,6 @@
package de.micromata.borgbutler.server;
import de.micromata.borgbutler.cache.ButlerCache;
import de.micromata.borgbutler.server.jetty.JettyServer;
import de.micromata.borgbutler.server.user.SingleUserManager;
import de.micromata.borgbutler.server.user.UserManager;
@@ -104,6 +105,7 @@
        }
        log.info("Shutting down BorgButler web server...");
        server.stop();
        ButlerCache.getInstance().save();
    }
    private static void printHelp(Options options) {