From cb56b76ef96177e92b741c1c2cc193c701416d83 Mon Sep 17 00:00:00 2001 From: kytv Date: Sat, 13 Oct 2012 12:45:25 +0000 Subject: [PATCH 1/4] i2prouter: check /proc/1/comm for systemd (thanks k0e) --- installer/resources/i2prouter | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/installer/resources/i2prouter b/installer/resources/i2prouter index d49877795..fde3a0d47 100644 --- a/installer/resources/i2prouter +++ b/installer/resources/i2prouter @@ -45,7 +45,7 @@ GETTEXT=$(which gettext > /dev/null 2>&1) # Where to install the systemd service SYSTEMD_SERVICE="/etc/systemd/system/${APP_NAME}.service" -if grep -q systemd /proc/cmdline; then +if grep -q systemd /proc/1/comm ; then USE_SYSTEMD=1 fi @@ -1321,6 +1321,8 @@ installdaemon() { echo "esac" >> /etc/rc.d/${APP_NAME} chmod 755 /etc/rc.d/${APP_NAME} chown root:root /etc/rc.d/${APP_NAME} + eval echo `gettext ' The $APP_LONG_NAME daemon has been installed.'` + eval echo `gettext ' Add \"i2p\" to the DAEMONS variable in /etc/rc.conf to enable.'` else # We'll end up here if systemd is enabled. # If systemd is enabled we don't need the initscript @@ -1330,10 +1332,6 @@ installdaemon() { if [ ! -f "${SYSTEMD_SERVICE}" ]; then installsystemd fi - if ! grep -q systemd /proc/cmdline; then - eval echo `gettext ' The $APP_LONG_NAME daemon has been installed.'` - eval echo `gettext ' Add \"i2p\" to the DAEMONS variable in /etc/rc.conf to enable.'` - fi fi elif [ -f /etc/SuSE-release ] ; then eval echo `gettext 'Detected SuSE or SLES:'` From 5d6d27907dc89bd183db003513d9d90892281575 Mon Sep 17 00:00:00 2001 From: zzz Date: Sun, 14 Oct 2012 13:54:08 +0000 Subject: [PATCH 2/4] * Console: Use non-nio connector for Java 5 and JamVM/gij (tickets #715 and #743) * SystemVersion: Centralize more methods here --- .../i2p/router/web/RouterConsoleRunner.java | 50 +++++++++++++++---- .../net/i2p/router/web/StatSummarizer.java | 8 ++- core/java/src/net/i2p/crypto/SHA1.java | 8 +-- .../net/i2p/util/ReusableGZIPInputStream.java | 2 +- .../i2p/util/ReusableGZIPOutputStream.java | 2 +- core/java/src/net/i2p/util/SystemVersion.java | 27 +++++++++- installer/resources/eepsite/jetty.xml | 4 +- 7 files changed, 76 insertions(+), 25 deletions(-) diff --git a/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java b/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java index e361df3eb..488c5b655 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java @@ -34,11 +34,14 @@ import net.i2p.util.PortMapper; import net.i2p.util.SecureDirectory; import net.i2p.util.SecureFileOutputStream; import net.i2p.util.ShellCommand; +import net.i2p.util.SystemVersion; import net.i2p.util.VersionComparator; +import org.mortbay.jetty.AbstractConnector; import org.mortbay.jetty.Connector; import org.mortbay.jetty.NCSARequestLog; import org.mortbay.jetty.Server; +import org.mortbay.jetty.bio.SocketConnector; import org.mortbay.jetty.handler.ContextHandlerCollection; import org.mortbay.jetty.handler.DefaultHandler; import org.mortbay.jetty.handler.HandlerCollection; @@ -49,6 +52,7 @@ import org.mortbay.jetty.security.HashUserRealm; import org.mortbay.jetty.security.Constraint; import org.mortbay.jetty.security.ConstraintMapping; import org.mortbay.jetty.security.SecurityHandler; +import org.mortbay.jetty.security.SslSocketConnector; import org.mortbay.jetty.security.SslSelectChannelConnector; import org.mortbay.jetty.servlet.ServletHandler; import org.mortbay.jetty.servlet.ServletHolder; @@ -177,8 +181,7 @@ public class RouterConsoleRunner { try { //TODO: move away from routerconsole into a separate application. //ApplicationManager? - VersionComparator v = new VersionComparator(); - boolean recentJava = v.compare(System.getProperty("java.runtime.version"), "1.6") >= 0; + boolean recentJava = SystemVersion.isJava6(); // default false for now boolean desktopguiEnabled = I2PAppContext.getGlobalContext().getBooleanProperty("desktopgui.enabled"); if (recentJava && desktopguiEnabled) { @@ -334,12 +337,22 @@ public class RouterConsoleRunner { // _server.addListener('[' + host + "]:" + _listenPort); //else // _server.addListener(host + ':' + _listenPort); - SelectChannelConnector lsnr = new SelectChannelConnector(); + AbstractConnector lsnr; + if (SystemVersion.isJava6() && !SystemVersion.isGNU()) { + SelectChannelConnector slsnr = new SelectChannelConnector(); + slsnr.setUseDirectBuffers(false); // default true seems to be leaky + lsnr = slsnr; + } else { + // Jetty 6 and NIO on Java 5 don't get along that well + // Also: http://jira.codehaus.org/browse/JETTY-1238 + // "Do not use GCJ with Jetty, it will not work." + // Actually it does if you don't use NIO + lsnr = new SocketConnector(); + } lsnr.setHost(host); lsnr.setPort(lport); lsnr.setMaxIdleTime(90*1000); // default 10 sec lsnr.setName("ConsoleSocket"); // all with same name will use the same thread pool - lsnr.setUseDirectBuffers(false); // default true seems to be leaky //_server.addConnector(lsnr); connectors.add(lsnr); boundAddresses++; @@ -389,22 +402,37 @@ public class RouterConsoleRunner { } // TODO if class not found use SslChannelConnector // Sadly there's no common base class with the ssl methods in it - SslSelectChannelConnector ssll = new SslSelectChannelConnector(); + AbstractConnector ssll; + if (SystemVersion.isJava6() && !SystemVersion.isGNU()) { + SslSelectChannelConnector sssll = new SslSelectChannelConnector(); + // the keystore path and password + sssll.setKeystore(keyStore.getAbsolutePath()); + sssll.setPassword(ctx.getProperty(PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD)); + // the X.509 cert password (if not present, verifyKeyStore() returned false) + sssll.setKeyPassword(ctx.getProperty(PROP_KEY_PASSWORD, "thisWontWork")); + sssll.setUseDirectBuffers(false); // default true seems to be leaky + ssll = sssll; + } else { + // Jetty 6 and NIO on Java 5 don't get along that well + SslSocketConnector sssll = new SslSocketConnector(); + // the keystore path and password + sssll.setKeystore(keyStore.getAbsolutePath()); + sssll.setPassword(ctx.getProperty(PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD)); + // the X.509 cert password (if not present, verifyKeyStore() returned false) + sssll.setKeyPassword(ctx.getProperty(PROP_KEY_PASSWORD, "thisWontWork")); + ssll = sssll; + } ssll.setHost(host); ssll.setPort(sslPort); - // the keystore path and password - ssll.setKeystore(keyStore.getAbsolutePath()); - ssll.setPassword(ctx.getProperty(PROP_KEYSTORE_PASSWORD, DEFAULT_KEYSTORE_PASSWORD)); - // the X.509 cert password (if not present, verifyKeyStore() returned false) - ssll.setKeyPassword(ctx.getProperty(PROP_KEY_PASSWORD, "thisWontWork")); ssll.setMaxIdleTime(90*1000); // default 10 sec ssll.setName("ConsoleSocket"); // all with same name will use the same thread pool - ssll.setUseDirectBuffers(false); // default true seems to be leaky //_server.addConnector(ssll); connectors.add(ssll); boundAddresses++; } catch (Exception e) { System.err.println("Unable to bind routerconsole to " + host + " port " + sslPort + " for SSL: " + e); + if (SystemVersion.isGNU()) + System.err.println("Probably because GNU classpath does not support Sun keystores"); System.err.println("You may ignore this warning if the console is still available at https://localhost:" + sslPort); } } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/StatSummarizer.java b/apps/routerconsole/java/src/net/i2p/router/web/StatSummarizer.java index 825133c0e..199cf5e4e 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/StatSummarizer.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/StatSummarizer.java @@ -67,12 +67,10 @@ public class StatSummarizer implements Runnable { public void run() { // JRobin 1.5.9 crashes these JVMs - String vendor = System.getProperty("java.vendor"); - if (vendor.startsWith("Apache") || // Harmony - vendor.startsWith("GNU Classpath") || // JamVM - vendor.startsWith("Free Software Foundation")) { // gij + if (SystemVersion.isApache() || // Harmony + SystemVersion.isGNU()) { // JamVM or gij _log.logAlways(Log.WARN, "Graphing not supported with this JVM: " + - vendor + ' ' + + System.getProperty("java.vendor") + ' ' + System.getProperty("java.version") + " (" + System.getProperty("java.runtime.name") + ' ' + System.getProperty("java.runtime.version") + ')'); diff --git a/core/java/src/net/i2p/crypto/SHA1.java b/core/java/src/net/i2p/crypto/SHA1.java index 7ea68de56..bfe07630c 100644 --- a/core/java/src/net/i2p/crypto/SHA1.java +++ b/core/java/src/net/i2p/crypto/SHA1.java @@ -20,6 +20,8 @@ import java.security.DigestException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import net.i2p.util.SystemVersion; + /** * NOTE: As of 0.8.7, use getInstance() instead of new SHA1(), which will * return the JVM's MessageDigest if it is faster. @@ -94,10 +96,8 @@ public final class SHA1 extends MessageDigest implements Cloneable { static { // oddly, Bitzi is faster than Oracle - see test results below boolean useBitzi = true; - String vendor = System.getProperty("java.vendor"); - if (vendor.startsWith("Apache") || // Harmony - vendor.startsWith("GNU Classpath") || // JamVM - vendor.startsWith("Free Software Foundation")) { // gij + if (SystemVersion.isApache() || // Harmony + SystemVersion.isGNU()) { // JamVM or gij try { MessageDigest.getInstance("SHA-1"); useBitzi = false; diff --git a/core/java/src/net/i2p/util/ReusableGZIPInputStream.java b/core/java/src/net/i2p/util/ReusableGZIPInputStream.java index f09c9711c..5ef5b7801 100644 --- a/core/java/src/net/i2p/util/ReusableGZIPInputStream.java +++ b/core/java/src/net/i2p/util/ReusableGZIPInputStream.java @@ -9,7 +9,7 @@ import java.util.concurrent.LinkedBlockingQueue; public class ReusableGZIPInputStream extends ResettableGZIPInputStream { // Apache Harmony 5.0M13 Deflater doesn't work after reset() // Neither does Android - private static final boolean ENABLE_CACHING = !(System.getProperty("java.vendor").startsWith("Apache") || + private static final boolean ENABLE_CACHING = !(SystemVersion.isApache() || SystemVersion.isAndroid()); private static final LinkedBlockingQueue _available; static { diff --git a/core/java/src/net/i2p/util/ReusableGZIPOutputStream.java b/core/java/src/net/i2p/util/ReusableGZIPOutputStream.java index fe686095e..3cbf1dd33 100644 --- a/core/java/src/net/i2p/util/ReusableGZIPOutputStream.java +++ b/core/java/src/net/i2p/util/ReusableGZIPOutputStream.java @@ -20,7 +20,7 @@ import net.i2p.data.DataHelper; public class ReusableGZIPOutputStream extends ResettableGZIPOutputStream { // Apache Harmony 5.0M13 Deflater doesn't work after reset() // Neither does Android - private static final boolean ENABLE_CACHING = !(System.getProperty("java.vendor").startsWith("Apache") || + private static final boolean ENABLE_CACHING = !(SystemVersion.isApache() || SystemVersion.isAndroid()); private static final LinkedBlockingQueue _available; static { diff --git a/core/java/src/net/i2p/util/SystemVersion.java b/core/java/src/net/i2p/util/SystemVersion.java index d43cddc89..484a29323 100644 --- a/core/java/src/net/i2p/util/SystemVersion.java +++ b/core/java/src/net/i2p/util/SystemVersion.java @@ -15,14 +15,23 @@ public abstract class SystemVersion { private static final boolean _isWin = System.getProperty("os.name").startsWith("Win"); private static final boolean _isMac = System.getProperty("os.name").startsWith("Mac"); - private static final boolean _isAndroid = System.getProperty("java.vendor").contains("Android"); + private static final boolean _isAndroid; + private static final boolean _isApache; + private static final boolean _isGNU; private static final boolean _is64 = "64".equals(System.getProperty("sun.arch.data.model")) || System.getProperty("os.arch").contains("64"); + private static final boolean _hasWrapper = System.getProperty("wrapper.version") != null; private static final boolean _oneDotSix; private static final int _androidSDK; static { + String vendor = System.getProperty("java.vendor"); + _isAndroid = vendor.contains("Android"); + _isApache = vendor.startsWith("Apache"); + _isGNU = vendor.startsWith("GNU Classpath") || // JamVM + vendor.startsWith("Free Software Foundation"); // gij + int sdk = 0; if (_isAndroid) { try { @@ -52,6 +61,20 @@ public abstract class SystemVersion { return _isAndroid; } + /** + * Apache Harmony JVM, or Android + */ + public static boolean isApache() { + return _isApache || _isAndroid; + } + + /** + * gij or JamVM with GNU Classpath + */ + public static boolean isGNU() { + return _isGNU; + } + /** * Better than (new VersionComparator()).compare(System.getProperty("java.version"), "1.6") >= 0 * as it handles Android also, where java.version = "0". @@ -90,6 +113,6 @@ public abstract class SystemVersion { * Same as I2PAppContext.hasWrapper() */ public static boolean hasWrapper() { - return System.getProperty("wrapper.version") != null; + return _hasWrapper; } } diff --git a/installer/resources/eepsite/jetty.xml b/installer/resources/eepsite/jetty.xml index ba30a55eb..0e873ca77 100644 --- a/installer/resources/eepsite/jetty.xml +++ b/installer/resources/eepsite/jetty.xml @@ -90,7 +90,9 @@ From 184220f4c5f5fb3b1c491212ef3a3f3ed513e0ed Mon Sep 17 00:00:00 2001 From: zzz Date: Sun, 14 Oct 2012 13:54:38 +0000 Subject: [PATCH 3/4] minor optimization --- .../java/src/net/i2p/router/web/SummaryHelper.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java index c520a2bb5..99a64df94 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/SummaryHelper.java @@ -456,10 +456,11 @@ public class SummaryHelper extends HelperBase { /** compare translated nicknames - put "shared clients" first in the sort */ private class AlphaComparator implements Comparator { + private final String xsc = _("shared clients"); + public int compare(Destination lhs, Destination rhs) { String lname = getName(lhs); String rname = getName(rhs); - String xsc = _("shared clients"); if (lname.equals(xsc)) return -1; if (rname.equals(xsc)) From 8df2a2d00ab2b00026013d98abdc2e8ab30b494f Mon Sep 17 00:00:00 2001 From: zzz Date: Sun, 14 Oct 2012 16:38:36 +0000 Subject: [PATCH 4/4] * i2psnark: Fix request tracking bug preventing piece requests --- .../src/org/klomp/snark/PeerCoordinator.java | 17 ++++++++++++++--- .../java/src/org/klomp/snark/PeerState.java | 5 +++++ .../java/src/org/klomp/snark/Piece.java | 18 ++++++++++++++++-- history.txt | 5 +++++ .../java/src/net/i2p/router/RouterVersion.java | 2 +- 5 files changed, 41 insertions(+), 6 deletions(-) diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java index 2869193a0..8ffde7363 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java @@ -215,7 +215,7 @@ class PeerCoordinator implements PeerListener public Storage getStorage() { return storage; } - // for web page detailed stats + /** for web page detailed stats */ public List peerList() { return new ArrayList(peers); @@ -446,6 +446,12 @@ class PeerCoordinator implements PeerListener synchronized (downloaded_old) { Arrays.fill(downloaded_old, 0); } + // failsafe + synchronized(wantedPieces) { + for (Piece pc : wantedPieces) { + pc.clear(); + } + } timer.schedule((CHECK_PERIOD / 2) + _random.nextInt((int) CHECK_PERIOD)); } @@ -750,8 +756,12 @@ class PeerCoordinator implements PeerListener // AND if there are almost no wanted pieces left (real end game). // If we do end game all the time, we generate lots of extra traffic // when the seeder is super-slow and all the peers are "caught up" - if (wantedSize > END_GAME_THRESHOLD) + if (wantedSize > END_GAME_THRESHOLD) { + if (_log.shouldLog(Log.INFO)) + _log.info("Nothing to request, " + requested.size() + " being requested and " + + wantedSize + " still wanted"); return null; // nothing to request and not in end game + } // let's not all get on the same piece // Even better would be to sort by number of requests if (record) @@ -1078,10 +1088,11 @@ class PeerCoordinator implements PeerListener /** Called when a peer is removed, to prevent it from being used in * rarest-first calculations. */ - public void removePeerFromPieces(Peer peer) { + private void removePeerFromPieces(Peer peer) { synchronized(wantedPieces) { for (Piece piece : wantedPieces) { piece.removePeer(peer); + piece.setRequested(peer, false); } } } diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerState.java b/apps/i2psnark/java/src/org/klomp/snark/PeerState.java index 8f80d4496..95bef3c4f 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/PeerState.java +++ b/apps/i2psnark/java/src/org/klomp/snark/PeerState.java @@ -682,6 +682,7 @@ class PeerState implements DataLoader _log.debug(peer + " addRequest() we are choked, delaying requestNextPiece()"); return; } + // huh? rv unused more_pieces = requestNextPiece(); } else if (more_pieces) // We want something { @@ -711,6 +712,8 @@ class PeerState implements DataLoader } // failsafe + // However this is bad as it thrashes the peer when we change our mind + // Ticket 691 cause here? if (interesting && lastRequest == null && outstandingRequests.isEmpty()) setInteresting(false); @@ -784,6 +787,8 @@ class PeerState implements DataLoader } // failsafe + // However this is bad as it thrashes the peer when we change our mind + // Ticket 691 cause here? if (outstandingRequests.isEmpty()) lastRequest = null; diff --git a/apps/i2psnark/java/src/org/klomp/snark/Piece.java b/apps/i2psnark/java/src/org/klomp/snark/Piece.java index 3ca03ad98..9a2e2e0e7 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Piece.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Piece.java @@ -12,7 +12,7 @@ class Piece implements Comparable { private final int id; private final Set peers; /** @since 0.8.3 */ - private Set requests; + private volatile Set requests; /** @since 0.8.1 */ private int priority; @@ -54,7 +54,10 @@ class Piece implements Comparable { /** caller must synchronize */ public boolean addPeer(Peer peer) { return this.peers.add(peer.getPeerID()); } - /** caller must synchronize */ + /** + * Caller must synchronize. + * @return true if removed + */ public boolean removePeer(Peer peer) { return this.peers.remove(peer.getPeerID()); } /** @@ -104,6 +107,17 @@ class Piece implements Comparable { public int getRequestCount() { return this.requests == null ? 0 : this.requests.size(); } + + /** + * Clear all knowledge of peers + * Caller must synchronize + * @since 0.9.3 + */ + public void clear() { + peers.clear(); + if (requests != null) + requests.clear(); + } /** @return default 0 @since 0.8.1 */ public int getPriority() { return this.priority; } diff --git a/history.txt b/history.txt index 191680e4b..e10156df6 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,8 @@ +2012-10-14 zzz + * Console: Use non-nio connector for Java 5 and JamVM/gij + (tickets #715 and #743) + * i2psnark: Fix request tracking bug preventing piece requests + 2012-10-11 kytv * Italian translation updates from Transifex * i2prouter: diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 31c35f8c3..ea17ad55f 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -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 = 14; + public final static long BUILD = 15; /** for example "-test" */ public final static String EXTRA = "";