Opened 23 months ago

Last modified 20 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


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.


Change History (3)

comment:1 Changed 23 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/"
#  from [5ebeb5d5785d9665ef7329caf3c0b43c9cc7d6e7]
#    to [213f8829cfbb3e83c18fcd7426d79cafdcf33914]
--- router/java/src/net/i2p/router/	5ebeb5d5785d9665ef7329caf3c0b43c9cc7d6e7
+++ router/java/src/net/i2p/router/	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 {
         /** constructor complete */
@@ -811,6 +816,8 @@ public class Router implements RouterClo
             //for debugging
+        if (_listener != null)
+            _listener.routerStateChanged(state);

comment:2 Changed 23 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 20 months ago by zzz

see also #1697

Note: See TracTickets for help on using tickets.