org.apache.geode.internal.cache.tier.sockets.ClientUpdateMessageImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of geode-core Show documentation
Show all versions of geode-core Show documentation
Apache Geode provides a database-like consistency model, reliable transaction processing and a shared-nothing architecture to maintain very low latency performance with high concurrency processing
/*
* 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.tier.sockets;
import java.io.ByteArrayInputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.logging.log4j.Logger;
import org.apache.geode.DataSerializer;
import org.apache.geode.GemFireIOException;
import org.apache.geode.InternalGemFireError;
import org.apache.geode.cache.query.CqQuery;
import org.apache.geode.cache.query.internal.cq.InternalCqQuery;
import org.apache.geode.cache.util.ObjectSizer;
import org.apache.geode.internal.DSCODE;
import org.apache.geode.internal.InternalDataSerializer;
import org.apache.geode.internal.Sendable;
import org.apache.geode.internal.Version;
import org.apache.geode.internal.cache.CachedDeserializable;
import org.apache.geode.internal.cache.CachedDeserializableFactory;
import org.apache.geode.internal.cache.EntryEventImpl;
import org.apache.geode.internal.cache.Token;
import org.apache.geode.internal.cache.EntryEventImpl.NewValueImporter;
import org.apache.geode.internal.cache.EntryEventImpl.SerializedCacheValueImpl;
import org.apache.geode.internal.cache.EnumListenerEvent;
import org.apache.geode.internal.cache.EventID;
import org.apache.geode.internal.cache.LocalRegion;
import org.apache.geode.internal.cache.WrappedCallbackArgument;
import org.apache.geode.internal.cache.ha.HAContainerRegion;
import org.apache.geode.internal.cache.lru.Sizeable;
import org.apache.geode.internal.cache.tier.MessageType;
import org.apache.geode.internal.cache.versions.VersionTag;
import org.apache.geode.internal.logging.LogService;
import org.apache.geode.internal.offheap.MemoryAllocatorImpl;
/**
* Class ClientUpdateMessageImpl
is a message representing a cache operation that is
* sent from a server to an interested client.
*
*
* @since GemFire 4.2
*/
public class ClientUpdateMessageImpl implements ClientUpdateMessage, Sizeable, NewValueImporter {
private static final long serialVersionUID = 7037106666445312400L;
private static final Logger logger = LogService.getLogger();
/**
* The operation performed (e.g. AFTER_CREATE, AFTER_UPDATE, AFTER_DESTROY, AFTER_INVALIDATE,
* AFTER_REGION_DESTROY)
*/
protected EnumListenerEvent _operation;
/**
* The name of the Region
that was updated
*/
private String _regionName;
/**
* The key that was updated
*/
private Object _keyOfInterest;
/**
* The new value
*/
private Object _value;
/**
* Whether the value is a serialized object or just a byte[]
*/
protected byte _valueIsObject;
/**
* The callback argument
*/
protected Object _callbackArgument;
/**
* The membership id of the originator of the event
*/
protected ClientProxyMembershipID _membershipId;
/**
* The event id of the event
*/
protected EventID _eventIdentifier;
private boolean _shouldConflate = false;
/**
* To determine if this client message is part of InterestList.
*/
private volatile boolean _isInterestListPassed;
/**
* To determine if this client message is part of CQs.
*/
private volatile boolean _hasCqs = false;
/**
* Map containing clientId and the cqs satisfied for the client.
*/
private ClientCqConcurrentMap _clientCqs = null;
/**
* Client list satisfying the interestList who want values
*/
private volatile Set _clientInterestList;
/**
* Client list satisfying the interestList who want invalidations
*/
private volatile Set _clientInterestListInv;
/**
* To determine if the message is result of netLoad. If its net load the message is not delivered
* to the client that has requested the load.
*/
private transient boolean _isNetLoad = false;
/**
* Represents the changed bytes of this event's _value.
*
* @since GemFire 6.1
*/
private byte[] deltaBytes = null;
private VersionTag versionTag;
/* added up all constants and form single value */
private static final int CONSTANT_MEMORY_OVERHEAD;
/**
* Constructor.
*
* @param operation The operation performed (e.g. AFTER_CREATE, AFTER_UPDATE, AFTER_DESTROY,
* AFTER_INVALIDATE, AFTER_REGION_DESTROY)
* @param region The Region
that was updated
* @param keyOfInterest The key that was updated
* @param value The new value
* @param valueIsObject false if value is an actual byte[] that isn't serialized info
* @param callbackArgument The callback argument
* @param memberId membership id of the originator of the event
*/
public ClientUpdateMessageImpl(EnumListenerEvent operation, LocalRegion region,
Object keyOfInterest, Object value, byte valueIsObject, Object callbackArgument,
ClientProxyMembershipID memberId, EventID eventIdentifier) {
this(operation, region, keyOfInterest, value, null, valueIsObject, callbackArgument, memberId,
eventIdentifier, null);
}
public ClientUpdateMessageImpl(EnumListenerEvent operation, LocalRegion region,
Object keyOfInterest, Object value, byte[] delta, byte valueIsObject, Object callbackArgument,
ClientProxyMembershipID memberId, EventID eventIdentifier, VersionTag versionTag) {
// this._clientInterestList = new HashSet();
// this._clientInterestListInv = new HashSet();
this._operation = operation;
this._regionName = region.getFullPath();
this._keyOfInterest = keyOfInterest;
this._value = value;
this._valueIsObject = valueIsObject;
this._callbackArgument = callbackArgument;
this._membershipId = memberId;
this._eventIdentifier = eventIdentifier;
this._shouldConflate = (isUpdate() && region.getEnableConflation());
this.deltaBytes = delta;
this.versionTag = versionTag;
}
/**
* Constructor used by ClientInstantiatorMessage
*
* @param operation The operation performed (e.g. AFTER_CREATE, AFTER_UPDATE, AFTER_DESTROY,
* AFTER_INVALIDATE, AFTER_REGION_DESTROY)
* @param memberId membership id of the originator of the event
* @param eventIdentifier EventID of this message
*/
protected ClientUpdateMessageImpl(EnumListenerEvent operation, ClientProxyMembershipID memberId,
EventID eventIdentifier) {
// this._clientInterestList = new HashSet();
// this._clientInterestListInv = new HashSet();
this._operation = operation;
this._membershipId = memberId;
this._eventIdentifier = eventIdentifier;
}
/**
* default constructor
*
*/
public ClientUpdateMessageImpl() {
}
public String getRegionName() {
return this._regionName;
}
public Object getKeyOfInterest() {
return this._keyOfInterest;
}
public EnumListenerEvent getOperation() {
return this._operation;
}
public Object getValue() {
return this._value;
}
public boolean valueIsObject() {
return (this._valueIsObject == 0x01);
}
/**
* @return the callback argument
*/
public Object getCallbackArgument() {
return this._callbackArgument;
}
/// Conflatable interface methods ///
/**
* Determines whether or not to conflate this message. This method will answer true IFF the
* message's operation is AFTER_UPDATE and its region has enabled are conflation. Otherwise, this
* method will answer false. Messages whose operation is AFTER_CREATE, AFTER_DESTROY,
* AFTER_INVALIDATE or AFTER_REGION_DESTROY are not conflated.
*
* @return Whether to conflate this message
*/
public boolean shouldBeConflated() {
// If the message is an update, it may be conflatable. If it is a
// create, destroy, invalidate or destroy-region, it is not conflatable.
// Only updates are conflated. If it is an update, then verify that
// the region has conflation enabled.
return this._shouldConflate;
}
public String getRegionToConflate() {
return this._regionName;
}
public Object getKeyToConflate() {
return this._keyOfInterest;
}
public Object getValueToConflate() {
return this._value;
}
public void setLatestValue(Object value) {
// does this also need to set _valueIsObject
this._value = value;
}
/// End Conflatable interface methods ///
public ClientProxyMembershipID getMembershipId() {
return this._membershipId;
}
/**
* Returns the unqiue event eventifier for event corresponding to this message.
*
* @return the unqiue event eventifier for event corresponding to this message.
*/
public EventID getEventId() {
return this._eventIdentifier;
}
public VersionTag getVersionTag() {
return this.versionTag;
}
public boolean isCreate() {
return this._operation == EnumListenerEvent.AFTER_CREATE;
}
public boolean isUpdate() {
return this._operation == EnumListenerEvent.AFTER_UPDATE;
}
public boolean isDestroy() {
return this._operation == EnumListenerEvent.AFTER_DESTROY;
}
public boolean isInvalidate() {
return this._operation == EnumListenerEvent.AFTER_INVALIDATE;
}
public boolean isDestroyRegion() {
return this._operation == EnumListenerEvent.AFTER_REGION_DESTROY;
}
public boolean isClearRegion() {
return this._operation == EnumListenerEvent.AFTER_REGION_CLEAR;
}
public boolean isInvalidateRegion() {
return this._operation == EnumListenerEvent.AFTER_REGION_INVALIDATE;
}
public boolean isClientCompatible() {
return false;
}
public Message getMessage(CacheClientProxy proxy, boolean notify) throws IOException {
// the MessageDispatcher uses getMessage(CacheClientProxy, byte[]) for this class
throw new Error("ClientUpdateMessage.getMessage(proxy) should not be invoked");
}
/**
* Returns a Message
generated from the fields of this
* ClientUpdateMessage
.
*
* @param latestValue Object containing the latest value to use. This could be the original value
* if conflation is not enabled, or it could be a conflated value if conflation is enabled.
* @return a Message
generated from the fields of this
* ClientUpdateMessage
* @throws IOException
* @see org.apache.geode.internal.cache.tier.sockets.Message
*/
protected Message getMessage(CacheClientProxy proxy, byte[] latestValue) throws IOException {
Version clientVersion = proxy.getVersion();
byte[] serializedValue = null;
Message message = null;
boolean conflation = false;
conflation = (proxy.clientConflation == HandShake.CONFLATION_ON)
|| (proxy.clientConflation == HandShake.CONFLATION_DEFAULT && this.shouldBeConflated());
if (latestValue != null) {
serializedValue = latestValue;
} else {
/**
* This means latestValue is instance of Delta, and its delta has already been extracted and
* put into deltaBytes. We serialize the value.
*/
if (this.deltaBytes == null || isCreate()) {
// Delta could not be extracted. We would need to send full value.
// OR A CREATE operation has a value which has delta. But we send full value for CREATE.
// So serialize it.
this._value = serializedValue = CacheServerHelper.serialize(latestValue);
}
}
if (clientVersion.compareTo(Version.GFE_70) >= 0) {
message = getGFE70Message(proxy, serializedValue, conflation, clientVersion);
} else if (clientVersion.compareTo(Version.GFE_65) >= 0) {
message = getGFE65Message(proxy, serializedValue, conflation, clientVersion);
} else if (clientVersion.compareTo(Version.GFE_61) >= 0) {
message = getGFE61Message(proxy, serializedValue, conflation, clientVersion);
} else if (clientVersion.compareTo(Version.GFE_57) >= 0) {
message = getGFEMessage(proxy.getProxyID(), latestValue, clientVersion);
} else {
throw new IOException(
"Unsupported client version for server-to-client message creation: " + clientVersion);
}
return message;
}
protected Message getGFEMessage(ClientProxyMembershipID proxyId, byte[] latestValue,
Version clientVersion) throws IOException {
Message message = null;
// Add CQ info.
int cqMsgParts = 0;
boolean clientHasCq = this._hasCqs && (this.getCqs(proxyId) != null);
if (clientHasCq) {
cqMsgParts = (this.getCqs(proxyId).length * 2) + 1;
}
if (isCreate() || isUpdate()) {
// Create or update event
if (this._clientInterestListInv != null && this._clientInterestListInv.contains(proxyId)) {
// Notify all - do not send the value
message = new Message(6, clientVersion);
message.setMessageType(MessageType.LOCAL_INVALIDATE);
message.addStringPart(this._regionName, true);
// Currently serializing the key here instead of when the message
// is put in the queue so that it can be conflated it later
message.addStringOrObjPart(this._keyOfInterest);
message.addObjPart(this._callbackArgument);
message.addObjPart(Boolean.valueOf(isClientInterested(proxyId)));
message.addObjPart(Boolean.FALSE);
} else {
// Notify by subscription - send the value
message = new Message(7 + cqMsgParts, clientVersion);
// Set message type
if (isCreate()) {
message.setMessageType(MessageType.LOCAL_CREATE);
} else {
message.setMessageType(MessageType.LOCAL_UPDATE);
}
message.addStringPart(this._regionName, true);
// Currently serializing the key here instead of when the message
// is put in the queue so that it can be conflated it later
message.addStringOrObjPart(this._keyOfInterest);
message.addRawPart(latestValue, (this._valueIsObject == 0x01));
message.addObjPart(this._callbackArgument);
message.addObjPart(Boolean.valueOf(isClientInterested(proxyId)));
message.addObjPart(Boolean.valueOf(clientHasCq));
if (clientHasCq) {
this.addCqsToMessage(proxyId, message);
}
}
} else if (isDestroy() || isInvalidate()) {
message = new Message(6 + cqMsgParts, clientVersion);
if (isDestroy()) {
message.setMessageType(MessageType.LOCAL_DESTROY);
} else {
message.setMessageType(MessageType.LOCAL_INVALIDATE);
}
message.addStringPart(this._regionName, true);
// Currently serializing the key here instead of when the message
// is put in the queue so that it can be conflated it later
message.addStringOrObjPart(this._keyOfInterest);
message.addObjPart(this._callbackArgument);
message.addObjPart(Boolean.valueOf(isClientInterested(proxyId)));
message.addObjPart(Boolean.valueOf(clientHasCq));
if (clientHasCq) {
this.addCqsToMessage(proxyId, message);
}
} else if (isDestroyRegion()) {
message = new Message(4 + cqMsgParts, clientVersion);
message.setMessageType(MessageType.LOCAL_DESTROY_REGION);
message.addStringPart(this._regionName, true);
message.addObjPart(this._callbackArgument);
message.addObjPart(Boolean.valueOf(clientHasCq));
if (clientHasCq) {
this.addCqsToMessage(proxyId, message);
}
} else if (isClearRegion()) {
message = new Message(4 + cqMsgParts, clientVersion);
message.setMessageType(MessageType.CLEAR_REGION);
message.addStringPart(this._regionName, true);
message.addObjPart(this._callbackArgument);
message.addObjPart(Boolean.valueOf(clientHasCq));
if (clientHasCq) {
this.addCqsToMessage(proxyId, message);
}
} else if (isInvalidateRegion()) {
message = new Message(4 + cqMsgParts, clientVersion);
message.setMessageType(MessageType.INVALIDATE_REGION);
message.addStringPart(this._regionName, true);
message.addObjPart(this._callbackArgument);
message.addObjPart(Boolean.valueOf(clientHasCq));
if (clientHasCq) {
this.addCqsToMessage(proxyId, message);
}
} else {
throw new InternalGemFireError("Don't know what kind of message");
}
message.setTransactionId(0);
// Add the EventId since 5.1 (used to prevent duplicate events
// received on the client side after a failover)
message.addObjPart(this._eventIdentifier);
return message;
}
protected Message getGFE61Message(CacheClientProxy proxy, byte[] latestValue, boolean conflation,
Version clientVersion) throws IOException {
Message message = null;
ClientProxyMembershipID proxyId = proxy.getProxyID();
// Add CQ info.
int cqMsgParts = 0;
boolean clientHasCq = this._hasCqs && (this.getCqs(proxyId) != null);
if (clientHasCq) {
cqMsgParts = (this.getCqs(proxyId).length * 2) + 1;
}
if (isCreate() || isUpdate()) {
// Create or update event
if (this._clientInterestListInv != null && this._clientInterestListInv.contains(proxyId)) {
// Notify all - do not send the value
message = new Message(6, clientVersion);
message.setMessageType(MessageType.LOCAL_INVALIDATE);
// Add the region name
message.addStringPart(this._regionName, true);
// Add the key
// Currently serializing the key here instead of when the message
// is put in the queue so that it can be conflated it later
message.addStringOrObjPart(this._keyOfInterest);
// Add the callback argument
message.addObjPart(this._callbackArgument);
// Add interestlist status.
message.addObjPart(Boolean.valueOf(isClientInterested(proxyId)));
// Add CQ status.
message.addObjPart(Boolean.FALSE);
} else {
boolean isClientInterested = isClientInterested(proxyId);
// Notify by subscription - send the value
message = new Message(8 + cqMsgParts, clientVersion);
// Set message type
if (isCreate()) {
message.setMessageType(MessageType.LOCAL_CREATE);
// Add the region name
message.addStringPart(this._regionName, true);
// Add the key
// Currently serializing the key here instead of when the message
// is put in the queue so that it can be conflated it later
message.addStringOrObjPart(this._keyOfInterest);
message.addObjPart(Boolean.FALSE); // NO delta
// Add the value (which has already been serialized)
message.addRawPart(latestValue, (this._valueIsObject == 0x01));
} else {
message.setMessageType(MessageType.LOCAL_UPDATE);
// Add the region name
message.addStringPart(this._regionName, true);
// Add the key
// Currently serializing the key here instead of when the message
// is put in the queue so that it can be conflated it later
message.addStringOrObjPart(this._keyOfInterest);
if (this.deltaBytes != null && !conflation && !proxy.isMarkerEnqueued()
&& !proxy.getRegionsWithEmptyDataPolicy().containsKey(_regionName)) {
message.addObjPart(Boolean.TRUE);
message.addBytesPart(this.deltaBytes);
proxy.getStatistics().incDeltaMessagesSent();
} else {
message.addObjPart(Boolean.FALSE);
byte[] l = latestValue;
if (l == null) {
if (!(this._value instanceof byte[])) {
this._value = CacheServerHelper.serialize(this._value);
}
l = (byte[]) this._value;
}
// Add the value (which has already been serialized)
message.addRawPart(l, (this._valueIsObject == 0x01));
}
}
// Add the callback argument
message.addObjPart(this._callbackArgument);
// Add interest list status.
message.addObjPart(Boolean.valueOf(isClientInterested));
// Add CQ status.
message.addObjPart(Boolean.valueOf(clientHasCq));
if (clientHasCq) {
this.addCqsToMessage(proxyId, message);
}
}
} else if (isDestroy() || isInvalidate()) {
// Destroy or invalidate event
message = new Message(6 + cqMsgParts, clientVersion);
if (isDestroy()) {
message.setMessageType(MessageType.LOCAL_DESTROY);
} else {
message.setMessageType(MessageType.LOCAL_INVALIDATE);
}
message.addStringPart(this._regionName, true);
// Currently serializing the key here instead of when the message
// is put in the queue so that it can be conflated later
message.addStringOrObjPart(this._keyOfInterest);
message.addObjPart(this._callbackArgument);
message.addObjPart(Boolean.valueOf(isClientInterested(proxyId)));
message.addObjPart(Boolean.valueOf(clientHasCq));
if (clientHasCq) {
this.addCqsToMessage(proxyId, message);
}
} else if (isDestroyRegion()) {
message = new Message(4 + cqMsgParts, clientVersion);
message.setMessageType(MessageType.LOCAL_DESTROY_REGION);
message.addStringPart(this._regionName, true);
message.addObjPart(this._callbackArgument);
message.addObjPart(Boolean.valueOf(clientHasCq));
if (clientHasCq) {
this.addCqsToMessage(proxyId, message);
}
} else if (isClearRegion()) {
message = new Message(4 + cqMsgParts, clientVersion);
message.setMessageType(MessageType.CLEAR_REGION);
message.addStringPart(this._regionName, true);
message.addObjPart(this._callbackArgument);
message.addObjPart(Boolean.valueOf(clientHasCq));
if (clientHasCq) {
this.addCqsToMessage(proxyId, message);
}
} else if (isInvalidateRegion()) {
message = new Message(4 + cqMsgParts, clientVersion);
message.setMessageType(MessageType.INVALIDATE_REGION);
message.addStringPart(this._regionName, true);
message.addObjPart(this._callbackArgument);
message.addObjPart(Boolean.valueOf(clientHasCq));
if (clientHasCq) {
this.addCqsToMessage(proxyId, message);
}
} else {
throw new InternalGemFireError("Don't know what kind of message");
}
message.setTransactionId(0);
// Add the EventId since 5.1 (used to prevent duplicate events
// received on the client side after a failover)
message.addObjPart(this._eventIdentifier);
return message;
}
protected Message getGFE65Message(CacheClientProxy proxy, byte[] p_latestValue,
boolean conflation, Version clientVersion) throws IOException {
byte[] latestValue = p_latestValue;
Message message = null;
ClientProxyMembershipID proxyId = proxy.getProxyID();
// Add CQ info.
int cqMsgParts = 0;
boolean clientHasCq = this._hasCqs && (this.getCqs(proxyId) != null);
if (clientHasCq) {
cqMsgParts = (this.getCqs(proxyId).length * 2) + 1;
}
if (isCreate() || isUpdate()) {
// Create or update event
if (this._clientInterestListInv != null && this._clientInterestListInv.contains(proxyId)) {
// Client is registered for invalidates.
if (cqMsgParts > 0) {
cqMsgParts++; // To store base operation type for CQ.
}
message = new Message(6 + cqMsgParts, clientVersion);
message.setMessageType(MessageType.LOCAL_INVALIDATE);
// Add the region name
message.addStringPart(this._regionName, true);
// Add the key
// Currently serializing the key here instead of when the message
// is put in the queue so that it can be conflated it later
message.addStringOrObjPart(this._keyOfInterest);
} else {
// Notify by subscription - send the value
message = new Message(8 + cqMsgParts, clientVersion);
// Set message type
if (isCreate()) {
message.setMessageType(MessageType.LOCAL_CREATE);
// Add the region name
message.addStringPart(this._regionName, true);
// Add the key
// Currently serializing the key here instead of when the message
// is put in the queue so that it can be conflated it later
message.addStringOrObjPart(this._keyOfInterest);
message.addObjPart(Boolean.FALSE); // NO delta
// Add the value (which has already been serialized)
message.addRawPart(latestValue, (this._valueIsObject == 0x01));
} else {
message.setMessageType(MessageType.LOCAL_UPDATE);
// Add the region name
message.addStringPart(this._regionName, true);
// Add the key
// Currently serializing the key here instead of when the message
// is put in the queue so that it can be conflated it later
message.addStringOrObjPart(this._keyOfInterest);
if (this.deltaBytes != null && !conflation && !proxy.isMarkerEnqueued()
&& !proxy.getRegionsWithEmptyDataPolicy().containsKey(_regionName)) {
message.addObjPart(Boolean.TRUE);
message.addBytesPart(this.deltaBytes);
proxy.getStatistics().incDeltaMessagesSent();
} else {
message.addObjPart(Boolean.FALSE);
if (latestValue == null) {
if (!(this._value instanceof byte[])) {
this._value = CacheServerHelper.serialize(this._value);
}
latestValue = (byte[]) this._value;
}
// Add the value (which has already been serialized)
message.addRawPart(latestValue, (this._valueIsObject == 0x01));
}
}
}
message.addObjPart(this._callbackArgument);
message.addObjPart(Boolean.valueOf(isClientInterested(proxyId)));
message.addObjPart(Boolean.valueOf(clientHasCq));
if (clientHasCq) {
if (message.getMessageType() == MessageType.LOCAL_INVALIDATE) {
// in case of invalidate, set the region operation type.
message.addIntPart(isCreate() ? MessageType.LOCAL_CREATE : MessageType.LOCAL_UPDATE);
}
this.addCqsToMessage(proxyId, message);
}
} else if (isDestroy() || isInvalidate()) {
if (isDestroy()) {
message = new Message(6 + cqMsgParts, clientVersion);
message.setMessageType(MessageType.LOCAL_DESTROY);
} else {
if (clientHasCq) {
cqMsgParts++;/* To store the region operation for CQ */
}
message = new Message(6 + cqMsgParts, clientVersion);
message.setMessageType(MessageType.LOCAL_INVALIDATE);
}
message.addStringPart(this._regionName, true);
message.addStringOrObjPart(this._keyOfInterest);
message.addObjPart(this._callbackArgument);
message.addObjPart(Boolean.valueOf(isClientInterested(proxyId)));
message.addObjPart(Boolean.valueOf(clientHasCq));
if (clientHasCq) {
if (isInvalidate()) {
// This is to take care when invalidate message is getting sent
// to the Client. See the code for create/update operation.
message.addIntPart(MessageType.LOCAL_INVALIDATE);
}
this.addCqsToMessage(proxyId, message);
}
} else if (isDestroyRegion()) {
message = new Message(4 + cqMsgParts, clientVersion);
message.setMessageType(MessageType.LOCAL_DESTROY_REGION);
message.addStringPart(this._regionName, true);
message.addObjPart(this._callbackArgument);
message.addObjPart(Boolean.valueOf(clientHasCq));
if (clientHasCq) {
this.addCqsToMessage(proxyId, message);
}
} else if (isClearRegion()) {
message = new Message(4 + cqMsgParts, clientVersion);
message.setMessageType(MessageType.CLEAR_REGION);
message.addStringPart(this._regionName, true);
message.addObjPart(this._callbackArgument);
message.addObjPart(Boolean.valueOf(clientHasCq));
if (clientHasCq) {
this.addCqsToMessage(proxyId, message);
}
} else if (isInvalidateRegion()) {
message = new Message(4 + cqMsgParts, clientVersion);
message.setMessageType(MessageType.INVALIDATE_REGION);
message.addStringPart(this._regionName, true);
message.addObjPart(this._callbackArgument);
// Add CQ status.
message.addObjPart(Boolean.valueOf(clientHasCq));
if (clientHasCq) {
this.addCqsToMessage(proxyId, message);
}
} else {
throw new InternalGemFireError("Don't know what kind of message");
}
message.setTransactionId(0);
// Add the EventId since 5.1 (used to prevent duplicate events
// received on the client side after a failover)
message.addObjPart(this._eventIdentifier);
return message;
}
protected Message getGFE70Message(CacheClientProxy proxy, byte[] p_latestValue,
boolean conflation, Version clientVersion) throws IOException {
byte[] latestValue = p_latestValue;
Message message = null;
ClientProxyMembershipID proxyId = proxy.getProxyID();
// Add CQ info.
int cqMsgParts = 0;
boolean clientHasCq = this._hasCqs && (this.getCqs(proxyId) != null);
if (clientHasCq) {
cqMsgParts = (this.getCqs(proxyId).length * 2) + 1;
}
if (isCreate() || isUpdate()) {
// Create or update event
if (this._clientInterestListInv != null && this._clientInterestListInv.contains(proxyId)) {
// Client is registered for invalidates.
if (cqMsgParts > 0) {
cqMsgParts++; // To store base operation type for CQ.
}
message = getMessage(7 + cqMsgParts, clientVersion);
message.setMessageType(MessageType.LOCAL_INVALIDATE);
message.addStringPart(this._regionName, true);
message.addStringOrObjPart(this._keyOfInterest);
} else {
// Notify by subscription - send the value
message = getMessage(9 + cqMsgParts, clientVersion);
if (isCreate()) {
message.setMessageType(MessageType.LOCAL_CREATE);
message.addStringPart(this._regionName, true);
message.addStringOrObjPart(this._keyOfInterest);
message.addObjPart(Boolean.FALSE); // NO delta
// Add the value (which has already been serialized)
message.addRawPart(latestValue, (this._valueIsObject == 0x01));
} else {
message.setMessageType(MessageType.LOCAL_UPDATE);
message.addStringPart(this._regionName, true);
message.addStringOrObjPart(this._keyOfInterest);
if (this.deltaBytes != null && !conflation && !proxy.isMarkerEnqueued()
&& !proxy.getRegionsWithEmptyDataPolicy().containsKey(_regionName)) {
message.addObjPart(Boolean.TRUE);
message.addBytesPart(this.deltaBytes);
proxy.getStatistics().incDeltaMessagesSent();
} else {
message.addObjPart(Boolean.FALSE);
if (latestValue == null) {
if (!(this._value instanceof byte[])) {
this._value = CacheServerHelper.serialize(this._value);
}
latestValue = (byte[]) this._value;
}
// Add the value (which has already been serialized)
message.addRawPart(latestValue, (this._valueIsObject == 0x01));
}
}
}
message.addObjPart(this._callbackArgument);
if (this.versionTag != null) {
this.versionTag.setCanonicalIDs(proxy.getCache().getDistributionManager());
}
message.addObjPart(this.versionTag);
message.addObjPart(Boolean.valueOf(isClientInterested(proxyId)));
message.addObjPart(Boolean.valueOf(clientHasCq));
if (clientHasCq) {
if (message.getMessageType() == MessageType.LOCAL_INVALIDATE) {
// in case of invalidate, set the region operation type.
message.addIntPart(isCreate() ? MessageType.LOCAL_CREATE : MessageType.LOCAL_UPDATE);
}
this.addCqsToMessage(proxyId, message);
}
} else if (isDestroy() || isInvalidate()) {
if (isDestroy()) {
message = getMessage(7 + cqMsgParts, clientVersion);
message.setMessageType(MessageType.LOCAL_DESTROY);
} else {
if (clientHasCq) {
cqMsgParts++;/* To store the region operation for CQ */
}
message = getMessage(7 + cqMsgParts, clientVersion);
message.setMessageType(MessageType.LOCAL_INVALIDATE);
}
message.addStringPart(this._regionName, true);
message.addStringOrObjPart(this._keyOfInterest);
message.addObjPart(this._callbackArgument);
message.addObjPart(this.versionTag);
message.addObjPart(Boolean.valueOf(isClientInterested(proxyId)));
message.addObjPart(Boolean.valueOf(clientHasCq));
if (clientHasCq) {
if (isInvalidate()) {
// This is to take care when invalidate message is getting sent
// to the Client. See the code for create/update operation.
message.addIntPart(MessageType.LOCAL_INVALIDATE);
}
this.addCqsToMessage(proxyId, message);
}
} else if (isDestroyRegion()) {
message = getMessage(4 + cqMsgParts, clientVersion);
message.setMessageType(MessageType.LOCAL_DESTROY_REGION);
message.addStringPart(this._regionName, true);
message.addObjPart(this._callbackArgument);
message.addObjPart(Boolean.valueOf(clientHasCq));
if (clientHasCq) {
this.addCqsToMessage(proxyId, message);
}
} else if (isClearRegion()) {
message = getMessage(4 + cqMsgParts, clientVersion);
message.setMessageType(MessageType.CLEAR_REGION);
message.addStringPart(this._regionName, true);
message.addObjPart(this._callbackArgument);
message.addObjPart(Boolean.valueOf(clientHasCq));
if (clientHasCq) {
this.addCqsToMessage(proxyId, message);
}
} else if (isInvalidateRegion()) {
message = getMessage(4 + cqMsgParts, clientVersion);
message.setMessageType(MessageType.INVALIDATE_REGION);
message.addStringPart(this._regionName, true);
message.addObjPart(this._callbackArgument);
// Add CQ status.
message.addObjPart(Boolean.valueOf(clientHasCq));
if (clientHasCq) {
this.addCqsToMessage(proxyId, message);
}
} else {
throw new InternalGemFireError("Don't know what kind of message");
}
message.setTransactionId(0);
// Add the EventId since 5.1 (used to prevent duplicate events
// received on the client side after a failover)
message.addObjPart(this._eventIdentifier);
return message;
}
private static final ThreadLocal