propagate from branch 'i2p.i2p.zzz.test2' (head b6de226d1664089488ab2b438fe7457e9fb8e563)

to branch 'i2p.i2p' (head 0cf35c87b68a5360bd35257e36dfe7f740e53693)
This commit is contained in:
zzz
2015-04-17 13:18:22 +00:00
18 changed files with 775 additions and 371 deletions

View File

@ -75,7 +75,7 @@ public class JobQueue {
/** default max # job queue runners operating */
private final static int DEFAULT_MAX_RUNNERS = 1;
/** router.config parameter to override the max runners @deprecated unimplemented */
/** router.config parameter to override the max runners */
private final static String PROP_MAX_RUNNERS = "router.maxJobRunners";
/** how frequently should we check and update the max runners */
@ -330,7 +330,7 @@ public class JobQueue {
public void allowParallelOperation() {
_allowParallelOperation = true;
runQueue(RUNNERS);
runQueue(_context.getProperty(PROP_MAX_RUNNERS, RUNNERS));
}
/**

View File

@ -8,15 +8,10 @@ package net.i2p.router;
*
*/
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
@ -49,7 +44,6 @@ import net.i2p.router.util.EventLog;
import net.i2p.stat.RateStat;
import net.i2p.stat.StatManager;
import net.i2p.util.ByteCache;
import net.i2p.util.FileUtil;
import net.i2p.util.FortunaRandomSource;
import net.i2p.util.I2PAppThread;
import net.i2p.util.I2PThread;
@ -113,6 +107,7 @@ public class Router implements RouterClock.ClockShiftListener {
private final static String DNS_CACHE_TIME = "" + (5*60);
private static final String EVENTLOG = "eventlog.txt";
private static final String PROP_JBIGI = "jbigi.loadedResource";
public static final String UPDATE_FILE = "i2pupdate.zip";
private static final String originalTimeZoneID;
static {
@ -1497,199 +1492,11 @@ public class Router implements RouterClock.ClockShiftListener {
// If it does an update, it never returns.
// I guess it's better to have the other-router check above this, we don't want to
// overwrite an existing running router's jar files. Other than ours.
r.installUpdates();
InstallUpdate.installUpdates(r);
// ********* Start no threads before here ********* //
r.runRouter();
}
}
public static final String UPDATE_FILE = "i2pupdate.zip";
private static final String DELETE_FILE = "deletelist.txt";
/**
* Context must be available.
* Unzip update file found in the router dir OR base dir, to the base dir
*
* If successful, will call exit() and never return.
*
* If we can't write to the base dir, complain.
* Note: _log not available here.
*/
private void installUpdates() {
File updateFile = new File(_context.getRouterDir(), UPDATE_FILE);
boolean exists = updateFile.exists();
if (!exists) {
updateFile = new File(_context.getBaseDir(), UPDATE_FILE);
exists = updateFile.exists();
}
if (exists) {
// do a simple permissions test, if it fails leave the file in place and don't restart
File test = new File(_context.getBaseDir(), "history.txt");
if ((test.exists() && !test.canWrite()) || (!_context.getBaseDir().canWrite())) {
System.out.println("ERROR: No write permissions on " + _context.getBaseDir() +
" to extract software update file");
// carry on
return;
}
System.out.println("INFO: Update file exists [" + UPDATE_FILE + "] - installing");
// verify the whole thing first
// we could remember this fails, and not bother restarting, but who cares...
boolean ok = FileUtil.verifyZip(updateFile);
if (ok) {
// This may be useful someday. First added in 0.8.2
// Moved above the extract so we don't NCDFE
_config.put("router.updateLastInstalled", "" + System.currentTimeMillis());
// Set the last version to the current version, since 0.8.13
_config.put("router.previousVersion", RouterVersion.VERSION);
_config.put("router.previousFullVersion", RouterVersion.FULL_VERSION);
saveConfig();
ok = FileUtil.extractZip(updateFile, _context.getBaseDir());
}
// Very important - we have now trashed our jars.
// After this point, do not use any new I2P classes, or they will fail to load
// and we will die with NCDFE.
// Ideally, do not use I2P classes at all, new or not.
try {
if (ok) {
// We do this here so we may delete old jars before we restart
deleteListedFiles();
System.out.println("INFO: Update installed");
} else {
System.out.println("ERROR: Update failed!");
}
if (!ok) {
// we can't leave the file in place or we'll continually restart, so rename it
File bad = new File(_context.getRouterDir(), "BAD-" + UPDATE_FILE);
boolean renamed = updateFile.renameTo(bad);
if (renamed) {
System.out.println("Moved update file to " + bad.getAbsolutePath());
} else {
System.out.println("Deleting file " + updateFile.getAbsolutePath());
ok = true; // so it will be deleted
}
}
if (ok) {
boolean deleted = updateFile.delete();
if (!deleted) {
System.out.println("ERROR: Unable to delete the update file!");
updateFile.deleteOnExit();
}
}
// exit whether ok or not
if (_context.hasWrapper())
System.out.println("INFO: Restarting after update");
else
System.out.println("WARNING: Exiting after update, restart I2P");
} catch (Throwable t) {
// hide the NCDFE
// hopefully the update file got deleted or we will loop
}
System.exit(EXIT_HARD_RESTART);
} else {
deleteJbigiFiles();
// It was here starting in 0.8.12 so it could be used the very first time
// Now moved up so it is usually run only after an update
// But the first time before jetty 6 it will run here...
// Here we can't remove jars
deleteListedFiles();
}
}
/**
* Remove extracted libjbigi.so and libjcpuid.so files if we have a newer jbigi.jar,
* so the new ones will be extracted.
* We do this after the restart, not after the extract, because it's safer, and
* because people may upgrade their jbigi.jar file manually.
*
* Copied from NativeBigInteger, which we can't access here or the
* libs will get loaded.
*/
private void deleteJbigiFiles() {
boolean isX86 = SystemVersion.isX86();
String osName = System.getProperty("os.name").toLowerCase(Locale.US);
boolean isWin = SystemVersion.isWindows();
boolean isMac = SystemVersion.isMac();
// only do this on these OSes
boolean goodOS = isWin || isMac ||
osName.contains("linux") || osName.contains("freebsd");
// only do this on these x86
File jbigiJar = new File(_context.getBaseDir(), "lib/jbigi.jar");
if (isX86 && goodOS && jbigiJar.exists()) {
String libPrefix = (isWin ? "" : "lib");
String libSuffix = (isWin ? ".dll" : isMac ? ".jnilib" : ".so");
File jcpuidLib = new File(_context.getBaseDir(), libPrefix + "jcpuid" + libSuffix);
if (jcpuidLib.canWrite() && jbigiJar.lastModified() > jcpuidLib.lastModified()) {
String path = jcpuidLib.getAbsolutePath();
boolean success = FileUtil.copy(path, path + ".bak", true, true);
if (success) {
boolean success2 = jcpuidLib.delete();
if (success2) {
System.out.println("New jbigi.jar detected, moved jcpuid library to " +
path + ".bak");
System.out.println("Check logs for successful installation of new library");
}
}
}
File jbigiLib = new File(_context.getBaseDir(), libPrefix + "jbigi" + libSuffix);
if (jbigiLib.canWrite() && jbigiJar.lastModified() > jbigiLib.lastModified()) {
String path = jbigiLib.getAbsolutePath();
boolean success = FileUtil.copy(path, path + ".bak", true, true);
if (success) {
boolean success2 = jbigiLib.delete();
if (success2) {
System.out.println("New jbigi.jar detected, moved jbigi library to " +
path + ".bak");
System.out.println("Check logs for successful installation of new library");
}
}
}
}
}
/**
* Delete all files listed in the delete file.
* Format: One file name per line, comment lines start with '#'.
* All file names must be relative to $I2P, absolute file names not allowed.
* We probably can't remove old jars this way.
* Fails silently.
* Use no new I2P classes here so it may be called after zip extraction.
* @since 0.8.12
*/
private void deleteListedFiles() {
File deleteFile = new File(_context.getBaseDir(), DELETE_FILE);
if (!deleteFile.exists())
return;
// this is similar to FileUtil.readTextFile() but we can't use any I2P classes here
FileInputStream fis = null;
BufferedReader in = null;
try {
fis = new FileInputStream(deleteFile);
in = new BufferedReader(new InputStreamReader(fis, "UTF-8"));
String line;
while ( (line = in.readLine()) != null) {
String fl = line.trim();
if (fl.contains("..") || fl.startsWith("#") || fl.length() == 0)
continue;
File df = new File(fl);
if (df.isAbsolute())
continue;
df = new File(_context.getBaseDir(), fl);
if (df.exists() && !df.isDirectory()) {
if (df.delete())
System.out.println("INFO: File [" + fl + "] deleted");
}
}
} catch (IOException ioe) {}
finally {
if (in != null) try { in.close(); } catch(IOException ioe) {}
if (deleteFile.delete())
System.out.println("INFO: File [" + DELETE_FILE + "] deleted");
}
}
/*******
private static void verifyWrapperConfig() {

View File

@ -0,0 +1,215 @@
package net.i2p.router.tasks;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import net.i2p.router.Router;
import net.i2p.router.RouterContext;
import net.i2p.router.RouterVersion;
import net.i2p.util.FileUtil;
import net.i2p.util.SystemVersion;
/**
* If the i2pupdate.zip file is present,
* unzip it and JVM exit.
*
* @since 0.9.20 moved from Router.java
*/
public class InstallUpdate {
private static final String DELETE_FILE = "deletelist.txt";
/**
* Context must be available.
* Unzip update file found in the router dir OR base dir, to the base dir
*
* If successful, will call exit() and never return.
*
* If we can't write to the base dir, write message to System.out and return.
* Note: _log not available here.
*/
public static void installUpdates(Router r) {
RouterContext context = r.getContext();
File updateFile = new File(context.getRouterDir(), Router.UPDATE_FILE);
boolean exists = updateFile.exists();
if (!exists) {
updateFile = new File(context.getBaseDir(), Router.UPDATE_FILE);
exists = updateFile.exists();
}
if (exists) {
// do a simple permissions test, if it fails leave the file in place and don't restart
File test = new File(context.getBaseDir(), "history.txt");
if ((test.exists() && !test.canWrite()) || (!context.getBaseDir().canWrite())) {
System.out.println("ERROR: No write permissions on " + context.getBaseDir() +
" to extract software update file");
// carry on
return;
}
System.out.println("INFO: Update file exists [" + Router.UPDATE_FILE + "] - installing");
// verify the whole thing first
// we could remember this fails, and not bother restarting, but who cares...
boolean ok = FileUtil.verifyZip(updateFile);
if (ok) {
// This may be useful someday. First added in 0.8.2
// Moved above the extract so we don't NCDFE
Map<String, String> config = new HashMap<String, String>(4);
config.put("router.updateLastInstalled", "" + System.currentTimeMillis());
// Set the last version to the current version, since 0.8.13
config.put("router.previousVersion", RouterVersion.VERSION);
config.put("router.previousFullVersion", RouterVersion.FULL_VERSION);
r.saveConfig(config, null);
ok = FileUtil.extractZip(updateFile, context.getBaseDir());
}
// Very important - we have now trashed our jars.
// After this point, do not use any new I2P classes, or they will fail to load
// and we will die with NCDFE.
// Ideally, do not use I2P classes at all, new or not.
try {
if (ok) {
// We do this here so we may delete old jars before we restart
deleteListedFiles(context);
System.out.println("INFO: Update installed");
} else {
System.out.println("ERROR: Update failed!");
}
if (!ok) {
// we can't leave the file in place or we'll continually restart, so rename it
File bad = new File(context.getRouterDir(), "BAD-" + Router.UPDATE_FILE);
boolean renamed = updateFile.renameTo(bad);
if (renamed) {
System.out.println("Moved update file to " + bad.getAbsolutePath());
} else {
System.out.println("Deleting file " + updateFile.getAbsolutePath());
ok = true; // so it will be deleted
}
}
if (ok) {
boolean deleted = updateFile.delete();
if (!deleted) {
System.out.println("ERROR: Unable to delete the update file!");
updateFile.deleteOnExit();
}
}
// exit whether ok or not
if (context.hasWrapper())
System.out.println("INFO: Restarting after update");
else
System.out.println("WARNING: Exiting after update, restart I2P");
} catch (Throwable t) {
// hide the NCDFE
// hopefully the update file got deleted or we will loop
}
System.exit(Router.EXIT_HARD_RESTART);
} else {
deleteJbigiFiles(context);
// It was here starting in 0.8.12 so it could be used the very first time
// Now moved up so it is usually run only after an update
// But the first time before jetty 6 it will run here...
// Here we can't remove jars
deleteListedFiles(context);
}
}
/**
* Remove extracted libjbigi.so and libjcpuid.so files if we have a newer jbigi.jar,
* so the new ones will be extracted.
* We do this after the restart, not after the extract, because it's safer, and
* because people may upgrade their jbigi.jar file manually.
*
* Copied from NativeBigInteger, which we can't access here or the
* libs will get loaded.
*/
private static void deleteJbigiFiles(RouterContext context) {
boolean isX86 = SystemVersion.isX86();
String osName = System.getProperty("os.name").toLowerCase(Locale.US);
boolean isWin = SystemVersion.isWindows();
boolean isMac = SystemVersion.isMac();
// only do this on these OSes
boolean goodOS = isWin || isMac ||
osName.contains("linux") || osName.contains("freebsd");
// only do this on these x86
File jbigiJar = new File(context.getBaseDir(), "lib/jbigi.jar");
if (isX86 && goodOS && jbigiJar.exists()) {
String libPrefix = (isWin ? "" : "lib");
String libSuffix = (isWin ? ".dll" : isMac ? ".jnilib" : ".so");
File jcpuidLib = new File(context.getBaseDir(), libPrefix + "jcpuid" + libSuffix);
if (jcpuidLib.canWrite() && jbigiJar.lastModified() > jcpuidLib.lastModified()) {
String path = jcpuidLib.getAbsolutePath();
boolean success = FileUtil.copy(path, path + ".bak", true, true);
if (success) {
boolean success2 = jcpuidLib.delete();
if (success2) {
System.out.println("New jbigi.jar detected, moved jcpuid library to " +
path + ".bak");
System.out.println("Check logs for successful installation of new library");
}
}
}
File jbigiLib = new File(context.getBaseDir(), libPrefix + "jbigi" + libSuffix);
if (jbigiLib.canWrite() && jbigiJar.lastModified() > jbigiLib.lastModified()) {
String path = jbigiLib.getAbsolutePath();
boolean success = FileUtil.copy(path, path + ".bak", true, true);
if (success) {
boolean success2 = jbigiLib.delete();
if (success2) {
System.out.println("New jbigi.jar detected, moved jbigi library to " +
path + ".bak");
System.out.println("Check logs for successful installation of new library");
}
}
}
}
}
/**
* Delete all files listed in the delete file.
* Format: One file name per line, comment lines start with '#'.
* All file names must be relative to $I2P, absolute file names not allowed.
* We probably can't remove old jars this way.
* Fails silently.
* Use no new I2P classes here so it may be called after zip extraction.
* @since 0.8.12
*/
private static void deleteListedFiles(RouterContext context) {
File deleteFile = new File(context.getBaseDir(), DELETE_FILE);
if (!deleteFile.exists())
return;
// this is similar to FileUtil.readTextFile() but we can't use any I2P classes here
FileInputStream fis = null;
BufferedReader in = null;
try {
fis = new FileInputStream(deleteFile);
in = new BufferedReader(new InputStreamReader(fis, "UTF-8"));
String line;
while ( (line = in.readLine()) != null) {
String fl = line.trim();
if (fl.contains("..") || fl.startsWith("#") || fl.length() == 0)
continue;
File df = new File(fl);
if (df.isAbsolute())
continue;
df = new File(context.getBaseDir(), fl);
if (df.exists() && !df.isDirectory()) {
if (df.delete())
System.out.println("INFO: File [" + fl + "] deleted");
}
}
} catch (IOException ioe) {}
finally {
if (in != null) try { in.close(); } catch(IOException ioe) {}
if (deleteFile.delete())
System.out.println("INFO: File [" + DELETE_FILE + "] deleted");
}
}
}

View File

@ -4,6 +4,7 @@
Miscellaneous classes, mostly things that are executed periodically as
Jobs, Threads, and SimpleTimer.TimedEvents.
These are used only by Router.java.
Nothing here is to be used externally, not a part of the public API.
</p>
</body>
</html>

View File

@ -70,8 +70,12 @@ public class FIFOBandwidthRefiller implements Runnable {
public static final int MIN_INBOUND_BANDWIDTH_PEAK = 3;
/** For now, until there is some tuning and safe throttling, we set the floor at a 3KBps during burst */
public static final int MIN_OUTBOUND_BANDWIDTH_PEAK = 3;
/** Max for reasonable bloom filter false positive rate. See util/DecayingBloomFilter and tunnel/BloomFilterIVValidator */
public static final int MAX_OUTBOUND_BANDWIDTH = 4096;
/**
* Max for reasonable Bloom filter false positive rate.
* Do not increase without adding a new Bloom filter size!
* See util/DecayingBloomFilter and tunnel/BloomFilterIVValidator.
*/
public static final int MAX_OUTBOUND_BANDWIDTH = 8192;
/**
* how often we replenish the queues.

View File

@ -1,9 +1,12 @@
package net.i2p.router.tunnel;
import java.io.File;
import net.i2p.data.DataHelper;
import net.i2p.router.RouterContext;
import net.i2p.router.util.DecayingBloomFilter;
import net.i2p.router.util.DecayingHashSet;
import net.i2p.util.Log;
import net.i2p.util.SimpleByteCache;
import net.i2p.util.SystemVersion;
@ -26,12 +29,19 @@ class BloomFilterIVValidator implements IVValidator {
private static final int MIN_SHARE_KBPS_TO_USE_BLOOM = 64;
private static final int MIN_SHARE_KBPS_FOR_BIG_BLOOM = 512;
private static final int MIN_SHARE_KBPS_FOR_HUGE_BLOOM = 1536;
private static final int MIN_SHARE_KBPS_FOR_HUGE2_BLOOM = 4096;
private static final long MIN_MEM_TO_USE_BLOOM = 64*1024*1024l;
private static final long MIN_MEM_FOR_BIG_BLOOM = 128*1024*1024l;
private static final long MIN_MEM_FOR_HUGE_BLOOM = 256*1024*1024l;
private static final long MIN_MEM_FOR_HUGE2_BLOOM = 384*1024*1024l;
/** for testing */
private static final String PROP_FORCE = "router.forceDecayingBloomFilter";
/** for testing */
private static final String PROP_DISABLE = "router.disableDecayingBloomFilter";
/**
* @param Kbps share bandwidth
*/
public BloomFilterIVValidator(RouterContext ctx, int KBps) {
_context = ctx;
// Select the filter based on share bandwidth and memory.
@ -39,21 +49,36 @@ class BloomFilterIVValidator implements IVValidator {
// to keep acceptable false positive rates.
// See DBF, BloomSHA1, and KeySelector for details.
long maxMemory = SystemVersion.getMaxMemory();
if (_context.getBooleanProperty(PROP_FORCE))
if (_context.getBooleanProperty(PROP_FORCE)) {
_filter = new DecayingBloomFilter(ctx, HALFLIFE_MS, 16, "TunnelIVV"); // 2MB fixed
else if (KBps < MIN_SHARE_KBPS_TO_USE_BLOOM || maxMemory < MIN_MEM_TO_USE_BLOOM)
} else if (_context.getBooleanProperty(PROP_DISABLE)) {
_filter = null;
} else if (KBps < MIN_SHARE_KBPS_TO_USE_BLOOM || maxMemory < MIN_MEM_TO_USE_BLOOM) {
if (KBps >= MIN_SHARE_KBPS_TO_USE_BLOOM)
warn(maxMemory, KBps, MIN_MEM_TO_USE_BLOOM, MIN_SHARE_KBPS_TO_USE_BLOOM);
_filter = new DecayingHashSet(ctx, HALFLIFE_MS, 16, "TunnelIVV"); // appx. 4MB max
else if (KBps >= MIN_SHARE_KBPS_FOR_HUGE_BLOOM && maxMemory >= MIN_MEM_FOR_HUGE_BLOOM)
} else if (KBps >= MIN_SHARE_KBPS_FOR_HUGE2_BLOOM && maxMemory >= MIN_MEM_FOR_HUGE2_BLOOM) {
_filter = new DecayingBloomFilter(ctx, HALFLIFE_MS, 16, "TunnelIVV", 26); // 16MB fixed
} else if (KBps >= MIN_SHARE_KBPS_FOR_HUGE_BLOOM && maxMemory >= MIN_MEM_FOR_HUGE_BLOOM) {
if (KBps >= MIN_SHARE_KBPS_FOR_HUGE2_BLOOM)
warn(maxMemory, KBps, MIN_MEM_FOR_HUGE2_BLOOM, MIN_SHARE_KBPS_FOR_HUGE2_BLOOM);
_filter = new DecayingBloomFilter(ctx, HALFLIFE_MS, 16, "TunnelIVV", 25); // 8MB fixed
else if (KBps >= MIN_SHARE_KBPS_FOR_BIG_BLOOM && maxMemory >= MIN_MEM_FOR_BIG_BLOOM)
} else if (KBps >= MIN_SHARE_KBPS_FOR_BIG_BLOOM && maxMemory >= MIN_MEM_FOR_BIG_BLOOM) {
if (KBps >= MIN_SHARE_KBPS_FOR_HUGE_BLOOM)
warn(maxMemory, KBps, MIN_MEM_FOR_HUGE_BLOOM, MIN_SHARE_KBPS_FOR_HUGE_BLOOM);
_filter = new DecayingBloomFilter(ctx, HALFLIFE_MS, 16, "TunnelIVV", 24); // 4MB fixed
else
} else {
if (KBps >= MIN_SHARE_KBPS_FOR_BIG_BLOOM)
warn(maxMemory, KBps, MIN_MEM_FOR_BIG_BLOOM, MIN_SHARE_KBPS_FOR_BIG_BLOOM);
_filter = new DecayingBloomFilter(ctx, HALFLIFE_MS, 16, "TunnelIVV"); // 2MB fixed
}
ctx.statManager().createRateStat("tunnel.duplicateIV", "Note that a duplicate IV was received", "Tunnels",
new long[] { 60*60*1000l });
}
public boolean receiveIV(byte ivData[], int ivOffset, byte payload[], int payloadOffset) {
if (_filter == null) // testing only
return true;
byte[] buf = SimpleByteCache.acquire(HopProcessor.IV_LENGTH);
DataHelper.xor(ivData, ivOffset, payload, payloadOffset, buf, 0, HopProcessor.IV_LENGTH);
boolean dup = _filter.add(buf);
@ -62,5 +87,26 @@ class BloomFilterIVValidator implements IVValidator {
return !dup; // return true if it is OK, false if it isn't
}
public void destroy() { _filter.stopDecaying(); }
public void destroy() {
if (_filter != null)
_filter.stopDecaying();
}
/** @since 0.9.20 */
private void warn(long maxMemory, int KBps, long recMaxMem, int threshKBps) {
if (SystemVersion.isAndroid())
return;
String msg =
"Configured for " + DataHelper.formatSize(KBps *1024) +
"Bps share bandwidth but only " +
DataHelper.formatSize(maxMemory) + "B available memory." +
" Recommend increasing wrapper.java.maxmemory in " +
_context.getBaseDir() + File.separatorChar + "wrapper.config" +
// getMaxMemory() returns significantly lower than wrapper config, so add 10%
" to at least " + (recMaxMem * 11 / 10 / (1024*1024)) + " (MB)" +
" if the actual share bandwidth exceeds " +
DataHelper.formatSize(threshKBps * 1024) + "Bps.";
System.out.println("WARN: " + msg);
_context.logManager().getLog(BloomFilterIVValidator.class).logAlways(Log.WARN, msg);
}
}

View File

@ -372,6 +372,9 @@ public class DecayingBloomFilter {
*
* Following stats for m=25, k=10:
* 1792 2.4E-6; 4096 0.14%; 5120 0.6%; 6144 1.7%; 8192 6.8%; 10240 15%
*
* Following stats for m=26, k=10:
* 4096 7.3E-6; 5120 4.5E-5; 6144 1.8E-4; 8192 0.14%; 10240 0.6%, 12288 1.7%
*</pre>
*/
/*****
@ -400,16 +403,23 @@ public class DecayingBloomFilter {
}
private static void testByLong(int kbps, int m, int numRuns) {
System.out.println("Starting 8 byte test");
int messages = 60 * 10 * kbps;
Random r = new Random();
java.util.Random r = new java.util.Random();
DecayingBloomFilter filter = new DecayingBloomFilter(I2PAppContext.getGlobalContext(), 600*1000, 8, "test", m);
int falsePositives = 0;
long totalTime = 0;
double fpr = 0d;
for (int j = 0; j < numRuns; j++) {
// screen out birthday paradoxes (waste of time and space?)
java.util.Set<Long> longs = new java.util.HashSet<Long>(messages);
long start = System.currentTimeMillis();
for (int i = 0; i < messages; i++) {
if (filter.add(r.nextLong())) {
long rand;
do {
rand = r.nextLong();
} while (!longs.add(Long.valueOf(rand)));
if (filter.add(rand)) {
falsePositives++;
//System.out.println("False positive " + falsePositives + " (testByLong j=" + j + " i=" + i + ")");
}
@ -422,13 +432,14 @@ public class DecayingBloomFilter {
System.out.println("False postive rate should be " + fpr);
System.out.println("After " + numRuns + " runs pushing " + messages + " entries in "
+ DataHelper.formatDuration(totalTime/numRuns) + " per run, there were "
+ falsePositives + " false positives");
+ falsePositives + " false positives (" +
(((double) falsePositives) / messages) + ')');
}
private static void testByBytes(int kbps, int m, int numRuns) {
System.out.println("Starting 16 byte test");
byte iv[][] = new byte[60*10*kbps][16];
Random r = new Random();
java.util.Random r = new java.util.Random();
for (int i = 0; i < iv.length; i++)
r.nextBytes(iv[i]);
@ -452,7 +463,8 @@ public class DecayingBloomFilter {
System.out.println("False postive rate should be " + fpr);
System.out.println("After " + numRuns + " runs pushing " + iv.length + " entries in "
+ DataHelper.formatDuration(totalTime/numRuns) + " per run, there were "
+ falsePositives + " false positives");
+ falsePositives + " false positives (" +
(((double) falsePositives) / iv.length) + ')');
//System.out.println("inserted: " + bloom.size() + " with " + bloom.capacity()
// + " (" + bloom.falsePositives()*100.0d + "% false positive)");
}