* Updates:

- Notify manager about all available update methods at once, so the priority
     system works and it doesn't only update via HTTP
   - Start router update download at startup if available
   - Only check plugins when core version increases, not decreases, so we
     don't update plugins when downgrading
   - Limit length of URL shown on summary bar
This commit is contained in:
zzz
2013-04-19 11:49:22 +00:00
parent ca1e8d09cc
commit 1e5ffe636f
7 changed files with 149 additions and 44 deletions

View File

@ -101,6 +101,7 @@ public class ConsoleUpdateManager implements UpdateManager {
notifyInstalled(NEWS, "", Long.toString(NewsHelper.lastUpdated(_context)));
notifyInstalled(ROUTER_SIGNED, "", RouterVersion.VERSION);
// hack to init from the current news file... do this before we register Updaters
// This will not kick off any Updaters as none are yet registered
(new NewsFetcher(_context, this, Collections.EMPTY_LIST)).checkForUpdates();
for (String plugin : PluginStarter.getPlugins()) {
Properties props = PluginStarter.pluginProperties(_context, plugin);
@ -608,6 +609,7 @@ public class ConsoleUpdateManager implements UpdateManager {
/**
* Called by the Updater, either after check() was called, or it found out on its own.
* Use this if there is only one UpdateMethod; otherwise use the Map method below.
*
* @param newsSource who told us
* @param id plugin name for plugins, ignored otherwise
@ -620,50 +622,95 @@ public class ConsoleUpdateManager implements UpdateManager {
UpdateType type, String id,
UpdateMethod method, List<URI> updateSources,
String newVersion, String minVersion) {
return notifyVersionAvailable(task, newsSource, type, id,
Collections.singletonMap(method, updateSources),
newVersion, minVersion);
}
/**
* Called by the Checker, either after check() was called, or it found out on its own.
* Checkers must use this method if there are multiple UpdateMethods discoverd simultaneously.
*
* @param newsSource who told us
* @param id plugin name for plugins, ignored otherwise
* @param sourceMap Mapping of methods to sources
* @param newVersion The new version available
* @param minVersion The minimum installed version to be able to update to newVersion
* @return true if we didn't know already
* @since 0.9.6
*/
public boolean notifyVersionAvailable(UpdateTask task, URI newsSource,
UpdateType type, String id,
Map<UpdateMethod, List<URI>> sourceMap,
String newVersion, String minVersion) {
if (type == NEWS) {
// shortcut
notifyInstalled(NEWS, "", newVersion);
return true;
}
UpdateItem ui = new UpdateItem(type, id);
VersionAvailable newVA = new VersionAvailable(newVersion, minVersion, method, updateSources);
Version old = _installed.get(ui);
if (_log.shouldLog(Log.INFO))
_log.info("notifyVersionAvailable " + ui + ' ' + newVA + " old: " + old);
if (old != null && old.compareTo(newVA) >= 0) {
if (_log.shouldLog(Log.WARN))
_log.warn(ui.toString() + ' ' + old + " already installed");
return false;
}
old = _downloaded.get(ui);
if (old != null && old.compareTo(newVA) >= 0) {
if (_log.shouldLog(Log.WARN))
_log.warn(ui.toString() + ' ' + old + " already downloaded");
return false;
}
VersionAvailable oldVA = _available.get(ui);
if (oldVA != null) {
int comp = oldVA.compareTo(newVA);
if (comp > 0) {
boolean shouldUpdate = false;
for (Map.Entry<UpdateMethod, List<URI>> e : sourceMap.entrySet()) {
UpdateMethod method = e.getKey();
List<URI> updateSources = e.getValue();
VersionAvailable newVA = new VersionAvailable(newVersion, minVersion, method, updateSources);
Version old = _installed.get(ui);
if (_log.shouldLog(Log.INFO))
_log.info("notifyVersionAvailable " + ui + ' ' + newVA + " old: " + old);
if (old != null && old.compareTo(newVA) >= 0) {
if (_log.shouldLog(Log.WARN))
_log.warn(ui.toString() + ' ' + oldVA + " already available");
_log.warn(ui.toString() + ' ' + old + " already installed");
// don't bother updating sources
return false;
}
if (comp == 0) {
if (oldVA.sourceMap.putIfAbsent(method, updateSources) == null) {
if (_log.shouldLog(Log.WARN))
_log.warn(ui.toString() + ' ' + oldVA + " updated with new source method");
} else {
old = _downloaded.get(ui);
if (old != null && old.compareTo(newVA) >= 0) {
if (_log.shouldLog(Log.WARN))
_log.warn(ui.toString() + ' ' + old + " already downloaded");
// don't bother updating sources
return false;
}
VersionAvailable oldVA = _available.get(ui);
if (oldVA != null) {
int comp = oldVA.compareTo(newVA);
if (comp > 0) {
if (_log.shouldLog(Log.WARN))
_log.warn(ui.toString() + ' ' + oldVA + " already available");
}
return false;
continue;
} else if (comp == 0) {
List<URI> oldSources = oldVA.sourceMap.putIfAbsent(method, updateSources);
if (oldSources == null) {
// merge with existing VersionAvailable
// new method
if (_log.shouldLog(Log.WARN))
_log.warn(ui.toString() + ' ' + oldVA + " updated with new source method");
} else if (!oldSources.containsAll(updateSources)) {
// merge with existing VersionAvailable
// new sources to existing method
for (URI uri : updateSources) {
if (!oldSources.contains(uri)) {
if (_log.shouldLog(Log.WARN))
_log.warn(ui.toString() + ' ' + oldVA + " adding " + uri + " to method " + method);
oldSources.add(uri);
}
}
} else {
if (_log.shouldLog(Log.WARN))
_log.warn(ui.toString() + ' ' + oldVA + " already available");
}
continue;
} // else new version is newer
}
}
if (_log.shouldLog(Log.INFO))
_log.info(ui.toString() + ' ' + newVA + " now available");
_available.put(ui, newVA);
// Use the new VersionAvailable
if (_log.shouldLog(Log.INFO))
_log.info(ui.toString() + ' ' + newVA + " now available");
_available.put(ui, newVA);
shouldUpdate = true;
}
if (!shouldUpdate)
return false;
String msg = null;
switch (type) {
@ -679,7 +726,12 @@ public class ConsoleUpdateManager implements UpdateManager {
if (shouldInstall() &&
!(isUpdateInProgress(ROUTER_SIGNED) ||
isUpdateInProgress(ROUTER_UNSIGNED))) {
if (_log.shouldLog(Log.INFO))
_log.info("Updating " + ui + " after notify");
update_fromCheck(type, id, DEFAULT_MAX_TIME);
} else {
if (_log.shouldLog(Log.INFO))
_log.info("Not updating " + ui + ", update disabled or in progress");
}
// ConfigUpdateHandler, SummaryHelper, SummaryBarRenderer handle status display
break;
@ -890,7 +942,7 @@ public class ConsoleUpdateManager implements UpdateManager {
}
/** from NewsFetcher */
private boolean shouldInstall() {
boolean shouldInstall() {
String policy = _context.getProperty(ConfigUpdateHandler.PROP_UPDATE_POLICY);
if ("notify".equals(policy) || NewsHelper.dontInstall(_context))
return false;
@ -1049,7 +1101,9 @@ public class ConsoleUpdateManager implements UpdateManager {
}
static String linkify(String url) {
return "<a target=\"_blank\" href=\"" + url + "\"/>" + url + "</a>";
String durl = url.length() <= 28 ? url :
url.substring(0, 25) + "&hellip;";
return "<a target=\"_blank\" href=\"" + url + "\"/>" + durl + "</a>";
}
/** translate a string */

View File

@ -148,21 +148,21 @@ class NewsFetcher extends UpdateRunner {
// TODO if minversion > our version, continue
// and look for a second entry with clearnet URLs
// TODO clearnet URLs, notify with HTTP_CLEARNET and/or HTTPS_CLEARNET
_mgr.notifyVersionAvailable(this, _currentURI,
ROUTER_SIGNED, "", HTTP,
_mgr.getUpdateURLs(ROUTER_SIGNED, "", HTTP),
ver, "");
Map<UpdateMethod, List<URI>> sourceMap = new HashMap(4);
sourceMap.put(HTTP, _mgr.getUpdateURLs(ROUTER_SIGNED, "", HTTP));
String key = FileUtil.isPack200Supported() ? SU2_KEY : SUD_KEY;
String murl = args.get(key);
if (murl != null) {
List<URI> uris = tokenize(murl);
if (!uris.isEmpty()) {
Collections.shuffle(uris, _context.random());
_mgr.notifyVersionAvailable(this, _currentURI,
ROUTER_SIGNED, "", TORRENT,
uris, ver, "");
sourceMap.put(TORRENT, uris);
}
}
// notify about all sources at once
_mgr.notifyVersionAvailable(this, _currentURI,
ROUTER_SIGNED, "", sourceMap,
ver, "");
} else {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Our version is current");

View File

@ -39,6 +39,7 @@ class NewsTimerTask implements SimpleTimer.TimedEvent {
private final RouterContext _context;
private final Log _log;
private final ConsoleUpdateManager _mgr;
private boolean _firstRun = true;
private static final long INITIAL_DELAY = 5*60*1000;
private static final long RUN_DELAY = 10*60*1000;
@ -64,7 +65,20 @@ class NewsTimerTask implements SimpleTimer.TimedEvent {
// nonblocking
fetchUnsignedHead();
}
} else if (_firstRun) {
// This covers the case where we got a new news but then shut down before it
// was successfully downloaded, and then restarted within the 36 hour delay
// before fetching news again.
// If we already know about a new version (from ConsoleUpdateManager calling
// NewsFetcher.checkForUpdates() before any Updaters were registered),
// this will fire off an update.
// If disabled this does nothing.
// TODO unsigned too?
if (_mgr.shouldInstall() &&
!_mgr.isCheckInProgress() && !_mgr.isUpdateInProgress())
_mgr.update(ROUTER_SIGNED);
}
_firstRun = false;
}
private boolean shouldFetchNews() {

View File

@ -69,9 +69,13 @@ public class PluginStarter implements Runnable {
public void run() {
if (_context.getBooleanPropertyDefaultTrue("plugins.autoUpdate") &&
(!NewsHelper.isUpdateInProgress()) &&
(!RouterVersion.VERSION.equals(_context.getProperty("router.previousVersion"))))
updateAll(_context, true);
!NewsHelper.isUpdateInProgress()) {
String prev = _context.getProperty("router.previousVersion");
if (prev != null &&
(new VersionComparator()).compare(RouterVersion.VERSION, prev) > 0) {
updateAll(_context, true);
}
}
startPlugins(_context);
}

View File

@ -5,6 +5,7 @@ import java.io.IOException;
import java.io.Writer;
import java.net.URI;
import java.util.List;
import java.util.Map;
/**
* The central resource coordinating updates.
@ -34,6 +35,7 @@ public interface UpdateManager {
/**
* Called by the Checker, either after check() was called, or it found out on its own.
* Use this if there is only one UpdateMethod; otherwise use the Map method below.
*
* @param newsSource who told us
* @param id plugin name for plugins, ignored otherwise
@ -48,6 +50,23 @@ public interface UpdateManager {
UpdateMethod method, List<URI> updateSources,
String newVersion, String minVersion);
/**
* Called by the Checker, either after check() was called, or it found out on its own.
* Checkers must use this method if there are multiple UpdateMethods discoverd simultaneously.
*
* @param newsSource who told us
* @param id plugin name for plugins, ignored otherwise
* @param sourceMap Mapping of methods to sources
* @param newVersion The new version available
* @param minVersion The minimum installed version to be able to update to newVersion
* @return true if we didn't know already
* @since 0.9.6
*/
public boolean notifyVersionAvailable(UpdateTask task, URI newsSource,
UpdateType type, String id,
Map<UpdateMethod, List<URI>> sourceMap,
String newVersion, String minVersion);
/**
* Called by the Checker after check() was called and all notifyVersionAvailable() callbacks are finished
* @param newer notifyVersionAvailable was called

View File

@ -1,3 +1,17 @@
2013-04-19 zzz
* AppManager: Register jetty, console, and SAM with manager
* i2psnark: Disable spellcheck in more form fields
* LogManager: Add support for saving properties added in recent releases
* Updates:
- Notify manager about all available update methods at once, so the priority
system works and it doesn't only update via HTTP
- Start router update download at startup if available
- Only check plugins when core version increases, not decreases, so we
don't update plugins when downgrading
- Limit length of URL shown on summary bar
* WorkingDir: Correctly strip DOS line endings while migrating,
to fix eepsite location on 0.9.5 Windows installs (ticket #919)
2013-04-18 zzz
* i2psnark: Fix params after P-R-G
* i2ptunnel: Set target=_top in all external links to break out of console iframe

View File

@ -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 = 10;
public final static long BUILD = 11;
/** for example "-test" */
public final static String EXTRA = "";