diff options
4 files changed, 497 insertions, 0 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java index e31f2412c0..19b6b080da 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java @@ -2057,6 +2057,292 @@ public class PackWriter implements AutoCloseable { return true; } + /** + * Summary of how PackWriter created the pack. + * + * @deprecated Use {@link PackStatistics} instead. + */ + @Deprecated + public static class Statistics { + /** Statistics about a single class of object. */ + public static class ObjectType { + // All requests are forwarded to this object. + private PackStatistics.ObjectType objectType; + + /** + * Wraps an + * {@link org.eclipse.jgit.storage.pack.PackStatistics.ObjectType} + * instance to maintain backwards compatibility with existing API. + * + * @param type + * the wrapped instance + */ + public ObjectType(PackStatistics.ObjectType type) { + objectType = type; + } + + /** + * @return total number of objects output. This total includes the + * value of {@link #getDeltas()}. + */ + public long getObjects() { + return objectType.getObjects(); + } + + /** + * @return total number of deltas output. This may be lower than the + * actual number of deltas if a cached pack was reused. + */ + public long getDeltas() { + return objectType.getDeltas(); + } + + /** + * @return number of objects whose existing representation was + * reused in the output. This count includes + * {@link #getReusedDeltas()}. + */ + public long getReusedObjects() { + return objectType.getReusedObjects(); + } + + /** + * @return number of deltas whose existing representation was reused + * in the output, as their base object was also output or + * was assumed present for a thin pack. This may be lower + * than the actual number of reused deltas if a cached pack + * was reused. + */ + public long getReusedDeltas() { + return objectType.getReusedDeltas(); + } + + /** + * @return total number of bytes written. This size includes the + * object headers as well as the compressed data. This size + * also includes all of {@link #getDeltaBytes()}. + */ + public long getBytes() { + return objectType.getBytes(); + } + + /** + * @return number of delta bytes written. This size includes the + * object headers for the delta objects. + */ + public long getDeltaBytes() { + return objectType.getDeltaBytes(); + } + } + + // All requests are forwarded to this object. + private PackStatistics statistics; + + /** + * Wraps a {@link PackStatistics} object to maintain backwards + * compatibility with existing API. + * + * @param stats + * the wrapped PackStatitics object + */ + public Statistics(PackStatistics stats) { + statistics = stats; + } + + /** + * @return unmodifiable collection of objects to be included in the + * pack. May be null if the pack was hand-crafted in a unit + * test. + */ + public Set<ObjectId> getInterestingObjects() { + return statistics.getInterestingObjects(); + } + + /** + * @return unmodifiable collection of objects that should be excluded + * from the pack, as the peer that will receive the pack already + * has these objects. + */ + public Set<ObjectId> getUninterestingObjects() { + return statistics.getUninterestingObjects(); + } + + /** + * @return unmodifiable collection of the cached packs that were reused + * in the output, if any were selected for reuse. + */ + public Collection<CachedPack> getReusedPacks() { + return statistics.getReusedPacks(); + } + + /** + * @return number of objects in the output pack that went through the + * delta search process in order to find a potential delta base. + */ + public int getDeltaSearchNonEdgeObjects() { + return statistics.getDeltaSearchNonEdgeObjects(); + } + + /** + * @return number of objects in the output pack that went through delta + * base search and found a suitable base. This is a subset of + * {@link #getDeltaSearchNonEdgeObjects()}. + */ + public int getDeltasFound() { + return statistics.getDeltasFound(); + } + + /** + * @return total number of objects output. This total includes the value + * of {@link #getTotalDeltas()}. + */ + public long getTotalObjects() { + return statistics.getTotalObjects(); + } + + /** + * @return the count of objects that needed to be discovered through an + * object walk because they were not found in bitmap indices. + * Returns -1 if no bitmap indices were found. + * + * @since 4.0 + */ + public long getBitmapIndexMisses() { + return statistics.getBitmapIndexMisses(); + } + + /** + * @return total number of deltas output. This may be lower than the + * actual number of deltas if a cached pack was reused. + */ + public long getTotalDeltas() { + return statistics.getTotalDeltas(); + } + + /** + * @return number of objects whose existing representation was reused in + * the output. This count includes {@link #getReusedDeltas()}. + */ + public long getReusedObjects() { + return statistics.getReusedObjects(); + } + + /** + * @return number of deltas whose existing representation was reused in + * the output, as their base object was also output or was + * assumed present for a thin pack. This may be lower than the + * actual number of reused deltas if a cached pack was reused. + */ + public long getReusedDeltas() { + return statistics.getReusedDeltas(); + } + + /** + * @return total number of bytes written. This size includes the pack + * header, trailer, thin pack, and reused cached pack(s). + */ + public long getTotalBytes() { + return statistics.getTotalBytes(); + } + + /** + * @return size of the thin pack in bytes, if a thin pack was generated. + * A thin pack is created when the client already has objects + * and some deltas are created against those objects, or if a + * cached pack is being used and some deltas will reference + * objects in the cached pack. This size does not include the + * pack header or trailer. + */ + public long getThinPackBytes() { + return statistics.getThinPackBytes(); + } + + /** + * @param typeCode + * object type code, e.g. OBJ_COMMIT or OBJ_TREE. + * @return information about this type of object in the pack. + */ + public ObjectType byObjectType(int typeCode) { + return new ObjectType(statistics.byObjectType(typeCode)); + } + + /** @return true if the resulting pack file was a shallow pack. */ + public boolean isShallow() { + return statistics.isShallow(); + } + + /** @return depth (in commits) the pack includes if shallow. */ + public int getDepth() { + return statistics.getDepth(); + } + + /** + * @return time in milliseconds spent enumerating the objects that need + * to be included in the output. This time includes any restarts + * that occur when a cached pack is selected for reuse. + */ + public long getTimeCounting() { + return statistics.getTimeCounting(); + } + + /** + * @return time in milliseconds spent matching existing representations + * against objects that will be transmitted, or that the client + * can be assumed to already have. + */ + public long getTimeSearchingForReuse() { + return statistics.getTimeSearchingForReuse(); + } + + /** + * @return time in milliseconds spent finding the sizes of all objects + * that will enter the delta compression search window. The + * sizes need to be known to better match similar objects + * together and improve delta compression ratios. + */ + public long getTimeSearchingForSizes() { + return statistics.getTimeSearchingForSizes(); + } + + /** + * @return time in milliseconds spent on delta compression. This is + * observed wall-clock time and does not accurately track CPU + * time used when multiple threads were used to perform the + * delta compression. + */ + public long getTimeCompressing() { + return statistics.getTimeCompressing(); + } + + /** + * @return time in milliseconds spent writing the pack output, from + * start of header until end of trailer. The transfer speed can + * be approximated by dividing {@link #getTotalBytes()} by this + * value. + */ + public long getTimeWriting() { + return statistics.getTimeWriting(); + } + + /** @return total time spent processing this pack. */ + public long getTimeTotal() { + return statistics.getTimeTotal(); + } + + /** + * @return get the average output speed in terms of bytes-per-second. + * {@code getTotalBytes() / (getTimeWriting() / 1000.0)}. + */ + public double getTransferRate() { + return statistics.getTransferRate(); + } + + /** @return formatted message string for display to clients. */ + public String getMessage() { + return statistics.getMessage(); + } + } + private class MutableState { /** Estimated size of a single ObjectToPack instance. */ // Assume 64-bit pointers, since this is just an estimate. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java index f9ab56d950..101057fb4f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java @@ -312,6 +312,8 @@ public class UploadPack { private PackStatistics statistics; + private UploadPackLogger logger = UploadPackLogger.NULL; + /** * Create a new pack upload for an open repository. * @@ -584,6 +586,28 @@ public class UploadPack { } /** + * @return the configured logger. + * + * @deprecated Use {@link #getPreUploadHook()}. + */ + @Deprecated + public UploadPackLogger getLogger() { + return logger; + } + + /** + * Set the logger. + * + * @param logger + * the logger instance. If null, no logging occurs. + * @deprecated Use {@link #setPreUploadHook(PreUploadHook)}. + */ + @Deprecated + public void setLogger(UploadPackLogger logger) { + this.logger = logger; + } + + /** * Check whether the client expects a side-band stream. * * @return true if the client has advertised a side-band capability, false @@ -659,6 +683,21 @@ public class UploadPack { * @return statistics about pack output, if a pack was sent. Null if no pack * was sent, such as during the negotation phase of a smart HTTP * connection, or if the client was already up-to-date. + * @since 3.0 + * @deprecated Use {@link #getStatistics()}. + */ + @Deprecated + public PackWriter.Statistics getPackStatistics() { + return statistics == null ? null + : new PackWriter.Statistics(statistics); + } + + /** + * Get the PackWriter's statistics if a pack was sent to the client. + * + * @return statistics about pack output, if a pack was sent. Null if no pack + * was sent, such as during the negotation phase of a smart HTTP + * connection, or if the client was already up-to-date. * @since 4.1 */ public PackStatistics getStatistics() { @@ -1508,6 +1547,7 @@ public class UploadPack { statistics = pw.getStatistics(); if (statistics != null) { postUploadHook.onPostUpload(statistics); + logger.onPackStatistics(new PackWriter.Statistics(statistics)); } pw.close(); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPackLogger.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPackLogger.java new file mode 100644 index 0000000000..85ebecc450 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPackLogger.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2011, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.transport; + +import org.eclipse.jgit.internal.storage.pack.PackWriter; + +/** + * Logs activity that occurred within {@link UploadPack}. + * <p> + * Implementors of the interface are responsible for associating the current + * thread to a particular connection, if they need to also include connection + * information. One method is to use a {@link java.lang.ThreadLocal} to remember + * the connection information before invoking UploadPack. + * + * @deprecated use {@link PostUploadHook} instead + */ +@Deprecated +public interface UploadPackLogger { + /** A simple no-op logger. */ + public static final UploadPackLogger NULL = new UploadPackLogger() { + public void onPackStatistics(PackWriter.Statistics stats) { + // Do nothing. + } + }; + + /** + * Notice to the logger after a pack has been sent. + * + * @param stats + * the statistics after sending a pack to the client. + * @since 3.0 + */ + public void onPackStatistics(PackWriter.Statistics stats); +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPackLoggerChain.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPackLoggerChain.java new file mode 100644 index 0000000000..4ea0319d9c --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPackLoggerChain.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2011, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.transport; + +import java.util.List; + +import org.eclipse.jgit.internal.storage.pack.PackWriter; + +/** + * UploadPackLogger that delegates to a list of other loggers. + * <p> + * loggers are run in the order passed to the constructor. + * + * @deprecated Use {@link PostUploadHookChain} instead. + */ +@Deprecated +public class UploadPackLoggerChain implements UploadPackLogger { + private final UploadPackLogger[] loggers; + private final int count; + + /** + * Create a new logger chaining the given loggers together. + * + * @param loggers + * loggers to execute, in order. + * @return a new logger chain of the given loggers. + */ + public static UploadPackLogger newChain( + List<? extends UploadPackLogger> loggers) { + UploadPackLogger[] newLoggers = new UploadPackLogger[loggers.size()]; + int i = 0; + for (UploadPackLogger logger : loggers) + if (logger != UploadPackLogger.NULL) + newLoggers[i++] = logger; + if (i == 0) + return UploadPackLogger.NULL; + else if (i == 1) + return newLoggers[0]; + else + return new UploadPackLoggerChain(newLoggers, i); + } + + /** + * @since 3.0 + */ + public void onPackStatistics(PackWriter.Statistics stats) { + for (int i = 0; i < count; i++) + loggers[i].onPackStatistics(stats); + } + + private UploadPackLoggerChain(UploadPackLogger[] loggers, int count) { + this.loggers = loggers; + this.count = count; + } +} |