From f61183d2d85bb76cdf2b4db972951ffa34987b82 Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Wed, 29 Feb 2012 18:09:16 +0000 Subject: [PATCH] * DataStructures: - Remove static logs - Sort addresses in RouterInfo at initialization only; change from Set to List to save space - Remove unused counters in Lease to save space - Increase max leases to 16 --- core/java/src/net/i2p/data/DataHelper.java | 12 +++- core/java/src/net/i2p/data/LeaseSet.java | 42 ++++++++++---- core/java/src/net/i2p/data/RouterInfo.java | 55 +++++++++++-------- router/java/src/net/i2p/router/Blocklist.java | 8 +-- .../kademlia/FloodfillVerifyStoreJob.java | 2 +- ...andleFloodfillDatabaseStoreMessageJob.java | 9 +-- .../router/peermanager/ProfileOrganizer.java | 3 +- 7 files changed, 83 insertions(+), 48 deletions(-) diff --git a/core/java/src/net/i2p/data/DataHelper.java b/core/java/src/net/i2p/data/DataHelper.java index d809926098..ad6ac6ea9d 100644 --- a/core/java/src/net/i2p/data/DataHelper.java +++ b/core/java/src/net/i2p/data/DataHelper.java @@ -1299,10 +1299,20 @@ public class DataHelper { // rv.add(struct); //} ArrayList<DataStructure> rv = new ArrayList(dataStructures); - Collections.sort(rv, new DataStructureComparator()); + sortStructureList(rv); return rv; } + /** + * See above. + * DEPRECATED - Only used by RouterInfo. + * + * @since 0.9 + */ + static void sortStructureList(List<? extends DataStructure> dataStructures) { + Collections.sort(dataStructures, new DataStructureComparator()); + } + /** * See sortStructures() comments. * @since 0.8.3 diff --git a/core/java/src/net/i2p/data/LeaseSet.java b/core/java/src/net/i2p/data/LeaseSet.java index e372f401cd..9fe9ebb304 100644 --- a/core/java/src/net/i2p/data/LeaseSet.java +++ b/core/java/src/net/i2p/data/LeaseSet.java @@ -56,7 +56,6 @@ import net.i2p.util.RandomSource; * @author jrandom */ public class LeaseSet extends DatabaseEntry { - private final static Log _log = new Log(LeaseSet.class); private Destination _destination; private PublicKey _encryptionKey; private SigningPublicKey _signingKey; @@ -71,11 +70,26 @@ public class LeaseSet extends DatabaseEntry { private boolean _decrypted; private boolean _checked; - /** This seems like plenty */ - public final static int MAX_LEASES = 6; + /** + * Unlimited before 0.6.3; + * 6 as of 0.6.3; + * Increased in version 0.9. + * + * Leasesets larger than 6 should be used with caution, + * as each lease adds 44 bytes, and routers older than version 0.9 + * will not be able to connect as they will throw an exception in + * readBytes(). Also, the churn will be quite rapid, leading to + * frequent netdb stores and transmission on existing connections. + * + * However we increase it now in case some hugely popular eepsite arrives. + * Strategies elsewhere in the router to efficiently handle + * large leasesets are TBD. + */ + public static final int MAX_LEASES = 16; + private static final int OLD_MAX_LEASES = 6; public LeaseSet() { - _leases = new ArrayList(MAX_LEASES); + _leases = new ArrayList(OLD_MAX_LEASES); _firstExpiration = Long.MAX_VALUE; } @@ -354,14 +368,16 @@ public class LeaseSet extends DatabaseEntry { * Must be called after all the leases are in place, but before sign(). */ public void encrypt(SessionKey key) { - if (_log.shouldLog(Log.WARN)) - _log.warn("encrypting lease: " + _destination.calculateHash()); + //if (_log.shouldLog(Log.WARN)) + // _log.warn("encrypting lease: " + _destination.calculateHash()); try { encryp(key); } catch (DataFormatException dfe) { - _log.error("Error encrypting lease: " + _destination.calculateHash()); + Log log = I2PAppContext.getGlobalContext().logManager().getLog(LeaseSet.class); + log.error("Error encrypting lease: " + _destination.calculateHash()); } catch (IOException ioe) { - _log.error("Error encrypting lease: " + _destination.calculateHash()); + Log log = I2PAppContext.getGlobalContext().logManager().getLog(LeaseSet.class); + log.error("Error encrypting lease: " + _destination.calculateHash()); } } @@ -420,8 +436,8 @@ public class LeaseSet extends DatabaseEntry { * encrypted leaseset can be sent on to others (via writeBytes()) */ private void decrypt(SessionKey key) throws DataFormatException, IOException { - if (_log.shouldLog(Log.WARN)) - _log.warn("decrypting lease: " + _destination.calculateHash()); + //if (_log.shouldLog(Log.WARN)) + // _log.warn("decrypting lease: " + _destination.calculateHash()); int size = _leases.size(); if (size < 2) throw new DataFormatException("Bad number of leases for decryption"); @@ -468,9 +484,11 @@ public class LeaseSet extends DatabaseEntry { decrypt(key); _decrypted = true; } catch (DataFormatException dfe) { - _log.error("Error decrypting lease: " + _destination.calculateHash() + dfe); + Log log = I2PAppContext.getGlobalContext().logManager().getLog(LeaseSet.class); + log.error("Error decrypting lease: " + _destination.calculateHash() + dfe); } catch (IOException ioe) { - _log.error("Error decrypting lease: " + _destination.calculateHash() + ioe); + Log log = I2PAppContext.getGlobalContext().logManager().getLog(LeaseSet.class); + log.error("Error decrypting lease: " + _destination.calculateHash() + ioe); } } _checked = true; diff --git a/core/java/src/net/i2p/data/RouterInfo.java b/core/java/src/net/i2p/data/RouterInfo.java index 6c34ad2023..398b61e0c8 100644 --- a/core/java/src/net/i2p/data/RouterInfo.java +++ b/core/java/src/net/i2p/data/RouterInfo.java @@ -13,6 +13,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date; @@ -24,6 +25,7 @@ import java.util.Properties; import java.util.Set; import java.util.Vector; +import net.i2p.I2PAppContext; import net.i2p.crypto.SHA256Generator; import net.i2p.util.Clock; import net.i2p.util.Log; @@ -43,10 +45,14 @@ import net.i2p.util.OrderedProperties; * @author jrandom */ public class RouterInfo extends DatabaseEntry { - private final static Log _log = new Log(RouterInfo.class); private RouterIdentity _identity; private volatile long _published; - private final Set<RouterAddress> _addresses; + /** + * Addresses must be sorted by SHA256. + * When an RI is created, they are sorted in setAddresses(). + * Save addresses in the order received so we need not resort. + */ + private final List<RouterAddress> _addresses; /** may be null to save memory, no longer final */ private Set<Hash> _peers; private final Properties _options; @@ -71,7 +77,7 @@ public class RouterInfo extends DatabaseEntry { public static final String BW_CAPABILITY_CHARS = "KLMNO"; public RouterInfo() { - _addresses = new HashSet(2); + _addresses = new ArrayList(2); _options = new OrderedProperties(); } @@ -156,21 +162,33 @@ public class RouterInfo extends DatabaseEntry { * * @return unmodifiable view, non-null */ - public Set<RouterAddress> getAddresses() { - return Collections.unmodifiableSet(_addresses); + public Collection<RouterAddress> getAddresses() { + return Collections.unmodifiableCollection(_addresses); } /** * Specify a set of RouterAddress structures at which this router * can be contacted. * - * @throws IllegalStateException if RouterInfo is already signed + * Warning - Sorts the addresses here. Do not modify any address + * after calling this, as the sort order is based on the + * hash of the entire address structure. + * + * @param addresses may be null + * @throws IllegalStateException if RouterInfo is already signed or addresses previously set */ - public void setAddresses(Set<RouterAddress> addresses) { - if (_signature != null) + public void setAddresses(Collection<RouterAddress> addresses) { + if (_signature != null || !_addresses.isEmpty()) throw new IllegalStateException(); - _addresses.clear(); - if (addresses != null) _addresses.addAll(addresses); + if (addresses != null) { + _addresses.addAll(addresses); + if (_addresses.size() > 1) { + // WARNING this sort algorithm cannot be changed, as it must be consistent + // network-wide. The signature is not checked at readin time, but only + // later, and the addresses are stored in a Set, not a List. + DataHelper.sortStructureList(_addresses); + } + } } /** @@ -270,14 +288,7 @@ public class RouterInfo extends DatabaseEntry { DataHelper.writeLong(out, 1, 0); } else { DataHelper.writeLong(out, 1, sz); - Collection<RouterAddress> addresses = _addresses; - if (sz > 1) { - // WARNING this sort algorithm cannot be changed, as it must be consistent - // network-wide. The signature is not checked at readin time, but only - // later, and the addresses are stored in a Set, not a List. - addresses = (Collection<RouterAddress>) DataHelper.sortStructures(addresses); - } - for (RouterAddress addr : addresses) { + for (RouterAddress addr : _addresses) { addr.writeBytes(out); } } @@ -458,16 +469,16 @@ public class RouterInfo extends DatabaseEntry { _validated = true; if (!_isValid) { + Log log = I2PAppContext.getGlobalContext().logManager().getLog(RouterInfo.class); byte data[] = null; try { data = getBytes(); } catch (DataFormatException dfe) { - _log.error("Error validating", dfe); + log.error("Error validating", dfe); return; } - if (_log.shouldLog(Log.ERROR)) - _log.error("Invalid [" + SHA256Generator.getInstance().calculateHash(data).toBase64() - + (_log.shouldLog(Log.WARN) ? ("]\n" + toString()) : ""), + log.error("Invalid [" + SHA256Generator.getInstance().calculateHash(data).toBase64() + + (log.shouldLog(Log.WARN) ? ("]\n" + toString()) : ""), new Exception("Signature failed")); } } diff --git a/router/java/src/net/i2p/router/Blocklist.java b/router/java/src/net/i2p/router/Blocklist.java index 153b14e7c9..48ff328a2c 100644 --- a/router/java/src/net/i2p/router/Blocklist.java +++ b/router/java/src/net/i2p/router/Blocklist.java @@ -479,15 +479,9 @@ public class Blocklist { List<byte[]> rv = new ArrayList(1); RouterInfo pinfo = _context.netDb().lookupRouterInfoLocally(peer); if (pinfo == null) return rv; - Set<RouterAddress> paddr = pinfo.getAddresses(); - if (paddr == null || paddr.isEmpty()) - return rv; String oldphost = null; - List<RouterAddress> pladdr = new ArrayList(paddr); // for each peer address - for (int j = 0; j < paddr.size(); j++) { - RouterAddress pa = (RouterAddress) pladdr.get(j); - if (pa == null) continue; + for (RouterAddress pa : pinfo.getAddresses()) { String phost = pa.getOption("host"); if (phost == null) continue; if (oldphost != null && oldphost.equals(phost)) continue; diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillVerifyStoreJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillVerifyStoreJob.java index 9fe6e25221..7b567d6126 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillVerifyStoreJob.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/FloodfillVerifyStoreJob.java @@ -216,7 +216,7 @@ public class FloodfillVerifyStoreJob extends JobImpl { if (_log.shouldLog(Log.WARN)) _log.warn("Verify failed (older) for " + _key); if (_log.shouldLog(Log.INFO)) - _log.info("Rcvd older lease: " + dsm.getEntry()); + _log.info("Rcvd older data: " + dsm.getEntry()); } else if (_message instanceof DatabaseSearchReplyMessage) { // assume 0 old, all new, 0 invalid, 0 dup getContext().profileManager().dbLookupReply(_target, 0, diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/HandleFloodfillDatabaseStoreMessageJob.java b/router/java/src/net/i2p/router/networkdb/kademlia/HandleFloodfillDatabaseStoreMessageJob.java index 9774f65bd8..21c6a5ccd5 100644 --- a/router/java/src/net/i2p/router/networkdb/kademlia/HandleFloodfillDatabaseStoreMessageJob.java +++ b/router/java/src/net/i2p/router/networkdb/kademlia/HandleFloodfillDatabaseStoreMessageJob.java @@ -8,12 +8,13 @@ package net.i2p.router.networkdb.kademlia; * */ +import java.util.Collection; import java.util.Date; -import java.util.Set; import net.i2p.data.DatabaseEntry; import net.i2p.data.Hash; import net.i2p.data.LeaseSet; +import net.i2p.data.RouterAddress; import net.i2p.data.RouterIdentity; import net.i2p.data.RouterInfo; import net.i2p.data.i2np.DatabaseStoreMessage; @@ -145,9 +146,9 @@ public class HandleFloodfillDatabaseStoreMessageJob extends JobImpl { _log.shouldLog(Log.WARN)) _log.warn("Blocklisting new peer " + key + ' ' + ri); } else { - Set oldAddr = prevNetDb.getAddresses(); - Set newAddr = ri.getAddresses(); - if (newAddr != null && (!newAddr.equals(oldAddr)) && + Collection<RouterAddress> oldAddr = prevNetDb.getAddresses(); + Collection<RouterAddress> newAddr = ri.getAddresses(); + if ((!newAddr.equals(oldAddr)) && (!getContext().shitlist().isShitlistedForever(key)) && getContext().blocklist().isBlocklisted(key) && _log.shouldLog(Log.WARN)) diff --git a/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java b/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java index 8b14d22a0f..d8459166a5 100644 --- a/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java +++ b/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java @@ -7,6 +7,7 @@ import java.net.UnknownHostException; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -1258,7 +1259,7 @@ public class ProfileOrganizer { RouterInfo pinfo = _context.netDb().lookupRouterInfoLocally(peer); if (pinfo == null) return rv; - Set<RouterAddress> paddr = pinfo.getAddresses(); + Collection<RouterAddress> paddr = pinfo.getAddresses(); if (paddr == null) return rv; for (RouterAddress pa : paddr) { -- GitLab