diff --git a/history.txt b/history.txt index 24042ea2f3..d639c79bda 100644 --- a/history.txt +++ b/history.txt @@ -1,7 +1,10 @@ +2020-08-14 zzz + * Profiles: Create profiles in the nonblocking path + 2020-08-10 idk * Replace all icons with icons from a single consistent source/style, icons - used from FontAwesome suggested by design team and selected and edited by - Sadie. + used from FontAwesome suggested by design team and selected and edited by + Sadie. 2020-08-01 zzz * Debian: Support libjson-simple-java 3 for bullseye diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 5a58b19bc2..cef5686075 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,10 +18,10 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 11; + public final static long BUILD = 12; /** for example "-test" */ - public final static String EXTRA = ""; + public final static String EXTRA = "-rc"; public final static String FULL_VERSION = VERSION + "-" + BUILD + EXTRA; public static void main(String args[]) { System.out.println("I2P Router version: " + FULL_VERSION); diff --git a/router/java/src/net/i2p/router/peermanager/ProfileManagerImpl.java b/router/java/src/net/i2p/router/peermanager/ProfileManagerImpl.java index 0846fd69ea..c9d4e5bcc0 100644 --- a/router/java/src/net/i2p/router/peermanager/ProfileManagerImpl.java +++ b/router/java/src/net/i2p/router/peermanager/ProfileManagerImpl.java @@ -361,10 +361,11 @@ public class ProfileManagerImpl implements ProfileManager { /** * Non-blocking. - * @return null if the profile doesn't exist, or the fetch would have blocked + * Creates a new profile if it didn't exist. + * @return null if the fetch or create would have blocked * @since 0.8.12 */ private PeerProfile getProfileNonblocking(Hash peer) { - return _context.profileOrganizer().getProfileNonblocking(peer); + return _context.profileOrganizer().getOrCreateProfileNonblocking(peer); } } diff --git a/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java b/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java index 8c1e4a4954..f74deeb144 100644 --- a/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java +++ b/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java @@ -132,6 +132,15 @@ public class ProfileOrganizer { _reorganizeLock.readLock().unlock(); } + /** + * Get the lock if we can. Non-blocking. + * @return true if the lock was acquired + * @since 0.9.47 + */ + private boolean tryWriteLock() { + return _reorganizeLock.writeLock().tryLock(); + } + /** @return true if the lock was acquired */ private boolean getWriteLock() { try { @@ -189,6 +198,48 @@ public class ProfileOrganizer { return null; } + /** + * Retrieve the profile for the given peer, if one exists. + * If it does not exist and it can get the lock, it will create and return a new profile. + * Non-blocking. Returns null if a reorganize is happening. + * @since 0.9.47 + */ + PeerProfile getOrCreateProfileNonblocking(Hash peer) { + if (peer.equals(_us)) { + if (_log.shouldWarn()) + _log.warn("Who wanted our own profile?", new Exception("I did")); + return null; + } + if (!tryReadLock()) + return null; + PeerProfile rv; + try { + rv = locked_getProfile(peer); + } finally { releaseReadLock(); } + if (rv != null) + return rv; + rv = new PeerProfile(_context, peer); + rv.coalesceStats(); + if (!tryWriteLock()) + return null; + try { + // double check + PeerProfile old = locked_getProfile(peer); + if (old != null) + return old; + _notFailingPeers.put(peer, rv); + _notFailingPeersList.add(peer); + // Add to high cap only if we have room. Don't add to Fast; wait for reorg. + if (_thresholdCapacityValue <= rv.getCapacityValue() && + isSelectable(peer) && + _highCapacityPeers.size() < getMaximumHighCapPeers()) { + _highCapacityPeers.put(peer, rv); + } + _strictCapacityOrder.add(rv); + } finally { releaseWriteLock(); } + return rv; + } + /** * Add the new profile, returning the old value (or null if no profile existed) *