From 5013f8b1c1f2fb703bb58f48d3268b35e3b36562 Mon Sep 17 00:00:00 2001 From: Kai Takac Date: Wed, 4 Dec 2019 19:04:58 +0100 Subject: [PATCH 1/2] Add throttle to AutosaveUIManager (fixes #5679) --- CHANGELOG.md | 1 + .../autosaveandbackup/AutosaveManager.java | 31 +++++++++---------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c7510c95a7..c7fd0e48924 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - We added support to switch between biblatex and bibtex library types. [#5550](https://github.com/JabRef/jabref/issues/5550) - We changed the save action buttons to be easier to understand. [#5565](https://github.com/JabRef/jabref/issues/5565) - We made the columns for groups, files and uri in the main table reorderable and merged the clickable icon columns for uri, url, doi and eprint. [#5544](https://github.com/JabRef/jabref/pull/5544) +- We reduced the number of write actions performed when autosave is enabled [#5679](https://github.com/JabRef/jabref/issues/5679) ### Fixed diff --git a/src/main/java/org/jabref/logic/autosaveandbackup/AutosaveManager.java b/src/main/java/org/jabref/logic/autosaveandbackup/AutosaveManager.java index 95a651c7aa6..d401e3f2439 100644 --- a/src/main/java/org/jabref/logic/autosaveandbackup/AutosaveManager.java +++ b/src/main/java/org/jabref/logic/autosaveandbackup/AutosaveManager.java @@ -2,12 +2,7 @@ import java.util.HashSet; import java.util.Set; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.RejectedExecutionException; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.database.event.AutosaveEvent; @@ -21,24 +16,27 @@ /** * Saves the given {@link BibDatabaseContext} on every {@link BibDatabaseContextChangedEvent} by posting a new {@link AutosaveEvent}. - * An intelligent {@link ExecutorService} with a {@link BlockingQueue} prevents a high load while saving and rejects all redundant save tasks. + * An intelligent {@link ScheduledThreadPoolExecutor} prevents a high load while saving and rejects all redundant save tasks. + * The scheduled action is stored and canceled if a newer save action is proposed. */ public class AutosaveManager { private static final Logger LOGGER = LoggerFactory.getLogger(AutosaveManager.class); + private static final int AUTO_SAVE_DELAY = 200; private static Set runningInstances = new HashSet<>(); private final BibDatabaseContext bibDatabaseContext; - private final BlockingQueue workerQueue; - private final ExecutorService executor; + private final ScheduledExecutorService executor; private final EventBus eventBus; private final CoarseChangeFilter changeFilter; + private Future scheduledSaveAction; private AutosaveManager(BibDatabaseContext bibDatabaseContext) { this.bibDatabaseContext = bibDatabaseContext; - this.workerQueue = new ArrayBlockingQueue<>(1); - this.executor = new ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS, workerQueue); + ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1); + executor.setRemoveOnCancelPolicy(true); // This prevents memory leaks + this.executor = executor; this.eventBus = new EventBus(); this.changeFilter = new CoarseChangeFilter(bibDatabaseContext); changeFilter.registerListener(this); @@ -46,13 +44,12 @@ private AutosaveManager(BibDatabaseContext bibDatabaseContext) { @Subscribe public synchronized void listen(@SuppressWarnings("unused") BibDatabaseContextChangedEvent event) { - try { - executor.submit(() -> { - eventBus.post(new AutosaveEvent()); - }); - } catch (RejectedExecutionException e) { - LOGGER.debug("Rejecting autosave while another save process is already running."); + if(scheduledSaveAction != null) { + scheduledSaveAction.cancel(false); } + scheduledSaveAction = executor.schedule(() -> { + eventBus.post(new AutosaveEvent()); + }, AUTO_SAVE_DELAY, TimeUnit.MILLISECONDS); } private void shutdown() { From 1c90ac1543a0e9fe189a51708f9e32370ab251ae Mon Sep 17 00:00:00 2001 From: Kai Takac Date: Thu, 5 Dec 2019 18:26:37 +0100 Subject: [PATCH 2/2] Fix checkstyle errors --- .../jabref/logic/autosaveandbackup/AutosaveManager.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jabref/logic/autosaveandbackup/AutosaveManager.java b/src/main/java/org/jabref/logic/autosaveandbackup/AutosaveManager.java index d401e3f2439..10e941fac15 100644 --- a/src/main/java/org/jabref/logic/autosaveandbackup/AutosaveManager.java +++ b/src/main/java/org/jabref/logic/autosaveandbackup/AutosaveManager.java @@ -2,7 +2,10 @@ import java.util.HashSet; import java.util.Set; -import java.util.concurrent.*; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import org.jabref.model.database.BibDatabaseContext; import org.jabref.model.database.event.AutosaveEvent; @@ -44,7 +47,7 @@ private AutosaveManager(BibDatabaseContext bibDatabaseContext) { @Subscribe public synchronized void listen(@SuppressWarnings("unused") BibDatabaseContextChangedEvent event) { - if(scheduledSaveAction != null) { + if (scheduledSaveAction != null) { scheduledSaveAction.cancel(false); } scheduledSaveAction = executor.schedule(() -> {