- Only fail after all URLs are tried

- Move registration from servlet to manager and delay
- Fix plugin updates
- More logging
This commit is contained in:
zzz
2012-10-21 17:14:54 +00:00
parent 0fc452b683
commit 8b2889e317
8 changed files with 69 additions and 36 deletions

View File

@ -27,6 +27,7 @@ import java.util.concurrent.LinkedBlockingQueue;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.data.Base64; import net.i2p.data.Base64;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.update.*;
import net.i2p.util.ConcurrentHashSet; import net.i2p.util.ConcurrentHashSet;
import net.i2p.util.FileUtil; import net.i2p.util.FileUtil;
import net.i2p.util.I2PAppThread; import net.i2p.util.I2PAppThread;
@ -65,6 +66,8 @@ public class SnarkManager implements CompleteListener {
private volatile boolean _running; private volatile boolean _running;
private volatile boolean _stopping; private volatile boolean _stopping;
private final Map<String, Tracker> _trackerMap; private final Map<String, Tracker> _trackerMap;
private UpdateManager _umgr;
private UpdateHandler _uhandler;
public static final String PROP_I2CP_HOST = "i2psnark.i2cpHost"; public static final String PROP_I2CP_HOST = "i2psnark.i2cpHost";
public static final String PROP_I2CP_PORT = "i2psnark.i2cpPort"; public static final String PROP_I2CP_PORT = "i2psnark.i2cpPort";
@ -149,10 +152,28 @@ public class SnarkManager implements CompleteListener {
_connectionAcceptor = new ConnectionAcceptor(_util); _connectionAcceptor = new ConnectionAcceptor(_util);
_monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor", true); _monitor = new I2PAppThread(new DirMonitor(), "Snark DirMonitor", true);
_monitor.start(); _monitor.start();
// delay until UpdateManager is there
_context.simpleScheduler().addEvent(new Register(), 4*60*1000);
// Not required, Jetty has a shutdown hook // Not required, Jetty has a shutdown hook
//_context.addShutdownTask(new SnarkManagerShutdown()); //_context.addShutdownTask(new SnarkManagerShutdown());
} }
/** @since 0.9.4 */
private class Register implements SimpleTimer.TimedEvent {
public void timeReached() {
if (!_running)
return;
_umgr = _context.updateManager();
if (_umgr != null) {
_uhandler = new UpdateHandler(_context, _umgr, SnarkManager.this);
_umgr.register(_uhandler, UpdateType.ROUTER_SIGNED, UpdateMethod.TORRENT, 10);
_log.warn("Registering with update manager");
} else {
_log.warn("No update manager to register with");
}
}
}
/* /*
* Called by the webapp at Jetty shutdown. * Called by the webapp at Jetty shutdown.
* Stops all torrents. Does not close the tunnel, so the announces have a chance. * Stops all torrents. Does not close the tunnel, so the announces have a chance.
@ -160,6 +181,10 @@ public class SnarkManager implements CompleteListener {
* Runs inline. * Runs inline.
*/ */
public void stop() { public void stop() {
if (_umgr != null && _uhandler != null) {
//_uhandler.shutdown();
_umgr.unregister(_uhandler, UpdateType.ROUTER_SIGNED, UpdateMethod.TORRENT);
}
_running = false; _running = false;
_monitor.interrupt(); _monitor.interrupt();
_connectionAcceptor.halt(); _connectionAcceptor.halt();

View File

@ -21,7 +21,7 @@ import net.i2p.update.*;
* *
* @since 0.9.4 * @since 0.9.4
*/ */
public class UpdateHandler implements Updater { class UpdateHandler implements Updater {
private final I2PAppContext _context; private final I2PAppContext _context;
private final UpdateManager _umgr; private final UpdateManager _umgr;
private final SnarkManager _smgr; private final SnarkManager _smgr;

View File

@ -30,7 +30,6 @@ import javax.servlet.http.HttpServletResponse;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.data.Base64; import net.i2p.data.Base64;
import net.i2p.data.DataHelper; import net.i2p.data.DataHelper;
import net.i2p.update.*;
import net.i2p.util.I2PAppThread; import net.i2p.util.I2PAppThread;
import net.i2p.util.Log; import net.i2p.util.Log;
@ -43,7 +42,6 @@ import org.klomp.snark.SnarkManager;
import org.klomp.snark.Storage; import org.klomp.snark.Storage;
import org.klomp.snark.Tracker; import org.klomp.snark.Tracker;
import org.klomp.snark.TrackerClient; import org.klomp.snark.TrackerClient;
import org.klomp.snark.UpdateHandler;
import org.klomp.snark.dht.DHT; import org.klomp.snark.dht.DHT;
import org.mortbay.jetty.servlet.DefaultServlet; import org.mortbay.jetty.servlet.DefaultServlet;
@ -59,8 +57,6 @@ public class I2PSnarkServlet extends DefaultServlet {
private I2PAppContext _context; private I2PAppContext _context;
private Log _log; private Log _log;
private SnarkManager _manager; private SnarkManager _manager;
private UpdateManager _umgr;
private UpdateHandler _uhandler;
private static long _nonce; private static long _nonce;
private Resource _resourceBase; private Resource _resourceBase;
private String _themePath; private String _themePath;
@ -80,11 +76,6 @@ public class I2PSnarkServlet extends DefaultServlet {
configFile = "i2psnark.config"; configFile = "i2psnark.config";
_manager.loadConfig(configFile); _manager.loadConfig(configFile);
_manager.start(); _manager.start();
_umgr = _context.updateManager();
if (_umgr != null) {
_uhandler = new UpdateHandler(_context, _umgr, _manager);
_umgr.register(_uhandler, UpdateType.ROUTER_SIGNED, UpdateMethod.TORRENT, 10);
}
try { try {
_resourceBase = Resource.newResource(_manager.getDataDir().getAbsolutePath()); _resourceBase = Resource.newResource(_manager.getDataDir().getAbsolutePath());
} catch (IOException ioe) {} } catch (IOException ioe) {}
@ -95,10 +86,6 @@ public class I2PSnarkServlet extends DefaultServlet {
public void destroy() { public void destroy() {
if (_manager != null) if (_manager != null)
_manager.stop(); _manager.stop();
if (_umgr != null && _uhandler != null) {
//_uhandler.shutdown();
_umgr.unregister(_uhandler, UpdateType.ROUTER_SIGNED, UpdateMethod.TORRENT);
}
super.destroy(); super.destroy();
} }

View File

@ -62,7 +62,7 @@ public class ConsoleUpdateManager implements UpdateManager {
/** active updating tasks, pointing to the next ones to try */ /** active updating tasks, pointing to the next ones to try */
private final Map<UpdateTask, List<RegisteredUpdater>> _downloaders; private final Map<UpdateTask, List<RegisteredUpdater>> _downloaders;
/** as reported by checkers */ /** as reported by checkers */
private final Map<UpdateItem, VersionAvailable> _available; private final ConcurrentHashMap<UpdateItem, VersionAvailable> _available;
/** downloaded but NOT installed */ /** downloaded but NOT installed */
private final Map<UpdateItem, Version> _downloaded; private final Map<UpdateItem, Version> _downloaded;
/** downloaded AND installed */ /** downloaded AND installed */
@ -406,15 +406,19 @@ public class ConsoleUpdateManager implements UpdateManager {
/** /**
* Install a plugin. Non-blocking. * Install a plugin. Non-blocking.
* If returns true, then call isUpdateInProgress() in a loop * If returns true, then call isUpdateInProgress() in a loop
* @param name if null, a new install
* @return true if task started * @return true if task started
*/ */
public boolean installPlugin(URI uri) { public boolean installPlugin(String name, URI uri) {
String fakeName = Long.toString(_context.random().nextLong()); if (name == null)
name = Long.toString(_context.random().nextLong());
List<URI> uris = Collections.singletonList(uri); List<URI> uris = Collections.singletonList(uri);
UpdateItem fake = new UpdateItem(PLUGIN_INSTALL, fakeName); UpdateItem item = new UpdateItem(PLUGIN_INSTALL, name);
VersionAvailable va = new VersionAvailable("", "", HTTP, uris); VersionAvailable va = new VersionAvailable("", "", HTTP, uris);
_available.put(fake, va); _available.putIfAbsent(item, va);
return update(PLUGIN_INSTALL, fakeName); if (_log.shouldLog(Log.WARN))
_log.warn("Install plugin: " + name + ' ' + va);
return update(PLUGIN_INSTALL, name);
} }
/** /**
@ -479,8 +483,11 @@ public class ConsoleUpdateManager implements UpdateManager {
List<URI> updateSources = null; List<URI> updateSources = null;
UpdateItem ui = new UpdateItem(type, id); UpdateItem ui = new UpdateItem(type, id);
VersionAvailable va = _available.get(ui); VersionAvailable va = _available.get(ui);
if (va == null) if (va == null) {
if (_log.shouldLog(Log.WARN))
_log.warn("No version available for: " + type + ' ' + id);
return false; return false;
}
List<RegisteredUpdater> sorted = new ArrayList(_registeredUpdaters); List<RegisteredUpdater> sorted = new ArrayList(_registeredUpdaters);
Collections.sort(sorted); Collections.sort(sorted);
return retry(ui, va.sourceMap, sorted, maxTime) != null; return retry(ui, va.sourceMap, sorted, maxTime) != null;
@ -505,14 +512,21 @@ public class ConsoleUpdateManager implements UpdateManager {
if (t != null) { if (t != null) {
// race window here // race window here
// store the remaining ones for retrying // store the remaining ones for retrying
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
_log.info("Starting " + r); _log.info("Starting " + r);
_downloaders.put(t, toTry); _downloaders.put(t, toTry);
return t; return t;
} else {
if (_log.shouldLog(Log.WARN))
_log.warn("Updater refused: " + r + " for " + meth + ' ' + e.getValue());
} }
} }
} }
if (_log.shouldLog(Log.WARN))
_log.warn("Nothing left to try for: " + r);
} }
if (_log.shouldLog(Log.WARN))
_log.warn("Nothing left to try for: " + ui);
return null; return null;
} }
@ -1097,7 +1111,7 @@ public class ConsoleUpdateManager implements UpdateManager {
@Override @Override
public String toString() { public String toString() {
return "RegisteredUpdater " + updater.getClass().getSimpleName() + " for " + type + ' ' + method + " @pri " + priority; return "RegisteredUpdater " + updater.getClass() + " for " + type + ' ' + method + " @pri " + priority;
} }
} }
@ -1138,7 +1152,7 @@ public class ConsoleUpdateManager implements UpdateManager {
@Override @Override
public String toString() { public String toString() {
return "RegisteredChecker " + checker.getClass().getSimpleName() + " for " + type + ' ' + method + " @pri " + priority; return "RegisteredChecker " + checker.getClass() + " for " + type + ' ' + method + " @pri " + priority;
} }
} }
@ -1206,7 +1220,7 @@ public class ConsoleUpdateManager implements UpdateManager {
@Override @Override
public String toString() { public String toString() {
return "VersionAvailable " + version + ' ' + sourceMap; return "VersionAvailable \"" + version + "\" " + sourceMap;
} }
} }
} }

View File

@ -70,10 +70,9 @@ class PluginUpdateHandler implements Checker, Updater {
return null; return null;
Properties props = PluginStarter.pluginProperties(_context, appName); Properties props = PluginStarter.pluginProperties(_context, appName);
String oldVersion = props.getProperty("version"); String oldVersion = props.getProperty("version");
String xpi2pURL = props.getProperty("updateURL"); if (oldVersion == null) {
if (oldVersion == null || xpi2pURL == null) { // assume new install
//updateStatus("<b>" + _("Cannot check, plugin {0} is not installed", appName) + "</b>"); oldVersion = "0";
return null;
} }
UpdateRunner update = new PluginUpdateRunner(_context, _mgr, updateSources, appName, oldVersion); UpdateRunner update = new PluginUpdateRunner(_context, _mgr, updateSources, appName, oldVersion);

View File

@ -111,6 +111,8 @@ class PluginUpdateRunner extends UpdateRunner {
_log.error("Error downloading plugin", t); _log.error("Error downloading plugin", t);
} }
} }
if (!_updated)
_mgr.notifyTaskFailed(this, "", null);
} }
@Override @Override

View File

@ -167,6 +167,7 @@ class UpdateRunner extends I2PAppThread implements UpdateTask, EepGet.StatusList
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug("Attempt failed on " + url, cause); _log.debug("Attempt failed on " + url, cause);
// ignored // ignored
_mgr.notifyAttemptFailed(this, url, null);
} }
/** subclasses should override */ /** subclasses should override */
@ -204,10 +205,12 @@ class UpdateRunner extends I2PAppThread implements UpdateTask, EepGet.StatusList
/** subclasses should override */ /** subclasses should override */
public void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt) { public void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt) {
// don't display bytesTransferred as it is meaningless // don't display bytesTransferred as it is meaningless
_log.error("Update from " + url + " did not download completely (" + if (_log.shouldLog(Log.WARN))
_log.warn("Update from " + url + " did not download completely (" +
bytesRemaining + " remaining after " + currentAttempt + " tries)"); bytesRemaining + " remaining after " + currentAttempt + " tries)");
updateStatus("<b>" + _("Transfer failed from {0}", linkify(url)) + "</b>"); updateStatus("<b>" + _("Transfer failed from {0}", linkify(url)) + "</b>");
_mgr.notifyTaskFailed(this, "", null); _mgr.notifyAttemptFailed(this, url, null);
// update() will call notifyTaskFailed() after last URL
} }
public void headerReceived(String url, int attemptNum, String key, String val) {} public void headerReceived(String url, int attemptNum, String key, String val) {}

View File

@ -322,7 +322,7 @@ public class ConfigClientsHandler extends FormHandler {
addFormError(_("No plugin URL specified.")); addFormError(_("No plugin URL specified."));
return; return;
} }
installPlugin(url); installPlugin(null, url);
} }
private void updatePlugin(String app) { private void updatePlugin(String app) {
@ -332,7 +332,7 @@ public class ConfigClientsHandler extends FormHandler {
addFormError(_("No update URL specified for {0}",app)); addFormError(_("No update URL specified for {0}",app));
return; return;
} }
installPlugin(url); installPlugin(app, url);
} }
/** @since 0.8.13 */ /** @since 0.8.13 */
@ -349,7 +349,10 @@ public class ConfigClientsHandler extends FormHandler {
} catch (InterruptedException ie) {} } catch (InterruptedException ie) {}
} }
private void installPlugin(String url) { /**
* @param app null for a new install
*/
private void installPlugin(String app, String url) {
ConsoleUpdateManager mgr = (ConsoleUpdateManager) _context.updateManager(); ConsoleUpdateManager mgr = (ConsoleUpdateManager) _context.updateManager();
if (mgr == null) { if (mgr == null) {
addFormError("Update manager not registered, cannot install"); addFormError("Update manager not registered, cannot install");
@ -366,7 +369,7 @@ public class ConfigClientsHandler extends FormHandler {
addFormError(_("Bad URL {0}", url)); addFormError(_("Bad URL {0}", url));
return; return;
} }
if (mgr.installPlugin(uri)) if (mgr.installPlugin(app, uri))
addFormNotice(_("Downloading plugin from {0}", url)); addFormNotice(_("Downloading plugin from {0}", url));
else else
addFormError("Cannot install, check logs"); addFormError("Cannot install, check logs");