/*
* This file is part of the Illarion project.
*
* Copyright © 2015 - Illarion e.V.
*
* Illarion is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Illarion is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
package illarion.client.util;
import javax.annotation.Nonnull;
import java.util.Arrays;
/**
* This class is used to measure the performance of the connection to the server.
*
* @author Martin Karing <nitram@illarion.org>
*/
public final class ConnectionPerformanceClock {
/**
* The last time the ping command was handed over to NetComm.
*/
private static long lastSendToNetComm;
/**
* The last time the command was encoded to the network interface.
*/
private static long lastEncode;
/**
* The last measured time the server took to respond to a command.
*/
private static long lastServerTime;
/**
* The last measured time the command required to pass though NetComm, the server and the publishing queue.
*/
private static long lastNetCommTime;
@Nonnull
private static final long[] lastServerTimes = new long[16];
private static final long[] lastNetCommTimes = new long[16];
private static int serverTimesCursor;
private static int netCommTimesCursor;
static {
reset();
}
/**
* Private constructor to prevent instantiation
*/
private ConnectionPerformanceClock(){
}
public static boolean isReadyForNewPing() {
if (lastSendToNetComm == -1) {
return true;
}
return (System.currentTimeMillis() - lastEncode) >= 10000;
}
/**
* Report that the command is just about to be handed over to the network interface.
*/
public static void notifySendToNetComm() {
if (lastSendToNetComm == -1) {
lastSendToNetComm = System.currentTimeMillis();
}
}
/**
* Report that the command is now encoded to the network device and send to the server.
*/
public static void notifyNetCommEncode() {
if (lastEncode == -1) {
lastEncode = System.currentTimeMillis();
}
}
/**
* Report that the command was received from the server and is now decoded.
*/
public static void notifyNetCommDecode() {
long localLastEncode = lastEncode;
lastEncode = -1;
if (localLastEncode > -1) {
lastServerTime = System.currentTimeMillis() - localLastEncode;
lastServerTimes[serverTimesCursor] = lastServerTime;
serverTimesCursor = (serverTimesCursor + 1) % lastServerTimes.length;
}
}
/**
* Report that the command is now published to the client.
*/
public static void notifyPublishToClient() {
long localLastSendToNetComm = lastSendToNetComm;
lastSendToNetComm = -1;
if (localLastSendToNetComm > -1) {
lastNetCommTime = System.currentTimeMillis() - localLastSendToNetComm;
lastNetCommTimes[netCommTimesCursor] = lastServerTime;
netCommTimesCursor = (netCommTimesCursor + 1) % lastNetCommTimes.length;
}
}
/**
* Reset all recoded times.
*/
public static void reset() {
lastSendToNetComm = -1;
lastEncode = -1;
lastServerTime = -1;
lastNetCommTime = -1;
Arrays.fill(lastServerTimes, 0);
Arrays.fill(lastNetCommTimes, 0);
serverTimesCursor = 0;
netCommTimesCursor = 0;
}
/**
* Get the time in milliseconds the server took to respond to the measurement command.
*
* @return the server response time in milliseconds
*/
public static long getServerPing() {
return lastServerTime;
}
/**
* Get the time in milliseconds a command took to pass through NetComm and the server.
*
* @return the total processing time of a command in milliseconds
*/
public static long getNetCommPing() {
return lastNetCommTime;
}
public static long getMaxServerPing() {
long max = 0L;
for (long lastServerTime : lastServerTimes) {
if (lastServerTime > max) {
max = lastServerTime;
}
}
return max;
}
}