diff options
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse/jgit/storage/dfs/DfsBlockCacheConfig.java')
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/storage/dfs/DfsBlockCacheConfig.java | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/dfs/DfsBlockCacheConfig.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/dfs/DfsBlockCacheConfig.java new file mode 100644 index 0000000000..14c96987c1 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/dfs/DfsBlockCacheConfig.java @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2011, 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.storage.dfs; + +import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_CORE_SECTION; +import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_DFS_SECTION; +import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BLOCK_LIMIT; +import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BLOCK_SIZE; +import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_READ_AHEAD_LIMIT; +import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_READ_AHEAD_THREADS; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import org.eclipse.jgit.lib.Config; + +/** Configuration parameters for {@link DfsBlockCache}. */ +public class DfsBlockCacheConfig { + /** 1024 (number of bytes in one kibibyte/kilobyte) */ + public static final int KB = 1024; + + /** 1024 {@link #KB} (number of bytes in one mebibyte/megabyte) */ + public static final int MB = 1024 * KB; + + private long blockLimit; + + private int blockSize; + + private int readAheadLimit; + + private ThreadPoolExecutor readAheadService; + + /** Create a default configuration. */ + public DfsBlockCacheConfig() { + setBlockLimit(32 * MB); + setBlockSize(64 * KB); + } + + /** + * @return maximum number bytes of heap memory to dedicate to caching pack + * file data. <b>Default is 32 MB.</b> + */ + public long getBlockLimit() { + return blockLimit; + } + + /** + * @param newLimit + * maximum number bytes of heap memory to dedicate to caching + * pack file data. + * @return {@code this} + */ + public DfsBlockCacheConfig setBlockLimit(final long newLimit) { + blockLimit = newLimit; + return this; + } + + /** + * @return size in bytes of a single window mapped or read in from the pack + * file. <b>Default is 64 KB.</b> + */ + public int getBlockSize() { + return blockSize; + } + + /** + * @param newSize + * size in bytes of a single window read in from the pack file. + * @return {@code this} + */ + public DfsBlockCacheConfig setBlockSize(final int newSize) { + blockSize = Math.max(512, newSize); + return this; + } + + /** @return number of bytes to read ahead sequentially by. */ + public int getReadAheadLimit() { + return readAheadLimit; + } + + /** + * @param newSize + * new read-ahead limit, in bytes. + * @return {@code this} + */ + public DfsBlockCacheConfig setReadAheadLimit(final int newSize) { + readAheadLimit = Math.max(0, newSize); + return this; + } + + /** @return service to perform read-ahead of sequential blocks. */ + public ThreadPoolExecutor getReadAheadService() { + return readAheadService; + } + + /** + * @param svc + * service to perform read-ahead of sequential blocks with. If + * not null the {@link RejectedExecutionHandler} must be managed + * by the JGit DFS library and not the application. + * @return {@code this}. + */ + public DfsBlockCacheConfig setReadAheadService(ThreadPoolExecutor svc) { + if (svc != null) + svc.setRejectedExecutionHandler(ReadAheadRejectedExecutionHandler.INSTANCE); + readAheadService = svc; + return this; + } + + /** + * Update properties by setting fields from the configuration. + * <p> + * If a property is not defined in the configuration, then it is left + * unmodified. + * + * @param rc + * configuration to read properties from. + * @return {@code this} + */ + public DfsBlockCacheConfig fromConfig(final Config rc) { + setBlockLimit(rc.getLong( + CONFIG_CORE_SECTION, + CONFIG_DFS_SECTION, + CONFIG_KEY_BLOCK_LIMIT, + getBlockLimit())); + + setBlockSize(rc.getInt( + CONFIG_CORE_SECTION, + CONFIG_DFS_SECTION, + CONFIG_KEY_BLOCK_SIZE, + getBlockSize())); + + setReadAheadLimit(rc.getInt( + CONFIG_CORE_SECTION, + CONFIG_DFS_SECTION, + CONFIG_KEY_READ_AHEAD_LIMIT, + getReadAheadLimit())); + + int readAheadThreads = rc.getInt( + CONFIG_CORE_SECTION, + CONFIG_DFS_SECTION, + CONFIG_KEY_READ_AHEAD_THREADS, + 0); + + if (0 < getReadAheadLimit() && 0 < readAheadThreads) { + setReadAheadService(new ThreadPoolExecutor( + 1, // Minimum number of threads kept alive. + readAheadThreads, // Maximum threads active. + 60, TimeUnit.SECONDS, // Idle threads wait this long before ending. + new ArrayBlockingQueue<Runnable>(1), // Do not queue deeply. + new ThreadFactory() { + private final String name = "JGit-DFS-ReadAhead"; + private final AtomicInteger cnt = new AtomicInteger(); + private final ThreadGroup group = new ThreadGroup(name); + + public Thread newThread(Runnable body) { + int id = cnt.incrementAndGet(); + Thread thread = new Thread(group, body, name + "-" + id); + thread.setDaemon(true); + thread.setContextClassLoader(getClass().getClassLoader()); + return thread; + } + }, ReadAheadRejectedExecutionHandler.INSTANCE)); + } + return this; + } +} |