IGNITE-7287 Thin client: add configurable idle connection timeout

This closes #3287


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/1a939b0a
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/1a939b0a
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/1a939b0a

Branch: refs/heads/ignite-zk
Commit: 1a939b0ae002ea7d7661e42f1468212a91b71e9c
Parents: 9d2bd45
Author: Pavel Tupitsyn <[email protected]>
Authored: Wed Dec 27 11:17:29 2017 +0300
Committer: Pavel Tupitsyn <[email protected]>
Committed: Wed Dec 27 11:17:29 2017 +0300

----------------------------------------------------------------------
 .../ClientConnectorConfiguration.java           | 33 +++++++++++++++++++
 .../odbc/ClientListenerNioListener.java         |  5 +++
 .../odbc/ClientListenerProcessor.java           |  3 +-
 .../utils/PlatformConfigurationUtils.java       |  4 ++-
 .../Client/ClientConnectionTest.cs              | 34 ++++++++++++++++++++
 .../Config/full-config.xml                      |  2 +-
 .../IgniteConfigurationSerializerTest.cs        |  4 ++-
 .../IgniteConfigurationTest.cs                  |  1 +
 .../ClientConnectorConfiguration.cs             | 17 ++++++++++
 .../IgniteConfigurationSection.xsd              |  5 +++
 10 files changed, 104 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/1a939b0a/modules/core/src/main/java/org/apache/ignite/configuration/ClientConnectorConfiguration.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/configuration/ClientConnectorConfiguration.java
 
b/modules/core/src/main/java/org/apache/ignite/configuration/ClientConnectorConfiguration.java
index 1c33a00..d2520d2 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/configuration/ClientConnectorConfiguration.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/configuration/ClientConnectorConfiguration.java
@@ -42,6 +42,9 @@ public class ClientConnectorConfiguration {
     /** Default size of thread pool. */
     public static final int DFLT_THREAD_POOL_SIZE = 
IgniteConfiguration.DFLT_PUBLIC_THREAD_CNT;
 
+    /** Default idle timeout. */
+    public static final int DFLT_IDLE_TIMEOUT = 0;
+
     /** Host. */
     private String host;
 
@@ -66,6 +69,9 @@ public class ClientConnectorConfiguration {
     /** Thread pool size. */
     private int threadPoolSize = DFLT_THREAD_POOL_SIZE;
 
+    /** Idle timeout. */
+    private long idleTimeout = DFLT_IDLE_TIMEOUT;
+
     /**
      * Creates SQL connector configuration with all default values.
      */
@@ -89,6 +95,7 @@ public class ClientConnectorConfiguration {
         sockSndBufSize = cfg.getSocketSendBufferSize();
         tcpNoDelay = cfg.isTcpNoDelay();
         threadPoolSize = cfg.getThreadPoolSize();
+        idleTimeout = cfg.getIdleTimeout();
     }
 
     /**
@@ -268,6 +275,32 @@ public class ClientConnectorConfiguration {
         return this;
     }
 
+    /**
+     * Gets idle timeout for client connections.
+     * If no packets come within idle timeout, the connection is closed.
+     * Zero or negative means no timeout.
+     *
+     * @return Idle timeout in milliseconds.
+     */
+    public long getIdleTimeout() {
+        return idleTimeout;
+    }
+
+    /**
+     * Sets idle timeout for client connections.
+     * If no packets come within idle timeout, the connection is closed.
+     * Zero or negative means no timeout.
+     *
+     * @param idleTimeout Idle timeout in milliseconds.
+     * @see #getIdleTimeout()
+     * @return {@code this} for chaining.
+     */
+    public ClientConnectorConfiguration setIdleTimeout(long idleTimeout) {
+        this.idleTimeout = idleTimeout;
+
+        return this;
+    }
+
     /** {@inheritDoc} */
     @Override public String toString() {
         return S.toString(ClientConnectorConfiguration.class, this);

http://git-wip-us.apache.org/repos/asf/ignite/blob/1a939b0a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java
index faecab3..b41e240 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerNioListener.java
@@ -158,6 +158,11 @@ public class ClientListenerNioListener extends 
GridNioServerListenerAdapter<byte
         }
     }
 
+    /** {@inheritDoc} */
+    @Override public void onSessionIdleTimeout(GridNioSession ses) {
+        ses.close();
+    }
+
     /**
      * Perform handshake.
      *

http://git-wip-us.apache.org/repos/asf/ignite/blob/1a939b0a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java
index 06977c8..ebd5156 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/ClientListenerProcessor.java
@@ -123,6 +123,7 @@ public class ClientListenerProcessor extends 
GridProcessorAdapter {
                         };
 
                         int maxOpenCursors = 
cliConnCfg.getMaxOpenCursorsPerConnection();
+                        long idleTimeout = cliConnCfg.getIdleTimeout();
 
                         GridNioServer<byte[]> srv0 = 
GridNioServer.<byte[]>builder()
                             .address(hostAddr)
@@ -139,7 +140,7 @@ public class ClientListenerProcessor extends 
GridProcessorAdapter {
                             
.socketReceiveBufferSize(cliConnCfg.getSocketReceiveBufferSize())
                             .filters(filters)
                             .directMode(false)
-                            .idleTimeout(Long.MAX_VALUE)
+                            .idleTimeout(idleTimeout > 0 ? idleTimeout : 
Long.MAX_VALUE)
                             .build();
 
                         srv0.start();

http://git-wip-us.apache.org/repos/asf/ignite/blob/1a939b0a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
index 6a265eb..b048f48 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
@@ -1589,7 +1589,8 @@ public class PlatformConfigurationUtils {
                 .setSocketReceiveBufferSize(in.readInt())
                 .setTcpNoDelay(in.readBoolean())
                 .setMaxOpenCursorsPerConnection(in.readInt())
-                .setThreadPoolSize(in.readInt());
+                .setThreadPoolSize(in.readInt())
+                .setIdleTimeout(in.readLong());
     }
 
     /**
@@ -1611,6 +1612,7 @@ public class PlatformConfigurationUtils {
             w.writeBoolean(cfg.isTcpNoDelay());
             w.writeInt(cfg.getMaxOpenCursorsPerConnection());
             w.writeInt(cfg.getThreadPoolSize());
+            w.writeLong(cfg.getIdleTimeout());
         } else {
             w.writeBoolean(false);
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1a939b0a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientConnectionTest.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientConnectionTest.cs
 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientConnectionTest.cs
index 2b92eb7..0bf3c37 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientConnectionTest.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientConnectionTest.cs
@@ -272,6 +272,40 @@ namespace Apache.Ignite.Core.Tests.Client
         }
 
         /// <summary>
+        /// Tests the <see cref="ClientConnectorConfiguration.IdleTimeout"/> 
property.
+        /// </summary>
+        [Test]
+        [Category(TestUtils.CategoryIntensive)]
+        public void TestIdleTimeout()
+        {
+            var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration())
+            {
+                ClientConnectorConfiguration = new ClientConnectorConfiguration
+                {
+                    IdleTimeout = TimeSpan.FromMilliseconds(100)
+                }
+            };
+
+            var ignite = Ignition.Start(cfg);
+            Assert.AreEqual(100, 
ignite.GetConfiguration().ClientConnectorConfiguration.IdleTimeout.TotalMilliseconds);
+
+            using (var client = StartClient())
+            {
+                var cache = client.GetOrCreateCache<int, int>("foo");
+                cache[1] = 1;
+                Assert.AreEqual(1, cache[1]);
+                
+                Thread.Sleep(90);
+                Assert.AreEqual(1, cache[1]);
+                
+                // Idle check frequency is 2 seconds.
+                Thread.Sleep(4000);
+                var ex = Assert.Throws<SocketException>(() => cache.Get(1));
+                Assert.AreEqual(SocketError.ConnectionAborted, 
ex.SocketErrorCode);
+            }
+        }
+
+        /// <summary>
         /// Starts the client.
         /// </summary>
         private static IIgniteClient StartClient()

http://git-wip-us.apache.org/repos/asf/ignite/blob/1a939b0a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/full-config.xml
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/full-config.xml 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/full-config.xml
index 1fc42ad..aff48f5 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/full-config.xml
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/full-config.xml
@@ -112,7 +112,7 @@
         </memoryPolicies>
     </memoryConfiguration>
     <sqlConnectorConfiguration host='bar' port='10' portRange='11' 
socketSendBufferSize='12' socketReceiveBufferSize='13' tcpNoDelay='true' 
maxOpenCursorsPerConnection='14' threadPoolSize='15' />
-    <clientConnectorConfiguration host='bar' port='10' portRange='11' 
socketSendBufferSize='12' socketReceiveBufferSize='13' tcpNoDelay='true' 
maxOpenCursorsPerConnection='14' threadPoolSize='15' />
+    <clientConnectorConfiguration host='bar' port='10' portRange='11' 
socketSendBufferSize='12' socketReceiveBufferSize='13' tcpNoDelay='true' 
maxOpenCursorsPerConnection='14' threadPoolSize='15' idleTimeout = "00:00:19" />
     <persistentStoreConfiguration alwaysWriteFullPages='true' 
checkpointingFrequency='00:00:1' checkpointingPageBufferSize='2' 
                                   checkpointingThreads='3' 
lockWaitTime='00:00:04' persistentStorePath='foo' tlbSize='5' 
                                   walArchivePath='bar' 
walFlushFrequency='00:00:06' walFsyncDelayNanos='7' walHistorySize='8' 

http://git-wip-us.apache.org/repos/asf/ignite/blob/1a939b0a/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
index 167854d..5512975 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs
@@ -250,6 +250,7 @@ namespace Apache.Ignite.Core.Tests
             Assert.IsTrue(client.TcpNoDelay);
             Assert.AreEqual(14, client.MaxOpenCursorsPerConnection);
             Assert.AreEqual(15, client.ThreadPoolSize);
+            Assert.AreEqual(19, client.IdleTimeout.TotalSeconds);
 
             var pers = cfg.PersistentStoreConfiguration;
 
@@ -895,7 +896,8 @@ namespace Apache.Ignite.Core.Tests
                     SocketReceiveBufferSize = 5,
                     SocketSendBufferSize = 6,
                     TcpNoDelay = false,
-                    ThreadPoolSize = 7
+                    ThreadPoolSize = 7,
+                    IdleTimeout = TimeSpan.FromMinutes(5)
                 },
                 PersistentStoreConfiguration = new PersistentStoreConfiguration
                 {

http://git-wip-us.apache.org/repos/asf/ignite/blob/1a939b0a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
index 4d71929..0b1b499 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
@@ -594,6 +594,7 @@ namespace Apache.Ignite.Core.Tests
             
Assert.AreEqual(ClientConnectorConfiguration.DefaultSocketBufferSize, 
cfg.SocketSendBufferSize);
             Assert.AreEqual(ClientConnectorConfiguration.DefaultTcpNoDelay, 
cfg.TcpNoDelay);
             
Assert.AreEqual(ClientConnectorConfiguration.DefaultThreadPoolSize, 
cfg.ThreadPoolSize);
+            Assert.AreEqual(ClientConnectorConfiguration.DefaultIdleTimeout, 
cfg.IdleTimeout);
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/1a939b0a/modules/platforms/dotnet/Apache.Ignite.Core/Configuration/ClientConnectorConfiguration.cs
----------------------------------------------------------------------
diff --git 
a/modules/platforms/dotnet/Apache.Ignite.Core/Configuration/ClientConnectorConfiguration.cs
 
b/modules/platforms/dotnet/Apache.Ignite.Core/Configuration/ClientConnectorConfiguration.cs
index 8c23d99..a5b2403 100644
--- 
a/modules/platforms/dotnet/Apache.Ignite.Core/Configuration/ClientConnectorConfiguration.cs
+++ 
b/modules/platforms/dotnet/Apache.Ignite.Core/Configuration/ClientConnectorConfiguration.cs
@@ -17,9 +17,11 @@
 
 namespace Apache.Ignite.Core.Configuration
 {
+    using System;
     using System.ComponentModel;
     using System.Diagnostics;
     using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Impl.Binary;
 
     /// <summary>
     /// Client connector configuration (ODBC, JDBC, Thin Client).
@@ -55,6 +57,11 @@ namespace Apache.Ignite.Core.Configuration
         /// Default SQL connector thread pool size.
         /// </summary>
         public static readonly int DefaultThreadPoolSize = 
IgniteConfiguration.DefaultThreadPoolSize;
+        
+        /// <summary>
+        /// Default idle timeout.
+        /// </summary>
+        public static TimeSpan DefaultIdleTimeout = TimeSpan.Zero;
 
         /// <summary>
         /// Initializes a new instance of the <see 
cref="ClientConnectorConfiguration"/> class.
@@ -68,6 +75,7 @@ namespace Apache.Ignite.Core.Configuration
             TcpNoDelay = DefaultTcpNoDelay;
             MaxOpenCursorsPerConnection = DefaultMaxOpenCursorsPerConnection;
             ThreadPoolSize = DefaultThreadPoolSize;
+            IdleTimeout = DefaultIdleTimeout;
         }
 
         /// <summary>
@@ -85,6 +93,7 @@ namespace Apache.Ignite.Core.Configuration
             TcpNoDelay = reader.ReadBoolean();
             MaxOpenCursorsPerConnection = reader.ReadInt();
             ThreadPoolSize = reader.ReadInt();
+            IdleTimeout = reader.ReadLongAsTimespan();
         }
 
         /// <summary>
@@ -102,6 +111,7 @@ namespace Apache.Ignite.Core.Configuration
             writer.WriteBoolean(TcpNoDelay);
             writer.WriteInt(MaxOpenCursorsPerConnection);
             writer.WriteInt(ThreadPoolSize);
+            writer.WriteTimeSpanAsLong(IdleTimeout);
         }
 
         /// <summary>
@@ -155,5 +165,12 @@ namespace Apache.Ignite.Core.Configuration
         /// Gets or sets the size of the thread pool.
         /// </summary>
         public int ThreadPoolSize { get; set; }
+        
+        /// <summary>
+        /// Gets or sets idle timeout for client connections on the server 
side.
+        /// If no packets come within idle timeout, the connection is closed 
by the server.
+        /// Zero or negative means no timeout.
+        /// </summary>
+        public TimeSpan IdleTimeout { get; set; }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1a939b0a/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
index 5d76cde..190b3ad 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
@@ -1442,6 +1442,11 @@
                                 <xs:documentation>SQL connector thread pool 
size.</xs:documentation>
                             </xs:annotation>
                         </xs:attribute>
+                        <xs:attribute name="idleTimeout" type="xs:string">
+                            <xs:annotation>
+                                <xs:documentation>Idle timeout for client 
connections on the server side. If no packets come within idle timeout, the 
connection is closed by the server. Zero or negative for no 
timeout.</xs:documentation>
+                            </xs:annotation>
+                        </xs:attribute>
                     </xs:complexType>
                 </xs:element>
                 <xs:element name="persistentStoreConfiguration" minOccurs="0">

Reply via email to