text: /**
   * Copyright (C) 2009-2013 Barchart, Inc. <http://www.barchart.com/>
   *
   * All rights reserved. Licensed under the OSI BSD License.
   *
   * http://www.opensource.org/licenses/bsd-license.php
   */
  package com.barchart.udt;
  
  import java.lang.reflect.Field;
  
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  /**
   * note: do not change field names; used by JNI
   */
  public class MonitorUDT {
  
  	private static final Logger log = LoggerFactory.getLogger(MonitorUDT.class);
  
  	protected final SocketUDT socketUDT;
  
  	protected MonitorUDT(final SocketUDT socketUDT) {
  		this.socketUDT = socketUDT;
  	}
  
  	// UDT API
  
  	// ### global measurements
  
  	/** time since the UDT entity is started, in milliseconds. */
  	protected volatile long msTimeStamp;
  
  	public long millisSinceStart() {
  		return msTimeStamp;
  	}
  
  	/**
  	 * total number of sent data packets, including retransmissions
  	 */
  	protected volatile long pktSentTotal;
  
  	public long globalSentTotal() {
  		return pktSentTotal;
  	}
  
  	/**
  	 * total number of received packets
  	 */
  	protected volatile long pktRecvTotal;
  
  	public long globalReceivedTotal() {
  		return pktRecvTotal;
  	}
  
  	/**
  	 * total number of lost packets (sender side)
  	 */
  	protected volatile int pktSndLossTotal;
  
  	public int globalSenderLost() {
  		return pktSndLossTotal;
  	}
  
  	/**
  	 * total number of lost packets (receiver side)
  	 */
  	protected volatile int pktRcvLossTotal;
  
  	public int globalReceiverLost() {
  		return pktRcvLossTotal;
  	}
  
  	/**
  	 * total number of retransmitted packets
  	 */
  	protected volatile int pktRetransTotal;
  
  	public int globalRetransmittedTotal() {
  		return pktRetransTotal;
  	}
  
  	/**
  	 * total number of sent ACK packets
  	 */
  	protected volatile int pktSentACKTotal;
  
  	public int globalSentAckTotal() {
  		return pktSentACKTotal;
  	}
  
  	/**
  	 * total number of received ACK packets
  	 */
  	protected volatile int pktRecvACKTotal;
  
  	public int globalReceivedAckTotal() {
  		return pktRecvACKTotal;
  	}
  
  	/**
  	 * total number of sent NAK packets
  	 */
  	protected volatile int pktSentNAKTotal;
  
  	public int globalSentNakTotal() {
  		return pktSentNAKTotal;
  	}
  
  	/**
  	 * total number of received NAK packets
  	 */
  	protected volatile int pktRecvNAKTotal;
  
  	public int globalReceivedNakTotal() {
  		return pktRecvNAKTotal;
  	}
  
  	/**
  	 * total time duration when UDT is sending data (idle time exclusive)
  	 */
  	protected volatile long usSndDurationTotal;
  
  	public long globalMicrosSendDurationTotal() {
  		return usSndDurationTotal;
  	}
  
  	// ### local measurements
  
  	/**
  	 * number of sent data packets, including retransmissions
  	 */
  	protected volatile long pktSent;
  
  	public long localPacketsSent() {
  		return pktSent;
  	}
  
  	/**
  	 * number of received packets
  	 */
  	protected volatile long pktRecv;
  
  	public long localPacketsReceived() {
  		return pktRecv;
  	}
  
  	/**
  	 * number of lost packets (sender side)
  	 */
  	protected volatile int pktSndLoss;
  
  	public int localSenderLost() {
  		return pktSndLoss;
  	}
  
  	/**
  	 * number of lost packets (receiverer side)
  	 */
  	protected volatile int pktRcvLoss;
  
  	public int localReceiverLost() {
  		return pktRcvLoss;
  	}
  
  	/**
  	 * number of retransmitted packets
  	 */
  	protected volatile int pktRetrans;
  
  	public int localRetransmitted() {
  		return pktRetrans;
  	}
  
  	/**
  	 * number of sent ACK packets
  	 */
  	protected volatile int pktSentACK;
  
  	public int localSentAck() {
  		return pktSentACK;
  	}
  
  	/**
  	 * number of received ACK packets
  	 */
  	protected volatile int pktRecvACK;
  
  	public int localReceivedAck() {
  		return pktRecvACK;
  	}
  
  	/**
  	 * number of sent NAK packets
  	 */
  	protected volatile int pktSentNAK;
  
  	public int localSentNak() {
  		return pktSentNAK;
  	}
  
  	/**
  	 * number of received NAK packets
  	 */
  	protected volatile int pktRecvNAK;
  
  	public int localReceivedNak() {
  		return pktRecvNAK;
  	}
  
  	/**
  	 * sending rate in Mb/s
  	 */
  	protected volatile double mbpsSendRate;
  
  	public double mbpsSendRate() {
  		return mbpsSendRate;
  	}
  
  	/**
  	 * receiving rate in Mb/s
  	 */
  	protected volatile double mbpsRecvRate;
  
  	public double mbpsReceiveRate() {
  		return mbpsRecvRate;
  	}
  
  	/**
  	 * busy sending time (i.e., idle time exclusive)
  	 */
  	protected volatile long usSndDuration;
  
  	public long microsSendTime() {
  		return usSndDuration;
  	}
  
  	// ### instant measurements
  
  	/**
  	 * packet sending period, in microseconds
  	 */
  	protected volatile double usPktSndPeriod;
  
  	public double currentSendPeriod() {
  		return usPktSndPeriod;
  	}
  
  	/**
  	 * flow window size, in number of packets
  	 */
  	protected volatile int pktFlowWindow;
  
  	public int currentFlowWindow() {
  		return pktFlowWindow;
  	}
  
  	/**
  	 * congestion window size, in number of packets
  	 */
  	protected volatile int pktCongestionWindow;
  
  	public int currentCongestionWindow() {
  		return pktCongestionWindow;
  	}
  
  	/**
  	 * number of packets on flight
  	 */
  	protected volatile int pktFlightSize;
  
  	public int currentFlightSize() {
  		return pktFlightSize;
  	}
  
  	/**
  	 * RTT, in milliseconds
  	 */
  	protected volatile double msRTT;
  
  	public double currentMillisRTT() {
  		return msRTT;
  	}
  
  	/**
  	 * estimated bandwidth, in Mb/s
  	 */
  	protected volatile double mbpsBandwidth;
  
  	public double currentMbpsBandwidth() {
  		return mbpsBandwidth;
  	}
  
  	/**
  	 * available UDT sender buffer size
  	 */
  	protected volatile int byteAvailSndBuf;
  
  	public int currentAvailableInSender() {
  		return byteAvailSndBuf;
  	}
  
  	/**
  	 * available UDT receiver buffer size
  	 */
  	protected volatile int byteAvailRcvBuf;
  
  	public int currentAvailableInReceiver() {
  		return byteAvailRcvBuf;
  	}
  
  	/**
  	 * current monitor status snapshot for all parameters
  	 */
  	public void appendSnapshot(final StringBuilder text) {
  
  		text.append("\n\t");
  		text.append(String.format("[id: 0x%08x]", socketUDT.id()));
  
  		final Field fieldArray[] = MonitorUDT.class.getDeclaredFields();
  
  		for (final Field field : fieldArray) {
  
  			if (!isNumeric(field)) {
  				continue;
  			}
  
  			try {
  
  				field.setAccessible(true);
  
  				final String fieldName = field.getName();
  				final String fieldValue = field.get(this).toString();
  
  				text.append("\n\t");
  				text.append(fieldName);
  				text.append(" = ");
  				text.append(fieldValue);
  
  			} catch (final Exception e) {
  				log.error("unexpected", e);
  			}
  
  		}
  
  		final double localSendLoss = 100.0 * pktSndLoss / pktSent;
  
  		text.append("\n\t% localSendLoss = ");
  		text.append(localSendLoss);
  
  		final double localReceiveLoss = 100.0 * pktRcvLoss / pktRecv;
  
  		text.append("\n\t% localReceiveLoss = ");
  		text.append(localReceiveLoss);
  
  	}
  
  	protected boolean isNumeric(final Field field) {
  
  		final Class<?> fieledType = field.getType();
  
  		return fieledType == int.class || fieledType == long.class
  				|| fieledType == double.class;
  
  	}
  
  	@Override
  	public String toString() {
  
  		final StringBuilder text = new StringBuilder(1024);
  
  		appendSnapshot(text);
  
  		return text.toString();
  
  	}
  
  }
  