Author: toad
Date: 2008-04-14 16:00:44 +0000 (Mon, 14 Apr 2008)
New Revision: 19326
Added:
trunk/freenet/src/freenet/node/fcp/RequestCompletionCallback.java
trunk/freenet/src/freenet/pluginmanager/FredPluginVersioned.java
trunk/freenet/src/freenet/support/OOMHook.java
trunk/freenet/test/freenet/support/BufferTest.java
trunk/freenet/test/net/i2p/util/NativeBigIntegerTest.java
Removed:
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/bluebuttonbg.gif
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/bluebuttonbg_larger1.gif
Modified:
trunk/freenet/build.xml
trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
trunk/freenet/src/freenet/clients/http/BookmarkEditorToadlet.java
trunk/freenet/src/freenet/clients/http/PproxyToadlet.java
trunk/freenet/src/freenet/clients/http/QueueToadlet.java
trunk/freenet/src/freenet/clients/http/StaticToadlet.java
trunk/freenet/src/freenet/clients/http/StatisticsToadlet.java
trunk/freenet/src/freenet/clients/http/ToadletContext.java
trunk/freenet/src/freenet/clients/http/ToadletContextImpl.java
trunk/freenet/src/freenet/clients/http/bookmark/BookmarkManager.java
trunk/freenet/src/freenet/clients/http/filter/HTMLFilter.java
trunk/freenet/src/freenet/clients/http/staticfiles/defaultbookmarks.dat
trunk/freenet/src/freenet/clients/http/staticfiles/themes/boxed/theme.css
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/theme.css
trunk/freenet/src/freenet/clients/http/staticfiles/themes/sky/theme.css
trunk/freenet/src/freenet/config/Option.java
trunk/freenet/src/freenet/crypt/RandomSource.java
trunk/freenet/src/freenet/io/AddressTracker.java
trunk/freenet/src/freenet/io/comm/FreenetInetAddress.java
trunk/freenet/src/freenet/keys/BaseClientKey.java
trunk/freenet/src/freenet/keys/ClientCHKBlock.java
trunk/freenet/src/freenet/keys/FreenetURI.java
trunk/freenet/src/freenet/keys/NodeCHK.java
trunk/freenet/src/freenet/keys/NodeSSK.java
trunk/freenet/src/freenet/l10n/freenet.l10n.de.properties
trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties
trunk/freenet/src/freenet/l10n/freenet.l10n.fr.properties
trunk/freenet/src/freenet/node/DarknetPeerNode.java
trunk/freenet/src/freenet/node/FNPPacketMangler.java
trunk/freenet/src/freenet/node/FailureTable.java
trunk/freenet/src/freenet/node/IPDetectorPluginManager.java
trunk/freenet/src/freenet/node/LocationManager.java
trunk/freenet/src/freenet/node/MemoryChecker.java
trunk/freenet/src/freenet/node/Node.java
trunk/freenet/src/freenet/node/NodeCrypto.java
trunk/freenet/src/freenet/node/NodeIPPortDetector.java
trunk/freenet/src/freenet/node/OpennetManager.java
trunk/freenet/src/freenet/node/PacketSender.java
trunk/freenet/src/freenet/node/PeerManager.java
trunk/freenet/src/freenet/node/PeerNode.java
trunk/freenet/src/freenet/node/UptimeEstimator.java
trunk/freenet/src/freenet/node/fcp/ClientGet.java
trunk/freenet/src/freenet/node/fcp/ClientPutBase.java
trunk/freenet/src/freenet/node/fcp/ClientPutComplexDirMessage.java
trunk/freenet/src/freenet/node/fcp/FCPClient.java
trunk/freenet/src/freenet/node/fcp/FCPServer.java
trunk/freenet/src/freenet/node/fcp/PersistentPutDir.java
trunk/freenet/src/freenet/node/updater/NodeUpdater.java
trunk/freenet/src/freenet/node/useralerts/OpennetUserAlert.java
trunk/freenet/src/freenet/node/useralerts/UserAlertManager.java
trunk/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java
trunk/freenet/src/freenet/pluginmanager/PluginManager.java
trunk/freenet/src/freenet/store/BerkeleyDBFreenetStore.java
trunk/freenet/src/freenet/store/CHKStore.java
trunk/freenet/src/freenet/store/FreenetStore.java
trunk/freenet/src/freenet/store/PubkeyStore.java
trunk/freenet/src/freenet/store/RAMFreenetStore.java
trunk/freenet/src/freenet/store/SSKStore.java
trunk/freenet/src/freenet/store/StoreCallback.java
trunk/freenet/src/freenet/support/Base64.java
trunk/freenet/src/freenet/support/Buffer.java
trunk/freenet/src/freenet/support/Logger.java
trunk/freenet/src/freenet/support/LoggerHookChain.java
trunk/freenet/src/freenet/support/NumberedItem.java
trunk/freenet/src/freenet/support/NumberedItemComparator.java
trunk/freenet/src/freenet/support/OOMHandler.java
trunk/freenet/src/freenet/support/SectoredRandomGrabArray.java
trunk/freenet/src/freenet/support/SizeUtil.java
trunk/freenet/src/freenet/support/SortedLongSet.java
trunk/freenet/src/freenet/support/WeakHashSet.java
trunk/freenet/src/freenet/support/io/BaseFileBucket.java
trunk/freenet/src/freenet/support/io/FileBucket.java
trunk/freenet/src/freenet/support/io/MultiReaderBucket.java
trunk/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucket.java
trunk/freenet/src/freenet/support/math/SimpleBinaryRunningAverage.java
trunk/freenet/src/freenet/support/math/TrivialRunningAverage.java
trunk/freenet/src/freenet/tools/AddRef.java
trunk/freenet/src/net/i2p/util/NativeBigInteger.java
trunk/freenet/test/freenet/support/SortedLongSetTest.java
trunk/freenet/test/freenet/support/compress/GzipCompressorTest.java
Log:
Revert the revert: go back to r19322, except for Version.java which we keep.
Modified: trunk/freenet/build.xml
===================================================================
--- trunk/freenet/build.xml 2008-04-14 15:55:20 UTC (rev 19325)
+++ trunk/freenet/build.xml 2008-04-14 16:00:44 UTC (rev 19326)
@@ -155,6 +155,8 @@
<include name="**/*.class"/>
</fileset>
</batchtest>
+ <sysproperty key="benchmark" value="${benchmark}" />
+ <sysproperty key="extensiveTesting"
value="${extensiveTesting}" />
</junit>
</target>
Modified: trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
===================================================================
--- trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
2008-04-14 15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/client/async/ClientRequestScheduler.java
2008-04-14 16:00:44 UTC (rev 19326)
@@ -531,10 +531,11 @@
}
} else {
SendableGet[] gets = (SendableGet[]) o;
- SendableGet[] newGets = new
SendableGet[gets.length-1];
+ final int getsLength = gets.length;
+ SendableGet[] newGets = new
SendableGet[getsLength > 1 ? getsLength-1 : 0];
boolean found = false;
int x = 0;
- for(int j=0;j<gets.length;j++) {
+ for(int j=0;j<getsLength;j++) {
if(gets[j] == getter) {
found = true;
continue;
@@ -542,7 +543,7 @@
if(j == newGets.length) {
if(!found) {
if(complain)
-
Logger.normal(this, "Not found: "+getter+" for "+key+" removing
("+gets.length+" getters)");
+
Logger.normal(this, "Not found: "+getter+" for "+key+" removing ("+getsLength+"
getters)");
return; // not here
}
}
@@ -555,7 +556,7 @@
} else if(x == 1) {
pendingKeys.put(key, newGets[0]);
} else {
- if(x != gets.length-1) {
+ if(x != getsLength-1) {
SendableGet[] newNewGets = new
SendableGet[x];
System.arraycopy(newGets, 0,
newNewGets, 0, x);
newGets = newNewGets;
Modified: trunk/freenet/src/freenet/clients/http/BookmarkEditorToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/BookmarkEditorToadlet.java
2008-04-14 15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/clients/http/BookmarkEditorToadlet.java
2008-04-14 16:00:44 UTC (rev 19326)
@@ -16,6 +16,7 @@
import freenet.node.NodeClientCore;
import freenet.client.HighLevelSimpleClient;
import freenet.support.HTMLNode;
+import freenet.support.Logger;
import freenet.support.URLDecoder;
import freenet.support.URLEncodedFormatException;
import freenet.support.URLEncoder;
@@ -238,8 +239,9 @@
HTMLNode infoBox =
content.addChild(pageMaker.getInfobox("infobox-normal",
L10n.getString("BookmarkEditorToadlet.pasteTitle")));
HTMLNode infoBoxContent =
pageMaker.getContentNode(infoBox);
infoBoxContent.addChild("#",
L10n.getString("BookmarkEditorToadlet.pasteOrCancel"));
- HTMLNode cancelForm = ctx.addFormChild(infoBoxContent,
"", "cancelCutForm");
+ HTMLNode cancelForm = ctx.addFormChild(infoBoxContent,
"/bookmarkEditor/", "cancelCutForm");
cancelForm.addChild("input", new String[]{"type",
"name", "value"}, new String[]{"submit", "cancelCut",
L10n.getString("BookmarkEditorToadlet.cancelCut")});
+ cancelForm.addChild("input", new String[]{"type",
"name", "value"}, new String[]{"hidden", "action", "cancelCut"});
}
HTMLNode bookmarksBox =
content.addChild(pageMaker.getInfobox("infobox-normal",
L10n.getString("BookmarkEditorToadlet.myBookmarksTitle")));
@@ -248,6 +250,9 @@
HTMLNode addDefaultBookmarksForm = ctx.addFormChild(content,
"", "AddDefaultBookmarks");
addDefaultBookmarksForm.addChild("input", new String[]{"type",
"name", "value"}, new String[]{"submit", "AddDefaultBookmarks",
L10n.getString("BookmarkEditorToadlet.addDefaultBookmarks")});
+ if(Logger.shouldLog(Logger.DEBUG, this))
+ Logger.debug(this, "Returning:\n"+pageNode.generate());
+
this.writeHTMLReply(ctx, 200, "OK", pageNode.generate());
}
@@ -278,7 +283,7 @@
bookmark =
bookmarkManager.getCategoryByPath(bookmarkPath);
else
bookmark =
bookmarkManager.getItemByPath(bookmarkPath);
- if(bookmark == null) {
+ if(bookmark == null && !req.isPartSet("cancelCut")) {
HTMLNode errorBox =
content.addChild(pageMaker.getInfobox("infobox-error",
L10n.getString("BookmarkEditorToadlet.error")));
pageMaker.getContentNode(errorBox).addChild("#",
L10n.getString("BookmarkEditorToadlet.bookmarkDoesNotExist", new
String[]{"bookmark"}, new String[]{bookmarkPath}));
this.writeHTMLReply(ctx, 200, "OK",
pageNode.generate());
Modified: trunk/freenet/src/freenet/clients/http/PproxyToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/PproxyToadlet.java 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/clients/http/PproxyToadlet.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -422,6 +422,7 @@
HTMLNode pluginTable = infoboxContent.addChild("table",
"class", "plugins");
HTMLNode headerRow = pluginTable.addChild("tr");
headerRow.addChild("th", l10n("classNameTitle"));
+ headerRow.addChild("th", l10n("versionTitle"));
headerRow.addChild("th", l10n("internalIDTitle"));
headerRow.addChild("th", l10n("startedAtTitle"));
headerRow.addChild("th");
@@ -432,6 +433,7 @@
PluginInfoWrapper pi = (PluginInfoWrapper)
it.next();
HTMLNode pluginRow = pluginTable.addChild("tr");
pluginRow.addChild("td",
pi.getPluginClassName());
+ pluginRow.addChild("td", pi.getPluginVersion());
pluginRow.addChild("td", pi.getThreadName());
pluginRow.addChild("td", new
Date(pi.getStarted()).toString());
if (pi.isStopping()) {
Modified: trunk/freenet/src/freenet/clients/http/QueueToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/QueueToadlet.java 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/clients/http/QueueToadlet.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -3,14 +3,24 @@
* http://www.gnu.org/ for further details of the GPL. */
package freenet.clients.http;
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.EOFException;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.text.NumberFormat;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -30,6 +40,9 @@
import freenet.node.fcp.IdentifierCollisionException;
import freenet.node.fcp.MessageInvalidException;
import freenet.node.fcp.NotAllowedException;
+import freenet.node.fcp.RequestCompletionCallback;
+import freenet.node.useralerts.SimpleHTMLUserAlert;
+import freenet.node.useralerts.UserAlert;
import freenet.support.HTMLNode;
import freenet.support.Logger;
import freenet.support.MultiValueTable;
@@ -38,9 +51,10 @@
import freenet.support.api.HTTPRequest;
import freenet.support.api.HTTPUploadedFile;
import freenet.support.io.BucketTools;
+import freenet.support.io.Closer;
import freenet.support.io.FileBucket;
-public class QueueToadlet extends Toadlet {
+public class QueueToadlet extends Toadlet implements RequestCompletionCallback
{
private static final int LIST_IDENTIFIER = 1;
private static final int LIST_SIZE = 2;
@@ -70,6 +84,8 @@
this.core = core;
this.fcp = fcp;
if(fcp == null) throw new NullPointerException();
+ fcp.setCompletionCallback(this);
+ loadCompletedIdentifiers();
}
public void handlePost(URI uri, HTTPRequest request, ToadletContext
ctx) throws ToadletContextClosedException, IOException, RedirectException {
@@ -1051,4 +1067,191 @@
return "GET, POST";
}
+ /**
+ * List of completed request identifiers which the user hasn't
acknowledged yet.
+ */
+ private final HashSet completedRequestIdentifiers = new HashSet();
+
+ public void notifyFailure(ClientRequest req) {
+ // FIXME do something???
+ }
+
+ public void notifySuccess(ClientRequest req) {
+ synchronized(completedRequestIdentifiers) {
+ completedRequestIdentifiers.add(req.getIdentifier());
+ }
+ registerAlert(req);
+ saveCompletedIdentifiersOffThread();
+ }
+
+ private void saveCompletedIdentifiersOffThread() {
+ core.getExecutor().execute(new Runnable() {
+ public void run() {
+ saveCompletedIdentifiers();
+ }
+ }, "Save completed identifiers");
+ }
+
+ private void loadCompletedIdentifiers() {
+ File completedIdentifiersList = new
File(core.node.getNodeDir(), "completed.list");
+ File completedIdentifiersListNew = new
File(core.node.getNodeDir(), "completed.list.bak");
+ if(!readCompletedIdentifiers(completedIdentifiersList)) {
+ readCompletedIdentifiers(completedIdentifiersListNew);
+ }
+ String[] identifiers;
+ synchronized(completedRequestIdentifiers) {
+ identifiers = (String[])
completedRequestIdentifiers.toArray(new
String[completedRequestIdentifiers.size()]);
+ }
+ for(int i=0;i<identifiers.length;i++) {
+ ClientRequest req =
fcp.getGlobalClient().getRequest(identifiers[i]);
+ if(req == null) continue;
+ registerAlert(req);
+ }
+ }
+
+ private boolean readCompletedIdentifiers(File file) {
+ FileInputStream fis = null;
+ try {
+ fis = new FileInputStream(file);
+ BufferedInputStream bis = new BufferedInputStream(fis);
+ InputStreamReader isr = new InputStreamReader(bis,
"UTF-8");
+ BufferedReader br = new BufferedReader(isr);
+ synchronized(completedRequestIdentifiers) {
+ completedRequestIdentifiers.clear();
+ while(true) {
+ String identifier = br.readLine();
+ if(identifier == null) return true;
+
completedRequestIdentifiers.add(identifier);
+ }
+ }
+ } catch (EOFException e) {
+ // Normal
+ return true;
+ } catch (FileNotFoundException e) {
+ // Normal
+ return false;
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e) {
+ Logger.error(this, "Could not read completed
identifiers list from "+file);
+ return false;
+ } finally {
+ Closer.close(fis);
+ }
+ }
+
+ private void saveCompletedIdentifiers() {
+ FileOutputStream fos = null;
+ BufferedWriter bw = null;
+ File completedIdentifiersList = new
File(core.node.getNodeDir(), "completed.list");
+ File completedIdentifiersListNew = new
File(core.node.getNodeDir(), "completed.list.bak");
+ File temp;
+ try {
+ temp = File.createTempFile("completed.list", ".tmp",
core.node.getNodeDir());
+ temp.deleteOnExit();
+ fos = new FileOutputStream(temp);
+ OutputStreamWriter osw = new OutputStreamWriter(fos,
"UTF-8");
+ bw = new BufferedWriter(osw);
+ String[] identifiers;
+ synchronized(completedRequestIdentifiers) {
+ identifiers = (String[])
completedRequestIdentifiers.toArray(new
String[completedRequestIdentifiers.size()]);
+ }
+ for(int i=0;i<identifiers.length;i++)
+ bw.write(identifiers[i]+'\n');
+ } catch (FileNotFoundException e) {
+ Logger.error(this, "Unable to save completed requests
list (can't find node directory?!!?): "+e, e);
+ return;
+ } catch (IOException e) {
+ Logger.error(this, "Unable to save completed requests
list: "+e, e);
+ return;
+ } finally {
+ if(bw != null) {
+ try {
+ bw.close();
+ } catch (IOException e) {
+ try {
+ fos.close();
+ } catch (IOException e1) {
+ // Ignore
+ }
+ }
+ } else {
+ try {
+ fos.close();
+ } catch (IOException e1) {
+ // Ignore
+ }
+ }
+ }
+ completedIdentifiersListNew.delete();
+ temp.renameTo(completedIdentifiersListNew);
+
if(!completedIdentifiersListNew.renameTo(completedIdentifiersList)) {
+ completedIdentifiersList.delete();
+
if(!completedIdentifiersListNew.renameTo(completedIdentifiersList)) {
+ Logger.error(this, "Unable to store completed
identifiers list because unable to rename "+completedIdentifiersListNew+" to
"+completedIdentifiersList);
+ }
+ }
+ }
+
+ private void registerAlert(ClientRequest req) {
+ final String identifier = req.getIdentifier();
+ if(req instanceof ClientGet) {
+ FreenetURI uri = ((ClientGet)req).getURI();
+ long size = ((ClientGet)req).getDataSize();
+ String name = uri.getPreferredFilename();
+ String title = l10n("downloadSucceededTitle",
"filename", name);
+ HTMLNode text = new HTMLNode("div");
+ L10n.addL10nSubstitution(text,
"QueueToadlet.downloadSucceeded",
+ new String[] { "link", "/link",
"origlink", "/origlink", "filename", "size" },
+ new String[] { "<a
href=\"/queue/"+uri.toACIIString()+"\">", "</a>", "<a
href=\"/"+uri.toACIIString()+"\">", "</a>", name, SizeUtil.formatSize(size) } );
+ core.alerts.register(new SimpleHTMLUserAlert(true,
title, text, UserAlert.MINOR) {
+ public void onDismiss() {
+
synchronized(completedRequestIdentifiers) {
+
completedRequestIdentifiers.remove(identifier);
+ }
+ saveCompletedIdentifiersOffThread();
+ }
+ });
+ } else if(req instanceof ClientPut) {
+ FreenetURI uri = ((ClientPut)req).getFinalURI();
+ long size = ((ClientPut)req).getDataSize();
+ String name = uri.getPreferredFilename();
+ String title = l10n("uploadSucceededTitle", "filename",
name);
+ HTMLNode text = new HTMLNode("div");
+ L10n.addL10nSubstitution(text,
"QueueToadlet.uploadSucceeded",
+ new String[] { "link", "/link",
"filename", "size" },
+ new String[] { "<a
href=\"/"+uri.toACIIString()+"\">", "</a>", name, SizeUtil.formatSize(size) } );
+ core.alerts.register(new SimpleHTMLUserAlert(true,
title, text, UserAlert.MINOR) {
+ public void onDismiss() {
+
synchronized(completedRequestIdentifiers) {
+
completedRequestIdentifiers.remove(identifier);
+ }
+ saveCompletedIdentifiersOffThread();
+ }
+ });
+ } else if(req instanceof ClientPutDir) {
+ FreenetURI uri = ((ClientPutDir)req).getFinalURI();
+ long size = ((ClientPutDir)req).getTotalDataSize();
+ int files = ((ClientPutDir)req).getNumberOfFiles();
+ String name = uri.getPreferredFilename();
+ String title =
l10n("QueueToadlet.siteUploadSucceededTitle", "filename", name);
+ HTMLNode text = new HTMLNode("div");
+ L10n.addL10nSubstitution(text,
"QueueToadlet.siteUploadSucceeded",
+ new String[] { "link", "/link",
"filename", "size", "files" },
+ new String[] { "<a
href=\"/"+uri.toACIIString()+"\">", "</a>", name, SizeUtil.formatSize(size),
Integer.toString(files) } );
+ core.alerts.register(new SimpleHTMLUserAlert(true,
title, text, UserAlert.MINOR) {
+ public void onDismiss() {
+
synchronized(completedRequestIdentifiers) {
+
completedRequestIdentifiers.remove(identifier);
+ }
+ saveCompletedIdentifiersOffThread();
+ }
+ });
+ }
+ }
+
+ String l10n(String key, String pattern, String value) {
+ return L10n.getString("QueueToadlet."+key, pattern, value);
+ }
+
}
Modified: trunk/freenet/src/freenet/clients/http/StaticToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/StaticToadlet.java 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/clients/http/StaticToadlet.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -1,9 +1,12 @@
package freenet.clients.http;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
+import java.net.URL;
+import java.util.Date;
import freenet.client.DefaultMIMETypes;
import freenet.l10n.L10n;
@@ -58,12 +61,32 @@
strm.close();
os.close();
- ctx.sendReplyHeaders(200, "OK", null,
DefaultMIMETypes.guessMIMEType(path, false), data.size());
+ URL url = getClass().getResource(ROOT_PATH+path);
+ Date mTime = getUrlMTime(url);
+
+ ctx.sendReplyHeaders(200, "OK", null,
DefaultMIMETypes.guessMIMEType(path, false), data.size(), mTime);
ctx.writeData(data);
data.free();
}
+ /**
+ * Try to find the modification time for a URL, or return null if not
possible
+ * We usually load our resources from the JAR, or possibly from a file
in some setups, so we check the modification time of
+ * the JAR for resources in a jar and the mtime for files.
+ */
+ private Date getUrlMTime(URL url) {
+ if (url.getProtocol().equals("jar")) {
+ File f = new File(url.getPath().substring(0,
url.getPath().indexOf('!')));
+ return new Date(f.lastModified());
+ } else if (url.getProtocol().equals("file")) {
+ File f = new File(url.getPath());
+ return new Date(f.lastModified());
+ } else {
+ return null;
+ }
+ }
+
private String l10n(String key) {
return L10n.getString("StaticToadlet."+key);
}
Modified: trunk/freenet/src/freenet/clients/http/StatisticsToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/StatisticsToadlet.java
2008-04-14 15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/clients/http/StatisticsToadlet.java
2008-04-14 16:00:44 UTC (rev 19326)
@@ -481,8 +481,14 @@
row=storeSizeTable.addChild("tr");
row.addChild("td", "Success Rate");
- row.addChild("td",
fix1p4.format(100.0*storeHits/storeAccesses)+"%");
- row.addChild("td",
fix1p4.format(100.0*cacheHits/cacheAccesses)+"%");
+ if (storeAccesses > 0)
+ row.addChild("td", fix1p4.format(100.0 * storeHits /
storeAccesses) + "%");
+ else
+ row.addChild("td", "N/A");
+ if (cacheAccesses > 0)
+ row.addChild("td", fix1p4.format(100.0 * cacheHits /
cacheAccesses) + "%");
+ else
+ row.addChild("td", "N/A");
row=storeSizeTable.addChild("tr");
row.addChild("td", "Writes");
Modified: trunk/freenet/src/freenet/clients/http/ToadletContext.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/ToadletContext.java 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/clients/http/ToadletContext.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -1,6 +1,7 @@
package freenet.clients.http;
import java.io.IOException;
+import java.util.Date;
import freenet.support.HTMLNode;
import freenet.support.MultiValueTable;
@@ -20,7 +21,10 @@
* @param mvt Any extra headers.
* @param mimeType The MIME type of the reply.
* @param length The length of the reply.
+ * @param mTime The modification time of the data being sent or null
for 'now' and disabling caching
*/
+ void sendReplyHeaders(int code, String desc, MultiValueTable mvt,
String mimeType, long length, Date mTime) throws ToadletContextClosedException,
IOException;
+
void sendReplyHeaders(int code, String desc, MultiValueTable mvt,
String mimeType, long length) throws ToadletContextClosedException, IOException;
/**
Modified: trunk/freenet/src/freenet/clients/http/ToadletContextImpl.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/ToadletContextImpl.java
2008-04-14 15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/clients/http/ToadletContextImpl.java
2008-04-14 16:00:44 UTC (rev 19326)
@@ -104,7 +104,7 @@
private static void sendHTMLError(OutputStream os, int code, String
httpReason, String htmlMessage, boolean disconnect, MultiValueTable mvt) throws
IOException {
if(mvt == null) mvt = new MultiValueTable();
byte[] messageBytes = htmlMessage.getBytes("UTF-8");
- sendReplyHeaders(os, code, httpReason, mvt, "text/html;
charset=UTF-8", messageBytes.length, disconnect);
+ sendReplyHeaders(os, code, httpReason, mvt, "text/html;
charset=UTF-8", messageBytes.length, null, disconnect);
os.write(messageBytes);
}
@@ -123,8 +123,12 @@
}
public void sendReplyHeaders(int replyCode, String replyDescription,
MultiValueTable mvt, String mimeType, long contentLength) throws
ToadletContextClosedException, IOException {
+ sendReplyHeaders(replyCode, replyDescription, mvt, mimeType,
contentLength, null);
+ }
+
+ public void sendReplyHeaders(int replyCode, String replyDescription,
MultiValueTable mvt, String mimeType, long contentLength, Date mTime) throws
ToadletContextClosedException, IOException {
if(closed) throw new ToadletContextClosedException();
- sendReplyHeaders(sockOutputStream, replyCode, replyDescription,
mvt, mimeType, contentLength, shouldDisconnect);
+ sendReplyHeaders(sockOutputStream, replyCode, replyDescription,
mvt, mimeType, contentLength, mTime, shouldDisconnect);
}
public PageMaker getPageMaker() {
@@ -135,7 +139,7 @@
return headers;
}
- static void sendReplyHeaders(OutputStream sockOutputStream, int
replyCode, String replyDescription, MultiValueTable mvt, String mimeType, long
contentLength, boolean disconnect) throws IOException {
+ static void sendReplyHeaders(OutputStream sockOutputStream, int
replyCode, String replyDescription, MultiValueTable mvt, String mimeType, long
contentLength, Date mTime, boolean disconnect) throws IOException {
// Construct headers
if(mvt == null)
mvt = new MultiValueTable();
@@ -147,17 +151,30 @@
}
if(contentLength >= 0)
mvt.put("content-length", Long.toString(contentLength));
- // FIXME allow caching on a config option.
- // For now cater to the paranoid.
- // Also this may fix a wierd bug...
- // All keys are lower-case
- mvt.put("expires", "Thu, 01 Jan 1970 00:00:00 GMT");
- // Sent now, expires now.
- String time = makeHTTPDate(System.currentTimeMillis());
- mvt.put("last-modified", time);
- mvt.put("date", time);
- mvt.put("pragma", "no-cache");
- mvt.put("cache-control", "max-age=0, must-revalidate, no-cache,
no-store, post-check=0, pre-check=0");
+
+ String expiresTime;
+ if (mTime == null) {
+ expiresTime = "Thu, 01 Jan 1970 00:00:00 GMT";
+ } else {
+ // use an expiry time of 1 day, somewhat arbitrarily
+ expiresTime = makeHTTPDate(mTime.getTime() + (24 * 60 *
60 * 1000));
+ }
+ mvt.put("expires", expiresTime);
+
+ String nowString = makeHTTPDate(System.currentTimeMillis());
+ String lastModString;
+ if (mTime == null) {
+ lastModString = nowString;
+ } else {
+ lastModString = makeHTTPDate(mTime.getTime());
+ }
+
+ mvt.put("last-modified", lastModString);
+ mvt.put("date", nowString);
+ if (mTime == null) {
+ mvt.put("pragma", "no-cache");
+ mvt.put("cache-control", "max-age=0, must-revalidate,
no-cache, no-store, post-check=0, pre-check=0");
+ }
if(disconnect)
mvt.put("connection", "close");
else
Modified: trunk/freenet/src/freenet/clients/http/bookmark/BookmarkManager.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/bookmark/BookmarkManager.java
2008-04-14 15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/clients/http/bookmark/BookmarkManager.java
2008-04-14 16:00:44 UTC (rev 19326)
@@ -23,7 +23,7 @@
public class BookmarkManager {
- public static SimpleFieldSet DEFAULT_BOOKMARKS = null;
+ public static final SimpleFieldSet DEFAULT_BOOKMARKS;
private final NodeClientCore node;
private final USKUpdatedCallback uskCB = new USKUpdatedCallback();
public static final BookmarkCategory MAIN_CATEGORY = new
BookmarkCategory("/");
@@ -33,6 +33,7 @@
private boolean isSavingBookmarks = false;
static {
String name =
"freenet/clients/http/staticfiles/defaultbookmarks.dat";
+ SimpleFieldSet defaultBookmarks = null;
InputStream in = null;
try {
ClassLoader loader = ClassLoader.getSystemClassLoader();
@@ -40,11 +41,12 @@
// Returns null on lookup failures:
in = loader.getResourceAsStream(name);
if(in != null)
- DEFAULT_BOOKMARKS = SimpleFieldSet.readFrom(in,
false, false);
+ defaultBookmarks = SimpleFieldSet.readFrom(in,
false, false);
} catch(Exception e) {
Logger.error("BookmarkManager", "Error while loading
the default bookmark file from " + name + " :" + e.getMessage(), e);
} finally {
Closer.close(in);
+ DEFAULT_BOOKMARKS = defaultBookmarks;
}
}
Modified: trunk/freenet/src/freenet/clients/http/filter/HTMLFilter.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/filter/HTMLFilter.java
2008-04-14 15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/clients/http/filter/HTMLFilter.java
2008-04-14 16:00:44 UTC (rev 19326)
@@ -16,6 +16,7 @@
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
+import java.nio.charset.MalformedInputException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
@@ -95,6 +96,9 @@
HTMLParseContext pc = new HTMLParseContext(r, w, null, new
NullFilterCallback(), true);
try {
pc.run(null);
+ } catch (MalformedInputException e) {
+ // Not this charset
+ return null;
} catch (IOException e) {
throw e;
} catch (Throwable t) {
Modified:
trunk/freenet/src/freenet/clients/http/staticfiles/defaultbookmarks.dat
===================================================================
--- trunk/freenet/src/freenet/clients/http/staticfiles/defaultbookmarks.dat
2008-04-14 15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/clients/http/staticfiles/defaultbookmarks.dat
2008-04-14 16:00:44 UTC (rev 19326)
@@ -15,15 +15,15 @@
BookmarkCategory0.Content.Bookmark2.Name=Another Index
BookmarkCategory0.Content.Bookmark2.Description=Comprehensive categorised
index of freesites and Thaw indexes; links to everything
BookmarkCategory0.Content.Bookmark2.hasAnActivelink=false
-BookmarkCategory0.Content.Bookmark2.URI=USK at
zQyF2O1o8B4y40w7Twz8y2I9haW3d2DTlxjTHPu7zc8,h2mhQNNE9aQvF~2yKAmKV1uorr7141-QOroBf5hrlbw,AQACAAE/AnotherIndex/57/
+BookmarkCategory0.Content.Bookmark2.URI=USK at
zQyF2O1o8B4y40w7Twz8y2I9haW3d2DTlxjTHPu7zc8,h2mhQNNE9aQvF~2yKAmKV1uorr7141-QOroBf5hrlbw,AQACAAE/AnotherIndex/58/
BookmarkCategory0.Content.Bookmark1.Name=Freenet Activelink Index (warning: it
will take a long time for all the images to load!)
BookmarkCategory0.Content.Bookmark1.hasAnActivelink=true
BookmarkCategory0.Content.Bookmark1.Description=A graphical freenet index
(this will take a long time to load as it preloads the sites; contains no porn)
-BookmarkCategory0.Content.Bookmark1.URI=USK at
qd-hk0vHYg7YvK2BQsJMcUD5QSF0tDkgnnF6lnWUH0g,xTFOV9ddCQQk6vQ6G~jfL6IzRUgmfMcZJ6nuySu~NUc,AQACAAE/activelink-index/37/
+BookmarkCategory0.Content.Bookmark1.URI=USK at
qd-hk0vHYg7YvK2BQsJMcUD5QSF0tDkgnnF6lnWUH0g,xTFOV9ddCQQk6vQ6G~jfL6IzRUgmfMcZJ6nuySu~NUc,AQACAAE/activelink-index/38/
BookmarkCategory0.Content.Bookmark4.Name=Freenet Activelink Index Text Version
(non-graphical version of FAI)
BookmarkCategory0.Content.Bookmark4.hasAnActivelink=true
BookmarkCategory0.Content.Bookmark4.Description=Text version of the Activelink
Index
-BookmarkCategory0.Content.Bookmark4.URI=USK at
qd-hk0vHYg7YvK2BQsJMcUD5QSF0tDkgnnF6lnWUH0g,xTFOV9ddCQQk6vQ6G~jfL6IzRUgmfMcZJ6nuySu~NUc,AQACAAE/activelink-index-text/2/
+BookmarkCategory0.Content.Bookmark4.URI=USK at
qd-hk0vHYg7YvK2BQsJMcUD5QSF0tDkgnnF6lnWUH0g,xTFOV9ddCQQk6vQ6G~jfL6IzRUgmfMcZJ6nuySu~NUc,AQACAAE/activelink-index-text/3/
BookmarkCategory1.Name=Freenet devel's flogs
BookmarkCategory1.Content.BookmarkCategory=0
BookmarkCategory1.Content.Bookmark=4
@@ -34,7 +34,7 @@
BookmarkCategory1.Content.Bookmark2.Name=Bombe
BookmarkCategory1.Content.Bookmark2.Description=Bombe's blog
BookmarkCategory1.Content.Bookmark2.hasAnActivelink=true
-BookmarkCategory1.Content.Bookmark2.URI=USK at
e3myoFyp5avg6WYN16ImHri6J7Nj8980Fm~aQe4EX1U,QvbWT0ImE0TwLODTl7EoJx2NBnwDxTbLTE6zkB-eGPs,AQACAAE/bombe/32/
+BookmarkCategory1.Content.Bookmark2.URI=USK at
e3myoFyp5avg6WYN16ImHri6J7Nj8980Fm~aQe4EX1U,QvbWT0ImE0TwLODTl7EoJx2NBnwDxTbLTE6zkB-eGPs,AQACAAE/bombe/33/
BookmarkCategory1.Content.Bookmark1.Name=Nextgen$
BookmarkCategory1.Content.Bookmark1.Description=NextGen$' blog
BookmarkCategory1.Content.Bookmark1.hasAnActivelink=true
@@ -53,7 +53,7 @@
BookmarkCategory2.Content.Bookmark1.Name=Freenet Message System
BookmarkCategory2.Content.Bookmark1.Description=The official freesite of FMS,
a spam resistant message board system for Freenet
BookmarkCategory2.Content.Bookmark1.hasAnActivelink=true
-BookmarkCategory2.Content.Bookmark1.URI=USK at
0npnMrqZNKRCRoGojZV93UNHCMN-6UU3rRSAmP6jNLE,~BG-edFtdCC1cSH4O3BWdeIYa8Sw5DfyrSV-TKdO5ec,AQACAAE/fms/42/
+BookmarkCategory2.Content.Bookmark1.URI=USK at
0npnMrqZNKRCRoGojZV93UNHCMN-6UU3rRSAmP6jNLE,~BG-edFtdCC1cSH4O3BWdeIYa8Sw5DfyrSV-TKdO5ec,AQACAAE/fms/43/
BookmarkCategory2.Content.Bookmark2.Name=Publish!
BookmarkCategory2.Content.Bookmark2.Description=Simple guide to publishing web
sites to Freenet
BookmarkCategory2.Content.Bookmark2.hasAnActivelink=true
Modified:
trunk/freenet/src/freenet/clients/http/staticfiles/themes/boxed/theme.css
===================================================================
--- trunk/freenet/src/freenet/clients/http/staticfiles/themes/boxed/theme.css
2008-04-14 15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/clients/http/staticfiles/themes/boxed/theme.css
2008-04-14 16:00:44 UTC (rev 19326)
@@ -329,7 +329,7 @@
.request-progress {
width: 100px;
- vertical-align: center;
+ vertical-align: middle;
}
.progressbar {
Deleted:
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/bluebuttonbg.gif
===================================================================
(Binary files differ)
Deleted:
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/bluebuttonbg_larger1.gif
===================================================================
(Binary files differ)
Modified:
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/theme.css
===================================================================
---
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/theme.css
2008-04-14 15:55:20 UTC (rev 19325)
+++
trunk/freenet/src/freenet/clients/http/staticfiles/themes/grayandblue/theme.css
2008-04-14 16:00:44 UTC (rev 19326)
@@ -27,22 +27,6 @@
border:1px dotted #676767;
}
-.bluebutton {
- background-image: url(bluebuttonbg_larger1.gif);
- background-repeat: no-repeat;
- font-family: verdana;
- font-size: 8pt;
- align: center;
- border: solid 0 #FFFFFF;
- color: #000000;
- margin: 0px;
- width: 140px;
- height: 21px;
- padding-top: 1px;
- padding-bottom: 3px;
- vertical-align: middle;
-}
-
pre, textarea {
font-family: Courier;
font-weight: normal;
Modified:
trunk/freenet/src/freenet/clients/http/staticfiles/themes/sky/theme.css
===================================================================
--- trunk/freenet/src/freenet/clients/http/staticfiles/themes/sky/theme.css
2008-04-14 15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/clients/http/staticfiles/themes/sky/theme.css
2008-04-14 16:00:44 UTC (rev 19326)
@@ -207,6 +207,11 @@
/* configuration page */
+table.config_navigation {
+ list-style-type: none;
+ margin-top: 10px;
+}
+
ul.config {
margin: 0 0 5px 0;
padding: 0;
@@ -214,18 +219,13 @@
}
ul.config li {
- margin: 0;
+ margin: 5px;
padding: 5px;
list-style: none;
text-align: left;
- display: table;
- position: relative;
+ background-color: #e5efff;
}
-ul.config li:hover span.configlongdesc {
- display: block;
-}
-
ul.config span.configprefix {
display: block;
width: 100%;
@@ -236,36 +236,25 @@
}
ul.config span.configshortdesc {
+ display: block;
text-align: left;
font-weight: bold;
- float: left;
margin-right: 10px;
- width: 300px;
- display: table-cell;
+ width: 30%;
+ float: left;
}
ul.config span.configlongdesc {
- display: none;
- position: absolute;
- left: 40px;
- background-color: #e1ecff;
- border: 1px solid #97beff;
- padding: 5px;
- /*
- * This should be 'top', but firefox is broken and doesn't
- + set the li to be a containing block with 'display: table' on
- */
- margin-top: 20px;
- z-index: 10;
+ display: block;
+ clear: left;
}
span.config {
- display: table-cell;
- width: 100%;
+ width: 70%;
}
ul.config input[type=text] {
- width: 100%;
+ width: 67%;
}
/* darknet page */
@@ -513,7 +502,7 @@
div.progressbar {
float: left;
- margin: none;
+ margin: 0px;
margin-right: 3px;
background-color: #f6f9ff;
border: solid 1px #97beff;
Modified: trunk/freenet/src/freenet/config/Option.java
===================================================================
--- trunk/freenet/src/freenet/config/Option.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/config/Option.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -9,21 +9,21 @@
public abstract class Option {
/** The parent SubConfig object */
- final SubConfig config;
+ protected final SubConfig config;
/** The option name */
- final String name;
+ protected final String name;
/** The sort order */
- final int sortOrder;
+ protected final int sortOrder;
/** Is this config variable expert-only? */
- final boolean expert;
+ protected final boolean expert;
/** Is this config variable to be written out even if it uses the
default value? */
- final boolean forceWrite;
+ protected final boolean forceWrite;
/** Short description of value e.g. "FCP port" */
- final String shortDesc;
+ protected final String shortDesc;
/** Long description of value e.g. "The TCP port to listen for FCP
connections on" */
- final String longDesc;
+ protected final String longDesc;
/** The configCallback associated to the Option */
- final ConfigCallback cb;
+ protected final ConfigCallback cb;
public final static int DATA_TYPE_STRING = 0;
public final static int DATA_TYPE_NUMBER = 1;
Modified: trunk/freenet/src/freenet/crypt/RandomSource.java
===================================================================
--- trunk/freenet/src/freenet/crypt/RandomSource.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/crypt/RandomSource.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -13,17 +13,29 @@
public abstract class RandomSource extends Random {
/**
- * Returns a 32 bit random floating point number. With this method,
- * all possible float values are approximately as likely to occur
- */
- public float nextFullFloat() {
+ * Returns a 32 bit random floating point number. With this method, all
possible float values
+ * are approximately as likely to occur.
+ *
+ * This method may return <tt>NaN</tt>, <tt>+Inf</tt>, <tt>-Inf</tt> or
other weird
+ * stuff. If you don't know what they are, this method is not for you.
+ *
+ * @see RandomSource#nextFloat()
+ */
+ // FIXME this method is unused, do you *really* want this method?
+ public float nextFullFloat() {
return Float.intBitsToFloat(nextInt());
}
/**
- * Returns a 64 bit random double. With this method, all possible
- * double values are approximately as likely to occur
- */
+ * Returns a 64 bit random double. With this method, all possible
double values are
+ * approximately as likely to occur.
+ *
+ * This method may return <tt>NaN</tt>, <tt>+Inf</tt>, <tt>-Inf</tt> or
other weird
+ * stuff. If you don't know what they are, this method is not for you.
+ *
+ * @see RandomSource#nextDouble()
+ */
+ // FIXME this method is unused, do you *really* want this method?
public double nextFullDouble() {
return Double.longBitsToDouble(nextLong());
}
Modified: trunk/freenet/src/freenet/io/AddressTracker.java
===================================================================
--- trunk/freenet/src/freenet/io/AddressTracker.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/io/AddressTracker.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -133,7 +133,7 @@
packetTo(peer, false);
}
- void packetTo(Peer peer, boolean sent) {
+ private void packetTo(Peer peer, boolean sent) {
peer = peer.dropHostName();
InetAddress ip = peer.getAddress();
long now = System.currentTimeMillis();
Modified: trunk/freenet/src/freenet/io/comm/FreenetInetAddress.java
===================================================================
--- trunk/freenet/src/freenet/io/comm/FreenetInetAddress.java 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/io/comm/FreenetInetAddress.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -147,7 +147,7 @@
if(!allowUnknown) throw e;
addr = null;
}
- if(logDEBUG) Logger.debug(this, "host is '"+host+"' and
addr.getHostAddress() is '"+addr.getHostAddress()+ '\'');
+ if(logDEBUG) Logger.debug(this, "host is '"+host+"' and
addr.getHostAddress() is '"+(addr != null ? addr.getHostAddress()+ '\'' : ""));
if(addr != null && addr.getHostAddress().equals(host)) {
if(logDEBUG) Logger.debug(this, '\'' +host+"' looks like an IP
address");
host = null;
Modified: trunk/freenet/src/freenet/keys/BaseClientKey.java
===================================================================
--- trunk/freenet/src/freenet/keys/BaseClientKey.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/keys/BaseClientKey.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -13,13 +13,14 @@
public abstract class BaseClientKey {
public static BaseClientKey getBaseKey(FreenetURI origURI) throws
MalformedURLException {
- if("CHK".equals(origURI.getKeyType()))
+ String keyType = origURI.getKeyType();
+ if("CHK".equals(keyType))
return new ClientCHK(origURI);
- if("SSK".equals(origURI.getKeyType()))
+ if("SSK".equals(keyType))
return new ClientSSK(origURI);
- if("KSK".equals(origURI.getKeyType()))
+ if("KSK".equals(keyType))
return ClientKSK.create(origURI.getDocName());
- if("USK".equals(origURI.getKeyType()))
+ if("USK".equals(keyType))
return USK.create(origURI);
throw new MalformedURLException("Unknown keytype from
"+origURI);
}
Modified: trunk/freenet/src/freenet/keys/ClientCHKBlock.java
===================================================================
--- trunk/freenet/src/freenet/keys/ClientCHKBlock.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/keys/ClientCHKBlock.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -89,8 +89,9 @@
throw new CHKDecodeException("Crypto key too short");
cipher.initialize(key.cryptoKey);
PCFBMode pcfb = PCFBMode.create(cipher);
- byte[] hbuf = new byte[headers.length-2];
- System.arraycopy(headers, 2, hbuf, 0, headers.length-2);
+ int headersLength = headers.length;
+ byte[] hbuf = new byte[headersLength > 2 ? headersLength-2 : 0];
+ System.arraycopy(headers, 2, hbuf, 0, hbuf.length);
byte[] dbuf = new byte[data.length];
System.arraycopy(data, 0, dbuf, 0, data.length);
// Decipher header first - functions as IV
Modified: trunk/freenet/src/freenet/keys/FreenetURI.java
===================================================================
--- trunk/freenet/src/freenet/keys/FreenetURI.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/keys/FreenetURI.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -434,8 +434,9 @@
*/
public FreenetURI popMetaString() {
String[] newMetaStr = null;
- if ((metaStr != null) && (metaStr.length > 1)) {
- newMetaStr = new String[metaStr.length - 1];
+ final int metaStrLength = metaStr.length;
+ if ((metaStr != null) && (metaStrLength > 1)) {
+ newMetaStr = new String[metaStrLength - 1];
System.arraycopy(metaStr, 1, newMetaStr, 0,
newMetaStr.length);
}
return setMetaString(newMetaStr);
@@ -643,12 +644,12 @@
dis.readFully(cryptoKey);
// Number of bytes of extra depends on key type
int extraLen;
- if(type == CHK)
+ if((type == CHK) || (type == SSK)) {
extraLen = ClientCHK.EXTRA_LENGTH;
- else //if(type == SSK)
- extraLen = ClientSSK.EXTRA_LENGTH;
- extra = new byte[extraLen];
- dis.readFully(extra);
+ extra = new byte[extraLen];
+ dis.readFully(extra);
+ } else
+ extra = new byte[0];
}
String docName = null;
if(type != CHK)
Modified: trunk/freenet/src/freenet/keys/NodeCHK.java
===================================================================
--- trunk/freenet/src/freenet/keys/NodeCHK.java 2008-04-14 15:55:20 UTC (rev
19325)
+++ trunk/freenet/src/freenet/keys/NodeCHK.java 2008-04-14 16:00:44 UTC (rev
19326)
@@ -8,6 +8,7 @@
import java.io.DataOutputStream;
import java.io.IOException;
import freenet.support.Base64;
+import freenet.support.Logger;
/**
* @author amphibian
@@ -83,4 +84,14 @@
System.arraycopy(routingKey, 0, buf, 2, routingKey.length);
return buf;
}
+
+ public static byte[] routingKeyFromFullKey(byte[] keyBuf) {
+ if(keyBuf.length == KEY_LENGTH) return keyBuf;
+ if(keyBuf.length != FULL_KEY_LENGTH) {
+ Logger.error(NodeCHK.class, "routingKeyFromFullKey() on
"+keyBuf.length+" bytes");
+ }
+ byte[] out = new byte[KEY_LENGTH];
+ System.arraycopy(keyBuf, 2, out, 0, KEY_LENGTH);
+ return out;
+ }
}
Modified: trunk/freenet/src/freenet/keys/NodeSSK.java
===================================================================
--- trunk/freenet/src/freenet/keys/NodeSSK.java 2008-04-14 15:55:20 UTC (rev
19325)
+++ trunk/freenet/src/freenet/keys/NodeSSK.java 2008-04-14 16:00:44 UTC (rev
19326)
@@ -193,5 +193,16 @@
pubKey = pubkeyCache.getKey(pubKeyHash);
return pubKey != null;
}
+
+ public static byte[] routingKeyFromFullKey(byte[] keyBuf) {
+ if(keyBuf.length != FULL_KEY_LENGTH) {
+ Logger.error(NodeSSK.class, "routingKeyFromFullKey() on
buffer length "+keyBuf.length);
+ }
+ byte[] encryptedHashedDocname = new byte[E_H_DOCNAME_SIZE];
+ byte[] pubKeyHash = new byte[PUBKEY_HASH_SIZE];
+ System.arraycopy(keyBuf, 2, encryptedHashedDocname, 0,
E_H_DOCNAME_SIZE);
+ System.arraycopy(keyBuf, 2+E_H_DOCNAME_SIZE, pubKeyHash, 0,
PUBKEY_HASH_SIZE);
+ return makeRoutingKey(pubKeyHash, encryptedHashedDocname);
+ }
}
Modified: trunk/freenet/src/freenet/l10n/freenet.l10n.de.properties
===================================================================
--- trunk/freenet/src/freenet/l10n/freenet.l10n.de.properties 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/l10n/freenet.l10n.de.properties 2008-04-14
16:00:44 UTC (rev 19326)
@@ -2,6 +2,8 @@
Announcer.announceAlertNoSeednodes=Es wurde keine seednodes.fref-Datei
gefunden, deshalb wird der Knoten nicht in der Lage sein sich aus eigener Kraft
automatisch mit dem Opennet zu verbinden. Bitte f?gen Sie manuell ein paar
Knoten hinzu oder laden Sie die Seednodes-Datei von
http://downloads.freenetproject.org/alpha/opennet/ herunter.
Announcer.announceAlertTitle=Knoten macht sich bekannt
Announcer.announceDetails=Wir haben k?rzlich ${recentSentAnnouncements}
Bekanntgaben gesendet, von denen ${runningAnnouncements} noch laufen, und haben
${addedNodes} Knoten hinzugef?gt (${refusedNodes} Knoten haben uns abgelehnt).
Wir sind gerade mit ${connectedSeednodes} Seednodes (Saat-Knoten) verbunden und
versuchen uns mit weiteren ${disconnectedSeednodes} zu verbinden.
+Announcer.announceDisabledTooOld=Diese Knoten scheint zu alt zu sein um sich
mit dem aktuellen Freenet-Netzwerk zu verbinden. Wir haben die Ank?ndigungen
deaktiviert, da sie nichts bringen. Bitte aktualisieren Sie Ihren Knoten so
bald wie m?glich (die automatische Aktualisierung k?nnte auf Ihre Eingabe
warten oder deaktiviert sein).
+Announcer.announceDisabledTooOldTitle=Ank?ndigungen deaktiviert (zu alt)
Announcer.announceLoading=Freenet l?dt gerade die Seednodes(Saat-Knoten)-Datei
herunter, sodass es versuchen kann sich im Rest des Netzwerks bekannt zu
machen. Die Bekanntgabe kann ein paar Minuten dauern.
Announcer.coolingOff=In den n?chsten ${time} Sekunden wartet der Knoten auf
die Knoten, bei denen er sich gerade gemeldet hat um sich zu verbinden. Wenn
dies nicht gen?gend Knoten hervorbringt, wird er es mit einem anderen Knoten
versuchen.
BookmarkEditorToadlet.addBookmark=Lesezeichen hinzuf?gen
@@ -72,7 +74,7 @@
ConfigToadlet.configNavTitle=Konfigurations-Navigation
ConfigToadlet.console=Konsole
ConfigToadlet.contributeTranslation=Zur ?bersetzung beitragen
-ConfigToadlet.defaultIs=Der Standard-Wert f?r diese Einstellung ist:
"${default}".
+ConfigToadlet.defaultIs=Standard-Wert: "${default}".
ConfigToadlet.false=nein
ConfigToadlet.fcp=FCP
ConfigToadlet.fproxy=FProxy
@@ -81,11 +83,11 @@
ConfigToadlet.node=Knoten
ConfigToadlet.pluginmanager=Plugin-Manager
ConfigToadlet.pluginmanager2=Plugin-Manager 2
-ConfigToadlet.possibilitiesTitle=Ihre M?glichkeiten
+ConfigToadlet.possibilitiesTitle=Fortsetzen
ConfigToadlet.reset=Zur?cksetzen
ConfigToadlet.returnToNodeConfig=Zur Knoten-Konfiguration zur?ckkehren
ConfigToadlet.shortTitle=Konfiguration
-ConfigToadlet.ssl=SSL (damit die Einstellungen ?bernommen werden, muss Freenet
neu gestartet werden)
+ConfigToadlet.ssl=SSL (ben?tigt Neustart)
ConfigToadlet.title=Freenet-Knoten-Konfiguration
ConfigToadlet.toadletsymlinker=ToadletSymlinker
ConfigToadlet.true=ja
@@ -315,12 +317,12 @@
FcpServer.filenameToStorePDataLong=Name der Datei, in der Details zu
persistenten (dauerhaften) Downloads gespeichert werden.
FcpServer.intervalBetweenWrites=Zeitraum zwischen dem Schreiben persistenter
Downloads auf den Datentr?ger.
FcpServer.intervalBetweenWritesLong=Zeitraum zwischen dem Schreiben
persistenter (dauerhafter) Downloads auf den Datentr?ger.
-FcpServer.isEnabled=Ist der FCP-Server aktiviert?
-FcpServer.isEnabledLong=Ist der FCP-Server aktiviert?
-FcpServer.portNumber=FCP-Port-Nummer
-FcpServer.portNumberLong=FCP-Port-Nummer.
+FcpServer.isEnabled=FCP aktivieren?
+FcpServer.isEnabledLong=Den "Freenet Client Protocol"-Server (Protokoll f?r
Programme die auf Freenet zugreifen) aktivieren
+FcpServer.portNumber=FCP-Port
+FcpServer.portNumberLong=Der TCP-Port auf dem der FCP-Server Nachrichten
empfangen soll.
FcpServer.ssl=SSL aktivieren?
-FcpServer.sslLong=SSL aktivieren?
+FcpServer.sslLong=SSL auf dem FCP-Server aktivieren?
FetchException.longError.1=Zu viele Ebenen von Rekursion (Schachtelung) in den
Archiven
FetchException.longError.10=Datei nicht im Archiv
FetchException.longError.11=Zu viele Pfad-Komponenten - kein Manifest(???)?
Versuchen Sie eine zu entfernen
@@ -406,8 +408,9 @@
FirstTimeWizardToadlet.continue=Fortfahren
FirstTimeWizardToadlet.continueEnd=Hier klicken, um anzufangen, Freenet zu
benutzen!
FirstTimeWizardToadlet.datastoreSize=Gr??e des Datenspeichers
-FirstTimeWizardToadlet.datastoreSizeLong=Bitte w?hlen Sie eine Gr??e f?r Ihren
Datenspeicher. Der Datenspeicher verh?lt sich wie ein Zwischenspeicher (Cache);
Daten f?r das Netzwerk zu speichern wird Ihnen zu einem besseren
Daten-Durchsatz verhelfen, wenn Sie popul?re Dateien anfordern. Je mehr Platz
Sie zur Verf?gung stellen k?nnen, desto besser ist es f?r die Gemeinschaft und
desto schneller wird Ihr Knoten.
+FirstTimeWizardToadlet.datastoreSizeLong=Bitte w?hlen Sie eine Gr??e f?r Ihren
Datenspeicher. Der Datenspeicher verh?lt sich wie ein Zwischenspeicher (Cache);
Daten f?r das Netzwerk zu speichern wird Ihnen zu einem besseren
Daten-Durchsatz verhelfen, wenn Sie popul?re Dateien anfordern. Je mehr Platz
Sie zur Verf?gung stellen k?nnen, desto besser ist es f?r die Gemeinschaft und
desto schneller wird Ihr Knoten, besonders das Herunterladen, sein.
FirstTimeWizardToadlet.enableOpennet=Kennen Sie jemanden, der bereits Freenet
benutzt?
+FirstTimeWizardToadlet.fivePercentDisk=(= 5% des freien Speicherplatzes)
FirstTimeWizardToadlet.homepageTitle=Freenet-Einrichtungs-Assistent!
FirstTimeWizardToadlet.iDoTrust=Trauen Sie Leuten die mit ${interface} (${ip})
verbunden sind?
FirstTimeWizardToadlet.isNetworkTrusted=Ist Ihr lokales Netzwerk
vertrauensw?rdig?
@@ -424,6 +427,7 @@
FirstTimeWizardToadlet.step4Title=Freenet-Einrichtungs-Assistent! - Gr??e des
Datenspeichers
FirstTimeWizardToadlet.step5Title=Freenet-Einrichtungs-Assistent! -
Netzwerk-Konfiguration
FirstTimeWizardToadlet.step6Title=Freenet-Einrichtungs-Assistent! - Herzlichen
Gl?ckwunsch, Ihr Knoten ist nun konfiguriert
+FirstTimeWizardToadlet.tenPercentDisk=(= 10% des freien Speicherplatzes)
FirstTimeWizardToadlet.warningTitle=Warnung!
FirstTimeWizardToadlet.welcomeInfoboxContent1=Willkommen beim
Freenet-Einrichtungs-Assistent. Dieses Werkzeug erlaubt es Ihnen, Ihren Knoten
schnell und einfach f?r den ersten Betrieb einzurichten.
FirstTimeWizardToadlet.welcomeInfoboxTitle=Willkommen zum
Freenet-Einrichtungs-Assistent!
@@ -962,10 +966,10 @@
SimpleToadletServer.illegalCSSName=CSS-Namen d?rfen keine Schr?gstriche oder
Doppelpunkte enthalten!
SimpleToadletServer.panicButton=Den Alarm-Knopf anzeigen?
SimpleToadletServer.panicButtonLong=Ob der Alarm-Knopf auf der
Warteschlangen-Seite (/queue/) angezeigt werden soll oder nicht.
-SimpleToadletServer.port=FProxy-Port-Nummer
-SimpleToadletServer.portLong=FProxy-Port-Nummer
+SimpleToadletServer.port=FProxy-Port
+SimpleToadletServer.portLong=Der TCP-Port auf dem FProxy Nachrichten empfangen
soll
SimpleToadletServer.ssl=SSL aktivieren?
-SimpleToadletServer.sslLong=SSL aktivieren?
+SimpleToadletServer.sslLong=SSL auf FProxy aktivieren?
StaticToadlet.pathInvalidChars=Der angegebene URI enth?lt nicht erlaubte
Zeichen.
StaticToadlet.pathNotFound=Der Pfad, den Sie angegeben haben, existiert nicht.
StaticToadlet.pathNotFoundTitle=Pfad nicht gefunden
@@ -983,10 +987,10 @@
StatisticsToadlet.fullTitle=Statistiken f?r ${name}
StatisticsToadlet.getLogs=Letzte Log-Datei des Knotens abrufen
StatisticsToadlet.inputRate=Eingehend: ${rate}/Sekunde (von ${max})
+StatisticsToadlet.javaVersion=Java-Version: ${version}
StatisticsToadlet.jeDumpButton=JE-Dump generieren
StatisticsToadlet.jvmInfoTitle=JVM-Info
StatisticsToadlet.jvmVendor=JVM-Hersteller: ${vendor}
-StatisticsToadlet.javaVersion=Java-Version: ${version}
StatisticsToadlet.jvmVersion=JVM-Version: ${version}
StatisticsToadlet.maxMemory=Maximaler Java-Speicher: ${memory}
StatisticsToadlet.noRequests=Ihr Knoten bearbeitet gerade keine Anfragen
@@ -1029,12 +1033,12 @@
TextModeClientInterfaceServer.bindToLong=Zu benutzende IP-Adresse
TextModeClientInterfaceServer.enableInputOutput=Auf stdout/stdin aktivieren?
TextModeClientInterfaceServer.enableInputOutputLong=Text-Modus-Client-Schnittstelle
in der Standard-Ein-/Ausgabe aktivieren? (.enabled (.aktiviert) bezieht sich
auf das stellen eines Servers im Telnet-Stil, dieser f?hrt es ?ber einen Sockel
(Socket) aus)
-TextModeClientInterfaceServer.enabled=TMCI aktivieren
-TextModeClientInterfaceServer.enabledLong=Ob das TMCI aktiviert werden soll
+TextModeClientInterfaceServer.enabled=TMCI aktivieren?
+TextModeClientInterfaceServer.enabledLong=Das "Text Mode Client Interface"
(textbasierte Schnittstelle f?r Programme die Freenet benutzen) aktivieren
TextModeClientInterfaceServer.ssl=SSL aktivieren?
-TextModeClientInterfaceServer.sslLong=SSL aktivieren?
-TextModeClientInterfaceServer.telnetPortNumber=Telnet-Port
-TextModeClientInterfaceServer.telnetPortNumberLong=Telnet-Port-Nummer
+TextModeClientInterfaceServer.sslLong=SSL auf dem TMCI-Server aktivieren?
+TextModeClientInterfaceServer.telnetPortNumber=TMCI-Port
+TextModeClientInterfaceServer.telnetPortNumberLong=Der TCP-Port auf dem der
TMCI-Server Nachrichten empfangen soll
TimeSkewDetectedUserAlert.text=Es wurde vom Knoten eine Zeitversetzung
erkannt. Das ist SEHR schlimm. Ihr Knoten wird nicht richtig laufen bis dies
behoben ist; h?ufige Ursachen sind ein falsch konfigurierter
Energie-Spar-Modus, Netzwerk-Zeit-Synchronisations-Programme, oder fehlerhafte
Hardware.
TimeSkewDetectedUserAlert.title=Zeitversetzung erkannt!
Toadlet.cancel=Abbrechen
Modified: trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties
===================================================================
--- trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/l10n/freenet.l10n.en.properties 2008-04-14
16:00:44 UTC (rev 19326)
@@ -800,6 +800,7 @@
PproxyToadlet.loadOtherPluginText=Here you can enter the URL of a plugin you
want to load. Other plugins than the ones listed above are not even remotely
supported or checked for privacy leaks by us, so if you load a remote plugin
here, you are basically on your own.
PproxyToadlet.loadOtherURLLabel=Plugin URL
PproxyToadlet.noPlugins=No plugins loaded
+PproxyToadlet.noVersion=N/A
PproxyToadlet.pluginNotFoundReload=The specified plugin could not be located
in order to reload it.
PproxyToadlet.pluginNotFoundReloadTitle=Plugin Not Found (reloading)
PproxyToadlet.pluginUnloaded=Plugin unloaded
@@ -830,18 +831,21 @@
PproxyToadlet.unloadPluginTitle=Unload plugin?
PproxyToadlet.unloadPluginWithName=Are you sure you wish to unload ${name}?
PproxyToadlet.unloadPurge=Remove plugin from cache
-QueueToadlet.DUinProgress=Directory uploads in progress
-QueueToadlet.DinProgress=Downloads in progress
-QueueToadlet.UinProgress=Uploads in progress
+PproxyToadlet.versionTitle=Version
+QueueToadlet.DUinProgress=Directory uploads in progress (${size})
+QueueToadlet.DinProgress=Downloads in progress (${size})
+QueueToadlet.UinProgress=Uploads in progress (${size})
QueueToadlet.change=Change
-QueueToadlet.completedDU=Completed directory uploads
-QueueToadlet.completedDinDownloadDirectory=Completed: Downloads to download
directory (${size})
-QueueToadlet.completedDinTempDirectory=Completed: Downloads to temporary
directory (${size})
-QueueToadlet.completedDtoDisk=Completed downloads to disk
-QueueToadlet.completedDtoTemp=Completed downloads to temp
-QueueToadlet.completedU=Completed: Uploads (${size})
-QueueToadlet.completedUDirectory=Completed: Directory Uploads (${size})
+QueueToadlet.completedDU=Completed directory uploads (${size})
+QueueToadlet.completedDinDownloadDirectory=Completed downloads to download
directory (${size})
+QueueToadlet.completedDinTempDirectory=Completed downloads to temporary
directory (${size})
+QueueToadlet.completedDtoDisk=Completed downloads to disk (${size})
+QueueToadlet.completedDtoTemp=Completed downloads to temp (${size})
+QueueToadlet.completedU=Completed uploads (${size})
+QueueToadlet.completedUDirectory=Completed directory uploads (${size})
QueueToadlet.download=Download
+QueueToadlet.downloadSucceededTitle=Download succeeded: ${filename}
+QueueToadlet.downloadSucceeded=The file ${origlink}${filename}${/origlink} has
been downloaded successfully. ${link}Click here${/link} to open the file
(${size}).
QueueToadlet.errorAccessDenied=Error: Access Denied!
QueueToadlet.errorAccessDeniedFile=The current configuration of the node
prohibits you from uploading the file "${file}".
QueueToadlet.errorDToDisk=Cannot download to disk
@@ -857,17 +861,14 @@
QueueToadlet.errorNoFileSelectedU=You did not select a file to upload.
QueueToadlet.errorNoKey=No key specified to download
QueueToadlet.errorNoKeyToD=You did not specify a key to download.
-QueueToadlet.failedD=Failed downloads
-QueueToadlet.failedD=Failed: Downloads (${size})
-QueueToadlet.failedDU=Failed directory uploads
-QueueToadlet.failedDU=Failed: Directory Uploads (${size})
+QueueToadlet.failedD=Failed downloads (${size})
+QueueToadlet.failedDU=Failed directory uploads (${size})
QueueToadlet.failedToRemove=Failed to remove ${id}: ${message}
QueueToadlet.failedToRemoveId=Failed to remove: ${id}
QueueToadlet.failedToRemoveRequest=Failed to remove request
QueueToadlet.failedToRestart=Failed to restart: ${id}
QueueToadlet.failedToRestartRequest=Failed to restart request
-QueueToadlet.failedU=Failed uploads
-QueueToadlet.failedU=Failed: Uploads (${size})
+QueueToadlet.failedU=Failed uploads (${size})
QueueToadlet.fcpIsMissing=FCP server is missing
QueueToadlet.fileName=Filename
QueueToadlet.files=Files
@@ -911,11 +912,15 @@
QueueToadlet.remove=Remove
QueueToadlet.requestNavigation=Request Navigation
QueueToadlet.restart=Restart
+QueueToadlet.siteUploadSucceededTitle=Freesite insert succeeded: ${filename}
+QueueToadlet.siteUploadSucceeded=Your freesite ${filename} (${files} files,
${size} total size) has been successfully uploaded to Freenet. ${link}Click
here${/link} to open the site homepage.
QueueToadlet.size=Size
QueueToadlet.starting=STARTING
QueueToadlet.title=Global queue of ${nodeName}
QueueToadlet.totalSize=Total Size
QueueToadlet.unknown=Unknown
+QueueToadlet.uploadSucceededTitle=Insert succeeded: ${filename}
+QueueToadlet.uploadSucceeded=Your file ${filename} (size ${size}) has been
successfully uploaded to Freenet. ${link}Click here${/link} to open the file.
QueueToadlet.warningUnsafeContent=Potentially Unsafe Content
QueueToadlet.warningUnsafeContentExplanation=The file you want to download is
currently not filtered by Freenet's content filter! That means that your
anonymity can be compromised by opening the file!
QueueToadlet.wipD=In Progress: Downloads (${size})
Modified: trunk/freenet/src/freenet/l10n/freenet.l10n.fr.properties
===================================================================
--- trunk/freenet/src/freenet/l10n/freenet.l10n.fr.properties 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/l10n/freenet.l10n.fr.properties 2008-04-14
16:00:44 UTC (rev 19326)
@@ -2,6 +2,8 @@
Announcer.announceAlertNoSeednodes=Le fichier seednodes.fref est introuvable,
le n?ud ne peut pas se connecter ? l'Opennet automatiquement. Veuillez ?tablir
des connexions manuellement, ou t?l?charger le fichier
http://downloads.freenetproject.org/alpha/opennet/seednodes.fref et le placer
dans le r?pertoire freenet.
Announcer.announceAlertTitle=Connexion au r?seau
Announcer.announceDetails=Nous avons envoy? ${recentSentAnnouncements}
annonces, dont ${runningAnnouncements} sont toujours en cours, et ajout?
${addedNodes} n?uds (${refusedNodes} n?uds ont refus? de se connecter). Nous
sommes actuellement connect?s ? ${connectedSeednodes} seednodes et essayons de
nous connecter ? ${disconnectedSeednodes} autres.
+Announcer.announceDisabledTooOld=Votre noeud est trop ancien pour se connecter
au r?seau Freenet actuel. Les annonces sont d?sactiv?es puisqu'elles ne m?nent
nulle part. Veuillez mettre votre noeud ? jour (la mise ? jour automatique
attend peut-?tre une confirmation ou alors vous l'avez d?sactiv?e).
+Announcer.announceDisabledTooOldTitle=Annonces d?sactiv?es (noeud trop ancien)
Announcer.announceLoading=Freenet t?l?charge la liste des seednodes afin de
pouvoir annoncer sa pr?sence sur le r?seau. Cela va prendre quelques minutes.
Announcer.coolingOff=Pendant les ${time} prochaines secondes, le noeud va
attendre que les noeuds auxquels il s'est annonc? se connectent. S'il n'y en a
pas assez, il essaiera ? nouveau.
BookmarkEditorToadlet.addBookmark=Ajouter un marque-page
@@ -72,7 +74,7 @@
ConfigToadlet.configNavTitle=Sections de configuration
ConfigToadlet.console=console
ConfigToadlet.contributeTranslation=Aider ? la traduction
-ConfigToadlet.defaultIs=La valeur par d?faut est : '${default}'.
+ConfigToadlet.defaultIs=Par d?faut : '${default}'.
ConfigToadlet.false=non
ConfigToadlet.fcp=fcp
ConfigToadlet.fproxy=fproxy
@@ -81,11 +83,11 @@
ConfigToadlet.node=noeud
ConfigToadlet.pluginmanager=gestionnaire de plugins
ConfigToadlet.pluginmanager2=gestionnaire de plugins 2
-ConfigToadlet.possibilitiesTitle=Vos possibilit?s
+ConfigToadlet.possibilitiesTitle=Continuer
ConfigToadlet.reset=R?initialiser
ConfigToadlet.returnToNodeConfig=Retourner ? la page de configuration
ConfigToadlet.shortTitle=Configuration
-ConfigToadlet.ssl=SSL (n'affecte pas les connexions d?ja ?tablies, red?marrez
si n?cessaire)
+ConfigToadlet.ssl=SSL (red?marrage n?cessaire)
ConfigToadlet.title=Configuration du noeud Freenet
ConfigToadlet.toadletsymlinker=toadletsymlinker
ConfigToadlet.true=oui
@@ -112,8 +114,18 @@
ConnectionsToadlet.nodeStatus.TOO NEW=TROP RECENT
ConnectionsToadlet.nodeStatus.TOO OLD=TROP ANCIEN
ConnectionsToadlet.nodeStatus.UNKNOWN STATUS=ETAT INCONNU
+ConnectivityToadlet.addressTitle=Adresse
+ConnectivityToadlet.byIPTitle=Paquets pour ${ip} par adresse IP - ${status}
(dur?e de vie minimum du tunnel ${tunnelLength})
+ConnectivityToadlet.byPortTitle=Paquets pour ${port} par port - ${status}
(dur?e de vie minimum du tunnel ${tunnelLength})
ConnectivityToadlet.connectivity=Raccordement ? Internet
ConnectivityToadlet.connectivityTitle=Raccordement r?seau
+ConnectivityToadlet.firstReceiveLeadTime=D?lai avant la premi?re r?ception
+ConnectivityToadlet.firstSendLeadTime=D?lai avant le premier envoi
+ConnectivityToadlet.local=LOCAL
+ConnectivityToadlet.localRemoteTitle=Local/distant
+ConnectivityToadlet.noreply=PAS DE REPONSE
+ConnectivityToadlet.remote=DISTANT
+ConnectivityToadlet.sentReceivedTitle=Paquets envoy?s/re?us
ConnectivityToadlet.summaryTitle=Raccordement r?seau
ConnectivityToadlet.title=Raccordement internet de ${nodeName}
ContentDataFilter.unknownCharset=La page que vous essayez d'afficher utilise
un jeu de caract?re inconnu. Cela signifie que le noeud ne pourra pas la
filtrer, et qu'elle pourait compromettre votre anonymat.
@@ -309,12 +321,12 @@
FcpServer.filenameToStorePDataLong=Fichier o? stocker les d?tails sur les
t?l?chargements persistants.
FcpServer.intervalBetweenWrites=Intervalle entre les ?critures des
t?l?chargements persistants sur le disque
FcpServer.intervalBetweenWritesLong=Intervalle entre les ?critures des
t?l?chargements persistants sur le disque.
-FcpServer.isEnabled=Le serveur FCP est-il activ? ?
-FcpServer.isEnabledLong=Le serveur FCP est-il activ? ?
+FcpServer.isEnabled=Activer FCP ?
+FcpServer.isEnabledLong=Activer le serveur de Protocole pour Client de Freenet
FcpServer.portNumber=Port FCP
-FcpServer.portNumberLong=Port FCP.
-FcpServer.ssl=Activer ssl ?
-FcpServer.sslLong=Activer ssl ?
+FcpServer.portNumberLong=Le port TCP ?cout? par le serveur FCP
+FcpServer.ssl=Activer SSL ?
+FcpServer.sslLong=Activer SSL sur le serveur FCP
FetchException.longError.1=Trop de niveau de r?cursivit? dans ces archives
FetchException.longError.10=Le ficher ne se trouve pas dans l'archive
FetchException.longError.11=Chemin trop long - pas un manifeste ? Essayez de
raccourcir le chemin
@@ -389,7 +401,7 @@
FileOffer.succeededReceiveHeader=Le transfert du fichier ${filename} de
${node} a r?ussi.
FileOffer.succeededReceiveTitle=Fichier re?u
FirstTimeWizardToadlet.bandwidthLimit=Limites de d?bit
-FirstTimeWizardToadlet.bandwidthLimitLong=Veuillez choisir le type et la
vitesse de votre connexion internet dans la liste ci-dessous.
+FirstTimeWizardToadlet.bandwidthLimitLong=Veuillez choisir le type et la
vitesse de votre connexion internet (download/upload) dans la liste ci-dessous.
FirstTimeWizardToadlet.chooseNodeName=Vous devez choisir un nom !
FirstTimeWizardToadlet.chooseNodeNameLong=Veuillez entrer un nom pour votre
n?ud (nous recommandons un pseudo ou une adresse email). Cela permettra ? vos
amis (les n?uds de confiance que vous aurez ajout?s manuellement) de
reconnaitre votre n?ud. Ce nom ne sera pas visible pour les Inconnus (ces n?uds
ajout?s automatiquement par l'Opennet). Vous devez savoir que n'importe quel
Ami ou Inconnu peut vous identifier facilement par votre IP, puisque vous ?tes
connect? ? eux, mais il ne peuvent pas savoir ce que vous faites dans le r?seau.
FirstTimeWizardToadlet.clickContinue=Cliquez ici pour continuer.
@@ -400,8 +412,9 @@
FirstTimeWizardToadlet.continue=Continuer
FirstTimeWizardToadlet.continueEnd=Cliquez ici pour commencer ? utiliser
Freenet !
FirstTimeWizardToadlet.datastoreSize=Taille du store
-FirstTimeWizardToadlet.datastoreSizeLong=Veuillez sp?cifier la taille de votre
datastore. Le datastore agit comme un cache ; stocker les donn?es du r?seau
am?liorera les performances quand vous t?l?chargerez des fichiers populaires.
Plus vous stockez de donn?es, plus vous aidez la communaut? et plus votre noeud
sera rapide.
+FirstTimeWizardToadlet.datastoreSizeLong=Veuillez sp?cifier la taille de votre
datastore. Le datastore agit comme un cache ; stocker les donn?es du r?seau
am?liorera les performances quand vous t?l?chargerez des fichiers populaires.
Plus vous stockez de donn?es, plus vous aidez la communaut? et plus votre noeud
sera rapide (surtout les t?l?chargements).
FirstTimeWizardToadlet.enableOpennet=Connaissez-vous des gens qui utilisent
Freenet ?
+FirstTimeWizardToadlet.fivePercentDisk=(= 5% de l'espace libre)
FirstTimeWizardToadlet.homepageTitle=Assistant de d?marrage Freenet !
FirstTimeWizardToadlet.iDoTrust=Faites-vous confiance aux personnes connect?s
par ${interface} (${ip}) ?
FirstTimeWizardToadlet.isNetworkTrusted=Le r?seau local est-il digne de
confiance ?
@@ -418,6 +431,7 @@
FirstTimeWizardToadlet.step4Title=Assistant de d?marrage Freenet ! - Taille du
datastore
FirstTimeWizardToadlet.step5Title=Assistant de d?marrage Freenet ! -
Configuration r?seau
FirstTimeWizardToadlet.step6Title=Assistant de d?marrage Freenet ! -
F?licitations, votre noeud est configur?.
+FirstTimeWizardToadlet.tenPercentDisk=(= 10% de l'espace libre)
FirstTimeWizardToadlet.warningTitle=Attention !
FirstTimeWizardToadlet.welcomeInfoboxContent1=Bienvenue dans l'assistant de
d?marrage Freenet . Cet outil vous permettra de configurer rapidement et
facilement votre noeud.
FirstTimeWizardToadlet.welcomeInfoboxTitle=Bienvenue sur l'assistant de
d?marrage Freenet !
@@ -894,7 +908,7 @@
QueueToadlet.priority6=ne se terminera jamais
QueueToadlet.progress=Progression
QueueToadlet.progressbarAccurate=Cette valeur est pr?cise
-QueueToadlet.progressbarNotAccurate=Cette valeur risque de changer car le
traitement du fichier n'est pas termin?e
+QueueToadlet.progressbarNotAccurate=Cette valeur risque de changer quand de
nouveaux blocs seront trouv?s
QueueToadlet.reason=Raison
QueueToadlet.remove=Supprimer
QueueToadlet.requestNavigation=Parcours des requ?tes
@@ -904,13 +918,18 @@
QueueToadlet.title=File d'attente globale de ${nodeName}
QueueToadlet.totalSize=Taille totale
QueueToadlet.unknown=Inconnu
+QueueToadlet.uploadProgressbarNotAccurate=Cette valeur risque de changer quand
de nouveaux blocs seront ins?r?s
QueueToadlet.warningUnsafeContent=Contenu potentiellement dangereux
QueueToadlet.warningUnsafeContentExplanation=Ce fichier n'est pas filtr? par
votre noeud Freenet ! Cela signifie qu'ouvrir ce fichier peut compromettre
votre anonymat.
QueueToadlet.wipD=En cours : T?l?chargements (${size})
QueueToadlet.wipDU=En cours : Insertions de dossiers (${size})
QueueToadlet.wipU=En cours : Insertions (${size})
-RequestStarterGroup.scheduler=Priorit?s de l'ordonnanceur
+RequestStarterGroup.scheduler=Priorit?s de l'ordonnanceur : hard (respect
strict des priorit?s) ou soft (m?lange l?g?rement les priorit?s)
+RequestStarterGroup.schedulerCHKInserts=Gestion des priorit?s par
l'ordonnanceur (insertions de CHK)
+RequestStarterGroup.schedulerCHKRequests=Gestion des priorit?s par
l'ordonnanceur (requ?tes de CHK)
RequestStarterGroup.schedulerLong=D?finir les r?gles de priorit? de
l'ordonnanceur.
+RequestStarterGroup.schedulerSSKInserts=Gestion des priorit?s par
l'ordonnanceur (insertions de SSK)
+RequestStarterGroup.schedulerSSKRequests=Gestion des priorit?s par
l'ordonnanceur (requ?tes de SSK)
RevocationKeyFoundUserAlert.text=Le noeud a trouv? la cl? de r?vocation des
mises ? jour automatiques sur le r?seau. Cela signifie que le syst?me de mise ?
jour automatique a certainement ?t? COMPROMIS ! En cons?quence, il a ?t?
d?sactiv? sur votre noeud afin d'?viter que de "mauvaises choses" soient
install?es. Nous vous conseillons fortement de rechercher les mises ? jour sur
le site officiel. Assurez vous que le site n'a pas ?t? falsifi? lui aussi. Le
message de r?vocation est : ${message}.
RevocationKeyFoundUserAlert.title=La cl? priv?e du projet a ?t? compromise !
SSL.enable=Activer le support SSL ?
@@ -953,10 +972,10 @@
SimpleToadletServer.illegalCSSName=Le nom du CSS ne doit contenir ni slash, ni
points !
SimpleToadletServer.panicButton=Afficher le bouton panique ?
SimpleToadletServer.panicButtonLong=Choisir d'afficher ou non le bouton
panique sur la page /File d'attente/.
-SimpleToadletServer.port=Num?ro de port FProxy
-SimpleToadletServer.portLong=Num?ro de port FProxy
-SimpleToadletServer.ssl=Activer ssl?
-SimpleToadletServer.sslLong=Activer ssl ?
+SimpleToadletServer.port=Port FProxy
+SimpleToadletServer.portLong=Port TCP ?cout? par FProxy
+SimpleToadletServer.ssl=Activer SSL ?
+SimpleToadletServer.sslLong=Activer SSL pour FProxy
StaticToadlet.pathInvalidChars=Cette URI contient des caract?res interdits.
StaticToadlet.pathNotFound=Le chemin sp?cifi? n'existe pas.
StaticToadlet.pathNotFoundTitle=Chemin introuvable.
@@ -974,6 +993,7 @@
StatisticsToadlet.getLogs=R?cup?rer le dernier journal du noeud
StatisticsToadlet.inputRate=R?ception : ${rate}/seconde (sur ${max}/seconde)
StatisticsToadlet.insertOutput=Traffic d'insertion (traffic utile): CHK ${chk}
SSK ${ssk}.
+StatisticsToadlet.javaVersion=Version de Java : ${version}
StatisticsToadlet.jeDumpButton=G?n?rer un dump JE
StatisticsToadlet.jvmInfoTitle=Informations sur la JVM
StatisticsToadlet.jvmVendor=Distributeur de la JVM : ${vendor}
@@ -1022,12 +1042,12 @@
TextModeClientInterfaceServer.bindToLong=Adresse IP o? ?couter
TextModeClientInterfaceServer.enableInputOutput=Activer sur stdin/stdout ?
TextModeClientInterfaceServer.enableInputOutputLong=Activer l'interface en
mode texte ? (activer consiste ? fournir une interface ? la telnet, ? travers
une socket)
-TextModeClientInterfaceServer.enabled=Activer TMCI
-TextModeClientInterfaceServer.enabledLong=Activer le serveur TMCI (interface
en ligne de commande) ou non
-TextModeClientInterfaceServer.ssl=Activer ssl ?
-TextModeClientInterfaceServer.sslLong=Activer ssl ?
-TextModeClientInterfaceServer.telnetPortNumber=Port telnet
-TextModeClientInterfaceServer.telnetPortNumberLong=Num?ro de port telnet
+TextModeClientInterfaceServer.enabled=Activer TMCI ?
+TextModeClientInterfaceServer.enabledLong=Activer l'interface en mode texte
+TextModeClientInterfaceServer.ssl=Activer SSL ?
+TextModeClientInterfaceServer.sslLong=Activer SSL sur le serveur TMCI
+TextModeClientInterfaceServer.telnetPortNumber=Port TMCI
+TextModeClientInterfaceServer.telnetPortNumberLong=Le port TCP ?cout? par le
serveur TMCI
TimeSkewDetectedUserAlert.text=Un d?callage horaire a ?t? d?tect? par votre
noeud. C'est TRES mauvais. Votre noeud ne fonctionnera pas correctement tant
que ce ne sera pas corrig?. Les causes habituelles sont une mauvaise
configuration de la mise en veille, du client de synchronisation horaire ou un
probl?me mat?riel.
TimeSkewDetectedUserAlert.title=D?callage horaire d?tect? !
Toadlet.cancel=Annuler
Modified: trunk/freenet/src/freenet/node/DarknetPeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/DarknetPeerNode.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/node/DarknetPeerNode.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -546,7 +546,7 @@
Logger.error(this, "Extra peer data directory for peer
not a directory: "+extraPeerDataPeerDir.getPath());
return -1;
}
- Integer[] localFileNumbers = null;
+ Integer[] localFileNumbers;
int nextFileNumber = 0;
synchronized(extraPeerDataFileNumbers) {
// Find the first free slot
@@ -635,7 +635,7 @@
Logger.error(this, "Extra peer data directory for peer
not a directory: "+extraPeerDataPeerDir.getPath());
return;
}
- Integer[] localFileNumbers = null;
+ Integer[] localFileNumbers;
synchronized(extraPeerDataFileNumbers) {
localFileNumbers = (Integer[])
extraPeerDataFileNumbers.toArray(new Integer[extraPeerDataFileNumbers.size()]);
}
@@ -731,7 +731,7 @@
public void sendQueuedN2NMs() {
if(logMINOR)
Logger.minor(this, "Sending queued N2NMs for
"+shortToString());
- Integer[] localFileNumbers = null;
+ Integer[] localFileNumbers;
synchronized(queuedToSendN2NMExtraPeerDataFileNumbers) {
localFileNumbers = (Integer[])
queuedToSendN2NMExtraPeerDataFileNumbers.toArray(new
Integer[queuedToSendN2NMExtraPeerDataFileNumbers.size()]);
}
Modified: trunk/freenet/src/freenet/node/FNPPacketMangler.java
===================================================================
--- trunk/freenet/src/freenet/node/FNPPacketMangler.java 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/node/FNPPacketMangler.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -944,7 +944,7 @@
}
// sanity check
- byte[] myNi = null;
+ byte[] myNi;
synchronized (pn) {
myNi = (byte[]) pn.jfkNoncesSent.get(replyTo);
}
@@ -1124,7 +1124,7 @@
byte[] data = new byte[decypheredPayload.length -
decypheredPayloadOffset];
System.arraycopy(decypheredPayload, decypheredPayloadOffset,
data, 0, decypheredPayload.length - decypheredPayloadOffset);
long bootID = Fields.bytesToLong(data);
- byte[] hisRef = new byte[data.length -8];
+ byte[] hisRef = new byte[data.length > 8 ? data.length -8 : 0];
System.arraycopy(data, 8, hisRef, 0, hisRef.length);
// construct the peernode
Modified: trunk/freenet/src/freenet/node/FailureTable.java
===================================================================
--- trunk/freenet/src/freenet/node/FailureTable.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/node/FailureTable.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -154,18 +154,21 @@
if(logMINOR) Logger.minor(this, "Deleting "+offer+"
from "+this);
synchronized(this) {
int idx = -1;
- for(int i=0;i<offers.length;i++) {
+ final int offerLength = offers.length;
+ for(int i=0;i<offerLength;i++) {
if(offers[i] == offer) idx = i;
}
if(idx == -1) return;
- BlockOffer[] newOffers = new
BlockOffer[offers.length-1];
- if(idx > 0)
- System.arraycopy(offers, 0, newOffers,
0, idx);
- if(idx < newOffers.length)
- System.arraycopy(offers, idx+1,
newOffers, idx, offers.length-idx-1);
- offers = newOffers;
+ if(offers.length > 1) {
+ BlockOffer[] newOffers = new
BlockOffer[offerLength > 1 ? offerLength-1 : 0];
+ if(idx > 0)
+ System.arraycopy(offers, 0,
newOffers, 0, idx);
+ if(idx < newOffers.length)
+ System.arraycopy(offers, idx+1,
newOffers, idx, offers.length-idx-1);
+ offers = newOffers;
+ }
}
- if(offers.length == 0) {
+ if(offers.length < 1) {
synchronized(FailureTable.this) {
blockOfferListByKey.removeKey(entry.key);
}
Modified: trunk/freenet/src/freenet/node/IPDetectorPluginManager.java
===================================================================
--- trunk/freenet/src/freenet/node/IPDetectorPluginManager.java 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/node/IPDetectorPluginManager.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -8,6 +8,7 @@
import java.util.Set;
import java.util.Vector;
+import freenet.io.AddressTracker;
import freenet.io.comm.FreenetInetAddress;
import freenet.io.comm.Peer;
import freenet.l10n.L10n;
@@ -36,10 +37,12 @@
final boolean suggestPortForward;
private int[] portsNotForwarded;
+ boolean noDismiss;
- public MyUserAlert(String title, String text, boolean
suggestPortForward, short code) {
+ public MyUserAlert(String title, String text, boolean
suggestPortForward, short code, boolean noDismiss) {
super(false, title, text, null, code, true,
L10n.getString("UserAlert.hide"), false, null);
this.suggestPortForward = suggestPortForward;
+ this.noDismiss = noDismiss;
portsNotForwarded = new int[] { };
}
@@ -63,10 +66,10 @@
StringBuffer sb = new StringBuffer();
sb.append(super.getText());
if(portsNotForwarded.length == 1) {
- sb.append(l10n("suggestForwardPort", "port",
Integer.toString(portsNotForwarded[0])));
+ sb.append(l10n("suggestForwardPort", "port",
Integer.toString(Math.abs(portsNotForwarded[0]))));
} else if(portsNotForwarded.length >= 2) {
sb.append(l10n("suggestForwardTwoPorts", new
String[] { "port1", "port2" },
- new String[] {
Integer.toString(portsNotForwarded[0]), Integer.toString(portsNotForwarded[1])
}));
+ new String[] {
Integer.toString(Math.abs(portsNotForwarded[0])),
Integer.toString(Math.abs(portsNotForwarded[1])) }));
if(portsNotForwarded.length > 2)
Logger.error(this, "Not able to tell
user about more than 2 ports to forward! ("+portsNotForwarded.length+")");
}
@@ -88,7 +91,16 @@
}
public boolean userCanDismiss() {
- return !suggestPortForward;
+ if(noDismiss) return true;
+ // If no ports need forwarding, make it dismissable
immediately.
+ if(!suggestPortForward) return true;
+ // Prevent NPE.
+ if(portsNotForwarded == null) return false;
+ // If any port definitely does need forwarding, make it
non-dismissable.
+ for(int i=0;i<portsNotForwarded.length;i++)
+ if(portsNotForwarded[i] < 0) return false; //
Port definitely needs to be forwarded
+ // Otherwise it is dismissable.
+ return true;
}
}
@@ -114,28 +126,31 @@
this.node = node;
this.detector = detector;
noConnectionAlert = new MyUserAlert(
l10n("noConnectivityTitle"), l10n("noConnectivity"),
- true, UserAlert.ERROR);
+ true, UserAlert.ERROR, true);
symmetricAlert = new MyUserAlert(l10n("symmetricTitle"),
l10n("symmetric"),
- true, UserAlert.ERROR);
+ true, UserAlert.ERROR, false);
portRestrictedAlert = new
MyUserAlert(l10n("portRestrictedTitle"), l10n("portRestricted"),
- true, UserAlert.WARNING);
+ true, UserAlert.WARNING, false);
restrictedAlert = new MyUserAlert(l10n("restrictedTitle"),
l10n("restricted"),
- false, UserAlert.MINOR);
+ false, UserAlert.MINOR, false);
}
public int[] getUDPPortsNotForwarded() {
OpennetManager om = node.getOpennet();
- if(om == null || om.crypto.definitelyPortForwarded()) {
- if(node.darknetDefinitelyPortForwarded()) {
+ int darknetStatus =
node.darknetCrypto.getDetectedConnectivityStatus();
+ int opennetStatus = om == null ? AddressTracker.DONT_KNOW :
om.crypto.getDetectedConnectivityStatus();
+ if(om == null || opennetStatus ==
AddressTracker.DEFINITELY_PORT_FORWARDED) {
+ if(darknetStatus ==
AddressTracker.DEFINITELY_PORT_FORWARDED) {
return new int[] { };
} else {
- return new int[] { node.getDarknetPortNumber()
};
+ return new int[] { (darknetStatus <
AddressTracker.DONT_KNOW ? -1 : 1) * node.getDarknetPortNumber() };
}
} else {
- if(node.darknetDefinitelyPortForwarded()) {
- return new int[] { om.crypto.portNumber };
+ if(darknetStatus ==
AddressTracker.DEFINITELY_PORT_FORWARDED) {
+ return new int[] { (opennetStatus <
AddressTracker.DONT_KNOW ? -1 : 1 ) * om.crypto.portNumber };
} else {
- return new int[] { node.getDarknetPortNumber(),
om.crypto.portNumber };
+ return new int[] { (darknetStatus <
AddressTracker.DONT_KNOW ? -1 : 1 ) * node.getDarknetPortNumber(),
+ (opennetStatus <
AddressTracker.DONT_KNOW ? -1 : 1 ) * om.crypto.portNumber };
}
}
}
Modified: trunk/freenet/src/freenet/node/LocationManager.java
===================================================================
--- trunk/freenet/src/freenet/node/LocationManager.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/node/LocationManager.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -10,8 +10,12 @@
import java.text.DateFormat;
import java.util.Date;
import java.util.Enumeration;
+import java.util.HashSet;
import java.util.Hashtable;
+import java.util.Iterator;
import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
import java.util.Vector;
import freenet.crypt.RandomSource;
@@ -345,7 +349,7 @@
}
registerKnownLocation(hisLoc);
- double[] hisFriendLocs = new double[hisBufLong.length-2];
+ double[] hisFriendLocs = new double[hisBufLong.length > 2 ?
hisBufLong.length-2 : 0];
for(int i=0;i<hisFriendLocs.length;i++) {
hisFriendLocs[i] = Double.longBitsToDouble(hisBufLong[i+2]);
if((hisFriendLocs[i] < 0.0) || (hisFriendLocs[i] > 1.0)) {
@@ -542,7 +546,7 @@
}
registerKnownLocation(hisLoc);
- double[] hisFriendLocs = new double[hisBufLong.length-2];
+ double[] hisFriendLocs = new double[hisBufLong.length > 2 ?
hisBufLong.length-2 : 0];
for(int i=0;i<hisFriendLocs.length;i++) {
hisFriendLocs[i] =
Double.longBitsToDouble(hisBufLong[i+2]);
if((hisFriendLocs[i] < 0.0) || (hisFriendLocs[i] > 1.0)) {
@@ -1217,20 +1221,28 @@
public void lostOrRestartedNode(PeerNode pn) {
Vector v = new Vector();
synchronized(recentlyForwardedIDs) {
- Enumeration e = recentlyForwardedIDs.keys();
- while(e.hasMoreElements()) {
- Long l = (Long)e.nextElement();
- RecentlyForwardedItem item =
(RecentlyForwardedItem)recentlyForwardedIDs.get(l);
+ Set entrySet = recentlyForwardedIDs.entrySet();
+ Iterator it = entrySet.iterator();
+ while (it.hasNext()) {
+ Map.Entry entry = (Map.Entry) it.next();
+ Long l = (Long) entry.getKey();
+
+ RecentlyForwardedItem item =
(RecentlyForwardedItem) entry.getValue();
+
if(item == null) {
Logger.error(this, "Key is "+l+" but no value on
recentlyForwardedIDs - shouldn't be possible");
continue;
}
if(item.routedTo != pn) continue;
if(item.successfullyForwarded) {
- removeRecentlyForwardedItem(item);
v.add(item);
}
}
+
+ // remove them
+ Iterator it2 = v.iterator();
+ while (it2.hasNext())
+
removeRecentlyForwardedItem((RecentlyForwardedItem) it2.next());
}
int dumped=v.size();
if (dumped!=0 && logMINOR)
Modified: trunk/freenet/src/freenet/node/MemoryChecker.java
===================================================================
--- trunk/freenet/src/freenet/node/MemoryChecker.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/node/MemoryChecker.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -47,7 +47,7 @@
ps.queueTimedJob(this, 120 * 250); // 30 sec
return;
} else
- ps.queueTimedJob(this, 120 * sleeptime);
+ ps.queueTimedJob(this, (long) 120 * sleeptime);
// FIXME
// Do not remove until all known memory issues fixed,
Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java 2008-04-14 15:55:20 UTC (rev
19325)
+++ trunk/freenet/src/freenet/node/Node.java 2008-04-14 16:00:44 UTC (rev
19326)
@@ -15,6 +15,7 @@
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.util.Arrays;
+import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -107,6 +108,7 @@
import freenet.support.LRUQueue;
import freenet.support.Logger;
import freenet.support.OOMHandler;
+import freenet.support.OOMHook;
import freenet.support.PooledExecutor;
import freenet.support.ShortBuffer;
import freenet.support.SimpleFieldSet;
@@ -124,7 +126,7 @@
/**
* @author amphibian
*/
-public class Node implements TimeSkewDetectorCallback, GetPubkey {
+public class Node implements TimeSkewDetectorCallback, GetPubkey, OOMHook {
private static boolean logMINOR;
@@ -475,7 +477,7 @@
* to the datastore only if it's from an insert, and we are a sink, but
when calculating whether
* we are a sink we ignore nodes which have less uptime (percentage)
than this parameter.
*/
- private static final int MIN_UPTIME_STORE_KEY = 40;
+ private static final int MIN_UPTIME_STORE_KEY = 0;
/**
* Read all storable settings (identity etc) from the node file.
@@ -1468,33 +1470,33 @@
System.out.println("Initializing CHK Datastore
("+maxStoreKeys+" keys)");
chkDatastore = new CHKStore();
BerkeleyDBFreenetStore.construct(storeDir, true,
suffix, maxStoreKeys, FreenetStore.TYPE_CHK,
- storeEnvironment, storeShutdownHook,
reconstructFile, chkDatastore);
+ storeEnvironment, storeShutdownHook,
reconstructFile, chkDatastore, random);
Logger.normal(this, "Initializing CHK Datacache");
System.out.println("Initializing CHK Datacache
("+maxCacheKeys+ ':' +maxCacheKeys+" keys)");
chkDatacache = new CHKStore();
BerkeleyDBFreenetStore.construct(storeDir, false,
suffix, maxCacheKeys, FreenetStore.TYPE_CHK,
- storeEnvironment, storeShutdownHook,
reconstructFile, chkDatacache);
+ storeEnvironment, storeShutdownHook,
reconstructFile, chkDatacache, random);
Logger.normal(this, "Initializing pubKey Datastore");
System.out.println("Initializing pubKey Datastore");
pubKeyDatastore = new PubkeyStore();
BerkeleyDBFreenetStore.construct(storeDir, true,
suffix, maxStoreKeys, FreenetStore.TYPE_PUBKEY,
- storeEnvironment, storeShutdownHook,
reconstructFile, pubKeyDatastore);
+ storeEnvironment, storeShutdownHook,
reconstructFile, pubKeyDatastore, random);
Logger.normal(this, "Initializing pubKey Datacache");
System.out.println("Initializing pubKey Datacache
("+maxCacheKeys+" keys)");
pubKeyDatacache = new PubkeyStore();
BerkeleyDBFreenetStore.construct(storeDir, false,
suffix, maxCacheKeys, FreenetStore.TYPE_PUBKEY,
- storeEnvironment, storeShutdownHook,
reconstructFile, pubKeyDatacache);
+ storeEnvironment, storeShutdownHook,
reconstructFile, pubKeyDatacache, random);
// FIXME can't auto-fix SSK stores.
Logger.normal(this, "Initializing SSK Datastore");
System.out.println("Initializing SSK Datastore");
sskDatastore = new SSKStore(this);
BerkeleyDBFreenetStore.construct(storeDir, true,
suffix, maxStoreKeys, FreenetStore.TYPE_SSK,
- storeEnvironment, storeShutdownHook,
reconstructFile, sskDatastore);
+ storeEnvironment, storeShutdownHook,
reconstructFile, sskDatastore, random);
Logger.normal(this, "Initializing SSK Datacache");
System.out.println("Initializing SSK Datacache
("+maxCacheKeys+" keys)");
sskDatacache = new SSKStore(this);
BerkeleyDBFreenetStore.construct(storeDir, false,
suffix, maxStoreKeys, FreenetStore.TYPE_SSK,
- storeEnvironment, storeShutdownHook,
reconstructFile, sskDatacache);
+ storeEnvironment, storeShutdownHook,
reconstructFile, sskDatacache, random);
} catch (FileNotFoundException e1) {
String msg = "Could not open datastore: "+e1;
Logger.error(this, msg, e1);
@@ -1620,6 +1622,8 @@
e.printStackTrace();
throw new
NodeInitException(NodeInitException.EXIT_COULD_NOT_START_UPDATER, "Could not
create Updater: "+e);
}
+
+ OOMHandler.addOOMHook(this);
Logger.normal(this, "Node constructor completed");
System.out.println("Node constructor completed");
@@ -1648,8 +1652,8 @@
}
Logger.normal(this, "Freenet 0.7 Build
#"+Version.buildNumber()+" r"+Version.cvsRevision);
System.out.println("Freenet 0.7 Build
#"+Version.buildNumber()+" r"+Version.cvsRevision);
- Logger.normal(this, "FNP port is on "+darknetCrypto.bindto+ ':'
+getDarknetPortNumber());
- System.out.println("FNP port is on "+darknetCrypto.bindto+ ':'
+getDarknetPortNumber());
+ Logger.normal(this, "FNP port is on
"+darknetCrypto.getBindTo()+ ':' +getDarknetPortNumber());
+ System.out.println("FNP port is on "+darknetCrypto.getBindTo()+
':' +getDarknetPortNumber());
// Start services
// SubConfig pluginManagerConfig = new SubConfig("pluginmanager3",
config);
@@ -3116,9 +3120,9 @@
*/
public synchronized boolean dontDetect() {
// Only return true if bindTo is set on all ports which are in
use
- if(!darknetCrypto.bindto.isRealInternetAddress(false, true,
false)) return false;
+ if(!darknetCrypto.getBindTo().isRealInternetAddress(false,
true, false)) return false;
if(opennet != null) {
- if(opennet.crypto.bindto.isRealInternetAddress(false,
true, false)) return false;
+
if(opennet.crypto.getBindTo().isRealInternetAddress(false, true, false)) return
false;
}
return true;
}
@@ -3266,4 +3270,23 @@
public void setDispatcherHook(NodeDispatcherCallback cb) {
this.dispatcher.setHook(cb);
}
+
+ /**
+ * Free some memory
+ */
+ public void handleOOM() throws Exception {
+ if (cachedPubKeys != null) {
+ Object value;
+ do {
+ value = cachedPubKeys.popKey();
+ } while (value != null);
+ }
+ if (recentlyCompletedIDs != null) {
+ synchronized (recentlyCompletedIDs) {
+ // half it size
+ while (recentlyCompletedIDs.size() >
MAX_RECENTLY_COMPLETED_IDS / 2)
+ recentlyCompletedIDs.pop();
+ }
+ }
+ }
}
Modified: trunk/freenet/src/freenet/node/NodeCrypto.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeCrypto.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/node/NodeCrypto.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -51,7 +51,6 @@
/** The object which handles our specific UDP port, pulls messages from
it, feeds them to the packet mangler for decryption etc */
UdpSocketHandler socket;
public FNPPacketMangler packetMangler;
- final FreenetInetAddress bindto;
// FIXME: abstract out address stuff? Possibly to something like
NodeReference?
final int portNumber;
byte[] myIdentity; // FIXME: simple identity block; should be unique
@@ -100,7 +99,7 @@
int port = config.getPort();
- bindto = config.getBindTo();
+ FreenetInetAddress bindto = config.getBindTo();
UdpSocketHandler u = null;
@@ -505,4 +504,12 @@
public boolean definitelyPortForwarded() {
return socket.getDetectedConnectivityStatus() ==
AddressTracker.DEFINITELY_PORT_FORWARDED;
}
+
+ public int getDetectedConnectivityStatus() {
+ return socket.getDetectedConnectivityStatus();
+ }
+
+ public FreenetInetAddress getBindTo() {
+ return config.getBindTo();
+ }
}
Modified: trunk/freenet/src/freenet/node/NodeIPPortDetector.java
===================================================================
--- trunk/freenet/src/freenet/node/NodeIPPortDetector.java 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/node/NodeIPPortDetector.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -43,18 +43,13 @@
* (for that port/NodeCrypto) list of IP addresses (still without port
numbers).
*/
FreenetInetAddress[] detectPrimaryIPAddress() {
- FreenetInetAddress[] addresses =
ipDetector.detectPrimaryIPAddress();
- FreenetInetAddress addr = crypto.bindto;
+ FreenetInetAddress addr = crypto.getBindTo();
if(addr.isRealInternetAddress(false, true, false)) {
- for(int i=0;i<addresses.length;i++) {
- if(addresses[i] == addr) return addresses;
- }
- FreenetInetAddress[] newAddresses = new
FreenetInetAddress[addresses.length+1];
- System.arraycopy(addresses, 0, newAddresses, 0,
addresses.length);
- newAddresses[addresses.length] = addr;
- return newAddresses;
+ // Binding to a real internet address => don't want us
to use the others, most likely
+ // he is on a multi-homed box where only one IP can be
used for Freenet.
+ return new FreenetInetAddress[] { addr };
}
- return addresses;
+ return ipDetector.detectPrimaryIPAddress();
}
/**
@@ -82,7 +77,8 @@
if((p == null) || p.isNull()) continue;
// DNSRequester doesn't deal with our own node
if(!IPUtil.isValidAddress(p.getAddress(true),
false)) continue;
- Logger.normal(this, "Peer
"+peerList[i].getPeer()+" thinks we are "+p);
+ if(Logger.shouldLog(Logger.MINOR, this))
+ Logger.minor(this, "Peer
"+peerList[i].getPeer()+" thinks we are "+p);
if(countsByPeer.containsKey(p)) {
Integer count = (Integer)
countsByPeer.get(p);
Integer newCount = new
Integer(count.intValue()+1);
Modified: trunk/freenet/src/freenet/node/OpennetManager.java
===================================================================
--- trunk/freenet/src/freenet/node/OpennetManager.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/node/OpennetManager.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -415,7 +415,7 @@
successCount++;
if(peersLRU.contains(pn)) {
peersLRU.push(pn);
- Logger.normal(this, "Opennet peer "+pn+"
promoted to top of LRU because of successful request");
+ if(logMINOR) Logger.minor(this, "Opennet peer
"+pn+" promoted to top of LRU because of successful request");
return;
} else {
if(logMINOR) Logger.minor(this, "Success on
opennet peer which isn't in the LRU!: "+pn, new Exception("debug"));
Modified: trunk/freenet/src/freenet/node/PacketSender.java
===================================================================
--- trunk/freenet/src/freenet/node/PacketSender.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/node/PacketSender.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -385,7 +385,7 @@
lastClearedOldSwapChains = now;
}
- long oldNow = System.currentTimeMillis();
+ long oldNow = now;
// Send may have taken some time
now = System.currentTimeMillis();
Modified: trunk/freenet/src/freenet/node/PeerManager.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerManager.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/node/PeerManager.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -319,7 +319,8 @@
connectedPeers = newConnectedPeers;
// removing from myPeers
- PeerNode[] newMyPeers = new PeerNode[myPeers.length-1];
+ int myPeerLength = myPeers.length;
+ PeerNode[] newMyPeers = new PeerNode[myPeerLength > 1 ?
myPeerLength-1 : 0];
int positionInNewArray = 0;
for(int i=0;i<myPeers.length;i++) {
if(myPeers[i]!=pn){
Modified: trunk/freenet/src/freenet/node/PeerNode.java
===================================================================
--- trunk/freenet/src/freenet/node/PeerNode.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/node/PeerNode.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -817,7 +817,6 @@
}
if(logMINOR)
Logger.minor(this, "Updating handshake IPs for peer '"
+ shortToString() + "' (" + ignoreHostnames + ')');
- Peer[] localHandshakeIPs;
Peer[] myNominalPeer;
// Don't synchronize while doing lookups which may take a long
time!
@@ -825,9 +824,9 @@
myNominalPeer = (Peer[]) nominalPeer.toArray(new
Peer[nominalPeer.size()]);
}
+ Peer[] localHandshakeIPs;
if(myNominalPeer.length == 0) {
if(localDetectedPeer == null) {
- localHandshakeIPs = null;
synchronized(this) {
handshakeIPs = null;
}
@@ -2266,7 +2265,7 @@
try {
simpleVersion =
Version.getArbitraryBuildNumber(version);
} catch (VersionParseException e) {
- Logger.error(this, "Bad version:
"+simpleVersion+" : "+e, e);
+ Logger.error(this, "Bad version: " +
version + " : " + e, e);
}
}
Version.seenVersion(newVersion);
@@ -3638,8 +3637,9 @@
}
public synchronized boolean completedAnnounce(long uid) {
- if(runningAnnounceUIDs.length == 0) return false;
- long[] newList = new long[runningAnnounceUIDs.length - 1];
+ final int runningAnnounceUIDsLength =
runningAnnounceUIDs.length;
+ if(runningAnnounceUIDsLength < 1) return false;
+ long[] newList = new long[runningAnnounceUIDsLength - 1];
int x = 0;
for(int i=0;i<runningAnnounceUIDs.length;i++) {
if(i == runningAnnounceUIDs.length) return false;
Modified: trunk/freenet/src/freenet/node/UptimeEstimator.java
===================================================================
--- trunk/freenet/src/freenet/node/UptimeEstimator.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/node/UptimeEstimator.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -101,7 +101,7 @@
if(slot == wasOnline.length) slot = 0;
}
long now = System.currentTimeMillis();
- if(logFile.length() > wasOnline.length*4) {
+ if(logFile.length() > (long) wasOnline.length*4) {
prevFile.delete();
logFile.renameTo(prevFile);
}
Modified: trunk/freenet/src/freenet/node/fcp/ClientGet.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientGet.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/node/fcp/ClientGet.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -415,6 +415,7 @@
if(!dontFree)
data.free();
finish();
+ client.notifySuccess(this);
}
private void trySendDataFoundOrGetFailed(FCPConnectionOutputHandler
handler) {
@@ -496,6 +497,7 @@
Logger.minor(this, "Caught "+e, e);
trySendDataFoundOrGetFailed(null);
finish();
+ client.notifyFailure(this);
if(persistenceType != PERSIST_CONNECTION)
client.server.forceStorePersistentRequests();
}
Modified: trunk/freenet/src/freenet/node/fcp/ClientPutBase.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPutBase.java 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/node/fcp/ClientPutBase.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -141,6 +141,7 @@
freeData();
finish();
trySendFinalMessage(null);
+ client.notifySuccess(this);
if(persistenceType != PERSIST_CONNECTION)
client.server.forceStorePersistentRequests();
}
@@ -154,6 +155,7 @@
freeData();
finish();
trySendFinalMessage(null);
+ client.notifyFailure(this);
if(persistenceType != PERSIST_CONNECTION)
client.server.forceStorePersistentRequests();
}
Modified: trunk/freenet/src/freenet/node/fcp/ClientPutComplexDirMessage.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/ClientPutComplexDirMessage.java
2008-04-14 15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/node/fcp/ClientPutComplexDirMessage.java
2008-04-14 16:00:44 UTC (rev 19326)
@@ -9,6 +9,7 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
+import java.util.Map;
import freenet.client.async.ManifestElement;
import freenet.node.Node;
@@ -151,10 +152,11 @@
* HashMap's containing ManifestElement's.
*/
private void convertFilesByNameToManifestElements(HashMap filesByName,
HashMap manifestElements, Node node) throws MessageInvalidException {
- Iterator i = filesByName.keySet().iterator();
+ Iterator i = filesByName.entrySet().iterator();
while(i.hasNext()) {
- String tempName = (String) (i.next());
- Object val = filesByName.get(tempName);
+ Map.Entry entry = (Map.Entry) i.next();
+ String tempName = (String) entry.getKey();
+ Object val = entry.getValue();
if(val instanceof HashMap) {
HashMap h = (HashMap) val;
HashMap manifests = new HashMap();
Modified: trunk/freenet/src/freenet/node/fcp/FCPClient.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/FCPClient.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/node/fcp/FCPClient.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -18,7 +18,7 @@
*/
public class FCPClient {
- public FCPClient(String name2, FCPServer server, FCPConnectionHandler
handler, boolean isGlobalQueue) {
+ public FCPClient(String name2, FCPServer server, FCPConnectionHandler
handler, boolean isGlobalQueue, RequestCompletionCallback cb) {
this.name = name2;
if(name == null) throw new NullPointerException();
this.currentConnection = handler;
@@ -35,6 +35,7 @@
watchGlobalVerbosityMask = Integer.MAX_VALUE;
toStart = new LinkedList();
lowLevelClient = this;
+ completionCallback = cb;
}
/** The client's Name sent in the ClientHello message */
@@ -66,6 +67,7 @@
private final LinkedList toStart;
/** Low-level client object, for freenet.client.async. Normally ==
this. */
final Object lowLevelClient;
+ private RequestCompletionCallback completionCallback;
public synchronized FCPConnectionHandler getConnection() {
return currentConnection;
@@ -254,4 +256,27 @@
public String toString() {
return super.toString()+ ':' +name;
}
+
+ /**
+ * Callback called when a request succeeds.
+ */
+ public void notifySuccess(ClientRequest req) {
+ if(completionCallback != null)
+ completionCallback.notifySuccess(req);
+ }
+
+ /**
+ * Callback called when a request fails
+ * @param get
+ */
+ public void notifyFailure(ClientRequest req) {
+ if(completionCallback != null)
+ completionCallback.notifyFailure(req);
+ }
+
+ public synchronized RequestCompletionCallback
setRequestCompletionCallback(RequestCompletionCallback cb) {
+ RequestCompletionCallback old = completionCallback;
+ completionCallback = cb;
+ return old;
+ }
}
Modified: trunk/freenet/src/freenet/node/fcp/FCPServer.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/FCPServer.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/node/fcp/FCPServer.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -119,7 +119,7 @@
defaultFetchContext = client.getFetchContext();
defaultInsertContext = client.getInsertContext(false);
- globalClient = new FCPClient("Global Queue", this, null, true);
+ globalClient = new FCPClient("Global Queue", this, null, true,
null);
logMINOR = Logger.shouldLog(Logger.MINOR, this);
@@ -517,7 +517,7 @@
oldClient = (FCPClient) clientsByName.get(name);
if(oldClient == null) {
// Create new client
- FCPClient client = new FCPClient(name, this,
handler, false);
+ FCPClient client = new FCPClient(name, this,
handler, false, null);
clientsByName.put(name, client);
return client;
} else {
@@ -681,9 +681,10 @@
gis = new GZIPInputStream(fis);
bis = new BufferedInputStream(gis);
Logger.normal(this, "Loading persistent requests from
"+file);
- if(file.length() > 0)
+ if (file.length() > 0) {
loadPersistentRequests(bis);
- else
+ haveLoadedPersistentRequests = true;
+ } else
throw new IOException("File empty"); // If it's
empty, try the temp file.
} catch (IOException e) {
Logger.error(this, "IOE : " + e.getMessage(), e);
@@ -696,6 +697,7 @@
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
loadPersistentRequests(bis);
+ haveLoadedPersistentRequests = true;
} catch (IOException e1) {
Logger.normal(this, "It's corrupted too : Not
reading any persistent requests from disk: "+e1);
return;
@@ -899,4 +901,9 @@
return hasFinishedStart;
}
+ public void setCompletionCallback(RequestCompletionCallback cb) {
+ if(globalClient.setRequestCompletionCallback(cb) != null)
+ Logger.error(this, "Replacing request completion
callback "+cb, new Exception("error"));
+ }
+
}
Modified: trunk/freenet/src/freenet/node/fcp/PersistentPutDir.java
===================================================================
--- trunk/freenet/src/freenet/node/fcp/PersistentPutDir.java 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/node/fcp/PersistentPutDir.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -86,7 +86,7 @@
} else if(data instanceof FileBucket) {
subset.putSingle("UploadFrom", "disk");
subset.putSingle("Filename",
((FileBucket)data).getFile().getPath());
- } else if((data instanceof
PaddedEphemerallyEncryptedBucket) || (data == null)) {
+ } else if (data instanceof
PaddedEphemerallyEncryptedBucket) {
subset.putSingle("UploadFrom",
"direct");
} else {
throw new IllegalStateException("Don't
know what to do with bucket: "+data);
Copied: trunk/freenet/src/freenet/node/fcp/RequestCompletionCallback.java (from
rev 19322, trunk/freenet/src/freenet/node/fcp/RequestCompletionCallback.java)
===================================================================
--- trunk/freenet/src/freenet/node/fcp/RequestCompletionCallback.java
(rev 0)
+++ trunk/freenet/src/freenet/node/fcp/RequestCompletionCallback.java
2008-04-14 16:00:44 UTC (rev 19326)
@@ -0,0 +1,15 @@
+package freenet.node.fcp;
+
+public interface RequestCompletionCallback {
+
+ /**
+ * Callback called when a request succeeds.
+ */
+ public void notifySuccess(ClientRequest req);
+
+ /**
+ * Callback called when a request fails
+ */
+ public void notifyFailure(ClientRequest req);
+
+}
Modified: trunk/freenet/src/freenet/node/updater/NodeUpdater.java
===================================================================
--- trunk/freenet/src/freenet/node/updater/NodeUpdater.java 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/node/updater/NodeUpdater.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -29,7 +29,6 @@
private FetchContext ctx;
private FetchResult result;
private ClientGetter cg;
- private boolean finalCheck;
private FreenetURI URI;
private final Ticker ticker;
public final NodeClientCore core;
@@ -297,10 +296,6 @@
return URI;
}
- public boolean inFinalCheck() {
- return finalCheck;
- }
-
public void onMajorProgress() {
// Ignore
}
Modified: trunk/freenet/src/freenet/node/useralerts/OpennetUserAlert.java
===================================================================
--- trunk/freenet/src/freenet/node/useralerts/OpennetUserAlert.java
2008-04-14 15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/node/useralerts/OpennetUserAlert.java
2008-04-14 16:00:44 UTC (rev 19326)
@@ -9,12 +9,12 @@
private final Node node;
public OpennetUserAlert(Node node) {
- super(true, L10n.getString("OpennetUserAlert.warningTitle"),
L10n.getString("OpennetUserAlert.warning"), new HTMLNode("#",
L10n.getString("OpennetUserAlert.warning")), UserAlert.WARNING, false,
L10n.getString("UserAlert.hide"), false, null);
+ super(true, L10n.getString("OpennetUserAlert.warningTitle"),
L10n.getString("OpennetUserAlert.warning"), new HTMLNode("#",
L10n.getString("OpennetUserAlert.warning")), UserAlert.WARNING, true,
L10n.getString("UserAlert.hide"), false, null);
this.node = node;
}
public boolean isValid() {
- return node.isOpennetEnabled();
+ return node.isOpennetEnabled() && valid;
}
}
Modified: trunk/freenet/src/freenet/node/useralerts/UserAlertManager.java
===================================================================
--- trunk/freenet/src/freenet/node/useralerts/UserAlertManager.java
2008-04-14 15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/node/useralerts/UserAlertManager.java
2008-04-14 16:00:44 UTC (rev 19326)
@@ -64,7 +64,7 @@
}
public UserAlert[] getAlerts() {
- UserAlert[] a = null;
+ UserAlert[] a;
synchronized (alerts) {
a = (UserAlert[]) alerts.toArray(new
UserAlert[alerts.size()]);
}
Copied: trunk/freenet/src/freenet/pluginmanager/FredPluginVersioned.java (from
rev 19322, trunk/freenet/src/freenet/pluginmanager/FredPluginVersioned.java)
===================================================================
--- trunk/freenet/src/freenet/pluginmanager/FredPluginVersioned.java
(rev 0)
+++ trunk/freenet/src/freenet/pluginmanager/FredPluginVersioned.java
2008-04-14 16:00:44 UTC (rev 19326)
@@ -0,0 +1,10 @@
+package freenet.pluginmanager;
+
+/**
+ * A Fred plugin that has a version
+ * @author dbkr
+ *
+ */
+public interface FredPluginVersioned {
+ public String getVersion();
+}
Modified: trunk/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java
===================================================================
--- trunk/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java
2008-04-14 15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java
2008-04-14 16:00:44 UTC (rev 19326)
@@ -3,6 +3,7 @@
import java.util.Date;
import java.util.HashSet;
+import freenet.l10n.L10n;
import freenet.support.Logger;
import freenet.support.StringArray;
@@ -21,11 +22,11 @@
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;
- //public String
public PluginInfoWrapper(FredPlugin plug, String filename) {
this.plug = plug;
@@ -41,6 +42,7 @@
isPortForwardPlugin = (plug instanceof FredPluginPortForward);
isMultiplePlugin = (plug instanceof FredPluginMultiple);
isFCPPlugin = (plug instanceof FredPluginFCP);
+ isVersionedPlugin = (plug instanceof FredPluginVersioned);
}
void setThread(Thread ps) {
@@ -66,6 +68,14 @@
return plug.getClass().getName();
}
+ public String getPluginVersion() {
+ if (isVersionedPlugin) {
+ return ((FredPluginVersioned)plug).getVersion();
+ } else {
+ return L10n.getString("PproxyToadlet.noVersion");
+ }
+ }
+
public synchronized String[] getPluginToadletSymlinks(){
return StringArray.toArray(toadletLinks.toArray());
}
Modified: trunk/freenet/src/freenet/pluginmanager/PluginManager.java
===================================================================
--- trunk/freenet/src/freenet/pluginmanager/PluginManager.java 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/pluginmanager/PluginManager.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -263,7 +263,7 @@
File pluginDirectory = new File(node.getNodeDir(), "plugins");
if (lastSlash == -1) {
/* it's an official plugin! */
- pluginFile = new File(pluginDirectory,
pluginSpecification + ".jar.url");
+ pluginFile = new File(pluginDirectory,
pluginSpecification + ".jar");
} else {
pluginFile = new File(pluginDirectory,
pluginSpecification.substring(lastSlash + 1));
}
@@ -491,6 +491,11 @@
/* get plugin filename. */
String completeFilename = pluginUrl.getPath();
String filename =
completeFilename.substring(completeFilename.lastIndexOf('/') + 1);
+ // The URL to the JAR file might end with .url because of the
insane download server that redirects to a JAR file
+ // in response to a request for a file ending '.url'. Strip it
off if so, since we want our JAR to end with '.jar'.
+ if (filename.endsWith(".url")) {
+ filename = filename.substring(0, filename.length() - 4);
+ }
pluginFile = new File(pluginDirectory, filename);
/* check if file needs to be downloaded. */
Modified: trunk/freenet/src/freenet/store/BerkeleyDBFreenetStore.java
===================================================================
--- trunk/freenet/src/freenet/store/BerkeleyDBFreenetStore.java 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/store/BerkeleyDBFreenetStore.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -30,12 +30,16 @@
import com.sleepycat.je.Transaction;
import com.sleepycat.je.log.DbChecksumException;
import com.sleepycat.je.log.LogFileNotFoundException;
+
+import freenet.crypt.RandomSource;
import freenet.keys.KeyVerifyException;
import freenet.node.NodeInitException;
import freenet.node.SemiOrderedShutdownHook;
import freenet.support.Fields;
import freenet.support.HexUtil;
import freenet.support.Logger;
+import freenet.support.OOMHandler;
+import freenet.support.OOMHook;
import freenet.support.SortedLongSet;
/**
@@ -46,7 +50,7 @@
* @author tubbie
* @author amphibian
*/
-public class BerkeleyDBFreenetStore implements FreenetStore {
+public class BerkeleyDBFreenetStore implements FreenetStore, OOMHook {
private static boolean logMINOR;
private static boolean logDEBUG;
@@ -55,6 +59,7 @@
private final File reconstructFile;
private final int dataBlockSize;
private final int headerBlockSize;
+ private final RandomSource random;
private final Environment environment;
private final TupleBinding storeBlockTupleBinding;
@@ -98,7 +103,7 @@
public static FreenetStore construct(File baseStoreDir, boolean
isStore, String suffix,
long maxStoreKeys, short type,
Environment storeEnvironment, SemiOrderedShutdownHook
storeShutdownHook, File reconstructFile,
- StoreCallback callback) throws DatabaseException,
IOException {
+ StoreCallback callback, RandomSource random) throws
DatabaseException, IOException {
// Location of new store file
String newStoreFileName = typeName(type) + suffix + '.' +
(isStore ? "store" : "cache");
File newStoreFile = new File(baseStoreDir, newStoreFileName);
@@ -116,17 +121,17 @@
System.err.println("Opening database using "+newStoreFile);
return openStore(storeEnvironment, newDBPrefix, newStoreFile,
lruFile, keysFile, newFixSecondaryFile, maxStoreKeys, storeShutdownHook,
- reconstructFile, callback);
+ reconstructFile, callback, random);
}
private static FreenetStore openStore(Environment storeEnvironment,
String newDBPrefix, File newStoreFile, File lruFile,
File keysFile, File newFixSecondaryFile, long
maxStoreKeys, SemiOrderedShutdownHook storeShutdownHook,
- File reconstructFile, StoreCallback callback) throws
DatabaseException, IOException {
+ File reconstructFile, StoreCallback callback,
RandomSource random) throws DatabaseException, IOException {
try {
// First try just opening it.
return new BerkeleyDBFreenetStore(storeEnvironment,
newDBPrefix, newStoreFile, lruFile, keysFile, newFixSecondaryFile,
maxStoreKeys, false, storeShutdownHook,
reconstructFile,
- callback);
+ callback, random);
} catch (DatabaseException e) {
// Try a reconstruct
@@ -140,7 +145,7 @@
// Reconstruct
return new BerkeleyDBFreenetStore(storeEnvironment,
newDBPrefix, newStoreFile, lruFile, keysFile, newFixSecondaryFile,
- maxStoreKeys, storeShutdownHook,
reconstructFile, callback);
+ maxStoreKeys, storeShutdownHook,
reconstructFile, callback, random);
}
}
@@ -167,7 +172,8 @@
* @param lruFile
* LRU data file, flat file store for recovery
* @param keysFile
- * Keys data file, flat file store for recvoery
+ * Keys data file, flat file store for recovery, created
only if
+ * <code>callback.storeFullKeys()</code> is <code>true</code>
* @param fixSecondaryFile
* Flag file. Created when secondary database error occur. If
* this file exist on start, delete it and recreate the
secondary
@@ -189,10 +195,11 @@
private BerkeleyDBFreenetStore(Environment env, String prefix, File
storeFile, File lruFile, File keysFile,
File fixSecondaryFile, long maxChkBlocks, boolean wipe,
SemiOrderedShutdownHook storeShutdownHook,
File reconstructFile,
- StoreCallback callback) throws IOException,
DatabaseException {
+ StoreCallback callback, RandomSource random) throws
IOException, DatabaseException {
logMINOR = Logger.shouldLog(Logger.MINOR, this);
logDEBUG = Logger.shouldLog(Logger.DEBUG, this);
+ this.random = random;
this.environment = env;
this.name = prefix;
this.fixSecondaryFile = fixSecondaryFile;
@@ -204,6 +211,8 @@
this.headerBlockSize = callback.headerLength();
this.keyLength = callback.fullKeyLength();
callback.setStore(this);
+
+ OOMHandler.addOOMHook(this);
this.freeBlocks = new SortedLongSet();
@@ -325,7 +334,7 @@
private long checkForHoles(long blocksInFile, boolean dontTruncate)
throws DatabaseException {
System.err.println("Checking for holes in database...
"+blocksInFile+" blocks in file");
- WrapperManager.signalStarting((int)Math.min(Integer.MAX_VALUE,
5*60*1000 + blocksInFile*100)); // 10/sec
+ WrapperManager.signalStarting((int) Math.min(Integer.MAX_VALUE,
5 * 60 * 1000 + blocksInFile * 100L)); // 10/sec
long holes = 0;
long maxPresent = 0;
freeBlocks.clear();
@@ -444,7 +453,7 @@
if(!dontCheckForHoles)
checkForHoles(maxBlocksInStore, true);
- WrapperManager.signalStarting((int)(Math.min(Integer.MAX_VALUE,
5*60*1000 + blocksInStore * 100))); // 10 per second
+ WrapperManager.signalStarting((int)
(Math.min(Integer.MAX_VALUE, 5 * 60 * 1000 + blocksInStore * 100L))); // 10 per
second
long realSize = countCHKBlocksFromFile();
@@ -509,7 +518,7 @@
}
x++;
if(x % 1024 == 0) {
- System.out.println("Reading
store prior to shrink: "+(x*100/realSize)+ "% ( "+x+ '/' +realSize+ ')');
+ System.out.println("Reading
store prior to shrink: "+((long)x*100/realSize)+ "% ( "+x+ '/' +realSize+ ')');
}
if(x == Integer.MAX_VALUE) {
System.err.println("Key number
"+x+" - ignoring store after "+(x*(dataBlockSize+headerBlockSize)+" bytes"));
@@ -675,8 +684,12 @@
System.out.println("Completing shrink"); // FIXME remove
int totalUnwantedBlocks =
unwantedMoveNums.length+freeEarlySlots.length;
- WrapperManager.signalStarting(Math.min(Integer.MAX_VALUE,
5*60*1000 + (totalUnwantedBlocks-wantedMoveNums.length) * 100));
+ WrapperManager.signalStarting((int) Math.min(Integer.MAX_VALUE,
5*60*1000 + (totalUnwantedBlocks-wantedMoveNums.length) * 100L));
// If there are any slots left over, they must be free.
+
+ // FIXME put these into the database as we do in reconstruct().
+ // Not doing that now as its not immediately obvious how to
deal with it...
+
freeBlocks.clear();
t = environment.beginTransaction(null,null);
for(int i=wantedMoveNums.length;i<totalUnwantedBlocks;i++) {
@@ -760,7 +773,7 @@
try {
String msg = "Shrinking store: "+curBlocks+" ->
"+maxBlocks+" (from db "+keysDB.count()+", highest
"+highestBlockNumberInDatabase()+", from file "+countCHKBlocksFromFile()+ ')';
System.err.println(msg); Logger.normal(this, msg);
-
WrapperManager.signalStarting((int)Math.min(Integer.MAX_VALUE, (5*60*1000 + 100
* (Math.max(0, curBlocks-maxBlocks)))));
+
WrapperManager.signalStarting((int)Math.min(Integer.MAX_VALUE, (5*60*1000 +
100L * (Math.max(0, curBlocks-maxBlocks)))));
while(true) {
t = environment.beginTransaction(null,null);
long deleted = 0;
@@ -854,9 +867,9 @@
*/
private BerkeleyDBFreenetStore(Environment env, String prefix, File
storeFile, File lruFile, File keysFile,
File fixSecondaryFile, long maxChkBlocks,
SemiOrderedShutdownHook storeShutdownHook, File reconstructFile,
- StoreCallback callback) throws DatabaseException,
IOException {
+ StoreCallback callback, RandomSource random) throws
DatabaseException, IOException {
this(env, prefix, storeFile, lruFile, keysFile,
fixSecondaryFile, maxChkBlocks, true, storeShutdownHook,
- reconstructFile, callback);
+ reconstructFile, callback, random);
}
private static void wipeOldDatabases(Environment env, String prefix) {
@@ -880,12 +893,51 @@
}
}
+ /**
+ * Reconstruct the database using flat file stores and other dark magic.
+ *
+ * <strong>You are not expected to understand this.</strong>
+ *
+ * <dl>
+ * <dt>header + data</dt>
+ * <dd>read from storeRAF, always available.</dd>
+ *
+ * <dt>fullKey</dt>
+ * <dd>read from keyRAF, maybe null.</dd>
+ *
+ * <dt>routingkey </dt>
+ * <dd>
+ * <ol>
+ * <li><code>callback.routingKeyFromFullKey(); </code></li>
+ * <li>if <code>null</code> or <code>KeyVerifyException</code>,<code>
callback.construct().getRoutingKey()</code>,
+ * may throw <code>KeyVerifyException</code></li>
+ * <ol>
+ * <code>fullKey</code> (and hence
+ * <code>callback.routingKeyFromFullKey(); </code>) may be phantom,
hence
+ * we must verify
+ * <code> callback.construct().getRoutingKey() == routingkey </code> on
+ * <code>fetch()</code> </dd>
+ * </dl>
+ *
+ * On <code>OperationStatus.KEYEXIST</code> or bad
+ * <code> callback.construct</code>:
+ * <ol>
+ * <li>insert a database entry with random key, (minimum lru - 1); </li>
+ * <li>if <code>op != OperationStatus.SUCCESS</code>,
+ * <code>addFreeBlock()</code>.</li>
+ * </ol>
+ *
+ *
+ * @throws DatabaseException
+ * @throws IOException
+ */
private void reconstruct() throws DatabaseException, IOException {
if(keysDB.count() != 0)
throw new IllegalStateException("Store must be empty
before reconstruction!");
System.err.println("Reconstructing store index from store file:
callback="+callback);
Logger.error(this, "Reconstructing store index from store file:
callback="+callback);
- WrapperManager.signalStarting((int)(Math.min(Integer.MAX_VALUE,
5*60*1000+(storeRAF.length()/(dataBlockSize+headerBlockSize))*1000)));
+ WrapperManager.signalStarting((int)
(Math.min(Integer.MAX_VALUE, 5 * 60 * 1000
+ + (storeRAF.length() / (dataBlockSize +
headerBlockSize)) * 1000L)));
// Reusing the buffer is safe, provided we don't do anything
with the resulting StoreBlock.
byte[] header = new byte[headerBlockSize];
byte[] data = new byte[dataBlockSize];
@@ -894,7 +946,20 @@
long dupes = 0;
long failures = 0;
long expectedLength =
storeRAF.length()/(dataBlockSize+headerBlockSize);
+ // Find minimum and maximum LRU.
+ long minLRU = Long.MAX_VALUE;
+ long maxLRU = Long.MIN_VALUE;
try {
+ lruRAF.seek(0);
+ for(long i=0;i<lruRAF.length()/8;i++) {
+ long lru = lruRAF.readLong();
+ if(lru > maxLRU) maxLRU = lru;
+ if(lru < minLRU) minLRU = lru;
+ }
+ } catch (IOException e) {
+ // We don't want this to be fatal...
+ }
+ try {
storeRAF.seek(0);
lruRAF.seek(0);
long lruRAFLength = lruRAF.length();
@@ -939,18 +1004,41 @@
}
try {
byte[] routingkey = null;
- try {
- StorableBlock block =
callback.construct(data, header, null, readKey ? keyBuf : null);
- routingkey =
block.getRoutingKey();
- } catch (KeyVerifyException e) {
- String err = "Bogus or
unreconstructible key at slot "+l+" : "+e+" - lost block "+l;
- Logger.error(this, err, e);
- System.err.println(err);
- addFreeBlock(l, true, "can't
reconsturct key ("+callback+ ')');
- routingkey = null;
- failures++;
- continue;
+ if(keyBuf != null &&
!isAllNull(keyBuf)) {
+ routingkey =
callback.routingKeyFromFullKey(keyBuf);
+ if(routingkey == keyBuf) {
+ // Copy it.
+ byte[] newkey = new
byte[routingkey.length];
+
System.arraycopy(routingkey, 0, newkey, 0, routingkey.length);
+ routingkey = newkey;
+ }
}
+ if(routingkey == null) {
+ try {
+ StorableBlock block =
callback.construct(data, header, null, readKey ? keyBuf : null);
+ routingkey =
block.getRoutingKey();
+ } catch (KeyVerifyException e) {
+ String err = "Bogus or
unreconstructible key at slot "+l+" : "+e+" - lost block "+l;
+ Logger.error(this, err,
e);
+ System.err.println(err);
+ failures++;
+ t =
environment.beginTransaction(null,null);
+ StoreBlock storeBlock =
new StoreBlock(l, --minLRU);
+ byte[] buf = new
byte[32];
+ random.nextBytes(buf);
+ DatabaseEntry
routingkeyDBE = new DatabaseEntry(buf);
+ DatabaseEntry blockDBE
= new DatabaseEntry();
+
storeBlockTupleBinding.objectToEntry(storeBlock, blockDBE);
+ OperationStatus op =
keysDB.putNoOverwrite(t,routingkeyDBE,blockDBE);
+ if(op !=
OperationStatus.SUCCESS) {
+
Logger.error(this, "Impossible operation status inserting bogus key to LRU:
"+op);
+ addFreeBlock(l,
true, "Impossible to add (invalid) to LRU: "+op);
+ }
+ t.commitNoSync();
+ t = null;
+ continue;
+ }
+ }
t =
environment.beginTransaction(null,null);
StoreBlock storeBlock = new
StoreBlock(l, lruVal);
DatabaseEntry routingkeyDBE = new
DatabaseEntry(routingkey);
@@ -958,8 +1046,23 @@
storeBlockTupleBinding.objectToEntry(storeBlock, blockDBE);
OperationStatus op =
keysDB.putNoOverwrite(t,routingkeyDBE,blockDBE);
if(op == OperationStatus.KEYEXIST) {
- addFreeBlock(l, true,
"duplicate");
+ Logger.error(this, "Duplicate
block: "+l);
+ System.err.println("Duplicate
block: "+l);
dupes++;
+ storeBlock = new StoreBlock(l,
--minLRU);
+ byte[] buf = new byte[32];
+ random.nextBytes(buf);
+ routingkeyDBE = new
DatabaseEntry(buf);
+ blockDBE = new DatabaseEntry();
+
storeBlockTupleBinding.objectToEntry(storeBlock, blockDBE);
+ op =
keysDB.putNoOverwrite(t,routingkeyDBE,blockDBE);
+ if(op !=
OperationStatus.SUCCESS) {
+ Logger.error(this,
"Impossible operation status inserting bogus key to LRU: "+op);
+ addFreeBlock(l, true,
"Impossible to add (dupe) to LRU: "+op);
+ }
+ t.commitNoSync();
+ t = null;
+ continue;
} else if(op !=
OperationStatus.SUCCESS) {
addFreeBlock(l, true, "failure:
"+op);
failures++;
@@ -996,6 +1099,12 @@
}
}
+ private boolean isAllNull(byte[] buf) {
+ for(int i=0;i<buf.length;i++)
+ if(buf[i] != 0) return false;
+ return true;
+ }
+
private int runningFetches;
/**
@@ -1066,6 +1175,56 @@
block = callback.construct(data, header,
routingkey, fullKey);
+ if(!Arrays.equals(block.getRoutingKey(),
routingkey)) {
+
+ synchronized(this) {
+ misses++;
+ }
+
+ keysDB.delete(t, routingkeyDBE);
+
+ // Insert the block into the index.
+ // Set the LRU to minimum - 1.
+
+ long lru = getMinRecentlyUsed(t) - 1;
+
+ Logger.normal(this, "Does not verify
(not the expected key), setting accessTime to "+lru+" for :
"+HexUtil.bytesToHex(routingkey));
+
+ storeBlock = new
StoreBlock(storeBlock.offset, lru);
+
+ routingkeyDBE = new
DatabaseEntry(block.getRoutingKey());
+
+ blockDBE = new DatabaseEntry();
+
storeBlockTupleBinding.objectToEntry(storeBlock, blockDBE);
+ try {
+
keysDB.put(t,routingkeyDBE,blockDBE);
+ synchronized(storeRAF) {
+ if(keysRAF != null) {
+
keysRAF.seek(storeBlock.offset * keyLength);
+
keysRAF.write(fullKey);
+ if(logDEBUG)
+
Logger.debug(this, "Written full key length "+fullKey.length+" to block
"+storeBlock.offset+" at "+(storeBlock.offset * keyLength)+" for "+callback);
+ } else if(logDEBUG) {
+
Logger.debug(this, "Not writing full key length "+fullKey.length+" for block
"+storeBlock.offset+" for "+callback);
+ }
+ }
+ } catch (DatabaseException e) {
+ Logger.error(this, "Caught
database exception "+e+" while replacing element");
+ addFreeBlock(storeBlock.offset,
true, "Bogus key");
+ c.close();
+ c = null;
+ t.commit();
+ t = null;
+ return null;
+ }
+ Logger.normal(this, "Successfully
replaced entry at block number "+storeBlock.offset+" lru "+lru);
+ c.close();
+ c = null;
+ t.commit();
+ t = null;
+ return null;
+ }
+
if(!dontPromote) {
storeBlock.updateRecentlyUsed();
DatabaseEntry updateDBE = new
DatabaseEntry();
@@ -1093,15 +1252,51 @@
} catch(KeyVerifyException ex) {
Logger.normal(this, "Does not verify ("+ex+"),
setting accessTime to 0 for : "+HexUtil.bytesToHex(routingkey), ex);
+ synchronized(this) {
+ misses++;
+ }
+ synchronized(storeRAF) {
+ // Clear the key in the keys file.
+ byte[] buf = new byte[fullKey.length];
+ for(int i=0;i<buf.length;i++) buf[i] =
0; // FIXME unnecessary?
+ if(keysRAF != null) {
+ keysRAF.seek(storeBlock.offset
* keyLength);
+ keysRAF.write(buf);
+ }
+ }
+
keysDB.delete(t, routingkeyDBE);
+
+ // Insert the block into the index with a
random key, so that it's part of the LRU.
+ // Set the LRU to minimum - 1.
+
+ long lru = getMinRecentlyUsed(t) - 1;
+
+ byte[] randomKey = new byte[fullKey.length];
+ random.nextBytes(randomKey);
+
+ storeBlock = new StoreBlock(storeBlock.offset,
lru);
+
+ routingkeyDBE = new DatabaseEntry(randomKey);
+
+ blockDBE = new DatabaseEntry();
+
storeBlockTupleBinding.objectToEntry(storeBlock, blockDBE);
+ try {
+ keysDB.put(t,routingkeyDBE,blockDBE);
+ } catch (DatabaseException e) {
+ Logger.error(this, "Caught database
exception "+e+" while adding corrupt element to LRU");
+ addFreeBlock(storeBlock.offset, true,
"Bogus key");
+ c.close();
+ c = null;
+ t.commit();
+ t = null;
+ return null;
+ }
+
c.close();
c = null;
t.commit();
t = null;
- addFreeBlock(storeBlock.offset, true, "Key does
not verify");
- synchronized(this) {
- misses++;
- }
return null;
}
synchronized(this) {
@@ -1414,6 +1609,15 @@
}
Logger.error(this, "Corrupt secondary database
("+getName()+"). Should be cleaned up on restart.");
System.err.println("Corrupt secondary database
("+getName()+"). Should be cleaned up on restart.");
+
+ System.err.println("Flusing data store files ("
+ getName() + ")");
+ flushAndCloseRAF(storeRAF);
+ storeRAF = null;
+ flushAndCloseRAF(lruRAF);
+ lruRAF = null;
+ flushAndCloseRAF(keysRAF);
+ keysRAF = null;
+
WrapperManager.restart();
System.exit(freenet.node.NodeInitException.EXIT_DATABASE_REQUIRES_RESTART);
} else if(ex instanceof DbChecksumException || ex
instanceof RunRecoveryException || ex instanceof LogFileNotFoundException ||
@@ -1430,13 +1634,22 @@
System.err.println("Corrupt database
("+getName()+") but could not create flag file "+reconstructFile);
return; // Not sure what else we can do
}
+
+ System.err.println("Flusing data store files ("
+ getName() + ")");
+ flushAndCloseRAF(storeRAF);
+ storeRAF = null;
+ flushAndCloseRAF(lruRAF);
+ lruRAF = null;
+ flushAndCloseRAF(keysRAF);
+ keysRAF = null;
+
System.err.println("Restarting to fix corrupt
store database...");
Logger.error(this, "Restarting to fix corrupt
store database...");
WrapperManager.restart();
} else {
if(ex.getCause() != null)
checkSecondaryDatabaseError(ex.getCause());
- }
+ }
}
}
@@ -1583,7 +1796,17 @@
private final Object closeLock = new Object();
- private void closeRAF(RandomAccessFile file, boolean logError) {
+ private static void flushAndCloseRAF(RandomAccessFile file) {
+ try {
+ if (file != null)
+ file.getFD().sync();
+ } catch (IOException e) {
+ // ignore
+ }
+ closeRAF(file, false);
+ }
+
+ private static void closeRAF(RandomAccessFile file, boolean logError) {
try {
if (file != null)
file.close();
@@ -1595,7 +1818,7 @@
}
}
- private void closeDB(Database db, boolean logError) {
+ private static void closeDB(Database db, boolean logError) {
try {
if (db != null)
db.close();
@@ -1723,6 +1946,35 @@
return maxRecentlyUsed;
}
+ private long getMinRecentlyUsed(Transaction t) {
+ long minRecentlyUsed = 0;
+
+ Cursor c = null;
+ try {
+ c = accessTimeDB.openCursor(t,null);
+ DatabaseEntry keyDBE = new DatabaseEntry();
+ DatabaseEntry dataDBE = new DatabaseEntry();
+
if(c.getFirst(keyDBE,dataDBE,null)==OperationStatus.SUCCESS) {
+ StoreBlock storeBlock = (StoreBlock)
storeBlockTupleBinding.entryToObject(dataDBE);
+ minRecentlyUsed = storeBlock.getRecentlyUsed();
+ }
+ c.close();
+ c = null;
+ } catch(DatabaseException ex) {
+ ex.printStackTrace();
+ } finally {
+ if(c != null) {
+ try {
+ c.close();
+ } catch (DatabaseException e) {
+ Logger.error(this, "Caught "+e, e);
+ }
+ }
+ }
+
+ return minRecentlyUsed;
+ }
+
private long getNewRecentlyUsed() {
synchronized(lastRecentlyUsedSync) {
lastRecentlyUsed++;
@@ -1786,7 +2038,7 @@
System.err.println("Recreating secondary databases");
System.err.println("This may take some time...");
- WrapperManager.signalStarting((int)(Math.min(Integer.MAX_VALUE,
5*60*1000+keysDB.count()*100)));
+ WrapperManager.signalStarting((int)
(Math.min(Integer.MAX_VALUE, 5 * 60 * 1000 + keysDB.count() * 100L)));
// Of course it's not a solution but a quick fix
// Integer.MAX_VALUE seems to trigger an overflow or whatever
...
@@ -1888,4 +2140,13 @@
return db;
}
+
+ public void handleOOM() throws Exception {
+ if (storeRAF != null)
+ storeRAF.getFD().sync();
+ if (keysRAF != null)
+ keysRAF.getFD().sync();
+ if (lruRAF != null)
+ lruRAF.getFD().sync();
+ }
}
Modified: trunk/freenet/src/freenet/store/CHKStore.java
===================================================================
--- trunk/freenet/src/freenet/store/CHKStore.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/store/CHKStore.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -50,7 +50,18 @@
}
public boolean storeFullKeys() {
+ // Worth the extra two file descriptors, because if we have the
keys we can do lazy
+ // reconstruction i.e. don't construct each block, just
transcode from the .keys file
+ // straight into the database.
+ return true;
+ }
+
+ public boolean constructNeedsKey() {
return false;
}
+ public byte[] routingKeyFromFullKey(byte[] keyBuf) {
+ return NodeCHK.routingKeyFromFullKey(keyBuf);
+ }
+
}
Modified: trunk/freenet/src/freenet/store/FreenetStore.java
===================================================================
--- trunk/freenet/src/freenet/store/FreenetStore.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/store/FreenetStore.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -22,15 +22,16 @@
*/
StorableBlock fetch(byte[] routingKey, byte[] fullKey, boolean
dontPromote) throws IOException;
- /**
- * Store a block.
- *
- * @throws KeyCollisionException
- * If the key already exists but has different contents.
- * @param overwrite
- * If true, overwrite old content rather than throwing a
- * <code>KeyCollisionException</code>.
- */
+ /**
+ * Store a block.
+ *
+ * @throws KeyCollisionException
+ * If the key already exists and
<code>callback.collisionPossible()</code> is
+ * <code>true</code>.
+ * @param overwrite
+ * If true, overwrite old content rather than throwing a
+ * <code>KeyCollisionException</code>.
+ */
public void put(StorableBlock block, byte[] routingkey, byte[] fullKey,
byte[] data, byte[] header,
boolean overwrite) throws IOException, KeyCollisionException;
Modified: trunk/freenet/src/freenet/store/PubkeyStore.java
===================================================================
--- trunk/freenet/src/freenet/store/PubkeyStore.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/store/PubkeyStore.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -58,4 +58,12 @@
return false;
}
+ public boolean constructNeedsKey() {
+ return false;
+ }
+
+ public byte[] routingKeyFromFullKey(byte[] keyBuf) {
+ return keyBuf;
+ }
+
}
Modified: trunk/freenet/src/freenet/store/RAMFreenetStore.java
===================================================================
--- trunk/freenet/src/freenet/store/RAMFreenetStore.java 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/store/RAMFreenetStore.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -81,10 +81,6 @@
boolean storeFullKeys = callback.storeFullKeys();
if(oldBlock != null) {
if(callback.collisionPossible()) {
- boolean equals = Arrays.equals(oldBlock.data,
data) &&
- Arrays.equals(oldBlock.header, header)
&&
- (storeFullKeys ?
Arrays.equals(oldBlock.fullKey, fullKey) : true);
- if(equals) return;
if(overwrite) {
oldBlock.data = data;
oldBlock.header = header;
Modified: trunk/freenet/src/freenet/store/SSKStore.java
===================================================================
--- trunk/freenet/src/freenet/store/SSKStore.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/store/SSKStore.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -60,4 +60,12 @@
return true;
}
+ public boolean constructNeedsKey() {
+ return true;
+ }
+
+ public byte[] routingKeyFromFullKey(byte[] keyBuf) {
+ return NodeSSK.routingKeyFromFullKey(keyBuf);
+ }
+
}
Modified: trunk/freenet/src/freenet/store/StoreCallback.java
===================================================================
--- trunk/freenet/src/freenet/store/StoreCallback.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/store/StoreCallback.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -26,6 +26,9 @@
/** Whether we should create a .keys file to keep full keys in in order
to reconstruct. */
public abstract boolean storeFullKeys();
+ /** Whether we need the key in order to reconstruct a block. */
+ public abstract boolean constructNeedsKey();
+
/** Length of a full key. Full keys are stored in the .keys file. Also
fixed. */
public abstract int fullKeyLength();
@@ -41,7 +44,9 @@
// Reconstruction
- /** Construct a StorableBlock from the data, headers, and optionally
routing key or full key
+ /** Construct a StorableBlock from the data, headers, and optionally
routing key or full key.
+ * IMPORTANT: Using the full key or routing key is OPTIONAL, and if we
don't use them, WE DON'T
+ * CHECK THEM EITHER! You MUST check that the key is the one you
expected.
* @throws KeyVerifyException */
abstract StorableBlock construct(byte[] data, byte[] headers, byte[]
routingKey, byte[] fullKey) throws KeyVerifyException;
@@ -68,4 +73,7 @@
public long keyCount() {
return store.keyCount();
}
+
+ /** Generate a routing key from a full key */
+ public abstract byte[] routingKeyFromFullKey(byte[] keyBuf);
}
Modified: trunk/freenet/src/freenet/support/Base64.java
===================================================================
--- trunk/freenet/src/freenet/support/Base64.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/support/Base64.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -1,7 +1,5 @@
package freenet.support;
-import java.util.Random;
-
/**
* This class provides encoding of byte arrays into Base64-encoded strings,
* and decoding the other way.
Modified: trunk/freenet/src/freenet/support/Buffer.java
===================================================================
--- trunk/freenet/src/freenet/support/Buffer.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/support/Buffer.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -38,7 +38,9 @@
private final int _length;
/**
- * Create a Buffer by reading a DataInputStream
+ * Create a Buffer by reading a DataInputStream.
+ * Note that this a) expects that the first 4 bytes to be a length
indicator of the rest of the byte stream and
+ * b) these first 4 bytes are removed from the byte stream before
storing the rest
*
* @param dis
* @throws IOException
Modified: trunk/freenet/src/freenet/support/Logger.java
===================================================================
--- trunk/freenet/src/freenet/support/Logger.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/support/Logger.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -18,12 +18,12 @@
public final static class OSThread {
- public static boolean getPIDEnabled = false;
- public static boolean getPPIDEnabled = false;
- public static boolean logToFileEnabled = false;
- public static int logToFileVerbosity = DEBUG;
- public static boolean logToStdOutEnabled = false;
- public static boolean procSelfStatEnabled = false;
+ private static boolean getPIDEnabled = false;
+ private static boolean getPPIDEnabled = false;
+ private static boolean logToFileEnabled = false;
+ private static int logToFileVerbosity = DEBUG;
+ private static boolean logToStdOutEnabled = false;
+ private static boolean procSelfStatEnabled = false;
/**
* Get the thread's process ID or return -1 if it's unavailable
for some reason
Modified: trunk/freenet/src/freenet/support/LoggerHookChain.java
===================================================================
--- trunk/freenet/src/freenet/support/LoggerHookChain.java 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/support/LoggerHookChain.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -59,10 +59,11 @@
* Remove a hook from the logger.
*/
public synchronized void removeHook(LoggerHook lh) {
- LoggerHook[] newHooks = new LoggerHook[hooks.length-1];
+ final int hooksLength = hooks.length;
+ LoggerHook[] newHooks = new LoggerHook[hooksLength > 1 ? hooksLength-1
: 0];
int x=0;
boolean removed = false;
- for(int i=0;i<hooks.length;i++) {
+ for(int i=0;i<hooksLength;i++) {
if(hooks[i] == lh) {
removed = true;
} else {
Modified: trunk/freenet/src/freenet/support/NumberedItem.java
===================================================================
--- trunk/freenet/src/freenet/support/NumberedItem.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/support/NumberedItem.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -2,6 +2,8 @@
/**
* An object with a number.
+ *
+ * @see IntNumberedItem
*/
public interface NumberedItem {
Modified: trunk/freenet/src/freenet/support/NumberedItemComparator.java
===================================================================
--- trunk/freenet/src/freenet/support/NumberedItemComparator.java
2008-04-14 15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/support/NumberedItemComparator.java
2008-04-14 16:00:44 UTC (rev 19326)
@@ -11,12 +11,6 @@
final boolean wrapAround;
public int compare(Object o1, Object o2) {
- int x = ocompare(o1, o2);
- //Logger.minor(this, "compare("+o1+","+o2+") = "+x);
- return x;
- }
-
- public int ocompare(Object o1, Object o2) {
// Nulls at the end of the list
if((o1 == null) && (o2 == null))
return 0; // null == null
Modified: trunk/freenet/src/freenet/support/OOMHandler.java
===================================================================
--- trunk/freenet/src/freenet/support/OOMHandler.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/support/OOMHandler.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -3,6 +3,9 @@
* http://www.gnu.org/ for further details of the GPL. */
package freenet.support;
+import java.util.Iterator;
+import java.util.Set;
+
import org.tanukisoftware.wrapper.WrapperManager;
import freenet.support.Logger;
@@ -11,16 +14,62 @@
* Do this processing as a standard response to an OutOfMemoryError
*/
public class OOMHandler {
-
- public synchronized static void handleOOM(OutOfMemoryError e) {
+ private static volatile boolean isOOM = false;
+
+ /**
+ * Emergency memory, freed when OOM occur. Marked <code>volatile</code>
to make sure gc thread
+ * see it's free'd.
+ */
+ private static volatile byte[] emergencyPool = new byte[8192];
+
+ /**
+ * List of {@link OOMHook}s
+ */
+ private static Set oomHooks = new WeakHashSet();
+
+ public static void addOOMHook(OOMHook hook) {
+ synchronized (oomHooks) {
+ oomHooks.add(hook);
+ }
+ }
+
+ public static void handleOOM(OutOfMemoryError e) {
+ if (isOOM) {
+ Logger.error(null, "Double OOM", e);
+ return;
+ }
+
+ isOOM = true;
+
Runtime r = null;
try {
r = Runtime.getRuntime();
long usedAtStart = r.totalMemory() - r.freeMemory();
+
+ if (emergencyPool != null)
+ emergencyPool = null;
+
System.gc();
System.runFinalization();
+
+ // iterate all oom hooks
+ Iterator it = oomHooks.iterator();
+ while (it.hasNext()) {
+ OOMHook hook = ((OOMHook) it.next());
+ if (hook != null) {
+ try {
+ hook.handleOOM();
+ } catch (Throwable t) {
+ //ignore
+ }
+ }
+
+ System.gc();
+ }
+
System.gc();
System.runFinalization();
+
System.err.println(e.getClass());
System.err.println(e.getMessage());
e.printStackTrace();
@@ -46,6 +95,8 @@
while(tg.getParent() != null) tg = tg.getParent();
System.err.println("Running threads:
"+tg.activeCount());
WrapperManager.requestThreadDump(); // Will probably
crash, but never mind...
+ } finally {
+ isOOM = false;
}
}
}
Copied: trunk/freenet/src/freenet/support/OOMHook.java (from rev 19322,
trunk/freenet/src/freenet/support/OOMHook.java)
===================================================================
--- trunk/freenet/src/freenet/support/OOMHook.java
(rev 0)
+++ trunk/freenet/src/freenet/support/OOMHook.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -0,0 +1,13 @@
+package freenet.support;
+
+/**
+ * @author sdiz
+ */
+public interface OOMHook {
+ /**
+ * Handle OutOfMemoryError
+ *
+ * (try to free some cache, save the files, etc).
+ */
+ void handleOOM() throws Exception;
+}
Modified: trunk/freenet/src/freenet/support/SectoredRandomGrabArray.java
===================================================================
--- trunk/freenet/src/freenet/support/SectoredRandomGrabArray.java
2008-04-14 15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/support/SectoredRandomGrabArray.java
2008-04-14 16:00:44 UTC (rev 19326)
@@ -124,16 +124,17 @@
// Just because the item is cancelled does not
necessarily mean the whole client is.
// E.g. a segment may return cancelled because it is
decoding, that doesn't mean
// other segments are cancelled. So just go around the
loop in that case.
+ final int grabArraysLength = grabArrays.length;
if(rga.isEmpty()) {
if(logMINOR)
Logger.minor(this, "Removing grab array
"+x+" : "+rga+" for "+rga.getObject()+" (is empty)");
Object client = rga.getObject();
grabArraysByClient.remove(client);
- RemoveRandomWithObject[] newArray = new
RemoveRandomWithObject[grabArrays.length-1];
+ RemoveRandomWithObject[] newArray = new
RemoveRandomWithObject[grabArraysLength > 1 ? grabArraysLength-1 : 0];
if(x > 0)
System.arraycopy(grabArrays, 0,
newArray, 0, x);
- if(x < grabArrays.length-1)
- System.arraycopy(grabArrays, x+1,
newArray, x, grabArrays.length - (x+1));
+ if(x < grabArraysLength-1)
+ System.arraycopy(grabArrays, x+1,
newArray, x, grabArraysLength - (x+1));
grabArrays = newArray;
}
if(item == null) {
@@ -141,7 +142,7 @@
// Hmmm...
excluded++;
if(excluded > MAX_EXCLUDED) {
- Logger.normal(this, "Too many
sub-arrays are entirely excluded on "+this+" length = "+grabArrays.length, new
Exception("error"));
+ Logger.normal(this, "Too many
sub-arrays are entirely excluded on "+this+" length = "+grabArraysLength, new
Exception("error"));
return null;
}
}
Modified: trunk/freenet/src/freenet/support/SizeUtil.java
===================================================================
--- trunk/freenet/src/freenet/support/SizeUtil.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/support/SizeUtil.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -4,7 +4,7 @@
* Size formatting utility.
*/
public class SizeUtil {
- public static String[] suffixes = {"B",
"KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"};
+ public final static String[] suffixes = { "B", "KiB", "MiB", "GiB",
"TiB", "PiB", "EiB", "ZiB", "YiB" };
public static String formatSize(long sz) {
return formatSize(sz, false);
Modified: trunk/freenet/src/freenet/support/SortedLongSet.java
===================================================================
--- trunk/freenet/src/freenet/support/SortedLongSet.java 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/support/SortedLongSet.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -48,7 +48,7 @@
* @return <code>true</code>, if <code>num</code> exist.
*/
public synchronized boolean contains(long num) {
- int x = Arrays.binarySearch(data, num);
+ int x = binarySearch(num);
if(x >= 0)
return true;
else
@@ -62,7 +62,7 @@
* the item to be removed
*/
public synchronized void remove(long item) {
- int x = Arrays.binarySearch(data, item);
+ int x = binarySearch(item);
if(x >= 0) {
if(x < length-1)
System.arraycopy(data, x+1, data, x,
length-x-1);
@@ -98,12 +98,12 @@
/**
* Add the item, if it (or an item of the same number) is not already
- * present. <strong>This method does not accept
<code>Long.MAX_VALUE</code>.</strong>
+ * present.
*
* @return <code>true</code>, if we added the item.
*/
public synchronized boolean push(long num) {
- int x = Arrays.binarySearch(data, num);
+ int x = binarySearch(num);
if(x >= 0) return false;
// insertion point
x = -x-1;
@@ -114,14 +114,12 @@
/**
* Add the item.
*
- * <strong>This method does not accept
<code>Long.MAX_VALUE</code>.</strong>
- *
* @throws {@link IllegalArgumentException}
* if the item already exist
* @return <code>true</code>, if we added the item.
*/
public synchronized void add(long num) {
- int x = Arrays.binarySearch(data, num);
+ int x = binarySearch(num);
if(x >= 0) throw new IllegalArgumentException(); // already
exists
// insertion point
x = -x-1;
@@ -179,4 +177,21 @@
return output;
}
+ private int binarySearch(long key) {
+ int low = 0;
+ int high = length - 1;
+
+ while (low <= high) {
+ int mid = (low + high) >>> 1;
+ long midVal = data[mid];
+
+ if (midVal < key)
+ low = mid + 1;
+ else if (midVal > key)
+ high = mid - 1;
+ else
+ return mid; // key found
+ }
+ return -(low + 1); // key not found.
+ }
}
Modified: trunk/freenet/src/freenet/support/WeakHashSet.java
===================================================================
--- trunk/freenet/src/freenet/support/WeakHashSet.java 2008-04-14 15:55:20 UTC
(rev 19325)
+++ trunk/freenet/src/freenet/support/WeakHashSet.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -1,12 +1,11 @@
package freenet.support;
+import java.util.AbstractSet;
import java.util.Collection;
import java.util.Iterator;
-import java.util.Set;
import java.util.WeakHashMap;
-public class WeakHashSet implements Set {
-
+public class WeakHashSet extends AbstractSet {
private final WeakHashMap map;
public WeakHashSet() {
@@ -17,14 +16,6 @@
return map.put(key, null) == null;
}
- public boolean addAll(Collection arg0) {
- boolean changed = false;
- for(Iterator i=arg0.iterator();i.hasNext();) {
- changed |= add(i.next());
- }
- return changed;
- }
-
public void clear() {
map.clear();
}
@@ -34,10 +25,7 @@
}
public boolean containsAll(Collection arg0) {
- for(Iterator i=arg0.iterator();i.hasNext();) {
- if(!map.containsKey(i.next())) return false;
- }
- return true;
+ return map.keySet().containsAll(arg0);
}
public boolean isEmpty() {
@@ -52,19 +40,6 @@
return map.remove(key) != null;
}
- public boolean removeAll(Collection arg0) {
- boolean changed = false;
- for(Iterator i=arg0.iterator();i.hasNext();) {
- changed |= remove(i.next());
- }
- return changed;
- }
-
- public boolean retainAll(Collection arg0) {
- // FIXME
- throw new UnsupportedOperationException();
- }
-
public int size() {
return map.size();
}
@@ -76,5 +51,4 @@
public Object[] toArray(Object[] arg0) {
return map.keySet().toArray(arg0);
}
-
}
Modified: trunk/freenet/src/freenet/support/io/BaseFileBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/io/BaseFileBucket.java 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/support/io/BaseFileBucket.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -219,13 +219,10 @@
}
class FileBucketInputStream extends FileInputStream {
- Exception e;
boolean closed;
public FileBucketInputStream(File f) throws IOException {
super(f);
- if (Logger.shouldLog(Logger.DEBUG, this))
- e = new Exception("debug");
}
public void close() throws IOException {
@@ -280,7 +277,7 @@
getFile().delete();
}
- public void finalize() {
+ protected void finalize() {
if(deleteOnFinalize())
free(true);
}
@@ -396,17 +393,27 @@
if(toClose != null) {
Logger.error(this, "Streams open free()ing "+this+" :
"+StringArray.toString(toClose), new Exception("debug"));
- for(int i=0;i<toClose.length;i++) {
- try {
- if(toClose[i] instanceof
FileBucketOutputStream) {
- ((FileBucketOutputStream)
toClose[i]).close();
- } else {
- ((FileBucketInputStream)
toClose[i]).close();
+ double toCloseLength = toClose.length;
+ while(toCloseLength > 0) {
+ int toCloseThisRound;
+ if(toCloseLength <= Integer.MAX_VALUE) {
+ toCloseThisRound = (int) toCloseLength;
+ toCloseLength = 0;
+ } else
+ toCloseLength -= (toCloseThisRound =
Integer.MAX_VALUE);
+
+ for(int i=0; i<toCloseThisRound; i++) {
+ try {
+ if(toClose[i] instanceof
FileBucketOutputStream) {
+
((FileBucketOutputStream) toClose[i]).close();
+ } else {
+
((FileBucketInputStream) toClose[i]).close();
+ }
+ } catch (IOException e) {
+ Logger.error(this, "Caught
closing stream in free(): "+e, e);
+ } catch (Throwable t) {
+ Logger.error(this, "Caught
closing stream in free(): "+t, t);
}
- } catch (IOException e) {
- Logger.error(this, "Caught closing
stream in free(): "+e, e);
- } catch (Throwable t) {
- Logger.error(this, "Caught closing
stream in free(): "+t, t);
}
}
}
Modified: trunk/freenet/src/freenet/support/io/FileBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/io/FileBucket.java 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/support/io/FileBucket.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -22,7 +22,6 @@
protected final boolean createFileOnly;
// JVM caches File.size() and there is no way to flush the cache, so we
// need to track it ourselves
- protected long fileRestartCounter;
protected static String tempDir = null;
Modified: trunk/freenet/src/freenet/support/io/MultiReaderBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/io/MultiReaderBucket.java 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/support/io/MultiReaderBucket.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -120,7 +120,7 @@
return bucket.size();
}
- public void finalize() {
+ protected void finalize() {
free();
}
Modified:
trunk/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucket.java
2008-04-14 15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/support/io/PaddedEphemerallyEncryptedBucket.java
2008-04-14 16:00:44 UTC (rev 19326)
@@ -271,7 +271,7 @@
if(size < minPaddedSize) size = minPaddedSize;
if(size == minPaddedSize) return size;
long min = minPaddedSize;
- long max = minPaddedSize << 1;
+ long max = (long)minPaddedSize << 1;
while(true) {
if(max < 0)
throw new Error("Impossible size: "+size+" -
min="+min+", max="+max);
Modified: trunk/freenet/src/freenet/support/math/SimpleBinaryRunningAverage.java
===================================================================
--- trunk/freenet/src/freenet/support/math/SimpleBinaryRunningAverage.java
2008-04-14 15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/support/math/SimpleBinaryRunningAverage.java
2008-04-14 16:00:44 UTC (rev 19326)
@@ -160,7 +160,7 @@
ba = new BitSet(maxSize);
maximumSize = maxSize;
byte[] b = new byte[HexUtil.countBytesForBits(size)];
- dis.read(b);
+ dis.readFully(b);
HexUtil.bytesToBits(b, ba, size);
calculateTotalOnesZeros();
defaultValue = 0.5; // not used
Modified: trunk/freenet/src/freenet/support/math/TrivialRunningAverage.java
===================================================================
--- trunk/freenet/src/freenet/support/math/TrivialRunningAverage.java
2008-04-14 15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/freenet/support/math/TrivialRunningAverage.java
2008-04-14 16:00:44 UTC (rev 19326)
@@ -40,7 +40,9 @@
}
public Object clone() {
- return new TrivialRunningAverage(this);
+ synchronized (this) {
+ return new TrivialRunningAverage(this);
+ }
}
Modified: trunk/freenet/src/freenet/tools/AddRef.java
===================================================================
--- trunk/freenet/src/freenet/tools/AddRef.java 2008-04-14 15:55:20 UTC (rev
19325)
+++ trunk/freenet/src/freenet/tools/AddRef.java 2008-04-14 16:00:44 UTC (rev
19326)
@@ -108,7 +108,6 @@
protected SimpleFieldSet getMessage(LineReadingInputStream lis){
SimpleFieldSet sfs = new SimpleFieldSet(true);
- sfs=new SimpleFieldSet(true);
try {
while(lis.available()>0){
String line = lis.readLine(128, 128, true);
Modified: trunk/freenet/src/net/i2p/util/NativeBigInteger.java
===================================================================
--- trunk/freenet/src/net/i2p/util/NativeBigInteger.java 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/src/net/i2p/util/NativeBigInteger.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -10,8 +10,6 @@
import java.math.BigInteger;
import java.util.Random;
-import java.security.SecureRandom;
-
import java.net.URL;
import java.io.FileOutputStream;
import java.io.InputStream;
@@ -267,126 +265,7 @@
public static boolean isNative() {
return _nativeOk;
}
-
/**
- * <p>Compare the BigInteger.modPow/doubleValue vs the
NativeBigInteger.modPow/doubleValue of some
- * really big (2Kbit) numbers 100 different times and benchmark the
- * performance (or shit a brick if they don't match). </p>
- *
- */
- public static void main(String args[]) {
- runModPowTest(100);
- runDoubleValueTest(100);
- }
-
- /* the sample numbers are elG generator/prime so we can test with
reasonable numbers */
- private final static byte[] _sampleGenerator = new
BigInteger("2").toByteArray();
- private final static byte[] _samplePrime = new
BigInteger("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" +
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" +
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" +
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" +
"83655D23DCA3AD961C62F356208552BB9ED529077096966D" +
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" +
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" +
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510" +
"15728E5A8AACAA68FFFFFFFFFFFFFFFF", 16).toByteArray();
-
- private static void runModPowTest(int numRuns) {
- System.out.println("DEBUG: Warming up the random number
generator...");
- SecureRandom rand = new SecureRandom();
- rand.nextBoolean();
- System.out.println("DEBUG: Random number generator warmed up");
-
- BigInteger jg = new BigInteger(_sampleGenerator);
- BigInteger jp = new BigInteger(_samplePrime);
-
- long totalTime = 0;
- long javaTime = 0;
-
- int runsProcessed = 0;
- for(runsProcessed = 0; runsProcessed < numRuns;
runsProcessed++) {
- BigInteger bi = new BigInteger(2048, rand);
- NativeBigInteger g = new
NativeBigInteger(_sampleGenerator);
- NativeBigInteger p = new NativeBigInteger(_samplePrime);
- NativeBigInteger k = new NativeBigInteger(1,
bi.toByteArray());
- long beforeModPow = System.currentTimeMillis();
- BigInteger myValue = g.modPow(k, p);
- long afterModPow = System.currentTimeMillis();
- BigInteger jval = jg.modPow(bi, jp);
- long afterJavaModPow = System.currentTimeMillis();
-
- totalTime += (afterModPow - beforeModPow);
- javaTime += (afterJavaModPow - afterModPow);
- if(!myValue.equals(jval)) {
- System.err.println("ERROR: [" + runsProcessed +
"]\tnative modPow != java modPow");
- System.err.println("ERROR: native modPow value:
" + myValue.toString());
- System.err.println("ERROR: java modPow value: "
+ jval.toString());
- System.err.println("ERROR: run time: " +
totalTime + "ms (" + (totalTime / (runsProcessed + 1)) + "ms each)");
- break;
- } else
- System.out.println("DEBUG: current run time: "
+ (afterModPow - beforeModPow) + "ms (total: " + totalTime + "ms, " +
(totalTime / (runsProcessed + 1)) + "ms each)");
- }
- System.out.println("INFO: run time: " + totalTime + "ms (" +
(totalTime / (runsProcessed + 1)) + "ms each)");
- if(numRuns == runsProcessed)
- System.out.println("INFO: " + runsProcessed + " runs
complete without any errors");
- else
- System.out.println("ERROR: " + runsProcessed + " runs
until we got an error");
-
- if(_nativeOk) {
- System.out.println("native run time: \t" + totalTime +
"ms (" + (totalTime / (runsProcessed + 1)) + "ms each)");
- System.out.println("java run time: \t" + javaTime +
"ms (" + (javaTime / (runsProcessed + 1)) + "ms each)");
- System.out.println("native = " + ((totalTime * 100.0d)
/ (double) javaTime) + "% of pure java time");
- } else {
- System.out.println("java run time: \t" + javaTime + "ms
(" + (javaTime / (runsProcessed + 1)) + "ms each)");
- System.out.println("However, we couldn't load the
native library, so this doesn't test much");
- }
- }
-
- private static void runDoubleValueTest(int numRuns) {
- System.out.println("DEBUG: Warming up the random number
generator...");
- SecureRandom rand = new SecureRandom();
- rand.nextBoolean();
- System.out.println("DEBUG: Random number generator warmed up");
-
- BigInteger jg = new BigInteger(_sampleGenerator);
-
- long totalTime = 0;
- long javaTime = 0;
-
- int MULTIPLICATOR = 50000; //Run the doubleValue() calls within
a loop since they are pretty fast..
- int runsProcessed = 0;
- for(runsProcessed = 0; runsProcessed < numRuns;
runsProcessed++) {
- NativeBigInteger g = new
NativeBigInteger(_sampleGenerator);
- long beforeDoubleValue = System.currentTimeMillis();
- double dNative = 0;
- for(int mult = 0; mult < MULTIPLICATOR; mult++)
- dNative = g.doubleValue();
- long afterDoubleValue = System.currentTimeMillis();
- double jval = 0;
- for(int mult = 0; mult < MULTIPLICATOR; mult++)
- jval = jg.doubleValue();
- long afterJavaDoubleValue = System.currentTimeMillis();
-
- totalTime += (afterDoubleValue - beforeDoubleValue);
- javaTime += (afterJavaDoubleValue - afterDoubleValue);
- if(dNative != jval) {
- System.err.println("ERROR: [" + runsProcessed +
"]\tnative double != java double");
- System.err.println("ERROR: native double value:
" + dNative);
- System.err.println("ERROR: java double value: "
+ jval);
- System.err.println("ERROR: run time: " +
totalTime + "ms (" + (totalTime / (runsProcessed + 1)) + "ms each)");
- break;
- } else
- System.out.println("DEBUG: current run time: "
+ (afterDoubleValue - beforeDoubleValue) + "ms (total: " + totalTime + "ms, " +
(totalTime / (runsProcessed + 1)) + "ms each)");
- }
- System.out.println("INFO: run time: " + totalTime + "ms (" +
(totalTime / (runsProcessed + 1)) + "ms each)");
- if(numRuns == runsProcessed)
- System.out.println("INFO: " + runsProcessed + " runs
complete without any errors");
- else
- System.out.println("ERROR: " + runsProcessed + " runs
until we got an error");
-
- if(_nativeOk) {
- System.out.println("native run time: \t" + totalTime +
"ms (" + (totalTime / (runsProcessed + 1)) + "ms each)");
- System.out.println("java run time: \t" + javaTime +
"ms (" + (javaTime / (runsProcessed + 1)) + "ms each)");
- System.out.println("native = " + ((totalTime * 100.0d)
/ (double) javaTime) + "% of pure java time");
- } else {
- System.out.println("java run time: \t" + javaTime + "ms
(" + (javaTime / (runsProcessed + 1)) + "ms each)");
- System.out.println("However, we couldn't load the
native library, so this doesn't test much");
- }
- }
-
- /**
* <p>Do whatever we can to load up the native library backing this
BigInteger's native methods.
* If it can find a custom built jbigi.dll / libjbigi.so, it'll use
that. Otherwise
* it'll try to look in the classpath for the correct library (see
loadFromResource).
Copied: trunk/freenet/test/freenet/support/BufferTest.java (from rev 19322,
trunk/freenet/test/freenet/support/BufferTest.java)
===================================================================
--- trunk/freenet/test/freenet/support/BufferTest.java
(rev 0)
+++ trunk/freenet/test/freenet/support/BufferTest.java 2008-04-14 16:00:44 UTC
(rev 19326)
@@ -0,0 +1,173 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+package freenet.support;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+/**
+ * Test case for {@link freenet.support.Buffer} class.
+ *
+ * @author stuart martin <wavey at freenetproject.org>
+ */
+public class BufferTest extends TestCase {
+
+ private static final String DATA_STRING_1 =
"asldkjaskjdsakdhasdhaskjdhaskjhbkasbhdjkasbduiwbxgdoudgboewuydxbybuewyxbuewyuwe"
+
+
"dasdkljasndijwnodhnqweoidhnaouidhbnwoduihwnxodiuhnwuioxdhnwqiouhnxwqoiushdnxwqoiudhxnwqoiudhxni";
+
+ public void testByteArrayBuffer() {
+
+ byte[] data = DATA_STRING_1.getBytes();
+
+ Buffer buffer = new Buffer(data);
+
+ assertEquals(data, buffer.getData());
+
+ doTestBuffer(data, buffer);
+ }
+
+ public void testByteArrayIndexBuffer() {
+
+ // get content
+ byte[] data = DATA_STRING_1.getBytes();
+
+ byte[] dataSub = new byte[5];
+
+ // prepare 'substring'
+ System.arraycopy(data, 4, dataSub, 0, 5);
+
+ Buffer buffer = new Buffer(data, 4, 5);
+
+ assertFalse(dataSub.equals(buffer.getData()));
+
+ doTestBuffer(dataSub, buffer);
+ }
+
+
+ public void testDataInputStreamBuffer() {
+
+ byte[] data = DATA_STRING_1.getBytes(); // get some content
+
+ byte[] data2 = new byte[data.length + 4]; // make room for 4
byte length indicator
+
+ int length = DATA_STRING_1.getBytes().length;
+
+ // populate length as first 4 bytes
+ data2[0] = (byte)((length & 0xff000000) >> 24);
+ data2[1] = (byte)((length & 0xff0000) >> 16);
+ data2[2] = (byte)((length & 0xff00) >> 8);
+ data2[3] = (byte)((length & 0xff) );
+
+ System.arraycopy(data, 0, data2, 4, data.length); // populate
rest of content
+
+ DataInputStream dis = new DataInputStream(new
ByteArrayInputStream(data2));
+ Buffer buffer = null;
+
+ try {
+ buffer = new Buffer(dis);
+ } catch (IOException e) {
+ fail("unexpected exception: " + e.getMessage());
+ }
+ // perform rest of test with the *original* array because
Buffer(DataInputStream) chomps first 4 bytes
+ doTestBuffer(data, buffer);
+ }
+
+ private void doTestBuffer(byte[] data, Buffer buffer) {
+ assertEquals(data.length, buffer.getLength());
+
+ for(int i = 0; i < buffer.getLength(); i++) {
+ assertEquals(data[i], buffer.byteAt(i));
+ }
+
+ try{
+ buffer.byteAt(data.length + 1); // expect exception
+ fail();
+ }
+ catch(ArrayIndexOutOfBoundsException e) {
+ // expect this
+ }
+ }
+
+ public void testLongBufferToString() {
+
+ Buffer buffer = new Buffer(DATA_STRING_1.getBytes());
+ String longString = buffer.toString();
+ assertEquals("Buffer {" + buffer.getLength() + "}", longString);
+ }
+
+ public void testShortBufferToString() {
+ String shortString = "feep";
+ Buffer shortBuffer = new Buffer(shortString.getBytes());
+
+ String outString = shortBuffer.toString();
+ assertEquals(outString, "{4:102 101 101 112 "); // FIXME: final
brace?
+ }
+
+ public void testEquals() {
+
+ Buffer b1 = new Buffer("Buffer1".getBytes());
+ Buffer b2 = new Buffer("Buffer2".getBytes());
+ Buffer b3 = new Buffer("Buffer1".getBytes());
+
+ assertFalse(b1.equals(b2));
+ assertTrue(b1.equals(b3));
+ assertFalse(b2.equals(b3));
+ assertTrue(b1.equals(b1));
+ assertTrue(b2.equals(b2));
+ assertTrue(b3.equals(b1));
+ }
+
+ public void testHashcode() {
+
+ Buffer b1 = new Buffer("Buffer1".getBytes());
+ Buffer b2 = new Buffer("Buffer2".getBytes());
+ Buffer b3 = new Buffer("Buffer1".getBytes());
+
+ Map hashMap = new HashMap();
+
+ hashMap.put(b1, b1);
+ hashMap.put(b2, b2);
+ hashMap.put(b3, b3); // should clobber b1 due to content
+
+ // see if b3 survived
+ Object o = hashMap.get(b3);
+ assertFalse(o == b1);
+ assertTrue(o == b3);
+
+ // see if b1 survived
+ o = hashMap.get(b1);
+ assertFalse(o == b1);
+ assertTrue(o == b3);
+ }
+
+ public void testCopy() {
+
+ byte[] oldBuf = DATA_STRING_1.getBytes();
+ Buffer b = new Buffer(oldBuf);
+
+ byte[] newBuf = new byte[b.getLength()];
+ b.copyTo(newBuf, 0);
+
+ for(int i = 0; i < oldBuf.length; i++) {
+ assertEquals(newBuf[i], oldBuf[i]);
+ }
+ }
+}
Modified: trunk/freenet/test/freenet/support/SortedLongSetTest.java
===================================================================
--- trunk/freenet/test/freenet/support/SortedLongSetTest.java 2008-04-14
15:55:20 UTC (rev 19325)
+++ trunk/freenet/test/freenet/support/SortedLongSetTest.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -8,13 +8,7 @@
* @author sdiz
*/
public class SortedLongSetTest extends TestCase {
- /*
- * FIXME use Long.MAX_VALUE , not MAX_VALUE - 1
- */
- private final static long[] testArray = {
- 10, 8, 6, 2, 0, 1, 11,
- Long.MAX_VALUE - 1, 4, 7, 5, 3, Long.MIN_VALUE
- };
+ private final static long[] testArray = { 10, 8, 6, 2, 0, 1, 11,
Long.MAX_VALUE, 4, 7, 5, 3, Long.MIN_VALUE };
protected SortedLongSet perpare(long[] array) {
SortedLongSet set = new SortedLongSet();
@@ -60,7 +54,7 @@
// Contain
assertTrue(set.contains(0L));
assertTrue(set.contains(3L));
- assertTrue(set.contains(Long.MAX_VALUE - 1));
+ assertTrue(set.contains(Long.MAX_VALUE));
assertTrue(set.contains(Long.MIN_VALUE));
// Not contain
Modified: trunk/freenet/test/freenet/support/compress/GzipCompressorTest.java
===================================================================
--- trunk/freenet/test/freenet/support/compress/GzipCompressorTest.java
2008-04-14 15:55:20 UTC (rev 19325)
+++ trunk/freenet/test/freenet/support/compress/GzipCompressorTest.java
2008-04-14 16:00:44 UTC (rev 19326)
@@ -52,7 +52,10 @@
// check GZIP is the first compressor
assertEquals(gzipCompressor, compressorZero);
+ }
+ public void testCompress() {
+
// do gzip compression
byte[] compressedData =
doCompress(UNCOMPRESSED_DATA_1.getBytes());
@@ -63,15 +66,48 @@
for (int i = 0; i < compressedData.length; i++) {
assertEquals(COMPRESSED_DATA_1[i], compressedData[i]);
}
+ }
- // do gzip uncompression
- byte[] uncompressedData = doUncompress(compressedData);
+ public void testBucketDecompress() {
+ byte[] compressedData = COMPRESSED_DATA_1;
+
+ // do gzip decompression with buckets
+ byte[] uncompressedData = doBucketDecompress(compressedData);
+
// is the (round-tripped) uncompressed string the same as the
original?
String uncompressedString = new String(uncompressedData);
assertEquals(uncompressedString, UNCOMPRESSED_DATA_1);
}
+ public void testByteArrayDecompress() {
+
+ // build 5k array
+ byte[] originalUncompressedData = new byte[5 * 1024];
+ for(int i = 0; i < originalUncompressedData.length; i++) {
+ originalUncompressedData[i] = 1;
+ }
+
+ byte[] compressedData = doCompress(originalUncompressedData);
+ byte[] outUncompressedData = new byte[5 * 1024];
+
+ int writtenBytes = 0;
+
+ try {
+ writtenBytes =
Compressor.GZIP.decompress(compressedData, 0, compressedData.length,
outUncompressedData);
+ } catch (CompressionOutputSizeException e) {
+ fail("unexpected exception thrown : " + e.getMessage());
+ }
+
+ assertEquals(writtenBytes, originalUncompressedData.length);
+ assertEquals(originalUncompressedData.length,
outUncompressedData.length);
+
+ // check each byte is exactly as expected
+ for (int i = 0; i < outUncompressedData.length; i++) {
+ assertEquals(originalUncompressedData[i],
outUncompressedData[i]);
+ }
+ }
+
public void testCompressException() {
byte[] uncompressedData = UNCOMPRESSED_DATA_1.getBytes();
@@ -109,7 +145,7 @@
}
}
- private byte[] doUncompress(byte[] compressedData) {
+ private byte[] doBucketDecompress(byte[] compressedData) {
Bucket inBucket = new ArrayBucket(compressedData);
BucketFactory factory = new ArrayBucketFactory();
Copied: trunk/freenet/test/net/i2p/util/NativeBigIntegerTest.java (from rev
19322, trunk/freenet/test/net/i2p/util/NativeBigIntegerTest.java)
===================================================================
--- trunk/freenet/test/net/i2p/util/NativeBigIntegerTest.java
(rev 0)
+++ trunk/freenet/test/net/i2p/util/NativeBigIntegerTest.java 2008-04-14
16:00:44 UTC (rev 19326)
@@ -0,0 +1,114 @@
+package net.i2p.util;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import junit.framework.TestCase;
+
+public class NativeBigIntegerTest extends TestCase {
+ // Run with <code>ant -Dbenchmark=true</code> to do benchmark
+ private static final boolean BENCHMARK =
Boolean.getBoolean("benchmark");
+ private static int numRuns = BENCHMARK ? 200 : 5;
+
+ /*
+ * the sample numbers are elG generator/prime so we can test with
reasonable
+ * numbers
+ */
+ private final static byte[] _sampleGenerator = new
BigInteger("2").toByteArray();
+ private final static byte[] _samplePrime = new
BigInteger("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+ + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" +
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+ + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+ + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" +
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+ + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" +
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
+ + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" +
"15728E5A8AACAA68FFFFFFFFFFFFFFFF", 16)
+ .toByteArray();
+
+ private SecureRandom rand;
+ private int runsProcessed;
+
+ private BigInteger jg;
+ private BigInteger jp;
+
+ private long totalTime = 0;
+ private long javaTime = 0;
+
+ protected void setUp() throws Exception {
+ if (!NativeBigInteger.isNative())
+ printError("can't load native code");
+
+ printInfo("DEBUG: Warming up the random number generator...");
+ rand = new SecureRandom();
+ rand.nextBoolean();
+ printInfo("DEBUG: Random number generator warmed up");
+
+ jg = new BigInteger(_sampleGenerator);
+ jp = new BigInteger(_samplePrime);
+
+ totalTime = javaTime = 0;
+ }
+
+ protected void tearDown() throws Exception {
+ printInfo("INFO: run time: " + totalTime + "ms (" + (totalTime
/ (runsProcessed + 1)) + "ms each)");
+ if (numRuns == runsProcessed)
+ printInfo("INFO: " + runsProcessed + " runs complete
without any errors");
+ else
+ printError("ERROR: " + runsProcessed + " runs until we
got an error");
+
+ printInfo("native run time: \t" + totalTime + "ms (" +
(totalTime / (runsProcessed + 1)) + "ms each)");
+ printInfo("java run time: \t" + javaTime + "ms (" + (javaTime
/ (runsProcessed + 1)) + "ms each)");
+ printInfo("native = " + ((totalTime * 100.0d) / (double)
javaTime) + "% of pure java time");
+ }
+
+ public void testModPow() {
+ for (runsProcessed = 0; runsProcessed < numRuns;
runsProcessed++) {
+ BigInteger bi = new BigInteger(2048, rand);
+ NativeBigInteger g = new
NativeBigInteger(_sampleGenerator);
+ NativeBigInteger p = new NativeBigInteger(_samplePrime);
+ NativeBigInteger k = new NativeBigInteger(1,
bi.toByteArray());
+
+ long beforeModPow = System.currentTimeMillis();
+ BigInteger myValue = g.modPow(k, p);
+ long afterModPow = System.currentTimeMillis();
+ BigInteger jval = jg.modPow(bi, jp);
+ long afterJavaModPow = System.currentTimeMillis();
+
+ totalTime += (afterModPow - beforeModPow);
+ javaTime += (afterJavaModPow - afterModPow);
+
+ assertEquals(jval, myValue);
+ }
+ }
+
+ public void testDoubleValue() {
+ BigInteger jg = new BigInteger(_sampleGenerator);
+
+ int MULTIPLICATOR = 50000; //Run the doubleValue() calls within
a loop since they are pretty fast..
+ for (runsProcessed = 0; runsProcessed < numRuns;
runsProcessed++) {
+ NativeBigInteger g = new
NativeBigInteger(_sampleGenerator);
+ long beforeDoubleValue = System.currentTimeMillis();
+ double dNative = 0;
+ for (int mult = 0; mult < MULTIPLICATOR; mult++)
+ dNative = g.doubleValue();
+ long afterDoubleValue = System.currentTimeMillis();
+ double jval = 0;
+ for (int mult = 0; mult < MULTIPLICATOR; mult++)
+ jval = jg.doubleValue();
+ long afterJavaDoubleValue = System.currentTimeMillis();
+
+ totalTime += (afterDoubleValue - beforeDoubleValue);
+ javaTime += (afterJavaDoubleValue - afterDoubleValue);
+
+ assertEquals(jval, dNative, 0);
+ }
+ }
+
+ private static void printInfo(String info) {
+ if (BENCHMARK)
+ System.out.println(info);
+ }
+
+ private static void printError(String info) {
+ if (BENCHMARK)
+ System.err.println(info);
+ }
+}