com.gemstone.gemfire.internal.cache.DestroyPartitionedRegionMessage Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gemfire-core Show documentation
Show all versions of gemfire-core Show documentation
SnappyData store based off Pivotal GemFireXD
/*
* Copyright (c) 2010-2015 Pivotal Software, Inc. All rights reserved.
*
* Licensed 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. See accompanying
* LICENSE file.
*/
package com.gemstone.gemfire.internal.cache;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Set;
import com.gemstone.gemfire.DataSerializer;
import com.gemstone.gemfire.cache.CacheException;
import com.gemstone.gemfire.cache.Operation;
import com.gemstone.gemfire.distributed.internal.DistributionAdvisor;
import com.gemstone.gemfire.distributed.internal.DistributionManager;
import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
import com.gemstone.gemfire.distributed.internal.ReplyException;
import com.gemstone.gemfire.distributed.internal.ReplyMessage;
import com.gemstone.gemfire.distributed.internal.ReplyProcessor21;
import com.gemstone.gemfire.i18n.LogWriterI18n;
import com.gemstone.gemfire.internal.Assert;
import com.gemstone.gemfire.internal.cache.PartitionedRegion;
import com.gemstone.gemfire.internal.cache.RegionEventImpl;
import com.gemstone.gemfire.internal.cache.partitioned.PartitionMessage;
import com.gemstone.gemfire.internal.cache.partitioned.RegionAdvisor;
import com.gemstone.gemfire.internal.cache.partitioned.RegionAdvisor.PartitionProfile;
/**
* This message is sent for two purposes
* 1) To destroy the
* {@link com.gemstone.gemfire.internal.cache.PartitionedRegion} for all members
* specified (typically sent to all members that have the
* PartitionedRegion
defined.)
* 2) To inform the other nodes that {@link com.gemstone.gemfire.internal.cache.PartitionedRegion} is closed/locally destroyed or cache is closed on a node
* This results in updating of the RegionAdvisor of the remote nodes.
*
* Sending this message should flush all previous
* {@link com.gemstone.gemfire.cache.Region} operations, which means this
* operation should not over-ride
* {@link com.gemstone.gemfire.internal.cache.partitioned.PartitionMessage#getProcessorId()}. It is critical
* guarantee delivery of events sent prior to this message.
* A standard {@link ReplyMessage} is used to send the reply, however any exception that it carries
* is ignored, preventing interuption after sending this message.
*
* @author Mitch Thomas
* @since 5.0
*/
public final class DestroyPartitionedRegionMessage extends PartitionMessage
{
private Object cbArg;
/** The specific destroy operation performed on the sender */
private Operation op;
/** Serial number of the region being removed */
private int prSerial;
/** Serial numbers of the buckets for this region */
private int bucketSerials[];
/**
* Empty constructor to satisfy {@link DataSerializer} requirements
*/
public DestroyPartitionedRegionMessage() {
}
/**
*
* @param recipients the set of members on which the partitioned region should be destoryed
* @param region the partitioned region
* @param processor the processor that the reply will use to notify of the reply.
* @see #send(Set, PartitionedRegion, RegionEventImpl, int[])
*/
private DestroyPartitionedRegionMessage(Set recipients, PartitionedRegion region,
ReplyProcessor21 processor,
final RegionEventImpl event, int serials[]) {
super(recipients, region.getPRId(), processor, null);
this.cbArg = event.getRawCallbackArgument();
this.op = event.getOperation();
this.prSerial = region.getSerialNumber();
Assert.assertTrue(this.prSerial != DistributionAdvisor.ILLEGAL_SERIAL);
this.bucketSerials = serials;
}
/**
*
* @param recipients
* set of members who have the PartitionedRegion defined.
* @param r
* the PartitionedRegion to destroy on each member
* @return the response on which to wait for the confirmation
*/
public static DestroyPartitionedRegionResponse send(Set recipients, PartitionedRegion r,
final RegionEventImpl event, int serials[])
{
Assert.assertTrue(recipients != null, "DestroyMessage NULL recipients set");
DestroyPartitionedRegionResponse resp = new DestroyPartitionedRegionResponse(r.getSystem(),
recipients);
DestroyPartitionedRegionMessage m = new DestroyPartitionedRegionMessage(
recipients, r,
resp, event, serials);
r.getDistributionManager().putOutgoing(m);
return resp;
}
@Override
protected boolean operateOnPartitionedRegion(DistributionManager dm,
PartitionedRegion r, long startTime) throws CacheException {
if (this.op.isLocal()) {
// notify the advisor that the sending member has locally destroyed (or closed) the region
PartitionProfile pp = r.getRegionAdvisor().getPartitionProfile(getSender());
if (pp==null) { //Fix for bug#36863
// dm.getLogger().fine(this + ": null sender");
return true;
}
// final Lock isClosingWriteLock = r.getRegionAdvisor().getPartitionProfile(getSender()).getIsClosingWriteLock();
Assert.assertTrue(this.prSerial != DistributionAdvisor.ILLEGAL_SERIAL);
boolean ok = true;
// Examine this peer's profile and look at the serial number in that
// profile. If we have a newer profile, ignore the request.
int oldSerial = pp.getSerialNumber();
if (DistributionAdvisor.isNewerSerialNumber(oldSerial, this.prSerial)) {
ok = false;
if (dm.getLoggerI18n().fineEnabled()) {
dm.getLoggerI18n().fine("Not removing region " + r.getName()
+ "; serial requested = " + this.prSerial
+ "; actual is " + r.getSerialNumber());
}
}
if (ok) {
RegionAdvisor ra = r.getRegionAdvisor();
ra.removeIdAndBuckets(this.sender, this.prSerial, this.bucketSerials, !this.op.isClose());
// r.getRegionAdvisor().removeId(this.sender);
}
sendReply(getSender(), getProcessorId(), dm, null, r, startTime);
/* } finally {
isClosingWriteLock.unlock();
}*/
return false;
}
// dm.getLogger().fine(this + ": not local");
// If region's isDestroyed flag is true, we can check if local destroy is done or not and if NOT,
// we can invoke destroyPartitionedRegionLocally method.
if (r.isDestroyed()) {
boolean isClose = this.op.isClose();
r.destroyPartitionedRegionLocally(!isClose);
return true;
}
if (DistributionManager.VERBOSE) {
LogWriterI18n l = r.getCache().getLoggerI18n();
if(l.fineEnabled()){
l.fine(getClass().getName() + " operateOnRegion: " + r.getFullPath());
}
}
RegionEventImpl event = new RegionEventImpl(r, this.op,
this.cbArg, true, r.getMyId());
r.basicDestroyRegion(event, false, false, true);
return true;
}
@Override
protected void appendFields(StringBuilder buff) {
super.appendFields(buff);
buff.append("; cbArg=").append(this.cbArg).append("; op=").append(this.op);
buff.append("; prSerial=" + prSerial);
buff.append("; bucketSerials (" + bucketSerials.length + ")=(");
for (int i = 0; i < bucketSerials.length; i ++) {
buff.append(Integer.toString(bucketSerials[i]));
if (i < bucketSerials.length - 1) {
buff.append(", ");
}
}
}
public int getDSFID() {
return DESTROY_PARTITIONED_REGION_MESSAGE;
}
@Override
public void fromData(DataInput in)
throws IOException, ClassNotFoundException {
super.fromData(in);
this.cbArg = DataSerializer.readObject(in);
this.op = Operation.fromOrdinal(in.readByte());
this.prSerial = in.readInt();
int len = in.readInt();
this.bucketSerials = new int[len];
for (int i = 0; i < len ; i ++) {
this.bucketSerials[i] = in.readInt();
}
}
@Override
public void toData(DataOutput out)
throws IOException {
super.toData(out);
DataSerializer.writeObject(this.cbArg, out);
out.writeByte(this.op.ordinal);
out.writeInt(this.prSerial);
out.writeInt(this.bucketSerials.length);
for (int i = 0; i < this.bucketSerials.length; i++) {
out.writeInt(this.bucketSerials[i]);
}
}
/**
* The response on which to wait for all the replies. This response ignores any exceptions received from the "far side"
*
* @author Mitch Thomas
* @since 5.0
*/
static public class DestroyPartitionedRegionResponse extends ReplyProcessor21
{
public DestroyPartitionedRegionResponse(InternalDistributedSystem system,
Set initMembers) {
super(system, initMembers);
}
/**
* Ignore any incoming exception from other VMs, we just want an
* acknowledgement that the message was processed.
*/
@Override
protected void processException(ReplyException ex)
{
getDistributionManager().getLoggerI18n().fine(
"DestroyRegionResponse ignoring exception", ex);
}
}
}