You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2016/02/09 12:54:25 UTC
[2/2] ignite git commit: IGNITE-2380: Added ability to start Ignite
using configuration from app.config. This closes #417.
IGNITE-2380: Added ability to start Ignite using configuration from app.config. This closes #417.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/a4d8a049
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/a4d8a049
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/a4d8a049
Branch: refs/heads/master
Commit: a4d8a049138a4d4bc86a59ccb273f7e214baf694
Parents: f7c1296
Author: Pavel Tupitsyn <pt...@gridgain.com>
Authored: Tue Feb 9 14:54:20 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Tue Feb 9 14:54:20 2016 +0300
----------------------------------------------------------------------
.../Apache.Ignite.Core.Tests.csproj | 4 +
.../Apache.Ignite.Core.Tests/FutureTest.cs | 1 +
.../IgniteConfigurationSectionTest.cs | 69 +++
.../IgniteConfigurationSerializerTest.cs | 554 +++++++++++++++++++
.../dotnet/Apache.Ignite.Core.Tests/app.config | 54 ++
.../Apache.Ignite.Core.csproj | 11 +
.../Binary/IBinarySerializer.cs | 6 +-
.../IgniteConfigurationSection.cs | 80 +++
.../IgniteConfigurationSection.xsd | 281 ++++++++++
.../dotnet/Apache.Ignite.Core/Ignition.cs | 39 ++
.../Impl/Common/BooleanLowerCaseConverter.cs | 60 ++
.../Common/IgniteConfigurationXmlSerializer.cs | 410 ++++++++++++++
.../Impl/Common/TypeStringConverter.cs | 115 ++++
.../Impl/Events/EventTypeConverter.cs | 133 +++++
14 files changed, 1814 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
index f5e98c5..fb14ed5 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
@@ -55,6 +55,7 @@
<HintPath>..\libs\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="System" />
+ <Reference Include="System.configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.XML" />
@@ -117,6 +118,8 @@
<Compile Include="ExceptionsTest.cs" />
<Compile Include="ExecutableTest.cs" />
<Compile Include="FutureTest.cs" />
+ <Compile Include="IgniteConfigurationSectionTest.cs" />
+ <Compile Include="IgniteConfigurationSerializerTest.cs" />
<Compile Include="IgniteConfigurationTest.cs" />
<Compile Include="IgniteTestBase.cs" />
<Compile Include="LifecycleTest.cs" />
@@ -251,6 +254,7 @@
<ItemGroup>
<None Include="Apache.Ignite.Core.Tests.nunit" />
<None Include="Apache.Ignite.Core.Tests.snk" />
+ <None Include="app.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core.Tests/FutureTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/FutureTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/FutureTest.cs
index f18be8c..bc1f08f 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/FutureTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/FutureTest.cs
@@ -67,6 +67,7 @@ namespace Apache.Ignite.Core.Tests
[TestFixtureTearDown]
public void TestFixtureTearDown()
{
+ Ignition.StopAll(true);
TestUtils.KillProcesses();
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSectionTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSectionTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSectionTest.cs
new file mode 100644
index 0000000..29aea90
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSectionTest.cs
@@ -0,0 +1,69 @@
+/*
+ * 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.Tests
+{
+ using System;
+ using System.Configuration;
+ using System.Linq;
+ using Apache.Ignite.Core.Impl.Common;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests <see cref="IgniteConfigurationSection"/>.
+ /// </summary>
+ public class IgniteConfigurationSectionTest
+ {
+ /// <summary>
+ /// Tests the read.
+ /// </summary>
+ [Test]
+ public void TestRead()
+ {
+ var section = (IgniteConfigurationSection) ConfigurationManager.GetSection("igniteConfiguration");
+
+ Assert.AreEqual("myGrid1", section.IgniteConfiguration.GridName);
+ Assert.AreEqual("cacheName", section.IgniteConfiguration.CacheConfiguration.Single().Name);
+ }
+
+ /// <summary>
+ /// Tests the ignite start.
+ /// </summary>
+ [Test]
+ public void TestIgniteStart()
+ {
+ Environment.SetEnvironmentVariable(Classpath.EnvIgniteNativeTestClasspath, "true");
+
+ using (var ignite = Ignition.StartFromApplicationConfiguration("igniteConfiguration"))
+ {
+ Assert.AreEqual("myGrid1", ignite.Name);
+ Assert.IsNotNull(ignite.GetCache<int, int>("cacheName"));
+ }
+
+ using (var ignite = Ignition.StartFromApplicationConfiguration("igniteConfiguration2"))
+ {
+ Assert.AreEqual("myGrid2", ignite.Name);
+ Assert.IsNotNull(ignite.GetCache<int, int>("cacheName2"));
+ }
+
+ using (var ignite = Ignition.StartFromApplicationConfiguration())
+ {
+ Assert.IsTrue(ignite.Name.StartsWith("myGrid"));
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs
new file mode 100644
index 0000000..d8c52ee
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs
@@ -0,0 +1,554 @@
+/*
+ * 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.
+ */
+
+// ReSharper disable UnusedAutoPropertyAccessor.Global
+// ReSharper disable MemberCanBePrivate.Global
+namespace Apache.Ignite.Core.Tests
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.IO;
+ using System.Linq;
+ using System.Text;
+ using System.Threading;
+ using System.Xml;
+ using System.Xml.Schema;
+ using Apache.Ignite.Core.Binary;
+ using Apache.Ignite.Core.Cache.Configuration;
+ using Apache.Ignite.Core.Cache.Store;
+ using Apache.Ignite.Core.Common;
+ using Apache.Ignite.Core.Discovery.Tcp;
+ using Apache.Ignite.Core.Discovery.Tcp.Multicast;
+ using Apache.Ignite.Core.Events;
+ using Apache.Ignite.Core.Impl.Common;
+ using Apache.Ignite.Core.Lifecycle;
+ using Apache.Ignite.Core.Tests.Binary;
+ using NUnit.Framework;
+
+ /// <summary>
+ /// Tests <see cref="IgniteConfiguration"/> serialization.
+ /// </summary>
+ public class IgniteConfigurationSerializerTest
+ {
+ /// <summary>
+ /// Tests the predefined XML.
+ /// </summary>
+ [Test]
+ public void TestPredefinedXml()
+ {
+ var xml = @"<igniteConfig workDirectory='c:' JvmMaxMemoryMb='1024' MetricsLogFrequency='0:0:10'>
+ <localhost>127.1.1.1</localhost>
+ <binaryConfiguration>
+ <defaultNameMapper type='Apache.Ignite.Core.Tests.IgniteConfigurationSerializerTest+NameMapper, Apache.Ignite.Core.Tests' bar='testBar' />
+ <types>
+ <string>Apache.Ignite.Core.Tests.IgniteConfigurationSerializerTest+FooClass, Apache.Ignite.Core.Tests</string>
+ </types>
+ </binaryConfiguration>
+ <discoverySpi type='TcpDiscoverySpi' joinTimeout='0:1:0'>
+ <ipFinder type='TcpDiscoveryMulticastIpFinder' addressRequestAttempts='7' />
+ </discoverySpi>
+ <jvmOptions><string>-Xms1g</string><string>-Xmx4g</string></jvmOptions>
+ <lifecycleBeans>
+ <iLifecycleBean type='Apache.Ignite.Core.Tests.IgniteConfigurationSerializerTest+LifecycleBean, Apache.Ignite.Core.Tests' foo='15' />
+ </lifecycleBeans>
+ <cacheConfiguration>
+ <cacheConfiguration cacheMode='Replicated'>
+ <queryEntities>
+ <queryEntity keyType='System.Int32' valueType='System.String'>
+ <fields>
+ <queryField name='length' fieldType='System.Int32' />
+ </fields>
+ <aliases>
+ <queryAlias fullName='somefield.field' alias='shortField' />
+ </aliases>
+ <indexes>
+ <queryIndex name='idx' indexType='Geospatial'>
+ <fields>
+ <queryIndexField name='indexFld' isDescending='true' />
+ </fields>
+ </queryIndex>
+ </indexes>
+ </queryEntity>
+ </queryEntities>
+ </cacheConfiguration>
+ <cacheConfiguration name='secondCache' />
+ </cacheConfiguration>
+ <includedEventTypes>
+ <int>42</int>
+ <int>TaskFailed</int>
+ <int>JobFinished</int>
+ </includedEventTypes>
+ </igniteConfig>";
+ var reader = XmlReader.Create(new StringReader(xml));
+
+ var cfg = IgniteConfigurationXmlSerializer.Deserialize(reader);
+
+ Assert.AreEqual("c:", cfg.WorkDirectory);
+ Assert.AreEqual("127.1.1.1", cfg.Localhost);
+ Assert.AreEqual(1024, cfg.JvmMaxMemoryMb);
+ Assert.AreEqual(TimeSpan.FromSeconds(10), cfg.MetricsLogFrequency);
+ Assert.AreEqual(TimeSpan.FromMinutes(1), ((TcpDiscoverySpi)cfg.DiscoverySpi).JoinTimeout);
+ Assert.AreEqual(7,
+ ((TcpDiscoveryMulticastIpFinder) ((TcpDiscoverySpi) cfg.DiscoverySpi).IpFinder).AddressRequestAttempts);
+ Assert.AreEqual(new[] { "-Xms1g", "-Xmx4g" }, cfg.JvmOptions);
+ Assert.AreEqual(15, ((LifecycleBean) cfg.LifecycleBeans.Single()).Foo);
+ Assert.AreEqual("testBar", ((NameMapper) cfg.BinaryConfiguration.DefaultNameMapper).Bar);
+ Assert.AreEqual(
+ "Apache.Ignite.Core.Tests.IgniteConfigurationSerializerTest+FooClass, Apache.Ignite.Core.Tests",
+ cfg.BinaryConfiguration.Types.Single());
+ Assert.AreEqual(new[] {42, EventType.TaskFailed, EventType.JobFinished}, cfg.IncludedEventTypes);
+
+ Assert.AreEqual("secondCache", cfg.CacheConfiguration.Last().Name);
+
+ var cacheCfg = cfg.CacheConfiguration.First();
+
+ Assert.AreEqual(CacheMode.Replicated, cacheCfg.CacheMode);
+
+ var queryEntity = cacheCfg.QueryEntities.Single();
+ Assert.AreEqual(typeof(int), queryEntity.KeyType);
+ Assert.AreEqual(typeof(string), queryEntity.ValueType);
+ Assert.AreEqual("length", queryEntity.Fields.Single().Name);
+ Assert.AreEqual(typeof(int), queryEntity.Fields.Single().FieldType);
+ Assert.AreEqual("somefield.field", queryEntity.Aliases.Single().FullName);
+ Assert.AreEqual("shortField", queryEntity.Aliases.Single().Alias);
+ Assert.AreEqual(QueryIndexType.Geospatial, queryEntity.Indexes.Single().IndexType);
+ Assert.AreEqual("indexFld", queryEntity.Indexes.Single().Fields.Single().Name);
+ Assert.AreEqual(true, queryEntity.Indexes.Single().Fields.Single().IsDescending);
+ }
+
+ /// <summary>
+ /// Tests the serialize deserialize.
+ /// </summary>
+ [Test]
+ public void TestSerializeDeserialize()
+ {
+ // Test custom
+ CheckSerializeDeserialize(GetTestConfig());
+
+ // Test custom with different culture to make sure numbers are serialized properly
+ RunWithCustomCulture(() => CheckSerializeDeserialize(GetTestConfig()));
+
+ // Test default
+ CheckSerializeDeserialize(new IgniteConfiguration());
+ }
+
+ /// <summary>
+ /// Tests the schema validation.
+ /// </summary>
+ [Test]
+ public void TestSchemaValidation()
+ {
+ CheckSchemaValidation();
+
+ RunWithCustomCulture(CheckSchemaValidation);
+
+ // Check invalid xml
+ const string invalidXml =
+ @"<igniteConfiguration xmlns='http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection'>
+ <binaryConfiguration /><binaryConfiguration />
+ </igniteConfiguration>";
+
+ Assert.Throws<XmlSchemaValidationException>(() => CheckSchemaValidation(invalidXml));
+ }
+
+ /// <summary>
+ /// Checks the schema validation.
+ /// </summary>
+ private static void CheckSchemaValidation()
+ {
+ var sb = new StringBuilder();
+
+ using (var xmlWriter = XmlWriter.Create(sb))
+ {
+ IgniteConfigurationXmlSerializer.Serialize(GetTestConfig(), xmlWriter, "igniteConfiguration");
+ }
+
+ CheckSchemaValidation(sb.ToString());
+ }
+
+ /// <summary>
+ /// Checks the schema validation.
+ /// </summary>
+ /// <param name="xml">The XML.</param>
+ private static void CheckSchemaValidation(string xml)
+ {
+ var document = new XmlDocument();
+
+ document.Schemas.Add("http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection",
+ XmlReader.Create("IgniteConfigurationSection.xsd"));
+
+ document.Load(new StringReader(xml));
+
+ document.Validate(null);
+ }
+
+ /// <summary>
+ /// Checks the serialize deserialize.
+ /// </summary>
+ /// <param name="cfg">The config.</param>
+ private static void CheckSerializeDeserialize(IgniteConfiguration cfg)
+ {
+ var resCfg = SerializeDeserialize(cfg);
+
+ AssertReflectionEqual(cfg, resCfg);
+ }
+
+ /// <summary>
+ /// Serializes and deserializes a config.
+ /// </summary>
+ private static IgniteConfiguration SerializeDeserialize(IgniteConfiguration cfg)
+ {
+ var sb = new StringBuilder();
+
+ using (var xmlWriter = XmlWriter.Create(sb))
+ {
+ IgniteConfigurationXmlSerializer.Serialize(cfg, xmlWriter, "igniteConfig");
+ }
+
+ var xml = sb.ToString();
+
+ using (var xmlReader = XmlReader.Create(new StringReader(xml)))
+ {
+ xmlReader.MoveToContent();
+ return IgniteConfigurationXmlSerializer.Deserialize(xmlReader);
+ }
+ }
+
+ /// <summary>
+ /// Asserts equality with reflection.
+ /// </summary>
+ private static void AssertReflectionEqual(object x, object y)
+ {
+ var type = x.GetType();
+
+ Assert.AreEqual(type, y.GetType());
+
+ if (type.IsValueType || type == typeof (string) || type.IsSubclassOf(typeof (Type)))
+ {
+ Assert.AreEqual(x, y);
+ return;
+ }
+
+ var props = type.GetProperties();
+
+ foreach (var propInfo in props)
+ {
+ var propType = propInfo.PropertyType;
+
+ var xVal = propInfo.GetValue(x, null);
+ var yVal = propInfo.GetValue(y, null);
+
+ if (xVal == null || yVal == null)
+ {
+ Assert.IsNull(xVal);
+ Assert.IsNull(yVal);
+ }
+ else if (propType != typeof(string) && propType.IsGenericType
+ && propType.GetGenericTypeDefinition() == typeof (ICollection<>))
+ {
+ var xCol = ((IEnumerable) xVal).OfType<object>().ToList();
+ var yCol = ((IEnumerable) yVal).OfType<object>().ToList();
+
+ Assert.AreEqual(xCol.Count, yCol.Count);
+
+ for (int i = 0; i < xCol.Count; i++)
+ AssertReflectionEqual(xCol[i], yCol[i]);
+ }
+ else
+ {
+ AssertReflectionEqual(xVal, yVal);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the test configuration.
+ /// </summary>
+ private static IgniteConfiguration GetTestConfig()
+ {
+ return new IgniteConfiguration
+ {
+ GridName = "gridName",
+ JvmOptions = new[] {"1", "2"},
+ Localhost = "localhost11",
+ JvmClasspath = "classpath",
+ Assemblies = new[] {"asm1", "asm2", "asm3"},
+ BinaryConfiguration = new BinaryConfiguration
+ {
+ TypeConfigurations = new[]
+ {
+ new BinaryTypeConfiguration
+ {
+ IsEnum = true,
+ KeepDeserialized = true,
+ AffinityKeyFieldName = "affKeyFieldName",
+ TypeName = "typeName",
+ IdMapper = new IdMapper(),
+ NameMapper = new NameMapper(),
+ Serializer = new TestSerializer()
+ }
+ },
+ DefaultIdMapper = new IdMapper(),
+ DefaultKeepDeserialized = true,
+ DefaultNameMapper = new NameMapper(),
+ DefaultSerializer = new TestSerializer()
+ },
+ CacheConfiguration = new[]
+ {
+ new CacheConfiguration("cacheName")
+ {
+ AtomicWriteOrderMode = CacheAtomicWriteOrderMode.Primary,
+ AtomicityMode = CacheAtomicityMode.Transactional,
+ Backups = 15,
+ CacheMode = CacheMode.Partitioned,
+ CacheStoreFactory = new TestCacheStoreFactory(),
+ CopyOnRead = true,
+ EagerTtl = true,
+ EnableSwap = true,
+ EvictSynchronized = true,
+ EvictSynchronizedConcurrencyLevel = 13,
+ EvictSynchronizedKeyBufferSize = 14,
+ EvictSynchronizedTimeout = TimeSpan.FromMinutes(3),
+ Invalidate = true,
+ KeepBinaryInStore = true,
+ LoadPreviousValue = true,
+ LockTimeout = TimeSpan.FromSeconds(56),
+ LongQueryWarningTimeout = TimeSpan.FromSeconds(99),
+ MaxConcurrentAsyncOperations = 24,
+ MaxEvictionOverflowRatio = 5.6F,
+ MemoryMode = CacheMemoryMode.OffheapValues,
+ OffHeapMaxMemory = 567,
+ QueryEntities = new[]
+ {
+ new QueryEntity
+ {
+ Fields = new[]
+ {
+ new QueryField("field", typeof (int))
+ },
+ Indexes = new[]
+ {
+ new QueryIndex("field") { IndexType = QueryIndexType.FullText }
+ },
+ Aliases = new[]
+ {
+ new QueryAlias("field.field", "fld")
+ },
+ KeyType = typeof (string),
+ ValueType = typeof (long)
+ },
+ },
+ ReadFromBackup = true,
+ RebalanceBatchSize = 33,
+ RebalanceDelay = TimeSpan.MaxValue,
+ RebalanceMode = CacheRebalanceMode.Sync,
+ RebalanceThrottle = TimeSpan.FromHours(44),
+ RebalanceTimeout = TimeSpan.FromMinutes(8),
+ SqlEscapeAll = true,
+ SqlOnheapRowCacheSize = 679,
+ StartSize = 1023,
+ WriteBehindBatchSize = 45,
+ WriteBehindEnabled = true,
+ WriteBehindFlushFrequency = TimeSpan.FromSeconds(5),
+ WriteBehindFlushSize = 66,
+ WriteBehindFlushThreadCount = 2,
+ WriteSynchronizationMode = CacheWriteSynchronizationMode.FullAsync
+ }
+ },
+ ClientMode = true,
+ DiscoverySpi = new TcpDiscoverySpi
+ {
+ NetworkTimeout = TimeSpan.FromSeconds(1),
+ SocketTimeout = TimeSpan.FromSeconds(2),
+ AckTimeout = TimeSpan.FromSeconds(3),
+ JoinTimeout = TimeSpan.FromSeconds(4),
+ MaxAckTimeout = TimeSpan.FromSeconds(5),
+ IpFinder = new TcpDiscoveryMulticastIpFinder
+ {
+ TimeToLive = 110,
+ MulticastGroup = "multicastGroup",
+ AddressRequestAttempts = 10,
+ MulticastPort = 987,
+ ResponseTimeout = TimeSpan.FromDays(1),
+ LocalAddress = "127.0.0.2",
+ Endpoints = new[] {"", "abc"}
+ }
+ },
+ IgniteHome = "igniteHome",
+ IncludedEventTypes = EventType.CacheQueryAll,
+ JvmDllPath = @"c:\jvm",
+ JvmInitialMemoryMb = 1024,
+ JvmMaxMemoryMb = 2048,
+ LifecycleBeans = new[] {new LifecycleBean(), new LifecycleBean() },
+ MetricsExpireTime = TimeSpan.FromSeconds(15),
+ MetricsHistorySize = 45,
+ MetricsLogFrequency = TimeSpan.FromDays(2),
+ MetricsUpdateFrequency = TimeSpan.MinValue,
+ NetworkSendRetryCount = 7,
+ NetworkSendRetryDelay = TimeSpan.FromSeconds(98),
+ NetworkTimeout = TimeSpan.FromMinutes(4),
+ SuppressWarnings = true,
+ WorkDirectory = @"c:\work"
+ };
+ }
+
+ /// <summary>
+ /// Runs the with custom culture.
+ /// </summary>
+ /// <param name="action">The action.</param>
+ private static void RunWithCustomCulture(Action action)
+ {
+ RunWithCulture(action, CultureInfo.InvariantCulture);
+ RunWithCulture(action, CultureInfo.GetCultureInfo("ru-RU"));
+ }
+
+ /// <summary>
+ /// Runs the with culture.
+ /// </summary>
+ /// <param name="action">The action.</param>
+ /// <param name="cultureInfo">The culture information.</param>
+ private static void RunWithCulture(Action action, CultureInfo cultureInfo)
+ {
+ var oldCulture = Thread.CurrentThread.CurrentCulture;
+
+ try
+ {
+ Thread.CurrentThread.CurrentCulture = cultureInfo;
+
+ action();
+ }
+ finally
+ {
+ Thread.CurrentThread.CurrentCulture = oldCulture;
+ }
+ }
+
+ /// <summary>
+ /// Test bean.
+ /// </summary>
+ public class LifecycleBean : ILifecycleBean
+ {
+ /// <summary>
+ /// Gets or sets the foo.
+ /// </summary>
+ /// <value>
+ /// The foo.
+ /// </value>
+ public int Foo { get; set; }
+
+ /// <summary>
+ /// This method is called when lifecycle event occurs.
+ /// </summary>
+ /// <param name="evt">Lifecycle event.</param>
+ public void OnLifecycleEvent(LifecycleEventType evt)
+ {
+ // No-op.
+ }
+ }
+
+ /// <summary>
+ /// Test mapper.
+ /// </summary>
+ public class NameMapper : IBinaryNameMapper
+ {
+ /// <summary>
+ /// Gets or sets the bar.
+ /// </summary>
+ /// <value>
+ /// The bar.
+ /// </value>
+ public string Bar { get; set; }
+
+ /// <summary>
+ /// Gets the type name.
+ /// </summary>
+ /// <param name="name">The name.</param>
+ /// <returns>
+ /// Type name.
+ /// </returns>
+ public string GetTypeName(string name)
+ {
+ return name;
+ }
+
+ /// <summary>
+ /// Gets the field name.
+ /// </summary>
+ /// <param name="name">The name.</param>
+ /// <returns>
+ /// Field name.
+ /// </returns>
+ public string GetFieldName(string name)
+ {
+ return name;
+ }
+ }
+
+ /// <summary>
+ /// Serializer.
+ /// </summary>
+ public class TestSerializer : IBinarySerializer
+ {
+ /// <summary>
+ /// Write portalbe object.
+ /// </summary>
+ /// <param name="obj">Object.</param>
+ /// <param name="writer">Poratble writer.</param>
+ public void WriteBinary(object obj, IBinaryWriter writer)
+ {
+ // No-op.
+ }
+
+ /// <summary>
+ /// Read binary object.
+ /// </summary>
+ /// <param name="obj">Instantiated empty object.</param>
+ /// <param name="reader">Poratble reader.</param>
+ public void ReadBinary(object obj, IBinaryReader reader)
+ {
+ // No-op.
+ }
+ }
+
+ /// <summary>
+ /// Test class.
+ /// </summary>
+ public class FooClass
+ {
+ // No-op.
+ }
+
+ /// <summary>
+ /// Test factory.
+ /// </summary>
+ public class TestCacheStoreFactory : IFactory<ICacheStore>
+ {
+ /// <summary>
+ /// Creates an instance of the cache store.
+ /// </summary>
+ /// <returns>
+ /// New instance of the cache store.
+ /// </returns>
+ public ICacheStore CreateInstance()
+ {
+ return null;
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core.Tests/app.config
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/app.config b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/app.config
new file mode 100644
index 0000000..c290c83
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/app.config
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ 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.
+-->
+
+<configuration>
+ <configSections>
+ <section name="igniteConfiguration" type="Apache.Ignite.Core.IgniteConfigurationSection, Apache.Ignite.Core" />
+ <section name="igniteConfiguration2" type="Apache.Ignite.Core.IgniteConfigurationSection, Apache.Ignite.Core" />
+ </configSections>
+
+ <igniteConfiguration xmlns="http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection" gridName="myGrid1">
+ <discoverySpi type="TcpDiscoverySpi">
+ <ipFinder type="TcpDiscoveryStaticIpFinder">
+ <endpoints>
+ <string>127.0.0.1:47500..47501</string>
+ </endpoints>
+ </ipFinder>
+ </discoverySpi>
+
+ <cacheConfiguration>
+ <cacheConfiguration name="cacheName" />
+ </cacheConfiguration>
+ </igniteConfiguration>
+
+ <igniteConfiguration2 gridName="myGrid2">
+ <discoverySpi type="TcpDiscoverySpi">
+ <ipFinder type="TcpDiscoveryStaticIpFinder">
+ <endpoints>
+ <string>127.0.0.1:47500..47501</string>
+ </endpoints>
+ </ipFinder>
+ </discoverySpi>
+
+ <cacheConfiguration>
+ <cacheConfiguration name="cacheName2" />
+ </cacheConfiguration>
+ </igniteConfiguration2>
+
+</configuration>
http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
index e2efd0a..d0ef352 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -60,7 +60,9 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
+ <Reference Include="System.configuration" />
<Reference Include="System.Core" />
+ <Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Binary\Package-Info.cs" />
@@ -183,6 +185,7 @@
<Compile Include="Events\TaskEvent.cs" />
<Compile Include="GlobalSuppressions.cs" />
<Compile Include="IgniteConfiguration.cs" />
+ <Compile Include="IgniteConfigurationSection.cs" />
<Compile Include="Ignition.cs" />
<Compile Include="IIgnite.cs" />
<Compile Include="Impl\Binary\BinaryEnum.cs" />
@@ -222,11 +225,13 @@
<Compile Include="Impl\Collections\MultiValueDictionary.cs" />
<Compile Include="Impl\Collections\ReadOnlyCollection.cs" />
<Compile Include="Impl\Collections\ReadOnlyDictionary.cs" />
+ <Compile Include="Impl\Common\BooleanLowerCaseConverter.cs" />
<Compile Include="Impl\Common\CancelledTask.cs" />
<Compile Include="Impl\Common\Classpath.cs" />
<Compile Include="Impl\Common\CopyOnWriteConcurrentDictionary.cs" />
<Compile Include="Impl\Common\DelegateConverter.cs" />
<Compile Include="Impl\Common\DelegateTypeDescriptor.cs" />
+ <Compile Include="Impl\Events\EventTypeConverter.cs" />
<Compile Include="Impl\Common\Fnv1Hash.cs" />
<Compile Include="Impl\Common\Future.cs" />
<Compile Include="Impl\Common\FutureConverter.cs" />
@@ -234,10 +239,12 @@
<Compile Include="Impl\Common\IgniteArgumentCheck.cs" />
<Compile Include="Impl\Common\IFutureConverter.cs" />
<Compile Include="Impl\Common\IFutureInternal.cs" />
+ <Compile Include="Impl\Common\IgniteConfigurationXmlSerializer.cs" />
<Compile Include="Impl\Common\IgniteHome.cs" />
<Compile Include="Impl\Common\LoadedAssembliesResolver.cs" />
<Compile Include="Impl\Common\ResizeableArray.cs" />
<Compile Include="Impl\Common\TypeCaster.cs" />
+ <Compile Include="Impl\Common\TypeStringConverter.cs" />
<Compile Include="Impl\Compute\Closure\ComputeAbstractClosureTask.cs" />
<Compile Include="Impl\Compute\Closure\ComputeActionJob.cs" />
<Compile Include="Impl\Compute\Closure\ComputeFuncJob.cs" />
@@ -434,6 +441,10 @@
<ItemGroup>
<None Include="Apache.Ignite.Core.ruleset" />
<None Include="Apache.Ignite.Core.snk" />
+ <None Include="IgniteConfigurationSection.xsd">
+ <SubType>Designer</SubType>
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinarySerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinarySerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinarySerializer.cs
index 23dc811..3f924eb 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinarySerializer.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinarySerializer.cs
@@ -23,17 +23,17 @@ namespace Apache.Ignite.Core.Binary
public interface IBinarySerializer
{
/// <summary>
- /// Write portalbe object.
+ /// Write binary object.
/// </summary>
/// <param name="obj">Object.</param>
- /// <param name="writer">Poratble writer.</param>
+ /// <param name="writer">Binary writer.</param>
void WriteBinary(object obj, IBinaryWriter writer);
/// <summary>
/// Read binary object.
/// </summary>
/// <param name="obj">Instantiated empty object.</param>
- /// <param name="reader">Poratble reader.</param>
+ /// <param name="reader">Binary reader.</param>
void ReadBinary(object obj, IBinaryReader reader);
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.cs b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.cs
new file mode 100644
index 0000000..51b963e
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.cs
@@ -0,0 +1,80 @@
+/*
+ * 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
+{
+ using System.Configuration;
+ using System.Text;
+ using System.Xml;
+ using Apache.Ignite.Core.Impl.Common;
+
+ /// <summary>
+ /// Ignite configuration section for app.config and web.config files.
+ /// </summary>
+ public class IgniteConfigurationSection : ConfigurationSection
+ {
+ /// <summary>
+ /// Gets or sets the ignite configuration.
+ /// </summary>
+ /// <value>
+ /// The ignite configuration.
+ /// </value>
+ public IgniteConfiguration IgniteConfiguration { get; private set; }
+
+ /// <summary>
+ /// Reads XML from the configuration file.
+ /// </summary>
+ /// <param name="reader">The reader object, which reads from the configuration file.</param>
+ protected override void DeserializeSection(XmlReader reader)
+ {
+ IgniteArgumentCheck.NotNull(reader, "reader");
+
+ IgniteConfiguration = IgniteConfigurationXmlSerializer.Deserialize(reader);
+ }
+
+ /// <summary>
+ /// Creates an XML string containing an unmerged view of the <see cref="ConfigurationSection" />
+ /// object as a single section to write to a file.
+ /// </summary>
+ /// <param name="parentElement">The <see cref="ConfigurationElement" />
+ /// instance to use as the parent when performing the un-merge.</param>
+ /// <param name="name">The name of the section to create.</param>
+ /// <param name="saveMode">The <see cref="ConfigurationSaveMode" /> instance
+ /// to use when writing to a string.</param>
+ /// <returns>
+ /// An XML string containing an unmerged view of the <see cref="ConfigurationSection" /> object.
+ /// </returns>
+ protected override string SerializeSection(ConfigurationElement parentElement, string name,
+ ConfigurationSaveMode saveMode)
+ {
+ IgniteArgumentCheck.NotNull(parentElement, "parentElement");
+ IgniteArgumentCheck.NotNullOrEmpty(name, "name");
+
+ if (IgniteConfiguration == null)
+ return string.Format("<{0} />", name);
+
+ var sb = new StringBuilder();
+
+ using (var xmlWriter = XmlWriter.Create(sb))
+ {
+ IgniteConfigurationXmlSerializer.Serialize(IgniteConfiguration, xmlWriter, name);
+
+ return sb.ToString();
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
new file mode 100644
index 0000000..5181217
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
@@ -0,0 +1,281 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ 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.
+-->
+
+<xs:schema id="IgniteConfigurationSection"
+ targetNamespace="http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection"
+ elementFormDefault="qualified"
+ xmlns="http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection"
+ xmlns:mstns="http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xs:element name="igniteConfiguration">
+ <xs:complexType>
+ <xs:all>
+ <xs:element name="binaryConfiguration" minOccurs="0">
+ <xs:complexType>
+ <xs:all>
+ <xs:element name="typeConfigurations" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="binaryTypeConfiguration">
+ <xs:complexType>
+ <xs:all>
+ <xs:element name="nameMapper" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="type" type="xs:string" use="required" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="idMapper" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="type" type="xs:string" use="required" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="serializer" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="type" type="xs:string" use="required" />
+ </xs:complexType>
+ </xs:element>
+ </xs:all>
+ <xs:attribute name="typeName" type="xs:string" />
+ <xs:attribute name="affinityKeyFieldName" type="xs:string" />
+ <xs:attribute name="keepDeserialized" type="xs:string" />
+ <xs:attribute name="isEnum" type="xs:boolean" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="defaultNameMapper" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="type" type="xs:string" use="required" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="defaultIdMapper" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="type" type="xs:string" use="required" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="defaultSerializer" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="type" type="xs:string" use="required" />
+ </xs:complexType>
+ </xs:element>
+ </xs:all>
+ <xs:attribute name="defaultKeepDeserialized" type="xs:boolean" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="cacheConfiguration" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="cacheConfiguration" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:all>
+ <xs:element name="cacheStoreFactory" minOccurs="0">
+ <xs:complexType>
+ <xs:attribute name="type" type="xs:string" use="required" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="queryEntities" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="queryEntity" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:all>
+ <xs:element name="fields" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="queryField" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required" />
+ <xs:attribute name="fieldType" type="xs:string" />
+ <xs:attribute name="fieldTypeName" type="xs:string" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="aliases" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="queryAlias" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="fullName" type="xs:string" use="required" />
+ <xs:attribute name="alias" type="xs:string" use="required" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="indexes" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="queryIndex" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="fields" minOccurs="1">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="queryIndexField" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="name" type="xs:string" use="required" />
+ <xs:attribute name="isDescending" type="xs:boolean" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="name" type="xs:string" />
+ <xs:attribute name="indexType" type="xs:string" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:all>
+ <xs:attribute name="keyTypeName" type="xs:string"/>
+ <xs:attribute name="keyType" type="xs:string" />
+ <xs:attribute name="valueTypeName" type="xs:string" />
+ <xs:attribute name="valueType" type="xs:string" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:all>
+ <xs:attribute name="name" type="xs:string" />
+ <xs:attribute name="writeSynchronizationMode" type="xs:string" />
+ <xs:attribute name="evictSynchronized" type="xs:boolean" />
+ <xs:attribute name="evictSynchronizedKeyBufferSize" type="xs:int" />
+ <xs:attribute name="evictSynchronizedConcurrencyLevel" type="xs:int" />
+ <xs:attribute name="evictSynchronizedTimeout" type="xs:string" />
+ <xs:attribute name="maxEvictionOverflowRatio" type="xs:decimal" />
+ <xs:attribute name="startSize" type="xs:int" />
+ <xs:attribute name="loadPreviousValue" type="xs:string" />
+ <xs:attribute name="atomicityMode" type="xs:string" />
+ <xs:attribute name="atomicWriteOrderMode" type="xs:string" />
+ <xs:attribute name="backups" type="xs:int" />
+ <xs:attribute name="lockTimeout" type="xs:string" />
+ <xs:attribute name="invalidate" type="xs:boolean" />
+ <xs:attribute name="rebalanceMode" type="xs:string" />
+ <xs:attribute name="rebalanceBatchSize" type="xs:int" />
+ <xs:attribute name="enableSwap" type="xs:boolean" />
+ <xs:attribute name="maxConcurrentAsyncOperations" type="xs:int" />
+ <xs:attribute name="writeBehindEnabled" type="xs:boolean" />
+ <xs:attribute name="writeBehindFlushSize" type="xs:int" />
+ <xs:attribute name="writeBehindFlushThreadCount" type="xs:int" />
+ <xs:attribute name="writeBehindBatchSize" type="xs:int" />
+ <xs:attribute name="rebalanceTimeout" type="xs:string" />
+ <xs:attribute name="rebalanceDelay" type="xs:string" />
+ <xs:attribute name="rebalanceThrottle" type="xs:string" />
+ <xs:attribute name="offHeapMaxMemory" type="xs:int" />
+ <xs:attribute name="memoryMode" type="xs:string" />
+ <xs:attribute name="longQueryWarningTimeout" type="xs:string" />
+ <xs:attribute name="sqlEscapeAll" type="xs:boolean" />
+ <xs:attribute name="sqlOnheapRowCacheSize" type="xs:int" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="jvmOptions" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="string" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="assemblies" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="string" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="lifecycleBeans" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="iLifecycleBean">
+ <xs:complexType>
+ <xs:attribute name="type" type="xs:string" use="required" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="discoverySpi" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="ipFinder" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="endpoints" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="string" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="type" type="xs:string" use="required" />
+ <xs:attribute name="localAddress" type="xs:string" />
+ <xs:attribute name="multicastGroup" type="xs:string" />
+ <xs:attribute name="multicastPort" type="xs:int" />
+ <xs:attribute name="addressRequestAttempts" type="xs:int" />
+ <xs:attribute name="responseTimeout" type="xs:string" />
+ <xs:attribute name="timeToLive" type="xs:byte" />
+ </xs:complexType>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="socketTimeout" type="xs:string" />
+ <xs:attribute name="ackTimeout" type="xs:string" />
+ <xs:attribute name="maxAckTimeout" type="xs:string" />
+ <xs:attribute name="networkTimeout" type="xs:string" />
+ <xs:attribute name="joinTimeout" type="xs:string" />
+ <xs:attribute name="type" type="xs:string" use="required" />
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="includedEventTypes" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" name="int" type="xs:string" />
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:all>
+ <xs:attribute name="gridName" type="xs:string" />
+ <xs:attribute name="jvmDllPath" type="xs:string" />
+ <xs:attribute name="igniteHome" type="xs:string" />
+ <xs:attribute name="jvmClasspath" type="xs:string" />
+ <xs:attribute name="suppressWarnings" type="xs:boolean" />
+ <xs:attribute name="jvmInitialMemoryMb" type="xs:int" />
+ <xs:attribute name="jvmMaxMemoryMb" type="xs:int" />
+ <xs:attribute name="clientMode" type="xs:boolean" />
+ <xs:attribute name="metricsExpireTime" type="xs:string" />
+ <xs:attribute name="metricsHistorySize" type="xs:int" />
+ <xs:attribute name="metricsLogFrequency" type="xs:string" />
+ <xs:attribute name="metricsUpdateFrequency" type="xs:string" />
+ <xs:attribute name="networkSendRetryCount" type="xs:int" />
+ <xs:attribute name="networkSendRetryDelay" type="xs:string" />
+ <xs:attribute name="networkTimeout" type="xs:string" />
+ <xs:attribute name="workDirectory" type="xs:string" />
+ <xs:attribute name="localhost" type="xs:string" />
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
index 0549010..70d7422 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
@@ -20,6 +20,7 @@ namespace Apache.Ignite.Core
{
using System;
using System.Collections.Generic;
+ using System.Configuration;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
@@ -116,6 +117,44 @@ namespace Apache.Ignite.Core
}
/// <summary>
+ /// Reads <see cref="IgniteConfiguration"/> from first <see cref="IgniteConfigurationSection"/> in the
+ /// application configuration and starts Ignite.
+ /// </summary>
+ /// <returns>Started Ignite.</returns>
+ public static IIgnite StartFromApplicationConfiguration()
+ {
+ var cfg = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
+
+ var section = cfg.Sections.OfType<IgniteConfigurationSection>().FirstOrDefault();
+
+ if (section == null)
+ throw new ConfigurationErrorsException(
+ string.Format("Could not find {0} in current application configuration",
+ typeof(IgniteConfigurationSection).Name));
+
+ return Start(section.IgniteConfiguration);
+ }
+
+ /// <summary>
+ /// Reads <see cref="IgniteConfiguration"/> from application configuration
+ /// <see cref="IgniteConfigurationSection"/> with specified name and starts Ignite.
+ /// </summary>
+ /// <param name="sectionName">Name of the section.</param>
+ /// <returns>Started Ignite.</returns>
+ public static IIgnite StartFromApplicationConfiguration(string sectionName)
+ {
+ IgniteArgumentCheck.NotNullOrEmpty(sectionName, "sectionName");
+
+ var section = ConfigurationManager.GetSection(sectionName) as IgniteConfigurationSection;
+
+ if (section == null)
+ throw new ConfigurationErrorsException(string.Format("Could not find {0} with name '{1}'",
+ typeof(IgniteConfigurationSection).Name, sectionName));
+
+ return Start(section.IgniteConfiguration);
+ }
+
+ /// <summary>
/// Starts Ignite with given configuration.
/// </summary>
/// <returns>Started Ignite.</returns>
http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/BooleanLowerCaseConverter.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/BooleanLowerCaseConverter.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/BooleanLowerCaseConverter.cs
new file mode 100644
index 0000000..e8cced2
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/BooleanLowerCaseConverter.cs
@@ -0,0 +1,60 @@
+/*
+ * 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.Common
+{
+ using System;
+ using System.ComponentModel;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Globalization;
+
+ /// <summary>
+ /// Bollean converter that returns lower-case strings, for XML serialization.
+ /// </summary>
+ internal class BooleanLowerCaseConverter : BooleanConverter
+ {
+ /// <summary>
+ /// Default instance.
+ /// </summary>
+ public static readonly BooleanLowerCaseConverter Instance = new BooleanLowerCaseConverter();
+
+ /// <summary>
+ /// Converts the given value object to the specified type, using the specified context and culture information.
+ /// </summary>
+ /// <param name="context">An <see cref="ITypeDescriptorContext" /> that provides a format context.</param>
+ /// <param name="culture">
+ /// A <see cref="CultureInfo" />. If null is passed, the current culture is assumed.
+ /// </param>
+ /// <param name="value">The <see cref="object" /> to convert.</param>
+ /// <param name="destinationType">
+ /// The <see cref="Type" /> to convert the <paramref name="value" /> parameter to.
+ /// </param>
+ /// <returns>
+ /// An <see cref="object" /> that represents the converted value.
+ /// </returns>
+ [SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase")]
+ [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "2")]
+ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value,
+ Type destinationType)
+ {
+ if (destinationType == typeof (string))
+ return value.ToString().ToLowerInvariant();
+
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/a4d8a049/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs
new file mode 100644
index 0000000..af25bfa
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/IgniteConfigurationXmlSerializer.cs
@@ -0,0 +1,410 @@
+/*
+ * 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.Common
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.ComponentModel;
+ using System.Configuration;
+ using System.Diagnostics;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Linq;
+ using System.Reflection;
+ using System.Xml;
+ using Apache.Ignite.Core.Impl.Events;
+
+ /// <summary>
+ /// Serializes <see cref="IgniteConfiguration"/> to XML.
+ /// </summary>
+ internal static class IgniteConfigurationXmlSerializer
+ {
+ /** Attribute that specifies a type for abstract properties, such as IpFinder. */
+ private const string TypNameAttribute = "type";
+
+ /** Xmlns. */
+ private const string XmlnsAttribute = "xmlns";
+
+ /** Schema. */
+ private const string Schema = "http://ignite.apache.org/schema/dotnet/IgniteConfigurationSection";
+
+ /// <summary>
+ /// Deserializes <see cref="IgniteConfiguration"/> from specified <see cref="XmlReader"/>.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ /// <returns>Resulting <see cref="IgniteConfiguration"/>.</returns>
+ public static IgniteConfiguration Deserialize(XmlReader reader)
+ {
+ IgniteArgumentCheck.NotNull(reader, "reader");
+
+ var cfg = new IgniteConfiguration();
+
+ if (reader.NodeType == XmlNodeType.Element || reader.Read())
+ ReadElement(reader, cfg);
+
+ return cfg;
+ }
+
+ /// <summary>
+ /// Serializes specified <see cref="IgniteConfiguration" /> to <see cref="XmlWriter" />.
+ /// </summary>
+ /// <param name="configuration">The configuration.</param>
+ /// <param name="writer">The writer.</param>
+ /// <param name="rootElementName">Name of the root element.</param>
+ public static void Serialize(IgniteConfiguration configuration, XmlWriter writer, string rootElementName)
+ {
+ IgniteArgumentCheck.NotNull(configuration, "configuration");
+ IgniteArgumentCheck.NotNull(writer, "writer");
+ IgniteArgumentCheck.NotNullOrEmpty(rootElementName, "rootElementName");
+
+ WriteElement(configuration, writer, rootElementName, typeof(IgniteConfiguration));
+ }
+
+ /// <summary>
+ /// Writes new element.
+ /// </summary>
+ private static void WriteElement(object obj, XmlWriter writer, string rootElementName, Type valueType,
+ PropertyInfo property = null)
+ {
+ if (valueType == typeof(IgniteConfiguration))
+ writer.WriteStartElement(rootElementName, Schema); // write xmlns for the root element
+ else
+ writer.WriteStartElement(rootElementName);
+
+ if (IsBasicType(valueType))
+ WriteBasicProperty(obj, writer, valueType, property);
+ else if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof (ICollection<>))
+ WriteCollectionProperty(obj, writer, valueType, property);
+ else
+ WriteComplexProperty(obj, writer, valueType);
+
+ writer.WriteEndElement();
+ }
+
+ /// <summary>
+ /// Writes the property of a basic type (primitives, strings, types).
+ /// </summary>
+ [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
+ private static void WriteBasicProperty(object obj, XmlWriter writer, Type valueType, PropertyInfo property)
+ {
+ var converter = GetConverter(property, valueType);
+
+ var stringValue = converter.ConvertToInvariantString(obj);
+
+ writer.WriteString(stringValue);
+ }
+
+ /// <summary>
+ /// Writes the collection property.
+ /// </summary>
+ private static void WriteCollectionProperty(object obj, XmlWriter writer, Type valueType, PropertyInfo property)
+ {
+ var elementType = valueType.GetGenericArguments().Single();
+
+ var elementTypeName = PropertyNameToXmlName(elementType.Name);
+
+ foreach (var element in (IEnumerable)obj)
+ WriteElement(element, writer, elementTypeName, elementType, property);
+ }
+
+ /// <summary>
+ /// Writes the complex property (nested object).
+ /// </summary>
+ [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute")]
+ private static void WriteComplexProperty(object obj, XmlWriter writer, Type valueType)
+ {
+ var props = GetNonDefaultProperties(obj).ToList();
+
+ // Specify type for interfaces and abstract classes
+ if (valueType.IsAbstract)
+ writer.WriteAttributeString(TypNameAttribute, TypeStringConverter.Convert(obj.GetType()));
+
+ // Write attributes
+ foreach (var prop in props.Where(p => IsBasicType(p.PropertyType)))
+ {
+ var converter = GetConverter(prop, prop.PropertyType);
+ var stringValue = converter.ConvertToInvariantString(prop.GetValue(obj, null));
+ writer.WriteAttributeString(PropertyNameToXmlName(prop.Name), stringValue);
+ }
+
+ // Write elements
+ foreach (var prop in props.Where(p => !IsBasicType(p.PropertyType)))
+ WriteElement(prop.GetValue(obj, null), writer, PropertyNameToXmlName(prop.Name),
+ prop.PropertyType, prop);
+ }
+
+ /// <summary>
+ /// Reads the element.
+ /// </summary>
+ private static void ReadElement(XmlReader reader, object target)
+ {
+ var targetType = target.GetType();
+
+ // Read attributes
+ while (reader.MoveToNextAttribute())
+ {
+ var name = reader.Name;
+ var val = reader.Value;
+
+ SetProperty(target, name, val);
+ }
+
+ // Read content
+ reader.MoveToElement();
+
+ while (reader.Read())
+ {
+ if (reader.NodeType != XmlNodeType.Element)
+ continue;
+
+ var name = reader.Name;
+ var prop = GetPropertyOrThrow(name, reader.Value, targetType);
+ var propType = prop.PropertyType;
+
+ if (IsBasicType(propType))
+ {
+ // Regular property in xmlElement form
+ SetProperty(target, name, reader.ReadString());
+ }
+ else if (propType.IsGenericType && propType.GetGenericTypeDefinition() == typeof (ICollection<>))
+ {
+ // Collection
+ ReadCollectionProperty(reader, prop, target);
+ }
+ else
+ {
+ // Nested object (complex property)
+ prop.SetValue(target, ReadComplexProperty(reader, propType, prop.Name, targetType), null);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Reads the complex property (nested object).
+ /// </summary>
+ private static object ReadComplexProperty(XmlReader reader, Type propType, string propName, Type targetType)
+ {
+ if (propType.IsAbstract)
+ {
+ var typeName = reader.GetAttribute(TypNameAttribute);
+
+ var derivedTypes = GetConcreteDerivedTypes(propType);
+
+ propType = typeName == null
+ ? null
+ : Type.GetType(typeName, false) ?? derivedTypes.FirstOrDefault(x => x.Name == typeName);
+
+ if (propType == null)
+ {
+ var message = string.Format("'type' attribute is required for '{0}.{1}' property", targetType.Name,
+ propName);
+
+ if (typeName != null)
+ {
+ message += ", specified type cannot be resolved: " + typeName;
+ }
+ else if (derivedTypes.Any())
+ message += ", possible values are: " + string.Join(", ", derivedTypes.Select(x => x.Name));
+
+ throw new ConfigurationErrorsException(message);
+ }
+ }
+
+ var nestedVal = Activator.CreateInstance(propType);
+
+ using (var subReader = reader.ReadSubtree())
+ {
+ subReader.Read(); // read first element
+
+ ReadElement(subReader, nestedVal);
+ }
+
+ return nestedVal;
+ }
+
+ /// <summary>
+ /// Reads the collection.
+ /// </summary>
+ private static void ReadCollectionProperty(XmlReader reader, PropertyInfo prop, object target)
+ {
+ var elementType = prop.PropertyType.GetGenericArguments().Single();
+
+ var listType = typeof (List<>).MakeGenericType(elementType);
+
+ var list = (IList) Activator.CreateInstance(listType);
+
+ var converter = IsBasicType(elementType) ? GetConverter(prop, elementType) : null;
+
+ using (var subReader = reader.ReadSubtree())
+ {
+ subReader.Read(); // skip list head
+ while (subReader.Read())
+ {
+ if (subReader.NodeType != XmlNodeType.Element)
+ continue;
+
+ if (subReader.Name != PropertyNameToXmlName(elementType.Name))
+ throw new ConfigurationErrorsException(
+ string.Format("Invalid list element in IgniteConfiguration: expected '{0}', but was '{1}'",
+ PropertyNameToXmlName(elementType.Name), subReader.Name));
+
+ list.Add(converter != null
+ ? converter.ConvertFromInvariantString(subReader.ReadString())
+ : ReadComplexProperty(subReader, elementType, prop.Name, target.GetType()));
+ }
+ }
+
+ prop.SetValue(target, list, null);
+ }
+
+ /// <summary>
+ /// Sets the property.
+ /// </summary>
+ private static void SetProperty(object target, string propName, string propVal)
+ {
+ if (propName == TypNameAttribute || propName == XmlnsAttribute)
+ return;
+
+ var type = target.GetType();
+ var property = GetPropertyOrThrow(propName, propVal, type);
+
+ var converter = GetConverter(property, property.PropertyType);
+
+ var convertedVal = converter.ConvertFromInvariantString(propVal);
+
+ property.SetValue(target, convertedVal, null);
+ }
+
+ /// <summary>
+ /// Gets concrete derived types.
+ /// </summary>
+ private static List<Type> GetConcreteDerivedTypes(Type type)
+ {
+ return type.Assembly.GetTypes().Where(t => t.IsClass && !t.IsAbstract && type.IsAssignableFrom(t)).ToList();
+ }
+
+ /// <summary>
+ /// Gets specified property from a type or throws an exception.
+ /// </summary>
+ private static PropertyInfo GetPropertyOrThrow(string propName, string propVal, Type type)
+ {
+ var property = type.GetProperty(XmlNameToPropertyName(propName));
+
+ if (property == null)
+ throw new ConfigurationErrorsException(
+ string.Format(
+ "Invalid IgniteConfiguration attribute '{0}={1}', there is no such property on '{2}'",
+ propName, propVal, type));
+
+ return property;
+ }
+
+ /// <summary>
+ /// Converts an XML name to CLR name.
+ /// </summary>
+ private static string XmlNameToPropertyName(string name)
+ {
+ Debug.Assert(name.Length > 0);
+
+ if (name == "int")
+ return "Int32"; // allow aliases
+
+ return char.ToUpperInvariant(name[0]) + name.Substring(1);
+ }
+
+ /// <summary>
+ /// Converts a CLR name to XML name.
+ /// </summary>
+ private static string PropertyNameToXmlName(string name)
+ {
+ Debug.Assert(name.Length > 0);
+
+ if (name == "Int32")
+ return "int"; // allow aliases
+
+ return char.ToLowerInvariant(name[0]) + name.Substring(1);
+ }
+
+ /// <summary>
+ /// Determines whether specified type is a basic built-in type.
+ /// </summary>
+ private static bool IsBasicType(Type propertyType)
+ {
+ Debug.Assert(propertyType != null);
+
+ return propertyType.IsValueType || propertyType == typeof(string) || propertyType == typeof(Type);
+ }
+
+ /// <summary>
+ /// Gets converter for a property.
+ /// </summary>
+ private static TypeConverter GetConverter(PropertyInfo property, Type propertyType)
+ {
+ Debug.Assert(property != null);
+ Debug.Assert(propertyType != null);
+
+ if (propertyType.IsEnum)
+ return new GenericEnumConverter(propertyType);
+
+ if (propertyType == typeof (Type))
+ return TypeStringConverter.Instance;
+
+ if (propertyType == typeof(bool))
+ return BooleanLowerCaseConverter.Instance;
+
+ if (property.DeclaringType == typeof (IgniteConfiguration) && property.Name == "IncludedEventTypes")
+ return EventTypeConverter.Instance;
+
+ var converter = TypeDescriptor.GetConverter(propertyType);
+
+ if (converter == null || !converter.CanConvertFrom(typeof(string)) ||
+ !converter.CanConvertTo(typeof(string)))
+ throw new ConfigurationErrorsException("No converter for type " + propertyType);
+
+ return converter;
+ }
+
+ /// <summary>
+ /// Gets properties with non-default value.
+ /// </summary>
+ private static IEnumerable<PropertyInfo> GetNonDefaultProperties(object obj)
+ {
+ Debug.Assert(obj != null);
+
+ return obj.GetType().GetProperties().Where(p => !Equals(p.GetValue(obj, null), GetDefaultValue(p)));
+ }
+
+ /// <summary>
+ /// Gets the default value for a property.
+ /// </summary>
+ private static object GetDefaultValue(PropertyInfo property)
+ {
+ var attr = property.GetCustomAttributes(true).OfType<DefaultValueAttribute>().FirstOrDefault();
+
+ if (attr != null)
+ return attr.Value;
+
+ var propertyType = property.PropertyType;
+
+ if (propertyType.IsValueType)
+ return Activator.CreateInstance(propertyType);
+
+ return null;
+ }
+ }
+}