use of org.apache.geode.cache.TransactionDataRebalancedException in project geode by apache.
the class RemoteTransactionDUnitTest method testTxFunctionWithOtherOps.
@Test
public void testTxFunctionWithOtherOps() {
Host host = Host.getHost(0);
VM accessor = host.getVM(0);
VM datastore1 = host.getVM(1);
VM datastore2 = host.getVM(2);
initAccessorAndDataStore(accessor, datastore1, datastore2, 0);
SerializableCallable registerFunction = new SerializableCallable() {
public Object call() throws Exception {
FunctionService.registerFunction(new TXFunction());
return null;
}
};
accessor.invoke(registerFunction);
datastore1.invoke(registerFunction);
datastore2.invoke(registerFunction);
accessor.invoke(new SerializableCallable() {
public Object call() throws Exception {
Region custRegion = getGemfireCache().getRegion(CUSTOMER);
TXManagerImpl mgr = getGemfireCache().getTXMgr();
mgr.begin();
try {
FunctionService.onRegion(custRegion).execute(TXFunction.id).getResult();
fail("Expected exception not thrown");
} catch (TransactionException expected) {
}
Set filter = new HashSet();
filter.add(expectedCustId);
FunctionService.onRegion(custRegion).withFilter(filter).execute(TXFunction.id).getResult();
assertEquals(expectedCustomer, custRegion.get(expectedCustId));
TXStateProxy tx = mgr.internalSuspend();
assertNull(custRegion.get(expectedCustId));
mgr.internalResume(tx);
return null;
}
});
final Integer txOnDatastore1 = (Integer) datastore1.invoke(getNumberOfTXInProgress);
final Integer txOnDatastore2 = (Integer) datastore2.invoke(getNumberOfTXInProgress);
assertEquals(1, txOnDatastore1 + txOnDatastore2);
accessor.invoke(new SerializableCallable() {
public Object call() throws Exception {
Region custRegion = getGemfireCache().getRegion(CUSTOMER);
CacheTransactionManager mgr = getGemfireCache().getTXMgr();
mgr.commit();
assertEquals(expectedCustomer, custRegion.get(expectedCustId));
custRegion.destroy(expectedCustId);
return null;
}
});
// test onMembers
SerializableCallable getMember = new SerializableCallable() {
public Object call() throws Exception {
return getGemfireCache().getMyId();
}
};
final InternalDistributedMember ds1 = (InternalDistributedMember) datastore1.invoke(getMember);
final InternalDistributedMember ds2 = (InternalDistributedMember) datastore2.invoke(getMember);
accessor.invoke(new SerializableCallable() {
public Object call() throws Exception {
PartitionedRegion pr = (PartitionedRegion) getGemfireCache().getRegion(CUSTOMER);
// get owner for expectedKey
DistributedMember owner = pr.getOwnerForKey(pr.getKeyInfo(expectedCustId));
// get key on datastore1
CustId keyOnOwner = null;
keyOnOwner = getKeyOnMember(owner, pr);
TXManagerImpl mgr = getGemfireCache().getTXMgr();
mgr.begin();
// bootstrap tx on owner
pr.get(keyOnOwner);
Set<DistributedMember> members = new HashSet<DistributedMember>();
members.add(ds1);
members.add(ds2);
try {
FunctionService.onMembers(members).execute(TXFunction.id).getResult();
fail("expected exception not thrown");
} catch (TransactionException expected) {
}
FunctionService.onMember(owner).execute(TXFunction.id).getResult();
assertEquals(expectedCustomer, pr.get(expectedCustId));
TXStateProxy tx = mgr.internalSuspend();
assertNull(pr.get(expectedCustId));
mgr.internalResume(tx);
return null;
}
});
final Integer txOnDatastore1_1 = (Integer) datastore1.invoke(getNumberOfTXInProgress);
final Integer txOnDatastore2_1 = (Integer) datastore2.invoke(getNumberOfTXInProgress);
assertEquals(1, txOnDatastore1_1 + txOnDatastore2_1);
accessor.invoke(new SerializableCallable() {
public Object call() throws Exception {
Region custRegion = getGemfireCache().getRegion(CUSTOMER);
CacheTransactionManager mgr = getGemfireCache().getTXMgr();
mgr.commit();
assertEquals(expectedCustomer, custRegion.get(expectedCustId));
custRegion.destroy(expectedCustId);
return null;
}
});
// test function execution on data store
final DistributedMember owner = (DistributedMember) accessor.invoke(new SerializableCallable() {
public Object call() throws Exception {
PartitionedRegion pr = (PartitionedRegion) getGemfireCache().getRegion(CUSTOMER);
return pr.getOwnerForKey(pr.getKeyInfo(expectedCustId));
}
});
SerializableCallable testFnOnDs = new SerializableCallable() {
public Object call() throws Exception {
TXManagerImpl mgr = getGemfireCache().getTXMgr();
PartitionedRegion pr = (PartitionedRegion) getGemfireCache().getRegion(CUSTOMER);
CustId keyOnDs = getKeyOnMember(pr.getMyId(), pr);
mgr.begin();
pr.get(keyOnDs);
Set filter = new HashSet();
filter.add(keyOnDs);
FunctionService.onRegion(pr).withFilter(filter).execute(TXFunction.id).getResult();
assertEquals(expectedCustomer, pr.get(expectedCustId));
TXStateProxy tx = mgr.internalSuspend();
assertNull(pr.get(expectedCustId));
mgr.internalResume(tx);
return null;
}
};
SerializableCallable closeTx = new SerializableCallable() {
public Object call() throws Exception {
Region custRegion = getGemfireCache().getRegion(CUSTOMER);
CacheTransactionManager mgr = getGemfireCache().getTXMgr();
mgr.commit();
assertEquals(expectedCustomer, custRegion.get(expectedCustId));
custRegion.destroy(expectedCustId);
return null;
}
};
if (owner.equals(ds1)) {
datastore1.invoke(testFnOnDs);
final Integer txOnDatastore1_2 = (Integer) datastore1.invoke(getNumberOfTXInProgress);
final Integer txOnDatastore2_2 = (Integer) datastore2.invoke(getNumberOfTXInProgress);
// ds1 has a local transaction, not
assertEquals(0, txOnDatastore1_2 + txOnDatastore2_2);
// remote
datastore1.invoke(closeTx);
} else {
datastore2.invoke(testFnOnDs);
final Integer txOnDatastore1_2 = (Integer) datastore1.invoke(getNumberOfTXInProgress);
final Integer txOnDatastore2_2 = (Integer) datastore2.invoke(getNumberOfTXInProgress);
// ds1 has a local transaction, not
assertEquals(0, txOnDatastore1_2 + txOnDatastore2_2);
// remote
datastore2.invoke(closeTx);
}
// test that function is rejected if function target is not same as txState target
accessor.invoke(new SerializableCallable() {
public Object call() throws Exception {
CacheTransactionManager mgr = getGemfireCache().getTXMgr();
PartitionedRegion pr = (PartitionedRegion) getGemfireCache().getRegion(CUSTOMER);
CustId keyOnDs1 = getKeyOnMember(ds1, pr);
CustId keyOnDs2 = getKeyOnMember(ds2, pr);
mgr.begin();
// bootstrap txState
pr.get(keyOnDs1);
Set filter = new HashSet();
filter.add(keyOnDs2);
try {
FunctionService.onRegion(pr).withFilter(filter).execute(TXFunction.id).getResult();
fail("expected Exception not thrown");
} catch (TransactionDataRebalancedException expected) {
}
try {
FunctionService.onMember(ds2).execute(TXFunction.id).getResult();
fail("expected exception not thrown");
} catch (TransactionDataNotColocatedException expected) {
}
mgr.commit();
return null;
}
});
}
use of org.apache.geode.cache.TransactionDataRebalancedException in project geode by apache.
the class PartitionedRegion method getDataRegionForRead.
@Override
public LocalRegion getDataRegionForRead(final KeyInfo keyInfo) {
final Object entryKey = keyInfo.getKey();
BucketRegion br;
try {
PartitionedRegionDataStore ds = getDataStore();
if (ds == null) {
throw new TransactionException(LocalizedStrings.PartitionedRegion_TX_ON_DATASTORE.toLocalizedString());
}
// TODO provide appropriate Operation and arg
int bucketId = keyInfo.getBucketId();
if (bucketId == KeyInfo.UNKNOWN_BUCKET) {
bucketId = PartitionedRegionHelper.getHashKey(this, null, entryKey, keyInfo.getValue(), keyInfo.getCallbackArg());
keyInfo.setBucketId(bucketId);
}
br = ds.getInitializedBucketWithKnownPrimaryForId(null, bucketId);
if (keyInfo.isCheckPrimary()) {
try {
br.checkForPrimary();
} catch (PrimaryBucketException pbe) {
throw new TransactionDataRebalancedException(LocalizedStrings.PartitionedRegion_TRANSACTIONAL_DATA_MOVED_DUE_TO_REBALANCING.toLocalizedString(), pbe);
}
}
} catch (RegionDestroyedException ignore) {
// TODO: why is this purposely not wrapping the original cause?
throw new TransactionDataNotColocatedException(LocalizedStrings.PartitionedRegion_KEY_0_NOT_COLOCATED_WITH_TRANSACTION.toLocalizedString(entryKey));
} catch (ForceReattemptException ignore) {
br = null;
}
return br;
}
use of org.apache.geode.cache.TransactionDataRebalancedException in project geode by apache.
the class PartitionedRegion method getFromBucket.
/**
* @param requestingClient the client requesting the object, or null if not from a client
* @param allowRetry if false then do not retry
*/
private Object getFromBucket(final InternalDistributedMember targetNode, int bucketId, final Object key, final Object aCallbackArgument, boolean disableCopyOnRead, boolean preferCD, ClientProxyMembershipID requestingClient, EntryEventImpl clientEvent, boolean returnTombstones, boolean allowRetry) {
final boolean isDebugEnabled = logger.isDebugEnabled();
final int retryAttempts = calcRetry();
Object obj;
// retry the get remotely until it finds the right node managing the bucket
int count = 0;
RetryTimeKeeper retryTime = null;
InternalDistributedMember retryNode = targetNode;
while (count <= retryAttempts) {
// Every continuation should check for DM cancellation
if (retryNode == null) {
checkReadiness();
if (retryTime == null) {
retryTime = new RetryTimeKeeper(this.retryTimeout);
}
retryNode = getNodeForBucketReadOrLoad(bucketId);
// No storage found for bucket, early out preventing hot loop, bug 36819
if (retryNode == null) {
checkShutdown();
return null;
}
continue;
}
final boolean isLocal = this.localMaxMemory > 0 && retryNode.equals(getMyId());
try {
if (isLocal) {
obj = this.dataStore.getLocally(bucketId, key, aCallbackArgument, disableCopyOnRead, preferCD, requestingClient, clientEvent, returnTombstones, false);
} else {
if (this.haveCacheLoader) {
/* MergeGemXDHDFSToGFE -readoing from local bucket was disabled in GemXD */
if (null != (obj = getFromLocalBucket(bucketId, key, aCallbackArgument, disableCopyOnRead, preferCD, requestingClient, clientEvent, returnTombstones))) {
return obj;
}
}
obj = getRemotely(retryNode, bucketId, key, aCallbackArgument, preferCD, requestingClient, clientEvent, returnTombstones);
// TODO: there should be better way than this one
String name = Thread.currentThread().getName();
if (name.startsWith("ServerConnection") && !getMyId().equals(retryNode)) {
setNetworkHopType(bucketId, (InternalDistributedMember) retryNode);
}
}
return obj;
} catch (PRLocallyDestroyedException pde) {
if (isDebugEnabled) {
logger.debug("getFromBucket Encountered PRLocallyDestroyedException", pde);
}
checkReadiness();
if (allowRetry) {
retryNode = getNodeForBucketReadOrLoad(bucketId);
} else {
// Only transactions set allowRetry to false,
// fail the transaction here as region is destroyed.
Throwable cause = pde.getCause();
if (cause != null && cause instanceof RegionDestroyedException) {
throw (RegionDestroyedException) cause;
} else {
// set the cause to RegionDestroyedException.
throw new RegionDestroyedException(toString(), getFullPath());
}
}
} catch (ForceReattemptException prce) {
prce.checkKey(key);
checkReadiness();
if (allowRetry) {
InternalDistributedMember lastNode = retryNode;
if (isDebugEnabled) {
logger.debug("getFromBucket: retry attempt: {} of {}", count, retryAttempts, prce);
}
retryNode = getNodeForBucketReadOrLoad(bucketId);
if (lastNode.equals(retryNode)) {
if (retryTime == null) {
retryTime = new RetryTimeKeeper(this.retryTimeout);
}
if (retryTime.overMaximum()) {
break;
}
if (isDebugEnabled) {
logger.debug("waiting to retry node {}", retryNode);
}
retryTime.waitToRetryNode();
}
} else {
// with transaction
if (prce instanceof BucketNotFoundException) {
throw new TransactionDataRebalancedException(LocalizedStrings.PartitionedRegion_TRANSACTIONAL_DATA_MOVED_DUE_TO_REBALANCING.toLocalizedString(key), prce);
}
Throwable cause = prce.getCause();
if (cause instanceof PrimaryBucketException) {
throw (PrimaryBucketException) cause;
} else if (cause instanceof TransactionDataRebalancedException) {
throw (TransactionDataRebalancedException) cause;
} else if (cause instanceof RegionDestroyedException) {
throw new TransactionDataRebalancedException(LocalizedStrings.PartitionedRegion_TRANSACTIONAL_DATA_MOVED_DUE_TO_REBALANCING.toLocalizedString(key), cause);
} else {
// Should not see it currently, added to be protected against future changes.
throw new TransactionException("Failed to get key: " + key, prce);
}
}
} catch (PrimaryBucketException notPrimary) {
if (allowRetry) {
if (isDebugEnabled) {
logger.debug("getFromBucket: {} on Node {} not primary", notPrimary.getLocalizedMessage(), retryNode);
}
getRegionAdvisor().notPrimary(bucketId, retryNode);
retryNode = getNodeForBucketReadOrLoad(bucketId);
} else {
throw notPrimary;
}
}
// It's possible this is a GemFire thread e.g. ServerConnection
// which got to this point because of a distributed system shutdown or
// region closure which uses interrupt to break any sleep() or wait()
// calls
// e.g. waitForPrimary
checkShutdown();
count++;
if (count == 1) {
this.prStats.incGetOpsRetried();
}
this.prStats.incGetRetries();
if (isDebugEnabled) {
logger.debug("getFromBucket: Attempting to resend get to node {} after {} failed attempts", retryNode, count);
}
}
// While
// Fix for bug 36014
PartitionedRegionDistributionException e = null;
if (logger.isDebugEnabled()) {
e = new PartitionedRegionDistributionException(LocalizedStrings.PartitionRegion_NO_VM_AVAILABLE_FOR_GET_IN_0_ATTEMPTS.toLocalizedString(count));
}
logger.warn(LocalizedMessage.create(LocalizedStrings.PartitionRegion_NO_VM_AVAILABLE_FOR_GET_IN_0_ATTEMPTS, count), e);
return null;
}
use of org.apache.geode.cache.TransactionDataRebalancedException in project geode by apache.
the class PartitionedTXRegionStub method destroyExistingEntry.
public void destroyExistingEntry(EntryEventImpl event, boolean cacheWrite, Object expectedOldValue) {
PartitionedRegion pr = (PartitionedRegion) event.getLocalRegion();
try {
pr.destroyRemotely(state.getTarget(), event.getKeyInfo().getBucketId(), event, expectedOldValue);
} catch (TransactionException e) {
RuntimeException re = getTransactionException(event.getKeyInfo(), e);
re.initCause(e.getCause());
throw re;
} catch (PrimaryBucketException e) {
RuntimeException re = getTransactionException(event.getKeyInfo(), e);
re.initCause(e);
throw re;
} catch (ForceReattemptException e) {
RuntimeException re;
if (isBucketNotFoundException(e)) {
re = new TransactionDataRebalancedException(LocalizedStrings.PartitionedRegion_TRANSACTIONAL_DATA_MOVED_DUE_TO_REBALANCING.toLocalizedString());
} else {
re = new TransactionDataNodeHasDepartedException(LocalizedStrings.PartitionedRegion_TRANSACTION_DATA_NODE_0_HAS_DEPARTED_TO_PROCEED_ROLLBACK_THIS_TRANSACTION_AND_BEGIN_A_NEW_ONE.toLocalizedString(state.getTarget()));
}
re.initCause(e);
waitToRetry();
throw re;
}
trackBucketForTx(event.getKeyInfo());
}
use of org.apache.geode.cache.TransactionDataRebalancedException in project geode by apache.
the class PartitionedTXRegionStub method invalidateExistingEntry.
public void invalidateExistingEntry(EntryEventImpl event, boolean invokeCallbacks, boolean forceNewEntry) {
PartitionedRegion pr = (PartitionedRegion) event.getLocalRegion();
try {
pr.invalidateRemotely(state.getTarget(), event.getKeyInfo().getBucketId(), event);
} catch (TransactionException e) {
RuntimeException re = getTransactionException(event.getKeyInfo(), e);
re.initCause(e.getCause());
throw re;
} catch (PrimaryBucketException e) {
RuntimeException re = getTransactionException(event.getKeyInfo(), e);
re.initCause(e);
throw re;
} catch (ForceReattemptException e) {
RuntimeException re;
if (isBucketNotFoundException(e)) {
re = new TransactionDataRebalancedException(LocalizedStrings.PartitionedRegion_TRANSACTIONAL_DATA_MOVED_DUE_TO_REBALANCING.toLocalizedString());
} else {
re = new TransactionDataNodeHasDepartedException(LocalizedStrings.PartitionedRegion_TRANSACTION_DATA_NODE_0_HAS_DEPARTED_TO_PROCEED_ROLLBACK_THIS_TRANSACTION_AND_BEGIN_A_NEW_ONE.toLocalizedString(state.getTarget()));
}
re.initCause(e);
waitToRetry();
throw re;
}
trackBucketForTx(event.getKeyInfo());
}
Aggregations