- Lots of fixes for notifying when updates and checks are complete

- Fixes for NewsHelper stored timestamps
- Add getProperty(String, long) to context for sanity
- New methods and types
- Logging improvements
- Add failsafe TaskCleaner
This commit is contained in:
zzz
2012-10-18 14:28:14 +00:00
parent 2b50c5aaf4
commit 0b4401e64b
13 changed files with 145 additions and 76 deletions

View File

@@ -75,6 +75,8 @@ public class ConsoleUpdateManager implements UpdateManager {
private static final long DEFAULT_MAX_TIME = 3*60*60*1000L;
private static final long DEFAULT_CHECK_TIME = 60*1000;
private static final long STATUS_CLEAN_TIME = 20*60*1000;
private static final long TASK_CLEANER_TIME = 15*60*1000;
public ConsoleUpdateManager(RouterContext ctx) {
_context = ctx;
@@ -124,6 +126,7 @@ public class ConsoleUpdateManager implements UpdateManager {
register((Checker)puh, PLUGIN_INSTALL, HTTP, 0);
register((Updater)puh, PLUGIN_INSTALL, HTTP, 0);
new NewsTimerTask(_context);
_context.simpleScheduler().addPeriodicEvent(new TaskCleaner(), TASK_CLEANER_TIME);
}
public void shutdown() {
@@ -167,8 +170,11 @@ public class ConsoleUpdateManager implements UpdateManager {
UpdateTask t;
synchronized(_activeCheckers) {
t = r.checker.check(type, r.method, id, current, maxWait);
if (t != null)
if (t != null) {
if (_log.shouldLog(Log.INFO))
_log.info("Starting " + r);
_activeCheckers.add(t);
}
}
if (t != null) {
synchronized(t) {
@@ -198,7 +204,7 @@ public class ConsoleUpdateManager implements UpdateManager {
public void check(UpdateType type, String id) {
if (isCheckInProgress(type, id)) {
if (_log.shouldLog(Log.WARN))
_log.warn("Check or update already in progress for: " + type + ' ' + id);
_log.warn("Check already in progress for: " + type + ' ' + id);
return;
}
for (RegisteredChecker r : _registeredCheckers) {
@@ -207,6 +213,8 @@ public class ConsoleUpdateManager implements UpdateManager {
synchronized(_activeCheckers) {
UpdateTask t = r.checker.check(type, r.method, id, current, DEFAULT_CHECK_TIME);
if (t != null) {
if (_log.shouldLog(Log.INFO))
_log.info("Starting " + r);
_activeCheckers.add(t);
break;
}
@@ -489,6 +497,8 @@ public class ConsoleUpdateManager implements UpdateManager {
if (t != null) {
// race window here
// store the remaining ones for retrying
if (_log.shouldLog(Log.INFO))
_log.info("Starting " + r);
_downloaders.put(t, toTry);
return t;
}
@@ -624,7 +634,7 @@ public class ConsoleUpdateManager implements UpdateManager {
*/
public void notifyCheckComplete(UpdateTask task, boolean newer, boolean success) {
if (_log.shouldLog(Log.INFO))
_log.info(task.toString() + " complete");
_log.info("Checker " + task + " for " + task.getType() + " complete");
synchronized(_activeCheckers) {
_activeCheckers.remove(task);
}
@@ -688,7 +698,8 @@ public class ConsoleUpdateManager implements UpdateManager {
* @param t may be null
*/
public void notifyAttemptFailed(UpdateTask task, String reason, Throwable t) {
_log.warn("Attempt failed " + task + ": " + reason, t);
if (_log.shouldLog(Log.WARN))
_log.warn("Attempt failed " + task + " for " + task.getType() + ": " + reason, t);
}
/**
@@ -697,7 +708,7 @@ public class ConsoleUpdateManager implements UpdateManager {
*/
public void notifyTaskFailed(UpdateTask task, String reason, Throwable t) {
if (_log.shouldLog(Log.WARN))
_log.warn("Failed " + task + ": " + reason, t);
_log.warn("Failed " + task + " for " + task.getType() + ": " + reason, t);
List<RegisteredUpdater> toTry = _downloaders.get(task);
if (toTry != null) {
UpdateItem ui = new UpdateItem(task.getType(), task.getID());
@@ -711,6 +722,7 @@ public class ConsoleUpdateManager implements UpdateManager {
}
}
_downloaders.remove(task);
_activeCheckers.remove(task);
///// for certain types only
finishStatus("<b>" + _("Transfer failed from {0}", linkify(task.getURI().toString())) + "</b>");
}
@@ -729,7 +741,7 @@ public class ConsoleUpdateManager implements UpdateManager {
*/
public boolean notifyComplete(UpdateTask task, String actualVersion, File file) {
if (_log.shouldLog(Log.INFO))
_log.info(task.toString() + " complete");
_log.info("Updater " + task + " for " + task.getType() + " complete");
boolean rv = false;
switch (task.getType()) {
case TYPE_DUMMY:
@@ -1004,12 +1016,12 @@ public class ConsoleUpdateManager implements UpdateManager {
private void finishStatus(String msg) {
updateStatus(msg);
_context.simpleScheduler().addEvent(new Cleaner(msg), 20*60*1000);
_context.simpleScheduler().addEvent(new StatusCleaner(msg), STATUS_CLEAN_TIME);
}
private class Cleaner implements SimpleTimer.TimedEvent {
private class StatusCleaner implements SimpleTimer.TimedEvent {
private final String _msg;
public Cleaner(String msg) {
public StatusCleaner(String msg) {
_msg = msg;
}
public void timeReached() {
@@ -1018,6 +1030,36 @@ public class ConsoleUpdateManager implements UpdateManager {
}
}
/**
* Failsafe
*/
private class TaskCleaner implements SimpleTimer.TimedEvent {
public void timeReached() {
if (!_activeCheckers.isEmpty()) {
synchronized(_activeCheckers) {
for (Iterator<UpdateTask> iter = _activeCheckers.iterator(); iter.hasNext(); ) {
UpdateTask t = iter.next();
if (!t.isRunning()) {
if (_log.shouldLog(Log.WARN))
_log.warn("Failsafe remove checker " + t);
iter.remove();
}
}
}
}
if (!_downloaders.isEmpty()) {
for (Iterator<UpdateTask> iter = _downloaders.keySet().iterator(); iter.hasNext(); ) {
UpdateTask t = iter.next();
if (!t.isRunning()) {
if (_log.shouldLog(Log.WARN))
_log.warn("Failsafe remove downloader " + t);
iter.remove();
}
}
}
}
}
/**
* Equals on updater, type and method only
*/

View File

@@ -37,6 +37,9 @@ class NewsFetcher extends UpdateRunner {
private String _lastModified;
private final File _newsFile;
private final File _tempFile;
/** is the news newer */
private boolean _isNewer;
private boolean _success;
private static final String TEMP_NEWS_FILE = "news.xml.temp";
@@ -65,8 +68,14 @@ class NewsFetcher extends UpdateRunner {
}
@Override
public void update() {
fetchNews();
public void run() {
_isRunning = true;
try {
fetchNews();
} finally {
_mgr.notifyCheckComplete(this, _isNewer, _success);
_isRunning = false;
}
}
public void fetchNews() {
@@ -93,8 +102,9 @@ class NewsFetcher extends UpdateRunner {
if (lastMod != null) {
_lastModified = lastMod;
long lm = RFC822Date.parse822Date(lastMod);
if (lm > 0)
_context.router().saveConfig(NewsHelper.PROP_LAST_CHECKED, Long.toString(lm));
if (lm == 0)
lm = _context.clock().now();
_context.router().saveConfig(NewsHelper.PROP_LAST_CHECKED, Long.toString(lm));
}
return;
}
@@ -107,8 +117,6 @@ class NewsFetcher extends UpdateRunner {
private static final String VERSION_STRING = "version=\"" + RouterVersion.VERSION + "\"";
private static final String VERSION_PREFIX = "version=\"";
///// move to UpdateManager?
/**
* Parse the installed (not the temp) news file for the latest version.
* TODO: Real XML parsing, different update methods,
@@ -181,6 +189,7 @@ class NewsFetcher extends UpdateRunner {
_context.router().saveConfig(NewsHelper.PROP_LAST_UPDATED, newVer);
_mgr.notifyVersionAvailable(this, _currentURI, NEWS, "", HTTP,
null, newVer, "");
_isNewer = true;
checkForUpdates();
} else {
if (_log.shouldLog(Log.ERROR))
@@ -190,6 +199,7 @@ class NewsFetcher extends UpdateRunner {
if (_log.shouldLog(Log.WARN))
_log.warn("Transfer complete, but no file? - probably 304 Not Modified");
}
_success = true;
}
/** override to prevent status update */

View File

@@ -8,11 +8,15 @@ import java.util.List;
import net.i2p.router.RouterContext;
import net.i2p.router.web.ConfigUpdateHelper;
import net.i2p.update.*;
import static net.i2p.update.UpdateType.*;
import static net.i2p.update.UpdateMethod.*;
/**
* Task to periodically look for updates to the news.xml, and to keep
* track of whether that has an announcement for a new version.
*
* Overrides UpdateRunner for convenience, this is not an Updater
*
* @since 0.9.4 moved from NewsFetcher
*/
class NewsHandler extends UpdateHandler implements Checker {
@@ -31,8 +35,8 @@ class NewsHandler extends UpdateHandler implements Checker {
*/
public UpdateTask check(UpdateType type, UpdateMethod method,
String id, String currentVersion, long maxTime) {
if ((type != UpdateType.ROUTER_SIGNED && type != UpdateType.ROUTER_SIGNED_PACK200 && type != UpdateType.NEWS) ||
method != UpdateMethod.HTTP)
if ((type != ROUTER_SIGNED && type != ROUTER_SIGNED_PACK200 && type != NEWS) ||
method != HTTP)
return null;
List<URI> updateSources = new ArrayList(2);
try {

View File

@@ -43,9 +43,18 @@ class PluginUpdateChecker extends UpdateRunner {
_oldVersion = oldVersion;
}
@Override
public UpdateType getType() { return UpdateType.PLUGIN; }
@Override
public void run() {
_isRunning = true;
try {
update();
} finally {
_isRunning = false;
}
}
@Override
protected void update() {

View File

@@ -46,9 +46,9 @@ class UnsignedUpdateChecker extends UpdateRunner {
try {
success = fetchUnsignedHead();
} finally {
_mgr.notifyCheckComplete(this, _unsignedUpdateAvailable, success);
_isRunning = false;
}
_mgr.notifyCheckComplete(this, _unsignedUpdateAvailable, success);
}

View File

@@ -12,6 +12,8 @@ import net.i2p.router.util.RFC822Date;
import net.i2p.router.web.ConfigUpdateHandler;
import net.i2p.router.web.NewsHelper;
import net.i2p.update.*;
import static net.i2p.update.UpdateType.*;
import static net.i2p.update.UpdateMethod.*;
import net.i2p.util.EepGet;
import net.i2p.util.FileUtil;
import net.i2p.util.I2PAppThread;
@@ -54,18 +56,7 @@ class UnsignedUpdateHandler implements Checker, Updater {
return null;
}
String lastUpdate = _context.getProperty(NewsHelper.PROP_LAST_UPDATE_TIME);
if (lastUpdate == null) {
// we don't know what version you have, so stamp it with the current time,
// and we'll look for something newer next time around.
_context.router().saveConfig(NewsHelper.PROP_LAST_UPDATE_TIME,
Long.toString(_context.clock().now()));
return null;
}
long ms = 0;
try {
ms = Long.parseLong(lastUpdate);
} catch (NumberFormatException nfe) {}
long ms = _context.getProperty(NewsHelper.PROP_LAST_UPDATE_TIME, 0L);
if (ms <= 0) {
// we don't know what version you have, so stamp it with the current time,
// and we'll look for something newer next time around.
@@ -90,7 +81,7 @@ class UnsignedUpdateHandler implements Checker, Updater {
@Override
public UpdateTask update(UpdateType type, UpdateMethod method, List<URI> updateSources,
String id, String newVersion, long maxTime) {
if (type != UpdateType.ROUTER_UNSIGNED || method != UpdateMethod.HTTP || updateSources.isEmpty())
if (type != ROUTER_UNSIGNED || method != HTTP || updateSources.isEmpty())
return null;
UpdateRunner update = new UnsignedUpdateRunner(_context, updateSources);
update.start();

View File

@@ -9,6 +9,7 @@ import net.i2p.router.RouterContext;
import net.i2p.router.util.RFC822Date;
import net.i2p.router.web.ConfigUpdateHandler;
import net.i2p.update.*;
import static net.i2p.update.UpdateType.*;
import net.i2p.util.EepGet;
import net.i2p.util.FileUtil;
import net.i2p.util.I2PAppThread;
@@ -31,7 +32,7 @@ class UnsignedUpdateRunner extends UpdateRunner {
@Override
public UpdateType getType() { return UpdateType.ROUTER_UNSIGNED; }
public UpdateType getType() { return ROUTER_UNSIGNED; }
/** Get the file */

View File

@@ -83,6 +83,8 @@ class UpdateRunner extends I2PAppThread implements UpdateTask, EepGet.StatusList
_isRunning = true;
try {
update();
} catch (Throwable t) {
_mgr.notifyTaskFailed(this, "", t);
} finally {
_isRunning = false;
}
@@ -207,6 +209,7 @@ class UpdateRunner extends I2PAppThread implements UpdateTask, EepGet.StatusList
_log.error("Update from " + url + " did not download completely (" +
bytesRemaining + " remaining after " + currentAttempt + " tries)");
updateStatus("<b>" + _("Transfer failed from {0}", linkify(url)) + "</b>");
_mgr.notifyTaskFailed(this, "", null);
}
public void headerReceived(String url, int attemptNum, String key, String val) {}