diff --git a/apps/systray/java/src/net/i2p/apps/systray/UrlLauncher.java b/apps/systray/java/src/net/i2p/apps/systray/UrlLauncher.java index f93f0876a2cb2479484d33403cc6eeddfa8fa2ea..aeb159aa3baa77c892b217079087f5197c00269b 100644 --- a/apps/systray/java/src/net/i2p/apps/systray/UrlLauncher.java +++ b/apps/systray/java/src/net/i2p/apps/systray/UrlLauncher.java @@ -43,6 +43,32 @@ public class UrlLauncher { private static final int MAX_WAIT_TIME = 5*60*1000; private static final int MAX_TRIES = 99; + /** + * Browsers to try IN-ORDER + */ + private static final String[] BROWSERS = { + // This debian script tries everything in $BROWSER, then gnome-www-browser and x-www-browser + // if X is running and www-browser otherwise. Those point to the user's preferred + // browser using the update-alternatives system. + "sensible-browser", + // another one that opens a preferred browser + "xdg-open", + // Try x-www-browser directly + "x-www-browser", + // general graphical browsers + "defaultbrowser", // puppy linux + "opera -newpage", + "firefox", + "mozilla", + "netscape", + "konqueror", + "galeon", + // Text Mode Browsers only below here + "www-browser", + "links", + "lynx" + }; + /** * Prevent bad user experience by waiting for the server to be there * before launching the browser. @@ -156,7 +182,7 @@ public class UrlLauncher { if (bufferedReader != null) try { bufferedReader.close(); } catch (IOException ioe) {} } - if (_shellCommand.executeSilentAndWaitTimed(browserString + " " + url, 5)) + if (_shellCommand.executeSilentAndWaitTimed(browserString + ' ' + url, 5)) return true; } else { @@ -164,48 +190,10 @@ public class UrlLauncher { // fall through } - // This debian script tries everything in $BROWSER, then gnome-www-browser and x-www-browser - // if X is running and www-browser otherwise. Those point to the user's preferred - // browser using the update-alternatives system. - if (_shellCommand.executeSilentAndWaitTimed("sensible-browser " + url, 5)) - return true; - - // Try x-www-browser directly - if (_shellCommand.executeSilentAndWaitTimed("x-www-browser " + url, 5)) - return true; - - // puppy linux - if (_shellCommand.executeSilentAndWaitTimed("defaultbrowser " + url, 5)) - return true; - - if (_shellCommand.executeSilentAndWaitTimed("opera -newpage " + url, 5)) - return true; - - if (_shellCommand.executeSilentAndWaitTimed("firefox " + url, 5)) - return true; - - if (_shellCommand.executeSilentAndWaitTimed("mozilla " + url, 5)) - return true; - - if (_shellCommand.executeSilentAndWaitTimed("netscape " + url, 5)) - return true; - - if (_shellCommand.executeSilentAndWaitTimed("konqueror " + url, 5)) - return true; - - if (_shellCommand.executeSilentAndWaitTimed("galeon " + url, 5)) - return true; - - // Text Mode Browsers only below here - if (_shellCommand.executeSilentAndWaitTimed("www-browser " + url, 5)) - return true; - - if (_shellCommand.executeSilentAndWaitTimed("links " + url, 5)) - return true; - - if (_shellCommand.executeSilentAndWaitTimed("lynx " + url, 5)) - return true; - + for (int i = 0; i < BROWSERS.length; i++) { + if (_shellCommand.executeSilentAndWaitTimed(BROWSERS[i] + ' ' + url, 5)) + return true; + } } return false; } diff --git a/core/java/src/net/i2p/I2PAppContext.java b/core/java/src/net/i2p/I2PAppContext.java index be42467f459f7ea4e019ef575beda34f2e252cb1..e7527c3d140929b46ec0bf723d057e175b40f619 100644 --- a/core/java/src/net/i2p/I2PAppContext.java +++ b/core/java/src/net/i2p/I2PAppContext.java @@ -113,13 +113,13 @@ public class I2PAppContext { private volatile boolean _simpleTimerInitialized; private volatile boolean _simpleTimer2Initialized; protected final Set<Runnable> _shutdownTasks; - private File _baseDir; - private File _configDir; - private File _routerDir; - private File _pidDir; - private File _logDir; - private File _appDir; - private File _tmpDir; + private final File _baseDir; + private final File _configDir; + private final File _routerDir; + private final File _pidDir; + private final File _logDir; + private final File _appDir; + private volatile File _tmpDir; // split up big lock on this to avoid deadlocks private final Object _lock1 = new Object(), _lock2 = new Object(), _lock3 = new Object(), _lock4 = new Object(), _lock5 = new Object(), _lock6 = new Object(), _lock7 = new Object(), _lock8 = new Object(), @@ -210,11 +210,9 @@ public class I2PAppContext { if (envProps != null) _overrideProps.putAll(envProps); _shutdownTasks = new ConcurrentHashSet(32); - initializeDirs(); _portMapper = new PortMapper(this); - } - /** + /* * Directories. These are all set at instantiation and will not be changed by * subsequent property changes. * All properties, if set, should be absolute paths. @@ -259,7 +257,7 @@ public class I2PAppContext { * All dirs except the base are created if they don't exist, but the creation will fail silently. * @since 0.7.6 */ - private void initializeDirs() { + String s = getProperty("i2p.dir.base", System.getProperty("user.dir")); _baseDir = new File(s); diff --git a/core/java/src/net/i2p/util/SimpleByteCache.java b/core/java/src/net/i2p/util/SimpleByteCache.java index b41f9ad9b5bf87acedd4aebd7ad8d591b262732f..dae27d80e12e7f71dd0f620da9f58c75e867e295 100644 --- a/core/java/src/net/i2p/util/SimpleByteCache.java +++ b/core/java/src/net/i2p/util/SimpleByteCache.java @@ -16,7 +16,7 @@ import java.util.concurrent.LinkedBlockingQueue; */ public final class SimpleByteCache { - private static final Map<Integer, SimpleByteCache> _caches = new ConcurrentHashMap(8); + private static final ConcurrentHashMap<Integer, SimpleByteCache> _caches = new ConcurrentHashMap(8); private static final int DEFAULT_SIZE = 64; @@ -45,7 +45,9 @@ public final class SimpleByteCache { SimpleByteCache cache = _caches.get(sz); if (cache == null) { cache = new SimpleByteCache(cacheSize, size); - _caches.put(sz, cache); + SimpleByteCache old = _caches.putIfAbsent(sz, cache); + if (old != null) + cache = old; } cache.resize(cacheSize); return cache; diff --git a/history.txt b/history.txt index d802e2979c71b73129a2c05e665ee464010d984f..add456e93b4f922d255b8df588a4c389d0c051a7 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,12 @@ +2012-09-25 zzz + * Context: Make files final + * EventLog: Fix IAE on portable + * Jetty: Add non-NIO selector option (ticket #715) + * OutboundEstablishState: Cleanup (ticket #671) + * SimpleByteCache: Concurrent fix + * UPnP: Cleanup & final + * URLLauncher: Add xdg-open (ticket #617) + 2012-09-21 zzz * BuildHandler: Use CoDel for inbound queue * ByteCache: @@ -45,8 +54,8 @@ - Raise netdb store and reply priority * Router: - Boost priority of shutdown thread - - Replace ident log with new, general-purpose event log. - - Use for stops, starts, and updates, and others. + - Replace ident log with new, general-purpose event log; + use for stops, starts, and updates, and others. - New AQM CoDel queue utilities - Startup/shutdown synchronization fixes * RouterAddress: Remove unused expiration field to save space diff --git a/installer/resources/eepsite/jetty.xml b/installer/resources/eepsite/jetty.xml index 51af5537980d98079877d1f5bdb029d6a99f8b05..ba30a55ebd8264e540799807a8eeaf874ad8fb1d 100644 --- a/installer/resources/eepsite/jetty.xml +++ b/installer/resources/eepsite/jetty.xml @@ -12,7 +12,7 @@ <!-- * port: Default 7658 in the addConnector section --> <!-- * docroot: Change the ResourceBase in the contexts/base-context.xml file --> <!-- to serve files from a different location. --> -<!-- * threads: Raise MinThreads and/or MaxThreads in the addListener section --> +<!-- * threads: Raise maximumPoolSize in the ThreadPool section --> <!-- if you have a high-traffic site and get a lot of warnings. --> <!-- * Uncomment the addWebApplications section to use to enable --> <!-- war files placed in the webapps/ dir. --> @@ -65,7 +65,8 @@ --> <!-- Optional Java 5 bounded threadpool with job queue - Requests above the max will be rejected + Requests above the max will be rejected and logged. + High-traffic sites should increase maximumPoolSize. TODO: would be nice to use the 5-arg constructor but how do you use an Enum as the TimeUnit argument? Alternatively, make a custom class where we can @@ -75,7 +76,7 @@ <New class="org.mortbay.thread.concurrent.ThreadPool"> <Arg type="int">0</Arg> <Set name="corePoolSize">1</Set> - <Set name="maximumPoolSize">16</Set> + <Set name="maximumPoolSize">24</Set> </New> </Set> @@ -89,6 +90,8 @@ <!-- Use this connector for many frequently idle connections and for threadless continuations. + Not recommended on Java 5 - comment out and uncomment the + SocketConnector below. --> <Call name="addConnector"> <Arg> @@ -106,6 +109,24 @@ </Arg> </Call> + <!-- Recommended to use this connector on Java 5, as + Jetty 6 and Java 5 NIO don't play well together. + --> + <!-- + <Call name="addConnector"> + <Arg> + <New class="org.mortbay.jetty.bio.SocketConnector"> + <Set name="host">127.0.0.1</Set> + <Set name="port">7658</Set> + <Set name="maxIdleTime">60000</Set> + <Set name="Acceptors">1</Set> + <Set name="statsOn">false</Set> + <Set name="confidentialPort">8443</Set> + </New> + </Arg> + </Call> + --> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> <!-- To add a HTTPS SSL listener --> <!-- see jetty-ssl.xml to add an ssl connector. use --> diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 87e5bffca0684477c0ba8daee48da05fbea99f44..282c18b42238909e2faa8bba95d82c15667d116c 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 = 1; + public final static long BUILD = 2; /** for example "-test" */ public final static String EXTRA = ""; diff --git a/router/java/src/net/i2p/router/transport/UPnP.java b/router/java/src/net/i2p/router/transport/UPnP.java index 1401b3baab142a89f9571402538fa21519650cd1..abcd8214e7946e0cdf359f29ac7b0a15474f4e8e 100644 --- a/router/java/src/net/i2p/router/transport/UPnP.java +++ b/router/java/src/net/i2p/router/transport/UPnP.java @@ -78,7 +78,7 @@ class UPnP extends ControlPoint implements DeviceChangeListener, EventListener { private volatile boolean thinksWeAreDoubleNatted = false; /** List of ports we want to forward */ - private Set<ForwardPort> portsToForward; + private final Set<ForwardPort> portsToForward; /** List of ports we have actually forwarded */ private final Set<ForwardPort> portsForwarded; /** Callback to call when a forward fails or succeeds */ @@ -88,13 +88,14 @@ class UPnP extends ControlPoint implements DeviceChangeListener, EventListener { super(); _context = context; _log = _context.logManager().getLog(UPnP.class); + portsToForward = new HashSet<ForwardPort>(); portsForwarded = new HashSet<ForwardPort>(); addDeviceChangeListener(this); } - public boolean runPlugin() { + public synchronized boolean runPlugin() { synchronized(lock) { - portsToForward = null; + portsToForward.clear(); } return super.start(); } @@ -102,9 +103,9 @@ class UPnP extends ControlPoint implements DeviceChangeListener, EventListener { /** * WARNING - Blocking up to 2 seconds */ - public void terminate() { + public synchronized void terminate() { synchronized(lock) { - portsToForward = null; + portsToForward.clear(); } // this gets spun off in a thread... unregisterPortMappings(); @@ -221,9 +222,10 @@ class UPnP extends ControlPoint implements DeviceChangeListener, EventListener { private void registerPortMappings() { Set ports; synchronized(lock) { - ports = portsToForward; + ports = new HashSet(portsForwarded); } - if(ports == null) return; + if (ports.isEmpty()) + return; registerPorts(ports); } @@ -281,6 +283,8 @@ class UPnP extends ControlPoint implements DeviceChangeListener, EventListener { synchronized(lock) { ports = new HashSet(portsForwarded); } + if (ports.isEmpty()) + return; this.unregisterPorts(ports); } @@ -528,17 +532,15 @@ class UPnP extends ControlPoint implements DeviceChangeListener, EventListener { if(upstreamMaxBitRate > 0) sb.append("<br>").append(_("UPnP reports the maximum upstream bit rate is {0}bits/sec", DataHelper.formatSize2(upstreamMaxBitRate))); synchronized(lock) { - if(portsToForward != null) { - for(ForwardPort port : portsToForward) { - sb.append("<br>"); - if(portsForwarded.contains(port)) - // {0} is TCP or UDP - // {1,number,#####} prevents 12345 from being output as 12,345 in the English locale. - // If you want the digit separator in your locale, translate as {1}. - sb.append(_("{0} port {1,number,#####} was successfully forwarded by UPnP.", protoToString(port.protocol), port.portNumber)); - else - sb.append(_("{0} port {1,number,#####} was not forwarded by UPnP.", protoToString(port.protocol), port.portNumber)); - } + for(ForwardPort port : portsToForward) { + sb.append("<br>"); + if(portsForwarded.contains(port)) + // {0} is TCP or UDP + // {1,number,#####} prevents 12345 from being output as 12,345 in the English locale. + // If you want the digit separator in your locale, translate as {1}. + sb.append(_("{0} port {1,number,#####} was successfully forwarded by UPnP.", protoToString(port.protocol), port.portNumber)); + else + sb.append(_("{0} port {1,number,#####} was not forwarded by UPnP.", protoToString(port.protocol), port.portNumber)); } } @@ -726,13 +728,13 @@ class UPnP extends ControlPoint implements DeviceChangeListener, EventListener { _log.error("ForwardPortCallback changed from "+forwardCallback+" to "+cb+" - using new value, but this is very strange!"); } forwardCallback = cb; - if(portsToForward == null || portsToForward.isEmpty()) { - portsToForward = ports; + if (portsToForward.isEmpty()) { + portsToForward.addAll(ports); portsToForwardNow = ports; portsToDumpNow = null; } else if(ports.isEmpty()) { portsToDumpNow = portsToForward; - portsToForward = ports; + portsToForward.clear(); portsToForwardNow = null; } else { // Some ports to keep, some ports to dump @@ -760,7 +762,8 @@ class UPnP extends ControlPoint implements DeviceChangeListener, EventListener { portsToDumpNow.add(port); } } - portsToForward = ports; + portsToForward.clear(); + portsToForward.addAll(ports); } if(_router == null) { if (_log.shouldLog(Log.WARN)) @@ -768,9 +771,9 @@ class UPnP extends ControlPoint implements DeviceChangeListener, EventListener { return; // When one is found, we will do the forwards } } - if(portsToDumpNow != null) + if(portsToDumpNow != null && !portsToDumpNow.isEmpty()) unregisterPorts(portsToDumpNow); - if(portsToForwardNow != null) + if(portsToForwardNow != null && !portsToForwardNow.isEmpty()) registerPorts(portsToForwardNow); } diff --git a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java index 47922180d7ac73b732a717de5a27053276fde48f..797060c5838bfab1fb5a5d5db1103de39934356e 100644 --- a/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java +++ b/router/java/src/net/i2p/router/transport/udp/OutboundEstablishState.java @@ -369,7 +369,7 @@ class OutboundEstablishState { off += 4; DataHelper.toLong(signed, off, 4, _receivedSignedOnTime); boolean valid = _context.dsa().verifySignature(_receivedSignature, signed, _remotePeer.getSigningPublicKey()); - if (!valid || _log.shouldLog(Log.DEBUG)) { + if (_log.shouldLog(Log.DEBUG) || (_log.shouldLog(Log.WARN) && !valid)) { StringBuilder buf = new StringBuilder(128); buf.append("Signed sessionCreated:"); buf.append(" Alice: ").append(Addresses.toString(_aliceIP, _alicePort)); diff --git a/router/java/src/net/i2p/router/util/EventLog.java b/router/java/src/net/i2p/router/util/EventLog.java index 9a2d9d20e114cfe080d320561f078929613f2114..d3486206ba83e25f776bd006323d578bdc2aaaf3 100644 --- a/router/java/src/net/i2p/router/util/EventLog.java +++ b/router/java/src/net/i2p/router/util/EventLog.java @@ -48,12 +48,11 @@ public class EventLog { public static final String WATCHDOG = "watchdog"; /** - * @param file must be absolute - * @throws IllegalArgumentException if not absolute + * @param file should be absolute */ public EventLog(I2PAppContext ctx, File file) { - if (!file.isAbsolute()) - throw new IllegalArgumentException(); + //if (!file.isAbsolute()) + // throw new IllegalArgumentException(); _context = ctx; _file = file; _cache = new HashMap(4); @@ -128,7 +127,7 @@ public class EventLog { continue; Long ltime = Long.valueOf(time); String info = s.length > 2 ? s[2] : ""; - rv.put(time, info); + rv.put(ltime, info); } catch (IndexOutOfBoundsException ioobe) { } catch (NumberFormatException nfe) { }