forked from I2P_Developers/i2p.i2p
NetDB: Publish RI faster when costs change (ticket #1437)
PLRIJ interval was 37-50 minutes. Reduce that by 4x, but for 3 out of 4 times, only publish if something changes, including cost. 4th time, always publish, as before. This will hopefully reduce routers getting slammed to conn limits on a transport.
This commit is contained in:
15
history.txt
15
history.txt
@ -1,9 +1,20 @@
|
||||
2015-01-09 zzz
|
||||
* NetDB: Publish RI faster when costs change (ticket #1437)
|
||||
|
||||
2015-01-08 zzz
|
||||
* Console, i2ptunnel, proxy: Renaming of various things to "hidden services"
|
||||
|
||||
2015-01-07 zzz
|
||||
* ClientAppConfig: Start i2ptunnel sooner (ticket #1162)
|
||||
* NetDB: Possible fixes for reseed completion not recognized (ticket #1384)
|
||||
* Router: Add startup/shutdown state machine
|
||||
* Router:
|
||||
- Add startup/shutdown state machine
|
||||
- Don't reset uptime after a soft restart
|
||||
* Startup: Accept tunnels after 10 minutes instead of 20 (ticket #1152)
|
||||
* Tunnels: Cleanup, catch more cases of zero-hop configuration
|
||||
* Tunnels:
|
||||
- Cleanup, catch more cases of zero-hop configuration
|
||||
- Temporarily increase exploratory tunnel quantity at startup,
|
||||
so that netdb refresh will work better
|
||||
|
||||
2015-01-05 zzz
|
||||
* Blocklist:
|
||||
|
@ -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 = 9;
|
||||
public final static long BUILD = 10;
|
||||
|
||||
/** for example "-test" */
|
||||
public final static String EXTRA = "";
|
||||
|
@ -8,10 +8,17 @@ package net.i2p.router.networkdb;
|
||||
*
|
||||
*/
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import net.i2p.data.DataFormatException;
|
||||
import net.i2p.data.router.RouterAddress;
|
||||
import net.i2p.data.router.RouterInfo;
|
||||
import net.i2p.data.SigningPrivateKey;
|
||||
import net.i2p.router.JobImpl;
|
||||
@ -30,15 +37,16 @@ public class PublishLocalRouterInfoJob extends JobImpl {
|
||||
|
||||
/**
|
||||
* Don't store if somebody else stored it recently.
|
||||
* Must be less than PUBLISH_DELAY * 3 / 16 (see getDelay())
|
||||
*/
|
||||
private static final long MIN_PUBLISH_DELAY = 25*60*1000;
|
||||
private static final long MIN_PUBLISH_DELAY = 9*60*1000;
|
||||
|
||||
/**
|
||||
* Too short and the network puts a big connection load on the
|
||||
* floodfills since we store directly.
|
||||
* Too long and the floodfill will drop us - timeout is 60 minutes.
|
||||
*/
|
||||
private static final long PUBLISH_DELAY = MIN_PUBLISH_DELAY * 2;
|
||||
private static final long PUBLISH_DELAY = 52*60*1000;
|
||||
|
||||
/** this needs to be long enough to give us time to start up,
|
||||
but less than 20m (when we start accepting tunnels and could be a IBGW)
|
||||
@ -47,7 +55,8 @@ public class PublishLocalRouterInfoJob extends JobImpl {
|
||||
we can't build IB exploratory tunnels.
|
||||
*/
|
||||
private static final long FIRST_TIME_DELAY = 90*1000;
|
||||
boolean _notFirstTime;
|
||||
private volatile boolean _notFirstTime;
|
||||
private final AtomicInteger _runCount = new AtomicInteger();
|
||||
|
||||
public PublishLocalRouterInfoJob(RouterContext ctx) {
|
||||
super(ctx);
|
||||
@ -55,6 +64,7 @@ public class PublishLocalRouterInfoJob extends JobImpl {
|
||||
}
|
||||
|
||||
public String getName() { return "Publish Local Router Info"; }
|
||||
|
||||
public void runJob() {
|
||||
long last = getContext().netDb().getLastRouterInfoPublishTime();
|
||||
long now = getContext().clock().now();
|
||||
@ -63,16 +73,45 @@ public class PublishLocalRouterInfoJob extends JobImpl {
|
||||
requeue(last + delay - now);
|
||||
return;
|
||||
}
|
||||
RouterInfo ri = new RouterInfo(getContext().router().getRouterInfo());
|
||||
RouterInfo oldRI = getContext().router().getRouterInfo();
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Old routerInfo contains " + ri.getAddresses().size()
|
||||
+ " addresses and " + ri.getOptionsMap().size() + " options");
|
||||
Properties stats = getContext().statPublisher().publishStatistics();
|
||||
stats.setProperty(RouterInfo.PROP_NETWORK_ID, ""+Router.NETWORK_ID);
|
||||
_log.debug("Old routerInfo contains " + oldRI.getAddresses().size()
|
||||
+ " addresses and " + oldRI.getOptionsMap().size() + " options");
|
||||
try {
|
||||
List<RouterAddress> oldAddrs = new ArrayList(oldRI.getAddresses());
|
||||
List<RouterAddress> newAddrs = getContext().commSystem().createAddresses();
|
||||
int count = _runCount.incrementAndGet();
|
||||
if (_notFirstTime && (count % 4) != 0 && oldAddrs.size() == newAddrs.size()) {
|
||||
// 3 times out of 4, we don't republish if everything is the same...
|
||||
// If something changed, including the cost, then publish,
|
||||
// otherwise don't.
|
||||
boolean different = false;
|
||||
Comparator<RouterAddress> comp = new AddrComparator();
|
||||
Collections.sort(oldAddrs, comp);
|
||||
Collections.sort(newAddrs, comp);
|
||||
for (int i = 0; i < oldAddrs.size(); i++) {
|
||||
// deepEquals() includes cost
|
||||
if (!oldAddrs.get(i).deepEquals(newAddrs.get(i))) {
|
||||
different = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!different) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Not republishing early because costs are the same");
|
||||
requeue(getDelay());
|
||||
return;
|
||||
}
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Republishing early because addresses or costs have changed - old:\n" +
|
||||
oldAddrs + "\nnew:\n" + newAddrs);
|
||||
}
|
||||
RouterInfo ri = new RouterInfo(oldRI);
|
||||
ri.setPublished(getContext().clock().now());
|
||||
Properties stats = getContext().statPublisher().publishStatistics();
|
||||
stats.setProperty(RouterInfo.PROP_NETWORK_ID, ""+Router.NETWORK_ID);
|
||||
ri.setOptions(stats);
|
||||
ri.setAddresses(getContext().commSystem().createAddresses());
|
||||
ri.setAddresses(newAddrs);
|
||||
|
||||
getContext().router().addCapabilities(ri);
|
||||
SigningPrivateKey key = getContext().keyManager().getSigningPrivateKey();
|
||||
@ -98,8 +137,7 @@ public class PublishLocalRouterInfoJob extends JobImpl {
|
||||
_log.error("Error signing the updated local router info!", dfe);
|
||||
}
|
||||
if (_notFirstTime) {
|
||||
long delay = getDelay();
|
||||
requeue(delay);
|
||||
requeue(getDelay());
|
||||
} else {
|
||||
requeue(FIRST_TIME_DELAY);
|
||||
_notFirstTime = true;
|
||||
@ -107,6 +145,29 @@ public class PublishLocalRouterInfoJob extends JobImpl {
|
||||
}
|
||||
|
||||
private long getDelay() {
|
||||
return (PUBLISH_DELAY * 3 / 4) + getContext().random().nextLong(PUBLISH_DELAY / 4);
|
||||
long rv = (PUBLISH_DELAY * 3 / 4) + getContext().random().nextLong(PUBLISH_DELAY / 4);
|
||||
// run 4x as often as usual publish time (see above)
|
||||
rv /= 4;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Arbitrary sort so we can attempt to compare costs between two RIs to see if they have changed
|
||||
*
|
||||
* @since 0.9.18
|
||||
*/
|
||||
private static class AddrComparator implements Comparator<RouterAddress>, Serializable {
|
||||
public int compare(RouterAddress l, RouterAddress r) {
|
||||
int c = l.getTransportStyle().compareTo(r.getTransportStyle());
|
||||
if (c != 0)
|
||||
return c;
|
||||
String lh = l.getHost();
|
||||
String rh = r.getHost();
|
||||
if (lh == null)
|
||||
return rh == null ? 0 : -1;
|
||||
if (rh == null)
|
||||
return 1;
|
||||
return lh.compareTo(rh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user