From de2f2ca49cce4f4bf8fd0b86004bc29a9029db92 Mon Sep 17 00:00:00 2001
From: Kai Reinhard <K.Reinhard@micromata.de>
Date: Sun, 06 Jan 2019 13:50:52 +0000
Subject: [PATCH] ConcurrentModificationException while multiple loading request of different repo archives.

---
 borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ArchiveFilelistCache.java |    7 ++++---
 borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java          |   45 +++++++++++++++++++++++++--------------------
 2 files changed, 29 insertions(+), 23 deletions(-)

diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ArchiveFilelistCache.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ArchiveFilelistCache.java
index 04abb8c..6a3ee1a 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ArchiveFilelistCache.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ArchiveFilelistCache.java
@@ -53,7 +53,9 @@
             log.info("Saving archive content as file list: " + file.getAbsolutePath());
             try (ObjectOutputStream outputStream = new ObjectOutputStream(new BufferedOutputStream(new GzipCompressorOutputStream(new FileOutputStream(file))))) {
                 outputStream.writeObject(filesystemItems.size());
-                for (BorgFilesystemItem item : filesystemItems) {
+                Iterator<BorgFilesystemItem> it = filesystemItems.iterator();
+                while(it.hasNext()) {
+                    BorgFilesystemItem item = it.next();
                     outputStream.writeObject(item);
                 }
                 outputStream.writeObject("EOF");
@@ -118,13 +120,13 @@
             return null;
         }
         log.info("Loading archive content as file list from: " + file.getAbsolutePath());
-        List<BorgFilesystemItem> list = null;
         try {
             // Set last modified time of file:
             Files.setAttribute(file.toPath(), "lastModifiedTime", FileTime.fromMillis(System.currentTimeMillis()));
         } catch (IOException ex) {
             log.error("Can't set lastModifiedTime on file '" + file.getAbsolutePath() + "'. Pruning old cache files may not work.");
         }
+        List<BorgFilesystemItem> list =  new ArrayList<>();
         try (ObjectInputStream inputStream = new ObjectInputStream(new BufferedInputStream(new GzipCompressorInputStream(new FileInputStream(file))))) {
             Object obj = inputStream.readObject();
             if (!(obj instanceof Integer)) {
@@ -132,7 +134,6 @@
                 return null;
             }
             int size = (Integer) obj;
-            list = new ArrayList<>();
             int fileNumber = -1;
             for (int i = 0; i < size; i++) {
                 ++fileNumber;
diff --git a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java
index 650d4a5..5f7f9d3 100644
--- a/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java
+++ b/borgbutler-core/src/main/java/de/micromata/borgbutler/cache/ButlerCache.java
@@ -18,6 +18,7 @@
 
 import java.io.File;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 
 /**
@@ -269,30 +270,34 @@
         if (archive == null || StringUtils.isBlank(archive.getName())) {
             return null;
         }
-        List<BorgFilesystemItem> items = archiveFilelistCache.load(repoConfig, archive, filter);
-        if (items == null && forceLoad) {
-            List<BorgFilesystemItem> list = BorgCommands.listArchiveContent(repoConfig, archive);
-            if (CollectionUtils.isNotEmpty(list)) {
-                archiveFilelistCache.save(repoConfig, archive, list);
-                items = new ArrayList<>();
-                int fileNumber = -1;
-                for (BorgFilesystemItem item : list) {
-                    ++fileNumber;
-                    item.setFileNumber(fileNumber);
-                    if (filter == null || filter.matches(item)) {
-                        items.add(item);
-                        if (filter != null && filter.isFinished()) break;
+        synchronized (archive) {
+            List<BorgFilesystemItem> items = archiveFilelistCache.load(repoConfig, archive, filter);
+            if (items == null && forceLoad) {
+                List<BorgFilesystemItem> list = BorgCommands.listArchiveContent(repoConfig, archive);
+                if (CollectionUtils.isNotEmpty(list)) {
+                    archiveFilelistCache.save(repoConfig, archive, list);
+                    items = new ArrayList<>();
+                    int fileNumber = -1;
+                    Iterator<BorgFilesystemItem> it = list.iterator(); // Don't use for-each (ConcurrentModificationException)
+                    while (it.hasNext()) {
+                        BorgFilesystemItem item = it.next();
+                        ++fileNumber;
+                        item.setFileNumber(fileNumber);
+                        if (filter == null || filter.matches(item)) {
+                            items.add(item);
+                            if (filter != null && filter.isFinished()) break;
+                        }
+                    }
+                    if (filter != null) {
+                        items = filter.reduce(items);
                     }
                 }
-                if (filter != null) {
-                    items = filter.reduce(items);
-                }
             }
+            if (items == null && forceLoad) {
+                log.warn("Repo::archiv with name '" + archive.getBorgIdentifier() + "' not found.");
+            }
+            return items;
         }
-        if (items == null && forceLoad) {
-            log.warn("Repo::archiv with name '" + archive.getBorgIdentifier() + "' not found.");
-        }
-        return items;
     }
 
     public List<BorgFilesystemItem> getArchiveContent(File file) {

--
Gitblit v1.10.0