1 /*
2 * Copyright (C) 2008-2010, Google Inc.
3 * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com> and others
4 *
5 * This program and the accompanying materials are made available under the
6 * terms of the Eclipse Distribution License v. 1.0 which is available at
7 * https://www.eclipse.org/org/documents/edl-v10.php.
8 *
9 * SPDX-License-Identifier: BSD-3-Clause
10 */
11
12 package org.eclipse.jgit.storage.pack;
13
14 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_CORE_SECTION;
15 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BIGFILE_THRESHOLD;
16 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BITMAP_CONTIGUOUS_COMMIT_COUNT;
17 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BITMAP_DISTANT_COMMIT_SPAN;
18 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BITMAP_EXCESSIVE_BRANCH_COUNT;
19 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BITMAP_INACTIVE_BRANCH_AGE_INDAYS;
20 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BITMAP_RECENT_COMMIT_COUNT;
21 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BUILD_BITMAPS;
22 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_COMPRESSION;
23 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_CUT_DELTACHAINS;
24 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_DELTA_CACHE_LIMIT;
25 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_DELTA_CACHE_SIZE;
26 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_DELTA_COMPRESSION;
27 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_DEPTH;
28 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_INDEXVERSION;
29 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_MIN_SIZE_PREVENT_RACYPACK;
30 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_REUSE_DELTAS;
31 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_REUSE_OBJECTS;
32 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_SINGLE_PACK;
33 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_THREADS;
34 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_WAIT_PREVENT_RACYPACK;
35 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_WINDOW;
36 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_WINDOW_MEMORY;
37 import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_PACK_SECTION;
38
39 import java.util.concurrent.Executor;
40 import java.util.zip.Deflater;
41
42 import org.eclipse.jgit.internal.storage.file.PackIndexWriter;
43 import org.eclipse.jgit.lib.Config;
44 import org.eclipse.jgit.lib.Repository;
45
46 /**
47 * Configuration used by a pack writer when constructing the stream.
48 *
49 * A configuration may be modified once created, but should not be modified
50 * while it is being used by a PackWriter. If a configuration is not modified it
51 * is safe to share the same configuration instance between multiple concurrent
52 * threads executing different PackWriters.
53 */
54 public class PackConfig {
55 /**
56 * Default value of deltas reuse option: {@value}
57 *
58 * @see #setReuseDeltas(boolean)
59 */
60 public static final boolean DEFAULT_REUSE_DELTAS = true;
61
62 /**
63 * Default value of objects reuse option: {@value}
64 *
65 * @see #setReuseObjects(boolean)
66 */
67 public static final boolean DEFAULT_REUSE_OBJECTS = true;
68
69 /**
70 * Default value of keep old packs option: {@value}
71 * @see #setPreserveOldPacks(boolean)
72 * @since 4.7
73 */
74 public static final boolean DEFAULT_PRESERVE_OLD_PACKS = false;
75
76 /**
77 * Default value of prune old packs option: {@value}
78 * @see #setPrunePreserved(boolean)
79 * @since 4.7
80 */
81 public static final boolean DEFAULT_PRUNE_PRESERVED = false;
82
83 /**
84 * Default value of delta compress option: {@value}
85 *
86 * @see #setDeltaCompress(boolean)
87 */
88 public static final boolean DEFAULT_DELTA_COMPRESS = true;
89
90 /**
91 * Default value of delta base as offset option: {@value}
92 *
93 * @see #setDeltaBaseAsOffset(boolean)
94 */
95 public static final boolean DEFAULT_DELTA_BASE_AS_OFFSET = false;
96
97 /**
98 * Default value of maximum delta chain depth: {@value}
99 *
100 * @see #setMaxDeltaDepth(int)
101 */
102 public static final int DEFAULT_MAX_DELTA_DEPTH = 50;
103
104 /**
105 * Default window size during packing: {@value}
106 *
107 * @see #setDeltaSearchWindowSize(int)
108 */
109 public static final int DEFAULT_DELTA_SEARCH_WINDOW_SIZE = 10;
110
111 private static final int MB = 1 << 20;
112
113 /**
114 * Default big file threshold: {@value}
115 *
116 * @see #setBigFileThreshold(int)
117 */
118 public static final int DEFAULT_BIG_FILE_THRESHOLD = 50 * MB;
119
120 /**
121 * Default if we wait before opening a newly written pack to prevent its
122 * lastModified timestamp could be racy
123 *
124 * @since 5.1.8
125 */
126 public static final boolean DEFAULT_WAIT_PREVENT_RACY_PACK = false;
127
128 /**
129 * Default if we wait before opening a newly written pack to prevent its
130 * lastModified timestamp could be racy
131 *
132 * @since 5.1.8
133 */
134 public static final long DEFAULT_MINSIZE_PREVENT_RACY_PACK = 100 * MB;
135
136 /**
137 * Default delta cache size: {@value}
138 *
139 * @see #setDeltaCacheSize(long)
140 */
141 public static final long DEFAULT_DELTA_CACHE_SIZE = 50 * 1024 * 1024;
142
143 /**
144 * Default delta cache limit: {@value}
145 *
146 * @see #setDeltaCacheLimit(int)
147 */
148 public static final int DEFAULT_DELTA_CACHE_LIMIT = 100;
149
150 /**
151 * Default index version: {@value}
152 *
153 * @see #setIndexVersion(int)
154 */
155 public static final int DEFAULT_INDEX_VERSION = 2;
156
157 /**
158 * Default value of the build bitmaps option: {@value}
159 *
160 * @see #setBuildBitmaps(boolean)
161 * @since 3.0
162 */
163 public static final boolean DEFAULT_BUILD_BITMAPS = true;
164
165 /**
166 * Default count of most recent commits to select for bitmaps. Only applies
167 * when bitmaps are enabled: {@value}
168 *
169 * @see #setBitmapContiguousCommitCount(int)
170 * @since 4.2
171 */
172 public static final int DEFAULT_BITMAP_CONTIGUOUS_COMMIT_COUNT = 100;
173
174 /**
175 * Count at which the span between selected commits changes from
176 * "bitmapRecentCommitSpan" to "bitmapDistantCommitSpan". Only applies when
177 * bitmaps are enabled: {@value}
178 *
179 * @see #setBitmapRecentCommitCount(int)
180 * @since 4.2
181 */
182 public static final int DEFAULT_BITMAP_RECENT_COMMIT_COUNT = 20000;
183
184 /**
185 * Default spacing between commits in recent history when selecting commits
186 * for bitmaps. Only applies when bitmaps are enabled: {@value}
187 *
188 * @see #setBitmapRecentCommitSpan(int)
189 * @since 4.2
190 */
191 public static final int DEFAULT_BITMAP_RECENT_COMMIT_SPAN = 100;
192
193 /**
194 * Default spacing between commits in distant history when selecting commits
195 * for bitmaps. Only applies when bitmaps are enabled: {@value}
196 *
197 * @see #setBitmapDistantCommitSpan(int)
198 * @since 4.2
199 */
200 public static final int DEFAULT_BITMAP_DISTANT_COMMIT_SPAN = 5000;
201
202 /**
203 * Default count of branches required to activate inactive branch commit
204 * selection. If the number of branches is less than this then bitmaps for
205 * the entire commit history of all branches will be created, otherwise
206 * branches marked as "inactive" will have coverage for only partial
207 * history: {@value}
208 *
209 * @see #setBitmapExcessiveBranchCount(int)
210 * @since 4.2
211 */
212 public static final int DEFAULT_BITMAP_EXCESSIVE_BRANCH_COUNT = 100;
213
214 /**
215 * Default age at which a branch is considered inactive. Age is taken as the
216 * number of days ago that the most recent commit was made to a branch. Only
217 * affects bitmap processing if bitmaps are enabled and the
218 * "excessive branch count" has been exceeded: {@value}
219 *
220 * @see #setBitmapInactiveBranchAgeInDays(int)
221 * @since 4.2
222 */
223 public static final int DEFAULT_BITMAP_INACTIVE_BRANCH_AGE_IN_DAYS = 90;
224
225 private int compressionLevel = Deflater.DEFAULT_COMPRESSION;
226
227 private boolean reuseDeltas = DEFAULT_REUSE_DELTAS;
228
229 private boolean reuseObjects = DEFAULT_REUSE_OBJECTS;
230
231 private boolean preserveOldPacks = DEFAULT_PRESERVE_OLD_PACKS;
232
233 private boolean prunePreserved = DEFAULT_PRUNE_PRESERVED;
234
235 private boolean deltaBaseAsOffset = DEFAULT_DELTA_BASE_AS_OFFSET;
236
237 private boolean deltaCompress = DEFAULT_DELTA_COMPRESS;
238
239 private int maxDeltaDepth = DEFAULT_MAX_DELTA_DEPTH;
240
241 private int deltaSearchWindowSize = DEFAULT_DELTA_SEARCH_WINDOW_SIZE;
242
243 private long deltaSearchMemoryLimit;
244
245 private long deltaCacheSize = DEFAULT_DELTA_CACHE_SIZE;
246
247 private int deltaCacheLimit = DEFAULT_DELTA_CACHE_LIMIT;
248
249 private int bigFileThreshold = DEFAULT_BIG_FILE_THRESHOLD;
250
251 private boolean waitPreventRacyPack = DEFAULT_WAIT_PREVENT_RACY_PACK;
252
253 private long minSizePreventRacyPack = DEFAULT_MINSIZE_PREVENT_RACY_PACK;
254
255 private int threads;
256
257 private Executor executor;
258
259 private int indexVersion = DEFAULT_INDEX_VERSION;
260
261 private boolean buildBitmaps = DEFAULT_BUILD_BITMAPS;
262
263 private int bitmapContiguousCommitCount = DEFAULT_BITMAP_CONTIGUOUS_COMMIT_COUNT;
264
265 private int bitmapRecentCommitCount = DEFAULT_BITMAP_RECENT_COMMIT_COUNT;
266
267 private int bitmapRecentCommitSpan = DEFAULT_BITMAP_RECENT_COMMIT_SPAN;
268
269 private int bitmapDistantCommitSpan = DEFAULT_BITMAP_DISTANT_COMMIT_SPAN;
270
271 private int bitmapExcessiveBranchCount = DEFAULT_BITMAP_EXCESSIVE_BRANCH_COUNT;
272
273 private int bitmapInactiveBranchAgeInDays = DEFAULT_BITMAP_INACTIVE_BRANCH_AGE_IN_DAYS;
274
275 private boolean cutDeltaChains;
276
277 private boolean singlePack;
278
279 /**
280 * Create a default configuration.
281 */
282 public PackConfig() {
283 // Fields are initialized to defaults.
284 }
285
286 /**
287 * Create a configuration honoring the repository's settings.
288 *
289 * @param db
290 * the repository to read settings from. The repository is not
291 * retained by the new configuration, instead its settings are
292 * copied during the constructor.
293 */
294 public PackConfig(Repository db) {
295 fromConfig(db.getConfig());
296 }
297
298 /**
299 * Create a configuration honoring settings in a
300 * {@link org.eclipse.jgit.lib.Config}.
301 *
302 * @param cfg
303 * the source to read settings from. The source is not retained
304 * by the new configuration, instead its settings are copied
305 * during the constructor.
306 */
307 public PackConfig(Config cfg) {
308 fromConfig(cfg);
309 }
310
311 /**
312 * Copy an existing configuration to a new instance.
313 *
314 * @param cfg
315 * the source configuration to copy from.
316 */
317 public PackConfighref="../../../../../org/eclipse/jgit/storage/pack/PackConfig.html#PackConfig">PackConfig(PackConfig cfg) {
318 this.compressionLevel = cfg.compressionLevel;
319 this.reuseDeltas = cfg.reuseDeltas;
320 this.reuseObjects = cfg.reuseObjects;
321 this.preserveOldPacks = cfg.preserveOldPacks;
322 this.prunePreserved = cfg.prunePreserved;
323 this.deltaBaseAsOffset = cfg.deltaBaseAsOffset;
324 this.deltaCompress = cfg.deltaCompress;
325 this.maxDeltaDepth = cfg.maxDeltaDepth;
326 this.deltaSearchWindowSize = cfg.deltaSearchWindowSize;
327 this.deltaSearchMemoryLimit = cfg.deltaSearchMemoryLimit;
328 this.deltaCacheSize = cfg.deltaCacheSize;
329 this.deltaCacheLimit = cfg.deltaCacheLimit;
330 this.bigFileThreshold = cfg.bigFileThreshold;
331 this.waitPreventRacyPack = cfg.waitPreventRacyPack;
332 this.minSizePreventRacyPack = cfg.minSizePreventRacyPack;
333 this.threads = cfg.threads;
334 this.executor = cfg.executor;
335 this.indexVersion = cfg.indexVersion;
336 this.buildBitmaps = cfg.buildBitmaps;
337 this.bitmapContiguousCommitCount = cfg.bitmapContiguousCommitCount;
338 this.bitmapRecentCommitCount = cfg.bitmapRecentCommitCount;
339 this.bitmapRecentCommitSpan = cfg.bitmapRecentCommitSpan;
340 this.bitmapDistantCommitSpan = cfg.bitmapDistantCommitSpan;
341 this.bitmapExcessiveBranchCount = cfg.bitmapExcessiveBranchCount;
342 this.bitmapInactiveBranchAgeInDays = cfg.bitmapInactiveBranchAgeInDays;
343 this.cutDeltaChains = cfg.cutDeltaChains;
344 this.singlePack = cfg.singlePack;
345 }
346
347 /**
348 * Check whether to reuse deltas existing in repository.
349 *
350 * Default setting: {@value #DEFAULT_REUSE_DELTAS}
351 *
352 * @return true if object is configured to reuse deltas; false otherwise.
353 */
354 public boolean isReuseDeltas() {
355 return reuseDeltas;
356 }
357
358 /**
359 * Set reuse deltas configuration option for the writer.
360 *
361 * When enabled, writer will search for delta representation of object in
362 * repository and use it if possible. Normally, only deltas with base to
363 * another object existing in set of objects to pack will be used. The
364 * exception however is thin-packs where the base object may exist on the
365 * other side.
366 *
367 * When raw delta data is directly copied from a pack file, its checksum is
368 * computed to verify the data is not corrupt.
369 *
370 * Default setting: {@value #DEFAULT_REUSE_DELTAS}
371 *
372 * @param reuseDeltas
373 * boolean indicating whether or not try to reuse deltas.
374 */
375 public void setReuseDeltas(boolean reuseDeltas) {
376 this.reuseDeltas = reuseDeltas;
377 }
378
379 /**
380 * Checks whether to reuse existing objects representation in repository.
381 *
382 * Default setting: {@value #DEFAULT_REUSE_OBJECTS}
383 *
384 * @return true if writer is configured to reuse objects representation from
385 * pack; false otherwise.
386 */
387 public boolean isReuseObjects() {
388 return reuseObjects;
389 }
390
391 /**
392 * Set reuse objects configuration option for the writer.
393 *
394 * If enabled, writer searches for compressed representation in a pack file.
395 * If possible, compressed data is directly copied from such a pack file.
396 * Data checksum is verified.
397 *
398 * Default setting: {@value #DEFAULT_REUSE_OBJECTS}
399 *
400 * @param reuseObjects
401 * boolean indicating whether or not writer should reuse existing
402 * objects representation.
403 */
404 public void setReuseObjects(boolean reuseObjects) {
405 this.reuseObjects = reuseObjects;
406 }
407
408 /**
409 * Checks whether to preserve old packs in a preserved directory
410 *
411 * Default setting: {@value #DEFAULT_PRESERVE_OLD_PACKS}
412 *
413 * @return true if repacking will preserve old pack files.
414 * @since 4.7
415 */
416 public boolean isPreserveOldPacks() {
417 return preserveOldPacks;
418 }
419
420 /**
421 * Set preserve old packs configuration option for repacking.
422 *
423 * If enabled, old pack files are moved into a preserved subdirectory instead
424 * of being deleted
425 *
426 * Default setting: {@value #DEFAULT_PRESERVE_OLD_PACKS}
427 *
428 * @param preserveOldPacks
429 * boolean indicating whether or not preserve old pack files
430 * @since 4.7
431 */
432 public void setPreserveOldPacks(boolean preserveOldPacks) {
433 this.preserveOldPacks = preserveOldPacks;
434 }
435
436 /**
437 * Checks whether to remove preserved pack files in a preserved directory
438 *
439 * Default setting: {@value #DEFAULT_PRUNE_PRESERVED}
440 *
441 * @return true if repacking will remove preserved pack files.
442 * @since 4.7
443 */
444 public boolean isPrunePreserved() {
445 return prunePreserved;
446 }
447
448 /**
449 * Set prune preserved configuration option for repacking.
450 *
451 * If enabled, preserved pack files are removed from a preserved subdirectory
452 *
453 * Default setting: {@value #DEFAULT_PRESERVE_OLD_PACKS}
454 *
455 * @param prunePreserved
456 * boolean indicating whether or not preserve old pack files
457 * @since 4.7
458 */
459 public void setPrunePreserved(boolean prunePreserved) {
460 this.prunePreserved = prunePreserved;
461 }
462
463 /**
464 * True if writer can use offsets to point to a delta base.
465 *
466 * If true the writer may choose to use an offset to point to a delta base
467 * in the same pack, this is a newer style of reference that saves space.
468 * False if the writer has to use the older (and more compatible style) of
469 * storing the full ObjectId of the delta base.
470 *
471 * Default setting: {@value #DEFAULT_DELTA_BASE_AS_OFFSET}
472 *
473 * @return true if delta base is stored as an offset; false if it is stored
474 * as an ObjectId.
475 */
476 public boolean isDeltaBaseAsOffset() {
477 return deltaBaseAsOffset;
478 }
479
480 /**
481 * Set writer delta base format.
482 *
483 * Delta base can be written as an offset in a pack file (new approach
484 * reducing file size) or as an object id (legacy approach, compatible with
485 * old readers).
486 *
487 * Default setting: {@value #DEFAULT_DELTA_BASE_AS_OFFSET}
488 *
489 * @param deltaBaseAsOffset
490 * boolean indicating whether delta base can be stored as an
491 * offset.
492 */
493 public void setDeltaBaseAsOffset(boolean deltaBaseAsOffset) {
494 this.deltaBaseAsOffset = deltaBaseAsOffset;
495 }
496
497 /**
498 * Check whether the writer will create new deltas on the fly.
499 *
500 * Default setting: {@value #DEFAULT_DELTA_COMPRESS}
501 *
502 * @return true if the writer will create a new delta when either
503 * {@link #isReuseDeltas()} is false, or no suitable delta is
504 * available for reuse.
505 */
506 public boolean isDeltaCompress() {
507 return deltaCompress;
508 }
509
510 /**
511 * Set whether or not the writer will create new deltas on the fly.
512 *
513 * Default setting: {@value #DEFAULT_DELTA_COMPRESS}
514 *
515 * @param deltaCompress
516 * true to create deltas when {@link #isReuseDeltas()} is false,
517 * or when a suitable delta isn't available for reuse. Set to
518 * false to write whole objects instead.
519 */
520 public void setDeltaCompress(boolean deltaCompress) {
521 this.deltaCompress = deltaCompress;
522 }
523
524 /**
525 * Get maximum depth of delta chain set up for the writer.
526 *
527 * Generated chains are not longer than this value.
528 *
529 * Default setting: {@value #DEFAULT_MAX_DELTA_DEPTH}
530 *
531 * @return maximum delta chain depth.
532 */
533 public int getMaxDeltaDepth() {
534 return maxDeltaDepth;
535 }
536
537 /**
538 * Set up maximum depth of delta chain for the writer.
539 *
540 * Generated chains are not longer than this value. Too low value causes low
541 * compression level, while too big makes unpacking (reading) longer.
542 *
543 * Default setting: {@value #DEFAULT_MAX_DELTA_DEPTH}
544 *
545 * @param maxDeltaDepth
546 * maximum delta chain depth.
547 */
548 public void setMaxDeltaDepth(int maxDeltaDepth) {
549 this.maxDeltaDepth = maxDeltaDepth;
550 }
551
552 /**
553 * Whether existing delta chains should be cut at
554 * {@link #getMaxDeltaDepth()}.
555 *
556 * @return true if existing delta chains should be cut at
557 * {@link #getMaxDeltaDepth()}. Default is false, allowing existing
558 * chains to be of any length.
559 * @since 3.0
560 */
561 public boolean getCutDeltaChains() {
562 return cutDeltaChains;
563 }
564
565 /**
566 * Enable cutting existing delta chains at {@link #getMaxDeltaDepth()}.
567 *
568 * By default this is disabled and existing chains are kept at whatever
569 * length a prior packer was configured to create. This allows objects to be
570 * packed one with a large depth (for example 250), and later to quickly
571 * repack the repository with a shorter depth (such as 50), but reusing the
572 * complete delta chains created by the earlier 250 depth.
573 *
574 * @param cut
575 * true to cut existing chains.
576 * @since 3.0
577 */
578 public void setCutDeltaChains(boolean cut) {
579 cutDeltaChains = cut;
580 }
581
582 /**
583 * Whether all of refs/* should be packed in a single pack.
584 *
585 * @return true if all of refs/* should be packed in a single pack. Default
586 * is false, packing a separate GC_REST pack for references outside
587 * of refs/heads/* and refs/tags/*.
588 * @since 4.9
589 */
590 public boolean getSinglePack() {
591 return singlePack;
592 }
593
594 /**
595 * If {@code true}, packs a single GC pack for all objects reachable from
596 * refs/*. Otherwise packs the GC pack with objects reachable from
597 * refs/heads/* and refs/tags/*, and a GC_REST pack with the remaining
598 * reachable objects. Disabled by default, packing GC and GC_REST.
599 *
600 * @param single
601 * true to pack a single GC pack rather than GC and GC_REST packs
602 * @since 4.9
603 */
604 public void setSinglePack(boolean single) {
605 singlePack = single;
606 }
607
608 /**
609 * Get the number of objects to try when looking for a delta base.
610 *
611 * This limit is per thread, if 4 threads are used the actual memory used
612 * will be 4 times this value.
613 *
614 * Default setting: {@value #DEFAULT_DELTA_SEARCH_WINDOW_SIZE}
615 *
616 * @return the object count to be searched.
617 */
618 public int getDeltaSearchWindowSize() {
619 return deltaSearchWindowSize;
620 }
621
622 /**
623 * Set the number of objects considered when searching for a delta base.
624 *
625 * Default setting: {@value #DEFAULT_DELTA_SEARCH_WINDOW_SIZE}
626 *
627 * @param objectCount
628 * number of objects to search at once. Must be at least 2.
629 */
630 public void setDeltaSearchWindowSize(int objectCount) {
631 if (objectCount <= 2)
632 setDeltaCompress(false);
633 else
634 deltaSearchWindowSize = objectCount;
635 }
636
637 /**
638 * Get maximum number of bytes to put into the delta search window.
639 *
640 * Default setting is 0, for an unlimited amount of memory usage. Actual
641 * memory used is the lower limit of either this setting, or the sum of
642 * space used by at most {@link #getDeltaSearchWindowSize()} objects.
643 *
644 * This limit is per thread, if 4 threads are used the actual memory limit
645 * will be 4 times this value.
646 *
647 * @return the memory limit.
648 */
649 public long getDeltaSearchMemoryLimit() {
650 return deltaSearchMemoryLimit;
651 }
652
653 /**
654 * Set the maximum number of bytes to put into the delta search window.
655 *
656 * Default setting is 0, for an unlimited amount of memory usage. If the
657 * memory limit is reached before {@link #getDeltaSearchWindowSize()} the
658 * window size is temporarily lowered.
659 *
660 * @param memoryLimit
661 * Maximum number of bytes to load at once, 0 for unlimited.
662 */
663 public void setDeltaSearchMemoryLimit(long memoryLimit) {
664 deltaSearchMemoryLimit = memoryLimit;
665 }
666
667 /**
668 * Get the size of the in-memory delta cache.
669 *
670 * This limit is for the entire writer, even if multiple threads are used.
671 *
672 * Default setting: {@value #DEFAULT_DELTA_CACHE_SIZE}
673 *
674 * @return maximum number of bytes worth of delta data to cache in memory.
675 * If 0 the cache is infinite in size (up to the JVM heap limit
676 * anyway). A very tiny size such as 1 indicates the cache is
677 * effectively disabled.
678 */
679 public long getDeltaCacheSize() {
680 return deltaCacheSize;
681 }
682
683 /**
684 * Set the maximum number of bytes of delta data to cache.
685 *
686 * During delta search, up to this many bytes worth of small or hard to
687 * compute deltas will be stored in memory. This cache speeds up writing by
688 * allowing the cached entry to simply be dumped to the output stream.
689 *
690 * Default setting: {@value #DEFAULT_DELTA_CACHE_SIZE}
691 *
692 * @param size
693 * number of bytes to cache. Set to 0 to enable an infinite
694 * cache, set to 1 (an impossible size for any delta) to disable
695 * the cache.
696 */
697 public void setDeltaCacheSize(long size) {
698 deltaCacheSize = size;
699 }
700
701 /**
702 * Maximum size in bytes of a delta to cache.
703 *
704 * Default setting: {@value #DEFAULT_DELTA_CACHE_LIMIT}
705 *
706 * @return maximum size (in bytes) of a delta that should be cached.
707 */
708 public int getDeltaCacheLimit() {
709 return deltaCacheLimit;
710 }
711
712 /**
713 * Set the maximum size of a delta that should be cached.
714 *
715 * During delta search, any delta smaller than this size will be cached, up
716 * to the {@link #getDeltaCacheSize()} maximum limit. This speeds up writing
717 * by allowing these cached deltas to be output as-is.
718 *
719 * Default setting: {@value #DEFAULT_DELTA_CACHE_LIMIT}
720 *
721 * @param size
722 * maximum size (in bytes) of a delta to be cached.
723 */
724 public void setDeltaCacheLimit(int size) {
725 deltaCacheLimit = size;
726 }
727
728 /**
729 * Get the maximum file size that will be delta compressed.
730 *
731 * Files bigger than this setting will not be delta compressed, as they are
732 * more than likely already highly compressed binary data files that do not
733 * delta compress well, such as MPEG videos.
734 *
735 * Default setting: {@value #DEFAULT_BIG_FILE_THRESHOLD}
736 *
737 * @return the configured big file threshold.
738 */
739 public int getBigFileThreshold() {
740 return bigFileThreshold;
741 }
742
743 /**
744 * Set the maximum file size that should be considered for deltas.
745 *
746 * Default setting: {@value #DEFAULT_BIG_FILE_THRESHOLD}
747 *
748 * @param bigFileThreshold
749 * the limit, in bytes.
750 */
751 public void setBigFileThreshold(int bigFileThreshold) {
752 this.bigFileThreshold = bigFileThreshold;
753 }
754
755 /**
756 * Get whether we wait before opening a newly written pack to prevent its
757 * lastModified timestamp could be racy
758 *
759 * @return whether we wait before opening a newly written pack to prevent
760 * its lastModified timestamp could be racy
761 * @since 5.1.8
762 */
763 public boolean isWaitPreventRacyPack() {
764 return waitPreventRacyPack;
765 }
766
767 /**
768 * Get whether we wait before opening a newly written pack to prevent its
769 * lastModified timestamp could be racy. Returns {@code true} if
770 * {@code waitToPreventRacyPack = true} and
771 * {@code packSize > minSizePreventRacyPack}, {@code false} otherwise.
772 *
773 * @param packSize
774 * size of the pack file
775 *
776 * @return whether we wait before opening a newly written pack to prevent
777 * its lastModified timestamp could be racy
778 * @since 5.1.8
779 */
780 public boolean doWaitPreventRacyPack(long packSize) {
781 return isWaitPreventRacyPack()
782 && packSize > getMinSizePreventRacyPack();
783 }
784
785 /**
786 * Set whether we wait before opening a newly written pack to prevent its
787 * lastModified timestamp could be racy
788 *
789 * @param waitPreventRacyPack
790 * whether we wait before opening a newly written pack to prevent
791 * its lastModified timestamp could be racy
792 * @since 5.1.8
793 */
794 public void setWaitPreventRacyPack(boolean waitPreventRacyPack) {
795 this.waitPreventRacyPack = waitPreventRacyPack;
796 }
797
798 /**
799 * Get minimum packfile size for which we wait before opening a newly
800 * written pack to prevent its lastModified timestamp could be racy if
801 * {@code isWaitToPreventRacyPack} is {@code true}.
802 *
803 * @return minimum packfile size, default is 100 MiB
804 *
805 * @since 5.1.8
806 */
807 public long getMinSizePreventRacyPack() {
808 return minSizePreventRacyPack;
809 }
810
811 /**
812 * Set minimum packfile size for which we wait before opening a newly
813 * written pack to prevent its lastModified timestamp could be racy if
814 * {@code isWaitToPreventRacyPack} is {@code true}.
815 *
816 * @param minSizePreventRacyPack
817 * minimum packfile size, default is 100 MiB
818 *
819 * @since 5.1.8
820 */
821 public void setMinSizePreventRacyPack(long minSizePreventRacyPack) {
822 this.minSizePreventRacyPack = minSizePreventRacyPack;
823 }
824
825 /**
826 * Get the compression level applied to objects in the pack.
827 *
828 * Default setting: {@value java.util.zip.Deflater#DEFAULT_COMPRESSION}
829 *
830 * @return current compression level, see {@link java.util.zip.Deflater}.
831 */
832 public int getCompressionLevel() {
833 return compressionLevel;
834 }
835
836 /**
837 * Set the compression level applied to objects in the pack.
838 *
839 * Default setting: {@value java.util.zip.Deflater#DEFAULT_COMPRESSION}
840 *
841 * @param level
842 * compression level, must be a valid level recognized by the
843 * {@link java.util.zip.Deflater} class.
844 */
845 public void setCompressionLevel(int level) {
846 compressionLevel = level;
847 }
848
849 /**
850 * Get the number of threads used during delta compression.
851 *
852 * Default setting: 0 (auto-detect processors)
853 *
854 * @return number of threads used for delta compression. 0 will auto-detect
855 * the threads to the number of available processors.
856 */
857 public int getThreads() {
858 return threads;
859 }
860
861 /**
862 * Set the number of threads to use for delta compression.
863 *
864 * During delta compression, if there are enough objects to be considered
865 * the writer will start up concurrent threads and allow them to compress
866 * different sections of the repository concurrently.
867 *
868 * An application thread pool can be set by {@link #setExecutor(Executor)}.
869 * If not set a temporary pool will be created by the writer, and torn down
870 * automatically when compression is over.
871 *
872 * Default setting: 0 (auto-detect processors)
873 *
874 * @param threads
875 * number of threads to use. If <= 0 the number of available
876 * processors for this JVM is used.
877 */
878 public void setThreads(int threads) {
879 this.threads = threads;
880 }
881
882 /**
883 * Get the preferred thread pool to execute delta search on.
884 *
885 * @return the preferred thread pool to execute delta search on.
886 */
887 public Executor getExecutor() {
888 return executor;
889 }
890
891 /**
892 * Set the executor to use when using threads.
893 *
894 * During delta compression if the executor is non-null jobs will be queued
895 * up on it to perform delta compression in parallel. Aside from setting the
896 * executor, the caller must set {@link #setThreads(int)} to enable threaded
897 * delta search.
898 *
899 * @param executor
900 * executor to use for threads. Set to null to create a temporary
901 * executor just for the writer.
902 */
903 public void setExecutor(Executor executor) {
904 this.executor = executor;
905 }
906
907 /**
908 * Get the pack index file format version this instance creates.
909 *
910 * Default setting: {@value #DEFAULT_INDEX_VERSION}
911 *
912 * @return the index version, the special version 0 designates the oldest
913 * (most compatible) format available for the objects.
914 * @see PackIndexWriter
915 */
916 public int getIndexVersion() {
917 return indexVersion;
918 }
919
920 /**
921 * Set the pack index file format version this instance will create.
922 *
923 * Default setting: {@value #DEFAULT_INDEX_VERSION}
924 *
925 * @param version
926 * the version to write. The special version 0 designates the
927 * oldest (most compatible) format available for the objects.
928 * @see PackIndexWriter
929 */
930 public void setIndexVersion(int version) {
931 indexVersion = version;
932 }
933
934 /**
935 * True if writer is allowed to build bitmaps for indexes.
936 *
937 * Default setting: {@value #DEFAULT_BUILD_BITMAPS}
938 *
939 * @return true if delta base is the writer can choose to output an index
940 * with bitmaps.
941 * @since 3.0
942 */
943 public boolean isBuildBitmaps() {
944 return buildBitmaps;
945 }
946
947 /**
948 * Set writer to allow building bitmaps for supported pack files.
949 *
950 * Index files can include bitmaps to speed up future ObjectWalks.
951 *
952 * Default setting: {@value #DEFAULT_BUILD_BITMAPS}
953 *
954 * @param buildBitmaps
955 * boolean indicating whether bitmaps may be included in the
956 * index.
957 * @since 3.0
958 */
959 public void setBuildBitmaps(boolean buildBitmaps) {
960 this.buildBitmaps = buildBitmaps;
961 }
962
963 /**
964 * Get the count of most recent commits for which to build bitmaps.
965 *
966 * Default setting: {@value #DEFAULT_BITMAP_CONTIGUOUS_COMMIT_COUNT}
967 *
968 * @return the count of most recent commits for which to build bitmaps
969 * @since 4.2
970 */
971 public int getBitmapContiguousCommitCount() {
972 return bitmapContiguousCommitCount;
973 }
974
975 /**
976 * Set the count of most recent commits for which to build bitmaps.
977 *
978 * Default setting: {@value #DEFAULT_BITMAP_CONTIGUOUS_COMMIT_COUNT}
979 *
980 * @param count
981 * the count of most recent commits for which to build bitmaps
982 * @since 4.2
983 */
984 public void setBitmapContiguousCommitCount(int count) {
985 bitmapContiguousCommitCount = count;
986 }
987
988 /**
989 * Get the count at which to switch from "bitmapRecentCommitSpan" to
990 * "bitmapDistantCommitSpan".
991 *
992 * Default setting: {@value #DEFAULT_BITMAP_RECENT_COMMIT_COUNT}
993 *
994 * @return the count for switching between recent and distant spans
995 * @since 4.2
996 */
997 public int getBitmapRecentCommitCount() {
998 return bitmapRecentCommitCount;
999 }
1000
1001 /**
1002 * Set the count at which to switch from "bitmapRecentCommitSpan" to
1003 * "bitmapDistantCommitSpan".
1004 *
1005 * Default setting: {@value #DEFAULT_BITMAP_RECENT_COMMIT_COUNT}
1006 *
1007 * @param count
1008 * the count for switching between recent and distant spans
1009 * @since 4.2
1010 */
1011 public void setBitmapRecentCommitCount(int count) {
1012 bitmapRecentCommitCount = count;
1013 }
1014
1015 /**
1016 * Get the span of commits when building bitmaps for recent history.
1017 *
1018 * Default setting: {@value #DEFAULT_BITMAP_RECENT_COMMIT_SPAN}
1019 *
1020 * @return the span of commits when building bitmaps for recent history
1021 * @since 4.2
1022 */
1023 public int getBitmapRecentCommitSpan() {
1024 return bitmapRecentCommitSpan;
1025 }
1026
1027 /**
1028 * Set the span of commits when building bitmaps for recent history.
1029 *
1030 * Default setting: {@value #DEFAULT_BITMAP_RECENT_COMMIT_SPAN}
1031 *
1032 * @param span
1033 * the span of commits when building bitmaps for recent history
1034 * @since 4.2
1035 */
1036 public void setBitmapRecentCommitSpan(int span) {
1037 bitmapRecentCommitSpan = span;
1038 }
1039
1040 /**
1041 * Get the span of commits when building bitmaps for distant history.
1042 *
1043 * Default setting: {@value #DEFAULT_BITMAP_DISTANT_COMMIT_SPAN}
1044 *
1045 * @return the span of commits when building bitmaps for distant history
1046 * @since 4.2
1047 */
1048 public int getBitmapDistantCommitSpan() {
1049 return bitmapDistantCommitSpan;
1050 }
1051
1052 /**
1053 * Set the span of commits when building bitmaps for distant history.
1054 *
1055 * Default setting: {@value #DEFAULT_BITMAP_DISTANT_COMMIT_SPAN}
1056 *
1057 * @param span
1058 * the span of commits when building bitmaps for distant history
1059 * @since 4.2
1060 */
1061 public void setBitmapDistantCommitSpan(int span) {
1062 bitmapDistantCommitSpan = span;
1063 }
1064
1065 /**
1066 * Get the count of branches deemed "excessive". If the count of branches in
1067 * a repository exceeds this number and bitmaps are enabled, "inactive"
1068 * branches will have fewer bitmaps than "active" branches.
1069 *
1070 * Default setting: {@value #DEFAULT_BITMAP_EXCESSIVE_BRANCH_COUNT}
1071 *
1072 * @return the count of branches deemed "excessive"
1073 * @since 4.2
1074 */
1075 public int getBitmapExcessiveBranchCount() {
1076 return bitmapExcessiveBranchCount;
1077 }
1078
1079 /**
1080 * Set the count of branches deemed "excessive". If the count of branches in
1081 * a repository exceeds this number and bitmaps are enabled, "inactive"
1082 * branches will have fewer bitmaps than "active" branches.
1083 *
1084 * Default setting: {@value #DEFAULT_BITMAP_EXCESSIVE_BRANCH_COUNT}
1085 *
1086 * @param count
1087 * the count of branches deemed "excessive"
1088 * @since 4.2
1089 */
1090 public void setBitmapExcessiveBranchCount(int count) {
1091 bitmapExcessiveBranchCount = count;
1092 }
1093
1094 /**
1095 * Get the age in days that marks a branch as "inactive".
1096 *
1097 * Default setting: {@value #DEFAULT_BITMAP_INACTIVE_BRANCH_AGE_IN_DAYS}
1098 *
1099 * @return the age in days that marks a branch as "inactive"
1100 * @since 4.2
1101 */
1102 public int getBitmapInactiveBranchAgeInDays() {
1103 return bitmapInactiveBranchAgeInDays;
1104 }
1105
1106 /**
1107 * Set the age in days that marks a branch as "inactive".
1108 *
1109 * Default setting: {@value #DEFAULT_BITMAP_INACTIVE_BRANCH_AGE_IN_DAYS}
1110 *
1111 * @param ageInDays
1112 * the age in days that marks a branch as "inactive"
1113 * @since 4.2
1114 */
1115 public void setBitmapInactiveBranchAgeInDays(int ageInDays) {
1116 bitmapInactiveBranchAgeInDays = ageInDays;
1117 }
1118
1119 /**
1120 * Update properties by setting fields from the configuration.
1121 *
1122 * If a property's corresponding variable is not defined in the supplied
1123 * configuration, then it is left unmodified.
1124 *
1125 * @param rc
1126 * configuration to read properties from.
1127 */
1128 public void fromConfig(Config rc) {
1129 setMaxDeltaDepth(rc.getInt(CONFIG_PACK_SECTION, CONFIG_KEY_DEPTH,
1130 getMaxDeltaDepth()));
1131 setDeltaSearchWindowSize(rc.getInt(CONFIG_PACK_SECTION,
1132 CONFIG_KEY_WINDOW, getDeltaSearchWindowSize()));
1133 setDeltaSearchMemoryLimit(rc.getLong(CONFIG_PACK_SECTION,
1134 CONFIG_KEY_WINDOW_MEMORY, getDeltaSearchMemoryLimit()));
1135 setDeltaCacheSize(rc.getLong(CONFIG_PACK_SECTION,
1136 CONFIG_KEY_DELTA_CACHE_SIZE, getDeltaCacheSize()));
1137 setDeltaCacheLimit(rc.getInt(CONFIG_PACK_SECTION,
1138 CONFIG_KEY_DELTA_CACHE_LIMIT, getDeltaCacheLimit()));
1139 setCompressionLevel(rc.getInt(CONFIG_PACK_SECTION,
1140 CONFIG_KEY_COMPRESSION, rc.getInt(CONFIG_CORE_SECTION,
1141 CONFIG_KEY_COMPRESSION, getCompressionLevel())));
1142 setIndexVersion(rc.getInt(CONFIG_PACK_SECTION,
1143 CONFIG_KEY_INDEXVERSION,
1144 getIndexVersion()));
1145 setBigFileThreshold(rc.getInt(CONFIG_CORE_SECTION,
1146 CONFIG_KEY_BIGFILE_THRESHOLD, getBigFileThreshold()));
1147 setThreads(rc.getInt(CONFIG_PACK_SECTION, CONFIG_KEY_THREADS,
1148 getThreads()));
1149
1150 // These variables aren't standardized
1151 setReuseDeltas(rc.getBoolean(CONFIG_PACK_SECTION,
1152 CONFIG_KEY_REUSE_DELTAS, isReuseDeltas()));
1153 setReuseObjects(rc.getBoolean(CONFIG_PACK_SECTION,
1154 CONFIG_KEY_REUSE_OBJECTS, isReuseObjects()));
1155 setDeltaCompress(rc.getBoolean(CONFIG_PACK_SECTION,
1156 CONFIG_KEY_DELTA_COMPRESSION, isDeltaCompress()));
1157 setCutDeltaChains(rc.getBoolean(CONFIG_PACK_SECTION,
1158 CONFIG_KEY_CUT_DELTACHAINS, getCutDeltaChains()));
1159 setSinglePack(rc.getBoolean(CONFIG_PACK_SECTION,
1160 CONFIG_KEY_SINGLE_PACK,
1161 getSinglePack()));
1162 setBuildBitmaps(rc.getBoolean(CONFIG_PACK_SECTION,
1163 CONFIG_KEY_BUILD_BITMAPS, isBuildBitmaps()));
1164 setBitmapContiguousCommitCount(rc.getInt(CONFIG_PACK_SECTION,
1165 CONFIG_KEY_BITMAP_CONTIGUOUS_COMMIT_COUNT,
1166 getBitmapContiguousCommitCount()));
1167 setBitmapRecentCommitCount(rc.getInt(CONFIG_PACK_SECTION,
1168 CONFIG_KEY_BITMAP_RECENT_COMMIT_COUNT,
1169 getBitmapRecentCommitCount()));
1170 setBitmapRecentCommitSpan(rc.getInt(CONFIG_PACK_SECTION,
1171 CONFIG_KEY_BITMAP_RECENT_COMMIT_COUNT,
1172 getBitmapRecentCommitSpan()));
1173 setBitmapDistantCommitSpan(rc.getInt(CONFIG_PACK_SECTION,
1174 CONFIG_KEY_BITMAP_DISTANT_COMMIT_SPAN,
1175 getBitmapDistantCommitSpan()));
1176 setBitmapExcessiveBranchCount(rc.getInt(CONFIG_PACK_SECTION,
1177 CONFIG_KEY_BITMAP_EXCESSIVE_BRANCH_COUNT,
1178 getBitmapExcessiveBranchCount()));
1179 setBitmapInactiveBranchAgeInDays(rc.getInt(CONFIG_PACK_SECTION,
1180 CONFIG_KEY_BITMAP_INACTIVE_BRANCH_AGE_INDAYS,
1181 getBitmapInactiveBranchAgeInDays()));
1182 setWaitPreventRacyPack(rc.getBoolean(CONFIG_PACK_SECTION,
1183 CONFIG_KEY_WAIT_PREVENT_RACYPACK, isWaitPreventRacyPack()));
1184 setMinSizePreventRacyPack(rc.getLong(CONFIG_PACK_SECTION,
1185 CONFIG_KEY_MIN_SIZE_PREVENT_RACYPACK,
1186 getMinSizePreventRacyPack()));
1187 }
1188
1189 /** {@inheritDoc} */
1190 @Override
1191 public String toString() {
1192 final StringBuilder b = new StringBuilder();
1193 b.append("maxDeltaDepth=").append(getMaxDeltaDepth()); //$NON-NLS-1$
1194 b.append(", deltaSearchWindowSize=").append(getDeltaSearchWindowSize()); //$NON-NLS-1$
1195 b.append(", deltaSearchMemoryLimit=") //$NON-NLS-1$
1196 .append(getDeltaSearchMemoryLimit());
1197 b.append(", deltaCacheSize=").append(getDeltaCacheSize()); //$NON-NLS-1$
1198 b.append(", deltaCacheLimit=").append(getDeltaCacheLimit()); //$NON-NLS-1$
1199 b.append(", compressionLevel=").append(getCompressionLevel()); //$NON-NLS-1$
1200 b.append(", indexVersion=").append(getIndexVersion()); //$NON-NLS-1$
1201 b.append(", bigFileThreshold=").append(getBigFileThreshold()); //$NON-NLS-1$
1202 b.append(", threads=").append(getThreads()); //$NON-NLS-1$
1203 b.append(", reuseDeltas=").append(isReuseDeltas()); //$NON-NLS-1$
1204 b.append(", reuseObjects=").append(isReuseObjects()); //$NON-NLS-1$
1205 b.append(", deltaCompress=").append(isDeltaCompress()); //$NON-NLS-1$
1206 b.append(", buildBitmaps=").append(isBuildBitmaps()); //$NON-NLS-1$
1207 b.append(", bitmapContiguousCommitCount=") //$NON-NLS-1$
1208 .append(getBitmapContiguousCommitCount());
1209 b.append(", bitmapRecentCommitCount=") //$NON-NLS-1$
1210 .append(getBitmapRecentCommitCount());
1211 b.append(", bitmapRecentCommitSpan=") //$NON-NLS-1$
1212 .append(getBitmapRecentCommitSpan());
1213 b.append(", bitmapDistantCommitSpan=") //$NON-NLS-1$
1214 .append(getBitmapDistantCommitSpan());
1215 b.append(", bitmapExcessiveBranchCount=") //$NON-NLS-1$
1216 .append(getBitmapExcessiveBranchCount());
1217 b.append(", bitmapInactiveBranchAge=") //$NON-NLS-1$
1218 .append(getBitmapInactiveBranchAgeInDays());
1219 b.append(", singlePack=").append(getSinglePack()); //$NON-NLS-1$
1220 return b.toString();
1221 }
1222 }