Author: toad
Date: 2008-09-24 22:16:49 +0000 (Wed, 24 Sep 2008)
New Revision: 22824
Added:
branches/db4o/freenet/test/freenet/support/io/MockInputStream.java
Removed:
branches/db4o/freenet/test/freenet/support/api/
Modified:
branches/db4o/freenet/build.xml
branches/db4o/freenet/src/freenet/client/ArchiveManager.java
branches/db4o/freenet/src/freenet/client/async/USKFetcher.java
branches/db4o/freenet/src/freenet/client/async/USKManager.java
branches/db4o/freenet/src/freenet/crypt/SSL.java
branches/db4o/freenet/src/freenet/keys/Key.java
branches/db4o/freenet/src/freenet/l10n/freenet.l10n.de.properties
branches/db4o/freenet/src/freenet/l10n/freenet.l10n.en.properties
branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-cn.properties
branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-tw.properties
branches/db4o/freenet/src/freenet/node/KeyTracker.java
branches/db4o/freenet/src/freenet/node/Node.java
branches/db4o/freenet/src/freenet/node/NodeClientCore.java
branches/db4o/freenet/src/freenet/node/PeerManager.java
branches/db4o/freenet/src/freenet/node/PeerNode.java
branches/db4o/freenet/src/freenet/node/TestnetHandler.java
branches/db4o/freenet/src/freenet/node/fcp/FCPConnectionInputHandler.java
branches/db4o/freenet/src/freenet/support/DoublyLinkedList.java
branches/db4o/freenet/src/freenet/support/DoublyLinkedListImpl.java
branches/db4o/freenet/src/freenet/support/HTMLNode.java
branches/db4o/freenet/src/freenet/support/LRUHashtable.java
branches/db4o/freenet/src/freenet/support/LRUQueue.java
branches/db4o/freenet/src/freenet/support/io/ArrayBucket.java
branches/db4o/freenet/src/freenet/support/io/ArrayBucketFactory.java
branches/db4o/freenet/src/freenet/support/io/LineReadingInputStream.java
branches/db4o/freenet/src/freenet/support/io/TempBucketFactory.java
branches/db4o/freenet/src/freenet/support/io/TooLongException.java
branches/db4o/freenet/test/freenet/clients/http/filter/ContentFilterTest.java
branches/db4o/freenet/test/freenet/support/compress/GzipCompressorTest.java
branches/db4o/freenet/test/freenet/support/io/LineReadingInputStreamTest.java
Log:
Merge build 1157 to db4o branch: changes from 21939 to 22001.
Modified: branches/db4o/freenet/build.xml
===================================================================
--- branches/db4o/freenet/build.xml 2008-09-24 20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/build.xml 2008-09-24 22:16:49 UTC (rev 22824)
@@ -82,6 +82,7 @@
<pathelement location="javax-security.jar"/>
<pathelement location="javax-crypto.jar"/>
</classpath>
+ <compilerarg value="-Xlint"/>
<!-- following a very temporary list of files to be
build -->
<include name="org/**/*.java"/>
@@ -128,12 +129,16 @@
<!-- ================================================== -->
<target name="unit-build" depends="compile" if="junit.present"
unless="skip_tests">
+ <delete dir="${build-test}"/>
+ <mkdir dir="${build-test}"/>
+
<javac srcdir="${test}" destdir="${build-test}" debug="on"
optimize="on" source="1.5">
<classpath>
<pathelement path="${build}"/>
<pathelement
location="${freenet-ext.location}"/>
<pathelement location="${junit.location}"/>
</classpath>
+ <compilerarg value="-Xlint"/>
<include name="**/*.java"/>
<exclude name="*.java"/>
</javac>
@@ -152,7 +157,7 @@
<batchtest fork="yes">
<fileset dir="${build-test}">
- <include name="**/*.class"/>
+ <include name="**/*Test.class"/>
</fileset>
</batchtest>
<sysproperty key="benchmark" value="${benchmark}" />
Modified: branches/db4o/freenet/src/freenet/client/ArchiveManager.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/ArchiveManager.java
2008-09-24 20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/client/ArchiveManager.java
2008-09-24 22:16:49 UTC (rev 22824)
@@ -38,7 +38,8 @@
public static final String METADATA_NAME = ".metadata";
private static boolean logMINOR;
- final long maxArchiveSize;
+ private long maxArchiveSize;
+
final long maxArchivedFileSize;
// ArchiveHandler's
@@ -215,7 +216,7 @@
ctx.setLastHash(realHash);
}
if(data.size() > maxArchiveSize)
- throw new ArchiveFailureException("Archive too big");
+ throw new ArchiveFailureException("Archive too big
("+data.size()+" > "+maxArchiveSize+")!");
if(archiveType != Metadata.ARCHIVE_ZIP)
throw new ArchiveFailureException("Unknown or
unsupported archive algorithm "+archiveType);
@@ -491,4 +492,12 @@
public static void init(ObjectContainer container, ClientContext
context, final long nodeDBHandle) {
ArchiveHandlerImpl.init(container, context, nodeDBHandle);
}
+
+ public synchronized long getMaxArchiveSize() {
+ return maxArchiveSize;
+ }
+
+ public synchronized void setMaxArchiveSize(long maxArchiveSize) {
+ this.maxArchiveSize = maxArchiveSize;
+ }
}
Modified: branches/db4o/freenet/src/freenet/client/async/USKFetcher.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/async/USKFetcher.java
2008-09-24 20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/client/async/USKFetcher.java
2008-09-24 22:16:49 UTC (rev 22824)
@@ -162,6 +162,7 @@
checker.schedule(container, context);
}
+ @Override
public String toString() {
return "USKAttempt for "+number+" for
"+origUSK.getURI()+" for "+USKFetcher.this;
}
@@ -471,7 +472,7 @@
if (delay<=0) {
schedule(container, context);
} else {
- uskManager.ticker.queueTimedJob(new Runnable() {
+ context.ticker.queueTimedJob(new Runnable() {
public void run() {
USKFetcher.this.schedule(null, context);
}
Modified: branches/db4o/freenet/src/freenet/client/async/USKManager.java
===================================================================
--- branches/db4o/freenet/src/freenet/client/async/USKManager.java
2008-09-24 20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/client/async/USKManager.java
2008-09-24 22:16:49 UTC (rev 22824)
@@ -13,7 +13,7 @@
import freenet.node.NodeClientCore;
import freenet.node.RequestClient;
import freenet.node.RequestStarter;
-import freenet.node.Ticker;
+import freenet.support.Executor;
import freenet.support.LRUQueue;
import freenet.support.Logger;
@@ -45,7 +45,7 @@
final FetchContext backgroundFetchContext;
- final Ticker ticker;
+ final Executor executor;
private ClientContext context;
@@ -58,7 +58,7 @@
checkersByUSK = new HashMap();
backgroundFetchersByClearUSK = new HashMap();
temporaryBackgroundFetchersLRU = new LRUQueue();
- ticker = core.getTicker();
+ executor = core.getExecutor();
}
public void init(ObjectContainer container, ClientContext context) {
@@ -160,15 +160,15 @@
}
if(callbacks != null) {
// Run off-thread, because of locking, and because
client callbacks may take some time
- ticker.queueTimedJob(new Runnable() {
- public void run() {
- USK usk = origUSK.copy(number);
- for(int i=0;i<callbacks.length;i++)
-
callbacks[i].onFoundEdition(number, usk, null, // non-persistent
- context, false,
(short)-1, null);
+ final USK usk = origUSK.copy(number);
+ for(final USKCallback callback :
callbacks)
+
context.mainExecutor.execute(new Runnable() {
+ public void run() {
+
callback.onFoundEdition(number, usk, null, // non-persistent
+
context, false, (short)-1, null);
+ }
+ }, "USKManager callback
executor for " +callback);
}
- }, 0);
- }
}
/**
@@ -214,11 +214,11 @@
cb.onFoundEdition(curEd, origUSK.copy(curEd), null,
context, false, (short)-1, null);
final USKFetcher fetcher = sched;
if(fetcher != null) {
- ticker.queueTimedJob(new Runnable() {
+ executor.execute(new Runnable() {
public void run() {
fetcher.schedule(null, context);
}
- }, 0);
+ }, "USKManager.schedule for "+fetcher);
}
}
Modified: branches/db4o/freenet/src/freenet/crypt/SSL.java
===================================================================
--- branches/db4o/freenet/src/freenet/crypt/SSL.java 2008-09-24 20:42:20 UTC
(rev 22823)
+++ branches/db4o/freenet/src/freenet/crypt/SSL.java 2008-09-24 22:16:49 UTC
(rev 22824)
@@ -28,8 +28,6 @@
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
-import com.sleepycat.je.utilint.NotImplementedYetException;
-
import freenet.config.InvalidConfigValueException;
import freenet.config.SubConfig;
import freenet.support.Logger;
Modified: branches/db4o/freenet/src/freenet/keys/Key.java
===================================================================
--- branches/db4o/freenet/src/freenet/keys/Key.java 2008-09-24 20:42:20 UTC
(rev 22823)
+++ branches/db4o/freenet/src/freenet/keys/Key.java 2008-09-24 22:16:49 UTC
(rev 22824)
@@ -123,16 +123,20 @@
public abstract short getType();
+ @Override
public int hashCode() {
return hash;
}
+ @Override
public boolean equals(Object o){
if(o == null || !(o instanceof Key)) return false;
return Arrays.equals(routingKey, ((Key)o).routingKey);
}
- static Bucket decompress(boolean isCompressed, byte[] output, int
outputLength, BucketFactory bf, int maxLength, short compressionAlgorithm,
boolean shortLength) throws CHKDecodeException, IOException {
+ static Bucket decompress(boolean isCompressed, byte[] output, int
outputLength, BucketFactory bf, long maxLength, short compressionAlgorithm,
boolean shortLength) throws CHKDecodeException, IOException {
+ if(maxLength < 0)
+ throw new IllegalArgumentException("maxlength="+maxLength);
if(isCompressed) {
if(Logger.shouldLog(Logger.MINOR, Key.class))
Logger.minor(Key.class, "Decompressing
"+output.length+" bytes in decode with codec "+compressionAlgorithm);
@@ -146,7 +150,7 @@
len = ((((((output[0] & 0xff) << 8) + (output[1] & 0xff)) << 8)
+ (output[2] & 0xff)) << 8) +
(output[3] & 0xff);
if(len > maxLength)
- throw new TooBigException("Invalid precompressed size: "+len);
+ throw new TooBigException("Invalid precompressed size: "+len +
" maxlength="+maxLength);
Compressor decompressor =
Compressor.getCompressionAlgorithmByMetadataID(compressionAlgorithm);
Bucket inputBucket = new SimpleReadOnlyArrayBucket(output,
shortLength?2:4, outputLength-(shortLength?2:4));
try {
Modified: branches/db4o/freenet/src/freenet/l10n/freenet.l10n.de.properties
===================================================================
--- branches/db4o/freenet/src/freenet/l10n/freenet.l10n.de.properties
2008-09-24 20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/l10n/freenet.l10n.de.properties
2008-09-24 22:16:49 UTC (rev 22824)
@@ -86,11 +86,15 @@
ConfigToadlet.fproxy=FProxy
ConfigToadlet.fullTitle=Freenet-Knoten-Konfiguration von ${name}
ConfigToadlet.logger=Logger
+ConfigToadlet.needRestart=Eine Einstellung ben?tigt einen Neustart um in Kraft
treten zu k?nnen. Bitte starten Sie den Knoten umgehend neu.
+ConfigToadlet.needRestartShort=Eine Einstellung ben?tigt einen Neustart um in
Kraft treten zu k?nnen. Bitte starten Sie den Knoten umgehend neu.
+ConfigToadlet.needRestartTitle=Neustart des Knotens erforderlich
ConfigToadlet.node=Knoten
ConfigToadlet.pluginmanager=Plugin-Manager
ConfigToadlet.pluginmanager2=Plugin-Manager 2
ConfigToadlet.possibilitiesTitle=Fortsetzen
ConfigToadlet.reset=Zur?cksetzen
+ConfigToadlet.restartNode=Jetzt Neustarten
ConfigToadlet.returnToNodeConfig=Zur?ck zur Knoten-Konfiguration
ConfigToadlet.shortTitle=Konfiguration
ConfigToadlet.ssl=SSL (ben?tigt Neustart)
@@ -421,12 +425,12 @@
FirstTimeWizardToadlet.congratz=Willkommen an Bord!
FirstTimeWizardToadlet.congratzLong=Herzlichen Gl?ckwunsch, die
Basis-Konfiguration Ihres Freenet-Knotens ist nun abgeschlossen. Sie k?nnen
alle Parameter, die Sie soeben eingestellt haben, ?ndern indem Sie auf die
"Konfiguration"s-Seite gehen, diese ist jederzeit vom Men? auf der linken Seite
der Oberfl?che erreichbar. Bitte beachten Sie, dass Freenet zu Anfang langsam
sein wird, dies wird sich mit der Zeit verbessern. Sie k?nnen beginnen indem
Sie auf die Lesezeichen auf der n?chsten Seite klicken. Wir w?nschen Ihnen ein
angenehmes Freenet-Erlebnis.
FirstTimeWizardToadlet.connectToStrangers=Mit Fremden verbinden?
-FirstTimeWizardToadlet.connectToStrangersLong=Im Idealfall w?rden sich alle
Freenet-Benutzer nur mit Leuten verbinden, die sie kennen. Dies ist weitaus
sicherer, da es es sehr schwer f?r andere macht herauszufinden, dass Sie
Freenet benutzen. Wenn Sie jedoch nicht mindestens 5 Leute kennen, die bereits
Freenet benutzen, k?nnen Sie entscheiden sich mit Fremden zu verbinden.
Beachten Sie, dass Sie dies jederzeit wieder ausschalten k?nnen.
+FirstTimeWizardToadlet.connectToStrangersLong=Um Freenet zu benutzen m?ssen
Sie sich mit mindestens f?nf anderen Knoten verbinden. Diese sollten im
Idealfall von Leuten betrieben werden, die Sie kennen und denen Sie vertrauen.
Wenn Sie nicht genug Leute kennen, die Freenet benutzen, k?nnen Sie sich dazu
entschlie?en sich auch mit den Knoten von Fremden zu verbinden. Sich mit
Fremden zu verbinden erm?glicht es jedoch anderen herauszufinden, dass Sie
Freenet benutzen und birgt andere zus?tzliche Sicherheits-Risiken. Wenn Sie die
Tatsache, dass Sie Freenet benutzen, geheim halten wollen, k?nnte Sie dies in
Schwierigkeiten bringen.
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, besonders das Herunterladen, sein.
-FirstTimeWizardToadlet.enableOpennet=Kennen Sie jemanden, der bereits Freenet
benutzt?
+FirstTimeWizardToadlet.enableOpennet=Es ist auch sp?ter, wenn Sie genug
Freunde hinzugef?gt haben, noch m?glich die Verbindung zu Fremden
auszuschalten. Sie werden dann jedoch in der Zwischenzeit bereits ein paar
Informationen an Fremde preisgegeben haben. Freenet ist immer noch
experimentell und wir geben keine Garantie f?r die Sicherheit.
FirstTimeWizardToadlet.fivePercentDisk=(= 5% des freien Speicherplatzes)
FirstTimeWizardToadlet.homepageTitle=Freenet-Einrichtungs-Assistent!
FirstTimeWizardToadlet.iDoTrust=Trauen Sie Leuten die mit ${interface} (${ip})
verbunden sind?
@@ -436,9 +440,9 @@
FirstTimeWizardToadlet.memoryLimitLong=Wie viel (Arbeits-)Speicher m?chten Sie
Freenet erlauben zu benutzen? Wenn Sie viele Downloads oder Uploads in der
Warteschlange haben, wird Freenet mehr Speicher brauchen. Wir empfehlen Ihnen
dies nicht auf weniger als 128MB zu setzen, es sei denn Sie haben wirklich
wenig RAM. Wenn Sie 1GB oder mehr haben, sollten Sie dies wahrscheinlich auf
mindestens 256MB setzen. Diese Einstellung wird nach einem Neustart von Freenet
wirksam.
FirstTimeWizardToadlet.noNetworkIF=Keine zus?tzliche Netzwerk-Schnittstelle
gefunden
FirstTimeWizardToadlet.noNetworkIFLong=Freenet hat keine zus?tzliche
Netzwerk-Schnittstelle gefunden. Es wird annehmen, dass Sie sich von Ihrem
Computer (und nur von Ihrem Computer) mit ihm verbinden.
-FirstTimeWizardToadlet.opennetNo=Ja, ich habe mindestens 5 Freunde, die
bereits Freenet benutzen und werde Ihre Kontaktdaten auf der Freunde-Seite
eintragen.
+FirstTimeWizardToadlet.opennetNo=Ich habe mindestens 5 Freunde, die bereits
Freenet benutzen und werde Ihre Kontaktdaten auf der Freunde-Seite eintragen.
FirstTimeWizardToadlet.opennetWarning=Wenn Freenet dort wo Sie leben illegal
ist oder wenn Sie es benutzen um Inhalte abzurufen, die Sie in Schwierigkeiten
bringen k?nnten, kann es sein, dass dem Knoten zu sagen, dass er sich
automatisch mit Fremden verbinden soll, gef?hrlich ist, da es das Leben eines
Angreifers deutlich erleichtert. Freenet ist immer noch experimentell und wir
geben keine Garantie f?r die Sicherheit.
-FirstTimeWizardToadlet.opennetYes=Nein, ich m?chte, dass der Knoten
automatisch Fremde findet mit denen er sich verbinden kann.
+FirstTimeWizardToadlet.opennetYes=Ich m?chte, dass der Knoten automatisch
Fremde findet mit denen er sich verbinden kann.
FirstTimeWizardToadlet.skipWizard=Ich bin kein Neuling, bitte ?berspringe den
Assistenten!
FirstTimeWizardToadlet.step1Title=Freenet-Einrichtungs-Assistent! - Freunde
und Fremde
FirstTimeWizardToadlet.step2Title=Freenet-Einrichtungs-Assistent! - W?hlen Sie
einen Knoten-Namen
@@ -719,16 +723,24 @@
NodeClientCore.downloadAllowedDirsLong=Per Semikolon getrennte Liste von
Verzeichnissen, in welche das Herunterladen erlaubt ist. "downloads" steht f?r
das Download-Verzeichnis, wenn das Feld leer ist bedeutet dies, dass keine
Dateien auf Datentr?ger heruntergeladen werden d?rfen, "all" erlaubt das
Herunterladen ?berall hin. WARNUNG! Wenn diese Option auf "all" gesetzt wird,
kann jeder Benutzer jede Datei an jeden Ort auf Ihrem Computer herunterladen!
NodeClientCore.downloadDir=Standard Download-Verzeichnis
NodeClientCore.downloadDirLong=Das Verzeichnis in welchem heruntergeladene
Dateien standardm??ig gespeichert werden
+NodeClientCore.encryptPersistentTempBuckets=Die tempor?ren persistenten
Buckets verschl?sseln? LASSEN SIE DIES IN RUHE!
+NodeClientCore.encryptPersistentTempBucketsLong=Die tempor?ren persistenten
Buckets verschl?sseln? In manchen F?llen (wenn Sie Festplatten- und
Swap-Verschl?sselung benutzen) kann es sein, dass es keinen Sinn macht die
tempor?ren persistenten Buckets zu verschl?sseln. LASSEN SIE DIE FINGER DAVON,
WENN SIE NICHT GENAU WISSEN WAS SIE TUN!
+NodeClientCore.encryptTempBuckets=Die tempor?ren Buckets verschl?sseln? LASSEN
SIE DIES IN RUHE!
+NodeClientCore.encryptTempBucketsLong=Die tempor?ren Buckets verschl?sseln? In
manchen F?llen (wenn Sie Festplatten- und Swap-Verschl?sselung benutzen) kann
es sein, dass es keinen Sinn macht die tempor?ren Buckets zu verschl?sseln.
LASSEN SIE DIE FINGER DAVON, WENN SIE NICHT GENAU WISSEN WAS SIE TUN!
NodeClientCore.fileForClientStats=Datei in welcher die Statistiken gespeichert
werden
NodeClientCore.fileForClientStatsLong=Datei in der die Drosselungs-Statistiken
gespeichert werden (wird ben?tigt um herauszufinden wie oft Anfragen gesendet
werden sollen).
NodeClientCore.lazyResume=Vervollst?ndige das Laden persistenter Anfragen beim
Start? (Braucht mehr Speicher)
NodeClientCore.lazyResumeLong=Der Knoten kann persistente (dauerhafte)
anstehende Anfragen beim Starten laden, oder er kann die Daten in den Speicher
einlesen und dann die Anfragen nachdem der Knoten vollst?ndig gestartet ist
komplettieren. K?rzere Start-Zeiten, braucht aber mehr Speicher.
+NodeClientCore.maxRAMBucketSize=Maximale Gr??e eines RAMBuckets
+NodeClientCore.maxRAMBucketSizeLong=Maximale Gr??e eines RAMBuckets (gr??ere
Buckets werden als Dateien auf der Festplatte gespeichert)
NodeClientCore.maxUSKFetchers=Maximal erlaubte Anzahl von USK-Abrufern
NodeClientCore.maxUSKFetchersLong=Maximale Anzahl zugelassener USK-Abrufer
NodeClientCore.maxUSKFetchersMustBeGreaterThanZero=Muss gr??er als Null sein
NodeClientCore.movingTempDirOnTheFlyNotSupported=Das Verschieben des
tempor?ren Verzeichnisses im laufenden Betrieb, wird im Moment (noch?) nicht
unterst?tzt
NodeClientCore.persistentTempDir=Verzeichnis f?r persistente tempor?re Dateien
NodeClientCore.persistentTempDirLong=Name des Verzeichnisses in welchem
persistente (dauerhafte) tempor?re Dateien gespeichert werden
+NodeClientCore.ramBucketPoolSize=Menge an RAM das f?r tempor?re Buckets
reserviert wird
+NodeClientCore.ramBucketPoolSizeLong=Menge an RAM das f?r tempor?re Buckets
reserviert wird. Es ist ein Kompromiss zwischen mehr Speicherauslastung und
mehr IO-Zugriffen.
NodeClientCore.startingUp=Bitte geben Sie Freenet etwas Zeit, um komplett zu
starten. In der Zwischenzeit k?nnte es sein, dass einige Dinge nicht
funkionieren und der Knoten langsamer als gew?hnlich ist.
NodeClientCore.startingUpShort=Freenet startet noch, einige Dinge k?nnten noch
nicht funktionieren und der Knoten k?nnte langsam sein.
NodeClientCore.startingUpTitle=Freenet startet gerade.
@@ -1060,6 +1072,8 @@
SimpleToadletServer.illegalCSSName=CSS-Namen d?rfen keine Schr?gstriche oder
Doppelpunkte enthalten!
SimpleToadletServer.panicButton=Den Alarm-Knopf anzeigen?
SimpleToadletServer.panicButtonLong=Zeigt einen "Alarm-Knopf" auf der
Warteschlangen-Seite an, welcher alle Anfragen ohne Nachfrage entfernt.
+SimpleToadletServer.passthroughMaxSize=Maximale Gr??e f?r das transparente
Durchreichen in FProxy
+SimpleToadletServer.passthroughMaxSizeLong=Maximale Gr??e einer Datei f?r das
transparente Durchreichen in FProxy
SimpleToadletServer.port=FProxy-Port
SimpleToadletServer.portLong=Der TCP-Port auf dem FProxy Nachrichten empfangen
soll
SimpleToadletServer.ssl=SSL aktivieren?
Modified: branches/db4o/freenet/src/freenet/l10n/freenet.l10n.en.properties
===================================================================
--- branches/db4o/freenet/src/freenet/l10n/freenet.l10n.en.properties
2008-09-24 20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/l10n/freenet.l10n.en.properties
2008-09-24 22:16:49 UTC (rev 22824)
@@ -717,6 +717,8 @@
Node.tooSmallMTUShort=Connection problems: Your connection's MTU is too short
for Freenet to work well. Expect problems.
Node.withAnnouncement=Allow the node to bootstrap itself using seednodes?
Node.withAnnouncementLong=Allow the node to bootstrap itself using seednodes?
While this has to be the default behaviour, it's insecure by design.
+NodeClientCore.maxArchiveSize=Maximum size of any given archive
+NodeClientCore.maxArchiveSizeLong=Maximum size of any given archive
NodeClientCore.couldNotFindOrCreateDir=Could not find or create directory
NodeClientCore.downloadAllowedDirs=Directories downloading is allowed to
NodeClientCore.downloadAllowedDirsLong=Semicolon separated list of directories
to which downloads are allowed. "downloads" means downloadsDir, empty means no
downloads to disk allowed, "all" means downloads allowed from anywhere.
WARNING! If this is set to "all" any user can download any file to anywhere on
your computer!
Modified: branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-cn.properties
===================================================================
--- branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-cn.properties
2008-09-24 20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-cn.properties
2008-09-24 22:16:49 UTC (rev 22824)
@@ -90,11 +90,15 @@
ConfigToadlet.logger=???
ConfigToadlet.modeAdvanced=??????
ConfigToadlet.modeSimple=??????
+ConfigToadlet.needRestart=?????????????, ???????.
+ConfigToadlet.needRestartShort=?????????????, ???????.
+ConfigToadlet.needRestartTitle=??????
ConfigToadlet.node=??
ConfigToadlet.pluginmanager=?????
ConfigToadlet.pluginmanager2=?????2
ConfigToadlet.possibilitiesTitle=??
ConfigToadlet.reset=??
+ConfigToadlet.restartNode=????
ConfigToadlet.returnToNodeConfig=??????
ConfigToadlet.shortTitle=??
ConfigToadlet.ssl=SSL (????)
@@ -728,16 +732,26 @@
NodeClientCore.downloadAllowedDirsLong=?????????????, ??????. ???? downloads
?????????, ???????????????????, ??? all ??????????????. ??! ????? all ??,
?????????????????, ??????????????!
NodeClientCore.downloadDir=??????
NodeClientCore.downloadDirLong=??????????????
+NodeClientCore.encryptPersistentTempBuckets=??????????? ????!
+NodeClientCore.encryptPersistentTempBucketsLong=???????????????
????????????????????(?????????????????). ????????????????????!
+NodeClientCore.encryptTempBuckets=???????? ????!
+NodeClientCore.encryptTempBucketsLong=????????????
????????????????(?????????????????). ????????????????????!
NodeClientCore.fileForClientStats=????????????
NodeClientCore.fileForClientStatsLong=??????????????(???????????)
NodeClientCore.lazyResume=?????????????? (????????)
NodeClientCore.lazyResumeLong=???????????????, ??????????????,
????????????????. ???????, ??????????.
+NodeClientCore.maxArchiveSize=??????????
+NodeClientCore.maxArchiveSizeLong=??????????
+NodeClientCore.maxRAMBucketSize=??????????
+NodeClientCore.maxRAMBucketSizeLong=?????(RAMBucket)?????(??????????????)
NodeClientCore.maxUSKFetchers=??? USK ???????
NodeClientCore.maxUSKFetchersLong=??? USK ???????
NodeClientCore.maxUSKFetchersMustBeGreaterThanZero=?????
NodeClientCore.movingTempDirOnTheFlyNotSupported=????????????????
NodeClientCore.persistentTempDir=?????????
NodeClientCore.persistentTempDirLong=?????????????
+NodeClientCore.ramBucketPoolSize=???????????
+NodeClientCore.ramBucketPoolSizeLong=???????????. ??????????????????.
NodeClientCore.startingUp=?? Freenet ???????????, ???????????????,
?????????????.
NodeClientCore.startingUpShort=Freenet ?????, ??????????, ?????????.
NodeClientCore.startingUpTitle=Freenet ?????
@@ -1072,6 +1086,8 @@
SimpleToadletServer.illegalCSSName=CSS ???????????!
SimpleToadletServer.panicButton=?????????
SimpleToadletServer.panicButtonLong=???????'????', ????????????????, ?????????.
+SimpleToadletServer.passthroughMaxSize=Fproxy ????????
+SimpleToadletServer.passthroughMaxSizeLong=Fproxy ????????????
SimpleToadletServer.port=FProxy ????
SimpleToadletServer.portLong=FProxy ????? TCP ????
SimpleToadletServer.ssl=?? SSL?
Modified: branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-tw.properties
===================================================================
--- branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-tw.properties
2008-09-24 20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/l10n/freenet.l10n.zh-tw.properties
2008-09-24 22:16:49 UTC (rev 22824)
@@ -89,11 +89,15 @@
ConfigToadlet.logger=???
ConfigToadlet.modeAdvanced=??????
ConfigToadlet.modeSimple=??????
+ConfigToadlet.needRestart=?????????????, ???????.
+ConfigToadlet.needRestartShort=?????????????, ???????.
+ConfigToadlet.needRestartTitle=??????
ConfigToadlet.node=??
ConfigToadlet.pluginmanager=?????
ConfigToadlet.pluginmanager2=?????2
ConfigToadlet.possibilitiesTitle=??
ConfigToadlet.reset=??
+ConfigToadlet.restartNode=????
ConfigToadlet.returnToNodeConfig=??????
ConfigToadlet.shortTitle=??
ConfigToadlet.ssl=SSL (????)
@@ -727,16 +731,26 @@
NodeClientCore.downloadAllowedDirsLong=?????????????, ??????. ???? downloads
?????????, ???????????????????, ??? all ??????????????. ??! ????? all ??,
?????????????????, ?????????????!
NodeClientCore.downloadDir=??????
NodeClientCore.downloadDirLong=??????????????
+NodeClientCore.encryptPersistentTempBuckets=??????????? ????!
+NodeClientCore.encryptPersistentTempBucketsLong=???????????????
????????????????????(?????????????????). ????????????????????!
+NodeClientCore.encryptTempBuckets=???????? ????!
+NodeClientCore.encryptTempBucketsLong=????????????
????????????????(?????????????????). ????????????????????!
NodeClientCore.fileForClientStats=????????????
NodeClientCore.fileForClientStatsLong=??????????????(???????????)
NodeClientCore.lazyResume=?????????????? (?????????)
NodeClientCore.lazyResumeLong=???????????????, ???????????????,
????????????????. ???????, ???????????.
+NodeClientCore.maxArchiveSize=??????????
+NodeClientCore.maxArchiveSizeLong=??????????
+NodeClientCore.maxRAMBucketSize=??????????
+NodeClientCore.maxRAMBucketSizeLong=?????(RAMBucket)?????(??????????????)
NodeClientCore.maxUSKFetchers=??? USK ???????
NodeClientCore.maxUSKFetchersLong=??? USK ???????
NodeClientCore.maxUSKFetchersMustBeGreaterThanZero=?????
NodeClientCore.movingTempDirOnTheFlyNotSupported=????????????????
NodeClientCore.persistentTempDir=?????????
NodeClientCore.persistentTempDirLong=?????????????
+NodeClientCore.ramBucketPoolSize=????????????
+NodeClientCore.ramBucketPoolSizeLong=????????????. ???????????????????.
NodeClientCore.startingUp=?? Freenet ???????????, ???????????????,
?????????????.
NodeClientCore.startingUpShort=Freenet ?????, ??????????, ?????????.
NodeClientCore.startingUpTitle=Freenet ?????
@@ -1071,6 +1085,8 @@
SimpleToadletServer.illegalCSSName=CSS ???????????!
SimpleToadletServer.panicButton=?????????
SimpleToadletServer.panicButtonLong=???????'????', ????????????????, ?????????.
+SimpleToadletServer.passthroughMaxSize=Fproxy ????????
+SimpleToadletServer.passthroughMaxSizeLong=Fproxy ????????????
SimpleToadletServer.port=FProxy ???
SimpleToadletServer.portLong=FProxy ????? TCP ???
SimpleToadletServer.ssl=?? SSL?
Modified: branches/db4o/freenet/src/freenet/node/KeyTracker.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/KeyTracker.java 2008-09-24
20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/node/KeyTracker.java 2008-09-24
22:16:49 UTC (rev 22824)
@@ -37,254 +37,251 @@
public class KeyTracker {
private static boolean logMINOR;
-
- /** Parent PeerNode */
- public final PeerNode pn;
-
- /** Are we the secondary key? */
- private boolean isDeprecated;
-
- /** Cipher to both encrypt outgoing packets with and decrypt
- * incoming ones. */
- public final BlockCipher sessionCipher;
-
- /** Key for above cipher, so far for debugging */
- public final byte[] sessionKey;
-
- /** Packets we have sent to the node, minus those that have
- * been acknowledged. */
- private final LimitedRangeIntByteArrayMap sentPacketsContents;
-
- /** Serial numbers of packets that we want to acknowledge,
- * and when they become urgent. We always add to the end,
- * and we always remove from the beginning, so should always
- * be consistent. */
- private final List ackQueue;
-
- /** Serial numbers of packets that we have forgotten. Usually
- * when we have forgotten a packet it just means that it has
- * been shifted to another KeyTracker because this one was
- * deprecated; the messages will get through in the end.
- */
- private final List forgottenQueue;
-
- /** The highest incoming serial number we have ever seen
- * from the other side. Includes actual packets and resend
- * requests (provided they are within range). */
- private int highestSeenIncomingSerialNumber;
-
- /** Serial numbers of packets we want to be resent by the
- * other side to us, the time at which they become sendable,
- * and the time at which they become urgent. In order of
- * the latter. */
- private final UpdatableSortedLinkedListWithForeignIndex resendRequestQueue;
-
- /** Serial numbers of packets we want to be acknowledged by
- * the other side, the time at which they become sendable,
- * and the time at which they become urgent. In order of
- * the latter. */
- private final UpdatableSortedLinkedListWithForeignIndex ackRequestQueue;
-
- /** Numbered packets that we need to send to the other side
- * because they asked for them. Just contains the numbers. */
- private final HashSet packetsToResend;
-
- /** Ranges of packet numbers we have received from the other
- * side. */
- private final ReceivedPacketNumbers packetNumbersReceived;
-
- /** Counter to generate the next packet number */
- private int nextPacketNumber;
-
- final long createdTime;
-
+ /** Parent PeerNode */
+ public final PeerNode pn;
+ /** Are we the secondary key? */
+ private volatile boolean isDeprecated;
+ /** Cipher to both encrypt outgoing packets with and decrypt
+ * incoming ones. */
+ public final BlockCipher sessionCipher;
+ /** Key for above cipher, so far for debugging */
+ public final byte[] sessionKey;
+ /** Packets we have sent to the node, minus those that have
+ * been acknowledged. */
+ private final LimitedRangeIntByteArrayMap sentPacketsContents;
+ /** Serial numbers of packets that we want to acknowledge,
+ * and when they become urgent. We always add to the end,
+ * and we always remove from the beginning, so should always
+ * be consistent. */
+ private final List ackQueue;
+ /** Serial numbers of packets that we have forgotten. Usually
+ * when we have forgotten a packet it just means that it has
+ * been shifted to another KeyTracker because this one was
+ * deprecated; the messages will get through in the end.
+ */
+ private final List forgottenQueue;
+ /** The highest incoming serial number we have ever seen
+ * from the other side. Includes actual packets and resend
+ * requests (provided they are within range). */
+ private int highestSeenIncomingSerialNumber;
+ /** Serial numbers of packets we want to be resent by the
+ * other side to us, the time at which they become sendable,
+ * and the time at which they become urgent. In order of
+ * the latter. */
+ private final UpdatableSortedLinkedListWithForeignIndex
resendRequestQueue;
+ /** Serial numbers of packets we want to be acknowledged by
+ * the other side, the time at which they become sendable,
+ * and the time at which they become urgent. In order of
+ * the latter. */
+ private final UpdatableSortedLinkedListWithForeignIndex ackRequestQueue;
+ /** Numbered packets that we need to send to the other side
+ * because they asked for them. Just contains the numbers. */
+ private final HashSet packetsToResend;
+ /** Ranges of packet numbers we have received from the other
+ * side. */
+ private final ReceivedPacketNumbers packetNumbersReceived;
+ /** Counter to generate the next packet number */
+ private int nextPacketNumber;
+ final long createdTime;
/** The time at which we last successfully decoded a packet. */
private long timeLastDecodedPacket;
-
- /** Everything is clear to start with */
- KeyTracker(PeerNode pn, BlockCipher cipher, byte[] sessionKey) {
- this.pn = pn;
- this.sessionCipher = cipher;
- this.sessionKey = sessionKey;
- ackQueue = new LinkedList();
- forgottenQueue = new LinkedList();
- highestSeenIncomingSerialNumber = -1;
- // give some leeway
- sentPacketsContents = new LimitedRangeIntByteArrayMap(128);
- resendRequestQueue = new UpdatableSortedLinkedListWithForeignIndex();
- ackRequestQueue = new UpdatableSortedLinkedListWithForeignIndex();
- packetsToResend = new HashSet();
- packetNumbersReceived = new ReceivedPacketNumbers(512);
- isDeprecated = false;
- nextPacketNumber = pn.node.random.nextInt(100*1000);
- createdTime = System.currentTimeMillis();
- logMINOR = Logger.shouldLog(Logger.MINOR, this);
- }
- /**
- * Set the deprecated flag to indicate that we are now
- * no longer the primary key. And wake up any threads trying to lock
- * a packet number; they can be sent with the new KT.
- *
- * After this, new packets will not be sent. It will not be possible to
allocate a new
- * packet number. However, old resend requests etc may still be sent.
- */
- public void deprecated() {
- logMINOR = Logger.shouldLog(Logger.MINOR, this);
- isDeprecated = true;
- sentPacketsContents.interrupt();
- }
-
- /**
- * @return The highest received incoming serial number.
- */
- public int highestReceivedIncomingSeqNumber() {
- return this.highestSeenIncomingSerialNumber;
- }
+ /** Everything is clear to start with */
+ KeyTracker(PeerNode pn, BlockCipher cipher, byte[] sessionKey) {
+ this.pn = pn;
+ this.sessionCipher = cipher;
+ this.sessionKey = sessionKey;
+ ackQueue = new LinkedList();
+ forgottenQueue = new LinkedList();
+ highestSeenIncomingSerialNumber = -1;
+ // give some leeway
+ sentPacketsContents = new LimitedRangeIntByteArrayMap(128);
+ resendRequestQueue = new
UpdatableSortedLinkedListWithForeignIndex();
+ ackRequestQueue = new
UpdatableSortedLinkedListWithForeignIndex();
+ packetsToResend = new HashSet();
+ packetNumbersReceived = new ReceivedPacketNumbers(512);
+ isDeprecated = false;
+ nextPacketNumber = pn.node.random.nextInt(100 * 1000);
+ createdTime = System.currentTimeMillis();
+ logMINOR = Logger.shouldLog(Logger.MINOR, this);
+ }
- /**
- * Received this packet??
- */
- public boolean alreadyReceived(int seqNumber) {
- return packetNumbersReceived.contains(seqNumber);
- }
-
- /** toString() - don't leak the key unless asked to */
- public String toString() {
- return super.toString()+" for "+pn.shortToString();
- }
+ /**
+ * Set the deprecated flag to indicate that we are now
+ * no longer the primary key. And wake up any threads trying to lock
+ * a packet number; they can be sent with the new KT.
+ *
+ * After this, new packets will not be sent. It will not be possible to
allocate a new
+ * packet number. However, old resend requests etc may still be sent.
+ */
+ public void deprecated() {
+ logMINOR = Logger.shouldLog(Logger.MINOR, this);
+ isDeprecated = true;
+ sentPacketsContents.interrupt();
+ }
- /**
- * Queue an ack to be sent back to the node soon.
- * @param seqNumber The number of the packet to be acked.
- */
- public void queueAck(int seqNumber) {
- if(logMINOR) Logger.minor(this, "Queueing ack for "+seqNumber);
- QueuedAck qa = new QueuedAck(seqNumber);
- synchronized(ackQueue) {
- ackQueue.add(qa);
- }
- // Will go urgent in 200ms
- }
-
- public void queueForgotten(int seqNumber) {
- queueForgotten(seqNumber, true);
- }
-
- public void queueForgotten(int seqNumber, boolean log) {
- if(log && ((!isDeprecated) || logMINOR)) {
- String msg = "Queueing forgotten for "+seqNumber+" for "+this;
- if(!isDeprecated) Logger.error(this, msg);
- else Logger.minor(this, msg);
- }
- QueuedForgotten qf = new QueuedForgotten(seqNumber);
- synchronized(forgottenQueue) {
- forgottenQueue.add(qf);
- }
- }
-
- static class PacketActionItem { // anyone got a better name?
- /** Packet sequence number */
- int packetNumber;
- /** Time at which this packet's ack or resend request becomes urgent
- * and can trigger an otherwise empty packet to be sent. */
- long urgentTime;
-
- public String toString() {
- return super.toString()+": packet "+packetNumber+"
urgent@"+urgentTime+ '(' +(System.currentTimeMillis()-urgentTime)+ ')';
- }
- }
-
- private final static class QueuedAck extends PacketActionItem {
- QueuedAck(int packet) {
- long now = System.currentTimeMillis();
- packetNumber = packet;
- /** If not included on a packet in next 200ms, then
- * force a send of an otherwise empty packet.
- */
- urgentTime = now + 200;
- }
- }
+ /**
+ * @return The highest received incoming serial number.
+ */
+ public int highestReceivedIncomingSeqNumber() {
+ return this.highestSeenIncomingSerialNumber;
+ }
- // FIXME this is almost identical to QueuedAck, coalesce the classes
- private final static class QueuedForgotten extends PacketActionItem {
- QueuedForgotten(int packet) {
- long now = System.currentTimeMillis();
- packetNumber = packet;
- /** If not included on a packet in next 500ms, then
- * force a send of an otherwise empty packet.
- */
- urgentTime = now + 500;
- }
- }
+ /**
+ * Received this packet??
+ */
+ public boolean alreadyReceived(int seqNumber) {
+ return packetNumbersReceived.contains(seqNumber);
+ }
- private abstract class BaseQueuedResend extends PacketActionItem
implements IndexableUpdatableSortedLinkedListItem {
- /** Time at which this item becomes sendable.
- * When we send a resend request, this is reset to t+500ms.
- *
- * Constraint: urgentTime is always greater than activeTime.
- */
- long activeTime;
- final Integer packetNumberAsInteger;
-
- void sent() throws UpdatableSortedLinkedListKilledException {
- long now = System.currentTimeMillis();
- activeTime = now + 500;
- urgentTime = activeTime + urgentDelay();
- // This is only removed when we actually receive the packet
- // But for now it will sleep
- }
-
- BaseQueuedResend(int packetNumber) {
- this.packetNumber = packetNumber;
- packetNumberAsInteger = new Integer(packetNumber);
- long now = System.currentTimeMillis();
- activeTime = initialActiveTime(now);
- urgentTime = activeTime + urgentDelay();
- }
+ /** toString() - don't leak the key unless asked to */
+ @Override
+ public String toString() {
+ return super.toString() + " for " + pn.shortToString();
+ }
- abstract long urgentDelay();
-
- abstract long initialActiveTime(long now);
+ /**
+ * Queue an ack to be sent back to the node soon.
+ * @param seqNumber The number of the packet to be acked.
+ */
+ public void queueAck(int seqNumber) {
+ if(logMINOR)
+ Logger.minor(this, "Queueing ack for " + seqNumber);
+ QueuedAck qa = new QueuedAck(seqNumber);
+ synchronized(ackQueue) {
+ ackQueue.add(qa);
+ }
+ // Will go urgent in 200ms
+ }
- private Item next;
- private Item prev;
-
- public final Item getNext() {
- return next;
- }
+ public void queueForgotten(int seqNumber) {
+ queueForgotten(seqNumber, true);
+ }
- public final Item setNext(Item i) {
- Item old = next;
- next = i;
- return old;
- }
+ public void queueForgotten(int seqNumber, boolean log) {
+ if(log && ((!isDeprecated) || logMINOR)) {
+ String msg = "Queueing forgotten for " + seqNumber + "
for " + this;
+ if(!isDeprecated)
+ Logger.error(this, msg);
+ else
+ Logger.minor(this, msg);
+ }
+ QueuedForgotten qf = new QueuedForgotten(seqNumber);
+ synchronized(forgottenQueue) {
+ forgottenQueue.add(qf);
+ }
+ }
- public Item getPrev() {
- return prev;
- }
+ static class PacketActionItem { // anyone got a better name?
- public Item setPrev(Item i) {
- Item old = prev;
- prev = i;
- return old;
- }
+ /** Packet sequence number */
+ int packetNumber;
+ /** Time at which this packet's ack or resend request becomes
urgent
+ * and can trigger an otherwise empty packet to be sent. */
+ long urgentTime;
- public int compareTo(Object o) {
- BaseQueuedResend r = (BaseQueuedResend)o;
- if(urgentTime > r.urgentTime) return 1;
- if(urgentTime < r.urgentTime) return -1;
- if(packetNumber > r.packetNumber) return 1;
- if(packetNumber < r.packetNumber) return -1;
- return 0;
- }
-
- public Object indexValue() {
- return packetNumberAsInteger;
- }
-
- private DoublyLinkedList parent;
-
+ @Override
+ public String toString() {
+ return super.toString() + ": packet " + packetNumber +
" urgent@" + urgentTime + '(' + (System.currentTimeMillis() - urgentTime) + ')';
+ }
+ }
+
+ private final static class QueuedAck extends PacketActionItem {
+
+ QueuedAck(int packet) {
+ long now = System.currentTimeMillis();
+ packetNumber = packet;
+ /** If not included on a packet in next 200ms, then
+ * force a send of an otherwise empty packet.
+ */
+ urgentTime = now + 200;
+ }
+ }
+
+ // FIXME this is almost identical to QueuedAck, coalesce the classes
+ private final static class QueuedForgotten extends PacketActionItem {
+
+ QueuedForgotten(int packet) {
+ long now = System.currentTimeMillis();
+ packetNumber = packet;
+ /** If not included on a packet in next 500ms, then
+ * force a send of an otherwise empty packet.
+ */
+ urgentTime = now + 500;
+ }
+ }
+
+ private abstract class BaseQueuedResend extends PacketActionItem
+ implements IndexableUpdatableSortedLinkedListItem {
+
+ /** Time at which this item becomes sendable.
+ * When we send a resend request, this is reset to t+500ms.
+ *
+ * Constraint: urgentTime is always greater than activeTime.
+ */
+ long activeTime;
+ final Integer packetNumberAsInteger;
+
+ void sent() throws UpdatableSortedLinkedListKilledException {
+ long now = System.currentTimeMillis();
+ activeTime = now + 500;
+ urgentTime = activeTime + urgentDelay();
+ // This is only removed when we actually receive the packet
+ // But for now it will sleep
+ }
+
+ BaseQueuedResend(int packetNumber) {
+ this.packetNumber = packetNumber;
+ packetNumberAsInteger = new Integer(packetNumber);
+ long now = System.currentTimeMillis();
+ activeTime = initialActiveTime(now);
+ urgentTime = activeTime + urgentDelay();
+ }
+
+ abstract long urgentDelay();
+
+ abstract long initialActiveTime(long now);
+ private Item next;
+ private Item prev;
+
+ public final Item getNext() {
+ return next;
+ }
+
+ public final Item setNext(Item i) {
+ Item old = next;
+ next = i;
+ return old;
+ }
+
+ public Item getPrev() {
+ return prev;
+ }
+
+ public Item setPrev(Item i) {
+ Item old = prev;
+ prev = i;
+ return old;
+ }
+
+ public int compareTo(Object o) {
+ BaseQueuedResend r = (BaseQueuedResend) o;
+ if(urgentTime > r.urgentTime)
+ return 1;
+ if(urgentTime < r.urgentTime)
+ return -1;
+ if(packetNumber > r.packetNumber)
+ return 1;
+ if(packetNumber < r.packetNumber)
+ return -1;
+ return 0;
+ }
+
+ public Object indexValue() {
+ return packetNumberAsInteger;
+ }
+ private DoublyLinkedList parent;
+
public DoublyLinkedList getParent() {
return parent;
}
@@ -294,722 +291,756 @@
parent = l;
return old;
}
- }
-
- private class QueuedResendRequest extends BaseQueuedResend {
- long initialActiveTime(long now) {
- return now; // Active immediately; reordering is rare
- }
-
- QueuedResendRequest(int packetNumber) {
- super(packetNumber);
- }
-
- void sent() throws UpdatableSortedLinkedListKilledException {
- synchronized(resendRequestQueue) {
- super.sent();
- resendRequestQueue.update(this);
- }
- }
+ }
+ private class QueuedResendRequest extends BaseQueuedResend {
+
+ long initialActiveTime(long now) {
+ return now; // Active immediately; reordering is rare
+ }
+
+ QueuedResendRequest(int packetNumber) {
+ super(packetNumber);
+ }
+
+ @Override
+ void sent() throws UpdatableSortedLinkedListKilledException {
+ synchronized(resendRequestQueue) {
+ super.sent();
+ resendRequestQueue.update(this);
+ }
+ }
+
long urgentDelay() {
return PacketSender.MAX_COALESCING_DELAY; // Urgent
pretty soon
}
- }
-
- private class QueuedAckRequest extends BaseQueuedResend {
-
- final long createdTime;
- long activeDelay;
-
- long initialActiveTime(long now) {
- // Request an ack after four RTTs
- activeDelay = twoRTTs();
- return now + activeDelay;
- }
-
- QueuedAckRequest(int packetNumber, boolean sendSoon) {
- super(packetNumber);
- this.createdTime = System.currentTimeMillis();
- if(sendSoon) {
- activeTime -= activeDelay;
- urgentTime -= activeDelay;
- }
- }
-
- void sent() throws UpdatableSortedLinkedListKilledException {
- synchronized(ackRequestQueue) {
- super.sent();
- ackRequestQueue.update(this);
- }
- }
+ }
- /**
- * Acknowledged.
- */
+ private class QueuedAckRequest extends BaseQueuedResend {
+
+ final long createdTime;
+ long activeDelay;
+
+ long initialActiveTime(long now) {
+ // Request an ack after four RTTs
+ activeDelay = twoRTTs();
+ return now + activeDelay;
+ }
+
+ QueuedAckRequest(int packetNumber, boolean sendSoon) {
+ super(packetNumber);
+ this.createdTime = System.currentTimeMillis();
+ if(sendSoon) {
+ activeTime -= activeDelay;
+ urgentTime -= activeDelay;
+ }
+ }
+
+ @Override
+ void sent() throws UpdatableSortedLinkedListKilledException {
+ synchronized(ackRequestQueue) {
+ super.sent();
+ ackRequestQueue.update(this);
+ }
+ }
+
+ /**
+ * Acknowledged.
+ */
public void onAcked() {
long t = Math.max(0, System.currentTimeMillis() -
createdTime);
pn.reportPing(t);
- if(logMINOR) Logger.minor(this, "Reported round-trip
time of "+TimeUtil.formatTime(t, 2, true)+" on "+pn.getPeer()+" (avg
"+TimeUtil.formatTime((long)pn.averagePingTime(),2,true)+", #"+packetNumber+
')');
+ if(logMINOR)
+ Logger.minor(this, "Reported round-trip time of
" + TimeUtil.formatTime(t, 2, true) + " on " + pn.getPeer() + " (avg " +
TimeUtil.formatTime((long) pn.averagePingTime(), 2, true) + ", #" +
packetNumber + ')');
}
long urgentDelay() {
return PacketSender.MAX_COALESCING_DELAY;
}
- }
-
- /**
- * Called when we receive a packet.
- * @param seqNumber The packet's serial number.
- * See the comments in FNPPacketMangler.processOutgoing* for
- * the reason for the locking.
- */
- public synchronized void receivedPacket(int seqNumber) {
- timeLastDecodedPacket = System.currentTimeMillis();
- logMINOR = Logger.shouldLog(Logger.MINOR, this);
- if(logMINOR) Logger.minor(this, "Received packet "+seqNumber+" from
"+pn.shortToString());
- if(seqNumber == -1) return;
- // FIXME delete this log statement
- if(logMINOR) Logger.minor(this, "Still received packet: "+seqNumber);
- // Received packet
- receivedPacketNumber(seqNumber);
- // Ack it even if it is a resend
- queueAck(seqNumber);
- }
+ }
- // TCP uses four RTTs with no ack to resend ... but we have a more drawn
out protocol, we
- // should use only two.
- public long twoRTTs() {
- // FIXME upper bound necessary ?
- return (long) Math.min(Math.max(250, pn.averagePingTime()*2), 2500);
- }
-
- protected void receivedPacketNumber(int seqNumber) {
- if(logMINOR) Logger.minor(this, "Handling received packet number
"+seqNumber);
- queueResendRequests(seqNumber);
- packetNumbersReceived.got(seqNumber);
- try {
+ /**
+ * Called when we receive a packet.
+ * @param seqNumber The packet's serial number.
+ * See the comments in FNPPacketMangler.processOutgoing* for
+ * the reason for the locking.
+ */
+ public synchronized void receivedPacket(int seqNumber) {
+ timeLastDecodedPacket = System.currentTimeMillis();
+ logMINOR = Logger.shouldLog(Logger.MINOR, this);
+ if(logMINOR)
+ Logger.minor(this, "Received packet " + seqNumber + "
from " + pn.shortToString());
+ if(seqNumber == -1)
+ return;
+ // FIXME delete this log statement
+ if(logMINOR)
+ Logger.minor(this, "Still received packet: " +
seqNumber);
+ // Received packet
+ receivedPacketNumber(seqNumber);
+ // Ack it even if it is a resend
+ queueAck(seqNumber);
+ }
+
+ // TCP uses four RTTs with no ack to resend ... but we have a more
drawn out protocol, we
+ // should use only two.
+ public long twoRTTs() {
+ // FIXME upper bound necessary ?
+ return (long) Math.min(Math.max(250, pn.averagePingTime() * 2),
2500);
+ }
+
+ protected void receivedPacketNumber(int seqNumber) {
+ if(logMINOR)
+ Logger.minor(this, "Handling received packet number " +
seqNumber);
+ queueResendRequests(seqNumber);
+ packetNumbersReceived.got(seqNumber);
+ try {
removeResendRequest(seqNumber);
- } catch (UpdatableSortedLinkedListKilledException e) {
+ } catch(UpdatableSortedLinkedListKilledException e) {
// Ignore, not our problem
}
- synchronized(this) {
- highestSeenIncomingSerialNumber =
Math.max(highestSeenIncomingSerialNumber, seqNumber);
- }
- if(logMINOR) Logger.minor(this, "Handled received packet number
"+seqNumber);
- }
-
- /**
- * Remove a resend request from the queue.
- * @param seqNumber
- * @throws UpdatableSortedLinkedListKilledException
- */
- private void removeResendRequest(int seqNumber) throws
UpdatableSortedLinkedListKilledException {
- resendRequestQueue.removeByKey(new Integer(seqNumber));
- }
+ synchronized(this) {
+ highestSeenIncomingSerialNumber =
Math.max(highestSeenIncomingSerialNumber, seqNumber);
+ }
+ if(logMINOR)
+ Logger.minor(this, "Handled received packet number " +
seqNumber);
+ }
- /**
- * Add some resend requests if necessary.
- * @param seqNumber The number of the packet we just received.
- */
- private void queueResendRequests(int seqNumber) {
- int max;
- synchronized(this) {
- max = packetNumbersReceived.highest();
- }
- if(seqNumber > max) {
- try {
- if((max != -1) && (seqNumber - max > 1)) {
- if(logMINOR) Logger.minor(this, "Queueing resends from "+max+"
to "+seqNumber);
- // Missed some packets out
- for(int i=max+1;i<seqNumber;i++) {
- queueResendRequest(i);
- }
- }
- } catch (UpdatableSortedLinkedListKilledException e) {
- // Ignore (we are decoding packet, not sending one)
- }
- }
- }
+ /**
+ * Remove a resend request from the queue.
+ * @param seqNumber
+ * @throws UpdatableSortedLinkedListKilledException
+ */
+ private void removeResendRequest(int seqNumber) throws
UpdatableSortedLinkedListKilledException {
+ resendRequestQueue.removeByKey(seqNumber);
+ }
- /**
- * Queue a resend request
- * @param packetNumber the packet serial number to queue a
- * resend request for
- * @throws UpdatableSortedLinkedListKilledException
- */
- private void queueResendRequest(int packetNumber) throws
UpdatableSortedLinkedListKilledException {
- synchronized(resendRequestQueue) {
- if(queuedResendRequest(packetNumber)) {
- if(logMINOR) Logger.minor(this, "Not queueing resend
request for "+packetNumber+" - already queued");
- return;
- }
- if(logMINOR) Logger.minor(this, "Queueing resend request for
"+packetNumber);
- QueuedResendRequest qrr = new QueuedResendRequest(packetNumber);
- resendRequestQueue.add(qrr);
- }
- }
+ /**
+ * Add some resend requests if necessary.
+ * @param seqNumber The number of the packet we just received.
+ */
+ private void queueResendRequests(int seqNumber) {
+ int max;
+ synchronized(this) {
+ max = packetNumbersReceived.highest();
+ }
+ if(seqNumber > max)
+ try {
+ if((max != -1) && (seqNumber - max > 1)) {
+ if(logMINOR)
+ Logger.minor(this, "Queueing
resends from " + max + " to " + seqNumber);
+ // Missed some packets out
+ for(int i = max + 1; i < seqNumber;
i++) {
+ queueResendRequest(i);
+ }
+ }
+ } catch(UpdatableSortedLinkedListKilledException e) {
+ // Ignore (we are decoding packet, not sending
one)
+ }
+ }
- /**
- * Queue an ack request
- * @param packetNumber the packet serial number to queue a
- * resend request for
- * @throws UpdatableSortedLinkedListKilledException
- */
- private void queueAckRequest(int packetNumber) throws
UpdatableSortedLinkedListKilledException {
- synchronized(ackRequestQueue) {
- // FIXME should we just remove the existing ack request? If we
do, we get a better
- // estimate of RTT on lossy links... if we don't, lossy links
will include the average
- // time to send a packet including all resends. The latter may
be useful, and in fact
- // the former is unreliable...
- if(queuedAckRequest(packetNumber)) {
- if(logMINOR) Logger.minor(this, "Not queueing ack request for
"+packetNumber+" - already queued");
- return;
- }
- if(logMINOR) Logger.minor(this, "Queueing ack request for
"+packetNumber+" on "+this);
- QueuedAckRequest qrr = new QueuedAckRequest(packetNumber, false);
- ackRequestQueue.add(qrr);
- }
- }
+ /**
+ * Queue a resend request
+ * @param packetNumber the packet serial number to queue a
+ * resend request for
+ * @throws UpdatableSortedLinkedListKilledException
+ */
+ private void queueResendRequest(int packetNumber) throws
UpdatableSortedLinkedListKilledException {
+ synchronized(resendRequestQueue) {
+ if(queuedResendRequest(packetNumber)) {
+ if(logMINOR)
+ Logger.minor(this, "Not queueing resend
request for " + packetNumber + " - already queued");
+ return;
+ }
+ if(logMINOR)
+ Logger.minor(this, "Queueing resend request for
" + packetNumber);
+ QueuedResendRequest qrr = new
QueuedResendRequest(packetNumber);
+ resendRequestQueue.add(qrr);
+ }
+ }
- /**
- * Is an ack request queued for this packet number?
- */
- private boolean queuedAckRequest(int packetNumber) {
- return ackRequestQueue.containsKey(new Integer(packetNumber));
- }
+ /**
+ * Queue an ack request
+ * @param packetNumber the packet serial number to queue a
+ * resend request for
+ * @throws UpdatableSortedLinkedListKilledException
+ */
+ private void queueAckRequest(int packetNumber) throws
UpdatableSortedLinkedListKilledException {
+ synchronized(ackRequestQueue) {
+ // FIXME should we just remove the existing ack
request? If we do, we get a better
+ // estimate of RTT on lossy links... if we don't, lossy
links will include the average
+ // time to send a packet including all resends. The
latter may be useful, and in fact
+ // the former is unreliable...
+ if(queuedAckRequest(packetNumber)) {
+ if(logMINOR)
+ Logger.minor(this, "Not queueing ack
request for " + packetNumber + " - already queued");
+ return;
+ }
+ if(logMINOR)
+ Logger.minor(this, "Queueing ack request for "
+ packetNumber + " on " + this);
+ QueuedAckRequest qrr = new
QueuedAckRequest(packetNumber, false);
+ ackRequestQueue.add(qrr);
+ }
+ }
- /**
- * Is a resend request queued for this packet number?
- */
- private boolean queuedResendRequest(int packetNumber) {
- return resendRequestQueue.containsKey(new Integer(packetNumber));
- }
+ /**
+ * Is an ack request queued for this packet number?
+ */
+ private boolean queuedAckRequest(int packetNumber) {
+ return ackRequestQueue.containsKey(new Integer(packetNumber));
+ }
- /**
- * Called when we have received several packet acknowledgements.
- * Synchronized for the same reason as the sender code is:
- * So that we don't end up sending packets too late when overloaded,
- * and get horrible problems such as asking to resend packets which
- * haven't been sent yet.
- */
- public synchronized void acknowledgedPackets(int[] seqNos) {
- AsyncMessageCallback[][] callbacks = new
AsyncMessageCallback[seqNos.length][];
- for(int i=0;i<seqNos.length;i++) {
- int realSeqNo = seqNos[i];
- if(logMINOR) Logger.minor(this, "Acknowledged packet:
"+realSeqNo);
+ /**
+ * Is a resend request queued for this packet number?
+ */
+ private boolean queuedResendRequest(int packetNumber) {
+ return resendRequestQueue.containsKey(new
Integer(packetNumber));
+ }
+
+ /**
+ * Called when we have received several packet acknowledgements.
+ * Synchronized for the same reason as the sender code is:
+ * So that we don't end up sending packets too late when overloaded,
+ * and get horrible problems such as asking to resend packets which
+ * haven't been sent yet.
+ */
+ public synchronized void acknowledgedPackets(int[] seqNos) {
+ AsyncMessageCallback[][] callbacks = new
AsyncMessageCallback[seqNos.length][];
+ for(int i = 0; i < seqNos.length; i++) {
+ int realSeqNo = seqNos[i];
+ if(logMINOR)
+ Logger.minor(this, "Acknowledged packet: " +
realSeqNo);
+ try {
+ removeAckRequest(realSeqNo);
+ } catch(UpdatableSortedLinkedListKilledException e) {
+ // Ignore, we are processing an incoming packet
+ }
+ if(logMINOR)
+ Logger.minor(this, "Removed ack request");
+ callbacks[i] =
sentPacketsContents.getCallbacks(realSeqNo);
+ byte[] buf = sentPacketsContents.get(realSeqNo);
+ long timeAdded = sentPacketsContents.getTime(realSeqNo);
+ if(sentPacketsContents.remove(realSeqNo))
+ if(buf.length > Node.PACKET_SIZE) {
+ PacketThrottle throttle =
pn.getThrottle();
+ throttle.notifyOfPacketAcknowledged();
+
throttle.setRoundTripTime(System.currentTimeMillis() - timeAdded);
+ }
+ }
+ int cbCount = 0;
+ for(int i = 0; i < callbacks.length; i++) {
+ AsyncMessageCallback[] cbs = callbacks[i];
+ if(cbs != null)
+ for(int j = 0; j < cbs.length; j++) {
+ cbs[j].acknowledged();
+ cbCount++;
+ }
+ }
+ if(cbCount > 0 && logMINOR)
+ Logger.minor(this, "Executed " + cbCount + "
callbacks");
+ }
+
+ /**
+ * Called when we have received a packet acknowledgement.
+ * @param realSeqNo
+ */
+ public void acknowledgedPacket(int realSeqNo) {
+ logMINOR = Logger.shouldLog(Logger.MINOR, this);
+ AsyncMessageCallback[] callbacks;
+ if(logMINOR)
+ Logger.minor(this, "Acknowledged packet: " + realSeqNo);
try {
- removeAckRequest(realSeqNo);
- } catch (UpdatableSortedLinkedListKilledException e) {
+ synchronized(this) {
+ removeAckRequest(realSeqNo);
+ }
+ } catch(UpdatableSortedLinkedListKilledException e) {
// Ignore, we are processing an incoming packet
}
- if(logMINOR) Logger.minor(this, "Removed ack request");
- callbacks[i] = sentPacketsContents.getCallbacks(realSeqNo);
+ if(logMINOR)
+ Logger.minor(this, "Removed ack request");
+ callbacks = sentPacketsContents.getCallbacks(realSeqNo);
byte[] buf = sentPacketsContents.get(realSeqNo);
long timeAdded = sentPacketsContents.getTime(realSeqNo);
- if(sentPacketsContents.remove(realSeqNo)) {
+ if(sentPacketsContents.remove(realSeqNo))
if(buf.length > Node.PACKET_SIZE) {
PacketThrottle throttle = pn.getThrottle();
throttle.notifyOfPacketAcknowledged();
throttle.setRoundTripTime(System.currentTimeMillis() - timeAdded);
}
+ if(callbacks != null) {
+ for(int i = 0; i < callbacks.length; i++)
+ callbacks[i].acknowledged();
+ if(logMINOR)
+ Logger.minor(this, "Executed " +
callbacks.length + " callbacks");
}
}
- int cbCount = 0;
- for(int i=0;i<callbacks.length;i++) {
- AsyncMessageCallback[] cbs = callbacks[i];
- if(cbs != null) {
- for(int j=0;j<cbs.length;j++) {
- cbs[j].acknowledged();
- cbCount++;
- }
- }
- }
- if(cbCount > 0 && logMINOR)
- Logger.minor(this, "Executed "+cbCount+" callbacks");
- }
-
+
/**
- * Called when we have received a packet acknowledgement.
- * @param realSeqNo
- */
- public void acknowledgedPacket(int realSeqNo) {
- logMINOR = Logger.shouldLog(Logger.MINOR, this);
- AsyncMessageCallback[] callbacks;
- if(logMINOR) Logger.minor(this, "Acknowledged packet: "+realSeqNo);
- try {
- synchronized (this){
- removeAckRequest(realSeqNo);
+ * Remove an ack request from the queue by packet number.
+ * @throws UpdatableSortedLinkedListKilledException
+ */
+ private void removeAckRequest(int seqNo) throws
UpdatableSortedLinkedListKilledException {
+ QueuedAckRequest qr = (QueuedAckRequest)
ackRequestQueue.removeByKey(seqNo);
+ if(qr != null)
+ qr.onAcked();
+ else
+ Logger.normal(this, "Removing ack request twice? Null
on " + seqNo + " from " + pn.getPeer() + " (" + TimeUtil.formatTime((int)
pn.averagePingTime(), 2, true) + " ping avg)");
+ }
+
+ /**
+ * Resend (off-thread but ASAP) a packet.
+ * @param seqNumber The serial number of the packet to be
+ * resent.
+ */
+ public void resendPacket(int seqNumber) {
+ byte[] resendData = sentPacketsContents.get(seqNumber);
+ if(resendData != null) {
+ if(resendData.length > Node.PACKET_SIZE)
+ pn.getThrottle().notifyOfPacketLost();
+ synchronized(packetsToResend) {
+ packetsToResend.add(seqNumber);
+ }
+ pn.node.ps.wakeUp();
+ } else {
+ String msg = "Asking me to resend packet " + seqNumber +
+ " which we haven't sent yet or which they have
already acked (next=" + nextPacketNumber + ')';
+ // Might just be late, but could indicate something
serious.
+ if(isDeprecated) {
+ if(logMINOR)
+ Logger.minor(this, "Other side wants us
to resend packet " + seqNumber + " for " + this + " - we cannot do this because
we are deprecated");
+ } else
+ Logger.normal(this, msg);
}
- } catch (UpdatableSortedLinkedListKilledException e) {
- // Ignore, we are processing an incoming packet
}
- if(logMINOR) Logger.minor(this, "Removed ack request");
- callbacks = sentPacketsContents.getCallbacks(realSeqNo);
- byte[] buf = sentPacketsContents.get(realSeqNo);
- long timeAdded = sentPacketsContents.getTime(realSeqNo);
- if(sentPacketsContents.remove(realSeqNo)) {
- if(buf.length > Node.PACKET_SIZE) {
- PacketThrottle throttle = pn.getThrottle();
- throttle.notifyOfPacketAcknowledged();
- throttle.setRoundTripTime(System.currentTimeMillis() -
timeAdded);
- }
- }
- if(callbacks != null) {
- for(int i=0;i<callbacks.length;i++)
- callbacks[i].acknowledged();
- if(logMINOR) Logger.minor(this, "Executed "+callbacks.length+"
callbacks");
- }
- }
- /**
- * Remove an ack request from the queue by packet number.
- * @throws UpdatableSortedLinkedListKilledException
- */
- private void removeAckRequest(int seqNo) throws
UpdatableSortedLinkedListKilledException {
- QueuedAckRequest qr =
(QueuedAckRequest)ackRequestQueue.removeByKey(seqNo);
- if(qr != null) qr.onAcked();
- else
- Logger.normal(this, "Removing ack request twice? Null on
"+seqNo+" from "+pn.getPeer()+" ("+TimeUtil.formatTime((int)
pn.averagePingTime(), 2, true)+" ping avg)");
- }
-
- /**
- * Resend (off-thread but ASAP) a packet.
- * @param seqNumber The serial number of the packet to be
- * resent.
- */
- public void resendPacket(int seqNumber) {
- byte[] resendData = sentPacketsContents.get(seqNumber);
- if(resendData != null) {
- if(resendData.length > Node.PACKET_SIZE)
- pn.getThrottle().notifyOfPacketLost();
- synchronized(packetsToResend) {
- packetsToResend.add(seqNumber);
- }
- pn.node.ps.wakeUp();
- } else {
- synchronized(this) {
- String msg = "Asking me to resend packet "+seqNumber+
- " which we haven't sent yet or which they have
already acked (next="+nextPacketNumber+ ')';
- // Might just be late, but could indicate something
serious.
- if(isDeprecated) {
- if(logMINOR)
- Logger.minor(this, "Other side wants us
to resend packet "+seqNumber+" for "+this+" - we cannot do this because we are
deprecated");
- } else {
- Logger.normal(this, msg);
- }
- }
- }
- }
-
- /**
- * Called when we receive an AckRequest.
- * @param packetNumber The packet that the other side wants
- * us to re-ack.
- */
- public synchronized void receivedAckRequest(int packetNumber) {
- if(queuedAck(packetNumber)) {
- // Already going to send an ack
- // Don't speed it up though; wasteful
- } else {
- if(packetNumbersReceived.contains(packetNumber)) {
- // We have received it, so send them an ack
- queueAck(packetNumber);
- } else {
- // We have not received it, so get them to resend it
- try {
+ /**
+ * Called when we receive an AckRequest.
+ * @param packetNumber The packet that the other side wants
+ * us to re-ack.
+ */
+ public synchronized void receivedAckRequest(int packetNumber) {
+ if(queuedAck(packetNumber)) {
+ // Already going to send an ack
+ // Don't speed it up though; wasteful
+ } else
+ if(packetNumbersReceived.contains(packetNumber))
+ // We have received it, so send them an ack
+ queueAck(packetNumber);
+ else {
+ // We have not received it, so get them to
resend it
+ try {
queueResendRequest(packetNumber);
- } catch
(UpdatableSortedLinkedListKilledException e) {
+ }
catch(UpdatableSortedLinkedListKilledException e) {
// Ignore, we are decoding, not sending.
}
- highestSeenIncomingSerialNumber =
Math.max(highestSeenIncomingSerialNumber, packetNumber);
- }
- }
- }
+ highestSeenIncomingSerialNumber =
Math.max(highestSeenIncomingSerialNumber, packetNumber);
+ }
+ }
- /**
- * Is there a queued ack with the given packet number?
- * FIXME: have a hashtable? The others do, but probably it
- * isn't necessary. We should be consistent about this -
- * either take it out of UpdatableSortedLinkedListWithForeignIndex,
- * or add one here.
- */
- private boolean queuedAck(int packetNumber) {
- synchronized(ackQueue) {
- Iterator it = ackQueue.iterator();
- while (it.hasNext()) {
- QueuedAck qa = (QueuedAck) it.next();
- if(qa.packetNumber == packetNumber) return true;
- }
- }
- return false;
- }
+ /**
+ * Is there a queued ack with the given packet number?
+ * FIXME: have a hashtable? The others do, but probably it
+ * isn't necessary. We should be consistent about this -
+ * either take it out of UpdatableSortedLinkedListWithForeignIndex,
+ * or add one here.
+ */
+ private boolean queuedAck(int packetNumber) {
+ synchronized(ackQueue) {
+ Iterator it = ackQueue.iterator();
+ while(it.hasNext()) {
+ QueuedAck qa = (QueuedAck) it.next();
+ if(qa.packetNumber == packetNumber)
+ return true;
+ }
+ }
+ return false;
+ }
- /**
- * Destination forgot a packet.
- * This is normal if we are the secondary key.
- * @param seqNumber The packet number lost.
- */
- public synchronized void destForgotPacket(int seqNumber) {
- if(isDeprecated) {
- Logger.normal(this, "Destination forgot packet: "+seqNumber);
- } else {
- Logger.error(this, "Destination forgot packet: "+seqNumber);
- }
- try {
- removeResendRequest(seqNumber);
- } catch (UpdatableSortedLinkedListKilledException e) {
- // Ignore
+ /**
+ * Destination forgot a packet.
+ * This is normal if we are the secondary key.
+ * @param seqNumber The packet number lost.
+ */
+ public void destForgotPacket(int seqNumber) {
+ if(isDeprecated)
+ Logger.normal(this, "Destination forgot packet: " +
seqNumber);
+ else
+ Logger.error(this, "Destination forgot packet: " +
seqNumber);
+ synchronized(this) {
+ try {
+ removeResendRequest(seqNumber);
+ } catch(UpdatableSortedLinkedListKilledException e) {
+ // Ignore
+ }
}
- }
+ }
- /**
- * @return A packet number for a new outgoing packet.
- * This method will block until one is available if
- * necessary.
- * @throws KeyChangedException if the thread is interrupted when waiting
- */
- public int allocateOutgoingPacketNumber() throws KeyChangedException,
NotConnectedException {
- int packetNumber;
- if(!pn.isConnected()) throw new NotConnectedException();
- synchronized(this) {
- if(isDeprecated) throw new KeyChangedException();
- packetNumber = nextPacketNumber++;
- if(logMINOR) Logger.minor(this, "Allocated "+packetNumber+" in
allocateOutgoingPacketNumber for "+this);
- }
- while(true) {
- try {
- sentPacketsContents.lock(packetNumber);
- return packetNumber;
- } catch (InterruptedException e) {
- synchronized(this) {
- if(isDeprecated) throw new KeyChangedException();
- }
- }
- }
- }
+ /**
+ * @return A packet number for a new outgoing packet.
+ * This method will block until one is available if
+ * necessary.
+ * @throws KeyChangedException if the thread is interrupted when waiting
+ */
+ public int allocateOutgoingPacketNumber() throws KeyChangedException,
NotConnectedException {
+ int packetNumber;
+ if(!pn.isConnected())
+ throw new NotConnectedException();
+ synchronized(this) {
+ if(isDeprecated)
+ throw new KeyChangedException();
+ packetNumber = nextPacketNumber++;
+ if(logMINOR)
+ Logger.minor(this, "Allocated " + packetNumber
+ " in allocateOutgoingPacketNumber for " + this);
+ }
+ while(true) {
+ try {
+ sentPacketsContents.lock(packetNumber);
+ return packetNumber;
+ } catch(InterruptedException e) {
+ synchronized(this) {
+ if(isDeprecated)
+ throw new KeyChangedException();
+ }
+ }
+ }
+ }
- /**
- * @return A packet number for a new outgoing packet.
- * This method will not block, and will throw an exception
- * if it would need to block.
- * @throws KeyChangedException if the thread is interrupted when waiting
- */
- public int allocateOutgoingPacketNumberNeverBlock() throws
KeyChangedException, NotConnectedException, WouldBlockException {
- int packetNumber;
- if(!pn.isConnected()) throw new NotConnectedException();
- synchronized(this) {
- packetNumber = nextPacketNumber;
- if(isDeprecated) throw new KeyChangedException();
- sentPacketsContents.lockNeverBlock(packetNumber);
- nextPacketNumber = packetNumber+1;
- if(logMINOR) Logger.minor(this, "Allocated "+packetNumber+" in
allocateOutgoingPacketNumberNeverBlock for "+this);
- return packetNumber;
- }
- }
+ /**
+ * @return A packet number for a new outgoing packet.
+ * This method will not block, and will throw an exception
+ * if it would need to block.
+ * @throws KeyChangedException if the thread is interrupted when waiting
+ */
+ public int allocateOutgoingPacketNumberNeverBlock() throws
KeyChangedException, NotConnectedException, WouldBlockException {
+ int packetNumber;
+ if(!pn.isConnected())
+ throw new NotConnectedException();
+ synchronized(this) {
+ packetNumber = nextPacketNumber;
+ if(isDeprecated)
+ throw new KeyChangedException();
+ sentPacketsContents.lockNeverBlock(packetNumber);
+ nextPacketNumber = packetNumber + 1;
+ if(logMINOR)
+ Logger.minor(this, "Allocated " + packetNumber
+ " in allocateOutgoingPacketNumberNeverBlock for " + this);
+ return packetNumber;
+ }
+ }
- public int[] grabForgotten() {
- if(logMINOR) Logger.minor(this, "Grabbing forgotten packet numbers");
- int[] acks;
- synchronized(forgottenQueue) {
- // Grab the acks and tell them they are sent
- int length = forgottenQueue.size();
- acks = new int[length];
- int i=0;
-
- Iterator it = forgottenQueue.iterator();
- while (it.hasNext()) {
- QueuedForgotten ack = (QueuedForgotten) it.next();
- acks[i++] = ack.packetNumber;
- if(logMINOR) Logger.minor(this, "Grabbing ack
"+ack.packetNumber+" from "+this);
- it.remove(); // sent
- }
- }
- return acks;
- }
+ public int[] grabForgotten() {
+ if(logMINOR)
+ Logger.minor(this, "Grabbing forgotten packet numbers");
+ int[] acks;
+ synchronized(forgottenQueue) {
+ // Grab the acks and tell them they are sent
+ int length = forgottenQueue.size();
+ acks = new int[length];
+ int i = 0;
+ Iterator it = forgottenQueue.iterator();
+ while(it.hasNext()) {
+ QueuedForgotten ack = (QueuedForgotten)
it.next();
+ acks[i++] = ack.packetNumber;
+ if(logMINOR)
+ Logger.minor(this, "Grabbing ack " +
ack.packetNumber + " from " + this);
+ it.remove(); // sent
+ }
+ }
+ return acks;
+ }
+
public void requeueForgot(int[] forgotPackets, int start, int length) {
synchronized(forgottenQueue) { // It doesn't do anything else
does it? REDFLAG
- for(int i=start;i<start+length;i++) {
+ for(int i = start; i < start + length; i++) {
queueForgotten(i, false);
}
}
}
-
- /**
- * Grab all the currently queued acks to be sent to this node.
- * @return An array of packet numbers that we need to acknowledge.
- */
- public int[] grabAcks() {
- if(logMINOR) Logger.minor(this, "Grabbing acks");
- int[] acks;
- synchronized(ackQueue) {
- // Grab the acks and tell them they are sent
- int length = ackQueue.size();
- acks = new int[length];
- int i=0;
- Iterator it = ackQueue.iterator();
- while (it.hasNext()) {
- QueuedAck ack = (QueuedAck) it.next();
- acks[i++] = ack.packetNumber;
- if(logMINOR) Logger.minor(this, "Grabbing ack
"+ack.packetNumber+" from "+this);
- it.remove(); // sent
- }
- }
- return acks;
- }
+ /**
+ * Grab all the currently queued acks to be sent to this node.
+ * @return An array of packet numbers that we need to acknowledge.
+ */
+ public int[] grabAcks() {
+ if(logMINOR)
+ Logger.minor(this, "Grabbing acks");
+ int[] acks;
+ synchronized(ackQueue) {
+ // Grab the acks and tell them they are sent
+ int length = ackQueue.size();
+ acks = new int[length];
+ int i = 0;
+ Iterator it = ackQueue.iterator();
+ while(it.hasNext()) {
+ QueuedAck ack = (QueuedAck) it.next();
+ acks[i++] = ack.packetNumber;
+ if(logMINOR)
+ Logger.minor(this, "Grabbing ack " +
ack.packetNumber + " from " + this);
+ it.remove(); // sent
+ }
+ }
+ return acks;
+ }
- /**
- * Grab all the currently queued resend requests.
- * @return An array of the packet numbers of all the packets we want to be
resent.
- * @throws NotConnectedException If the peer is no longer connected.
- */
- public int[] grabResendRequests() throws NotConnectedException {
- UpdatableSortedLinkedListItem[] items;
- int[] packetNumbers;
- int realLength;
- long now = System.currentTimeMillis();
- try {
- synchronized(resendRequestQueue) {
- items = resendRequestQueue.toArray();
- int length = items.length;
- packetNumbers = new int[length];
- realLength = 0;
- for(int i=0;i<length;i++) {
- QueuedResendRequest qrr = (QueuedResendRequest)items[i];
- if(packetNumbersReceived.contains(qrr.packetNumber)) {
- if(logMINOR) Logger.minor(this, "Have already seen
"+qrr.packetNumber+", removing from resend list");
- resendRequestQueue.remove(qrr);
- continue;
- }
- if(qrr.activeTime <= now) {
- packetNumbers[realLength++] = qrr.packetNumber;
- if(logMINOR) Logger.minor(this, "Grabbing resend request:
"+qrr.packetNumber+" from "+this);
- qrr.sent();
- } else {
- if(logMINOR) Logger.minor(this, "Rejecting resend
request: "+qrr.packetNumber+" - in future by "+(qrr.activeTime-now)+"ms for
"+this);
- }
- }
- }
- } catch (UpdatableSortedLinkedListKilledException e) {
- throw new NotConnectedException();
- }
- int[] trimmedPacketNumbers = new int[realLength];
- System.arraycopy(packetNumbers, 0, trimmedPacketNumbers, 0,
realLength);
- return trimmedPacketNumbers;
- }
+ /**
+ * Grab all the currently queued resend requests.
+ * @return An array of the packet numbers of all the packets we want to
be resent.
+ * @throws NotConnectedException If the peer is no longer connected.
+ */
+ public int[] grabResendRequests() throws NotConnectedException {
+ UpdatableSortedLinkedListItem[] items;
+ int[] packetNumbers;
+ int realLength;
+ long now = System.currentTimeMillis();
+ try {
+ synchronized(resendRequestQueue) {
+ items = resendRequestQueue.toArray();
+ int length = items.length;
+ packetNumbers = new int[length];
+ realLength = 0;
+ for(int i = 0; i < length; i++) {
+ QueuedResendRequest qrr =
(QueuedResendRequest) items[i];
+
if(packetNumbersReceived.contains(qrr.packetNumber)) {
+ if(logMINOR)
+ Logger.minor(this,
"Have already seen " + qrr.packetNumber + ", removing from resend list");
+ resendRequestQueue.remove(qrr);
+ continue;
+ }
+ if(qrr.activeTime <= now) {
+ packetNumbers[realLength++] =
qrr.packetNumber;
+ if(logMINOR)
+ Logger.minor(this,
"Grabbing resend request: " + qrr.packetNumber + " from " + this);
+ qrr.sent();
+ } else
+ if(logMINOR)
+ Logger.minor(this,
"Rejecting resend request: " + qrr.packetNumber + " - in future by " +
(qrr.activeTime - now) + "ms for " + this);
+ }
+ }
+ } catch(UpdatableSortedLinkedListKilledException e) {
+ throw new NotConnectedException();
+ }
+ int[] trimmedPacketNumbers = new int[realLength];
+ System.arraycopy(packetNumbers, 0, trimmedPacketNumbers, 0,
realLength);
+ return trimmedPacketNumbers;
+ }
- public int[] grabAckRequests() throws NotConnectedException {
- UpdatableSortedLinkedListItem[] items;
- int[] packetNumbers;
- int realLength;
- if(logMINOR) Logger.minor(this, "Grabbing ack requests");
- try {
- synchronized(ackRequestQueue) {
- long now = System.currentTimeMillis();
- items = ackRequestQueue.toArray();
- int length = items.length;
- packetNumbers = new int[length];
- realLength = 0;
- for(int i=0;i<length;i++) {
- QueuedAckRequest qr = (QueuedAckRequest)items[i];
- int packetNumber = qr.packetNumber;
- if(qr.activeTime <= now) {
- if(sentPacketsContents.get(packetNumber) == null) {
- if(logMINOR) Logger.minor(this, "Asking to ack packet
which has already been acked: "+packetNumber+" on "+this+".grabAckRequests");
- ackRequestQueue.remove(qr);
- continue;
- }
- if(now - qr.createdTime > 2*60*1000) {
- Logger.error(this, "Packet "+qr.packetNumber+" sent
over "+(now - qr.createdTime)+"ms ago and still not acked on "+this+" for "+pn);
- }
- packetNumbers[realLength++] = packetNumber;
- if(logMINOR) Logger.minor(this, "Grabbing ack request
"+packetNumber+" ("+realLength+") from "+this);
- qr.sent();
- } else {
- if(logMINOR) Logger.minor(this, "Ignoring ack request
"+packetNumber+" ("+realLength+") - will become active in
"+(qr.activeTime-now)+"ms on "+this+" - "+qr);
- }
- }
- }
- } catch (UpdatableSortedLinkedListKilledException e) {
- throw new NotConnectedException();
- }
- if(logMINOR) Logger.minor(this, "realLength now "+realLength);
- int[] trimmedPacketNumbers = new int[realLength];
- System.arraycopy(packetNumbers, 0, trimmedPacketNumbers, 0,
realLength);
- if(logMINOR) Logger.minor(this, "Returning
"+trimmedPacketNumbers.length+" ackRequests");
- return trimmedPacketNumbers;
- }
+ public int[] grabAckRequests() throws NotConnectedException {
+ UpdatableSortedLinkedListItem[] items;
+ int[] packetNumbers;
+ int realLength;
+ if(logMINOR)
+ Logger.minor(this, "Grabbing ack requests");
+ try {
+ synchronized(ackRequestQueue) {
+ long now = System.currentTimeMillis();
+ items = ackRequestQueue.toArray();
+ int length = items.length;
+ packetNumbers = new int[length];
+ realLength = 0;
+ for(int i = 0; i < length; i++) {
+ QueuedAckRequest qr =
(QueuedAckRequest) items[i];
+ int packetNumber = qr.packetNumber;
+ if(qr.activeTime <= now) {
+
if(sentPacketsContents.get(packetNumber) == null) {
+ if(logMINOR)
+
Logger.minor(this, "Asking to ack packet which has already been acked: " +
packetNumber + " on " + this + ".grabAckRequests");
+
ackRequestQueue.remove(qr);
+ continue;
+ }
+ if(now - qr.createdTime > 2 *
60 * 1000)
+ Logger.error(this,
"Packet " + qr.packetNumber + " sent over " + (now - qr.createdTime) + "ms ago
and still not acked on " + this + " for " + pn);
+ packetNumbers[realLength++] =
packetNumber;
+ if(logMINOR)
+ Logger.minor(this,
"Grabbing ack request " + packetNumber + " (" + realLength + ") from " + this);
+ qr.sent();
+ } else
+ if(logMINOR)
+ Logger.minor(this,
"Ignoring ack request " + packetNumber + " (" + realLength + ") - will become
active in " + (qr.activeTime - now) + "ms on " + this + " - " + qr);
+ }
+ }
+ } catch(UpdatableSortedLinkedListKilledException e) {
+ throw new NotConnectedException();
+ }
+ if(logMINOR)
+ Logger.minor(this, "realLength now " + realLength);
+ int[] trimmedPacketNumbers = new int[realLength];
+ System.arraycopy(packetNumbers, 0, trimmedPacketNumbers, 0,
realLength);
+ if(logMINOR)
+ Logger.minor(this, "Returning " +
trimmedPacketNumbers.length + " ackRequests");
+ return trimmedPacketNumbers;
+ }
- /**
- * @return The time at which we will have to send some
- * notifications. Or Long.MAX_VALUE if there are none to send.
- */
- public long getNextUrgentTime() {
- long earliestTime = Long.MAX_VALUE;
- synchronized(ackQueue) {
- if(!ackQueue.isEmpty()) {
- QueuedAck qa = (QueuedAck) ackQueue.get(0);
- earliestTime = qa.urgentTime;
- }
- }
- synchronized(resendRequestQueue) {
- if(!resendRequestQueue.isEmpty()) {
- QueuedResendRequest qr = (QueuedResendRequest)
resendRequestQueue.getLowest();
- earliestTime = Math.min(earliestTime, qr.urgentTime);
- }
- }
- synchronized(ackRequestQueue) {
- if(!ackRequestQueue.isEmpty()) {
- QueuedAckRequest qr = (QueuedAckRequest)
ackRequestQueue.getLowest();
- earliestTime = Math.min(earliestTime, qr.urgentTime);
- }
- }
- return earliestTime;
- }
+ /**
+ * @return The time at which we will have to send some
+ * notifications. Or Long.MAX_VALUE if there are none to send.
+ */
+ public long getNextUrgentTime() {
+ long earliestTime = Long.MAX_VALUE;
+ synchronized(ackQueue) {
+ if(!ackQueue.isEmpty()) {
+ QueuedAck qa = (QueuedAck) ackQueue.get(0);
+ earliestTime = qa.urgentTime;
+ }
+ }
+ synchronized(resendRequestQueue) {
+ if(!resendRequestQueue.isEmpty()) {
+ QueuedResendRequest qr = (QueuedResendRequest)
resendRequestQueue.getLowest();
+ earliestTime = Math.min(earliestTime,
qr.urgentTime);
+ }
+ }
+ synchronized(ackRequestQueue) {
+ if(!ackRequestQueue.isEmpty()) {
+ QueuedAckRequest qr = (QueuedAckRequest)
ackRequestQueue.getLowest();
+ earliestTime = Math.min(earliestTime,
qr.urgentTime);
+ }
+ }
+ return earliestTime;
+ }
- /**
- * @return The last sent new packet number.
- */
- public int getLastOutgoingSeqNumber() {
- synchronized(this) {
- return nextPacketNumber-1;
- }
- }
+ /**
+ * @return The last sent new packet number.
+ */
+ public int getLastOutgoingSeqNumber() {
+ synchronized(this) {
+ return nextPacketNumber - 1;
+ }
+ }
- /**
- * Report a packet has been sent
- * @param data The data we have just sent (payload only, decrypted).
- * @param seqNumber The packet number.
- * @throws NotConnectedException
- */
- public void sentPacket(byte[] data, int seqNumber, AsyncMessageCallback[]
callbacks, short priority) throws NotConnectedException {
- if(callbacks != null) {
- for(int i=0;i<callbacks.length;i++) {
- if(callbacks[i] == null)
- throw new NullPointerException();
- }
- }
- sentPacketsContents.add(seqNumber, data, callbacks, priority);
- try {
+ /**
+ * Report a packet has been sent
+ * @param data The data we have just sent (payload only, decrypted).
+ * @param seqNumber The packet number.
+ * @throws NotConnectedException
+ */
+ public void sentPacket(byte[] data, int seqNumber,
AsyncMessageCallback[] callbacks, short priority) throws NotConnectedException {
+ if(callbacks != null)
+ for(int i = 0; i < callbacks.length; i++) {
+ if(callbacks[i] == null)
+ throw new NullPointerException();
+ }
+ sentPacketsContents.add(seqNumber, data, callbacks, priority);
+ try {
queueAckRequest(seqNumber);
- } catch (UpdatableSortedLinkedListKilledException e) {
+ } catch(UpdatableSortedLinkedListKilledException e) {
throw new NotConnectedException();
}
- }
+ }
- /**
- * Clear the KeyTracker. Deprecate it, clear all resend, ack, request-ack
etc queues.
- * Return the messages we still had in flight. The caller will then either
add them to
- * another KeyTracker, or call their callbacks to indicate failure.
- */
- private LimitedRangeIntByteArrayMapElement[] clear() {
- if(logMINOR) Logger.minor(this, "Clearing "+this);
- isDeprecated = true;
- LimitedRangeIntByteArrayMapElement[] elements;
- synchronized(sentPacketsContents) {
- elements = sentPacketsContents.grabAll(); // will clear
- }
- synchronized(ackQueue) {
- ackQueue.clear();
- }
- resendRequestQueue.kill();
- ackRequestQueue.kill();
- synchronized(packetsToResend) {
- packetsToResend.clear();
- }
- packetNumbersReceived.clear();
- return elements;
- }
+ /**
+ * Clear the KeyTracker. Deprecate it, clear all resend, ack,
request-ack etc queues.
+ * Return the messages we still had in flight. The caller will then
either add them to
+ * another KeyTracker, or call their callbacks to indicate failure.
+ */
+ private LimitedRangeIntByteArrayMapElement[] clear() {
+ if(logMINOR)
+ Logger.minor(this, "Clearing " + this);
+ isDeprecated = true;
+ LimitedRangeIntByteArrayMapElement[] elements;
+ synchronized(sentPacketsContents) {
+ elements = sentPacketsContents.grabAll(); // will clear
+ }
+ synchronized(ackQueue) {
+ ackQueue.clear();
+ }
+ resendRequestQueue.kill();
+ ackRequestQueue.kill();
+ synchronized(packetsToResend) {
+ packetsToResend.clear();
+ }
+ packetNumbersReceived.clear();
+ return elements;
+ }
- /**
- * Completely deprecate the KeyTracker, in favour of a new one.
- * It will no longer be used for anything. The KeyTracker will be cleared
and all outstanding packets
- * moved to the new KeyTracker.
- *
- * *** Must only be called if the KeyTracker is not to be kept. Otherwise,
we may receive some packets twice. ***
- */
- public void completelyDeprecated(KeyTracker newTracker) {
- if(logMINOR) Logger.minor(this, "Completely deprecated: "+this+" in
favour of "+newTracker);
- LimitedRangeIntByteArrayMapElement[] elements = clear();
- if(elements.length == 0) return; // nothing more to do
- MessageItem[] messages = new MessageItem[elements.length];
- for(int i=0;i<elements.length;i++) {
- LimitedRangeIntByteArrayMapElement element = elements[i];
- byte[] buf = element.data;
- AsyncMessageCallback[] callbacks = element.callbacks;
- // Ignore packet#
- if(logMINOR) Logger.minor(this, "Queueing resend of what was once
"+element.packetNumber);
- messages[i] = new MessageItem(buf, callbacks, true, 0,
pn.resendByteCounter, element.priority);
- }
- pn.requeueMessageItems(messages, 0, messages.length, true);
-
- pn.node.ps.wakeUp();
- }
+ /**
+ * Completely deprecate the KeyTracker, in favour of a new one.
+ * It will no longer be used for anything. The KeyTracker will be
cleared and all outstanding packets
+ * moved to the new KeyTracker.
+ *
+ * *** Must only be called if the KeyTracker is not to be kept.
Otherwise, we may receive some packets twice. ***
+ */
+ public void completelyDeprecated(KeyTracker newTracker) {
+ if(logMINOR)
+ Logger.minor(this, "Completely deprecated: " + this + "
in favour of " + newTracker);
+ LimitedRangeIntByteArrayMapElement[] elements = clear();
+ if(elements.length == 0)
+ return; // nothing more to do
+ MessageItem[] messages = new MessageItem[elements.length];
+ for(int i = 0; i < elements.length; i++) {
+ LimitedRangeIntByteArrayMapElement element =
elements[i];
+ byte[] buf = element.data;
+ AsyncMessageCallback[] callbacks = element.callbacks;
+ // Ignore packet#
+ if(logMINOR)
+ Logger.minor(this, "Queueing resend of what was
once " + element.packetNumber);
+ messages[i] = new MessageItem(buf, callbacks, true, 0,
pn.resendByteCounter, element.priority);
+ }
+ pn.requeueMessageItems(messages, 0, messages.length, true);
- /**
- * Called when the node appears to have been disconnected.
- * Dump all sent messages.
- */
- public void disconnected() {
- // Clear everything, call the callbacks
- LimitedRangeIntByteArrayMapElement[] elements = clear();
- for(int i=0;i<elements.length;i++) {
- LimitedRangeIntByteArrayMapElement element = elements[i];
- AsyncMessageCallback[] callbacks = element.callbacks;
- if(callbacks != null) {
- for(int j=0;j<callbacks.length;j++)
- callbacks[j].disconnected();
- }
- }
- }
+ pn.node.ps.wakeUp();
+ }
- /**
- * Fill rpiTemp with ResendPacketItems of packets that need to be
- * resent.
- * @return An array of integers which contains the packet numbers
- * to be resent (the RPI's are put into rpiTemp), or null if there
- * are no packets to resend.
- *
- * Not a very nice API, but it saves a load of allocations, and at
- * least it's documented!
- */
- public int[] grabResendPackets(Vector rpiTemp, int[] numbers) {
- rpiTemp.clear();
- long now = System.currentTimeMillis();
- long fourRTTs = twoRTTs();
- int count=0;
- synchronized(packetsToResend) {
- int len = packetsToResend.size();
- if(numbers.length < len)
- numbers = new int[len * 2];
- for(Iterator it=packetsToResend.iterator();it.hasNext();) {
- int packetNo = ((Integer)it.next()).intValue();
- long resentTime = sentPacketsContents.getReaddedTime(packetNo);
- if(now - resentTime > fourRTTs) {
- // Either never resent, or resent at least 4 RTTs ago
- numbers[count++] = packetNo;
- it.remove();
- }
- }
- packetsToResend.clear();
- }
- for(int i=0;i<count;i++) {
- int packetNo = numbers[i];
- byte[] buf = sentPacketsContents.get(packetNo);
- if(buf == null) {
- if(logMINOR) Logger.minor(this, "Contents null for "+packetNo+"
in grabResendPackets on "+this);
- continue; // acked already?
- }
- AsyncMessageCallback[] callbacks =
sentPacketsContents.getCallbacks(packetNo);
- short priority = sentPacketsContents.getPriority(packetNo,
DMT.PRIORITY_BULK_DATA);
- rpiTemp.add(new ResendPacketItem(buf, packetNo, this, callbacks,
priority));
- }
- if(rpiTemp.isEmpty()) return null;
- return numbers;
- }
+ /**
+ * Called when the node appears to have been disconnected.
+ * Dump all sent messages.
+ */
+ public void disconnected() {
+ // Clear everything, call the callbacks
+ LimitedRangeIntByteArrayMapElement[] elements = clear();
+ for(int i = 0; i < elements.length; i++) {
+ LimitedRangeIntByteArrayMapElement element =
elements[i];
+ AsyncMessageCallback[] callbacks = element.callbacks;
+ if(callbacks != null)
+ for(int j = 0; j < callbacks.length; j++)
+ callbacks[j].disconnected();
+ }
+ }
+ /**
+ * Fill rpiTemp with ResendPacketItems of packets that need to be
+ * resent.
+ * @return An array of integers which contains the packet numbers
+ * to be resent (the RPI's are put into rpiTemp), or null if there
+ * are no packets to resend.
+ *
+ * Not a very nice API, but it saves a load of allocations, and at
+ * least it's documented!
+ */
+ public int[] grabResendPackets(Vector rpiTemp, int[] numbers) {
+ rpiTemp.clear();
+ long now = System.currentTimeMillis();
+ long fourRTTs = twoRTTs();
+ int count = 0;
+ synchronized(packetsToResend) {
+ int len = packetsToResend.size();
+ if(numbers.length < len)
+ numbers = new int[len * 2];
+ for(Iterator it = packetsToResend.iterator();
it.hasNext();) {
+ int packetNo = ((Integer) it.next()).intValue();
+ long resentTime =
sentPacketsContents.getReaddedTime(packetNo);
+ if(now - resentTime > fourRTTs) {
+ // Either never resent, or resent at
least 4 RTTs ago
+ numbers[count++] = packetNo;
+ it.remove();
+ }
+ }
+ packetsToResend.clear();
+ }
+ for(int i = 0; i < count; i++) {
+ int packetNo = numbers[i];
+ byte[] buf = sentPacketsContents.get(packetNo);
+ if(buf == null) {
+ if(logMINOR)
+ Logger.minor(this, "Contents null for "
+ packetNo + " in grabResendPackets on " + this);
+ continue; // acked already?
+ }
+ AsyncMessageCallback[] callbacks =
sentPacketsContents.getCallbacks(packetNo);
+ short priority =
sentPacketsContents.getPriority(packetNo, DMT.PRIORITY_BULK_DATA);
+ rpiTemp.add(new ResendPacketItem(buf, packetNo, this,
callbacks, priority));
+ }
+ if(rpiTemp.isEmpty())
+ return null;
+ return numbers;
+ }
+
public boolean isDeprecated() {
return this.isDeprecated;
}
@@ -1033,5 +1064,4 @@
public synchronized long timeLastDecodedPacket() {
return timeLastDecodedPacket;
}
-
}
Modified: branches/db4o/freenet/src/freenet/node/Node.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/Node.java 2008-09-24 20:42:20 UTC
(rev 22823)
+++ branches/db4o/freenet/src/freenet/node/Node.java 2008-09-24 22:16:49 UTC
(rev 22824)
@@ -1500,63 +1500,6 @@
final String suffix = "-" + getDarknetPortNumber();
String datastoreDir = nodeConfig.getString("storeDir");
- // FIXME: temporary cludge for backward compat.
- File tmpFile = new File("datastore");
- if(".".equals(datastoreDir) && !tmpFile.exists()) {
- System.out.println("Your node seems to be using the old
directory, we will move it: !!DO NOT RESTART!!");
- Logger.normal(this, "Your node seems to be using the
old directory, we will move it: !!DO NOT RESTART!!");
- boolean done = false;
- try {
- if(tmpFile.mkdir()) {
- File chkStoreCache = new
File("chk"+suffix+".cache");
- File chkStoreCacheNew = new
File("datastore/chk"+suffix+".cache");
-
if(!chkStoreCache.renameTo(chkStoreCacheNew))
- throw new IOException();
- File chkStoreStore = new
File("chk"+suffix+".store");
- File chkStoreStoreNew = new
File("datastore/chk"+suffix+".store");
-
if(!chkStoreStore.renameTo(chkStoreStoreNew))
- throw new IOException();
-
- File sskStoreCache = new
File("ssk"+suffix+".cache");
- File sskStoreCacheNew = new
File("datastore/ssk"+suffix+".cache");
-
if(!sskStoreCache.renameTo(sskStoreCacheNew))
- throw new IOException();
- File sskStoreStore = new
File("ssk"+suffix+".store");
- File sskStoreStoreNew = new
File("datastore/ssk"+suffix+".store");
-
if(!sskStoreStore.renameTo(sskStoreStoreNew))
- throw new IOException();
-
- File pubkeyStoreCache = new
File("pubkey"+suffix+".cache");
- File pubkeyStoreCacheNew = new
File("datastore/pubkey"+suffix+".cache");
-
if(!pubkeyStoreCache.renameTo(pubkeyStoreCacheNew))
- throw new IOException();
- File pubkeyStoreStore = new
File("pubkey"+suffix+".store");
- File pubkeyStoreStoreNew = new
File("datastore/pubkey"+suffix+".store");
-
if(!pubkeyStoreStore.renameTo(pubkeyStoreStoreNew))
- throw new IOException();
-
- File databaseStoreDir = new
File("database"+suffix);
- File databaseStoreDirNew = new
File("datastore/database"+suffix);
-
if(!databaseStoreDir.renameTo(databaseStoreDirNew))
- throw new IOException();
- done = true;
- }
- } catch (Throwable e) {
- e.printStackTrace();
- done = false;
- }
-
- if(done) {
- datastoreDir = "datastore/";
- nodeConfig.fixOldDefault("storeDir",
datastoreDir);
- Logger.normal(this, "The migration is complete,
cool :)");
- System.out.println("The migration is complete,
cool :)");
- } else {
- Logger.error(this, "Something went wrong :(
please report the bug!");
- System.err.println("Something went wrong :(
please report the bug!");
- }
- }
-
storeDir = new File(datastoreDir);
if(!((storeDir.exists() && storeDir.isDirectory()) ||
(storeDir.mkdir()))) {
String msg = "Could not find or create datastore
directory";
Modified: branches/db4o/freenet/src/freenet/node/NodeClientCore.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/NodeClientCore.java 2008-09-24
20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/node/NodeClientCore.java 2008-09-24
22:16:49 UTC (rev 22824)
@@ -1,5 +1,6 @@
package freenet.node;
+import freenet.config.NodeNeedRestartException;
import java.io.File;
import java.io.IOException;
import java.net.URI;
@@ -130,7 +131,6 @@
public static int maxBackgroundUSKFetchers; // Client stuff that
needs to be configged - FIXME
static final int MAX_ARCHIVE_HANDLERS = 200; // don't take up much
RAM... FIXME
static final long MAX_CACHED_ARCHIVE_DATA = 32 * 1024 * 1024; // make a
fixed fraction of the store by default? FIXME
- static final long MAX_ARCHIVE_SIZE = 2 * 1024 * 1024; // ??? FIXME
static final long MAX_ARCHIVED_FILE_SIZE = 1024 * 1024; // arbitrary...
FIXME
static final int MAX_CACHED_ELEMENTS = 256 * 1024; // equally
arbitrary! FIXME hopefully we can cache many of these though
/** Each FEC item can take a fair amount of RAM, since it's fully
activated with all the buckets, potentially 256
@@ -355,7 +355,21 @@
});
setUploadAllowedDirs(nodeConfig.getStringArr("uploadAllowedDirs"));
- archiveManager = new ArchiveManager(MAX_ARCHIVE_HANDLERS,
MAX_CACHED_ARCHIVE_DATA, MAX_ARCHIVE_SIZE, MAX_ARCHIVED_FILE_SIZE,
MAX_CACHED_ELEMENTS, tempBucketFactory);
+ nodeConfig.register("maxArchiveSize", "5MiB", sortOrder++,
true, false, "NodeClientCore.maxArchiveSize",
"NodeClientCore.maxArchiveSizeLong", new LongCallback() {
+
+ @Override
+ public Long get() {
+ return archiveManager.getMaxArchiveSize();
+ }
+
+ @Override
+ public void set(Long val) throws
InvalidConfigValueException, NodeNeedRestartException {
+ if(val == get()) return;
+ archiveManager.setMaxArchiveSize(val);
+ }
+ });
+
+ archiveManager = new ArchiveManager(MAX_ARCHIVE_HANDLERS,
MAX_CACHED_ARCHIVE_DATA, nodeConfig.getLong("maxArchiveSize"),
MAX_ARCHIVED_FILE_SIZE, MAX_CACHED_ELEMENTS, tempBucketFactory);
Logger.normal(this, "Initializing USK Manager");
System.out.println("Initializing USK Manager");
uskManager.init(container, clientContext);
Modified: branches/db4o/freenet/src/freenet/node/PeerManager.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/PeerManager.java 2008-09-24
20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/node/PeerManager.java 2008-09-24
22:16:49 UTC (rev 22824)
@@ -4,7 +4,6 @@
package freenet.node;
import java.io.BufferedReader;
-import java.io.BufferedWriter;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
@@ -14,7 +13,6 @@
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
-import java.io.Writer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
@@ -1068,6 +1066,7 @@
return sb.toString();
}
private final Object writePeersSync = new Object();
+ private final Object writePeerFileSync = new Object();
void writePeers() {
node.ps.queueTimedJob(new Runnable() {
@@ -1077,25 +1076,83 @@
}
}, 0);
}
+
+ protected StringBuilder getDarknetPeersString() {
+ StringBuilder sb = new StringBuilder();
+ PeerNode[] peers;
+ synchronized(this) {
+ peers = myPeers;
+ }
+ for(PeerNode pn : peers) {
+ if(pn instanceof DarknetPeerNode)
+ sb.append(pn.exportDiskFieldSet());
+ }
+
+ return sb;
+ }
+
+ protected StringBuilder getOpennetPeersString() {
+ StringBuilder sb = new StringBuilder();
+ PeerNode[] peers;
+ synchronized(this) {
+ peers = myPeers;
+ }
+ for(PeerNode pn : peers) {
+ if(pn instanceof OpennetPeerNode)
+ sb.append(pn.exportDiskFieldSet());
+ }
+
+ return sb;
+ }
+
+ protected StringBuilder getOldOpennetPeersString(OpennetManager om) {
+ StringBuilder sb = new StringBuilder();
+ PeerNode[] peers;
+ synchronized(this) {
+ peers = om.getOldPeers();
+ }
+ for(PeerNode pn : peers) {
+ if(pn instanceof OpennetPeerNode)
+ sb.append(pn.exportDiskFieldSet());
+ }
+
+ return sb;
+ }
private void writePeersInner() {
+ StringBuilder darknet = null;
+ StringBuilder opennet = null;
+ StringBuilder oldOpennetPeers = null;
+ String oldOpennetPeersFilename = null;
+
synchronized(writePeersSync) {
if(darkFilename != null)
- writePeersInner(darkFilename,
getDarknetPeers());
+ darknet = getDarknetPeersString();
OpennetManager om = node.getOpennet();
if(om != null) {
if(openFilename != null)
- writePeersInner(openFilename,
getOpennetPeers());
- writePeersInner(om.getOldPeersFilename(),
om.getOldPeers());
+ opennet = getOpennetPeersString();
+ oldOpennetPeersFilename =
om.getOldPeersFilename();
+ oldOpennetPeers = getOldOpennetPeersString(om);
}
}
+
+ synchronized(writePeerFileSync) {
+ if(darknet != null)
+ writePeersInner(darkFilename, darknet);
+ if(oldOpennetPeers != null) {
+ if(opennet != null)
+ writePeersInner(openFilename, opennet);
+ writePeersInner(oldOpennetPeersFilename,
oldOpennetPeers);
+ }
+ }
}
/**
* Write the peers file to disk
*/
- private void writePeersInner(String filename, PeerNode[] peers) {
- synchronized(writePeersSync) {
+ private void writePeersInner(String filename, StringBuilder sb) {
+ synchronized(writePeerFileSync) {
FileOutputStream fos = null;
String f = filename + ".bak";
try {
@@ -1112,13 +1169,11 @@
Closer.close(w);
throw new Error("Impossible: JVM doesn't
support UTF-8: " + e2, e2);
}
- BufferedWriter bw = new BufferedWriter(w);
try {
- boolean succeeded = writePeers(bw, peers);
- bw.close();
- bw = null;
- if(!succeeded)
- return;
+ w.write(sb.toString());
+ w.flush();
+ w.close();
+ w = null;
File fnam = new File(filename);
FileUtil.renameTo(new File(f), fnam);
@@ -1131,38 +1186,12 @@
Logger.error(this, "Cannot write file: " + e,
e);
return; // don't overwrite old file!
} finally {
- Closer.close(bw);
+ Closer.close(w);
Closer.close(fos);
}
}
}
- public boolean writePeers(Writer bw) {
- if(!writePeers(bw, getDarknetPeers()))
- return false;
- if(!writePeers(bw, getOpennetPeers()))
- return false;
- return true;
- }
-
- public boolean writePeers(Writer bw, PeerNode[] peers) {
- for(int i = 0; i < peers.length; i++) {
- try {
- peers[i].write(bw);
- bw.flush();
- } catch(IOException e) {
- try {
- bw.close();
- } catch(IOException e1) {
- Logger.error(this, "Cannot close file!:
" + e1, e1);
- }
- Logger.error(this, "Cannot write peers to disk:
" + e, e);
- return false;
- }
- }
- return true;
- }
-
/**
* Update the numbers needed by our PeerManagerUserAlert on the UAM.
* Also run the node's onConnectedPeers() method if applicable
Modified: branches/db4o/freenet/src/freenet/node/PeerNode.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/PeerNode.java 2008-09-24
20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/node/PeerNode.java 2008-09-24
22:16:49 UTC (rev 22824)
@@ -2564,6 +2564,17 @@
fs.put("metadata", meta);
fs.writeTo(w);
}
+
+ /**
+ * (both metadata + normal fieldset but atomically)
+ */
+ public synchronized SimpleFieldSet exportDiskFieldSet() {
+ SimpleFieldSet fs = exportFieldSet();
+ SimpleFieldSet meta = exportMetadataFieldSet();
+ if(!meta.isEmpty())
+ fs.put("metadata", meta);
+ return fs;
+ }
/**
* Export metadata about the node as a SimpleFieldSet
Modified: branches/db4o/freenet/src/freenet/node/TestnetHandler.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/TestnetHandler.java 2008-09-24
20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/node/TestnetHandler.java 2008-09-24
22:16:49 UTC (rev 22824)
@@ -182,8 +182,6 @@
fs =
node.exportOpennetPublicFieldSet();
fs.writeTo(bw);
}
- bw.write("\n\nMy peers:\n");
- node.peers.writePeers(bw);
bw.close();
}else {
Logger.error(this, "Unknown testnet
command: "+command);
Modified:
branches/db4o/freenet/src/freenet/node/fcp/FCPConnectionInputHandler.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/fcp/FCPConnectionInputHandler.java
2008-09-24 20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/node/fcp/FCPConnectionInputHandler.java
2008-09-24 22:16:49 UTC (rev 22824)
@@ -14,6 +14,7 @@
import freenet.support.SimpleFieldSet;
import freenet.support.io.Closer;
import freenet.support.io.LineReadingInputStream;
+import freenet.support.io.TooLongException;
public class FCPConnectionInputHandler implements Runnable {
@@ -31,6 +32,8 @@
freenet.support.Logger.OSThread.logPID(this);
try {
realRun();
+ } catch (TooLongException e) {
+ Logger.normal(this, "Caught"+e.getMessage(),e);
} catch (IOException e) {
if(Logger.shouldLog(Logger.MINOR, this))
Logger.minor(this, "Caught "+e, e);
Modified: branches/db4o/freenet/src/freenet/support/DoublyLinkedList.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/DoublyLinkedList.java
2008-09-24 20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/support/DoublyLinkedList.java
2008-09-24 22:16:49 UTC (rev 22824)
@@ -6,31 +6,31 @@
* Framework for managing a doubly linked list.
* @author tavin
*/
-public interface DoublyLinkedList<T> {
+public interface DoublyLinkedList<T extends DoublyLinkedList.Item<T>> {
public abstract DoublyLinkedList<T> clone();
/**
* List element
*/
- public interface Item<T> {
+ public interface Item<T extends Item<T>> {
/**
* Get next {@link Item}. May or may not return
* <code>null</code> if this is the last <code>Item</code>.
*
* @see DoublyLinkedList#hasNext()
*/
- DoublyLinkedList.Item<T> getNext();
+ T getNext();
/** Set next {@link Item} */
- DoublyLinkedList.Item<T> setNext(DoublyLinkedList.Item<T> i);
+ T setNext(T i);
/**
* Get previous {@link Item}. May or may not return <code>null</code>
* if this is the first <code>Item</code>.
*
* @see DoublyLinkedList#hasNext()
*/
- Item<T> getPrev();
+ T getPrev();
/** Get previous {@link Item} */
- Item<T> setPrev(DoublyLinkedList.Item<T> i);
+ T setPrev(T i);
/** Return the contained list. <strong>For sanity checking
only.</strong> */
DoublyLinkedList<T> getParent();
@@ -45,23 +45,23 @@
/** Check if this list is empty. @return <code>true</code> if this list is
empty, <code>false</code> otherwise. */
boolean isEmpty();
/** Get a {@link Enumeration} of {@link DoublyLinkedList.Item}. */
- Enumeration elements(); // for consistency w/ typical Java API
+ Enumeration<T> elements(); // for consistency w/ typical Java API
/**
* Returns the first item.
* @return the item at the head of the list, or <code>null</code> if empty
*/
- Item head();
+ T head();
/**
* Returns the last item.
* @return the item at the tail of the list, or <code>null</code> if empty
*/
- Item tail();
+ T tail();
/**
* Puts the item before the first item.
*/
- void unshift(DoublyLinkedList.Item<T> i);
+ void unshift(T i);
/**
* Put all items in the specified list before the first item.
*/
@@ -69,7 +69,7 @@
/**
* Removes and returns the first item.
*/
- Item shift();
+ T shift();
/**
* Remove <tt>n</tt> elements from head and return them as a
<code>DoublyLinkedList</code>.
*/
@@ -78,7 +78,7 @@
/**
* Puts the item after the last item.
*/
- void push(DoublyLinkedList.Item<T> i);
+ void push(T i);
/**
* Puts all items in the specified list after the last item.
*/
@@ -86,41 +86,41 @@
/**
* Removes and returns the last item.
*/
- Item pop();
+ T pop();
/**
* Remove <tt>n</tt> elements from tail and return them as a
<code>DoublyLinkedList</code>.
*/
DoublyLinkedList pop(int n);
- /** @return <code>true</code> if <code>i</code> has next item. (ie. not
the last item); <code>false</code> otherwise */
- boolean hasNext(DoublyLinkedList.Item<T> i);
+ /** @return <code>true</code> if <code>i</code> has next item. (ie. not
the last item); <code>false</code> otherwise */
+ boolean hasNext(T i);
/** @return <code>true</code> if <code>i</code> has previous item. (ie.
not the first item); <code>false</code> otherwise */
- boolean hasPrev(DoublyLinkedList.Item<T> i);
+ boolean hasPrev(T i);
/** @return next item of <code>i</code>. If this is the last element,
return <code>null</code> */
- Item next(DoublyLinkedList.Item<T> i);
+ T next(T i);
/** @return previous item of <code>i</code>. If this is the first element,
return <code>null</code> */
- Item prev(DoublyLinkedList.Item<T> i);
- /** Remove and return a element
+ T prev(T i);
+ /** Remove and return a element
* @return this item, or <code>null</code> if the item was not in the list
*/
- Item remove(DoublyLinkedList.Item<T> i);
+ T remove(T i);
/**
* Inserts item <code>j</code> before item <code>i</code>.
*/
- void insertPrev(DoublyLinkedList.Item<T> i, DoublyLinkedList.Item<T> j);
+ void insertPrev(T i, T j);
/**
* Inserts the entire {@link DoublyLinkedList} <code>l</code> before item
<code>i</code>.
*/
- void insertPrev(DoublyLinkedList.Item<T> i, DoublyLinkedList<T> l);
+ void insertPrev(T i, DoublyLinkedList<T> l);
/**
* Inserts item <code>j</code> after item <code>i</code.
*/
- void insertNext(DoublyLinkedList.Item<T> i, DoublyLinkedList.Item<T> j);
+ void insertNext(T i, T j);
/**
* Inserts the entire {@link DoublyLinkedList} <code>l</code> after item
<code>i</code>.
*/
- void insertNext(DoublyLinkedList.Item<T> i, DoublyLinkedList<T> l);
+ void insertNext(T i, DoublyLinkedList<T> l);
}
Modified: branches/db4o/freenet/src/freenet/support/DoublyLinkedListImpl.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/DoublyLinkedListImpl.java
2008-09-24 20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/support/DoublyLinkedListImpl.java
2008-09-24 22:16:49 UTC (rev 22824)
@@ -10,10 +10,10 @@
* TODO: there are still some unimplemented methods
* -- it remains to be seen if they are needed at all
*/
-public class DoublyLinkedListImpl<T> implements DoublyLinkedList<T>{
+public class DoublyLinkedListImpl<T extends DoublyLinkedListImpl.Item<T>>
implements DoublyLinkedList<T> {
protected int size;
- protected DoublyLinkedListImpl.Item<T> _headptr, _tailptr;
+ protected T _headptr, _tailptr;
@Override
public final DoublyLinkedListImpl<T> clone() {
@@ -24,14 +24,14 @@
* A new list with no items.
*/
public DoublyLinkedListImpl() {
- _headptr = new Item<T>();
- _tailptr = new Item<T>();
+ _headptr = (T) new Item();
+ _tailptr = (T) new Item();
_headptr.setParent(this);
_tailptr.setParent(this);
clear();
}
- protected DoublyLinkedListImpl(DoublyLinkedListImpl.Item<T> _h,
DoublyLinkedListImpl.Item<T> _t, int size) {
+ protected DoublyLinkedListImpl(T _h, T _t, int size) {
_headptr = _h;
_tailptr = _t;
_headptr.setParent(this);
@@ -43,13 +43,13 @@
/**
* @param impl
*/
- protected DoublyLinkedListImpl(DoublyLinkedListImpl impl) {
+ protected DoublyLinkedListImpl(DoublyLinkedListImpl<T> impl) {
this();
- Enumeration<DoublyLinkedListImpl.Item<T>> e = impl.forwardElements();
+ Enumeration<T> e = impl.forwardElements();
boolean checked = false;
for(;e.hasMoreElements();) {
- DoublyLinkedListImpl.Item<T> oi = e.nextElement();
- DoublyLinkedList.Item<T> i = oi.clone();
+ T oi = e.nextElement();
+ T i = oi.clone();
if(!checked) {
checked = true;
if(!i.getClass().getName().equals(oi.getClass().getName())) {
@@ -70,8 +70,8 @@
// Help to detect removal after clear().
// The check in remove() is enough, strictly,
// as long as people don't add elements afterwards.
- DoublyLinkedList.Item<T> pos = _headptr.next;
- DoublyLinkedList.Item<T> opos = _headptr;
+ DoublyLinkedList.Item pos = _headptr.next;
+ DoublyLinkedList.Item opos = _headptr;
while(true) {
if(pos == _tailptr) break;
if(pos == null) break;
@@ -104,22 +104,22 @@
* {@inheritDoc}
* @see #forwardElements()
*/
- public final Enumeration<DoublyLinkedList.Item<T>> elements() {
+ public final Enumeration elements() {
return forwardElements();
}
/**
* {@inheritDoc}
*/
- public final DoublyLinkedList.Item<T> head() {
- return size == 0 ? null : _headptr.next;
+ public final T head() {
+ return size == 0 ? null : (T) _headptr.next;
}
/**
* {@inheritDoc}
*/
- public final DoublyLinkedList.Item<T> tail() {
- return size == 0 ? null : _tailptr.prev;
+ public final T tail() {
+ return size == 0 ? null : (T) _tailptr.prev;
}
@@ -127,8 +127,8 @@
/**
* {@inheritDoc}
*/
- public final void unshift(DoublyLinkedList.Item<T> i) {
- insertNext(_headptr, i);
+ public final void unshift(T i) {
+ insertNext((T) _headptr, i);
}
/**
@@ -141,8 +141,8 @@
/**
* {@inheritDoc}
*/
- public final DoublyLinkedList.Item<T> shift() {
- return size == 0 ? null : remove(_headptr.next);
+ public final T shift() {
+ return size == 0 ? null : (T) remove((T) _headptr.next);
}
/**
* {@inheritDoc}
@@ -152,13 +152,13 @@
if (n > size) n = size;
if (n < 1) return new DoublyLinkedListImpl<T>();
- DoublyLinkedList.Item<T> i = _headptr;
+ T i = _headptr;
for (int m=0; m<n; ++m)
i = i.getNext();
- DoublyLinkedList.Item<T> j = i.getNext();
- Item<T> newheadptr = new Item<T>();
- Item<T> newtailptr = new Item<T>();
+ T j = i.getNext();
+ T newheadptr = (T) new Item<T>();
+ T newtailptr = (T) new Item<T>();
j.setPrev(newheadptr);
newheadptr.setNext(j);
@@ -179,8 +179,8 @@
/**
* {@inheritDoc}
*/
- public final void push(DoublyLinkedList.Item<T> i) {
- insertPrev(_tailptr, i);
+ public final void push(T i) {
+ insertPrev((T) _tailptr, i);
}
/**
* {@inheritDoc}
@@ -192,8 +192,8 @@
/**
* {@inheritDoc}
*/
- public final DoublyLinkedList.Item<T> pop() {
- return size == 0 ? null : remove(_tailptr.prev);
+ public final T pop() {
+ return size == 0 ? null : (T) remove((T) _tailptr.prev);
}
/**
* {@inheritDoc}
@@ -203,13 +203,13 @@
if (n > size) n = size;
if (n < 1) return new DoublyLinkedListImpl<T>();
- DoublyLinkedList.Item<T> i = _tailptr;
+ T i = _tailptr;
for (int m=0; m<n; ++m)
i = i.getPrev();
- DoublyLinkedList.Item<T> j = i.getPrev();
- DoublyLinkedListImpl.Item<T> newtailptr = new Item<T>();
- DoublyLinkedListImpl.Item<T> newheadptr = new Item<T>();
+ T j = i.getPrev();
+ T newtailptr = (T) new Item<T>();
+ T newheadptr = (T) new Item<T>();
j.setNext(newtailptr);
newtailptr.setPrev(j);
@@ -230,29 +230,29 @@
/**
* {@inheritDoc}
*/
- public final boolean hasNext(DoublyLinkedList.Item<T> i) {
- DoublyLinkedList.Item<T> next = i.getNext();
+ public final boolean hasNext(T i) {
+ DoublyLinkedList.Item next = i.getNext();
return (next != null) && (next != _tailptr);
}
/**
* {@inheritDoc}
*/
- public final boolean hasPrev(DoublyLinkedList.Item<T> i) {
- DoublyLinkedList.Item<T> prev = i.getPrev();
+ public final boolean hasPrev(T i) {
+ DoublyLinkedList.Item prev = i.getPrev();
return (prev != null) && (prev != _headptr);
}
/**
* {@inheritDoc}
*/
- public final DoublyLinkedList.Item<T> next(DoublyLinkedList.Item<T> i) {
- DoublyLinkedList.Item<T> next = i.getNext();
- return next == _tailptr ? null : next;
+ public final T next(T i) {
+ T next = i.getNext();
+ return next == _tailptr ? null : (T) next;
}
/**
* {@inheritDoc}
*/
- public final DoublyLinkedList.Item<T> prev(DoublyLinkedList.Item<T> i) {
- DoublyLinkedList.Item<T> prev = i.getPrev();
+ public final T prev(T i) {
+ T prev = i.getPrev();
return prev == _headptr ? null : prev;
}
@@ -262,7 +262,7 @@
/**
* {@inheritDoc}
*/
- public DoublyLinkedList.Item<T> remove(DoublyLinkedList.Item<T> i) {
+ public T remove(T i) {
if (i.getParent() == null) return null; // not in list
if(isEmpty()) {
Logger.error(this, "Illegal ERROR: Removing from an empty
list!!");
@@ -270,7 +270,7 @@
}
if (i.getParent() != this)
throw new PromiscuousItemException(i, i.getParent());
- DoublyLinkedList.Item<T> next = i.getNext(), prev = i.getPrev();
+ T next = i.getNext(), prev = i.getPrev();
if ((next == null) && (prev == null)) return null; // not in the list
if ((next == null) || (prev == null))
throw new NullPointerException("next="+next+", prev="+prev); //
partially in the list?!
@@ -291,7 +291,7 @@
/**
* {@inheritDoc}
*/
- public void insertPrev(DoublyLinkedList.Item<T> i,
DoublyLinkedList.Item<T> j) {
+ public void insertPrev(T i, T j) {
if (i.getParent() == null)
throw new PromiscuousItemException(i, i.getParent()); //
different trace to make easier debugging
if (i.getParent() != this)
@@ -300,7 +300,7 @@
throw new PromiscuousItemException(j, j.getParent());
if ((j.getNext() != null) || (j.getPrev() != null))
throw new PromiscuousItemException(j);
- DoublyLinkedList.Item<T> prev = i.getPrev();
+ T prev = i.getPrev();
if (prev == null)
throw new VirginItemException(i);
prev.setNext(j);
@@ -315,21 +315,21 @@
* {@inheritDoc}
* FIXME: unimplemented
*/
- public void insertPrev(DoublyLinkedList.Item<T> i, DoublyLinkedList<T> l) {
+ public void insertPrev(T i, DoublyLinkedList<T> l) {
throw new RuntimeException("function currently unimplemented because i
am a lazy sod");
}
/**
* {@inheritDoc}
*/
- public void insertNext(DoublyLinkedList.Item<T> i,
DoublyLinkedList.Item<T> j) {
+ public void insertNext(T i, T j) {
if (i.getParent() != this)
throw new PromiscuousItemException(i, i.getParent());
if (j.getParent() != null)
throw new PromiscuousItemException(j, i.getParent());
if ((j.getNext() != null) || (j.getPrev() != null))
throw new PromiscuousItemException(j);
- DoublyLinkedList.Item next = i.getNext();
+ T next = i.getNext();
if (next == null)
throw new VirginItemException(i);
next.setPrev(j);
@@ -344,7 +344,7 @@
* {@inheritDoc}
* FIXME: unimplemented
*/
- public void insertNext(DoublyLinkedList.Item<T> i, DoublyLinkedList<T> l) {
+ public void insertNext(T i, DoublyLinkedList<T> l) {
throw new RuntimeException("function currently unimplemented because i
am a lazy sod");
}
@@ -354,54 +354,54 @@
/**
* @return an Enumeration of list elements from head to tail
*/
- private Enumeration<DoublyLinkedList.Item<T>> forwardElements() {
+ private Enumeration<T> forwardElements() {
return new ForwardWalker();
}
/**
* @return an Enumeration of list elements from tail to head
*/
- protected Enumeration<DoublyLinkedList.Item<T>> reverseElements() {
- return new ReverseWalker();
+ protected Enumeration<T> reverseElements() {
+ return new ReverseWalker();
}
- private class ForwardWalker<T extends DoublyLinkedListImpl.Item<T>>
implements Enumeration<DoublyLinkedList.Item<T>> {
- protected DoublyLinkedList.Item<T> next;
+ private class ForwardWalker implements Enumeration<T> {
+ protected DoublyLinkedList.Item next;
protected ForwardWalker() {
next = _headptr.getNext();
}
- protected ForwardWalker(DoublyLinkedList.Item<T> startAt,
+ protected ForwardWalker(DoublyLinkedList.Item startAt,
boolean inclusive) {
next = (inclusive ? startAt : startAt.getNext());
}
public final boolean hasMoreElements() {
return next != _tailptr;
}
- public DoublyLinkedList.Item<T> nextElement() {
+ public T nextElement() {
if (next == _tailptr)
throw new NoSuchElementException();
- DoublyLinkedList.Item<T> result = next;
+ T result = (T) next;
next = next.getNext();
return result;
}
}
- private class ReverseWalker<T extends DoublyLinkedList.Item<T>> implements
Enumeration<DoublyLinkedList.Item<T>> {
- protected DoublyLinkedList.Item<T> next;
+ private class ReverseWalker implements Enumeration<T> {
+ protected DoublyLinkedList.Item next;
protected ReverseWalker() {
next = _tailptr.getPrev();
}
- protected ReverseWalker(DoublyLinkedList.Item<T> startAt,
+ protected ReverseWalker(DoublyLinkedList.Item startAt,
boolean inclusive) {
next = (inclusive ? startAt : startAt.getPrev());
}
public final boolean hasMoreElements() {
return next != _headptr;
}
- public DoublyLinkedList.Item<T> nextElement() {
+ public T nextElement() {
if (next == _headptr)
throw new NoSuchElementException();
- DoublyLinkedList.Item<T> result = next;
+ T result = (T) next;
if(next == null) throw new IllegalStateException("next==null");
next = next.getPrev();
return result;
@@ -411,36 +411,36 @@
//=== list element ====================================================
- public static class Item<T> implements DoublyLinkedList.Item<T> {
- private DoublyLinkedList.Item<T> prev;
- private DoublyLinkedList.Item<T> next;
+ public static class Item<T extends Item<T>> implements
DoublyLinkedList.Item<T> {
+ private T prev;
+ private T next;
private DoublyLinkedList list;
@Override
- public DoublyLinkedList.Item<T> clone() {
+ public T clone() {
if(getClass() != Item.class)
throw new RuntimeException("Must implement clone() for
"+getClass());
- return new Item<T>();
+ return (T) new Item();
}
- public final DoublyLinkedList.Item getNext() {
+ public final T getNext() {
return next;
}
- public final DoublyLinkedList.Item setNext(DoublyLinkedList.Item<T> i)
{
- DoublyLinkedList.Item<T> old = next;
+ public final T setNext(T i) {
+ T old = next;
next = i;
return old;
}
- public final DoublyLinkedList.Item getPrev() {
+ public final T getPrev() {
return prev;
}
- public final DoublyLinkedList.Item setPrev(DoublyLinkedList.Item<T> i)
{
- DoublyLinkedList.Item<T> old = prev;
+ public final T setPrev(T i) {
+ T old = prev;
prev = i;
return old;
}
- public DoublyLinkedList getParent() {
+ public DoublyLinkedList<T> getParent() {
return list;
}
- public DoublyLinkedList setParent(DoublyLinkedList<T> l) {
+ public DoublyLinkedList<T> setParent(DoublyLinkedList<T> l) {
DoublyLinkedList old = list;
list = l;
return old;
Modified: branches/db4o/freenet/src/freenet/support/HTMLNode.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/HTMLNode.java 2008-09-24
20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/support/HTMLNode.java 2008-09-24
22:16:49 UTC (rev 22824)
@@ -8,7 +8,6 @@
import java.util.Locale;
import java.util.Map;
import java.util.Set;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class HTMLNode implements XMLCharacterClasses {
@@ -44,9 +43,7 @@
}
public HTMLNode(String name, String[] attributeNames, String[]
attributeValues, String content) {
-
- Matcher nameMatcher = namePattern.matcher(name);
- if ((name == null) || (!"#".equals(name) && !"%".equals(name)
&& !nameMatcher.matches())) {
+ if ((name == null) || (!"#".equals(name) && !"%".equals(name)
&& !namePattern.matcher(name).matches())) {
throw new IllegalArgumentException("element name is not
legal");
}
if ((attributeNames != null) && (attributeValues != null)) {
@@ -193,7 +190,9 @@
}
if (children.size() == 0) {
if ("textarea".equals(name) || ("div").equals(name) ||
("a").equals(name)) {
-
tagBuffer.append("></").append(name).append('>');
+ tagBuffer.append("></");
+ tagBuffer.append(name);
+ tagBuffer.append('>');
} else {
tagBuffer.append(" />");
}
@@ -206,7 +205,9 @@
HTMLNode childNode = children.get(childIndex);
childNode.generate(tagBuffer);
}
- tagBuffer.append("</").append(name).append('>');
+ tagBuffer.append("</");
+ tagBuffer.append(name);
+ tagBuffer.append('>');
if(("div").equals(name)|| ("form").equals(name)||
("input").equals(name)|| ("li").equals(name)|| ("option").equals(name)||
("script").equals(name)|| ("table").equals(name)|| ("tr").equals(name)||
("td").equals(name)) {
tagBuffer.append('\n');
}
Modified: branches/db4o/freenet/src/freenet/support/LRUHashtable.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/LRUHashtable.java 2008-09-24
20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/support/LRUHashtable.java 2008-09-24
22:16:49 UTC (rev 22824)
@@ -12,7 +12,7 @@
* push is by far the most done operation, this should be an
* overall improvement.
*/
- private final DoublyLinkedListImpl<V> list = new DoublyLinkedListImpl<V>();
+ private final DoublyLinkedListImpl<QItem<K, V>> list = new
DoublyLinkedListImpl<QItem<K, V>>();
private final Hashtable<K, QItem<K, V>> hash = new Hashtable<K, QItem<K,
V>>();
/**
@@ -34,12 +34,12 @@
Logger.minor(this, "Pushed "+insert+" ( "+key+ ' ' +value+" )");
list.unshift(insert);
- }
+ }
/**
* @return Least recently pushed key.
*/
- public final synchronized Object popKey() {
+ public final synchronized K popKey() {
if ( list.size() > 0 ) {
return ( hash.remove(((QItem) list.pop()).obj)).obj;
} else {
@@ -50,7 +50,7 @@
/**
* @return Least recently pushed value.
*/
- public final synchronized Object popValue() {
+ public final synchronized V popValue() {
if ( list.size() > 0 ) {
return ( hash.remove(((QItem) list.pop()).obj)).value;
} else {
@@ -58,12 +58,12 @@
}
}
- public final synchronized Object peekValue() {
+ public final synchronized V peekValue() {
if ( list.size() > 0 ) {
if(hash == null) throw new NullPointerException();
- QItem tail = (QItem) list.tail();
+ QItem<K,V> tail = (QItem<K,V>) list.tail();
Object object = tail.obj;
- QItem i = (QItem) hash.get(object);
+ QItem<K,V> i = (QItem<K,V>) hash.get(object);
if(i == null) {
String obToString = "(toString() threw)";
try {
@@ -114,39 +114,39 @@
return q.value;
}
- public Enumeration keys() {
+ public Enumeration<K> keys() {
return new ItemEnumeration();
}
- public Enumeration values() {
+ public Enumeration<V> values() {
return new ValuesEnumeration();
}
- private class ItemEnumeration implements Enumeration {
- private Enumeration source = list.reverseElements();
+ private class ItemEnumeration implements Enumeration<K> {
+ private Enumeration<QItem<K, V>> source =
list.reverseElements();
public boolean hasMoreElements() {
return source.hasMoreElements();
}
- public Object nextElement() {
- return ((QItem) source.nextElement()).obj;
+ public K nextElement() {
+ return source.nextElement().obj;
}
}
- private class ValuesEnumeration implements Enumeration {
- private Enumeration source = list.reverseElements();
+ private class ValuesEnumeration implements Enumeration<V> {
+ private Enumeration<QItem<K, V>> source =
list.reverseElements();
public boolean hasMoreElements() {
return source.hasMoreElements();
}
- public Object nextElement() {
- return ((QItem) source.nextElement()).value;
+ public V nextElement() {
+ return (source.nextElement()).value;
}
}
- public static class QItem<K, V> extends DoublyLinkedListImpl.Item<V> {
+ protected static class QItem<K, V> extends
DoublyLinkedListImpl.Item<QItem<K, V>> {
public K obj;
public V value;
@@ -166,7 +166,7 @@
}
/**
- * Note that unlike the java.util versions, this will not reallocate
(hence it doesn't return),
+ * Note that unlike the java.util versions, this will not reallocate
(hence it doesn't return),
* so pass in an appropriately big array, and make sure you hold the
lock!
* @param entries
* @return
Modified: branches/db4o/freenet/src/freenet/support/LRUQueue.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/LRUQueue.java 2008-09-24
20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/support/LRUQueue.java 2008-09-24
22:16:49 UTC (rev 22824)
@@ -3,7 +3,7 @@
import java.util.Enumeration;
import java.util.Hashtable;
-public class LRUQueue {
+public class LRUQueue<T> {
/*
* I've just converted this to using the DLList and Hashtable
@@ -12,8 +12,8 @@
* push is by far the most done operation, this should be an
* overall improvement.
*/
- private final DoublyLinkedListImpl list = new DoublyLinkedListImpl();
- private final Hashtable hash = new Hashtable();
+ private final DoublyLinkedListImpl<QItem<T>> list = new
DoublyLinkedListImpl<QItem<T>>();
+ private final Hashtable<T, QItem<T>> hash = new Hashtable<T, QItem<T>>();
/**
* push()ing an object that is already in
@@ -21,10 +21,10 @@
* recently used position, but doesn't add
* a duplicate entry in the queue.
*/
- public final synchronized void push(Object obj) {
- QItem insert = (QItem)hash.get(obj);
+ public final synchronized void push(T obj) {
+ QItem<T> insert = hash.get(obj);
if (insert == null) {
- insert = new QItem(obj);
+ insert = new QItem<T>(obj);
hash.put(obj,insert);
} else {
list.remove(insert);
@@ -36,10 +36,10 @@
/**
* push to bottom (least recently used position)
*/
- public synchronized void pushLeast(Object obj) {
- QItem insert = (QItem)hash.get(obj);
+ public synchronized void pushLeast(T obj) {
+ QItem<T> insert = hash.get(obj);
if (insert == null) {
- insert = new QItem(obj);
+ insert = new QItem<T>(obj);
hash.put(obj,insert);
} else {
list.remove(insert);
@@ -51,9 +51,9 @@
/**
* @return Least recently pushed Object.
*/
- public final synchronized Object pop() {
+ public final synchronized T pop() {
if ( list.size() > 0 ) {
- return ((QItem)hash.remove(((QItem)list.pop()).obj)).obj;
+ return hash.remove(list.pop().obj).obj;
} else {
return null;
}
@@ -63,8 +63,8 @@
return list.size();
}
- public final synchronized boolean remove(Object obj) {
- QItem i = (QItem)(hash.remove(obj));
+ public final synchronized boolean remove(T obj) {
+ QItem<T> i = hash.remove(obj);
if(i != null) {
list.remove(i);
return true;
@@ -82,26 +82,26 @@
return hash.containsKey(obj);
}
- public Enumeration elements() {
+ public Enumeration<T> elements() {
return new ItemEnumeration();
}
- private class ItemEnumeration implements Enumeration {
- private Enumeration source = list.reverseElements();
+ private class ItemEnumeration implements Enumeration<T> {
+ private Enumeration<QItem<T>> source = list.reverseElements();
public boolean hasMoreElements() {
return source.hasMoreElements();
}
- public Object nextElement() {
- return ((QItem) source.nextElement()).obj;
+ public T nextElement() {
+ return source.nextElement().obj;
}
}
- private static class QItem extends DoublyLinkedListImpl.Item {
- public Object obj;
+ private static class QItem<T> extends DoublyLinkedListImpl.Item<QItem<T>> {
+ public T obj;
- public QItem(Object obj) {
+ public QItem(T obj) {
this.obj = obj;
}
}
@@ -119,7 +119,7 @@
* order.
* @param array The array to fill in. If it is too small a new array of
the same type will be allocated.
*/
- public synchronized Object[] toArray(Object[] array) {
+ public synchronized <E> E[] toArray(E[] array) {
return hash.keySet().toArray(array);
}
@@ -131,8 +131,8 @@
public synchronized Object[] toArrayOrdered() {
Object[] array = new Object[list.size()];
int x = 0;
- for(Enumeration e =
list.reverseElements();e.hasMoreElements();) {
- array[x++] = ((QItem)e.nextElement()).obj;
+ for(Enumeration<QItem<T>> e =
list.reverseElements();e.hasMoreElements();) {
+ array[x++] = e.nextElement().obj;
}
return array;
}
@@ -146,14 +146,14 @@
* The array to fill in. If it is too small a new array of
the
* same type will be allocated.
*/
- public synchronized Object[] toArrayOrdered(Object[] array) {
+ public synchronized <E> E[] toArrayOrdered(E[] array) {
array = toArray(array);
int listSize = list.size();
if(array.length != listSize)
throw new
IllegalStateException("array.length="+array.length+" but list.size="+listSize);
int x = 0;
- for(Enumeration e =
list.reverseElements();e.hasMoreElements();) {
- array[x++] = ((QItem)e.nextElement()).obj;
+ for(Enumeration<QItem<T>> e =
list.reverseElements();e.hasMoreElements();) {
+ array[x++] = (E) e.nextElement().obj;
}
return array;
}
Modified: branches/db4o/freenet/src/freenet/support/io/ArrayBucket.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/io/ArrayBucket.java
2008-09-24 20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/support/io/ArrayBucket.java
2008-09-24 22:16:49 UTC (rev 22824)
@@ -1,5 +1,6 @@
package freenet.support.io;
+import freenet.support.Logger;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -13,28 +14,40 @@
import freenet.support.api.Bucket;
/**
- * A bucket that stores data in the memory.
- *
- * @author oskar
+ * A bucket that stores data in RAM
*/
public class ArrayBucket implements Bucket {
private final ArrayList<byte[]> data;
private final String name;
private volatile boolean readOnly;
-
- public ArrayBucket() {
- this("ArrayBucket");
+
+ /** The maximum size of the bucket; -1 means no maxSize */
+ private final long maxSize;
+ private long size;
+
+ private static boolean logDEBUG = false;
+
+ public ArrayBucket(long maxSize) {
+ this("ArrayBucket", maxSize);
}
+
+ public ArrayBucket(byte[] finalData) {
+ this(finalData, finalData.length);
+ setReadOnly();
+ }
- public ArrayBucket(byte[] initdata) {
- this("ArrayBucket");
+ public ArrayBucket(byte[] initdata, long maxSize) {
+ this("ArrayBucket", maxSize);
data.add(initdata);
}
- ArrayBucket(String name) {
+ ArrayBucket(String name, long maxSize) {
data = new ArrayList<byte[]>();
this.name = name;
+ this.maxSize = maxSize;
+ if(logDEBUG && maxSize < 0)
+ Logger.minor(this, "Has been called with maxSize<0 !",
new NullPointerException());
}
public synchronized OutputStream getOutputStream() throws IOException {
@@ -67,12 +80,7 @@
}
public synchronized long size() {
- long currentSize = 0;
-
- for(byte[] buf : data)
- currentSize += buf.length;
-
- return currentSize;
+ return size;
}
public String getName() {
@@ -89,13 +97,23 @@
@Override
public synchronized void write(byte b[], int off, int len) {
if(readOnly) throw new IllegalStateException("Read
only");
+ long sizeIfWritten = size + len;
+ if(logDEBUG && maxSize > -1 && maxSize < sizeIfWritten)
// FIXME: should be IOE but how to do it?
+ throw new IllegalArgumentException("The maxSize
of the bucket is "+maxSize+
+ " and writing "+len+ " bytes to it
would make it oversize!");
super.write(b, off, len);
+ size = sizeIfWritten;
}
@Override
public synchronized void write(int b) {
if(readOnly) throw new IllegalStateException("Read
only");
+ long sizeIfWritten = size + 1;
+ if(logDEBUG && maxSize > -1 && maxSize < sizeIfWritten)
// FIXME: should be IOE but how to do it?
+ throw new IllegalArgumentException("The maxSize
of the bucket is "+maxSize+
+ " and writing 1 byte to it would make
it oversize!");
super.write(b);
+ size = sizeIfWritten;
}
@Override
@@ -128,12 +146,12 @@
return -1;
}
}
- int i = in.read();
- if (i == -1) {
+ int x = in.read();
+ if (x == -1) {
in = null;
return priv_read();
} else {
- return i;
+ return x;
}
}
@@ -155,12 +173,12 @@
return -1;
}
}
- int i = in.read(b, off, len);
- if (i == -1) {
+ int x = in.read(b, off, len);
+ if (x == -1) {
in = null;
return priv_read(b, off, len);
} else {
- return i;
+ return x;
}
}
@@ -187,14 +205,16 @@
}
public synchronized void free() {
+ readOnly = true;
data.clear();
+ size = 0;
// Not much else we can do.
}
public synchronized byte[] toByteArray() {
long sz = size();
- int size = (int)sz;
- byte[] buf = new byte[size];
+ int bufSize = (int)sz;
+ byte[] buf = new byte[bufSize];
int index = 0;
for(Iterator i=data.iterator();i.hasNext();) {
byte[] obuf = (byte[]) i.next();
Modified: branches/db4o/freenet/src/freenet/support/io/ArrayBucketFactory.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/io/ArrayBucketFactory.java
2008-09-24 20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/support/io/ArrayBucketFactory.java
2008-09-24 22:16:49 UTC (rev 22824)
@@ -11,11 +11,11 @@
public class ArrayBucketFactory implements BucketFactory {
public Bucket makeBucket(long size) throws IOException {
- return new ArrayBucket();
+ return new ArrayBucket(size);
}
public void freeBucket(Bucket b) throws IOException {
- // Do nothing
+ b.free();
}
}
Modified:
branches/db4o/freenet/src/freenet/support/io/LineReadingInputStream.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/io/LineReadingInputStream.java
2008-09-24 20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/support/io/LineReadingInputStream.java
2008-09-24 22:16:49 UTC (rev 22824)
@@ -3,6 +3,7 @@
* http://www.gnu.org/ for further details of the GPL. */
package freenet.support.io;
+import freenet.support.HexUtil;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -32,7 +33,7 @@
byte[] buf = new byte[Math.max(Math.min(128, maxLength),
Math.min(1024, bufferSize))];
int ctr = 0;
- mark((maxLength+1)*2); // Might be more than maxLengh if we use
utf8
+ mark(Integer.MAX_VALUE); // Might be more than maxLengh if we
use utf8
while(true) {
int x = read(buf, ctr, buf.length - ctr);
if(x == -1) {
@@ -41,9 +42,8 @@
return new String(buf, 0, ctr, utf ? "UTF-8" :
"ISO-8859-1");
}
// REDFLAG this is definitely safe with the above
charsets, it may not be safe with some wierd ones.
- for(; ctr < buf.length; ctr++) {
- if(ctr >= maxLength)
- throw new TooLongException();
+ int end = ctr + x;
+ for(; ctr < end; ctr++) {
if(buf[ctr] == '\n') {
String toReturn = "";
if(ctr != 0) {
@@ -54,10 +54,12 @@
skip(ctr + 1);
return toReturn;
}
+ if(ctr >= maxLength)
+ throw new TooLongException("We reached
maxLength="+maxLength+ " parsing\n "+HexUtil.bytesToHex(buf, 0, ctr) + "\n" +
new String(buf, 0, ctr, utf ? "UTF-8" : "ISO-8859-1"));
}
- if(x > 0) {
+ if((buf.length != maxLength) && (buf.length - ctr <
bufferSize)) {
byte[] newBuf = new byte[Math.min(buf.length *
2, maxLength)];
- System.arraycopy(buf, 0, newBuf, 0, buf.length);
+ System.arraycopy(buf, 0, newBuf, 0, ctr);
buf = newBuf;
}
}
@@ -84,7 +86,7 @@
return new String(buf, 0, ctr, utf ? "UTF-8" :
"ISO-8859-1");
}
if(ctr >= maxLength)
- throw new TooLongException();
+ throw new TooLongException("We reached
maxLength="+maxLength+ " parsing\n "+HexUtil.bytesToHex(buf, 0, ctr) + "\n" +
new String(buf, 0, ctr, utf ? "UTF-8" : "ISO-8859-1"));
if(ctr >= buf.length) {
byte[] newBuf = new byte[Math.min(buf.length *
2, maxLength)];
System.arraycopy(buf, 0, newBuf, 0, buf.length);
Modified: branches/db4o/freenet/src/freenet/support/io/TempBucketFactory.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/io/TempBucketFactory.java
2008-09-24 20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/support/io/TempBucketFactory.java
2008-09-24 22:16:49 UTC (rev 22824)
@@ -1,3 +1,6 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
package freenet.support.io;
import freenet.crypt.RandomSource;
@@ -6,32 +9,95 @@
import freenet.support.api.Bucket;
import freenet.support.api.BucketFactory;
-/*
- * This code is part of FProxy, an HTTP proxy server for Freenet. It is
- * distributed under the GNU Public Licence (GPL) version 2. See
- * http://www.gnu.org/ for further details of the GPL.
- */
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.Random;
+import com.db4o.ObjectContainer;
+
/**
* Temporary Bucket Factory
- *
- * @author giannij
*/
public class TempBucketFactory implements BucketFactory {
+ public class TempBucket implements Bucket {
+ private Bucket currentBucket;
+
+ public TempBucket(Bucket cur) {
+ this.currentBucket = cur;
+ }
+
+ public final void migrateToFileBucket() throws IOException {
+ RAMBucket ramBucket = null;
+ synchronized(this) {
+ if(!isRAMBucket())
+ return;
+ ramBucket = (RAMBucket) currentBucket;
+ TempFileBucket tempFB = new
TempFileBucket(filenameGenerator.makeRandomFilename(), filenameGenerator);
+ BucketTools.copy(currentBucket, tempFB);
+ currentBucket = tempFB;
+ }
+ ramBucket.free();
+ }
+
+ public final synchronized boolean isRAMBucket() {
+ return (currentBucket instanceof RAMBucket);
+ }
+
+ public synchronized OutputStream getOutputStream() throws
IOException {
+ return currentBucket.getOutputStream();
+ }
+
+ public synchronized InputStream getInputStream() throws
IOException {
+ return currentBucket.getInputStream();
+ }
+
+ public synchronized String getName() {
+ return currentBucket.getName();
+ }
+
+ public synchronized long size() {
+ return currentBucket.size();
+ }
+
+ public synchronized boolean isReadOnly() {
+ return currentBucket.isReadOnly();
+ }
+
+ public synchronized void setReadOnly() {
+ currentBucket.setReadOnly();
+ }
+
+ public synchronized void free() {
+ currentBucket.free();
+ }
+
+ public Bucket createShadow() throws IOException {
+ return currentBucket.createShadow();
+ }
+
+ public void removeFrom(ObjectContainer container) {
+ currentBucket.removeFrom(container);
+ container.delete(this);
+ }
+
+ public void storeTo(ObjectContainer container) {
+ currentBucket.storeTo(container);
+ container.set(this);
+ }
+ }
+
private class RAMBucket extends ArrayBucket {
- private final long size;
-
public RAMBucket(long size) {
- super("RAMBucket");
- this.size = size;
+ super("RAMBucket", size);
+ _hasTaken(size);
}
@Override
public void free() {
super.free();
- _hasFreed(size);
+ _hasFreed(size());
}
}
@@ -45,8 +111,8 @@
public long maxRAMBucketSize;
public long maxRamUsed;
- final RandomSource strongPRNG;
- final Random weakPRNG;
+ private final RandomSource strongPRNG;
+ private final Random weakPRNG;
private volatile boolean reallyEncrypt;
// Storage accounting disabled by default.
@@ -67,7 +133,11 @@
return makeBucket(size, factor, defaultIncrement);
}
- protected synchronized void _hasFreed(long size) {
+ private synchronized void _hasTaken(long size) {
+ bytesInUse += size;
+ }
+
+ private synchronized void _hasFreed(long size) {
bytesInUse -= size;
}
@@ -111,19 +181,21 @@
* If it is not possible to create a temp bucket due to
an
* I/O error
*/
- public Bucket makeBucket(long size, float factor, long increment)
throws IOException {
+ public TempBucket makeBucket(long size, float factor, long increment)
throws IOException {
Bucket realBucket = null;
- boolean isARAMBucket = false;
+ boolean useRAMBucket = false;
synchronized(this) {
if((size > 0) && (size <= maxRAMBucketSize) &&
(bytesInUse <= maxRamUsed)) {
- bytesInUse += size;
- isARAMBucket = true;
+ useRAMBucket = true;
}
}
- realBucket = (isARAMBucket ? new RAMBucket(size) : new
TempFileBucket(filenameGenerator.makeRandomFilename(), filenameGenerator));
+ // Do we want a RAMBucket or a FileBucket?
+ realBucket = (useRAMBucket ? new RAMBucket(size) : new
TempFileBucket(filenameGenerator.makeRandomFilename(), filenameGenerator));
+ // Do we want it to be encrypted?
+ realBucket = (!reallyEncrypt ? realBucket : new
PaddedEphemerallyEncryptedBucket(realBucket, 1024, strongPRNG, weakPRNG));
- return (!reallyEncrypt ? realBucket : new
PaddedEphemerallyEncryptedBucket(realBucket, 1024, strongPRNG, weakPRNG));
+ return new TempBucket(realBucket);
}
}
Modified: branches/db4o/freenet/src/freenet/support/io/TooLongException.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/io/TooLongException.java
2008-09-24 20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/src/freenet/support/io/TooLongException.java
2008-09-24 22:16:49 UTC (rev 22824)
@@ -9,4 +9,7 @@
public class TooLongException extends IOException {
private static final long serialVersionUID = -1;
+ TooLongException(String s) {
+ super(s);
+ }
}
\ No newline at end of file
Modified:
branches/db4o/freenet/test/freenet/clients/http/filter/ContentFilterTest.java
===================================================================
---
branches/db4o/freenet/test/freenet/clients/http/filter/ContentFilterTest.java
2008-09-24 20:42:20 UTC (rev 22823)
+++
branches/db4o/freenet/test/freenet/clients/http/filter/ContentFilterTest.java
2008-09-24 22:16:49 UTC (rev 22824)
@@ -62,7 +62,8 @@
private String HTMLFilter(String data) throws Exception {
String typeName = "text/html";
URI baseURI = new URI(BASE_URI);
+ byte[] dataToFilter = data.getBytes("UTF-8");
- return ContentFilter.filter(new
ArrayBucket(data.getBytes("UTF-8")), bf, typeName, baseURI,
null).data.toString();
+ return ContentFilter.filter(new ArrayBucket(dataToFilter, -1),
bf, typeName, baseURI, null).data.toString();
}
}
Modified:
branches/db4o/freenet/test/freenet/support/compress/GzipCompressorTest.java
===================================================================
--- branches/db4o/freenet/test/freenet/support/compress/GzipCompressorTest.java
2008-09-24 20:42:20 UTC (rev 22823)
+++ branches/db4o/freenet/test/freenet/support/compress/GzipCompressorTest.java
2008-09-24 22:16:49 UTC (rev 22824)
@@ -111,7 +111,7 @@
public void testCompressException() {
byte[] uncompressedData = UNCOMPRESSED_DATA_1.getBytes();
- Bucket inBucket = new ArrayBucket(uncompressedData);
+ Bucket inBucket = new ArrayBucket(uncompressedData,
uncompressedData.length);
BucketFactory factory = new ArrayBucketFactory();
try {
@@ -133,7 +133,7 @@
byte[] compressedData = doCompress(uncompressedData);
- Bucket inBucket = new ArrayBucket(compressedData);
+ Bucket inBucket = new ArrayBucket(compressedData,
uncompressedData.length);
BucketFactory factory = new ArrayBucketFactory();
try {
@@ -147,7 +147,7 @@
private byte[] doBucketDecompress(byte[] compressedData) {
- Bucket inBucket = new ArrayBucket(compressedData);
+ Bucket inBucket = new ArrayBucket(compressedData,
compressedData.length);
BucketFactory factory = new ArrayBucketFactory();
Bucket outBucket = null;
@@ -179,7 +179,7 @@
}
private byte[] doCompress(byte[] uncompressedData) {
- Bucket inBucket = new ArrayBucket(uncompressedData);
+ Bucket inBucket = new ArrayBucket(uncompressedData,
uncompressedData.length);
BucketFactory factory = new ArrayBucketFactory();
Bucket outBucket = null;
Modified:
branches/db4o/freenet/test/freenet/support/io/LineReadingInputStreamTest.java
===================================================================
---
branches/db4o/freenet/test/freenet/support/io/LineReadingInputStreamTest.java
2008-09-24 20:42:20 UTC (rev 22823)
+++
branches/db4o/freenet/test/freenet/support/io/LineReadingInputStreamTest.java
2008-09-24 22:16:49 UTC (rev 22824)
@@ -21,6 +21,9 @@
};
public static final String STRESSED_LINE = "\n\u0114\n";
+ public static final String NULL_LINE = "a\u0000\u0000\u0000\u0000\n";
+ public static final String LENGTH_CHECKING_LINE = "a\u0000a\n";
+ public static final int LENGTH_CHECKING_LINE_LF = 3;
public static final int MAX_LENGTH = 128;
public static final int BUFFER_SIZE = 128;
@@ -42,17 +45,28 @@
assertNull(instance.readLineWithoutMarking(MAX_LENGTH,
BUFFER_SIZE, false));
// is it returning null?
- is = new NullInputStream();
+ is = new MockInputStream();
instance = new LineReadingInputStream(is);
assertNull(instance.readLineWithoutMarking(0, BUFFER_SIZE,
false));
+ assertNull(instance.readLineWithoutMarking(0, 0, false));
// is it throwing?
- is = new ByteArrayInputStream("aaa\na\n".getBytes());
+ is = new ByteArrayInputStream(LENGTH_CHECKING_LINE.getBytes());
instance = new LineReadingInputStream(is);
try {
- instance.readLineWithoutMarking(2, BUFFER_SIZE, true);
+ instance.readLineWithoutMarking(LENGTH_CHECKING_LINE_LF
- 1, BUFFER_SIZE, true);
fail();
} catch (TooLongException e) {}
+
+ // Same test shouldn't throw
+ is = new ByteArrayInputStream(LENGTH_CHECKING_LINE.getBytes());
+ instance = new LineReadingInputStream(is);
+ assertEquals(LENGTH_CHECKING_LINE.substring(0,
LENGTH_CHECKING_LINE_LF),
instance.readLineWithoutMarking(LENGTH_CHECKING_LINE_LF, BUFFER_SIZE, true));
+
+ // is it handling nulls properly? @see #2501
+ is = new ByteArrayInputStream(NULL_LINE.getBytes());
+ instance = new LineReadingInputStream(is);
+ assertEquals(NULL_LINE.substring(0, 5),
instance.readLineWithoutMarking(BUFFER_SIZE, 1, true));
}
public void testReadLine() throws Exception {
@@ -71,18 +85,29 @@
}
assertNull(instance.readLine(MAX_LENGTH, BUFFER_SIZE, false));
- // is it returning null?
- is = new NullInputStream();
+ // is it returning null? and blocking when it should be?
+ is = new MockInputStream();
instance = new LineReadingInputStream(is);
assertNull(instance.readLine(0, BUFFER_SIZE, false));
+ assertNull(instance.readLine(0, 0, false));
// is it throwing?
- is = new ByteArrayInputStream("aaa\na\n".getBytes());
+ is = new ByteArrayInputStream(LENGTH_CHECKING_LINE.getBytes());
instance = new LineReadingInputStream(is);
try {
- instance.readLine(2, BUFFER_SIZE, true);
+ instance.readLine(LENGTH_CHECKING_LINE_LF - 1,
BUFFER_SIZE, true);
fail();
} catch (TooLongException e) {}
+
+ // Same test shouldn't throw
+ is = new ByteArrayInputStream(LENGTH_CHECKING_LINE.getBytes());
+ instance = new LineReadingInputStream(is);
+ assertEquals(LENGTH_CHECKING_LINE.substring(0,
LENGTH_CHECKING_LINE_LF), instance.readLine(LENGTH_CHECKING_LINE_LF,
BUFFER_SIZE, true));
+
+ // is it handling nulls properly? @see #2501
+ is = new ByteArrayInputStream(NULL_LINE.getBytes());
+ instance = new LineReadingInputStream(is);
+ assertEquals(NULL_LINE.substring(0, 5),
instance.readLine(BUFFER_SIZE, 1, true));
}
public void testBothImplementation() throws Exception {
Copied: branches/db4o/freenet/test/freenet/support/io/MockInputStream.java
(from rev 22001, trunk/freenet/test/freenet/support/io/MockInputStream.java)
===================================================================
--- branches/db4o/freenet/test/freenet/support/io/MockInputStream.java
(rev 0)
+++ branches/db4o/freenet/test/freenet/support/io/MockInputStream.java
2008-09-24 22:16:49 UTC (rev 22824)
@@ -0,0 +1,20 @@
+/* This code is part of Freenet. It is distributed under the GNU General
+ * Public License, version 2 (or at your option any later version). See
+ * http://www.gnu.org/ for further details of the GPL. */
+package freenet.support.io;
+
+import java.io.InputStream;
+
+public class MockInputStream extends InputStream {
+
+ public MockInputStream() {
+ }
+
+ public int read() {
+ return -1;
+ }
+
+ public int read(byte[] data, int offset, int len) {
+ return len;
+ }
+}
\ No newline at end of file