You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by is...@apache.org on 2019/01/17 16:34:12 UTC
[ignite] branch master updated: IGNITE-9904: Atomic Cache
operations for C++ thin
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 <is...@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;
};
/**