package com.jenjinstudios.server.net;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Implements the update loop in the form of a TimerTask.
* @author Caleb Brinkman
*/
class ServerUpdateTask implements Runnable
{
/** The logger for this class. */
private static final Logger LOGGER = Logger.getLogger(ServerUpdateTask.class.getName());
/** The time in nanoseconds of the last 50 update cycles. */
private final double[] lastCycles;
/** The server for which this loop runs. */
private final TaskedServer server;
/** The start time, in nanoseconds, of the current cycle. */
private volatile long cycleStart = 0;
/** The current cycle number. */
private int cycleNum;
/** The actual average UPS of this server. */
private double averageUPS;
/**
* Construct a new {@code ServerLoop} for the specified server.
* @param server The server for which this server loop works.
*/
@SuppressWarnings("unchecked")
public ServerUpdateTask(TaskedServer server) {
this.server = server;
lastCycles = new double[server.getUps() * 10];
cycleNum = 0;
}
@Override
public void run() {
startNewCycle();
checkForNewClients();
runSynchronizedTasks();
runRepeatedTasks();
runQueuedMessages();
update();
broadcast();
}
private void checkForNewClients() {
try
{
server.checkListenerForClients();
} catch (Exception ex)
{
LOGGER.log(Level.WARNING, "Exception when checking for new clients", ex);
}
}
private void broadcast() {
try
{
server.broadcast();
} catch (Exception ex)
{
LOGGER.log(Level.WARNING, "Exception when broadcasting", ex);
}
}
private void update() {
try
{
server.update();
} catch (Exception ex)
{
LOGGER.log(Level.WARNING, "Exception when updating server", ex);
}
}
private void runQueuedMessages() {
try
{
server.runClientHandlerQueuedMessages();
} catch (Exception ex)
{
LOGGER.log(Level.WARNING, "Exception when executing client messages", ex);
}
}
/** Run the repeated tasks in the server queue. */
private void runRepeatedTasks() {
try
{
server.runRepeatedTasks();
} catch (Exception ex)
{
LOGGER.log(Level.WARNING, "Exception when running repeated tasks.", ex);
}
}
/** Run the synchronized tasks in the server queue. */
private void runSynchronizedTasks() {
try
{
server.runSyncedTasks();
} catch (Exception ex)
{
LOGGER.log(Level.WARNING, "Exception when running repeated tasks.", ex);
}
}
/** Called at the beginning of a new server update cycle. */
private void startNewCycle() {
long oldCycleStart = cycleStart == 0 ? System.currentTimeMillis() - 1000 / server.getUps() : cycleStart;
cycleStart = System.currentTimeMillis();
double cycleLength = (cycleStart - oldCycleStart) / 1000d;
lastCycles[getCycleArrayIndex()] = cycleLength;
cycleNum++;
double total = 0;
for (double l : lastCycles)
{
total += l;
}
averageUPS = (ceilNumCycles() / total);
}
private double ceilNumCycles() {
return cycleNum < 1 || cycleNum > lastCycles.length ?
lastCycles.length : cycleNum;
}
private int getCycleArrayIndex() { return Math.abs(cycleNum) % lastCycles.length; }
double getAverageUPS() { return averageUPS; }
long getCycleStartTime() { return cycleStart; }
}