Opened 5 months ago

Last modified 2 months ago

#2560 new enhancement

Add listener to Router _state events

Reported by: Zlatin Balevsky Owned by:
Priority: minor Milestone: undecided
Component: router/general Version: 0.9.40
Keywords: Cc:
Parent Tickets: Sensitive: no

Description

It would be very helpful for applications that embed the router to listen to router state changes. This way a fine-grained progress indicator can be displayed to the user while the router is initializing.

Subtickets

Change History (3)

comment:1 Changed 5 months ago by Zlatin Balevsky

Something as simple as this will do:

package net.i2p.router;

public interface RouterListener {
    public void routerStateChanged(Router.State state);
}
#
# old_revision [7e976c1281c29bf08527bb13df249b39c19e1af9]
#
# patch "router/java/src/net/i2p/router/Router.java"
#  from [5ebeb5d5785d9665ef7329caf3c0b43c9cc7d6e7]
#    to [213f8829cfbb3e83c18fcd7426d79cafdcf33914]
#
============================================================
--- router/java/src/net/i2p/router/Router.java	5ebeb5d5785d9665ef7329caf3c0b43c9cc7d6e7
+++ router/java/src/net/i2p/router/Router.java	213f8829cfbb3e83c18fcd7426d79cafdcf33914
@@ -100,6 +100,7 @@ public class Router implements RouterClo
     private final EventLog _eventLog;
     private final Object _stateLock = new Object();
     private State _state = State.UNINITIALIZED;
+    private volatile RouterListener _listener;
     private FamilyKeyCrypto _familyKeyCrypto;
     private boolean _familyKeyCryptoFail;
     public final Object _familyKeyLock = new Object();
@@ -740,13 +741,17 @@ public class Router implements RouterClo
     }
 
     ////////// begin state management
-    
+   
+    public void setRouterListener(RouterListener listener) {
+        _listener = listener;
+    }
+ 
     /**
      *  Startup / shutdown states
      *
      *  @since 0.9.18
      */
-    private enum State {
+    public enum State {
         UNINITIALIZED,
         /** constructor complete */
         INITIALIZED,
@@ -811,6 +816,8 @@ public class Router implements RouterClo
             //for debugging
             _context.logManager().flush();
         }
+        if (_listener != null)
+            _listener.routerStateChanged(state);
     }
 
     /**

comment:2 Changed 4 months ago by zzz

I don't think this would give you the "fine-grained" status you're looking for. There's only a few states. If you're in router context, you have access to everything, so you could check for router info, peer, and tunnel counts, or whatever else is important. Especially client tunnels for your application.

Here's an example of the timing of what you'd see, this is a startup for the first time in a few days:

07/04 xx:42:03.027 WARN  [impleAppMain] net.i2p.router.Router         : Router state change from STARTING_1 to STARTING_2
07/04 xx:42:03.065 WARN  [impleAppMain] net.i2p.router.Router         : Router state change from STARTING_2 to STARTING_3
07/04 xx:42:09.999 WARN  [JobQueue 4/4] net.i2p.router.Router         : Router state change from STARTING_3 to NETDB_READY
07/04 xx:43:07.338 WARN  [receiver 1/5] net.i2p.router.Router         : Router state change from NETDB_READY to RUNNING

I'm also wary of directly exposing our internal state in an API, that would limit our ability to change things later.

And wouldn't we have to call the listener from inside the sync block to ensure ordering? But I'd rather not call external code from inside a lock…

comment:3 Changed 2 months ago by zzz

see also #1697

Note: See TracTickets for help on using tickets.