http://git-wip-us.apache.org/repos/asf/ignite/blob/ed658597/modules/platforms/cpp/thin-client-test/src/cache_client_test.cpp ---------------------------------------------------------------------- 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 new file mode 100644 index 0000000..5594134 --- /dev/null +++ b/modules/platforms/cpp/thin-client-test/src/cache_client_test.cpp @@ -0,0 +1,743 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _MSC_VER +# define BOOST_TEST_DYN_LINK +#endif + +#include <boost/test/unit_test.hpp> +#include <boost/thread/thread.hpp> + +#include <ignite/ignition.h> + +#include <ignite/thin/ignite_client_configuration.h> +#include <ignite/thin/ignite_client.h> + +#include <ignite/thin/cache/cache_peek_mode.h> + +#include <ignite/complex_type.h> +#include <test_utils.h> + +using namespace ignite::thin; +using namespace boost::unit_test; + +class CacheClientTestSuiteFixture +{ +public: + static ignite::Ignite StartNode(const char* name) + { + return ignite_test::StartCrossPlatformServerNode("cache.xml", name); + } + + CacheClientTestSuiteFixture() + { + serverNode = StartNode("ServerNode"); + } + + ~CacheClientTestSuiteFixture() + { + ignite::Ignition::StopAll(false); + } + + template<typename K, typename V> + void LocalPeek(cache::CacheClient<K,V>& cache, const K& key, V& value) + { + using namespace ignite::impl::thin; + using namespace ignite::impl::thin::cache; + + CacheClientProxy& proxy = CacheClientProxy::GetFromCacheClient(cache); + + WritableKeyImpl<K> wkey(key); + ReadableImpl<V> rvalue(value); + + proxy.LocalPeek(wkey, rvalue); + } + + template<typename KeyType> + void NumPartitionTest(int64_t num) + { + StartNode("node1"); + + boost::this_thread::sleep_for(boost::chrono::seconds(2)); + + IgniteClientConfiguration cfg; + cfg.SetEndPoints("127.0.0.1:11110..11120"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<KeyType, int64_t> cache = + client.GetCache<KeyType, int64_t>("partitioned"); + + cache.RefreshAffinityMapping(); + + for (int64_t i = 1; i < num; ++i) + cache.Put(static_cast<KeyType>(i * 39916801), i * 5039); + + for (int64_t i = 1; i < num; ++i) + { + int64_t val; + LocalPeek(cache, static_cast<KeyType>(i * 39916801), val); + + BOOST_CHECK_EQUAL(val, i * 5039); + } + } + + void SizeTest(int32_t peekMode) + { + IgniteClientConfiguration cfg; + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<int32_t, int32_t> cache = + client.GetCache<int32_t, int32_t>("partitioned"); + + for (int32_t i = 0; i < 1000; ++i) + cache.Put(i, i * 5039); + + int64_t size = cache.GetSize(peekMode); + BOOST_CHECK_EQUAL(size, 1000); + } + +private: + /** Server node. */ + ignite::Ignite serverNode; +}; + +BOOST_FIXTURE_TEST_SUITE(CacheClientTestSuite, CacheClientTestSuiteFixture) + +BOOST_AUTO_TEST_CASE(CacheClientGetCacheExisting) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + client.GetCache<int32_t, std::string>("local"); +} + +BOOST_AUTO_TEST_CASE(CacheClientGetCacheNonxisting) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + BOOST_REQUIRE_THROW((client.GetCache<int32_t, std::string>("unknown")), ignite::IgniteError); +} + +BOOST_AUTO_TEST_CASE(CacheClientGetOrCreateCacheExisting) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + client.GetOrCreateCache<std::string, int32_t>("local"); +} + +BOOST_AUTO_TEST_CASE(CacheClientGetOrCreateCacheNonexisting) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + client.GetOrCreateCache<std::string, int32_t>("unknown"); +} + +BOOST_AUTO_TEST_CASE(CacheClientCreateCacheExisting) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + BOOST_REQUIRE_THROW((client.CreateCache<std::string, int32_t>("local")), ignite::IgniteError); +} + +BOOST_AUTO_TEST_CASE(CacheClientCreateCacheNonexisting) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + client.CreateCache<std::string, int32_t>("unknown"); +} + +BOOST_AUTO_TEST_CASE(CacheClientDestroyCacheExisting) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + client.DestroyCache("local"); +} + +BOOST_AUTO_TEST_CASE(CacheClientDestroyCacheNonexisting) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + BOOST_REQUIRE_THROW(client.DestroyCache("unknown"), ignite::IgniteError); +} + +BOOST_AUTO_TEST_CASE(CacheClientGetCacheNames) +{ + std::set<std::string> expectedNames; + + expectedNames.insert("local_atomic"); + expectedNames.insert("partitioned_atomic_near"); + expectedNames.insert("partitioned_near"); + expectedNames.insert("partitioned2"); + expectedNames.insert("partitioned"); + expectedNames.insert("replicated"); + expectedNames.insert("replicated_atomic"); + expectedNames.insert("local"); + expectedNames.insert("partitioned_atomic"); + + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + std::vector<std::string> caches; + + client.GetCacheNames(caches); + + BOOST_CHECK_EQUAL(expectedNames.size(), caches.size()); + + for (std::vector<std::string>::const_iterator it = caches.begin(); it != caches.end(); ++it) + { + BOOST_CHECK_EQUAL(expectedNames.count(*it), 1); + } +} + +BOOST_AUTO_TEST_CASE(CacheClientPutGetBasicKeyValue) +{ + 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.Get(key); + + BOOST_CHECK_EQUAL(valOut, valIn); +} + +BOOST_AUTO_TEST_CASE(CacheClientPutGetComplexValue) +{ + 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"); + + ignite::ComplexType valIn; + + int32_t key = 42; + + valIn.i32Field = 123; + valIn.strField = "Test value"; + valIn.objField.f1 = 42; + valIn.objField.f2 = "Inner value"; + + cache.Put(key, valIn); + + ignite::ComplexType valOut = cache.Get(key); + + 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_AUTO_TEST_CASE(CacheClientPutGetComplexKey) +{ + 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 = 42; + + cache.Put(key, valIn); + + int32_t valOut = cache.Get(key); + + BOOST_CHECK_EQUAL(valIn, valOut); +} + +BOOST_AUTO_TEST_CASE(CacheClientContainsBasicKey) +{ + 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"; + + BOOST_CHECK(!cache.ContainsKey(key)); + + cache.Put(key, valIn); + + BOOST_CHECK(cache.ContainsKey(key)); +} + +BOOST_AUTO_TEST_CASE(CacheClientContainsComplexKey) +{ + 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 = 42; + + BOOST_CHECK(!cache.ContainsKey(key)); + + cache.Put(key, valIn); + + BOOST_CHECK(cache.ContainsKey(key)); +} + +BOOST_AUTO_TEST_CASE(CacheClientPartitionsInt8) +{ + NumPartitionTest<int8_t>(100); +} + +BOOST_AUTO_TEST_CASE(CacheClientPartitionsInt16) +{ + NumPartitionTest<int16_t>(2000); +} + +BOOST_AUTO_TEST_CASE(CacheClientPartitionsInt32) +{ + NumPartitionTest<int32_t>(1050); +} + +BOOST_AUTO_TEST_CASE(CacheClientPartitionsInt64) +{ + NumPartitionTest<int64_t>(2000); +} + +BOOST_AUTO_TEST_CASE(CacheClientPartitionsUint16) +{ + NumPartitionTest<uint16_t>(1500); +} + +BOOST_AUTO_TEST_CASE(CacheClientPartitionsFloat) +{ + NumPartitionTest<float>(1500); +} + +BOOST_AUTO_TEST_CASE(CacheClientPartitionsDouble) +{ + NumPartitionTest<double>(500); +} + +BOOST_AUTO_TEST_CASE(CacheClientPartitionsString) +{ + StartNode("node1"); + + boost::this_thread::sleep_for(boost::chrono::seconds(2)); + + IgniteClientConfiguration cfg; + cfg.SetEndPoints("127.0.0.1:11110..11120"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<std::string, int64_t> cache = + client.GetCache<std::string, int64_t>("partitioned"); + + cache.RefreshAffinityMapping(); + + for (int64_t i = 1; i < 1000; ++i) + cache.Put(ignite::common::LexicalCast<std::string>(i * 39916801), i * 5039); + + for (int64_t i = 1; i < 1000; ++i) + { + int64_t val; + LocalPeek(cache, ignite::common::LexicalCast<std::string>(i * 39916801), val); + + BOOST_CHECK_EQUAL(val, i * 5039); + } +} + +BOOST_AUTO_TEST_CASE(CacheClientPartitionsGuid) +{ + StartNode("node1"); + + boost::this_thread::sleep_for(boost::chrono::seconds(2)); + + IgniteClientConfiguration cfg; + cfg.SetEndPoints("127.0.0.1:11110..11120"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<ignite::Guid, int64_t> cache = + client.GetCache<ignite::Guid, int64_t>("partitioned"); + + cache.RefreshAffinityMapping(); + + for (int64_t i = 1; i < 1000; ++i) + cache.Put(ignite::Guid(i * 406586897, i * 87178291199), i * 5039); + + for (int64_t i = 1; i < 1000; ++i) + { + int64_t val; + LocalPeek(cache, ignite::Guid(i * 406586897, i * 87178291199), val); + + BOOST_CHECK_EQUAL(val, i * 5039); + } +} + +BOOST_AUTO_TEST_CASE(CacheClientPartitionsComplexType) +{ + StartNode("node1"); + + boost::this_thread::sleep_for(boost::chrono::seconds(2)); + + IgniteClientConfiguration cfg; + cfg.SetEndPoints("127.0.0.1:11110..11120"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<ignite::ComplexType, int64_t> cache = + client.GetCache<ignite::ComplexType, int64_t>("partitioned"); + + cache.RefreshAffinityMapping(); + + for (int64_t i = 1; i < 1000; ++i) + { + ignite::ComplexType key; + + key.i32Field = static_cast<int32_t>(i * 406586897); + key.strField = ignite::common::LexicalCast<std::string>(i * 39916801); + key.objField.f1 = static_cast<int32_t>(i * 87178291199); + key.objField.f2 = ignite::common::LexicalCast<std::string>(i * 59969537); + + cache.Put(key, i * 5039); + } + + for (int64_t i = 1; i < 1000; ++i) + { + ignite::ComplexType key; + + key.i32Field = static_cast<int32_t>(i * 406586897); + key.strField = ignite::common::LexicalCast<std::string>(i * 39916801); + key.objField.f1 = static_cast<int32_t>(i * 87178291199); + key.objField.f2 = ignite::common::LexicalCast<std::string>(i * 59969537); + + int64_t val; + LocalPeek(cache, key, val); + + BOOST_CHECK_EQUAL(val, i * 5039); + } +} + +BOOST_AUTO_TEST_CASE(CacheClientPartitionsDate) +{ + StartNode("node1"); + + boost::this_thread::sleep_for(boost::chrono::seconds(2)); + + IgniteClientConfiguration cfg; + cfg.SetEndPoints("127.0.0.1:11110..11120"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<ignite::Date, int64_t> cache = + client.GetCache<ignite::Date, int64_t>("partitioned"); + + cache.RefreshAffinityMapping(); + + for (int64_t i = 1; i < 1000; ++i) + cache.Put(ignite::common::MakeDateGmt( + static_cast<int>(1990 + i), + std::abs(static_cast<int>((i * 87178291199) % 11) + 1), + std::abs(static_cast<int>((i * 39916801) % 27) + 1), + std::abs(static_cast<int>(9834497 * i) % 24), + std::abs(static_cast<int>(i * 87178291199) % 60), + std::abs(static_cast<int>(i * 39916801) % 60)), + i * 5039); + + for (int64_t i = 1; i < 1000; ++i) + { + int64_t val; + LocalPeek(cache, ignite::common::MakeDateGmt( + static_cast<int>(1990 + i), + std::abs(static_cast<int>((i * 87178291199) % 11) + 1), + std::abs(static_cast<int>((i * 39916801) % 27) + 1), + std::abs(static_cast<int>(9834497 * i) % 24), + std::abs(static_cast<int>(i * 87178291199) % 60), + std::abs(static_cast<int>(i * 39916801) % 60)), + val); + + BOOST_CHECK_EQUAL(val, i * 5039); + } +} + +BOOST_AUTO_TEST_CASE(CacheClientPartitionsTime) +{ + StartNode("node1"); + + boost::this_thread::sleep_for(boost::chrono::seconds(2)); + + IgniteClientConfiguration cfg; + cfg.SetEndPoints("127.0.0.1:11110..11120"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<ignite::Time, int64_t> cache = + client.GetCache<ignite::Time, int64_t>("partitioned"); + + cache.RefreshAffinityMapping(); + + for (int64_t i = 1; i < 100; ++i) + cache.Put(ignite::common::MakeTimeGmt( + std::abs(static_cast<int>(9834497 * i) % 24), + std::abs(static_cast<int>(i * 87178291199) % 60), + std::abs(static_cast<int>(i * 39916801) % 60)), + i * 5039); + + for (int64_t i = 1; i < 100; ++i) + { + int64_t val; + LocalPeek(cache, ignite::common::MakeTimeGmt( + std::abs(static_cast<int>(9834497 * i) % 24), + std::abs(static_cast<int>(i * 87178291199) % 60), + std::abs(static_cast<int>(i * 39916801) % 60)), + val); + + BOOST_CHECK_EQUAL(val, i * 5039); + } +} + +BOOST_AUTO_TEST_CASE(CacheClientPartitionsTimestamp) +{ + StartNode("node1"); + + boost::this_thread::sleep_for(boost::chrono::seconds(2)); + + IgniteClientConfiguration cfg; + cfg.SetEndPoints("127.0.0.1:11110..11120"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<ignite::Timestamp, int64_t> cache = + client.GetCache<ignite::Timestamp, int64_t>("partitioned"); + + cache.RefreshAffinityMapping(); + + for (int64_t i = 1; i < 1000; ++i) + cache.Put(ignite::common::MakeTimestampGmt( + static_cast<int>(1990 + i), + std::abs(static_cast<int>(i * 87178291199) % 11 + 1), + std::abs(static_cast<int>(i * 39916801) % 28), + std::abs(static_cast<int>(9834497 * i) % 24), + std::abs(static_cast<int>(i * 87178291199) % 60), + std::abs(static_cast<int>(i * 39916801) % 60), + std::abs(static_cast<long>((i * 303595777) % 1000000000))), + i * 5039); + + for (int64_t i = 1; i < 1000; ++i) + { + int64_t val; + LocalPeek(cache, ignite::common::MakeTimestampGmt( + static_cast<int>(1990 + i), + std::abs(static_cast<int>(i * 87178291199) % 11 + 1), + std::abs(static_cast<int>(i * 39916801) % 28), + std::abs(static_cast<int>(9834497 * i) % 24), + std::abs(static_cast<int>(i * 87178291199) % 60), + std::abs(static_cast<int>(i * 39916801) % 60), + std::abs(static_cast<long>((i * 303595777) % 1000000000))), + val); + + BOOST_CHECK_EQUAL(val, i * 5039); + } +} + +BOOST_AUTO_TEST_CASE(CacheClientGetSizeAll) +{ + SizeTest(cache::CachePeekMode::ALL); +} + +BOOST_AUTO_TEST_CASE(CacheClientGetSizePrimary) +{ + SizeTest(cache::CachePeekMode::PRIMARY); +} + +BOOST_AUTO_TEST_CASE(CacheClientGetSizeOnheap) +{ + SizeTest(cache::CachePeekMode::ONHEAP); +} + +BOOST_AUTO_TEST_CASE(CacheClientGetSizeSeveral) +{ + using cache::CachePeekMode; + + SizeTest( + CachePeekMode::NEAR_CACHE | + CachePeekMode::PRIMARY | + CachePeekMode::BACKUP | + CachePeekMode::ONHEAP | + CachePeekMode::OFFHEAP + ); +} + +BOOST_AUTO_TEST_CASE(CacheClientRemoveAll) +{ + IgniteClientConfiguration cfg; + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<int32_t, int32_t> cache = + client.GetCache<int32_t, int32_t>("partitioned"); + + for (int32_t i = 0; i < 1000; ++i) + cache.Put(i, i * 5039); + + int64_t size = cache.GetSize(cache::CachePeekMode::ALL); + BOOST_CHECK_EQUAL(size, 1000); + + cache.RemoveAll(); + + size = cache.GetSize(cache::CachePeekMode::ALL); + BOOST_CHECK_EQUAL(size, 0); +} + +BOOST_AUTO_TEST_CASE(CacheClientClearAll) +{ + IgniteClientConfiguration cfg; + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<int32_t, int32_t> cache = + client.GetCache<int32_t, int32_t>("partitioned"); + + for (int32_t i = 0; i < 1000; ++i) + cache.Put(i, i * 5039); + + int64_t size = cache.GetSize(cache::CachePeekMode::ALL); + BOOST_CHECK_EQUAL(size, 1000); + + cache.Clear(); + + size = cache.GetSize(cache::CachePeekMode::ALL); + BOOST_CHECK_EQUAL(size, 0); +} + +BOOST_AUTO_TEST_CASE(CacheClientRemove) +{ + IgniteClientConfiguration cfg; + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<int32_t, int32_t> cache = + client.GetCache<int32_t, int32_t>("partitioned"); + + for (int32_t i = 0; i < 1000; ++i) + cache.Put(i, i * 5039); + + int64_t size = cache.GetSize(cache::CachePeekMode::ALL); + BOOST_CHECK_EQUAL(size, 1000); + + for (int32_t i = 0; i < 1000; ++i) + { + BOOST_CHECK(cache.Remove(i)); + + size = cache.GetSize(cache::CachePeekMode::ALL); + BOOST_CHECK_EQUAL(size, 1000 - i - 1); + } +} + +BOOST_AUTO_TEST_CASE(CacheClientClear) +{ + IgniteClientConfiguration cfg; + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient client = IgniteClient::Start(cfg); + + cache::CacheClient<int32_t, int32_t> cache = + client.GetCache<int32_t, int32_t>("partitioned"); + + for (int32_t i = 0; i < 1000; ++i) + cache.Put(i, i * 5039); + + int64_t size = cache.GetSize(cache::CachePeekMode::ALL); + BOOST_CHECK_EQUAL(size, 1000); + + for (int32_t i = 0; i < 1000; ++i) + { + cache.Clear(i); + + size = cache.GetSize(cache::CachePeekMode::ALL); + BOOST_CHECK_EQUAL(size, 1000 - i - 1); + } +} + +BOOST_AUTO_TEST_SUITE_END()
http://git-wip-us.apache.org/repos/asf/ignite/blob/ed658597/modules/platforms/cpp/thin-client-test/src/ignite_client_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/thin-client-test/src/ignite_client_test.cpp b/modules/platforms/cpp/thin-client-test/src/ignite_client_test.cpp new file mode 100644 index 0000000..4dbc7f7 --- /dev/null +++ b/modules/platforms/cpp/thin-client-test/src/ignite_client_test.cpp @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _MSC_VER +# define BOOST_TEST_DYN_LINK +#endif + +#include <boost/test/unit_test.hpp> + +#include <ignite/ignition.h> + +#include <ignite/thin/ignite_client_configuration.h> +#include <ignite/thin/ignite_client.h> + +#include <test_utils.h> + +using namespace ignite::thin; +using namespace boost::unit_test; + +class IgniteClientTestSuiteFixture +{ +public: + IgniteClientTestSuiteFixture() + { + serverNode = ignite_test::StartCrossPlatformServerNode("cache.xml", "ServerNode"); + } + + ~IgniteClientTestSuiteFixture() + { + ignite::Ignition::StopAll(false); + } + +private: + /** Server node. */ + ignite::Ignite serverNode; +}; + +BOOST_FIXTURE_TEST_SUITE(IgniteClientTestSuite, IgniteClientTestSuiteFixture) + +BOOST_AUTO_TEST_CASE(IgniteClientConnection) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + IgniteClient::Start(cfg); +} + +BOOST_AUTO_TEST_CASE(IgniteClientConnectionFailover) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11109..11111"); + + IgniteClient::Start(cfg); +} + +BOOST_AUTO_TEST_SUITE_END() http://git-wip-us.apache.org/repos/asf/ignite/blob/ed658597/modules/platforms/cpp/thin-client-test/src/ssl_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/thin-client-test/src/ssl_test.cpp b/modules/platforms/cpp/thin-client-test/src/ssl_test.cpp new file mode 100644 index 0000000..6bfda49 --- /dev/null +++ b/modules/platforms/cpp/thin-client-test/src/ssl_test.cpp @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _MSC_VER +# define BOOST_TEST_DYN_LINK +#endif + +#include <boost/test/unit_test.hpp> + +#include <ignite/ignition.h> + +#include <ignite/thin/ignite_client_configuration.h> +#include <ignite/thin/ignite_client.h> + +#include <test_utils.h> + +using namespace ignite::thin; +using namespace boost::unit_test; + +class SslTestSuiteFixture +{ +public: + SslTestSuiteFixture() + { + serverNode = ignite_test::StartCrossPlatformServerNode("ssl.xml", "ServerNode"); + } + + ~SslTestSuiteFixture() + { + ignite::Ignition::StopAll(false); + } + + std::string GetConfigFile(const std::string& file) + { + using namespace ignite::common; + std::stringstream pathBuilder; + + pathBuilder << ignite_test::GetTestConfigDir() << Fs << "ssl" << Fs << file; + + return pathBuilder.str(); + } + +private: + /** Server node. */ + ignite::Ignite serverNode; +}; + +BOOST_FIXTURE_TEST_SUITE(SslTestSuite, SslTestSuiteFixture) + +BOOST_AUTO_TEST_CASE(SslConnectionSuccess) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + cfg.SetSslMode(SslMode::REQUIRE); + cfg.SetSslCertFile(GetConfigFile("client_full.pem")); + cfg.SetSslKeyFile(GetConfigFile("client_full.pem")); + cfg.SetSslCaFile(GetConfigFile("ca.pem")); + + IgniteClient::Start(cfg); +} + +BOOST_AUTO_TEST_CASE(SslConnectionReject) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + cfg.SetSslMode(SslMode::REQUIRE); + cfg.SetSslCertFile(GetConfigFile("client_unknown.pem")); + cfg.SetSslKeyFile(GetConfigFile("client_unknown.pem")); + cfg.SetSslCaFile(GetConfigFile("ca.pem")); + + BOOST_CHECK_THROW(IgniteClient::Start(cfg), ignite::IgniteError); +} + +BOOST_AUTO_TEST_CASE(SslConnectionReject2) +{ + IgniteClientConfiguration cfg; + + cfg.SetEndPoints("127.0.0.1:11110"); + + cfg.SetSslMode(SslMode::DISABLE); + + BOOST_CHECK_THROW(IgniteClient::Start(cfg), ignite::IgniteError); +} + +BOOST_AUTO_TEST_SUITE_END() http://git-wip-us.apache.org/repos/asf/ignite/blob/ed658597/modules/platforms/cpp/thin-client-test/src/teamcity/teamcity_boost.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/thin-client-test/src/teamcity/teamcity_boost.cpp b/modules/platforms/cpp/thin-client-test/src/teamcity/teamcity_boost.cpp new file mode 100644 index 0000000..2f3afe9 --- /dev/null +++ b/modules/platforms/cpp/thin-client-test/src/teamcity/teamcity_boost.cpp @@ -0,0 +1,159 @@ +/* Copyright 2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $Revision: 88625 $ +*/ + +#define BOOST_TEST_MODULE IgniteThinClientTest + +#include <sstream> + +#include <boost/test/unit_test_suite_impl.hpp> +#include <boost/test/results_collector.hpp> +#include <boost/test/utils/basic_cstring/io.hpp> +#include <boost/test/unit_test_log.hpp> +#include <boost/test/included/unit_test.hpp> + +#include "teamcity/teamcity_messages.h" + +using namespace boost::unit_test; +using namespace std; + +namespace JetBrains { + +// Custom formatter for TeamCity messages +class TeamcityBoostLogFormatter: public boost::unit_test::unit_test_log_formatter { + TeamcityMessages messages; + std::string currentDetails; + std::string flowId; + +public: + TeamcityBoostLogFormatter(const std::string &_flowId); + TeamcityBoostLogFormatter(); + + void log_start(std::ostream&, boost::unit_test::counter_t test_cases_amount); + void log_finish(std::ostream&); + void log_build_info(std::ostream&); + + void test_unit_start(std::ostream&, boost::unit_test::test_unit const& tu); + void test_unit_finish(std::ostream&, + boost::unit_test::test_unit const& tu, + unsigned long elapsed); + void test_unit_skipped(std::ostream&, boost::unit_test::test_unit const& tu); + + void log_exception(std::ostream&, + boost::unit_test::log_checkpoint_data const&, + boost::unit_test::const_string explanation); + + void log_entry_start(std::ostream&, + boost::unit_test::log_entry_data const&, + log_entry_types let); + void log_entry_value(std::ostream&, boost::unit_test::const_string value); + void log_entry_finish(std::ostream&); +}; + +// Fake fixture to register formatter +struct TeamcityFormatterRegistrar { + TeamcityFormatterRegistrar() { + if (JetBrains::underTeamcity()) { + boost::unit_test::unit_test_log.set_formatter(new JetBrains::TeamcityBoostLogFormatter()); + boost::unit_test::unit_test_log.set_threshold_level(boost::unit_test::log_successful_tests); + } + } +}; +BOOST_GLOBAL_FIXTURE(TeamcityFormatterRegistrar); + +// Formatter implementation +string toString(const_string bstr) { + stringstream ss; + + ss << bstr; + + return ss.str(); +} + +TeamcityBoostLogFormatter::TeamcityBoostLogFormatter(const std::string &_flowId) +: flowId(_flowId) +{} + +TeamcityBoostLogFormatter::TeamcityBoostLogFormatter() +: flowId(getFlowIdFromEnvironment()) +{} + +void TeamcityBoostLogFormatter::log_start(ostream &out, counter_t test_cases_amount) +{} + +void TeamcityBoostLogFormatter::log_finish(ostream &out) +{} + +void TeamcityBoostLogFormatter::log_build_info(ostream &out) +{} + +void TeamcityBoostLogFormatter::test_unit_start(ostream &out, test_unit const& tu) { + messages.setOutput(out); + + if (tu.p_type == tut_case) { + messages.testStarted(tu.p_name, flowId); + } else { + messages.suiteStarted(tu.p_name, flowId); + } + + currentDetails.clear(); +} + +void TeamcityBoostLogFormatter::test_unit_finish(ostream &out, test_unit const& tu, unsigned long elapsed) { + messages.setOutput(out); + + test_results const& tr = results_collector.results(tu.p_id); + if (tu.p_type == tut_case) { + if(!tr.passed()) { + if(tr.p_skipped) { + messages.testIgnored(tu.p_name, "ignored", flowId); + } else if (tr.p_aborted) { + messages.testFailed(tu.p_name, "aborted", currentDetails, flowId); + } else { + messages.testFailed(tu.p_name, "failed", currentDetails, flowId); + } + } + + messages.testFinished(tu.p_name, elapsed / 1000, flowId); + } else { + messages.suiteFinished(tu.p_name, flowId); + } +} + +void TeamcityBoostLogFormatter::test_unit_skipped(ostream &out, test_unit const& tu) +{} + +void TeamcityBoostLogFormatter::log_exception(ostream &out, log_checkpoint_data const&, const_string explanation) { + string what = toString(explanation); + + out << what << endl; + currentDetails += what + "\n"; +} + +void TeamcityBoostLogFormatter::log_entry_start(ostream&, log_entry_data const&, log_entry_types let) +{} + +void TeamcityBoostLogFormatter::log_entry_value(ostream &out, const_string value) { + out << value; + currentDetails += toString(value); +} + +void TeamcityBoostLogFormatter::log_entry_finish(ostream &out) { + out << endl; + currentDetails += "\n"; +} + +} http://git-wip-us.apache.org/repos/asf/ignite/blob/ed658597/modules/platforms/cpp/thin-client-test/src/teamcity/teamcity_messages.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/thin-client-test/src/teamcity/teamcity_messages.cpp b/modules/platforms/cpp/thin-client-test/src/teamcity/teamcity_messages.cpp new file mode 100644 index 0000000..2837542 --- /dev/null +++ b/modules/platforms/cpp/thin-client-test/src/teamcity/teamcity_messages.cpp @@ -0,0 +1,150 @@ +/* Copyright 2011 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * $Revision: 88625 $ +*/ + +#include <stdlib.h> +#include <sstream> + +#include "teamcity/teamcity_messages.h" + +using namespace std; + +namespace JetBrains { + +std::string getFlowIdFromEnvironment() { + const char *flowId = getenv("TEAMCITY_PROCESS_FLOW_ID"); + return flowId == NULL ? "" : flowId; +} + +bool underTeamcity() { + return getenv("TEAMCITY_PROJECT_NAME") != NULL; +} + +TeamcityMessages::TeamcityMessages() +: m_out(&cout) +{} + +void TeamcityMessages::setOutput(ostream &out) { + m_out = &out; +} + +string TeamcityMessages::escape(string s) { + string result; + + for (size_t i = 0; i < s.length(); i++) { + char c = s[i]; + + switch (c) { + case '\n': result.append("|n"); break; + case '\r': result.append("|r"); break; + case '\'': result.append("|'"); break; + case '|': result.append("||"); break; + case ']': result.append("|]"); break; + default: result.append(&c, 1); + } + } + + return result; +} + +void TeamcityMessages::openMsg(const string &name) { + // endl for http://jetbrains.net/tracker/issue/TW-4412 + *m_out << endl << "##teamcity[" << name; +} + +void TeamcityMessages::closeMsg() { + *m_out << "]"; + // endl for http://jetbrains.net/tracker/issue/TW-4412 + *m_out << endl; + m_out->flush(); +} + +void TeamcityMessages::writeProperty(string name, string value) { + *m_out << " " << name << "='" << escape(value) << "'"; +} + +void TeamcityMessages::suiteStarted(string name, string flowid) { + openMsg("testSuiteStarted"); + writeProperty("name", name); + if(flowid.length() > 0) { + writeProperty("flowId", flowid); + } + + closeMsg(); +} + +void TeamcityMessages::suiteFinished(string name, string flowid) { + openMsg("testSuiteFinished"); + writeProperty("name", name); + if(flowid.length() > 0) { + writeProperty("flowId", flowid); + } + + closeMsg(); +} + +void TeamcityMessages::testStarted(string name, string flowid) { + openMsg("testStarted"); + writeProperty("name", name); + if(flowid.length() > 0) { + writeProperty("flowId", flowid); + } + + closeMsg(); +} + +void TeamcityMessages::testFinished(string name, int durationMs, string flowid) { + openMsg("testFinished"); + + writeProperty("name", name); + + if(flowid.length() > 0) { + writeProperty("flowId", flowid); + } + + if(durationMs >= 0) { + stringstream out; + out << durationMs; + writeProperty("duration", out.str()); + } + + closeMsg(); +} + +void TeamcityMessages::testFailed(string name, string message, string details, string flowid) { + openMsg("testFailed"); + writeProperty("name", name); + writeProperty("message", message); + writeProperty("details", details); + if(flowid.length() > 0) { + writeProperty("flowId", flowid); + } + + closeMsg(); +} + +void TeamcityMessages::testIgnored(std::string name, std::string message, string flowid) { + openMsg("testIgnored"); + writeProperty("name", name); + writeProperty("message", message); + if(flowid.length() > 0) { + writeProperty("flowId", flowid); + } + + closeMsg(); +} + +} http://git-wip-us.apache.org/repos/asf/ignite/blob/ed658597/modules/platforms/cpp/thin-client-test/src/test_utils.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/thin-client-test/src/test_utils.cpp b/modules/platforms/cpp/thin-client-test/src/test_utils.cpp new file mode 100644 index 0000000..a60e392 --- /dev/null +++ b/modules/platforms/cpp/thin-client-test/src/test_utils.cpp @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <cassert> + +#include <ignite/common/platform_utils.h> + +#include "test_utils.h" + +namespace ignite_test +{ + std::string GetTestConfigDir() + { + return ignite::common::GetEnv("IGNITE_NATIVE_TEST_CPP_THIN_CONFIG_PATH"); + } + + void InitConfig(ignite::IgniteConfiguration& cfg, const char* cfgFile) + { + using namespace ignite; + + assert(cfgFile != 0); + + cfg.jvmOpts.push_back("-Xdebug"); + cfg.jvmOpts.push_back("-Xnoagent"); + cfg.jvmOpts.push_back("-Djava.compiler=NONE"); + cfg.jvmOpts.push_back("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"); + cfg.jvmOpts.push_back("-XX:+HeapDumpOnOutOfMemoryError"); + cfg.jvmOpts.push_back("-Duser.timezone=GMT"); + cfg.jvmOpts.push_back("-DIGNITE_QUIET=false"); + cfg.jvmOpts.push_back("-DIGNITE_CONSOLE_APPENDER=false"); + cfg.jvmOpts.push_back("-DIGNITE_UPDATE_NOTIFIER=false"); + cfg.jvmOpts.push_back("-Duser.language=en"); + // Un-comment to debug SSL + //cfg.jvmOpts.push_back("-Djavax.net.debug=ssl"); + + cfg.igniteHome = jni::ResolveIgniteHome(); + cfg.jvmClassPath = jni::CreateIgniteHomeClasspath(cfg.igniteHome, true); + +#ifdef IGNITE_TESTS_32 + cfg.jvmInitMem = 256; + cfg.jvmMaxMem = 768; +#else + cfg.jvmInitMem = 1024; + cfg.jvmMaxMem = 4096; +#endif + + cfg.springCfgPath = GetTestConfigDir().append("/").append(cfgFile); + } + + ignite::Ignite StartServerNode(const char* cfgFile, const char* name) + { + using namespace ignite; + + assert(name != 0); + + IgniteConfiguration cfg; + + InitConfig(cfg, cfgFile); + + return Ignition::Start(cfg, name); + } + + ignite::Ignite StartCrossPlatformServerNode(const char* cfgFile, const char* name) + { + std::string config(cfgFile); + +#ifdef IGNITE_TESTS_32 + // Cutting off the ".xml" part. + config.resize(config.size() - 4); + config += "-32.xml"; +#endif //IGNITE_TESTS_32 + + return StartServerNode(config.c_str(), name); + } + + std::string AppendPath(const std::string& base, const std::string& toAdd) + { + std::stringstream stream; + + stream << base << ignite::common::Fs << toAdd; + + return stream.str(); + } + + void ClearLfs() + { + std::string home = ignite::jni::ResolveIgniteHome(); + std::string workDir = AppendPath(home, "work"); + + ignite::common::DeletePath(workDir); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/ed658597/modules/platforms/cpp/thin-client/Makefile.am ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/thin-client/Makefile.am b/modules/platforms/cpp/thin-client/Makefile.am new file mode 100644 index 0000000..f8d9190 --- /dev/null +++ b/modules/platforms/cpp/thin-client/Makefile.am @@ -0,0 +1,72 @@ +## +## Licensed to the Apache Software Foundation (ASF) under one or more +## contributor license agreements. See the NOTICE file distributed with +## this work for additional information regarding copyright ownership. +## The ASF licenses this file to You under the Apache License, Version 2.0 +## (the "License"); you may not use this file except in compliance with +## the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## + +ACLOCAL_AMFLAGS =-I m4 + +lib_LTLIBRARIES = libignite-thin-client.la + +SUBDIRS = \ + include + +AM_CPPFLAGS = \ + -I$(srcdir)/include \ + -I$(srcdir)/src \ + -I@top_srcdir@/common/include \ + -I@top_srcdir@/common/os/linux/include \ + -I@top_srcdir@/binary/include \ + -DIGNITE_IMPL \ + -D__STDC_LIMIT_MACROS \ + -D__STDC_CONSTANT_MACROS + +AM_CXXFLAGS = \ + -Wall \ + -std=c++03 + +libignite_thin_client_la_LIBADD = \ + @top_srcdir@/binary/libignite-binary.la + +libignite_thin_client_la_LDFLAGS = \ + -no-undefined \ + -ldl \ + -version-info 0:0:0 \ + -release $(PACKAGE_VERSION) + +libignite_thin_client_la_DEPENDENCIES = \ + @top_srcdir@/binary/libignite-binary.la + +libignite_thin_client_la_SOURCES = \ + os/linux/src/net/net_utils.cpp \ + os/linux/src/net/tcp_socket_client.cpp \ + src/impl/utility.cpp \ + src/impl/protocol_version.cpp \ + src/impl/data_channel.cpp \ + src/impl/net/remote_type_updater.cpp \ + src/impl/message.cpp \ + src/impl/ignite_client_impl.cpp \ + src/impl/cache/cache_client_proxy.cpp \ + src/impl/cache/cache_client_impl.cpp \ + src/impl/cache/cache_affinity_info.cpp \ + src/impl/data_router.cpp \ + src/impl/ssl/ssl_gateway.cpp \ + src/impl/ssl/secure_socket_client.cpp \ + src/ignite_client.cpp + +clean-local: + $(RM) *.gcno *.gcda + +clean-docs: + $(RM) $(DX_CLEANFILES) http://git-wip-us.apache.org/repos/asf/ignite/blob/ed658597/modules/platforms/cpp/thin-client/README.md ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/thin-client/README.md b/modules/platforms/cpp/thin-client/README.md new file mode 100644 index 0000000..523524b --- /dev/null +++ b/modules/platforms/cpp/thin-client/README.md @@ -0,0 +1,4 @@ +Apache Ignite Thin C++ client +======================================= + +TBD \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/ed658597/modules/platforms/cpp/thin-client/include/Makefile.am ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/thin-client/include/Makefile.am b/modules/platforms/cpp/thin-client/include/Makefile.am new file mode 100644 index 0000000..79816fe --- /dev/null +++ b/modules/platforms/cpp/thin-client/include/Makefile.am @@ -0,0 +1,31 @@ +## +## Licensed to the Apache Software Foundation (ASF) under one or more +## contributor license agreements. See the NOTICE file distributed with +## this work for additional information regarding copyright ownership. +## The ASF licenses this file to You under the Apache License, Version 2.0 +## (the "License"); you may not use this file except in compliance with +## the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## + +ACLOCAL_AMFLAGS =-I m4 + +noinst_HEADERS = \ + ignite/thin/ssl_mode.h \ + ignite/thin/ignite_client.h \ + ignite/thin/ignite_client_configuration.h \ + ignite/thin/cache/cache_client.h \ + ignite/impl/thin/writable_key.h \ + ignite/impl/thin/readable.h \ + ignite/impl/thin/writable.h \ + ignite/impl/thin/cache/cache_client_proxy.h + +uninstall-hook: + if [ -d ${includedir}/ignite ]; then find ${includedir}/ignite -type d -empty -delete; fi http://git-wip-us.apache.org/repos/asf/ignite/blob/ed658597/modules/platforms/cpp/thin-client/include/ignite/impl/thin/cache/cache_client_proxy.h ---------------------------------------------------------------------- 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 new file mode 100644 index 0000000..00c04f6 --- /dev/null +++ b/modules/platforms/cpp/thin-client/include/ignite/impl/thin/cache/cache_client_proxy.h @@ -0,0 +1,165 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _IGNITE_IMPL_THIN_CACHE_CACHE_CLIENT_PROXY +#define _IGNITE_IMPL_THIN_CACHE_CACHE_CLIENT_PROXY + +#include <ignite/common/concurrent.h> + +namespace ignite +{ + namespace impl + { + namespace thin + { + /* Forward declaration. */ + class Writable; + + /* Forward declaration. */ + class WritableKey; + + /* Forward declaration. */ + class Readable; + + namespace cache + { + /** + * Ignite client class proxy. + */ + class IGNITE_IMPORT_EXPORT CacheClientProxy + { + public: + /** + * Constructor. + */ + CacheClientProxy(const common::concurrent::SharedPointer<void>& impl) : + impl(impl) + { + // No-op. + } + + /** + * Destructor. + */ + ~CacheClientProxy() + { + // No-op. + } + + /** + * Put value to cache. + * + * @param key Key. + * @param value Value. + */ + void Put(const WritableKey& key, const Writable& value); + + /** + * Get value from cache. + * + * @param key Key. + * @param value Value. + */ + void Get(const WritableKey& key, Readable& value); + + /** + * Check if the cache contains a value for the specified key. + * + * @param key Key whose presence in this cache is to be tested. + * @return @c true if the cache contains specified key. + */ + bool ContainsKey(const WritableKey& key); + + /** + * Gets the number of all entries cached across all nodes. + * @note This operation is distributed and will query all participating nodes for their cache sizes. + * + * @param peekModes Peek modes mask. + * @return Cache size across all nodes. + */ + int64_t GetSize(int32_t peekModes); + + /** + * Peeks at in-memory cached value using default optional peek mode. This method will not load value + * from any persistent store or from a remote node. + * + * Use for testing purposes only. + * + * @param key Key whose presence in this cache is to be tested. + * @param value Value. + */ + void LocalPeek(const WritableKey& key, Readable& value); + + /** + * Update cache partitions info. + */ + void RefreshAffinityMapping(); + + /** + * 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. + * This method is transactional and will enlist the entry into ongoing transaction if there is one. + * + * @param key Key whose mapping is to be removed from cache. + * @return False if there was no matching key. + */ + bool Remove(const WritableKey& key); + + /** + * Removes all mappings from cache. + * If write-through is enabled, the value will be removed from store. + * This method is transactional and will enlist the entry into ongoing transaction if there is one. + */ + void RemoveAll(); + + /** + * Clear entry from the cache and swap storage, without notifying listeners or CacheWriters. + * Entry is cleared only if it is not currently locked, and is not participating in a transaction. + * + * @param key Key to clear. + */ + void Clear(const WritableKey& key); + + /** + * Clear cache. + */ + void Clear(); + + /** + * Get from CacheClient. + * Use for testing purposes only. + */ + template<typename CacheClientT> + static CacheClientProxy& GetFromCacheClient(CacheClientT& instance) + { + return instance.proxy; + } + + private: + /** Implementation. */ + common::concurrent::SharedPointer<void> impl; + }; + } + } + } +} +#endif // _IGNITE_IMPL_THIN_CACHE_CACHE_CLIENT_PROXY http://git-wip-us.apache.org/repos/asf/ignite/blob/ed658597/modules/platforms/cpp/thin-client/include/ignite/impl/thin/readable.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/thin-client/include/ignite/impl/thin/readable.h b/modules/platforms/cpp/thin-client/include/ignite/impl/thin/readable.h new file mode 100644 index 0000000..8c3e337 --- /dev/null +++ b/modules/platforms/cpp/thin-client/include/ignite/impl/thin/readable.h @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _IGNITE_IMPL_THIN_READABLE +#define _IGNITE_IMPL_THIN_READABLE + +#include <ignite/impl/binary/binary_reader_impl.h> + +namespace ignite +{ + namespace impl + { + namespace thin + { + /** + * Abstraction to any type that can be read from a binary stream. + */ + class Readable + { + public: + /** + * Destructor. + */ + virtual ~Readable() + { + // No-op. + } + + /** + * Read value using reader. + * + * @param reader Reader to use. + */ + virtual void Read(binary::BinaryReaderImpl& reader) = 0; + }; + + /** + * Implementation of the Readable class for a concrete type. + */ + template<typename T> + class ReadableImpl : public Readable + { + public: + /** Value type. */ + typedef T ValueType; + + /** + * Constructor. + * + * @param value Value. + */ + ReadableImpl(ValueType& value) : + value(value) + { + // No-op. + } + + /** + * Destructor. + */ + virtual ~ReadableImpl() + { + // No-op. + } + + /** + * Read value using reader. + * + * @param reader Reader to use. + */ + virtual void Read(binary::BinaryReaderImpl& reader) + { + reader.ReadTopObject0(value); + } + + private: + /** Data router. */ + ValueType& value; + }; + } + } +} + +#endif // _IGNITE_IMPL_THIN_READABLE http://git-wip-us.apache.org/repos/asf/ignite/blob/ed658597/modules/platforms/cpp/thin-client/include/ignite/impl/thin/writable.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/thin-client/include/ignite/impl/thin/writable.h b/modules/platforms/cpp/thin-client/include/ignite/impl/thin/writable.h new file mode 100644 index 0000000..5d5eefe --- /dev/null +++ b/modules/platforms/cpp/thin-client/include/ignite/impl/thin/writable.h @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _IGNITE_IMPL_THIN_WRITABLE +#define _IGNITE_IMPL_THIN_WRITABLE + +#include <ignite/impl/binary/binary_writer_impl.h> + +namespace ignite +{ + namespace impl + { + namespace thin + { + /** + * Abstraction to any type that can be written to a binary stream. + */ + class Writable + { + public: + /** + * Destructor. + */ + virtual ~Writable() + { + // No-op. + } + + /** + * Write value using writer. + * + * @param writer Writer to use. + */ + virtual void Write(binary::BinaryWriterImpl& writer) const = 0; + }; + + /** + * Implementation of the Writable class for a concrete type. + */ + template<typename T> + class WritableImpl : public Writable + { + public: + /** Value type. */ + typedef T ValueType; + + /** + * Constructor. + * + * @param value Value. + */ + WritableImpl(const ValueType& value) : + value(value) + { + // No-op. + } + + /** + * Destructor. + */ + virtual ~WritableImpl() + { + // No-op. + } + + /** + * Write value using writer. + * + * @param writer Writer to use. + */ + virtual void Write(binary::BinaryWriterImpl& writer) const + { + writer.WriteObject(value); + } + + private: + /** Value. */ + const ValueType& value; + }; + } + } +} + +#endif // _IGNITE_IMPL_THIN_WRITABLE http://git-wip-us.apache.org/repos/asf/ignite/blob/ed658597/modules/platforms/cpp/thin-client/include/ignite/impl/thin/writable_key.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/thin-client/include/ignite/impl/thin/writable_key.h b/modules/platforms/cpp/thin-client/include/ignite/impl/thin/writable_key.h new file mode 100644 index 0000000..bf16fd1 --- /dev/null +++ b/modules/platforms/cpp/thin-client/include/ignite/impl/thin/writable_key.h @@ -0,0 +1,681 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _IGNITE_IMPL_THIN_WRITABLE_KEY +#define _IGNITE_IMPL_THIN_WRITABLE_KEY + +#include <ignite/common/decimal.h> + +#include <ignite/impl/binary/binary_writer_impl.h> + +#include <ignite/impl/thin/writable.h> + +namespace ignite +{ + namespace impl + { + namespace thin + { + /** + * Abstraction to any type that can be written to a binary stream. + */ + class WritableKey : public Writable + { + public: + /** + * Destructor. + */ + virtual ~WritableKey() + { + // No-op. + } + + /** + * Get hash code of the value. + * + * @return Hash code of the value. + */ + virtual int32_t GetHashCode() const = 0; + }; + + /** + * Implementation of the Writable class for a user type. + */ + template<typename T> + class WritableKeyImpl : public WritableKey + { + public: + enum { BUFFER_SIZE = 1024 }; + + /** Value type. */ + typedef T ValueType; + + /** + * Constructor. + * + * @param value Value. + */ + WritableKeyImpl(const ValueType& value) : + value(value), + mem(BUFFER_SIZE) + { + // No-op. + } + + /** + * Destructor. + */ + virtual ~WritableKeyImpl() + { + // No-op. + } + + /** + * Write value using writer. + * + * @param writer Writer to use. + */ + virtual void Write(binary::BinaryWriterImpl& writer) const + { + if (mem.Length() == 0) + { + writer.WriteObject(value); + } + else + { + interop::InteropOutputStream *stream = writer.GetStream(); + + stream->WriteInt8Array(mem.Data(), mem.Length()); + } + } + + /** + * Get hash code of the value. + * + * @return Hash code of the value. + */ + virtual int32_t GetHashCode() const + { + if (mem.Length() == 0) + { + interop::InteropOutputStream stream(&mem); + binary::BinaryWriterImpl writer(&stream, 0); + + writer.WriteObject(value); + + stream.Synchronize(); + } + + binary::BinaryObjectImpl binaryKey(mem, 0, 0, 0); + + return binaryKey.GetHashCode(); + } + + private: + /** Value. */ + const ValueType& value; + + /** Memory. */ + mutable interop::InteropUnpooledMemory mem; + }; + + /** + * Implementation of the Writable class for an basic type. + */ + template<typename T> + class WritableBasicKeyImpl : public WritableKey + { + public: + /** Value type. */ + typedef T ValueType; + + /** + * Constructor. + * + * @param value Value. + */ + WritableBasicKeyImpl(const ValueType& value) : + value(value) + { + // No-op. + } + + /** + * Destructor. + */ + virtual ~WritableBasicKeyImpl() + { + // No-op. + } + + /** + * Write value using writer. + * + * @param writer Writer to use. + */ + virtual void Write(binary::BinaryWriterImpl& writer) const + { + writer.WriteObject(value); + } + + protected: + /** Value. */ + const ValueType& value; + }; + + /** + * Specializatoin for int8_t type. + */ + template<> + class WritableKeyImpl<int8_t> : public WritableBasicKeyImpl<int8_t> + { + public: + /** + * Constructor. + * + * @param value Value. + */ + WritableKeyImpl(const int8_t& value) : + WritableBasicKeyImpl(value) + { + // No-op. + } + + /** + * Destructor. + */ + virtual ~WritableKeyImpl() + { + // No-op. + } + + /** + * Get hash code of the value. + * + * @return Hash code of the value. + */ + virtual int32_t GetHashCode() const + { + return static_cast<int32_t>(value); + } + }; + + /** + * Specializatoin for int16_t type. + */ + template<> + class WritableKeyImpl<int16_t> : public WritableBasicKeyImpl<int16_t> + { + public: + /** + * Constructor. + * + * @param value Value. + */ + WritableKeyImpl(const int16_t& value) : + WritableBasicKeyImpl(value) + { + // No-op. + } + + /** + * Destructor. + */ + virtual ~WritableKeyImpl() + { + // No-op. + } + + /** + * Get hash code of the value. + * + * @return Hash code of the value. + */ + virtual int32_t GetHashCode() const + { + return static_cast<int32_t>(value); + } + }; + + /** + * Specializatoin for int32_t type. + */ + template<> + class WritableKeyImpl<int32_t> : public WritableBasicKeyImpl<int32_t> + { + public: + /** + * Constructor. + * + * @param value Value. + */ + WritableKeyImpl(const int32_t& value) : + WritableBasicKeyImpl(value) + { + // No-op. + } + + /** + * Destructor. + */ + virtual ~WritableKeyImpl() + { + // No-op. + } + + /** + * Get hash code of the value. + * + * @return Hash code of the value. + */ + virtual int32_t GetHashCode() const + { + return value; + } + }; + + /** + * Specializatoin for uint16_t type. + */ + template<> + class WritableKeyImpl<uint16_t> : public WritableBasicKeyImpl<uint16_t> + { + public: + /** + * Constructor. + * + * @param value Value. + */ + WritableKeyImpl(const uint16_t& value) : + WritableBasicKeyImpl(value) + { + // No-op. + } + + /** + * Destructor. + */ + virtual ~WritableKeyImpl() + { + // No-op. + } + + /** + * Get hash code of the value. + * + * @return Hash code of the value. + */ + virtual int32_t GetHashCode() const + { + return static_cast<int32_t>(value); + } + }; + + /** + * Specializatoin for boolean type. + */ + template<> + class WritableKeyImpl<bool> : public WritableBasicKeyImpl<bool> + { + public: + /** + * Constructor. + * + * @param value Value. + */ + WritableKeyImpl(const bool& value) : + WritableBasicKeyImpl(value) + { + // No-op. + } + + /** + * Destructor. + */ + virtual ~WritableKeyImpl() + { + // No-op. + } + + /** + * Get hash code of the value. + * + * @return Hash code of the value. + */ + virtual int32_t GetHashCode() const + { + return value ? 1231 : 1237; + } + }; + + /** + * Specializatoin for int64_t type. + */ + template<> + class WritableKeyImpl<int64_t> : public WritableBasicKeyImpl<int64_t> + { + public: + /** + * Constructor. + * + * @param value Value. + */ + WritableKeyImpl(const int64_t& value) : + WritableBasicKeyImpl(value) + { + // No-op. + } + + /** + * Destructor. + */ + virtual ~WritableKeyImpl() + { + // No-op. + } + + /** + * Get hash code of the value. + * + * @return Hash code of the value. + */ + virtual int32_t GetHashCode() const + { + return static_cast<int32_t>(value ^ ((value >> 32) & 0xFFFFFFFF)); + } + }; + + /** + * Specializatoin for float type. + */ + template<> + class WritableKeyImpl<float> : public WritableBasicKeyImpl<float> + { + public: + /** + * Constructor. + * + * @param value Value. + */ + WritableKeyImpl(const float& value) : + WritableBasicKeyImpl(value) + { + // No-op. + } + + /** + * Destructor. + */ + virtual ~WritableKeyImpl() + { + // No-op. + } + + /** + * Get hash code of the value. + * + * @return Hash code of the value. + */ + virtual int32_t GetHashCode() const + { + const int32_t *res = reinterpret_cast<const int32_t*>(&value); + + return *res; + } + }; + + /** + * Specializatoin for double type. + */ + template<> + class WritableKeyImpl<double> : public WritableBasicKeyImpl<double> + { + public: + /** + * Constructor. + * + * @param value Value. + */ + WritableKeyImpl(const double& value) : + WritableBasicKeyImpl(value) + { + // No-op. + } + + /** + * Destructor. + */ + virtual ~WritableKeyImpl() + { + // No-op. + } + + /** + * Get hash code of the value. + * + * @return Hash code of the value. + */ + virtual int32_t GetHashCode() const + { + const int64_t *res = reinterpret_cast<const int64_t*>(&value); + + return static_cast<int32_t>(*res ^ ((*res >> 32) & 0xFFFFFFFF)); + } + }; + + /** + * Specializatoin for std::string type. + */ + template<> + class WritableKeyImpl<std::string> : public WritableBasicKeyImpl<std::string> + { + public: + /** + * Constructor. + * + * @param value Value. + */ + WritableKeyImpl(const std::string& value) : + WritableBasicKeyImpl(value) + { + // No-op. + } + + /** + * Destructor. + */ + virtual ~WritableKeyImpl() + { + // No-op. + } + + /** + * Get hash code of the value. + * + * @return Hash code of the value. + */ + virtual int32_t GetHashCode() const + { + int32_t hash = 0; + + for (size_t i = 0; i < value.size(); ++i) + hash = 31 * hash + value[i]; + + return hash; + } + }; + + /** + * Specializatoin for Guid type. + */ + template<> + class WritableKeyImpl<Guid> : public WritableBasicKeyImpl<Guid> + { + public: + /** + * Constructor. + * + * @param value Value. + */ + WritableKeyImpl(const Guid& value) : + WritableBasicKeyImpl(value) + { + // No-op. + } + + /** + * Destructor. + */ + virtual ~WritableKeyImpl() + { + // No-op. + } + + /** + * Get hash code of the value. + * + * @return Hash code of the value. + */ + virtual int32_t GetHashCode() const + { + int64_t hilo = value.GetMostSignificantBits() ^ value.GetLeastSignificantBits(); + + return static_cast<int32_t>(hilo ^ ((hilo >> 32) & 0xFFFFFFFF)); + } + }; + + /** + * Specializatoin for Date type. + */ + template<> + class WritableKeyImpl<Date> : public WritableBasicKeyImpl<Date> + { + public: + /** + * Constructor. + * + * @param value Value. + */ + WritableKeyImpl(const Date& value) : + WritableBasicKeyImpl(value) + { + // No-op. + } + + /** + * Destructor. + */ + virtual ~WritableKeyImpl() + { + // No-op. + } + + /** + * Get hash code of the value. + * + * @return Hash code of the value. + */ + virtual int32_t GetHashCode() const + { + int64_t ht = value.GetMilliseconds(); + + return static_cast<int32_t>(ht ^ ((ht >> 32) & 0xFFFFFFFF)); + } + }; + + /** + * Specializatoin for Timestamp type. + */ + template<> + class WritableKeyImpl<Timestamp> : public WritableBasicKeyImpl<Timestamp> + { + public: + /** + * Constructor. + * + * @param value Value. + */ + WritableKeyImpl(const Timestamp& value) : + WritableBasicKeyImpl(value) + { + // No-op. + } + + /** + * Destructor. + */ + virtual ~WritableKeyImpl() + { + // No-op. + } + + /** + * Get hash code of the value. + * + * @return Hash code of the value. + */ + virtual int32_t GetHashCode() const + { + int64_t ht = value.GetMilliseconds(); + + return static_cast<int32_t>(ht ^ ((ht >> 32) & 0xFFFFFFFF)); + } + }; + + /** + * Specializatoin for Time type. + */ + template<> + class WritableKeyImpl<Time> : public WritableBasicKeyImpl<Time> + { + public: + /** + * Constructor. + * + * @param value Value. + */ + WritableKeyImpl(const Time& value) : + WritableBasicKeyImpl(value) + { + // No-op. + } + + /** + * Destructor. + */ + virtual ~WritableKeyImpl() + { + // No-op. + } + + /** + * Get hash code of the value. + * + * @return Hash code of the value. + */ + virtual int32_t GetHashCode() const + { + int64_t ht = value.GetMilliseconds(); + + return static_cast<int32_t>(ht ^ ((ht >> 32) & 0xFFFFFFFF)); + } + }; + } + } +} + +#endif // _IGNITE_IMPL_THIN_WRITABLE_KEY http://git-wip-us.apache.org/repos/asf/ignite/blob/ed658597/modules/platforms/cpp/thin-client/include/ignite/thin/cache/cache_client.h ---------------------------------------------------------------------- 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 new file mode 100644 index 0000000..1719c07 --- /dev/null +++ b/modules/platforms/cpp/thin-client/include/ignite/thin/cache/cache_client.h @@ -0,0 +1,225 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Declares ignite::thin::cache::CacheClient. + */ + +#ifndef _IGNITE_THIN_CACHE_CACHE_CLIENT +#define _IGNITE_THIN_CACHE_CACHE_CLIENT + +#include <ignite/common/concurrent.h> + +#include <ignite/impl/thin/writable.h> +#include <ignite/impl/thin/writable_key.h> +#include <ignite/impl/thin/readable.h> + +#include <ignite/impl/thin/cache/cache_client_proxy.h> + +namespace ignite +{ + namespace thin + { + namespace cache + { + /** + * Cache client class template. + * + * Main entry point for all Data Grid APIs. + * + * Both key and value types should be default-constructable, copy-constructable and assignable. Also + * BinaryType class template should be specialized for both types, if they are not one of the basic types. + * + * This class implemented as a reference to an implementation so copying of this class instance will only + * create another reference to the same underlying object. Underlying object released automatically once all + * the instances are destructed. + * + * @tparam K Cache key type. + * @tparam V Cache value type. + */ + template<typename K, typename V> + class CacheClient + { + friend class impl::thin::cache::CacheClientProxy; + + public: + /** Key type. */ + typedef K KeyType; + + /** Value type. */ + typedef V ValueType; + + /** + * Constructor. + * + * @param impl Implementation. + */ + CacheClient(common::concurrent::SharedPointer<void> impl) : + proxy(impl) + { + // No-op. + } + + /** + * Destructor. + */ + ~CacheClient() + { + // No-op. + } + + /** + * Associate the specified value with the specified key in the cache. + * + * @param key Key. + * @param value Value. + */ + void Put(const KeyType& key, const ValueType& value) + { + impl::thin::WritableKeyImpl<KeyType> wrKey(key); + impl::thin::WritableImpl<ValueType> wrValue(value); + + proxy.Put(wrKey, wrValue); + } + + /** + * Get value from the cache. + * + * @param key Key. + * @param value Value. + */ + void Get(const KeyType& key, ValueType& value) + { + impl::thin::WritableKeyImpl<KeyType> wrKey(key); + impl::thin::ReadableImpl<ValueType> rdValue(value); + + proxy.Get(wrKey, rdValue); + } + + /** + * Get value from cache. + * + * @param key Key. + * @return Value. + */ + ValueType Get(const KeyType& key) + { + ValueType value; + + Get(key, value); + + return value; + } + + /** + * Check if the cache contains a value for the specified key. + * + * @param key Key whose presence in this cache is to be tested. + * @return @c true if the cache contains specified key. + */ + bool ContainsKey(const KeyType& key) + { + impl::thin::WritableKeyImpl<KeyType> wrKey(key); + + return proxy.ContainsKey(wrKey); + } + + /** + * Gets the number of all entries cached across all nodes. + * @note This operation is distributed and will query all participating nodes for their cache sizes. + * + * @see CachePeekMode for details. + * + * @param peekModes Peek modes mask. + * @return Cache size across all nodes. + */ + int64_t GetSize(int32_t peekModes) + { + return proxy.GetSize(peekModes); + } + + /** + * 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. + * This method is transactional and will enlist the entry into ongoing transaction if there is one. + * + * @param key Key whose mapping is to be removed from cache. + * @return False if there was no matching key. + */ + bool Remove(const KeyType& key) + { + impl::thin::WritableKeyImpl<KeyType> wrKey(key); + + return proxy.Remove(wrKey); + } + + /** + * Removes all mappings from cache. + * If write-through is enabled, the value will be removed from store. + * This method is transactional and will enlist the entry into ongoing transaction if there is one. + */ + void RemoveAll() + { + proxy.RemoveAll(); + } + + /** + * Clear entry from the cache and swap storage, without notifying listeners or CacheWriters. + * Entry is cleared only if it is not currently locked, and is not participating in a transaction. + * + * @param key Key to clear. + */ + void Clear(const KeyType& key) + { + impl::thin::WritableKeyImpl<KeyType> wrKey(key); + + proxy.Clear(wrKey); + } + + /** + * Clear cache. + */ + void Clear() + { + proxy.Clear(); + } + + /** + * Refresh affinity mapping. + * + * TODO + */ + void RefreshAffinityMapping() + { + proxy.RefreshAffinityMapping(); + } + + private: + /** Implementation. */ + impl::thin::cache::CacheClientProxy proxy; + }; + } + } +} + +#endif // _IGNITE_THIN_CACHE_CACHE_CLIENT