Author: jfrederic.clere(a)jboss.com
Date: 2008-09-29 04:41:56 -0400 (Mon, 29 Sep 2008)
New Revision: 1914
Added:
trunk/mod_cluster/test/java/org/jboss/mod_cluster/Domaintest.java
trunk/mod_cluster/test/java/org/jboss/mod_cluster/StartJBossWeb.java
Modified:
trunk/mod_cluster/native/include/node.h
trunk/mod_cluster/native/mod_manager/mod_manager.c
trunk/mod_cluster/native/mod_manager/node.c
trunk/mod_cluster/native/mod_proxy_cluster/mod_proxy_cluster.c
trunk/mod_cluster/test/java/build.xml
trunk/mod_cluster/test/java/org/jboss/mod_cluster/Client.java
Log:
Add logic for domain.
Modified: trunk/mod_cluster/native/include/node.h
===================================================================
--- trunk/mod_cluster/native/include/node.h 2008-09-29 06:48:51 UTC (rev 1913)
+++ trunk/mod_cluster/native/include/node.h 2008-09-29 08:41:56 UTC (rev 1914)
@@ -184,5 +184,9 @@
* Remove the node from shared memory (free the slotmem)
*/
int (*remove_node)(nodeinfo_t *node);
+/*
+ * Find the node using the JVMRoute information
+ */
+int (*find_node)(nodeinfo_t **node, const char *route);
};
#endif /*NODE_H*/
Modified: trunk/mod_cluster/native/mod_manager/mod_manager.c
===================================================================
--- trunk/mod_cluster/native/mod_manager/mod_manager.c 2008-09-29 06:48:51 UTC (rev 1913)
+++ trunk/mod_cluster/native/mod_manager/mod_manager.c 2008-09-29 08:41:56 UTC (rev 1914)
@@ -130,6 +130,10 @@
{
return (remove_node(nodestatsmem, node));
}
+static apr_status_t loc_find_node(nodeinfo_t *node, char *route)
+{
+ return (find_node(nodestatsmem, node, route));
+}
/* Check is the nodes (in shared memory) were modified since last
* call to worker_nodes_are_updated().
@@ -177,7 +181,8 @@
loc_get_max_size_node,
loc_worker_nodes_need_update,
loc_worker_nodes_are_updated,
- loc_remove_node
+ loc_remove_node,
+ loc_find_node
};
/*
Modified: trunk/mod_cluster/native/mod_manager/node.c
===================================================================
--- trunk/mod_cluster/native/mod_manager/node.c 2008-09-29 06:48:51 UTC (rev 1913)
+++ trunk/mod_cluster/native/mod_manager/node.c 2008-09-29 08:41:56 UTC (rev 1914)
@@ -195,6 +195,24 @@
return rv;
}
+/**
+ * find a node record from the shared table using JVMRoute
+ * @param pointer to the shared table.
+ * @param node address where the node is located in the shared table.
+ * @param route JVMRoute to search
+ * @return APR_SUCCESS if all went well
+ */
+apr_status_t find_node(mem_t *s, nodeinfo_t **node, const char *route)
+{
+ nodeinfo_t ou;
+ apr_status_t rv;
+
+ strcpy(ou.mess.JVMRoute, route);
+ *node = &ou;
+ rv = s->storage->ap_slotmem_do(s->slotmem, loc_read_node, node, s->p);
+ return rv;
+}
+
/*
* get the ids for the used (not free) nodes in the table
* @param pointer to the shared table.
Modified: trunk/mod_cluster/native/mod_proxy_cluster/mod_proxy_cluster.c
===================================================================
--- trunk/mod_cluster/native/mod_proxy_cluster/mod_proxy_cluster.c 2008-09-29 06:48:51 UTC
(rev 1913)
+++ trunk/mod_cluster/native/mod_proxy_cluster/mod_proxy_cluster.c 2008-09-29 08:41:56 UTC
(rev 1914)
@@ -550,6 +550,7 @@
* Check that the worker will handle the host/context.
* The id of the worker is used to find the (slot) node in the shared
* memory.
+ * (See get_context_host_balancer too).
*/
static int iscontext_host_ok(request_rec *r, proxy_balancer *balancer,
proxy_worker *worker)
@@ -588,7 +589,7 @@
/* check for /context[/] in the URL */
len = strlen(context->context);
if (strncmp(r->uri, context->context, len) == 0) {
- if (r->uri[len] == '\0' || r->uri[len-1] ==
'/') {
+ if (r->uri[len] == '\0' || r->uri[len] == '/'
|| len == 1) {
/* Check status */
switch (context->status)
{
@@ -611,6 +612,22 @@
}
/*
+ * Check that the worker corresponds to a node that belongs to the same domain according
to the JVMRoute.
+ */
+static int isnode_domain_ok(request_rec *r, proxy_worker *worker,
+ const char *domain)
+{
+ nodeinfo_t *ou;
+ node_storage->read_node(worker->id, &ou);
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+ "isnode_domain_ok: domain %s:%s", domain,
ou->mess.Domain);
+ if (domain == NULL)
+ return 1; /* OK no domain in the corresponding to the SESSIONID */
+ if (strcmp(ou->mess.Domain, domain) == 0)
+ return 1; /* OK */
+ return 0;
+}
+/*
* Check that the request has a sessionid (even invalid)
* Use the name of the balancer.
*/
@@ -653,6 +670,7 @@
}
/*
* Search the balancer that corresponds to the pair context/host
+ * (See iscontext_host_ok()).
*/
static char *get_context_host_balancer(request_rec *r)
{
@@ -707,7 +725,7 @@
/* check for /context[/] in the URL */
len = strlen(context->context);
if (strncmp(r->uri, context->context, len) == 0) {
- if (r->uri[len] == '\0' || r->uri[len] ==
'/') {
+ if (r->uri[len] == '\0' || r->uri[len] ==
'/' || len==1) {
/* Check status */
switch (context->status)
{
@@ -741,6 +759,7 @@
* Our logic is a bit different the mod_balancer one. We check the
* context and host to prevent to route to application beeing redeploy or
* stopped in one node but not in others.
+ * We also try the domain.
*/
static proxy_worker *find_best_byrequests(proxy_balancer *balancer,
request_rec *r)
@@ -749,9 +768,11 @@
int total_factor = 0;
proxy_worker *worker;
proxy_worker *mycandidate = NULL;
- int checking_standby;
- int checked_standby;
+ int checking_standby = 0;
+ int checked_standby = 0;
+ int checked_domain = 1;
void *sconf = r->server->module_config;
+ const char *domain = apr_table_get(r->notes, "session-domain");
proxy_server_conf *conf = (proxy_server_conf *)
ap_get_module_config(sconf, &proxy_module);
@@ -763,7 +784,8 @@
update_workers_node(conf, r->pool, r->server);
/* First try to see if we have available candidate */
- checking_standby = checked_standby = 0;
+ if (domain && strlen(domain)>0)
+ checked_domain = 0;
while (!mycandidate && !checked_standby) {
worker = (proxy_worker *)balancer->workers->elts;
for (i = 0; i < balancer->workers->nelts; i++, worker++) {
@@ -788,6 +810,12 @@
* and that can map the context.
*/
if (PROXY_WORKER_IS_USABLE(worker) && iscontext_host_ok(r, balancer,
worker)) {
+ if (!checked_domain) {
+ /* First try only nodes in the domain */
+ if (!isnode_domain_ok(r, worker, domain)) {
+ continue;
+ }
+ }
if (worker->s->lbfactor == 0 && checking_standby) {
mycandidate = worker;
break; /* Done */
@@ -800,7 +828,10 @@
}
}
}
- checked_standby = checking_standby++;
+ if (checked_domain) {
+ checked_standby = checking_standby++;
+ }
+ checked_domain++;
}
if (mycandidate) {
@@ -1210,7 +1241,9 @@
return DECLINED;
}
-/* Find the worker that has the 'route' defined
+/*
+ * Find the worker that has the 'route' defined
+ * (Should we also find the domain corresponding to it).
*/
static proxy_worker *find_route_worker(proxy_balancer *balancer,
const char *route, request_rec *r)
@@ -1220,6 +1253,9 @@
int checked_standby;
proxy_worker *worker;
+ nodeinfo_t *ou;
+ char *domain;
+ apr_status_t rv;
checking_standby = checked_standby = 0;
while (!checked_standby) {
@@ -1231,6 +1267,7 @@
if ( (checking_standby ? !PROXY_WORKER_IS_STANDBY(worker) :
PROXY_WORKER_IS_STANDBY(worker)) )
continue;
if (*(worker->s->route) && strcmp(worker->s->route,
route) == 0) {
+ /* that is the worker corresponding to the route */
if (worker && PROXY_WORKER_IS_USABLE(worker)) {
return worker;
} else {
@@ -1276,8 +1313,19 @@
}
checked_standby = checking_standby++;
}
+ /* We don't find a worker try to locate the domain for a fail-over */
+ rv = node_storage->find_node(&ou, route);
+ if (rv == APR_SUCCESS) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
+ "proxy: Found domain %s for %s", ou->mess.Domain,
route);
+ apr_table_setn(r->notes, "session-domain", ou->mess.Domain);
+ }
return NULL;
}
+
+/*
+ * Find the worker corresponding to the JVMRoute.
+ */
static proxy_worker *find_session_route(proxy_balancer *balancer,
request_rec *r,
char **route,
@@ -1321,7 +1369,7 @@
if (worker && strcmp(*route, worker->s->route)) {
/*
* Notice that the route of the worker chosen is different from
- * the route supplied by the client.
+ * the route supplied by the client. (mod_proxy compatibility).
*/
apr_table_setn(r->subprocess_env, "BALANCER_ROUTE_CHANGED",
"1");
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
Modified: trunk/mod_cluster/test/java/build.xml
===================================================================
--- trunk/mod_cluster/test/java/build.xml 2008-09-29 06:48:51 UTC (rev 1913)
+++ trunk/mod_cluster/test/java/build.xml 2008-09-29 08:41:56 UTC (rev 1914)
@@ -98,7 +98,43 @@
<jvmarg line="-Dcluster=${cluster} -Dtest=${test}"/>
<classpath refid="tomcat.test.classpath"/>
</java>
+ </target>
+ <!-- Test the domain logic -->
+ <target name="domain" depends="compile">
+ <copy file="conf/web.xml" todir="${test.classes}/conf"/>
+ <!-- Create 4 server with a port to stop them -->
+ <java dir="${test.classes}"
classname="org.jboss.mod_cluster.StartJBossWeb"
+ spawn="true" fork="yes"
failonerror="${test.failonerror}">
+ <arg line="8009 node1 dom1 8005"/>
+ <jvmarg line="-Dcluster=${cluster}"/>
+ <classpath refid="tomcat.test.classpath"/>
+ </java>
+ <java dir="${test.classes}"
classname="org.jboss.mod_cluster.StartJBossWeb"
+ spawn="true" fork="yes"
failonerror="${test.failonerror}">
+ <arg line="8010 node2 dom1 8006"/>
+ <jvmarg line="-Dcluster=${cluster}"/>
+ <classpath refid="tomcat.test.classpath"/>
+ </java>
+ <java dir="${test.classes}"
classname="org.jboss.mod_cluster.StartJBossWeb"
+ spawn="true" fork="yes"
failonerror="${test.failonerror}">
+ <arg line="8011 node3 dom2 8007"/>
+ <jvmarg line="-Dcluster=${cluster}"/>
+ <classpath refid="tomcat.test.classpath"/>
+ </java>
+ <java dir="${test.classes}"
classname="org.jboss.mod_cluster.StartJBossWeb"
+ spawn="true" fork="yes"
failonerror="${test.failonerror}">
+ <arg line="8012 node4 dom2 8008"/>
+ <jvmarg line="-Dcluster=${cluster}"/>
+ <classpath refid="tomcat.test.classpath"/>
+ </java>
+ <!-- Run a test : connect, get the node, stop it and check we stay on the domain
-->
+ <java dir="${test.classes}" classname="${test.runner}"
fork="yes" failonerror="${test.failonerror}">
+ <arg value="org.jboss.mod_cluster.Maintest"/>
+ <jvmarg line="-Dcluster=${cluster} -Dtest=Domaintest"/>
+ <classpath refid="tomcat.test.classpath"/>
+ </java>
+
</target>
<!-- Download and dependency building -->
Modified: trunk/mod_cluster/test/java/org/jboss/mod_cluster/Client.java
===================================================================
--- trunk/mod_cluster/test/java/org/jboss/mod_cluster/Client.java 2008-09-29 06:48:51 UTC
(rev 1913)
+++ trunk/mod_cluster/test/java/org/jboss/mod_cluster/Client.java 2008-09-29 08:41:56 UTC
(rev 1914)
@@ -219,7 +219,7 @@
if (nodes[1].compareTo(node) == 0) {
return 0;
} else {
- System.out.println("node
changed too");
+ System.out.println("node
" + nodes[1] + " changed too");
return -1;
}
} else
Added: trunk/mod_cluster/test/java/org/jboss/mod_cluster/Domaintest.java
===================================================================
--- trunk/mod_cluster/test/java/org/jboss/mod_cluster/Domaintest.java
(rev 0)
+++ trunk/mod_cluster/test/java/org/jboss/mod_cluster/Domaintest.java 2008-09-29 08:41:56
UTC (rev 1914)
@@ -0,0 +1,136 @@
+/*
+ * mod_cluster
+ *
+ * Copyright(c) 2008 Red Hat Middleware, LLC,
+ * and individual contributors as indicated by the @authors tag.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * @author Jean-Frederic Clere
+ * @version $Revision$
+ */
+
+package org.jboss.mod_cluster;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+import java.lang.Exception;
+import java.net.Socket;
+import java.io.PrintWriter;
+import java.io.InputStream;
+
+public class Domaintest extends TestCase {
+
+ public static void main( String args[] ) {
+ TestRunner.run(suite());
+ }
+ public static Test suite() {
+ TestSuite suite = new TestSuite();
+ suite.addTest(new TestSuite(Domaintest.class));
+ return suite;
+ }
+
+ public void testDomain() {
+ boolean clienterror = false;
+ String node;
+ int stopport = 0;
+ // The test expects 4 JBossWEB started on node1 to node4 and port 8005 to 8005.
+ System.out.println("Running Domain tests");
+
+ // Wait for the JBossWEB to start
+ try {
+ Thread.sleep(25000);
+ } catch (InterruptedException ex) {
+ ex.printStackTrace();
+ }
+
+ Client client = new Client();
+ try {
+ client.runit("http://localhost:7779/ROOT/MyCount", 10, false,
true);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ clienterror = true;
+ }
+
+ node = client.getnode();
+ if (node == null)
+ clienterror = true;
+
+ if (clienterror) {
+ stopAll();
+ fail("Client error");
+ }
+
+ if (node.equals("node1")) {
+ node = "node2";
+ stopport = 8005;
+ } else if (node.equals("node2")) {
+ node = "node1";
+ stopport = 8006;
+ } else if (node.equals("node3")) {
+ node = "node4";
+ stopport = 8007;
+ } else if (node.equals("node4")) {
+ node = "node3";
+ stopport = 8008;
+ }
+ client.setnode(node);
+ stopNode(stopport);
+ try {
+ client.start();
+ client.join();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ clienterror = true;
+ }
+
+ if (client.getresultok())
+ System.out.println("Test DONE");
+ else {
+ System.out.println("Test FAILED");
+ clienterror = true;
+ }
+ stopAll();
+
+ }
+
+ public void stopNode(int port) {
+ System.out.println("Stopping: " + port);
+ try {
+ Socket socket = new Socket("localhost", port);
+ PrintWriter out = new PrintWriter(socket.getOutputStream());
+ InputStream in = socket.getInputStream();
+ out.print("SHUTDOWN");
+ out.flush();
+ in.read();
+ socket.close();
+ } catch (Exception ex) {
+ ex.printStackTrace(System.out);
+ }
+ System.out.println("Stopped: " + port);
+ }
+ public void stopAll() {
+ stopNode(8005);
+ stopNode(8006);
+ stopNode(8007);
+ stopNode(8008);
+ }
+}
Added: trunk/mod_cluster/test/java/org/jboss/mod_cluster/StartJBossWeb.java
===================================================================
--- trunk/mod_cluster/test/java/org/jboss/mod_cluster/StartJBossWeb.java
(rev 0)
+++ trunk/mod_cluster/test/java/org/jboss/mod_cluster/StartJBossWeb.java 2008-09-29
08:41:56 UTC (rev 1914)
@@ -0,0 +1,98 @@
+/*
+ * mod_cluster
+ *
+ * Copyright(c) 2008 Red Hat Middleware, LLC,
+ * and individual contributors as indicated by the @authors tag.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * @author Jean-Frederic Clere
+ * @version $Revision$
+ */
+
+package org.jboss.mod_cluster;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
+import org.apache.catalina.startup.Embedded;
+import org.apache.catalina.Engine;
+import org.apache.catalina.Host;
+import org.apache.catalina.Context;
+import org.apache.catalina.*;
+import org.apache.catalina.connector.Connector;
+import org.apache.catalina.core.*;
+import org.apache.catalina.startup.HostConfig;
+
+import org.apache.catalina.LifecycleListener;
+
+public class StartJBossWeb {
+
+ /* Start a JBossWEB with domain */
+ public static void main(String[] args) {
+
+ StandardServer server = null;
+ JBossWeb service = null;
+ int port = 8009;
+ int serverport = 8005;
+ String node = "node1";
+ String domain = "dom1";
+ if (args.length == 4) {
+ port = Integer.parseInt(args[0]);
+ node = args[1];
+ domain = args[2];
+ serverport = Integer.parseInt(args[3]);
+ }
+ System.out.println("Starting JBossWEB on " + port + " " +
node + " " + domain + " " + serverport);
+
+ try {
+ server = (StandardServer) ServerFactory.getServer();
+ server.setPort(serverport);
+
+ service = new JBossWeb(node, "localhost");
+ service.addConnector(port);
+ server.addService(service);
+
+ LifecycleListener cluster =
Maintest.createClusterListener("232.0.0.2", 23364, false, domain);
+ server.addLifecycleListener(cluster);
+
+ server.start();
+
+ } catch(IOException ex) {
+ ex.printStackTrace();
+ } catch (LifecycleException ex) {
+ ex.printStackTrace();
+ }
+
+ // Wait until we are stopped...
+ server.await();
+
+ // Stop the server or services.
+ try {
+ server.stop();
+ // service.stop();
+ // service2.stop();
+ } catch (LifecycleException ex) {
+ ex.printStackTrace();
+ }
+
+ }
+}