Author: toad Date: 2008-09-24 20:42:20 +0000 (Wed, 24 Sep 2008) New Revision: 22823
Added: branches/db4o/freenet/src/freenet/config/ConfigException.java branches/db4o/freenet/src/freenet/config/NodeNeedRestartException.java branches/db4o/freenet/src/freenet/node/simulator/BootstrapPullTest.java branches/db4o/freenet/src/freenet/node/simulator/BootstrapPushPullTest.java branches/db4o/freenet/src/freenet/node/simulator/BootstrapSeedTest.java branches/db4o/freenet/src/freenet/pluginmanager/FredPluginBandwidthIndicator.java branches/db4o/freenet/test/freenet/crypt/YarrowTest.java branches/db4o/freenet/test/freenet/support/io/ branches/db4o/freenet/test/freenet/support/io/LineReadingInputStreamTest.java Removed: branches/db4o/freenet/src/freenet/client/TempStoreElement.java branches/db4o/freenet/src/freenet/clients/http/PluginToadlet.java branches/db4o/freenet/src/freenet/crypt/DigestFactory.java branches/db4o/freenet/src/freenet/crypt/SHA1Factory.java branches/db4o/freenet/src/freenet/oldplugins/ branches/db4o/freenet/src/freenet/support/StringArray.java branches/db4o/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucketFactory.java branches/db4o/freenet/src/freenet/support/io/PersistentEncryptedTempBucketFactory.java branches/db4o/freenet/test/freenet/support/io/LineReadingInputStreamTest.java Modified: branches/db4o/freenet/src/freenet/client/ArchiveManager.java branches/db4o/freenet/src/freenet/client/FECCodec.java branches/db4o/freenet/src/freenet/client/HighLevelSimpleClient.java branches/db4o/freenet/src/freenet/client/HighLevelSimpleClientImpl.java branches/db4o/freenet/src/freenet/client/RealArchiveStoreItem.java branches/db4o/freenet/src/freenet/client/async/BaseSingleFileFetcher.java branches/db4o/freenet/src/freenet/client/async/ClientContext.java branches/db4o/freenet/src/freenet/client/async/ClientRequestScheduler.java branches/db4o/freenet/src/freenet/client/async/SimpleManifestPutter.java branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSegment.java branches/db4o/freenet/src/freenet/clients/http/ConfigToadlet.java branches/db4o/freenet/src/freenet/clients/http/ConnectionsToadlet.java branches/db4o/freenet/src/freenet/clients/http/FProxyToadlet.java branches/db4o/freenet/src/freenet/clients/http/FirstTimeWizardToadlet.java branches/db4o/freenet/src/freenet/clients/http/HTTPRequestImpl.java branches/db4o/freenet/src/freenet/clients/http/PageMaker.java branches/db4o/freenet/src/freenet/clients/http/QueueToadlet.java branches/db4o/freenet/src/freenet/clients/http/SimpleToadletServer.java branches/db4o/freenet/src/freenet/clients/http/StatisticsToadlet.java branches/db4o/freenet/src/freenet/clients/http/SymlinkerToadlet.java branches/db4o/freenet/src/freenet/clients/http/Toadlet.java branches/db4o/freenet/src/freenet/clients/http/bookmark/BookmarkCategory.java branches/db4o/freenet/src/freenet/clients/http/staticfiles/defaultbookmarks.dat branches/db4o/freenet/src/freenet/clients/http/staticfiles/themes/clean/theme.css branches/db4o/freenet/src/freenet/config/BooleanOption.java branches/db4o/freenet/src/freenet/config/Config.java branches/db4o/freenet/src/freenet/config/ConfigCallback.java branches/db4o/freenet/src/freenet/config/IntOption.java branches/db4o/freenet/src/freenet/config/InvalidConfigValueException.java branches/db4o/freenet/src/freenet/config/LongOption.java branches/db4o/freenet/src/freenet/config/NullBooleanCallback.java branches/db4o/freenet/src/freenet/config/NullIntCallback.java branches/db4o/freenet/src/freenet/config/NullLongCallback.java branches/db4o/freenet/src/freenet/config/NullShortCallback.java branches/db4o/freenet/src/freenet/config/NullStringCallback.java branches/db4o/freenet/src/freenet/config/Option.java branches/db4o/freenet/src/freenet/config/PersistentConfig.java branches/db4o/freenet/src/freenet/config/ShortOption.java branches/db4o/freenet/src/freenet/config/StringArrOption.java branches/db4o/freenet/src/freenet/config/StringOption.java branches/db4o/freenet/src/freenet/config/SubConfig.java branches/db4o/freenet/src/freenet/config/WrapperConfig.java branches/db4o/freenet/src/freenet/crypt/DiffieHellman.java branches/db4o/freenet/src/freenet/crypt/SSL.java branches/db4o/freenet/src/freenet/crypt/Yarrow.java branches/db4o/freenet/src/freenet/io/AddressIdentifier.java branches/db4o/freenet/src/freenet/io/NetworkInterface.java branches/db4o/freenet/src/freenet/io/comm/DMT.java branches/db4o/freenet/src/freenet/io/comm/FreenetInetAddress.java branches/db4o/freenet/src/freenet/io/comm/UdpSocketHandler.java branches/db4o/freenet/src/freenet/l10n/L10n.java branches/db4o/freenet/src/freenet/l10n/freenet.l10n.de.properties branches/db4o/freenet/src/freenet/l10n/freenet.l10n.en.properties branches/db4o/freenet/src/freenet/l10n/freenet.l10n.fr.properties branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-cn.properties branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-tw.properties branches/db4o/freenet/src/freenet/node/ConfigurablePersister.java branches/db4o/freenet/src/freenet/node/FNPPacketMangler.java branches/db4o/freenet/src/freenet/node/FailureTable.java branches/db4o/freenet/src/freenet/node/FailureTableEntry.java branches/db4o/freenet/src/freenet/node/GlobalProbe.java branches/db4o/freenet/src/freenet/node/IPDetectorPluginManager.java branches/db4o/freenet/src/freenet/node/LoggingConfigHandler.java branches/db4o/freenet/src/freenet/node/Node.java branches/db4o/freenet/src/freenet/node/NodeClientCore.java branches/db4o/freenet/src/freenet/node/NodeCrypto.java branches/db4o/freenet/src/freenet/node/NodeCryptoConfig.java branches/db4o/freenet/src/freenet/node/NodeDispatcher.java branches/db4o/freenet/src/freenet/node/NodeIPDetector.java branches/db4o/freenet/src/freenet/node/NodeInitException.java branches/db4o/freenet/src/freenet/node/NodeStarter.java branches/db4o/freenet/src/freenet/node/NodeStats.java branches/db4o/freenet/src/freenet/node/PeerManager.java branches/db4o/freenet/src/freenet/node/PeerNode.java branches/db4o/freenet/src/freenet/node/PeerNodeStatus.java branches/db4o/freenet/src/freenet/node/SeedClientPeerNode.java branches/db4o/freenet/src/freenet/node/TestnetHandler.java branches/db4o/freenet/src/freenet/node/TextModeClientInterface.java branches/db4o/freenet/src/freenet/node/TextModeClientInterfaceServer.java branches/db4o/freenet/src/freenet/node/UptimeEstimator.java branches/db4o/freenet/src/freenet/node/fcp/ClientGet.java branches/db4o/freenet/src/freenet/node/fcp/ClientPutMessage.java branches/db4o/freenet/src/freenet/node/fcp/ClientRequest.java branches/db4o/freenet/src/freenet/node/fcp/ConfigData.java branches/db4o/freenet/src/freenet/node/fcp/FCPConnectionHandler.java branches/db4o/freenet/src/freenet/node/fcp/FCPServer.java branches/db4o/freenet/src/freenet/node/fcp/PutSuccessfulMessage.java branches/db4o/freenet/src/freenet/node/simulator/RealNodeBusyNetworkTest.java branches/db4o/freenet/src/freenet/node/simulator/RealNodeRequestInsertTest.java branches/db4o/freenet/src/freenet/node/simulator/SeednodePingTest.java branches/db4o/freenet/src/freenet/node/updater/NodeUpdateManager.java branches/db4o/freenet/src/freenet/node/useralerts/MeaningfulNodeNameUserAlert.java branches/db4o/freenet/src/freenet/pluginmanager/PluginDownLoaderOfficial.java branches/db4o/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java branches/db4o/freenet/src/freenet/pluginmanager/PluginManager.java branches/db4o/freenet/src/freenet/store/RAMFreenetStore.java branches/db4o/freenet/src/freenet/support/DoublyLinkedList.java branches/db4o/freenet/src/freenet/support/DoublyLinkedListImpl.java branches/db4o/freenet/src/freenet/support/Fields.java branches/db4o/freenet/src/freenet/support/FileLoggerHook.java branches/db4o/freenet/src/freenet/support/HTMLEncoder.java branches/db4o/freenet/src/freenet/support/HTMLNode.java branches/db4o/freenet/src/freenet/support/LRUHashtable.java branches/db4o/freenet/src/freenet/support/OOMHandler.java branches/db4o/freenet/src/freenet/support/PooledExecutor.java branches/db4o/freenet/src/freenet/support/SimpleFieldSet.java branches/db4o/freenet/src/freenet/support/SizeUtil.java branches/db4o/freenet/src/freenet/support/SortedLongSet.java branches/db4o/freenet/src/freenet/support/TimeSortedHashtable.java branches/db4o/freenet/src/freenet/support/WeakHashSet.java branches/db4o/freenet/src/freenet/support/api/BooleanCallback.java branches/db4o/freenet/src/freenet/support/api/IntCallback.java branches/db4o/freenet/src/freenet/support/api/LongCallback.java branches/db4o/freenet/src/freenet/support/api/ShortCallback.java branches/db4o/freenet/src/freenet/support/api/StringArrCallback.java branches/db4o/freenet/src/freenet/support/api/StringCallback.java branches/db4o/freenet/src/freenet/support/compress/GzipCompressor.java branches/db4o/freenet/src/freenet/support/io/ArrayBucket.java branches/db4o/freenet/src/freenet/support/io/BaseFileBucket.java branches/db4o/freenet/src/freenet/support/io/BucketTools.java branches/db4o/freenet/src/freenet/support/io/Closer.java branches/db4o/freenet/src/freenet/support/io/DelayedFreeBucket.java branches/db4o/freenet/src/freenet/support/io/LineReadingInputStream.java branches/db4o/freenet/src/freenet/support/io/NativeThread.java branches/db4o/freenet/src/freenet/support/io/PersistentTempBucketFactory.java branches/db4o/freenet/src/freenet/support/io/RandomAccessThing.java branches/db4o/freenet/src/freenet/support/io/TempBucketFactory.java branches/db4o/freenet/test/freenet/support/BufferTest.java branches/db4o/freenet/test/freenet/support/ByteArrayWrapperTest.java branches/db4o/freenet/test/freenet/support/MultiValueTableTest.java Log: Merge 1155 into db4o branch. All changes from 21652 to 21939. Modified: branches/db4o/freenet/src/freenet/client/ArchiveManager.java =================================================================== --- branches/db4o/freenet/src/freenet/client/ArchiveManager.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/client/ArchiveManager.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -3,7 +3,6 @@ * http://www.gnu.org/ for further details of the GPL. */ package freenet.client; -import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.util.Arrays; @@ -20,11 +19,8 @@ import freenet.support.Logger; import freenet.support.MutableBoolean; import freenet.support.api.Bucket; +import freenet.support.api.BucketFactory; import freenet.support.io.BucketTools; -import freenet.support.io.FilenameGenerator; -import freenet.support.io.PaddedEphemerallyEncryptedBucket; -import freenet.support.io.TempFileBucket; -import java.util.Random; import com.db4o.ObjectContainer; @@ -41,9 +37,7 @@ public static final String METADATA_NAME = ".metadata"; private static boolean logMINOR; - - final RandomSource strongPRNG; - final Random weakPRNG; + final long maxArchiveSize; final long maxArchivedFileSize; @@ -60,8 +54,8 @@ private long cachedData; /** Map from ArchiveKey to ArchiveStoreElement */ private final LRUHashtable storedData; - /** Filename generator */ - private final FilenameGenerator filenameGenerator; + /** Bucket Factory */ + private final BucketFactory tempBucketFactory; /** * Create an ArchiveManager. @@ -78,7 +72,7 @@ * @param random A cryptographicaly secure random source * @param weakRandom A weak and cheap random source */ - public ArchiveManager(int maxHandlers, long maxCachedData, long maxArchiveSize, long maxArchivedFileSize, int maxCachedElements, RandomSource random, Random weakRandom, FilenameGenerator filenameGenerator) { + public ArchiveManager(int maxHandlers, long maxCachedData, long maxArchiveSize, long maxArchivedFileSize, int maxCachedElements, BucketFactory tempBucketFactory) { maxArchiveHandlers = maxHandlers; archiveHandlers = new LRUHashtable(); this.maxCachedElements = maxCachedElements; @@ -86,9 +80,7 @@ storedData = new LRUHashtable(); this.maxArchiveSize = maxArchiveSize; this.maxArchivedFileSize = maxArchivedFileSize; - this.strongPRNG = random; - this.weakPRNG = weakRandom; - this.filenameGenerator = filenameGenerator; + this.tempBucketFactory = tempBucketFactory; logMINOR = Logger.shouldLog(Logger.MINOR, this); } @@ -253,8 +245,7 @@ } else { // Read the element long realLen = 0; - TempStoreElement temp = makeTempStoreBucket(size); - Bucket output = temp.bucket; + Bucket output = tempBucketFactory.makeBucket(size); OutputStream out = output.getOutputStream(); int readBytes; @@ -264,7 +255,7 @@ if(readBytes > maxArchivedFileSize) { addErrorElement(ctx, key, name, "File too big: "+maxArchivedFileSize+" greater than current archived file size limit "+maxArchivedFileSize); out.close(); - temp.close(); + output.free(); continue outer; } } @@ -272,7 +263,7 @@ out.close(); if(name.equals(".metadata")) gotMetadata = true; - addStoreElement(ctx, key, name, temp, gotElement, element, callback, container, context); + addStoreElement(ctx, key, name, output, gotElement, element, callback, container, context); names.add(name); trimStoredData(); } @@ -328,18 +319,19 @@ addToDirectory(dir, name, ""); } Metadata metadata = new Metadata(dir, ""); - TempStoreElement element = makeTempStoreBucket(-1); int x = 0; + Bucket bucket = null; while(true) { try { + bucket = tempBucketFactory.makeBucket(Metadata.MAX_SPLITFILE_PARAMS_LENGTH); byte[] buf = metadata.writeToByteArray(); - OutputStream os = element.bucket.getOutputStream(); + OutputStream os = bucket.getOutputStream(); os.write(buf); os.close(); - return addStoreElement(ctx, key, ".metadata", element, gotElement, element2, callback, container, context); + return addStoreElement(ctx, key, ".metadata", bucket, gotElement, element2, callback, container, context); } catch (MetadataUnresolvedException e) { try { - x = resolve(e, x, element, ctx, key, gotElement, element2, callback, container, context); + x = resolve(e, x, bucket, ctx, key, gotElement, element2, callback, container, context); } catch (IOException e1) { throw new ArchiveFailureException("Failed to create metadata: "+e1, e1); } @@ -350,17 +342,17 @@ } } - private int resolve(MetadataUnresolvedException e, int x, TempStoreElement element, ArchiveStoreContext ctx, FreenetURI key, MutableBoolean gotElement, String element2, ArchiveExtractCallback callback, ObjectContainer container, ClientContext context) throws IOException, ArchiveFailureException { + private int resolve(MetadataUnresolvedException e, int x, Bucket bucket, ArchiveStoreContext ctx, FreenetURI key, MutableBoolean gotElement, String element2, ArchiveExtractCallback callback, ObjectContainer container, ClientContext context) throws IOException, ArchiveFailureException { Metadata[] m = e.mustResolve; for(int i=0;i<m.length;i++) { try { byte[] buf = m[i].writeToByteArray(); - OutputStream os = element.bucket.getOutputStream(); + OutputStream os = bucket.getOutputStream(); os.write(buf); os.close(); - addStoreElement(ctx, key, ".metadata-"+(x++), element, gotElement, element2, callback, container, context); + addStoreElement(ctx, key, ".metadata-"+(x++), bucket, gotElement, element2, callback, container, context); } catch (MetadataUnresolvedException e1) { - x = resolve(e, x, element, ctx, key, gotElement, element2, callback, container, context); + x = resolve(e, x, bucket, ctx, key, gotElement, element2, callback, container, context); } } return x; @@ -428,7 +420,7 @@ * @throws ArchiveFailureException If a failure occurred resulting in the data not being readable. Only happens if * callback != null. */ - private ArchiveStoreItem addStoreElement(ArchiveStoreContext ctx, FreenetURI key, String name, TempStoreElement temp, MutableBoolean gotElement, String callbackName, ArchiveExtractCallback callback, ObjectContainer container, ClientContext context) throws ArchiveFailureException { + private ArchiveStoreItem addStoreElement(ArchiveStoreContext ctx, FreenetURI key, String name, Bucket temp, MutableBoolean gotElement, String callbackName, ArchiveExtractCallback callback, ObjectContainer container, ClientContext context) throws ArchiveFailureException { RealArchiveStoreItem element = new RealArchiveStoreItem(ctx, key, name, temp); if(logMINOR) Logger.minor(this, "Adding store element: "+element+" ( "+key+ ' ' +name+" size "+element.spaceUsed()+" )"); ArchiveStoreItem oldItem; @@ -479,23 +471,6 @@ } } - /** - * Create a file Bucket in the store directory, encrypted using an ethereal key. - * This is not yet associated with a name, so will be deleted when it goes out - * of scope. Not counted towards allocated data as will be short-lived and will not - * go over the maximum size. Will obviously keep its key when we move it to main. - */ - private TempStoreElement makeTempStoreBucket(long size) { - long id = filenameGenerator.makeRandomFilename(); - File myFile = filenameGenerator.getFilename(id); - TempFileBucket fb = new TempFileBucket(id, filenameGenerator); - - byte[] cipherKey = new byte[32]; - strongPRNG.nextBytes(cipherKey); - PaddedEphemerallyEncryptedBucket encryptedBucket = new PaddedEphemerallyEncryptedBucket(fb, 1024, strongPRNG, weakPRNG); - return new TempStoreElement(myFile, fb, encryptedBucket); - } - /** * Is the given MIME type an archive type that we can deal with? */ Modified: branches/db4o/freenet/src/freenet/client/FECCodec.java =================================================================== --- branches/db4o/freenet/src/freenet/client/FECCodec.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/client/FECCodec.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -196,7 +196,7 @@ for(int i = 0; i < dataBlockStatus.length; i++) { Bucket data = buckets[i]; if(data.size() != blockLength) - throw new IllegalStateException("Block " + i + ": " + data + " : " + dataBlockStatus[i] + " length " + data.size()); + throw new IllegalStateException("Block " + i + ": " + data + " : " + dataBlockStatus[i] + " length " + data.size() + " whereas blockLength="+blockLength); dataBlockStatus[i].setData(data); } } Modified: branches/db4o/freenet/src/freenet/client/HighLevelSimpleClient.java =================================================================== --- branches/db4o/freenet/src/freenet/client/HighLevelSimpleClient.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/client/HighLevelSimpleClient.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -7,6 +7,8 @@ import java.util.Set; import freenet.client.async.ClientCallback; +import freenet.client.async.ClientGetter; +import freenet.client.async.ClientPutter; import freenet.client.events.ClientEventListener; import freenet.keys.FreenetURI; import freenet.node.RequestClient; @@ -42,7 +44,7 @@ /** * Non-blocking fetch of a URI with a configurable max-size, context object, callback and context. */ - public void fetch(FreenetURI uri, long maxSize, RequestClient context, ClientCallback callback, FetchContext fctx) throws FetchException; + public ClientGetter fetch(FreenetURI uri, long maxSize, RequestClient context, ClientCallback callback, FetchContext fctx) throws FetchException; /** * Blocking insert. @@ -54,7 +56,7 @@ /** * Non-blocking insert. */ - public void insert(InsertBlock insert, boolean getCHKOnly, String filenameHint, boolean isMetadata, InsertContext ctx, ClientCallback cb) throws InsertException; + public ClientPutter insert(InsertBlock insert, boolean getCHKOnly, String filenameHint, boolean isMetadata, InsertContext ctx, ClientCallback cb) throws InsertException; /** * Blocking insert of a redirect. Modified: branches/db4o/freenet/src/freenet/client/HighLevelSimpleClientImpl.java =================================================================== --- branches/db4o/freenet/src/freenet/client/HighLevelSimpleClientImpl.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/client/HighLevelSimpleClientImpl.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -92,7 +92,7 @@ curMaxTempLength = Long.MAX_VALUE; curMaxMetadataLength = 1024 * 1024; this.cacheLocalRequests = cacheLocalRequests; - this.persistentBucketFactory = node.persistentEncryptedTempBucketFactory; + this.persistentBucketFactory = node.persistentTempBucketFactory; } public void setMaxLength(long maxLength) { @@ -128,10 +128,11 @@ return fw.waitForCompletion(); } - public void fetch(FreenetURI uri, long maxSize, RequestClient clientContext, ClientCallback callback, FetchContext fctx) throws FetchException { + public ClientGetter fetch(FreenetURI uri, long maxSize, RequestClient clientContext, ClientCallback callback, FetchContext fctx) throws FetchException { if(uri == null) throw new NullPointerException(); ClientGetter get = new ClientGetter(callback, core.requestStarters.chkFetchScheduler, core.requestStarters.sskFetchScheduler, uri, fctx, priorityClass, clientContext, null, null); core.clientContext.start(get); + return get; } public FreenetURI insert(InsertBlock insert, boolean getCHKOnly, String filenameHint) throws InsertException { @@ -148,11 +149,12 @@ return pw.waitForCompletion(); } - public void insert(InsertBlock insert, boolean getCHKOnly, String filenameHint, boolean isMetadata, InsertContext ctx, ClientCallback cb) throws InsertException { + public ClientPutter insert(InsertBlock insert, boolean getCHKOnly, String filenameHint, boolean isMetadata, InsertContext ctx, ClientCallback cb) throws InsertException { ClientPutter put = new ClientPutter(cb, insert.getData(), insert.desiredURI, insert.clientMetadata, ctx, core.requestStarters.chkPutScheduler, core.requestStarters.sskPutScheduler, priorityClass, getCHKOnly, isMetadata, this, null, filenameHint, false); core.clientContext.start(put, false); + return put; } public FreenetURI insertRedirect(FreenetURI insertURI, FreenetURI targetURI) throws InsertException { Modified: branches/db4o/freenet/src/freenet/client/RealArchiveStoreItem.java =================================================================== --- branches/db4o/freenet/src/freenet/client/RealArchiveStoreItem.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/client/RealArchiveStoreItem.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -3,16 +3,12 @@ * http://www.gnu.org/ for further details of the GPL. */ package freenet.client; -import java.io.File; - import freenet.keys.FreenetURI; import freenet.support.api.Bucket; -import freenet.support.io.FileUtil; import freenet.support.io.MultiReaderBucket; class RealArchiveStoreItem extends ArchiveStoreItem { - private final File myFilename; private final MultiReaderBucket mb; private final Bucket bucket; private final long spaceUsed; @@ -24,13 +20,12 @@ * @param temp The TempStoreElement currently storing the data. * @param manager The parent ArchiveManager within which this item is stored. */ - RealArchiveStoreItem(ArchiveStoreContext ctx, FreenetURI key2, String realName, TempStoreElement temp) { + RealArchiveStoreItem(ArchiveStoreContext ctx, FreenetURI key2, String realName, Bucket bucket) { super(new ArchiveKey(key2, realName), ctx); - mb = new MultiReaderBucket(temp.bucket); + mb = new MultiReaderBucket(bucket); this.bucket = mb.getReaderBucket(); - temp.underBucket.setReadOnly(); - this.myFilename = temp.underBucket.getFile(); - spaceUsed = FileUtil.estimateUsage(myFilename, temp.underBucket.size()); + bucket.setReadOnly(); + spaceUsed = bucket.size(); } /** @@ -54,6 +49,7 @@ return spaceUsed; } + @Override void innerClose() { bucket.free(); } Deleted: branches/db4o/freenet/src/freenet/client/TempStoreElement.java =================================================================== --- branches/db4o/freenet/src/freenet/client/TempStoreElement.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/client/TempStoreElement.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -1,25 +0,0 @@ -/* This code is part of Freenet. It is distributed under the GNU General - * Public License, version 2 (or at your option any later version). See - * http://www.gnu.org/ for further details of the GPL. */ -package freenet.client; - -import java.io.File; - -import freenet.support.io.PaddedEphemerallyEncryptedBucket; -import freenet.support.io.TempFileBucket; - -class TempStoreElement { - final File myFilename; - final PaddedEphemerallyEncryptedBucket bucket; - final TempFileBucket underBucket; - - TempStoreElement(File myFile, TempFileBucket fb, PaddedEphemerallyEncryptedBucket encryptedBucket) { - this.myFilename = myFile; - this.underBucket = fb; - this.bucket = encryptedBucket; - } - - public void close() { - underBucket.free(); - } -} \ No newline at end of file Modified: branches/db4o/freenet/src/freenet/client/async/BaseSingleFileFetcher.java =================================================================== --- branches/db4o/freenet/src/freenet/client/async/BaseSingleFileFetcher.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/client/async/BaseSingleFileFetcher.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -18,6 +18,7 @@ import freenet.node.RequestClient; import freenet.node.RequestScheduler; import freenet.node.SendableGet; +import freenet.support.Executor; import freenet.support.Logger; public abstract class BaseSingleFileFetcher extends SendableGet implements HasKeyListener { @@ -109,11 +110,10 @@ if(persistent) container.deactivate(key, 5); } - return true; // We will retry, just not yet. See requeueAfterCooldown(Key). } else { reschedule(container, context); } - return true; + return true; // We will retry in any case, maybe not just not yet. See requeueAfterCooldown(Key). } return false; } Modified: branches/db4o/freenet/src/freenet/client/async/ClientContext.java =================================================================== --- branches/db4o/freenet/src/freenet/client/async/ClientContext.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/client/async/ClientContext.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -58,7 +58,7 @@ this.backgroundBlockEncoder = core.backgroundBlockEncoder; this.random = core.random; archiveManager = core.archiveManager; - this.persistentBucketFactory = core.persistentEncryptedTempBucketFactory; + this.persistentBucketFactory = core.persistentTempBucketFactory; this.tempBucketFactory = core.tempBucketFactory; this.healingQueue = core.getHealingQueue(); this.uskManager = core.uskManager; Modified: branches/db4o/freenet/src/freenet/client/async/ClientRequestScheduler.java =================================================================== --- branches/db4o/freenet/src/freenet/client/async/ClientRequestScheduler.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/client/async/ClientRequestScheduler.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -48,7 +48,7 @@ private static boolean logMINOR; - public static class PrioritySchedulerCallback implements StringCallback, EnumerableOptionCallback { + public static class PrioritySchedulerCallback extends StringCallback implements EnumerableOptionCallback { final ClientRequestScheduler cs; private final String[] possibleValues = new String[]{ ClientRequestScheduler.PRIORITY_HARD, ClientRequestScheduler.PRIORITY_SOFT }; Modified: branches/db4o/freenet/src/freenet/client/async/SimpleManifestPutter.java =================================================================== --- branches/db4o/freenet/src/freenet/client/async/SimpleManifestPutter.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/client/async/SimpleManifestPutter.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -474,7 +474,7 @@ // FIXME support formats other than .zip. // Only the *decoding* is generic at present. - Bucket zipBucket = context.getBucketFactory(persistent()).makeBucket(-1); + Bucket zipBucket = context.getBucketFactory(persistent()).makeBucket(baseMetadata.dataLength()); OutputStream os = new BufferedOutputStream(zipBucket.getOutputStream()); ZipOutputStream zos = new ZipOutputStream(os); ZipEntry ze; Modified: branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSegment.java =================================================================== --- branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSegment.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/client/async/SplitFileFetcherSegment.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -373,7 +373,7 @@ } } } - decodedData = context.getBucketFactory(persistent).makeBucket(-1); + decodedData = context.getBucketFactory(persistent).makeBucket(maxBlockLength * dataBuckets.length); if(logMINOR) Logger.minor(this, "Copying data from "+dataBuckets.length+" data blocks"); OutputStream os = decodedData.getOutputStream(); for(int i=0;i<dataBuckets.length;i++) { Modified: branches/db4o/freenet/src/freenet/clients/http/ConfigToadlet.java =================================================================== --- branches/db4o/freenet/src/freenet/clients/http/ConfigToadlet.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/clients/http/ConfigToadlet.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -10,14 +10,18 @@ import freenet.client.HighLevelSimpleClient; import freenet.config.BooleanOption; import freenet.config.Config; +import freenet.config.ConfigCallback; import freenet.config.EnumerableOptionCallback; import freenet.config.InvalidConfigValueException; +import freenet.config.NodeNeedRestartException; import freenet.config.Option; import freenet.config.SubConfig; import freenet.config.WrapperConfig; import freenet.l10n.L10n; import freenet.node.Node; import freenet.node.NodeClientCore; +import freenet.node.useralerts.AbstractUserAlert; +import freenet.node.useralerts.UserAlert; import freenet.support.HTMLNode; import freenet.support.Logger; import freenet.support.MultiValueTable; @@ -32,7 +36,64 @@ private final Config config; private final NodeClientCore core; private final Node node; - + private boolean needRestart = false; + private NeedRestartUserAlert needRestartUserAlert; + + private class NeedRestartUserAlert extends AbstractUserAlert { + @Override + public String getTitle() { + return l10n("needRestartTitle"); + } + + @Override + public String getText() { + return getHTMLText().toString(); + } + + @Override + public String getShortText() { + return l10n("needRestartShort"); + } + + @Override + public HTMLNode getHTMLText() { + HTMLNode alertNode = new HTMLNode("div"); + alertNode.addChild("#", l10n("needRestart")); + + if (node.isUsingWrapper()) { + alertNode.addChild("br"); + HTMLNode restartForm = alertNode.addChild("form", // + new String[] { "action", "method" },// + new String[] { "/", "get" }); + restartForm.addChild("div"); + restartForm.addChild("input",// + new String[] { "type", "name" },// + new String[] { "hidden", "restart" }); + restartForm.addChild("input", // + new String[] { "type", "name", "value" },// + new String[] { "submit", "restart2",// + l10n("restartNode") }); + } + + return alertNode; + } + + @Override + public short getPriorityClass() { + return UserAlert.WARNING; + } + + @Override + public boolean isValid() { + return needRestart; + } + + @Override + public boolean userCanDismiss() { + return false; + } + } + ConfigToadlet(HighLevelSimpleClient client, Config conf, Node node, NodeClientCore core) { super(client); config=conf; @@ -40,7 +101,9 @@ this.node = node; } - public void handlePost(URI uri, HTTPRequest request, ToadletContext ctx) throws ToadletContextClosedException, IOException { + + @Override + public void handlePost(URI uri, HTTPRequest request, ToadletContext ctx) throws ToadletContextClosedException, IOException { StringBuffer errbuf = new StringBuffer(); SubConfig[] sc = config.getConfigs(); @@ -60,7 +123,7 @@ boolean logMINOR = Logger.shouldLog(Logger.MINOR, this); for(int i=0; i<sc.length ; i++){ - Option[] o = sc[i].getOptions(); + Option<?>[] o = sc[i].getOptions(); String prefix = sc[i].getPrefix(); String configName; @@ -68,7 +131,7 @@ configName=o[j].getName(); if(logMINOR) Logger.minor(this, "Setting "+prefix+ '.' +configName); - // we ignore unreconized parameters + // we ignore unreconized parameters if(request.isPartSet(prefix+ '.' +configName)) { String value = request.getPartAsString(prefix+ '.' +configName, MAX_PARAM_VALUE_SIZE); if(!(o[j].getValueString().equals(value))){ @@ -77,6 +140,8 @@ o[j].setValue(value); } catch (InvalidConfigValueException e) { errbuf.append(o[j].getName()).append(' ').append(e.getMessage()).append('\n'); + } catch (NodeNeedRestartException e) { + needRestart = true; } catch (Exception e){ errbuf.append(o[j].getName()).append(' ').append(e).append('\n'); Logger.error(this, "Caught "+e, e); @@ -102,7 +167,32 @@ if (errbuf.length() == 0) { HTMLNode infobox = contentNode.addChild(ctx.getPageMaker().getInfobox("infobox-success", l10n("appliedTitle"))); - ctx.getPageMaker().getContentNode(infobox).addChild("#", l10n("appliedSuccess")); + HTMLNode content = ctx.getPageMaker().getContentNode(infobox); + content.addChild("#", l10n("appliedSuccess")); + + if (needRestart) { + content.addChild("br"); + content.addChild("#", l10n("needRestart")); + + if (node.isUsingWrapper()) { + content.addChild("br"); + HTMLNode restartForm = content.addChild("form",// + new String[] { "action", "method" }, new String[] { "/", "get" }// + ).addChild("div"); + restartForm.addChild("input",// + new String[] { "type", "name" },// + new String[] { "hidden", "restart" }); + restartForm.addChild("input", // + new String[] { "type", "name", "value" },// + new String[] { "submit", "restart2",// + l10n("restartNode") }); + } + + if (needRestartUserAlert == null) { + needRestartUserAlert = new NeedRestartUserAlert(); + node.clientCore.alerts.register(needRestartUserAlert); + } + } } else { HTMLNode infobox = contentNode.addChild(ctx.getPageMaker().getInfobox("infobox-error", l10n("appliedFailureTitle"))); HTMLNode content = ctx.getPageMaker().getContentNode(infobox).addChild("div", "class", "infobox-content"); @@ -125,7 +215,8 @@ return L10n.getString("ConfigToadlet." + string); } - public void handleGet(URI uri, HTTPRequest req, ToadletContext ctx) throws ToadletContextClosedException, IOException { + @Override + public void handleGet(URI uri, HTTPRequest req, ToadletContext ctx) throws ToadletContextClosedException, IOException { if(!ctx.isAllowedFullAccess()) { super.sendErrorPage(ctx, 403, L10n.getString("Toadlet.unauthorizedTitle"), L10n.getString("Toadlet.unauthorized")); @@ -171,7 +262,7 @@ String defaultValue = "128"; String curValue = WrapperConfig.getWrapperProperty(configName); item.addChild("span", new String[]{ "class", "title", "style" }, - new String[]{ "configshortdesc", L10n.getString("ConfigToadlet.defaultIs", new String[] { "default" }, new String[] { defaultValue }), + new String[]{ "configshortdesc", L10n.getString("ConfigToadlet.defaultIs", new String[] { "default" }, new String[] { defaultValue }), "cursor: help;" }).addChild(L10n.getHTMLNode("WrapperConfig."+configName+".short")); item.addChild("span", "class", "config").addChild("input", new String[] { "type", "class", "name", "value" }, new String[] { "text", "config", configName, curValue }); item.addChild("span", "class", "configlongdesc").addChild(L10n.getHTMLNode("WrapperConfig."+configName+".long")); @@ -180,7 +271,7 @@ for(int i=0; i<sc.length;i++){ short displayedConfigElements = 0; - Option[] o = sc[i].getOptions(); + Option<?>[] o = sc[i].getOptions(); HTMLNode configGroupUlNode = new HTMLNode("ul", "class", "config"); for(int j=0; j<o.length; j++){ @@ -190,20 +281,31 @@ HTMLNode configItemNode = configGroupUlNode.addChild("li"); configItemNode.addChild("span", new String[]{ "class", "title", "style" }, - new String[]{ "configshortdesc", L10n.getString("ConfigToadlet.defaultIs", new String[] { "default" }, new String[] { o[j].getDefault() }) + (mode >= PageMaker.MODE_ADVANCED ? " ["+sc[i].getPrefix() + '.' + o[j].getName() + ']' : ""), + new String[]{ "configshortdesc", L10n.getString("ConfigToadlet.defaultIs", new String[] { "default" }, new String[] { o[j].getDefault() }) + (mode >= PageMaker.MODE_ADVANCED ? " ["+sc[i].getPrefix() + '.' + o[j].getName() + ']' : ""), "cursor: help;" }).addChild(L10n.getHTMLNode(o[j].getShortDesc())); HTMLNode configItemValueNode = configItemNode.addChild("span", "class", "config"); if(o[j].getValueString() == null){ Logger.error(this, sc[i].getPrefix() + configName + "has returned null from config!);"); - continue; + continue; } - if(o[j].getCallback() instanceof EnumerableOptionCallback) - configItemValueNode.addChild(addComboBox((EnumerableOptionCallback)o[j].getCallback(), sc[i], configName)); - else if(o[j].getCallback() instanceof BooleanCallback) - configItemValueNode.addChild(addBooleanComboBox(((BooleanOption)o[j]).getValue(), sc[i], configName)); + ConfigCallback<?> callback = o[j].getCallback(); + if(callback instanceof EnumerableOptionCallback) + configItemValueNode.addChild(addComboBox((EnumerableOptionCallback) callback, sc[i], + configName, callback.isReadOnly())); + else if(callback instanceof BooleanCallback) + configItemValueNode.addChild(addBooleanComboBox(((BooleanOption) o[j]).getValue(), sc[i], + configName, callback.isReadOnly())); + else if (callback.isReadOnly()) + configItemValueNode.addChild("input", // + new String[] { "type", "class", "disabled", "alt", "name", "value" }, // + new String[] { "text", "config", "disabled", o[j].getShortDesc(), + sc[i].getPrefix() + '.' + configName, o[j].getValueString() }); else - configItemValueNode.addChild("input", new String[] { "type", "class", "alt", "name", "value" }, new String[] { "text", "config", o[j].getShortDesc(), sc[i].getPrefix() + '.' + configName, o[j].getValueString() }); + configItemValueNode.addChild("input",// + new String[] { "type", "class", "alt", "name", "value" }, // + new String[] { "text", "config", o[j].getShortDesc(), + sc[i].getPrefix() + '.' + configName, o[j].getValueString() }); configItemNode.addChild("span", "class", "configlongdesc").addChild(L10n.getHTMLNode(o[j].getLongDesc())); } @@ -222,12 +324,20 @@ this.writeHTMLReply(ctx, 200, "OK", pageNode.generate()); } - public String supportedMethods() { + @Override + public String supportedMethods() { return "GET, POST"; } - private HTMLNode addComboBox(EnumerableOptionCallback o, SubConfig sc, String name) { - HTMLNode result = new HTMLNode("select", "name", sc.getPrefix() + '.' + name); + private HTMLNode addComboBox(EnumerableOptionCallback o, SubConfig sc, String name, boolean disabled) { + HTMLNode result; + if (disabled) + result = new HTMLNode("select", // + new String[] { "name", "disabled" }, // + new String[] { sc.getPrefix() + '.' + name, "disabled" }); + else + result = new HTMLNode("select", "name", sc.getPrefix() + '.' + name); + String[] possibleValues = o.getPossibleValues(); for(int i=0; i<possibleValues.length; i++) { if(possibleValues[i].equals(o.get())) @@ -239,17 +349,23 @@ return result; } - private HTMLNode addBooleanComboBox(boolean value, SubConfig sc, String name) { - HTMLNode result = new HTMLNode("select", "name", sc.getPrefix() + '.' + name); - - if(value) { - result.addChild("option", new String[] { "value", "selected" }, new String[] { - "true", "selected" }, l10n("true")); + private HTMLNode addBooleanComboBox(boolean value, SubConfig sc, String name, boolean disabled) { + HTMLNode result; + if (disabled) + result = new HTMLNode("select", // + new String[] { "name", "disabled" }, // + new String[] { sc.getPrefix() + '.' + name, "disabled" }); + else + result = new HTMLNode("select", "name", sc.getPrefix() + '.' + name); + + if (value) { + result.addChild("option", new String[] { "value", "selected" }, new String[] { "true", "selected" }, + l10n("true")); result.addChild("option", "value", "false", l10n("false")); } else { result.addChild("option", "value", "true", l10n("true")); - result.addChild("option", new String[] { "value", "selected" }, new String[] { - "false", "selected" }, l10n("false")); + result.addChild("option", new String[] { "value", "selected" }, new String[] { "false", "selected" }, + l10n("false")); } return result; Modified: branches/db4o/freenet/src/freenet/clients/http/ConnectionsToadlet.java =================================================================== --- branches/db4o/freenet/src/freenet/clients/http/ConnectionsToadlet.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/clients/http/ConnectionsToadlet.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -120,7 +120,8 @@ long total2 = secondNode.getTotalInputBytes()+secondNode.getTotalOutputBytes(); return compareLongs(total1, total2); }else if(sortBy.equals("selection_percentage")){ - return compareLongs(firstNode.getNumberOfSelections(), secondNode.getNumberOfSelections()); + long sinceWhen = System.currentTimeMillis() - PeerNode.SELECTION_SAMPLING_PERIOD; + return compareInts(firstNode.getNumberOfSelections().headSet(sinceWhen).size(), secondNode.getNumberOfSelections().headSet(sinceWhen).size()); }else if(sortBy.equals("time_delta")){ return compareLongs(firstNode.getClockDelta(), secondNode.getClockDelta()); }else if(sortBy.equals(("uptime"))){ @@ -418,9 +419,8 @@ } } - long numberOfSelectionSamples = peers.getNumberOfSelectionSamples(); - for (int peerIndex = 0, peerCount = peerNodeStatuses.length; peerIndex < peerCount; peerIndex++) { - + int numberOfSelectionSamples = peers.getNumberOfSelectionSamples().tailSet(now - PeerNode.SELECTION_SAMPLING_PERIOD).size(); + for (int peerIndex = 0, peerCount = peerNodeStatuses.length; peerIndex < peerCount; peerIndex++) { PeerNodeStatus peerNodeStatus = peerNodeStatuses[peerIndex]; drawRow(peerTable, peerNodeStatus, mode >= PageMaker.MODE_ADVANCED, fProxyJavascriptEnabled, now, path, enablePeerActions, endCols, drawMessageTypes, numberOfSelectionSamples); @@ -693,9 +693,11 @@ abstract protected SimpleFieldSet getNoderef(); - private void drawRow(HTMLNode peerTable, PeerNodeStatus peerNodeStatus, boolean advancedModeEnabled, boolean fProxyJavascriptEnabled, long now, String path, boolean enablePeerActions, SimpleColumn[] endCols, boolean drawMessageTypes, long numberOfSelectionSamples) { - HTMLNode peerRow = peerTable.addChild("tr"); - + private void drawRow(HTMLNode peerTable, PeerNodeStatus peerNodeStatus, boolean advancedModeEnabled, boolean fProxyJavascriptEnabled, long now, String path, boolean enablePeerActions, SimpleColumn[] endCols, boolean drawMessageTypes, int numberOfSelectionSamples) { + int peerSelectionCount = peerNodeStatus.getNumberOfSelections().tailSet(now - PeerNode.SELECTION_SAMPLING_PERIOD).size(); + int peerSelectionPercentage = (numberOfSelectionSamples > 0 ? (peerSelectionCount*100/numberOfSelectionSamples) : 0); + HTMLNode peerRow = peerTable.addChild("tr", "class", "darknet_connections_"+(peerSelectionPercentage > PeerNode.SELECTION_PERCENTAGE_WARNING ? "warning" : "normal")); + if(enablePeerActions) { // check box column peerRow.addChild("td", "class", "peer-marker").addChild("input", new String[] { "type", "name" }, new String[] { "checkbox", "node_" + peerNodeStatus.hashCode() }); @@ -775,7 +777,7 @@ // percent of time connected column peerRow.addChild("td", "class", "peer-idle" /* FIXME */).addChild("#", fix1.format(peerNodeStatus.getPercentTimeRoutableConnection())); // selection stats - peerRow.addChild("td", "class", "peer-idle" /* FIXME */).addChild("#", (numberOfSelectionSamples > 0 ? ((peerNodeStatus.getNumberOfSelections()*100/numberOfSelectionSamples)+"%") : "N/A")); + peerRow.addChild("td", "class", "peer-idle" /* FIXME */).addChild("#", (numberOfSelectionSamples > 0 ? (peerSelectionPercentage+"%") : "N/A")); // total traffic column peerRow.addChild("td", "class", "peer-idle" /* FIXME */).addChild("#", SizeUtil.formatSize(peerNodeStatus.getTotalInputBytes())+" / "+SizeUtil.formatSize(peerNodeStatus.getTotalOutputBytes())+"/"+SizeUtil.formatSize(peerNodeStatus.getResendBytesSent())); // congestion control Modified: branches/db4o/freenet/src/freenet/clients/http/FProxyToadlet.java =================================================================== --- branches/db4o/freenet/src/freenet/clients/http/FProxyToadlet.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/clients/http/FProxyToadlet.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -56,7 +56,7 @@ // ?force= links become invalid after 2 hours. private static final long FORCE_GRAIN_INTERVAL = 60*60*1000; /** Maximum size for transparent pass-through, should be a config option */ - static final long MAX_LENGTH = 2*1024*1024; // 2MB + static long MAX_LENGTH = 2*1024*1024; // 2MB static final URI welcome; static { @@ -95,6 +95,7 @@ return "GET"; } + @Override public void handlePost(URI uri, HTTPRequest req, ToadletContext ctx) throws ToadletContextClosedException, IOException, RedirectException { String ks = uri.getPath(); @@ -320,9 +321,10 @@ return false; } + @Override public void handleGet(URI uri, HTTPRequest httprequest, ToadletContext ctx) throws ToadletContextClosedException, IOException, RedirectException { - //String ks = uri.toString(); + String ks = uri.getPath(); boolean logMINOR = Logger.shouldLog(Logger.MINOR, this); @@ -446,7 +448,7 @@ String referer = sanitizeReferer(ctx); - handleDownload(ctx, data, ctx.getBucketFactory(), mimeType, requestedMimeType, httprequest.getParam("force", null), httprequest.isParameterSet("forcedownload"), "/", key, maxSize != MAX_LENGTH ? "&max-size="+maxSize : "", referer, true, ctx, core); + handleDownload(ctx, data, ctx.getBucketFactory(), mimeType, requestedMimeType, httprequest.getParam("force", null), httprequest.isParameterSet("forcedownload"), "/", key, maxSize != MAX_LENGTH ? "&max-size="+SizeUtil.formatSizeWithoutSpace(maxSize) : "", referer, true, ctx, core); } catch (FetchException e) { String msg = e.getMessage(); @@ -574,7 +576,7 @@ fileInformationList.addChild("li", l10n("sizeUnknown")); } if(mime != null) { - fileInformationList.addChild("li", L10n.getString("FProxyToadlet."+(finalized ? "mimeType" : "expectedMimeType"), new String[] { "mime" }, new String[] { mime }));; + fileInformationList.addChild("li", L10n.getString("FProxyToadlet."+(finalized ? "mimeType" : "expectedMimeType"), new String[] { "mime" }, new String[] { mime })); } else { fileInformationList.addChild("li", l10n("unknownMIMEType")); } @@ -667,9 +669,6 @@ WelcomeToadlet welcometoadlet = new WelcomeToadlet(client, core, node, bookmarks); server.register(welcometoadlet, "/welcome/", true, false); - PluginToadlet pluginToadlet = new PluginToadlet(client, node.pluginManager2, core); - server.register(pluginToadlet, "/plugin/", true, true); - ConfigToadlet configtoadlet = new ConfigToadlet(client, config, node, core); server.register(configtoadlet, "/config/", true, "FProxyToadlet.configTitle", "FProxyToadlet.config", true, null); Modified: branches/db4o/freenet/src/freenet/clients/http/FirstTimeWizardToadlet.java =================================================================== --- branches/db4o/freenet/src/freenet/clients/http/FirstTimeWizardToadlet.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/clients/http/FirstTimeWizardToadlet.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -10,11 +10,14 @@ import freenet.client.HighLevelSimpleClient; import freenet.config.Config; +import freenet.config.ConfigException; import freenet.config.InvalidConfigValueException; +import freenet.config.NodeNeedRestartException; import freenet.config.WrapperConfig; import freenet.l10n.L10n; import freenet.node.Node; import freenet.node.NodeClientCore; +import freenet.pluginmanager.FredPluginBandwidthIndicator; import freenet.support.Fields; import freenet.support.HTMLNode; import freenet.support.Logger; @@ -25,15 +28,23 @@ /** * A first time wizard aimed to ease the configuration of the node. * - * @author Florent Daignière <nextgens at freenetproject.org> - * - * TODO: a choose your CSS step ? + * TODO: a choose your CSS step? */ public class FirstTimeWizardToadlet extends Toadlet { private final NodeClientCore core; private final Config config; + private enum WIZARD_STEP { + WELCOME, + OPENNET, + NAME_SELECTION, + BANDWIDTH, + DATASTORE_SIZE, + MEMORY, + CONGRATZ; + } + FirstTimeWizardToadlet(HighLevelSimpleClient client, Node node, NodeClientCore core) { super(client); this.core = core; @@ -42,15 +53,16 @@ public static final String TOADLET_URL = "/wizard/"; + @Override public void handleGet(URI uri, HTTPRequest request, ToadletContext ctx) throws ToadletContextClosedException, IOException { if(!ctx.isAllowedFullAccess()) { super.sendErrorPage(ctx, 403, "Unauthorized", L10n.getString("Toadlet.unauthorized")); return; } - int currentStep = request.getIntParam("step"); + WIZARD_STEP currentStep = WIZARD_STEP.valueOf(request.getParam("step", WIZARD_STEP.WELCOME.toString())); - if(currentStep == 1) { + if(currentStep == WIZARD_STEP.OPENNET) { HTMLNode pageNode = ctx.getPageMaker().getPageNode(l10n("step1Title"), false, ctx); HTMLNode contentNode = ctx.getPageMaker().getContentNode(pageNode); @@ -66,14 +78,16 @@ opennetDiv.addChild("input", new String[] { "type", "name", "value" }, new String[] { "radio", "enableOpennet", "true" }, l10n("opennetYes")); opennetDiv.addChild("br"); opennetDiv.addChild("input", new String[] { "type", "name", "value" }, new String[] { "radio", "enableOpennet", "false" }, l10n("opennetNo")); - HTMLNode para = opennetForm.addChild("p"); - para.addChild("b", l10n("warningTitle")+' '); - L10n.addL10nSubstitution(para, "FirstTimeWizardToadlet.opennetWarning", new String[] { "bold", "/bold" }, new String[] { "<b>", "</b>" }); opennetForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "submit", "opennetF", L10n.getString("FirstTimeWizardToadlet.continue")}); opennetForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "submit", "cancel", L10n.getString("Toadlet.cancel")}); this.writeHTMLReply(ctx, 200, "OK", pageNode.generate()); return; - } else if(currentStep == 2) { + } else if(currentStep == WIZARD_STEP.NAME_SELECTION) { + // Attempt to skip one step if possible: opennet nodes don't need a name + if(Boolean.valueOf(request.getParam("opennet"))) { + super.writeTemporaryRedirect(ctx, "step3", TOADLET_URL+"?step="+WIZARD_STEP.BANDWIDTH); + return; + } HTMLNode pageNode = ctx.getPageMaker().getPageNode(l10n("step2Title"), false, ctx); HTMLNode contentNode = ctx.getPageMaker().getContentNode(pageNode); @@ -90,7 +104,12 @@ nnameForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "submit", "cancel", L10n.getString("Toadlet.cancel")}); this.writeHTMLReply(ctx, 200, "OK", pageNode.generate()); return; - } else if(currentStep == 3) { + } else if(currentStep == WIZARD_STEP.BANDWIDTH) { + // Attempt to skip one step if possible + if(canAutoconfigureBandwidth()){ + super.writeTemporaryRedirect(ctx, "step4", TOADLET_URL+"?step="+WIZARD_STEP.DATASTORE_SIZE); + return; + } HTMLNode pageNode = ctx.getPageMaker().getPageNode(l10n("step3Title"), false, ctx); HTMLNode contentNode = ctx.getPageMaker().getContentNode(pageNode); @@ -103,6 +122,7 @@ HTMLNode bandwidthForm = ctx.addFormChild(bandwidthInfoboxContent, ".", "bwForm"); HTMLNode result = bandwidthForm.addChild("select", "name", "bw"); + // don't forget to update handlePost too if you change that! result.addChild("option", "value", "8K", l10n("bwlimitLowerSpeed")); // Special case for 128kbps to increase performance at the cost of some link degradation. Above that we use 50% of the limit. result.addChild("option", "value", "12K", "512+/128 kbps"); @@ -115,7 +135,12 @@ bandwidthForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "submit", "cancel", L10n.getString("Toadlet.cancel")}); this.writeHTMLReply(ctx, 200, "OK", pageNode.generate()); return; - } else if(currentStep == 4) { + } else if(currentStep == WIZARD_STEP.DATASTORE_SIZE) { + // Attempt to skip one step if possible + if(canAutoconfigureDatastoreSize()) { + super.writeTemporaryRedirect(ctx, "step4", TOADLET_URL+"?step="+WIZARD_STEP.MEMORY); + return; + } HTMLNode pageNode = ctx.getPageMaker().getPageNode(l10n("step4Title"), false, ctx); HTMLNode contentNode = ctx.getPageMaker().getContentNode(pageNode); @@ -127,57 +152,7 @@ bandwidthInfoboxContent.addChild("#", l10n("datastoreSizeLong")); HTMLNode bandwidthForm = ctx.addFormChild(bandwidthInfoboxContent, ".", "dsForm"); HTMLNode result = bandwidthForm.addChild("select", "name", "ds"); - - // Use JNI to find out the free space on this partition. - long freeSpace = -1; - File dir = FileUtil.getCanonicalFile(core.node.getNodeDir()); - try { - Class c = dir.getClass(); - Method m = c.getDeclaredMethod("getFreeSpace", new Class[0]); - if(m != null) { - Long lFreeSpace = (Long) m.invoke(dir, new Object[0]); - if(lFreeSpace != null) { - freeSpace = lFreeSpace.longValue(); - System.err.println("Found free space on node's partition: "+freeSpace+" on "+dir+" = "+SizeUtil.formatSize(freeSpace)); - } - } - } catch (NoSuchMethodException e) { - // Ignore - freeSpace = -1; - } catch (Throwable t) { - System.err.println("Trying to access 1.6 getFreeSpace(), caught "+t); - freeSpace = -1; - } - - if(freeSpace <= 0) { - result.addChild("option", new String[] { "value", "selected" }, new String[] { "1G", "selected" }, "1GiB"); - } else { - if(freeSpace / 10 > 1024*1024*1024) { - // If 10GB+ free, default to 10% of available disk space. - String size = SizeUtil.formatSize(freeSpace/10); - String shortSize = SizeUtil.stripBytesEtc(size); - result.addChild("option", new String[] { "value", "selected" }, new String[] { shortSize, "selected" }, size+" "+l10n("tenPercentDisk")); - if(freeSpace / 20 > 1024*1024*1024) { - // If 20GB+ free, also offer 5% of available disk space. - size = SizeUtil.formatSize(freeSpace/20); - shortSize = SizeUtil.stripBytesEtc(size); - result.addChild("option", "value", shortSize, size+" "+l10n("fivePercentDisk")); - } - result.addChild("option", "value", "1G", "1GiB"); - } else if(freeSpace < 1024*1024*1024) { - // If less than 1GB free, default to 256MB and also offer 512MB. - result.addChild("option", new String[] { "value", "selected" }, new String[] { "256M", "selected" }, "256MiB"); - result.addChild("option", "value", "512M", "512MiB"); - } else if(freeSpace < 5*1024*1024*1024) { - // If less than 5GB free, default to 512MB - result.addChild("option", new String[] { "value", "selected" }, new String[] { "512M", "selected" }, "512MiB"); - result.addChild("option", "value", "1G", "1GiB"); - } else { - // If unknown, or 5-10GB free, default to 1GB. - result.addChild("option", new String[] { "value", "selected" }, new String[] { "1G", "selected" }, "1GiB"); - } - } result.addChild("option", "value", "2G", "2GiB"); result.addChild("option", "value", "3G", "3GiB"); result.addChild("option", "value", "5G", "5GiB"); @@ -191,7 +166,13 @@ bandwidthForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "submit", "cancel", L10n.getString("Toadlet.cancel")}); this.writeHTMLReply(ctx, 200, "OK", pageNode.generate()); return; - } else if(currentStep == 6) { + } else if(currentStep == WIZARD_STEP.MEMORY) { + // FIXME: Get rid of it when the db4o branch is merged or auto-detect it (be careful of classpath's bug @see <freenet.Node>) + // Attempt to skip one step if possible + if(!WrapperConfig.canChangeProperties()) { + super.writeTemporaryRedirect(ctx, "step6", TOADLET_URL+"?step="+WIZARD_STEP.CONGRATZ); + return; + } HTMLNode pageNode = ctx.getPageMaker().getPageNode(l10n("step6Title"), false, ctx); HTMLNode contentNode = ctx.getPageMaker().getContentNode(pageNode); @@ -215,7 +196,7 @@ this.writeHTMLReply(ctx, 200, "OK", pageNode.generate()); return; - }else if(currentStep == 7) { + }else if(currentStep == WIZARD_STEP.CONGRATZ) { HTMLNode pageNode = ctx.getPageMaker().getPageNode(l10n("step7Title"), true, ctx); HTMLNode contentNode = ctx.getPageMaker().getContentNode(pageNode); @@ -243,7 +224,7 @@ HTMLNode firstParagraph = welcomeInfoboxContent.addChild("p"); firstParagraph.addChild("#", l10n("welcomeInfoboxContent1")); HTMLNode secondParagraph = welcomeInfoboxContent.addChild("p"); - secondParagraph.addChild("a", "href", "?step=1").addChild("#", L10n.getString("FirstTimeWizardToadlet.clickContinue")); + secondParagraph.addChild("a", "href", "?step="+WIZARD_STEP.OPENNET).addChild("#", L10n.getString("FirstTimeWizardToadlet.clickContinue")); HTMLNode thirdParagraph = welcomeInfoboxContent.addChild("p"); thirdParagraph.addChild("a", "href", "/").addChild("#", l10n("skipWizard")); @@ -251,6 +232,7 @@ this.writeHTMLReply(ctx, 200, "OK", pageNode.generate()); } + @Override public void handlePost(URI uri, HTTPRequest request, ToadletContext ctx) throws ToadletContextClosedException, IOException { if(!ctx.isAllowedFullAccess()) { @@ -274,51 +256,39 @@ enable = Fields.stringToBool(isOpennetEnabled); } catch (NumberFormatException e) { Logger.error(this, "Invalid opennetEnabled: "+isOpennetEnabled, e); - super.writeTemporaryRedirect(ctx, "step1", TOADLET_URL+"?step=1"); + super.writeTemporaryRedirect(ctx, "step1", TOADLET_URL+"?step="+WIZARD_STEP.OPENNET); return; } try { config.get("node.opennet").set("enabled", enable); } catch (InvalidConfigValueException e) { - Logger.error(this, "Should not happen setting opennet.enabled="+enable+" please repot: "+e, e); - super.writeTemporaryRedirect(ctx, "step1", TOADLET_URL+"?step=1"); + Logger.error(this, "Should not happen setting opennet.enabled=" + enable + " please report: " + e, e); + super.writeTemporaryRedirect(ctx, "step1", TOADLET_URL+"?step="+WIZARD_STEP.OPENNET); return; + } catch (NodeNeedRestartException e) { + Logger.error(this, "Should not happen setting opennet.enabled=" + enable + " please report: " + e, e); + super.writeTemporaryRedirect(ctx, "step1", TOADLET_URL + "?step=" + WIZARD_STEP.OPENNET); + return; } - super.writeTemporaryRedirect(ctx, "step1", TOADLET_URL+"?step=2"); + super.writeTemporaryRedirect(ctx, "step1", TOADLET_URL+"?step="+WIZARD_STEP.NAME_SELECTION+"&opennet="+enable); return; } else if(request.isPartSet("nnameF")) { String selectedNName = request.getPartAsString("nname", 128); - try { config.get("node").set("name", selectedNName); Logger.normal(this, "The node name has been set to "+ selectedNName); - } catch (InvalidConfigValueException e) { + } catch (ConfigException e) { Logger.error(this, "Should not happen, please report!" + e, e); } - super.writeTemporaryRedirect(ctx, "step3", TOADLET_URL+"?step=3"); + super.writeTemporaryRedirect(ctx, "step3", TOADLET_URL+"?step="+WIZARD_STEP.BANDWIDTH); return; } else if(request.isPartSet("bwF")) { - String selectedUploadSpeed =request.getPartAsString("bw", 6); - - try { - config.get("node").set("outputBandwidthLimit", selectedUploadSpeed); - Logger.normal(this, "The outputBandwidthLimit has been set to "+ selectedUploadSpeed); - } catch (InvalidConfigValueException e) { - Logger.error(this, "Should not happen, please report!" + e, e); - } - super.writeTemporaryRedirect(ctx, "step4", TOADLET_URL+"?step=4"); + _setUpstreamBandwidthLimit(request.getPartAsString("bw", 6)); + super.writeTemporaryRedirect(ctx, "step4", TOADLET_URL+"?step="+WIZARD_STEP.DATASTORE_SIZE); return; } else if(request.isPartSet("dsF")) { - String selectedStoreSize =request.getPartAsString("ds", 6); - - try { - config.get("node").set("storeSize", selectedStoreSize); - Logger.normal(this, "The storeSize has been set to "+ selectedStoreSize); - } catch (InvalidConfigValueException e) { - Logger.error(this, "Should not happen, please report!" + e, e); - } - boolean canDoStepSix = WrapperConfig.canChangeProperties(); - super.writeTemporaryRedirect(ctx, "step5", TOADLET_URL+"?step="+(canDoStepSix?"6":"7")); + _setDatastoreSize(request.getPartAsString("ds", 6)); + super.writeTemporaryRedirect(ctx, "step5", TOADLET_URL+"?step="+WIZARD_STEP.MEMORY); return; } else if(request.isPartSet("memoryF")) { String selectedMemorySize = request.getPartAsString("memoryF", 6); @@ -327,7 +297,7 @@ if(memorySize >= 0) { WrapperConfig.setWrapperProperty("wrapper.java.maxmemory", selectedMemorySize); } - super.writeTemporaryRedirect(ctx, "step5", TOADLET_URL+"?step=7"); + super.writeTemporaryRedirect(ctx, "step6", TOADLET_URL+"?step="+WIZARD_STEP.CONGRATZ); return; } @@ -341,4 +311,99 @@ public String supportedMethods() { return "GET, POST"; } + + private void _setDatastoreSize(String selectedStoreSize) { + try { + config.get("node").set("storeSize", selectedStoreSize); + Logger.normal(this, "The storeSize has been set to " + selectedStoreSize); + } catch(ConfigException e) { + Logger.error(this, "Should not happen, please report!" + e, e); + } + } + + private void _setUpstreamBandwidthLimit(String selectedUploadSpeed) { + try { + config.get("node").set("outputBandwidthLimit", selectedUploadSpeed); + Logger.normal(this, "The outputBandwidthLimit has been set to " + selectedUploadSpeed); + } catch (ConfigException e) { + Logger.error(this, "Should not happen, please report!" + e, e); + } + } + + private void _setDownstreamBandwidthLimit(String selectedDownloadSpeed) { + try { + config.get("node").set("inputBandwidthLimit", selectedDownloadSpeed); + Logger.normal(this, "The inputBandwidthLimit has been set to " + selectedDownloadSpeed); + } catch(ConfigException e) { + Logger.error(this, "Should not happen, please report!" + e, e); + } + } + + private boolean canAutoconfigureBandwidth() { + FredPluginBandwidthIndicator bwIndicator = core.node.ipDetector.getBandwidthIndicator(); + if(bwIndicator == null) + return false; + + int downstreamBWLimit = bwIndicator.getDownstreamMaxBitRate(); + if(downstreamBWLimit > 0) { + int bytes = (downstreamBWLimit / 8) - 1; + String downstreamBWLimitString = SizeUtil.formatSize(bytes * 2 / 3); + _setDownstreamBandwidthLimit(downstreamBWLimitString); + Logger.normal(this, "The node has a bandwidthIndicator: it has reported downstream=" + downstreamBWLimit + "bits/sec... we will use " + downstreamBWLimitString + " and skip the bandwidth selection step of the wizard."); + } + + // We don't mind if the downstreamBWLimit couldn't be set, but upstreamBWLimit is important + int upstreamBWLimit = bwIndicator.getUpstramMaxBitRate(); + if(upstreamBWLimit > 0) { + int bytes = (upstreamBWLimit / 8) - 1; + String upstreamBWLimitString = (bytes < 16384 ? "8K" : SizeUtil.formatSize(bytes / 2)); + _setUpstreamBandwidthLimit(upstreamBWLimitString); + Logger.normal(this, "The node has a bandwidthIndicator: it has reported upstream=" + upstreamBWLimit + "bits/sec... we will use " + upstreamBWLimitString + " and skip the bandwidth selection step of the wizard."); + return true; + }else + return false; + } + + private boolean canAutoconfigureDatastoreSize() { + // Use JNI to find out the free space on this partition. + long freeSpace = -1; + File dir = FileUtil.getCanonicalFile(core.node.getNodeDir()); + try { + Class c = dir.getClass(); + Method m = c.getDeclaredMethod("getFreeSpace", new Class[0]); + if(m != null) { + Long lFreeSpace = (Long) m.invoke(dir, new Object[0]); + if(lFreeSpace != null) { + freeSpace = lFreeSpace.longValue(); + System.err.println("Found free space on node's partition: on " + dir + " = " + SizeUtil.formatSize(freeSpace)); + } + } + } catch(NoSuchMethodException e) { + // Ignore + freeSpace = -1; + } catch(Throwable t) { + System.err.println("Trying to access 1.6 getFreeSpace(), caught " + t); + freeSpace = -1; + } + + if(freeSpace <= 0) + return false; + else { + String shortSize = null; + if(freeSpace / 20 > 1024 * 1024 * 1024) { + // If 20GB+ free, 5% of available disk space. + shortSize = SizeUtil.formatSize(freeSpace / 20); + }else if(freeSpace / 10 > 1024 * 1024 * 1024) { + // If 10GB+ free, 10% of available disk space. + shortSize = SizeUtil.formatSize(freeSpace / 10); + }else if(freeSpace / 5 > 1024 * 1024 * 1024) { + // If 5GB+ free, default to 512MB + shortSize = "512MB"; + }else + shortSize = "256MB"; + + _setDatastoreSize(shortSize); + return true; + } + } } Modified: branches/db4o/freenet/src/freenet/clients/http/HTTPRequestImpl.java =================================================================== --- branches/db4o/freenet/src/freenet/clients/http/HTTPRequestImpl.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/clients/http/HTTPRequestImpl.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -3,6 +3,7 @@ * http://www.gnu.org/ for further details of the GPL. */ package freenet.clients.http; +import freenet.support.Fields; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; @@ -619,7 +620,7 @@ } String value = this.getParameterValue(name); try { - return Long.parseLong(value); + return Fields.parseLong(value); } catch (NumberFormatException e) { return defaultValue; } Modified: branches/db4o/freenet/src/freenet/clients/http/PageMaker.java =================================================================== --- branches/db4o/freenet/src/freenet/clients/http/PageMaker.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/clients/http/PageMaker.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -202,11 +202,11 @@ * * @return An {@link ArrayList} containing the names of all available themes */ - public List getThemes() { + public List<String> getThemes() { if (jarThemesCache != null) { return jarThemesCache; } - List themes = new ArrayList(); + List<String> themes = new ArrayList<String>(); try { URL url = getClass().getResource("staticfiles/themes/"); URLConnection urlConnection = url.openConnection(); Deleted: branches/db4o/freenet/src/freenet/clients/http/PluginToadlet.java =================================================================== --- branches/db4o/freenet/src/freenet/clients/http/PluginToadlet.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/clients/http/PluginToadlet.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -1,295 +0,0 @@ -/* This code is part of Freenet. It is distributed under the GNU General - * Public License, version 2 (or at your option any later version). See - * http://www.gnu.org/ for further details of the GPL. */ -package freenet.clients.http; - -import java.io.IOException; -import java.net.URI; - -import freenet.client.HighLevelSimpleClient; -import freenet.l10n.L10n; -import freenet.node.NodeClientCore; -import freenet.oldplugins.plugin.HttpPlugin; -import freenet.oldplugins.plugin.Plugin; -import freenet.oldplugins.plugin.PluginManager; -import freenet.support.HTMLNode; -import freenet.support.MultiValueTable; -import freenet.support.api.HTTPRequest; - -/** - * Toadlet for the plugin manager. - * - * @author David 'Bombe' Roden <bombe at freenetproject.org> - * @version $Id$ - */ -public class PluginToadlet extends Toadlet { - - private static final int MAX_PLUGIN_NAME_LENGTH = 1024; - /** The plugin manager backing this toadlet. */ - private final PluginManager pluginManager; - private final NodeClientCore core; - - /** - * Creates a new toadlet. - * - * @param client - * The high-level client to use - * @param pluginManager - * The plugin manager to use - */ - protected PluginToadlet(HighLevelSimpleClient client, PluginManager pluginManager, NodeClientCore core) { - super(client); - this.pluginManager = pluginManager; - this.core = core; - } - - /** - * This toadlet support GET and POST operations. - * - * @see freenet.clients.http.Toadlet#supportedMethods() - * @return "GET,POST" - */ - public String supportedMethods() { - return "GET,POST"; - } - - /** - * Handles a GET request. - * - * @see freenet.clients.http.Toadlet#handleGet(java.net.URI, - * freenet.clients.http.ToadletContext) - * @param uri - * The URI that was requested - * @param ctx - * The context of this toadlet - */ - public void handleGet(URI uri, HTTPRequest httpRequest, ToadletContext ctx) throws ToadletContextClosedException, IOException, RedirectException { - String uriPath = uri.getPath(); - String pluginName = uriPath.substring(uriPath.lastIndexOf('/') + 1); - - if (pluginName.length() > 0) { - Plugin plugin = findPlugin(pluginName); - if (plugin != null) { - if (plugin instanceof HttpPlugin) { - ((HttpPlugin) plugin).handleGet(httpRequest, ctx); - } else { - writeHTMLReply(ctx, 220, "OK", createBox(ctx, l10n("noWebInterfaceTitle"), l10n("noWebInterface")).toString()); - } - return; - } - writeHTMLReply(ctx, 220, "OK", createBox(ctx, l10n("pluginNotFoundTitle"), l10n("pluginNotFound")).toString()); - return; - } - - if(!ctx.isAllowedFullAccess()) { - super.sendErrorPage(ctx, 403, "Unauthorized", l10n("unauthorized")); - return; - } - - String action = httpRequest.getParam("action"); - if (action.length() == 0) { - writePermanentRedirect(ctx, "Plugin list", "?action=list"); - return; - } - - StringBuffer replyBuffer = new StringBuffer(); - if ("list".equals(action)) { - replyBuffer.append(listPlugins(ctx)); - } else { - writeHTMLReply(ctx, 220, "OK", createBox(ctx, l10n("unsupportedMethodTitle"), l10n("unsupportedMethod")).toString()); - return; - } - writeHTMLReply(ctx, 220, "OK", replyBuffer.toString()); - } - - private String l10n(String key) { - return L10n.getString("PluginToadlet."+key); - } - - /** - * @see freenet.clients.http.Toadlet#handlePost(java.net.URI, freenet.support.api.Bucket, freenet.clients.http.ToadletContext) - */ - public void handlePost(URI uri, HTTPRequest httpRequest, ToadletContext ctx) throws ToadletContextClosedException, IOException, RedirectException { - String uriPath = uri.getPath(); - String pluginName = uriPath.substring(uriPath.lastIndexOf('/') + 1); - - if (pluginName.length() > 0) { - Plugin plugin = findPlugin(pluginName); - if (plugin != null) { - if (plugin instanceof HttpPlugin) { - ((HttpPlugin) plugin).handlePost(httpRequest, ctx); - } else { - writeHTMLReply(ctx, 220, "OK", createBox(ctx, l10n("noWebInterfaceTitle"), l10n("noWebInterface")).toString()); - } - return; - } - writeHTMLReply(ctx, 220, "OK", createBox(ctx, l10n("pluginNotFoundTitle") , l10n("pluginNotFound")).toString()); - return; - } - - if(!ctx.isAllowedFullAccess()) { - super.sendErrorPage(ctx, 403, "Unauthorized", l10n("unauthorized")); - return; - } - - String pass = httpRequest.getPartAsString("formPassword", 32); - if((pass == null) || !pass.equals(core.formPassword)) { - MultiValueTable headers = new MultiValueTable(); - headers.put("Location", "/plugin/"); - ctx.sendReplyHeaders(302, "Found", headers, null, 0); - return; - } - - String action = httpRequest.getPartAsString("action", 32); - if (action.length() == 0) { - writePermanentRedirect(ctx, l10n("pluginList"), "?action=list"); - return; - } - - StringBuffer replyBuffer = new StringBuffer(); - if ("add".equals(action)) { - pluginName = httpRequest.getPartAsString("pluginName", MAX_PLUGIN_NAME_LENGTH); - - boolean added = false; - try { - pluginManager.addPlugin(pluginName, true); - added = true; - } catch (IllegalArgumentException iae1) { - super.sendErrorPage(ctx, l10n("failedToLoadPluginTitle"), l10n("failedToLoadPlugin"), iae1); - return; - } - if (added) { - writePermanentRedirect(ctx, l10n("pluginList"), "?action=list"); - return; - } - replyBuffer.append(createBox(ctx, l10n("failedToLoadPluginTitle"), l10n("failedToLoadPluginCheckClass"))); - } else if ("reload".equals(action)) { - pluginName = httpRequest.getPartAsString("pluginName", MAX_PLUGIN_NAME_LENGTH); - Plugin plugin = findPlugin(pluginName); - pluginManager.removePlugin(plugin, false); - pluginManager.addPlugin(plugin.getClass().getName(), false); - writePermanentRedirect(ctx, l10n("pluginList"), "?action=list"); - return; - } else if ("unload".equals(action)) { - pluginName = httpRequest.getPartAsString("pluginName", MAX_PLUGIN_NAME_LENGTH); - Plugin plugin = findPlugin(pluginName); - pluginManager.removePlugin(plugin, true); - writePermanentRedirect(ctx, l10n("pluginList"), "?action=list"); - return; - } - writeHTMLReply(ctx, 220, "OK", replyBuffer.toString()); - } - - /** - * Searches the currently installed plugins for the plugin with the - * specified internal name. - * - * @param internalPluginName - * The internal name of the wanted plugin - * @return The wanted plugin, or <code>null</code> if no plugin could be - * found - */ - private Plugin findPlugin(String internalPluginName) { - Plugin[] plugins = pluginManager.getPlugins(); - for (int pluginIndex = 0, pluginCount = plugins.length; pluginIndex < pluginCount; pluginIndex++) { - Plugin plugin = plugins[pluginIndex]; - String pluginName = plugin.getClass().getName() + '@' + pluginIndex; - if (pluginName.equals(internalPluginName)) { - return plugin; - } - } - return null; - } - - /** - * Creates a complete HTML page containing a list of all plugins. - * - * @param context - * The toadlet context - * @return A StringBuffer containing the HTML page - */ - private String listPlugins(ToadletContext context) { - Plugin[] plugins = pluginManager.getPlugins(); - PageMaker pageMaker = context.getPageMaker(); - HTMLNode pageNode = pageMaker.getPageNode( l10n("pluginListTitle"), context); - HTMLNode contentNode = pageMaker.getContentNode(pageNode); - - HTMLNode infobox = contentNode.addChild("div", "class", "infobox"); - infobox.addChild("div", "class", "infobox-header", l10n("pluginList")); - HTMLNode table = infobox.addChild("div", "class", "infobox-content").addChild("table", "class", "plugintable"); - HTMLNode headerRow = table.addChild("tr"); - headerRow.addChild("th", l10n("pluginNameTitle")); - headerRow.addChild("th", l10n("internalNameTitle")); - headerRow.addChild("th", "colspan", "3"); - for (int pluginIndex = 0, pluginCount = plugins.length; pluginIndex < pluginCount; pluginIndex++) { - Plugin plugin = plugins[pluginIndex]; - String internalName = plugin.getClass().getName() + '@' + pluginIndex; - HTMLNode tableRow = table.addChild("tr"); - tableRow.addChild("td", plugin.getPluginName()); - tableRow.addChild("td", internalName); - if (plugin instanceof HttpPlugin) { - tableRow.addChild("td").addChild("form", new String[] { "action", "method", "target" }, new String[] { internalName, "get", "_new" }).addChild("div").addChild("input", new String[] { "type", "value" }, new String[] { "submit", l10n("visit") }); - } else { - tableRow.addChild("td"); - } - HTMLNode reloadForm = context.addFormChild(tableRow, ".", "pluginReloadForm"); - reloadForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "hidden", "action", "reload" }); - reloadForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "hidden", "pluginName", internalName }); - reloadForm.addChild("input", new String[] { "type", "value" }, new String[] { "submit", "Reload" }); - HTMLNode unloadForm = context.addFormChild(tableRow, ".", "pluginUnloadForm"); - unloadForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "hidden", "action", "unload" }); - unloadForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "hidden", "pluginName", internalName }); - unloadForm.addChild("input", new String[] { "type", "value" }, new String[] { "submit", "Unload" }); - } - - contentNode.addChild(createAddPluginBox(context)); - - return pageNode.generate(); - } - - /** - * Creates an alert box with the specified title and message. A link to the - * plugin list is added after the message. - * - * @param context - * The toadlet context - * @param title - * The title of the box - * @param message - * The content of the box - * @return A StringBuffer containing the complete page - */ - private StringBuffer createBox(ToadletContext context, String title, String message) { - PageMaker pageMaker = context.getPageMaker(); - HTMLNode pageNode = pageMaker.getPageNode(title, context); - HTMLNode contentNode = pageMaker.getContentNode(pageNode); - HTMLNode infobox = contentNode.addChild("div", "class", "infobox infobox-alert"); - infobox.addChild("div", "class", "infobox-header", title); - HTMLNode infoboxContent = infobox.addChild("div", "class", "infobox-content"); - infoboxContent.addChild("#", message); - infoboxContent.addChild("br"); - L10n.addL10nSubstitution(infoboxContent, "PluginToadlet.returnToPluginsWithLinks", new String[] { "link", "/link" }, - new String[] { "<a href=\"?action=list\">", "</a>" }); - StringBuffer pageBuffer = new StringBuffer(); - pageNode.generate(pageBuffer); - return pageBuffer; - } - - /** - * Appends the HTML code for the “add plugin” box to the given - * StringBuffer. - * - * @param outputBuffer - * The StringBuffer to append the HTML code to - */ - private HTMLNode createAddPluginBox(ToadletContext ctx) { - HTMLNode addPluginBox = new HTMLNode("div", "class", "infobox"); - addPluginBox.addChild("div", "class", "infobox-header", l10n("addPluginTitle")); - HTMLNode addForm = ctx.addFormChild(addPluginBox.addChild("div", "class", "infobox-content"), ".", "addPluginBox"); - addForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "hidden", "action", "add" }); - addForm.addChild("input", new String[] { "type", "name", "value", "size" }, new String[] { "text", "pluginName", "", "40" }); - addForm.addChild("input", new String[] { "type", "value" }, new String[] { "submit", l10n("loadPluginCommand")}); - return addPluginBox; - } - -} Modified: branches/db4o/freenet/src/freenet/clients/http/QueueToadlet.java =================================================================== --- branches/db4o/freenet/src/freenet/clients/http/QueueToadlet.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/clients/http/QueueToadlet.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -296,7 +296,7 @@ else fnam = null; /* copy bucket data */ - Bucket copiedBucket = core.persistentEncryptedTempBucketFactory.makeBucket(file.getData().size()); + Bucket copiedBucket = core.persistentTempBucketFactory.makeBucket(file.getData().size()); BucketTools.copy(file.getData(), copiedBucket); final ClientPut clientPut; try { Modified: branches/db4o/freenet/src/freenet/clients/http/SimpleToadletServer.java =================================================================== --- branches/db4o/freenet/src/freenet/clients/http/SimpleToadletServer.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/clients/http/SimpleToadletServer.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -38,10 +38,10 @@ import freenet.support.HTMLNode; import freenet.support.Logger; import freenet.support.OOMHandler; -import freenet.support.StringArray; import freenet.support.api.BooleanCallback; import freenet.support.api.BucketFactory; import freenet.support.api.IntCallback; +import freenet.support.api.LongCallback; import freenet.support.api.StringCallback; import freenet.support.io.ArrayBucketFactory; @@ -80,12 +80,12 @@ static boolean isPanicButtonToBeShown; public static final int DEFAULT_FPROXY_PORT = 8888; - class FProxySSLCallback implements BooleanCallback { + class FProxySSLCallback extends BooleanCallback { - public boolean get() { + public Boolean get() { return ssl; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { if(val == get()) return; if(!SSL.available()) { throw new InvalidConfigValueException("Enable SSL support before use ssl with Fproxy"); @@ -93,22 +93,42 @@ ssl = val; throw new InvalidConfigValueException("Cannot change SSL on the fly, please restart freenet"); } + @Override + public boolean isReadOnly() { + return true; + } } + + class FProxyPassthruMaxSize extends LongCallback { + + public Long get() { + return FProxyToadlet.MAX_LENGTH; + } + + public void set(Long val) throws InvalidConfigValueException { + if(val == get()) return; + FProxyToadlet.MAX_LENGTH = val; + } + } - class FProxyPortCallback implements IntCallback { + class FProxyPortCallback extends IntCallback { - public int get() { + public Integer get() { return port; } - public void set(int newPort) throws InvalidConfigValueException { + public void set(Integer newPort) throws InvalidConfigValueException { if(port != newPort) throw new InvalidConfigValueException(L10n.getString("cannotChangePortOnTheFly")); // FIXME } + @Override + public boolean isReadOnly() { + return true; + } } - class FProxyBindtoCallback implements StringCallback { + class FProxyBindtoCallback extends StringCallback { public String get() { return bindTo; @@ -129,7 +149,7 @@ } } - class FProxyAllowedHostsCallback implements StringCallback { + class FProxyAllowedHostsCallback extends StringCallback { public String get() { return networkInterface.getAllowedHosts(); @@ -140,10 +160,9 @@ networkInterface.setAllowedHosts(allowedHosts); } } - } - class FProxyCSSNameCallback implements StringCallback, EnumerableOptionCallback { + class FProxyCSSNameCallback extends StringCallback implements EnumerableOptionCallback { public String get() { return cssName; @@ -161,11 +180,11 @@ } public String[] getPossibleValues() { - return StringArray.toArray(pageMaker.getThemes().toArray()); + return pageMaker.getThemes().toArray(new String[0]); } } - class FProxyCSSOverrideCallback implements StringCallback { + class FProxyCSSOverrideCallback extends StringCallback { public String get() { return (cssOverride == null ? "" : cssOverride.toString()); @@ -187,14 +206,14 @@ } } - class FProxyEnabledCallback implements BooleanCallback { + class FProxyEnabledCallback extends BooleanCallback { - public boolean get() { + public Boolean get() { synchronized(SimpleToadletServer.this) { return myThread != null; } } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { if(val == get()) return; synchronized(SimpleToadletServer.this) { if(val) { @@ -229,7 +248,7 @@ } } - private static class FProxyAdvancedModeEnabledCallback implements BooleanCallback { + private static class FProxyAdvancedModeEnabledCallback extends BooleanCallback { private final SimpleToadletServer ts; @@ -237,17 +256,17 @@ this.ts = ts; } - public boolean get() { + public Boolean get() { return ts.isAdvancedModeEnabled(); } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { if(val == get()) return; ts.enableAdvancedMode(val); } } - private static class FProxyJavascriptEnabledCallback implements BooleanCallback { + private static class FProxyJavascriptEnabledCallback extends BooleanCallback { private final SimpleToadletServer ts; @@ -255,11 +274,11 @@ this.ts = ts; } - public boolean get() { + public Boolean get() { return ts.isFProxyJavascriptEnabled(); } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { if(val == get()) return; ts.enableFProxyJavascript(val); } @@ -340,11 +359,11 @@ new FProxyJavascriptEnabledCallback(this)); fproxyConfig.register("showPanicButton", false, configItemOrder++, true, true, "SimpleToadletServer.panicButton", "SimpleToadletServer.panicButtonLong", new BooleanCallback(){ - public boolean get(){ + public Boolean get() { return SimpleToadletServer.isPanicButtonToBeShown; } - public void set(boolean value){ + public void set(Boolean value) { if(value == SimpleToadletServer.isPanicButtonToBeShown) return; else SimpleToadletServer.isPanicButtonToBeShown = value; } @@ -358,13 +377,13 @@ fproxyConfig.register("enablePersistentConnections", false, configItemOrder++, true, false, "SimpleToadletServer.enablePersistentConnections", "SimpleToadletServer.enablePersistentConnectionsLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { synchronized(SimpleToadletServer.this) { return enablePersistentConnections; } } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { synchronized(SimpleToadletServer.this) { enablePersistentConnections = val; } @@ -381,13 +400,13 @@ fproxyConfig.register("enableInlinePrefetch", false, configItemOrder++, true, false, "SimpleToadletServer.enableInlinePrefetch", "SimpleToadletServer.enableInlinePrefetchLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { synchronized(SimpleToadletServer.this) { return enableInlinePrefetch; } } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { synchronized(SimpleToadletServer.this) { enableInlinePrefetch = val; } @@ -395,6 +414,9 @@ }); enableInlinePrefetch = fproxyConfig.getBoolean("enableInlinePrefetch"); + fproxyConfig.register("passthroughMaxSize", 2L*1024*1024, configItemOrder++, true, false, "SimpleToadletServer.passthroughMaxSize", "SimpleToadletServer.passthroughMaxSizeLong", new FProxyPassthruMaxSize()); + FProxyToadlet.MAX_LENGTH = fproxyConfig.getLong("passthroughMaxSize"); + fproxyConfig.register("allowedHosts", "127.0.0.1,0:0:0:0:0:0:0:1", configItemOrder++, true, true, "SimpleToadletServer.allowedHosts", "SimpleToadletServer.allowedHostsLong", new FProxyAllowedHostsCallback()); fproxyConfig.register("allowedHostsFullAccess", "127.0.0.1,0:0:0:0:0:0:0:1", configItemOrder++, true, true, "SimpleToadletServer.allowedFullAccess", @@ -413,10 +435,10 @@ allowedFullAccess = new AllowedHosts(fproxyConfig.getString("allowedHostsFullAccess")); fproxyConfig.register("doRobots", false, configItemOrder++, true, false, "SimpleToadletServer.doRobots", "SimpleToadletServer.doRobotsLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { return doRobots; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { doRobots = val; } }); Modified: branches/db4o/freenet/src/freenet/clients/http/StatisticsToadlet.java =================================================================== --- branches/db4o/freenet/src/freenet/clients/http/StatisticsToadlet.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/clients/http/StatisticsToadlet.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -119,6 +119,7 @@ return count; } + @Override public void handleGet(URI uri, HTTPRequest request, ToadletContext ctx) throws ToadletContextClosedException, IOException, RedirectException { if(!ctx.isAllowedFullAccess()) { @@ -348,25 +349,15 @@ int[] outgoingLocalRequestCountArray = new int[1]; int[] outgoingLocalRequestLocation = stats.getOutgoingLocalRequestLocation(outgoingLocalRequestCountArray); int outgoingLocalRequestsCount = outgoingLocalRequestCountArray[0]; - - if(outgoingLocalRequestsCount > 0) { - HTMLNode nodeSpecialisationInfobox = nextTableCell.addChild("div", "class", "infobox"); - nodeSpecialisationInfobox.addChild("div", "class", "infobox-header", "Outgoing\u00a0Local\u00a0Request\u00a0Distribution"); - HTMLNode nodeSpecialisationTable = nodeSpecialisationInfobox.addChild("div", "class", "infobox-content").addChild("table"); - addSpecialisation(nodeSpecialisationTable, myLocation, outgoingLocalRequestsCount, outgoingLocalRequestLocation); - } - - overviewTableRow = overviewTable.addChild("tr"); - nextTableCell = overviewTableRow.addChild("td", "class", "first"); int[] outgoingRequestCountArray = new int[1]; int[] outgoingRequestLocation = stats.getOutgoingRequestLocation(outgoingRequestCountArray); int outgoingRequestsCount = outgoingRequestCountArray[0]; - if(outgoingRequestsCount > 0) { + if(outgoingLocalRequestsCount > 0 && outgoingRequestsCount > 0) { HTMLNode nodeSpecialisationInfobox = nextTableCell.addChild("div", "class", "infobox"); nodeSpecialisationInfobox.addChild("div", "class", "infobox-header", "Outgoing\u00a0Request\u00a0Distribution"); HTMLNode nodeSpecialisationTable = nodeSpecialisationInfobox.addChild("div", "class", "infobox-content").addChild("table"); - addSpecialisation(nodeSpecialisationTable, myLocation, outgoingRequestsCount, outgoingRequestLocation); + addCombinedSpecialisation(nodeSpecialisationTable, myLocation, outgoingLocalRequestsCount, outgoingLocalRequestLocation, outgoingRequestsCount, outgoingRequestLocation); } } @@ -680,13 +671,13 @@ locationSwapList.addChild("li", "locChangePerSwap:\u00a0" + fix1p6sci.format(locChangeSession/swaps)); } if ((swaps > 0.0) && (nodeUptimeSeconds >= 60)) { - locationSwapList.addChild("li", "locChangePerMinute:\u00a0" + fix1p6sci.format(locChangeSession/(double)(nodeUptimeSeconds/60.0))); + locationSwapList.addChild("li", "locChangePerMinute:\u00a0" + fix1p6sci.format(locChangeSession/(nodeUptimeSeconds/60.0))); } if ((swaps > 0.0) && (nodeUptimeSeconds >= 60)) { - locationSwapList.addChild("li", "swapsPerMinute:\u00a0" + fix1p6sci.format(swaps/(double)(nodeUptimeSeconds/60.0))); + locationSwapList.addChild("li", "swapsPerMinute:\u00a0" + fix1p6sci.format(swaps/(nodeUptimeSeconds/60.0))); } if ((noSwaps > 0.0) && (nodeUptimeSeconds >= 60)) { - locationSwapList.addChild("li", "noSwapsPerMinute:\u00a0" + fix1p6sci.format(noSwaps/(double)(nodeUptimeSeconds/60.0))); + locationSwapList.addChild("li", "noSwapsPerMinute:\u00a0" + fix1p6sci.format(noSwaps/(nodeUptimeSeconds/60.0))); } if ((swaps > 0.0) && (noSwaps > 0.0)) { locationSwapList.addChild("li", "swapsPerNoSwaps:\u00a0" + fix1p6sci.format(swaps/noSwaps)); @@ -1024,6 +1015,7 @@ overviewList.addChild("li", "backedOffPercent:\u00a0" + fix3p1pct.format(backedOffPercent)); overviewList.addChild("li", "pInstantReject:\u00a0" + fix3p1pct.format(stats.pRejectIncomingInstantly())); overviewList.addChild("li", "unclaimedFIFOSize:\u00a0" + node.getUnclaimedFIFOSize()); + overviewList.addChild("li", "RAMBucketPoolSize:\u00a0" + SizeUtil.formatSize(core.tempBucketFactory.getRamUsed())+ " / "+ SizeUtil.formatSize(core.tempBucketFactory.getMaxRamUsed())); overviewList.addChild("li", "uptimeAverage:\u00a0" + fix3p1pct.format(node.uptime.getUptime())); } @@ -1141,6 +1133,7 @@ strength = 1 - ((double) age / MAX_CIRCLE_AGE_THRESHOLD ); histogramIndex = (int) (Math.floor(location.doubleValue() * HISTOGRAM_LENGTH)); histogram[histogramIndex]++; + nodeCircleInfoboxContent.addChild("span", new String[] { "style", "class" }, new String[] { generatePeerCircleStyleString(location.doubleValue(), false, strength), "connected" }, "x"); } nodeCircleInfoboxContent.addChild("span", new String[] { "style", "class" }, new String[] { generatePeerCircleStyleString(myLocation, true, 1.0), "me" }, "x"); @@ -1150,9 +1143,10 @@ nodeHistogramLegendCell = nodeHistogramLegendTableRow.addChild("td"); nodeHistogramGraphCell = nodeHistogramGraphTableRow.addChild("td", "style", "height: 100px;"); nodeHistogramLegendCell.addChild("div", "class", "histogramLabel").addChild("#", fix1p1.format(((double) i) / HISTOGRAM_LENGTH )); - // histogramPercent = ((double) histogram[ i ] ) / nodeCount; - nodeHistogramGraphCell.addChild("div", new String[] { "class", "style" }, new String[] { "histogramConnected", "height: " + fix3pctUS.format(histogramPercent) + "; width: 100%;" }, "\u00a0"); + + // Don't use HTMLNode here to speed things up + nodeHistogramGraphCell.addChild("%", "<div class=\"histogramConnected\" style=\"height: " + fix3pctUS.format(histogramPercent) + "; width: 100%;\">\u00a0</div>"); } } @@ -1169,8 +1163,34 @@ nodeHistogramGraphCell2.addChild("#", fix1p1.format(((double) i) / incomingRequestLocation.length )); nodeHistogramGraphCell.addChild("div", new String[] { "class", "style" }, new String[] { "histogramConnected", "height: " + fix3pctUS.format(((double)incomingRequestLocation[i]) / incomingRequestsCount) + "; width: 100%;" }, "\u00a0"); } - } + + private void addCombinedSpecialisation(HTMLNode table, double peerLocation, int locallyOriginatingRequestsCount, int[] locallyOriginatingRequests, int remotelyOriginatingRequestsCount, int[] remotelyOriginatingRequests) { + assert(locallyOriginatingRequests.length == remotelyOriginatingRequests.length); + HTMLNode nodeHistogramLegendTableRow = table.addChild("tr"); + HTMLNode nodeHistogramGraphTableRow = table.addChild("tr"); + int myIndex = (int)(peerLocation * locallyOriginatingRequests.length); + for (int i = 0; i<locallyOriginatingRequests.length; i++) { + HTMLNode nodeHistogramLegendCell = nodeHistogramLegendTableRow.addChild("td"); + HTMLNode nodeHistogramGraphCell = nodeHistogramGraphTableRow.addChild("td", "style", "height: 100px;"); + HTMLNode nodeHistogramGraphCell2 = nodeHistogramLegendCell.addChild("div", "class", "histogramLabel"); + if(i == myIndex) + nodeHistogramGraphCell2 = nodeHistogramGraphCell2.addChild("span", "class", "me"); + nodeHistogramGraphCell2.addChild("#", fix1p1.format(((double) i) / locallyOriginatingRequests.length )); + nodeHistogramGraphCell.addChild("div", + new String[] { "class", "style" }, + new String[] { "histogramConnected", "height: " + + fix3pctUS.format(((double)locallyOriginatingRequests[i]) / locallyOriginatingRequestsCount) + + "; width: 100%;" }, + "\u00a0"); + nodeHistogramGraphCell.addChild("div", + new String[] { "class", "style" }, + new String[] { "histogramDisconnected", "height: " + + fix3pctUS.format(((double)remotelyOriginatingRequests[i]) / remotelyOriginatingRequestsCount) + + "; width: 100%;" }, + "\u00a0"); + } + } private void addPeerCircle (HTMLNode circleTable, PeerNodeStatus[] peerNodeStatuses, double myLocation) { int[] histogramConnected = new int[HISTOGRAM_LENGTH]; Modified: branches/db4o/freenet/src/freenet/clients/http/SymlinkerToadlet.java =================================================================== --- branches/db4o/freenet/src/freenet/clients/http/SymlinkerToadlet.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/clients/http/SymlinkerToadlet.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -35,6 +35,10 @@ // FIXME throw new InvalidConfigValueException("Cannot set the plugins that's loaded."); } + + public boolean isReadOnly() { + return true; + } }); String fns[] = tslconfig.getStringArr("symlinks"); Modified: branches/db4o/freenet/src/freenet/clients/http/Toadlet.java =================================================================== --- branches/db4o/freenet/src/freenet/clients/http/Toadlet.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/clients/http/Toadlet.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -83,7 +83,7 @@ MultiValueTable hdrtbl = new MultiValueTable(); hdrtbl.put("Allow", this.supportedMethods()); - StringBuffer pageBuffer = new StringBuffer(); + StringBuilder pageBuffer = new StringBuilder(); pageNode.generate(pageBuffer); toadletContext.sendReplyHeaders(405, "Operation not Supported", hdrtbl, "text/html; charset=utf-8", pageBuffer.length()); toadletContext.writeData(pageBuffer.toString().getBytes("UTF-8")); Modified: branches/db4o/freenet/src/freenet/clients/http/bookmark/BookmarkCategory.java =================================================================== --- branches/db4o/freenet/src/freenet/clients/http/bookmark/BookmarkCategory.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/clients/http/bookmark/BookmarkCategory.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -4,8 +4,6 @@ import freenet.support.SimpleFieldSet; import java.util.Vector; -import freenet.support.StringArray; - public class BookmarkCategory extends Bookmark { public static final String NAME = "BookmarkCategory"; @@ -112,13 +110,13 @@ } public String[] toStrings() { - return StringArray.toArray(toStrings("").toArray()); + return toStrings("").toArray(new String[0]); } // Iternal use only - private Vector toStrings(String prefix) { - Vector strings = new Vector(); + private Vector<String> toStrings(String prefix) { + Vector<String> strings = new Vector<String>(); BookmarkItems items = getItems(); BookmarkCategories subCategories = getSubCategories(); prefix += this.name + "/"; Modified: branches/db4o/freenet/src/freenet/clients/http/staticfiles/defaultbookmarks.dat =================================================================== --- branches/db4o/freenet/src/freenet/clients/http/staticfiles/defaultbookmarks.dat 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/clients/http/staticfiles/defaultbookmarks.dat 2008-09-24 20:42:20 UTC (rev 22823) @@ -7,19 +7,19 @@ BookmarkCategory0.Content.Bookmark0.Name=The Ultimate FreeNet Index BookmarkCategory0.Content.Bookmark0.Description=A new one-page index with a menu including categories BookmarkCategory0.Content.Bookmark0.hasAnActivelink=true -BookmarkCategory0.Content.Bookmark0.URI=USK at 0I8gctpUE32CM0iQhXaYpCMvtPPGfT4pjXm01oid5Zc,3dAcn4fX2LyxO6uCnWFTx-2HKZ89uruurcKwLSCxbZ4,AQACAAE/Ultimate-Freenet-Index/25/ +BookmarkCategory0.Content.Bookmark0.URI=USK at 0I8gctpUE32CM0iQhXaYpCMvtPPGfT4pjXm01oid5Zc,3dAcn4fX2LyxO6uCnWFTx-2HKZ89uruurcKwLSCxbZ4,AQACAAE/Ultimate-Freenet-Index/28/ BookmarkCategory0.Content.Bookmark3.Name=Index des sites Fran?ais BookmarkCategory0.Content.Bookmark3.Description=A small French index with descriptions BookmarkCategory0.Content.Bookmark3.hasAnActivelink=true -BookmarkCategory0.Content.Bookmark3.URI=USK at RJnh1EnvOSPwOWVRS2nyhC4eIQkKoNE5hcTv7~yY-sM,pOloLxnKWM~AL24iDMHOAvTvCqMlB-p2BO9zK96TOZA,AQACAAE/index_fr/54/ +BookmarkCategory0.Content.Bookmark3.URI=USK at RJnh1EnvOSPwOWVRS2nyhC4eIQkKoNE5hcTv7~yY-sM,pOloLxnKWM~AL24iDMHOAvTvCqMlB-p2BO9zK96TOZA,AQACAAE/index_fr/61/ BookmarkCategory0.Content.Bookmark2.Name=Freenet Activelink Index (SLOW: graphical index, preloads all the sites, so takes *ages* to load) BookmarkCategory0.Content.Bookmark2.hasAnActivelink=true BookmarkCategory0.Content.Bookmark2.Description=A graphical freenet index (this will take a long time to load as it preloads the sites) -BookmarkCategory0.Content.Bookmark2.URI=USK at qd-hk0vHYg7YvK2BQsJMcUD5QSF0tDkgnnF6lnWUH0g,xTFOV9ddCQQk6vQ6G~jfL6IzRUgmfMcZJ6nuySu~NUc,AQACAAE/activelink-index/67/ +BookmarkCategory0.Content.Bookmark2.URI=USK at qd-hk0vHYg7YvK2BQsJMcUD5QSF0tDkgnnF6lnWUH0g,xTFOV9ddCQQk6vQ6G~jfL6IzRUgmfMcZJ6nuySu~NUc,AQACAAE/activelink-index/78/ BookmarkCategory0.Content.Bookmark1.Name=Freenet Activelink Index Text Version (a quick-loading non-graphical index site, no porn) BookmarkCategory0.Content.Bookmark1.hasAnActivelink=true BookmarkCategory0.Content.Bookmark1.Description=Text version of the Activelink Index -BookmarkCategory0.Content.Bookmark1.URI=USK at qd-hk0vHYg7YvK2BQsJMcUD5QSF0tDkgnnF6lnWUH0g,xTFOV9ddCQQk6vQ6G~jfL6IzRUgmfMcZJ6nuySu~NUc,AQACAAE/activelink-index-text/30/ +BookmarkCategory0.Content.Bookmark1.URI=USK at qd-hk0vHYg7YvK2BQsJMcUD5QSF0tDkgnnF6lnWUH0g,xTFOV9ddCQQk6vQ6G~jfL6IzRUgmfMcZJ6nuySu~NUc,AQACAAE/activelink-index-text/39/ BookmarkCategory1.Name=Freenet devel's flogs BookmarkCategory1.Content.BookmarkCategory=0 BookmarkCategory1.Content.Bookmark=5 @@ -34,7 +34,7 @@ BookmarkCategory1.Content.Bookmark2.Name=Bombe BookmarkCategory1.Content.Bookmark2.Description=Bombe's flog BookmarkCategory1.Content.Bookmark2.hasAnActivelink=true -BookmarkCategory1.Content.Bookmark2.URI=USK at e3myoFyp5avg6WYN16ImHri6J7Nj8980Fm~aQe4EX1U,QvbWT0ImE0TwLODTl7EoJx2NBnwDxTbLTE6zkB-eGPs,AQACAAE/bombe/41/ +BookmarkCategory1.Content.Bookmark2.URI=USK at e3myoFyp5avg6WYN16ImHri6J7Nj8980Fm~aQe4EX1U,QvbWT0ImE0TwLODTl7EoJx2NBnwDxTbLTE6zkB-eGPs,AQACAAE/bombe/42/ BookmarkCategory1.Content.Bookmark1.Name=Nextgen$ BookmarkCategory1.Content.Bookmark1.Description=NextGen$' flog BookmarkCategory1.Content.Bookmark1.hasAnActivelink=true @@ -49,7 +49,7 @@ BookmarkCategory2.Content.Bookmark0.Name=Freenet Message System BookmarkCategory2.Content.Bookmark0.Description=The official freesite of FMS, a spam resistant message board system for Freenet BookmarkCategory2.Content.Bookmark0.hasAnActivelink=true -BookmarkCategory2.Content.Bookmark0.URI=USK at 0npnMrqZNKRCRoGojZV93UNHCMN-6UU3rRSAmP6jNLE,~BG-edFtdCC1cSH4O3BWdeIYa8Sw5DfyrSV-TKdO5ec,AQACAAE/fms/62/ +BookmarkCategory2.Content.Bookmark0.URI=USK at 0npnMrqZNKRCRoGojZV93UNHCMN-6UU3rRSAmP6jNLE,~BG-edFtdCC1cSH4O3BWdeIYa8Sw5DfyrSV-TKdO5ec,AQACAAE/fms/78/ BookmarkCategory2.Content.Bookmark1.Name=Freemail BookmarkCategory2.Content.Bookmark1.Description=The official site for Freemail - email over Freenet BookmarkCategory2.Content.Bookmark1.hasAnActivelink=true Modified: branches/db4o/freenet/src/freenet/clients/http/staticfiles/themes/clean/theme.css =================================================================== --- branches/db4o/freenet/src/freenet/clients/http/staticfiles/themes/clean/theme.css 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/clients/http/staticfiles/themes/clean/theme.css 2008-09-24 20:42:20 UTC (rev 22823) @@ -378,6 +378,10 @@ text-align: center; } +tr.darknet_connections_warning { + background-color: #ffff00; +} + table.sentmessagetypes { display: inline; } Modified: branches/db4o/freenet/src/freenet/config/BooleanOption.java =================================================================== --- branches/db4o/freenet/src/freenet/config/BooleanOption.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/config/BooleanOption.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -6,65 +6,25 @@ import freenet.l10n.L10n; import freenet.support.api.BooleanCallback; -public class BooleanOption extends Option { - - final boolean defaultValue; - final BooleanCallback cb; - private boolean currentValue; - +public class BooleanOption extends Option<Boolean> { public BooleanOption(SubConfig conf, String optionName, boolean defaultValue, int sortOrder, boolean expert, boolean forceWrite, String shortDesc, String longDesc, BooleanCallback cb) { - super(conf, optionName, cb, sortOrder, expert, forceWrite, shortDesc, longDesc, Option.DATA_TYPE_BOOLEAN); + super(conf, optionName, cb, sortOrder, expert, forceWrite, shortDesc, longDesc, Option.DataType.BOOLEAN); this.defaultValue = defaultValue; - this.cb = cb; this.currentValue = defaultValue; } - /** Get the current value. This is the value in use if we have finished - * initialization, otherwise it is the value set at startup (possibly the default). */ - public boolean getValue() { - if(config.hasFinishedInitialization()) - return currentValue = cb.get(); - else return currentValue; - } - - public void setValue(String val) throws InvalidConfigValueException { + public Boolean parseString(String val) throws InvalidConfigValueException { if(val.equalsIgnoreCase("true") || val.equalsIgnoreCase("yes")) { - set(true); + return true; } else if(val.equalsIgnoreCase("false") || val.equalsIgnoreCase("no")) { - set(false); + return false; } else throw new OptionFormatException(L10n.getString("BooleanOption.parseError", "val", val)); } - - public void set(boolean b) throws InvalidConfigValueException { - cb.set(b); - currentValue = b; - } - - public String getValueString() { - return Boolean.toString(getValue()); - } - public void setInitialValue(String val) throws InvalidConfigValueException { - if(val.equalsIgnoreCase("true") || val.equalsIgnoreCase("yes")) { - currentValue = true; - } else if(val.equalsIgnoreCase("false") || val.equalsIgnoreCase("no")) { - currentValue = false; - } else - throw new OptionFormatException(L10n.getString("BooleanOption.parseError", "val", val)); + @Override + protected String toString(Boolean val) { + return val.toString(); } - - public boolean isDefault() { - getValue(); - return currentValue == defaultValue; - } - - public String getDefault() { - return Boolean.toString(defaultValue); - } - - public void setDefault() { - currentValue = defaultValue; - } } Modified: branches/db4o/freenet/src/freenet/config/Config.java =================================================================== --- branches/db4o/freenet/src/freenet/config/Config.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/config/Config.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -3,26 +3,21 @@ * http://www.gnu.org/ for further details of the GPL. */ package freenet.config; +import java.io.IOException; import java.util.LinkedHashMap; /** Global configuration object for a node. SubConfig's register here. * Handles writing to a file etc. */ public class Config { + public static enum RequestType { + CURRENT_SETTINGS, DEFAULT_SETTINGS, SORT_ORDER, EXPERT_FLAG, FORCE_WRITE_FLAG, SHORT_DESCRIPTION, LONG_DESCRIPTION, DATA_TYPE + }; - public static final int CONFIG_REQUEST_TYPE_CURRENT_SETTINGS = 1; - public static final int CONFIG_REQUEST_TYPE_DEFAULT_SETTINGS = 2; - public static final int CONFIG_REQUEST_TYPE_SORT_ORDER = 3; - public static final int CONFIG_REQUEST_TYPE_EXPERT_FLAG = 4; - public static final int CONFIG_REQUEST_TYPE_FORCE_WRITE_FLAG = 5; - public static final int CONFIG_REQUEST_TYPE_SHORT_DESCRIPTION = 6; - public static final int CONFIG_REQUEST_TYPE_LONG_DESCRIPTION = 7; - public static final int CONFIG_REQUEST_TYPE_DATA_TYPE = 8; - - protected final LinkedHashMap configsByPrefix; + protected final LinkedHashMap<String, SubConfig> configsByPrefix; public Config() { - configsByPrefix = new LinkedHashMap(); + configsByPrefix = new LinkedHashMap<String, SubConfig>(); } public void register(SubConfig sc) { @@ -50,10 +45,10 @@ /** Fetch all the SubConfig's. Used by user-facing config thingies. */ public synchronized SubConfig[] getConfigs() { - return (SubConfig[]) configsByPrefix.values().toArray(new SubConfig[configsByPrefix.size()]); + return configsByPrefix.values().toArray(new SubConfig[configsByPrefix.size()]); } public synchronized SubConfig get(String subConfig){ - return (SubConfig)configsByPrefix.get(subConfig); + return configsByPrefix.get(subConfig); } } Modified: branches/db4o/freenet/src/freenet/config/ConfigCallback.java =================================================================== --- branches/db4o/freenet/src/freenet/config/ConfigCallback.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/config/ConfigCallback.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -3,6 +3,23 @@ * http://www.gnu.org/ for further details of the GPL. */ package freenet.config; -public interface ConfigCallback { - /** Nothing usefull here */ +public abstract class ConfigCallback<T> { + /** + * Get the current, used value of the config variable. + */ + public abstract T get(); + + /** + * Set the config variable to a new value. + * + * @param val + * The new value. + * @throws InvalidConfigOptionException + * If the new value is invalid for this particular option. + */ + public abstract void set(T val) throws InvalidConfigValueException, NodeNeedRestartException; + + public boolean isReadOnly() { + return false; + } } Copied: branches/db4o/freenet/src/freenet/config/ConfigException.java (from rev 21939, trunk/freenet/src/freenet/config/ConfigException.java) =================================================================== --- branches/db4o/freenet/src/freenet/config/ConfigException.java (rev 0) +++ branches/db4o/freenet/src/freenet/config/ConfigException.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -0,0 +1,15 @@ +/* This code is part of Freenet. It is distributed under the GNU General + * Public License, version 2 (or at your option any later version). See + * http://www.gnu.org/ for further details of the GPL. */ +package freenet.config; + +/** + * Usefull if you want to catch all exceptions the config framework can return; + */ +public abstract class ConfigException extends Exception { + private static final long serialVersionUID = -1; + + public ConfigException(String msg) { + super(msg); + } +} \ No newline at end of file Modified: branches/db4o/freenet/src/freenet/config/IntOption.java =================================================================== --- branches/db4o/freenet/src/freenet/config/IntOption.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/config/IntOption.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -8,89 +8,37 @@ import freenet.support.api.IntCallback; /** Integer config variable */ -public class IntOption extends Option { - - final int defaultValue; - final IntCallback cb; - private int currentValue; - // Cache it mostly so that we can keep SI units - private String cachedStringValue; +public class IntOption extends Option<Integer> { + public IntOption(SubConfig conf, String optionName, String defaultValueString, int sortOrder, boolean expert, + boolean forceWrite, String shortDesc, String longDesc, IntCallback cb) { + this(conf, optionName, Fields.parseInt(defaultValueString), sortOrder, expert, forceWrite, shortDesc, longDesc, + cb); + } - public IntOption(SubConfig conf, String optionName, int defaultValue, String defaultValueString, - int sortOrder, boolean expert, boolean forceWrite, String shortDesc, String longDesc, IntCallback cb) { - super(conf, optionName, cb, sortOrder, expert, forceWrite, shortDesc, longDesc, Option.DATA_TYPE_NUMBER); + public IntOption(SubConfig conf, String optionName, Integer defaultValue, int sortOrder, boolean expert, + boolean forceWrite, String shortDesc, String longDesc, IntCallback cb) { + super(conf, optionName, cb, sortOrder, expert, forceWrite, shortDesc, longDesc, Option.DataType.NUMBER); this.defaultValue = defaultValue; - this.cb = cb; this.currentValue = defaultValue; - this.cachedStringValue = defaultValueString; } - public IntOption(SubConfig conf, String optionName, String defaultValueString, - int sortOrder, boolean expert, boolean forceWrite, String shortDesc, String longDesc, IntCallback cb) { - super(conf, optionName, cb, sortOrder, expert, forceWrite, shortDesc, longDesc, Option.DATA_TYPE_NUMBER); - this.defaultValue = Fields.parseSIInt(defaultValueString); - this.cb = cb; - this.currentValue = defaultValue; - this.cachedStringValue = defaultValueString; - } - - /** Get the current value. This is the value in use if we have finished - * initialization, otherwise it is the value set at startup (possibly the default). */ - public int getValue() { - if(config.hasFinishedInitialization()) { - int val = cb.get(); - if(currentValue != val) { - currentValue = val; - cachedStringValue = null; - } - } - return currentValue; - } - - public void setValue(String val) throws InvalidConfigValueException { - int x; - try{ - x = Fields.parseSIInt(val); + @Override + protected Integer parseString(String val) throws InvalidConfigValueException { + Integer x; + try { + x = Fields.parseInt(val); } catch (NumberFormatException e) { throw new InvalidConfigValueException(l10n("parseError", "val", val)); } - cb.set(x); - cachedStringValue = val; - currentValue = x; + return x; } - - public void setInitialValue(String val) throws InvalidConfigValueException { - int x; - try{ - x = Fields.parseSIInt(val); - } catch (NumberFormatException e) { - throw new InvalidConfigValueException(l10n("parseError", "val", val)); - } - cachedStringValue = val; - currentValue = x; - } private String l10n(String key, String pattern, String value) { - return L10n.getString("IntOption."+key, pattern, value); + return L10n.getString("IntOption." + key, pattern, value); } - public String getValueString() { - int val = getValue(); - if(cachedStringValue != null) return cachedStringValue; - return Integer.toString(val); + @Override + protected String toString(Integer val) { + return Fields.intToString(val); } - - public String getDefault(){ - return Integer.toString(defaultValue); - } - - public boolean isDefault() { - getValue(); - return currentValue == defaultValue; - } - - public void setDefault() { - currentValue = defaultValue; - } - } Modified: branches/db4o/freenet/src/freenet/config/InvalidConfigValueException.java =================================================================== --- branches/db4o/freenet/src/freenet/config/InvalidConfigValueException.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/config/InvalidConfigValueException.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -10,11 +10,9 @@ * it merely means that there are no immediately detectable problems with * it. */ -public class InvalidConfigValueException extends Exception { - private static final long serialVersionUID = -1; +public class InvalidConfigValueException extends ConfigException { public InvalidConfigValueException(String msg) { super(msg); } - } Modified: branches/db4o/freenet/src/freenet/config/LongOption.java =================================================================== --- branches/db4o/freenet/src/freenet/config/LongOption.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/config/LongOption.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -8,91 +8,37 @@ import freenet.support.api.LongCallback; /** Long config variable */ -public class LongOption extends Option { - - final long defaultValue; - final LongCallback cb; - private long currentValue; - // Cache it mostly so that we can keep SI units - private String cachedStringValue; - - public LongOption(SubConfig conf, String optionName, long defaultValue, String defaultValueString, - int sortOrder, boolean expert, boolean forceWrite, String shortDesc, String longDesc, LongCallback cb) { - super(conf, optionName, cb, sortOrder, expert, forceWrite, shortDesc, longDesc, Option.DATA_TYPE_NUMBER); - this.defaultValue = defaultValue; - this.cb = cb; - this.currentValue = defaultValue; - this.cachedStringValue = defaultValueString; +public class LongOption extends Option<Long> { + public LongOption(SubConfig conf, String optionName, String defaultValueString, int sortOrder, boolean expert, + boolean forceWrite, String shortDesc, String longDesc, LongCallback cb) { + this(conf, optionName, Fields.parseLong(defaultValueString), sortOrder, expert, forceWrite, shortDesc, + longDesc, cb); } - public LongOption(SubConfig conf, String optionName, String defaultValueString, - int sortOrder, boolean expert, boolean forceWrite, String shortDesc, String longDesc, LongCallback cb) { - super(conf, optionName, cb, sortOrder, expert, forceWrite, shortDesc, longDesc, Option.DATA_TYPE_NUMBER); - this.defaultValue = Fields.parseSILong(defaultValueString); - this.cb = cb; + public LongOption(SubConfig conf, String optionName, Long defaultValue, int sortOrder, boolean expert, + boolean forceWrite, String shortDesc, String longDesc, LongCallback cb) { + super(conf, optionName, cb, sortOrder, expert, forceWrite, shortDesc, longDesc, Option.DataType.NUMBER); + this.defaultValue = defaultValue; this.currentValue = defaultValue; - this.cachedStringValue = defaultValueString; } - - /** Get the current value. This is the value in use if we have finished - * initialization, otherwise it is the value set at startup (possibly the default). */ - public long getValue() { - if(config.hasFinishedInitialization()) { - long val = cb.get(); - if(currentValue != val) { - currentValue = val; - cachedStringValue = null; - } - } - return currentValue; - } - - public void setValue(String val) throws InvalidConfigValueException { - long x; - try{ - x = Fields.parseSILong(val); - }catch (NumberFormatException e) { - throw new InvalidConfigValueException(l10n("parseError", "val", val)); - } - cb.set(x); - cachedStringValue = val; - currentValue = x; - } - - public String getValueString() { - long l = getValue(); - if(cachedStringValue != null) - return cachedStringValue; - else - return Long.toString(l); - } - public void setInitialValue(String val) throws InvalidConfigValueException { - long x; - try{ - x = Fields.parseSILong(val); - }catch (NumberFormatException e) { + @Override + protected Long parseString(String val) throws InvalidConfigValueException { + Long x; + try { + x = Fields.parseLong(val); + } catch (NumberFormatException e) { throw new InvalidConfigValueException(l10n("parseError", "val", val)); } - cachedStringValue = val; - currentValue = x; + return x; } - + private String l10n(String key, String pattern, String value) { - return L10n.getString("LongOption."+key, pattern, value); + return L10n.getString("LongOption." + key, pattern, value); } - - public boolean isDefault() { - getValue(); - return currentValue == defaultValue; - } - public String getDefault() { - return Long.toString(defaultValue); + @Override + protected String toString(Long val) { + return Fields.longToString(val); } - - public void setDefault() { - currentValue = defaultValue; - } - } Copied: branches/db4o/freenet/src/freenet/config/NodeNeedRestartException.java (from rev 21939, trunk/freenet/src/freenet/config/NodeNeedRestartException.java) =================================================================== --- branches/db4o/freenet/src/freenet/config/NodeNeedRestartException.java (rev 0) +++ branches/db4o/freenet/src/freenet/config/NodeNeedRestartException.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -0,0 +1,19 @@ +/* This code is part of Freenet. It is distributed under the GNU General + * Public License, version 2 (or at your option any later version). See + * http://www.gnu.org/ for further details of the GPL. */ +package freenet.config; + +/** + * Thrown when the node refuses to set a config variable to a particular + * value because it is invalid. Just because this is not thrown does not + * necessarily mean that there are no problems with the value defined, + * it merely means that there are no immediately detectable problems with + * it. + */ +public class NodeNeedRestartException extends ConfigException { + + public NodeNeedRestartException(String msg) { + super(msg); + } + +} Modified: branches/db4o/freenet/src/freenet/config/NullBooleanCallback.java =================================================================== --- branches/db4o/freenet/src/freenet/config/NullBooleanCallback.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/config/NullBooleanCallback.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -2,13 +2,13 @@ import freenet.support.api.BooleanCallback; -public class NullBooleanCallback implements BooleanCallback { +public class NullBooleanCallback extends BooleanCallback { - public boolean get() { + public Boolean get() { return false; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { // Ignore } Modified: branches/db4o/freenet/src/freenet/config/NullIntCallback.java =================================================================== --- branches/db4o/freenet/src/freenet/config/NullIntCallback.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/config/NullIntCallback.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -2,13 +2,13 @@ import freenet.support.api.IntCallback; -public class NullIntCallback implements IntCallback { +public class NullIntCallback extends IntCallback { - public int get() { + public Integer get() { return 0; } - public void set(int val) throws InvalidConfigValueException { + public void set(Integer val) throws InvalidConfigValueException { // Ignore } Modified: branches/db4o/freenet/src/freenet/config/NullLongCallback.java =================================================================== --- branches/db4o/freenet/src/freenet/config/NullLongCallback.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/config/NullLongCallback.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -2,13 +2,13 @@ import freenet.support.api.LongCallback; -public class NullLongCallback implements LongCallback { +public class NullLongCallback extends LongCallback { - public long get() { - return 0; + public Long get() { + return 0L; } - public void set(long val) throws InvalidConfigValueException { + public void set(Long val) throws InvalidConfigValueException { // Ignore } Modified: branches/db4o/freenet/src/freenet/config/NullShortCallback.java =================================================================== --- branches/db4o/freenet/src/freenet/config/NullShortCallback.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/config/NullShortCallback.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -2,13 +2,13 @@ import freenet.support.api.ShortCallback; -public class NullShortCallback implements ShortCallback { +public class NullShortCallback extends ShortCallback { - public short get() { + public Short get() { return 0; } - public void set(short val) throws InvalidConfigValueException { + public void set(Short val) throws InvalidConfigValueException { // Ignore } Modified: branches/db4o/freenet/src/freenet/config/NullStringCallback.java =================================================================== --- branches/db4o/freenet/src/freenet/config/NullStringCallback.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/config/NullStringCallback.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -2,7 +2,7 @@ import freenet.support.api.StringCallback; -public class NullStringCallback implements StringCallback { +public class NullStringCallback extends StringCallback { public String get() { return ""; Modified: branches/db4o/freenet/src/freenet/config/Option.java =================================================================== --- branches/db4o/freenet/src/freenet/config/Option.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/config/Option.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -3,11 +3,11 @@ * http://www.gnu.org/ for further details of the GPL. */ package freenet.config; + /** * A config option. */ -public abstract class Option { - +public abstract class Option<T> { /** The parent SubConfig object */ protected final SubConfig config; /** The option name */ @@ -23,17 +23,20 @@ /** Long description of value e.g. "The TCP port to listen for FCP connections on" */ protected final String longDesc; /** The configCallback associated to the Option */ - protected final ConfigCallback cb; + protected final ConfigCallback<T> cb; - public final static int DATA_TYPE_STRING = 0; - public final static int DATA_TYPE_NUMBER = 1; - public final static int DATA_TYPE_BOOLEAN = 2; - public final static int DATA_TYPE_STRING_ARRAY = 3; + protected T defaultValue; + protected T currentValue; + public static enum DataType { + STRING, NUMBER, BOOLEAN, STRING_ARRAY + }; + /** Data type : used to make it possible to make user inputs more friendly in FCP apps */ - final int dataType; + final DataType dataType; - Option(SubConfig config, String name, ConfigCallback cb, int sortOrder, boolean expert, boolean forceWrite, String shortDesc, String longDesc, int dataType) { + Option(SubConfig config, String name, ConfigCallback<T> cb, int sortOrder, boolean expert, boolean forceWrite, + String shortDesc, String longDesc, DataType dataType) { this.config = config; this.name = name; this.cb = cb; @@ -46,27 +49,47 @@ } /** - * Set this option's current value to a string. Will call the callback. Does not care - * whether the value of the option has changed. + * Set this option's current value to a string. Will call the callback. Does not care whether + * the value of the option has changed. */ - public abstract void setValue(String val) throws InvalidConfigValueException; + public final void setValue(String val) throws InvalidConfigValueException, NodeNeedRestartException { + T x = parseString(val); + set(x); + } + protected abstract T parseString(String val) throws InvalidConfigValueException; + protected abstract String toString(T val); + + protected final void set(T val) throws InvalidConfigValueException, NodeNeedRestartException { + try { + cb.set(val); + currentValue = val; + } catch (NodeNeedRestartException e) { + currentValue = val; + throw e; + } + } + /** * Get the current value of the option as a string. */ - public abstract String getValueString(); + public final String getValueString() { + return toString(currentValue); + } /** Set to a value from the config file; this is not passed on to the callback, as we * expect the client-side initialization to check the value. The callback is not valid * until the client calls finishedInitialization(). * @throws InvalidConfigValueException */ - public abstract void setInitialValue(String val) throws InvalidConfigValueException; + public final void setInitialValue(String val) throws InvalidConfigValueException { + currentValue = parseString(val); + } /** * Call the callback with the current value of the option. */ - public void forceUpdate() throws InvalidConfigValueException { + public void forceUpdate() throws InvalidConfigValueException, NodeNeedRestartException { setValue(getValueString()); } @@ -94,31 +117,56 @@ return sortOrder; } - public int getDataType() { + public DataType getDataType() { return dataType; } public String getDataTypeStr() { switch(dataType) { - case(DATA_TYPE_STRING): return "string"; - case(DATA_TYPE_NUMBER): return "number"; - case(DATA_TYPE_BOOLEAN): return "boolean"; - case(DATA_TYPE_STRING_ARRAY): return "stringArray"; + case STRING: + return "string"; + case NUMBER: + return "number"; + case BOOLEAN: + return "boolean"; + case STRING_ARRAY: + return "stringArray"; default: return null; } } /** + * Get the current value. This is the value in use if we have finished initialization, otherwise + * it is the value set at startup (possibly the default). + */ + public final T getValue() { + if (config.hasFinishedInitialization()) + return currentValue = cb.get(); + else + return currentValue; + } + + /** * Is this option set to the default? */ - public abstract boolean isDefault(); + public boolean isDefault() { + getValue(); + return (currentValue == null ? false : currentValue.equals(defaultValue)); + } + + /** + * Set to the default. Don't use after completed initialization, as this does not call the + * callback. + */ + public final void setDefault() { + currentValue = defaultValue; + } - /** Set to the default. Don't use after completed initialization, as this does not call the callback. FIXME fix this? */ - public abstract void setDefault(); - - public abstract String getDefault(); + public final String getDefault() { + return toString(defaultValue); + } - public ConfigCallback getCallback() { + public final ConfigCallback<T> getCallback() { return cb; } } Modified: branches/db4o/freenet/src/freenet/config/PersistentConfig.java =================================================================== --- branches/db4o/freenet/src/freenet/config/PersistentConfig.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/config/PersistentConfig.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -36,15 +36,15 @@ } public SimpleFieldSet exportFieldSet(boolean withDefaults) { - return exportFieldSet(Config.CONFIG_REQUEST_TYPE_CURRENT_SETTINGS, withDefaults); + return exportFieldSet(Config.RequestType.CURRENT_SETTINGS, withDefaults); } - public SimpleFieldSet exportFieldSet(int configRequestType, boolean withDefaults) { + public SimpleFieldSet exportFieldSet(Config.RequestType configRequestType, boolean withDefaults) { SimpleFieldSet fs = new SimpleFieldSet(true); SubConfig[] configs; synchronized(this) { // FIXME maybe keep a cache of this? - configs = (SubConfig[]) configsByPrefix.values().toArray(new SubConfig[configsByPrefix.size()]); + configs = configsByPrefix.values().toArray(new SubConfig[configsByPrefix.size()]); } SubConfig current; for(int i=0;i<configs.length;i++) { Modified: branches/db4o/freenet/src/freenet/config/ShortOption.java =================================================================== --- branches/db4o/freenet/src/freenet/config/ShortOption.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/config/ShortOption.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -4,68 +4,31 @@ import freenet.support.Fields; import freenet.support.api.ShortCallback; -public class ShortOption extends Option { - - final short defaultValue; - final ShortCallback cb; - private short currentValue; - +public class ShortOption extends Option<Short> { public ShortOption(SubConfig conf, String optionName, short defaultValue, int sortOrder, boolean expert, boolean forceWrite, String shortDesc, String longDesc, ShortCallback cb) { - super(conf, optionName, cb, sortOrder, expert, forceWrite, shortDesc, longDesc, Option.DATA_TYPE_NUMBER); + super(conf, optionName, cb, sortOrder, expert, forceWrite, shortDesc, longDesc, Option.DataType.NUMBER); this.defaultValue = defaultValue; - this.cb = cb; this.currentValue = defaultValue; } - - /** Get the current value. This is the value in use if we have finished - * initialization, otherwise it is the value set at startup (possibly the default). */ - public short getValue() { - if(config.hasFinishedInitialization()) - return currentValue = cb.get(); - else return currentValue; + + private String l10n(String key, String pattern, String value) { + return L10n.getString("ShortOption."+key, pattern, value); } - public void setValue(String val) throws InvalidConfigValueException { + @Override + protected Short parseString(String val) throws InvalidConfigValueException { short x; - try{ - x= Fields.parseSIShort(val); + try { + x = Fields.parseShort(val); } catch (NumberFormatException e) { throw new InvalidConfigValueException(l10n("unrecognisedShort", "val", val)); } - cb.set(x); - currentValue = x; + return x; } - public String getValueString() { - return Short.toString(getValue()); - } - - public void setInitialValue(String val) throws InvalidConfigValueException { - short x; - try{ - x = Fields.parseSIShort(val); - } catch (NumberFormatException e) { - throw new InvalidConfigValueException(l10n("unrecognisedShort", "val", val)); - } - currentValue = x; - } - - private String l10n(String key, String pattern, String value) { - return L10n.getString("ShortOption."+key, pattern, value); - } - - public boolean isDefault() { - getValue(); - return currentValue == defaultValue; - } - - public String getDefault() { - return Short.toString(defaultValue); - } - - public void setDefault() { - currentValue = defaultValue; - } - + @Override + protected String toString(Short val) { + return Fields.shortToString(val); + } } Modified: branches/db4o/freenet/src/freenet/config/StringArrOption.java =================================================================== --- branches/db4o/freenet/src/freenet/config/StringArrOption.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/config/StringArrOption.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -8,80 +8,45 @@ import freenet.support.URLEncoder; import freenet.support.api.StringArrCallback; -public class StringArrOption extends Option { - - private final String[] defaultValue; - private final StringArrCallback cb; - private String[] currentValue; - +public class StringArrOption extends Option<String[]> { public static final String delimiter = ";"; public StringArrOption(SubConfig conf, String optionName, String[] defaultValue, int sortOrder, boolean expert, boolean forceWrite, String shortDesc, String longDesc, StringArrCallback cb) { - super(conf, optionName, cb, sortOrder, expert, forceWrite, shortDesc, longDesc, Option.DATA_TYPE_STRING_ARRAY); + super(conf, optionName, cb, sortOrder, expert, forceWrite, shortDesc, longDesc, Option.DataType.STRING_ARRAY); this.defaultValue = (defaultValue==null)?new String[0]:defaultValue; - this.cb = cb; this.currentValue = (defaultValue==null)?new String[0]:defaultValue; } - - /** Get the current value. This is the value in use if we have finished - * initialization, otherwise it is the value set at startup (possibly the default). */ - public String[] getValue() { - if(config.hasFinishedInitialization()) - currentValue = cb.get(); - return currentValue; - } + public String[] parseString(String val) throws InvalidConfigValueException { + if(val.length() == 0) return new String[0]; + String[] out = val.split(delimiter); - public void setValue(String[] val) throws InvalidConfigValueException { - setInitialValue(val); - cb.set(this.currentValue); - } - - public void setValue(String val) throws InvalidConfigValueException { try { - setValue(stringToArray(val)); + for (int i = 0; i < out.length; i++) { + if (out[i].equals(":")) + out[i] = ""; + else + out[i] = URLDecoder.decode(out[i], true /* FIXME false */); + } } catch (URLEncodedFormatException e) { throw new InvalidConfigValueException(l10n("parseError", "error", e.getLocalizedMessage())); } - } - - public static String[] stringToArray(String val) throws URLEncodedFormatException { - if(val.length() == 0) return new String[0]; - String[] out = val.split(delimiter); - for(int i=0;i<out.length;i++) { - if(out[i].equals(":")) - out[i] = ""; - else - out[i] = URLDecoder.decode(out[i], true /* FIXME false */); - } return out; } - - public String getValueString() { - return arrayToString(getValue()); - } public void setInitialValue(String[] val) throws InvalidConfigValueException { this.currentValue = val; } - public void setInitialValue(String val) throws InvalidConfigValueException { - try { - this.currentValue = stringToArray(val); - } catch (URLEncodedFormatException e) { - throw new InvalidConfigValueException(l10n("parseError", "error", e.getLocalizedMessage())); - } - } - private String l10n(String key, String pattern, String value) { return L10n.getString("StringArrOption."+key, pattern, value); } - public static String arrayToString(String[] arr) { + public String toString(String[] arr) { if (arr == null) return null; - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); for (int i = 0 ; i < arr.length ; i++) { String val = arr[i]; if(val.length() == 0) @@ -101,17 +66,8 @@ } } - public String getDefault() { - return arrayToString(defaultValue); - } - public boolean isDefault() { - getValueString(); + getValue(); return currentValue == null ? false : Arrays.equals(currentValue, defaultValue); } - - public void setDefault() { - currentValue = defaultValue; - } - } Modified: branches/db4o/freenet/src/freenet/config/StringOption.java =================================================================== --- branches/db4o/freenet/src/freenet/config/StringOption.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/config/StringOption.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -5,51 +5,21 @@ import freenet.support.api.StringCallback; -public class StringOption extends Option { - - final String defaultValue; - final StringCallback cb; - private String currentValue; - +public class StringOption extends Option<String> { public StringOption(SubConfig conf, String optionName, String defaultValue, int sortOrder, boolean expert, boolean forceWrite, String shortDesc, String longDesc, StringCallback cb) { - super(conf, optionName, cb, sortOrder, expert, forceWrite, shortDesc, longDesc, Option.DATA_TYPE_STRING); + super(conf, optionName, cb, sortOrder, expert, forceWrite, shortDesc, longDesc, Option.DataType.STRING); this.defaultValue = defaultValue; - this.cb = cb; this.currentValue = defaultValue; } - - /** Get the current value. This is the value in use if we have finished - * initialization, otherwise it is the value set at startup (possibly the default). */ - public String getValue() { - if(config.hasFinishedInitialization()) - return currentValue = cb.get(); - else return currentValue; - } - public void setValue(String val) throws InvalidConfigValueException { - cb.set(val); - this.currentValue = val; // Callbacks are in charge of ensuring it matches with possibleValues + @Override + protected String parseString(String val) throws InvalidConfigValueException { + return val; } - - public String getValueString() { - return getValue(); - } - public void setInitialValue(String val) throws InvalidConfigValueException { - this.currentValue = val; + @Override + protected String toString(String val) { + return val; } - - public boolean isDefault() { - getValue(); - return (currentValue == null ? false : currentValue.equals(defaultValue)); - } - - public void setDefault() { - currentValue = defaultValue; - } - - public String getDefault(){ - return defaultValue; - } } Modified: branches/db4o/freenet/src/freenet/config/SubConfig.java =================================================================== --- branches/db4o/freenet/src/freenet/config/SubConfig.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/config/SubConfig.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -3,8 +3,8 @@ * http://www.gnu.org/ for further details of the GPL. */ package freenet.config; +import java.util.Iterator; import java.util.LinkedHashMap; -import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.Map.Entry; @@ -22,9 +22,9 @@ /** * A specific configuration block. */ -public class SubConfig implements Comparable { +public class SubConfig implements Comparable<SubConfig> { - private final LinkedHashMap map; + private final LinkedHashMap<String, Option<?>> map; public final Config config; final String prefix; private boolean hasInitialized; @@ -32,7 +32,7 @@ public SubConfig(String prefix, Config config) { this.config = config; this.prefix = prefix; - map = new LinkedHashMap(); + map = new LinkedHashMap<String, Option<?>>(); hasInitialized = false; config.register(this); } @@ -41,15 +41,15 @@ * Return all the options registered. Each includes its name. * Used by e.g. webconfig. */ - public synchronized Option[] getOptions() { - return (Option[]) map.values().toArray(new Option[map.size()]); + public synchronized Option<?>[] getOptions() { + return map.values().toArray(new Option[map.size()]); } - public synchronized Option getOption(String option){ - return (Option)map.get(option); + public synchronized Option<?> getOption(String option) { + return map.get(option); } - public void register(Option o) { + public void register(Option<?> o) { synchronized(this) { if(o.name.indexOf(SimpleFieldSet.MULTI_LEVEL_CHAR) != -1) throw new IllegalArgumentException("Option names must not contain "+SimpleFieldSet.MULTI_LEVEL_CHAR); @@ -63,13 +63,13 @@ public void register(String optionName, int defaultValue, int sortOrder, boolean expert, boolean forceWrite, String shortDesc, String longDesc, IntCallback cb) { if(cb == null) cb = new NullIntCallback(); - register(new IntOption(this, optionName, defaultValue, null, sortOrder, expert, forceWrite, shortDesc, longDesc, cb)); + register(new IntOption(this, optionName, defaultValue, sortOrder, expert, forceWrite, shortDesc, longDesc, cb)); } public void register(String optionName, long defaultValue, int sortOrder, boolean expert, boolean forceWrite, String shortDesc, String longDesc, LongCallback cb) { if(cb == null) cb = new NullLongCallback(); - register(new LongOption(this, optionName, defaultValue, null, sortOrder, expert, forceWrite, shortDesc, longDesc, cb)); + register(new LongOption(this, optionName, defaultValue, sortOrder, expert, forceWrite, shortDesc, longDesc, cb)); } public void register(String optionName, String defaultValueString, int sortOrder, @@ -178,12 +178,12 @@ * Set options from a SimpleFieldSet. Once we process an option, we must remove it. */ public void setOptions(SimpleFieldSet sfs) { - Set entrySet = map.entrySet(); - Iterator i = entrySet.iterator(); + Set<Map.Entry<String, Option<?>>> entrySet = map.entrySet(); + Iterator<Entry<String, Option<?>>> i = entrySet.iterator(); while(i.hasNext()) { - Map.Entry entry = (Map.Entry) i.next(); - String key = (String) entry.getKey(); - Option o = (Option) entry.getValue(); + Entry<String, Option<?>> entry = i.next(); + String key = entry.getKey(); + Option<?> o = entry.getValue(); String val = sfs.get(key); if(val != null) { try { @@ -192,6 +192,11 @@ String msg = "Invalid config value: "+prefix+SimpleFieldSet.MULTI_LEVEL_CHAR+key+" = "+val+" : error: "+e; Logger.error(this, msg, e); System.err.println(msg); // might be about logging? + } catch (NodeNeedRestartException e) { + // Impossible + String msg = "Impossible: " + prefix + SimpleFieldSet.MULTI_LEVEL_CHAR + key + " = " + val + + " : error: " + e; + Logger.error(this, msg, e); } } } @@ -202,53 +207,55 @@ } public SimpleFieldSet exportFieldSet(boolean withDefaults) { - return exportFieldSet(Config.CONFIG_REQUEST_TYPE_CURRENT_SETTINGS, withDefaults); + return exportFieldSet(Config.RequestType.CURRENT_SETTINGS, withDefaults); } - public SimpleFieldSet exportFieldSet(int configRequestType, boolean withDefaults) { + public SimpleFieldSet exportFieldSet(Config.RequestType configRequestType, boolean withDefaults) { SimpleFieldSet fs = new SimpleFieldSet(true); + @SuppressWarnings("unchecked") + Map.Entry<String, Option<?>>[] entries = new Map.Entry[map.size()]; // FIXME is any locking at all necessary here? After it has finished init, it's constant... - Map.Entry[] entries; synchronized(this) { - entries = (Entry[]) map.entrySet().toArray(new Map.Entry[map.size()]); + entries = map.entrySet().toArray(entries); } boolean logMINOR = Logger.shouldLog(Logger.MINOR, this); if(logMINOR) Logger.minor(this, "Prefix="+prefix); for(int i=0;i<entries.length;i++) { - Map.Entry entry = (Map.Entry) entries[i]; - String key = (String) entry.getKey(); - Option o = (Option) entry.getValue(); -// if(logMINOR) -// Logger.minor(this, "Key="+key+" value="+o.getValueString()+" default="+o.isDefault()); - if(configRequestType == Config.CONFIG_REQUEST_TYPE_CURRENT_SETTINGS && (!withDefaults) && o.isDefault() && (!o.forceWrite)) { + Map.Entry<String, Option<?>> entry = entries[i]; + String key = entry.getKey(); + Option<?> o = entry.getValue(); + if(logMINOR) + Logger.minor(this, "Key="+key+" value="+o.getValueString()+" default="+o.isDefault()); + if (configRequestType == Config.RequestType.CURRENT_SETTINGS && (!withDefaults) && o.isDefault() + && (!o.forceWrite)) { if(logMINOR) Logger.minor(this, "Skipping "+key+" - "+o.isDefault()); continue; } switch (configRequestType) { - case Config.CONFIG_REQUEST_TYPE_CURRENT_SETTINGS: + case CURRENT_SETTINGS: fs.putSingle(key, o.getValueString()); break; - case Config.CONFIG_REQUEST_TYPE_DEFAULT_SETTINGS: + case DEFAULT_SETTINGS: fs.putSingle(key, o.getDefault()); break; - case Config.CONFIG_REQUEST_TYPE_SORT_ORDER: + case SORT_ORDER: fs.put(key, o.getSortOrder()); break; - case Config.CONFIG_REQUEST_TYPE_EXPERT_FLAG: + case EXPERT_FLAG: fs.put(key, o.isExpert()); break; - case Config.CONFIG_REQUEST_TYPE_FORCE_WRITE_FLAG: + case FORCE_WRITE_FLAG: fs.put(key, o.isForcedWrite()); break; - case Config.CONFIG_REQUEST_TYPE_SHORT_DESCRIPTION: + case SHORT_DESCRIPTION: fs.putSingle(key, L10n.getString(o.getShortDesc())); break; - case Config.CONFIG_REQUEST_TYPE_LONG_DESCRIPTION: + case LONG_DESCRIPTION: fs.putSingle(key, L10n.getString(o.getLongDesc())); break; - case Config.CONFIG_REQUEST_TYPE_DATA_TYPE: + case DATA_TYPE: fs.putSingle(key, o.getDataTypeStr()); break; default: @@ -263,19 +270,21 @@ /** * Force an option to be updated even if it hasn't changed. - * @throws InvalidConfigValueException + * + * @throws InvalidConfigValueException + * @throws NodeNeedRestartException */ - public void forceUpdate(String optionName) throws InvalidConfigValueException { - Option o = (Option) map.get(optionName); + public void forceUpdate(String optionName) throws InvalidConfigValueException, NodeNeedRestartException { + Option<?> o = map.get(optionName); o.forceUpdate(); } - public void set(String name, String value) throws InvalidConfigValueException { - Option o = (Option) map.get(name); + public void set(String name, String value) throws InvalidConfigValueException, NodeNeedRestartException { + Option<?> o = map.get(name); o.setValue(value); } - public void set(String name, boolean value) throws InvalidConfigValueException { + public void set(String name, boolean value) throws InvalidConfigValueException, NodeNeedRestartException { BooleanOption o = (BooleanOption) map.get(name); o.set(value); } @@ -288,7 +297,7 @@ * @param value The value of the option. */ public void fixOldDefault(String name, String value) { - Option o = (Option) map.get(name); + Option<?> o = map.get(name); if(o.getValueString().equals(value)) o.setDefault(); } @@ -301,7 +310,7 @@ * @param value The value of the option. */ public void fixOldDefaultRegex(String name, String value) { - Option o = (Option) map.get(name); + Option<?> o = map.get(name); if(o.getValueString().matches(value)) o.setDefault(); } @@ -310,15 +319,11 @@ return prefix; } - public int compareTo(Object o){ - if((o == null) || !(o instanceof SubConfig)) return 0; - else{ - SubConfig second = (SubConfig) o; - if(this.getPrefix().compareTo(second.getPrefix())>0) - return 1; - else - return -1; - } + public int compareTo(SubConfig second) { + if (this.getPrefix().compareTo(second.getPrefix()) > 0) + return 1; + else + return -1; } public String getRawOption(String name) { Modified: branches/db4o/freenet/src/freenet/config/WrapperConfig.java =================================================================== --- branches/db4o/freenet/src/freenet/config/WrapperConfig.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/config/WrapperConfig.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -24,12 +24,12 @@ */ public class WrapperConfig { - private static HashMap overrides = new HashMap(); + private static HashMap<String, String> overrides = new HashMap<String, String>(); public static String getWrapperProperty(String name) { synchronized(WrapperConfig.class) { if(overrides.containsKey(name)) - return (String) overrides.get(name); + return overrides.get(name); } return WrapperManager.getProperties().getProperty(name, null); } Modified: branches/db4o/freenet/src/freenet/crypt/DiffieHellman.java =================================================================== --- branches/db4o/freenet/src/freenet/crypt/DiffieHellman.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/crypt/DiffieHellman.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -6,6 +6,7 @@ package freenet.crypt; +import freenet.node.FNPPacketMangler; import java.math.BigInteger; import java.util.Random; import java.util.Stack; @@ -20,10 +21,10 @@ * When the number of precalculations falls below this threshold generation * starts up to make more. */ - private static final int PRECALC_RESUME = 150; + private static final int PRECALC_RESUME = FNPPacketMangler.DH_CONTEXT_BUFFER_SIZE; /** Maximum number of precalculations to create. */ - private static final int PRECALC_MAX = 300; + private static final int PRECALC_MAX = FNPPacketMangler.DH_CONTEXT_BUFFER_SIZE * 2; /** * How often to wake up and make sure the precalculation buffer is full @@ -49,7 +50,7 @@ private static class PrecalcBufferFill extends NativeThread { public PrecalcBufferFill() { - super("Diffie-Hellman-Precalc", NativeThread.LOW_PRIORITY, false); + super("Diffie-Hellman-Precalc", NativeThread.MIN_PRIORITY, false); setDaemon(true); } @@ -119,6 +120,7 @@ } } + Logger.normal(DiffieHellman.class, "DiffieHellman had to generate a parameter on thread! (report if that happens often)"); return genParams(); } Deleted: branches/db4o/freenet/src/freenet/crypt/DigestFactory.java =================================================================== --- branches/db4o/freenet/src/freenet/crypt/DigestFactory.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/crypt/DigestFactory.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -1,15 +0,0 @@ -/* This code is part of Freenet. It is distributed under the GNU General - * Public License, version 2 (or at your option any later version). See - * http://www.gnu.org/ for further details of the GPL. */ -package freenet.crypt; - -/* - * @deprecated Digests should be able to reinitialize themselves instead - * Re-precated since I need to create many digests at the same time for the - * serial hash. - **/ -public interface DigestFactory { - - public Digest getInstance(); - -} Deleted: branches/db4o/freenet/src/freenet/crypt/SHA1Factory.java =================================================================== --- branches/db4o/freenet/src/freenet/crypt/SHA1Factory.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/crypt/SHA1Factory.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -1,12 +0,0 @@ -/* This code is part of Freenet. It is distributed under the GNU General - * Public License, version 2 (or at your option any later version). See - * http://www.gnu.org/ for further details of the GPL. */ -package freenet.crypt; - -public class SHA1Factory implements DigestFactory { - - public Digest getInstance() { - return SHA1.getInstance(); - } - -} Modified: branches/db4o/freenet/src/freenet/crypt/SSL.java =================================================================== --- branches/db4o/freenet/src/freenet/crypt/SSL.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/crypt/SSL.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -23,16 +23,18 @@ import java.security.Key; import java.security.KeyStore; import java.security.cert.Certificate; + import javax.net.ServerSocketFactory; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; +import com.sleepycat.je.utilint.NotImplementedYetException; + import freenet.config.InvalidConfigValueException; import freenet.config.SubConfig; import freenet.support.Logger; import freenet.support.api.BooleanCallback; import freenet.support.api.StringCallback; - import freenet.support.io.Closer; public class SSL { @@ -64,11 +66,11 @@ sslConfig.register("sslEnable", false, configItemOrder++, true, true, "SSL.enable", "SSL.enableLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { return enable; } - public void set(boolean newValue) throws InvalidConfigValueException { + public void set(Boolean newValue) throws InvalidConfigValueException { if(newValue != get()) { enable = newValue; if(enable) Modified: branches/db4o/freenet/src/freenet/crypt/Yarrow.java =================================================================== --- branches/db4o/freenet/src/freenet/crypt/Yarrow.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/crypt/Yarrow.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -61,14 +61,18 @@ public final File seedfile; //A file to which seed data should be dumped periodically public Yarrow() { - this("prng.seed", "SHA1", "Rijndael", true); + this("prng.seed", "SHA1", "Rijndael", true, true); } + + public Yarrow(boolean canBlock) { + this("prng.seed", "SHA1", "Rijndael", true, canBlock); + } - public Yarrow(String seed, String digest, String cipher, boolean updateSeed) { - this(new File(seed), digest, cipher, updateSeed); + public Yarrow(String seed, String digest, String cipher, boolean updateSeed, boolean canBlock) { + this(new File(seed), digest, cipher, updateSeed, canBlock); } - public Yarrow(File seed, String digest, String cipher, boolean updateSeed) { + public Yarrow(File seed, String digest, String cipher, boolean updateSeed, boolean canBlock) { SecureRandom s; try { s = SecureRandom.getInstance("SHA1PRNG"); @@ -85,7 +89,7 @@ throw new RuntimeException("Cannot initialize Yarrow!: " + e, e); } entropy_init(seed); - seedFromExternalStuff(true); + seedFromExternalStuff(canBlock); if(updateSeed && !(seed.toString()).equals("/dev/urandom")) //Dont try to update the seedfile if we know that it wont be possible anyways seedfile = seed; else @@ -646,7 +650,7 @@ * Test routine */ public static void main(String[] args) throws Exception { - Yarrow r = new Yarrow(new File("/dev/urandom"), "SHA1", "Rijndael", true); + Yarrow r = new Yarrow(new File("/dev/urandom"), "SHA1", "Rijndael", true, false); byte[] b = new byte[1024]; Modified: branches/db4o/freenet/src/freenet/io/AddressIdentifier.java =================================================================== --- branches/db4o/freenet/src/freenet/io/AddressIdentifier.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/io/AddressIdentifier.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -46,23 +46,9 @@ ipv6PatternWithPercentScopeID = Pattern.compile(ipv6AddressRegex + percentScopeIDRegex); ipv6ISATAPPattern = Pattern.compile(ipv6ISATAPAddressRegex); } - - public static class AddressType { - - public static final AddressType OTHER = new AddressType("Other"); - public static final AddressType IPv4 = new AddressType("IPv4"); - public static final AddressType IPv6 = new AddressType("IPv6"); - - private final String name; - - private AddressType(String name) { - this.name = name; - } - - public String toString() { - return name; - } - + + public enum AddressType { + OTHER, IPv4, IPv6; } /** Modified: branches/db4o/freenet/src/freenet/io/NetworkInterface.java =================================================================== --- branches/db4o/freenet/src/freenet/io/NetworkInterface.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/io/NetworkInterface.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -16,6 +16,7 @@ package freenet.io; +import java.io.Closeable; import java.io.IOException; import java.net.Inet6Address; import java.net.InetAddress; @@ -40,7 +41,7 @@ * @author David Roden <droden at gmail.com> * @version $Id$ */ -public class NetworkInterface { +public class NetworkInterface implements Closeable { public static final String DEFAULT_BIND_TO = "127.0.0.1,0:0:0:0:0:0:0:1"; @@ -138,6 +139,7 @@ InetSocketAddress addr = null; try { addr = new InetSocketAddress((String) bindToTokenList.get(serverSocketIndex), port); + serverSocket.setReuseAddress(true); serverSocket.bind(addr); } catch (SocketException e) { if(ignoreUnbindableIP6 && addr != null && addr.getAddress() instanceof Inet6Address) Modified: branches/db4o/freenet/src/freenet/io/comm/DMT.java =================================================================== --- branches/db4o/freenet/src/freenet/io/comm/DMT.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/io/comm/DMT.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -1206,18 +1206,6 @@ msg.set(DATA, new ShortBuffer(buf)); return msg; } - - @Deprecated - public static final MessageType FNPLocChangeNotification = new MessageType("FNPLocationChangeNotification", PRIORITY_LOW) {{ - addField(LOCATION, Double.class); - }}; - - @Deprecated - public static final Message createFNPLocChangeNotification(double newLoc) { - Message msg = new Message(FNPLocChangeNotification); - msg.set(LOCATION, newLoc); - return msg; - } public static final MessageType FNPLocChangeNotificationNew = new MessageType("FNPLocationChangeNotification2", PRIORITY_LOW) {{ addField(LOCATION, Double.class); Modified: branches/db4o/freenet/src/freenet/io/comm/FreenetInetAddress.java =================================================================== --- branches/db4o/freenet/src/freenet/io/comm/FreenetInetAddress.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/io/comm/FreenetInetAddress.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -141,7 +141,7 @@ AddressIdentifier.AddressType addressType = AddressIdentifier.getAddressType(host); boolean logDEBUG = Logger.shouldLog(Logger.DEBUG, this); if(logDEBUG) Logger.debug(this, "Address type of '"+host+"' appears to be '"+addressType+ '\''); - if(!addressType.toString().equals("Other")) { + if(addressType != AddressIdentifier.AddressType.OTHER) { try { addr = InetAddress.getByName(host); } catch (UnknownHostException e) { Modified: branches/db4o/freenet/src/freenet/io/comm/UdpSocketHandler.java =================================================================== --- branches/db4o/freenet/src/freenet/io/comm/UdpSocketHandler.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/io/comm/UdpSocketHandler.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -64,6 +64,7 @@ _sock.setReceiveBufferSize(65536); try { // Exit reasonably quickly + _sock.setReuseAddress(true); _sock.setSoTimeout(1000); } catch (SocketException e) { throw new RuntimeException(e); @@ -158,7 +159,6 @@ private void realRun(DatagramPacket packet) { // Single receiving thread - logDEBUG = Logger.shouldLog(Logger.MINOR, this); boolean gotPacket = getPacket(packet); long now = System.currentTimeMillis(); if (gotPacket) { Modified: branches/db4o/freenet/src/freenet/l10n/L10n.java =================================================================== --- branches/db4o/freenet/src/freenet/l10n/L10n.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/l10n/L10n.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -290,7 +290,7 @@ private static String quoteReplacement(String s) { if ((s.indexOf('\\') == -1) && (s.indexOf('$') == -1)) return s; - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); for (int i=0; i<s.length(); i++) { char c = s.charAt(i); if (c == '\\') { Modified: branches/db4o/freenet/src/freenet/l10n/freenet.l10n.de.properties =================================================================== --- branches/db4o/freenet/src/freenet/l10n/freenet.l10n.de.properties 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/l10n/freenet.l10n.de.properties 2008-09-24 20:42:20 UTC (rev 22823) @@ -280,6 +280,7 @@ FProxyToadlet.notEnoughMetaStrings=Nicht genug Meta-Zeichenfolgen FProxyToadlet.notFoundTitle=Nicht gefunden FProxyToadlet.openAsText=${link}Klicken Sie hier${/link} um die Datei als Flie?text zu ?ffnen (dies sollte nicht gef?hrlich, k?nnte allerdings durcheinander/unleserlich sein). +FProxyToadlet.openAsThawIndex=${link}Hier klicken${/link} um die Datei mit dem Thaw Index Browser zu ?ffnen (lesen Sie die obige Warnung!). FProxyToadlet.openForce=${link}Klicken Sie hier${/link} um die Datei als ${mime} zu ?ffnen (lesen Sie die obenstehende Warnung!). FProxyToadlet.openForceDisk=${link}Klicken Sie hier${/link} um Ihren Browser zu zwingen, die Datei auf einen Datentr?ger herunterzuladen. FProxyToadlet.openPossRSSAsPlainText=${link}Klicken Sie hier${/link} um die Datei als Flie?text zu ?ffnen (dies ${bold}kann gef?hrlich sein${/bold} wenn Sie Internet Explorer 7 oder Firefox 2 benutzen). @@ -693,8 +694,8 @@ Node.passOpennetPeersThroughDarknetLong=Wenn aktiviert, werden Opennet-Knotenreferenzen (NIEMALS unsere eigene Darknet-Knotenreferenz) ?ber unsere Darknet-Partner weitergeleitet. Sodass ein Knoten (dieser Knoten oder seine Partner) Opennet-Partner von seinen Darknet-Partnern bekommen kann. Dies ist n?tzlich, da es uns erlaubt einen Bootstrap (Erlangung neuer Quellen ohne vorher welche zu haben) nach neuen Opennet-Partnern durchzuf?hren nachdem wir unsere Partner, zum Beispiel durch Ausfallzeiten, verloren haben. Jedoch kann es eine Traffic(Verkehrs)-Analyse etwas erleichtern, deshalb sollten Sie es ausschalten wenn Sie paranoid sind. Node.port=FNP-Port Nummer (UDP) Node.portLong=UDP-Port f?r Knoten-zu-Knoten Kommunikationen (Freenet-Knoten-Protokoll) -Node.publishOurPeersLocation=Sollen wir die Position unserer Partner an unsere Partner weitergeben? -Node.publishOurPeersLocationLong=Sollen wir die Position unserer Partner an unsere Partner weitergeben? Dies zu tun, hilft dem Routing gibt aber Informationen an potenzielle Angreifer preis. +Node.publishOurPeersLocation=Sollen wir die Positionen unserer Partner an unsere Partner weitergeben? +Node.publishOurPeersLocationLong=Sollen wir die Positionen unserer Partner an unsere Partner weitergeben? Dies zu tun, hilft dem Routing gibt aber Informationen an potenzielle Angreifer preis. Node.routeAccordingToOurPeersLocation=Sollen wir die Positionen der Partner unserer Partner zu Routing-Zwecken ber?cksichtigen? Node.routeAccordingToOurPeersLocationLong=Sollen wir die Positionen der Partner unserer Partner zu Routing-Zwecken ber?cksichtigen? Dies zu tun verbessert das Routing, k?nnte aber einem potenziellen Angreifer helfen. Node.storeDirectory=Speicher-Verzeichnis @@ -711,6 +712,8 @@ Node.tooSmallMTU=MTU zu niedrig Node.tooSmallMTULong=Die MTU ihrer Verbindung scheint ${mtu} Bytes zu sein. Freenet wird mit einer MTU unter ${minMTU} Bytes nicht gut funktionieren: Verbindungen werden unzuverl?ssig und wom?glich langsam sein. Bitte beheben Sie dieses Problem, wenn m?glich. Node.tooSmallMTUShort=Verbindungsprobleme: Die MTU Ihrer Verbindung ist zu klein damit Freenet gut funktioniert. Es sind Probleme zu erwarten. +Node.withAnnouncement=Dem Knoten erlauben sich mit Hilfe von Seednodes automatisch zu verbinden? +Node.withAnnouncementLong=Dem Knoten erlauben sich mit Hilfe von Seednodes (Saatknoten) automatisch zu verbinden? Obwohl dies die Standard-Einstellung darstellt, ist es prinzip-bedingt unsicher. NodeClientCore.couldNotFindOrCreateDir=Das Verzeichnis konnte weder gefunden noch angelegt werden NodeClientCore.downloadAllowedDirs=Verzeichnisse in welche das Herunterladen erlaubt ist NodeClientCore.downloadAllowedDirsLong=Per Semikolon getrennte Liste von Verzeichnissen, in welche das Herunterladen erlaubt ist. "downloads" steht f?r das Download-Verzeichnis, wenn das Feld leer ist bedeutet dies, dass keine Dateien auf Datentr?ger heruntergeladen werden d?rfen, "all" erlaubt das Herunterladen ?berall hin. WARNUNG! Wenn diese Option auf "all" gesetzt wird, kann jeder Benutzer jede Datei an jeden Ort auf Ihrem Computer herunterladen! @@ -828,6 +831,10 @@ PeersSayKeyBlownAlert.intro=Ein oder mehrere Ihrer Partner melden, dass der Schl?ssel der automatischen Aktualisierung unbrauchbar sei! Dies bedeutet, dass ein Angreifer den privaten Schl?ssel f?r das automatische Aktualisierungs-System kennen k?nnte und deshalb Ihren Knoten zur Ausf?hrung von Code seiner Wahl veranlassen k?nnte (wenn Sie aktualisieren)! Das automatische Aktualisierungs-System wurde ausgeschaltet. Es ist auch m?glich, dass Ihre Partner diesbez?glich bewusst l?gen. PeersSayKeyBlownAlert.short=Einige Ihrer Partner melden, dass der Schl?ssel f?r die automatischen Aktualisierungen unbrauchbar gemacht wurde! PeersSayKeyBlownAlert.titleWithCount=Laut ${count} Partner(n) ist der Schl?ssel der automatischen Aktualisierung unbrauchbar! +PluginConfig.configFile=Plugin-Konfigurations-Datei +PluginConfig.configFileLong=Pfad/Dateiname der Datei in welcher die Einstellungen der Plugins (Erweiterungen) gespeichert werden. +PluginConfig.installDir=Plugin-Installations-Verzeichnis +PluginConfig.installDirLong=Verzeichnis in dem die Plugins (Erweiterungen) installiert werden. PluginManager.cannotSetOnceLoaded=Kann die Plugin(=Erweiterungs)-Liste nicht modifizieren sobald sie geladen wurde PluginManager.loadedOnStartup=Plugins die beim Start geladen werden PluginManager.loadedOnStartupLong=Klassenpfad, Name und Verzeichnis f?r Plugins (Erweiterungen) die beim Start des Knotens geladen werden sollen @@ -861,13 +868,17 @@ PproxyToadlet.changeReloadOnStartup=?ndern PproxyToadlet.classNameTitle=Klassen-Name PproxyToadlet.downloadNotAllowedFromRemoteServer=Das downloaden von Plugins ist nur von unserem Server erlaubt. +PproxyToadlet.fileonly=nur lokale Dateien PproxyToadlet.internalIDTitle=Interne ID +PproxyToadlet.loadFreenetPlugin=Ein inoffizielles Plugin aus dem Freenet hinzuf?gen +PproxyToadlet.loadFreenetPluginText=Hier k?nnen Sie die Freenet-URI eines Plugins das Sie laden m?chten eingeben. Diese Plugins werden von uns nicht im Entferntesten unterst?tzt oder darauf ?berpr?ft, ob sie private Informationen herausgeben. Wenn Sie also hier ein inoffizielles Plugin laden, sind Sie auf sich allein gestellt. +PproxyToadlet.loadFreenetURLLabel=Schl?ssel des Plugins PproxyToadlet.loadOfficialPlugin=Ein offizielles Plugin hinzuf?gen PproxyToadlet.loadOfficialPluginLabel=Offizielles Plugin laden PproxyToadlet.loadOfficialPluginText=Diese Plugins liegen auf den Servern des Freenet-Projekts. Wir glauben, dass diese Plugins keine pers?nlichen Informationen ungefragt herausgeben, auch wenn wir es nicht garantieren. PproxyToadlet.loadOfficialPluginWarning=WARNUNG: Das Laden eines offiziellen Plugins beinhaltet das Herunterladen des Plugins aus dem Internet (nicht aus dem Freenet). Laden Sie hier keine Plugins herunter wenn dies ein Problem darstellt. PproxyToadlet.loadOtherPlugin=Ein inoffizielles Plugin hinzuf?gen -PproxyToadlet.loadOtherPluginText=Hier k?nnen Sie die URL eines Plugins eingeben, das geladen werden soll. Andere Plugins als die oben aufgelisteten, werden von uns noch nicht einmal im Entferntesten unterst?tzt oder darauf gepr?ft, ob sie pers?nliche Informationen herausgeben. Wenn Sie also hier ein inoffizielles Plugin laden, sind Sie auf sich allein gestellt. +PproxyToadlet.loadOtherPluginText=Hier k?nnen Sie die URL eines Plugins eingeben, das geladen werden soll. Andere Plugins als die oben aufgelisteten, werden von uns noch nicht einmal im Entferntesten unterst?tzt oder darauf ?berpr?ft, ob sie pers?nliche Informationen herausgeben. Wenn Sie also hier ein inoffizielles Plugin laden, sind Sie auf sich allein gestellt. PproxyToadlet.loadOtherURLLabel=Plugin-URL PproxyToadlet.loadPluginLabel=Plugin laden: PproxyToadlet.noPlugins=Keine Plugins geladen Modified: branches/db4o/freenet/src/freenet/l10n/freenet.l10n.en.properties =================================================================== --- branches/db4o/freenet/src/freenet/l10n/freenet.l10n.en.properties 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/l10n/freenet.l10n.en.properties 2008-09-24 20:42:20 UTC (rev 22823) @@ -87,6 +87,10 @@ ConfigToadlet.fproxy=fproxy ConfigToadlet.fullTitle=Freenet Node Configuration of ${name} ConfigToadlet.logger=logger +ConfigToadlet.needRestartTitle=Node restart required +ConfigToadlet.needRestart=Some config need restart to activate, please restart the node immediately. +ConfigToadlet.needRestartShort=Some config need restart to activate, please restart the node immediately. +ConfigToadlet.restartNode=Restart Now PageMaker.modeSimple=Simple interface PageMaker.modeSimpleTooltip=A simple interface all users can use PageMaker.modeAdvanced=Advanced interface @@ -255,12 +259,10 @@ FirstTimeWizardToadlet.chooseNodeName=Node name required! FirstTimeWizardToadlet.chooseNodeNameLong=Please enter a node name in the field below (we recommend a nickname possibly with an email address). This is so that your friends (trusted peers, which you have manually added) can easily tell your node from their other nodes. This is not visible to strangers (untrusted automatically added peers). Note that any friend or stranger may trivially identify you from your IP address, since you are connected to them, but they cannot easily tell what you are requesting. FirstTimeWizardToadlet.connectToStrangers=Connect to strangers? -FirstTimeWizardToadlet.connectToStrangersLong=Ideally, all Freenet users would connect only to people they know. This is far more secure, making it very difficult for others to tell that you are using Freenet. However, if you don't know at least 5 people already running Freenet, you can choose to connect to strangers. Note that you can always turn this off later. -FirstTimeWizardToadlet.enableOpennet=Do you know anyone already using Freenet? -FirstTimeWizardToadlet.opennetYes=No, I want the node to automatically find strangers to connect to. -FirstTimeWizardToadlet.opennetNo=Yes, I have at least 5 friends already using Freenet and I will add their details on the Friends page. -FirstTimeWizardToadlet.warningTitle=Warning! -FirstTimeWizardToadlet.opennetWarning=If Freenet is illegal where you live, or if you are using it to access materials that may get you into trouble, telling the node to automatically connect to strangers may be dangerous as it makes life much easier for an attacker. Freenet is still experimental, and we offer no guarantees about security. +FirstTimeWizardToadlet.connectToStrangersLong=To run Freenet, you must connect to at least five other nodes. These should ideally be run by people whom you know and trust. If you don't know enough friends running Freenet, you can choose to connect to strangers' nodes as well. However, connecting to strangers allows others to find out that you are using Freenet and adds some additional security risks. If you want to keep your use of Freenet secret, this may get you into trouble. +FirstTimeWizardToadlet.enableOpennet=It is possible to turn off stranger connections later on, once you have added enough friends, although you will already have revealed some information to strangers in the meantime. Freenet is still experimental, and we offer no guarantees about security. +FirstTimeWizardToadlet.opennetYes=I want the node to automatically find strangers to connect to. +FirstTimeWizardToadlet.opennetNo=I have at least 5 friends already using Freenet and I will add their details on the Friends page. FirstTimeWizardToadlet.welcomeInfoboxTitle=Welcome to Freenet first time wizard! FirstTimeWizardToadlet.welcomeInfoboxContent1=Welcome to Freenet first time wizard. This tool will enable you to configure your node quickly and easily to get you started. FirstTimeWizardToadlet.bandwidthLimit=Bandwidth limits @@ -720,6 +722,10 @@ NodeClientCore.downloadAllowedDirsLong=Semicolon separated list of directories to which downloads are allowed. "downloads" means downloadsDir, empty means no downloads to disk allowed, "all" means downloads allowed from anywhere. WARNING! If this is set to "all" any user can download any file to anywhere on your computer! NodeClientCore.downloadDir=Default download directory NodeClientCore.downloadDirLong=The directory to save downloaded files into by default +NodeClientCore.encryptPersistentTempBuckets=Encrypt the persistent temporary buckets? LEAVE THIS ALONE! +NodeClientCore.encryptPersistentTempBucketsLong=Encrypt the persistent temporary buckets? In some cases (if you use hard-drive and swap encryption) it might not make sense to encrypt persistent temporary buckets. LEAVE THIS ALONE IF YOU DON'T KNOW WHAT YOU ARE DOING! +NodeClientCore.encryptTempBuckets=Encrypt the temporary buckets? LEAVE THIS ALONE! +NodeClientCore.encryptTempBucketsLong=Encrypt the temporary buckets? In some cases (if you use hard-drive and swap encryption) it might not make sense to encrypt temporary buckets. LEAVE THIS ALONE IF YOU DON'T KNOW WHAT YOU ARE DOING! NodeClientCore.fileForClientStats=File to store client statistics in NodeClientCore.fileForClientStatsLong=File to store client throttling statistics in (used to decide how often to send requests) NodeClientCore.lazyResume=Complete loading of persistent requests after startup? (Uses more memory) @@ -730,6 +736,10 @@ NodeClientCore.movingTempDirOnTheFlyNotSupported=Moving temp directory on the fly not supported at present NodeClientCore.persistentTempDir=Persistent temp files directory NodeClientCore.persistentTempDirLong=Name of directory to put persistent temp files in +NodeClientCore.maxRAMBucketSize=Maximum size of a RAMBucket +NodeClientCore.maxRAMBucketSizeLong=Maximum size of a RAMBucket (bigger buckets will be kept as files on the disk) +NodeClientCore.ramBucketPoolSize=Amount of RAM to dedicate to temporary buckets +NodeClientCore.ramBucketPoolSizeLong=Amount of RAM to dedicate to temporary buckets. The tradeoff is more memory usage against more IOs. NodeClientCore.startingUpTitle=Freenet is starting up NodeClientCore.startingUp=Please allow Freenet a few moments to complete the startup process, in the meantime some things may not work and the node may be slower than usual. NodeClientCore.startingUpShort=Freenet is starting up, some things may not work and the node may be slow. @@ -1050,6 +1060,8 @@ SimpleToadletServer.illegalCSSName=CSS name must not contain slashes or colons! SimpleToadletServer.panicButton=Show the panic button? SimpleToadletServer.panicButtonLong=Shows a 'panic button' on the queue page that will remove all requests with no confirmation. +SimpleToadletServer.passthroughMaxSize=Maximum size for transparent pass-through in fproxy +SimpleToadletServer.passthroughMaxSizeLong=Maximum size of a file for transparent pass-through in fproxy SimpleToadletServer.port=FProxy port SimpleToadletServer.portLong=The TCP port FProxy should listen on SimpleToadletServer.ssl=Enable SSL? Modified: branches/db4o/freenet/src/freenet/l10n/freenet.l10n.fr.properties =================================================================== --- branches/db4o/freenet/src/freenet/l10n/freenet.l10n.fr.properties 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/l10n/freenet.l10n.fr.properties 2008-09-24 20:42:20 UTC (rev 22823) @@ -285,6 +285,7 @@ FProxyToadlet.notEnoughMetaStrings=Pas assez de m?ta-donn?es FProxyToadlet.notFoundTitle=Introuvable FProxyToadlet.openAsText=${link}Cliquez ici${/link} pour ouvrir le fichier en texte brut (ceci ne devrait pr?senter aucun danger mais risque d'?tre illisible). +FProxyToadlet.openAsThawIndex=${link}Cliquer ici${/link} pour ouvrir ce fichier avec le navigateur d'index Thaw (lisez l'avertissement ci-dessus !). FProxyToadlet.openForce=${link}Cliquez ici${/link} pour ouvrir le fichier en tant que ${mime} (lisez l'avertissement ci-dessus !). FProxyToadlet.openForceDisk=${link}Cliquez ici${/link} pour force le navigateur ? enregistrer le fichier sur le disque. FProxyToadlet.openPossRSSAsForceDisk=${link}Cliquez ici${/link} pour essayer de forcer votre navigateur ? enregistrer ce fichier sur le disque (${bold}ceci peut ?tre dangereux${/bold} si vous utilisez Firefox 2.0.0, les versions suivantes n'ont pas de probl?me). @@ -719,6 +720,8 @@ Node.tooSmallMTU=MTU trop faible Node.tooSmallMTULong=Le MTU de votre connexion est de ${mtu} octets. Freenet a besoin d'un MTU de ${minMTU} au moins pour fonctionner correctement : les connexions seront lentes et peu fiables. Corrigez ce probl?me si possible. Node.tooSmallMTUShort=Probl?mes de connexion : Le MTU de votre connexion est trop faible pour Freenet. Attendez-vous ? des probl?mes. +Node.withAnnouncement=S'annoncer aux seednodes ? +Node.withAnnouncementLong=Laisser le noeud s'annoncer aux seednodes ? C'est indispensable mais c'est un risque? NodeClientCore.couldNotFindOrCreateDir=Impossible de trouver ou de cr?er le dossier NodeClientCore.downloadAllowedDirs=Les dossiers de t?l?chargement autoris?s sont NodeClientCore.downloadAllowedDirsLong=Liste de dossiers (s?par?s par des ';') o? le t?l?chargement est autoris?. "downloads" correspond au dossier de t?l?chargement, laissez-la vide pour n'autoriser aucun t?l?chargement sur le disque dur, "all" autorise les t?l?chargements partout ! @@ -836,6 +839,10 @@ PeersSayKeyBlownAlert.intro=Au moins un des noeuds auxquels vous ?tes connect? affirme que la cl? de mise ? jour est compromise ! Cela signifie qu'il est possible qu'un attaquant connaisse la cl? du syst?me de mise ? jour automatique et l'utilise pour essayer de vous pirater (si vous acceptez la mise ? jour) ! Le syst?me de mise ? jour automatique a ?t? d?sactiv?. Il est aussi possible que ces noeuds mentent d?lib?r?ment. PeersSayKeyBlownAlert.short=Certains noeuds disent que la cl? de mise ? jour automatique a ?t? compromise ! PeersSayKeyBlownAlert.titleWithCount=${count} noeud(s) affirme(nt) que la cl? de mise ? jour automatique est compromise ! +PluginConfig.configFile=Fichier de configuration des plugins +PluginConfig.configFileLong=Chemin du fichier de configuration des plugins +PluginConfig.installDir=Dossier d'installation des plugins +PluginConfig.installDirLong=Dossier d'installation des plugins PluginManager.cannotSetOnceLoaded=Impossible de d?finir la liste des plugins une fois d?marr? PluginManager.loadedOnStartup=Plugins ? charger au d?marrage PluginManager.loadedOnStartupLong=Classpath, nom et emplacement des plugins ? charger au d?marrage du node @@ -869,11 +876,15 @@ PproxyToadlet.changeReloadOnStartup=Changer PproxyToadlet.classNameTitle=Nom de Class PproxyToadlet.downloadNotAllowedFromRemoteServer=Le t?l?chargement de plugins n'est autoris? que depuis notre serveur. +PproxyToadlet.fileonly=Fichiers locaux uniquement PproxyToadlet.internalIDTitle=ID interne +PproxyToadlet.loadFreenetPlugin=Chargez un plugin non officiel depuis Freenet +PproxyToadlet.loadFreenetPluginText=Vous pouvez entrer la cl? Freenet d'un plugin que vous voulez charger. Ces plugins ne sont ni support?s ni m?me test?s par le projet. Si vous en chargez un, vous ?tes livr? ? vous m?me. +PproxyToadlet.loadFreenetURLLabel=Cl? du plugin PproxyToadlet.loadOfficialPlugin=Ajouter un plugin officiel PproxyToadlet.loadOfficialPluginLabel=Charger un plugin officiel PproxyToadlet.loadOfficialPluginText=Ces plugins sont h?berg?s sur les serveurs du projet Freenet. Nous pensons que ces plugins ne contiennent pas de failles de s?curit?, sans toutefois le garantir. -PproxyToadlet.loadOfficialPluginWarning=ATTENTION : Charger un plugin officiel implique de le t?l?charger sur internet (pas sur freenet). Un attaquant pourrait le d?tecter et peut-?tre interf?rer. Ne chargez pas de plugins si vous pensez qu'il y a un risque. +PproxyToadlet.loadOfficialPluginWarning=ATTENTION : Charger un plugin officiel implique de le t?l?charger sur internet (pas sur freenet). Ne chargez pas de plugins si vous pensez qu'il y a un risque. PproxyToadlet.loadOtherPlugin=Charger un plugin non-officiel PproxyToadlet.loadOtherPluginText=Vous pouvez entrer l'URL d'un plugin que vous voulez charger. Les plugins qui ne sont pas list?s ci-dessus ne sont pas support?s et leur s?curit? n'est pas v?rifi?e. Donc, si vous chargez un plugin ici, vous ?tes livr? ? vous m?me. PproxyToadlet.loadOtherURLLabel=URL du plugin @@ -1065,7 +1076,7 @@ SimpleToadletServer.sslLong=Activer SSL pour FProxy StartupToadlet.entropyErrorContent=Il n'y a pas assez d'entropy sur votre syst?me... Freenet ne d?marrera pas avant d'en avoir suffisament. StartupToadlet.entropyErrorTitle=Pas assez d'entropie disponible ! -StartupToadlet.isStartingUp=D?arrage de Freenet en cours, veuillez patienter. +StartupToadlet.isStartingUp=D?marrage de Freenet en cours, veuillez patienter. StartupToadlet.title=D?marrage de Freenet StaticToadlet.pathInvalidChars=Cette URI contient des caract?res interdits. StaticToadlet.pathNotFound=Le chemin sp?cifi? n'existe pas. Modified: branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-cn.properties =================================================================== --- branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-cn.properties 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-cn.properties 2008-09-24 20:42:20 UTC (rev 22823) @@ -878,7 +878,7 @@ PproxyToadlet.changeReloadOnStartup=?? PproxyToadlet.classNameTitle=???? PproxyToadlet.downloadNotAllowedFromRemoteServer=??????????????. -PproxyToadlet.fileonly=?????? +PproxyToadlet.fileonly=??????? PproxyToadlet.internalIDTitle=????? PproxyToadlet.loadFreenetPlugin=? Freenet ???????? PproxyToadlet.loadFreenetPluginText=????????????????? Freenet URI. ???????????, ??????????????, ??????????, ????????????. @@ -886,7 +886,7 @@ PproxyToadlet.loadOfficialPlugin=?????? PproxyToadlet.loadOfficialPluginLabel=?????? PproxyToadlet.loadOfficialPluginText=?????? Freenet ???????. ????????????????, ????????. -PproxyToadlet.loadOfficialPluginWarning=??: ????????????????, ??? Freenet ??. ?????????????, ?????. ?????????????, ??????????. +PproxyToadlet.loadOfficialPluginWarning=??: ????????????????, ??? Freenet ??. ?????????????, ??????????. PproxyToadlet.loadOtherPlugin=??????? PproxyToadlet.loadOtherPluginText=?????????????? URL. ???????????????????, ???????????????????. ????????????????????, ????????. PproxyToadlet.loadOtherURLLabel=??? URL Modified: branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-tw.properties =================================================================== --- branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-tw.properties 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-tw.properties 2008-09-24 20:42:20 UTC (rev 22823) @@ -877,7 +877,7 @@ PproxyToadlet.changeReloadOnStartup=?? PproxyToadlet.classNameTitle=???? PproxyToadlet.downloadNotAllowedFromRemoteServer=????????????????. -PproxyToadlet.fileonly=?????? +PproxyToadlet.fileonly=??????? PproxyToadlet.internalIDTitle=????? PproxyToadlet.loadFreenetPlugin=? Freenet ?????????? PproxyToadlet.loadFreenetPluginText=????????????????? Freenet URI. ???????????, ??????????????, ??????????, ????????????. @@ -885,7 +885,7 @@ PproxyToadlet.loadOfficialPlugin=?????? PproxyToadlet.loadOfficialPluginLabel=?????? PproxyToadlet.loadOfficialPluginText=???????? Freenet ???????. ????????????????, ????????. -PproxyToadlet.loadOfficialPluginWarning=??: ?????????????????, ??? Freenet ??. ?????????????, ?????. ?????????????, ??????????. +PproxyToadlet.loadOfficialPluginWarning=??: ?????????????????, ??? Freenet ??. ?????????????, ??????????. PproxyToadlet.loadOtherPlugin=??????? PproxyToadlet.loadOtherPluginText=?????????????? URL. ???????????????????, ???????????????????. ????????????????????, ????????. PproxyToadlet.loadOtherURLLabel=??? URL Modified: branches/db4o/freenet/src/freenet/node/ConfigurablePersister.java =================================================================== --- branches/db4o/freenet/src/freenet/node/ConfigurablePersister.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/ConfigurablePersister.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -22,7 +22,6 @@ public void set(String val) throws InvalidConfigValueException { setThrottles(val); } - }); String throttleFile = nodeConfig.getString(optionName); Modified: branches/db4o/freenet/src/freenet/node/FNPPacketMangler.java =================================================================== --- branches/db4o/freenet/src/freenet/node/FNPPacketMangler.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/FNPPacketMangler.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -43,7 +43,6 @@ import freenet.support.HexUtil; import freenet.support.Logger; import freenet.support.SimpleFieldSet; -import freenet.support.StringArray; import freenet.support.TimeUtil; import freenet.support.WouldBlockException; import freenet.support.io.NativeThread; @@ -95,7 +94,7 @@ /* How often shall we generate a new exponential and add it to the FIFO? */ public final static int DH_GENERATION_INTERVAL = 30000; // 30sec /* How big is the FIFO? */ - public final static int DH_CONTEXT_BUFFER_SIZE = 10; + public final static int DH_CONTEXT_BUFFER_SIZE = 20; /* * The FIFO itself * Get a lock on dhContextFIFO before touching it! @@ -1634,10 +1633,9 @@ */ private void sendAuthPacket(byte[] output, BlockCipher cipher, PeerNode pn, Peer replyTo, boolean anonAuth) { int length = output.length; - // FIXME shorten seednode phase 3/4 so it's within the limit -// if(length > sock.getMaxPacketSize()) { -// throw new IllegalStateException("Cannot send auth packet: too long: "+length); -// } + if(length > sock.getMaxPacketSize()) { + throw new IllegalStateException("Cannot send auth packet: too long: "+length); + } PCFBMode pcfb = PCFBMode.create(cipher); byte[] iv = new byte[pcfb.lengthIV()]; node.random.nextBytes(iv); @@ -2077,7 +2075,7 @@ alreadyReported[x] = mi.alreadyReportedBytes; x++; if(mi.cb != null) callbacksCount += mi.cb.length; - if(logMINOR) Logger.minor(this, "Sending: "+mi+" length "+data.length+" cb "+ StringArray.toString(mi.cb)+" reported "+mi.alreadyReportedBytes); + if(logMINOR) Logger.minor(this, "Sending: "+mi+" length "+data.length+" cb "+ Arrays.toString(mi.cb)+" reported "+mi.alreadyReportedBytes); length += (data.length + 2); } } @@ -2294,7 +2292,7 @@ if(logMINOR) { String log = "processOutgoingPreformatted("+Fields.hashCode(buf)+", "+offset+ ',' +length+ ',' +tracker+ ',' +packetNumber+ ','; if(callbacks == null) log += "null"; - else log += ""+callbacks.length+StringArray.toString(callbacks); // FIXME too verbose? + else log += ""+callbacks.length+Arrays.toString(callbacks); // FIXME too verbose? Logger.minor(this, log); } if((tracker == null) || (!tracker.pn.isConnected())) { @@ -2833,10 +2831,8 @@ // reset the authenticator cache authenticatorCache.clear(); } - if(logMINOR) - Logger.minor(this, "Reset the JFK transitent key because "+(isCacheTooBig ? ("the cache's capacity is exeeded ("+authenticatorCache.size()+')') : "it's time to rekey") + this); node.getTicker().queueTimedJob(transientKeyRekeyer, "JFKmaybeResetTransitentKey "+now, TRANSIENT_KEY_REKEYING_MIN_INTERVAL, false); - Logger.normal(this, "JFK's TransientKey has been changed and the message cache flushed."); + Logger.normal(this, "JFK's TransientKey has been changed and the message cache flushed because "+(isCacheTooBig ? ("the cache is oversized ("+authenticatorCache.size()+')') : "it's time to rekey")+ " on " + this); return true; } Modified: branches/db4o/freenet/src/freenet/node/FailureTable.java =================================================================== --- branches/db4o/freenet/src/freenet/node/FailureTable.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/FailureTable.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -98,12 +98,9 @@ FailureTableEntry entry; synchronized(this) { entry = (FailureTableEntry) entriesByKey.get(key); - if(entry == null) { + if(entry == null) entry = new FailureTableEntry(key); - entriesByKey.push(key, entry); - } else { - entriesByKey.push(key, entry); - } + entriesByKey.push(key, entry); trimEntries(now); } entry.failedTo(routedTo, timeout, now, htl); @@ -115,12 +112,10 @@ FailureTableEntry entry; synchronized(this) { entry = (FailureTableEntry) entriesByKey.get(key); - if(entry == null) { + if(entry == null) entry = new FailureTableEntry(key); - entriesByKey.push(key, entry); - } else { - entriesByKey.push(key, entry); - } + entriesByKey.push(key, entry); + trimEntries(now); } if(routedTo != null) Modified: branches/db4o/freenet/src/freenet/node/FailureTableEntry.java =================================================================== --- branches/db4o/freenet/src/freenet/node/FailureTableEntry.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/FailureTableEntry.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -8,7 +8,7 @@ import freenet.keys.Key; import freenet.support.Logger; -import freenet.support.StringArray; +import java.util.Arrays; class FailureTableEntry implements TimedOutNodesList { @@ -75,7 +75,7 @@ */ public void onFailure(short htl2, PeerNode[] requestors, PeerNode[] requestedFrom, int timeout, long now) { if(logMINOR) - Logger.minor(this, "onFailure("+htl2+",requestors="+StringArray.toString(requestors)+",requestedFrom="+StringArray.toString(requestedFrom)+",timeout="+timeout); + Logger.minor(this, "onFailure("+htl2+",requestors="+Arrays.toString(requestors)+",requestedFrom="+Arrays.toString(requestedFrom)+",timeout="+timeout); synchronized(this) { if(requestors != null) { for(int i=0;i<requestors.length;i++) Modified: branches/db4o/freenet/src/freenet/node/GlobalProbe.java =================================================================== --- branches/db4o/freenet/src/freenet/node/GlobalProbe.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/GlobalProbe.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -4,20 +4,20 @@ package freenet.node; import freenet.support.Logger; -import freenet.support.StringArray; +import java.util.Arrays; public class GlobalProbe implements Runnable { double lastLocation = 0.0; long lastTime; int lastHops; - boolean doneSomething = false; + private boolean doneSomething = false; final ProbeCallback cb; final Node node; int ctr; final int probeType; - GlobalProbe(Node n, int probeType) { + public GlobalProbe(Node n, int probeType) { this.node = n; this.probeType = probeType; cb = new ProbeCallback() { @@ -33,7 +33,7 @@ } public void onTrace(long uid, double target, double nearest, double best, short htl, short counter, double location, long nodeUID, double[] peerLocs, long[] peerUIDs, double[] locsNotVisited, short forkCount, short linearCount, String reason, long prevUID) { - String msg = "Probe trace: UID="+uid+" target="+target+" nearest="+nearest+" best="+best+" htl="+htl+" counter="+counter+" location="+location+" node UID="+nodeUID+" prev UID="+prevUID+" peers="+NodeDispatcher.peersUIDsToString(peerUIDs, peerLocs)+" locs not visited: "+StringArray.toString(locsNotVisited)+" fork count: "+forkCount+" linear count: "+linearCount+" from "+reason; + String msg = "Probe trace: UID="+uid+" target="+target+" nearest="+nearest+" best="+best+" htl="+htl+" counter="+counter+" location="+location+" node UID="+nodeUID+" prev UID="+prevUID+" peers="+NodeDispatcher.peersUIDsToString(peerUIDs, peerLocs)+" locs not visited: "+Arrays.toString(locsNotVisited)+" fork count: "+forkCount+" linear count: "+linearCount+" from "+reason; Logger.normal(this, msg); } @@ -100,13 +100,11 @@ private void output(double loc, int hops) { double estimatedNodes = ((double) (ctr+1)) / loc; Logger.error(this, "LOCATION "+ctr+": " + loc+" - estimated nodes: "+estimatedNodes+" ("+hops+" hops)"); - System.out.println("LOCATION "+ctr+": " + loc+" - estimated nodes: "+estimatedNodes+" ("+hops+" hops)"); + System.err.println("LOCATION "+ctr+": " + loc+" - estimated nodes: "+estimatedNodes+" ("+hops+" hops)"); } private void error(String string) { Logger.error(this, string); - System.out.println("GlobalProbe error: "+string); + System.err.println("GlobalProbe error: "+string); } - - } Modified: branches/db4o/freenet/src/freenet/node/IPDetectorPluginManager.java =================================================================== --- branches/db4o/freenet/src/freenet/node/IPDetectorPluginManager.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/IPDetectorPluginManager.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -277,7 +277,7 @@ */ public int[] getUDPPortsNotForwarded() { OpennetManager om = node.getOpennet(); - int darknetStatus = node.darknetCrypto.getDetectedConnectivityStatus(); + int darknetStatus = (node.peers.anyDarknetPeers() ? node.darknetCrypto.getDetectedConnectivityStatus() : AddressTracker.MAYBE_PORT_FORWARDED); int opennetStatus = om == null ? AddressTracker.DONT_KNOW : om.crypto.getDetectedConnectivityStatus(); if(om == null || opennetStatus > AddressTracker.DONT_KNOW) { if(darknetStatus > AddressTracker.DONT_KNOW) { @@ -289,7 +289,7 @@ if(darknetStatus > AddressTracker.DONT_KNOW) { return new int[] { (opennetStatus < AddressTracker.DONT_KNOW ? -1 : 1 ) * om.crypto.portNumber }; } else { - return new int[] { (darknetStatus < AddressTracker.DONT_KNOW ? -1 : 1 ) * node.getDarknetPortNumber(), + return new int[] { ((darknetStatus < AddressTracker.DONT_KNOW) ? -1 : 1 ) * node.getDarknetPortNumber(), (opennetStatus < AddressTracker.DONT_KNOW ? -1 : 1 ) * om.crypto.portNumber }; } } Modified: branches/db4o/freenet/src/freenet/node/LoggingConfigHandler.java =================================================================== --- branches/db4o/freenet/src/freenet/node/LoggingConfigHandler.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/LoggingConfigHandler.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -8,6 +8,7 @@ import freenet.config.EnumerableOptionCallback; import freenet.config.InvalidConfigValueException; +import freenet.config.NodeNeedRestartException; import freenet.config.OptionFormatException; import freenet.config.SubConfig; import freenet.support.Executor; @@ -23,7 +24,7 @@ import freenet.support.api.StringCallback; public class LoggingConfigHandler { - private static class PriorityCallback implements StringCallback, EnumerableOptionCallback { + private static class PriorityCallback extends StringCallback implements EnumerableOptionCallback { private final String[] possibleValues = new String[]{ "ERROR", "NORMAL", "MINOR", "DEBUG" }; public String get() { @@ -45,7 +46,7 @@ public void setPossibleValues(String[] val) { throw new NullPointerException("Should not happen!"); - } + } } protected static final String LOG_PREFIX = "freenet"; @@ -64,10 +65,10 @@ loggingConfig.register("enabled", true, 1, true, false, "LogConfigHandler.enabled", "LogConfigHandler.enabledLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { return fileLoggerHook != null; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { if(val == (fileLoggerHook != null)) return; if(!val) { disableLogger(); @@ -110,11 +111,12 @@ config.register("maxZippedLogsSize", "128M", 3, true, true, "LogConfigHandler.maxZippedLogsSize", "LogConfigHandler.maxZippedLogsSizeLong", new LongCallback() { - public long get() { + public Long get() { return maxZippedLogsSize; } - public void set(long val) throws InvalidConfigValueException { - if(val < 0) val = 0; + public void set(Long val) throws InvalidConfigValueException { + if (val < 0) + val = 0L; maxZippedLogsSize = val; if(fileLoggerHook != null) { fileLoggerHook.setMaxOldLogsSize(val); @@ -179,11 +181,12 @@ // max cached bytes in RAM config.register("maxCachedBytes", "10M", 6, true, false, "LogConfigHandler.maxCachedBytes", "LogConfigHandler.maxCachedBytesLong", new LongCallback() { - public long get() { + public Long get() { return maxCachedLogBytes; } - public void set(long val) throws InvalidConfigValueException { - if(val < 0) val = 0; + public void set(Long val) throws InvalidConfigValueException { + if (val < 0) + val = 0L; if(val == maxCachedLogBytes) return; maxCachedLogBytes = val; if(fileLoggerHook != null) @@ -196,10 +199,10 @@ // max cached lines in RAM config.register("maxCachedLines", "100k", 7, true, false, "LogConfigHandler.maxCachedLines", "LogConfigHandler.maxCachedLinesLong", new IntCallback() { - public int get() { + public Integer get() { return maxCachedLogLines; } - public void set(int val) throws InvalidConfigValueException { + public void set(Integer val) throws InvalidConfigValueException { if(val < 0) val = 0; if(val == maxCachedLogLines) return; maxCachedLogLines = val; @@ -237,6 +240,10 @@ } catch (InvalidConfigValueException e2) { System.err.println("Invalid config value for logger.priority in config file: "+config.getString("priority")); // Leave it at the default. + } catch (NodeNeedRestartException e) { + // impossible + System.err.println("impossible NodeNeedRestartException for logger.priority in config file: " + + config.getString("priority")); } FileLoggerHook hook; try { @@ -344,7 +351,8 @@ return maxZippedLogsSize; } - public void setMaxZippedLogFiles(String maxSizeAsString) throws InvalidConfigValueException { + public void setMaxZippedLogFiles(String maxSizeAsString) throws InvalidConfigValueException, + NodeNeedRestartException { config.set("maxZippedLogsSize", maxSizeAsString); } Modified: branches/db4o/freenet/src/freenet/node/Node.java =================================================================== --- branches/db4o/freenet/src/freenet/node/Node.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/Node.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -3,6 +3,7 @@ import java.io.BufferedReader; import java.io.File; +import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; @@ -45,6 +46,7 @@ import freenet.config.FreenetFilePersistentConfig; import freenet.config.InvalidConfigValueException; import freenet.config.LongOption; +import freenet.config.NodeNeedRestartException; import freenet.config.PersistentConfig; import freenet.config.SubConfig; import freenet.crypt.DSAPublicKey; @@ -127,7 +129,6 @@ import freenet.support.io.FileUtil; import freenet.support.io.NativeThread; import freenet.support.transport.ip.HostnameSyntaxException; -import java.io.FileFilter; /** * @author amphibian @@ -141,7 +142,7 @@ private static TimeSkewDetectedUserAlert timeSkewDetectedUserAlert; private final static ClockProblemDetectedUserAlert clockProblemDetectedUserAlert = new ClockProblemDetectedUserAlert(); - public class NodeNameCallback implements StringCallback { + public class NodeNameCallback extends StringCallback { GetPubkey node; NodeNameCallback(GetPubkey n) { @@ -179,30 +180,40 @@ } } - private class StoreTypeCallback implements StringCallback, EnumerableOptionCallback { + private class StoreTypeCallback extends StringCallback implements EnumerableOptionCallback { + private String cachedStoreType; public String get() { - return storeType; + if (cachedStoreType == null) + cachedStoreType = storeType; + return cachedStoreType; } - public void set(String val) throws InvalidConfigValueException { - throw new InvalidConfigValueException("Store type cannot be changed on the fly"); + public void set(String val) throws InvalidConfigValueException, NodeNeedRestartException { + boolean found = false; + for (String p : getPossibleValues()) { + if (p.equals(val)) { + found = true; + break; + } + } + if (!found) + throw new InvalidConfigValueException("Invalid store type"); + + cachedStoreType = val; + throw new NodeNeedRestartException("Store type cannot be changed on the fly"); } public String[] getPossibleValues() { - return new String[] { - "bdb-index", - "ram" - }; + return new String[] { "bdb-index", "ram" }; } public void setPossibleValues(String[] val) { throw new UnsupportedOperationException(); } - } - private static class L10nCallback implements StringCallback, EnumerableOptionCallback { + private static class L10nCallback extends StringCallback implements EnumerableOptionCallback { public String get() { return L10n.mapLanguageNameToLongName(L10n.getSelectedLanguage()); @@ -483,7 +494,6 @@ // Things that's needed to keep track of public final PluginManager pluginManager; - public freenet.oldplugins.plugin.PluginManager pluginManager2; // Helpers public final InetAddress localhostAddress; @@ -777,6 +787,9 @@ // Don't translate the below as very few users will use it. throw new InvalidConfigValueException("Moving node directory on the fly not supported at present"); } + public boolean isReadOnly() { + return true; + } }); nodeDir = new File(nodeConfig.getString("nodeDir")); @@ -910,11 +923,11 @@ nodeConfig.register("disableProbabilisticHTLs", false, sortOrder++, true, false, "Node.disablePHTLS", "Node.disablePHTLSLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { return disableProbabilisticHTLs; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { disableProbabilisticHTLs = val; } @@ -924,11 +937,11 @@ nodeConfig.register("maxHTL", DEFAULT_MAX_HTL, sortOrder++, true, false, "Node.maxHTL", "Node.maxHTLLong", new ShortCallback() { - public short get() { + public Short get() { return maxHTL; } - public void set(short val) throws InvalidConfigValueException { + public void set(Short val) throws InvalidConfigValueException { if(maxHTL < 0) throw new InvalidConfigValueException("Impossible max HTL"); maxHTL = val; } @@ -952,63 +965,75 @@ nodeConfig.register("enableARKs", true, sortOrder++, true, false, "Node.enableARKs", "Node.enableARKsLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { return enableARKs; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { throw new InvalidConfigValueException("Cannot change on the fly"); } - + + public boolean isReadOnly() { + return true; + } }); enableARKs = nodeConfig.getBoolean("enableARKs"); nodeConfig.register("enablePerNodeFailureTables", true, sortOrder++, true, false, "Node.enablePerNodeFailureTables", "Node.enablePerNodeFailureTablesLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { return enablePerNodeFailureTables; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { throw new InvalidConfigValueException("Cannot change on the fly"); } - + + public boolean isReadOnly() { + return true; + } }); enablePerNodeFailureTables = nodeConfig.getBoolean("enablePerNodeFailureTables"); nodeConfig.register("enableULPRDataPropagation", true, sortOrder++, true, false, "Node.enableULPRDataPropagation", "Node.enableULPRDataPropagationLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { return enableULPRDataPropagation; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { throw new InvalidConfigValueException("Cannot change on the fly"); } - + + public boolean isReadOnly() { + return true; + } }); enableULPRDataPropagation = nodeConfig.getBoolean("enableULPRDataPropagation"); nodeConfig.register("enableSwapping", true, sortOrder++, true, false, "Node.enableSwapping", "Node.enableSwappingLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { return enableSwapping; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { throw new InvalidConfigValueException("Cannot change on the fly"); } - + + public boolean isReadOnly() { + return true; + } }); enableSwapping = nodeConfig.getBoolean("enableSwapping"); nodeConfig.register("publishOurPeersLocation", false, sortOrder++, true, false, "Node.publishOurPeersLocation", "Node.publishOurPeersLocationLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { return publishOurPeersLocation; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { publishOurPeersLocation = val; } }); @@ -1016,22 +1041,22 @@ nodeConfig.register("routeAccordingToOurPeersLocation", false, sortOrder++, true, false, "Node.routeAccordingToOurPeersLocation", "Node.routeAccordingToOurPeersLocationLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { return routeAccordingToOurPeersLocation; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { routeAccordingToOurPeersLocation = val; } }); routeAccordingToOurPeersLocation = nodeConfig.getBoolean("routeAccordingToOurPeersLocation"); nodeConfig.register("enableSwapQueueing", true, sortOrder++, true, false, "Node.enableSwapQueueing", "Node.enableSwapQueueingLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { return enableSwapQueueing; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { enableSwapQueueing = val; } @@ -1039,11 +1064,11 @@ enableSwapQueueing = nodeConfig.getBoolean("enableSwapQueueing"); nodeConfig.register("enablePacketCoalescing", true, sortOrder++, true, false, "Node.enablePacketCoalescing", "Node.enablePacketCoalescingLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { return enablePacketCoalescing; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { enablePacketCoalescing = val; } @@ -1088,11 +1113,11 @@ // Bandwidth limit nodeConfig.register("outputBandwidthLimit", "15K", sortOrder++, false, true, "Node.outBWLimit", "Node.outBWLimitLong", new IntCallback() { - public int get() { + public Integer get() { //return BlockTransmitter.getHardBandwidthLimit(); return outputBandwidthLimit; } - public void set(int obwLimit) throws InvalidConfigValueException { + public void set(Integer obwLimit) throws InvalidConfigValueException { if(obwLimit <= 0) throw new InvalidConfigValueException(l10n("bwlimitMustBePositive")); synchronized(Node.this) { outputBandwidthLimit = obwLimit; @@ -1113,11 +1138,11 @@ outputThrottle = new DoubleTokenBucket(obwLimit/2, (1000L*1000L*1000L) / obwLimit, obwLimit/2, 0.8); nodeConfig.register("inputBandwidthLimit", "-1", sortOrder++, false, true, "Node.inBWLimit", "Node.inBWLimitLong", new IntCallback() { - public int get() { + public Integer get() { if(inputLimitDefault) return -1; return inputBandwidthLimit; } - public void set(int ibwLimit) throws InvalidConfigValueException { + public void set(Integer ibwLimit) throws InvalidConfigValueException { synchronized(Node.this) { if(ibwLimit == -1) { inputLimitDefault = true; @@ -1142,11 +1167,11 @@ nodeConfig.register("throttleLocalTraffic", false, sortOrder++, true, false, "Node.throttleLocalTraffic", "Node.throttleLocalTrafficLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { return throttleLocalData; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { throttleLocalData = val; } @@ -1177,7 +1202,9 @@ try { logConfigHandler.setMaxZippedLogFiles(TESTNET_MIN_MAX_ZIPPED_LOGFILES_STRING); } catch (InvalidConfigValueException e) { - throw new Error("Impossible: "+e); + throw new Error("Impossible: " + e, e); + } catch (NodeNeedRestartException e) { + throw new Error("Impossible: " + e, e); } } } else { @@ -1245,10 +1272,10 @@ final SubConfig opennetConfig = new SubConfig("node.opennet", config); opennetConfig.register("connectToSeednodes", true, 0, true, false, "Node.withAnnouncement", "Node.withAnnouncementLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { return isAllowedToConnectToSeednodes; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { if(val == get()) return; synchronized(Node.this) { if(opennet != null) @@ -1257,17 +1284,21 @@ isAllowedToConnectToSeednodes = val; } } + + public boolean isReadOnly() { + return opennet != null; + } }); isAllowedToConnectToSeednodes = opennetConfig.getBoolean("connectToSeednodes"); // Can be enabled on the fly opennetConfig.register("enabled", false, 0, false, true, "Node.opennetEnabled", "Node.opennetEnabledLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { synchronized(Node.this) { return opennet != null; } } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { OpennetManager o; synchronized(Node.this) { if(val == (opennet != null)) return; @@ -1292,10 +1323,10 @@ opennetConfig.register("maxOpennetPeers", "20", 1, true, false, "Node.maxOpennetPeers", "Node.maxOpennetPeersLong", new IntCallback() { - public int get() { + public Integer get() { return maxOpennetPeers; } - public void set(int inputMaxOpennetPeers) throws InvalidConfigValueException { + public void set(Integer inputMaxOpennetPeers) throws InvalidConfigValueException { if(inputMaxOpennetPeers < 0) throw new InvalidConfigValueException(l10n("mustBePositive")); if(inputMaxOpennetPeers > 20) throw new InvalidConfigValueException(l10n("maxOpennetPeersMustBeTwentyOrLess")); maxOpennetPeers = inputMaxOpennetPeers; @@ -1320,11 +1351,11 @@ opennetConfig.register("acceptSeedConnections", true, 2, true, true, "Node.acceptSeedConnectionsShort", "Node.acceptSeedConnections", new BooleanCallback() { - public boolean get() { + public Boolean get() { return acceptSeedConnections; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { acceptSeedConnections = val; } @@ -1337,13 +1368,13 @@ nodeConfig.register("passOpennetPeersThroughDarknet", true, sortOrder++, true, false, "Node.passOpennetPeersThroughDarknet", "Node.passOpennetPeersThroughDarknetLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { synchronized(Node.this) { return passOpennetRefsThroughDarknet; } } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { synchronized(Node.this) { passOpennetRefsThroughDarknet = val; } @@ -1364,6 +1395,9 @@ // FIXME throw new InvalidConfigValueException("Moving extra peer data directory on the fly not supported at present"); } + public boolean isReadOnly() { + return true; + } }); extraPeerDataDir = new File(nodeConfig.getString("extraPeerDataDir")); if(!((extraPeerDataDir.exists() && extraPeerDataDir.isDirectory()) || (extraPeerDataDir.mkdir()))) { @@ -1381,13 +1415,13 @@ nodeConfig.register("storeForceBigShrinks", false, sortOrder++, true, false, "Node.forceBigShrink", "Node.forceBigShrinkLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { synchronized(Node.this) { return storeForceBigShrinks; } } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { synchronized(Node.this) { storeForceBigShrinks = val; } @@ -1402,11 +1436,11 @@ nodeConfig.register("storeSize", "1G", sortOrder++, false, true, "Node.storeSize", "Node.storeSizeLong", new LongCallback() { - public long get() { + public Long get() { return maxTotalDatastoreSize; } - public void set(long storeSize) throws InvalidConfigValueException { + public void set(Long storeSize) throws InvalidConfigValueException { if((storeSize < 0) || (storeSize < (32 * 1024 * 1024))) throw new InvalidConfigValueException(l10n("invalidStoreSize")); long newMaxStoreKeys = storeSize / sizePerKey; @@ -1459,6 +1493,9 @@ // FIXME throw new InvalidConfigValueException("Moving datastore on the fly not supported at present"); } + public boolean isReadOnly() { + return true; + } }); final String suffix = "-" + getDarknetPortNumber(); @@ -1610,11 +1647,11 @@ nodeConfig.register("databaseMaxMemory", "20M", sortOrder++, true, false, "Node.databaseMemory", "Node.databaseMemoryLong", new LongCallback() { - public long get() { + public Long get() { return databaseMaxMemory; } - public void set(long val) throws InvalidConfigValueException { + public void set(Long val) throws InvalidConfigValueException { if(val < 0) throw new InvalidConfigValueException(l10n("mustBePositive")); else { @@ -1737,14 +1774,13 @@ nodeConfig.register("disableHangCheckers", false, sortOrder++, true, false, "Node.disableHangCheckers", "Node.disableHangCheckersLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { return disableHangCheckers; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { disableHangCheckers = val; } - }); disableHangCheckers = nodeConfig.getBoolean("disableHangCheckers"); @@ -1756,8 +1792,7 @@ Logger.normal(this, "Initializing Plugin Manager"); System.out.println("Initializing Plugin Manager"); pluginManager = new PluginManager(this); - pluginManager2 = new freenet.oldplugins.plugin.PluginManager(this); - + FetchContext ctx = clientCore.makeClient((short)0, true).getFetchContext(); ctx.allowSplitfiles = false; @@ -2183,16 +2218,14 @@ } void addTransferringRequestHandler(long id) { - Long l = new Long(id); synchronized(transferringRequestHandlers) { - transferringRequestHandlers.add(l); + transferringRequestHandlers.add(id); } } void removeTransferringRequestHandler(long id) { - Long l = new Long(id); synchronized(transferringRequestHandlers) { - transferringRequestHandlers.remove(l); + transferringRequestHandlers.remove(id); } } @@ -2527,9 +2560,8 @@ } public boolean lockUID(long uid, boolean ssk, boolean insert, boolean offerReply, boolean local) { - Long l = new Long(uid); synchronized(runningUIDs) { - if(!runningUIDs.add(l)) { + if(!runningUIDs.add(uid)) { // Already present. return false; } @@ -2538,23 +2570,22 @@ HashSet set = getUIDTracker(ssk, insert, offerReply, local); synchronized(set) { if(logMINOR) Logger.minor(this, "Locking "+uid+" ssk="+ssk+" insert="+insert+" offerReply="+offerReply+" local="+local+" size="+set.size()); - set.add(l); + set.add(uid); if(logMINOR) Logger.minor(this, "Locked "+uid+" ssk="+ssk+" insert="+insert+" offerReply="+offerReply+" local="+local+" size="+set.size()); } return true; } public void unlockUID(long uid, boolean ssk, boolean insert, boolean canFail, boolean offerReply, boolean local) { - Long l = new Long(uid); completed(uid); HashSet set = getUIDTracker(ssk, insert, offerReply, local); synchronized(set) { if(logMINOR) Logger.minor(this, "Unlocking "+uid+" ssk="+ssk+" insert="+insert+" offerReply="+offerReply+", local="+local+" size="+set.size()); - set.remove(l); + set.remove(uid); if(logMINOR) Logger.minor(this, "Unlocked "+uid+" ssk="+ssk+" insert="+insert+" offerReply="+offerReply+", local="+local+" size="+set.size()); } synchronized(runningUIDs) { - if(!runningUIDs.remove(l) && !canFail) + if(!runningUIDs.remove(uid) && !canFail) throw new IllegalStateException("Could not unlock "+uid+ '!'); } } @@ -2737,7 +2768,7 @@ */ public boolean recentlyCompleted(long id) { synchronized (recentlyCompletedIDs) { - return recentlyCompletedIDs.contains(new Long(id)); + return recentlyCompletedIDs.contains(id); } } @@ -2746,7 +2777,7 @@ */ void completed(long id) { synchronized (recentlyCompletedIDs) { - recentlyCompletedIDs.push(new Long(id)); + recentlyCompletedIDs.push(id); while(recentlyCompletedIDs.size() > MAX_RECENTLY_COMPLETED_IDS) recentlyCompletedIDs.pop(); } @@ -3235,7 +3266,7 @@ } } - public void setName(String key) throws InvalidConfigValueException { + public void setName(String key) throws InvalidConfigValueException, NodeNeedRestartException { config.get("node").getOption("name").setValue(key); } Modified: branches/db4o/freenet/src/freenet/node/NodeClientCore.java =================================================================== --- branches/db4o/freenet/src/freenet/node/NodeClientCore.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/NodeClientCore.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -67,14 +67,12 @@ import freenet.support.api.BooleanCallback; import freenet.support.api.Bucket; import freenet.support.api.IntCallback; -import freenet.support.api.BucketFactory; +import freenet.support.api.LongCallback; import freenet.support.api.StringArrCallback; import freenet.support.api.StringCallback; import freenet.support.io.FileUtil; import freenet.support.io.FilenameGenerator; import freenet.support.io.NativeThread; -import freenet.support.io.PaddedEphemerallyEncryptedBucketFactory; -import freenet.support.io.PersistentEncryptedTempBucketFactory; import freenet.support.io.PersistentTempBucketFactory; import freenet.support.io.TempBucketFactory; @@ -98,14 +96,13 @@ private boolean uploadAllowedEverywhere; public final FilenameGenerator tempFilenameGenerator; public final FilenameGenerator persistentFilenameGenerator; - public final BucketFactory tempBucketFactory; + public final TempBucketFactory tempBucketFactory; + public final PersistentTempBucketFactory persistentTempBucketFactory; public final Node node; final NodeStats nodeStats; public final RandomSource random; final File tempDir; // Persistent temporary buckets public final FECQueue fecQueue; - public final PersistentTempBucketFactory persistentTempBucketFactory; - public final PersistentEncryptedTempBucketFactory persistentEncryptedTempBucketFactory; public final UserAlertManager alerts; final TextModeClientInterfaceServer tmci; TextModeClientInterface directTMCI; @@ -180,6 +177,9 @@ // FIXME throw new InvalidConfigValueException(l10n("movingTempDirOnTheFlyNotSupported")); } + public boolean isReadOnly() { + return true; + } }); tempDir = new File(nodeConfig.getString("tempDir")); @@ -195,10 +195,21 @@ throw new NodeInitException(NodeInitException.EXIT_BAD_TEMP_DIR, msg); } - archiveManager = new ArchiveManager(MAX_ARCHIVE_HANDLERS, MAX_CACHED_ARCHIVE_DATA, MAX_ARCHIVE_SIZE, MAX_ARCHIVED_FILE_SIZE, MAX_CACHED_ELEMENTS, random, node.fastWeakRandom, tempFilenameGenerator); uskManager = new USKManager(this); // Persistent temp files + nodeConfig.register("encryptPersistentTempBuckets", true, sortOrder++, true, false, "NodeClientCore.encryptPersistentTempBuckets", "NodeClientCore.encryptPersistentTempBucketsLong", new BooleanCallback() { + + public Boolean get() { + return (persistentTempBucketFactory == null ? true : persistentTempBucketFactory.isEncrypting()); + } + + public void set(Boolean val) throws InvalidConfigValueException { + if((val == get()) || (persistentTempBucketFactory == null)) return; + persistentTempBucketFactory.setEncryption(val); + } + }); + nodeConfig.register("persistentTempDir", new File(nodeDir, "persistent-temp-" + portNumber).toString(), sortOrder++, true, false, "NodeClientCore.persistentTempDir", "NodeClientCore.persistentTempDirLong", new StringCallback() { @@ -212,32 +223,68 @@ // FIXME throw new InvalidConfigValueException("Moving persistent temp directory on the fly not supported at present"); } + public boolean isReadOnly() { + return true; + } }); try { File dir = new File(nodeConfig.getString("persistentTempDir")); String prefix = "freenet-temp-"; - persistentTempBucketFactory = PersistentTempBucketFactory.load(dir, prefix, random, node.fastWeakRandom, container, node.nodeDBHandle); + persistentTempBucketFactory = PersistentTempBucketFactory.load(dir, prefix, random, node.fastWeakRandom, container, node.nodeDBHandle, nodeConfig.getBoolean("encryptPersistentTempBuckets")); persistentTempBucketFactory.init(dir, prefix, random, node.fastWeakRandom); - persistentEncryptedTempBucketFactory = PersistentEncryptedTempBucketFactory.load(persistentTempBucketFactory, container); persistentFilenameGenerator = persistentTempBucketFactory.fg; } catch(IOException e2) { String msg = "Could not find or create persistent temporary directory"; throw new NodeInitException(NodeInitException.EXIT_BAD_TEMP_DIR, msg); } - tempBucketFactory = new PaddedEphemerallyEncryptedBucketFactory(new TempBucketFactory(tempFilenameGenerator), random, node.fastWeakRandom, 1024); - - healingQueue = new SimpleHealingQueue( - new InsertContext(tempBucketFactory, tempBucketFactory, persistentTempBucketFactory, - 0, 2, 1, 0, 0, new SimpleEventProducer(), - !Node.DONT_CACHE_LOCAL_REQUESTS), RequestStarter.PREFETCH_PRIORITY_CLASS, 512 /* FIXME make configurable */); - clientContext = new ClientContext(this); storeChecker.setContext(clientContext); requestStarters = new RequestStarterGroup(node, this, portNumber, random, config, throttleFS, clientContext); clientContext.init(requestStarters); InsertCompressor.load(container, clientContext); + nodeConfig.register("maxRAMBucketSize", "32KiB", sortOrder++, true, false, "NodeClientCore.maxRAMBucketSize", "NodeClientCore.maxRAMBucketSizeLong", new LongCallback() { + + public Long get() { + return (tempBucketFactory == null ? 0 : tempBucketFactory.getMaxRAMBucketSize()); + } + + public void set(Long val) throws InvalidConfigValueException { + if((val == get()) || (tempBucketFactory == null)) return; + tempBucketFactory.setMaxRAMBucketSize(val); + } + }); + nodeConfig.register("RAMBucketPoolSize", "10MiB", sortOrder++, true, false, "NodeClientCore.ramBucketPoolSize", "NodeClientCore.ramBucketPoolSizeLong", new LongCallback() { + + public Long get() { + return (tempBucketFactory == null ? 0 : tempBucketFactory.getMaxRamUsed()); + } + + public void set(Long val) throws InvalidConfigValueException { + if((val == get()) || (tempBucketFactory == null)) return; + tempBucketFactory.setMaxRamUsed(val); + } + }); + + nodeConfig.register("encryptTempBuckets", true, sortOrder++, true, false, "NodeClientCore.encryptTempBuckets", "NodeClientCore.encryptTempBucketsLong", new BooleanCallback() { + + public Boolean get() { + return (tempBucketFactory == null ? true : tempBucketFactory.isEncrypting()); + } + + public void set(Boolean val) throws InvalidConfigValueException { + if((val == get()) || (tempBucketFactory == null)) return; + tempBucketFactory.setEncryption(val); + } + }); + tempBucketFactory = new TempBucketFactory(tempFilenameGenerator, nodeConfig.getLong("maxRAMBucketSize"), nodeConfig.getLong("RAMBucketPoolSize"), random, node.fastWeakRandom, nodeConfig.getBoolean("encryptTempBuckets")); + + healingQueue = new SimpleHealingQueue( + new InsertContext(tempBucketFactory, tempBucketFactory, persistentTempBucketFactory, + 0, 2, 1, 0, 0, new SimpleEventProducer(), + !Node.DONT_CACHE_LOCAL_REQUESTS), RequestStarter.PREFETCH_PRIORITY_CLASS, 512 /* FIXME make configurable */); + // Downloads directory nodeConfig.register("downloadsDir", "downloads", sortOrder++, true, true, "NodeClientCore.downloadDir", "NodeClientCore.downloadDirLong", new StringCallback() { @@ -308,6 +355,7 @@ }); setUploadAllowedDirs(nodeConfig.getStringArr("uploadAllowedDirs")); + archiveManager = new ArchiveManager(MAX_ARCHIVE_HANDLERS, MAX_CACHED_ARCHIVE_DATA, MAX_ARCHIVE_SIZE, MAX_ARCHIVED_FILE_SIZE, MAX_CACHED_ELEMENTS, tempBucketFactory); Logger.normal(this, "Initializing USK Manager"); System.out.println("Initializing USK Manager"); uskManager.init(container, clientContext); @@ -315,11 +363,11 @@ nodeConfig.register("lazyResume", false, sortOrder++, true, false, "NodeClientCore.lazyResume", "NodeClientCore.lazyResumeLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { return lazyResume; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { synchronized(NodeClientCore.this) { lazyResume = val; } @@ -331,11 +379,11 @@ nodeConfig.register("maxBackgroundUSKFetchers", "64", sortOrder++, true, false, "NodeClientCore.maxUSKFetchers", "NodeClientCore.maxUSKFetchersLong", new IntCallback() { - public int get() { + public Integer get() { return maxBackgroundUSKFetchers; } - public void set(int uskFetch) throws InvalidConfigValueException { + public void set(Integer uskFetch) throws InvalidConfigValueException { if(uskFetch <= 0) throw new InvalidConfigValueException(l10n("maxUSKFetchersMustBeGreaterThanZero")); maxBackgroundUSKFetchers = uskFetch; Modified: branches/db4o/freenet/src/freenet/node/NodeCrypto.java =================================================================== --- branches/db4o/freenet/src/freenet/node/NodeCrypto.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/NodeCrypto.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -36,7 +36,6 @@ import freenet.keys.InsertableClientSSK; import freenet.support.Base64; import freenet.support.Fields; -import freenet.support.HexUtil; import freenet.support.IllegalBase64Exception; import freenet.support.Logger; import freenet.support.SimpleFieldSet; @@ -357,9 +356,8 @@ BigInteger m = new BigInteger(1, SHA256.digest(ref)); if(logMINOR) Logger.minor(this, "m = "+m.toString(16)); DSASignature _signature = DSA.sign(cryptoGroup, privKey, m, random); - // FIXME remove this ... eventually - if(!DSA.verify(pubKey, _signature, m, false)) - Logger.error(this, "Signature failed!"); + if(logMINOR && !DSA.verify(pubKey, _signature, m, false)) + throw new NodeInitException(NodeInitException.EXIT_EXCEPTION_TO_DEBUG, mySignedReference); return _signature; } catch(UnsupportedEncodingException e){ //duh ? @@ -370,13 +368,9 @@ } } - public static boolean DISABLE_GROUP_STRIP = false; - private byte[] myCompressedRef(boolean setup, boolean heavySetup, boolean forARK) { SimpleFieldSet fs = exportPublicFieldSet(setup, heavySetup, forARK); - // TODO: we should change that to ((setup || heavySetup) && !forARK) when all the nodes have the new code - boolean shouldStripGroup = heavySetup && Global.DSAgroupBigA.equals(cryptoGroup); - if(DISABLE_GROUP_STRIP) shouldStripGroup = false; + boolean shouldStripGroup = ((setup || heavySetup) && !forARK) && Global.DSAgroupBigA.equals(cryptoGroup); if(shouldStripGroup) fs.removeSubset("dsaGroup"); Modified: branches/db4o/freenet/src/freenet/node/NodeCryptoConfig.java =================================================================== --- branches/db4o/freenet/src/freenet/node/NodeCryptoConfig.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/NodeCryptoConfig.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -50,14 +50,14 @@ NodeCryptoConfig(SubConfig config, int sortOrder, boolean onePerIP) throws NodeInitException { config.register("listenPort", -1 /* means random */, sortOrder++, true, true, "Node.port", "Node.portLong", new IntCallback() { - public int get() { + public Integer get() { synchronized(NodeCryptoConfig.class) { if(crypto != null) portNumber = crypto.portNumber; return portNumber; } } - public void set(int val) throws InvalidConfigValueException { + public void set(Integer val) throws InvalidConfigValueException { if(portNumber < -1 || portNumber == 0 || portNumber > 65535) { throw new InvalidConfigValueException("Invalid port number"); @@ -73,6 +73,9 @@ portNumber = val; } } + public boolean isReadOnly() { + return true; + } }); try{ @@ -97,13 +100,13 @@ config.register("testingDropPacketsEvery", 0, sortOrder++, true, false, "Node.dropPacketEvery", "Node.dropPacketEveryLong", new IntCallback() { - public int get() { + public Integer get() { synchronized(NodeCryptoConfig.this) { return dropProbability; } } - public void set(int val) throws InvalidConfigValueException { + public void set(Integer val) throws InvalidConfigValueException { if(val < 0) throw new InvalidConfigValueException("testingDropPacketsEvery must not be negative"); synchronized(NodeCryptoConfig.this) { if(val == dropProbability) return; @@ -111,7 +114,7 @@ if(crypto == null) return; } crypto.onSetDropProbability(val); - } + } }); dropProbability = config.getInt("testingDropPacketsEvery"); @@ -119,13 +122,13 @@ config.register("oneConnectionPerIP", onePerIP, sortOrder++, true, false, "Node.oneConnectionPerIP", "Node.oneConnectionPerIPLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { synchronized(NodeCryptoConfig.this) { return oneConnectionPerAddress; } } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { synchronized(NodeCryptoConfig.this) { oneConnectionPerAddress = val; } @@ -137,29 +140,29 @@ config.register("alwaysAllowLocalAddresses", false, sortOrder++, true, false, "Node.alwaysAllowLocalAddresses", "Node.alwaysAllowLocalAddressesLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { synchronized(NodeCryptoConfig.this) { return alwaysAllowLocalAddresses; } } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { synchronized(NodeCryptoConfig.this) { alwaysAllowLocalAddresses = val; } - } + } }); alwaysAllowLocalAddresses = config.getBoolean("alwaysAllowLocalAddresses"); config.register("assumeNATed", true, sortOrder++, true, true, "Node.assumeNATed", "Node.assumeNATedLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { return assumeNATed; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { assumeNATed = val; - } + } }); assumeNATed = config.getBoolean("assumeNATed"); } @@ -188,7 +191,7 @@ return portNumber; } - class NodeBindtoCallback implements StringCallback { + class NodeBindtoCallback extends StringCallback { public String get() { return bindTo.toString(); @@ -199,6 +202,9 @@ // FIXME why not? Can't we use freenet.io.NetworkInterface like everywhere else, just adapt it for UDP? throw new InvalidConfigValueException("Cannot be updated on the fly"); } + public boolean isReadOnly() { + return true; + } } public synchronized FreenetInetAddress getBindTo() { Modified: branches/db4o/freenet/src/freenet/node/NodeDispatcher.java =================================================================== --- branches/db4o/freenet/src/freenet/node/NodeDispatcher.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/NodeDispatcher.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -143,13 +143,6 @@ } // We claim it in any case return true; - } else if(source.isRealConnection() && spec == DMT.FNPLocChangeNotification) { - double newLoc = m.getDouble(DMT.LOCATION); - source.updateLocation(newLoc); - // TODO: remove dead code when FNPLocChangeNotificationNew is mandatory - if(source.getVersionNumber() > 1153) - Logger.error(this, "We received a FNPLocChangeNotification from a recent build: that should *not* happen! ("+source.toString()+')'); - return true; } else if(source.isRealConnection() && spec == DMT.FNPLocChangeNotificationNew) { double newLoc = m.getDouble(DMT.LOCATION); ShortBuffer buffer = ((ShortBuffer) m.getObject(DMT.PEER_LOCATIONS)); Modified: branches/db4o/freenet/src/freenet/node/NodeIPDetector.java =================================================================== --- branches/db4o/freenet/src/freenet/node/NodeIPDetector.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/NodeIPDetector.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -18,6 +18,7 @@ import freenet.node.useralerts.SimpleUserAlert; import freenet.node.useralerts.UserAlert; import freenet.pluginmanager.DetectedIP; +import freenet.pluginmanager.FredPluginBandwidthIndicator; import freenet.pluginmanager.FredPluginIPDetector; import freenet.pluginmanager.FredPluginPortForward; import freenet.support.HTMLNode; @@ -372,7 +373,6 @@ } redetectAddress(); } - }); hasValidAddressOverride = true; @@ -419,7 +419,6 @@ } redetectAddress(); } - }); String ipHintString = nodeConfig.getString("tempIPAddressHint"); @@ -438,16 +437,15 @@ nodeConfig.register("includeLocalAddressesInNoderefs", false, sortOrder++, true, false, "NodeIPDectector.inclLocalAddress", "NodeIPDectector.inclLocalAddressLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { return includeLocalAddressesInNoderefs; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { includeLocalAddressesInNoderefs = val; lastIPAddress = null; ipDetector.clearCached(); } - }); includeLocalAddressesInNoderefs = nodeConfig.getBoolean("includeLocalAddressesInNoderefs"); @@ -526,6 +524,18 @@ ipDetectorManager.unregisterPortForwardPlugin(forward); } + //TODO: ugly: deal with multiple instances properly + public synchronized void registerBandwidthIndicatorPlugin(FredPluginBandwidthIndicator indicator) { + bandwidthIndicator = indicator; + } + public synchronized void unregisterBandwidthIndicatorPlugin(FredPluginBandwidthIndicator indicator) { + bandwidthIndicator = null; + } + public synchronized FredPluginBandwidthIndicator getBandwidthIndicator() { + return bandwidthIndicator; + } + private FredPluginBandwidthIndicator bandwidthIndicator; + boolean hasValidAddressOverride() { synchronized(this) { return hasValidAddressOverride; Modified: branches/db4o/freenet/src/freenet/node/NodeInitException.java =================================================================== --- branches/db4o/freenet/src/freenet/node/NodeInitException.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/NodeInitException.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -37,6 +37,8 @@ public static final int EXIT_NODE_UPPER_LIMIT = 1024; public static final int EXIT_BROKE_WRAPPER_CONF = 28; public static final int EXIT_OUT_OF_MEMORY_PROTECTING_DATABASE = 29; + public static final int EXIT_EXCEPTION_TO_DEBUG = 1023; + private static final long serialVersionUID = -1; NodeInitException(int exitCode, String msg) { Modified: branches/db4o/freenet/src/freenet/node/NodeStarter.java =================================================================== --- branches/db4o/freenet/src/freenet/node/NodeStarter.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/NodeStarter.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -393,6 +393,8 @@ configFS.put("node.opennet.oneConnectionPerIP", false); configFS.put("node.opennet.assumeNATed", true); configFS.put("node.opennet.connectToSeednodes", connectToSeednodes); + configFS.put("node.encryptTempBuckets", false); + configFS.put("node.encryptPersistentTempBuckets", false); PersistentConfig config = new PersistentConfig(configFS); Modified: branches/db4o/freenet/src/freenet/node/NodeStats.java =================================================================== --- branches/db4o/freenet/src/freenet/node/NodeStats.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/NodeStats.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -212,10 +212,10 @@ statsConfig.register("threadLimit", 500, sortOrder++, true, true, "NodeStat.threadLimit", "NodeStat.threadLimitLong", new IntCallback() { - public int get() { + public Integer get() { return threadLimit; } - public void set(int val) throws InvalidConfigValueException { + public void set(Integer val) throws InvalidConfigValueException { if(val == get()) return; if(val < 100) throw new InvalidConfigValueException(l10n("valueTooLow")); @@ -227,10 +227,10 @@ // Yes it could be in seconds insteed of multiples of 0.12, but we don't want people to play with it :) statsConfig.register("aggressiveGC", aggressiveGCModificator, sortOrder++, true, false, "NodeStat.aggressiveGC", "NodeStat.aggressiveGCLong", new IntCallback() { - public int get() { + public Integer get() { return aggressiveGCModificator; } - public void set(int val) throws InvalidConfigValueException { + public void set(Integer val) throws InvalidConfigValueException { if(val == get()) return; Logger.normal(this, "Changing aggressiveGCModificator to "+val); aggressiveGCModificator = val; @@ -241,11 +241,11 @@ myMemoryChecker = new MemoryChecker(node.ps, aggressiveGCModificator); statsConfig.register("memoryChecker", true, sortOrder++, true, false, "NodeStat.memCheck", "NodeStat.memCheckLong", new BooleanCallback(){ - public boolean get() { + public Boolean get() { return myMemoryChecker.isRunning(); } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { if(val == get()) return; if(val) @@ -259,18 +259,17 @@ statsConfig.register("ignoreLocalVsRemoteBandwidthLiability", false, sortOrder++, true, false, "NodeStat.ignoreLocalVsRemoteBandwidthLiability", "NodeStat.ignoreLocalVsRemoteBandwidthLiabilityLong", new BooleanCallback() { - public boolean get() { + public Boolean get() { synchronized(NodeStats.this) { return ignoreLocalVsRemoteBandwidthLiability; } } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { synchronized(NodeStats.this) { ignoreLocalVsRemoteBandwidthLiability = val; } } - }); persister = new ConfigurablePersister(this, statsConfig, "nodeThrottleFile", "node-throttle.dat", sortOrder++, true, false, Modified: branches/db4o/freenet/src/freenet/node/PeerManager.java =================================================================== --- branches/db4o/freenet/src/freenet/node/PeerManager.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/PeerManager.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -38,6 +38,8 @@ import freenet.support.SimpleFieldSet; import freenet.support.io.FileUtil; import freenet.support.io.Closer; +import java.util.SortedSet; +import java.util.TreeSet; /** * @author amphibian @@ -79,9 +81,14 @@ private long nextRoutableConnectionStatsUpdateTime = -1; /** routableConnectionStats update interval (milliseconds) */ private static final long routableConnectionStatsUpdateInterval = 7 * 1000; // 7 seconds - /** number of samples we have to do stats on peer-selection */ - private long numberOfSelectionSamples = 0; + /** + * Track the number of times a PeerNode has been selected by the routing algorithm + * @see PeerNode.numberOfSelections + */ + private SortedSet<Long> numberOfSelectionSamples = new TreeSet<Long>(); + private final Object numberOfSelectionSamplesSync = new Object(); + public static final int PEER_NODE_STATUS_CONNECTED = 1; public static final int PEER_NODE_STATUS_ROUTING_BACKED_OFF = 2; public static final int PEER_NODE_STATUS_TOO_NEW = 3; @@ -991,10 +998,8 @@ //Add the location which we did not pick, if it exists. if(closestNotBackedOff != null && closestBackedOff != null) addUnpickedLocsTo.add(new Double(closestBackedOff.getLocation())); - - //TODO: synchronize! ; store the stats here instead of into PeerNode? - best.incrementNumberOfSelections(); - numberOfSelectionSamples++; + + incrementSelectionSamples(now, best); } return best; @@ -1219,6 +1224,17 @@ } return false; } + + public boolean anyDarknetPeers() { + PeerNode[] conns; + synchronized(this) { + conns = connectedPeers; + } + for(PeerNode p : conns) + if(p.isDarknet()) + return true; + return false; + } /** * Ask each PeerNode to read in it's extra peer data @@ -1824,7 +1840,19 @@ return null; } - public long getNumberOfSelectionSamples() { - return numberOfSelectionSamples; + public SortedSet<Long> getNumberOfSelectionSamples() { + synchronized (numberOfSelectionSamplesSync) { + return new TreeSet<Long>(numberOfSelectionSamples); + } } + + private void incrementSelectionSamples(long now, PeerNode pn) { + // TODO: reimplement with a bit field to spare memory + synchronized (numberOfSelectionSamplesSync) { + if(numberOfSelectionSamples.size() > PeerNode.SELECTION_MAX_SAMPLES * OpennetManager.MAX_PEERS_FOR_SCALING) + numberOfSelectionSamples = numberOfSelectionSamples.tailSet(now - PeerNode.SELECTION_SAMPLING_PERIOD); + numberOfSelectionSamples.add(now); + pn.incrementNumberOfSelections(now); + } + } } Modified: branches/db4o/freenet/src/freenet/node/PeerNode.java =================================================================== --- branches/db4o/freenet/src/freenet/node/PeerNode.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/PeerNode.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -74,7 +74,8 @@ import freenet.support.math.TimeDecayingRunningAverage; import freenet.support.transport.ip.HostnameSyntaxException; import freenet.support.transport.ip.IPUtil; -import java.util.Collection; +import java.util.SortedSet; +import java.util.TreeSet; /** * @author amphibian @@ -151,9 +152,21 @@ private long timeLastRoutable; /** Time added or restarted (reset on startup unlike peerAddedTime) */ private long timeAddedOrRestarted; - /** Number of time that peer has been selected by the routing algorithm */ - private long numberOfSelections = 0; + /** + * Track the number of times this PeerNode has been selected by + * the routing algorithm over a given period of time + */ + private SortedSet<Long> numberOfSelections = new TreeSet<Long>(); + private final Object numberOfSelectionsSync = new Object(); + // 5mins; yes it's alchemy! + public static final int SELECTION_SAMPLING_PERIOD = 5 * 60 * 1000; + // 30%; yes it's alchemy too! and probably *way* too high to serve any purpose + public static final int SELECTION_PERCENTAGE_WARNING = 30; + // Should be good enough provided we don't get selected more than 10 times per/sec + // Lower the following value if you want to spare memory... or better switch from a TreeSet to a bit field. + public static final int SELECTION_MAX_SAMPLES = 10 * SELECTION_SAMPLING_PERIOD / 1000; + /** Are we connected? If not, we need to start trying to * handshake. */ @@ -975,7 +988,6 @@ * PeerManager in e.g. verified. */ public boolean isRoutable() { - //FIXME: isConnected() is redundant if 'isRoutable', right? ... currentLocation>1.0 is impossible. return isConnected() && isRoutingCompatible() && !(currentLocation < 0.0 || currentLocation > 1.0); } @@ -1607,24 +1619,6 @@ } } } - - /** - * Update the Location to a new value. - * @deprecated - */ - public void updateLocation(double newLoc) { - logMINOR = Logger.shouldLog(Logger.MINOR, PeerNode.class); - if(newLoc < 0.0 || newLoc > 1.0) { - Logger.error(this, "Invalid location update for " + this+ " ("+newLoc+')', new Exception("error")); - // Ignore it - return; - } - synchronized(this) { - currentLocation = newLoc; - locSetTime = System.currentTimeMillis(); - } - node.peers.writePeers(); - } public void updateLocation(double newLoc, double[] newLocs) { logMINOR = Logger.shouldLog(Logger.MINOR, PeerNode.class); @@ -2109,14 +2103,12 @@ * Send any high level messages that need to be sent on connect. */ protected void sendInitialMessages() { - Message locMsg = ((getVersionNumber() > 1153) ? - DMT.createFNPLocChangeNotificationNew(node.lm.getLocation(), node.peers.getPeerLocationDoubles(true)) : - DMT.createFNPLocChangeNotification(node.lm.getLocation())); + Message locMsg = DMT.createFNPLocChangeNotificationNew(node.lm.getLocation(), node.peers.getPeerLocationDoubles(true)); Message ipMsg = DMT.createFNPDetectedIPAddress(detectedPeer); Message timeMsg = DMT.createFNPTime(System.currentTimeMillis()); Message packetsMsg = createSentPacketsMessage(); - Message dRouting = DMT.createRoutingStatus(!disableRoutingHasBeenSetLocally); - Message uptime = DMT.createFNPUptime((byte)(int)(100*node.uptime.getUptime())); + Message dRoutingMsg = DMT.createRoutingStatus(!disableRoutingHasBeenSetLocally); + Message uptimeMsg = DMT.createFNPUptime((byte)(int)(100*node.uptime.getUptime())); try { if(isRealConnection()) @@ -2124,8 +2116,8 @@ sendAsync(ipMsg, null, 0, node.nodeStats.initialMessagesCtr); sendAsync(timeMsg, null, 0, node.nodeStats.initialMessagesCtr); sendAsync(packetsMsg, null, 0, node.nodeStats.initialMessagesCtr); - sendAsync(dRouting, null, 0, node.nodeStats.initialMessagesCtr); - sendAsync(uptime, null, 0, node.nodeStats.initialMessagesCtr); + sendAsync(dRoutingMsg, null, 0, node.nodeStats.initialMessagesCtr); + sendAsync(uptimeMsg, null, 0, node.nodeStats.initialMessagesCtr); } catch(NotConnectedException e) { Logger.error(this, "Completed handshake with " + getPeer() + " but disconnected (" + isConnected + ':' + currentTracker + "!!!: " + e, e); } @@ -2972,9 +2964,9 @@ synchronized(this) { count = (Long) localNodeSentMessageTypes.get(messageSpecName); if(count == null) - count = new Long(1); + count = 1L; else - count = new Long(count.longValue() + 1); + count = count.longValue() + 1; localNodeSentMessageTypes.put(messageSpecName, count); } } @@ -2988,9 +2980,9 @@ synchronized(localNodeReceivedMessageTypes) { count = (Long) localNodeReceivedMessageTypes.get(messageSpecName); if(count == null) - count = new Long(1); + count = 1L; else - count = new Long(count.longValue() + 1); + count = count.longValue() + 1; localNodeReceivedMessageTypes.put(messageSpecName, count); } } @@ -3990,12 +3982,20 @@ return (short)(((int)uptime) & 0xFF); } - public long getNumberOfSelections() { - return numberOfSelections; + public SortedSet<Long> getNumberOfSelections() { + // FIXME: returning a copy is not an option: find a smarter way of dealing with the synchronization + synchronized(numberOfSelectionsSync) { + return numberOfSelections; + } } - public void incrementNumberOfSelections() { - numberOfSelections++; + public void incrementNumberOfSelections(long time) { + // TODO: reimplement with a bit field to spare memory + synchronized(numberOfSelectionsSync) { + if(numberOfSelections.size() > SELECTION_MAX_SAMPLES) + numberOfSelections = numberOfSelections.tailSet(time - SELECTION_SAMPLING_PERIOD); + numberOfSelections.add(time); + } } private long offeredMainJarVersion; Modified: branches/db4o/freenet/src/freenet/node/PeerNodeStatus.java =================================================================== --- branches/db4o/freenet/src/freenet/node/PeerNodeStatus.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/PeerNodeStatus.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -8,6 +8,7 @@ import freenet.io.comm.Peer; import freenet.io.xfer.PacketThrottle; import freenet.support.Logger; +import java.util.SortedSet; /** * Contains various status information for a {@link PeerNode}. Used e.g. in @@ -94,7 +95,7 @@ private final int reportedUptimePercentage; - private final long numberOfSelections; + private final SortedSet<Long> numberOfSelections; PeerNodeStatus(PeerNode peerNode, boolean noHeavy) { if(Logger.shouldLog(Logger.MINOR, this)) { @@ -397,7 +398,7 @@ return reportedUptimePercentage; } - public long getNumberOfSelections() { + public SortedSet<Long> getNumberOfSelections() { return numberOfSelections; } } Modified: branches/db4o/freenet/src/freenet/node/SeedClientPeerNode.java =================================================================== --- branches/db4o/freenet/src/freenet/node/SeedClientPeerNode.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/SeedClientPeerNode.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -100,6 +100,10 @@ System.currentTimeMillis() - lastReceivedPacketTime() > 60*1000) return true; } + } else { + // Disconnect after an hour in any event. + if(System.currentTimeMillis() - timeLastConnectionCompleted() > 60*60*1000) + return true; } return false; } Modified: branches/db4o/freenet/src/freenet/node/TestnetHandler.java =================================================================== --- branches/db4o/freenet/src/freenet/node/TestnetHandler.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/TestnetHandler.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -208,7 +208,7 @@ } - private static class TestnetEnabledCallback implements BooleanCallback { + private static class TestnetEnabledCallback extends BooleanCallback { final Node node; @@ -216,30 +216,33 @@ this.node = node; } - public boolean get() { + public Boolean get() { return node.testnetEnabled; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { if(node.testnetEnabled == val) return; throw new InvalidConfigValueException(L10n.getString("TestnetHandler.cannotEnableDisableOnTheFly")); } - + + public boolean isReadOnly() { + return true; + } } - static class TestnetPortNumberCallback implements IntCallback { + static class TestnetPortNumberCallback extends IntCallback { Node node; TestnetPortNumberCallback(Node n){ this.node = n; } - public int get() { + public Integer get() { return node.testnetHandler.getPort(); } - public void set(int val) throws InvalidConfigValueException { + public void set(Integer val) throws InvalidConfigValueException { if(val == get()) return; node.testnetHandler.rebind(val); } Modified: branches/db4o/freenet/src/freenet/node/TextModeClientInterface.java =================================================================== --- branches/db4o/freenet/src/freenet/node/TextModeClientInterface.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/TextModeClientInterface.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -45,12 +45,12 @@ import freenet.support.OOMHandler; import freenet.support.SimpleFieldSet; import freenet.support.SizeUtil; -import freenet.support.StringArray; import freenet.support.api.Bucket; import freenet.support.io.ArrayBucket; import freenet.support.io.ArrayBucketFactory; import freenet.support.io.BucketTools; import freenet.support.io.FileBucket; +import java.util.Arrays; /** * @author amphibian @@ -860,7 +860,7 @@ } public void onTrace(long uid, double target, double nearest, double best, short htl, short counter, double location, long nodeUID, double[] peerLocs, long[] peerUIDs, double[] locsNotVisited, short forkCount, short linearCounter, String reason, long prevUID) { - String msg = "Probe trace: UID="+uid+" target="+target+" nearest="+nearest+" best="+best+" htl="+htl+" counter="+counter+" linear="+linearCounter+" location="+location+"node UID="+nodeUID+" prev UID="+prevUID+" peer locs="+StringArray.toString(peerLocs)+" peer UIDs="+StringArray.toString(peerUIDs)+" locs not visited = "+StringArray.toString(locsNotVisited)+" forks: "+forkCount+" reason="+reason+'\n'; + String msg = "Probe trace: UID="+uid+" target="+target+" nearest="+nearest+" best="+best+" htl="+htl+" counter="+counter+" linear="+linearCounter+" location="+location+"node UID="+nodeUID+" prev UID="+prevUID+" peer locs="+Arrays.toString(peerLocs)+" peer UIDs="+Arrays.toString(peerUIDs)+" locs not visited = "+Arrays.toString(locsNotVisited)+" forks: "+forkCount+" reason="+reason+'\n'; try { out.write(msg.getBytes()); out.flush(); Modified: branches/db4o/freenet/src/freenet/node/TextModeClientInterfaceServer.java =================================================================== --- branches/db4o/freenet/src/freenet/node/TextModeClientInterfaceServer.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/TextModeClientInterfaceServer.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -103,7 +103,7 @@ } - static class TMCIEnabledCallback implements BooleanCallback { + static class TMCIEnabledCallback extends BooleanCallback { final NodeClientCore core; @@ -111,24 +111,27 @@ this.core = core; } - public boolean get() { + public Boolean get() { return core.getTextModeClientInterface() != null; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { if(val == get()) return; // FIXME implement - see bug #122 throw new InvalidConfigValueException("Cannot be updated on the fly"); } + public boolean isReadOnly() { + return true; + } } - static class TMCISSLCallback implements BooleanCallback { + static class TMCISSLCallback extends BooleanCallback { - public boolean get() { + public Boolean get() { return ssl; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { if(val == get()) return; if(!SSL.available()) { throw new InvalidConfigValueException("Enable SSL support before use ssl with TMCI"); @@ -136,9 +139,12 @@ ssl = val; throw new InvalidConfigValueException("Cannot change SSL on the fly, please restart freenet"); } + public boolean isReadOnly() { + return true; + } } - static class TMCIDirectEnabledCallback implements BooleanCallback { + static class TMCIDirectEnabledCallback extends BooleanCallback { final NodeClientCore core; @@ -146,18 +152,21 @@ this.core = core; } - public boolean get() { + public Boolean get() { return core.getDirectTMCI() != null; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { if(val == get()) return; // FIXME implement - see bug #122 throw new InvalidConfigValueException("Cannot be updated on the fly"); } + public boolean isReadOnly() { + return true; + } } - static class TMCIBindtoCallback implements StringCallback { + static class TMCIBindtoCallback extends StringCallback { final NodeClientCore core; @@ -183,7 +192,7 @@ } } - static class TMCIAllowedHostsCallback implements StringCallback { + static class TMCIAllowedHostsCallback extends StringCallback { private final NodeClientCore core; @@ -208,10 +217,9 @@ throw new InvalidConfigValueException("Setting allowedHosts for TMCI (console) server when TMCI is disabled"); } } - } - static class TCMIPortNumberCallback implements IntCallback{ + static class TCMIPortNumberCallback extends IntCallback { final NodeClientCore core; @@ -219,7 +227,7 @@ this.core = core; } - public int get() { + public Integer get() { if(core.getTextModeClientInterface()!=null) return core.getTextModeClientInterface().port; else @@ -227,7 +235,7 @@ } // TODO: implement it - public void set(int val) throws InvalidConfigValueException { + public void set(Integer val) throws InvalidConfigValueException { if(val == get()) return; core.getTextModeClientInterface().setPort(val); } Modified: branches/db4o/freenet/src/freenet/node/UptimeEstimator.java =================================================================== --- branches/db4o/freenet/src/freenet/node/UptimeEstimator.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/UptimeEstimator.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -48,8 +48,6 @@ /** We write to disk every 5 minutes. The offset is derived from the node's identity. */ private long timeOffset; - private final DecimalFormat fix1p2 = new DecimalFormat("0.00"); - public UptimeEstimator(File nodeDir, Ticker ticker, byte[] bs) { this.ticker = ticker; logFile = new File(nodeDir, "uptime.dat"); @@ -67,7 +65,7 @@ readData(prevFile, base); readData(logFile, base); schedule(System.currentTimeMillis()); - System.out.println("Created uptime estimator, time offset is "+timeOffset+" uptime at startup is "+fix1p2.format(getUptime())+'%'); + System.out.println("Created uptime estimator, time offset is "+timeOffset+" uptime at startup is "+new DecimalFormat("0.00").format(getUptime())+'%'); } private void readData(File file, int base) { Modified: branches/db4o/freenet/src/freenet/node/fcp/ClientGet.java =================================================================== --- branches/db4o/freenet/src/freenet/node/fcp/ClientGet.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/fcp/ClientGet.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -112,9 +112,9 @@ targetFile = null; tempFile = null; if(persistenceType == PERSIST_FOREVER) - ret = server.core.persistentTempBucketFactory.makeEncryptedBucket(); + ret = server.core.persistentTempBucketFactory.makeBucket(maxOutputLength); else - ret = server.core.tempBucketFactory.makeBucket(-1); + ret = server.core.tempBucketFactory.makeBucket(maxOutputLength); } returnBucket = ret; getter = new ClientGetter(this, server.core.requestStarters.chkFetchScheduler, server.core.requestStarters.sskFetchScheduler, uri, fctx, priorityClass, @@ -164,9 +164,9 @@ tempFile = null; try { if(persistenceType == PERSIST_FOREVER) - ret = server.core.persistentTempBucketFactory.makeEncryptedBucket(); + ret = server.core.persistentTempBucketFactory.makeBucket(fctx.maxOutputLength); else - ret = server.core.tempBucketFactory.makeBucket(-1); + ret = server.core.tempBucketFactory.makeBucket(fctx.maxOutputLength); } catch (IOException e) { Logger.error(this, "Cannot create bucket for temp storage: "+e, e); getter = null; @@ -246,9 +246,9 @@ try { // Create a new temp bucket if(persistenceType == PERSIST_FOREVER) - ret = server.core.persistentTempBucketFactory.makeEncryptedBucket(); + ret = server.core.persistentTempBucketFactory.makeBucket(fctx.maxOutputLength); else - ret = server.core.tempBucketFactory.makeBucket(-1); + ret = server.core.tempBucketFactory.makeBucket(fctx.maxOutputLength); } catch (IOException e1) { Logger.error(this, "Cannot create bucket for temp storage: "+e, e); getter = null; Modified: branches/db4o/freenet/src/freenet/node/fcp/ClientPutMessage.java =================================================================== --- branches/db4o/freenet/src/freenet/node/fcp/ClientPutMessage.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/fcp/ClientPutMessage.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -262,7 +262,7 @@ Bucket createBucket(BucketFactory bf, long length, FCPServer server) throws IOException { if(persistenceType == ClientRequest.PERSIST_FOREVER) { - return server.core.persistentTempBucketFactory.makeEncryptedBucket(); + return server.core.persistentTempBucketFactory.makeBucket(length); } else { return super.createBucket(bf, length, server); } Modified: branches/db4o/freenet/src/freenet/node/fcp/ClientRequest.java =================================================================== --- branches/db4o/freenet/src/freenet/node/fcp/ClientRequest.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/fcp/ClientRequest.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -115,7 +115,7 @@ finished = Fields.stringToBool(fs.get("Finished"), false); global = Fields.stringToBool(fs.get("Global"), false); final String stime = fs.get("StartupTime"); - this.startupTime = stime == null ? System.currentTimeMillis() : Fields.parseSILong(stime); + this.startupTime = stime == null ? System.currentTimeMillis() : Fields.parseLong(stime); completionTime = fs.getLong("CompletionTime", 0); if (finished) started=true; Modified: branches/db4o/freenet/src/freenet/node/fcp/ConfigData.java =================================================================== --- branches/db4o/freenet/src/freenet/node/fcp/ConfigData.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/fcp/ConfigData.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -40,49 +40,49 @@ public SimpleFieldSet getFieldSet() { SimpleFieldSet fs = new SimpleFieldSet(true); if(withCurrent) { - SimpleFieldSet current = node.config.exportFieldSet(Config.CONFIG_REQUEST_TYPE_CURRENT_SETTINGS, true); + SimpleFieldSet current = node.config.exportFieldSet(Config.RequestType.CURRENT_SETTINGS, true); if(!current.isEmpty()) { fs.put("current", current); } } if(withDefaults) { - SimpleFieldSet defaultSettings = node.config.exportFieldSet(Config.CONFIG_REQUEST_TYPE_DEFAULT_SETTINGS, false); + SimpleFieldSet defaultSettings = node.config.exportFieldSet(Config.RequestType.DEFAULT_SETTINGS, false); if(!defaultSettings.isEmpty()) { fs.put("default", defaultSettings); } } if(withSortOrder) { - SimpleFieldSet sortOrder = node.config.exportFieldSet(Config.CONFIG_REQUEST_TYPE_SORT_ORDER, false); + SimpleFieldSet sortOrder = node.config.exportFieldSet(Config.RequestType.SORT_ORDER, false); if(!sortOrder.isEmpty()) { fs.put("sortOrder", sortOrder); } } if(withExpertFlag) { - SimpleFieldSet expertFlag = node.config.exportFieldSet(Config.CONFIG_REQUEST_TYPE_EXPERT_FLAG, false); + SimpleFieldSet expertFlag = node.config.exportFieldSet(Config.RequestType.EXPERT_FLAG, false); if(!expertFlag.isEmpty()) { fs.put("expertFlag", expertFlag); } } if(withForceWriteFlag) { - SimpleFieldSet forceWriteFlag = node.config.exportFieldSet(Config.CONFIG_REQUEST_TYPE_FORCE_WRITE_FLAG, false); + SimpleFieldSet forceWriteFlag = node.config.exportFieldSet(Config.RequestType.FORCE_WRITE_FLAG, false); if(!forceWriteFlag.isEmpty()) { fs.put("forceWriteFlag", forceWriteFlag); } } if(withShortDescription) { - SimpleFieldSet shortDescription = node.config.exportFieldSet(Config.CONFIG_REQUEST_TYPE_SHORT_DESCRIPTION, false); + SimpleFieldSet shortDescription = node.config.exportFieldSet(Config.RequestType.SHORT_DESCRIPTION, false); if(!shortDescription.isEmpty()) { fs.put("shortDescription", shortDescription); } } if(withLongDescription) { - SimpleFieldSet longDescription = node.config.exportFieldSet(Config.CONFIG_REQUEST_TYPE_LONG_DESCRIPTION, false); + SimpleFieldSet longDescription = node.config.exportFieldSet(Config.RequestType.LONG_DESCRIPTION, false); if(!longDescription.isEmpty()) { fs.put("longDescription", longDescription); } } if(withDataTypes) { - SimpleFieldSet type = node.config.exportFieldSet(Config.CONFIG_REQUEST_TYPE_DATA_TYPE, false); + SimpleFieldSet type = node.config.exportFieldSet(Config.RequestType.DATA_TYPE, false); if(!type.isEmpty()) { fs.put("dataType", type); } Modified: branches/db4o/freenet/src/freenet/node/fcp/FCPConnectionHandler.java =================================================================== --- branches/db4o/freenet/src/freenet/node/fcp/FCPConnectionHandler.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/fcp/FCPConnectionHandler.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -1,6 +1,7 @@ package freenet.node.fcp; import java.io.BufferedOutputStream; +import java.io.Closeable; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -22,7 +23,7 @@ import freenet.support.io.FileUtil; import freenet.support.io.NativeThread; -public class FCPConnectionHandler { +public class FCPConnectionHandler implements Closeable { private static final class DirectoryAccess { final boolean canWrite; final boolean canRead; Modified: branches/db4o/freenet/src/freenet/node/fcp/FCPServer.java =================================================================== --- branches/db4o/freenet/src/freenet/node/fcp/FCPServer.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/fcp/FCPServer.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -11,6 +11,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.net.Socket; +import java.util.LinkedList; import java.util.Vector; import java.util.WeakHashMap; import java.util.zip.GZIPInputStream; @@ -51,6 +52,7 @@ import freenet.support.io.BucketTools; import freenet.support.io.Closer; import freenet.support.io.NativeThread; +import freenet.support.io.FileUtil; /** * FCP server process. @@ -188,7 +190,7 @@ ch.start(); } - static class FCPPortNumberCallback implements IntCallback { + static class FCPPortNumberCallback extends IntCallback { private final NodeClientCore node; @@ -196,18 +198,22 @@ this.node = node; } - public int get() { + public Integer get() { return node.getFCPServer().port; } - public void set(int val) throws InvalidConfigValueException { + public void set(Integer val) throws InvalidConfigValueException { if(val != get()) { throw new InvalidConfigValueException("Cannot change FCP port number on the fly"); } } + + public boolean isReadOnly() { + return true; + } } - static class FCPEnabledCallback implements BooleanCallback{ + static class FCPEnabledCallback extends BooleanCallback { final NodeClientCore node; @@ -215,24 +221,28 @@ this.node = node; } - public boolean get() { + public Boolean get() { return node.getFCPServer().enabled; } //TODO: Allow it - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { if(val != get()) { throw new InvalidConfigValueException(l10n("cannotStartOrStopOnTheFly")); } } + + public boolean isReadOnly() { + return true; + } } - static class FCPSSLCallback implements BooleanCallback{ + static class FCPSSLCallback extends BooleanCallback { - public boolean get() { + public Boolean get() { return ssl; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { if(val == get()) return; if(!SSL.available()) { throw new InvalidConfigValueException("Enable SSL support before use ssl with FCP"); @@ -240,12 +250,16 @@ ssl = val; throw new InvalidConfigValueException("Cannot change SSL on the fly, please restart freenet"); } + + public boolean isReadOnly() { + return true; + } } // FIXME: Consider moving everything except enabled into constructor // Actually we could move enabled in too with an exception??? - static class FCPBindtoCallback implements StringCallback{ + static class FCPBindtoCallback extends StringCallback { final NodeClientCore node; @@ -272,7 +286,7 @@ } } - static class FCPAllowedHostsCallback implements StringCallback { + static class FCPAllowedHostsCallback extends StringCallback { private final NodeClientCore node; @@ -291,28 +305,26 @@ if (!val.equals(get())) { node.getFCPServer().networkInterface.setAllowedHosts(val); } - } - + } } - static class PersistentDownloadsEnabledCallback implements BooleanCallback { + static class PersistentDownloadsEnabledCallback extends BooleanCallback { boolean enabled; - public boolean get() { + public Boolean get() { return enabled; } - public void set(boolean set) throws InvalidConfigValueException { + public void set(Boolean set) throws InvalidConfigValueException { // This option will be removed completely soon, so there is little // point in translating it. FIXME remove. - if(set != enabled) throw new InvalidConfigValueException("Cannot disable/enable persistent download loading support on the fly"); + if(set.booleanValue() != enabled) throw new InvalidConfigValueException("Cannot disable/enable persistent download loading support on the fly"); } } - static class FCPAllowedHostsFullAccessCallback implements StringCallback { - + static class FCPAllowedHostsFullAccessCallback extends StringCallback { private final NodeClientCore node; public FCPAllowedHostsFullAccessCallback(NodeClientCore node) { @@ -330,8 +342,7 @@ } } - - static class PersistentDownloadsFileCallback implements StringCallback { + static class PersistentDownloadsFileCallback extends StringCallback { FCPServer server; @@ -346,27 +357,27 @@ } } - static class AssumeDDADownloadIsAllowedCallback implements BooleanCallback{ + static class AssumeDDADownloadIsAllowedCallback extends BooleanCallback { FCPServer server; - public boolean get() { + public Boolean get() { return server.assumeDownloadDDAIsAllowed; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { if(val == get()) return; server.assumeDownloadDDAIsAllowed = val; } } - static class AssumeDDAUploadIsAllowedCallback implements BooleanCallback{ + static class AssumeDDAUploadIsAllowedCallback extends BooleanCallback { FCPServer server; - public boolean get() { + public Boolean get() { return server.assumeUploadDDAIsAllowed; } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { if(val == get()) return; server.assumeUploadDDAIsAllowed = val; } Modified: branches/db4o/freenet/src/freenet/node/fcp/PutSuccessfulMessage.java =================================================================== --- branches/db4o/freenet/src/freenet/node/fcp/PutSuccessfulMessage.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/fcp/PutSuccessfulMessage.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -28,7 +28,7 @@ SimpleFieldSet fs = new SimpleFieldSet(true); fs.putSingle("Identifier", identifier); if(global) fs.putSingle("Global", "true"); - // FIXME debug and remove! + // This is useful for simple clients. if(uri != null) fs.putSingle("URI", uri.toString()); fs.put("StartupTime", startupTime); Copied: branches/db4o/freenet/src/freenet/node/simulator/BootstrapPullTest.java (from rev 21939, trunk/freenet/src/freenet/node/simulator/BootstrapPullTest.java) =================================================================== --- branches/db4o/freenet/src/freenet/node/simulator/BootstrapPullTest.java (rev 0) +++ branches/db4o/freenet/src/freenet/node/simulator/BootstrapPullTest.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -0,0 +1,196 @@ +package freenet.node.simulator; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.net.InetAddress; +import java.net.Socket; + +import org.spaceroots.mantissa.random.MersenneTwister; + +import freenet.client.FetchException; +import freenet.client.HighLevelSimpleClient; +import freenet.crypt.RandomSource; +import freenet.keys.FreenetURI; +import freenet.node.Node; +import freenet.node.NodeInitException; +import freenet.node.NodeStarter; +import freenet.support.Logger; +import freenet.support.PooledExecutor; +import freenet.support.SimpleFieldSet; +import freenet.support.TimeUtil; +import freenet.support.LoggerHook.InvalidThresholdException; +import freenet.support.io.FileUtil; +import freenet.support.io.LineReadingInputStream; + +/** + * Insert a random block of data to an established node via FCP, then + * bootstrap a newbie node and pull it from that. + * @author Matthew Toseland <toad at amphibian.dyndns.org> (0xE43DA450) + */ +public class BootstrapPullTest { + + public static int TARGET_PEERS = 10; + public static int TEST_SIZE = 1024*1024; + + public static int EXIT_NO_SEEDNODES = 257; + public static int EXIT_FAILED_TARGET = 258; + public static int EXIT_INSERT_FAILED = 259; + public static int EXIT_FETCH_FAILED = 260; + public static int EXIT_INSERTER_PROBLEM = 261; + + public static int DARKNET_PORT = 5004; + public static int OPENNET_PORT = 5005; + + /** + * @param args + * @throws InvalidThresholdException + * @throws IOException + * @throws NodeInitException + * @throws InterruptedException + */ + public static void main(String[] args) throws InvalidThresholdException, IOException, NodeInitException, InterruptedException { + File dir = new File("bootstrap-pull-test"); + FileUtil.removeAll(dir); + RandomSource random = NodeStarter.globalTestInit(dir.getPath(), false, Logger.ERROR, ""); + byte[] seed = new byte[64]; + random.nextBytes(seed); + MersenneTwister fastRandom = new MersenneTwister(seed); + File seednodes = new File("seednodes.fref"); + if(!seednodes.exists() || seednodes.length() == 0 || !seednodes.canRead()) { + System.err.println("Unable to read seednodes.fref, it doesn't exist, or is empty"); + System.exit(EXIT_NO_SEEDNODES); + } + File secondInnerDir = new File(dir, Integer.toString(DARKNET_PORT)); + secondInnerDir.mkdir(); + FileInputStream fis = new FileInputStream(seednodes); + FileUtil.writeTo(fis, new File(secondInnerDir, "seednodes.fref")); + fis.close(); + + // Create the test data + System.out.println("Creating test data."); + File dataFile = File.createTempFile("testdata", ".tmp", dir); + OutputStream os = new FileOutputStream(dataFile); + byte[] buf = new byte[4096]; + for(long written = 0; written < TEST_SIZE;) { + fastRandom.nextBytes(buf); + int toWrite = (int) Math.min(TEST_SIZE - written, buf.length); + os.write(buf, 0, toWrite); + written += toWrite; + } + os.close(); + + // Insert it to the established node. + System.out.println("Inserting test data to an established node."); + FreenetURI uri = insertData(dataFile); + + // Bootstrap a second node. + secondInnerDir.mkdir(); + fis = new FileInputStream(seednodes); + FileUtil.writeTo(fis, new File(secondInnerDir, "seednodes.fref")); + fis.close(); + PooledExecutor executor = new PooledExecutor(); + Node secondNode = NodeStarter.createTestNode(DARKNET_PORT, OPENNET_PORT, dir.getPath(), true, false, false, Node.DEFAULT_MAX_HTL, 0, random, executor, 1000, 5*1024*1024, true, true, true, true, true, true, true, 12*1024, false, true); + secondNode.start(true); + waitForTenNodes(secondNode); + + // Fetch the data + long startFetchTime = System.currentTimeMillis(); + HighLevelSimpleClient client = secondNode.clientCore.makeClient((short)0); + try { + client.fetch(uri); + } catch (FetchException e) { + System.err.println("FETCH FAILED: "+e); + e.printStackTrace(); + System.exit(EXIT_FETCH_FAILED); + return; + } + long endFetchTime = System.currentTimeMillis(); + System.out.println("RESULT: Fetch took "+(endFetchTime-startFetchTime)+"ms ("+TimeUtil.formatTime(endFetchTime-startFetchTime)+") of "+uri+" ."); + secondNode.park(); + System.exit(0); + + } + + private static FreenetURI insertData(File dataFile) throws IOException { + long startInsertTime = System.currentTimeMillis(); + InetAddress localhost = InetAddress.getByName("127.0.0.1"); + Socket sock = new Socket(localhost, 9481); + OutputStream sockOS = sock.getOutputStream(); + InputStream sockIS = sock.getInputStream(); + System.out.println("Connected to node."); + LineReadingInputStream lis = new LineReadingInputStream(sockIS); + OutputStreamWriter osw = new OutputStreamWriter(sockOS, "UTF-8"); + osw.write("ClientHello\nExpectedVersion=0.7\nName=BootstrapPullTest-"+System.currentTimeMillis()+"\nEnd\n"); + osw.flush(); + String name = lis.readLine(65536, 128, true); + SimpleFieldSet fs = new SimpleFieldSet(lis, 65536, 128, true, true, false, true); + if(!name.equals("NodeHello")) { + System.err.println("No NodeHello from insertor node!"); + System.exit(EXIT_INSERTER_PROBLEM); + } + System.out.println("Connected to "+sock); + osw.write("ClientPut\nIdentifier=test-insert\nURI=CHK@\nVerbosity=1023\nUploadFrom=direct\nMaxRetries=-1\nDataLength="+TEST_SIZE+"\nData\n"); + osw.flush(); + InputStream is = new FileInputStream(dataFile); + FileUtil.copy(is, sockOS, TEST_SIZE); + System.out.println("Sent data"); + while(true) { + name = lis.readLine(65536, 128, true); + fs = new SimpleFieldSet(lis, 65536, 128, true, true, false, true); + System.out.println("Got FCP message: \n"+name); + System.out.print(fs.toOrderedString()); + if(name.equals("ProtocolError")) { + System.err.println("Protocol error when inserting data."); + System.exit(EXIT_INSERTER_PROBLEM); + } + if(name.equals("PutFailed")) { + System.err.println("Insert failed"); + System.exit(EXIT_INSERT_FAILED); + } + if(name.equals("PutSuccessful")) { + long endInsertTime = System.currentTimeMillis(); + FreenetURI uri = new FreenetURI(fs.get("URI")); + System.out.println("RESULT: Insert took "+(endInsertTime-startInsertTime)+"ms ("+TimeUtil.formatTime(endInsertTime-startInsertTime)+") to "+uri+" ."); + sockOS.close(); + sockIS.close(); + sock.close(); + return uri; + } + } + } + + private static void waitForTenNodes(Node node) throws InterruptedException { + long startTime = System.currentTimeMillis(); + // Wait until we have 10 connected nodes... + int seconds = 0; + boolean success = false; + while(seconds < 600) { + Thread.sleep(1000); + int seeds = node.peers.countSeednodes(); + int seedConns = node.peers.getConnectedSeedServerPeersVector(null).size(); + int opennetPeers = node.peers.countValidPeers(); + int opennetConns = node.peers.countConnectedOpennetPeers(); + System.err.println(""+seconds+" : seeds: "+seeds+", connected: "+seedConns + +" opennet: peers: "+opennetPeers+", connected: "+opennetConns); + seconds++; + if(opennetConns >= TARGET_PEERS) { + long timeTaken = System.currentTimeMillis()-startTime; + System.out.println("RESULT: Completed bootstrap ("+TARGET_PEERS+" peers) in "+timeTaken+"ms ("+TimeUtil.formatTime(timeTaken)+")"); + success = true; + break; + } + } + if(!success) { + System.err.println("Failed to reach target peers count "+TARGET_PEERS+" in 10 minutes."); + node.park(); + System.exit(EXIT_FAILED_TARGET); + } + } + + +} Copied: branches/db4o/freenet/src/freenet/node/simulator/BootstrapPushPullTest.java (from rev 21939, trunk/freenet/src/freenet/node/simulator/BootstrapPushPullTest.java) =================================================================== --- branches/db4o/freenet/src/freenet/node/simulator/BootstrapPushPullTest.java (rev 0) +++ branches/db4o/freenet/src/freenet/node/simulator/BootstrapPushPullTest.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -0,0 +1,143 @@ +package freenet.node.simulator; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.OutputStream; + +import freenet.client.ClientMetadata; +import freenet.client.FetchException; +import freenet.client.HighLevelSimpleClient; +import freenet.client.InsertBlock; +import freenet.client.InsertException; +import freenet.crypt.RandomSource; +import freenet.keys.FreenetURI; +import freenet.node.Node; +import freenet.node.NodeInitException; +import freenet.node.NodeStarter; +import freenet.support.Executor; +import freenet.support.Logger; +import freenet.support.PooledExecutor; +import freenet.support.TimeUtil; +import freenet.support.LoggerHook.InvalidThresholdException; +import freenet.support.api.Bucket; +import freenet.support.io.FileUtil; + +public class BootstrapPushPullTest { + + public static int TARGET_PEERS = 10; + public static int TEST_SIZE = 1024*1024; + + public static int EXIT_NO_SEEDNODES = 257; + public static int EXIT_FAILED_TARGET = 258; + public static int EXIT_INSERT_FAILED = 259; + public static int EXIT_FETCH_FAILED = 260; + + public static void main(String[] args) throws InvalidThresholdException, IOException, NodeInitException, InterruptedException { + File dir = new File("bootstrap-push-pull-test"); + FileUtil.removeAll(dir); + RandomSource random = NodeStarter.globalTestInit(dir.getPath(), false, Logger.ERROR, ""); + File seednodes = new File("seednodes.fref"); + if(!seednodes.exists() || seednodes.length() == 0 || !seednodes.canRead()) { + System.err.println("Unable to read seednodes.fref, it doesn't exist, or is empty"); + System.exit(EXIT_NO_SEEDNODES); + } + File innerDir = new File(dir, "5000"); + innerDir.mkdir(); + FileInputStream fis = new FileInputStream(seednodes); + FileUtil.writeTo(fis, new File(innerDir, "seednodes.fref")); + fis.close(); + // Create one node + Executor executor = new PooledExecutor(); + Node node = NodeStarter.createTestNode(5000, 5001, dir.getPath(), true, false, false, Node.DEFAULT_MAX_HTL, 0, random, executor, 1000, 5*1024*1024, true, true, true, true, true, true, true, 12*1024, false, true); + //NodeCrypto.DISABLE_GROUP_STRIP = true; + //Logger.setupStdoutLogging(Logger.MINOR, "freenet:NORMAL,freenet.node.NodeDispatcher:MINOR,freenet.node.FNPPacketMangler:MINOR"); + Logger.getChain().setThreshold(Logger.ERROR); // kill logging + // Start it + node.start(true); + waitForTenNodes(node); + System.out.println("Creating test data: "+TEST_SIZE+" bytes."); + Bucket data = node.clientCore.tempBucketFactory.makeBucket(TEST_SIZE); + OutputStream os = data.getOutputStream(); + byte[] buf = new byte[4096]; + for(long written = 0; written < TEST_SIZE;) { + node.fastWeakRandom.nextBytes(buf); + int toWrite = (int) Math.min(TEST_SIZE - written, buf.length); + os.write(buf, 0, toWrite); + written += toWrite; + } + os.close(); + System.out.println("Inserting test data."); + HighLevelSimpleClient client = node.clientCore.makeClient((short)0); + InsertBlock block = new InsertBlock(data, new ClientMetadata(null), FreenetURI.EMPTY_CHK_URI); + long startInsertTime = System.currentTimeMillis(); + FreenetURI uri; + try { + uri = client.insert(block, false, null); + } catch (InsertException e) { + System.err.println("INSERT FAILED: "+e); + e.printStackTrace(); + System.exit(EXIT_INSERT_FAILED); + return; + } + long endInsertTime = System.currentTimeMillis(); + System.out.println("RESULT: Insert took "+(endInsertTime-startInsertTime)+"ms ("+TimeUtil.formatTime(endInsertTime-startInsertTime)+") to "+uri+" ."); + node.park(); + + // Bootstrap a second node. + File secondInnerDir = new File(dir, "5002"); + secondInnerDir.mkdir(); + fis = new FileInputStream(seednodes); + FileUtil.writeTo(fis, new File(secondInnerDir, "seednodes.fref")); + fis.close(); + executor = new PooledExecutor(); + Node secondNode = NodeStarter.createTestNode(5002, 5003, dir.getPath(), true, false, false, Node.DEFAULT_MAX_HTL, 0, random, executor, 1000, 5*1024*1024, true, true, true, true, true, true, true, 12*1024, false, true); + secondNode.start(true); + waitForTenNodes(secondNode); + + // Fetch the data + long startFetchTime = System.currentTimeMillis(); + client = secondNode.clientCore.makeClient((short)0); + try { + client.fetch(uri); + } catch (FetchException e) { + System.err.println("FETCH FAILED: "+e); + e.printStackTrace(); + System.exit(EXIT_FETCH_FAILED); + return; + } + long endFetchTime = System.currentTimeMillis(); + System.out.println("RESULT: Fetch took "+(endFetchTime-startFetchTime)+"ms ("+TimeUtil.formatTime(endFetchTime-startFetchTime)+") of "+uri+" ."); + secondNode.park(); + System.exit(0); + } + + private static void waitForTenNodes(Node node) throws InterruptedException { + long startTime = System.currentTimeMillis(); + // Wait until we have 10 connected nodes... + int seconds = 0; + boolean success = false; + while(seconds < 600) { + Thread.sleep(1000); + int seeds = node.peers.countSeednodes(); + int seedConns = node.peers.getConnectedSeedServerPeersVector(null).size(); + int opennetPeers = node.peers.countValidPeers(); + int opennetConns = node.peers.countConnectedOpennetPeers(); + System.err.println(""+seconds+" : seeds: "+seeds+", connected: "+seedConns + +" opennet: peers: "+opennetPeers+", connected: "+opennetConns); + seconds++; + if(opennetConns >= TARGET_PEERS) { + long timeTaken = System.currentTimeMillis()-startTime; + System.out.println("RESULT: Completed bootstrap ("+TARGET_PEERS+" peers) in "+timeTaken+"ms ("+TimeUtil.formatTime(timeTaken)+")"); + success = true; + break; + } + } + if(!success) { + System.err.println("Failed to reach target peers count "+TARGET_PEERS+" in 10 minutes."); + node.park(); + System.exit(EXIT_FAILED_TARGET); + } + } + +} Copied: branches/db4o/freenet/src/freenet/node/simulator/BootstrapSeedTest.java (from rev 21939, trunk/freenet/src/freenet/node/simulator/BootstrapSeedTest.java) =================================================================== --- branches/db4o/freenet/src/freenet/node/simulator/BootstrapSeedTest.java (rev 0) +++ branches/db4o/freenet/src/freenet/node/simulator/BootstrapSeedTest.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -0,0 +1,77 @@ +package freenet.node.simulator; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +import freenet.crypt.RandomSource; +import freenet.node.Node; +import freenet.node.NodeInitException; +import freenet.node.NodeStarter; +import freenet.support.Executor; +import freenet.support.Logger; +import freenet.support.PooledExecutor; +import freenet.support.TimeUtil; +import freenet.support.LoggerHook.InvalidThresholdException; +import freenet.support.io.FileUtil; + +public class BootstrapSeedTest { + + public static int TARGET_PEERS = 10; + public static int EXIT_NO_SEEDNODES = 257; + public static int EXIT_FAILED_TARGET = 258; + + /** + * @param args + * @throws InvalidThresholdException + * @throws NodeInitException + * @throws InterruptedException + * @throws IOException + */ + public static void main(String[] args) throws InvalidThresholdException, NodeInitException, InterruptedException, IOException { + File dir = new File("bootstrap-test"); + FileUtil.removeAll(dir); + RandomSource random = NodeStarter.globalTestInit(dir.getPath(), false, Logger.ERROR, ""); + File seednodes = new File("seednodes.fref"); + if(!seednodes.exists() || seednodes.length() == 0 || !seednodes.canRead()) { + System.err.println("Unable to read seednodes.fref, it doesn't exist, or is empty"); + System.exit(EXIT_NO_SEEDNODES); + } + File innerDir = new File(dir, "5000"); + innerDir.mkdir(); + FileInputStream fis = new FileInputStream(seednodes); + FileUtil.writeTo(fis, new File(innerDir, "seednodes.fref")); + fis.close(); + // Create one node + Executor executor = new PooledExecutor(); + Node node = NodeStarter.createTestNode(5000, 5001, "bootstrap-test", true, false, false, Node.DEFAULT_MAX_HTL, 0, random, executor, 1000, 5*1024*1024, true, true, true, true, true, true, true, 12*1024, false, true); + //NodeCrypto.DISABLE_GROUP_STRIP = true; + //Logger.setupStdoutLogging(Logger.MINOR, "freenet:NORMAL,freenet.node.NodeDispatcher:MINOR,freenet.node.FNPPacketMangler:MINOR"); + Logger.getChain().setThreshold(Logger.ERROR); // kill logging + long startTime = System.currentTimeMillis(); + // Start it + node.start(true); + // Wait until we have 10 connected nodes... + int seconds = 0; + while(seconds < 600) { + Thread.sleep(1000); + int seeds = node.peers.countSeednodes(); + int seedConns = node.peers.getConnectedSeedServerPeersVector(null).size(); + int opennetPeers = node.peers.countValidPeers(); + int opennetConns = node.peers.countConnectedOpennetPeers(); + System.err.println(""+seconds+" : seeds: "+seeds+", connected: "+seedConns + +" opennet: peers: "+opennetPeers+", connected: "+opennetConns); + seconds++; + if(opennetConns >= TARGET_PEERS) { + long timeTaken = System.currentTimeMillis()-startTime; + System.out.println("Completed bootstrap ("+TARGET_PEERS+" peers) in "+timeTaken+"ms ("+TimeUtil.formatTime(timeTaken)+")"); + node.park(); + System.exit(0); + } + } + System.err.println("Failed to reach target peers count "+TARGET_PEERS+" in 5 minutes."); + node.park(); + System.exit(EXIT_FAILED_TARGET); + } + +} Modified: branches/db4o/freenet/src/freenet/node/simulator/RealNodeBusyNetworkTest.java =================================================================== --- branches/db4o/freenet/src/freenet/node/simulator/RealNodeBusyNetworkTest.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/simulator/RealNodeBusyNetworkTest.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -157,9 +157,9 @@ totalRunningRequests += nodes[i].clientCore.countTransientQueuedRequests(); } System.err.println("Running requests: "+totalRunningRequests); - if(totalRunningRequests == 0) return; + if(totalRunningRequests == 0) break; Thread.sleep(1000); } - + System.exit(0); } } Modified: branches/db4o/freenet/src/freenet/node/simulator/RealNodeRequestInsertTest.java =================================================================== --- branches/db4o/freenet/src/freenet/node/simulator/RealNodeRequestInsertTest.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/simulator/RealNodeRequestInsertTest.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -24,7 +24,6 @@ import freenet.support.Executor; import freenet.support.Logger; import freenet.support.PooledExecutor; -import freenet.support.StringArray; import freenet.support.LoggerHook.InvalidThresholdException; import freenet.support.io.ArrayBucket; import freenet.support.io.FileUtil; @@ -209,7 +208,7 @@ if(totalRunningUIDsAlt != 0) System.err.println("Still running UIDs (alt): "+totalRunningUIDsAlt); if(!runningUIDsList.isEmpty()) { - System.err.println("List of running UIDs: "+StringArray.toString(runningUIDsList.toArray())); + System.err.println("List of running UIDs: "+Arrays.toString(runningUIDsList.toArray())); } } catch (Throwable t) { Logger.error(RealNodeRequestInsertTest.class, "Caught "+t, t); Modified: branches/db4o/freenet/src/freenet/node/simulator/SeednodePingTest.java =================================================================== --- branches/db4o/freenet/src/freenet/node/simulator/SeednodePingTest.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/simulator/SeednodePingTest.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -10,7 +10,6 @@ import freenet.node.Announcer; import freenet.node.FSParseException; import freenet.node.Node; -import freenet.node.NodeCrypto; import freenet.node.NodeInitException; import freenet.node.NodeStarter; import freenet.node.OpennetDisabledException; @@ -39,7 +38,6 @@ // Create one node Executor executor = new PooledExecutor(); Node node = NodeStarter.createTestNode(5000, 5001, "seednode-pingtest", true, false, false, Node.DEFAULT_MAX_HTL, 0, random, executor, 1000, 5*1024*1024, true, false, false, false, false, false, false, 0, false, false); - NodeCrypto.DISABLE_GROUP_STRIP = true; // Connect & ping Vector<SeedServerTestPeerNode> seedNodes = new Vector<SeedServerTestPeerNode>(); Vector<SimpleFieldSet> seedNodesAsSFS = Announcer.readSeednodes(new File("/tmp/")); Modified: branches/db4o/freenet/src/freenet/node/updater/NodeUpdateManager.java =================================================================== --- branches/db4o/freenet/src/freenet/node/updater/NodeUpdateManager.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/updater/NodeUpdateManager.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -804,29 +804,29 @@ // Config callbacks - class UpdaterEnabledCallback implements BooleanCallback { + class UpdaterEnabledCallback extends BooleanCallback { - public boolean get() { + public Boolean get() { return isEnabled(); } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { enable(val); } } - class AutoUpdateAllowedCallback implements BooleanCallback { + class AutoUpdateAllowedCallback extends BooleanCallback { - public boolean get() { + public Boolean get() { return isAutoUpdateAllowed(); } - public void set(boolean val) throws InvalidConfigValueException { + public void set(Boolean val) throws InvalidConfigValueException { setAutoUpdateAllowed(val); } } - class UpdateURICallback implements StringCallback { + class UpdateURICallback extends StringCallback { boolean isExt; @@ -847,10 +847,9 @@ } setURI(isExt, uri); } - } - public class UpdateRevocationURICallback implements StringCallback { + public class UpdateRevocationURICallback extends StringCallback { public String get() { return getRevocationURI().toString(false, false); @@ -865,7 +864,6 @@ } setRevocationURI(uri); } - } /** Called when a peer indicates in its UOMAnnounce that it has fetched the revocation key Modified: branches/db4o/freenet/src/freenet/node/useralerts/MeaningfulNodeNameUserAlert.java =================================================================== --- branches/db4o/freenet/src/freenet/node/useralerts/MeaningfulNodeNameUserAlert.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/node/useralerts/MeaningfulNodeNameUserAlert.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -17,6 +17,7 @@ this.node = n; } + @Override public String getTitle() { return l10n("noNodeNickTitle"); } @@ -25,14 +26,17 @@ return L10n.getString("MeaningfulNodeNameUserAlert."+key); } + @Override public String getText() { return l10n("noNodeNick"); } + @Override public String getShortText() { return l10n("noNodeNickShort"); } + @Override public HTMLNode getHTMLText() { SubConfig sc = node.config.get("node"); Option o = sc.getOption("name"); @@ -55,4 +59,8 @@ return alertNode; } + @Override + public boolean isValid() { + return node.peers.anyDarknetPeers(); + } } Copied: branches/db4o/freenet/src/freenet/pluginmanager/FredPluginBandwidthIndicator.java (from rev 21939, trunk/freenet/src/freenet/pluginmanager/FredPluginBandwidthIndicator.java) =================================================================== --- branches/db4o/freenet/src/freenet/pluginmanager/FredPluginBandwidthIndicator.java (rev 0) +++ branches/db4o/freenet/src/freenet/pluginmanager/FredPluginBandwidthIndicator.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -0,0 +1,17 @@ +/* This code is part of Freenet. It is distributed under the GNU General + * Public License, version 2 (or at your option any later version). See + * http://www.gnu.org/ for further details of the GPL. */ +package freenet.pluginmanager; + +public interface FredPluginBandwidthIndicator { + + /** + * @return the reported upstream bit rate in bits per second. -1 if it's not available. Blocking. + */ + public int getUpstramMaxBitRate(); + + /** + * @return the reported downstream bit rate in bits per second. -1 if it's not available. Blocking. + */ + public int getDownstreamMaxBitRate(); +} Modified: branches/db4o/freenet/src/freenet/pluginmanager/PluginDownLoaderOfficial.java =================================================================== --- branches/db4o/freenet/src/freenet/pluginmanager/PluginDownLoaderOfficial.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/pluginmanager/PluginDownLoaderOfficial.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -3,12 +3,15 @@ * http://www.gnu.org/ for further details of the GPL. */ package freenet.pluginmanager; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.net.MalformedURLException; import java.net.URL; +import java.net.URLConnection; import java.security.KeyStore; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; @@ -35,7 +38,29 @@ @Override String getSHA1sum() throws PluginNotFoundException { - return null; + try { + URL sha1url = new URL(getSource().toString()+".sha1"); + URLConnection urlConnection = sha1url.openConnection(); + urlConnection.setUseCaches(false); + urlConnection.setAllowUserInteraction(false); + + InputStream is = openConnectionCheckRedirects(urlConnection); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + byte[] buffer = new byte[1024]; + int read; + + while ((read = is.read(buffer)) != -1) { + bos.write(buffer, 0, read); + } + + return new String(bos.toByteArray()).split(" ")[0]; + + } catch (MalformedURLException e) { + throw new PluginNotFoundException("impossible: "+e,e); + } catch (IOException e) { + throw new PluginNotFoundException("Error while fetching sha1 for plugin: "+e,e); + } } @Override Modified: branches/db4o/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java =================================================================== --- branches/db4o/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -5,37 +5,37 @@ import freenet.l10n.L10n; import freenet.support.Logger; -import freenet.support.StringArray; public class PluginInfoWrapper { // Parameters to make the object OTP private boolean fedPluginThread = false; // Public since only PluginHandler will know about it - private String className; + private final String className; private Thread thread; - private long start; - private String threadName; + private final long start; + private final String threadName; final FredPlugin plug; - private boolean isPproxyPlugin; - private boolean isThreadlessPlugin; - private boolean isIPDetectorPlugin; - private boolean isPortForwardPlugin; - private boolean isMultiplePlugin; - private boolean isFCPPlugin; - private boolean isVersionedPlugin; - private String filename; - private HashSet toadletLinks=new HashSet(); - private boolean stopping = false; - private boolean unregistered = false; + private final boolean isPproxyPlugin; + private final boolean isThreadlessPlugin; + private final boolean isIPDetectorPlugin; + private final boolean isBandwidthIndicator; + private final boolean isPortForwardPlugin; + private final boolean isMultiplePlugin; + private final boolean isFCPPlugin; + private final boolean isVersionedPlugin; + private final String filename; + private HashSet<String> toadletLinks = new HashSet<String>(); + private volatile boolean stopping = false; + private volatile boolean unregistered = false; public PluginInfoWrapper(FredPlugin plug, String filename) { this.plug = plug; - if (fedPluginThread) return; className = plug.getClass().toString(); this.filename = filename; threadName = 'p' + className.replaceAll("^class ", "") + '_' + hashCode(); start = System.currentTimeMillis(); fedPluginThread = true; + isBandwidthIndicator = (plug instanceof FredPluginBandwidthIndicator); isPproxyPlugin = (plug instanceof FredPluginHTTP); isThreadlessPlugin = (plug instanceof FredPluginThreadless); isIPDetectorPlugin = (plug instanceof FredPluginIPDetector); @@ -52,6 +52,7 @@ thread.setName(threadName); } + @Override public String toString() { return "ID: \"" +threadName + "\", Name: "+ className +", Started: " + (new Date(start)).toString(); } @@ -77,7 +78,7 @@ } public synchronized String[] getPluginToadletSymlinks(){ - return StringArray.toArray(toadletLinks.toArray()); + return toadletLinks.toArray(new String[0]); } public synchronized boolean addPluginToadletSymlink(String linkfrom){ @@ -143,6 +144,8 @@ manager.node.ipDetector.unregisterIPDetectorPlugin((FredPluginIPDetector)plug); if(isPortForwardPlugin) manager.node.ipDetector.unregisterPortForwardPlugin((FredPluginPortForward)plug); + if(isBandwidthIndicator) + manager.node.ipDetector.unregisterBandwidthIndicatorPlugin((FredPluginBandwidthIndicator)plug); } public boolean isPproxyPlugin() { @@ -152,6 +155,10 @@ public String getFilename() { return filename; } + + public boolean isBandwidthIndicator() { + return isBandwidthIndicator; + } public boolean isThreadlessPlugin() { return isThreadlessPlugin; Modified: branches/db4o/freenet/src/freenet/pluginmanager/PluginManager.java =================================================================== --- branches/db4o/freenet/src/freenet/pluginmanager/PluginManager.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/pluginmanager/PluginManager.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -6,20 +6,15 @@ import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.Vector; @@ -45,7 +40,6 @@ import freenet.support.Logger; import freenet.support.api.HTTPRequest; import freenet.support.api.StringArrCallback; -import freenet.support.api.StringCallback; import freenet.support.io.Closer; import freenet.support.io.FileUtil; @@ -60,16 +54,11 @@ * TODO: Synchronize * */ - - private String configFile; - private String installDir; - private final HashMap toadletList; /* All currently starting plugins. */ - private final Set/* <PluginProgress> */startingPlugins = new HashSet/* <PluginProgress> */(); - - private final Vector/* <PluginInfoWrapper> */pluginWrappers; + private final Set<PluginProgress> startingPlugins = new HashSet<PluginProgress>(); + private final Vector<PluginInfoWrapper> pluginWrappers; final Node node; private final NodeClientCore core; SubConfig pmconfig; @@ -78,23 +67,25 @@ private final HighLevelSimpleClient client; public PluginManager(Node node) { - + logMINOR = Logger.shouldLog(Logger.MINOR, this); logDEBUG = Logger.shouldLog(Logger.DEBUG, this); // config - + toadletList = new HashMap(); pluginWrappers = new Vector(); this.node = node; this.core = node.clientCore; - - if(logMINOR) Logger.minor(this, "Starting Plugin Manager"); - - if(logDEBUG) Logger.debug(this, "Initialize Plugin Manager config"); - + + if(logMINOR) + Logger.minor(this, "Starting Plugin Manager"); + + if(logDEBUG) + Logger.debug(this, "Initialize Plugin Manager config"); + client = core.makeClient(RequestStarter.INTERACTIVE_PRIORITY_CLASS, true); - + pmconfig = new SubConfig("pluginmanager", node.config); // pmconfig.register("configfile", "fplugins.ini", 9, true, true, "PluginConfig.configFile", "PluginConfig.configFileLong", // new StringCallback() { @@ -124,44 +115,43 @@ // installDir = pmconfig.getString("installdir"); // Start plugins in the config - pmconfig.register("loadplugin", null, 9, true, false, "PluginManager.loadedOnStartup", "PluginManager.loadedOnStartupLong", - new StringArrCallback() { - public String[] get() { - return getConfigLoadString(); - } + pmconfig.register("loadplugin", null, 0, true, false, "PluginManager.loadedOnStartup", "PluginManager.loadedOnStartupLong", + new StringArrCallback() { - public void set(String[] val) throws InvalidConfigValueException { - //if(storeDir.equals(new File(val))) return; - // FIXME - throw new InvalidConfigValueException(L10n.getString("PluginManager.cannotSetOnceLoaded")); - } - }); + public String[] get() { + return getConfigLoadString(); + } + public void set(String[] val) throws InvalidConfigValueException { + //if(storeDir.equals(new File(val))) return; + // FIXME + throw new InvalidConfigValueException(L10n.getString("PluginManager.cannotSetOnceLoaded")); + } + + @Override + public boolean isReadOnly() { + return true; + } + }); + String fns[] = pmconfig.getStringArr("loadplugin"); - if (fns != null) { - for (String name : fns) + if(fns != null) + for(String name : fns) startPluginAuto(name, false); - } pmconfig.finishedInitialization(); } private String[] getConfigLoadString() { - try{ - Iterator it = getPlugins().iterator(); - - Vector v = new Vector(); - - while (it.hasNext()) { - PluginInfoWrapper pluginInfoWrapper = (PluginInfoWrapper) it.next(); - v.add(pluginInfoWrapper.getFilename()); + Vector<String> v = new Vector<String>(); + + synchronized(pluginWrappers) { + for(PluginInfoWrapper pi : pluginWrappers) { + v.add(pi.getFilename()); } - - return (String[]) v.toArray(new String[v.size()]); - }catch (NullPointerException e){ - Logger.error(this, "error while loading plugins: disabling them:"+e); - return new String[0]; } + + return v.toArray(new String[v.size()]); } /** @@ -169,32 +159,30 @@ * * @return All currently starting plugins */ - public Set/* <PluginProgess> */getStartingPlugins() { - synchronized (startingPlugins) { + public Set/* <PluginProgess> */ getStartingPlugins() { + synchronized(startingPlugins) { return new HashSet/* <PluginProgress> */(startingPlugins); } } - - // try to guess around... public void startPluginAuto(final String pluginname, boolean store) { - - if (isOfficialPlugin(pluginname)) { + + if(isOfficialPlugin(pluginname)) { startPluginOfficial(pluginname, store); return; } - + try { FreenetURI uri = new FreenetURI(pluginname); startPluginFreenet(pluginname, store); return; - } catch (MalformedURLException e) { + } catch(MalformedURLException e) { // not a freenet key } - + File[] roots = File.listRoots(); - for (File f: roots) { - if (pluginname.startsWith(f.getName())) { + for(File f : roots) { + if(pluginname.startsWith(f.getName())) { startPluginFile(pluginname, store); return; } @@ -202,28 +190,28 @@ startPluginURL(pluginname, store); } - + public void startPluginOfficial(final String pluginname, boolean store) { realStartPlugin(new PluginDownLoaderOfficial(), pluginname, store); } - + public void startPluginFile(final String filename, boolean store) { realStartPlugin(new PluginDownLoaderFile(), filename, store); } - + public void startPluginURL(final String filename, boolean store) { realStartPlugin(new PluginDownLoaderURL(), filename, store); } - + public void startPluginFreenet(final String filename, boolean store) { realStartPlugin(new PluginDownLoaderFreenet(client), filename, true); } - + private void realStartPlugin(final PluginDownLoader pdl, final String filename, final boolean store) { - if (filename.trim().length() == 0) + if(filename.trim().length() == 0) return; final PluginProgress pluginProgress = new PluginProgress(filename); - synchronized (startingPlugins) { + synchronized(startingPlugins) { startingPlugins.add(pluginProgress); } node.executor.execute(new Runnable() { @@ -235,32 +223,29 @@ plug = loadPlugin(pdl, filename); pluginProgress.setProgress(PluginProgress.STARTING); PluginInfoWrapper pi = PluginHandler.startPlugin(PluginManager.this, filename, plug, new PluginRespirator(node, PluginManager.this)); - synchronized (pluginWrappers) { + synchronized(pluginWrappers) { pluginWrappers.add(pi); } Logger.normal(this, "Plugin loaded: " + filename); - } catch (PluginNotFoundException e) { + } catch(PluginNotFoundException e) { Logger.normal(this, "Loading plugin failed (" + filename + ')', e); String message = e.getMessage(); - core.alerts.register(new SimpleUserAlert(true, l10n("pluginLoadingFailedTitle"), l10n("pluginLoadingFailedWithMessage", new String[] { "name", "message" }, new String[] { filename, message }), l10n("pluginLoadingFailedShort", "name", filename), UserAlert.ERROR, PluginManager.class)); - } catch (UnsupportedClassVersionError e) { + core.alerts.register(new SimpleUserAlert(true, l10n("pluginLoadingFailedTitle"), l10n("pluginLoadingFailedWithMessage", new String[]{"name", "message"}, new String[]{filename, message}), l10n("pluginLoadingFailedShort", "name", filename), UserAlert.ERROR, PluginManager.class)); + } catch(UnsupportedClassVersionError e) { Logger.error(this, "Could not load plugin " + filename + " : " + e, e); System.err.println("Could not load plugin " + filename + " : " + e); e.printStackTrace(); - String jvmVersion = System.getProperty("java.version"); - if (jvmVersion.startsWith("1.4.") || jvmVersion.equals("1.4")) { - System.err.println("Plugin " + filename + " appears to require a later JVM"); - Logger.error(this, "Plugin " + filename + " appears to require a later JVM"); - core.alerts.register(new SimpleUserAlert(true, l10n("pluginReqNewerJVMTitle", "name", filename), l10n("pluginReqNewerJVM", "name", filename), l10n("pluginLoadingFailedShort", "name", filename), UserAlert.ERROR, PluginManager.class)); - } + System.err.println("Plugin " + filename + " appears to require a later JVM"); + Logger.error(this, "Plugin " + filename + " appears to require a later JVM"); + core.alerts.register(new SimpleUserAlert(true, l10n("pluginReqNewerJVMTitle", "name", filename), l10n("pluginReqNewerJVM", "name", filename), l10n("pluginLoadingFailedShort", "name", filename), UserAlert.ERROR, PluginManager.class)); } finally { - synchronized (startingPlugins) { + synchronized(startingPlugins) { startingPlugins.remove(pluginProgress); } } /* try not to destroy the config. */ - synchronized (this) { - if (store) + synchronized(this) { + if(store) core.storeConfig(); } } @@ -270,15 +255,15 @@ void register(FredPlugin plug, PluginInfoWrapper pi) { // handles FProxy? If so, register - if (pi.isPproxyPlugin()) + if(pi.isPproxyPlugin()) registerToadlet(plug); - if(pi.isIPDetectorPlugin()) { + if(pi.isIPDetectorPlugin()) node.ipDetector.registerIPDetectorPlugin((FredPluginIPDetector) plug); - } - if(pi.isPortForwardPlugin()) { + if(pi.isPortForwardPlugin()) node.ipDetector.registerPortForwardPlugin((FredPluginPortForward) plug); - } + if(pi.isBandwidthIndicator()) + node.ipDetector.registerBandwidthIndicatorPlugin((FredPluginBandwidthIndicator) plug); } /** @@ -294,7 +279,7 @@ } private String l10n(String key, String pattern, String value) { - return L10n.getString("PluginManager."+key, pattern, value); + return L10n.getString("PluginManager." + key, pattern, value); } /** @@ -313,20 +298,21 @@ return L10n.getString("PluginManager." + key, patterns, values); } - private void registerToadlet(FredPlugin pl){ + private void registerToadlet(FredPlugin pl) { //toadletList.put(e.getStackTrace()[1].getClass().toString(), pl); - synchronized (toadletList) { + synchronized(toadletList) { toadletList.put(pl.getClass().getName(), pl); } - Logger.normal(this, "Added HTTP handler for /plugins/"+pl.getClass().getName()+ '/'); + Logger.normal(this, "Added HTTP handler for /plugins/" + pl.getClass().getName() + '/'); } /** * Remove a plugin from the plugin list. */ public void removePlugin(PluginInfoWrapper pi) { - synchronized (pluginWrappers) { - if(!pluginWrappers.remove(pi)) return; + synchronized(pluginWrappers) { + if(!pluginWrappers.remove(pi)) + return; } core.storeConfig(); } @@ -340,79 +326,77 @@ public void removeCachedCopy(String pluginSpecification) { int lastSlash = pluginSpecification.lastIndexOf('/'); File pluginFile; - if (lastSlash == -1) { + if(lastSlash == -1) /* Windows, maybe? */ lastSlash = pluginSpecification.lastIndexOf('\\'); - } File pluginDirectory = new File(node.getNodeDir(), "plugins"); - if (lastSlash == -1) { + if(lastSlash == -1) /* it's an official plugin! */ pluginFile = new File(pluginDirectory, pluginSpecification + ".jar"); - } else { + else pluginFile = new File(pluginDirectory, pluginSpecification.substring(lastSlash + 1)); - } - if(logDEBUG) Logger.minor(this, "Delete plugin - plugname: " + pluginSpecification + "filename: " + pluginFile.getAbsolutePath() , new Exception("debug")); - if (pluginFile.exists()) { + if(logDEBUG) + Logger.minor(this, "Delete plugin - plugname: " + pluginSpecification + "filename: " + pluginFile.getAbsolutePath(), new Exception("debug")); + if(pluginFile.exists()) pluginFile.delete(); - } } public void unregisterPluginToadlet(PluginInfoWrapper pi) { - synchronized (toadletList) { + synchronized(toadletList) { try { toadletList.remove(pi.getPluginClassName()); - Logger.normal(this, "Removed HTTP handler for /plugins/"+ - pi.getPluginClassName()+ '/', new Exception("debug")); - } catch (Throwable ex) { + Logger.normal(this, "Removed HTTP handler for /plugins/" + + pi.getPluginClassName() + '/', new Exception("debug")); + } catch(Throwable ex) { Logger.error(this, "removing Plugin", ex); } } } public void addToadletSymlinks(PluginInfoWrapper pi) { - synchronized (toadletList) { + synchronized(toadletList) { try { String targets[] = pi.getPluginToadletSymlinks(); - if (targets == null) + if(targets == null) return; - for (int i = 0 ; i < targets.length ; i++) { + for(int i = 0; i < targets.length; i++) { toadletList.remove(targets[i]); Logger.normal(this, "Removed HTTP symlink: " + targets[i] + - " => /plugins/"+pi.getPluginClassName()+ '/'); + " => /plugins/" + pi.getPluginClassName() + '/'); } - } catch (Throwable ex) { + } catch(Throwable ex) { Logger.error(this, "removing Toadlet-link", ex); } } } public void removeToadletSymlinks(PluginInfoWrapper pi) { - synchronized (toadletList) { + synchronized(toadletList) { String rm = null; try { String targets[] = pi.getPluginToadletSymlinks(); - if (targets == null) + if(targets == null) return; - for (int i = 0 ; i < targets.length ; i++) { + for(int i = 0; i < targets.length; i++) { rm = targets[i]; toadletList.remove(targets[i]); pi.removePluginToadletSymlink(targets[i]); Logger.normal(this, "Removed HTTP symlink: " + targets[i] + - " => /plugins/"+pi.getPluginClassName()+ '/'); + " => /plugins/" + pi.getPluginClassName() + '/'); } - } catch (Throwable ex) { + } catch(Throwable ex) { Logger.error(this, "removing Toadlet-link: " + rm, ex); } } } public String dumpPlugins() { - StringBuffer out= new StringBuffer(); - synchronized (pluginWrappers) { - for(int i=0;i<pluginWrappers.size();i++) { - PluginInfoWrapper pi = (PluginInfoWrapper) pluginWrappers.get(i); + StringBuffer out = new StringBuffer(); + synchronized(pluginWrappers) { + for(int i = 0; i < pluginWrappers.size(); i++) { + PluginInfoWrapper pi = pluginWrappers.get(i); out.append(pi.toString()); out.append('\n'); } @@ -422,57 +406,57 @@ public Set getPlugins() { HashSet out = new HashSet(); - synchronized (pluginWrappers) { - for(int i=0;i<pluginWrappers.size();i++) { - PluginInfoWrapper pi = (PluginInfoWrapper) pluginWrappers.get(i); + synchronized(pluginWrappers) { + for(int i = 0; i < pluginWrappers.size(); i++) { + PluginInfoWrapper pi = pluginWrappers.get(i); out.add(pi); } } return out; } - + /** * look for PluginInfo for a FCPPlugin with given classname * @param plugname * @return the PluginInfo or null if not found */ public PluginInfoWrapper getFCPPluginInfo(String plugname) { - synchronized (pluginWrappers) { - for(int i=0;i<pluginWrappers.size();i++) { - PluginInfoWrapper pi = (PluginInfoWrapper) pluginWrappers.get(i); - if (pi.getPluginClassName().equals(plugname)) + synchronized(pluginWrappers) { + for(int i = 0; i < pluginWrappers.size(); i++) { + PluginInfoWrapper pi = pluginWrappers.get(i); + if(pi.getPluginClassName().equals(plugname)) return pi; } } return null; } - + /** * look for a FCPPlugin with given classname * @param plugname * @return the plugin or null if not found */ public FredPluginFCP getFCPPlugin(String plugname) { - synchronized (pluginWrappers) { - for(int i=0;i<pluginWrappers.size();i++) { - PluginInfoWrapper pi = (PluginInfoWrapper) pluginWrappers.get(i); - if (pi.isFCPPlugin() && pi.getPluginClassName().equals(plugname)) + synchronized(pluginWrappers) { + for(int i = 0; i < pluginWrappers.size(); i++) { + PluginInfoWrapper pi = pluginWrappers.get(i); + if(pi.isFCPPlugin() && pi.getPluginClassName().equals(plugname)) return (FredPluginFCP) pi.plug; } } return null; } - + /** * look for a Plugin with given classname * @param plugname * @return the true if not found */ public boolean isPluginLoaded(String plugname) { - synchronized (pluginWrappers) { - for(int i=0;i<pluginWrappers.size();i++) { - PluginInfoWrapper pi = (PluginInfoWrapper) pluginWrappers.get(i); - if (pi.getPluginClassName().equals(plugname)) + synchronized(pluginWrappers) { + for(int i = 0; i < pluginWrappers.size(); i++) { + PluginInfoWrapper pi = pluginWrappers.get(i); + if(pi.getPluginClassName().equals(plugname)) return true; } } @@ -481,30 +465,30 @@ public String handleHTTPGet(String plugin, HTTPRequest request) throws PluginHTTPException { FredPlugin handler = null; - synchronized (toadletList) { - handler = (FredPlugin)toadletList.get(plugin); + synchronized(toadletList) { + handler = (FredPlugin) toadletList.get(plugin); } /*if (handler == null) - return null; + return null; */ - if (handler instanceof FredPluginHTTP) - return ((FredPluginHTTP)handler).handleHTTPGet(request); + if(handler instanceof FredPluginHTTP) + return ((FredPluginHTTP) handler).handleHTTPGet(request); throw new NotFoundPluginHTTPException("Plugin not found!", "/plugins"); } public String handleHTTPPost(String plugin, HTTPRequest request) throws PluginHTTPException { FredPlugin handler = null; - synchronized (toadletList) { - handler = (FredPlugin)toadletList.get(plugin); + synchronized(toadletList) { + handler = (FredPlugin) toadletList.get(plugin); } /*if (handler == null) - return null; + return null; */ - if (handler instanceof FredPluginHTTP) - return ((FredPluginHTTP)handler).handleHTTPPost(request); + if(handler instanceof FredPluginHTTP) + return ((FredPluginHTTP) handler).handleHTTPPost(request); throw new NotFoundPluginHTTPException("Plugin not found!", "/plugins"); } @@ -512,36 +496,33 @@ public void killPlugin(String name, int maxWaitTime) { PluginInfoWrapper pi = null; boolean found = false; - synchronized (pluginWrappers) { - for(int i=0;i<pluginWrappers.size() && !found;i++) { - pi = (PluginInfoWrapper) pluginWrappers.get(i); - if (pi.getThreadName().equals(name)) { + synchronized(pluginWrappers) { + for(int i = 0; i < pluginWrappers.size() && !found; i++) { + pi = pluginWrappers.get(i); + if(pi.getThreadName().equals(name)) { found = true; break; } } } - if (found) { + if(found) pi.stopPlugin(this, maxWaitTime); - } } public void killPlugin(FredPlugin plugin, int maxWaitTime) { PluginInfoWrapper pi = null; boolean found = false; - synchronized (pluginWrappers) { - for(int i=0;i<pluginWrappers.size() && !found;i++) { - pi = (PluginInfoWrapper) pluginWrappers.get(i); - if (pi.plug == plugin) { + synchronized(pluginWrappers) { + for(int i = 0; i < pluginWrappers.size() && !found; i++) { + pi = pluginWrappers.get(i); + if(pi.plug == plugin) found = true; - } } } - if (found) { + if(found) pi.stopPlugin(this, maxWaitTime); - } } - + /** * Returns a list of the names of all available official plugins. Right now * this list is hardcoded but in future we could retrieve this list from emu @@ -550,7 +531,7 @@ * @return A list of all available plugin names */ public List<String> findAvailablePlugins() { - List<String> availablePlugins = new ArrayList<String> (); + List<String> availablePlugins = new ArrayList<String>(); availablePlugins.add("Echo"); availablePlugins.add("Freemail"); availablePlugins.add("HelloWorld"); @@ -566,12 +547,14 @@ availablePlugins.add("XMLSpider"); return availablePlugins; } - + public boolean isOfficialPlugin(String name) { - if ((name == null) || (name.trim().length() == 0)) return false; + if((name == null) || (name.trim().length() == 0)) + return false; List<String> availablePlugins = findAvailablePlugins(); - for(String n:availablePlugins) { - if (n.equals(name)) return true; + for(String n : availablePlugins) { + if(n.equals(name)) + return true; } return false; } @@ -592,12 +575,12 @@ * If anything goes wrong. */ private FredPlugin loadPlugin(PluginDownLoader pdl, String name) throws PluginNotFoundException { - + pdl.setSource(name); - + /* check for plugin directory. */ File pluginDirectory = new File(node.getNodeDir(), "plugins"); - if ((pluginDirectory.exists() && !pluginDirectory.isDirectory()) || (!pluginDirectory.exists() && !pluginDirectory.mkdirs())) { + if((pluginDirectory.exists() && !pluginDirectory.isDirectory()) || (!pluginDirectory.exists() && !pluginDirectory.mkdirs())) { Logger.error(this, "could not create plugin directory"); throw new PluginNotFoundException("could not create plugin directory"); } @@ -607,12 +590,11 @@ File pluginFile = new File(pluginDirectory, filename); /* check if file needs to be downloaded. */ - if (logMINOR) { + if(logMINOR) Logger.minor(this, "plugin file " + pluginFile.getAbsolutePath() + " exists: " + pluginFile.exists()); - } int RETRIES = 5; - for(int i=0;i<RETRIES;i++) { - if (!pluginFile.exists() || pluginFile.length() == 0) { + for(int i = 0; i < RETRIES; i++) { + if(!pluginFile.exists() || pluginFile.length() == 0) try { File tempPluginFile = null; OutputStream pluginOutputStream = null; @@ -620,13 +602,13 @@ try { tempPluginFile = File.createTempFile("plugin-", ".jar", pluginDirectory); tempPluginFile.deleteOnExit(); - - + + pluginOutputStream = new FileOutputStream(tempPluginFile); pluginInputStream = pdl.getInputStream(); byte[] buffer = new byte[1024]; int read; - while ((read = pluginInputStream.read(buffer)) != -1) { + while((read = pluginInputStream.read(buffer)) != -1) { pluginOutputStream.write(buffer, 0, read); } pluginOutputStream.close(); @@ -636,33 +618,32 @@ Logger.error(this, "could not rename temp file to plugin file"); throw new PluginNotFoundException("could not rename temp file to plugin file"); } - + String digest = pdl.getSHA1sum(); - if (digest != null) { + if(digest != null) { String testsum = getFileSHA1(pluginFile); - if (!(digest.equalsIgnoreCase(testsum))) { - Logger.error(this, "Checksum verification failed, should be " +digest+ " but was " + testsum); - throw new PluginNotFoundException("Checksum verification failed, should be " +digest+ " but was " + testsum); + if(!(digest.equalsIgnoreCase(testsum))) { + Logger.error(this, "Checksum verification failed, should be " + digest + " but was " + testsum); + throw new PluginNotFoundException("Checksum verification failed, should be " + digest + " but was " + testsum); } } - - } catch (IOException ioe1) { + + } catch(IOException ioe1) { Logger.error(this, "could not load plugin", ioe1); - if (tempPluginFile != null) { + if(tempPluginFile != null) tempPluginFile.delete(); - } throw new PluginNotFoundException("could not load plugin: " + ioe1.getMessage(), ioe1); } finally { Closer.close(pluginOutputStream); Closer.close(pluginInputStream); } - } catch (PluginNotFoundException e) { - if(i < RETRIES-1) { - Logger.normal(this, "Failed to load plugin: "+e, e); + } catch(PluginNotFoundException e) { + if(i < RETRIES - 1) { + Logger.normal(this, "Failed to load plugin: " + e, e); continue; - } else throw e; + } else + throw e; } - } } /* now get the manifest file. */ @@ -671,32 +652,32 @@ try { pluginJarFile = new JarFile(pluginFile); Manifest manifest = pluginJarFile.getManifest(); - if (manifest == null) { + if(manifest == null) { Logger.error(this, "could not load manifest from plugin file"); pluginFile.delete(); throw new PluginNotFoundException("could not load manifest from plugin file"); } Attributes mainAttributes = manifest.getMainAttributes(); - if (mainAttributes == null) { + if(mainAttributes == null) { Logger.error(this, "manifest does not contain attributes"); pluginFile.delete(); throw new PluginNotFoundException("manifest does not contain attributes"); } pluginMainClassName = mainAttributes.getValue("Plugin-Main-Class"); - if (pluginMainClassName == null) { + if(pluginMainClassName == null) { Logger.error(this, "manifest does not contain a Plugin-Main-Class attribute"); pluginFile.delete(); throw new PluginNotFoundException("manifest does not contain a Plugin-Main-Class attribute"); } - } catch (JarException je1) { + } catch(JarException je1) { Logger.error(this, "could not process jar file", je1); pluginFile.delete(); throw new PluginNotFoundException("could not process jar file", je1); - } catch (ZipException ze1) { + } catch(ZipException ze1) { Logger.error(this, "could not process jar file", ze1); pluginFile.delete(); throw new PluginNotFoundException("could not process jar file", ze1); - } catch (IOException ioe1) { + } catch(IOException ioe1) { Logger.error(this, "error processing jar file", ioe1); pluginFile.delete(); throw new PluginNotFoundException("error procesesing jar file", ioe1); @@ -708,36 +689,36 @@ JarClassLoader jarClassLoader = new JarClassLoader(pluginFile); Class pluginMainClass = jarClassLoader.loadClass(pluginMainClassName); Object object = pluginMainClass.newInstance(); - if (!(object instanceof FredPlugin)) { + if(!(object instanceof FredPlugin)) { Logger.error(this, "plugin main class is not a plugin"); pluginFile.delete(); throw new PluginNotFoundException("plugin main class is not a plugin"); } return (FredPlugin) object; - } catch (IOException ioe1) { + } catch(IOException ioe1) { Logger.error(this, "could not load plugin", ioe1); pluginFile.delete(); throw new PluginNotFoundException("could not load plugin", ioe1); - } catch (ClassNotFoundException cnfe1) { + } catch(ClassNotFoundException cnfe1) { Logger.error(this, "could not find plugin class", cnfe1); pluginFile.delete(); throw new PluginNotFoundException("could not find plugin class", cnfe1); - } catch (InstantiationException ie1) { + } catch(InstantiationException ie1) { Logger.error(this, "could not instantiate plugin", ie1); pluginFile.delete(); throw new PluginNotFoundException("could not instantiate plugin", ie1); - } catch (IllegalAccessException iae1) { + } catch(IllegalAccessException iae1) { Logger.error(this, "could not access plugin main class", iae1); pluginFile.delete(); throw new PluginNotFoundException("could not access plugin main class", iae1); - } catch (NoClassDefFoundError ncdfe1) { + } catch(NoClassDefFoundError ncdfe1) { Logger.error(this, "could not find class def, may a missing lib?", ncdfe1); pluginFile.delete(); throw new PluginNotFoundException("could not find class def, may a missing lib?", ncdfe1); - } catch (Throwable t) { + } catch(Throwable t) { Logger.error(this, "unexcpected error while plugin loading", t); pluginFile.delete(); - throw new PluginNotFoundException("unexcpected error while plugin loading "+t, t); + throw new PluginNotFoundException("unexcpected error while plugin loading " + t, t); } } @@ -746,7 +727,7 @@ MessageDigest hash = null; FileInputStream fis = null; BufferedInputStream bis = null; - + try { hash = MessageDigest.getInstance("SHA-1"); // We compute the hash @@ -757,9 +738,9 @@ byte[] buffer = new byte[BUFFERSIZE]; while((len = bis.read(buffer)) > -1) { hash.update(buffer, 0, len); - } - } catch (Exception e) { - throw new PluginNotFoundException("Error while computing sha1 hash of the downloaded plugin: "+e, e); + } + } catch(Exception e) { + throw new PluginNotFoundException("Error while computing sha1 hash of the downloaded plugin: " + e, e); } finally { Closer.close(bis); Closer.close(fis); @@ -781,16 +762,12 @@ /** State for downloading. */ public static final PluginProgress DOWNLOADING = new PluginProgress(); - /** State for starting. */ public static final PluginProgress STARTING = new PluginProgress(); - /** The starting time. */ private long startingTime = System.currentTimeMillis(); - /** The current state. */ private PluginProgress pluginProgress; - /** The name by which the plugin is loaded. */ private String name; @@ -859,16 +836,13 @@ * * @return The name of a constant, or the plugin progress */ - /* @Override */ + @Override public String toString() { - if (this == DOWNLOADING) { + if(this == DOWNLOADING) return "downloading"; - } else if (this == STARTING) { + else if(this == STARTING) return "starting"; - } return "PluginProgress[name=" + name + ",startingTime=" + startingTime + ",progress=" + pluginProgress + "]"; } - } - } Modified: branches/db4o/freenet/src/freenet/store/RAMFreenetStore.java =================================================================== --- branches/db4o/freenet/src/freenet/store/RAMFreenetStore.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/store/RAMFreenetStore.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -17,7 +17,7 @@ byte[] fullKey; } - private final LRUHashtable blocksByRoutingKey; + private final LRUHashtable<ByteArrayWrapper, Block> blocksByRoutingKey; private final StoreCallback callback; @@ -29,7 +29,7 @@ public RAMFreenetStore(StoreCallback callback, int maxKeys) { this.callback = callback; - this.blocksByRoutingKey = new LRUHashtable(); + this.blocksByRoutingKey = new LRUHashtable<ByteArrayWrapper, Block>(); this.maxKeys = maxKeys; callback.setStore(this); } @@ -37,7 +37,7 @@ public synchronized StorableBlock fetch(byte[] routingKey, byte[] fullKey, boolean dontPromote) throws IOException { ByteArrayWrapper key = new ByteArrayWrapper(routingKey); - Block block = (Block) blocksByRoutingKey.get(key); + Block block = blocksByRoutingKey.get(key); if(block == null) { misses++; return null; @@ -77,7 +77,7 @@ KeyCollisionException { writes++; ByteArrayWrapper key = new ByteArrayWrapper(routingkey); - Block oldBlock = (Block) blocksByRoutingKey.get(key); + Block oldBlock = blocksByRoutingKey.get(key); boolean storeFullKeys = callback.storeFullKeys(); if(oldBlock != null) { if(callback.collisionPossible()) { Modified: branches/db4o/freenet/src/freenet/support/DoublyLinkedList.java =================================================================== --- branches/db4o/freenet/src/freenet/support/DoublyLinkedList.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/DoublyLinkedList.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -6,36 +6,36 @@ * Framework for managing a doubly linked list. * @author tavin */ -public interface DoublyLinkedList { - public abstract Object clone(); +public interface DoublyLinkedList<T> { + public abstract DoublyLinkedList<T> clone(); /** * List element */ - public interface Item { + public interface Item<T> { /** * Get next {@link Item}. May or may not return * <code>null</code> if this is the last <code>Item</code>. * * @see DoublyLinkedList#hasNext() */ - Item getNext(); + DoublyLinkedList.Item<T> getNext(); /** Set next {@link Item} */ - Item setNext(Item i); + DoublyLinkedList.Item<T> setNext(DoublyLinkedList.Item<T> i); /** * Get previous {@link Item}. May or may not return <code>null</code> * if this is the first <code>Item</code>. * * @see DoublyLinkedList#hasNext() */ - Item getPrev(); + Item<T> getPrev(); /** Get previous {@link Item} */ - Item setPrev(Item i); + Item<T> setPrev(DoublyLinkedList.Item<T> i); /** Return the contained list. <strong>For sanity checking only.</strong> */ - DoublyLinkedList getParent(); + DoublyLinkedList<T> getParent(); /** Set the contained list. <strong>For sanity checking only.</strong>*/ - DoublyLinkedList setParent(DoublyLinkedList l); + DoublyLinkedList<T> setParent(DoublyLinkedList<T> l); } /** Clear this list */ @@ -61,11 +61,11 @@ /** * Puts the item before the first item. */ - void unshift(Item i); + void unshift(DoublyLinkedList.Item<T> i); /** * Put all items in the specified list before the first item. */ - void unshift(DoublyLinkedList l); + void unshift(DoublyLinkedList<T> l); /** * Removes and returns the first item. */ @@ -73,16 +73,16 @@ /** * Remove <tt>n</tt> elements from head and return them as a <code>DoublyLinkedList</code>. */ - DoublyLinkedList shift(int n); + DoublyLinkedList<T> shift(int n); /** * Puts the item after the last item. */ - void push(Item i); + void push(DoublyLinkedList.Item<T> i); /** * Puts all items in the specified list after the last item. */ - void push(DoublyLinkedList l); + void push(DoublyLinkedList<T> l); /** * Removes and returns the last item. */ @@ -93,34 +93,34 @@ DoublyLinkedList pop(int n); /** @return <code>true</code> if <code>i</code> has next item. (ie. not the last item); <code>false</code> otherwise */ - boolean hasNext(Item i); + boolean hasNext(DoublyLinkedList.Item<T> i); /** @return <code>true</code> if <code>i</code> has previous item. (ie. not the first item); <code>false</code> otherwise */ - boolean hasPrev(Item i); + boolean hasPrev(DoublyLinkedList.Item<T> i); /** @return next item of <code>i</code>. If this is the last element, return <code>null</code> */ - Item next(Item i); + Item next(DoublyLinkedList.Item<T> i); /** @return previous item of <code>i</code>. If this is the first element, return <code>null</code> */ - Item prev(Item i); + Item prev(DoublyLinkedList.Item<T> i); /** Remove and return a element * @return this item, or <code>null</code> if the item was not in the list */ - Item remove(Item i); + Item remove(DoublyLinkedList.Item<T> i); /** * Inserts item <code>j</code> before item <code>i</code>. */ - void insertPrev(Item i, Item j); + void insertPrev(DoublyLinkedList.Item<T> i, DoublyLinkedList.Item<T> j); /** * Inserts the entire {@link DoublyLinkedList} <code>l</code> before item <code>i</code>. */ - void insertPrev(Item i, DoublyLinkedList l); + void insertPrev(DoublyLinkedList.Item<T> i, DoublyLinkedList<T> l); /** * Inserts item <code>j</code> after item <code>i</code. */ - void insertNext(Item i, Item j); + void insertNext(DoublyLinkedList.Item<T> i, DoublyLinkedList.Item<T> j); /** * Inserts the entire {@link DoublyLinkedList} <code>l</code> after item <code>i</code>. */ - void insertNext(Item i, DoublyLinkedList l); + void insertNext(DoublyLinkedList.Item<T> i, DoublyLinkedList<T> l); } Modified: branches/db4o/freenet/src/freenet/support/DoublyLinkedListImpl.java =================================================================== --- branches/db4o/freenet/src/freenet/support/DoublyLinkedListImpl.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/DoublyLinkedListImpl.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -10,27 +10,28 @@ * TODO: there are still some unimplemented methods * -- it remains to be seen if they are needed at all */ -public class DoublyLinkedListImpl implements DoublyLinkedList { +public class DoublyLinkedListImpl<T> implements DoublyLinkedList<T>{ protected int size; - protected Item _headptr, _tailptr; + protected DoublyLinkedListImpl.Item<T> _headptr, _tailptr; - public final Object clone() { - return new DoublyLinkedListImpl(this); + @Override + public final DoublyLinkedListImpl<T> clone() { + return new DoublyLinkedListImpl<T>(this); } /** * A new list with no items. */ public DoublyLinkedListImpl() { - _headptr = new Item(); - _tailptr = new Item(); + _headptr = new Item<T>(); + _tailptr = new Item<T>(); _headptr.setParent(this); _tailptr.setParent(this); clear(); } - protected DoublyLinkedListImpl(Item _h, Item _t, int size) { + protected DoublyLinkedListImpl(DoublyLinkedListImpl.Item<T> _h, DoublyLinkedListImpl.Item<T> _t, int size) { _headptr = _h; _tailptr = _t; _headptr.setParent(this); @@ -44,11 +45,11 @@ */ protected DoublyLinkedListImpl(DoublyLinkedListImpl impl) { this(); - Enumeration e = impl.forwardElements(); + Enumeration<DoublyLinkedListImpl.Item<T>> e = impl.forwardElements(); boolean checked = false; for(;e.hasMoreElements();) { - Item oi = (Item)e.nextElement(); - Item i = (Item) oi.clone(); + DoublyLinkedListImpl.Item<T> oi = e.nextElement(); + DoublyLinkedList.Item<T> i = oi.clone(); if(!checked) { checked = true; if(!i.getClass().getName().equals(oi.getClass().getName())) { @@ -69,8 +70,8 @@ // Help to detect removal after clear(). // The check in remove() is enough, strictly, // as long as people don't add elements afterwards. - DoublyLinkedList.Item pos = _headptr.next; - DoublyLinkedList.Item opos = _headptr; + DoublyLinkedList.Item<T> pos = _headptr.next; + DoublyLinkedList.Item<T> opos = _headptr; while(true) { if(pos == _tailptr) break; if(pos == null) break; @@ -103,21 +104,21 @@ * {@inheritDoc} * @see #forwardElements() */ - public final Enumeration elements() { + public final Enumeration<DoublyLinkedList.Item<T>> elements() { return forwardElements(); } /** * {@inheritDoc} */ - public final DoublyLinkedList.Item head() { + public final DoublyLinkedList.Item<T> head() { return size == 0 ? null : _headptr.next; } /** * {@inheritDoc} */ - public final DoublyLinkedList.Item tail() { + public final DoublyLinkedList.Item<T> tail() { return size == 0 ? null : _tailptr.prev; } @@ -126,7 +127,7 @@ /** * {@inheritDoc} */ - public final void unshift(DoublyLinkedList.Item i) { + public final void unshift(DoublyLinkedList.Item<T> i) { insertNext(_headptr, i); } @@ -134,30 +135,30 @@ * {@inheritDoc} * FIXME: unimplemented */ - public void unshift(DoublyLinkedList l) { + public void unshift(DoublyLinkedList<T> l) { throw new RuntimeException("function currently unimplemented because i am a lazy sod"); } /** * {@inheritDoc} */ - public final DoublyLinkedList.Item shift() { + public final DoublyLinkedList.Item<T> shift() { return size == 0 ? null : remove(_headptr.next); } /** * {@inheritDoc} */ - public DoublyLinkedList shift(int n) { + public DoublyLinkedList<T> shift(int n) { if (n > size) n = size; - if (n < 1) return new DoublyLinkedListImpl(); + if (n < 1) return new DoublyLinkedListImpl<T>(); - DoublyLinkedList.Item i = _headptr; + DoublyLinkedList.Item<T> i = _headptr; for (int m=0; m<n; ++m) i = i.getNext(); - DoublyLinkedList.Item j = i.getNext(); - Item newheadptr = new Item(); - Item newtailptr = new Item(); + DoublyLinkedList.Item<T> j = i.getNext(); + Item<T> newheadptr = new Item<T>(); + Item<T> newtailptr = new Item<T>(); j.setPrev(newheadptr); newheadptr.setNext(j); @@ -165,7 +166,7 @@ i.setNext(newtailptr); newtailptr.setPrev(i); - DoublyLinkedList newlist = new DoublyLinkedListImpl(_headptr, newtailptr, n); + DoublyLinkedList<T> newlist = new DoublyLinkedListImpl<T>(_headptr, newtailptr, n); _headptr = newheadptr; _headptr.setParent(this); size -= n; @@ -178,37 +179,37 @@ /** * {@inheritDoc} */ - public final void push(DoublyLinkedList.Item i) { + public final void push(DoublyLinkedList.Item<T> i) { insertPrev(_tailptr, i); } /** * {@inheritDoc} * FIXME: unimplemented */ - public void push(DoublyLinkedList l) { + public void push(DoublyLinkedList<T> l) { throw new RuntimeException("function currently unimplemented because i am a lazy sod"); } /** * {@inheritDoc} */ - public final DoublyLinkedList.Item pop() { + public final DoublyLinkedList.Item<T> pop() { return size == 0 ? null : remove(_tailptr.prev); } /** * {@inheritDoc} */ - public DoublyLinkedList pop(int n) { + public DoublyLinkedList<T> pop(int n) { if (n > size) n = size; - if (n < 1) return new DoublyLinkedListImpl(); + if (n < 1) return new DoublyLinkedListImpl<T>(); - DoublyLinkedList.Item i = _tailptr; + DoublyLinkedList.Item<T> i = _tailptr; for (int m=0; m<n; ++m) i = i.getPrev(); - DoublyLinkedList.Item j = i.getPrev(); - Item newtailptr = new Item(); - Item newheadptr = new Item(); + DoublyLinkedList.Item<T> j = i.getPrev(); + DoublyLinkedListImpl.Item<T> newtailptr = new Item<T>(); + DoublyLinkedListImpl.Item<T> newheadptr = new Item<T>(); j.setNext(newtailptr); newtailptr.setPrev(j); @@ -217,7 +218,7 @@ i.setPrev(newheadptr); newheadptr.setNext(i); - DoublyLinkedList newlist = new DoublyLinkedListImpl(newheadptr, _tailptr, n); + DoublyLinkedList<T> newlist = new DoublyLinkedListImpl<T>(newheadptr, _tailptr, n); _tailptr = newtailptr; size -= n; @@ -229,29 +230,29 @@ /** * {@inheritDoc} */ - public final boolean hasNext(DoublyLinkedList.Item i) { - DoublyLinkedList.Item next = i.getNext(); + public final boolean hasNext(DoublyLinkedList.Item<T> i) { + DoublyLinkedList.Item<T> next = i.getNext(); return (next != null) && (next != _tailptr); } /** * {@inheritDoc} */ - public final boolean hasPrev(DoublyLinkedList.Item i) { - DoublyLinkedList.Item prev = i.getPrev(); + public final boolean hasPrev(DoublyLinkedList.Item<T> i) { + DoublyLinkedList.Item<T> prev = i.getPrev(); return (prev != null) && (prev != _headptr); } /** * {@inheritDoc} */ - public final DoublyLinkedList.Item next(DoublyLinkedList.Item i) { - DoublyLinkedList.Item next = i.getNext(); + public final DoublyLinkedList.Item<T> next(DoublyLinkedList.Item<T> i) { + DoublyLinkedList.Item<T> next = i.getNext(); return next == _tailptr ? null : next; } /** * {@inheritDoc} */ - public final DoublyLinkedList.Item prev(DoublyLinkedList.Item i) { - DoublyLinkedList.Item prev = i.getPrev(); + public final DoublyLinkedList.Item<T> prev(DoublyLinkedList.Item<T> i) { + DoublyLinkedList.Item<T> prev = i.getPrev(); return prev == _headptr ? null : prev; } @@ -261,7 +262,7 @@ /** * {@inheritDoc} */ - public DoublyLinkedList.Item remove(DoublyLinkedList.Item i) { + public DoublyLinkedList.Item<T> remove(DoublyLinkedList.Item<T> i) { if (i.getParent() == null) return null; // not in list if(isEmpty()) { Logger.error(this, "Illegal ERROR: Removing from an empty list!!"); @@ -269,7 +270,7 @@ } if (i.getParent() != this) throw new PromiscuousItemException(i, i.getParent()); - DoublyLinkedList.Item next = i.getNext(), prev = i.getPrev(); + DoublyLinkedList.Item<T> next = i.getNext(), prev = i.getPrev(); if ((next == null) && (prev == null)) return null; // not in the list if ((next == null) || (prev == null)) throw new NullPointerException("next="+next+", prev="+prev); // partially in the list?! @@ -290,7 +291,7 @@ /** * {@inheritDoc} */ - public void insertPrev(DoublyLinkedList.Item i, DoublyLinkedList.Item j) { + public void insertPrev(DoublyLinkedList.Item<T> i, DoublyLinkedList.Item<T> j) { if (i.getParent() == null) throw new PromiscuousItemException(i, i.getParent()); // different trace to make easier debugging if (i.getParent() != this) @@ -299,7 +300,7 @@ throw new PromiscuousItemException(j, j.getParent()); if ((j.getNext() != null) || (j.getPrev() != null)) throw new PromiscuousItemException(j); - DoublyLinkedList.Item prev = i.getPrev(); + DoublyLinkedList.Item<T> prev = i.getPrev(); if (prev == null) throw new VirginItemException(i); prev.setNext(j); @@ -314,14 +315,14 @@ * {@inheritDoc} * FIXME: unimplemented */ - public void insertPrev(DoublyLinkedList.Item i, DoublyLinkedList l) { + public void insertPrev(DoublyLinkedList.Item<T> i, DoublyLinkedList<T> l) { throw new RuntimeException("function currently unimplemented because i am a lazy sod"); } /** * {@inheritDoc} */ - public void insertNext(DoublyLinkedList.Item i, DoublyLinkedList.Item j) { + public void insertNext(DoublyLinkedList.Item<T> i, DoublyLinkedList.Item<T> j) { if (i.getParent() != this) throw new PromiscuousItemException(i, i.getParent()); if (j.getParent() != null) @@ -343,7 +344,7 @@ * {@inheritDoc} * FIXME: unimplemented */ - public void insertNext(DoublyLinkedList.Item i, DoublyLinkedList l) { + public void insertNext(DoublyLinkedList.Item<T> i, DoublyLinkedList<T> l) { throw new RuntimeException("function currently unimplemented because i am a lazy sod"); } @@ -353,54 +354,54 @@ /** * @return an Enumeration of list elements from head to tail */ - private Enumeration forwardElements() { + private Enumeration<DoublyLinkedList.Item<T>> forwardElements() { return new ForwardWalker(); } /** * @return an Enumeration of list elements from tail to head */ - protected Enumeration reverseElements() { + protected Enumeration<DoublyLinkedList.Item<T>> reverseElements() { return new ReverseWalker(); } - private class ForwardWalker implements Enumeration { - protected DoublyLinkedList.Item next; + private class ForwardWalker<T extends DoublyLinkedListImpl.Item<T>> implements Enumeration<DoublyLinkedList.Item<T>> { + protected DoublyLinkedList.Item<T> next; protected ForwardWalker() { next = _headptr.getNext(); } - protected ForwardWalker(DoublyLinkedList.Item startAt, + protected ForwardWalker(DoublyLinkedList.Item<T> startAt, boolean inclusive) { next = (inclusive ? startAt : startAt.getNext()); } public final boolean hasMoreElements() { return next != _tailptr; } - public Object nextElement() { + public DoublyLinkedList.Item<T> nextElement() { if (next == _tailptr) throw new NoSuchElementException(); - DoublyLinkedList.Item result = next; + DoublyLinkedList.Item<T> result = next; next = next.getNext(); return result; } } - private class ReverseWalker implements Enumeration { - protected DoublyLinkedList.Item next; + private class ReverseWalker<T extends DoublyLinkedList.Item<T>> implements Enumeration<DoublyLinkedList.Item<T>> { + protected DoublyLinkedList.Item<T> next; protected ReverseWalker() { next = _tailptr.getPrev(); } - protected ReverseWalker(DoublyLinkedList.Item startAt, + protected ReverseWalker(DoublyLinkedList.Item<T> startAt, boolean inclusive) { next = (inclusive ? startAt : startAt.getPrev()); } public final boolean hasMoreElements() { return next != _headptr; } - public Object nextElement() { + public DoublyLinkedList.Item<T> nextElement() { if (next == _headptr) throw new NoSuchElementException(); - DoublyLinkedList.Item result = next; + DoublyLinkedList.Item<T> result = next; if(next == null) throw new IllegalStateException("next==null"); next = next.getPrev(); return result; @@ -410,35 +411,36 @@ //=== list element ==================================================== - public static class Item implements DoublyLinkedList.Item { - private DoublyLinkedList.Item prev; - private DoublyLinkedList.Item next; + public static class Item<T> implements DoublyLinkedList.Item<T> { + private DoublyLinkedList.Item<T> prev; + private DoublyLinkedList.Item<T> next; private DoublyLinkedList list; - public Object clone() { + @Override + public DoublyLinkedList.Item<T> clone() { if(getClass() != Item.class) throw new RuntimeException("Must implement clone() for "+getClass()); - return new Item(); + return new Item<T>(); } public final DoublyLinkedList.Item getNext() { return next; } - public final DoublyLinkedList.Item setNext(DoublyLinkedList.Item i) { - DoublyLinkedList.Item old = next; + public final DoublyLinkedList.Item setNext(DoublyLinkedList.Item<T> i) { + DoublyLinkedList.Item<T> old = next; next = i; return old; } public final DoublyLinkedList.Item getPrev() { return prev; } - public final DoublyLinkedList.Item setPrev(DoublyLinkedList.Item i) { - DoublyLinkedList.Item old = prev; + public final DoublyLinkedList.Item setPrev(DoublyLinkedList.Item<T> i) { + DoublyLinkedList.Item<T> old = prev; prev = i; return old; } public DoublyLinkedList getParent() { return list; } - public DoublyLinkedList setParent(DoublyLinkedList l) { + public DoublyLinkedList setParent(DoublyLinkedList<T> l) { DoublyLinkedList old = list; list = l; return old; Modified: branches/db4o/freenet/src/freenet/support/Fields.java =================================================================== --- branches/db4o/freenet/src/freenet/support/Fields.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/Fields.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -60,6 +60,15 @@ 'y', 'z' }; + private static final long[] MULTIPLES = { + 1000, 1l << 10, + 1000 * 1000, 1l << 20, + 1000l * 1000l * 1000l, 1l << 30, + 1000l * 1000l * 1000l * 1000l, 1l << 40, + 1000l * 1000l * 1000l * 1000l * 1000, 1l << 50, + 1000l * 1000l * 1000l * 1000l * 1000l * 1000l, 1l << 60 + }; + /** * Converts a hex string into a long. Long.parseLong(hex, 16) assumes the * input is nonnegative unless there is a preceding minus sign. This method @@ -597,23 +606,20 @@ } /** - * Parse a human-readable string possibly including SI units into a short. + * Parse a human-readable string possibly including SI and ICE units into a short. * @throws NumberFormatException * if the string is not parseable */ - public static short parseSIShort(String s) throws NumberFormatException { + public static short parseShort(String s) throws NumberFormatException { + s = s.replaceFirst("(i)*B$", ""); short res = 1; int x = s.length() - 1; int idx; try { - long[] l = - { - 1000, - 1 << 10 }; while ((x >= 0) && ((idx = "kK".indexOf(s.charAt(x))) != -1)) { x--; - res *= l[idx]; + res *= MULTIPLES[idx]; } res *= Double.parseDouble(s.substring(0, x + 1)); } catch (ArithmeticException e) { @@ -624,27 +630,20 @@ } /** - * Parse a human-readable string possibly including SI units into an integer. + * Parse a human-readable string possibly including SI and ICE units into an integer. * @throws NumberFormatException * if the string is not parseable */ - public static int parseSIInt(String s) throws NumberFormatException { + public static int parseInt(String s) throws NumberFormatException { + s = s.replaceFirst("(i)*B$", ""); int res = 1; int x = s.length() - 1; int idx; try { - long[] l = - { - 1000, - 1 << 10, - 1000 * 1000, - 1 << 20, - 1000 * 1000 * 1000, - 1 << 30 }; while ((x >= 0) && ((idx = "kKmMgG".indexOf(s.charAt(x))) != -1)) { x--; - res *= l[idx]; + res *= MULTIPLES[idx]; } res *= Double.parseDouble(s.substring(0, x + 1)); } catch (ArithmeticException e) { @@ -655,33 +654,20 @@ } /** - * Parse a human-readable string possibly including SI units into a long. + * Parse a human-readable string possibly including SI and ICE units into a long. * @throws NumberFormatException * if the string is not parseable */ - public static long parseSILong(String s) throws NumberFormatException { + public static long parseLong(String s) throws NumberFormatException { + s = s.replaceFirst("(i)*B$", ""); long res = 1; int x = s.length() - 1; int idx; try { - long[] l = - { - 1000, - 1 << 10, - 1000 * 1000, - 1 << 20, - 1000l * 1000l * 1000l, - 1l << 30, - 1000l * 1000l * 1000l * 1000l, - 1l << 40, - 1000l * 1000l * 1000l * 1000l * 1000, - 1l << 50, - 1000l * 1000l * 1000l * 1000l * 1000l * 1000l, - 1l << 60 }; while ((x >= 0) && ((idx = "kKmMgGtTpPeE".indexOf(s.charAt(x))) != -1)) { x--; - res *= l[idx]; + res *= MULTIPLES[idx]; } String multiplier = s.substring(0, x + 1).trim(); if(multiplier.indexOf('.') > -1 || multiplier.indexOf('E') > -1) { @@ -698,6 +684,60 @@ return res; } + public static String longToString(long val) { + String[] u = { "k", "K", "m", "M", "g", "G", "t", "T", "p", "P", "e", "E" }; + String ret = Long.toString(val); + + if (val <= 0) + return ret; + + for (int i = MULTIPLES.length - 1; i >= 0; i--) { + if (val > MULTIPLES[i] && val % MULTIPLES[i] == 0) { + ret = (val / MULTIPLES[i]) + u[i]; + if (!u[i].toLowerCase().equals(u[i])) + ret += "iB"; + break; + } + } + return ret; + } + + public static String intToString(int val) { + String[] u = { "k", "K", "m", "M", "g", "G", "t", "T", "p", "P", "e", "E" }; + String ret = Integer.toString(val); + + if (val <= 0) + return ret; + + for (int i = MULTIPLES.length - 1; i >= 0; i--) { + if (val > MULTIPLES[i] && val % MULTIPLES[i] == 0) { + ret = (val / MULTIPLES[i]) + u[i]; + if (!u[i].toLowerCase().equals(u[i])) + ret += "iB"; + break; + } + } + return ret; + } + + public static String shortToString(short val) { + String[] u = { "k", "K", "m", "M", "g", "G", "t", "T", "p", "P", "e", "E" }; + String ret = Short.toString(val); + + if (val <= 0) + return ret; + + for (int i = MULTIPLES.length - 1; i >= 0; i--) { + if (val > MULTIPLES[i] && val % MULTIPLES[i] == 0) { + ret = (val / MULTIPLES[i]) + u[i]; + if (!u[i].toLowerCase().equals(u[i])) + ret += "iB"; + break; + } + } + return ret; + } + public static double[] bytesToDoubles(byte[] data, int offset, int length) { long[] longs = bytesToLongs(data, offset, length); double[] doubles = new double[longs.length]; Modified: branches/db4o/freenet/src/freenet/support/FileLoggerHook.java =================================================================== --- branches/db4o/freenet/src/freenet/support/FileLoggerHook.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/FileLoggerHook.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -1,6 +1,7 @@ package freenet.support; import java.io.BufferedOutputStream; +import java.io.Closeable; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; @@ -32,7 +33,7 @@ * * @author oskar */ -public class FileLoggerHook extends LoggerHook { +public class FileLoggerHook extends LoggerHook implements Closeable { /** Verbosity types */ public static final int DATE = 1, Modified: branches/db4o/freenet/src/freenet/support/HTMLEncoder.java =================================================================== --- branches/db4o/freenet/src/freenet/support/HTMLEncoder.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/HTMLEncoder.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -18,16 +18,16 @@ public static String encode(String s) { int n = s.length(); - StringBuffer sb = new StringBuffer(n); + StringBuilder sb = new StringBuilder(n); encodeToBuffer(n, s, sb); return sb.toString(); } - public static void encodeToBuffer(String s, StringBuffer sb) { + public static void encodeToBuffer(String s, StringBuilder sb) { encodeToBuffer(s.length(), s, sb); } - private static void encodeToBuffer(int n, String s, StringBuffer sb) { + private static void encodeToBuffer(int n, String s, StringBuilder sb) { for (int i = 0; i < n; i++) { char c = s.charAt(i); if(Character.isLetterOrDigit(c)){ //only special characters need checking @@ -48,7 +48,7 @@ private String[] strings; private int modulo = 0; - public CharTable(HashMap map){ + public CharTable(HashMap<Character, String> map){ int[] keys = new int[map.size()]; int keyIndex = 0; @@ -84,7 +84,7 @@ character = ((Character)it.next()); keyIndex = character.charValue()%modulo; chars[keyIndex] = character.charValue(); - strings[keyIndex] = (String) map.get(character); + strings[keyIndex] = map.get(character); } if (chars[0] == 0 && strings[0] != null) chars[0] = 1; } Modified: branches/db4o/freenet/src/freenet/support/HTMLNode.java =================================================================== --- branches/db4o/freenet/src/freenet/support/HTMLNode.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/HTMLNode.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -19,9 +19,9 @@ private final String content; - private final Map attributes = new HashMap(); + private final Map<String, String> attributes = new HashMap<String, String>(); - protected final List children = new ArrayList(); + protected final List<HTMLNode> children = new ArrayList<HTMLNode>(); public HTMLNode(String name) { this(name, null); @@ -61,7 +61,7 @@ } } this.name = name.toLowerCase(Locale.ENGLISH); - if (content != null && !name.equals("#") && !name.equals("%")) { + if (content != null && !("#").equals(name)&& !("%").equals(name)) { addChild(new HTMLNode("#", content)); this.content = null; } else @@ -83,12 +83,12 @@ attributes.put(attributeName, attributeValue); } - public Map getAttributes() { + public Map<String, String> getAttributes() { return Collections.unmodifiableMap(attributes); } public String getAttribute(String attributeName) { - return (String) attributes.get(attributeName); + return attributes.get(attributeName); } public HTMLNode addChild(HTMLNode childNode) { @@ -142,11 +142,11 @@ * "real" tag could be found */ public String getFirstTag() { - if (!name.equals("#")) { + if (!"#".equals(name)) { return name; } for (int childIndex = 0, childCount = children.size(); childIndex < childCount; childIndex++) { - HTMLNode childNode = (HTMLNode) children.get(childIndex); + HTMLNode childNode = children.get(childIndex); String tag = childNode.getFirstTag(); if (tag != null) { return tag; @@ -156,28 +156,29 @@ } public String generate() { - StringBuffer tagBuffer = new StringBuffer(); + StringBuilder tagBuffer = new StringBuilder(); return generate(tagBuffer).toString(); } - public StringBuffer generate(StringBuffer tagBuffer) { - if (name.equals("#") && (content != null)) { - HTMLEncoder.encodeToBuffer(content, tagBuffer); + public StringBuilder generate(StringBuilder tagBuffer) { + if("#".equals(name)) { + if(content != null) { + HTMLEncoder.encodeToBuffer(content, tagBuffer); + return tagBuffer; + } + + for(int childIndex = 0, childCount = children.size(); childIndex < childCount; childIndex++) { + HTMLNode childNode = children.get(childIndex); + childNode.generate(tagBuffer); + } return tagBuffer; } // Perhaps this should be something else, but since I don't know if '#' was not just arbitrary chosen, I'll just pick '%' // This allows non-encoded text to be appended to the tag buffer - if (name.equals("%")) { + if ("%".equals(name)) { tagBuffer.append(content); return tagBuffer; } - if (name.equals("#")) { - for (int childIndex = 0, childCount = children.size(); childIndex < childCount; childIndex++) { - HTMLNode childNode = (HTMLNode) children.get(childIndex); - childNode.generate(tagBuffer); - } - return tagBuffer; - } tagBuffer.append('<').append(name); Set attributeSet = attributes.entrySet(); for (Iterator attributeIterator = attributeSet.iterator(); attributeIterator.hasNext();) { @@ -188,25 +189,25 @@ HTMLEncoder.encodeToBuffer(attributeName, tagBuffer); tagBuffer.append("=\""); HTMLEncoder.encodeToBuffer(attributeValue, tagBuffer); - tagBuffer.append('"');; + tagBuffer.append('"'); } if (children.size() == 0) { - if (name.equals("textarea") || name.equals("div") || name.equals("a")) { - tagBuffer.append("></").append(name).append('>'); + if ("textarea".equals(name) || ("div").equals(name) || ("a").equals(name)) { + tagBuffer.append("></").append(name).append('>'); } else { tagBuffer.append(" />"); } } else { tagBuffer.append('>'); - if(name.equals("div") || name.equals("form") || name.equals("input") || name.equals("script") || name.equals("table") || name.equals("tr") || name.equals("td")) { + if(("div").equals(name) || ("form").equals(name) || ("input").equals(name) || ("script").equals(name) || ("table").equals(name) || ("tr").equals(name) || ("td").equals(name)) { tagBuffer.append('\n'); } for (int childIndex = 0, childCount = children.size(); childIndex < childCount; childIndex++) { - HTMLNode childNode = (HTMLNode) children.get(childIndex); + HTMLNode childNode = children.get(childIndex); childNode.generate(tagBuffer); } tagBuffer.append("</").append(name).append('>'); - if(name.equals("div") || name.equals("form") || name.equals("input") || name.equals("li") || name.equals("option") || name.equals("script") || name.equals("table") || name.equals("tr") || name.equals("td")) { + if(("div").equals(name)|| ("form").equals(name)|| ("input").equals(name)|| ("li").equals(name)|| ("option").equals(name)|| ("script").equals(name)|| ("table").equals(name)|| ("tr").equals(name)|| ("td").equals(name)) { tagBuffer.append('\n'); } } @@ -236,12 +237,13 @@ /** * @see freenet.support.HTMLNode#generate(java.lang.StringBuffer) */ - public StringBuffer generate(StringBuffer tagBuffer) { + @Override + public StringBuilder generate(StringBuilder tagBuffer) { tagBuffer.append("<!DOCTYPE ").append(name).append(" PUBLIC \"").append(systemUri).append("\">\n"); //TODO A meaningful exception should be raised // when trying to call the method for a HTMLDoctype // with number of child != 1 - return ((HTMLNode) children.get(0)).generate(tagBuffer); + return children.get(0).generate(tagBuffer); } } Modified: branches/db4o/freenet/src/freenet/support/LRUHashtable.java =================================================================== --- branches/db4o/freenet/src/freenet/support/LRUHashtable.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/LRUHashtable.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -3,7 +3,7 @@ import java.util.Enumeration; import java.util.Hashtable; -public class LRUHashtable { +public class LRUHashtable<K, V> { /* * I've just converted this to using the DLList and Hashtable @@ -12,8 +12,8 @@ * push is by far the most done operation, this should be an * overall improvement. */ - private final DoublyLinkedListImpl list = new DoublyLinkedListImpl(); - private final Hashtable hash = new Hashtable(); + private final DoublyLinkedListImpl<V> list = new DoublyLinkedListImpl<V>(); + private final Hashtable<K, QItem<K, V>> hash = new Hashtable<K, QItem<K, V>>(); /** * push()ing an object that is already in @@ -21,10 +21,10 @@ * recently used position, but doesn't add * a duplicate entry in the queue. */ - public final synchronized void push(Object key, Object value) { - QItem insert = (QItem)hash.get(key); + public final synchronized void push(K key, V value) { + QItem<K,V> insert = hash.get(key); if (insert == null) { - insert = new QItem(key, value); + insert = new QItem<K, V>(key, value); hash.put(key,insert); } else { insert.value = value; @@ -41,7 +41,7 @@ */ public final synchronized Object popKey() { if ( list.size() > 0 ) { - return ((QItem)hash.remove(((QItem)list.pop()).obj)).obj; + return ( hash.remove(((QItem) list.pop()).obj)).obj; } else { return null; } @@ -52,7 +52,7 @@ */ public final synchronized Object popValue() { if ( list.size() > 0 ) { - return ((QItem)hash.remove(((QItem)list.pop()).obj)).value; + return ( hash.remove(((QItem) list.pop()).obj)).value; } else { return null; } @@ -85,8 +85,8 @@ return list.size(); } - public final synchronized boolean removeKey(Object key) { - QItem i = (QItem)(hash.remove(key)); + public final synchronized boolean removeKey(K key) { + QItem<K,V> i = (hash.remove(key)); if(i != null) { list.remove(i); return true; @@ -100,7 +100,7 @@ * @param obj Object to match * @return true if this queue contains obj. */ - public final synchronized boolean containsKey(Object key) { + public final synchronized boolean containsKey(K key) { return hash.containsKey(key); } @@ -108,8 +108,8 @@ * Note that this does not automatically promote the key. You have * to do that by hand with push(key, value). */ - public final synchronized Object get(Object key) { - QItem q = (QItem) hash.get(key); + public final synchronized V get(K key) { + QItem<K,V> q = hash.get(key); if(q == null) return null; return q.value; } @@ -146,15 +146,16 @@ } } - private static class QItem extends DoublyLinkedListImpl.Item { - public Object obj; - public Object value; + public static class QItem<K, V> extends DoublyLinkedListImpl.Item<V> { + public K obj; + public V value; - public QItem(Object key, Object val) { + public QItem(K key, V val) { this.obj = key; this.value = val; } + @Override public String toString() { return super.toString()+": "+obj+ ' ' +value; } @@ -170,8 +171,8 @@ * @param entries * @return */ - public synchronized void valuesToArray(Object[] entries) { - Enumeration values = values(); + public synchronized void valuesToArray(V[] entries) { + Enumeration<V> values = values(); int i=0; while(values.hasMoreElements()) entries[i++] = values.nextElement(); Modified: branches/db4o/freenet/src/freenet/support/OOMHandler.java =================================================================== --- branches/db4o/freenet/src/freenet/support/OOMHandler.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/OOMHandler.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -8,8 +8,6 @@ import org.tanukisoftware.wrapper.WrapperManager; -import freenet.support.Logger; - /** * Do this processing as a standard response to an OutOfMemoryError */ @@ -25,7 +23,7 @@ /** * List of {@link OOMHook}s */ - private static Set oomHooks = new WeakHashSet(); + private static Set<OOMHook> oomHooks = new WeakHashSet<OOMHook>(); public static void addOOMHook(OOMHook hook) { synchronized (oomHooks) { @@ -41,9 +39,9 @@ System.runFinalization(); // iterate all oom hooks - Iterator it = oomHooks.iterator(); + Iterator<OOMHook> it = oomHooks.iterator(); while (it.hasNext()) { - OOMHook hook = ((OOMHook) it.next()); + OOMHook hook = it.next(); if (hook != null) { try { hook.handleLowMemory(); @@ -77,9 +75,9 @@ System.runFinalization(); // iterate all oom hooks - Iterator it = oomHooks.iterator(); + Iterator<OOMHook> it = oomHooks.iterator(); while (it.hasNext()) { - OOMHook hook = ((OOMHook) it.next()); + OOMHook hook = it.next(); if (hook != null) { try { hook.handleOutOfMemory(); Modified: branches/db4o/freenet/src/freenet/support/PooledExecutor.java =================================================================== --- branches/db4o/freenet/src/freenet/support/PooledExecutor.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/PooledExecutor.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -16,9 +16,9 @@ public class PooledExecutor implements Executor { /** All threads running or waiting */ - private final ArrayList[] runningThreads /* <MyThread> */ = new ArrayList[NativeThread.JAVA_PRIORITY_RANGE + 1]; + private final ArrayList<MyThread>[] runningThreads = new ArrayList[NativeThread.JAVA_PRIORITY_RANGE + 1]; /** Threads waiting for a job */ - private final ArrayList[] waitingThreads /* <MyThread> */ = new ArrayList[runningThreads.length]; + private final ArrayList<MyThread>[] waitingThreads = new ArrayList[runningThreads.length]; long[] threadCounter = new long[runningThreads.length]; private long jobCount; private long jobMisses; @@ -64,7 +64,7 @@ synchronized(this) { jobCount++; if(!waitingThreads[prio - 1].isEmpty()) { - t = (MyThread) waitingThreads[prio - 1].remove(waitingThreads[prio - 1].size() - 1); + t = waitingThreads[prio - 1].remove(waitingThreads[prio - 1].size() - 1); if(logMINOR) Logger.minor(this, "Reusing thread " + t); } else { @@ -140,6 +140,7 @@ threadNo = threadCounter; } + @Override public void run() { super.run(); long ranJobs = 0; Modified: branches/db4o/freenet/src/freenet/support/SimpleFieldSet.java =================================================================== --- branches/db4o/freenet/src/freenet/support/SimpleFieldSet.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/SimpleFieldSet.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -33,8 +33,8 @@ */ public class SimpleFieldSet { - private final Map values; - private Map subsets; + private final Map<String, String> values; + private Map<String, SimpleFieldSet> subsets; private String endMarker; private final boolean shortLived; static public final char MULTI_LEVEL_CHAR = '.'; @@ -49,7 +49,7 @@ * small. */ public SimpleFieldSet(boolean shortLived) { - values = new HashMap(); + values = new HashMap<String, String>(); subsets = null; this.shortLived = shortLived; } @@ -71,9 +71,9 @@ } public SimpleFieldSet(SimpleFieldSet sfs){ - values = new HashMap(sfs.values); + values = new HashMap<String, String>(sfs.values); if(sfs.subsets != null) - subsets = new HashMap(sfs.subsets); + subsets = new HashMap<String, SimpleFieldSet>(sfs.subsets); this.shortLived = false; // it's been copied! endMarker = sfs.endMarker; } @@ -173,14 +173,14 @@ public synchronized String get(String key) { int idx = key.indexOf(MULTI_LEVEL_CHAR); if(idx == -1) - return (String) values.get(key); + return values.get(key); else if(idx == 0) return (subset("") == null) ? null : subset("").get(key.substring(1)); else { if(subsets == null) return null; String before = key.substring(0, idx); String after = key.substring(idx+1); - SimpleFieldSet fs = (SimpleFieldSet) (subsets.get(before)); + SimpleFieldSet fs = subsets.get(before); if(fs == null) return null; return fs.get(after); } @@ -193,7 +193,7 @@ } private static final String[] split(String string) { - if(string == null) return new String[0]; + if(string == null) return EMPTY_STRING_ARRAY; return string.split(String.valueOf(MULTI_VALUE_CHAR)); // slower??? // int index = string.indexOf(';'); // if(index == -1) return null; @@ -212,7 +212,7 @@ } private static final String unsplit(String[] strings) { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); for(int i=0;i<strings.length;i++) { if(i != 0) sb.append(MULTI_VALUE_CHAR); sb.append(strings[i]); @@ -227,7 +227,7 @@ Iterator i = fs.values.keySet().iterator(); while(i.hasNext()) { String key = (String) i.next(); - String hisVal = (String) fs.values.get(key); + String hisVal = fs.values.get(key); values.put(key, hisVal); // overwrite old } if(fs.subsets == null) return; @@ -235,8 +235,8 @@ i = fs.subsets.keySet().iterator(); while(i.hasNext()) { String key = (String) i.next(); - SimpleFieldSet hisFS = (SimpleFieldSet) fs.subsets.get(key); - SimpleFieldSet myFS = (SimpleFieldSet) subsets.get(key); + SimpleFieldSet hisFS = fs.subsets.get(key); + SimpleFieldSet myFS = subsets.get(key); if(myFS != null) { myFS.putAllOverwrite(hisFS); } else { @@ -294,14 +294,14 @@ if(value == null) return true; // valid no-op if(value.indexOf('\n') != -1) throw new IllegalArgumentException("A simplefieldSet can't accept newlines !"); if((idx = key.indexOf(MULTI_LEVEL_CHAR)) == -1) { - String x = (String) values.get(key); + String x = values.get(key); if(!shortLived) key = key.intern(); if(x == null || overwrite) { values.put(key, value); } else { if(!allowMultiple) return false; - values.put(key, ((String)values.get(key))+ MULTI_VALUE_CHAR +value); + values.put(key, (values.get(key))+ MULTI_VALUE_CHAR +value); } } else { String before = key.substring(0, idx); @@ -309,7 +309,7 @@ SimpleFieldSet fs = null; if(subsets == null) subsets = new HashMap(); - fs = (SimpleFieldSet) (subsets.get(before)); + fs = subsets.get(before); if(fs == null) { fs = new SimpleFieldSet(shortLived); if(!shortLived) before = before.intern(); @@ -399,7 +399,7 @@ } private synchronized void writeToOrdered(Writer w, String prefix, boolean noEndMarker) throws IOException { - String[] keys = (String[]) values.keySet().toArray(new String[values.size()]); + String[] keys = values.keySet().toArray(new String[values.size()]); int i=0; // Sort @@ -410,7 +410,7 @@ w.write(prefix+keys[i]+KEYVALUE_SEPARATOR_CHAR+get(keys[i])+'\n'); if(subsets != null) { - String[] orderedPrefixes = (String[]) subsets.keySet().toArray(new String[subsets.size()]); + String[] orderedPrefixes = subsets.keySet().toArray(new String[subsets.size()]); // Sort Arrays.sort(orderedPrefixes); @@ -429,6 +429,7 @@ } } + @Override public String toString() { StringWriter sw = new StringWriter(); try { @@ -461,10 +462,10 @@ if(subsets == null) return null; int idx = key.indexOf(MULTI_LEVEL_CHAR); if(idx == -1) - return (SimpleFieldSet) subsets.get(key); + return subsets.get(key); String before = key.substring(0, idx); String after = key.substring(idx+1); - SimpleFieldSet fs = (SimpleFieldSet) subsets.get(before); + SimpleFieldSet fs = subsets.get(before); if(fs == null) return null; return fs.subset(after); } @@ -519,7 +520,7 @@ if(subsetIterator == null || !subsetIterator.hasNext()) break; String name = (String) subsetIterator.next(); if(name == null) continue; - SimpleFieldSet fs = (SimpleFieldSet) subsets.get(name); + SimpleFieldSet fs = subsets.get(name); if(fs == null) continue; String newPrefix = prefix + name + MULTI_LEVEL_CHAR; subIterator = fs.keyIterator(newPrefix); @@ -538,7 +539,7 @@ if(subIterator != null) subIterator = null; if(subsetIterator != null && subsetIterator.hasNext()) { String key = (String) subsetIterator.next(); - SimpleFieldSet fs = (SimpleFieldSet) subsets.get(key); + SimpleFieldSet fs = subsets.get(key); String newPrefix = prefix + key + MULTI_LEVEL_CHAR; subIterator = fs.keyIterator(newPrefix); } else @@ -571,7 +572,7 @@ subIterator = null; if(subsetIterator != null && subsetIterator.hasNext()) { String key = (String) subsetIterator.next(); - SimpleFieldSet fs = (SimpleFieldSet) subsets.get(key); + SimpleFieldSet fs = subsets.get(key); String newPrefix = prefix + key + MULTI_LEVEL_CHAR; subIterator = fs.keyIterator(newPrefix); } else { @@ -615,7 +616,7 @@ if(subsets == null) return; String before = key.substring(0, idx); String after = key.substring(idx+1); - SimpleFieldSet fs = (SimpleFieldSet) (subsets.get(before)); + SimpleFieldSet fs = subsets.get(before); if(fs == null) { return; } @@ -646,7 +647,7 @@ } else { String before = key.substring(0, idx); String after = key.substring(idx+1); - SimpleFieldSet fs = (SimpleFieldSet) (subsets.get(before)); + SimpleFieldSet fs = subsets.get(before); if(fs == null) { return; } @@ -669,7 +670,7 @@ } public String[] namesOfDirectSubsets() { - return (subsets == null) ? EMPTY_STRING_ARRAY : (String[]) subsets.keySet().toArray(new String[subsets.size()]); + return (subsets == null) ? EMPTY_STRING_ARRAY : subsets.keySet().toArray(new String[subsets.size()]); } public static SimpleFieldSet readFrom(InputStream is, boolean allowMultiple, boolean shortLived) throws IOException { Modified: branches/db4o/freenet/src/freenet/support/SizeUtil.java =================================================================== --- branches/db4o/freenet/src/freenet/support/SizeUtil.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/SizeUtil.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -10,7 +10,17 @@ return formatSize(sz, false); } + public static String formatSizeWithoutSpace(long sz) { + String[] result = _formatSize(sz); + return result[0].concat(result[1]); + } + public static String formatSize(long sz, boolean useNonBreakingSpace) { + String[] result = _formatSize(sz); + return result[0].concat((useNonBreakingSpace ? "\u00a0" : " ")).concat(result[1]); + } + + public static String[] _formatSize(long sz) { long s = 1; int i; for(i=0;i<SizeUtil.suffixes.length;i++) { @@ -24,39 +34,19 @@ s /= 1024; // we use the previous unit if (s == 1) // Bytes? Then we don't need real numbers with a comma { - return sz + " " + SizeUtil.suffixes[0]; + return new String[] { String.valueOf(sz), SizeUtil.suffixes[0] }; } else { double mantissa = (double)sz / (double)s; - String o = Double.toString(mantissa); + String o = String.valueOf(mantissa); if(o.indexOf('.') == 3) o = o.substring(0, 3); else if((o.indexOf('.') > -1) && (o.indexOf('E') == -1) && (o.length() > 4)) o = o.substring(0, 4); if(i < SizeUtil.suffixes.length) // handle the case where the mantissa is Infinity - if(useNonBreakingSpace) { - o += '\u00a0' + SizeUtil.suffixes[i]; - } else { - o += ' ' + SizeUtil.suffixes[i]; - } - return o; + return new String[] { o , SizeUtil.suffixes[i] }; + return new String[] { o , "" }; } } - - public static String stripBytesEtc(String size) { - if(size.length() > 0 && size.charAt(size.length()-1) == 'B') - size = size.substring(0, size.length()-1); - if(size.length() > 0 && size.charAt(size.length()-1) == 'i') - size = size.substring(0, size.length()-1); - if(size.indexOf(' ') != -1) { - StringBuffer sb = new StringBuffer(size.length()-1); - for(int i=0;i<size.length();i++) { - char c = size.charAt(i); - if(c != ' ') sb.append(c); - } - size = sb.toString(); - } - return size; - } } Modified: branches/db4o/freenet/src/freenet/support/SortedLongSet.java =================================================================== --- branches/db4o/freenet/src/freenet/support/SortedLongSet.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/SortedLongSet.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -1,6 +1,5 @@ package freenet.support; -import java.util.Arrays; /** * Sorted array of long's. Deleted: branches/db4o/freenet/src/freenet/support/StringArray.java =================================================================== --- branches/db4o/freenet/src/freenet/support/StringArray.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/StringArray.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -1,101 +0,0 @@ -/* This code is part of Freenet. It is distributed under the GNU General - * Public License, version 2 (or at your option any later version). See - * http://www.gnu.org/ for further details of the GPL. */ - -package freenet.support; - -/** - * This class implements various toString methods available in java 1.5 but not 1.4 - * - * @author Florent Daignière <nextgens at freenetproject.org> - */ -public class StringArray { - - /** - * This method implements the equivalent of Arrays.valueOf() (java 1.5) - * @param array - * @return string - */ - public static String toString(Object[] array){ - if((array != null) && (array.length > 0)){ - StringBuffer sb = new StringBuffer(); - for(int i=0; i<array.length; i++) - sb.append(array[i].toString()+'|'); - return '[' + sb.substring(0, sb.length() - 1) + ']'; - }else - return ""; - } - - /** - * This method implements the equivalent of Arrays.valueOf() (java 1.5) - * @param array - * @return string - */ - public static String toString(String[] array){ - if((array != null) && (array.length > 0)){ - StringBuffer sb = new StringBuffer(); - for(int i=0; i<array.length; i++) - sb.append(array[i]+'|'); - return '[' + sb.substring(0, sb.length() - 1) + ']'; - }else - return ""; - } - - /** - * This methods returns a String[] from Object[] - * @param array - * @return string[] - */ - public static String[] toArray(Object[] array){ - if((array != null) && (array.length > 0)){ - String[] result = new String[array.length]; - for(int i=0; i<array.length; i++) - result[i] = (array[i]).toString(); - return result; - }else - return null; - } - - public static String[] toArray(double[] array) { - if((array != null) && (array.length > 0)){ - String[] result = new String[array.length]; - for(int i=0; i<array.length; i++) - result[i] = Double.toString(array[i]); - return result; - }else - return null; - } - - public static String toString(double[] array) { - return toString(toArray(array)); - } - - public static String[] toArray(long[] array) { - if((array != null) && (array.length > 0)){ - String[] result = new String[array.length]; - for(int i=0; i<array.length; i++) - result[i] = Long.toString(array[i]); - return result; - }else - return null; - } - - public static String toString(long[] array) { - return toString(toArray(array)); - } - - public static String[] toArray(int[] array) { - if((array != null) && (array.length > 0)){ - String[] result = new String[array.length]; - for(int i=0; i<array.length; i++) - result[i] = Long.toString(array[i]); - return result; - }else - return null; - } - - public static String toString(int[] array) { - return toString(toArray(array)); - } - -} Modified: branches/db4o/freenet/src/freenet/support/TimeSortedHashtable.java =================================================================== --- branches/db4o/freenet/src/freenet/support/TimeSortedHashtable.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/TimeSortedHashtable.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -9,8 +9,18 @@ /** * Variant on LRUHashtable which provides an efficient how-many-since-time-T operation. */ -public class TimeSortedHashtable { - +public class TimeSortedHashtable implements Cloneable { + + public TimeSortedHashtable() { + this.elements = new TreeSet(new MyComparator()); + this.valueToElement = new HashMap(); + } + + private TimeSortedHashtable(TimeSortedHashtable c) { + this.elements = new TreeSet(c.elements); + this.valueToElement = new HashMap(c.valueToElement); + } + private static class Element { Element(long t, Comparable v) { @@ -54,9 +64,13 @@ } - private final TreeSet elements = new TreeSet(new MyComparator()); - private final HashMap valueToElement = new HashMap(); + private final TreeSet elements; + private final HashMap valueToElement; + public TimeSortedHashtable clone() { + return new TimeSortedHashtable(this); + } + public final void push(Comparable value) { push(value, System.currentTimeMillis()); } Modified: branches/db4o/freenet/src/freenet/support/WeakHashSet.java =================================================================== --- branches/db4o/freenet/src/freenet/support/WeakHashSet.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/WeakHashSet.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -5,50 +5,60 @@ import java.util.Iterator; import java.util.WeakHashMap; -public class WeakHashSet extends AbstractSet { - private final WeakHashMap map; +public class WeakHashSet<E> extends AbstractSet<E> { + private final WeakHashMap<E, Object> map; public WeakHashSet() { - map = new WeakHashMap(); + map = new WeakHashMap<E, Object>(); } - public boolean add(Object key) { + @Override + public boolean add(E key) { return map.put(key, null) == null; } - public void clear() { + @Override + public void clear() { map.clear(); } - public boolean contains(Object key) { + @Override + public boolean contains(Object key) { return map.containsKey(key); } - public boolean containsAll(Collection arg0) { + @Override + public boolean containsAll(Collection<?> arg0) { return map.keySet().containsAll(arg0); } - public boolean isEmpty() { + @Override + public boolean isEmpty() { return map.isEmpty(); } - public Iterator iterator() { + @Override + public Iterator<E> iterator() { return map.keySet().iterator(); } - public boolean remove(Object key) { + @Override + public boolean remove(Object key) { return map.remove(key) != null; } - public int size() { + @Override + public int size() { return map.size(); } - public Object[] toArray() { + @Override + public Object[] toArray() { return map.keySet().toArray(); } - public Object[] toArray(Object[] arg0) { + @Override + public <T> T[] toArray(T[] arg0) { return map.keySet().toArray(arg0); } } Modified: branches/db4o/freenet/src/freenet/support/api/BooleanCallback.java =================================================================== --- branches/db4o/freenet/src/freenet/support/api/BooleanCallback.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/api/BooleanCallback.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -4,25 +4,10 @@ package freenet.support.api; import freenet.config.ConfigCallback; -import freenet.config.InvalidConfigValueException; /** * A callback to be called when a config value of integer type changes. * Also reports the current value. */ -public interface BooleanCallback extends ConfigCallback { - - /** - * Get the current, used value of the config variable. - */ - boolean get(); - - /** - * Set the config variable to a new value. - * @param val The new value. - * @throws InvalidConfigOptionException If the new value is invalid for - * this particular option. - */ - void set(boolean val) throws InvalidConfigValueException; - +public abstract class BooleanCallback extends ConfigCallback<Boolean> { } Modified: branches/db4o/freenet/src/freenet/support/api/IntCallback.java =================================================================== --- branches/db4o/freenet/src/freenet/support/api/IntCallback.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/api/IntCallback.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -4,25 +4,10 @@ package freenet.support.api; import freenet.config.ConfigCallback; -import freenet.config.InvalidConfigValueException; /** * A callback to be called when a config value of integer type changes. * Also reports the current value. */ -public interface IntCallback extends ConfigCallback { - - /** - * Get the current, used value of the config variable. - */ - int get(); - - /** - * Set the config variable to a new value. - * @param val The new value. - * @throws InvalidConfigOptionException If the new value is invalid for - * this particular option. - */ - void set(int val) throws InvalidConfigValueException; - +public abstract class IntCallback extends ConfigCallback<Integer> { } Modified: branches/db4o/freenet/src/freenet/support/api/LongCallback.java =================================================================== --- branches/db4o/freenet/src/freenet/support/api/LongCallback.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/api/LongCallback.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -4,25 +4,10 @@ package freenet.support.api; import freenet.config.ConfigCallback; -import freenet.config.InvalidConfigValueException; /** * A callback to be called when a config value of long type changes. * Also reports the current value. */ -public interface LongCallback extends ConfigCallback { - - /** - * Get the current, used value of the config variable. - */ - long get(); - - /** - * Set the config variable to a new value. - * @param val The new value. - * @throws InvalidConfigOptionException If the new value is invalid for - * this particular option. - */ - void set(long val) throws InvalidConfigValueException; - +public abstract class LongCallback extends ConfigCallback<Long> { } Modified: branches/db4o/freenet/src/freenet/support/api/ShortCallback.java =================================================================== --- branches/db4o/freenet/src/freenet/support/api/ShortCallback.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/api/ShortCallback.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -1,25 +1,10 @@ package freenet.support.api; import freenet.config.ConfigCallback; -import freenet.config.InvalidConfigValueException; /** * A callback to be called when a config value of short type changes. * Also reports the current value. */ -public interface ShortCallback extends ConfigCallback { - - /** - * Get the current, used value of the config variable. - */ - short get(); - - /** - * Set the config variable to a new value. - * @param val The new value. - * @throws InvalidConfigOptionException If the new value is invalid for - * this particular option. - */ - void set(short val) throws InvalidConfigValueException; - +public abstract class ShortCallback extends ConfigCallback<Short> { } Modified: branches/db4o/freenet/src/freenet/support/api/StringArrCallback.java =================================================================== --- branches/db4o/freenet/src/freenet/support/api/StringArrCallback.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/api/StringArrCallback.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -4,22 +4,7 @@ package freenet.support.api; import freenet.config.ConfigCallback; -import freenet.config.InvalidConfigValueException; /** Callback (getter/setter) for a string config variable */ -public interface StringArrCallback extends ConfigCallback { - - /** - * Get the current, used value of the config variable. - */ - String[] get(); - - /** - * Set the config variable to a new value. - * @param val The new value. - * @throws InvalidConfigOptionException If the new value is invalid for - * this particular option. - */ - void set(String[] val) throws InvalidConfigValueException; - +public abstract class StringArrCallback extends ConfigCallback<String[]> { } Modified: branches/db4o/freenet/src/freenet/support/api/StringCallback.java =================================================================== --- branches/db4o/freenet/src/freenet/support/api/StringCallback.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/api/StringCallback.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -4,22 +4,8 @@ package freenet.support.api; import freenet.config.ConfigCallback; -import freenet.config.InvalidConfigValueException; /** Callback (getter/setter) for a string config variable */ -public interface StringCallback extends ConfigCallback { - - /** - * Get the current, used value of the config variable. - */ - String get(); +public abstract class StringCallback extends ConfigCallback<String> { - /** - * Set the config variable to a new value. - * @param val The new value. - * @throws InvalidConfigOptionException If the new value is invalid for - * this particular option. - */ - void set(String val) throws InvalidConfigValueException; - } Modified: branches/db4o/freenet/src/freenet/support/compress/GzipCompressor.java =================================================================== --- branches/db4o/freenet/src/freenet/support/compress/GzipCompressor.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/compress/GzipCompressor.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -17,7 +17,7 @@ public class GzipCompressor extends Compressor { public Bucket compress(Bucket data, BucketFactory bf, long maxLength) throws IOException, CompressionOutputSizeException { - Bucket output = bf.makeBucket(-1); + Bucket output = bf.makeBucket(maxLength); InputStream is = null; OutputStream os = null; GZIPOutputStream gos = null; @@ -54,7 +54,7 @@ if(preferred != null) output = preferred; else - output = bf.makeBucket(-1); + output = bf.makeBucket(maxLength); InputStream is = null; OutputStream os = null; try { Modified: branches/db4o/freenet/src/freenet/support/io/ArrayBucket.java =================================================================== --- branches/db4o/freenet/src/freenet/support/io/ArrayBucket.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/io/ArrayBucket.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -15,15 +15,13 @@ /** * A bucket that stores data in the memory. * - * FIXME: No synchronization, should there be? - * * @author oskar */ public class ArrayBucket implements Bucket { - private final ArrayList data; - private String name; - private boolean readOnly; + private final ArrayList<byte[]> data; + private final String name; + private volatile boolean readOnly; public ArrayBucket() { this("ArrayBucket"); @@ -35,20 +33,21 @@ } ArrayBucket(String name) { - data = new ArrayList(); + data = new ArrayList<byte[]>(); this.name = name; } - public OutputStream getOutputStream() throws IOException { + public synchronized OutputStream getOutputStream() throws IOException { if(readOnly) throw new IOException("Read only"); return new ArrayBucketOutputStream(); } - public InputStream getInputStream() { + public synchronized InputStream getInputStream() { return new ArrayBucketInputStream(); } - public String toString() { + @Override + public synchronized String toString() { StringBuffer s = new StringBuffer(250); for (Iterator i = data.iterator(); i.hasNext();) { byte[] b = (byte[]) i.next(); @@ -57,7 +56,7 @@ return s.toString(); } - public void read(InputStream in) throws IOException { + public synchronized void read(InputStream in) throws IOException { OutputStream out = new ArrayBucketOutputStream(); int i; byte[] b = new byte[8 * 1024]; @@ -67,13 +66,13 @@ out.close(); } - public long size() { - long size = 0; - for (Iterator i = data.iterator(); i.hasNext();) { - byte[] b = (byte[]) i.next(); - size += b.length; - } - return size; + public synchronized long size() { + long currentSize = 0; + + for(byte[] buf : data) + currentSize += buf.length; + + return currentSize; } public String getName() { @@ -81,15 +80,30 @@ } private class ArrayBucketOutputStream extends ByteArrayOutputStream { + boolean hasBeenClosed = false; public ArrayBucketOutputStream() { super(); } + + @Override + public synchronized void write(byte b[], int off, int len) { + if(readOnly) throw new IllegalStateException("Read only"); + super.write(b, off, len); + } + + @Override + public synchronized void write(int b) { + if(readOnly) throw new IllegalStateException("Read only"); + super.write(b); + } - public void close() throws IOException { + @Override + public synchronized void close() throws IOException { + if(hasBeenClosed) return; + hasBeenClosed = true; data.add(super.toByteArray()); if(readOnly) throw new IOException("Read only"); - // FIXME maybe we should throw on write instead? :) } } @@ -102,11 +116,11 @@ i = data.iterator(); } - public int read() { + public synchronized int read() { return priv_read(); } - private int priv_read() { + private synchronized int priv_read() { if (in == null) { if (i.hasNext()) { in = new ByteArrayInputStream((byte[]) i.next()); @@ -123,15 +137,17 @@ } } - public int read(byte[] b) { + @Override + public synchronized int read(byte[] b) { return priv_read(b, 0, b.length); } - public int read(byte[] b, int off, int len) { + @Override + public synchronized int read(byte[] b, int off, int len) { return priv_read(b, off, len); } - private int priv_read(byte[] b, int off, int len) { + private synchronized int priv_read(byte[] b, int off, int len) { if (in == null) { if (i.hasNext()) { in = new ByteArrayInputStream((byte[]) i.next()); @@ -148,7 +164,8 @@ } } - public int available() { + @Override + public synchronized int available() { if (in == null) { if (i.hasNext()) { in = new ByteArrayInputStream((byte[]) i.next()); @@ -169,12 +186,12 @@ readOnly = true; } - public void free() { + public synchronized void free() { data.clear(); // Not much else we can do. } - public byte[] toByteArray() { + public synchronized byte[] toByteArray() { long sz = size(); int size = (int)sz; byte[] buf = new byte[size]; Modified: branches/db4o/freenet/src/freenet/support/io/BaseFileBucket.java =================================================================== --- branches/db4o/freenet/src/freenet/support/io/BaseFileBucket.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/io/BaseFileBucket.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -14,8 +14,8 @@ import freenet.support.Fields; import freenet.support.Logger; import freenet.support.SimpleFieldSet; -import freenet.support.StringArray; import freenet.support.api.Bucket; +import java.util.Arrays; public abstract class BaseFileBucket implements Bucket, SerializableToFieldSetBucket { @@ -394,7 +394,7 @@ } if(toClose != null) { - Logger.error(this, "Streams open free()ing "+this+" : "+StringArray.toString(toClose), new Exception("debug")); + Logger.error(this, "Streams open free()ing "+this+" : "+Arrays.toString(toClose), new Exception("debug")); for(int i=0;i<toClose.length;i++) { try { if(toClose[i] instanceof FileBucketOutputStream) { @@ -421,6 +421,7 @@ } } + @Override public synchronized String toString() { StringBuffer sb = new StringBuffer(); sb.append(super.toString()); Modified: branches/db4o/freenet/src/freenet/support/io/BucketTools.java =================================================================== --- branches/db4o/freenet/src/freenet/support/io/BucketTools.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/io/BucketTools.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -288,6 +288,7 @@ if(bytes <= 0) { if(truncateLength == Long.MAX_VALUE) break; + new IOException().printStackTrace(); throw new IOException("Could not move required quantity of data in copyTo: "+bytes+" (moved "+moved+" of "+truncateLength+"): unable to read from "+is); } os.write(buf, 0, bytes); @@ -419,10 +420,12 @@ os.write(buf, 0, thisCycle); x += thisCycle; } + os.close(); + os = null; if(b.size() != blockLength) - throw new IllegalStateException(); + throw new IllegalStateException("The bucket's size is "+b.size()+" whereas it should be "+blockLength+'!'); return b; - } finally { os.close(); } + } finally { Closer.close(os); } } } Modified: branches/db4o/freenet/src/freenet/support/io/Closer.java =================================================================== --- branches/db4o/freenet/src/freenet/support/io/Closer.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/io/Closer.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -18,12 +18,8 @@ package freenet.support.io; +import java.io.Closeable; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Reader; -import java.io.Writer; -import java.util.jar.JarFile; import java.util.zip.ZipFile; /** @@ -36,77 +32,16 @@ * @version $Id$ */ public class Closer { - /** - * Closes the given output stream. + * Closes the given stream. * * @param outputStream * The output stream to close */ - public static void close(OutputStream outputStream) { - if (outputStream != null) { + public static void close(Closeable closable) { + if (closable != null) { try { - outputStream.close(); - } catch (IOException ioe1) { - } - } - } - - /** - * Closes the given input stream. - * - * @param inputStream - * The input stream to close - */ - public static void close(InputStream inputStream) { - if (inputStream != null) { - try { - inputStream.close(); - } catch (IOException ioe1) { - } - } - } - - /** - * Closes the given writer. - * - * @param writer - * The writer to close - */ - public static void close(Writer writer) { - if (writer != null) { - try { - writer.close(); - } catch (IOException ioe1) { - } - } - } - - /** - * Closes the given reader. - * - * @param reader - * The reader to close - */ - public static void close(Reader reader) { - if (reader != null) { - try { - reader.close(); - } catch (IOException ioe1) { - } - } - } - - /** - * Closes the given jar file. - * - * @param jarFile - * The jar file to close - */ - public static void close(JarFile jarFile) { - if (jarFile != null) { - try { - jarFile.close(); + closable.close(); } catch (IOException e) { } } Modified: branches/db4o/freenet/src/freenet/support/io/DelayedFreeBucket.java =================================================================== --- branches/db4o/freenet/src/freenet/support/io/DelayedFreeBucket.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/io/DelayedFreeBucket.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -22,7 +22,7 @@ Bucket bucket; boolean freed; - public DelayedFreeBucket(PersistentTempBucketFactory factory, PaddedEphemerallyEncryptedBucket bucket) { + public DelayedFreeBucket(PersistentTempBucketFactory factory, Bucket bucket) { this.factory = factory; this.bucket = bucket; if(bucket == null) throw new NullPointerException(); Modified: branches/db4o/freenet/src/freenet/support/io/LineReadingInputStream.java =================================================================== --- branches/db4o/freenet/src/freenet/support/io/LineReadingInputStream.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/io/LineReadingInputStream.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -16,8 +16,6 @@ super(in); } - private byte[] buf; - /** * Read a \n or \r\n terminated line of UTF-8 or ISO-8859-1. * @param maxLength The maximum length of a line. If a line is longer than this, we throw IOException rather @@ -26,31 +24,73 @@ * @param utf If true, read as UTF-8, if false, read as ISO-8859-1. */ public String readLine(int maxLength, int bufferSize, boolean utf) throws IOException { + if(maxLength <= bufferSize) + bufferSize = maxLength + 1; // Buffer too big, shrink it (add 1 for the optional \r) + + if(!markSupported()) + return readLineWithoutMarking(maxLength, bufferSize, utf); + + byte[] buf = new byte[Math.max(Math.min(128, maxLength), Math.min(1024, bufferSize))]; + int ctr = 0; + mark((maxLength+1)*2); // Might be more than maxLengh if we use utf8 + while(true) { + int x = read(buf, ctr, buf.length - ctr); + if(x == -1) { + if(ctr == 0) + return null; + return new String(buf, 0, ctr, utf ? "UTF-8" : "ISO-8859-1"); + } + // REDFLAG this is definitely safe with the above charsets, it may not be safe with some wierd ones. + for(; ctr < buf.length; ctr++) { + if(ctr >= maxLength) + throw new TooLongException(); + if(buf[ctr] == '\n') { + String toReturn = ""; + if(ctr != 0) { + boolean removeCR = (buf[ctr - 1] == '\r'); + toReturn = new String(buf, 0, (removeCR ? ctr - 1 : ctr), utf ? "UTF-8" : "ISO-8859-1"); + } + reset(); + skip(ctr + 1); + return toReturn; + } + } + if(x > 0) { + byte[] newBuf = new byte[Math.min(buf.length * 2, maxLength)]; + System.arraycopy(buf, 0, newBuf, 0, buf.length); + buf = newBuf; + } + } + } + + public String readLineWithoutMarking(int maxLength, int bufferSize, boolean utf) throws IOException { if(maxLength < bufferSize) bufferSize = maxLength + 1; // Buffer too big, shrink it (add 1 for the optional \r) - if(buf == null) - buf = new byte[Math.max(Math.min(128,maxLength), Math.min(1024, bufferSize))]; + byte[] buf = new byte[Math.max(Math.min(128, maxLength), Math.min(1024, bufferSize))]; int ctr = 0; while(true) { int x = read(); if(x == -1) { - if(ctr == 0) return null; + if(ctr == 0) + return null; return new String(buf, 0, ctr, utf ? "UTF-8" : "ISO-8859-1"); } // REDFLAG this is definitely safe with the above charsets, it may not be safe with some wierd ones. if(x == '\n') { - if(ctr == 0) return ""; - if(buf[ctr-1] == '\r') ctr--; + if(ctr == 0) + return ""; + if(buf[ctr - 1] == '\r') + ctr--; return new String(buf, 0, ctr, utf ? "UTF-8" : "ISO-8859-1"); } - if(ctr >= maxLength) throw new TooLongException(); + if(ctr >= maxLength) + throw new TooLongException(); if(ctr >= buf.length) { byte[] newBuf = new byte[Math.min(buf.length * 2, maxLength)]; System.arraycopy(buf, 0, newBuf, 0, buf.length); buf = newBuf; } - buf[ctr++] = (byte)x; + buf[ctr++] = (byte) x; } } - } Modified: branches/db4o/freenet/src/freenet/support/io/NativeThread.java =================================================================== --- branches/db4o/freenet/src/freenet/support/io/NativeThread.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/io/NativeThread.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -4,7 +4,6 @@ package freenet.support.io; -import java.io.File; import freenet.node.NodeStarter; import freenet.support.LibraryLoader; import freenet.support.Logger; @@ -93,6 +92,7 @@ */ private static native int getLinuxPriority(); + @Override public void run() { if(!setNativePriority(currentPriority)) System.err.println("setNativePriority("+currentPriority+") has failed!"); Deleted: branches/db4o/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucketFactory.java =================================================================== --- branches/db4o/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucketFactory.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucketFactory.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -1,31 +0,0 @@ -package freenet.support.io; - -import freenet.crypt.RandomSource; -import java.io.IOException; - -import freenet.support.api.Bucket; -import freenet.support.api.BucketFactory; -import java.util.Random; - -/** - * Factory wrapper for PaddedEphemerallyEncryptedBucket's, which are themselves - * wrappers. - */ -public class PaddedEphemerallyEncryptedBucketFactory implements BucketFactory { - - final BucketFactory baseFactory; - final RandomSource strongPRNG; - final Random weakPRNG; - final int minSize; - - public PaddedEphemerallyEncryptedBucketFactory(BucketFactory factory, RandomSource strongPRNG, Random weakPRNG, int minSize) { - baseFactory = factory; - this.minSize = minSize; - this.strongPRNG = strongPRNG; - this.weakPRNG = weakPRNG; - } - - public Bucket makeBucket(long size) throws IOException { - return new PaddedEphemerallyEncryptedBucket(baseFactory.makeBucket(size), minSize, strongPRNG, weakPRNG); - } -} Deleted: branches/db4o/freenet/src/freenet/support/io/PersistentEncryptedTempBucketFactory.java =================================================================== --- branches/db4o/freenet/src/freenet/support/io/PersistentEncryptedTempBucketFactory.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/io/PersistentEncryptedTempBucketFactory.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -1,52 +0,0 @@ -/* This code is part of Freenet. It is distributed under the GNU General - * Public License, version 2 (or at your option any later version). See - * http://www.gnu.org/ for further details of the GPL. */ -package freenet.support.io; - -import java.io.IOException; - -import com.db4o.ObjectContainer; -import com.db4o.ObjectSet; -import com.db4o.query.Predicate; -import com.db4o.query.Query; - -import freenet.support.api.Bucket; -import freenet.support.api.BucketFactory; - - -public class PersistentEncryptedTempBucketFactory implements BucketFactory { - - PersistentTempBucketFactory bf; - - public PersistentEncryptedTempBucketFactory(PersistentTempBucketFactory bf) { - this.bf = bf; - } - - public Bucket makeBucket(long size) throws IOException { - return bf.makeEncryptedBucket(); - } - - public static PersistentEncryptedTempBucketFactory load(final PersistentTempBucketFactory persistentTempBucketFactory, ObjectContainer container) { - // This causes an OOM in init. WTF? -// ObjectSet results = container.query(new Predicate() { -// public boolean match(PersistentEncryptedTempBucketFactory bf) { -// return bf.bf == persistentTempBucketFactory; -// } -// }); - // REDFLAG: - // Constraining on bf causes an OOM for Cooo on db4o 6.4.48.10991. Commenting out bf below fixes it. - // Neither of the below log messages was logged ... which suggests something very strange is happening in db4o. - // FIXME EVIL DB4O BUG - if can replicate, file a bug... but it didn't happen to me, on the same version, also on linux, so it may not be replicable. - Query query = container.query(); - query.constrain(PersistentEncryptedTempBucketFactory.class); - //query.descend("bf").constrain(persistentTempBucketFactory); - ObjectSet results = query.execute(); - while(results.hasNext()) { - PersistentEncryptedTempBucketFactory factory = (PersistentEncryptedTempBucketFactory) results.next(); - if(factory.bf == persistentTempBucketFactory) return factory; - System.err.println("Not matched factory"); - } - System.err.println("Creating new factory"); - return new PersistentEncryptedTempBucketFactory(persistentTempBucketFactory); - } -} Modified: branches/db4o/freenet/src/freenet/support/io/PersistentTempBucketFactory.java =================================================================== --- branches/db4o/freenet/src/freenet/support/io/PersistentTempBucketFactory.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/io/PersistentTempBucketFactory.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -44,12 +44,15 @@ private LinkedList bucketsToFree; private final long nodeDBHandle; + + private volatile boolean encrypt; - public PersistentTempBucketFactory(File dir, final String prefix, RandomSource strongPRNG, Random weakPRNG, long nodeDBHandle) throws IOException { + public PersistentTempBucketFactory(File dir, final String prefix, RandomSource strongPRNG, Random weakPRNG, boolean encrypt, long nodeDBHandle) throws IOException { boolean logMINOR = Logger.shouldLog(Logger.MINOR, this); this.strongPRNG = strongPRNG; this.nodeDBHandle = nodeDBHandle; this.weakPRNG = weakPRNG; + this.encrypt = encrypt; this.fg = new FilenameGenerator(weakPRNG, false, dir, prefix); if(!dir.exists()) { dir.mkdir(); @@ -116,19 +119,11 @@ originalFiles = null; } - private Bucket makeRawBucket(long size) throws IOException { - return new PersistentTempFileBucket(fg.makeRandomFilename(), fg); - } - public Bucket makeBucket(long size) throws IOException { - Bucket b = makeRawBucket(size); - return new DelayedFreeBucket(this, new PaddedEphemerallyEncryptedBucket(b, 1024, strongPRNG, weakPRNG)); + PersistentTempFileBucket rawBucket = new PersistentTempFileBucket(fg.makeRandomFilename(), fg); + Bucket maybeEncryptedBucket = (encrypt ? new PaddedEphemerallyEncryptedBucket(rawBucket, 1024, strongPRNG, weakPRNG) : rawBucket); + return new DelayedFreeBucket(this, maybeEncryptedBucket); } - - public Bucket makeEncryptedBucket() throws IOException { - Bucket b = makeRawBucket(-1); - return new DelayedFreeBucket(this, new PaddedEphemerallyEncryptedBucket(b, 1024, strongPRNG, weakPRNG)); - } /** * Free an allocated bucket, but only after the change has been written to disk. @@ -162,8 +157,12 @@ public long getID(File file) { return fg.getID(file); } + + public boolean isEncrypting() { + return encrypt; + } - public static PersistentTempBucketFactory load(File dir, String prefix, RandomSource random, Random fastWeakRandom, ObjectContainer container, final long nodeDBHandle) throws IOException { + public static PersistentTempBucketFactory load(File dir, String prefix, RandomSource random, Random fastWeakRandom, ObjectContainer container, final long nodeDBHandle, boolean encrypt) throws IOException { ObjectSet<PersistentTempBucketFactory> results = container.query(new Predicate<PersistentTempBucketFactory>() { public boolean match(PersistentTempBucketFactory factory) { if(factory.nodeDBHandle == nodeDBHandle) return true; @@ -174,9 +173,13 @@ PersistentTempBucketFactory factory = results.next(); container.activate(factory, 5); factory.init(dir, prefix, random, fastWeakRandom); + factory.setEncryption(encrypt); return factory; } else - return new PersistentTempBucketFactory(dir, prefix, random, fastWeakRandom, nodeDBHandle); + return new PersistentTempBucketFactory(dir, prefix, random, fastWeakRandom, encrypt, nodeDBHandle); } + public void setEncryption(boolean encrypt) { + this.encrypt = encrypt; + } } Modified: branches/db4o/freenet/src/freenet/support/io/RandomAccessThing.java =================================================================== --- branches/db4o/freenet/src/freenet/support/io/RandomAccessThing.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/io/RandomAccessThing.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -3,13 +3,14 @@ * http://www.gnu.org/ for further details of the GPL. */ package freenet.support.io; +import java.io.Closeable; import java.io.IOException; /** * Trivial random access file base interface. * @author toad */ -public interface RandomAccessThing { +public interface RandomAccessThing extends Closeable { public long size() throws IOException; Modified: branches/db4o/freenet/src/freenet/support/io/TempBucketFactory.java =================================================================== --- branches/db4o/freenet/src/freenet/support/io/TempBucketFactory.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/src/freenet/support/io/TempBucketFactory.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -1,5 +1,6 @@ package freenet.support.io; +import freenet.crypt.RandomSource; import java.io.IOException; import freenet.support.api.Bucket; @@ -10,6 +11,7 @@ * distributed under the GNU Public Licence (GPL) version 2. See * http://www.gnu.org/ for further details of the GPL. */ +import java.util.Random; /** * Temporary Bucket Factory @@ -18,15 +20,43 @@ */ public class TempBucketFactory implements BucketFactory { + private class RAMBucket extends ArrayBucket { + private final long size; + + public RAMBucket(long size) { + super("RAMBucket"); + this.size = size; + } + + @Override + public void free() { + super.free(); + _hasFreed(size); + } + } + private final FilenameGenerator filenameGenerator; + private long bytesInUse = 0; public final static long defaultIncrement = 4096; public final static float DEFAULT_FACTOR = 1.25F; + + public long maxRAMBucketSize; + public long maxRamUsed; + final RandomSource strongPRNG; + final Random weakPRNG; + private volatile boolean reallyEncrypt; + // Storage accounting disabled by default. - public TempBucketFactory(FilenameGenerator filenameGenerator) { + public TempBucketFactory(FilenameGenerator filenameGenerator, long maxBucketSizeKeptInRam, long maxRamUsed, RandomSource strongPRNG, Random weakPRNG, boolean reallyEncrypt) { this.filenameGenerator = filenameGenerator; + this.maxRamUsed = maxRamUsed; + this.maxRAMBucketSize = maxBucketSizeKeptInRam; + this.strongPRNG = strongPRNG; + this.weakPRNG = weakPRNG; + this.reallyEncrypt = reallyEncrypt; } public Bucket makeBucket(long size) throws IOException { @@ -36,6 +66,38 @@ public Bucket makeBucket(long size, float factor) throws IOException { return makeBucket(size, factor, defaultIncrement); } + + protected synchronized void _hasFreed(long size) { + bytesInUse -= size; + } + + public synchronized long getRamUsed() { + return bytesInUse; + } + + public synchronized void setMaxRamUsed(long size) { + maxRamUsed = size; + } + + public synchronized long getMaxRamUsed() { + return maxRamUsed; + } + + public synchronized void setMaxRAMBucketSize(long size) { + maxRAMBucketSize = size; + } + + public synchronized long getMaxRAMBucketSize() { + return maxRAMBucketSize; + } + + public void setEncryption(boolean value) { + reallyEncrypt = value; + } + + public boolean isEncrypting() { + return reallyEncrypt; + } /** * Create a temp bucket @@ -49,11 +111,19 @@ * If it is not possible to create a temp bucket due to an * I/O error */ - public TempFileBucket makeBucket(long size, float factor, long increment) - throws IOException { - long id = filenameGenerator.makeRandomFilename(); - - return new TempFileBucket(id, filenameGenerator); + public Bucket makeBucket(long size, float factor, long increment) throws IOException { + Bucket realBucket = null; + boolean isARAMBucket = false; + + synchronized(this) { + if((size > 0) && (size <= maxRAMBucketSize) && (bytesInUse <= maxRamUsed)) { + bytesInUse += size; + isARAMBucket = true; + } + } + + realBucket = (isARAMBucket ? new RAMBucket(size) : new TempFileBucket(filenameGenerator.makeRandomFilename(), filenameGenerator)); + + return (!reallyEncrypt ? realBucket : new PaddedEphemerallyEncryptedBucket(realBucket, 1024, strongPRNG, weakPRNG)); } - } Copied: branches/db4o/freenet/test/freenet/crypt/YarrowTest.java (from rev 21939, trunk/freenet/test/freenet/crypt/YarrowTest.java) =================================================================== --- branches/db4o/freenet/test/freenet/crypt/YarrowTest.java (rev 0) +++ branches/db4o/freenet/test/freenet/crypt/YarrowTest.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -0,0 +1,23 @@ +/* This code is part of Freenet. It is distributed under the GNU General + * Public License, version 2 (or at your option any later version). See + * http://www.gnu.org/ for further details of the GPL. */ +package freenet.crypt; + +import org.spaceroots.mantissa.random.ScalarSampleStatistics; +import junit.framework.*; + +public class YarrowTest extends TestCase { + + +// REDFLAG: for some reason that test fails on emu... investigate why and review our implementation of Yarrow! + public void testDouble() { +// Yarrow mt = new Yarrow(false); + ScalarSampleStatistics sample = new ScalarSampleStatistics(); +// for(int i = 0; i < 1000; ++i) { +// sample.add(mt.nextDouble()); +// } +// +// assertEquals(0.5, sample.getMean(), 0.02); +// assertEquals(1.0 / (2.0 * Math.sqrt(3.0)), sample.getStandardDeviation(), 0.002); + } +} Modified: branches/db4o/freenet/test/freenet/support/BufferTest.java =================================================================== --- branches/db4o/freenet/test/freenet/support/BufferTest.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/test/freenet/support/BufferTest.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -141,7 +141,7 @@ Buffer b2 = new Buffer("Buffer2".getBytes()); Buffer b3 = new Buffer("Buffer1".getBytes()); - Map hashMap = new HashMap(); + Map<Buffer, Buffer> hashMap = new HashMap<Buffer, Buffer>(); hashMap.put(b1, b1); hashMap.put(b2, b2); Modified: branches/db4o/freenet/test/freenet/support/ByteArrayWrapperTest.java =================================================================== --- branches/db4o/freenet/test/freenet/support/ByteArrayWrapperTest.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/test/freenet/support/ByteArrayWrapperTest.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -32,7 +32,7 @@ assertFalse(wrapper2.equals(wrapper3)); assertFalse(wrapper1.equals(new String())); - Map map = new HashMap(); + Map<ByteArrayWrapper, ByteArrayWrapper> map = new HashMap<ByteArrayWrapper, ByteArrayWrapper>(); map.put(wrapper1, wrapper1); map.put(wrapper2, wrapper2); // should clobber 1 by hashcode Modified: branches/db4o/freenet/test/freenet/support/MultiValueTableTest.java =================================================================== --- branches/db4o/freenet/test/freenet/support/MultiValueTableTest.java 2008-09-24 19:52:19 UTC (rev 22822) +++ branches/db4o/freenet/test/freenet/support/MultiValueTableTest.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -63,8 +63,8 @@ * @param valuesNumber number of objects to create * @return the sample List */ - private List fillSampleValuesList(int valuesNumber) { - List sampleValues = new LinkedList(); + private List<Object> fillSampleValuesList(int valuesNumber) { + List<Object> sampleValues = new LinkedList<Object>(); for(int i=0; i<valuesNumber;i++) sampleValues.add(new Object()); return sampleValues; Copied: branches/db4o/freenet/test/freenet/support/io (from rev 21939, trunk/freenet/test/freenet/support/io) Deleted: branches/db4o/freenet/test/freenet/support/io/LineReadingInputStreamTest.java =================================================================== --- trunk/freenet/test/freenet/support/io/LineReadingInputStreamTest.java 2008-08-16 19:34:12 UTC (rev 21939) +++ branches/db4o/freenet/test/freenet/support/io/LineReadingInputStreamTest.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -1,106 +0,0 @@ -/* This code is part of Freenet. It is distributed under the GNU General - * Public License, version 2 (or at your option any later version). See - * http://www.gnu.org/ for further details of the GPL. */ -package freenet.support.io; - -import java.io.BufferedInputStream; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStream; -import junit.framework.TestCase; - -public class LineReadingInputStreamTest extends TestCase { - public static final String BLOCK = "\ntesting1\ntesting2\r\ntesting3\n\n"; - public static final String[] LINES = new String[] { - "", - "testing1", - "testing2", - "testing3", - "" - }; - - public static final String STRESSED_LINE = "\n\u0114\n"; - - public static final int MAX_LENGTH = 128; - public static final int BUFFER_SIZE = 128; - - public void testReadLineWithoutMarking() throws Exception { - // try utf8 - InputStream is = new ByteArrayInputStream(STRESSED_LINE.getBytes("utf-8")); - LineReadingInputStream instance = new LineReadingInputStream(is); - assertEquals("", instance.readLineWithoutMarking(MAX_LENGTH, BUFFER_SIZE, true)); - assertEquals("\u0114", instance.readLineWithoutMarking(MAX_LENGTH, BUFFER_SIZE, true)); - assertNull(instance.readLineWithoutMarking(MAX_LENGTH, BUFFER_SIZE, true)); - - // try ISO-8859-1 - is = new ByteArrayInputStream(BLOCK.getBytes("ISO-8859-1")); - instance = new LineReadingInputStream(is); - for(String expectedLine : LINES) { - assertEquals(expectedLine, instance.readLineWithoutMarking(MAX_LENGTH, BUFFER_SIZE, false)); - } - assertNull(instance.readLineWithoutMarking(MAX_LENGTH, BUFFER_SIZE, false)); - - // is it returning null? - is = new NullInputStream(); - instance = new LineReadingInputStream(is); - assertNull(instance.readLineWithoutMarking(0, BUFFER_SIZE, false)); - - // is it throwing? - is = new ByteArrayInputStream("aaa\na\n".getBytes()); - instance = new LineReadingInputStream(is); - try { - instance.readLineWithoutMarking(2, BUFFER_SIZE, true); - fail(); - } catch (TooLongException e) {} - } - - public void testReadLine() throws Exception { - // try utf8 - InputStream is = new ByteArrayInputStream(STRESSED_LINE.getBytes("utf-8")); - LineReadingInputStream instance = new LineReadingInputStream(is); - assertEquals("", instance.readLine(MAX_LENGTH, BUFFER_SIZE, true)); - assertEquals("\u0114", instance.readLine(MAX_LENGTH, BUFFER_SIZE, true)); - assertNull(instance.readLine(MAX_LENGTH, BUFFER_SIZE, true)); - - // try ISO-8859-1 - is = new ByteArrayInputStream(BLOCK.getBytes("ISO-8859-1")); - instance = new LineReadingInputStream(is); - for(String expectedLine : LINES) { - assertEquals(expectedLine, instance.readLine(MAX_LENGTH, BUFFER_SIZE, false)); - } - assertNull(instance.readLine(MAX_LENGTH, BUFFER_SIZE, false)); - - // is it returning null? - is = new NullInputStream(); - instance = new LineReadingInputStream(is); - assertNull(instance.readLine(0, BUFFER_SIZE, false)); - - // is it throwing? - is = new ByteArrayInputStream("aaa\na\n".getBytes()); - instance = new LineReadingInputStream(is); - try { - instance.readLine(2, BUFFER_SIZE, true); - fail(); - } catch (TooLongException e) {} - } - - public void testBothImplementation() throws Exception { - // CWD is either the node's or the build tree - File f = new File("freenet.ini"); - if(!f.exists()) - f = new File("build.xml"); - BufferedInputStream bis1 = new BufferedInputStream(new FileInputStream(f)); - BufferedInputStream bis2 = new BufferedInputStream(new FileInputStream(f)); - LineReadingInputStream lris1 = new LineReadingInputStream(bis1); - LineReadingInputStream lris2 = new LineReadingInputStream(bis2); - - while(bis1.available() > 0 || bis2.available() > 0) { - String stringWithoutMark =lris2.readLineWithoutMarking(MAX_LENGTH*10, BUFFER_SIZE, true); - String stringWithMark = lris1.readLine(MAX_LENGTH*10, BUFFER_SIZE, true); - assertEquals(stringWithMark, stringWithoutMark); - } - assertNull(lris1.readLine(MAX_LENGTH, BUFFER_SIZE, true)); - assertNull(lris2.readLineWithoutMarking(MAX_LENGTH, BUFFER_SIZE, true)); - } -} Copied: branches/db4o/freenet/test/freenet/support/io/LineReadingInputStreamTest.java (from rev 21939, trunk/freenet/test/freenet/support/io/LineReadingInputStreamTest.java) =================================================================== --- branches/db4o/freenet/test/freenet/support/io/LineReadingInputStreamTest.java (rev 0) +++ branches/db4o/freenet/test/freenet/support/io/LineReadingInputStreamTest.java 2008-09-24 20:42:20 UTC (rev 22823) @@ -0,0 +1,106 @@ +/* This code is part of Freenet. It is distributed under the GNU General + * Public License, version 2 (or at your option any later version). See + * http://www.gnu.org/ for further details of the GPL. */ +package freenet.support.io; + +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import junit.framework.TestCase; + +public class LineReadingInputStreamTest extends TestCase { + public static final String BLOCK = "\ntesting1\ntesting2\r\ntesting3\n\n"; + public static final String[] LINES = new String[] { + "", + "testing1", + "testing2", + "testing3", + "" + }; + + public static final String STRESSED_LINE = "\n\u0114\n"; + + public static final int MAX_LENGTH = 128; + public static final int BUFFER_SIZE = 128; + + public void testReadLineWithoutMarking() throws Exception { + // try utf8 + InputStream is = new ByteArrayInputStream(STRESSED_LINE.getBytes("utf-8")); + LineReadingInputStream instance = new LineReadingInputStream(is); + assertEquals("", instance.readLineWithoutMarking(MAX_LENGTH, BUFFER_SIZE, true)); + assertEquals("\u0114", instance.readLineWithoutMarking(MAX_LENGTH, BUFFER_SIZE, true)); + assertNull(instance.readLineWithoutMarking(MAX_LENGTH, BUFFER_SIZE, true)); + + // try ISO-8859-1 + is = new ByteArrayInputStream(BLOCK.getBytes("ISO-8859-1")); + instance = new LineReadingInputStream(is); + for(String expectedLine : LINES) { + assertEquals(expectedLine, instance.readLineWithoutMarking(MAX_LENGTH, BUFFER_SIZE, false)); + } + assertNull(instance.readLineWithoutMarking(MAX_LENGTH, BUFFER_SIZE, false)); + + // is it returning null? + is = new NullInputStream(); + instance = new LineReadingInputStream(is); + assertNull(instance.readLineWithoutMarking(0, BUFFER_SIZE, false)); + + // is it throwing? + is = new ByteArrayInputStream("aaa\na\n".getBytes()); + instance = new LineReadingInputStream(is); + try { + instance.readLineWithoutMarking(2, BUFFER_SIZE, true); + fail(); + } catch (TooLongException e) {} + } + + public void testReadLine() throws Exception { + // try utf8 + InputStream is = new ByteArrayInputStream(STRESSED_LINE.getBytes("utf-8")); + LineReadingInputStream instance = new LineReadingInputStream(is); + assertEquals("", instance.readLine(MAX_LENGTH, BUFFER_SIZE, true)); + assertEquals("\u0114", instance.readLine(MAX_LENGTH, BUFFER_SIZE, true)); + assertNull(instance.readLine(MAX_LENGTH, BUFFER_SIZE, true)); + + // try ISO-8859-1 + is = new ByteArrayInputStream(BLOCK.getBytes("ISO-8859-1")); + instance = new LineReadingInputStream(is); + for(String expectedLine : LINES) { + assertEquals(expectedLine, instance.readLine(MAX_LENGTH, BUFFER_SIZE, false)); + } + assertNull(instance.readLine(MAX_LENGTH, BUFFER_SIZE, false)); + + // is it returning null? + is = new NullInputStream(); + instance = new LineReadingInputStream(is); + assertNull(instance.readLine(0, BUFFER_SIZE, false)); + + // is it throwing? + is = new ByteArrayInputStream("aaa\na\n".getBytes()); + instance = new LineReadingInputStream(is); + try { + instance.readLine(2, BUFFER_SIZE, true); + fail(); + } catch (TooLongException e) {} + } + + public void testBothImplementation() throws Exception { + // CWD is either the node's or the build tree + File f = new File("freenet.ini"); + if(!f.exists()) + f = new File("build.xml"); + BufferedInputStream bis1 = new BufferedInputStream(new FileInputStream(f)); + BufferedInputStream bis2 = new BufferedInputStream(new FileInputStream(f)); + LineReadingInputStream lris1 = new LineReadingInputStream(bis1); + LineReadingInputStream lris2 = new LineReadingInputStream(bis2); + + while(bis1.available() > 0 || bis2.available() > 0) { + String stringWithoutMark =lris2.readLineWithoutMarking(MAX_LENGTH*10, BUFFER_SIZE, true); + String stringWithMark = lris1.readLine(MAX_LENGTH*10, BUFFER_SIZE, true); + assertEquals(stringWithMark, stringWithoutMark); + } + assertNull(lris1.readLine(MAX_LENGTH, BUFFER_SIZE, true)); + assertNull(lris2.readLineWithoutMarking(MAX_LENGTH, BUFFER_SIZE, true)); + } +}
