blob: 6aa8be642d9e2c1f6fb227004e7d6c1143a3ffc5 [file] [log] [blame]
/*
* Copyright (C) 2008-2010, Google Inc.
* Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com> and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
* https://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
package org.eclipse.jgit.storage.pack;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_CORE_SECTION;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BIGFILE_THRESHOLD;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BITMAP_CONTIGUOUS_COMMIT_COUNT;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BITMAP_DISTANT_COMMIT_SPAN;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BITMAP_EXCESSIVE_BRANCH_COUNT;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BITMAP_INACTIVE_BRANCH_AGE_INDAYS;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BITMAP_RECENT_COMMIT_COUNT;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BUILD_BITMAPS;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_COMPRESSION;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CUT_DELTACHAINS;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_DELTA_CACHE_LIMIT;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_DELTA_CACHE_SIZE;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_DELTA_COMPRESSION;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_DEPTH;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_INDEXVERSION;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_MIN_SIZE_PREVENT_RACYPACK;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_REUSE_DELTAS;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_REUSE_OBJECTS;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_SEARCH_FOR_REUSE_TIMEOUT;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_SINGLE_PACK;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_THREADS;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_WAIT_PREVENT_RACYPACK;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_WINDOW;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_WINDOW_MEMORY;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_PACK_SECTION;
import java.time.Duration;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.zip.Deflater;
import org.eclipse.jgit.internal.storage.file.PackIndexWriter;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Repository;
/**
* Configuration used by a pack writer when constructing the stream.
*
* A configuration may be modified once created, but should not be modified
* while it is being used by a PackWriter. If a configuration is not modified it
* is safe to share the same configuration instance between multiple concurrent
* threads executing different PackWriters.
*/
public class PackConfig {
/**
* Default value of deltas reuse option: {@value}
*
* @see #setReuseDeltas(boolean)
*/
public static final boolean DEFAULT_REUSE_DELTAS = true;
/**
* Default value of objects reuse option: {@value}
*
* @see #setReuseObjects(boolean)
*/
public static final boolean DEFAULT_REUSE_OBJECTS = true;
/**
* Default value of keep old packs option: {@value}
* @see #setPreserveOldPacks(boolean)
* @since 4.7
*/
public static final boolean DEFAULT_PRESERVE_OLD_PACKS = false;
/**
* Default value of prune old packs option: {@value}
* @see #setPrunePreserved(boolean)
* @since 4.7
*/
public static final boolean DEFAULT_PRUNE_PRESERVED = false;
/**
* Default value of delta compress option: {@value}
*
* @see #setDeltaCompress(boolean)
*/
public static final boolean DEFAULT_DELTA_COMPRESS = true;
/**
* Default value of delta base as offset option: {@value}
*
* @see #setDeltaBaseAsOffset(boolean)
*/
public static final boolean DEFAULT_DELTA_BASE_AS_OFFSET = false;
/**
* Default value of maximum delta chain depth: {@value}
*
* @see #setMaxDeltaDepth(int)
*/
public static final int DEFAULT_MAX_DELTA_DEPTH = 50;
/**
* Default window size during packing: {@value}
*
* @see #setDeltaSearchWindowSize(int)
*/
public static final int DEFAULT_DELTA_SEARCH_WINDOW_SIZE = 10;
private static final int MB = 1 << 20;
/**
* Default big file threshold: {@value}
*
* @see #setBigFileThreshold(int)
*/
public static final int DEFAULT_BIG_FILE_THRESHOLD = 50 * MB;
/**
* Default if we wait before opening a newly written pack to prevent its
* lastModified timestamp could be racy
*
* @since 5.1.8
*/
public static final boolean DEFAULT_WAIT_PREVENT_RACY_PACK = false;
/**
* Default if we wait before opening a newly written pack to prevent its
* lastModified timestamp could be racy
*
* @since 5.1.8
*/
public static final long DEFAULT_MINSIZE_PREVENT_RACY_PACK = 100 * MB;
/**
* Default delta cache size: {@value}
*
* @see #setDeltaCacheSize(long)
*/
public static final long DEFAULT_DELTA_CACHE_SIZE = 50 * 1024 * 1024;
/**
* Default delta cache limit: {@value}
*
* @see #setDeltaCacheLimit(int)
*/
public static final int DEFAULT_DELTA_CACHE_LIMIT = 100;
/**
* Default index version: {@value}
*
* @see #setIndexVersion(int)
*/
public static final int DEFAULT_INDEX_VERSION = 2;
/**
* Default value of the build bitmaps option: {@value}
*
* @see #setBuildBitmaps(boolean)
* @since 3.0
*/
public static final boolean DEFAULT_BUILD_BITMAPS = true;
/**
* Default count of most recent commits to select for bitmaps. Only applies
* when bitmaps are enabled: {@value}
*
* @see #setBitmapContiguousCommitCount(int)
* @since 4.2
*/
public static final int DEFAULT_BITMAP_CONTIGUOUS_COMMIT_COUNT = 100;
/**
* Count at which the span between selected commits changes from
* "bitmapRecentCommitSpan" to "bitmapDistantCommitSpan". Only applies when
* bitmaps are enabled: {@value}
*
* @see #setBitmapRecentCommitCount(int)
* @since 4.2
*/
public static final int DEFAULT_BITMAP_RECENT_COMMIT_COUNT = 20000;
/**
* Default spacing between commits in recent history when selecting commits
* for bitmaps. Only applies when bitmaps are enabled: {@value}
*
* @see #setBitmapRecentCommitSpan(int)
* @since 4.2
*/
public static final int DEFAULT_BITMAP_RECENT_COMMIT_SPAN = 100;
/**
* Default spacing between commits in distant history when selecting commits
* for bitmaps. Only applies when bitmaps are enabled: {@value}
*
* @see #setBitmapDistantCommitSpan(int)
* @since 4.2
*/
public static final int DEFAULT_BITMAP_DISTANT_COMMIT_SPAN = 5000;
/**
* Default count of branches required to activate inactive branch commit
* selection. If the number of branches is less than this then bitmaps for
* the entire commit history of all branches will be created, otherwise
* branches marked as "inactive" will have coverage for only partial
* history: {@value}
*
* @see #setBitmapExcessiveBranchCount(int)
* @since 4.2
*/
public static final int DEFAULT_BITMAP_EXCESSIVE_BRANCH_COUNT = 100;
/**
* Default age at which a branch is considered inactive. Age is taken as the
* number of days ago that the most recent commit was made to a branch. Only
* affects bitmap processing if bitmaps are enabled and the
* "excessive branch count" has been exceeded: {@value}
*
* @see #setBitmapInactiveBranchAgeInDays(int)
* @since 4.2
*/
public static final int DEFAULT_BITMAP_INACTIVE_BRANCH_AGE_IN_DAYS = 90;
/**
* Default max time to spend during the search for reuse phase. This
* optimization is disabled by default: {@value}
*
* @see #setSearchForReuseTimeout(Duration)
* @since 5.13
*/
public static final Duration DEFAULT_SEARCH_FOR_REUSE_TIMEOUT = Duration
.ofSeconds(Integer.MAX_VALUE);
private int compressionLevel = Deflater.DEFAULT_COMPRESSION;
private boolean reuseDeltas = DEFAULT_REUSE_DELTAS;
private boolean reuseObjects = DEFAULT_REUSE_OBJECTS;
private boolean preserveOldPacks = DEFAULT_PRESERVE_OLD_PACKS;
private boolean prunePreserved = DEFAULT_PRUNE_PRESERVED;
private boolean deltaBaseAsOffset = DEFAULT_DELTA_BASE_AS_OFFSET;
private boolean deltaCompress = DEFAULT_DELTA_COMPRESS;
private int maxDeltaDepth = DEFAULT_MAX_DELTA_DEPTH;
private int deltaSearchWindowSize = DEFAULT_DELTA_SEARCH_WINDOW_SIZE;
private long deltaSearchMemoryLimit;
private long deltaCacheSize = DEFAULT_DELTA_CACHE_SIZE;
private int deltaCacheLimit = DEFAULT_DELTA_CACHE_LIMIT;
private int bigFileThreshold = DEFAULT_BIG_FILE_THRESHOLD;
private boolean waitPreventRacyPack = DEFAULT_WAIT_PREVENT_RACY_PACK;
private long minSizePreventRacyPack = DEFAULT_MINSIZE_PREVENT_RACY_PACK;
private int threads;
private Executor executor;
private int indexVersion = DEFAULT_INDEX_VERSION;
private boolean buildBitmaps = DEFAULT_BUILD_BITMAPS;
private int bitmapContiguousCommitCount = DEFAULT_BITMAP_CONTIGUOUS_COMMIT_COUNT;
private int bitmapRecentCommitCount = DEFAULT_BITMAP_RECENT_COMMIT_COUNT;
private int bitmapRecentCommitSpan = DEFAULT_BITMAP_RECENT_COMMIT_SPAN;
private int bitmapDistantCommitSpan = DEFAULT_BITMAP_DISTANT_COMMIT_SPAN;
private int bitmapExcessiveBranchCount = DEFAULT_BITMAP_EXCESSIVE_BRANCH_COUNT;
private int bitmapInactiveBranchAgeInDays = DEFAULT_BITMAP_INACTIVE_BRANCH_AGE_IN_DAYS;
private Duration searchForReuseTimeout = DEFAULT_SEARCH_FOR_REUSE_TIMEOUT;
private boolean cutDeltaChains;
private boolean singlePack;
/**
* Create a default configuration.
*/
public PackConfig() {
// Fields are initialized to defaults.
}
/**
* Create a configuration honoring the repository's settings.
*
* @param db
* the repository to read settings from. The repository is not
* retained by the new configuration, instead its settings are
* copied during the constructor.
*/
public PackConfig(Repository db) {
fromConfig(db.getConfig());
}
/**
* Create a configuration honoring settings in a
* {@link org.eclipse.jgit.lib.Config}.
*
* @param cfg
* the source to read settings from. The source is not retained
* by the new configuration, instead its settings are copied
* during the constructor.
*/
public PackConfig(Config cfg) {
fromConfig(cfg);
}
/**
* Copy an existing configuration to a new instance.
*
* @param cfg
* the source configuration to copy from.
*/
public PackConfig(PackConfig cfg) {
this.compressionLevel = cfg.compressionLevel;
this.reuseDeltas = cfg.reuseDeltas;
this.reuseObjects = cfg.reuseObjects;
this.preserveOldPacks = cfg.preserveOldPacks;
this.prunePreserved = cfg.prunePreserved;
this.deltaBaseAsOffset = cfg.deltaBaseAsOffset;
this.deltaCompress = cfg.deltaCompress;
this.maxDeltaDepth = cfg.maxDeltaDepth;
this.deltaSearchWindowSize = cfg.deltaSearchWindowSize;
this.deltaSearchMemoryLimit = cfg.deltaSearchMemoryLimit;
this.deltaCacheSize = cfg.deltaCacheSize;
this.deltaCacheLimit = cfg.deltaCacheLimit;
this.bigFileThreshold = cfg.bigFileThreshold;
this.waitPreventRacyPack = cfg.waitPreventRacyPack;
this.minSizePreventRacyPack = cfg.minSizePreventRacyPack;
this.threads = cfg.threads;
this.executor = cfg.executor;
this.indexVersion = cfg.indexVersion;
this.buildBitmaps = cfg.buildBitmaps;
this.bitmapContiguousCommitCount = cfg.bitmapContiguousCommitCount;
this.bitmapRecentCommitCount = cfg.bitmapRecentCommitCount;
this.bitmapRecentCommitSpan = cfg.bitmapRecentCommitSpan;
this.bitmapDistantCommitSpan = cfg.bitmapDistantCommitSpan;
this.bitmapExcessiveBranchCount = cfg.bitmapExcessiveBranchCount;
this.bitmapInactiveBranchAgeInDays = cfg.bitmapInactiveBranchAgeInDays;
this.cutDeltaChains = cfg.cutDeltaChains;
this.singlePack = cfg.singlePack;
this.searchForReuseTimeout = cfg.searchForReuseTimeout;
}
/**
* Check whether to reuse deltas existing in repository.
*
* Default setting: {@value #DEFAULT_REUSE_DELTAS}
*
* @return true if object is configured to reuse deltas; false otherwise.
*/
public boolean isReuseDeltas() {
return reuseDeltas;
}
/**
* Set reuse deltas configuration option for the writer.
*
* When enabled, writer will search for delta representation of object in
* repository and use it if possible. Normally, only deltas with base to
* another object existing in set of objects to pack will be used. The
* exception however is thin-packs where the base object may exist on the
* other side.
*
* When raw delta data is directly copied from a pack file, its checksum is
* computed to verify the data is not corrupt.
*
* Default setting: {@value #DEFAULT_REUSE_DELTAS}
*
* @param reuseDeltas
* boolean indicating whether or not try to reuse deltas.
*/
public void setReuseDeltas(boolean reuseDeltas) {
this.reuseDeltas = reuseDeltas;
}
/**
* Checks whether to reuse existing objects representation in repository.
*
* Default setting: {@value #DEFAULT_REUSE_OBJECTS}
*
* @return true if writer is configured to reuse objects representation from
* pack; false otherwise.
*/
public boolean isReuseObjects() {
return reuseObjects;
}
/**
* Set reuse objects configuration option for the writer.
*
* If enabled, writer searches for compressed representation in a pack file.
* If possible, compressed data is directly copied from such a pack file.
* Data checksum is verified.
*
* Default setting: {@value #DEFAULT_REUSE_OBJECTS}
*
* @param reuseObjects
* boolean indicating whether or not writer should reuse existing
* objects representation.
*/
public void setReuseObjects(boolean reuseObjects) {
this.reuseObjects = reuseObjects;
}
/**
* Checks whether to preserve old packs in a preserved directory
*
* Default setting: {@value #DEFAULT_PRESERVE_OLD_PACKS}
*
* @return true if repacking will preserve old pack files.
* @since 4.7
*/
public boolean isPreserveOldPacks() {
return preserveOldPacks;
}
/**
* Set preserve old packs configuration option for repacking.
*
* If enabled, old pack files are moved into a preserved subdirectory instead
* of being deleted
*
* Default setting: {@value #DEFAULT_PRESERVE_OLD_PACKS}
*
* @param preserveOldPacks
* boolean indicating whether or not preserve old pack files
* @since 4.7
*/
public void setPreserveOldPacks(boolean preserveOldPacks) {
this.preserveOldPacks = preserveOldPacks;
}
/**
* Checks whether to remove preserved pack files in a preserved directory
*
* Default setting: {@value #DEFAULT_PRUNE_PRESERVED}
*
* @return true if repacking will remove preserved pack files.
* @since 4.7
*/
public boolean isPrunePreserved() {
return prunePreserved;
}
/**
* Set prune preserved configuration option for repacking.
*
* If enabled, preserved pack files are removed from a preserved subdirectory
*
* Default setting: {@value #DEFAULT_PRESERVE_OLD_PACKS}
*
* @param prunePreserved
* boolean indicating whether or not preserve old pack files
* @since 4.7
*/
public void setPrunePreserved(boolean prunePreserved) {
this.prunePreserved = prunePreserved;
}
/**
* True if writer can use offsets to point to a delta base.
*
* If true the writer may choose to use an offset to point to a delta base
* in the same pack, this is a newer style of reference that saves space.
* False if the writer has to use the older (and more compatible style) of
* storing the full ObjectId of the delta base.
*
* Default setting: {@value #DEFAULT_DELTA_BASE_AS_OFFSET}
*
* @return true if delta base is stored as an offset; false if it is stored
* as an ObjectId.
*/
public boolean isDeltaBaseAsOffset() {
return deltaBaseAsOffset;
}
/**
* Set writer delta base format.
*
* Delta base can be written as an offset in a pack file (new approach
* reducing file size) or as an object id (legacy approach, compatible with
* old readers).
*
* Default setting: {@value #DEFAULT_DELTA_BASE_AS_OFFSET}
*
* @param deltaBaseAsOffset
* boolean indicating whether delta base can be stored as an
* offset.
*/
public void setDeltaBaseAsOffset(boolean deltaBaseAsOffset) {
this.deltaBaseAsOffset = deltaBaseAsOffset;
}
/**
* Check whether the writer will create new deltas on the fly.
*
* Default setting: {@value #DEFAULT_DELTA_COMPRESS}
*
* @return true if the writer will create a new delta when either
* {@link #isReuseDeltas()} is false, or no suitable delta is
* available for reuse.
*/
public boolean isDeltaCompress() {
return deltaCompress;
}
/**
* Set whether or not the writer will create new deltas on the fly.
*
* Default setting: {@value #DEFAULT_DELTA_COMPRESS}
*
* @param deltaCompress
* true to create deltas when {@link #isReuseDeltas()} is false,
* or when a suitable delta isn't available for reuse. Set to
* false to write whole objects instead.
*/
public void setDeltaCompress(boolean deltaCompress) {
this.deltaCompress = deltaCompress;
}
/**
* Get maximum depth of delta chain set up for the writer.
*
* Generated chains are not longer than this value.
*
* Default setting: {@value #DEFAULT_MAX_DELTA_DEPTH}
*
* @return maximum delta chain depth.
*/
public int getMaxDeltaDepth() {
return maxDeltaDepth;
}
/**
* Set up maximum depth of delta chain for the writer.
*
* Generated chains are not longer than this value. Too low value causes low
* compression level, while too big makes unpacking (reading) longer.
*
* Default setting: {@value #DEFAULT_MAX_DELTA_DEPTH}
*
* @param maxDeltaDepth
* maximum delta chain depth.
*/
public void setMaxDeltaDepth(int maxDeltaDepth) {
this.maxDeltaDepth = maxDeltaDepth;
}
/**
* Whether existing delta chains should be cut at
* {@link #getMaxDeltaDepth()}.
*
* @return true if existing delta chains should be cut at
* {@link #getMaxDeltaDepth()}. Default is false, allowing existing
* chains to be of any length.
* @since 3.0
*/
public boolean getCutDeltaChains() {
return cutDeltaChains;
}
/**
* Enable cutting existing delta chains at {@link #getMaxDeltaDepth()}.
*
* By default this is disabled and existing chains are kept at whatever
* length a prior packer was configured to create. This allows objects to be
* packed one with a large depth (for example 250), and later to quickly
* repack the repository with a shorter depth (such as 50), but reusing the
* complete delta chains created by the earlier 250 depth.
*
* @param cut
* true to cut existing chains.
* @since 3.0
*/
public void setCutDeltaChains(boolean cut) {
cutDeltaChains = cut;
}
/**
* Whether all of refs/* should be packed in a single pack.
*
* @return true if all of refs/* should be packed in a single pack. Default
* is false, packing a separate GC_REST pack for references outside
* of refs/heads/* and refs/tags/*.
* @since 4.9
*/
public boolean getSinglePack() {
return singlePack;
}
/**
* If {@code true}, packs a single GC pack for all objects reachable from
* refs/*. Otherwise packs the GC pack with objects reachable from
* refs/heads/* and refs/tags/*, and a GC_REST pack with the remaining
* reachable objects. Disabled by default, packing GC and GC_REST.
*
* @param single
* true to pack a single GC pack rather than GC and GC_REST packs
* @since 4.9
*/
public void setSinglePack(boolean single) {
singlePack = single;
}
/**
* Get the number of objects to try when looking for a delta base.
*
* This limit is per thread, if 4 threads are used the actual memory used
* will be 4 times this value.
*
* Default setting: {@value #DEFAULT_DELTA_SEARCH_WINDOW_SIZE}
*
* @return the object count to be searched.
*/
public int getDeltaSearchWindowSize() {
return deltaSearchWindowSize;
}
/**
* Set the number of objects considered when searching for a delta base.
*
* Default setting: {@value #DEFAULT_DELTA_SEARCH_WINDOW_SIZE}
*
* @param objectCount
* number of objects to search at once. Must be at least 2.
*/
public void setDeltaSearchWindowSize(int objectCount) {
if (objectCount <= 2)
setDeltaCompress(false);
else
deltaSearchWindowSize = objectCount;
}
/**
* Get maximum number of bytes to put into the delta search window.
*
* Default setting is 0, for an unlimited amount of memory usage. Actual
* memory used is the lower limit of either this setting, or the sum of
* space used by at most {@link #getDeltaSearchWindowSize()} objects.
*
* This limit is per thread, if 4 threads are used the actual memory limit
* will be 4 times this value.
*
* @return the memory limit.
*/
public long getDeltaSearchMemoryLimit() {
return deltaSearchMemoryLimit;
}
/**
* Set the maximum number of bytes to put into the delta search window.
*
* Default setting is 0, for an unlimited amount of memory usage. If the
* memory limit is reached before {@link #getDeltaSearchWindowSize()} the
* window size is temporarily lowered.
*
* @param memoryLimit
* Maximum number of bytes to load at once, 0 for unlimited.
*/
public void setDeltaSearchMemoryLimit(long memoryLimit) {
deltaSearchMemoryLimit = memoryLimit;
}
/**
* Get the size of the in-memory delta cache.
*
* This limit is for the entire writer, even if multiple threads are used.
*
* Default setting: {@value #DEFAULT_DELTA_CACHE_SIZE}
*
* @return maximum number of bytes worth of delta data to cache in memory.
* If 0 the cache is infinite in size (up to the JVM heap limit
* anyway). A very tiny size such as 1 indicates the cache is
* effectively disabled.
*/
public long getDeltaCacheSize() {
return deltaCacheSize;
}
/**
* Set the maximum number of bytes of delta data to cache.
*
* During delta search, up to this many bytes worth of small or hard to
* compute deltas will be stored in memory. This cache speeds up writing by
* allowing the cached entry to simply be dumped to the output stream.
*
* Default setting: {@value #DEFAULT_DELTA_CACHE_SIZE}
*
* @param size
* number of bytes to cache. Set to 0 to enable an infinite
* cache, set to 1 (an impossible size for any delta) to disable
* the cache.
*/
public void setDeltaCacheSize(long size) {
deltaCacheSize = size;
}
/**
* Maximum size in bytes of a delta to cache.
*
* Default setting: {@value #DEFAULT_DELTA_CACHE_LIMIT}
*
* @return maximum size (in bytes) of a delta that should be cached.
*/
public int getDeltaCacheLimit() {
return deltaCacheLimit;
}
/**
* Set the maximum size of a delta that should be cached.
*
* During delta search, any delta smaller than this size will be cached, up
* to the {@link #getDeltaCacheSize()} maximum limit. This speeds up writing
* by allowing these cached deltas to be output as-is.
*
* Default setting: {@value #DEFAULT_DELTA_CACHE_LIMIT}
*
* @param size
* maximum size (in bytes) of a delta to be cached.
*/
public void setDeltaCacheLimit(int size) {
deltaCacheLimit = size;
}
/**
* Get the maximum file size that will be delta compressed.
*
* Files bigger than this setting will not be delta compressed, as they are
* more than likely already highly compressed binary data files that do not
* delta compress well, such as MPEG videos.
*
* Default setting: {@value #DEFAULT_BIG_FILE_THRESHOLD}
*
* @return the configured big file threshold.
*/
public int getBigFileThreshold() {
return bigFileThreshold;
}
/**
* Set the maximum file size that should be considered for deltas.
*
* Default setting: {@value #DEFAULT_BIG_FILE_THRESHOLD}
*
* @param bigFileThreshold
* the limit, in bytes.
*/
public void setBigFileThreshold(int bigFileThreshold) {
this.bigFileThreshold = bigFileThreshold;
}
/**
* Get whether we wait before opening a newly written pack to prevent its
* lastModified timestamp could be racy
*
* @return whether we wait before opening a newly written pack to prevent
* its lastModified timestamp could be racy
* @since 5.1.8
*/
public boolean isWaitPreventRacyPack() {
return waitPreventRacyPack;
}
/**
* Get whether we wait before opening a newly written pack to prevent its
* lastModified timestamp could be racy. Returns {@code true} if
* {@code waitToPreventRacyPack = true} and
* {@code packSize > minSizePreventRacyPack}, {@code false} otherwise.
*
* @param packSize
* size of the pack file
*
* @return whether we wait before opening a newly written pack to prevent
* its lastModified timestamp could be racy
* @since 5.1.8
*/
public boolean doWaitPreventRacyPack(long packSize) {
return isWaitPreventRacyPack()
&& packSize > getMinSizePreventRacyPack();
}
/**
* Set whether we wait before opening a newly written pack to prevent its
* lastModified timestamp could be racy
*
* @param waitPreventRacyPack
* whether we wait before opening a newly written pack to prevent
* its lastModified timestamp could be racy
* @since 5.1.8
*/
public void setWaitPreventRacyPack(boolean waitPreventRacyPack) {
this.waitPreventRacyPack = waitPreventRacyPack;
}
/**
* Get minimum packfile size for which we wait before opening a newly
* written pack to prevent its lastModified timestamp could be racy if
* {@code isWaitToPreventRacyPack} is {@code true}.
*
* @return minimum packfile size, default is 100 MiB
*
* @since 5.1.8
*/
public long getMinSizePreventRacyPack() {
return minSizePreventRacyPack;
}
/**
* Set minimum packfile size for which we wait before opening a newly
* written pack to prevent its lastModified timestamp could be racy if
* {@code isWaitToPreventRacyPack} is {@code true}.
*
* @param minSizePreventRacyPack
* minimum packfile size, default is 100 MiB
*
* @since 5.1.8
*/
public void setMinSizePreventRacyPack(long minSizePreventRacyPack) {
this.minSizePreventRacyPack = minSizePreventRacyPack;
}
/**
* Get the compression level applied to objects in the pack.
*
* Default setting: {@value java.util.zip.Deflater#DEFAULT_COMPRESSION}
*
* @return current compression level, see {@link java.util.zip.Deflater}.
*/
public int getCompressionLevel() {
return compressionLevel;
}
/**
* Set the compression level applied to objects in the pack.
*
* Default setting: {@value java.util.zip.Deflater#DEFAULT_COMPRESSION}
*
* @param level
* compression level, must be a valid level recognized by the
* {@link java.util.zip.Deflater} class.
*/
public void setCompressionLevel(int level) {
compressionLevel = level;
}
/**
* Get the number of threads used during delta compression.
*
* Default setting: 0 (auto-detect processors)
*
* @return number of threads used for delta compression. 0 will auto-detect
* the threads to the number of available processors.
*/
public int getThreads() {
return threads;
}
/**
* Set the number of threads to use for delta compression.
*
* During delta compression, if there are enough objects to be considered
* the writer will start up concurrent threads and allow them to compress
* different sections of the repository concurrently.
*
* An application thread pool can be set by {@link #setExecutor(Executor)}.
* If not set a temporary pool will be created by the writer, and torn down
* automatically when compression is over.
*
* Default setting: 0 (auto-detect processors)
*
* @param threads
* number of threads to use. If &lt;= 0 the number of available
* processors for this JVM is used.
*/
public void setThreads(int threads) {
this.threads = threads;
}
/**
* Get the preferred thread pool to execute delta search on.
*
* @return the preferred thread pool to execute delta search on.
*/
public Executor getExecutor() {
return executor;
}
/**
* Set the executor to use when using threads.
*
* During delta compression if the executor is non-null jobs will be queued
* up on it to perform delta compression in parallel. Aside from setting the
* executor, the caller must set {@link #setThreads(int)} to enable threaded
* delta search.
*
* @param executor
* executor to use for threads. Set to null to create a temporary
* executor just for the writer.
*/
public void setExecutor(Executor executor) {
this.executor = executor;
}
/**
* Get the pack index file format version this instance creates.
*
* Default setting: {@value #DEFAULT_INDEX_VERSION}
*
* @return the index version, the special version 0 designates the oldest
* (most compatible) format available for the objects.
* @see PackIndexWriter
*/
public int getIndexVersion() {
return indexVersion;
}
/**
* Set the pack index file format version this instance will create.
*
* Default setting: {@value #DEFAULT_INDEX_VERSION}
*
* @param version
* the version to write. The special version 0 designates the
* oldest (most compatible) format available for the objects.
* @see PackIndexWriter
*/
public void setIndexVersion(int version) {
indexVersion = version;
}
/**
* True if writer is allowed to build bitmaps for indexes.
*
* Default setting: {@value #DEFAULT_BUILD_BITMAPS}
*
* @return true if delta base is the writer can choose to output an index
* with bitmaps.
* @since 3.0
*/
public boolean isBuildBitmaps() {
return buildBitmaps;
}
/**
* Set writer to allow building bitmaps for supported pack files.
*
* Index files can include bitmaps to speed up future ObjectWalks.
*
* Default setting: {@value #DEFAULT_BUILD_BITMAPS}
*
* @param buildBitmaps
* boolean indicating whether bitmaps may be included in the
* index.
* @since 3.0
*/
public void setBuildBitmaps(boolean buildBitmaps) {
this.buildBitmaps = buildBitmaps;
}
/**
* Get the count of most recent commits for which to build bitmaps.
*
* Default setting: {@value #DEFAULT_BITMAP_CONTIGUOUS_COMMIT_COUNT}
*
* @return the count of most recent commits for which to build bitmaps
* @since 4.2
*/
public int getBitmapContiguousCommitCount() {
return bitmapContiguousCommitCount;
}
/**
* Set the count of most recent commits for which to build bitmaps.
*
* Default setting: {@value #DEFAULT_BITMAP_CONTIGUOUS_COMMIT_COUNT}
*
* @param count
* the count of most recent commits for which to build bitmaps
* @since 4.2
*/
public void setBitmapContiguousCommitCount(int count) {
bitmapContiguousCommitCount = count;
}
/**
* Get the count at which to switch from "bitmapRecentCommitSpan" to
* "bitmapDistantCommitSpan".
*
* Default setting: {@value #DEFAULT_BITMAP_RECENT_COMMIT_COUNT}
*
* @return the count for switching between recent and distant spans
* @since 4.2
*/
public int getBitmapRecentCommitCount() {
return bitmapRecentCommitCount;
}
/**
* Set the count at which to switch from "bitmapRecentCommitSpan" to
* "bitmapDistantCommitSpan".
*
* Default setting: {@value #DEFAULT_BITMAP_RECENT_COMMIT_COUNT}
*
* @param count
* the count for switching between recent and distant spans
* @since 4.2
*/
public void setBitmapRecentCommitCount(int count) {
bitmapRecentCommitCount = count;
}
/**
* Get the span of commits when building bitmaps for recent history.
*
* Default setting: {@value #DEFAULT_BITMAP_RECENT_COMMIT_SPAN}
*
* @return the span of commits when building bitmaps for recent history
* @since 4.2
*/
public int getBitmapRecentCommitSpan() {
return bitmapRecentCommitSpan;
}
/**
* Set the span of commits when building bitmaps for recent history.
*
* Default setting: {@value #DEFAULT_BITMAP_RECENT_COMMIT_SPAN}
*
* @param span
* the span of commits when building bitmaps for recent history
* @since 4.2
*/
public void setBitmapRecentCommitSpan(int span) {
bitmapRecentCommitSpan = span;
}
/**
* Get the span of commits when building bitmaps for distant history.
*
* Default setting: {@value #DEFAULT_BITMAP_DISTANT_COMMIT_SPAN}
*
* @return the span of commits when building bitmaps for distant history
* @since 4.2
*/
public int getBitmapDistantCommitSpan() {
return bitmapDistantCommitSpan;
}
/**
* Set the span of commits when building bitmaps for distant history.
*
* Default setting: {@value #DEFAULT_BITMAP_DISTANT_COMMIT_SPAN}
*
* @param span
* the span of commits when building bitmaps for distant history
* @since 4.2
*/
public void setBitmapDistantCommitSpan(int span) {
bitmapDistantCommitSpan = span;
}
/**
* Get the count of branches deemed "excessive". If the count of branches in
* a repository exceeds this number and bitmaps are enabled, "inactive"
* branches will have fewer bitmaps than "active" branches.
*
* Default setting: {@value #DEFAULT_BITMAP_EXCESSIVE_BRANCH_COUNT}
*
* @return the count of branches deemed "excessive"
* @since 4.2
*/
public int getBitmapExcessiveBranchCount() {
return bitmapExcessiveBranchCount;
}
/**
* Set the count of branches deemed "excessive". If the count of branches in
* a repository exceeds this number and bitmaps are enabled, "inactive"
* branches will have fewer bitmaps than "active" branches.
*
* Default setting: {@value #DEFAULT_BITMAP_EXCESSIVE_BRANCH_COUNT}
*
* @param count
* the count of branches deemed "excessive"
* @since 4.2
*/
public void setBitmapExcessiveBranchCount(int count) {
bitmapExcessiveBranchCount = count;
}
/**
* Get the age in days that marks a branch as "inactive".
*
* Default setting: {@value #DEFAULT_BITMAP_INACTIVE_BRANCH_AGE_IN_DAYS}
*
* @return the age in days that marks a branch as "inactive"
* @since 4.2
*/
public int getBitmapInactiveBranchAgeInDays() {
return bitmapInactiveBranchAgeInDays;
}
/**
* Get the max time to spend during the search for reuse phase.
*
* Default setting: {@value #DEFAULT_SEARCH_FOR_REUSE_TIMEOUT}
*
* @return the maximum time to spend during the search for reuse phase.
* @since 5.13
*/
public Duration getSearchForReuseTimeout() {
return searchForReuseTimeout;
}
/**
* Set the age in days that marks a branch as "inactive".
*
* Default setting: {@value #DEFAULT_BITMAP_INACTIVE_BRANCH_AGE_IN_DAYS}
*
* @param ageInDays
* the age in days that marks a branch as "inactive"
* @since 4.2
*/
public void setBitmapInactiveBranchAgeInDays(int ageInDays) {
bitmapInactiveBranchAgeInDays = ageInDays;
}
/**
* Set the max time to spend during the search for reuse phase.
*
* @param timeout
* max time allowed during the search for reuse phase
*
* Default setting: {@value #DEFAULT_SEARCH_FOR_REUSE_TIMEOUT}
* @since 5.13
*/
public void setSearchForReuseTimeout(Duration timeout) {
searchForReuseTimeout = timeout;
}
/**
* Update properties by setting fields from the configuration.
*
* If a property's corresponding variable is not defined in the supplied
* configuration, then it is left unmodified.
*
* @param rc
* configuration to read properties from.
*/
public void fromConfig(Config rc) {
setMaxDeltaDepth(rc.getInt(CONFIG_PACK_SECTION, CONFIG_KEY_DEPTH,
getMaxDeltaDepth()));
setDeltaSearchWindowSize(rc.getInt(CONFIG_PACK_SECTION,
CONFIG_KEY_WINDOW, getDeltaSearchWindowSize()));
setDeltaSearchMemoryLimit(rc.getLong(CONFIG_PACK_SECTION,
CONFIG_KEY_WINDOW_MEMORY, getDeltaSearchMemoryLimit()));
setDeltaCacheSize(rc.getLong(CONFIG_PACK_SECTION,
CONFIG_KEY_DELTA_CACHE_SIZE, getDeltaCacheSize()));
setDeltaCacheLimit(rc.getInt(CONFIG_PACK_SECTION,
CONFIG_KEY_DELTA_CACHE_LIMIT, getDeltaCacheLimit()));
setCompressionLevel(rc.getInt(CONFIG_PACK_SECTION,
CONFIG_KEY_COMPRESSION, rc.getInt(CONFIG_CORE_SECTION,
CONFIG_KEY_COMPRESSION, getCompressionLevel())));
setIndexVersion(rc.getInt(CONFIG_PACK_SECTION,
CONFIG_KEY_INDEXVERSION,
getIndexVersion()));
setBigFileThreshold(rc.getInt(CONFIG_CORE_SECTION,
CONFIG_KEY_BIGFILE_THRESHOLD, getBigFileThreshold()));
setThreads(rc.getInt(CONFIG_PACK_SECTION, CONFIG_KEY_THREADS,
getThreads()));
// These variables aren't standardized
setReuseDeltas(rc.getBoolean(CONFIG_PACK_SECTION,
CONFIG_KEY_REUSE_DELTAS, isReuseDeltas()));
setReuseObjects(rc.getBoolean(CONFIG_PACK_SECTION,
CONFIG_KEY_REUSE_OBJECTS, isReuseObjects()));
setDeltaCompress(rc.getBoolean(CONFIG_PACK_SECTION,
CONFIG_KEY_DELTA_COMPRESSION, isDeltaCompress()));
setCutDeltaChains(rc.getBoolean(CONFIG_PACK_SECTION,
CONFIG_KEY_CUT_DELTACHAINS, getCutDeltaChains()));
setSinglePack(rc.getBoolean(CONFIG_PACK_SECTION,
CONFIG_KEY_SINGLE_PACK,
getSinglePack()));
setBuildBitmaps(rc.getBoolean(CONFIG_PACK_SECTION,
CONFIG_KEY_BUILD_BITMAPS, isBuildBitmaps()));
setBitmapContiguousCommitCount(rc.getInt(CONFIG_PACK_SECTION,
CONFIG_KEY_BITMAP_CONTIGUOUS_COMMIT_COUNT,
getBitmapContiguousCommitCount()));
setBitmapRecentCommitCount(rc.getInt(CONFIG_PACK_SECTION,
CONFIG_KEY_BITMAP_RECENT_COMMIT_COUNT,
getBitmapRecentCommitCount()));
setBitmapRecentCommitSpan(rc.getInt(CONFIG_PACK_SECTION,
CONFIG_KEY_BITMAP_RECENT_COMMIT_COUNT,
getBitmapRecentCommitSpan()));
setBitmapDistantCommitSpan(rc.getInt(CONFIG_PACK_SECTION,
CONFIG_KEY_BITMAP_DISTANT_COMMIT_SPAN,
getBitmapDistantCommitSpan()));
setBitmapExcessiveBranchCount(rc.getInt(CONFIG_PACK_SECTION,
CONFIG_KEY_BITMAP_EXCESSIVE_BRANCH_COUNT,
getBitmapExcessiveBranchCount()));
setBitmapInactiveBranchAgeInDays(rc.getInt(CONFIG_PACK_SECTION,
CONFIG_KEY_BITMAP_INACTIVE_BRANCH_AGE_INDAYS,
getBitmapInactiveBranchAgeInDays()));
setSearchForReuseTimeout(Duration.ofSeconds(rc.getTimeUnit(
CONFIG_PACK_SECTION, null,
CONFIG_KEY_SEARCH_FOR_REUSE_TIMEOUT,
getSearchForReuseTimeout().getSeconds(), TimeUnit.SECONDS)));
setWaitPreventRacyPack(rc.getBoolean(CONFIG_PACK_SECTION,
CONFIG_KEY_WAIT_PREVENT_RACYPACK, isWaitPreventRacyPack()));
setMinSizePreventRacyPack(rc.getLong(CONFIG_PACK_SECTION,
CONFIG_KEY_MIN_SIZE_PREVENT_RACYPACK,
getMinSizePreventRacyPack()));
}
/** {@inheritDoc} */
@Override
public String toString() {
final StringBuilder b = new StringBuilder();
b.append("maxDeltaDepth=").append(getMaxDeltaDepth()); //$NON-NLS-1$
b.append(", deltaSearchWindowSize=").append(getDeltaSearchWindowSize()); //$NON-NLS-1$
b.append(", deltaSearchMemoryLimit=") //$NON-NLS-1$
.append(getDeltaSearchMemoryLimit());
b.append(", deltaCacheSize=").append(getDeltaCacheSize()); //$NON-NLS-1$
b.append(", deltaCacheLimit=").append(getDeltaCacheLimit()); //$NON-NLS-1$
b.append(", compressionLevel=").append(getCompressionLevel()); //$NON-NLS-1$
b.append(", indexVersion=").append(getIndexVersion()); //$NON-NLS-1$
b.append(", bigFileThreshold=").append(getBigFileThreshold()); //$NON-NLS-1$
b.append(", threads=").append(getThreads()); //$NON-NLS-1$
b.append(", reuseDeltas=").append(isReuseDeltas()); //$NON-NLS-1$
b.append(", reuseObjects=").append(isReuseObjects()); //$NON-NLS-1$
b.append(", deltaCompress=").append(isDeltaCompress()); //$NON-NLS-1$
b.append(", buildBitmaps=").append(isBuildBitmaps()); //$NON-NLS-1$
b.append(", bitmapContiguousCommitCount=") //$NON-NLS-1$
.append(getBitmapContiguousCommitCount());
b.append(", bitmapRecentCommitCount=") //$NON-NLS-1$
.append(getBitmapRecentCommitCount());
b.append(", bitmapRecentCommitSpan=") //$NON-NLS-1$
.append(getBitmapRecentCommitSpan());
b.append(", bitmapDistantCommitSpan=") //$NON-NLS-1$
.append(getBitmapDistantCommitSpan());
b.append(", bitmapExcessiveBranchCount=") //$NON-NLS-1$
.append(getBitmapExcessiveBranchCount());
b.append(", bitmapInactiveBranchAge=") //$NON-NLS-1$
.append(getBitmapInactiveBranchAgeInDays());
b.append(", searchForReuseTimeout") //$NON-NLS-1$
.append(getSearchForReuseTimeout());
b.append(", singlePack=").append(getSinglePack()); //$NON-NLS-1$
return b.toString();
}
}