blob: 2a9ecb953d31691277a01a5411f22a822d733910 [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.internal.cache;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.apache.geode.DataSerializer;
import org.apache.geode.cache.EvictionAttributes;
import org.apache.geode.cache.ExpirationAttributes;
import org.apache.geode.cache.PartitionAttributes;
import org.apache.geode.cache.Scope;
import org.apache.geode.cache.partition.PartitionListener;
import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
import org.apache.geode.internal.ExternalizableDSFID;
import org.apache.geode.internal.InternalDataSerializer;
import org.apache.geode.internal.Version;
import org.apache.geode.internal.util.Versionable;
import org.apache.geode.internal.util.VersionedArrayList;
/**
* Maintains configuration information for a PartitionedRegion. Instances are stored in the
* allPartitionedRegion.
*/
public class PartitionRegionConfig extends ExternalizableDSFID implements Versionable {
private int prId;
private PartitionAttributesImpl pAttrs;
private Scope scope = null;
/** Nodes participating in this PartitionedRegion */
private VersionedArrayList nodes = null;
/**
* Flag to indicate whether the PartitionedRegion's destruction responsibility is taken up by
* someone
*/
private boolean isDestroying = false;
/**
* Flag to indicate whether this region has been created on all of the members that host the
* region that this region is colocated with. Once a region is in this state, new members will
* have to create this region before they can host any data for the colocated regions
*/
private boolean isColocationComplete;
private volatile boolean firstDataStoreCreated = false;
/**
* The full path of the region. Used for resolving colocation chains.
*/
private String fullPath = null;
private String partitionResolver = null;
private String colocatedWith = null;
private EvictionAttributes ea = new EvictionAttributesImpl();
private ExpirationAttributes regionTimeToLive = null;
private ExpirationAttributes regionIdleTimeout = null;
private ExpirationAttributes entryTimeToLive = null;
private ExpirationAttributes entryIdleTimeout = null;
private Set<FixedPartitionAttributesImpl> elderFPAs = null;
private ArrayList<String> partitionListenerClassNames = new ArrayList<String>();
public void setGatewaySenderIds(Set<String> gatewaySenderIds) {
this.gatewaySenderIds = Collections.unmodifiableSet(gatewaySenderIds);
}
private Set<String> gatewaySenderIds = Collections.emptySet();
/**
* Default constructor for DataSerializer
*/
public PartitionRegionConfig() {
// nothing
}
PartitionRegionConfig(int prId, String path, PartitionAttributes prAtt, Scope sc,
EvictionAttributes ea, final ExpirationAttributes regionIdleTimeout,
final ExpirationAttributes regionTimeToLive, final ExpirationAttributes entryIdleTimeout,
final ExpirationAttributes entryTimeToLive, Set<String> gatewaySenderIds) {
this.prId = prId;
this.pAttrs = (PartitionAttributesImpl) prAtt;
this.scope = sc;
this.isDestroying = false;
this.nodes = new VersionedArrayList();
if (prAtt.getPartitionResolver() != null) {
this.partitionResolver = prAtt.getPartitionResolver().getClass().getName();
}
this.colocatedWith = prAtt.getColocatedWith();
if (prAtt.getLocalMaxMemory() > 0) {
this.ea = ea;
this.firstDataStoreCreated = prAtt.getLocalMaxMemory() > 0;
}
this.regionIdleTimeout = regionIdleTimeout;
this.regionTimeToLive = regionTimeToLive;
this.entryIdleTimeout = entryIdleTimeout;
this.entryTimeToLive = entryTimeToLive;
this.isColocationComplete = colocatedWith == null;
this.fullPath = path;
this.elderFPAs = new LinkedHashSet<FixedPartitionAttributesImpl>();
PartitionListener[] prListeners = prAtt.getPartitionListeners();
if (prListeners != null && prListeners.length != 0) {
for (int i = 0; i < prListeners.length; i++) {
PartitionListener listener = prListeners[i];
this.partitionListenerClassNames.add(listener.getClass().getName());
}
}
this.gatewaySenderIds = gatewaySenderIds;
}
public Set<String> getGatewaySenderIds() {
return gatewaySenderIds;
}
/**
* Returns a the list of nodes that participate in the PartitionedRegion
*
* @return a copy of the list of nodes that the caller is free to modify
*/
Set<Node> getNodes() {
if (this.nodes != null) {
return nodes.getListCopy();
}
return null;
}
/**
* Return a safe, light weight size of the nodes
*
* @return number of VMs that participate in the PartitionedRegion
*/
int getNumberOfNodes() {
if (this.nodes != null) {
return nodes.size();
} else {
return 0;
}
}
/**
* Safely checks to see if the provided Node participates in the PartitionedRegion return true if
* the Node participates in the PartitionedRegion
*/
boolean containsNode(Node check) {
if (this.nodes != null) {
return nodes.contains(check);
} else {
return false;
}
}
/**
* Safely checks to see if the provided Node participates in the PartitionedRegion return true if
* the Node participates in the PartitionedRegion
*/
boolean containsMember(InternalDistributedMember memberId) {
if (this.nodes != null) {
for (Node node : this.nodes) {
if (memberId.equals(node.getMemberId())) {
return true;
}
}
}
return false;
}
/**
* Adds a new node to this configuration
*/
void addNode(Node newNode) {
if (nodes != null) {
nodes.add(newNode);
}
}
/**
* Removes a node from this configuration
*/
void removeNode(Node targetNode) {
if (nodes != null) {
nodes.remove(targetNode);
}
}
public int getPRId() {
return prId;
}
PartitionAttributes getPartitionAttrs() {
return pAttrs;
}
Scope getScope() {
return scope;
}
@Override
public String toString() {
String ret = "PartitionRegionConfig@" + System.identityHashCode(this) + ";prId=" + this.prId
+ ";scope=" + this.scope + ";partition attributes=" + this.pAttrs + ";partitionResolver="
+ this.partitionResolver + ";colocatedWith=" + this.colocatedWith + ";eviction attributes="
+ this.ea + ";regionIdleTimeout= " + this.regionIdleTimeout + ";regionTimeToLive= "
+ this.regionTimeToLive + ";entryIdleTimeout= " + this.entryIdleTimeout
+ ";entryTimeToLive= " + this.entryTimeToLive + "'elderFPAs=" + elderFPAs
+ "'gatewaySenderIds=" + gatewaySenderIds + ";nodes=";
if (this.nodes != null) {
return ret + nodes;
} else {
return ret + "null";
}
}
@Override
public int getDSFID() {
return PARTITION_REGION_CONFIG;
}
@Override
public void toData(DataOutput out) throws IOException {
out.writeInt(this.prId);
out.writeByte(this.scope.ordinal);
InternalDataSerializer.invokeToData(this.pAttrs, out);
out.writeBoolean(this.isDestroying);
out.writeBoolean(this.isColocationComplete);
InternalDataSerializer.invokeToData(this.nodes, out);
DataSerializer.writeString(this.partitionResolver, out);
DataSerializer.writeString(this.colocatedWith, out);
DataSerializer.writeString(this.fullPath, out);
InternalDataSerializer.invokeToData(this.ea, out);
InternalDataSerializer.invokeToData(this.regionIdleTimeout, out);
InternalDataSerializer.invokeToData(this.regionTimeToLive, out);
InternalDataSerializer.invokeToData(this.entryIdleTimeout, out);
InternalDataSerializer.invokeToData(this.entryTimeToLive, out);
out.writeBoolean(this.firstDataStoreCreated);
DataSerializer.writeObject(elderFPAs, out);
DataSerializer.writeArrayList(this.partitionListenerClassNames, out);
if (this.gatewaySenderIds.isEmpty()) {
DataSerializer.writeObject(null, out);
} else {
DataSerializer.writeObject(this.gatewaySenderIds, out);
}
}
@Override
public void fromData(DataInput in) throws IOException, ClassNotFoundException {
this.prId = in.readInt();
this.scope = Scope.fromOrdinal(in.readByte());
this.pAttrs = PartitionAttributesImpl.createFromData(in);
this.isDestroying = in.readBoolean();
this.isColocationComplete = in.readBoolean();
this.nodes = new VersionedArrayList();
InternalDataSerializer.invokeFromData(this.nodes, in);
this.partitionResolver = DataSerializer.readString(in);
this.colocatedWith = DataSerializer.readString(in);
this.fullPath = DataSerializer.readString(in);
this.ea = EvictionAttributesImpl.createFromData(in);
this.regionIdleTimeout = ExpirationAttributes.createFromData(in);
this.regionTimeToLive = ExpirationAttributes.createFromData(in);
this.entryIdleTimeout = ExpirationAttributes.createFromData(in);
this.entryTimeToLive = ExpirationAttributes.createFromData(in);
this.firstDataStoreCreated = in.readBoolean();
this.elderFPAs = DataSerializer.readObject(in);
if (this.elderFPAs == null) {
this.elderFPAs = new LinkedHashSet<FixedPartitionAttributesImpl>();
}
this.partitionListenerClassNames = DataSerializer.readArrayList(in);
this.gatewaySenderIds = DataSerializer.readObject(in);
if (this.gatewaySenderIds == null) {
this.gatewaySenderIds = Collections.emptySet();
}
}
/**
* This method returns true is a node has taken a responsibility of destroying the
* PartitionedRegion globally
*
* @return true, if a node has taken a responsibility of destroying the PartitionedRegion globally
* else it returns false
*/
boolean getIsDestroying() {
return isDestroying;
}
/**
* This method sets the isDestroying flag to true, to indicate that the PartitionedRegion's
* destruction responsibility is taken up by a node.
*
*/
void setIsDestroying() {
isDestroying = true;
}
void setColocationComplete(PartitionedRegion partitionedRegion) {
this.isColocationComplete = true;
partitionedRegion.executeColocationCallbacks();
}
public void setEntryIdleTimeout(ExpirationAttributes idleTimeout) {
this.entryIdleTimeout = idleTimeout;
}
public void setEntryTimeToLive(ExpirationAttributes timeToLive) {
this.entryTimeToLive = timeToLive;
}
public boolean isGreaterNodeListVersion(final PartitionRegionConfig other) {
return this.nodes.isNewerThan(other.nodes);
}
@Override
public Comparable getVersion() {
return this.nodes.getVersion();
}
@Override
public boolean isNewerThan(Versionable other) {
return this.nodes.isNewerThan(other);
}
@Override
public boolean isSame(Versionable other) {
return this.nodes.isSame(other);
}
@Override
public boolean isOlderThan(Versionable other) {
return this.nodes.isOlderThan(other);
}
public String getResolverClassName() {
return this.partitionResolver;
}
public String getColocatedWith() {
return colocatedWith;
}
public String getFullPath() {
return fullPath;
}
public boolean isColocationComplete() {
return isColocationComplete;
}
public EvictionAttributes getEvictionAttributes() {
return ea;
}
public ExpirationAttributes getEntryIdleTimeout() {
return entryIdleTimeout;
}
public ExpirationAttributes getEntryTimeToLive() {
return entryTimeToLive;
}
public ExpirationAttributes getRegionIdleTimeout() {
return regionIdleTimeout;
}
public ExpirationAttributes getRegionTimeToLive() {
return regionTimeToLive;
}
public boolean isFirstDataStoreCreated() {
return firstDataStoreCreated;
}
public void addFPAs(List<FixedPartitionAttributesImpl> fpaList) {
if (this.elderFPAs != null) {
this.elderFPAs.addAll(fpaList);
}
}
public Set<FixedPartitionAttributesImpl> getElderFPAs() {
return this.elderFPAs;
}
public ArrayList<String> getPartitionListenerClassNames() {
return partitionListenerClassNames;
}
public boolean hasSameDataStoreMembers(PartitionRegionConfig prConfig) {
for (Node node : getNodes()) {
if (!prConfig.containsMember(node.getMemberId())
&& ((node.getPRType() == Node.ACCESSOR_DATASTORE)
|| (node.getPRType() == Node.FIXED_PR_DATASTORE))) {
return false;
}
}
for (Node node : prConfig.getNodes()) {
if (!this.containsMember(node.getMemberId()) && ((node.getPRType() == Node.ACCESSOR_DATASTORE)
|| (node.getPRType() == Node.FIXED_PR_DATASTORE))) {
return false;
}
}
return true;
}
@Override
public Version[] getSerializationVersions() {
return null;
}
public void setDatastoreCreated(EvictionAttributes evictionAttributes) {
this.firstDataStoreCreated = true;
this.ea = evictionAttributes;
}
}