/* * 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.cache; import org.apache.geode.DataSerializable; import org.apache.geode.DataSerializer; import org.apache.geode.distributed.internal.membership.InternalRole; import org.apache.geode.distributed.Role; import org.apache.geode.internal.i18n.LocalizedStrings; import java.io.*; import java.util.*; /** * Configuration attributes for defining reliability requirements and behavior for a * <code>Region</code>. * * <p> * <code>MembershipAttributes</code> provides options for configuring a <code>Region</code> to * require one or more membership roles to be present in the system for reliable access to the * <code>Region</code>. Each {@link Role} is a user defined string name, such as Producer or Backup * or FooProducer. * </p> * * <p> * The {@link LossAction} defines the behavior when one or more required roles are missing. * </p> * * <p> * The {@link ResumptionAction} specifies the action to be taken when reliability resumes. * </p> * * <p> * <code>MembershipAttributes</code> have no effect unless one or more required roles are specified. * These attributes are immutable after the <code>Region</code> has been created. * </p> * * @deprecated this feature is scheduled to be removed */ public class MembershipAttributes implements DataSerializable, Externalizable { /** * Array of required role names by this process for reliable access to the region */ private /* final */ Set<Role> requiredRoles; /** * The configuration defining how this process behaves when there are missing required roles */ private /* final */ LossAction lossAction; /** * The action to take when missing required roles return to the system */ private /* final */ ResumptionAction resumptionAction; /** * Creates a new <code>MembershipAttributes</code> with the default configuration of no required * roles. */ public MembershipAttributes() { this.requiredRoles = Collections.emptySet(); this.lossAction = LossAction.FULL_ACCESS; this.resumptionAction = ResumptionAction.NONE; } /** * Creates a new <code>MembershipAttributes</code> with the specified required role names. * Reliability policy will default to {@linkplain LossAction#NO_ACCESS NO_ACCESS}, and resumption * action will default to {@linkplain ResumptionAction#REINITIALIZE REINITIALIZE}. * * @param requiredRoles array of role names required by this process for reliable access to the * region * @throws IllegalArgumentException if no requiredRoles are specified */ public MembershipAttributes(String[] requiredRoles) { this(requiredRoles, LossAction.NO_ACCESS, ResumptionAction.REINITIALIZE); } /** * Creates a new <code>MembershipAttributes</code> with the specified required role names, * reliability policy, and resumption action. * * @param requiredRoles array of role names required by this process for reliable access to the * region * @param lossAction the configuration defining how this process behaves when there are missing * required roles * @param resumptionAction the action to take when missing required roles return to the system * @throws IllegalArgumentException if the resumptionAction is incompatible with the lossAction or * if no requiredRoles are specified */ public MembershipAttributes(String[] requiredRoles, LossAction lossAction, ResumptionAction resumptionAction) { this.requiredRoles = toRoleSet(requiredRoles); if (this.requiredRoles.isEmpty()) { throw new IllegalArgumentException( LocalizedStrings.MembershipAttributes_ONE_OR_MORE_REQUIRED_ROLES_MUST_BE_SPECIFIED .toLocalizedString()); } this.lossAction = lossAction; this.resumptionAction = resumptionAction; } /** * Returns the set of {@linkplain org.apache.geode.distributed.Role Role}s that are required for * the reliability of this region. */ public Set<Role> getRequiredRoles() { return Collections.unmodifiableSet(this.requiredRoles); } /** * Returns true if there are one or more required roles specified. */ public boolean hasRequiredRoles() { return !this.requiredRoles.isEmpty(); } /** * Returns the reliability policy that describes behavior if any required roles are missing. */ public LossAction getLossAction() { return this.lossAction; } /** * Returns the resumption action that describes behavior when */ public ResumptionAction getResumptionAction() { return this.resumptionAction; } private final Set<Role> toRoleSet(String[] roleNames) { if (roleNames == null || roleNames.length == 0) { return Collections.emptySet(); } Set<Role> roleSet = new HashSet<Role>(); for (int i = 0; i < roleNames.length; i++) { roleSet.add(InternalRole.getRole(roleNames[i])); } return roleSet; } /** * Indicates whether some other object is "equal to" this one. * * @param other the reference object with which to compare. * @return true if this object is the same as the obj argument; false otherwise. */ @Override public boolean equals(Object other) { if (other == this) return true; if (other == null) return false; if (!(other instanceof MembershipAttributes)) return false; final MembershipAttributes that = (MembershipAttributes) other; if (this.requiredRoles != that.requiredRoles && !(this.requiredRoles != null && this.requiredRoles.equals(that.requiredRoles))) return false; if (this.lossAction != that.lossAction && !(this.lossAction != null && this.lossAction.equals(that.lossAction))) return false; if (this.resumptionAction != that.resumptionAction && !(this.resumptionAction != null && this.resumptionAction.equals(that.resumptionAction))) return false; return true; } /** * Returns a hash code for the object. This method is supported for the benefit of hashtables such * as those provided by java.util.Hashtable. * * @return the integer 0 if description is null; otherwise a unique integer. */ @Override public int hashCode() { int result = 17; final int mult = 37; result = mult * result + (this.requiredRoles == null ? 0 : this.requiredRoles.hashCode()); result = mult * result + (this.lossAction == null ? 0 : this.lossAction.hashCode()); result = mult * result + (this.resumptionAction == null ? 0 : this.resumptionAction.hashCode()); return result; } /** * Returns a string representation of the object. * * @return a string representation of the object */ @Override public String toString() { if (!hasRequiredRoles()) { return "RequiredRoles(none)"; } else { final StringBuffer sb = new StringBuffer(); sb.append("RequiredRoles("); boolean comma = false; for (Iterator<Role> iter = this.requiredRoles.iterator(); iter.hasNext();) { if (comma) sb.append(","); Role role = iter.next(); sb.append(role.getName()); comma = true; } sb.append("); Policy:"); sb.append(this.lossAction.toString()); sb.append("; Action:"); sb.append(this.resumptionAction.toString()); return sb.toString(); } } public void toData(DataOutput out) throws IOException { String[] names = new String[this.requiredRoles.size()]; Iterator<Role> iter = this.requiredRoles.iterator(); for (int i = 0; i < names.length; i++) { names[i] = iter.next().getName(); } DataSerializer.writeStringArray(names, out); out.writeByte(this.lossAction.ordinal); out.writeByte(this.resumptionAction.ordinal); } public void fromData(DataInput in) throws IOException, ClassNotFoundException { this.requiredRoles = toRoleSet(DataSerializer.readStringArray(in)); this.lossAction = LossAction.fromOrdinal(in.readByte()); this.resumptionAction = ResumptionAction.fromOrdinal(in.readByte()); } public void writeExternal(ObjectOutput out) throws IOException { // added to fix bug 36619 toData(out); } public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { // added to fix bug 36619 fromData(in); } }