瀏覽代碼

PackWriter: Make want/have actual sets

During parsing these are used with contains(). If they are a List
type, the contains operation is not efficient. Some callers such
as UploadPack often pass a List here, so convert to Set when the
type isn't efficient for contains().

Change-Id: If948ae3bf1f46e756bd2d5db14795e12ba7a6207
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
tags/v1.1.0.201109011030-rc2
Shawn O. Pearce 12 年之前
父節點
當前提交
74333e63b6

+ 15
- 15
org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackWriterTest.java 查看文件

import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.LinkedList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;


import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.junit.JGitTestUtil; import org.eclipse.jgit.junit.JGitTestUtil;


public class PackWriterTest extends SampleDataRepositoryTestCase { public class PackWriterTest extends SampleDataRepositoryTestCase {


private static final List<ObjectId> EMPTY_LIST_OBJECT = Collections
.<ObjectId> emptyList();
private static final Set<ObjectId> EMPTY_SET_OBJECT = Collections
.<ObjectId> emptySet();


private static final List<RevObject> EMPTY_LIST_REVS = Collections private static final List<RevObject> EMPTY_LIST_REVS = Collections
.<RevObject> emptyList(); .<RevObject> emptyList();
*/ */
@Test @Test
public void testWriteEmptyPack1() throws IOException { public void testWriteEmptyPack1() throws IOException {
createVerifyOpenPack(EMPTY_LIST_OBJECT, EMPTY_LIST_OBJECT, false, false);
createVerifyOpenPack(EMPTY_SET_OBJECT, EMPTY_SET_OBJECT, false, false);


assertEquals(0, writer.getObjectCount()); assertEquals(0, writer.getObjectCount());
assertEquals(0, pack.getObjectCount()); assertEquals(0, pack.getObjectCount());
final ObjectId nonExisting = ObjectId final ObjectId nonExisting = ObjectId
.fromString("0000000000000000000000000000000000000001"); .fromString("0000000000000000000000000000000000000001");
try { try {
createVerifyOpenPack(EMPTY_LIST_OBJECT, Collections.nCopies(1,
createVerifyOpenPack(EMPTY_SET_OBJECT, Collections.singleton(
nonExisting), false, false); nonExisting), false, false);
fail("Should have thrown MissingObjectException"); fail("Should have thrown MissingObjectException");
} catch (MissingObjectException x) { } catch (MissingObjectException x) {
public void testIgnoreNonExistingObjects() throws IOException { public void testIgnoreNonExistingObjects() throws IOException {
final ObjectId nonExisting = ObjectId final ObjectId nonExisting = ObjectId
.fromString("0000000000000000000000000000000000000001"); .fromString("0000000000000000000000000000000000000001");
createVerifyOpenPack(EMPTY_LIST_OBJECT, Collections.nCopies(1,
createVerifyOpenPack(EMPTY_SET_OBJECT, Collections.singleton(
nonExisting), false, true); nonExisting), false, true);
// shouldn't throw anything // shouldn't throw anything
} }
// TODO: testWritePackDeltasDepth() // TODO: testWritePackDeltasDepth()


private void writeVerifyPack1() throws IOException { private void writeVerifyPack1() throws IOException {
final LinkedList<ObjectId> interestings = new LinkedList<ObjectId>();
final HashSet<ObjectId> interestings = new HashSet<ObjectId>();
interestings.add(ObjectId interestings.add(ObjectId
.fromString("82c6b885ff600be425b4ea96dee75dca255b69e7")); .fromString("82c6b885ff600be425b4ea96dee75dca255b69e7"));
createVerifyOpenPack(interestings, EMPTY_LIST_OBJECT, false, false);
createVerifyOpenPack(interestings, EMPTY_SET_OBJECT, false, false);


final ObjectId expectedOrder[] = new ObjectId[] { final ObjectId expectedOrder[] = new ObjectId[] {
ObjectId.fromString("82c6b885ff600be425b4ea96dee75dca255b69e7"), ObjectId.fromString("82c6b885ff600be425b4ea96dee75dca255b69e7"),


private void writeVerifyPack2(boolean deltaReuse) throws IOException { private void writeVerifyPack2(boolean deltaReuse) throws IOException {
config.setReuseDeltas(deltaReuse); config.setReuseDeltas(deltaReuse);
final LinkedList<ObjectId> interestings = new LinkedList<ObjectId>();
final HashSet<ObjectId> interestings = new HashSet<ObjectId>();
interestings.add(ObjectId interestings.add(ObjectId
.fromString("82c6b885ff600be425b4ea96dee75dca255b69e7")); .fromString("82c6b885ff600be425b4ea96dee75dca255b69e7"));
final LinkedList<ObjectId> uninterestings = new LinkedList<ObjectId>();
final HashSet<ObjectId> uninterestings = new HashSet<ObjectId>();
uninterestings.add(ObjectId uninterestings.add(ObjectId
.fromString("540a36d136cf413e4b064c2b0e0a4db60f77feab")); .fromString("540a36d136cf413e4b064c2b0e0a4db60f77feab"));
createVerifyOpenPack(interestings, uninterestings, false, false); createVerifyOpenPack(interestings, uninterestings, false, false);
} }


private void writeVerifyPack4(final boolean thin) throws IOException { private void writeVerifyPack4(final boolean thin) throws IOException {
final LinkedList<ObjectId> interestings = new LinkedList<ObjectId>();
final HashSet<ObjectId> interestings = new HashSet<ObjectId>();
interestings.add(ObjectId interestings.add(ObjectId
.fromString("82c6b885ff600be425b4ea96dee75dca255b69e7")); .fromString("82c6b885ff600be425b4ea96dee75dca255b69e7"));
final LinkedList<ObjectId> uninterestings = new LinkedList<ObjectId>();
final HashSet<ObjectId> uninterestings = new HashSet<ObjectId>();
uninterestings.add(ObjectId uninterestings.add(ObjectId
.fromString("c59759f143fb1fe21c197981df75a7ee00290799")); .fromString("c59759f143fb1fe21c197981df75a7ee00290799"));
createVerifyOpenPack(interestings, uninterestings, thin, false); createVerifyOpenPack(interestings, uninterestings, thin, false);
.computeName().name()); .computeName().name());
} }


private void createVerifyOpenPack(final Collection<ObjectId> interestings,
final Collection<ObjectId> uninterestings, final boolean thin,
private void createVerifyOpenPack(final Set<ObjectId> interestings,
final Set<ObjectId> uninterestings, final boolean thin,
final boolean ignoreMissingUninteresting) final boolean ignoreMissingUninteresting)
throws MissingObjectException, IOException { throws MissingObjectException, IOException {
NullProgressMonitor m = NullProgressMonitor.INSTANCE; NullProgressMonitor m = NullProgressMonitor.INSTANCE;

+ 88
- 8
org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackWriter.java 查看文件

* points of graph traversal). * points of graph traversal).
* @throws IOException * @throws IOException
* when some I/O problem occur during reading objects. * when some I/O problem occur during reading objects.
* @deprecated to be removed in 2.0; use the Set version of this method.
*/ */
@Deprecated
public void preparePack(ProgressMonitor countingMonitor, public void preparePack(ProgressMonitor countingMonitor,
final Collection<? extends ObjectId> want, final Collection<? extends ObjectId> want,
final Collection<? extends ObjectId> have) throws IOException { final Collection<? extends ObjectId> have) throws IOException {
ObjectWalk ow = new ObjectWalk(reader);
preparePack(countingMonitor, ow, want, have);
preparePack(countingMonitor, ensureSet(want), ensureSet(have));
} }


/** /**
* points of graph traversal). * points of graph traversal).
* @throws IOException * @throws IOException
* when some I/O problem occur during reading objects. * when some I/O problem occur during reading objects.
* @deprecated to be removed in 2.0; use the Set version of this method.
*/ */
@Deprecated
public void preparePack(ProgressMonitor countingMonitor, public void preparePack(ProgressMonitor countingMonitor,
final ObjectWalk walk, final ObjectWalk walk,
final Collection<? extends ObjectId> interestingObjects, final Collection<? extends ObjectId> interestingObjects,
final Collection<? extends ObjectId> uninterestingObjects) final Collection<? extends ObjectId> uninterestingObjects)
throws IOException { throws IOException {
preparePack(countingMonitor, walk,
ensureSet(interestingObjects),
ensureSet(uninterestingObjects));
}

@SuppressWarnings("unchecked")
private static Set<ObjectId> ensureSet(Collection<? extends ObjectId> objs) {
Set<ObjectId> set;
if (objs instanceof Set<?>)
set = (Set<ObjectId>) objs;
else if (objs == null)
set = Collections.emptySet();
else
set = new HashSet<ObjectId>(objs);
return set;
}

/**
* Prepare the list of objects to be written to the pack stream.
* <p>
* Basing on these 2 sets, another set of objects to put in a pack file is
* created: this set consists of all objects reachable (ancestors) from
* interesting objects, except uninteresting objects and their ancestors.
* This method uses class {@link ObjectWalk} extensively to find out that
* appropriate set of output objects and their optimal order in output pack.
* Order is consistent with general git in-pack rules: sort by object type,
* recency, path and delta-base first.
* </p>
*
* @param countingMonitor
* progress during object enumeration.
* @param want
* collection of objects to be marked as interesting (start
* points of graph traversal).
* @param have
* collection of objects to be marked as uninteresting (end
* points of graph traversal).
* @throws IOException
* when some I/O problem occur during reading objects.
*/
public void preparePack(ProgressMonitor countingMonitor,
Set<? extends ObjectId> want,
Set<? extends ObjectId> have) throws IOException {
ObjectWalk ow = new ObjectWalk(reader);
preparePack(countingMonitor, ow, want, have);
}

/**
* Prepare the list of objects to be written to the pack stream.
* <p>
* Basing on these 2 sets, another set of objects to put in a pack file is
* created: this set consists of all objects reachable (ancestors) from
* interesting objects, except uninteresting objects and their ancestors.
* This method uses class {@link ObjectWalk} extensively to find out that
* appropriate set of output objects and their optimal order in output pack.
* Order is consistent with general git in-pack rules: sort by object type,
* recency, path and delta-base first.
* </p>
*
* @param countingMonitor
* progress during object enumeration.
* @param walk
* ObjectWalk to perform enumeration.
* @param interestingObjects
* collection of objects to be marked as interesting (start
* points of graph traversal).
* @param uninterestingObjects
* collection of objects to be marked as uninteresting (end
* points of graph traversal).
* @throws IOException
* when some I/O problem occur during reading objects.
*/
public void preparePack(ProgressMonitor countingMonitor,
final ObjectWalk walk,
final Set<? extends ObjectId> interestingObjects,
final Set<? extends ObjectId> uninterestingObjects)
throws IOException {
if (countingMonitor == null) if (countingMonitor == null)
countingMonitor = NullProgressMonitor.INSTANCE; countingMonitor = NullProgressMonitor.INSTANCE;
findObjectsToPack(countingMonitor, walk, interestingObjects, findObjectsToPack(countingMonitor, walk, interestingObjects,
/** /**
* Create an index file to match the pack file just written. * Create an index file to match the pack file just written.
* <p> * <p>
* This method can only be invoked after {@link #preparePack(Iterator)} or
* {@link #preparePack(ProgressMonitor, Collection, Collection)} has been
* invoked and completed successfully. Writing a corresponding index is an
* optional feature that not all pack users may require.
* This method can only be invoked after
* {@link #writePack(ProgressMonitor, ProgressMonitor, OutputStream)} has
* been invoked and completed successfully. Writing a corresponding index is
* an optional feature that not all pack users may require.
* *
* @param indexStream * @param indexStream
* output for the index data. Caller is responsible for closing * output for the index data. Caller is responsible for closing
} }


private void findObjectsToPack(final ProgressMonitor countingMonitor, private void findObjectsToPack(final ProgressMonitor countingMonitor,
final ObjectWalk walker, final Collection<? extends ObjectId> want,
Collection<? extends ObjectId> have)
final ObjectWalk walker, final Set<? extends ObjectId> want,
Set<? extends ObjectId> have)
throws MissingObjectException, IOException, throws MissingObjectException, IOException,
IncorrectObjectTypeException { IncorrectObjectTypeException {
final long countingStart = System.currentTimeMillis(); final long countingStart = System.currentTimeMillis();

+ 4
- 4
org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java 查看文件



import java.io.IOException; import java.io.IOException;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set;


import org.eclipse.jgit.JGitText; import org.eclipse.jgit.JGitText;
import org.eclipse.jgit.errors.NoRemoteRepositoryException; import org.eclipse.jgit.errors.NoRemoteRepositoryException;


private void writePack(final Map<String, RemoteRefUpdate> refUpdates, private void writePack(final Map<String, RemoteRefUpdate> refUpdates,
final ProgressMonitor monitor) throws IOException { final ProgressMonitor monitor) throws IOException {
List<ObjectId> remoteObjects = new ArrayList<ObjectId>(getRefs().size());
List<ObjectId> newObjects = new ArrayList<ObjectId>(refUpdates.size());
Set<ObjectId> remoteObjects = new HashSet<ObjectId>();
Set<ObjectId> newObjects = new HashSet<ObjectId>();


final PackWriter writer = new PackWriter(transport.getPackConfig(), final PackWriter writer = new PackWriter(transport.getPackConfig(),
local.newObjectReader()); local.newObjectReader());

+ 2
- 2
org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java 查看文件

private final Set<ObjectId> wantIds = new HashSet<ObjectId>(); private final Set<ObjectId> wantIds = new HashSet<ObjectId>();


/** Objects the client wants to obtain. */ /** Objects the client wants to obtain. */
private final List<RevObject> wantAll = new ArrayList<RevObject>();
private final Set<RevObject> wantAll = new HashSet<RevObject>();


/** Objects on both sides, these don't have to be sent. */ /** Objects on both sides, these don't have to be sent. */
private final List<RevObject> commonBase = new ArrayList<RevObject>();
private final Set<RevObject> commonBase = new HashSet<RevObject>();


/** Commit time of the oldest common commit, in seconds. */ /** Commit time of the oldest common commit, in seconds. */
private int oldestTime; private int oldestTime;

+ 4
- 2
org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkPushConnection.java 查看文件

import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;


import org.eclipse.jgit.JGitText; import org.eclipse.jgit.JGitText;
final PackWriter writer = new PackWriter(transport.getPackConfig(), final PackWriter writer = new PackWriter(transport.getPackConfig(),
local.newObjectReader()); local.newObjectReader());
try { try {
final List<ObjectId> need = new ArrayList<ObjectId>();
final List<ObjectId> have = new ArrayList<ObjectId>();
final Set<ObjectId> need = new HashSet<ObjectId>();
final Set<ObjectId> have = new HashSet<ObjectId>();
for (final RemoteRefUpdate r : updates) for (final RemoteRefUpdate r : updates)
need.add(r.getNewObjectId()); need.add(r.getNewObjectId());
for (final Ref r : getRefs()) { for (final Ref r : getRefs()) {

Loading…
取消
儲存