This is an automated email from the ASF dual-hosted git repository. isapego pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push: new c7961db IGNITE-9904: Atomic Cache operations for C++ thin c7961db is described below commit c7961dbd27696d255e5777685efe38bd1151323d Author: Igor Sapego <isap...@apache.org> AuthorDate: Thu Jan 17 19:32:24 2019 +0300 IGNITE-9904: Atomic Cache operations for C++ thin This closes #5039 --- .../cpp/core/include/ignite/cache/cache.h | 32 +- .../cpp/thin-client-test/src/cache_client_test.cpp | 710 +++++++++++++++++++++ .../ignite/impl/thin/cache/cache_client_proxy.h | 83 +++ .../include/ignite/thin/cache/cache_client.h | 239 ++++++- .../src/impl/cache/cache_client_impl.cpp | 70 +- .../thin-client/src/impl/cache/cache_client_impl.h | 83 +++ .../src/impl/cache/cache_client_proxy.cpp | 36 ++ .../platforms/cpp/thin-client/src/impl/message.h | 88 ++- 8 files changed, 1294 insertions(+), 47 deletions(-) diff --git a/modules/platforms/cpp/core/include/ignite/cache/cache.h b/modules/platforms/cpp/core/include/ignite/cache/cache.h index c230361..71aae7e 100644 --- a/modules/platforms/cpp/core/include/ignite/cache/cache.h +++ b/modules/platforms/cpp/core/include/ignite/cache/cache.h @@ -531,15 +531,15 @@ namespace ignite } /** - * Atomically replaces the value for a given key if and only if there is - * a value currently mapped by the key. + * Atomically replaces the value for a given key if and only if there is a value currently mapped by + * the key. * * This method should only be used on the valid instance. * * @param key Key with which the specified value is to be associated. * @param val Value to be associated with the specified key. - * @return The previous value associated with the specified key, or - * null if there was no mapping for the key. + * @return The previous value associated with the specified key, or null if there was no mapping for + * the key. */ V GetAndReplace(const K& key, const V& val) { @@ -553,16 +553,16 @@ namespace ignite } /** - * Atomically replaces the value for a given key if and only if there is - * a value currently mapped by the key. + * Atomically replaces the value for a given key if and only if there is a value currently mapped by + * the key. * * This method should only be used on the valid instance. * * @param key Key with which the specified value is to be associated. * @param val Value to be associated with the specified key. * @param err Error. - * @return The previous value associated with the specified key, or - * null if there was no mapping for the key. + * @return The previous value associated with the specified key, or null if there was no mapping for + * the key. */ V GetAndReplace(const K& key, const V& val, IgniteError& err) { @@ -617,8 +617,8 @@ namespace ignite } /** - * Atomically associates the specified key with the given value if it is not - * already associated with a value. + * Atomically associates the specified key with the given value if it is not already associated with + * a value. * * This method should only be used on the valid instance. * @@ -638,8 +638,8 @@ namespace ignite } /** - * Atomically associates the specified key with the given value if it is not - * already associated with a value. + * Atomically associates the specified key with the given value if it is not already associated with + * a value. * * This method should only be used on the valid instance. * @@ -765,8 +765,8 @@ namespace ignite } /** - * Stores given key-value pair in cache only if only if the previous value is equal to the - * old value passed as argument. + * Stores given key-value pair in cache only if the previous value is equal to the old value passed + * as argument. * This method is transactional and will enlist the entry into ongoing transaction if there is one. * * This method should only be used on the valid instance. @@ -788,8 +788,8 @@ namespace ignite } /** - * Stores given key-value pair in cache only if only if the previous value is equal to the - * old value passed as argument. + * Stores given key-value pair in cache only if the previous value is equal to the old value passed + * as argument. * This method is transactional and will enlist the entry into ongoing transaction if there is one. * * This method should only be used on the valid instance. diff --git a/modules/platforms/cpp/thin-client-test/src/cache_client_test.cpp b/modules/platforms/cpp/thin-client-test/src/cache_client_test.cpp index 4031d46..d5c7f5f 100644 --- a/modules/platforms/cpp/thin-client-test/src/cache_client_test.cpp +++ b/modules/platforms/cpp/thin-client-test/src/cache_client_test.cpp @@ -1199,5 +1199,715 @@ BOOST_AUTO_TEST_CASE(CacheClientContainsKeysIterators) BOOST_REQUIRE(cache.ContainsKeys(check.begin(), check.end())); } +BOOST_AUTO_TEST_CASE(CacheClientReplaceIfEqualsBasicKeyValue) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<int32_t, std::string> cache = client.GetCache<int32_t, std::string>("local"); + + int32_t key = 42; + std::string valIn1 = "Lorem ipsum"; + std::string valIn2 = "Test"; + + cache.Put(key, valIn1); + + BOOST_CHECK(!cache.Replace(key, valIn2, valIn2)); + + std::string valOut = cache.Get(key); + + BOOST_CHECK_EQUAL(valOut, valIn1); + + BOOST_CHECK(cache.Replace(key, valIn1, valIn2)); + + cache.Get(key, valOut); + + BOOST_CHECK_EQUAL(valOut, valIn2); +} + +BOOST_AUTO_TEST_CASE(CacheClientReplaceIfEqualsComplexValue) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<int32_t, ignite::ComplexType> cache = client.GetCache<int32_t, ignite::ComplexType>("local"); + + int32_t key = 42; + + ignite::ComplexType valIn1; + valIn1.i32Field = 123; + valIn1.strField = "Test value"; + valIn1.objField.f1 = 42; + valIn1.objField.f2 = "Inner value"; + + ignite::ComplexType valIn2; + valIn2.i32Field = 4234; + valIn2.strField = "Some"; + valIn2.objField.f1 = 654; + valIn2.objField.f2 = "Lorem"; + + cache.Put(key, valIn1); + + BOOST_REQUIRE(!cache.Replace(key, valIn2, valIn2)); + + ignite::ComplexType valOut = cache.Get(key); + + BOOST_CHECK_EQUAL(valIn1.i32Field, valOut.i32Field); + BOOST_CHECK_EQUAL(valIn1.strField, valOut.strField); + BOOST_CHECK_EQUAL(valIn1.objField.f1, valOut.objField.f1); + BOOST_CHECK_EQUAL(valIn1.objField.f2, valOut.objField.f2); + + BOOST_CHECK(cache.Replace(key, valIn1, valIn2)); + + cache.Get(key, valOut); + + BOOST_CHECK_EQUAL(valIn2.i32Field, valOut.i32Field); + BOOST_CHECK_EQUAL(valIn2.strField, valOut.strField); + BOOST_CHECK_EQUAL(valIn2.objField.f1, valOut.objField.f1); + BOOST_CHECK_EQUAL(valIn2.objField.f2, valOut.objField.f2); +} + +BOOST_AUTO_TEST_CASE(CacheClientReplaceIfEqualsComplexKey) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<ignite::ComplexType, int32_t> cache = client.GetCache<ignite::ComplexType, int32_t>("local"); + + ignite::ComplexType key; + + key.i32Field = 123; + key.strField = "Test value"; + key.objField.f1 = 42; + key.objField.f2 = "Inner value"; + + int32_t valIn1 = 123; + int32_t valIn2 = 321; + + cache.Put(key, valIn1); + + BOOST_CHECK(!cache.Replace(key, valIn2, valIn2)); + + int32_t valOut = cache.Get(key); + + BOOST_CHECK_EQUAL(valOut, valIn1); + + BOOST_CHECK(cache.Replace(key, valIn1, valIn2)); + + cache.Get(key, valOut); + + BOOST_CHECK_EQUAL(valOut, valIn2); +} + +BOOST_AUTO_TEST_CASE(CacheClientRemoveIfEqualsBasicKeyValue) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<int32_t, std::string> cache = client.GetCache<int32_t, std::string>("local"); + + int32_t key = 42; + std::string valIn1 = "Lorem ipsum"; + std::string valIn2 = "Test"; + + cache.Put(key, valIn1); + + BOOST_REQUIRE(!cache.Remove(key, valIn2)); + + BOOST_CHECK(cache.ContainsKey(key)); + + std::string valOut = cache.Get(key); + + BOOST_CHECK_EQUAL(valOut, valIn1); + + BOOST_CHECK(cache.Remove(key, valIn1)); + + BOOST_CHECK(!cache.ContainsKey(key)); +} + +BOOST_AUTO_TEST_CASE(CacheClientRemoveIfEqualsComplexValue) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<int32_t, ignite::ComplexType> cache = client.GetCache<int32_t, ignite::ComplexType>("local"); + + int32_t key = 42; + + ignite::ComplexType valIn1; + valIn1.i32Field = 123; + valIn1.strField = "Test value"; + valIn1.objField.f1 = 42; + valIn1.objField.f2 = "Inner value"; + + ignite::ComplexType valIn2; + valIn2.i32Field = 4234; + valIn2.strField = "Some"; + valIn2.objField.f1 = 654; + valIn2.objField.f2 = "Lorem"; + + cache.Put(key, valIn1); + + BOOST_CHECK(!cache.Remove(key, valIn2)); + + BOOST_CHECK(cache.ContainsKey(key)); + + ignite::ComplexType valOut = cache.Get(key); + + BOOST_CHECK_EQUAL(valIn1.i32Field, valOut.i32Field); + BOOST_CHECK_EQUAL(valIn1.strField, valOut.strField); + BOOST_CHECK_EQUAL(valIn1.objField.f1, valOut.objField.f1); + BOOST_CHECK_EQUAL(valIn1.objField.f2, valOut.objField.f2); + + BOOST_CHECK(cache.Remove(key, valIn1)); + + BOOST_CHECK(!cache.ContainsKey(key)); +} + +BOOST_AUTO_TEST_CASE(CacheClientRemoveIfEqualsComplexKey) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<ignite::ComplexType, int32_t> cache = client.GetCache<ignite::ComplexType, int32_t>("local"); + + ignite::ComplexType key; + + key.i32Field = 123; + key.strField = "Test value"; + key.objField.f1 = 42; + key.objField.f2 = "Inner value"; + + int32_t valIn1 = 123; + int32_t valIn2 = 321; + + cache.Put(key, valIn1); + + BOOST_CHECK(!cache.Remove(key, valIn2)); + + BOOST_CHECK(cache.ContainsKey(key)); + + int32_t valOut = cache.Get(key); + + BOOST_CHECK_EQUAL(valOut, valIn1); + + BOOST_CHECK(cache.Remove(key, valIn1)); + + BOOST_CHECK(!cache.ContainsKey(key)); +} + +BOOST_AUTO_TEST_CASE(CacheClientGetAndPutBasicKeyValue) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<int32_t, std::string> cache = client.GetCache<int32_t, std::string>("local"); + + int32_t key = 42; + std::string valIn1 = "Lorem ipsum"; + std::string valIn2 = "Test"; + + cache.Put(key, valIn1); + std::string valOut = cache.GetAndPut(key, valIn2); + + BOOST_CHECK_EQUAL(valOut, valIn1); + + cache.Get(key, valOut); + + BOOST_CHECK_EQUAL(valOut, valIn2); +} + +BOOST_AUTO_TEST_CASE(CacheClientGetAndPutComplexValue) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<int32_t, ignite::ComplexType> cache = client.GetCache<int32_t, ignite::ComplexType>("local"); + + int32_t key = 42; + + ignite::ComplexType valIn1; + valIn1.i32Field = 123; + valIn1.strField = "Test value"; + valIn1.objField.f1 = 42; + valIn1.objField.f2 = "Inner value"; + + ignite::ComplexType valIn2; + valIn2.i32Field = 4234; + valIn2.strField = "Some"; + valIn2.objField.f1 = 654; + valIn2.objField.f2 = "Lorem"; + + ignite::ComplexType valOut; + + cache.Put(key, valIn1); + cache.GetAndPut(key, valIn2, valOut); + + BOOST_CHECK_EQUAL(valIn1.i32Field, valOut.i32Field); + BOOST_CHECK_EQUAL(valIn1.strField, valOut.strField); + BOOST_CHECK_EQUAL(valIn1.objField.f1, valOut.objField.f1); + BOOST_CHECK_EQUAL(valIn1.objField.f2, valOut.objField.f2); + + cache.Get(key, valOut); + + BOOST_CHECK_EQUAL(valIn2.i32Field, valOut.i32Field); + BOOST_CHECK_EQUAL(valIn2.strField, valOut.strField); + BOOST_CHECK_EQUAL(valIn2.objField.f1, valOut.objField.f1); + BOOST_CHECK_EQUAL(valIn2.objField.f2, valOut.objField.f2); +} + +BOOST_AUTO_TEST_CASE(CacheClientGetAndPutComplexKey) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<ignite::ComplexType, int32_t> cache = client.GetCache<ignite::ComplexType, int32_t>("local"); + + ignite::ComplexType key; + + key.i32Field = 123; + key.strField = "Test value"; + key.objField.f1 = 42; + key.objField.f2 = "Inner value"; + + int32_t valIn1 = 123; + int32_t valIn2 = 321; + + cache.Put(key, valIn1); + int32_t valOut = cache.GetAndPut(key, valIn2); + + BOOST_CHECK_EQUAL(valOut, valIn1); + + cache.Get(key, valOut); + + BOOST_CHECK_EQUAL(valOut, valIn2); +} + +BOOST_AUTO_TEST_CASE(CacheClientGetAndRemoveBasicKeyValue) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<int32_t, std::string> cache = client.GetCache<int32_t, std::string>("local"); + + int32_t key = 42; + std::string valIn = "Lorem ipsum"; + + cache.Put(key, valIn); + std::string valOut = cache.GetAndRemove(key); + + BOOST_CHECK_EQUAL(valOut, valIn); + + BOOST_CHECK(!cache.ContainsKey(key)); +} + +BOOST_AUTO_TEST_CASE(CacheClientGetAndRemoveComplexValue) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<int32_t, ignite::ComplexType> cache = client.GetCache<int32_t, ignite::ComplexType>("local"); + + int32_t key = 42; + + ignite::ComplexType valIn; + valIn.i32Field = 123; + valIn.strField = "Test value"; + valIn.objField.f1 = 42; + valIn.objField.f2 = "Inner value"; + + ignite::ComplexType valOut; + + cache.Put(key, valIn); + cache.GetAndRemove(key, valOut); + + BOOST_CHECK_EQUAL(valIn.i32Field, valOut.i32Field); + BOOST_CHECK_EQUAL(valIn.strField, valOut.strField); + BOOST_CHECK_EQUAL(valIn.objField.f1, valOut.objField.f1); + BOOST_CHECK_EQUAL(valIn.objField.f2, valOut.objField.f2); + + BOOST_CHECK(!cache.ContainsKey(key)); +} + +BOOST_AUTO_TEST_CASE(CacheClientGetAndRemoveComplexKey) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<ignite::ComplexType, int32_t> cache = client.GetCache<ignite::ComplexType, int32_t>("local"); + + ignite::ComplexType key; + + key.i32Field = 123; + key.strField = "Test value"; + key.objField.f1 = 42; + key.objField.f2 = "Inner value"; + + int32_t valIn = 123; + + cache.Put(key, valIn); + int32_t valOut = cache.GetAndRemove(key); + + BOOST_CHECK_EQUAL(valOut, valIn); + + BOOST_CHECK(!cache.ContainsKey(key)); +} + +BOOST_AUTO_TEST_CASE(CacheClientGetAndReplaceBasicKeyValue) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<int32_t, std::string> cache = client.GetCache<int32_t, std::string>("local"); + + int32_t key = 42; + std::string valIn1 = "Lorem ipsum"; + std::string valIn2 = "Test"; + + std::string valOut; + cache.GetAndReplace(key, valIn1, valOut); + + BOOST_CHECK(valOut.empty()); + BOOST_CHECK(!cache.ContainsKey(key)); + + cache.Put(key, valIn1); + valOut = cache.GetAndReplace(key, valIn2); + + BOOST_CHECK_EQUAL(valOut, valIn1); + + cache.Get(key, valOut); + + BOOST_CHECK_EQUAL(valOut, valIn2); +} + +BOOST_AUTO_TEST_CASE(CacheClientGetAndReplaceComplexValue) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<int32_t, ignite::ComplexType> cache = client.GetCache<int32_t, ignite::ComplexType>("local"); + + int32_t key = 42; + + ignite::ComplexType valIn1; + valIn1.i32Field = 123; + valIn1.strField = "Test value"; + valIn1.objField.f1 = 42; + valIn1.objField.f2 = "Inner value"; + + ignite::ComplexType valIn2; + valIn2.i32Field = 4234; + valIn2.strField = "Some"; + valIn2.objField.f1 = 654; + valIn2.objField.f2 = "Lorem"; + + ignite::ComplexType valOut = cache.GetAndReplace(key, valIn1); + + BOOST_CHECK(!cache.ContainsKey(key)); + + cache.Put(key, valIn1); + cache.GetAndReplace(key, valIn2, valOut); + + BOOST_CHECK_EQUAL(valIn1.i32Field, valOut.i32Field); + BOOST_CHECK_EQUAL(valIn1.strField, valOut.strField); + BOOST_CHECK_EQUAL(valIn1.objField.f1, valOut.objField.f1); + BOOST_CHECK_EQUAL(valIn1.objField.f2, valOut.objField.f2); + + cache.Get(key, valOut); + + BOOST_CHECK_EQUAL(valIn2.i32Field, valOut.i32Field); + BOOST_CHECK_EQUAL(valIn2.strField, valOut.strField); + BOOST_CHECK_EQUAL(valIn2.objField.f1, valOut.objField.f1); + BOOST_CHECK_EQUAL(valIn2.objField.f2, valOut.objField.f2); +} + +BOOST_AUTO_TEST_CASE(CacheClientGetAndReplaceComplexKey) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<ignite::ComplexType, int32_t> cache = client.GetCache<ignite::ComplexType, int32_t>("local"); + + ignite::ComplexType key; + + key.i32Field = 123; + key.strField = "Test value"; + key.objField.f1 = 42; + key.objField.f2 = "Inner value"; + + int32_t valIn1 = 123; + int32_t valIn2 = 321; + + int32_t valOut; + cache.GetAndReplace(key, valIn1, valOut); + + BOOST_CHECK_EQUAL(valOut, 0); + BOOST_CHECK(!cache.ContainsKey(key)); + + cache.Put(key, valIn1); + valOut = cache.GetAndReplace(key, valIn2); + + BOOST_CHECK_EQUAL(valOut, valIn1); + + cache.Get(key, valOut); + + BOOST_CHECK_EQUAL(valOut, valIn2); +} + +BOOST_AUTO_TEST_CASE(CacheClientPutIfAbsentBasicKeyValue) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<int32_t, std::string> cache = client.GetCache<int32_t, std::string>("local"); + + int32_t key = 42; + std::string valIn1 = "Lorem ipsum"; + std::string valIn2 = "Test"; + + BOOST_CHECK(cache.PutIfAbsent(key, valIn1)); + BOOST_CHECK(cache.ContainsKey(key)); + + std::string valOut = cache.Get(key); + + BOOST_CHECK_EQUAL(valOut, valIn1); + + BOOST_CHECK(!cache.PutIfAbsent(key, valIn2)); + + cache.Get(key, valOut); + + BOOST_CHECK_EQUAL(valOut, valIn1); +} + +BOOST_AUTO_TEST_CASE(CacheClientPutIfAbsentComplexValue) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<int32_t, ignite::ComplexType> cache = client.GetCache<int32_t, ignite::ComplexType>("local"); + + int32_t key = 42; + + ignite::ComplexType valIn1; + valIn1.i32Field = 123; + valIn1.strField = "Test value"; + valIn1.objField.f1 = 42; + valIn1.objField.f2 = "Inner value"; + + ignite::ComplexType valIn2; + valIn2.i32Field = 4234; + valIn2.strField = "Some"; + valIn2.objField.f1 = 654; + valIn2.objField.f2 = "Lorem"; + + BOOST_CHECK(cache.PutIfAbsent(key, valIn1)); + BOOST_CHECK(cache.ContainsKey(key)); + + ignite::ComplexType valOut = cache.Get(key); + + BOOST_CHECK_EQUAL(valIn1.i32Field, valOut.i32Field); + BOOST_CHECK_EQUAL(valIn1.strField, valOut.strField); + BOOST_CHECK_EQUAL(valIn1.objField.f1, valOut.objField.f1); + BOOST_CHECK_EQUAL(valIn1.objField.f2, valOut.objField.f2); + + BOOST_CHECK(!cache.PutIfAbsent(key, valIn2)); + + cache.Get(key, valOut); + + BOOST_CHECK_EQUAL(valIn1.i32Field, valOut.i32Field); + BOOST_CHECK_EQUAL(valIn1.strField, valOut.strField); + BOOST_CHECK_EQUAL(valIn1.objField.f1, valOut.objField.f1); + BOOST_CHECK_EQUAL(valIn1.objField.f2, valOut.objField.f2); +} + +BOOST_AUTO_TEST_CASE(CacheClientPutIfAbsentComplexKey) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<ignite::ComplexType, int32_t> cache = client.GetCache<ignite::ComplexType, int32_t>("local"); + + ignite::ComplexType key; + + key.i32Field = 123; + key.strField = "Test value"; + key.objField.f1 = 42; + key.objField.f2 = "Inner value"; + + int32_t valIn1 = 123; + int32_t valIn2 = 321; + + BOOST_CHECK(cache.PutIfAbsent(key, valIn1)); + BOOST_CHECK(cache.ContainsKey(key)); + + int32_t valOut = cache.Get(key); + + BOOST_CHECK_EQUAL(valOut, valIn1); + + BOOST_CHECK(!cache.PutIfAbsent(key, valIn2)); + + cache.Get(key, valOut); + + BOOST_CHECK_EQUAL(valOut, valIn1); +} + +BOOST_AUTO_TEST_CASE(CacheClientGetAndPutIfAbsentBasicKeyValue) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<int32_t, std::string> cache = client.GetCache<int32_t, std::string>("local"); + + int32_t key = 42; + std::string valIn1 = "Lorem ipsum"; + std::string valIn2 = "Test"; + + std::string valOut = cache.GetAndPutIfAbsent(key, valIn1); + + BOOST_CHECK(valOut.empty()); + BOOST_CHECK(cache.ContainsKey(key)); + + cache.GetAndPutIfAbsent(key, valIn2, valOut); + + BOOST_CHECK_EQUAL(valOut, valIn1); + + cache.Get(key, valOut); + + BOOST_CHECK_EQUAL(valOut, valIn1); +} + +BOOST_AUTO_TEST_CASE(CacheClientGetAndPutIfAbsentComplexValue) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<int32_t, ignite::ComplexType> cache = client.GetCache<int32_t, ignite::ComplexType>("local"); + + int32_t key = 42; + + ignite::ComplexType valIn1; + valIn1.i32Field = 123; + valIn1.strField = "Test value"; + valIn1.objField.f1 = 42; + valIn1.objField.f2 = "Inner value"; + + ignite::ComplexType valIn2; + valIn2.i32Field = 4234; + valIn2.strField = "Some"; + valIn2.objField.f1 = 654; + valIn2.objField.f2 = "Lorem"; + + ignite::ComplexType valOut = cache.GetAndPutIfAbsent(key, valIn1); + + BOOST_CHECK(cache.ContainsKey(key)); + + cache.GetAndPutIfAbsent(key, valIn2, valOut); + + BOOST_CHECK_EQUAL(valIn1.i32Field, valOut.i32Field); + BOOST_CHECK_EQUAL(valIn1.strField, valOut.strField); + BOOST_CHECK_EQUAL(valIn1.objField.f1, valOut.objField.f1); + BOOST_CHECK_EQUAL(valIn1.objField.f2, valOut.objField.f2); + + cache.Get(key, valOut); + + BOOST_CHECK_EQUAL(valIn1.i32Field, valOut.i32Field); + BOOST_CHECK_EQUAL(valIn1.strField, valOut.strField); + BOOST_CHECK_EQUAL(valIn1.objField.f1, valOut.objField.f1); + BOOST_CHECK_EQUAL(valIn1.objField.f2, valOut.objField.f2); +} + +BOOST_AUTO_TEST_CASE(CacheClientGetAndPutIfAbsentComplexKey) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<ignite::ComplexType, int32_t> cache = client.GetCache<ignite::ComplexType, int32_t>("local"); + + ignite::ComplexType key; + + key.i32Field = 123; + key.strField = "Test value"; + key.objField.f1 = 42; + key.objField.f2 = "Inner value"; + + int32_t valIn1 = 123; + int32_t valIn2 = 321; + + int32_t valOut = cache.GetAndPutIfAbsent(key, valIn1); + + BOOST_CHECK_EQUAL(valOut, 0); + BOOST_CHECK(cache.ContainsKey(key)); + + cache.GetAndPutIfAbsent(key, valIn2, valOut); + + BOOST_CHECK_EQUAL(valOut, valIn1); + + cache.Get(key, valOut); + + BOOST_CHECK_EQUAL(valOut, valIn1); +} BOOST_AUTO_TEST_SUITE_END() diff --git a/modules/platforms/cpp/thin-client/include/ignite/impl/thin/cache/cache_client_proxy.h b/modules/platforms/cpp/thin-client/include/ignite/impl/thin/cache/cache_client_proxy.h index cda2fae..10f19c0 100644 --- a/modules/platforms/cpp/thin-client/include/ignite/impl/thin/cache/cache_client_proxy.h +++ b/modules/platforms/cpp/thin-client/include/ignite/impl/thin/cache/cache_client_proxy.h @@ -173,6 +173,16 @@ namespace ignite bool Remove(const WritableKey& key); /** + * Removes given key mapping from cache if one exists and value is equal to the passed in value. + * If write-through is enabled, the value will be removed from store. + * + * @param key Key whose mapping is to be removed from cache. + * @param val Value to match against currently cached value. + * @return True if entry was removed, false otherwise. + */ + bool Remove(const WritableKey& key, const Writable& val); + + /** * Removes given key mappings from cache. * If write-through is enabled, the value will be removed from store. * @@ -208,6 +218,79 @@ namespace ignite void ClearAll(const Writable& keys); /** + * Stores given key-value pair in cache only if the previous value is equal to the old value passed + * as argument. + * + * @param key Key to store in cache. + * @param oldVal Old value to match. + * @param newVal Value to be associated with the given key. + * @return True if replace happened, false otherwise. + */ + bool Replace(const WritableKey& key, const Writable& oldVal, const Writable& newVal); + + /** + * Associates the specified value with the specified key in this cache, returning an existing value + * if one existed. + * + * @param key Key with which the specified value is to be associated. + * @param valIn Value to be associated with the specified key. + * @param valOut The value associated with the key at the start of the operation or null if none + * was associated. + */ + void GetAndPut(const WritableKey& key, const Writable& valIn, Readable& valOut); + + /** + * Atomically removes the entry for a key only if currently mapped to some value. + * + * @param key Key with which the specified value is to be associated. + * @param valOut The value associated with the key at the start of the operation or null if none + * was associated. + */ + void GetAndRemove(const WritableKey& key, Readable& valOut); + + /** + * Atomically replaces the value for a given key if and only if there is a value currently mapped by + * the key. + * + * @param key Key with which the specified value is to be associated. + * @param valIn Value to be associated with the specified key. + * @param valOut The value associated with the key at the start of the operation or null if none was + * associated. + */ + void GetAndReplace(const WritableKey& key, const Writable& valIn, Readable& valOut); + + /** + * Atomically associates the specified key with the given value if it is not already associated with + * a value. + * + * @param key Key with which the specified value is to be associated. + * @param val Value to be associated with the specified key. + * @return True if a value was set. + */ + bool PutIfAbsent(const WritableKey& key, const Writable& val); + + /** + * Stores given key-value pair in cache only if cache had no previous mapping for it. + * + * If cache previously contained value for the given key, then this value is returned. + * + * In case of PARTITIONED or REPLICATED caches, the value will be loaded from the primary node, + * which in its turn may load the value from the swap storage, and consecutively, if it's not in + * swap, from the underlying persistent storage. + * + * If the returned value is not needed, method putxIfAbsent() should be used instead of this one to + * avoid the overhead associated with returning of the previous value. + * + * If write-through is enabled, the stored value will be persisted to store. + * + * @param key Key to store in cache. + * @param valIn Value to be associated with the given key. + * @param valOut Previously contained value regardless of whether put happened or not (null if there + * was no previous value). + */ + void GetAndPutIfAbsent(const WritableKey& key, const Writable& valIn, Readable& valOut); + + /** * Get from CacheClient. * Use for testing purposes only. */ diff --git a/modules/platforms/cpp/thin-client/include/ignite/thin/cache/cache_client.h b/modules/platforms/cpp/thin-client/include/ignite/thin/cache/cache_client.h index 1fcf4f5..2ae6972 100644 --- a/modules/platforms/cpp/thin-client/include/ignite/thin/cache/cache_client.h +++ b/modules/platforms/cpp/thin-client/include/ignite/thin/cache/cache_client.h @@ -163,9 +163,9 @@ namespace ignite /** * Retrieves values mapped to the specified keys from cache. - * If some value is not present in cache, then it will be looked up from swap storage. If - * it's not present in swap, or if swap is disabled, and if read-through is allowed, value - * will be loaded from persistent store. + * If some value is not present in cache, then it will be looked up from swap storage. If it's not + * present in swap, or if swap is disabled, and if read-through is allowed, value will be loaded from + * persistent store. * * @param begin Iterator pointing to the beginning of the key sequence. * @param end Iterator pointing to the end of the key sequence. @@ -182,9 +182,9 @@ namespace ignite /** * Retrieves values mapped to the specified keys from cache. - * If some value is not present in cache, then it will be looked up from swap storage. If - * it's not present in swap, or if swap is disabled, and if read-through is allowed, value - * will be loaded from persistent store. + * If some value is not present in cache, then it will be looked up from swap storage. If it's not + * present in swap, or if swap is disabled, and if read-through is allowed, value will be loaded from + * persistent store. * * @param keys Keys. * @param res Map of key-value pairs. @@ -198,9 +198,9 @@ namespace ignite /** * Stores given key-value pair in cache only if there is a previous mapping for it. * If cache previously contained value for the given key, then this value is returned. - * In case of PARTITIONED or REPLICATED caches, the value will be loaded from the primary node, - * which in its turn may load the value from the swap storage, and consecutively, if it's not - * in swap, rom the underlying persistent storage. + * In case of PARTITIONED or REPLICATED caches, the value will be loaded from the primary node, which in + * its turn may load the value from the swap storage, and consecutively, if it's not in swap, rom the + * underlying persistent storage. * If write-through is enabled, the stored value will be persisted to store. * * @param key Key to store in cache. @@ -216,6 +216,24 @@ namespace ignite } /** + * Stores given key-value pair in cache only if the previous value is equal to the old value passed + * as argument. + * + * @param key Key to store in cache. + * @param oldVal Old value to match. + * @param newVal Value to be associated with the given key. + * @return True if replace happened, false otherwise. + */ + bool Replace(const KeyType& key, const ValueType& oldVal, const ValueType& newVal) + { + impl::thin::WritableKeyImpl<KeyType> wrKey(key); + impl::thin::WritableImpl<ValueType> wrOldVal(oldVal); + impl::thin::WritableImpl<ValueType> wrNewVal(newVal); + + return proxy.Replace(wrKey, wrOldVal, wrNewVal); + } + + /** * Check if the cache contains a value for the specified key. * * @param key Key whose presence in this cache is to be tested. @@ -270,12 +288,12 @@ namespace ignite } /** - * Removes given key mapping from cache. If cache previously contained value for the given key, - * then this value is returned. In case of PARTITIONED or REPLICATED caches, the value will be - * loaded from the primary node, which in its turn may load the value from the disk-based swap - * storage, and consecutively, if it's not in swap, from the underlying persistent storage. - * If the returned value is not needed, method removex() should always be used instead of this - * one to avoid the overhead associated with returning of the previous value. + * Removes given key mapping from cache. If cache previously contained value for the given key, then + * this value is returned. In case of PARTITIONED or REPLICATED caches, the value will be loaded from + * the primary node, which in its turn may load the value from the disk-based swap storage, and + * consecutively, if it's not in swap, from the underlying persistent storage. + * If the returned value is not needed, method removex() should always be used instead of this one + * to avoid the overhead associated with returning of the previous value. * If write-through is enabled, the value will be removed from store. * * @param key Key whose mapping is to be removed from cache. @@ -289,6 +307,22 @@ namespace ignite } /** + * Removes given key mapping from cache if one exists and value is equal to the passed in value. + * If write-through is enabled, the value will be removed from store. + * + * @param key Key whose mapping is to be removed from cache. + * @param val Value to match against currently cached value. + * @return True if entry was removed, false otherwise. + */ + bool Remove(const KeyType& key, const ValueType& val) + { + impl::thin::WritableKeyImpl<KeyType> wrKey(key); + impl::thin::WritableImpl<ValueType> wrVal(val); + + return proxy.Remove(wrKey, wrVal); + } + + /** * Removes given key mappings from cache. * If write-through is enabled, the value will be removed from store. * @@ -374,6 +408,181 @@ namespace ignite } /** + * Associates the specified value with the specified key in this cache, returning an existing value if + * one existed. + * + * @param key Key with which the specified value is to be associated. + * @param valIn Value to be associated with the specified key. + * @param valOut The value associated with the key at the start of the operation or null if none was + * associated. + */ + void GetAndPut(const KeyType& key, const ValueType& valIn, ValueType& valOut) + { + impl::thin::WritableKeyImpl<KeyType> wrKey(key); + impl::thin::WritableImpl<ValueType> wrValIn(valIn); + impl::thin::ReadableImpl<ValueType> rdValOut(valOut); + + proxy.GetAndPut(wrKey, wrValIn, rdValOut); + } + + /** + * Associates the specified value with the specified key in this cache, returning an existing value if + * one existed. + * + * @param key Key with which the specified value is to be associated. + * @param valIn Value to be associated with the specified key. + * @return The value associated with the key at the start of the operation or null if none was + * associated. + */ + ValueType GetAndPut(const KeyType& key, const ValueType& valIn) + { + ValueType valOut; + + GetAndPut(key, valIn, valOut); + + return valOut; + } + + /** + * Atomically removes the entry for a key only if currently mapped to some value. + * + * @param key Key with which the specified value is to be associated. + * @param valOut The value associated with the key at the start of the operation or null if none was + * associated. + */ + void GetAndRemove(const KeyType& key, ValueType& valOut) + { + impl::thin::WritableKeyImpl<KeyType> wrKey(key); + impl::thin::ReadableImpl<ValueType> rdValOut(valOut); + + proxy.GetAndRemove(wrKey, rdValOut); + } + + /** + * Atomically removes the entry for a key only if currently mapped to some value. + * + * @param key Key with which the specified value is to be associated. + * @return The value associated with the key at the start of the operation or null if none was + * associated. + */ + ValueType GetAndRemove(const KeyType& key) + { + ValueType valOut; + + GetAndRemove(key, valOut); + + return valOut; + } + + /** + * Atomically replaces the value for a given key if and only if there is a value currently mapped by + * the key. + * + * @param key Key with which the specified value is to be associated. + * @param valIn Value to be associated with the specified key. + * @param valOut The value associated with the key at the start of the operation or null if none was + * associated. + */ + void GetAndReplace(const KeyType& key, const ValueType& valIn, ValueType& valOut) + { + impl::thin::WritableKeyImpl<KeyType> wrKey(key); + impl::thin::WritableImpl<ValueType> wrValIn(valIn); + impl::thin::ReadableImpl<ValueType> rdValOut(valOut); + + proxy.GetAndReplace(wrKey, wrValIn, rdValOut); + } + + /** + * Atomically replaces the value for a given key if and only if there is a value currently mapped by + * the key. + * + * @param key Key with which the specified value is to be associated. + * @param valIn Value to be associated with the specified key. + * @return The value associated with the key at the start of the operation or null if none was + * associated. + */ + ValueType GetAndReplace(const KeyType& key, const ValueType& valIn) + { + ValueType valOut; + + GetAndReplace(key, valIn, valOut); + + return valOut; + } + + /** + * Atomically associates the specified key with the given value if it is not already associated with + * a value. + * + * @param key Key with which the specified value is to be associated. + * @param val Value to be associated with the specified key. + * @return True if a value was set. + */ + bool PutIfAbsent(const KeyType& key, const ValueType& val) + { + impl::thin::WritableKeyImpl<KeyType> wrKey(key); + impl::thin::WritableImpl<ValueType> wrValIn(val); + + return proxy.PutIfAbsent(wrKey, wrValIn); + } + + /** + * Stores given key-value pair in cache only if cache had no previous mapping for it. + * + * If cache previously contained value for the given key, then this value is returned. + * + * In case of PARTITIONED or REPLICATED caches, the value will be loaded from the primary node, which in + * its turn may load the value from the swap storage, and consecutively, if it's not in swap, from + * the underlying persistent storage. + * + * If the returned value is not needed, method putxIfAbsent() should be used instead of this one to + * avoid the overhead associated with returning of the previous value. + * + * If write-through is enabled, the stored value will be persisted to store. + * + * @param key Key to store in cache. + * @param valIn Value to be associated with the given key. + * @param valOut Previously contained value regardless of whether put happened or not (null if there was + * no previous value). + */ + void GetAndPutIfAbsent(const KeyType& key, const ValueType& valIn, ValueType& valOut) + { + impl::thin::WritableKeyImpl<KeyType> wrKey(key); + impl::thin::WritableImpl<ValueType> wrValIn(valIn); + impl::thin::ReadableImpl<ValueType> rdValOut(valOut); + + proxy.GetAndPutIfAbsent(wrKey, wrValIn, rdValOut); + } + + /** + * Stores given key-value pair in cache only if cache had no previous mapping for it. + * + * If cache previously contained value for the given key, then this value is returned. + * + * In case of PARTITIONED or REPLICATED caches, the value will be loaded from the primary node, which in + * its turn may load the value from the swap storage, and consecutively, if it's not in swap, from + * the underlying persistent storage. + * + * If the returned value is not needed, method putxIfAbsent() should be used instead of this one to + * avoid the overhead associated with returning of the previous value. + * + * If write-through is enabled, the stored value will be persisted to store. + * + * @param key Key to store in cache. + * @param valIn Value to be associated with the given key. + * @return Previously contained value regardless of whether put happened or not (null if there was no + * previous value). + */ + ValueType GetAndPutIfAbsent(const KeyType& key, const ValueType& valIn) + { + ValueType valOut; + + GetAndPutIfAbsent(key, valIn, valOut); + + return valOut; + } + + /** * Refresh affinity mapping. * * Retrieves affinity mapping information from remote server. This information uses to send data diff --git a/modules/platforms/cpp/thin-client/src/impl/cache/cache_client_impl.cpp b/modules/platforms/cpp/thin-client/src/impl/cache/cache_client_impl.cpp index 78d0e13..b0f3827 100644 --- a/modules/platforms/cpp/thin-client/src/impl/cache/cache_client_impl.cpp +++ b/modules/platforms/cpp/thin-client/src/impl/cache/cache_client_impl.cpp @@ -77,7 +77,7 @@ namespace ignite void CacheClientImpl::Put(const WritableKey& key, const Writable& value) { - CacheKeyValueRequest<RequestType::CACHE_PUT> req(id, binary, key, value); + Cache2ValueRequest<RequestType::CACHE_PUT> req(id, binary, key, value); Response rsp; SyncCacheKeyMessage(key, req, rsp); @@ -109,7 +109,7 @@ namespace ignite bool CacheClientImpl::Replace(const WritableKey& key, const Writable& value) { - CacheKeyValueRequest<RequestType::CACHE_REPLACE> req(id, binary, key, value); + Cache2ValueRequest<RequestType::CACHE_REPLACE> req(id, binary, key, value); BoolResponse rsp; SyncCacheKeyMessage(key, req, rsp); @@ -152,7 +152,17 @@ namespace ignite CacheValueRequest<RequestType::CACHE_REMOVE_KEY> req(id, binary, key); BoolResponse rsp; - SyncMessage(req, rsp); + SyncCacheKeyMessage(key, req, rsp); + + return rsp.GetValue(); + } + + bool CacheClientImpl::Remove(const WritableKey& key, const Writable& val) + { + Cache2ValueRequest<RequestType::CACHE_REMOVE_IF_EQUALS> req(id, binary, key, val); + BoolResponse rsp; + + SyncCacheKeyMessage(key, req, rsp); return rsp.GetValue(); } @@ -178,7 +188,7 @@ namespace ignite CacheValueRequest<RequestType::CACHE_CLEAR_KEY> req(id, binary, key); Response rsp; - SyncMessage(req, rsp); + SyncCacheKeyMessage(key, req, rsp); } void CacheClientImpl::Clear() @@ -205,6 +215,58 @@ namespace ignite SyncCacheKeyMessage(key, req, rsp); } + bool CacheClientImpl::Replace(const WritableKey& key, const Writable& oldVal, const Writable& newVal) + { + Cache3ValueRequest<RequestType::CACHE_REPLACE_IF_EQUALS> req(id, binary, key, oldVal, newVal); + BoolResponse rsp; + + SyncCacheKeyMessage(key, req, rsp); + + return rsp.GetValue(); + } + + void CacheClientImpl::GetAndPut(const WritableKey& key, const Writable& valIn, Readable& valOut) + { + Cache2ValueRequest<RequestType::CACHE_GET_AND_PUT> req(id, binary, key, valIn); + CacheValueResponse rsp(valOut); + + SyncCacheKeyMessage(key, req, rsp); + } + + void CacheClientImpl::GetAndRemove(const WritableKey& key, Readable& valOut) + { + CacheValueRequest<RequestType::CACHE_GET_AND_REMOVE> req(id, binary, key); + CacheValueResponse rsp(valOut); + + SyncCacheKeyMessage(key, req, rsp); + } + + void CacheClientImpl::GetAndReplace(const WritableKey& key, const Writable& valIn, Readable& valOut) + { + Cache2ValueRequest<RequestType::CACHE_GET_AND_REPLACE> req(id, binary, key, valIn); + CacheValueResponse rsp(valOut); + + SyncCacheKeyMessage(key, req, rsp); + } + + bool CacheClientImpl::PutIfAbsent(const WritableKey& key, const Writable& val) + { + Cache2ValueRequest<RequestType::CACHE_PUT_IF_ABSENT> req(id, binary, key, val); + BoolResponse rsp; + + SyncCacheKeyMessage(key, req, rsp); + + return rsp.GetValue(); + } + + void CacheClientImpl::GetAndPutIfAbsent(const WritableKey& key, const Writable& valIn, Readable& valOut) + { + Cache2ValueRequest<RequestType::CACHE_GET_AND_PUT_IF_ABSENT> req(id, binary, key, valIn); + CacheValueResponse rsp(valOut); + + SyncCacheKeyMessage(key, req, rsp); + } + void CacheClientImpl::RefreshAffinityMapping() { router.Get()->RefreshAffinityMapping(id, binary); diff --git a/modules/platforms/cpp/thin-client/src/impl/cache/cache_client_impl.h b/modules/platforms/cpp/thin-client/src/impl/cache/cache_client_impl.h index f9555a2..eeb0113 100644 --- a/modules/platforms/cpp/thin-client/src/impl/cache/cache_client_impl.h +++ b/modules/platforms/cpp/thin-client/src/impl/cache/cache_client_impl.h @@ -156,6 +156,16 @@ namespace ignite bool Remove(const WritableKey& key); /** + * Removes given key mapping from cache if one exists and value is equal to the passed in value. + * If write-through is enabled, the value will be removed from store. + * + * @param key Key whose mapping is to be removed from cache. + * @param val Value to match against currently cached value. + * @return True if entry was removed, false otherwise. + */ + bool Remove(const WritableKey& key, const Writable& val); + + /** * Removes given key mappings from cache. * If write-through is enabled, the value will be removed from store. * @@ -203,6 +213,79 @@ namespace ignite void LocalPeek(const WritableKey& key, Readable& value); /** + * Stores given key-value pair in cache only if the previous value is equal to the old value passed + * as argument. + * + * @param key Key to store in cache. + * @param oldVal Old value to match. + * @param newVal Value to be associated with the given key. + * @return True if replace happened, false otherwise. + */ + bool Replace(const WritableKey& key, const Writable& oldVal, const Writable& newVal); + + /** + * Associates the specified value with the specified key in this cache, returning an existing value + * if one existed. + * + * @param key Key with which the specified value is to be associated. + * @param valIn Value to be associated with the specified key. + * @param valOut The value associated with the key at the start of the operation or null if none + * was associated. + */ + void GetAndPut(const WritableKey& key, const Writable& valIn, Readable& valOut); + + /** + * Atomically removes the entry for a key only if currently mapped to some value. + * + * @param key Key with which the specified value is to be associated. + * @param valOut The value associated with the key at the start of the operation or null if none + * was associated. + */ + void GetAndRemove(const WritableKey& key, Readable& valOut); + + /** + * Atomically replaces the value for a given key if and only if there is a value currently mapped by + * the key. + * + * @param key Key with which the specified value is to be associated. + * @param valIn Value to be associated with the specified key. + * @param valOut The value associated with the key at the start of the operation or null if none was + * associated. + */ + void GetAndReplace(const WritableKey& key, const Writable& valIn, Readable& valOut); + + /** + * Atomically associates the specified key with the given value if it is not already associated with + * a value. + * + * @param key Key with which the specified value is to be associated. + * @param val Value to be associated with the specified key. + * @return True if a value was set. + */ + bool PutIfAbsent(const WritableKey& key, const Writable& val); + + /** + * Stores given key-value pair in cache only if cache had no previous mapping for it. + * + * If cache previously contained value for the given key, then this value is returned. + * + * In case of PARTITIONED or REPLICATED caches, the value will be loaded from the primary node, + * which in its turn may load the value from the swap storage, and consecutively, if it's not in + * swap, from the underlying persistent storage. + * + * If the returned value is not needed, method putxIfAbsent() should be used instead of this one to + * avoid the overhead associated with returning of the previous value. + * + * If write-through is enabled, the stored value will be persisted to store. + * + * @param key Key to store in cache. + * @param valIn Value to be associated with the given key. + * @param valOut Previously contained value regardless of whether put happened or not (null if there + * was no previous value). + */ + void GetAndPutIfAbsent(const WritableKey& key, const Writable& valIn, Readable& valOut); + + /** * Update cache partitions info. */ void RefreshAffinityMapping(); diff --git a/modules/platforms/cpp/thin-client/src/impl/cache/cache_client_proxy.cpp b/modules/platforms/cpp/thin-client/src/impl/cache/cache_client_proxy.cpp index 3d37255..266d8d4 100644 --- a/modules/platforms/cpp/thin-client/src/impl/cache/cache_client_proxy.cpp +++ b/modules/platforms/cpp/thin-client/src/impl/cache/cache_client_proxy.cpp @@ -101,6 +101,11 @@ namespace ignite return GetCacheImpl(impl).Remove(key); } + bool CacheClientProxy::Remove(const WritableKey& key, const Writable& val) + { + return GetCacheImpl(impl).Remove(key, val); + } + void CacheClientProxy::RemoveAll(const Writable & keys) { return GetCacheImpl(impl).RemoveAll(keys); @@ -125,6 +130,37 @@ namespace ignite { GetCacheImpl(impl).ClearAll(keys); } + + bool CacheClientProxy::Replace(const WritableKey& key, const Writable& oldVal, const Writable& newVal) + { + return GetCacheImpl(impl).Replace(key, oldVal, newVal); + } + + void CacheClientProxy::GetAndPut(const WritableKey& key, const Writable& valIn, Readable& valOut) + { + GetCacheImpl(impl).GetAndPut(key, valIn, valOut); + } + + void CacheClientProxy::GetAndRemove(const WritableKey& key, Readable& valOut) + { + GetCacheImpl(impl).GetAndRemove(key, valOut); + } + + void CacheClientProxy::GetAndReplace(const WritableKey& key, const Writable& valIn, Readable& valOut) + { + GetCacheImpl(impl).GetAndReplace(key, valIn, valOut); + } + + bool CacheClientProxy::PutIfAbsent(const WritableKey& key, const Writable& val) + { + return GetCacheImpl(impl).PutIfAbsent(key, val); + } + + void CacheClientProxy::GetAndPutIfAbsent(const WritableKey& key, const Writable& valIn, + Readable& valOut) + { + GetCacheImpl(impl).GetAndPutIfAbsent(key, valIn, valOut); + } } } } diff --git a/modules/platforms/cpp/thin-client/src/impl/message.h b/modules/platforms/cpp/thin-client/src/impl/message.h index 2d0df6f..1835991 100644 --- a/modules/platforms/cpp/thin-client/src/impl/message.h +++ b/modules/platforms/cpp/thin-client/src/impl/message.h @@ -423,10 +423,10 @@ namespace ignite }; /** - * Cache key value request. + * Cache 2 value request. */ template<int32_t OpCode> - class CacheKeyValueRequest : public CacheValueRequest<OpCode> + class Cache2ValueRequest : public CacheRequest<OpCode> { public: /** @@ -434,12 +434,13 @@ namespace ignite * * @param cacheId Cache ID. * @param binary Binary cache flag. - * @param key Key. - * @param value Value. + * @param val1 Value 1. + * @param val2 Value 2. */ - CacheKeyValueRequest(int32_t cacheId, bool binary, const Writable& key, const Writable& value) : - CacheValueRequest<OpCode>(cacheId, binary, key), - value(value) + Cache2ValueRequest(int32_t cacheId, bool binary, const Writable& val1, const Writable& val2) : + CacheRequest<OpCode>(cacheId, binary), + val1(val1), + val2(val2) { // No-op. } @@ -447,7 +448,7 @@ namespace ignite /** * Destructor. */ - virtual ~CacheKeyValueRequest() + virtual ~Cache2ValueRequest() { // No-op. } @@ -459,14 +460,77 @@ namespace ignite */ virtual void Write(binary::BinaryWriterImpl& writer, const ProtocolVersion& ver) const { - CacheValueRequest<OpCode>::Write(writer, ver); + CacheRequest<OpCode>::Write(writer, ver); - value.Write(writer); + val1.Write(writer); + val2.Write(writer); } private: - /** Value. */ - const Writable& value; + /** Value 1. */ + const Writable& val1; + + /** Value 2. */ + const Writable& val2; + }; + + /** + * Cache 3 value request. + */ + template<int32_t OpCode> + class Cache3ValueRequest : public CacheRequest<OpCode> + { + public: + /** + * Constructor. + * + * @param cacheId Cache ID. + * @param binary Binary cache flag. + * @param val1 Value 1. + * @param val2 Value 2. + * @param val3 Value 3. + */ + Cache3ValueRequest(int32_t cacheId, bool binary, const Writable& val1, const Writable& val2, + const Writable& val3) : + CacheRequest<OpCode>(cacheId, binary), + val1(val1), + val2(val2), + val3(val3) + { + // No-op. + } + + /** + * Destructor. + */ + virtual ~Cache3ValueRequest() + { + // No-op. + } + + /** + * Write request using provided writer. + * @param writer Writer. + * @param ver Version. + */ + virtual void Write(binary::BinaryWriterImpl& writer, const ProtocolVersion& ver) const + { + CacheRequest<OpCode>::Write(writer, ver); + + val1.Write(writer); + val2.Write(writer); + val3.Write(writer); + } + + private: + /** Value 1. */ + const Writable& val1; + + /** Value 2. */ + const Writable& val2; + + /** Value 3. */ + const Writable& val3; }; /**