diff --git a/src/java/com/threerings/presents/data/ConMgrStats.java b/src/java/com/threerings/presents/data/ConMgrStats.java
index b8dead9a8..a77312999 100644
--- a/src/java/com/threerings/presents/data/ConMgrStats.java
+++ b/src/java/com/threerings/presents/data/ConMgrStats.java
@@ -27,69 +27,49 @@ import com.threerings.io.SimpleStreamableObject;
* Used to track and report stats on the connection manager.
*/
public class ConMgrStats extends SimpleStreamableObject
+ implements Cloneable
{
- /** The current index into the history arrays. */
- public int current;
+ /** The size of the queue of waiting to auth sockets. This is a snapshot at
+ * the time the stats are requested. */
+ public int authQueueSize;
- /** The size of the queue of waiting to auth sockets. */
- public int[] authQueueSize;
+ /** The size of the queue of waiting to die sockets. This is a snapshot at
+ * the time the stats are requested. */
+ public int deathQueueSize;
- /** The size of the queue of waiting to die sockets. */
- public int[] deathQueueSize;
+ /** The outgoing queue size. This is a snapshot at the time the stats are
+ * requested. */
+ public int outQueueSize;
- /** The outgoing queue size. */
- public int[] outQueueSize;
+ /** The overflow queue size. This is a snapshot at the time the stats are
+ * requested. */
+ public int overQueueSize;
- /** The overflow queue size. */
- public int[] overQueueSize;
+ /** The number of connection events since the server started up. */
+ public int connects;
- /** The number of bytes read. */
- public int[] bytesIn;
+ /** The number of disconnection events since the server started up. */
+ public int disconnects;
- /** The number of bytes written. */
- public int[] bytesOut;
+ /** The number of bytes read since the server started up. */
+ public long bytesIn;
- /** The number of messages read. */
- public int[] msgsIn;
+ /** The number of bytes written since the server started up. */
+ public long bytesOut;
- /** The number of messages written. */
- public int[] msgsOut;
+ /** The number of messages read since the server started up. */
+ public int msgsIn;
- /** Creates our historical arrays. */
- public void init ()
+ /** The number of messages written since the server started up. */
+ public int msgsOut;
+
+ @Override // from Objecet
+ public Object clone ()
{
- authQueueSize = new int[SLOTS];
- deathQueueSize = new int[SLOTS];
- outQueueSize = new int[SLOTS];
- overQueueSize = new int[SLOTS];
- bytesIn = new int[SLOTS];
- bytesOut = new int[SLOTS];
- msgsIn = new int[SLOTS];
- msgsOut = new int[SLOTS];
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException cnse) {
+ throw new RuntimeException(cnse);
+ }
}
-
- /** Advances the currently accumulating bucket and clears its
- * previous contents. */
- public void increment ()
- {
- current = (current + 1) % authQueueSize.length;
- authQueueSize[current] = 0;
- deathQueueSize[current] = 0;
- outQueueSize[current] = 0;
- overQueueSize[current] = 0;
- bytesIn[current] = 0;
- bytesOut[current] = 0;
- msgsIn[current] = 0;
- msgsOut[current] = 0;
- }
-
- /**
- * Returns the index of the most recently accumulated stats slot.
- */
- public int mostRecent ()
- {
- return (current + SLOTS - 1) % SLOTS;
- }
-
- protected static final int SLOTS = 60;
}
diff --git a/src/java/com/threerings/presents/server/net/ConnectionManager.java b/src/java/com/threerings/presents/server/net/ConnectionManager.java
index 4cf2d915a..bc7d7deb2 100644
--- a/src/java/com/threerings/presents/server/net/ConnectionManager.java
+++ b/src/java/com/threerings/presents/server/net/ConnectionManager.java
@@ -86,7 +86,7 @@ public class ConnectionManager extends LoopingThread
// create our stats record
_stats = new ConMgrStats();
- _stats.init();
+ _lastStats = new ConMgrStats();
// register as a "state of server" reporter
PresentsServer.registerReporter(this);
@@ -137,25 +137,23 @@ public class ConnectionManager extends LoopingThread
}
/**
- * Returns our current runtime statistics. When the stats are fetched
- * the counters are rolled to the next bucket. 60 buckets are tracked.
- * Note: don't call this method too frequently (more
- * often than once every few seconds or so) as it has to total things
- * up and run a number of synchronized methods.
+ * Returns our current runtime statistics. Note: don't call this
+ * method too frequently as it is synchronized and will contend
+ * with the network I/O thread.
*/
public synchronized ConMgrStats getStats ()
{
// fill in our snapshot values
- _stats.authQueueSize[_stats.current] = _authq.size();
- _stats.deathQueueSize[_stats.current] = _deathq.size();
- _stats.outQueueSize[_stats.current] = _outq.size();
+ _stats.authQueueSize = _authq.size();
+ _stats.deathQueueSize = _deathq.size();
+ _stats.outQueueSize = _outq.size();
if (_oflowqs.size() > 0) {
+ _stats.overQueueSize = 0;
for (OverflowQueue oq : _oflowqs.values()) {
- _stats.overQueueSize[_stats.current] += oq.size();
+ _stats.overQueueSize += oq.size();
}
}
- _stats.increment();
- return _stats;
+ return (ConMgrStats)_stats.clone();
}
/**
@@ -204,21 +202,21 @@ public class ConnectionManager extends LoopingThread
public void appendReport (
StringBuilder report, long now, long sinceLast, boolean reset)
{
- long bytesIn, bytesOut, msgsIn, msgsOut;
- synchronized (this) {
- bytesIn = _bytesIn;
- bytesOut = _bytesOut;
- msgsIn = _msgsIn;
- msgsOut = _msgsOut;
- if (reset) {
- _bytesIn = 0L;
- _bytesOut = 0L;
- _msgsIn = 0;
- _msgsOut = 0;
- }
+ ConMgrStats stats = getStats();
+ int connects = stats.connects - _lastStats.connects;
+ int disconnects = stats.disconnects - _lastStats.disconnects;
+ long bytesIn = stats.bytesIn - _lastStats.bytesIn;
+ long bytesOut = stats.bytesOut - _lastStats.bytesOut;
+ long msgsIn = stats.msgsIn - _lastStats.msgsIn;
+ long msgsOut = stats.msgsOut - _lastStats.msgsOut;
+ if (reset) {
+ _lastStats = stats;
}
report.append("* presents.net.ConnectionManager:\n");
+ report.append("- Network connections: ");
+ report.append(connects).append(" connects, ");
+ report.append(disconnects).append(" disconnects\n");
report.append("- Network input: ");
report.append(bytesIn).append(" bytes, ");
report.append(msgsIn).append(" msgs, ");
@@ -520,12 +518,12 @@ public class ConnectionManager extends LoopingThread
if (got != 0) {
synchronized (this) {
_bytesIn += got;
- _stats.bytesIn[_stats.current] += got;
+ _stats.bytesIn += got;
// we know that the handlers only report having
// read bytes when they have a whole message, so
// we can count thusly
_msgsIn++;
- _stats.msgsIn[_stats.current]++;
+ _stats.msgsIn++;
}
}
@@ -621,8 +619,8 @@ public class ConnectionManager extends LoopingThread
{
_msgsOut += msgs;
_bytesOut += bytes;
- _stats.msgsOut[_stats.current] += msgs;
- _stats.bytesOut[_stats.current] += bytes;
+ _stats.msgsOut += msgs;
+ _stats.bytesOut += bytes;
}
// documentation inherited
@@ -686,6 +684,9 @@ public class ConnectionManager extends LoopingThread
SelectionKey selkey = selchan.register(
_selector, SelectionKey.OP_READ);
_handlers.put(selkey, new AuthingConnection(this, selkey, channel));
+ synchronized (this) {
+ _stats.connects++;
+ }
return;
} catch (IOException ioe) {
@@ -754,6 +755,9 @@ public class ConnectionManager extends LoopingThread
// removed from the Selector when the socket is closed)
_handlers.remove(conn.getSelectionKey());
_oflowqs.remove(conn);
+ synchronized (this) {
+ _stats.disconnects++;
+ }
// let our observers know what's up
notifyObservers(CONNECTION_FAILED, conn, ioe, null);
@@ -914,6 +918,9 @@ public class ConnectionManager extends LoopingThread
/** Our current runtime stats. */
protected ConMgrStats _stats;
+ /** A snapshot of our runtime stats as of our last report. */
+ protected ConMgrStats _lastStats;
+
/** A runnable to execute when the connection manager thread exits. */
protected volatile Runnable _onExit;