diff --git a/history.txt b/history.txt index 7faab9dd3..e635ad677 100644 --- a/history.txt +++ b/history.txt @@ -1,6 +1,8 @@ 2015-06-08 dg * Language fixes * Make netDb.storeFloodNew graphable for testing (#1195) + * Directly connect to nearby floodfills to share our RI + to speed up integration of new floodfills (#1195) 2015-06-06 str4d * newsxml: Don't use XXX for parsing dates on Android diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 282c18b42..0725033fa 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 2; + public final static long BUILD = 3; /** for example "-test" */ public final static String EXTRA = ""; diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillMonitorJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillMonitorJob.java index 53eb0be4a..2c1a929d9 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillMonitorJob.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillMonitorJob.java @@ -6,6 +6,7 @@ import net.i2p.crypto.SigType; import net.i2p.data.Hash; import net.i2p.data.router.RouterAddress; import net.i2p.data.router.RouterInfo; +import net.i2p.router.Job; import net.i2p.router.JobImpl; import net.i2p.router.Router; import net.i2p.router.RouterContext; @@ -55,13 +56,27 @@ class FloodfillMonitorJob extends JobImpl { } else { getContext().router().eventLog().addEvent(EventLog.NOT_FLOODFILL); } - getContext().router().rebuildRouterInfo(); + getContext().router().rebuildRouterInfo(true); + Job routerInfoFlood = new FloodfillRouterInfoFloodJob(getContext(), _facade); + if(getContext().router().getUptime() < 5*60*1000) { + // Needed to prevent race if router.floodfillParticipant=true (not auto) + routerInfoFlood.getTiming().setStartAfter(getContext().clock().now() + 5*60*1000); + getContext().jobQueue().addJob(routerInfoFlood); + if(_log.shouldLog(Log.DEBUG)) { + _log.logAlways(Log.DEBUG, "Deferring our FloodfillRouterInfoFloodJob run because of low uptime."); + } + } else { + routerInfoFlood.runJob(); + if(_log.shouldLog(Log.DEBUG)) { + _log.logAlways(Log.DEBUG, "Running FloodfillRouterInfoFloodJob"); + } + } } if (_log.shouldLog(Log.INFO)) _log.info("Should we be floodfill? " + ff); int delay = (REQUEUE_DELAY / 2) + getContext().random().nextInt(REQUEUE_DELAY); // there's a lot of eligible non-floodfills, keep them from all jumping in at once - // To do: somehow assess the size of the network to make this adaptive? + // TODO: somehow assess the size of the network to make this adaptive? if (!ff) delay *= 4; // this was 7, reduced for moar FFs --zab requeue(delay); diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java index dc33507bc..0df3b3290 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillNetworkDatabaseFacade.java @@ -40,7 +40,7 @@ public class FloodfillNetworkDatabaseFacade extends KademliaNetworkDatabaseFacad * Was 7 through release 0.9; 5 for 0.9.1. * 4 as of 0.9.2; 3 as of 0.9.9 */ - private static final int MAX_TO_FLOOD = 3; + public static final int MAX_TO_FLOOD = 3; private static final int FLOOD_PRIORITY = OutNetMessage.PRIORITY_NETDB_FLOOD; private static final int FLOOD_TIMEOUT = 30*1000; diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillRouterInfoFloodJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillRouterInfoFloodJob.java new file mode 100644 index 000000000..fb620a1ad --- /dev/null +++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillRouterInfoFloodJob.java @@ -0,0 +1,63 @@ +package net.i2p.router.networkdb.kademlia; + +import java.util.Collections; +import java.util.List; + +import net.i2p.data.Hash; +import net.i2p.data.i2np.DatabaseStoreMessage; +import net.i2p.data.router.RouterAddress; +import net.i2p.data.router.RouterInfo; +import net.i2p.router.JobImpl; +import net.i2p.router.OutNetMessage; +import net.i2p.router.Router; +import net.i2p.router.RouterContext; +import net.i2p.stat.Rate; +import net.i2p.stat.RateStat; +import net.i2p.util.Log; + +/** + * Job to flood nearby floodfill routers with our RI. + * Speeds up integration of new ffs. Created for #1195. + * Also called when opting out of ff to call off the hounds ASAP. + * Currently floods FNDF.MAX_TO_FLOOD * 2 routers nearest to us. + * + */ +class FloodfillRouterInfoFloodJob extends JobImpl { + private final Log _log; + private final FloodfillNetworkDatabaseFacade _facade; + + private static final int FLOOD_PEERS = 2 * FloodfillNetworkDatabaseFacade.MAX_TO_FLOOD; + + public FloodfillRouterInfoFloodJob(RouterContext context, FloodfillNetworkDatabaseFacade facade) { + super(context); + _facade = facade; + _log = context.logManager().getLog(FloodfillRouterInfoFloodJob.class); + } + + public String getName() { return "Flood our RouterInfo to nearby floodfills"; } + + public void runJob() { + FloodfillPeerSelector sel = (FloodfillPeerSelector)_facade.getPeerSelector(); + DatabaseStoreMessage dsm; + OutNetMessage outMsg; + RouterInfo nextPeerInfo; + + List peers = sel.selectFloodfillParticipants(getContext().routerHash(), FLOOD_PEERS, null); + + for(Hash ri: peers) { + // Iterate through list of nearby (ff) peers + dsm = new DatabaseStoreMessage(getContext()); + dsm.setMessageExpiration(getContext().clock().now() + 10*1000); + dsm.setEntry(getContext().router().getRouterInfo()); + nextPeerInfo = getContext().netDb().lookupRouterInfoLocally(ri); + if(nextPeerInfo == null) { + continue; + } + outMsg = new OutNetMessage(getContext(), dsm, getContext().clock().now()+10*1000, OutNetMessage.PRIORITY_MY_NETDB_STORE, nextPeerInfo); + getContext().outNetMessagePool().add(outMsg); // Whoosh! + if(_log.shouldLog(Log.DEBUG)) { + _log.logAlways(Log.DEBUG, "Sending our RI to: " + nextPeerInfo.getHash()); + } + } + } +}