IGNITE-2805: CPP: Added transactions API. This closes #645.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/bc143c6a Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/bc143c6a Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/bc143c6a Branch: refs/heads/master Commit: bc143c6aa325831e94d8f471d62921abdf9b777b Parents: 949f0a4 Author: isapego <[email protected]> Authored: Wed May 11 09:32:24 2016 +0300 Committer: vozerov-gridgain <[email protected]> Committed: Wed May 11 09:32:24 2016 +0300 ---------------------------------------------------------------------- .gitignore | 1 + .../ignite/impl/binary/binary_reader_impl.h | 6 +- .../src/impl/binary/binary_reader_impl.cpp | 4 +- .../common/include/ignite/common/concurrent.h | 13 +- modules/platforms/cpp/core-test/Makefile.am | 1 + .../cpp/core-test/config/cache-test.xml | 6 + .../cpp/core-test/project/vs/core-test.vcxproj | 1 + .../project/vs/core-test.vcxproj.filters | 3 + .../cpp/core-test/src/transactions_test.cpp | 639 +++++++++++++++++++ modules/platforms/cpp/core/Makefile.am | 7 +- modules/platforms/cpp/core/include/Makefile.am | 9 +- .../cpp/core/include/ignite/cache/cache.h | 8 +- .../cpp/core/include/ignite/cache/cache_entry.h | 29 +- .../include/ignite/cache/query/query_cursor.h | 55 +- .../ignite/cache/query/query_fields_cursor.h | 39 +- .../ignite/cache/query/query_fields_row.h | 39 +- .../include/ignite/cache/query/query_scan.h | 2 +- .../core/include/ignite/cache/query/query_sql.h | 4 +- .../include/ignite/cache/query/query_text.h | 2 +- .../platforms/cpp/core/include/ignite/ignite.h | 22 +- .../core/include/ignite/impl/cache/cache_impl.h | 71 +-- .../impl/cache/query/query_fields_row_impl.h | 16 +- .../cpp/core/include/ignite/impl/ignite_impl.h | 47 +- .../ignite/impl/interop/interop_target.h | 142 +++++ .../cpp/core/include/ignite/impl/operations.h | 83 ++- .../ignite/impl/transactions/transaction_impl.h | 220 +++++++ .../impl/transactions/transactions_impl.h | 138 ++++ .../include/ignite/transactions/transaction.h | 214 +++++++ .../ignite/transactions/transaction_consts.h | 92 +++ .../ignite/transactions/transaction_metrics.h | 174 +++++ .../include/ignite/transactions/transactions.h | 164 +++++ modules/platforms/cpp/core/namespaces.dox | 10 +- .../platforms/cpp/core/project/vs/core.vcxproj | 12 + .../cpp/core/project/vs/core.vcxproj.filters | 42 ++ modules/platforms/cpp/core/src/ignite.cpp | 10 + .../cpp/core/src/impl/cache/cache_impl.cpp | 131 +--- .../platforms/cpp/core/src/impl/ignite_impl.cpp | 28 +- .../core/src/impl/interop/interop_target.cpp | 142 +++++ .../src/impl/transactions/transaction_impl.cpp | 196 ++++++ .../src/impl/transactions/transactions_impl.cpp | 200 ++++++ .../cpp/core/src/transactions/transaction.cpp | 204 ++++++ .../cpp/core/src/transactions/transactions.cpp | 142 +++++ .../platforms/cpp/jni/include/ignite/jni/java.h | 14 +- modules/platforms/cpp/jni/src/java.cpp | 35 +- .../cpp/odbc/include/ignite/odbc/column.h | 6 + .../platforms/cpp/odbc/project/vs/odbc.vcxproj | 1 - .../cpp/odbc/project/vs/odbc.vcxproj.filters | 1 - 47 files changed, 3159 insertions(+), 266 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/.gitignore ---------------------------------------------------------------------- diff --git a/.gitignore b/.gitignore index 5268e18..f36b1d6 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,4 @@ git-patch-prop-local.sh .settings .classpath .project +/modules/platforms/**/*.VC.db \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h index 426e44f..d2a4e24 100644 --- a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h +++ b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h @@ -1327,7 +1327,7 @@ namespace ignite else { int32_t pos = stream->Position() - 1; - IGNITE_ERROR_FORMATTED_3(IgniteError::IGNITE_ERR_BINARY, "Invalid header", "position", pos, "expected", expHdr, "actual", typeId) + IGNITE_ERROR_FORMATTED_3(IgniteError::IGNITE_ERR_BINARY, "Invalid header", "position", pos, "expected", (int)expHdr, "actual", (int)typeId) } } @@ -1350,7 +1350,7 @@ namespace ignite else { int32_t pos = stream->Position() - 1; - IGNITE_ERROR_FORMATTED_3(IgniteError::IGNITE_ERR_BINARY, "Invalid header", "position", pos, "expected", expHdr, "actual", typeId) + IGNITE_ERROR_FORMATTED_3(IgniteError::IGNITE_ERR_BINARY, "Invalid header", "position", pos, "expected", (int)expHdr, "actual", (int)typeId) } } }; @@ -1412,7 +1412,7 @@ namespace ignite else { int32_t pos = stream->Position() - 1; - IGNITE_ERROR_FORMATTED_3(IgniteError::IGNITE_ERR_BINARY, "Invalid header", "position", pos, "expected", IGNITE_TYPE_STRING, "actual", typeId) + IGNITE_ERROR_FORMATTED_3(IgniteError::IGNITE_ERR_BINARY, "Invalid header", "position", pos, "expected", (int)IGNITE_TYPE_STRING, "actual", (int)typeId) } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp b/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp index 1365c47..75a110b 100644 --- a/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp +++ b/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp @@ -733,7 +733,7 @@ namespace ignite else { int32_t pos = stream->Position() - 1; - IGNITE_ERROR_FORMATTED_3(IgniteError::IGNITE_ERR_BINARY, "Invalid header", "position", pos, "expected", IGNITE_TYPE_UUID, "actual", typeId) + IGNITE_ERROR_FORMATTED_3(IgniteError::IGNITE_ERR_BINARY, "Invalid header", "position", pos, "expected", (int)IGNITE_TYPE_UUID, "actual", (int)typeId) } } @@ -893,7 +893,7 @@ namespace ignite void BinaryReaderImpl::ThrowOnInvalidHeader(int32_t pos, int8_t expHdr, int8_t hdr) { - IGNITE_ERROR_FORMATTED_3(IgniteError::IGNITE_ERR_BINARY, "Invalid header", "position", pos, "expected", expHdr, "actual", hdr) + IGNITE_ERROR_FORMATTED_3(IgniteError::IGNITE_ERR_BINARY, "Invalid header", "position", pos, "expected", (int)expHdr, "actual", (int)hdr) } void BinaryReaderImpl::ThrowOnInvalidHeader(int8_t expHdr, int8_t hdr) const http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/common/include/ignite/common/concurrent.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/common/include/ignite/common/concurrent.h b/modules/platforms/cpp/common/include/ignite/common/concurrent.h index bc2d943..9a475da 100644 --- a/modules/platforms/cpp/common/include/ignite/common/concurrent.h +++ b/modules/platforms/cpp/common/include/ignite/common/concurrent.h @@ -216,7 +216,7 @@ namespace ignite */ T* Get() { - return impl ? static_cast<T*>(impl->Pointer()) : NULL; + return impl ? static_cast<T*>(impl->Pointer()) : 0; } /** @@ -226,18 +226,25 @@ namespace ignite */ const T* Get() const { - return impl ? static_cast<T*>(impl->Pointer()) : NULL; + return impl ? static_cast<T*>(impl->Pointer()) : 0; } /** * Check whether underlying raw pointer is valid. * + * Invalid instance can be returned if some of the previous + * operations have resulted in a failure. For example invalid + * instance can be returned by not-throwing version of method + * in case of error. Invalid instances also often can be + * created using default constructor. + * * @return True if valid. */ bool IsValid() const { - return impl != NULL; + return impl != 0; } + private: /** Implementation. */ SharedPointerImpl* impl; http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core-test/Makefile.am ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/Makefile.am b/modules/platforms/cpp/core-test/Makefile.am index d5634c9..d1f4ca5 100644 --- a/modules/platforms/cpp/core-test/Makefile.am +++ b/modules/platforms/cpp/core-test/Makefile.am @@ -58,6 +58,7 @@ ignite_tests_SOURCES = \ src/binary_reader_writer_raw_test.cpp \ src/binary_reader_writer_test.cpp \ src/binary_session_test.cpp \ + src/transactions_test.cpp \ src/teamcity_messages.cpp \ src/teamcity_boost.cpp http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core-test/config/cache-test.xml ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/config/cache-test.xml b/modules/platforms/cpp/core-test/config/cache-test.xml index f239ba9..659e12d 100644 --- a/modules/platforms/cpp/core-test/config/cache-test.xml +++ b/modules/platforms/cpp/core-test/config/cache-test.xml @@ -55,6 +55,12 @@ <property name="cacheMode" value="PARTITIONED"/> <property name="atomicityMode" value="TRANSACTIONAL"/> </bean> + + <bean parent="cache-template"> + <property name="name" value="partitioned2"/> + <property name="cacheMode" value="PARTITIONED"/> + <property name="atomicityMode" value="TRANSACTIONAL"/> + </bean> <bean parent="cache-template"> <property name="name" value="partitioned_atomic"/> http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj b/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj index 1bf27f2..edf87ba 100644 --- a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj +++ b/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj @@ -47,6 +47,7 @@ <ClCompile Include="..\..\src\interop_memory_test.cpp" /> <ClCompile Include="..\..\src\teamcity_boost.cpp" /> <ClCompile Include="..\..\src\teamcity_messages.cpp" /> + <ClCompile Include="..\..\src\transactions_test.cpp" /> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\include\ignite\binary_test_defs.h" /> http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters b/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters index ec7bab5..2259f4c 100644 --- a/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters +++ b/modules/platforms/cpp/core-test/project/vs/core-test.vcxproj.filters @@ -40,6 +40,9 @@ <ClCompile Include="..\..\src\ignite_error_test.cpp"> <Filter>Code</Filter> </ClCompile> + <ClCompile Include="..\..\src\transactions_test.cpp"> + <Filter>Code</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\include\teamcity_messages.h"> http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core-test/src/transactions_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core-test/src/transactions_test.cpp b/modules/platforms/cpp/core-test/src/transactions_test.cpp new file mode 100644 index 0000000..c194423 --- /dev/null +++ b/modules/platforms/cpp/core-test/src/transactions_test.cpp @@ -0,0 +1,639 @@ +/* + * 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. + */ + +#ifndef _MSC_VER + #define BOOST_TEST_DYN_LINK +#endif + +#include <boost/test/unit_test.hpp> + +#include "ignite/ignition.h" + +using namespace ignite; +using namespace ignite::transactions; +using namespace ignite::cache; +using namespace boost::unit_test; + +/* + * Test setup fixture. + */ +struct TransactionsTestSuiteFixture { + Ignite grid; + + /* + * Constructor. + */ + TransactionsTestSuiteFixture() + { + IgniteConfiguration cfg; + + cfg.jvmOpts.push_back("-Xdebug"); + cfg.jvmOpts.push_back("-Xnoagent"); + cfg.jvmOpts.push_back("-Djava.compiler=NONE"); + cfg.jvmOpts.push_back("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"); + cfg.jvmOpts.push_back("-XX:+HeapDumpOnOutOfMemoryError"); + +#ifdef IGNITE_TESTS_32 + cfg.jvmInitMem = 256; + cfg.jvmMaxMem = 768; +#else + cfg.jvmInitMem = 1024; + cfg.jvmMaxMem = 4096; +#endif + + char* cfgPath = getenv("IGNITE_NATIVE_TEST_CPP_CONFIG_PATH"); + + cfg.springCfgPath = std::string(cfgPath).append("/").append("cache-test.xml"); + + grid = Ignition::Start(cfg, "txTest"); + } + + /* + * Destructor. + */ + ~TransactionsTestSuiteFixture() + { + Ignition::Stop(grid.GetName(), true); + + grid = Ignite(); + } +}; + +BOOST_FIXTURE_TEST_SUITE(TransactionsTestSuite, TransactionsTestSuiteFixture) + +BOOST_AUTO_TEST_CASE(TransactionsMetrics) +{ + Cache<int, int> cache = grid.GetCache<int, int>("partitioned"); + + Transactions transactions = grid.GetTransactions(); + + TransactionMetrics metrics = transactions.GetMetrics(); + BOOST_REQUIRE(metrics.IsValid()); + + BOOST_CHECK_EQUAL(0, metrics.GetCommits()); + BOOST_CHECK_EQUAL(0, metrics.GetRollbacks()); +} + +BOOST_AUTO_TEST_CASE(TransactionCommit) +{ + Cache<int, int> cache = grid.GetCache<int, int>("partitioned"); + + Transactions transactions = grid.GetTransactions(); + + Transaction tx = transactions.GetTx(); + BOOST_REQUIRE(!tx.IsValid()); + + tx = transactions.TxStart(); + + BOOST_REQUIRE(transactions.GetTx().IsValid()); + + cache.Put(1, 1); + cache.Put(2, 2); + + tx.Commit(); + + BOOST_CHECK_EQUAL(1, cache.Get(1)); + BOOST_CHECK_EQUAL(2, cache.Get(2)); + + tx = transactions.GetTx(); + + BOOST_CHECK(!tx.IsValid()); +} + +BOOST_AUTO_TEST_CASE(TransactionRollback) +{ + Cache<int, int> cache = grid.GetCache<int, int>("partitioned"); + + cache.Put(1, 1); + cache.Put(2, 2); + + Transactions transactions = grid.GetTransactions(); + + Transaction tx = transactions.GetTx(); + BOOST_REQUIRE(!tx.IsValid()); + + tx = transactions.TxStart(); + + BOOST_REQUIRE(transactions.GetTx().IsValid()); + + cache.Put(1, 10); + cache.Put(2, 20); + + tx.Rollback(); + + BOOST_CHECK_EQUAL(1, cache.Get(1)); + BOOST_CHECK_EQUAL(2, cache.Get(2)); + + tx = transactions.GetTx(); + + BOOST_CHECK(!tx.IsValid()); +} + +BOOST_AUTO_TEST_CASE(TransactionClose) +{ + Cache<int, int> cache = grid.GetCache<int, int>("partitioned"); + + cache.Put(1, 1); + cache.Put(2, 2); + + Transactions transactions = grid.GetTransactions(); + + Transaction tx = transactions.GetTx(); + BOOST_REQUIRE(!tx.IsValid()); + + tx = transactions.TxStart(); + + BOOST_REQUIRE(transactions.GetTx().IsValid()); + + cache.Put(1, 10); + cache.Put(2, 20); + + tx.Close(); + + BOOST_CHECK_EQUAL(1, cache.Get(1)); + BOOST_CHECK_EQUAL(2, cache.Get(2)); + + tx = transactions.GetTx(); + + BOOST_CHECK(!tx.IsValid()); +} + +BOOST_AUTO_TEST_CASE(TransactionRollbackOnly) +{ + Cache<int, int> cache = grid.GetCache<int, int>("partitioned"); + + cache.Put(1, 1); + cache.Put(2, 2); + + Transactions transactions = grid.GetTransactions(); + + Transaction tx = transactions.TxStart(); + + cache.Put(1, 10); + cache.Put(2, 20); + + BOOST_CHECK(!tx.IsRollbackOnly()); + + tx.SetRollbackOnly(); + + BOOST_CHECK(tx.IsRollbackOnly()); + + try + { + tx.Commit(); + + BOOST_FAIL("Commit must fail for rollback-only transaction."); + } + catch (IgniteError& error) + { + // Expected exception. + BOOST_CHECK(error.GetCode() != IgniteError::IGNITE_SUCCESS); + } + + tx.Close(); + + BOOST_CHECK_EQUAL(IGNITE_TX_STATE_ROLLED_BACK, tx.GetState()); + BOOST_CHECK(tx.IsRollbackOnly()); + + BOOST_CHECK_EQUAL(1, cache.Get(1)); + BOOST_CHECK_EQUAL(2, cache.Get(2)); + + tx = transactions.GetTx(); + + BOOST_CHECK(!tx.IsValid()); +} + +BOOST_AUTO_TEST_CASE(TransactionAttributes) +{ + Cache<int, int> cache = grid.GetCache<int, int>("partitioned"); + + Transactions transactions = grid.GetTransactions(); + + Transaction tx = transactions.GetTx(); + BOOST_REQUIRE(!tx.IsValid()); + + tx = transactions.TxStart(IGNITE_TX_CONCURRENCY_OPTIMISTIC, + IGNITE_TX_ISOLATION_SERIALIZABLE, 1000, 100); + + BOOST_REQUIRE(transactions.GetTx().IsValid()); + + BOOST_CHECK_EQUAL(IGNITE_TX_CONCURRENCY_OPTIMISTIC, tx.GetConcurrency()); + BOOST_CHECK_EQUAL(IGNITE_TX_ISOLATION_SERIALIZABLE, tx.GetIsolation()); + BOOST_CHECK_EQUAL(1000, tx.GetTimeout()); + BOOST_CHECK_EQUAL(IGNITE_TX_STATE_ACTIVE, tx.GetState()); + + tx.Commit(); + + BOOST_CHECK_EQUAL(IGNITE_TX_STATE_COMMITTED, tx.GetState()); + + tx = transactions.GetTx(); + + BOOST_CHECK(!tx.IsValid()); + + tx = transactions.TxStart(IGNITE_TX_CONCURRENCY_PESSIMISTIC, + IGNITE_TX_ISOLATION_READ_COMMITTED, 2000, 10); + + BOOST_REQUIRE(transactions.GetTx().IsValid()); + + BOOST_CHECK_EQUAL(IGNITE_TX_CONCURRENCY_PESSIMISTIC, tx.GetConcurrency()); + BOOST_CHECK_EQUAL(IGNITE_TX_ISOLATION_READ_COMMITTED, tx.GetIsolation()); + BOOST_CHECK_EQUAL(2000, tx.GetTimeout()); + BOOST_CHECK_EQUAL(IGNITE_TX_STATE_ACTIVE, tx.GetState()); + + tx.Rollback(); + + BOOST_CHECK_EQUAL(IGNITE_TX_STATE_ROLLED_BACK, tx.GetState()); + + tx = transactions.GetTx(); + + BOOST_CHECK(!tx.IsValid()); + + tx = transactions.TxStart(IGNITE_TX_CONCURRENCY_OPTIMISTIC, + IGNITE_TX_ISOLATION_REPEATABLE_READ, 3000, 0); + + BOOST_REQUIRE(transactions.GetTx().IsValid()); + + BOOST_CHECK_EQUAL(IGNITE_TX_CONCURRENCY_OPTIMISTIC, tx.GetConcurrency()); + BOOST_CHECK_EQUAL(IGNITE_TX_ISOLATION_REPEATABLE_READ, tx.GetIsolation()); + BOOST_CHECK_EQUAL(3000, tx.GetTimeout()); + BOOST_CHECK_EQUAL(IGNITE_TX_STATE_ACTIVE, tx.GetState()); + + tx.Close(); + + BOOST_CHECK_EQUAL(IGNITE_TX_STATE_ROLLED_BACK, tx.GetState()); + + tx = transactions.GetTx(); + + BOOST_CHECK(!tx.IsValid()); +} + +BOOST_AUTO_TEST_CASE(CrossCacheCommit) +{ + Cache<int, int> cache1 = grid.GetCache<int, int>("partitioned"); + Cache<int, int> cache2 = grid.GetCache<int, int>("partitioned2"); + + cache1.Put(1, 1); + cache1.Put(2, 1); + + cache2.Put(1, 2); + cache2.Put(2, 2); + + Transactions transactions = grid.GetTransactions(); + + Transaction tx = transactions.GetTx(); + BOOST_REQUIRE(!tx.IsValid()); + + tx = transactions.TxStart(); + + BOOST_REQUIRE(transactions.GetTx().IsValid()); + + cache1.Put(1, 10); + cache1.Put(2, 10); + + cache2.Put(1, 20); + cache2.Put(2, 20); + + tx.Commit(); + + BOOST_CHECK_EQUAL(10, cache1.Get(1)); + BOOST_CHECK_EQUAL(10, cache1.Get(2)); + + BOOST_CHECK_EQUAL(20, cache2.Get(1)); + BOOST_CHECK_EQUAL(20, cache2.Get(2)); + + tx = transactions.GetTx(); + + BOOST_CHECK(!tx.IsValid()); +} + +BOOST_AUTO_TEST_CASE(CrossCacheRollback) +{ + Cache<int, int> cache1 = grid.GetCache<int, int>("partitioned"); + Cache<int, int> cache2 = grid.GetCache<int, int>("partitioned2"); + + cache1.Put(1, 1); + cache1.Put(2, 1); + + cache2.Put(1, 2); + cache2.Put(2, 2); + + Transactions transactions = grid.GetTransactions(); + + Transaction tx = transactions.GetTx(); + BOOST_REQUIRE(!tx.IsValid()); + + tx = transactions.TxStart(); + + BOOST_REQUIRE(transactions.GetTx().IsValid()); + + cache1.Put(1, 10); + cache1.Put(2, 10); + + cache2.Put(1, 20); + cache2.Put(2, 20); + + tx.Rollback(); + + BOOST_CHECK_EQUAL(1, cache1.Get(1)); + BOOST_CHECK_EQUAL(1, cache1.Get(2)); + + BOOST_CHECK_EQUAL(2, cache2.Get(1)); + BOOST_CHECK_EQUAL(2, cache2.Get(2)); + + tx = transactions.GetTx(); + + BOOST_CHECK(!tx.IsValid()); +} + +BOOST_AUTO_TEST_CASE(TransactionsMetricsNe) +{ + Cache<int, int> cache = grid.GetCache<int, int>("partitioned"); + + Transactions transactions = grid.GetTransactions(); + + IgniteError err; + + TransactionMetrics metrics = transactions.GetMetrics(err); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + BOOST_REQUIRE(metrics.IsValid()); + + BOOST_CHECK_EQUAL(0, metrics.GetCommits()); + BOOST_CHECK_EQUAL(0, metrics.GetRollbacks()); +} + +BOOST_AUTO_TEST_CASE(TransactionCommitNe) +{ + Cache<int, int> cache = grid.GetCache<int, int>("partitioned"); + + Transactions transactions = grid.GetTransactions(); + + IgniteError err; + + Transaction tx = transactions.GetTx(); + BOOST_REQUIRE(!tx.IsValid()); + + tx = transactions.TxStart(err); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + BOOST_REQUIRE(transactions.GetTx().IsValid()); + + cache.Put(1, 1, err); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + cache.Put(2, 2, err); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + tx.Commit(err); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + BOOST_CHECK_EQUAL(1, cache.Get(1, err)); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + BOOST_CHECK_EQUAL(2, cache.Get(2, err)); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + tx = transactions.GetTx(); + + BOOST_CHECK(!tx.IsValid()); +} + +BOOST_AUTO_TEST_CASE(TransactionRollbackNe) +{ + Cache<int, int> cache = grid.GetCache<int, int>("partitioned"); + + IgniteError err; + + cache.Put(1, 1, err); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + cache.Put(2, 2, err); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + Transactions transactions = grid.GetTransactions(); + + Transaction tx = transactions.GetTx(); + BOOST_REQUIRE(!tx.IsValid()); + + tx = transactions.TxStart(err); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + BOOST_REQUIRE(transactions.GetTx().IsValid()); + + cache.Put(1, 10, err); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + cache.Put(2, 20, err); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + tx.Rollback(err); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + BOOST_CHECK_EQUAL(1, cache.Get(1, err)); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + BOOST_CHECK_EQUAL(2, cache.Get(2, err)); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + tx = transactions.GetTx(); + + BOOST_CHECK(!tx.IsValid()); +} + +BOOST_AUTO_TEST_CASE(TransactionCloseNe) +{ + Cache<int, int> cache = grid.GetCache<int, int>("partitioned"); + + IgniteError err; + + cache.Put(1, 1, err); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + cache.Put(2, 2, err); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + Transactions transactions = grid.GetTransactions(); + + Transaction tx = transactions.GetTx(); + BOOST_REQUIRE(!tx.IsValid()); + + tx = transactions.TxStart(err); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + BOOST_REQUIRE(transactions.GetTx().IsValid()); + + cache.Put(1, 10, err); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + cache.Put(2, 20, err); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + tx.Close(err); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + BOOST_CHECK_EQUAL(1, cache.Get(1, err)); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + BOOST_CHECK_EQUAL(2, cache.Get(2, err)); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + tx = transactions.GetTx(); + + BOOST_CHECK(!tx.IsValid()); +} + +BOOST_AUTO_TEST_CASE(TransactionRollbackOnlyNe) +{ + Cache<int, int> cache = grid.GetCache<int, int>("partitioned"); + + IgniteError err; + + cache.Put(1, 1); + cache.Put(2, 2); + + Transactions transactions = grid.GetTransactions(); + + Transaction tx = transactions.TxStart(); + + cache.Put(1, 10); + cache.Put(2, 20); + + BOOST_CHECK(!tx.IsRollbackOnly()); + + tx.SetRollbackOnly(err); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + BOOST_CHECK(tx.IsRollbackOnly()); + + tx.Commit(err); + BOOST_REQUIRE(err.GetCode() != IgniteError::IGNITE_SUCCESS); + + tx.Close(err); + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + BOOST_CHECK_EQUAL(IGNITE_TX_STATE_ROLLED_BACK, tx.GetState()); + BOOST_CHECK(tx.IsRollbackOnly()); + + BOOST_CHECK_EQUAL(1, cache.Get(1)); + BOOST_CHECK_EQUAL(2, cache.Get(2)); + + tx = transactions.GetTx(); + + BOOST_CHECK(!tx.IsValid()); +} + +BOOST_AUTO_TEST_CASE(TransactionAttributesNe) +{ + Cache<int, int> cache = grid.GetCache<int, int>("partitioned"); + + IgniteError err; + + Transactions transactions = grid.GetTransactions(); + + Transaction tx = transactions.GetTx(); + BOOST_REQUIRE(!tx.IsValid()); + + tx = transactions.TxStart(IGNITE_TX_CONCURRENCY_OPTIMISTIC, + IGNITE_TX_ISOLATION_SERIALIZABLE, 1000, 100, err); + + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + BOOST_REQUIRE(transactions.GetTx().IsValid()); + + BOOST_CHECK_EQUAL(IGNITE_TX_CONCURRENCY_OPTIMISTIC, tx.GetConcurrency()); + BOOST_CHECK_EQUAL(IGNITE_TX_ISOLATION_SERIALIZABLE, tx.GetIsolation()); + BOOST_CHECK_EQUAL(1000, tx.GetTimeout()); + BOOST_CHECK_EQUAL(IGNITE_TX_STATE_ACTIVE, tx.GetState()); + + tx.Commit(); + + BOOST_CHECK_EQUAL(IGNITE_TX_STATE_COMMITTED, tx.GetState()); + + tx = transactions.GetTx(); + + BOOST_CHECK(!tx.IsValid()); + + tx = transactions.TxStart(IGNITE_TX_CONCURRENCY_PESSIMISTIC, + IGNITE_TX_ISOLATION_READ_COMMITTED, 2000, 10, err); + + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + BOOST_REQUIRE(transactions.GetTx().IsValid()); + + BOOST_CHECK_EQUAL(IGNITE_TX_CONCURRENCY_PESSIMISTIC, tx.GetConcurrency()); + BOOST_CHECK_EQUAL(IGNITE_TX_ISOLATION_READ_COMMITTED, tx.GetIsolation()); + BOOST_CHECK_EQUAL(2000, tx.GetTimeout()); + BOOST_CHECK_EQUAL(IGNITE_TX_STATE_ACTIVE, tx.GetState()); + + tx.Rollback(); + + BOOST_CHECK_EQUAL(IGNITE_TX_STATE_ROLLED_BACK, tx.GetState()); + + tx = transactions.GetTx(); + + BOOST_CHECK(!tx.IsValid()); + + tx = transactions.TxStart(IGNITE_TX_CONCURRENCY_OPTIMISTIC, + IGNITE_TX_ISOLATION_REPEATABLE_READ, 3000, 0, err); + + if (!err.GetCode() == IgniteError::IGNITE_SUCCESS) + BOOST_ERROR(err.GetText()); + + BOOST_REQUIRE(transactions.GetTx().IsValid()); + + BOOST_CHECK_EQUAL(IGNITE_TX_CONCURRENCY_OPTIMISTIC, tx.GetConcurrency()); + BOOST_CHECK_EQUAL(IGNITE_TX_ISOLATION_REPEATABLE_READ, tx.GetIsolation()); + BOOST_CHECK_EQUAL(3000, tx.GetTimeout()); + BOOST_CHECK_EQUAL(IGNITE_TX_STATE_ACTIVE, tx.GetState()); + + tx.Close(); + + BOOST_CHECK_EQUAL(IGNITE_TX_STATE_ROLLED_BACK, tx.GetState()); + + tx = transactions.GetTx(); + + BOOST_CHECK(!tx.IsValid()); +} + +BOOST_AUTO_TEST_SUITE_END() http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core/Makefile.am ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/Makefile.am b/modules/platforms/cpp/core/Makefile.am index 50d20b2..2b73476 100644 --- a/modules/platforms/cpp/core/Makefile.am +++ b/modules/platforms/cpp/core/Makefile.am @@ -60,7 +60,12 @@ libignite_la_SOURCES = \ src/impl/cache/query/query_impl.cpp \ src/impl/cache/cache_impl.cpp \ src/impl/interop/interop_external_memory.cpp \ - src/impl/ignite_impl.cpp + src/impl/interop/interop_target.cpp \ + src/impl/transactions/transaction_impl.cpp \ + src/impl/transactions/transactions_impl.cpp \ + src/impl/ignite_impl.cpp \ + src/transactions/transaction.cpp \ + src/transactions/transactions.cpp pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = $(srcdir)/ignite.pc http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core/include/Makefile.am ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/Makefile.am b/modules/platforms/cpp/core/include/Makefile.am index 7368b9f..f7159ae 100644 --- a/modules/platforms/cpp/core/include/Makefile.am +++ b/modules/platforms/cpp/core/include/Makefile.am @@ -27,8 +27,11 @@ nobase_include_HEADERS = \ ignite/impl/cache/query/query_fields_row_impl.h \ ignite/impl/cache/query/query_impl.h \ ignite/impl/cache/cache_impl.h \ + ignite/impl/interop/interop_target.h \ ignite/impl/interop/interop_external_memory.h \ ignite/impl/handle_registry.h \ + ignite/impl/transactions/transaction_impl.h \ + ignite/impl/transactions/transactions_impl.h \ ignite/cache/query/query_fields_row.h \ ignite/cache/query/query_fields_cursor.h \ ignite/cache/query/query_scan.h \ @@ -41,7 +44,11 @@ nobase_include_HEADERS = \ ignite/cache/cache.h \ ignite/cache/cache_entry.h \ ignite/cache/cache_peek_mode.h \ - ignite/ignition.h + ignite/ignition.h \ + ignite/transactions/transaction.h \ + ignite/transactions/transaction_consts.h \ + ignite/transactions/transactions.h \ + ignite/transactions/transaction_metrics.h uninstall-hook: if [ -d ${includedir}/ignite ]; then find ${includedir}/ignite -type d -empty -delete; fi http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core/include/ignite/cache/cache.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/cache/cache.h b/modules/platforms/cpp/core/include/ignite/cache/cache.h index a3a2197..e60c843 100644 --- a/modules/platforms/cpp/core/include/ignite/cache/cache.h +++ b/modules/platforms/cpp/core/include/ignite/cache/cache.h @@ -1184,9 +1184,15 @@ namespace ignite /** * Check if the instance is valid. * + * Invalid instance can be returned if some of the previous + * operations have resulted in a failure. For example invalid + * instance can be returned by not-throwing version of method + * in case of error. Invalid instances also often can be + * created using default constructor. + * * @return True if the instance is valid and can be used. */ - bool IsValid() + bool IsValid() const { return impl.IsValid(); } http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core/include/ignite/cache/cache_entry.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/cache/cache_entry.h b/modules/platforms/cpp/core/include/ignite/cache/cache_entry.h index ca8576e..adace5d 100644 --- a/modules/platforms/cpp/core/include/ignite/cache/cache_entry.h +++ b/modules/platforms/cpp/core/include/ignite/cache/cache_entry.h @@ -30,7 +30,10 @@ namespace ignite namespace cache { /** - * Cache entry. + * Cache entry class template. + * + * Both key and value types should be default-constructable, + * copy-constructable and assignable. */ template<typename K, typename V> class IGNITE_IMPORT_EXPORT CacheEntry @@ -38,8 +41,11 @@ namespace ignite public: /** * Default constructor. + * + * Creates instance with both key and value default-constructed. */ - CacheEntry() : key(K()), val(V()) + CacheEntry() : + key(), val() { // No-op. } @@ -50,7 +56,8 @@ namespace ignite * @param key Key. * @param val Value. */ - CacheEntry(const K& key, const V& val) : key(key), val(val) + CacheEntry(const K& key, const V& val) : + key(key), val(val) { // No-op. } @@ -77,14 +84,8 @@ namespace ignite { CacheEntry tmp(other); - K& key0 = key; - V& val0 = val; - - key = tmp.key; - val = tmp.val; - - tmp.key = key0; - tmp.val = val0; + std::swap(key, tmp.key); + std::swap(val, tmp.val); } return *this; @@ -92,7 +93,7 @@ namespace ignite /** * Get key. - * + * * @return Key. */ K GetKey() const @@ -112,10 +113,10 @@ namespace ignite private: /** Key. */ - K key; + K key; /** Value. */ - V val; + V val; }; } } http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core/include/ignite/cache/query/query_cursor.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/cache/query/query_cursor.h b/modules/platforms/cpp/core/include/ignite/cache/query/query_cursor.h index ea8fd3f..45eb54a 100644 --- a/modules/platforms/cpp/core/include/ignite/cache/query/query_cursor.h +++ b/modules/platforms/cpp/core/include/ignite/cache/query/query_cursor.h @@ -39,7 +39,10 @@ namespace ignite namespace query { /** - * Query cursor. + * Query cursor class template. + * + * Both key and value types should be default-constructable, + * copy-constructable and assignable. */ template<typename K, typename V> class QueryCursor @@ -47,8 +50,11 @@ namespace ignite public: /** * Default constructor. + * + * Constructed instance is not valid and thus can not be used + * as a cursor. */ - QueryCursor() : impl(NULL) + QueryCursor() : impl(0) { // No-op. } @@ -56,6 +62,8 @@ namespace ignite /** * Constructor. * + * Internal method. Should not be used by user. + * * @param impl Implementation. */ QueryCursor(impl::cache::query::QueryCursorImpl* impl) : impl(impl) @@ -65,6 +73,9 @@ namespace ignite /** * Check whether next entry exists. + * Throws IgniteError class instance in case of failure. + * + * This method should only be used on the valid instance. * * @return True if next entry exists. */ @@ -81,9 +92,13 @@ namespace ignite /** * Check whether next entry exists. + * Properly sets error param in case of failure. * - * @param err Error. - * @return True if next entry exists. + * This method should only be used on the valid instance. + * + * @param err Used to set operation result. + * @return True if next entry exists and operation resulted in + * success. Returns false on failure. */ bool HasNext(IgniteError& err) { @@ -102,6 +117,9 @@ namespace ignite /** * Get next entry. + * Throws IgniteError class instance in case of failure. + * + * This method should only be used on the valid instance. * * @return Next entry. */ @@ -118,9 +136,14 @@ namespace ignite /** * Get next entry. + * Properly sets error param in case of failure. * - * @param err Error. - * @return Next entry. + * This method should only be used on the valid instance. + * + * @param err Used to set operation result. + * @return Next entry on success and default-constructed + * entry on failure. Default-constructed entry contains + * default-constructed instances of both key and value types. */ CacheEntry<K, V> GetNext(IgniteError& err) { @@ -152,7 +175,10 @@ namespace ignite /** * Get all entries. - * + * Throws IgniteError class instance in case of failure. + * + * This method should only be used on the valid instance. + * * @param Vector where query entries will be stored. */ void GetAll(std::vector<CacheEntry<K, V>>& res) @@ -166,9 +192,12 @@ namespace ignite /** * Get all entries. + * Properly sets error param in case of failure. + * + * This method should only be used on the valid instance. * * @param Vector where query entries will be stored. - * @param err Error. + * @param err Used to set operation result. */ void GetAll(std::vector<CacheEntry<K, V>>& res, IgniteError& err) { @@ -187,9 +216,15 @@ namespace ignite /** * Check if the instance is valid. * + * Invalid instance can be returned if some of the previous + * operations have resulted in a failure. For example invalid + * instance can be returned by not-throwing version of method + * in case of error. Invalid instances also often can be + * created using default constructor. + * * @return True if the instance is valid and can be used. */ - bool IsValid() + bool IsValid() const { return impl.IsValid(); } @@ -202,4 +237,4 @@ namespace ignite } } -#endif //_IGNITE_CACHE_QUERY_QUERY_CURSOR \ No newline at end of file +#endif //_IGNITE_CACHE_QUERY_QUERY_CURSOR http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core/include/ignite/cache/query/query_fields_cursor.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/cache/query/query_fields_cursor.h b/modules/platforms/cpp/core/include/ignite/cache/query/query_fields_cursor.h index 1e70f97..3952ece 100644 --- a/modules/platforms/cpp/core/include/ignite/cache/query/query_fields_cursor.h +++ b/modules/platforms/cpp/core/include/ignite/cache/query/query_fields_cursor.h @@ -47,8 +47,11 @@ namespace ignite public: /** * Default constructor. + * + * Constructed instance is not valid and thus can not be used + * as a cursor. */ - QueryFieldsCursor() : impl(NULL) + QueryFieldsCursor() : impl(0) { // No-op. } @@ -56,6 +59,8 @@ namespace ignite /** * Constructor. * + * Internal method. Should not be used by user. + * * @param impl Implementation. */ QueryFieldsCursor(impl::cache::query::QueryCursorImpl* impl) : impl(impl) @@ -65,6 +70,9 @@ namespace ignite /** * Check whether next entry exists. + * Throws IgniteError class instance in case of failure. + * + * This method should only be used on the valid instance. * * @return True if next entry exists. */ @@ -81,9 +89,13 @@ namespace ignite /** * Check whether next entry exists. + * Properly sets error param in case of failure. * - * @param err Error. - * @return True if next entry exists. + * This method should only be used on the valid instance. + * + * @param err Used to set operation result. + * @return True if next entry exists and operation resulted in + * success. Returns false on failure. */ bool HasNext(IgniteError& err) { @@ -102,6 +114,9 @@ namespace ignite /** * Get next entry. + * Throws IgniteError class instance in case of failure. + * + * This method should only be used on the valid instance. * * @return Next entry. */ @@ -118,9 +133,13 @@ namespace ignite /** * Get next entry. + * Properly sets error param in case of failure. * - * @param err Error. - * @return Next entry. + * This method should only be used on the valid instance. + * + * @param err Used to set operation result. + * @return Next entry on success and invalid row instance on + * failure. */ QueryFieldsRow GetNext(IgniteError& err) { @@ -140,9 +159,15 @@ namespace ignite /** * Check if the instance is valid. * + * Invalid instance can be returned if some of the previous + * operations have resulted in a failure. For example invalid + * instance can be returned by not-throwing version of method + * in case of error. Invalid instances also often can be + * created using default constructor. + * * @return True if the instance is valid and can be used. */ - bool IsValid() + bool IsValid() const { return impl.IsValid(); } @@ -155,4 +180,4 @@ namespace ignite } } -#endif //_IGNITE_CACHE_QUERY_QUERY_FIELDS_CURSOR \ No newline at end of file +#endif //_IGNITE_CACHE_QUERY_QUERY_FIELDS_CURSOR http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core/include/ignite/cache/query/query_fields_row.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/cache/query/query_fields_row.h b/modules/platforms/cpp/core/include/ignite/cache/query/query_fields_row.h index 48a015a..521da76 100644 --- a/modules/platforms/cpp/core/include/ignite/cache/query/query_fields_row.h +++ b/modules/platforms/cpp/core/include/ignite/cache/query/query_fields_row.h @@ -46,8 +46,11 @@ namespace ignite public: /** * Default constructor. + * + * Constructed instance is not valid and thus can not be used + * as a cursor. */ - QueryFieldsRow() : impl(NULL) + QueryFieldsRow() : impl(0) { // No-op. } @@ -55,6 +58,8 @@ namespace ignite /** * Constructor. * + * Internal method. Should not be used by user. + * * @param impl Implementation. */ QueryFieldsRow(impl::cache::query::QueryFieldsRowImpl* impl) : impl(impl) @@ -64,6 +69,9 @@ namespace ignite /** * Check whether next entry exists. + * Throws IgniteError class instance in case of failure. + * + * This method should only be used on the valid instance. * * @return True if next entry exists. */ @@ -80,9 +88,13 @@ namespace ignite /** * Check whether next entry exists. + * Properly sets error param in case of failure. * - * @param err Error. - * @return True if next entry exists. + * This method should only be used on the valid instance. + * + * @param err Used to set operation result. + * @return True if next entry exists and operation resulted in + * success. Returns false on failure. */ bool HasNext(IgniteError& err) { @@ -101,6 +113,9 @@ namespace ignite /** * Get next entry. + * Throws IgniteError class instance in case of failure. + * + * This method should only be used on the valid instance. * * @return Next entry. */ @@ -118,9 +133,13 @@ namespace ignite /** * Get next entry. + * Properly sets error param in case of failure. * - * @param err Error. - * @return Next entry. + * This method should only be used on the valid instance. + * + * @param err Used to set operation result. + * @return Next entry on success and default-constructed type + * instance on failure. */ template<typename T> T GetNext(IgniteError& err) @@ -141,9 +160,15 @@ namespace ignite /** * Check if the instance is valid. * + * Invalid instance can be returned if some of the previous + * operations have resulted in a failure. For example invalid + * instance can be returned by not-throwing version of method + * in case of error. Invalid instances also often can be + * created using default constructor. + * * @return True if the instance is valid and can be used. */ - bool IsValid() + bool IsValid() const { return impl.IsValid(); } @@ -156,4 +181,4 @@ namespace ignite } } -#endif //_IGNITE_CACHE_QUERY_QUERY_FIELDS_ROW \ No newline at end of file +#endif //_IGNITE_CACHE_QUERY_QUERY_FIELDS_ROW http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core/include/ignite/cache/query/query_scan.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/cache/query/query_scan.h b/modules/platforms/cpp/core/include/ignite/cache/query/query_scan.h index 619e280..d4dd565 100644 --- a/modules/platforms/cpp/core/include/ignite/cache/query/query_scan.h +++ b/modules/platforms/cpp/core/include/ignite/cache/query/query_scan.h @@ -41,7 +41,7 @@ namespace ignite { public: /** - * Constructor. + * Default constructor. */ ScanQuery() : part(-1), pageSize(1024), loc(false) { http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h b/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h index f4ddb7d..d80fa51 100644 --- a/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h +++ b/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h @@ -49,7 +49,7 @@ namespace ignite * @param sql SQL string. */ SqlQuery(const std::string& type, const std::string& sql) : type(type), sql(sql), pageSize(1024), - loc(false), args(NULL) + loc(false), args() { // No-op. } @@ -245,4 +245,4 @@ namespace ignite } } -#endif //_IGNITE_CACHE_QUERY_QUERY_SQL \ No newline at end of file +#endif //_IGNITE_CACHE_QUERY_QUERY_SQL http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core/include/ignite/cache/query/query_text.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/cache/query/query_text.h b/modules/platforms/cpp/core/include/ignite/cache/query/query_text.h index 4f1c436..ded8f22 100644 --- a/modules/platforms/cpp/core/include/ignite/cache/query/query_text.h +++ b/modules/platforms/cpp/core/include/ignite/cache/query/query_text.h @@ -162,4 +162,4 @@ namespace ignite } } -#endif //_IGNITE_CACHE_QUERY_QUERY_TEXT \ No newline at end of file +#endif //_IGNITE_CACHE_QUERY_QUERY_TEXT http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core/include/ignite/ignite.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/ignite.h b/modules/platforms/cpp/core/include/ignite/ignite.h index aec9801..e4f9208 100644 --- a/modules/platforms/cpp/core/include/ignite/ignite.h +++ b/modules/platforms/cpp/core/include/ignite/ignite.h @@ -24,6 +24,7 @@ #define _IGNITE_IGNITE #include "ignite/cache/cache.h" +#include "ignite/transactions/transactions.h" #include "ignite/impl/ignite_impl.h" #include "ignite/ignite_configuration.h" @@ -81,7 +82,7 @@ namespace ignite template<typename K, typename V> cache::Cache<K, V> GetCache(const char* name, IgniteError* err) { - impl::cache::CacheImpl* cacheImpl = impl.Get()->GetCache<K, V>(name, err); + impl::cache::CacheImpl* cacheImpl = impl.Get()->GetCache<K, V>(name, *err); return cache::Cache<K, V>(cacheImpl); } @@ -114,7 +115,7 @@ namespace ignite template<typename K, typename V> cache::Cache<K, V> GetOrCreateCache(const char* name, IgniteError* err) { - impl::cache::CacheImpl* cacheImpl = impl.Get()->GetOrCreateCache<K, V>(name, err); + impl::cache::CacheImpl* cacheImpl = impl.Get()->GetOrCreateCache<K, V>(name, *err); return cache::Cache<K, V>(cacheImpl); } @@ -147,17 +148,30 @@ namespace ignite template<typename K, typename V> cache::Cache<K, V> CreateCache(const char* name, IgniteError* err) { - impl::cache::CacheImpl* cacheImpl = impl.Get()->CreateCache<K, V>(name, err); + impl::cache::CacheImpl* cacheImpl = impl.Get()->CreateCache<K, V>(name, *err); return cache::Cache<K, V>(cacheImpl); } /** + * Get transactions. + * + * @return Transaction class instance. + */ + transactions::Transactions GetTransactions(); + + /** * Check if the instance is valid. + * + * Invalid instance can be returned if some of the previous + * operations have resulted in a failure. For example invalid + * instance can be returned by not-throwing version of method + * in case of error. Invalid instances also often can be + * created using default constructor. * * @return True if the instance is valid and can be used. */ - bool IsValid() + bool IsValid() const { return impl.IsValid(); } http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core/include/ignite/impl/cache/cache_impl.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/impl/cache/cache_impl.h b/modules/platforms/cpp/core/include/ignite/impl/cache/cache_impl.h index d69a6eb..e5f8ab8 100644 --- a/modules/platforms/cpp/core/include/ignite/impl/cache/cache_impl.h +++ b/modules/platforms/cpp/core/include/ignite/impl/cache/cache_impl.h @@ -18,13 +18,13 @@ #ifndef _IGNITE_CACHE_IMPL #define _IGNITE_CACHE_IMPL -#include "ignite/cache/query/query_scan.h" -#include "ignite/cache/query/query_sql.h" -#include "ignite/cache/query/query_text.h" -#include "ignite/cache/query/query_sql_fields.h" -#include "ignite/impl/ignite_environment.h" -#include "ignite/impl/cache/query/query_impl.h" -#include "ignite/impl/operations.h" +#include <ignite/cache/query/query_scan.h> +#include <ignite/cache/query/query_sql.h> +#include <ignite/cache/query/query_text.h> +#include <ignite/cache/query/query_sql_fields.h> +#include <ignite/impl/cache/query/query_impl.h> + +#include <ignite/impl/interop/interop_target.h> namespace ignite { @@ -35,7 +35,7 @@ namespace ignite /** * Cache implementation. */ - class IGNITE_IMPORT_EXPORT CacheImpl + class IGNITE_IMPORT_EXPORT CacheImpl : private interop::InteropTarget { public: /** @@ -331,33 +331,9 @@ namespace ignite /** Name. */ char* name; - /** Environment. */ - ignite::common::concurrent::SharedPointer<IgniteEnvironment> env; - - /** Handle to Java object. */ - jobject javaRef; - IGNITE_NO_COPY_ASSIGNMENT(CacheImpl) /** - * Write data to memory. - * - * @param mem Memory. - * @param inOp Input opeartion. - * @param err Error. - * @return Memory pointer. - */ - int64_t WriteTo(interop::InteropMemory* mem, InputOperation& inOp, IgniteError* err); - - /** - * Read data from memory. - * - * @param mem Memory. - * @param outOp Output operation. - */ - void ReadFrom(interop::InteropMemory* mem, OutputOperation& outOp); - - /** * Internal cache size routine. * * @param peekModes Peek modes. @@ -368,27 +344,6 @@ namespace ignite int SizeInternal(const int32_t peekModes, const bool loc, IgniteError* err); /** - * Internal out operation. - * - * @param opType Operation type. - * @param inOp Input. - * @param err Error. - * @return Result. - */ - bool OutOpInternal(const int32_t opType, InputOperation& inOp, IgniteError* err); - - /** - * Internal out-in operation. - * - * @param opType Operation type. - * @param inOp Input. - * @param outOp Output. - * @param err Error. - */ - void OutInOpInternal(const int32_t opType, InputOperation& inOp, OutputOperation& outOp, - IgniteError* err); - - /** * Internal query execution routine. * * @param qry Query. @@ -400,23 +355,23 @@ namespace ignite { ignite::jni::java::JniErrorInfo jniErr; - ignite::common::concurrent::SharedPointer<interop::InteropMemory> mem = env.Get()->AllocateMemory(); + ignite::common::concurrent::SharedPointer<interop::InteropMemory> mem = GetEnvironment().AllocateMemory(); interop::InteropMemory* mem0 = mem.Get(); interop::InteropOutputStream out(mem0); - binary::BinaryWriterImpl writer(&out, env.Get()->GetTypeManager()); + binary::BinaryWriterImpl writer(&out, GetEnvironment().GetTypeManager()); ignite::binary::BinaryRawWriter rawWriter(&writer); qry.Write(rawWriter); out.Synchronize(); - jobject qryJavaRef = env.Get()->Context()->CacheOutOpQueryCursor(javaRef, typ, mem.Get()->PointerLong(), - &jniErr); + jobject qryJavaRef = GetEnvironment().Context()->CacheOutOpQueryCursor(GetTarget(), + typ, mem.Get()->PointerLong(), &jniErr); IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err); if (jniErr.code == ignite::java::IGNITE_JNI_ERR_SUCCESS) - return new query::QueryCursorImpl(env, qryJavaRef); + return new query::QueryCursorImpl(GetEnvironmentPointer(), qryJavaRef); else return NULL; } http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core/include/ignite/impl/cache/query/query_fields_row_impl.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/impl/cache/query/query_fields_row_impl.h b/modules/platforms/cpp/core/include/ignite/impl/cache/query/query_fields_row_impl.h index e940895..233c2d4 100644 --- a/modules/platforms/cpp/core/include/ignite/impl/cache/query/query_fields_row_impl.h +++ b/modules/platforms/cpp/core/include/ignite/impl/cache/query/query_fields_row_impl.h @@ -42,12 +42,12 @@ namespace ignite class QueryFieldsRowImpl { public: - typedef common::concurrent::SharedPointer<interop::InteropMemory> InteropMemorySharedPtr; + typedef common::concurrent::SharedPointer<interop::InteropMemory> SP_InteropMemory; /** * Default constructor. */ - QueryFieldsRowImpl() : mem(NULL), stream(NULL), reader(NULL), size(0), + QueryFieldsRowImpl() : mem(0), stream(0), reader(0), size(0), processed(0) { // No-op. @@ -58,7 +58,7 @@ namespace ignite * * @param mem Memory containig row data. */ - QueryFieldsRowImpl(InteropMemorySharedPtr mem) : mem(mem), stream(mem.Get()), + QueryFieldsRowImpl(SP_InteropMemory mem) : mem(mem), stream(mem.Get()), reader(&stream), size(reader.ReadInt32()), processed(0) { // No-op. @@ -141,16 +141,22 @@ namespace ignite /** * Check if the instance is valid. * + * Invalid instance can be returned if some of the previous + * operations have resulted in a failure. For example invalid + * instance can be returned by not-throwing version of method + * in case of error. Invalid instances also often can be + * created using default constructor. + * * @return True if the instance is valid and can be used. */ bool IsValid() { - return mem.Get() != NULL; + return mem.Get() != 0; } private: /** Row memory. */ - InteropMemorySharedPtr mem; + SP_InteropMemory mem; /** Row data stream. */ interop::InteropInputStream stream; http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core/include/ignite/impl/ignite_impl.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/impl/ignite_impl.h b/modules/platforms/cpp/core/include/ignite/impl/ignite_impl.h index 14d5c7b..aa4059e 100644 --- a/modules/platforms/cpp/core/include/ignite/impl/ignite_impl.h +++ b/modules/platforms/cpp/core/include/ignite/impl/ignite_impl.h @@ -23,6 +23,7 @@ #include <ignite/common/utils.h> #include "ignite/impl/cache/cache_impl.h" +#include "ignite/impl/transactions/transactions_impl.h" #include "ignite/impl/ignite_environment.h" namespace ignite @@ -34,7 +35,8 @@ namespace ignite */ class IGNITE_FRIEND_EXPORT IgniteImpl { - friend class Ignite; + typedef ignite::common::concurrent::SharedPointer<IgniteEnvironment> SP_IgniteEnvironment; + typedef ignite::common::concurrent::SharedPointer<impl::transactions::TransactionsImpl> SP_TransactionsImpl; public: /** * Constructor used to create new instance. @@ -42,7 +44,7 @@ namespace ignite * @param env Environment. * @param javaRef Reference to java object. */ - IgniteImpl(ignite::common::concurrent::SharedPointer<IgniteEnvironment> env, jobject javaRef); + IgniteImpl(SP_IgniteEnvironment env, jobject javaRef); /** * Destructor. @@ -70,7 +72,7 @@ namespace ignite * @param err Error. */ template<typename K, typename V> - cache::CacheImpl* GetCache(const char* name, IgniteError* err) + cache::CacheImpl* GetCache(const char* name, IgniteError& err) { ignite::jni::java::JniErrorInfo jniErr; @@ -78,7 +80,7 @@ namespace ignite if (!cacheJavaRef) { - IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err); + IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, &err); return NULL; } @@ -95,7 +97,7 @@ namespace ignite * @param err Error. */ template<typename K, typename V> - cache::CacheImpl* GetOrCreateCache(const char* name, IgniteError* err) + cache::CacheImpl* GetOrCreateCache(const char* name, IgniteError& err) { ignite::jni::java::JniErrorInfo jniErr; @@ -103,7 +105,7 @@ namespace ignite if (!cacheJavaRef) { - IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err); + IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, &err); return NULL; } @@ -120,7 +122,7 @@ namespace ignite * @param err Error. */ template<typename K, typename V> - cache::CacheImpl* CreateCache(const char* name, IgniteError* err) + cache::CacheImpl* CreateCache(const char* name, IgniteError& err) { ignite::jni::java::JniErrorInfo jniErr; @@ -128,7 +130,7 @@ namespace ignite if (!cacheJavaRef) { - IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, err); + IgniteError::SetError(jniErr.code, jniErr.errCls, jniErr.errMsg, &err); return NULL; } @@ -150,13 +152,34 @@ namespace ignite { return proxy.impl.Get(); } + + /** + * Get transactions. + * + * @return TransactionsImpl instance. + */ + SP_TransactionsImpl GetTransactions() + { + return txImpl; + } + private: + /** + * Get transactions internal call. + * + * @return TransactionsImpl instance. + */ + SP_TransactionsImpl InternalGetTransactions(IgniteError &err); + /** Environment. */ - ignite::common::concurrent::SharedPointer<IgniteEnvironment> env; - + SP_IgniteEnvironment env; + /** Native Java counterpart. */ - jobject javaRef; - + jobject javaRef; + + /** Transactions implementaion. */ + SP_TransactionsImpl txImpl; + IGNITE_NO_COPY_ASSIGNMENT(IgniteImpl) }; } http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core/include/ignite/impl/interop/interop_target.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/impl/interop/interop_target.h b/modules/platforms/cpp/core/include/ignite/impl/interop/interop_target.h new file mode 100644 index 0000000..8b6ebb9 --- /dev/null +++ b/modules/platforms/cpp/core/include/ignite/impl/interop/interop_target.h @@ -0,0 +1,142 @@ +/* + * 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. + */ + +#ifndef _IGNITE_IMPL_INTEROP_INTEROP_TARGET +#define _IGNITE_IMPL_INTEROP_INTEROP_TARGET + +#include <ignite/impl/ignite_environment.h> +#include <ignite/impl/operations.h> + +namespace ignite +{ + namespace impl + { + namespace interop + { + /** + * Interop target. + */ + class IGNITE_IMPORT_EXPORT InteropTarget + { + public: + /** + * Constructor used to create new instance. + * + * @param env Environment. + * @param javaRef Reference to java object. + */ + InteropTarget(ignite::common::concurrent::SharedPointer<IgniteEnvironment> env, jobject javaRef); + + /** + * Destructor. + */ + ~InteropTarget(); + + /** + * Internal out operation. + * + * @param opType Operation type. + * @param inOp Input. + * @param err Error. + * @return Result. + */ + bool OutOp(int32_t opType, InputOperation& inOp, IgniteError* err); + + /** + * Internal out operation. + * + * @param opType Operation type. + * @param inOp Input. + * @param err Error. + * @return Result. + */ + bool InOp(int32_t opType, OutputOperation& outOp, IgniteError* err); + + /** + * Internal out-in operation. + * + * @param opType Operation type. + * @param inOp Input. + * @param outOp Output. + * @param err Error. + */ + void OutInOp(int32_t opType, InputOperation& inOp, OutputOperation& outOp, + IgniteError* err); + + /** + * Get environment shared pointer. + * + * @return Environment shared pointer. + */ + ignite::common::concurrent::SharedPointer<IgniteEnvironment> GetEnvironmentPointer() + { + return env; + } + + protected: + /** + * Get raw target. + * + * @return Underlying java object reference. + */ + jobject GetTarget() + { + return javaRef; + } + + /** + * Get environment reference. + * + * @return Environment reference. + */ + IgniteEnvironment& GetEnvironment() + { + return *env.Get(); + } + + private: + /** Environment. */ + ignite::common::concurrent::SharedPointer<IgniteEnvironment> env; + + /** Handle to Java object. */ + jobject javaRef; + + IGNITE_NO_COPY_ASSIGNMENT(InteropTarget) + + /** + * Write data to memory. + * + * @param mem Memory. + * @param inOp Input opeartion. + * @param err Error. + * @return Memory pointer. + */ + int64_t WriteTo(interop::InteropMemory* mem, InputOperation& inOp, IgniteError* err); + + /** + * Read data from memory. + * + * @param mem Memory. + * @param outOp Output operation. + */ + void ReadFrom(interop::InteropMemory* mem, OutputOperation& outOp); + }; + } + } +} + +#endif //_IGNITE_IMPL_INTEROP_INTEROP_TARGET \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core/include/ignite/impl/operations.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/impl/operations.h b/modules/platforms/cpp/core/include/ignite/impl/operations.h index 40dd123..ed01ece 100644 --- a/modules/platforms/cpp/core/include/ignite/impl/operations.h +++ b/modules/platforms/cpp/core/include/ignite/impl/operations.h @@ -310,7 +310,7 @@ namespace ignite }; /** - * Output operation returning single object. + * Output operation returning two objects. */ template<typename T1, typename T2> class Out2Operation : public OutputOperation @@ -359,7 +359,86 @@ namespace ignite IGNITE_NO_COPY_ASSIGNMENT(Out2Operation) }; - + + /** + * Output operation returning four objects. + */ + template<typename T1, typename T2, typename T3, typename T4> + class Out4Operation : public OutputOperation + { + public: + /** + * Constructor. + */ + Out4Operation() + { + // No-op. + } + + virtual void ProcessOutput(ignite::impl::binary::BinaryReaderImpl& reader) + { + val1 = reader.ReadTopObject<T1>(); + val2 = reader.ReadTopObject<T2>(); + val3 = reader.ReadTopObject<T3>(); + val4 = reader.ReadTopObject<T4>(); + } + + /** + * Get value 1. + * + * @param Value 1. + */ + T1& Get1() + { + return val1; + } + + /** + * Get value 2. + * + * @param Value 2. + */ + T2& Get2() + { + return val2; + } + + /** + * Get value 3. + * + * @param Value 3. + */ + T3& Get3() + { + return val3; + } + + /** + * Get value 4. + * + * @param Value 4. + */ + T4& Get4() + { + return val4; + } + + private: + /** Value 1. */ + T1 val1; + + /** Value 2. */ + T2 val2; + + /** Value 3. */ + T3 val3; + + /** Value 4. */ + T4 val4; + + IGNITE_NO_COPY_ASSIGNMENT(Out4Operation) + }; + /** * Output map operation. */ http://git-wip-us.apache.org/repos/asf/ignite/blob/bc143c6a/modules/platforms/cpp/core/include/ignite/impl/transactions/transaction_impl.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/core/include/ignite/impl/transactions/transaction_impl.h b/modules/platforms/cpp/core/include/ignite/impl/transactions/transaction_impl.h new file mode 100644 index 0000000..6889c62 --- /dev/null +++ b/modules/platforms/cpp/core/include/ignite/impl/transactions/transaction_impl.h @@ -0,0 +1,220 @@ +/* + * 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. + */ + +#ifndef _IGNITE_IMPL_TRANSACTIONS_TRANSACTION_IMPL +#define _IGNITE_IMPL_TRANSACTIONS_TRANSACTION_IMPL + +#include <ignite/common/concurrent.h> +#include <ignite/jni/java.h> +#include <ignite/transactions/transaction_consts.h> + +#include "ignite/impl/transactions/transactions_impl.h" +#include "ignite/impl/ignite_environment.h" + +namespace ignite +{ + namespace impl + { + namespace transactions + { + /** + * Transaction implementation. + */ + class IGNITE_FRIEND_EXPORT TransactionImpl + { + typedef ignite::common::concurrent::SharedPointer<TransactionImpl> SP_TransactionImpl; + typedef ignite::common::concurrent::SharedPointer<TransactionsImpl> SP_TransactionsImpl; + typedef ignite::common::concurrent::ThreadLocalInstance<SP_TransactionImpl> TL_SP_TransactionsImpl; + typedef ignite::common::concurrent::CriticalSection CriticalSection; + typedef ignite::transactions::TransactionState TransactionState; + public: + /** + * Destructor. + */ + ~TransactionImpl(); + + /** + * Factory method. Create new instance of the class. + * + * @param txs Transactions implimentation. + * @param id Transaction id. + * @param concurrency Concurrency. + * @param isolation Isolation. + * @param timeout Timeout in milliseconds. + * @param txSize Transaction size. + * + * @return Shared pointer to new instance. + */ + static SP_TransactionImpl Create(SP_TransactionsImpl txs, int concurrency, + int isolation, int64_t timeout, int32_t txSize, IgniteError& err); + + /** + * Get active transaction for the current thread. + * + * @return Active transaction implementation for current thread + * or null pointer if there is no active transaction for + * the thread. + */ + static SP_TransactionImpl GetCurrent(); + + /** + * Check if the transaction has been closed. + * + * @return True if the transaction has been closed. + */ + bool IsClosed() const; + + /** + * Commit the transaction. + * + * @param err Error. + */ + void Commit(IgniteError& err); + + /** + * Rollback the transaction. + * + * @param err Error. + */ + void Rollback(IgniteError& err); + + /** + * Close the transaction. + * + * @param err Error. + */ + void Close(IgniteError& err); + + /** + * Make transaction into rollback-only. + * + * After transaction have been marked as rollback-only it may + * only be rolled back. Error occurs if such transaction is + * being commited. + * + * @param err Error. + */ + void SetRollbackOnly(IgniteError& err); + + /** + * Check if the transaction is rollback-only. + * + * After transaction have been marked as rollback-only it may + * only be rolled back. Error occurs if such transaction is + * being commited. + * + * @param err Error. + * @return True if the transaction is rollback-only. + */ + bool IsRollbackOnly(IgniteError& err); + + /** + * Get state. + * + * @param err Error. + * @return Current state. + */ + TransactionState GetState(IgniteError& err); + + /** + * Get concurrency. + * + * @return Concurrency. + */ + int GetConcurrency() const + { + return concurrency; + } + + /** + * Get isolation. + * + * @return Isolation. + */ + int GetIsolation() const + { + return isolation; + } + + /** + * Get timeout. + * + * @return Timeout in milliseconds. + */ + int64_t GetTimeout() const + { + return timeout; + } + + private: + /** + * Constructor. + * + * @param txs Transactions implimentation. + * @param id Transaction id. + * @param concurrency Concurrency. + * @param isolation Isolation. + * @param timeout Timeout in milliseconds. + * @param txSize Transaction size. + */ + TransactionImpl(SP_TransactionsImpl txs, int64_t id, int concurrency, + int isolation, int64_t timeout, int32_t txSize); + + /** + * Get error for closed transaction. + * + * @return Error instance. + */ + IgniteError GetClosedError() const; + + /** Thread local instance of the transaction. */ + static TL_SP_TransactionsImpl threadTx; + + /** Access lock. */ + CriticalSection accessLock; + + /** Transactions. */ + SP_TransactionsImpl txs; + + /** Transaction ID. */ + int64_t id; + + /** Concurrency. */ + int concurrency; + + /** Isolation. */ + int isolation; + + /** Timeout in milliseconds. */ + int64_t timeout; + + /** Transaction size. */ + int32_t txSize; + + /** Transaction state. */ + TransactionState state; + + /** Closed flag. */ + bool closed; + + IGNITE_NO_COPY_ASSIGNMENT(TransactionImpl) + }; + } + } +} + +#endif //_IGNITE_IMPL_TRANSACTIONS_TRANSACTION_IMPL \ No newline at end of file
