summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit
diff options
context:
space:
mode:
authorThirumala Reddy Mutchukota <thirumala@google.com>2017-02-06 14:08:27 -0800
committerThirumala Reddy Mutchukota <thirumala@google.com>2017-02-07 20:34:31 -0800
commit006f4d4d29eecc3d357b442cc76b76fdeff51de0 (patch)
tree4c7fac77e68025f8bb219e585bdc7b0c179a3d41 /org.eclipse.jgit
parentd4bd09b78daa733933a15733bc6ebbaa0a0485f1 (diff)
downloadjgit-006f4d4d29eecc3d357b442cc76b76fdeff51de0.tar.gz
jgit-006f4d4d29eecc3d357b442cc76b76fdeff51de0.zip
Reintroduce garbage pack coalescing when ttl > 0.
Disabling the garbage pack coalescing when garbageTtl > 0 can result in lot of garbage packs if they are created within the garbageTtl time. To avoid a large number of garbage packs, re-introducing garbage pack coalescing for the packs that are created within a single calendar day when the garbageTtl is more than one day or one third of the garbageTtl. Change-Id: If969716aeb55fb4fd0ff71d75f41a07638cd5a69 Signed-off-by: Thirumala Reddy Mutchukota <thirumala@google.com>
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollector.java80
1 files changed, 70 insertions, 10 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollector.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollector.java
index 56ff1b5c2e..968313254b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollector.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsGarbageCollector.java
@@ -56,9 +56,11 @@ import static org.eclipse.jgit.internal.storage.pack.PackExt.PACK;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
+import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -82,6 +84,7 @@ import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.storage.pack.PackConfig;
import org.eclipse.jgit.storage.pack.PackStatistics;
+import org.eclipse.jgit.util.SystemReader;
import org.eclipse.jgit.util.io.CountingOutputStream;
/** Repack and garbage collect a repository. */
@@ -100,7 +103,8 @@ public class DfsGarbageCollector {
private PackConfig packConfig;
- // See pack(), below, for how these two variables interact.
+ // See packIsCoalesceableGarbage(), below, for how these two variables
+ // interact.
private long coalesceGarbageLimit = 50 << 20;
private long garbageTtlMillis = TimeUnit.DAYS.toMillis(1);
@@ -228,14 +232,8 @@ public class DfsGarbageCollector {
if (packConfig.getIndexVersion() != 2)
throw new IllegalStateException(
JGitText.get().supportOnlyPackIndexVersion2);
- if (garbageTtlMillis > 0) {
- // We disable coalescing because the coalescing step will keep
- // refreshing the UNREACHABLE_GARBAGE pack and we wouldn't
- // actually prune anything.
- coalesceGarbageLimit = 0;
- }
- startTimeMillis = System.currentTimeMillis();
+ startTimeMillis = SystemReader.getInstance().getCurrentTime();
ctx = (DfsReader) objdb.newReader();
try {
refdb.refresh();
@@ -310,14 +308,14 @@ public class DfsGarbageCollector {
expiredGarbagePacks = new ArrayList<DfsPackFile>(packs.length);
long mostRecentGC = mostRecentGC(packs);
- long now = System.currentTimeMillis();
+ long now = SystemReader.getInstance().getCurrentTime();
for (DfsPackFile p : packs) {
DfsPackDescription d = p.getPackDescription();
if (d.getPackSource() != UNREACHABLE_GARBAGE) {
packsBefore.add(p);
} else if (packIsExpiredGarbage(d, mostRecentGC, now)) {
expiredGarbagePacks.add(p);
- } else if (d.getFileSize(PackExt.PACK) < coalesceGarbageLimit) {
+ } else if (packIsCoalesceableGarbage(d, now)) {
packsBefore.add(p);
}
}
@@ -360,6 +358,68 @@ public class DfsGarbageCollector {
&& now - d.getLastModified() >= garbageTtlMillis;
}
+ private boolean packIsCoalesceableGarbage(DfsPackDescription d, long now) {
+ // An UNREACHABLE_GARBAGE pack can be coalesced if its size is less than
+ // the coalesceGarbageLimit and either garbageTtl is zero or if the pack
+ // is created in a close time interval (on a single calendar day when
+ // the garbageTtl is more than one day or one third of the garbageTtl).
+ //
+ // When the garbageTtl is more than 24 hours, garbage packs that are
+ // created within a single calendar day are coalesced together. This
+ // would make the effective ttl of the garbage pack as garbageTtl+23:59
+ // and limit the number of garbage to a maximum number of
+ // garbageTtl_in_days + 1 (assuming all of them are less than the size
+ // of coalesceGarbageLimit).
+ //
+ // When the garbageTtl is less than or equal to 24 hours, garbage packs
+ // that are created within a one third of garbageTtl are coalesced
+ // together. This would make the effective ttl of the garbage packs as
+ // garbageTtl + (garbageTtl / 3) and would limit the number of garbage
+ // packs to a maximum number of 4 (assuming all of them are less than
+ // the size of coalesceGarbageLimit).
+
+ if (d.getPackSource() != UNREACHABLE_GARBAGE
+ || d.getFileSize(PackExt.PACK) >= coalesceGarbageLimit) {
+ return false;
+ }
+
+ if (garbageTtlMillis == 0) {
+ return true;
+ }
+
+ long lastModified = d.getLastModified();
+ long dayStartLastModified = dayStartInMillis(lastModified);
+ long dayStartToday = dayStartInMillis(now);
+
+ if (dayStartLastModified != dayStartToday) {
+ return false; // this pack is not created today.
+ }
+
+ if (garbageTtlMillis > TimeUnit.DAYS.toMillis(1)) {
+ return true; // ttl is more than one day and pack is created today.
+ }
+
+ long timeInterval = garbageTtlMillis / 3;
+ if (timeInterval == 0) {
+ return false; // ttl is too small, don't try to coalesce.
+ }
+
+ long modifiedTimeSlot = (lastModified - dayStartLastModified) / timeInterval;
+ long presentTimeSlot = (now - dayStartToday) / timeInterval;
+ return modifiedTimeSlot == presentTimeSlot;
+ }
+
+ private static long dayStartInMillis(long timeInMillis) {
+ Calendar cal = new GregorianCalendar(
+ SystemReader.getInstance().getTimeZone());
+ cal.setTimeInMillis(timeInMillis);
+ cal.set(Calendar.HOUR_OF_DAY, 0);
+ cal.set(Calendar.MINUTE, 0);
+ cal.set(Calendar.SECOND, 0);
+ cal.set(Calendar.MILLISECOND, 0);
+ return cal.getTimeInMillis();
+ }
+
/** @return all of the source packs that fed into this compaction. */
public List<DfsPackDescription> getSourcePacks() {
return toPrune();