forked from I2P_Developers/i2p.i2p
* Reseeder: Get rid of static instance, root in netDB,
don't use system properties for status
This commit is contained in:
@ -20,13 +20,11 @@ public class ConfigReseedHandler extends FormHandler {
|
||||
|
||||
if (_action.equals(_("Save changes and reseed now"))) {
|
||||
saveChanges();
|
||||
boolean reseedInProgress = Boolean.valueOf(System.getProperty("net.i2p.router.web.ReseedHandler.reseedInProgress")).booleanValue();
|
||||
if (reseedInProgress) {
|
||||
if (!_context.netDb().reseedChecker().requestReseed()) {
|
||||
addFormError(_("Reseeding is already in progress"));
|
||||
} else {
|
||||
// skip the nonce checking in ReseedHandler
|
||||
addFormNotice(_("Starting reseed process"));
|
||||
(new ReseedHandler(_context)).requestReseed();
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -74,8 +72,15 @@ public class ConfigReseedHandler extends FormHandler {
|
||||
saveString(Reseeder.PROP_SPROXY_PASSWORD, "spassword");
|
||||
saveBoolean(Reseeder.PROP_SPROXY_AUTH_ENABLE, "sauth");
|
||||
String url = getJettyString("reseedURL");
|
||||
if (url != null)
|
||||
changes.put(Reseeder.PROP_RESEED_URL, url.trim().replace("\r\n", ",").replace("\n", ","));
|
||||
if (url != null) {
|
||||
url = url.trim().replace("\r\n", ",").replace("\n", ",");
|
||||
if (url.length() <= 0) {
|
||||
addFormNotice("Restoring default URLs");
|
||||
removes.add(Reseeder.PROP_RESEED_URL);
|
||||
} else {
|
||||
changes.put(Reseeder.PROP_RESEED_URL, url);
|
||||
}
|
||||
}
|
||||
String mode = getJettyString("mode");
|
||||
boolean req = "1".equals(mode);
|
||||
boolean disabled = "2".equals(mode);
|
||||
|
@ -24,11 +24,7 @@ public class ReseedHandler extends HelperBase {
|
||||
}
|
||||
}
|
||||
|
||||
public void requestReseed() {
|
||||
synchronized (ReseedHandler.class) {
|
||||
if (_reseedRunner == null)
|
||||
_reseedRunner = new Reseeder(_context);
|
||||
_reseedRunner.requestReseed();
|
||||
}
|
||||
private void requestReseed() {
|
||||
_context.netDb().reseedChecker().requestReseed();
|
||||
}
|
||||
}
|
||||
|
@ -676,12 +676,12 @@ public class SummaryHelper extends HelperBase {
|
||||
.append("</a></h4>");
|
||||
}
|
||||
|
||||
boolean reseedInProgress = Boolean.valueOf(System.getProperty("net.i2p.router.web.ReseedHandler.reseedInProgress")).booleanValue();
|
||||
boolean reseedInProgress = _context.netDb().reseedChecker().inProgress();
|
||||
// If showing the reseed link is allowed
|
||||
if (allowReseed()) {
|
||||
if (reseedInProgress) {
|
||||
// While reseed occurring, show status message instead
|
||||
buf.append("<i>").append(System.getProperty("net.i2p.router.web.ReseedHandler.statusMessage","")).append("</i><br>");
|
||||
buf.append("<i>").append(_context.netDb().reseedChecker().getStatus()).append("</i><br>");
|
||||
} else {
|
||||
// While no reseed occurring, show reseed link
|
||||
long nonce = _context.random().nextLong();
|
||||
@ -696,7 +696,7 @@ public class SummaryHelper extends HelperBase {
|
||||
}
|
||||
// If a new reseed ain't running, and the last reseed had errors, show error message
|
||||
if (!reseedInProgress) {
|
||||
String reseedErrorMessage = System.getProperty("net.i2p.router.web.ReseedHandler.errorMessage","");
|
||||
String reseedErrorMessage = _context.netDb().reseedChecker().getError();
|
||||
if (reseedErrorMessage.length() > 0) {
|
||||
buf.append("<i>").append(reseedErrorMessage).append("</i><br>");
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import net.i2p.data.DatabaseEntry;
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.data.LeaseSet;
|
||||
import net.i2p.data.RouterInfo;
|
||||
import net.i2p.router.networkdb.reseed.ReseedChecker;
|
||||
|
||||
/**
|
||||
* Defines the mechanism for interacting with I2P's network database
|
||||
@ -73,4 +74,7 @@ public abstract class NetworkDatabaseFacade implements Service {
|
||||
public Set<LeaseSet> getLeases() { return Collections.EMPTY_SET; }
|
||||
/** public for NetDbRenderer in routerconsole */
|
||||
public Set<RouterInfo> getRouters() { return Collections.EMPTY_SET; }
|
||||
|
||||
/** @since 0.9 */
|
||||
public ReseedChecker reseedChecker() { return null; };
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ import net.i2p.router.TunnelPoolSettings;
|
||||
import net.i2p.router.networkdb.DatabaseLookupMessageHandler;
|
||||
import net.i2p.router.networkdb.DatabaseStoreMessageHandler;
|
||||
import net.i2p.router.networkdb.PublishLocalRouterInfoJob;
|
||||
import net.i2p.router.networkdb.reseed.ReseedChecker;
|
||||
import net.i2p.router.peermanager.PeerProfile;
|
||||
import net.i2p.util.ConcurrentHashSet;
|
||||
import net.i2p.util.Log;
|
||||
@ -67,6 +68,8 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
|
||||
private long _lastExploreNew;
|
||||
protected final PeerSelector _peerSelector;
|
||||
protected final RouterContext _context;
|
||||
private final ReseedChecker _reseedChecker;
|
||||
|
||||
/**
|
||||
* Map of Hash to RepublishLeaseSetJob for leases we'realready managing.
|
||||
* This is added to when we create a new RepublishLeaseSetJob, and the values are
|
||||
@ -146,6 +149,7 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
|
||||
_publishingLeaseSets = new HashMap(8);
|
||||
_activeRequests = new HashMap(8);
|
||||
_enforceNetId = DEFAULT_ENFORCE_NETID;
|
||||
_reseedChecker = new ReseedChecker(context);
|
||||
context.statManager().createRateStat("netDb.lookupLeaseSetDeferred", "how many lookups are deferred for a single leaseSet lookup?", "NetworkDatabase", new long[] { 60*60*1000 });
|
||||
context.statManager().createRateStat("netDb.exploreKeySet", "how many keys are queued for exploration?", "NetworkDatabase", new long[] { 60*60*1000 });
|
||||
// following are for StoreJob
|
||||
@ -167,6 +171,12 @@ public class KademliaNetworkDatabaseFacade extends NetworkDatabaseFacade {
|
||||
protected PeerSelector createPeerSelector() { return new PeerSelector(_context); }
|
||||
public PeerSelector getPeerSelector() { return _peerSelector; }
|
||||
|
||||
/** @since 0.9 */
|
||||
@Override
|
||||
public ReseedChecker reseedChecker() {
|
||||
return _reseedChecker;
|
||||
}
|
||||
|
||||
KBucketSet getKBuckets() { return _kb; }
|
||||
DataStore getDataStore() { return _ds; }
|
||||
|
||||
|
@ -382,7 +382,7 @@ class PersistentDataStore extends TransientDataStore {
|
||||
}
|
||||
|
||||
if (!_alreadyWarned) {
|
||||
ReseedChecker.checkReseed(_context, routerCount);
|
||||
_facade.reseedChecker().checkReseed(routerCount);
|
||||
_alreadyWarned = true;
|
||||
_initialized = true;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.i2p.router.networkdb.reseed;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.util.Log;
|
||||
@ -19,29 +20,144 @@ import net.i2p.util.Log;
|
||||
*/
|
||||
public class ReseedChecker {
|
||||
|
||||
private final RouterContext _context;
|
||||
private final Log _log;
|
||||
private final AtomicBoolean _inProgress = new AtomicBoolean();
|
||||
private String _lastStatus = "";
|
||||
private String _lastError = "";
|
||||
|
||||
private static final int MINIMUM = 15;
|
||||
|
||||
public static void checkReseed(RouterContext context, int count) {
|
||||
/**
|
||||
* All reseeding must be done through this instance.
|
||||
* Access through context.netDb().reseedChecker(), others should not instantiate
|
||||
*
|
||||
* @since 0.9
|
||||
*/
|
||||
public ReseedChecker(RouterContext context) {
|
||||
_context = context;
|
||||
_log = context.logManager().getLog(ReseedChecker.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a reseed is needed, and start it
|
||||
*
|
||||
* @param count current number of known routers
|
||||
* @return true if a reseed was started
|
||||
*/
|
||||
public boolean checkReseed(int count) {
|
||||
if (count >= MINIMUM)
|
||||
return;
|
||||
return false;
|
||||
|
||||
if (_context.getBooleanProperty(Reseeder.PROP_DISABLE)) {
|
||||
String s = "Only " + count + " peers remaining but reseed disabled by configuration";
|
||||
_lastError = s;
|
||||
_log.logAlways(Log.WARN, s);
|
||||
return false;
|
||||
}
|
||||
|
||||
// we check the i2p installation directory for a flag telling us not to reseed,
|
||||
// but also check the home directory for that flag too, since new users installing i2p
|
||||
// don't have an installation directory that they can put the flag in yet.
|
||||
File noReseedFile = new File(new File(System.getProperty("user.home")), ".i2pnoreseed");
|
||||
File noReseedFileAlt1 = new File(new File(System.getProperty("user.home")), "noreseed.i2p");
|
||||
File noReseedFileAlt2 = new File(context.getConfigDir(), ".i2pnoreseed");
|
||||
File noReseedFileAlt3 = new File(context.getConfigDir(), "noreseed.i2p");
|
||||
Log _log = context.logManager().getLog(ReseedChecker.class);
|
||||
File noReseedFileAlt2 = new File(_context.getConfigDir(), ".i2pnoreseed");
|
||||
File noReseedFileAlt3 = new File(_context.getConfigDir(), "noreseed.i2p");
|
||||
if (!noReseedFile.exists() && !noReseedFileAlt1.exists() && !noReseedFileAlt2.exists() && !noReseedFileAlt3.exists()) {
|
||||
if (count <= 1)
|
||||
_log.logAlways(Log.INFO, "Downloading peer router information for a new I2P installation");
|
||||
else
|
||||
_log.logAlways(Log.WARN, "Very few known peers remaining - reseeding now");
|
||||
Reseeder reseeder = new Reseeder(context);
|
||||
reseeder.requestReseed();
|
||||
return requestReseed();
|
||||
} else {
|
||||
_log.logAlways(Log.WARN, "Only " + count + " peers remaining but reseed disabled by config file");
|
||||
String s = "Only " + count + " peers remaining but reseed disabled by config file";
|
||||
_lastError = s;
|
||||
_log.logAlways(Log.WARN, s);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a reseed
|
||||
*
|
||||
* @return true if a reseed was started, false if already in progress
|
||||
* @since 0.9
|
||||
*/
|
||||
public boolean requestReseed() {
|
||||
if (_inProgress.compareAndSet(false, true)) {
|
||||
try {
|
||||
Reseeder reseeder = new Reseeder(_context, this);
|
||||
reseeder.requestReseed();
|
||||
return true;
|
||||
} catch (Throwable t) {
|
||||
_log.error("Reseed failed to start", t);
|
||||
done();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Reseed already in prgress");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is a reseed in progress?
|
||||
*
|
||||
* @since 0.9
|
||||
*/
|
||||
public boolean inProgress() {
|
||||
return _inProgress.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* The reseed is complete
|
||||
*
|
||||
* @since 0.9
|
||||
*/
|
||||
void done() {
|
||||
_inProgress.set(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Status from current reseed attempt,
|
||||
* probably empty if no reseed in progress.
|
||||
*
|
||||
* @return non-null, may be empty
|
||||
* @since 0.9
|
||||
*/
|
||||
public String getStatus() {
|
||||
return _lastStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Status from current reseed attempt
|
||||
*
|
||||
* @param s non-null, may be empty
|
||||
* @since 0.9
|
||||
*/
|
||||
void setStatus(String s) {
|
||||
_lastStatus = s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Error from last or current reseed attempt
|
||||
*
|
||||
* @return non-null, may be empty
|
||||
* @since 0.9
|
||||
*/
|
||||
public String getError() {
|
||||
return _lastError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Status from last or current reseed attempt
|
||||
*
|
||||
* @param s non-null, may be empty
|
||||
* @since 0.9
|
||||
*/
|
||||
void setError(String s) {
|
||||
_lastError = s;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -42,10 +42,9 @@ import net.i2p.util.Translate;
|
||||
* the router log, and the wrapper log.
|
||||
*/
|
||||
public class Reseeder {
|
||||
/** FIXME don't keep a static reference, store _isRunning some other way */
|
||||
private static ReseedRunner _reseedRunner;
|
||||
private final RouterContext _context;
|
||||
private final Log _log;
|
||||
private final ReseedChecker _checker;
|
||||
|
||||
// Reject unreasonably big files, because we download into a ByteArrayOutputStream.
|
||||
private static final long MAX_RESEED_RESPONSE_SIZE = 2 * 1024 * 1024;
|
||||
@ -81,11 +80,6 @@ public class Reseeder {
|
||||
"https://75.145.125.59/netDb/" + "," +
|
||||
"https://i2p.mooo.com/netDb/";
|
||||
|
||||
private static final String PROP_INPROGRESS = "net.i2p.router.web.ReseedHandler.reseedInProgress";
|
||||
/** the console shows this message while reseedInProgress == false */
|
||||
private static final String PROP_ERROR = "net.i2p.router.web.ReseedHandler.errorMessage";
|
||||
/** the console shows this message while reseedInProgress == true */
|
||||
private static final String PROP_STATUS = "net.i2p.router.web.ReseedHandler.statusMessage";
|
||||
public static final String PROP_PROXY_HOST = "router.reseedProxyHost";
|
||||
public static final String PROP_PROXY_PORT = "router.reseedProxyPort";
|
||||
/** @since 0.8.2 */
|
||||
@ -106,32 +100,27 @@ public class Reseeder {
|
||||
public static final String PROP_SPROXY_USERNAME = "router.reseedSSLProxy.username";
|
||||
public static final String PROP_SPROXY_PASSWORD = "router.reseedSSLProxy.password";
|
||||
public static final String PROP_SPROXY_AUTH_ENABLE = "router.reseedSSLProxy.authEnable";
|
||||
/** @since 0.9 */
|
||||
public static final String PROP_DISABLE = "router.reseedDisable";
|
||||
|
||||
// from PersistentDataStore
|
||||
private static final String ROUTERINFO_PREFIX = "routerInfo-";
|
||||
private static final String ROUTERINFO_SUFFIX = ".dat";
|
||||
|
||||
public Reseeder(RouterContext ctx) {
|
||||
Reseeder(RouterContext ctx, ReseedChecker rc) {
|
||||
_context = ctx;
|
||||
_log = ctx.logManager().getLog(Reseeder.class);
|
||||
_checker = rc;
|
||||
}
|
||||
|
||||
public void requestReseed() {
|
||||
synchronized (Reseeder.class) {
|
||||
if (_reseedRunner == null)
|
||||
_reseedRunner = new ReseedRunner();
|
||||
if (_reseedRunner.isRunning()) {
|
||||
return;
|
||||
} else {
|
||||
// set to daemon so it doesn't hang a shutdown
|
||||
Thread reseed = new I2PAppThread(_reseedRunner, "Reseed", true);
|
||||
reseed.start();
|
||||
}
|
||||
}
|
||||
|
||||
void requestReseed() {
|
||||
ReseedRunner reseedRunner = new ReseedRunner();
|
||||
// set to daemon so it doesn't hang a shutdown
|
||||
Thread reseed = new I2PAppThread(reseedRunner, "Reseed", true);
|
||||
reseed.start();
|
||||
}
|
||||
|
||||
public class ReseedRunner implements Runnable, EepGet.StatusListener {
|
||||
private class ReseedRunner implements Runnable, EepGet.StatusListener {
|
||||
private boolean _isRunning;
|
||||
private String _proxyHost;
|
||||
private int _proxyPort;
|
||||
@ -143,20 +132,21 @@ public class Reseeder {
|
||||
public ReseedRunner() {
|
||||
}
|
||||
|
||||
public boolean isRunning() { return _isRunning; }
|
||||
|
||||
/*
|
||||
* Do it.
|
||||
* We update PROP_ERROR here.
|
||||
*/
|
||||
public void run() {
|
||||
try {
|
||||
run2();
|
||||
} finally {
|
||||
_checker.done();
|
||||
}
|
||||
}
|
||||
|
||||
private void run2() {
|
||||
_isRunning = true;
|
||||
System.clearProperty(PROP_ERROR);
|
||||
System.setProperty(PROP_STATUS, _("Reseeding"));
|
||||
System.setProperty(PROP_INPROGRESS, "true");
|
||||
_attemptStarted = 0;
|
||||
_gotDate = 0;
|
||||
_sslState = null; // start fresh
|
||||
_checker.setError("");
|
||||
_checker.setStatus(_("Reseeding"));
|
||||
if (_context.getBooleanProperty(PROP_PROXY_ENABLE)) {
|
||||
_proxyHost = _context.getProperty(PROP_PROXY_HOST);
|
||||
_proxyPort = _context.getProperty(PROP_PROXY_PORT, -1);
|
||||
@ -165,24 +155,22 @@ public class Reseeder {
|
||||
int total = reseed(false);
|
||||
if (total >= 50) {
|
||||
System.out.println("Reseed complete, " + total + " received");
|
||||
System.clearProperty(PROP_ERROR);
|
||||
_checker.setError("");
|
||||
} else if (total > 0) {
|
||||
System.out.println("Reseed complete, only " + total + " received");
|
||||
System.setProperty(PROP_ERROR, ngettext("Reseed fetched only 1 router.",
|
||||
_checker.setError(ngettext("Reseed fetched only 1 router.",
|
||||
"Reseed fetched only {0} routers.", total));
|
||||
} else {
|
||||
System.out.println("Reseed failed, check network connection");
|
||||
System.out.println(
|
||||
"Ensure that nothing blocks outbound HTTP, check the logs, " +
|
||||
"and if nothing helps, read the FAQ about reseeding manually.");
|
||||
System.setProperty(PROP_ERROR, _("Reseed failed.") + ' ' +
|
||||
_checker.setError(_("Reseed failed.") + ' ' +
|
||||
_("See {0} for help.",
|
||||
"<a target=\"_top\" href=\"/configreseed\">" + _("reseed configuration page") + "</a>"));
|
||||
}
|
||||
System.setProperty(PROP_INPROGRESS, "false");
|
||||
System.clearProperty(PROP_STATUS);
|
||||
_sslState = null; // don't hold ref
|
||||
_isRunning = false;
|
||||
_checker.setStatus("");
|
||||
}
|
||||
|
||||
// EepGet status listeners
|
||||
@ -311,7 +299,7 @@ public class Reseeder {
|
||||
* Jetty directory listings are not compatible, as they look like
|
||||
* HREF="/full/path/to/routerInfo-...
|
||||
*
|
||||
* We update PROP_STATUS here.
|
||||
* We update the status here.
|
||||
*
|
||||
* @param echoStatus apparently always false
|
||||
* @return count of routerinfos successfully fetched
|
||||
@ -320,7 +308,7 @@ public class Reseeder {
|
||||
try {
|
||||
// Don't use context clock as we may be adjusting the time
|
||||
final long timeLimit = System.currentTimeMillis() + MAX_TIME_PER_HOST;
|
||||
System.setProperty(PROP_STATUS, _("Reseeding: fetching seed URL."));
|
||||
_checker.setStatus(_("Reseeding: fetching seed URL."));
|
||||
System.err.println("Reseeding from " + seedURL);
|
||||
URL dir = new URL(seedURL);
|
||||
byte contentRaw[] = readURL(dir);
|
||||
@ -377,7 +365,7 @@ public class Reseeder {
|
||||
for (Iterator<String> iter = urlList.iterator();
|
||||
iter.hasNext() && fetched < 200 && System.currentTimeMillis() < timeLimit; ) {
|
||||
try {
|
||||
System.setProperty(PROP_STATUS,
|
||||
_checker.setStatus(
|
||||
_("Reseeding: fetching router info from seed URL ({0} successful, {1} errors).", fetched, errors));
|
||||
|
||||
if (!fetchSeed(seedURL, iter.next()))
|
||||
|
Reference in New Issue
Block a user