diff options
author | Thirumala Reddy Mutchukota <thirumala@google.com> | 2017-02-06 14:08:27 -0800 |
---|---|---|
committer | Thirumala Reddy Mutchukota <thirumala@google.com> | 2017-02-07 20:34:31 -0800 |
commit | 006f4d4d29eecc3d357b442cc76b76fdeff51de0 (patch) | |
tree | 4c7fac77e68025f8bb219e585bdc7b0c179a3d41 /org.eclipse.jgit | |
parent | d4bd09b78daa733933a15733bc6ebbaa0a0485f1 (diff) | |
download | jgit-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.java | 80 |
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(); |