From 16b8ebf2d1d099ac355767b1b1853ae7bf8854f1 Mon Sep 17 00:00:00 2001 From: Dave Borowitz Date: Thu, 10 Nov 2011 12:49:15 -0800 Subject: [PATCH] Add an object encapsulating the state of a PackWriter Exposes essentially the same state machine to the programmer as is exposed to the client via a ProgressMonitor, using a wrapper around beginTask()/endTask(). Change-Id: Ic3622b4acea65d2b9b3551c668806981fa7293e3 --- .../org/eclipse/jgit/JGitText.properties | 1 + .../src/org/eclipse/jgit/JGitText.java | 1 + .../eclipse/jgit/storage/pack/PackWriter.java | 120 ++++++++++++++++-- 3 files changed, 108 insertions(+), 14 deletions(-) diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties index d017bb7ba..b8cf4e73a 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties @@ -215,6 +215,7 @@ hunkDisconnectedFromFile=Hunk disconnected from file hunkHeaderDoesNotMatchBodyLineCountOf=Hunk header {0} does not match body line count of {1} illegalArgumentNotA=Not {0} illegalCombinationOfArguments=The combination of arguments {0} and {1} is not allowed +illegalPackingPhase=Illegal packing phase {0} illegalStateExists=exists {0} improperlyPaddedBase64Input=Improperly padded Base64 input. inMemoryBufferLimitExceeded=In-memory buffer limit exceeded diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java index ceabe6d38..e64534753 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java @@ -275,6 +275,7 @@ public class JGitText extends TranslationBundle { /***/ public String hunkHeaderDoesNotMatchBodyLineCountOf; /***/ public String illegalArgumentNotA; /***/ public String illegalCombinationOfArguments; + /***/ public String illegalPackingPhase; /***/ public String illegalStateExists; /***/ public String improperlyPaddedBase64Input; /***/ public String inMemoryBufferLimitExceeded; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackWriter.java index ab4083182..12d601f10 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackWriter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackWriter.java @@ -174,6 +174,8 @@ public class PackWriter { private final Statistics stats; + private final MutableState state; + private Statistics.ObjectType typeStats; private List sortedByName; @@ -266,6 +268,7 @@ public class PackWriter { reuseDeltas = config.isReuseDeltas(); reuseValidate = true; // be paranoid by default stats = new Statistics(); + state = new MutableState(); } /** @@ -744,6 +747,37 @@ public class PackWriter { return sortedByName; } + private void beginPhase(PackingPhase phase, ProgressMonitor monitor, + int cnt) { + state.phase = phase; + String task; + switch (phase) { + case COUNTING: + task = JGitText.get().countingObjects; + break; + case GETTING_SIZES: + task = JGitText.get().searchForSizes; + break; + case FINDING_SOURCES: + task = JGitText.get().searchForReuse; + break; + case COMPRESSING: + task = JGitText.get().compressingObjects; + break; + case WRITING: + task = JGitText.get().writingObjects; + break; + default: + throw new IllegalArgumentException( + MessageFormat.format(JGitText.get().illegalPackingPhase, phase)); + } + monitor.beginTask(task, cnt); + } + + private void endPhase(ProgressMonitor monitor) { + monitor.endTask(); + } + /** * Write the prepared pack to the supplied stream. *

@@ -803,7 +837,7 @@ public class PackWriter { long objCnt = getObjectCount(); stats.totalObjects = objCnt; - writeMonitor.beginTask(JGitText.get().writingObjects, (int) objCnt); + beginPhase(PackingPhase.WRITING, writeMonitor, (int) objCnt); long writeStart = System.currentTimeMillis(); out.writeFileHeader(PACK_VERSION_GENERATED, objCnt); @@ -843,7 +877,7 @@ public class PackWriter { } reader.release(); - writeMonitor.endTask(); + endPhase(writeMonitor); } /** @@ -855,6 +889,11 @@ public class PackWriter { return stats; } + /** @return snapshot of the current state of this PackWriter. */ + public State getState() { + return state.snapshot(); + } + /** Release all resources used by this writer. */ public void release() { reader.release(); @@ -872,7 +911,7 @@ public class PackWriter { cnt += objectsLists[Constants.OBJ_TAG].size(); long start = System.currentTimeMillis(); - monitor.beginTask(JGitText.get().searchForReuse, cnt); + beginPhase(PackingPhase.FINDING_SOURCES, monitor, cnt); if (cnt <= 4096) { // For small object counts, do everything as one list. @@ -897,7 +936,7 @@ public class PackWriter { searchForReuse(monitor, objectsLists[Constants.OBJ_TAG]); } - monitor.endTask(); + endPhase(monitor); stats.timeSearchingForReuse = System.currentTimeMillis() - start; } @@ -944,7 +983,7 @@ public class PackWriter { // abort with an exception if we actually had to have it. // final long sizingStart = System.currentTimeMillis(); - monitor.beginTask(JGitText.get().searchForSizes, cnt); + beginPhase(PackingPhase.GETTING_SIZES, monitor, cnt); AsyncObjectSizeQueue sizeQueue = reader.getObjectSize( Arrays. asList(list).subList(0, cnt), false); try { @@ -989,7 +1028,7 @@ public class PackWriter { } finally { sizeQueue.release(); } - monitor.endTask(); + endPhase(monitor); stats.timeSearchingForSizes = System.currentTimeMillis() - sizingStart; // Sort the objects by path hash so like files are near each other, @@ -1035,9 +1074,9 @@ public class PackWriter { return; final long searchStart = System.currentTimeMillis(); - monitor.beginTask(JGitText.get().compressingObjects, nonEdgeCnt); + beginPhase(PackingPhase.COMPRESSING, monitor, nonEdgeCnt); searchForDeltas(monitor, list, cnt); - monitor.endTask(); + endPhase(monitor); stats.deltaSearchNonEdgeObjects = nonEdgeCnt; stats.timeCompressing = System.currentTimeMillis() - searchStart; @@ -1400,8 +1439,7 @@ public class PackWriter { throws MissingObjectException, IOException, IncorrectObjectTypeException { final long countingStart = System.currentTimeMillis(); - countingMonitor.beginTask(JGitText.get().countingObjects, - ProgressMonitor.UNKNOWN); + beginPhase(PackingPhase.COUNTING, countingMonitor, ProgressMonitor.UNKNOWN); if (have == null) have = Collections.emptySet(); @@ -1447,7 +1485,7 @@ public class PackWriter { cachedPacks.addAll(shortCircuit); for (CachedPack pack : shortCircuit) countingMonitor.update((int) pack.getObjectCount()); - countingMonitor.endTask(); + endPhase(countingMonitor); stats.timeCounting = System.currentTimeMillis() - countingStart; return; } @@ -1537,8 +1575,8 @@ public class PackWriter { wantObjs, haveObjs, pack); commits = new BlockList(); - countingMonitor.endTask(); - countingMonitor.beginTask(JGitText.get().countingObjects, + endPhase(countingMonitor); + beginPhase(PackingPhase.COUNTING, countingMonitor, ProgressMonitor.UNKNOWN); continue; } @@ -1625,7 +1663,7 @@ public class PackWriter { for (CachedPack pack : cachedPacks) countingMonitor.update((int) pack.getObjectCount()); - countingMonitor.endTask(); + endPhase(countingMonitor); stats.timeCounting = System.currentTimeMillis() - countingStart; } @@ -2099,4 +2137,58 @@ public class PackWriter { reusedObjects, reusedDeltas); } } + + private class MutableState { + private volatile PackingPhase phase; + + MutableState() { + phase = PackingPhase.COUNTING; + } + + State snapshot() { + return new State(phase); + } + } + + /** Possible states that a PackWriter can be in. */ + public static enum PackingPhase { + /** Counting objects phase. */ + COUNTING, + + /** Getting sizes phase. */ + GETTING_SIZES, + + /** Finding sources phase. */ + FINDING_SOURCES, + + /** Compressing objects phase. */ + COMPRESSING, + + /** Writing objects phase. */ + WRITING; + } + + /** Summary of the current state of a PackWriter. */ + public class State { + private final PackingPhase phase; + + State(PackingPhase phase) { + this.phase = phase; + } + + /** @return the PackConfig used to build the writer. */ + public PackConfig getConfig() { + return config; + } + + /** @return the current phase of the writer. */ + public PackingPhase getPhase() { + return phase; + } + + @Override + public String toString() { + return "PackWriter.State[" + phase + "]"; + } + } }