Hi

I am using H2 in a clustered configuration where we need some 
control/detection of which servers are currently in the cluster. I have 
added functionality to the jdbc connection to get the number of servers 
currently in the cluster and which servers that are available. Have a look 
at my patch and tell me what you think.

Best regards
  Nikolaj Fogh

-- 
You received this message because you are subscribed to the Google Groups "H2 
Database" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/h2-database.
For more options, visit https://groups.google.com/d/optout.
Index: src/docsrc/html/advanced.html
===================================================================
--- src/docsrc/html/advanced.html	(revision 5747)
+++ src/docsrc/html/advanced.html	(working copy)
@@ -390,6 +390,15 @@
 servers is returned, enclosed in single quote. Example: <code>'server1:9191,server2:9191'</code>.
 </p>
 
+<p>It is also possible to get the list of servers by using Connection.getClientInfo().</p>
+
+<p>The property list returned from <code>getClientInfo()</code> contains a <code>numServers</code> property that returns the 
+number of servers that are in the connection list. To get the actual servers, <code>getClientInfo()</code> also has
+properties <code>server0</code>..<code>serverX</code>, where serverX is the number of servers minus 1.
+
+<p>Example: To get the 2nd server in the connection list one uses <code>getClientInfo('server1')<code>. <b>Note:</b> The 
+<code>serverX</code> property only returns IP addresses and ports and not hostnames.</p>
+
 <h3>Clustering Algorithm and Limitations</h3>
 <p>
 Read-only queries are only executed against the first cluster node, but all other statements are
Index: src/main/org/h2/engine/Session.java
===================================================================
--- src/main/org/h2/engine/Session.java	(revision 5747)
+++ src/main/org/h2/engine/Session.java	(working copy)
@@ -127,6 +127,10 @@
         this.currentSchemaName = Constants.SCHEMA_MAIN;
     }
 
+    public ArrayList<String> getServers() {
+        return new ArrayList<String>();
+    }
+    
     public boolean setCommitOrRollbackDisabled(boolean x) {
         boolean old = commitOrRollbackDisabled;
         commitOrRollbackDisabled = x;
Index: src/main/org/h2/engine/SessionInterface.java
===================================================================
--- src/main/org/h2/engine/SessionInterface.java	(revision 5747)
+++ src/main/org/h2/engine/SessionInterface.java	(working copy)
@@ -6,6 +6,8 @@
 package org.h2.engine;
 
 import java.io.Closeable;
+import java.util.ArrayList;
+
 import org.h2.command.CommandInterface;
 import org.h2.message.Trace;
 import org.h2.store.DataHandler;
@@ -17,6 +19,13 @@
 public interface SessionInterface extends Closeable {
 
     /**
+     * Get the list of servers for this session.
+     *
+     * @return A list of "IP:PORT" strings for the servers in this session.
+     */
+    ArrayList<String> getServers();
+    
+    /**
      * Parse a command and prepare it for execution.
      *
      * @param sql the SQL statement
Index: src/main/org/h2/engine/SessionRemote.java
===================================================================
--- src/main/org/h2/engine/SessionRemote.java	(revision 5747)
+++ src/main/org/h2/engine/SessionRemote.java	(working copy)
@@ -8,6 +8,7 @@
 import java.io.IOException;
 import java.net.Socket;
 import java.util.ArrayList;
+import java.util.List;
 
 import org.h2.api.DatabaseEventListener;
 import org.h2.api.ErrorCode;
@@ -95,6 +96,17 @@
         this.connectionInfo = ci;
     }
 
+    public ArrayList<String> getServers() {
+    	ArrayList<String> serverList = new ArrayList<String>();
+    	
+        for (int i = 0; i < transferList.size(); i++) {
+            Transfer transfer = transferList.get(i);
+            serverList.add(transfer.getSocket().getInetAddress().getHostAddress().toString() + ":" + String.valueOf(transfer.getSocket().getPort()));
+        }
+        
+        return serverList;
+    }
+    
     private Transfer initTransfer(ConnectionInfo ci, String db, String server)
             throws IOException {
         Socket socket = NetUtils.createSocket(server,
Index: src/main/org/h2/jdbc/JdbcConnection.java
===================================================================
--- src/main/org/h2/jdbc/JdbcConnection.java	(revision 5747)
+++ src/main/org/h2/jdbc/JdbcConnection.java	(working copy)
@@ -25,6 +25,7 @@
 import java.sql.Savepoint;
 import java.sql.Statement;
 import java.sql.Struct;
+import java.util.ArrayList;
 import java.util.Map;
 import java.util.Properties;
 
@@ -47,7 +48,7 @@
 import org.h2.value.ValueNull;
 import org.h2.value.ValueString;
 
-/*## Java 1.7 ##
+//## Java 1.7 ##
 import java.util.concurrent.Executor;
 //*/
 
@@ -1715,35 +1716,37 @@
 
     /**
      * Get the client properties.
-     * This method always returns null.
      *
-     * @return always null
+     * @return the property list
      */
     @Override
     public Properties getClientInfo() throws SQLException {
         try {
-            debugCode("getClientInfo();");
-            // we don't have any client properties, so return null
-            return null;
+        	ArrayList<String> serverList = session.getServers();
+        	Properties p = new Properties();
+        	
+        	p.setProperty("numServers", String.valueOf(serverList.size()));
+        	for (int i = 0; i < serverList.size(); i++)
+        		p.setProperty("server" + String.valueOf(i), serverList.get(i));
+            return p;
         } catch (Exception e) {
             throw logAndConvert(e);
         }
     }
 
     /**
-     * Set a client property.
-     * This method always throws a SQLClientInfoException.
+     * Get a client property.
      *
      * @param name the client info name (ignored)
-     * @return this method never returns normally
+     * @return the property value
      */
     @Override
     public String getClientInfo(String name) throws SQLException {
         try {
+        	Properties p = getClientInfo();
             debugCodeCall("getClientInfo", name);
             checkClosed();
-            // we don't have any client properties, so just throw
-            throw new SQLClientInfoException();
+            return p.getProperty(name);
         } catch (Exception e) {
             throw logAndConvert(e);
         }
@@ -1814,7 +1817,7 @@
      *
      * @param schema the schema
      */
-/*## Java 1.7 ##
+//## Java 1.7 ##
     @Override
     public void setSchema(String schema) {
         // not supported
@@ -1824,7 +1827,7 @@
     /**
      * [Not supported]
      */
-/*## Java 1.7 ##
+//## Java 1.7 ##
     @Override
     public String getSchema() {
         return null;
@@ -1836,7 +1839,7 @@
      *
      * @param executor the executor used by this method
      */
-/*## Java 1.7 ##
+//## Java 1.7 ##
     @Override
     public void abort(Executor executor) {
         // not supported
@@ -1849,7 +1852,7 @@
      * @param executor the executor used by this method
      * @param milliseconds the TCP connection timeout
      */
-/*## Java 1.7 ##
+//## Java 1.7 ##
     @Override
     public void setNetworkTimeout(Executor executor, int milliseconds) {
         // not supported
@@ -1859,7 +1862,7 @@
     /**
      * [Not supported]
      */
-/*## Java 1.7 ##
+//## Java 1.7 ##
     @Override
     public int getNetworkTimeout() {
         return 0;
Index: src/test/org/h2/test/db/TestCluster.java
===================================================================
--- src/test/org/h2/test/db/TestCluster.java	(revision 5747)
+++ src/test/org/h2/test/db/TestCluster.java	(working copy)
@@ -10,6 +10,7 @@
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.util.Properties;
 
 import org.h2.api.ErrorCode;
 import org.h2.store.fs.FileUtils;
@@ -39,6 +40,7 @@
         testRecover();
         testRollback();
         testCase();
+        testClientInfo();
         testCreateClusterAtRuntime();
         testStartStopCluster();
     }
@@ -250,6 +252,60 @@
         n1.stop();
         deleteFiles();
     }
+    
+    private void testClientInfo() throws SQLException {
+        if (config.memory || config.networked || config.cipher != null) {
+            return;
+        }
+        int port1 = 9191, port2 = 9192;
+        String serverList = "localhost:" + port1 + ",localhost:" + port2;
+        deleteFiles();
+
+        org.h2.Driver.load();
+        String user = getUser(), password = getPassword();
+        Connection conn;
+
+        String url1 = getURL("jdbc:h2:tcp://localhost:" + port1 + "/test", true);
+        String url2 = getURL("jdbc:h2:tcp://localhost:" + port2 + "/test", true);
+        String urlCluster = getURL("jdbc:h2:tcp://" + serverList + "/test", true);
+
+        Server n1 = org.h2.tools.Server.createTcpServer("-tcpPort",
+                "" + port1, "-baseDir", getBaseDir() + "/node1").start();
+        Server n2 = org.h2.tools.Server.createTcpServer("-tcpPort",
+                "" + port2 , "-baseDir", getBaseDir() + "/node2").start();
+
+        CreateCluster.main("-urlSource", url1, "-urlTarget", url2,
+                "-user", user, "-password", password, "-serverList",
+                serverList);
+
+        conn = getConnection(urlCluster, user, password);
+        Properties p = conn.getClientInfo();
+		
+		assertEquals("2", p.getProperty("numServers"));
+        assertEquals("127.0.0.1:" + port1, p.getProperty("server0"));
+        assertEquals("127.0.0.1:" + port2, p.getProperty("server1"));
+
+		assertEquals("2", conn.getClientInfo("numServers"));
+        assertEquals("127.0.0.1:" + port1, conn.getClientInfo("server0"));
+        assertEquals("127.0.0.1:" + port2, conn.getClientInfo("server1"));
+        conn.close();
+
+        // stop server 2, and test if only one server is available
+        n2.stop();
+
+        conn = getConnection(urlCluster, user, password);
+        p = conn.getClientInfo();
+        
+        assertEquals("1", p.getProperty("numServers"));
+        assertEquals("127.0.0.1:" + port1, p.getProperty("server0"));
+        assertEquals("1", conn.getClientInfo("numServers"));
+        assertEquals("127.0.0.1:" + port1, conn.getClientInfo("server0"));
+        conn.close();
+
+        n1.stop();
+        deleteFiles();
+    }
+    
     private void testCreateClusterAtRuntime() throws SQLException {
         if (config.memory || config.networked || config.cipher != null) {
             return;

Reply via email to