Author: nextgens
Date: 2007-06-01 20:51:27 +0000 (Fri, 01 Jun 2007)
New Revision: 13462

Added:
   trunk/freenet/src/freenet/node/useralerts/TimeSkewDetectedUserAlert.java
Modified:
   trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties
   trunk/freenet/src/freenet/node/Node.java
   trunk/freenet/src/freenet/node/NodePinger.java
   trunk/freenet/src/freenet/node/NodeStats.java
   trunk/freenet/src/freenet/node/PeerNode.java
   trunk/freenet/src/freenet/support/math/TimeDecayingRunningAverage.java
Log:
Implement a TimeSkewDetectedUserAlert... the code hasn't been tested yet

Modified: trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties
===================================================================
--- trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties   2007-06-01 
20:44:14 UTC (rev 13461)
+++ trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties   2007-06-01 
20:51:27 UTC (rev 13462)
@@ -795,6 +795,8 @@
 TextModeClientInterfaceServer.enabledLong=Whether to enable the TMCI
 TextModeClientInterfaceServer.telnetPortNumber=Telnet port
 TextModeClientInterfaceServer.telnetPortNumberLong=Telnet port number
+TimeSkewDetectedUserAlert.title=Time skew detected!
+TimeSkewDetectedUserAlert.text=A time skew has been detected by the node. 
That's VERY bad. Your node won't perform correctly until it's fixed; Common 
causes are missconfigured powersafe mode, network time synchronization clients 
or buggy hardware.
 Toadlet.yes=Yes
 Toadlet.no=No
 Toadlet.cancel=Cancel

Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java    2007-06-01 20:44:14 UTC (rev 
13461)
+++ trunk/freenet/src/freenet/node/Node.java    2007-06-01 20:51:27 UTC (rev 
13462)
@@ -88,7 +88,7 @@
 import freenet.node.useralerts.BuildOldAgeUserAlert;
 import freenet.node.useralerts.ExtOldAgeUserAlert;
 import freenet.node.useralerts.MeaningfulNodeNameUserAlert;
-import freenet.node.useralerts.N2NTMUserAlert;
+import freenet.node.useralerts.TimeSkewDetectedUserAlert;
 import freenet.node.useralerts.UserAlert;
 import freenet.pluginmanager.PluginManager;
 import freenet.store.BerkeleyDBFreenetStore;
@@ -145,6 +145,7 @@

        private static MeaningfulNodeNameUserAlert nodeNameUserAlert;
        private static BuildOldAgeUserAlert buildOldAgeUserAlert;
+       private static TimeSkewDetectedUserAlert timeSkewDetectedUserAlert;

        public class NodeNameCallback implements StringCallback{
                        Node node;
@@ -2878,5 +2879,11 @@
        DSASignature sign(byte[] hash) {
                return DSA.sign(myCryptoGroup, myPrivKey, new 
NativeBigInteger(1, hash), random);
        }
-
+       
+       public synchronized void setTimeSkewDetectedUserAlert() {
+               if(timeSkewDetectedUserAlert == null) {
+                       timeSkewDetectedUserAlert = new 
TimeSkewDetectedUserAlert();
+                       clientCore.alerts.register(timeSkewDetectedUserAlert);
+               }
+       }
 }

Modified: trunk/freenet/src/freenet/node/NodePinger.java
===================================================================
--- trunk/freenet/src/freenet/node/NodePinger.java      2007-06-01 20:44:14 UTC 
(rev 13461)
+++ trunk/freenet/src/freenet/node/NodePinger.java      2007-06-01 20:51:27 UTC 
(rev 13462)
@@ -22,7 +22,7 @@
        NodePinger(Node n) {
                this.node = n;
                this.tdra = new TimeDecayingRunningAverage(0.0, 30*1000, // 30 
seconds
-                               0.0, CRAZY_MAX_PING_TIME);
+                               0.0, CRAZY_MAX_PING_TIME, node);
        }

        void start() {

Modified: trunk/freenet/src/freenet/node/NodeStats.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeStats.java       2007-06-01 20:44:14 UTC 
(rev 13461)
+++ trunk/freenet/src/freenet/node/NodeStats.java       2007-06-01 20:51:27 UTC 
(rev 13462)
@@ -136,8 +136,8 @@
        final TokenBucket requestInputThrottle;

        // various metrics
-       public RunningAverage routingMissDistance = new 
TimeDecayingRunningAverage(0.0, 180000, 0.0, 1.0);
-       public RunningAverage backedOffPercent = new 
TimeDecayingRunningAverage(0.0, 180000, 0.0, 1.0);
+       public final RunningAverage routingMissDistance;
+       public final RunningAverage backedOffPercent;
        protected final Persister persister;

        // ThreadCounting stuffs
@@ -167,13 +167,15 @@
                this.node = node;
                this.peers = node.peers;
                this.hardRandom = node.random;
+               this.routingMissDistance = new TimeDecayingRunningAverage(0.0, 
180000, 0.0, 1.0, node);
+               this.backedOffPercent = new TimeDecayingRunningAverage(0.0, 
180000, 0.0, 1.0, node);
                preemptiveRejectReasons = new StringCounter();
-               pInstantRejectIncoming = new TimeDecayingRunningAverage(0, 
60000, 0.0, 1.0);
+               pInstantRejectIncoming = new TimeDecayingRunningAverage(0, 
60000, 0.0, 1.0, node);
                ThreadGroup tg = Thread.currentThread().getThreadGroup();
                while(tg.getParent() != null) tg = tg.getParent();
                this.rootThreadGroup = tg;
                throttledPacketSendAverage =
-                       new TimeDecayingRunningAverage(1, 10*60*1000 /* should 
be significantly longer than a typical transfer */, 0, Long.MAX_VALUE);
+                       new TimeDecayingRunningAverage(1, 10*60*1000 /* should 
be significantly longer than a typical transfer */, 0, Long.MAX_VALUE, node);
                nodePinger = new NodePinger(node);

                previous_input_stat = 0;
@@ -269,32 +271,32 @@
                if(logMINOR) Logger.minor(this, "Read 
throttleFS:\n"+throttleFS);

                // Guesstimates. Hopefully well over the reality.
-               localChkFetchBytesSentAverage = new 
TimeDecayingRunningAverage(500, 180000, 0.0, 1024*1024*1024, throttleFS == null 
? null : throttleFS.subset("LocalChkFetchBytesSentAverage"));
-               localSskFetchBytesSentAverage = new 
TimeDecayingRunningAverage(500, 180000, 0.0, 1024*1024*1024, throttleFS == null 
? null : throttleFS.subset("LocalSskFetchBytesSentAverage"));
-               localChkInsertBytesSentAverage = new 
TimeDecayingRunningAverage(32768, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("LocalChkInsertBytesSentAverage"));
-               localSskInsertBytesSentAverage = new 
TimeDecayingRunningAverage(2048, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("LocalSskInsertBytesSentAverage"));
-               localChkFetchBytesReceivedAverage = new 
TimeDecayingRunningAverage(32768, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("LocalChkFetchBytesReceivedAverage"));
-               localSskFetchBytesReceivedAverage = new 
TimeDecayingRunningAverage(2048, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("LocalSskFetchBytesReceivedAverage"));
-               localChkInsertBytesReceivedAverage = new 
TimeDecayingRunningAverage(1024, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("LocalChkInsertBytesReceivedAverage"));
-               localSskInsertBytesReceivedAverage = new 
TimeDecayingRunningAverage(500, 180000, 0.0, 1024*1024*1024, throttleFS == null 
? null : throttleFS.subset("LocalChkInsertBytesReceivedAverage"));
+               localChkFetchBytesSentAverage = new 
TimeDecayingRunningAverage(500, 180000, 0.0, 1024*1024*1024, throttleFS == null 
? null : throttleFS.subset("LocalChkFetchBytesSentAverage"), node);
+               localSskFetchBytesSentAverage = new 
TimeDecayingRunningAverage(500, 180000, 0.0, 1024*1024*1024, throttleFS == null 
? null : throttleFS.subset("LocalSskFetchBytesSentAverage"), node);
+               localChkInsertBytesSentAverage = new 
TimeDecayingRunningAverage(32768, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("LocalChkInsertBytesSentAverage"), node);
+               localSskInsertBytesSentAverage = new 
TimeDecayingRunningAverage(2048, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("LocalSskInsertBytesSentAverage"), node);
+               localChkFetchBytesReceivedAverage = new 
TimeDecayingRunningAverage(32768, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("LocalChkFetchBytesReceivedAverage"), node);
+               localSskFetchBytesReceivedAverage = new 
TimeDecayingRunningAverage(2048, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("LocalSskFetchBytesReceivedAverage"), node);
+               localChkInsertBytesReceivedAverage = new 
TimeDecayingRunningAverage(1024, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("LocalChkInsertBytesReceivedAverage"), node);
+               localSskInsertBytesReceivedAverage = new 
TimeDecayingRunningAverage(500, 180000, 0.0, 1024*1024*1024, throttleFS == null 
? null : throttleFS.subset("LocalChkInsertBytesReceivedAverage"), node);

-               remoteChkFetchBytesSentAverage = new 
TimeDecayingRunningAverage(32768+1024+500, 180000, 0.0, 1024*1024*1024, 
throttleFS == null ? null : 
throttleFS.subset("RemoteChkFetchBytesSentAverage"));
-               remoteSskFetchBytesSentAverage = new 
TimeDecayingRunningAverage(1024+1024+500, 180000, 0.0, 1024*1024*1024, 
throttleFS == null ? null : 
throttleFS.subset("RemoteSskFetchBytesSentAverage"));
-               remoteChkInsertBytesSentAverage = new 
TimeDecayingRunningAverage(32768+32768+1024, 180000, 0.0, 1024*1024*1024, 
throttleFS == null ? null : 
throttleFS.subset("RemoteChkInsertBytesSentAverage"));
-               remoteSskInsertBytesSentAverage = new 
TimeDecayingRunningAverage(1024+1024+500, 180000, 0.0, 1024*1024*1024, 
throttleFS == null ? null : 
throttleFS.subset("RemoteSskInsertBytesSentAverage"));
-               remoteChkFetchBytesReceivedAverage = new 
TimeDecayingRunningAverage(32768+1024+500, 180000, 0.0, 1024*1024*1024, 
throttleFS == null ? null : 
throttleFS.subset("RemoteChkFetchBytesReceivedAverage"));
-               remoteSskFetchBytesReceivedAverage = new 
TimeDecayingRunningAverage(2048+500, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("RemoteSskFetchBytesReceivedAverage"));
-               remoteChkInsertBytesReceivedAverage = new 
TimeDecayingRunningAverage(32768+1024+500, 180000, 0.0, 1024*1024*1024, 
throttleFS == null ? null : 
throttleFS.subset("RemoteChkInsertBytesReceivedAverage"));
-               remoteSskInsertBytesReceivedAverage = new 
TimeDecayingRunningAverage(1024+1024+500, 180000, 0.0, 1024*1024*1024, 
throttleFS == null ? null : 
throttleFS.subset("RemoteSskInsertBytesReceivedAverage"));
+               remoteChkFetchBytesSentAverage = new 
TimeDecayingRunningAverage(32768+1024+500, 180000, 0.0, 1024*1024*1024, 
throttleFS == null ? null : 
throttleFS.subset("RemoteChkFetchBytesSentAverage"), node);
+               remoteSskFetchBytesSentAverage = new 
TimeDecayingRunningAverage(1024+1024+500, 180000, 0.0, 1024*1024*1024, 
throttleFS == null ? null : 
throttleFS.subset("RemoteSskFetchBytesSentAverage"), node);
+               remoteChkInsertBytesSentAverage = new 
TimeDecayingRunningAverage(32768+32768+1024, 180000, 0.0, 1024*1024*1024, 
throttleFS == null ? null : 
throttleFS.subset("RemoteChkInsertBytesSentAverage"), node);
+               remoteSskInsertBytesSentAverage = new 
TimeDecayingRunningAverage(1024+1024+500, 180000, 0.0, 1024*1024*1024, 
throttleFS == null ? null : 
throttleFS.subset("RemoteSskInsertBytesSentAverage"), node);
+               remoteChkFetchBytesReceivedAverage = new 
TimeDecayingRunningAverage(32768+1024+500, 180000, 0.0, 1024*1024*1024, 
throttleFS == null ? null : 
throttleFS.subset("RemoteChkFetchBytesReceivedAverage"), node);
+               remoteSskFetchBytesReceivedAverage = new 
TimeDecayingRunningAverage(2048+500, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("RemoteSskFetchBytesReceivedAverage"), node);
+               remoteChkInsertBytesReceivedAverage = new 
TimeDecayingRunningAverage(32768+1024+500, 180000, 0.0, 1024*1024*1024, 
throttleFS == null ? null : 
throttleFS.subset("RemoteChkInsertBytesReceivedAverage"), node);
+               remoteSskInsertBytesReceivedAverage = new 
TimeDecayingRunningAverage(1024+1024+500, 180000, 0.0, 1024*1024*1024, 
throttleFS == null ? null : 
throttleFS.subset("RemoteSskInsertBytesReceivedAverage"), node);

-               successfulChkFetchBytesSentAverage = new 
TimeDecayingRunningAverage(32768, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("SuccessfulChkFetchBytesSentAverage"));
-               successfulSskFetchBytesSentAverage = new 
TimeDecayingRunningAverage(2048, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("SuccessfulSskFetchBytesSentAverage"));
-               successfulChkInsertBytesSentAverage = new 
TimeDecayingRunningAverage(32768, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("SuccessfulChkInsertBytesSentAverage"));
-               successfulSskInsertBytesSentAverage = new 
TimeDecayingRunningAverage(2048, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("SuccessfulSskInsertBytesSentAverage"));
-               successfulChkFetchBytesReceivedAverage = new 
TimeDecayingRunningAverage(32768, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("SuccessfulChkFetchBytesReceivedAverage"));
-               successfulSskFetchBytesReceivedAverage = new 
TimeDecayingRunningAverage(2048, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("SuccessfulSskFetchBytesReceivedAverage"));
-               successfulChkInsertBytesReceivedAverage = new 
TimeDecayingRunningAverage(32768, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("SuccessfulChkInsertBytesReceivedAverage"));
-               successfulSskInsertBytesReceivedAverage = new 
TimeDecayingRunningAverage(2048, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("SuccessfulSskInsertBytesReceivedAverage"));
+               successfulChkFetchBytesSentAverage = new 
TimeDecayingRunningAverage(32768, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("SuccessfulChkFetchBytesSentAverage"), node);
+               successfulSskFetchBytesSentAverage = new 
TimeDecayingRunningAverage(2048, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("SuccessfulSskFetchBytesSentAverage"), node);
+               successfulChkInsertBytesSentAverage = new 
TimeDecayingRunningAverage(32768, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("SuccessfulChkInsertBytesSentAverage"), node);
+               successfulSskInsertBytesSentAverage = new 
TimeDecayingRunningAverage(2048, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("SuccessfulSskInsertBytesSentAverage"), node);
+               successfulChkFetchBytesReceivedAverage = new 
TimeDecayingRunningAverage(32768, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("SuccessfulChkFetchBytesReceivedAverage"), 
node);
+               successfulSskFetchBytesReceivedAverage = new 
TimeDecayingRunningAverage(2048, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("SuccessfulSskFetchBytesReceivedAverage"), 
node);
+               successfulChkInsertBytesReceivedAverage = new 
TimeDecayingRunningAverage(32768, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("SuccessfulChkInsertBytesReceivedAverage"), 
node);
+               successfulSskInsertBytesReceivedAverage = new 
TimeDecayingRunningAverage(2048, 180000, 0.0, 1024*1024*1024, throttleFS == 
null ? null : throttleFS.subset("SuccessfulSskInsertBytesReceivedAverage"), 
node);

                requestOutputThrottle = 
                        new TokenBucket(Math.max(obwLimit*60, 32768*20), 
(int)((1000L*1000L*1000L) / (obwLimit * 
FRACTION_OF_BANDWIDTH_USED_BY_REQUESTS)), 0);

Modified: trunk/freenet/src/freenet/node/PeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerNode.java        2007-06-01 20:44:14 UTC 
(rev 13461)
+++ trunk/freenet/src/freenet/node/PeerNode.java        2007-06-01 20:51:27 UTC 
(rev 13462)
@@ -362,6 +362,7 @@
        logMINOR = Logger.shouldLog(Logger.MINOR, this);
         this.node = node2;
         this.peers = peers;
+        this.backedOffPercent = new TimeDecayingRunningAverage(0.0, 180000, 
0.0, 1.0, node);
         String identityString = fs.get("identity");
        if(identityString == null)
                throw new PeerParseException("No identity!");
@@ -535,11 +536,11 @@
         // A SimpleRunningAverage would be a bad choice because it would cause 
oscillations.
         // So go for a filter.
         pingAverage = 
-               new TimeDecayingRunningAverage(1, 600*1000 /* should be 
significantly longer than a typical transfer */, 0, 
NodePinger.CRAZY_MAX_PING_TIME);
+               new TimeDecayingRunningAverage(1, 600*1000 /* should be 
significantly longer than a typical transfer */, 0, 
NodePinger.CRAZY_MAX_PING_TIME, node);

         // TDRA for probability of rejection
         pRejected =
-               new TimeDecayingRunningAverage(0, 600*1000, 0.0, 1.0);
+               new TimeDecayingRunningAverage(0, 600*1000, 0.0, 1.0, node);

         // ARK stuff.

@@ -2139,7 +2140,7 @@
        /** Previous backoff reason (used by setPeerNodeStatus)*/
        String previousRoutingBackoffReason;
        /* percent of time this peer is backed off */
-       public RunningAverage backedOffPercent = new 
TimeDecayingRunningAverage(0.0, 180000, 0.0, 1.0);
+       public final RunningAverage backedOffPercent;
        /* time of last sample */
        private long lastSampleTime = Long.MAX_VALUE;


Added: trunk/freenet/src/freenet/node/useralerts/TimeSkewDetectedUserAlert.java
===================================================================
--- trunk/freenet/src/freenet/node/useralerts/TimeSkewDetectedUserAlert.java    
                        (rev 0)
+++ trunk/freenet/src/freenet/node/useralerts/TimeSkewDetectedUserAlert.java    
2007-06-01 20:51:27 UTC (rev 13462)
@@ -0,0 +1,63 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.node.useralerts;
+
+import freenet.l10n.L10n;
+import freenet.support.HTMLNode;
+
+/**
+ * A simple user alert warning the user about the weird effect a time skew
+ * can have on a freenet node.
+ *
+ * This useralert is SET only and can be triggered from NodeStarter
+ *
+ * @author Florent Daignière <nextgens at freenetproject.org>
+ */
+public class TimeSkewDetectedUserAlert implements UserAlert {
+       private boolean isValid=false;
+       
+       public boolean userCanDismiss() {
+               return false;
+       }
+
+       public String getTitle() {
+               return l10n("title");
+       }
+       
+       private String l10n(String key) {
+               return L10n.getString("TimeSkewDetectedUserAlert."+key);
+       }
+
+       public String getText() {
+               return l10n("text");
+       }
+
+       public HTMLNode getHTMLText() {
+               return new HTMLNode("div", getText());
+       }
+
+       public short getPriorityClass() {
+               return UserAlert.CRITICAL_ERROR;
+       }
+
+       public boolean isValid() {
+               return isValid;
+       }
+       
+       public void isValid(boolean b){
+               if(userCanDismiss()) isValid=b;
+       }
+       
+       public String dismissButtonText(){
+               return L10n.getString("UserAlert.hide");
+       }
+       
+       public boolean shouldUnregisterOnDismiss() {
+               return false;
+       }
+       
+       public void onDismiss() {
+               // can't happen!
+       }
+}

Modified: trunk/freenet/src/freenet/support/math/TimeDecayingRunningAverage.java
===================================================================
--- trunk/freenet/src/freenet/support/math/TimeDecayingRunningAverage.java      
2007-06-01 20:44:14 UTC (rev 13461)
+++ trunk/freenet/src/freenet/support/math/TimeDecayingRunningAverage.java      
2007-06-01 20:51:27 UTC (rev 13462)
@@ -7,6 +7,7 @@
 import java.io.DataOutputStream;
 import java.io.IOException;

+import freenet.node.Node;
 import freenet.support.Logger;
 import freenet.support.SimpleFieldSet;

@@ -40,6 +41,7 @@
     double minReport;
     double maxReport;
     boolean logDEBUG;
+    private final Node node;

     public String toString() {
                long now = System.currentTimeMillis();
@@ -53,7 +55,7 @@
     }

     public TimeDecayingRunningAverage(double defaultValue, long halfLife,
-            double min, double max) {
+            double min, double max, final Node node) {
        curValue = defaultValue;
         this.defaultValue = defaultValue;
         started = false;
@@ -66,10 +68,11 @@
         if(logDEBUG)
                Logger.debug(this, "Created "+this,
                                new Exception("debug"));
+        this.node = node;
     }

     public TimeDecayingRunningAverage(double defaultValue, long halfLife,
-            double min, double max, SimpleFieldSet fs) {
+            double min, double max, SimpleFieldSet fs, final Node node) {
        curValue = defaultValue;
         this.defaultValue = defaultValue;
         started = false;
@@ -98,9 +101,10 @@
                        }
                }
         }
+        this.node = node;
     }

-    public TimeDecayingRunningAverage(double defaultValue, double halfLife, 
double min, double max, DataInputStream dis) throws IOException {
+    public TimeDecayingRunningAverage(double defaultValue, double halfLife, 
double min, double max, DataInputStream dis, final Node node) throws 
IOException {
         int m = dis.readInt();
         if(m != MAGIC) throw new IOException("Invalid magic "+m);
         int v = dis.readInt();
@@ -120,6 +124,7 @@
         lastReportTime = -1;
         createdTime = System.currentTimeMillis() - priorExperienceTime;
         totalReports = dis.readLong();
+        this.node = node;
     }

     public TimeDecayingRunningAverage(TimeDecayingRunningAverage a) {
@@ -132,6 +137,7 @@
         this.started = a.started;
         this.totalReports = a.totalReports;
         this.curValue = a.curValue;
+        this.node = a.node;
     }

     public synchronized double currentValue() {
@@ -165,13 +171,17 @@
                                         now - lastReportTime;
                                long uptime = now - createdTime;
                                if(thisInterval < 0) {
-                                       Logger.error(this, "Clock (reporting) 
went back in time, ignoring report: "+now+" was "+lastReportTime+" (back 
"+(-thisInterval)+"ms");
+                                       Logger.error(this, "Clock (reporting) 
went back in time, ignoring report: "+now+" was "+lastReportTime+" (back 
"+(-thisInterval)+"ms)");
                                        lastReportTime = now;
+                                       if(node != null)
+                                               
node.setTimeSkewDetectedUserAlert();
                                        return;
                                }
                                double thisHalfLife = halfLife;
                                if(uptime < 0) {
-                                       Logger.error(this, "Clock (uptime) went 
back in time, ignoring report: "+now+" was "+createdTime+" (back 
"+(-uptime)+"ms");
+                                       Logger.error(this, "Clock (uptime) went 
back in time, ignoring report: "+now+" was "+createdTime+" (back 
"+(-uptime)+"ms)");
+                                       if(node != null)
+                                               
node.setTimeSkewDetectedUserAlert();
                                        return;
                                } else {
                                        if((uptime / 4) < thisHalfLife) 
thisHalfLife = (uptime / 4);


Reply via email to