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

Kai Reinhard
09.28.2018 5c94bff143dd5876046e528855497a96cd2bb55a
Caches... (compressing started).
3 files modified
85 ■■■■ changed files
borgbutler-core/build.gradle 2 ●●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractCache.java 82 ●●●● patch | view | raw | blame | history
borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java 1 ●●●● patch | view | raw | blame | history
borgbutler-core/build.gradle
@@ -10,6 +10,8 @@
    compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.1'
    compile group: 'org.apache.commons', name: 'commons-exec', version: '1.3'
    compile group: 'org.apache.commons', name: 'commons-collections4', version: '4.2'
    compile group: 'org.apache.commons', name: 'commons-compress', version: '1.18'
    compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.6'
    compile group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.9.6'
borgbutler-core/src/main/java/de/micromata/borgbutler/cache/AbstractCache.java
@@ -1,18 +1,20 @@
package de.micromata.borgbutler.cache;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import de.micromata.borgbutler.config.BorgRepoConfig;
import de.micromata.borgbutler.config.Definitions;
import de.micromata.borgbutler.json.JsonUtils;
import lombok.Getter;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.io.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@@ -20,17 +22,34 @@
    private static Logger log = LoggerFactory.getLogger(AbstractCache.class);
    private static final String CACHE_FILE_PREFIX = "cache-";
    private static final String CACHE_FILE_EXTENSION = "json";
    private static final String CACHE_FILE_ZIP_EXTENSION = ".zip";
    /**
     * INITIAL - on startup (not yet read), DIRTY - modifications not written, SAVED - content written to file.
     */
    private enum STATE {INITIAL, DIRTY, SAVED}
    @JsonIgnore
    protected File cacheFile;
    @JsonIgnore
    @Getter
    @JsonProperty
    private boolean zip;
    @JsonIgnore
    private STATE state = STATE.INITIAL;
    @Getter
    private Date lastModified;
    @Getter
    private Date created;
    @Getter
    protected Map<String, T> elements = new HashMap<>();
    public T get(BorgRepoConfig repoConfig, String identifier) {
        if (identifier == null) {
            return null;
        }
        if (this.state == STATE.INITIAL) {
            read();
        }
        for (T element : elements.values()) {
            if (matches(element, identifier)) {
                return element;
@@ -52,6 +71,7 @@
     */
    public void clear() {
        elements.clear();
        state = STATE.DIRTY;
    }
    public void upsert(BorgRepoConfig repoConfig, T element) {
@@ -61,36 +81,69 @@
        } else {
            updateFrom(existingElement, element);
        }
        state = STATE.DIRTY; // Needed to save cache to file.
    }
    public void read() {
        try {
            if (!cacheFile.exists()) {
                // Cache file doesn't exist. Nothing to read.
                state = STATE.DIRTY; // Needed to save cache to file.
                return;
            }
            log.info("Parsing cache file '" + cacheFile.getAbsolutePath() + "'.");
            String json = FileUtils.readFileToString(cacheFile, Charset.forName("UTF-8"));
            String json;
            if (zip) {
                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.elements = readCache.elements;
                this.lastModified = readCache.lastModified;
                this.created = readCache.created;
                this.state = STATE.SAVED; // State of cache is updated from cache file.
            } 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.
        }
    }
    public void save() {
        if (this.state == STATE.SAVED || this.state == STATE.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 {
            FileUtils.write(cacheFile, json, Charset.forName("UTF-8"));
            if (this.zip) {
                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 = STATE.SAVED;
        } catch (IOException ex) {
            log.error("Error while trying to write repos cache file '" + cacheFile.getAbsolutePath() + "': "
            log.error("Error while trying to write cache file '" + cacheFile.getAbsolutePath() + "': "
                    + ex.getMessage(), ex);
            this.state = STATE.DIRTY;
        }
    }
@@ -101,12 +154,23 @@
    }
    AbstractCache(File cacheDir, String cacheFilename) {
        this(cacheDir, cacheFilename, false);
    }
    AbstractCache(File cacheDir, String cacheFilename, boolean zip) {
        this.zip = zip;
        String filename = CACHE_FILE_PREFIX + cacheFilename + "." + CACHE_FILE_EXTENSION;
        if (this.zip)
            filename = filename + CACHE_FILE_EXTENSION;
        cacheFile = new File(cacheDir, CACHE_FILE_PREFIX + cacheFilename + "." + CACHE_FILE_EXTENSION);
        this.state = STATE.INITIAL;
    }
    public static boolean isCacheFile(File file) {
        String filename = file.getName();
        String extension = FilenameUtils.getExtension(filename);
        return filename.startsWith(CACHE_FILE_PREFIX) && extension.equals(CACHE_FILE_EXTENSION);
        return filename.startsWith(CACHE_FILE_PREFIX) &&
                (extension.equals(CACHE_FILE_EXTENSION)
                        || extension.equals(CACHE_FILE_EXTENSION + CACHE_FILE_ZIP_EXTENSION));
    }
}
borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java
@@ -67,6 +67,5 @@
        caches.add(repoInfoCache = new RepoInfoCache(cacheDir));
        caches.add(repoListCache = new RepoListCache(cacheDir));
        caches.add(archiveListCache = new ArchiveListCache(cacheDir));
        read();
    }
}