Search in sources :

Example 1 with TopologyChanged

use of org.infinispan.notifications.cachelistener.annotation.TopologyChanged in project wildfly by wildfly.

the class CacheRegistry method topologyChanged.

@TopologyChanged
public void topologyChanged(TopologyChangedEvent<Node, Map.Entry<K, V>> event) {
    if (event.isPre())
        return;
    ConsistentHash previousHash = event.getConsistentHashAtStart();
    List<Address> previousMembers = previousHash.getMembers();
    ConsistentHash hash = event.getConsistentHashAtEnd();
    List<Address> members = hash.getMembers();
    Address localAddress = event.getCache().getCacheManager().getAddress();
    // Determine which nodes have left the cache view
    Set<Address> addresses = new HashSet<>(previousMembers);
    addresses.removeAll(members);
    try {
        this.topologyChangeExecutor.submit(() -> {
            if (!addresses.isEmpty()) {
                // We're only interested in the entries for which we are the primary owner
                List<Node> nodes = addresses.stream().filter(address -> hash.locatePrimaryOwner(address).equals(localAddress)).map(address -> this.factory.createNode(address)).collect(Collectors.toList());
                if (!nodes.isEmpty()) {
                    Cache<Node, Map.Entry<K, V>> cache = this.cache.getAdvancedCache().withFlags(Flag.FORCE_SYNCHRONOUS);
                    Map<K, V> removed = new HashMap<>();
                    try (Batch batch = this.batcher.createBatch()) {
                        for (Node node : nodes) {
                            Map.Entry<K, V> old = cache.remove(node);
                            if (old != null) {
                                removed.put(old.getKey(), old.getValue());
                            }
                        }
                    } catch (CacheException e) {
                        ClusteringServerLogger.ROOT_LOGGER.registryPurgeFailed(e, this.cache.getCacheManager().toString(), this.cache.getName(), nodes);
                    }
                    // Invoke listeners outside above tx context
                    if (!removed.isEmpty()) {
                        this.notifyListeners(Event.Type.CACHE_ENTRY_REMOVED, removed);
                    }
                }
            } else {
                // This is a merge after cluster split: re-populate the cache registry with lost registry entries
                if (!previousMembers.contains(localAddress)) {
                    // If this node is not a member at merge start, its mapping is lost and needs to be recreated and listeners notified
                    try {
                        this.populateRegistry();
                        // Local cache events do not trigger notifications
                        this.notifyListeners(Event.Type.CACHE_ENTRY_CREATED, this.entry);
                    } catch (CacheException e) {
                        ClusteringServerLogger.ROOT_LOGGER.failedToRestoreLocalRegistryEntry(e, this.cache.getCacheManager().toString(), this.cache.getName());
                    }
                }
            }
        });
    } catch (RejectedExecutionException e) {
    // Executor was shutdown
    }
}
Also used : CacheEntryRemoved(org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved) TopologyChanged(org.infinispan.notifications.cachelistener.annotation.TopologyChanged) ClusteringLogger(org.jboss.as.clustering.logging.ClusteringLogger) HashMap(java.util.HashMap) Cache(org.infinispan.Cache) HashSet(java.util.HashSet) ClassLoaderThreadFactory(org.wildfly.clustering.service.concurrent.ClassLoaderThreadFactory) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) Map(java.util.Map) CacheEntryModified(org.infinispan.notifications.cachelistener.annotation.CacheEntryModified) CacheEntryRemovedEvent(org.infinispan.notifications.cachelistener.event.CacheEntryRemovedEvent) ThreadFactory(java.util.concurrent.ThreadFactory) NodeFactory(org.wildfly.clustering.group.NodeFactory) ExecutorService(java.util.concurrent.ExecutorService) Address(org.infinispan.remoting.transport.Address) JBossThreadFactory(org.jboss.threads.JBossThreadFactory) CacheException(org.infinispan.commons.CacheException) ConsistentHash(org.infinispan.distribution.ch.ConsistentHash) Batcher(org.wildfly.clustering.ee.Batcher) Registry(org.wildfly.clustering.registry.Registry) Group(org.wildfly.clustering.group.Group) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) PrivilegedAction(java.security.PrivilegedAction) Collectors(java.util.stream.Collectors) Executors(java.util.concurrent.Executors) TopologyChangedEvent(org.infinispan.notifications.cachelistener.event.TopologyChangedEvent) TimeUnit(java.util.concurrent.TimeUnit) CacheEntryCreated(org.infinispan.notifications.cachelistener.annotation.CacheEntryCreated) AbstractMap(java.util.AbstractMap) List(java.util.List) WildFlySecurityManager(org.wildfly.security.manager.WildFlySecurityManager) Flag(org.infinispan.context.Flag) KeyFilter(org.infinispan.filter.KeyFilter) CacheEntryEvent(org.infinispan.notifications.cachelistener.event.CacheEntryEvent) Batch(org.wildfly.clustering.ee.Batch) Event(org.infinispan.notifications.cachelistener.event.Event) Node(org.wildfly.clustering.group.Node) ClusteringServerLogger(org.wildfly.clustering.server.logging.ClusteringServerLogger) Collections(java.util.Collections) ConsistentHash(org.infinispan.distribution.ch.ConsistentHash) Address(org.infinispan.remoting.transport.Address) HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) CacheException(org.infinispan.commons.CacheException) Node(org.wildfly.clustering.group.Node) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) Batch(org.wildfly.clustering.ee.Batch) HashMap(java.util.HashMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) AbstractMap(java.util.AbstractMap) HashSet(java.util.HashSet) TopologyChanged(org.infinispan.notifications.cachelistener.annotation.TopologyChanged)

Example 2 with TopologyChanged

use of org.infinispan.notifications.cachelistener.annotation.TopologyChanged in project wildfly by wildfly.

the class SchedulerTopologyChangeListener method topologyChanged.

@TopologyChanged
public CompletionStage<Void> topologyChanged(TopologyChangedEvent<K, V> event) {
    Cache<K, V> cache = event.getCache();
    Address address = cache.getCacheManager().getAddress();
    ConsistentHash oldHash = event.getWriteConsistentHashAtStart();
    Set<Integer> oldSegments = oldHash.getMembers().contains(address) ? oldHash.getPrimarySegmentsForOwner(address) : Collections.emptySet();
    ConsistentHash newHash = event.getWriteConsistentHashAtEnd();
    Set<Integer> newSegments = newHash.getMembers().contains(address) ? newHash.getPrimarySegmentsForOwner(address) : Collections.emptySet();
    if (event.isPre()) {
        // If there are segments that we no longer own, then run cancellation task
        if (!newSegments.containsAll(oldSegments)) {
            Future<?> future = this.scheduleTaskFuture.getAndSet(null);
            if (future != null) {
                future.cancel(true);
            }
            return CompletableFuture.runAsync(() -> this.cancelTask.accept(new ConsistentHashLocality(cache, newHash)), this.executor);
        }
    } else {
        // If we have newly owned segments, then run schedule task
        if (!oldSegments.containsAll(newSegments)) {
            Locality oldLocality = new ConsistentHashLocality(cache, oldHash);
            Locality newLocality = new ConsistentHashLocality(cache, newHash);
            try {
                Future<?> future = this.scheduleTaskFuture.getAndSet(this.executor.submit(() -> this.scheduleTask.accept(oldLocality, newLocality)));
                if (future != null) {
                    future.cancel(true);
                }
            } catch (RejectedExecutionException e) {
            // Executor was shutdown
            }
        }
    }
    return CompletableFutures.completedNull();
}
Also used : ConsistentHash(org.infinispan.distribution.ch.ConsistentHash) Address(org.infinispan.remoting.transport.Address) Locality(org.wildfly.clustering.infinispan.spi.distribution.Locality) ConsistentHashLocality(org.wildfly.clustering.infinispan.spi.distribution.ConsistentHashLocality) ConsistentHashLocality(org.wildfly.clustering.infinispan.spi.distribution.ConsistentHashLocality) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) TopologyChanged(org.infinispan.notifications.cachelistener.annotation.TopologyChanged)

Example 3 with TopologyChanged

use of org.infinispan.notifications.cachelistener.annotation.TopologyChanged in project wildfly by wildfly.

the class CacheServiceProviderRegistry method topologyChanged.

@TopologyChanged
public void topologyChanged(TopologyChangedEvent<T, Set<Address>> event) {
    if (!event.isPre()) {
        ConsistentHash previousHash = event.getWriteConsistentHashAtStart();
        List<Address> previousMembers = previousHash.getMembers();
        ConsistentHash hash = event.getWriteConsistentHashAtEnd();
        List<Address> members = hash.getMembers();
        if (!members.equals(previousMembers)) {
            Cache<T, Set<Address>> cache = event.getCache().getAdvancedCache().withFlags(Flag.FORCE_SYNCHRONOUS);
            Address localAddress = cache.getCacheManager().getAddress();
            // Determine which nodes have left the cache view
            Set<Address> leftMembers = new HashSet<>(previousMembers);
            leftMembers.removeAll(members);
            if (!leftMembers.isEmpty()) {
                Locality locality = new ConsistentHashLocality(cache, hash);
                // We're only interested in the entries for which we are the primary owner
                Iterator<Address> addresses = leftMembers.iterator();
                while (addresses.hasNext()) {
                    if (!locality.isLocal(addresses.next())) {
                        addresses.remove();
                    }
                }
            }
            // If this is a merge after cluster split: Re-assert services for local member
            Set<T> localServices = !previousMembers.contains(localAddress) ? this.listeners.keySet() : Collections.emptySet();
            if (!leftMembers.isEmpty() || !localServices.isEmpty()) {
                Batcher<? extends Batch> batcher = this.batcher;
                Invoker invoker = this.invoker;
                try {
                    this.topologyChangeExecutor.submit(new Runnable() {

                        @Override
                        public void run() {
                            if (!leftMembers.isEmpty()) {
                                try (Batch batch = batcher.createBatch()) {
                                    try (CloseableIterator<Map.Entry<T, Set<Address>>> entries = cache.getAdvancedCache().withFlags(Flag.FORCE_WRITE_LOCK).entrySet().iterator()) {
                                        while (entries.hasNext()) {
                                            Map.Entry<T, Set<Address>> entry = entries.next();
                                            Set<Address> addresses = entry.getValue();
                                            if (addresses.removeAll(leftMembers)) {
                                                entry.setValue(addresses);
                                            }
                                        }
                                    }
                                }
                            }
                            if (!localServices.isEmpty()) {
                                for (T localService : localServices) {
                                    invoker.invoke(new RegisterLocalServiceTask(localService));
                                }
                            }
                        }
                    });
                } catch (RejectedExecutionException e) {
                // Executor is shutdown
                }
            }
        }
    }
}
Also used : ConsistentHash(org.infinispan.distribution.ch.ConsistentHash) CloseableIterator(org.infinispan.commons.util.CloseableIterator) TreeSet(java.util.TreeSet) HashSet(java.util.HashSet) Set(java.util.Set) Address(org.infinispan.remoting.transport.Address) Locality(org.wildfly.clustering.infinispan.spi.distribution.Locality) ConsistentHashLocality(org.wildfly.clustering.infinispan.spi.distribution.ConsistentHashLocality) ConsistentHashLocality(org.wildfly.clustering.infinispan.spi.distribution.ConsistentHashLocality) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) RetryingInvoker(org.wildfly.clustering.ee.infinispan.retry.RetryingInvoker) Invoker(org.wildfly.clustering.ee.Invoker) Batch(org.wildfly.clustering.ee.Batch) ExceptionRunnable(org.wildfly.common.function.ExceptionRunnable) ConcurrentMap(java.util.concurrent.ConcurrentMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) AbstractMap(java.util.AbstractMap) HashSet(java.util.HashSet) TopologyChanged(org.infinispan.notifications.cachelistener.annotation.TopologyChanged)

Example 4 with TopologyChanged

use of org.infinispan.notifications.cachelistener.annotation.TopologyChanged in project wildfly by wildfly.

the class CacheRegistry method topologyChanged.

@TopologyChanged
public CompletionStage<Void> topologyChanged(TopologyChangedEvent<Address, Map.Entry<K, V>> event) {
    if (!event.isPre()) {
        ConsistentHash previousHash = event.getWriteConsistentHashAtStart();
        List<Address> previousMembers = previousHash.getMembers();
        ConsistentHash hash = event.getWriteConsistentHashAtEnd();
        List<Address> members = hash.getMembers();
        if (!members.equals(previousMembers)) {
            Cache<Address, Map.Entry<K, V>> cache = event.getCache().getAdvancedCache().withFlags(Flag.FORCE_SYNCHRONOUS);
            Address localAddress = cache.getCacheManager().getAddress();
            // Determine which nodes have left the cache view
            Set<Address> leftMembers = new HashSet<>(previousMembers);
            leftMembers.removeAll(members);
            if (!leftMembers.isEmpty()) {
                Locality locality = new ConsistentHashLocality(cache, hash);
                // We're only interested in the entries for which we are the primary owner
                Iterator<Address> addresses = leftMembers.iterator();
                while (addresses.hasNext()) {
                    if (!locality.isLocal(addresses.next())) {
                        addresses.remove();
                    }
                }
            }
            // If this is a merge after cluster split: re-populate the cache registry with lost registry entries
            boolean restoreLocalEntry = !previousMembers.contains(localAddress);
            if (!leftMembers.isEmpty() || restoreLocalEntry) {
                try {
                    this.topologyChangeExecutor.submit(() -> {
                        if (!leftMembers.isEmpty()) {
                            Map<K, V> removed = new HashMap<>();
                            try {
                                for (Address leftMember : leftMembers) {
                                    Map.Entry<K, V> old = cache.remove(leftMember);
                                    if (old != null) {
                                        removed.put(old.getKey(), old.getValue());
                                    }
                                }
                            } catch (CacheException e) {
                                ClusteringServerLogger.ROOT_LOGGER.registryPurgeFailed(e, this.cache.getCacheManager().toString(), this.cache.getName(), leftMembers);
                            }
                            if (!removed.isEmpty()) {
                                this.notifyListeners(Event.Type.CACHE_ENTRY_REMOVED, removed);
                            }
                        }
                        if (restoreLocalEntry) {
                            // If this node is not a member at merge start, its mapping may have been lost and need to be recreated
                            try {
                                if (cache.put(localAddress, this.entry) == null) {
                                    // Local cache events do not trigger notifications
                                    this.notifyListeners(Event.Type.CACHE_ENTRY_CREATED, this.entry);
                                }
                            } catch (CacheException e) {
                                ClusteringServerLogger.ROOT_LOGGER.failedToRestoreLocalRegistryEntry(e, this.cache.getCacheManager().toString(), this.cache.getName());
                            }
                        }
                    });
                } catch (RejectedExecutionException e) {
                // Executor was shutdown
                }
            }
        }
    }
    return CompletableFutures.completedNull();
}
Also used : ConsistentHash(org.infinispan.distribution.ch.ConsistentHash) Address(org.infinispan.remoting.transport.Address) Locality(org.wildfly.clustering.infinispan.spi.distribution.Locality) ConsistentHashLocality(org.wildfly.clustering.infinispan.spi.distribution.ConsistentHashLocality) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) CacheException(org.infinispan.commons.CacheException) ConsistentHashLocality(org.wildfly.clustering.infinispan.spi.distribution.ConsistentHashLocality) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) AbstractMap(java.util.AbstractMap) HashSet(java.util.HashSet) TopologyChanged(org.infinispan.notifications.cachelistener.annotation.TopologyChanged)

Example 5 with TopologyChanged

use of org.infinispan.notifications.cachelistener.annotation.TopologyChanged in project wildfly by wildfly.

the class CacheGroup method topologyChanged.

@TopologyChanged
public CompletionStage<Void> topologyChanged(TopologyChangedEvent<?, ?> event) {
    if (!event.isPre()) {
        int viewId = event.getCache().getAdvancedCache().getRpcManager().getTransport().getViewId();
        Address localAddress = event.getCache().getCacheManager().getAddress();
        Membership previousMembership = new CacheMembership(localAddress, event.getWriteConsistentHashAtStart(), this);
        Membership membership = new CacheMembership(localAddress, event.getWriteConsistentHashAtEnd(), this);
        Boolean status = this.views.get(viewId);
        boolean merged = (status != null) ? status : false;
        for (Map.Entry<GroupListener, ExecutorService> entry : this.listeners.entrySet()) {
            GroupListener listener = entry.getKey();
            ExecutorService executor = entry.getValue();
            Runnable listenerTask = new Runnable() {

                @Override
                public void run() {
                    try {
                        listener.membershipChanged(previousMembership, membership, merged);
                    } catch (Throwable e) {
                        ClusteringServerLogger.ROOT_LOGGER.warn(e.getLocalizedMessage(), e);
                    }
                }
            };
            try {
                executor.submit(listenerTask);
            } catch (RejectedExecutionException e) {
            // Listener was unregistered
            }
        }
        // Purge obsolete views
        this.views.headMap(viewId).clear();
    }
    return CompletableFutures.completedNull();
}
Also used : JGroupsAddress(org.infinispan.remoting.transport.jgroups.JGroupsAddress) Address(org.infinispan.remoting.transport.Address) LocalModeAddress(org.infinispan.remoting.transport.LocalModeAddress) GroupListener(org.wildfly.clustering.group.GroupListener) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) DefaultExecutorService(org.jboss.as.clustering.context.DefaultExecutorService) ExecutorService(java.util.concurrent.ExecutorService) Membership(org.wildfly.clustering.group.Membership) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) TreeMap(java.util.TreeMap) SortedMap(java.util.SortedMap) TopologyChanged(org.infinispan.notifications.cachelistener.annotation.TopologyChanged)

Aggregations

RejectedExecutionException (java.util.concurrent.RejectedExecutionException)5 TopologyChanged (org.infinispan.notifications.cachelistener.annotation.TopologyChanged)5 Address (org.infinispan.remoting.transport.Address)5 Map (java.util.Map)4 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)4 ConsistentHash (org.infinispan.distribution.ch.ConsistentHash)4 AbstractMap (java.util.AbstractMap)3 HashSet (java.util.HashSet)3 ConsistentHashLocality (org.wildfly.clustering.infinispan.spi.distribution.ConsistentHashLocality)3 Locality (org.wildfly.clustering.infinispan.spi.distribution.Locality)3 HashMap (java.util.HashMap)2 Set (java.util.Set)2 ExecutorService (java.util.concurrent.ExecutorService)2 CacheException (org.infinispan.commons.CacheException)2 Batch (org.wildfly.clustering.ee.Batch)2 PrivilegedAction (java.security.PrivilegedAction)1 Collections (java.util.Collections)1 List (java.util.List)1 SortedMap (java.util.SortedMap)1 TreeMap (java.util.TreeMap)1