Author: jfrederic.clere(a)jboss.com
Date: 2008-05-15 02:39:02 -0400 (Thu, 15 May 2008)
New Revision: 1604
Added:
trunk/mod_cluster/native/mod_manager/.deps
trunk/mod_cluster/native/mod_manager/Makefile.in
trunk/mod_cluster/native/mod_manager/balancer.c
trunk/mod_cluster/native/mod_manager/buildconf
trunk/mod_cluster/native/mod_manager/configure.in
trunk/mod_cluster/native/mod_manager/context.c
trunk/mod_cluster/native/mod_manager/host.c
trunk/mod_cluster/native/mod_manager/mod_manager.c
trunk/mod_cluster/native/mod_manager/node.c
Log:
Add shared table handlers and protocol processor.
Added: trunk/mod_cluster/native/mod_manager/.deps
===================================================================
Added: trunk/mod_cluster/native/mod_manager/Makefile.in
===================================================================
--- trunk/mod_cluster/native/mod_manager/Makefile.in (rev 0)
+++ trunk/mod_cluster/native/mod_manager/Makefile.in 2008-05-15 06:39:02 UTC (rev 1604)
@@ -0,0 +1,23 @@
+# Makefile.in for mod_proxy_cluster
+# copy the source in the httpd Apache source tree
+APACHE_BASE = @APACHE_BASE@
+top_builddir = @APACHE_BASE@
+# For .deps.
+builddir = @CLUSTER_BASE@
+# For the apache includes
+top_srcdir = @APACHE_BASE@
+
+include $(APACHE_BASE)/build/rules.mk
+SH_COMPILE = $(LIBTOOL) --mode=compile $(BASE_CC) -I../include -prefer-pic -c $<
&& touch $@
+
+all: mod_manager.so
+
+mod_manager.so: mod_manager.la
+ $(APACHE_BASE)/build/instdso.sh SH_LIBTOOL='$(LIBTOOL)' mod_manager.la `pwd`
+
+mod_manager.la: mod_manager.slo node.slo context.slo host.slo balancer.slo
+ $(SH_LINK) -rpath $(libexecdir) -module -avoid-version mod_manager.lo node.lo
context.lo host.lo balancer.lo
+
+clean:
+ rm -f *.o *.lo *.slo
+ rm -rf .libs
Added: trunk/mod_cluster/native/mod_manager/balancer.c
===================================================================
--- trunk/mod_cluster/native/mod_manager/balancer.c (rev 0)
+++ trunk/mod_cluster/native/mod_manager/balancer.c 2008-05-15 06:39:02 UTC (rev 1604)
@@ -0,0 +1,227 @@
+/*
+ * 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$
+ */
+
+/**
+ * @file balancer.c
+ * @brief balancer description Storage Module for Apache
+ *
+ * @defgroup MEM balancers
+ * @ingroup APACHE_MODS
+ * @{
+ */
+
+#include "apr.h"
+#include "apr_strings.h"
+#include "apr_pools.h"
+#include "apr_time.h"
+
+#include "slotmem.h"
+#include "balancer.h"
+
+struct mem {
+ ap_slotmem_t *slotmem;
+ const slotmem_storage_method *storage;
+ int num;
+ apr_pool_t *p;
+};
+
+static mem_t * create_attach_mem_balancer(char *string, int *num, int type, apr_pool_t
*p, slotmem_storage_method *storage) {
+ mem_t *ptr;
+ const char *storename;
+ apr_status_t rv;
+
+ ptr = apr_pcalloc(p, sizeof(mem_t));
+ if (!ptr) {
+ return NULL;
+ }
+ ptr->storage = storage;
+ storename = apr_pstrcat(p, string, BALANCEREXE, NULL);
+ if (type)
+ rv = ptr->storage->ap_slotmem_create(&ptr->slotmem, storename,
sizeof(balancerinfo_t), *num, p);
+ else {
+ apr_size_t size = sizeof(balancerinfo_t);
+ rv = ptr->storage->ap_slotmem_attach(&ptr->slotmem, storename,
&size, num, p);
+ }
+ if (rv != APR_SUCCESS) {
+ return NULL;
+ }
+ ptr->num = *num;
+ ptr->p = p;
+ return ptr;
+}
+/**
+ * Insert(alloc) and update a balancer record in the shared table
+ * @param pointer to the shared table.
+ * @param balancer balancer to store in the shared table.
+ * @return APR_SUCCESS if all went well
+ *
+ */
+static apr_status_t insert_update(void* mem, void **data, int id, apr_pool_t *pool)
+{
+ balancerinfo_t *in = (balancerinfo_t *)*data;
+ balancerinfo_t *ou = (balancerinfo_t *)mem;
+ if (strcmp(in->balancer, ou->balancer) == 0) {
+ memcpy(ou, in, sizeof(balancerinfo_t));
+ ou->id = id;
+ ou->updatetime = apr_time_sec(apr_time_now());
+ *data = ou;
+ return APR_SUCCESS;
+ }
+ return APR_NOTFOUND;
+}
+apr_status_t insert_update_balancer(mem_t *s, balancerinfo_t *balancer)
+{
+ apr_status_t rv;
+ balancerinfo_t *ou;
+ int ident;
+
+ balancer->id = 0;
+ rv = s->storage->ap_slotmem_do(s->slotmem, insert_update, &balancer,
s->p);
+ if (balancer->id != 0 && rv == APR_SUCCESS) {
+ return APR_SUCCESS; /* updated */
+ }
+
+ /* we have to insert it */
+ rv = s->storage->ap_slotmem_alloc(s->slotmem, &ident, (void **)
&ou);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ memcpy(ou, balancer, sizeof(balancerinfo_t));
+ ou->id = ident;
+ ou->updatetime = apr_time_sec(apr_time_now());
+
+ return APR_SUCCESS;
+}
+
+/**
+ * read a balancer record from the shared table
+ * @param pointer to the shared table.
+ * @param balancer balancer to read from the shared table.
+ * @return address of the read balancer or NULL if error.
+ */
+static apr_status_t loc_read_balancer(void* mem, void **data, int id, apr_pool_t *pool)
{
+ balancerinfo_t *in = (balancerinfo_t *)*data;
+ balancerinfo_t *ou = (balancerinfo_t *)mem;
+
+ if (strcmp(in->balancer, ou->balancer) == 0) {
+ *data = ou;
+ return APR_SUCCESS;
+ }
+ return APR_NOTFOUND;
+}
+APR_DECLARE(balancerinfo_t *) read_balancer(mem_t *s, balancerinfo_t *balancer)
+{
+ apr_status_t rv;
+ balancerinfo_t *ou = balancer;
+
+ if (balancer->id)
+ rv = s->storage->ap_slotmem_mem(s->slotmem, balancer->id, (void **)
&ou);
+ else {
+ rv = s->storage->ap_slotmem_do(s->slotmem, loc_read_balancer, &ou,
s->p);
+ }
+ if (rv == APR_SUCCESS)
+ return ou;
+ return NULL;
+}
+/**
+ * get a balancer record from the shared table
+ * @param pointer to the shared table.
+ * @param balancer address where the balancer is locate in the shared table.
+ * @param ids in the balancer table.
+ * @return APR_SUCCESS if all went well
+ */
+APR_DECLARE(apr_status_t) get_balancer(mem_t *s, balancerinfo_t **balancer, int ids)
+{
+ return(s->storage->ap_slotmem_mem(s->slotmem, ids, (void **) balancer));
+}
+
+/**
+ * remove(free) a balancer record from the shared table
+ * @param pointer to the shared table.
+ * @param balancer balancer to remove from the shared table.
+ * @return APR_SUCCESS if all went well
+ */
+APR_DECLARE(apr_status_t) remove_balancer(mem_t *s, balancerinfo_t *balancer)
+{
+ apr_status_t rv;
+ balancerinfo_t *ou = balancer;
+ if (balancer->id)
+ s->storage->ap_slotmem_free(s->slotmem, balancer->id, balancer);
+ else {
+ /* XXX: for the moment January 2007 ap_slotmem_free only uses ident to remove */
+ rv = s->storage->ap_slotmem_do(s->slotmem, loc_read_balancer, &ou,
s->p);
+ if (rv == APR_SUCCESS)
+ rv = s->storage->ap_slotmem_free(s->slotmem, ou->id, balancer);
+ }
+ return rv;
+}
+
+/*
+ * get the ids for the used (not free) balancers in the table
+ * @param pointer to the shared table.
+ * @param ids array of int to store the used id (must be big enough).
+ * @return number of balancer existing or -1 if error.
+ */
+APR_DECLARE(int) get_ids_used_balancer(mem_t *s, int *ids)
+{
+ return (s->storage->ap_slotmem_get_used(s->slotmem, ids));
+}
+
+/*
+ * read the size of the table.
+ * @param pointer to the shared table.
+ * @return number of balancer existing or -1 if error.
+ */
+APR_DECLARE(int) get_max_size_balancer(mem_t *s)
+{
+ return (s->storage->ap_slotmem_get_max_size(s->slotmem));
+}
+
+/**
+ * attach to the shared balancer table
+ * @param name of an existing shared table.
+ * @param address to store the size of the shared table.
+ * @param p pool to use for allocations.
+ * @param storage slotmem logic provider.
+ * @return address of struct used to access the table.
+ */
+mem_t * get_mem_balancer(char *string, int *num, apr_pool_t *p, slotmem_storage_method
*storage)
+{
+ return(create_attach_mem_balancer(string, num, 0, p, storage));
+}
+/**
+ * create a shared balancer table
+ * @param name to use to create the table.
+ * @param size of the shared table.
+ * @param p pool to use for allocations.
+ * @param storage slotmem logic provider.
+ * @return address of struct used to access the table.
+ */
+mem_t * create_mem_balancer(char *string, int *num, apr_pool_t *p, slotmem_storage_method
*storage)
+{
+ return(create_attach_mem_balancer(string, num, 1, p, storage));
+}
Added: trunk/mod_cluster/native/mod_manager/buildconf
===================================================================
--- trunk/mod_cluster/native/mod_manager/buildconf (rev 0)
+++ trunk/mod_cluster/native/mod_manager/buildconf 2008-05-15 06:39:02 UTC (rev 1604)
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+rm -rf aclocal.m4 autom4te*.cache
+
+echo "Creating configure ..."
+### do some work to toss config.cache?
+if ${AUTOCONF:-autoconf}; then
+ :
+else
+ echo "autoconf failed"
+ exit 1
+fi
Property changes on: trunk/mod_cluster/native/mod_manager/buildconf
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/mod_cluster/native/mod_manager/configure.in
===================================================================
--- trunk/mod_cluster/native/mod_manager/configure.in (rev 0)
+++ trunk/mod_cluster/native/mod_manager/configure.in 2008-05-15 06:39:02 UTC (rev 1604)
@@ -0,0 +1,24 @@
+dnl configure for mod_manager
+dnl
+
+AC_INIT(mod_manager.c)
+
+AC_MSG_CHECKING(for Apache httpd installation)
+AC_ARG_WITH(apache,
+[ --with-apache[=DIR] DIR is the apache base installation
+],
+[ if test "$withval" = "yes"; then
+ withval=/usr/local/etc/httpd
+ fi
+ if test "$withval" != "no"; then
+ APACHE_BASE=$withval
+ else
+ AC_MSG_ERROR(mod_manager need a valid apache location)
+ fi
+],
+[ AC_MSG_ERROR(Please use --with-apache[=DIR])])
+CLUSTER_BASE=`pwd`
+
+AC_SUBST(APACHE_BASE)
+AC_SUBST(CLUSTER_BASE)
+AC_OUTPUT(Makefile)
Added: trunk/mod_cluster/native/mod_manager/context.c
===================================================================
--- trunk/mod_cluster/native/mod_manager/context.c (rev 0)
+++ trunk/mod_cluster/native/mod_manager/context.c 2008-05-15 06:39:02 UTC (rev 1604)
@@ -0,0 +1,228 @@
+/*
+ * 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$
+ */
+
+/**
+ * @file context.c
+ * @brief context description Storage Module for Apache
+ *
+ * @defgroup MEM contexts
+ * @ingroup APACHE_MODS
+ * @{
+ */
+
+#include "apr.h"
+#include "apr_strings.h"
+#include "apr_pools.h"
+#include "apr_time.h"
+
+#include "slotmem.h"
+#include "context.h"
+
+struct mem {
+ ap_slotmem_t *slotmem;
+ const slotmem_storage_method *storage;
+ int num;
+ apr_pool_t *p;
+};
+
+static mem_t * create_attach_mem_context(char *string, int *num, int type, apr_pool_t *p,
slotmem_storage_method *storage) {
+ mem_t *ptr;
+ const char *storename;
+ apr_status_t rv;
+
+ ptr = apr_pcalloc(p, sizeof(mem_t));
+ if (!ptr) {
+ return NULL;
+ }
+ ptr->storage = storage;
+ storename = apr_pstrcat(p, string, CONTEXTEXE, NULL);
+ if (type)
+ rv = ptr->storage->ap_slotmem_create(&ptr->slotmem, storename,
sizeof(contextinfo_t), *num, p);
+ else {
+ apr_size_t size = sizeof(contextinfo_t);
+ rv = ptr->storage->ap_slotmem_attach(&ptr->slotmem, storename,
&size, num, p);
+ }
+ if (rv != APR_SUCCESS) {
+ return NULL;
+ }
+ ptr->num = *num;
+ ptr->p = p;
+ return ptr;
+}
+/**
+ * Insert(alloc) and update a context record in the shared table
+ * @param pointer to the shared table.
+ * @param context context to store in the shared table.
+ * @return APR_SUCCESS if all went well
+ *
+ */
+static apr_status_t insert_update(void* mem, void **data, int id, apr_pool_t *pool)
+{
+ contextinfo_t *in = (contextinfo_t *)*data;
+ contextinfo_t *ou = (contextinfo_t *)mem;
+ if (strcmp(in->context, ou->context) == 0 &&
+ in->vhost == ou->vhost && in->node == ou->node) {
+ memcpy(ou, in, sizeof(contextinfo_t));
+ ou->id = id;
+ ou->updatetime = apr_time_sec(apr_time_now());
+ *data = ou;
+ return APR_SUCCESS;
+ }
+ return APR_NOTFOUND;
+}
+apr_status_t insert_update_context(mem_t *s, contextinfo_t *context)
+{
+ apr_status_t rv;
+ contextinfo_t *ou;
+ int ident;
+
+ context->id = 0;
+ rv = s->storage->ap_slotmem_do(s->slotmem, insert_update, &context,
s->p);
+ if (context->id != 0 && rv == APR_SUCCESS) {
+ return APR_SUCCESS; /* updated */
+ }
+
+ /* we have to insert it */
+ rv = s->storage->ap_slotmem_alloc(s->slotmem, &ident, (void **)
&ou);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ memcpy(ou, context, sizeof(contextinfo_t));
+ ou->id = ident;
+ ou->updatetime = apr_time_sec(apr_time_now());
+
+ return APR_SUCCESS;
+}
+
+/**
+ * read a context record from the shared table
+ * @param pointer to the shared table.
+ * @param context context to read from the shared table.
+ * @return address of the read context or NULL if error.
+ */
+static apr_status_t loc_read_context(void* mem, void **data, int id, apr_pool_t *pool) {
+ contextinfo_t *in = (contextinfo_t *)*data;
+ contextinfo_t *ou = (contextinfo_t *)mem;
+ if (strcmp(in->context, ou->context) == 0 &&
+ in->vhost == ou->vhost && ou->node == in->node) {
+ *data = ou;
+ return APR_SUCCESS;
+ }
+ return APR_NOTFOUND;
+}
+APR_DECLARE(contextinfo_t *) read_context(mem_t *s, contextinfo_t *context)
+{
+ apr_status_t rv;
+ contextinfo_t *ou = context;
+
+ if (context->id)
+ rv = s->storage->ap_slotmem_mem(s->slotmem, context->id, (void **)
&ou);
+ else {
+ rv = s->storage->ap_slotmem_do(s->slotmem, loc_read_context, &ou,
s->p);
+ }
+ if (rv == APR_SUCCESS)
+ return ou;
+ return NULL;
+}
+/**
+ * get a context record from the shared table
+ * @param pointer to the shared table.
+ * @param context address where the context is locate in the shared table.
+ * @param ids in the context table.
+ * @return APR_SUCCESS if all went well
+ */
+APR_DECLARE(apr_status_t) get_context(mem_t *s, contextinfo_t **context, int ids)
+{
+ return(s->storage->ap_slotmem_mem(s->slotmem, ids, (void **) context));
+}
+
+/**
+ * remove(free) a context record from the shared table
+ * @param pointer to the shared table.
+ * @param context context to remove from the shared table.
+ * @return APR_SUCCESS if all went well
+ */
+APR_DECLARE(apr_status_t) remove_context(mem_t *s, contextinfo_t *context)
+{
+ apr_status_t rv;
+ contextinfo_t *ou = context;
+ if (context->id)
+ s->storage->ap_slotmem_free(s->slotmem, context->id, context);
+ else {
+ /* XXX: for the moment January 2007 ap_slotmem_free only uses ident to remove */
+ rv = s->storage->ap_slotmem_do(s->slotmem, loc_read_context, &ou,
s->p);
+ if (rv == APR_SUCCESS)
+ rv = s->storage->ap_slotmem_free(s->slotmem, ou->id, context);
+ }
+ return rv;
+}
+
+/*
+ * get the ids for the used (not free) contexts in the table
+ * @param pointer to the shared table.
+ * @param ids array of int to store the used id (must be big enough).
+ * @return number of context existing or -1 if error.
+ */
+APR_DECLARE(int) get_ids_used_context(mem_t *s, int *ids)
+{
+ return (s->storage->ap_slotmem_get_used(s->slotmem, ids));
+}
+
+/*
+ * read the size of the table.
+ * @param pointer to the shared table.
+ * @return number of context existing or -1 if error.
+ */
+APR_DECLARE(int) get_max_size_context(mem_t *s)
+{
+ return (s->storage->ap_slotmem_get_max_size(s->slotmem));
+}
+
+/**
+ * attach to the shared context table
+ * @param name of an existing shared table.
+ * @param address to store the size of the shared table.
+ * @param p pool to use for allocations.
+ * @param storage slotmem logic provider.
+ * @return address of struct used to access the table.
+ */
+mem_t * get_mem_context(char *string, int *num, apr_pool_t *p, slotmem_storage_method
*storage)
+{
+ return(create_attach_mem_context(string, num, 0, p, storage));
+}
+/**
+ * create a shared context table
+ * @param name to use to create the table.
+ * @param size of the shared table.
+ * @param p pool to use for allocations.
+ * @param storage slotmem logic provider.
+ * @return address of struct used to access the table.
+ */
+mem_t * create_mem_context(char *string, int *num, apr_pool_t *p, slotmem_storage_method
*storage)
+{
+ return(create_attach_mem_context(string, num, 1, p, storage));
+}
Added: trunk/mod_cluster/native/mod_manager/host.c
===================================================================
--- trunk/mod_cluster/native/mod_manager/host.c (rev 0)
+++ trunk/mod_cluster/native/mod_manager/host.c 2008-05-15 06:39:02 UTC (rev 1604)
@@ -0,0 +1,225 @@
+/*
+ * 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$
+ */
+
+/**
+ * @file host.c
+ * @brief host description Storage Module for Apache
+ *
+ * @defgroup MEM hosts
+ * @ingroup APACHE_MODS
+ * @{
+ */
+
+#include "apr.h"
+#include "apr_strings.h"
+#include "apr_pools.h"
+#include "apr_time.h"
+
+#include "slotmem.h"
+#include "host.h"
+
+struct mem {
+ ap_slotmem_t *slotmem;
+ const slotmem_storage_method *storage;
+ int num;
+ apr_pool_t *p;
+};
+
+static mem_t * create_attach_mem_host(char *string, int *num, int type, apr_pool_t *p,
slotmem_storage_method *storage) {
+ mem_t *ptr;
+ const char *storename;
+ apr_status_t rv;
+
+ ptr = apr_pcalloc(p, sizeof(mem_t));
+ if (!ptr) {
+ return NULL;
+ }
+ ptr->storage = storage;
+ storename = apr_pstrcat(p, string, HOSTEXE, NULL);
+ if (type)
+ rv = ptr->storage->ap_slotmem_create(&ptr->slotmem, storename,
sizeof(hostinfo_t), *num, p);
+ else {
+ apr_size_t size = sizeof(hostinfo_t);
+ rv = ptr->storage->ap_slotmem_attach(&ptr->slotmem, storename,
&size, num, p);
+ }
+ if (rv != APR_SUCCESS) {
+ return NULL;
+ }
+ ptr->num = *num;
+ ptr->p = p;
+ return ptr;
+}
+/**
+ * Insert(alloc) and update a host record in the shared table
+ * @param pointer to the shared table.
+ * @param host host to store in the shared table.
+ * @return APR_SUCCESS if all went well
+ *
+ */
+static apr_status_t insert_update(void* mem, void **data, int id, apr_pool_t *pool)
+{
+ hostinfo_t *in = (hostinfo_t *)*data;
+ hostinfo_t *ou = (hostinfo_t *)mem;
+ if (strcmp(in->host, ou->host) == 0 && in->vhost == ou->vhost
&& in->node == ou->node) {
+ memcpy(ou, in, sizeof(hostinfo_t));
+ ou->id = id;
+ ou->updatetime = apr_time_sec(apr_time_now());
+ *data = ou;
+ return APR_SUCCESS;
+ }
+ return APR_NOTFOUND;
+}
+apr_status_t insert_update_host(mem_t *s, hostinfo_t *host)
+{
+ apr_status_t rv;
+ hostinfo_t *ou;
+ int ident;
+
+ host->id = 0;
+ rv = s->storage->ap_slotmem_do(s->slotmem, insert_update, &host,
s->p);
+ if (host->id != 0 && rv == APR_SUCCESS) {
+ return APR_SUCCESS; /* updated */
+ }
+
+ /* we have to insert it */
+ rv = s->storage->ap_slotmem_alloc(s->slotmem, &ident, (void **)
&ou);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ memcpy(ou, host, sizeof(hostinfo_t));
+ ou->id = ident;
+ ou->updatetime = apr_time_sec(apr_time_now());
+
+ return APR_SUCCESS;
+}
+
+/**
+ * read a host record from the shared table
+ * @param pointer to the shared table.
+ * @param host host to read from the shared table.
+ * @return address of the read host or NULL if error.
+ */
+static apr_status_t loc_read_host(void* mem, void **data, int id, apr_pool_t *pool) {
+ hostinfo_t *in = (hostinfo_t *)*data;
+ hostinfo_t *ou = (hostinfo_t *)mem;
+
+ if (strcmp(in->host, ou->host) == 0 && in->node == ou->node ) {
+ *data = ou;
+ return APR_SUCCESS;
+ }
+ return APR_NOTFOUND;
+}
+APR_DECLARE(hostinfo_t *) read_host(mem_t *s, hostinfo_t *host)
+{
+ apr_status_t rv;
+ hostinfo_t *ou = host;
+
+ if (host->id)
+ rv = s->storage->ap_slotmem_mem(s->slotmem, host->id, (void **)
&ou);
+ else {
+ rv = s->storage->ap_slotmem_do(s->slotmem, loc_read_host, &ou,
s->p);
+ }
+ if (rv == APR_SUCCESS)
+ return ou;
+ return NULL;
+}
+/**
+ * get a host record from the shared table
+ * @param pointer to the shared table.
+ * @param host address where the host is locate in the shared table.
+ * @param ids in the host table.
+ * @return APR_SUCCESS if all went well
+ */
+APR_DECLARE(apr_status_t) get_host(mem_t *s, hostinfo_t **host, int ids)
+{
+ return(s->storage->ap_slotmem_mem(s->slotmem, ids, (void **) host));
+}
+
+/**
+ * remove(free) a host record from the shared table
+ * @param pointer to the shared table.
+ * @param host host to remove from the shared table.
+ * @return APR_SUCCESS if all went well
+ */
+APR_DECLARE(apr_status_t) remove_host(mem_t *s, hostinfo_t *host)
+{
+ apr_status_t rv;
+ hostinfo_t *ou = host;
+ if (host->id)
+ s->storage->ap_slotmem_free(s->slotmem, host->id, host);
+ else {
+ /* XXX: for the moment January 2007 ap_slotmem_free only uses ident to remove */
+ rv = s->storage->ap_slotmem_do(s->slotmem, loc_read_host, &ou,
s->p);
+ if (rv == APR_SUCCESS)
+ rv = s->storage->ap_slotmem_free(s->slotmem, ou->id, host);
+ }
+ return rv;
+}
+
+/*
+ * get the ids for the used (not free) hosts in the table
+ * @param pointer to the shared table.
+ * @param ids array of int to store the used id (must be big enough).
+ * @return number of host existing or -1 if error.
+ */
+APR_DECLARE(int) get_ids_used_host(mem_t *s, int *ids)
+{
+ return (s->storage->ap_slotmem_get_used(s->slotmem, ids));
+}
+
+/*
+ * read the size of the table.
+ * @param pointer to the shared table.
+ * @return number of host existing or -1 if error.
+ */
+APR_DECLARE(int) get_max_size_host(mem_t *s)
+{
+ return (s->storage->ap_slotmem_get_max_size(s->slotmem));
+}
+
+/**
+ * attach to the shared host table
+ * @param name of an existing shared table.
+ * @param address to store the size of the shared table.
+ * @param p pool to use for allocations.
+ * @return address of struct used to access the table.
+ */
+mem_t * get_mem_host(char *string, int *num, apr_pool_t *p, slotmem_storage_method
*storage)
+{
+ return(create_attach_mem_host(string, num, 0, p, storage));
+}
+/**
+ * create a shared host table
+ * @param name to use to create the table.
+ * @param size of the shared table.
+ * @param p pool to use for allocations.
+ * @return address of struct used to access the table.
+ */
+mem_t * create_mem_host(char *string, int *num, apr_pool_t *p, slotmem_storage_method
*storage)
+{
+ return(create_attach_mem_host(string, num, 1, p, storage));
+}
Added: trunk/mod_cluster/native/mod_manager/mod_manager.c
===================================================================
--- trunk/mod_cluster/native/mod_manager/mod_manager.c (rev 0)
+++ trunk/mod_cluster/native/mod_manager/mod_manager.c 2008-05-15 06:39:02 UTC (rev 1604)
@@ -0,0 +1,880 @@
+/*
+ Copyright 2008 Red Hat Middleware, LLC.
+ Licensed 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,i
+ 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.
+ */
+
+#include "apr_strings.h"
+#include "apr_lib.h"
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_log.h"
+#include "http_main.h"
+#include "http_request.h"
+#include "http_protocol.h"
+#include "http_core.h"
+#include "scoreboard.h"
+
+#include "slotmem.h"
+
+#include "node.h"
+#include "host.h"
+#include "context.h"
+#include "balancer.h"
+
+#define DEFMAXCONTEXT 100
+#define DEFMAXNODE 10
+#define DEFMAXHOST 20
+
+/* shared memory */
+mem_t *contextstatsmem = NULL;
+mem_t *nodestatsmem = NULL;
+mem_t *hoststatsmem = NULL;
+mem_t *balancerstatsmem = NULL;
+
+slotmem_storage_method *storage = NULL;
+
+module AP_MODULE_DECLARE_DATA manager_module;
+
+typedef struct mod_manager_config
+{
+ /* base name for the shared memory */
+ char *basefilename;
+ /* max number of context supported */
+ int maxcontext;
+ /* max munber of node supported */
+ int maxnode;
+ /* max munber of host supported */
+ int maxhost;
+} mod_manager_config;
+
+/*
+ * routines for the node_storage_method
+ */
+static apr_status_t loc_read_node(int ids, nodeinfo_t **node)
+{
+ return (get_node(nodestatsmem, node, ids));
+}
+static int loc_get_ids_used_node(int *ids)
+{
+ return(get_ids_used_node(nodestatsmem, ids));
+}
+static int loc_get_max_size_node()
+{
+ return(get_max_size_node(nodestatsmem));
+}
+static const struct node_storage_method node_storage =
+{
+ loc_read_node,
+ loc_get_ids_used_node,
+ loc_get_max_size_node
+};
+
+/*
+ * routines for the context_storage_method
+ */
+static apr_status_t loc_read_context(int ids, contextinfo_t **context)
+{
+ return (get_context(contextstatsmem, context, ids));
+}
+static int loc_get_ids_used_context(int *ids)
+{
+ return(get_ids_used_context(contextstatsmem, ids));
+}
+static int loc_get_max_size_context()
+{
+ return(get_max_size_context(contextstatsmem));
+}
+static const struct context_storage_method context_storage =
+{
+ loc_read_context,
+ loc_get_ids_used_context,
+ loc_get_max_size_context
+};
+
+/*
+ * routines for the host_storage_method
+ */
+static apr_status_t loc_read_host(int ids, hostinfo_t **host)
+{
+ return (get_host(hoststatsmem, host, ids));
+}
+static int loc_get_ids_used_host(int *ids)
+{
+ return(get_ids_used_host(hoststatsmem, ids));
+}
+static int loc_get_max_size_host()
+{
+ return(get_max_size_host(hoststatsmem));
+}
+static const struct host_storage_method host_storage =
+{
+ loc_read_host,
+ loc_get_ids_used_host,
+ loc_get_max_size_host
+};
+
+/*
+ * routines for the balancer_storage_method
+ */
+static apr_status_t loc_read_balancer(int ids, balancerinfo_t **balancer)
+{
+ return (get_balancer(balancerstatsmem, balancer, ids));
+}
+static int loc_get_ids_used_balancer(int *ids)
+{
+ return(get_ids_used_balancer(balancerstatsmem, ids));
+}
+static int loc_get_max_size_balancer()
+{
+ return(get_max_size_balancer(balancerstatsmem));
+}
+static const struct balancer_storage_method balancer_storage =
+{
+ loc_read_balancer,
+ loc_get_ids_used_balancer,
+ loc_get_max_size_balancer
+};
+
+/* helper for the handling of the Alias: host1,... Context: context1,... */
+struct cluster_host {
+ char *host;
+ char *context;
+ struct cluster_host *next;
+};
+
+/*
+ * call after parser the configuration.
+ * create the shared memory.
+ */
+static int manager_init(apr_pool_t *p, apr_pool_t *plog,
+ apr_pool_t *ptemp, server_rec *s)
+{
+ char *node;
+ char *context;
+ char *host;
+ char *balancer;
+ mod_manager_config *mconf = ap_get_module_config(s->module_config,
&manager_module);
+ if (mconf->basefilename) {
+ node = apr_pstrcat(ptemp, mconf->basefilename, ".node", NULL);
+ context = apr_pstrcat(ptemp, mconf->basefilename, ".context",
NULL);
+ host = apr_pstrcat(ptemp, mconf->basefilename, ".host", NULL);
+ balancer = apr_pstrcat(ptemp, mconf->basefilename, ".balancer",
NULL);
+ } else {
+ node = "manager.node";
+ context = "manager.context";
+ host = "manager.host";
+ host = "manager.balancer";
+ }
+
+ /* Get a provider to handle the shared memory */
+
+ storage = ap_lookup_provider(SLOTMEM_STORAGE, "shared", "0");
+ if (storage == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, 0, s,
"ap_lookup_provider %s failed", SLOTMEM_STORAGE);
+ return !OK;
+ }
+ nodestatsmem = create_mem_node(node, &mconf->maxnode, p, storage);
+ if (nodestatsmem == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, 0, s, "create_mem_node
%s failed", node);
+ return !OK;
+ }
+
+ contextstatsmem = create_mem_context(context, &mconf->maxcontext, p,
storage);
+ if (contextstatsmem == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, 0, s,
"create_mem_context failed");
+ return !OK;
+ }
+
+ hoststatsmem = create_mem_host(host, &mconf->maxhost, p, storage);
+ if (hoststatsmem == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, 0, s, "create_mem_host
failed");
+ return !OK;
+ }
+
+ balancerstatsmem = create_mem_balancer(balancer, &mconf->maxhost, p,
storage);
+ if (balancerstatsmem == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, 0, s,
"create_mem_balancer failed");
+ return !OK;
+ }
+
+ // sharedmem_initialize_cleanup(p);
+ return OK;
+}
+static char **process_buff(request_rec *r, char *buff)
+{
+ int i = 0;
+ char *s = buff;
+ char **ptr = NULL;
+ for (; *s != '\0'; s++) {
+ if (*s == '&') {
+ i++;
+ }
+ }
+ ptr = apr_palloc(r->pool, sizeof(char *) * ((2 *i) +1));
+ if (ptr == NULL)
+ return NULL;
+
+ s = buff;
+ ptr[0] = s;
+ ptr[2*i] = NULL;
+ i = 1;
+ for (; *s != '\0'; s++) {
+ if (*s == '&' || *s == '=') {
+ *s = '\0';
+ ptr[i] = s + 1;
+ i++;
+ }
+ }
+ return ptr;
+}
+/*
+ * Insert the hosts from Alias information
+ */
+static int insert_update_hosts(mem_t *mem, char *str, int node, int vhost)
+{
+ char *ptr = str;
+ char *previous = str;
+ int ret = 0;
+ hostinfo_t info;
+ char empty[1] = {'\0'};
+
+ info.node = node;
+ info.vhost = vhost;
+ if (ptr == NULL) {
+ ptr = empty;
+ previous = ptr;
+ }
+ while (*ptr) {
+ if (*ptr == ',') {
+ *ptr = '\0';
+ strncpy(info.host, previous, sizeof(info.host));
+ insert_update_host(mem, &info);
+ if (!ret)
+ ret = info.id;
+ previous = ptr + 1;
+ }
+ ptr ++;
+ }
+ strncpy(info.host, previous, sizeof(info.host));
+ insert_update_host(mem, &info);
+ return ret;
+}
+/*
+ * Insert the context from Context information
+ */
+static int insert_update_contexts(mem_t *mem, char *str, int node, int vhost, int
status)
+{
+ char *ptr = str;
+ char *previous = str;
+ int ret = 0;
+ contextinfo_t info;
+ char empty[2] = {'/','\0'};
+
+ info.node = node;
+ info.vhost = vhost;
+ info.status = status;
+ if (ptr == NULL) {
+ ptr = empty;
+ previous = ptr;
+ }
+ while (*ptr) {
+ if (*ptr == ',') {
+ *ptr = '\0';
+ strncpy(info.context, previous, sizeof(info.context));
+ insert_update_context(mem, &info);
+ if (!ret)
+ ret = info.id;
+ previous = ptr + 1;
+ }
+ ptr ++;
+ }
+ strncpy(info.context, previous, sizeof(info.context));
+ if (status != REMOVE)
+ insert_update_context(mem, &info);
+ else
+ remove_context(mem, &info);
+ return ret;
+}
+
+/*
+ * Process a CONFIG message
+ * JvmRoute?: <JvmRoute>
+ * Domain: <Domain>
+ * <Host: <Node IP>
+ * Port: <Connector Port>
+ * Type: <Type of the connector>
+ * Reserved: <Use connection pool initiated by Tomcat *.
+ * (<node conf>
+ * Virtual hosts in JBossAS
+ * Alias: <vhost list>
+ * Context corresponding to the applications.
+ * Context: <context list>
+ */
+static int process_config(request_rec *r, char *buff)
+{
+ /* Process the node description */
+ nodeinfo_t nodeinfo;
+ char *JVMRoute;
+ char *Domain;
+ char *Host;
+ char *Port;
+ char *Type;
+ /* XXX node conf */
+
+ struct cluster_host *vhost;
+ struct cluster_host *phost;
+
+ char **ptr = process_buff(r, buff);
+ if (ptr == NULL)
+ return 500;
+ vhost = apr_palloc(r->pool, sizeof(struct cluster_host));
+
+ /* Map nothing by default */
+ vhost->host = NULL;
+ vhost->context = NULL;
+ vhost->next = NULL;
+ phost = vhost;
+
+ nodeinfo.mess.reversed = 0;
+ int i = 0;
+ while (ptr[i]) {
+ if (strcasecmp(ptr[i], "Balancer") == 0) {
+ if (strlen(ptr[i+1])>=sizeof(nodeinfo.mess.balancer))
+ return 500;
+ strcpy(nodeinfo.mess.balancer, ptr[i+1]);
+ }
+ if (strcasecmp(ptr[i], "JVMRoute") == 0) {
+ if (strlen(ptr[i+1])>=sizeof(nodeinfo.mess.JVMRoute))
+ return 500;
+ strcpy(nodeinfo.mess.JVMRoute, ptr[i+1]);
+ }
+ if (strcasecmp(ptr[i], "Domain") == 0) {
+ if (strlen(ptr[i+1])>=sizeof(nodeinfo.mess.Domain))
+ return 500;
+ strcpy(nodeinfo.mess.Domain, ptr[i+1]);
+ }
+ if (strcasecmp(ptr[i], "Host") == 0) {
+ if (strlen(ptr[i+1])>=sizeof(nodeinfo.mess.Host))
+ return 500;
+ strcpy(nodeinfo.mess.Host, ptr[i+1]);
+ }
+ if (strcasecmp(ptr[i], "Port") == 0) {
+ if (strlen(ptr[i+1])>=sizeof(nodeinfo.mess.Port))
+ return 500;
+ strcpy(nodeinfo.mess.Port, ptr[i+1]);
+ }
+ if (strcasecmp(ptr[i], "Type") == 0) {
+ if (strlen(ptr[i+1])>=sizeof(nodeinfo.mess.Type))
+ return 500;
+ strcpy(nodeinfo.mess.Type, ptr[i+1]);
+ }
+ if (strcasecmp(ptr[i], "Reversed") == 0) {
+ if (strcasecmp(ptr[i+1], "yes") == 0) {
+ nodeinfo.mess.reversed = 1;
+ }
+ }
+ if (strcasecmp(ptr[i], "Alias") == 0) {
+ if (phost->host && !phost->context) {
+ return 500;
+ }
+ if (phost->host) {
+ phost->next = apr_palloc(r->pool, sizeof(struct cluster_host));
+ phost = phost->next;
+ phost->next = NULL;
+ phost->host = ptr[i+1];
+ phost->context = NULL;
+ } else {
+ phost->host = ptr[i+1];
+ }
+ }
+ if (strcasecmp(ptr[i], "Context") == 0) {
+ if (phost->context) {
+ return 500;
+ }
+ phost->context = ptr[i+1];
+ }
+ i++;
+ i++;
+ }
+ /* XXX: Read the default balancer name is balancer empty */
+
+ /* Insert or update node description */
+ int id;
+ if (insert_update_node(nodestatsmem, &nodeinfo, &id) != APR_SUCCESS)
+ return 500;
+
+ /* Insert the Alias and corresponding Context */
+ phost = vhost;
+ int vid = 1; /* zero and "" is empty */
+ while (phost) {
+ insert_update_hosts(hoststatsmem, phost->host, id, vid);
+ insert_update_contexts(contextstatsmem, phost->context, id, vid, STOPPED);
+ phost = phost->next;
+ vid++;
+ }
+ return OK;
+}
+/*
+ * Process a DUMP command.
+ */
+static int process_dump(request_rec *r, char *buff)
+{
+ int size, i;
+ int *id;
+
+ ap_set_content_type(r, "text/plain");
+
+ size = get_max_size_node(nodestatsmem);
+ id = apr_palloc(r->pool, sizeof(int) * size);
+ size = get_ids_used_node(nodestatsmem, id);
+ for (i=0; i<size; i++) {
+ nodeinfo_t *ou;
+ get_node(nodestatsmem, &ou, id[i]);
+ ap_rprintf(r, "node: [%d:%d] JVMRoute: %s Domain: [%s] Host: %s Port: %s
Type: %s\n",
+ id[i], ou->mess.id, ou->mess.JVMRoute, ou->mess.Domain,
+ ou->mess.Host, ou->mess.Port, ou->mess.Type);
+ }
+
+ size = get_max_size_host(hoststatsmem);
+ id = apr_palloc(r->pool, sizeof(int) * size);
+ size = get_ids_used_host(hoststatsmem, id);
+ for (i=0; i<size; i++) {
+ hostinfo_t *ou;
+ get_host(hoststatsmem, &ou, id[i]);
+ ap_rprintf(r, "host: %d [%s] vhost: %d node: %d\n", id[i], ou->host,
ou->vhost,
+ ou->node);
+ }
+
+ size = get_max_size_context(contextstatsmem);
+ id = apr_palloc(r->pool, sizeof(int) * size);
+ size = get_ids_used_context(contextstatsmem, id);
+ for (i=0; i<size; i++) {
+ contextinfo_t *ou;
+ get_context(contextstatsmem, &ou, id[i]);
+ ap_rprintf(r, "context: %d [%s] vhost: %d node: %d status: %d\n",
id[i], ou->context,
+ ou->vhost, ou->node,
+ ou->status);
+ }
+ return OK;
+}
+
+/* Process an enable/disable/stop application message */
+static int process_appl_cmd(request_rec *r, char *buff, int status)
+{
+ char *JVMRoute;
+ nodeinfo_t nodeinfo;
+ nodeinfo_t *node;
+ struct cluster_host *vhost;
+ struct cluster_host *phost;
+
+ char **ptr = process_buff(r, buff);
+ if (ptr == NULL)
+ return 500;
+
+ /* Map nothing by default */
+ vhost->host = NULL;
+ vhost->context = NULL;
+ vhost->next = NULL;
+ vhost = apr_palloc(r->pool, sizeof(struct cluster_host));
+ phost = vhost;
+
+ int i = 0;
+ while (ptr[i]) {
+ if (strcasecmp(ptr[i], "JVMRoute") == 0) {
+ if (strlen(ptr[i+1])>=sizeof(nodeinfo.mess.JVMRoute))
+ return 500;
+ strcpy(nodeinfo.mess.JVMRoute, ptr[i+1]);
+ nodeinfo.mess.id = 0;
+ }
+ if (strcasecmp(ptr[i], "Alias") == 0) {
+ if (phost->host && !phost->context) {
+ return 500;
+ }
+ if (phost->host) {
+ phost->next = apr_palloc(r->pool, sizeof(struct cluster_host));
+ phost = phost->next;
+ phost->next = NULL;
+ phost->host = ptr[i+1];
+ phost->context = NULL;
+ } else {
+ phost->host = ptr[i+1];
+ }
+ }
+ if (strcasecmp(ptr[i], "Context") == 0) {
+ if (phost->context) {
+ return 500;
+ }
+ phost->context = ptr[i+1];
+ }
+ i++;
+ i++;
+ }
+
+ /* Read the node */
+ node = read_node(nodestatsmem, &nodeinfo);
+ if (node == NULL)
+ return 500;
+
+ /* Read the ID of the virtual corresponding to the first Alias */
+ hostinfo_t hostinfo;
+ hostinfo_t *host;
+
+ hostinfo.node = node->mess.id;
+ if (vhost->host != NULL)
+ strcpy(hostinfo.host, vhost->host);
+ else
+ hostinfo.host[0] = '\0';
+
+ hostinfo.id = 0;
+ host = read_host(hoststatsmem, &hostinfo);
+ if (host == NULL) {
+ return 500;
+ }
+
+ /* Now update each context from Context: part */
+ insert_update_contexts(contextstatsmem, phost->context, node->mess.id,
host->vhost, status);
+ return OK;
+}
+static int process_enable(request_rec *r, char *buff)
+{
+ return process_appl_cmd(r, buff, ENABLED);
+}
+static int process_disable(request_rec *r, char *buff)
+{
+ return process_appl_cmd(r, buff, DISABLED);
+}
+static int process_stop(request_rec *r, char *buff)
+{
+ return process_appl_cmd(r, buff, STOPPED);
+}
+static int process_remove(request_rec *r, char *buff)
+{
+ return process_appl_cmd(r, buff, REMOVE);
+}
+
+/*
+ * XXX: Need to be write the idea is to get a provider for mod_proxy_cluster for each
scheme.
+ * Do a ping/png request to the node and set the load factor.
+ */
+static int isnode_up(request_rec *r, int id, char *scheme, int Load)
+{
+ return OK;
+}
+/*
+ * Process the STATUS command
+ * Load -1 : Broken
+ * Load 0 : Standby.
+ * Load 1-100 : Load factor.
+ */
+static int process_status(request_rec *r, char *buff)
+{
+ int Load;
+ nodeinfo_t nodeinfo;
+ nodeinfo_t *node;
+ char **ptr = process_buff(r, buff);
+ if (ptr == NULL)
+ return 500;
+
+ int i = 0;
+ while (ptr[i]) {
+ if (strcasecmp(ptr[i], "JVMRoute") == 0) {
+ if (strlen(ptr[i+1])>=sizeof(nodeinfo.mess.JVMRoute))
+ return 500;
+ strcpy(nodeinfo.mess.JVMRoute, ptr[i+1]);
+ nodeinfo.mess.id = 0;
+ }
+ else if (strcasecmp(ptr[i], "Load") == 0) {
+ Load = atoi(ptr[i+1]);
+ }
+ else
+ return 500;
+ i++;
+ i++;
+ }
+
+ /* Read the node */
+ node = read_node(nodestatsmem, &nodeinfo);
+ if (node == NULL)
+ return 500;
+
+ /*
+ * If the node is usualable do a ping/pong to prevent Split-Brain Syndrome
+ * and update the worker status and load factor acccording to the test result.
+ */
+ ap_set_content_type(r, "text/plain");
+ ap_rprintf(r, "Type=STATUS-RSP&JVMRoute=%s", nodeinfo.mess.JVMRoute);
+
+ if (isnode_up(r, node->mess.id, node->mess.Type, Load) != OK)
+ ap_rprintf(r, "&State=NOTOK");
+ else
+ ap_rprintf(r, "&State=OK");
+ if (ap_my_generation)
+ ap_rprintf(r, "&id=%d", ap_my_generation);
+ else
+ ap_rprintf(r, "&id=%d",
ap_scoreboard_image->global->restart_time);
+
+ ap_rprintf(r, "\n");
+ return OK;
+}
+
+/*
+ * Decodes a '%' escaped string, and returns the number of characters
+ * (From mod_proxy_ftp.c).
+ */
+static int decodeenc(char *x)
+{
+ int i, j, ch;
+
+ if (x[0] == '\0')
+ return 0; /* special case for no characters */
+ for (i = 0, j = 0; x[i] != '\0'; i++, j++) {
+ /* decode it if not already done */
+ ch = x[i];
+ if (ch == '%' && apr_isxdigit(x[i + 1]) &&
apr_isxdigit(x[i + 2])) {
+ ch = ap_proxy_hex2c(&x[i + 1]);
+ i += 2;
+ }
+ x[j] = ch;
+ }
+ x[j] = '\0';
+ return j;
+}
+/*
+ * This routine is called before mod_proxy translate name.
+ * This allows us to make decisions before mod_proxy
+ * to be able to fill tables even with ProxyPass / balancer...
+ */
+static int manager_trans(request_rec *r)
+{
+ int ours = 0;
+ if (strcasecmp(r->method, "CONFIG") == 0)
+ ours = 1;
+ else if (strcasecmp(r->method, "ENABLE-APP") == 0)
+ ours = 1;
+ else if (strcasecmp(r->method, "DISABLE-APP") == 0)
+ ours = 1;
+ else if (strcasecmp(r->method, "STOP-APP") == 0)
+ ours = 1;
+ else if (strcasecmp(r->method, "REMOVE-APP") == 0)
+ ours = 1;
+ else if (strcasecmp(r->method, "STATUS") == 0)
+ ours = 1;
+ else if (strcasecmp(r->method, "DUMP") == 0)
+ ours = 1;
+ if (ours) {
+ /* The method one of ours */
+ r->handler = "mod-cluster";
+ return OK;
+ }
+
+ return DECLINED;
+}
+
+
+/* Process the requests from the ModClusterService */
+static int manager_handler(request_rec *r)
+{
+ apr_bucket_brigade *input_brigade;
+ char buff[4096];
+ int bufsiz=sizeof(buff);
+ if (strcmp(r->handler, "mod-cluster"))
+ return DECLINED;
+ input_brigade = apr_brigade_create(r->connection->pool,
r->connection->bucket_alloc);
+ ap_get_brigade(r->input_filters, input_brigade, AP_MODE_READBYTES, APR_BLOCK_READ,
sizeof(buff));
+ apr_brigade_flatten(input_brigade, buff, &bufsiz);
+ buff[bufsiz] = '\0';
+ decodeenc(buff);
+ if (strcasecmp(r->method, "CONFIG") == 0)
+ return(process_config(r, buff));
+ /* Application handling */
+ else if (strcasecmp(r->method, "ENABLE-APP") == 0)
+ return(process_enable(r, buff));
+ else if (strcasecmp(r->method, "DISABLE-APP") == 0)
+ return(process_disable(r, buff));
+ else if (strcasecmp(r->method, "STOP-APP") == 0)
+ return(process_stop(r, buff));
+ else if (strcasecmp(r->method, "REMOVE-APP") == 0)
+ return(process_remove(r, buff));
+ /* Status handling */
+ else if (strcasecmp(r->method, "STATUS") == 0)
+ return(process_status(r, buff));
+ else if (strcasecmp(r->method, "DUMP") == 0)
+ return(process_dump(r, buff));
+ else {
+ /* The command is not supported */
+ r->status_line = apr_psprintf(r->pool, "%3.3u VERSION %d.%d.%d",
500, 0, 0, 0);
+ return 500;
+ }
+
+ return (OK);
+}
+
+/*
+ * Supported directives.
+ */
+AP_DECLARE_NONSTD(const char *) cmd_manager_maxcontext(cmd_parms *cmd, void *mconfig,
const char *word)
+{
+ mod_manager_config *mconf = ap_get_module_config(cmd->server->module_config,
&manager_module);
+ mconf->maxcontext = atoi(word);
+ return NULL;
+}
+AP_DECLARE_NONSTD(const char *) cmd_manager_maxnode(cmd_parms *cmd, void *mconfig, const
char *word)
+{
+ mod_manager_config *mconf = ap_get_module_config(cmd->server->module_config,
&manager_module);
+ mconf->maxnode = atoi(word);
+ return NULL;
+}
+AP_DECLARE_NONSTD(const char *) cmd_manager_maxhost(cmd_parms *cmd, void *mconfig, const
char *word)
+{
+ mod_manager_config *mconf = ap_get_module_config(cmd->server->module_config,
&manager_module);
+ mconf->maxhost = atoi(word);
+ return NULL;
+}
+AP_DECLARE_NONSTD(const char *) cmd_manager_memmanagerfile(cmd_parms *cmd, void *mconfig,
const char *word)
+{
+ mod_manager_config *mconf = ap_get_module_config(cmd->server->module_config,
&manager_module);
+ mconf->basefilename = apr_pstrdup(cmd->pool, word);
+ return NULL;
+}
+AP_DECLARE_NONSTD(const char *) cmd_manager_balancername(cmd_parms *cmd, void *mconfig,
const char *word)
+{
+ mod_manager_config *mconf = ap_get_module_config(cmd->server->module_config,
&manager_module);
+ /* XXX: create the entry in the shared balancer table */
+ return NULL;
+}
+static const command_rec manager_cmds[] =
+{
+ AP_INIT_TAKE1(
+ "Maxcontext",
+ cmd_manager_maxcontext,
+ NULL,
+ OR_ALL,
+ "Maxcontext - number max context supported by mod_cluster"
+ ),
+ AP_INIT_TAKE1(
+ "Maxnode",
+ cmd_manager_maxnode,
+ NULL,
+ OR_ALL,
+ "Maxnode - number max node supported by mod_cluster"
+ ),
+ AP_INIT_TAKE1(
+ "Maxhost",
+ cmd_manager_maxhost,
+ NULL,
+ OR_ALL,
+ "Maxhost - number max host (Alias in virtual hosts) supported by
mod_cluster"
+ ),
+ AP_INIT_TAKE1(
+ "MemManagerFile",
+ cmd_manager_memmanagerfile,
+ NULL,
+ OR_ALL,
+ "MemManagerFile - base name of the files used to create/attach to shared
memory"
+ ),
+ AP_INIT_TAKE1(
+ "ManagerBalancerName",
+ cmd_manager_balancername,
+ NULL,
+ OR_ALL,
+ "ManagerBalancerName - name of a balancer corresponding to the
manager"
+ ),
+ {NULL}
+};
+
+/* hooks declaration */
+
+static void manager_hooks(apr_pool_t *p)
+{
+ static const char * const aszSucc[]={ "mod_proxy.c", NULL };
+
+ /* Create the shared tables for mod_proxy_cluster */
+ ap_hook_post_config(manager_init, NULL, NULL, APR_HOOK_MIDDLE);
+
+ /* post read_request handling: to be handle to use ProxyPass / */
+ ap_hook_translate_name(manager_trans, NULL, aszSucc,
+ APR_HOOK_FIRST);
+
+ /* Process the request from the ModClusterService */
+ ap_hook_handler(manager_handler, NULL, NULL, APR_HOOK_MIDDLE);
+
+ /* Register nodes/hosts/contexts table provider */
+ ap_register_provider(p, "manager" , "shared", "0",
&node_storage);
+ ap_register_provider(p, "manager" , "shared", "1",
&host_storage);
+ ap_register_provider(p, "manager" , "shared", "2",
&context_storage);
+ ap_register_provider(p, "manager" , "shared", "3",
&balancer_storage);
+}
+
+/*
+ * Config creation stuff
+ */
+static void *create_manager_config(apr_pool_t *p)
+{
+ mod_manager_config *mconf = apr_pcalloc(p, sizeof(*mconf));
+
+ mconf->basefilename = NULL;
+ mconf->maxcontext = DEFMAXCONTEXT;
+ mconf->maxnode = DEFMAXNODE;
+ mconf->maxhost = DEFMAXHOST;
+ return mconf;
+}
+
+static void *create_manager_server_config(apr_pool_t *p, server_rec *s)
+{
+ return(create_manager_config(p));
+}
+static void *merge_manager_server_config(apr_pool_t *p, void *server1_conf,
+ void *server2_conf)
+{
+ mod_manager_config *mconf1 = (mod_manager_config *) server1_conf;
+ mod_manager_config *mconf2 = (mod_manager_config *) server2_conf;
+ mod_manager_config *mconf = apr_pcalloc(p, sizeof(*mconf));
+
+ mconf->basefilename = NULL;
+ mconf->maxcontext = DEFMAXCONTEXT;
+ mconf->maxnode = DEFMAXNODE;
+
+ if (mconf2->basefilename)
+ mconf->basefilename = apr_pstrdup(p, mconf2->basefilename);
+ else if (mconf1->basefilename)
+ mconf->basefilename = apr_pstrdup(p, mconf1->basefilename);
+
+ if (mconf2->maxcontext != DEFMAXCONTEXT)
+ mconf->maxcontext = mconf2->maxcontext;
+ else if (mconf1->maxcontext != DEFMAXCONTEXT)
+ mconf->maxcontext = mconf1->maxcontext;
+
+ if (mconf2->maxnode != DEFMAXNODE)
+ mconf->maxnode = mconf2->maxnode;
+ else if (mconf1->maxnode != DEFMAXNODE)
+ mconf->maxnode = mconf1->maxnode;
+
+ if (mconf2->maxhost != DEFMAXHOST)
+ mconf->maxhost = mconf2->maxhost;
+ else if (mconf1->maxhost != DEFMAXHOST)
+ mconf->maxhost = mconf1->maxhost;
+
+ return mconf;
+}
+
+/* Module declaration */
+
+module AP_MODULE_DECLARE_DATA manager_module = {
+ STANDARD20_MODULE_STUFF,
+ NULL,
+ NULL,
+ create_manager_server_config,
+ merge_manager_server_config,
+ manager_cmds, /* command table */
+ manager_hooks /* register hooks */
+};
Added: trunk/mod_cluster/native/mod_manager/node.c
===================================================================
--- trunk/mod_cluster/native/mod_manager/node.c (rev 0)
+++ trunk/mod_cluster/native/mod_manager/node.c 2008-05-15 06:39:02 UTC (rev 1604)
@@ -0,0 +1,242 @@
+/*
+ * 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$
+ */
+
+/**
+ * @file node.c
+ * @brief node description Storage Module for Apache
+ *
+ * @defgroup MEM nodes
+ * @ingroup APACHE_MODS
+ * @{
+ */
+
+#include "apr.h"
+#include "apr_strings.h"
+#include "apr_pools.h"
+#include "apr_time.h"
+
+#include "slotmem.h"
+#include "node.h"
+
+struct mem {
+ ap_slotmem_t *slotmem;
+ const slotmem_storage_method *storage;
+ int num;
+ apr_pool_t *p;
+};
+
+static mem_t * create_attach_mem_node(char *string, int *num, int type, apr_pool_t *p,
slotmem_storage_method *storage) {
+ mem_t *ptr;
+ const char *storename;
+ apr_status_t rv;
+
+ ptr = apr_pcalloc(p, sizeof(mem_t));
+ if (!ptr) {
+ return NULL;
+ }
+ ptr->storage = storage;
+ storename = apr_pstrcat(p, string, NODEEXE, NULL);
+ if (type)
+ rv = ptr->storage->ap_slotmem_create(&ptr->slotmem, storename,
sizeof(nodeinfo_t), *num, p);
+ else {
+ apr_size_t size = sizeof(nodeinfo_t);
+ rv = ptr->storage->ap_slotmem_attach(&ptr->slotmem, storename,
&size, num, p);
+ }
+ if (rv != APR_SUCCESS) {
+ return NULL;
+ }
+ ptr->num = *num;
+ ptr->p = p;
+ return ptr;
+}
+/**
+ * Insert(alloc) and update a node record in the shared table
+ * @param pointer to the shared table.
+ * @param node node to store in the shared table.
+ * @return APR_SUCCESS if all went well
+ *
+ */
+static apr_status_t insert_update(void* mem, void **data, int id, apr_pool_t *pool)
+{
+ nodeinfo_t *in = (nodeinfo_t *)*data;
+ nodeinfo_t *ou = (nodeinfo_t *)mem;
+ if (strcmp(in->mess.JVMRoute, ou->mess.JVMRoute) == 0) {
+ /*
+ * The node information is made of several pieces:
+ * Information from the cluster (nodemess_t).
+ * updatetime (time of last received message).
+ * offset (of the area shared with the proxy logic).
+ * stat (shared area with the proxy logic we shouldn't modify it here).
+ */
+ memcpy(ou, in, sizeof(nodemess_t));
+ ou->mess.id = id;
+ ou->updatetime = (unsigned long) apr_time_sec(apr_time_now());
+ ou->offset = sizeof(nodemess_t) + sizeof(unsigned long) + sizeof(int);
+ *data = ou;
+ return APR_SUCCESS;
+ }
+ return APR_NOTFOUND;
+}
+apr_status_t insert_update_node(mem_t *s, nodeinfo_t *node, int *id)
+{
+ apr_status_t rv;
+ nodeinfo_t *ou;
+ int ident;
+
+ node->mess.id = 0;
+ rv = s->storage->ap_slotmem_do(s->slotmem, insert_update, &node,
s->p);
+ if (node->mess.id != 0 && rv == APR_SUCCESS) {
+ *id = node->mess.id;
+ return APR_SUCCESS; /* updated */
+ }
+
+ /* we have to insert it */
+ rv = s->storage->ap_slotmem_alloc(s->slotmem, &ident, (void **)
&ou);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ memcpy(ou, node, sizeof(nodeinfo_t));
+ ou->mess.id = ident;
+ *id = ident;
+ ou->updatetime = (unsigned long) apr_time_sec(apr_time_now());
+
+ /* set of offset to the proxy_worker_stat */
+ ou->offset = sizeof(nodemess_t) + sizeof(unsigned long) + sizeof(int);
+
+ /* blank the proxy status information */
+ memset(ou->stat, '\0', SIZEOFSCORE);
+
+ return APR_SUCCESS;
+}
+
+/**
+ * read a node record from the shared table
+ * @param pointer to the shared table.
+ * @param node node to read from the shared table.
+ * @return address of the read node or NULL if error.
+ */
+static apr_status_t loc_read_node(void* mem, void **data, int id, apr_pool_t *pool) {
+ nodeinfo_t *in = (nodeinfo_t *)*data;
+ nodeinfo_t *ou = (nodeinfo_t *)mem;
+ if (strcmp(in->mess.JVMRoute, ou->mess.JVMRoute) == 0) {
+ *data = ou;
+ return APR_SUCCESS;
+ }
+ return APR_NOTFOUND;
+}
+APR_DECLARE(nodeinfo_t *) read_node(mem_t *s, nodeinfo_t *node)
+{
+ apr_status_t rv;
+ nodeinfo_t *ou = node;
+
+ if (node->mess.id)
+ rv = s->storage->ap_slotmem_mem(s->slotmem, node->mess.id, (void **)
&ou);
+ else {
+ rv = s->storage->ap_slotmem_do(s->slotmem, loc_read_node, &ou,
s->p);
+ }
+ if (rv == APR_SUCCESS)
+ return ou;
+ return NULL;
+}
+/**
+ * get a node record from the shared table
+ * @param pointer to the shared table.
+ * @param node address where the node is locate in the shared table.
+ * @param ids in the node table.
+ * @return APR_SUCCESS if all went well
+ */
+APR_DECLARE(apr_status_t) get_node(mem_t *s, nodeinfo_t **node, int ids)
+{
+ return(s->storage->ap_slotmem_mem(s->slotmem, ids, (void **) node));
+}
+
+/**
+ * remove(free) a node record from the shared table
+ * @param pointer to the shared table.
+ * @param node node to remove from the shared table.
+ * @return APR_SUCCESS if all went well
+ */
+APR_DECLARE(apr_status_t) remove_node(mem_t *s, nodeinfo_t *node)
+{
+ apr_status_t rv;
+ nodeinfo_t *ou = node;
+ if (node->mess.id)
+ s->storage->ap_slotmem_free(s->slotmem, node->mess.id, node);
+ else {
+ /* XXX: for the moment January 2007 ap_slotmem_free only uses ident to remove */
+ rv = s->storage->ap_slotmem_do(s->slotmem, loc_read_node, &ou,
s->p);
+ if (rv == APR_SUCCESS)
+ rv = s->storage->ap_slotmem_free(s->slotmem, ou->mess.id, node);
+ }
+ return rv;
+}
+
+/*
+ * get the ids for the used (not free) nodes in the table
+ * @param pointer to the shared table.
+ * @param ids array of int to store the used id (must be big enough).
+ * @return number of node existing or -1 if error.
+ */
+APR_DECLARE(int) get_ids_used_node(mem_t *s, int *ids)
+{
+ return (s->storage->ap_slotmem_get_used(s->slotmem, ids));
+}
+
+/*
+ * read the size of the table.
+ * @param pointer to the shared table.
+ * @return number of node existing or -1 if error.
+ */
+APR_DECLARE(int) get_max_size_node(mem_t *s)
+{
+ return (s->storage->ap_slotmem_get_max_size(s->slotmem));
+}
+
+/**
+ * attach to the shared node table
+ * @param name of an existing shared table.
+ * @param address to store the size of the shared table.
+ * @param p pool to use for allocations.
+ * @param storage slotmem logic provider.
+ * @return address of struct used to access the table.
+ */
+mem_t * get_mem_node(char *string, int *num, apr_pool_t *p, slotmem_storage_method
*storage)
+{
+ return(create_attach_mem_node(string, num, 0, p, storage));
+}
+/**
+ * create a shared node table
+ * @param name to use to create the table.
+ * @param size of the shared table.
+ * @param p pool to use for allocations.
+ * @param storage slotmem logic provider.
+ * @return address of struct used to access the table.
+ */
+mem_t * create_mem_node(char *string, int *num, apr_pool_t *p, slotmem_storage_method
*storage)
+{
+ return(create_attach_mem_node(string, num, 1, p, storage));
+}