blob: 5326b60ff8d81cc2ffe67d7a7f9fb1346da0f769 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.geode.distributed.internal.membership;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.geode.UnmodifiableException;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.distributed.internal.ClusterDistributionManager;
/**
* The MembershipView class represents a membership view. Note that this class is not synchronized,
* so take that under advisement if you decide to modify a view with add() or remove().
*/
public class MembershipView {
private int viewId;
private List<InternalDistributedMember> members;
private Set<InternalDistributedMember> shutdownMembers;
private Set<InternalDistributedMember> crashedMembers;
private InternalDistributedMember creator;
private Set<InternalDistributedMember> hashedMembers;
private volatile boolean unmodifiable;
public MembershipView() {
viewId = -1;
members = new ArrayList<>(0);
this.hashedMembers = new HashSet<>(members);
shutdownMembers = Collections.emptySet();
crashedMembers = new HashSet<>();
creator = null;
}
public MembershipView(InternalDistributedMember creator, int viewId,
List<InternalDistributedMember> members) {
this.viewId = viewId;
this.members = new ArrayList<>(members);
hashedMembers = new HashSet<>(this.members);
shutdownMembers = new HashSet<>();
crashedMembers = Collections.emptySet();
this.creator = creator;
}
/**
* Create a new view with the contents of the given view and the specified view ID
*/
public MembershipView(MembershipView other, int viewId) {
this.creator = other.creator;
this.viewId = viewId;
this.members = new ArrayList<>(other.members);
this.hashedMembers = new HashSet<>(other.members);
this.shutdownMembers = new HashSet<>(other.shutdownMembers);
this.crashedMembers = new HashSet<>(other.crashedMembers);
}
public MembershipView(InternalDistributedMember creator, int viewId,
List<InternalDistributedMember> mbrs, Set<InternalDistributedMember> shutdowns,
Set<InternalDistributedMember> crashes) {
this.creator = creator;
this.viewId = viewId;
this.members = mbrs;
this.hashedMembers = new HashSet<>(mbrs);
this.shutdownMembers = shutdowns;
this.crashedMembers = crashes;
}
public void makeUnmodifiable() {
unmodifiable = true;
}
public int getViewId() {
return this.viewId;
}
public InternalDistributedMember getCreator() {
return this.creator;
}
public void setCreator(InternalDistributedMember creator) {
this.creator = creator;
}
public void setViewId(int viewId) {
this.viewId = viewId;
}
public List<InternalDistributedMember> getMembers() {
return Collections.unmodifiableList(this.members);
}
/**
* return members that are i this view but not the given old view
*/
public List<InternalDistributedMember> getNewMembers(MembershipView olderView) {
List<InternalDistributedMember> result = new ArrayList<>(members);
result.removeAll(olderView.getMembers());
return result;
}
public Object get(int i) {
return this.members.get(i);
}
public void add(InternalDistributedMember mbr) {
if (unmodifiable) {
throw new UnmodifiableException("this membership view is not modifiable");
}
this.hashedMembers.add(mbr);
this.members.add(mbr);
}
public boolean remove(InternalDistributedMember mbr) {
if (unmodifiable) {
throw new UnmodifiableException("this membership view is not modifiable");
}
this.hashedMembers.remove(mbr);
return this.members.remove(mbr);
}
public void removeAll(Collection<InternalDistributedMember> ids) {
if (unmodifiable) {
throw new UnmodifiableException("this membership view is not modifiable");
}
this.hashedMembers.removeAll(ids);
ids.forEach(this::remove);
}
public boolean contains(DistributedMember mbr) {
assert mbr instanceof InternalDistributedMember;
return this.hashedMembers.contains(mbr);
}
public int size() {
return this.members.size();
}
public InternalDistributedMember getLeadMember() {
for (InternalDistributedMember mbr : this.members) {
if (mbr.getVmKind() == ClusterDistributionManager.NORMAL_DM_TYPE) {
return mbr;
}
}
return null;
}
/**
* Returns the ID from this view that is equal to the argument. If no such ID exists the argument
* is returned.
*/
public synchronized InternalDistributedMember getCanonicalID(InternalDistributedMember id) {
if (hashedMembers.contains(id)) {
for (InternalDistributedMember m : this.members) {
if (id.equals(m)) {
return m;
}
}
}
return id;
}
public InternalDistributedMember getCoordinator() {
for (InternalDistributedMember addr : members) {
if (addr.getMemberData().isPreferredForCoordinator()) {
return addr;
}
}
if (members.size() > 0) {
return members.get(0);
}
return null;
}
public Set<InternalDistributedMember> getShutdownMembers() {
return this.shutdownMembers;
}
public Set<InternalDistributedMember> getCrashedMembers() {
return this.crashedMembers;
}
public String toString() {
InternalDistributedMember lead = getLeadMember();
StringBuilder sb = new StringBuilder(200);
sb.append("View[").append(creator).append('|').append(viewId).append("] members: [");
boolean first = true;
for (InternalDistributedMember mbr : this.members) {
if (!first)
sb.append(", ");
sb.append(mbr);
if (mbr == lead) {
sb.append("{lead}");
}
first = false;
}
if (!this.shutdownMembers.isEmpty()) {
sb.append("] shutdown: [");
first = true;
for (InternalDistributedMember mbr : this.shutdownMembers) {
if (!first)
sb.append(", ");
sb.append(mbr);
first = false;
}
}
if (!this.crashedMembers.isEmpty()) {
sb.append("] crashed: [");
first = true;
for (InternalDistributedMember mbr : this.crashedMembers) {
if (!first)
sb.append(", ");
sb.append(mbr);
first = false;
}
}
sb.append("]");
return sb.toString();
}
@Override
public synchronized boolean equals(Object other) {
if (other == this) {
return true;
}
if (other instanceof MembershipView) {
return this.members.equals(((MembershipView) other).getMembers());
}
return false;
}
@Override
public synchronized int hashCode() {
return this.members.hashCode();
}
}