diff --git a/core/java/src/net/i2p/crypto/CryptixAESKeyCache.java b/core/java/src/net/i2p/crypto/CryptixAESKeyCache.java index 5084ae2b0..5d39c1578 100644 --- a/core/java/src/net/i2p/crypto/CryptixAESKeyCache.java +++ b/core/java/src/net/i2p/crypto/CryptixAESKeyCache.java @@ -1,7 +1,6 @@ package net.i2p.crypto; -import java.util.ArrayList; -import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; /** * Cache the objects used in CryptixRijndael_Algorithm.makeKey to reduce @@ -11,7 +10,7 @@ import java.util.List; * */ public final class CryptixAESKeyCache { - private final List _availableKeys; + private final LinkedBlockingQueue _availableKeys; private static final int KEYSIZE = 32; // 256bit AES private static final int BLOCKSIZE = 16; @@ -22,7 +21,7 @@ public final class CryptixAESKeyCache { private static final int MAX_KEYS = 64; public CryptixAESKeyCache() { - _availableKeys = new ArrayList(MAX_KEYS); + _availableKeys = new LinkedBlockingQueue(MAX_KEYS); } /** @@ -30,10 +29,9 @@ public final class CryptixAESKeyCache { * */ public final KeyCacheEntry acquireKey() { - synchronized (_availableKeys) { - if (!_availableKeys.isEmpty()) - return (KeyCacheEntry)_availableKeys.remove(0); - } + KeyCacheEntry rv = _availableKeys.poll(); + if (rv != null) + return rv; return createNew(); } @@ -42,10 +40,7 @@ public final class CryptixAESKeyCache { * */ public final void releaseKey(KeyCacheEntry key) { - synchronized (_availableKeys) { - if (_availableKeys.size() < MAX_KEYS) - _availableKeys.add(key); - } + _availableKeys.offer(key); } public static final KeyCacheEntry createNew() { diff --git a/core/java/src/net/i2p/crypto/DHSessionKeyBuilder.java b/core/java/src/net/i2p/crypto/DHSessionKeyBuilder.java index 2c1e57d8e..b438f2b47 100644 --- a/core/java/src/net/i2p/crypto/DHSessionKeyBuilder.java +++ b/core/java/src/net/i2p/crypto/DHSessionKeyBuilder.java @@ -65,35 +65,17 @@ public class DHSessionKeyBuilder { public final static String PROP_DH_PRECALC_MIN = "crypto.dh.precalc.min"; public final static String PROP_DH_PRECALC_MAX = "crypto.dh.precalc.max"; public final static String PROP_DH_PRECALC_DELAY = "crypto.dh.precalc.delay"; - public final static String DEFAULT_DH_PRECALC_MIN = "5"; - public final static String DEFAULT_DH_PRECALC_MAX = "50"; - public final static String DEFAULT_DH_PRECALC_DELAY = "10000"; + public final static int DEFAULT_DH_PRECALC_MIN = 5; + public final static int DEFAULT_DH_PRECALC_MAX = 50; + public final static int DEFAULT_DH_PRECALC_DELAY = 10000; static { I2PAppContext ctx = _context; ctx.statManager().createRateStat("crypto.dhGeneratePublicTime", "How long it takes to create x and X", "Encryption", new long[] { 60*1000, 5*60*1000, 60*60*1000 }); ctx.statManager().createRateStat("crypto.dhCalculateSessionTime", "How long it takes to create the session key", "Encryption", new long[] { 60*1000, 5*60*1000, 60*60*1000 }); - try { - int val = Integer.parseInt(ctx.getProperty(PROP_DH_PRECALC_MIN, DEFAULT_DH_PRECALC_MIN)); - MIN_NUM_BUILDERS = val; - } catch (Throwable t) { - int val = Integer.parseInt(DEFAULT_DH_PRECALC_MIN); - MIN_NUM_BUILDERS = val; - } - try { - int val = Integer.parseInt(ctx.getProperty(PROP_DH_PRECALC_MAX, DEFAULT_DH_PRECALC_MAX)); - MAX_NUM_BUILDERS = val; - } catch (Throwable t) { - int val = Integer.parseInt(DEFAULT_DH_PRECALC_MAX); - MAX_NUM_BUILDERS = val; - } - try { - int val = Integer.parseInt(ctx.getProperty(PROP_DH_PRECALC_DELAY, DEFAULT_DH_PRECALC_DELAY)); - CALC_DELAY = val; - } catch (Throwable t) { - int val = Integer.parseInt(DEFAULT_DH_PRECALC_DELAY); - CALC_DELAY = val; - } + MIN_NUM_BUILDERS = ctx.getProperty(PROP_DH_PRECALC_MIN, DEFAULT_DH_PRECALC_MIN); + MAX_NUM_BUILDERS = ctx.getProperty(PROP_DH_PRECALC_MAX, DEFAULT_DH_PRECALC_MAX); + CALC_DELAY = ctx.getProperty(PROP_DH_PRECALC_DELAY, DEFAULT_DH_PRECALC_DELAY); if (_log.shouldLog(Log.DEBUG)) _log.debug("DH Precalc (minimum: " + MIN_NUM_BUILDERS + " max: " + MAX_NUM_BUILDERS + ", delay: " diff --git a/core/java/src/net/i2p/crypto/DSAEngine.java b/core/java/src/net/i2p/crypto/DSAEngine.java index b083cc248..941774253 100644 --- a/core/java/src/net/i2p/crypto/DSAEngine.java +++ b/core/java/src/net/i2p/crypto/DSAEngine.java @@ -41,6 +41,10 @@ import net.i2p.data.SigningPublicKey; import net.i2p.util.Log; import net.i2p.util.NativeBigInteger; +/** + * Params and rv's changed from Hash to SHA1Hash for version 0.8.1 + * There shouldn't be any external users of those variants. + */ public class DSAEngine { private Log _log; private I2PAppContext _context; @@ -61,7 +65,9 @@ public class DSAEngine { public boolean verifySignature(Signature signature, InputStream in, SigningPublicKey verifyingKey) { return verifySignature(signature, calculateHash(in), verifyingKey); } - public boolean verifySignature(Signature signature, Hash hash, SigningPublicKey verifyingKey) { + + /** @param hash SHA-1 hash, NOT a SHA-256 hash */ + public boolean verifySignature(Signature signature, SHA1Hash hash, SigningPublicKey verifyingKey) { long start = _context.clock().now(); try { @@ -111,17 +117,18 @@ public class DSAEngine { } public Signature sign(byte data[], int offset, int length, SigningPrivateKey signingKey) { if ((signingKey == null) || (data == null) || (data.length <= 0)) return null; - Hash h = calculateHash(data, offset, length); + SHA1Hash h = calculateHash(data, offset, length); return sign(h, signingKey); } public Signature sign(InputStream in, SigningPrivateKey signingKey) { if ((signingKey == null) || (in == null) ) return null; - Hash h = calculateHash(in); + SHA1Hash h = calculateHash(in); return sign(h, signingKey); } - public Signature sign(Hash hash, SigningPrivateKey signingKey) { + /** @param hash SHA-1 hash, NOT a SHA-256 hash */ + public Signature sign(SHA1Hash hash, SigningPrivateKey signingKey) { if ((signingKey == null) || (hash == null)) return null; long start = _context.clock().now(); @@ -186,7 +193,8 @@ public class DSAEngine { return sig; } - public Hash calculateHash(InputStream in) { + /** @return hash SHA-1 hash, NOT a SHA-256 hash */ + public SHA1Hash calculateHash(InputStream in) { SHA1 digest = new SHA1(); byte buf[] = new byte[64]; int read = 0; @@ -199,14 +207,15 @@ public class DSAEngine { _log.warn("Unable to hash the stream", ioe); return null; } - return new Hash(digest.engineDigest()); + return new SHA1Hash(digest.engineDigest()); } - public static Hash calculateHash(byte[] source, int offset, int len) { + /** @return hash SHA-1 hash, NOT a SHA-256 hash */ + public static SHA1Hash calculateHash(byte[] source, int offset, int len) { SHA1 h = new SHA1(); h.engineUpdate(source, offset, len); byte digested[] = h.digest(); - return new Hash(digested); + return new SHA1Hash(digested); } public static void main(String args[]) { diff --git a/core/java/src/net/i2p/crypto/HMAC256Generator.java b/core/java/src/net/i2p/crypto/HMAC256Generator.java index bf0532109..3fc554639 100644 --- a/core/java/src/net/i2p/crypto/HMAC256Generator.java +++ b/core/java/src/net/i2p/crypto/HMAC256Generator.java @@ -15,16 +15,16 @@ import org.bouncycastle.crypto.macs.I2PHMac; * in {@link org.bouncycastle.crypto.macs.I2PHMac} and * {@link org.bouncycastle.crypto.digests.MD5Digest}. * + * deprecated unused */ public class HMAC256Generator extends HMACGenerator { public HMAC256Generator(I2PAppContext context) { super(context); } @Override protected I2PHMac acquire() { - synchronized (_available) { - if (!_available.isEmpty()) - return (I2PHMac)_available.remove(0); - } + I2PHMac rv = _available.poll(); + if (rv != null) + return rv; // the HMAC is hardcoded to use SHA256 digest size // for backwards compatability. next time we have a backwards // incompatible change, we should update this by removing ", 32" @@ -43,6 +43,7 @@ public class HMAC256Generator extends HMACGenerator { } +/****** public static void main(String args[]) { I2PAppContext ctx = I2PAppContext.getGlobalContext(); byte data[] = new byte[64]; @@ -51,4 +52,5 @@ public class HMAC256Generator extends HMACGenerator { Hash mac = ctx.hmac256().calculate(key, data); System.out.println(Base64.encode(mac.getData())); } +******/ } diff --git a/core/java/src/net/i2p/crypto/HMACGenerator.java b/core/java/src/net/i2p/crypto/HMACGenerator.java index aed444ed0..237c65055 100644 --- a/core/java/src/net/i2p/crypto/HMACGenerator.java +++ b/core/java/src/net/i2p/crypto/HMACGenerator.java @@ -1,8 +1,7 @@ package net.i2p.crypto; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; import net.i2p.I2PAppContext; import net.i2p.data.DataHelper; @@ -22,14 +21,14 @@ import org.bouncycastle.crypto.macs.I2PHMac; public class HMACGenerator { private I2PAppContext _context; /** set of available HMAC instances for calculate */ - protected final List _available; + protected final LinkedBlockingQueue _available; /** set of available byte[] buffers for verify */ - private final List _availableTmp; + private final LinkedBlockingQueue _availableTmp; public HMACGenerator(I2PAppContext context) { _context = context; - _available = new ArrayList(32); - _availableTmp = new ArrayList(32); + _available = new LinkedBlockingQueue(32); + _availableTmp = new LinkedBlockingQueue(32); } /** @@ -88,39 +87,30 @@ public class HMACGenerator { } protected I2PHMac acquire() { - synchronized (_available) { - if (!_available.isEmpty()) - return (I2PHMac)_available.remove(0); - } + I2PHMac rv = _available.poll(); + if (rv != null) + return rv; // the HMAC is hardcoded to use SHA256 digest size // for backwards compatability. next time we have a backwards // incompatible change, we should update this by removing ", 32" return new I2PHMac(new MD5Digest(), 32); } - private void release(Mac mac) { - synchronized (_available) { - if (_available.size() < 64) - _available.add(mac); - } + + private void release(I2PHMac mac) { + _available.offer(mac); } // temp buffers for verify(..) private byte[] acquireTmp() { - byte rv[] = null; - synchronized (_availableTmp) { - if (!_availableTmp.isEmpty()) - rv = (byte[])_availableTmp.remove(0); - } + byte rv[] = _availableTmp.poll(); if (rv != null) Arrays.fill(rv, (byte)0x0); else rv = new byte[Hash.HASH_LENGTH]; return rv; } + private void releaseTmp(byte tmp[]) { - synchronized (_availableTmp) { - if (_availableTmp.size() < 64) - _availableTmp.add((Object)tmp); - } + _availableTmp.offer(tmp); } } diff --git a/core/java/src/net/i2p/crypto/SHA1.java b/core/java/src/net/i2p/crypto/SHA1.java index d8a0ac1c2..6dbdee074 100644 --- a/core/java/src/net/i2p/crypto/SHA1.java +++ b/core/java/src/net/i2p/crypto/SHA1.java @@ -63,7 +63,7 @@ public final class SHA1 extends MessageDigest implements Cloneable { /** * This implementation returns a fixed-size digest. */ - private static final int HASH_LENGTH = 20; // bytes == 160 bits + static final int HASH_LENGTH = 20; // bytes == 160 bits /** * Private context for incomplete blocks and padding bytes. diff --git a/core/java/src/net/i2p/crypto/SHA1Hash.java b/core/java/src/net/i2p/crypto/SHA1Hash.java new file mode 100644 index 000000000..acbb68d4b --- /dev/null +++ b/core/java/src/net/i2p/crypto/SHA1Hash.java @@ -0,0 +1,81 @@ +package net.i2p.crypto; + +/* + * free (adj.): unencumbered; not under the control of others + * Written by jrandom in 2003 and released into the public domain + * with no warranty of any kind, either expressed or implied. + * It probably won't make your computer catch on fire, or eat + * your children, but it might. Use at your own risk. + * + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import net.i2p.data.DataFormatException; +import net.i2p.data.DataHelper; +import net.i2p.data.DataStructureImpl; + +/** + * Because DSAEngine was abusing Hash for 20-byte hashes + * + * @since 0.8.1 + * @author zzz + */ +public class SHA1Hash extends DataStructureImpl { + private byte[] _data; + private int _cachedHashCode; + + public final static int HASH_LENGTH = SHA1.HASH_LENGTH; + + /** @throws IllegalArgumentException if data is not 20 bytes (null is ok) */ + public SHA1Hash(byte data[]) { + setData(data); + } + + public byte[] getData() { + return _data; + } + + /** @throws IllegalArgumentException if data is not 20 bytes (null is ok) */ + public void setData(byte[] data) { + // FIXME DSAEngine uses a SHA-1 "Hash" as parameters and return values! + if (data != null && data.length != HASH_LENGTH) + throw new IllegalArgumentException("Hash must be 20 bytes"); + _data = data; + _cachedHashCode = calcHashCode(); + } + + /** @throws IOException always */ + public void readBytes(InputStream in) throws DataFormatException, IOException { + throw new IOException("unimplemented"); + } + + /** @throws IOException always */ + public void writeBytes(OutputStream out) throws DataFormatException, IOException { + throw new IOException("unimplemented"); + } + + @Override + public boolean equals(Object obj) { + if ((obj == null) || !(obj instanceof SHA1Hash)) return false; + return DataHelper.eq(_data, ((SHA1Hash) obj)._data); + } + + /** a Hash is a hash, so just use the first 4 bytes for speed */ + @Override + public int hashCode() { + return _cachedHashCode; + } + + /** a Hash is a hash, so just use the first 4 bytes for speed */ + private int calcHashCode() { + int rv = 0; + if (_data != null) { + for (int i = 0; i < 4; i++) + rv ^= (_data[i] << (i*8)); + } + return rv; + } +} diff --git a/core/java/src/net/i2p/crypto/YKGenerator.java b/core/java/src/net/i2p/crypto/YKGenerator.java index ad68ebec1..af83f2c92 100644 --- a/core/java/src/net/i2p/crypto/YKGenerator.java +++ b/core/java/src/net/i2p/crypto/YKGenerator.java @@ -10,24 +10,22 @@ package net.i2p.crypto; */ import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; import net.i2p.I2PAppContext; import net.i2p.util.Clock; import net.i2p.util.I2PThread; import net.i2p.util.Log; import net.i2p.util.NativeBigInteger; -import net.i2p.util.RandomSource; /** * Precalculate the Y and K for ElGamal encryption operations. * * This class precalcs a set of values on its own thread, using those transparently * when a new instance is created. By default, the minimum threshold for creating - * new values for the pool is 5, and the max pool size is 10. Whenever the pool has + * new values for the pool is 20, and the max pool size is 50. Whenever the pool has * less than the minimum, it fills it up again to the max. There is a delay after - * each precalculation so that the CPU isn't hosed during startup (defaulting to 10 seconds). + * each precalculation so that the CPU isn't hosed during startup. * These three parameters are controlled by java environmental variables and * can be adjusted via: * -Dcrypto.yk.precalc.min=40 -Dcrypto.yk.precalc.max=100 -Dcrypto.yk.precalc.delay=60000 @@ -39,51 +37,36 @@ import net.i2p.util.RandomSource; * @author jrandom */ class YKGenerator { - private final static Log _log = new Log(YKGenerator.class); - private static int MIN_NUM_BUILDERS = -1; - private static int MAX_NUM_BUILDERS = -1; - private static int CALC_DELAY = -1; - /* FIXME final type if you are to syncronize FIXME */ - private static volatile List _values = new ArrayList(50); // list of BigInteger[] values (y and k) - private static Thread _precalcThread = null; + //private final static Log _log = new Log(YKGenerator.class); + private static final int MIN_NUM_BUILDERS; + private static final int MAX_NUM_BUILDERS; + private static final int CALC_DELAY; + private static final LinkedBlockingQueue _values = new LinkedBlockingQueue(50); // list of BigInteger[] values (y and k) + private static final Thread _precalcThread; + private static final I2PAppContext ctx; public final static String PROP_YK_PRECALC_MIN = "crypto.yk.precalc.min"; public final static String PROP_YK_PRECALC_MAX = "crypto.yk.precalc.max"; public final static String PROP_YK_PRECALC_DELAY = "crypto.yk.precalc.delay"; - public final static String DEFAULT_YK_PRECALC_MIN = "10"; - public final static String DEFAULT_YK_PRECALC_MAX = "30"; - public final static String DEFAULT_YK_PRECALC_DELAY = "10000"; + public final static int DEFAULT_YK_PRECALC_MIN = 20; + public final static int DEFAULT_YK_PRECALC_MAX = 50; + public final static int DEFAULT_YK_PRECALC_DELAY = 200; /** check every 30 seconds whether we have less than the minimum */ - private final static long CHECK_DELAY = 30 * 1000; + private static long CHECK_DELAY = 30 * 1000; static { - I2PAppContext ctx = I2PAppContext.getGlobalContext(); - try { - int val = Integer.parseInt(ctx.getProperty(PROP_YK_PRECALC_MIN, DEFAULT_YK_PRECALC_MIN)); - MIN_NUM_BUILDERS = val; - } catch (Throwable t) { - int val = Integer.parseInt(DEFAULT_YK_PRECALC_MIN); - MIN_NUM_BUILDERS = val; - } - try { - int val = Integer.parseInt(ctx.getProperty(PROP_YK_PRECALC_MAX, DEFAULT_YK_PRECALC_MAX)); - MAX_NUM_BUILDERS = val; - } catch (Throwable t) { - int val = Integer.parseInt(DEFAULT_YK_PRECALC_MAX); - MAX_NUM_BUILDERS = val; - } - try { - int val = Integer.parseInt(ctx.getProperty(PROP_YK_PRECALC_DELAY, DEFAULT_YK_PRECALC_DELAY)); - CALC_DELAY = val; - } catch (Throwable t) { - int val = Integer.parseInt(DEFAULT_YK_PRECALC_DELAY); - CALC_DELAY = val; - } + ctx = I2PAppContext.getGlobalContext(); + MIN_NUM_BUILDERS = ctx.getProperty(PROP_YK_PRECALC_MIN, DEFAULT_YK_PRECALC_MIN); + MAX_NUM_BUILDERS = ctx.getProperty(PROP_YK_PRECALC_MAX, DEFAULT_YK_PRECALC_MAX); + CALC_DELAY = ctx.getProperty(PROP_YK_PRECALC_DELAY, DEFAULT_YK_PRECALC_DELAY); - if (_log.shouldLog(Log.DEBUG)) - _log.debug("ElGamal YK Precalc (minimum: " + MIN_NUM_BUILDERS + " max: " + MAX_NUM_BUILDERS + ", delay: " - + CALC_DELAY + ")"); + //if (_log.shouldLog(Log.DEBUG)) + // _log.debug("ElGamal YK Precalc (minimum: " + MIN_NUM_BUILDERS + " max: " + MAX_NUM_BUILDERS + ", delay: " + // + CALC_DELAY + ")"); + + ctx.statManager().createRateStat("crypto.YKUsed", "Need a YK from the queue", "Encryption", new long[] { 60*60*1000 }); + ctx.statManager().createRateStat("crypto.YKEmpty", "YK queue empty", "Encryption", new long[] { 60*60*1000 }); _precalcThread = new I2PThread(new YKPrecalcRunner(MIN_NUM_BUILDERS, MAX_NUM_BUILDERS)); _precalcThread.setName("YK Precalc"); @@ -93,45 +76,36 @@ class YKGenerator { } private static final int getSize() { - synchronized (_values) { - return _values.size(); - } + return _values.size(); } - private static final int addValues(BigInteger yk[]) { - int sz = 0; - synchronized (_values) { - _values.add(yk); - sz = _values.size(); - } - return sz; + /** @return true if successful, false if full */ + private static final boolean addValues(BigInteger yk[]) { + return _values.offer(yk); } + /** @return rv[0] = Y; rv[1] = K */ public static BigInteger[] getNextYK() { - if (true) { - synchronized (_values) { - if (!_values.isEmpty()) { - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Sufficient precalculated YK values - fetch the existing"); - return (BigInteger[]) _values.remove(0); - } - } - } - if (_log.shouldLog(Log.INFO)) _log.info("Insufficient precalculated YK values - create a new one"); + ctx.statManager().addRateData("crypto.YKUsed", 1, 0); + BigInteger[] rv = _values.poll(); + if (rv != null) + return rv; + ctx.statManager().addRateData("crypto.YKEmpty", 1, 0); return generateYK(); } private final static BigInteger _two = new NativeBigInteger(1, new byte[] { 0x02}); + /** @return rv[0] = Y; rv[1] = K */ private static final BigInteger[] generateYK() { NativeBigInteger k = null; BigInteger y = null; - long t0 = 0; - long t1 = 0; + //long t0 = 0; + //long t1 = 0; while (k == null) { - t0 = Clock.getInstance().now(); - k = new NativeBigInteger(KeyGenerator.PUBKEY_EXPONENT_SIZE, RandomSource.getInstance()); - t1 = Clock.getInstance().now(); + //t0 = Clock.getInstance().now(); + k = new NativeBigInteger(KeyGenerator.PUBKEY_EXPONENT_SIZE, ctx.random()); + //t1 = Clock.getInstance().now(); if (BigInteger.ZERO.compareTo(k) == 0) { k = null; continue; @@ -139,39 +113,31 @@ class YKGenerator { BigInteger kPlus2 = k.add(_two); if (kPlus2.compareTo(CryptoConstants.elgp) > 0) k = null; } - long t2 = Clock.getInstance().now(); + //long t2 = Clock.getInstance().now(); y = CryptoConstants.elgg.modPow(k, CryptoConstants.elgp); BigInteger yk[] = new BigInteger[2]; yk[0] = y; yk[1] = k; - long diff = t2 - t0; - if (diff > 1000) { - if (_log.shouldLog(Log.WARN)) _log.warn("Took too long to generate YK value for ElGamal (" + diff + "ms)"); - } + //long diff = t2 - t0; + //if (diff > 1000) { + // if (_log.shouldLog(Log.WARN)) _log.warn("Took too long to generate YK value for ElGamal (" + diff + "ms)"); + //} return yk; } public static void main(String args[]) { - RandomSource.getInstance().nextBoolean(); // warm it up - try { - Thread.sleep(20 * 1000); - } catch (InterruptedException ie) { // nop - } - _log.debug("\n\n\n\nBegin test\n"); + System.out.println("\n\n\n\nBegin test\n"); long negTime = 0; for (int i = 0; i < 5; i++) { long startNeg = Clock.getInstance().now(); getNextYK(); long endNeg = Clock.getInstance().now(); + negTime += endNeg - startNeg; } - _log.debug("YK fetch time for 5 runs: " + negTime + " @ " + negTime / 5l + "ms each"); - try { - Thread.sleep(30 * 1000); - } catch (InterruptedException ie) { // nop - } + System.out.println("YK fetch time for 5 runs: " + negTime + " @ " + negTime / 5l + "ms each"); } private static class YKPrecalcRunner implements Runnable { @@ -186,15 +152,21 @@ class YKGenerator { public void run() { while (true) { int curSize = 0; - long start = Clock.getInstance().now(); + //long start = Clock.getInstance().now(); int startSize = getSize(); + // Adjust delay + if (startSize <= (_minSize / 2) && CHECK_DELAY > 1000) + CHECK_DELAY -= 1000; + else if (startSize > (_minSize * 2) && CHECK_DELAY < 60000) + CHECK_DELAY += 1000; curSize = startSize; - while (curSize < _minSize) { - while (curSize < _maxSize) { - long begin = Clock.getInstance().now(); - curSize = addValues(generateYK()); - long end = Clock.getInstance().now(); - if (_log.shouldLog(Log.DEBUG)) _log.debug("Precalculated YK value in " + (end - begin) + "ms"); + if (curSize < _minSize) { + for (int i = curSize; i < _maxSize; i++) { + //long begin = Clock.getInstance().now(); + if (!addValues(generateYK())) + break; + //long end = Clock.getInstance().now(); + //if (_log.shouldLog(Log.DEBUG)) _log.debug("Precalculated YK value in " + (end - begin) + "ms"); // for some relief... try { Thread.sleep(CALC_DELAY); @@ -202,14 +174,14 @@ class YKGenerator { } } } - long end = Clock.getInstance().now(); - int numCalc = curSize - startSize; - if (numCalc > 0) { - if (_log.shouldLog(Log.DEBUG)) - _log.debug("Precalced " + numCalc + " to " + curSize + " in " - + (end - start - CALC_DELAY * numCalc) + "ms (not counting " - + (CALC_DELAY * numCalc) + "ms relief). now sleeping"); - } + //long end = Clock.getInstance().now(); + //int numCalc = curSize - startSize; + //if (numCalc > 0) { + // if (_log.shouldLog(Log.DEBUG)) + // _log.debug("Precalced " + numCalc + " to " + curSize + " in " + // + (end - start - CALC_DELAY * numCalc) + "ms (not counting " + // + (CALC_DELAY * numCalc) + "ms relief). now sleeping"); + //} try { Thread.sleep(CHECK_DELAY); } catch (InterruptedException ie) { // nop @@ -217,4 +189,4 @@ class YKGenerator { } } } -} \ No newline at end of file +}