diff --git a/apps/routerconsole/java/src/net/i2p/router/web/UpdateHandler.java b/apps/routerconsole/java/src/net/i2p/router/web/UpdateHandler.java
index 02d92dcf0..eebf1625c 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/UpdateHandler.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/UpdateHandler.java
@@ -33,6 +33,7 @@ public class UpdateHandler {
private DecimalFormat _pct = new DecimalFormat("00.0%");
private static final String SIGNED_UPDATE_FILE = "i2pupdate.sud";
+ private static final String PROP_UPDATE_IN_PROGRESS = "net.i2p.router.web.UpdateHandler.updateInProgress";
public UpdateHandler() {
this(ContextHelper.getContext(null));
@@ -67,21 +68,27 @@ public class UpdateHandler {
}
public void update() {
+ // don't block waiting for the other one to finish
+ if ("true".equals(System.getProperty(PROP_UPDATE_IN_PROGRESS, "false"))) {
+ _log.error("Update already running");
+ return;
+ }
synchronized (UpdateHandler.class) {
if (_updateRunner == null)
_updateRunner = new UpdateRunner();
if (_updateRunner.isRunning()) {
return;
} else {
- System.setProperty("net.i2p.router.web.UpdateHandler.updateInProgress", "true");
+ System.setProperty(PROP_UPDATE_IN_PROGRESS, "true");
I2PThread update = new I2PThread(_updateRunner, "Update");
update.start();
}
}
-
}
public String getStatus() {
+ if (_updateRunner == null)
+ return "";
return _updateRunner.getStatus();
}
@@ -89,22 +96,21 @@ public class UpdateHandler {
private boolean _isRunning;
private String _status;
private long _startedOn;
- private long _written;
public UpdateRunner() {
_isRunning = false;
- _status = "Updating ";
+ _status = "Updating";
}
public boolean isRunning() { return _isRunning; }
public String getStatus() { return _status; }
public void run() {
_isRunning = true;
update();
- System.setProperty("net.i2p.router.web.UpdateHandler.updateInProgress", "false");
+ System.setProperty(PROP_UPDATE_IN_PROGRESS, "false");
_isRunning = false;
}
private void update() {
_startedOn = -1;
- _status = "Updating ";
+ _status = "Updating";
String updateURL = selectUpdateURL();
if (_log.shouldLog(Log.DEBUG))
_log.debug("Selected update URL: " + updateURL);
@@ -115,64 +121,65 @@ public class UpdateHandler {
try {
proxyPort = Integer.parseInt(port);
} catch (NumberFormatException nfe) {
- System.setProperty("net.i2p.router.web.UpdateHandler.updateInProgress", "false");
+ System.setProperty(PROP_UPDATE_IN_PROGRESS, "false");
return;
}
try {
EepGet get = null;
if (shouldProxy)
- get = new EepGet(_context, proxyHost, proxyPort, 10, SIGNED_UPDATE_FILE, updateURL, false);
+ get = new EepGet(_context, proxyHost, proxyPort, 20, SIGNED_UPDATE_FILE, updateURL, false);
else
- get = new EepGet(_context, 10, SIGNED_UPDATE_FILE, updateURL, false);
+ get = new EepGet(_context, 1, SIGNED_UPDATE_FILE, updateURL, false);
get.addStatusListener(UpdateRunner.this);
_startedOn = _context.clock().now();
get.fetch();
} catch (Throwable t) {
_context.logManager().getLog(UpdateHandler.class).error("Error updating", t);
- System.setProperty("net.i2p.router.web.UpdateHandler.updateInProgress", "false");
+ System.setProperty(PROP_UPDATE_IN_PROGRESS, "false");
}
}
public void attemptFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt, int numRetries, Exception cause) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Attempt failed on " + url, cause);
- _written = 0;
// ignored
}
public void bytesTransferred(long alreadyTransferred, int currentWrite, long bytesTransferred, long bytesRemaining, String url) {
- _written += currentWrite;
StringBuffer buf = new StringBuffer(64);
buf.append("Updating ");
- double pct = ((double)alreadyTransferred + (double)_written) / ((double)alreadyTransferred + (double)bytesRemaining);
+ double pct = ((double)alreadyTransferred + (double)currentWrite) /
+ ((double)alreadyTransferred + (double)currentWrite + (double)bytesRemaining);
synchronized (_pct) {
buf.append(_pct.format(pct));
}
- buf.append(": \n").append(_written+alreadyTransferred);
- buf.append(" transferred ");
+ buf.append(": \n" + (currentWrite + alreadyTransferred));
+ buf.append(" transferred");
_status = buf.toString();
}
public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified) {
- _status = "Update downloaded ";
+ _status = "Update downloaded";
TrustedUpdate up = new TrustedUpdate(_context);
boolean ok = up.migrateVerified(RouterVersion.VERSION, SIGNED_UPDATE_FILE, "i2pupdate.zip");
File f = new File(SIGNED_UPDATE_FILE);
f.delete();
if (ok) {
_log.log(Log.CRIT, "Update was VERIFIED, restarting to install it");
- _status = "Update verified Restarting ";
+ _status = "Update verified Restarting";
restart();
} else {
- _log.log(Log.CRIT, "Update was INVALID - signing key is not trusted!");
- _status = "Update signing key invalid ";
- System.setProperty("net.i2p.router.web.UpdateHandler.updateInProgress", "false");
+ // One other possibility, the version in the file is not sufficient
+ // Perhaps need an int return code - but version problem unlikely?
+ _log.log(Log.CRIT, "Update was INVALID - signing key is not trusted or file is corrupt from " + url);
+ _status = "Update signing key invalid or file is corrupt from " + url + "";
+ System.setProperty(PROP_UPDATE_IN_PROGRESS, "false");
}
}
public void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt) {
_log.log(Log.CRIT, "Update from " + url + " did not download completely (" + bytesTransferred + " with "
+ bytesRemaining + " after " + currentAttempt + " tries)");
- _status = "Transfer failed ";
- System.setProperty("net.i2p.router.web.UpdateHandler.updateInProgress", "false");
+ _status = "Transfer failed";
+ System.setProperty(PROP_UPDATE_IN_PROGRESS, "false");
}
public void headerReceived(String url, int attemptNum, String key, String val) {}
public void attempting(String url) {}
diff --git a/apps/routerconsole/jsp/configupdate.jsp b/apps/routerconsole/jsp/configupdate.jsp
index 38dfe207b..634b362ae 100644
--- a/apps/routerconsole/jsp/configupdate.jsp
+++ b/apps/routerconsole/jsp/configupdate.jsp
@@ -27,7 +27,11 @@
if (prev != null) System.setProperty("net.i2p.router.web.ConfigUpdateHandler.noncePrev", prev);
System.setProperty("net.i2p.router.web.ConfigUpdateHandler.nonce", new java.util.Random().nextLong()+""); %>
" />
+ <% if ("true".equals(System.getProperty("net.i2p.router.web.UpdateHandler.updateInProgress", "false"))) { %>
+ Update In Progress
+ <% } else { %>
+ <% } %>
News URL:
">
Refresh frequency:
diff --git a/apps/routerconsole/jsp/summary.jsp b/apps/routerconsole/jsp/summary.jsp
index cf61e3f4a..475dd60c8 100644
--- a/apps/routerconsole/jsp/summary.jsp
+++ b/apps/routerconsole/jsp/summary.jsp
@@ -16,8 +16,9 @@
Now:<%
if (helper.updateAvailable()) {
+ // display all the time so we display the final failure message
+ out.print(" " + update.getStatus());
if ("true".equals(System.getProperty("net.i2p.router.web.UpdateHandler.updateInProgress", "false"))) {
- out.print(" " + update.getStatus());
} else {
long nonce = new java.util.Random().nextLong();
String prev = System.getProperty("net.i2p.router.web.UpdateHandler.nonce");
diff --git a/core/java/src/net/i2p/util/EepGet.java b/core/java/src/net/i2p/util/EepGet.java
index 86533fed8..111372330 100644
--- a/core/java/src/net/i2p/util/EepGet.java
+++ b/core/java/src/net/i2p/util/EepGet.java
@@ -215,6 +215,20 @@ public class EepGet {
}
public static interface StatusListener {
+ /**
+ * alreadyTransferred - total of all attempts, not including currentWrite
+ * If nonzero on the first call, a partial file of that length was found
+ * To track _actual_ transfer if the output file could already exist,
+ * the listener should keep its own counter,
+ * or subtract the initial alreadyTransferred value.
+ * currentWrite - since last call to the listener
+ * bytesTransferred - includes headers, retries, redirects, ...
+ * bytesRemaining - on this attempt only, currentWrite already subtracted -
+ * or -1 if chunked encoding or server does not return a length
+ *
+ * Total length should be == alreadyTransferred + currentWrite + bytesRemaining for all calls
+ *
+ */
public void bytesTransferred(long alreadyTransferred, int currentWrite, long bytesTransferred, long bytesRemaining, String url);
public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified);
public void attemptFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt, int numRetries, Exception cause);
@@ -227,7 +241,9 @@ public class EepGet {
private int _lineSize;
private long _startedOn;
private long _written;
+ private long _previousWritten;
private long _lastComplete;
+ private boolean _firstTime;
private DecimalFormat _pct = new DecimalFormat("00.0%");
private DecimalFormat _kbps = new DecimalFormat("###,000.00");
public CLIStatusListener() {
@@ -237,10 +253,19 @@ public class EepGet {
_markSize = markSize;
_lineSize = lineSize;
_written = 0;
+ _previousWritten = 0;
_lastComplete = _context.clock().now();
_startedOn = _lastComplete;
+ _firstTime = true;
}
public void bytesTransferred(long alreadyTransferred, int currentWrite, long bytesTransferred, long bytesRemaining, String url) {
+ if (_firstTime) {
+ if (alreadyTransferred > 0) {
+ _previousWritten = alreadyTransferred;
+ System.out.println("File found with length " + alreadyTransferred + ", resuming");
+ }
+ _firstTime = false;
+ }
for (int i = 0; i < currentWrite; i++) {
_written++;
if ( (_markSize > 0) && (_written % _markSize == 0) ) {
@@ -253,13 +278,14 @@ public class EepGet {
StringBuffer buf = new StringBuffer(50);
buf.append(" ");
if ( bytesRemaining > 0 ) {
- double pct = ((double)alreadyTransferred + (double)_written) / ((double)alreadyTransferred + (double)bytesRemaining);
+ double pct = ((double)_written + _previousWritten) /
+ ((double)alreadyTransferred + (double)currentWrite + (double)bytesRemaining);
synchronized (_pct) {
buf.append(_pct.format(pct));
}
buf.append(": ");
}
- buf.append(_written+alreadyTransferred);
+ buf.append(_written);
buf.append(" @ ");
double lineKBytes = ((double)_markSize * (double)_lineSize)/1024.0d;
double kbps = lineKBytes/((double)timeToSend/1000.0d);
@@ -270,7 +296,7 @@ public class EepGet {
buf.append(" / ");
long lifetime = _context.clock().now() - _startedOn;
- double lifetimeKBps = (1000.0d*(double)(_written+alreadyTransferred)/((double)lifetime*1024.0d));
+ double lifetimeKBps = (1000.0d*(double)(_written)/((double)lifetime*1024.0d));
synchronized (_kbps) {
buf.append(_kbps.format(lifetimeKBps));
}
@@ -283,32 +309,40 @@ public class EepGet {
}
}
public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified) {
+ long transferred;
+ if (_firstTime)
+ transferred = 0;
+ else
+ transferred = alreadyTransferred - _previousWritten;
System.out.println();
System.out.println("== " + new Date());
if (notModified) {
System.out.println("== Source not modified since last download");
} else {
if ( bytesRemaining > 0 ) {
- System.out.println("== Transfer of " + url + " completed with " + (alreadyTransferred+bytesTransferred)
- + " and " + (bytesRemaining - bytesTransferred) + " remaining");
- System.out.println("== Output saved to " + outputFile);
+ System.out.println("== Transfer of " + url + " completed with " + transferred
+ + " transferred and " + (bytesRemaining - bytesTransferred) + " remaining");
} else {
- System.out.println("== Transfer of " + url + " completed with " + (alreadyTransferred+bytesTransferred)
+ System.out.println("== Transfer of " + url + " completed with " + transferred
+ " bytes transferred");
- System.out.println("== Output saved to " + outputFile);
}
+ if (transferred > 0)
+ System.out.println("== Output saved to " + outputFile + " (" + alreadyTransferred + " bytes)");
}
long timeToSend = _context.clock().now() - _startedOn;
System.out.println("== Transfer time: " + DataHelper.formatDuration(timeToSend));
- System.out.println("== ETag: " + _etag);
- StringBuffer buf = new StringBuffer(50);
- buf.append("== Transfer rate: ");
- double kbps = (1000.0d*(double)(_written)/((double)timeToSend*1024.0d));
- synchronized (_kbps) {
- buf.append(_kbps.format(kbps));
+ if (_etag != null)
+ System.out.println("== ETag: " + _etag);
+ if (transferred > 0) {
+ StringBuffer buf = new StringBuffer(50);
+ buf.append("== Transfer rate: ");
+ double kbps = (1000.0d*(double)(transferred)/((double)timeToSend*1024.0d));
+ synchronized (_kbps) {
+ buf.append(_kbps.format(kbps));
+ }
+ buf.append("KBps");
+ System.out.println(buf.toString());
}
- buf.append("KBps");
- System.out.println(buf.toString());
}
public void attemptFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt, int numRetries, Exception cause) {
System.out.println();
@@ -499,13 +533,8 @@ public class EepGet {
timeout.resetTimer();
_out.write(buf, 0, read);
_bytesTransferred += read;
- // This seems necessary to properly resume a partial download into a stream,
- // as nothing else increments _alreadyTransferred, and there's no file length to check.
- // Hopefully this won't break compatibility with existing status listeners
- // (cause them to behave weird, or show weird numbers).
- _alreadyTransferred += read;
- if ((_maxSize > -1) && (_alreadyTransferred > _maxSize)) // could transfer a little over maxSize
- throw new IOException("Bytes transferred " + _alreadyTransferred + " violates maximum of " + _maxSize + " bytes");
+ if ((_maxSize > -1) && (_alreadyTransferred + read > _maxSize)) // could transfer a little over maxSize
+ throw new IOException("Bytes transferred " + (_alreadyTransferred + read) + " violates maximum of " + _maxSize + " bytes");
remaining -= read;
if (remaining==0 && _encodingChunked) {
int char1 = _proxyIn.read();
@@ -528,7 +557,9 @@ public class EepGet {
}
}
timeout.resetTimer();
- if (read > 0)
+ if (_bytesRemaining >= read) // else chunked?
+ _bytesRemaining -= read;
+ if (read > 0) {
for (int i = 0; i < _listeners.size(); i++)
((StatusListener)_listeners.get(i)).bytesTransferred(
_alreadyTransferred,
@@ -536,6 +567,11 @@ public class EepGet {
_bytesTransferred,
_encodingChunked?-1:_bytesRemaining,
_url);
+ // This seems necessary to properly resume a partial download into a stream,
+ // as nothing else increments _alreadyTransferred, and there's no file length to check.
+ // Do this after calling the listeners to keep the total correct
+ _alreadyTransferred += read;
+ }
}
if (_out != null)
diff --git a/history.txt b/history.txt
index d76613f61..45477f9f3 100644
--- a/history.txt
+++ b/history.txt
@@ -1,3 +1,16 @@
+2008-03-10 zzz
+ * EepGet: Fix byte count for bytesTransferred status listeners
+ (fixes command line status)
+ * UpdateHandler:
+ - Fix byte count display
+ - Display final status on router console
+ - Don't allow multiple update jobs to queue up
+ - Increase max retries
+ - Code cleanup
+ - Don't show 'check for update' button when update in progress
+ - Enhance error messages
+ * NetDb: Comment out published netDb stats disabled for .32
+
2008-03-08 zzz
* ClientPeerSelector: Implement strict ordering of peers,
based on XOR distance from a random hash
diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java
index e8a28a99e..7c973ae33 100644
--- a/router/java/src/net/i2p/router/RouterVersion.java
+++ b/router/java/src/net/i2p/router/RouterVersion.java
@@ -17,7 +17,7 @@ import net.i2p.CoreVersion;
public class RouterVersion {
public final static String ID = "$Revision: 1.548 $ $Date: 2008-02-10 15:00:00 $";
public final static String VERSION = "0.6.1.32";
- public final static long BUILD = 2;
+ public final static long BUILD = 3;
public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
System.out.println("Router ID: " + RouterVersion.ID);