X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=singleton-service%2Fmdsal-singleton-dom-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fsingleton%2Fdom%2Fimpl%2FClusterSingletonServiceGroupImpl.java;h=90ffc10e7a78d0977de5287c30301f93db754ab8;hb=62a591d105563555955efeeddb4f16af38529d57;hp=af18888ef24dddd43799754d35041df6cf276887;hpb=8216dbb9b22b70155a583e7d5444c0f6da78b0a1;p=mdsal.git diff --git a/singleton-service/mdsal-singleton-dom-impl/src/main/java/org/opendaylight/mdsal/singleton/dom/impl/ClusterSingletonServiceGroupImpl.java b/singleton-service/mdsal-singleton-dom-impl/src/main/java/org/opendaylight/mdsal/singleton/dom/impl/ClusterSingletonServiceGroupImpl.java index af18888ef2..90ffc10e7a 100644 --- a/singleton-service/mdsal-singleton-dom-impl/src/main/java/org/opendaylight/mdsal/singleton/dom/impl/ClusterSingletonServiceGroupImpl.java +++ b/singleton-service/mdsal-singleton-dom-impl/src/main/java/org/opendaylight/mdsal/singleton/dom/impl/ClusterSingletonServiceGroupImpl.java @@ -56,12 +56,18 @@ final class ClusterSingletonServiceGroupImpl

, E extends Generi private final S entityOwnershipService; private final String clusterSingletonGroupIdentifier; - private final Semaphore clusterLock = new Semaphore(1); + private final Semaphore clusterLock = new Semaphore(1, true); /* Entity instances */ private final E serviceEntity; private final E doubleCandidateEntity; + // TODO :it needs to rewrite for StateMachine (INITIALIZED, TRY_TO_TAKE_LEADERSHIP, LEADER, FOLLOWER, TERMINATED) + // INITIALIZED : we have registered baseCandidate and we are waiting for first EOS response (!do we really need it?) + // FOLLOWER : baseCandidate is registered correctly + // TRY_TO_TAKE_LEADERSHIP : guardCandidate is registered correctly + // LEADER : both candidate have mastership from EOS + // TERMINATED : service go down @GuardedBy("clusterLock") private boolean hasOwnership = false; @GuardedBy("clusterLock") @@ -98,9 +104,10 @@ final class ClusterSingletonServiceGroupImpl

, E extends Generi boolean needReleaseLock = false; final ListenableFuture> destroyFuture; try { - needReleaseLock = clusterLock.tryAcquire(10, TimeUnit.SECONDS); + needReleaseLock = clusterLock.tryAcquire(1, TimeUnit.SECONDS); } catch (final Exception e) { - LOG.warn("Unexpected Exception for service Provider {} in closing phase.", clusterSingletonGroupIdentifier, e); + LOG.warn("Unexpected Exception for service Provider {} in closing phase.", clusterSingletonGroupIdentifier, + e); } finally { if (serviceEntityCandidateReg != null) { serviceEntityCandidateReg.close(); @@ -111,10 +118,11 @@ final class ClusterSingletonServiceGroupImpl

, E extends Generi for (final ClusterSingletonServiceRegistrationDelegator service : serviceGroup) { serviceCloseFutureList.add(service.closeServiceInstance()); } + hasOwnership = false; } destroyFuture = Futures.allAsList(serviceCloseFutureList); final Semaphore finalRelease = needReleaseLock ? clusterLock : null; - Futures.addCallback(destroyFuture, newAsyncCloseCallback(finalRelease)); + Futures.addCallback(destroyFuture, newAsyncCloseCallback(finalRelease, true)); } return destroyFuture; } @@ -134,6 +142,7 @@ final class ClusterSingletonServiceGroupImpl

, E extends Generi } catch (final Exception e) { LOG.debug("Unexpected error by registration service Provider {}", clusterSingletonGroupIdentifier, e); needCloseProviderInstance = true; + throw new RuntimeException(e); } finally { closeResources(needReleaseLock, needCloseProviderInstance); } @@ -158,6 +167,7 @@ final class ClusterSingletonServiceGroupImpl

, E extends Generi } catch (final Exception e) { LOG.debug("Unexpected error by registration service Provider {}", clusterSingletonGroupIdentifier, e); needCloseProviderInstance = true; + throw new RuntimeException(e); } finally { closeResources(needReleaseLock, needCloseProviderInstance); } @@ -173,24 +183,27 @@ final class ClusterSingletonServiceGroupImpl

, E extends Generi try { clusterLock.acquire(); needReleaseLock = true; - serviceGroup.remove(service); - if (hasOwnership) { - service.closeServiceInstance(); + if (serviceGroup.size() > 1) { + if (hasOwnership) { + service.closeServiceInstance(); + } + serviceGroup.remove(service); + LOG.debug("Service {} was removed from group.", service.getIdentifier().getValue()); + } else { + needCloseProviderInstance = true; } } catch (final Exception e) { LOG.debug("Unexpected error by registration service Provider {}", clusterSingletonGroupIdentifier, e); needCloseProviderInstance = true; + throw new RuntimeException(e); } finally { closeResources(needReleaseLock, needCloseProviderInstance); - if (serviceGroup.isEmpty()) { - this.closeClusterSingletonGroup(); - } } } @Override - public final void ownershipChanged(final C ownershipChange) { - LOG.debug("Ownership change {} for ClusterSingletonServiceGrou {}", ownershipChange, + public void ownershipChanged(final C ownershipChange) { + LOG.debug("Ownership change {} for ClusterSingletonServiceGroup {}", ownershipChange, clusterSingletonGroupIdentifier); try { if (ownershipChange.inJeopardy()) { @@ -222,15 +235,6 @@ final class ClusterSingletonServiceGroupImpl

, E extends Generi * SLAVE to MASTER : ownershipChange.getState().isOwner() && !ownershipChange.getState().wasOwner() */ takeOwnership(); - } else if (EntityOwnershipChangeState.LOCAL_OWNERSHIP_LOST_NEW_OWNER.equals(ownershipChange.getState()) - || EntityOwnershipChangeState.LOCAL_OWNERSHIP_LOST_NO_OWNER - .equals(ownershipChange.getState())) { - /* - * MASTER to SLAVE : !ownershipChange.getState().isOwner() && ownershipChange.getState().wasOwner() - */ - LOG.warn("Unexpected lost doubleCandidate {} leadership. Close service instance {}", - doubleCandidateEntity, clusterSingletonGroupIdentifier); - lostOwnership(); } else { /* Not needed notifications */ LOG.debug("Not processed doubleCandidate OwnershipChange {} in service Provider {}", @@ -256,9 +260,12 @@ final class ClusterSingletonServiceGroupImpl

, E extends Generi try { clusterLock.acquire(); needReleaseLock = true; - Verify.verify(serviceEntityCandidateReg != null); - Verify.verify(asyncCloseEntityCandidateReg == null); - asyncCloseEntityCandidateReg = entityOwnershipService.registerCandidate(doubleCandidateEntity); + if (serviceEntityCandidateReg != null) { + Verify.verify(asyncCloseEntityCandidateReg == null); + asyncCloseEntityCandidateReg = entityOwnershipService.registerCandidate(doubleCandidateEntity); + } else { + LOG.debug("Service {} is closed, so don't to tryTakeLeadership", clusterSingletonGroupIdentifier); + } } catch (final Exception e) { LOG.error("Unexpected exception state for service Provider {} in TryToTakeLeadership", clusterSingletonGroupIdentifier, e); @@ -278,12 +285,15 @@ final class ClusterSingletonServiceGroupImpl

, E extends Generi try { clusterLock.acquire(); needReleaseLock = true; - Verify.verify(serviceEntityCandidateReg != null); - Verify.verify(asyncCloseEntityCandidateReg != null); - for (final ClusterSingletonServiceRegistrationDelegator service : serviceGroup) { - service.instantiateServiceInstance(); + if (serviceEntityCandidateReg != null) { + Verify.verify(asyncCloseEntityCandidateReg != null); + for (final ClusterSingletonServiceRegistrationDelegator service : serviceGroup) { + service.instantiateServiceInstance(); + } + hasOwnership = true; + } else { + LOG.debug("Service {} is closed, so don't take leadership", clusterSingletonGroupIdentifier); } - hasOwnership = true; } catch (final Exception e) { LOG.error("Unexpected exception state for service Provider {} in TakeLeadership", clusterSingletonGroupIdentifier, e); @@ -305,17 +315,23 @@ final class ClusterSingletonServiceGroupImpl

, E extends Generi try { clusterLock.acquire(); needReleaseLock = true; - Verify.verify(serviceEntityCandidateReg != null); final List> serviceCloseFutureList = new ArrayList<>(); if (hasOwnership) { Verify.verify(asyncCloseEntityCandidateReg != null); for (final ClusterSingletonServiceRegistrationDelegator service : serviceGroup) { serviceCloseFutureList.add(service.closeServiceInstance()); } + hasOwnership = false; } final ListenableFuture> destroyFuture = Futures.allAsList(serviceCloseFutureList); - Futures.addCallback(destroyFuture, newAsyncCloseCallback(clusterLock)); + if (serviceEntityCandidateReg != null) { + // we don't want to remove this instance from map + Futures.addCallback(destroyFuture, newAsyncCloseCallback(clusterLock, false)); + } else { + // we have to remove this ClusterSingletonServiceGroup instance from map + Futures.addCallback(destroyFuture, newAsyncCloseCallback(clusterLock, true)); + } /* * We wish to stop all possible EOS activities before we don't close * a close candidate registration that acts as a guard. So we don't want @@ -336,46 +352,33 @@ final class ClusterSingletonServiceGroupImpl

, E extends Generi /* * Help method for finalization every acquired functionality */ + @GuardedBy("clusterLock") private void closeResources(final boolean needReleaseLock, final boolean needCloseProvider) { - if (needReleaseLock) { - clusterLock.release(); - } if (needCloseProvider) { - final ListenableFuture> closeFutureList = this.closeClusterSingletonGroup(); - Futures.addCallback(closeFutureList, new FutureCallback>() { - - @Override - public void onSuccess(final List result) { - removeThisGroupFromProvider(null); - } - - @Override - public void onFailure(final Throwable t) { - removeThisGroupFromProvider(t); - } - }); + // The Game Over for this ClusterSingletonServiceGroup instance + if (serviceEntityCandidateReg != null) { + serviceEntityCandidateReg.close(); + serviceEntityCandidateReg = null; + } + // Remove instance immediately because actual state is follower or initialization + if (asyncCloseEntityCandidateReg == null) { + allServiceGroups.remove(clusterSingletonGroupIdentifier, this); + } } - } - /* - * Help method for final ClusterSingletonGroup removing - */ - protected final void removeThisGroupFromProvider(@Nullable final Throwable t) { - LOG.debug("Removing ClusterSingletonServiceGroup {}", clusterSingletonGroupIdentifier); - if (t != null) { - LOG.warn("Unexpected problem by closingResources ClusterSingletonServiceGroup {}", - clusterSingletonGroupIdentifier); + if (needReleaseLock) { + clusterLock.release(); } - allServiceGroups.remove(clusterSingletonGroupIdentifier, this); } /* * Help method creates FutureCallback for suspend Future */ - private FutureCallback> newAsyncCloseCallback(@Nullable final Semaphore semaphore) { - final Consumer closeEntityCandidateRegistration = (@Nullable final Throwable t) -> { - if (t != null) { - LOG.warn("Unexpected error closing service instance {}", clusterSingletonGroupIdentifier, t); + private FutureCallback> newAsyncCloseCallback(@Nullable final Semaphore semaphore, + final boolean isInCloseProcess) { + final Consumer closeEntityCandidateRegistration = (@Nullable final Throwable throwable) -> { + if (throwable != null) { + LOG.warn("Unexpected error closing service instance {}", clusterSingletonGroupIdentifier, throwable); } else { LOG.debug("Destroy service Instance {} is success", clusterSingletonGroupIdentifier); } @@ -383,10 +386,12 @@ final class ClusterSingletonServiceGroupImpl

, E extends Generi asyncCloseEntityCandidateReg.close(); asyncCloseEntityCandidateReg = null; } + if (isInCloseProcess) { + allServiceGroups.remove(clusterSingletonGroupIdentifier, this); + } if (semaphore != null) { semaphore.release(); } - allServiceGroups.remove(clusterSingletonGroupIdentifier, this); }; return new FutureCallback>() {