All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.infinispan.topology.ClusterCacheStatus Maven / Gradle / Ivy

There is a newer version: 15.1.3.Final
Show newest version
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors
 * as indicated by the @author tags. All rights reserved.
 * See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * of the GNU Lesser General Public License, v. 2.1.
 * This program is distributed in the hope that it will be useful, but WITHOUT A
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public License,
 * v.2.1 along with this distribution; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA  02110-1301, USA.
 */

package org.infinispan.topology;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.infinispan.distribution.ch.ConsistentHash;
import org.infinispan.remoting.transport.Address;
import org.infinispan.util.Immutables;
import org.infinispan.util.InfinispanCollections;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;

/**
* Keeps track of a cache's status: members, current/pending consistent hashes, and rebalance status
*
* @author Dan Berindei
* @since 5.2
*/
public class ClusterCacheStatus {
   private static final Log log = LogFactory.getLog(ClusterCacheStatus.class);
   private static boolean trace = log.isTraceEnabled();

   private final String cacheName;
   private final CacheJoinInfo joinInfo;
   // Cache members, some of which may not have received state yet
   private volatile List
members; // Cache members that have not yet received state. Always included in the members list. private volatile List
joiners; // Cache topology. Its consistent hashes contain only members that did receive/are receiving state // The members of both consistent hashes must be included in the members list. private volatile CacheTopology cacheTopology; private volatile RebalanceConfirmationCollector rebalanceStatus; public ClusterCacheStatus(String cacheName, CacheJoinInfo joinInfo) { this.cacheName = cacheName; this.joinInfo = joinInfo; this.cacheTopology = new CacheTopology(-1, null, null); this.members = InfinispanCollections.emptyList(); this.joiners = InfinispanCollections.emptyList(); if (trace) log.tracef("Cache %s initialized, join info is %s", cacheName, joinInfo); } public CacheJoinInfo getJoinInfo() { return joinInfo; } public List
getMembers() { return members; } public boolean hasMembers() { return !members.isEmpty(); } public List
getJoiners() { return joiners; } public boolean hasJoiners() { return !joiners.isEmpty(); } public void setMembers(List
newMembers) { synchronized (this) { members = Immutables.immutableListCopy(newMembers); ConsistentHash currentCH = cacheTopology.getCurrentCH(); if (currentCH != null) { joiners = immutableRemoveAll(members, currentCH.getMembers()); } else { joiners = members; } if (trace) log.tracef("Cache %s members list updated, members = %s, joiners = %s", cacheName, members, joiners); } } /** * @return {@code true} if the joiner was not already a member, {@code false} otherwise */ public boolean addMember(Address joiner) { synchronized (this) { if (members.contains(joiner)) { if (trace) log.tracef("Trying to add node %s to cache %s, but it is already a member: " + "members = %s, joiners = %s", joiner, cacheName, members, joiners); return false; } members = immutableAdd(members, joiner); joiners = immutableAdd(joiners, joiner); if (trace) log.tracef("Added joiner %s to cache %s: members = %s, joiners = %s", joiner, cacheName, members, joiners); return true; } } /** * @return {@code true} if the leaver was a member, {@code false} otherwise */ public boolean removeMember(Address leaver) { synchronized (this) { if (!members.contains(leaver)) { if (trace) log.tracef("Trying to remove node %s from cache %s, but it is not a member: " + "members = %s", leaver, cacheName, members); return false; } members = immutableRemove(members, leaver); joiners = immutableRemove(joiners, leaver); if (trace) log.tracef("Removed node %s from cache %s: members = %s, joiners = %s", leaver, cacheName, members, joiners); return true; } } /** * @return {@code true} if the members list has changed, {@code false} otherwise */ public boolean updateClusterMembers(List
newClusterMembers) { synchronized (this) { if (newClusterMembers.containsAll(members)) { if (trace) log.tracef("Cluster members updated for cache %s, no leavers detected: " + "cache members = %s", cacheName, newClusterMembers); return false; } members = immutableRetainAll(members, newClusterMembers); joiners = immutableRetainAll(joiners, newClusterMembers); if (trace) log.tracef("Cluster members updated for cache %s: members = %s, joiners = %s", cacheName, members, joiners); return true; } } public CacheTopology getCacheTopology() { return cacheTopology; } public void updateCacheTopology(CacheTopology newTopology) { synchronized (this) { this.cacheTopology = newTopology; if (!members.containsAll(cacheTopology.getMembers())) { throw new IllegalStateException(String.format("Trying to set a topology with invalid members " + "for cache %s: members = %s, topology = %s", cacheName, members, cacheTopology)); } // update the joiners list if (newTopology.getCurrentCH() != null) { joiners = immutableRemoveAll(members, newTopology.getCurrentCH().getMembers()); } if (trace) log.tracef("Cache %s topology updated: members = %s, joiners = %s, topology = %s", cacheName, members, joiners, cacheTopology); } } public boolean needConsistentHashUpdate() { // The list of current members is always included in the list of pending members, // so we only need to check one list. // Also returns false if both CHs are null return !members.containsAll(cacheTopology.getMembers()); } public List
pruneInvalidMembers(List
possibleMembers) { return immutableRetainAll(possibleMembers, members); } public boolean isRebalanceInProgress() { return rebalanceStatus != null; } /** * @return {@code true} if a rebalance was started, {@code false} if a rebalance was already in progress */ public boolean startRebalance(CacheTopology newTopology) { synchronized (this) { if (rebalanceStatus != null) return false; rebalanceStatus = new RebalanceConfirmationCollector(cacheName, newTopology.getTopologyId(), newTopology.getMembers()); this.cacheTopology = newTopology; return true; } } /** * @return {@code true} if this was the last confirmation needed, {@code false} if more confirmations * are needed or if the rebalance was already confirmed in another way (e.g. members list update) */ public boolean confirmRebalanceOnNode(Address member, int receivedTopologyId) { synchronized (this) { if (rebalanceStatus == null) return false; return rebalanceStatus.confirmRebalance(member, receivedTopologyId); } } /** * Should be called after the members list was updated in any other way ({@link #removeMember(Address)}, * {@link #updateClusterMembers} etc.) * * @return {@code true} if the rebalance was confirmed with this update, {@code false} if more confirmations * are needed or if the rebalance was already confirmed in another way (e.g. the last member confirmed) */ public boolean updateRebalanceMembersList() { synchronized (this) { if (rebalanceStatus == null) return false; return rebalanceStatus.updateMembers(members); } } public void endRebalance() { synchronized (this) { if (rebalanceStatus == null) { throw new IllegalStateException("Can't end rebalance, there is no rebalance in progress"); } rebalanceStatus = null; } } // Helpers for working with immutable lists private List immutableAdd(List list, T element) { List result = new ArrayList(list); result.add(element); return Collections.unmodifiableList(result); } private List immutableRemove(List list, T element) { List result = new ArrayList(list); result.remove(element); return Collections.unmodifiableList(result); } private List immutableRemoveAll(List list, List otherList) { List result = new ArrayList(list); result.removeAll(otherList); return Collections.unmodifiableList(result); } private List immutableRetainAll(List list, List otherList) { List result = new ArrayList(list); result.retainAll(otherList); return Collections.unmodifiableList(result); } @Override public String toString() { return "ClusterCacheStatus{" + "cacheName='" + cacheName + '\'' + ", members=" + members + ", joiners=" + joiners + ", cacheTopology=" + cacheTopology + ", rebalanceStatus=" + rebalanceStatus + '}'; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy