From 5da6d76ec72eb28052ab8a54cbfcfaa78d87fa2c Mon Sep 17 00:00:00 2001 From: Mario Ivanac Date: Wed, 15 May 2019 23:26:57 +0200 Subject: [PATCH 1/3] GEODE-6641: Code impacts for support for two phase commit transactions Added test --- clicache/src/Cache.cpp | 3 +- clicache/src/CacheTransactionManager.hpp | 7 +- .../include/geode/CacheTransactionManager.hpp | 32 ++++++ .../ThinClientTransactions.hpp | 101 +++++++++++++++++- .../ThinClientTransactionsXA.hpp | 36 ++----- .../testThinClientTransactionsWithSticky.cpp | 4 + ...estThinClientTransactionsWithoutSticky.cpp | 4 + cppcache/src/CacheImpl.cpp | 2 +- .../InternalCacheTransactionManager2PC.cpp | 27 ----- .../InternalCacheTransactionManager2PC.hpp | 75 ------------- ...InternalCacheTransactionManager2PCImpl.hpp | 4 +- 11 files changed, 154 insertions(+), 141 deletions(-) delete mode 100644 cppcache/src/InternalCacheTransactionManager2PC.cpp delete mode 100644 cppcache/src/InternalCacheTransactionManager2PC.hpp diff --git a/clicache/src/Cache.cpp b/clicache/src/Cache.cpp index 9c133fd5df..622ff85d70 100644 --- a/clicache/src/Cache.cpp +++ b/clicache/src/Cache.cpp @@ -99,8 +99,7 @@ namespace Apache // TODO shared_ptr this should be checking the return type for which tx mgr try { - auto nativeptr = std::dynamic_pointer_cast( - m_nativeptr->get()->getCacheTransactionManager()); + auto nativeptr = m_nativeptr->get()->getCacheTransactionManager(); return Apache::Geode::Client::CacheTransactionManager::Create(nativeptr.get()); } finally diff --git a/clicache/src/CacheTransactionManager.hpp b/clicache/src/CacheTransactionManager.hpp index bddb407caa..00f2dbf956 100644 --- a/clicache/src/CacheTransactionManager.hpp +++ b/clicache/src/CacheTransactionManager.hpp @@ -21,7 +21,6 @@ #include "geode_defs.hpp" #include "begin_native.hpp" #include -#include "InternalCacheTransactionManager2PC.hpp" #include "end_native.hpp" #include "native_shared_ptr.hpp" #include "TransactionId.hpp" @@ -204,7 +203,7 @@ namespace Apache internal: - inline static CacheTransactionManager^ Create(native::InternalCacheTransactionManager2PC* nativeptr ) + inline static CacheTransactionManager^ Create(native::CacheTransactionManager* nativeptr ) { return ( nativeptr != nullptr ? gcnew CacheTransactionManager( nativeptr ) : nullptr ); @@ -217,12 +216,12 @@ namespace Apache /// Private constructor to wrap a native object pointer /// /// The native object pointer - inline CacheTransactionManager(native::InternalCacheTransactionManager2PC* nativeptr ) + inline CacheTransactionManager(native::CacheTransactionManager* nativeptr ) : m_nativeptr(nativeptr) { } - native::InternalCacheTransactionManager2PC* m_nativeptr; + native::CacheTransactionManager* m_nativeptr; }; } // namespace Client } // namespace Geode diff --git a/cppcache/include/geode/CacheTransactionManager.hpp b/cppcache/include/geode/CacheTransactionManager.hpp index 06ebc08c5b..4fa3ebbeea 100644 --- a/cppcache/include/geode/CacheTransactionManager.hpp +++ b/cppcache/include/geode/CacheTransactionManager.hpp @@ -47,6 +47,38 @@ class APACHE_GEODE_EXPORT CacheTransactionManager { */ virtual void begin() = 0; + /** + * Performs prepare during 2 phase commit completion, for the transaction + * associated with the current thread. + * Locks of the entries modified in the current transaction on the server + * side. If the prepare operation fails due to a conflict it will destroy + * the transaction state and throw a {@link CommitConflictException}. + * If the prepare operation succeeds, transaction state is set to + * prepared state. When this method completes, the thread is still + * associated with a transaction, and is waiting on commit or rollback + * operation. + * + * @throws IllegalStateException if the thread is not associated with a + * transaction + * + * @throws CommitConflictException if the commit operation fails due to + * a write conflict. + * + * @throws TransactionDataNodeHasDepartedException if the node hosting the + * transaction data has departed. This is only relevant for transaction that + * involve PartitionedRegions. + * + * @throws TransactionDataNotColocatedException if at commit time, the data + * involved in the transaction has moved away from the transaction hosting + * node. This can only happen if rebalancing/recovery happens during a + * transaction that involves a PartitionedRegion. + * + * @throws TransactionInDoubtException when Geode cannot tell which nodes + * have applied the transaction and which have not. This only occurs if nodes + * fail mid-commit, and only then in very rare circumstances. + */ + virtual void prepare() = 0; + /** Commit the transaction associated with the current thread. If * the commit operation fails due to a conflict it will destroy * the transaction state and throw a {@link diff --git a/cppcache/integration-test/ThinClientTransactions.hpp b/cppcache/integration-test/ThinClientTransactions.hpp index 0f9e22c859..c49b5de994 100644 --- a/cppcache/integration-test/ThinClientTransactions.hpp +++ b/cppcache/integration-test/ThinClientTransactions.hpp @@ -349,12 +349,15 @@ void doNetsearch(const char* name, const char* key, const char* value) { } const char* keys[] = {"Key-1", "Key-2", "Key-3", "Key-4", - "Key-5", "Key-6", "Key-7"}; + "Key-5", "Key-6", "Key-7", "Key-8", + "Key-9", "Key-10", "Key-11"}; const char* vals[] = {"Value-1", "Value-2", "Value-3", "Value-4", - "Value-5", "Value-6", "Value-7"}; + "Value-5", "Value-6", "Value-7", "Value-8", + "Value-9", "Value-10", "Value-11"}; const char* nvals[] = {"New Value-1", "New Value-2", "New Value-3", "New Value-4", "New Value-5", "New Value-6", - "New Value-7"}; + "New Value-7", "New Value-8", "New Value-9", + "New Value-10", "New Value-11"}; const char* regionNames[] = {"DistRegionAck", "DistRegionNoAck", "testregion"}; @@ -1002,6 +1005,98 @@ DUNIT_TASK_DEFINITION(CLIENT2, UpdateClient2Entries) LOG("StepSix complete."); } END_TASK_DEFINITION +DUNIT_TASK_DEFINITION(CLIENT1, CreateClient1additionalEntries) + { + auto txManager = getHelper()->getCache()->getCacheTransactionManager(); + txManager->begin(); + createEntry(regionNames[0], keys[7], vals[7]); + createEntry(regionNames[1], keys[8], vals[8]); + txManager->prepare(); + txManager->commit(); + verifyEntry(regionNames[0], keys[7], vals[7]); + verifyEntry(regionNames[1], keys[8], vals[8]); + txManager->begin(); + updateEntry(regionNames[0], keys[7], nvals[7]); + updateEntry(regionNames[1], keys[8], nvals[8]); + txManager->commit(); + verifyEntry(regionNames[0], keys[7], nvals[7]); + verifyEntry(regionNames[1], keys[8], nvals[8]); + LOG("StepSeven complete."); + } +END_TASK_DEFINITION +DUNIT_TASK_DEFINITION(CLIENT2, CreateClient2additionalEntries) + { + doNetsearch(regionNames[0], keys[0], vals[0]); + doNetsearch(regionNames[1], keys[2], vals[2]); + auto txManager = getHelper()->getCache()->getCacheTransactionManager(); + txManager->begin(); + createEntry(regionNames[0], keys[9], vals[9]); + createEntry(regionNames[1], keys[10], vals[10]); + txManager->commit(); + verifyEntry(regionNames[0], keys[9], vals[9]); + verifyEntry(regionNames[1], keys[10], vals[10]); + txManager->begin(); + updateEntry(regionNames[0], keys[9], nvals[9]); + updateEntry(regionNames[1], keys[10], nvals[10]); + txManager->prepare(); + txManager->commit(); + verifyEntry(regionNames[0], keys[9], nvals[9]); + verifyEntry(regionNames[1], keys[10], nvals[10]); + LOG("StepEight complete."); + } +END_TASK_DEFINITION +DUNIT_TASK_DEFINITION(CLIENT1, UpdateClient1additionalEntries) + { + auto txManager = getHelper()->getCache()->getCacheTransactionManager(); + txManager->begin(); + updateEntry(regionNames[0], keys[7], vals[5]); + updateEntry(regionNames[1], keys[8], vals[6]); + txManager->commit(); + verifyEntry(regionNames[0], keys[7], vals[5]); + verifyEntry(regionNames[1], keys[8], vals[6]); + txManager->begin(); + updateEntry(regionNames[0], keys[7], vals[7]); + updateEntry(regionNames[1], keys[8], vals[8]); + txManager->prepare(); + txManager->rollback(); + verifyEntry(regionNames[0], keys[7], vals[5]); + verifyEntry(regionNames[1], keys[8], vals[6]); + txManager->begin(); + updateEntry(regionNames[0], keys[7], nvals[7]); + updateEntry(regionNames[1], keys[8], nvals[8]); + txManager->commit(); + verifyEntry(regionNames[0], keys[7], nvals[7]); + verifyEntry(regionNames[1], keys[8], nvals[8]); + LOG("StepNine complete."); + } +END_TASK_DEFINITION +DUNIT_TASK_DEFINITION(CLIENT2, UpdateClient2additionalEntries) + { + auto txManager = getHelper()->getCache()->getCacheTransactionManager(); + txManager->begin(); + updateEntry(regionNames[0], keys[9], nvals[7]); + updateEntry(regionNames[1], keys[10], nvals[8]); + txManager->prepare(); + txManager->commit(); + verifyEntry(regionNames[0], keys[9], nvals[7]); + verifyEntry(regionNames[1], keys[10], nvals[8]); + txManager->begin(); + updateEntry(regionNames[0], keys[9], nvals[9]); + updateEntry(regionNames[1], keys[10], nvals[10]); + txManager->rollback(); + verifyEntry(regionNames[0], keys[9], nvals[7]); + verifyEntry(regionNames[1], keys[10], nvals[8]); + txManager->begin(); + updateEntry(regionNames[0], keys[9], nvals[9]); + updateEntry(regionNames[1], keys[10], nvals[10]); + txManager->prepare(); + txManager->commit(); + verifyEntry(regionNames[0], keys[9], nvals[9]); + verifyEntry(regionNames[1], keys[10], nvals[10]); + LOG("StepTen complete."); + } +END_TASK_DEFINITION + DUNIT_TASK_DEFINITION(CLIENT1, CreateClient1EntryTwice) { createEntryTwice(regionNames[0], CREATE_TWICE_KEY, CREATE_TWICE_VALUE); } END_TASK_DEFINITION diff --git a/cppcache/integration-test/ThinClientTransactionsXA.hpp b/cppcache/integration-test/ThinClientTransactionsXA.hpp index e52a26f162..70b5c4be6b 100644 --- a/cppcache/integration-test/ThinClientTransactionsXA.hpp +++ b/cppcache/integration-test/ThinClientTransactionsXA.hpp @@ -27,7 +27,7 @@ #include #include -#include +#include #define ROOT_NAME "ThinClientTransactionsXA" #define ROOT_SCOPE DISTRIBUTED_ACK @@ -43,7 +43,7 @@ using apache::geode::client::CacheServerException; using apache::geode::client::EntryExistsException; using apache::geode::client::EntryNotFoundException; using apache::geode::client::IllegalStateException; -using apache::geode::client::InternalCacheTransactionManager2PC; +using apache::geode::client::CacheTransactionManager; using apache::geode::client::Properties; using apache::geode::client::TransactionException; using apache::geode::client::TransactionId; @@ -384,9 +384,7 @@ class SuspendTransactionThread : public ACE_Task_Base { sprintf(buf, " In SuspendTransactionThread"); LOG(buf); - auto txManager = - std::dynamic_pointer_cast( - getHelper()->getCache()->getCacheTransactionManager()); + auto txManager = getHelper()->getCache()->getCacheTransactionManager(); txManager->begin(); @@ -462,9 +460,7 @@ class ResumeTransactionThread : public ACE_Task_Base { "In ResumeTransactionThread - Key should not have been " "found in region."); - auto txManager = - std::dynamic_pointer_cast( - getHelper()->getCache()->getCacheTransactionManager()); + auto txManager = getHelper()->getCache()->getCacheTransactionManager(); if (m_tryResumeWithSleep) { THREADERRORCHECK(!txManager->isSuspended(m_suspendedTransaction), "In ResumeTransactionThread - the transaction should " @@ -580,9 +576,7 @@ END_TASK_DEFINITION DUNIT_TASK_DEFINITION(CLIENT1, SuspendResumeCommit) { - auto txManager = - std::dynamic_pointer_cast( - getHelper()->getCache()->getCacheTransactionManager()); + auto txManager = getHelper()->getCache()->getCacheTransactionManager(); auto regPtr0 = getHelper()->getRegion(regionNames[0]); ASSERT(regPtr0 != nullptr, "In SuspendResumeCommit - Region not found."); auto regPtr1 = getHelper()->getRegion(regionNames[1]); @@ -665,9 +659,7 @@ END_TASK_DEFINITION DUNIT_TASK_DEFINITION(CLIENT1, SuspendTimeOut) { - auto txManager = - std::dynamic_pointer_cast( - getHelper()->getCache()->getCacheTransactionManager()); + auto txManager = getHelper()->getCache()->getCacheTransactionManager(); auto keyPtr4 = CacheableKey::create(keys[4]); auto keyPtr5 = CacheableKey::create(keys[5]); @@ -709,9 +701,7 @@ END_TASK_DEFINITION DUNIT_TASK_DEFINITION(CLIENT1, SuspendResumeRollback) { - auto txManager = - std::dynamic_pointer_cast( - getHelper()->getCache()->getCacheTransactionManager()); + auto txManager = getHelper()->getCache()->getCacheTransactionManager(); auto keyPtr4 = CacheableKey::create(keys[4]); auto keyPtr5 = CacheableKey::create(keys[5]); auto keyPtr6 = CacheableKey::create(keys[6]); @@ -951,9 +941,7 @@ END_TASK_DEFINITION DUNIT_TASK_DEFINITION(CLIENT1, StepThree) { - auto txManager = - std::dynamic_pointer_cast( - getHelper()->getCache()->getCacheTransactionManager()); + auto txManager = getHelper()->getCache()->getCacheTransactionManager(); txManager->begin(); createEntry(regionNames[0], keys[0], vals[0]); createEntry(regionNames[1], keys[2], vals[2]); @@ -967,9 +955,7 @@ DUNIT_TASK_DEFINITION(CLIENT2, StepFour) { doNetsearch(regionNames[0], keys[0], vals[0]); doNetsearch(regionNames[1], keys[2], vals[2]); - auto txManager = - std::dynamic_pointer_cast( - getHelper()->getCache()->getCacheTransactionManager()); + auto txManager = getHelper()->getCache()->getCacheTransactionManager(); txManager->begin(); createEntry(regionNames[0], keys[1], vals[1]); createEntry(regionNames[1], keys[3], vals[3]); @@ -1016,9 +1002,7 @@ DUNIT_TASK_DEFINITION(CLIENT2, StepSix) { doNetsearch(regionNames[0], keys[0], vals[0]); doNetsearch(regionNames[1], keys[2], vals[2]); - auto txManager = - std::dynamic_pointer_cast( - getHelper()->getCache()->getCacheTransactionManager()); + auto txManager = getHelper()->getCache()->getCacheTransactionManager(); txManager->begin(); updateEntry(regionNames[0], keys[1], nvals[1]); updateEntry(regionNames[1], keys[3], nvals[3]); diff --git a/cppcache/integration-test/testThinClientTransactionsWithSticky.cpp b/cppcache/integration-test/testThinClientTransactionsWithSticky.cpp index d27131d521..6d0aba8269 100644 --- a/cppcache/integration-test/testThinClientTransactionsWithSticky.cpp +++ b/cppcache/integration-test/testThinClientTransactionsWithSticky.cpp @@ -33,6 +33,10 @@ DUNIT_MAIN CALL_TASK(CreateClient1EntryTwice); CALL_TASK(CreateClient1KeyThriceWithSticky); + CALL_TASK(CreateClient1additionalEntries); + CALL_TASK(CreateClient2additionalEntries); + CALL_TASK(UpdateClient1additionalEntries); + CALL_TASK(UpdateClient2additionalEntries); CALL_TASK(SuspendResumeInThread); CALL_TASK(SuspendResumeCommit); diff --git a/cppcache/integration-test/testThinClientTransactionsWithoutSticky.cpp b/cppcache/integration-test/testThinClientTransactionsWithoutSticky.cpp index e3d2351cea..22cd8ed6a3 100644 --- a/cppcache/integration-test/testThinClientTransactionsWithoutSticky.cpp +++ b/cppcache/integration-test/testThinClientTransactionsWithoutSticky.cpp @@ -33,6 +33,10 @@ DUNIT_MAIN CALL_TASK(CreateClient1EntryTwice); CALL_TASK(CreateClient1KeyThriceWithoutSticky); + CALL_TASK(CreateClient1additionalEntries); + CALL_TASK(CreateClient2additionalEntries); + CALL_TASK(UpdateClient1additionalEntries); + CALL_TASK(UpdateClient2additionalEntries); CALL_TASK(SuspendResumeInThread); CALL_TASK(SuspendResumeCommit); diff --git a/cppcache/src/CacheImpl.cpp b/cppcache/src/CacheImpl.cpp index 4ba2b12e0a..7853fdc130 100644 --- a/cppcache/src/CacheImpl.cpp +++ b/cppcache/src/CacheImpl.cpp @@ -79,7 +79,7 @@ CacheImpl::CacheImpl(Cache* c, const std::shared_ptr& dsProps, m_authInitialize(authInitialize) { using apache::geode::statistics::StatisticsManager; - m_cacheTXManager = std::shared_ptr( + m_cacheTXManager = std::shared_ptr( new InternalCacheTransactionManager2PCImpl(this)); auto& prop = m_distributedSystem.getSystemProperties(); diff --git a/cppcache/src/InternalCacheTransactionManager2PC.cpp b/cppcache/src/InternalCacheTransactionManager2PC.cpp deleted file mode 100644 index f511acb103..0000000000 --- a/cppcache/src/InternalCacheTransactionManager2PC.cpp +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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. - */ - -#include "InternalCacheTransactionManager2PC.hpp" - -namespace apache { -namespace geode { -namespace client { -InternalCacheTransactionManager2PC::InternalCacheTransactionManager2PC() {} -InternalCacheTransactionManager2PC::~InternalCacheTransactionManager2PC() {} -} // namespace client -} // namespace geode -} // namespace apache diff --git a/cppcache/src/InternalCacheTransactionManager2PC.hpp b/cppcache/src/InternalCacheTransactionManager2PC.hpp deleted file mode 100644 index c88c258b13..0000000000 --- a/cppcache/src/InternalCacheTransactionManager2PC.hpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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. - */ - -#pragma once - -#ifndef GEODE_INTERNALCACHETRANSACTIONMANAGER2PC_H_ -#define GEODE_INTERNALCACHETRANSACTIONMANAGER2PC_H_ - -#include - -namespace apache { -namespace geode { -namespace client { - -/** - * Extension of the apache::geode::client::CacheTransactionManager that enables - * client - * application - * to use Geode transaction as part of the global XA transaction. - * - * The prepare method of this class corresponds to the prepare phases of the - * 2 phase commit protocol driven by a global transaction manager. - * - * The implementation of the apache::geode::client::CacheTransactionManager - * commit() and - * rollback() - * methods must be 2 phase commit process aware. - * - * Methods of this class are expected to be called by a custom XA Resource - * Manager - * that is wrapping and adapting Geode client to XA specification - * requirements. - * - * @since 8.3 - * - */ -class APACHE_GEODE_EXPORT InternalCacheTransactionManager2PC - : public virtual CacheTransactionManager { - public: - /** - * Performs prepare during 2 phase commit completion. - * Locks of the entries modified in the current transaction on the server - * side. - * - * Calls to subsequent commit() or rollback() methods overridden by this class - * are - * expected to succeed after prepare() has returned successfully. - * Geode commits internal transaction irreversibly on commit() call. - * - */ - virtual void prepare() = 0; - - protected: - InternalCacheTransactionManager2PC(); - virtual ~InternalCacheTransactionManager2PC(); -}; -} // namespace client -} // namespace geode -} // namespace apache - -#endif // GEODE_INTERNALCACHETRANSACTIONMANAGER2PC_H_ diff --git a/cppcache/src/InternalCacheTransactionManager2PCImpl.hpp b/cppcache/src/InternalCacheTransactionManager2PCImpl.hpp index e5fdc8f968..d2e453f35b 100644 --- a/cppcache/src/InternalCacheTransactionManager2PCImpl.hpp +++ b/cppcache/src/InternalCacheTransactionManager2PCImpl.hpp @@ -21,15 +21,13 @@ #define GEODE_INTERNALCACHETRANSACTIONMANAGER2PCIMPL_H_ #include "CacheTransactionManagerImpl.hpp" -#include "InternalCacheTransactionManager2PC.hpp" namespace apache { namespace geode { namespace client { class InternalCacheTransactionManager2PCImpl - : public CacheTransactionManagerImpl, - public InternalCacheTransactionManager2PC { + : public CacheTransactionManagerImpl { public: explicit InternalCacheTransactionManager2PCImpl(CacheImpl* cache); virtual ~InternalCacheTransactionManager2PCImpl() override; From b4ecda61cfaf2a5a8439ee3fcb308182c8c1f3fb Mon Sep 17 00:00:00 2001 From: Mario Ivanac Date: Thu, 6 Jun 2019 20:17:30 +0200 Subject: [PATCH 2/3] GEODE-6641: Code impacts for support for two phase commit transactions Added test framework --- .../ThinClientTransactions.hpp | 100 +-- .../ThinClientTransactionsNewXA.hpp | 659 ++++++++++++++++++ .../testThinClientTransactionsNewXA.cpp | 25 + .../testThinClientTransactionsWithSticky.cpp | 4 - ...estThinClientTransactionsWithoutSticky.cpp | 4 - 5 files changed, 687 insertions(+), 105 deletions(-) create mode 100644 cppcache/integration-test/ThinClientTransactionsNewXA.hpp create mode 100644 cppcache/integration-test/testThinClientTransactionsNewXA.cpp diff --git a/cppcache/integration-test/ThinClientTransactions.hpp b/cppcache/integration-test/ThinClientTransactions.hpp index c49b5de994..76e13ac4b8 100644 --- a/cppcache/integration-test/ThinClientTransactions.hpp +++ b/cppcache/integration-test/ThinClientTransactions.hpp @@ -349,15 +349,12 @@ void doNetsearch(const char* name, const char* key, const char* value) { } const char* keys[] = {"Key-1", "Key-2", "Key-3", "Key-4", - "Key-5", "Key-6", "Key-7", "Key-8", - "Key-9", "Key-10", "Key-11"}; + "Key-5", "Key-6", "Key-7"}; const char* vals[] = {"Value-1", "Value-2", "Value-3", "Value-4", - "Value-5", "Value-6", "Value-7", "Value-8", - "Value-9", "Value-10", "Value-11"}; + "Value-5", "Value-6", "Value-7"}; const char* nvals[] = {"New Value-1", "New Value-2", "New Value-3", "New Value-4", "New Value-5", "New Value-6", - "New Value-7", "New Value-8", "New Value-9", - "New Value-10", "New Value-11"}; + "New Value-7"}; const char* regionNames[] = {"DistRegionAck", "DistRegionNoAck", "testregion"}; @@ -1005,97 +1002,6 @@ DUNIT_TASK_DEFINITION(CLIENT2, UpdateClient2Entries) LOG("StepSix complete."); } END_TASK_DEFINITION -DUNIT_TASK_DEFINITION(CLIENT1, CreateClient1additionalEntries) - { - auto txManager = getHelper()->getCache()->getCacheTransactionManager(); - txManager->begin(); - createEntry(regionNames[0], keys[7], vals[7]); - createEntry(regionNames[1], keys[8], vals[8]); - txManager->prepare(); - txManager->commit(); - verifyEntry(regionNames[0], keys[7], vals[7]); - verifyEntry(regionNames[1], keys[8], vals[8]); - txManager->begin(); - updateEntry(regionNames[0], keys[7], nvals[7]); - updateEntry(regionNames[1], keys[8], nvals[8]); - txManager->commit(); - verifyEntry(regionNames[0], keys[7], nvals[7]); - verifyEntry(regionNames[1], keys[8], nvals[8]); - LOG("StepSeven complete."); - } -END_TASK_DEFINITION -DUNIT_TASK_DEFINITION(CLIENT2, CreateClient2additionalEntries) - { - doNetsearch(regionNames[0], keys[0], vals[0]); - doNetsearch(regionNames[1], keys[2], vals[2]); - auto txManager = getHelper()->getCache()->getCacheTransactionManager(); - txManager->begin(); - createEntry(regionNames[0], keys[9], vals[9]); - createEntry(regionNames[1], keys[10], vals[10]); - txManager->commit(); - verifyEntry(regionNames[0], keys[9], vals[9]); - verifyEntry(regionNames[1], keys[10], vals[10]); - txManager->begin(); - updateEntry(regionNames[0], keys[9], nvals[9]); - updateEntry(regionNames[1], keys[10], nvals[10]); - txManager->prepare(); - txManager->commit(); - verifyEntry(regionNames[0], keys[9], nvals[9]); - verifyEntry(regionNames[1], keys[10], nvals[10]); - LOG("StepEight complete."); - } -END_TASK_DEFINITION -DUNIT_TASK_DEFINITION(CLIENT1, UpdateClient1additionalEntries) - { - auto txManager = getHelper()->getCache()->getCacheTransactionManager(); - txManager->begin(); - updateEntry(regionNames[0], keys[7], vals[5]); - updateEntry(regionNames[1], keys[8], vals[6]); - txManager->commit(); - verifyEntry(regionNames[0], keys[7], vals[5]); - verifyEntry(regionNames[1], keys[8], vals[6]); - txManager->begin(); - updateEntry(regionNames[0], keys[7], vals[7]); - updateEntry(regionNames[1], keys[8], vals[8]); - txManager->prepare(); - txManager->rollback(); - verifyEntry(regionNames[0], keys[7], vals[5]); - verifyEntry(regionNames[1], keys[8], vals[6]); - txManager->begin(); - updateEntry(regionNames[0], keys[7], nvals[7]); - updateEntry(regionNames[1], keys[8], nvals[8]); - txManager->commit(); - verifyEntry(regionNames[0], keys[7], nvals[7]); - verifyEntry(regionNames[1], keys[8], nvals[8]); - LOG("StepNine complete."); - } -END_TASK_DEFINITION -DUNIT_TASK_DEFINITION(CLIENT2, UpdateClient2additionalEntries) - { - auto txManager = getHelper()->getCache()->getCacheTransactionManager(); - txManager->begin(); - updateEntry(regionNames[0], keys[9], nvals[7]); - updateEntry(regionNames[1], keys[10], nvals[8]); - txManager->prepare(); - txManager->commit(); - verifyEntry(regionNames[0], keys[9], nvals[7]); - verifyEntry(regionNames[1], keys[10], nvals[8]); - txManager->begin(); - updateEntry(regionNames[0], keys[9], nvals[9]); - updateEntry(regionNames[1], keys[10], nvals[10]); - txManager->rollback(); - verifyEntry(regionNames[0], keys[9], nvals[7]); - verifyEntry(regionNames[1], keys[10], nvals[8]); - txManager->begin(); - updateEntry(regionNames[0], keys[9], nvals[9]); - updateEntry(regionNames[1], keys[10], nvals[10]); - txManager->prepare(); - txManager->commit(); - verifyEntry(regionNames[0], keys[9], nvals[9]); - verifyEntry(regionNames[1], keys[10], nvals[10]); - LOG("StepTen complete."); - } -END_TASK_DEFINITION DUNIT_TASK_DEFINITION(CLIENT1, CreateClient1EntryTwice) { createEntryTwice(regionNames[0], CREATE_TWICE_KEY, CREATE_TWICE_VALUE); } diff --git a/cppcache/integration-test/ThinClientTransactionsNewXA.hpp b/cppcache/integration-test/ThinClientTransactionsNewXA.hpp new file mode 100644 index 0000000000..53d9afe4f4 --- /dev/null +++ b/cppcache/integration-test/ThinClientTransactionsNewXA.hpp @@ -0,0 +1,659 @@ +/* + * 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. + */ + +#pragma once + +#ifndef GEODE_INTEGRATION_TEST_THINCLIENTTRANSACTIONSNEWXA_H_ +#define GEODE_INTEGRATION_TEST_THINCLIENTTRANSACTIONSNEWXA_H_ + +#include "fw_dunit.hpp" +#include +#include +#include + +#include +#include +#include + +#define ROOT_NAME "ThinClientTransactionsNewXA" +#define ROOT_SCOPE DISTRIBUTED_ACK + +#include "CacheHelper.hpp" + +namespace { // NOLINT(google-build-namespaces) + +using apache::geode::client::CacheableKey; +using apache::geode::client::CacheableString; +using apache::geode::client::CacheHelper; +using apache::geode::client::CacheServerException; +using apache::geode::client::EntryExistsException; +using apache::geode::client::EntryNotFoundException; +using apache::geode::client::IllegalStateException; +using apache::geode::client::Properties; +using apache::geode::client::TransactionException; +using apache::geode::client::TransactionId; + +#define CLIENT1 s1p1 +#define CLIENT2 s1p2 +#define SERVER1 s2p1 +#define SERVER2 s2p2 +#define CREATE_TWICE_KEY "__create_twice_key" +#define CREATE_TWICE_VALUE "__create_twice_value" +CacheHelper* cacheHelper = nullptr; +static bool isLocalServer = false; +static bool isLocator = false; +static int numberOfLocators = 0; + +const char* locatorsG = + CacheHelper::getLocatorHostPort(isLocator, isLocalServer, numberOfLocators); + +void initClient(const bool isthinClient) { + if (cacheHelper == nullptr) { + auto config = Properties::create(); + config->insert("suspended-tx-timeout", std::chrono::minutes(1)); + cacheHelper = new CacheHelper(isthinClient, config); + } + ASSERT(cacheHelper, "Failed to create a CacheHelper client instance."); +} + +void cleanProc() { + if (cacheHelper != nullptr) { + delete cacheHelper; + cacheHelper = nullptr; + } +} + +CacheHelper* getHelper() { + ASSERT(cacheHelper != nullptr, "No cacheHelper initialized."); + return cacheHelper; +} + +void _verifyEntry(const char* name, const char* key, const char* val, + bool noKey) { + // Verify key and value exist in this region, in this process. + const char* value = val ? val : ""; + char* buf = + reinterpret_cast(malloc(1024 + strlen(key) + strlen(value))); + ASSERT(buf, "Unable to malloc buffer for logging."); + if (noKey) { + sprintf(buf, "Verify key %s does not exist in region %s", key, name); + } else if (!val) { + sprintf(buf, "Verify value for key %s does not exist in region %s", key, + name); + } else { + sprintf(buf, "Verify value for key %s is: %s in region %s", key, value, + name); + } + LOG(buf); + free(buf); + + auto regPtr = getHelper()->getRegion(name); + ASSERT(regPtr != nullptr, "Region not found."); + + auto keyPtr = CacheableKey::create(key); + + // if the region is no ack, then we may need to wait... + if (noKey == false) { // need to find the key! + ASSERT(regPtr->containsKey(keyPtr), "Key not found in region."); + } + if (val != nullptr) { // need to have a value! + ASSERT(regPtr->containsValueForKey(keyPtr), "Value not found in region."); + } + + // loop up to MAX times, testing condition + uint32_t MAX = 100; + uint32_t SLEEP = 10; // milliseconds + uint32_t containsKeyCnt = 0; + uint32_t containsValueCnt = 0; + uint32_t testValueCnt = 0; + + for (int i = MAX; i >= 0; i--) { + if (noKey) { + if (regPtr->containsKey(keyPtr)) { + containsKeyCnt++; + } else { + break; + } + ASSERT(containsKeyCnt < MAX, "Key found in region."); + } + if (val == nullptr) { + if (regPtr->containsValueForKey(keyPtr)) { + containsValueCnt++; + } else { + break; + } + ASSERT(containsValueCnt < MAX, "Value found in region."); + } + + if (val != nullptr) { + auto checkPtr = + std::dynamic_pointer_cast(regPtr->get(keyPtr)); + + ASSERT(checkPtr != nullptr, "Value Ptr should not be null."); + char buf[1024]; + sprintf(buf, "In verify loop, get returned %s for key %s", + checkPtr->value().c_str(), key); + LOG(buf); + if (strcmp(checkPtr->value().c_str(), value) != 0) { + testValueCnt++; + } else { + break; + } + ASSERT(testValueCnt < MAX, "Incorrect value found."); + } + dunit::sleep(SLEEP); + } +} + +#define verifyEntry(x, y, z) _verifyEntry(x, y, z, __LINE__) + +void _verifyEntry(const char* name, const char* key, const char* val, + int line) { + char logmsg[1024]; + sprintf(logmsg, "verifyEntry() called from %d.\n", line); + LOG(logmsg); + _verifyEntry(name, key, val, false); + LOG("Entry verified."); +} + +void createRegion(const char* name, bool ackMode, const char* endpoints, + bool clientNotificationEnabled = false, + bool cachingEnable = true) { + LOG("createRegion() entered."); + fprintf(stdout, "Creating region -- %s ackMode is %d\n", name, ackMode); + fflush(stdout); + auto regPtr = getHelper()->createRegion(name, ackMode, cachingEnable, nullptr, + endpoints, clientNotificationEnabled); + ASSERT(regPtr != nullptr, "Failed to create region."); + LOG("Region created."); +} +void createPooledRegion(const char* name, bool ackMode, const char* locators, + const char* poolname, + bool clientNotificationEnabled = false, + bool cachingEnable = true) { + LOG("createRegion_Pool() entered."); + fprintf(stdout, "Creating region -- %s ackMode is %d\n", name, ackMode); + fflush(stdout); + auto regPtr = + getHelper()->createPooledRegion(name, ackMode, locators, poolname, + cachingEnable, clientNotificationEnabled); + ASSERT(regPtr != nullptr, "Failed to create region."); + LOG("Pooled Region created."); +} + +void createPooledRegionSticky(const char* name, bool ackMode, + const char* locators, const char* poolname, + bool clientNotificationEnabled = false, + bool cachingEnable = true) { + LOG("createRegion_Pool() entered."); + fprintf(stdout, "Creating region -- %s ackMode is %d\n", name, ackMode); + fflush(stdout); + auto regPtr = getHelper()->createPooledRegionSticky( + name, ackMode, locators, poolname, cachingEnable, + clientNotificationEnabled); + ASSERT(regPtr != nullptr, "Failed to create region."); + LOG("Pooled Region created."); +} + +void createEntry(const char* name, const char* key, const char* value) { + LOG("createEntry() entered."); + fprintf(stdout, "Creating entry -- key: %s value: %s in region %s\n", key, + value, name); + fflush(stdout); + // Create entry, verify entry is correct + auto keyPtr = CacheableKey::create(key); + auto valPtr = CacheableString::create(value); + + auto regPtr = getHelper()->getRegion(name); + ASSERT(regPtr != nullptr, "Region not found."); + + ASSERT(!regPtr->containsKey(keyPtr), + "Key should not have been found in region."); + ASSERT(!regPtr->containsValueForKey(keyPtr), + "Value should not have been found in region."); + + // regPtr->create( keyPtr, valPtr ); + regPtr->put(keyPtr, valPtr); + LOG("Created entry."); + + // verifyEntry( name, key, value ); + LOG("Entry created."); +} +void createEntryTwice(const char* name, const char* key, const char* value) { + LOG("createEntryTwice() entered."); + char message[500]; + sprintf(message, "Creating entry -- key: %s value: %s in region %s\n", key, + value, name); + LOG(message); + auto keyPtr = CacheableKey::create(key); + auto valPtr = CacheableString::create(value); + auto regPtr = getHelper()->getRegion(name); + regPtr->create(keyPtr, valPtr); + try { + regPtr->create(keyPtr, valPtr); + } catch (const EntryExistsException& geodeExcp) { + LOG(geodeExcp.what()); + LOG("createEntryTwice() Clean Exit."); + return; + } + ASSERT(false, + "Creating key twice is not allowed and while doing that exception was " + "not thrown"); + return; // This return will never reach +} + +void updateEntry(const char* name, const char* key, const char* value) { + LOG("updateEntry() entered."); + fprintf(stdout, "Updating entry -- key: %s value: %s in region %s\n", key, + value, name); + fflush(stdout); + // Update entry, verify entry is correct + auto keyPtr = CacheableKey::create(key); + auto valPtr = CacheableString::create(value); + + auto regPtr = getHelper()->getRegion(name); + ASSERT(regPtr != nullptr, "Region not found."); + + ASSERT(regPtr->containsKey(keyPtr), "Key should have been found in region."); + ASSERT(regPtr->containsValueForKey(keyPtr), + "Value should have been found in region."); + + regPtr->put(keyPtr, valPtr); + LOG("Put entry."); + + verifyEntry(name, key, value); + LOG("Entry updated."); +} + +void doGetAgain(const char* name, const char* key, const char* value) { + LOG("doGetAgain() entered."); + fprintf(stdout, + "get for entry -- key: %s expecting value: %s in region %s\n", key, + value, name); + fflush(stdout); + // Get entry created in Process A, verify entry is correct + auto keyPtr = CacheableKey::create(key); + + auto regPtr = getHelper()->getRegion(name); + fprintf(stdout, "get region name%s\n", regPtr->getName().c_str()); + fflush(stdout); + ASSERT(regPtr != nullptr, "Region not found."); + + auto checkPtr = std::dynamic_pointer_cast( + regPtr->get(keyPtr)); // force a netsearch + + if (checkPtr != nullptr) { + LOG("checkPtr is not null"); + char buf[1024]; + sprintf(buf, "In doGetAgain, get returned %s for key %s", + checkPtr->value().c_str(), key); + LOG(buf); + } else { + LOG("checkPtr is nullptr"); + } + verifyEntry(name, key, value); + LOG("GetAgain complete."); +} + +void doNetsearch(const char* name, const char* key, const char* value) { + LOG("doNetsearch() entered."); + fprintf( + stdout, + "Netsearching for entry -- key: %s expecting value: %s in region %s\n", + key, value, name); + fflush(stdout); + static int count = 0; + // Get entry created in Process A, verify entry is correct + auto keyPtr = CacheableKey::create(key); + + auto regPtr = getHelper()->getRegion(name); + fprintf(stdout, "netsearch region %s\n", regPtr->getName().c_str()); + fflush(stdout); + ASSERT(regPtr != nullptr, "Region not found."); + + if (count == 0) { + ASSERT(!regPtr->containsKey(keyPtr), + "Key should not have been found in region."); + ASSERT(!regPtr->containsValueForKey(keyPtr), + "Value should not have been found in region."); + count++; + } + auto checkPtr = std::dynamic_pointer_cast( + regPtr->get(keyPtr)); // force a netsearch + + if (checkPtr != nullptr) { + LOG("checkPtr is not null"); + char buf[1024]; + sprintf(buf, "In net search, get returned %s for key %s", + checkPtr->value().c_str(), key); + LOG(buf); + } else { + LOG("checkPtr is nullptr"); + } + verifyEntry(name, key, value); + LOG("Netsearch complete."); +} + +const char* keys[] = {"Key-1", "Key-2", "Key-3", "Key-4", + "Key-5", "Key-6", "Key-7", "Key-8", + "Key-9", "Key-10", "Key-11"}; +const char* vals[] = {"Value-1", "Value-2", "Value-3", "Value-4", + "Value-5", "Value-6", "Value-7", "Value-8", + "Value-9", "Value-10", "Value-11"}; +const char* nvals[] = {"New Value-1", "New Value-2", "New Value-3", + "New Value-4", "New Value-5", "New Value-6", + "New Value-7", "New Value-8", "New Value-9", + "New Value-10", "New Value-11"}; + +const char* regionNames[] = {"DistRegionAck", "DistRegionNoAck", "testregion"}; + +const bool USE_ACK = true; +const bool NO_ACK = false; + +#include "LocatorHelper.hpp" +#define THREADERRORCHECK(x, y) \ + if (!(x)) { \ + m_isFailed = true; \ + sprintf(m_error, y); \ + return -1; \ + } + +DUNIT_TASK_DEFINITION(CLIENT1, CreateNonexistentServerRegion_Pooled_Locator) + { + initClient(true); + createPooledRegion("non-region", USE_ACK, locatorsG, "__TESTPOOL1_"); + try { + createEntry("non-region", keys[0], vals[0]); + FAIL( + "Expected exception when doing operations on a non-existent region."); + } catch (const CacheServerException& ex) { + printf( + "Got expected CacheServerException when performing operation " + "on a non-existent region: %s\n", + ex.what()); + } + } +END_TASK_DEFINITION + +DUNIT_TASK_DEFINITION(CLIENT1, + CreateNonexistentServerRegion_Pooled_Locator_Sticky) + { + initClient(true); + createPooledRegionSticky("non-region", USE_ACK, locatorsG, "__TESTPOOL1_"); + try { + createEntry("non-region", keys[0], vals[0]); + FAIL( + "Expected exception when doing operations on a non-existent region."); + } catch (const CacheServerException& ex) { + printf( + "Got expected CacheServerException when performing operation " + "on a non-existent region: %s\n", + ex.what()); + } + } +END_TASK_DEFINITION + +DUNIT_TASK_DEFINITION(CLIENT1, StepOne_Pooled_Locator) + { + createPooledRegion(regionNames[0], USE_ACK, locatorsG, "__TESTPOOL1_"); + createPooledRegion(regionNames[1], NO_ACK, locatorsG, "__TESTPOOL1_"); + LOG("StepOne_Pooled complete."); + } +END_TASK_DEFINITION + +DUNIT_TASK_DEFINITION(CLIENT1, StepOne_Pooled_Locator_Sticky) + { + createPooledRegionSticky(regionNames[0], USE_ACK, locatorsG, + "__TESTPOOL1_"); + createPooledRegionSticky(regionNames[1], NO_ACK, locatorsG, "__TESTPOOL1_"); + LOG("StepOne_Pooled_Locator_Sticky complete."); + } +END_TASK_DEFINITION + +DUNIT_TASK_DEFINITION(CLIENT2, StepTwo_Pooled_Locator) + { + initClient(true); + createPooledRegion(regionNames[0], USE_ACK, locatorsG, "__TESTPOOL1_"); + createPooledRegion(regionNames[1], NO_ACK, locatorsG, "__TESTPOOL1_"); + LOG("StepTwo complete."); + } +END_TASK_DEFINITION + +DUNIT_TASK_DEFINITION(CLIENT2, StepTwo_Pooled_Locator_Sticky) + { + initClient(true); + createPooledRegionSticky(regionNames[0], USE_ACK, locatorsG, + "__TESTPOOL1_"); + createPooledRegionSticky(regionNames[1], NO_ACK, locatorsG, "__TESTPOOL1_"); + LOG("StepTwo complete."); + } +END_TASK_DEFINITION + +DUNIT_TASK_DEFINITION(CLIENT1, StepThree) + { + auto txManager = getHelper()->getCache()->getCacheTransactionManager(); + txManager->begin(); + createEntry(regionNames[0], keys[0], vals[0]); + createEntry(regionNames[1], keys[2], vals[2]); + txManager->prepare(); + txManager->commit(); + LOG("StepThree complete."); + } +END_TASK_DEFINITION + +DUNIT_TASK_DEFINITION(CLIENT2, StepFour) + { + doNetsearch(regionNames[0], keys[0], vals[0]); + doNetsearch(regionNames[1], keys[2], vals[2]); + auto txManager = getHelper()->getCache()->getCacheTransactionManager(); + txManager->begin(); + createEntry(regionNames[0], keys[1], vals[1]); + createEntry(regionNames[1], keys[3], vals[3]); + txManager->prepare(); + txManager->commit(); + verifyEntry(regionNames[0], keys[1], vals[1]); + verifyEntry(regionNames[1], keys[3], vals[3]); + LOG("StepFour complete."); + } +END_TASK_DEFINITION +DUNIT_TASK_DEFINITION(CLIENT1, StepFive) + { + auto reg0 = getHelper()->getRegion(regionNames[0]); + auto reg1 = getHelper()->getRegion(regionNames[1]); + auto vec0 = reg0->serverKeys(); + auto vec1 = reg1->serverKeys(); + ASSERT(vec0.size() == 2, "Should have 2 keys in first region."); + ASSERT(vec1.size() == 2, "Should have 2 keys in second region."); + std::string key0, key1; + key0 = vec0[0]->toString().c_str(); + key1 = vec0[1]->toString().c_str(); + ASSERT(key0 != key1, "The two keys should be different in first region."); + ASSERT(key0 == keys[0] || key0 == keys[1], + "Unexpected key in first region."); + ASSERT(key1 == keys[0] || key1 == keys[1], + "Unexpected key in first region."); + + key0 = vec1[0]->toString().c_str(); + key1 = vec1[1]->toString().c_str(); + ASSERT(key0 != key1, "The two keys should be different in second region."); + ASSERT(key0 == keys[2] || key0 == keys[3], + "Unexpected key in second region."); + ASSERT(key1 == keys[2] || key1 == keys[3], + "Unexpected key in second region."); + + doNetsearch(regionNames[0], keys[1], vals[1]); + doNetsearch(regionNames[1], keys[3], vals[3]); + updateEntry(regionNames[0], keys[0], nvals[0]); + updateEntry(regionNames[1], keys[2], nvals[2]); + LOG("StepFive complete."); + } +END_TASK_DEFINITION +DUNIT_TASK_DEFINITION(CLIENT2, StepSix) + { + doNetsearch(regionNames[0], keys[0], vals[0]); + doNetsearch(regionNames[1], keys[2], vals[2]); + auto txManager = getHelper()->getCache()->getCacheTransactionManager(); + txManager->begin(); + updateEntry(regionNames[0], keys[1], nvals[1]); + updateEntry(regionNames[1], keys[3], nvals[3]); + txManager->prepare(); + txManager->commit(); + LOG("StepSix complete."); + } +END_TASK_DEFINITION + +DUNIT_TASK_DEFINITION(CLIENT1, CreateClient1additionalEntries) + { + auto txManager = getHelper()->getCache()->getCacheTransactionManager(); + txManager->begin(); + createEntry(regionNames[0], keys[7], vals[7]); + createEntry(regionNames[1], keys[8], vals[8]); + txManager->prepare(); + txManager->commit(); + verifyEntry(regionNames[0], keys[7], vals[7]); + verifyEntry(regionNames[1], keys[8], vals[8]); + txManager->begin(); + updateEntry(regionNames[0], keys[7], nvals[7]); + updateEntry(regionNames[1], keys[8], nvals[8]); + txManager->commit(); + verifyEntry(regionNames[0], keys[7], nvals[7]); + verifyEntry(regionNames[1], keys[8], nvals[8]); + LOG("StepSeven complete."); + } +END_TASK_DEFINITION +DUNIT_TASK_DEFINITION(CLIENT2, CreateClient2additionalEntries) + { + doNetsearch(regionNames[0], keys[0], vals[0]); + doNetsearch(regionNames[1], keys[2], vals[2]); + auto txManager = getHelper()->getCache()->getCacheTransactionManager(); + txManager->begin(); + createEntry(regionNames[0], keys[9], vals[9]); + createEntry(regionNames[1], keys[10], vals[10]); + txManager->commit(); + verifyEntry(regionNames[0], keys[9], vals[9]); + verifyEntry(regionNames[1], keys[10], vals[10]); + txManager->begin(); + updateEntry(regionNames[0], keys[9], nvals[9]); + updateEntry(regionNames[1], keys[10], nvals[10]); + txManager->prepare(); + txManager->commit(); + verifyEntry(regionNames[0], keys[9], nvals[9]); + verifyEntry(regionNames[1], keys[10], nvals[10]); + LOG("StepEight complete."); + } +END_TASK_DEFINITION +DUNIT_TASK_DEFINITION(CLIENT1, UpdateClient1additionalEntries) + { + auto txManager = getHelper()->getCache()->getCacheTransactionManager(); + txManager->begin(); + updateEntry(regionNames[0], keys[7], vals[5]); + updateEntry(regionNames[1], keys[8], vals[6]); + txManager->commit(); + verifyEntry(regionNames[0], keys[7], vals[5]); + verifyEntry(regionNames[1], keys[8], vals[6]); + txManager->begin(); + updateEntry(regionNames[0], keys[7], vals[7]); + updateEntry(regionNames[1], keys[8], vals[8]); + txManager->prepare(); + txManager->rollback(); + verifyEntry(regionNames[0], keys[7], vals[5]); + verifyEntry(regionNames[1], keys[8], vals[6]); + txManager->begin(); + updateEntry(regionNames[0], keys[7], nvals[7]); + updateEntry(regionNames[1], keys[8], nvals[8]); + txManager->commit(); + verifyEntry(regionNames[0], keys[7], nvals[7]); + verifyEntry(regionNames[1], keys[8], nvals[8]); + LOG("StepNine complete."); + } +END_TASK_DEFINITION +DUNIT_TASK_DEFINITION(CLIENT2, UpdateClient2additionalEntries) + { + auto txManager = getHelper()->getCache()->getCacheTransactionManager(); + txManager->begin(); + updateEntry(regionNames[0], keys[9], nvals[7]); + updateEntry(regionNames[1], keys[10], nvals[8]); + txManager->prepare(); + txManager->commit(); + verifyEntry(regionNames[0], keys[9], nvals[7]); + verifyEntry(regionNames[1], keys[10], nvals[8]); + txManager->begin(); + updateEntry(regionNames[0], keys[9], nvals[9]); + updateEntry(regionNames[1], keys[10], nvals[10]); + txManager->rollback(); + verifyEntry(regionNames[0], keys[9], nvals[7]); + verifyEntry(regionNames[1], keys[10], nvals[8]); + txManager->begin(); + updateEntry(regionNames[0], keys[9], nvals[9]); + updateEntry(regionNames[1], keys[10], nvals[10]); + txManager->prepare(); + txManager->commit(); + verifyEntry(regionNames[0], keys[9], nvals[9]); + verifyEntry(regionNames[1], keys[10], nvals[10]); + LOG("StepTen complete."); + } +END_TASK_DEFINITION + +DUNIT_TASK_DEFINITION(CLIENT1, CloseCache1) + { cleanProc(); } +END_TASK_DEFINITION + +DUNIT_TASK_DEFINITION(CLIENT2, CloseCache2) + { cleanProc(); } +END_TASK_DEFINITION + +DUNIT_TASK_DEFINITION(SERVER1, CloseServer1) + { + if (isLocalServer) { + CacheHelper::closeServer(1); + LOG("SERVER1 stopped"); + } + } +END_TASK_DEFINITION + +void runXATransactionOps(bool isSticky = false) { + CALL_TASK(CreateLocator1); + CALL_TASK(CreateServer1_With_Locator) + + if (isSticky) { + CALL_TASK(CreateNonexistentServerRegion_Pooled_Locator_Sticky); + CALL_TASK(StepOne_Pooled_Locator_Sticky); + CALL_TASK(StepTwo_Pooled_Locator_Sticky); + } else { + CALL_TASK(CreateNonexistentServerRegion_Pooled_Locator); + CALL_TASK(StepOne_Pooled_Locator); + CALL_TASK(StepTwo_Pooled_Locator); + } + + CALL_TASK(StepThree); + CALL_TASK(StepFour); + CALL_TASK(StepFive); + CALL_TASK(StepSix); + CALL_TASK(CreateClient1additionalEntries); + CALL_TASK(CreateClient2additionalEntries); + CALL_TASK(UpdateClient1additionalEntries); + CALL_TASK(UpdateClient2additionalEntries); + + CALL_TASK(CloseCache1); + CALL_TASK(CloseCache2); + CALL_TASK(CloseServer1); + CALL_TASK(CloseLocator1); +} + +} // namespace + +#endif // GEODE_INTEGRATION_TEST_THINCLIENTTRANSACTIONSNEWXA_H_ diff --git a/cppcache/integration-test/testThinClientTransactionsNewXA.cpp b/cppcache/integration-test/testThinClientTransactionsNewXA.cpp new file mode 100644 index 0000000000..a0e6df8e83 --- /dev/null +++ b/cppcache/integration-test/testThinClientTransactionsNewXA.cpp @@ -0,0 +1,25 @@ +/* + * 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. + */ + +#include "ThinClientTransactionsNewXA.hpp" + +DUNIT_MAIN + { + runXATransactionOps(false); + runXATransactionOps(true); + } +END_MAIN diff --git a/cppcache/integration-test/testThinClientTransactionsWithSticky.cpp b/cppcache/integration-test/testThinClientTransactionsWithSticky.cpp index 6d0aba8269..d27131d521 100644 --- a/cppcache/integration-test/testThinClientTransactionsWithSticky.cpp +++ b/cppcache/integration-test/testThinClientTransactionsWithSticky.cpp @@ -33,10 +33,6 @@ DUNIT_MAIN CALL_TASK(CreateClient1EntryTwice); CALL_TASK(CreateClient1KeyThriceWithSticky); - CALL_TASK(CreateClient1additionalEntries); - CALL_TASK(CreateClient2additionalEntries); - CALL_TASK(UpdateClient1additionalEntries); - CALL_TASK(UpdateClient2additionalEntries); CALL_TASK(SuspendResumeInThread); CALL_TASK(SuspendResumeCommit); diff --git a/cppcache/integration-test/testThinClientTransactionsWithoutSticky.cpp b/cppcache/integration-test/testThinClientTransactionsWithoutSticky.cpp index 22cd8ed6a3..e3d2351cea 100644 --- a/cppcache/integration-test/testThinClientTransactionsWithoutSticky.cpp +++ b/cppcache/integration-test/testThinClientTransactionsWithoutSticky.cpp @@ -33,10 +33,6 @@ DUNIT_MAIN CALL_TASK(CreateClient1EntryTwice); CALL_TASK(CreateClient1KeyThriceWithoutSticky); - CALL_TASK(CreateClient1additionalEntries); - CALL_TASK(CreateClient2additionalEntries); - CALL_TASK(UpdateClient1additionalEntries); - CALL_TASK(UpdateClient2additionalEntries); CALL_TASK(SuspendResumeInThread); CALL_TASK(SuspendResumeCommit); From 17c922c36a38eea09f18fe18b760869262abd788 Mon Sep 17 00:00:00 2001 From: Mario Ivanac Date: Thu, 4 Jul 2019 00:21:35 +0200 Subject: [PATCH 3/3] GEODE-6641: New test framework --- .../ThinClientTransactionsNewXA.hpp | 659 ------------------ .../testThinClientTransactionsNewXA.cpp | 25 - .../test/ClientTransactionXATest.cpp | 91 +++ 3 files changed, 91 insertions(+), 684 deletions(-) delete mode 100644 cppcache/integration-test/ThinClientTransactionsNewXA.hpp delete mode 100644 cppcache/integration-test/testThinClientTransactionsNewXA.cpp create mode 100644 cppcache/integration/test/ClientTransactionXATest.cpp diff --git a/cppcache/integration-test/ThinClientTransactionsNewXA.hpp b/cppcache/integration-test/ThinClientTransactionsNewXA.hpp deleted file mode 100644 index 53d9afe4f4..0000000000 --- a/cppcache/integration-test/ThinClientTransactionsNewXA.hpp +++ /dev/null @@ -1,659 +0,0 @@ -/* - * 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. - */ - -#pragma once - -#ifndef GEODE_INTEGRATION_TEST_THINCLIENTTRANSACTIONSNEWXA_H_ -#define GEODE_INTEGRATION_TEST_THINCLIENTTRANSACTIONSNEWXA_H_ - -#include "fw_dunit.hpp" -#include -#include -#include - -#include -#include -#include - -#define ROOT_NAME "ThinClientTransactionsNewXA" -#define ROOT_SCOPE DISTRIBUTED_ACK - -#include "CacheHelper.hpp" - -namespace { // NOLINT(google-build-namespaces) - -using apache::geode::client::CacheableKey; -using apache::geode::client::CacheableString; -using apache::geode::client::CacheHelper; -using apache::geode::client::CacheServerException; -using apache::geode::client::EntryExistsException; -using apache::geode::client::EntryNotFoundException; -using apache::geode::client::IllegalStateException; -using apache::geode::client::Properties; -using apache::geode::client::TransactionException; -using apache::geode::client::TransactionId; - -#define CLIENT1 s1p1 -#define CLIENT2 s1p2 -#define SERVER1 s2p1 -#define SERVER2 s2p2 -#define CREATE_TWICE_KEY "__create_twice_key" -#define CREATE_TWICE_VALUE "__create_twice_value" -CacheHelper* cacheHelper = nullptr; -static bool isLocalServer = false; -static bool isLocator = false; -static int numberOfLocators = 0; - -const char* locatorsG = - CacheHelper::getLocatorHostPort(isLocator, isLocalServer, numberOfLocators); - -void initClient(const bool isthinClient) { - if (cacheHelper == nullptr) { - auto config = Properties::create(); - config->insert("suspended-tx-timeout", std::chrono::minutes(1)); - cacheHelper = new CacheHelper(isthinClient, config); - } - ASSERT(cacheHelper, "Failed to create a CacheHelper client instance."); -} - -void cleanProc() { - if (cacheHelper != nullptr) { - delete cacheHelper; - cacheHelper = nullptr; - } -} - -CacheHelper* getHelper() { - ASSERT(cacheHelper != nullptr, "No cacheHelper initialized."); - return cacheHelper; -} - -void _verifyEntry(const char* name, const char* key, const char* val, - bool noKey) { - // Verify key and value exist in this region, in this process. - const char* value = val ? val : ""; - char* buf = - reinterpret_cast(malloc(1024 + strlen(key) + strlen(value))); - ASSERT(buf, "Unable to malloc buffer for logging."); - if (noKey) { - sprintf(buf, "Verify key %s does not exist in region %s", key, name); - } else if (!val) { - sprintf(buf, "Verify value for key %s does not exist in region %s", key, - name); - } else { - sprintf(buf, "Verify value for key %s is: %s in region %s", key, value, - name); - } - LOG(buf); - free(buf); - - auto regPtr = getHelper()->getRegion(name); - ASSERT(regPtr != nullptr, "Region not found."); - - auto keyPtr = CacheableKey::create(key); - - // if the region is no ack, then we may need to wait... - if (noKey == false) { // need to find the key! - ASSERT(regPtr->containsKey(keyPtr), "Key not found in region."); - } - if (val != nullptr) { // need to have a value! - ASSERT(regPtr->containsValueForKey(keyPtr), "Value not found in region."); - } - - // loop up to MAX times, testing condition - uint32_t MAX = 100; - uint32_t SLEEP = 10; // milliseconds - uint32_t containsKeyCnt = 0; - uint32_t containsValueCnt = 0; - uint32_t testValueCnt = 0; - - for (int i = MAX; i >= 0; i--) { - if (noKey) { - if (regPtr->containsKey(keyPtr)) { - containsKeyCnt++; - } else { - break; - } - ASSERT(containsKeyCnt < MAX, "Key found in region."); - } - if (val == nullptr) { - if (regPtr->containsValueForKey(keyPtr)) { - containsValueCnt++; - } else { - break; - } - ASSERT(containsValueCnt < MAX, "Value found in region."); - } - - if (val != nullptr) { - auto checkPtr = - std::dynamic_pointer_cast(regPtr->get(keyPtr)); - - ASSERT(checkPtr != nullptr, "Value Ptr should not be null."); - char buf[1024]; - sprintf(buf, "In verify loop, get returned %s for key %s", - checkPtr->value().c_str(), key); - LOG(buf); - if (strcmp(checkPtr->value().c_str(), value) != 0) { - testValueCnt++; - } else { - break; - } - ASSERT(testValueCnt < MAX, "Incorrect value found."); - } - dunit::sleep(SLEEP); - } -} - -#define verifyEntry(x, y, z) _verifyEntry(x, y, z, __LINE__) - -void _verifyEntry(const char* name, const char* key, const char* val, - int line) { - char logmsg[1024]; - sprintf(logmsg, "verifyEntry() called from %d.\n", line); - LOG(logmsg); - _verifyEntry(name, key, val, false); - LOG("Entry verified."); -} - -void createRegion(const char* name, bool ackMode, const char* endpoints, - bool clientNotificationEnabled = false, - bool cachingEnable = true) { - LOG("createRegion() entered."); - fprintf(stdout, "Creating region -- %s ackMode is %d\n", name, ackMode); - fflush(stdout); - auto regPtr = getHelper()->createRegion(name, ackMode, cachingEnable, nullptr, - endpoints, clientNotificationEnabled); - ASSERT(regPtr != nullptr, "Failed to create region."); - LOG("Region created."); -} -void createPooledRegion(const char* name, bool ackMode, const char* locators, - const char* poolname, - bool clientNotificationEnabled = false, - bool cachingEnable = true) { - LOG("createRegion_Pool() entered."); - fprintf(stdout, "Creating region -- %s ackMode is %d\n", name, ackMode); - fflush(stdout); - auto regPtr = - getHelper()->createPooledRegion(name, ackMode, locators, poolname, - cachingEnable, clientNotificationEnabled); - ASSERT(regPtr != nullptr, "Failed to create region."); - LOG("Pooled Region created."); -} - -void createPooledRegionSticky(const char* name, bool ackMode, - const char* locators, const char* poolname, - bool clientNotificationEnabled = false, - bool cachingEnable = true) { - LOG("createRegion_Pool() entered."); - fprintf(stdout, "Creating region -- %s ackMode is %d\n", name, ackMode); - fflush(stdout); - auto regPtr = getHelper()->createPooledRegionSticky( - name, ackMode, locators, poolname, cachingEnable, - clientNotificationEnabled); - ASSERT(regPtr != nullptr, "Failed to create region."); - LOG("Pooled Region created."); -} - -void createEntry(const char* name, const char* key, const char* value) { - LOG("createEntry() entered."); - fprintf(stdout, "Creating entry -- key: %s value: %s in region %s\n", key, - value, name); - fflush(stdout); - // Create entry, verify entry is correct - auto keyPtr = CacheableKey::create(key); - auto valPtr = CacheableString::create(value); - - auto regPtr = getHelper()->getRegion(name); - ASSERT(regPtr != nullptr, "Region not found."); - - ASSERT(!regPtr->containsKey(keyPtr), - "Key should not have been found in region."); - ASSERT(!regPtr->containsValueForKey(keyPtr), - "Value should not have been found in region."); - - // regPtr->create( keyPtr, valPtr ); - regPtr->put(keyPtr, valPtr); - LOG("Created entry."); - - // verifyEntry( name, key, value ); - LOG("Entry created."); -} -void createEntryTwice(const char* name, const char* key, const char* value) { - LOG("createEntryTwice() entered."); - char message[500]; - sprintf(message, "Creating entry -- key: %s value: %s in region %s\n", key, - value, name); - LOG(message); - auto keyPtr = CacheableKey::create(key); - auto valPtr = CacheableString::create(value); - auto regPtr = getHelper()->getRegion(name); - regPtr->create(keyPtr, valPtr); - try { - regPtr->create(keyPtr, valPtr); - } catch (const EntryExistsException& geodeExcp) { - LOG(geodeExcp.what()); - LOG("createEntryTwice() Clean Exit."); - return; - } - ASSERT(false, - "Creating key twice is not allowed and while doing that exception was " - "not thrown"); - return; // This return will never reach -} - -void updateEntry(const char* name, const char* key, const char* value) { - LOG("updateEntry() entered."); - fprintf(stdout, "Updating entry -- key: %s value: %s in region %s\n", key, - value, name); - fflush(stdout); - // Update entry, verify entry is correct - auto keyPtr = CacheableKey::create(key); - auto valPtr = CacheableString::create(value); - - auto regPtr = getHelper()->getRegion(name); - ASSERT(regPtr != nullptr, "Region not found."); - - ASSERT(regPtr->containsKey(keyPtr), "Key should have been found in region."); - ASSERT(regPtr->containsValueForKey(keyPtr), - "Value should have been found in region."); - - regPtr->put(keyPtr, valPtr); - LOG("Put entry."); - - verifyEntry(name, key, value); - LOG("Entry updated."); -} - -void doGetAgain(const char* name, const char* key, const char* value) { - LOG("doGetAgain() entered."); - fprintf(stdout, - "get for entry -- key: %s expecting value: %s in region %s\n", key, - value, name); - fflush(stdout); - // Get entry created in Process A, verify entry is correct - auto keyPtr = CacheableKey::create(key); - - auto regPtr = getHelper()->getRegion(name); - fprintf(stdout, "get region name%s\n", regPtr->getName().c_str()); - fflush(stdout); - ASSERT(regPtr != nullptr, "Region not found."); - - auto checkPtr = std::dynamic_pointer_cast( - regPtr->get(keyPtr)); // force a netsearch - - if (checkPtr != nullptr) { - LOG("checkPtr is not null"); - char buf[1024]; - sprintf(buf, "In doGetAgain, get returned %s for key %s", - checkPtr->value().c_str(), key); - LOG(buf); - } else { - LOG("checkPtr is nullptr"); - } - verifyEntry(name, key, value); - LOG("GetAgain complete."); -} - -void doNetsearch(const char* name, const char* key, const char* value) { - LOG("doNetsearch() entered."); - fprintf( - stdout, - "Netsearching for entry -- key: %s expecting value: %s in region %s\n", - key, value, name); - fflush(stdout); - static int count = 0; - // Get entry created in Process A, verify entry is correct - auto keyPtr = CacheableKey::create(key); - - auto regPtr = getHelper()->getRegion(name); - fprintf(stdout, "netsearch region %s\n", regPtr->getName().c_str()); - fflush(stdout); - ASSERT(regPtr != nullptr, "Region not found."); - - if (count == 0) { - ASSERT(!regPtr->containsKey(keyPtr), - "Key should not have been found in region."); - ASSERT(!regPtr->containsValueForKey(keyPtr), - "Value should not have been found in region."); - count++; - } - auto checkPtr = std::dynamic_pointer_cast( - regPtr->get(keyPtr)); // force a netsearch - - if (checkPtr != nullptr) { - LOG("checkPtr is not null"); - char buf[1024]; - sprintf(buf, "In net search, get returned %s for key %s", - checkPtr->value().c_str(), key); - LOG(buf); - } else { - LOG("checkPtr is nullptr"); - } - verifyEntry(name, key, value); - LOG("Netsearch complete."); -} - -const char* keys[] = {"Key-1", "Key-2", "Key-3", "Key-4", - "Key-5", "Key-6", "Key-7", "Key-8", - "Key-9", "Key-10", "Key-11"}; -const char* vals[] = {"Value-1", "Value-2", "Value-3", "Value-4", - "Value-5", "Value-6", "Value-7", "Value-8", - "Value-9", "Value-10", "Value-11"}; -const char* nvals[] = {"New Value-1", "New Value-2", "New Value-3", - "New Value-4", "New Value-5", "New Value-6", - "New Value-7", "New Value-8", "New Value-9", - "New Value-10", "New Value-11"}; - -const char* regionNames[] = {"DistRegionAck", "DistRegionNoAck", "testregion"}; - -const bool USE_ACK = true; -const bool NO_ACK = false; - -#include "LocatorHelper.hpp" -#define THREADERRORCHECK(x, y) \ - if (!(x)) { \ - m_isFailed = true; \ - sprintf(m_error, y); \ - return -1; \ - } - -DUNIT_TASK_DEFINITION(CLIENT1, CreateNonexistentServerRegion_Pooled_Locator) - { - initClient(true); - createPooledRegion("non-region", USE_ACK, locatorsG, "__TESTPOOL1_"); - try { - createEntry("non-region", keys[0], vals[0]); - FAIL( - "Expected exception when doing operations on a non-existent region."); - } catch (const CacheServerException& ex) { - printf( - "Got expected CacheServerException when performing operation " - "on a non-existent region: %s\n", - ex.what()); - } - } -END_TASK_DEFINITION - -DUNIT_TASK_DEFINITION(CLIENT1, - CreateNonexistentServerRegion_Pooled_Locator_Sticky) - { - initClient(true); - createPooledRegionSticky("non-region", USE_ACK, locatorsG, "__TESTPOOL1_"); - try { - createEntry("non-region", keys[0], vals[0]); - FAIL( - "Expected exception when doing operations on a non-existent region."); - } catch (const CacheServerException& ex) { - printf( - "Got expected CacheServerException when performing operation " - "on a non-existent region: %s\n", - ex.what()); - } - } -END_TASK_DEFINITION - -DUNIT_TASK_DEFINITION(CLIENT1, StepOne_Pooled_Locator) - { - createPooledRegion(regionNames[0], USE_ACK, locatorsG, "__TESTPOOL1_"); - createPooledRegion(regionNames[1], NO_ACK, locatorsG, "__TESTPOOL1_"); - LOG("StepOne_Pooled complete."); - } -END_TASK_DEFINITION - -DUNIT_TASK_DEFINITION(CLIENT1, StepOne_Pooled_Locator_Sticky) - { - createPooledRegionSticky(regionNames[0], USE_ACK, locatorsG, - "__TESTPOOL1_"); - createPooledRegionSticky(regionNames[1], NO_ACK, locatorsG, "__TESTPOOL1_"); - LOG("StepOne_Pooled_Locator_Sticky complete."); - } -END_TASK_DEFINITION - -DUNIT_TASK_DEFINITION(CLIENT2, StepTwo_Pooled_Locator) - { - initClient(true); - createPooledRegion(regionNames[0], USE_ACK, locatorsG, "__TESTPOOL1_"); - createPooledRegion(regionNames[1], NO_ACK, locatorsG, "__TESTPOOL1_"); - LOG("StepTwo complete."); - } -END_TASK_DEFINITION - -DUNIT_TASK_DEFINITION(CLIENT2, StepTwo_Pooled_Locator_Sticky) - { - initClient(true); - createPooledRegionSticky(regionNames[0], USE_ACK, locatorsG, - "__TESTPOOL1_"); - createPooledRegionSticky(regionNames[1], NO_ACK, locatorsG, "__TESTPOOL1_"); - LOG("StepTwo complete."); - } -END_TASK_DEFINITION - -DUNIT_TASK_DEFINITION(CLIENT1, StepThree) - { - auto txManager = getHelper()->getCache()->getCacheTransactionManager(); - txManager->begin(); - createEntry(regionNames[0], keys[0], vals[0]); - createEntry(regionNames[1], keys[2], vals[2]); - txManager->prepare(); - txManager->commit(); - LOG("StepThree complete."); - } -END_TASK_DEFINITION - -DUNIT_TASK_DEFINITION(CLIENT2, StepFour) - { - doNetsearch(regionNames[0], keys[0], vals[0]); - doNetsearch(regionNames[1], keys[2], vals[2]); - auto txManager = getHelper()->getCache()->getCacheTransactionManager(); - txManager->begin(); - createEntry(regionNames[0], keys[1], vals[1]); - createEntry(regionNames[1], keys[3], vals[3]); - txManager->prepare(); - txManager->commit(); - verifyEntry(regionNames[0], keys[1], vals[1]); - verifyEntry(regionNames[1], keys[3], vals[3]); - LOG("StepFour complete."); - } -END_TASK_DEFINITION -DUNIT_TASK_DEFINITION(CLIENT1, StepFive) - { - auto reg0 = getHelper()->getRegion(regionNames[0]); - auto reg1 = getHelper()->getRegion(regionNames[1]); - auto vec0 = reg0->serverKeys(); - auto vec1 = reg1->serverKeys(); - ASSERT(vec0.size() == 2, "Should have 2 keys in first region."); - ASSERT(vec1.size() == 2, "Should have 2 keys in second region."); - std::string key0, key1; - key0 = vec0[0]->toString().c_str(); - key1 = vec0[1]->toString().c_str(); - ASSERT(key0 != key1, "The two keys should be different in first region."); - ASSERT(key0 == keys[0] || key0 == keys[1], - "Unexpected key in first region."); - ASSERT(key1 == keys[0] || key1 == keys[1], - "Unexpected key in first region."); - - key0 = vec1[0]->toString().c_str(); - key1 = vec1[1]->toString().c_str(); - ASSERT(key0 != key1, "The two keys should be different in second region."); - ASSERT(key0 == keys[2] || key0 == keys[3], - "Unexpected key in second region."); - ASSERT(key1 == keys[2] || key1 == keys[3], - "Unexpected key in second region."); - - doNetsearch(regionNames[0], keys[1], vals[1]); - doNetsearch(regionNames[1], keys[3], vals[3]); - updateEntry(regionNames[0], keys[0], nvals[0]); - updateEntry(regionNames[1], keys[2], nvals[2]); - LOG("StepFive complete."); - } -END_TASK_DEFINITION -DUNIT_TASK_DEFINITION(CLIENT2, StepSix) - { - doNetsearch(regionNames[0], keys[0], vals[0]); - doNetsearch(regionNames[1], keys[2], vals[2]); - auto txManager = getHelper()->getCache()->getCacheTransactionManager(); - txManager->begin(); - updateEntry(regionNames[0], keys[1], nvals[1]); - updateEntry(regionNames[1], keys[3], nvals[3]); - txManager->prepare(); - txManager->commit(); - LOG("StepSix complete."); - } -END_TASK_DEFINITION - -DUNIT_TASK_DEFINITION(CLIENT1, CreateClient1additionalEntries) - { - auto txManager = getHelper()->getCache()->getCacheTransactionManager(); - txManager->begin(); - createEntry(regionNames[0], keys[7], vals[7]); - createEntry(regionNames[1], keys[8], vals[8]); - txManager->prepare(); - txManager->commit(); - verifyEntry(regionNames[0], keys[7], vals[7]); - verifyEntry(regionNames[1], keys[8], vals[8]); - txManager->begin(); - updateEntry(regionNames[0], keys[7], nvals[7]); - updateEntry(regionNames[1], keys[8], nvals[8]); - txManager->commit(); - verifyEntry(regionNames[0], keys[7], nvals[7]); - verifyEntry(regionNames[1], keys[8], nvals[8]); - LOG("StepSeven complete."); - } -END_TASK_DEFINITION -DUNIT_TASK_DEFINITION(CLIENT2, CreateClient2additionalEntries) - { - doNetsearch(regionNames[0], keys[0], vals[0]); - doNetsearch(regionNames[1], keys[2], vals[2]); - auto txManager = getHelper()->getCache()->getCacheTransactionManager(); - txManager->begin(); - createEntry(regionNames[0], keys[9], vals[9]); - createEntry(regionNames[1], keys[10], vals[10]); - txManager->commit(); - verifyEntry(regionNames[0], keys[9], vals[9]); - verifyEntry(regionNames[1], keys[10], vals[10]); - txManager->begin(); - updateEntry(regionNames[0], keys[9], nvals[9]); - updateEntry(regionNames[1], keys[10], nvals[10]); - txManager->prepare(); - txManager->commit(); - verifyEntry(regionNames[0], keys[9], nvals[9]); - verifyEntry(regionNames[1], keys[10], nvals[10]); - LOG("StepEight complete."); - } -END_TASK_DEFINITION -DUNIT_TASK_DEFINITION(CLIENT1, UpdateClient1additionalEntries) - { - auto txManager = getHelper()->getCache()->getCacheTransactionManager(); - txManager->begin(); - updateEntry(regionNames[0], keys[7], vals[5]); - updateEntry(regionNames[1], keys[8], vals[6]); - txManager->commit(); - verifyEntry(regionNames[0], keys[7], vals[5]); - verifyEntry(regionNames[1], keys[8], vals[6]); - txManager->begin(); - updateEntry(regionNames[0], keys[7], vals[7]); - updateEntry(regionNames[1], keys[8], vals[8]); - txManager->prepare(); - txManager->rollback(); - verifyEntry(regionNames[0], keys[7], vals[5]); - verifyEntry(regionNames[1], keys[8], vals[6]); - txManager->begin(); - updateEntry(regionNames[0], keys[7], nvals[7]); - updateEntry(regionNames[1], keys[8], nvals[8]); - txManager->commit(); - verifyEntry(regionNames[0], keys[7], nvals[7]); - verifyEntry(regionNames[1], keys[8], nvals[8]); - LOG("StepNine complete."); - } -END_TASK_DEFINITION -DUNIT_TASK_DEFINITION(CLIENT2, UpdateClient2additionalEntries) - { - auto txManager = getHelper()->getCache()->getCacheTransactionManager(); - txManager->begin(); - updateEntry(regionNames[0], keys[9], nvals[7]); - updateEntry(regionNames[1], keys[10], nvals[8]); - txManager->prepare(); - txManager->commit(); - verifyEntry(regionNames[0], keys[9], nvals[7]); - verifyEntry(regionNames[1], keys[10], nvals[8]); - txManager->begin(); - updateEntry(regionNames[0], keys[9], nvals[9]); - updateEntry(regionNames[1], keys[10], nvals[10]); - txManager->rollback(); - verifyEntry(regionNames[0], keys[9], nvals[7]); - verifyEntry(regionNames[1], keys[10], nvals[8]); - txManager->begin(); - updateEntry(regionNames[0], keys[9], nvals[9]); - updateEntry(regionNames[1], keys[10], nvals[10]); - txManager->prepare(); - txManager->commit(); - verifyEntry(regionNames[0], keys[9], nvals[9]); - verifyEntry(regionNames[1], keys[10], nvals[10]); - LOG("StepTen complete."); - } -END_TASK_DEFINITION - -DUNIT_TASK_DEFINITION(CLIENT1, CloseCache1) - { cleanProc(); } -END_TASK_DEFINITION - -DUNIT_TASK_DEFINITION(CLIENT2, CloseCache2) - { cleanProc(); } -END_TASK_DEFINITION - -DUNIT_TASK_DEFINITION(SERVER1, CloseServer1) - { - if (isLocalServer) { - CacheHelper::closeServer(1); - LOG("SERVER1 stopped"); - } - } -END_TASK_DEFINITION - -void runXATransactionOps(bool isSticky = false) { - CALL_TASK(CreateLocator1); - CALL_TASK(CreateServer1_With_Locator) - - if (isSticky) { - CALL_TASK(CreateNonexistentServerRegion_Pooled_Locator_Sticky); - CALL_TASK(StepOne_Pooled_Locator_Sticky); - CALL_TASK(StepTwo_Pooled_Locator_Sticky); - } else { - CALL_TASK(CreateNonexistentServerRegion_Pooled_Locator); - CALL_TASK(StepOne_Pooled_Locator); - CALL_TASK(StepTwo_Pooled_Locator); - } - - CALL_TASK(StepThree); - CALL_TASK(StepFour); - CALL_TASK(StepFive); - CALL_TASK(StepSix); - CALL_TASK(CreateClient1additionalEntries); - CALL_TASK(CreateClient2additionalEntries); - CALL_TASK(UpdateClient1additionalEntries); - CALL_TASK(UpdateClient2additionalEntries); - - CALL_TASK(CloseCache1); - CALL_TASK(CloseCache2); - CALL_TASK(CloseServer1); - CALL_TASK(CloseLocator1); -} - -} // namespace - -#endif // GEODE_INTEGRATION_TEST_THINCLIENTTRANSACTIONSNEWXA_H_ diff --git a/cppcache/integration-test/testThinClientTransactionsNewXA.cpp b/cppcache/integration-test/testThinClientTransactionsNewXA.cpp deleted file mode 100644 index a0e6df8e83..0000000000 --- a/cppcache/integration-test/testThinClientTransactionsNewXA.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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. - */ - -#include "ThinClientTransactionsNewXA.hpp" - -DUNIT_MAIN - { - runXATransactionOps(false); - runXATransactionOps(true); - } -END_MAIN diff --git a/cppcache/integration/test/ClientTransactionXATest.cpp b/cppcache/integration/test/ClientTransactionXATest.cpp new file mode 100644 index 0000000000..277013c098 --- /dev/null +++ b/cppcache/integration/test/ClientTransactionXATest.cpp @@ -0,0 +1,91 @@ +/* + * 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. + */ + +#include + +#include +#include + +#include + +#include +#include +#include +#include + +#include "framework/Cluster.h" + +namespace { + +using apache::geode::client::CacheableString; + +std::shared_ptr setupRegion( + apache::geode::client::Cache &cache) { + auto region = + cache.createRegionFactory(apache::geode::client::RegionShortcut::PROXY) + .setPoolName("default") + .create("region"); + return region; +} + +TEST(ClientTransactionXATest, interTxand2PCTx) { + Cluster cluster{LocatorCount{1}, ServerCount{1}}; + cluster.getGfsh() + .create() + .region() + .withName("region") + .withType("PARTITION") + .execute(); + + auto cache = cluster.createCache(); + auto region = setupRegion(cache); + + cache.getCacheTransactionManager()->begin(); + region->put("one", "one"); + cache.getCacheTransactionManager()->commit(); + auto v1 = std::dynamic_pointer_cast(region->get("one")); + EXPECT_EQ("one", v1->value()); + + cache.getCacheTransactionManager()->begin(); + region->put("two", "two"); + cache.getCacheTransactionManager()->prepare(); + cache.getCacheTransactionManager()->commit(); + auto v2 = std::dynamic_pointer_cast(region->get("two")); + EXPECT_EQ("two", v2->value()); + + cache.getCacheTransactionManager()->begin(); + region->put("two", "three"); + cache.getCacheTransactionManager()->prepare(); + cache.getCacheTransactionManager()->rollback(); + auto v3 = std::dynamic_pointer_cast(region->get("two")); + EXPECT_EQ("two", v3->value()); + + cache.getCacheTransactionManager()->begin(); + region->put("one", "three"); + cache.getCacheTransactionManager()->rollback(); + auto v4 = std::dynamic_pointer_cast(region->get("one")); + EXPECT_EQ("one", v4->value()); + + cache.getCacheTransactionManager()->begin(); + region->put("one", "two"); + cache.getCacheTransactionManager()->prepare(); + cache.getCacheTransactionManager()->commit(); + auto v5 = std::dynamic_pointer_cast(region->get("one")); + EXPECT_EQ("two", v5->value()); +} + +} // namespace