http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/CacheClientConfiguration.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/CacheClientConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/CacheClientConfiguration.cs new file mode 100644 index 0000000..21ca247 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/CacheClientConfiguration.cs @@ -0,0 +1,420 @@ +/* + * 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. + */ + +namespace Apache.Ignite.Core.Client.Cache +{ + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Diagnostics; + using System.Diagnostics.CodeAnalysis; + using System.IO; + using System.Linq; + using Apache.Ignite.Core.Cache; + using Apache.Ignite.Core.Cache.Configuration; + using Apache.Ignite.Core.Configuration; + using Apache.Ignite.Core.Impl; + using Apache.Ignite.Core.Impl.Binary.IO; + using Apache.Ignite.Core.Impl.Client.Cache; + using Apache.Ignite.Core.Impl.Common; + + /// <summary> + /// Ignite client cache configuration. + /// Same thing as <see cref="CacheConfiguration"/>, but with a subset of properties that can be accessed from + /// Ignite thin client (see <see cref="IIgniteClient"/>). + /// <para /> + /// Note that caches created from server nodes can be accessed from thin client, and vice versa. + /// The only difference is that thin client can not read or write certain <see cref="CacheConfiguration"/> + /// properties, so a separate class exists to make it clear which properties can be used. + /// </summary> + public class CacheClientConfiguration + { + /// <summary> + /// Initializes a new instance of the <see cref="CacheConfiguration"/> class. + /// </summary> + public CacheClientConfiguration() : this((string) null) + { + // No-op. + } + + /// <summary> + /// Initializes a new instance of the <see cref="CacheConfiguration"/> class. + /// </summary> + /// <param name="name">Cache name.</param> + public CacheClientConfiguration(string name) + { + Name = name; + + Backups = CacheConfiguration.DefaultBackups; + AtomicityMode = CacheConfiguration.DefaultAtomicityMode; + CacheMode = CacheConfiguration.DefaultCacheMode; + CopyOnRead = CacheConfiguration.DefaultCopyOnRead; + WriteSynchronizationMode = CacheConfiguration.DefaultWriteSynchronizationMode; + EagerTtl = CacheConfiguration.DefaultEagerTtl; + Invalidate = CacheConfiguration.DefaultInvalidate; + LockTimeout = CacheConfiguration.DefaultLockTimeout; + MaxConcurrentAsyncOperations = CacheConfiguration.DefaultMaxConcurrentAsyncOperations; + ReadFromBackup = CacheConfiguration.DefaultReadFromBackup; + RebalanceBatchSize = CacheConfiguration.DefaultRebalanceBatchSize; + RebalanceMode = CacheConfiguration.DefaultRebalanceMode; + RebalanceThrottle = CacheConfiguration.DefaultRebalanceThrottle; + RebalanceTimeout = CacheConfiguration.DefaultRebalanceTimeout; + PartitionLossPolicy = CacheConfiguration.DefaultPartitionLossPolicy; + SqlIndexMaxInlineSize = CacheConfiguration.DefaultSqlIndexMaxInlineSize; + RebalanceOrder = CacheConfiguration.DefaultRebalanceOrder; + RebalanceBatchesPrefetchCount = CacheConfiguration.DefaultRebalanceBatchesPrefetchCount; + MaxQueryIteratorsCount = CacheConfiguration.DefaultMaxQueryIteratorsCount; + QueryParallelism = CacheConfiguration.DefaultQueryParallelism; + } + + /// <summary> + /// Initializes a new instance of the <see cref="CacheConfiguration"/> class + /// and populates <see cref="QueryEntities"/> according to provided query types. + /// </summary> + /// <param name="name">Cache name.</param> + /// <param name="queryTypes"> + /// Collection of types to be registered as query entities. These types should use + /// <see cref="QuerySqlFieldAttribute"/> to configure query fields and properties. + /// </param> + public CacheClientConfiguration(string name, params Type[] queryTypes) : this(name) + { + QueryEntities = queryTypes.Select(type => new QueryEntity { ValueType = type }).ToArray(); + } + + /// <summary> + /// Initializes a new instance of the <see cref="CacheConfiguration"/> class. + /// </summary> + /// <param name="name">Cache name.</param> + /// <param name="queryEntities">Query entities.</param> + public CacheClientConfiguration(string name, params QueryEntity[] queryEntities) : this(name) + { + QueryEntities = queryEntities; + } + + /// <summary> + /// Initializes a new instance of the <see cref="CacheConfiguration"/> class, + /// performing a deep copy of specified cache configuration. + /// </summary> + /// <param name="other">The other configuration to perfrom deep copy from.</param> + public CacheClientConfiguration(CacheClientConfiguration other) + { + if (other != null) + { + using (var stream = IgniteManager.Memory.Allocate().GetStream()) + { + ClientCacheConfigurationSerializer.Write(stream, other); + + stream.SynchronizeOutput(); + stream.Seek(0, SeekOrigin.Begin); + + ClientCacheConfigurationSerializer.Read(stream, this); + } + + CopyLocalProperties(other); + } + } + + /// <summary> + /// Initializes a new instance of the <see cref="CacheClientConfiguration" /> class, copying properties from + /// provided server cache configuration. See also <see cref="ToCacheConfiguration"/>. + /// </summary> + /// <param name="cacheConfiguration">Server cache configuration.</param> + /// <param name="ignoreUnsupportedProperties">If set to <c>true</c>, + /// ignores unsupported properties instead of throwing an exception.</param> + public CacheClientConfiguration(CacheConfiguration cacheConfiguration, bool ignoreUnsupportedProperties) + { + IgniteArgumentCheck.NotNull(cacheConfiguration, "cacheConfiguration"); + + ClientCacheConfigurationSerializer.Copy(cacheConfiguration, this, ignoreUnsupportedProperties); + } + + /// <summary> + /// Converts this instance to full <see cref="CacheConfiguration"/>. + /// </summary> + public CacheConfiguration ToCacheConfiguration() + { + var cfg = new CacheConfiguration(); + + ClientCacheConfigurationSerializer.Copy(this, cfg); + + return cfg; + } + + /// <summary> + /// Initializes a new instance of the <see cref="CacheClientConfiguration"/> class. + /// </summary> + internal CacheClientConfiguration(IBinaryStream stream) + { + Debug.Assert(stream != null); + + ClientCacheConfigurationSerializer.Read(stream, this); + } + + /// <summary> + /// Copies the local properties (properties that are not written in Write method). + /// </summary> + private void CopyLocalProperties(CacheClientConfiguration cfg) + { + Debug.Assert(cfg != null); + + if (QueryEntities != null && cfg.QueryEntities != null) + { + var entities = cfg.QueryEntities.Where(x => x != null).ToDictionary(x => GetQueryEntityKey(x), x => x); + + foreach (var entity in QueryEntities.Where(x => x != null)) + { + QueryEntity src; + + if (entities.TryGetValue(GetQueryEntityKey(entity), out src)) + { + entity.CopyLocalProperties(src); + } + } + } + } + + /// <summary> + /// Gets the query entity key. + /// </summary> + private static string GetQueryEntityKey(QueryEntity x) + { + return x.KeyTypeName + "^" + x.ValueTypeName; + } + + /// <summary> + /// Gets or sets the cache name. + /// </summary> + public string Name { get; set; } + + /// <summary> + /// Gets or sets write synchronization mode. This mode controls whether the main + /// caller should wait for update on other nodes to complete or not. + /// </summary> + [DefaultValue(CacheConfiguration.DefaultWriteSynchronizationMode)] + public CacheWriteSynchronizationMode WriteSynchronizationMode { get; set; } + + /// <summary> + /// Gets or sets flag indicating whether expired cache entries will be eagerly removed from cache. + /// When set to false, expired entries will be removed on next entry access. + /// </summary> + [DefaultValue(CacheConfiguration.DefaultEagerTtl)] + public bool EagerTtl { get; set; } + + /// <summary> + /// Gets or sets caching mode to use. + /// </summary> + [DefaultValue(CacheConfiguration.DefaultCacheMode)] + public CacheMode CacheMode { get; set; } + + /// <summary> + /// Gets or sets cache atomicity mode. + /// </summary> + [DefaultValue(CacheConfiguration.DefaultAtomicityMode)] + public CacheAtomicityMode AtomicityMode { get; set; } + + /// <summary> + /// Gets or sets number of nodes used to back up single partition for + /// <see cref="Core.Cache.Configuration.CacheMode.Partitioned"/> cache. + /// </summary> + [DefaultValue(CacheConfiguration.DefaultBackups)] + public int Backups { get; set; } + + /// <summary> + /// Gets or sets default lock acquisition timeout. + /// </summary> + [DefaultValue(typeof(TimeSpan), "00:00:00")] + public TimeSpan LockTimeout { get; set; } + + /// <summary> + /// Invalidation flag. If true, values will be invalidated (nullified) upon commit in near cache. + /// </summary> + [DefaultValue(CacheConfiguration.DefaultInvalidate)] + public bool Invalidate { get; set; } + + /// <summary> + /// Gets or sets cache rebalance mode. + /// </summary> + [DefaultValue(CacheConfiguration.DefaultRebalanceMode)] + public CacheRebalanceMode RebalanceMode { get; set; } + + /// <summary> + /// Gets or sets size (in number bytes) to be loaded within a single rebalance message. + /// Rebalancing algorithm will split total data set on every node into multiple batches prior to sending data. + /// </summary> + [DefaultValue(CacheConfiguration.DefaultRebalanceBatchSize)] + public int RebalanceBatchSize { get; set; } + + /// <summary> + /// Gets or sets maximum number of allowed concurrent asynchronous operations, 0 for unlimited. + /// </summary> + [DefaultValue(CacheConfiguration.DefaultMaxConcurrentAsyncOperations)] + public int MaxConcurrentAsyncOperations { get; set; } + + /// <summary> + /// Gets or sets rebalance timeout. + /// </summary> + [DefaultValue(typeof(TimeSpan), "00:00:10")] + public TimeSpan RebalanceTimeout { get; set; } + + /// <summary> + /// Gets or sets delay upon a node joining or leaving topology (or crash) + /// after which rebalancing should be started automatically. + /// Rebalancing should be delayed if you plan to restart nodes + /// after they leave topology, or if you plan to start multiple nodes at once or one after another + /// and don't want to repartition and rebalance until all nodes are started. + /// </summary> + public TimeSpan RebalanceDelay { get; set; } + + /// <summary> + /// Time to wait between rebalance messages to avoid overloading of CPU or network. + /// When rebalancing large data sets, the CPU or network can get over-consumed with rebalancing messages, + /// which consecutively may slow down the application performance. This parameter helps tune + /// the amount of time to wait between rebalance messages to make sure that rebalancing process + /// does not have any negative performance impact. Note that application will continue to work + /// properly while rebalancing is still in progress. + /// <para/> + /// Value of 0 means that throttling is disabled. + /// </summary> + public TimeSpan RebalanceThrottle { get; set; } + + /// <summary> + /// Gets or sets flag indicating whether data can be read from backup. + /// </summary> + [DefaultValue(CacheConfiguration.DefaultReadFromBackup)] + public bool ReadFromBackup { get; set; } + + /// <summary> + /// Gets or sets flag indicating whether copy of the value stored in cache should be created + /// for cache operation implying return value. + /// </summary> + [DefaultValue(CacheConfiguration.DefaultCopyOnRead)] + public bool CopyOnRead { get; set; } + + /// <summary> + /// If true all the SQL table and field names will be escaped with double quotes like + /// ({ "tableName"."fieldsName"}). This enforces case sensitivity for field names and + /// also allows having special characters in table and field names. + /// </summary> + public bool SqlEscapeAll { get; set; } + + /// <summary> + /// Gets or sets the query entity configuration. + /// </summary> + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + public ICollection<QueryEntity> QueryEntities { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether statistics gathering is enabled on a cache. + /// These statistics can be retrieved via <see cref="ICache{TK,TV}.GetMetrics()"/>. + /// </summary> + public bool EnableStatistics { get; set; } + + /// <summary> + /// Gets or sets the name of the data region, see <see cref="DataRegionConfiguration"/>. + /// </summary> + public string DataRegionName { get; set; } + + /// <summary> + /// Gets or sets the partition loss policy. This policy defines how Ignite will react to + /// a situation when all nodes for some partition leave the cluster. + /// </summary> + [DefaultValue(CacheConfiguration.DefaultPartitionLossPolicy)] + public PartitionLossPolicy PartitionLossPolicy { get; set; } + + /// <summary> + /// Gets or sets the cache group name. Caches with the same group name share single underlying 'physical' + /// cache (partition set), but are logically isolated. + /// <para /> + /// Since underlying cache is shared, the following configuration properties should be the same within group: + /// <see cref="CacheMode"/>, <see cref="PartitionLossPolicy"/>, <see cref="DataRegionName"/>. + /// <para /> + /// Grouping caches reduces overall overhead, since internal data structures are shared. + /// </summary> + public string GroupName { get; set; } + + /// <summary> + /// Gets or sets maximum inline size in bytes for sql indexes. See also <see cref="QueryIndex.InlineSize"/>. + /// -1 for automatic. + /// </summary> + [DefaultValue(CacheConfiguration.DefaultSqlIndexMaxInlineSize)] + public int SqlIndexMaxInlineSize { get; set; } + + /// <summary> + /// Gets or sets the key configuration. + /// </summary> + [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + public ICollection<CacheKeyConfiguration> KeyConfiguration { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether on-heap cache is enabled for the off-heap based page memory. + /// </summary> + public bool OnheapCacheEnabled { get; set; } + + /// <summary> + /// Gets or sets the cache rebalance order. Caches with bigger RebalanceOrder are rebalanced later than caches + /// with smaller RebalanceOrder. + /// <para /> + /// Default is 0, which means unordered rebalance. All caches with RebalanceOrder=0 are rebalanced without any + /// delay concurrently. + /// <para /> + /// This parameter is applicable only for caches with <see cref="RebalanceMode"/> of + /// <see cref="CacheRebalanceMode.Sync"/> and <see cref="CacheRebalanceMode.Async"/>. + /// </summary> + [DefaultValue(CacheConfiguration.DefaultRebalanceOrder)] + public int RebalanceOrder { get; set; } + + /// <summary> + /// Gets or sets the rebalance batches prefetch count. + /// <para /> + /// Source node can provide more than one batch at rebalance start to improve performance. + /// Default is <see cref="CacheConfiguration.DefaultRebalanceBatchesPrefetchCount"/>, minimum is 2. + /// </summary> + [DefaultValue(CacheConfiguration.DefaultRebalanceBatchesPrefetchCount)] + public long RebalanceBatchesPrefetchCount { get; set; } + + /// <summary> + /// Gets or sets the maximum number of active query iterators. + /// </summary> + [DefaultValue(CacheConfiguration.DefaultMaxQueryIteratorsCount)] + public int MaxQueryIteratorsCount { get; set; } + + /// <summary> + /// Gets or sets the size of the query detail metrics to be stored in memory. + /// <para /> + /// 0 means disabled metrics. + /// </summary> + [DefaultValue(CacheConfiguration.DefaultQueryDetailMetricsSize)] + public int QueryDetailMetricsSize { get; set; } + + /// <summary> + /// Gets or sets the SQL schema. + /// Non-quoted identifiers are not case sensitive. Quoted identifiers are case sensitive. + /// <para /> + /// Quoted <see cref="Name"/> is used by default. + /// </summary> + public string SqlSchema { get; set; } + + /// <summary> + /// Gets or sets the desired query parallelism within a single node. + /// Query executor may or may not use this hint, depending on estimated query cost. + /// <para /> + /// Default is <see cref="CacheConfiguration.DefaultQueryParallelism"/>. + /// </summary> + [DefaultValue(CacheConfiguration.DefaultQueryParallelism)] + public int QueryParallelism { get; set; } + } +}
http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/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 d772ba6..a3964c6 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs @@ -220,5 +220,10 @@ namespace Apache.Ignite.Core.Client.Cache /// <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); + + /// <summary> + /// Gets the cache configuration. + /// </summary> + CacheClientConfiguration GetConfiguration(); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core/Client/IIgniteClient.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Client/IIgniteClient.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Client/IIgniteClient.cs index ceb8f26..d5ba835 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Client/IIgniteClient.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/IIgniteClient.cs @@ -18,6 +18,7 @@ namespace Apache.Ignite.Core.Client { using System; + using System.Collections.Generic; using Apache.Ignite.Core.Client.Cache; /// <summary> @@ -40,5 +41,54 @@ namespace Apache.Ignite.Core.Client /// <typeparam name="TK">Cache key type.</typeparam> /// <typeparam name="TV">Cache value type.</typeparam> ICacheClient<TK, TV> GetCache<TK, TV>(string name); + + /// <summary> + /// Gets existing cache with the given name or creates new one using template configuration. + /// </summary> + /// <typeparam name="TK">Cache key type.</typeparam> + /// <typeparam name="TV">Cache value type.</typeparam> + /// <param name="name">Cache name.</param> + /// <returns>Existing or newly created cache.</returns> + ICacheClient<TK, TV> GetOrCreateCache<TK, TV>(string name); + + /// <summary> + /// Gets existing cache with the given name or creates new one using provided configuration. + /// </summary> + /// <typeparam name="TK">Cache key type.</typeparam> + /// <typeparam name="TV">Cache value type.</typeparam> + /// <param name="configuration">Cache configuration.</param> + /// <returns>Existing or newly created cache.</returns> + ICacheClient<TK, TV> GetOrCreateCache<TK, TV>(CacheClientConfiguration configuration); + + /// <summary> + /// Dynamically starts new cache using template configuration. + /// </summary> + /// <typeparam name="TK">Cache key type.</typeparam> + /// <typeparam name="TV">Cache value type.</typeparam> + /// <param name="name">Cache name.</param> + /// <returns>Existing or newly created cache.</returns> + ICacheClient<TK, TV> CreateCache<TK, TV>(string name); + + /// <summary> + /// Dynamically starts new cache using provided configuration. + /// </summary> + /// <typeparam name="TK">Cache key type.</typeparam> + /// <typeparam name="TV">Cache value type.</typeparam> + /// <param name="configuration">Cache configuration.</param> + /// <returns>Existing or newly created cache.</returns> + ICacheClient<TK, TV> CreateCache<TK, TV>(CacheClientConfiguration configuration); + + /// <summary> + /// Gets the collection of names of currently available caches, or empty collection if there are no caches. + /// </summary> + /// <returns>Collection of names of currently available caches.</returns> + ICollection<string> GetCacheNames(); + + /// <summary> + /// Destroys dynamically created (with <see cref="CreateCache{TK,TV}(string)"/> or + /// <see cref="GetOrCreateCache{TK,TV}(string)"/>) cache. + /// </summary> + /// <param name="name">The name of the cache to stop.</param> + void DestroyCache(string name); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core/IIgnite.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IIgnite.cs b/modules/platforms/dotnet/Apache.Ignite.Core/IIgnite.cs index f61da06..bf6a227 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/IIgnite.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/IIgnite.cs @@ -276,7 +276,6 @@ namespace Apache.Ignite.Core /// <summary> /// Gets the collection of names of currently available caches, or empty collection if there are no caches. - /// Note that null string is a valid cache name. /// </summary> /// <returns>Collection of names of currently available caches.</returns> ICollection<string> GetCacheNames(); http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderExtensions.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderExtensions.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderExtensions.cs index 9be06c5..de0277b 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderExtensions.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderExtensions.cs @@ -124,5 +124,23 @@ namespace Apache.Ignite.Core.Impl.Binary return res; } + + /// <summary> + /// Reads the string collection. + /// </summary> + public static ICollection<string> ReadStringCollection(this IBinaryRawReader reader) + { + Debug.Assert(reader != null); + + var cnt = reader.ReadInt(); + var res = new List<string>(cnt); + + for (var i = 0; i < cnt; i++) + { + res.Add(reader.ReadString()); + } + + return res; + } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/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 be6e7da..a3b42b8 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 @@ -327,6 +327,12 @@ namespace Apache.Ignite.Core.Impl.Client.Cache return DoOutInOp(ClientOp.CacheGetSize, w => WritePeekModes(modes, w), s => s.ReadLong()); } + /** <inheritDoc /> */ + public CacheClientConfiguration GetConfiguration() + { + return DoOutInOp(ClientOp.CacheGetConfiguration, null, s => new CacheClientConfiguration(s)); + } + /// <summary> /// Does the out in op. /// </summary> http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/ClientCacheConfigurationSerializer.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/ClientCacheConfigurationSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/ClientCacheConfigurationSerializer.cs new file mode 100644 index 0000000..160d09f --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/ClientCacheConfigurationSerializer.cs @@ -0,0 +1,261 @@ +/* + * 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. + */ + +namespace Apache.Ignite.Core.Impl.Client.Cache +{ + using System; + using System.Diagnostics; + using Apache.Ignite.Core.Cache.Configuration; + using Apache.Ignite.Core.Client.Cache; + using Apache.Ignite.Core.Impl.Binary; + using Apache.Ignite.Core.Impl.Binary.IO; + + /// <summary> + /// Writes and reads <see cref="CacheConfiguration"/> for thin client mode. + /// <para /> + /// Thin client supports a subset of <see cref="CacheConfiguration"/> properties, so + /// <see cref="CacheConfiguration.Read"/> is not suitable. + /// </summary> + internal static class ClientCacheConfigurationSerializer + { + /// <summary> + /// Copies one cache configuration to another. + /// </summary> + public static void Copy(CacheConfiguration from, CacheClientConfiguration to, bool ignoreUnsupportedProperties) + { + Debug.Assert(from != null); + Debug.Assert(to != null); + + to.AtomicityMode = from.AtomicityMode; + to.Backups = from.Backups; + to.CacheMode = from.CacheMode; + to.CopyOnRead = from.CopyOnRead; + to.DataRegionName = from.DataRegionName; + to.EagerTtl = from.EagerTtl; + to.EnableStatistics = from.EnableStatistics; + to.GroupName = from.GroupName; + to.Invalidate = from.Invalidate; + to.LockTimeout = from.LockTimeout; + to.MaxConcurrentAsyncOperations = from.MaxConcurrentAsyncOperations; + to.MaxQueryIteratorsCount = from.MaxQueryIteratorsCount; + to.Name = from.Name; + to.OnheapCacheEnabled = from.OnheapCacheEnabled; + to.PartitionLossPolicy = from.PartitionLossPolicy; + to.QueryDetailMetricsSize = from.QueryDetailMetricsSize; + to.QueryParallelism = from.QueryParallelism; + to.ReadFromBackup = from.ReadFromBackup; + to.RebalanceBatchSize = from.RebalanceBatchSize; + to.RebalanceBatchesPrefetchCount = from.RebalanceBatchesPrefetchCount; + to.RebalanceDelay = from.RebalanceDelay; + to.RebalanceMode = from.RebalanceMode; + to.RebalanceOrder = from.RebalanceOrder; + to.RebalanceThrottle = from.RebalanceThrottle; + to.RebalanceTimeout = from.RebalanceTimeout; + to.SqlEscapeAll = from.SqlEscapeAll; + to.SqlIndexMaxInlineSize = from.SqlIndexMaxInlineSize; + to.SqlSchema = from.SqlSchema; + to.WriteSynchronizationMode = from.WriteSynchronizationMode; + + to.KeyConfiguration = from.KeyConfiguration; + to.QueryEntities = from.QueryEntities; + + if (!ignoreUnsupportedProperties) + { + // Unsupported complex properties. + ThrowUnsupportedIfNotDefault(from.AffinityFunction, "AffinityFunction"); + ThrowUnsupportedIfNotDefault(from.EvictionPolicy, "EvictionPolicy"); + ThrowUnsupportedIfNotDefault(from.ExpiryPolicyFactory, "ExpiryPolicyFactory"); + ThrowUnsupportedIfNotDefault(from.PluginConfigurations, "PluginConfigurations"); + ThrowUnsupportedIfNotDefault(from.CacheStoreFactory, "CacheStoreFactory"); + ThrowUnsupportedIfNotDefault(from.NearConfiguration, "NearConfiguration"); + + // Unsupported store-related properties. + ThrowUnsupportedIfNotDefault(from.KeepBinaryInStore, "KeepBinaryInStore"); + ThrowUnsupportedIfNotDefault(from.LoadPreviousValue, "LoadPreviousValue"); + ThrowUnsupportedIfNotDefault(from.ReadThrough, "ReadThrough"); + ThrowUnsupportedIfNotDefault(from.WriteThrough, "WriteThrough"); + ThrowUnsupportedIfNotDefault(from.StoreConcurrentLoadAllThreshold, "StoreConcurrentLoadAllThreshold", + CacheConfiguration.DefaultStoreConcurrentLoadAllThreshold); + ThrowUnsupportedIfNotDefault(from.WriteBehindBatchSize, "WriteBehindBatchSize", + CacheConfiguration.DefaultWriteBehindBatchSize); + ThrowUnsupportedIfNotDefault(from.WriteBehindCoalescing, "WriteBehindCoalescing", + CacheConfiguration.DefaultWriteBehindCoalescing); + ThrowUnsupportedIfNotDefault(from.WriteBehindEnabled, "WriteBehindEnabled"); + ThrowUnsupportedIfNotDefault(from.WriteBehindFlushFrequency, "WriteBehindFlushFrequency", + CacheConfiguration.DefaultWriteBehindFlushFrequency); + ThrowUnsupportedIfNotDefault(from.WriteBehindFlushSize, "WriteBehindFlushSize", + CacheConfiguration.DefaultWriteBehindFlushSize); + ThrowUnsupportedIfNotDefault(from.WriteBehindFlushThreadCount, "WriteBehindFlushThreadCount", + CacheConfiguration.DefaultWriteBehindFlushThreadCount); + } + } + /// <summary> + /// Copies one cache configuration to another. + /// </summary> + public static void Copy(CacheClientConfiguration from, CacheConfiguration to) + { + Debug.Assert(from != null); + Debug.Assert(to != null); + + to.AtomicityMode = from.AtomicityMode; + to.Backups = from.Backups; + to.CacheMode = from.CacheMode; + to.CopyOnRead = from.CopyOnRead; + to.DataRegionName = from.DataRegionName; + to.EagerTtl = from.EagerTtl; + to.EnableStatistics = from.EnableStatistics; + to.GroupName = from.GroupName; + to.Invalidate = from.Invalidate; + to.LockTimeout = from.LockTimeout; + to.MaxConcurrentAsyncOperations = from.MaxConcurrentAsyncOperations; + to.MaxQueryIteratorsCount = from.MaxQueryIteratorsCount; + to.Name = from.Name; + to.OnheapCacheEnabled = from.OnheapCacheEnabled; + to.PartitionLossPolicy = from.PartitionLossPolicy; + to.QueryDetailMetricsSize = from.QueryDetailMetricsSize; + to.QueryParallelism = from.QueryParallelism; + to.ReadFromBackup = from.ReadFromBackup; + to.RebalanceBatchSize = from.RebalanceBatchSize; + to.RebalanceBatchesPrefetchCount = from.RebalanceBatchesPrefetchCount; + to.RebalanceDelay = from.RebalanceDelay; + to.RebalanceMode = from.RebalanceMode; + to.RebalanceOrder = from.RebalanceOrder; + to.RebalanceThrottle = from.RebalanceThrottle; + to.RebalanceTimeout = from.RebalanceTimeout; + to.SqlEscapeAll = from.SqlEscapeAll; + to.SqlIndexMaxInlineSize = from.SqlIndexMaxInlineSize; + to.SqlSchema = from.SqlSchema; + to.WriteSynchronizationMode = from.WriteSynchronizationMode; + + to.KeyConfiguration = from.KeyConfiguration; + to.QueryEntities = from.QueryEntities; + } + + /// <summary> + /// Writes the specified config. + /// </summary> + public static void Write(IBinaryStream stream, CacheClientConfiguration cfg) + { + Debug.Assert(stream != null); + Debug.Assert(cfg != null); + + // Configuration should be written with a system marshaller. + var writer = BinaryUtils.Marshaller.StartMarshal(stream); + var pos = writer.Stream.Position; + writer.WriteInt(0); // Reserve for length. + + writer.WriteInt((int)cfg.AtomicityMode); + writer.WriteInt(cfg.Backups); + writer.WriteInt((int)cfg.CacheMode); + writer.WriteBoolean(cfg.CopyOnRead); + writer.WriteString(cfg.DataRegionName); + writer.WriteBoolean(cfg.EagerTtl); + writer.WriteBoolean(cfg.EnableStatistics); + writer.WriteString(cfg.GroupName); + writer.WriteBoolean(cfg.Invalidate); + writer.WriteTimeSpanAsLong(cfg.LockTimeout); + writer.WriteInt(cfg.MaxConcurrentAsyncOperations); + writer.WriteInt(cfg.MaxQueryIteratorsCount); + writer.WriteString(cfg.Name); + writer.WriteBoolean(cfg.OnheapCacheEnabled); + writer.WriteInt((int)cfg.PartitionLossPolicy); + writer.WriteInt(cfg.QueryDetailMetricsSize); + writer.WriteInt(cfg.QueryParallelism); + writer.WriteBoolean(cfg.ReadFromBackup); + writer.WriteInt(cfg.RebalanceBatchSize); + writer.WriteLong(cfg.RebalanceBatchesPrefetchCount); + writer.WriteTimeSpanAsLong(cfg.RebalanceDelay); + writer.WriteInt((int)cfg.RebalanceMode); + writer.WriteInt(cfg.RebalanceOrder); + writer.WriteTimeSpanAsLong(cfg.RebalanceThrottle); + writer.WriteTimeSpanAsLong(cfg.RebalanceTimeout); + writer.WriteBoolean(cfg.SqlEscapeAll); + writer.WriteInt(cfg.SqlIndexMaxInlineSize); + writer.WriteString(cfg.SqlSchema); + writer.WriteInt((int)cfg.WriteSynchronizationMode); + + writer.WriteCollectionRaw(cfg.KeyConfiguration); + writer.WriteCollectionRaw(cfg.QueryEntities); + + // Write length (so that part of the config can be skipped). + var len = writer.Stream.Position - pos - 4; + writer.Stream.WriteInt(pos, len); + } + /// <summary> + /// Reads the config. + /// </summary> + public static void Read(IBinaryStream stream, CacheClientConfiguration cfg) + { + Debug.Assert(stream != null); + + // Configuration should be read with system marshaller. + var reader = BinaryUtils.Marshaller.StartUnmarshal(stream); + + var len = reader.ReadInt(); + var pos = reader.Stream.Position; + + cfg.AtomicityMode = (CacheAtomicityMode)reader.ReadInt(); + cfg.Backups = reader.ReadInt(); + cfg.CacheMode = (CacheMode)reader.ReadInt(); + cfg.CopyOnRead = reader.ReadBoolean(); + cfg.DataRegionName = reader.ReadString(); + cfg.EagerTtl = reader.ReadBoolean(); + cfg.EnableStatistics = reader.ReadBoolean(); + cfg.GroupName = reader.ReadString(); + cfg.Invalidate = reader.ReadBoolean(); + cfg.LockTimeout = reader.ReadLongAsTimespan(); + cfg.MaxConcurrentAsyncOperations = reader.ReadInt(); + cfg.MaxQueryIteratorsCount = reader.ReadInt(); + cfg.Name = reader.ReadString(); + cfg.OnheapCacheEnabled = reader.ReadBoolean(); + cfg.PartitionLossPolicy = (PartitionLossPolicy)reader.ReadInt(); + cfg.QueryDetailMetricsSize = reader.ReadInt(); + cfg.QueryParallelism = reader.ReadInt(); + cfg.ReadFromBackup = reader.ReadBoolean(); + cfg.RebalanceBatchSize = reader.ReadInt(); + cfg.RebalanceBatchesPrefetchCount = reader.ReadLong(); + cfg.RebalanceDelay = reader.ReadLongAsTimespan(); + cfg.RebalanceMode = (CacheRebalanceMode)reader.ReadInt(); + cfg.RebalanceOrder = reader.ReadInt(); + cfg.RebalanceThrottle = reader.ReadLongAsTimespan(); + cfg.RebalanceTimeout = reader.ReadLongAsTimespan(); + cfg.SqlEscapeAll = reader.ReadBoolean(); + cfg.SqlIndexMaxInlineSize = reader.ReadInt(); + cfg.SqlSchema = reader.ReadString(); + cfg.WriteSynchronizationMode = (CacheWriteSynchronizationMode)reader.ReadInt(); + cfg.KeyConfiguration = reader.ReadCollectionRaw(r => new CacheKeyConfiguration(r)); + cfg.QueryEntities = reader.ReadCollectionRaw(r => new QueryEntity(r)); + + Debug.Assert(len == reader.Stream.Position - pos); + } + + /// <summary> + /// Throws the unsupported exception if property is not default. + /// </summary> + // ReSharper disable ParameterOnlyUsedForPreconditionCheck.Local + // ReSharper disable UnusedParameter.Local + private static void ThrowUnsupportedIfNotDefault<T>(T obj, string propertyName, T defaultValue = default(T)) + { + if (!Equals(obj, defaultValue)) + { + throw new NotSupportedException( + string.Format("{0}.{1} property is not supported in thin client mode.", + typeof(CacheConfiguration).Name, propertyName)); + } + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/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 3511a79..779b73e 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs @@ -49,6 +49,13 @@ namespace Apache.Ignite.Core.Impl.Client CacheRemoveIfEquals = 25, CacheGetSize = 26, CacheRemoveKeys = 27, - CacheRemoveAll = 28 + CacheRemoveAll = 28, + CacheCreateWithName = 29, + CacheGetOrCreateWithName = 30, + CacheDestroy = 31, + CacheGetNames = 32, + CacheGetConfiguration = 33, + CacheCreateWithConfiguration = 34, + CacheGetOrCreateWithConfiguration = 35 } } http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientStatus.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientStatus.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientStatus.cs index a2e66e8..294a202 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientStatus.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientStatus.cs @@ -26,6 +26,7 @@ namespace Apache.Ignite.Core.Impl.Client Fail = 1, InvalidOpCode = 2, CacheDoesNotExist = 1000, + CacheExists = 1001, TooManyCursors = 1010 } } http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs index d05355a..13a3a83 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs @@ -18,6 +18,7 @@ namespace Apache.Ignite.Core.Impl.Client { using System; + using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using Apache.Ignite.Core.Binary; @@ -25,6 +26,7 @@ namespace Apache.Ignite.Core.Impl.Client using Apache.Ignite.Core.Client.Cache; using Apache.Ignite.Core.Datastream; using Apache.Ignite.Core.Impl.Binary; + using Apache.Ignite.Core.Impl.Binary.IO; using Apache.Ignite.Core.Impl.Client.Cache; using Apache.Ignite.Core.Impl.Cluster; using Apache.Ignite.Core.Impl.Common; @@ -88,6 +90,62 @@ namespace Apache.Ignite.Core.Impl.Client } /** <inheritDoc /> */ + public ICacheClient<TK, TV> GetOrCreateCache<TK, TV>(string name) + { + IgniteArgumentCheck.NotNull(name, "name"); + + DoOutOp(ClientOp.CacheGetOrCreateWithName, w => w.WriteString(name)); + + return GetCache<TK, TV>(name); + } + + /** <inheritDoc /> */ + public ICacheClient<TK, TV> GetOrCreateCache<TK, TV>(CacheClientConfiguration configuration) + { + IgniteArgumentCheck.NotNull(configuration, "configuration"); + + DoOutOp(ClientOp.CacheGetOrCreateWithConfiguration, + w => ClientCacheConfigurationSerializer.Write(w.Stream, configuration)); + + return GetCache<TK, TV>(configuration.Name); + } + + /** <inheritDoc /> */ + public ICacheClient<TK, TV> CreateCache<TK, TV>(string name) + { + IgniteArgumentCheck.NotNull(name, "name"); + + DoOutOp(ClientOp.CacheCreateWithName, w => w.WriteString(name)); + + return GetCache<TK, TV>(name); + } + + /** <inheritDoc /> */ + public ICacheClient<TK, TV> CreateCache<TK, TV>(CacheClientConfiguration configuration) + { + IgniteArgumentCheck.NotNull(configuration, "configuration"); + + DoOutOp(ClientOp.CacheCreateWithConfiguration, + w => ClientCacheConfigurationSerializer.Write(w.Stream, configuration)); + + return GetCache<TK, TV>(configuration.Name); + } + + /** <inheritDoc /> */ + public ICollection<string> GetCacheNames() + { + return DoOutInOp(ClientOp.CacheGetNames, null, s => Marshaller.StartUnmarshal(s).ReadStringCollection()); + } + + /** <inheritDoc /> */ + public void DestroyCache(string name) + { + IgniteArgumentCheck.NotNull(name, "name"); + + DoOutOp(ClientOp.CacheDestroy, w => w.WriteString(name)); + } + + /** <inheritDoc /> */ public IIgnite GetIgnite() { throw GetClientNotSupportedException(); @@ -155,5 +213,32 @@ namespace Apache.Ignite.Core.Impl.Client return new NotSupportedException(msg); } + + /// <summary> + /// Does the out in op. + /// </summary> + private T DoOutInOp<T>(ClientOp opId, Action<BinaryWriter> writeAction, + Func<IBinaryStream, T> readFunc) + { + return _socket.DoOutInOp(opId, stream => + { + if (writeAction != null) + { + var writer = _marsh.StartMarshal(stream); + + writeAction(writer); + + _marsh.FinishMarshal(writer); + } + }, readFunc); + } + + /// <summary> + /// Does the out op. + /// </summary> + private void DoOutOp(ClientOp opId, Action<BinaryWriter> writeAction = null) + { + DoOutInOp<object>(opId, writeAction, null); + } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/examples/Apache.Ignite.Examples/App.config ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/examples/Apache.Ignite.Examples/App.config b/modules/platforms/dotnet/examples/Apache.Ignite.Examples/App.config index 1249ed8..8f78382 100644 --- a/modules/platforms/dotnet/examples/Apache.Ignite.Examples/App.config +++ b/modules/platforms/dotnet/examples/Apache.Ignite.Examples/App.config @@ -30,10 +30,6 @@ localhost="127.0.0.1" peerAssemblyLoadingMode="CurrentAppDomain"> <atomicConfiguration atomicSequenceReserveSize="10" /> - <cacheConfiguration> - <cacheConfiguration name="default-cache" /> - </cacheConfiguration> - <discoverySpi type="TcpDiscoverySpi"> <ipFinder type="TcpDiscoveryMulticastIpFinder"> <endpoints> http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/examples/Apache.Ignite.Examples/ThinClient/ThinClientPutGetExample.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/examples/Apache.Ignite.Examples/ThinClient/ThinClientPutGetExample.cs b/modules/platforms/dotnet/examples/Apache.Ignite.Examples/ThinClient/ThinClientPutGetExample.cs index 9158b09..cc35840 100644 --- a/modules/platforms/dotnet/examples/Apache.Ignite.Examples/ThinClient/ThinClientPutGetExample.cs +++ b/modules/platforms/dotnet/examples/Apache.Ignite.Examples/ThinClient/ThinClientPutGetExample.cs @@ -36,12 +36,11 @@ namespace Apache.Ignite.Examples.ThinClient /// 2) Start example. /// <para /> /// This example can also work via pure Java node started with ignite.bat/ignite.sh. - /// The only requirement is that the nodes have to create the cache named "default-cache" in advance. /// </summary> public static class ThinClientPutGetExample { /// <summary> Cache name. </summary> - private const string CacheName = "default-cache"; + private const string CacheName = "thinClientCache"; [STAThread] public static void Main() @@ -56,7 +55,7 @@ namespace Apache.Ignite.Examples.ThinClient Console.WriteLine(); Console.WriteLine(">>> Cache put-get client example started."); - ICacheClient<int, Organization> cache = igniteClient.GetCache<int, Organization>(CacheName); + ICacheClient<int, Organization> cache = igniteClient.GetOrCreateCache<int, Organization>(CacheName); PutGet(cache); } http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/examples/Apache.Ignite.Examples/ThinClient/ThinClientQueryExample.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/examples/Apache.Ignite.Examples/ThinClient/ThinClientQueryExample.cs b/modules/platforms/dotnet/examples/Apache.Ignite.Examples/ThinClient/ThinClientQueryExample.cs index 49c87b7..61b3a8b 100644 --- a/modules/platforms/dotnet/examples/Apache.Ignite.Examples/ThinClient/ThinClientQueryExample.cs +++ b/modules/platforms/dotnet/examples/Apache.Ignite.Examples/ThinClient/ThinClientQueryExample.cs @@ -40,7 +40,7 @@ namespace Apache.Ignite.Examples.ThinClient public class ThinClientQueryExample { /// <summary> Cache name. </summary> - private const string CacheName = "default-cache"; + private const string CacheName = "thinClientCache"; [STAThread] public static void Main() @@ -55,7 +55,7 @@ namespace Apache.Ignite.Examples.ThinClient Console.WriteLine(); Console.WriteLine(">>> Cache query client example started."); - ICacheClient<int, Employee> cache = igniteClient.GetCache<int, Employee>(CacheName); + ICacheClient<int, Employee> cache = igniteClient.GetOrCreateCache<int, Employee>(CacheName); // Populate cache with sample data entries. PopulateCache(cache);