/*
* Copyright (c) 2001-2007 Sun Microsystems, Inc. All rights reserved.
*
* The Sun Project JXTA(TM) Software License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. 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.
*
* 3. The end-user documentation included with the redistribution, if any, must
* include the following acknowledgment: "This product includes software
* developed by Sun Microsystems, Inc. for JXTA(TM) technology."
* Alternately, this acknowledgment may appear in the software itself, if
* and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA" must
* not be used to endorse or promote products derived from this software
* without prior written permission. For written permission, please contact
* Project JXTA at http://www.jxta.org.
*
* 5. Products derived from this software may not be called "JXTA", nor may
* "JXTA" appear in their name, without prior written permission of Sun.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 SUN
* MICROSYSTEMS OR ITS 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.
*
* JXTA is a registered trademark of Sun Microsystems, Inc. in the United
* States and other countries.
*
* Please see the license information page at :
* <http://www.jxta.org/project/www/license.html> for instructions on use of
* the license in source files.
*
* ====================================================================
*
* This software consists of voluntary contributions made by many individuals
* on behalf of Project JXTA. For more information on Project JXTA, please see
* http://www.jxta.org.
*
* This license is based on the BSD license adopted by the Apache Foundation.
*/
package net.jxta.impl.rendezvous.rendezvousMeter;
import net.jxta.document.Element;
import net.jxta.document.TextElement;
import net.jxta.util.documentSerializable.DocumentSerializable;
import net.jxta.util.documentSerializable.DocumentSerializableUtilities;
import net.jxta.util.documentSerializable.DocumentSerializationException;
import java.util.Enumeration;
/**
The Metric corresponding to the state and aggregate information of a Rendezvous Service
**/
public class RendezvousMetric implements DocumentSerializable {
public static final String EDGE = "edge";
public static final String RENDEZVOUS = "rendezvous";
public static final String STOPPED = "stopped"; // but internally represent as null
private String state = null;
private long transitionTime = 0;
private long totalEdgeTime;
private int numEdgeTransitions;
private long totalRendezvousTime;
private long numRendezvousTransitions;
private int numReceivedProcessedLocally;
private int numReceivedRepropagatedInGroup;
private int numReceivedInvalid;
private int numReceivedDead;
private int numReceivedLoopback;
private int numReceivedDuplicate;
private int numPropagated;
private int numFailedPropagating;
private int numRepropagated;
private int numFailedRepropagating;
private int numPropagatedToPeers;
private int numFailedPropagatingToPeers;
private int numPeersPropagatedTo;
private int numPropagatedInGroup;
private int numPropagatedToNeighbors;
private int numFailedPropagatingToNeighbors;
private int numWalks;
private int numFailedWalks;
private int numWalkedToPeers;
private int numFailedWalkToPeers;
private int numPeersWalkedTo;
public RendezvousMetric() {}
public RendezvousMetric(RendezvousMetric prototype) {
if (prototype == null) {
this.state = STOPPED;
} else {
this.state = prototype.state;
this.transitionTime = prototype.transitionTime;
}
}
/** Get the current state (edge, rendezvous or stopped)
* @return RendezvousMetric.EDGE, RendezvousMetric.RENDEZVOUS or RendezvousMetric.STOPPED
**/
public String getState() {
return (state != null) ? state : STOPPED;
}
/** Get the time that it entered the current state
* @return transition time in ms since January 1, 1970, 00:00:00 GMT
**/
public long getTransitionTime() {
return transitionTime;
}
/** Is this Rendezvous currently operating as an Edge **/
public boolean isEdge() {
return (state != null) && state.equals(EDGE);
}
/** Is this Rendezvous currently operating as an Rendezvous */
public boolean isRendezvous() {
return (state != null) && state.equals(RENDEZVOUS);
}
/** Get the time that it began operating as an Edge
* @return time or 0 if it is not currently an Edge
**/
public long getEdgeStartTime() {
return isEdge() ? transitionTime : 0;
}
/** Get the total time it began operating as an Edge.
* <BR><BR>
* <B>Note:</B> This does not include the current time as edge (if it is currently an edge)
* @see #getTotalEdgeTime(long)
* @return time in ms (see note above)
**/
public long getTotalEdgeTime() {
return totalEdgeTime;
}
/** Get the total time it began operating as an Edge. If it is currently operating as
* an edge, then the total time is adjusted to include the time since the transition time
* to an edge until the provided time
* @param adjustmentTime The time of this metric will be adjusted to
* @see #getTotalEdgeTime()
* @return time in ms (see note above)
**/
public long getTotalEdgeTime(long adjustmentTime) {
long result = totalEdgeTime;
if (isEdge()) {
result += (adjustmentTime - this.transitionTime);
}
return result;
}
/** The number of times the peer has become an edge **/
public int getNumEdgeTransitions() {
return numEdgeTransitions;
}
/** Get the time that it began operating as an Rendezvous
* @return time or 0 if it is not currently an Rendezvous
**/
public long getRendezvousStartTime() {
return isRendezvous() ? transitionTime : 0;
}
/** Get the total time it began operating as an Rendezvous.
* <BR><BR>
* <B>Note:</B> This does not include the current time as rendezvous (if it is currently an rendezvous)
* @see #getTotalRendezvousTime(long)
* @return time in ms (see note above)
**/
public long getTotalRendezvousTime() {
return totalRendezvousTime;
}
/** Get the total time it began operating as an Rendezvous. If it is currently operating as
* a rendezvous, then the total time is adjusted to include the time since the transition time
* to an rendezvous until the provided time
* @param adjustmentTime The time of this metric will be adjusted to
* @see #getTotalRendezvousTime()
* @return time in ms (see note above)
**/
public long getTotalRendezvousTime(long adjustmentTime) {
long result = totalRendezvousTime;
if (isRendezvous()) {
result += (adjustmentTime - this.transitionTime);
}
return result;
}
/** The number of times the peer has become an rendezvous **/
public long getNumRendezvousTransitions() {
return numRendezvousTransitions;
}
/** The number of messages received that were sent to local listeners **/
public int getNumReceivedProcessedLocally() {
return numReceivedProcessedLocally;
}
/** The number of messages received that were repropagated to the group **/
public int getNumReceivedRepropagatedInGroup() {
return numReceivedRepropagatedInGroup;
}
/** The number of invalid messages received **/
public int getNumReceivedInvalid() {
return numReceivedInvalid;
}
/** The number of TTL Dead messages received **/
public int getNumReceivedDead() {
return numReceivedDead;
}
/** The number of messages received that originated at peer **/
public int getNumReceivedLoopback() {
return numReceivedLoopback;
}
/** The number of duplicate messages received **/
public int getNumReceivedDuplicate() {
return numReceivedDuplicate;
}
/** The total number of inbound messages to the rendezvous service that could not be delivered**/
public int getTotalReceivedUndelivered() {
return numReceivedInvalid + numReceivedDead + numReceivedLoopback + numReceivedDuplicate;
}
/** The total number of inbound messages to the rendezvous service **/
public int getTotalReceived() {
return getTotalReceivedUndelivered() + numReceivedProcessedLocally + numReceivedRepropagatedInGroup;
}
/** The number of outbound messages propagated **/
public int getNumPropagated() {
return numPropagated;
}
/** The number of outbound messages failed during propagation **/
public int getNumFailedPropagating() {
return numFailedPropagating;
}
/** The number of outbound messages repropagated **/
public int getNumRepropagated() {
return numRepropagated;
}
/** The number of outbound messages failed during repropagation **/
public int getNumFailedRepropagating() {
return numFailedRepropagating;
}
/** The number of outbound messages propagated to peers **/
public int getNumPropagatedToPeers() {
return numPropagatedToPeers;
}
/** The number of outbound messages failed when propagated to peers **/
public int getNumFailedPropagatingToPeers() {
return numFailedPropagatingToPeers;
}
/** The number of peers that outbound messages were propagated to **/
public int getNumPeersPropagatedTo() {
return numPeersPropagatedTo;
}
/** The number of outbound messages propagated in group **/
public int getNumPropagatedInGroup() {
return numPropagatedInGroup;
}
/** The number of outbound messages propagated to neighbors **/
public int getNumPropagatedToNeighbors() {
return numPropagatedToNeighbors;
}
/** The number of outbound messages failed when propagated to neighbors **/
public int getNumFailedPropagatingToNeighbors() {
return numFailedPropagatingToNeighbors;
}
/** The number of outbound messages walked **/
public int getNumWalks() {
return numWalks;
}
/** The number of outbound messages failed attempting walk **/
public int getNumFailedWalks() {
return numFailedWalks;
}
/** The number of outbound messages walked to a set of peers **/
public int getNumWalkedToPeers() {
return numWalkedToPeers;
}
/** The number of outbound messages failed in an attempt to walk to a set of peers **/
public int getNumFailedWalkToPeers() {
return numFailedWalkToPeers;
}
/** The number of peers that outbound messages were walked to **/
public int getNumPeersWalkedTo() {
return numPeersWalkedTo;
}
/** Get the duration of current transition to an edge
* <BR><BR>
* <B>Note:</B> This assumes the clocks are in sync with the reporting peer
* @see #getTimeAsEdge(long)
* @return time in ms (see note above) or 0 if not edge
**/
public long getTimeAsEdge() {
return getTimeAsEdge(System.currentTimeMillis());
}
/** Get the duration of time became an edge until the specified time
* @param adjustmentTime The time of this metric will be computed until
* @see #getTimeAsEdge()
* @return time in ms (see note above) or 0 if not connected
**/
public long getTimeAsEdge(long adjustmentTime) {
if (isEdge()) {
return (adjustmentTime - this.transitionTime);
} else {
return 0;
}
}
/** Get the duration of current transition to a rendezvous
* <BR><BR>
* <B>Note:</B> This assumes the clocks are in sync with the reporting peer
* @see #getTimeAsRendezvous(long)
* @return time in ms (see note above) or 0 if not edge
**/
public long getTimeAsRendezvous() {
return getTimeAsRendezvous(System.currentTimeMillis());
}
/** Get the duration of time became an rendezvous until the specified time
* @param adjustmentTime The time of this metric will be computed until
* @see #getTimeAsRendezvous()
* @return time in ms (see note above) or 0 if not connected
**/
public long getTimeAsRendezvous(long adjustmentTime) {
if (isRendezvous()) {
return (adjustmentTime - this.transitionTime);
} else {
return 0;
}
}
void startEdge(long transitionTime) {
this.transitionTime = transitionTime;
this.state = EDGE;
this.numEdgeTransitions++;
}
void stopEdge(long transitionTime, long timeAsEdge) {
this.state = STOPPED;
this.transitionTime = transitionTime;
this.totalEdgeTime += timeAsEdge;
}
void startRendezvous(long transitionTime) {
this.state = RENDEZVOUS;
this.transitionTime = transitionTime;
this.numRendezvousTransitions++;
}
void stopRendezvous(long transitionTime, long timeAsRendezvous) {
this.state = STOPPED;
this.transitionTime = transitionTime;
this.totalRendezvousTime += timeAsRendezvous;
}
void invalidMessageReceived() {
numReceivedInvalid++;
}
void receivedMessageProcessedLocally() {
numReceivedProcessedLocally++;
}
void receivedMessageRepropagatedInGroup() {
numReceivedRepropagatedInGroup++;
}
void receivedDeadMessage() {
numReceivedDead++;
}
void receivedLoopbackMessage() {
numReceivedLoopback++;
}
void receivedDuplicateMessage() {
numReceivedDuplicate++;
}
void propagateToPeers(int numPeers) {
numPropagatedToPeers++;
numPeersPropagatedTo += numPeers;
}
void propagateToNeighbors() {
numPropagatedToNeighbors++;
}
void propagateToNeighborsFailed() {
numFailedPropagatingToNeighbors++;
}
void propagateToGroup() {
numPropagatedInGroup++;
}
void walk() {
numWalks++;
}
void walkFailed() {
numFailedWalks++;
}
void walkToPeers(int numPeers) {
numWalkedToPeers++;
numPeersWalkedTo += numPeers;
}
void walkToPeersFailed() {
numFailedWalkToPeers++;
}
public void mergeMetrics(RendezvousMetric otherRendezvousMetric) {
if (otherRendezvousMetric == null) {
return;
}
if (otherRendezvousMetric.state != null) {
state = otherRendezvousMetric.state;
}
if (otherRendezvousMetric.transitionTime != 0) {
transitionTime = otherRendezvousMetric.transitionTime;
}
this.totalEdgeTime += otherRendezvousMetric.totalEdgeTime;
this.numEdgeTransitions += otherRendezvousMetric.numEdgeTransitions;
this.totalRendezvousTime += otherRendezvousMetric.totalRendezvousTime;
this.numRendezvousTransitions += otherRendezvousMetric.numRendezvousTransitions;
this.numReceivedProcessedLocally += otherRendezvousMetric.numReceivedProcessedLocally;
this.numReceivedRepropagatedInGroup += otherRendezvousMetric.numReceivedRepropagatedInGroup;
this.numReceivedInvalid += otherRendezvousMetric.numReceivedInvalid;
this.numReceivedDead += otherRendezvousMetric.numReceivedDead;
this.numReceivedLoopback += otherRendezvousMetric.numReceivedLoopback;
this.numReceivedDuplicate += otherRendezvousMetric.numReceivedDuplicate;
this.numPropagated += otherRendezvousMetric.numPropagated;
this.numFailedPropagating += otherRendezvousMetric.numFailedPropagating;
this.numRepropagated += otherRendezvousMetric.numRepropagated;
this.numFailedRepropagating += otherRendezvousMetric.numFailedRepropagating;
this.numPropagatedToPeers += otherRendezvousMetric.numPropagatedToPeers;
this.numFailedPropagatingToPeers += otherRendezvousMetric.numFailedPropagatingToPeers;
this.numPeersPropagatedTo += otherRendezvousMetric.numPeersPropagatedTo;
this.numPropagatedInGroup += otherRendezvousMetric.numPropagatedInGroup;
this.numPropagatedToNeighbors += otherRendezvousMetric.numPropagatedToNeighbors;
this.numFailedPropagatingToNeighbors += otherRendezvousMetric.numFailedPropagatingToNeighbors;
this.numWalks += otherRendezvousMetric.numWalks;
this.numFailedWalks += otherRendezvousMetric.numFailedWalks;
this.numWalkedToPeers += otherRendezvousMetric.numWalkedToPeers;
this.numFailedWalkToPeers += otherRendezvousMetric.numFailedWalkToPeers;
this.numPeersWalkedTo += otherRendezvousMetric.numPeersWalkedTo;
}
public void serializeTo(Element element) throws DocumentSerializationException {
if (state != null) {
DocumentSerializableUtilities.addString(element, "state", state);
}
if (transitionTime != 0) {
DocumentSerializableUtilities.addLong(element, "transitionTime", transitionTime);
}
if (totalEdgeTime != 0) {
DocumentSerializableUtilities.addLong(element, "totalEdgeTime", totalEdgeTime);
}
if (numEdgeTransitions != 0) {
DocumentSerializableUtilities.addInt(element, "numEdgeTransitions", numEdgeTransitions);
}
if (totalRendezvousTime != 0) {
DocumentSerializableUtilities.addLong(element, "totalRendezvousTime", totalRendezvousTime);
}
if (numRendezvousTransitions != 0) {
DocumentSerializableUtilities.addLong(element, "numRendezvousTransitions", numRendezvousTransitions);
}
if (numReceivedProcessedLocally != 0) {
DocumentSerializableUtilities.addInt(element, "numReceivedProcessedLocally", numReceivedProcessedLocally);
}
if (numReceivedRepropagatedInGroup != 0) {
DocumentSerializableUtilities.addInt(element, "numReceivedRepropagatedInGroup", numReceivedRepropagatedInGroup);
}
if (numReceivedInvalid != 0) {
DocumentSerializableUtilities.addInt(element, "numReceivedInvalid", numReceivedInvalid);
}
if (numReceivedDead != 0) {
DocumentSerializableUtilities.addInt(element, "numReceivedDead", numReceivedDead);
}
if (numReceivedLoopback != 0) {
DocumentSerializableUtilities.addInt(element, "numReceivedLoopback", numReceivedLoopback);
}
if (numReceivedDuplicate != 0) {
DocumentSerializableUtilities.addInt(element, "numReceivedDuplicate", numReceivedDuplicate);
}
if (numPropagated != 0) {
DocumentSerializableUtilities.addInt(element, "numPropagated", numPropagated);
}
if (numFailedPropagating != 0) {
DocumentSerializableUtilities.addInt(element, "numFailedPropagating", numFailedPropagating);
}
if (numRepropagated != 0) {
DocumentSerializableUtilities.addInt(element, "numRepropagated", numRepropagated);
}
if (numFailedRepropagating != 0) {
DocumentSerializableUtilities.addInt(element, "numFailedRepropagating", numFailedRepropagating);
}
if (numPropagatedToPeers != 0) {
DocumentSerializableUtilities.addInt(element, "numPropagatedToPeers", numPropagatedToPeers);
}
if (numFailedPropagatingToPeers != 0) {
DocumentSerializableUtilities.addInt(element, "numFailedPropagatingToPeers", numFailedPropagatingToPeers);
}
if (numPeersPropagatedTo != 0) {
DocumentSerializableUtilities.addInt(element, "numPeersPropagatedTo", numPeersPropagatedTo);
}
if (numPropagatedInGroup != 0) {
DocumentSerializableUtilities.addInt(element, "numPropagatedInGroup", numPropagatedInGroup);
}
if (numPropagatedToNeighbors != 0) {
DocumentSerializableUtilities.addInt(element, "numPropagatedToNeighbors", numPropagatedToNeighbors);
}
if (numFailedPropagatingToNeighbors != 0) {
DocumentSerializableUtilities.addInt(element, "numFailedPropagatingToNeighbors", numFailedPropagatingToNeighbors);
}
if (numWalks != 0) {
DocumentSerializableUtilities.addInt(element, "numWalks", numWalks);
}
if (numFailedWalks != 0) {
DocumentSerializableUtilities.addInt(element, "numFailedWalks", numFailedWalks);
}
if (numWalkedToPeers != 0) {
DocumentSerializableUtilities.addInt(element, "numWalkedToPeers", numWalkedToPeers);
}
if (numFailedWalkToPeers != 0) {
DocumentSerializableUtilities.addInt(element, "numFailedWalkToPeers", numFailedWalkToPeers);
}
if (numPeersWalkedTo != 0) {
DocumentSerializableUtilities.addInt(element, "numPeersWalkedTo", numPeersWalkedTo);
}
}
public void initializeFrom(Element element) throws DocumentSerializationException {
for (Enumeration e = element.getChildren(); e.hasMoreElements();) {
Element childElement = (TextElement) e.nextElement();
String tagName = (String) childElement.getKey();
if (tagName.equals("state")) {
state = DocumentSerializableUtilities.getString(childElement);
} else if (tagName.equals("transitionTime")) {
transitionTime = DocumentSerializableUtilities.getLong(childElement);
} else if (tagName.equals("totalEdgeTime")) {
totalEdgeTime = DocumentSerializableUtilities.getLong(childElement);
} else if (tagName.equals("numEdgeTransitions")) {
numEdgeTransitions = DocumentSerializableUtilities.getInt(childElement);
} else if (tagName.equals("totalRendezvousTime")) {
totalRendezvousTime = DocumentSerializableUtilities.getLong(childElement);
} else if (tagName.equals("numRendezvousTransitions")) {
numRendezvousTransitions = DocumentSerializableUtilities.getLong(childElement);
} else if (tagName.equals("numReceivedProcessedLocally")) {
numReceivedProcessedLocally = DocumentSerializableUtilities.getInt(childElement);
} else if (tagName.equals("numReceivedRepropagatedInGroup")) {
numReceivedRepropagatedInGroup = DocumentSerializableUtilities.getInt(childElement);
} else if (tagName.equals("numReceivedInvalid")) {
numReceivedInvalid = DocumentSerializableUtilities.getInt(childElement);
} else if (tagName.equals("numReceivedDead")) {
numReceivedDead = DocumentSerializableUtilities.getInt(childElement);
} else if (tagName.equals("numReceivedLoopback")) {
numReceivedLoopback = DocumentSerializableUtilities.getInt(childElement);
} else if (tagName.equals("numReceivedDuplicate")) {
numReceivedDuplicate = DocumentSerializableUtilities.getInt(childElement);
} else if (tagName.equals("numPropagated")) {
numPropagated = DocumentSerializableUtilities.getInt(childElement);
} else if (tagName.equals("numFailedPropagating")) {
numFailedPropagating = DocumentSerializableUtilities.getInt(childElement);
} else if (tagName.equals("numRepropagated")) {
numRepropagated = DocumentSerializableUtilities.getInt(childElement);
} else if (tagName.equals("numFailedRepropagating")) {
numFailedRepropagating = DocumentSerializableUtilities.getInt(childElement);
} else if (tagName.equals("numPropagatedToPeers")) {
numPropagatedToPeers = DocumentSerializableUtilities.getInt(childElement);
} else if (tagName.equals("numFailedPropagatingToPeers")) {
numFailedPropagatingToPeers = DocumentSerializableUtilities.getInt(childElement);
} else if (tagName.equals("numPeersPropagatedTo")) {
numPeersPropagatedTo = DocumentSerializableUtilities.getInt(childElement);
} else if (tagName.equals("numPropagatedInGroup")) {
numPropagatedInGroup = DocumentSerializableUtilities.getInt(childElement);
} else if (tagName.equals("numPropagatedToNeighbors")) {
numPropagatedToNeighbors = DocumentSerializableUtilities.getInt(childElement);
} else if (tagName.equals("numFailedPropagatingToNeighbors")) {
numFailedPropagatingToNeighbors = DocumentSerializableUtilities.getInt(childElement);
} else if (tagName.equals("numWalks")) {
numWalks = DocumentSerializableUtilities.getInt(childElement);
} else if (tagName.equals("numFailedWalks")) {
numFailedWalks = DocumentSerializableUtilities.getInt(childElement);
} else if (tagName.equals("numWalkedToPeers")) {
numWalkedToPeers = DocumentSerializableUtilities.getInt(childElement);
} else if (tagName.equals("numFailedWalkToPeers")) {
numFailedWalkToPeers = DocumentSerializableUtilities.getInt(childElement);
} else if (tagName.equals("numPeersWalkedTo")) {
numPeersWalkedTo = DocumentSerializableUtilities.getInt(childElement);
}
}
}
}