提交 4b204d0b authored 作者: noelgrandin@gmail.com's avatar noelgrandin@gmail.com

Add client-info property to get the number of servers currently in the cluster

and which servers that are available. (patch from  Nikolaj Fogh) 
上级 b33f7212
......@@ -390,6 +390,15 @@ If the result is <code>''</code> (two single quotes), then the cluster mode is d
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
......
......@@ -19,6 +19,8 @@ Change Log
<h2>Next Version (unreleased)</h2>
<ul><li>The LIRS cache now re-sizes the internal hash map if needed.
<ul><li>Optionally persist session history in the H2 console. (patch from Martin Grajcar)
<ul><li>Add client-info property to get the number of servers currently in the cluster
and which servers that are available. (patch from Nikolaj Fogh)
</li></ul>
<h2>Version 1.4.179 Beta (2014-06-23)</h2>
......
......@@ -127,6 +127,10 @@ public class Session extends SessionWithState {
this.currentSchemaName = Constants.SCHEMA_MAIN;
}
public ArrayList<String> getClusterServers() {
return new ArrayList<String>();
}
public boolean setCommitOrRollbackDisabled(boolean x) {
boolean old = commitOrRollbackDisabled;
commitOrRollbackDisabled = x;
......
......@@ -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;
......@@ -16,6 +18,13 @@ import org.h2.value.Value;
*/
public interface SessionInterface extends Closeable {
/**
* Get the list of the cluster servers for this session.
*
* @return A list of "IP:PORT" strings for the cluster servers in this session.
*/
ArrayList<String> getClusterServers();
/**
* Parse a command and prepare it for execution.
*
......
......@@ -95,6 +95,15 @@ public class SessionRemote extends SessionWithState implements DataHandler {
this.connectionInfo = ci;
}
public ArrayList<String> getClusterServers() {
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,
......
......@@ -25,6 +25,7 @@ import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.ArrayList;
import java.util.Map;
import java.util.Properties;
......@@ -1715,35 +1716,44 @@ public class JdbcConnection extends TraceObject implements Connection {
/**
* 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;
if (isDebugEnabled()) {
debugCode("getClientInfo();");
}
checkClosed();
ArrayList<String> serverList = session.getClusterServers();
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 {
debugCodeCall("getClientInfo", name);
if (isDebugEnabled()) {
debugCodeCall("getClientInfo", name);
}
checkClosed();
// we don't have any client properties, so just throw
throw new SQLClientInfoException();
Properties p = getClientInfo();
return p.getProperty(name);
} catch (Exception e) {
throw logAndConvert(e);
}
......
......@@ -10,6 +10,7 @@ import java.sql.PreparedStatement;
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 @@ public class TestCluster extends TestBase {
testRecover();
testRollback();
testCase();
testClientInfo();
testCreateClusterAtRuntime();
testStartStopCluster();
}
......@@ -250,6 +252,60 @@ public class TestCluster extends TestBase {
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;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论