Author: j16sdiz Date: 2008-08-15 08:20:48 +0000 (Fri, 15 Aug 2008) New Revision: 21886
Added: branches/saltedhashstore/freenet/src/freenet/config/ConfigException.java branches/saltedhashstore/freenet/src/freenet/config/NodeNeedRestartException.java branches/saltedhashstore/freenet/src/freenet/node/simulator/BootstrapPullTest.java branches/saltedhashstore/freenet/src/freenet/node/simulator/BootstrapPushPullTest.java branches/saltedhashstore/freenet/src/freenet/node/simulator/BootstrapSeedTest.java branches/saltedhashstore/freenet/src/freenet/pluginmanager/FredPluginBandwidthIndicator.java branches/saltedhashstore/freenet/test/freenet/crypt/YarrowTest.java Removed: branches/saltedhashstore/freenet/src/freenet/client/TempStoreElement.java branches/saltedhashstore/freenet/src/freenet/clients/http/NinjaSpider.java branches/saltedhashstore/freenet/src/freenet/clients/http/PluginToadlet.java branches/saltedhashstore/freenet/src/freenet/clients/http/Spider.java branches/saltedhashstore/freenet/src/freenet/oldplugins/plugin/HttpPlugin.java branches/saltedhashstore/freenet/src/freenet/oldplugins/plugin/Plugin.java branches/saltedhashstore/freenet/src/freenet/oldplugins/plugin/PluginManager.java branches/saltedhashstore/freenet/src/freenet/oldplugins/plugin/TestHttpPlugin.java branches/saltedhashstore/freenet/src/freenet/oldplugins/plugin/TestPlugin.java branches/saltedhashstore/freenet/src/freenet/support/StringArray.java branches/saltedhashstore/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucketFactory.java branches/saltedhashstore/freenet/src/freenet/support/io/PersistentEncryptedTempBucketFactory.java Modified: branches/saltedhashstore/freenet/src/freenet/client/ArchiveManager.java branches/saltedhashstore/freenet/src/freenet/client/FECCodec.java branches/saltedhashstore/freenet/src/freenet/client/HighLevelSimpleClientImpl.java branches/saltedhashstore/freenet/src/freenet/client/RealArchiveStoreItem.java branches/saltedhashstore/freenet/src/freenet/client/async/BaseSingleFileFetcher.java branches/saltedhashstore/freenet/src/freenet/client/async/ClientRequestScheduler.java branches/saltedhashstore/freenet/src/freenet/client/async/SimpleManifestPutter.java branches/saltedhashstore/freenet/src/freenet/client/async/SimpleSingleFileFetcher.java branches/saltedhashstore/freenet/src/freenet/client/async/SplitFileFetcherSegment.java branches/saltedhashstore/freenet/src/freenet/client/async/USKChecker.java branches/saltedhashstore/freenet/src/freenet/clients/http/ConfigToadlet.java branches/saltedhashstore/freenet/src/freenet/clients/http/ConnectionsToadlet.java branches/saltedhashstore/freenet/src/freenet/clients/http/FProxyToadlet.java branches/saltedhashstore/freenet/src/freenet/clients/http/FirstTimeWizardToadlet.java branches/saltedhashstore/freenet/src/freenet/clients/http/HTTPRequestImpl.java branches/saltedhashstore/freenet/src/freenet/clients/http/PageMaker.java branches/saltedhashstore/freenet/src/freenet/clients/http/QueueToadlet.java branches/saltedhashstore/freenet/src/freenet/clients/http/SimpleToadletServer.java branches/saltedhashstore/freenet/src/freenet/clients/http/StatisticsToadlet.java branches/saltedhashstore/freenet/src/freenet/clients/http/SymlinkerToadlet.java branches/saltedhashstore/freenet/src/freenet/clients/http/bookmark/BookmarkCategory.java branches/saltedhashstore/freenet/src/freenet/clients/http/staticfiles/themes/clean/theme.css branches/saltedhashstore/freenet/src/freenet/config/BooleanOption.java branches/saltedhashstore/freenet/src/freenet/config/Config.java branches/saltedhashstore/freenet/src/freenet/config/ConfigCallback.java branches/saltedhashstore/freenet/src/freenet/config/IntOption.java branches/saltedhashstore/freenet/src/freenet/config/InvalidConfigValueException.java branches/saltedhashstore/freenet/src/freenet/config/LongOption.java branches/saltedhashstore/freenet/src/freenet/config/Option.java branches/saltedhashstore/freenet/src/freenet/config/PersistentConfig.java branches/saltedhashstore/freenet/src/freenet/config/ShortOption.java branches/saltedhashstore/freenet/src/freenet/config/StringArrOption.java branches/saltedhashstore/freenet/src/freenet/config/StringOption.java branches/saltedhashstore/freenet/src/freenet/config/SubConfig.java branches/saltedhashstore/freenet/src/freenet/config/WrapperConfig.java branches/saltedhashstore/freenet/src/freenet/crypt/DiffieHellman.java branches/saltedhashstore/freenet/src/freenet/crypt/SSL.java branches/saltedhashstore/freenet/src/freenet/crypt/Yarrow.java branches/saltedhashstore/freenet/src/freenet/io/AddressIdentifier.java branches/saltedhashstore/freenet/src/freenet/io/NetworkInterface.java branches/saltedhashstore/freenet/src/freenet/io/comm/DMT.java branches/saltedhashstore/freenet/src/freenet/io/comm/FreenetInetAddress.java branches/saltedhashstore/freenet/src/freenet/io/comm/UdpSocketHandler.java branches/saltedhashstore/freenet/src/freenet/l10n/freenet.l10n.de.properties branches/saltedhashstore/freenet/src/freenet/l10n/freenet.l10n.en.properties branches/saltedhashstore/freenet/src/freenet/l10n/freenet.l10n.fr.properties branches/saltedhashstore/freenet/src/freenet/l10n/freenet.l10n.zh-cn.properties branches/saltedhashstore/freenet/src/freenet/l10n/freenet.l10n.zh-tw.properties branches/saltedhashstore/freenet/src/freenet/node/ConfigurablePersister.java branches/saltedhashstore/freenet/src/freenet/node/FNPPacketMangler.java branches/saltedhashstore/freenet/src/freenet/node/FailureTableEntry.java branches/saltedhashstore/freenet/src/freenet/node/GlobalProbe.java branches/saltedhashstore/freenet/src/freenet/node/IPDetectorPluginManager.java branches/saltedhashstore/freenet/src/freenet/node/LoggingConfigHandler.java branches/saltedhashstore/freenet/src/freenet/node/Node.java branches/saltedhashstore/freenet/src/freenet/node/NodeClientCore.java branches/saltedhashstore/freenet/src/freenet/node/NodeCrypto.java branches/saltedhashstore/freenet/src/freenet/node/NodeCryptoConfig.java branches/saltedhashstore/freenet/src/freenet/node/NodeDispatcher.java branches/saltedhashstore/freenet/src/freenet/node/NodeIPDetector.java branches/saltedhashstore/freenet/src/freenet/node/NodeStarter.java branches/saltedhashstore/freenet/src/freenet/node/NodeStats.java branches/saltedhashstore/freenet/src/freenet/node/PeerManager.java branches/saltedhashstore/freenet/src/freenet/node/PeerNode.java branches/saltedhashstore/freenet/src/freenet/node/PeerNodeStatus.java branches/saltedhashstore/freenet/src/freenet/node/SeedClientPeerNode.java branches/saltedhashstore/freenet/src/freenet/node/TestnetHandler.java branches/saltedhashstore/freenet/src/freenet/node/TextModeClientInterface.java branches/saltedhashstore/freenet/src/freenet/node/TextModeClientInterfaceServer.java branches/saltedhashstore/freenet/src/freenet/node/UptimeEstimator.java branches/saltedhashstore/freenet/src/freenet/node/fcp/ClientGet.java branches/saltedhashstore/freenet/src/freenet/node/fcp/ClientPutMessage.java branches/saltedhashstore/freenet/src/freenet/node/fcp/ClientRequest.java branches/saltedhashstore/freenet/src/freenet/node/fcp/ConfigData.java branches/saltedhashstore/freenet/src/freenet/node/fcp/FCPServer.java branches/saltedhashstore/freenet/src/freenet/node/fcp/PutSuccessfulMessage.java branches/saltedhashstore/freenet/src/freenet/node/simulator/RealNodeBusyNetworkTest.java branches/saltedhashstore/freenet/src/freenet/node/simulator/RealNodeRequestInsertTest.java branches/saltedhashstore/freenet/src/freenet/node/simulator/SeednodePingTest.java branches/saltedhashstore/freenet/src/freenet/node/updater/NodeUpdateManager.java branches/saltedhashstore/freenet/src/freenet/node/useralerts/MeaningfulNodeNameUserAlert.java branches/saltedhashstore/freenet/src/freenet/pluginmanager/PluginDownLoaderOfficial.java branches/saltedhashstore/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java branches/saltedhashstore/freenet/src/freenet/pluginmanager/PluginManager.java branches/saltedhashstore/freenet/src/freenet/support/Fields.java branches/saltedhashstore/freenet/src/freenet/support/PooledExecutor.java branches/saltedhashstore/freenet/src/freenet/support/SizeUtil.java branches/saltedhashstore/freenet/src/freenet/support/TimeSortedHashtable.java branches/saltedhashstore/freenet/src/freenet/support/api/BooleanCallback.java branches/saltedhashstore/freenet/src/freenet/support/api/IntCallback.java branches/saltedhashstore/freenet/src/freenet/support/api/LongCallback.java branches/saltedhashstore/freenet/src/freenet/support/api/ShortCallback.java branches/saltedhashstore/freenet/src/freenet/support/api/StringArrCallback.java branches/saltedhashstore/freenet/src/freenet/support/api/StringCallback.java branches/saltedhashstore/freenet/src/freenet/support/compress/GzipCompressor.java branches/saltedhashstore/freenet/src/freenet/support/io/ArrayBucket.java branches/saltedhashstore/freenet/src/freenet/support/io/BaseFileBucket.java branches/saltedhashstore/freenet/src/freenet/support/io/BucketTools.java branches/saltedhashstore/freenet/src/freenet/support/io/DelayedFreeBucket.java branches/saltedhashstore/freenet/src/freenet/support/io/NativeThread.java branches/saltedhashstore/freenet/src/freenet/support/io/PersistentTempBucketFactory.java branches/saltedhashstore/freenet/src/freenet/support/io/TempBucketFactory.java Log: Merge trunk r21884 into saltedhashstore Modified: branches/saltedhashstore/freenet/src/freenet/client/ArchiveManager.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/client/ArchiveManager.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/client/ArchiveManager.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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; @@ -13,17 +12,13 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; -import freenet.crypt.RandomSource; import freenet.keys.FreenetURI; import freenet.support.LRUHashtable; 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; /** * Cache of recently decoded archives: @@ -38,9 +33,7 @@ public static final String METADATA_NAME = ".metadata"; private static boolean logMINOR; - - final RandomSource strongPRNG; - final Random weakPRNG; + final long maxArchiveSize; final long maxArchivedFileSize; @@ -57,8 +50,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. @@ -75,7 +68,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; @@ -83,9 +76,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); } @@ -238,8 +229,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; @@ -249,7 +239,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; } } @@ -257,7 +247,7 @@ out.close(); if(name.equals(".metadata")) gotMetadata = true; - addStoreElement(ctx, key, name, temp, gotElement, element, callback); + addStoreElement(ctx, key, name, output, gotElement, element, callback); names.add(name); trimStoredData(); } @@ -313,18 +303,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); + return addStoreElement(ctx, key, ".metadata", bucket, gotElement, element2, callback); } catch (MetadataUnresolvedException e) { try { - x = resolve(e, x, element, ctx, key, gotElement, element2, callback); + x = resolve(e, x, bucket, ctx, key, gotElement, element2, callback); } catch (IOException e1) { throw new ArchiveFailureException("Failed to create metadata: "+e1, e1); } @@ -335,17 +326,17 @@ } } - private int resolve(MetadataUnresolvedException e, int x, TempStoreElement element, ArchiveStoreContext ctx, FreenetURI key, MutableBoolean gotElement, String element2, ArchiveExtractCallback callback) throws IOException, ArchiveFailureException { + private int resolve(MetadataUnresolvedException e, int x, Bucket bucket, ArchiveStoreContext ctx, FreenetURI key, MutableBoolean gotElement, String element2, ArchiveExtractCallback callback) 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); + addStoreElement(ctx, key, ".metadata-"+(x++), bucket, gotElement, element2, callback); } catch (MetadataUnresolvedException e1) { - x = resolve(e, x, element, ctx, key, gotElement, element2, callback); + x = resolve(e, x, bucket, ctx, key, gotElement, element2, callback); } } return x; @@ -413,7 +404,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) throws ArchiveFailureException { + private ArchiveStoreItem addStoreElement(ArchiveStoreContext ctx, FreenetURI key, String name, Bucket temp, MutableBoolean gotElement, String callbackName, ArchiveExtractCallback callback) 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; @@ -464,23 +455,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/saltedhashstore/freenet/src/freenet/client/FECCodec.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/client/FECCodec.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/client/FECCodec.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -199,7 +199,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/saltedhashstore/freenet/src/freenet/client/HighLevelSimpleClientImpl.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/client/HighLevelSimpleClientImpl.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/client/HighLevelSimpleClientImpl.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -98,7 +98,7 @@ curMaxTempLength = Long.MAX_VALUE; curMaxMetadataLength = 1024 * 1024; this.cacheLocalRequests = cacheLocalRequests; - this.persistentBucketFactory = node.persistentEncryptedTempBucketFactory; + this.persistentBucketFactory = node.persistentTempBucketFactory; this.healingQueue = node.getHealingQueue(); this.blockEncoder = node.backgroundBlockEncoder; } Modified: branches/saltedhashstore/freenet/src/freenet/client/RealArchiveStoreItem.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/client/RealArchiveStoreItem.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/client/RealArchiveStoreItem.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/client/TempStoreElement.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/client/TempStoreElement.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/client/TempStoreElement.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/client/async/BaseSingleFileFetcher.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/client/async/BaseSingleFileFetcher.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/client/async/BaseSingleFileFetcher.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -12,6 +12,7 @@ import freenet.node.KeysFetchingLocally; import freenet.node.RequestScheduler; import freenet.node.SendableGet; +import freenet.support.Executor; import freenet.support.Logger; public abstract class BaseSingleFileFetcher extends SendableGet { @@ -64,9 +65,12 @@ return key instanceof ClientSSK; } - /** Try again - returns true if we can retry - * @param sched */ - protected boolean retry(RequestScheduler sched) { + /** + * Try again - returns true if we can retry + * @param sched + * @param the executor we will use to run the retry off-thread + */ + protected boolean retry(RequestScheduler sched, Executor exec) { retryCount++; if(Logger.shouldLog(Logger.MINOR, this)) Logger.minor(this, "Attempting to retry... (max "+maxRetries+", current "+retryCount+ ')'); @@ -79,12 +83,15 @@ Logger.error(this, "Already on the cooldown queue for "+this, new Exception("error")); else cooldownWakeupTime = sched.queueCooldown(key, this); - return true; // We will retry, just not yet. See requeueAfterCooldown(Key). } else { + exec.execute(new Runnable() { + public void run() { schedule(); } - return true; + }, "Retry executor for "+sched.toString()); } + return true; // We will retry in any case, maybe not just not yet. See requeueAfterCooldown(Key). + } return false; } Modified: branches/saltedhashstore/freenet/src/freenet/client/async/ClientRequestScheduler.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/client/async/ClientRequestScheduler.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/client/async/ClientRequestScheduler.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -41,7 +41,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/saltedhashstore/freenet/src/freenet/client/async/SimpleManifestPutter.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/client/async/SimpleManifestPutter.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/client/async/SimpleManifestPutter.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -405,7 +405,7 @@ // FIXME support formats other than .zip. // Only the *decoding* is generic at present. - Bucket zipBucket = ctx.bf.makeBucket(-1); + Bucket zipBucket = ctx.bf.makeBucket(baseMetadata.dataLength()); OutputStream os = new BufferedOutputStream(zipBucket.getOutputStream()); ZipOutputStream zos = new ZipOutputStream(os); ZipEntry ze; Modified: branches/saltedhashstore/freenet/src/freenet/client/async/SimpleSingleFileFetcher.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/client/async/SimpleSingleFileFetcher.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/client/async/SimpleSingleFileFetcher.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -94,7 +94,7 @@ forceFatal = true; } if(!(e.isFatal() || forceFatal) ) { - if(retry(sched)) { + if(retry(sched, ctx.executor)) { if(logMINOR) Logger.minor(this, "Retrying"); return; } Modified: branches/saltedhashstore/freenet/src/freenet/client/async/SplitFileFetcherSegment.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/client/async/SplitFileFetcherSegment.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/client/async/SplitFileFetcherSegment.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -227,7 +227,7 @@ } } } - decodedData = fetchContext.bucketFactory.makeBucket(-1); + decodedData = fetchContext.bucketFactory.makeBucket(maxBlockLength * dataBuckets.length); if(logMINOR) Logger.minor(this, "Copying data from data blocks"); OutputStream os = decodedData.getOutputStream(); for(int i=0;i<dataBuckets.length;i++) { @@ -261,7 +261,7 @@ // Encode any check blocks we don't have if(codec != null) { - codec.addToQueue(new FECJob(codec, dataBuckets, checkBuckets, 32768, fetchContext.bucketFactory, this, false)); + codec.addToQueue(new FECJob(codec, dataBuckets, checkBuckets, CHKBlock.DATA_LENGTH, fetchContext.bucketFactory, this, false)); } } Modified: branches/saltedhashstore/freenet/src/freenet/client/async/USKChecker.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/client/async/USKChecker.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/client/async/USKChecker.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -61,7 +61,7 @@ canRetry = true; } - if(canRetry && retry(sched)) return; + if(canRetry && retry(sched, ctx.executor)) return; // Ran out of retries. unregister(false); Modified: branches/saltedhashstore/freenet/src/freenet/clients/http/ConfigToadlet.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/clients/http/ConfigToadlet.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/clients/http/ConfigToadlet.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/clients/http/ConnectionsToadlet.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/clients/http/ConnectionsToadlet.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/clients/http/ConnectionsToadlet.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/clients/http/FProxyToadlet.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/clients/http/FProxyToadlet.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/clients/http/FProxyToadlet.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -55,7 +55,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 { @@ -94,6 +94,7 @@ return "GET"; } + @Override public void handlePost(URI uri, HTTPRequest req, ToadletContext ctx) throws ToadletContextClosedException, IOException, RedirectException { String ks = uri.getPath(); @@ -319,9 +320,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); @@ -442,7 +444,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(); @@ -570,7 +572,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")); } @@ -663,9 +665,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/saltedhashstore/freenet/src/freenet/clients/http/FirstTimeWizardToadlet.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/clients/http/FirstTimeWizardToadlet.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/clients/http/FirstTimeWizardToadlet.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/clients/http/HTTPRequestImpl.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/clients/http/HTTPRequestImpl.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/clients/http/HTTPRequestImpl.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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; } Deleted: branches/saltedhashstore/freenet/src/freenet/clients/http/NinjaSpider.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/clients/http/NinjaSpider.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/clients/http/NinjaSpider.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -1,739 +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.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - -import org.w3c.dom.DOMImplementation; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Text; - -import freenet.client.ClientMetadata; -import freenet.client.FetchException; -import freenet.client.FetchResult; -import freenet.client.FetchContext; -import freenet.client.InsertException; -import freenet.client.async.BaseClientPutter; -import freenet.client.async.ClientCallback; -import freenet.client.async.ClientGetter; -import freenet.clients.http.filter.ContentFilter; -import freenet.clients.http.filter.FoundURICallback; -import freenet.clients.http.filter.UnsafeContentTypeException; -import freenet.keys.FreenetURI; -import freenet.node.NodeClientCore; -import freenet.node.RequestStarter; -import freenet.oldplugins.plugin.HttpPlugin; -import freenet.oldplugins.plugin.PluginManager; -import freenet.support.HTMLNode; -import freenet.support.Logger; -import freenet.support.MultiValueTable; -import freenet.support.api.Bucket; -import freenet.support.api.HTTPRequest; -import freenet.support.io.NullBucketFactory; - -/** - * FIXME move to a proper plugin. - * - * FIXME localise - and how to do that for plugins? Should they use the main L10n? - * - * NinjaSpider. Produces a ninj^W err ... an XML index. - * - * - * I think regarding the name, a little explanation is required: - * - * This name comes from my flatmate, David Anderson. It originated in the following discussion over dinner: - * him> I've just thought of something weird... - * me> oO - * him> The term "spider" for indexing software comes from the analogy "a spider on the web", right ? - * me> Yeeess... ? - * him> So, if you're writing a spider for a darknet, isn't it a .... *Ninja Spider* ? :D - * - * Maybe we should stop buying beers ... However, I needed a name for the spider, - * and NinjaSpider sounds more fun than XmlSpider, so it stuck :) - * - */ -public class NinjaSpider implements HttpPlugin, ClientCallback, FoundURICallback { - - - long tProducedIndex; - - // URIs visited, or fetching, or queued. Added once then forgotten about. - private final HashSet visitedURIs = new HashSet(); - private final HashSet urisWithWords = new HashSet(); - private final HashSet failedURIs = new HashSet(); - private final HashSet queuedURISet = new HashSet(); - private final LinkedList queuedURIList = new LinkedList(); - private final HashMap runningFetchesByURI = new HashMap(); - private final HashMap urisByWord = new HashMap(); - private final HashMap titlesOfURIs = new HashMap(); - - private static final int minTimeBetweenEachIndexRewriting = 10; - - // Can have many; this limit only exists to save memory. - private static final int maxParallelRequests = 20; - private int maxShownURIs = 50; - - private NodeClientCore core; - private FetchContext ctx; - private final short PRIORITY_CLASS = RequestStarter.PREFETCH_PRIORITY_CLASS; - private boolean stopped = true; - - private static final String indexFilename = "new.index.xml"; - - private static final String pluginName = "Ninja spider"; - - private static final boolean htmlOnly = true; - - - /* The ones below are required to genereate a correct index, see: - * http://wiki.freenetproject.org/AnotherFreenetIndexFormat - */ - private static final String indexTitle= "This is an index"; - private static final String indexOwner = "Another anonymous"; - private static final String indexOwnerEmail = null; /* can be null */ - private final HashMap sizeOfURIs = new HashMap(); /* String (URI) -> Long */ - private final HashMap mimeOfURIs = new HashMap(); /* String (URI) -> String */ - private final HashMap lastPositionByURI = new HashMap(); /* String (URI) -> Integer */ /* Use to determine word position on each uri */ - private final HashMap positionsByWordByURI = new HashMap(); /* String (URI) -> HashMap (String (word) -> Integer[] (Positions)) */ - - - - private synchronized void queueURI(FreenetURI uri) { - /* Currently we don't handle PDF or other contents, - so it's not interresting to download them - */ - - String tmp = uri.toString().toLowerCase(); - - if(htmlOnly - && (tmp.indexOf(".htm") < 0) - && (tmp.charAt(tmp.length()-1) != '/')) - return; - - if ((!visitedURIs.contains(uri)) && queuedURISet.add(uri)) { - queuedURIList.addLast(uri); - visitedURIs.add(uri); - } - } - - private void startSomeRequests() { - ArrayList toStart = null; - synchronized (this) { - if (stopped) { - return; - } - int running = runningFetchesByURI.size(); - int queued = queuedURIList.size(); - - if ((running >= maxParallelRequests) || (queued == 0)) - return; - - toStart = new ArrayList(Math.min(maxParallelRequests - running, queued)); - - for (int i = running; i < maxParallelRequests; i++) { - if (queuedURIList.isEmpty()) - break; - FreenetURI uri = (FreenetURI) queuedURIList.removeFirst(); - queuedURISet.remove(uri); - ClientGetter getter = makeGetter(uri); - toStart.add(getter); - } - for (int i = 0; i < toStart.size(); i++) { - ClientGetter g = (ClientGetter) toStart.get(i); - try { - runningFetchesByURI.put(g.getURI(), g); - g.start(); - } catch (FetchException e) { - onFailure(e, g); - } - } - } - } - - private ClientGetter makeGetter(FreenetURI uri) { - ClientGetter g = new ClientGetter(this, core.requestStarters.chkFetchScheduler, core.requestStarters.sskFetchScheduler, uri, ctx, PRIORITY_CLASS, this, null, null); - return g; - } - - public void onSuccess(FetchResult result, ClientGetter state) { - FreenetURI uri = state.getURI(); - synchronized (this) { - runningFetchesByURI.remove(uri); - } - startSomeRequests(); - ClientMetadata cm = result.getMetadata(); - Bucket data = result.asBucket(); - String mimeType = cm.getMIMEType(); - - sizeOfURIs.put(uri.toString(), new Long(data.size())); - mimeOfURIs.put(uri.toString(), mimeType); - - try { - ContentFilter.filter(data, new NullBucketFactory(), mimeType, new URI("http://127.0.0.1:8888/" + uri.toString()), this); - } catch (UnsafeContentTypeException e) { - return; // Ignore - } catch (IOException e) { - Logger.error(this, "Bucket error?: " + e, e); - } catch (URISyntaxException e) { - Logger.error(this, "Internal error: " + e, e); - } finally { - data.free(); - } - } - - public void onFailure(FetchException e, ClientGetter state) { - FreenetURI uri = state.getURI(); - synchronized (this) { - failedURIs.add(uri); - runningFetchesByURI.remove(uri); - } - if (e.newURI != null) - queueURI(e.newURI); - else - queueURI(uri); - startSomeRequests(); - } - - public void onSuccess(BaseClientPutter state) { - // Ignore - } - - public void onFailure(InsertException e, BaseClientPutter state) { - // Ignore - } - - public void onGeneratedURI(FreenetURI uri, BaseClientPutter state) { - // Ignore - } - - public void foundURI(FreenetURI uri) { - queueURI(uri); - startSomeRequests(); - } - - public void foundURI(FreenetURI uri, boolean inline) { - queueURI(uri); - startSomeRequests(); - } - - public void onText(String s, String type, URI baseURI) { - - FreenetURI uri; - try { - uri = new FreenetURI(baseURI.getPath().substring(1));/*substring(1) because we don't want the initial '/' */ - } catch (MalformedURLException e) { - Logger.error(this, "Caught " + e, e); - return; - } - - if((type != null) && (type.length() != 0) && type.toLowerCase().equals("title") - && (s != null) && (s.length() != 0) && (s.indexOf('\n') < 0)) { - /* We should have a correct title */ - titlesOfURIs.put(uri.toString(), s); - type = "title"; - } - else - type = null; - - - String[] words = s.split("[^A-Za-z0-9]"); - - Integer lastPosition = null; - - lastPosition = (Integer)lastPositionByURI.get(uri.toString()); - - if(lastPosition == null) - lastPosition = new Integer(1); /* We start to count from 1 */ - - for (int i = 0; i < words.length; i++) { - String word = words[i]; - if ((word == null) || (word.length() == 0)) - continue; - word = word.toLowerCase(); - - if(type == null) - addWord(word, lastPosition.intValue() + i, uri); - else - addWord(word, -1 * (i+1), uri); - } - - if(type == null) { - lastPosition = new Integer(lastPosition.intValue() + words.length); - lastPositionByURI.put(uri.toString(), lastPosition); - } - } - - private synchronized void addWord(String word, int position, FreenetURI uri) { - - /* I know that it's bad for i18n */ - /* But words separation or file filtering seems to already killed words matching [^a-zA-Z] ... */ - if(word.length() < 3) - return; - - - FreenetURI[] uris = (FreenetURI[]) urisByWord.get(word); - - //Integer[] positions = (Integer[]) positionsByWordByURI.get(word); - - urisWithWords.add(uri); - - - /* Word position indexation */ - HashMap wordPositionsForOneUri = (HashMap)positionsByWordByURI.get(uri.toString()); /* For a given URI, take as key a word, and gives position */ - - if(wordPositionsForOneUri == null) { - wordPositionsForOneUri = new HashMap(); - wordPositionsForOneUri.put(word, new Integer[] { new Integer(position) }); - positionsByWordByURI.put(uri.toString(), wordPositionsForOneUri); - } else { - Integer[] positions = (Integer[])wordPositionsForOneUri.get(word); - - if(positions == null) { - positions = new Integer[] { new Integer(position) }; - wordPositionsForOneUri.put(word, positions); - } else { - Integer[] newPositions = new Integer[positions.length + 1]; - - System.arraycopy(positions, 0, newPositions, 0, positions.length); - newPositions[positions.length] = new Integer(position); - - wordPositionsForOneUri.put(word, newPositions); - } - } - - - - /* Words indexation */ - if (uris == null) { - urisByWord.put(word, new FreenetURI[] { uri }); - } else { - for (int i = 0; i < uris.length; i++) { - if (uris[i].equals(uri)) - return; - } - - FreenetURI[] newURIs = new FreenetURI[uris.length + 1]; - - System.arraycopy(uris, 0, newURIs, 0, uris.length); - newURIs[uris.length] = uri; - urisByWord.put(word, newURIs); - } - - if (tProducedIndex + minTimeBetweenEachIndexRewriting * 1000 < System.currentTimeMillis()) { - try { - produceIndex(); - } catch (IOException e) { - Logger.error(this, "Caught " + e + " while creating index", e); - } - tProducedIndex = System.currentTimeMillis(); - } - } - - /** - * Produce an XML index in new.index.xml - */ - private synchronized void produceIndex() throws IOException { - File outputFile; - StreamResult resultStream; - - if (urisByWord.isEmpty() || urisWithWords.isEmpty()) { - Logger.normal(this, "No URIs with words -> no index generation"); - return; - } - - outputFile = new File(indexFilename); - - if(outputFile.exists() - && !outputFile.canWrite()) { - Logger.error(this, "Spider: Unable to write '" + indexFilename +"'. Check permissions."); - return; - } - - resultStream = new StreamResult(outputFile); - - - /* Initialize xml builder */ - Document xmlDoc = null; - DocumentBuilderFactory xmlFactory = null; - DocumentBuilder xmlBuilder = null; - DOMImplementation impl = null; - Element rootElement = null; - - xmlFactory = DocumentBuilderFactory.newInstance(); - - - try { - xmlBuilder = xmlFactory.newDocumentBuilder(); - } catch(javax.xml.parsers.ParserConfigurationException e) { - /* Will (should ?) never happen */ - Logger.error(this, "Spider: Error while initializing XML generator: "+e.toString()); - return; - } - - - impl = xmlBuilder.getDOMImplementation(); - - /* Starting to generate index */ - - xmlDoc = impl.createDocument(null, "index", null); - rootElement = xmlDoc.getDocumentElement(); - - /* Adding header to the index */ - Element headerElement = xmlDoc.createElement("header"); - - /* -> title */ - Element subHeaderElement = xmlDoc.createElement("title"); - Text subHeaderText = xmlDoc.createTextNode(indexTitle); - - subHeaderElement.appendChild(subHeaderText); - headerElement.appendChild(subHeaderElement); - - /* -> owner */ - subHeaderElement = xmlDoc.createElement("owner"); - subHeaderText = xmlDoc.createTextNode(indexOwner); - - subHeaderElement.appendChild(subHeaderText); - headerElement.appendChild(subHeaderElement); - - /* -> owner email */ - if(indexOwnerEmail != null) { - subHeaderElement = xmlDoc.createElement("email"); - subHeaderText = xmlDoc.createTextNode(indexOwnerEmail); - - subHeaderElement.appendChild(subHeaderText); - headerElement.appendChild(subHeaderElement); - } - - - - String[] words = (String[]) urisByWord.keySet().toArray(new String[urisByWord.size()]); - Arrays.sort(words); - - FreenetURI[] uris = (FreenetURI[]) urisWithWords.toArray(new FreenetURI[urisWithWords.size()]); - HashMap urisToNumbers = new HashMap(); - - /* Adding freesite list to the index */ - Element filesElement = xmlDoc.createElement("files"); /* filesElement != fileElement */ - - for (int i = 0; i < uris.length; i++) { - urisToNumbers.put(uris[i], new Integer(i)); - - Element fileElement = xmlDoc.createElement("file"); - - fileElement.setAttribute("id", Integer.toString(i)); - fileElement.setAttribute("key", uris[i].toString()); - - Long size = (Long)sizeOfURIs.get(uris[i].toString()); - - if(size == null) { - Logger.error(this, "Spider: size is missing"); - } else { - fileElement.setAttribute("size", size.toString()); - } - fileElement.setAttribute("mime", ((String)mimeOfURIs.get(uris[i].toString()))); - - Element titleElement = xmlDoc.createElement("option"); - titleElement.setAttribute("name", "title"); - titleElement.setAttribute("value", (String)titlesOfURIs.get(uris[i].toString())); - - fileElement.appendChild(titleElement); - filesElement.appendChild(fileElement); - } - - - /* Adding word index */ - Element keywordsElement = xmlDoc.createElement("keywords"); - - /* Word by word */ - for (int i = 0; i < words.length; i++) { - Element wordElement = xmlDoc.createElement("word"); - wordElement.setAttribute("v", words[i]); - - FreenetURI[] urisForWord = (FreenetURI[]) urisByWord.get(words[i]); - - /* URI by URI */ - for (int j = 0; j < urisForWord.length; j++) { - FreenetURI uri = urisForWord[j]; - Integer x = (Integer) urisToNumbers.get(uri); - - if (x == null) { - Logger.error(this, "Eh?"); - continue; - } - - Element uriElement = xmlDoc.createElement("file"); - uriElement.setAttribute("id", x.toString()); - - /* Position by position */ - HashMap positionsForGivenWord = (HashMap)positionsByWordByURI.get(uri.toString()); - Integer[] positions = (Integer[])positionsForGivenWord.get(words[i]); - - StringBuffer positionList = new StringBuffer(); - - for(int k=0; k < positions.length ; k++) { - if(k!=0) - positionList.append(','); - - positionList.append(positions[k].toString()); - } - - uriElement.appendChild(xmlDoc.createTextNode(positionList.toString())); - - wordElement.appendChild(uriElement); - } - - keywordsElement.appendChild(wordElement); - } - - rootElement.appendChild(headerElement); - rootElement.appendChild(filesElement); - rootElement.appendChild(keywordsElement); - - /* Serialization */ - DOMSource domSource = new DOMSource(xmlDoc); - TransformerFactory transformFactory = TransformerFactory.newInstance(); - Transformer serializer; - - try { - serializer = transformFactory.newTransformer(); - } catch(javax.xml.transform.TransformerConfigurationException e) { - Logger.error(this, "Spider: Error while serializing XML (transformFactory.newTransformer()): "+e.toString()); - return; - } - - - serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); - serializer.setOutputProperty(OutputKeys.INDENT,"yes"); - - /* final step */ - try { - serializer.transform(domSource, resultStream); - } catch(javax.xml.transform.TransformerException e) { - Logger.error(this, "Spider: Error while serializing XML (transform()): "+e.toString()); - return; - } - - if(Logger.shouldLog(Logger.MINOR, this)) - Logger.minor(this, "Spider: indexes regenerated."); - } - - /** - * @see freenet.oldplugins.plugin.HttpPlugin#handleGet(freenet.clients.http.HTTPRequestImpl, freenet.clients.http.ToadletContext) - */ - public void handleGet(HTTPRequest request, ToadletContext context) throws IOException, ToadletContextClosedException { - String action = request.getParam("action"); - PageMaker pageMaker = context.getPageMaker(); - if ((action == null) || (action.length() == 0)) { - MultiValueTable responseHeaders = new MultiValueTable(); - responseHeaders.put("Location", "?action=list"); - context.sendReplyHeaders(301, "Redirect", responseHeaders, "text/html; charset=utf-8", 0); - return; - } else if ("list".equals(action)) { - String listName = request.getParam("listName", null); - - HTMLNode pageNode = pageMaker.getPageNode(pluginName, context); - HTMLNode contentNode = pageMaker.getContentNode(pageNode); - - /* create copies for multi-threaded use */ - if (listName == null) { - Map runningFetches = new HashMap(runningFetchesByURI); - List queued = new ArrayList(queuedURIList); - Set visited = new HashSet(visitedURIs); - Set failed = new HashSet(failedURIs); - contentNode.addChild(createNavbar(runningFetches.size(), queued.size(), visited.size(), failed.size())); - contentNode.addChild(createAddBox()); - contentNode.addChildren(createList("Running Fetches", "running", runningFetches.keySet(), maxShownURIs)); - contentNode.addChildren(createList("Queued URIs", "queued", queued, maxShownURIs)); - contentNode.addChildren(createList("Visited URIs", "visited", visited, maxShownURIs)); - contentNode.addChildren(createList("Failed URIs", "failed", failed, maxShownURIs)); - } else { - contentNode.addChild(createBackBox()); - if ("failed".equals(listName)) { - Set failed = new HashSet(failedURIs); - contentNode.addChildren(createList("Failed URIs", "failed", failed, -1)); - } else if ("visited".equals(listName)) { - Set visited = new HashSet(visitedURIs); - contentNode.addChildren(createList("Visited URIs", "visited", visited, -1)); - } else if ("queued".equals(listName)) { - List queued = new ArrayList(queuedURIList); - contentNode.addChildren(createList("Queued URIs", "queued", queued, -1)); - } else if ("running".equals(listName)) { - Map runningFetches = new HashMap(runningFetchesByURI); - contentNode.addChildren(createList("Running Fetches", "running", runningFetches.keySet(), -1)); - } - } - MultiValueTable responseHeaders = new MultiValueTable(); - byte[] responseBytes = pageNode.generate().getBytes("UTF-8"); - context.sendReplyHeaders(200, "OK", responseHeaders, "text/html; charset=utf-8", responseBytes.length); - context.writeData(responseBytes); - } else if ("add".equals(action)) { - String uriParam = request.getParam("key"); - try { - FreenetURI uri = new FreenetURI(uriParam); - synchronized (this) { - failedURIs.remove(uri); - visitedURIs.remove(uri); - } - queueURI(uri); - startSomeRequests(); - } catch (MalformedURLException mue1) { - sendSimpleResponse(context, "URL invalid", "The given URI is not valid. Please return and try again."); - return; - } - MultiValueTable responseHeaders = new MultiValueTable(); - responseHeaders.put("Location", "?action=list"); - context.sendReplyHeaders(301, "Redirect", responseHeaders, "text/html; charset=utf-8", 0); - return; - } - } - - /** - * @see freenet.oldplugins.plugin.HttpPlugin#handlePost(freenet.clients.http.HTTPRequestImpl, freenet.clients.http.ToadletContext) - */ - public void handlePost(HTTPRequest request, ToadletContext context) throws IOException { - } - - private void sendSimpleResponse(ToadletContext context, String title, String message) throws ToadletContextClosedException, IOException { - 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); - infobox.addChild("div", "class", "infobox-content", message); - byte[] responseBytes = pageNode.generate().getBytes("utf-8"); - context.sendReplyHeaders(200, "OK", new MultiValueTable(), "text/html; charset=utf-8", responseBytes.length); - context.writeData(responseBytes); - } - - private HTMLNode createBackBox() { - HTMLNode backBox = new HTMLNode("div", "class", "infobox"); - HTMLNode backBoxContent = backBox.addChild("div", "class", "infobox-content"); - backBoxContent.addChild("#", "Return to the "); - backBoxContent.addChild("a", "href", "?action=list", "list of all URIs"); - backBoxContent.addChild("#", "."); - return backBox; - } - - private HTMLNode createAddBox() { - HTMLNode addBox = new HTMLNode("div", "class", "infobox"); - addBox.addChild("div", "class", "infobox-header", "Add a URI"); - HTMLNode addForm = addBox.addChild("div", "class", "infobox-content").addChild("form", new String[] { "action", "method" }, new String[] { "", "get" }); - addForm.addChild("input", new String[] { "type", "name", "value" }, new String[] { "hidden", "action", "add" }); - addForm.addChild("input", new String[] { "type", "size", "name", "value" }, new String[] { "text", "40", "key", "" }); - addForm.addChild("input", new String[] { "type", "value" }, new String[] { "submit", "Add URI" }); - return addBox; - } - - private HTMLNode createNavbar(int running, int queued, int visited, int failed) { - HTMLNode infobox = new HTMLNode("div", "class", "infobox navbar"); - infobox.addChild("div", "class", "infobox-header", "Page navigation"); - HTMLNode links = infobox.addChild("div", "class", "infobox-content").addChild("ul"); - links.addChild("li").addChild("a", "href", "#running", "Running (" + running + ')'); - links.addChild("li").addChild("a", "href", "#queued", "Queued (" + queued + ')'); - links.addChild("li").addChild("a", "href", "#visited", "Visited (" + visited + ')'); - links.addChild("li").addChild("a", "href", "#failed", "Failed (" + failed + ')'); - return infobox; - } - - private HTMLNode[] createList(String listName, String anchorName, Collection collection, int maxCount) { - HTMLNode listBox = new HTMLNode("div", "class", "infobox"); - listBox.addChild("div", "class", "infobox-header", listName + " (" + collection.size() + ')'); - HTMLNode listContent = listBox.addChild("div", "class", "infobox-content"); - Iterator collectionItems = collection.iterator(); - int itemCount = 0; - while (collectionItems.hasNext()) { - FreenetURI uri = (FreenetURI) collectionItems.next(); - listContent.addChild("#", uri.toString()); - listContent.addChild("br"); - if (itemCount++ == maxCount) { - listContent.addChild("br"); - listContent.addChild("a", "href", "?action=list&listName=" + anchorName, "Show all\u2026"); - break; - } - } - return new HTMLNode[] { new HTMLNode("a", "name", anchorName), listBox }; - } - - /** - * @see freenet.oldplugins.plugin.Plugin#getPluginName() - */ - public String getPluginName() { - return pluginName; - } - - /** - * @see freenet.oldplugins.plugin.Plugin#setPluginManager(freenet.oldplugins.plugin.PluginManager) - */ - public void setPluginManager(PluginManager pluginManager) { - this.core = pluginManager.getClientCore(); - this.ctx = core.makeClient((short) 0).getFetchContext(); - ctx.maxSplitfileBlockRetries = 10; - ctx.maxNonSplitfileRetries = 10; - ctx.maxTempLength = 2 * 1024 * 1024; - ctx.maxOutputLength = 2 * 1024 * 1024; - tProducedIndex = System.currentTimeMillis(); - } - - - /** - * @see freenet.oldplugins.plugin.Plugin#startPlugin() - */ - public void startPlugin() { - FreenetURI[] initialURIs = core.getBookmarkURIs(); - for (int i = 0; i < initialURIs.length; i++) - queueURI(initialURIs[i]); - stopped = false; - Thread starterThread = new Thread("Spider Plugin Starter") { - public void run() { - startSomeRequests(); - } - }; - starterThread.setDaemon(true); - starterThread.start(); - } - - /** - * @see freenet.oldplugins.plugin.Plugin#stopPlugin() - */ - public void stopPlugin() { - synchronized (this) { - stopped = true; - queuedURIList.clear(); - } - } - - public void onMajorProgress() { - // Ignore - } - - public void onFetchable(BaseClientPutter state) { - // Ignore - } - - - -} Modified: branches/saltedhashstore/freenet/src/freenet/clients/http/PageMaker.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/clients/http/PageMaker.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/clients/http/PageMaker.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/clients/http/PluginToadlet.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/clients/http/PluginToadlet.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/clients/http/PluginToadlet.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/clients/http/QueueToadlet.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/clients/http/QueueToadlet.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/clients/http/QueueToadlet.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -54,7 +54,6 @@ import freenet.support.io.BucketTools; import freenet.support.io.Closer; import freenet.support.io.FileBucket; -import java.util.StringTokenizer; public class QueueToadlet extends Toadlet implements RequestCompletionCallback { @@ -319,7 +318,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); try { ClientPut clientPut = new ClientPut(fcp.getGlobalClient(), insertURI, identifier, Integer.MAX_VALUE, RequestStarter.BULK_SPLITFILE_PRIORITY_CLASS, ClientRequest.PERSIST_FOREVER, null, false, !compress, -1, ClientPutMessage.UPLOAD_FROM_DIRECT, null, file.getContentType(), copiedBucket, null, fnam, false); Modified: branches/saltedhashstore/freenet/src/freenet/clients/http/SimpleToadletServer.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/clients/http/SimpleToadletServer.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/clients/http/SimpleToadletServer.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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; } }); Deleted: branches/saltedhashstore/freenet/src/freenet/clients/http/Spider.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/clients/http/Spider.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/clients/http/Spider.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -1,472 +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.BufferedWriter; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.io.UnsupportedEncodingException; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import freenet.client.ClientMetadata; -import freenet.client.FetchException; -import freenet.client.FetchResult; -import freenet.client.FetchContext; -import freenet.client.InsertException; -import freenet.client.async.BaseClientPutter; -import freenet.client.async.ClientCallback; -import freenet.client.async.ClientGetter; -import freenet.clients.http.filter.ContentFilter; -import freenet.clients.http.filter.FoundURICallback; -import freenet.clients.http.filter.UnsafeContentTypeException; -import freenet.keys.FreenetURI; -import freenet.node.NodeClientCore; -import freenet.node.RequestStarter; -import freenet.oldplugins.plugin.HttpPlugin; -import freenet.oldplugins.plugin.PluginManager; -import freenet.support.HTMLNode; -import freenet.support.Logger; -import freenet.support.MultiValueTable; -import freenet.support.api.Bucket; -import freenet.support.api.HTTPRequest; -import freenet.support.io.NullBucketFactory; - -/** - * Spider. Produces an index. - */ -public class Spider implements HttpPlugin, ClientCallback, FoundURICallback { - - long tProducedIndex; - - // URIs visited, or fetching, or queued. Added once then forgotten about. - private final HashSet visitedURIs = new HashSet(); - private final HashSet urisWithWords = new HashSet(); - private final HashSet failedURIs = new HashSet(); - private final HashSet queuedURISet = new HashSet(); - private final LinkedList queuedURIList = new LinkedList(); - private final HashMap runningFetchesByURI = new HashMap(); - private final HashMap urisByWord = new HashMap(); - private final HashMap titlesOfURIs = new HashMap(); - - private static final int minTimeBetweenEachIndexRewriting = 10; - - // Can have many; this limit only exists to save memory. - private static final int maxParallelRequests = 20; - private int maxShownURIs = 50; - - private NodeClientCore core; - private FetchContext ctx; - private final short PRIORITY_CLASS = RequestStarter.PREFETCH_PRIORITY_CLASS; - private boolean stopped = true; - - private synchronized void queueURI(FreenetURI uri) { - if ((!visitedURIs.contains(uri)) && queuedURISet.add(uri)) { - queuedURIList.addLast(uri); - visitedURIs.add(uri); - } - } - - private void startSomeRequests() { - try{ - Thread.sleep(30 * 1000); // Let the node start up - } catch (InterruptedException e){} - - FreenetURI[] initialURIs = core.getBookmarkURIs(); - for (int i = 0; i < initialURIs.length; i++) - queueURI(initialURIs[i]); - - ArrayList toStart = null; - synchronized (this) { - if (stopped) { - return; - } - int running = runningFetchesByURI.size(); - int queued = queuedURIList.size(); - - if ((running >= maxParallelRequests) || (queued == 0)) - return; - - toStart = new ArrayList(Math.min(maxParallelRequests - running, queued)); - - for (int i = running; i < maxParallelRequests; i++) { - if (queuedURIList.isEmpty()) - break; - FreenetURI uri = (FreenetURI) queuedURIList.removeFirst(); - queuedURISet.remove(uri); - ClientGetter getter = makeGetter(uri); - toStart.add(getter); - } - for (int i = 0; i < toStart.size(); i++) { - ClientGetter g = (ClientGetter) toStart.get(i); - try { - runningFetchesByURI.put(g.getURI(), g); - g.start(); - } catch (FetchException e) { - onFailure(e, g); - } - } - } - } - - private ClientGetter makeGetter(FreenetURI uri) { - ClientGetter g = new ClientGetter(this, core.requestStarters.chkFetchScheduler, core.requestStarters.sskFetchScheduler, uri, ctx, PRIORITY_CLASS, this, null, null); - return g; - } - - public void onSuccess(FetchResult result, ClientGetter state) { - FreenetURI uri = state.getURI(); - synchronized (this) { - runningFetchesByURI.remove(uri); - } - startSomeRequests(); - ClientMetadata cm = result.getMetadata(); - Bucket data = result.asBucket(); - String mimeType = cm.getMIMEType(); - try { - ContentFilter.filter(data, new NullBucketFactory(), mimeType, uri.toURI("http://127.0.0.1:8888/"), this); - } catch (UnsafeContentTypeException e) { - return; // Ignore - } catch (IOException e) { - Logger.error(this, "Bucket error?: " + e, e); - } catch (URISyntaxException e) { - Logger.error(this, "Internal error: " + e, e); - } finally { - data.free(); - } - } - - public void onFailure(FetchException e, ClientGetter state) { - FreenetURI uri = state.getURI(); - synchronized (this) { - failedURIs.add(uri); - runningFetchesByURI.remove(uri); - } - if (e.newURI != null) - queueURI(e.newURI); - else - queueURI(uri); - startSomeRequests(); - } - - public void onSuccess(BaseClientPutter state) { - // Ignore - } - - public void onFailure(InsertException e, BaseClientPutter state) { - // Ignore - } - - public void onGeneratedURI(FreenetURI uri, BaseClientPutter state) { - // Ignore - } - - public void foundURI(FreenetURI uri) { - queueURI(uri); - startSomeRequests(); - } - - public void foundURI(FreenetURI uri, boolean inline) { - queueURI(uri); - startSomeRequests(); - } - - public void onText(String s, String type, URI baseURI) { - - FreenetURI uri; - try { - uri = new FreenetURI(baseURI.getPath()); - } catch (MalformedURLException e) { - Logger.error(this, "Caught " + e, e); - return; - } - - if((type != null) && (type.length() != 0) && type.toLowerCase().equals("title") - && (s != null) && (s.length() != 0) && (s.indexOf('\n') < 0)) { - /* We should have a correct title */ - titlesOfURIs.put(uri.toString(), s); - } - - - String[] words = s.split("[^A-Za-z0-9]"); - for (int i = 0; i < words.length; i++) { - String word = words[i]; - if ((word == null) || (word.length() == 0)) - continue; - word = word.toLowerCase(); - addWord(word, uri); - } - } - - private synchronized void addWord(String word, FreenetURI uri) { - FreenetURI[] uris = (FreenetURI[]) urisByWord.get(word); - urisWithWords.add(uri); - if (uris == null) { - urisByWord.put(word, new FreenetURI[] { uri }); - } else { - for (int i = 0; i < uris.length; i++) { - if (uris[i].equals(uri)) - return; - } - FreenetURI[] newURIs = new FreenetURI[uris.length + 1]; - System.arraycopy(uris, 0, newURIs, 0, uris.length); - newURIs[uris.length] = uri; - urisByWord.put(word, newURIs); - } - if (tProducedIndex + minTimeBetweenEachIndexRewriting * 1000 < System.currentTimeMillis()) { - try { - produceIndex(); - } catch (IOException e) { - Logger.error(this, "Caught " + e + " while creating index", e); - } - tProducedIndex = System.currentTimeMillis(); - } - } - - private synchronized void produceIndex() throws IOException { - // Produce an index file. - FileOutputStream fos = new FileOutputStream("index.new"); - OutputStreamWriter osw; - try { - osw = new OutputStreamWriter(fos, "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new Error("Impossible: JVM doesn't support UTF-8: " + e, e); - } - - if (urisByWord.isEmpty() || urisWithWords.isEmpty()) { - System.out.println("No URIs with words"); - return; - } - BufferedWriter bw = new BufferedWriter(osw); - String[] words = (String[]) urisByWord.keySet().toArray(new String[urisByWord.size()]); - Arrays.sort(words); - FreenetURI[] uris = (FreenetURI[]) urisWithWords.toArray(new FreenetURI[urisWithWords.size()]); - HashMap urisToNumbers = new HashMap(); - for (int i = 0; i < uris.length; i++) { - urisToNumbers.put(uris[i], new Integer(i)); - bw.write('!' + uris[i].toString() + '\n'); - bw.write("+" + titlesOfURIs.get(uris[i].toString()) + '\n'); - } - for (int i = 0; i < words.length; i++) { - StringBuffer s = new StringBuffer(); - s.append('?'); - s.append(words[i]); - FreenetURI[] urisForWord = (FreenetURI[]) urisByWord.get(words[i]); - for (int j = 0; j < urisForWord.length; j++) { - FreenetURI uri = urisForWord[j]; - Integer x = (Integer) urisToNumbers.get(uri); - if (x == null) - Logger.error(this, "Eh?"); - else { - s.append(' '); - s.append(x.toString()); - } - } - s.append('\n'); - bw.write(s.toString()); - } - bw.close(); - } - - /** - * @see freenet.oldplugins.plugin.HttpPlugin#handleGet(freenet.clients.http.HTTPRequestImpl, freenet.clients.http.ToadletContext) - */ - public void handleGet(HTTPRequest request, ToadletContext context) throws IOException, ToadletContextClosedException { - String action = request.getParam("action"); - PageMaker pageMaker = context.getPageMaker(); - if ((action == null) || (action.length() == 0)) { - MultiValueTable responseHeaders = new MultiValueTable(); - responseHeaders.put("Location", "?action=list"); - context.sendReplyHeaders(301, "Redirect", responseHeaders, "text/html; charset=utf-8", 0); - return; - } else if ("list".equals(action)) { - String listName = request.getParam("listName", null); - HTMLNode pageNode = pageMaker.getPageNode("The Definitive Spider", context); - HTMLNode contentNode = pageMaker.getContentNode(pageNode); - /* create copies for multi-threaded use */ - if (listName == null) { - Map runningFetches = new HashMap(runningFetchesByURI); - List queued = new ArrayList(queuedURIList); - Set visited = new HashSet(visitedURIs); - Set failed = new HashSet(failedURIs); - contentNode.addChild(createNavbar(pageMaker, runningFetches.size(), queued.size(), visited.size(), failed.size())); - contentNode.addChild(createAddBox(pageMaker, context)); - contentNode.addChild(createList(pageMaker, "Running Fetches", "running", runningFetches.keySet(), maxShownURIs)); - contentNode.addChild(createList(pageMaker, "Queued URIs", "queued", queued, maxShownURIs)); - contentNode.addChild(createList(pageMaker, "Visited URIs", "visited", visited, maxShownURIs)); - contentNode.addChild(createList(pageMaker, "Failed URIs", "failed", failed, maxShownURIs)); - } else { - contentNode.addChild(createBackBox(pageMaker)); - if ("failed".equals(listName)) { - Set failed = new HashSet(failedURIs); - contentNode.addChild(createList(pageMaker, "Failed URIs", "failed", failed, -1)); - } else if ("visited".equals(listName)) { - Set visited = new HashSet(visitedURIs); - contentNode.addChild(createList(pageMaker, "Visited URIs", "visited", visited, -1)); - } else if ("queued".equals(listName)) { - List queued = new ArrayList(queuedURIList); - contentNode.addChild(createList(pageMaker, "Queued URIs", "queued", queued, -1)); - } else if ("running".equals(listName)) { - Map runningFetches = new HashMap(runningFetchesByURI); - contentNode.addChild(createList(pageMaker, "Running Fetches", "running", runningFetches.keySet(), -1)); - } - } - MultiValueTable responseHeaders = new MultiValueTable(); - byte[] responseBytes = pageNode.generate().getBytes("utf-8"); - context.sendReplyHeaders(200, "OK", responseHeaders, "text/html; charset=utf-8", responseBytes.length); - context.writeData(responseBytes); - } else if ("add".equals(action)) { - String uriParam = request.getParam("key"); - try { - FreenetURI uri = new FreenetURI(uriParam); - synchronized (this) { - failedURIs.remove(uri); - visitedURIs.remove(uri); - } - queueURI(uri); - startSomeRequests(); - } catch (MalformedURLException mue1) { - sendSimpleResponse(context, "URL invalid", "The given URI is not valid."); - return; - } - MultiValueTable responseHeaders = new MultiValueTable(); - responseHeaders.put("Location", "?action=list"); - context.sendReplyHeaders(301, "Redirect", responseHeaders, "text/html; charset=utf-8", 0); - return; - } - } - - /** - * @see freenet.oldplugins.plugin.HttpPlugin#handlePost(freenet.clients.http.HTTPRequestImpl, freenet.clients.http.ToadletContext) - */ - public void handlePost(HTTPRequest request, ToadletContext context) throws IOException { - } - - private void sendSimpleResponse(ToadletContext context, String title, String message) throws ToadletContextClosedException, IOException { - PageMaker pageMaker = context.getPageMaker(); - HTMLNode pageNode = pageMaker.getPageNode(title, context); - HTMLNode contentNode = pageMaker.getContentNode(pageNode); - HTMLNode infobox = contentNode.addChild(pageMaker.getInfobox("infobox-alter", title)); - HTMLNode infoboxContent = pageMaker.getContentNode(infobox); - infoboxContent.addChild("#", message); - byte[] responseBytes = pageNode.generate().getBytes("utf-8"); - context.sendReplyHeaders(200, "OK", new MultiValueTable(), "text/html; charset=utf-8", responseBytes.length); - context.writeData(responseBytes); - } - - private HTMLNode createBackBox(PageMaker pageMaker) { - HTMLNode backbox = pageMaker.getInfobox((String) null); - HTMLNode backContent = pageMaker.getContentNode(backbox); - backContent.addChild("#", "Return to the "); - backContent.addChild("a", "href", "?action=list", "list of all URIs"); - backContent.addChild("#", "."); - return backbox; - } - - private HTMLNode createAddBox(PageMaker pageMaker, ToadletContext ctx) { - HTMLNode addBox = pageMaker.getInfobox("Add a URI"); - HTMLNode formNode = pageMaker.getContentNode(addBox).addChild("form", new String[] { "action", "method" }, new String[] { "", "get" }); - formNode.addChild("input", new String[] { "type", "name", "value" }, new String[] { "hidden", "action", "add" }); - formNode.addChild("input", new String[] { "type", "size", "name", "value" }, new String[] { "text", "40", "key", "" }); - formNode.addChild("input", new String[] { "type", "value" }, new String[] { "submit", "Add URI" }); - return addBox; - } - - private HTMLNode createNavbar(PageMaker pageMaker, int running, int queued, int visited, int failed) { - HTMLNode navbar = pageMaker.getInfobox("navbar", "Page Navigation"); - HTMLNode list = pageMaker.getContentNode(navbar).addChild("ul"); - list.addChild("li").addChild("a", "href", "#running", "Running (" + running + ')'); - list.addChild("li").addChild("a", "href", "#queued", "Queued (" + queued + ')'); - list.addChild("li").addChild("a", "href", "#visited", "Visited (" + visited + ')'); - list.addChild("li").addChild("a", "href", "#failed", "Failed (" + failed + ')'); - return navbar; - } - - private HTMLNode createList(PageMaker pageMaker, String listName, String anchorName, Collection collection, int maxCount) { - HTMLNode listNode = new HTMLNode("div"); - listNode.addChild("a", "name", anchorName); - HTMLNode listBox = pageMaker.getInfobox(listName); - HTMLNode listContent = pageMaker.getContentNode(listBox); - listNode.addChild(listBox); - Iterator collectionItems = collection.iterator(); - int itemCount = 0; - while (collectionItems.hasNext()) { - FreenetURI uri = (FreenetURI) collectionItems.next(); - listContent.addChild("#", uri.toString()); - listContent.addChild("br"); - if (itemCount++ == maxCount) { - listContent.addChild("br"); - listContent.addChild("a", "href", "?action=list&listName=" + anchorName, "Show all\u2026"); - break; - } - } - return listNode; - } - - /** - * @see freenet.oldplugins.plugin.Plugin#getPluginName() - */ - public String getPluginName() { - return "The Definitive Spider"; - } - - /** - * @see freenet.oldplugins.plugin.Plugin#setPluginManager(freenet.oldplugins.plugin.PluginManager) - */ - public void setPluginManager(PluginManager pluginManager) { - this.core = pluginManager.getClientCore(); - this.ctx = core.makeClient((short) 0).getFetchContext(); - ctx.maxSplitfileBlockRetries = 10; - ctx.maxNonSplitfileRetries = 10; - ctx.maxTempLength = 2 * 1024 * 1024; - ctx.maxOutputLength = 2 * 1024 * 1024; - tProducedIndex = System.currentTimeMillis(); - } - - - /** - * @see freenet.oldplugins.plugin.Plugin#startPlugin() - */ - public void startPlugin() { - stopped = false; - Thread starterThread = new Thread("Spider Plugin Starter") { - public void run() { - startSomeRequests(); - } - }; - starterThread.setDaemon(true); - starterThread.start(); - } - - /** - * @see freenet.oldplugins.plugin.Plugin#stopPlugin() - */ - public void stopPlugin() { - synchronized (this) { - stopped = true; - queuedURIList.clear(); - } - } - - public void onMajorProgress() { - // Ignore - } - - public void onFetchable(BaseClientPutter state) { - // Ignore - } - -} Modified: branches/saltedhashstore/freenet/src/freenet/clients/http/StatisticsToadlet.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/clients/http/StatisticsToadlet.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/clients/http/StatisticsToadlet.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -345,25 +345,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); } } @@ -1010,6 +1000,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())); } @@ -1155,8 +1146,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/saltedhashstore/freenet/src/freenet/clients/http/SymlinkerToadlet.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/clients/http/SymlinkerToadlet.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/clients/http/SymlinkerToadlet.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/clients/http/bookmark/BookmarkCategory.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/clients/http/bookmark/BookmarkCategory.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/clients/http/bookmark/BookmarkCategory.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/clients/http/staticfiles/themes/clean/theme.css =================================================================== --- branches/saltedhashstore/freenet/src/freenet/clients/http/staticfiles/themes/clean/theme.css 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/clients/http/staticfiles/themes/clean/theme.css 2008-08-15 08:20:48 UTC (rev 21886) @@ -378,6 +378,10 @@ text-align: center; } +tr.darknet_connections_warning { + background-color: #ffff00; +} + table.sentmessagetypes { display: inline; } Modified: branches/saltedhashstore/freenet/src/freenet/config/BooleanOption.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/config/BooleanOption.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/config/BooleanOption.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/config/Config.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/config/Config.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/config/Config.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/config/ConfigCallback.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/config/ConfigCallback.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/config/ConfigCallback.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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; + } } Added: branches/saltedhashstore/freenet/src/freenet/config/ConfigException.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/config/ConfigException.java (rev 0) +++ branches/saltedhashstore/freenet/src/freenet/config/ConfigException.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/config/IntOption.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/config/IntOption.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/config/IntOption.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/config/InvalidConfigValueException.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/config/InvalidConfigValueException.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/config/InvalidConfigValueException.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/config/LongOption.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/config/LongOption.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/config/LongOption.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/config/NodeNeedRestartException.java (from rev 21885, branches/saltedhashstore/freenet/src/freenet/config/InvalidConfigValueException.java) =================================================================== --- branches/saltedhashstore/freenet/src/freenet/config/NodeNeedRestartException.java (rev 0) +++ branches/saltedhashstore/freenet/src/freenet/config/NodeNeedRestartException.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/config/Option.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/config/Option.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/config/Option.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/config/PersistentConfig.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/config/PersistentConfig.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/config/PersistentConfig.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/config/ShortOption.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/config/ShortOption.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/config/ShortOption.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/config/StringArrOption.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/config/StringArrOption.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/config/StringArrOption.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/config/StringOption.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/config/StringOption.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/config/StringOption.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/config/SubConfig.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/config/SubConfig.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/config/SubConfig.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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); @@ -62,12 +62,12 @@ public void register(String optionName, int defaultValue, int sortOrder, boolean expert, boolean forceWrite, String shortDesc, String longDesc, IntCallback cb) { - 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) { - 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, @@ -171,12 +171,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 { @@ -185,6 +185,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); } } } @@ -195,53 +200,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: @@ -256,19 +263,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); } @@ -281,7 +290,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(); } @@ -294,7 +303,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(); } @@ -303,15 +312,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/saltedhashstore/freenet/src/freenet/config/WrapperConfig.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/config/WrapperConfig.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/config/WrapperConfig.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/crypt/DiffieHellman.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/crypt/DiffieHellman.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/crypt/DiffieHellman.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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(); } Modified: branches/saltedhashstore/freenet/src/freenet/crypt/SSL.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/crypt/SSL.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/crypt/SSL.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -15,7 +15,6 @@ */ package freenet.crypt; -import com.sleepycat.je.utilint.NotImplementedYetException; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; @@ -24,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 { @@ -65,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/saltedhashstore/freenet/src/freenet/crypt/Yarrow.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/crypt/Yarrow.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/crypt/Yarrow.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/io/AddressIdentifier.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/io/AddressIdentifier.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/io/AddressIdentifier.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/io/NetworkInterface.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/io/NetworkInterface.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/io/NetworkInterface.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -138,6 +138,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/saltedhashstore/freenet/src/freenet/io/comm/DMT.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/io/comm/DMT.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/io/comm/DMT.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/io/comm/FreenetInetAddress.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/io/comm/FreenetInetAddress.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/io/comm/FreenetInetAddress.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/io/comm/UdpSocketHandler.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/io/comm/UdpSocketHandler.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/io/comm/UdpSocketHandler.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -64,6 +64,7 @@ _sock.setReceiveBufferSize(65536); try { // Exit reasonably quickly + _sock.setReuseAddress(true); _sock.setSoTimeout(1000); } catch (SocketException e) { throw new RuntimeException(e); Modified: branches/saltedhashstore/freenet/src/freenet/l10n/freenet.l10n.de.properties =================================================================== --- branches/saltedhashstore/freenet/src/freenet/l10n/freenet.l10n.de.properties 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/l10n/freenet.l10n.de.properties 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/l10n/freenet.l10n.en.properties =================================================================== --- branches/saltedhashstore/freenet/src/freenet/l10n/freenet.l10n.en.properties 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/l10n/freenet.l10n.en.properties 2008-08-15 08:20:48 UTC (rev 21886) @@ -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. @@ -1052,6 +1062,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/saltedhashstore/freenet/src/freenet/l10n/freenet.l10n.fr.properties =================================================================== --- branches/saltedhashstore/freenet/src/freenet/l10n/freenet.l10n.fr.properties 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/l10n/freenet.l10n.fr.properties 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/l10n/freenet.l10n.zh-cn.properties =================================================================== --- branches/saltedhashstore/freenet/src/freenet/l10n/freenet.l10n.zh-cn.properties 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/l10n/freenet.l10n.zh-cn.properties 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/l10n/freenet.l10n.zh-tw.properties =================================================================== --- branches/saltedhashstore/freenet/src/freenet/l10n/freenet.l10n.zh-tw.properties 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/l10n/freenet.l10n.zh-tw.properties 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/node/ConfigurablePersister.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/ConfigurablePersister.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/ConfigurablePersister.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -22,7 +22,6 @@ public void set(String val) throws InvalidConfigValueException { setThrottles(val); } - }); String throttleFile = nodeConfig.getString(optionName); Modified: branches/saltedhashstore/freenet/src/freenet/node/FNPPacketMangler.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/FNPPacketMangler.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/FNPPacketMangler.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/node/FailureTableEntry.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/FailureTableEntry.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/FailureTableEntry.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/node/GlobalProbe.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/GlobalProbe.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/GlobalProbe.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -4,7 +4,7 @@ package freenet.node; import freenet.support.Logger; -import freenet.support.StringArray; +import java.util.Arrays; public class GlobalProbe implements Runnable { @@ -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); } Modified: branches/saltedhashstore/freenet/src/freenet/node/IPDetectorPluginManager.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/IPDetectorPluginManager.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/IPDetectorPluginManager.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/node/LoggingConfigHandler.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/LoggingConfigHandler.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/LoggingConfigHandler.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/node/Node.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/Node.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/Node.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -38,6 +38,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; @@ -133,7 +134,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) { @@ -171,31 +172,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", - "salt-hash", - "ram" - }; + return new String[] { "bdb-index", "salt-hash", "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()); @@ -462,7 +472,6 @@ // Things that's needed to keep track of public final PluginManager pluginManager; - public freenet.oldplugins.plugin.PluginManager pluginManager2; // Helpers public final InetAddress localhostAddress; @@ -756,6 +765,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")); @@ -811,11 +823,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; } @@ -825,11 +837,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; } @@ -853,63 +865,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; } }); @@ -917,22 +941,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; } @@ -940,11 +964,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; } @@ -988,11 +1012,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; @@ -1013,11 +1037,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; @@ -1042,11 +1066,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; } @@ -1077,7 +1101,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 { @@ -1142,10 +1168,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) @@ -1154,17 +1180,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; @@ -1189,10 +1219,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; @@ -1217,11 +1247,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; } @@ -1234,13 +1264,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; } @@ -1261,6 +1291,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()))) { @@ -1278,13 +1311,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; } @@ -1299,11 +1332,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; @@ -1356,6 +1389,9 @@ // FIXME throw new InvalidConfigValueException("Moving datastore on the fly not supported at present"); } + public boolean isReadOnly() { + return true; + } }); final String suffix = "-" + getDarknetPortNumber(); @@ -1571,11 +1607,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 { @@ -1707,14 +1743,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"); @@ -1726,8 +1761,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; @@ -2147,16 +2181,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); } } @@ -2491,9 +2523,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; } @@ -2502,23 +2533,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+ '!'); } } @@ -2701,7 +2731,7 @@ */ public boolean recentlyCompleted(long id) { synchronized (recentlyCompletedIDs) { - return recentlyCompletedIDs.contains(new Long(id)); + return recentlyCompletedIDs.contains(id); } } @@ -2710,7 +2740,7 @@ */ void completed(long id) { synchronized (recentlyCompletedIDs) { - recentlyCompletedIDs.push(new Long(id)); + recentlyCompletedIDs.push(id); while(recentlyCompletedIDs.size() > MAX_RECENTLY_COMPLETED_IDS) recentlyCompletedIDs.pop(); } @@ -3199,7 +3229,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/saltedhashstore/freenet/src/freenet/node/NodeClientCore.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/NodeClientCore.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/NodeClientCore.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -53,14 +53,12 @@ import freenet.support.SimpleFieldSet; import freenet.support.api.BooleanCallback; 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; @@ -83,13 +81,12 @@ private File[] uploadAllowedDirs; private boolean uploadAllowedEverywhere; final FilenameGenerator tempFilenameGenerator; - 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 PersistentTempBucketFactory persistentTempBucketFactory; - public final PersistentEncryptedTempBucketFactory persistentEncryptedTempBucketFactory; public final UserAlertManager alerts; final TextModeClientInterfaceServer tmci; TextModeClientInterface directTMCI; @@ -157,6 +154,9 @@ // FIXME throw new InvalidConfigValueException(l10n("movingTempDirOnTheFlyNotSupported")); } + public boolean isReadOnly() { + return true; + } }); tempDir = new File(nodeConfig.getString("tempDir")); @@ -173,6 +173,18 @@ } // 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() { @@ -186,17 +198,53 @@ // FIXME throw new InvalidConfigValueException("Moving persistent temp directory on the fly not supported at present"); } + public boolean isReadOnly() { + return true; + } }); try { - persistentTempBucketFactory = new PersistentTempBucketFactory(new File(nodeConfig.getString("persistentTempDir")), "freenet-temp-", random, node.fastWeakRandom); - persistentEncryptedTempBucketFactory = new PersistentEncryptedTempBucketFactory(persistentTempBucketFactory); + persistentTempBucketFactory = new PersistentTempBucketFactory(new File(nodeConfig.getString("persistentTempDir")), "freenet-temp-", random, node.fastWeakRandom, nodeConfig.getBoolean("encryptPersistentTempBuckets")); } 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); + nodeConfig.register("maxRAMBucketSize", "128KiB", 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")); + // Downloads directory nodeConfig.register("downloadsDir", "downloads", sortOrder++, true, true, "NodeClientCore.downloadDir", "NodeClientCore.downloadDirLong", new StringCallback() { @@ -267,7 +315,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, random, node.fastWeakRandom, tempFilenameGenerator); + 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 = new USKManager(this); @@ -280,11 +328,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; } @@ -296,11 +344,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/saltedhashstore/freenet/src/freenet/node/NodeCrypto.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/NodeCrypto.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/NodeCrypto.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -32,7 +32,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; @@ -366,13 +365,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/saltedhashstore/freenet/src/freenet/node/NodeCryptoConfig.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/NodeCryptoConfig.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/NodeCryptoConfig.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/node/NodeDispatcher.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/NodeDispatcher.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/NodeDispatcher.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/node/NodeIPDetector.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/NodeIPDetector.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/NodeIPDetector.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/node/NodeStarter.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/NodeStarter.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/NodeStarter.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/node/NodeStats.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/NodeStats.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/NodeStats.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/node/PeerManager.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/PeerManager.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/PeerManager.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/node/PeerNode.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/PeerNode.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/PeerNode.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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. */ @@ -1607,24 +1620,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 +2104,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 +2117,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 +2965,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 +2981,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 +3983,19 @@ return (short)(((int)uptime) & 0xFF); } - public long getNumberOfSelections() { - return numberOfSelections; + public SortedSet<Long> getNumberOfSelections() { + synchronized(numberOfSelectionsSync) { + return new TreeSet<Long>(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/saltedhashstore/freenet/src/freenet/node/PeerNodeStatus.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/PeerNodeStatus.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/PeerNodeStatus.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/node/SeedClientPeerNode.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/SeedClientPeerNode.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/SeedClientPeerNode.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/node/TestnetHandler.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/TestnetHandler.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/TestnetHandler.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/node/TextModeClientInterface.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/TextModeClientInterface.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/TextModeClientInterface.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/node/TextModeClientInterfaceServer.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/TextModeClientInterfaceServer.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/TextModeClientInterfaceServer.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/node/UptimeEstimator.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/UptimeEstimator.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/UptimeEstimator.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/node/fcp/ClientGet.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/fcp/ClientGet.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/fcp/ClientGet.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -105,9 +105,9 @@ tempFile = null; try { if(persistenceType == PERSIST_FOREVER) - ret = client.server.core.persistentTempBucketFactory.makeEncryptedBucket(); + ret = client.server.core.persistentTempBucketFactory.makeBucket(maxOutputLength); else - ret = fctx.bucketFactory.makeBucket(-1); + ret = fctx.bucketFactory.makeBucket(maxOutputLength); } catch (IOException e) { Logger.error(this, "Cannot create bucket for temp storage: "+e, e); onFailure(new FetchException(FetchException.BUCKET_ERROR, e), null); @@ -174,9 +174,9 @@ tempFile = null; try { if(persistenceType == PERSIST_FOREVER) - ret = client.server.core.persistentTempBucketFactory.makeEncryptedBucket(); + ret = client.server.core.persistentTempBucketFactory.makeBucket(fctx.maxOutputLength); else - ret = fctx.bucketFactory.makeBucket(-1); + ret = fctx.bucketFactory.makeBucket(fctx.maxOutputLength); } catch (IOException e) { Logger.error(this, "Cannot create bucket for temp storage: "+e, e); onFailure(new FetchException(FetchException.BUCKET_ERROR, e), null); @@ -269,9 +269,9 @@ try { // Create a new temp bucket if(persistenceType == PERSIST_FOREVER) - ret = client.server.core.persistentTempBucketFactory.makeEncryptedBucket(); + ret = client.server.core.persistentTempBucketFactory.makeBucket(fctx.maxOutputLength); else - ret = fctx.bucketFactory.makeBucket(-1); + ret = fctx.bucketFactory.makeBucket(fctx.maxOutputLength); } catch (IOException e1) { Logger.error(this, "Cannot create bucket for temp storage: "+e, e); onFailure(new FetchException(FetchException.BUCKET_ERROR, e), null); Modified: branches/saltedhashstore/freenet/src/freenet/node/fcp/ClientPutMessage.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/fcp/ClientPutMessage.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/fcp/ClientPutMessage.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -260,7 +260,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/saltedhashstore/freenet/src/freenet/node/fcp/ClientRequest.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/fcp/ClientRequest.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/fcp/ClientRequest.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -109,7 +109,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/saltedhashstore/freenet/src/freenet/node/fcp/ConfigData.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/fcp/ConfigData.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/fcp/ConfigData.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -38,49 +38,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/saltedhashstore/freenet/src/freenet/node/fcp/FCPServer.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/fcp/FCPServer.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/fcp/FCPServer.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -16,6 +16,7 @@ import java.io.OutputStreamWriter; import java.net.Socket; import java.util.Iterator; +import java.util.LinkedList; import java.util.Vector; import java.util.WeakHashMap; import java.util.zip.GZIPInputStream; @@ -49,7 +50,6 @@ import freenet.support.api.StringCallback; import freenet.support.io.Closer; import freenet.support.io.FileUtil; -import java.util.LinkedList; /** * FCP server process. @@ -193,7 +193,7 @@ ch.start(); } - static class FCPPortNumberCallback implements IntCallback { + static class FCPPortNumberCallback extends IntCallback { private final NodeClientCore node; @@ -201,18 +201,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; @@ -220,24 +224,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"); @@ -245,12 +253,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; @@ -277,7 +289,7 @@ } } - static class FCPAllowedHostsCallback implements StringCallback { + static class FCPAllowedHostsCallback extends StringCallback { private final NodeClientCore node; @@ -296,12 +308,10 @@ if (!val.equals(get())) { node.getFCPServer().networkInterface.setAllowedHosts(val); } - } - + } } - static class FCPAllowedHostsFullAccessCallback implements StringCallback { - + static class FCPAllowedHostsFullAccessCallback extends StringCallback { private final NodeClientCore node; public FCPAllowedHostsFullAccessCallback(NodeClientCore node) { @@ -320,22 +330,22 @@ } - static class PersistentDownloadsEnabledCallback implements BooleanCallback { + static class PersistentDownloadsEnabledCallback extends BooleanCallback { FCPServer server; - public boolean get() { + public Boolean get() { return server.persistentDownloadsEnabled(); } - public void set(boolean set) { + public void set(Boolean set) { if(server.persistentDownloadsEnabled() != set) server.setPersistentDownloadsEnabled(set); } } - static class PersistentDownloadsFileCallback implements StringCallback { + static class PersistentDownloadsFileCallback extends StringCallback { FCPServer server; @@ -350,15 +360,15 @@ } } - static class PersistentDownloadsIntervalCallback implements LongCallback { + static class PersistentDownloadsIntervalCallback extends LongCallback { FCPServer server; - public long get() { + public Long get() { return server.persistenceInterval; } - public void set(long value) { + public void set(Long value) { server.persistenceInterval = value; FCPServerPersister p = server.persister; if(p != null) { @@ -369,27 +379,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/saltedhashstore/freenet/src/freenet/node/fcp/PutSuccessfulMessage.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/fcp/PutSuccessfulMessage.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/fcp/PutSuccessfulMessage.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -26,7 +26,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); Added: branches/saltedhashstore/freenet/src/freenet/node/simulator/BootstrapPullTest.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/simulator/BootstrapPullTest.java (rev 0) +++ branches/saltedhashstore/freenet/src/freenet/node/simulator/BootstrapPullTest.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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); + } + } + + +} Added: branches/saltedhashstore/freenet/src/freenet/node/simulator/BootstrapPushPullTest.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/simulator/BootstrapPushPullTest.java (rev 0) +++ branches/saltedhashstore/freenet/src/freenet/node/simulator/BootstrapPushPullTest.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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); + } + } + +} Added: branches/saltedhashstore/freenet/src/freenet/node/simulator/BootstrapSeedTest.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/simulator/BootstrapSeedTest.java (rev 0) +++ branches/saltedhashstore/freenet/src/freenet/node/simulator/BootstrapSeedTest.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/node/simulator/RealNodeBusyNetworkTest.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/simulator/RealNodeBusyNetworkTest.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/simulator/RealNodeBusyNetworkTest.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -157,9 +157,9 @@ totalRunningRequests += nodes[i].clientCore.countQueuedRequests(); } System.err.println("Running requests: "+totalRunningRequests); - if(totalRunningRequests == 0) return; + if(totalRunningRequests == 0) break; Thread.sleep(1000); } - + System.exit(0); } } Modified: branches/saltedhashstore/freenet/src/freenet/node/simulator/RealNodeRequestInsertTest.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/simulator/RealNodeRequestInsertTest.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/simulator/RealNodeRequestInsertTest.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/node/simulator/SeednodePingTest.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/simulator/SeednodePingTest.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/simulator/SeednodePingTest.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/node/updater/NodeUpdateManager.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/updater/NodeUpdateManager.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/updater/NodeUpdateManager.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/node/useralerts/MeaningfulNodeNameUserAlert.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/node/useralerts/MeaningfulNodeNameUserAlert.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/node/useralerts/MeaningfulNodeNameUserAlert.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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(); + } } Deleted: branches/saltedhashstore/freenet/src/freenet/oldplugins/plugin/HttpPlugin.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/oldplugins/plugin/HttpPlugin.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/oldplugins/plugin/HttpPlugin.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -1,48 +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.oldplugins.plugin; - -import java.io.IOException; - -import freenet.clients.http.ToadletContext; -import freenet.clients.http.ToadletContextClosedException; -import freenet.support.api.HTTPRequest; - -/** - * Interface for plugins that support HTTP interaction. - * - * @author David 'Bombe' Roden <bombe at freenetproject.org> - * @version $Id$ - */ -public interface HttpPlugin extends Plugin { - - /** - * Handles the GET request. - * - * @param request - * The request used to interact with this plugin - * @param context - * The context of the HTTP request - * @throws IOException - * if an I/O error occurs - * @throws ToadletContextClosedException - * if the context has already been closed. - */ - public void handleGet(HTTPRequest request, ToadletContext context) throws IOException, ToadletContextClosedException; - - /** - * Handles the POST request. - * - * @param request - * The request used to interact with this plugin - * @param context - * The context of the HTTP request - * @throws IOException - * if an I/O error occurs - * @throws ToadletContextClosedException - * if the context has already been closed. - */ - public void handlePost(HTTPRequest request, ToadletContext context) throws IOException, ToadletContextClosedException; - -} Deleted: branches/saltedhashstore/freenet/src/freenet/oldplugins/plugin/Plugin.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/oldplugins/plugin/Plugin.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/oldplugins/plugin/Plugin.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -1,40 +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.oldplugins.plugin; - -/** - * Interface for Fred plugins. - * - * @author David 'Bombe' Roden <bombe at freenetproject.org> - * @version $Id$ - */ -public interface Plugin { - - /** - * Returns the name of the plugin. - * - * @return The name of the plugin - */ - public String getPluginName(); - - /** - * Sets the plugin manager that manages this plugin. - * - * @param pluginManager - * The plugin manager - */ - public void setPluginManager(PluginManager pluginManager); - - /** - * Starts the plugin. If the plugin needs threads they have to be started - * here. - */ - public void startPlugin(); - - /** - * Stops the plugin. - */ - public void stopPlugin(); - -} Deleted: branches/saltedhashstore/freenet/src/freenet/oldplugins/plugin/PluginManager.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/oldplugins/plugin/PluginManager.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/oldplugins/plugin/PluginManager.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -1,238 +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.oldplugins.plugin; - -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.List; - -import freenet.config.InvalidConfigValueException; -import freenet.config.SubConfig; -import freenet.l10n.L10n; -import freenet.node.Node; -import freenet.node.NodeClientCore; -import freenet.support.Logger; -import freenet.support.StringArray; -import freenet.support.api.StringArrCallback; - -/** - * Manages plugins. - * - * @author David 'Bombe' Roden <bombe at freenetproject.org> - * @version $Id$ - */ -public class PluginManager { - - /** Object used for synchronization. */ - private final Object syncObject = new Object(); - - /** The node. */ - private final Node node; - - /** The configuration of this plugin manager. */ - private final SubConfig config; - - /** Currently loaded plugins. */ - private List plugins = new ArrayList(); - - /** - * Creates a new plugin manager. - * - * @param node - * The node - */ - public PluginManager(Node node) { - this.node = node; - - config = new SubConfig("pluginmanager2", node.config); - config.register("loadedPlugins", new String[0], 9, true, true, "PluginManager.loadedPlugins", "PluginManager.loadedPluginsLong", new StringArrCallback() { - - /** - * Returns the current value of this option. - * - * @see freenet.support.api.StringArrCallback#get() - * @return The current value of this option - */ - public String[] get() { - if(plugins.size() == 0) return new String[0]; - String[] retval; - synchronized (syncObject) { - retval = new String[plugins.size()]; - for(int i=0;i<plugins.size();i++) { - Plugin plugin = (Plugin) plugins.get(i); - retval[i] = plugin.getClass().getName(); - } - } - if(Logger.shouldLog(Logger.MINOR, this)) - Logger.minor(this, "Plugin list: " + StringArray.toString(retval)); - return retval; - }; - - /** - * Sets the new value of this option. - * - * @see freenet.support.api.StringArrCallback#set(java.lang.String) - * @param val - * The new value - * @throws InvalidConfigValueException - * if setting the value is not allowed, or the new value - * is not valid - */ - public void set(String[] val) throws InvalidConfigValueException { - throw new InvalidConfigValueException(L10n.getString("PluginManager.cannotSetOnceLoaded")); - }; - }); - - String[] loadedPluginNames = config.getStringArr("loadedPlugins"); - if (loadedPluginNames != null && loadedPluginNames.length > 0) { - for (int pluginIndex = 0, pluginCount = loadedPluginNames.length; pluginIndex < pluginCount; pluginIndex++) { - String pluginName = loadedPluginNames[pluginIndex]; - try { - addPlugin(pluginName, false); - } catch (Throwable t) { - Logger.error(this, "Failed to load plugin "+pluginName+" : "+t, t); - } - } - } - - config.finishedInitialization(); - } - - /** - * Returns the node that created this plugin manager. - * - * @return The node that created this plugin manager - */ - public Node getNode() { - return node; - } - - /** - * Returns all currently loaded plugins. The array is returned in no - * particular order. - * - * @return All currently loaded plugins - */ - public Plugin[] getPlugins() { - synchronized (syncObject) { - return (Plugin[]) plugins.toArray(new Plugin[plugins.size()]); - } - } - - /** - * Adds a plugin to the plugin manager. The name can contain a URL for a jar - * file from which the plugin is then loaded. If it does the URL and the - * plugin name are separated by a '@', e.g. - * 'plugin.TestPlugin at http://www.example.com/test.jar'. URLs can contain - * every protocol your VM understands. - * - * @see URL - * @param pluginName - * The name of the plugin - * - * FIXME IllegalArgumentException is not the best way to convey an error here! - */ - public void addPlugin(String pluginName, final boolean store) throws IllegalArgumentException { - if(Logger.shouldLog(Logger.MINOR, this)) - Logger.minor(this, "Loading plugin "+pluginName+(store?"" : " (don't store afterwards)")); - final Plugin newPlugin = createPlugin(pluginName); - if (newPlugin == null) { - throw new IllegalArgumentException(); - } - newPlugin.setPluginManager(this); - synchronized (syncObject) { - plugins.add(newPlugin); - } - node.executor.execute(new Runnable() { - public void run() { - try{ - while(!node.isHasStarted()) - Thread.sleep(1000); - }catch (InterruptedException e) {} - newPlugin.startPlugin(); - if(store) - node.clientCore.storeConfig(); - } - }, "Plugin loader"); - - } - - /** - * Remoes the plugin from the list of running plugins. The plugin is stopped - * before removing it. - * - * @param plugin - * The plugin to remove - */ - public void removePlugin(Plugin plugin, boolean store) { - plugin.stopPlugin(); - synchronized (syncObject) { - plugins.remove(plugin); - } - if(store) - node.clientCore.storeConfig(); - } - - /** - * Creates a plugin from a name. The name can contain a URL for a jar file - * from which the plugin is then loaded. If it does the URL and the plugin - * name are separated by a '@', e.g. - * 'plugin.TestPlugin at http://www.example.com/test.jar'. URLs can contain - * every protocol your VM understands. - * <p> - * <b>WARNING:</b> The code to load JAR files from URLs has <b>not</b> - * been tested. - * - * @see URL - * @param pluginName - * The name of the plugin - * @return The created plugin, or <code>null</code> if the plugin could - * not be created - */ - private Plugin createPlugin(String pluginName) { - int p = pluginName.indexOf('@'); - String pluginSource = null; - - /* split up */ - if (p > -1) { - pluginSource = pluginName.substring(p + 1); - pluginName = pluginName.substring(0, p); - } - - /* load jar file */ - ClassLoader classLoader = getClass().getClassLoader(); - if (pluginSource != null) { - try { - URL pluginSourceUrl = new URL(pluginSource); - classLoader = new URLClassLoader(new URL[] { pluginSourceUrl }); - } catch (MalformedURLException mue1) { - Logger.normal(this, "could not create class loader", mue1); - return null; - } - } - - /* load class from class loader */ - try { - Class pluginClass = classLoader.loadClass(pluginName); - if (Plugin.class.isAssignableFrom(pluginClass)) { - Plugin plugin = (Plugin) pluginClass.newInstance(); - return plugin; - } - } catch (ClassNotFoundException e) { - Logger.normal(this, "could not find plugin class: " + pluginName+" : "+e, e); - } catch (InstantiationException e) { - Logger.normal(this, "could not instantiate plugin class: " + pluginName+" : "+e, e); - } catch (IllegalAccessException e) { - Logger.normal(this, "could not instantiate plugin class: " + pluginName+" : "+e, e); - } - return null; - } - - public NodeClientCore getClientCore() { - return node.clientCore; - } - -} Deleted: branches/saltedhashstore/freenet/src/freenet/oldplugins/plugin/TestHttpPlugin.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/oldplugins/plugin/TestHttpPlugin.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/oldplugins/plugin/TestHttpPlugin.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -1,62 +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.oldplugins.plugin; - -import java.io.IOException; - -import freenet.clients.http.ToadletContext; -import freenet.clients.http.ToadletContextClosedException; -import freenet.support.MultiValueTable; -import freenet.support.api.HTTPRequest; - -/** - * Test HTTP plugin. Outputs "Plugin works" to the browser. - * - * @author David 'Bombe' Roden <bombe at freenetproject.org> - * @version $Id$ - */ -public class TestHttpPlugin implements HttpPlugin { - - /** - * @throws ToadletContextClosedException - * @see freenet.oldplugins.plugin.HttpPlugin#handleGet(freenet.clients.http.HTTPRequestImpl) - */ - public void handleGet(HTTPRequest request, ToadletContext context) throws IOException, ToadletContextClosedException { - byte[] messageBytes = "Plugin works.".getBytes("UTF-8"); - context.sendReplyHeaders(200, "OK", new MultiValueTable(), "text/html; charset=utf-8", messageBytes.length); - context.writeData(messageBytes, 0, messageBytes.length); - } - - /** - * @see freenet.oldplugins.plugin.HttpPlugin#handlePost(freenet.clients.http.HTTPRequestImpl) - */ - public void handlePost(HTTPRequest request, ToadletContext context) throws IOException, ToadletContextClosedException { - } - - /** - * @see freenet.oldplugins.plugin.Plugin#getPluginName() - */ - public String getPluginName() { - return "Simple HTTP Test Plugin"; - } - - /** - * @see freenet.oldplugins.plugin.Plugin#setPluginManager(freenet.oldplugins.plugin.PluginManager) - */ - public void setPluginManager(PluginManager pluginManager) { - } - - /** - * @see freenet.oldplugins.plugin.Plugin#startPlugin() - */ - public void startPlugin() { - } - - /** - * @see freenet.oldplugins.plugin.Plugin#stopPlugin() - */ - public void stopPlugin() { - } - -} Deleted: branches/saltedhashstore/freenet/src/freenet/oldplugins/plugin/TestPlugin.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/oldplugins/plugin/TestPlugin.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/oldplugins/plugin/TestPlugin.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -1,39 +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.oldplugins.plugin; - -/** - * Test plugin. Does absolutely nothing. - * - * @author David 'Bombe' Roden <bombe at freenetproject.org> - * @version $Id$ - */ -public class TestPlugin implements Plugin { - - /** - * @see freenet.oldplugins.plugin.Plugin#getPluginName() - */ - public String getPluginName() { - return "Simple Test Plugin"; - } - - /** - * @see freenet.oldplugins.plugin.Plugin#setPluginManager(freenet.oldplugins.plugin.PluginManager) - */ - public void setPluginManager(PluginManager pluginManager) { - } - - /** - * @see freenet.oldplugins.plugin.Plugin#startPlugin() - */ - public void startPlugin() { - } - - /** - * @see freenet.oldplugins.plugin.Plugin#stopPlugin() - */ - public void stopPlugin() { - } - -} Added: branches/saltedhashstore/freenet/src/freenet/pluginmanager/FredPluginBandwidthIndicator.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/pluginmanager/FredPluginBandwidthIndicator.java (rev 0) +++ branches/saltedhashstore/freenet/src/freenet/pluginmanager/FredPluginBandwidthIndicator.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/pluginmanager/PluginDownLoaderOfficial.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/pluginmanager/PluginDownLoaderOfficial.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/pluginmanager/PluginDownLoaderOfficial.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/pluginmanager/PluginManager.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/pluginmanager/PluginManager.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/pluginmanager/PluginManager.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/support/Fields.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/support/Fields.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/support/Fields.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/support/PooledExecutor.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/support/PooledExecutor.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/support/PooledExecutor.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/support/SizeUtil.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/support/SizeUtil.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/support/SizeUtil.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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; - } } Deleted: branches/saltedhashstore/freenet/src/freenet/support/StringArray.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/support/StringArray.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/support/StringArray.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/support/TimeSortedHashtable.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/support/TimeSortedHashtable.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/support/TimeSortedHashtable.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/support/api/BooleanCallback.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/support/api/BooleanCallback.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/support/api/BooleanCallback.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/support/api/IntCallback.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/support/api/IntCallback.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/support/api/IntCallback.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/support/api/LongCallback.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/support/api/LongCallback.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/support/api/LongCallback.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/support/api/ShortCallback.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/support/api/ShortCallback.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/support/api/ShortCallback.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/support/api/StringArrCallback.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/support/api/StringArrCallback.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/support/api/StringArrCallback.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/support/api/StringCallback.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/support/api/StringCallback.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/support/api/StringCallback.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/support/compress/GzipCompressor.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/support/compress/GzipCompressor.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/support/compress/GzipCompressor.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -16,7 +16,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; @@ -53,7 +53,7 @@ if(preferred != null) output = preferred; else - output = bf.makeBucket(-1); + output = bf.makeBucket(maxLength); InputStream is = data.getInputStream(); OutputStream os = output.getOutputStream(); decompress(is, os, maxLength, maxCheckSizeLength); Modified: branches/saltedhashstore/freenet/src/freenet/support/io/ArrayBucket.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/support/io/ArrayBucket.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/support/io/ArrayBucket.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -13,15 +13,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"); @@ -33,20 +31,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(); @@ -55,7 +54,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]; @@ -65,13 +64,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() { @@ -79,15 +78,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? :) } } @@ -100,11 +114,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()); @@ -121,15 +135,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()); @@ -146,7 +162,8 @@ } } - public int available() { + @Override + public synchronized int available() { if (in == null) { if (i.hasNext()) { in = new ByteArrayInputStream((byte[]) i.next()); @@ -167,12 +184,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/saltedhashstore/freenet/src/freenet/support/io/BaseFileBucket.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/support/io/BaseFileBucket.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/support/io/BaseFileBucket.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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 { @@ -392,7 +392,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) { @@ -419,6 +419,7 @@ } } + @Override public synchronized String toString() { return super.toString()+ ':' +getFile().getPath()+":streams="+(streams == null ? 0 : streams.size()); } Modified: branches/saltedhashstore/freenet/src/freenet/support/io/BucketTools.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/support/io/BucketTools.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/support/io/BucketTools.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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,9 +420,11 @@ 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/saltedhashstore/freenet/src/freenet/support/io/DelayedFreeBucket.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/support/io/DelayedFreeBucket.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/support/io/DelayedFreeBucket.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -20,7 +20,7 @@ Bucket bucket; boolean freed; - public DelayedFreeBucket(PersistentTempBucketFactory factory, PaddedEphemerallyEncryptedBucket bucket) { + public DelayedFreeBucket(PersistentTempBucketFactory factory, Bucket bucket) { this.factory = factory; this.bucket = bucket; } Modified: branches/saltedhashstore/freenet/src/freenet/support/io/NativeThread.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/support/io/NativeThread.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/support/io/NativeThread.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucketFactory.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucketFactory.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucketFactory.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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/saltedhashstore/freenet/src/freenet/support/io/PersistentEncryptedTempBucketFactory.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/support/io/PersistentEncryptedTempBucketFactory.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/support/io/PersistentEncryptedTempBucketFactory.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -1,23 +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 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(); - } -} Modified: branches/saltedhashstore/freenet/src/freenet/support/io/PersistentTempBucketFactory.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/support/io/PersistentTempBucketFactory.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/support/io/PersistentTempBucketFactory.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -42,12 +42,15 @@ /** Buckets to free */ private LinkedList bucketsToFree; + + private volatile boolean encrypt; - public PersistentTempBucketFactory(File dir, final String prefix, RandomSource strongPRNG, Random weakPRNG) throws IOException { + public PersistentTempBucketFactory(File dir, final String prefix, RandomSource strongPRNG, Random weakPRNG, boolean encrypt) throws IOException { boolean logMINOR = Logger.shouldLog(Logger.MINOR, this); this.dir = dir; this.strongPRNG = strongPRNG; this.weakPRNG = weakPRNG; + this.encrypt = encrypt; this.fg = new FilenameGenerator(weakPRNG, false, dir, prefix); if(!dir.exists()) { dir.mkdir(); @@ -104,19 +107,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. @@ -150,5 +145,12 @@ public long getID(File file) { return fg.getID(file); } + + public boolean isEncrypting() { + return encrypt; + } + public void setEncryption(boolean encrypt) { + this.encrypt = encrypt; + } } Modified: branches/saltedhashstore/freenet/src/freenet/support/io/TempBucketFactory.java =================================================================== --- branches/saltedhashstore/freenet/src/freenet/support/io/TempBucketFactory.java 2008-08-15 08:18:12 UTC (rev 21885) +++ branches/saltedhashstore/freenet/src/freenet/support/io/TempBucketFactory.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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)); } - } Added: branches/saltedhashstore/freenet/test/freenet/crypt/YarrowTest.java =================================================================== --- branches/saltedhashstore/freenet/test/freenet/crypt/YarrowTest.java (rev 0) +++ branches/saltedhashstore/freenet/test/freenet/crypt/YarrowTest.java 2008-08-15 08:20:48 UTC (rev 21886) @@ -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); + } +}
