Performance enhancements ported from GemFire 8.2.0.x This increases throughput in GMSMembershipManager by avoiding write-locks on the view in some places.
I also found GMSHealthMonitor was mistakenly referencing a CORBA class's "debug" static variable and found an out-of-date comment in AnalyzeSerializablesJUnitTest. Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/3f6acdc7 Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/3f6acdc7 Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/3f6acdc7 Branch: refs/heads/master Commit: 3f6acdc70fd6454af6b44a719a318e2106d68e46 Parents: 3e20193 Author: Bruce Schuchardt <bschucha...@pivotal.io> Authored: Tue Jul 19 13:31:09 2016 -0700 Committer: Bruce Schuchardt <bschucha...@pivotal.io> Committed: Tue Jul 19 13:31:09 2016 -0700 ---------------------------------------------------------------------- .../membership/gms/fd/GMSHealthMonitor.java | 8 +- .../gms/mgr/GMSMembershipManager.java | 191 ++++++++++--------- .../AnalyzeSerializablesJUnitTest.java | 4 +- 3 files changed, 109 insertions(+), 94 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3f6acdc7/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/fd/GMSHealthMonitor.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/fd/GMSHealthMonitor.java b/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/fd/GMSHealthMonitor.java old mode 100755 new mode 100644 index e0f22a5..586427f --- a/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/fd/GMSHealthMonitor.java +++ b/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/fd/GMSHealthMonitor.java @@ -295,9 +295,7 @@ public class GMSHealthMonitor implements HealthMonitor, MessageHandler { socket.shutdownOutput(); GMSHealthMonitor.this.stats.incFinalCheckResponsesSent(); GMSHealthMonitor.this.stats.incTcpFinalCheckResponsesSent(); - if (debug) { - logger.debug("HealthMonitor: server replied OK."); - } + logger.debug("HealthMonitor: server replied OK."); } else { if (logger.isDebugEnabled()) { logger.debug("HealthMonitor: sending ERROR reply - my UUID is {},{} received is {},{}. My viewID is {} received is {}", @@ -312,9 +310,7 @@ public class GMSHealthMonitor implements HealthMonitor, MessageHandler { socket.shutdownOutput(); GMSHealthMonitor.this.stats.incFinalCheckResponsesSent(); GMSHealthMonitor.this.stats.incTcpFinalCheckResponsesSent(); - if (debug) { - logger.debug("HealthMonitor: server replied ERROR."); - } + logger.debug("HealthMonitor: server replied ERROR."); } } catch (IOException e) { // this is expected if it is a connection-timeout or other failure http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3f6acdc7/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/mgr/GMSMembershipManager.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/mgr/GMSMembershipManager.java b/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/mgr/GMSMembershipManager.java index b755f6c..e6ca8e1 100644 --- a/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/mgr/GMSMembershipManager.java +++ b/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/membership/gms/mgr/GMSMembershipManager.java @@ -60,8 +60,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.concurrent.locks.*; public class GMSMembershipManager implements MembershipManager, Manager { @@ -219,7 +218,9 @@ public class GMSMembershipManager implements MembershipManager, Manager * @see #latestView */ protected ReadWriteLock latestViewLock = new ReentrantReadWriteLock(); - + private final Lock latestViewReadLock = latestViewLock.readLock(); + private final Lock latestViewWriteLock = latestViewLock.writeLock(); + /** * This is the listener that accepts our membership events */ @@ -424,7 +425,7 @@ public class GMSMembershipManager implements MembershipManager, Manager // } // We perform the update under a global lock so that other // incoming events will not be lost in terms of our global view. - latestViewLock.writeLock().lock(); + latestViewWriteLock.lock(); try { // first determine the version for multicast message serialization Version version = Version.CURRENT; @@ -597,7 +598,7 @@ public class GMSMembershipManager implements MembershipManager, Manager catch (DistributedSystemDisconnectedException se) { } } finally { - latestViewLock.writeLock().unlock(); + latestViewWriteLock.unlock(); } } @@ -630,7 +631,7 @@ public class GMSMembershipManager implements MembershipManager, Manager services.setShutdownCause(null); services.getCancelCriterion().cancel(null); - latestViewLock.writeLock().lock(); + latestViewWriteLock.lock(); try { try { this.isJoining = true; // added for bug #44373 @@ -668,7 +669,7 @@ public class GMSMembershipManager implements MembershipManager, Manager } } finally { - latestViewLock.writeLock().unlock(); + latestViewWriteLock.unlock(); } } @@ -880,7 +881,7 @@ public class GMSMembershipManager implements MembershipManager, Manager final InternalDistributedMember member = (InternalDistributedMember)dm; boolean warn = false; - latestViewLock.writeLock().lock(); + latestViewWriteLock.lock(); try { // At this point, the join may have been discovered by // other means. @@ -955,7 +956,7 @@ public class GMSMembershipManager implements MembershipManager, Manager latestView = newMembers; } } finally { - latestViewLock.writeLock().unlock(); + latestViewWriteLock.unlock(); } if (warn) { // fix for bug #41538 - deadlock while alerting logger.warn(LocalizedMessage.create( @@ -969,7 +970,7 @@ public class GMSMembershipManager implements MembershipManager, Manager /** starts periodic task to perform cleanup chores such as expire surprise members */ private void startCleanupTimer() { - latestViewLock.writeLock().lock(); + latestViewWriteLock.lock(); try { if (this.cleanupTimer != null) { return; @@ -980,7 +981,7 @@ public class GMSMembershipManager implements MembershipManager, Manager SystemTimer.SystemTimerTask st = new SystemTimer.SystemTimerTask() { @Override public void run2() { - latestViewLock.writeLock().lock(); + latestViewWriteLock.lock(); try { long oldestAllowed = System.currentTimeMillis() - surpriseMemberTimeout; for (Iterator it=surpriseMembers.entrySet().iterator(); it.hasNext(); ) { @@ -996,14 +997,14 @@ public class GMSMembershipManager implements MembershipManager, Manager } } } finally { - latestViewLock.writeLock().unlock(); + latestViewWriteLock.unlock(); } } }; this.cleanupTimer.scheduleAtFixedRate(st, surpriseMemberTimeout, surpriseMemberTimeout/3); } // ds != null && ds.isConnected() } finally { - latestViewLock.writeLock().unlock(); + latestViewWriteLock.unlock(); } } /** @@ -1029,7 +1030,7 @@ public class GMSMembershipManager implements MembershipManager, Manager } public void warnShun(DistributedMember m) { - latestViewLock.writeLock().lock(); + latestViewWriteLock.lock(); try { if (!shunnedMembers.containsKey(m)) { return; // not shunned @@ -1039,7 +1040,7 @@ public class GMSMembershipManager implements MembershipManager, Manager } shunnedAndWarnedMembers.add(m); } finally { - latestViewLock.writeLock().unlock(); + latestViewWriteLock.unlock(); } // issue warning outside of sync since it may cause messaging and we don't // want to hold the view lock while doing that @@ -1063,47 +1064,48 @@ public class GMSMembershipManager implements MembershipManager, Manager InternalDistributedMember m = msg.getSender(); boolean shunned = false; - // First grab the lock: check the sender against our stabilized view. - latestViewLock.writeLock().lock(); - try { - if (isShunned(m)) { - if (msg instanceof StartupMessage) { - endShun(m); - } - else { - // fix for bug 41538 - sick alert listener causes deadlock - // due to view lock being held during messaging - shunned = true; + // If this member is shunned or new, grab the latestViewWriteLock: update the appropriate data structure. + // synchronized (latestViewLock) { + if (isShunnedOrNew(m)) { + latestViewWriteLock.lock(); + try { + if (isShunned(m)) { + if (msg instanceof StartupMessage) { + endShun(m); + } else { + // fix for bug 41538 - sick alert listener causes deadlock + // due to view latestViewReadWriteLock being held during messaging + shunned = true; + } } - } // isShunned - if (!shunned) { - isNew = !latestView.contains(m) && !surpriseMembers.containsKey(m); - - // If it's a new sender, wait our turn, generate the event - if (isNew) { - shunned = !addSurpriseMember(m); - } // isNew + if (!shunned) { + // If it's a new sender, wait our turn, generate the event + if (isNew(m)) { + shunned = !addSurpriseMember(m); + } + } + } finally { + latestViewWriteLock.unlock(); } - - // Latch the view before we unlock - } finally { - latestViewLock.writeLock().unlock(); } - + if (shunned) { // bug #41538 - shun notification must be outside synchronization to avoid hanging warnShun(m); - logger.info("Membership: Ignoring message from shunned member <{}>:{}", m, msg); + if (logger.isTraceEnabled(LogMarker.DISTRIBUTION_VIEWS)) { + logger.trace(LogMarker.DISTRIBUTION_VIEWS, "Membership: Ignoring message from shunned member <{}>:{}", m, msg); + } throw new MemberShunnedException(m); } - + listener.messageReceived(msg); } - /** - * Process a new view object, or place on the startup queue - * @param viewArg the new view - */ + + /** + * Process a new view object, or place on the startup queue + * @param viewArg the new view + */ protected void handleOrDeferViewEvent(NetView viewArg) { if (this.isJoining) { // bug #44373 - queue all view messages while joining. @@ -1114,7 +1116,7 @@ public class GMSMembershipManager implements MembershipManager, Manager return; } } - latestViewLock.writeLock().lock(); + latestViewWriteLock.lock(); try { synchronized(startupLock) { if (!processingEvents) { @@ -1131,7 +1133,7 @@ public class GMSMembershipManager implements MembershipManager, Manager listener.messageReceived(v); } finally { - latestViewLock.writeLock().unlock(); + latestViewWriteLock.unlock(); } } @@ -1146,7 +1148,7 @@ public class GMSMembershipManager implements MembershipManager, Manager * @param suspectInfo the suspectee and suspector */ protected void handleOrDeferSuspect(SuspectMember suspectInfo) { - latestViewLock.writeLock().lock(); + latestViewWriteLock.lock(); try { synchronized(startupLock) { if (!processingEvents) { @@ -1163,7 +1165,7 @@ public class GMSMembershipManager implements MembershipManager, Manager // let's not get huffy about it } } finally { - latestViewLock.writeLock().unlock(); + latestViewWriteLock.unlock(); } } @@ -1325,9 +1327,9 @@ public class GMSMembershipManager implements MembershipManager, Manager // Grab the latest view under a mutex... NetView v; - latestViewLock.readLock().lock(); + latestViewReadLock.lock(); v = latestView; - latestViewLock.readLock().unlock(); + latestViewReadLock.unlock(); NetView result = new NetView(v, v.getViewId()); @@ -1348,11 +1350,11 @@ public class GMSMembershipManager implements MembershipManager, Manager * @return the lead member associated with the latest view */ public DistributedMember getLeadMember() { - latestViewLock.readLock().lock(); + latestViewReadLock.lock(); try { return latestView == null? null : latestView.getLeadMember(); } finally { - latestViewLock.readLock().unlock(); + latestViewReadLock.unlock(); } } @@ -1365,18 +1367,18 @@ public class GMSMembershipManager implements MembershipManager, Manager * @return the current membership view coordinator */ public DistributedMember getCoordinator() { - latestViewLock.readLock().lock(); + latestViewReadLock.lock(); try { return latestView == null? null : latestView.getCoordinator(); } finally { - latestViewLock.readLock().unlock(); + latestViewReadLock.unlock(); } } public boolean memberExists(DistributedMember m) { - latestViewLock.readLock().lock(); + latestViewReadLock.lock(); NetView v = latestView; - latestViewLock.readLock().unlock(); + latestViewReadLock.unlock(); return v.getMembers().contains(m); } @@ -1500,11 +1502,11 @@ public class GMSMembershipManager implements MembershipManager, Manager // Make sure that channel information is consistent // Probably not important in this particular case, but just // to be consistent... - latestViewLock.writeLock().lock(); + latestViewWriteLock.lock(); try { destroyMember(address, false, "orderly shutdown"); } finally { - latestViewLock.writeLock().unlock(); + latestViewWriteLock.unlock(); } } } @@ -1684,13 +1686,13 @@ public class GMSMembershipManager implements MembershipManager, Manager InternalDistributedMember[] keys; if (content.forAll()) { allDestinations = true; - latestViewLock.writeLock().lock(); + latestViewReadLock.lock(); try { List<InternalDistributedMember> keySet = latestView.getMembers(); keys = new InternalDistributedMember[keySet.size()]; keys = (InternalDistributedMember[])keySet.toArray(keys); } finally { - latestViewLock.writeLock().unlock(); + latestViewReadLock.unlock(); } } else { @@ -1917,11 +1919,11 @@ public class GMSMembershipManager implements MembershipManager, Manager if (m != null) { GMSMember id = (GMSMember)m.getNetMember(); if (!id.hasUUID()) { - latestViewLock.readLock().lock(); + latestViewReadLock.lock(); try { addresses[i] = latestView.getCanonicalID(addresses[i]); } finally { - latestViewLock.readLock().unlock(); + latestViewReadLock.unlock(); } } } @@ -1941,9 +1943,9 @@ public class GMSMembershipManager implements MembershipManager, Manager public void setShutdown() { - latestViewLock.writeLock().lock(); + latestViewWriteLock.lock(); shutdownInProgress = true; - latestViewLock.writeLock().unlock(); + latestViewWriteLock.unlock(); } @Override @@ -1965,7 +1967,7 @@ public class GMSMembershipManager implements MembershipManager, Manager boolean crashed, final String reason) { // Make sure it is removed from the view - latestViewLock.writeLock().lock(); + latestViewWriteLock.lock(); try { if (latestView.contains(member)) { NetView newView = new NetView(latestView, latestView.getViewId()); @@ -1973,7 +1975,7 @@ public class GMSMembershipManager implements MembershipManager, Manager latestView = newView; } } finally { - latestViewLock.writeLock().unlock(); + latestViewWriteLock.unlock(); } surpriseMembers.remove(member); @@ -2031,29 +2033,46 @@ public class GMSMembershipManager implements MembershipManager, Manager * list if it was shunned too far in the past. * * Concurrency: protected by {@link #latestViewLock} ReentrantReadWriteLock - * + * + * @guarded.By latestViewLock * @return true if the given member is a zombie */ public boolean isShunned(DistributedMember m) { - latestViewLock.writeLock().lock(); + if (!shunnedMembers.containsKey(m)) { + return false; + } + + latestViewWriteLock.lock(); try { - if (!shunnedMembers.containsKey(m)) - return false; - // Make sure that the entry isn't stale... long shunTime = ((Long)shunnedMembers.get(m)).longValue(); long now = System.currentTimeMillis(); - if (shunTime + SHUNNED_SUNSET * 1000 > now) + if (shunTime + SHUNNED_SUNSET * 1000 > now) { return true; + } // Oh, it _is_ stale. Remove it while we're here. endShun(m); return false; } finally { - latestViewLock.writeLock().unlock(); + latestViewWriteLock.unlock(); } } + private final boolean isShunnedOrNew(final InternalDistributedMember m) { + latestViewReadLock.lock(); + try { + return shunnedMembers.containsKey(m) || isNew(m); + } finally { // synchronized + latestViewReadLock.unlock(); + } + } + + // must be invoked under view read or write lock + private final boolean isNew(final InternalDistributedMember m) { + return !latestView.contains(m) && !surpriseMembers.containsKey(m); + } + /** * Indicate whether the given member is in the surprise member list * <P> @@ -2068,7 +2087,7 @@ public class GMSMembershipManager implements MembershipManager, Manager * @return true if the given member is a surprise member */ public boolean isSurpriseMember(DistributedMember m) { - latestViewLock.readLock().lock(); + latestViewReadLock.lock(); try { if (surpriseMembers.containsKey(m)) { long birthTime = ((Long)surpriseMembers.get(m)).longValue(); @@ -2077,7 +2096,7 @@ public class GMSMembershipManager implements MembershipManager, Manager } return false; } finally { - latestViewLock.readLock().unlock(); + latestViewReadLock.unlock(); } } @@ -2091,11 +2110,11 @@ public class GMSMembershipManager implements MembershipManager, Manager if (logger.isDebugEnabled()) { logger.debug("test hook is adding surprise member {} birthTime={}", m, birthTime); } - latestViewLock.writeLock().lock(); + latestViewWriteLock.lock(); try { surpriseMembers.put((InternalDistributedMember)m, Long.valueOf(birthTime)); } finally { - latestViewLock.writeLock().unlock(); + latestViewWriteLock.unlock(); } } @@ -2253,11 +2272,11 @@ public class GMSMembershipManager implements MembershipManager, Manager } } if (!wait) { - latestViewLock.readLock().lock(); + latestViewReadLock.lock(); try { wait = this.latestView.contains(idm); } finally { - latestViewLock.readLock().unlock(); + latestViewReadLock.unlock(); } if (wait && logger.isDebugEnabled()) { logger.debug("waiting for {} to leave the membership view", mbr); @@ -2310,7 +2329,7 @@ public class GMSMembershipManager implements MembershipManager, Manager CountDownLatch currentLatch = null; // ARB: preconditions // remoteId != null - latestViewLock.writeLock().lock(); + latestViewWriteLock.lock(); try { if (latestView == null) { // Not sure how this would happen, but see bug 38460. @@ -2326,7 +2345,7 @@ public class GMSMembershipManager implements MembershipManager, Manager this.memberLatch.put(remoteId, currentLatch); } } finally { - latestViewLock.writeLock().unlock(); + latestViewWriteLock.unlock(); } if (!foundRemoteId) { @@ -2381,7 +2400,7 @@ public class GMSMembershipManager implements MembershipManager, Manager public void registerTestHook(MembershipTestHook mth) { // lock for additions to avoid races during startup - latestViewLock.writeLock().lock(); + latestViewWriteLock.lock(); try { if (this.membershipTestHooks == null) { this.membershipTestHooks = Collections.singletonList(mth); @@ -2392,12 +2411,12 @@ public class GMSMembershipManager implements MembershipManager, Manager this.membershipTestHooks = l; } } finally { - latestViewLock.writeLock().unlock(); + latestViewWriteLock.unlock(); } } public void unregisterTestHook(MembershipTestHook mth) { - latestViewLock.writeLock().lock(); + latestViewWriteLock.lock(); try { if (this.membershipTestHooks != null) { if (this.membershipTestHooks.size() == 1) { @@ -2409,7 +2428,7 @@ public class GMSMembershipManager implements MembershipManager, Manager } } } finally { - latestViewLock.writeLock().unlock(); + latestViewWriteLock.unlock(); } } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/3f6acdc7/geode-core/src/test/java/com/gemstone/gemfire/codeAnalysis/AnalyzeSerializablesJUnitTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/com/gemstone/gemfire/codeAnalysis/AnalyzeSerializablesJUnitTest.java b/geode-core/src/test/java/com/gemstone/gemfire/codeAnalysis/AnalyzeSerializablesJUnitTest.java index 1c9b8c4..d551c9f 100644 --- a/geode-core/src/test/java/com/gemstone/gemfire/codeAnalysis/AnalyzeSerializablesJUnitTest.java +++ b/geode-core/src/test/java/com/gemstone/gemfire/codeAnalysis/AnalyzeSerializablesJUnitTest.java @@ -53,9 +53,9 @@ public class AnalyzeSerializablesJUnitTest { @Before public void loadClasses() throws Exception { String version = System.getProperty("java.runtime.version"); - boolean jdk17 = version != null && version.startsWith("1.8"); + boolean jdk18 = version != null && version.startsWith("1.8"); // sanctioned info is based on a 1.7 compiler - Assume.assumeTrue("AnalyzeSerializables requires a Java 7 but tests are running with v"+version, jdk17); + Assume.assumeTrue("AnalyzeSerializables requires a Java 8 but tests are running with v"+version, jdk18); if (classes.size() > 0) { return; }