From 18ae9bb57db46d7d8720394cf409d56cd4b750f7 Mon Sep 17 00:00:00 2001 From: Matthias Sohn Date: Sun, 11 Jun 2017 01:20:34 +0200 Subject: Allow to use an external ExecutorService for background auto-gc If set use the external executor, otherwise use JGit's own simple WorkQueue. Move WorkQueue to an internal package so we can reuse it without exposing it in the public API. Change-Id: I060d62ffd6692362a88b4bf13ee07b0dc857abe9 Signed-off-by: Matthias Sohn --- .../org/eclipse/jgit/internal/storage/file/GC.java | 22 ++++- .../eclipse/jgit/lib/BatchingProgressMonitor.java | 2 + .../src/org/eclipse/jgit/lib/RepositoryCache.java | 1 + .../src/org/eclipse/jgit/lib/WorkQueue.java | 100 -------------------- .../org/eclipse/jgit/lib/internal/WorkQueue.java | 103 +++++++++++++++++++++ 5 files changed, 125 insertions(+), 103 deletions(-) delete mode 100644 org.eclipse.jgit/src/org/eclipse/jgit/lib/WorkQueue.java create mode 100644 org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/WorkQueue.java (limited to 'org.eclipse.jgit/src/org') diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java index 17f3e6ab84..ad611d3505 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/GC.java @@ -78,7 +78,6 @@ import java.util.TreeMap; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -107,6 +106,7 @@ import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.lib.ProgressMonitor; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Ref.Storage; +import org.eclipse.jgit.lib.internal.WorkQueue; import org.eclipse.jgit.lib.RefDatabase; import org.eclipse.jgit.lib.ReflogEntry; import org.eclipse.jgit.lib.ReflogReader; @@ -151,7 +151,19 @@ public class GC { private static final int DEFAULT_AUTOLIMIT = 6700; - private static ExecutorService executor = Executors.newFixedThreadPool(1); + private static volatile ExecutorService executor; + + /** + * Set the executor for running auto-gc in the background. If no executor is + * set JGit's own WorkQueue will be used. + * + * @param e + * the executor to be used for running auto-gc + * @since 4.8 + */ + public static void setExecutor(ExecutorService e) { + executor = e; + } private final FileRepository repo; @@ -271,7 +283,7 @@ public class GC { } return Collections.emptyList(); }; - Future> result = executor.submit(gcTask); + Future> result = executor().submit(gcTask); if (background) { // TODO(ms): in 5.0 change signature and return the Future return Collections.emptyList(); @@ -283,6 +295,10 @@ public class GC { } } + private ExecutorService executor() { + return (executor != null) ? executor : WorkQueue.getExecutor(); + } + private Collection doGc() throws IOException, ParseException { if (automatic && !needGc()) { return Collections.emptyList(); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchingProgressMonitor.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchingProgressMonitor.java index 54c80522b8..a75293d6cb 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchingProgressMonitor.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BatchingProgressMonitor.java @@ -46,6 +46,8 @@ package org.eclipse.jgit.lib; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import org.eclipse.jgit.lib.internal.WorkQueue; + /** ProgressMonitor that batches update events. */ public abstract class BatchingProgressMonitor implements ProgressMonitor { private long delayStartTime; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java index baa5286862..53e9fe3c53 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/RepositoryCache.java @@ -55,6 +55,7 @@ import java.util.concurrent.TimeUnit; import org.eclipse.jgit.annotations.NonNull; import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.internal.storage.file.FileRepository; +import org.eclipse.jgit.lib.internal.WorkQueue; import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.IO; import org.eclipse.jgit.util.RawParseUtils; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/WorkQueue.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/WorkQueue.java deleted file mode 100644 index 07b87f58d2..0000000000 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/WorkQueue.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2008-2016, Google Inc. - * and other copyright owners as documented in the project's IP log. - * - * This program and the accompanying materials are made available - * under the terms of the Eclipse Distribution License v1.0 which - * accompanies this distribution, is reproduced below, and is - * available at http://www.eclipse.org/org/documents/edl-v10.php - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * - Neither the name of the Eclipse Foundation, Inc. nor the - * names of its contributors may be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package org.eclipse.jgit.lib; - -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.ThreadFactory; - -/** - * Simple work queue to run tasks in the background - */ -class WorkQueue { - private static final ScheduledThreadPoolExecutor executor; - - static final Object executorKiller; - - static { - // To support garbage collection, start our thread but - // swap out the thread factory. When our class is GC'd - // the executorKiller will finalize and ask the executor - // to shutdown, ending the worker. - // - int threads = 1; - executor = new ScheduledThreadPoolExecutor(threads, - new ThreadFactory() { - private final ThreadFactory baseFactory = Executors - .defaultThreadFactory(); - - @Override - public Thread newThread(Runnable taskBody) { - Thread thr = baseFactory.newThread(taskBody); - thr.setName("JGit-WorkQueue"); //$NON-NLS-1$ - thr.setDaemon(true); - return thr; - } - }); - executor.setRemoveOnCancelPolicy(true); - executor.setContinueExistingPeriodicTasksAfterShutdownPolicy(false); - executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); - executor.prestartAllCoreThreads(); - - // Now that the threads are running, its critical to swap out - // our own thread factory for one that isn't in the ClassLoader. - // This allows the class to GC. - // - executor.setThreadFactory(Executors.defaultThreadFactory()); - - executorKiller = new Object() { - @Override - protected void finalize() { - executor.shutdownNow(); - } - }; - } - - static ScheduledThreadPoolExecutor getExecutor() { - return executor; - } -} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/WorkQueue.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/WorkQueue.java new file mode 100644 index 0000000000..3303f47722 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/internal/WorkQueue.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2008-2016, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib.internal; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadFactory; + +/** + * Simple work queue to run tasks in the background + */ +public class WorkQueue { + private static final ScheduledThreadPoolExecutor executor; + + static final Object executorKiller; + + static { + // To support garbage collection, start our thread but + // swap out the thread factory. When our class is GC'd + // the executorKiller will finalize and ask the executor + // to shutdown, ending the worker. + // + int threads = 1; + executor = new ScheduledThreadPoolExecutor(threads, + new ThreadFactory() { + private final ThreadFactory baseFactory = Executors + .defaultThreadFactory(); + + @Override + public Thread newThread(Runnable taskBody) { + Thread thr = baseFactory.newThread(taskBody); + thr.setName("JGit-WorkQueue"); //$NON-NLS-1$ + thr.setDaemon(true); + return thr; + } + }); + executor.setRemoveOnCancelPolicy(true); + executor.setContinueExistingPeriodicTasksAfterShutdownPolicy(false); + executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); + executor.prestartAllCoreThreads(); + + // Now that the threads are running, its critical to swap out + // our own thread factory for one that isn't in the ClassLoader. + // This allows the class to GC. + // + executor.setThreadFactory(Executors.defaultThreadFactory()); + + executorKiller = new Object() { + @Override + protected void finalize() { + executor.shutdownNow(); + } + }; + } + + /** + * @return the WorkQueue's executor + */ + public static ScheduledThreadPoolExecutor getExecutor() { + return executor; + } +} -- cgit v1.2.3