/*
* 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.client.internal;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.logging.log4j.Logger;
import org.apache.geode.cache.CacheLoader;
import org.apache.geode.cache.CacheWriter;
import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.InterestResultPolicy;
import org.apache.geode.cache.Operation;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.Region.Entry;
import org.apache.geode.cache.client.PoolManager;
import org.apache.geode.cache.client.internal.ContainsKeyOp.MODE;
import org.apache.geode.cache.execute.Function;
import org.apache.geode.cache.execute.ResultCollector;
import org.apache.geode.distributed.internal.ServerLocation;
import org.apache.geode.internal.cache.AbstractRegion;
import org.apache.geode.internal.cache.ClientServerObserver;
import org.apache.geode.internal.cache.ClientServerObserverHolder;
import org.apache.geode.internal.cache.EntryEventImpl;
import org.apache.geode.internal.cache.EventID;
import org.apache.geode.internal.cache.EventIDHolder;
import org.apache.geode.internal.cache.LocalRegion;
import org.apache.geode.internal.cache.TXCommitMessage;
import org.apache.geode.internal.cache.TXManagerImpl;
import org.apache.geode.internal.cache.TXStateProxy;
import org.apache.geode.internal.cache.execute.ServerRegionFunctionExecutor;
import org.apache.geode.internal.cache.tier.InterestType;
import org.apache.geode.internal.cache.tier.sockets.VersionedObjectList;
import org.apache.geode.internal.cache.tier.sockets.VersionedObjectList.Iterator;
import org.apache.geode.internal.cache.tx.ClientTXStateStub;
import org.apache.geode.internal.cache.tx.TransactionalOperation.ServerRegionOperation;
import org.apache.geode.internal.i18n.LocalizedStrings;
import org.apache.geode.internal.logging.LogService;
import org.apache.geode.internal.logging.log4j.LocalizedMessage;
/**
* Used to send region operations from a client to a server
*
* @since GemFire 5.7
*/
@SuppressWarnings("deprecation")
public class ServerRegionProxy extends ServerProxy implements ServerRegionDataAccess {
private static final Logger logger = LogService.getLogger();
private final LocalRegion region;
private final String regionName;
/**
* Creates a server region proxy for the given region.
*
* @param r the region
* @throws IllegalStateException if the region does not have a pool
*/
public ServerRegionProxy(Region r) {
super(calcPool(r));
assert r instanceof LocalRegion;
this.region = (LocalRegion) r;
this.regionName = r.getFullPath();
}
/**
* Used by tests to create proxies for "fake" regions. Also, used by ClientStatsManager for admin
* region.
*/
public ServerRegionProxy(String regionName, PoolImpl pool) {
super(pool);
this.region = null;
this.regionName = regionName;
}
private static InternalPool calcPool(Region r) {
String poolName = r.getAttributes().getPoolName();
if (poolName == null || "".equals(poolName)) {
throw new IllegalStateException(
"The region " + r.getFullPath() + " did not have a client pool configured.");
} else {
InternalPool pool = (InternalPool) PoolManager.find(poolName);
if (pool == null) {
throw new IllegalStateException("The pool " + poolName + " does not exist.");
}
return pool;
}
}
/*
* (non-Javadoc)
*
* @see org.apache.geode.cache.client.internal.ServerRegionDataAccess#get(java.lang.Object,
* java.lang.Object)
*/
public Object get(Object key, Object callbackArg, EntryEventImpl clientEvent) {
recordTXOperation(ServerRegionOperation.GET, key, callbackArg);
return GetOp.execute(this.pool, this.region, key, callbackArg,
this.pool.getPRSingleHopEnabled(), clientEvent);
}
public int size() {
return SizeOp.execute(this.pool, this.regionName);
}
/**
* Do not call this method if the value is Delta instance. Exclicitly passing
* <code>Operation.CREATE</code> to the <code>PutOp.execute()</code> method as the caller of this
* method does not put Delta instances as value.
*
* @param key
* @param value
* @param event
* @param callbackArg
*/
public Object putForMetaRegion(Object key, Object value, byte[] deltaBytes, EntryEventImpl event,
Object callbackArg, boolean isMetaRegionPutOp) {
if (this.region == null) {
return PutOp.execute(this.pool, this.regionName, key, value, deltaBytes, event,
Operation.CREATE, false, null, callbackArg, this.pool.getPRSingleHopEnabled(),
isMetaRegionPutOp);
} else {
return PutOp.execute(this.pool, this.region, key, value, deltaBytes, event, Operation.CREATE,
false, null, callbackArg, this.pool.getPRSingleHopEnabled());
}
}
public Object put(Object key, Object value, byte[] deltaBytes, EntryEventImpl event, Operation op,
boolean requireOldValue, Object expectedOldValue, Object callbackArg, boolean isCreate) {
recordTXOperation(ServerRegionOperation.PUT, key, value, deltaBytes, event.getEventId(), op,
Boolean.valueOf(requireOldValue), expectedOldValue, callbackArg, Boolean.valueOf(isCreate));
Operation operation = op;
if (!isCreate && this.region.getDataPolicy() == DataPolicy.EMPTY && op.isCreate()
&& op != Operation.PUT_IF_ABSENT) {
operation = Operation.UPDATE;
}
if (this.region == null) {
return PutOp.execute(this.pool, this.regionName, key, value, deltaBytes, event, operation,
requireOldValue, expectedOldValue, callbackArg, this.pool.getPRSingleHopEnabled(), false);
} else {
return PutOp.execute(this.pool, this.region, key, value, deltaBytes, event, operation,
requireOldValue, expectedOldValue, callbackArg, this.pool.getPRSingleHopEnabled());
}
}
/**
* Does a region put on the server using the given connection.
*
* @param con the connection to use to send to the server
* @param key the entry key to do the put on
* @param value the entry value to put
* @param eventId the event ID for this put
* @param callbackArg an optional callback arg to pass to any cache callbacks
*/
public void putOnForTestsOnly(Connection con, Object key, Object value, EventID eventId,
Object callbackArg) {
EventIDHolder event = new EventIDHolder(eventId);
PutOp.execute(con, this.pool, this.regionName, key, value, event, callbackArg,
this.pool.getPRSingleHopEnabled());
}
/*
* (non-Javadoc)
*
* @see org.apache.geode.cache.client.internal.ServerRegionDataAccess#destroy(java.lang.Object,
* java.lang.Object, org.apache.geode.cache.Operation, org.apache.geode.internal.cache.EventID,
* java.lang.Object)
*/
public Object destroy(Object key, Object expectedOldValue, Operation operation,
EntryEventImpl event, Object callbackArg) {
if (event.isBulkOpInProgress()) {
// this is a removeAll, ignore this!
return null;
}
recordTXOperation(ServerRegionOperation.DESTROY, key, expectedOldValue, operation,
event.getEventId(), callbackArg);
return DestroyOp.execute(this.pool, this.region, key, expectedOldValue, operation, event,
callbackArg, this.pool.getPRSingleHopEnabled());
}
public void invalidate(EntryEventImpl event) {
recordTXOperation(ServerRegionOperation.INVALIDATE, event.getKey(), event);
InvalidateOp.execute(this.pool, this.region.getFullPath(), event);
}
/**
* Does a region entry destroy on the server using the given connection.
*
* @param con the connection to use to send to the server
* @param key the entry key to do the destroy on
* @param expectedOldValue the value that the entry must have to perform the operation, or null
* @param operation the operation being performed (Operation.DESTROY, Operation.REMOVE)
* @param event the event for this destroy operation
* @param callbackArg an optional callback arg to pass to any cache callbacks
*/
public void destroyOnForTestsOnly(Connection con, Object key, Object expectedOldValue,
Operation operation, EntryEventImpl event, Object callbackArg) {
DestroyOp.execute(con, this.pool, this.regionName, key, expectedOldValue, operation, event,
callbackArg);
}
/**
* Does a region destroy on the server
*
* @param eventId the event id for this destroy
* @param callbackArg an optional callback arg to pass to any cache callbacks
*/
public void destroyRegion(EventID eventId, Object callbackArg) {
DestroyRegionOp.execute(this.pool, this.regionName, eventId, callbackArg);
}
/**
* Does a region destroy on the server using the given connection.
*
* @param con the connection to use to send to the server
* @param eventId the event id for this destroy
* @param callbackArg an optional callback arg to pass to any cache callbacks
*/
public void destroyRegionOnForTestsOnly(Connection con, EventID eventId, Object callbackArg) {
DestroyRegionOp.execute(con, this.pool, this.regionName, eventId, callbackArg);
}
public TXCommitMessage commit(int txId) {
TXCommitMessage tx = CommitOp.execute(this.pool, txId);
return tx;
}
public void rollback(int txId) {
RollbackOp.execute(this.pool, txId);
}
/*
* (non-Javadoc)
*
* @see
* org.apache.geode.cache.client.internal.ServerRegionDataAccess#clear(org.apache.geode.internal.
* cache.EventID, java.lang.Object)
*/
public void clear(EventID eventId, Object callbackArg) {
ClearOp.execute(this.pool, this.regionName, eventId, callbackArg);
}
/**
* Does a region clear on the server using the given connection.
*
* @param con the connection to use to send to the server
* @param eventId the event id for this clear
* @param callbackArg an optional callback arg to pass to any cache callbacks
*/
public void clearOnForTestsOnly(Connection con, EventID eventId, Object callbackArg) {
ClearOp.execute(con, this.pool, this.regionName, eventId, callbackArg);
}
/*
* (non-Javadoc)
*
* @see
* org.apache.geode.cache.client.internal.ServerRegionDataAccess#containsKey(java.lang.Object)
*/
public boolean containsKey(Object key) {
recordTXOperation(ServerRegionOperation.CONTAINS_KEY, key);
return ContainsKeyOp.execute(this.pool, this.regionName, key, MODE.KEY);
}
/*
* (non-Javadoc)
*
* @see
* org.apache.geode.cache.client.internal.ServerRegionDataAccess#containsKey(java.lang.Object)
*/
public boolean containsValueForKey(Object key) {
recordTXOperation(ServerRegionOperation.CONTAINS_VALUE_FOR_KEY, key);
return ContainsKeyOp.execute(this.pool, this.regionName, key, MODE.VALUE_FOR_KEY);
}
/*
* (non-Javadoc)
*
* @see
* org.apache.geode.cache.client.internal.ServerRegionDataAccess#containsKey(java.lang.Object)
*/
public boolean containsValue(Object value) {
recordTXOperation(ServerRegionOperation.CONTAINS_VALUE, null, value);
return ContainsKeyOp.execute(this.pool, this.regionName, value, MODE.VALUE);
}
/*
* (non-Javadoc)
*
* @see org.apache.geode.cache.client.internal.ServerRegionDataAccess#keySet()
*/
public Set keySet() {
recordTXOperation(ServerRegionOperation.KEY_SET, null);
return KeySetOp.execute(this.pool, this.regionName);
}
/**
* Does a region registerInterest on a server
*
* @param key describes what we are interested in
* @param interestType the {@link InterestType} for this registration
* @param policy the interest result policy for this registration
* @param isDurable true if this registration is durable
* @param regionDataPolicy the data policy ordinal of the region
* @return list of keys
*/
public List registerInterest(final Object key, final int interestType,
final InterestResultPolicy policy, final boolean isDurable, final byte regionDataPolicy) {
return registerInterest(key, interestType, policy, isDurable, false, regionDataPolicy);
}
/**
* Does a region registerInterest on a server
*
* @param key describes what we are interested in
* @param interestType the {@link InterestType} for this registration
* @param policy the interest result policy for this registration
* @param isDurable true if this registration is durable
* @param receiveUpdatesAsInvalidates whether to act like notify-by-subscription is false.
* @param regionDataPolicy the data policy ordinal of the region
* @return list of keys
*/
public List registerInterest(final Object key, final int interestType,
final InterestResultPolicy policy, final boolean isDurable,
final boolean receiveUpdatesAsInvalidates, final byte regionDataPolicy) {
if (interestType == InterestType.KEY && key instanceof List) {
return registerInterestList((List) key, policy, isDurable, receiveUpdatesAsInvalidates,
regionDataPolicy);
} else {
final RegisterInterestTracker rit = this.pool.getRITracker();
List result = null;
boolean finished = false;
try {
// register with the tracker early
rit.addSingleInterest(this.region, key, interestType, policy, isDurable,
receiveUpdatesAsInvalidates);
result = RegisterInterestOp.execute(this.pool, this.regionName, key, interestType, policy,
isDurable, receiveUpdatesAsInvalidates, regionDataPolicy);
//////// TEST PURPOSE ONLY ///////////
if (PoolImpl.AFTER_REGISTER_CALLBACK_FLAG) {
ClientServerObserver bo = ClientServerObserverHolder.getInstance();
bo.afterInterestRegistration();
}
/////////////////////////////////////////
finished = true;
return result;
} finally {
if (!finished) {
rit.removeSingleInterest(this.region, key, interestType, isDurable,
receiveUpdatesAsInvalidates);
}
}
}
}
/**
* Support for server-side interest registration
*/
public void addSingleInterest(Object key, int interestType, InterestResultPolicy pol,
boolean isDurable, boolean receiveUpdatesAsInvalidates) {
RegisterInterestTracker rit = this.pool.getRITracker();
boolean finished = false;
try {
rit.addSingleInterest(this.region, key, interestType, pol, isDurable,
receiveUpdatesAsInvalidates);
finished = true;
} finally {
if (!finished) {
rit.removeSingleInterest(this.region, key, interestType, isDurable,
receiveUpdatesAsInvalidates);
}
}
}
public void addListInterest(List keys, InterestResultPolicy pol, boolean isDurable,
boolean receiveUpdatesAsInvalidates) {
RegisterInterestTracker rit = this.pool.getRITracker();
boolean finished = false;
try {
rit.addInterestList(this.region, keys, pol, isDurable, receiveUpdatesAsInvalidates);
finished = true;
} finally {
if (!finished) {
rit.removeInterestList(this.region, keys, isDurable, receiveUpdatesAsInvalidates);
}
}
}
/**
* Support for server-side interest registration
*/
public void removeSingleInterest(Object key, int interestType, boolean isDurable,
boolean receiveUpdatesAsInvalidates) {
this.pool.getRITracker().removeSingleInterest(this.region, key, interestType, isDurable,
receiveUpdatesAsInvalidates);
}
public void removeListInterest(List keys, boolean isDurable,
boolean receiveUpdatesAsInvalidates) {
this.pool.getRITracker().removeInterestList(this.region, keys, isDurable,
receiveUpdatesAsInvalidates);
}
/**
* Does a region registerInterest on a server described by the given server location
* <p>
* Note that this call by-passes the RegisterInterestTracker.
*
* @param sl the server to do the register interest on.
* @param key describes what we are interested in
* @param interestType the {@link InterestType} for this registration
* @param policy the interest result policy for this registration
* @param isDurable true if this registration is durable
* @param regionDataPolicy the data policy ordinal of the region
* @return list of keys
*/
public List registerInterestOn(ServerLocation sl, final Object key, final int interestType,
final InterestResultPolicy policy, final boolean isDurable, final byte regionDataPolicy) {
return registerInterestOn(sl, key, interestType, policy, isDurable, false, regionDataPolicy);
}
/**
* Does a region registerInterest on a server described by the given server location
* <p>
* Note that this call by-passes the RegisterInterestTracker.
*
* @param sl the server to do the register interest on.
* @param key describes what we are interested in
* @param interestType the {@link InterestType} for this registration
* @param policy the interest result policy for this registration
* @param isDurable true if this registration is durable
* @param receiveUpdatesAsInvalidates whether to act like notify-by-subscription is false.
* @param regionDataPolicy the data policy ordinal of the region
* @return list of keys
*/
public List registerInterestOn(ServerLocation sl, final Object key, final int interestType,
final InterestResultPolicy policy, final boolean isDurable,
final boolean receiveUpdatesAsInvalidates, final byte regionDataPolicy) {
if (interestType == InterestType.KEY && key instanceof List) {
return RegisterInterestListOp.executeOn(sl, this.pool, this.regionName, (List) key, policy,
isDurable, receiveUpdatesAsInvalidates, regionDataPolicy);
} else {
return RegisterInterestOp.executeOn(sl, this.pool, this.regionName, key, interestType, policy,
isDurable, receiveUpdatesAsInvalidates, regionDataPolicy);
}
}
/**
* Does a region registerInterest on a server described by the given connection
* <p>
* Note that this call by-passes the RegisterInterestTracker.
*
* @param conn the connection to do the register interest on.
* @param key describes what we are interested in
* @param interestType the {@link InterestType} for this registration
* @param policy the interest result policy for this registration
* @param isDurable true if this registration is durable
* @param regionDataPolicy the data policy ordinal of the region
* @return list of keys
*/
public List registerInterestOn(Connection conn, final Object key, final int interestType,
final InterestResultPolicy policy, final boolean isDurable, final byte regionDataPolicy) {
return registerInterestOn(conn, key, interestType, policy, isDurable, false, regionDataPolicy);
}
/**
* Does a region registerInterest on a server described by the given connection
* <p>
* Note that this call by-passes the RegisterInterestTracker.
*
* @param conn the connection to do the register interest on.
* @param key describes what we are interested in
* @param interestType the {@link InterestType} for this registration
* @param policy the interest result policy for this registration
* @param isDurable true if this registration is durable
* @param receiveUpdatesAsInvalidates whether to act like notify-by-subscription is false.
* @param regionDataPolicy the data policy ordinal of the region
* @return list of keys
*/
public List registerInterestOn(Connection conn, final Object key, final int interestType,
final InterestResultPolicy policy, final boolean isDurable,
final boolean receiveUpdatesAsInvalidates, final byte regionDataPolicy) {
if (interestType == InterestType.KEY && key instanceof List) {
return RegisterInterestListOp.executeOn(conn, this.pool, this.regionName, (List) key, policy,
isDurable, receiveUpdatesAsInvalidates, regionDataPolicy);
} else {
return RegisterInterestOp.executeOn(conn, this.pool, this.regionName, key, interestType,
policy, isDurable, receiveUpdatesAsInvalidates, regionDataPolicy);
}
}
/**
* Does a region registerInterestList on a server
*
* @param keys list of keys we are interested in
* @param policy the interest result policy for this registration
* @param isDurable true if this registration is durable
* @param regionDataPolicy the data policy ordinal of the region
* @return list of keys
*/
public List registerInterestList(List keys, InterestResultPolicy policy, boolean isDurable,
boolean receiveUpdatesAsInvalidates, final byte regionDataPolicy) {
final RegisterInterestTracker rit = this.pool.getRITracker();
List result = null;
boolean finished = false;
try {
// register with the tracker early
rit.addInterestList(this.region, keys, policy, isDurable, receiveUpdatesAsInvalidates);
result = RegisterInterestListOp.execute(this.pool, this.regionName, keys, policy, isDurable,
receiveUpdatesAsInvalidates, regionDataPolicy);
finished = true;
//////// TEST PURPOSE ONLY ///////////
if (PoolImpl.AFTER_REGISTER_CALLBACK_FLAG) {
ClientServerObserver bo = ClientServerObserverHolder.getInstance();
bo.afterInterestRegistration();
}
/////////////////////////////////////////
return result;
} finally {
if (!finished) {
rit.removeInterestList(this.region, keys, isDurable, receiveUpdatesAsInvalidates);
}
}
}
/**
* Does a region unregisterInterest on a server
*
* @param key describes what we are no longer interested in
* @param interestType the {@link InterestType} for this unregister
* @param isClosing true if this unregister is done by a close
* @param keepAlive true if this unregister should not undo a durable registration
*/
public void unregisterInterest(Object key, int interestType, boolean isClosing,
boolean keepAlive) {
if (interestType == InterestType.KEY && key instanceof List) {
unregisterInterestList((List) key, isClosing, keepAlive);
} else {
RegisterInterestTracker rit = this.pool.getRITracker();
boolean removed = rit.removeSingleInterest(this.region, key, interestType, false, false)
|| rit.removeSingleInterest(this.region, key, interestType, true, false)
|| rit.removeSingleInterest(this.region, key, interestType, false, true)
|| rit.removeSingleInterest(this.region, key, interestType, true, true);
if (removed) {
UnregisterInterestOp.execute(this.pool, this.regionName, key, interestType, isClosing,
keepAlive);
}
}
}
/**
* Does a region unregisterInterestList on a server
*
* @param keys list of keys we are interested in
* @param isClosing true if this unregister is done by a close
* @param keepAlive true if this unregister should not undo a durable registration
*/
public void unregisterInterestList(List keys, boolean isClosing, boolean keepAlive) {
RegisterInterestTracker rit = this.pool.getRITracker();
boolean removed = rit.removeInterestList(this.region, keys, false, true)
|| rit.removeInterestList(this.region, keys, false, false)
|| rit.removeInterestList(this.region, keys, true, true)
|| rit.removeInterestList(this.region, keys, true, false);
if (removed) {
UnregisterInterestListOp.execute(this.pool, this.regionName, keys, isClosing, keepAlive);
}
}
public List getInterestList(int interestType) {
return this.pool.getRITracker().getInterestList(this.regionName, interestType);
}
@Override
public VersionedObjectList putAll(Map map, EventID eventId, boolean skipCallbacks,
Object callbackArg) {
recordTXOperation(ServerRegionOperation.PUT_ALL, null, map, eventId);
int txID = TXManagerImpl.getCurrentTXUniqueId();
if (this.pool.getPRSingleHopEnabled() && (txID == TXManagerImpl.NOTX)) {
return PutAllOp.execute(this.pool, this.region, map, eventId, skipCallbacks,
this.pool.getRetryAttempts(), callbackArg);
} else {
return PutAllOp.execute(this.pool, this.region, map, eventId, skipCallbacks, false,
callbackArg);
}
}
@Override
public VersionedObjectList removeAll(Collection<Object> keys, EventID eventId,
Object callbackArg) {
recordTXOperation(ServerRegionOperation.REMOVE_ALL, null, keys, eventId);
int txID = TXManagerImpl.getCurrentTXUniqueId();
if (this.pool.getPRSingleHopEnabled() && (txID == TXManagerImpl.NOTX)) {
return RemoveAllOp.execute(this.pool, this.region, keys, eventId,
this.pool.getRetryAttempts(), callbackArg);
} else {
return RemoveAllOp.execute(this.pool, this.region, keys, eventId, false, callbackArg);
}
}
@Override
public VersionedObjectList getAll(List keys, Object callback) {
recordTXOperation(ServerRegionOperation.GET_ALL, null, keys);
int txID = TXManagerImpl.getCurrentTXUniqueId();
VersionedObjectList result;
if (this.pool.getPRSingleHopEnabled() && (txID == TXManagerImpl.NOTX)) {
result =
GetAllOp.execute(this.pool, this.region, keys, this.pool.getRetryAttempts(), callback);
} else {
result = GetAllOp.execute(this.pool, this.regionName, keys, callback);
}
if (result != null) {
for (Iterator it = result.iterator(); it.hasNext();) {
VersionedObjectList.Entry entry = it.next();
Object key = entry.getKey();
Object value = entry.getValue();
boolean isOnServer = entry.isKeyNotOnServer();
if (!isOnServer) {
if (value instanceof Throwable) {
logger.warn(LocalizedMessage.create(
LocalizedStrings.GetAll_0_CAUGHT_THE_FOLLOWING_EXCEPTION_ATTEMPTING_TO_GET_VALUE_FOR_KEY_1,
new Object[] {value, key}), (Throwable) value);
}
}
}
}
return result;
}
/**
* Release use of this pool
*/
public void detach(boolean keepalive) {
this.pool.getRITracker().unregisterRegion(this, keepalive);
super.detach();
}
public String getRegionName() {
return this.regionName;
}
public Region getRegion() {
return this.region;
}
public void executeFunction(String rgnName, Function function,
ServerRegionFunctionExecutor serverRegionExecutor, ResultCollector resultCollector,
byte hasResult, boolean replaying) {
recordTXOperation(ServerRegionOperation.EXECUTE_FUNCTION, null, Integer.valueOf(1), function,
serverRegionExecutor, resultCollector, Byte.valueOf(hasResult));
int retryAttempts = pool.getRetryAttempts();
if (this.pool.getPRSingleHopEnabled()) {
ClientMetadataService cms = region.getCache().getClientMetadataService();
if (cms.isMetadataStable()) {
if (serverRegionExecutor.getFilter().isEmpty()) {
HashMap<ServerLocation, HashSet<Integer>> serverToBuckets =
cms.groupByServerToAllBuckets(this.region, function.optimizeForWrite());
if (serverToBuckets == null || serverToBuckets.isEmpty()) {
ExecuteRegionFunctionOp.execute(this.pool, rgnName, function, serverRegionExecutor,
resultCollector, hasResult, retryAttempts);
cms.scheduleGetPRMetaData(region, false);
} else {
ExecuteRegionFunctionSingleHopOp.execute(this.pool, this.region, function,
serverRegionExecutor, resultCollector, hasResult, serverToBuckets, retryAttempts,
true);
}
} else {
boolean isBucketFilter = serverRegionExecutor.getExecuteOnBucketSetFlag();
Map<ServerLocation, HashSet> serverToFilterMap =
cms.getServerToFilterMap(serverRegionExecutor.getFilter(), region,
function.optimizeForWrite(), isBucketFilter);
if (serverToFilterMap == null || serverToFilterMap.isEmpty()) {
ExecuteRegionFunctionOp.execute(this.pool, rgnName, function, serverRegionExecutor,
resultCollector, hasResult, retryAttempts);
cms.scheduleGetPRMetaData(region, false);
} else {
ExecuteRegionFunctionSingleHopOp.execute(this.pool, this.region, function,
serverRegionExecutor, resultCollector, hasResult, serverToFilterMap, retryAttempts,
isBucketFilter);
}
}
} else {
cms.scheduleGetPRMetaData(region, false);
ExecuteRegionFunctionOp.execute(this.pool, rgnName, function, serverRegionExecutor,
resultCollector, hasResult, retryAttempts);
}
} else {
ExecuteRegionFunctionOp.execute(this.pool, rgnName, function, serverRegionExecutor,
resultCollector, hasResult, retryAttempts);
}
}
public void executeFunction(String rgnName, String functionId,
ServerRegionFunctionExecutor serverRegionExecutor, ResultCollector resultCollector,
byte hasResult, boolean isHA, boolean optimizeForWrite, boolean replaying) {
recordTXOperation(ServerRegionOperation.EXECUTE_FUNCTION, null, Integer.valueOf(2), functionId,
serverRegionExecutor, resultCollector, Byte.valueOf(hasResult), Boolean.valueOf(isHA),
Boolean.valueOf(optimizeForWrite));
int retryAttempts = pool.getRetryAttempts();
if (this.pool.getPRSingleHopEnabled()) {
ClientMetadataService cms = this.region.getCache().getClientMetadataService();
if (cms.isMetadataStable()) {
if (serverRegionExecutor.getFilter().isEmpty()) {
HashMap<ServerLocation, HashSet<Integer>> serverToBuckets =
cms.groupByServerToAllBuckets(this.region, optimizeForWrite);
if (serverToBuckets == null || serverToBuckets.isEmpty()) {
ExecuteRegionFunctionOp.execute(this.pool, rgnName, functionId, serverRegionExecutor,
resultCollector, hasResult, retryAttempts, isHA, optimizeForWrite);
cms.scheduleGetPRMetaData(this.region, false);
} else {
ExecuteRegionFunctionSingleHopOp.execute(this.pool, this.region, functionId,
serverRegionExecutor, resultCollector, hasResult, serverToBuckets, retryAttempts,
true, isHA, optimizeForWrite);
}
} else {
boolean isBucketsAsFilter = serverRegionExecutor.getExecuteOnBucketSetFlag();
Map<ServerLocation, HashSet> serverToFilterMap = cms.getServerToFilterMap(
serverRegionExecutor.getFilter(), region, optimizeForWrite, isBucketsAsFilter);
if (serverToFilterMap == null || serverToFilterMap.isEmpty()) {
ExecuteRegionFunctionOp.execute(this.pool, rgnName, functionId, serverRegionExecutor,
resultCollector, hasResult, retryAttempts, isHA, optimizeForWrite);
cms.scheduleGetPRMetaData(region, false);
} else {
ExecuteRegionFunctionSingleHopOp.execute(this.pool, this.region, functionId,
serverRegionExecutor, resultCollector, hasResult, serverToFilterMap, retryAttempts,
false, isHA, optimizeForWrite);
}
}
} else {
cms.scheduleGetPRMetaData(region, false);
ExecuteRegionFunctionOp.execute(this.pool, rgnName, functionId, serverRegionExecutor,
resultCollector, hasResult, retryAttempts, isHA, optimizeForWrite);
}
} else {
ExecuteRegionFunctionOp.execute(this.pool, rgnName, functionId, serverRegionExecutor,
resultCollector, hasResult, retryAttempts, isHA, optimizeForWrite);
}
}
public void executeFunctionNoAck(String rgnName, Function function,
ServerRegionFunctionExecutor serverRegionExecutor, byte hasResult, boolean replaying) {
recordTXOperation(ServerRegionOperation.EXECUTE_FUNCTION, null, Integer.valueOf(3), function,
serverRegionExecutor, Byte.valueOf(hasResult));
ExecuteRegionFunctionNoAckOp.execute(this.pool, rgnName, function, serverRegionExecutor,
hasResult);
}
public void executeFunctionNoAck(String rgnName, String functionId,
ServerRegionFunctionExecutor serverRegionExecutor, byte hasResult, boolean isHA,
boolean optimizeForWrite, boolean replaying) {
recordTXOperation(ServerRegionOperation.EXECUTE_FUNCTION, null, Integer.valueOf(4), functionId,
serverRegionExecutor, Byte.valueOf(hasResult));
ExecuteRegionFunctionNoAckOp.execute(this.pool, rgnName, functionId, serverRegionExecutor,
hasResult, isHA, optimizeForWrite);
}
public Entry getEntry(Object key) {
recordTXOperation(ServerRegionOperation.GET_ENTRY, key);
return (Entry) GetEntryOp.execute(pool, region, key);
}
/**
* Transaction synchronization notification to the servers
*
* @see org.apache.geode.internal.cache.tx.ClientTXStateStub#beforeCompletion()
*/
public void beforeCompletion(int txId) {
TXSynchronizationOp.execute(pool, 0, txId,
TXSynchronizationOp.CompletionType.BEFORE_COMPLETION);
}
/**
* Transaction synchronization notification to the servers
*
* @param status
* @return the server's TXCommitMessage
* @see org.apache.geode.internal.cache.tx.ClientTXStateStub#afterCompletion(int)
*/
public TXCommitMessage afterCompletion(int status, int txId) {
return TXSynchronizationOp.execute(pool, status, txId,
TXSynchronizationOp.CompletionType.AFTER_COMPLETION);
}
public byte[] getFunctionAttributes(String functionId) {
return (byte[]) GetFunctionAttributeOp.execute(this.pool, functionId);
}
/** test hook */
private void recordTXOperation(ServerRegionOperation op, Object key, Object... arguments) {
if (ClientTXStateStub.transactionRecordingEnabled()) {
TXStateProxy tx = TXManagerImpl.getCurrentTXState();
if (tx == null) {
return;
}
tx.recordTXOperation(this, op, key, arguments);
}
}
}