http://git-wip-us.apache.org/repos/asf/ignite/blob/97b91e9c/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs index c456592..083038a 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTest.cs @@ -23,6 +23,7 @@ namespace Apache.Ignite.Core.Tests.Client.Cache using System.Linq; using System.Threading; using Apache.Ignite.Core.Binary; + using Apache.Ignite.Core.Cache; using Apache.Ignite.Core.Client; using Apache.Ignite.Core.Impl.Client; using NUnit.Framework; @@ -58,6 +59,11 @@ namespace Apache.Ignite.Core.Tests.Client.Cache // Null key. Assert.Throws<ArgumentNullException>(() => clientCache.Get(null)); + + // Null vs 0. + var intCache = client.GetCache<int?, int?>(CacheName); + intCache.Put(1, 0); + Assert.AreEqual(0, intCache.Get(1)); } } @@ -78,7 +84,7 @@ namespace Apache.Ignite.Core.Tests.Client.Cache { var person = new Person {Id = 100, Name = "foo"}; var person2 = new Person2 {Id = 200, Name = "bar"}; - + var serverCache = GetCache<Person>(); var clientCache = client.GetCache<int?, Person>(CacheName); @@ -110,6 +116,604 @@ namespace Apache.Ignite.Core.Tests.Client.Cache } /// <summary> + /// Tests the TryGet method. + /// </summary> + [Test] + public void TestTryGet() + { + using (var client = GetClient()) + { + var cache = client.GetCache<int?, int>(CacheName); + + cache[1] = 0; + cache[2] = 2; + + // Non-existent key. + int res; + var success = cache.TryGet(0, out res); + + Assert.AreEqual(0, res); + Assert.IsFalse(success); + + // Key with default value. + success = cache.TryGet(1, out res); + + Assert.AreEqual(0, res); + Assert.IsTrue(success); + + // Key with custom value. + success = cache.TryGet(2, out res); + + Assert.AreEqual(2, res); + Assert.IsTrue(success); + + // Null key. + Assert.Throws<ArgumentNullException>(() => cache.TryGet(null, out res)); + } + } + + /// <summary> + /// Tests the GetAll method. + /// </summary> + [Test] + public void TestGetAll() + { + using (var client = GetClient()) + { + var cache = client.GetCache<int?, int>(CacheName); + + cache[1] = 1; + cache[2] = 2; + cache[3] = 3; + + var res = cache.GetAll(new int?[] {1}).Single(); + Assert.AreEqual(1, res.Key); + Assert.AreEqual(1, res.Value); + + res = cache.GetAll(new int?[] {1, -1}).Single(); + Assert.AreEqual(1, res.Key); + Assert.AreEqual(1, res.Value); + + CollectionAssert.AreEquivalent(new[] {1, 2, 3}, + cache.GetAll(new int?[] {1, 2, 3}).Select(x => x.Value)); + + Assert.Throws<ArgumentNullException>(() => cache.GetAll(null)); + + Assert.Throws<IgniteClientException>(() => cache.GetAll(new int?[] {1, null})); + Assert.Throws<IgniteClientException>(() => cache.GetAll(new int?[] {null})); + } + } + + /// <summary> + /// Tests the GetAndPut method. + /// </summary> + [Test] + public void TestGetAndPut() + { + using (var client = GetClient()) + { + var cache = client.GetCache<int?, int?>(CacheName); + + Assert.IsFalse(cache.ContainsKey(1)); + + var res = cache.GetAndPut(1, 1); + Assert.IsFalse(res.Success); + Assert.IsNull(res.Value); + + Assert.IsTrue(cache.ContainsKey(1)); + + res = cache.GetAndPut(1, 2); + Assert.IsTrue(res.Success); + Assert.AreEqual(1, res.Value); + + Assert.AreEqual(2, cache[1]); + + Assert.Throws<ArgumentNullException>(() => cache.GetAndPut(1, null)); + Assert.Throws<ArgumentNullException>(() => cache.GetAndPut(null, 1)); + } + } + + /// <summary> + /// Tests the GetAndReplace method. + /// </summary> + [Test] + public void TestGetAndReplace() + { + using (var client = GetClient()) + { + var cache = client.GetCache<int?, int?>(CacheName); + + Assert.IsFalse(cache.ContainsKey(1)); + + var res = cache.GetAndReplace(1, 1); + Assert.IsFalse(res.Success); + Assert.IsNull(res.Value); + + Assert.IsFalse(cache.ContainsKey(1)); + cache[1] = 1; + + res = cache.GetAndReplace(1, 2); + Assert.IsTrue(res.Success); + Assert.AreEqual(1, res.Value); + + Assert.AreEqual(2, cache[1]); + + Assert.Throws<ArgumentNullException>(() => cache.GetAndReplace(1, null)); + Assert.Throws<ArgumentNullException>(() => cache.GetAndReplace(null, 1)); + } + } + + /// <summary> + /// Tests the GetAndRemove method. + /// </summary> + [Test] + public void TestGetAndRemove() + { + using (var client = GetClient()) + { + var cache = client.GetCache<int?, int?>(CacheName); + + Assert.IsFalse(cache.ContainsKey(1)); + + var res = cache.GetAndRemove(1); + Assert.IsFalse(res.Success); + Assert.IsNull(res.Value); + + Assert.IsFalse(cache.ContainsKey(1)); + cache[1] = 1; + + res = cache.GetAndRemove(1); + Assert.IsTrue(res.Success); + Assert.AreEqual(1, res.Value); + + Assert.IsFalse(cache.ContainsKey(1)); + + Assert.Throws<ArgumentNullException>(() => cache.GetAndRemove(null)); + } + } + + /// <summary> + /// Tests the ContainsKey method. + /// </summary> + [Test] + public void TestContainsKey() + { + using (var client = GetClient()) + { + var cache = client.GetCache<int?, int>(CacheName); + + cache[1] = 1; + + Assert.IsTrue(cache.ContainsKey(1)); + Assert.IsFalse(cache.ContainsKey(2)); + + Assert.Throws<ArgumentNullException>(() => cache.ContainsKey(null)); + } + } + + /// <summary> + /// Tests the ContainsKeys method. + /// </summary> + [Test] + public void TestContainsKeys() + { + using (var client = GetClient()) + { + var cache = client.GetCache<int, int>(CacheName); + + cache[1] = 1; + cache[2] = 2; + cache[3] = 3; + + Assert.IsTrue(cache.ContainsKeys(new[] {1})); + Assert.IsTrue(cache.ContainsKeys(new[] {1, 2})); + Assert.IsTrue(cache.ContainsKeys(new[] {2, 1})); + Assert.IsTrue(cache.ContainsKeys(new[] {1, 2, 3})); + Assert.IsTrue(cache.ContainsKeys(new[] {1, 3, 2})); + + Assert.IsFalse(cache.ContainsKeys(new[] {0})); + Assert.IsFalse(cache.ContainsKeys(new[] {0, 1})); + Assert.IsFalse(cache.ContainsKeys(new[] {1, 0})); + Assert.IsFalse(cache.ContainsKeys(new[] {1, 2, 3, 0})); + + Assert.Throws<ArgumentNullException>(() => cache.ContainsKeys(null)); + } + } + + /// <summary> + /// Tests the PutIfAbsent method. + /// </summary> + [Test] + public void TestPutIfAbsent() + { + using (var client = GetClient()) + { + var cache = client.GetCache<int?, int?>(CacheName); + + Assert.IsFalse(cache.ContainsKey(1)); + + var res = cache.PutIfAbsent(1, 1); + Assert.IsTrue(res); + Assert.AreEqual(1, cache[1]); + + res = cache.PutIfAbsent(1, 2); + Assert.IsFalse(res); + Assert.AreEqual(1, cache[1]); + + Assert.Throws<ArgumentNullException>(() => cache.PutIfAbsent(null, 1)); + Assert.Throws<ArgumentNullException>(() => cache.PutIfAbsent(1, null)); + } + } + + /// <summary> + /// Tests the GetAndPutIfAbsent method. + /// </summary> + [Test] + public void TestGetAndPutIfAbsent() + { + using (var client = GetClient()) + { + var cache = client.GetCache<int?, int?>(CacheName); + + Assert.IsFalse(cache.ContainsKey(1)); + + var res = cache.GetAndPutIfAbsent(1, 1); + Assert.IsFalse(res.Success); + Assert.IsNull(res.Value); + Assert.AreEqual(1, cache[1]); + + res = cache.GetAndPutIfAbsent(1, 2); + Assert.IsTrue(res.Success); + Assert.AreEqual(1, res.Value); + Assert.AreEqual(1, cache[1]); + + Assert.Throws<ArgumentNullException>(() => cache.GetAndPutIfAbsent(null, 1)); + Assert.Throws<ArgumentNullException>(() => cache.GetAndPutIfAbsent(1, null)); + } + } + + /// <summary> + /// Tests the Replace method. + /// </summary> + [Test] + public void TestReplace() + { + using (var client = GetClient()) + { + var cache = client.GetCache<int?, int?>(CacheName); + + Assert.IsFalse(cache.ContainsKey(1)); + + var res = cache.Replace(1, 1); + Assert.IsFalse(res); + Assert.IsFalse(cache.ContainsKey(1)); + + cache[1] = 1; + + res = cache.Replace(1, 2); + Assert.IsTrue(res); + Assert.AreEqual(2, cache[1]); + + Assert.Throws<ArgumentNullException>(() => cache.Replace(null, 1)); + Assert.Throws<ArgumentNullException>(() => cache.Replace(1, null)); + } + } + + /// <summary> + /// Tests the Replace overload with additional argument. + /// </summary> + [Test] + public void TestReplace2() + { + using (var client = GetClient()) + { + var cache = client.GetCache<int?, int?>(CacheName); + + Assert.IsFalse(cache.ContainsKey(1)); + + var res = cache.Replace(1, 1, 2); + Assert.IsFalse(res); + Assert.IsFalse(cache.ContainsKey(1)); + + cache[1] = 1; + + res = cache.Replace(1, -1, 2); + Assert.IsFalse(res); + Assert.AreEqual(1, cache[1]); + + res = cache.Replace(1, 1, 2); + Assert.IsTrue(res); + Assert.AreEqual(2, cache[1]); + + Assert.Throws<ArgumentNullException>(() => cache.Replace(null, 1, 1)); + Assert.Throws<ArgumentNullException>(() => cache.Replace(1, null, 1)); + Assert.Throws<ArgumentNullException>(() => cache.Replace(1, 1, null)); + } + } + + /// <summary> + /// Tests the PutAll method. + /// </summary> + [Test] + public void TestPutAll() + { + using (var client = GetClient()) + { + // Primitives. + var cache = client.GetCache<int?, int?>(CacheName); + + cache.PutAll(Enumerable.Range(1, 3).ToDictionary(x => (int?) x, x => (int?) x + 1)); + + Assert.AreEqual(2, cache[1]); + Assert.AreEqual(3, cache[2]); + Assert.AreEqual(4, cache[3]); + + // Objects. + var cache2 = client.GetCache<int, Container>(CacheName); + + var obj1 = new Container(); + var obj2 = new Container(); + var obj3 = new Container(); + + obj1.Inner = obj2; + obj2.Inner = obj1; + obj3.Inner = obj2; + + cache2.PutAll(new Dictionary<int, Container> + { + {1, obj1}, + {2, obj2}, + {3, obj3} + }); + + var res1 = cache2[1]; + var res2 = cache2[2]; + var res3 = cache2[3]; + + Assert.AreEqual(res1, res1.Inner.Inner); + Assert.AreEqual(res2, res2.Inner.Inner); + Assert.IsNotNull(res3.Inner.Inner.Inner); + + // Nulls. + Assert.Throws<ArgumentNullException>(() => cache.PutAll(null)); + + Assert.Throws<IgniteClientException>(() => cache.PutAll(new[] + { + new KeyValuePair<int?, int?>(null, 1) + })); + + Assert.Throws<IgniteClientException>(() => cache.PutAll(new[] + { + new KeyValuePair<int?, int?>(1, null) + })); + } + } + + /// <summary> + /// Tests the Clear method. + /// </summary> + [Test] + public void TestClear() + { + using (var client = GetClient()) + { + var cache = client.GetCache<int?, int?>(CacheName); + + cache[1] = 1; + cache[2] = 2; + + cache.Clear(); + + Assert.IsFalse(cache.ContainsKey(1)); + Assert.IsFalse(cache.ContainsKey(2)); + } + } + + /// <summary> + /// Tests the Clear method with a key argument. + /// </summary> + [Test] + public void TestClearKey() + { + using (var client = GetClient()) + { + var cache = client.GetCache<int?, int?>(CacheName); + + cache[1] = 1; + cache[2] = 2; + + cache.Clear(1); + Assert.IsFalse(cache.ContainsKey(1)); + Assert.IsTrue(cache.ContainsKey(2)); + + cache.Clear(2); + Assert.IsFalse(cache.ContainsKey(1)); + Assert.IsFalse(cache.ContainsKey(2)); + + Assert.Throws<ArgumentNullException>(() => cache.Clear(null)); + } + } + + /// <summary> + /// Tests the ClearAll method. + /// </summary> + [Test] + public void TestClearAll() + { + using (var client = GetClient()) + { + var cache = client.GetCache<int?, int?>(CacheName); + + cache[1] = 1; + cache[2] = 2; + cache[3] = 3; + + cache.ClearAll(new int?[] {1, 3}); + Assert.IsFalse(cache.ContainsKey(1)); + Assert.IsTrue(cache.ContainsKey(2)); + Assert.IsFalse(cache.ContainsKey(3)); + + Assert.Throws<ArgumentNullException>(() => cache.ClearAll(null)); + Assert.Throws<IgniteClientException>(() => cache.ClearAll(new int?[] {null, 1})); + } + } + + /// <summary> + /// Tests the Remove method. + /// </summary> + [Test] + public void TestRemove() + { + using (var client = GetClient()) + { + var cache = client.GetCache<int?, int?>(CacheName); + + cache[1] = 1; + cache[2] = 2; + + var res = cache.Remove(1); + Assert.IsTrue(res); + Assert.IsFalse(cache.ContainsKey(1)); + Assert.IsTrue(cache.ContainsKey(2)); + + res = cache.Remove(2); + Assert.IsTrue(res); + Assert.IsFalse(cache.ContainsKey(1)); + Assert.IsFalse(cache.ContainsKey(2)); + + res = cache.Remove(-1); + Assert.IsFalse(res); + + Assert.Throws<ArgumentNullException>(() => cache.Remove(null)); + } + } + + /// <summary> + /// Tests the Remove method with value argument. + /// </summary> + [Test] + public void TestRemoveKeyVal() + { + using (var client = GetClient()) + { + var cache = client.GetCache<int?, int?>(CacheName); + + cache[1] = 1; + cache[2] = 2; + + var res = cache.Remove(1, 0); + Assert.IsFalse(res); + + res = cache.Remove(0, 0); + Assert.IsFalse(res); + + res = cache.Remove(1, 1); + Assert.IsTrue(res); + Assert.IsFalse(cache.ContainsKey(1)); + Assert.IsTrue(cache.ContainsKey(2)); + + res = cache.Remove(2, 2); + Assert.IsTrue(res); + Assert.IsFalse(cache.ContainsKey(1)); + Assert.IsFalse(cache.ContainsKey(2)); + + res = cache.Remove(2, 2); + Assert.IsFalse(res); + + Assert.Throws<ArgumentNullException>(() => cache.Remove(1, null)); + Assert.Throws<ArgumentNullException>(() => cache.Remove(null, 1)); + } + } + + /// <summary> + /// Tests the RemoveAll with a set of keys. + /// </summary> + [Test] + public void TestRemoveReys() + { + using (var client = GetClient()) + { + var cache = client.GetCache<int?, int?>(CacheName); + var keys = Enumerable.Range(1, 10).Cast<int?>().ToArray(); + + cache.PutAll(keys.ToDictionary(x => x, x => x)); + + cache.RemoveAll(keys.Skip(2)); + CollectionAssert.AreEquivalent(keys.Take(2), cache.GetAll(keys).Select(x => x.Key)); + + cache.RemoveAll(new int?[] {1}); + Assert.AreEqual(2, cache.GetAll(keys).Single().Value); + + cache.RemoveAll(keys); + cache.RemoveAll(keys); + + Assert.AreEqual(0, cache.GetSize()); + + Assert.Throws<ArgumentNullException>(() => cache.RemoveAll(null)); + Assert.Throws<IgniteClientException>(() => cache.RemoveAll(new int?[] {1, null})); + } + } + + /// <summary> + /// Tests the RemoveAll method without argument. + /// </summary> + [Test] + public void TestRemoveAll() + { + using (var client = GetClient()) + { + var cache = client.GetCache<int, int>(CacheName); + + cache[1] = 1; + cache[2] = 2; + + cache.RemoveAll(); + + Assert.AreEqual(0, cache.GetSize()); + } + } + + /// <summary> + /// Tests the GetSize method. + /// </summary> + [Test] + public void TestGetSize() + { + using (var client = GetClient()) + { + var cache = client.GetCache<int, int>(CacheName); + + Assert.AreEqual(0, cache.GetSize()); + Assert.AreEqual(0, cache.GetSize(CachePeekMode.All)); + Assert.AreEqual(0, cache.GetSize(CachePeekMode.Backup)); + Assert.AreEqual(0, cache.GetSize(CachePeekMode.Near)); + Assert.AreEqual(0, cache.GetSize(CachePeekMode.Offheap)); + Assert.AreEqual(0, cache.GetSize(CachePeekMode.Onheap)); + Assert.AreEqual(0, cache.GetSize(CachePeekMode.Primary)); + + cache[1] = 1; + + Assert.AreEqual(1, cache.GetSize()); + Assert.AreEqual(1, cache.GetSize(CachePeekMode.All)); + Assert.AreEqual(0, cache.GetSize(CachePeekMode.Backup)); + Assert.AreEqual(0, cache.GetSize(CachePeekMode.Near)); + Assert.AreEqual(1, cache.GetSize(CachePeekMode.Offheap)); + Assert.AreEqual(0, cache.GetSize(CachePeekMode.Onheap)); + Assert.AreEqual(1, cache.GetSize(CachePeekMode.Primary)); + + cache.PutAll(Enumerable.Range(1, 100).ToDictionary(x => x, x => x)); + + Assert.AreEqual(100, cache.GetSize()); + Assert.AreEqual(100, cache.GetSize(CachePeekMode.All)); + Assert.AreEqual(0, cache.GetSize(CachePeekMode.Backup)); + Assert.AreEqual(0, cache.GetSize(CachePeekMode.Near)); + Assert.AreEqual(100, cache.GetSize(CachePeekMode.Offheap)); + Assert.AreEqual(0, cache.GetSize(CachePeekMode.Onheap)); + Assert.AreEqual(100, cache.GetSize(CachePeekMode.Primary)); + } + } + + /// <summary> /// Tests client get in multiple threads with a single client. /// </summary> [Test] @@ -170,5 +774,10 @@ namespace Apache.Ignite.Core.Tests.Client.Cache Assert.AreEqual((int) ClientStatus.CacheDoesNotExist, ex.ErrorCode); } } + + private class Container + { + public Container Inner; + } } }
http://git-wip-us.apache.org/repos/asf/ignite/blob/97b91e9c/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestNoMeta.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestNoMeta.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestNoMeta.cs index 6695835..782e3cc 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestNoMeta.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestNoMeta.cs @@ -52,7 +52,7 @@ namespace Apache.Ignite.Core.Tests.Client.Cache using (var client = Ignition.StartClient(cfg)) { var serverCache = Ignition.GetIgnite().GetOrCreateCache<int?, Person>( - new CacheConfiguration(CacheName, new QueryEntity + new CacheConfiguration("person", new QueryEntity { KeyType = typeof(int), ValueType = typeof(Person), @@ -63,7 +63,7 @@ namespace Apache.Ignite.Core.Tests.Client.Cache } })); - var clientCache = client.GetCache<int?, Person>(CacheName); + var clientCache = client.GetCache<int?, Person>(serverCache.Name); // Put through client cache. clientCache.Put(1, new Person { Id = 100, Name = "foo" }); http://git-wip-us.apache.org/repos/asf/ignite/blob/97b91e9c/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs index 81e1418..408eb73 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs @@ -76,6 +76,15 @@ namespace Apache.Ignite.Core.Tests.Client } /// <summary> + /// Sets up the test. + /// </summary> + [SetUp] + public void TestSetUp() + { + GetCache<int>().RemoveAll(); + } + + /// <summary> /// Gets the cache. /// </summary> protected static ICache<int, T> GetCache<T>() http://git-wip-us.apache.org/repos/asf/ignite/blob/97b91e9c/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs index edd411c..d772ba6 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs @@ -51,6 +51,25 @@ namespace Apache.Ignite.Core.Client.Cache TV Get(TK key); /// <summary> + /// Retrieves value mapped to the specified key from cache. + /// </summary> + /// <param name="key">Key.</param> + /// <param name="value">When this method returns, the value associated with the specified key, + /// if the key is found; otherwise, the default value for the type of the value parameter. + /// This parameter is passed uninitialized.</param> + /// <returns> + /// true if the cache contains an element with the specified key; otherwise, false. + /// </returns> + bool TryGet(TK key, out TV value); + + /// <summary> + /// Retrieves values mapped to the specified keys from cache. + /// </summary> + /// <param name="keys">Keys.</param> + /// <returns>Map of key-value pairs.</returns> + ICollection<ICacheEntry<TK, TV>> GetAll(IEnumerable<TK> keys); + + /// <summary> /// Gets or sets a cache value with the specified key. /// Shortcut to <see cref="Get"/> and <see cref="Put"/> /// </summary> @@ -60,10 +79,146 @@ namespace Apache.Ignite.Core.Client.Cache TV this[TK key] { get; set; } /// <summary> + /// Check if cache contains mapping for this key. + /// </summary> + /// <param name="key">Key.</param> + /// <returns>True if cache contains mapping for this key.</returns> + bool ContainsKey(TK key); + + /// <summary> + /// Check if cache contains mapping for these keys. + /// </summary> + /// <param name="keys">Keys.</param> + /// <returns>True if cache contains mapping for all these keys.</returns> + bool ContainsKeys(IEnumerable<TK> keys); + + /// <summary> /// Executes a Scan query. /// </summary> /// <param name="scanQuery">Scan query.</param> /// <returns>Query cursor.</returns> IQueryCursor<ICacheEntry<TK, TV>> Query(ScanQuery<TK, TV> scanQuery); + + /// <summary> + /// Associates the specified value with the specified key in this cache, + /// returning an existing value if one existed. + /// </summary> + /// <param name="key">Key with which the specified value is to be associated.</param> + /// <param name="val">Value to be associated with the specified key.</param> + /// <returns> + /// The value associated with the key at the start of the operation. + /// </returns> + CacheResult<TV> GetAndPut(TK key, TV val); + + /// <summary> + /// Atomically replaces the value for a given key if and only if there is a value currently mapped by the key. + /// </summary> + /// <param name="key">Key with which the specified value is to be associated.</param> + /// <param name="val">Value to be associated with the specified key.</param> + /// <returns> + /// The previous value associated with the specified key. + /// </returns> + CacheResult<TV> GetAndReplace(TK key, TV val); + + /// <summary> + /// Atomically removes the entry for a key only if currently mapped to some value. + /// </summary> + /// <param name="key">Key with which the specified value is associated.</param> + /// <returns>The value if one existed.</returns> + CacheResult<TV> GetAndRemove(TK key); + + /// <summary> + /// Atomically associates the specified key with the given value if it is not already associated with a value. + /// </summary> + /// <param name="key">Key with which the specified value is to be associated.</param> + /// <param name="val">Value to be associated with the specified key.</param> + /// <returns>True if a value was set.</returns> + bool PutIfAbsent(TK key, TV val); + + /// <summary> + /// Stores given key-value pair in cache only if cache had no previous mapping for it. + /// </summary> + /// <param name="key">Key to store in cache.</param> + /// <param name="val">Value to be associated with the given key.</param> + /// <returns> + /// Previously contained value regardless of whether put happened or not. + /// </returns> + CacheResult<TV> GetAndPutIfAbsent(TK key, TV val); + + /// <summary> + /// Stores given key-value pair in cache only if there is a previous mapping for it. + /// </summary> + /// <param name="key">Key to store in cache.</param> + /// <param name="val">Value to be associated with the given key.</param> + /// <returns>True if the value was replaced.</returns> + bool Replace(TK key, TV val); + + /// <summary> + /// Stores given key-value pair in cache only if only if the previous value is equal to the + /// old value passed as argument. + /// </summary> + /// <param name="key">Key to store in cache.</param> + /// <param name="oldVal">Old value to match.</param> + /// <param name="newVal">Value to be associated with the given key.</param> + /// <returns>True if replace happened, false otherwise.</returns> + bool Replace(TK key, TV oldVal, TV newVal); + + /// <summary> + /// Stores given key-value pairs in cache. + /// </summary> + /// <param name="vals">Key-value pairs to store in cache.</param> + void PutAll(IEnumerable<KeyValuePair<TK, TV>> vals); + + /// <summary> + /// Clears the contents of the cache, without notifying listeners or CacheWriters. + /// </summary> + void Clear(); + + /// <summary> + /// Clear entry from the cache, without notifying listeners or CacheWriters. + /// </summary> + /// <param name="key">Key to clear.</param> + void Clear(TK key); + + /// <summary> + /// Clear entries from the cache, without notifying listeners or CacheWriters. + /// </summary> + /// <param name="keys">Keys to clear.</param> + void ClearAll(IEnumerable<TK> keys); + + /// <summary> + /// Removes given key mapping from cache, notifying listeners and cache writers. + /// </summary> + /// <param name="key">Key to remove.</param> + /// <returns>True if entry was removed, false otherwise.</returns> + bool Remove(TK key); + + /// <summary> + /// Removes given key mapping from cache if one exists and value is equal to the passed in value. + /// </summary> + /// <param name="key">Key whose mapping is to be removed from cache.</param> + /// <param name="val">Value to match against currently cached value.</param> + /// <returns>True if entry was removed, false otherwise.</returns> + bool Remove(TK key, TV val); + + /// <summary> + /// Removes given key mappings from cache, notifying listeners and cache writers. + /// </summary> + /// <param name="keys">Keys to be removed from cache.</param> + void RemoveAll(IEnumerable<TK> keys); + + /// <summary> + /// Removes all mappings from cache, notifying listeners and cache writers. + /// </summary> + void RemoveAll(); + + /// <summary> + /// Gets the number of all entries cached across all nodes. + /// <para /> + /// NOTE: this operation is distributed and will query all participating nodes for their cache sizes. + /// </summary> + /// <param name="modes">Optional peek modes. If not provided, then total cache size is returned.</param> + /// <returns>Cache size across all nodes.</returns> + long GetSize(params CachePeekMode[] modes); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/97b91e9c/modules/platforms/dotnet/Apache.Ignite.Core/Client/IgniteClientException.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Client/IgniteClientException.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Client/IgniteClientException.cs index a20bec3..2df3d1b 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Client/IgniteClientException.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/IgniteClientException.cs @@ -104,5 +104,13 @@ namespace Apache.Ignite.Core.Client info.AddValue(ErrorCodeField, _errorCode); } + + /// <summary> + /// Returns a <see cref="string" /> that represents this instance. + /// </summary> + public override string ToString() + { + return string.Format("{0} [ErrorCode={1}]", base.ToString(), ErrorCode); + } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/97b91e9c/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs index 9d45f50..ca9fb63 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs @@ -342,7 +342,7 @@ namespace Apache.Ignite.Core.Impl.Cache w => { w.WriteObjectDetached(key); - w.WriteInt(EncodePeekModes(modes)); + w.WriteInt(IgniteUtils.EncodePeekModes(modes)); }, (s, r) => r == True ? new CacheResult<TV>(Unmarshal<TV>(s)) : new CacheResult<TV>(), _readException); @@ -808,7 +808,7 @@ namespace Apache.Ignite.Core.Impl.Cache /** <inheritDoc /> */ public Task<int> GetSizeAsync(params CachePeekMode[] modes) { - var modes0 = EncodePeekModes(modes); + var modes0 = IgniteUtils.EncodePeekModes(modes); return DoOutOpAsync<int>(CacheOp.SizeAsync, w => w.WriteInt(modes0)); } @@ -821,7 +821,7 @@ namespace Apache.Ignite.Core.Impl.Cache /// <returns>Size.</returns> private int Size0(bool loc, params CachePeekMode[] modes) { - var modes0 = EncodePeekModes(modes); + var modes0 = IgniteUtils.EncodePeekModes(modes); var op = loc ? CacheOp.SizeLoc : CacheOp.Size; @@ -1147,7 +1147,7 @@ namespace Apache.Ignite.Core.Impl.Cache /** <inheritdoc /> */ public IEnumerable<ICacheEntry<TK, TV>> GetLocalEntries(CachePeekMode[] peekModes) { - return new CacheEnumerable<TK, TV>(this, EncodePeekModes(peekModes)); + return new CacheEnumerable<TK, TV>(this, IgniteUtils.EncodePeekModes(peekModes)); } /** <inheritdoc /> */ @@ -1189,22 +1189,6 @@ namespace Apache.Ignite.Core.Impl.Cache } /// <summary> - /// Encodes the peek modes into a single int value. - /// </summary> - private static int EncodePeekModes(CachePeekMode[] modes) - { - int modesEncoded = 0; - - if (modes != null) - { - foreach (var mode in modes) - modesEncoded |= (int) mode; - } - - return modesEncoded; - } - - /// <summary> /// Reads results of InvokeAll operation. /// </summary> /// <typeparam name="T">The type of the result.</typeparam> http://git-wip-us.apache.org/repos/asf/ignite/blob/97b91e9c/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheClient.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheClient.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheClient.cs index 5492ef8..be6e7da 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheClient.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheClient.cs @@ -21,6 +21,7 @@ namespace Apache.Ignite.Core.Impl.Client.Cache using System.Collections.Generic; using System.Diagnostics; using System.IO; + using Apache.Ignite.Core.Binary; using Apache.Ignite.Core.Cache; using Apache.Ignite.Core.Cache.Query; using Apache.Ignite.Core.Client; @@ -54,7 +55,7 @@ namespace Apache.Ignite.Core.Impl.Client.Cache private readonly Marshaller _marsh; /** Keep binary flag. */ - private bool _keepBinary = false; + private readonly bool _keepBinary = false; /// <summary> /// Initializes a new instance of the <see cref="CacheClient{TK, TV}" /> class. @@ -94,6 +95,39 @@ namespace Apache.Ignite.Core.Impl.Client.Cache } /** <inheritDoc /> */ + public bool TryGet(TK key, out TV value) + { + IgniteArgumentCheck.NotNull(key, "key"); + + var res = DoOutInOp(ClientOp.CacheGet, w => w.WriteObject(key), UnmarshalCacheResult<TV>); + + value = res.Value; + + return res.Success; + } + + /** <inheritDoc /> */ + public ICollection<ICacheEntry<TK, TV>> GetAll(IEnumerable<TK> keys) + { + IgniteArgumentCheck.NotNull(keys, "keys"); + + return DoOutInOp(ClientOp.CacheGetAll, w => w.WriteEnumerable(keys), stream => + { + var reader = _marsh.StartUnmarshal(stream, _keepBinary); + + var cnt = reader.ReadInt(); + var res = new List<ICacheEntry<TK, TV>>(cnt); + + for (var i = 0; i < cnt; i++) + { + res.Add(new CacheEntry<TK, TV>(reader.ReadObject<TK>(), reader.ReadObject<TV>())); + } + + return res; + }); + } + + /** <inheritDoc /> */ public void Put(TK key, TV val) { IgniteArgumentCheck.NotNull(key, "key"); @@ -107,6 +141,22 @@ namespace Apache.Ignite.Core.Impl.Client.Cache } /** <inheritDoc /> */ + public bool ContainsKey(TK key) + { + IgniteArgumentCheck.NotNull(key, "key"); + + return DoOutInOp(ClientOp.CacheContainsKey, w => w.WriteObjectDetached(key), r => r.ReadBool()); + } + + /** <inheritDoc /> */ + public bool ContainsKeys(IEnumerable<TK> keys) + { + IgniteArgumentCheck.NotNull(keys, "keys"); + + return DoOutInOp(ClientOp.CacheContainsKeys, w => w.WriteEnumerable(keys), r => r.ReadBool()); + } + + /** <inheritDoc /> */ public IQueryCursor<ICacheEntry<TK, TV>> Query(ScanQuery<TK, TV> scanQuery) { IgniteArgumentCheck.NotNull(scanQuery, "query"); @@ -116,6 +166,166 @@ namespace Apache.Ignite.Core.Impl.Client.Cache return DoOutInOp(ClientOp.QueryScan, w => WriteScanQuery(w, scanQuery), s => new ClientQueryCursor<TK, TV>(_ignite, s.ReadLong(), _keepBinary, s)); } + + /** <inheritDoc /> */ + public CacheResult<TV> GetAndPut(TK key, TV val) + { + IgniteArgumentCheck.NotNull(key, "key"); + IgniteArgumentCheck.NotNull(val, "val"); + + return DoOutInOp(ClientOp.CacheGetAndPut, w => + { + w.WriteObjectDetached(key); + w.WriteObjectDetached(val); + }, UnmarshalCacheResult<TV>); + } + + /** <inheritDoc /> */ + public CacheResult<TV> GetAndReplace(TK key, TV val) + { + IgniteArgumentCheck.NotNull(key, "key"); + IgniteArgumentCheck.NotNull(val, "val"); + + return DoOutInOp(ClientOp.CacheGetAndReplace, w => + { + w.WriteObjectDetached(key); + w.WriteObjectDetached(val); + }, UnmarshalCacheResult<TV>); + } + + /** <inheritDoc /> */ + public CacheResult<TV> GetAndRemove(TK key) + { + IgniteArgumentCheck.NotNull(key, "key"); + + return DoOutInOp(ClientOp.CacheGetAndRemove, w => w.WriteObjectDetached(key), + UnmarshalCacheResult<TV>); + } + + /** <inheritDoc /> */ + public bool PutIfAbsent(TK key, TV val) + { + IgniteArgumentCheck.NotNull(key, "key"); + IgniteArgumentCheck.NotNull(val, "val"); + + return DoOutInOp(ClientOp.CachePutIfAbsent, w => + { + w.WriteObjectDetached(key); + w.WriteObjectDetached(val); + }, s => s.ReadBool()); + } + + /** <inheritDoc /> */ + public CacheResult<TV> GetAndPutIfAbsent(TK key, TV val) + { + IgniteArgumentCheck.NotNull(key, "key"); + IgniteArgumentCheck.NotNull(val, "val"); + + return DoOutInOp(ClientOp.CacheGetAndPutIfAbsent, w => + { + w.WriteObjectDetached(key); + w.WriteObjectDetached(val); + }, UnmarshalCacheResult<TV>); + } + + /** <inheritDoc /> */ + public bool Replace(TK key, TV val) + { + IgniteArgumentCheck.NotNull(key, "key"); + IgniteArgumentCheck.NotNull(val, "val"); + + return DoOutInOp(ClientOp.CacheReplace, w => + { + w.WriteObjectDetached(key); + w.WriteObjectDetached(val); + }, s => s.ReadBool()); + } + + /** <inheritDoc /> */ + public bool Replace(TK key, TV oldVal, TV newVal) + { + IgniteArgumentCheck.NotNull(key, "key"); + IgniteArgumentCheck.NotNull(oldVal, "oldVal"); + IgniteArgumentCheck.NotNull(newVal, "newVal"); + + return DoOutInOp(ClientOp.CacheReplaceIfEquals, w => + { + w.WriteObjectDetached(key); + w.WriteObjectDetached(oldVal); + w.WriteObjectDetached(newVal); + }, s => s.ReadBool()); + } + + /** <inheritDoc /> */ + public void PutAll(IEnumerable<KeyValuePair<TK, TV>> vals) + { + IgniteArgumentCheck.NotNull(vals, "vals"); + + DoOutOp(ClientOp.CachePutAll, w => w.WriteDictionary(vals)); + } + + /** <inheritDoc /> */ + public void Clear() + { + DoOutOp(ClientOp.CacheClear); + } + + /** <inheritDoc /> */ + public void Clear(TK key) + { + IgniteArgumentCheck.NotNull(key, "key"); + + DoOutOp(ClientOp.CacheClearKey, w => w.WriteObjectDetached(key)); + } + + /** <inheritDoc /> */ + public void ClearAll(IEnumerable<TK> keys) + { + IgniteArgumentCheck.NotNull(keys, "keys"); + + DoOutOp(ClientOp.CacheClearKeys, w => w.WriteEnumerable(keys)); + } + + /** <inheritDoc /> */ + public bool Remove(TK key) + { + IgniteArgumentCheck.NotNull(key, "key"); + + return DoOutInOp(ClientOp.CacheRemoveKey, w => w.WriteObjectDetached(key), r => r.ReadBool()); + } + + /** <inheritDoc /> */ + public bool Remove(TK key, TV val) + { + IgniteArgumentCheck.NotNull(key, "key"); + IgniteArgumentCheck.NotNull(val, "val"); + + return DoOutInOp(ClientOp.CacheRemoveIfEquals, w => + { + w.WriteObjectDetached(key); + w.WriteObjectDetached(val); + }, r => r.ReadBool()); + } + + /** <inheritDoc /> */ + public void RemoveAll(IEnumerable<TK> keys) + { + IgniteArgumentCheck.NotNull(keys, "keys"); + + DoOutOp(ClientOp.CacheRemoveKeys, w => w.WriteEnumerable(keys)); + } + + /** <inheritDoc /> */ + public void RemoveAll() + { + DoOutOp(ClientOp.CacheRemoveAll); + } + + /** <inheritDoc /> */ + public long GetSize(params CachePeekMode[] modes) + { + return DoOutInOp(ClientOp.CacheGetSize, w => WritePeekModes(modes, w), s => s.ReadLong()); + } /// <summary> /// Does the out in op. @@ -142,7 +352,7 @@ namespace Apache.Ignite.Core.Impl.Client.Cache /// <summary> /// Does the out op. /// </summary> - private void DoOutOp(ClientOp opId, Action<BinaryWriter> writeAction) + private void DoOutOp(ClientOp opId, Action<BinaryWriter> writeAction = null) { DoOutInOp<object>(opId, writeAction, null); } @@ -165,6 +375,23 @@ namespace Apache.Ignite.Core.Impl.Client.Cache } /// <summary> + /// Unmarshals the value, wrapping in a cache result. + /// </summary> + private CacheResult<T> UnmarshalCacheResult<T>(IBinaryStream stream) + { + var hdr = stream.ReadByte(); + + if (hdr == BinaryUtils.HdrNull) + { + return new CacheResult<T>(); + } + + stream.Seek(-1, SeekOrigin.Current); + + return new CacheResult<T>(_marsh.Unmarshal<T>(stream)); + } + + /// <summary> /// Writes the scan query. /// </summary> private void WriteScanQuery(BinaryWriter writer, ScanQuery<TK, TV> qry) @@ -214,5 +441,34 @@ namespace Apache.Ignite.Core.Impl.Client.Cache { return new KeyNotFoundException("The given key was not present in the cache."); } + + /// <summary> + /// Writes the peek modes. + /// </summary> + private static void WritePeekModes(ICollection<CachePeekMode> modes, IBinaryRawWriter w) + { + if (modes == null) + { + w.WriteInt(0); + } + else + { + w.WriteInt(modes.Count); + + foreach (var m in modes) + { + // Convert bit flag to ordinal. + byte val = 0; + var flagVal = (int)m; + + while ((flagVal = flagVal >> 1) > 0) + { + val++; + } + + w.WriteByte(val); + } + } + } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/97b91e9c/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs index c39b68f..3511a79 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs @@ -30,6 +30,25 @@ namespace Apache.Ignite.Core.Impl.Client BinaryTypePut = 6, QueryScan = 7, QueryScanCursorGetPage = 8, - ResourceClose = 9 + ResourceClose = 9, + CacheContainsKey = 10, + CacheContainsKeys = 11, + CacheGetAll = 12, + CacheGetAndPut = 13, + CacheGetAndReplace = 14, + CacheGetAndRemove = 15, + CachePutIfAbsent = 16, + CacheGetAndPutIfAbsent = 17, + CacheReplace = 18, + CacheReplaceIfEquals = 19, + CachePutAll = 20, + CacheClear = 21, + CacheClearKey = 22, + CacheClearKeys = 23, + CacheRemoveKey = 24, + CacheRemoveIfEquals = 25, + CacheGetSize = 26, + CacheRemoveKeys = 27, + CacheRemoveAll = 28 } } http://git-wip-us.apache.org/repos/asf/ignite/blob/97b91e9c/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs index d55960a..e439208 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs @@ -27,6 +27,7 @@ namespace Apache.Ignite.Core.Impl using System.Reflection; using System.Runtime.InteropServices; using System.Text; + using Apache.Ignite.Core.Cache; using Apache.Ignite.Core.Cluster; using Apache.Ignite.Core.Common; using Apache.Ignite.Core.Impl.Binary; @@ -510,5 +511,25 @@ namespace Apache.Ignite.Core.Impl return res; } + + /// <summary> + /// Encodes the peek modes into a single int value. + /// </summary> + public static int EncodePeekModes(CachePeekMode[] modes) + { + var res = 0; + + if (modes == null) + { + return res; + } + + foreach (var mode in modes) + { + res |= (int)mode; + } + + return res; + } } }
