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